Import Cobalt 8.22891
diff --git a/src/base/third_party/nspr/prcpucfg_starboard.h b/src/base/third_party/nspr/prcpucfg_starboard.h
index 3aaa298..2113b0f 100644
--- a/src/base/third_party/nspr/prcpucfg_starboard.h
+++ b/src/base/third_party/nspr/prcpucfg_starboard.h
@@ -95,6 +95,7 @@
 
 #define PR_BYTES_PER_WORD_LOG2   2
 #define PR_BYTES_PER_DWORD_LOG2  3
+
 #elif SB_IS(ARCH_X86) && SB_IS(64_BIT)
 #define PR_BYTES_PER_BYTE   1
 #define PR_BYTES_PER_SHORT  2
@@ -135,6 +136,7 @@
 
 #define PR_BYTES_PER_WORD_LOG2  3
 #define PR_BYTES_PER_DWORD_LOG2 3
+
 #elif SB_IS(ARCH_X86) && SB_IS(32_BIT)
 #define PR_BYTES_PER_BYTE   1
 #define PR_BYTES_PER_SHORT  2
@@ -175,6 +177,7 @@
 
 #define PR_BYTES_PER_WORD_LOG2   2
 #define PR_BYTES_PER_DWORD_LOG2  3
+
 #elif SB_IS(ARCH_MIPS) && SB_IS(32_BIT)
 #define PR_BYTES_PER_BYTE   1
 #define PR_BYTES_PER_SHORT  2
@@ -215,6 +218,7 @@
 
 #define PR_BYTES_PER_WORD_LOG2   2
 #define PR_BYTES_PER_DWORD_LOG2  3
+
 #elif SB_IS(ARCH_ARM) && SB_IS(32_BIT)
 #define PR_BYTES_PER_BYTE   1
 #define PR_BYTES_PER_SHORT  2
@@ -255,6 +259,48 @@
 
 #define PR_BYTES_PER_WORD_LOG2   2
 #define PR_BYTES_PER_DWORD_LOG2  3
+
+#elif SB_IS(ARCH_ARM) && SB_IS(64_BIT)
+#define PR_BYTES_PER_BYTE   1
+#define PR_BYTES_PER_SHORT  2
+#define PR_BYTES_PER_INT    4
+#define PR_BYTES_PER_INT64  8
+#define PR_BYTES_PER_LONG   8
+#define PR_BYTES_PER_FLOAT  4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD   8
+#define PR_BYTES_PER_DWORD  8
+
+#define PR_BITS_PER_BYTE    8
+#define PR_BITS_PER_SHORT   16
+#define PR_BITS_PER_INT     32
+#define PR_BITS_PER_INT64   64
+#define PR_BITS_PER_LONG    64
+#define PR_BITS_PER_FLOAT   32
+#define PR_BITS_PER_DOUBLE  64
+#define PR_BITS_PER_WORD    64
+
+#define PR_BITS_PER_BYTE_LOG2   3
+#define PR_BITS_PER_SHORT_LOG2  4
+#define PR_BITS_PER_INT_LOG2    5
+#define PR_BITS_PER_INT64_LOG2  6
+#define PR_BITS_PER_LONG_LOG2   6
+#define PR_BITS_PER_FLOAT_LOG2  5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2   6
+
+#define PR_ALIGN_OF_SHORT   2
+#define PR_ALIGN_OF_INT     4
+#define PR_ALIGN_OF_LONG    4
+#define PR_ALIGN_OF_INT64   4
+#define PR_ALIGN_OF_FLOAT   4
+#define PR_ALIGN_OF_DOUBLE  4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD    4
+
+#define PR_BYTES_PER_WORD_LOG2   3
+#define PR_BYTES_PER_DWORD_LOG2  3
+
 #else
 #  error "No configuration definition for Starboard ARCH + BITS."
 #endif
diff --git a/src/cobalt/base/tokens.h b/src/cobalt/base/tokens.h
index 5c42945..3ae1cdc 100644
--- a/src/cobalt/base/tokens.h
+++ b/src/cobalt/base/tokens.h
@@ -31,9 +31,12 @@
     MacroOpWithNameOnly(all)                                  \
     MacroOpWithNameOnly(animationend)                         \
     MacroOpWithNameOnly(assertive)                            \
+    MacroOpWithNameOnly(attribute)                            \
     MacroOpWithNameOnly(blur)                                 \
     MacroOpWithNameOnly(canplay)                              \
     MacroOpWithNameOnly(canplaythrough)                       \
+    MacroOpWithNameOnly(characterData)                        \
+    MacroOpWithNameOnly(childList)                            \
     MacroOpWithNameOnly(close)                                \
     MacroOpWithNameOnly(durationchange)                       \
     MacroOpWithNameOnly(emptied)                              \
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.cc
deleted file mode 100644
index 7f862f5..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.cc
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCAnonymousIndexedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::AnonymousIndexedGetterInterface;
-using cobalt::bindings::testing::JSCAnonymousIndexedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCAnonymousIndexedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCAnonymousIndexedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousIndexedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousIndexedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCAnonymousIndexedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousIndexedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCAnonymousIndexedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousIndexedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousIndexedGetterInterface::InterfaceObject::s_info = {
-    "AnonymousIndexedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousIndexedGetterInterface::InterfaceObject)
-};  // JSCAnonymousIndexedGetterInterface::InterfaceObject::s_info
-
-void JSCAnonymousIndexedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCAnonymousIndexedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCAnonymousIndexedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "AnonymousIndexedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCAnonymousIndexedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCAnonymousIndexedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousIndexedGetterInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCAnonymousIndexedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousIndexedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousIndexedGetterInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousIndexedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousIndexedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousIndexedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousIndexedGetterInterface::Prototype::s_info = {
-    "AnonymousIndexedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousIndexedGetterInterface::Prototype)
-};  // JSCAnonymousIndexedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCAnonymousIndexedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCAnonymousIndexedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCAnonymousIndexedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCAnonymousIndexedGetterInterface::property_table_values[] = {
-    { "length",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlength),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousIndexedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousIndexedGetterInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousIndexedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousIndexedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousIndexedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCAnonymousIndexedGetterInterface::NonTrivialStaticFields>
-    JSCAnonymousIndexedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCAnonymousIndexedGetterInterface::s_info = {
-    "AnonymousIndexedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousIndexedGetterInterface)
-};  // JSCAnonymousIndexedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCAnonymousIndexedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCAnonymousIndexedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCAnonymousIndexedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCAnonymousIndexedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  AnonymousIndexedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<AnonymousIndexedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCAnonymousIndexedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCAnonymousIndexedGetterInterface>(global_data.heap))
-      JSCAnonymousIndexedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCAnonymousIndexedGetterInterface::JSCAnonymousIndexedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<AnonymousIndexedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCAnonymousIndexedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCAnonymousIndexedGetterInterface::~JSCAnonymousIndexedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCAnonymousIndexedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCAnonymousIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCAnonymousIndexedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCAnonymousIndexedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-  if (s_has_named_getter) {
-    JSCAnonymousIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousIndexedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCAnonymousIndexedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, object);
-  if (impl) {
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCAnonymousIndexedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCAnonymousIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCAnonymousIndexedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCAnonymousIndexedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCAnonymousIndexedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCAnonymousIndexedGetterInterface", "deletePropertyByIndex");
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-  }
-  return false;
-}
-
-bool JSCAnonymousIndexedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCAnonymousIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousIndexedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCAnonymousIndexedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCAnonymousIndexedGetterInterface", "get length");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->length());
-  return result;
-}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("JSCAnonymousIndexedGetterInterface", "IndexedPropertyGetter");
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->AnonymousIndexedGetter(index));
-  return result;
-}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCAnonymousIndexedGetterInterface", "IndexedPropertySetter");
-  AnonymousIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  uint32_t value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->AnonymousIndexedSetter(index, value);
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.h
deleted file mode 100644
index db0c679..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousIndexedGetterInterface.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCAnonymousIndexedGetterInterface_h
-#define JSCAnonymousIndexedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/anonymous_indexed_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCAnonymousIndexedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to AnonymousIndexedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCAnonymousIndexedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<AnonymousIndexedGetterInterface>& impl);
-  ~JSCAnonymousIndexedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCAnonymousIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.cc
deleted file mode 100644
index 5944536..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.cc
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCAnonymousNamedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::AnonymousNamedGetterInterface;
-using cobalt::bindings::testing::JSCAnonymousNamedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = true;
-const bool s_has_named_setter = true;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCAnonymousNamedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCAnonymousNamedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousNamedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCAnonymousNamedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCAnonymousNamedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousNamedGetterInterface::InterfaceObject::s_info = {
-    "AnonymousNamedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedGetterInterface::InterfaceObject)
-};  // JSCAnonymousNamedGetterInterface::InterfaceObject::s_info
-
-void JSCAnonymousNamedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCAnonymousNamedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "AnonymousNamedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCAnonymousNamedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCAnonymousNamedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousNamedGetterInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCAnonymousNamedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousNamedGetterInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousNamedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousNamedGetterInterface::Prototype::s_info = {
-    "AnonymousNamedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedGetterInterface::Prototype)
-};  // JSCAnonymousNamedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCAnonymousNamedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCAnonymousNamedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCAnonymousNamedGetterInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousNamedGetterInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousNamedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCAnonymousNamedGetterInterface::NonTrivialStaticFields>
-    JSCAnonymousNamedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCAnonymousNamedGetterInterface::s_info = {
-    "AnonymousNamedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedGetterInterface)
-};  // JSCAnonymousNamedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCAnonymousNamedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCAnonymousNamedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  AnonymousNamedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<AnonymousNamedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCAnonymousNamedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCAnonymousNamedGetterInterface>(global_data.heap))
-      JSCAnonymousNamedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCAnonymousNamedGetterInterface::JSCAnonymousNamedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<AnonymousNamedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCAnonymousNamedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCAnonymousNamedGetterInterface::~JSCAnonymousNamedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCAnonymousNamedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCAnonymousNamedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCAnonymousNamedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCAnonymousNamedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (s_has_named_getter) {
-    JSCAnonymousNamedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCAnonymousNamedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, object);
-  if (impl) {
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCAnonymousNamedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCAnonymousNamedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCAnonymousNamedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCAnonymousNamedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCAnonymousNamedGetterInterface::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("JSCAnonymousNamedGetterInterface", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-
-bool JSCAnonymousNamedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCAnonymousNamedGetterInterface", "deletePropertyByIndex");
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deletePropertyByIndex(cell, exec_state, index);
-  }
-  return false;
-}
-
-bool JSCAnonymousNamedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCAnonymousNamedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCAnonymousNamedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCAnonymousNamedGetterInterface", "NamedPropertyGetter");
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->AnonymousNamedGetter(property_name_utf8));
-  return result;
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCAnonymousNamedGetterInterface", "NamedPropertySetter");
-  AnonymousNamedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  std::string value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->AnonymousNamedSetter(property_name_utf8, value);
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.h
deleted file mode 100644
index 53742d8..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedGetterInterface.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCAnonymousNamedGetterInterface_h
-#define JSCAnonymousNamedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/anonymous_named_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCAnonymousNamedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to AnonymousNamedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCAnonymousNamedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<AnonymousNamedGetterInterface>& impl);
-  ~JSCAnonymousNamedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCAnonymousNamedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.cc
deleted file mode 100644
index 807e02d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.cc
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCAnonymousNamedIndexedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::AnonymousNamedIndexedGetterInterface;
-using cobalt::bindings::testing::JSCAnonymousNamedIndexedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = true;
-const bool s_has_named_setter = true;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCAnonymousNamedIndexedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCAnonymousNamedIndexedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::s_info = {
-    "AnonymousNamedIndexedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedIndexedGetterInterface::InterfaceObject)
-};  // JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::s_info
-
-void JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCAnonymousNamedIndexedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedIndexedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "AnonymousNamedIndexedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCAnonymousNamedIndexedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCAnonymousNamedIndexedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCAnonymousNamedIndexedGetterInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCAnonymousNamedIndexedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedIndexedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousNamedIndexedGetterInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedIndexedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousNamedIndexedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedIndexedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCAnonymousNamedIndexedGetterInterface::Prototype::s_info = {
-    "AnonymousNamedIndexedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedIndexedGetterInterface::Prototype)
-};  // JSCAnonymousNamedIndexedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCAnonymousNamedIndexedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedIndexedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCAnonymousNamedIndexedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCAnonymousNamedIndexedGetterInterface::property_table_values[] = {
-    { "length",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlength),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCAnonymousNamedIndexedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCAnonymousNamedIndexedGetterInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCAnonymousNamedIndexedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCAnonymousNamedIndexedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCAnonymousNamedIndexedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCAnonymousNamedIndexedGetterInterface::NonTrivialStaticFields>
-    JSCAnonymousNamedIndexedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCAnonymousNamedIndexedGetterInterface::s_info = {
-    "AnonymousNamedIndexedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCAnonymousNamedIndexedGetterInterface)
-};  // JSCAnonymousNamedIndexedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCAnonymousNamedIndexedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedIndexedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCAnonymousNamedIndexedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCAnonymousNamedIndexedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  AnonymousNamedIndexedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<AnonymousNamedIndexedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCAnonymousNamedIndexedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCAnonymousNamedIndexedGetterInterface>(global_data.heap))
-      JSCAnonymousNamedIndexedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCAnonymousNamedIndexedGetterInterface::JSCAnonymousNamedIndexedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<AnonymousNamedIndexedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCAnonymousNamedIndexedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCAnonymousNamedIndexedGetterInterface::~JSCAnonymousNamedIndexedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCAnonymousNamedIndexedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCAnonymousNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCAnonymousNamedIndexedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCAnonymousNamedIndexedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-  if (s_has_named_getter) {
-    JSCAnonymousNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedIndexedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCAnonymousNamedIndexedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, object);
-  if (impl) {
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCAnonymousNamedIndexedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCAnonymousNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCAnonymousNamedIndexedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCAnonymousNamedIndexedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCAnonymousNamedIndexedGetterInterface::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("JSCAnonymousNamedIndexedGetterInterface", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-
-bool JSCAnonymousNamedIndexedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "deletePropertyByIndex");
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-  }
-  return false;
-}
-
-bool JSCAnonymousNamedIndexedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCAnonymousNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCAnonymousNamedIndexedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCAnonymousNamedIndexedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "get length");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->length());
-  return result;
-}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "IndexedPropertyGetter");
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->AnonymousIndexedGetter(index));
-  return result;
-}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "IndexedPropertySetter");
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  uint32_t value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->AnonymousIndexedSetter(index, value);
-}
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "NamedPropertyGetter");
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->AnonymousNamedGetter(property_name_utf8));
-  return result;
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCAnonymousNamedIndexedGetterInterface", "NamedPropertySetter");
-  AnonymousNamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<AnonymousNamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  std::string value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->AnonymousNamedSetter(property_name_utf8, value);
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.h
deleted file mode 100644
index 7aff3ee..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCAnonymousNamedIndexedGetterInterface.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCAnonymousNamedIndexedGetterInterface_h
-#define JSCAnonymousNamedIndexedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/anonymous_named_indexed_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCAnonymousNamedIndexedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to AnonymousNamedIndexedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCAnonymousNamedIndexedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<AnonymousNamedIndexedGetterInterface>& impl);
-  ~JSCAnonymousNamedIndexedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCAnonymousNamedIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.cc
deleted file mode 100644
index 6ad9df6..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.cc
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCArbitraryInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSarbitraryProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSarbitraryProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue constructorJSArbitraryInterface(JSC::ExecState*);
-JSC::EncodedJSValue functionJSarbitraryFunction(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCArbitraryInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCArbitraryInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCArbitraryInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCArbitraryInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCArbitraryInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCArbitraryInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCArbitraryInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCArbitraryInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCArbitraryInterface::InterfaceObject::s_info = {
-    "ArbitraryInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCArbitraryInterface::InterfaceObject)
-};  // JSCArbitraryInterface::InterfaceObject::s_info
-
-void JSCArbitraryInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCArbitraryInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCArbitraryInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSArbitraryInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ArbitraryInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCArbitraryInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCArbitraryInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCArbitraryInterface::Prototype::property_table_values[] = {
-    { "arbitraryFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSarbitraryFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCArbitraryInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCArbitraryInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCArbitraryInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCArbitraryInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCArbitraryInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCArbitraryInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCArbitraryInterface::Prototype::s_info = {
-    "ArbitraryInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCArbitraryInterface::Prototype)
-};  // JSCArbitraryInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCArbitraryInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCArbitraryInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCArbitraryInterface::Prototype class
-
-const JSC::HashTableValue JSCArbitraryInterface::property_table_values[] = {
-    { "arbitraryProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSarbitraryProperty),
-        reinterpret_cast<intptr_t>(setJSarbitraryProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCArbitraryInterface::property_table_values
-
-// static
-const JSC::HashTable JSCArbitraryInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCArbitraryInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCArbitraryInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCArbitraryInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCArbitraryInterface::NonTrivialStaticFields>
-    JSCArbitraryInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCArbitraryInterface::s_info = {
-    "ArbitraryInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCArbitraryInterface)
-};  // JSCArbitraryInterface::s_info
-
-// static
-JSC::JSObject* JSCArbitraryInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCArbitraryInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCArbitraryInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCArbitraryInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ArbitraryInterface::ArbitraryInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ArbitraryInterface::ArbitraryInterfaceWrappableType()";
-    return NULL;
-  }
-  ArbitraryInterface* impl_ptr =
-      base::polymorphic_downcast<ArbitraryInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCArbitraryInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCArbitraryInterface>(global_data.heap))
-      JSCArbitraryInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCArbitraryInterface::JSCArbitraryInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ArbitraryInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCArbitraryInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCArbitraryInterface::~JSCArbitraryInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCArbitraryInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCArbitraryInterface* this_object = JSC::jsCast<JSCArbitraryInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCArbitraryInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCArbitraryInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCArbitraryInterface* this_object = JSC::jsCast<JSCArbitraryInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCArbitraryInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCArbitraryInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCArbitraryInterface* this_object = JSC::jsCast<JSCArbitraryInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCArbitraryInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSarbitraryProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCArbitraryInterface", "get arbitraryProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ArbitraryInterface* impl =
-      GetWrappableOrSetException<ArbitraryInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->arbitrary_property());
-  return result;
-}
-
-void setJSarbitraryProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCArbitraryInterface", "set arbitraryProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ArbitraryInterface* impl =
-      GetWrappableOrSetException<ArbitraryInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_arbitrary_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue constructorJSArbitraryInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<ArbitraryInterface> new_object =
-        new ArbitraryInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue functionJSarbitraryFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCArbitraryInterface", "call arbitraryFunction");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  ArbitraryInterface* impl =
-      GetWrappableOrSetException<ArbitraryInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->ArbitraryFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.h
deleted file mode 100644
index 0ea203b..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCArbitraryInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCArbitraryInterface_h
-#define JSCArbitraryInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCArbitraryInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ArbitraryInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCArbitraryInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ArbitraryInterface>& impl);
-  ~JSCArbitraryInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCArbitraryInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.cc
deleted file mode 100644
index 0af6ea5..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.cc
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCBaseInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::BaseInterface;
-using cobalt::bindings::testing::JSCBaseInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSbaseAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::EncodedJSValue constructorJSBaseInterface(JSC::ExecState*);
-JSC::EncodedJSValue functionJSbaseOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCBaseInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCBaseInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCBaseInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBaseInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCBaseInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBaseInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCBaseInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBaseInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCBaseInterface::InterfaceObject::s_info = {
-    "BaseInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBaseInterface::InterfaceObject)
-};  // JSCBaseInterface::InterfaceObject::s_info
-
-void JSCBaseInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCBaseInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCBaseInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSBaseInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "BaseInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCBaseInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCBaseInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCBaseInterface::Prototype::property_table_values[] = {
-    { "baseOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSbaseOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCBaseInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBaseInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCBaseInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBaseInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCBaseInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBaseInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCBaseInterface::Prototype::s_info = {
-    "BaseInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBaseInterface::Prototype)
-};  // JSCBaseInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCBaseInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCBaseInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCBaseInterface::Prototype class
-
-const JSC::HashTableValue JSCBaseInterface::property_table_values[] = {
-    { "baseAttribute",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSbaseAttribute),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBaseInterface::property_table_values
-
-// static
-const JSC::HashTable JSCBaseInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBaseInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCBaseInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBaseInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCBaseInterface::NonTrivialStaticFields>
-    JSCBaseInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCBaseInterface::s_info = {
-    "BaseInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBaseInterface)
-};  // JSCBaseInterface::s_info
-
-// static
-JSC::JSObject* JSCBaseInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCBaseInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCBaseInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCBaseInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == BaseInterface::BaseInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match BaseInterface::BaseInterfaceWrappableType()";
-    return NULL;
-  }
-  BaseInterface* impl_ptr =
-      base::polymorphic_downcast<BaseInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCBaseInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCBaseInterface>(global_data.heap))
-      JSCBaseInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCBaseInterface::JSCBaseInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<BaseInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCBaseInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCBaseInterface::~JSCBaseInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCBaseInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCBaseInterface* this_object = JSC::jsCast<JSCBaseInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCBaseInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCBaseInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCBaseInterface* this_object = JSC::jsCast<JSCBaseInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCBaseInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCBaseInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCBaseInterface* this_object = JSC::jsCast<JSCBaseInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCBaseInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSbaseAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCBaseInterface", "get baseAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  BaseInterface* impl =
-      GetWrappableOrSetException<BaseInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->base_attribute());
-  return result;
-}
-
-JSC::EncodedJSValue constructorJSBaseInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<BaseInterface> new_object =
-        new BaseInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue functionJSbaseOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCBaseInterface", "call baseOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  BaseInterface* impl =
-      GetWrappableOrSetException<BaseInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->BaseOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.h
deleted file mode 100644
index dfdf90a..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCBaseInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCBaseInterface_h
-#define JSCBaseInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/base_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCBaseInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to BaseInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCBaseInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<BaseInterface>& impl);
-  ~JSCBaseInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCBaseInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.cc
deleted file mode 100644
index 23b1192..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.cc
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCBooleanTypeTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::BooleanTypeTestInterface;
-using cobalt::bindings::testing::JSCBooleanTypeTestInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSbooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSbooleanProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSbooleanArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSbooleanReturnOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCBooleanTypeTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCBooleanTypeTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCBooleanTypeTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBooleanTypeTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCBooleanTypeTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBooleanTypeTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCBooleanTypeTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBooleanTypeTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCBooleanTypeTestInterface::InterfaceObject::s_info = {
-    "BooleanTypeTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBooleanTypeTestInterface::InterfaceObject)
-};  // JSCBooleanTypeTestInterface::InterfaceObject::s_info
-
-void JSCBooleanTypeTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCBooleanTypeTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCBooleanTypeTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "BooleanTypeTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCBooleanTypeTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCBooleanTypeTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCBooleanTypeTestInterface::Prototype::property_table_values[] = {
-    { "booleanArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSbooleanArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "booleanReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSbooleanReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCBooleanTypeTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBooleanTypeTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCBooleanTypeTestInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBooleanTypeTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCBooleanTypeTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBooleanTypeTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCBooleanTypeTestInterface::Prototype::s_info = {
-    "BooleanTypeTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBooleanTypeTestInterface::Prototype)
-};  // JSCBooleanTypeTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCBooleanTypeTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCBooleanTypeTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCBooleanTypeTestInterface::Prototype class
-
-const JSC::HashTableValue JSCBooleanTypeTestInterface::property_table_values[] = {
-    { "booleanProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSbooleanProperty),
-        reinterpret_cast<intptr_t>(setJSbooleanProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCBooleanTypeTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCBooleanTypeTestInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCBooleanTypeTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCBooleanTypeTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCBooleanTypeTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCBooleanTypeTestInterface::NonTrivialStaticFields>
-    JSCBooleanTypeTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCBooleanTypeTestInterface::s_info = {
-    "BooleanTypeTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCBooleanTypeTestInterface)
-};  // JSCBooleanTypeTestInterface::s_info
-
-// static
-JSC::JSObject* JSCBooleanTypeTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCBooleanTypeTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCBooleanTypeTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCBooleanTypeTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType()";
-    return NULL;
-  }
-  BooleanTypeTestInterface* impl_ptr =
-      base::polymorphic_downcast<BooleanTypeTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCBooleanTypeTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCBooleanTypeTestInterface>(global_data.heap))
-      JSCBooleanTypeTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCBooleanTypeTestInterface::JSCBooleanTypeTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<BooleanTypeTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCBooleanTypeTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCBooleanTypeTestInterface::~JSCBooleanTypeTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCBooleanTypeTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCBooleanTypeTestInterface* this_object = JSC::jsCast<JSCBooleanTypeTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCBooleanTypeTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCBooleanTypeTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCBooleanTypeTestInterface* this_object = JSC::jsCast<JSCBooleanTypeTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCBooleanTypeTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCBooleanTypeTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCBooleanTypeTestInterface* this_object = JSC::jsCast<JSCBooleanTypeTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCBooleanTypeTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSbooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCBooleanTypeTestInterface", "get booleanProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  BooleanTypeTestInterface* impl =
-      GetWrappableOrSetException<BooleanTypeTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->boolean_property());
-  return result;
-}
-
-void setJSbooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCBooleanTypeTestInterface", "set booleanProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  BooleanTypeTestInterface* impl =
-      GetWrappableOrSetException<BooleanTypeTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<bool >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_boolean_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSbooleanArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCBooleanTypeTestInterface", "call booleanArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  BooleanTypeTestInterface* impl =
-      GetWrappableOrSetException<BooleanTypeTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<bool >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->BooleanArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSbooleanReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCBooleanTypeTestInterface", "call booleanReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  BooleanTypeTestInterface* impl =
-      GetWrappableOrSetException<BooleanTypeTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<bool >::ReturnType return_value = impl->BooleanReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.h
deleted file mode 100644
index 86a52fe..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCBooleanTypeTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCBooleanTypeTestInterface_h
-#define JSCBooleanTypeTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/boolean_type_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCBooleanTypeTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to BooleanTypeTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCBooleanTypeTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<BooleanTypeTestInterface>& impl);
-  ~JSCBooleanTypeTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCBooleanTypeTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.cc
deleted file mode 100644
index e80158a..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.cc
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCCallbackFunctionInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::CallbackFunctionInterface;
-using cobalt::bindings::testing::JSCCallbackFunctionInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJScallbackAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableCallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableCallbackAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJStakesFunctionThatReturnsString(JSC::ExecState*);
-JSC::EncodedJSValue functionJStakesFunctionWithNullableParameters(JSC::ExecState*);
-JSC::EncodedJSValue functionJStakesFunctionWithOneParameter(JSC::ExecState*);
-JSC::EncodedJSValue functionJStakesFunctionWithSeveralParameters(JSC::ExecState*);
-JSC::EncodedJSValue functionJStakesVoidFunction(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCCallbackFunctionInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCCallbackFunctionInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCCallbackFunctionInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackFunctionInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCCallbackFunctionInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackFunctionInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCCallbackFunctionInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackFunctionInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCCallbackFunctionInterface::InterfaceObject::s_info = {
-    "CallbackFunctionInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackFunctionInterface::InterfaceObject)
-};  // JSCCallbackFunctionInterface::InterfaceObject::s_info
-
-void JSCCallbackFunctionInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCCallbackFunctionInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCCallbackFunctionInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "CallbackFunctionInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCCallbackFunctionInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCCallbackFunctionInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCCallbackFunctionInterface::Prototype::property_table_values[] = {
-    { "takesFunctionThatReturnsString",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStakesFunctionThatReturnsString),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "takesFunctionWithNullableParameters",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStakesFunctionWithNullableParameters),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "takesFunctionWithOneParameter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStakesFunctionWithOneParameter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "takesFunctionWithSeveralParameters",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStakesFunctionWithSeveralParameters),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "takesVoidFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStakesVoidFunction),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCCallbackFunctionInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackFunctionInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCCallbackFunctionInterface::Prototype::property_table_prototype = {
-    21,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackFunctionInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCCallbackFunctionInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackFunctionInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCCallbackFunctionInterface::Prototype::s_info = {
-    "CallbackFunctionInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackFunctionInterface::Prototype)
-};  // JSCCallbackFunctionInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCCallbackFunctionInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCCallbackFunctionInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCCallbackFunctionInterface::Prototype class
-
-const JSC::HashTableValue JSCCallbackFunctionInterface::property_table_values[] = {
-    { "callbackAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJScallbackAttribute),
-        reinterpret_cast<intptr_t>(setJScallbackAttribute),
-        JSC::NoIntrinsic
-    },
-    { "nullableCallbackAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableCallbackAttribute),
-        reinterpret_cast<intptr_t>(setJSnullableCallbackAttribute),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackFunctionInterface::property_table_values
-
-// static
-const JSC::HashTable JSCCallbackFunctionInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackFunctionInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCCallbackFunctionInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackFunctionInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCCallbackFunctionInterface::NonTrivialStaticFields>
-    JSCCallbackFunctionInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCCallbackFunctionInterface::s_info = {
-    "CallbackFunctionInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackFunctionInterface)
-};  // JSCCallbackFunctionInterface::s_info
-
-// static
-JSC::JSObject* JSCCallbackFunctionInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCCallbackFunctionInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCCallbackFunctionInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCCallbackFunctionInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType()";
-    return NULL;
-  }
-  CallbackFunctionInterface* impl_ptr =
-      base::polymorphic_downcast<CallbackFunctionInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCCallbackFunctionInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCCallbackFunctionInterface>(global_data.heap))
-      JSCCallbackFunctionInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCCallbackFunctionInterface::JSCCallbackFunctionInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<CallbackFunctionInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCCallbackFunctionInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCCallbackFunctionInterface::~JSCCallbackFunctionInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCCallbackFunctionInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCCallbackFunctionInterface* this_object = JSC::jsCast<JSCCallbackFunctionInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCCallbackFunctionInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCCallbackFunctionInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCCallbackFunctionInterface* this_object = JSC::jsCast<JSCCallbackFunctionInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCCallbackFunctionInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCCallbackFunctionInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCCallbackFunctionInterface* this_object = JSC::jsCast<JSCCallbackFunctionInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCCallbackFunctionInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "get callbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->callback_attribute());
-  return result;
-}
-
-void setJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "set callbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_callback_attribute(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableCallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "get nullableCallbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_callback_attribute());
-  return result;
-}
-
-void setJSnullableCallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "set nullableCallbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_callback_attribute(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJStakesFunctionThatReturnsString(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "call takesFunctionThatReturnsString");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackFunctionInterface::FunctionThatReturnsString >::ConversionType cb;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &cb);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->TakesFunctionThatReturnsString(cb);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJStakesFunctionWithNullableParameters(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "call takesFunctionWithNullableParameters");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackFunctionInterface::FunctionWithNullableParameters >::ConversionType cb;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &cb);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->TakesFunctionWithNullableParameters(cb);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJStakesFunctionWithOneParameter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "call takesFunctionWithOneParameter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackFunctionInterface::FunctionWithOneParameter >::ConversionType cb;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &cb);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->TakesFunctionWithOneParameter(cb);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJStakesFunctionWithSeveralParameters(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "call takesFunctionWithSeveralParameters");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackFunctionInterface::FunctionWithSeveralParameters >::ConversionType cb;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &cb);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->TakesFunctionWithSeveralParameters(cb);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJStakesVoidFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackFunctionInterface", "call takesVoidFunction");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackFunctionInterface* impl =
-      GetWrappableOrSetException<CallbackFunctionInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType cb;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &cb);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->TakesVoidFunction(cb);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.h
deleted file mode 100644
index 71f4a8d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackFunctionInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCCallbackFunctionInterface_h
-#define JSCCallbackFunctionInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/callback_function_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCCallbackFunctionInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to CallbackFunctionInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCCallbackFunctionInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<CallbackFunctionInterface>& impl);
-  ~JSCCallbackFunctionInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCCallbackFunctionInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.cc
deleted file mode 100644
index 0654877..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.cc
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCCallbackInterfaceInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCSingleOperationInterface.h"
-#include "cobalt/bindings/testing/single_operation_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::CallbackInterfaceInterface;
-using cobalt::bindings::testing::JSCCallbackInterfaceInterface;
-using cobalt::bindings::testing::JSCSingleOperationInterface;
-using cobalt::bindings::testing::SingleOperationInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJScallbackAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSregisterCallback(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsomeOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCCallbackInterfaceInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCCallbackInterfaceInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCCallbackInterfaceInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackInterfaceInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCCallbackInterfaceInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackInterfaceInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCCallbackInterfaceInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackInterfaceInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCCallbackInterfaceInterface::InterfaceObject::s_info = {
-    "CallbackInterfaceInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackInterfaceInterface::InterfaceObject)
-};  // JSCCallbackInterfaceInterface::InterfaceObject::s_info
-
-void JSCCallbackInterfaceInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCCallbackInterfaceInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCCallbackInterfaceInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "CallbackInterfaceInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCCallbackInterfaceInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCCallbackInterfaceInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCCallbackInterfaceInterface::Prototype::property_table_values[] = {
-    { "registerCallback",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSregisterCallback),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "someOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsomeOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCCallbackInterfaceInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackInterfaceInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCCallbackInterfaceInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackInterfaceInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCCallbackInterfaceInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackInterfaceInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCCallbackInterfaceInterface::Prototype::s_info = {
-    "CallbackInterfaceInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackInterfaceInterface::Prototype)
-};  // JSCCallbackInterfaceInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCCallbackInterfaceInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCCallbackInterfaceInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCCallbackInterfaceInterface::Prototype class
-
-const JSC::HashTableValue JSCCallbackInterfaceInterface::property_table_values[] = {
-    { "callbackAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJScallbackAttribute),
-        reinterpret_cast<intptr_t>(setJScallbackAttribute),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCCallbackInterfaceInterface::property_table_values
-
-// static
-const JSC::HashTable JSCCallbackInterfaceInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCCallbackInterfaceInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCCallbackInterfaceInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCCallbackInterfaceInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCCallbackInterfaceInterface::NonTrivialStaticFields>
-    JSCCallbackInterfaceInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCCallbackInterfaceInterface::s_info = {
-    "CallbackInterfaceInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCCallbackInterfaceInterface)
-};  // JSCCallbackInterfaceInterface::s_info
-
-// static
-JSC::JSObject* JSCCallbackInterfaceInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCCallbackInterfaceInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCCallbackInterfaceInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCCallbackInterfaceInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType()";
-    return NULL;
-  }
-  CallbackInterfaceInterface* impl_ptr =
-      base::polymorphic_downcast<CallbackInterfaceInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCCallbackInterfaceInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCCallbackInterfaceInterface>(global_data.heap))
-      JSCCallbackInterfaceInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCCallbackInterfaceInterface::JSCCallbackInterfaceInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<CallbackInterfaceInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCCallbackInterfaceInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCCallbackInterfaceInterface::~JSCCallbackInterfaceInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCCallbackInterfaceInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCCallbackInterfaceInterface* this_object = JSC::jsCast<JSCCallbackInterfaceInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCCallbackInterfaceInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCCallbackInterfaceInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCCallbackInterfaceInterface* this_object = JSC::jsCast<JSCCallbackInterfaceInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCCallbackInterfaceInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCCallbackInterfaceInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCCallbackInterfaceInterface* this_object = JSC::jsCast<JSCCallbackInterfaceInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCCallbackInterfaceInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCCallbackInterfaceInterface", "get callbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  CallbackInterfaceInterface* impl =
-      GetWrappableOrSetException<CallbackInterfaceInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->callback_attribute());
-  return result;
-}
-
-void setJScallbackAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCCallbackInterfaceInterface", "set callbackAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  CallbackInterfaceInterface* impl =
-      GetWrappableOrSetException<CallbackInterfaceInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_callback_attribute(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSregisterCallback(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackInterfaceInterface", "call registerCallback");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackInterfaceInterface* impl =
-      GetWrappableOrSetException<CallbackInterfaceInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType callback_interface;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &callback_interface);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->RegisterCallback(callback_interface);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsomeOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCCallbackInterfaceInterface", "call someOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  CallbackInterfaceInterface* impl =
-      GetWrappableOrSetException<CallbackInterfaceInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->SomeOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.h
deleted file mode 100644
index a7feb43..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCCallbackInterfaceInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCCallbackInterfaceInterface_h
-#define JSCCallbackInterfaceInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/callback_interface_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCCallbackInterfaceInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to CallbackInterfaceInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCCallbackInterfaceInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<CallbackInterfaceInterface>& impl);
-  ~JSCCallbackInterfaceInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCCallbackInterfaceInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.cc
deleted file mode 100644
index c1d873b..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.cc
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCConditionalInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ConditionalInterface;
-using cobalt::bindings::testing::JSCConditionalInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-JSC::JSValue getJSenabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSenabledAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-#endif  // defined(ENABLE_CONDITIONAL_PROPERTY)
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-JSC::JSValue getJSdisabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSdisabledAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-#endif  // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-JSC::EncodedJSValue functionJSdisabledOperation(JSC::ExecState*);
-#endif  // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-JSC::EncodedJSValue functionJSenabledOperation(JSC::ExecState*);
-#endif  // defined(ENABLE_CONDITIONAL_PROPERTY)
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCConditionalInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCConditionalInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConditionalInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConditionalInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCConditionalInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConditionalInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCConditionalInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConditionalInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConditionalInterface::InterfaceObject::s_info = {
-    "ConditionalInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConditionalInterface::InterfaceObject)
-};  // JSCConditionalInterface::InterfaceObject::s_info
-
-void JSCConditionalInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCConditionalInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCConditionalInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ConditionalInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCConditionalInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCConditionalInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConditionalInterface::Prototype::property_table_values[] = {
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-    { "disabledOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSdisabledOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-#endif  // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-    { "enabledOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSenabledOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-#endif  // defined(ENABLE_CONDITIONAL_PROPERTY)
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCConditionalInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConditionalInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCConditionalInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConditionalInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConditionalInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConditionalInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConditionalInterface::Prototype::s_info = {
-    "ConditionalInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConditionalInterface::Prototype)
-};  // JSCConditionalInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCConditionalInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCConditionalInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCConditionalInterface::Prototype class
-
-const JSC::HashTableValue JSCConditionalInterface::property_table_values[] = {
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-    { "enabledAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSenabledAttribute),
-        reinterpret_cast<intptr_t>(setJSenabledAttribute),
-        JSC::NoIntrinsic
-    },
-#endif   // defined(ENABLE_CONDITIONAL_PROPERTY)
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-    { "disabledAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSdisabledAttribute),
-        reinterpret_cast<intptr_t>(setJSdisabledAttribute),
-        JSC::NoIntrinsic
-    },
-#endif   // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConditionalInterface::property_table_values
-
-// static
-const JSC::HashTable JSCConditionalInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConditionalInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConditionalInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConditionalInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCConditionalInterface::NonTrivialStaticFields>
-    JSCConditionalInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCConditionalInterface::s_info = {
-    "ConditionalInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConditionalInterface)
-};  // JSCConditionalInterface::s_info
-
-// static
-JSC::JSObject* JSCConditionalInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCConditionalInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCConditionalInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCConditionalInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ConditionalInterface::ConditionalInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ConditionalInterface::ConditionalInterfaceWrappableType()";
-    return NULL;
-  }
-  ConditionalInterface* impl_ptr =
-      base::polymorphic_downcast<ConditionalInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCConditionalInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCConditionalInterface>(global_data.heap))
-      JSCConditionalInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCConditionalInterface::JSCConditionalInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ConditionalInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCConditionalInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCConditionalInterface::~JSCConditionalInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCConditionalInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCConditionalInterface* this_object = JSC::jsCast<JSCConditionalInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCConditionalInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCConditionalInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCConditionalInterface* this_object = JSC::jsCast<JSCConditionalInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCConditionalInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCConditionalInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCConditionalInterface* this_object = JSC::jsCast<JSCConditionalInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCConditionalInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-JSC::JSValue getJSenabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCConditionalInterface", "get enabledAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->enabled_attribute());
-  return result;
-}
-
-void setJSenabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCConditionalInterface", "set enabledAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int32_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_enabled_attribute(cobalt_value);
-  }
-}
-#endif  // defined(ENABLE_CONDITIONAL_PROPERTY)
-
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-JSC::JSValue getJSdisabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCConditionalInterface", "get disabledAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->disabled_attribute());
-  return result;
-}
-
-void setJSdisabledAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCConditionalInterface", "set disabledAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int32_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_disabled_attribute(cobalt_value);
-  }
-}
-#endif  // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-
-JSC::EncodedJSValue functionJSdisabledOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCConditionalInterface", "call disabledOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->DisabledOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-#endif  // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
-
-JSC::EncodedJSValue functionJSenabledOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCConditionalInterface", "call enabledOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  ConditionalInterface* impl =
-      GetWrappableOrSetException<ConditionalInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->EnabledOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-#endif  // defined(ENABLE_CONDITIONAL_PROPERTY)
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
-#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.h
deleted file mode 100644
index 6a67c7f..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConditionalInterface.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCConditionalInterface_h
-#define JSCConditionalInterface_h
-
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/conditional_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCConditionalInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ConditionalInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCConditionalInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ConditionalInterface>& impl);
-  ~JSCConditionalInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
-
-#endif  // JSCConditionalInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.cc
deleted file mode 100644
index 7919ac5..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.cc
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCConstantsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ConstantsInterface;
-using cobalt::bindings::testing::JSCConstantsInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSINTEGER_CONSTANT(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSDOUBLE_CONSTANT(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCConstantsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCConstantsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstantsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { "INTEGER_CONSTANT",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSINTEGER_CONSTANT),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "DOUBLE_CONSTANT",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSDOUBLE_CONSTANT),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstantsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCConstantsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstantsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCConstantsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstantsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstantsInterface::InterfaceObject::s_info = {
-    "ConstantsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstantsInterface::InterfaceObject)
-};  // JSCConstantsInterface::InterfaceObject::s_info
-
-void JSCConstantsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCConstantsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCConstantsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ConstantsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCConstantsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCConstantsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstantsInterface::Prototype::property_table_values[] = {
-    { "INTEGER_CONSTANT",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSINTEGER_CONSTANT),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "DOUBLE_CONSTANT",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSDOUBLE_CONSTANT),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCConstantsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstantsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCConstantsInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstantsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstantsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstantsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstantsInterface::Prototype::s_info = {
-    "ConstantsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstantsInterface::Prototype)
-};  // JSCConstantsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCConstantsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCConstantsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCConstantsInterface::Prototype class
-
-const JSC::HashTableValue JSCConstantsInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstantsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCConstantsInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstantsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstantsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstantsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCConstantsInterface::NonTrivialStaticFields>
-    JSCConstantsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCConstantsInterface::s_info = {
-    "ConstantsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstantsInterface)
-};  // JSCConstantsInterface::s_info
-
-// static
-JSC::JSObject* JSCConstantsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCConstantsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCConstantsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCConstantsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ConstantsInterface::ConstantsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ConstantsInterface::ConstantsInterfaceWrappableType()";
-    return NULL;
-  }
-  ConstantsInterface* impl_ptr =
-      base::polymorphic_downcast<ConstantsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCConstantsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCConstantsInterface>(global_data.heap))
-      JSCConstantsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCConstantsInterface::JSCConstantsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ConstantsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCConstantsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCConstantsInterface::~JSCConstantsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCConstantsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCConstantsInterface* this_object = JSC::jsCast<JSCConstantsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCConstantsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCConstantsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCConstantsInterface* this_object = JSC::jsCast<JSCConstantsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCConstantsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCConstantsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCConstantsInterface* this_object = JSC::jsCast<JSCConstantsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCConstantsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSINTEGER_CONSTANT(
-    JSC::ExecState* exec_state, JSC::JSValue, JSC::PropertyName) {
-  TRACE_EVENT0("JSCConstantsInterface", "get INTEGER_CONSTANT");
-  COMPILE_ASSERT(ConstantsInterface::kIntegerConstant == 5,
-                 ValueForConstantsInterface_kIntegerConstantDoesNotMatchIDL);
-  // JSCGlobalObject* is only needed for non-primitive types.
-  return ToJSValue(NULL, 5);
-}
-
-JSC::JSValue getJSDOUBLE_CONSTANT(
-    JSC::ExecState* exec_state, JSC::JSValue, JSC::PropertyName) {
-  TRACE_EVENT0("JSCConstantsInterface", "get DOUBLE_CONSTANT");
-  DCHECK_EQ(2.718, ConstantsInterface::kDoubleConstant) <<
-      "The value for ConstantsInterface::kDoubleConstant does not match "
-      "the value in the interface definition.";
-  // JSCGlobalObject* is only needed for non-primitive types.
-  return ToJSValue(NULL, 2.718);
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.h
deleted file mode 100644
index d977ced..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstantsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCConstantsInterface_h
-#define JSCConstantsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/constants_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCConstantsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ConstantsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCConstantsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ConstantsInterface>& impl);
-  ~JSCConstantsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCConstantsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.cc
deleted file mode 100644
index eac76c2..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.cc
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCConstructorInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ConstructorInterface;
-using cobalt::bindings::testing::JSCConstructorInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue constructorJSConstructorInterface(JSC::ExecState*);
-JSC::EncodedJSValue constructorJSConstructorInterface1(JSC::ExecState*);
-JSC::EncodedJSValue constructorJSConstructorInterface2(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCConstructorInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCConstructorInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstructorInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCConstructorInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCConstructorInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstructorInterface::InterfaceObject::s_info = {
-    "ConstructorInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorInterface::InterfaceObject)
-};  // JSCConstructorInterface::InterfaceObject::s_info
-
-void JSCConstructorInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCConstructorInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCConstructorInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSConstructorInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ConstructorInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCConstructorInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCConstructorInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstructorInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCConstructorInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCConstructorInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstructorInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstructorInterface::Prototype::s_info = {
-    "ConstructorInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorInterface::Prototype)
-};  // JSCConstructorInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCConstructorInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCConstructorInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCConstructorInterface::Prototype class
-
-const JSC::HashTableValue JSCConstructorInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorInterface::property_table_values
-
-// static
-const JSC::HashTable JSCConstructorInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstructorInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCConstructorInterface::NonTrivialStaticFields>
-    JSCConstructorInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCConstructorInterface::s_info = {
-    "ConstructorInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorInterface)
-};  // JSCConstructorInterface::s_info
-
-// static
-JSC::JSObject* JSCConstructorInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCConstructorInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCConstructorInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCConstructorInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ConstructorInterface::ConstructorInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ConstructorInterface::ConstructorInterfaceWrappableType()";
-    return NULL;
-  }
-  ConstructorInterface* impl_ptr =
-      base::polymorphic_downcast<ConstructorInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCConstructorInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCConstructorInterface>(global_data.heap))
-      JSCConstructorInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCConstructorInterface::JSCConstructorInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ConstructorInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCConstructorInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCConstructorInterface::~JSCConstructorInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCConstructorInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCConstructorInterface* this_object = JSC::jsCast<JSCConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCConstructorInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCConstructorInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCConstructorInterface* this_object = JSC::jsCast<JSCConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCConstructorInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCConstructorInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCConstructorInterface* this_object = JSC::jsCast<JSCConstructorInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCConstructorInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue constructorJSConstructorInterface(JSC::ExecState* exec_state) {
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-    case(0): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return constructorJSConstructorInterface1(exec_state);
-      }
-      break;
-    }
-    case(1): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return constructorJSConstructorInterface2(exec_state);
-      }
-      break;
-    }
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-}
-
-JSC::EncodedJSValue constructorJSConstructorInterface1(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<ConstructorInterface> new_object =
-        new ConstructorInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue constructorJSConstructorInterface2(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<bool >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-    scoped_refptr<ConstructorInterface> new_object =
-        new ConstructorInterface(arg);
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.h
deleted file mode 100644
index 3d0eb62..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCConstructorInterface_h
-#define JSCConstructorInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/constructor_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCConstructorInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ConstructorInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCConstructorInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ConstructorInterface>& impl);
-  ~JSCConstructorInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.cc
deleted file mode 100644
index dc8159a..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.cc
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCConstructorWithArgumentsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ConstructorWithArgumentsInterface;
-using cobalt::bindings::testing::JSCConstructorWithArgumentsInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlongArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSbooleanArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSstringArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::EncodedJSValue constructorJSConstructorWithArgumentsInterface(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCConstructorWithArgumentsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCConstructorWithArgumentsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstructorWithArgumentsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorWithArgumentsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCConstructorWithArgumentsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorWithArgumentsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCConstructorWithArgumentsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorWithArgumentsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstructorWithArgumentsInterface::InterfaceObject::s_info = {
-    "ConstructorWithArgumentsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorWithArgumentsInterface::InterfaceObject)
-};  // JSCConstructorWithArgumentsInterface::InterfaceObject::s_info
-
-void JSCConstructorWithArgumentsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCConstructorWithArgumentsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCConstructorWithArgumentsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 2;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSConstructorWithArgumentsInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ConstructorWithArgumentsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCConstructorWithArgumentsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCConstructorWithArgumentsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCConstructorWithArgumentsInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCConstructorWithArgumentsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorWithArgumentsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCConstructorWithArgumentsInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorWithArgumentsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstructorWithArgumentsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorWithArgumentsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCConstructorWithArgumentsInterface::Prototype::s_info = {
-    "ConstructorWithArgumentsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorWithArgumentsInterface::Prototype)
-};  // JSCConstructorWithArgumentsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCConstructorWithArgumentsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCConstructorWithArgumentsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCConstructorWithArgumentsInterface::Prototype class
-
-const JSC::HashTableValue JSCConstructorWithArgumentsInterface::property_table_values[] = {
-    { "longArg",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlongArg),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "booleanArg",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSbooleanArg),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "stringArg",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSstringArg),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCConstructorWithArgumentsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCConstructorWithArgumentsInterface::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCConstructorWithArgumentsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCConstructorWithArgumentsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCConstructorWithArgumentsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCConstructorWithArgumentsInterface::NonTrivialStaticFields>
-    JSCConstructorWithArgumentsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCConstructorWithArgumentsInterface::s_info = {
-    "ConstructorWithArgumentsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCConstructorWithArgumentsInterface)
-};  // JSCConstructorWithArgumentsInterface::s_info
-
-// static
-JSC::JSObject* JSCConstructorWithArgumentsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCConstructorWithArgumentsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCConstructorWithArgumentsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCConstructorWithArgumentsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType()";
-    return NULL;
-  }
-  ConstructorWithArgumentsInterface* impl_ptr =
-      base::polymorphic_downcast<ConstructorWithArgumentsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCConstructorWithArgumentsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCConstructorWithArgumentsInterface>(global_data.heap))
-      JSCConstructorWithArgumentsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCConstructorWithArgumentsInterface::JSCConstructorWithArgumentsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ConstructorWithArgumentsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCConstructorWithArgumentsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCConstructorWithArgumentsInterface::~JSCConstructorWithArgumentsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCConstructorWithArgumentsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCConstructorWithArgumentsInterface* this_object = JSC::jsCast<JSCConstructorWithArgumentsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCConstructorWithArgumentsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCConstructorWithArgumentsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCConstructorWithArgumentsInterface* this_object = JSC::jsCast<JSCConstructorWithArgumentsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCConstructorWithArgumentsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCConstructorWithArgumentsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCConstructorWithArgumentsInterface* this_object = JSC::jsCast<JSCConstructorWithArgumentsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCConstructorWithArgumentsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlongArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCConstructorWithArgumentsInterface", "get longArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ConstructorWithArgumentsInterface* impl =
-      GetWrappableOrSetException<ConstructorWithArgumentsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->long_arg());
-  return result;
-}
-
-JSC::JSValue getJSbooleanArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCConstructorWithArgumentsInterface", "get booleanArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ConstructorWithArgumentsInterface* impl =
-      GetWrappableOrSetException<ConstructorWithArgumentsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->boolean_arg());
-  return result;
-}
-
-JSC::JSValue getJSstringArg(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCConstructorWithArgumentsInterface", "get stringArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ConstructorWithArgumentsInterface* impl =
-      GetWrappableOrSetException<ConstructorWithArgumentsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->string_arg());
-  return result;
-}
-
-JSC::EncodedJSValue constructorJSConstructorWithArgumentsInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  TypeTraits<bool >::ConversionType arg2;
-  // Optional arguments with default values
-  TypeTraits<std::string >::ConversionType default_arg =
-      "default";
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  size_t num_set_arguments = 3;
-  if (exec_state->argumentCount() > 2) {
-    FromJSValue(exec_state,
-        exec_state->argument(2),
-        kNoConversionFlags,
-        &exception_state,
-        &default_arg);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-  }
-    scoped_refptr<ConstructorWithArgumentsInterface> new_object =
-        new ConstructorWithArgumentsInterface(arg1, arg2, default_arg);
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.h
deleted file mode 100644
index 3a69aab..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCConstructorWithArgumentsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCConstructorWithArgumentsInterface_h
-#define JSCConstructorWithArgumentsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/constructor_with_arguments_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCConstructorWithArgumentsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ConstructorWithArgumentsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCConstructorWithArgumentsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ConstructorWithArgumentsInterface>& impl);
-  ~JSCConstructorWithArgumentsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCConstructorWithArgumentsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
deleted file mode 100644
index e37be61..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCDOMStringTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::DOMStringTestInterface;
-using cobalt::bindings::testing::JSCDOMStringTestInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSproperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSproperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSreadOnlyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSreadOnlyTokenProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSnullIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullIsEmptyProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSundefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSundefinedIsEmptyProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableUndefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableUndefinedIsEmptyProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCDOMStringTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCDOMStringTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDOMStringTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDOMStringTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCDOMStringTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDOMStringTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCDOMStringTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDOMStringTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDOMStringTestInterface::InterfaceObject::s_info = {
-    "DOMStringTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDOMStringTestInterface::InterfaceObject)
-};  // JSCDOMStringTestInterface::InterfaceObject::s_info
-
-void JSCDOMStringTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCDOMStringTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCDOMStringTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "DOMStringTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCDOMStringTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCDOMStringTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDOMStringTestInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCDOMStringTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDOMStringTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCDOMStringTestInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDOMStringTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDOMStringTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDOMStringTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDOMStringTestInterface::Prototype::s_info = {
-    "DOMStringTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDOMStringTestInterface::Prototype)
-};  // JSCDOMStringTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCDOMStringTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCDOMStringTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCDOMStringTestInterface::Prototype class
-
-const JSC::HashTableValue JSCDOMStringTestInterface::property_table_values[] = {
-    { "property",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSproperty),
-        reinterpret_cast<intptr_t>(setJSproperty),
-        JSC::NoIntrinsic
-    },
-    { "readOnlyProperty",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSreadOnlyProperty),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "readOnlyTokenProperty",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSreadOnlyTokenProperty),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "nullIsEmptyProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullIsEmptyProperty),
-        reinterpret_cast<intptr_t>(setJSnullIsEmptyProperty),
-        JSC::NoIntrinsic
-    },
-    { "undefinedIsEmptyProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSundefinedIsEmptyProperty),
-        reinterpret_cast<intptr_t>(setJSundefinedIsEmptyProperty),
-        JSC::NoIntrinsic
-    },
-    { "nullableUndefinedIsEmptyProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableUndefinedIsEmptyProperty),
-        reinterpret_cast<intptr_t>(setJSnullableUndefinedIsEmptyProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDOMStringTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCDOMStringTestInterface::property_table_prototype = {
-    21,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDOMStringTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDOMStringTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDOMStringTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCDOMStringTestInterface::NonTrivialStaticFields>
-    JSCDOMStringTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCDOMStringTestInterface::s_info = {
-    "DOMStringTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDOMStringTestInterface)
-};  // JSCDOMStringTestInterface::s_info
-
-// static
-JSC::JSObject* JSCDOMStringTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCDOMStringTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCDOMStringTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCDOMStringTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == DOMStringTestInterface::DOMStringTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match DOMStringTestInterface::DOMStringTestInterfaceWrappableType()";
-    return NULL;
-  }
-  DOMStringTestInterface* impl_ptr =
-      base::polymorphic_downcast<DOMStringTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCDOMStringTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCDOMStringTestInterface>(global_data.heap))
-      JSCDOMStringTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCDOMStringTestInterface::JSCDOMStringTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<DOMStringTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCDOMStringTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCDOMStringTestInterface::~JSCDOMStringTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCDOMStringTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCDOMStringTestInterface* this_object = JSC::jsCast<JSCDOMStringTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCDOMStringTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCDOMStringTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCDOMStringTestInterface* this_object = JSC::jsCast<JSCDOMStringTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCDOMStringTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCDOMStringTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCDOMStringTestInterface* this_object = JSC::jsCast<JSCDOMStringTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCDOMStringTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSproperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get property");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->property());
-  return result;
-}
-
-void setJSproperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "set property");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSreadOnlyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get readOnlyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->read_only_property());
-  return result;
-}
-
-JSC::JSValue getJSreadOnlyTokenProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get readOnlyTokenProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->read_only_token_property());
-  return result;
-}
-
-JSC::JSValue getJSnullIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get nullIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->null_is_empty_property());
-  return result;
-}
-
-void setJSnullIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "set nullIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagTreatNullAsEmptyString), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_null_is_empty_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSundefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get undefinedIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->undefined_is_empty_property());
-  return result;
-}
-
-void setJSundefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "set undefinedIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagTreatUndefinedAsEmptyString), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_undefined_is_empty_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableUndefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "get nullableUndefinedIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_undefined_is_empty_property());
-  return result;
-}
-
-void setJSnullableUndefinedIsEmptyProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDOMStringTestInterface", "set nullableUndefinedIsEmptyProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DOMStringTestInterface* impl =
-      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<std::string > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable | kConversionFlagTreatUndefinedAsEmptyString), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_undefined_is_empty_property(cobalt_value);
-  }
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.h
deleted file mode 100644
index 32ccb2c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCDOMStringTestInterface_h
-#define JSCDOMStringTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/dom_string_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCDOMStringTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to DOMStringTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCDOMStringTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<DOMStringTestInterface>& impl);
-  ~JSCDOMStringTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCDOMStringTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.cc
deleted file mode 100644
index a11005c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.cc
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCDerivedGetterSetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::DerivedGetterSetterInterface;
-using cobalt::bindings::testing::JSCDerivedGetterSetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSpropertyOnDerivedClass(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSpropertyOnDerivedClass(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSderivedIndexedGetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSderivedIndexedSetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoperationOnDerivedClass(JSC::ExecState*);
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = true;
-const bool s_has_named_setter = true;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = false;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCDerivedGetterSetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCDerivedGetterSetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDerivedGetterSetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedGetterSetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCDerivedGetterSetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedGetterSetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCDerivedGetterSetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedGetterSetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDerivedGetterSetterInterface::InterfaceObject::s_info = {
-    "DerivedGetterSetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedGetterSetterInterface::InterfaceObject)
-};  // JSCDerivedGetterSetterInterface::InterfaceObject::s_info
-
-void JSCDerivedGetterSetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCDerivedGetterSetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCDerivedGetterSetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "DerivedGetterSetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCDerivedGetterSetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCDerivedGetterSetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDerivedGetterSetterInterface::Prototype::property_table_values[] = {
-    { "derivedIndexedGetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSderivedIndexedGetter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "derivedIndexedSetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSderivedIndexedSetter),
-        static_cast<intptr_t>(2),
-        JSC::NoIntrinsic
-    },
-    { "operationOnDerivedClass",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoperationOnDerivedClass),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCDerivedGetterSetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedGetterSetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCDerivedGetterSetterInterface::Prototype::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedGetterSetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDerivedGetterSetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedGetterSetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDerivedGetterSetterInterface::Prototype::s_info = {
-    "DerivedGetterSetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedGetterSetterInterface::Prototype)
-};  // JSCDerivedGetterSetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCDerivedGetterSetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCDerivedGetterSetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype =
-        bindings::testing::JSCNamedIndexedGetterInterface::GetPrototype(global_object);
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCDerivedGetterSetterInterface::Prototype class
-
-const JSC::HashTableValue JSCDerivedGetterSetterInterface::property_table_values[] = {
-    { "length",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlength),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "propertyOnDerivedClass",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSpropertyOnDerivedClass),
-        reinterpret_cast<intptr_t>(setJSpropertyOnDerivedClass),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedGetterSetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCDerivedGetterSetterInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedGetterSetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDerivedGetterSetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedGetterSetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCDerivedGetterSetterInterface::NonTrivialStaticFields>
-    JSCDerivedGetterSetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCDerivedGetterSetterInterface::s_info = {
-    "DerivedGetterSetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedGetterSetterInterface)
-};  // JSCDerivedGetterSetterInterface::s_info
-
-// static
-JSC::JSObject* JSCDerivedGetterSetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCDerivedGetterSetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCDerivedGetterSetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCDerivedGetterSetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType()";
-    return NULL;
-  }
-  DerivedGetterSetterInterface* impl_ptr =
-      base::polymorphic_downcast<DerivedGetterSetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCDerivedGetterSetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCDerivedGetterSetterInterface>(global_data.heap))
-      JSCDerivedGetterSetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCDerivedGetterSetterInterface::JSCDerivedGetterSetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<DerivedGetterSetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCDerivedGetterSetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCDerivedGetterSetterInterface::~JSCDerivedGetterSetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCDerivedGetterSetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCDerivedGetterSetterInterface* this_object = JSC::jsCast<JSCDerivedGetterSetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCDerivedGetterSetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCDerivedGetterSetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-  if (s_has_named_getter) {
-    JSCDerivedGetterSetterInterface* this_object = JSC::jsCast<JSCDerivedGetterSetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCDerivedGetterSetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, object);
-  if (impl) {
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCDerivedGetterSetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCDerivedGetterSetterInterface* this_object = JSC::jsCast<JSCDerivedGetterSetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCDerivedGetterSetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCDerivedGetterSetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCDerivedGetterSetterInterface::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("JSCDerivedGetterSetterInterface", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-
-bool JSCDerivedGetterSetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "deletePropertyByIndex");
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (impl) {
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-  }
-  return false;
-}
-
-bool JSCDerivedGetterSetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCDerivedGetterSetterInterface* this_object = JSC::jsCast<JSCDerivedGetterSetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCDerivedGetterSetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "get length");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->length());
-  return result;
-}
-
-JSC::JSValue getJSpropertyOnDerivedClass(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "get propertyOnDerivedClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->property_on_derived_class());
-  return result;
-}
-
-void setJSpropertyOnDerivedClass(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "set propertyOnDerivedClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<bool >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_property_on_derived_class(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSderivedIndexedGetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "call derivedIndexedGetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  TypeTraits<uint32_t >::ReturnType return_value = impl->DerivedIndexedGetter(index);
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSderivedIndexedSetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "call derivedIndexedSetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-  TypeTraits<uint32_t >::ConversionType value;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->DerivedIndexedSetter(index, value);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoperationOnDerivedClass(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "call operationOnDerivedClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->OperationOnDerivedClass();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "IndexedPropertyGetter");
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->DerivedIndexedGetter(index));
-  return result;
-}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "IndexedPropertySetter");
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  uint32_t value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->DerivedIndexedSetter(index, value);
-}
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "NamedPropertyGetter");
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->AnonymousNamedGetter(property_name_utf8));
-  return result;
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCDerivedGetterSetterInterface", "NamedPropertySetter");
-  DerivedGetterSetterInterface* impl =
-      GetWrappableOrSetException<DerivedGetterSetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  std::string value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->AnonymousNamedSetter(property_name_utf8, value);
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.h
deleted file mode 100644
index dd449eb..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedGetterSetterInterface.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCDerivedGetterSetterInterface_h
-#define JSCDerivedGetterSetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "JSCNamedIndexedGetterInterface.h"
-#include "cobalt/bindings/testing/derived_getter_setter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCDerivedGetterSetterInterface
-    : public bindings::testing::JSCNamedIndexedGetterInterface {
-  typedef bindings::testing::JSCNamedIndexedGetterInterface BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to DerivedGetterSetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCDerivedGetterSetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<DerivedGetterSetterInterface>& impl);
-  ~JSCDerivedGetterSetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCDerivedGetterSetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
deleted file mode 100644
index 34a3976..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCDerivedInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::DerivedInterface;
-using cobalt::bindings::testing::JSCDerivedInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSderivedAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState*);
-JSC::EncodedJSValue functionJSderivedOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = false;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCDerivedInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCDerivedInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDerivedInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCDerivedInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCDerivedInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDerivedInterface::InterfaceObject::s_info = {
-    "DerivedInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedInterface::InterfaceObject)
-};  // JSCDerivedInterface::InterfaceObject::s_info
-
-void JSCDerivedInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCDerivedInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCDerivedInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSDerivedInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "DerivedInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCDerivedInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCDerivedInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDerivedInterface::Prototype::property_table_values[] = {
-    { "derivedOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSderivedOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCDerivedInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCDerivedInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDerivedInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDerivedInterface::Prototype::s_info = {
-    "DerivedInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedInterface::Prototype)
-};  // JSCDerivedInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCDerivedInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCDerivedInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype =
-        bindings::testing::JSCBaseInterface::GetPrototype(global_object);
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCDerivedInterface::Prototype class
-
-const JSC::HashTableValue JSCDerivedInterface::property_table_values[] = {
-    { "derivedAttribute",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSderivedAttribute),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDerivedInterface::property_table_values
-
-// static
-const JSC::HashTable JSCDerivedInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDerivedInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDerivedInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDerivedInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCDerivedInterface::NonTrivialStaticFields>
-    JSCDerivedInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCDerivedInterface::s_info = {
-    "DerivedInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDerivedInterface)
-};  // JSCDerivedInterface::s_info
-
-// static
-JSC::JSObject* JSCDerivedInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCDerivedInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCDerivedInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCDerivedInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == DerivedInterface::DerivedInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match DerivedInterface::DerivedInterfaceWrappableType()";
-    return NULL;
-  }
-  DerivedInterface* impl_ptr =
-      base::polymorphic_downcast<DerivedInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCDerivedInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCDerivedInterface>(global_data.heap))
-      JSCDerivedInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCDerivedInterface::JSCDerivedInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<DerivedInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCDerivedInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCDerivedInterface::~JSCDerivedInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCDerivedInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCDerivedInterface* this_object = JSC::jsCast<JSCDerivedInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCDerivedInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCDerivedInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCDerivedInterface* this_object = JSC::jsCast<JSCDerivedInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCDerivedInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCDerivedInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCDerivedInterface* this_object = JSC::jsCast<JSCDerivedInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCDerivedInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSderivedAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDerivedInterface", "get derivedAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DerivedInterface* impl =
-      GetWrappableOrSetException<DerivedInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->derived_attribute());
-  return result;
-}
-
-JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<DerivedInterface> new_object =
-        new DerivedInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue functionJSderivedOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCDerivedInterface", "call derivedOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  DerivedInterface* impl =
-      GetWrappableOrSetException<DerivedInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->DerivedOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.h
deleted file mode 100644
index 1aa746e..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCDerivedInterface_h
-#define JSCDerivedInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "JSCBaseInterface.h"
-#include "cobalt/bindings/testing/derived_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCDerivedInterface
-    : public bindings::testing::JSCBaseInterface {
-  typedef bindings::testing::JSCBaseInterface BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to DerivedInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCDerivedInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<DerivedInterface>& impl);
-  ~JSCDerivedInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCDerivedInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.cc
deleted file mode 100644
index dc31ae1..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.cc
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCDisabledInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::DisabledInterface;
-using cobalt::bindings::testing::JSCDisabledInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSdisabledProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSdisabledProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSdisabledFunction(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCDisabledInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCDisabledInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDisabledInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDisabledInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCDisabledInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDisabledInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCDisabledInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDisabledInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDisabledInterface::InterfaceObject::s_info = {
-    "DisabledInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDisabledInterface::InterfaceObject)
-};  // JSCDisabledInterface::InterfaceObject::s_info
-
-void JSCDisabledInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCDisabledInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCDisabledInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "DisabledInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCDisabledInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCDisabledInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCDisabledInterface::Prototype::property_table_values[] = {
-    { "disabledFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSdisabledFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCDisabledInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDisabledInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCDisabledInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDisabledInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDisabledInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDisabledInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCDisabledInterface::Prototype::s_info = {
-    "DisabledInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDisabledInterface::Prototype)
-};  // JSCDisabledInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCDisabledInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCDisabledInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCDisabledInterface::Prototype class
-
-const JSC::HashTableValue JSCDisabledInterface::property_table_values[] = {
-    { "disabledProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSdisabledProperty),
-        reinterpret_cast<intptr_t>(setJSdisabledProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCDisabledInterface::property_table_values
-
-// static
-const JSC::HashTable JSCDisabledInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCDisabledInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCDisabledInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCDisabledInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCDisabledInterface::NonTrivialStaticFields>
-    JSCDisabledInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCDisabledInterface::s_info = {
-    "DisabledInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCDisabledInterface)
-};  // JSCDisabledInterface::s_info
-
-// static
-JSC::JSObject* JSCDisabledInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCDisabledInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCDisabledInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCDisabledInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == DisabledInterface::DisabledInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match DisabledInterface::DisabledInterfaceWrappableType()";
-    return NULL;
-  }
-  DisabledInterface* impl_ptr =
-      base::polymorphic_downcast<DisabledInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCDisabledInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCDisabledInterface>(global_data.heap))
-      JSCDisabledInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCDisabledInterface::JSCDisabledInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<DisabledInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCDisabledInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCDisabledInterface::~JSCDisabledInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCDisabledInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCDisabledInterface* this_object = JSC::jsCast<JSCDisabledInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCDisabledInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCDisabledInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCDisabledInterface* this_object = JSC::jsCast<JSCDisabledInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCDisabledInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCDisabledInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCDisabledInterface* this_object = JSC::jsCast<JSCDisabledInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCDisabledInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSdisabledProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCDisabledInterface", "get disabledProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  DisabledInterface* impl =
-      GetWrappableOrSetException<DisabledInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->disabled_property());
-  return result;
-}
-
-void setJSdisabledProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCDisabledInterface", "set disabledProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  DisabledInterface* impl =
-      GetWrappableOrSetException<DisabledInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int32_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_disabled_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSdisabledFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCDisabledInterface", "call disabledFunction");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  DisabledInterface* impl =
-      GetWrappableOrSetException<DisabledInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->DisabledFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
-#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.h
deleted file mode 100644
index f03711f..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDisabledInterface.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCDisabledInterface_h
-#define JSCDisabledInterface_h
-
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/disabled_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCDisabledInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to DisabledInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCDisabledInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<DisabledInterface>& impl);
-  ~JSCDisabledInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-
-#endif  // JSCDisabledInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.cc
deleted file mode 100644
index 94267fc..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.cc
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCEnumerationInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::EnumerationInterface;
-using cobalt::bindings::testing::JSCEnumerationInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-// Declare and define these in the same namespace that the other overloads
-// were brought into with the using declaration.
-JSC::JSValue ToJSValue(JSCGlobalObject*, EnumerationInterface::TestEnum in_enum);
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-    int conversion_flags, JSCExceptionState* exception_state,
-    EnumerationInterface::TestEnum* out_enum);
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSenumProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSenumProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue constructorJSEnumerationInterface(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCEnumerationInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCEnumerationInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCEnumerationInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCEnumerationInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCEnumerationInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCEnumerationInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCEnumerationInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCEnumerationInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCEnumerationInterface::InterfaceObject::s_info = {
-    "EnumerationInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCEnumerationInterface::InterfaceObject)
-};  // JSCEnumerationInterface::InterfaceObject::s_info
-
-void JSCEnumerationInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCEnumerationInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCEnumerationInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSEnumerationInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "EnumerationInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCEnumerationInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCEnumerationInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCEnumerationInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCEnumerationInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCEnumerationInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCEnumerationInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCEnumerationInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCEnumerationInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCEnumerationInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCEnumerationInterface::Prototype::s_info = {
-    "EnumerationInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCEnumerationInterface::Prototype)
-};  // JSCEnumerationInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCEnumerationInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCEnumerationInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCEnumerationInterface::Prototype class
-
-const JSC::HashTableValue JSCEnumerationInterface::property_table_values[] = {
-    { "enumProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSenumProperty),
-        reinterpret_cast<intptr_t>(setJSenumProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCEnumerationInterface::property_table_values
-
-// static
-const JSC::HashTable JSCEnumerationInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCEnumerationInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCEnumerationInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCEnumerationInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCEnumerationInterface::NonTrivialStaticFields>
-    JSCEnumerationInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCEnumerationInterface::s_info = {
-    "EnumerationInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCEnumerationInterface)
-};  // JSCEnumerationInterface::s_info
-
-// static
-JSC::JSObject* JSCEnumerationInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCEnumerationInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCEnumerationInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCEnumerationInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == EnumerationInterface::EnumerationInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match EnumerationInterface::EnumerationInterfaceWrappableType()";
-    return NULL;
-  }
-  EnumerationInterface* impl_ptr =
-      base::polymorphic_downcast<EnumerationInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCEnumerationInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCEnumerationInterface>(global_data.heap))
-      JSCEnumerationInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCEnumerationInterface::JSCEnumerationInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<EnumerationInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCEnumerationInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCEnumerationInterface::~JSCEnumerationInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCEnumerationInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCEnumerationInterface* this_object = JSC::jsCast<JSCEnumerationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCEnumerationInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCEnumerationInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCEnumerationInterface* this_object = JSC::jsCast<JSCEnumerationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCEnumerationInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCEnumerationInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCEnumerationInterface* this_object = JSC::jsCast<JSCEnumerationInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCEnumerationInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSenumProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCEnumerationInterface", "get enumProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  EnumerationInterface* impl =
-      GetWrappableOrSetException<EnumerationInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->enum_property());
-  return result;
-}
-
-void setJSenumProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCEnumerationInterface", "set enumProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  EnumerationInterface* impl =
-      GetWrappableOrSetException<EnumerationInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<EnumerationInterface::TestEnum >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_enum_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue constructorJSEnumerationInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<EnumerationInterface> new_object =
-        new EnumerationInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
-
-namespace {
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object, EnumerationInterface::TestEnum in_enum) {
-  JSC::JSGlobalData* global_data = &(global_object->globalData());
-  switch (in_enum) {
-    case EnumerationInterface::kAlpha: return JSC::jsString(global_data, "alpha");
-    case EnumerationInterface::kBeta: return JSC::jsString(global_data, "beta");
-    case EnumerationInterface::kGamma: return JSC::jsString(global_data, "gamma");
-    default:
-      NOTREACHED();
-      return JSC::jsUndefined();
-  }
-}
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, JSCExceptionState* exception_state,
-                 EnumerationInterface::TestEnum* out_enum) {
-  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
-  // JSValue -> IDL enum algorithm described here:
-  // http://heycam.github.io/webidl/#es-enumeration
-
-  // 1. Let S be the result of calling ToString(V).
-  JSC::JSString* js_string = jsvalue.toString(exec_state);
-  if (exec_state->hadException()) {
-    DLOG(WARNING) << "Exception converting value to string";
-    return;
-  }
-  const WTF::String& wtf_string = js_string->tryGetValue();
-  // 3. Return the enumeration value of type E that is equal to S.
-if (wtf_string == "alpha") {
-    *out_enum = EnumerationInterface::kAlpha;
-  } else if (wtf_string == "beta") {
-    *out_enum = EnumerationInterface::kBeta;
-  } else if (wtf_string == "gamma") {
-    *out_enum = EnumerationInterface::kGamma;
-  } else {
-    // 2. If S is not one of E's enumeration values, then throw a TypeError.
-    JSC::throwTypeError(exec_state);
-  }
-}
-}  // namespace
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.h
deleted file mode 100644
index 3f1cd55..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCEnumerationInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCEnumerationInterface_h
-#define JSCEnumerationInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/enumeration_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCEnumerationInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to EnumerationInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCEnumerationInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<EnumerationInterface>& impl);
-  ~JSCEnumerationInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCEnumerationInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.cc
deleted file mode 100644
index 8ba3dbf..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.cc
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCExceptionObjectInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ExceptionObjectInterface;
-using cobalt::bindings::testing::JSCExceptionObjectInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSerror(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSmessage(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCExceptionObjectInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCExceptionObjectInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExceptionObjectInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionObjectInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCExceptionObjectInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionObjectInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCExceptionObjectInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionObjectInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExceptionObjectInterface::InterfaceObject::s_info = {
-    "ExceptionObjectInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionObjectInterface::InterfaceObject)
-};  // JSCExceptionObjectInterface::InterfaceObject::s_info
-
-void JSCExceptionObjectInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCExceptionObjectInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCExceptionObjectInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ExceptionObjectInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCExceptionObjectInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCExceptionObjectInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExceptionObjectInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCExceptionObjectInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionObjectInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCExceptionObjectInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionObjectInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExceptionObjectInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionObjectInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExceptionObjectInterface::Prototype::s_info = {
-    "ExceptionObjectInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionObjectInterface::Prototype)
-};  // JSCExceptionObjectInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCExceptionObjectInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCExceptionObjectInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->errorPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCExceptionObjectInterface::Prototype class
-
-const JSC::HashTableValue JSCExceptionObjectInterface::property_table_values[] = {
-    { "error",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSerror),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "message",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSmessage),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionObjectInterface::property_table_values
-
-// static
-const JSC::HashTable JSCExceptionObjectInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionObjectInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExceptionObjectInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionObjectInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCExceptionObjectInterface::NonTrivialStaticFields>
-    JSCExceptionObjectInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCExceptionObjectInterface::s_info = {
-    "ExceptionObjectInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionObjectInterface)
-};  // JSCExceptionObjectInterface::s_info
-
-// static
-JSC::JSObject* JSCExceptionObjectInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCExceptionObjectInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCExceptionObjectInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCExceptionObjectInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType()";
-    return NULL;
-  }
-  ExceptionObjectInterface* impl_ptr =
-      base::polymorphic_downcast<ExceptionObjectInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ErrorInstanceType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCExceptionObjectInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCExceptionObjectInterface>(global_data.heap))
-      JSCExceptionObjectInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  global_data.heap.addFinalizer(wrapper, destroy);
-  return wrapper;
-}
-JSCExceptionObjectInterface::JSCExceptionObjectInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ExceptionObjectInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCExceptionObjectInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  WTF::String error_message = ToWTFString(wrappable()->message());
-  BaseClass::finishCreation(global_data, error_message);
-  DCHECK(inherits(&s_info));
-}
-
-JSCExceptionObjectInterface::~JSCExceptionObjectInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCExceptionObjectInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCExceptionObjectInterface* this_object = JSC::jsCast<JSCExceptionObjectInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCExceptionObjectInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCExceptionObjectInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCExceptionObjectInterface* this_object = JSC::jsCast<JSCExceptionObjectInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCExceptionObjectInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCExceptionObjectInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCExceptionObjectInterface* this_object = JSC::jsCast<JSCExceptionObjectInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCExceptionObjectInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSerror(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCExceptionObjectInterface", "get error");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ExceptionObjectInterface* impl =
-      GetWrappableOrSetException<ExceptionObjectInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->error());
-  return result;
-}
-
-JSC::JSValue getJSmessage(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCExceptionObjectInterface", "get message");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ExceptionObjectInterface* impl =
-      GetWrappableOrSetException<ExceptionObjectInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->message());
-  return result;
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.h
deleted file mode 100644
index 9e1f2bc..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionObjectInterface.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCExceptionObjectInterface_h
-#define JSCExceptionObjectInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/exception_object_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorInstance.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCExceptionObjectInterface
-    : public script::javascriptcore::ExceptionBase {
-  typedef script::javascriptcore::ExceptionBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ExceptionObjectInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCExceptionObjectInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ExceptionObjectInterface>& impl);
-  ~JSCExceptionObjectInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCExceptionObjectInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.cc
deleted file mode 100644
index 2dab46e..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.cc
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCExceptionsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ExceptionsInterface;
-using cobalt::bindings::testing::JSCExceptionsInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSattributeThrowsException(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSattributeThrowsException(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue constructorJSExceptionsInterface(JSC::ExecState*);
-JSC::EncodedJSValue functionJSfunctionThrowsException(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCExceptionsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCExceptionsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExceptionsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCExceptionsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCExceptionsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExceptionsInterface::InterfaceObject::s_info = {
-    "ExceptionsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionsInterface::InterfaceObject)
-};  // JSCExceptionsInterface::InterfaceObject::s_info
-
-void JSCExceptionsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCExceptionsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCExceptionsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSExceptionsInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ExceptionsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCExceptionsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCExceptionsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExceptionsInterface::Prototype::property_table_values[] = {
-    { "functionThrowsException",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSfunctionThrowsException),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCExceptionsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCExceptionsInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExceptionsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExceptionsInterface::Prototype::s_info = {
-    "ExceptionsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionsInterface::Prototype)
-};  // JSCExceptionsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCExceptionsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCExceptionsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCExceptionsInterface::Prototype class
-
-const JSC::HashTableValue JSCExceptionsInterface::property_table_values[] = {
-    { "attributeThrowsException",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSattributeThrowsException),
-        reinterpret_cast<intptr_t>(setJSattributeThrowsException),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExceptionsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCExceptionsInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExceptionsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExceptionsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExceptionsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCExceptionsInterface::NonTrivialStaticFields>
-    JSCExceptionsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCExceptionsInterface::s_info = {
-    "ExceptionsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExceptionsInterface)
-};  // JSCExceptionsInterface::s_info
-
-// static
-JSC::JSObject* JSCExceptionsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCExceptionsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCExceptionsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCExceptionsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ExceptionsInterface::ExceptionsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ExceptionsInterface::ExceptionsInterfaceWrappableType()";
-    return NULL;
-  }
-  ExceptionsInterface* impl_ptr =
-      base::polymorphic_downcast<ExceptionsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCExceptionsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCExceptionsInterface>(global_data.heap))
-      JSCExceptionsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCExceptionsInterface::JSCExceptionsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ExceptionsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCExceptionsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCExceptionsInterface::~JSCExceptionsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCExceptionsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCExceptionsInterface* this_object = JSC::jsCast<JSCExceptionsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCExceptionsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCExceptionsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCExceptionsInterface* this_object = JSC::jsCast<JSCExceptionsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCExceptionsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCExceptionsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCExceptionsInterface* this_object = JSC::jsCast<JSCExceptionsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCExceptionsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSattributeThrowsException(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCExceptionsInterface", "get attributeThrowsException");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ExceptionsInterface* impl =
-      GetWrappableOrSetException<ExceptionsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCExceptionState exception_state(global_object);
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->attribute_throws_exception(&exception_state));
-  if (exception_state.is_exception_set()) {
-    return JSC::throwError(exec_state, exception_state.exception_object());
-  }
-  return result;
-}
-
-void setJSattributeThrowsException(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCExceptionsInterface", "set attributeThrowsException");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ExceptionsInterface* impl =
-      GetWrappableOrSetException<ExceptionsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<bool >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_attribute_throws_exception(cobalt_value, &exception_state);
-    if (exception_state.is_exception_set()) {
-      JSC::throwError(exec_state, exception_state.exception_object());
-    }
-  }
-}
-
-JSC::EncodedJSValue constructorJSExceptionsInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<ExceptionsInterface> new_object =
-        new ExceptionsInterface(&exception_state);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue functionJSfunctionThrowsException(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCExceptionsInterface", "call functionThrowsException");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  ExceptionsInterface* impl =
-      GetWrappableOrSetException<ExceptionsInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->FunctionThrowsException(&exception_state);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.h
deleted file mode 100644
index 8cf99e2..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExceptionsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCExceptionsInterface_h
-#define JSCExceptionsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/exceptions_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCExceptionsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ExceptionsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCExceptionsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ExceptionsInterface>& impl);
-  ~JSCExceptionsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCExceptionsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.cc
deleted file mode 100644
index 50b3d7a..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.cc
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCExtendedIDLAttributesInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ExtendedIDLAttributesInterface;
-using cobalt::bindings::testing::JSCExtendedIDLAttributesInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJScallWithSettings(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCExtendedIDLAttributesInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCExtendedIDLAttributesInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExtendedIDLAttributesInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExtendedIDLAttributesInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCExtendedIDLAttributesInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExtendedIDLAttributesInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCExtendedIDLAttributesInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExtendedIDLAttributesInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExtendedIDLAttributesInterface::InterfaceObject::s_info = {
-    "ExtendedIDLAttributesInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExtendedIDLAttributesInterface::InterfaceObject)
-};  // JSCExtendedIDLAttributesInterface::InterfaceObject::s_info
-
-void JSCExtendedIDLAttributesInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCExtendedIDLAttributesInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCExtendedIDLAttributesInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ExtendedIDLAttributesInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCExtendedIDLAttributesInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCExtendedIDLAttributesInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCExtendedIDLAttributesInterface::Prototype::property_table_values[] = {
-    { "callWithSettings",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJScallWithSettings),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCExtendedIDLAttributesInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExtendedIDLAttributesInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCExtendedIDLAttributesInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExtendedIDLAttributesInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExtendedIDLAttributesInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExtendedIDLAttributesInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCExtendedIDLAttributesInterface::Prototype::s_info = {
-    "ExtendedIDLAttributesInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExtendedIDLAttributesInterface::Prototype)
-};  // JSCExtendedIDLAttributesInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCExtendedIDLAttributesInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCExtendedIDLAttributesInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCExtendedIDLAttributesInterface::Prototype class
-
-const JSC::HashTableValue JSCExtendedIDLAttributesInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCExtendedIDLAttributesInterface::property_table_values
-
-// static
-const JSC::HashTable JSCExtendedIDLAttributesInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCExtendedIDLAttributesInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCExtendedIDLAttributesInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCExtendedIDLAttributesInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCExtendedIDLAttributesInterface::NonTrivialStaticFields>
-    JSCExtendedIDLAttributesInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCExtendedIDLAttributesInterface::s_info = {
-    "ExtendedIDLAttributesInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCExtendedIDLAttributesInterface)
-};  // JSCExtendedIDLAttributesInterface::s_info
-
-// static
-JSC::JSObject* JSCExtendedIDLAttributesInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCExtendedIDLAttributesInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCExtendedIDLAttributesInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCExtendedIDLAttributesInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType()";
-    return NULL;
-  }
-  ExtendedIDLAttributesInterface* impl_ptr =
-      base::polymorphic_downcast<ExtendedIDLAttributesInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCExtendedIDLAttributesInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCExtendedIDLAttributesInterface>(global_data.heap))
-      JSCExtendedIDLAttributesInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCExtendedIDLAttributesInterface::JSCExtendedIDLAttributesInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ExtendedIDLAttributesInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCExtendedIDLAttributesInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCExtendedIDLAttributesInterface::~JSCExtendedIDLAttributesInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCExtendedIDLAttributesInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCExtendedIDLAttributesInterface* this_object = JSC::jsCast<JSCExtendedIDLAttributesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCExtendedIDLAttributesInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCExtendedIDLAttributesInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCExtendedIDLAttributesInterface* this_object = JSC::jsCast<JSCExtendedIDLAttributesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCExtendedIDLAttributesInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCExtendedIDLAttributesInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCExtendedIDLAttributesInterface* this_object = JSC::jsCast<JSCExtendedIDLAttributesInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCExtendedIDLAttributesInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJScallWithSettings(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCExtendedIDLAttributesInterface", "call callWithSettings");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  ExtendedIDLAttributesInterface* impl =
-      GetWrappableOrSetException<ExtendedIDLAttributesInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->CallWithSettings(global_object->GetEnvironmentSettings());
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.h
deleted file mode 100644
index 42e2316..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCExtendedIDLAttributesInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCExtendedIDLAttributesInterface_h
-#define JSCExtendedIDLAttributesInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/extended_idl_attributes_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCExtendedIDLAttributesInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ExtendedIDLAttributesInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCExtendedIDLAttributesInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ExtendedIDLAttributesInterface>& impl);
-  ~JSCExtendedIDLAttributesInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCExtendedIDLAttributesInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.cc
deleted file mode 100644
index 035124a..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.cc
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCGarbageCollectionTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCGarbageCollectionTestInterface.h"
-#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::GarbageCollectionTestInterface;
-using cobalt::bindings::testing::JSCGarbageCollectionTestInterface;
-using cobalt::bindings::testing::GarbageCollectionTestInterface;
-using cobalt::bindings::testing::JSCGarbageCollectionTestInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSprevious(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSprevious(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnext(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnext(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue constructorJSGarbageCollectionTestInterface(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-scoped_refptr<Wrappable> GetOpaqueRootFromWrappable(
-    const scoped_refptr<Wrappable>& wrappable) {
-  GarbageCollectionTestInterface* impl =
-      base::polymorphic_downcast<GarbageCollectionTestInterface*>(wrappable.get());
-  Wrappable* opaque_root = impl->GetHead();
-  return make_scoped_refptr<Wrappable>(opaque_root);
-}
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCGarbageCollectionTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCGarbageCollectionTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGarbageCollectionTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGarbageCollectionTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCGarbageCollectionTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGarbageCollectionTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCGarbageCollectionTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGarbageCollectionTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGarbageCollectionTestInterface::InterfaceObject::s_info = {
-    "GarbageCollectionTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGarbageCollectionTestInterface::InterfaceObject)
-};  // JSCGarbageCollectionTestInterface::InterfaceObject::s_info
-
-void JSCGarbageCollectionTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCGarbageCollectionTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCGarbageCollectionTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSGarbageCollectionTestInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "GarbageCollectionTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCGarbageCollectionTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCGarbageCollectionTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGarbageCollectionTestInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCGarbageCollectionTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGarbageCollectionTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCGarbageCollectionTestInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGarbageCollectionTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGarbageCollectionTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGarbageCollectionTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGarbageCollectionTestInterface::Prototype::s_info = {
-    "GarbageCollectionTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGarbageCollectionTestInterface::Prototype)
-};  // JSCGarbageCollectionTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCGarbageCollectionTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCGarbageCollectionTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCGarbageCollectionTestInterface::Prototype class
-
-const JSC::HashTableValue JSCGarbageCollectionTestInterface::property_table_values[] = {
-    { "previous",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSprevious),
-        reinterpret_cast<intptr_t>(setJSprevious),
-        JSC::NoIntrinsic
-    },
-    { "next",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnext),
-        reinterpret_cast<intptr_t>(setJSnext),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGarbageCollectionTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCGarbageCollectionTestInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGarbageCollectionTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGarbageCollectionTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGarbageCollectionTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCGarbageCollectionTestInterface::NonTrivialStaticFields>
-    JSCGarbageCollectionTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCGarbageCollectionTestInterface::s_info = {
-    "GarbageCollectionTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGarbageCollectionTestInterface)
-};  // JSCGarbageCollectionTestInterface::s_info
-
-// static
-JSC::JSObject* JSCGarbageCollectionTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCGarbageCollectionTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCGarbageCollectionTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCGarbageCollectionTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType()";
-    return NULL;
-  }
-  GarbageCollectionTestInterface* impl_ptr =
-      base::polymorphic_downcast<GarbageCollectionTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCGarbageCollectionTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCGarbageCollectionTestInterface>(global_data.heap))
-      JSCGarbageCollectionTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCGarbageCollectionTestInterface::JSCGarbageCollectionTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<GarbageCollectionTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-  set_get_opaque_root_function(base::Bind(&GetOpaqueRootFromWrappable));
-}
-
-void JSCGarbageCollectionTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCGarbageCollectionTestInterface::~JSCGarbageCollectionTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCGarbageCollectionTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCGarbageCollectionTestInterface* this_object = JSC::jsCast<JSCGarbageCollectionTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCGarbageCollectionTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCGarbageCollectionTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCGarbageCollectionTestInterface* this_object = JSC::jsCast<JSCGarbageCollectionTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCGarbageCollectionTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCGarbageCollectionTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCGarbageCollectionTestInterface* this_object = JSC::jsCast<JSCGarbageCollectionTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCGarbageCollectionTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSprevious(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCGarbageCollectionTestInterface", "get previous");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  GarbageCollectionTestInterface* impl =
-      GetWrappableOrSetException<GarbageCollectionTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->previous());
-  return result;
-}
-
-void setJSprevious(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCGarbageCollectionTestInterface", "set previous");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  GarbageCollectionTestInterface* impl =
-      GetWrappableOrSetException<GarbageCollectionTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<scoped_refptr<GarbageCollectionTestInterface> >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_previous(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnext(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCGarbageCollectionTestInterface", "get next");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  GarbageCollectionTestInterface* impl =
-      GetWrappableOrSetException<GarbageCollectionTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->next());
-  return result;
-}
-
-void setJSnext(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCGarbageCollectionTestInterface", "set next");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  GarbageCollectionTestInterface* impl =
-      GetWrappableOrSetException<GarbageCollectionTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<scoped_refptr<GarbageCollectionTestInterface> >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_next(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue constructorJSGarbageCollectionTestInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<GarbageCollectionTestInterface> new_object =
-        new GarbageCollectionTestInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.h
deleted file mode 100644
index 58ef5c2..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGarbageCollectionTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCGarbageCollectionTestInterface_h
-#define JSCGarbageCollectionTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCGarbageCollectionTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to GarbageCollectionTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCGarbageCollectionTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<GarbageCollectionTestInterface>& impl);
-  ~JSCGarbageCollectionTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCGarbageCollectionTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.cc
deleted file mode 100644
index 25312f8..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.cc
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCGetOpaqueRootInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::GetOpaqueRootInterface;
-using cobalt::bindings::testing::JSCGetOpaqueRootInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue constructorJSGetOpaqueRootInterface(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-scoped_refptr<Wrappable> GetOpaqueRootFromWrappable(
-    const scoped_refptr<Wrappable>& wrappable) {
-  GetOpaqueRootInterface* impl =
-      base::polymorphic_downcast<GetOpaqueRootInterface*>(wrappable.get());
-  Wrappable* opaque_root = impl->get_opaque_root_function_name();
-  return make_scoped_refptr<Wrappable>(opaque_root);
-}
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCGetOpaqueRootInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCGetOpaqueRootInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGetOpaqueRootInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGetOpaqueRootInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCGetOpaqueRootInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGetOpaqueRootInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCGetOpaqueRootInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGetOpaqueRootInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGetOpaqueRootInterface::InterfaceObject::s_info = {
-    "GetOpaqueRootInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGetOpaqueRootInterface::InterfaceObject)
-};  // JSCGetOpaqueRootInterface::InterfaceObject::s_info
-
-void JSCGetOpaqueRootInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCGetOpaqueRootInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCGetOpaqueRootInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSGetOpaqueRootInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "GetOpaqueRootInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCGetOpaqueRootInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCGetOpaqueRootInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGetOpaqueRootInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCGetOpaqueRootInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGetOpaqueRootInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCGetOpaqueRootInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGetOpaqueRootInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGetOpaqueRootInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGetOpaqueRootInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGetOpaqueRootInterface::Prototype::s_info = {
-    "GetOpaqueRootInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGetOpaqueRootInterface::Prototype)
-};  // JSCGetOpaqueRootInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCGetOpaqueRootInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCGetOpaqueRootInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCGetOpaqueRootInterface::Prototype class
-
-const JSC::HashTableValue JSCGetOpaqueRootInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGetOpaqueRootInterface::property_table_values
-
-// static
-const JSC::HashTable JSCGetOpaqueRootInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGetOpaqueRootInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGetOpaqueRootInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGetOpaqueRootInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCGetOpaqueRootInterface::NonTrivialStaticFields>
-    JSCGetOpaqueRootInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCGetOpaqueRootInterface::s_info = {
-    "GetOpaqueRootInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGetOpaqueRootInterface)
-};  // JSCGetOpaqueRootInterface::s_info
-
-// static
-JSC::JSObject* JSCGetOpaqueRootInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCGetOpaqueRootInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCGetOpaqueRootInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCGetOpaqueRootInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == GetOpaqueRootInterface::GetOpaqueRootInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match GetOpaqueRootInterface::GetOpaqueRootInterfaceWrappableType()";
-    return NULL;
-  }
-  GetOpaqueRootInterface* impl_ptr =
-      base::polymorphic_downcast<GetOpaqueRootInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCGetOpaqueRootInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCGetOpaqueRootInterface>(global_data.heap))
-      JSCGetOpaqueRootInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCGetOpaqueRootInterface::JSCGetOpaqueRootInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<GetOpaqueRootInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-  set_get_opaque_root_function(base::Bind(&GetOpaqueRootFromWrappable));
-}
-
-void JSCGetOpaqueRootInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCGetOpaqueRootInterface::~JSCGetOpaqueRootInterface() {
-  // Empty destructor
-}
-
-void JSCGetOpaqueRootInterface::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor) {
-  WrapperBase<JSC::JSDestructibleObject, Wrappable>::visitChildren(
-      cell, visitor);
-
-  JSCGlobalObject* global_object = JSC::jsCast<JSCGlobalObject*>(
-      JSC::jsCast<JSObject*>(cell)->globalObject());
-
-  GetOpaqueRootInterface* impl = base::polymorphic_downcast<GetOpaqueRootInterface*>(
-      JSC::jsCast<WrapperBase*>(cell)->wrappable().get());
-
-  Wrappable* opaque_root0 = impl->add_opaque_root_function_name();
-  if (opaque_root0) {
-    visitor.addOpaqueRoot(opaque_root0);
-  }
-}
-
-// Look up property slot for querying property values.
-bool JSCGetOpaqueRootInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCGetOpaqueRootInterface* this_object = JSC::jsCast<JSCGetOpaqueRootInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCGetOpaqueRootInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCGetOpaqueRootInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCGetOpaqueRootInterface* this_object = JSC::jsCast<JSCGetOpaqueRootInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCGetOpaqueRootInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCGetOpaqueRootInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCGetOpaqueRootInterface* this_object = JSC::jsCast<JSCGetOpaqueRootInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCGetOpaqueRootInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue constructorJSGetOpaqueRootInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<GetOpaqueRootInterface> new_object =
-        new GetOpaqueRootInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.h
deleted file mode 100644
index 4e88b6c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGetOpaqueRootInterface.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCGetOpaqueRootInterface_h
-#define JSCGetOpaqueRootInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/get_opaque_root_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCGetOpaqueRootInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to GetOpaqueRootInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCGetOpaqueRootInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<GetOpaqueRootInterface>& impl);
-  ~JSCGetOpaqueRootInterface();
-
-  static void visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor);
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCGetOpaqueRootInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.cc
deleted file mode 100644
index fe08052..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.cc
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCGlobalInterfaceParent.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::GlobalInterfaceParent;
-using cobalt::bindings::testing::JSCGlobalInterfaceParent;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJSparentOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCGlobalInterfaceParent::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCGlobalInterfaceParent";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGlobalInterfaceParent::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGlobalInterfaceParent::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCGlobalInterfaceParent::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGlobalInterfaceParent::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCGlobalInterfaceParent::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGlobalInterfaceParent::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGlobalInterfaceParent::InterfaceObject::s_info = {
-    "GlobalInterfaceParentConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGlobalInterfaceParent::InterfaceObject)
-};  // JSCGlobalInterfaceParent::InterfaceObject::s_info
-
-void JSCGlobalInterfaceParent::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCGlobalInterfaceParent::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCGlobalInterfaceParent::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "GlobalInterfaceParent");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCGlobalInterfaceParent::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCGlobalInterfaceParent::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCGlobalInterfaceParent::Prototype::property_table_values[] = {
-    { "parentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSparentOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCGlobalInterfaceParent::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGlobalInterfaceParent::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCGlobalInterfaceParent::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGlobalInterfaceParent::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGlobalInterfaceParent::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGlobalInterfaceParent::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCGlobalInterfaceParent::Prototype::s_info = {
-    "GlobalInterfaceParentPrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGlobalInterfaceParent::Prototype)
-};  // JSCGlobalInterfaceParent::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCGlobalInterfaceParent::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCGlobalInterfaceParent::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCGlobalInterfaceParent::Prototype class
-
-const JSC::HashTableValue JSCGlobalInterfaceParent::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCGlobalInterfaceParent::property_table_values
-
-// static
-const JSC::HashTable JSCGlobalInterfaceParent::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCGlobalInterfaceParent::property_table_prototype
-
-// static
-const JSC::HashTable* JSCGlobalInterfaceParent::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCGlobalInterfaceParent::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCGlobalInterfaceParent::NonTrivialStaticFields>
-    JSCGlobalInterfaceParent::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCGlobalInterfaceParent::s_info = {
-    "GlobalInterfaceParent",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCGlobalInterfaceParent)
-};  // JSCGlobalInterfaceParent::s_info
-
-// static
-JSC::JSObject* JSCGlobalInterfaceParent::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCGlobalInterfaceParent::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCGlobalInterfaceParent::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCGlobalInterfaceParent::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == GlobalInterfaceParent::GlobalInterfaceParentWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match GlobalInterfaceParent::GlobalInterfaceParentWrappableType()";
-    return NULL;
-  }
-  GlobalInterfaceParent* impl_ptr =
-      base::polymorphic_downcast<GlobalInterfaceParent*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCGlobalInterfaceParent* wrapper =
-      new (NotNull, JSC::allocateCell<JSCGlobalInterfaceParent>(global_data.heap))
-      JSCGlobalInterfaceParent(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCGlobalInterfaceParent::JSCGlobalInterfaceParent(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<GlobalInterfaceParent>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCGlobalInterfaceParent::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCGlobalInterfaceParent::~JSCGlobalInterfaceParent() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCGlobalInterfaceParent::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCGlobalInterfaceParent* this_object = JSC::jsCast<JSCGlobalInterfaceParent*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCGlobalInterfaceParent, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCGlobalInterfaceParent::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCGlobalInterfaceParent* this_object = JSC::jsCast<JSCGlobalInterfaceParent*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCGlobalInterfaceParent, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCGlobalInterfaceParent::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCGlobalInterfaceParent* this_object = JSC::jsCast<JSCGlobalInterfaceParent*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCGlobalInterfaceParent, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJSparentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCGlobalInterfaceParent", "call parentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  GlobalInterfaceParent* impl =
-      GetWrappableOrSetException<GlobalInterfaceParent>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->ParentOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.h b/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.h
deleted file mode 100644
index ebbbfa9..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCGlobalInterfaceParent.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCGlobalInterfaceParent_h
-#define JSCGlobalInterfaceParent_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/global_interface_parent.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCGlobalInterfaceParent
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to GlobalInterfaceParent.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCGlobalInterfaceParent(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<GlobalInterfaceParent>& impl);
-  ~JSCGlobalInterfaceParent();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCGlobalInterfaceParent_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
deleted file mode 100644
index 1049b03..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCIndexedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::IndexedGetterInterface;
-using cobalt::bindings::testing::JSCIndexedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::EncodedJSValue functionJSindexedDeleter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSindexedGetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSindexedSetter(JSC::ExecState*);
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCIndexedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCIndexedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCIndexedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCIndexedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCIndexedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCIndexedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCIndexedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCIndexedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCIndexedGetterInterface::InterfaceObject::s_info = {
-    "IndexedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCIndexedGetterInterface::InterfaceObject)
-};  // JSCIndexedGetterInterface::InterfaceObject::s_info
-
-void JSCIndexedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCIndexedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCIndexedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "IndexedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCIndexedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCIndexedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCIndexedGetterInterface::Prototype::property_table_values[] = {
-    { "indexedDeleter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSindexedDeleter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "indexedGetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSindexedGetter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "indexedSetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSindexedSetter),
-        static_cast<intptr_t>(2),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCIndexedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCIndexedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCIndexedGetterInterface::Prototype::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCIndexedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCIndexedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCIndexedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCIndexedGetterInterface::Prototype::s_info = {
-    "IndexedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCIndexedGetterInterface::Prototype)
-};  // JSCIndexedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCIndexedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCIndexedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCIndexedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCIndexedGetterInterface::property_table_values[] = {
-    { "length",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlength),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCIndexedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCIndexedGetterInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCIndexedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCIndexedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCIndexedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCIndexedGetterInterface::NonTrivialStaticFields>
-    JSCIndexedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCIndexedGetterInterface::s_info = {
-    "IndexedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCIndexedGetterInterface)
-};  // JSCIndexedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCIndexedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCIndexedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCIndexedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCIndexedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == IndexedGetterInterface::IndexedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match IndexedGetterInterface::IndexedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  IndexedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<IndexedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCIndexedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCIndexedGetterInterface>(global_data.heap))
-      JSCIndexedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCIndexedGetterInterface::JSCIndexedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<IndexedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCIndexedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCIndexedGetterInterface::~JSCIndexedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCIndexedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCIndexedGetterInterface* this_object = JSC::jsCast<JSCIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCIndexedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCIndexedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-  if (s_has_named_getter) {
-    JSCIndexedGetterInterface* this_object = JSC::jsCast<JSCIndexedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCIndexedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, object);
-  if (impl) {
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCIndexedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCIndexedGetterInterface* this_object = JSC::jsCast<JSCIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCIndexedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCIndexedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCIndexedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "deletePropertyByIndex");
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-  }
-  return false;
-}
-
-bool JSCIndexedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCIndexedGetterInterface* this_object = JSC::jsCast<JSCIndexedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCIndexedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "get length");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->length());
-  return result;
-}
-
-JSC::EncodedJSValue functionJSindexedDeleter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedDeleter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->IndexedDeleter(index);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSindexedGetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedGetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  TypeTraits<uint32_t >::ReturnType return_value = impl->IndexedGetter(index);
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSindexedSetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedSetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-  TypeTraits<uint32_t >::ConversionType value;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->IndexedSetter(index, value);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "IndexedPropertyGetter");
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->IndexedGetter(index));
-  return result;
-}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCIndexedGetterInterface", "IndexedPropertySetter");
-  IndexedGetterInterface* impl =
-      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  uint32_t value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->IndexedSetter(index, value);
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.h
deleted file mode 100644
index 563e4b9..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCIndexedGetterInterface_h
-#define JSCIndexedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/indexed_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCIndexedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to IndexedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCIndexedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<IndexedGetterInterface>& impl);
-  ~JSCIndexedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.cc
deleted file mode 100644
index 987a767..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.cc
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCInterfaceWithUnsupportedProperties.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::InterfaceWithUnsupportedProperties;
-using cobalt::bindings::testing::JSCInterfaceWithUnsupportedProperties;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSsupportedAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCInterfaceWithUnsupportedProperties::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCInterfaceWithUnsupportedProperties";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCInterfaceWithUnsupportedProperties::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCInterfaceWithUnsupportedProperties::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCInterfaceWithUnsupportedProperties::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCInterfaceWithUnsupportedProperties::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCInterfaceWithUnsupportedProperties::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCInterfaceWithUnsupportedProperties::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCInterfaceWithUnsupportedProperties::InterfaceObject::s_info = {
-    "InterfaceWithUnsupportedPropertiesConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCInterfaceWithUnsupportedProperties::InterfaceObject)
-};  // JSCInterfaceWithUnsupportedProperties::InterfaceObject::s_info
-
-void JSCInterfaceWithUnsupportedProperties::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCInterfaceWithUnsupportedProperties::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCInterfaceWithUnsupportedProperties::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "InterfaceWithUnsupportedProperties");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCInterfaceWithUnsupportedProperties::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCInterfaceWithUnsupportedProperties::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCInterfaceWithUnsupportedProperties::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCInterfaceWithUnsupportedProperties::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCInterfaceWithUnsupportedProperties::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCInterfaceWithUnsupportedProperties::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCInterfaceWithUnsupportedProperties::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCInterfaceWithUnsupportedProperties::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCInterfaceWithUnsupportedProperties::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCInterfaceWithUnsupportedProperties::Prototype::s_info = {
-    "InterfaceWithUnsupportedPropertiesPrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCInterfaceWithUnsupportedProperties::Prototype)
-};  // JSCInterfaceWithUnsupportedProperties::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCInterfaceWithUnsupportedProperties::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCInterfaceWithUnsupportedProperties::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCInterfaceWithUnsupportedProperties::Prototype class
-
-const JSC::HashTableValue JSCInterfaceWithUnsupportedProperties::property_table_values[] = {
-    { "supportedAttribute",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSsupportedAttribute),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCInterfaceWithUnsupportedProperties::property_table_values
-
-// static
-const JSC::HashTable JSCInterfaceWithUnsupportedProperties::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCInterfaceWithUnsupportedProperties::property_table_prototype
-
-// static
-const JSC::HashTable* JSCInterfaceWithUnsupportedProperties::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCInterfaceWithUnsupportedProperties::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCInterfaceWithUnsupportedProperties::NonTrivialStaticFields>
-    JSCInterfaceWithUnsupportedProperties::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCInterfaceWithUnsupportedProperties::s_info = {
-    "InterfaceWithUnsupportedProperties",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCInterfaceWithUnsupportedProperties)
-};  // JSCInterfaceWithUnsupportedProperties::s_info
-
-// static
-JSC::JSObject* JSCInterfaceWithUnsupportedProperties::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCInterfaceWithUnsupportedProperties::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCInterfaceWithUnsupportedProperties::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCInterfaceWithUnsupportedProperties::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType()";
-    return NULL;
-  }
-  InterfaceWithUnsupportedProperties* impl_ptr =
-      base::polymorphic_downcast<InterfaceWithUnsupportedProperties*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCInterfaceWithUnsupportedProperties* wrapper =
-      new (NotNull, JSC::allocateCell<JSCInterfaceWithUnsupportedProperties>(global_data.heap))
-      JSCInterfaceWithUnsupportedProperties(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCInterfaceWithUnsupportedProperties::JSCInterfaceWithUnsupportedProperties(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<InterfaceWithUnsupportedProperties>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCInterfaceWithUnsupportedProperties::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCInterfaceWithUnsupportedProperties::~JSCInterfaceWithUnsupportedProperties() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCInterfaceWithUnsupportedProperties::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCInterfaceWithUnsupportedProperties* this_object = JSC::jsCast<JSCInterfaceWithUnsupportedProperties*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCInterfaceWithUnsupportedProperties, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCInterfaceWithUnsupportedProperties::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCInterfaceWithUnsupportedProperties* this_object = JSC::jsCast<JSCInterfaceWithUnsupportedProperties*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCInterfaceWithUnsupportedProperties, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCInterfaceWithUnsupportedProperties::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCInterfaceWithUnsupportedProperties* this_object = JSC::jsCast<JSCInterfaceWithUnsupportedProperties*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCInterfaceWithUnsupportedProperties, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSsupportedAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCInterfaceWithUnsupportedProperties", "get supportedAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  InterfaceWithUnsupportedProperties* impl =
-      GetWrappableOrSetException<InterfaceWithUnsupportedProperties>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->supported_attribute());
-  return result;
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.h b/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.h
deleted file mode 100644
index 5d55bde..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCInterfaceWithUnsupportedProperties.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCInterfaceWithUnsupportedProperties_h
-#define JSCInterfaceWithUnsupportedProperties_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/interface_with_unsupported_properties.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCInterfaceWithUnsupportedProperties
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to InterfaceWithUnsupportedProperties.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCInterfaceWithUnsupportedProperties(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<InterfaceWithUnsupportedProperties>& impl);
-  ~JSCInterfaceWithUnsupportedProperties();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCInterfaceWithUnsupportedProperties_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.cc
deleted file mode 100644
index 1825c9e..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.cc
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNamedConstructorInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NamedConstructorInterface;
-using cobalt::bindings::testing::JSCNamedConstructorInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue constructorJSNamedConstructorInterface(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNamedConstructorInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNamedConstructorInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedConstructorInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedConstructorInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNamedConstructorInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedConstructorInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNamedConstructorInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedConstructorInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedConstructorInterface::InterfaceObject::s_info = {
-    "NamedConstructorInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedConstructorInterface::InterfaceObject)
-};  // JSCNamedConstructorInterface::InterfaceObject::s_info
-
-void JSCNamedConstructorInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNamedConstructorInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSNamedConstructorInterface);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NamedConstructorInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNamedConstructorInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNamedConstructorInterface::NamedInterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    NamedInterfaceObject* this_object = JSC::jsCast<NamedInterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    NamedInterfaceObject* this_object = JSC::jsCast<NamedInterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<NamedInterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNamedConstructorInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  NamedInterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedConstructorInterface::NamedInterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedConstructorInterface::NamedInterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNamedConstructorInterface::NamedInterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedConstructorInterface::NamedInterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNamedConstructorInterface::NamedInterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedConstructorInterface::NamedInterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedConstructorInterface::NamedInterfaceObject::s_info = {
-    "NamedConstructorInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedConstructorInterface::NamedInterfaceObject)
-};  // JSCNamedConstructorInterface::NamedInterfaceObject::s_info
-
-void JSCNamedConstructorInterface::NamedInterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNamedConstructorInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::NamedInterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSNamedConstructorInterface);
-
-    // Create the new interface object.
-    NamedInterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<NamedInterfaceObject>(global_data.heap))
-        NamedInterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "SomeNamedConstructor");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNamedConstructorInterface::NamedInterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNamedConstructorInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedConstructorInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNamedConstructorInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedConstructorInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNamedConstructorInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedConstructorInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedConstructorInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedConstructorInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedConstructorInterface::Prototype::s_info = {
-    "NamedConstructorInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedConstructorInterface::Prototype)
-};  // JSCNamedConstructorInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNamedConstructorInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNamedConstructorInterface::Prototype class
-
-const JSC::HashTableValue JSCNamedConstructorInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedConstructorInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNamedConstructorInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedConstructorInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedConstructorInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedConstructorInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNamedConstructorInterface::NonTrivialStaticFields>
-    JSCNamedConstructorInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNamedConstructorInterface::s_info = {
-    "NamedConstructorInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedConstructorInterface)
-};  // JSCNamedConstructorInterface::s_info
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNamedConstructorInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-JSC::JSObject* JSCNamedConstructorInterface::GetNamedConstructor(
-    JSC::ExecState* exec_state) {
-  return NamedInterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSObject* JSCNamedConstructorInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NamedConstructorInterface::NamedConstructorInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NamedConstructorInterface::NamedConstructorInterfaceWrappableType()";
-    return NULL;
-  }
-  NamedConstructorInterface* impl_ptr =
-      base::polymorphic_downcast<NamedConstructorInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNamedConstructorInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNamedConstructorInterface>(global_data.heap))
-      JSCNamedConstructorInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNamedConstructorInterface::JSCNamedConstructorInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NamedConstructorInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNamedConstructorInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNamedConstructorInterface::~JSCNamedConstructorInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNamedConstructorInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNamedConstructorInterface* this_object = JSC::jsCast<JSCNamedConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNamedConstructorInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNamedConstructorInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNamedConstructorInterface* this_object = JSC::jsCast<JSCNamedConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNamedConstructorInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNamedConstructorInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNamedConstructorInterface* this_object = JSC::jsCast<JSCNamedConstructorInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNamedConstructorInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue constructorJSNamedConstructorInterface(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<NamedConstructorInterface> new_object =
-        new NamedConstructorInterface();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.h
deleted file mode 100644
index b0af676..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedConstructorInterface.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNamedConstructorInterface_h
-#define JSCNamedConstructorInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/named_constructor_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNamedConstructorInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // Get the named constructor for this wrapper class.
-  static JSC::JSObject* GetNamedConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NamedConstructorInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNamedConstructorInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NamedConstructorInterface>& impl);
-  ~JSCNamedConstructorInterface();
-
- private:
-  class InterfaceObject;
-  class NamedInterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNamedConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.cc
deleted file mode 100644
index 27a6fa1..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.cc
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNamedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NamedGetterInterface;
-using cobalt::bindings::testing::JSCNamedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJSnamedDeleter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnamedGetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnamedSetter(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = true;
-const bool s_has_named_setter = true;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNamedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNamedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNamedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNamedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedGetterInterface::InterfaceObject::s_info = {
-    "NamedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedGetterInterface::InterfaceObject)
-};  // JSCNamedGetterInterface::InterfaceObject::s_info
-
-void JSCNamedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNamedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNamedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NamedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNamedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNamedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedGetterInterface::Prototype::property_table_values[] = {
-    { "namedDeleter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnamedDeleter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "namedGetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnamedGetter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "namedSetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnamedSetter),
-        static_cast<intptr_t>(2),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNamedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNamedGetterInterface::Prototype::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedGetterInterface::Prototype::s_info = {
-    "NamedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedGetterInterface::Prototype)
-};  // JSCNamedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNamedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNamedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNamedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCNamedGetterInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNamedGetterInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNamedGetterInterface::NonTrivialStaticFields>
-    JSCNamedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNamedGetterInterface::s_info = {
-    "NamedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedGetterInterface)
-};  // JSCNamedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCNamedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNamedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNamedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNamedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NamedGetterInterface::NamedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NamedGetterInterface::NamedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  NamedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<NamedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNamedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNamedGetterInterface>(global_data.heap))
-      JSCNamedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNamedGetterInterface::JSCNamedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NamedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNamedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNamedGetterInterface::~JSCNamedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNamedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNamedGetterInterface* this_object = JSC::jsCast<JSCNamedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNamedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCNamedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (s_has_named_getter) {
-    JSCNamedGetterInterface* this_object = JSC::jsCast<JSCNamedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCNamedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, object);
-  if (impl) {
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCNamedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNamedGetterInterface* this_object = JSC::jsCast<JSCNamedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNamedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCNamedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCNamedGetterInterface::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("JSCNamedGetterInterface", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-
-bool JSCNamedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "deletePropertyByIndex");
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deletePropertyByIndex(cell, exec_state, index);
-  }
-  return false;
-}
-
-bool JSCNamedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNamedGetterInterface* this_object = JSC::jsCast<JSCNamedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNamedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJSnamedDeleter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "call namedDeleter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType name;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &name);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NamedDeleter(name);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnamedGetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "call namedGetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType name;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &name);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  TypeTraits<std::string >::ReturnType return_value = impl->NamedGetter(name);
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSnamedSetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "call namedSetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType name;
-  TypeTraits<std::string >::ConversionType value;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &name);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NamedSetter(name, value);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "NamedPropertyGetter");
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->NamedGetter(property_name_utf8));
-  return result;
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCNamedGetterInterface", "NamedPropertySetter");
-  NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  std::string value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->NamedSetter(property_name_utf8, value);
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-    NamedGetterInterface* impl =
-      GetWrappableOrSetException<NamedGetterInterface>(exec_state, cell);
-  if (impl) {
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-    impl->NamedDeleter(property_name_utf8);
-    return true;
-  }
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.h
deleted file mode 100644
index cf9ad8d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedGetterInterface.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNamedGetterInterface_h
-#define JSCNamedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/named_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNamedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NamedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNamedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NamedGetterInterface>& impl);
-  ~JSCNamedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNamedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.cc
deleted file mode 100644
index ed0cf6e..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.cc
+++ /dev/null
@@ -1,1193 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNamedIndexedGetterInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NamedIndexedGetterInterface;
-using cobalt::bindings::testing::JSCNamedIndexedGetterInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSpropertyOnBaseClass(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSpropertyOnBaseClass(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSindexedGetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSindexedSetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnamedGetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnamedSetter(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoperationOnBaseClass(JSC::ExecState*);
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = true;
-const bool s_has_named_setter = true;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNamedIndexedGetterInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNamedIndexedGetterInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedIndexedGetterInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedIndexedGetterInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNamedIndexedGetterInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedIndexedGetterInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNamedIndexedGetterInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedIndexedGetterInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedIndexedGetterInterface::InterfaceObject::s_info = {
-    "NamedIndexedGetterInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedIndexedGetterInterface::InterfaceObject)
-};  // JSCNamedIndexedGetterInterface::InterfaceObject::s_info
-
-void JSCNamedIndexedGetterInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNamedIndexedGetterInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNamedIndexedGetterInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NamedIndexedGetterInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNamedIndexedGetterInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNamedIndexedGetterInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNamedIndexedGetterInterface::Prototype::property_table_values[] = {
-    { "indexedGetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSindexedGetter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "indexedSetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSindexedSetter),
-        static_cast<intptr_t>(2),
-        JSC::NoIntrinsic
-    },
-    { "namedGetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnamedGetter),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "namedSetter",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnamedSetter),
-        static_cast<intptr_t>(2),
-        JSC::NoIntrinsic
-    },
-    { "operationOnBaseClass",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoperationOnBaseClass),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNamedIndexedGetterInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedIndexedGetterInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNamedIndexedGetterInterface::Prototype::property_table_prototype = {
-    21,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedIndexedGetterInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedIndexedGetterInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedIndexedGetterInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNamedIndexedGetterInterface::Prototype::s_info = {
-    "NamedIndexedGetterInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedIndexedGetterInterface::Prototype)
-};  // JSCNamedIndexedGetterInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNamedIndexedGetterInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNamedIndexedGetterInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNamedIndexedGetterInterface::Prototype class
-
-const JSC::HashTableValue JSCNamedIndexedGetterInterface::property_table_values[] = {
-    { "length",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSlength),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "propertyOnBaseClass",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSpropertyOnBaseClass),
-        reinterpret_cast<intptr_t>(setJSpropertyOnBaseClass),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNamedIndexedGetterInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNamedIndexedGetterInterface::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNamedIndexedGetterInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNamedIndexedGetterInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNamedIndexedGetterInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNamedIndexedGetterInterface::NonTrivialStaticFields>
-    JSCNamedIndexedGetterInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNamedIndexedGetterInterface::s_info = {
-    "NamedIndexedGetterInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNamedIndexedGetterInterface)
-};  // JSCNamedIndexedGetterInterface::s_info
-
-// static
-JSC::JSObject* JSCNamedIndexedGetterInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNamedIndexedGetterInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNamedIndexedGetterInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNamedIndexedGetterInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType()";
-    return NULL;
-  }
-  NamedIndexedGetterInterface* impl_ptr =
-      base::polymorphic_downcast<NamedIndexedGetterInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNamedIndexedGetterInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNamedIndexedGetterInterface>(global_data.heap))
-      JSCNamedIndexedGetterInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNamedIndexedGetterInterface::JSCNamedIndexedGetterInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NamedIndexedGetterInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNamedIndexedGetterInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNamedIndexedGetterInterface::~JSCNamedIndexedGetterInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNamedIndexedGetterInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCNamedIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNamedIndexedGetterInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// static
-bool JSCNamedIndexedGetterInterface::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-  if (s_has_named_getter) {
-    JSCNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCNamedIndexedGetterInterface*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void JSCNamedIndexedGetterInterface::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, object);
-  if (impl) {
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-
-// Look up property slot and put the |value|.
-void JSCNamedIndexedGetterInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCNamedIndexedGetterInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNamedIndexedGetterInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-// static
-void JSCNamedIndexedGetterInterface::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-
-bool JSCNamedIndexedGetterInterface::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("JSCNamedIndexedGetterInterface", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-
-bool JSCNamedIndexedGetterInterface::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "deletePropertyByIndex");
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (impl) {
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-  }
-  return false;
-}
-
-bool JSCNamedIndexedGetterInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNamedIndexedGetterInterface* this_object = JSC::jsCast<JSCNamedIndexedGetterInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNamedIndexedGetterInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSlength(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "get length");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->length());
-  return result;
-}
-
-JSC::JSValue getJSpropertyOnBaseClass(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "get propertyOnBaseClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->property_on_base_class());
-  return result;
-}
-
-void setJSpropertyOnBaseClass(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "set propertyOnBaseClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<bool >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_property_on_base_class(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSindexedGetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "call indexedGetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  TypeTraits<uint32_t >::ReturnType return_value = impl->IndexedGetter(index);
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSindexedSetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "call indexedSetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType index;
-  TypeTraits<uint32_t >::ConversionType value;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &index);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->IndexedSetter(index, value);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnamedGetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "call namedGetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType name;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &name);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  TypeTraits<std::string >::ReturnType return_value = impl->NamedGetter(name);
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSnamedSetter(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "call namedSetter");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType name;
-  TypeTraits<std::string >::ConversionType value;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &name);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NamedSetter(name, value);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoperationOnBaseClass(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "call operationOnBaseClass");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->OperationOnBaseClass();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "IndexedPropertyGetter");
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->IndexedGetter(index));
-  return result;
-}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "IndexedPropertySetter");
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  uint32_t value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->IndexedSetter(index, value);
-}
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "NamedPropertyGetter");
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->NamedGetter(property_name_utf8));
-  return result;
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("JSCNamedIndexedGetterInterface", "NamedPropertySetter");
-  NamedIndexedGetterInterface* impl =
-      GetWrappableOrSetException<NamedIndexedGetterInterface>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  std::string value;
-  FromJSValue(exec_state, jsc_value,
-      kNoConversionFlags,
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  impl->NamedSetter(property_name_utf8, value);
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.h
deleted file mode 100644
index c84aab4..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNamedIndexedGetterInterface.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNamedIndexedGetterInterface_h
-#define JSCNamedIndexedGetterInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/named_indexed_getter_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNamedIndexedGetterInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NamedIndexedGetterInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNamedIndexedGetterInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NamedIndexedGetterInterface>& impl);
-  ~JSCNamedIndexedGetterInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNamedIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.cc
deleted file mode 100644
index 889d4d7..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.cc
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNestedPutForwardsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCPutForwardsInterface.h"
-#include "cobalt/bindings/testing/put_forwards_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NestedPutForwardsInterface;
-using cobalt::bindings::testing::JSCNestedPutForwardsInterface;
-using cobalt::bindings::testing::JSCPutForwardsInterface;
-using cobalt::bindings::testing::PutForwardsInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSnestedForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnestedForwardingAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNestedPutForwardsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNestedPutForwardsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNestedPutForwardsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNestedPutForwardsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNestedPutForwardsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNestedPutForwardsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNestedPutForwardsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNestedPutForwardsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNestedPutForwardsInterface::InterfaceObject::s_info = {
-    "NestedPutForwardsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNestedPutForwardsInterface::InterfaceObject)
-};  // JSCNestedPutForwardsInterface::InterfaceObject::s_info
-
-void JSCNestedPutForwardsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNestedPutForwardsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNestedPutForwardsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NestedPutForwardsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNestedPutForwardsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNestedPutForwardsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNestedPutForwardsInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNestedPutForwardsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNestedPutForwardsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNestedPutForwardsInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNestedPutForwardsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNestedPutForwardsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNestedPutForwardsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNestedPutForwardsInterface::Prototype::s_info = {
-    "NestedPutForwardsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNestedPutForwardsInterface::Prototype)
-};  // JSCNestedPutForwardsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNestedPutForwardsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNestedPutForwardsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNestedPutForwardsInterface::Prototype class
-
-const JSC::HashTableValue JSCNestedPutForwardsInterface::property_table_values[] = {
-    { "nestedForwardingAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnestedForwardingAttribute),
-        reinterpret_cast<intptr_t>(setJSnestedForwardingAttribute),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNestedPutForwardsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNestedPutForwardsInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNestedPutForwardsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNestedPutForwardsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNestedPutForwardsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNestedPutForwardsInterface::NonTrivialStaticFields>
-    JSCNestedPutForwardsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNestedPutForwardsInterface::s_info = {
-    "NestedPutForwardsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNestedPutForwardsInterface)
-};  // JSCNestedPutForwardsInterface::s_info
-
-// static
-JSC::JSObject* JSCNestedPutForwardsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNestedPutForwardsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNestedPutForwardsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNestedPutForwardsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType()";
-    return NULL;
-  }
-  NestedPutForwardsInterface* impl_ptr =
-      base::polymorphic_downcast<NestedPutForwardsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNestedPutForwardsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNestedPutForwardsInterface>(global_data.heap))
-      JSCNestedPutForwardsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNestedPutForwardsInterface::JSCNestedPutForwardsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NestedPutForwardsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNestedPutForwardsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNestedPutForwardsInterface::~JSCNestedPutForwardsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNestedPutForwardsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNestedPutForwardsInterface* this_object = JSC::jsCast<JSCNestedPutForwardsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNestedPutForwardsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNestedPutForwardsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNestedPutForwardsInterface* this_object = JSC::jsCast<JSCNestedPutForwardsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNestedPutForwardsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNestedPutForwardsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNestedPutForwardsInterface* this_object = JSC::jsCast<JSCNestedPutForwardsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNestedPutForwardsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSnestedForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNestedPutForwardsInterface", "get nestedForwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NestedPutForwardsInterface* impl =
-      GetWrappableOrSetException<NestedPutForwardsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nested_forwarding_attribute());
-  return result;
-}
-
-void setJSnestedForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNestedPutForwardsInterface", "set nestedForwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NestedPutForwardsInterface* impl =
-      GetWrappableOrSetException<NestedPutForwardsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  {
-    scoped_refptr<PutForwardsInterface> forwarded_impl =
-        impl->nested_forwarding_attribute();
-    if (!forwarded_impl) {
-      return;
-    }
-  {
-    scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl =
-        forwarded_impl->forwarding_attribute();
-    if (!forwarded_forwarded_impl) {
-      return;
-    }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    forwarded_forwarded_impl->set_arbitrary_property(cobalt_value);
-  }
-  }
-
-  }
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.h
deleted file mode 100644
index 2a35ff4..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNestedPutForwardsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNestedPutForwardsInterface_h
-#define JSCNestedPutForwardsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/nested_put_forwards_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNestedPutForwardsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NestedPutForwardsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNestedPutForwardsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NestedPutForwardsInterface>& impl);
-  ~JSCNestedPutForwardsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNestedPutForwardsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.cc
deleted file mode 100644
index 2d96b5d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.cc
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNoConstructorInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NoConstructorInterface;
-using cobalt::bindings::testing::JSCNoConstructorInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNoConstructorInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNoConstructorInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNoConstructorInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNoConstructorInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNoConstructorInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNoConstructorInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNoConstructorInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNoConstructorInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNoConstructorInterface::InterfaceObject::s_info = {
-    "NoConstructorInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNoConstructorInterface::InterfaceObject)
-};  // JSCNoConstructorInterface::InterfaceObject::s_info
-
-void JSCNoConstructorInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNoConstructorInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNoConstructorInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NoConstructorInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNoConstructorInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNoConstructorInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNoConstructorInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNoConstructorInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNoConstructorInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNoConstructorInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNoConstructorInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNoConstructorInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNoConstructorInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNoConstructorInterface::Prototype::s_info = {
-    "NoConstructorInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNoConstructorInterface::Prototype)
-};  // JSCNoConstructorInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNoConstructorInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNoConstructorInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNoConstructorInterface::Prototype class
-
-const JSC::HashTableValue JSCNoConstructorInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNoConstructorInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNoConstructorInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNoConstructorInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNoConstructorInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNoConstructorInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNoConstructorInterface::NonTrivialStaticFields>
-    JSCNoConstructorInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNoConstructorInterface::s_info = {
-    "NoConstructorInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNoConstructorInterface)
-};  // JSCNoConstructorInterface::s_info
-
-// static
-JSC::JSObject* JSCNoConstructorInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNoConstructorInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNoConstructorInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNoConstructorInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NoConstructorInterface::NoConstructorInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NoConstructorInterface::NoConstructorInterfaceWrappableType()";
-    return NULL;
-  }
-  NoConstructorInterface* impl_ptr =
-      base::polymorphic_downcast<NoConstructorInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNoConstructorInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNoConstructorInterface>(global_data.heap))
-      JSCNoConstructorInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNoConstructorInterface::JSCNoConstructorInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NoConstructorInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNoConstructorInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNoConstructorInterface::~JSCNoConstructorInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNoConstructorInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNoConstructorInterface* this_object = JSC::jsCast<JSCNoConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNoConstructorInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNoConstructorInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNoConstructorInterface* this_object = JSC::jsCast<JSCNoConstructorInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNoConstructorInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNoConstructorInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNoConstructorInterface* this_object = JSC::jsCast<JSCNoConstructorInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNoConstructorInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.h
deleted file mode 100644
index 8c31ac4..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNoConstructorInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNoConstructorInterface_h
-#define JSCNoConstructorInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/no_constructor_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNoConstructorInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NoConstructorInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNoConstructorInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NoConstructorInterface>& impl);
-  ~JSCNoConstructorInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNoConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.cc
deleted file mode 100644
index dec1a8c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.cc
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNoInterfaceObjectInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NoInterfaceObjectInterface;
-using cobalt::bindings::testing::JSCNoInterfaceObjectInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNoInterfaceObjectInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNoInterfaceObjectInterface::Prototype::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNoInterfaceObjectInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNoInterfaceObjectInterface::Prototype::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNoInterfaceObjectInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNoInterfaceObjectInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNoInterfaceObjectInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNoInterfaceObjectInterface::Prototype::s_info = {
-    "NoInterfaceObjectInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNoInterfaceObjectInterface::Prototype)
-};  // JSCNoInterfaceObjectInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNoInterfaceObjectInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNoInterfaceObjectInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNoInterfaceObjectInterface::Prototype class
-
-const JSC::HashTableValue JSCNoInterfaceObjectInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNoInterfaceObjectInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNoInterfaceObjectInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNoInterfaceObjectInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNoInterfaceObjectInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNoInterfaceObjectInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNoInterfaceObjectInterface::NonTrivialStaticFields>
-    JSCNoInterfaceObjectInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNoInterfaceObjectInterface::s_info = {
-    "NoInterfaceObjectInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNoInterfaceObjectInterface)
-};  // JSCNoInterfaceObjectInterface::s_info
-
-// static
-JSC::JSObject* JSCNoInterfaceObjectInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-
-// static
-JSC::JSObject* JSCNoInterfaceObjectInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType()";
-    return NULL;
-  }
-  NoInterfaceObjectInterface* impl_ptr =
-      base::polymorphic_downcast<NoInterfaceObjectInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNoInterfaceObjectInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNoInterfaceObjectInterface>(global_data.heap))
-      JSCNoInterfaceObjectInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNoInterfaceObjectInterface::JSCNoInterfaceObjectInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NoInterfaceObjectInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNoInterfaceObjectInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNoInterfaceObjectInterface::~JSCNoInterfaceObjectInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNoInterfaceObjectInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNoInterfaceObjectInterface* this_object = JSC::jsCast<JSCNoInterfaceObjectInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNoInterfaceObjectInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNoInterfaceObjectInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNoInterfaceObjectInterface* this_object = JSC::jsCast<JSCNoInterfaceObjectInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNoInterfaceObjectInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNoInterfaceObjectInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNoInterfaceObjectInterface* this_object = JSC::jsCast<JSCNoInterfaceObjectInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNoInterfaceObjectInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.h
deleted file mode 100644
index bbc4f66..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNoInterfaceObjectInterface.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNoInterfaceObjectInterface_h
-#define JSCNoInterfaceObjectInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/no_interface_object_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNoInterfaceObjectInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NoInterfaceObjectInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNoInterfaceObjectInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NoInterfaceObjectInterface>& impl);
-  ~JSCNoInterfaceObjectInterface();
-
- private:
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNoInterfaceObjectInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.cc
deleted file mode 100644
index 6acb572..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.cc
+++ /dev/null
@@ -1,1215 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNullableTypesTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NullableTypesTestInterface;
-using cobalt::bindings::testing::JSCNullableTypesTestInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSnullableBooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableBooleanProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableNumericProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableNumericProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableStringProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableStringProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableObjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableObjectProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSnullableBooleanArgument(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableBooleanOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableNumericArgument(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableNumericOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableObjectArgument(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableObjectOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableStringArgument(JSC::ExecState*);
-JSC::EncodedJSValue functionJSnullableStringOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNullableTypesTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNullableTypesTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNullableTypesTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNullableTypesTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNullableTypesTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNullableTypesTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNullableTypesTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNullableTypesTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNullableTypesTestInterface::InterfaceObject::s_info = {
-    "NullableTypesTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNullableTypesTestInterface::InterfaceObject)
-};  // JSCNullableTypesTestInterface::InterfaceObject::s_info
-
-void JSCNullableTypesTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNullableTypesTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNullableTypesTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NullableTypesTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNullableTypesTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNullableTypesTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNullableTypesTestInterface::Prototype::property_table_values[] = {
-    { "nullableBooleanArgument",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableBooleanArgument),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "nullableBooleanOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableBooleanOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "nullableNumericArgument",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableNumericArgument),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "nullableNumericOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableNumericOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "nullableObjectArgument",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableObjectArgument),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "nullableObjectOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableObjectOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "nullableStringArgument",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableStringArgument),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "nullableStringOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSnullableStringOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNullableTypesTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNullableTypesTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNullableTypesTestInterface::Prototype::property_table_prototype = {
-    40,  // compactSize
-    31,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNullableTypesTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNullableTypesTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNullableTypesTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNullableTypesTestInterface::Prototype::s_info = {
-    "NullableTypesTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNullableTypesTestInterface::Prototype)
-};  // JSCNullableTypesTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNullableTypesTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNullableTypesTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNullableTypesTestInterface::Prototype class
-
-const JSC::HashTableValue JSCNullableTypesTestInterface::property_table_values[] = {
-    { "nullableBooleanProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableBooleanProperty),
-        reinterpret_cast<intptr_t>(setJSnullableBooleanProperty),
-        JSC::NoIntrinsic
-    },
-    { "nullableNumericProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableNumericProperty),
-        reinterpret_cast<intptr_t>(setJSnullableNumericProperty),
-        JSC::NoIntrinsic
-    },
-    { "nullableStringProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableStringProperty),
-        reinterpret_cast<intptr_t>(setJSnullableStringProperty),
-        JSC::NoIntrinsic
-    },
-    { "nullableObjectProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableObjectProperty),
-        reinterpret_cast<intptr_t>(setJSnullableObjectProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNullableTypesTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNullableTypesTestInterface::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNullableTypesTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNullableTypesTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNullableTypesTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNullableTypesTestInterface::NonTrivialStaticFields>
-    JSCNullableTypesTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNullableTypesTestInterface::s_info = {
-    "NullableTypesTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNullableTypesTestInterface)
-};  // JSCNullableTypesTestInterface::s_info
-
-// static
-JSC::JSObject* JSCNullableTypesTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNullableTypesTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNullableTypesTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNullableTypesTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType()";
-    return NULL;
-  }
-  NullableTypesTestInterface* impl_ptr =
-      base::polymorphic_downcast<NullableTypesTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNullableTypesTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNullableTypesTestInterface>(global_data.heap))
-      JSCNullableTypesTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNullableTypesTestInterface::JSCNullableTypesTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NullableTypesTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNullableTypesTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNullableTypesTestInterface::~JSCNullableTypesTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNullableTypesTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNullableTypesTestInterface* this_object = JSC::jsCast<JSCNullableTypesTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNullableTypesTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNullableTypesTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNullableTypesTestInterface* this_object = JSC::jsCast<JSCNullableTypesTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNullableTypesTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNullableTypesTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNullableTypesTestInterface* this_object = JSC::jsCast<JSCNullableTypesTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNullableTypesTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSnullableBooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "get nullableBooleanProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_boolean_property());
-  return result;
-}
-
-void setJSnullableBooleanProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "set nullableBooleanProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<bool > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_boolean_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableNumericProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "get nullableNumericProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_numeric_property());
-  return result;
-}
-
-void setJSnullableNumericProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "set nullableNumericProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<int32_t > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_numeric_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableStringProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "get nullableStringProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_string_property());
-  return result;
-}
-
-void setJSnullableStringProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "set nullableStringProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<std::string > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_string_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableObjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "get nullableObjectProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_object_property());
-  return result;
-}
-
-void setJSnullableObjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "set nullableObjectProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_object_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSnullableBooleanArgument(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableBooleanArgument");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<base::optional<bool > >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagNullable),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NullableBooleanArgument(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnullableBooleanOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableBooleanOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<base::optional<bool > >::ReturnType return_value = impl->NullableBooleanOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSnullableNumericArgument(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableNumericArgument");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<base::optional<int32_t > >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagNullable),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NullableNumericArgument(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnullableNumericOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableNumericOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<base::optional<int32_t > >::ReturnType return_value = impl->NullableNumericOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSnullableObjectArgument(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableObjectArgument");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagNullable),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NullableObjectArgument(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnullableObjectOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableObjectOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType return_value = impl->NullableObjectOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSnullableStringArgument(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableStringArgument");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<base::optional<std::string > >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagNullable),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->NullableStringArgument(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSnullableStringOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNullableTypesTestInterface", "call nullableStringOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NullableTypesTestInterface* impl =
-      GetWrappableOrSetException<NullableTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<base::optional<std::string > >::ReturnType return_value = impl->NullableStringOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.h
deleted file mode 100644
index 78bc0ed..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNullableTypesTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNullableTypesTestInterface_h
-#define JSCNullableTypesTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/nullable_types_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNullableTypesTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NullableTypesTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNullableTypesTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NullableTypesTestInterface>& impl);
-  ~JSCNullableTypesTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNullableTypesTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
deleted file mode 100644
index 6db7067..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
+++ /dev/null
@@ -1,1973 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCNumericTypesTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::NumericTypesTestInterface;
-using cobalt::bindings::testing::JSCNumericTypesTestInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSbyteProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSbyteProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSoctetProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSoctetProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSshortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSshortProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunsignedShortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunsignedShortProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSlongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSlongProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunsignedLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunsignedLongProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSlongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSlongLongProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunsignedLongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunsignedLongLongProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSdoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSdoubleProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunrestrictedDoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunrestrictedDoubleProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue functionJSbyteArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSbyteReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSdoubleArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSdoubleReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSlongArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSlongLongArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSlongLongReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSlongReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoctetArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoctetReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSshortArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSshortReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunrestrictedDoubleArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunrestrictedDoubleReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedLongArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedLongReturnOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedShortArgumentOperation(JSC::ExecState*);
-JSC::EncodedJSValue functionJSunsignedShortReturnOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCNumericTypesTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCNumericTypesTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNumericTypesTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNumericTypesTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCNumericTypesTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNumericTypesTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCNumericTypesTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNumericTypesTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNumericTypesTestInterface::InterfaceObject::s_info = {
-    "NumericTypesTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNumericTypesTestInterface::InterfaceObject)
-};  // JSCNumericTypesTestInterface::InterfaceObject::s_info
-
-void JSCNumericTypesTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCNumericTypesTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCNumericTypesTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "NumericTypesTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCNumericTypesTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCNumericTypesTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCNumericTypesTestInterface::Prototype::property_table_values[] = {
-    { "byteArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSbyteArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "byteReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSbyteReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "doubleArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSdoubleArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "doubleReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSdoubleReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "longArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSlongArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "longLongArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSlongLongArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "longLongReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSlongLongReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "longReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSlongReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "octetArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoctetArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "octetReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoctetReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "shortArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSshortArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "shortReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSshortReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "unrestrictedDoubleArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunrestrictedDoubleArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "unrestrictedDoubleReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunrestrictedDoubleReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedLongArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongLongArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedLongLongArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongLongReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedLongLongReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedLongReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "unsignedShortArgumentOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedShortArgumentOperation),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "unsignedShortReturnOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSunsignedShortReturnOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCNumericTypesTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNumericTypesTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCNumericTypesTestInterface::Prototype::property_table_prototype = {
-    84,  // compactSize
-    63,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNumericTypesTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNumericTypesTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNumericTypesTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCNumericTypesTestInterface::Prototype::s_info = {
-    "NumericTypesTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNumericTypesTestInterface::Prototype)
-};  // JSCNumericTypesTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCNumericTypesTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCNumericTypesTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCNumericTypesTestInterface::Prototype class
-
-const JSC::HashTableValue JSCNumericTypesTestInterface::property_table_values[] = {
-    { "byteProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSbyteProperty),
-        reinterpret_cast<intptr_t>(setJSbyteProperty),
-        JSC::NoIntrinsic
-    },
-    { "octetProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSoctetProperty),
-        reinterpret_cast<intptr_t>(setJSoctetProperty),
-        JSC::NoIntrinsic
-    },
-    { "shortProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSshortProperty),
-        reinterpret_cast<intptr_t>(setJSshortProperty),
-        JSC::NoIntrinsic
-    },
-    { "unsignedShortProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunsignedShortProperty),
-        reinterpret_cast<intptr_t>(setJSunsignedShortProperty),
-        JSC::NoIntrinsic
-    },
-    { "longProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSlongProperty),
-        reinterpret_cast<intptr_t>(setJSlongProperty),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunsignedLongProperty),
-        reinterpret_cast<intptr_t>(setJSunsignedLongProperty),
-        JSC::NoIntrinsic
-    },
-    { "longLongProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSlongLongProperty),
-        reinterpret_cast<intptr_t>(setJSlongLongProperty),
-        JSC::NoIntrinsic
-    },
-    { "unsignedLongLongProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunsignedLongLongProperty),
-        reinterpret_cast<intptr_t>(setJSunsignedLongLongProperty),
-        JSC::NoIntrinsic
-    },
-    { "doubleProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSdoubleProperty),
-        reinterpret_cast<intptr_t>(setJSdoubleProperty),
-        JSC::NoIntrinsic
-    },
-    { "unrestrictedDoubleProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunrestrictedDoubleProperty),
-        reinterpret_cast<intptr_t>(setJSunrestrictedDoubleProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCNumericTypesTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCNumericTypesTestInterface::property_table_prototype = {
-    41,  // compactSize
-    31,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCNumericTypesTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCNumericTypesTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCNumericTypesTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCNumericTypesTestInterface::NonTrivialStaticFields>
-    JSCNumericTypesTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCNumericTypesTestInterface::s_info = {
-    "NumericTypesTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCNumericTypesTestInterface)
-};  // JSCNumericTypesTestInterface::s_info
-
-// static
-JSC::JSObject* JSCNumericTypesTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCNumericTypesTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCNumericTypesTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCNumericTypesTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType()";
-    return NULL;
-  }
-  NumericTypesTestInterface* impl_ptr =
-      base::polymorphic_downcast<NumericTypesTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCNumericTypesTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCNumericTypesTestInterface>(global_data.heap))
-      JSCNumericTypesTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCNumericTypesTestInterface::JSCNumericTypesTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<NumericTypesTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCNumericTypesTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCNumericTypesTestInterface::~JSCNumericTypesTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCNumericTypesTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCNumericTypesTestInterface* this_object = JSC::jsCast<JSCNumericTypesTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCNumericTypesTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCNumericTypesTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCNumericTypesTestInterface* this_object = JSC::jsCast<JSCNumericTypesTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCNumericTypesTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCNumericTypesTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCNumericTypesTestInterface* this_object = JSC::jsCast<JSCNumericTypesTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCNumericTypesTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSbyteProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get byteProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->byte_property());
-  return result;
-}
-
-void setJSbyteProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set byteProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int8_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_byte_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSoctetProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get octetProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->octet_property());
-  return result;
-}
-
-void setJSoctetProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set octetProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<uint8_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_octet_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSshortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get shortProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->short_property());
-  return result;
-}
-
-void setJSshortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set shortProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int16_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_short_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunsignedShortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get unsignedShortProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->unsigned_short_property());
-  return result;
-}
-
-void setJSunsignedShortProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set unsignedShortProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<uint16_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_unsigned_short_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSlongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get longProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->long_property());
-  return result;
-}
-
-void setJSlongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set longProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int32_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_long_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunsignedLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get unsignedLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->unsigned_long_property());
-  return result;
-}
-
-void setJSunsignedLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set unsignedLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<uint32_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_unsigned_long_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSlongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get longLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->long_long_property());
-  return result;
-}
-
-void setJSlongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set longLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<int64_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_long_long_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunsignedLongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get unsignedLongLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->unsigned_long_long_property());
-  return result;
-}
-
-void setJSunsignedLongLongProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set unsignedLongLongProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<uint64_t >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_unsigned_long_long_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSdoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get doubleProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->double_property());
-  return result;
-}
-
-void setJSdoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set doubleProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<double >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagRestricted), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_double_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunrestrictedDoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "get unrestrictedDoubleProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->unrestricted_double_property());
-  return result;
-}
-
-void setJSunrestrictedDoubleProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "set unrestrictedDoubleProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<double >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_unrestricted_double_property(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue functionJSbyteArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call byteArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int8_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->ByteArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSbyteReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call byteReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<int8_t >::ReturnType return_value = impl->ByteReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSdoubleArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call doubleArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<double >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagRestricted),
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->DoubleArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSdoubleReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call doubleReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<double >::ReturnType return_value = impl->DoubleReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSlongArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->LongArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSlongLongArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int64_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->LongLongArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSlongLongReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<int64_t >::ReturnType return_value = impl->LongLongReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSlongReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<int32_t >::ReturnType return_value = impl->LongReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSoctetArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call octetArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint8_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OctetArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoctetReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call octetReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<uint8_t >::ReturnType return_value = impl->OctetReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSshortArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call shortArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int16_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->ShortArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSshortReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call shortReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<int16_t >::ReturnType return_value = impl->ShortReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSunrestrictedDoubleArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unrestrictedDoubleArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<double >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->UnrestrictedDoubleArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSunrestrictedDoubleReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unrestrictedDoubleReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<double >::ReturnType return_value = impl->UnrestrictedDoubleReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSunsignedLongArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint32_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->UnsignedLongArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint64_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->UnsignedLongLongArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<uint64_t >::ReturnType return_value = impl->UnsignedLongLongReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSunsignedLongReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<uint32_t >::ReturnType return_value = impl->UnsignedLongReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSunsignedShortArgumentOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedShortArgumentOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<uint16_t >::ConversionType arg1;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->UnsignedShortArgumentOperation(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSunsignedShortReturnOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedShortReturnOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  NumericTypesTestInterface* impl =
-      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<uint16_t >::ReturnType return_value = impl->UnsignedShortReturnOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.h
deleted file mode 100644
index 38b8244..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCNumericTypesTestInterface_h
-#define JSCNumericTypesTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/numeric_types_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCNumericTypesTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to NumericTypesTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCNumericTypesTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<NumericTypesTestInterface>& impl);
-  ~JSCNumericTypesTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCNumericTypesTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.cc
deleted file mode 100644
index 6ce03c8..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.cc
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCObjectTypeBindingsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "JSCBaseInterface.h"
-#include "JSCDerivedInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-#include "cobalt/bindings/testing/base_interface.h"
-#include "cobalt/bindings/testing/derived_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::ObjectTypeBindingsInterface;
-using cobalt::bindings::testing::JSCObjectTypeBindingsInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::BaseInterface;
-using cobalt::bindings::testing::DerivedInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::bindings::testing::JSCBaseInterface;
-using cobalt::bindings::testing::JSCDerivedInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSarbitraryObject(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSarbitraryObject(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSbaseInterface(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::JSValue getJSderivedInterface(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSderivedInterface(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSobjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSobjectProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCObjectTypeBindingsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCObjectTypeBindingsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCObjectTypeBindingsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCObjectTypeBindingsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCObjectTypeBindingsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCObjectTypeBindingsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCObjectTypeBindingsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCObjectTypeBindingsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCObjectTypeBindingsInterface::InterfaceObject::s_info = {
-    "ObjectTypeBindingsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCObjectTypeBindingsInterface::InterfaceObject)
-};  // JSCObjectTypeBindingsInterface::InterfaceObject::s_info
-
-void JSCObjectTypeBindingsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCObjectTypeBindingsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCObjectTypeBindingsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "ObjectTypeBindingsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCObjectTypeBindingsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCObjectTypeBindingsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCObjectTypeBindingsInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCObjectTypeBindingsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCObjectTypeBindingsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCObjectTypeBindingsInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCObjectTypeBindingsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCObjectTypeBindingsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCObjectTypeBindingsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCObjectTypeBindingsInterface::Prototype::s_info = {
-    "ObjectTypeBindingsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCObjectTypeBindingsInterface::Prototype)
-};  // JSCObjectTypeBindingsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCObjectTypeBindingsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCObjectTypeBindingsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCObjectTypeBindingsInterface::Prototype class
-
-const JSC::HashTableValue JSCObjectTypeBindingsInterface::property_table_values[] = {
-    { "arbitraryObject",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSarbitraryObject),
-        reinterpret_cast<intptr_t>(setJSarbitraryObject),
-        JSC::NoIntrinsic
-    },
-    { "baseInterface",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSbaseInterface),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "derivedInterface",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSderivedInterface),
-        reinterpret_cast<intptr_t>(setJSderivedInterface),
-        JSC::NoIntrinsic
-    },
-    { "objectProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSobjectProperty),
-        reinterpret_cast<intptr_t>(setJSobjectProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCObjectTypeBindingsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCObjectTypeBindingsInterface::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCObjectTypeBindingsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCObjectTypeBindingsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCObjectTypeBindingsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCObjectTypeBindingsInterface::NonTrivialStaticFields>
-    JSCObjectTypeBindingsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCObjectTypeBindingsInterface::s_info = {
-    "ObjectTypeBindingsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCObjectTypeBindingsInterface)
-};  // JSCObjectTypeBindingsInterface::s_info
-
-// static
-JSC::JSObject* JSCObjectTypeBindingsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCObjectTypeBindingsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCObjectTypeBindingsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCObjectTypeBindingsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType()";
-    return NULL;
-  }
-  ObjectTypeBindingsInterface* impl_ptr =
-      base::polymorphic_downcast<ObjectTypeBindingsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCObjectTypeBindingsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCObjectTypeBindingsInterface>(global_data.heap))
-      JSCObjectTypeBindingsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCObjectTypeBindingsInterface::JSCObjectTypeBindingsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<ObjectTypeBindingsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCObjectTypeBindingsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCObjectTypeBindingsInterface::~JSCObjectTypeBindingsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCObjectTypeBindingsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCObjectTypeBindingsInterface* this_object = JSC::jsCast<JSCObjectTypeBindingsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCObjectTypeBindingsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCObjectTypeBindingsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCObjectTypeBindingsInterface* this_object = JSC::jsCast<JSCObjectTypeBindingsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCObjectTypeBindingsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCObjectTypeBindingsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCObjectTypeBindingsInterface* this_object = JSC::jsCast<JSCObjectTypeBindingsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCObjectTypeBindingsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSarbitraryObject(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "get arbitraryObject");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->arbitrary_object());
-  return result;
-}
-
-void setJSarbitraryObject(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "set arbitraryObject");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_arbitrary_object(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSbaseInterface(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "get baseInterface");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->base_interface());
-  return result;
-}
-
-JSC::JSValue getJSderivedInterface(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "get derivedInterface");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->derived_interface());
-  return result;
-}
-
-void setJSderivedInterface(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "set derivedInterface");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<scoped_refptr<DerivedInterface> >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_derived_interface(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSobjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "get objectProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->object_property());
-  return result;
-}
-
-void setJSobjectProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCObjectTypeBindingsInterface", "set objectProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  ObjectTypeBindingsInterface* impl =
-      GetWrappableOrSetException<ObjectTypeBindingsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<OpaqueHandle >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_object_property(cobalt_value);
-  }
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.h
deleted file mode 100644
index 54dea0d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCObjectTypeBindingsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCObjectTypeBindingsInterface_h
-#define JSCObjectTypeBindingsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/object_type_bindings_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCObjectTypeBindingsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to ObjectTypeBindingsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCObjectTypeBindingsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<ObjectTypeBindingsInterface>& impl);
-  ~JSCObjectTypeBindingsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCObjectTypeBindingsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
deleted file mode 100644
index 816ea6c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCOperationsTestInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::OperationsTestInterface;
-using cobalt::bindings::testing::JSCOperationsTestInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJSlongFunctionNoArgs(JSC::ExecState*);
-JSC::EncodedJSValue functionJSobjectFunctionNoArgs(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoptionalArgumentWithDefault(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoptionalArguments(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoptionalNullableArgumentsWithDefaults(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction1(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction2(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction3(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction4(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedFunction5(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedNullable(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedNullable1(JSC::ExecState*);
-JSC::EncodedJSValue functionJSoverloadedNullable2(JSC::ExecState*);
-JSC::EncodedJSValue functionJSstringFunctionNoArgs(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvariadicPrimitiveArguments(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvariadicStringArgumentsAfterOptionalArgument(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvoidFunctionLongArg(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvoidFunctionNoArgs(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvoidFunctionObjectArg(JSC::ExecState*);
-JSC::EncodedJSValue functionJSvoidFunctionStringArg(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction1(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction2(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCOperationsTestInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCOperationsTestInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCOperationsTestInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { "overloadedFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(staticFunctionJSoverloadedFunction),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCOperationsTestInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCOperationsTestInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCOperationsTestInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCOperationsTestInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCOperationsTestInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCOperationsTestInterface::InterfaceObject::s_info = {
-    "OperationsTestInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCOperationsTestInterface::InterfaceObject)
-};  // JSCOperationsTestInterface::InterfaceObject::s_info
-
-void JSCOperationsTestInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCOperationsTestInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCOperationsTestInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "OperationsTestInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCOperationsTestInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCOperationsTestInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCOperationsTestInterface::Prototype::property_table_values[] = {
-    { "longFunctionNoArgs",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSlongFunctionNoArgs),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "objectFunctionNoArgs",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSobjectFunctionNoArgs),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "optionalArgumentWithDefault",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoptionalArgumentWithDefault),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "optionalArguments",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoptionalArguments),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "optionalNullableArgumentsWithDefaults",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoptionalNullableArgumentsWithDefaults),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "overloadedFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoverloadedFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "overloadedNullable",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSoverloadedNullable),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "stringFunctionNoArgs",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSstringFunctionNoArgs),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "variadicPrimitiveArguments",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvariadicPrimitiveArguments),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "variadicStringArgumentsAfterOptionalArgument",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvariadicStringArgumentsAfterOptionalArgument),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "voidFunctionLongArg",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvoidFunctionLongArg),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "voidFunctionNoArgs",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvoidFunctionNoArgs),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "voidFunctionObjectArg",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvoidFunctionObjectArg),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "voidFunctionStringArg",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSvoidFunctionStringArg),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCOperationsTestInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCOperationsTestInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCOperationsTestInterface::Prototype::property_table_prototype = {
-    46,  // compactSize
-    31,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCOperationsTestInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCOperationsTestInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCOperationsTestInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCOperationsTestInterface::Prototype::s_info = {
-    "OperationsTestInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCOperationsTestInterface::Prototype)
-};  // JSCOperationsTestInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCOperationsTestInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCOperationsTestInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCOperationsTestInterface::Prototype class
-
-const JSC::HashTableValue JSCOperationsTestInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCOperationsTestInterface::property_table_values
-
-// static
-const JSC::HashTable JSCOperationsTestInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCOperationsTestInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCOperationsTestInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCOperationsTestInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCOperationsTestInterface::NonTrivialStaticFields>
-    JSCOperationsTestInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCOperationsTestInterface::s_info = {
-    "OperationsTestInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCOperationsTestInterface)
-};  // JSCOperationsTestInterface::s_info
-
-// static
-JSC::JSObject* JSCOperationsTestInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCOperationsTestInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCOperationsTestInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCOperationsTestInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == OperationsTestInterface::OperationsTestInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match OperationsTestInterface::OperationsTestInterfaceWrappableType()";
-    return NULL;
-  }
-  OperationsTestInterface* impl_ptr =
-      base::polymorphic_downcast<OperationsTestInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCOperationsTestInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCOperationsTestInterface>(global_data.heap))
-      JSCOperationsTestInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCOperationsTestInterface::JSCOperationsTestInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<OperationsTestInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCOperationsTestInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCOperationsTestInterface::~JSCOperationsTestInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCOperationsTestInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCOperationsTestInterface* this_object = JSC::jsCast<JSCOperationsTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCOperationsTestInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCOperationsTestInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCOperationsTestInterface* this_object = JSC::jsCast<JSCOperationsTestInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCOperationsTestInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCOperationsTestInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCOperationsTestInterface* this_object = JSC::jsCast<JSCOperationsTestInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCOperationsTestInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJSlongFunctionNoArgs(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call longFunctionNoArgs");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<int32_t >::ReturnType return_value = impl->LongFunctionNoArgs();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSobjectFunctionNoArgs(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call objectFunctionNoArgs");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType return_value = impl->ObjectFunctionNoArgs();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSoptionalArgumentWithDefault(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call optionalArgumentWithDefault");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  // Optional arguments with default values
-  TypeTraits<double >::ConversionType arg1 =
-      2.718;
-
-  size_t num_set_arguments = 1;
-  if (exec_state->argumentCount() > 0) {
-    FromJSValue(exec_state,
-        exec_state->argument(0),
-        (kConversionFlagRestricted),
-        &exception_state,
-        &arg1);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-  }
-  impl->OptionalArgumentWithDefault(arg1);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoptionalArguments(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call optionalArguments");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  // Optional arguments
-  TypeTraits<int32_t >::ConversionType arg2;
-  TypeTraits<int32_t >::ConversionType arg3;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  size_t num_set_arguments = 1;
-  if (exec_state->argumentCount() > 1) {
-    FromJSValue(exec_state,
-        exec_state->argument(1),
-        kNoConversionFlags,
-        &exception_state,
-        &arg2);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-    ++num_set_arguments;
-  }
-  if (exec_state->argumentCount() > 2) {
-    FromJSValue(exec_state,
-        exec_state->argument(2),
-        kNoConversionFlags,
-        &exception_state,
-        &arg3);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-    ++num_set_arguments;
-  }
-  switch (num_set_arguments) {
-    case 1:
-      {
-        impl->OptionalArguments(arg1);
-        return JSC::JSValue::encode(JSC::jsUndefined());
-        break;
-      }
-    case 2:
-      {
-        impl->OptionalArguments(arg1, arg2);
-        return JSC::JSValue::encode(JSC::jsUndefined());
-        break;
-      }
-    case 3:
-      {
-        impl->OptionalArguments(arg1, arg2, arg3);
-        return JSC::JSValue::encode(JSC::jsUndefined());
-        break;
-      }
-    default:
-      NOTREACHED();
-      return JSC::JSValue::encode(JSC::jsUndefined());
-  }
-
-}
-
-JSC::EncodedJSValue functionJSoptionalNullableArgumentsWithDefaults(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call optionalNullableArgumentsWithDefaults");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  // Optional arguments with default values
-  TypeTraits<base::optional<bool > >::ConversionType arg1 =
-      base::nullopt;
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg2 =
-      NULL;
-
-  size_t num_set_arguments = 2;
-  if (exec_state->argumentCount() > 0) {
-    FromJSValue(exec_state,
-        exec_state->argument(0),
-        (kConversionFlagNullable),
-        &exception_state,
-        &arg1);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-  }
-  if (exec_state->argumentCount() > 1) {
-    FromJSValue(exec_state,
-        exec_state->argument(1),
-        (kConversionFlagNullable),
-        &exception_state,
-        &arg2);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-  }
-  impl->OptionalNullableArgumentsWithDefaults(arg1, arg2);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call overloadedFunction");
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-    case(0): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return functionJSoverloadedFunction1(exec_state);
-      }
-      break;
-    }
-    case(1): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      JSC::JSValue arg = exec_state->argument(0);
-      if (arg.isNumber()) {
-        return functionJSoverloadedFunction2(exec_state);
-      }
-      if (true) {
-        return functionJSoverloadedFunction3(exec_state);
-      }
-      if (true) {
-        return functionJSoverloadedFunction2(exec_state);
-      }
-      break;
-    }
-    case(3): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      JSC::JSValue arg = exec_state->argument(2);
-      if (arg.inherits(JSCArbitraryInterface::s_classinfo())) {
-        return functionJSoverloadedFunction5(exec_state);
-      }
-      if (true) {
-        return functionJSoverloadedFunction4(exec_state);
-      }
-      break;
-    }
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction1(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->OverloadedFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction2(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedFunction(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction3(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedFunction(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction4(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 3;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  TypeTraits<int32_t >::ConversionType arg2;
-  TypeTraits<int32_t >::ConversionType arg3;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(2, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(2),
-      kNoConversionFlags,
-      &exception_state, &arg3);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedFunction(arg1, arg2, arg3);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedFunction5(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 3;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  TypeTraits<int32_t >::ConversionType arg2;
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(2, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(2),
-      kNoConversionFlags,
-      &exception_state, &arg3);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedFunction(arg1, arg2, arg3);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedNullable(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call overloadedNullable");
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-    case(1): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      JSC::JSValue arg = exec_state->argument(0);
-      if (arg.isUndefinedOrNull()) {
-        return functionJSoverloadedNullable2(exec_state);
-      }
-      if (true) {
-        return functionJSoverloadedNullable1(exec_state);
-      }
-      break;
-    }
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-}
-
-JSC::EncodedJSValue functionJSoverloadedNullable1(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedNullable(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSoverloadedNullable2(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<base::optional<bool > >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagNullable),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->OverloadedNullable(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSstringFunctionNoArgs(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call stringFunctionNoArgs");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<std::string >::ReturnType return_value = impl->StringFunctionNoArgs();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSvariadicPrimitiveArguments(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call variadicPrimitiveArguments");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  // Variadic argument
-  TypeTraits<std::vector<int32_t> >::ConversionType bools;
-
-  // Get variadic arguments.
-  const size_t kFirstVariadicArgIndex = 0;
-  if (exec_state->argumentCount() > kFirstVariadicArgIndex) {
-    bools.resize(exec_state->argumentCount() - kFirstVariadicArgIndex);
-    for (int i = 0; i + kFirstVariadicArgIndex < exec_state->argumentCount(); ++i) {
-      FromJSValue(exec_state,
-          exec_state->argument(i + kFirstVariadicArgIndex),
-          kNoConversionFlags,
-          &exception_state,
-          &bools[i]);
-      if (exception_state.is_exception_set()) {
-        return JSC::throwVMError(exec_state, exception_state.exception_object());
-      }
-    }
-  }
-  impl->VariadicPrimitiveArguments(bools);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSvariadicStringArgumentsAfterOptionalArgument(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call variadicStringArgumentsAfterOptionalArgument");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  // Optional arguments
-  TypeTraits<bool >::ConversionType optional_arg;
-  // Variadic argument
-  TypeTraits<std::vector<std::string> >::ConversionType strings;
-
-  size_t num_set_arguments = 0;
-  if (exec_state->argumentCount() > 0) {
-    FromJSValue(exec_state,
-        exec_state->argument(0),
-        kNoConversionFlags,
-        &exception_state,
-        &optional_arg);
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-    ++num_set_arguments;
-  }
-
-  // Get variadic arguments.
-  const size_t kLastOptionalArgIndex = 1;
-  if (num_set_arguments == kLastOptionalArgIndex) {
-    // If the last optional argument has been set, we will call the overload
-    // that takes the variadic argument, possibly with an empty vector in the
-    // case that there are no more arguments left.
-    ++num_set_arguments;
-  }
-  const size_t kFirstVariadicArgIndex = 1;
-  if (exec_state->argumentCount() > kFirstVariadicArgIndex) {
-    strings.resize(exec_state->argumentCount() - kFirstVariadicArgIndex);
-    for (int i = 0; i + kFirstVariadicArgIndex < exec_state->argumentCount(); ++i) {
-      FromJSValue(exec_state,
-          exec_state->argument(i + kFirstVariadicArgIndex),
-          kNoConversionFlags,
-          &exception_state,
-          &strings[i]);
-      if (exception_state.is_exception_set()) {
-        return JSC::throwVMError(exec_state, exception_state.exception_object());
-      }
-    }
-  }
-  switch (num_set_arguments) {
-    case 0:
-      {
-        impl->VariadicStringArgumentsAfterOptionalArgument();
-        return JSC::JSValue::encode(JSC::jsUndefined());
-        break;
-      }
-    case 2:
-      {
-        impl->VariadicStringArgumentsAfterOptionalArgument(optional_arg, strings);
-        return JSC::JSValue::encode(JSC::jsUndefined());
-        break;
-      }
-    default:
-      NOTREACHED();
-      return JSC::JSValue::encode(JSC::jsUndefined());
-  }
-
-}
-
-JSC::EncodedJSValue functionJSvoidFunctionLongArg(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call voidFunctionLongArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->VoidFunctionLongArg(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSvoidFunctionNoArgs(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call voidFunctionNoArgs");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->VoidFunctionNoArgs();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSvoidFunctionObjectArg(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call voidFunctionObjectArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->VoidFunctionObjectArg(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSvoidFunctionStringArg(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call voidFunctionStringArg");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  OperationsTestInterface* impl =
-      GetWrappableOrSetException<OperationsTestInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->VoidFunctionStringArg(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCOperationsTestInterface", "call overloadedFunction");
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-    case(1): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return staticFunctionJSoverloadedFunction1(exec_state);
-      }
-      break;
-    }
-    case(2): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return staticFunctionJSoverloadedFunction2(exec_state);
-      }
-      break;
-    }
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-}
-
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction1(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<double >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagRestricted),
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  OperationsTestInterface::OverloadedFunction(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSoverloadedFunction2(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 2;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<double >::ConversionType arg1;
-  TypeTraits<double >::ConversionType arg2;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      (kConversionFlagRestricted),
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      (kConversionFlagRestricted),
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  OperationsTestInterface::OverloadedFunction(arg1, arg2);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.h
deleted file mode 100644
index d1158e9..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCOperationsTestInterface_h
-#define JSCOperationsTestInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/operations_test_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCOperationsTestInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to OperationsTestInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCOperationsTestInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<OperationsTestInterface>& impl);
-  ~JSCOperationsTestInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCOperationsTestInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
deleted file mode 100644
index c51d3be..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCPutForwardsInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::PutForwardsInterface;
-using cobalt::bindings::testing::JSCPutForwardsInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSforwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSforwardingAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSstaticForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSstaticForwardingAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCPutForwardsInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCPutForwardsInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCPutForwardsInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { "staticForwardingAttribute",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSstaticForwardingAttribute),
-        0,
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCPutForwardsInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCPutForwardsInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCPutForwardsInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCPutForwardsInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCPutForwardsInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCPutForwardsInterface::InterfaceObject::s_info = {
-    "PutForwardsInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCPutForwardsInterface::InterfaceObject)
-};  // JSCPutForwardsInterface::InterfaceObject::s_info
-
-void JSCPutForwardsInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCPutForwardsInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCPutForwardsInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "PutForwardsInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCPutForwardsInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCPutForwardsInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCPutForwardsInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCPutForwardsInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCPutForwardsInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCPutForwardsInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCPutForwardsInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCPutForwardsInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCPutForwardsInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCPutForwardsInterface::Prototype::s_info = {
-    "PutForwardsInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCPutForwardsInterface::Prototype)
-};  // JSCPutForwardsInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCPutForwardsInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCPutForwardsInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCPutForwardsInterface::Prototype class
-
-const JSC::HashTableValue JSCPutForwardsInterface::property_table_values[] = {
-    { "forwardingAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSforwardingAttribute),
-        reinterpret_cast<intptr_t>(setJSforwardingAttribute),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCPutForwardsInterface::property_table_values
-
-// static
-const JSC::HashTable JSCPutForwardsInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCPutForwardsInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCPutForwardsInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCPutForwardsInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCPutForwardsInterface::NonTrivialStaticFields>
-    JSCPutForwardsInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCPutForwardsInterface::s_info = {
-    "PutForwardsInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCPutForwardsInterface)
-};  // JSCPutForwardsInterface::s_info
-
-// static
-JSC::JSObject* JSCPutForwardsInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCPutForwardsInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCPutForwardsInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCPutForwardsInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == PutForwardsInterface::PutForwardsInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match PutForwardsInterface::PutForwardsInterfaceWrappableType()";
-    return NULL;
-  }
-  PutForwardsInterface* impl_ptr =
-      base::polymorphic_downcast<PutForwardsInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCPutForwardsInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCPutForwardsInterface>(global_data.heap))
-      JSCPutForwardsInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCPutForwardsInterface::JSCPutForwardsInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<PutForwardsInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCPutForwardsInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCPutForwardsInterface::~JSCPutForwardsInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCPutForwardsInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCPutForwardsInterface* this_object = JSC::jsCast<JSCPutForwardsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCPutForwardsInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCPutForwardsInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCPutForwardsInterface* this_object = JSC::jsCast<JSCPutForwardsInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCPutForwardsInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCPutForwardsInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCPutForwardsInterface* this_object = JSC::jsCast<JSCPutForwardsInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCPutForwardsInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSforwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCPutForwardsInterface", "get forwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  PutForwardsInterface* impl =
-      GetWrappableOrSetException<PutForwardsInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->forwarding_attribute());
-  return result;
-}
-
-void setJSforwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCPutForwardsInterface", "set forwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  PutForwardsInterface* impl =
-      GetWrappableOrSetException<PutForwardsInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  {
-    scoped_refptr<ArbitraryInterface> forwarded_impl =
-        impl->forwarding_attribute();
-    if (!forwarded_impl) {
-      return;
-    }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    forwarded_impl->set_arbitrary_property(cobalt_value);
-  }
-  }
-
-}
-
-JSC::JSValue getJSstaticForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCPutForwardsInterface", "get staticForwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      PutForwardsInterface::static_forwarding_attribute());
-  return result;
-}
-
-void setJSstaticForwardingAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCPutForwardsInterface", "set staticForwardingAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  {
-    scoped_refptr<ArbitraryInterface> forwarded_impl =
-        PutForwardsInterface::static_forwarding_attribute();
-    if (!forwarded_impl) {
-      return;
-    }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    forwarded_impl->set_arbitrary_property(cobalt_value);
-  }
-  }
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.h
deleted file mode 100644
index 2fbc8e1..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCPutForwardsInterface_h
-#define JSCPutForwardsInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/put_forwards_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCPutForwardsInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to PutForwardsInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCPutForwardsInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<PutForwardsInterface>& impl);
-  ~JSCPutForwardsInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCPutForwardsInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.cc b/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.cc
deleted file mode 100644
index 0d06309..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.cc
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCSequenceUser.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::SequenceUser;
-using cobalt::bindings::testing::JSCSequenceUser;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue constructorJSSequenceUser(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetInterfaceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetInterfaceSequenceSequenceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetLongSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetStringSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetStringSequenceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetUnionOfStringAndStringSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSgetUnionSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetInterfaceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetInterfaceSequenceSequenceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetLongSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetStringSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetStringSequenceSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetUnionOfStringAndStringSequence(JSC::ExecState*);
-JSC::EncodedJSValue functionJSsetUnionSequence(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCSequenceUser::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCSequenceUser";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCSequenceUser::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCSequenceUser::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCSequenceUser::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCSequenceUser::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCSequenceUser::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCSequenceUser::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCSequenceUser::InterfaceObject::s_info = {
-    "SequenceUserConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCSequenceUser::InterfaceObject)
-};  // JSCSequenceUser::InterfaceObject::s_info
-
-void JSCSequenceUser::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCSequenceUser::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCSequenceUser::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSSequenceUser);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "SequenceUser");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCSequenceUser::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCSequenceUser::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCSequenceUser::Prototype::property_table_values[] = {
-    { "getInterfaceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetInterfaceSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getInterfaceSequenceSequenceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetInterfaceSequenceSequenceSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getLongSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetLongSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getStringSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetStringSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getStringSequenceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetStringSequenceSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getUnionOfStringAndStringSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetUnionOfStringAndStringSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "getUnionSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetUnionSequence),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "setInterfaceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetInterfaceSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setInterfaceSequenceSequenceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetInterfaceSequenceSequenceSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setLongSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetLongSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setStringSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetStringSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setStringSequenceSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetStringSequenceSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setUnionOfStringAndStringSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetUnionOfStringAndStringSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "setUnionSequence",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSsetUnionSequence),
-        static_cast<intptr_t>(1),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCSequenceUser::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCSequenceUser::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCSequenceUser::Prototype::property_table_prototype = {
-    46,  // compactSize
-    31,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCSequenceUser::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCSequenceUser::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCSequenceUser::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCSequenceUser::Prototype::s_info = {
-    "SequenceUserPrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCSequenceUser::Prototype)
-};  // JSCSequenceUser::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCSequenceUser::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCSequenceUser::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCSequenceUser::Prototype class
-
-const JSC::HashTableValue JSCSequenceUser::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCSequenceUser::property_table_values
-
-// static
-const JSC::HashTable JSCSequenceUser::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCSequenceUser::property_table_prototype
-
-// static
-const JSC::HashTable* JSCSequenceUser::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCSequenceUser::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCSequenceUser::NonTrivialStaticFields>
-    JSCSequenceUser::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCSequenceUser::s_info = {
-    "SequenceUser",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCSequenceUser)
-};  // JSCSequenceUser::s_info
-
-// static
-JSC::JSObject* JSCSequenceUser::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCSequenceUser::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCSequenceUser::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCSequenceUser::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == SequenceUser::SequenceUserWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match SequenceUser::SequenceUserWrappableType()";
-    return NULL;
-  }
-  SequenceUser* impl_ptr =
-      base::polymorphic_downcast<SequenceUser*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCSequenceUser* wrapper =
-      new (NotNull, JSC::allocateCell<JSCSequenceUser>(global_data.heap))
-      JSCSequenceUser(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCSequenceUser::JSCSequenceUser(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<SequenceUser>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCSequenceUser::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCSequenceUser::~JSCSequenceUser() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCSequenceUser::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCSequenceUser* this_object = JSC::jsCast<JSCSequenceUser*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCSequenceUser, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCSequenceUser::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCSequenceUser* this_object = JSC::jsCast<JSCSequenceUser*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCSequenceUser, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCSequenceUser::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCSequenceUser* this_object = JSC::jsCast<JSCSequenceUser*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCSequenceUser, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue constructorJSSequenceUser(JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-    scoped_refptr<SequenceUser> new_object =
-        new SequenceUser();
-    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-
-}
-
-JSC::EncodedJSValue functionJSgetInterfaceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getInterfaceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< scoped_refptr<ArbitraryInterface> > >::ReturnType return_value = impl->GetInterfaceSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetInterfaceSequenceSequenceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getInterfaceSequenceSequenceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< script::Sequence< script::Sequence< scoped_refptr<ArbitraryInterface> > > > >::ReturnType return_value = impl->GetInterfaceSequenceSequenceSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetLongSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getLongSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< int32_t > >::ReturnType return_value = impl->GetLongSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetStringSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getStringSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< std::string > >::ReturnType return_value = impl->GetStringSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetStringSequenceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getStringSequenceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< script::Sequence< std::string > > >::ReturnType return_value = impl->GetStringSequenceSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetUnionOfStringAndStringSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getUnionOfStringAndStringSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::UnionType2<std::string, script::Sequence< std::string > > >::ReturnType return_value = impl->GetUnionOfStringAndStringSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSgetUnionSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call getUnionSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<script::Sequence< script::UnionType2<std::string, scoped_refptr<ArbitraryInterface> > > >::ReturnType return_value = impl->GetUnionSequence();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSsetInterfaceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setInterfaceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< scoped_refptr<ArbitraryInterface> > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetInterfaceSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetInterfaceSequenceSequenceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setInterfaceSequenceSequenceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< script::Sequence< script::Sequence< scoped_refptr<ArbitraryInterface> > > > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetInterfaceSequenceSequenceSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetLongSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setLongSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< int32_t > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetLongSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetStringSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setStringSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< std::string > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetStringSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetStringSequenceSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setStringSequenceSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< script::Sequence< std::string > > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetStringSequenceSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetUnionOfStringAndStringSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setUnionOfStringAndStringSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::UnionType2<std::string, script::Sequence< std::string > > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetUnionOfStringAndStringSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSsetUnionSequence(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCSequenceUser", "call setUnionSequence");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  SequenceUser* impl =
-      GetWrappableOrSetException<SequenceUser>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<script::Sequence< script::UnionType2<std::string, scoped_refptr<ArbitraryInterface> > > >::ConversionType elements;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &elements);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  impl->SetUnionSequence(elements);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.h b/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.h
deleted file mode 100644
index 251cec3..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCSequenceUser.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCSequenceUser_h
-#define JSCSequenceUser_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/sequence_user.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCSequenceUser
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to SequenceUser.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCSequenceUser(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<SequenceUser>& impl);
-  ~JSCSequenceUser();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCSequenceUser_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.cc
deleted file mode 100644
index 60515f6..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/callback-interface.h.template
-
-// clang-format off
-
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCSingleOperationInterface.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-
-namespace {
-using cobalt::bindings::testing::SingleOperationInterface;
-using cobalt::bindings::testing::JSCSingleOperationInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-
-using cobalt::script::javascriptcore::GetCallableForCallbackInterface;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::util::GetExceptionString;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-JSCSingleOperationInterface::JSCSingleOperationInterface(
-    JSC::JSObject* implementing_object)
-    : implementing_object_(implementing_object) { }
-
-base::optional<int32_t > JSCSingleOperationInterface::HandleCallback(
-    const scoped_refptr<script::Wrappable>& callback_this,
-    const scoped_refptr<ArbitraryInterface>& value,
-    bool* had_exception) const {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(implementing_object_->globalObject());
-  JSC::JSGlobalData* global_data = &global_object->globalData();
-  JSC::ExecState* exec_state = global_object->globalExec();
-  JSC::JSLockHolder lock(*global_data);
-
-  // get callable object
-  JSC::JSValue callable;
-  JSC::CallData call_data;
-  JSC::CallType call_type = GetCallableForCallbackInterface(exec_state,
-      implementing_object_, "handleCallback", &callable, &call_data);
-  if (call_type == JSC::CallTypeNone) {
-    // TypeError
-    DLOG(INFO) << "User object was not callable.";
-    *had_exception = true;
-    return base::optional<int32_t >();
-  }
-
-  JSC::JSValue js_this = ToJSValue(global_object, callback_this);
-
-  // Convert args.
-  JSC::MarkedArgumentBuffer args;
-  args.append(ToJSValue(global_object, value));
-
-  // call
-  JSC::DynamicGlobalObjectScope global_object_scope(*global_data, global_object);
-  JSC::JSValue js_return_value =
-      JSC::call(exec_state, callable, call_type, call_data, js_this, args);
-  if (exec_state->hadException()) {
-    DLOG(WARNING) << "Exception in callback: "
-                  << GetExceptionString(exec_state);
-    exec_state->clearException();
-    *had_exception = true;
-    return base::optional<int32_t >();
-  }
-  JSCExceptionState exception_state(global_object);
-  base::optional<int32_t > cobalt_return_value;
-  FromJSValue(exec_state, js_return_value, 0, &exception_state, &cobalt_return_value);
-
-  *had_exception = exception_state.is_exception_set();
-  return cobalt_return_value;
-}
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.h
deleted file mode 100644
index 6b8be4c..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCSingleOperationInterface.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/callback-interface.h.template
-
-// clang-format off
-
-#ifndef JSCSingleOperationInterface_h
-#define JSCSingleOperationInterface_h
-
-#include "cobalt/script/wrappable.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "cobalt/bindings/testing/single_operation_interface.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCSingleOperationInterface : public SingleOperationInterface {
- public:
-  JSCSingleOperationInterface(JSC::JSObject* implementing_object);
-  base::optional<int32_t > HandleCallback(
-      const scoped_refptr<script::Wrappable>& callback_this,
-      const scoped_refptr<ArbitraryInterface>& value,
-      bool* had_exception) const OVERRIDE;
-  JSC::JSObject* implementing_object() const { return implementing_object_; }
-
- private:
-  JSC::JSObject* implementing_object_;
-};
-
-}  // namespace bindings
-}  // namespace testing
-namespace script {
-// Explicit instantiation of CallbackInterfaceTraits struct so we can infer
-// the type of the generated class from the type of the callback interface.
-template<>
-struct CallbackInterfaceTraits<bindings::testing::SingleOperationInterface> {
-  typedef bindings::testing::JSCSingleOperationInterface JSCCallbackInterfaceClass;
-};
-
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // JSCSingleOperationInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
deleted file mode 100644
index d791d04..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCStaticPropertiesInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::StaticPropertiesInterface;
-using cobalt::bindings::testing::JSCStaticPropertiesInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSstaticAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSstaticAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue staticFunctionJSstaticFunction(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSstaticFunction1(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSstaticFunction2(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSstaticFunction3(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSstaticFunction4(JSC::ExecState*);
-JSC::EncodedJSValue staticFunctionJSstaticFunction5(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCStaticPropertiesInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCStaticPropertiesInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStaticPropertiesInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { "staticAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSstaticAttribute),
-        reinterpret_cast<intptr_t>(setJSstaticAttribute),
-        JSC::NoIntrinsic
-    },
-    { "staticFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(staticFunctionJSstaticFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStaticPropertiesInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCStaticPropertiesInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStaticPropertiesInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCStaticPropertiesInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStaticPropertiesInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStaticPropertiesInterface::InterfaceObject::s_info = {
-    "StaticPropertiesInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStaticPropertiesInterface::InterfaceObject)
-};  // JSCStaticPropertiesInterface::InterfaceObject::s_info
-
-void JSCStaticPropertiesInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCStaticPropertiesInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCStaticPropertiesInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "StaticPropertiesInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCStaticPropertiesInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCStaticPropertiesInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStaticPropertiesInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCStaticPropertiesInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStaticPropertiesInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCStaticPropertiesInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStaticPropertiesInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStaticPropertiesInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStaticPropertiesInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStaticPropertiesInterface::Prototype::s_info = {
-    "StaticPropertiesInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStaticPropertiesInterface::Prototype)
-};  // JSCStaticPropertiesInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCStaticPropertiesInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCStaticPropertiesInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCStaticPropertiesInterface::Prototype class
-
-const JSC::HashTableValue JSCStaticPropertiesInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStaticPropertiesInterface::property_table_values
-
-// static
-const JSC::HashTable JSCStaticPropertiesInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStaticPropertiesInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStaticPropertiesInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStaticPropertiesInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCStaticPropertiesInterface::NonTrivialStaticFields>
-    JSCStaticPropertiesInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCStaticPropertiesInterface::s_info = {
-    "StaticPropertiesInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStaticPropertiesInterface)
-};  // JSCStaticPropertiesInterface::s_info
-
-// static
-JSC::JSObject* JSCStaticPropertiesInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCStaticPropertiesInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCStaticPropertiesInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCStaticPropertiesInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType()";
-    return NULL;
-  }
-  StaticPropertiesInterface* impl_ptr =
-      base::polymorphic_downcast<StaticPropertiesInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCStaticPropertiesInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCStaticPropertiesInterface>(global_data.heap))
-      JSCStaticPropertiesInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCStaticPropertiesInterface::JSCStaticPropertiesInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<StaticPropertiesInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCStaticPropertiesInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCStaticPropertiesInterface::~JSCStaticPropertiesInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCStaticPropertiesInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCStaticPropertiesInterface* this_object = JSC::jsCast<JSCStaticPropertiesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCStaticPropertiesInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCStaticPropertiesInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCStaticPropertiesInterface* this_object = JSC::jsCast<JSCStaticPropertiesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCStaticPropertiesInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCStaticPropertiesInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCStaticPropertiesInterface* this_object = JSC::jsCast<JSCStaticPropertiesInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCStaticPropertiesInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSstaticAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCStaticPropertiesInterface", "get staticAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      StaticPropertiesInterface::static_attribute());
-  return result;
-}
-
-void setJSstaticAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCStaticPropertiesInterface", "set staticAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    StaticPropertiesInterface::set_static_attribute(cobalt_value);
-  }
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCStaticPropertiesInterface", "call staticFunction");
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-    case(0): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      if (true) {
-        return staticFunctionJSstaticFunction1(exec_state);
-      }
-      break;
-    }
-    case(1): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      JSC::JSValue arg = exec_state->argument(0);
-      if (arg.isNumber()) {
-        return staticFunctionJSstaticFunction2(exec_state);
-      }
-      if (true) {
-        return staticFunctionJSstaticFunction3(exec_state);
-      }
-      if (true) {
-        return staticFunctionJSstaticFunction2(exec_state);
-      }
-      break;
-    }
-    case(3): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-      JSC::JSValue arg = exec_state->argument(2);
-      if (arg.inherits(JSCArbitraryInterface::s_classinfo())) {
-        return staticFunctionJSstaticFunction5(exec_state);
-      }
-      if (true) {
-        return staticFunctionJSstaticFunction4(exec_state);
-      }
-      break;
-    }
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction1(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  StaticPropertiesInterface::StaticFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction2(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  StaticPropertiesInterface::StaticFunction(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction3(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 1;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<std::string >::ConversionType arg;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  StaticPropertiesInterface::StaticFunction(arg);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction4(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 3;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  TypeTraits<int32_t >::ConversionType arg2;
-  TypeTraits<int32_t >::ConversionType arg3;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(2, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(2),
-      kNoConversionFlags,
-      &exception_state, &arg3);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue staticFunctionJSstaticFunction5(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  const size_t kMinArguments = 3;
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-  // Non-optional arguments
-  TypeTraits<int32_t >::ConversionType arg1;
-  TypeTraits<int32_t >::ConversionType arg2;
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3;
-
-  DCHECK_LT(0, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(0),
-      kNoConversionFlags,
-      &exception_state, &arg1);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(1, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(1),
-      kNoConversionFlags,
-      &exception_state, &arg2);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-
-  DCHECK_LT(2, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument(2),
-      kNoConversionFlags,
-      &exception_state, &arg3);
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.h
deleted file mode 100644
index dbb5bf8..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCStaticPropertiesInterface_h
-#define JSCStaticPropertiesInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/static_properties_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCStaticPropertiesInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to StaticPropertiesInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCStaticPropertiesInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<StaticPropertiesInterface>& impl);
-  ~JSCStaticPropertiesInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCStaticPropertiesInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.cc
deleted file mode 100644
index 87dd022..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.cc
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCStringifierAnonymousOperationInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::StringifierAnonymousOperationInterface;
-using cobalt::bindings::testing::JSCStringifierAnonymousOperationInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue StringifierJS(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCStringifierAnonymousOperationInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCStringifierAnonymousOperationInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierAnonymousOperationInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAnonymousOperationInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCStringifierAnonymousOperationInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAnonymousOperationInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCStringifierAnonymousOperationInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAnonymousOperationInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierAnonymousOperationInterface::InterfaceObject::s_info = {
-    "StringifierAnonymousOperationInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAnonymousOperationInterface::InterfaceObject)
-};  // JSCStringifierAnonymousOperationInterface::InterfaceObject::s_info
-
-void JSCStringifierAnonymousOperationInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCStringifierAnonymousOperationInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCStringifierAnonymousOperationInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "StringifierAnonymousOperationInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCStringifierAnonymousOperationInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCStringifierAnonymousOperationInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierAnonymousOperationInterface::Prototype::property_table_values[] = {
-    { "toString",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(StringifierJS),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCStringifierAnonymousOperationInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAnonymousOperationInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierAnonymousOperationInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAnonymousOperationInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierAnonymousOperationInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAnonymousOperationInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierAnonymousOperationInterface::Prototype::s_info = {
-    "StringifierAnonymousOperationInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAnonymousOperationInterface::Prototype)
-};  // JSCStringifierAnonymousOperationInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCStringifierAnonymousOperationInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCStringifierAnonymousOperationInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCStringifierAnonymousOperationInterface::Prototype class
-
-const JSC::HashTableValue JSCStringifierAnonymousOperationInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAnonymousOperationInterface::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierAnonymousOperationInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAnonymousOperationInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierAnonymousOperationInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAnonymousOperationInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCStringifierAnonymousOperationInterface::NonTrivialStaticFields>
-    JSCStringifierAnonymousOperationInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCStringifierAnonymousOperationInterface::s_info = {
-    "StringifierAnonymousOperationInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAnonymousOperationInterface)
-};  // JSCStringifierAnonymousOperationInterface::s_info
-
-// static
-JSC::JSObject* JSCStringifierAnonymousOperationInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCStringifierAnonymousOperationInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCStringifierAnonymousOperationInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCStringifierAnonymousOperationInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType()";
-    return NULL;
-  }
-  StringifierAnonymousOperationInterface* impl_ptr =
-      base::polymorphic_downcast<StringifierAnonymousOperationInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCStringifierAnonymousOperationInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCStringifierAnonymousOperationInterface>(global_data.heap))
-      JSCStringifierAnonymousOperationInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCStringifierAnonymousOperationInterface::JSCStringifierAnonymousOperationInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<StringifierAnonymousOperationInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCStringifierAnonymousOperationInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCStringifierAnonymousOperationInterface::~JSCStringifierAnonymousOperationInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCStringifierAnonymousOperationInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCStringifierAnonymousOperationInterface* this_object = JSC::jsCast<JSCStringifierAnonymousOperationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCStringifierAnonymousOperationInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCStringifierAnonymousOperationInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCStringifierAnonymousOperationInterface* this_object = JSC::jsCast<JSCStringifierAnonymousOperationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCStringifierAnonymousOperationInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCStringifierAnonymousOperationInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCStringifierAnonymousOperationInterface* this_object = JSC::jsCast<JSCStringifierAnonymousOperationInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCStringifierAnonymousOperationInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-JSC::EncodedJSValue StringifierJS(JSC::ExecState* exec_state) {
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  StringifierAnonymousOperationInterface* impl =
-      GetWrappableOrSetException<StringifierAnonymousOperationInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(global_object, impl->AnonymousStringifier());
-  return JSC::JSValue::encode(result);
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.h
deleted file mode 100644
index ac79ef5..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAnonymousOperationInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCStringifierAnonymousOperationInterface_h
-#define JSCStringifierAnonymousOperationInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/stringifier_anonymous_operation_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCStringifierAnonymousOperationInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to StringifierAnonymousOperationInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCStringifierAnonymousOperationInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<StringifierAnonymousOperationInterface>& impl);
-  ~JSCStringifierAnonymousOperationInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCStringifierAnonymousOperationInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.cc
deleted file mode 100644
index 3b0dfed..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.cc
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCStringifierAttributeInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::StringifierAttributeInterface;
-using cobalt::bindings::testing::JSCStringifierAttributeInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJStheStringifierAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJStheStringifierAttribute(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::EncodedJSValue StringifierJS(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCStringifierAttributeInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCStringifierAttributeInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierAttributeInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAttributeInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCStringifierAttributeInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAttributeInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCStringifierAttributeInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAttributeInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierAttributeInterface::InterfaceObject::s_info = {
-    "StringifierAttributeInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAttributeInterface::InterfaceObject)
-};  // JSCStringifierAttributeInterface::InterfaceObject::s_info
-
-void JSCStringifierAttributeInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCStringifierAttributeInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCStringifierAttributeInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "StringifierAttributeInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCStringifierAttributeInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCStringifierAttributeInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierAttributeInterface::Prototype::property_table_values[] = {
-    { "toString",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(StringifierJS),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCStringifierAttributeInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAttributeInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierAttributeInterface::Prototype::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAttributeInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierAttributeInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAttributeInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierAttributeInterface::Prototype::s_info = {
-    "StringifierAttributeInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAttributeInterface::Prototype)
-};  // JSCStringifierAttributeInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCStringifierAttributeInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCStringifierAttributeInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCStringifierAttributeInterface::Prototype class
-
-const JSC::HashTableValue JSCStringifierAttributeInterface::property_table_values[] = {
-    { "theStringifierAttribute",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJStheStringifierAttribute),
-        reinterpret_cast<intptr_t>(setJStheStringifierAttribute),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierAttributeInterface::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierAttributeInterface::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierAttributeInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierAttributeInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierAttributeInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCStringifierAttributeInterface::NonTrivialStaticFields>
-    JSCStringifierAttributeInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCStringifierAttributeInterface::s_info = {
-    "StringifierAttributeInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierAttributeInterface)
-};  // JSCStringifierAttributeInterface::s_info
-
-// static
-JSC::JSObject* JSCStringifierAttributeInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCStringifierAttributeInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCStringifierAttributeInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCStringifierAttributeInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType()";
-    return NULL;
-  }
-  StringifierAttributeInterface* impl_ptr =
-      base::polymorphic_downcast<StringifierAttributeInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCStringifierAttributeInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCStringifierAttributeInterface>(global_data.heap))
-      JSCStringifierAttributeInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCStringifierAttributeInterface::JSCStringifierAttributeInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<StringifierAttributeInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCStringifierAttributeInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCStringifierAttributeInterface::~JSCStringifierAttributeInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCStringifierAttributeInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCStringifierAttributeInterface* this_object = JSC::jsCast<JSCStringifierAttributeInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCStringifierAttributeInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCStringifierAttributeInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCStringifierAttributeInterface* this_object = JSC::jsCast<JSCStringifierAttributeInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCStringifierAttributeInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCStringifierAttributeInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCStringifierAttributeInterface* this_object = JSC::jsCast<JSCStringifierAttributeInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCStringifierAttributeInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJStheStringifierAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCStringifierAttributeInterface", "get theStringifierAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  StringifierAttributeInterface* impl =
-      GetWrappableOrSetException<StringifierAttributeInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->the_stringifier_attribute());
-  return result;
-}
-
-void setJStheStringifierAttribute(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCStringifierAttributeInterface", "set theStringifierAttribute");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  StringifierAttributeInterface* impl =
-      GetWrappableOrSetException<StringifierAttributeInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_the_stringifier_attribute(cobalt_value);
-  }
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-JSC::EncodedJSValue StringifierJS(JSC::ExecState* exec_state) {
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  StringifierAttributeInterface* impl =
-      GetWrappableOrSetException<StringifierAttributeInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(global_object, impl->the_stringifier_attribute());
-  return JSC::JSValue::encode(result);
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.h
deleted file mode 100644
index 3d84c36..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierAttributeInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCStringifierAttributeInterface_h
-#define JSCStringifierAttributeInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/stringifier_attribute_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCStringifierAttributeInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to StringifierAttributeInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCStringifierAttributeInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<StringifierAttributeInterface>& impl);
-  ~JSCStringifierAttributeInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCStringifierAttributeInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.cc
deleted file mode 100644
index db2d4b4..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.cc
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCStringifierOperationInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::StringifierOperationInterface;
-using cobalt::bindings::testing::JSCStringifierOperationInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJStheStringifierOperation(JSC::ExecState*);
-JSC::EncodedJSValue StringifierJS(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCStringifierOperationInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCStringifierOperationInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierOperationInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierOperationInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCStringifierOperationInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierOperationInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCStringifierOperationInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierOperationInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierOperationInterface::InterfaceObject::s_info = {
-    "StringifierOperationInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierOperationInterface::InterfaceObject)
-};  // JSCStringifierOperationInterface::InterfaceObject::s_info
-
-void JSCStringifierOperationInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCStringifierOperationInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCStringifierOperationInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "StringifierOperationInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCStringifierOperationInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCStringifierOperationInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCStringifierOperationInterface::Prototype::property_table_values[] = {
-    { "theStringifierOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJStheStringifierOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "toString",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(StringifierJS),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCStringifierOperationInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierOperationInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierOperationInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierOperationInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierOperationInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierOperationInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCStringifierOperationInterface::Prototype::s_info = {
-    "StringifierOperationInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierOperationInterface::Prototype)
-};  // JSCStringifierOperationInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCStringifierOperationInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCStringifierOperationInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCStringifierOperationInterface::Prototype class
-
-const JSC::HashTableValue JSCStringifierOperationInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCStringifierOperationInterface::property_table_values
-
-// static
-const JSC::HashTable JSCStringifierOperationInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCStringifierOperationInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCStringifierOperationInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCStringifierOperationInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCStringifierOperationInterface::NonTrivialStaticFields>
-    JSCStringifierOperationInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCStringifierOperationInterface::s_info = {
-    "StringifierOperationInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCStringifierOperationInterface)
-};  // JSCStringifierOperationInterface::s_info
-
-// static
-JSC::JSObject* JSCStringifierOperationInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCStringifierOperationInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCStringifierOperationInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCStringifierOperationInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == StringifierOperationInterface::StringifierOperationInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match StringifierOperationInterface::StringifierOperationInterfaceWrappableType()";
-    return NULL;
-  }
-  StringifierOperationInterface* impl_ptr =
-      base::polymorphic_downcast<StringifierOperationInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCStringifierOperationInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCStringifierOperationInterface>(global_data.heap))
-      JSCStringifierOperationInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCStringifierOperationInterface::JSCStringifierOperationInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<StringifierOperationInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCStringifierOperationInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCStringifierOperationInterface::~JSCStringifierOperationInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCStringifierOperationInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCStringifierOperationInterface* this_object = JSC::jsCast<JSCStringifierOperationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCStringifierOperationInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCStringifierOperationInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCStringifierOperationInterface* this_object = JSC::jsCast<JSCStringifierOperationInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCStringifierOperationInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCStringifierOperationInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCStringifierOperationInterface* this_object = JSC::jsCast<JSCStringifierOperationInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCStringifierOperationInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJStheStringifierOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCStringifierOperationInterface", "call theStringifierOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  StringifierOperationInterface* impl =
-      GetWrappableOrSetException<StringifierOperationInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<std::string >::ReturnType return_value = impl->TheStringifierOperation();
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-JSC::EncodedJSValue StringifierJS(JSC::ExecState* exec_state) {
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  StringifierOperationInterface* impl =
-      GetWrappableOrSetException<StringifierOperationInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(global_object, impl->TheStringifierOperation());
-  return JSC::JSValue::encode(result);
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.h
deleted file mode 100644
index f20c26d..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStringifierOperationInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCStringifierOperationInterface_h
-#define JSCStringifierOperationInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/stringifier_operation_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCStringifierOperationInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to StringifierOperationInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCStringifierOperationInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<StringifierOperationInterface>& impl);
-  ~JSCStringifierOperationInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCStringifierOperationInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.cc
deleted file mode 100644
index 0dbd16b..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.cc
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCTargetInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::TargetInterface;
-using cobalt::bindings::testing::JSCTargetInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::EncodedJSValue functionJSimplementedInterfaceFunction(JSC::ExecState*);
-JSC::EncodedJSValue functionJSpartialInterfaceFunction(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCTargetInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCTargetInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCTargetInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCTargetInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCTargetInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCTargetInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCTargetInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCTargetInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCTargetInterface::InterfaceObject::s_info = {
-    "TargetInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCTargetInterface::InterfaceObject)
-};  // JSCTargetInterface::InterfaceObject::s_info
-
-void JSCTargetInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCTargetInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCTargetInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "TargetInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCTargetInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCTargetInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCTargetInterface::Prototype::property_table_values[] = {
-    { "implementedInterfaceFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSimplementedInterfaceFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "partialInterfaceFunction",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSpartialInterfaceFunction),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCTargetInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCTargetInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCTargetInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCTargetInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCTargetInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCTargetInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCTargetInterface::Prototype::s_info = {
-    "TargetInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCTargetInterface::Prototype)
-};  // JSCTargetInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCTargetInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCTargetInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCTargetInterface::Prototype class
-
-const JSC::HashTableValue JSCTargetInterface::property_table_values[] = {
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCTargetInterface::property_table_values
-
-// static
-const JSC::HashTable JSCTargetInterface::property_table_prototype = {
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCTargetInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCTargetInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCTargetInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCTargetInterface::NonTrivialStaticFields>
-    JSCTargetInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCTargetInterface::s_info = {
-    "TargetInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCTargetInterface)
-};  // JSCTargetInterface::s_info
-
-// static
-JSC::JSObject* JSCTargetInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCTargetInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCTargetInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCTargetInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == TargetInterface::TargetInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match TargetInterface::TargetInterfaceWrappableType()";
-    return NULL;
-  }
-  TargetInterface* impl_ptr =
-      base::polymorphic_downcast<TargetInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCTargetInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCTargetInterface>(global_data.heap))
-      JSCTargetInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCTargetInterface::JSCTargetInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<TargetInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCTargetInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCTargetInterface::~JSCTargetInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCTargetInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCTargetInterface* this_object = JSC::jsCast<JSCTargetInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCTargetInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCTargetInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCTargetInterface* this_object = JSC::jsCast<JSCTargetInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCTargetInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCTargetInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCTargetInterface* this_object = JSC::jsCast<JSCTargetInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCTargetInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::EncodedJSValue functionJSimplementedInterfaceFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCTargetInterface", "call implementedInterfaceFunction");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  TargetInterface* impl =
-      GetWrappableOrSetException<TargetInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->ImplementedInterfaceFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-
-JSC::EncodedJSValue functionJSpartialInterfaceFunction(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCTargetInterface", "call partialInterfaceFunction");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  TargetInterface* impl =
-      GetWrappableOrSetException<TargetInterface>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->PartialInterfaceFunction();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.h
deleted file mode 100644
index 511a979..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCTargetInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCTargetInterface_h
-#define JSCTargetInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/target_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCTargetInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to TargetInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCTargetInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<TargetInterface>& impl);
-  ~JSCTargetInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCTargetInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
deleted file mode 100644
index e1a3fce..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCUnionTypesInterface.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCArbitraryInterface.h"
-#include "JSCBaseInterface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-#include "cobalt/bindings/testing/base_interface.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::UnionTypesInterface;
-using cobalt::bindings::testing::JSCUnionTypesInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::BaseInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::bindings::testing::JSCBaseInterface;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSunionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunionProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunionWithNullableMemberProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunionWithNullableMemberProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSnullableUnionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSnullableUnionProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSunionBaseProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSunionBaseProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = true;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCUnionTypesInterface::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCUnionTypesInterface";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCUnionTypesInterface::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCUnionTypesInterface::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCUnionTypesInterface::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCUnionTypesInterface::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCUnionTypesInterface::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCUnionTypesInterface::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCUnionTypesInterface::InterfaceObject::s_info = {
-    "UnionTypesInterfaceConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCUnionTypesInterface::InterfaceObject)
-};  // JSCUnionTypesInterface::InterfaceObject::s_info
-
-void JSCUnionTypesInterface::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCUnionTypesInterface::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCUnionTypesInterface::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "UnionTypesInterface");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCUnionTypesInterface::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCUnionTypesInterface::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCUnionTypesInterface::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCUnionTypesInterface::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCUnionTypesInterface::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCUnionTypesInterface::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCUnionTypesInterface::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCUnionTypesInterface::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCUnionTypesInterface::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCUnionTypesInterface::Prototype::s_info = {
-    "UnionTypesInterfacePrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCUnionTypesInterface::Prototype)
-};  // JSCUnionTypesInterface::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCUnionTypesInterface::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCUnionTypesInterface::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCUnionTypesInterface::Prototype class
-
-const JSC::HashTableValue JSCUnionTypesInterface::property_table_values[] = {
-    { "unionProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunionProperty),
-        reinterpret_cast<intptr_t>(setJSunionProperty),
-        JSC::NoIntrinsic
-    },
-    { "unionWithNullableMemberProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunionWithNullableMemberProperty),
-        reinterpret_cast<intptr_t>(setJSunionWithNullableMemberProperty),
-        JSC::NoIntrinsic
-    },
-    { "nullableUnionProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSnullableUnionProperty),
-        reinterpret_cast<intptr_t>(setJSnullableUnionProperty),
-        JSC::NoIntrinsic
-    },
-    { "unionBaseProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSunionBaseProperty),
-        reinterpret_cast<intptr_t>(setJSunionBaseProperty),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCUnionTypesInterface::property_table_values
-
-// static
-const JSC::HashTable JSCUnionTypesInterface::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCUnionTypesInterface::property_table_prototype
-
-// static
-const JSC::HashTable* JSCUnionTypesInterface::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCUnionTypesInterface::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCUnionTypesInterface::NonTrivialStaticFields>
-    JSCUnionTypesInterface::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCUnionTypesInterface::s_info = {
-    "UnionTypesInterface",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCUnionTypesInterface)
-};  // JSCUnionTypesInterface::s_info
-
-// static
-JSC::JSObject* JSCUnionTypesInterface::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCUnionTypesInterface::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCUnionTypesInterface::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-JSC::JSObject* JSCUnionTypesInterface::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == UnionTypesInterface::UnionTypesInterfaceWrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match UnionTypesInterface::UnionTypesInterfaceWrappableType()";
-    return NULL;
-  }
-  UnionTypesInterface* impl_ptr =
-      base::polymorphic_downcast<UnionTypesInterface*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  JSCUnionTypesInterface* wrapper =
-      new (NotNull, JSC::allocateCell<JSCUnionTypesInterface>(global_data.heap))
-      JSCUnionTypesInterface(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-  return wrapper;
-}
-JSCUnionTypesInterface::JSCUnionTypesInterface(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    const scoped_refptr<UnionTypesInterface>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl) {
-}
-
-void JSCUnionTypesInterface::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCUnionTypesInterface::~JSCUnionTypesInterface() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCUnionTypesInterface::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCUnionTypesInterface* this_object = JSC::jsCast<JSCUnionTypesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool found_property_slot = JSC::getStaticValueSlot<JSCUnionTypesInterface, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCUnionTypesInterface::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCUnionTypesInterface* this_object = JSC::jsCast<JSCUnionTypesInterface*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCUnionTypesInterface, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCUnionTypesInterface::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCUnionTypesInterface* this_object = JSC::jsCast<JSCUnionTypesInterface*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCUnionTypesInterface, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSunionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "get unionProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->union_property());
-  return result;
-}
-
-void setJSunionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "set unionProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_union_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunionWithNullableMemberProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "get unionWithNullableMemberProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->union_with_nullable_member_property());
-  return result;
-}
-
-void setJSunionWithNullableMemberProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "set unionWithNullableMemberProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_union_with_nullable_member_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSnullableUnionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "get nullableUnionProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->nullable_union_property());
-  return result;
-}
-
-void setJSnullableUnionProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "set nullableUnionProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      (kConversionFlagNullable), &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_nullable_union_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSunionBaseProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "get unionBaseProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->union_base_property());
-  return result;
-}
-
-void setJSunionBaseProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCUnionTypesInterface", "set unionBaseProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  UnionTypesInterface* impl =
-      GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<script::UnionType2<scoped_refptr<BaseInterface>, std::string > >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_union_base_property(cobalt_value);
-  }
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.h b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.h
deleted file mode 100644
index ddc64d2..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCUnionTypesInterface_h
-#define JSCUnionTypesInterface_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "cobalt/bindings/testing/union_types_interface.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCUnionTypesInterface
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to UnionTypesInterface.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCUnionTypesInterface(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      const scoped_refptr<UnionTypesInterface>& impl);
-  ~JSCUnionTypesInterface();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCUnionTypesInterface_h
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc b/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc
deleted file mode 100644
index b1720fd..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc
+++ /dev/null
@@ -1,1229 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.cc.template
-
-// clang-format off
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-#include "JSCWindow.h"
-
-#include "base/debug/trace_event.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-#include "JSCAnonymousIndexedGetterInterface.h"
-#include "JSCAnonymousNamedGetterInterface.h"
-#include "JSCAnonymousNamedIndexedGetterInterface.h"
-#include "JSCArbitraryInterface.h"
-#include "JSCBaseInterface.h"
-#include "JSCBooleanTypeTestInterface.h"
-#include "JSCCallbackFunctionInterface.h"
-#include "JSCCallbackInterfaceInterface.h"
-#include "JSCConditionalInterface.h"
-#include "JSCConstantsInterface.h"
-#include "JSCConstructorInterface.h"
-#include "JSCConstructorWithArgumentsInterface.h"
-#include "JSCDOMStringTestInterface.h"
-#include "JSCDerivedGetterSetterInterface.h"
-#include "JSCDerivedInterface.h"
-#include "JSCDisabledInterface.h"
-#include "JSCEnumerationInterface.h"
-#include "JSCExceptionObjectInterface.h"
-#include "JSCExceptionsInterface.h"
-#include "JSCExtendedIDLAttributesInterface.h"
-#include "JSCGarbageCollectionTestInterface.h"
-#include "JSCGetOpaqueRootInterface.h"
-#include "JSCGlobalInterfaceParent.h"
-#include "JSCImplementedInterface.h"
-#include "JSCIndexedGetterInterface.h"
-#include "JSCInterfaceWithUnsupportedProperties.h"
-#include "JSCNamedConstructorInterface.h"
-#include "JSCNamedGetterInterface.h"
-#include "JSCNamedIndexedGetterInterface.h"
-#include "JSCNestedPutForwardsInterface.h"
-#include "JSCNoConstructorInterface.h"
-#include "JSCNoInterfaceObjectInterface.h"
-#include "JSCNullableTypesTestInterface.h"
-#include "JSCNumericTypesTestInterface.h"
-#include "JSCObjectTypeBindingsInterface.h"
-#include "JSCOperationsTestInterface.h"
-#include "JSCPutForwardsInterface.h"
-#include "JSCSequenceUser.h"
-#include "JSCSingleOperationInterface.h"
-#include "JSCStaticPropertiesInterface.h"
-#include "JSCStringifierAnonymousOperationInterface.h"
-#include "JSCStringifierAttributeInterface.h"
-#include "JSCStringifierOperationInterface.h"
-#include "JSCTargetInterface.h"
-#include "JSCUnionTypesInterface.h"
-#include "JSCWindow.h"
-#include "cobalt/bindings/testing/anonymous_indexed_getter_interface.h"
-#include "cobalt/bindings/testing/anonymous_named_getter_interface.h"
-#include "cobalt/bindings/testing/anonymous_named_indexed_getter_interface.h"
-#include "cobalt/bindings/testing/arbitrary_interface.h"
-#include "cobalt/bindings/testing/base_interface.h"
-#include "cobalt/bindings/testing/boolean_type_test_interface.h"
-#include "cobalt/bindings/testing/callback_function_interface.h"
-#include "cobalt/bindings/testing/callback_interface_interface.h"
-#include "cobalt/bindings/testing/conditional_interface.h"
-#include "cobalt/bindings/testing/constants_interface.h"
-#include "cobalt/bindings/testing/constructor_interface.h"
-#include "cobalt/bindings/testing/constructor_with_arguments_interface.h"
-#include "cobalt/bindings/testing/derived_getter_setter_interface.h"
-#include "cobalt/bindings/testing/derived_interface.h"
-#include "cobalt/bindings/testing/disabled_interface.h"
-#include "cobalt/bindings/testing/dom_string_test_interface.h"
-#include "cobalt/bindings/testing/enumeration_interface.h"
-#include "cobalt/bindings/testing/exception_object_interface.h"
-#include "cobalt/bindings/testing/exceptions_interface.h"
-#include "cobalt/bindings/testing/extended_idl_attributes_interface.h"
-#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
-#include "cobalt/bindings/testing/get_opaque_root_interface.h"
-#include "cobalt/bindings/testing/global_interface_parent.h"
-#include "cobalt/bindings/testing/implemented_interface.h"
-#include "cobalt/bindings/testing/indexed_getter_interface.h"
-#include "cobalt/bindings/testing/interface_with_unsupported_properties.h"
-#include "cobalt/bindings/testing/named_constructor_interface.h"
-#include "cobalt/bindings/testing/named_getter_interface.h"
-#include "cobalt/bindings/testing/named_indexed_getter_interface.h"
-#include "cobalt/bindings/testing/nested_put_forwards_interface.h"
-#include "cobalt/bindings/testing/no_constructor_interface.h"
-#include "cobalt/bindings/testing/no_interface_object_interface.h"
-#include "cobalt/bindings/testing/nullable_types_test_interface.h"
-#include "cobalt/bindings/testing/numeric_types_test_interface.h"
-#include "cobalt/bindings/testing/object_type_bindings_interface.h"
-#include "cobalt/bindings/testing/operations_test_interface.h"
-#include "cobalt/bindings/testing/put_forwards_interface.h"
-#include "cobalt/bindings/testing/sequence_user.h"
-#include "cobalt/bindings/testing/single_operation_interface.h"
-#include "cobalt/bindings/testing/static_properties_interface.h"
-#include "cobalt/bindings/testing/stringifier_anonymous_operation_interface.h"
-#include "cobalt/bindings/testing/stringifier_attribute_interface.h"
-#include "cobalt/bindings/testing/stringifier_operation_interface.h"
-#include "cobalt/bindings/testing/target_interface.h"
-#include "cobalt/bindings/testing/union_types_interface.h"
-#include "cobalt/bindings/testing/window.h"
-
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-
-namespace {
-using cobalt::bindings::testing::Window;
-using cobalt::bindings::testing::JSCWindow;
-using cobalt::bindings::testing::AnonymousIndexedGetterInterface;
-using cobalt::bindings::testing::AnonymousNamedGetterInterface;
-using cobalt::bindings::testing::AnonymousNamedIndexedGetterInterface;
-using cobalt::bindings::testing::ArbitraryInterface;
-using cobalt::bindings::testing::BaseInterface;
-using cobalt::bindings::testing::BooleanTypeTestInterface;
-using cobalt::bindings::testing::CallbackFunctionInterface;
-using cobalt::bindings::testing::CallbackInterfaceInterface;
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::ConditionalInterface;
-#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::ConstantsInterface;
-using cobalt::bindings::testing::ConstructorInterface;
-using cobalt::bindings::testing::ConstructorWithArgumentsInterface;
-using cobalt::bindings::testing::DOMStringTestInterface;
-using cobalt::bindings::testing::DerivedGetterSetterInterface;
-using cobalt::bindings::testing::DerivedInterface;
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::DisabledInterface;
-#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::EnumerationInterface;
-using cobalt::bindings::testing::ExceptionObjectInterface;
-using cobalt::bindings::testing::ExceptionsInterface;
-using cobalt::bindings::testing::ExtendedIDLAttributesInterface;
-using cobalt::bindings::testing::GarbageCollectionTestInterface;
-using cobalt::bindings::testing::GetOpaqueRootInterface;
-using cobalt::bindings::testing::GlobalInterfaceParent;
-using cobalt::bindings::testing::ImplementedInterface;
-using cobalt::bindings::testing::IndexedGetterInterface;
-using cobalt::bindings::testing::InterfaceWithUnsupportedProperties;
-using cobalt::bindings::testing::JSCAnonymousIndexedGetterInterface;
-using cobalt::bindings::testing::JSCAnonymousNamedGetterInterface;
-using cobalt::bindings::testing::JSCAnonymousNamedIndexedGetterInterface;
-using cobalt::bindings::testing::JSCArbitraryInterface;
-using cobalt::bindings::testing::JSCBaseInterface;
-using cobalt::bindings::testing::JSCBooleanTypeTestInterface;
-using cobalt::bindings::testing::JSCCallbackFunctionInterface;
-using cobalt::bindings::testing::JSCCallbackInterfaceInterface;
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::JSCConditionalInterface;
-#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::JSCConstantsInterface;
-using cobalt::bindings::testing::JSCConstructorInterface;
-using cobalt::bindings::testing::JSCConstructorWithArgumentsInterface;
-using cobalt::bindings::testing::JSCDOMStringTestInterface;
-using cobalt::bindings::testing::JSCDerivedGetterSetterInterface;
-using cobalt::bindings::testing::JSCDerivedInterface;
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::JSCDisabledInterface;
-#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-using cobalt::bindings::testing::JSCEnumerationInterface;
-using cobalt::bindings::testing::JSCExceptionObjectInterface;
-using cobalt::bindings::testing::JSCExceptionsInterface;
-using cobalt::bindings::testing::JSCExtendedIDLAttributesInterface;
-using cobalt::bindings::testing::JSCGarbageCollectionTestInterface;
-using cobalt::bindings::testing::JSCGetOpaqueRootInterface;
-using cobalt::bindings::testing::JSCGlobalInterfaceParent;
-using cobalt::bindings::testing::JSCImplementedInterface;
-using cobalt::bindings::testing::JSCIndexedGetterInterface;
-using cobalt::bindings::testing::JSCInterfaceWithUnsupportedProperties;
-using cobalt::bindings::testing::JSCNamedConstructorInterface;
-using cobalt::bindings::testing::JSCNamedGetterInterface;
-using cobalt::bindings::testing::JSCNamedIndexedGetterInterface;
-using cobalt::bindings::testing::JSCNestedPutForwardsInterface;
-using cobalt::bindings::testing::JSCNoConstructorInterface;
-using cobalt::bindings::testing::JSCNoInterfaceObjectInterface;
-using cobalt::bindings::testing::JSCNullableTypesTestInterface;
-using cobalt::bindings::testing::JSCNumericTypesTestInterface;
-using cobalt::bindings::testing::JSCObjectTypeBindingsInterface;
-using cobalt::bindings::testing::JSCOperationsTestInterface;
-using cobalt::bindings::testing::JSCPutForwardsInterface;
-using cobalt::bindings::testing::JSCSequenceUser;
-using cobalt::bindings::testing::JSCSingleOperationInterface;
-using cobalt::bindings::testing::JSCStaticPropertiesInterface;
-using cobalt::bindings::testing::JSCStringifierAnonymousOperationInterface;
-using cobalt::bindings::testing::JSCStringifierAttributeInterface;
-using cobalt::bindings::testing::JSCStringifierOperationInterface;
-using cobalt::bindings::testing::JSCTargetInterface;
-using cobalt::bindings::testing::JSCUnionTypesInterface;
-using cobalt::bindings::testing::JSCWindow;
-using cobalt::bindings::testing::NamedConstructorInterface;
-using cobalt::bindings::testing::NamedGetterInterface;
-using cobalt::bindings::testing::NamedIndexedGetterInterface;
-using cobalt::bindings::testing::NestedPutForwardsInterface;
-using cobalt::bindings::testing::NoConstructorInterface;
-using cobalt::bindings::testing::NoInterfaceObjectInterface;
-using cobalt::bindings::testing::NullableTypesTestInterface;
-using cobalt::bindings::testing::NumericTypesTestInterface;
-using cobalt::bindings::testing::ObjectTypeBindingsInterface;
-using cobalt::bindings::testing::OperationsTestInterface;
-using cobalt::bindings::testing::PutForwardsInterface;
-using cobalt::bindings::testing::SequenceUser;
-using cobalt::bindings::testing::SingleOperationInterface;
-using cobalt::bindings::testing::StaticPropertiesInterface;
-using cobalt::bindings::testing::StringifierAnonymousOperationInterface;
-using cobalt::bindings::testing::StringifierAttributeInterface;
-using cobalt::bindings::testing::StringifierOperationInterface;
-using cobalt::bindings::testing::TargetInterface;
-using cobalt::bindings::testing::UnionTypesInterface;
-using cobalt::bindings::testing::Window;
-using cobalt::script::CallbackInterfaceTraits;
-using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
-using cobalt::script::ScriptObject;
-using cobalt::script::Wrappable;
-
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-}  // namespace
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-namespace {
-JSC::JSValue getJSwindowProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-void setJSwindowProperty(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-JSC::JSValue getJSwindow(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-JSC::EncodedJSValue functionJSgetStackTrace(JSC::ExecState*);
-JSC::EncodedJSValue functionJSwindowOperation(JSC::ExecState*);
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = false;
-const bool s_has_named_setter = false;
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = false;
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-}  // namespace
-
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class JSCWindow::InterfaceObject : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    InterfaceObject* this_object = JSC::jsCast<InterfaceObject*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<InterfaceObject>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for JSCWindow";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  InterfaceObject(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCWindow::InterfaceObject::property_table_values[] = {
-    // static functions will also go here.
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCWindow::InterfaceObject::property_table_values
-
-// static
-const JSC::HashTable
-JSCWindow::InterfaceObject::property_table_prototype = {
-    // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCWindow::InterfaceObject::property_table_prototype
-
-// static
-const JSC::HashTable*
-JSCWindow::InterfaceObject::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCWindow::InterfaceObject::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo JSCWindow::InterfaceObject::s_info = {
-    "WindowConstructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCWindow::InterfaceObject)
-};  // JSCWindow::InterfaceObject::s_info
-
-void JSCWindow::InterfaceObject::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            JSCWindow::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* JSCWindow::InterfaceObject::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-
-    // Create the new interface object.
-    InterfaceObject* new_interface_object =
-        new (NotNull, JSC::allocateCell<InterfaceObject>(global_data.heap))
-        InterfaceObject(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "Window");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of JSCWindow::InterfaceObject class
-
-// Class that defines a JS Object representing this interface's prototype
-class JSCWindow::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue JSCWindow::Prototype::property_table_values[] = {
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>(JSCWindow::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCWindow::Prototype::property_table_values
-
-// static
-const JSC::HashTable JSCWindow::Prototype::property_table_prototype = {
-    4,  // compactSize
-    3,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCWindow::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* JSCWindow::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCWindow::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo JSCWindow::Prototype::s_info = {
-    "WindowPrototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCWindow::Prototype)
-};  // JSCWindow::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool JSCWindow::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* JSCWindow::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-    JSC::JSObject* parent_prototype =
-        bindings::testing::JSCGlobalInterfaceParent::GetPrototype(global_object);
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of JSCWindow::Prototype class
-
-const JSC::HashTableValue JSCWindow::property_table_values[] = {
-    { "windowProperty",
-        JSC::DontDelete ,
-        reinterpret_cast<intptr_t>(getJSwindowProperty),
-        reinterpret_cast<intptr_t>(setJSwindowProperty),
-        JSC::NoIntrinsic
-    },
-    { "window",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJSwindow),
-        0,
-        JSC::NoIntrinsic
-    },
-    { "getStackTrace",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSgetStackTrace),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { "windowOperation",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJSwindowOperation),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // JSCWindow::property_table_values
-
-// static
-const JSC::HashTable JSCWindow::property_table_prototype = {
-    19,  // compactSize
-    15,  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // JSCWindow::property_table_prototype
-
-// static
-const JSC::HashTable* JSCWindow::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      JSCWindow::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<JSCWindow::NonTrivialStaticFields>
-    JSCWindow::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo JSCWindow::s_info = {
-    "Window",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE(JSCWindow)
-};  // JSCWindow::s_info
-
-// static
-JSC::JSObject* JSCWindow::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-// static
-JSC::JSObject* JSCWindow::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue JSCWindow::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-
-// static
-script::javascriptcore::JSCGlobalObject* JSCWindow::Create(
-    const scoped_refptr<Window>& global_interface,
-    script::EnvironmentSettings* environment_settings,
-    JSC::JSGlobalData* global_data,
-    ScriptObjectRegistry* script_object_registry) {
-  scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory =
-      make_scoped_ptr(new script::javascriptcore::WrapperFactory());
-  wrapper_factory->RegisterWrappableType(
-      AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
-      JSCAnonymousIndexedGetterInterface::s_classinfo(),
-      JSCAnonymousIndexedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(),
-      JSCAnonymousNamedGetterInterface::s_classinfo(),
-      JSCAnonymousNamedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(),
-      JSCAnonymousNamedIndexedGetterInterface::s_classinfo(),
-      JSCAnonymousNamedIndexedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ArbitraryInterface::ArbitraryInterfaceWrappableType(),
-      JSCArbitraryInterface::s_classinfo(),
-      JSCArbitraryInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      BaseInterface::BaseInterfaceWrappableType(),
-      JSCBaseInterface::s_classinfo(),
-      JSCBaseInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(),
-      JSCBooleanTypeTestInterface::s_classinfo(),
-      JSCBooleanTypeTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(),
-      JSCCallbackFunctionInterface::s_classinfo(),
-      JSCCallbackFunctionInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(),
-      JSCCallbackInterfaceInterface::s_classinfo(),
-      JSCCallbackInterfaceInterface::GetCreateWrapperFunction());
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
-      ConditionalInterface::ConditionalInterfaceWrappableType(),
-      JSCConditionalInterface::s_classinfo(),
-      JSCConditionalInterface::GetCreateWrapperFunction());
-#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
-      ConstantsInterface::ConstantsInterfaceWrappableType(),
-      JSCConstantsInterface::s_classinfo(),
-      JSCConstantsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ConstructorInterface::ConstructorInterfaceWrappableType(),
-      JSCConstructorInterface::s_classinfo(),
-      JSCConstructorInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(),
-      JSCConstructorWithArgumentsInterface::s_classinfo(),
-      JSCConstructorWithArgumentsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      DOMStringTestInterface::DOMStringTestInterfaceWrappableType(),
-      JSCDOMStringTestInterface::s_classinfo(),
-      JSCDOMStringTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(),
-      JSCDerivedGetterSetterInterface::s_classinfo(),
-      JSCDerivedGetterSetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      DerivedInterface::DerivedInterfaceWrappableType(),
-      JSCDerivedInterface::s_classinfo(),
-      JSCDerivedInterface::GetCreateWrapperFunction());
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
-      DisabledInterface::DisabledInterfaceWrappableType(),
-      JSCDisabledInterface::s_classinfo(),
-      JSCDisabledInterface::GetCreateWrapperFunction());
-#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
-      EnumerationInterface::EnumerationInterfaceWrappableType(),
-      JSCEnumerationInterface::s_classinfo(),
-      JSCEnumerationInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(),
-      JSCExceptionObjectInterface::s_classinfo(),
-      JSCExceptionObjectInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ExceptionsInterface::ExceptionsInterfaceWrappableType(),
-      JSCExceptionsInterface::s_classinfo(),
-      JSCExceptionsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(),
-      JSCExtendedIDLAttributesInterface::s_classinfo(),
-      JSCExtendedIDLAttributesInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType(),
-      JSCGarbageCollectionTestInterface::s_classinfo(),
-      JSCGarbageCollectionTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      GetOpaqueRootInterface::GetOpaqueRootInterfaceWrappableType(),
-      JSCGetOpaqueRootInterface::s_classinfo(),
-      JSCGetOpaqueRootInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      GlobalInterfaceParent::GlobalInterfaceParentWrappableType(),
-      JSCGlobalInterfaceParent::s_classinfo(),
-      JSCGlobalInterfaceParent::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ImplementedInterface::ImplementedInterfaceWrappableType(),
-      JSCImplementedInterface::s_classinfo(),
-      JSCImplementedInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      IndexedGetterInterface::IndexedGetterInterfaceWrappableType(),
-      JSCIndexedGetterInterface::s_classinfo(),
-      JSCIndexedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(),
-      JSCInterfaceWithUnsupportedProperties::s_classinfo(),
-      JSCInterfaceWithUnsupportedProperties::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NamedConstructorInterface::NamedConstructorInterfaceWrappableType(),
-      JSCNamedConstructorInterface::s_classinfo(),
-      JSCNamedConstructorInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NamedGetterInterface::NamedGetterInterfaceWrappableType(),
-      JSCNamedGetterInterface::s_classinfo(),
-      JSCNamedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(),
-      JSCNamedIndexedGetterInterface::s_classinfo(),
-      JSCNamedIndexedGetterInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(),
-      JSCNestedPutForwardsInterface::s_classinfo(),
-      JSCNestedPutForwardsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NoConstructorInterface::NoConstructorInterfaceWrappableType(),
-      JSCNoConstructorInterface::s_classinfo(),
-      JSCNoConstructorInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(),
-      JSCNoInterfaceObjectInterface::s_classinfo(),
-      JSCNoInterfaceObjectInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(),
-      JSCNullableTypesTestInterface::s_classinfo(),
-      JSCNullableTypesTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(),
-      JSCNumericTypesTestInterface::s_classinfo(),
-      JSCNumericTypesTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(),
-      JSCObjectTypeBindingsInterface::s_classinfo(),
-      JSCObjectTypeBindingsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      OperationsTestInterface::OperationsTestInterfaceWrappableType(),
-      JSCOperationsTestInterface::s_classinfo(),
-      JSCOperationsTestInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      PutForwardsInterface::PutForwardsInterfaceWrappableType(),
-      JSCPutForwardsInterface::s_classinfo(),
-      JSCPutForwardsInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      SequenceUser::SequenceUserWrappableType(),
-      JSCSequenceUser::s_classinfo(),
-      JSCSequenceUser::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(),
-      JSCStaticPropertiesInterface::s_classinfo(),
-      JSCStaticPropertiesInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(),
-      JSCStringifierAnonymousOperationInterface::s_classinfo(),
-      JSCStringifierAnonymousOperationInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(),
-      JSCStringifierAttributeInterface::s_classinfo(),
-      JSCStringifierAttributeInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      StringifierOperationInterface::StringifierOperationInterfaceWrappableType(),
-      JSCStringifierOperationInterface::s_classinfo(),
-      JSCStringifierOperationInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      TargetInterface::TargetInterfaceWrappableType(),
-      JSCTargetInterface::s_classinfo(),
-      JSCTargetInterface::GetCreateWrapperFunction());
-  wrapper_factory->RegisterWrappableType(
-      UnionTypesInterface::UnionTypesInterfaceWrappableType(),
-      JSCUnionTypesInterface::s_classinfo(),
-      JSCUnionTypesInterface::GetCreateWrapperFunction());
-
-  JSC::JSLockHolder lock(global_data);
-  JSC::Structure* structure = JSC::Structure::create(
-      *global_data,
-      NULL,           // JSC::JSGlobalObject*
-      JSC::jsNull(),  // prototype
-      JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags),
-      &s_info);
-  JSCWindow* global_wrapper =
-      new (NotNull, JSC::allocateCell<JSCWindow>(global_data->heap))
-      JSCWindow(
-          global_data,
-          structure,
-          script_object_registry,
-          wrapper_factory.Pass(),
-          environment_settings,
-          global_interface);
-  global_wrapper->finishCreation(*global_data);
-  global_data->heap.addFinalizer(global_wrapper, JSCWindow::destroy);
-  global_wrapper->setPrototype(
-      global_wrapper->globalData(),
-      JSCWindow::GetPrototype(global_wrapper));
-
-  return global_wrapper;
-}
-JSCWindow::JSCWindow(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-    scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory,
-    script::EnvironmentSettings* environment_settings,
-    const scoped_refptr<Window>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl,
-      wrapper_factory.Pass(), environment_settings) {
-}
-
-void JSCWindow::finishCreation(JSC::JSGlobalData& global_data) {
-  BaseClass::finishCreation(global_data);
-  DCHECK(inherits(&s_info));
-}
-
-JSCWindow::~JSCWindow() {
-  // Empty destructor
-}
-
-// Look up property slot for querying property values.
-bool JSCWindow::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  JSCWindow* this_object = JSC::jsCast<JSCWindow*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  // Global interface may have both operations and properties as own properties
-  // so we cannot use getStaticValueSlot.
-  bool found_property_slot = JSC::getStaticPropertySlot<JSCWindow, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-
-// Look up property slot and put the |value|.
-void JSCWindow::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  JSCWindow* this_object = JSC::jsCast<JSCWindow*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<JSCWindow, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-
-bool JSCWindow::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  JSCWindow* this_object = JSC::jsCast<JSCWindow*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<JSCWindow, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-
-JSC::JSValue getJSwindowProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCWindow", "get windowProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  Window* impl =
-      GetWrappableOrSetException<Window>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->window_property());
-  return result;
-}
-
-void setJSwindowProperty(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("JSCWindow", "set windowProperty");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  Window* impl =
-      GetWrappableOrSetException<Window>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-  TypeTraits<std::string >::ConversionType cobalt_value;
-  FromJSValue(exec_state, value,
-      kNoConversionFlags, &exception_state,
-      &cobalt_value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    impl->set_window_property(cobalt_value);
-  }
-}
-
-JSC::JSValue getJSwindow(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("JSCWindow", "get window");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  Window* impl =
-      GetWrappableOrSetException<Window>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      impl->window());
-  return result;
-}
-
-JSC::EncodedJSValue functionJSgetStackTrace(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCWindow", "call getStackTrace");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  Window* impl =
-      GetWrappableOrSetException<Window>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  TypeTraits<std::string >::ReturnType return_value = impl->GetStackTrace(global_object->GetStackTrace());
-  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
-
-}
-
-JSC::EncodedJSValue functionJSwindowOperation(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("JSCWindow", "call windowOperation");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  Window* impl =
-      GetWrappableOrSetException<Window>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-
-  impl->WindowOperation();
-  return JSC::JSValue::encode(JSC::jsUndefined());
-
-}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  return false;
-}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-
-}  // namespace testing
-}  // namespace bindings
-
-namespace script {
-
-template<>
-void GlobalEnvironment::CreateGlobalObject<Window>(
-    const scoped_refptr<Window>& global_interface,
-    EnvironmentSettings* environment_settings) {
-  JSCGlobalEnvironment* jsc_global_environment =
-      base::polymorphic_downcast<JSCGlobalEnvironment*>(this);
-  JSCEngine* jsc_engine = jsc_global_environment->engine();
-
-  JSCGlobalObject* global_object = JSCWindow::Create(
-      global_interface, environment_settings,
-      jsc_engine->global_data(), jsc_engine->script_object_registry());
-  jsc_global_environment->SetGlobalObject(global_object);
-}
-
-// MSVS compiler does not need this explicit instantiation, and generates a
-// compiler error.
-#if !defined(_MSC_VER)
-// Explicitly instantiate the template function for template type Window
-// This is needed to prevent link errors when trying to resolve the template
-// instantiation.
-template
-void GlobalEnvironment::CreateGlobalObject<Window>(
-    const scoped_refptr<Window>& global_interface,
-    EnvironmentSettings* environment_settings);
-#endif
-
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.h b/src/cobalt/bindings/generated/jsc/testing/JSCWindow.h
deleted file mode 100644
index 337e702..0000000
--- a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
-// Auto-generated from template: bindings/javascriptcore/templates/interface.h.template
-
-// clang-format off
-
-#ifndef JSCWindow_h
-#define JSCWindow_h
-
-#include "base/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "JSCGlobalInterfaceParent.h"
-#include "cobalt/bindings/testing/window.h"
-
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace bindings {
-namespace testing {
-
-class JSCWindow
-    : public script::javascriptcore::JSCGlobalObject {
-  typedef script::javascriptcore::JSCGlobalObject BaseClass;
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-
-  static script::javascriptcore::JSCGlobalObject* Create(
-      const scoped_refptr<Window>& global_interface,
-      script::EnvironmentSettings* environment_settings,
-      JSC::JSGlobalData* global_data,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry);
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  JSCWindow(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-      scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory,
-      script::EnvironmentSettings* environment_settings,
-      const scoped_refptr<Window>& impl);
-  ~JSCWindow();
-
- private:
-  class InterfaceObject;
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-
-}  // namespace bindings
-}  // namespace testing
-}  // namespace cobalt
-
-#endif  // JSCWindow_h
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
index 1431c98..99f4334 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
index a8d43f5..d0582d8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
index 3c2595d..b0c6695 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
index 44c9b63..4f4784df 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
index cdc9be8..132b075 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
index 9a99f9a..e410fed 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
index 3be6905..1a096d0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
index 10ac0df..f48c900 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/single_operation_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
index 9cdd93d..6212ba4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -61,24 +61,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
index bcdf5b9..03c4196 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
index 8f70977..1bc6ac8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
index 133af7b..f0e18bd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
index 9f8c0df..b3bd4dd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
index bd6275e..4675e1d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
index 91b1f0a..208da07 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
index ee423a0..0375829 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -61,24 +61,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
index 8a1d44d..69d01c4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 // Declare and define these in the same namespace that the other overloads
 // were brought into with the using declaration.
 void ToJSValue(
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
index bd69c56..225b3e4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -60,24 +60,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
index 57c7eb2..99d0bd4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
index e3fc612..637bd2d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc
index 898f998..af6ac31 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/garbage_collection_test_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
index 0c5b553..000b086 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
index 7c3b03f..008fe1d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
index 84c8d65..9c30841 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
index abefc97..e6eb894 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
index 24c5476..89c25ee 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
index 600a69b..39327ca 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
index 4bac6ac..d94c42e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
index 0cd1892..cc2a0d3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/put_forwards_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
index 2c2c72a..fda94fd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
index 7fcd823..5dc3462 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
index 7744590..c84d0da 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
index 127a4f1..c69246b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
index fd32f75..eee7181 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -34,11 +34,11 @@
 #include "cobalt/bindings/testing/derived_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -71,24 +71,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
index 884fca6..97906a1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
index 93471b0..85d028c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSequenceUser.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsSequenceUser.cc
index 164ed3c..3612c6c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSequenceUser.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSequenceUser.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
index 9c2fe11..083be93 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
@@ -30,11 +30,11 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -63,24 +63,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
index bb8be7c..2f8dbd5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
index 2313691..591fce5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
index 0eae6b1..aa4ccda 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
index c680c08..afd7fcf 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
@@ -28,11 +28,11 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -59,24 +59,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
index 709d054..2c61789 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -32,11 +32,11 @@
 #include "cobalt/bindings/testing/base_interface.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -67,24 +67,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 }  // namespace
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
index 69c6ccb..acb3053 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -120,11 +120,11 @@
 #include "cobalt/bindings/testing/window.h"
 
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -251,24 +251,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 JSObject* DummyFunctor(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   NOTREACHED();
@@ -788,6 +788,7 @@
   MozjsWindow::CreateProxy(
       context, global_interface);
   mozjs_global_environment->SetEnvironmentSettings(environment_settings);
+  mozjs_global_environment->EvaluateAutomatics();
 
   WrapperFactory* wrapper_factory =
       mozjs_global_environment->wrapper_factory();
diff --git a/src/cobalt/bindings/javascriptcore/__init__.py b/src/cobalt/bindings/javascriptcore/__init__.py
deleted file mode 100644
index ef65bee..0000000
--- a/src/cobalt/bindings/javascriptcore/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Required for Python to search this directory for module files
diff --git a/src/cobalt/bindings/javascriptcore/code_generator.py b/src/cobalt/bindings/javascriptcore/code_generator.py
deleted file mode 100644
index 89f3e71..0000000
--- a/src/cobalt/bindings/javascriptcore/code_generator.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""JSC-specific implementation of CodeGeneratorCobalt.
-
-Defines CodeGeneratorJsc and ExpressionGeneratorJsc classes.
-"""
-
-import os
-import sys
-
-# Add the bindings directory to the path.
-module_path, module_filename = os.path.split(os.path.realpath(__file__))
-cobalt_bindings_dir = os.path.normpath(os.path.join(module_path, os.pardir))
-sys.path.append(cobalt_bindings_dir)
-
-from code_generator_cobalt import CodeGeneratorCobalt  # pylint: disable=g-import-not-at-top
-from expression_generator import ExpressionGenerator
-
-TEMPLATES_DIR = os.path.normpath(os.path.join(module_path, 'templates'))
-
-
-def calculate_jsc_lookup_size(num_properties):
-  """Calculate the number of entries to allocate in JSC::Lookup hash table."""
-  # JSC::Lookup uses an array internally to represent hash entries.
-  # The first |size_mask + 1| entries are hash buckets, and the remaining
-  # entries starting from entries[size_mask+1] are used for hash collisions.
-  # In the worst case where all keys collide, we will need
-  # (size_mask +1) + (num_properties - 1) entries, to account for properties[0]
-  # getting assigned to a hash bucket, and the remaining N-1 properties getting
-  # assigned to overflow entries.
-  # TODO: WebKit's bindings generation script calculates the actual
-  # required number of entries by duplicating the JSC::Lookup logic in the
-  # script and determining the number of collisions. If we want to reduce the
-  # number of entries allocated we can do something similar.
-  size_mask = calculate_jsc_lookup_size_mask(num_properties)
-  return (size_mask + 1) + max(0, (num_properties - 1))
-
-
-def calculate_jsc_lookup_size_mask(num_properties):
-  """Calculate the number of hash buckets to use in JSC::Lookup hash table."""
-  # 2 * num_properties is the heuristic used in WebKit's JSC bindings generation
-  # script to determine the number of hash buckets for the property hash table
-  num_hash_buckets = max(1, 2 * num_properties)
-  # JSC::Lookup hash table implementation uses a bitmask of the Identifier's
-  # hash to determine which bucket a Property goes into. This also rounds the
-  # number of buckets up to the closest power of 2.
-  return pow(2, num_hash_buckets.bit_length()) - 1
-
-
-class ExpressionGeneratorJsc(ExpressionGenerator):
-  """Implementation of ExpressionGenerator for JavaScriptCore."""
-
-  def is_undefined(self, arg):
-    return '%s.isUndefined()' % arg
-
-  def is_undefined_or_null(self, arg):
-    return '%s.isUndefinedOrNull()' % arg
-
-  def inherits_interface(self, interface_name, arg):
-    return '%s.inherits(JSC%s::s_classinfo())' % (arg, interface_name)
-
-  def is_number(self, arg):
-    return '%s.isNumber()' % arg
-
-
-class CodeGeneratorJsc(CodeGeneratorCobalt):
-  """Code generator class for JavaScriptCore bindings."""
-
-  _expression_generator = ExpressionGeneratorJsc()
-
-  def __init__(self, interfaces_info, cache_dir, output_dir):
-    CodeGeneratorCobalt.__init__(self, interfaces_info, TEMPLATES_DIR,
-                                 cache_dir, output_dir)
-
-  @property
-  def generated_file_prefix(self):
-    return 'JSC'
-
-  @property
-  def expression_generator(self):
-    return CodeGeneratorJsc._expression_generator
-
-  def build_interface_context(self, interface, interface_info, definitions):
-    """Overrides CodeGeneratorCobalt.build_interface_context."""
-    context = super(CodeGeneratorJsc, self).build_interface_context(
-        interface, interface_info, definitions)
-    jsc_lookup_info = {
-        'calculate_jsc_lookup_size': calculate_jsc_lookup_size,
-        'calculate_jsc_lookup_size_mask': calculate_jsc_lookup_size_mask,
-    }
-    context.update(jsc_lookup_info)
-    return context
diff --git a/src/cobalt/bindings/javascriptcore/idl_compiler.py b/src/cobalt/bindings/javascriptcore/idl_compiler.py
deleted file mode 100644
index 9277e29..0000000
--- a/src/cobalt/bindings/javascriptcore/idl_compiler.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Compile an .idl file to Cobalt JSC bindings (.h and .cpp files).
-
-Calls into idl_compiler_cobalt.shared_main specifying the JavaScriptCore
-CodeGenerator class.
-"""
-
-import os
-import sys
-
-module_path, module_filename = os.path.split(os.path.realpath(__file__))
-bindings_dir = os.path.normpath(os.path.join(module_path, os.pardir))
-sys.path.append(bindings_dir)
-
-from idl_compiler_cobalt import generate_bindings  # pylint: disable=g-import-not-at-top
-from javascriptcore.code_generator import CodeGeneratorJsc
-
-if __name__ == '__main__':
-  sys.exit(generate_bindings(CodeGeneratorJsc))
diff --git a/src/cobalt/bindings/javascriptcore/templates/callback-interface.cc.template b/src/cobalt/bindings/javascriptcore/templates/callback-interface.cc.template
deleted file mode 100644
index 6768199..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/callback-interface.cc.template
+++ /dev/null
@@ -1,118 +0,0 @@
-{#
- # Copyright 2016 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-{% extends "callback-interface-base.cc.template" %}
-{% block includes %}
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-{{ super() }}
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-{% endblock includes %}
-
-{% block using_directives %}
-{{ super() }}
-using cobalt::script::javascriptcore::GetCallableForCallbackInterface;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::util::GetExceptionString;
-{% endblock using_directives %}
-
-{% block implementation %}
-namespace cobalt {
-{% for component in components %}
-namespace {{component}} {
-{% endfor %}
-
-{{binding_class}}::{{binding_class}}(
-    JSC::JSObject* implementing_object)
-    : implementing_object_(implementing_object) { }
-
-{% for operation in operations %}
-{% for overload in operation.overloads %}
-{{overload.type}} {{binding_class}}::{{overload.name}}(
-    const scoped_refptr<script::Wrappable>& callback_this,
-  {% for arg in overload.arguments %}
-    {{arg.arg_type}} {{arg.name}},
-  {% endfor %}
-    bool* had_exception) const {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(implementing_object_->globalObject());
-  JSC::JSGlobalData* global_data = &global_object->globalData();
-  JSC::ExecState* exec_state = global_object->globalExec();
-  JSC::JSLockHolder lock(*global_data);
-
-  // get callable object
-  JSC::JSValue callable;
-  JSC::CallData call_data;
-  JSC::CallType call_type = GetCallableForCallbackInterface(exec_state,
-      implementing_object_, "{{overload.idl_name}}", &callable, &call_data);
-  if (call_type == JSC::CallTypeNone) {
-    // TypeError
-    DLOG(INFO) << "User object was not callable.";
-    *had_exception = true;
-{% if overload.type == 'void' %}
-    return;
-{% else %}
-    return {{overload.type}}();
-{% endif %}
-  }
-
-  JSC::JSValue js_this = ToJSValue(global_object, callback_this);
-
-  // Convert args.
-  JSC::MarkedArgumentBuffer args;
-  {% for arg in overload.arguments %}
-  args.append(ToJSValue(global_object, {{arg.name}}));
-  {% endfor %}
-
-  // call
-  JSC::DynamicGlobalObjectScope global_object_scope(*global_data, global_object);
-  JSC::JSValue js_return_value =
-      JSC::call(exec_state, callable, call_type, call_data, js_this, args);
-  if (exec_state->hadException()) {
-    DLOG(WARNING) << "Exception in callback: "
-                  << GetExceptionString(exec_state);
-    exec_state->clearException();
-    *had_exception = true;
-{% if overload.type == 'void' %}
-    return;
-{% else %}
-    return {{overload.type}}();
-{% endif %}
-  }
-{% if overload.type != 'void' %}
-  JSCExceptionState exception_state(global_object);
-  {{overload.type}} cobalt_return_value;
-  FromJSValue(exec_state, js_return_value, 0, &exception_state, &cobalt_return_value);
-
-  *had_exception = exception_state.is_exception_set();
-  return cobalt_return_value;
-{% else %}
-  *had_exception = false;
-{% endif %}
-}
-{% endfor %}
-{% endfor %}
-
-{% for component in components %}
-}  // namespace {{component}}
-{% endfor %}
-}  // namespace cobalt
-{% endblock implementation %}
diff --git a/src/cobalt/bindings/javascriptcore/templates/callback-interface.h.template b/src/cobalt/bindings/javascriptcore/templates/callback-interface.h.template
deleted file mode 100644
index 3a399c6..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/callback-interface.h.template
+++ /dev/null
@@ -1,65 +0,0 @@
-{#
- # Copyright 2016 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-{% extends "callback-interface-base.h.template" %}
-
-{% block includes %}
-#include "cobalt/script/wrappable.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-{% for include in header_includes %}
-#include "{{include}}"
-{% endfor %}
-{% endblock includes %}
-
-{% block implementation %}
-namespace cobalt {
-{% for component in components %}
-namespace {{component}} {
-{% endfor %}
-
-class {{binding_class}} : public {{impl_class}} {
- public:
-  {{binding_class}}(JSC::JSObject* implementing_object);
-{% for operation in operations %}
-{% for overload in operation.overloads %}
-  {{overload.type}} {{overload.name}}(
-      const scoped_refptr<script::Wrappable>& callback_this,
-    {% for arg in overload.arguments %}
-      {{arg.arg_type}} {{arg.name}},
-    {% endfor %}
-      bool* had_exception) const OVERRIDE;
-{% endfor %}
-{% endfor %}
-  JSC::JSObject* implementing_object() const { return implementing_object_; }
-
- private:
-  JSC::JSObject* implementing_object_;
-};
-
-{% for component in components %}
-}  // namespace {{component}}
-{% endfor %}
-namespace script {
-// Explicit instantiation of CallbackInterfaceTraits struct so we can infer
-// the type of the generated class from the type of the callback interface.
-template<>
-struct CallbackInterfaceTraits<{{fully_qualified_impl_class}}> {
-  typedef {{fully_qualified_binding_class}} JSCCallbackInterfaceClass;
-};
-
-}  // namespace script
-}  // namespace cobalt
-{% endblock implementation %}
diff --git a/src/cobalt/bindings/javascriptcore/templates/interface-object.template b/src/cobalt/bindings/javascriptcore/templates/interface-object.template
deleted file mode 100644
index 325ea41..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/interface-object.template
+++ /dev/null
@@ -1,233 +0,0 @@
-{#
- # Copyright 2016 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-
-{% macro create_interface_object(interface_object_class_name, interface_object_name) -%}
-// Class that defines a JS Object representing this interface's Interface Object
-// https://www.w3.org/TR/WebIDL/#interface-object
-class {{binding_class}}::{{interface_object_class_name}} : public ConstructorBase {
- public:
-  // Get the Interface Object. Will create a new Interface Object if necessary,
-  // otherwise it will return the cached one.
-  static JSC::JSObject* GetInstance(JSC::ExecState* exec);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec,
-                                 JSC::PropertyName property_name,
-                                 JSC::PropertySlot& slot) {
-    {{interface_object_class_name}}* this_object = JSC::jsCast<{{interface_object_class_name}}*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-
-    // Same process as JSC::getStaticPropertySlot<>, which is defined in Lookup.h
-    // Since JSFunction::getOwnPropertySlot is protected, we can't call it from
-    // the helper function.
-    const JSC::HashEntry* entry =
-        GetPropertyTable(exec)->entry(exec, property_name);
-
-    if (!entry) // not found, forward to parent
-      return Base::getOwnPropertySlot(this_object, exec, property_name, slot);
-
-    if (entry->attributes() & JSC::Function)
-        return setUpStaticFunctionSlot(exec, entry, this_object, property_name, slot);
-
-    slot.setCacheableCustom(this_object, entry->propertyGetter());
-    return true;
-  }
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                  JSC::PropertyName property_name, JSC::JSValue value,
-                  JSC::PutPropertySlot& slot) {
-    {{interface_object_class_name}}* this_object = JSC::jsCast<{{interface_object_class_name}}*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-    bool found_property = JSC::lookupPut<{{interface_object_class_name}}>(
-        exec_state, property_name, value, GetPropertyTable(exec_state),
-        this_object, slot.isStrictMode());
-    DLOG_IF(INFO, !found_property) << "Did not find property named " <<
-        WTF::String(property_name.publicName()).utf8().data() <<
-        " to set on interface object for {{binding_class}}";
-    if (!found_property) {
-      BaseClass::put(cell, exec_state, property_name, value, slot);
-    }
-  }
-
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
-{% if not constructor %}
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
-{% endif %}
-
- private:
-  typedef ConstructorBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::ImplementsHasInstance |
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  {{interface_object_class_name}}(JSC::ExecState* exec_state, JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(exec_state, global_object, structure) { }
-  void finishCreation(JSC::ExecState* exec_state,
-                      JSC::NativeExecutable* native_executable, int length,
-                      const String& name);
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue {{binding_class}}::{{interface_object_class_name}}::property_table_values[] = {
-    // static functions will also go here.
-{% for attribute in static_attributes %}
-{% if attribute.conditional %}
-#if defined({{attribute.conditional}})
-{% endif %}
-    { "{{attribute.idl_name}}",
-        JSC::DontDelete {{'| JSC::ReadOnly' if attribute.is_read_only}},
-        reinterpret_cast<intptr_t>(getJS{{attribute.idl_name}}),
-        {% if attribute.is_read_only %}
-        0,
-        {% else %}
-        reinterpret_cast<intptr_t>(setJS{{attribute.idl_name}}),
-        {% endif %}
-        JSC::NoIntrinsic
-    },
-{% if attribute.conditional %}
-#endif  // defined({{attribute.conditional}})
-{% endif %}
-{% endfor %}
-{% for operation in static_operations %}
-{% if operation.conditional %}
-#if defined({{operation.conditional}})
-{% endif %}
-    { "{{operation.idl_name}}",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(staticFunctionJS{{operation.idl_name}}),
-        static_cast<intptr_t>({{operation.length}}),
-        JSC::NoIntrinsic
-    },
-{% if operation.conditional %}
-#endif  // defined({{operation.conditional}})
-{% endif %}
-{% endfor %}
-{% for constant in constants %}
-    { "{{constant.idl_name}}",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJS{{constant.idl_name}}),
-        0,
-        JSC::NoIntrinsic
-    },
-{% endfor %}
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // {{binding_class}}::{{interface_object_class_name}}::property_table_values
-
-// static
-const JSC::HashTable
-{{binding_class}}::{{interface_object_class_name}}::property_table_prototype = {
-{% set num_properties = constants|length + static_attributes|length + static_operations|length %}
-    // Sizes will be calculated based on the number of static functions as well.
-    {{ calculate_jsc_lookup_size(num_properties) }},  // compactSize
-    {{ calculate_jsc_lookup_size_mask(num_properties) }},  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // {{binding_class}}::{{interface_object_class_name}}::property_table_prototype
-
-// static
-const JSC::HashTable*
-{{binding_class}}::{{interface_object_class_name}}::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      {{binding_class}}::{{interface_object_class_name}}::s_classinfo(),
-      property_table_prototype);
-}
-
-const JSC::ClassInfo {{binding_class}}::{{interface_object_class_name}}::s_info = {
-    "{{interface_name}}Constructor",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE({{binding_class}}::{{interface_object_class_name}})
-};  // {{binding_class}}::{{interface_object_class_name}}::s_info
-
-void {{binding_class}}::{{interface_object_class_name}}::finishCreation(
-    JSC::ExecState* exec_state, JSC::NativeExecutable* native_executable,
-    int length, const String& name) {
-  BaseClass::finishCreation(exec_state, native_executable, length, name);
-  ASSERT(inherits(&s_info));
-  // Add a 'prototype' property whose value is the prototype object.
-  putDirect(exec_state->globalData(),
-            exec_state->propertyNames().prototype,
-            {{binding_class}}::GetPrototype(exec_state->lexicalGlobalObject()),
-            JSC::DontDelete | JSC::ReadOnly | JSC::DontEnum);
-  DCHECK(hasOwnProperty(exec_state, JSC::Identifier(exec_state, "prototype")));
-}
-
-// static
-JSC::JSObject* {{binding_class}}::{{interface_object_class_name}}::GetInstance(
-    JSC::ExecState* exec_state) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached interface object, and create a new one if needed.
-  JSC::JSObject* interface_object = global_object->object_cache()->GetCachedConstructor(&s_info);
-  if (interface_object == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSObject* parent_prototype = global_object->functionPrototype();
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-{% if constructor %}
-    const int kNumArguments = {{constructor.length}};
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJS{{impl_class}});
-{% else %}
-    const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
-{% endif %}
-
-    // Create the new interface object.
-    {{interface_object_class_name}}* new_interface_object =
-        new (NotNull, JSC::allocateCell<{{interface_object_class_name}}>(global_data.heap))
-        {{interface_object_class_name}}(exec_state, global_object, structure);
-    new_interface_object->finishCreation(exec_state, executable, kNumArguments, "{{interface_object_name}}");
-    // Add the interface object to the cache.
-    global_object->object_cache()->CacheConstructor(&s_info, new_interface_object);
-    interface_object = new_interface_object;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedConstructor(&s_info), interface_object);
-  return interface_object;
-}
-
-// End of {{binding_class}}::{{interface_object_class_name}} class
-{% endmacro %}
diff --git a/src/cobalt/bindings/javascriptcore/templates/interface.cc.template b/src/cobalt/bindings/javascriptcore/templates/interface.cc.template
deleted file mode 100644
index 4958230..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/interface.cc.template
+++ /dev/null
@@ -1,1126 +0,0 @@
-{#
- # Copyright 2015 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-{% extends "interface-base.cc.template" %}
-{% block includes %}
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-
-{{ super() }}
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-{% if named_property_getter %}
-#include "cobalt/script/javascriptcore/jsc_property_enumerator.h"
-{% endif %}
-#include "cobalt/script/javascriptcore/type_traits.h"
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-{% if is_exception_interface %}
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorPrototype.h"
-{% endif %}
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/FunctionPrototype.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ObjectPrototype.h"
-{% endblock includes %}
-{% block using_directives %}
-{{ super() }}
-using cobalt::script::javascriptcore::kConversionFlagNullable;
-using cobalt::script::javascriptcore::kConversionFlagRestricted;
-using cobalt::script::javascriptcore::kConversionFlagTreatNullAsEmptyString;
-using cobalt::script::javascriptcore::kConversionFlagTreatUndefinedAsEmptyString;
-using cobalt::script::javascriptcore::kNoConversionFlags;
-using cobalt::script::javascriptcore::ConstructorBase;
-using cobalt::script::javascriptcore::GetWrappableOrSetException;
-using cobalt::script::javascriptcore::FromJSValue;
-using cobalt::script::javascriptcore::FromWTFString;
-using cobalt::script::javascriptcore::JSCCallbackFunction;
-using cobalt::script::javascriptcore::JSCCallbackFunctionHolder;
-using cobalt::script::javascriptcore::JSCCallbackInterfaceHolder;
-using cobalt::script::javascriptcore::JSCEngine;
-using cobalt::script::javascriptcore::JSCExceptionState;
-using cobalt::script::javascriptcore::JSCGlobalEnvironment;
-using cobalt::script::javascriptcore::JSCGlobalObject;
-using cobalt::script::javascriptcore::JSCObjectHandle;
-using cobalt::script::javascriptcore::JSCObjectHandleHolder;
-{% if named_property_getter %}
-using cobalt::script::javascriptcore::JSCPropertyEnumerator;
-{% endif %}
-using cobalt::script::javascriptcore::JSObjectToWrappable;
-using cobalt::script::javascriptcore::PrototypeBase;
-using cobalt::script::javascriptcore::ScriptObjectRegistry;
-using cobalt::script::javascriptcore::ThreadLocalHashTable;
-using cobalt::script::javascriptcore::ToJSValue;
-using cobalt::script::javascriptcore::ToWTFString;
-using cobalt::script::javascriptcore::TypeTraits;
-using cobalt::script::javascriptcore::WrapperBase;
-using cobalt::script::javascriptcore::util::HasPropertyOnPrototype;
-using cobalt::script::javascriptcore::util::GetStackTrace;
-{% endblock using_directives %}
-{% block enumeration_declarations %}
-{% if enumerations|length %}
-// Declare and define these in the same namespace that the other overloads
-// were brought into with the using declaration.
-{% for enumeration in enumerations %}
-JSC::JSValue ToJSValue(JSCGlobalObject*, {{impl_class}}::{{enumeration.name}} in_enum);
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-    int conversion_flags, JSCExceptionState* exception_state,
-    {{impl_class}}::{{enumeration.name}}* out_enum);
-{% endfor %}
-{% endif %}
-{% endblock enumeration_declarations %}
-
-{% from 'macros.cc.template' import add_extra_arguments %}
-{% from 'macros.cc.template' import call_function %}
-{% from 'macros.cc.template' import constructor_implementation with context %}
-{% from 'macros.cc.template' import function_implementation with context %}
-{% from 'macros.cc.template' import overload_resolution_implementation with context %}
-{% from 'macros.cc.template' import set_attribute_implementation with context %}
-{% from 'interface-object.template' import create_interface_object with context %}
-
-{% block implementation %}
-namespace {
-{% for constant in constants %}
-JSC::JSValue getJS{{constant.idl_name}}(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-{% endfor %}
-{% for attribute in attributes + static_attributes %}
-{% if attribute.conditional %}
-#if defined({{attribute.conditional}})
-{% endif %}
-JSC::JSValue getJS{{attribute.idl_name}}(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name);
-{% if attribute.has_setter %}
-void setJS{{attribute.idl_name}}(
-    JSC::ExecState* exec,
-    JSC::JSObject* this_object,
-    JSC::JSValue value);
-{% endif %}
-{% if attribute.conditional %}
-#endif  // defined({{attribute.conditional}})
-{% endif %}
-{% endfor %}
-{% if constructor %}
-JSC::EncodedJSValue constructorJS{{impl_class}}(JSC::ExecState*);
-{% for overload in constructor.overloads if constructor.overloads|length > 1 %}
-JSC::EncodedJSValue constructorJS{{impl_class}}{{overload.overload_index}}(JSC::ExecState*);
-{% endfor %}
-{% endif %}
-{% for operation in operations + static_operations %}
-{% if operation.conditional %}
-#if defined({{operation.conditional}})
-{% endif %}
-{% set boundFunctionPrefix = "staticFunctionJS" if operation.is_static else "functionJS" %}
-JSC::EncodedJSValue {{boundFunctionPrefix}}{{operation.idl_name}}(JSC::ExecState*);
-{% for overload in operation.overloads if operation.overloads|length > 1 %}
-JSC::EncodedJSValue {{boundFunctionPrefix}}{{overload.idl_name}}{{overload.overload_index}}(JSC::ExecState*);
-{% endfor %}
-{% if operation.conditional %}
-#endif  // defined({{operation.conditional}})
-{% endif %}
-{% endfor %}
-{% if indexed_property_getter %}
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index);
-{% endif %}
-{% if indexed_property_setter %}
-void IndexedPropertySetter(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value);
-{% endif %}
-{% if stringifier %}
-JSC::EncodedJSValue StringifierJS(JSC::ExecState*);
-{% endif %}
-
-// These are declared unconditionally, but only defined if needed by the
-// interface.
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value);
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name);
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name);
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value);
-
-const bool s_has_named_getter = {{'true' if named_property_getter else 'false'}};
-const bool s_has_named_setter = {{'true' if named_property_setter else 'false'}};
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-const bool s_use_debug_missing_property_handler = {{'true' if not parent_interface else 'false'}};
-#else
-const bool s_use_debug_missing_property_handler = false;
-#endif
-{% if get_opaque_root %}
-scoped_refptr<Wrappable> GetOpaqueRootFromWrappable(
-    const scoped_refptr<Wrappable>& wrappable) {
-  {{impl_class}}* impl =
-      base::polymorphic_downcast<{{impl_class}}*>(wrappable.get());
-  Wrappable* opaque_root = impl->{{get_opaque_root}}();
-  return make_scoped_refptr<Wrappable>(opaque_root);
-}
-{% endif %}
-}  // namespace
-
-{% if has_interface_object %}
-{{create_interface_object("InterfaceObject", impl_class)}}
-{% endif %}
-{% if named_constructor %}
-{{create_interface_object("NamedInterfaceObject", named_constructor)}}
-{% endif %}
-{% include "prototype-object.template" %}
-
-const JSC::HashTableValue {{binding_class}}::property_table_values[] = {
-{% for attribute in attributes %}
-{% if attribute.conditional %}
-#if defined({{attribute.conditional}})
-{% endif %}
-    { "{{attribute.idl_name}}",
-        JSC::DontDelete {{'| JSC::ReadOnly' if not attribute.has_setter}},
-        reinterpret_cast<intptr_t>(getJS{{attribute.idl_name}}),
-        {% if attribute.has_setter %}
-        reinterpret_cast<intptr_t>(setJS{{attribute.idl_name}}),
-        {% else %}
-        0,
-        {% endif %}
-        JSC::NoIntrinsic
-    },
-{% if attribute.conditional %}
-#endif   // defined({{attribute.conditional}})
-{% endif %}
-{% endfor %}
-{% if is_global_interface %}
-{% for operation in operations %}
-{% if operation.conditional %}
-#if defined({{operation.conditional}})
-{% endif %}
-    { "{{operation.idl_name}}",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJS{{operation.idl_name}}),
-        static_cast<intptr_t>({{operation.length}}),
-        JSC::NoIntrinsic
-    },
-{% if operation.conditional %}
-#endif  // defined({{operation.conditional}})
-{% endif %}
-{% endfor %}
-{% endif %}
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // {{binding_class}}::property_table_values
-
-// static
-const JSC::HashTable {{binding_class}}::property_table_prototype = {
-{# This doesn't take into account disabled properties, but this is okay. This
-   value must be at least as large as the number of properties. #}
-{% set num_properties = attributes|length %}
-{% if is_global_interface %}
-{% set num_properties = num_properties + operations|length %}
-{% endif %}
-    {{ calculate_jsc_lookup_size(num_properties) }},  // compactSize
-    {{ calculate_jsc_lookup_size_mask(num_properties) }},  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // {{binding_class}}::property_table_prototype
-
-// static
-const JSC::HashTable* {{binding_class}}::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      {{binding_class}}::s_classinfo(), property_table_prototype);
-}
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-base::LazyInstance<{{binding_class}}::NonTrivialStaticFields>
-    {{binding_class}}::non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-
-const JSC::ClassInfo {{binding_class}}::s_info = {
-    "{{interface_name}}",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE({{binding_class}})
-};  // {{binding_class}}::s_info
-
-// static
-JSC::JSObject* {{binding_class}}::GetPrototype(
-    JSC::JSGlobalObject* global_object) {
-  return Prototype::GetInstance(global_object);
-}
-
-{% if has_interface_object %}
-// static
-JSC::JSObject* {{binding_class}}::GetConstructor(
-    JSC::ExecState* exec_state) {
-  return InterfaceObject::GetInstance(exec_state);
-}
-
-// static
-JSC::JSValue {{binding_class}}::Prototype::GetConstructor(
-      JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name) {
-  return JSC::JSValue(InterfaceObject::GetInstance(exec_state));
-}
-{% endif %}
-{% if named_constructor %}
-JSC::JSObject* {{binding_class}}::GetNamedConstructor(
-    JSC::ExecState* exec_state) {
-  return NamedInterfaceObject::GetInstance(exec_state);
-}
-{% endif %}
-{% if is_global_interface %}
-
-// static
-script::javascriptcore::JSCGlobalObject* {{binding_class}}::Create(
-    const scoped_refptr<{{impl_class}}>& global_interface,
-    script::EnvironmentSettings* environment_settings,
-    JSC::JSGlobalData* global_data,
-    ScriptObjectRegistry* script_object_registry) {
-  scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory =
-      make_scoped_ptr(new script::javascriptcore::WrapperFactory());
-{% for interface in all_interfaces %}
-{% if interface.conditional %}
-#if defined({{interface.conditional}})
-{% endif %}
-  {# Don't register a create method for the global interface, since we do not
-     create a wrapper for it directly. #}
-  {% if interface.name != impl_class %}
-  wrapper_factory->RegisterWrappableType(
-      {{interface.name}}::{{interface.name}}WrappableType(),
-      JSC{{interface.name}}::s_classinfo(),
-      JSC{{interface.name}}::GetCreateWrapperFunction());
-  {% endif %}
-{% if interface.conditional %}
-#endif  // defined({{interface.conditional}})
-{% endif %}
-{% endfor %}
-
-  JSC::JSLockHolder lock(global_data);
-  JSC::Structure* structure = JSC::Structure::create(
-      *global_data,
-      NULL,           // JSC::JSGlobalObject*
-      JSC::jsNull(),  // prototype
-      JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags),
-      &s_info);
-  {{binding_class}}* global_wrapper =
-      new (NotNull, JSC::allocateCell<{{binding_class}}>(global_data->heap))
-      {{binding_class}}(
-          global_data,
-          structure,
-          script_object_registry,
-          wrapper_factory.Pass(),
-          environment_settings,
-          global_interface);
-  global_wrapper->finishCreation(*global_data);
-  global_data->heap.addFinalizer(global_wrapper, {{binding_class}}::destroy);
-  global_wrapper->setPrototype(
-      global_wrapper->globalData(),
-      {{binding_class}}::GetPrototype(global_wrapper));
-
-  return global_wrapper;
-}
-{% else %}
-
-// static
-JSC::JSObject* {{binding_class}}::Create(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) {
-  if (!(wrappable->GetWrappableType() == {{impl_class}}::{{impl_class}}WrappableType())) {
-    NOTREACHED() << "Type of wrappable does not match {{impl_class}}::{{impl_class}}WrappableType()";
-    return NULL;
-  }
-  {{impl_class}}* impl_ptr =
-      base::polymorphic_downcast<{{impl_class}}*>(wrappable.get());
-
-  JSC::JSGlobalData& global_data = global_object->globalData();
-
-  // Get or Create the prototype object for this interface.
-  JSC::JSObject* prototype = Prototype::GetInstance(global_object);
-  DCHECK(prototype);
-
-  JSC::JSLockHolder lock(global_data);
-  // Create a JSC::Structure object for this instance.
-{% if is_exception_interface %}
-  JSC::TypeInfo type_info(JSC::ErrorInstanceType, StructureFlags);
-{% else %}
-  JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-{% endif %}
-  JSC::Structure* structure = JSC::Structure::create(
-      global_data,
-      global_object,
-      JSC::JSValue(prototype),
-      type_info,
-      &s_info);
-
-  // Instantiate a new garbage-collected wrapper object.
-  {{binding_class}}* wrapper =
-      new (NotNull, JSC::allocateCell<{{binding_class}}>(global_data.heap))
-      {{binding_class}}(
-          &global_data,
-          structure,
-          global_object->script_object_registry(),
-          make_scoped_refptr(impl_ptr));
-  wrapper->finishCreation(global_data);
-{% if is_exception_interface %}
-  global_data.heap.addFinalizer(wrapper, destroy);
-{% endif %}
-  return wrapper;
-}
-{% endif %}
-{{binding_class}}::{{binding_class}}(
-    JSC::JSGlobalData* global_data,
-    JSC::Structure* structure,
-    ScriptObjectRegistry* script_object_registry,
-{% if is_global_interface %}
-    scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory,
-    script::EnvironmentSettings* environment_settings,
-{% endif %}
-    const scoped_refptr<{{impl_class}}>& impl)
-    : BaseClass(global_data, structure, script_object_registry, impl{% if is_global_interface %},
-      wrapper_factory.Pass(), environment_settings{% endif %}) {
-{% if get_opaque_root %}
-  set_get_opaque_root_function(base::Bind(&GetOpaqueRootFromWrappable));
-{% endif %}
-}
-
-void {{binding_class}}::finishCreation(JSC::JSGlobalData& global_data) {
-{% if is_exception_interface %}
-  WTF::String error_message = ToWTFString(wrappable()->message());
-  BaseClass::finishCreation(global_data, error_message);
-{% else %}
-  BaseClass::finishCreation(global_data);
-{% endif %}
-  DCHECK(inherits(&s_info));
-}
-
-{{binding_class}}::~{{binding_class}}() {
-  // Empty destructor
-}
-{% if add_opaque_roots %}
-
-void {{binding_class}}::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor) {
-  WrapperBase<JSC::JSDestructibleObject, Wrappable>::visitChildren(
-      cell, visitor);
-
-  JSCGlobalObject* global_object = JSC::jsCast<JSCGlobalObject*>(
-      JSC::jsCast<JSObject*>(cell)->globalObject());
-
-  {{impl_class}}* impl = base::polymorphic_downcast<{{impl_class}}*>(
-      JSC::jsCast<WrapperBase*>(cell)->wrappable().get());
-
-{% for opaque_root in add_opaque_roots %}
-  Wrappable* opaque_root{{loop.index0}} = impl->{{opaque_root}}();
-  if (opaque_root{{loop.index0}}) {
-    visitor.addOpaqueRoot(opaque_root{{loop.index0}});
-  }
-{% endfor %}
-}
-{% endif %}
-
-// Look up property slot for querying property values.
-bool {{binding_class}}::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  {{binding_class}}* this_object = JSC::jsCast<{{binding_class}}*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-{% if is_global_interface %}
-  // Global interface may have both operations and properties as own properties
-  // so we cannot use getStaticValueSlot.
-  bool found_property_slot = JSC::getStaticPropertySlot<{{binding_class}}, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-{% else %}
-  bool found_property_slot = JSC::getStaticValueSlot<{{binding_class}}, BaseClass>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-{% endif %}
-  if (s_has_named_getter || s_use_debug_missing_property_handler) {
-    bool found_property_on_prototype_chain = false;
-    if (!found_property_slot && cell->isObject()) {
-      JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-      if (prototype_value.isObject()) {
-        JSC::JSObject* prototype = JSC::asObject(prototype_value);
-        found_property_on_prototype_chain =
-            prototype->hasProperty(exec, property_name);
-      }
-    }
-    if (s_has_named_getter) {
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        if (QueryNamedProperty(this_object, exec, property_name)) {
-          slot.setCustom(cell, &NamedPropertyGetter);
-          found_property_slot = true;
-        }
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      // The property was not found as an own-property, nor was it found on the
-      // prototype chain, so set the missing property handler to be called
-      // when getting this property value.
-      if (!found_property_slot && !found_property_on_prototype_chain) {
-        slot.setCustom(cell, &OnGetMissingProperty);
-        found_property_slot = true;
-      }
-    }
-  }
-  return found_property_slot;
-}
-{% if indexed_property_getter or named_property_getter %}
-
-// static
-bool {{binding_class}}::getOwnPropertySlotByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::PropertySlot& slot) {
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-{% if indexed_property_getter %}
-  if (index < impl->length()) {
-    slot.setCustomIndex(cell, index, IndexedPropertyGetter);
-    return true;
-  }
-{% endif %}
-  if (s_has_named_getter) {
-    {{binding_class}}* this_object = JSC::jsCast<{{binding_class}}*>(cell);
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property) {
-      if (QueryNamedProperty(this_object, exec_state, property_name)) {
-        slot.setCustom(cell, &NamedPropertyGetter);
-        return true;
-      }
-    }
-  }
-  return Base::getOwnPropertySlotByIndex(cell, exec_state, index, slot);
-}
-
-void {{binding_class}}::getOwnPropertyNames(JSC::JSObject* object,
-    JSC::ExecState* exec_state, JSC::PropertyNameArray& property_names,
-    JSC::EnumerationMode mode) {
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, object);
-  if (impl) {
-{% if indexed_property_getter %}
-    for (uint32 i = 0; i < impl->length(); ++i) {
-      property_names.add(JSC::Identifier::from(exec_state, i));
-    }
-{% endif %}
-{% if named_property_getter %}
-    JSCPropertyEnumerator enumerator(exec_state, &property_names);
-    impl->EnumerateNamedProperties(&enumerator);
-{% endif %}
-    Base::getOwnPropertyNames(object, exec_state, property_names, mode);
-  }
-}
-{% endif %}
-
-// Look up property slot and put the |value|.
-void {{binding_class}}::put(JSC::JSCell* cell, JSC::ExecState* exec,
-    JSC::PropertyName property_name, JSC::JSValue value,
-    JSC::PutPropertySlot& slot) {
-  {{binding_class}}* this_object = JSC::jsCast<{{binding_class}}*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  bool property_handled = false;
-  if (s_has_named_setter || s_use_debug_missing_property_handler) {
-    // Need to look up the property manually.
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec, property_name);
-
-    if (s_has_named_setter) {
-      // We didn't find the property on the object or prototype chain, so
-      // set or create a new named property.
-      if (!has_property) {
-        std::string property_name_utf8 = FromWTFString(property_name.publicName());
-        NamedPropertySetter(cell, exec, property_name, value);
-        property_handled = true;
-      }
-    }
-    if (s_use_debug_missing_property_handler) {
-      if (!has_property && !property_handled) {
-        property_handled = OnSetMissingProperty(cell, exec, property_name, value);
-      }
-    }
-{% if not is_global_interface and not parent_interface %}
-#ifdef __LB_SHELL__FORCE_LOGGING__
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-
-    base::AutoLock lock(non_trivial_static_fields.Get().lock_);
-    base::hash_set<std::string>& properties_warned_about =
-        non_trivial_static_fields.Get().properties_warned_about;
-
-    if (properties_warned_about.find(property_name_utf8) ==
-        properties_warned_about.end()) {
-      properties_warned_about.insert(property_name_utf8);
-      WTF::String class_name = cell->className();
-      DLOG_IF(WARNING, !has_property) << "Did not find property named " <<
-              property_name_utf8 << " to set on wrapper for "
-              << FromWTFString(class_name)
-              << std::endl << StackTraceToString(GetStackTrace(exec, 32))
-              << std::endl;
-    }
-#endif  // __LB_SHELL__FORCE_LOGGING__
-{% endif %}
-  }
-
-  if (!property_handled) {
-    JSC::lookupPut<{{binding_class}}, BaseClass>(
-        exec, property_name, value, GetPropertyTable(exec), this_object, slot);
-  }
-}
-{% if indexed_property_setter or named_property_setter %}
-
-// static
-void {{binding_class}}::putByIndex(JSC::JSCell* cell,
-    JSC::ExecState* exec_state, uint32_t index, JSC::JSValue value,
-    bool should_throw) {
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (impl) {
-    bool property_handled = false;
-{% if indexed_property_setter %}
-    if (index < impl->length()) {
-      IndexedPropertySetter(cell, exec_state, index, value);
-      property_handled = true;
-    }
-{% endif %}
-    if (s_has_named_setter) {
-      if (!property_handled) {
-        JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-        bool has_property = HasOwnPropertyOrPrototypeProperty(
-            cell, exec_state, property_name);
-        if (!has_property) {
-          NamedPropertySetter(cell, exec_state, property_name, value);
-          property_handled = true;
-        }
-      }
-    }
-    if (!property_handled) {
-      Base::putByIndex(cell, exec_state, index, value, should_throw);
-    }
-  }
-}
-
-{% endif %}
-{% if supports_named_properties %}
-
-bool {{binding_class}}::deleteProperty(JSC::JSCell* cell,
-                                       JSC::ExecState* exec_state,
-                                       JSC::PropertyName property_name) {
-  TRACE_EVENT1("{{binding_class}}", "deleteProperty", "property",
-               TRACE_STR_COPY(WTF::String(property_name.publicName()).utf8().data()));
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (impl) {
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deleteProperty(cell, exec_state, property_name);
-  }
-  return false;
-}
-{% endif %}
-{% if supports_named_properties or supports_indexed_properties %}
-
-bool {{binding_class}}::deletePropertyByIndex(JSC::JSCell* cell,
-                                              JSC::ExecState* exec_state,
-                                              uint32_t index) {
-  TRACE_EVENT0("{{binding_class}}", "deletePropertyByIndex");
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (impl) {
-{% if supports_indexed_properties %}
-    // https://heycam.github.io/webidl/#delete
-    // Return true if index is not a supported property index.
-    return index >= impl->length();
-{% elif supports_named_properties %}
-    JSC::PropertyName property_name = JSC::Identifier::from(exec_state, index);
-    bool has_property = HasOwnPropertyOrPrototypeProperty(
-        cell, exec_state, property_name);
-    if (!has_property &&
-        QueryNamedProperty(cell, exec_state, property_name)) {
-      return NamedPropertyDeleter(cell, exec_state, property_name);
-    }
-    return Base::deletePropertyByIndex(cell, exec_state, index);
-{% endif %}
-  }
-  return false;
-}
-{% endif %}
-
-bool {{binding_class}}::HasOwnPropertyOrPrototypeProperty(
-    JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  {{binding_class}}* this_object = JSC::jsCast<{{binding_class}}*>(cell);
-  JSC::PropertySlot lookup_slot;
-  bool has_property = JSC::getStaticPropertySlot<{{binding_class}}, BaseClass>(
-      exec_state, GetPropertyTable(exec_state), this_object, property_name,
-      lookup_slot);
-  return has_property || HasPropertyOnPrototype(exec_state, cell, property_name);
-}
-
-namespace {
-{% for constant in constants %}
-
-JSC::JSValue getJS{{constant.idl_name}}(
-    JSC::ExecState* exec_state, JSC::JSValue, JSC::PropertyName) {
-  TRACE_EVENT0("{{binding_class}}", "get {{constant.idl_name}}");
-{% if constant.can_use_compile_assert %}
-  COMPILE_ASSERT({{impl_class}}::{{constant.name}} == {{constant.value}},
-                 ValueFor{{impl_class}}_{{constant.name}}DoesNotMatchIDL);
-{% else %}
-  DCHECK_EQ({{constant.value}}, {{impl_class}}::{{constant.name}}) <<
-      "The value for {{impl_class}}::{{constant.name}} does not match "
-      "the value in the interface definition.";
-{% endif %}
-  // JSCGlobalObject* is only needed for non-primitive types.
-  return ToJSValue(NULL, {{constant.value}});
-}
-{% endfor %}
-{% for attribute in attributes + static_attributes %}
-
-{% if attribute.conditional %}
-#if defined({{attribute.conditional}})
-{% endif %}
-JSC::JSValue getJS{{attribute.idl_name}}(
-    JSC::ExecState* exec_state,
-    JSC::JSValue slot_base,
-    JSC::PropertyName property_name) {
-  TRACE_EVENT0("{{binding_class}}", "get {{attribute.idl_name}}");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-{% if not attribute.is_static %}
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-{% endif %}
-{% if attribute.raises_exception %}
-  JSCExceptionState exception_state(global_object);
-{% endif %}
-
-{% if attribute.is_named_constructor_attribute %}
-  JSC::JSObject* constructor_object =
-      JSC{{attribute.interface_name}}::GetNamedConstructor(
-          global_object->globalExec());
-  DCHECK(constructor_object)
-      << "NULL constructor returned for {{attribute.interface_name}}.";
-  return JSC::JSValue(constructor_object);
-{% elif attribute.is_constructor_attribute %}
-  JSC::JSObject* constructor_object =
-      JSC{{attribute.interface_name}}::GetConstructor(
-          global_object->globalExec());
-  DCHECK(constructor_object)
-      << "NULL constructor returned for {{attribute.interface_name}}.";
-  return JSC::JSValue(constructor_object);
-{% else %}
-{% call(arguments_list) add_extra_arguments('global_object', [], attribute) %}
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      {{ call_function("impl", impl_class, attribute.getter_function_name, arguments_list, attribute.is_static) -}});
-{% if attribute.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    return JSC::throwError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-  return result;
-{% endcall %}
-{% endif %}
-}
-{% if attribute.has_setter %}
-
-void setJS{{attribute.idl_name}}(
-    JSC::ExecState* exec_state,
-    JSC::JSObject* this_object,
-    JSC::JSValue value) {
-  TRACE_EVENT0("{{binding_class}}", "set {{attribute.idl_name}}");
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-{% if not attribute.is_static %}
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, this_object);
-  if (!impl) {
-    return;
-  }
-{% endif %}
-{{ set_attribute_implementation(attribute, impl_class, "impl") }}
-}
-{% endif %}
-{% if attribute.conditional %}
-#endif  // defined({{attribute.conditional}})
-{% endif %}
-{% endfor %}
-{% if constructor %}
-
-JSC::EncodedJSValue constructorJS{{impl_class}}(JSC::ExecState* exec_state) {
-{% if constructor.overloads|length == 1 %}
-{{constructor_implementation(constructor.overloads[0])}}
-{% else %}
-{{overload_resolution_implementation(constructor, 'constructorJS' + impl_class)}}
-{% endif %}
-}
-{% for overload in constructor.overloads if constructor.overloads|length > 1 %}
-
-JSC::EncodedJSValue constructorJS{{impl_class}}{{overload.overload_index}}(JSC::ExecState* exec_state) {
-{{constructor_implementation(overload)}}
-}
-{% endfor %}
-{% endif %}
-{% for operation in operations + static_operations %}
-{% if operation.conditional %}
-#if defined({{operation.conditional}})
-{% endif %}
-
-{% set boundFunctionPrefix = "staticFunctionJS" if operation.is_static else "functionJS" %}
-JSC::EncodedJSValue {{boundFunctionPrefix}}{{operation.idl_name}}(
-    JSC::ExecState* exec_state) {
-  TRACE_EVENT0("{{binding_class}}", "call {{operation.idl_name}}");
-{% if operation.overloads|length == 1 %}
-{{function_implementation(operation.overloads[0])}}
-{% else %}
-{{overload_resolution_implementation(operation, boundFunctionPrefix + operation.idl_name)}}
-{% endif %}
-}
-{% for overload in operation.overloads if operation.overloads|length > 1 %}
-
-JSC::EncodedJSValue {{boundFunctionPrefix}}{{operation.idl_name}}{{overload.overload_index}}(
-    JSC::ExecState* exec_state) {
-{{function_implementation(overload)}}
-}
-{% endfor %}
-{% if operation.conditional %}
-#endif  // defined({{operation.conditional}})
-{% endif %}
-{% endfor %}
-{% if indexed_property_getter %}
-
-JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, uint32_t index) {
-  TRACE_EVENT0("{{binding_class}}", "IndexedPropertyGetter");
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-{% call(arguments_list)
-    add_extra_arguments('global_object', ['index'], indexed_property_getter) %}
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      {{ call_function("impl", impl_class, indexed_property_getter.name,
-                       arguments_list, False) -}});
-{% if indexed_property_getter.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    return JSC::throwError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-  return result;
-{% endcall %}
-}
-{% endif %}
-{% if indexed_property_setter %}
-
-void IndexedPropertySetter(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, uint32_t index, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("{{binding_class}}", "IndexedPropertySetter");
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  {{indexed_property_setter.type}} value;
-  FromJSValue(exec_state, jsc_value,
-      {{indexed_property_setter.conversion_flags}},
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-{% call(arguments_list) add_extra_arguments(
-    'global_object', ['index', 'value'], indexed_property_setter) %}
-  {{ call_function("impl", impl_class, indexed_property_setter.name,
-                   arguments_list, False) -}};
-{% if indexed_property_setter.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-{% endcall %}
-}
-{% endif %}
-{% if named_property_getter %}
-
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  TRACE_EVENT0("{{binding_class}}", "NamedPropertyGetter");
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, slot_base);
-  if (!impl) {
-    return exec_state->exception();
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-{% call(arguments_list) add_extra_arguments('global_object', ['property_name_utf8'], named_property_getter) %}
-  JSC::JSValue result = ToJSValue(
-      global_object,
-      {{ call_function("impl", impl_class, named_property_getter.name, arguments_list, False) -}});
-{% if named_property_getter.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    return JSC::throwError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-  return result;
-{% endcall %}
-}
-
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (!impl) {
-    return false;
-  }
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  return impl->CanQueryNamedProperty(property_name_utf8);
-}
-{% else %}
-JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool QueryNamedProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-  NOTREACHED();
-  return false;
-}
-{% endif %}
-{% if named_property_setter %}
-
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  TRACE_EVENT0("{{binding_class}}", "NamedPropertySetter");
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (!impl) {
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-
-  std::string property_name_utf8 = FromWTFString(property_name.publicName());
-  {{named_property_setter.type}} value;
-  FromJSValue(exec_state, jsc_value,
-      {{named_property_setter.conversion_flags}},
-      &exception_state, &value);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-{% call(arguments_list) add_extra_arguments(
-    'global_object', ['property_name_utf8', 'value'], named_property_setter) %}
-  {{ call_function(
-      "impl", impl_class, named_property_setter.name, arguments_list, False) -}};
-{% if named_property_setter.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-{% endcall %}
-}
-{% else %}
-void NamedPropertySetter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue jsc_value) {
-  NOTREACHED();
-}
-{% endif %}
-
-bool NamedPropertyDeleter(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name) {
-{% if named_property_deleter %}
-    {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, cell);
-  if (impl) {
-    std::string property_name_utf8 = FromWTFString(property_name.publicName());
-    impl->{{named_property_deleter.name}}(property_name_utf8);
-    return true;
-  }
-{% endif %}
-  return false;
-}
-{% if stringifier %}
-
-JSC::EncodedJSValue StringifierJS(JSC::ExecState* exec_state) {
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  JSC::JSValue result = ToJSValue(global_object, impl->{{stringifier.name}}());
-  return JSC::JSValue::encode(result);
-}
-{% endif %}
-
-#if !defined(COBALT_BUILD_TYPE_GOLD)
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onGetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onGetMissingProperty exists, so call this and
-      // return the result as the value for this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(slot_base);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval;
-    }
-  }
-  return JSC::jsUndefined();
-}
-
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSC::JSValue callable = global_object->get(
-      exec_state, JSC::Identifier(exec_state, "__onSetMissingProperty"));
-  if (!callable.isUndefined()) {
-    JSC::CallData call_data;
-    JSC::CallType call_type = JSC::getCallData(callable, call_data);
-    if (call_type != JSC::CallTypeNone) {
-      // The function called __onSetMissingProperty exists, so call this with
-      // the value to be set. The missing property handler returns true if it
-      // has handled the setting of this property.
-      JSC::MarkedArgumentBuffer args;
-      args.append(cell);
-      args.append(JSC::JSValue(
-              JSC::JSString::create(
-                  global_object->globalData(), property_name.publicName())));
-      args.append(value);
-      JSC::JSValue retval = JSC::call(
-          exec_state, callable, call_type, call_data, global_object, args);
-      return retval.toBoolean(exec_state);
-    }
-  }
-  return false;
-}
-#else
-JSC::JSValue OnGetMissingProperty(JSC::ExecState* exec_state,
-    JSC::JSValue slot_base, JSC::PropertyName property_name) {
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-bool OnSetMissingProperty(JSC::JSCell* cell, JSC::ExecState* exec_state,
-    JSC::PropertyName property_name, JSC::JSValue value) {
-  NOTREACHED();
-  return false;
-}
-#endif
-}  // namespace
-{% endblock implementation %}
-
-{% block create_global_object_impl %}
-  JSCGlobalEnvironment* jsc_global_environment =
-      base::polymorphic_downcast<JSCGlobalEnvironment*>(this);
-  JSCEngine* jsc_engine = jsc_global_environment->engine();
-
-  JSCGlobalObject* global_object = {{binding_class}}::Create(
-      global_interface, environment_settings,
-      jsc_engine->global_data(), jsc_engine->script_object_registry());
-  jsc_global_environment->SetGlobalObject(global_object);
-{% endblock create_global_object_impl %}
-
-{% block enumeration_definitions %}
-{% for enumeration in enumerations %}
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object, {{impl_class}}::{{enumeration.name}} in_enum) {
-  JSC::JSGlobalData* global_data = &(global_object->globalData());
-  switch (in_enum) {
-{% for value, idl_value in enumeration.value_pairs %}
-    case {{impl_class}}::{{value}}: return JSC::jsString(global_data, "{{idl_value}}");
-{% endfor %}
-    default:
-      NOTREACHED();
-      return JSC::jsUndefined();
-  }
-}
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, JSCExceptionState* exception_state,
-                 {{impl_class}}::{{enumeration.name}}* out_enum) {
-  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
-  // JSValue -> IDL enum algorithm described here:
-  // http://heycam.github.io/webidl/#es-enumeration
-
-  // 1. Let S be the result of calling ToString(V).
-  JSC::JSString* js_string = jsvalue.toString(exec_state);
-  if (exec_state->hadException()) {
-    DLOG(WARNING) << "Exception converting value to string";
-    return;
-  }
-  const WTF::String& wtf_string = js_string->tryGetValue();
-  // 3. Return the enumeration value of type E that is equal to S.
-{% for value, idl_value in enumeration.value_pairs %}
-  {{-" else " if not loop.first}}if (wtf_string == "{{idl_value}}") {
-    *out_enum = {{impl_class}}::{{value}};
-  }{% endfor %} else {
-    // 2. If S is not one of E's enumeration values, then throw a TypeError.
-    JSC::throwTypeError(exec_state);
-  }
-}
-{% endfor %}
-{% endblock enumeration_definitions %}
diff --git a/src/cobalt/bindings/javascriptcore/templates/interface.h.template b/src/cobalt/bindings/javascriptcore/templates/interface.h.template
deleted file mode 100644
index 0fb76e8..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/interface.h.template
+++ /dev/null
@@ -1,176 +0,0 @@
-{#
- # Copyright 2015 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-{% extends "interface-base.h.template" %}
-{% block includes %}
-{{ super() }}
-#include "base/threading/thread_local_storage.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-{% if is_exception_interface %}
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorInstance.h"
-{% endif %}
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-{% endblock includes%}
-
-{% block implementation %}
-class {{binding_class}}
-{% if is_global_interface %}
-    : public script::javascriptcore::JSCGlobalObject {
-  typedef script::javascriptcore::JSCGlobalObject BaseClass;
-{% elif is_exception_interface %}
-    : public script::javascriptcore::ExceptionBase {
-  typedef script::javascriptcore::ExceptionBase BaseClass;
-{% elif parent_interface %}
-    : public {{parent_interface}} {
-  typedef {{parent_interface}} BaseClass;
-{% else %}
-    : public script::javascriptcore::InterfaceBase {
-  typedef script::javascriptcore::InterfaceBase BaseClass;
-{% endif %}
- public:
-
-  // Get the prototype object for this wrapper class.
-  static JSC::JSObject* GetPrototype(JSC::JSGlobalObject* global_object);
-{% if has_interface_object %}
-
-  // Get the interface object for this wrapper class.
-  static JSC::JSObject* GetConstructor(JSC::ExecState* exec_state);
-{% endif %}
-{% if named_constructor %}
-
-  // Get the named constructor for this wrapper class.
-  static JSC::JSObject* GetNamedConstructor(JSC::ExecState* exec_state);
-{% endif %}
-
-  // JavaScriptCore functions and members
-
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-{% if indexed_property_getter or named_property_getter %}
-
-  static bool getOwnPropertySlotByIndex(JSC::JSCell* cell,
-                                        JSC::ExecState* exec_state,
-                                        uint32_t index,
-                                        JSC::PropertySlot& slot);
-
-  static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*,
-                                  JSC::PropertyNameArray&,
-                                  JSC::EnumerationMode);
-{% endif %}
-{% if indexed_property_setter or named_property_setter %}
-
-  static void putByIndex(JSC::JSCell* cell, JSC::ExecState* exec_state,
-                         uint32_t index, JSC::JSValue value, bool should_throw);
-{% endif %}
-
-  // static override. Needed to support setting a property.
-  static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName,
-                  JSC::JSValue, JSC::PutPropertySlot&);
-{% if supports_named_properties %}
-
-  static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
-{% endif %}
-{% if supports_indexed_properties or supports_named_properties %}
-
-  static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, uint32_t);
-{% endif %}
-
-  // static override. This function will be called after a new object has
-  // been created.
-  void finishCreation(JSC::JSGlobalData& global_data);
-{% if not is_global_interface %}
-
-  static script::javascriptcore::WrapperFactory::CreateWrapperFunction
-      GetCreateWrapperFunction() {
-    return base::Bind(&Create);
-  }
-
- private:
-  // Create a new wrapper for |wrappable|, which will be cast to {{impl_class}}.
-  static JSC::JSObject* Create(
-      script::javascriptcore::JSCGlobalObject* global_object,
-      const scoped_refptr<script::Wrappable>& wrappable);
-{% else %}
-
-  static script::javascriptcore::JSCGlobalObject* Create(
-      const scoped_refptr<{{impl_class}}>& global_interface,
-      script::EnvironmentSettings* environment_settings,
-      JSC::JSGlobalData* global_data,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry);
-{% endif %}
-
- protected:
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  {{binding_class}}(
-      JSC::JSGlobalData* global_data,
-      JSC::Structure* structure,
-      script::javascriptcore::ScriptObjectRegistry* script_object_registry,
-{% if is_global_interface %}
-      scoped_ptr<script::javascriptcore::WrapperFactory> wrapper_factory,
-      script::EnvironmentSettings* environment_settings,
-{% endif %}
-      const scoped_refptr<{{impl_class}}>& impl);
-  ~{{binding_class}}();
-  {% if add_opaque_roots %}
-
-  static void visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor);
-  {% endif %}
-
- private:
-{% if has_interface_object %}
-  class InterfaceObject;
-{% endif %}
-{% if named_constructor %}
-  class NamedInterfaceObject;
-{% endif %}
-  class Prototype;
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-  static base::LazyInstance<
-      cobalt::script::javascriptcore::ThreadLocalHashTable>
-          thread_local_property_table;
-
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static bool HasOwnPropertyOrPrototypeProperty(JSC::JSCell* cell,
-      JSC::ExecState* exec_state, JSC::PropertyName property_name);
-
-#ifdef __LB_SHELL__FORCE_LOGGING__
-  struct NonTrivialStaticFields {
-    // TODO: Only log attempts of usage of unsupported Web APIs.
-    base::hash_set<std::string> properties_warned_about;
-    base::Lock lock_;
-  };
-  static base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields;
-#endif  // __LB_SHELL__FORCE_LOGGING__
-};
-{% endblock implementation %}
diff --git a/src/cobalt/bindings/javascriptcore/templates/macros.cc.template b/src/cobalt/bindings/javascriptcore/templates/macros.cc.template
deleted file mode 100644
index a3a20fe..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/macros.cc.template
+++ /dev/null
@@ -1,325 +0,0 @@
-{#
- # Extract and marshal arguments that will be passed to a function-like call.
- # Parameters:
- #     operation: An IdlOperation object
- # Passed to caller:
- #     A string that can be used as the parameters for a function call. It will
- #     be either empty, or a comma-separated list of variable names.
- #}
-{% macro extract_arguments(operation) %}
-{% set non_optional_arguments = operation.arguments|rejectattr('is_optional')|rejectattr('is_variadic')|list %}
-{% set optional_arguments = operation.arguments|selectattr('is_optional')|list %}
-{% set num_default_arguments = optional_arguments|rejectattr('default_value', 'none')|list|length %}
-{% set variadic_argument = operation.arguments|last if (operation.arguments|length > 0) and (operation.arguments|last).is_variadic %}
-{% set has_non_default_optional_arguments = optional_arguments|length > num_default_arguments %}
-
-{%- if non_optional_arguments|length > 0 %}
-  const size_t kMinArguments = {{non_optional_arguments|length}};
-  if (exec_state->argumentCount() < kMinArguments) {
-    return JSC::throwVMNotEnoughArgumentsError(exec_state);
-  }
-{% endif -%}
-
-{# Declare variables for all arguments #}
-{% for argument in non_optional_arguments %}
-{% if loop.first %}
-  // Non-optional arguments
-{% endif %}
-  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
-{% endfor %}
-{% for argument in optional_arguments if argument.default_value %}
-{% if loop.first %}
-  // Optional arguments with default values
-{% endif %}
-  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}} =
-      {{argument.default_value}};
-{% endfor %}
-{% for argument in optional_arguments if not argument.default_value %}
-{% if loop.first %}
-  // Optional arguments
-{% endif %}
-  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
-{% endfor %}
-{% if variadic_argument %}
-  // Variadic argument
-  TypeTraits<{{variadic_argument.type}} >::ConversionType {{variadic_argument.name}};
-{% endif -%}
-
-{% for argument in non_optional_arguments %}
-
-  DCHECK_LT({{loop.index0}}, exec_state->argumentCount());
-  FromJSValue(exec_state,
-      exec_state->argument({{loop.index0}}),
-      {{argument.conversion_flags}},
-      &exception_state, &{{argument.name}});
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-{% endfor -%}
-{% for argument in optional_arguments %}
-{% if loop.first %}
-
-  size_t num_set_arguments = {{non_optional_arguments|length + num_default_arguments}};
-{% endif %}
-  if (exec_state->argumentCount() > {{loop.index0 + non_optional_arguments|length}}) {
-    FromJSValue(exec_state,
-        exec_state->argument({{loop.index0 + non_optional_arguments|length}}),
-        {{argument.conversion_flags}},
-        &exception_state,
-        &{{argument.name}});
-    if (exception_state.is_exception_set()) {
-      return JSC::throwVMError(exec_state, exception_state.exception_object());
-    }
-{% if not argument.default_value %}
-    ++num_set_arguments;
-{% endif %}
-  }
-{% endfor %}
-{% if variadic_argument %}
-
-  // Get variadic arguments.
-{% if optional_arguments|length %}
-  const size_t kLastOptionalArgIndex = {{non_optional_arguments|length + optional_arguments|length}};
-  if (num_set_arguments == kLastOptionalArgIndex) {
-    // If the last optional argument has been set, we will call the overload
-    // that takes the variadic argument, possibly with an empty vector in the
-    // case that there are no more arguments left.
-    ++num_set_arguments;
-  }
-{% endif %}
-  const size_t kFirstVariadicArgIndex = {{operation.arguments|length - 1}};
-  if (exec_state->argumentCount() > kFirstVariadicArgIndex) {
-    {{variadic_argument.name}}.resize(exec_state->argumentCount() - kFirstVariadicArgIndex);
-    for (int i = 0; i + kFirstVariadicArgIndex < exec_state->argumentCount(); ++i) {
-      FromJSValue(exec_state,
-          exec_state->argument(i + kFirstVariadicArgIndex),
-          {{variadic_argument.conversion_flags}},
-          &exception_state,
-          &{{variadic_argument.name}}[i]);
-      if (exception_state.is_exception_set()) {
-        return JSC::throwVMError(exec_state, exception_state.exception_object());
-      }
-    }
-  }
-{% endif -%}
-
-{# Call the implementation function, based on the number of set arguments. #}
-{% if has_non_default_optional_arguments %}
-  switch (num_set_arguments) {
-{% for num_arguments in range(non_optional_arguments|length + num_default_arguments, operation.arguments|length + 1) %}
-{# If no variadic arguments have been set, we still call the function with
-   signature that has the variadic argument and pass an empty vector. There is
-   no such function signature that takes the optional parameter immediately
-   preceeding the variadic argument but does not take the variadic arguments. #}
-{% if loop.last or not operation.arguments[num_arguments].is_variadic %}
-{% set function_arguments = operation.arguments[0:num_arguments]|map(attribute='name')|list %}
-    case {{num_arguments}}:
-      {
-        {# whitespace control block #}
-        {{-caller(function_arguments)|indent(8, True)}}
-        break;
-      }
-{% endif %}
-{% endfor %}
-    default:
-      NOTREACHED();
-      return JSC::JSValue::encode(JSC::jsUndefined());
-  }
-{% else %} {#- has_non_default_optional_arguments #}
-{% set function_arguments = operation.arguments|map(attribute='name')|list %}
-  {# whitespace control block #}
-  {{-caller(function_arguments)|indent(2, True)}}
-{% endif %}
-{% endmacro %}
-
-{#
- # Append extra arguments that should be passed to a cobalt function.
- # Specifically, this will prepend parameters specified on IDLs using the
- # [CallWith=] extended attribute.
- # Parameters:
- #     global_object: A C++ expression to retrieve a JSCGlobalObject pointer.
- #     arguments_list: A list of C++ expressions that represent a sequence of
- #         arguments that will be passed to a function.
- #     idl_object: An IDL object that may have the extended attribute that
- #         we are interested in.
- #     is_constructor: True if we are extracting the extended attribute for
- #         a constructor.
- # Passed to caller:
- #     arguments_list, possibly with extra arguments prepended.
- #}
-{% macro add_extra_arguments(global_object, arguments_list, context) %}
-{% set prepend = [] %}
-{% set append = [] %}
-{% if context.call_with %}
-{% set prepend = ['%s->Get%s()'|format(global_object, context.call_with)] %}
-{% endif %}
-{% if context.raises_exception %}
-{% set append = ['&exception_state'] %}
-{% endif %}
-{{caller(prepend + arguments_list + append)}}
-{%- endmacro %}
-
-{#
- # Create an expression to call a member function, which might be static,
- # with the given arguments.
- # Parameters:
- #     this_object: A string that is the name of a C++ variable that is a
- #         pointer to an instance of the implementation class.
- #     class_name: A string that is the name of the C++ implementation class.
- #     function_name: A string that is the name of the function to be called.
- #     arguments_list: A list of C++ expressions that represent a sequence of
- #         arguments that will be passed to a function.
- #     is_static: True if the method is static.
- #}
-{% macro call_function(this_object, class_name, function_name, arguments_list, is_static) %}
-{% if is_static %}
-{{class_name}}::{{function_name}}({{arguments_list|join(', ')}})
-{%- else %}
-{{this_object}}->{{function_name}}({{arguments_list|join(', ')}})
-{%- endif %}
-{%- endmacro %}
-
-{#
- # Function body for operation bindings.
- # Parameters:
- #     operation: The operation context object
- #}
-{% macro function_implementation(operation) %}
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-{% if not operation.is_static %}
-  JSC::JSObject* this_object =
-      exec_state->hostThisValue().toThisObject(exec_state);
-  {{impl_class}}* impl =
-      GetWrappableOrSetException<{{impl_class}}>(exec_state, this_object);
-  if (!impl) {
-    return JSC::JSValue::encode(exec_state->exception());
-  }
-{% endif %}
-
-{% call(arguments_list) extract_arguments(operation) %}
-{% call(arguments_list) add_extra_arguments('global_object', arguments_list, operation) %}
-{{ 'TypeTraits<%s >::ReturnType return_value = '|format(operation.type) if operation.type != 'void'}}
-{{- call_function("impl", impl_class, operation.name, arguments_list, operation.is_static) -}};
-{% if operation.raises_exception %}
-if (exception_state.is_exception_set()) {
-  return JSC::throwVMError(exec_state, exception_state.exception_object());
-}
-{% endif %}
-return JSC::JSValue::encode({{'ToJSValue(global_object, return_value)' if operation.type != 'void' else 'JSC::jsUndefined()'}});
-{% endcall %}
-{% endcall %}
-{%- endmacro %}
-
-{#
- # Function body for constructor bindings.
- # Parameters:
- #     operation: The constructor context object
- #}
-{% macro constructor_implementation(constructor) %}
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-{% call(arguments_list) extract_arguments(constructor) %}
-{% call(arguments_list) add_extra_arguments('global_object', arguments_list, constructor) %}
-  scoped_refptr<{{impl_class}}> new_object =
-      new {{impl_class}}({{arguments_list|join(', ')}});
-{% if constructor.raises_exception %}
-  if (exception_state.is_exception_set()) {
-    return JSC::throwVMError(exec_state, exception_state.exception_object());
-  }
-{% endif %}
-  return JSC::JSValue::encode(ToJSValue(global_object, new_object));
-{% endcall %}
-{% endcall %}
-{%- endmacro %}
-
-{#
- # Function body for overload resolution function.
- # Parameters:
- #     overload_context: The overload context object.
- #     bound_function_prefix: The prefix of the function to be called on
- #         resolution. The overload index will be appended to this.
- #}
-{% macro overload_resolution_implementation(overload_context, bound_function_prefix) %}
-  const size_t num_arguments = exec_state->argumentCount();
-  switch(num_arguments) {
-{% for length, distinguishing_argument_index, resolution_tests in overload_context.overload_resolution_by_length %}
-    case({{length}}): {
-      // Overload resolution algorithm details found here:
-      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-{# In the case there is only one resolution condition, we don't need the arg. #}
-{% if resolution_tests|length > 1 %}
-      JSC::JSValue arg = exec_state->argument({{distinguishing_argument_index}});
-{% endif %}
-{% for test, overload in resolution_tests %}
-      if ({{test("arg")}}) {
-        return {{bound_function_prefix}}{{overload.overload_index}}(exec_state);
-      }
-{% endfor %}
-      break;
-    }
-{% endfor %}
-  }
-  // Invalid number of args
-  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
-  // 4. If S is empty, then throw a TypeError.
-  return JSC::throwVMTypeError(exec_state);
-{%- endmacro %}
-
-{#
- # Function body for setting an attribute value.
- # Parameters:
- #     attribute: The attribute context object.
- #     impl_class: Cobalt class name of the Cobalt implementation of the
- #         interface on which the attribute is a member.
- #     cobalt_impl: Variable name of a pointer to a Cobalt implementation of the
- #         interface on which the attribute is a member.
- #}
-{% macro set_attribute_implementation(attribute, impl_class, cobalt_impl) %}
-{% if attribute.is_constructor_attribute %}
-  NOTIMPLEMENTED() << "Setting constructors not yet supported.";
-{% else %}
-{% if attribute.put_forwards %}
-  {
-    {{attribute.type}} forwarded_{{cobalt_impl}} =
-        {{call_function(cobalt_impl, impl_class, attribute.getter_function_name,
-          arguments_list, attribute.is_static)-}};
-    if (!forwarded_{{cobalt_impl}}) {
-      return;
-    }
-{{ set_attribute_implementation(attribute.put_forwards, attribute.type,
-                                "forwarded_" + cobalt_impl) }}
-  }
-{% else %} {#- if attribute.put_forwards #}
-  TypeTraits<{{attribute.type}} >::ConversionType cobalt_value;
-{% if attribute.is_event_listener %}
-  ToEventListenerAttribute(exec_state, value, {{attribute.conversion_flags}},
-      &exception_state, this_object, &cobalt_value);
-{% else %}
-  FromJSValue(exec_state, value,
-      {{attribute.conversion_flags}}, &exception_state,
-      &cobalt_value);
-{% endif %}
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return;
-  }
-{% call(arguments_list) add_extra_arguments('global_object', ['cobalt_value'],
-                                            attribute) %}
-  // Check if argument conversion raised an exception.
-  if (!exec_state->hadException()) {
-    {{ call_function(cobalt_impl, impl_class, attribute.setter_function_name,
-                     arguments_list, attribute.is_static) -}};
-{% if attribute.raises_exception %}
-    if (exception_state.is_exception_set()) {
-      JSC::throwError(exec_state, exception_state.exception_object());
-    }
-{% endif %}
-  }
-{%- endcall %}
-{% endif %} {#- attribute.put_forwards #}
-{% endif %} {#- attribute.is_constructor_attribute #}
-{%- endmacro %}
-
diff --git a/src/cobalt/bindings/javascriptcore/templates/prototype-object.template b/src/cobalt/bindings/javascriptcore/templates/prototype-object.template
deleted file mode 100644
index 603493f..0000000
--- a/src/cobalt/bindings/javascriptcore/templates/prototype-object.template
+++ /dev/null
@@ -1,179 +0,0 @@
-{#
- # Copyright 2016 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- #     http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #}
-// Class that defines a JS Object representing this interface's prototype
-class {{binding_class}}::Prototype : public PrototypeBase {
- public:
-  // Get the prototype. Will create a new prototype if necessary, otherwise it
-  // will return a cached prototype.
-  static JSC::JSObject* GetInstance(JSC::JSGlobalObject* global_object);
-  DECLARE_CLASSINFO();
-
-  // Needed when JSC::OverridesGetOwnPropertySlot StructureFlag is set
-  // Must be public so that it can be accessible from getStaticValueSlot<>.
-  static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*,
-                                 JSC::PropertyName,
-                                 JSC::PropertySlot&);
-
- private:
-  typedef PrototypeBase BaseClass;
-
-  static const unsigned StructureFlags =
-      JSC::OverridesGetOwnPropertySlot |
-      BaseClass::StructureFlags;
-
-  Prototype(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : BaseClass(global_object, structure) { }
-
-{% if has_interface_object %}
-  static JSC::JSValue GetConstructor(JSC::ExecState* exec_state,
-      JSC::JSValue slot_base,
-      JSC::PropertyName property_name);
-{% endif %}
-  static const JSC::HashTable* GetPropertyTable(JSC::ExecState* exec_state);
-
-  static const JSC::HashTableValue property_table_values[];
-  static const JSC::HashTable property_table_prototype;
-};
-
-const JSC::HashTableValue {{binding_class}}::Prototype::property_table_values[] = {
-{% for operation in operations if not is_global_interface %}
-{% if operation.conditional %}
-#if defined({{operation.conditional}})
-{% endif %}
-    { "{{operation.idl_name}}",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(functionJS{{operation.idl_name}}),
-        static_cast<intptr_t>({{operation.length}}),
-        JSC::NoIntrinsic
-    },
-{% if operation.conditional %}
-#endif  // defined({{operation.conditional}})
-{% endif %}
-{% endfor %}
-{% if stringifier %}
-    { "toString",
-        JSC::DontDelete | JSC::Function,
-        reinterpret_cast<intptr_t>(StringifierJS),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-{% endif %}
-{% for constant in constants %}
-    { "{{constant.idl_name}}",
-        JSC::DontDelete | JSC::ReadOnly,
-        reinterpret_cast<intptr_t>(getJS{{constant.idl_name}}),
-        0,
-        JSC::NoIntrinsic
-    },
-{% endfor %}
-{% if has_interface_object %}
-    { "constructor",
-        JSC::DontDelete | JSC::DontEnum,
-        reinterpret_cast<intptr_t>({{binding_class}}::Prototype::GetConstructor),
-        static_cast<intptr_t>(0),
-        JSC::NoIntrinsic
-    },
-{% endif %}
-    { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
-};  // {{binding_class}}::Prototype::property_table_values
-
-// static
-const JSC::HashTable {{binding_class}}::Prototype::property_table_prototype = {
-{% set num_prototype_properties = constants|length %}
-{% if not is_global_interface %}
-{% set num_prototype_properties = num_prototype_properties + operations|length %}
-{% endif %}
-{% if has_interface_object %}
-{% set num_prototype_properties = num_prototype_properties + 1 %}
-{% endif %}
-{% if stringifier %}
-{% set num_prototype_properties = num_prototype_properties + 1 %}
-{% endif %}
-    {{ calculate_jsc_lookup_size(num_prototype_properties) }},  // compactSize
-    {{ calculate_jsc_lookup_size_mask(num_prototype_properties) }},  // compactSizeMask
-    property_table_values,
-    NULL  // table allocated at runtime
-};  // {{binding_class}}::Prototype::property_table_prototype
-
-// static
-const JSC::HashTable* {{binding_class}}::Prototype::GetPropertyTable(
-    JSC::ExecState* exec_state) {
-  return ThreadLocalHashTable::GetInstance()->GetHashTable(
-      {{binding_class}}::Prototype::s_classinfo(), property_table_prototype);
-}
-
-const JSC::ClassInfo {{binding_class}}::Prototype::s_info = {
-    "{{interface_name}}Prototype",  // className
-    BaseClass::s_classinfo(),  // parentClass
-    NULL,  // static hash-table of properties (not used)
-    GetPropertyTable,  // function pointer to get hash-table of properties
-    CREATE_METHOD_TABLE({{binding_class}}::Prototype)
-};  // {{binding_class}}::Prototype::s_info
-
-// Look up property slot for querying property values.
-bool {{binding_class}}::Prototype::getOwnPropertySlot(JSC::JSCell* cell,
-    JSC::ExecState* exec, JSC::PropertyName property_name,
-    JSC::PropertySlot& slot) {
-  Prototype* this_object = JSC::jsCast<Prototype*>(cell);
-  ASSERT_GC_OBJECT_INHERITS(this_object, &s_info);
-  return JSC::getStaticPropertySlot<Prototype, JSC::JSObject>(
-      exec, GetPropertyTable(exec), this_object, property_name, slot);
-}
-
-// static
-JSC::JSObject* {{binding_class}}::Prototype::GetInstance(
-    JSC::JSGlobalObject* base_global_object) {
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalObject*>(base_global_object);
-  ASSERT_GC_OBJECT_INHERITS(global_object, JSCGlobalObject::s_classinfo());
-
-  // Try to get the cached prototype, and create a new one if needed.
-  JSC::JSObject* prototype = global_object->object_cache()->GetCachedPrototype(&s_info);
-  if (prototype == NULL) {
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSLockHolder lock(&global_data);
-
-{% if parent_interface %}
-    JSC::JSObject* parent_prototype =
-        {{parent_interface}}::GetPrototype(global_object);
-{% elif is_exception_interface %}
-    JSC::JSObject* parent_prototype = global_object->errorPrototype();
-{% else %}
-    JSC::JSObject* parent_prototype = global_object->objectPrototype();
-{% endif %}
-    JSC::TypeInfo type_info(JSC::ObjectType, StructureFlags);
-    JSC::Structure* structure = JSC::Structure::create(
-        global_data,
-        global_object,
-        JSC::JSValue(parent_prototype),
-        type_info,
-        &s_info);
-
-    // Create the new prototype object.
-    Prototype* new_prototype =
-        new (NotNull, JSC::allocateCell<Prototype>(
-            global_data.heap))
-        Prototype(global_object, structure);
-    new_prototype->finishCreation(global_data);
-    // Add the prototype to the cache.
-    global_object->object_cache()->CachePrototype(&s_info, new_prototype);
-    prototype = new_prototype;
-  }
-  DCHECK_EQ(global_object->object_cache()->GetCachedPrototype(&s_info), prototype);
-  return prototype;
-}
-
-// End of {{binding_class}}::Prototype class
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template
index 90ed015..06c23c3 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -27,11 +27,11 @@
 {% block includes %}
 {{ super() }}
 #include "base/lazy_instance.h"
-#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/exception_state.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
-#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_property_enumerator.h"
@@ -53,24 +53,24 @@
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::ExceptionState;
+using cobalt::script::Wrappable;
 using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::InterfaceData;
+using cobalt::script::mozjs::MozjsCallbackFunction;
+using cobalt::script::mozjs::MozjsExceptionState;
+using cobalt::script::mozjs::MozjsGlobalEnvironment;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::ProxyHandler;
+using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::TypeTraits;
+using cobalt::script::mozjs::WrapperFactory;
+using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
 using cobalt::script::mozjs::kNoConversionFlags;
-using cobalt::script::mozjs::InterfaceData;
-using cobalt::script::mozjs::MozjsCallbackFunction;
-using cobalt::script::mozjs::MozjsExceptionState;
-using cobalt::script::mozjs::MozjsGlobalEnvironment;
-using cobalt::script::mozjs::MozjsUserObjectHolder;
-using cobalt::script::mozjs::MozjsPropertyEnumerator;
-using cobalt::script::mozjs::ProxyHandler;
-using cobalt::script::mozjs::ToJSValue;
-using cobalt::script::mozjs::TypeTraits;
-using cobalt::script::mozjs::WrapperPrivate;
-using cobalt::script::mozjs::WrapperFactory;
-using cobalt::script::Wrappable;
 {% endblock using_directives %}
 {% block enumeration_declarations %}
 {% if enumerations|length %}
@@ -945,6 +945,7 @@
   {{binding_class}}::CreateProxy(
       context, global_interface);
   mozjs_global_environment->SetEnvironmentSettings(environment_settings);
+  mozjs_global_environment->EvaluateAutomatics();
 
   WrapperFactory* wrapper_factory =
       mozjs_global_environment->wrapper_factory();
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.bat b/src/cobalt/bindings/run_cobalt_bindings_tests.bat
index e26fc8d..2df4a48 100644
--- a/src/cobalt/bindings/run_cobalt_bindings_tests.bat
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.bat
@@ -14,5 +14,4 @@
 @rem limitations under the License.
 @rem
 
-@python run_cobalt_bindings_tests.py jsc %*
 @python run_cobalt_bindings_tests.py mozjs %*
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.py b/src/cobalt/bindings/run_cobalt_bindings_tests.py
index 4aa69b8..a364191 100644
--- a/src/cobalt/bindings/run_cobalt_bindings_tests.py
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.py
@@ -37,7 +37,6 @@
 # Add cobalt's bindings generation scripts to the path.
 sys.path.append(cobalt_bindings_dir)
 from idl_compiler_cobalt import IdlCompilerCobalt  # pylint: disable=g-import-not-at-top
-from javascriptcore.code_generator import CodeGeneratorJsc
 from mozjs.code_generator import CodeGeneratorMozjs
 CodeGeneratorMozjs45 = __import__(  # pylint: disable=invalid-name
     'mozjs-45.code_generator').code_generator.CodeGeneratorMozjs
@@ -54,9 +53,7 @@
   parser.add_argument('engine')
   args = parser.parse_args(argv[1:])
 
-  if args.engine.lower() == 'jsc':
-    generator = CodeGeneratorJsc
-  elif args.engine.lower() == 'mozjs':
+  if args.engine.lower() == 'mozjs':
     generator = CodeGeneratorMozjs
   elif args.engine.lower() == 'mozjs-45':
     generator = CodeGeneratorMozjs45
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.sh b/src/cobalt/bindings/run_cobalt_bindings_tests.sh
index 3cce2da..12ff255 100755
--- a/src/cobalt/bindings/run_cobalt_bindings_tests.sh
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.sh
@@ -19,6 +19,5 @@
 # Ensure we are in the bindings directory.
 cd "$(dirname "${BASH_SOURCE[0]}")"
 
-python run_cobalt_bindings_tests.py jsc "$@"
 python run_cobalt_bindings_tests.py mozjs "$@"
 python run_cobalt_bindings_tests.py mozjs-45 "$@"
diff --git a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp b/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp
deleted file mode 100644
index bb7227e..0000000
--- a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp
+++ /dev/null
@@ -1,46 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SequenceUser.idl
-SingleOperationInterface.idl
-StaticPropertiesInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
-UnsupportedInterface.idl
diff --git a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp b/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp
deleted file mode 100644
index 3b0f3da..0000000
--- a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp
+++ /dev/null
@@ -1,45 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SequenceUser.idl
-SingleOperationInterface.idl
-StaticPropertiesInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
diff --git a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp
deleted file mode 100644
index ea6cdb9..0000000
--- a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp
+++ /dev/null
@@ -1,49 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SequenceUser.idl
-SingleOperationInterface.idl
-StaticPropertiesInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
-ImplementedInterface.idl
-PartialInterface.idl
-InterfaceWithUnsupportedProperties_partial.idl
-UnsupportedInterface.idl
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 765ee14..0f6eb18 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -260,7 +260,9 @@
 const char kYouTubeTvLocationPolicy[] =
     "h5vcc-location-src "
     "https://www.youtube.com/tv "
+    "https://www.youtube.com/tv/ "
     "https://web-release-qa.youtube.com/tv "
+    "https://web-release-qa.youtube.com/tv/ "
 #if defined(ENABLE_ABOUT_SCHEME)
     "about: "
 #endif
diff --git a/src/cobalt/browser/browser.gyp b/src/cobalt/browser/browser.gyp
index c544756..755d85f 100644
--- a/src/cobalt/browser/browser.gyp
+++ b/src/cobalt/browser/browser.gyp
@@ -58,6 +58,7 @@
         'COBALT_IMAGE_CACHE_SIZE_IN_BYTES=<(image_cache_size_in_bytes)',
         'COBALT_REMOTE_TYPEFACE_CACHE_SIZE_IN_BYTES=<(remote_typeface_cache_size_in_bytes)',
         'COBALT_IMAGE_CACHE_CAPACITY_MULTIPLIER_WHEN_PLAYING_VIDEO=<(image_cache_capacity_multiplier_when_playing_video)',
+        'COBALT_MESH_CACHE_SIZE_IN_BYTES=<(mesh_cache_size_in_bytes)',
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/accessibility/accessibility.gyp:accessibility',
diff --git a/src/cobalt/browser/browser_bindings.gyp b/src/cobalt/browser/browser_bindings.gyp
index 5d6e627..802b803 100644
--- a/src/cobalt/browser/browser_bindings.gyp
+++ b/src/cobalt/browser/browser_bindings.gyp
@@ -163,6 +163,7 @@
         '../h5vcc/H5vccSettings.idl',
         '../h5vcc/H5vccStorage.idl',
         '../h5vcc/H5vccSystem.idl',
+        '../h5vcc/H5vccTraceEvent.idl',
 
         '../speech/SpeechRecognition.idl',
         '../speech/SpeechRecognitionAlternative.idl',
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index d14f425..1bcdc3c 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -514,7 +514,7 @@
   }
 
 #if defined(ENABLE_DEBUG_CONSOLE)
-  trace_manager.OnKeyEventProduced();
+  trace_manager_.OnKeyEventProduced();
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
 
   InjectKeyEventToMainWebModule(event);
@@ -642,6 +642,9 @@
       FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
                             base::Unretained(&got_window_driver)));
   got_window_driver.Wait();
+  // This log is relied on by the webdriver benchmark tests, so it shouldn't be
+  // changed unless the corresponding benchmark logic is changed as well.
+  LOG(INFO) << "Created WindowDriver: ID=" << window_id.id();
   DCHECK(window_driver);
   return window_driver.Pass();
 }
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 82322b3..e275d55 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -299,7 +299,7 @@
   // Manages a second web module to implement the debug console.
   scoped_ptr<DebugConsole> debug_console_;
 
-  TraceManager trace_manager;
+  TraceManager trace_manager_;
 
   // Command handler object for toggling the input fuzzer on/off.
   base::ConsoleCommandManager::CommandHandler fuzzer_toggle_command_handler_;
diff --git a/src/cobalt/browser/debug_console/debug_console.js b/src/cobalt/browser/debug_console/debug_console.js
index 7c2f8a5..6f56962 100644
--- a/src/cobalt/browser/debug_console/debug_console.js
+++ b/src/cobalt/browser/debug_console/debug_console.js
@@ -32,6 +32,44 @@
 // Number of animation frame samples since the last update.
 var animationFrameSamples = 0;
 
+// Map of 'Unidentified' additional Cobalt keyCodes to equivalent keys.
+var unidentifiedCobaltKeyMap = {
+  // kSbKeyGamepad1
+  0x8000: 'Enter',
+  // kSbKeyGamepad2
+  0x8001: 'Esc',
+  // kSbKeyGamepad3
+  0x8002: 'Home',
+  // kSbKeyGamepad5
+  0x8008: 'Enter',
+  // kSbKeyGamepad6
+  0x8009: 'Enter',
+  // kSbKeyGamepadDPadUp
+  0x800C: 'ArrowUp',
+  // kSbKeyGamepadDPadDown
+  0x800D: 'ArrowDown',
+  // kSbKeyGamepadDPadLeft
+  0x800E: 'ArrowLeft',
+  // kSbKeyGamepadDPadRight
+  0x800F: 'ArrowRight',
+  // kSbKeyGamepadLeftStickUp
+  0x8011: 'ArrowUp',
+  // kSbKeyGamepadLeftStickDown
+  0x8012: 'ArrowDown',
+  // kSbKeyGamepadLeftStickLeft
+  0x8013: 'ArrowLeft',
+  // kSbKeyGamepadLeftStickRight
+  0x8014: 'ArrowRight',
+  // kSbKeyGamepadRightStickUp
+  0x8015: 'ArrowUp',
+  // kSbKeyGamepadRightStickDown
+  0x8016: 'ArrowDown',
+  // kSbKeyGamepadRightStickLeft
+  0x8017: 'ArrowLeft',
+  // kSbKeyGamepadRightStickRight
+  0x8018: 'ArrowRight'
+};
+
 function createMessageLog() {
   var messageContainer = document.getElementById('messageContainer');
   messageLog = new MessageLog(messageContainer);
@@ -195,6 +233,10 @@
 
 function onKeydown(event) {
   var key = event.key;
+  if (key == 'Unidentified') {
+    key = unidentifiedCobaltKeyMap[event.keyCode] || 'Unidentified';
+  }
+
   if (key == 'ArrowLeft') {
     commandInput.moveCursor(-1);
   } else if (key == 'ArrowRight') {
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
deleted file mode 100644
index b50619f..0000000
--- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
+++ /dev/null
@@ -1,149 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSS.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MemoryInfo.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../webdriver/ScriptExecutorParams.idl
-../webdriver/ScriptExecutorResult.idl
-../websocket/WebSocket.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp
deleted file mode 100644
index b50619f..0000000
--- a/src/cobalt/browser/global_objects_idl_files_list.tmp
+++ /dev/null
@@ -1,149 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSS.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MemoryInfo.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../webdriver/ScriptExecutorParams.idl
-../webdriver/ScriptExecutorResult.idl
-../websocket/WebSocket.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
deleted file mode 100644
index a9c6e86..0000000
--- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
+++ /dev/null
@@ -1,176 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSS.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MemoryInfo.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../webdriver/ScriptExecutorParams.idl
-../webdriver/ScriptExecutorResult.idl
-../websocket/WebSocket.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
-../cssom/LinkStyle.idl
-../dom/Document_CSSOM.idl
-../dom/Document_HTML5.idl
-../dom/Document_WebAnimationsAPI.idl
-../dom/Element_CSSOMView.idl
-../dom/Element_DOMParsingAndSerialization.idl
-../dom/ElementCSSInlineStyle.idl
-../dom/GlobalCrypto.idl
-../dom/GlobalEventHandlers.idl
-../dom/HTMLElement_CSSOMView.idl
-../dom/NavigatorID.idl
-../dom/NavigatorLanguage.idl
-../dom/NavigatorPlugins.idl
-../dom/NavigatorStorageUtils.idl
-../dom/NonDocumentTypeChildNode.idl
-../dom/NonElementParentNode.idl
-../dom/ParentNode.idl
-../dom/Performance_HighResolutionTime.idl
-../dom/URLUtils.idl
-../dom/Window_AnimationTiming.idl
-../dom/Window_CSSOM.idl
-../dom/Window_CSSOMView.idl
-../dom/Window_Performance.idl
-../dom/WindowEventHandlers.idl
-../dom/WindowLocalStorage.idl
-../dom/WindowSessionStorage.idl
-../dom/WindowTimers.idl
diff --git a/src/cobalt/browser/memory_tracker/memory_tracker_tool_impl.cc b/src/cobalt/browser/memory_tracker/memory_tracker_tool_impl.cc
index cc317ea..91b34f3 100644
--- a/src/cobalt/browser/memory_tracker/memory_tracker_tool_impl.cc
+++ b/src/cobalt/browser/memory_tracker/memory_tracker_tool_impl.cc
@@ -126,6 +126,24 @@
   return s;
 }
 
+// Removes odd elements and resizes vector.
+template <typename VectorType>
+void RemoveOddElements(VectorType* v) {
+  typedef typename VectorType::iterator iterator;
+
+  iterator read_it = v->end();
+  iterator write_it = v->end();
+  for (size_t i = 0; i*2 < v->size(); ++i) {
+    write_it = v->begin() + i;
+    read_it = v->begin() + (i*2);
+    *write_it = *read_it;
+  }
+  if (write_it != v->end()) {
+    write_it++;
+  }
+  v->erase(write_it, v->end());
+}
+
 // NoMemoryTracking will disable memory tracking while in the current scope of
 // execution. When the object is destroyed it will reset the previous state
 // of allocation tracking.
@@ -191,8 +209,8 @@
   }
   std::string TimeInMinutesString() const {
     base::TimeDelta delta_t = time_since_start();
-    int64 seconds = delta_t.InSeconds();
-    float time_mins = static_cast<float>(seconds) / 60.f;
+    float seconds = static_cast<float>(delta_t.InMilliseconds()) / 1000.0f;
+    float time_mins = seconds / 60.f;
     std::stringstream ss;
 
     ss << time_mins;
@@ -662,7 +680,7 @@
      << "// to be used in a stacked graph." << kNewLine;
 
   // HEADER.
-  ss << "Time(mins),";
+  ss << kQuote << "Time(mins)" << kQuote << kDelimiter;
   for (MapIt it = samples.begin(); it != samples.end(); ++it) {
     const std::string& name = it->first;
     ss << kQuote << SanitizeCSVKey(name) << kQuote << kDelimiter;
@@ -672,7 +690,8 @@
   // Print out the values of each of the samples.
   for (size_t i = 0; i < smallest_sample_size; ++i) {
     // Output time first so that it can be used as an x-axis.
-    const double time_mins = timeseries.time_stamps_[i].InSeconds()/60.f;
+    const double time_mins =
+        timeseries.time_stamps_[i].InMilliseconds() / (1000. * 60.);
     ss << time_mins << ",";
     for (MapIt it = samples.begin(); it != samples.end(); ++it) {
       const int64 alloc_bytes = it->second.allocated_bytes_[i];
@@ -692,7 +711,7 @@
   ss << kNewLine << "// CSV of COUNT of allocations per region." << kNewLine;
 
   // HEADER
-  ss << "Time(mins),";
+  ss << kQuote << "Time(mins)" << kQuote << kDelimiter;
   for (MapIt it = samples.begin(); it != samples.end(); ++it) {
     const std::string& name = it->first;
     ss << kQuote << SanitizeCSVKey(name) << kQuote << kDelimiter;
@@ -700,7 +719,8 @@
   ss << kNewLine;
   for (size_t i = 0; i < smallest_sample_size; ++i) {
     // Output time first so that it can be used as an x-axis.
-    const double time_mins = timeseries.time_stamps_[i].InSeconds() / 60.f;
+    const double time_mins =
+        timeseries.time_stamps_[i].InMilliseconds() / (1000. * 60.);
     ss << time_mins << ",";
     for (MapIt it = samples.begin(); it != samples.end(); ++it) {
       const int64 n_allocs = it->second.number_allocations_[i];
@@ -710,6 +730,7 @@
   }
   ss << "// END CSV of COUNT of allocations per region." << kNewLine;
   ss << "//////////////////////////////////////////////";
+  ss << kNewLine;
 
   std::string output = ss.str();
   return output;
@@ -720,6 +741,7 @@
     const base::TimeDelta& time_now) {
   const size_t sample_count = timeseries->time_stamps_.size();
   timeseries->time_stamps_.push_back(time_now);
+
   MapAllocationSamples& map_samples = timeseries->samples_;
 
   std::vector<const AllocationGroup*> vector_output;
@@ -780,11 +802,11 @@
 void MemoryTrackerCompressedTimeSeries::Compress(TimeSeries* timeseries) {
   typedef MapAllocationSamples::iterator MapIt;
   MapAllocationSamples& samples = timeseries->samples_;
-  DoCompression(&(timeseries->time_stamps_));
+  RemoveOddElements(&(timeseries->time_stamps_));
   for (MapIt it = samples.begin(); it != samples.end(); ++it) {
     AllocationSamples& data = it->second;
-    DoCompression(&data.allocated_bytes_);
-    DoCompression(&data.number_allocations_);
+    RemoveOddElements(&data.allocated_bytes_);
+    RemoveOddElements(&data.number_allocations_);
   }
 }
 
diff --git a/src/cobalt/browser/trace_manager.h b/src/cobalt/browser/trace_manager.h
index 2fc4dc6..8ace7b8 100644
--- a/src/cobalt/browser/trace_manager.h
+++ b/src/cobalt/browser/trace_manager.h
@@ -28,6 +28,7 @@
 namespace cobalt {
 namespace browser {
 
+// Wrapper class which wraps all trace related stuff.
 class TraceManager {
  public:
   // Returns whether there's a trace that is active.
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 572200d..e1ab7dc 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -229,6 +229,9 @@
   // from URLs.
   scoped_ptr<loader::font::RemoteTypefaceCache> remote_typeface_cache_;
 
+  // MeshCache that is used to manage mesh cache logic.
+  scoped_ptr<loader::mesh::MeshCache> mesh_cache_;
+
   // Interface between LocalStorage and the Storage Manager.
   scoped_ptr<dom::LocalStorageDatabase> local_storage_database_;
 
@@ -386,6 +389,13 @@
       loader_factory_.get());
   DCHECK(remote_typeface_cache_);
 
+  DCHECK_LE(0, data.options.mesh_cache_capacity);
+  mesh_cache_ = loader::mesh::CreateMeshCache(
+      base::StringPrintf("%s.MeshCache", name_.c_str()),
+      static_cast<uint32>(data.options.mesh_cache_capacity),
+      loader_factory_.get());
+  DCHECK(mesh_cache_);
+
   local_storage_database_.reset(
       new dom::LocalStorageDatabase(data.network_module->storage_manager()));
   DCHECK(local_storage_database_);
@@ -420,8 +430,8 @@
       css_parser_.get(), dom_parser_.get(), fetcher_factory_.get(),
       &resource_provider_, image_cache_.get(),
       reduced_image_cache_capacity_manager_.get(), remote_typeface_cache_.get(),
-      local_storage_database_.get(), data.media_module, data.media_module,
-      execution_state_.get(), script_runner_.get(),
+      mesh_cache_.get(), local_storage_database_.get(), data.media_module,
+      data.media_module, execution_state_.get(), script_runner_.get(),
       media_source_registry_.get(),
       web_module_stat_tracker_->dom_stat_tracker(), data.initial_url,
       data.network_module->GetUserAgent(),
@@ -543,6 +553,7 @@
   javascript_engine_.reset();
   web_module_stat_tracker_.reset();
   local_storage_database_.reset();
+  mesh_cache_.reset();
   remote_typeface_cache_.reset();
   image_cache_.reset();
   fetcher_factory_.reset();
@@ -746,6 +757,7 @@
       image_cache_capacity(COBALT_IMAGE_CACHE_SIZE_IN_BYTES),
       remote_typeface_cache_capacity(
           COBALT_REMOTE_TYPEFACE_CACHE_SIZE_IN_BYTES),
+      mesh_cache_capacity(COBALT_MESH_CACHE_SIZE_IN_BYTES),
       csp_enforcement_mode(dom::kCspEnforcementEnable),
       csp_insecure_allowed_token(0),
       track_event_stats(false),
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 2307e89..dfeb9dc 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -122,12 +122,15 @@
     // can't be changed from the whitelisted origins.
     std::string location_policy;
 
-    // Image cache capaticy in bytes.
+    // Image cache capacity in bytes.
     int image_cache_capacity;
 
     // Typeface cache capacity in bytes.
     int remote_typeface_cache_capacity;
 
+    // Mesh cache capacity in bytes.
+    int mesh_cache_capacity;
+
     // Content Security Policy enforcement mode for this web module.
     dom::CspEnforcementType csp_enforcement_mode;
 
diff --git a/src/cobalt/browser/web_module_stat_tracker.cc b/src/cobalt/browser/web_module_stat_tracker.cc
index 06323fa..64b999f 100644
--- a/src/cobalt/browser/web_module_stat_tracker.cc
+++ b/src/cobalt/browser/web_module_stat_tracker.cc
@@ -129,6 +129,16 @@
           StringPrintf("Event.Count.%s.DOM.HtmlElement.UpdateComputedStyle",
                        name.c_str()),
           0, "Number of update computed styles for HTML elements."),
+      count_dom_generate_html_element_computed_style(
+          StringPrintf(
+              "Event.Count.%s.DOM.HtmlElement.GenerateHtmlElementComputedStyle",
+              name.c_str()),
+          0, "Number of generated computed styles for HTML elements."),
+      count_dom_generate_pseudo_element_computed_style(
+          StringPrintf("Event.Count.%s.DOM.HtmlElement."
+                       "GeneratePseudoElementComputedStyle",
+                       name.c_str()),
+          0, "Number of generated computed styles for Pseudo elements."),
       count_layout_boxes_created(
           StringPrintf("Event.Count.%s.Layout.Box.Created", name.c_str()), 0,
           "Number of boxes created."),
@@ -174,6 +184,7 @@
       ,
       value_dictionary(
           StringPrintf("Event.%s.ValueDictionary", name.c_str()),
+          "{}"
           "All event values represented as a dictionary in a string.")
 #endif  // ENABLE_WEBDRIVER
 {
@@ -207,6 +218,10 @@
       dom_stat_tracker_->update_matching_rules_count();
   event_stats->count_dom_update_computed_style =
       dom_stat_tracker_->update_computed_style_count();
+  event_stats->count_dom_generate_html_element_computed_style =
+      dom_stat_tracker_->generate_html_element_computed_style_count();
+  event_stats->count_dom_generate_pseudo_element_computed_style =
+      dom_stat_tracker_->generate_pseudo_element_computed_style_count();
   event_stats->count_layout_boxes_created =
       layout_stat_tracker_->boxes_created_count();
   event_stats->count_layout_boxes_destroyed =
@@ -249,10 +264,15 @@
       << dom_stat_tracker_->html_elements_created_count() << ", "
       << "\"CntDomHtmlElementsDestroyed\":"
       << dom_stat_tracker_->html_elements_destroyed_count() << ", "
-      << "\"CntDomUpdateMatchingRuleCalls\":"
+      << "\"CntDomUpdateMatchingRules\":"
       << dom_stat_tracker_->update_matching_rules_count() << ", "
-      << "\"CntDomUpdateComputedStyleCalls\":"
+      << "\"CntDomUpdateComputedStyle\":"
       << dom_stat_tracker_->update_computed_style_count() << ", "
+      << "\"CntDomGenerateHtmlComputedStyle\":"
+      << dom_stat_tracker_->generate_html_element_computed_style_count() << ", "
+      << "\"CntDomGeneratePseudoComputedStyle\":"
+      << dom_stat_tracker_->generate_pseudo_element_computed_style_count()
+      << ", "
       << "\"CntLayoutBoxes\":" << layout_stat_tracker_->total_boxes() << ", "
       << "\"CntLayoutBoxesCreated\":"
       << layout_stat_tracker_->boxes_created_count() << ", "
diff --git a/src/cobalt/browser/web_module_stat_tracker.h b/src/cobalt/browser/web_module_stat_tracker.h
index 95efb4a..b4f24e7 100644
--- a/src/cobalt/browser/web_module_stat_tracker.h
+++ b/src/cobalt/browser/web_module_stat_tracker.h
@@ -82,6 +82,10 @@
     base::CVal<int, base::CValPublic> count_dom_html_elements_destroyed;
     base::CVal<int, base::CValPublic> count_dom_update_matching_rules;
     base::CVal<int, base::CValPublic> count_dom_update_computed_style;
+    base::CVal<int, base::CValPublic>
+        count_dom_generate_html_element_computed_style;
+    base::CVal<int, base::CValPublic>
+        count_dom_generate_pseudo_element_computed_style;
     base::CVal<int, base::CValPublic> count_layout_boxes_created;
     base::CVal<int, base::CValPublic> count_layout_boxes_destroyed;
 
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index b679c25..255f12e 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-21796
\ No newline at end of file
+22891
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 9ab623b..8174cbd 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -169,6 +169,11 @@
     # typefaces downloaded from a web page.
     'remote_typeface_cache_size_in_bytes%': 5 * 1024 * 1024,
 
+    # Determines the capacity of the mesh cache. Each mesh is held compressed
+    # in main memory, to be inflated into a GPU buffer when needed for
+    # projection. Default to 0 and set by platforms that support map-to-mesh.
+    'mesh_cache_size_in_bytes%': 0,
+
     # Only relevant if you are using the Blitter API.
     # Determines the capacity of the software surface cache, which is used to
     # cache all surfaces that are rendered via a software rasterizer to avoid
diff --git a/src/cobalt/build/generate_data_header.py b/src/cobalt/build/generate_data_header.py
index 1bfdff4..322b6b8 100755
--- a/src/cobalt/build/generate_data_header.py
+++ b/src/cobalt/build/generate_data_header.py
@@ -28,18 +28,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-
 """Convert binary files to source arrays.
 
-This script takes all of the files in a given directory (and all of its
-subdirectories) and concatenates them for access at byte arrays in a c++
-header file.
+This script takes all of the given input files and directories (and all
+subdirectories) and concatenates them for access at byte arrays in a c++ header
+file.
 
-The directory to check is specified as the first argument, and the output
-header is specified as the second argument.
-
-The utility function GenerateMap() is also generated to populate a std::map
-that maps between filenames and the embedded file.
+The utility function GenerateMap() is also generated to populate a std::map that
+maps between filenames and the embedded file.
 
 All generated symbols will be placed under the user-provided namespace.
 """
@@ -48,64 +44,85 @@
 import sys
 
 
-def GetVariableNameFromPath(file_path):
-  # Get rid of non-variable name friendly characters
-  return file_path.replace('.', '_').replace('/', '_')
+class InputFile(object):
+  """A file with an absolute path and a path that it is relative to."""
+
+  def __init__(self, path, parent):
+    self.path = os.path.abspath(path)
+    self.parent = os.path.abspath(parent)
+
+  def GetRelativePath(self):
+    return os.path.relpath(self.path, self.parent)
+
+  def GetVariableName(self):
+    # Get rid of non-variable name friendly characters
+    return self.GetRelativePath().replace('.', '_').replace('/', '_')
 
 
-def WriteFileDataToHeader(input_file, output_file):
+def WriteFileDataToHeader(filename, output_file):
   """Concatenates a single file into the output file."""
-  with file(input_file, 'rb') as f:
+  with file(filename, 'rb') as f:
     file_contents = f.read()
-    def chunks(l, n):
-      """ Yield successive n-sized chunks from l."""
+
+    def Chunks(l, n):
+      """Yield successive n-sized chunks from l."""
       for i in xrange(0, len(l), n):
-        yield l[i:i+n]
+        yield l[i:i + n]
 
-    output_string = ',\n'.join([', '.join(['0x%02x' % ord(y) for y in x])
-                    for x in chunks(file_contents, 200)])
-    output_file.write('{' + output_string + '};\n\n')
+    output_string = ',\n'.join([
+        ', '.join(['0x%02x' % ord(y) for y in x])
+        for x in Chunks(file_contents, 13)
+    ])
+    output_file.write('{\n' + output_string + '\n};\n\n')
 
 
-def GetFilesToConcatenate(input_directory):
-  """Get list of files to concatenate.
+def GetInputFilesToConcatenate(paths):
+  """Converts a list of paths into a flattened list of InputFiles.
+
+  If an input path is a directory, it adds an entry for each file in that
+  subtree, and keeps it relative to the specified directory.
+
+  If an input path is a regular file, it adds an entry for that file, relative
+  to its immediate parent directory.
 
   Args:
-    input_directory: Directory to search for files.
-  Returns:
-    A list of all files that we would like to concatenate relative
-    to the input directory.
+    paths: Array of paths to search for files.
 
+  Returns:
+    A list of InputFiles that we would like to concatenate.
   """
 
   file_list = []
-  for dirpath, _, files in os.walk(input_directory):
-    for input_file in files:
-      file_list.append(
-          os.path.relpath(
-              os.path.join(dirpath, input_file),
-              input_directory))
+  for path in paths:
+    path = os.path.abspath(path)
+    if os.path.isdir(path):
+      for directory, _, files in os.walk(path):
+        for filename in files:
+          file_list.append(InputFile(os.path.join(directory, filename), path))
+    elif os.path.isfile(path):
+      file_list.append(InputFile(path, os.path.dirname(path)))
+    else:
+      raise '%s is not a file or directory.' % path
   return file_list
 
 
-def WriteAllFilesToHeader(input_directory, files, output_file):
-  """Writes the content of all passed in files to the header file."""
+def WriteAllFilesToHeader(input_files, output_file):
+  """Writes the content of all passed in InputFiles to the header file."""
 
-  for path in files:
-    input_file_variable_name = GetVariableNameFromPath(path)
+  for input_file in input_files:
+    input_file_variable_name = input_file.GetVariableName()
     output_file.write('const unsigned char %s[] =\n' % input_file_variable_name)
-
-    WriteFileDataToHeader(os.path.join(input_directory, path), output_file)
+    WriteFileDataToHeader(input_file.path, output_file)
 
 
-def GenerateMapFunction(files, output_file):
+def GenerateMapFunction(input_files, output_file):
   """Generate C++ containing a map.
 
   Generates a c++ function that populates a map (mapping filenames to the
   embedded contents.)
 
   Args:
-    files: List of filenames in the map.
+    input_files: List of InputFiles in the map.
     output_file: Name of c++ file to write out.
   """
 
@@ -114,17 +131,18 @@
       'inline void GenerateMap(GeneratedResourceMap &out_map) {\n')
 
   # os.walk gets dirpath, dirnames, filenames; we want just filenames, so [2]
-  for path in files:
+  for input_file in input_files:
     # The lookup key will be the file path relative to the input directory
-    input_file_variable_name = GetVariableNameFromPath(path)
+    input_file_variable_name = input_file.GetVariableName()
     output_file.write('  out_map["%s"] = FileContents(%s, sizeof(%s));\n' %
-                      (path, input_file_variable_name, input_file_variable_name)
-                     )
+                      (input_file.GetRelativePath(), input_file_variable_name,
+                       input_file_variable_name))
 
   output_file.write('}\n\n')
 
 
-def main(namespace, input_directory, output_file_name):
+def WriteHeader(namespace, output_file_name, files_to_concatenate):
+  """Writes an embedded resource header to the given output filename."""
   output_file = open(output_file_name, 'w')
   include_guard = '_COBALT_GENERATED_' + namespace.upper() + '_H_'
   output_file.write('// Copyright 2014 Google Inc. '
@@ -133,22 +151,22 @@
                     '#ifndef ' + include_guard + '\n'
                     '#define ' + include_guard + '\n\n'
                     '#include \"cobalt/base/generated_resources_types.h\"\n\n'
-                    'namespace ' + namespace +' {\n')
+                    'namespace ' + namespace + ' {\n')
 
-  files_to_concatenate = GetFilesToConcatenate(input_directory)
-  WriteAllFilesToHeader(input_directory,
-                        files_to_concatenate,
-                        output_file)
+  WriteAllFilesToHeader(files_to_concatenate, output_file)
   GenerateMapFunction(files_to_concatenate, output_file)
 
   output_file.write('} // namespace ' + namespace + '\n\n'
                     '#endif // ' + include_guard + '\n')
 
 
+def main(namespace, output_file_name, paths):
+  WriteHeader(namespace, output_file_name, GetInputFilesToConcatenate(paths))
+
+
 if __name__ == '__main__':
-  if len(sys.argv) != 4:
-    print ('usage:\n %s <namespace> <input directory> <output filepath>' %
-           sys.argv[0])
+  if len(sys.argv) < 4:
+    print 'usage:\n %s <namespace> <output-file> <inputs...> \n' % sys.argv[0]
     print __doc__
     sys.exit(1)
-  main(sys.argv[1], sys.argv[2], sys.argv[3])
+  main(sys.argv[1], sys.argv[2], sys.argv[3:])
diff --git a/src/cobalt/cssom/compound_selector.h b/src/cobalt/cssom/compound_selector.h
index b4e1121..097e2cd 100644
--- a/src/cobalt/cssom/compound_selector.h
+++ b/src/cobalt/cssom/compound_selector.h
@@ -117,8 +117,8 @@
   Specificity specificity_;
   bool has_pseudo_element_;
   // This flag tracks whether or not during rule matching, after the initial
-  // candidate gathering phase, the simple selectors additional checks during
-  // the verification phase to determine a match; otherwise, the act of
+  // candidate gathering phase, the simple selectors require additional checks
+  // during the verification phase to determine a match; otherwise, the act of
   // being gathered itself proves the match.
   // There are two cases where the selectors require a visit:
   // 1. There are multiple selectors. Gathering only tests against the first
diff --git a/src/cobalt/cssom/cssom.gyp b/src/cobalt/cssom/cssom.gyp
index 2d3723e..96cd74d 100644
--- a/src/cobalt/cssom/cssom.gyp
+++ b/src/cobalt/cssom/cssom.gyp
@@ -269,7 +269,7 @@
           'outputs': [
             '<(output_path)',
           ],
-          'action': ['python', '<(script_path)', 'CSSOMEmbeddedResources', '<(input_directory)', '<(output_path)'],
+          'action': ['python', '<(script_path)', 'CSSOMEmbeddedResources', '<(output_path)', '<(input_directory)'],
           'message': 'Embedding cssom resources in "<(input_directory)" into header file, "<(output_path)".',
           'msvs_cygwin_shell': 1,
         },
diff --git a/src/cobalt/dom/character_data.cc b/src/cobalt/dom/character_data.cc
index 1c031f6..6ffff25 100644
--- a/src/cobalt/dom/character_data.cc
+++ b/src/cobalt/dom/character_data.cc
@@ -16,11 +16,19 @@
 
 #include "cobalt/dom/character_data.h"
 
+#include "cobalt/dom/mutation_reporter.h"
+
 namespace cobalt {
 namespace dom {
 
 CharacterData::CharacterData(Document* document, const base::StringPiece& data)
     : Node(document), data_(data.begin(), data.end()) {}
 
+void CharacterData::set_data(const std::string& data) {
+  MutationReporter mutation_reporter(this, GatherInclusiveAncestorsObservers());
+  mutation_reporter.ReportCharacterDataMutation(data_);
+  data_ = data;
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/character_data.h b/src/cobalt/dom/character_data.h
index 08d5b00..12a8d9d 100644
--- a/src/cobalt/dom/character_data.h
+++ b/src/cobalt/dom/character_data.h
@@ -33,19 +33,29 @@
   // Web API: Node
   base::optional<std::string> node_value() const OVERRIDE { return data_; }
   void set_node_value(const base::optional<std::string>& node_value) OVERRIDE {
-    data_ = node_value.value_or("");
+    // Don't use value_or to avoid copying the string.
+    if (node_value) {
+      set_data(node_value.value());
+    } else {
+      set_data("");
+    }
   }
 
   base::optional<std::string> text_content() const OVERRIDE { return data_; }
   void set_text_content(
       const base::optional<std::string>& text_content) OVERRIDE {
-    data_ = text_content.value_or("");
+    // Don't use value_or to avoid copying the string.
+    if (text_content) {
+      set_data(text_content.value());
+    } else {
+      set_data("");
+    }
   }
 
   // Web API: CharacterData
   //
   std::string data() const { return data_; }
-  void set_data(const std::string& data) { data_ = data; }
+  void set_data(const std::string& data);
 
   // Custom, not in any spec.
   //
diff --git a/src/cobalt/dom/comment_test.cc b/src/cobalt/dom/comment_test.cc
index 6de330b..71c1c45 100644
--- a/src/cobalt/dom/comment_test.cc
+++ b/src/cobalt/dom/comment_test.cc
@@ -42,7 +42,7 @@
 
 CommentTest::CommentTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, "") {
+                            NULL, NULL, NULL, NULL, NULL, "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
   document_ = new Document(&html_element_context_);
 }
diff --git a/src/cobalt/dom/document_test.cc b/src/cobalt/dom/document_test.cc
index ee0f442..e50c06c 100644
--- a/src/cobalt/dom/document_test.cc
+++ b/src/cobalt/dom/document_test.cc
@@ -66,7 +66,7 @@
     : css_parser_(css_parser::Parser::Create()),
       dom_stat_tracker_(new DomStatTracker("DocumentTest")),
       html_element_context_(NULL, css_parser_.get(), NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, NULL,
+                            NULL, NULL, NULL, NULL, NULL, NULL,
                             dom_stat_tracker_.get(), "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
 }
diff --git a/src/cobalt/dom/document_type_test.cc b/src/cobalt/dom/document_type_test.cc
index 90f51c3..540dc53 100644
--- a/src/cobalt/dom/document_type_test.cc
+++ b/src/cobalt/dom/document_type_test.cc
@@ -27,7 +27,7 @@
  protected:
   DocumentTypeTest()
       : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, NULL, ""),
+                              NULL, NULL, NULL, NULL, NULL, ""),
         document_(new Document(&html_element_context_)) {}
   ~DocumentTypeTest() OVERRIDE {}
 
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp
index 02775e4..3d2a9e9 100644
--- a/src/cobalt/dom/dom.gyp
+++ b/src/cobalt/dom/dom.gyp
@@ -179,10 +179,15 @@
         'memory_info.h',
         'mime_type_array.cc',
         'mime_type_array.h',
+        'mutation_observer_task_manager.cc',
+        'mutation_observer_task_manager.h',
         'mutation_observer.cc',
         'mutation_observer.h',
         'mutation_observer_init.h',
+        'mutation_record.cc',
         'mutation_record.h',
+        'mutation_reporter.cc',
+        'mutation_reporter.h',
         'named_node_map.cc',
         'named_node_map.h',
         'navigator.cc',
@@ -206,6 +211,9 @@
         'progress_event.h',
         'pseudo_element.cc',
         'pseudo_element.h',
+        'registered_observer.h',
+        'registered_observer_list.cc',
+        'registered_observer_list.h',
         'rule_matching.cc',
         'rule_matching.h',
         'screen.h',
diff --git a/src/cobalt/dom/dom_implementation_test.cc b/src/cobalt/dom/dom_implementation_test.cc
index a9687aa..ff137ed 100644
--- a/src/cobalt/dom/dom_implementation_test.cc
+++ b/src/cobalt/dom/dom_implementation_test.cc
@@ -28,7 +28,7 @@
 TEST(DOMImplementationTest, CreateDocumentShouldCreateXMLDocument) {
   HTMLElementContext html_element_context(NULL, NULL, NULL, NULL, NULL, NULL,
                                           NULL, NULL, NULL, NULL, NULL, NULL,
-                                          "");
+                                          NULL, "");
   scoped_refptr<DOMImplementation> dom_implementation =
       new DOMImplementation(&html_element_context);
   scoped_refptr<Document> document =
diff --git a/src/cobalt/dom/dom_parser_test.cc b/src/cobalt/dom/dom_parser_test.cc
index 0e5cde6..fe037e1 100644
--- a/src/cobalt/dom/dom_parser_test.cc
+++ b/src/cobalt/dom/dom_parser_test.cc
@@ -50,8 +50,8 @@
           &stub_script_runner_, NULL /* media_source_registry */,
           NULL /* resource_provider */, NULL /* image_cache */,
           NULL /* reduced_image_cache_capacity_manager */,
-          NULL /* remote_typeface_cache */, NULL /* dom_stat_tracker */,
-          "" /* language */),
+          NULL /* remote_typeface_cache */, NULL /* mesh_cache */,
+          NULL /* dom_stat_tracker */, "" /* language */),
       dom_parser_(new DOMParser(&html_element_context_)) {}
 
 TEST_F(DOMParserTest, ParsesXML) {
diff --git a/src/cobalt/dom/dom_stat_tracker.cc b/src/cobalt/dom/dom_stat_tracker.cc
index 81ad1a8..83dcd38 100644
--- a/src/cobalt/dom/dom_stat_tracker.cc
+++ b/src/cobalt/dom/dom_stat_tracker.cc
@@ -34,7 +34,9 @@
       html_elements_created_count_(0),
       html_elements_destroyed_count_(0),
       update_matching_rules_count_(0),
-      update_computed_style_count_(0) {
+      update_computed_style_count_(0),
+      generate_html_element_computed_style_count_(0),
+      generate_pseudo_element_computed_style_count_(0) {
   stop_watch_durations_.resize(kNumStopWatchTypes, base::TimeDelta());
 }
 
@@ -94,6 +96,14 @@
 
 void DomStatTracker::OnUpdateComputedStyle() { ++update_computed_style_count_; }
 
+void DomStatTracker::OnGenerateHtmlElementComputedStyle() {
+  ++generate_html_element_computed_style_count_;
+}
+
+void DomStatTracker::OnGeneratePseudoElementComputedStyle() {
+  ++generate_pseudo_element_computed_style_count_;
+}
+
 base::TimeDelta DomStatTracker::GetStopWatchTypeDuration(
     StopWatchType type) const {
   return stop_watch_durations_[type];
@@ -117,6 +127,8 @@
   html_elements_destroyed_count_ = 0;
   update_matching_rules_count_ = 0;
   update_computed_style_count_ = 0;
+  generate_html_element_computed_style_count_ = 0;
+  generate_pseudo_element_computed_style_count_ = 0;
 }
 
 }  // namespace dom
diff --git a/src/cobalt/dom/dom_stat_tracker.h b/src/cobalt/dom/dom_stat_tracker.h
index 80e1208..23d8bcd 100644
--- a/src/cobalt/dom/dom_stat_tracker.h
+++ b/src/cobalt/dom/dom_stat_tracker.h
@@ -49,6 +49,8 @@
   void OnHtmlElementDestroyed();
   void OnUpdateMatchingRules();
   void OnUpdateComputedStyle();
+  void OnGenerateHtmlElementComputedStyle();
+  void OnGeneratePseudoElementComputedStyle();
 
   int total_html_elements() const { return total_html_elements_; }
 
@@ -64,6 +66,12 @@
   int update_computed_style_count() const {
     return update_computed_style_count_;
   }
+  int generate_html_element_computed_style_count() const {
+    return generate_html_element_computed_style_count_;
+  }
+  int generate_pseudo_element_computed_style_count() const {
+    return generate_pseudo_element_computed_style_count_;
+  }
 
   base::TimeDelta GetStopWatchTypeDuration(StopWatchType type) const;
 
@@ -92,6 +100,8 @@
   int html_elements_destroyed_count_;
   int update_matching_rules_count_;
   int update_computed_style_count_;
+  int generate_html_element_computed_style_count_;
+  int generate_pseudo_element_computed_style_count_;
 
   // Stop watch-related.
   std::vector<base::TimeDelta> stop_watch_durations_;
diff --git a/src/cobalt/dom/dom_string_map_test.cc b/src/cobalt/dom/dom_string_map_test.cc
index d9c5521..365c9a8 100644
--- a/src/cobalt/dom/dom_string_map_test.cc
+++ b/src/cobalt/dom/dom_string_map_test.cc
@@ -45,7 +45,7 @@
 
 DOMStringMapTest::DOMStringMapTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, ""),
+                            NULL, NULL, NULL, NULL, NULL, ""),
       document_(new Document(&html_element_context_)),
       element_(new Element(document_, base::Token("element"))),
       dom_string_map_(new DOMStringMap(element_)) {}
diff --git a/src/cobalt/dom/dom_test.gyp b/src/cobalt/dom/dom_test.gyp
index 9bbd53a..a80be3f 100644
--- a/src/cobalt/dom/dom_test.gyp
+++ b/src/cobalt/dom/dom_test.gyp
@@ -49,6 +49,7 @@
         'local_storage_database_test.cc',
         'location_test.cc',
         'media_query_list_test.cc',
+        'mutation_observer_test.cc',
         'node_dispatch_event_test.cc',
         'node_list_live_test.cc',
         'node_list_test.cc',
diff --git a/src/cobalt/dom/dom_token_list_test.cc b/src/cobalt/dom/dom_token_list_test.cc
index 0ef5e3e..70e224c 100644
--- a/src/cobalt/dom/dom_token_list_test.cc
+++ b/src/cobalt/dom/dom_token_list_test.cc
@@ -40,7 +40,7 @@
 
 DOMTokenListTest::DOMTokenListTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, "") {
+                            NULL, NULL, NULL, NULL, NULL, "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
   document_ = new Document(&html_element_context_);
 }
diff --git a/src/cobalt/dom/element.cc b/src/cobalt/dom/element.cc
index 7300b67..8eddb53 100644
--- a/src/cobalt/dom/element.cc
+++ b/src/cobalt/dom/element.cc
@@ -32,6 +32,7 @@
 #include "cobalt/dom/html_collection.h"
 #include "cobalt/dom/html_element.h"
 #include "cobalt/dom/html_element_context.h"
+#include "cobalt/dom/mutation_reporter.h"
 #include "cobalt/dom/named_node_map.h"
 #include "cobalt/dom/parser.h"
 #include "cobalt/dom/serializer.h"
@@ -187,6 +188,11 @@
   //    value is value, and then append this attribute to the context object and
   //    terminate these steps.
   // 5. Change attribute from context object to value.
+
+  base::optional<std::string> old_value = GetAttribute(attr_name);
+  MutationReporter mutation_reporter(this, GatherInclusiveAncestorsObservers());
+  mutation_reporter.ReportAttributesMutation(attr_name, old_value);
+
   switch (attr_name.size()) {
     case 5:
       if (attr_name == kStyleAttributeName) {
@@ -252,6 +258,13 @@
     StringToLowerASCII(&attr_name);
   }
 
+  base::optional<std::string> old_value = GetAttribute(attr_name);
+  if (old_value) {
+    MutationReporter mutation_reporter(this,
+                                       GatherInclusiveAncestorsObservers());
+    mutation_reporter.ReportAttributesMutation(attr_name, old_value);
+  }
+
   // 2. Remove the first attribute from the context object whose name is name,
   //    if any.
   switch (attr_name.size()) {
diff --git a/src/cobalt/dom/element_test.cc b/src/cobalt/dom/element_test.cc
index c8b5ea9..d4a3724 100644
--- a/src/cobalt/dom/element_test.cc
+++ b/src/cobalt/dom/element_test.cc
@@ -61,7 +61,7 @@
       dom_parser_(new dom_parser::Parser()),
       dom_stat_tracker_(new DomStatTracker("ElementTest")),
       html_element_context_(NULL, css_parser_.get(), dom_parser_.get(), NULL,
-                            NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                             dom_stat_tracker_.get(), "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
   document_ = new Document(&html_element_context_);
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index b3ea234..9123ffb 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -956,6 +956,7 @@
   UpdateComputedStyleInvalidationFlags invalidation_flags;
 
   if (generate_computed_style) {
+    dom_stat_tracker_->OnGenerateHtmlElementComputedStyle();
     bool animations_modified = false;
 
     scoped_refptr<cssom::CSSComputedStyleData> new_computed_style =
@@ -982,7 +983,7 @@
     css_computed_style_declaration_->UpdateInheritedData();
   }
 
-  // NOTE: Currently, pseudo elements computed styles are always generated. If
+  // NOTE: Currently, pseudo element's computed styles are always generated. If
   // this becomes a performance bottleneck, change the logic so that it only
   // occurs when needed.
 
@@ -990,6 +991,7 @@
   for (int pseudo_element_type = 0; pseudo_element_type < kMaxPseudoElementType;
        ++pseudo_element_type) {
     if (pseudo_elements_[pseudo_element_type]) {
+      dom_stat_tracker_->OnGeneratePseudoElementComputedStyle();
       bool animations_modified = false;
 
       scoped_refptr<cssom::CSSComputedStyleData> pseudo_element_computed_style =
diff --git a/src/cobalt/dom/html_element_context.cc b/src/cobalt/dom/html_element_context.cc
index c7a9975..e3888d3 100644
--- a/src/cobalt/dom/html_element_context.cc
+++ b/src/cobalt/dom/html_element_context.cc
@@ -32,7 +32,8 @@
     loader::image::ReducedCacheCapacityManager*
         reduced_image_cache_capacity_manager,
     loader::font::RemoteTypefaceCache* remote_typeface_cache,
-    DomStatTracker* dom_stat_tracker, const std::string& language)
+    loader::mesh::MeshCache* mesh_cache, DomStatTracker* dom_stat_tracker,
+    const std::string& language)
     : fetcher_factory_(fetcher_factory),
       css_parser_(css_parser),
       dom_parser_(dom_parser),
@@ -45,6 +46,7 @@
       reduced_image_cache_capacity_manager_(
           reduced_image_cache_capacity_manager),
       remote_typeface_cache_(remote_typeface_cache),
+      mesh_cache_(mesh_cache),
       dom_stat_tracker_(dom_stat_tracker),
       language_(language),
       sync_load_thread_("Synchronous Load"),
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h
index a751b03..4c0f933 100644
--- a/src/cobalt/dom/html_element_context.h
+++ b/src/cobalt/dom/html_element_context.h
@@ -28,6 +28,7 @@
 #include "cobalt/loader/fetcher_factory.h"
 #include "cobalt/loader/font/remote_typeface_cache.h"
 #include "cobalt/loader/image/image_cache.h"
+#include "cobalt/loader/mesh/mesh_cache.h"
 #include "cobalt/media/can_play_type_handler.h"
 #include "cobalt/media/web_media_player_factory.h"
 #include "cobalt/script/script_runner.h"
@@ -53,6 +54,7 @@
                      loader::image::ReducedCacheCapacityManager*
                          reduced_image_cache_capacity_manager,
                      loader::font::RemoteTypefaceCache* remote_typeface_cache,
+                     loader::mesh::MeshCache* mesh_cache,
                      DomStatTracker* dom_stat_tracker,
                      const std::string& language);
   ~HTMLElementContext();
@@ -85,6 +87,8 @@
     return remote_typeface_cache_;
   }
 
+  loader::mesh::MeshCache* mesh_cache() const { return mesh_cache_; }
+
   DomStatTracker* dom_stat_tracker() { return dom_stat_tracker_; }
 
   const std::string& language() const { return language_; }
@@ -113,6 +117,7 @@
   loader::image::ReducedCacheCapacityManager* const
       reduced_image_cache_capacity_manager_;
   loader::font::RemoteTypefaceCache* const remote_typeface_cache_;
+  loader::mesh::MeshCache* const mesh_cache_;
   DomStatTracker* const dom_stat_tracker_;
   const std::string language_;
 
diff --git a/src/cobalt/dom/html_element_factory_test.cc b/src/cobalt/dom/html_element_factory_test.cc
index 2f0c00c..c1485fb 100644
--- a/src/cobalt/dom/html_element_factory_test.cc
+++ b/src/cobalt/dom/html_element_factory_test.cc
@@ -60,8 +60,8 @@
             NULL /* media_source_registry */, NULL /* resource_provider */,
             NULL /* image_cache */,
             NULL /* reduced_image_cache_capacity_manager */,
-            NULL /* remote_typeface_cache */, dom_stat_tracker_.get(),
-            "" /* language */),
+            NULL /* remote_typeface_cache */, NULL /* mesh_cache */,
+            dom_stat_tracker_.get(), "" /* language */),
         document_(new Document(&html_element_context_)) {}
   ~HTMLElementFactoryTest() OVERRIDE {}
 
diff --git a/src/cobalt/dom/html_element_test.cc b/src/cobalt/dom/html_element_test.cc
index e445dcb..2178549 100644
--- a/src/cobalt/dom/html_element_test.cc
+++ b/src/cobalt/dom/html_element_test.cc
@@ -110,8 +110,8 @@
   HTMLElementTest()
       : dom_stat_tracker_(new DomStatTracker("HTMLElementTest")),
         html_element_context_(NULL, &css_parser_, NULL, NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, NULL, dom_stat_tracker_.get(),
-                              ""),
+                              NULL, NULL, NULL, NULL, NULL,
+                              dom_stat_tracker_.get(), ""),
         document_(new Document(&html_element_context_)) {}
   ~HTMLElementTest() OVERRIDE {}
 
diff --git a/src/cobalt/dom/location.cc b/src/cobalt/dom/location.cc
index 9886f33..7202a3fd 100644
--- a/src/cobalt/dom/location.cc
+++ b/src/cobalt/dom/location.cc
@@ -83,5 +83,12 @@
   }
 }
 
+void Location::Reload() {
+  if (!navigation_callback_.is_null()) {
+    LOG(INFO) << "Reloading URL: " << url();
+    navigation_callback_.Run(url());
+  }
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/location.h b/src/cobalt/dom/location.h
index d9552ca..1b3aa76 100644
--- a/src/cobalt/dom/location.h
+++ b/src/cobalt/dom/location.h
@@ -49,11 +49,7 @@
 
   void Replace(const std::string& url);
 
-  void Reload() {
-    if (!navigation_callback_.is_null()) {
-      navigation_callback_.Run(url());
-    }
-  }
+  void Reload();
 
   // Web API: URLUtils (implements)
   //
diff --git a/src/cobalt/dom/mutation_observer.cc b/src/cobalt/dom/mutation_observer.cc
index 3cfa7a0..04057a8 100644
--- a/src/cobalt/dom/mutation_observer.cc
+++ b/src/cobalt/dom/mutation_observer.cc
@@ -16,12 +16,15 @@
 
 #include "cobalt/dom/mutation_observer.h"
 
+#include "cobalt/dom/mutation_observer_task_manager.h"
+#include "cobalt/dom/node.h"
+
 namespace cobalt {
 namespace dom {
 // Abstract base class for a MutationCallback.
 class MutationObserver::CallbackInternal {
  public:
-  virtual void RunCallback(const MutationRecordSequence& mutations,
+  virtual bool RunCallback(const MutationRecordSequence& mutations,
                            const scoped_refptr<MutationObserver>& observer) = 0;
   virtual ~CallbackInternal() {}
 };
@@ -33,9 +36,11 @@
   ScriptCallback(const MutationObserver::MutationCallbackArg& callback,
                  MutationObserver* owner)
       : callback_(owner, callback) {}
-  void RunCallback(const MutationObserver::MutationRecordSequence& mutations,
+  bool RunCallback(const MutationObserver::MutationRecordSequence& mutations,
                    const scoped_refptr<MutationObserver>& observer) OVERRIDE {
-    callback_.value().Run(mutations, observer);
+    script::CallbackResult<void> result =
+        callback_.value().Run(mutations, observer);
+    return !result.exception;
   }
 
  private:
@@ -48,37 +53,114 @@
   explicit NativeCallback(
       const MutationObserver::NativeMutationCallback& callback)
       : callback_(callback) {}
-  void RunCallback(const MutationObserver::MutationRecordSequence& mutations,
+  bool RunCallback(const MutationObserver::MutationRecordSequence& mutations,
                    const scoped_refptr<MutationObserver>& observer) OVERRIDE {
     callback_.Run(mutations, observer);
+    return true;
   }
 
  private:
   MutationObserver::NativeMutationCallback callback_;
 };
+
 }  // namespace
 
 MutationObserver::MutationObserver(
-    const NativeMutationCallback& native_callback) {
+    const NativeMutationCallback& native_callback,
+    MutationObserverTaskManager* task_manager)
+    : task_manager_(task_manager) {
   callback_.reset(new NativeCallback(native_callback));
+  task_manager_->OnMutationObserverCreated(this);
 }
 
-MutationObserver::MutationObserver(const MutationCallbackArg& callback) {
+MutationObserver::MutationObserver(const MutationCallbackArg& callback,
+                                   MutationObserverTaskManager* task_manager)
+    : task_manager_(task_manager) {
   callback_.reset(new ScriptCallback(callback, this));
+  task_manager_->OnMutationObserverCreated(this);
+}
+
+MutationObserver::~MutationObserver() {
+  task_manager_->OnMutationObserverDestroyed(this);
 }
 
 void MutationObserver::Observe(const scoped_refptr<Node>& target,
                                const MutationObserverInit& options) {
-  UNREFERENCED_PARAMETER(target);
-  UNREFERENCED_PARAMETER(options);
-  NOTIMPLEMENTED();
+  if (!target) {
+    // |target| is not nullable, so if this is NULL that indicates a bug in the
+    // bindings layer.
+    NOTREACHED();
+    return;
+  }
+  if (!target->RegisterMutationObserver(make_scoped_refptr(this), options)) {
+    // TODO: Throw TypeError.
+    NOTREACHED();
+  }
+  TrackObservedNode(target);
 }
 
-void MutationObserver::Disconnect() { NOTIMPLEMENTED(); }
+void MutationObserver::Disconnect() {
+  // The disconnect() method must, for each node in the context object's
+  // list of nodes, remove any registered observer on node for which the context
+  // object is the observer, and also empty context object's record queue.
+  for (WeakNodeVector::iterator it = observed_nodes_.begin();
+       it != observed_nodes_.end(); ++it) {
+    dom::Node* node = it->get();
+    if (node != NULL) {
+      node->UnregisterMutationObserver(make_scoped_refptr(this));
+    }
+  }
+  observed_nodes_.clear();
+  record_queue_.clear();
+}
 
 MutationObserver::MutationRecordSequence MutationObserver::TakeRecords() {
-  NOTIMPLEMENTED();
-  return MutationRecordSequence();
+  // The takeRecords() method must return a copy of the record queue and then
+  // empty the record queue.
+  MutationRecordSequence record_queue;
+  record_queue.swap(record_queue_);
+  return record_queue;
+}
+
+void MutationObserver::QueueMutationRecord(
+    const scoped_refptr<MutationRecord>& record) {
+  record_queue_.push_back(record);
+  task_manager_->QueueMutationObserverMicrotask();
+}
+
+bool MutationObserver::Notify() {
+  // https://www.w3.org/TR/dom/#mutationobserver
+  // Step 3 of "notify mutation observers" steps:
+  //     1. Let queue be a copy of mo's record queue.
+  //     2. Empty mo's record queue.
+  MutationRecordSequence records = TakeRecords();
+
+  //     3. Remove all transient registered observers whose observer is mo.
+  // TODO: handle transient registered observers.
+
+  //     4. If queue is non-empty, call mo's callback with queue as first
+  //        argument, and mo (itself) as second argument and callback this
+  //        value. If this throws an exception, report the exception.
+  if (!records.empty()) {
+    return callback_->RunCallback(records, make_scoped_refptr(this));
+  }
+  // If no records, return true to indicate no error occurred.
+  return true;
+}
+
+void MutationObserver::TrackObservedNode(const scoped_refptr<dom::Node>& node) {
+  for (WeakNodeVector::iterator it = observed_nodes_.begin();
+       it != observed_nodes_.end();) {
+    if (*it == NULL) {
+      it = observed_nodes_.erase(it);
+      continue;
+    }
+    if (*it == node) {
+      return;
+    }
+    ++it;
+  }
+  observed_nodes_.push_back(base::AsWeakPtr(node.get()));
 }
 
 }  // namespace dom
diff --git a/src/cobalt/dom/mutation_observer.h b/src/cobalt/dom/mutation_observer.h
index a78030a..fa8daa9 100644
--- a/src/cobalt/dom/mutation_observer.h
+++ b/src/cobalt/dom/mutation_observer.h
@@ -24,7 +24,6 @@
 #include "base/memory/scoped_ptr.h"
 #include "cobalt/dom/mutation_observer_init.h"
 #include "cobalt/dom/mutation_record.h"
-#include "cobalt/dom/node.h"
 #include "cobalt/script/callback_function.h"
 #include "cobalt/script/sequence.h"
 #include "cobalt/script/wrappable.h"
@@ -32,6 +31,9 @@
 namespace cobalt {
 namespace dom {
 
+class MutationObserverTaskManager;
+class Node;
+
 // A MutationObserver object can be used to observe mutations to the tree of
 // nodes.
 // https://www.w3.org/TR/dom/#mutationobserver
@@ -51,22 +53,44 @@
 
   // Not part of the spec. Support creating MutationObservers from native Cobalt
   // code.
-  explicit MutationObserver(const NativeMutationCallback& native_callback);
+  MutationObserver(const NativeMutationCallback& native_callback,
+                   MutationObserverTaskManager* task_manager);
 
   // Web Api: MutationObserver
-  explicit MutationObserver(const MutationCallbackArg& callback);
+  MutationObserver(const MutationCallbackArg& callback,
+                   MutationObserverTaskManager* task_manager);
+  ~MutationObserver();
+
   void Observe(const scoped_refptr<Node>& target,
                const MutationObserverInit& options);
   void Disconnect();
   MutationRecordSequence TakeRecords();
 
+  // Not part of the MutationObserver interface. Implements step (4.8) of the
+  // "queue a mutation record" algorithm.
+  // https://www.w3.org/TR/dom/#queue-a-mutation-record
+  void QueueMutationRecord(const scoped_refptr<MutationRecord>& record);
+
+  // Not part of the the MutationObserver interface. Implements steps (3) of the
+  // "notify mutation observers" algorithm.
+  // https://www.w3.org/TR/dom/#notify-mutation-observers
+  bool Notify();
+
   // Internal helper class to allow creation of a MutationObserver with either a
   // native or script callback. Must be public so it can be inherited from in
   // the .cc file.
   class CallbackInternal;
 
+  DEFINE_WRAPPABLE_TYPE(MutationObserver);
+
  private:
+  void TrackObservedNode(const scoped_refptr<dom::Node>& node);
+
   scoped_ptr<CallbackInternal> callback_;
+  typedef std::vector<base::WeakPtr<dom::Node> > WeakNodeVector;
+  WeakNodeVector observed_nodes_;
+  MutationRecordSequence record_queue_;
+  MutationObserverTaskManager* task_manager_;
 };
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_observer_init.h b/src/cobalt/dom/mutation_observer_init.h
index 3e3c0ea..bd39b33 100644
--- a/src/cobalt/dom/mutation_observer_init.h
+++ b/src/cobalt/dom/mutation_observer_init.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "base/optional.h"
+#include "cobalt/script/sequence.h"
 
 namespace cobalt {
 namespace dom {
@@ -28,20 +29,101 @@
 // Represents the MutationObserverInit dictionary type that is used to
 // initialize the MutationObserver interface.
 // https://www.w3.org/TR/dom/#mutationobserver
-struct MutationObserverInit {
-  typedef std::vector<std::string> StringSequence;
+class MutationObserverInit {
+ public:
+  typedef script::Sequence<std::string> StringSequence;
 
-  // Default values as specified in the IDL.
-  MutationObserverInit() : child_list(false), subtree(false) {}
+  MutationObserverInit()
+      : child_list_(false),
+        attributes_(false),
+        has_attributes_(false),
+        character_data_(false),
+        has_character_data_(false),
+        subtree_(false),
+        attribute_old_value_(false),
+        has_attribute_old_value_(false),
+        character_data_old_value_(false),
+        has_character_data_old_value_(false),
+        has_attribute_filter_(false) {}
 
+  bool child_list() const { return child_list_; }
+  void set_child_list(bool value) { child_list_ = value; }
+
+  bool attributes() const {
+    DCHECK(has_attributes_);
+    return attributes_;
+  }
+  void set_attributes(bool value) {
+    has_attributes_ = true;
+    attributes_ = value;
+  }
+  bool has_attributes() const { return has_attributes_; }
+
+  bool character_data() const {
+    DCHECK(has_character_data_);
+    return character_data_;
+  }
+  void set_character_data(bool value) {
+    has_character_data_ = true;
+    character_data_ = value;
+  }
+  bool has_character_data() const { return has_character_data_; }
+
+  bool subtree() const { return subtree_; }
+  void set_subtree(bool value) { subtree_ = value; }
+
+  bool attribute_old_value() const {
+    DCHECK(has_attribute_old_value_);
+    return attribute_old_value_;
+  }
+  void set_attribute_old_value(bool value) {
+    has_attribute_old_value_ = true;
+    attribute_old_value_ = value;
+  }
+  bool has_attribute_old_value() const { return has_attribute_old_value_; }
+
+  bool character_data_old_value() const {
+    DCHECK(has_character_data_old_value_);
+    return character_data_old_value_;
+  }
+  void set_character_data_old_value(bool value) {
+    has_character_data_old_value_ = true;
+    character_data_old_value_ = value;
+  }
+  bool has_character_data_old_value() const {
+    return has_character_data_old_value_;
+  }
+
+  const StringSequence& attribute_filter() const {
+    DCHECK(has_attribute_filter_);
+    return attribute_filter_;
+  }
+  void set_attribute_filter(StringSequence value) {
+    has_attribute_filter_ = true;
+    attribute_filter_ = value;
+  }
+  bool has_attribute_filter() const { return has_attribute_filter_; }
+
+ private:
   // Dictionary members:
-  bool child_list;
-  base::optional<bool> attributes;
-  base::optional<bool> character_data;
-  bool subtree;
-  base::optional<bool> attribute_old_value;
-  base::optional<bool> character_data_old_value;
-  base::optional<StringSequence> attribute_filter;
+  bool child_list_;
+
+  bool attributes_;
+  bool has_attributes_;
+
+  bool character_data_;
+  bool has_character_data_;
+
+  bool subtree_;
+
+  bool attribute_old_value_;
+  bool has_attribute_old_value_;
+
+  bool character_data_old_value_;
+  bool has_character_data_old_value_;
+
+  StringSequence attribute_filter_;
+  bool has_attribute_filter_;
 };
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_observer_task_manager.cc b/src/cobalt/dom/mutation_observer_task_manager.cc
new file mode 100644
index 0000000..b7c7c7a
--- /dev/null
+++ b/src/cobalt/dom/mutation_observer_task_manager.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/dom/mutation_observer_task_manager.h"
+
+#include "base/callback.h"
+#include "base/message_loop.h"
+
+namespace cobalt {
+namespace dom {
+
+void MutationObserverTaskManager::OnMutationObserverCreated(
+    MutationObserver* observer) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(observers_.find(observer) == observers_.end());
+  observers_.insert(observer);
+}
+void MutationObserverTaskManager::OnMutationObserverDestroyed(
+    MutationObserver* observer) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(observers_.find(observer) != observers_.end());
+  observers_.erase(observer);
+}
+
+void MutationObserverTaskManager::QueueMutationObserverMicrotask() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  // https://www.w3.org/TR/dom/#queue-a-mutation-observer-compound-microtask
+  // To queue a mutation observer compound microtask, run these steps:
+  // 1. If mutation observer compound microtask queued flag is set, terminate
+  //    these steps.
+  if (task_posted_) {
+    return;
+  }
+  // 2. Set mutation observer compound microtask queued flag.
+  task_posted_ = true;
+  // 3. Queue a compound microtask to notify mutation observers.
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&MutationObserverTaskManager::NotifyMutationObservers,
+                 base::Unretained(this)));
+}
+
+void MutationObserverTaskManager::NotifyMutationObservers() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(task_posted_);
+  DCHECK(MessageLoop::current());
+  // https://www.w3.org/TR/dom/#notify-mutation-observers
+  // To notify mutation observers, run these steps:
+  // 1. Unset mutation observer compound microtask queued flag.
+  task_posted_ = false;
+
+  // 2. Let notify list be a copy of unit of related similar-origin browsing
+  //    contexts's list of MutationObserver objects.
+  // 3. For each MutationObserver object mo in notify list, execute a compound
+  //    microtask subtask to run these steps: [HTML]
+  //
+  // Subtask steps are implemented in MutationObserver::Notify.
+  for (MutationObserverSet::iterator it = observers_.begin();
+       it != observers_.end(); ++it) {
+    MutationObserver* observer = *it;
+    if (!observer->Notify()) {
+      DLOG(ERROR) << "Exception when notifying mutation observer.";
+    }
+  }
+}
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_observer_task_manager.h b/src/cobalt/dom/mutation_observer_task_manager.h
new file mode 100644
index 0000000..c080492
--- /dev/null
+++ b/src/cobalt/dom/mutation_observer_task_manager.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_DOM_MUTATION_OBSERVER_TASK_MANAGER_H_
+#define COBALT_DOM_MUTATION_OBSERVER_TASK_MANAGER_H_
+
+#include <utility>
+
+#include "base/hash_tables.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/dom/mutation_observer.h"
+
+namespace cobalt {
+namespace dom {
+
+// The Mutation observer spec describes a sequence of steps to "queue a mutation
+// observer compound microtask" and "notify mutation observers". These steps
+// are implemented in this helper class, which must outlive all
+// MutationObserver instances.
+// The spec expects an EventLoop implementation, which Cobalt does not currently
+// have.
+// https://www.w3.org/TR/dom/#mutation-observers
+class MutationObserverTaskManager {
+ public:
+  MutationObserverTaskManager() : task_posted_(false) {}
+
+  // These should be called in the constructor/destructor of the
+  // MutationObserver.
+  void OnMutationObserverCreated(MutationObserver* observer);
+  void OnMutationObserverDestroyed(MutationObserver* observer);
+
+  // Post a task to notify mutation observers, if one is not already posted.
+  void QueueMutationObserverMicrotask();
+
+ private:
+  // Notify all mutation observers.
+  void NotifyMutationObservers();
+
+  typedef base::hash_set<MutationObserver*> MutationObserverSet;
+
+  base::ThreadChecker thread_checker_;
+  MutationObserverSet observers_;
+  bool task_posted_;
+};
+
+}  // namespace dom
+}  // namespace cobalt
+
+#endif  // COBALT_DOM_MUTATION_OBSERVER_TASK_MANAGER_H_
diff --git a/src/cobalt/dom/mutation_observer_test.cc b/src/cobalt/dom/mutation_observer_test.cc
new file mode 100644
index 0000000..32a1a04
--- /dev/null
+++ b/src/cobalt/dom/mutation_observer_test.cc
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "cobalt/dom/element.h"
+#include "cobalt/dom/mutation_observer_init.h"
+#include "cobalt/dom/mutation_observer_task_manager.h"
+#include "cobalt/dom/mutation_record.h"
+#include "cobalt/dom/mutation_reporter.h"
+#include "cobalt/dom/node_list.h"
+#include "cobalt/dom/text.h"
+#include "cobalt/script/sequence.h"
+#include "cobalt/test/empty_document.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::SaveArg;
+
+namespace cobalt {
+namespace dom {
+// Helper struct for childList mutations.
+struct ChildListMutationArguments {
+  scoped_refptr<dom::Element> previous_sibling;
+  scoped_refptr<dom::Element> next_sibling;
+  scoped_refptr<dom::NodeList> added_nodes;
+  scoped_refptr<dom::NodeList> removed_nodes;
+};
+
+class MutationCallbackMock {
+ public:
+  MOCK_METHOD2(NativeMutationCallback,
+               void(const MutationObserver::MutationRecordSequence&,
+                    const scoped_refptr<MutationObserver>&));
+};
+
+class MutationObserverTest : public ::testing::Test {
+ protected:
+  dom::Document* document() { return empty_document_.document(); }
+  MutationObserverTaskManager* task_manager() { return &task_manager_; }
+  MutationCallbackMock* callback_mock() { return &callback_mock_; }
+
+  scoped_refptr<Element> CreateDiv() {
+    scoped_refptr<Element> element = document()->CreateElement("div");
+    DCHECK(element);
+    document()->AppendChild(element);
+    return element;
+  }
+
+  scoped_refptr<MutationObserver> CreateObserver() {
+    return new MutationObserver(
+        base::Bind(&MutationCallbackMock::NativeMutationCallback,
+                   base::Unretained(&callback_mock_)),
+        &task_manager_);
+  }
+
+  ChildListMutationArguments CreateChildListMutationArguments() {
+    // These nodes are not actually related in the way they are named
+    // (next_sibling, previous_sibling, etc) but that is not relevant for the
+    // purpose of these tests.
+    ChildListMutationArguments args;
+    args.previous_sibling = CreateDiv();
+    args.next_sibling = CreateDiv();
+    args.added_nodes = new NodeList();
+    args.added_nodes->AppendNode(CreateDiv());
+    args.removed_nodes = new NodeList();
+    args.removed_nodes->AppendNode(CreateDiv());
+    return args;
+  }
+
+ private:
+  MutationObserverTaskManager task_manager_;
+  test::EmptyDocument empty_document_;
+  MutationCallbackMock callback_mock_;
+  MessageLoop message_loop_;
+};
+
+TEST_F(MutationObserverTest, CreateAttributeMutationRecord) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  scoped_refptr<MutationRecord> record =
+      MutationRecord::CreateAttributeMutationRecord(target, "attribute_name",
+                                                    std::string("old_value"));
+  ASSERT_TRUE(record);
+
+  // "type" and attribute-related attributes are set as expected
+  EXPECT_STREQ("attribute", record->type().c_str());
+  EXPECT_TRUE(record->attribute_name());
+  EXPECT_STREQ("attribute_name", record->attribute_name()->c_str());
+  EXPECT_TRUE(record->old_value());
+  EXPECT_STREQ("old_value", record->old_value()->c_str());
+
+  // "target" is set as expected.
+  EXPECT_EQ(target, record->target());
+
+  // Namespaces are not supported.
+  EXPECT_FALSE(record->attribute_namespace());
+
+  // Unrelated attributes are not set.
+  EXPECT_FALSE(record->added_nodes());
+  EXPECT_FALSE(record->removed_nodes());
+  EXPECT_FALSE(record->previous_sibling());
+  EXPECT_FALSE(record->next_sibling());
+}
+
+TEST_F(MutationObserverTest, CreateCharacterDataMutationRecord) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  scoped_refptr<MutationRecord> record =
+      MutationRecord::CreateCharacterDataMutationRecord(
+          target, std::string("old_character_data"));
+  ASSERT_TRUE(record);
+
+  // "type" and attribute-related attributes are set as expected
+  EXPECT_STREQ("characterData", record->type().c_str());
+  EXPECT_TRUE(record->old_value());
+  EXPECT_STREQ("old_character_data", record->old_value()->c_str());
+
+  // "target" is set as expected.
+  EXPECT_EQ(target, record->target());
+
+  // Unrelated attributes are not set.
+  EXPECT_FALSE(record->attribute_name());
+  EXPECT_FALSE(record->attribute_namespace());
+  EXPECT_FALSE(record->added_nodes());
+  EXPECT_FALSE(record->removed_nodes());
+  EXPECT_FALSE(record->previous_sibling());
+  EXPECT_FALSE(record->next_sibling());
+}
+
+TEST_F(MutationObserverTest, CreateChildListMutationRecord) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+
+  ChildListMutationArguments args = CreateChildListMutationArguments();
+  scoped_refptr<MutationRecord> record =
+      MutationRecord::CreateChildListMutationRecord(
+          target, args.added_nodes, args.removed_nodes, args.previous_sibling,
+          args.next_sibling);
+  ASSERT_TRUE(record);
+
+  // "type" and attribute-related attributes are set as expected
+  EXPECT_STREQ("childList", record->type().c_str());
+  EXPECT_EQ(args.added_nodes, record->added_nodes());
+  EXPECT_EQ(args.removed_nodes, record->removed_nodes());
+  EXPECT_EQ(args.previous_sibling, record->previous_sibling());
+  EXPECT_EQ(args.next_sibling, record->next_sibling());
+
+  // "target" is set as expected.
+  EXPECT_EQ(target, record->target());
+
+  // Unrelated attributes are not set.
+  EXPECT_FALSE(record->attribute_name());
+  EXPECT_FALSE(record->attribute_namespace());
+  EXPECT_FALSE(record->old_value());
+}
+
+TEST_F(MutationObserverTest, MutationObserverInit) {
+  MutationObserverInit init;
+  // Default values are set according to spec.
+  EXPECT_FALSE(init.child_list());
+  EXPECT_FALSE(init.subtree());
+
+  // Other values are not set.
+  EXPECT_FALSE(init.has_attributes());
+  EXPECT_FALSE(init.has_character_data());
+  EXPECT_FALSE(init.has_attribute_old_value());
+  EXPECT_FALSE(init.has_character_data_old_value());
+  EXPECT_FALSE(init.has_attribute_filter());
+
+  // Set other values.
+  init.set_attributes(true);
+  init.set_character_data(true);
+  init.set_attribute_old_value(true);
+  init.set_character_data_old_value(true);
+  script::Sequence<std::string> attribute_filter;
+  attribute_filter.push_back("a_filter");
+  init.set_attribute_filter(attribute_filter);
+
+  // Other values are now set.
+  EXPECT_TRUE(init.has_attributes());
+  EXPECT_TRUE(init.attributes());
+  EXPECT_TRUE(init.has_character_data());
+  EXPECT_TRUE(init.character_data());
+  EXPECT_TRUE(init.has_attribute_old_value());
+  EXPECT_TRUE(init.attribute_old_value());
+  EXPECT_TRUE(init.has_character_data_old_value());
+  EXPECT_TRUE(init.character_data_old_value());
+  EXPECT_TRUE(init.has_attribute_filter());
+  EXPECT_EQ(init.attribute_filter().size(), attribute_filter.size());
+  EXPECT_EQ(init.attribute_filter().at(0), attribute_filter.at(0));
+}
+
+TEST_F(MutationObserverTest, TakeRecords) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+
+  // Newly created observer shouldn't have records.
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserver::MutationRecordSequence records;
+  records = observer->TakeRecords();
+  EXPECT_TRUE(records.empty());
+
+  // Append a mutation records.
+  scoped_refptr<MutationRecord> record =
+      MutationRecord::CreateCharacterDataMutationRecord(target,
+                                                        "old_character_data");
+  observer->QueueMutationRecord(record);
+
+  // The queued record can be taken once.
+  records = observer->TakeRecords();
+  ASSERT_EQ(1, records.size());
+  ASSERT_EQ(records.at(0), record);
+  records = observer->TakeRecords();
+  EXPECT_TRUE(records.empty());
+}
+
+TEST_F(MutationObserverTest, Notify) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+
+  // Create a new observer and queue a mutation record.
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  scoped_refptr<MutationRecord> record =
+      MutationRecord::CreateCharacterDataMutationRecord(target,
+                                                        "old_character_data");
+  observer->QueueMutationRecord(record);
+
+  // Callback should be fired with the first argument being a sequence of the
+  // queued record, and the second argument being the observer.
+  MutationObserver::MutationRecordSequence records;
+  EXPECT_CALL(*callback_mock(), NativeMutationCallback(_, observer))
+      .WillOnce(SaveArg<0>(&records));
+  observer->Notify();
+  ASSERT_EQ(1, records.size());
+  EXPECT_EQ(record, records.at(0));
+
+  // There should be no more records queued up after the callback has been
+  // fired.
+  records = observer->TakeRecords();
+  EXPECT_TRUE(records.empty());
+}
+
+TEST_F(MutationObserverTest, ReportMutation) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  // Create a registered observer that cares about attribute and character data
+  // mutations.
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit init;
+  init.set_attributes(true);
+  init.set_child_list(false);
+  init.set_character_data(true);
+
+  // Create a MutationReporter for the list of registered observers.
+  scoped_ptr<std::vector<RegisteredObserver> > registered_observers(
+      new std::vector<RegisteredObserver>());
+  registered_observers->push_back(
+      RegisteredObserver(target.get(), observer, init));
+  MutationReporter reporter(target.get(), registered_observers.Pass());
+
+  // Report a few mutations.
+  reporter.ReportAttributesMutation("attribute_name", std::string("old_value"));
+  reporter.ReportCharacterDataMutation("old_character_data");
+  ChildListMutationArguments args = CreateChildListMutationArguments();
+  reporter.ReportChildListMutation(args.added_nodes, args.removed_nodes,
+                                   args.previous_sibling, args.next_sibling);
+
+  // Check that mutation records for the mutation types we care about have
+  // been queued.
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(2, records.size());
+  EXPECT_EQ(records.at(0)->type(), "attribute");
+  EXPECT_EQ(records.at(1)->type(), "characterData");
+}
+
+TEST_F(MutationObserverTest, AttributeFilter) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  // Create a registered observer that cares about attribute and character data
+  // mutations.
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit init;
+  script::Sequence<std::string> attribute_filter;
+  attribute_filter.push_back("banana");
+  attribute_filter.push_back("potato");
+  init.set_attribute_filter(attribute_filter);
+  init.set_attributes(true);
+
+  // Create a MutationReporter for the list of registered observers.
+  scoped_ptr<std::vector<RegisteredObserver> > registered_observers(
+      new std::vector<RegisteredObserver>());
+  registered_observers->push_back(
+      RegisteredObserver(target.get(), observer, init));
+  MutationReporter reporter(target.get(), registered_observers.Pass());
+
+  // Report a few attribute mutations.
+  reporter.ReportAttributesMutation("banana", std::string("rotten"));
+  reporter.ReportAttributesMutation("apple", std::string("wormy"));
+  reporter.ReportAttributesMutation("potato", std::string("mashed"));
+
+  // Check that mutation records for the filtered attrbiutes have been queued.
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(2, records.size());
+  EXPECT_STREQ(records.at(0)->attribute_name()->c_str(), "banana");
+  EXPECT_STREQ(records.at(1)->attribute_name()->c_str(), "potato");
+}
+
+TEST_F(MutationObserverTest, RegisteredObserverList) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+
+  RegisteredObserverList observer_list(target.get());
+
+  // Add an observer with options.
+  MutationObserverInit options;
+  options.set_attributes(true);
+  EXPECT_TRUE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(1, observer_list.registered_observers().size());
+  EXPECT_EQ(observer, observer_list.registered_observers()[0].observer());
+  EXPECT_TRUE(observer_list.registered_observers()[0].options().attributes());
+  EXPECT_FALSE(
+      observer_list.registered_observers()[0].options().has_character_data());
+  EXPECT_FALSE(observer_list.registered_observers()[0].options().child_list());
+
+  // Adding the same observer updates the options.
+  options = MutationObserverInit();
+  options.set_child_list(true);
+  EXPECT_TRUE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(1, observer_list.registered_observers().size());
+  EXPECT_EQ(observer, observer_list.registered_observers()[0].observer());
+  EXPECT_FALSE(
+      observer_list.registered_observers()[0].options().has_attributes());
+  EXPECT_FALSE(
+      observer_list.registered_observers()[0].options().has_character_data());
+  EXPECT_TRUE(observer_list.registered_observers()[0].options().child_list());
+
+  // Remove the observer.
+  observer_list.RemoveMutationObserver(observer);
+  EXPECT_EQ(0, observer_list.registered_observers().size());
+}
+
+TEST_F(MutationObserverTest, LazilySetOptions) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+
+  RegisteredObserverList observer_list(target.get());
+
+  // |attributes| gets set if an attribute-related option is set.
+  MutationObserverInit options;
+  options.set_attribute_old_value(true);
+  EXPECT_TRUE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(1, observer_list.registered_observers().size());
+  EXPECT_TRUE(observer_list.registered_observers()[0].options().attributes());
+
+  // |character_data| gets set if an attribute-related option is set.
+  options = MutationObserverInit();
+  options.set_character_data_old_value(true);
+  EXPECT_TRUE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(1, observer_list.registered_observers().size());
+  EXPECT_TRUE(
+      observer_list.registered_observers()[0].options().character_data());
+}
+
+TEST_F(MutationObserverTest, InvalidOptions) {
+  scoped_refptr<dom::Element> target = CreateDiv();
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+
+  RegisteredObserverList observer_list(target.get());
+
+  // No type of mutation is set.
+  MutationObserverInit options;
+  EXPECT_FALSE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(0, observer_list.registered_observers().size());
+
+  // |attributes| is set as false, but attribute old data is set.
+  options.set_attributes(false);
+  options.set_attribute_old_value(true);
+  EXPECT_FALSE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(0, observer_list.registered_observers().size());
+
+  // |character_data| is set as false, but attribute old data is set.
+  options = MutationObserverInit();
+  options.set_character_data(false);
+  options.set_character_data_old_value(true);
+  EXPECT_FALSE(observer_list.AddMutationObserver(observer, options));
+  EXPECT_EQ(0, observer_list.registered_observers().size());
+}
+
+TEST_F(MutationObserverTest, AddChildNodes) {
+  scoped_refptr<Element> root = CreateDiv();
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit options;
+  options.set_subtree(true);
+  options.set_child_list(true);
+  observer->Observe(root, options);
+
+  scoped_refptr<Element> child1 = document()->CreateElement("div");
+  scoped_refptr<Element> child2 = document()->CreateElement("div");
+  ASSERT_TRUE(child1);
+  ASSERT_TRUE(child2);
+
+  root->AppendChild(child1);
+  child1->AppendChild(child2);
+
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(2, records.size());
+  EXPECT_EQ("childList", records.at(0)->type());
+  EXPECT_EQ(root, records.at(0)->target());
+  ASSERT_FALSE(records.at(0)->removed_nodes());
+  ASSERT_TRUE(records.at(0)->added_nodes());
+  ASSERT_EQ(1, records.at(0)->added_nodes()->length());
+  EXPECT_EQ(child1, records.at(0)->added_nodes()->Item(0));
+
+  EXPECT_EQ("childList", records.at(1)->type());
+  EXPECT_EQ(child1, records.at(1)->target());
+  ASSERT_FALSE(records.at(1)->removed_nodes());
+  ASSERT_TRUE(records.at(1)->added_nodes());
+  ASSERT_EQ(1, records.at(1)->added_nodes()->length());
+  EXPECT_EQ(child2, records.at(1)->added_nodes()->Item(0));
+}
+
+TEST_F(MutationObserverTest, RemoveChildNode) {
+  scoped_refptr<Element> root = CreateDiv();
+  scoped_refptr<Element> child1 = document()->CreateElement("div");
+  scoped_refptr<Element> child2 = document()->CreateElement("div");
+  ASSERT_TRUE(child1);
+  ASSERT_TRUE(child2);
+
+  root->AppendChild(child1);
+  child1->AppendChild(child2);
+
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit options;
+  options.set_subtree(true);
+  options.set_child_list(true);
+  observer->Observe(root, options);
+
+  child1->RemoveChild(child2);
+
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(1, records.size());
+  EXPECT_EQ("childList", records.at(0)->type());
+  EXPECT_EQ(child1, records.at(0)->target());
+  ASSERT_TRUE(records.at(0)->removed_nodes());
+  ASSERT_EQ(1, records.at(0)->removed_nodes()->length());
+  EXPECT_EQ(child2, records.at(0)->removed_nodes()->Item(0));
+}
+
+TEST_F(MutationObserverTest, MutateCharacterData) {
+  scoped_refptr<Element> root = CreateDiv();
+  scoped_refptr<Text> text = document()->CreateTextNode("initial-data");
+  ASSERT_TRUE(text);
+  root->AppendChild(text);
+
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit options;
+  options.set_subtree(true);
+  options.set_character_data(true);
+  observer->Observe(root, options);
+
+  text->set_data("new-data");
+
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(1, records.size());
+  EXPECT_EQ("characterData", records.at(0)->type());
+  EXPECT_EQ(text, records.at(0)->target());
+  ASSERT_TRUE(records.at(0)->old_value());
+  EXPECT_STREQ("initial-data", records.at(0)->old_value()->c_str());
+}
+
+TEST_F(MutationObserverTest, MutateAttribute) {
+  scoped_refptr<Element> root = CreateDiv();
+  root->SetAttribute("banana", "purple");
+  root->SetAttribute("apple", "green");
+
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  script::Sequence<std::string> filter;
+  filter.push_back("banana");
+  MutationObserverInit options;
+  options.set_attributes(true);
+  options.set_attribute_filter(filter);
+  observer->Observe(root, options);
+
+  root->SetAttribute("banana", "yellow");
+  root->SetAttribute("apple", "brown");
+
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  ASSERT_EQ(1, records.size());
+  EXPECT_EQ("attribute", records.at(0)->type());
+  EXPECT_EQ(root, records.at(0)->target());
+  ASSERT_TRUE(records.at(0)->old_value());
+  ASSERT_TRUE(records.at(0)->attribute_name());
+  EXPECT_STREQ("banana", records.at(0)->attribute_name()->c_str());
+  EXPECT_STREQ("purple", records.at(0)->old_value()->c_str());
+}
+
+TEST_F(MutationObserverTest, Disconnect) {
+  scoped_refptr<Element> root = CreateDiv();
+  scoped_refptr<Text> text = document()->CreateTextNode("initial-data");
+  ASSERT_TRUE(text);
+  root->AppendChild(text);
+
+  scoped_refptr<MutationObserver> observer = CreateObserver();
+  MutationObserverInit options;
+  options.set_subtree(true);
+  options.set_character_data(true);
+  observer->Observe(root, options);
+
+  // This should queue up a mutation record.
+  text->set_data("new-data");
+
+  observer->Disconnect();
+  MutationObserver::MutationRecordSequence records = observer->TakeRecords();
+  // MutationObserver.disconnect() should clear any queued records.
+  EXPECT_EQ(0, records.size());
+
+  // This should not queue a mutation record.
+  text->set_data("more-new-data");
+  records = observer->TakeRecords();
+  EXPECT_EQ(0, records.size());
+}
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_record.cc b/src/cobalt/dom/mutation_record.cc
new file mode 100644
index 0000000..31d6eb2
--- /dev/null
+++ b/src/cobalt/dom/mutation_record.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/dom/mutation_record.h"
+
+#include "cobalt/dom/node.h"
+#include "cobalt/dom/node_list.h"
+
+namespace cobalt {
+namespace dom {
+
+scoped_refptr<MutationRecord> MutationRecord::CreateAttributeMutationRecord(
+    const scoped_refptr<Node>& target, const std::string& attribute_name,
+    const base::optional<std::string>& old_value) {
+  scoped_refptr<MutationRecord> record =
+      new MutationRecord(base::Tokens::attribute(), target);
+  record->attribute_name_ = attribute_name;
+  record->old_value_ = old_value;
+  return record;
+}
+
+scoped_refptr<MutationRecord> MutationRecord::CreateCharacterDataMutationRecord(
+    const scoped_refptr<Node>& target, const std::string& old_character_data) {
+  scoped_refptr<MutationRecord> record =
+      new MutationRecord(base::Tokens::characterData(), target);
+  record->old_value_ = old_character_data;
+  return record;
+}
+
+scoped_refptr<MutationRecord> MutationRecord::CreateChildListMutationRecord(
+    const scoped_refptr<Node>& target,
+    const scoped_refptr<dom::NodeList>& added_nodes,
+    const scoped_refptr<dom::NodeList>& removed_nodes,
+    const scoped_refptr<dom::Node>& previous_sibling,
+    const scoped_refptr<dom::Node>& next_sibling) {
+  scoped_refptr<MutationRecord> record =
+      new MutationRecord(base::Tokens::childList(), target);
+  record->added_nodes_ = added_nodes;
+  record->removed_nodes_ = removed_nodes;
+  record->previous_sibling_ = previous_sibling;
+  record->next_sibling_ = next_sibling;
+  return record;
+}
+
+MutationRecord::MutationRecord(const base::Token& type,
+                               const scoped_refptr<Node>& target)
+    : type_(type), target_(target) {}
+MutationRecord::~MutationRecord() {}
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_record.h b/src/cobalt/dom/mutation_record.h
index cd43589..9c21010 100644
--- a/src/cobalt/dom/mutation_record.h
+++ b/src/cobalt/dom/mutation_record.h
@@ -20,30 +20,70 @@
 #include <string>
 
 #include "base/optional.h"
-#include "cobalt/dom/node.h"
-#include "cobalt/dom/node_list.h"
+#include "cobalt/base/token.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
 namespace dom {
 
+class Node;
+class NodeList;
+
 // MutationRecords are used with the MutationObserver interface to describe a
 // mutation on the documnet.
 // https://www.w3.org/TR/dom/#mutationrecord
 class MutationRecord : public script::Wrappable {
  public:
   // Web API: MutationRecord
-  std::string type() { return ""; }
-  scoped_refptr<dom::Node> target() { return NULL; }
-  scoped_refptr<dom::NodeList> added_nodes() { return NULL; }
-  scoped_refptr<dom::NodeList> removed_nodes() { return NULL; }
-  scoped_refptr<dom::Node> previous_sibling() { return NULL; }
-  scoped_refptr<dom::Node> next_sibling() { return NULL; }
-  base::optional<std::string> attribute_name() { return base::nullopt; }
-  base::optional<std::string> attribute_namespace() { return base::nullopt; }
-  base::optional<std::string> old_value() { return base::nullopt; }
+  const base::Token& type() { return type_; }
+  const scoped_refptr<dom::Node>& target() { return target_; }
+  const scoped_refptr<dom::NodeList>& added_nodes() { return added_nodes_; }
+  const scoped_refptr<dom::NodeList>& removed_nodes() { return removed_nodes_; }
+  const scoped_refptr<dom::Node>& previous_sibling() {
+    return previous_sibling_;
+  }
+  const scoped_refptr<dom::Node>& next_sibling() { return next_sibling_; }
+  const base::optional<std::string>& attribute_name() {
+    return attribute_name_;
+  }
+  const base::optional<std::string>& attribute_namespace() {
+    return attribute_namespace_;
+  }
+  const base::optional<std::string>& old_value() { return old_value_; }
+
+  // Not part of the MutationRecord interface. These create functions implement
+  // the part of the "queueing a mutation record" algorithm pertaining to
+  // creating a new Mutation Record (step 4).
+  // https://www.w3.org/TR/dom/#queue-a-mutation-record
+  static scoped_refptr<MutationRecord> CreateAttributeMutationRecord(
+      const scoped_refptr<Node>& target, const std::string& attribute_name,
+      const base::optional<std::string>& old_value);
+
+  static scoped_refptr<MutationRecord> CreateCharacterDataMutationRecord(
+      const scoped_refptr<Node>& target, const std::string& old_character_data);
+
+  static scoped_refptr<MutationRecord> CreateChildListMutationRecord(
+      const scoped_refptr<Node>& target,
+      const scoped_refptr<dom::NodeList>& added_nodes,
+      const scoped_refptr<dom::NodeList>& removed_nodes,
+      const scoped_refptr<dom::Node>& previous_sibling,
+      const scoped_refptr<dom::Node>& next_sibling);
 
   DEFINE_WRAPPABLE_TYPE(MutationRecord);
+
+ private:
+  MutationRecord(const base::Token& type, const scoped_refptr<Node>& target);
+  ~MutationRecord();
+
+  base::Token type_;
+  scoped_refptr<dom::Node> target_;
+  scoped_refptr<dom::NodeList> added_nodes_;
+  scoped_refptr<dom::NodeList> removed_nodes_;
+  scoped_refptr<dom::Node> previous_sibling_;
+  scoped_refptr<dom::Node> next_sibling_;
+  base::optional<std::string> attribute_name_;
+  base::optional<std::string> attribute_namespace_;
+  base::optional<std::string> old_value_;
 };
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_reporter.cc b/src/cobalt/dom/mutation_reporter.cc
new file mode 100644
index 0000000..28bb037
--- /dev/null
+++ b/src/cobalt/dom/mutation_reporter.cc
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/dom/mutation_reporter.h"
+
+#include "base/hash_tables.h"
+#include "cobalt/dom/mutation_observer.h"
+#include "cobalt/dom/mutation_observer_init.h"
+#include "cobalt/dom/node.h"
+#include "cobalt/dom/node_list.h"
+
+namespace cobalt {
+namespace dom {
+namespace {
+
+// Internal helper class to determine if a registered observer cares about a
+// certain type of mutation, and for creating a mutation record for different
+// types of mutations.
+class MutationRecordBuilder {
+ public:
+  virtual bool IsInterested(const MutationObserverInit& options) = 0;
+  virtual scoped_refptr<MutationRecord> CreateMutationRecord(
+      const scoped_refptr<Node>& target) = 0;
+};
+
+// MutationRecordBuild for attribute mutations.
+class AttributeMutationRecordBuilder : public MutationRecordBuilder {
+ public:
+  AttributeMutationRecordBuilder(const std::string& attribute_name,
+                                 const base::optional<std::string>& old_value)
+      : attribute_name_(attribute_name), old_value_(old_value) {}
+
+  bool IsInterested(const MutationObserverInit& options) OVERRIDE {
+    // https://www.w3.org/TR/dom/#queue-a-mutation-record
+    // 2. If type is "attributes" and options's attributes is not true,
+    // continue.
+    if (!options.has_attributes() || !options.attributes()) {
+      return false;
+    }
+
+    // 3. If type is "attributes", options's attributeFilter is present,
+    //    and either options's attributeFilter does not contain name or
+    //    namespace is non-null, continue.
+    if (options.has_attribute_filter()) {
+      // Cobalt doesn't support namespaces, so ignore that part of step (2).
+      for (size_t i = 0; i < options.attribute_filter().size(); ++i) {
+        if (options.attribute_filter().at(i) == attribute_name_) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return true;
+  }
+
+  scoped_refptr<MutationRecord> CreateMutationRecord(
+      const scoped_refptr<Node>& target) OVERRIDE {
+    return MutationRecord::CreateAttributeMutationRecord(
+        target, attribute_name_, old_value_);
+  }
+
+ private:
+  std::string attribute_name_;
+  base::optional<std::string> old_value_;
+};
+
+// MutationRecordBuild for character data mutations.
+class CharacterDataMutationRecordBuilder : public MutationRecordBuilder {
+ public:
+  explicit CharacterDataMutationRecordBuilder(
+      const std::string& old_character_data)
+      : old_character_data_(old_character_data) {}
+
+  bool IsInterested(const MutationObserverInit& options) OVERRIDE {
+    // https://www.w3.org/TR/dom/#queue-a-mutation-record
+    // 4. If type is "characterData" and options's characterData is not true,
+    //    continue.
+    return options.has_character_data() && options.character_data();
+  }
+  scoped_refptr<MutationRecord> CreateMutationRecord(
+      const scoped_refptr<Node>& target) OVERRIDE {
+    return MutationRecord::CreateCharacterDataMutationRecord(
+        target, old_character_data_);
+  }
+
+ private:
+  std::string old_character_data_;
+};
+
+// MutationRecordBuild for child list mutations.
+class ChildListMutationRecordBuilder : public MutationRecordBuilder {
+ public:
+  ChildListMutationRecordBuilder(
+      const scoped_refptr<dom::NodeList>& added_nodes,
+      const scoped_refptr<dom::NodeList>& removed_nodes,
+      const scoped_refptr<dom::Node>& previous_sibling,
+      const scoped_refptr<dom::Node>& next_sibling)
+      : added_nodes_(added_nodes),
+        removed_nodes_(removed_nodes),
+        previous_sibling_(previous_sibling),
+        next_sibling_(next_sibling) {}
+
+  bool IsInterested(const MutationObserverInit& options) OVERRIDE {
+    // https://www.w3.org/TR/dom/#queue-a-mutation-record
+    // 5. If type is "childList" and options's childList is false, continue.
+    return options.child_list();
+  }
+
+  scoped_refptr<MutationRecord> CreateMutationRecord(
+      const scoped_refptr<Node>& target) OVERRIDE {
+    return MutationRecord::CreateChildListMutationRecord(
+        target, added_nodes_, removed_nodes_, previous_sibling_, next_sibling_);
+  }
+
+ private:
+  scoped_refptr<dom::NodeList> added_nodes_;
+  scoped_refptr<dom::NodeList> removed_nodes_;
+  scoped_refptr<dom::Node> previous_sibling_;
+  scoped_refptr<dom::Node> next_sibling_;
+};
+
+// Iterate through |registered_observers| and create a new MutationRecord via
+// |record_builder| for interested observers.
+void ReportToInterestedObservers(
+    const scoped_refptr<Node>& target,
+    MutationReporter::RegisteredObserverVector* registered_observers,
+    MutationRecordBuilder* record_builder) {
+  typedef base::hash_set<MutationObserver*> MutationObserverSet;
+  MutationObserverSet reported_observers;
+  for (size_t i = 0; i < registered_observers->size(); ++i) {
+    const RegisteredObserver& registered_observer = registered_observers->at(i);
+    MutationObserver* observer = registered_observer.observer().get();
+    const MutationObserverInit& options = registered_observer.options();
+
+    // The mutation has already been reported to this observer, so skip it, per
+    // step 3.6 (https://www.w3.org/TR/dom/#queue-a-mutation-record)
+    if (reported_observers.find(observer) != reported_observers.end()) {
+      continue;
+    }
+
+    // https://www.w3.org/TR/dom/#queue-a-mutation-record
+    // 1. If node is not target and options's subtree is false, continue.
+    if (registered_observer.target() != target && !options.subtree()) {
+      continue;
+    }
+    // This observer doesn't care about this mutation, so skip it.
+    if (!record_builder->IsInterested(options)) {
+      continue;
+    }
+    // Queue a mutation record on the observer.
+    observer->QueueMutationRecord(record_builder->CreateMutationRecord(target));
+    reported_observers.insert(observer);
+  }
+}
+
+}  // namespace
+
+MutationReporter::MutationReporter(
+    dom::Node* target,
+    scoped_ptr<RegisteredObserverVector> registered_observers)
+    : target_(target), observers_(registered_observers.Pass()) {}
+
+MutationReporter::~MutationReporter() {}
+
+// Implement the "queue a mutation record" algorithm.
+// https://www.w3.org/TR/dom/#queue-a-mutation-record
+void MutationReporter::ReportAttributesMutation(
+    const std::string& name,
+    const base::optional<std::string>& old_value) const {
+  AttributeMutationRecordBuilder record_builder(name, old_value);
+  ReportToInterestedObservers(target_, observers_.get(), &record_builder);
+}
+
+void MutationReporter::ReportCharacterDataMutation(
+    const std::string& old_value) const {
+  CharacterDataMutationRecordBuilder record_builder(old_value);
+  ReportToInterestedObservers(target_, observers_.get(), &record_builder);
+}
+
+void MutationReporter::ReportChildListMutation(
+    const scoped_refptr<dom::NodeList>& added_nodes,
+    const scoped_refptr<dom::NodeList>& removed_nodes,
+    const scoped_refptr<dom::Node>& previous_sibling,
+    const scoped_refptr<dom::Node>& next_sibling) const {
+  ChildListMutationRecordBuilder record_builder(added_nodes, removed_nodes,
+                                                previous_sibling, next_sibling);
+  ReportToInterestedObservers(target_, observers_.get(), &record_builder);
+}
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/mutation_reporter.h b/src/cobalt/dom/mutation_reporter.h
new file mode 100644
index 0000000..d8ccda3
--- /dev/null
+++ b/src/cobalt/dom/mutation_reporter.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_DOM_MUTATION_REPORTER_H_
+#define COBALT_DOM_MUTATION_REPORTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/dom/registered_observer.h"
+
+namespace cobalt {
+namespace dom {
+
+class Node;
+class NodeList;
+
+// Helper class that reports a mutation to interested MutationObservers
+// according to the "queue a mutation record" algorithm:
+// https://www.w3.org/TR/dom/#queue-a-mutation-record
+//
+// This class is intended to be used internally in the Node class.
+class MutationReporter {
+ public:
+  typedef std::vector<RegisteredObserver> RegisteredObserverVector;
+  // Construct a MutationReporter with a list of potentially interested
+  // RegisteredObservers. In practice, this list of |registered_observers| will
+  // the RegisteredObservers registered to the node that is being mutated and
+  // its ancestors. |registered_observers| may contain duplicates.
+  MutationReporter(dom::Node* target,
+                   scoped_ptr<RegisteredObserverVector> registered_observers);
+
+  ~MutationReporter();
+
+  // Implement the "queue a mutation record" algorithm for the different types
+  // of mutations.
+  void ReportAttributesMutation(
+      const std::string& name,
+      const base::optional<std::string>& old_value) const;
+  void ReportCharacterDataMutation(const std::string& old_value) const;
+  void ReportChildListMutation(
+      const scoped_refptr<dom::NodeList>& added_nodes,
+      const scoped_refptr<dom::NodeList>& removed_nodes,
+      const scoped_refptr<dom::Node>& previous_sibling,
+      const scoped_refptr<dom::Node>& next_sibling) const;
+
+ private:
+  dom::Node* target_;
+  scoped_ptr<RegisteredObserverVector> observers_;
+};
+}  // namespace dom
+}  // namespace cobalt
+#endif  // COBALT_DOM_MUTATION_REPORTER_H_
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index b82b0c0..f6c6b69 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -32,6 +32,7 @@
 #include "cobalt/dom/global_stats.h"
 #include "cobalt/dom/html_collection.h"
 #include "cobalt/dom/html_element_context.h"
+#include "cobalt/dom/mutation_reporter.h"
 #include "cobalt/dom/node_descendants_iterator.h"
 #include "cobalt/dom/node_list.h"
 #include "cobalt/dom/node_list_live.h"
@@ -287,11 +288,26 @@
   node->AdoptIntoDocument(node_document_);
 
   // 10. Remove child from its parent with the suppress observers flag set.
-  Remove(child);
+  Remove(child, true);
 
   // 11. Insert node into parent before reference child with the suppress
   // observers flag set.
-  Insert(node, reference_child);
+  Insert(node, reference_child, true);
+
+  // 12. Let nodes be node's children if node is a DocumentFragment node, and a
+  // list containing solely node otherwise.
+  // 13. Queue a mutation record of "childList" for target parent with
+  // addedNodes nodes, removedNodes a list solely containing child, nextSibling
+  // reference child, and previousSibling child's previous sibling.
+  MutationReporter mutation_reporter(this, GatherInclusiveAncestorsObservers());
+  scoped_refptr<dom::NodeList> added_nodes = new dom::NodeList();
+  added_nodes->AppendNode(node);
+  scoped_refptr<dom::NodeList> removed_nodes = new dom::NodeList();
+  removed_nodes->AppendNode(child);
+  mutation_reporter.ReportChildListMutation(
+      added_nodes, removed_nodes,
+      child->previous_sibling_ /* previous_sibling */,
+      reference_child /* next_sibling */);
 
   return child;
 }
@@ -427,7 +443,8 @@
       previous_sibling_(NULL),
       last_child_(NULL),
       inserted_into_document_(false),
-      node_generation_(kInitialNodeGeneration) {
+      node_generation_(kInitialNodeGeneration),
+      ALLOW_THIS_IN_INITIALIZER_LIST(registered_observers_(this)) {
   DCHECK(node_document_);
   ++(node_count_log.Get().count);
   GlobalStats::GetInstance()->Add(this);
@@ -508,6 +525,21 @@
   }
 }
 
+scoped_ptr<Node::RegisteredObserverVector>
+Node::GatherInclusiveAncestorsObservers() {
+  scoped_ptr<RegisteredObserverVector> inclusive_observers(
+      new RegisteredObserverVector());
+  Node* current = this;
+  while (current) {
+    const RegisteredObserverList::RegisteredObserverVector& node_observers =
+        current->registered_observers_.registered_observers();
+    inclusive_observers->insert(inclusive_observers->end(),
+                                node_observers.begin(), node_observers.end());
+    current = current->parent_;
+  }
+  return inclusive_observers.Pass();
+}
+
 // Algorithm for EnsurePreInsertionValidity:
 //   https://www.w3.org/TR/dom/#concept-node-ensure-pre-insertion-validity
 bool Node::EnsurePreInsertionValidity(const scoped_refptr<Node>& node,
@@ -577,7 +609,7 @@
   // 4. Adopt node into parent's node document.
   // 5. Insert node into parent before reference child.
   node->AdoptIntoDocument(node_document_);
-  Insert(node, child == node ? child->next_sibling_ : child);
+  Insert(node, child == node ? child->next_sibling_ : child, false);
 
   // 6. Return node.
   return node;
@@ -586,16 +618,35 @@
 // Algorithm for Insert:
 //   https://www.w3.org/TR/dom/#concept-node-insert
 void Node::Insert(const scoped_refptr<Node>& node,
-                  const scoped_refptr<Node>& child) {
+                  const scoped_refptr<Node>& child, bool suppress_observers) {
   // 1. 2. Not needed by Cobalt.
   // 3. Let nodes be node's children if node is a DocumentFragment node, and a
   // list containing solely node otherwise.
-  // 4. ~ 6. Not needed by Cobalt.
+  // 4. 5. Not needed by Cobalt.
+  // 6. If suppress observers flag is unset, queue a mutation record of
+  //    "childList" for parent with addedNodes nodes, nextSibling child, and
+  //    previousSibling child's previous sibling or parent's last child if
+  //    child is null.
   // 7. For each newNode in nodes, in tree order, run these substeps:
   //   1. Insert newNode into parent before child or at the end of parent if
   //   child is null.
   //   2. Run the insertion steps with newNode.
 
+  if (!suppress_observers) {
+    scoped_ptr<RegisteredObserverVector> observers =
+        GatherInclusiveAncestorsObservers();
+    if (!observers->empty()) {
+      MutationReporter mutation_reporter(this, observers.Pass());
+      scoped_refptr<dom::NodeList> added_nodes = new dom::NodeList();
+      added_nodes->AppendNode(node);
+      mutation_reporter.ReportChildListMutation(
+          added_nodes, NULL, child && child->previous_sibling_
+                                 ? child->previous_sibling_
+                                 : this->last_child_ /* previous_sibling */,
+          child /* next_sibling */);
+    }
+  }
+
   node->parent_ = this;
 
   scoped_refptr<Node> next_sibling = child;
@@ -646,7 +697,7 @@
   }
 
   // 2. Remove child from parent.
-  Remove(child);
+  Remove(child, false);
 
   // 3. Return child.
   return child;
@@ -654,7 +705,7 @@
 
 // Algorithm for Remove:
 //   https://www.w3.org/TR/dom/#concept-node-remove
-void Node::Remove(const scoped_refptr<Node>& node) {
+void Node::Remove(const scoped_refptr<Node>& node, bool suppress_observers) {
   DCHECK(node);
 
   OnMutation();
@@ -674,10 +725,34 @@
     node->OnRemovedFromDocument();
   }
 
-  // 1. ~ 8. Not needed by Cobalt.
+  // 1. 5. Not needed by Cobalt.
+  // 6. Let oldPreviousSibling be node's previous sibling
+  // 7. If suppress observers flag is unset, queue a mutation record of
+  // "childList" for parent with removedNodes a list solely containing node,
+  // nextSibling node's next sibling, and previousSibling oldPreviousSibling.
+  // 8. For each ancestor ancestor of node, if ancestor has any registered
+  // observers whose options's subtree is true, then for each such registered
+  // observer registered, append a transient registered observer whose observer
+  // and options are identical to those of registered and source which is
+  // registered to node's list of registered observers.
   // 9. Remove node from its parent.
   // 10. Run the removing steps with node, parent, and oldPreviousSibling.
 
+  scoped_ptr<RegisteredObserverVector> observers =
+      GatherInclusiveAncestorsObservers();
+  if (!observers->empty()) {
+    // Step 7 - Queue a mutation record.
+    if (!suppress_observers) {
+      MutationReporter mutation_reporter(this, observers.Pass());
+      scoped_refptr<dom::NodeList> removed_nodes = new dom::NodeList();
+      removed_nodes->AppendNode(node);
+      mutation_reporter.ReportChildListMutation(
+          NULL, removed_nodes, node->previous_sibling_ /* previous_sibling */,
+          node->next_sibling_ /* next_sibling */);
+    }
+    // TODO: transient registered observers.
+  }
+
   if (node->previous_sibling_) {
     node->previous_sibling_->next_sibling_ = node->next_sibling_;
   } else {
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h
index 7e349d6..17f35e2 100644
--- a/src/cobalt/dom/node.h
+++ b/src/cobalt/dom/node.h
@@ -18,12 +18,16 @@
 #define COBALT_DOM_NODE_H_
 
 #include <string>
+#include <vector>
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "cobalt/base/token.h"
 #include "cobalt/dom/event_target.h"
+#include "cobalt/dom/mutation_observer.h"
+#include "cobalt/dom/mutation_observer_init.h"
+#include "cobalt/dom/registered_observer_list.h"
 
 namespace cobalt {
 namespace dom {
@@ -222,6 +226,15 @@
   // descendents.
   void PurgeCachedResourceReferencesRecursively();
 
+  bool RegisterMutationObserver(const scoped_refptr<MutationObserver>& observer,
+                                const MutationObserverInit& options) {
+    return registered_observers_.AddMutationObserver(observer, options);
+  }
+  void UnregisterMutationObserver(
+      const scoped_refptr<MutationObserver>& observer) {
+    registered_observers_.RemoveMutationObserver(observer);
+  }
+
   DEFINE_WRAPPABLE_TYPE(Node);
 
  protected:
@@ -255,6 +268,10 @@
   // Triggers a generation update in this node and all its ancestor nodes.
   void UpdateGenerationForNodeAndAncestors();
 
+  // Gather a list of RegisteredObservers on this node and its ancestors.
+  typedef std::vector<RegisteredObserver> RegisteredObserverVector;
+  scoped_ptr<RegisteredObserverVector> GatherInclusiveAncestorsObservers();
+
  private:
   // From EventTarget.
   std::string GetDebugName() OVERRIDE { return node_name().c_str(); }
@@ -268,11 +285,11 @@
 
   scoped_refptr<Node> PreInsert(const scoped_refptr<Node>& node,
                                 const scoped_refptr<Node>& child);
-  void Insert(const scoped_refptr<Node>& node,
-              const scoped_refptr<Node>& child);
+  void Insert(const scoped_refptr<Node>& node, const scoped_refptr<Node>& child,
+              bool suppress_observers);
 
   scoped_refptr<Node> PreRemove(const scoped_refptr<Node>& child);
-  void Remove(const scoped_refptr<Node>& node);
+  void Remove(const scoped_refptr<Node>& node, bool suppress_observers);
 
   // Called everytime mutation happens, i.e. when a child is inserted or removed
   // from this node.
@@ -293,6 +310,8 @@
   scoped_refptr<Node> first_child_;
   scoped_refptr<Node> next_sibling_;
 
+  RegisteredObserverList registered_observers_;
+
   DISALLOW_COPY_AND_ASSIGN(Node);
 };
 
diff --git a/src/cobalt/dom/node_dispatch_event_test.cc b/src/cobalt/dom/node_dispatch_event_test.cc
index 2051305..95b223c 100644
--- a/src/cobalt/dom/node_dispatch_event_test.cc
+++ b/src/cobalt/dom/node_dispatch_event_test.cc
@@ -59,7 +59,7 @@
 
 NodeDispatchEventTest::NodeDispatchEventTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, "") {
+                            NULL, NULL, NULL, NULL, NULL, "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
 
   document_ = new Document(&html_element_context_);
diff --git a/src/cobalt/dom/node_list_live_test.cc b/src/cobalt/dom/node_list_live_test.cc
index e3f757f..1ec534e 100644
--- a/src/cobalt/dom/node_list_live_test.cc
+++ b/src/cobalt/dom/node_list_live_test.cc
@@ -30,7 +30,7 @@
   NodeListLiveTest()
       : dom_stat_tracker_("NodeListLiveTest"),
         html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, &dom_stat_tracker_, ""),
+                              NULL, NULL, NULL, NULL, &dom_stat_tracker_, ""),
         document_(new Document(&html_element_context_)) {}
 
   ~NodeListLiveTest() OVERRIDE {}
diff --git a/src/cobalt/dom/node_list_test.cc b/src/cobalt/dom/node_list_test.cc
index c2e7b9a..3b52082 100644
--- a/src/cobalt/dom/node_list_test.cc
+++ b/src/cobalt/dom/node_list_test.cc
@@ -30,7 +30,8 @@
   NodeListTest()
       : dom_stat_tracker_(new DomStatTracker("NodeListTest")),
         html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, dom_stat_tracker_.get(), ""),
+                              NULL, NULL, NULL, NULL, dom_stat_tracker_.get(),
+                              ""),
         document_(new Document(&html_element_context_)) {}
 
   ~NodeListTest() OVERRIDE {}
diff --git a/src/cobalt/dom/node_test.cc b/src/cobalt/dom/node_test.cc
index a4abe5e..d7e6eda 100644
--- a/src/cobalt/dom/node_test.cc
+++ b/src/cobalt/dom/node_test.cc
@@ -78,7 +78,7 @@
 
 NodeTest::NodeTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, "") {
+                            NULL, NULL, NULL, NULL, NULL, "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
 
   document_ = new Document(&html_element_context_);
diff --git a/src/cobalt/dom/registered_observer.h b/src/cobalt/dom/registered_observer.h
new file mode 100644
index 0000000..ec46bf8
--- /dev/null
+++ b/src/cobalt/dom/registered_observer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_DOM_REGISTERED_OBSERVER_H_
+#define COBALT_DOM_REGISTERED_OBSERVER_H_
+
+#include "base/memory/ref_counted.h"
+#include "cobalt/dom/mutation_observer.h"
+#include "cobalt/dom/mutation_observer_init.h"
+
+namespace cobalt {
+namespace dom {
+
+class Node;
+
+// Represents the concept of a "registered observer" as described in the
+// Mutation Observer spec.
+// https://www.w3.org/TR/dom/#registered-observer
+// This class is expected to be used internally in the Node class as a part of
+// mutation reporting.
+class RegisteredObserver {
+ public:
+  // A RegisteredObserver must not outlive the |target| node that is being
+  // observed.
+  RegisteredObserver(const Node* target,
+                     const scoped_refptr<MutationObserver>& observer,
+                     const MutationObserverInit& options)
+      : target_(target), observer_(observer), options_(options) {}
+
+  const scoped_refptr<MutationObserver>& observer() const { return observer_; }
+  const MutationObserverInit& options() const { return options_; }
+  void set_options(const MutationObserverInit& options) { options_ = options; }
+  const Node* target() const { return target_; }
+
+ private:
+  const Node* target_;
+  scoped_refptr<MutationObserver> observer_;
+  MutationObserverInit options_;
+};
+}  // namespace dom
+}  // namespace cobalt
+#endif  // COBALT_DOM_REGISTERED_OBSERVER_H_
diff --git a/src/cobalt/dom/registered_observer_list.cc b/src/cobalt/dom/registered_observer_list.cc
new file mode 100644
index 0000000..4e86008
--- /dev/null
+++ b/src/cobalt/dom/registered_observer_list.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/dom/registered_observer_list.h"
+
+namespace cobalt {
+namespace dom {
+namespace {
+// This algorithm is part of the description of the observe() method. It may
+// modify |options| and returns false if a TypeError should be thrown.
+// https://www.w3.org/TR/dom/#dom-mutationobserver-observe
+bool InitializeOptions(MutationObserverInit* options) {
+  if (options->has_attribute_old_value() || options->has_attribute_filter()) {
+    // 1. If either options' attributeOldValue or attributeFilter is present and
+    //    options' attributes is omitted, set options' attributes to true.
+    if (!options->has_attributes()) {
+      options->set_attributes(true);
+    }
+    // 4. If options' attributeOldValue is true and options' attributes is
+    //    false, throw a JavaScript TypeError.
+    // 5. If options' attributeFilter is present and options' attributes is
+    //    false, throw a JavaScript TypeError.
+    if (!options->attributes()) {
+      return false;
+    }
+  }
+  if (options->has_character_data_old_value()) {
+    // 2. If options' characterDataOldValue is present and options'
+    //    characterData is omitted, set options' characterData to true.
+    if (!options->has_character_data()) {
+      options->set_character_data(true);
+    }
+    // 6. If options' characterDataOldValue is true and options' characterData
+    //    is false, throw a JavaScript TypeError.
+    if (!options->character_data()) {
+      return false;
+    }
+  }
+  // 3. If none of options' childList attributes, and characterData is true,
+  // throw a TypeError.
+  const bool child_list = options->child_list();
+  const bool attributes = options->has_attributes() && options->attributes();
+  const bool character_data =
+      options->has_character_data() && options->character_data();
+  if (!(child_list || attributes || character_data)) {
+    return false;
+  }
+  return true;
+}
+}  // namespace
+
+bool RegisteredObserverList::AddMutationObserver(
+    const scoped_refptr<MutationObserver>& observer,
+    const MutationObserverInit& const_options) {
+  MutationObserverInit options(const_options);
+  if (!InitializeOptions(&options)) {
+    return false;
+  }
+  // https://www.w3.org/TR/dom/#dom-mutationobserver-observe
+  // 7. For each registered observer registered in target's list of registered
+  //    observers whose observer is the context object:
+  //        1. Remove all transient registered observers whose source is
+  //           registered.
+  //        2. Replace registered's options with options.
+  typedef RegisteredObserverVector::iterator RegisteredObserverIterator;
+  for (RegisteredObserverIterator it = registered_observers_.begin();
+       it != registered_observers_.end(); ++it) {
+    // TODO: Remove transient registered observers.
+    if (it->observer() == observer) {
+      it->set_options(options);
+      return true;
+    }
+  }
+  // 8. Otherwise, add a new registered observer to target's list of registered
+  //    observers with the context object as the observer and options as the
+  //    options, and add target to context object's list of nodes on which it is
+  //    registered.
+  registered_observers_.push_back(
+      RegisteredObserver(target_, observer, options));
+  return true;
+}
+
+void RegisteredObserverList::RemoveMutationObserver(
+    const scoped_refptr<MutationObserver>& observer) {
+  typedef RegisteredObserverVector::iterator RegisteredObserverIterator;
+  for (RegisteredObserverIterator it = registered_observers_.begin();
+       it != registered_observers_.end(); ++it) {
+    if (it->observer() == observer) {
+      registered_observers_.erase(it);
+      return;
+    }
+  }
+  NOTREACHED() << "Did not find a mutation observer to unregister.";
+}
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/registered_observer_list.h b/src/cobalt/dom/registered_observer_list.h
new file mode 100644
index 0000000..8ab2365
--- /dev/null
+++ b/src/cobalt/dom/registered_observer_list.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_DOM_REGISTERED_OBSERVER_LIST_H_
+#define COBALT_DOM_REGISTERED_OBSERVER_LIST_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "cobalt/dom/mutation_observer.h"
+#include "cobalt/dom/mutation_observer_init.h"
+#include "cobalt/dom/registered_observer.h"
+
+namespace cobalt {
+namespace dom {
+
+class Node;
+
+// A list of "registered observers" as described in the Mutation Observer spec.
+// https://www.w3.org/TR/dom/#registered-observer
+//
+// Implements the functionality described in the MutationObserver.observe
+// method:
+// https://www.w3.org/TR/dom/#dom-mutationobserver-observe
+class RegisteredObserverList {
+ public:
+  typedef std::vector<RegisteredObserver> RegisteredObserverVector;
+
+  // A RegisteredObserverList must not outlive the |target| node that is being
+  // observed.
+  explicit RegisteredObserverList(const Node* target) : target_(target) {}
+
+  // Implement the MutationObserver.observe method
+  // https://www.w3.org/TR/dom/#dom-mutationobserver-observe
+  bool AddMutationObserver(const scoped_refptr<MutationObserver>& observer,
+                           const MutationObserverInit& options);
+  void RemoveMutationObserver(const scoped_refptr<MutationObserver>& observer);
+
+  const RegisteredObserverVector& registered_observers() {
+    return registered_observers_;
+  }
+
+ private:
+  const Node* target_;
+  RegisteredObserverVector registered_observers_;
+};
+}  // namespace dom
+}  // namespace cobalt
+#endif  // COBALT_DOM_REGISTERED_OBSERVER_LIST_H_
diff --git a/src/cobalt/dom/rule_matching_test.cc b/src/cobalt/dom/rule_matching_test.cc
index c8b1135..faf8f73 100644
--- a/src/cobalt/dom/rule_matching_test.cc
+++ b/src/cobalt/dom/rule_matching_test.cc
@@ -45,7 +45,7 @@
         dom_parser_(new dom_parser::Parser()),
         dom_stat_tracker_(new DomStatTracker("RuleMatchingTest")),
         html_element_context_(NULL, css_parser_.get(), dom_parser_.get(), NULL,
-                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                               dom_stat_tracker_.get(), ""),
         document_(new Document(&html_element_context_)),
         root_(document_->CreateElement("html")->AsHTMLElement()) {
diff --git a/src/cobalt/dom/serializer_test.cc b/src/cobalt/dom/serializer_test.cc
index dedcbe1..e6ccd63 100644
--- a/src/cobalt/dom/serializer_test.cc
+++ b/src/cobalt/dom/serializer_test.cc
@@ -47,7 +47,8 @@
     : dom_parser_(new dom_parser::Parser()),
       dom_stat_tracker_(new DomStatTracker("SerializerTest")),
       html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, dom_stat_tracker_.get(), ""),
+                            NULL, NULL, NULL, NULL, dom_stat_tracker_.get(),
+                            ""),
       document_(new Document(&html_element_context_)),
       root_(new Element(document_, base::Token("root"))),
       source_location_(base::SourceLocation("[object SerializerTest]", 1, 1)) {}
diff --git a/src/cobalt/dom/text_test.cc b/src/cobalt/dom/text_test.cc
index 5b504b8..381e24c 100644
--- a/src/cobalt/dom/text_test.cc
+++ b/src/cobalt/dom/text_test.cc
@@ -41,7 +41,7 @@
 
 TextTest::TextTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, "") {
+                            NULL, NULL, NULL, NULL, NULL, "") {
   EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
   document_ = new Document(&html_element_context_);
 }
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 57ee8a5..25b6106 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -68,6 +68,7 @@
                loader::image::ReducedCacheCapacityManager*
                    reduced_image_cache_capacity_manager,
                loader::font::RemoteTypefaceCache* remote_typeface_cache,
+               loader::mesh::MeshCache* mesh_cache,
                LocalStorageDatabase* local_storage_database,
                media::CanPlayTypeHandler* can_play_type_handler,
                media::WebMediaPlayerFactory* web_media_player_factory,
@@ -91,7 +92,7 @@
           fetcher_factory, css_parser, dom_parser, can_play_type_handler,
           web_media_player_factory, script_runner, media_source_registry,
           resource_provider, image_cache, reduced_image_cache_capacity_manager,
-          remote_typeface_cache, dom_stat_tracker, language)),
+          remote_typeface_cache, mesh_cache, dom_stat_tracker, language)),
       performance_(new Performance(new base::SystemMonotonicClock())),
       ALLOW_THIS_IN_INITIALIZER_LIST(document_(new Document(
           html_element_context_.get(),
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 8e48bc7..30a57d9 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -34,6 +34,7 @@
 #include "cobalt/dom/event_target.h"
 #include "cobalt/dom/media_query_list.h"
 #include "cobalt/dom/media_source.h"
+#include "cobalt/dom/mutation_observer_task_manager.h"
 #include "cobalt/dom/parser.h"
 #include "cobalt/network_bridge/cookie_jar.h"
 #include "cobalt/network_bridge/net_poster.h"
@@ -46,6 +47,7 @@
 #include "cobalt/loader/font/remote_typeface_cache.h"
 #include "cobalt/loader/image/image_cache.h"
 #include "cobalt/loader/loader.h"
+#include "cobalt/loader/mesh/mesh_cache.h"
 #include "cobalt/media/can_play_type_handler.h"
 #include "cobalt/media/web_media_player_factory.h"
 #include "cobalt/script/callback_function.h"
@@ -92,6 +94,7 @@
          loader::image::ReducedCacheCapacityManager*
              reduced_image_cache_capacity_manager,
          loader::font::RemoteTypefaceCache* remote_typeface_cache,
+         loader::mesh::MeshCache* mesh_cache,
          LocalStorageDatabase* local_storage_database,
          media::CanPlayTypeHandler* can_play_type_handler,
          media::WebMediaPlayerFactory* web_media_player_factory,
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc
index 8879146..fe10614 100644
--- a/src/cobalt/dom/window_test.cc
+++ b/src/cobalt/dom/window_test.cc
@@ -53,7 +53,7 @@
         url_("about:blank"),
         window_(new Window(
             1920, 1080, css_parser_.get(), dom_parser_.get(),
-            fetcher_factory_.get(), NULL, NULL, NULL, NULL,
+            fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL,
             &local_storage_database_, stub_media_module_.get(),
             stub_media_module_.get(), NULL, NULL, NULL, NULL, url_, "", "en-US",
             base::Callback<void(const GURL &)>(),
diff --git a/src/cobalt/dom/xml_document_test.cc b/src/cobalt/dom/xml_document_test.cc
index 4603520..e2e48a4 100644
--- a/src/cobalt/dom/xml_document_test.cc
+++ b/src/cobalt/dom/xml_document_test.cc
@@ -27,7 +27,7 @@
 TEST(XMLDocumentTest, IsXMLDocument) {
   HTMLElementContext html_element_context(NULL, NULL, NULL, NULL, NULL, NULL,
                                           NULL, NULL, NULL, NULL, NULL, NULL,
-                                          "");
+                                          NULL, "");
   scoped_refptr<Document> document = new XMLDocument(&html_element_context);
   EXPECT_TRUE(document->IsXMLDocument());
 }
diff --git a/src/cobalt/dom_parser/html_decoder_test.cc b/src/cobalt/dom_parser/html_decoder_test.cc
index 1aed737..9770fab 100644
--- a/src/cobalt/dom_parser/html_decoder_test.cc
+++ b/src/cobalt/dom_parser/html_decoder_test.cc
@@ -70,7 +70,7 @@
                             dom_parser_.get(), NULL /* can_play_type_handler */,
                             NULL /* web_media_player_factory */,
                             &stub_script_runner_, NULL, NULL, NULL, NULL, NULL,
-                            dom_stat_tracker_.get(), ""),
+                            NULL, dom_stat_tracker_.get(), ""),
       document_(
           new dom::Document(&html_element_context_, dom::Document::Options())),
       root_(new dom::Element(document_, base::Token("element"))),
diff --git a/src/cobalt/dom_parser/xml_decoder_test.cc b/src/cobalt/dom_parser/xml_decoder_test.cc
index e7336eb..218885b 100644
--- a/src/cobalt/dom_parser/xml_decoder_test.cc
+++ b/src/cobalt/dom_parser/xml_decoder_test.cc
@@ -51,7 +51,7 @@
 
 XMLDecoderTest::XMLDecoderTest()
     : html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, NULL, ""),
+                            NULL, NULL, NULL, NULL, NULL, ""),
       document_(new dom::XMLDocument(&html_element_context_)),
       source_location_(base::SourceLocation("[object XMLDecoderTest]", 1, 1)) {}
 
diff --git a/src/cobalt/h5vcc/H5vcc.idl b/src/cobalt/h5vcc/H5vcc.idl
index 6a24827..0e16d13 100644
--- a/src/cobalt/h5vcc/H5vcc.idl
+++ b/src/cobalt/h5vcc/H5vcc.idl
@@ -36,4 +36,5 @@
   readonly attribute H5vccSettings settings;
   readonly attribute H5vccStorage storage;
   readonly attribute H5vccSystem system;
+  readonly attribute H5vccTraceEvent traceEvent;
 };
diff --git a/src/cobalt/h5vcc/H5vccTraceEvent.idl b/src/cobalt/h5vcc/H5vccTraceEvent.idl
new file mode 100644
index 0000000..4e64778
--- /dev/null
+++ b/src/cobalt/h5vcc/H5vccTraceEvent.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface H5vccTraceEvent {
+  void start();
+  void stop();
+
+  void traceBegin(DOMString category, DOMString name);
+  void traceEnd(DOMString category, DOMString name);
+
+  void traceIntBegin(DOMString category, DOMString name,
+                     DOMString arg1_name, long arg1_value);
+  void traceIntEnd(DOMString category, DOMString name,
+                   DOMString arg1_name, long arg1_value);
+
+  void traceFloatBegin(DOMString category, DOMString name,
+                       DOMString arg1_name, float arg1_value);
+  void traceFloatEnd(DOMString category, DOMString name,
+                     DOMString arg1_name, float arg1_value);
+
+  void traceStringBegin(DOMString category, DOMString name,
+                        DOMString arg1_name, DOMString arg1_value);
+  void traceStringEnd(DOMString category, DOMString name,
+                      DOMString arg1_name, DOMString arg1_value);
+};
diff --git a/src/cobalt/h5vcc/h5vcc.cc b/src/cobalt/h5vcc/h5vcc.cc
index b220382..cb4633e 100644
--- a/src/cobalt/h5vcc/h5vcc.cc
+++ b/src/cobalt/h5vcc/h5vcc.cc
@@ -28,6 +28,7 @@
   settings_ = new H5vccSettings(settings.media_module);
   storage_ = new H5vccStorage(settings.network_module);
   system_ = new H5vccSystem(settings.media_module);
+  trace_event_ = new H5vccTraceEvent();
 }
 
 }  // namespace h5vcc
diff --git a/src/cobalt/h5vcc/h5vcc.gyp b/src/cobalt/h5vcc/h5vcc.gyp
index c208fd0..d23ac7c 100644
--- a/src/cobalt/h5vcc/h5vcc.gyp
+++ b/src/cobalt/h5vcc/h5vcc.gyp
@@ -52,6 +52,8 @@
         'h5vcc_storage.h',
         'h5vcc_system.cc',
         'h5vcc_system.h',
+        'h5vcc_trace_event.cc',
+        'h5vcc_trace_event.h',
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/build/cobalt_build_id.gyp:cobalt_build_id',
diff --git a/src/cobalt/h5vcc/h5vcc.h b/src/cobalt/h5vcc/h5vcc.h
index 369cad3..6f09230 100644
--- a/src/cobalt/h5vcc/h5vcc.h
+++ b/src/cobalt/h5vcc/h5vcc.h
@@ -27,6 +27,7 @@
 #include "cobalt/h5vcc/h5vcc_settings.h"
 #include "cobalt/h5vcc/h5vcc_storage.h"
 #include "cobalt/h5vcc/h5vcc_system.h"
+#include "cobalt/h5vcc/h5vcc_trace_event.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
@@ -59,6 +60,9 @@
   const scoped_refptr<H5vccSettings>& settings() const { return settings_; }
   const scoped_refptr<H5vccStorage>& storage() const { return storage_; }
   const scoped_refptr<H5vccSystem>& system() const { return system_; }
+  const scoped_refptr<H5vccTraceEvent>& trace_event() const {
+    return trace_event_;
+  }
 
   DEFINE_WRAPPABLE_TYPE(H5vcc);
 
@@ -70,6 +74,7 @@
   scoped_refptr<H5vccSettings> settings_;
   scoped_refptr<H5vccStorage> storage_;
   scoped_refptr<H5vccSystem> system_;
+  scoped_refptr<H5vccTraceEvent> trace_event_;
 
   DISALLOW_COPY_AND_ASSIGN(H5vcc);
 };
diff --git a/src/cobalt/h5vcc/h5vcc_trace_event.cc b/src/cobalt/h5vcc/h5vcc_trace_event.cc
new file mode 100644
index 0000000..ca43293
--- /dev/null
+++ b/src/cobalt/h5vcc/h5vcc_trace_event.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/h5vcc/h5vcc_trace_event.h"
+
+namespace cobalt {
+namespace h5vcc {
+
+namespace {
+const char* kOutputTraceFilename = "h5vcc_trace_event.json";
+}  // namespace
+
+H5vccTraceEvent::H5vccTraceEvent() {}
+
+void H5vccTraceEvent::Start() {
+  if (trace_to_file_) {
+    DLOG(WARNING) << "H5vccTraceEvent is already started.";
+  } else {
+    trace_to_file_.reset(
+        new trace_event::ScopedTraceToFile(FilePath(kOutputTraceFilename)));
+  }
+}
+
+void H5vccTraceEvent::Stop() {
+  if (trace_to_file_) {
+    trace_to_file_.reset();
+  } else {
+    DLOG(WARNING) << "H5vccTraceEvent is already stopped.";
+  }
+}
+
+}  // namespace h5vcc
+}  // namespace cobalt
diff --git a/src/cobalt/h5vcc/h5vcc_trace_event.h b/src/cobalt/h5vcc/h5vcc_trace_event.h
new file mode 100644
index 0000000..f3e45f6
--- /dev/null
+++ b/src/cobalt/h5vcc/h5vcc_trace_event.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_H5VCC_H5VCC_TRACE_EVENT_H_
+#define COBALT_H5VCC_H5VCC_TRACE_EVENT_H_
+
+#include <string>
+
+#include "base/debug/trace_event.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/trace_event/scoped_trace_to_file.h"
+
+namespace cobalt {
+namespace h5vcc {
+
+#define TRACE_EVENT0_FOR_EACH(MacroOp)   \
+  MacroOp(Begin, BEGIN)                  \
+  MacroOp(End, END)                      \
+
+#define DEFINE_H5VCC_TRACE_EVENT0(Name, FunctionName)                      \
+  void Trace##Name(const std::string& category, const std::string& name) { \
+    UNREFERENCED_PARAMETER(category);                                      \
+    UNREFERENCED_PARAMETER(name);                                          \
+    TRACE_EVENT_COPY_##FunctionName##0(category.c_str(), name.c_str());    \
+  }
+
+#define TRACE_EVENT1_FOR_EACH(MacroOp)                                \
+  MacroOp(IntBegin, BEGIN, int32)                                     \
+  MacroOp(IntEnd, END, int32)                                         \
+  MacroOp(FloatBegin, BEGIN, float)                                   \
+  MacroOp(FloatEnd, END, float)                                       \
+  MacroOp(StringBegin, BEGIN, const std::string&)                     \
+  MacroOp(StringEnd, END, const std::string&)
+
+#define DEFINE_H5VCC_TRACE_EVENT1(TraceName, FunctionName, CppType)           \
+  void Trace##TraceName(const std::string& category, const std::string& name, \
+                        const std::string& arg1_name, CppType arg1_value) {   \
+    UNREFERENCED_PARAMETER(category);                                         \
+    UNREFERENCED_PARAMETER(name);                                             \
+    UNREFERENCED_PARAMETER(arg1_name);                                        \
+    UNREFERENCED_PARAMETER(arg1_value);                                       \
+    TRACE_EVENT_COPY_##FunctionName##1(category.c_str(), name.c_str(),        \
+                                       arg1_name.c_str(), arg1_value);        \
+  }
+
+class H5vccTraceEvent : public script::Wrappable {
+ public:
+  H5vccTraceEvent();
+
+  void Start();
+  void Stop();
+
+  TRACE_EVENT0_FOR_EACH(DEFINE_H5VCC_TRACE_EVENT0)
+  TRACE_EVENT1_FOR_EACH(DEFINE_H5VCC_TRACE_EVENT1)
+
+  DEFINE_WRAPPABLE_TYPE(H5vccTraceEvent);
+
+ private:
+  // This object can be set to start a trace.
+  // While initialized, it means that a trace is on-going.
+  scoped_ptr<trace_event::ScopedTraceToFile> trace_to_file_;
+
+  DISALLOW_COPY_AND_ASSIGN(H5vccTraceEvent);
+};
+
+#undef DEFINE_H5VCC_TRACE_EVENT0
+#undef TRACE_EVENT0_FOR_EACH
+#undef DEFINE_H5VCC_TRACE_EVENT1
+#undef TRACE_EVENT1_FOR_EACH
+
+}  // namespace h5vcc
+}  // namespace cobalt
+
+#endif  // COBALT_H5VCC_H5VCC_TRACE_EVENT_H_
diff --git a/src/cobalt/layout/layout_manager.cc b/src/cobalt/layout/layout_manager.cc
index 1639aa5..aa2f4d9 100644
--- a/src/cobalt/layout/layout_manager.cc
+++ b/src/cobalt/layout/layout_manager.cc
@@ -108,8 +108,10 @@
     : window_(window),
       locale_(icu::Locale::createCanonical(language.c_str())),
       used_style_provider_(
-          new UsedStyleProvider(window->html_element_context()->image_cache(),
-                                window->document()->font_cache())),
+          new UsedStyleProvider(window->html_element_context(),
+                                window->html_element_context()->image_cache(),
+                                window->document()->font_cache(),
+                                window->html_element_context()->mesh_cache())),
       on_render_tree_produced_callback_(on_render_tree_produced),
       layout_trigger_(layout_trigger),
       layout_dirty_(StringPrintf("%s.Layout.IsDirty", name.c_str()), true,
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 7bcb96a..0163f06 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -20,6 +20,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/cssom/filter_function_list_value.h"
 #include "cobalt/cssom/keyword_value.h"
 #include "cobalt/cssom/mtm_function.h"
@@ -284,13 +285,34 @@
   const cssom::MTMFunction* mtm_filter_function =
       cssom::MTMFunction::ExtractFromFilterList(computed_style()->filter());
 
-  Node* content_node;
+  Node* content_node = NULL;
   if (mtm_filter_function) {
+    const cssom::MTMFunction::MeshSpec& spec = mtm_filter_function->mesh_spec();
     const scoped_refptr<cssom::KeywordValue>& stereo_mode_keyword_value =
         mtm_filter_function->stereo_mode();
     render_tree::StereoMode stereo_mode =
         ReadStereoMode(stereo_mode_keyword_value);
-    content_node = new FilterNode(MapToMeshFilter(stereo_mode), frame_node);
+
+    if (spec.mesh_type() == cssom::MTMFunction::kUrls) {
+      // Custom mesh URLs.
+      cssom::URLValue* url_value =
+          base::polymorphic_downcast<cssom::URLValue*>(spec.mesh_url().get());
+      GURL url(url_value->value());
+      scoped_refptr<render_tree::Mesh> mesh(
+          used_style_provider()->ResolveURLToMesh(url));
+
+      DCHECK(mesh) << "Could not load mesh specified by map-to-mesh filter.";
+
+      content_node =
+          new FilterNode(MapToMeshFilter(stereo_mode, mesh), frame_node);
+    } else if (spec.mesh_type() == cssom::MTMFunction::kEquirectangular) {
+      // Default equirectangular mesh.
+      content_node = new FilterNode(MapToMeshFilter(stereo_mode), frame_node);
+    } else {
+      NOTREACHED() << "Invalid mesh specification type. Expected"
+                      "'equirectangular' keyword or list of URLs.";
+      content_node = frame_node;
+    }
   } else {
     content_node = frame_node;
   }
diff --git a/src/cobalt/layout/used_style.cc b/src/cobalt/layout/used_style.cc
index 26cc44d..0464bf9 100644
--- a/src/cobalt/layout/used_style.cc
+++ b/src/cobalt/layout/used_style.cc
@@ -40,6 +40,7 @@
 #include "cobalt/cssom/transform_function_visitor.h"
 #include "cobalt/cssom/transform_matrix_function_value.h"
 #include "cobalt/cssom/translate_function.h"
+#include "cobalt/loader/mesh/mesh_cache.h"
 #include "cobalt/math/transform_2d.h"
 #include "cobalt/render_tree/brush.h"
 #include "cobalt/render_tree/composition_node.h"
@@ -406,9 +407,14 @@
 
 }  // namespace
 
-UsedStyleProvider::UsedStyleProvider(loader::image::ImageCache* image_cache,
-                                     dom::FontCache* font_cache)
-    : image_cache_(image_cache), font_cache_(font_cache) {}
+UsedStyleProvider::UsedStyleProvider(
+    dom::HTMLElementContext* html_element_context,
+    loader::image::ImageCache* image_cache, dom::FontCache* font_cache,
+    loader::mesh::MeshCache* mesh_cache)
+    : html_element_context_(html_element_context),
+      image_cache_(image_cache),
+      font_cache_(font_cache),
+      mesh_cache_(mesh_cache) {}
 
 scoped_refptr<dom::FontList> UsedStyleProvider::GetUsedFontList(
     const scoped_refptr<cssom::PropertyValue>& font_family_refptr,
@@ -465,6 +471,12 @@
   return image_cache_->CreateCachedResource(url)->TryGetResource();
 }
 
+scoped_refptr<render_tree::Mesh> UsedStyleProvider::ResolveURLToMesh(
+    const GURL& url) {
+  DCHECK(mesh_cache_);
+  return mesh_cache_->CreateCachedResource(url)->TryGetResource();
+}
+
 void UsedStyleProvider::CleanupAfterLayout() {
   // Clear out the last font properties prior to requesting that the font cache
   // process inactive font lists. The reason for this is that the font cache
diff --git a/src/cobalt/layout/used_style.h b/src/cobalt/layout/used_style.h
index 8c964a1..b3212c9 100644
--- a/src/cobalt/layout/used_style.h
+++ b/src/cobalt/layout/used_style.h
@@ -27,12 +27,14 @@
 #include "cobalt/cssom/transform_matrix.h"
 #include "cobalt/dom/font_cache.h"
 #include "cobalt/dom/font_list.h"
+#include "cobalt/dom/html_element_context.h"
 #include "cobalt/layout/layout_unit.h"
 #include "cobalt/layout/size_layout_unit.h"
 #include "cobalt/loader/image/image_cache.h"
 #include "cobalt/math/size.h"
 #include "cobalt/math/size_f.h"
 #include "cobalt/render_tree/color_rgba.h"
+#include "cobalt/render_tree/mesh.h"
 #include "cobalt/render_tree/node.h"
 #include "cobalt/render_tree/resource_provider.h"
 #include "cobalt/render_tree/rounded_corners.h"
@@ -56,8 +58,10 @@
 
 class UsedStyleProvider {
  public:
-  UsedStyleProvider(loader::image::ImageCache* image_cache,
-                    dom::FontCache* font_cache);
+  UsedStyleProvider(dom::HTMLElementContext* html_element_context,
+                    loader::image::ImageCache* image_cache,
+                    dom::FontCache* font_cache,
+                    loader::mesh::MeshCache* mesh_cache = NULL);
 
   scoped_refptr<dom::FontList> GetUsedFontList(
       const scoped_refptr<cssom::PropertyValue>& font_family_refptr,
@@ -66,19 +70,26 @@
       const scoped_refptr<cssom::PropertyValue>& font_weight_refptr);
 
   scoped_refptr<render_tree::Image> ResolveURLToImage(const GURL& url);
+  scoped_refptr<render_tree::Mesh> ResolveURLToMesh(const GURL& url);
 
   bool has_image_cache(const loader::image::ImageCache* image_cache) const {
     return image_cache == image_cache_;
   }
 
+  dom::HTMLElementContext* html_element_context() const {
+    return html_element_context_;
+  }
+
  private:
   // Called after layout is completed so that it can perform any necessary
   // cleanup. Its primary current purpose is making a request to the font cache
   // to remove any font lists that are no longer being referenced by boxes.
   void CleanupAfterLayout();
 
+  dom::HTMLElementContext* html_element_context_;
   loader::image::ImageCache* const image_cache_;
   dom::FontCache* const font_cache_;
+  loader::mesh::MeshCache* const mesh_cache_;
 
   // |font_list_key_| is retained in between lookups so that the font names
   // vector will not need to allocate elements each time that it is populated.
diff --git a/src/cobalt/loader/blob_fetcher.cc b/src/cobalt/loader/blob_fetcher.cc
index d6a48b8..4118206 100644
--- a/src/cobalt/loader/blob_fetcher.cc
+++ b/src/cobalt/loader/blob_fetcher.cc
@@ -29,9 +29,8 @@
       resolver_callback_(resolver_callback),
       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
   DCHECK(!resolver_callback_.is_null());
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      base::Bind(&BlobFetcher::Fetch, weak_ptr_factory_.GetWeakPtr()));
+
+  Fetch();
 }
 
 void BlobFetcher::Fetch() {
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp
index 45f5be4..3dd867c 100644
--- a/src/cobalt/loader/loader.gyp
+++ b/src/cobalt/loader/loader.gyp
@@ -58,6 +58,7 @@
         'loader_factory.cc',
         'loader_factory.h',
         'loader_types.h',
+        'mesh/mesh_cache.h',
         'mesh/mesh_decoder.cc',
         'mesh/mesh_decoder.h',
         'mesh/projection_codec/constants.h',
@@ -172,6 +173,7 @@
       'sources': [
         '<(input_directory)/splash_screen.css',
         '<(input_directory)/splash_screen.html',
+        '<(input_directory)/splash_screen.js',
         '<(input_directory)/you_tube_logo.png',
       ],
       'actions': [
@@ -184,7 +186,7 @@
           'outputs': [
             '<(output_path)',
           ],
-          'action': ['python', '<(script_path)', 'LoaderEmbeddedResources', '<(input_directory)', '<(output_path)'],
+          'action': ['python', '<(script_path)', 'LoaderEmbeddedResources', '<(output_path)', '<(input_directory)'],
           'message': 'Embedding layout resources in "<(input_directory)" into header file, "<(output_path)".',
         },
       ],
diff --git a/src/cobalt/loader/mesh/mesh_cache.h b/src/cobalt/loader/mesh/mesh_cache.h
new file mode 100644
index 0000000..4e01047
--- /dev/null
+++ b/src/cobalt/loader/mesh/mesh_cache.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_LOADER_MESH_MESH_CACHE_H_
+#define COBALT_LOADER_MESH_MESH_CACHE_H_
+
+#include <string>
+
+#include "cobalt/loader/loader_factory.h"
+#include "cobalt/loader/resource_cache.h"
+#include "cobalt/render_tree/mesh.h"
+
+namespace cobalt {
+namespace loader {
+namespace mesh {
+
+// |MeshResourceCacheType| provides the types and implements the functions
+// required by |ResourceCache<MeshResourceCacheType>|
+struct MeshResourceCacheType {
+  typedef render_tree::Mesh ResourceType;
+
+  static uint32 GetEstimatedSizeInBytes(
+      const scoped_refptr<ResourceType>& resource) {
+    return resource->GetEstimatedSizeInBytes();
+  }
+};
+
+typedef CachedResource<MeshResourceCacheType> CachedMesh;
+typedef CachedResourceReferenceWithCallbacks<MeshResourceCacheType>
+    CachedMeshReferenceWithCallbacks;
+typedef CachedMeshReferenceWithCallbacks::CachedResourceReferenceVector
+    CachedMeshReferenceVector;
+
+typedef ResourceCache<MeshResourceCacheType> MeshCache;
+
+// CreateMeshCache() provides a mechanism for creating an |MeshCache|.
+inline static scoped_ptr<MeshCache> CreateMeshCache(
+    const std::string& name, uint32 cache_capacity,
+    loader::LoaderFactory* loader_factory) {
+  return make_scoped_ptr<MeshCache>(new MeshCache(
+      name, cache_capacity, base::Bind(&loader::LoaderFactory::CreateMeshLoader,
+                                       base::Unretained(loader_factory))));
+}
+
+}  // namespace mesh
+}  // namespace loader
+}  // namespace cobalt
+
+#endif  // COBALT_LOADER_MESH_MESH_CACHE_H_
diff --git a/src/cobalt/loader/mesh/mesh_decoder.cc b/src/cobalt/loader/mesh/mesh_decoder.cc
index 7333776..5b41f44 100644
--- a/src/cobalt/loader/mesh/mesh_decoder.cc
+++ b/src/cobalt/loader/mesh/mesh_decoder.cc
@@ -74,6 +74,7 @@
   scoped_ptr<MeshCollection> mesh_collection_;
   std::vector<render_tree::Mesh::Vertex> mesh_vertices_;
   render_tree::Mesh::DrawMode mesh_draw_mode_;
+  uint32 crc_;
 
   DISALLOW_COPY_AND_ASSIGN(MeshDecoderSink);
 };
@@ -84,7 +85,7 @@
 MeshDecoderSink::~MeshDecoderSink() {}
 
 bool MeshDecoderSink::IsCached(uint32 crc) {
-  UNREFERENCED_PARAMETER(crc);
+  crc_ = crc;
   return false;
 }
 
@@ -140,7 +141,7 @@
 
 void MeshDecoderSink::EndMeshInstance() {
   mesh_collection_->push_back(scoped_refptr<render_tree::Mesh>(
-      new render_tree::Mesh(mesh_vertices_, mesh_draw_mode_)));
+      new render_tree::Mesh(mesh_vertices_, mesh_draw_mode_, crc_)));
 }
 
 void MeshDecoderSink::EndMeshCollection() {
@@ -215,9 +216,9 @@
     return;
   }
 
-  if (raw_data_->size() == 0) {
-    // Mesh projection boxes cannot be empty, since they are BMFF boxes and
-    // carry at least a size and type 4cc.
+  if (raw_data_->size() <= 4) {
+    // Mesh projection boxes cannot be empty, since they carry at least the
+    // version and flags.
     error_callback_.Run("MeshDecoder passed an empty buffer, cannot decode.");
     return;
   }
@@ -225,8 +226,9 @@
   std::string error_string;
   MeshDecoderSink::MeshCollectionList mesh_collection_list;
 
-  if (MeshDecoderSink::Decode(&raw_data_->at(0), raw_data_->size(),
-                              &mesh_collection_list)) {
+  if (MeshDecoderSink::DecodeBoxContents(
+          0, 0, &raw_data_->at(4),  // Skip version and flags.
+          raw_data_->size(), &mesh_collection_list)) {
     scoped_refptr<render_tree::Mesh> mesh =
         MeshDecoderSink::ExtractSingleMesh(mesh_collection_list);
 
diff --git a/src/cobalt/loader/mesh/mesh_decoder.h b/src/cobalt/loader/mesh/mesh_decoder.h
index d11e210..1558acd 100644
--- a/src/cobalt/loader/mesh/mesh_decoder.h
+++ b/src/cobalt/loader/mesh/mesh_decoder.h
@@ -41,6 +41,15 @@
               const SuccessCallback& success_callback,
               const ErrorCallback& error_callback);
 
+  // This function is used for binding a callback to create a MeshDecoder.
+  static scoped_ptr<Decoder> Create(
+      render_tree::ResourceProvider* resource_provider,
+      const SuccessCallback& success_callback,
+      const ErrorCallback& error_callback) {
+    return scoped_ptr<Decoder>(
+        new MeshDecoder(resource_provider, success_callback, error_callback));
+  }
+
   // From Decoder.
   void DecodeChunk(const char* data, size_t size) OVERRIDE;
   void Finish() OVERRIDE;
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h
index d829a35..335c90c 100644
--- a/src/cobalt/loader/resource_cache.h
+++ b/src/cobalt/loader/resource_cache.h
@@ -144,6 +144,8 @@
 
   void RunCallbacks(CallbackType type);
 
+  void EnableCompletionCallbacks();
+
   const GURL url_;
 
   scoped_refptr<ResourceType> resource_;
@@ -154,6 +156,14 @@
 
   base::ThreadChecker cached_resource_thread_checker_;
 
+  // In some cases (such as when the resource input data is stored in memory),
+  // completion callbacks (e.g. resource fetch success/failure) could be
+  // triggered from within the resource initialization callstack, and we are
+  // not prepared to handle that. These members let us ensure that we are fully
+  // initialized before we proceed with any completion callbacks.
+  bool completion_callbacks_enabled_;
+  base::Closure completion_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(CachedResource);
 };
 
@@ -207,7 +217,9 @@
     const GURL& url, const csp::SecurityCallback& security_callback,
     const CreateLoaderFunction& create_loader_function,
     ResourceCacheType* resource_cache)
-    : url_(url), resource_cache_(resource_cache) {
+    : url_(url),
+      resource_cache_(resource_cache),
+      completion_callbacks_enabled_(false) {
   DCHECK(cached_resource_thread_checker_.CalledOnValidThread());
 
   loader_ = create_loader_function.Run(
@@ -220,7 +232,10 @@
 CachedResource<CacheType>::CachedResource(const GURL& url,
                                           ResourceType* resource,
                                           ResourceCacheType* resource_cache)
-    : url_(url), resource_(resource), resource_cache_(resource_cache) {
+    : url_(url),
+      resource_(resource),
+      resource_cache_(resource_cache),
+      completion_callbacks_enabled_(false) {
   DCHECK(cached_resource_thread_checker_.CalledOnValidThread());
 }
 
@@ -256,8 +271,14 @@
   resource_ = resource;
 
   loader_.reset();
-  resource_cache_->NotifyResourceLoadingComplete(this,
-                                                 kOnLoadingSuccessCallbackType);
+
+  completion_callback_ =
+      base::Bind(&ResourceCacheType::NotifyResourceLoadingComplete,
+                 base::Unretained(resource_cache_), base::Unretained(this),
+                 kOnLoadingSuccessCallbackType);
+  if (completion_callbacks_enabled_) {
+    completion_callback_.Run();
+  }
 }
 
 template <typename CacheType>
@@ -267,8 +288,13 @@
   LOG(WARNING) << "Error while loading '" << url_ << "': " << error;
 
   loader_.reset();
-  resource_cache_->NotifyResourceLoadingComplete(this,
-                                                 kOnLoadingErrorCallbackType);
+  completion_callback_ =
+      base::Bind(&ResourceCacheType::NotifyResourceLoadingComplete,
+                 base::Unretained(resource_cache_), base::Unretained(this),
+                 kOnLoadingErrorCallbackType);
+  if (completion_callbacks_enabled_) {
+    completion_callback_.Run();
+  }
 }
 
 template <typename CacheType>
@@ -304,6 +330,14 @@
   }
 }
 
+template <typename CacheType>
+void CachedResource<CacheType>::EnableCompletionCallbacks() {
+  completion_callbacks_enabled_ = true;
+  if (!completion_callback_.is_null()) {
+    completion_callback_.Run();
+  }
+}
+
 //////////////////////////////////////////////////////////////////////////
 // CachedResourceReferenceWithCallbacks
 //////////////////////////////////////////////////////////////////////////
@@ -563,6 +597,12 @@
       url, security_callback_, create_loader_function_, this));
   cached_resource_map_.insert(
       std::make_pair(url.spec(), cached_resource.get()));
+
+  // Only now that we are finished initializing |cached_resource|, allow
+  // completion callbacks to proceed. This can be an issue for resources that
+  // load and decode synchronously and immediately.
+  cached_resource->EnableCompletionCallbacks();
+
   return cached_resource;
 }
 
diff --git a/src/cobalt/loader/testdata/projection.box b/src/cobalt/loader/testdata/projection.box
index 22a3bb5..1e5cdff 100644
--- a/src/cobalt/loader/testdata/projection.box
+++ b/src/cobalt/loader/testdata/projection.box
Binary files differ
diff --git a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
index 1c18737..9c00b58 100644
--- a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
+++ b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
@@ -88,6 +88,11 @@
       case kSbSystemDeviceTypeTV:
         youtube_tv_info_->device_type = YouTubeTVInfo::kTV;
         break;
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+      case kSbSystemDeviceTypeAndroidTV:
+        youtube_tv_info_->device_type = YouTubeTVInfo::kAndroidTV;
+        break;
+#endif  // SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
       case kSbSystemDeviceTypeDesktopPC:
       default:
         youtube_tv_info_->device_type = YouTubeTVInfo::kInvalidDeviceType;
diff --git a/src/cobalt/network/user_agent_string_factory.cc b/src/cobalt/network/user_agent_string_factory.cc
index 77a7628..12fe0ef 100644
--- a/src/cobalt/network/user_agent_string_factory.cc
+++ b/src/cobalt/network/user_agent_string_factory.cc
@@ -109,6 +109,10 @@
       return "STB";
     case YouTubeTVInfo::kTV:
       return "TV";
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+    case YouTubeTVInfo::kAndroidTV:
+      return "ATV";
+#endif  // SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
     case YouTubeTVInfo::kInvalidDeviceType:
     default:
       NOTREACHED();
diff --git a/src/cobalt/network/user_agent_string_factory.h b/src/cobalt/network/user_agent_string_factory.h
index b391595..8d73c3b 100644
--- a/src/cobalt/network/user_agent_string_factory.h
+++ b/src/cobalt/network/user_agent_string_factory.h
@@ -48,6 +48,9 @@
   struct YouTubeTVInfo {
     enum DeviceType {
       kInvalidDeviceType,
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+      kAndroidTV,
+#endif  // SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
       kBlueRayDiskPlayer,
       kGameConsole,
       kOverTheTopBox,
diff --git a/src/cobalt/render_tree/map_to_mesh_filter.h b/src/cobalt/render_tree/map_to_mesh_filter.h
index 0f996fa..29448d5 100644
--- a/src/cobalt/render_tree/map_to_mesh_filter.h
+++ b/src/cobalt/render_tree/map_to_mesh_filter.h
@@ -19,6 +19,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "cobalt/render_tree/mesh.h"
 
 namespace cobalt {
 namespace render_tree {
@@ -26,16 +27,21 @@
 enum StereoMode { kMono, kLeftRight, kTopBottom };
 
 // A MapToMeshFilter can be used to map source content onto a 3D mesh, within a
-// specified well-defined viewport.
+// specified well-defined viewport. A null mesh indicates the equirectangular
+// mesh should be used.
 class MapToMeshFilter {
  public:
-  explicit MapToMeshFilter(const StereoMode stereo_mode)
-      : stereo_mode_(stereo_mode) {}
+  explicit MapToMeshFilter(const StereoMode stereo_mode,
+                           scoped_refptr<render_tree::Mesh> mesh = NULL)
+      : stereo_mode_(stereo_mode), mesh_(mesh) {}
 
   StereoMode GetStereoMode() const { return stereo_mode_; }
 
+  scoped_refptr<render_tree::Mesh> mesh() const { return mesh_; }
+
  private:
   StereoMode stereo_mode_;
+  scoped_refptr<render_tree::Mesh> mesh_;
 };
 
 }  // namespace render_tree
diff --git a/src/cobalt/render_tree/mesh.h b/src/cobalt/render_tree/mesh.h
index 334bd60..25c1def 100644
--- a/src/cobalt/render_tree/mesh.h
+++ b/src/cobalt/render_tree/mesh.h
@@ -22,6 +22,7 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "starboard/types.h"
 #include "third_party/glm/glm/vec2.hpp"
 #include "third_party/glm/glm/vec3.hpp"
@@ -52,18 +53,25 @@
     kDrawModeTriangleFan = 6
   };
 
-  Mesh(const std::vector<Vertex>& vertices, const DrawMode mode)
-      : vertices_(vertices), draw_mode_(CheckDrawMode(mode)) {}
+  Mesh(const std::vector<Vertex>& vertices, const DrawMode mode,
+       base::optional<uint32> crc = base::nullopt)
+      : vertices_(vertices), draw_mode_(CheckDrawMode(mode)), crc_(crc) {}
 
   const std::vector<Vertex>& vertices() const { return vertices_; }
 
   DrawMode draw_mode() const { return draw_mode_; }
 
+  const base::optional<uint32>& crc() const { return crc_; }
+
   uint32 GetEstimatedSizeInBytes() const {
     return static_cast<uint32>(vertices().size() * sizeof(Vertex) +
                                sizeof(DrawMode));
   }
 
+  bool HasSameCrcAs(scoped_refptr<Mesh> other_mesh) const {
+    return other_mesh && other_mesh->crc() == crc_;
+  }
+
  protected:
   virtual ~Mesh() {}
 
@@ -86,6 +94,9 @@
 
   const std::vector<Vertex> vertices_;
   const DrawMode draw_mode_;
+  // Cyclic Redundancy Check code of the mesh projection box that contains this
+  // mesh.
+  const base::optional<uint32> crc_;
 };
 
 }  // namespace render_tree
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index fabca63..c3ab6cd 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -64,7 +64,7 @@
   // Create a dummy EGLSurface object to be assigned as the target surface
   // when we need to make OpenGL calls that do not depend on a surface (e.g.
   // creating a texture).
-  null_surface_ = new PBufferRenderTargetEGL(display, config, math::Size(1, 1));
+  null_surface_ = new PBufferRenderTargetEGL(display, config, math::Size(0, 0));
 
   ScopedMakeCurrent scoped_current_context(this);
 
diff --git a/src/cobalt/renderer/backend/egl/graphics_system.cc b/src/cobalt/renderer/backend/egl/graphics_system.cc
index a83bb00..7a73c9c 100644
--- a/src/cobalt/renderer/backend/egl/graphics_system.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_system.cc
@@ -75,8 +75,10 @@
                              8,
                              EGL_ALPHA_SIZE,
                              8,
+#if !SB_HAS_QUIRK(NO_EGL_BIND_TO_TEXTURE)
                              EGL_BIND_TO_TEXTURE_RGBA,
                              EGL_TRUE,
+#endif
                              EGL_RENDERABLE_TYPE,
                              EGL_OPENGL_ES2_BIT,
                              EGL_NONE};
diff --git a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
index d7af3f7..0634c82 100644
--- a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
+++ b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
@@ -35,6 +35,14 @@
       EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
       EGL_NONE,
   };
+  // When a dummy 0-area render target is requested, it will not be used as a
+  // drawing target and we therefore don't require for it to be a texture.
+  if (dimensions.height() == 0 && dimensions.width() == 0) {
+    // Fake 1x1 to avoid an arithmetic error (SIGFPE) in eglMakeCurrent() on
+    // some platforms.
+    surface_attrib_list[1] = surface_attrib_list[3] = 1;
+    surface_attrib_list[4] = EGL_NONE;
+  }
 
   surface_ =
     eglCreatePbufferSurface(display_, config_, surface_attrib_list);
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/vertex_mesh.glsl b/src/cobalt/renderer/glimp_shaders/glsl/vertex_mesh.glsl
index b41b78f..81611c6 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/vertex_mesh.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/vertex_mesh.glsl
@@ -1,11 +1,10 @@
 attribute vec3 a_position;

 attribute vec2 a_tex_coord;

 varying vec2 v_tex_coord;

-uniform vec2 u_tex_offset;

-uniform vec2 u_tex_multiplier;

+uniform mat3 u_tex_transform;

 uniform mat4 u_mvp_matrix;

 void main() {

   gl_Position = u_mvp_matrix * vec4(a_position.xyz, 1.0);

-  v_tex_coord.x = a_tex_coord.x * u_tex_multiplier.x + u_tex_offset.x;

-  v_tex_coord.y = a_tex_coord.y * u_tex_multiplier.y + u_tex_offset.y;

+  vec3 tex_coord = u_tex_transform * vec3(a_tex_coord, 1.0);

+  v_tex_coord = tex_coord.xy;

 }

diff --git a/src/cobalt/script/engine.gyp b/src/cobalt/script/engine.gyp
index 18af9d8..ddb6e3e 100644
--- a/src/cobalt/script/engine.gyp
+++ b/src/cobalt/script/engine.gyp
@@ -31,16 +31,8 @@
       # building 'all'.
       'target_name': 'all_engines',
       'type': 'none',
-      'conditions': [
-        ['OS == "starboard"', {
-          'dependencies': [
-            'mozjs/mozjs.gyp:*',
-          ],
-        }, {  #else
-          'dependencies': [
-            'javascriptcore/javascriptcore.gyp:*',
-          ],
-        }],
+      'dependencies': [
+        'mozjs/mozjs.gyp:*',
       ],
     },
   ],
diff --git a/src/cobalt/script/engine_variables.gypi b/src/cobalt/script/engine_variables.gypi
index 98f91e8..98f413c 100644
--- a/src/cobalt/script/engine_variables.gypi
+++ b/src/cobalt/script/engine_variables.gypi
@@ -14,7 +14,6 @@
 
 {
   'includes': [
-    'javascriptcore/javascriptcore_variables.gypi',
     'mozjs/mozjs_variables.gypi',
     'mozjs-45/mozjs-45_variables.gypi',
   ],
diff --git a/src/cobalt/script/javascriptcore/constructor_base.h b/src/cobalt/script/javascriptcore/constructor_base.h
deleted file mode 100644
index ab192f1..0000000
--- a/src/cobalt/script/javascriptcore/constructor_base.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_CONSTRUCTOR_BASE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_CONSTRUCTOR_BASE_H_
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// All JavaScriptCore interface object classes will inherit from this.
-class ConstructorBase : public JSC::JSFunction {
- public:
-  // static override. This prevents this object from being called as a normal
-  // function, throwing a TypeError if the user attempts to do so.
-  static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&) {
-    return JSC::CallTypeNone;
-  }
-
- protected:
-  ConstructorBase(JSC::ExecState* exec_state,
-                  JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : JSC::JSFunction(exec_state, global_object, structure) {}
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_CONSTRUCTOR_BASE_H_
diff --git a/src/cobalt/script/javascriptcore/conversion_helpers.cc b/src/cobalt/script/javascriptcore/conversion_helpers.cc
deleted file mode 100644
index 9484c0d..0000000
--- a/src/cobalt/script/javascriptcore/conversion_helpers.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSScope.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSString.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-JSC::JSValue StringToJSValue(JSC::JSGlobalData* global_data,
-                             const std::string& utf8_string) {
-  WTF::String wtf_string = ToWTFString(utf8_string);
-  JSC::JSString* js_string = JSC::jsString(global_data, wtf_string);
-  JSC::JSValue string_value(js_string);
-  DCHECK(string_value.isString());
-  return string_value;
-}
-
-void JSValueToString(JSC::ExecState* exec_state, JSC::JSValue value,
-                     std::string* out_string) {
-  // By default null and undefined evaluate to the strings "null" and
-  // "undefined" respectively.
-  // TODO: Optimize this.
-  JSC::JSString* js_string = value.toString(exec_state);
-  const WTF::String& wtf_string = js_string->value(exec_state);
-  *out_string = FromWTFString(wtf_string);
-}
-
-JSC::JSValue TokenToJSValue(JSC::JSGlobalData* global_data,
-                            base::Token utf8_string) {
-  WTF::String wtf_string = ToWTFString(utf8_string.c_str());
-  JSC::JSString* js_string = JSC::jsString(global_data, wtf_string);
-  JSC::JSValue string_value(js_string);
-  DCHECK(string_value.isString());
-  return string_value;
-}
-
-WTF::String ToWTFString(const std::string& utf8_string) {
-  WTF::String wtf_string;
-  // If the string is all ASCII, we can convert it using half the memory of
-  // the generalized conversion function. This is significant as  uses
-  // some huge ASCII-only source files (> 10M chars).
-  if (IsStringASCII(utf8_string)) {
-    wtf_string = WTF::String(utf8_string.c_str(), utf8_string.length());
-  }
-
-  wtf_string = WTF::String::fromUTF8(utf8_string.c_str());
-  if (wtf_string.isNull()) {
-    if (!IsStringUTF8(utf8_string)) {
-      DLOG(ERROR) << "Non-UTF8 characters in input string";
-    } else {
-      DLOG(ERROR) << "Unknown error converting to WTFString";
-    }
-    wtf_string = WTF::String::fromUTF8("");
-  }
-  return wtf_string;
-}
-
-std::string FromWTFString(const WTF::String& wtf_string) {
-  WTF::CString utf8_string = wtf_string.utf8();
-  return std::string(utf8_string.data(), utf8_string.length());
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/conversion_helpers.h b/src/cobalt/script/javascriptcore/conversion_helpers.h
deleted file mode 100644
index 3b30135..0000000
--- a/src/cobalt/script/javascriptcore/conversion_helpers.h
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_CONVERSION_HELPERS_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_CONVERSION_HELPERS_H_
-
-#include <limits>
-#include <string>
-
-#include "base/logging.h"
-#include "base/optional.h"
-#include "cobalt/base/enable_if.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/base/token.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function_holder.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/union_type_conversion_forward.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Flags that can be used as a bitmask for special conversion behaviour.
-enum ConversionFlags {
-  kNoConversionFlags = 0,
-  kConversionFlagRestricted = 1 << 0,
-  kConversionFlagNullable = 1 << 1,
-  kConversionFlagTreatNullAsEmptyString = 1 << 2,
-  kConversionFlagTreatUndefinedAsEmptyString = 1 << 3,
-
-  // Valid conversion flags for numeric values.
-  kConversionFlagsNumeric = kConversionFlagRestricted,
-
-  // Valid conversion flags for string types.
-  kConversionFlagsString = kConversionFlagTreatNullAsEmptyString |
-                           kConversionFlagTreatUndefinedAsEmptyString,
-
-  // Valid conversion flags for callback functions.
-  kConversionFlagsCallbackFunction = kConversionFlagNullable,
-
-  // Valid conversion flags for callback interfaces.
-  kConversionFlagsCallbackInterface = kConversionFlagNullable,
-
-  // Valid conversion flags for objects.
-  kConversionFlagsObject = kConversionFlagNullable,
-};
-
-// Convert std::string in utf8 encoding to WTFString.
-WTF::String ToWTFString(const std::string& utf8_string);
-
-// Convert WTFString to std::string in utf8.
-std::string FromWTFString(const WTF::String& wtf_string);
-
-// Convert std::string in utf8 encoding to a JSValue representing the string.
-JSC::JSValue StringToJSValue(JSC::JSGlobalData* global_data,
-                             const std::string& utf8_string);
-
-// Convert a JSValue to a std::string in utf8 encoding.
-void JSValueToString(JSC::ExecState* exec_state, JSC::JSValue value,
-                     std::string* out_string);
-
-// Convert base::Token in utf8 encoding to a JSValue representing the string.
-JSC::JSValue TokenToJSValue(JSC::JSGlobalData* global_data,
-                            base::Token utf8_string);
-
-// For a given JSObject* get a pointer to the corresponding Cobalt
-// implementation.
-template <class T>
-inline T* JSObjectToWrappable(JSC::ExecState* exec_state,
-                              JSC::JSObject* js_object,
-                              ExceptionState* out_exception) {
-  // Assumes we've already checked that null values are acceptable.
-  if (!js_object) {
-    return NULL;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  Wrappable* wrappable = NULL;
-  const JSC::ClassInfo* class_info = NULL;
-  if (js_object == global_object) {
-    // This is the global object, so get the pointer to the global interface
-    // from the JSCGlobalObject.
-    wrappable = global_object->global_interface().get();
-    class_info = JSCGlobalObject::s_classinfo();
-  } else if (global_object->wrapper_factory()->IsWrapper(js_object)) {
-    // This is a wrapper object, so get the Wrappable from the appropriate
-    // base class.
-    if (js_object->isErrorInstance()) {
-      wrappable = ExceptionBase::GetWrappable(js_object).get();
-    } else {
-      wrappable = InterfaceBase::GetWrappable(js_object).get();
-    }
-    class_info =
-        global_object->wrapper_factory()->GetClassInfo(base::GetTypeId<T>());
-  } else {
-    // This is not a platform object. Return a type error.
-    out_exception->SetSimpleException(kDoesNotImplementInterface);
-    return NULL;
-  }
-
-  // Check that the js_object is the expected class.
-  if (js_object->inherits(class_info)) {
-    return base::polymorphic_downcast<T*>(wrappable);
-  } else {
-    out_exception->SetSimpleException(kDoesNotImplementInterface);
-    return NULL;
-  }
-}
-
-// GetWrappableOrSetException functions will set an exception if the value is
-// not a Wrapper object that corresponds to the Wrappable type T.
-// Additionally, an exception will be set if object is NULL.
-template <class T>
-T* GetWrappableOrSetException(JSC::ExecState* exec_state,
-                              JSC::JSObject* object) {
-  if (!object) {
-    JSC::throwTypeError(exec_state);
-    return NULL;
-  }
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCExceptionState exception_state(global_object);
-  T* impl = JSObjectToWrappable<T>(exec_state, object, &exception_state);
-  if (exception_state.is_exception_set()) {
-    JSC::throwError(exec_state, exception_state.exception_object());
-    return NULL;
-  }
-  return impl;
-}
-
-template <class T>
-T* GetWrappableOrSetException(JSC::ExecState* exec_state, JSC::JSCell* cell) {
-  // getObject() returns NULL if the cell is not an object.
-  JSC::JSObject* object = cell ? cell->getObject() : NULL;
-  return GetWrappableOrSetException<T>(exec_state, object);
-}
-
-template <class T>
-T* GetWrappableOrSetException(JSC::ExecState* exec_state, JSC::JSValue value) {
-  // getObject() returns NULL if the value is not an object.
-  JSC::JSObject* object = value.getObject();
-  return GetWrappableOrSetException<T>(exec_state, object);
-}
-
-// Overloads of ToJSValue convert different Cobalt types to JSValue.
-//
-// bool -> JSValue
-inline JSC::JSValue ToJSValue(JSCGlobalObject*, bool in_boolean) {
-  return JSC::jsBoolean(in_boolean);
-}
-
-// numeric types -> JSValue
-template <class T>
-inline JSC::JSValue ToJSValue(
-    JSCGlobalObject*, T in_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized>::type* =
-        NULL) {
-  JSC::JSValue number_value = JSC::jsNumber(in_number);
-  DCHECK(number_value.isNumber());
-  return number_value;
-}
-
-// std::string -> JSValue
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              const std::string& in_string) {
-  return StringToJSValue(&(global_object->globalData()), in_string);
-}
-
-// base::Token -> JSValue
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              base::Token in_token) {
-  return TokenToJSValue(&(global_object->globalData()), in_token);
-}
-
-// object -> JSValue
-template <class T>
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              const scoped_refptr<T>& in_object) {
-  if (!in_object) {
-    return JSC::jsNull();
-  }
-  JSC::JSObject* wrapper =
-      global_object->wrapper_factory()->GetWrapper(global_object, in_object);
-  DCHECK(wrapper);
-  return JSC::JSValue(wrapper);
-}
-
-// optional<T> -> JSValue
-template <class T>
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              base::optional<T> in_optional) {
-  if (!in_optional) {
-    return JSC::jsNull();
-  }
-  return ToJSValue(global_object, in_optional.value());
-}
-
-// CallbackFunction -> JSValue
-template <class T>
-inline JSC::JSValue ToJSValue(
-    JSCGlobalObject* global_object,
-    const ScriptObject<CallbackFunction<T> >* callback_function) {
-  if (!callback_function) {
-    return JSC::jsNull();
-  }
-
-  // Downcast to JSCCallbackFunctionHolder, which has public members that
-  // we can use to dig in to get the JS object.
-  const JSCCallbackFunctionHolder<CallbackFunction<T> >*
-      jsc_callback_function_holder = base::polymorphic_downcast<
-          const JSCCallbackFunctionHolder<CallbackFunction<T> >*>(
-          callback_function);
-  // Get the base CallbackFunction<T> class from the JSCCallbackFunctionHolder.
-  const CallbackFunction<T>* callback =
-      jsc_callback_function_holder->GetScriptObject();
-  // Shouldn't be NULL. If the callback was NULL then NULL should have been
-  // passed as an argument into this function.
-  DCHECK(callback);
-  // Downcast to the JSCCallbackFunction type, from which we can get the
-  // JSFunction.
-  const JSCCallbackFunction<T>* jsc_callback =
-      base::polymorphic_downcast<const JSCCallbackFunction<T>*>(callback);
-  return JSC::JSValue(jsc_callback->callable());
-}
-
-// CallbackInterface -> JSValue
-template <class T>
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              const ScriptObject<T>* callback_interface) {
-  if (!callback_interface) {
-    return JSC::jsNull();
-  }
-  typedef typename CallbackInterfaceTraits<T>::JSCCallbackInterfaceClass
-      JSCCallbackInterfaceClass;
-  // Downcast to JSCCallbackInterfaceHolder
-  const JSCCallbackInterfaceHolder<T>* jsc_callback_interface_holder =
-      base::polymorphic_downcast<const JSCCallbackInterfaceHolder<T>*>(
-          callback_interface);
-
-  // Shouldn't be NULL. If the callback was NULL then NULL should have been
-  // passed as an argument into this function.
-  // Downcast to the corresponding JSCCallbackInterface type, from which we can
-  // get the implementing object.
-  const JSCCallbackInterfaceClass* jsc_callback_interface =
-      base::polymorphic_downcast<const JSCCallbackInterfaceClass*>(
-          jsc_callback_interface_holder->GetScriptObject());
-  DCHECK(jsc_callback_interface);
-  // Return the user object implementing this interface.
-  return JSC::JSValue(jsc_callback_interface->implementing_object());
-}
-
-// OpaqueHandle -> JSValue
-inline JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                              const OpaqueHandleHolder* opaque_handle_holder) {
-  if (!opaque_handle_holder) {
-    return JSC::jsNull();
-  }
-
-  // Downcast to JSCObjectHandleHolder, which has public members that
-  // we can use to dig in to get the JS object.
-  const JSCObjectHandleHolder* jsc_object_handle_holder =
-      base::polymorphic_downcast<const JSCObjectHandleHolder*>(
-          opaque_handle_holder);
-
-  JSC::JSObject* js_object = jsc_object_handle_holder->js_object();
-  if (js_object) {
-    return JSC::JSValue(js_object);
-  } else {
-    return JSC::jsNull();
-  }
-}
-
-// Overloads of FromJSValue retrieve the Cobalt value from a JSValue.
-//
-// JSValue -> bool
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        bool* out_bool) {
-  DCHECK_EQ(conversion_flags, kNoConversionFlags)
-      << "No conversion flags supported.";
-  *out_bool = jsvalue.toBoolean(exec_state);
-}
-
-// JSValue -> signed integers <= 4 bytes
-template <class T>
-inline void FromJSValue(
-    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
-    ExceptionState* out_exception, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) <= 4),
-                             T>::type* = NULL) {
-  DCHECK_EQ(conversion_flags, kNoConversionFlags)
-      << "No conversion flags supported.";
-  int32_t int32_value = jsvalue.toInt32(exec_state);
-  *out_number = static_cast<T>(int32_value);
-}
-
-// JSValue -> unsigned integers <= 4 bytes
-template <class T>
-inline void FromJSValue(
-    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
-    ExceptionState* out_exception, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 !std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) <= 4),
-                             T>::type* = NULL) {
-  DCHECK_EQ(conversion_flags, kNoConversionFlags)
-      << "No conversion flags supported.";
-  uint32_t uint32_value = jsvalue.toUInt32(exec_state);
-  *out_number = static_cast<T>(uint32_value);
-}
-
-// JSValue -> signed integers > 4 bytes
-template <class T>
-inline void FromJSValue(
-    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
-    ExceptionState* out_exception, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) > 4),
-                             T>::type* = NULL) {
-  NOTIMPLEMENTED();
-}
-
-// JSValue -> unsigned integers > 4 bytes
-template <class T>
-inline void FromJSValue(
-    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
-    ExceptionState* out_exception, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 !std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) > 4),
-                             T>::type* = NULL) {
-  NOTIMPLEMENTED();
-}
-
-// JSValue -> double
-template <class T>
-inline void FromJSValue(
-    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
-    ExceptionState* out_exception, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 !std::numeric_limits<T>::is_integer,
-                             T>::type* = NULL) {
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsNumeric, 0)
-      << "Unexpected conversion flags found.";
-  double double_value = jsvalue.toNumber(exec_state);
-  if (!isfinite(double_value) &&
-      (conversion_flags & kConversionFlagRestricted)) {
-    out_exception->SetSimpleException(kNotFinite);
-    return;
-  }
-  *out_number = double_value;
-}
-
-// JSValue -> std::string
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        std::string* out_string) {
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsString, 0)
-      << "Unexpected conversion flags found: ";
-  if (jsvalue.isNull() &&
-      conversion_flags & kConversionFlagTreatNullAsEmptyString) {
-    *out_string = "";
-  } else if (jsvalue.isUndefined() &&
-             conversion_flags & kConversionFlagTreatUndefinedAsEmptyString) {
-    *out_string = "";
-  } else {
-    JSValueToString(exec_state, jsvalue, out_string);
-  }
-}
-
-// JSValue -> object
-template <class T>
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        scoped_refptr<T>* out_object) {
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
-      << "Unexpected conversion flags found.";
-
-  JSC::JSObject* js_object = NULL;
-  if (jsvalue.isNull()) {
-    if (!(conversion_flags & kConversionFlagNullable)) {
-      out_exception->SetSimpleException(kNotNullableType);
-      return;
-    }
-  } else {
-    // Returns NULL if jsvalue is not an object.
-    js_object = jsvalue.getObject();
-    if (!js_object) {
-      out_exception->SetSimpleException(kNotObjectType);
-      return;
-    }
-  }
-  *out_object = JSObjectToWrappable<T>(exec_state, js_object, out_exception);
-}
-
-// JSValue -> optional<T>
-template <class T>
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        base::optional<T>* out_optional) {
-  if (jsvalue.isNull()) {
-    *out_optional = base::nullopt;
-  } else if (jsvalue.isUndefined()) {
-    *out_optional = base::nullopt;
-  } else {
-    *out_optional = T();
-    FromJSValue(exec_state, jsvalue,
-                conversion_flags & ~kConversionFlagNullable, out_exception,
-                &(out_optional->value()));
-  }
-}
-
-// JSValue -> optional<T>
-template <>
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        base::optional<std::string>* out_optional) {
-  if (jsvalue.isNull()) {
-    *out_optional = base::nullopt;
-  } else if (jsvalue.isUndefined() &&
-             !(conversion_flags & kConversionFlagTreatUndefinedAsEmptyString)) {
-    // If TreatUndefinedAs=EmptyString is set, skip the default conversion
-    // of undefined to null.
-    *out_optional = base::nullopt;
-  } else {
-    *out_optional = std::string();
-    FromJSValue(exec_state, jsvalue,
-                conversion_flags & ~kConversionFlagNullable, out_exception,
-                &(out_optional->value()));
-  }
-}
-
-// JSValue -> CallbackFunction
-template <class T>
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        JSCCallbackFunctionHolder<T>* out_callback) {
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0)
-      << "No conversion flags supported.";
-  if (jsvalue.isNull()) {
-    if (!(conversion_flags & kConversionFlagNullable)) {
-      out_exception->SetSimpleException(kNotNullableType);
-    }
-    // If it is a nullable type, just return.
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  // https://www.w3.org/TR/WebIDL/#es-callback-function
-  // 1. If V is not a Function object, throw a TypeError
-  if (!jsvalue.isFunction()) {
-    out_exception->SetSimpleException(kNotFunctionValue);
-    return;
-  }
-
-  JSC::JSFunction* js_function =
-      JSC::jsCast<JSC::JSFunction*>(jsvalue.asCell());
-  DCHECK(js_function);
-  JSCCallbackFunction<typename T::Signature> callback_function(js_function);
-  *out_callback = JSCCallbackFunctionHolder<T>(
-      callback_function, global_object->script_object_registry());
-}
-
-// JSValue -> CallbackInterface
-template <class T>
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        JSCCallbackInterfaceHolder<T>* out_callback_interface) {
-  typedef typename CallbackInterfaceTraits<T>::JSCCallbackInterfaceClass
-      JSCCallbackInterfaceClass;
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0)
-      << "No conversion flags supported.";
-  if (jsvalue.isNull()) {
-    if (!(conversion_flags & kConversionFlagNullable)) {
-      out_exception->SetSimpleException(kNotNullableType);
-    }
-    // If it is a nullable type, just return.
-    return;
-  }
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-
-  // https://www.w3.org/TR/WebIDL/#es-user-objects
-  // Any user object can be considered to implement a user interface. Actually
-  // checking if the correct properties exist will happen when the operation
-  // on the callback interface is run.
-
-  if (!jsvalue.isFunction() && !jsvalue.isObject()) {
-    out_exception->SetSimpleException(kNotObjectOrFunction);
-    return;
-  }
-
-  JSC::JSObject* js_object = jsvalue.getObject();
-  DCHECK(js_object);
-  JSCCallbackInterfaceClass callback_interface(js_object);
-  *out_callback_interface = JSCCallbackInterfaceHolder<T>(
-      callback_interface, global_object->script_object_registry());
-}
-
-// JSValue -> OpaqueHandle
-inline void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                        int conversion_flags, ExceptionState* out_exception,
-                        JSCObjectHandleHolder* out_handle) {
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
-      << "Unexpected conversion flags found.";
-  JSC::JSObject* js_object = NULL;
-  if (jsvalue.isNull()) {
-    if (!(conversion_flags & kConversionFlagNullable)) {
-      out_exception->SetSimpleException(kNotNullableType);
-    }
-    // Return here whether an exception was set or not.
-    return;
-  } else {
-    // https://www.w3.org/TR/WebIDL/#es-object
-    // 1. If Type(V) is not Object, throw a TypeError
-    js_object = jsvalue.getObject();
-    if (!js_object) {
-      out_exception->SetSimpleException(kNotObjectType);
-      return;
-    }
-  }
-
-  // Null cases should be handled above.
-  DCHECK(js_object);
-
-  JSCGlobalObject* global_object =
-      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-  JSCObjectHandle jsc_object_handle(js_object);
-  *out_handle = JSCObjectHandleHolder(jsc_object_handle,
-                                      global_object->script_object_registry());
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#include "cobalt/script/javascriptcore/jsc_callback_function_impl.h"
-// Union type conversion is generated by a pump script.
-#include "cobalt/script/javascriptcore/union_type_conversion_impl.h"
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_CONVERSION_HELPERS_H_
diff --git a/src/cobalt/script/javascriptcore/javascriptcore.gyp b/src/cobalt/script/javascriptcore/javascriptcore.gyp
deleted file mode 100644
index 73b048f..0000000
--- a/src/cobalt/script/javascriptcore/javascriptcore.gyp
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
-  'targets': [
-    {
-      'target_name': 'engine',
-      'type': 'static_library',
-      'sources': [
-        'conversion_helpers.cc',
-        'conversion_helpers.h',
-        'js_object_cache.cc',
-        'js_object_cache.h',
-        'jsc_call_frame.cc',
-        'jsc_call_frame.h',
-        'jsc_callback_interface.cc',
-        'jsc_debugger.cc',
-        'jsc_debugger.h',
-        'jsc_engine.cc',
-        'jsc_engine.h',
-        'jsc_exception_state.cc',
-        'jsc_exception_state.h',
-        'jsc_gc_markup_visitor.h',
-        'jsc_global_environment.cc',
-        'jsc_global_environment.h',
-        'jsc_global_object.cc',
-        'jsc_global_object.h',
-        'jsc_object_handle.h',
-        'jsc_object_owner.h',
-        'jsc_scope.cc',
-        'jsc_scope.h',
-        'jsc_source_code.cc',
-        'jsc_source_code.h',
-        'jsc_source_provider.cc',
-        'jsc_source_provider.h',
-        'script_object_registry.cc',
-        'script_object_registry.h',
-        'thread_local_hash_table.cc',
-        'thread_local_hash_table.h',
-        'util/binding_helpers.cc',
-        'util/binding_helpers.h',
-        'util/exception_helpers.cc',
-        'util/exception_helpers.h',
-        'wrapper_base.h',
-        'wrapper_factory.cc',
-        'wrapper_factory.h',
-      ],
-      'defines': [
-        '__DISABLE_WTF_LOGGING__',
-      ],
-      'include_dirs': [
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore',
-        '<(DEPTH)/third_party/WebKit/Source/WTF',
-      ],
-      'dependencies': [
-        '<(DEPTH)/cobalt/script/script.gyp:script',
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore',
-      ],
-      'all_dependent_settings': {
-        'defines': [
-          'ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT',
-          'ENGINE_USES_CONSERVATIVE_ROOTING',
-        ],
-      },
-      'msvs_disabled_warnings': [
-        # dll-interface warnings. Not easily fixed for template types.
-        4251,
-      ],
-    },
-    {
-      'target_name': 'jsc_engine_test',
-      'type': '<(gtest_target_type)',
-      'sources': [
-        'numeric_conversion_test.cc',
-      ],
-      'defines': [
-        '__DISABLE_WTF_LOGGING__',
-      ],
-      'include_dirs': [
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore',
-        '<(DEPTH)/third_party/WebKit/Source/WTF',
-      ],
-      'dependencies': [
-        '<(DEPTH)/base/base.gyp:run_all_unittests',
-        '<(DEPTH)/cobalt/base/base.gyp:base',
-        '<(DEPTH)/testing/gmock.gyp:gmock',
-        '<(DEPTH)/testing/gtest.gyp:gtest',
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore',
-        'engine',
-      ]
-    },
-    {
-      # Standalone executable for JS engine
-      'target_name': 'jsc',
-      'type': '<(final_executable_type)',
-      'sources': [
-        'jsc.cc',
-      ],
-      'defines': [
-        '__DISABLE_WTF_LOGGING__',
-      ],
-      'include_dirs': [
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore',
-        '<(DEPTH)/third_party/WebKit/Source/WTF',
-      ],
-      'dependencies': [
-        ':engine',
-        '<(DEPTH)/cobalt/base/base.gyp:base',
-        '<(DEPTH)/cobalt/script/script.gyp:standalone_javascript_runner',
-        '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore',
-      ],
-    },
-  ],
-}
diff --git a/src/cobalt/script/javascriptcore/javascriptcore_variables.gypi b/src/cobalt/script/javascriptcore/javascriptcore_variables.gypi
deleted file mode 100644
index cc0e9cd..0000000
--- a/src/cobalt/script/javascriptcore/javascriptcore_variables.gypi
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
-  'variables': {
-    'conditions': [
-      ['javascript_engine == "javascriptcore"', {
-        'generated_bindings_prefix': 'JSC',
-        'engine_include_dirs': [
-          '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore',
-          '<(DEPTH)/third_party/WebKit/Source/WTF',
-        ],
-        'engine_dependencies': [
-          '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore',
-        ],
-        'engine_defines': [
-          # Avoid WTF LOG macro.
-          '__DISABLE_WTF_LOGGING__',
-        ],
-        'engine_templates_dir': [
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates',
-        ],
-        'engine_template_files': [
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/callback-interface.cc.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/callback-interface.h.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/interface.cc.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/interface.h.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/interface-object.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/macros.cc.template',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/templates/prototype-object.template',
-        ],
-        'engine_bindings_scripts': [
-          '<(DEPTH)/cobalt/bindings/javascriptcore/code_generator.py',
-          '<(DEPTH)/cobalt/bindings/javascriptcore/idl_compiler.py',
-        ],
-        'engine_idl_compiler': '<(DEPTH)/cobalt/bindings/javascriptcore/idl_compiler.py',
-      }],
-    ],
-  },
-}
diff --git a/src/cobalt/script/javascriptcore/js_object_cache.cc b/src/cobalt/script/javascriptcore/js_object_cache.cc
deleted file mode 100644
index 1a99230..0000000
--- a/src/cobalt/script/javascriptcore/js_object_cache.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/js_object_cache.h"
-
-#include <utility>
-
-#include "base/hash_tables.h"
-
-#if !defined(BASE_HASH_USE_HASH_STRUCT)
-namespace BASE_HASH_NAMESPACE {
-template<>
-inline size_t hash_value(const JSC::WriteBarrier<JSC::JSObject>& value) {
-  return hash_value(value.get());
-}
-}  // namespace BASE_HASH_NAMESPACE
-#endif
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-PrototypeBase* JSObjectCache::GetCachedPrototype(
-    const JSC::ClassInfo* class_info) {
-  CachedPrototypeMap::iterator it = cached_prototypes_.find(class_info);
-  if (it != cached_prototypes_.end()) {
-    return it->second.get();
-  }
-  return NULL;
-}
-
-void JSObjectCache::CachePrototype(const JSC::ClassInfo* class_info,
-                                 PrototypeBase* object) {
-  std::pair<CachedPrototypeMap::iterator, bool> pair_ib;
-  pair_ib = cached_prototypes_.insert(std::make_pair(
-      class_info, JSC::WriteBarrier<PrototypeBase>(global_object_->globalData(),
-                                                   global_object_, object)));
-  DCHECK(pair_ib.second)
-      << "Another Prototype was already registered for this ClassInfo";
-}
-
-ConstructorBase* JSObjectCache::GetCachedConstructor(
-    const JSC::ClassInfo* class_info) {
-  CachedConstructorMap::iterator it = cached_constructors_.find(class_info);
-  if (it != cached_constructors_.end()) {
-    return it->second.get();
-  }
-  return NULL;
-}
-
-void JSObjectCache::CacheConstructor(const JSC::ClassInfo* class_info,
-                                   ConstructorBase* object) {
-  std::pair<CachedConstructorMap::iterator, bool> pair_ib;
-  pair_ib = cached_constructors_.insert(std::make_pair(
-      class_info, JSC::WriteBarrier<ConstructorBase>(
-                      global_object_->globalData(), global_object_, object)));
-  DCHECK(pair_ib.second)
-      << "Another Prototype was already registered for this ClassInfo";
-}
-
-void JSObjectCache::CacheJSObject(JSC::JSObject* js_object) {
-  cached_objects_.insert(js_object);
-}
-
-void JSObjectCache::UncacheJSObject(JSC::JSObject* js_object) {
-  CachedObjectMultiset::iterator it = cached_objects_.find(js_object);
-  if (it != cached_objects_.end()) {
-    cached_objects_.erase(it);
-  } else {
-    NOTREACHED() << "Trying to uncache a JSObject that was not cached.";
-  }
-}
-
-void JSObjectCache::VisitChildren(JSC::SlotVisitor* visitor) {
-  for (CachedPrototypeMap::iterator it = cached_prototypes_.begin();
-       it != cached_prototypes_.end(); ++it) {
-    visitor->append(&(it->second));
-  }
-  for (CachedConstructorMap::iterator it = cached_constructors_.begin();
-       it != cached_constructors_.end(); ++it) {
-    visitor->append(&(it->second));
-  }
-  for (CachedObjectMultiset::iterator it = cached_objects_.begin();
-       it != cached_objects_.end(); ++it) {
-    JSC::JSObject* js_object = *it;
-    visitor->appendUnbarrieredPointer(&js_object);
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/js_object_cache.h b/src/cobalt/script/javascriptcore/js_object_cache.h
deleted file mode 100644
index 6e5a271..0000000
--- a/src/cobalt/script/javascriptcore/js_object_cache.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JS_OBJECT_CACHE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JS_OBJECT_CACHE_H_
-
-#include "base/bind.h"
-#include "base/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "cobalt/base/type_id.h"
-#include "cobalt/script/javascriptcore/constructor_base.h"
-#include "cobalt/script/javascriptcore/prototype_base.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class JSCGlobalObject;
-
-//
-class JSObjectCache {
- public:
-  explicit JSObjectCache(JSC::JSGlobalObject* global_object)
-      : global_object_(global_object) {}
-  // Cache an interface's Prototype object by ClassInfo. Cached objects will
-  // not be garbage collected.
-  PrototypeBase* GetCachedPrototype(const JSC::ClassInfo* class_info);
-  void CachePrototype(const JSC::ClassInfo* class_info, PrototypeBase* object);
-
-  // Cache an interface's Interface Object (constructor) by ClassInfo. Cached
-  // objects will not be garbage collected.
-  ConstructorBase* GetCachedConstructor(const JSC::ClassInfo* class_info);
-  void CacheConstructor(const JSC::ClassInfo* class_info,
-                        ConstructorBase* object);
-
-  // Cache a reference to this JS object internally and visit it during garbage
-  // collection. This will prevent it from being garbage collected.
-  // Calling this multiple times for the same object results in multiple
-  // references being stored.
-  void CacheJSObject(JSC::JSObject* js_object);
-
-  // Remove a reference to this JS object from the internal list of objects
-  // that are visited during garbage collection.
-  void UncacheJSObject(JSC::JSObject* js_object);
-
-  // Called during garbage collection phase. Cached objects will be visited and
-  // thus prevented from being garbage collected.
-  void VisitChildren(JSC::SlotVisitor* visitor);
-
- private:
-  typedef base::hash_map<const JSC::ClassInfo*,
-                         JSC::WriteBarrier<PrototypeBase> > CachedPrototypeMap;
-  typedef base::hash_map<const JSC::ClassInfo*,
-                         JSC::WriteBarrier<ConstructorBase> >
-      CachedConstructorMap;
-  typedef base::hash_multiset<JSC::JSObject*> CachedObjectMultiset;
-
-  JSC::JSGlobalObject* global_object_;
-  CachedPrototypeMap cached_prototypes_;
-  CachedConstructorMap cached_constructors_;
-  CachedObjectMultiset cached_objects_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JS_OBJECT_CACHE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc.cc b/src/cobalt/script/javascriptcore/jsc.cc
deleted file mode 100644
index 45ab380..0000000
--- a/src/cobalt/script/javascriptcore/jsc.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <iostream>
-
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/string_util.h"
-#include "cobalt/base/wrap_main.h"
-#include "cobalt/script/javascriptcore/jsc_engine.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/standalone_javascript_runner.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-// Error.h needs to be included before JSCTypedArrayStubs.h
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/JSCTypedArrayStubs.h"  // NOLINT(build/include_alpha)
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Identifier.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace {
-
-JSC::EncodedJSValue JSC_HOST_CALL PrintFunction(JSC::ExecState* exec) {
-  std::vector<std::string> string_args;
-  for (uint32 i = 0; i < exec->argumentCount(); ++i) {
-    string_args.push_back(
-        exec->argument(i).toString(exec)->value(exec).utf8().data());
-  }
-  std::string joined = JoinString(string_args, ' ');
-  std::cout << joined << std::endl;
-  return JSC::JSValue::encode(JSC::jsUndefined());
-}
-
-void AddFunction(JSCGlobalObject* global_object, const char* name,
-                 JSC::NativeFunction function, uint32 arguments) {
-  JSC::Identifier identifier(global_object->globalExec(), name);
-  global_object->putDirect(
-      global_object->globalData(), identifier,
-      JSC::JSFunction::create(global_object->globalExec(), global_object,
-                              arguments, identifier.string(), function));
-}
-
-#if !USE(EXPORT_MACROS)
-void AddConstructableFunction(JSCGlobalObject* global_object, const char* name,
-                              JSC::NativeFunction function, uint32 arguments) {
-  JSC::Identifier identifier(global_object->globalExec(), name);
-  global_object->putDirect(
-      global_object->globalData(), identifier,
-      JSC::JSFunction::create(global_object->globalExec(), global_object,
-                              arguments, identifier.string(), function,
-                              JSC::NoIntrinsic, function));
-}
-#endif
-
-void SetupBindings(JSCGlobalObject* global_object) {
-  JSC::JSLockHolder lock(&global_object->globalData());
-  AddFunction(global_object, "print", &PrintFunction, 1);
-
-  // Getting these exported properly will take a bit of work, and it's likely
-  // not worth it.
-#if !USE(EXPORT_MACROS)
-  AddConstructableFunction(global_object, "Uint8Array",
-                           JSC::constructJSUint8Array, 1);
-  AddConstructableFunction(global_object, "Uint8ClampedArray",
-                           JSC::constructJSUint8ClampedArray, 1);
-  AddConstructableFunction(global_object, "Uint16Array",
-                           JSC::constructJSUint16Array, 1);
-  AddConstructableFunction(global_object, "Uint32Array",
-                           JSC::constructJSUint32Array, 1);
-  AddConstructableFunction(global_object, "Int8Array",
-                           JSC::constructJSInt8Array, 1);
-  AddConstructableFunction(global_object, "Int16Array",
-                           JSC::constructJSInt16Array, 1);
-  AddConstructableFunction(global_object, "Int32Array",
-                           JSC::constructJSInt32Array, 1);
-  AddConstructableFunction(global_object, "Float32Array",
-                           JSC::constructJSFloat32Array, 1);
-  AddConstructableFunction(global_object, "Float64Array",
-                           JSC::constructJSFloat64Array, 1);
-#endif
-}
-
-int JSCMain(int argc, char** argv) {
-  cobalt::script::StandaloneJavascriptRunner standalone_runner;
-  standalone_runner.global_environment()->EnableEval();
-
-  JSCGlobalObject* global_object =
-      static_cast<JSCGlobalEnvironment*>(
-          standalone_runner.global_environment().get())
-          ->global_object();
-  SetupBindings(global_object);
-
-  CommandLine command_line(argc, argv);
-  CommandLine::StringVector args = command_line.GetArgs();
-  if (!args.empty()) {
-    FilePath source_file(args[0]);
-    standalone_runner.ExecuteFile(source_file);
-  } else {
-    standalone_runner.RunInteractive();
-  }
-  return 0;
-}
-
-}  // namespace
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-COBALT_WRAP_SIMPLE_MAIN(cobalt::script::javascriptcore::JSCMain);
diff --git a/src/cobalt/script/javascriptcore/jsc_call_frame.cc b/src/cobalt/script/javascriptcore/jsc_call_frame.cc
deleted file mode 100644
index 864e8d0..0000000
--- a/src/cobalt/script/javascriptcore/jsc_call_frame.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_call_frame.h"
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-#include "cobalt/script/javascriptcore/jsc_scope.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/CString.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-namespace cobalt {
-namespace script {
-
-namespace javascriptcore {
-
-namespace {
-// Conversion from intptr_t to std::string.
-// Used to generate a unique string ID by converting the object pointer.
-std::string IntptrToString(intptr_t input) {
-  COMPILE_ASSERT(sizeof(int64) >= sizeof(intptr_t),
-                 int64_not_big_enough_to_store_intptr_t);
-  int64 input_as_int64 = static_cast<int64>(input);
-  return base::Int64ToString(input_as_int64);
-}
-}  // namespace
-
-JSCCallFrame::JSCCallFrame(const JSC::DebuggerCallFrame& call_frame,
-                           intptr_t script_id, int line_number)
-    : call_frame_(call_frame),
-      script_id_(IntptrToString(script_id)),
-      line_number_(line_number) {
-  Initialize();
-}
-
-JSCCallFrame::JSCCallFrame(const JSC::DebuggerCallFrame& call_frame,
-                           intptr_t script_id, int line_number,
-                           int column_number)
-    : call_frame_(call_frame),
-      script_id_(IntptrToString(script_id)),
-      line_number_(line_number),
-      column_number_(column_number) {
-  Initialize();
-}
-
-JSCCallFrame::~JSCCallFrame() {}
-
-void JSCCallFrame::Initialize() {
-  DCHECK(call_frame_.callFrame());
-  DCHECK_GT(script_id_.length(), 0);
-  global_object_ = JSC::jsCast<JSCGlobalObject*>(
-      call_frame_.callFrame()->dynamicGlobalObject());
-  DCHECK(global_object_);
-
-  JSC::JSValue this_value = call_frame_.callFrame()->thisValue();
-  JSC::JSObject* this_object = this_value.getObject();
-  if (this_object) {
-    this_holder_.reset(
-        new JSCObjectHandleHolder(JSCObjectHandle(this_object),
-                                  global_object_->script_object_registry()));
-  } else {
-    DLOG(WARNING) << "JavaScript 'this' value is not an object.";
-  }
-}
-
-std::string JSCCallFrame::GetCallFrameId() {
-  return IntptrToString(reinterpret_cast<intptr_t>(call_frame_.callFrame()));
-}
-
-scoped_ptr<CallFrame> JSCCallFrame::GetCaller() {
-  JSC::CallFrame* call_frame = call_frame_.callFrame();
-  DCHECK(call_frame);
-  DCHECK(!call_frame->hasHostCallFrameFlag());
-
-  // Get the caller.
-  intptr_t source_id;
-  int line_number;
-  String url;
-  JSC::JSValue function;
-  call_frame->interpreter()->retrieveLastCaller(call_frame, line_number,
-                                                source_id, url, function);
-  call_frame = call_frame->callerFrame();
-
-  if (!call_frame || call_frame->hasHostCallFrameFlag()) {
-    // No valid JavaScript caller, return NULL;
-    return scoped_ptr<CallFrame>();
-  }
-
-  return scoped_ptr<CallFrame>(new JSCCallFrame(
-      JSC::DebuggerCallFrame(call_frame), source_id, line_number));
-}
-
-std::string JSCCallFrame::GetFunctionName() {
-  return call_frame_.functionName().utf8().data();
-}
-
-int JSCCallFrame::GetLineNumber() {
-  // Line number is absolute - will need to be adjusted for the start line in
-  // inline scripts.
-  DCHECK_GT(line_number_, 0);
-  return line_number_;
-}
-
-base::optional<int> JSCCallFrame::GetColumnNumber() { return column_number_; }
-
-std::string JSCCallFrame::GetScriptId() { return script_id_; }
-
-scoped_ptr<Scope> JSCCallFrame::GetScopeChain() {
-  DCHECK(call_frame_.callFrame());
-  DCHECK(call_frame_.callFrame()->scope());
-  return scoped_ptr<Scope>(new JSCScope(call_frame_.callFrame()->scope()));
-}
-
-const OpaqueHandleHolder* JSCCallFrame::GetThis() { return this_holder_.get(); }
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_call_frame.h b/src/cobalt/script/javascriptcore/jsc_call_frame.h
deleted file mode 100644
index dbaebf5..0000000
--- a/src/cobalt/script/javascriptcore/jsc_call_frame.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALL_FRAME_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALL_FRAME_H_
-
-#include <string>
-
-#include "base/optional.h"
-#include "cobalt/script/call_frame.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/scope.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/debugger/DebuggerCallFrame.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// JavaScriptCore-specific implementation of a JavaScript call frame.
-class JSCCallFrame : public CallFrame {
- public:
-  JSCCallFrame(const JSC::DebuggerCallFrame& call_frame, intptr_t script_id,
-               int line_number);
-  JSCCallFrame(const JSC::DebuggerCallFrame& call_frame, intptr_t script_id,
-               int line_number, int column_number);
-  ~JSCCallFrame() OVERRIDE;
-
-  std::string GetCallFrameId() OVERRIDE;
-  scoped_ptr<CallFrame> GetCaller() OVERRIDE;
-  std::string GetFunctionName() OVERRIDE;
-  int GetLineNumber() OVERRIDE;
-  base::optional<int> GetColumnNumber() OVERRIDE;
-  std::string GetScriptId() OVERRIDE;
-  scoped_ptr<Scope> GetScopeChain() OVERRIDE;
-  const OpaqueHandleHolder* GetThis() OVERRIDE;
-
- private:
-  // Called by both constructors to perform common initialization.
-  void Initialize();
-
-  JSC::DebuggerCallFrame call_frame_;
-  std::string script_id_;
-  int line_number_;
-  base::optional<int> column_number_;
-  JSCGlobalObject* global_object_;
-  scoped_ptr<JSCObjectHandleHolder> this_holder_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALL_FRAME_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_function.h b/src/cobalt/script/javascriptcore/jsc_callback_function.h
deleted file mode 100644
index 818acec..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_function.h
+++ /dev/null
@@ -1,503 +0,0 @@
-// This file was GENERATED by command:
-//     pump.py jsc_callback_function.h.pump
-// DO NOT EDIT BY HAND!!!
-
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
-
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "cobalt/script/callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "cobalt/script/logging_exception_state.h"
-#include "cobalt/script/script_object.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-
-// The JSCCallbackFunction type is used to represent IDL callback functions.
-// Create a new JSCCallbackFunction by specifying the base CallbackFunction
-// as a template parameter to the constructor.
-//
-// Constructor parameters:
-//     callable: A handle that keeps keeps alive the JSC::JSFunction that
-//         will be called when the callback is fired.
-//     callback: A base::Callback that will be executed when the Run(...)
-//         function is executed. It will take as parameters a JSC::JSFunction
-//         followed by any arguments that are defined on the callback type.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace internal {
-// Helper template functions for Callback functions' return values before being
-// returned to Cobalt.
-// Converts the return value from JavaScript into the correct Cobalt type, or
-// sets the exception bit if conversion fails.
-template <typename R>
-inline CallbackResult<R> ConvertReturnValue(JSC::ExecState* exec_state,
-                                            JSC::JSValue jsvalue);
-}
-// First, we forward declare the Callback class template. This informs the
-// compiler that the template only has 1 type parameter which is the base
-// CallbackFunction template class with parameters.
-//
-// See base/callback.h.pump for further discussion on this pattern.
-template <typename Sig>
-class JSCCallbackFunction;
-
-template <typename R>
-class JSCCallbackFunction<R(void)>
-    : public CallbackFunction<R(void)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run()
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1>
-class JSCCallbackFunction<R(A1)>
-    : public CallbackFunction<R(A1)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2>
-class JSCCallbackFunction<R(A1, A2)>
-    : public CallbackFunction<R(A1, A2)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-class JSCCallbackFunction<R(A1, A2, A3)>
-    : public CallbackFunction<R(A1, A2, A3)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
-      typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-    args.append(ToJSValue(global_object, a3));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class JSCCallbackFunction<R(A1, A2, A3, A4)>
-    : public CallbackFunction<R(A1, A2, A3, A4)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
-      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
-      typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-    args.append(ToJSValue(global_object, a3));
-    args.append(ToJSValue(global_object, a4));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-class JSCCallbackFunction<R(A1, A2, A3, A4, A5)>
-    : public CallbackFunction<R(A1, A2, A3, A4, A5)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
-      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
-      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
-      typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-    args.append(ToJSValue(global_object, a3));
-    args.append(ToJSValue(global_object, a4));
-    args.append(ToJSValue(global_object, a5));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-class JSCCallbackFunction<R(A1, A2, A3, A4, A5, A6)>
-    : public CallbackFunction<R(A1, A2, A3, A4, A5, A6)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
-      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
-      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
-      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
-      typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-    args.append(ToJSValue(global_object, a3));
-    args.append(ToJSValue(global_object, a4));
-    args.append(ToJSValue(global_object, a5));
-    args.append(ToJSValue(global_object, a6));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-class JSCCallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)>
-    : public CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run(
-      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
-      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
-      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
-      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
-      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
-      typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
-      typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    args.append(ToJSValue(global_object, a1));
-    args.append(ToJSValue(global_object, a2));
-    args.append(ToJSValue(global_object, a3));
-    args.append(ToJSValue(global_object, a4));
-    args.append(ToJSValue(global_object, a5));
-    args.append(ToJSValue(global_object, a6));
-    args.append(ToJSValue(global_object, a7));
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value,
-            args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_function.h.pump b/src/cobalt/script/javascriptcore/jsc_callback_function.h.pump
deleted file mode 100644
index abba9da..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_function.h.pump
+++ /dev/null
@@ -1,137 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ This should be no larger than MAX_ARITY in base/bind.h.pump.
-$var MAX_ARITY = 7
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
-
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "cobalt/script/callback_function.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-#include "cobalt/script/logging_exception_state.h"
-#include "cobalt/script/script_object.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-
-// The JSCCallbackFunction type is used to represent IDL callback functions.
-// Create a new JSCCallbackFunction by specifying the base CallbackFunction
-// as a template parameter to the constructor.
-//
-// Constructor parameters:
-//     callable: A handle that keeps keeps alive the JSC::JSFunction that
-//         will be called when the callback is fired.
-//     callback: A base::Callback that will be executed when the Run(...)
-//         function is executed. It will take as parameters a JSC::JSFunction
-//         followed by any arguments that are defined on the callback type.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace internal {
-// Helper template functions for Callback functions' return values before being
-// returned to Cobalt.
-// Converts the return value from JavaScript into the correct Cobalt type, or
-// sets the exception bit if conversion fails.
-template <typename R>
-inline CallbackResult<R> ConvertReturnValue(JSC::ExecState* exec_state,
-                                            JSC::JSValue jsvalue);
-}
-// First, we forward declare the Callback class template. This informs the
-// compiler that the template only has 1 type parameter which is the base
-// CallbackFunction template class with parameters.
-//
-// See base/callback.h.pump for further discussion on this pattern.
-template <typename Sig>
-class JSCCallbackFunction;
-
-$range ARITY 0..MAX_ARITY
-$for ARITY [[
-$range ARG 1..ARITY
-
-
-$if ARITY == 0 [[
-template <typename R>
-class JSCCallbackFunction<R(void)>
-    : public CallbackFunction<R(void)> {
-]] $else [[
-template <typename R, $for ARG , [[typename A$(ARG)]]>
-class JSCCallbackFunction<R($for ARG , [[A$(ARG)]])>
-    : public CallbackFunction<R($for ARG , [[A$(ARG)]])> {
-]]
-
- public:
-  explicit JSCCallbackFunction(JSC::JSFunction* callable)
-      : callable_(callable) { DCHECK(callable_); }
-
-  CallbackResult<R> Run($for ARG , [[
-
-      typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
-      const OVERRIDE {
-    TRACE_EVENT0("cobalt::script::javascriptcore", "JSCCallbackFunction::Run");
-    DCHECK(callable_);
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(callable_->globalObject());
-    JSC::JSLockHolder lock(global_object->globalData());
-
-    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
-    // Callback 'this' is set to null, unless overridden by other specifications
-    JSC::JSValue this_value = JSC::jsNull();
-    JSC::MarkedArgumentBuffer args;
-    $for ARG [[args.append(ToJSValue(global_object, a$(ARG)));
-    ]]
-
-    JSC::CallData call_data;
-    JSC::CallType call_type =
-        JSC::JSFunction::getCallData(callable_, call_data);
-    JSC::ExecState* exec_state = global_object->globalExec();
-    JSC::JSGlobalData& global_data = global_object->globalData();
-    JSC::JSValue retval =
-        JSC::call(exec_state, callable_, call_type, call_data, this_value, args);
-    CallbackResult<R> callback_result;
-    if (exec_state->hadException()) {
-      DLOG(WARNING) << "Exception in callback: "
-                    << util::GetExceptionString(exec_state);
-
-      exec_state->clearException();
-      callback_result.exception = true;
-    } else {
-      callback_result = internal::ConvertReturnValue<R>(exec_state, retval);
-    }
-    return callback_result;
-  }
-
-  JSC::JSFunction* callable() const { return callable_; }
-
- private:
-  JSC::JSFunction* callable_;
-};
-
-]]
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_function_holder.h b/src/cobalt/script/javascriptcore/jsc_callback_function_holder.h
deleted file mode 100644
index eeb641f..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_function_holder.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_HOLDER_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_HOLDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/script_object.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Implementation of the ScriptObject interface for JSCCallbackFunctions.
-template <typename CallbackFunction>
-class JSCCallbackFunctionHolder : public ScriptObject<CallbackFunction> {
- public:
-  typedef JSCCallbackFunction<typename CallbackFunction::Signature>
-      JSCCallbackFunctionClass;
-  typedef ScriptObject<CallbackFunction> BaseClass;
-
-  JSCCallbackFunctionHolder() : script_object_registry_(NULL) {}
-
-  explicit JSCCallbackFunctionHolder(
-      const JSCCallbackFunctionClass& cb,
-      ScriptObjectRegistry* script_object_registry)
-      : jsc_callable_(cb), script_object_registry_(script_object_registry) {
-    JSC::validateCell(jsc_callable_.value().callable());
-  }
-
-  void RegisterOwner(Wrappable* owner) OVERRIDE {
-    JSC::validateCell(jsc_callable_.value().callable());
-    script_object_registry_->RegisterObjectOwner(
-        owner, jsc_callable_.value().callable());
-  }
-
-  void DeregisterOwner(Wrappable* owner) OVERRIDE {
-    // callable_ may be in the process of being garbage collected.
-    script_object_registry_->DeregisterObjectOwner(
-        owner, jsc_callable_.value().callable());
-  }
-
-  const CallbackFunction* GetScriptObject() const OVERRIDE {
-    return jsc_callable_ ? &jsc_callable_.value() : NULL;
-  }
-
-  scoped_ptr<BaseClass> MakeCopy() const OVERRIDE {
-    DCHECK(jsc_callable_);
-    return make_scoped_ptr<BaseClass>(new JSCCallbackFunctionHolder(
-        jsc_callable_.value(), script_object_registry_));
-  }
-
-  bool EqualTo(const BaseClass& other) const OVERRIDE {
-    const JSCCallbackFunctionHolder* jsc_other =
-        base::polymorphic_downcast<const JSCCallbackFunctionHolder*>(&other);
-    if (!jsc_callable_) {
-      return !jsc_other->jsc_callable_;
-    }
-    DCHECK(jsc_callable_);
-    DCHECK(jsc_other->jsc_callable_);
-    return jsc_callable_->callable() == jsc_other->jsc_callable_->callable();
-  }
-
- private:
-  base::optional<JSCCallbackFunctionClass> jsc_callable_;
-  ScriptObjectRegistry* script_object_registry_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_HOLDER_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_function_impl.h b/src/cobalt/script/javascriptcore/jsc_callback_function_impl.h
deleted file mode 100644
index c95a14a..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_function_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_IMPL_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_IMPL_H_
-
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace internal {
-// Helper template functions for Callback functions' return values before being
-// returned to Cobalt.
-// Converts the return value from JavaScript into the correct Cobalt type, or
-// sets the exception bit if conversion fails.
-template <typename R>
-inline CallbackResult<R> ConvertReturnValue(JSC::ExecState* exec_state,
-                                            JSC::JSValue jsvalue) {
-  // TODO: Pass conversion flags to callback function return value.
-  const int kConversionFlags = 0;
-  CallbackResult<R> callback_result;
-  LoggingExceptionState exception_state;
-  FromJSValue(exec_state, jsvalue, kConversionFlags, &exception_state,
-              &callback_result.result);
-  callback_result.exception = exception_state.is_exception_set();
-  return callback_result;
-}
-template <>
-inline CallbackResult<void> ConvertReturnValue(JSC::ExecState* exec_state,
-                                               JSC::JSValue jsvalue) {
-  // No conversion necessary.
-  return CallbackResult<void>();
-}
-}  // namespace internal
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_FUNCTION_IMPL_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_interface.cc b/src/cobalt/script/javascriptcore/jsc_callback_interface.cc
deleted file mode 100644
index 967d24e..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_interface.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_callback_interface.h"
-
-#include "base/logging.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSScope.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Helper class to get the actual callable object from a JSObject.
-JSC::CallType GetCallableForCallbackInterface(
-    JSC::ExecState* exec_state, JSC::JSObject* implementing_object,
-    const char* property_name, JSC::JSValue* out_callable,
-    JSC::CallData* out_call_data) {
-  DCHECK(implementing_object);
-  DCHECK(out_callable);
-  DCHECK(out_call_data);
-
-  JSC::JSValue callable = implementing_object;
-  JSC::CallType call_type = JSC::getCallData(callable, *out_call_data);
-  if (call_type == JSC::CallTypeNone) {
-    JSC::Identifier identifier(exec_state, property_name);
-    callable = implementing_object->get(exec_state, identifier);
-    call_type = JSC::getCallData(callable, *out_call_data);
-  }
-  if (call_type != JSC::CallTypeNone) {
-    *out_callable = callable;
-  }
-  return call_type;
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_interface.h b/src/cobalt/script/javascriptcore/jsc_callback_interface.h
deleted file mode 100644
index 2c62925..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_interface.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_H_
-
-#include "cobalt/script/callback_interface_traits.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/CallData.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Helper class to get the actual callable object from a JSObject.
-JSC::CallType GetCallableForCallbackInterface(
-    JSC::ExecState* exec_state, JSC::JSObject* implementing_object,
-    const char* property_name, JSC::JSValue* out_callable,
-    JSC::CallData* out_call_data);
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_callback_interface_holder.h b/src/cobalt/script/javascriptcore/jsc_callback_interface_holder.h
deleted file mode 100644
index 686e442..0000000
--- a/src/cobalt/script/javascriptcore/jsc_callback_interface_holder.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_HOLDER_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_HOLDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface.h"
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/script_object.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-template <typename CallbackInterface>
-class JSCCallbackInterfaceHolder : public ScriptObject<CallbackInterface> {
- public:
-  typedef typename CallbackInterfaceTraits<
-      CallbackInterface>::JSCCallbackInterfaceClass JSCCallbackInterface;
-  typedef ScriptObject<CallbackInterface> BaseClass;
-
-  JSCCallbackInterfaceHolder() : script_object_registry_(NULL) {}
-  JSCCallbackInterfaceHolder(const JSCCallbackInterface& callback_interface,
-                             ScriptObjectRegistry* script_object_registry)
-      : callback_interface_(callback_interface),
-        script_object_registry_(script_object_registry) {}
-
-  void RegisterOwner(Wrappable* owner) OVERRIDE {
-    DCHECK(callback_interface_);
-    JSC::JSObject* implementing_object =
-        callback_interface_->implementing_object();
-    JSC::validateCell(implementing_object);
-    script_object_registry_->RegisterObjectOwner(owner, implementing_object);
-  }
-
-  void DeregisterOwner(Wrappable* owner) OVERRIDE {
-    // The implementing object may be NULL if it's been garbage collected. Still
-    // call Deregister in this case.
-    DCHECK(callback_interface_);
-    JSC::JSObject* implementing_object =
-        callback_interface_->implementing_object();
-    script_object_registry_->DeregisterObjectOwner(owner, implementing_object);
-  }
-
-  const CallbackInterface* GetScriptObject() const OVERRIDE {
-    return callback_interface_ ? &callback_interface_.value() : NULL;
-  }
-
-  scoped_ptr<ScriptObject<CallbackInterface> > MakeCopy() const OVERRIDE {
-    DCHECK(callback_interface_);
-    return make_scoped_ptr<BaseClass>(new JSCCallbackInterfaceHolder(
-        callback_interface_.value(), script_object_registry_));
-  }
-
-  bool EqualTo(const BaseClass& other) const OVERRIDE {
-    const JSCCallbackInterfaceHolder* jsc_other =
-        base::polymorphic_downcast<const JSCCallbackInterfaceHolder*>(&other);
-    if (!callback_interface_) {
-      return !jsc_other->callback_interface_;
-    }
-    DCHECK(callback_interface_);
-    DCHECK(jsc_other->callback_interface_);
-    return callback_interface_->implementing_object() ==
-           jsc_other->callback_interface_->implementing_object();
-  }
-
- private:
-  base::optional<JSCCallbackInterface> callback_interface_;
-  ScriptObjectRegistry* script_object_registry_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_CALLBACK_INTERFACE_HOLDER_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_debugger.cc b/src/cobalt/script/javascriptcore/jsc_debugger.cc
deleted file mode 100644
index 78c3a63..0000000
--- a/src/cobalt/script/javascriptcore/jsc_debugger.cc
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_debugger.h"
-
-#include <cstdlib>
-#include <string>
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascriptcore/jsc_call_frame.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_source_provider.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/debugger/DebuggerCallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/heap/MarkedBlock.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/parser/SourceProvider.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Executable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSCell.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSScope.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-
-namespace cobalt {
-namespace script {
-
-// Static factory method declared in public interface.
-scoped_ptr<ScriptDebugger> ScriptDebugger::CreateDebugger(
-    GlobalEnvironment* global_environment, Delegate* delegate) {
-  return scoped_ptr<ScriptDebugger>(
-      new javascriptcore::JSCDebugger(global_environment, delegate));
-}
-
-namespace javascriptcore {
-
-namespace {
-// Type used to store a set of source providers.
-typedef WTF::HashSet<JSC::SourceProvider*> SourceProviderSet;
-
-// Functor to iterate over the JS cells and gather source providers.
-class GathererFunctor : public JSC::MarkedBlock::VoidFunctor {
- public:
-  GathererFunctor(JSC::JSGlobalObject* global_object,
-                  SourceProviderSet* source_providers)
-      : global_object_(global_object), source_providers_(source_providers) {}
-
-  void operator()(JSC::JSCell* cell) {
-    JSC::JSFunction* function = JSC::jsDynamicCast<JSC::JSFunction*>(cell);
-    if (function && !function->isHostFunction() &&
-        function->scope()->globalObject() == global_object_ &&
-        function->executable()->isFunctionExecutable()) {
-      source_providers_->add(
-          JSC::jsCast<JSC::FunctionExecutable*>(function->executable())
-              ->source()
-              .provider());
-    }
-  }
-
- private:
-  SourceProviderSet* source_providers_;
-  JSC::JSGlobalObject* global_object_;
-};
-
-// Uses the GatherorFunctor defined above to gather all the currently parsed
-// source providers defined in |global_object| and populate |source_providers|.
-// This is called once by the |attach| method; the script debugger is
-// automatically notified of subsequently parsed scripts via the |source_parsed|
-// method.
-void GatherSourceProviders(JSC::JSGlobalObject* global_object,
-                           SourceProviderSet* source_providers) {
-  DCHECK(global_object);
-  DCHECK(source_providers);
-  source_providers->clear();
-  GathererFunctor gatherer_functor(global_object, source_providers);
-  JSC::JSGlobalData& global_data = global_object->globalData();
-  global_data.heap.objectSpace().forEachLiveCell(gatherer_functor);
-}
-
-intptr_t StringToIntptr(const std::string& input) {
-  COMPILE_ASSERT(sizeof(int64) >= sizeof(intptr_t),
-                 int64_not_big_enough_to_store_intptr_t);
-  int64 as_int64 = 0;
-  bool did_convert = base::StringToInt64(input, &as_int64);
-  DCHECK(did_convert);
-  return static_cast<intptr_t>(as_int64);
-}
-}  // namespace
-
-JSCDebugger::JSCDebugger(GlobalEnvironment* global_environment,
-                         Delegate* delegate)
-    : global_environment_(global_environment),
-      delegate_(delegate),
-      pause_on_exceptions_(kNone),
-      pause_on_next_statement_(false),
-      pause_on_call_frame_(NULL),
-      current_call_frame_(NULL),
-      current_source_id_(0),
-      current_line_number_(0),
-      current_column_number_(0),
-      is_paused_(false) {}
-
-JSCDebugger::~JSCDebugger() {
-  if (GetGlobalObject()->debugger() == this) {
-    detach(GetGlobalObject());
-  }
-}
-
-void JSCDebugger::Attach() {
-  if (GetGlobalObject()->debugger() == NULL) {
-    attach(GetGlobalObject());
-  } else {
-    DLOG(WARNING) << "Debugger is already attached.";
-  }
-}
-
-void JSCDebugger::Detach() {
-  if (GetGlobalObject()->debugger() == this) {
-    detach(GetGlobalObject());
-  } else {
-    DLOG(WARNING) << "Debugger is not attached.";
-  }
-}
-
-void JSCDebugger::Pause() {
-  pause_on_next_statement_ = true;
-  pause_on_call_frame_ = NULL;
-}
-
-void JSCDebugger::Resume() {
-  pause_on_next_statement_ = false;
-  pause_on_call_frame_ = NULL;
-}
-
-void JSCDebugger::SetBreakpoint(const std::string& script_id, int line_number,
-                                int column_number) {
-  // Convert the string script_id used by devtools into the intptr_t source_id
-  // used internally.
-  intptr_t source_id = StringToIntptr(script_id);
-
-  breakpoints_.push_back(Breakpoint(source_id, line_number, column_number));
-}
-
-script::ScriptDebugger::PauseOnExceptionsState
-JSCDebugger::SetPauseOnExceptions(PauseOnExceptionsState state) {
-  const PauseOnExceptionsState previous_state = pause_on_exceptions_;
-  pause_on_exceptions_ = state;
-  return previous_state;
-}
-
-void JSCDebugger::StepInto() {
-  pause_on_next_statement_ = true;
-  pause_on_call_frame_ = NULL;
-}
-
-void JSCDebugger::StepOut() {
-  pause_on_next_statement_ = false;
-  const JSC::CallFrame* call_frame = current_call_frame_.callFrame();
-  pause_on_call_frame_ = call_frame ? call_frame->callerFrame() : NULL;
-}
-
-void JSCDebugger::StepOver() {
-  pause_on_next_statement_ = false;
-  pause_on_call_frame_ = current_call_frame_.callFrame();
-  DCHECK(pause_on_call_frame_);
-}
-
-JSCGlobalObject* JSCDebugger::GetGlobalObject() const {
-  return base::polymorphic_downcast<JSCGlobalEnvironment*>(global_environment_)
-      ->global_object();
-}
-
-void JSCDebugger::attach(JSC::JSGlobalObject* global_object) {
-  DCHECK(global_object);
-  JSC::Debugger::attach(global_object);
-
-  // Gather the source providers and call |sourceParsed| on each one.
-  // Any scripts parsed after this point will automatically invoke a call
-  // to |sourceParsed|.
-  SourceProviderSet source_providers;
-  GatherSourceProviders(global_object, &source_providers);
-
-  for (SourceProviderSet::iterator iter = source_providers.begin();
-       iter != source_providers.end(); ++iter) {
-    sourceParsed(global_object->globalExec(), *iter, -1, String());
-  }
-}
-
-void JSCDebugger::detach(JSC::JSGlobalObject* global_object) {
-  DCHECK(global_object);
-  JSC::Debugger::detach(global_object);
-  delegate_->OnScriptDebuggerDetach("canceled_by_user");
-}
-
-void JSCDebugger::sourceParsed(JSC::ExecState* exec_state,
-                               JSC::SourceProvider* source_provider,
-                               int error_line,
-                               const WTF::String& error_message) {
-  UNREFERENCED_PARAMETER(exec_state);
-  DCHECK(source_provider);
-
-  if (error_line < 0) {
-    // Script was parsed successfully.
-    delegate_->OnScriptParsed(
-        scoped_ptr<SourceProvider>(new JSCSourceProvider(source_provider)));
-  } else {
-    // Script failed to parse.
-    delegate_->OnScriptFailedToParse(
-        scoped_ptr<SourceProvider>(new JSCSourceProvider(
-            source_provider, error_line, error_message.utf8().data())));
-  }
-}
-
-void JSCDebugger::exception(const JSC::DebuggerCallFrame& call_frame,
-                            intptr_t source_id, int line_number,
-                            int column_number, bool has_handler) {
-  if (pause_on_exceptions_ == kAll ||
-      (pause_on_exceptions_ == kUncaught && !has_handler)) {
-    pause_on_next_statement_ = true;
-    pause_on_call_frame_ = NULL;
-  }
-
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::atStatement(const JSC::DebuggerCallFrame& call_frame,
-                              intptr_t source_id, int line_number,
-                              int column_number) {
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::callEvent(const JSC::DebuggerCallFrame& call_frame,
-                            intptr_t source_id, int line_number,
-                            int column_number) {
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::returnEvent(const JSC::DebuggerCallFrame& call_frame,
-                              intptr_t source_id, int line_number,
-                              int column_number) {
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::willExecuteProgram(const JSC::DebuggerCallFrame& call_frame,
-                                     intptr_t source_id, int line_number,
-                                     int column_number) {
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::didExecuteProgram(const JSC::DebuggerCallFrame& call_frame,
-                                    intptr_t source_id, int line_number,
-                                    int column_number) {
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::didReachBreakpoint(const JSC::DebuggerCallFrame& call_frame,
-                                     intptr_t source_id, int line_number,
-                                     int column_number) {
-  pause_on_next_statement_ = true;
-  pause_on_call_frame_ = NULL;
-  UpdateAndPauseIfNeeded(call_frame, source_id, line_number, column_number);
-}
-
-void JSCDebugger::UpdateAndPauseIfNeeded(
-    const JSC::DebuggerCallFrame& call_frame, intptr_t source_id,
-    int line_number, int column_number) {
-  // Don't do anything if we're currently paused. We want to remember the call
-  // frame and source location at the point we paused, not override them with
-  // any debugging scripts that get evaluated while paused.
-  if (is_paused_) {
-    return;
-  }
-
-  UpdateSourceLocation(source_id, line_number, column_number);
-  UpdateCallFrame(call_frame);
-  PauseIfNeeded(call_frame);
-}
-
-void JSCDebugger::UpdateSourceLocation(intptr_t source_id, int line_number,
-                                       int column_number) {
-  current_source_id_ = source_id;
-  current_line_number_ = line_number;
-  current_column_number_ = column_number;
-}
-
-void JSCDebugger::UpdateCallFrame(const JSC::DebuggerCallFrame& call_frame) {
-  current_call_frame_ = call_frame;
-}
-
-void JSCDebugger::PauseIfNeeded(const JSC::DebuggerCallFrame& call_frame) {
-  // Determine whether we should pause.
-  bool will_pause = pause_on_next_statement_;
-  will_pause |=
-      pause_on_call_frame_ && pause_on_call_frame_ == call_frame.callFrame();
-  will_pause |= IsBreakpointAtCurrentLocation();
-
-  if (!will_pause) {
-    return;
-  }
-
-  // Set the |is_paused_| state for the remainder of this function.
-  ScopedPausedState paused(this);
-
-  // Delegate handles the actual blocking of the thread to implement Pause.
-  delegate_->OnScriptDebuggerPause(scoped_ptr<CallFrame>(
-      new JSCCallFrame(call_frame, current_source_id_, current_line_number_,
-                       current_column_number_)));
-}
-
-bool JSCDebugger::IsBreakpointAtCurrentLocation() const {
-  for (BreakpointVector::const_iterator it = breakpoints_.begin();
-       it != breakpoints_.end(); ++it) {
-    if (it->source_id == current_source_id_ &&
-        it->line_number == current_line_number_ &&
-        (it->column_number == 0 ||
-         it->column_number == current_column_number_)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_debugger.h b/src/cobalt/script/javascriptcore/jsc_debugger.h
deleted file mode 100644
index 7c0b03b..0000000
--- a/src/cobalt/script/javascriptcore/jsc_debugger.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/script_debugger.h"
-#include "cobalt/script/source_provider.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/debugger/Debugger.h"
-#include "third_party/WebKit/Source/JavaScriptCore/debugger/DebuggerCallFrame.h"
-#include "third_party/WebKit/Source/WTF/wtf/HashSet.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-namespace JSC {
-class ExecState;
-class JSGlobalData;
-class JSGlobalObject;
-class JSScope;
-class JSValue;
-class SourceProvider;
-}
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// JavaScriptCore-specific implementation of a JavaScript debugger.
-// Uses multiple inheritance in accordance with the C++ style guide to extend
-// JSC::Debugger and implement ScriptDebugger.
-//
-// Only the ScriptDebugger is publicly exposed.
-// This class is not designed to be thread-safe - it is assumed that all
-// public methods will be run on the same message loop as the JavaScript
-// global object to which this debugger connects.
-class JSCDebugger : protected JSC::Debugger, public ScriptDebugger {
- public:
-  JSCDebugger(GlobalEnvironment* global_environment, Delegate* delegate);
-  ~JSCDebugger() OVERRIDE;
-
-  // Implementation of ScriptDebugger.
-  void Attach() OVERRIDE;
-  void Detach() OVERRIDE;
-  void Pause() OVERRIDE;
-  void Resume() OVERRIDE;
-  void SetBreakpoint(const std::string& script_id, int line_number,
-                     int column_number) OVERRIDE;
-  PauseOnExceptionsState SetPauseOnExceptions(
-      PauseOnExceptionsState state) OVERRIDE;
-  void StepInto() OVERRIDE;
-  void StepOut() OVERRIDE;
-  void StepOver() OVERRIDE;
-
- protected:
-  // Hides a non-virtual JSC::Debugger method with the same name.
-  void attach(JSC::JSGlobalObject* global_object);
-
-  // The following methods are overrides of pure virtual methods in
-  // JSC::Debugger, hence the non-standard names.
-  void detach(JSC::JSGlobalObject* global_object) OVERRIDE;
-
-  void sourceParsed(JSC::ExecState* exec_state,
-                    JSC::SourceProvider* source_provider, int error_line,
-                    const WTF::String& error_message) OVERRIDE;
-
-  void exception(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id,
-                 int line_number, int column_number, bool has_handler) OVERRIDE;
-
-  void atStatement(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id,
-                   int line_number, int column_number) OVERRIDE;
-
-  void callEvent(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id,
-                 int line_number, int column_number) OVERRIDE;
-
-  void returnEvent(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id,
-                   int line_number, int column_number) OVERRIDE;
-
-  void willExecuteProgram(const JSC::DebuggerCallFrame& call_frame,
-                          intptr_t source_id, int line_number,
-                          int column_number) OVERRIDE;
-
-  void didExecuteProgram(const JSC::DebuggerCallFrame& call_frame,
-                         intptr_t source_id, int line_number,
-                         int column_number) OVERRIDE;
-
-  void didReachBreakpoint(const JSC::DebuggerCallFrame& call_frame,
-                          intptr_t source_id, int line_number,
-                          int column_number) OVERRIDE;
-
- private:
-  // Physical breakpoint corresponding to a specific source location.
-  // TODO: Include other attributes, e.g. condition.
-  struct Breakpoint {
-    Breakpoint(intptr_t source_id, int line_number, int column_number)
-        : source_id(source_id),
-          line_number(line_number),
-          column_number(column_number) {}
-    intptr_t source_id;
-    int line_number;
-    int column_number;
-  };
-
-  typedef std::vector<Breakpoint> BreakpointVector;
-
-  // Sets the |is_paused_| member of the debugger while in scope, unsets it
-  // on destruction.
-  class ScopedPausedState {
-   public:
-    explicit ScopedPausedState(JSCDebugger* debugger) : debugger(debugger) {
-      debugger->is_paused_ = true;
-    }
-    ~ScopedPausedState() { debugger->is_paused_ = false; }
-
-   private:
-    JSCDebugger* debugger;
-  };
-
-  // Convenience function to get the global object pointer from the proxy.
-  JSCGlobalObject* GetGlobalObject() const;
-
-  // Update functions called by the overridden methods from JSC:Debugger above
-  // (e.g. |atStatement|) as script is executed.
-  void UpdateAndPauseIfNeeded(const JSC::DebuggerCallFrame& call_frame,
-                              intptr_t source_id, int line_number,
-                              int column_number);
-  void UpdateSourceLocation(intptr_t source_id, int line_number,
-                            int column_number);
-  void UpdateCallFrame(const JSC::DebuggerCallFrame& call_frame);
-  void PauseIfNeeded(const JSC::DebuggerCallFrame& call_frame);
-
-  // Sends event notifications via |delegate_|.
-  void SendPausedEvent(const JSC::DebuggerCallFrame& call_frame);
-  void SendResumedEvent();
-
-  // Whether any of the currently active breakpoints matches the current
-  // source location.
-  bool IsBreakpointAtCurrentLocation() const;
-
-  base::ThreadChecker thread_checker_;
-  GlobalEnvironment* global_environment_;
-
-  // Lifetime managed by the caller of this object's constructor.
-  Delegate* delegate_;
-
-  // Whether script execution pauses on exceptions.
-  PauseOnExceptionsState pause_on_exceptions_;
-
-  // Code execution control flags. Script execution can pause on the next
-  // statement, or on a specific call frame.
-  bool pause_on_next_statement_;
-  JSC::CallFrame* pause_on_call_frame_;
-
-  // Current call frame.
-  JSC::DebuggerCallFrame current_call_frame_;
-
-  // Current source location.
-  intptr_t current_source_id_;
-  int current_line_number_;
-  int current_column_number_;
-
-  // Whether script execution is currently paused.
-  bool is_paused_;
-
-  // Currently active breakpoints.
-  BreakpointVector breakpoints_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_engine.cc b/src/cobalt/script/javascriptcore/jsc_engine.cc
deleted file mode 100644
index 178f66b..0000000
--- a/src/cobalt/script/javascriptcore/jsc_engine.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "cobalt/script/javascriptcore/jsc_engine.h"
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "cobalt/base/c_val.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/InitializeThreading.h"
-#include "third_party/WebKit/Source/WTF/wtf/OSAllocator.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-namespace {
-
-class JSCEngineStats {
- public:
-  JSCEngineStats();
-
-  static JSCEngineStats* GetInstance() {
-    return Singleton<JSCEngineStats,
-                     StaticMemorySingletonTraits<JSCEngineStats> >::get();
-  }
-
-  void JSCEngineCreated() {
-    base::AutoLock auto_lock(lock_);
-    ++js_engine_count_;
-  }
-
-  void JSCEngineDestroyed() {
-    base::AutoLock auto_lock(lock_);
-    --js_engine_count_;
-  }
-
-  size_t UpdateMemoryStatsAndReturnReserved() {
-    base::AutoLock auto_lock(lock_);
-    if (js_engine_count_.value() == 0) {
-      return 0;
-    }
-    return OSAllocator::getCurrentBytesAllocated();
-  }
-
- private:
-  friend struct StaticMemorySingletonTraits<JSCEngineStats>;
-
-  base::Lock lock_;
-  base::CVal<size_t> js_engine_count_;
-};
-
-JSCEngineStats::JSCEngineStats()
-    : js_engine_count_("Count.JS.Engine", 0,
-                       "Total JavaScript engine registered.") {}
-
-}  // namespace
-
-JSCEngine::JSCEngine() {
-  global_data_ = JSC::JSGlobalData::create(JSC::LargeHeap);
-  JSCEngineStats::GetInstance()->JSCEngineCreated();
-}
-
-JSCEngine::~JSCEngine() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSCEngineStats::GetInstance()->JSCEngineDestroyed();
-  script_object_registry_.ClearEntries();
-}
-
-scoped_refptr<GlobalEnvironment> JSCEngine::CreateGlobalEnvironment() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return new JSCGlobalEnvironment(this);
-}
-
-void JSCEngine::CollectGarbage() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(global_data_.get());
-  DCHECK(global_data_->heap.isSafeToCollect());
-  global_data_->heap.collectAllGarbage();
-}
-
-void JSCEngine::ReportExtraMemoryCost(size_t bytes) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(global_data_.get());
-  global_data_->heap.reportExtraMemoryCost(bytes);
-}
-
-size_t JSCEngine::UpdateMemoryStatsAndReturnReserved() {
-  return JSCEngineStats::GetInstance()->UpdateMemoryStatsAndReturnReserved();
-}
-
-}  // namespace javascriptcore
-
-scoped_ptr<JavaScriptEngine> JavaScriptEngine::CreateEngine() {
-  // Documentation in InitializeThreading.h states this function should be
-  // called from the main thread. However, calling it here from the thread each
-  // engine is created on appears to show no difference in practice.
-  JSC::initializeThreading();
-
-  // There must be at most one JSGlobalData instance created per thread.
-  scoped_ptr<javascriptcore::JSCEngine> engine(new javascriptcore::JSCEngine());
-
-  // Global data should be of Default type - one per thread.
-  DCHECK(!engine->global_data()->usingAPI());
-
-  return engine.PassAs<JavaScriptEngine>();
-}
-
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_engine.h b/src/cobalt/script/javascriptcore/jsc_engine.h
deleted file mode 100644
index 7ee06e0..0000000
--- a/src/cobalt/script/javascriptcore/jsc_engine.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_ENGINE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_ENGINE_H_
-
-#include "base/threading/thread_checker.h"
-#include "cobalt/script/javascript_engine.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class JSCEngine : public JavaScriptEngine {
- public:
-  JSCEngine();
-  ~JSCEngine() OVERRIDE;
-
-  scoped_refptr<GlobalEnvironment> CreateGlobalEnvironment() OVERRIDE;
-  void CollectGarbage() OVERRIDE;
-  void ReportExtraMemoryCost(size_t bytes) OVERRIDE;
-  size_t UpdateMemoryStatsAndReturnReserved() OVERRIDE;
-
-  JSC::JSGlobalData* global_data() { return global_data_.get(); }
-  ScriptObjectRegistry* script_object_registry() {
-    return &script_object_registry_;
-  }
-
- private:
-  base::ThreadChecker thread_checker_;
-  ScriptObjectRegistry script_object_registry_;
-  RefPtr<JSC::JSGlobalData> global_data_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_ENGINE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_exception_state.cc b/src/cobalt/script/javascriptcore/jsc_exception_state.cc
deleted file mode 100644
index b1c63d2..0000000
--- a/src/cobalt/script/javascriptcore/jsc_exception_state.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-
-#include <string>
-
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Error.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorInstance.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-void JSCExceptionState::SetException(
-    const scoped_refptr<ScriptException>& exception) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(&global_object_->globalData());
-  exception_ =
-      global_object_->wrapper_factory()->GetWrapper(global_object_, exception);
-  DCHECK(exception_->isErrorInstance());
-}
-
-void JSCExceptionState::SetSimpleException(MessageType message_type, ...) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(&global_object_->globalData());
-
-  va_list arguments;
-  va_start(arguments, message_type);
-  WTF::String error_string = ToWTFString(
-      base::StringPrintV(GetExceptionMessageFormat(message_type), arguments));
-  va_end(arguments);
-
-  switch (GetSimpleExceptionType(message_type)) {
-    case kError:
-      exception_ = JSC::createError(global_object_, error_string);
-      break;
-    case kTypeError:
-      exception_ = JSC::createTypeError(global_object_, error_string);
-      break;
-    case kRangeError:
-      exception_ = JSC::createRangeError(global_object_, error_string);
-      break;
-    case kReferenceError:
-      exception_ = JSC::createReferenceError(global_object_, error_string);
-      break;
-    case kSyntaxError:
-      exception_ = JSC::createSyntaxError(global_object_, error_string);
-      break;
-    case kURIError:
-      exception_ = JSC::createURIError(global_object_, error_string);
-      break;
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_exception_state.h b/src/cobalt/script/javascriptcore/jsc_exception_state.h
deleted file mode 100644
index 1dfd273..0000000
--- a/src/cobalt/script/javascriptcore/jsc_exception_state.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_EXCEPTION_STATE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_EXCEPTION_STATE_H_
-
-#include "base/threading/thread_checker.h"
-#include "cobalt/script/exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class JSCExceptionState : public ExceptionState {
- public:
-  explicit JSCExceptionState(JSCGlobalObject* global_object)
-      : global_object_(global_object), exception_(NULL) {}
-  // ExceptionState interface
-  void SetException(const scoped_refptr<ScriptException>& exception) OVERRIDE;
-  void SetSimpleException(MessageType message_type, ...) OVERRIDE;
-
-  bool is_exception_set() const { return (exception_ != NULL); }
-  JSC::JSObject* exception_object() { return exception_; }
-
- private:
-  JSCGlobalObject* global_object_;
-  JSC::JSObject* exception_;
-  base::ThreadChecker thread_checker_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_EXCEPTION_STATE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_global_environment.cc b/src/cobalt/script/javascriptcore/jsc_global_environment.cc
deleted file mode 100644
index 98e6d01..0000000
--- a/src/cobalt/script/javascriptcore/jsc_global_environment.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/debug/trace_event.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascriptcore/jsc_engine.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/javascriptcore/jsc_source_code.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/heap/StrongInlines.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Completion.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-void JSCGlobalEnvironment::PreventGarbageCollection(
-    const scoped_refptr<Wrappable>& wrappable) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(global_object_);
-
-  JSC::JSLockHolder lock(global_object_->globalData());
-
-  JSC::JSObject* wrapper = global_object_->wrapper_factory()->GetWrapper(
-      global_object_.get(), wrappable);
-  global_object_->object_cache()->CacheJSObject(wrapper);
-}
-
-JSCGlobalEnvironment::~JSCGlobalEnvironment() {
-  if (global_object_.get()) {
-    global_object_->setReportEvalCallback(NULL);
-  }
-}
-
-void JSCGlobalEnvironment::CreateGlobalObject() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(engine_->global_data());
-
-  JSCGlobalObject* global_object = JSCGlobalObject::Create(
-      engine_->global_data(), engine_->script_object_registry());
-  SetGlobalObject(global_object);
-}
-
-void JSCGlobalEnvironment::AllowGarbageCollection(
-    const scoped_refptr<Wrappable>& wrappable) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(global_object_);
-
-  JSC::JSLockHolder lock(global_object_->globalData());
-
-  JSC::JSObject* wrapper = global_object_->wrapper_factory()->GetWrapper(
-      global_object_.get(), wrappable);
-  global_object_->object_cache()->UncacheJSObject(wrapper);
-}
-
-void JSCGlobalEnvironment::DisableEval(const std::string& message) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(global_object_);
-  global_object_->setEvalEnabled(false, message.c_str());
-}
-
-void JSCGlobalEnvironment::EnableEval() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(global_object_);
-  global_object_->setEvalEnabled(true);
-}
-
-void JSCGlobalEnvironment::DisableJit() {}
-
-void JSCGlobalEnvironment::Bind(const std::string& identifier,
-                                const scoped_refptr<Wrappable>& impl) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  javascriptcore::JSCGlobalObject* jsc_global_object =
-      base::polymorphic_downcast<javascriptcore::JSCGlobalEnvironment*>(this)
-          ->global_object();
-
-  JSC::JSLockHolder lock(&jsc_global_object->globalData());
-
-  JSC::JSObject* wrapper =
-      jsc_global_object->wrapper_factory()->GetWrapper(jsc_global_object, impl);
-
-  JSC::Identifier jsc_identifier =
-      JSC::Identifier(jsc_global_object->globalExec(), identifier.c_str());
-
-  // Make sure the property we are binding doesn't already exist.
-  DCHECK(!jsc_global_object->hasOwnProperty(jsc_global_object->globalExec(),
-                                            jsc_identifier));
-
-  // Add the property to the global object.
-  jsc_global_object->putDirect(jsc_global_object->globalData(), jsc_identifier,
-                               wrapper);
-}
-
-bool JSCGlobalEnvironment::EvaluateScript(
-    const scoped_refptr<SourceCode>& source_code, std::string* out_result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(global_object_->globalData());
-
-  JSC::JSValue result;
-  bool success = EvaluateScriptInternal(source_code, &result);
-  if (out_result) {
-    if (!success) {
-      *out_result =
-          util::GetExceptionString(global_object_->globalExec(), result);
-    } else {
-      WTF::String return_string =
-          result.toWTFString(global_object_->globalExec());
-      *out_result = return_string.utf8().data();
-    }
-  }
-
-  return success;
-}
-
-bool JSCGlobalEnvironment::EvaluateScript(
-    const scoped_refptr<SourceCode>& source_code,
-    const scoped_refptr<Wrappable>& owning_object,
-    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  JSC::JSLockHolder lock(global_object_->globalData());
-
-  JSC::JSValue result;
-  if (!EvaluateScriptInternal(source_code, &result)) {
-    std::string exception =
-        util::GetExceptionString(global_object_->globalExec(), result);
-    DLOG(ERROR) << exception;
-    return false;
-  }
-  JSCObjectHandle jsc_object_handle(JSC::asObject(result));
-  JSCObjectHandleHolder jsc_object_holder(
-      JSCObjectHandle(JSC::asObject(result)),
-      global_object_->script_object_registry());
-  out_opaque_handle->emplace(owning_object.get(), jsc_object_holder);
-  return true;
-}
-
-std::vector<StackFrame> JSCGlobalEnvironment::GetStackTrace(int max_frames) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return util::GetStackTrace(global_object_->globalExec(), max_frames);
-}
-
-void JSCGlobalEnvironment::reportEval() {
-  if (!report_eval_cb_.is_null()) {
-    report_eval_cb_.Run();
-  }
-}
-
-void JSCGlobalEnvironment::SetGlobalObject(JSCGlobalObject* jsc_global_object) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(reinterpret_cast<uintptr_t>(global_object_.get()), NULL);
-  global_object_ =
-      JSC::Strong<JSCGlobalObject>(*engine_->global_data(), jsc_global_object);
-  global_object_->setReportEvalCallback(this);
-  // Disable eval() unless it's explicitly enabled (by CSP, for example).
-  DisableEval("eval() is disabled by default.");
-}
-
-bool JSCGlobalEnvironment::EvaluateScriptInternal(
-    const scoped_refptr<SourceCode>& source_code, JSC::JSValue* out_result) {
-  TRACE_EVENT0("cobalt::script::javascriptcore",
-               "JSCGlobalEnvironment::EvaluateScriptInternal");
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(global_object_);
-
-  JSC::ExecState* exec = global_object_->globalExec();
-  // Downcast to the JSC implementation of the SourceCode interface.
-  JSCSourceCode* jsc_source_code =
-      base::polymorphic_downcast<JSCSourceCode*>(source_code.get());
-
-  // Evaluate the source code and gather the return value and exception if
-  // one occurred.
-  JSC::JSValue exception;
-  JSC::JSValue return_value = JSC::evaluate(exec, jsc_source_code->source(),
-                                            JSC::JSValue(),  // thisValue
-                                            &exception);
-  if (exception) {
-    *out_result = exception;
-    exec->clearException();
-    return false;
-  } else {
-    *out_result = return_value;
-    return true;
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_global_environment.h b/src/cobalt/script/javascriptcore/jsc_global_environment.h
deleted file mode 100644
index dcb530d..0000000
--- a/src/cobalt/script/javascriptcore/jsc_global_environment.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_ENVIRONMENT_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_ENVIRONMENT_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/script/global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_engine.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class ScriptObjectRegistry;
-
-// GlobalEnvironment is a ref-counted object that is managed by the browser, and
-// JavaScriptCore's JSGlobalObject is a garbage-collected object.
-// It should only be accessed from the thread that created it.
-class JSCGlobalEnvironment : public GlobalEnvironment,
-                             public JSC::ReportEvalCallback {
- public:
-  explicit JSCGlobalEnvironment(JSCEngine* engine) : engine_(engine) {}
-  ~JSCGlobalEnvironment() OVERRIDE;
-
-  void CreateGlobalObject() OVERRIDE;
-
-  // out_result holds the string value of the last statement executed, or
-  // an exception message in the case of an exception.
-  bool EvaluateScript(const scoped_refptr<SourceCode>& source_code,
-                      std::string* out_result) OVERRIDE;
-
-  bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
-                      const scoped_refptr<Wrappable>& owning_object,
-                      base::optional<OpaqueHandleHolder::Reference>*
-                          out_opaque_handle) OVERRIDE;
-
-  std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE;
-
-  // Create the wrapper object if it has not been created, and add it to
-  // the JSObjectCache.
-  void PreventGarbageCollection(
-      const scoped_refptr<Wrappable>& wrappable) OVERRIDE;
-
-  // Remove a reference to the wrapper object from the JSObjectCache.
-  void AllowGarbageCollection(
-      const scoped_refptr<Wrappable>& wrappable) OVERRIDE;
-
-  void DisableEval(const std::string& message) OVERRIDE;
-
-  void EnableEval() OVERRIDE;
-
-  void DisableJit() OVERRIDE;
-
-  void SetReportEvalCallback(const base::Closure& report_eval) OVERRIDE {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    report_eval_cb_ = report_eval;
-  }
-
-  // Dynamically bind an object to the global object.
-  void Bind(const std::string& identifier,
-            const scoped_refptr<Wrappable>& impl) OVERRIDE;
-
-  JSCGlobalObject* global_object() { return global_object_.get(); }
-
-  JSCEngine* engine() { return engine_; }
-
- private:
-  // JSC::ReportEvalCallback
-  void reportEval() OVERRIDE;
-
-  void SetGlobalObject(JSCGlobalObject* jsc_global_object);
-
-  bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
-                              JSC::JSValue* out_result);
-
-  base::ThreadChecker thread_checker_;
-  // Strong references prevent the object from getting garbage collected. It
-  // is used as a root for object graph traversal.
-  JSC::Strong<JSCGlobalObject> global_object_;
-  JSCEngine* engine_;
-  base::Closure report_eval_cb_;
-  friend class GlobalEnvironment;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_ENVIRONMENT_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_global_object.cc b/src/cobalt/script/javascriptcore/jsc_global_object.cc
deleted file mode 100644
index 9122348..0000000
--- a/src/cobalt/script/javascriptcore/jsc_global_object.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-
-#include "base/logging.h"
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-const JSC::ClassInfo JSCGlobalObject::s_info = {
-    "JSCGlobalObject", JSC::JSGlobalObject::s_classinfo(), 0, 0,
-    CREATE_METHOD_TABLE(JSCGlobalObject)};
-
-JSCGlobalObject* JSCGlobalObject::Create(
-    JSC::JSGlobalData* global_data,
-    ScriptObjectRegistry* script_object_registry) {
-  JSC::Structure* structure = JSC::Structure::create(
-      *global_data,
-      NULL,           // JSC::JSGlobalObject*
-      JSC::jsNull(),  // prototype
-      JSC::TypeInfo(JSC::GlobalObjectType, JSC::JSGlobalObject::StructureFlags),
-      &s_info);
-  JSCGlobalObject* global_object =
-      new (NotNull, JSC::allocateCell<JSCGlobalObject>(global_data->heap))
-          JSCGlobalObject(global_data, structure, script_object_registry, NULL,
-                          scoped_ptr<WrapperFactory>(), NULL);
-  global_object->finishCreation(*global_data);
-  global_data->heap.addFinalizer(global_object, destroy);
-  return global_object;
-}
-
-JSCGlobalObject::JSCGlobalObject(JSC::JSGlobalData* global_data,
-                                 JSC::Structure* structure,
-                                 ScriptObjectRegistry* script_object_registry,
-                                 const scoped_refptr<Wrappable>& wrappable,
-                                 scoped_ptr<WrapperFactory> wrapper_factory,
-                                 EnvironmentSettings* environment_settings)
-    : JSC::JSGlobalObject(*global_data, structure),
-      global_interface_(wrappable),
-      wrapper_factory_(wrapper_factory.Pass()),
-      object_cache_(new JSObjectCache(this)),
-      script_object_registry_(script_object_registry),
-      environment_settings_(environment_settings) {}
-
-std::vector<script::StackFrame> JSCGlobalObject::GetStackTrace(int max_frames) {
-  return util::GetStackTrace(globalExec(), max_frames);
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_global_object.h b/src/cobalt/script/javascriptcore/jsc_global_object.h
deleted file mode 100644
index 89f0dc6..0000000
--- a/src/cobalt/script/javascriptcore/jsc_global_object.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_OBJECT_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_OBJECT_H_
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "cobalt/script/environment_settings.h"
-#include "cobalt/script/javascriptcore/js_object_cache.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-#include "cobalt/script/stack_frame.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// JSCGlobalObject is JavaScriptCore's Global Object in Cobalt. It inherits from
-// JSC::GlobalObject so we can use this wherever a JSC::GlobalObject would be
-// used, allowing us to downcast to JSCGlobalObject.
-// JSCGlobalObject is a garbage-collected object.
-class JSCGlobalObject : public JSC::JSGlobalObject {
- public:
-  // Create a new garbage-collected JSCGlobalObject instance.
-  static JSCGlobalObject* Create(JSC::JSGlobalData* global_data,
-                                 ScriptObjectRegistry* script_object_registry);
-
-  scoped_refptr<Wrappable> global_interface() { return global_interface_; }
-
-  const WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); }
-
-  JSObjectCache* object_cache() { return object_cache_.get(); }
-
-  ScriptObjectRegistry* script_object_registry() {
-    return script_object_registry_;
-  }
-
-  // Getters for CallWith= arguments
-  EnvironmentSettings* GetEnvironmentSettings() {
-    return environment_settings_;
-  }
-  std::vector<StackFrame> GetStackTrace(int max_frames = 0);
-
-  // JavaScriptCore stuff
-  DECLARE_CLASSINFO();
-
-  // Classes that inherit from JSC::GlobalObject set this flag, and set a
-  // finalizer method on creation.
-  static const bool needsDestruction = false;
-
-  // Statically override this to ensure that we visit objects that are cached
-  // or otherwise should not be garbage collected.
-  static void visitChildren(JSC::JSCell* cell,
-                            JSC::SlotVisitor& visitor) {  // NOLINT
-    JSC::JSGlobalObject::visitChildren(cell, visitor);
-    // Cast the JSC::JSCell* to a JSCGlobalObject, and call the non-static
-    // visit_children function.
-    ASSERT_GC_OBJECT_INHERITS(cell, &s_info);
-    JSCGlobalObject* this_object = JSC::jsCast<JSCGlobalObject*>(cell);
-    this_object->object_cache_->VisitChildren(&visitor);
-    this_object->script_object_registry_->VisitOwnedObjects(
-        this_object->global_interface_.get(), &visitor);
-  }
-
-  // static override. This will be called when this object is garbage collected.
-  static void destroy(JSC::JSCell* cell) {
-    // This is necessary when a garbage-collected object has a non-trivial
-    // destructor.
-    static_cast<JSCGlobalObject*>(cell)->~JSCGlobalObject();
-  }
-
- protected:
-  JSCGlobalObject(JSC::JSGlobalData* global_data, JSC::Structure* structure,
-                  ScriptObjectRegistry* script_object_registry,
-                  const scoped_refptr<Wrappable>& global_interface,
-                  scoped_ptr<WrapperFactory> wrapper_factory,
-                  EnvironmentSettings* environment_settings);
-
- private:
-  scoped_refptr<Wrappable> global_interface_;
-  scoped_ptr<WrapperFactory> wrapper_factory_;
-  scoped_ptr<JSObjectCache> object_cache_;
-  ScriptObjectRegistry* script_object_registry_;
-  EnvironmentSettings* environment_settings_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_GLOBAL_OBJECT_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_object_handle.h b/src/cobalt/script/javascriptcore/jsc_object_handle.h
deleted file mode 100644
index 3b79a93..0000000
--- a/src/cobalt/script/javascriptcore/jsc_object_handle.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_H_
-
-#include "cobalt/script/opaque_handle.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// A wrapper around a JSC::JSObject that can be passed into Cobalt as an
-// opaque script object.
-class JSCObjectHandle : public OpaqueHandle {
- public:
-  explicit JSCObjectHandle(JSC::JSObject* wrapper) : handle_(wrapper) {}
-  JSC::JSObject* handle() const { return handle_; }
-
- private:
-  JSC::JSObject* handle_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_object_handle_holder.h b/src/cobalt/script/javascriptcore/jsc_object_handle_holder.h
deleted file mode 100644
index 6c1c172..0000000
--- a/src/cobalt/script/javascriptcore/jsc_object_handle_holder.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_HOLDER_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_HOLDER_H_
-
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle.h"
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Implementation of OpaqueHandleHolder class which is used to pass opaque
-// script handles into Cobalt.
-class JSCObjectHandleHolder : public OpaqueHandleHolder {
- public:
-  JSCObjectHandleHolder() : script_object_registry_(NULL) {}
-
-  explicit JSCObjectHandleHolder(const JSCObjectHandle& handle,
-                                 ScriptObjectRegistry* script_object_registry)
-      : object_handle_(handle),
-        script_object_registry_(script_object_registry) {}
-
-  void RegisterOwner(Wrappable* owner) OVERRIDE {
-    JSC::JSObject* object = js_object();
-    JSC::validateCell(object);
-    script_object_registry_->RegisterObjectOwner(owner, object);
-  }
-
-  void DeregisterOwner(Wrappable* owner) OVERRIDE {
-    JSC::JSObject* object = js_object();
-    // object may be in the process of being garbage collected, so do not
-    // dereference it.
-    script_object_registry_->DeregisterObjectOwner(owner, object);
-  }
-
-  const OpaqueHandle* GetScriptObject() const OVERRIDE {
-    return object_handle_ ? &object_handle_.value() : NULL;
-  }
-
-  scoped_ptr<OpaqueHandleHolder> MakeCopy() const OVERRIDE {
-    DCHECK(object_handle_);
-    return make_scoped_ptr<OpaqueHandleHolder>(new JSCObjectHandleHolder(
-        object_handle_.value(), script_object_registry_));
-  }
-
-  bool EqualTo(const OpaqueHandleHolder& other) const OVERRIDE {
-    const JSCObjectHandleHolder* jsc_other =
-        base::polymorphic_downcast<const JSCObjectHandleHolder*>(&other);
-    if (!object_handle_) {
-      return !jsc_other->object_handle_;
-    }
-    DCHECK(object_handle_);
-    DCHECK(jsc_other->object_handle_);
-    return object_handle_->handle() == jsc_other->object_handle_->handle();
-  }
-
-  JSC::JSObject* js_object() const {
-    DCHECK(object_handle_);
-    return object_handle_->handle();
-  }
-
- private:
-  base::optional<JSCObjectHandle> object_handle_;
-  ScriptObjectRegistry* script_object_registry_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_OBJECT_HANDLE_HOLDER_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_property_enumerator.h b/src/cobalt/script/javascriptcore/jsc_property_enumerator.h
deleted file mode 100644
index 709cf08..0000000
--- a/src/cobalt/script/javascriptcore/jsc_property_enumerator.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_PROPERTY_ENUMERATOR_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_PROPERTY_ENUMERATOR_H_
-
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/property_enumerator.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// Implements the PropertyEnumerator interface. Enumerated properties will
-// be added to the JSC::PropertyNameArray that is passed in at construction.
-class JSCPropertyEnumerator : public PropertyEnumerator {
- public:
-  JSCPropertyEnumerator(JSC::ExecState* exec_state,
-                        JSC::PropertyNameArray* property_names)
-      : exec_state_(exec_state), property_names_(property_names) {}
-  void AddProperty(const std::string& property_name) OVERRIDE {
-    WTF::String wtf_string = ToWTFString(property_name);
-    JSC::Identifier identifier(exec_state_, wtf_string.impl());
-    property_names_->add(identifier);
-  }
-
- private:
-  JSC::ExecState* exec_state_;
-  JSC::PropertyNameArray* property_names_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_PROPERTY_ENUMERATOR_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_scope.cc b/src/cobalt/script/javascriptcore/jsc_scope.cc
deleted file mode 100644
index c503aa6..0000000
--- a/src/cobalt/script/javascriptcore/jsc_scope.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_scope.h"
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSScope.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-
-namespace cobalt {
-namespace script {
-
-namespace javascriptcore {
-
-JSCScope::JSCScope(JSC::JSScope* scope) : scope_(scope), global_object_(NULL) {
-  DCHECK(scope_);
-  global_object_ = JSC::jsCast<JSCGlobalObject*>(scope->globalObject());
-  DCHECK(global_object_);
-
-  scope_holder_.reset(new JSCObjectHandleHolder(
-      JSCObjectHandle(scope_), global_object_->script_object_registry()));
-  DCHECK(scope_holder_);
-}
-
-JSCScope::~JSCScope() {}
-
-const OpaqueHandleHolder* JSCScope::GetObject() { return scope_holder_.get(); }
-
-Scope::Type JSCScope::GetType() {
-  DCHECK(scope_);
-  int type = scope_->structure()->typeInfo().type();
-  std::string type_string;
-  switch (type) {
-    case JSC::GlobalObjectType:
-      return kGlobal;
-    case JSC::ActivationObjectType:
-      return kLocal;
-    default: {
-      DLOG(WARNING) << "Unexpected scope type: " << type;
-      return kLocal;
-    }
-  }
-}
-
-scoped_ptr<Scope> JSCScope::GetNext() {
-  DCHECK(scope_);
-  if (scope_->next()) {
-    return scoped_ptr<Scope>(new JSCScope(scope_->next()));
-  } else {
-    return scoped_ptr<Scope>();
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_scope.h b/src/cobalt/script/javascriptcore/jsc_scope.h
deleted file mode 100644
index 1e11e96..0000000
--- a/src/cobalt/script/javascriptcore/jsc_scope.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SCOPE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SCOPE_H_
-
-#include <string>
-
-#include "base/optional.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/scope.h"
-
-namespace JSC {
-class JSScope;
-}
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// JavaScriptCore-specific implementation of a JavaScript call frame.
-class JSCScope : public Scope {
- public:
-  explicit JSCScope(JSC::JSScope* scope);
-  ~JSCScope() OVERRIDE;
-
-  const OpaqueHandleHolder* GetObject() OVERRIDE;
-  Type GetType() OVERRIDE;
-  scoped_ptr<Scope> GetNext() OVERRIDE;
-
- private:
-  JSC::JSScope* scope_;
-  JSCGlobalObject* global_object_;
-  scoped_ptr<JSCObjectHandleHolder> scope_holder_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SCOPE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_source_code.cc b/src/cobalt/script/javascriptcore/jsc_source_code.cc
deleted file mode 100644
index 7ff4be5..0000000
--- a/src/cobalt/script/javascriptcore/jsc_source_code.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_source_code.h"
-
-#include <string>
-
-#include "base/string_util.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/source_code.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/parser/SourceCode.h"
-#include "third_party/WebKit/Source/JavaScriptCore/parser/SourceProvider.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-namespace {
-
-// Similar to JSC::StringSourceProvider, but takes in a UTF-8 string and
-// converts to a UTF-16 WTF string.
-class UTF8StringSourceProvider : public JSC::SourceProvider {
- public:
-  static WTF::PassRefPtr<UTF8StringSourceProvider> Create(
-      const std::string& source_utf8, const std::string& source_url,
-      int line_number, int column_number) {
-    return WTF::adoptRef(new UTF8StringSourceProvider(
-        source_utf8, source_url, line_number, column_number));
-  }
-  const WTF::String& source() const OVERRIDE { return source_; }
-
- private:
-  explicit UTF8StringSourceProvider(const std::string& source_utf8,
-                                    const std::string& source_url,
-                                    int line_number, int column_number)
-      : SourceProvider(
-            ToWTFString(source_url),
-            WTF::TextPosition(
-                WTF::OrdinalNumber::fromOneBasedInt(line_number),
-                WTF::OrdinalNumber::fromOneBasedInt(column_number))) {
-    source_ = ToWTFString(source_utf8);
-  }
-  WTF::String source_;
-};
-
-}  // namespace
-
-JSCSourceCode::JSCSourceCode(const std::string& source_utf8,
-                             const base::SourceLocation& source_location) {
-  RefPtr<UTF8StringSourceProvider> source_provider =
-      UTF8StringSourceProvider::Create(source_utf8, source_location.file_path,
-                                       source_location.line_number,
-                                       source_location.column_number);
-  source_ = JSC::SourceCode(source_provider, source_location.line_number);
-}
-
-}  // namespace javascriptcore
-
-// static method declared in public interface
-scoped_refptr<SourceCode> SourceCode::CreateSourceCode(
-    const std::string& source_utf8,
-    const base::SourceLocation& source_location) {
-  return new javascriptcore::JSCSourceCode(source_utf8, source_location);
-}
-
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_source_code.h b/src/cobalt/script/javascriptcore/jsc_source_code.h
deleted file mode 100644
index 2e7e76d..0000000
--- a/src/cobalt/script/javascriptcore/jsc_source_code.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_CODE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_CODE_H_
-
-#include <string>
-
-#include "cobalt/script/source_code.h"
-
-#include "config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/parser/SourceCode.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class JSCSourceCode : public SourceCode {
- public:
-  explicit JSCSourceCode(const std::string& source_utf8,
-                         const base::SourceLocation& source_location);
-  JSC::SourceCode& source() { return source_; }
-
- private:
-  JSC::SourceCode source_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_CODE_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_source_provider.cc b/src/cobalt/script/javascriptcore/jsc_source_provider.cc
deleted file mode 100644
index 836b044..0000000
--- a/src/cobalt/script/javascriptcore/jsc_source_provider.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/jsc_source_provider.h"
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/parser/SourceProvider.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/CString.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-namespace cobalt {
-namespace script {
-
-namespace javascriptcore {
-
-namespace {
-// Conversion from intptr_t to std::string.
-// Used to convert the ID used by JSC::SourceProvider (which is cast from the
-// object pointer) to a string.
-std::string IntptrToString(intptr_t input) {
-  COMPILE_ASSERT(sizeof(int64) >= sizeof(intptr_t),
-                 int64_not_big_enough_to_store_intptr_t);
-  int64 input_as_int64 = static_cast<int64>(input);
-  return base::Int64ToString(input_as_int64);
-}
-}  // namespace
-
-JSCSourceProvider::JSCSourceProvider(JSC::SourceProvider* source_provider)
-    : source_provider_(source_provider) {
-  DCHECK(source_provider_);
-}
-
-JSCSourceProvider::JSCSourceProvider(JSC::SourceProvider* source_provider,
-                                     int error_line,
-                                     const std::string& error_message)
-    : source_provider_(source_provider),
-      error_line_(error_line),
-      error_message_(error_message) {
-  DCHECK(source_provider_);
-  DCHECK_GE(error_line, 0);
-}
-
-JSCSourceProvider::~JSCSourceProvider() {}
-
-base::optional<int> JSCSourceProvider::GetEndColumn() {
-  // TODO: Work out how to get this from a JSC::SourceProvider.
-  // Should be provided for inline scripts.
-  return base::nullopt;
-}
-
-base::optional<int> JSCSourceProvider::GetEndLine() {
-  // TODO: Work out how to get this from a JSC::SourceProvider.
-  // Should be provided for inline scripts.
-  return base::nullopt;
-}
-
-base::optional<int> JSCSourceProvider::GetErrorLine() { return error_line_; }
-
-base::optional<std::string> JSCSourceProvider::GetErrorMessage() {
-  return error_message_;
-}
-
-std::string JSCSourceProvider::GetScriptId() {
-  return IntptrToString(source_provider_->asID());
-}
-
-std::string JSCSourceProvider::GetScriptSource() {
-  return source_provider_->source().utf8().data();
-}
-
-base::optional<std::string> JSCSourceProvider::GetSourceMapUrl() {
-  // TODO: Determine if we need to support this, and if so, how.
-  return base::nullopt;
-}
-
-base::optional<int> JSCSourceProvider::GetStartColumn() {
-  return source_provider_->startPosition().m_column.oneBasedInt();
-}
-
-base::optional<int> JSCSourceProvider::GetStartLine() {
-  return source_provider_->startPosition().m_line.oneBasedInt();
-}
-
-std::string JSCSourceProvider::GetUrl() {
-  return source_provider_->url().utf8().data();
-}
-
-base::optional<bool> JSCSourceProvider::IsContentScript() {
-  return base::nullopt;
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_source_provider.h b/src/cobalt/script/javascriptcore/jsc_source_provider.h
deleted file mode 100644
index 92bb359..0000000
--- a/src/cobalt/script/javascriptcore/jsc_source_provider.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_PROVIDER_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_PROVIDER_H_
-
-#include <base/optional.h>
-#include <cobalt/script/source_provider.h>
-
-#include <string>
-
-namespace JSC {
-class SourceProvider;
-}
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// JavaScriptCore-specific implementation of a JavaScript source provider.
-class JSCSourceProvider : public SourceProvider {
- public:
-  explicit JSCSourceProvider(JSC::SourceProvider* source_provider);
-  JSCSourceProvider(JSC::SourceProvider* source_provider, int error_line,
-                    const std::string& error_message);
-  ~JSCSourceProvider() OVERRIDE;
-
-  base::optional<int> GetEndColumn() OVERRIDE;
-  base::optional<int> GetEndLine() OVERRIDE;
-  base::optional<int> GetErrorLine() OVERRIDE;
-  base::optional<std::string> GetErrorMessage() OVERRIDE;
-  std::string GetScriptId() OVERRIDE;
-  std::string GetScriptSource() OVERRIDE;
-  base::optional<std::string> GetSourceMapUrl() OVERRIDE;
-  base::optional<int> GetStartColumn() OVERRIDE;
-  base::optional<int> GetStartLine() OVERRIDE;
-  std::string GetUrl() OVERRIDE;
-  base::optional<bool> IsContentScript() OVERRIDE;
-
- private:
-  JSC::SourceProvider* source_provider_;
-  base::optional<int> error_line_;
-  base::optional<std::string> error_message_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_SOURCE_PROVIDER_H_
diff --git a/src/cobalt/script/javascriptcore/jsc_wrapper_handle.h b/src/cobalt/script/javascriptcore/jsc_wrapper_handle.h
deleted file mode 100644
index 53d98b0..0000000
--- a/src/cobalt/script/javascriptcore/jsc_wrapper_handle.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_WRAPPER_HANDLE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_WRAPPER_HANDLE_H_
-
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// A wrapper around a JSC::Weak handle to a garbage-collected JSC::JSObject
-// object. It's expected that this is a WrapperBase<T> object.
-class JSCWrapperHandle : public Wrappable::WeakWrapperHandle {
- public:
-  explicit JSCWrapperHandle(JSC::PassWeak<JSC::JSObject> wrapper) {
-    handle_ = wrapper;
-  }
-  static JSC::JSObject* GetJSObject(
-      const Wrappable::WeakWrapperHandle* handle) {
-    if (handle) {
-      return base::polymorphic_downcast<const JSCWrapperHandle*>(handle)
-          ->handle_.get();
-    }
-    return NULL;
-  }
-
- private:
-  JSC::Weak<JSC::JSObject> handle_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_WRAPPER_HANDLE_H_
diff --git a/src/cobalt/script/javascriptcore/numeric_conversion_test.cc b/src/cobalt/script/javascriptcore/numeric_conversion_test.cc
deleted file mode 100644
index ed07bb4..0000000
--- a/src/cobalt/script/javascriptcore/numeric_conversion_test.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <limits>
-
-#include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/script/javascript_engine.h"
-#include "cobalt/script/javascriptcore/conversion_helpers.h"
-#include "cobalt/script/javascriptcore/jsc_global_environment.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/testing/mock_exception_state.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSFunction.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSString.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-using testing::_;
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-namespace {
-
-template <int kNumber>
-JSC::EncodedJSValue JSC_HOST_CALL returnNumberFunction(JSC::ExecState* exec) {
-  return JSC::JSValue::encode(JSC::jsNumber(kNumber));
-}
-
-template <typename T>
-class NumericConversionTest : public ::testing::Test {
- public:
-  NumericConversionTest()
-      : engine_(JavaScriptEngine::CreateEngine()),
-        global_environment_(engine_->CreateGlobalEnvironment()),
-        jsc_global_object_(NULL),
-        exec_state_(NULL) {
-    global_environment_->CreateGlobalObject();
-    jsc_global_object_ = base::polymorphic_downcast<JSCGlobalEnvironment*>(
-                             global_environment_.get())
-                             ->global_object();
-    exec_state_ = jsc_global_object_->globalExec();
-  }
-
-  void AddFunction(JSC::JSObject* object, const char* name,
-                   JSC::NativeFunction function) {
-    int num_arguments = 0;
-    JSC::Identifier identifier(jsc_global_object_->globalExec(), name);
-    object->putDirect(jsc_global_object_->globalData(), identifier,
-                      JSC::JSFunction::create(jsc_global_object_->globalExec(),
-                                              jsc_global_object_, num_arguments,
-                                              identifier.string(), function));
-  }
-
-  const scoped_ptr<JavaScriptEngine> engine_;
-  const scoped_refptr<GlobalEnvironment> global_environment_;
-  JSCGlobalObject* jsc_global_object_;
-  JSC::ExecState* exec_state_;
-  testing::MockExceptionState exception_state_;
-};
-
-template <typename T>
-class IntegerConversionTest : public NumericConversionTest<T> {};
-
-template <typename T>
-class FloatingPointConversionTest : public NumericConversionTest<T> {};
-
-typedef ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
-                         double> NumericTypes;
-typedef ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t>
-    IntegerTypes;
-typedef ::testing::Types<double> FloatingPointTypes;
-TYPED_TEST_CASE(NumericConversionTest, NumericTypes);
-TYPED_TEST_CASE(IntegerConversionTest, IntegerTypes);
-TYPED_TEST_CASE(FloatingPointConversionTest, FloatingPointTypes);
-
-template <class T>
-T JSValueToNumber(JSC::ExecState* exec_state, JSC::JSValue js_value,
-                  int conversion_flags, ExceptionState* exception_state) {
-  T value;
-  FromJSValue(exec_state, js_value, conversion_flags, exception_state, &value);
-  return value;
-}
-
-}  // namespace
-
-// Conversion between a JavaScript value and an IDL integer type is described
-// here:
-//     https://www.w3.org/TR/WebIDL/#es-byte
-//     https://www.w3.org/TR/WebIDL/#es-octet
-//     https://www.w3.org/TR/WebIDL/#es-short
-//     https://www.w3.org/TR/WebIDL/#es-unsigned-short
-//     https://www.w3.org/TR/WebIDL/#es-long
-//     https://www.w3.org/TR/WebIDL/#es-unsigned-long
-//     https://www.w3.org/TR/WebIDL/#es-double
-// The first step in each of these algorithms is the ToNumber operation:
-//     http://es5.github.io/#x9.3
-// ToNumber describes how various non-numeric types should convert to a
-// number.
-
-// ToNumber: http://es5.github.io/#x9.3
-TYPED_TEST(NumericConversionTest, BooleanConversion) {
-  EXPECT_EQ(1, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsBoolean(true), kNoConversionFlags,
-                   &this->exception_state_));
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsBoolean(false), kNoConversionFlags,
-                   &this->exception_state_));
-}
-
-// ToNumber applied to the String Type: http://es5.github.io/#x9.3.1
-TYPED_TEST(NumericConversionTest, StringConversion) {
-  JSC::ExecState* exec = this->jsc_global_object_->globalExec();
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsString(this->exec_state_, ""),
-                   kNoConversionFlags, &this->exception_state_));
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsString(this->exec_state_, "    "),
-                   kNoConversionFlags, &this->exception_state_));
-
-  // Integer types convert NaN to 0, and float types throw a TypeError.
-  if (std::numeric_limits<TypeParam>::is_integer) {
-    EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                     this->exec_state_,
-                     JSC::jsString(this->exec_state_, "not_a_number"),
-                     kNoConversionFlags, &this->exception_state_));
-  }
-
-  EXPECT_EQ(32, JSValueToNumber<TypeParam>(
-                    this->exec_state_, JSC::jsString(this->exec_state_, "32"),
-                    kNoConversionFlags, &this->exception_state_));
-  EXPECT_EQ(32, JSValueToNumber<TypeParam>(
-                    this->exec_state_, JSC::jsString(this->exec_state_, "0x20"),
-                    kNoConversionFlags, &this->exception_state_));
-
-  if (!std::numeric_limits<TypeParam>::is_integer) {
-    EXPECT_EQ(54.34,
-              JSValueToNumber<TypeParam>(
-                  this->exec_state_, JSC::jsString(this->exec_state_, "54.34"),
-                  kNoConversionFlags, &this->exception_state_));
-  }
-}
-
-// Described in the integer type conversion algorithms:
-//     Set x to sign(x)*floor(abs(x))
-// Also in ToUint16, ToInt32, and ToUInt64:
-//     3. Let posInt be sign(number) * floor(abs(number))
-TYPED_TEST(IntegerConversionTest, FloatingPointToIntegerConversion) {
-  EXPECT_EQ(5, JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNumber(5.1),
-                                          kNoConversionFlags,
-                                          &this->exception_state_));
-  if (std::numeric_limits<TypeParam>::is_signed) {
-    EXPECT_EQ(-5, JSValueToNumber<TypeParam>(
-                      this->exec_state_, JSC::jsNumber(-5.1),
-                      kNoConversionFlags, &this->exception_state_));
-  }
-}
-
-// http://es5.github.io/#x9.3
-TYPED_TEST(IntegerConversionTest, OtherConversions) {
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNull(),
-                                          kNoConversionFlags,
-                                          &this->exception_state_));
-
-  const double kInfinity = std::numeric_limits<double>::infinity();
-  const double kNegativeInfinity = -std::numeric_limits<double>::infinity();
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsUndefined(),
-                                          kNoConversionFlags,
-                                          &this->exception_state_));
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsNumber(kInfinity),
-                   kNoConversionFlags, &this->exception_state_));
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                   this->exec_state_, JSC::jsNumber(kNegativeInfinity),
-                   kNoConversionFlags, &this->exception_state_));
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNaN(),
-                                          kNoConversionFlags,
-                                          &this->exception_state_));
-}
-
-// http://es5.github.io/#x9.3
-TYPED_TEST(FloatingPointConversionTest, OtherConversions) {
-  EXPECT_EQ(0, JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNull(),
-                                          kNoConversionFlags,
-                                          &this->exception_state_));
-
-  // Check that unrestricted types convert back as expected
-  const double kInfinity = std::numeric_limits<double>::infinity();
-  const double kNegativeInfinity = -std::numeric_limits<double>::infinity();
-
-  // Unrestricted non-finite floating point conversions
-  EXPECT_EQ(kInfinity, JSValueToNumber<TypeParam>(
-                           this->exec_state_, JSC::jsNumber(kInfinity),
-                           kNoConversionFlags, &this->exception_state_));
-  EXPECT_EQ(kNegativeInfinity,
-            JSValueToNumber<TypeParam>(
-                this->exec_state_, JSC::jsNumber(kNegativeInfinity),
-                kNoConversionFlags, &this->exception_state_));
-  EXPECT_TRUE(isnan(JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNaN(),
-                                               kNoConversionFlags,
-                                               &this->exception_state_)));
-
-  // Restricted non-finite floating point conversions. These should throw a
-  // TypeError.
-  EXPECT_CALL(this->exception_state_, SetSimpleExceptionVA(kNotFinite, _))
-      .Times(3);
-  JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNumber(kInfinity),
-                             kConversionFlagRestricted,
-                             &this->exception_state_);
-  JSValueToNumber<TypeParam>(
-      this->exec_state_, JSC::jsNumber(kNegativeInfinity),
-      kConversionFlagRestricted, &this->exception_state_);
-  JSValueToNumber<TypeParam>(this->exec_state_, JSC::jsNaN(),
-                             kConversionFlagRestricted,
-                             &this->exception_state_);
-}
-
-// ToNumber (http://es5.github.io/#x9.3) calls the ToPrimitive operation:
-//     http://es5.github.io/#x9.1
-// ToPrimitive calls the [[DefaultValue]] method of the object:
-//     http://es5.github.io/#x8.12.8
-TYPED_TEST(NumericConversionTest, ObjectConversion) {
-  JSC::JSLockHolder lock(this->jsc_global_object_->globalData());
-  JSC::Structure* structure =
-      JSC::createEmptyObjectStructure(this->jsc_global_object_->globalData(),
-                                      this->jsc_global_object_, JSC::jsNull());
-  {
-    JSC::JSObject* object =
-        JSC::constructEmptyObject(this->exec_state_, structure);
-    this->AddFunction(object, "valueOf", &(returnNumberFunction<5>));
-    EXPECT_EQ(
-        5, JSValueToNumber<TypeParam>(this->jsc_global_object_->globalExec(),
-                                      JSC::JSValue(object), kNoConversionFlags,
-                                      &this->exception_state_));
-  }
-  {
-    JSC::JSObject* object =
-        JSC::constructEmptyObject(this->exec_state_, structure);
-    // The conversion algorithm uses the value of toString() if it is
-    // a primitive value, which is not necessarily a string.
-    this->AddFunction(object, "toString", &(returnNumberFunction<5>));
-    EXPECT_EQ(5, JSValueToNumber<TypeParam>(
-                     this->exec_state_, JSC::JSValue(object),
-                     kNoConversionFlags, &this->exception_state_));
-  }
-  {
-    JSC::JSObject* object =
-        JSC::constructEmptyObject(this->exec_state_, structure);
-    EXPECT_EQ(0, JSValueToNumber<TypeParam>(
-                     this->exec_state_, JSC::JSValue(object),
-                     kNoConversionFlags, &this->exception_state_));
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/prototype_base.h b/src/cobalt/script/javascriptcore/prototype_base.h
deleted file mode 100644
index 592b8ce..0000000
--- a/src/cobalt/script/javascriptcore/prototype_base.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_PROTOTYPE_BASE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_PROTOTYPE_BASE_H_
-
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// All JavaScriptCore interface object classes will inherit from this.
-class PrototypeBase : public JSC::JSNonFinalObject {
-  // This class doesn't have any implementation, and is just used as a common
-  // base class.
- protected:
-  PrototypeBase(JSC::JSGlobalObject* global_object, JSC::Structure* structure)
-      : JSC::JSNonFinalObject(global_object->globalData(), structure) {}
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_PROTOTYPE_BASE_H_
diff --git a/src/cobalt/script/javascriptcore/script_object_registry.cc b/src/cobalt/script/javascriptcore/script_object_registry.cc
deleted file mode 100644
index 2d3b09f..0000000
--- a/src/cobalt/script/javascriptcore/script_object_registry.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/script_object_registry.h"
-
-#include <utility>
-
-#include "base/stl_util.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-void ScriptObjectRegistry::RegisterObjectOwner(const Wrappable* owner,
-                                               JSC::JSObject* js_object) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(owner);
-  DCHECK(js_object);
-  owned_object_multimap_.insert(
-      std::make_pair(owner, new JSC::Weak<JSC::JSObject>(js_object)));
-}
-
-void ScriptObjectRegistry::DeregisterObjectOwner(const Wrappable* owner,
-                                                 JSC::JSObject* js_object) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  std::pair<OwnedObjectMultiMap::iterator, OwnedObjectMultiMap::iterator>
-      pair_range;
-  pair_range = owned_object_multimap_.equal_range(owner);
-  for (OwnedObjectMultiMap::iterator it = pair_range.first;
-       it != pair_range.second; ++it) {
-    if (it->second->get() == js_object) {
-      // There may be multiple mappings between a specific owner and
-      // js_object. Only remove the first mapping.
-      delete it->second;
-      owned_object_multimap_.erase(it);
-      return;
-    }
-  }
-}
-
-void ScriptObjectRegistry::VisitOwnedObjects(Wrappable* owner,
-                                             JSC::SlotVisitor* visitor) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  std::pair<OwnedObjectMultiMap::iterator, OwnedObjectMultiMap::iterator>
-      pair_range;
-  pair_range = owned_object_multimap_.equal_range(owner);
-  for (OwnedObjectMultiMap::iterator it = pair_range.first;
-       it != pair_range.second; ++it) {
-    visitor->appendUnbarrieredWeak(it->second);
-  }
-}
-
-void ScriptObjectRegistry::ClearEntries() {
-  STLDeleteValues(&owned_object_multimap_);
-}
-
-ScriptObjectRegistry::~ScriptObjectRegistry() {
-  // Since the ScriptObjectRegistry is destroyed after JSGlobalData, we can't
-  // free any remaining JSC::Weak objects in here since they will try to access
-  // structures that have already been destroyed.
-  DCHECK_EQ(owned_object_multimap_.size(), 0);
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/script_object_registry.h b/src/cobalt/script/javascriptcore/script_object_registry.h
deleted file mode 100644
index e503581..0000000
--- a/src/cobalt/script/javascriptcore/script_object_registry.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_SCRIPT_OBJECT_REGISTRY_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_SCRIPT_OBJECT_REGISTRY_H_
-
-#include "base/hash_tables.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// ScriptObjectRegistry maintains the mapping between Wrappable
-// objects and the JSObjects that they reference.
-class ScriptObjectRegistry {
- public:
-  // Register an ownership relationship between |owner| and |js_object|.
-  // After registering this relationship, VisitOwnedObjects() can be called
-  // to visit all objects registered to the owner. DeregisterObjectOwner
-  // must be called before |owner| is destroyed.
-  void RegisterObjectOwner(const Wrappable* owner, JSC::JSObject* js_object);
-
-  // Deregister the mapping of all objects owned by |owner|. js_object may
-  // be getting garbage collected so should not be referenced.
-  void DeregisterObjectOwner(const Wrappable* owner, JSC::JSObject* js_object);
-
-  // Visit objects that are owned by the specified JSObject.
-  void VisitOwnedObjects(Wrappable* owner, JSC::SlotVisitor* visitor);
-
-  // Clear all entries and free allocated memory. This should be called before
-  // the JSGlobalData is destroyed.
-  void ClearEntries();
-
-  ~ScriptObjectRegistry();
-
- private:
-  typedef base::hash_multimap<const Wrappable*, JSC::Weak<JSC::JSObject>*>
-      OwnedObjectMultiMap;
-  base::ThreadChecker thread_checker_;
-  OwnedObjectMultiMap owned_object_multimap_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_SCRIPT_OBJECT_REGISTRY_H_
diff --git a/src/cobalt/script/javascriptcore/thread_local_hash_table.cc b/src/cobalt/script/javascriptcore/thread_local_hash_table.cc
deleted file mode 100644
index ecd089f..0000000
--- a/src/cobalt/script/javascriptcore/thread_local_hash_table.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "cobalt/script/javascriptcore/thread_local_hash_table.h"
-
-#include <map>
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-namespace {
-typedef std::map<const JSC::ClassInfo*, JSC::HashTable> HashTableMap;
-}
-
-// static
-ThreadLocalHashTable* ThreadLocalHashTable::GetInstance() {
-  return Singleton<ThreadLocalHashTable>::get();
-}
-
-ThreadLocalHashTable::ThreadLocalHashTable() : slot_(SlotDestructor) {}
-
-ThreadLocalHashTable::~ThreadLocalHashTable() {
-  // If there is any data stored in our slot on this thread, destroy it now
-  // before freeing the slot itself, otherwise that data will be leaked.
-  SlotDestructor(slot_.Get());
-  slot_.Free();
-}
-
-JSC::HashTable* ThreadLocalHashTable::GetHashTable(
-    const JSC::ClassInfo* class_info, const JSC::HashTable& prototype) {
-  if (!slot_.Get()) {
-    slot_.Set(new HashTableMap);
-  }
-  DCHECK(slot_.Get());
-  HashTableMap* hash_table_map = static_cast<HashTableMap*>(slot_.Get());
-  if (hash_table_map->find(class_info) == hash_table_map->end()) {
-    (*hash_table_map)[class_info] = prototype;
-  }
-  return &(*hash_table_map)[class_info];
-}
-
-// static
-void ThreadLocalHashTable::SlotDestructor(void* value) {
-  HashTableMap* hash_table_map = static_cast<HashTableMap*>(value);
-  if (hash_table_map) {
-    for (HashTableMap::iterator it = hash_table_map->begin();
-         it != hash_table_map->end(); ++it) {
-      it->second.deleteTable();
-    }
-    delete hash_table_map;
-  }
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/thread_local_hash_table.h b/src/cobalt/script/javascriptcore/thread_local_hash_table.h
deleted file mode 100644
index 2801d77..0000000
--- a/src/cobalt/script/javascriptcore/thread_local_hash_table.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_THREAD_LOCAL_HASH_TABLE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_THREAD_LOCAL_HASH_TABLE_H_
-
-#include "base/memory/singleton.h"
-#include "base/threading/thread_local_storage.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/Lookup.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class ThreadLocalHashTable {
- public:
-  static ThreadLocalHashTable* GetInstance();
-
-  JSC::HashTable* GetHashTable(const JSC::ClassInfo* class_info,
-                               const JSC::HashTable& prototype);
-
- private:
-  ThreadLocalHashTable();
-  ~ThreadLocalHashTable();
-  static void SlotDestructor(void* value);
-
-  base::ThreadLocalStorage::Slot slot_;
-
-  friend struct DefaultSingletonTraits<ThreadLocalHashTable>;
-  DISALLOW_COPY_AND_ASSIGN(ThreadLocalHashTable);
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_THREAD_LOCAL_HASH_TABLE_H_
diff --git a/src/cobalt/script/javascriptcore/type_traits.h b/src/cobalt/script/javascriptcore/type_traits.h
deleted file mode 100644
index f7bba62..0000000
--- a/src/cobalt/script/javascriptcore/type_traits.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_TYPE_TRAITS_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_TYPE_TRAITS_H_
-
-#include "cobalt/script/callback_interface_traits.h"
-#include "cobalt/script/javascriptcore/jsc_callback_function_holder.h"
-#include "cobalt/script/javascriptcore/jsc_callback_interface_holder.h"
-#include "cobalt/script/javascriptcore/jsc_object_handle_holder.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-template <typename T>
-struct TypeTraits {
-  // The type to convert into from a JS Value in the bindings implementation.
-  typedef T ConversionType;
-  // Type type returned from a Cobalt implementation of a bound function.
-  typedef T ReturnType;
-};
-
-template <>
-struct TypeTraits<OpaqueHandle> {
-  typedef JSCObjectHandleHolder ConversionType;
-  typedef const ScriptObject<OpaqueHandle>* ReturnType;
-};
-
-template <typename Sig>
-struct TypeTraits<CallbackFunction<Sig> > {
-  typedef JSCCallbackFunctionHolder<CallbackFunction<Sig> > ConversionType;
-  typedef const ScriptObject<CallbackFunction<Sig> >* ReturnType;
-};
-
-template <typename CallbackInterface>
-struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > {
-  typedef JSCCallbackInterfaceHolder<CallbackInterface> ConversionType;
-  typedef const ScriptObject<CallbackInterface>* ReturnType;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_TYPE_TRAITS_H_
diff --git a/src/cobalt/script/javascriptcore/union_type_conversion_forward.h b/src/cobalt/script/javascriptcore/union_type_conversion_forward.h
deleted file mode 100644
index 04f0d97..0000000
--- a/src/cobalt/script/javascriptcore/union_type_conversion_forward.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// This file was GENERATED by command:
-//     pump.py union_type_conversion_forward.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
-
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/union_type.h"
-
-// Forward declaration for ToJSValue and FromJSValue for IDL union types.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-template <typename T1, typename T2>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-    const script::UnionType2<T1, T2>& in_union);
-
-template <typename T1, typename T2>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType2<T1, T2>* out_union);
-
-template <typename T1, typename T2, typename T3>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-    const script::UnionType3<T1, T2, T3>& in_union);
-
-template <typename T1, typename T2, typename T3>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType3<T1, T2, T3>* out_union);
-
-template <typename T1, typename T2, typename T3, typename T4>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-    const script::UnionType4<T1, T2, T3, T4>& in_union);
-
-template <typename T1, typename T2, typename T3, typename T4>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType4<T1, T2, T3, T4>* out_union);
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/javascriptcore/union_type_conversion_forward.h.pump b/src/cobalt/script/javascriptcore/union_type_conversion_forward.h.pump
deleted file mode 100644
index d6268cd..0000000
--- a/src/cobalt/script/javascriptcore/union_type_conversion_forward.h.pump
+++ /dev/null
@@ -1,58 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ Maximum number of different member types in a union.
-$var MAX_MEMBERS = 4
-
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
-#define SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
-
-#include "cobalt/script/javascriptcore/jsc_exception_state.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/union_type.h"
-
-// Forward declaration for ToJSValue and FromJSValue for IDL union types.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-$range NUM_MEMBERS 2..MAX_MEMBERS
-$for NUM_MEMBERS [[
-$range TYPE 1..NUM_MEMBERS
-
-template <$for TYPE , [[typename T$(TYPE)]]>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union);
-
-template <$for TYPE , [[typename T$(TYPE)]]>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union);
-
-]]  $$ for NUM_MEMBERS
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/javascriptcore/union_type_conversion_impl.h b/src/cobalt/script/javascriptcore/union_type_conversion_impl.h
deleted file mode 100644
index 9122056..0000000
--- a/src/cobalt/script/javascriptcore/union_type_conversion_impl.h
+++ /dev/null
@@ -1,625 +0,0 @@
-// This file was GENERATED by command:
-//     pump.py union_type_conversion_impl.h.pump
-// DO NOT EDIT BY HAND!!!
-
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
-
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/union_type.h"
-
-// Conversion to/from JSC::JSValue for IDL union types.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-template <typename T1, typename T2>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                       const script::UnionType2<T1, T2>& in_union) {
-  if (in_union.template IsType<T1>()) {
-    return ToJSValue(global_object, in_union.template AsType<T1>());
-  }
-  if (in_union.template IsType<T2>()) {
-    return ToJSValue(global_object, in_union.template AsType<T2>());
-  }
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-
-template <typename T1, typename T2>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType2<T1, T2>* out_union) {
-  DCHECK_EQ(0, conversion_flags);
-  // JS -> IDL type conversion procedure described here:
-  // http://heycam.github.io/webidl/#es-union
-
-  // 1. If the union type includes a nullable type and V is null or undefined,
-  // then return the IDL value null.
-  if (jsvalue.isNull() || jsvalue.isUndefined()) {
-    // If the type was nullable or undefined, we should have caught that as a
-    // part of the base::optional<T> conversion.
-    NOTREACHED();
-    return;
-  }
-  // Typedef for readability.
-  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
-
-  // Forward declare all potential types
-  T1 t1;
-  T2 t2;
-
-  // 3.1 If types includes an interface type that V implements, then return the
-  //     IDL value that is a reference to the object V.
-  // 3.2 If types includes object, then return the IDL value that is a reference
-  //     to the object V.
-  //
-  // The specification doesn't dictate what should happen if V implements more
-  // than one of the interfaces. For example, if V implements interface B and
-  // interface B inherits from interface A, what happens if both A and B are
-  // union members? Blink doesn't seem to do anything special for this case.
-  // Just choose the first interface in the flattened members that matches.
-  if (jsvalue.isObject()) {
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-    const WrapperFactory* wrapper_factory = global_object->wrapper_factory();
-    JSC::JSCell* js_cell = jsvalue.asCell();
-
-    if (UnionTypeTraitsT1::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT1::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType2<T1, T2>(t1);
-      return;
-    }
-    if (UnionTypeTraitsT2::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT2::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType2<T1, T2>(t2);
-      return;
-    }
-  }
-
-  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
-  //       TypedArrayName, callback functions, dictionary, array type.
-  //       And sequences if necessary.
-
-  // 14. If V is a Boolean value, then:
-  //   1. If types includes a boolean, then return the result of converting V
-  //      to boolean.
-  if (jsvalue.isBoolean()) {
-    if (UnionTypeTraitsT1::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType2<T1, T2>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType2<T1, T2>(t2);
-      return;
-    }
-  }
-
-  // 15. If V is a Number value, then:
-  //   1. If types includes a numeric type, then return the result of converting
-  //      V to that numeric type.
-  if (jsvalue.isNumber()) {
-    if (UnionTypeTraitsT1::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType2<T1, T2>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType2<T1, T2>(t2);
-      return;
-    }
-  }
-
-  // 16. If types includes a string type, then return the result of converting V
-  // to that type.
-  if (jsvalue.isString()) {
-    if (UnionTypeTraitsT1::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType2<T1, T2>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType2<T1, T2>(t2);
-      return;
-    }
-  }
-
-  // 17. If types includes a numeric type, then return the result of converting
-  // V to that numeric type.
-  if (UnionTypeTraitsT1::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType2<T1, T2>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType2<T1, T2>(t2);
-    return;
-  }
-
-  // 18. If types includes a boolean, then return the result of converting V to
-  // boolean.
-  if (UnionTypeTraitsT1::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType2<T1, T2>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType2<T1, T2>(t2);
-    return;
-  }
-
-  // 19. Throw a TypeError.
-  exception_state->SetSimpleException(kNotUnionType);
-}
-
-template <typename T1, typename T2, typename T3>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                       const script::UnionType3<T1, T2, T3>& in_union) {
-  if (in_union.template IsType<T1>()) {
-    return ToJSValue(global_object, in_union.template AsType<T1>());
-  }
-  if (in_union.template IsType<T2>()) {
-    return ToJSValue(global_object, in_union.template AsType<T2>());
-  }
-  if (in_union.template IsType<T3>()) {
-    return ToJSValue(global_object, in_union.template AsType<T3>());
-  }
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-
-template <typename T1, typename T2, typename T3>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType3<T1, T2, T3>* out_union) {
-  DCHECK_EQ(0, conversion_flags);
-  // JS -> IDL type conversion procedure described here:
-  // http://heycam.github.io/webidl/#es-union
-
-  // 1. If the union type includes a nullable type and V is null or undefined,
-  // then return the IDL value null.
-  if (jsvalue.isNull() || jsvalue.isUndefined()) {
-    // If the type was nullable or undefined, we should have caught that as a
-    // part of the base::optional<T> conversion.
-    NOTREACHED();
-    return;
-  }
-  // Typedef for readability.
-  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3;
-
-  // Forward declare all potential types
-  T1 t1;
-  T2 t2;
-  T3 t3;
-
-  // 3.1 If types includes an interface type that V implements, then return the
-  //     IDL value that is a reference to the object V.
-  // 3.2 If types includes object, then return the IDL value that is a reference
-  //     to the object V.
-  //
-  // The specification doesn't dictate what should happen if V implements more
-  // than one of the interfaces. For example, if V implements interface B and
-  // interface B inherits from interface A, what happens if both A and B are
-  // union members? Blink doesn't seem to do anything special for this case.
-  // Just choose the first interface in the flattened members that matches.
-  if (jsvalue.isObject()) {
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-    const WrapperFactory* wrapper_factory = global_object->wrapper_factory();
-    JSC::JSCell* js_cell = jsvalue.asCell();
-
-    if (UnionTypeTraitsT1::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT1::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType3<T1, T2, T3>(t1);
-      return;
-    }
-    if (UnionTypeTraitsT2::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT2::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType3<T1, T2, T3>(t2);
-      return;
-    }
-    if (UnionTypeTraitsT3::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT3::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType3<T1, T2, T3>(t3);
-      return;
-    }
-  }
-
-  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
-  //       TypedArrayName, callback functions, dictionary, array type.
-  //       And sequences if necessary.
-
-  // 14. If V is a Boolean value, then:
-  //   1. If types includes a boolean, then return the result of converting V
-  //      to boolean.
-  if (jsvalue.isBoolean()) {
-    if (UnionTypeTraitsT1::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType3<T1, T2, T3>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType3<T1, T2, T3>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType3<T1, T2, T3>(t3);
-      return;
-    }
-  }
-
-  // 15. If V is a Number value, then:
-  //   1. If types includes a numeric type, then return the result of converting
-  //      V to that numeric type.
-  if (jsvalue.isNumber()) {
-    if (UnionTypeTraitsT1::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType3<T1, T2, T3>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType3<T1, T2, T3>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType3<T1, T2, T3>(t3);
-      return;
-    }
-  }
-
-  // 16. If types includes a string type, then return the result of converting V
-  // to that type.
-  if (jsvalue.isString()) {
-    if (UnionTypeTraitsT1::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType3<T1, T2, T3>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType3<T1, T2, T3>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType3<T1, T2, T3>(t3);
-      return;
-    }
-  }
-
-  // 17. If types includes a numeric type, then return the result of converting
-  // V to that numeric type.
-  if (UnionTypeTraitsT1::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType3<T1, T2, T3>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType3<T1, T2, T3>(t2);
-    return;
-  }
-  if (UnionTypeTraitsT3::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-    *out_union = script::UnionType3<T1, T2, T3>(t3);
-    return;
-  }
-
-  // 18. If types includes a boolean, then return the result of converting V to
-  // boolean.
-  if (UnionTypeTraitsT1::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType3<T1, T2, T3>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType3<T1, T2, T3>(t2);
-    return;
-  }
-  if (UnionTypeTraitsT3::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-    *out_union = script::UnionType3<T1, T2, T3>(t3);
-    return;
-  }
-
-  // 19. Throw a TypeError.
-  exception_state->SetSimpleException(kNotUnionType);
-}
-
-template <typename T1, typename T2, typename T3, typename T4>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                       const script::UnionType4<T1, T2, T3, T4>& in_union) {
-  if (in_union.template IsType<T1>()) {
-    return ToJSValue(global_object, in_union.template AsType<T1>());
-  }
-  if (in_union.template IsType<T2>()) {
-    return ToJSValue(global_object, in_union.template AsType<T2>());
-  }
-  if (in_union.template IsType<T3>()) {
-    return ToJSValue(global_object, in_union.template AsType<T3>());
-  }
-  if (in_union.template IsType<T4>()) {
-    return ToJSValue(global_object, in_union.template AsType<T4>());
-  }
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-
-template <typename T1, typename T2, typename T3, typename T4>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType4<T1, T2, T3, T4>* out_union) {
-  DCHECK_EQ(0, conversion_flags);
-  // JS -> IDL type conversion procedure described here:
-  // http://heycam.github.io/webidl/#es-union
-
-  // 1. If the union type includes a nullable type and V is null or undefined,
-  // then return the IDL value null.
-  if (jsvalue.isNull() || jsvalue.isUndefined()) {
-    // If the type was nullable or undefined, we should have caught that as a
-    // part of the base::optional<T> conversion.
-    NOTREACHED();
-    return;
-  }
-  // Typedef for readability.
-  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3;
-  typedef ::cobalt::script::internal::UnionTypeTraits<T4> UnionTypeTraitsT4;
-
-  // Forward declare all potential types
-  T1 t1;
-  T2 t2;
-  T3 t3;
-  T4 t4;
-
-  // 3.1 If types includes an interface type that V implements, then return the
-  //     IDL value that is a reference to the object V.
-  // 3.2 If types includes object, then return the IDL value that is a reference
-  //     to the object V.
-  //
-  // The specification doesn't dictate what should happen if V implements more
-  // than one of the interfaces. For example, if V implements interface B and
-  // interface B inherits from interface A, what happens if both A and B are
-  // union members? Blink doesn't seem to do anything special for this case.
-  // Just choose the first interface in the flattened members that matches.
-  if (jsvalue.isObject()) {
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-    const WrapperFactory* wrapper_factory = global_object->wrapper_factory();
-    JSC::JSCell* js_cell = jsvalue.asCell();
-
-    if (UnionTypeTraitsT1::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT1::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-      return;
-    }
-    if (UnionTypeTraitsT2::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT2::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-      return;
-    }
-    if (UnionTypeTraitsT3::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT3::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-      return;
-    }
-    if (UnionTypeTraitsT4::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT4::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-      return;
-    }
-  }
-
-  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
-  //       TypedArrayName, callback functions, dictionary, array type.
-  //       And sequences if necessary.
-
-  // 14. If V is a Boolean value, then:
-  //   1. If types includes a boolean, then return the result of converting V
-  //      to boolean.
-  if (jsvalue.isBoolean()) {
-    if (UnionTypeTraitsT1::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-      return;
-    }
-
-    if (UnionTypeTraitsT4::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-      return;
-    }
-  }
-
-  // 15. If V is a Number value, then:
-  //   1. If types includes a numeric type, then return the result of converting
-  //      V to that numeric type.
-  if (jsvalue.isNumber()) {
-    if (UnionTypeTraitsT1::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-      return;
-    }
-
-    if (UnionTypeTraitsT4::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-      return;
-    }
-  }
-
-  // 16. If types includes a string type, then return the result of converting V
-  // to that type.
-  if (jsvalue.isString()) {
-    if (UnionTypeTraitsT1::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-      return;
-    }
-
-    if (UnionTypeTraitsT2::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-      return;
-    }
-
-    if (UnionTypeTraitsT3::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-      return;
-    }
-
-    if (UnionTypeTraitsT4::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-      return;
-    }
-  }
-
-  // 17. If types includes a numeric type, then return the result of converting
-  // V to that numeric type.
-  if (UnionTypeTraitsT1::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-    return;
-  }
-  if (UnionTypeTraitsT3::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-    return;
-  }
-  if (UnionTypeTraitsT4::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-    return;
-  }
-
-  // 18. If types includes a boolean, then return the result of converting V to
-  // boolean.
-  if (UnionTypeTraitsT1::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t1);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
-    return;
-  }
-  if (UnionTypeTraitsT2::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t2);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
-    return;
-  }
-  if (UnionTypeTraitsT3::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t3);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
-    return;
-  }
-  if (UnionTypeTraitsT4::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t4);
-    *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
-    return;
-  }
-
-  // 19. Throw a TypeError.
-  exception_state->SetSimpleException(kNotUnionType);
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/javascriptcore/union_type_conversion_impl.h.pump b/src/cobalt/script/javascriptcore/union_type_conversion_impl.h.pump
deleted file mode 100644
index 54eae9a..0000000
--- a/src/cobalt/script/javascriptcore/union_type_conversion_impl.h.pump
+++ /dev/null
@@ -1,199 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ Maximum number of different member types in a union.
-$var MAX_MEMBERS = 4
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
-
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/union_type.h"
-
-// Conversion to/from JSC::JSValue for IDL union types.
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-$range NUM_MEMBERS 2..MAX_MEMBERS
-$for NUM_MEMBERS [[
-
-$range TYPE 1..NUM_MEMBERS
-
-template <$for TYPE , [[typename T$(TYPE)]]>
-JSC::JSValue ToJSValue(JSCGlobalObject* global_object,
-                       const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union) {
-$for TYPE [[
-
-  if (in_union.template IsType<T$(TYPE)>()) {
-    return ToJSValue(global_object, in_union.template AsType<T$(TYPE)>());
-  }
-]]
-
-  NOTREACHED();
-  return JSC::jsUndefined();
-}
-
-template <$for TYPE , [[typename T$(TYPE)]]>
-void FromJSValue(JSC::ExecState* exec_state, JSC::JSValue jsvalue,
-                 int conversion_flags, ExceptionState* exception_state,
-                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union) {
-  DCHECK_EQ(0, conversion_flags);
-  // JS -> IDL type conversion procedure described here:
-  // http://heycam.github.io/webidl/#es-union
-
-  // 1. If the union type includes a nullable type and V is null or undefined,
-  // then return the IDL value null.
-  if (jsvalue.isNull() || jsvalue.isUndefined()) {
-    // If the type was nullable or undefined, we should have caught that as a
-    // part of the base::optional<T> conversion.
-    NOTREACHED();
-    return;
-  }
-  // Typedef for readability.
-
-$for TYPE [[
-  typedef ::cobalt::script::internal::UnionTypeTraits<T$(TYPE)> UnionTypeTraitsT$(TYPE);
-
-]]
-
-  // Forward declare all potential types
-
-$for TYPE [[
-  T$(TYPE) t$(TYPE);
-
-]]
-
-  // 3.1 If types includes an interface type that V implements, then return the
-  //     IDL value that is a reference to the object V.
-  // 3.2 If types includes object, then return the IDL value that is a reference
-  //     to the object V.
-  //
-  // The specification doesn't dictate what should happen if V implements more
-  // than one of the interfaces. For example, if V implements interface B and
-  // interface B inherits from interface A, what happens if both A and B are
-  // union members? Blink doesn't seem to do anything special for this case.
-  // Just choose the first interface in the flattened members that matches.
-  if (jsvalue.isObject()) {
-    JSCGlobalObject* global_object =
-        JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
-    const WrapperFactory* wrapper_factory = global_object->wrapper_factory();
-    JSC::JSCell* js_cell = jsvalue.asCell();
-
-
-$for TYPE [[
-    if (UnionTypeTraitsT$(TYPE)::is_interface_type &&
-        js_cell->inherits(
-            wrapper_factory->GetClassInfo(
-                UnionTypeTraitsT$(TYPE)::GetTypeID()))) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-      return;
-    }
-
-]]
-  }
-
-  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
-  //       TypedArrayName, callback functions, dictionary, array type.
-  //       And sequences if necessary.
-
-  // 14. If V is a Boolean value, then:
-  //   1. If types includes a boolean, then return the result of converting V
-  //      to boolean.
-  if (jsvalue.isBoolean()) {
-$for TYPE [[
-
-    if (UnionTypeTraitsT$(TYPE)::is_boolean_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-      return;
-    }
-
-]]
-  }
-
-  // 15. If V is a Number value, then:
-  //   1. If types includes a numeric type, then return the result of converting
-  //      V to that numeric type.
-  if (jsvalue.isNumber()) {
-$for TYPE [[
-
-    if (UnionTypeTraitsT$(TYPE)::is_numeric_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-      return;
-    }
-
-]]
-  }
-
-  // 16. If types includes a string type, then return the result of converting V
-  // to that type.
-  if (jsvalue.isString()) {
-$for TYPE [[
-
-    if (UnionTypeTraitsT$(TYPE)::is_string_type) {
-      FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-      return;
-    }
-
-]]
-  }
-
-  // 17. If types includes a numeric type, then return the result of converting
-  // V to that numeric type.
-$for TYPE [[
-
-  if (UnionTypeTraitsT$(TYPE)::is_numeric_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-    *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-    return;
-  }
-]]
-
-
-  // 18. If types includes a boolean, then return the result of converting V to
-  // boolean.
-$for TYPE [[
-
-  if (UnionTypeTraitsT$(TYPE)::is_boolean_type) {
-    FromJSValue(exec_state, jsvalue, conversion_flags, exception_state, &t$(TYPE));
-    *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
-    return;
-  }
-]]
-
-
-  // 19. Throw a TypeError.
-  exception_state->SetSimpleException(kNotUnionType);
-}
-
-]]  $$ for NUM_MEMBERS
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/javascriptcore/util/binding_helpers.cc b/src/cobalt/script/javascriptcore/util/binding_helpers.cc
deleted file mode 100644
index 872aa1f..0000000
--- a/src/cobalt/script/javascriptcore/util/binding_helpers.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/util/binding_helpers.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace util {
-
-bool HasPropertyOnPrototype(JSC::ExecState* exec_state, JSC::JSCell* cell,
-                            JSC::PropertyName property_name) {
-  if (cell->isObject()) {
-    JSC::JSValue prototype_value = JSC::asObject(cell)->prototype();
-    if (prototype_value.isObject()) {
-      JSC::JSObject* prototype = JSC::asObject(prototype_value);
-      if (prototype->hasProperty(exec_state, property_name)) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-}  // namespace util
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/util/binding_helpers.h b/src/cobalt/script/javascriptcore/util/binding_helpers.h
deleted file mode 100644
index 3f51716..0000000
--- a/src/cobalt/script/javascriptcore/util/binding_helpers.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_BINDING_HELPERS_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_BINDING_HELPERS_H_
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSCell.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/PropertyName.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace util {
-
-bool HasPropertyOnPrototype(JSC::ExecState* exec_state, JSC::JSCell* cell,
-                            JSC::PropertyName property_name);
-
-}  // namespace util
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_BINDING_HELPERS_H_
diff --git a/src/cobalt/script/javascriptcore/util/exception_helpers.cc b/src/cobalt/script/javascriptcore/util/exception_helpers.cc
deleted file mode 100644
index 4e44e6c..0000000
--- a/src/cobalt/script/javascriptcore/util/exception_helpers.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/script/javascriptcore/util/exception_helpers.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/stringprintf.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/Interpreter.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSDestructibleObject.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSScope.h"
-#include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace util {
-
-std::string GetExceptionString(JSC::ExecState* exec_state) {
-  return GetExceptionString(exec_state, exec_state->exception());
-}
-
-std::string GetExceptionString(JSC::ExecState* exec_state,
-                               JSC::JSValue exception) {
-  JSC::JSGlobalData* global_data = &exec_state->globalData();
-
-  WTF::String wtf_exception_string = exception.toWTFString(exec_state);
-  std::string exception_string =
-      exception.toWTFString(exec_state).utf8().data();
-  exception_string += "\n";
-
-  JSC::JSObject* exception_object = exception.toObject(exec_state);
-  JSC::JSValue stack_value = exception_object->getDirect(
-      *global_data, global_data->propertyNames->stack);
-  if (!stack_value.isEmpty() && stack_value.isString()) {
-    exception_string += stack_value.toWTFString(exec_state).utf8().data();
-  } else {
-    int line_number =
-        exception_object->get(exec_state, JSC::Identifier(exec_state, "line"))
-            .toInt32(exec_state);
-    std::string source_url =
-        exception_object->get(exec_state,
-                              JSC::Identifier(exec_state, "sourceURL"))
-            .toWTFString(exec_state)
-            .utf8()
-            .data();
-    exception_string +=
-        base::StringPrintf("%s:%d", source_url.c_str(), line_number);
-  }
-  return exception_string;
-}
-
-std::vector<StackFrame> GetStackTrace(JSC::ExecState* exec, int max_frames) {
-  std::vector<StackFrame> stack_frames;
-  JSC::JSLockHolder lock(exec);
-
-  WTF::Vector<JSC::StackFrame> stack_trace;
-  exec->interpreter()->getStackTrace(&exec->globalData(), stack_trace);
-  if (max_frames == 0) {
-    max_frames = static_cast<int>(stack_trace.size());
-  } else {
-    max_frames = std::min(max_frames, static_cast<int>(stack_trace.size()));
-  }
-  for (int i = 0; i < max_frames; ++i) {
-    WTF::String function_name = stack_trace[i].friendlyFunctionName(exec);
-    WTF::String source_url = stack_trace[i].friendlySourceURL();
-    uint32 line_number = stack_trace[i].friendlyLineNumber();
-
-    StackFrame sf;
-    sf.function_name = function_name.utf8().data();
-    if (!source_url.isEmpty()) {
-      sf.source_url = source_url.utf8().data();
-    }
-    sf.line_number = line_number;
-    sf.column_number = 0;
-    stack_frames.push_back(sf);
-  }
-  return stack_frames;
-}
-
-}  // namespace util
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/util/exception_helpers.h b/src/cobalt/script/javascriptcore/util/exception_helpers.h
deleted file mode 100644
index 07918fd..0000000
--- a/src/cobalt/script/javascriptcore/util/exception_helpers.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_EXCEPTION_HELPERS_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_EXCEPTION_HELPERS_H_
-
-#include <string>
-#include <vector>
-
-#include "cobalt/script/stack_frame.h"
-
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/interpreter/CallFrame.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSValue.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace util {
-
-std::string GetExceptionString(JSC::ExecState* exec_state);
-
-std::string GetExceptionString(JSC::ExecState* exec_state,
-                               JSC::JSValue exception);
-
-// Retrieve stack frame information. Set max_frames to 0 to get all
-// available, or non-0 to limit the number of frames returned.
-std::vector<StackFrame> GetStackTrace(JSC::ExecState* exec_state,
-                                      int max_frames);
-
-}  // namespace util
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_UTIL_EXCEPTION_HELPERS_H_
diff --git a/src/cobalt/script/javascriptcore/wrapper_base.h b/src/cobalt/script/javascriptcore/wrapper_base.h
deleted file mode 100644
index cdcf27b..0000000
--- a/src/cobalt/script/javascriptcore/wrapper_base.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "cobalt/script/javascriptcore/jsc_global_object.h"
-#include "cobalt/script/script_exception.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorInstance.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSDestructibleObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-// All JavaScriptCore wrapper classes will inherit from this. This provides a
-// common base class for all wrapper objects. It holds a reference-counted
-// handle to a Wrappable object, which is the base class of all objects that
-// can be referenced from JavaScript.
-// The WrappableBase template class must be derived from script::Wrappable.
-template <typename JSCBaseClass, typename WrappableBase>
-class WrapperBase : public JSCBaseClass {
- public:
-  const scoped_refptr<WrappableBase>& wrappable() { return wrappable_; }
-
-  scoped_refptr<WrappableBase> GetOpaqueRoot() {
-    if (!get_opaque_root_function_.is_null()) {
-      return get_opaque_root_function_.Run(wrappable_);
-    }
-    return NULL;
-  }
-
-  static scoped_refptr<WrappableBase>& GetWrappable(JSC::JSObject* js_object) {
-    ASSERT_GC_OBJECT_INHERITS(js_object, WrapperBase::s_classinfo());
-    WrapperBase* wrapper_base = JSC::jsCast<WrapperBase*>(js_object);
-    return wrapper_base->wrappable_;
-  }
-
- protected:
-  typedef base::Callback<scoped_refptr<WrappableBase>(
-      const scoped_refptr<WrappableBase>&)> GetOpaqueRootFunction;
-
-  WrapperBase(JSC::JSGlobalData* global_data, JSC::Structure* structure,
-              ScriptObjectRegistry* script_object_registry,
-              const scoped_refptr<WrappableBase>& impl)
-      : JSCBaseClass(*global_data, structure),
-        wrappable_(impl),
-        script_object_registry_(script_object_registry) {}
-
-  void set_get_opaque_root_function(
-      const GetOpaqueRootFunction& get_opaque_root_function) {
-    DCHECK(get_opaque_root_function_.is_null());
-    get_opaque_root_function_ = get_opaque_root_function;
-  }
-
-  // static override. This function will be called during garbage collection
-  // to mark any garbage-collected objects that are referencable from this
-  // object.
-  static void visitChildren(JSC::JSCell* cell,
-      JSC::SlotVisitor& visitor) {  // NOLINT(runtime/references)
-    JSCBaseClass::visitChildren(cell, visitor);
-    WrapperBase* this_object = JSC::jsCast<WrapperBase*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(this_object, WrapperBase::s_classinfo());
-    // In general most wrappers won't have any such owned objects, but
-    // this shouldn't be too expensive.
-    this_object->script_object_registry_->VisitOwnedObjects(
-        this_object->wrappable_.get(), &visitor);
-  }
-
-  // static override. This will be called when this object is garbage collected.
-  static void destroy(JSC::JSCell* cell) {
-    // Note that the WrapperBase destructor is non-virtual.
-    // JSC's garbage-collected heap seems to not support classes with virtual
-    // functions, as suggested by the lack of a virtual destructor in JSCell,
-    // the base class for all GC objects, and the lack of any virtual functions
-    // in WebKit's bindings implementation.
-    // Garbage-collected classes with a non-trivial destructor and/or
-    // member variables that need to be destructed must override destroy() to
-    // ensure that the class is destructed properly.
-    static_cast<WrapperBase*>(cell)->~WrapperBase();
-  }
-
- private:
-  scoped_refptr<WrappableBase> wrappable_;
-  ScriptObjectRegistry* script_object_registry_;
-  GetOpaqueRootFunction get_opaque_root_function_;
-};
-
-// Base for regular interfaces.
-typedef WrapperBase<JSC::JSDestructibleObject, Wrappable> InterfaceBase;
-// Base for exception interfaces.
-typedef WrapperBase<JSC::ErrorInstance, ScriptException> ExceptionBase;
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_
diff --git a/src/cobalt/script/javascriptcore/wrapper_factory.cc b/src/cobalt/script/javascriptcore/wrapper_factory.cc
deleted file mode 100644
index 57fa196..0000000
--- a/src/cobalt/script/javascriptcore/wrapper_factory.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "cobalt/script/javascriptcore/wrapper_factory.h"
-
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "cobalt/script/javascriptcore/jsc_wrapper_handle.h"
-#include "cobalt/script/javascriptcore/wrapper_base.h"
-#include "third_party/WebKit/Source/JavaScriptCore/heap/WeakHandleOwner.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-namespace {
-
-class CachedHandleOwner : public JSC::WeakHandleOwner {
- public:
-  // Return true if handle can be reached from some root unknown to JSC.
-  // This can be used to keep a cached wrapper from being garbage collected
-  // even though there are no strong references to it.
-  bool isReachableFromOpaqueRoots(
-      JSC::Handle<JSC::Unknown> handle,
-      void* context,
-      JSC::SlotVisitor& visitor) OVERRIDE {  // NOLINT(runtime/references)
-    JSC::JSObject* js_object = JSC::asObject(handle.get().asCell());
-    if (js_object->isGlobalObject()) {
-      NOTREACHED() << "CachedHandleOwner shouldn't refer to a global object";
-      return false;
-    }
-
-    if (js_object->isErrorInstance()) {
-      return IsReachableFromOpaqueRoots(JSC::jsCast<ExceptionBase*>(js_object),
-                                        &visitor);
-    } else {
-      return IsReachableFromOpaqueRoots(JSC::jsCast<InterfaceBase*>(js_object),
-                                        &visitor);
-    }
-  }
-
- private:
-  template <class T>
-  bool IsReachableFromOpaqueRoots(T* wrapper_base,
-                                  JSC::SlotVisitor* slot_visitor) {
-    scoped_refptr<Wrappable> opaque_root = wrapper_base->GetOpaqueRoot();
-
-    // Check if we might want to keep this cached wrapper alive despite it not
-    // being referenced anywhere
-    if (!ShouldKeepWrapperAlive(wrapper_base, opaque_root)) {
-      return false;
-    }
-
-    // If this wrapper has an opaque root, check if that root has been marked.
-    // If the root is not alive, we do not want to keep this wrapper alive.
-    if (opaque_root && slot_visitor->containsOpaqueRoot(opaque_root.get())) {
-      return true;
-    }
-
-    // If this wrapper's wrappable has been marked as an opaque root, keep it
-    // alive.
-    if (slot_visitor->containsOpaqueRoot(wrapper_base->wrappable().get())) {
-      return true;
-    }
-
-    return false;
-  }
-
-  template <class T>
-  bool ShouldKeepWrapperAlive(T* wrapper_base,
-                              const scoped_refptr<Wrappable>& opaque_root) {
-    if (opaque_root && opaque_root == wrapper_base->wrappable()) {
-      // This is the root, so keep this wrapper alive. This will in turn keep
-      // the entire tree alive.
-      return true;
-    }
-
-    // If a custom property has been set on the wrapper object, we should keep
-    // it alive so that the property persists next time the object is
-    // referenced from JS.
-    if (wrapper_base->hasCustomProperties()) {
-      return true;
-    }
-
-    // Check if the wrapper should be kept alive based on the impl's state.
-    return wrapper_base->wrappable()->ShouldKeepWrapperAlive();
-  }
-};
-
-base::LazyInstance<CachedHandleOwner> cached_handle_owner =
-    LAZY_INSTANCE_INITIALIZER;
-}  // namespace
-
-void WrapperFactory::RegisterWrappableType(
-    base::TypeId wrappable_type, const JSC::ClassInfo* class_info,
-    const CreateWrapperFunction& create_function) {
-  std::pair<WrappableTypeInfoMap::iterator, bool> pib =
-      wrappable_type_infos_.insert(std::make_pair(
-          wrappable_type, WrappableTypeInfo(class_info, create_function)));
-  DCHECK(pib.second)
-      << "RegisterWrappableType registered for type more than once.";
-  wrapper_class_infos_.insert(class_info);
-}
-
-JSC::JSObject* WrapperFactory::GetWrapper(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) const {
-  if (!wrappable) {
-    return NULL;
-  }
-
-  JSC::JSObject* wrapper =
-      JSCWrapperHandle::GetJSObject(GetCachedWrapper(wrappable.get()));
-  if (!wrapper) {
-    if (global_object->global_interface() == wrappable) {
-      // Wrapper for the global object is a special case.
-      wrapper = global_object;
-    } else {
-      scoped_ptr<Wrappable::WeakWrapperHandle> object_handle =
-      WrapperFactory::CreateWrapper(global_object, wrappable);
-      SetCachedWrapper(wrappable.get(), object_handle.Pass());
-      wrapper = JSCWrapperHandle::GetJSObject(
-          GetCachedWrapper(wrappable.get()));
-    }
-  }
-  DCHECK(wrapper);
-  return wrapper;
-}
-
-bool WrapperFactory::IsWrapper(JSC::JSObject* js_object) const {
-  WrapperClassInfoSet::const_iterator it =
-      wrapper_class_infos_.find(js_object->classInfo());
-  return it != wrapper_class_infos_.end();
-}
-
-const JSC::ClassInfo* WrapperFactory::GetClassInfo(
-    base::TypeId wrappable_type) const {
-  WrappableTypeInfoMap::const_iterator it =
-      wrappable_type_infos_.find(wrappable_type);
-  if (it == wrappable_type_infos_.end()) {
-    NOTREACHED();
-    return NULL;
-  }
-  return it->second.class_info;
-}
-
-scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
-    JSCGlobalObject* global_object,
-    const scoped_refptr<Wrappable>& wrappable) const {
-  WrappableTypeInfoMap::const_iterator it =
-      wrappable_type_infos_.find(wrappable->GetWrappableType());
-  if (it == wrappable_type_infos_.end()) {
-    NOTREACHED();
-    return scoped_ptr<Wrappable::WeakWrapperHandle>();
-  }
-  return make_scoped_ptr<Wrappable::WeakWrapperHandle>(
-      new JSCWrapperHandle(JSC::PassWeak<JSC::JSObject>(
-          it->second.create_function.Run(global_object, wrappable),
-          cached_handle_owner.Pointer())));
-}
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/wrapper_factory.h b/src/cobalt/script/javascriptcore/wrapper_factory.h
deleted file mode 100644
index dbe2c1f..0000000
--- a/src/cobalt/script/javascriptcore/wrapper_factory.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_FACTORY_H_
-#define COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_FACTORY_H_
-
-#include "base/bind.h"
-#include "base/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "cobalt/base/type_id.h"
-#include "cobalt/script/wrappable.h"
-#include "third_party/WebKit/Source/JavaScriptCore/config.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/ClassInfo.h"
-#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSObject.h"
-
-namespace cobalt {
-namespace script {
-namespace javascriptcore {
-
-class JSCGlobalObject;
-
-class WrapperFactory : public Wrappable::CachedWrapperAccessor {
- public:
-  typedef base::Callback<JSC::JSObject*(
-      JSCGlobalObject*, const scoped_refptr<Wrappable>&)> CreateWrapperFunction;
-  void RegisterWrappableType(base::TypeId wrappable_type,
-                             const JSC::ClassInfo* class_info,
-                             const CreateWrapperFunction& create_function);
-
-  // Gets a Wrapper object for this Wrappable. It may create a new Wrapper.
-  JSC::JSObject* GetWrapper(JSCGlobalObject* global_object,
-                            const scoped_refptr<Wrappable>& wrappable) const;
-
-  // Returns true if this JSObject is a Wrapper object.
-  bool IsWrapper(JSC::JSObject* js_object) const;
-
-  // Gets the JSC::ClassInfo that corresponds to this Wrappable type.
-  const JSC::ClassInfo* GetClassInfo(base::TypeId wrappable_type) const;
-
- private:
-  scoped_ptr<Wrappable::WeakWrapperHandle> CreateWrapper(
-      JSCGlobalObject* global_object,
-      const scoped_refptr<Wrappable>& wrappable) const;
-
-  struct WrappableTypeInfo {
-    WrappableTypeInfo(const JSC::ClassInfo* info,
-                      const CreateWrapperFunction& function)
-        : class_info(info), create_function(function) {}
-    const JSC::ClassInfo* class_info;
-    CreateWrapperFunction create_function;
-  };
-  typedef base::hash_map<base::TypeId, WrappableTypeInfo> WrappableTypeInfoMap;
-  typedef base::hash_set<const JSC::ClassInfo*> WrapperClassInfoSet;
-
-  WrappableTypeInfoMap wrappable_type_infos_;
-  WrapperClassInfoSet wrapper_class_infos_;
-};
-
-}  // namespace javascriptcore
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_FACTORY_H_
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp
index 00b5356..7262cdc 100644
--- a/src/cobalt/script/mozjs/mozjs.gyp
+++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -42,6 +42,7 @@
       'dependencies': [
         '<(DEPTH)/cobalt/script/script.gyp:script',
         '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib',
+        'embed_mozjs_resources_as_header_files',
       ],
       'defines': [
         'MOZJS_GARBAGE_COLLECTION_THRESHOLD_IN_BYTES=<(mozjs_garbage_collection_threshold_in_bytes)',
@@ -104,5 +105,41 @@
       },
       'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
+
+    {
+      # This target takes specified files and embeds them as header files for
+      # inclusion into the binary. The script currently requires all resources
+      # to be embedded to live in the same directory.
+      'target_name': 'embed_mozjs_resources_as_header_files',
+      'type': 'none',
+      # Because we generate a header, we must set the hard_dependency flag.
+      'hard_dependency': 1,
+      'variables': {
+        'script_path': '<(DEPTH)/cobalt/build/generate_data_header.py',
+        'output_path': '<(SHARED_INTERMEDIATE_DIR)/cobalt/script/mozjs/embedded_resources.h',
+      },
+      'sources': [
+        '<(DEPTH)/third_party/promise-polyfill/promise.min.js',
+      ],
+      'actions': [
+        {
+          'action_name': 'embed_mozjs_resources_as_header_files',
+          'inputs': [
+            '<(script_path)',
+            '<@(_sources)',
+          ],
+          'outputs': [
+            '<(output_path)',
+          ],
+          'action': ['python', '<(script_path)', 'MozjsEmbeddedResources', '<(output_path)', '<@(_sources)' ],
+          'message': 'Embedding MozJS resources in into header file, "<(output_path)".',
+        },
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '<(SHARED_INTERMEDIATE_DIR)',
+        ],
+      },
+    },
   ],
 }
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc
index ee1237f..337db82 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -22,6 +22,7 @@
 #include "base/stringprintf.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/embedded_resources.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_source_code.h"
 #include "cobalt/script/mozjs/mozjs_wrapper_handle.h"
@@ -193,6 +194,8 @@
       context_, ProxyHandler::NewProxy(context_, global_object, NULL, NULL,
                                        proxy_handler.Pointer()));
   global_object_proxy_ = proxy;
+
+  EvaluateAutomatics();
 }
 
 bool MozjsGlobalEnvironment::EvaluateScript(
@@ -350,6 +353,20 @@
   DCHECK(success);
 }
 
+void MozjsGlobalEnvironment::EvaluateAutomatics() {
+  TRACK_MEMORY_SCOPE("Javascript");
+  std::string source(
+      reinterpret_cast<const char*>(MozjsEmbeddedResources::promise_min_js),
+      sizeof(MozjsEmbeddedResources::promise_min_js));
+  scoped_refptr<SourceCode> source_code =
+      new MozjsSourceCode(source, base::SourceLocation("promise.min.js", 1, 1));
+  std::string result;
+  bool success = EvaluateScript(source_code, &result);
+  if (!success) {
+    DLOG(FATAL) << result;
+  }
+}
+
 InterfaceData* MozjsGlobalEnvironment::GetInterfaceData(intptr_t key) {
   CachedInterfaceData::iterator it = cached_interface_data_.find(key);
   if (it != cached_interface_data_.end()) {
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.h b/src/cobalt/script/mozjs/mozjs_global_environment.h
index 8f719e3..ff6e83d 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.h
@@ -77,6 +77,9 @@
   void Bind(const std::string& identifier,
             const scoped_refptr<Wrappable>& impl) OVERRIDE;
 
+  // Evaluates any automatically included Javascript for the environment.
+  void EvaluateAutomatics();
+
   JSContext* context() const { return context_; }
 
   JSObject* global_object_proxy() const { return global_object_proxy_; }
diff --git a/src/cobalt/script/sequence.h b/src/cobalt/script/sequence.h
index 683f6e0..71fd46b 100644
--- a/src/cobalt/script/sequence.h
+++ b/src/cobalt/script/sequence.h
@@ -17,6 +17,7 @@
 #ifndef COBALT_SCRIPT_SEQUENCE_H_
 #define COBALT_SCRIPT_SEQUENCE_H_
 
+#include <algorithm>
 #include <iosfwd>
 #include <vector>
 
@@ -58,7 +59,9 @@
   typedef typename SequenceType::const_reference const_reference;
   void push_back(const_reference value) { sequence_.push_back(value); }
   size_type size() const { return sequence_.size(); }
+  bool empty() const { return sequence_.empty(); }
   const_reference at(size_type index) const { return sequence_.at(index); }
+  void swap(Sequence<T>& other) { sequence_.swap(other.sequence_); }
 
  private:
   SequenceType sequence_;
diff --git a/src/cobalt/test/document_loader.h b/src/cobalt/test/document_loader.h
index bffc7a8..f905a29 100644
--- a/src/cobalt/test/document_loader.h
+++ b/src/cobalt/test/document_loader.h
@@ -65,8 +65,8 @@
             NULL /* web_media_player_factory */, &script_runner_,
             NULL /* media_source_registry */, &resource_provider_,
             image_cache_.get(), NULL /* reduced_image_cache_capacity_manager */,
-            NULL /* remote_font_cache */, dom_stat_tracker_.get(),
-            "" /* language */) {}
+            NULL /* remote_font_cache */, NULL /* mesh_cache */,
+            dom_stat_tracker_.get(), "" /* language */) {}
   void Load(const GURL& url) {
     // Load the document in a nested message loop.
     dom::Document::Options options(url);
diff --git a/src/cobalt/test/empty_document.h b/src/cobalt/test/empty_document.h
index 9fae1b9..c65159f 100644
--- a/src/cobalt/test/empty_document.h
+++ b/src/cobalt/test/empty_document.h
@@ -33,7 +33,7 @@
       : css_parser_(css_parser::Parser::Create()),
         dom_stat_tracker_(new dom::DomStatTracker("EmptyDocument")),
         html_element_context_(NULL, css_parser_.get(), NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, NULL, NULL,
+                              NULL, NULL, NULL, NULL, NULL, NULL,
                               dom_stat_tracker_.get(), ""),
         document_(new dom::Document(&html_element_context_)) {}
 
diff --git a/src/cobalt/webdriver/dispatcher.cc b/src/cobalt/webdriver/dispatcher.cc
index a035bc8..0eb1bce 100644
--- a/src/cobalt/webdriver/dispatcher.cc
+++ b/src/cobalt/webdriver/dispatcher.cc
@@ -164,9 +164,8 @@
   // Use reverse iterators for the match so we can early-out of a mismatch
   // more quickly. Most requests start with '/session/:sessionId/', for
   // example.
-  typedef std::pair<std::vector<std::string>::const_reverse_iterator,
-                    std::vector<std::string>::const_reverse_iterator>
-      MismatchResultPair;
+  typedef std::vector<std::string>::const_reverse_iterator MismatchResult;
+  typedef std::pair<MismatchResult, MismatchResult> MismatchResultPair;
   typedef std::pair<CommandMappingLookup::iterator,
                     CommandMappingLookup::iterator> EqualRangeResultPair;
 
@@ -189,7 +188,7 @@
     if (result_pair.first == components.rend()) {
       DCHECK(
           result_pair.second ==
-          static_cast<const CommandMapping>(it->second).path_components.rend());
+          static_cast<MismatchResult>(it->second.path_components.rend()));
       return &it->second;
     }
   }
diff --git a/src/cobalt/webdriver/get_element_text_test.cc b/src/cobalt/webdriver/get_element_text_test.cc
index b9a87e9..a42b3a2 100644
--- a/src/cobalt/webdriver/get_element_text_test.cc
+++ b/src/cobalt/webdriver/get_element_text_test.cc
@@ -43,7 +43,7 @@
       : css_parser_(css_parser::Parser::Create()),
         dom_stat_tracker_(new dom::DomStatTracker("GetElementTextTest")),
         html_element_context_(NULL, css_parser_.get(), NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, NULL, NULL,
+                              NULL, NULL, NULL, NULL, NULL, NULL,
                               dom_stat_tracker_.get(), "") {}
 
   void SetUp() OVERRIDE {
diff --git a/src/cobalt/webdriver/testing/stub_window.h b/src/cobalt/webdriver/testing/stub_window.h
index aa6c912..fdd4cad 100644
--- a/src/cobalt/webdriver/testing/stub_window.h
+++ b/src/cobalt/webdriver/testing/stub_window.h
@@ -52,7 +52,7 @@
     global_environment_ = engine_->CreateGlobalEnvironment();
     window_ = new dom::Window(
         1920, 1080, css_parser_.get(), dom_parser_.get(),
-        fetcher_factory_.get(), NULL, NULL, NULL, NULL,
+        fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL,
         &local_storage_database_, stub_media_module_.get(),
         stub_media_module_.get(), NULL, NULL, NULL, dom_stat_tracker_.get(),
         url_, "", "en-US", base::Callback<void(const GURL&)>(),
diff --git a/src/cobalt/webdriver_benchmarks/tests/README.md b/src/cobalt/webdriver_benchmarks/tests/README.md
index 1274513..032c41c 100644
--- a/src/cobalt/webdriver_benchmarks/tests/README.md
+++ b/src/cobalt/webdriver_benchmarks/tests/README.md
@@ -6,8 +6,8 @@
 
 Each file should contain a set of tests in Python "unittest" format.
 
-All tests in all of the files in this directory will be run on the build system.
-Results can be recorded in the build results database.
+All tests in all of the files included within "all.py" will be run on the
+build system. Results can be recorded in the build results database.
 
 To run an individual test, simply execute a script directly (or run
 all of them via "all.py"). Platform configuration will be inferred from
@@ -17,12 +17,16 @@
 To make a new test:
 
  1. If appropriate, create a new file borrowing the boilerplate from
-    an existing simple file, such as "shelf.py"
+    an existing simple file, such as "browse_horizontal.py".
 
- 2. If this file contains internal names or details, consider adding it
+ 2. Add the file name to the tests added within "all.py", causing it run
+    when "all.py" is run.
+
+ 3. If this file contains internal names or details, consider adding it
     to the "EXCLUDE.FILES" list.
 
- 3. Use the `record_test_result*` methods in `tv_testcase_util` where appropriate.
+ 4. Use the `record_test_result*` methods in `tv_testcase_util` where
+    appropriate.
 
- 4. Results must be added to the build results database schema. See
+ 5. Results must be added to the build results database schema. See
     the internal "README-Updating-Result-Schema.md" file
diff --git a/src/cobalt/webdriver_benchmarks/tests/all.py b/src/cobalt/webdriver_benchmarks/tests/all.py
index 78924c0..3cd8266 100755
--- a/src/cobalt/webdriver_benchmarks/tests/all.py
+++ b/src/cobalt/webdriver_benchmarks/tests/all.py
@@ -17,22 +17,29 @@
 # pylint: disable=C6204,C6203
 import tv_testcase
 
+def _add_test(test_suite, dir_path, test_name):
+  if os.path.isfile(os.path.join(dir_path, test_name + ".py")):
+    print("Adding test: {}".format(test_name))
+    test_suite.addTest(unittest.TestLoader().loadTestsFromModule(
+        importlib.import_module("tests." + test_name)))
 
 # pylint: disable=unused-argument
 def load_tests(loader, tests, pattern):
   """This is a Python unittest "load_tests protocol method."""
-  s = unittest.TestSuite()
+  test_suite = unittest.TestSuite()
+  dir_path = os.path.dirname(__file__)
 
-  for f in os.listdir(os.path.dirname(__file__)):
-    if not f.endswith(".py"):
-      continue
-    if f.startswith("_"):
-      continue
-    if f == "all.py":
-      continue
-    s.addTest(unittest.TestLoader().loadTestsFromModule(
-        importlib.import_module("tests." + f[:-3])))
-  return s
+  # "time_to_shelf" must be the first test added. The timings that it
+  # records require it to run first.
+  _add_test(test_suite, dir_path, "time_to_shelf")
+  _add_test(test_suite, dir_path, "browse_horizontal")
+  _add_test(test_suite, dir_path, "browse_vertical")
+  _add_test(test_suite, dir_path, "browse_to_guide")
+  _add_test(test_suite, dir_path, "browse_to_search")
+  _add_test(test_suite, dir_path, "browse_to_watch")
+  _add_test(test_suite, dir_path, "csi")
+
+  return test_suite
 
 if __name__ == "__main__":
   tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py b/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py
index 5751cd2..d55cb5a 100755
--- a/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py
+++ b/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py
@@ -36,8 +36,6 @@
 
     for _ in xrange(NUM_LOAD_TV_CALLS):
       self.load_tv()
-      self.wait_for_processing_complete_after_focused_shelf()
-
       self.send_keys(tv.FOCUSED_TILE, keys.Keys.ARROW_RIGHT)
       self.wait_for_processing_complete_after_focused_shelf()
 
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py b/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py
index 750addd..20e13e5 100755
--- a/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py
+++ b/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py
@@ -45,7 +45,6 @@
 
     for _ in xrange(NUM_LOAD_TV_CALLS):
       self.load_tv()
-      self.assert_displayed(tv.FOCUSED_SHELF)
 
       for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
         browse_to_guide_recorder.on_start_event()
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py b/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py
index 8b0e0a8..3c4728e 100755
--- a/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py
+++ b/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py
@@ -47,7 +47,6 @@
 
     for _ in xrange(NUM_LOAD_TV_CALLS):
       self.load_tv()
-      self.assert_displayed(tv.FOCUSED_SHELF)
 
       for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
         browse_to_search_recorder.on_start_event()
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py b/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py
index 3733dd8..956d44b 100755
--- a/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py
+++ b/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py
@@ -48,7 +48,6 @@
 
     for _ in xrange(NUM_LOAD_TV_CALLS):
       self.load_tv()
-      self.wait_for_processing_complete_after_focused_shelf()
 
       for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL):
         self.send_keys(tv.FOCUSED_SHELF, keys.Keys.ARROW_DOWN)
@@ -59,6 +58,10 @@
         self.wait_for_media_element_playing()
         browse_to_watch_recorder.on_end_event()
 
+        # Wait for the title card hidden before sending the escape. Otherwise,
+        # two escapes are required to exit the video.
+        self.wait_for_title_card_hidden()
+
         watch_to_browse_recorder.on_start_event()
         self.send_keys(tv.FOCUSED_WATCH, keys.Keys.ESCAPE)
         self.wait_for_processing_complete_after_focused_shelf()
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py b/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py
index ac44823..76a3ff8 100755
--- a/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py
+++ b/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py
@@ -36,8 +36,6 @@
 
     for _ in xrange(NUM_LOAD_TV_CALLS):
       self.load_tv()
-      self.wait_for_processing_complete_after_focused_shelf()
-
       self.send_keys(tv.FOCUSED_SHELF, keys.Keys.ARROW_DOWN)
       self.wait_for_processing_complete_after_focused_shelf()
 
diff --git a/src/cobalt/webdriver_benchmarks/tests/time_to_shelf.py b/src/cobalt/webdriver_benchmarks/tests/time_to_shelf.py
index 9551d9d..4a1c6fa 100755
--- a/src/cobalt/webdriver_benchmarks/tests/time_to_shelf.py
+++ b/src/cobalt/webdriver_benchmarks/tests/time_to_shelf.py
@@ -19,7 +19,6 @@
 from __future__ import division
 from __future__ import print_function
 
-import datetime
 import os
 import sys
 
@@ -27,39 +26,43 @@
 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
 
 # pylint: disable=C6204,C6203
+import timer
 import tv_testcase
 import tv_testcase_util
 
 
 class TimeToShelf(tv_testcase.TvTestCase):
 
+  def setUp(self):
+    # Override TvTestCase's setUp() so that blank startup can first be measured.
+    pass
+
   def test_simple(self):
     """This test tries to measure the startup time for the YouTube TV page.
 
     Specifically, this test uses the Cobalt CVal Cobalt.Lifetime, which gets
     updated ~60Hz on a best effort basis and is in microseconds, to determine
-    "timeToShelfBlankStartupTimeUs" and uses Python's datetime module to
-    determine "timeToShelfTestTimeShelfDisplayMedianUs".
-
-    Note: t0 is defined after Cobalt starts up, but has not navigated to a page.
-    If that true startup time metric is desired, perhaps a separate should be
-    used.
+    "timeToShelfBlankStartupTimeUs" and uses Timer to determine
+    "timeToShelfTestTimeShelfDisplayMedianUs".
     """
-    metrics_array = []
+
     blank_startup_time_microseconds = self.get_cval('Cobalt.Lifetime')
+
+    # Call TvTestCase's setUp() now that the blank startup time has been
+    # measured.
+    super(TimeToShelf, self).setUp()
+
+    metrics_array = []
     for _ in range(10):
-      t0 = datetime.datetime.now()
-      self.load_tv()
-      self.wait_for_processing_complete_after_focused_shelf()
-      t1 = datetime.datetime.now()
-      delta = t1 - t0
-      startup_time_microseconds = delta.seconds * 1000000 + delta.microseconds
+      with timer.Timer('TimeShelfDisplay') as t:
+        self.load_tv()
+      startup_time_microseconds = int(t.seconds_elapsed * 1000000)
       metrics_array.append(startup_time_microseconds)
 
-    tv_testcase_util.record_test_result_median(
-        'timeToShelfTestTimeShelfDisplayMedianUs', metrics_array)
     tv_testcase_util.record_test_result('timeToShelfBlankStartupTimeUs',
                                         blank_startup_time_microseconds)
+    tv_testcase_util.record_test_result_median(
+        'timeToShelfTestTimeShelfDisplayMedianUs', metrics_array)
 
 
 if __name__ == '__main__':
diff --git a/src/cobalt/webdriver_benchmarks/tv.py b/src/cobalt/webdriver_benchmarks/tv.py
index 6bd0a70..5382a8d 100644
--- a/src/cobalt/webdriver_benchmarks/tv.py
+++ b/src/cobalt/webdriver_benchmarks/tv.py
@@ -11,6 +11,7 @@
 FOCUSED_TILE = '.focused.tile'
 FOCUSED_WATCH = '.focused.watch'
 SEARCH_LEGEND = '.search.no-model.legend-item'
+TITLE_CARD_HIDDEN = '.title-card.hidden'
 
 SEARCH = '#search'
 WATCH = '#watch'
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase.py b/src/cobalt/webdriver_benchmarks/tv_testcase.py
index 796c860..b3781b4 100644
--- a/src/cobalt/webdriver_benchmarks/tv_testcase.py
+++ b/src/cobalt/webdriver_benchmarks/tv_testcase.py
@@ -11,21 +11,10 @@
 import time
 import unittest
 
-# pylint: disable=C6204
-try:
-  # This code works for Python 2.
-  import urlparse
-  from urllib import urlencode
-except ImportError:
-  # This code works for Python 3.
-  import urllib.parse as urlparse
-  from urllib.parse import urlencode
-
 # This directory is a package
 sys.path.insert(0, os.path.abspath("."))
 # pylint: disable=C6204,C6203
 import c_val_names
-import container_util
 import tv
 import tv_testcase_runner
 import tv_testcase_util
@@ -38,18 +27,18 @@
 ElementNotVisibleException = tv_testcase_util.import_selenium_module(
     submodule="common.exceptions").ElementNotVisibleException
 
-BASE_URL = "https://www.youtube.com/"
-TV_APP_PATH = "/tv"
-BASE_PARAMS = {"env_forcedOffAllExperiments": True}
+WINDOWDRIVER_CREATED_TIMEOUT_SECONDS = 30
 PAGE_LOAD_WAIT_SECONDS = 30
 PROCESSING_TIMEOUT_SECONDS = 15
 MEDIA_TIMEOUT_SECONDS = 30
-# Today, Cobalt's WebDriver has a race that
-# can leave the former page's DOM visible after a navigate.
-# As a workaround, sleep for a bit
-# b/33275371
+TITLE_CARD_HIDDEN_TIMEOUT_SECONDS = 30
+# Currently, after loading a new URL with cookies enabled, Kabuki randomizes
+# the shelf entries when the page finishes loading. Sleep for a bit to allow
+# this to occur before starting any additional logic.
 COBALT_POST_NAVIGATE_SLEEP_SECONDS = 5
 
+_is_initialized = False
+
 
 class TvTestCase(unittest.TestCase):
   """Base class for WebDriver tests.
@@ -58,12 +47,18 @@
   with an internal class with the same name.
   """
 
+  class WindowDriverCreatedTimeoutException(BaseException):
+    """Exception thrown when WindowDriver was not created in time."""
+
   class ProcessingTimeoutException(BaseException):
     """Exception thrown when processing did not complete in time."""
 
   class MediaTimeoutException(BaseException):
     """Exception thrown when media did not complete in time."""
 
+  class TitleCardHiddenTimeoutException(BaseException):
+    """Exception thrown when title card did not disappear in time."""
+
   @classmethod
   def setUpClass(cls):
     print("Running " + cls.__name__)
@@ -72,9 +67,23 @@
   def tearDownClass(cls):
     print("Done " + cls.__name__)
 
+  def setUp(self):
+    global _is_initialized
+    if not _is_initialized:
+      # Initialize the tests. This involves loading a URL which applies the
+      # forcedOffAllExperiments cookies, ensuring that no subsequent loads
+      # include experiments. Additionally, loading this URL triggers a reload.
+      query_params = {"env_forcedOffAllExperiments": True}
+      triggers_reload = True
+      self.load_tv(None, query_params, triggers_reload)
+      _is_initialized = True
+
   def get_webdriver(self):
     return tv_testcase_runner.GetWebDriver()
 
+  def get_windowdriver_created(self):
+    return tv_testcase_runner.GetWindowDriverCreated()
+
   def get_cval(self, cval_name):
     """Returns the Python object represented by a JSON cval string.
 
@@ -90,32 +99,14 @@
     else:
       return json.loads(json_result)
 
-  def goto(self, path, query_params=None):
-    """Goes to a path off of BASE_URL.
-
-    Args:
-      path: URL path without the hostname.
-      query_params: Dictionary of parameter names and values.
-    Raises:
-      Underlying WebDriver exceptions
-    """
-    parsed_url = list(urlparse.urlparse(BASE_URL))
-    parsed_url[2] = path
-    query_dict = BASE_PARAMS.copy()
-    if query_params:
-      query_dict.update(urlparse.parse_qsl(parsed_url[4]))
-      container_util.merge_dict(query_dict, query_params)
-    parsed_url[4] = urlencode(query_dict, doseq=True)
-    final_url = urlparse.urlunparse(parsed_url)
-    self.get_webdriver().get(final_url)
-    time.sleep(COBALT_POST_NAVIGATE_SLEEP_SECONDS)
-
-  def load_tv(self, label=None, additional_query_params=None):
+  def load_tv(self, label=None, additional_query_params=None,
+              triggers_reload=False):
     """Loads the main TV page and waits for it to display.
 
     Args:
       label: A value for the label query parameter.
       additional_query_params: A dict containing additional query parameters.
+      triggers_reload: Whether or not the navigation will trigger a reload.
     Raises:
       Underlying WebDriver exceptions
     """
@@ -124,13 +115,19 @@
       query_params = {"label": label}
     if additional_query_params is not None:
       query_params.update(additional_query_params)
-    self.goto(TV_APP_PATH, query_params)
+    self.get_windowdriver_created().clear()
+    self.get_webdriver().get(tv_testcase_util.get_tv_url(query_params))
+    self.wait_for_windowdriver_created()
+    if triggers_reload:
+      self.get_windowdriver_created().clear()
+      self.wait_for_windowdriver_created()
+    time.sleep(COBALT_POST_NAVIGATE_SLEEP_SECONDS)
     # Note that the internal tests use "expect_transition" which is
     # a mechanism that sets a maximum timeout for a "@with_retries"
     # decorator-driven success retry loop for subsequent webdriver requests.
     #
     # We'll skip that sophistication here.
-    self.poll_until_found(tv.FOCUSED_SHELF)
+    self.wait_for_processing_complete_after_focused_shelf()
 
   def poll_until_found(self, css_selector):
     """Polls until an element is found.
@@ -217,6 +214,12 @@
           raise
         time.sleep(1)
 
+  def wait_for_windowdriver_created(self):
+    """Waits for Cobalt to create a WindowDriver."""
+    windowdriver_created = self.get_windowdriver_created()
+    if not windowdriver_created.wait(WINDOWDRIVER_CREATED_TIMEOUT_SECONDS):
+      raise TvTestCase.WindowDriverCreatedTimeoutException()
+
   def wait_for_processing_complete_after_focused_shelf(self):
     """Waits for Cobalt to focus on a shelf and complete pending layouts."""
     self.poll_until_found(tv.FOCUSED_SHELF)
@@ -272,9 +275,21 @@
         c_val_names.event_duration_dom_video_start_delay()) == 0:
       if time.time() - start_time > MEDIA_TIMEOUT_SECONDS:
         raise TvTestCase.MediaTimeoutException()
-
       time.sleep(0.1)
 
+  def wait_for_title_card_hidden(self):
+    """Waits for the title to disappear while a video is playing.
+
+    Raises:
+      TitleCardHiddenTimeoutException: The title card did not become hidden in
+      the required time.
+    """
+    start_time = time.time()
+    while not self.find_elements(tv.TITLE_CARD_HIDDEN):
+      if time.time() - start_time > TITLE_CARD_HIDDEN_TIMEOUT_SECONDS:
+        raise TvTestCase.TitleCardHiddenTimeoutException()
+      time.sleep(1)
+
 
 def main():
   logging.basicConfig(level=logging.DEBUG)
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py b/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
index 50acc3c..d8aec07 100644
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
+++ b/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
@@ -59,9 +59,7 @@
     self.event_type = options.event_type
     self.skip_font_file_load_events = options.skip_font_file_load_events
 
-    if self.skip_font_file_load_events:
-      self.font_files_loaded_count = self.test.get_cval(
-          c_val_names.count_font_files_loaded())
+    self.font_files_loaded_count = None
 
     self.render_tree_failure_count = 0
     self.font_file_load_skip_count = 0
@@ -78,8 +76,10 @@
     self._add_value_dictionary_recorder("CntDomHtmlElements")
     self._add_value_dictionary_recorder("CntDomHtmlElementsCreated")
     self._add_value_dictionary_recorder("CntDomHtmlElementsDestroyed")
-    self._add_value_dictionary_recorder("CntDomUpdateMatchingRuleCalls")
-    self._add_value_dictionary_recorder("CntDomUpdateComputedStyleCalls")
+    self._add_value_dictionary_recorder("CntDomUpdateMatchingRules")
+    self._add_value_dictionary_recorder("CntDomUpdateComputedStyle")
+    self._add_value_dictionary_recorder("CntDomGenerateHtmlComputedStyle")
+    self._add_value_dictionary_recorder("CntDomGeneratePseudoComputedStyle")
     self._add_value_dictionary_recorder("CntLayoutBoxes")
     self._add_value_dictionary_recorder("CntLayoutBoxesCreated")
     self._add_value_dictionary_recorder("CntLayoutBoxesDestroyed")
@@ -109,12 +109,17 @@
 
   def on_start_event(self):
     """Handles logic related to the start of the event instance."""
-    pass
+
+    # If the recorder is set to skip events with font file loads and the font
+    # file loaded count hasn't been initialized yet, then do that now.
+    if self.skip_font_file_load_events and self.font_files_loaded_count is None:
+      self.font_files_loaded_count = self.test.get_cval(
+          c_val_names.count_font_files_loaded())
 
   def on_end_event(self):
     """Handles logic related to the end of the event instance."""
 
-    # If the event is set to skip events with font file loads and a font file
+    # If the recorder is set to skip events with font file loads and a font file
     # loaded during the event, then its data is not collected. Log that it was
     # skipped and return.
     if self.skip_font_file_load_events:
@@ -133,7 +138,7 @@
 
     # If the event failed to produce a render tree, then its data is not
     # collected. Log the failure and return.
-    if not value_dictionary.get("ProducedRenderTree"):
+    if not value_dictionary or not value_dictionary.get("ProducedRenderTree"):
       self.render_tree_failure_count += 1
       print("{} event failed to produce render tree! {} events failed.".format(
           self.event_name, self.render_tree_failure_count))
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py b/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
index ab69ff6..d543c4a 100755
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
+++ b/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
@@ -47,6 +47,8 @@
 # Pattern to match Cobalt log line for when the WebDriver port has been
 # opened.
 RE_WEBDRIVER_LISTEN = re.compile(r"Starting WebDriver server on port (\d+)")
+# Pattern to match Cobalt log line for when a WindowDriver has been created.
+RE_WINDOWDRIVER_CREATED = re.compile(r"Created WindowDriver: ID=\S+")
 
 STARTUP_TIMEOUT_SECONDS = 2 * 60
 
@@ -61,6 +63,7 @@
 }
 
 _webdriver = None
+_windowdriver_created = threading.Event()
 
 
 def GetWebDriver():
@@ -68,6 +71,11 @@
   return _webdriver
 
 
+def GetWindowDriverCreated():
+  """Returns the WindowDriver created instance."""
+  return _windowdriver_created
+
+
 class TimeoutException(Exception):
   pass
 
@@ -96,7 +104,13 @@
     self.launcher = app_launcher.CreateLauncher(
         platform, executable, devkit_name=devkit_name, close_output_file=False)
 
-    self.launcher.SetArgs(["--enable_webdriver"])
+    args = []
+    args.append("--enable_webdriver")
+    args.append("--null_savegame")
+    args.append("--debug_console=off")
+    args.append("--url=about:blank")
+
+    self.launcher.SetArgs(args)
     self.launcher.SetOutputCallback(self._HandleLine)
     self.log_file_path = log_file_path
     self.log_file = None
@@ -123,6 +137,11 @@
   def _HandleLine(self, line):
     """Internal log line callback."""
 
+    # Check for a WindowDriver being created.
+    if RE_WINDOWDRIVER_CREATED.search(line):
+      _windowdriver_created.set()
+      return
+
     # Wait for WebDriver port here then connect
     if self.test_script_started.is_set():
       return
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py b/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
index 51840c3..4542e90 100644
--- a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
+++ b/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
@@ -8,6 +8,10 @@
 import json
 import sys
 
+# pylint: disable=C6204
+import urlparse
+from urllib import urlencode
+
 import container_util
 
 # These are watched for in webdriver_benchmark_test.py
@@ -18,6 +22,11 @@
 EVENT_TYPE_KEY_DOWN = "KeyDown"
 EVENT_TYPE_KEY_UP = "KeyUp"
 
+# URL-related constants
+BASE_URL = "https://www.youtube.com/"
+TV_APP_PATH = "/tv"
+BASE_PARAMS = {}
+
 
 def import_selenium_module(submodule=None):
   """Dynamically imports a selenium.webdriver submodule.
@@ -52,6 +61,23 @@
   return module
 
 
+def get_url(path, query_params=None):
+  """Returns the URL indicated by the path and query parameters."""
+  parsed_url = list(urlparse.urlparse(BASE_URL))
+  parsed_url[2] = path
+  query_dict = BASE_PARAMS.copy()
+  if query_params:
+    query_dict.update(urlparse.parse_qsl(parsed_url[4]))
+    container_util.merge_dict(query_dict, query_params)
+  parsed_url[4] = urlencode(query_dict, doseq=True)
+  return urlparse.urlunparse(parsed_url)
+
+
+def get_tv_url(query_params=None):
+  """Returns the tv URL indicated by the query parameters."""
+  return get_url(TV_APP_PATH, query_params)
+
+
 def record_test_result(name, result):
   """Records an individual scalar result of a benchmark test.
 
diff --git a/src/media/filters/chunk_demuxer.cc b/src/media/filters/chunk_demuxer.cc
index 76cc2c8..64760b8 100644
--- a/src/media/filters/chunk_demuxer.cc
+++ b/src/media/filters/chunk_demuxer.cc
@@ -73,7 +73,7 @@
 #if defined(OS_STARBOARD)
 #if SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
 
-static const CodecInfo kVP9CodecInfo = { "vp9", DemuxerStream::VIDEO };
+static const CodecInfo kVP9CodecInfo = {"vp9*", DemuxerStream::VIDEO};
 
 static const CodecInfo* kVideoWebMCodecs[] = {
   &kVP9CodecInfo,
diff --git a/src/nb/string_interner.cc b/src/nb/string_interner.cc
index 482ea95..b4da03a 100644
--- a/src/nb/string_interner.cc
+++ b/src/nb/string_interner.cc
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include "nb/hash.h"
 #include "nb/string_interner.h"
+#include "starboard/client_porting/poem/string_poem.h"
+#include "starboard/string.h"
 
 namespace nb {
 
@@ -69,4 +72,64 @@
   return out;
 }
 
-}  // namespace nb
+ConcurrentStringInterner::ConcurrentStringInterner(size_t table_size) {
+  Construct(table_size);
+}
+
+void ConcurrentStringInterner::Construct(size_t table_size) {
+  if (table_size == 0) {
+    table_size = 1;
+  }
+  string_interner_table_.reserve(table_size);
+  for (size_t i = 0; i < table_size; ++i) {
+    string_interner_table_.push_back(new StringInterner);
+  }
+}
+
+ConcurrentStringInterner::~ConcurrentStringInterner() {
+  for (size_t i = 0; i < string_interner_table_.size(); ++i) {
+    delete string_interner_table_[i];
+  }
+}
+
+const std::string& ConcurrentStringInterner::Intern(const std::string& str) {
+  return GetBucket(str.c_str(), str.size()).Intern(str);
+}
+
+const std::string& ConcurrentStringInterner::Intern(const char* c_string) {
+  return GetBucket(c_string, SbStringGetLength(c_string)).Intern(c_string);
+}
+
+const std::string* ConcurrentStringInterner::Get(const std::string& str) const {
+  return GetBucket(str.c_str(), str.size()).Get(str);
+}
+
+const std::string* ConcurrentStringInterner::Get(const char* c_string) const {
+  return GetBucket(c_string, SbStringGetLength(c_string)).Get(c_string);
+}
+
+size_t ConcurrentStringInterner::Size() const {
+  size_t sum = 0;
+  for (size_t i = 0; i < string_interner_table_.size(); ++i) {
+    sum += string_interner_table_[i]->Size();
+  }
+  return sum;
+}
+
+nb::StringInterner&
+ConcurrentStringInterner::GetBucket(const char* string, size_t n) {
+  uint32_t hash_value = nb::RuntimeHash32(string, n);
+  size_t index =
+    static_cast<size_t>(hash_value % string_interner_table_.size());
+  return *string_interner_table_[index];
+}
+
+const nb::StringInterner&
+ConcurrentStringInterner::GetBucket(const char* string, size_t n) const {
+  uint32_t hash_value = nb::RuntimeHash32(string, n);
+  size_t index =
+    static_cast<size_t>(hash_value % string_interner_table_.size());
+  return *string_interner_table_[index];
+}
+
+ }  // namespace nb
diff --git a/src/nb/string_interner.h b/src/nb/string_interner.h
index 2ae07ba..87840bf 100644
--- a/src/nb/string_interner.h
+++ b/src/nb/string_interner.h
@@ -19,6 +19,7 @@
 
 #include <set>
 #include <string>
+#include <vector>
 
 #include "starboard/configuration.h"
 #include "starboard/mutex.h"
@@ -67,6 +68,31 @@
   SB_DISALLOW_COPY_AND_ASSIGN(StringInterner);
 };
 
+class ConcurrentStringInterner {
+ public:
+  explicit ConcurrentStringInterner(size_t table_size = 32);
+  ~ConcurrentStringInterner();  // All outstanding const std::string* are invalidated.
+
+  // Returns an equivalent string to the input. If the input is missing from
+  // the data store then a copy-by-value is made.
+  const std::string& Intern(const std::string& str);
+  const std::string& Intern(const char* c_string);
+
+  // Returns the string object if it exists, otherwise NULL.
+  const std::string* Get(const std::string& str) const;
+  const std::string* Get(const char* c_string) const;
+
+  size_t Size() const;
+
+ private:
+  void Construct(size_t table_size);
+  StringInterner& GetBucket(const char* string, size_t n);
+  const StringInterner& GetBucket(const char* string, size_t n) const;
+  std::vector<StringInterner*> string_interner_table_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(ConcurrentStringInterner);
+};
+
 }  // namespace nb
 
 #endif  // NB_STRING_INTERNER_H_
diff --git a/src/nb/string_interner_test.cc b/src/nb/string_interner_test.cc
index dc4df8c..cb296a8 100644
--- a/src/nb/string_interner_test.cc
+++ b/src/nb/string_interner_test.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cstring>
 #include <string>
 
 #include "nb/string_interner.h"
@@ -22,8 +23,31 @@
 namespace nb {
 namespace {
 
-TEST(StringInterner, Intern) {
-  StringInterner string_interner;
+typedef ::testing::Types<StringInterner, ConcurrentStringInterner>
+    StringInternerTypes;
+
+// Defines test type that will be instantiated using each type in
+// AllAtomicTypes type list.
+template <typename T>
+class StringInternerTest : public ::testing::Test {};
+TYPED_TEST_CASE(StringInternerTest, StringInternerTypes);  // Registration.
+
+std::string GenerateRandomString(size_t size) {
+  static const char valid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                    "abcdefghijklmnopqrstuvwxyz";
+  static const size_t n = strlen(valid_chars);
+
+  std::stringstream ss;
+  for (size_t i = 0; i < size; ++i) {
+    size_t random_char_index = std::rand() % n;
+    ss << valid_chars[random_char_index];
+  }
+  return ss.str();
+}
+
+TYPED_TEST(StringInternerTest, Intern) {
+  typedef TypeParam StringInternerT;
+  StringInternerT string_interner;
   EXPECT_FALSE(string_interner.Get("A"));
   EXPECT_EQ(&string_interner.Intern("A"), &string_interner.Intern("A"));
   EXPECT_TRUE(string_interner.Get("A"));
@@ -32,8 +56,9 @@
   EXPECT_EQ(2, string_interner.Size());
 }
 
-TEST(StringInterner, InternStdString) {
-  StringInterner string_interner;
+TYPED_TEST(StringInternerTest, InternStdString) {
+  typedef TypeParam StringInternerT;
+  StringInternerT string_interner;
   std::string a = "A";
   std::string a_copy = "A";
   std::string b = "B";
@@ -46,5 +71,47 @@
   EXPECT_EQ(2, string_interner.Size());
 }
 
+TYPED_TEST(StringInternerTest, InternBothStrings) {
+  typedef TypeParam StringInternerT;
+  StringInternerT string_interner;
+
+  std::string a_stdstring = "A";
+  const char* c_string = "A";
+
+  const std::string* a_pointer = &string_interner.Intern("A");
+  EXPECT_EQ(a_pointer, &string_interner.Intern(c_string));
+  EXPECT_EQ(a_pointer, &string_interner.Intern(a_stdstring));
+}
+
+// Tests the expectation that a set of unique strings can all be inserted
+// into the (Concurrent)StringInterner.
+TYPED_TEST(StringInternerTest, LoadLotsOfUniqueStrings) {
+  typedef TypeParam StringInternerT;
+  StringInternerT string_interner;
+
+  static const size_t kNumStringsToLoad = 1000;
+
+  std::set<std::string> all_unique_strings;
+
+  // Keep generating random strings until we have a full set of unique strings.
+  while (all_unique_strings.size() < kNumStringsToLoad) {
+    all_unique_strings.insert(GenerateRandomString(25));
+  }
+
+  for (std::set<std::string>::const_iterator it = all_unique_strings.begin();
+       it != all_unique_strings.end(); ++it) {
+    const std::string& str = *it;
+    ASSERT_FALSE(string_interner.Get(str));
+    ASSERT_FALSE(string_interner.Get(str.c_str()));  // c-string version.
+
+    string_interner.Intern(str);
+
+    ASSERT_TRUE(string_interner.Get(str));
+    ASSERT_TRUE(string_interner.Get(str.c_str()));  // c-string version.
+  }
+
+  ASSERT_EQ(string_interner.Size(), all_unique_strings.size());
+}
+
 }  // namespace
 }  // namespace nb
diff --git a/src/net/http/http_util.cc b/src/net/http/http_util.cc
index 033b00d..c406586 100644
--- a/src/net/http/http_util.cc
+++ b/src/net/http/http_util.cc
@@ -426,6 +426,13 @@
   return c == '"' || c == '\'';
 }
 
+bool HttpUtil::IsTokenChar(char c) {
+  return !(c >= 0x7F || c <= 0x20 || c == '(' || c == ')' || c == '<' ||
+           c == '>' || c == '@' || c == ',' || c == ';' || c == ':' ||
+           c == '\\' || c == '"' || c == '/' || c == '[' || c == ']' ||
+           c == '?' || c == '=' || c == '{' || c == '}');
+}
+
 // See RFC 2616 Sec 2.2 for the definition of |token|.
 bool HttpUtil::IsToken(string::const_iterator begin,
                        string::const_iterator end) {
diff --git a/src/net/http/http_util.h b/src/net/http/http_util.h
index 7560b92..1846664 100644
--- a/src/net/http/http_util.h
+++ b/src/net/http/http_util.h
@@ -104,6 +104,8 @@
   // Whether the character is the start of a quotation mark.
   static bool IsQuote(char c);
 
+  // Whether the character is a valid |tchar| as defined in RFC 7230 Sec 3.2.6.
+  static bool IsTokenChar(char c);
   // Whether the string is a valid |token| as defined in RFC 2616 Sec 2.2.
   static bool IsToken(std::string::const_iterator begin,
                       std::string::const_iterator end);
diff --git a/src/net/net.gyp b/src/net/net.gyp
index 36d3e12..4a0a740 100644
--- a/src/net/net.gyp
+++ b/src/net/net.gyp
@@ -10,7 +10,7 @@
     # this flag is set, we hackily avoid using mmap() in the disk cache.
     'posix_avoid_mmap%': 0,
 
-    'enable_websockets%' : 0,
+    'enable_websockets%' : 1,
     'use_native_http_stack%': 0,
   },
   'targets': [
@@ -676,10 +676,18 @@
         'url_request/url_request_throttler_manager.h',
         'url_request/view_cache_helper.cc',
         'url_request/view_cache_helper.h',
+        'websockets/websocket_extension.cc',
+        'websockets/websocket_extension.h',
+        'websockets/websocket_extension_parser.cc',
+        'websockets/websocket_extension_parser.h',
         'websockets/websocket_frame.cc',
         'websockets/websocket_frame.h',
         'websockets/websocket_frame_parser.cc',
         'websockets/websocket_frame_parser.h',
+        'websockets/websocket_handshake_challenge.cc',
+        'websockets/websocket_handshake_challenge.h',
+        'websockets/websocket_handshake_constants.cc',
+        'websockets/websocket_handshake_constants.h',
         'websockets/websocket_handshake_handler.cc',
         'websockets/websocket_handshake_handler.h',
         'websockets/websocket_job.cc',
@@ -1037,6 +1045,7 @@
         'url_request/view_cache_helper_unittest.cc',
         'websockets/websocket_frame_parser_unittest.cc',
         'websockets/websocket_frame_unittest.cc',
+        'websockets/websocket_handshake_challenge_test.cc',
         'websockets/websocket_handshake_handler_unittest.cc',
         'websockets/websocket_handshake_handler_spdy2_unittest.cc',
         'websockets/websocket_handshake_handler_spdy3_unittest.cc',
diff --git a/src/net/socket_stream/socket_stream.cc b/src/net/socket_stream/socket_stream.cc
index 73d5a2b..95f56a7 100644
--- a/src/net/socket_stream/socket_stream.cc
+++ b/src/net/socket_stream/socket_stream.cc
@@ -40,6 +40,7 @@
 #include "net/socket/tcp_client_socket.h"
 #include "net/socket_stream/socket_stream_metrics.h"
 #include "net/url_request/url_request.h"
+#include "starboard/memory.h"
 
 static const int kMaxPendingSendAllowed = 32768;  // 32 kilobytes.
 static const int kReadBufferSize = 4096;
@@ -79,7 +80,8 @@
 SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
 
 void SocketStream::ResponseHeaders::Realloc(size_t new_size) {
-  headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
+  headers_.reset(
+      static_cast<char*>(SbMemoryReallocate(headers_.release(), new_size)));
 }
 
 SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
diff --git a/src/net/socket_stream/socket_stream.h b/src/net/socket_stream/socket_stream.h
index a86aee8..3fa1f13 100644
--- a/src/net/socket_stream/socket_stream.h
+++ b/src/net/socket_stream/socket_stream.h
@@ -93,7 +93,10 @@
     // Called when an error occured.
     // This is only for error reporting to the delegate.
     // |error| is net::Error.
-    virtual void OnError(const SocketStream* socket, int error) {}
+    virtual void OnError(const SocketStream* socket, int error) {
+      UNREFERENCED_PARAMETER(socket);
+      UNREFERENCED_PARAMETER(error);
+    }
 
     // Called when reading cookies to allow the delegate to block access to the
     // cookie.
diff --git a/src/net/spdy/spdy_session.h b/src/net/spdy/spdy_session.h
index abb5e92..6c18212 100644
--- a/src/net/spdy/spdy_session.h
+++ b/src/net/spdy/spdy_session.h
@@ -292,6 +292,10 @@
   }
 
   void set_spdy_session_pool(SpdySessionPool* pool) {
+    // Not sure why pool is not referenced, so I added UNREFERENCED_PARAMETER
+    // here.  It is likely a bug, but not worth investigating as Cobalt does
+    // not support SPDY, and it is unlikely if it ever will.
+    UNREFERENCED_PARAMETER(pool);
     spdy_session_pool_ = NULL;
   }
 
diff --git a/src/net/websockets/websocket_extension.cc b/src/net/websockets/websocket_extension.cc
new file mode 100644
index 0000000..6e558ad
--- /dev/null
+++ b/src/net/websockets/websocket_extension.cc
@@ -0,0 +1,82 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_extension.h"
+
+#include <map>
+#include <string>
+
+#include "base/logging.h"
+#include "net/http/http_util.h"
+
+namespace net {
+
+WebSocketExtension::Parameter::Parameter(const std::string& name)
+    : name_(name) {}
+
+WebSocketExtension::Parameter::Parameter(const std::string& name,
+                                         const std::string& value)
+    : name_(name), value_(value) {
+  DCHECK(!value.empty());
+  // |extension-param| must be a token.
+  DCHECK(HttpUtil::IsToken(value));
+}
+
+bool WebSocketExtension::Parameter::Equals(const Parameter& other) const {
+  return name_ == other.name_ && value_ == other.value_;
+}
+
+WebSocketExtension::WebSocketExtension() {}
+
+WebSocketExtension::WebSocketExtension(const std::string& name) : name_(name) {}
+
+WebSocketExtension::WebSocketExtension(const WebSocketExtension& other) {
+  name_ = other.name_;
+  parameters_ = other.parameters_;
+}
+
+WebSocketExtension::~WebSocketExtension() {}
+
+bool WebSocketExtension::Equals(const WebSocketExtension& other) const {
+  if (name_ != other.name_)
+    return false;
+  if (parameters_.size() != other.parameters_.size())
+    return false;
+
+  std::multimap<std::string, std::string> this_parameters, other_parameters;
+  for (std::vector<Parameter>::const_iterator iterator = parameters_.begin();
+       iterator != parameters_.end(); ++iterator) {
+    const Parameter& p(*iterator);
+    this_parameters.insert(std::make_pair(p.name(), p.value()));
+  }
+  for (std::vector<Parameter>::const_iterator iterator =
+           other.parameters_.begin();
+       iterator != other.parameters_.end(); ++iterator) {
+    const Parameter& p(*iterator);
+    other_parameters.insert(std::make_pair(p.name(), p.value()));
+  }
+  return this_parameters == other_parameters;
+}
+
+std::string WebSocketExtension::ToString() const {
+  if (name_.empty())
+    return std::string();
+
+  std::string result = name_;
+
+  for (std::vector<Parameter>::const_iterator iterator = parameters_.begin();
+       iterator != parameters_.end(); ++iterator) {
+    const Parameter& param(*iterator);
+    result += "; " + param.name();
+    if (!param.HasValue())
+      continue;
+
+    // |extension-param| must be a token and we don't need to quote it.
+    DCHECK(HttpUtil::IsToken(param.value()));
+    result += "=" + param.value();
+  }
+  return result;
+}
+
+}  // namespace net
diff --git a/src/net/websockets/websocket_extension.h b/src/net/websockets/websocket_extension.h
new file mode 100644
index 0000000..4c42a76
--- /dev/null
+++ b/src/net/websockets/websocket_extension.h
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_EXTENSION_H_
+#define NET_WEBSOCKETS_WEBSOCKET_EXTENSION_H_
+
+#include <string>
+#include <vector>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// A WebSocketExtension instance represents a WebSocket extension specified
+// in RFC6455.
+class NET_EXPORT_PRIVATE WebSocketExtension {
+ public:
+  // Note that RFC6455 does not allow a parameter with an empty value.
+  class NET_EXPORT_PRIVATE Parameter {
+   public:
+    // Construct a parameter which does not have a value.
+    explicit Parameter(const std::string& name);
+    // Construct a parameter with a non-empty value.
+    Parameter(const std::string& name, const std::string& value);
+
+    bool HasValue() const { return !value_.empty(); }
+    const std::string& name() const { return name_; }
+    const std::string& value() const { return value_; }
+    bool Equals(const Parameter& other) const;
+
+    // The default copy constructor and the assignment operator are defined:
+    // we need them.
+   private:
+    std::string name_;
+    std::string value_;
+  };
+
+  WebSocketExtension();
+  explicit WebSocketExtension(const std::string& name);
+  WebSocketExtension(const WebSocketExtension& other);
+  ~WebSocketExtension();
+
+  void Add(const Parameter& parameter) { parameters_.push_back(parameter); }
+  const std::string& name() const { return name_; }
+  const std::vector<Parameter>& parameters() const { return parameters_; }
+  bool Equals(const WebSocketExtension& other) const;
+  std::string ToString() const;
+
+  // The default copy constructor and the assignment operator are defined:
+  // we need them.
+ private:
+  std::string name_;
+  std::vector<Parameter> parameters_;
+};
+
+}  // namespace net
+
+#endif  // NET_WEBSOCKETS_WEBSOCKET_EXTENSION_H_
diff --git a/src/net/websockets/websocket_extension_parser.cc b/src/net/websockets/websocket_extension_parser.cc
new file mode 100644
index 0000000..6e52fbf
--- /dev/null
+++ b/src/net/websockets/websocket_extension_parser.cc
@@ -0,0 +1,149 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_extension_parser.h"
+
+#include "base/logging.h"
+#include "net/http/http_util.h"
+
+namespace net {
+
+WebSocketExtensionParser::WebSocketExtensionParser() {}
+
+WebSocketExtensionParser::~WebSocketExtensionParser() {}
+
+bool WebSocketExtensionParser::Parse(const char* data, size_t size) {
+  current_ = data;
+  end_ = data + size;
+  extensions_.clear();
+
+  bool failed = false;
+
+  do {
+    WebSocketExtension extension;
+    if (!ConsumeExtension(&extension)) {
+      failed = true;
+      break;
+    }
+    extensions_.push_back(extension);
+
+    ConsumeSpaces();
+  } while (ConsumeIfMatch(','));
+
+  if (!failed && current_ == end_)
+    return true;
+
+  extensions_.clear();
+  return false;
+}
+
+bool WebSocketExtensionParser::Consume(char c) {
+  ConsumeSpaces();
+  if (current_ == end_ || c != *current_)
+    return false;
+  ++current_;
+  return true;
+}
+
+bool WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
+  base::StringPiece name;
+  if (!ConsumeToken(&name))
+    return false;
+  *extension = WebSocketExtension(name.as_string());
+
+  while (ConsumeIfMatch(';')) {
+    WebSocketExtension::Parameter parameter((std::string()));
+    if (!ConsumeExtensionParameter(&parameter))
+      return false;
+    extension->Add(parameter);
+  }
+
+  return true;
+}
+
+bool WebSocketExtensionParser::ConsumeExtensionParameter(
+    WebSocketExtension::Parameter* parameter) {
+  base::StringPiece name, value;
+  std::string value_string;
+
+  if (!ConsumeToken(&name))
+    return false;
+
+  if (!ConsumeIfMatch('=')) {
+    *parameter = WebSocketExtension::Parameter(name.as_string());
+    return true;
+  }
+
+  if (Lookahead('\"')) {
+    if (!ConsumeQuotedToken(&value_string))
+      return false;
+  } else {
+    if (!ConsumeToken(&value))
+      return false;
+    value_string = value.as_string();
+  }
+  *parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
+  return true;
+}
+
+bool WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
+  ConsumeSpaces();
+  const char* head = current_;
+  while (current_ < end_ && HttpUtil::IsTokenChar(*current_))
+    ++current_;
+  if (current_ == head)
+    return false;
+  *token = base::StringPiece(head, current_ - head);
+  return true;
+}
+
+bool WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
+  if (!Consume('"'))
+    return false;
+
+  *token = "";
+  while (current_ < end_ && *current_ != '"') {
+    if (*current_ == '\\') {
+      ++current_;
+      if (current_ == end_)
+        return false;
+    }
+    if (!HttpUtil::IsTokenChar(*current_))
+      return false;
+    *token += *current_;
+    ++current_;
+  }
+  if (current_ == end_)
+    return false;
+  DCHECK_EQ(*current_, '"');
+
+  ++current_;
+
+  return !token->empty();
+}
+
+void WebSocketExtensionParser::ConsumeSpaces() {
+  while (current_ < end_ && (*current_ == ' ' || *current_ == '\t'))
+    ++current_;
+  return;
+}
+
+bool WebSocketExtensionParser::Lookahead(char c) {
+  const char* head = current_;
+  bool result = Consume(c);
+  current_ = head;
+  return result;
+}
+
+bool WebSocketExtensionParser::ConsumeIfMatch(char c) {
+  const char* head = current_;
+  if (!Consume(c)) {
+    current_ = head;
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace net
diff --git a/src/net/websockets/websocket_extension_parser.h b/src/net/websockets/websocket_extension_parser.h
new file mode 100644
index 0000000..66fe804
--- /dev/null
+++ b/src/net/websockets/websocket_extension_parser.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_EXTENSION_PARSER_H_
+#define NET_WEBSOCKETS_WEBSOCKET_EXTENSION_PARSER_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/websockets/websocket_extension.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE WebSocketExtensionParser {
+ public:
+  WebSocketExtensionParser();
+  ~WebSocketExtensionParser();
+
+  // Parses the given string as a Sec-WebSocket-Extensions header value.
+  //
+  // There must be no newline characters in the input. LWS-concatenation must
+  // have already been done before calling this method.
+  //
+  // Returns true if the method was successful (no syntax error was found).
+  bool Parse(const char* data, size_t size);
+  bool Parse(const std::string& data) {
+    return Parse(data.data(), data.size());
+  }
+
+  // Returns the result of the last Parse() method call.
+  const std::vector<WebSocketExtension>& extensions() const {
+    return extensions_;
+  }
+
+ private:
+  WARN_UNUSED_RESULT bool Consume(char c);
+  WARN_UNUSED_RESULT bool ConsumeExtension(WebSocketExtension* extension);
+  WARN_UNUSED_RESULT bool ConsumeExtensionParameter(
+      WebSocketExtension::Parameter* parameter);
+  WARN_UNUSED_RESULT bool ConsumeToken(base::StringPiece* token);
+  WARN_UNUSED_RESULT bool ConsumeQuotedToken(std::string* token);
+  void ConsumeSpaces();
+  WARN_UNUSED_RESULT bool Lookahead(char c);
+  WARN_UNUSED_RESULT bool ConsumeIfMatch(char c);
+
+  // The current position in the input string.
+  const char* current_;
+  // The pointer of the end of the input string.
+  const char* end_;
+  std::vector<WebSocketExtension> extensions_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocketExtensionParser);
+};
+
+}  // namespace net
+
+#endif  // NET_WEBSOCKETS_WEBSOCKET_EXTENSION_PARSER_H_
diff --git a/src/net/websockets/websocket_handshake_challenge.cc b/src/net/websockets/websocket_handshake_challenge.cc
new file mode 100644
index 0000000..3a1c3e8
--- /dev/null
+++ b/src/net/websockets/websocket_handshake_challenge.cc
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_challenge.h"
+
+#include "base/base64.h"
+#include "base/sha1.h"
+#include "net/websockets/websocket_handshake_constants.h"
+
+namespace net {
+
+std::string ComputeSecWebSocketAccept(const std::string& key) {
+  std::string accept;
+  std::string hash = base::SHA1HashString(key + websockets::kWebSocketGuid);
+  base::Base64Encode(hash, &accept);
+  return accept;
+}
+
+}  // namespace net
diff --git a/src/net/websockets/websocket_handshake_challenge.h b/src/net/websockets/websocket_handshake_challenge.h
new file mode 100644
index 0000000..e21f2b0
--- /dev/null
+++ b/src/net/websockets/websocket_handshake_challenge.h
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
+#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// Given a WebSocket handshake challenge, compute the value that the server
+// should return in the Sec-WebSocket-Accept header.
+NET_EXPORT_PRIVATE std::string ComputeSecWebSocketAccept(
+    const std::string& key);
+
+}  // namespace net
+
+#endif  // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CHALLENGE_H_
diff --git a/src/net/websockets/websocket_handshake_challenge_test.cc b/src/net/websockets/websocket_handshake_challenge_test.cc
new file mode 100644
index 0000000..d7e45ca
--- /dev/null
+++ b/src/net/websockets/websocket_handshake_challenge_test.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_challenge.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+// Test the example challenge from the RFC6455.
+TEST(WebSocketHandshakeChallengeTest, RFC6455) {
+  const std::string key = "dGhlIHNhbXBsZSBub25jZQ==";
+  std::string accept = ComputeSecWebSocketAccept(key);
+  EXPECT_EQ("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", accept);
+}
+
+}  // namespace
+
+}  // namespace net
diff --git a/src/net/websockets/websocket_handshake_constants.cc b/src/net/websockets/websocket_handshake_constants.cc
new file mode 100644
index 0000000..bb031e2
--- /dev/null
+++ b/src/net/websockets/websocket_handshake_constants.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_constants.h"
+
+namespace net {
+namespace websockets {
+
+const char kHttpProtocolVersion[] = "HTTP/1.1";
+
+const size_t kRawChallengeLength = 16;
+
+const char kSecWebSocketProtocol[] = "Sec-WebSocket-Protocol";
+const char kSecWebSocketExtensions[] = "Sec-WebSocket-Extensions";
+const char kSecWebSocketKey[] = "Sec-WebSocket-Key";
+const char kSecWebSocketAccept[] = "Sec-WebSocket-Accept";
+const char kSecWebSocketVersion[] = "Sec-WebSocket-Version";
+
+const char kSupportedVersion[] = "13";
+
+const char kUpgrade[] = "Upgrade";
+const char kWebSocketGuid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+const char kSecWebSocketProtocolSpdy3[] = ":sec-websocket-protocol";
+const char kSecWebSocketExtensionsSpdy3[] = ":sec-websocket-extensions";
+
+const char* const kSecWebSocketProtocolLowercase =
+    kSecWebSocketProtocolSpdy3 + 1;
+const char* const kSecWebSocketExtensionsLowercase =
+    kSecWebSocketExtensionsSpdy3 + 1;
+const char kSecWebSocketKeyLowercase[] = "sec-websocket-key";
+const char kSecWebSocketVersionLowercase[] = "sec-websocket-version";
+const char kUpgradeLowercase[] = "upgrade";
+const char kWebSocketLowercase[] = "websocket";
+
+}  // namespace websockets
+}  // namespace net
diff --git a/src/net/websockets/websocket_handshake_constants.h b/src/net/websockets/websocket_handshake_constants.h
new file mode 100644
index 0000000..6b17be0
--- /dev/null
+++ b/src/net/websockets/websocket_handshake_constants.h
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A set of common constants that are needed for the WebSocket handshake.
+// In general, you should prefer using these constants to literal strings,
+// except in tests.
+//
+// These constants cannot be used in files that are compiled on iOS, because
+// this file is not compiled on iOS.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CONSTANTS_H_
+#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CONSTANTS_H_
+
+#include <stddef.h>
+
+#include "net/base/net_export.h"
+
+// This file plases constants inside the ::net::websockets namespace to avoid
+// risk of collisions with other symbols in libnet.
+namespace net {
+namespace websockets {
+
+// "HTTP/1.1"
+// RFC6455 only requires HTTP/1.1 "or better" but in practice an HTTP version
+// other than 1.1 should not occur in a WebSocket handshake.
+extern const char kHttpProtocolVersion[];
+
+// The Sec-WebSockey-Key challenge is 16 random bytes, base64 encoded.
+extern const size_t kRawChallengeLength;
+
+// "Sec-WebSocket-Protocol"
+extern const char kSecWebSocketProtocol[];
+
+// "Sec-WebSocket-Extensions"
+extern const char kSecWebSocketExtensions[];
+
+// "Sec-WebSocket-Key"
+extern const char kSecWebSocketKey[];
+
+// "Sec-WebSocket-Accept"
+extern const char kSecWebSocketAccept[];
+
+// "Sec-WebSocket-Version"
+extern const char kSecWebSocketVersion[];
+
+// This implementation only supports one version of the WebSocket protocol,
+// "13", as specified in RFC6455. If support for multiple versions is added in
+// future, it will probably no longer be worth having a constant for this.
+extern const char kSupportedVersion[];
+
+// "Upgrade"
+extern const char kUpgrade[];
+
+// "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" as defined in section 4.1 of
+// RFC6455.
+extern const char NET_EXPORT kWebSocketGuid[];
+
+// Colon-prefixed lowercase headers for SPDY3.
+
+// ":sec-websocket-protocol"
+extern const char kSecWebSocketProtocolSpdy3[];
+
+// ":sec-websocket-extensions"
+extern const char kSecWebSocketExtensionsSpdy3[];
+
+// Some parts of the code require lowercase versions of the header names in
+// order to do case-insensitive comparisons, or because of SPDY.
+// "sec-websocket-protocol"
+extern const char* const kSecWebSocketProtocolLowercase;
+
+// "sec-websocket-extensions"
+extern const char* const kSecWebSocketExtensionsLowercase;
+
+// "sec-webSocket-key"
+extern const char kSecWebSocketKeyLowercase[];
+
+// "sec-websocket-version"
+extern const char kSecWebSocketVersionLowercase[];
+
+// "upgrade"
+extern const char kUpgradeLowercase[];
+
+// "websocket", as used in the "Upgrade:" header. This is always lowercase
+// (except in obsolete versions of the protocol).
+extern const char kWebSocketLowercase[];
+
+}  // namespace websockets
+}  // namespace net
+
+#endif  // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_CONSTANTS_H_
diff --git a/src/net/websockets/websocket_handshake_handler.cc b/src/net/websockets/websocket_handshake_handler.cc
index 991ea31..657f2c6 100644
--- a/src/net/websockets/websocket_handshake_handler.cc
+++ b/src/net/websockets/websocket_handshake_handler.cc
@@ -541,10 +541,13 @@
   headers_ = FilterHeaders(headers_, headers_to_remove, headers_to_remove_len);
 }
 
+std::size_t WebSocketHandshakeResponseHandler::GetRawResponseLength() const {
+  return original_header_length_ + GetResponseKeySize();
+}
+
 std::string WebSocketHandshakeResponseHandler::GetRawResponse() const {
   DCHECK(HasResponse());
-  return std::string(original_.data(),
-                     original_header_length_ + GetResponseKeySize());
+  return std::string(original_.data(), GetRawResponseLength());
 }
 
 std::string WebSocketHandshakeResponseHandler::GetResponse() {
diff --git a/src/net/websockets/websocket_handshake_handler.h b/src/net/websockets/websocket_handshake_handler.h
index b4a0dd5..a39403c 100644
--- a/src/net/websockets/websocket_handshake_handler.h
+++ b/src/net/websockets/websocket_handshake_handler.h
@@ -132,6 +132,7 @@
 
   // Gets raw WebSocket handshake response received from WebSocket server.
   std::string GetRawResponse() const;
+  std::size_t GetRawResponseLength() const;
 
   // Gets WebSocket handshake response message sent to renderer process.
   std::string GetResponse();
diff --git a/src/net/websockets/websocket_job.cc b/src/net/websockets/websocket_job.cc
index ff60ebe..e04cecd 100644
--- a/src/net/websockets/websocket_job.cc
+++ b/src/net/websockets/websocket_job.cc
@@ -17,8 +17,6 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/http/http_util.h"
-#include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_session_pool.h"
 #include "net/url_request/url_request_context.h"
 #include "net/websockets/websocket_handshake_handler.h"
 #include "net/websockets/websocket_net_log_params.h"
@@ -59,18 +57,11 @@
 
 namespace net {
 
-bool WebSocketJob::websocket_over_spdy_enabled_ = false;
-
 // static
 void WebSocketJob::EnsureInit() {
   g_websocket_job_init.Get();
 }
 
-// static
-void WebSocketJob::set_websocket_over_spdy_enabled(bool enabled) {
-  websocket_over_spdy_enabled_ = enabled;
-}
-
 WebSocketJob::WebSocketJob(SocketStream::Delegate* delegate)
     : delegate_(delegate),
       state_(INITIALIZED),
@@ -80,7 +71,6 @@
       started_to_send_handshake_request_(false),
       handshake_request_sent_(0),
       response_cookies_save_index_(0),
-      spdy_protocol_version_(0),
       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_for_send_pending_(this)) {
 }
@@ -181,7 +171,7 @@
     AddRef();  // Balanced when callback_ is cleared.
     return ERR_IO_PENDING;
   }
-  return TrySpdyStream();
+  return OK;
 }
 
 void WebSocketJob::OnConnected(
@@ -279,73 +269,6 @@
     delegate_->OnError(socket, error);
 }
 
-void WebSocketJob::OnCreatedSpdyStream(int result) {
-  DCHECK(spdy_websocket_stream_.get());
-  DCHECK(socket_.get());
-  DCHECK_NE(ERR_IO_PENDING, result);
-
-  if (state_ == CLOSED) {
-    result = ERR_ABORTED;
-  } else if (result == OK) {
-    state_ = CONNECTING;
-    result = ERR_PROTOCOL_SWITCHED;
-  } else {
-    spdy_websocket_stream_.reset();
-  }
-
-  CompleteIO(result);
-}
-
-void WebSocketJob::OnSentSpdyHeaders(int result) {
-  DCHECK_NE(INITIALIZED, state_);
-  if (state_ != CONNECTING)
-    return;
-  if (delegate_)
-    delegate_->OnSentData(socket_, handshake_request_->original_length());
-  handshake_request_.reset();
-}
-
-int WebSocketJob::OnReceivedSpdyResponseHeader(
-    const SpdyHeaderBlock& headers, int status) {
-  DCHECK_NE(INITIALIZED, state_);
-  if (state_ != CONNECTING)
-    return status;
-  if (status != OK)
-    return status;
-  // TODO(toyoshim): Fallback to non-spdy connection?
-  handshake_response_->ParseResponseHeaderBlock(headers,
-                                                challenge_,
-                                                spdy_protocol_version_);
-
-  SaveCookiesAndNotifyHeaderComplete();
-  return OK;
-}
-
-void WebSocketJob::OnSentSpdyData(int amount_sent) {
-  DCHECK_NE(INITIALIZED, state_);
-  DCHECK_NE(CONNECTING, state_);
-  if (state_ == CLOSED)
-    return;
-  if (!spdy_websocket_stream_.get())
-    return;
-  OnSentData(socket_, amount_sent);
-}
-
-void WebSocketJob::OnReceivedSpdyData(const char* data, int length) {
-  DCHECK_NE(INITIALIZED, state_);
-  DCHECK_NE(CONNECTING, state_);
-  if (state_ == CLOSED)
-    return;
-  if (!spdy_websocket_stream_.get())
-    return;
-  OnReceivedData(socket_, data, length);
-}
-
-void WebSocketJob::OnCloseSpdyStream() {
-  spdy_websocket_stream_.reset();
-  OnClose(socket_);
-}
-
 bool WebSocketJob::SendHandshakeRequest(const char* data, int len) {
   DCHECK_EQ(state_, CONNECTING);
   if (started_to_send_handshake_request_)
@@ -389,13 +312,7 @@
 }
 
 void WebSocketJob::DoSendData() {
-  if (spdy_websocket_stream_.get()) {
-    scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
-    handshake_request_->GetRequestHeaderBlock(
-        socket_->url(), headers.get(), &challenge_, spdy_protocol_version_);
-    spdy_websocket_stream_->SendRequest(headers.Pass());
-  } else {
-    const std::string& handshake_request =
+      const std::string& handshake_request =
         handshake_request_->GetRawRequest();
     handshake_request_sent_ = 0;
     socket_->net_log()->AddEvent(
@@ -403,7 +320,6 @@
         base::Bind(&NetLogWebSocketHandshakeCallback, &handshake_request));
     socket_->SendData(handshake_request.data(),
                       handshake_request.size());
-  }
   // Just buffered in |handshake_request_|.
   started_to_send_handshake_request_ = true;
 }
@@ -441,10 +357,7 @@
     return;
   }
   // handshake message is completed.
-  std::string raw_response = handshake_response_->GetRawResponse();
-  socket_->net_log()->AddEvent(
-      NetLog::TYPE_WEB_SOCKET_READ_RESPONSE_HEADERS,
-      base::Bind(&NetLogWebSocketHandshakeCallback, &raw_response));
+
   if (len - response_length > 0) {
     // If we received extra data, it should be frame data.
     DCHECK(received_data_after_handshake_.empty());
@@ -536,57 +449,6 @@
   return addresses_;
 }
 
-int WebSocketJob::TrySpdyStream() {
-  if (!socket_.get())
-    return ERR_FAILED;
-
-  if (!websocket_over_spdy_enabled_)
-    return OK;
-
-  // Check if we have a SPDY session available.
-  HttpTransactionFactory* factory =
-      socket_->context()->http_transaction_factory();
-  if (!factory)
-    return OK;
-  scoped_refptr<HttpNetworkSession> session = factory->GetSession();
-  if (!session.get())
-    return OK;
-  SpdySessionPool* spdy_pool = session->spdy_session_pool();
-  const HostPortProxyPair pair(HostPortPair::FromURL(socket_->url()),
-                               socket_->proxy_server());
-  if (!spdy_pool->HasSession(pair))
-    return OK;
-
-  // Forbid wss downgrade to SPDY without SSL.
-  // TODO(toyoshim): Does it realize the same policy with HTTP?
-  scoped_refptr<SpdySession> spdy_session =
-      spdy_pool->Get(pair, *socket_->net_log());
-  SSLInfo ssl_info;
-  bool was_npn_negotiated;
-  NextProto protocol_negotiated = kProtoUnknown;
-  bool use_ssl = spdy_session->GetSSLInfo(
-      &ssl_info, &was_npn_negotiated, &protocol_negotiated);
-  if (socket_->is_secure() && !use_ssl)
-    return OK;
-
-  // Create SpdyWebSocketStream.
-  spdy_protocol_version_ = spdy_session->GetProtocolVersion();
-  spdy_websocket_stream_.reset(new SpdyWebSocketStream(spdy_session, this));
-
-  int result = spdy_websocket_stream_->InitializeStream(
-      socket_->url(), MEDIUM, *socket_->net_log());
-  if (result == OK) {
-    OnConnected(socket_, kMaxPendingSendAllowed);
-    return ERR_PROTOCOL_SWITCHED;
-  }
-  if (result != ERR_IO_PENDING) {
-    spdy_websocket_stream_.reset();
-    return OK;
-  }
-
-  return ERR_IO_PENDING;
-}
-
 void WebSocketJob::SetWaiting() {
   waiting_ = true;
 }
@@ -607,12 +469,7 @@
 }
 
 void WebSocketJob::RetryPendingIO() {
-  int result = TrySpdyStream();
-
-  // In the case of ERR_IO_PENDING, CompleteIO() will be called from
-  // OnCreatedSpdyStream().
-  if (result != ERR_IO_PENDING)
-    CompleteIO(result);
+  CompleteIO(OK);
 }
 
 void WebSocketJob::CompleteIO(int result) {
@@ -626,16 +483,12 @@
 }
 
 bool WebSocketJob::SendDataInternal(const char* data, int length) {
-  if (spdy_websocket_stream_.get())
-    return ERR_IO_PENDING == spdy_websocket_stream_->SendData(data, length);
   if (socket_.get())
     return socket_->SendData(data, length);
   return false;
 }
 
 void WebSocketJob::CloseInternal() {
-  if (spdy_websocket_stream_.get())
-    spdy_websocket_stream_->Close();
   if (socket_.get())
     socket_->Close();
 }
diff --git a/src/net/websockets/websocket_job.h b/src/net/websockets/websocket_job.h
index e01085b..99a9c93 100644
--- a/src/net/websockets/websocket_job.h
+++ b/src/net/websockets/websocket_job.h
@@ -13,8 +13,6 @@
 #include "net/base/address_list.h"
 #include "net/base/completion_callback.h"
 #include "net/socket_stream/socket_stream_job.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_websocket_stream.h"
 
 class GURL;
 
@@ -33,8 +31,7 @@
 // TODO(ukai): refactor websocket.cc to use this.
 class NET_EXPORT WebSocketJob
     : public SocketStreamJob,
-      public SocketStream::Delegate,
-      public SpdyWebSocketStream::Delegate {
+      public SocketStream::Delegate {
  public:
   // This is state of WebSocket, not SocketStream.
   enum State {
@@ -49,10 +46,6 @@
 
   static void EnsureInit();
 
-  // Enable or Disable WebSocket over SPDY feature.
-  // This function is intended to be called before I/O thread starts.
-  static void set_websocket_over_spdy_enabled(bool enabled);
-
   State state() const { return state_; }
   virtual void Connect() OVERRIDE;
   virtual bool SendData(const char* data, int len) OVERRIDE;
@@ -77,19 +70,12 @@
                                      bool fatal) OVERRIDE;
   virtual void OnError(const SocketStream* socket, int error) OVERRIDE;
 
-  // SpdyWebSocketStream::Delegate methods.
-  virtual void OnCreatedSpdyStream(int status) OVERRIDE;
-  virtual void OnSentSpdyHeaders(int status) OVERRIDE;
-  virtual int OnReceivedSpdyResponseHeader(
-      const SpdyHeaderBlock& headers, int status) OVERRIDE;
-  virtual void OnSentSpdyData(int amount_sent) OVERRIDE;
-  virtual void OnReceivedSpdyData(const char* data, int length) OVERRIDE;
-  virtual void OnCloseSpdyStream() OVERRIDE;
+  WebSocketHandshakeResponseHandler* GetHandshakeResponse() {
+    return handshake_response_.get();
+  }
 
  private:
   friend class WebSocketThrottle;
-  friend class WebSocketJobSpdy2Test;
-  friend class WebSocketJobSpdy3Test;
   virtual ~WebSocketJob();
 
   bool SendHandshakeRequest(const char* data, int len);
@@ -107,7 +93,6 @@
   GURL GetURLForCookies() const;
 
   const AddressList& address_list() const;
-  int TrySpdyStream();
   void SetWaiting();
   bool IsWaiting() const;
   void Wakeup();
@@ -118,8 +103,6 @@
   void CloseInternal();
   void SendPending();
 
-  static bool websocket_over_spdy_enabled_;
-
   SocketStream::Delegate* delegate_;
   State state_;
   bool waiting_;
@@ -139,8 +122,6 @@
   scoped_refptr<DrainableIOBuffer> current_send_buffer_;
   std::vector<char> received_data_after_handshake_;
 
-  int spdy_protocol_version_;
-  scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_;
   std::string challenge_;
 
   base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_;
diff --git a/src/net/websockets/websocket_throttle_unittest.cc b/src/net/websockets/websocket_throttle_unittest.cc
index ef05c4c..7577574 100644
--- a/src/net/websockets/websocket_throttle_unittest.cc
+++ b/src/net/websockets/websocket_throttle_unittest.cc
@@ -63,7 +63,6 @@
   DummySocketStreamDelegate delegate;
   // TODO(toyoshim): We need to consider both spdy-enabled and spdy-disabled
   // configuration.
-  WebSocketJob::set_websocket_over_spdy_enabled(true);
 
   // For host1: 1.2.3.4, 1.2.3.5, 1.2.3.6
   AddressList addr;
@@ -280,7 +279,6 @@
 TEST_F(WebSocketThrottleTest, NoThrottleForDuplicateAddress) {
   TestURLRequestContext context;
   DummySocketStreamDelegate delegate;
-  WebSocketJob::set_websocket_over_spdy_enabled(true);
 
   // For localhost: 127.0.0.1, 127.0.0.1
   AddressList addr;
diff --git a/src/starboard/accessibility.h b/src/starboard/accessibility.h
new file mode 100644
index 0000000..fbe4c97
--- /dev/null
+++ b/src/starboard/accessibility.h
@@ -0,0 +1,57 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Module Overview: Starboard Accessibility module
+//
+// Provides access to the system options and settings related to accessibility.
+
+#ifndef STARBOARD_ACCESSIBILITY_H_
+#define STARBOARD_ACCESSIBILITY_H_
+
+#include "starboard/export.h"
+#include "starboard/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+
+// A group of settings related to text-to-speech functionality, for platforms
+// that expose system settings for text-to-speech.
+typedef struct SbAccessibilityTextToSpeechSettings {
+  // Whether this platform has a system setting for text-to-speech or not.
+  bool has_text_to_speech_setting;
+
+  // Whether the text-to-speech setting is enabled or not. This setting is only
+  // valid if |has_text_to_speech_setting| is set to true.
+  bool is_text_to_speech_enabled;
+} SbAccessibilityTextToSpeechSettings;
+
+// Get the platform settings related to the text-to-speech accessibility
+// feature. This function returns false if |out_settings| is NULL or if it is
+// not zero-initialized.
+//
+// |out_settings|: A pointer to a zero-initialized
+//    SbAccessibilityTextToSpeechSettings struct.
+SB_EXPORT bool SbAccessibilityGetTextToSpeechSettings(
+    SbAccessibilityTextToSpeechSettings* out_settings);
+
+#endif  // SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // STARBOARD_ACCESSIBILITY_H_
diff --git a/src/starboard/common/flat_map.h b/src/starboard/common/flat_map.h
index 4f4d39c..2e04d60 100644
--- a/src/starboard/common/flat_map.h
+++ b/src/starboard/common/flat_map.h
@@ -53,7 +53,7 @@
 //   where n is the number of items in flatmap
 //   and m is the input size for the operation.
 //
-// bulk insert |  O(n+m + m*log(m))
+// bulk insert |  O(m*log(m) + m*log(n) + n+m) (sort input, check dups, merge)
 // insert      |  O(n)
 // erase       |  O(n)
 // bulk erase  |  O(n*m)     TODO: Make faster - O(n+m + log(m))
diff --git a/src/starboard/doc/api_process.md b/src/starboard/doc/api_process.md
new file mode 100644
index 0000000..5e6e6e2
--- /dev/null
+++ b/src/starboard/doc/api_process.md
@@ -0,0 +1,68 @@
+# Starboard API Review Process
+
+## Why do we need a process?
+The Starboard API is the contract between Starboard applications and
+implementors of the Starboard API. Changing existing APIs and adding new
+required APIs breaks that contract and increases the cost of implementors
+keeping their Starboard port up-to-date. Pushing a release to the Open Source
+repository signals to Starboard implementors that any non-experimental APIs in
+that version will not change for as long as that version of Starboard is
+supported by the Starboard applications. We cannot change those newly frozen
+APIs without causing a potentially significant disruption to any partners who
+have already implemented them, or are in the process of implementing them.
+
+While having a process may make it harder to add new things to Starboard, it is
+much harder to remove or change things that are already there.
+
+Thus we need to give special focus to changes to the Starboard API to ensure its
+consistency with existing APIs design principles. Unnecessary churn on the
+Starboard API creates more work for Starboard application developers and may
+discourage porters from keeping Starboard applications up-to-date on their
+platforms. This process is intended to save time and effort for both Starboard
+application developers and Starboard implementors in the long run, and
+illustrates the complexity of dealing with a wide variety of platforms
+simultaneously.
+
+## So you want to add a new API?
+Historically, we have done API review as a part of the Code Review process using
+Gerrit. This works well for small-ish changes. For larger changes, consider
+writing a design document up front before defining the new API.
+
+### Who does the review?
+Send a message to the public cobalt-dev group to request a review.
+
+### What is the process?
+Developers are strongly encouraged to create the interface and upload that to
+Gerrit for review before spending time on stubs and tests. Iteration on the
+interface will necessarily result in changes to the stubs and tests, which can
+result in more work for the implementer of a new API.
+
+1. Upload a .h file with Module Overview and (optionally) initial function
+   prototypes
+    * New APIs should be declared in the experimental version, as described in the
+      starboard versioning doc.
+2. Discuss the new API with whoever is performing the review, and address
+   comments.
+3. Iterate.
+    * As a part of the review process, the reviewer will work with you to ensure
+      that the new API adheres to the starboard principles.
+4. Finalize function declarations.
+5. Implement tests and stubs.
+    * Existing platforms on trunk should not break as a result of this change.
+    * At this point, you may submit the interface, tests, and stubs with your
+      reviewer’s +2.
+6. Implement the interface for at least one platform.
+7. Iterate
+8. It may be that implementation of the API reveals things that were overlooked
+   during the earlier stages of the review.
+
+Ideally most major points of feedback will be caught early in the review process
+before much time has been spent on implementation.
+In the case that the platform in (6) is an internal platform, provide a
+reference implementation for at least one external reference platform. This can
+be in a follow-up CL, but must be implemented before the new API is frozen
+(see [versioning.md](versioning.md)).
+
+## How to design a new API
+See [principles.md](principles.md) for a guide on how to design a good Starboard
+API.
diff --git a/src/starboard/doc/versioning.md b/src/starboard/doc/versioning.md
new file mode 100644
index 0000000..3e18903
--- /dev/null
+++ b/src/starboard/doc/versioning.md
@@ -0,0 +1,135 @@
+# Starboard Versioning
+
+## Motivation
+When a porter implements Starboard for a platform, it is more precise to say
+that they have implemented support for a certain version of Starboard.
+Changes to the Starboard API are associated with Starboard versions. Any usage
+of new Starboard APIs must also be protected by a compile-time check for the
+Starboard version it belongs to. This decoupling of Cobalt and Starboard
+versions ensures that a porter can update to a newer version of Cobalt, but not
+be required to implement new Starboard APIs, if the version of Starboard they
+have implemented is still supported.
+
+## Starboard API version vs. Starboard application version
+The Starboard version describes the set of Starboard APIs available to Starboard
+applications. It will be incremented with every open-source release that
+includes changes to the Starboard API. Reasons to increment the Starboard API
+version include:
+
+* New Starboard APIs
+* Removed Starboard APIs
+* Modified semantics to existing APIs
+
+Some notable cases that do not justify incrementing the Starboard version
+include:
+
+* More descriptive or clearer comments for existing APIs that do not change the
+  semantics
+* New utility classes that are built on top of Starboard APIs, such as
+  `starboard::ScopedFile`
+* Changes that affect the upward API to Starboard applications, but not the
+  downward API to porters. For example, defining new upward APIs in terms of
+  existing Starboard APIs.
+
+A particular Starboard application may be versioned independently of the
+Starboard API. A given version of a Starboard application may support a range of
+Starboard versions. It may be the case that some new functionality in a
+Starboard application requires Starboard APIs that were added to a particular
+API version. If a porter wants to use such a feature, they must therefore also
+implement the required version of the Starboard API. For example, Voice Search
+was added to Cobalt version 5 and requires the SbMicrophone APIs which were
+added to Starboard version 2. Platforms that implemented Starboard version 1
+continued to build and run Cobalt 5 correctly, but the Voice Search feature
+would be unavailable.
+
+## Range of supported Starboard versions
+The minimum supported API version is defined by the `SB_MINIMUM_API_VERSION`
+macro, which is defined in starboard/configuration.h. Likewise, the
+`SB_MAXIMUM_API_VERSION` macro defines the maximum supported API version. All
+platforms must declare a `SB_API_VERSION` macro in the platform’s
+configuration.h to declare the starboard version the platform has implemented.
+Declaring implementation for an API version outside this range will result in an
+error at compilation time.
+Generally Starboard applications will not support all versions of the Starboard
+API indefinitely. Starboard application owners may increment the minimum
+required Starboard version at their discretion.
+TBD: Timelines and communication around when an upcoming Cobalt release will
+require porters to implement a newer version of Starboard.
+
+## Using new Starboard APIs from Starboard Applications
+Usage of a Starboard API that is not available in all supported Starboard API
+versions must be guarded with a check for `SB_API_VERSION`. Starboard
+applications must continue to function correctly and must not disable existing
+functionality if this check evaluates to false, but it’s acceptable to disable
+new functionality in Starboard applications if this evaluates to false.
+
+## Adding and using new Starboard APIs
+### “experimental” Starboard version
+At any given time, exactly one version of Starboard will be denoted as the
+“experimental” version, as defined by the `SB_EXPERIMENTAL_API_VERSION` macro in
+starboard/configuration.h. It is generally not recommended to declare support
+for this version. Any Starboard APIs defined in the experimental version are
+subject to change and API requirements could be added, removed, or changed at
+any time.
+### “frozen” Starboard versions
+All Starboard versions that are less than the experimental version are
+considered frozen. Any Starboard APIs in a frozen version shall not change as
+long as that version is supported by Cobalt.
+### Life of a Starboard API
+New Starboard APIs should be defined in the experimental version. In practice,
+they should be declared as follows:
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+void SbNewFunctionality();
+#endif
+```
+
+Starboard application features that use a new API must have a similar check:
+
+```
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+When a new version of a Starboard Application that requires new Starboard APIs
+is to be released, these new Starboard APIs will be frozen to the value of the
+current experimental version, and the experimental version will be incremented
+by one.
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= 7
+void SbNewFunctionality();
+#endif
+
+// starboard/other_new_functionality.h
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+void SbStillInDevelopment();
+#endif
+
+// starboard/configuration.h
+#define SB_EXPERIMENTAL_API_VERSION 8
+
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= 7
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+A developer who increments the experimental version must ensure that stubs and
+reference platforms declare support for the new experimental version through
+their respective `SB_API_VERSION` macros.
+
+## Open questions
+### Communicating Starboard API changes to porters
+When a new version of Starboard is released, there should be a process to
+describe the changes to the API, which Cobalt features depend on these, and a
+timeline for when porters will be required to move to the new version.
diff --git a/src/starboard/event.h b/src/starboard/event.h
index 44cdd79..f7d9a68 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -151,6 +151,13 @@
   // callback directly, so SbEventHandle should never receive this event
   // directly. The data type is an internally-defined structure.
   kSbEventTypeScheduled,
+
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+  // The platform's accessibility settings have changed. The application should
+  // query the accessibility settings using the appropriate APIs to get the
+  // new settings.
+  kSbEventTypeAccessiblitySettingsChanged,
+#endif
 } SbEventType;
 
 // Structure representing a Starboard event and its data.
diff --git a/src/starboard/linux/x64directfb/future/starboard_platform.gyp b/src/starboard/linux/x64directfb/future/starboard_platform.gyp
index 189aaf1..dd6f502 100644
--- a/src/starboard/linux/x64directfb/future/starboard_platform.gyp
+++ b/src/starboard/linux/x64directfb/future/starboard_platform.gyp
@@ -18,6 +18,7 @@
       'product_name': 'starboard_platform_future',
       'type': 'static_library',
       'sources': [
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_create_blitter.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_destroy.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_get_format.cc',
diff --git a/src/starboard/linux/x64x11/atomic_public.h b/src/starboard/linux/x64x11/atomic_public.h
index 169cb89..7845b02 100644
--- a/src/starboard/linux/x64x11/atomic_public.h
+++ b/src/starboard/linux/x64x11/atomic_public.h
@@ -14,4 +14,9 @@
  * limitations under the License.
  */
 
+#ifndef STARBOARD_LINUX_X64X11_ATOMIC_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_ATOMIC_PUBLIC_H_
+
 #include "starboard/linux/shared/atomic_public.h"
+
+#endif  // STARBOARD_LINUX_X64X11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/future/starboard_platform.gyp b/src/starboard/linux/x64x11/future/starboard_platform.gyp
index 6435941..3c1ac11 100644
--- a/src/starboard/linux/x64x11/future/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/future/starboard_platform.gyp
@@ -22,6 +22,7 @@
       'type': 'static_library',
       'sources': [
         '<@(starboard_platform_sources)',
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_create_egl.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_destroy.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_get_format.cc',
diff --git a/src/starboard/linux/x64x11/thread_types_public.h b/src/starboard/linux/x64x11/thread_types_public.h
index 6548e00..716c697 100644
--- a/src/starboard/linux/x64x11/thread_types_public.h
+++ b/src/starboard/linux/x64x11/thread_types_public.h
@@ -14,4 +14,9 @@
  * limitations under the License.
  */
 
+#ifndef STARBOARD_LINUX_X64X11_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_THREAD_TYPES_PUBLIC_H_
+
 #include "starboard/linux/shared/thread_types_public.h"
+
+#endif  // STARBOARD_LINUX_X64X11_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/memory.h b/src/starboard/memory.h
index 7181541..1a7d3e9 100644
--- a/src/starboard/memory.h
+++ b/src/starboard/memory.h
@@ -292,6 +292,16 @@
   return result;
 }
 
+// Returns true if the first |count| bytes of |buffer| are set to zero.
+static SB_C_INLINE bool SbMemoryIsZero(const void* buffer, size_t count) {
+  if (count == 0) {
+    return true;
+  }
+  const char* char_buffer = (const char*)(buffer);
+  return char_buffer[0] == 0 &&
+         SbMemoryCompare(char_buffer, char_buffer + 1, count - 1) == 0;
+}
+
 /////////////////////////////////////////////////////////////////
 // Deprecated. Do not use.
 /////////////////////////////////////////////////////////////////
diff --git a/src/starboard/nplb/accessibility_get_setting_test.cc b/src/starboard/nplb/accessibility_get_setting_test.cc
new file mode 100644
index 0000000..ab182f7
--- /dev/null
+++ b/src/starboard/nplb/accessibility_get_setting_test.cc
@@ -0,0 +1,42 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/accessibility.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+
+TEST(SbAccessibilityGetSettingTest, CanCallGetTextToSpeechSettings) {
+  SbAccessibilityTextToSpeechSettings settings = {0};
+  EXPECT_TRUE(SbAccessibilityGetTextToSpeechSettings(&settings));
+}
+
+TEST(SbAccessibilityGetSettingTest, CallTextToSpeechWithInvalidArgument) {
+  // |settings| should be zero-initialized.
+  SbAccessibilityTextToSpeechSettings settings = {1};
+  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(&settings));
+
+  // Argument should not be NULL.
+  EXPECT_FALSE(SbAccessibilityGetTextToSpeechSettings(NULL));
+}
+
+#endif
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/include_all.c b/src/starboard/nplb/include_all.c
index e55a271..69ce553 100644
--- a/src/starboard/nplb/include_all.c
+++ b/src/starboard/nplb/include_all.c
@@ -14,6 +14,7 @@
 
 // Includes all headers in a C context to make sure they compile as C files.
 
+#include "starboard/accessibility.h"
 #include "starboard/atomic.h"
 #include "starboard/audio_sink.h"
 #include "starboard/blitter.h"
diff --git a/src/starboard/nplb/memory_is_zero_test.cc b/src/starboard/nplb/memory_is_zero_test.cc
new file mode 100644
index 0000000..5529071
--- /dev/null
+++ b/src/starboard/nplb/memory_is_zero_test.cc
@@ -0,0 +1,52 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/memory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+const size_t kSize = 128;
+
+TEST(SbMemoryIsZeroTest, MemoryIsZero) {
+  int8_t buffer[kSize] = {0};
+
+  EXPECT_TRUE(SbMemoryIsZero(&buffer, sizeof(buffer)));
+}
+
+TEST(SbMemoryIsZeroTest, MemoryIsNonZero) {
+  int8_t buffer[kSize] = {0};
+  buffer[kSize - 1] = 1;
+
+  EXPECT_FALSE(SbMemoryIsZero(&buffer, sizeof(buffer)));
+  EXPECT_TRUE(SbMemoryIsZero(&buffer, sizeof(buffer) - 1));
+}
+
+TEST(SbMemoryIsZeroTest, EmptyBufferIsZero) {
+  EXPECT_TRUE(SbMemoryIsZero(NULL, 0));
+}
+
+TEST(SbMemoryIsZeroTest, SingleByte) {
+  int8_t zero = 0;
+  int8_t non_zero = 1;
+
+  EXPECT_TRUE(SbMemoryIsZero(&zero, 1));
+  EXPECT_FALSE(SbMemoryIsZero(&non_zero, 1));
+}
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 2bf9cb6..fd578f0 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -22,6 +22,7 @@
       'type': '<(gtest_target_type)',
       'sources': [
         '<(DEPTH)/starboard/common/test_main.cc',
+        'accessibility_get_setting_test.cc',
         'atomic_test.cc',
         'audio_sink_create_test.cc',
         'audio_sink_destroy_test.cc',
@@ -117,10 +118,11 @@
         'memory_allocate_test.cc',
         'memory_compare_test.cc',
         'memory_copy_test.cc',
-        'memory_find_byte_test.cc',
         'memory_deallocate_aligned_test.cc',
         'memory_deallocate_test.cc',
         'memory_get_stack_bounds_test.cc',
+        'memory_is_zero_test.cc',
+        'memory_find_byte_test.cc',
         'memory_map_test.cc',
         'memory_move_test.cc',
         'memory_reallocate_test.cc',
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi
index a096687..9fcbc9f 100644
--- a/src/starboard/raspi/shared/starboard_platform.gypi
+++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -302,6 +302,7 @@
         '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
         '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
         '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc',
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
         '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
         '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc
index 61155d6..63fb43d 100644
--- a/src/starboard/shared/starboard/player/player_worker.cc
+++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -96,12 +96,13 @@
 void* PlayerWorker::ThreadEntryPoint(void* context) {
   ThreadParam* param = static_cast<ThreadParam*>(context);
   SB_DCHECK(param != NULL);
+  PlayerWorker* player_worker = param->player_worker;
   {
     ScopedLock scoped_lock(param->mutex);
-    param->player_worker->job_queue_.reset(new JobQueue);
+    player_worker->job_queue_.reset(new JobQueue);
     param->condition_variable.Signal();
   }
-  param->player_worker->RunLoop();
+  player_worker->RunLoop();
   return NULL;
 }
 
diff --git a/src/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc b/src/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc
new file mode 100644
index 0000000..6a2d326
--- /dev/null
+++ b/src/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc
@@ -0,0 +1,27 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/accessibility.h"
+
+#include "starboard/memory.h"
+
+bool SbAccessibilityGetTextToSpeechSettings(
+    SbAccessibilityTextToSpeechSettings* out_setting) {
+  if (!out_setting ||
+      !SbMemoryIsZero(out_setting,
+                      sizeof(SbAccessibilityTextToSpeechSettings))) {
+    return false;
+  }
+  return true;
+}
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index ff61a20..b228978 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -25,6 +25,7 @@
         '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
         '<(DEPTH)/starboard/shared/starboard/log_message.cc',
         '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
+        '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
         '<(DEPTH)/starboard/shared/stub/atomic_public.h',
         '<(DEPTH)/starboard/shared/stub/audio_sink_create.cc',
         '<(DEPTH)/starboard/shared/stub/audio_sink_destroy.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h
index 2d5a1a2..8532ad8 100644
--- a/src/starboard/system.h
+++ b/src/starboard/system.h
@@ -129,6 +129,11 @@
   // Desktop PC.
   kSbSystemDeviceTypeDesktopPC,
 
+#if SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+  // An Android TV Device.
+  kSbSystemDeviceTypeAndroidTV,
+#endif  // SB_API_VERSION >= SB_EXPERIMENTAL_API_VERSION
+
   // Unknown device.
   kSbSystemDeviceTypeUnknown,
 } SbSystemDeviceType;
diff --git a/src/third_party/libwebp/libwebp.gyp b/src/third_party/libwebp/libwebp.gyp
index 947ed92..59deb74 100644
--- a/src/third_party/libwebp/libwebp.gyp
+++ b/src/third_party/libwebp/libwebp.gyp
@@ -80,6 +80,10 @@
         },{  # "target_arch != "arm" or arm_version < 7"
           'type': 'none',
         }],
+        ['target_arch == "arm" and arm_version >= 8 and clang == 1', {
+          # NEON is implicit on ARMv8, and clang doesn't like the redundant flag
+          'cflags!': [ '-mfpu=neon' ],
+        }],
         ['order_profiling != 0', {
           'target_conditions' : [
             ['_toolset=="target"', {
diff --git a/src/third_party/mozjs/js/src/vm/NumericConversions.h b/src/third_party/mozjs/js/src/vm/NumericConversions.h
index 61511a0..94cddae 100644
--- a/src/third_party/mozjs/js/src/vm/NumericConversions.h
+++ b/src/third_party/mozjs/js/src/vm/NumericConversions.h
@@ -132,7 +132,11 @@
 inline int32_t
 ToInt32(double d)
 {
-#if defined (__arm__) && defined (__GNUC__)
+#if defined(__ANDROID__) && defined(__clang__) && \
+    __clang_major__ == 3 && __clang_minor__ == 8
+#define ANDROID_CLANG38 1
+#endif
+#if defined (__arm__) && defined (__GNUC__) && !defined(ANDROID_CLANG38)
     int32_t i;
     uint32_t    tmp0;
     uint32_t    tmp1;
@@ -256,6 +260,7 @@
 #else
     return detail::ToIntWidth<int32_t>(d);
 #endif
+#undef ANDROID_CLANG38
 }
 
 /* ES5 9.6 (specialized for doubles). */
diff --git a/src/third_party/mozjs/mfbt/double-conversion/utils.h b/src/third_party/mozjs/mfbt/double-conversion/utils.h
index 0eec2d9..52fe028 100644
--- a/src/third_party/mozjs/mfbt/double-conversion/utils.h
+++ b/src/third_party/mozjs/mfbt/double-conversion/utils.h
@@ -53,7 +53,7 @@
 // disabled.)
 // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
 #if defined(_M_X64) || defined(__x86_64__) || \
-    defined(__ARMEL__) || defined(__avr32__) || \
+    defined(__ARMEL__) || defined(__avr32__) || defined(__aarch64__) || \
     defined(__hppa__) || defined(__ia64__) || \
     defined(__mips__) || defined(__powerpc__) || \
     defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
diff --git a/src/third_party/openssl/openssl.gyp b/src/third_party/openssl/openssl.gyp
index 484a49e..27a29c3 100644
--- a/src/third_party/openssl/openssl.gyp
+++ b/src/third_party/openssl/openssl.gyp
@@ -593,61 +593,71 @@
             'openssl_config_path': 'config/android',
           },
         }],
-        ['target_arch == "arm"', {
-          'sources!': [
-            # Use assembly version of this source file for ARM.
-            'openssl/crypto/aes/aes_core.c',
+        ['OS=="lb_shell" or OS=="starboard"', {
+          # Don't use assembly in steel or starboard.
+          # TODO: Investigate whether assembly helps low-profile devices.
+          'defines': [
+            'OPENSSL_NO_ASM',
           ],
-          'sources': [
-            'openssl/crypto/aes/asm/aes-armv4.S',
-            'openssl/crypto/bn/asm/armv4-gf2m.S',
-            'openssl/crypto/bn/asm/armv4-mont.S',
-            'openssl/crypto/modes/asm/ghash-armv4.S',
-            'openssl/crypto/sha/asm/sha1-armv4-large.S',
-            'openssl/crypto/sha/asm/sha256-armv4.S',
-            'openssl/crypto/sha/asm/sha512-armv4.S',
-          ],
-        }],
-        ['target_arch == "ia32"', {
-          'sources!': [
-            # Use assembly version of this source file for ARM.
-            'openssl/crypto/aes/aes_core.c',
-            'openssl/crypto/aes/aes_cbc.c',
-            'openssl/crypto/des/des_enc.c',
-            'openssl/crypto/des/fcrypt_b.c',
-            'openssl/crypto/bf/bf_enc.c',
-            'openssl/crypto/bn/bn_asm.c',
-          ],
-          'sources': [
-            'openssl/crypto/aes/asm/aes-586.S',
-            'openssl/crypto/aes/asm/aesni-x86.S',
-            'openssl/crypto/aes/asm/vpaes-x86.S',
-            'openssl/crypto/bf/asm/bf-586.S',
-            'openssl/crypto/bn/asm/bn-586.S',
-            'openssl/crypto/bn/asm/co-586.S',
-            'openssl/crypto/bn/asm/x86-gf2m.S',
-            'openssl/crypto/bn/asm/x86-mont.S',
-            'openssl/crypto/des/asm/crypt586.S',
-            'openssl/crypto/des/asm/des-586.S',
-            'openssl/crypto/md5/asm/md5-586.S',
-            'openssl/crypto/modes/asm/ghash-x86.S',
-            'openssl/crypto/sha/asm/sha1-586.S',
-            'openssl/crypto/sha/asm/sha256-586.S',
-            'openssl/crypto/sha/asm/sha512-586.S',
-          ],
-        }],
-        ['target_arch=="mips"', {
-          'sources!': [
-            # Use assembly version of these source files for MIPS.
-            'openssl/crypto/bn/bn_asm.c',
-            'openssl/crypto/aes/aes_core.c',
-          ],
-          'sources': [
-            'openssl/crypto/aes/asm/aes-mips.S',
-            'openssl/crypto/bn/asm/bn-mips.S',
-            'openssl/crypto/bn/asm/mips-mont.S',
-            'openssl/crypto/sha/asm/sha1-mips.S',
-            'openssl/crypto/sha/asm/sha256-mips.S',
+        }, {  # Not steel or starboard, use assembly
+          'conditions': [
+            ['target_arch == "arm"', {
+              'sources!': [
+                # Use assembly version of this source file for ARM.
+                'openssl/crypto/aes/aes_core.c',
+              ],
+              'sources': [
+                'openssl/crypto/aes/asm/aes-armv4.S',
+                'openssl/crypto/bn/asm/armv4-gf2m.S',
+                'openssl/crypto/bn/asm/armv4-mont.S',
+                'openssl/crypto/modes/asm/ghash-armv4.S',
+                'openssl/crypto/sha/asm/sha1-armv4-large.S',
+                'openssl/crypto/sha/asm/sha256-armv4.S',
+                'openssl/crypto/sha/asm/sha512-armv4.S',
+              ],
+            }],
+            ['target_arch == "ia32"', {
+              'sources!': [
+                # Use assembly version of these source files for IA32.
+                'openssl/crypto/aes/aes_core.c',
+                'openssl/crypto/aes/aes_cbc.c',
+                'openssl/crypto/des/des_enc.c',
+                'openssl/crypto/des/fcrypt_b.c',
+                'openssl/crypto/bf/bf_enc.c',
+                'openssl/crypto/bn/bn_asm.c',
+              ],
+              'sources': [
+                'openssl/crypto/aes/asm/aes-586.S',
+                'openssl/crypto/aes/asm/aesni-x86.S',
+                'openssl/crypto/aes/asm/vpaes-x86.S',
+                'openssl/crypto/bf/asm/bf-586.S',
+                'openssl/crypto/bn/asm/bn-586.S',
+                'openssl/crypto/bn/asm/co-586.S',
+                'openssl/crypto/bn/asm/x86-gf2m.S',
+                'openssl/crypto/bn/asm/x86-mont.S',
+                'openssl/crypto/des/asm/crypt586.S',
+                'openssl/crypto/des/asm/des-586.S',
+                'openssl/crypto/md5/asm/md5-586.S',
+                'openssl/crypto/modes/asm/ghash-x86.S',
+                'openssl/crypto/sha/asm/sha1-586.S',
+                'openssl/crypto/sha/asm/sha256-586.S',
+                'openssl/crypto/sha/asm/sha512-586.S',
+              ],
+            }],
+            ['target_arch=="mips"', {
+              'sources!': [
+                # Use assembly version of these source files for MIPS.
+                'openssl/crypto/bn/bn_asm.c',
+                'openssl/crypto/aes/aes_core.c',
+              ],
+              'sources': [
+                'openssl/crypto/aes/asm/aes-mips.S',
+                'openssl/crypto/bn/asm/bn-mips.S',
+                'openssl/crypto/bn/asm/mips-mont.S',
+                'openssl/crypto/sha/asm/sha1-mips.S',
+                'openssl/crypto/sha/asm/sha256-mips.S',
+              ],
+            }],
           ],
         }],
         ['clang==1', {
@@ -683,7 +693,6 @@
             'NO_SYS_UN_H',
             'NO_SYSLOG',
             'NO_WINDOWS_BRAINDEATH',
-            'OPENSSL_NO_ASM',
             'OPENSSL_NO_BF',
             'OPENSSL_NO_BUF_FREELISTS',
             'OPENSSL_NO_CAMELLIA',
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.S b/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.S
index 038f086..4cb7b99 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.S
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.S
@@ -121,7 +121,7 @@
 	beq	.Lialu
 
 	veor	d18,d18
-	vmov.32	d19,r3,r3		@ two copies of b1
+	vmov	d19,r3,r3		@ two copies of b1
 	vmov.32	d18[0],r1		@ a1
 
 	veor	d20,d20
diff --git a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.S b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.S
index d66c4cb..a32a2e8 100644
--- a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.S
+++ b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.S
@@ -3,6 +3,11 @@
 .text
 .code	32
 
+#ifdef  __clang__
+#define ldrplb  ldrbpl
+#define ldrneb  ldrbne
+#endif
+
 .type	rem_4bit,%object
 .align	5
 rem_4bit:
diff --git a/src/third_party/promise-polyfill/CHANGELOG.md b/src/third_party/promise-polyfill/CHANGELOG.md
new file mode 100644
index 0000000..f9bf5b5
--- /dev/null
+++ b/src/third_party/promise-polyfill/CHANGELOG.md
@@ -0,0 +1,94 @@
+# Changelog
+
+## 6.0.0 Deprecated `Promise._setImmediateFn` and `Promise._setUnhandledRejectionFn`
+This allows subclassing Promise without rewriting functions
+- `Promise._setImmediateFn(<immediateFn>)` has been deprecated. Use `Promise._immediateFn = <immediateFn>` instead.
+- `Promise._setUnhandledRejectionFn(<rejectionFn>)` has been deprecated. Use `Promise._unhandledRejectionFn = <rejectionFn>` instead.
+These functions will be removed in the next major version.
+
+### 5.2.1 setTimeout to 0
+Fixed bug where setTimeout was set to 1 instead of 0 for async execution
+
+### 5.2.0 Subclassing
+Allowed Subclassing. [#27](https://github.com/taylorhakes/promise-polyfill/pull/27)
+
+### 5.1.0 Fixed reliance on setTimeout
+Changed possibly unhanded warnings to use asap function instead of setTimeout
+
+## 5.0.0 Removed multiple params from Promise.all
+Removed non standard functionality of passing multiple params to Promise.all. You must pass an array now. You must change this code
+```js
+Promise.all(prom1, prom2, prom3);
+```
+to this
+```js
+Promise.all([prom1, prom2, prom3]);
+```
+
+### 4.0.4 IE8 console.warn fix
+IE8 does not have console, unless you open the developer tools. This fix checks to makes sure console.warn is defined before calling it.
+
+### 4.0.3 Fix case in bower.json
+bower.json had Promise.js instead of promise.js
+
+### 4.0.2 promise.js case fix in package.json
+Fixed promise.js in package.json. It was accidently published as Promise.js
+
+## 4.0.1 Unhandled Rejections and Other Fixes
+- Added unhandled rejection warnings to the console
+- Removed Grunt, jasmine and other unused code
+- Renamed Promise.js to lowercase promise.js in multiple places
+
+### 3.0.1 Fixed shadowing issue on setTimeout
+New version fixing this major bug https://github.com/taylorhakes/promise-polyfill/pull/17
+
+## 3.0.0 Updated setTimeout to not be affected by test mocks
+This is considered a breaking change because people may have been using this functionality. If you would like to keep version 2 functionality, set Promise._setImmediateFn on `promise-polyfill` like the code below.
+
+```js
+var Promise = require('promise-polyfill');
+Promise._setImmedateFn(function(fn) {
+  setTimeout(fn, 1);
+});
+```
+
+### 2.1.0 Promise._setImmedateFn
+Removed dead code Promise.immedateFn and added Promise._setImmediateFn(fn);
+
+### 2.0.2 Simplified Global detection
+Simplified attaching to global object
+
+### 2.0.1 Webworker bugfixes
+Fixed Webworkers missing window object
+
+## 2.0.0 
+**Changed the following line**
+```
+module.exports = root.Promise ? root.Promise : Promise;
+```
+to
+```
+module.exports = Promise;
+```
+
+This means the library will not use built-in Promise by default. This allows for more consistency.
+
+You can easily add the functionality back.
+```
+var Promise = window.Promise || require('promise-polyfill');
+```
+
+**Added Promise.immediateFn to allow changing the setImmedate function**
+```
+Promise.immediateFn = window.setAsap;
+```
+
+### 1.1.4 Updated Promise to use correct global object in Browser and Node
+
+### 1.1.3 Fixed browserify issue with `this`
+
+### 1.1.2 Updated Promise.resolve to resolve with original Promise
+
+### 1.1.0 Performance Improvements for Modern Browsers
+
+## 1.0.1 Update README.md
diff --git a/src/third_party/promise-polyfill/LICENSE b/src/third_party/promise-polyfill/LICENSE
new file mode 100644
index 0000000..94b9dac
--- /dev/null
+++ b/src/third_party/promise-polyfill/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Taylor Hakes
+Copyright (c) 2014 Forbes Lindesay
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/src/third_party/promise-polyfill/README.cobalt b/src/third_party/promise-polyfill/README.cobalt
new file mode 100644
index 0000000..2048a76
--- /dev/null
+++ b/src/third_party/promise-polyfill/README.cobalt
@@ -0,0 +1,15 @@
+Name: promise-polyfill

+Short Name: promise-polyfill

+URL: https://github.com/taylorhakes/promise-polyfill

+Version: 6.0.2

+Date: Nov 24, 2016

+License: MIT

+License File: LICENSE

+Security Critical: yes

+

+Description:

+A pure-ES5 implementation of ES6 Promises.

+

+Local Modifications:

+Deleted unnecessary files.

+Modified to be slightly more tolerant of setTimeout missing.
\ No newline at end of file
diff --git a/src/third_party/promise-polyfill/README.md b/src/third_party/promise-polyfill/README.md
new file mode 100644
index 0000000..a60d646
--- /dev/null
+++ b/src/third_party/promise-polyfill/README.md
@@ -0,0 +1,96 @@
+<a href="http://promises-aplus.github.com/promises-spec">
+    <img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
+         align="right" alt="Promises/A+ logo" />
+</a>
+# Promise Polyfill
+[![travis][travis-image]][travis-url]
+
+[travis-image]: https://img.shields.io/travis/taylorhakes/promise-polyfill.svg?style=flat
+[travis-url]: https://travis-ci.org/taylorhakes/promise-polyfill
+
+
+Lightweight ES6 Promise polyfill for the browser and node. Adheres closely to the spec. It is a perfect polyfill IE, Firefox or any other browser that does not support native promises.
+
+For API information about Promises, please check out this article [HTML5Rocks article](http://www.html5rocks.com/en/tutorials/es6/promises/).
+
+It is extremely lightweight. ***< 1kb Gzipped***
+
+## Browser Support
+IE8+, Chrome, Firefox, IOS 4+, Safari 5+, Opera
+
+### NPM Use
+```
+npm install promise-polyfill --save-exact
+```
+### Bower Use
+```
+bower install promise-polyfill
+```
+
+## Downloads
+
+- [Promise](https://raw.github.com/taylorhakes/promise-polyfill/master/promise.js)
+- [Promise-min](https://raw.github.com/taylorhakes/promise-polyfill/master/promise.min.js)
+
+## Simple use
+```js
+import Promise from 'promise-polyfill'; 
+
+// To add to window
+if (!window.Promise) {
+  window.Promise = Promise;
+}
+```
+
+then you can use like normal Promises
+```js
+var prom = new Promise(function(resolve, reject) {
+  // do a thing, possibly async, then…
+
+  if (/* everything turned out fine */) {
+    resolve("Stuff worked!");
+  }  else {
+    reject(new Error("It broke"));
+  }
+});
+
+prom.then(function(result) {
+  // Do something when async done
+});
+```
+
+## Deprecations
+- `Promise._setImmediateFn(<immediateFn>)` has been deprecated. Use `Promise._immediateFn = <immediateFn>;` instead.
+- `Promise._setUnhandledRejectionFn(<rejectionFn>)` has been deprecated. Use `Promise._unhandledRejectionFn = <rejectionFn>` instead.
+These functions will be removed in the next major version.
+
+## Performance
+By default promise-polyfill uses `setImmediate`, but falls back to `setTimeout` for executing asynchronously. If a browser does not support `setImmediate` (IE/Edge are the only browsers with setImmediate), you may see performance issues.
+Use a `setImmediate` polyfill to fix this issue. [setAsap](https://github.com/taylorhakes/setAsap) or [setImmediate](https://github.com/YuzuJS/setImmediate) work well.
+
+If you polyfill `window.setImmediate` or use `Promise._immediateFn = yourImmediateFn` it will be used instead of `window.setTimeout`
+```
+npm install setasap --save
+```
+```js
+var Promise = require('promise-polyfill');
+var setAsap = require('setasap');
+Promise._immediateFn = setAsap;
+```
+
+## Unhandled Rejections
+promise-polyfill will warn you about possibly unhandled rejections. It will show a console warning if a Promise is rejected, but no `.catch` is used. You can turn off this behavior by setting `Promise._setUnhandledRejectionFn(<rejectError>)`.
+If you would like to disable unhandled rejections. Use a noop like below.
+```js
+Promise._unhandledRejectionFn = function(rejectError) {};
+```
+
+
+## Testing
+```
+npm install
+npm test
+```
+
+## License
+MIT
diff --git a/src/third_party/promise-polyfill/promise.js b/src/third_party/promise-polyfill/promise.js
new file mode 100644
index 0000000..63aaa54
--- /dev/null
+++ b/src/third_party/promise-polyfill/promise.js
@@ -0,0 +1,233 @@
+(function (root) {
+
+  // Store setTimeout reference so promise-polyfill will be unaffected by
+  // other code modifying setTimeout (like sinon.useFakeTimers())
+  var setTimeoutFunc = root.setTimeout;
+
+  function noop() {}
+
+  // Polyfill for Function.prototype.bind
+  function bind(fn, thisArg) {
+    return function () {
+      fn.apply(thisArg, arguments);
+    };
+  }
+
+  function Promise(fn) {
+    if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
+    if (typeof fn !== 'function') throw new TypeError('not a function');
+    this._state = 0;
+    this._handled = false;
+    this._value = undefined;
+    this._deferreds = [];
+
+    doResolve(fn, this);
+  }
+
+  function handle(self, deferred) {
+    while (self._state === 3) {
+      self = self._value;
+    }
+    if (self._state === 0) {
+      self._deferreds.push(deferred);
+      return;
+    }
+    self._handled = true;
+    Promise._immediateFn(function () {
+      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
+      if (cb === null) {
+        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
+        return;
+      }
+      var ret;
+      try {
+        ret = cb(self._value);
+      } catch (e) {
+        reject(deferred.promise, e);
+        return;
+      }
+      resolve(deferred.promise, ret);
+    });
+  }
+
+  function resolve(self, newValue) {
+    try {
+      // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
+      if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
+      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
+        var then = newValue.then;
+        if (newValue instanceof Promise) {
+          self._state = 3;
+          self._value = newValue;
+          finale(self);
+          return;
+        } else if (typeof then === 'function') {
+          doResolve(bind(then, newValue), self);
+          return;
+        }
+      }
+      self._state = 1;
+      self._value = newValue;
+      finale(self);
+    } catch (e) {
+      reject(self, e);
+    }
+  }
+
+  function reject(self, newValue) {
+    self._state = 2;
+    self._value = newValue;
+    finale(self);
+  }
+
+  function finale(self) {
+    if (self._state === 2 && self._deferreds.length === 0) {
+      Promise._immediateFn(function() {
+        if (!self._handled) {
+          Promise._unhandledRejectionFn(self._value);
+        }
+      });
+    }
+
+    for (var i = 0, len = self._deferreds.length; i < len; i++) {
+      handle(self, self._deferreds[i]);
+    }
+    self._deferreds = null;
+  }
+
+  function Handler(onFulfilled, onRejected, promise) {
+    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
+    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
+    this.promise = promise;
+  }
+
+  /**
+   * Take a potentially misbehaving resolver function and make sure
+   * onFulfilled and onRejected are only called once.
+   *
+   * Makes no guarantees about asynchrony.
+   */
+  function doResolve(fn, self) {
+    var done = false;
+    try {
+      fn(function (value) {
+        if (done) return;
+        done = true;
+        resolve(self, value);
+      }, function (reason) {
+        if (done) return;
+        done = true;
+        reject(self, reason);
+      });
+    } catch (ex) {
+      if (done) return;
+      done = true;
+      reject(self, ex);
+    }
+  }
+
+  Promise.prototype['catch'] = function (onRejected) {
+    return this.then(null, onRejected);
+  };
+
+  Promise.prototype.then = function (onFulfilled, onRejected) {
+    var prom = new (this.constructor)(noop);
+
+    handle(this, new Handler(onFulfilled, onRejected, prom));
+    return prom;
+  };
+
+  Promise.all = function (arr) {
+    var args = Array.prototype.slice.call(arr);
+
+    return new Promise(function (resolve, reject) {
+      if (args.length === 0) return resolve([]);
+      var remaining = args.length;
+
+      function res(i, val) {
+        try {
+          if (val && (typeof val === 'object' || typeof val === 'function')) {
+            var then = val.then;
+            if (typeof then === 'function') {
+              then.call(val, function (val) {
+                res(i, val);
+              }, reject);
+              return;
+            }
+          }
+          args[i] = val;
+          if (--remaining === 0) {
+            resolve(args);
+          }
+        } catch (ex) {
+          reject(ex);
+        }
+      }
+
+      for (var i = 0; i < args.length; i++) {
+        res(i, args[i]);
+      }
+    });
+  };
+
+  Promise.resolve = function (value) {
+    if (value && typeof value === 'object' && value.constructor === Promise) {
+      return value;
+    }
+
+    return new Promise(function (resolve) {
+      resolve(value);
+    });
+  };
+
+  Promise.reject = function (value) {
+    return new Promise(function (resolve, reject) {
+      reject(value);
+    });
+  };
+
+  Promise.race = function (values) {
+    return new Promise(function (resolve, reject) {
+      for (var i = 0, len = values.length; i < len; i++) {
+        values[i].then(resolve, reject);
+      }
+    });
+  };
+
+  // Use polyfill for setImmediate for performance gains
+  Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
+    function (fn) {
+      setTimeoutFunc(fn, 0);
+    };
+
+  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
+    if (typeof console !== 'undefined' && console) {
+      console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
+    }
+  };
+
+  /**
+   * Set the immediate function to execute callbacks
+   * @param fn {function} Function to execute
+   * @deprecated
+   */
+  Promise._setImmediateFn = function _setImmediateFn(fn) {
+    Promise._immediateFn = fn;
+  };
+
+  /**
+   * Change the function to execute on unhandled rejection
+   * @param {function} fn Function to execute on unhandled rejection
+   * @deprecated
+   */
+  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
+    Promise._unhandledRejectionFn = fn;
+  };
+
+  if (typeof module !== 'undefined' && module.exports) {
+    module.exports = Promise;
+  } else if (!root.Promise) {
+    root.Promise = Promise;
+  }
+
+})(this);
diff --git a/src/third_party/promise-polyfill/promise.min.js b/src/third_party/promise-polyfill/promise.min.js
new file mode 100644
index 0000000..1ae225e
--- /dev/null
+++ b/src/third_party/promise-polyfill/promise.min.js
@@ -0,0 +1 @@
+!function(e){function n(){}function t(e,n){return function(){e.apply(n,arguments)}}function o(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(e,this)}function i(e,n){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(n):(e._handled=!0,void o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null===t)return void(1===e._state?r:u)(n.promise,e._value);var o;try{o=t(e._value)}catch(i){return void u(n.promise,i)}r(n.promise,o)}))}function r(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var i=n.then;if(n instanceof o)return e._state=3,e._value=n,void f(e);if("function"==typeof i)return void s(t(i,n),e)}e._state=1,e._value=n,f(e)}catch(r){u(e,r)}}function u(e,n){e._state=2,e._value=n,f(e)}function f(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;n<t;n++)i(e,e._deferreds[n]);e._deferreds=null}function c(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}function s(e,n){var t=!1;try{e(function(e){t||(t=!0,r(n,e))},function(e){t||(t=!0,u(n,e))})}catch(o){if(t)return;t=!0,u(n,o)}}var a=e.setTimeout;o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,t){var o=new this.constructor(n);return i(this,new c(e,t,o)),o},o.all=function(e){var n=Array.prototype.slice.call(e);return new o(function(e,t){function o(r,u){try{if(u&&("object"==typeof u||"function"==typeof u)){var f=u.then;if("function"==typeof f)return void f.call(u,function(e){o(r,e)},t)}n[r]=u,0===--i&&e(n)}catch(c){t(c)}}if(0===n.length)return e([]);for(var i=n.length,r=0;r<n.length;r++)o(r,n[r])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(n,t){for(var o=0,i=e.length;o<i;o++)e[o].then(n,t)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)},o._setImmediateFn=function(e){o._immediateFn=e},o._setUnhandledRejectionFn=function(e){o._unhandledRejectionFn=e},"undefined"!=typeof module&&module.exports?module.exports=o:e.Promise||(e.Promise=o)}(this);
\ No newline at end of file
diff --git a/src/third_party/promise-polyfill/test/adapter.js b/src/third_party/promise-polyfill/test/adapter.js
new file mode 100644
index 0000000..ca85741
--- /dev/null
+++ b/src/third_party/promise-polyfill/test/adapter.js
@@ -0,0 +1,14 @@
+var Promise = require('../promise');
+module.exports = {
+	resolved: Promise.resolve,
+	rejected: Promise.rejected,
+	deferred: function() {
+		var obj = {};
+		var prom = new Promise(function(resolve, reject) {
+			obj.resolve = resolve;
+			obj.reject = reject;
+		});
+		obj.promise = prom;
+		return obj;
+	}
+};
diff --git a/src/third_party/promise-polyfill/test/promise.js b/src/third_party/promise-polyfill/test/promise.js
new file mode 100644
index 0000000..6d9fedc
--- /dev/null
+++ b/src/third_party/promise-polyfill/test/promise.js
@@ -0,0 +1,190 @@
+var Promise = require('../promise');
+var sinon = require('sinon');
+var assert = require('assert');
+var adapter = require('./adapter');
+describe("Promises/A+ Tests", function () {
+  require("promises-aplus-tests").mocha(adapter);
+});
+describe('Promise', function () {
+  describe('Promise._setImmediateFn', function () {
+    afterEach(function() {
+      Promise._setImmediateFn((typeof setImmediate === 'function' && function (fn) {
+            setImmediate(fn);
+          }) ||
+      function (fn) {
+        setTimeout(fn, 1);
+      });
+    });
+    it('changes immediate fn', function () {
+      var spy = sinon.spy();
+
+      function immediateFn(fn) {
+        spy();
+        fn();
+      }
+      Promise._setImmediateFn(immediateFn);
+      var done = false;
+      new Promise(function (resolve) {
+        resolve();
+      }).then(function () {
+        done = true;
+      });
+      assert(spy.calledOnce);
+      assert(done);
+    });
+    it('changes immediate fn multiple', function () {
+      var spy1 = sinon.spy();
+
+      function immediateFn1(fn) {
+        spy1();
+        fn();
+      }
+
+      var spy2 = sinon.spy();
+
+      function immediateFn2(fn) {
+        spy2();
+        fn();
+      }
+
+      Promise._setImmediateFn(immediateFn1);
+      var done = false;
+      new Promise(function (resolve) {
+        resolve();
+      }).then(function () {
+      });
+      Promise._setImmediateFn(immediateFn2);
+      new Promise(function (resolve) {
+        resolve();
+      }).then(function () {
+        done = true;
+      });
+      assert(spy2.called);
+      assert(spy1.calledOnce);
+      assert(done);
+    });
+  });
+  describe('Promise._onUnhandledRejection', function () {
+    var stub, sandbox;
+    beforeEach(function() {
+      sandbox = sinon.sandbox.create();
+      stub = sandbox.stub(console, 'warn');
+    });
+    afterEach(function() {
+      sandbox.restore();
+    });
+    it('no error on resolve', function (done) {
+      Promise.resolve(true).then(function(result) {
+        return result;
+      }).then(function(result) {
+        return result;
+      });
+
+      setTimeout(function() {
+        assert(!stub.called);
+        done();
+      }, 50);
+    });
+    it('error single Promise', function (done) {
+      new Promise(function(resolve, reject) {
+        abc.abc = 1;
+      });
+      setTimeout(function() {
+        assert(stub.calledOnce);
+        done();
+      }, 50);
+    });
+    it('multi promise error', function (done) {
+      new Promise(function(resolve, reject) {
+        abc.abc = 1;
+      }).then(function(result) {
+        return result;
+      });
+      setTimeout(function() {
+        assert(stub.calledOnce);
+        done();
+      }, 50);
+    });
+    it('promise catch no error', function (done) {
+      new Promise(function(resolve, reject) {
+        abc.abc = 1;
+      }).catch(function(result) {
+        return result;
+      });
+      setTimeout(function() {
+        assert(!stub.called);
+        done();
+      }, 50);
+    });
+    it('promise catch no error', function (done) {
+      new Promise(function(resolve, reject) {
+        abc.abc = 1;
+      }).then(function(result) {
+        return result;
+      }).catch(function(result) {
+        return result;
+      });
+      setTimeout(function() {
+        assert(!stub.called);
+        done();
+      }, 50);
+    });
+    it('promise reject error', function (done) {
+      Promise.reject('hello');
+      setTimeout(function() {
+        assert(stub.calledOnce);
+        done();
+      }, 50);
+    });
+    it('promise reject error late', function (done) {
+      var prom = Promise.reject('hello');
+      prom.catch(function() {
+
+      });
+      setTimeout(function() {
+        assert(!stub.called);
+        done();
+      }, 50);
+    });
+    it('promise reject error late', function (done) {
+      Promise.reject('hello');
+      setTimeout(function() {
+        assert.equal(stub.args[0][1], 'hello');
+        done();
+      }, 50);
+    });
+  });
+  describe('Promise.prototype.then', function() {
+    var spy,
+        SubClass;
+    beforeEach(function() {
+      spy = sinon.spy();
+      SubClass = function() {
+        spy();
+        Promise.apply(this, arguments);
+      };
+
+      function __() { this.constructor = SubClass; }
+      __.prototype = Promise.prototype;
+      SubClass.prototype = new __();
+
+      SubClass.prototype.then = function() {
+        return Promise.prototype.then.apply(this, arguments);
+      };
+    });
+    it('subclassed Promise resolves to subclass', function() {
+      var prom = new SubClass(function(resolve) {
+        resolve();
+      }).then(function() {}, function() {});
+      assert(spy.calledTwice);
+      assert(prom instanceof SubClass);
+    });
+    it('subclassed Promise rejects to subclass', function() {
+      var prom = new SubClass(function(_, reject) {
+        reject();
+      }).then(function() {}, function() {});
+      assert(spy.calledTwice);
+      assert(prom instanceof SubClass);
+    });
+  });
+});

\ No newline at end of file
diff --git a/src/third_party/protobuf-3/BUILD b/src/third_party/protobuf-3/BUILD
new file mode 100644
index 0000000..8b1046b
--- /dev/null
+++ b/src/third_party/protobuf-3/BUILD
@@ -0,0 +1,709 @@
+# Bazel (http://bazel.io/) BUILD file for Protobuf.
+
+licenses(["notice"])
+
+################################################################################
+# Protobuf Runtime Library
+################################################################################
+
+COPTS = [
+    "-DHAVE_PTHREAD",
+    "-Wall",
+    "-Wwrite-strings",
+    "-Woverloaded-virtual",
+    "-Wno-sign-compare",
+    "-Wno-error=unused-function",
+]
+
+config_setting(
+    name = "android",
+    values = {
+        "crosstool_top": "//external:android/crosstool",
+    },
+)
+
+# Android builds do not need to link in a separate pthread library.
+LINK_OPTS = select({
+    ":android": [],
+    "//conditions:default": ["-lpthread"],
+})
+
+load(
+    "protobuf",
+    "cc_proto_library",
+    "py_proto_library",
+    "internal_gen_well_known_protos_java",
+    "internal_protobuf_py_tests",
+)
+
+config_setting(
+    name = "ios_armv7",
+    values = {
+        "ios_cpu": "armv7",
+    },
+)
+
+config_setting(
+    name = "ios_armv7s",
+    values = {
+        "ios_cpu": "armv7s",
+    },
+)
+
+config_setting(
+    name = "ios_arm64",
+    values = {
+        "ios_cpu": "arm64",
+    },
+)
+
+IOS_ARM_COPTS = COPTS + [
+    "-DOS_IOS",
+    "-miphoneos-version-min=7.0",
+    "-arch armv7",
+    "-arch armv7s",
+    "-arch arm64",
+    "-D__thread=",
+    "-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.2.sdk/",
+]
+
+cc_library(
+    name = "protobuf_lite",
+    srcs = [
+        # AUTOGEN(protobuf_lite_srcs)
+        "src/google/protobuf/arena.cc",
+        "src/google/protobuf/arenastring.cc",
+        "src/google/protobuf/extension_set.cc",
+        "src/google/protobuf/generated_message_util.cc",
+        "src/google/protobuf/io/coded_stream.cc",
+        "src/google/protobuf/io/zero_copy_stream.cc",
+        "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+        "src/google/protobuf/message_lite.cc",
+        "src/google/protobuf/repeated_field.cc",
+        "src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc",
+        "src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc",
+        "src/google/protobuf/stubs/bytestream.cc",
+        "src/google/protobuf/stubs/common.cc",
+        "src/google/protobuf/stubs/int128.cc",
+        "src/google/protobuf/stubs/once.cc",
+        "src/google/protobuf/stubs/status.cc",
+        "src/google/protobuf/stubs/statusor.cc",
+        "src/google/protobuf/stubs/stringpiece.cc",
+        "src/google/protobuf/stubs/stringprintf.cc",
+        "src/google/protobuf/stubs/structurally_valid.cc",
+        "src/google/protobuf/stubs/strutil.cc",
+        "src/google/protobuf/stubs/time.cc",
+        "src/google/protobuf/wire_format_lite.cc",
+    ],
+    hdrs = glob(["src/google/protobuf/**/*.h"]),
+    copts = select({
+        ":ios_armv7": IOS_ARM_COPTS,
+        ":ios_armv7s": IOS_ARM_COPTS,
+        ":ios_arm64": IOS_ARM_COPTS,
+        "//conditions:default": COPTS,
+    }),
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "protobuf",
+    srcs = [
+        # AUTOGEN(protobuf_srcs)
+        "src/google/protobuf/any.cc",
+        "src/google/protobuf/any.pb.cc",
+        "src/google/protobuf/api.pb.cc",
+        "src/google/protobuf/compiler/importer.cc",
+        "src/google/protobuf/compiler/parser.cc",
+        "src/google/protobuf/descriptor.cc",
+        "src/google/protobuf/descriptor.pb.cc",
+        "src/google/protobuf/descriptor_database.cc",
+        "src/google/protobuf/duration.pb.cc",
+        "src/google/protobuf/dynamic_message.cc",
+        "src/google/protobuf/empty.pb.cc",
+        "src/google/protobuf/extension_set_heavy.cc",
+        "src/google/protobuf/field_mask.pb.cc",
+        "src/google/protobuf/generated_message_reflection.cc",
+        "src/google/protobuf/io/gzip_stream.cc",
+        "src/google/protobuf/io/printer.cc",
+        "src/google/protobuf/io/strtod.cc",
+        "src/google/protobuf/io/tokenizer.cc",
+        "src/google/protobuf/io/zero_copy_stream_impl.cc",
+        "src/google/protobuf/map_field.cc",
+        "src/google/protobuf/message.cc",
+        "src/google/protobuf/reflection_ops.cc",
+        "src/google/protobuf/service.cc",
+        "src/google/protobuf/source_context.pb.cc",
+        "src/google/protobuf/struct.pb.cc",
+        "src/google/protobuf/stubs/mathlimits.cc",
+        "src/google/protobuf/stubs/substitute.cc",
+        "src/google/protobuf/text_format.cc",
+        "src/google/protobuf/timestamp.pb.cc",
+        "src/google/protobuf/type.pb.cc",
+        "src/google/protobuf/unknown_field_set.cc",
+        "src/google/protobuf/util/field_comparator.cc",
+        "src/google/protobuf/util/field_mask_util.cc",
+        "src/google/protobuf/util/internal/datapiece.cc",
+        "src/google/protobuf/util/internal/default_value_objectwriter.cc",
+        "src/google/protobuf/util/internal/error_listener.cc",
+        "src/google/protobuf/util/internal/field_mask_utility.cc",
+        "src/google/protobuf/util/internal/json_escaping.cc",
+        "src/google/protobuf/util/internal/json_objectwriter.cc",
+        "src/google/protobuf/util/internal/json_stream_parser.cc",
+        "src/google/protobuf/util/internal/object_writer.cc",
+        "src/google/protobuf/util/internal/proto_writer.cc",
+        "src/google/protobuf/util/internal/protostream_objectsource.cc",
+        "src/google/protobuf/util/internal/protostream_objectwriter.cc",
+        "src/google/protobuf/util/internal/type_info.cc",
+        "src/google/protobuf/util/internal/type_info_test_helper.cc",
+        "src/google/protobuf/util/internal/utility.cc",
+        "src/google/protobuf/util/json_util.cc",
+        "src/google/protobuf/util/message_differencer.cc",
+        "src/google/protobuf/util/time_util.cc",
+        "src/google/protobuf/util/type_resolver_util.cc",
+        "src/google/protobuf/wire_format.cc",
+        "src/google/protobuf/wrappers.pb.cc",
+    ],
+    hdrs = glob(["src/**/*.h"]),
+    copts = select({
+        ":ios_armv7": IOS_ARM_COPTS,
+        ":ios_armv7s": IOS_ARM_COPTS,
+        ":ios_arm64": IOS_ARM_COPTS,
+        "//conditions:default": COPTS,
+    }),
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protobuf_lite"],
+)
+
+objc_library(
+    name = "protobuf_objc",
+    hdrs = ["objectivec/GPBProtocolBuffers.h"],
+    includes = ["objectivec"],
+    non_arc_srcs = ["objectivec/GPBProtocolBuffers.m"],
+    visibility = ["//visibility:public"],
+)
+
+RELATIVE_WELL_KNOWN_PROTOS = [
+    # AUTOGEN(well_known_protos)
+    "google/protobuf/any.proto",
+    "google/protobuf/api.proto",
+    "google/protobuf/compiler/plugin.proto",
+    "google/protobuf/descriptor.proto",
+    "google/protobuf/duration.proto",
+    "google/protobuf/empty.proto",
+    "google/protobuf/field_mask.proto",
+    "google/protobuf/source_context.proto",
+    "google/protobuf/struct.proto",
+    "google/protobuf/timestamp.proto",
+    "google/protobuf/type.proto",
+    "google/protobuf/wrappers.proto",
+]
+
+WELL_KNOWN_PROTOS = ["src/" + s for s in RELATIVE_WELL_KNOWN_PROTOS]
+
+filegroup(
+    name = "well_known_protos",
+    srcs = WELL_KNOWN_PROTOS,
+    visibility = ["//visibility:public"],
+)
+
+cc_proto_library(
+    name = "cc_wkt_protos",
+    srcs = WELL_KNOWN_PROTOS,
+    include = "src",
+    default_runtime = ":protobuf",
+    internal_bootstrap_hack = 1,
+    protoc = ":protoc",
+    visibility = ["//visibility:public"],
+)
+
+################################################################################
+# Protocol Buffers Compiler
+################################################################################
+
+cc_library(
+    name = "protoc_lib",
+    srcs = [
+        # AUTOGEN(protoc_lib_srcs)
+        "src/google/protobuf/compiler/code_generator.cc",
+        "src/google/protobuf/compiler/command_line_interface.cc",
+        "src/google/protobuf/compiler/cpp/cpp_enum.cc",
+        "src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_extension.cc",
+        "src/google/protobuf/compiler/cpp/cpp_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_file.cc",
+        "src/google/protobuf/compiler/cpp/cpp_generator.cc",
+        "src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+        "src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_message.cc",
+        "src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_service.cc",
+        "src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
+        "src/google/protobuf/compiler/csharp/csharp_enum.cc",
+        "src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+        "src/google/protobuf/compiler/csharp/csharp_generator.cc",
+        "src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+        "src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_message.cc",
+        "src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+        "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+        "src/google/protobuf/compiler/java/java_context.cc",
+        "src/google/protobuf/compiler/java/java_doc_comment.cc",
+        "src/google/protobuf/compiler/java/java_enum.cc",
+        "src/google/protobuf/compiler/java/java_enum_field.cc",
+        "src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_enum_lite.cc",
+        "src/google/protobuf/compiler/java/java_extension.cc",
+        "src/google/protobuf/compiler/java/java_extension_lite.cc",
+        "src/google/protobuf/compiler/java/java_field.cc",
+        "src/google/protobuf/compiler/java/java_file.cc",
+        "src/google/protobuf/compiler/java/java_generator.cc",
+        "src/google/protobuf/compiler/java/java_generator_factory.cc",
+        "src/google/protobuf/compiler/java/java_helpers.cc",
+        "src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+        "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_map_field.cc",
+        "src/google/protobuf/compiler/java/java_map_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_message.cc",
+        "src/google/protobuf/compiler/java/java_message_builder.cc",
+        "src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+        "src/google/protobuf/compiler/java/java_message_field.cc",
+        "src/google/protobuf/compiler/java/java_message_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_message_lite.cc",
+        "src/google/protobuf/compiler/java/java_name_resolver.cc",
+        "src/google/protobuf/compiler/java/java_primitive_field.cc",
+        "src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_service.cc",
+        "src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+        "src/google/protobuf/compiler/java/java_string_field.cc",
+        "src/google/protobuf/compiler/java/java_string_field_lite.cc",
+        "src/google/protobuf/compiler/javanano/javanano_enum.cc",
+        "src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_extension.cc",
+        "src/google/protobuf/compiler/javanano/javanano_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_file.cc",
+        "src/google/protobuf/compiler/javanano/javanano_generator.cc",
+        "src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+        "src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_message.cc",
+        "src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+        "src/google/protobuf/compiler/js/js_generator.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+        "src/google/protobuf/compiler/plugin.cc",
+        "src/google/protobuf/compiler/plugin.pb.cc",
+        "src/google/protobuf/compiler/python/python_generator.cc",
+        "src/google/protobuf/compiler/ruby/ruby_generator.cc",
+        "src/google/protobuf/compiler/subprocess.cc",
+        "src/google/protobuf/compiler/zip_writer.cc",
+    ],
+    copts = COPTS,
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protobuf"],
+)
+
+cc_binary(
+    name = "protoc",
+    srcs = ["src/google/protobuf/compiler/main.cc"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protoc_lib"],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+RELATIVE_LITE_TEST_PROTOS = [
+    # AUTOGEN(lite_test_protos)
+    "google/protobuf/map_lite_unittest.proto",
+    "google/protobuf/unittest_import_lite.proto",
+    "google/protobuf/unittest_import_public_lite.proto",
+    "google/protobuf/unittest_lite.proto",
+    "google/protobuf/unittest_no_arena_lite.proto",
+]
+
+LITE_TEST_PROTOS = ["src/" + s for s in RELATIVE_LITE_TEST_PROTOS]
+
+RELATIVE_TEST_PROTOS = [
+    # AUTOGEN(test_protos)
+    "google/protobuf/any_test.proto",
+    "google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto",
+    "google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto",
+    "google/protobuf/map_proto2_unittest.proto",
+    "google/protobuf/map_unittest.proto",
+    "google/protobuf/unittest.proto",
+    "google/protobuf/unittest_arena.proto",
+    "google/protobuf/unittest_custom_options.proto",
+    "google/protobuf/unittest_drop_unknown_fields.proto",
+    "google/protobuf/unittest_embed_optimize_for.proto",
+    "google/protobuf/unittest_empty.proto",
+    "google/protobuf/unittest_enormous_descriptor.proto",
+    "google/protobuf/unittest_import.proto",
+    "google/protobuf/unittest_import_public.proto",
+    "google/protobuf/unittest_lite_imports_nonlite.proto",
+    "google/protobuf/unittest_mset.proto",
+    "google/protobuf/unittest_mset_wire_format.proto",
+    "google/protobuf/unittest_no_arena.proto",
+    "google/protobuf/unittest_no_arena_import.proto",
+    "google/protobuf/unittest_no_field_presence.proto",
+    "google/protobuf/unittest_no_generic_services.proto",
+    "google/protobuf/unittest_optimize_for.proto",
+    "google/protobuf/unittest_preserve_unknown_enum.proto",
+    "google/protobuf/unittest_preserve_unknown_enum2.proto",
+    "google/protobuf/unittest_proto3_arena.proto",
+    "google/protobuf/unittest_proto3_arena_lite.proto",
+    "google/protobuf/unittest_proto3_lite.proto",
+    "google/protobuf/unittest_well_known_types.proto",
+    "google/protobuf/util/internal/testdata/anys.proto",
+    "google/protobuf/util/internal/testdata/books.proto",
+    "google/protobuf/util/internal/testdata/default_value.proto",
+    "google/protobuf/util/internal/testdata/default_value_test.proto",
+    "google/protobuf/util/internal/testdata/field_mask.proto",
+    "google/protobuf/util/internal/testdata/maps.proto",
+    "google/protobuf/util/internal/testdata/oneofs.proto",
+    "google/protobuf/util/internal/testdata/struct.proto",
+    "google/protobuf/util/internal/testdata/timestamp_duration.proto",
+    "google/protobuf/util/json_format_proto3.proto",
+    "google/protobuf/util/message_differencer_unittest.proto",
+]
+
+TEST_PROTOS = ["src/" + s for s in RELATIVE_TEST_PROTOS]
+
+cc_proto_library(
+    name = "cc_test_protos",
+    srcs = LITE_TEST_PROTOS + TEST_PROTOS,
+    include = "src",
+    default_runtime = ":protobuf",
+    protoc = ":protoc",
+    deps = [":cc_wkt_protos"],
+)
+
+COMMON_TEST_SRCS = [
+    # AUTOGEN(common_test_srcs)
+    "src/google/protobuf/arena_test_util.cc",
+    "src/google/protobuf/map_test_util.cc",
+    "src/google/protobuf/test_util.cc",
+    "src/google/protobuf/testing/file.cc",
+    "src/google/protobuf/testing/googletest.cc",
+]
+
+cc_binary(
+    name = "test_plugin",
+    srcs = [
+        # AUTOGEN(test_plugin_srcs)
+        "src/google/protobuf/compiler/mock_code_generator.cc",
+        "src/google/protobuf/compiler/test_plugin.cc",
+        "src/google/protobuf/testing/file.cc",
+    ],
+    deps = [
+        ":protobuf",
+        ":protoc_lib",
+        "//external:gtest",
+    ],
+)
+
+cc_test(
+    name = "protobuf_test",
+    srcs = COMMON_TEST_SRCS + [
+        # AUTOGEN(test_srcs)
+        "src/google/protobuf/any_test.cc",
+        "src/google/protobuf/arena_unittest.cc",
+        "src/google/protobuf/arenastring_unittest.cc",
+        "src/google/protobuf/compiler/command_line_interface_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_unittest.cc",
+        "src/google/protobuf/compiler/cpp/metadata_test.cc",
+        "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc",
+        "src/google/protobuf/compiler/importer_unittest.cc",
+        "src/google/protobuf/compiler/java/java_doc_comment_unittest.cc",
+        "src/google/protobuf/compiler/java/java_plugin_unittest.cc",
+        "src/google/protobuf/compiler/mock_code_generator.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc",
+        "src/google/protobuf/compiler/parser_unittest.cc",
+        "src/google/protobuf/compiler/python/python_plugin_unittest.cc",
+        "src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc",
+        "src/google/protobuf/descriptor_database_unittest.cc",
+        "src/google/protobuf/descriptor_unittest.cc",
+        "src/google/protobuf/drop_unknown_fields_test.cc",
+        "src/google/protobuf/dynamic_message_unittest.cc",
+        "src/google/protobuf/extension_set_unittest.cc",
+        "src/google/protobuf/generated_message_reflection_unittest.cc",
+        "src/google/protobuf/io/coded_stream_unittest.cc",
+        "src/google/protobuf/io/printer_unittest.cc",
+        "src/google/protobuf/io/tokenizer_unittest.cc",
+        "src/google/protobuf/io/zero_copy_stream_unittest.cc",
+        "src/google/protobuf/map_field_test.cc",
+        "src/google/protobuf/map_test.cc",
+        "src/google/protobuf/message_unittest.cc",
+        "src/google/protobuf/no_field_presence_test.cc",
+        "src/google/protobuf/preserve_unknown_enum_test.cc",
+        "src/google/protobuf/proto3_arena_lite_unittest.cc",
+        "src/google/protobuf/proto3_arena_unittest.cc",
+        "src/google/protobuf/proto3_lite_unittest.cc",
+        "src/google/protobuf/reflection_ops_unittest.cc",
+        "src/google/protobuf/repeated_field_reflection_unittest.cc",
+        "src/google/protobuf/repeated_field_unittest.cc",
+        "src/google/protobuf/stubs/bytestream_unittest.cc",
+        "src/google/protobuf/stubs/common_unittest.cc",
+        "src/google/protobuf/stubs/int128_unittest.cc",
+        "src/google/protobuf/stubs/once_unittest.cc",
+        "src/google/protobuf/stubs/status_test.cc",
+        "src/google/protobuf/stubs/statusor_test.cc",
+        "src/google/protobuf/stubs/stringpiece_unittest.cc",
+        "src/google/protobuf/stubs/stringprintf_unittest.cc",
+        "src/google/protobuf/stubs/structurally_valid_unittest.cc",
+        "src/google/protobuf/stubs/strutil_unittest.cc",
+        "src/google/protobuf/stubs/template_util_unittest.cc",
+        "src/google/protobuf/stubs/time_test.cc",
+        "src/google/protobuf/stubs/type_traits_unittest.cc",
+        "src/google/protobuf/text_format_unittest.cc",
+        "src/google/protobuf/unknown_field_set_unittest.cc",
+        "src/google/protobuf/util/field_comparator_test.cc",
+        "src/google/protobuf/util/field_mask_util_test.cc",
+        "src/google/protobuf/util/internal/default_value_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/json_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/json_stream_parser_test.cc",
+        "src/google/protobuf/util/internal/protostream_objectsource_test.cc",
+        "src/google/protobuf/util/internal/protostream_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/type_info_test_helper.cc",
+        "src/google/protobuf/util/json_util_test.cc",
+        "src/google/protobuf/util/message_differencer_unittest.cc",
+        "src/google/protobuf/util/time_util_test.cc",
+        "src/google/protobuf/util/type_resolver_util_test.cc",
+        "src/google/protobuf/well_known_types_unittest.cc",
+        "src/google/protobuf/wire_format_unittest.cc",
+    ],
+    copts = COPTS,
+    data = [
+        ":test_plugin",
+    ] + glob([
+        "src/google/protobuf/**/*",
+    ]),
+    includes = [
+        "src/",
+    ],
+    linkopts = LINK_OPTS,
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":protoc_lib",
+        "//external:gtest_main",
+    ],
+)
+
+################################################################################
+# Java support
+################################################################################
+internal_gen_well_known_protos_java(
+    srcs = WELL_KNOWN_PROTOS,
+)
+
+java_library(
+    name = "protobuf_java",
+    srcs = glob([
+        "java/core/src/main/java/com/google/protobuf/*.java",
+    ]) + [
+        ":gen_well_known_protos_java",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+java_library(
+    name = "protobuf_java_util",
+    srcs = glob([
+        "java/util/src/main/java/com/google/protobuf/util/*.java",
+    ]),
+    deps = [
+        "protobuf_java",
+        "//external:gson",
+        "//external:guava",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+################################################################################
+# Python support
+################################################################################
+
+py_library(
+    name = "python_srcs",
+    srcs = glob(
+        [
+            "python/google/protobuf/*.py",
+            "python/google/protobuf/**/*.py",
+        ],
+        exclude = [
+            "python/google/protobuf/internal/*_test.py",
+            "python/google/protobuf/internal/test_util.py",
+        ],
+    ),
+    srcs_version = "PY2AND3",
+    imports = ["python"],
+)
+
+cc_binary(
+    name = "internal/_api_implementation.so",
+    srcs = ["python/google/protobuf/internal/api_implementation.cc"],
+    copts = COPTS + [
+        "-DPYTHON_PROTO2_CPP_IMPL_V2",
+    ],
+    linkshared = 1,
+    linkstatic = 1,
+    deps = select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": ["//external:python_headers"],
+    }),
+)
+
+cc_binary(
+    name = "pyext/_message.so",
+    srcs = glob([
+        "python/google/protobuf/pyext/*.cc",
+        "python/google/protobuf/pyext/*.h",
+    ]),
+    copts = COPTS + [
+        "-DGOOGLE_PROTOBUF_HAS_ONEOF=1",
+    ] + select({
+        "//conditions:default": [],
+        ":allow_oversize_protos": ["-DPROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS=1"],
+    }),
+    includes = [
+        "python/",
+        "src/",
+    ],
+    linkshared = 1,
+    linkstatic = 1,
+    deps = [
+        ":protobuf",
+    ] + select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": ["//external:python_headers"],
+    }),
+)
+
+config_setting(
+    name = "use_fast_cpp_protos",
+    values = {
+        "define": "use_fast_cpp_protos=true",
+    },
+)
+
+config_setting(
+    name = "allow_oversize_protos",
+    values = {
+        "define": "allow_oversize_protos=true",
+    },
+)
+
+py_proto_library(
+    name = "protobuf_python",
+    srcs = WELL_KNOWN_PROTOS,
+    include = "src",
+    data = select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": [
+            ":internal/_api_implementation.so",
+            ":pyext/_message.so",
+        ],
+    }),
+    default_runtime = "",
+    protoc = ":protoc",
+    py_libs = [
+        ":python_srcs",
+        "//external:six"
+    ],
+    srcs_version = "PY2AND3",
+    visibility = ["//visibility:public"],
+)
+
+py_proto_library(
+    name = "python_common_test_protos",
+    srcs = LITE_TEST_PROTOS + TEST_PROTOS,
+    include = "src",
+    default_runtime = "",
+    protoc = ":protoc",
+    srcs_version = "PY2AND3",
+    deps = [":protobuf_python"],
+)
+
+py_proto_library(
+    name = "python_specific_test_protos",
+    srcs = glob([
+        "python/google/protobuf/internal/*.proto",
+        "python/google/protobuf/internal/import_test_package/*.proto",
+    ]),
+    include = "python",
+    default_runtime = ":protobuf_python",
+    protoc = ":protoc",
+    srcs_version = "PY2AND3",
+    deps = [":python_common_test_protos"],
+)
+
+py_library(
+    name = "python_tests",
+    srcs = glob(
+        [
+            "python/google/protobuf/internal/*_test.py",
+            "python/google/protobuf/internal/test_util.py",
+        ],
+    ),
+    imports = ["python"],
+    srcs_version = "PY2AND3",
+    deps = [
+        ":protobuf_python",
+        ":python_common_test_protos",
+        ":python_specific_test_protos",
+    ],
+)
+
+internal_protobuf_py_tests(
+    name = "python_tests_batch",
+    data = glob([
+        "src/google/protobuf/**/*",
+    ]),
+    modules = [
+        "descriptor_database_test",
+        "descriptor_pool_test",
+        "descriptor_test",
+        "generator_test",
+        "json_format_test",
+        "message_factory_test",
+        "message_test",
+        "proto_builder_test",
+        "reflection_test",
+        "service_reflection_test",
+        "symbol_database_test",
+        "text_encoding_test",
+        "text_format_test",
+        "unknown_fields_test",
+        "wire_format_test",
+    ],
+    deps = [":python_tests"],
+)
diff --git a/src/third_party/protobuf-3/BUILD.gn b/src/third_party/protobuf-3/BUILD.gn
new file mode 100644
index 0000000..84c916a
--- /dev/null
+++ b/src/third_party/protobuf-3/BUILD.gn
@@ -0,0 +1,652 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("protobuf_config") {
+  include_dirs = [ "src" ]
+  defines = [
+    "GOOGLE_PROTOBUF_NO_RTTI",
+    "GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+  ]
+  if (!is_win) {
+    defines += [ "HAVE_PTHREAD" ]
+  }
+}
+
+config("protobuf_warnings") {
+  cflags = []
+  if (is_clang) {
+    # protobuf-3 contains a few functions that are unused.
+    cflags += [ "-Wno-unused-function" ]
+  }
+}
+
+if (is_component_build) {
+  config("protobuf_use_dlls") {
+    defines = [ "PROTOBUF_USE_DLLS" ]
+  }
+}
+
+# This config should be applied to targets using generated code from the proto
+# compiler. It sets up the include directories properly.
+config("using_proto") {
+  include_dirs = [
+    "src",
+    "$root_gen_dir/protoc_out",
+  ]
+}
+
+protobuf_lite_sources = [
+  "src/google/protobuf/arena.cc",
+  "src/google/protobuf/arena.h",
+  "src/google/protobuf/arenastring.cc",
+  "src/google/protobuf/arenastring.h",
+  "src/google/protobuf/extension_set.cc",
+  "src/google/protobuf/extension_set.h",
+  "src/google/protobuf/generated_message_util.cc",
+  "src/google/protobuf/generated_message_util.h",
+  "src/google/protobuf/io/coded_stream.cc",
+  "src/google/protobuf/io/coded_stream.h",
+  "src/google/protobuf/io/coded_stream_inl.h",
+  "src/google/protobuf/io/zero_copy_stream.cc",
+  "src/google/protobuf/io/zero_copy_stream.h",
+  "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+  "src/google/protobuf/io/zero_copy_stream_impl_lite.h",
+  "src/google/protobuf/map.h",
+  "src/google/protobuf/map_entry_lite.h",
+  "src/google/protobuf/map_field_lite.h",
+  "src/google/protobuf/map_type_handler.h",
+  "src/google/protobuf/message_lite.cc",
+  "src/google/protobuf/message_lite.h",
+  "src/google/protobuf/repeated_field.cc",
+  "src/google/protobuf/repeated_field.h",
+  "src/google/protobuf/stubs/atomicops.h",
+  "src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_arm_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_arm_qnx.h",
+  "src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h",
+  "src/google/protobuf/stubs/atomicops_internals_generic_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_macosx.h",
+  "src/google/protobuf/stubs/atomicops_internals_mips_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_pnacl.h",
+  "src/google/protobuf/stubs/atomicops_internals_power.h",
+  "src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_solaris.h",
+  "src/google/protobuf/stubs/atomicops_internals_tsan.h",
+  "src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc",
+  "src/google/protobuf/stubs/atomicops_internals_x86_gcc.h",
+  "src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc",
+  "src/google/protobuf/stubs/atomicops_internals_x86_msvc.h",
+  "src/google/protobuf/stubs/atomic_sequence_num.h",
+  "src/google/protobuf/stubs/bytestream.cc",
+  "src/google/protobuf/stubs/bytestream.h",
+  "src/google/protobuf/stubs/callback.h",
+  "src/google/protobuf/stubs/casts.h",
+  "src/google/protobuf/stubs/common.cc",
+  "src/google/protobuf/stubs/common.h",
+  "src/google/protobuf/stubs/fastmem.h",
+  "src/google/protobuf/stubs/hash.h",
+  "src/google/protobuf/stubs/int128.cc",
+  "src/google/protobuf/stubs/int128.h",
+  "src/google/protobuf/stubs/logging.h",
+  "src/google/protobuf/stubs/macros.h",
+  "src/google/protobuf/stubs/map_util.h",
+  "src/google/protobuf/stubs/mutex.h",
+  "src/google/protobuf/stubs/once.cc",
+  "src/google/protobuf/stubs/once.h",
+  "src/google/protobuf/stubs/platform_macros.h",
+  "src/google/protobuf/stubs/port.h",
+  "src/google/protobuf/stubs/scoped_ptr.h",
+  "src/google/protobuf/stubs/shared_ptr.h",
+  "src/google/protobuf/stubs/status.cc",
+  "src/google/protobuf/stubs/status.h",
+  "src/google/protobuf/stubs/status_macros.h",
+  "src/google/protobuf/stubs/statusor.cc",
+  "src/google/protobuf/stubs/statusor.h",
+  "src/google/protobuf/stubs/stl_util.h",
+  "src/google/protobuf/stubs/stringpiece.cc",
+  "src/google/protobuf/stubs/stringpiece.h",
+  "src/google/protobuf/stubs/stringprintf.cc",
+  "src/google/protobuf/stubs/stringprintf.h",
+  "src/google/protobuf/stubs/structurally_valid.cc",
+  "src/google/protobuf/stubs/strutil.cc",
+  "src/google/protobuf/stubs/strutil.h",
+  "src/google/protobuf/stubs/template_util.h",
+  "src/google/protobuf/stubs/type_traits.h",
+  "src/google/protobuf/stubs/time.cc",
+  "src/google/protobuf/stubs/time.h",
+  "src/google/protobuf/wire_format_lite.cc",
+  "src/google/protobuf/wire_format_lite.h",
+  "src/google/protobuf/wire_format_lite_inl.h",
+]
+
+protobuf_lite_cflags = []
+if (is_win) {
+  protobuf_lite_cflags = [
+    "/wd4018",  # signed/unsigned mismatch in comparison
+    "/wd4065",  # switch statement contains 'default' but no 'case' labels
+    "/wd4146",  # unary minus operator applied to unsigned type
+    "/wd4244",  # implicit conversion, possible loss of data
+    "/wd4267",  # size_t to int truncation
+    "/wd4291",  # no matching operator delete for a placement new.
+    "/wd4305",  # double to float truncation
+    "/wd4355",  # 'this' used in base member initializer list
+    "/wd4506",  # no definition for inline function (protobuf issue #240)
+    "/wd4715",  # not all control paths return a value (fixed in trunk)
+  ]
+}
+
+component("protobuf_lite") {
+  sources = protobuf_lite_sources
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+
+    # Must be after no_chromium_code for warning flags to be ordered
+    # correctly.
+    ":protobuf_warnings",
+  ]
+
+  if (is_win) {
+    configs -= [ "//build/config/win:lean_and_mean" ]
+  }
+
+  public_configs = [
+    ":protobuf_config",
+
+    # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+    "//build/config/compiler:no_size_t_to_int_warning",
+  ]
+
+  deps = [
+    "//build/config/sanitizers:deps",
+  ]
+
+  cflags = protobuf_lite_cflags
+
+  # Required for component builds. See http://crbug.com/172800.
+  if (is_component_build) {
+    public_configs += [ ":protobuf_use_dlls" ]
+    defines = [ "LIBPROTOBUF_EXPORTS" ]
+  }
+}
+
+# This is the full, heavy protobuf lib that's needed for c++ .protos that don't
+# specify the LITE_RUNTIME option. The protocol compiler itself (protoc) falls
+# into that category. Do not use in Chrome code.
+static_library("protobuf_full") {
+  # Prevent people from depending on this outside our file.
+  visibility = [ ":*" ]
+
+  sources = protobuf_lite_sources
+  sources += [
+    "src/google/protobuf/any.cc",
+    "src/google/protobuf/any.h",
+    "src/google/protobuf/any.pb.cc",
+    "src/google/protobuf/any.pb.h",
+    "src/google/protobuf/api.pb.cc",
+    "src/google/protobuf/api.pb.h",
+    "src/google/protobuf/compiler/importer.cc",
+    "src/google/protobuf/compiler/importer.h",
+    "src/google/protobuf/compiler/parser.cc",
+    "src/google/protobuf/compiler/parser.h",
+    "src/google/protobuf/descriptor.cc",
+    "src/google/protobuf/descriptor.h",
+    "src/google/protobuf/descriptor.pb.cc",
+    "src/google/protobuf/descriptor.pb.h",
+    "src/google/protobuf/descriptor_database.cc",
+    "src/google/protobuf/descriptor_database.h",
+    "src/google/protobuf/duration.pb.cc",
+    "src/google/protobuf/duration.pb.h",
+    "src/google/protobuf/dynamic_message.cc",
+    "src/google/protobuf/dynamic_message.h",
+    "src/google/protobuf/empty.pb.cc",
+    "src/google/protobuf/empty.pb.h",
+    "src/google/protobuf/extension_set_heavy.cc",
+    "src/google/protobuf/field_mask.pb.cc",
+    "src/google/protobuf/field_mask.pb.h",
+    "src/google/protobuf/generated_enum_reflection.h",
+    "src/google/protobuf/generated_enum_util.h",
+    "src/google/protobuf/generated_message_reflection.cc",
+    "src/google/protobuf/generated_message_reflection.h",
+
+    # gzip_stream.cc pulls in zlib, but it's not actually used by protoc, just
+    # by test code, so instead of compiling zlib for the host, let's just
+    # exclude this.
+    # "src/google/protobuf/io/gzip_stream.cc",
+    # "src/google/protobuf/io/gzip_stream.h",
+
+    "src/google/protobuf/io/printer.cc",
+    "src/google/protobuf/io/printer.h",
+    "src/google/protobuf/io/strtod.cc",
+    "src/google/protobuf/io/strtod.h",
+    "src/google/protobuf/io/tokenizer.cc",
+    "src/google/protobuf/io/tokenizer.h",
+    "src/google/protobuf/io/zero_copy_stream_impl.cc",
+    "src/google/protobuf/io/zero_copy_stream_impl.h",
+    "src/google/protobuf/map_entry.h",
+    "src/google/protobuf/map_field.cc",
+    "src/google/protobuf/map_field.h",
+    "src/google/protobuf/map_field_inl.h",
+    "src/google/protobuf/message.cc",
+    "src/google/protobuf/message.h",
+    "src/google/protobuf/metadata.h",
+    "src/google/protobuf/reflection.h",
+    "src/google/protobuf/reflection_internal.h",
+    "src/google/protobuf/reflection_ops.cc",
+    "src/google/protobuf/reflection_ops.h",
+    "src/google/protobuf/service.cc",
+    "src/google/protobuf/service.h",
+    "src/google/protobuf/source_context.pb.cc",
+    "src/google/protobuf/source_context.pb.h",
+    "src/google/protobuf/struct.pb.cc",
+    "src/google/protobuf/struct.pb.h",
+    "src/google/protobuf/stubs/mathlimits.cc",
+    "src/google/protobuf/stubs/mathlimits.h",
+    "src/google/protobuf/stubs/mathutil.h",
+    "src/google/protobuf/stubs/singleton.h",
+    "src/google/protobuf/stubs/substitute.cc",
+    "src/google/protobuf/stubs/substitute.h",
+    "src/google/protobuf/text_format.cc",
+    "src/google/protobuf/text_format.h",
+    "src/google/protobuf/timestamp.pb.cc",
+    "src/google/protobuf/timestamp.pb.h",
+    "src/google/protobuf/type.pb.cc",
+    "src/google/protobuf/type.pb.h",
+    "src/google/protobuf/unknown_field_set.cc",
+    "src/google/protobuf/unknown_field_set.h",
+    "src/google/protobuf/util/field_comparator.cc",
+    "src/google/protobuf/util/field_comparator.h",
+    "src/google/protobuf/util/field_mask_util.cc",
+    "src/google/protobuf/util/field_mask_util.h",
+    "src/google/protobuf/util/internal/constants.h",
+    "src/google/protobuf/util/internal/datapiece.cc",
+    "src/google/protobuf/util/internal/datapiece.h",
+    "src/google/protobuf/util/internal/default_value_objectwriter.cc",
+    "src/google/protobuf/util/internal/default_value_objectwriter.h",
+    "src/google/protobuf/util/internal/error_listener.cc",
+    "src/google/protobuf/util/internal/error_listener.h",
+    "src/google/protobuf/util/internal/field_mask_utility.cc",
+    "src/google/protobuf/util/internal/field_mask_utility.h",
+    "src/google/protobuf/util/internal/json_escaping.cc",
+    "src/google/protobuf/util/internal/json_escaping.h",
+    "src/google/protobuf/util/internal/json_objectwriter.cc",
+    "src/google/protobuf/util/internal/json_objectwriter.h",
+    "src/google/protobuf/util/internal/json_stream_parser.cc",
+    "src/google/protobuf/util/internal/json_stream_parser.h",
+    "src/google/protobuf/util/internal/location_tracker.h",
+    "src/google/protobuf/util/internal/object_location_tracker.h",
+    "src/google/protobuf/util/internal/object_source.h",
+    "src/google/protobuf/util/internal/object_writer.cc",
+    "src/google/protobuf/util/internal/object_writer.h",
+    "src/google/protobuf/util/internal/proto_writer.cc",
+    "src/google/protobuf/util/internal/proto_writer.h",
+    "src/google/protobuf/util/internal/protostream_objectsource.cc",
+    "src/google/protobuf/util/internal/protostream_objectsource.h",
+    "src/google/protobuf/util/internal/protostream_objectwriter.cc",
+    "src/google/protobuf/util/internal/protostream_objectwriter.h",
+    "src/google/protobuf/util/internal/structured_objectwriter.h",
+    "src/google/protobuf/util/internal/type_info.cc",
+    "src/google/protobuf/util/internal/type_info.h",
+    "src/google/protobuf/util/internal/type_info_test_helper.cc",
+    "src/google/protobuf/util/internal/type_info_test_helper.h",
+    "src/google/protobuf/util/internal/utility.cc",
+    "src/google/protobuf/util/internal/utility.h",
+    "src/google/protobuf/util/json_util.cc",
+    "src/google/protobuf/util/json_util.h",
+    "src/google/protobuf/util/message_differencer.cc",
+    "src/google/protobuf/util/message_differencer.h",
+    "src/google/protobuf/util/time_util.cc",
+    "src/google/protobuf/util/time_util.h",
+    "src/google/protobuf/util/type_resolver.h",
+    "src/google/protobuf/util/type_resolver_util.cc",
+    "src/google/protobuf/util/type_resolver_util.h",
+    "src/google/protobuf/wire_format.cc",
+    "src/google/protobuf/wire_format.h",
+    "src/google/protobuf/wrappers.pb.cc",
+    "src/google/protobuf/wrappers.pb.h",
+  ]
+
+  deps = [
+    "//build/config/sanitizers:deps",
+  ]
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+
+    # Must be after no_chromium_code for warning flags to be ordered
+    # correctly.
+    ":protobuf_warnings",
+  ]
+  if (is_win) {
+    configs -= [ "//build/config/win:lean_and_mean" ]
+  }
+  public_configs = [
+    ":protobuf_config",
+
+    # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+    "//build/config/compiler:no_size_t_to_int_warning",
+  ]
+
+  cflags = protobuf_lite_cflags
+}
+
+# Only compile the compiler for the host architecture.
+if (current_toolchain == host_toolchain) {
+  # protoc compiler is separated into protoc library and executable targets to
+  # support protoc plugins that need to link libprotoc, but not the main()
+  # itself. See src/google/protobuf/compiler/plugin.h
+  static_library("protoc_lib") {
+    sources = [
+      "src/google/protobuf/compiler/code_generator.cc",
+      "src/google/protobuf/compiler/code_generator.h",
+      "src/google/protobuf/compiler/command_line_interface.cc",
+      "src/google/protobuf/compiler/command_line_interface.h",
+      "src/google/protobuf/compiler/cpp/cpp_enum.cc",
+      "src/google/protobuf/compiler/cpp/cpp_enum.h",
+      "src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_enum_field.h",
+      "src/google/protobuf/compiler/cpp/cpp_extension.cc",
+      "src/google/protobuf/compiler/cpp/cpp_extension.h",
+      "src/google/protobuf/compiler/cpp/cpp_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_field.h",
+      "src/google/protobuf/compiler/cpp/cpp_file.cc",
+      "src/google/protobuf/compiler/cpp/cpp_file.h",
+      "src/google/protobuf/compiler/cpp/cpp_generator.cc",
+      "src/google/protobuf/compiler/cpp/cpp_generator.h",
+      "src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+      "src/google/protobuf/compiler/cpp/cpp_helpers.h",
+      "src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_map_field.h",
+      "src/google/protobuf/compiler/cpp/cpp_message.cc",
+      "src/google/protobuf/compiler/cpp/cpp_message.h",
+      "src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_message_field.h",
+      "src/google/protobuf/compiler/cpp/cpp_options.h",
+      "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_primitive_field.h",
+      "src/google/protobuf/compiler/cpp/cpp_service.cc",
+      "src/google/protobuf/compiler/cpp/cpp_service.h",
+      "src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+      "src/google/protobuf/compiler/cpp/cpp_string_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
+      "src/google/protobuf/compiler/csharp/csharp_doc_comment.h",
+      "src/google/protobuf/compiler/csharp/csharp_enum.cc",
+      "src/google/protobuf/compiler/csharp/csharp_enum.h",
+      "src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_enum_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+      "src/google/protobuf/compiler/csharp/csharp_field_base.h",
+      "src/google/protobuf/compiler/csharp/csharp_generator.cc",
+      "src/google/protobuf/compiler/csharp/csharp_generator.h",
+      "src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+      "src/google/protobuf/compiler/csharp/csharp_helpers.h",
+      "src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_map_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_message.cc",
+      "src/google/protobuf/compiler/csharp/csharp_message.h",
+      "src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_message_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_options.h",
+      "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_primitive_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
+      "src/google/protobuf/compiler/csharp/csharp_reflection_class.h",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h",
+      "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+      "src/google/protobuf/compiler/csharp/csharp_source_generator_base.h",
+      "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+      "src/google/protobuf/compiler/csharp/csharp_wrapper_field.h",
+      "src/google/protobuf/compiler/java/java_context.cc",
+      "src/google/protobuf/compiler/java/java_context.h",
+      "src/google/protobuf/compiler/java/java_doc_comment.cc",
+      "src/google/protobuf/compiler/java/java_doc_comment.h",
+      "src/google/protobuf/compiler/java/java_enum.cc",
+      "src/google/protobuf/compiler/java/java_enum.h",
+      "src/google/protobuf/compiler/java/java_enum_field.cc",
+      "src/google/protobuf/compiler/java/java_enum_field.h",
+      "src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_enum_field_lite.h",
+      "src/google/protobuf/compiler/java/java_enum_lite.cc",
+      "src/google/protobuf/compiler/java/java_enum_lite.h",
+      "src/google/protobuf/compiler/java/java_extension.cc",
+      "src/google/protobuf/compiler/java/java_extension.h",
+      "src/google/protobuf/compiler/java/java_extension_lite.cc",
+      "src/google/protobuf/compiler/java/java_extension_lite.h",
+      "src/google/protobuf/compiler/java/java_field.cc",
+      "src/google/protobuf/compiler/java/java_field.h",
+      "src/google/protobuf/compiler/java/java_file.cc",
+      "src/google/protobuf/compiler/java/java_file.h",
+      "src/google/protobuf/compiler/java/java_generator.cc",
+      "src/google/protobuf/compiler/java/java_generator.h",
+      "src/google/protobuf/compiler/java/java_generator_factory.cc",
+      "src/google/protobuf/compiler/java/java_generator_factory.h",
+      "src/google/protobuf/compiler/java/java_helpers.cc",
+      "src/google/protobuf/compiler/java/java_helpers.h",
+      "src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+      "src/google/protobuf/compiler/java/java_lazy_message_field.h",
+      "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_lazy_message_field_lite.h",
+      "src/google/protobuf/compiler/java/java_map_field.cc",
+      "src/google/protobuf/compiler/java/java_map_field.h",
+      "src/google/protobuf/compiler/java/java_map_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_map_field_lite.h",
+      "src/google/protobuf/compiler/java/java_message.cc",
+      "src/google/protobuf/compiler/java/java_message.h",
+      "src/google/protobuf/compiler/java/java_message_builder.cc",
+      "src/google/protobuf/compiler/java/java_message_builder.h",
+      "src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+      "src/google/protobuf/compiler/java/java_message_builder_lite.h",
+      "src/google/protobuf/compiler/java/java_message_field.cc",
+      "src/google/protobuf/compiler/java/java_message_field.h",
+      "src/google/protobuf/compiler/java/java_message_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_message_field_lite.h",
+      "src/google/protobuf/compiler/java/java_message_lite.cc",
+      "src/google/protobuf/compiler/java/java_message_lite.h",
+      "src/google/protobuf/compiler/java/java_name_resolver.cc",
+      "src/google/protobuf/compiler/java/java_name_resolver.h",
+      "src/google/protobuf/compiler/java/java_primitive_field.cc",
+      "src/google/protobuf/compiler/java/java_primitive_field.h",
+      "src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_primitive_field_lite.h",
+      "src/google/protobuf/compiler/java/java_service.cc",
+      "src/google/protobuf/compiler/java/java_service.h",
+      "src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+      "src/google/protobuf/compiler/java/java_shared_code_generator.h",
+      "src/google/protobuf/compiler/java/java_string_field.cc",
+      "src/google/protobuf/compiler/java/java_string_field.h",
+      "src/google/protobuf/compiler/java/java_string_field_lite.cc",
+      "src/google/protobuf/compiler/java/java_string_field_lite.h",
+      "src/google/protobuf/compiler/javanano/javanano_enum.cc",
+      "src/google/protobuf/compiler/javanano/javanano_enum.h",
+      "src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+      "src/google/protobuf/compiler/javanano/javanano_enum_field.h",
+      "src/google/protobuf/compiler/javanano/javanano_extension.cc",
+      "src/google/protobuf/compiler/javanano/javanano_extension.h",
+      "src/google/protobuf/compiler/javanano/javanano_field.cc",
+      "src/google/protobuf/compiler/javanano/javanano_field.h",
+      "src/google/protobuf/compiler/javanano/javanano_file.cc",
+      "src/google/protobuf/compiler/javanano/javanano_file.h",
+      "src/google/protobuf/compiler/javanano/javanano_generator.cc",
+      "src/google/protobuf/compiler/javanano/javanano_generator.h",
+      "src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+      "src/google/protobuf/compiler/javanano/javanano_helpers.h",
+      "src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+      "src/google/protobuf/compiler/javanano/javanano_map_field.h",
+      "src/google/protobuf/compiler/javanano/javanano_message.cc",
+      "src/google/protobuf/compiler/javanano/javanano_message.h",
+      "src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+      "src/google/protobuf/compiler/javanano/javanano_message_field.h",
+      "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+      "src/google/protobuf/compiler/javanano/javanano_primitive_field.h",
+      "src/google/protobuf/compiler/js/js_generator.cc",
+      "src/google/protobuf/compiler/js/js_generator.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_enum.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_enum_field.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_extension.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_field.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_file.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_generator.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_helpers.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_map_field.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_message.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_message_field.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_oneof.h",
+      "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+      "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h",
+      "src/google/protobuf/compiler/plugin.cc",
+      "src/google/protobuf/compiler/plugin.h",
+      "src/google/protobuf/compiler/plugin.pb.cc",
+      "src/google/protobuf/compiler/plugin.pb.h",
+      "src/google/protobuf/compiler/python/python_generator.cc",
+      "src/google/protobuf/compiler/python/python_generator.h",
+      "src/google/protobuf/compiler/ruby/ruby_generator.cc",
+      "src/google/protobuf/compiler/ruby/ruby_generator.h",
+      "src/google/protobuf/compiler/subprocess.cc",
+      "src/google/protobuf/compiler/subprocess.h",
+      "src/google/protobuf/compiler/zip_writer.cc",
+      "src/google/protobuf/compiler/zip_writer.h",
+    ]
+
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [
+      "//build/config/compiler:no_chromium_code",
+
+      # Must be after no_chromium_code for warning flags to be ordered
+      # correctly.
+      ":protobuf_warnings",
+    ]
+    if (is_win) {
+      # This is defined internally, don't warn on duplicate.
+      configs -= [ "//build/config/win:lean_and_mean" ]
+    }
+
+    public_configs = [ ":protobuf_config" ]
+
+    cflags = protobuf_lite_cflags
+
+    public_deps = [
+      ":protobuf_full",
+    ]
+  }
+
+  executable("protoc") {
+    sources = [
+      "src/google/protobuf/compiler/main.cc",
+    ]
+
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+
+    cflags = protobuf_lite_cflags
+
+    deps = [
+      ":protoc_lib",
+
+      # Default manifest on Windows (a no-op elsewhere).
+      "//build/win:default_exe_manifest",
+    ]
+  }
+}
+
+google_python_dir = "$root_out_dir/pyproto/google"
+
+copy("copy_google") {
+  sources = [
+    "__init__.py",
+  ]
+  outputs = [
+    "$google_python_dir/{{source_file_part}}",
+  ]
+}
+
+copy("copy_six") {
+  sources = [
+    "third_party/six/six.py",
+  ]
+  outputs = [
+    "$google_python_dir/third_party/six/{{source_file_part}}",
+  ]
+}
+
+copy("copy_google_protobuf") {
+  sources = [
+    "python/google/protobuf/__init__.py",
+    "python/google/protobuf/descriptor.py",
+    "python/google/protobuf/descriptor_database.py",
+    "python/google/protobuf/descriptor_pool.py",
+    "python/google/protobuf/json_format.py",
+    "python/google/protobuf/message.py",
+    "python/google/protobuf/message_factory.py",
+    "python/google/protobuf/proto_builder.py",
+    "python/google/protobuf/reflection.py",
+    "python/google/protobuf/service.py",
+    "python/google/protobuf/service_reflection.py",
+    "python/google/protobuf/symbol_database.py",
+    "python/google/protobuf/text_encoding.py",
+    "python/google/protobuf/text_format.py",
+
+    # TODO(ncarter): protoc's python generator treats descriptor.proto
+    # specially, but only when the input path is exactly
+    # "google/protobuf/descriptor.proto".  I'm not sure how to execute a rule
+    # from a different directory.  For now, use a manually-generated copy of
+    # descriptor_pb2.py.
+    "python/google/protobuf/descriptor_pb2.py",
+  ]
+  outputs = [
+    "$google_python_dir/protobuf/{{source_file_part}}",
+  ]
+}
+
+copy("copy_google_protobuf_internal") {
+  sources = [
+    "python/google/protobuf/internal/__init__.py",
+    "python/google/protobuf/internal/_parameterized.py",
+    "python/google/protobuf/internal/api_implementation.py",
+    "python/google/protobuf/internal/containers.py",
+    "python/google/protobuf/internal/decoder.py",
+    "python/google/protobuf/internal/encoder.py",
+    "python/google/protobuf/internal/enum_type_wrapper.py",
+    "python/google/protobuf/internal/message_listener.py",
+    "python/google/protobuf/internal/python_message.py",
+    "python/google/protobuf/internal/type_checkers.py",
+    "python/google/protobuf/internal/well_known_types.py",
+    "python/google/protobuf/internal/wire_format.py",
+  ]
+  outputs = [
+    "$google_python_dir/protobuf/internal/{{source_file_part}}",
+  ]
+}
+
+group("py_proto") {
+  public_deps = [
+    ":copy_google",
+    ":copy_google_protobuf",
+    ":copy_google_protobuf_internal",
+    ":copy_six",
+  ]
+
+  # Targets that depend on this should depend on the copied data files.
+  data = get_target_outputs(":copy_google")
+  data += get_target_outputs(":copy_six")
+  data += get_target_outputs(":copy_google_protobuf")
+  data += get_target_outputs(":copy_google_protobuf_internal")
+}
diff --git a/src/third_party/protobuf-3/CHANGES.txt b/src/third_party/protobuf-3/CHANGES.txt
new file mode 100644
index 0000000..3459ccc
--- /dev/null
+++ b/src/third_party/protobuf-3/CHANGES.txt
@@ -0,0 +1,1182 @@
+2016-05-16 version 3.0.0-beta-3 (C++/Java/Python/Ruby/Nano/Objective-C/C#/JavaScript)
+  General
+  * Supported Proto3 lite-runtime in C++/Java for mobile platforms.
+  * Any type now supports APIs to specify prefixes other than
+    type.googleapis.com
+  * Removed javanano_use_deprecated_package option; Nano will always has its own
+    ".nano" package.
+
+  C++ (Beta)
+  * Improved hash maps.
+      - Improved hash maps comments. In particular, please note that equal hash
+        maps will not necessarily have the same iteration order and
+        serialization.
+      - Added a new hash maps implementation that will become the default in a
+        later release.
+  * Arenas
+      - Several inlined methods in Arena were moved to out-of-line to improve
+        build performance and code size.
+      - Added SpaceAllocatedAndUsed() to report both space used and allocated
+      - Added convenient class UnsafeArenaAllocatedRepeatedPtrFieldBackInserter
+  * Any
+      - Allow custom type URL prefixes in Any packing.
+      - TextFormat now expand the Any type rather than printing bytes.
+  * Performance optimizations and various bug fixes.
+
+  Java (Beta)
+  * Introduced an ExperimentalApi annotation. Annotated APIs are experimental
+    and are subject to change in a backward incompatible way in future releases.
+  * Introduced zero-copy serialization as an ExperimentalApi
+      - Introduction of the `ByteOutput` interface. This is similar to
+        `OutputStream` but provides semantics for lazy writing (i.e. no
+        immediate copy required) of fields that are considered to be immutable.
+      - `ByteString` now supports writing to a `ByteOutput`, which will directly
+        expose the internals of the `ByteString` (i.e. `byte[]` or `ByteBuffer`)
+        to the `ByteOutput` without copying.
+      - `CodedOutputStream` now supports writing to a `ByteOutput`. `ByteString`
+        instances that are too large to fit in the internal buffer will be
+        (lazily) written to the `ByteOutput` directly.
+      - This allows applications using large `ByteString` fields to avoid
+        duplication of these fields entirely. Such an application can supply a
+        `ByteOutput` that chains together the chunks received from
+        `CodedOutputStream` before forwarding them onto the IO system.
+  * Other related changes to `CodedOutputStream`
+      - Additional use of `sun.misc.Unsafe` where possible to perform fast
+        access to `byte[]` and `ByteBuffer` values and avoiding unnecessary
+        range checking.
+      - `ByteBuffer`-backed `CodedOutputStream` now writes directly to the
+        `ByteBuffer` rather than to an intermediate array.
+  * Improved lite-runtime.
+      - Lite protos now implement deep equals/hashCode/toString
+      - Significantly improved the performance of Builder#mergeFrom() and
+        Builder#mergeDelimitedFrom()
+  * Various bug fixes and small feature enhancement.
+      - Fixed stack overflow when in hashCode() for infinite recursive oneofs.
+      - Fixed the lazy field parsing in lite to merge rather than overwrite.
+      - TextFormat now supports reporting line/column numbers on errors.
+      - Updated to add appropriate @Override for better compiler errors.
+
+  Python (Beta)
+  * Added JSON format for Any, Struct, Value and ListValue
+  * [ ] is now accepted for both repeated scalar fields and repeated message
+    fields in text format parser.
+  * Numerical field name is now supported in text format.
+  * Added DiscardUnknownFields API for python protobuf message.
+
+  Objective-C (Beta)
+  * Proto comments now come over as HeaderDoc comments in the generated sources
+    so Xcode can pick them up and display them.
+  * The library headers have been updated to use HeaderDoc comments so Xcode can
+    pick them up and display them.
+  * The per message and per field overhead in both generated code and runtime
+    object sizes was reduced.
+  * Generated code now include deprecated annotations when the proto file
+    included them.
+
+  C# (Beta)
+  In general: some changes are breaking, which require regenerating messages.
+  Most user-written code will not be impacted *except* for the renaming of enum
+  values.
+
+  * Allow custom type URL prefixes in `Any` packing, and ignore them when
+    unpacking
+  * `protoc` is now in a separate NuGet package (Google.Protobuf.Tools)
+  * New option: `internal_access` to generate internal classes
+  * Enum values are now PascalCased, and if there's a prefix which matches the
+    name of the enum, that is removed (so an enum `COLOR` with a value
+    `COLOR_BLUE` would generate a value of just `Blue`). An option
+    (`legacy_enum_values`) is temporarily available to disable this, but the
+    option will be removed for GA.
+  * `json_name` option is now honored
+  * If group tags are encountered when parsing, they are validated more
+    thoroughly (although we don't support actual groups)
+  * NuGet dependencies are better specified
+  * Breaking: `Preconditions` is renamed to `ProtoPreconditions`
+  * Breaking: `GeneratedCodeInfo` is renamed to `GeneratedClrTypeInfo`
+  * `JsonFormatter` now allows writing to a `TextWriter`
+  * New interface, `ICustomDiagnosticMessage` to allow more compact
+    representations from `ToString`
+  * `CodedInputStream` and `CodedOutputStream` now implement `IDisposable`,
+    which simply disposes of the streams they were constructed with
+  * Map fields no longer support null values (in line with other languages)
+  * Improvements in JSON formatting and parsing
+
+  Javascript (Alpha)
+  * Better support for "bytes" fields: bytes fields can be read as either a
+    base64 string or UInt8Array (in environments where TypedArray is supported).
+  * New support for CommonJS imports.  This should make it easier to use the
+    JavaScript support in Node.js and tools like WebPack.  See js/README.md for
+    more information.
+  * Some significant internal refactoring to simplify and modularize the code.
+
+  Ruby (Alpha)
+  * JSON serialization now properly uses camelCased names, with a runtime option
+    that will preserve original names from .proto files instead.
+  * Well-known types are now included in the distribution.
+  * Release now includes binary gems for Windows, Mac, and Linux instead of just
+    source gems.
+  * Bugfix for serializing oneofs.
+
+  C++/Java Lite (Alpha)
+    A new "lite" generator parameter was introduced in the protoc for C++ and
+    Java for Proto3 syntax messages. Example usage:
+
+     ./protoc --cpp_out=lite:$OUTPUT_PATH foo.proto
+
+    The protoc will treat the current input and all the transitive dependencies
+    as LITE. The same generator parameter must be used to generate the
+    dependencies.
+
+    In Proto3 syntax files, "optimized_for=LITE_RUNTIME" is no longer supported.
+
+
+2015-12-30 version 3.0.0-beta-2 (C++/Java/Python/Ruby/Nano/Objective-C/C#/JavaScript)
+  General
+  * Introduced a new language implementation: JavaScript.
+  * Added a new field option "json_name". By default proto field names are
+    converted to "lowerCamelCase" in proto3 JSON format. This option can be
+    used to override this behavior and specify a different JSON name for the
+    field.
+  * Added conformance tests to ensure implementations are following proto3 JSON
+    specification.
+
+  C++ (Beta)
+  * Various bug fixes and improvements to the JSON support utility:
+      - Duplicate map keys in JSON are now rejected (i.e., translation will
+        fail).
+      - Fixed wire-format for google.protobuf.Value/ListValue.
+      - Fixed precision loss when converting google.protobuf.Timestamp.
+      - Fixed a bug when parsing invalid UTF-8 code points.
+      - Fixed a memory leak.
+      - Reduced call stack usage.
+
+  Java (Beta)
+  * Cleaned up some unused methods on CodedOutputStream.
+  * Presized lists for packed fields during parsing in the lite runtime to
+    reduce allocations and improve performance.
+  * Improved the performance of unknown fields in the lite runtime.
+  * Introduced UnsafeByteStrings to support zero-copy ByteString creation.
+  * Various bug fixes and improvements to the JSON support utility:
+      - Fixed a thread-safety bug.
+      - Added a new option “preservingProtoFieldNames” to JsonFormat.
+      - Added a new option “includingDefaultValueFields” to JsonFormat.
+      - Updated the JSON utility to comply with proto3 JSON specification.
+
+  Python (Beta)
+  * Added proto3 JSON format utility. It includes support for all field types
+    and a few well-known types except for Any and Struct.
+  * Added runtime support for Any, Timestamp, Duration and FieldMask.
+  * [ ] is now accepted for repeated scalar fields in text format parser.
+  * Map fields now have proper O(1) performance for lookup/insert/delete
+    when using the Python/C++ implementation. They were previously using O(n)
+    search-based algorithms because the C++ reflection interface didn't
+    support true map operations.
+
+  Objective-C (Beta)
+  * Various bug-fixes and code tweaks to pass more strict compiler warnings.
+  * Now has conformance test coverage and is passing all tests.
+
+  C# (Beta)
+  * Various bug-fixes.
+  * Code generation: Files generated in directories based on namespace.
+  * Code generation: Include comments from .proto files in XML doc
+    comments (naively)
+  * Code generation: Change organization/naming of "reflection class" (access
+    to file descriptor)
+  * Code generation and library: Add Parser property to MessageDescriptor,
+    and introduce a non-generic parser type.
+  * Library: Added TypeRegistry to support JSON parsing/formatting of Any.
+  * Library: Added Any.Pack/Unpack support.
+  * Library: Implemented JSON parsing.
+
+  Javascript (Alpha)
+  * Added proto3 support for JavaScript. The runtime is written in pure
+    JavaScript and works in browsers and in Node.js. To generate JavaScript
+    code for your proto, invoke protoc with "--js_out". See js/README.md
+    for more build instructions.
+
+2015-08-26 version 3.0.0-beta-1 (C++/Java/Python/Ruby/Nano/Objective-C/C#)
+  About Beta
+  * This is the first beta release of protobuf v3.0.0. Not all languages
+    have reached beta stage. Languages not marked as beta are still in
+    alpha (i.e., be prepared for API breaking changes).
+
+  General
+  * Proto3 JSON is supported in several languages (fully supported in C++
+    and Java, partially supported in Ruby/C#). The JSON spec is defined in
+    the proto3 language guide:
+
+      https://developers.google.com/protocol-buffers/docs/proto3#json
+
+    We will publish a more detailed spec to define the exact behavior of
+    proto3-conformant JSON serializers and parsers. Until then, do not rely
+    on specific behaviors of the implementation if it’s not documented in
+    the above spec. More specifically, the behavior is not yet finalized for
+    the following:
+      - Parsing invalid JSON input (e.g., input with trailing commas).
+      - Non-camelCase names in JSON input.
+      - The same field appears multiple times in JSON input.
+      - JSON arrays contain “null” values.
+      - The message has unknown fields.
+
+  * Proto3 now enforces strict UTF-8 checking. Parsing will fail if a string
+    field contains non UTF-8 data.
+
+  C++ (Beta)
+  * Introduced new utility functions/classes in the google/protobuf/util
+    directory:
+      - MessageDifferencer: compare two proto messages and report their
+                            differences.
+      - JsonUtil: support converting protobuf binary format to/from JSON.
+      - TimeUtil: utility functions to work with well-known types Timestamp
+                  and Duration.
+      - FieldMaskUtil: utility functions to work with FieldMask.
+
+  * Performance optimization of arena construction and destruction.
+  * Bug fixes for arena and maps support.
+  * Changed to use cmake for Windows Visual Studio builds.
+  * Added Bazel support.
+
+  Java (Beta)
+  * Introduced a new util package that will be distributed as a separate
+    artifact in maven. It contains:
+      - JsonFormat: convert proto messages to/from JSON.
+      - TimeUtil: utility functions to work with Timestamp and Duration.
+      - FieldMaskUtil: utility functions to work with FieldMask.
+
+  * The static PARSER in each generated message is deprecated, and it will
+    be removed in a future release. A static parser() getter is generated
+    for each message type instead.
+  * Performance optimizations for String fields serialization.
+  * Performance optimizations for Lite runtime on Android:
+      - Reduced allocations
+      - Reduced method overhead after ProGuarding
+      - Reduced code size after ProGuarding
+
+  Python (Alpha)
+  * Removed legacy Python 2.5 support.
+  * Moved to a single Python 2.x/3.x-compatible codebase, instead of using 2to3.
+  * Fixed build/tests on Python 2.6, 2.7, 3.3, and 3.4.
+      - Pure-Python works on all four.
+      - Python/C++ implementation works on all but 3.4, due to changes in the
+        Python/C++ API in 3.4.
+  * Some preliminary work has been done to allow for multiple DescriptorPools
+    with Python/C++.
+
+  Ruby (Alpha)
+  * Many bugfixes:
+      - fixed parsing/serialization of bytes, sint, sfixed types
+      - other parser bugfixes
+      - fixed memory leak affecting Ruby 2.2
+
+  JavaNano (Alpha)
+  * JavaNano generated code now will be put in a nano package by default to
+    avoid conflicts with Java generated code.
+
+  Objective-C (Alpha)
+  * Added non-null markup to ObjC library. Requires SDK 8.4+ to build.
+  * Many bugfixes:
+      - Removed the class/enum filter.
+      - Renamed some internal types to avoid conflicts with the well-known types
+        protos.
+      - Added missing support for parsing repeated primitive fields in packed or
+        unpacked forms.
+      - Added *Count for repeated and map<> fields to avoid auto-create when
+        checking for them being set.
+
+  C# (Alpha)
+  * Namespace changed to Google.Protobuf (and NuGet package will be named
+    correspondingly).
+  * Target platforms now .NET 4.5 and selected portable subsets only.
+  * Removed lite runtime.
+  * Reimplementation to use mutable message types.
+  * Null references used to represent "no value" for message type fields.
+  * Proto3 semantics supported; proto2 files are prohibited for C# codegen.
+    Most proto3 features supported:
+      - JSON formatting (a.k.a. serialization to JSON), including well-known
+        types (except for Any).
+      - Wrapper types mapped to nullable value types (or string/ByteString
+        allowing nullability). JSON parsing is not supported yet.
+      - maps
+      - oneof
+      - enum unknown value preservation
+
+2015-05-25 version 3.0.0-alpha-3 (Objective-C/C#):
+  General
+  * Introduced two new language implementations (Objective-C, C#) to proto3.
+  * Explicit "optional" keyword are disallowed in proto3 syntax, as fields are
+    optional by default.
+  * Group fields are no longer supported in proto3 syntax.
+  * Changed repeated primitive fields to use packed serialization by default in
+    proto3 (implemented for C++, Java, Python in this release).  The user can
+    still disable packed serialization by setting packed to false for now.
+  * Added well-known type protos (any.proto, empty.proto, timestamp.proto,
+    duration.proto, etc.). Users can import and use these protos just like
+    regular proto files. Additional runtime support will be added for them in
+    future releases (in the form of utility helper functions, or having them
+    replaced by language specific types in generated code).
+  * Added a "reserved" keyword in both proto2 and proto3 syntax. User can use
+    this keyword to declare reserved field numbers and names to prevent them
+    from being reused by other fields in the same message.
+
+    To reserve field numbers, add a reserved declaration in your message:
+
+      message TestMessage {
+        reserved 2, 15, 9 to 11, 3;
+      }
+
+    This reserves field numbers 2, 3, 9, 10, 11 and 15. If a user uses any of
+    these as field numbers, the protocol buffer compiler will report an error.
+
+    Field names can also be reserved:
+
+      message TestMessage {
+        reserved "foo", "bar";
+      }
+
+  * Various bug fixes since 3.0.0-alpha-2
+
+  Objective-C
+    Objective-C includes a code generator and a native objective-c runtime
+    library.  By adding “--objc_out” to protoc, the code generator will generate
+    a header(*.pbobjc.h) and an implementation file(*.pbobjc.m) for each proto
+    file.
+
+    In this first release, the generated interface provides: enums, messages,
+    field support(single, repeated, map, oneof), proto2 and proto3 syntax
+    support, parsing and serialization. It’s  compatible with ARC and non-ARC
+    usage. Besides, user can also access it via the swift bridging header.
+
+    See objectivec/README.md for details.
+
+  C#
+    * C# protobufs are based on project
+      https://github.com/jskeet/protobuf-csharp-port. The original project was
+      frozen and all the new development will happen here.
+    * Codegen plugin for C# was completely rewritten to C++ and is now an
+      integral part of protoc.
+    * Some refactorings and cleanup has been applied to the C# runtime library.
+    * Only proto2 is supported in C# at the moment, proto3 support is in
+      progress and will likely bring significant breaking changes to the API.
+
+    See csharp/README.md for details.
+
+  C++
+    * Added runtime support for Any type. To use Any in your proto file, first
+      import the definition of Any:
+
+        // foo.proto
+        import "google/protobuf/any.proto";
+        message Foo {
+          google.protobuf.Any any_field = 1;
+        }
+        message Bar {
+          int32 value = 1;
+        }
+
+      Then in C++ you can access the Any field using PackFrom()/UnpackTo()
+      methods:
+
+        Foo foo;
+        Bar bar = ...;
+        foo.mutable_any_field()->PackFrom(bar);
+        ...
+        if (foo.any_field().IsType<Bar>()) {
+          foo.any_field().UnpackTo(&bar);
+          ...
+        }
+    * In text format, entries of a map field will be sorted by key.
+
+  Java
+    * Continued optimizations on the lite runtime to improve performance for
+      Android.
+
+  Python
+    * Added map support.
+      - maps now have a dict-like interface (msg.map_field[key] = value)
+      - existing code that modifies maps via the repeated field interface
+        will need to be updated.
+
+  Ruby
+    * Improvements to RepeatedField's emulation of the Ruby Array API.
+    * Various speedups and internal cleanups.
+
+2015-02-26 version 3.0.0-alpha-2 (Python/Ruby/JavaNano):
+  General
+  * Introduced three new language implementations (Ruby, JavaNano, and
+    Python) to proto3.
+  * Various bug fixes since 3.0.0-alpha-1
+
+  Python:
+    Python has received several updates, most notably support for proto3
+    semantics in any .proto file that declares syntax="proto3".
+    Messages declared in proto3 files no longer represent field presence
+    for scalar fields (number, enums, booleans, or strings).  You can
+    no longer call HasField() for such fields, and they are serialized
+    based on whether they have a non-zero/empty/false value.
+
+    One other notable change is in the C++-accelerated implementation.
+    Descriptor objects (which describe the protobuf schema and allow
+    reflection over it) are no longer duplicated between the Python
+    and C++ layers.  The Python descriptors are now simple wrappers
+    around the C++ descriptors.  This change should significantly
+    reduce the memory usage of programs that use a lot of message
+    types.
+
+  Ruby:
+    We have added proto3 support for Ruby via a native C extension.
+
+    The Ruby extension itself is included in the ruby/ directory, and details on
+    building and installing the extension are in ruby/README.md. The extension
+    will also be published as a Ruby gem. Code generator support is included as
+    part of `protoc` with the `--ruby_out` flag.
+
+    The Ruby extension implements a user-friendly DSL to define message types
+    (also generated by the code generator from `.proto` files).  Once a message
+    type is defined, the user may create instances of the message that behave in
+    ways idiomatic to Ruby. For example:
+
+    - Message fields are present as ordinary Ruby properties (getter method
+      `foo` and setter method `foo=`).
+    - Repeated field elements are stored in a container that acts like a native
+      Ruby array, and map elements are stored in a container that acts like a
+      native Ruby hashmap.
+    - The usual well-known methods, such as `#to_s`, `#dup`, and the like, are
+      present.
+
+    Unlike several existing third-party Ruby extensions for protobuf, this
+    extension is built on a "strongly-typed" philosophy: message fields and
+    array/map containers will throw exceptions eagerly when values of the
+    incorrect type are inserted.
+
+    See ruby/README.md for details.
+
+  JavaNano:
+    JavaNano is a special code generator and runtime library designed especially
+    for resource-restricted systems, like Android. It is very resource-friendly
+    in both the amount of code and the runtime overhead. Here is an an overview
+    of JavaNano features compared with the official Java protobuf:
+
+    - No descriptors or message builders.
+    - All messages are mutable; fields are public Java fields.
+    - For optional fields only, encapsulation behind setter/getter/hazzer/
+      clearer functions is opt-in, which provide proper 'has' state support.
+    - For proto2, if not opted in, has state (field presence) is not available.
+      Serialization outputs all fields not equal to their defaults.
+      The behavior is consistent with proto3 semantics.
+    - Required fields (proto2 only) are always serialized.
+    - Enum constants are integers; protection against invalid values only
+      when parsing from the wire.
+    - Enum constants can be generated into container interfaces bearing
+      the enum's name (so the referencing code is in Java style).
+    - CodedInputByteBufferNano can only take byte[] (not InputStream).
+    - Similarly CodedOutputByteBufferNano can only write to byte[].
+    - Repeated fields are in arrays, not ArrayList or Vector. Null array
+      elements are allowed and silently ignored.
+    - Full support for serializing/deserializing repeated packed fields.
+    - Support  extensions (in proto2).
+    - Unset messages/groups are null, not an immutable empty default
+      instance.
+    - toByteArray(...) and mergeFrom(...) are now static functions of
+      MessageNano.
+    - The 'bytes' type translates to the Java type byte[].
+
+    See javanano/README.txt for details.
+
+2014-12-01 version 3.0.0-alpha-1 (C++/Java):
+
+  General
+  * Introduced Protocol Buffers language version 3 (aka proto3).
+
+    When protobuf was initially opensourced it implemented Protocol Buffers
+    language version 2 (aka proto2), which is why the version number
+    started from v2.0.0. From v3.0.0, a new language version (proto3) is
+    introduced while the old version (proto2) will continue to be supported.
+
+    The main intent of introducing proto3 is to clean up protobuf before
+    pushing the language as the foundation of Google's new API platform.
+    In proto3, the language is simplified, both for ease of use and  to
+    make it available in a wider range of programming languages. At the
+    same time a few features are added to better support common idioms
+    found in APIs.
+
+    The following are the main new features in language version 3:
+
+      1. Removal of field presence logic for primitive value fields, removal
+         of required fields, and removal of default values. This makes proto3
+         significantly easier to implement with open struct representations,
+         as in languages like Android Java, Objective C, or Go.
+      2. Removal of unknown fields.
+      3. Removal of extensions, which are instead replaced by a new standard
+         type called Any.
+      4. Fix semantics for unknown enum values.
+      5. Addition of maps.
+      6. Addition of a small set of standard types for representation of time,
+         dynamic data, etc.
+      7. A well-defined encoding in JSON as an alternative to binary proto
+         encoding.
+
+    This release (v3.0.0-alpha-1) includes partial proto3 support for C++ and
+    Java. Items 6 (well-known types) and 7 (JSON format) in the above feature
+    list are not implemented.
+
+    A new notion "syntax" is introduced to specify whether a .proto file
+    uses proto2 or proto3:
+
+      // foo.proto
+      syntax = "proto3";
+      message Bar {...}
+
+    If omitted, the protocol compiler will generate a warning and "proto2" will
+    be used as the default. This warning will be turned into an error in a
+    future release.
+
+    We recommend that new Protocol Buffers users use proto3. However, we do not
+    generally recommend that existing users migrate from proto2 from proto3 due
+    to API incompatibility, and we will continue to support proto2 for a long
+    time.
+
+  * Added support for map fields (implemented in C++/Java for both proto2 and
+    proto3).
+
+    Map fields can be declared using the following syntax:
+
+      message Foo {
+        map<string, string> values = 1;
+      }
+
+    Data of a map field will be stored in memory as an unordered map and it
+    can be accessed through generated accessors.
+
+  C++
+  * Added arena allocation support (for both proto2 and proto3).
+
+    Profiling shows memory allocation and deallocation constitutes a significant
+    fraction of CPU-time spent in protobuf code and arena allocation is a
+    technique introduced to reduce this cost. With arena allocation, new
+    objects will be allocated from a large piece of preallocated memory and
+    deallocation of these objects is almost free. Early adoption shows 20% to
+    50% improvement in some Google binaries.
+
+    To enable arena support, add the following option to your .proto file:
+
+      option cc_enable_arenas = true;
+
+    Protocol compiler will generate additional code to make the generated
+    message classes work with arenas. This does not change the existing API
+    of protobuf messages and does not affect wire format. Your existing code
+    should continue to work after adding this option. In the future we will
+    make this option enabled by default.
+
+    To actually take advantage of arena allocation, you need to use the arena
+    APIs when creating messages. A quick example of using the arena API:
+
+      {
+        google::protobuf::Arena arena;
+        // Allocate a protobuf message in the arena.
+        MyMessage* message = Arena::CreateMessage<MyMessage>(&arena);
+        // All submessages will be allocated in the same arena.
+        if (!message->ParseFromString(data)) {
+          // Deal with malformed input data.
+        }
+        // Must not delete the message here. It will be deleted automatically
+        // when the arena is destroyed.
+      }
+
+    Currently arena does not work with map fields. Enabling arena in a .proto
+    file containing map fields will result in compile errors in the generated
+    code. This will be addressed in a future release.
+
+2014-10-20 version 2.6.1:
+
+  C++
+  * Added atomicops support for Solaris.
+  * Released memory allocated by InitializeDefaultRepeatedFields() and
+    GetEmptyString(). Some memory sanitizers reported them as memory leaks.
+
+  Java
+  * Updated DynamicMessage.setField() to handle repeated enum values
+    correctly.
+  * Fixed a bug that caused NullPointerException to be thrown when
+    converting manually constructed FileDescriptorProto to
+    FileDescriptor.
+
+  Python
+  * Fixed WhichOneof() to work with de-serialized protobuf messages.
+  * Fixed a missing file problem of Python C++ implementation.
+
+2014-08-15 version 2.6.0:
+
+  General
+  * Added oneofs(unions) feature. Fields in the same oneof will share
+    memory and at most one field can be set at the same time. Use the
+    oneof keyword to define a oneof like:
+      message SampleMessage {
+        oneof test_oneof {
+          string name = 4;
+          YourMessage sub_message = 9;
+        }
+      }
+  * Files, services, enums, messages, methods and enum values can be marked
+    as deprecated now.
+  * Added Support for list values, including lists of messages, when
+    parsing text-formatted protos in C++ and Java.
+      For example:  foo: [1, 2, 3]
+
+  C++
+  * Enhanced customization on TestFormat printing.
+  * Added SwapFields() in reflection API to swap a subset of fields.
+    Added SetAllocatedMessage() in reflection API.
+  * Repeated primitive extensions are now packable. The
+    [packed=true] option only affects serializers. Therefore, it is
+    possible to switch a repeated extension field to packed format
+    without breaking backwards-compatibility.
+  * Various speed optimizations.
+
+  Java
+  * writeTo() method in ByteString can now write a substring to an
+    output stream. Added endWith() method for ByteString.
+  * ByteString and ByteBuffer are now supported in CodedInputStream
+    and CodedOutputStream.
+  * java_generate_equals_and_hash can now be used with the LITE_RUNTIME.
+
+  Python
+  * A new C++-backed extension module (aka "cpp api v2") that replaces the
+    old ("cpp api v1") one.  Much faster than the pure Python code.  This one
+    resolves many bugs and is recommended for general use over the
+    pure Python when possible.
+  * Descriptors now have enum_types_by_name and extension_types_by_name dict
+    attributes.
+  * Support for Python 3.
+
+2013-02-27 version 2.5.0:
+
+  General
+  * New notion "import public" that allows a proto file to forward the content
+    it imports to its importers. For example,
+      // foo.proto
+      import public "bar.proto";
+      import "baz.proto";
+
+      // qux.proto
+      import "foo.proto";
+      // Stuff defined in bar.proto may be used in this file, but stuff from
+      // baz.proto may NOT be used without importing it explicitly.
+    This is useful for moving proto files. To move a proto file, just leave
+    a single "import public" in the old proto file.
+  * New enum option "allow_alias" that specifies whether different symbols can
+    be assigned the same numeric value. Default value is "true". Setting it to
+    false causes the compiler to reject enum definitions where multiple symbols
+    have the same numeric value.
+    Note: We plan to flip the default value to "false" in a future release.
+    Projects using enum aliases should set the option to "true" in their .proto
+    files.
+
+  C++
+  * New generated method set_allocated_foo(Type* foo) for message and string
+    fields. This method allows you to set the field to a pre-allocated object
+    and the containing message takes the ownership of that object.
+  * Added SetAllocatedExtension() and ReleaseExtension() to extensions API.
+  * Custom options are now formatted correctly when descriptors are printed in
+    text format.
+  * Various speed optimizations.
+
+  Java
+  * Comments in proto files are now collected and put into generated code as
+    comments for corresponding classes and data members.
+  * Added Parser to parse directly into messages without a Builder. For
+    example,
+      Foo foo = Foo.PARSER.ParseFrom(input);
+    Using Parser is ~25% faster than using Builder to parse messages.
+  * Added getters/setters to access the underlying ByteString of a string field
+    directly.
+  * ByteString now supports more operations: substring(), prepend(), and
+    append(). The implementation of ByteString uses a binary tree structure
+    to support these operations efficiently.
+  * New method findInitializationErrors() that lists all missing required
+    fields.
+  * Various code size and speed optimizations.
+
+  Python
+  * Added support for dynamic message creation. DescriptorDatabase,
+    DescriptorPool, and MessageFactory work like their C++ counterparts to
+    simplify Descriptor construction from *DescriptorProtos, and MessageFactory
+    provides a message instance from a Descriptor.
+  * Added pickle support for protobuf messages.
+  * Unknown fields are now preserved after parsing.
+  * Fixed bug where custom options were not correctly populated. Custom
+    options can be accessed now.
+  * Added EnumTypeWrapper that provides better accessibility to enum types.
+  * Added ParseMessage(descriptor, bytes) to generate a new Message instance
+    from a descriptor and a byte string.
+
+2011-05-01 version 2.4.1:
+
+  C++
+  * Fixed the friendship problem for old compilers to make the library now gcc 3
+    compatible again.
+  * Fixed vcprojects/extract_includes.bat to extract compiler/plugin.h.
+
+  Java
+  * Removed usages of JDK 1.6 only features to make the library now JDK 1.5
+    compatible again.
+  * Fixed a bug about negative enum values.
+  * serialVersionUID is now defined in generated messages for java serializing.
+  * Fixed protoc to use java.lang.Object, which makes "Object" now a valid
+    message name again.
+
+  Python
+  * Experimental C++ implementation now requires C++ protobuf library installed.
+    See the README.txt in the python directory for details.
+
+2011-02-02 version 2.4.0:
+
+  General
+  * The RPC (cc|java|py)_generic_services default value is now false instead of
+    true.
+  * Custom options can have aggregate types. For example,
+      message MyOption {
+        optional string comment = 1;
+        optional string author = 2;
+      }
+      extend google.protobuf.FieldOptions {
+        optional MyOption myoption = 12345;
+      }
+    This option can now be set as follows:
+      message SomeType {
+        optional int32 field = 1 [(myoption) = { comment:'x' author:'y' }];
+      }
+
+  C++
+  * Various speed and code size optimizations.
+  * Added a release_foo() method on string and message fields.
+  * Fixed gzip_output_stream sub-stream handling.
+
+  Java
+  * Builders now maintain sub-builders for sub-messages. Use getFooBuilder() to
+    get the builder for the sub-message "foo". This allows you to repeatedly
+    modify deeply-nested sub-messages without rebuilding them.
+  * Builder.build() no longer invalidates the Builder for generated messages
+    (You may continue to modify it and then build another message).
+  * Code generator will generate efficient equals() and hashCode()
+    implementations if new option java_generate_equals_and_hash is enabled.
+    (Otherwise, reflection-based implementations are used.)
+  * Generated messages now implement Serializable.
+  * Fields with [deprecated=true] will be marked with @Deprecated in Java.
+  * Added lazy conversion of UTF-8 encoded strings to String objects to improve
+    performance.
+  * Various optimizations.
+  * Enum value can be accessed directly, instead of calling getNumber() on the
+    enum member.
+  * For each enum value, an integer constant is also generated with the suffix
+    _VALUE.
+
+  Python
+  * Added an experimental  C++ implementation for Python messages via a Python
+    extension. Implementation type is controlled by an environment variable
+    PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION (valid values: "cpp" and "python")
+    The default value is currently "python" but will be changed to "cpp" in
+    future release.
+  * Improved performance on message instantiation significantly.
+    Most of the work on message instantiation is done just once per message
+    class, instead of once per message instance.
+  * Improved performance on text message parsing.
+  * Allow add() to forward keyword arguments to the concrete class.
+      E.g. instead of
+        item = repeated_field.add()
+        item.foo = bar
+        item.baz = quux
+      You can do:
+        repeated_field.add(foo=bar, baz=quux)
+  * Added a sort() interface to the BaseContainer.
+  * Added an extend() method to repeated composite fields.
+  * Added UTF8 debug string support.
+
+2010-01-08 version 2.3.0:
+
+  General
+  * Parsers for repeated numeric fields now always accept both packed and
+    unpacked input.  The [packed=true] option only affects serializers.
+    Therefore, it is possible to switch a field to packed format without
+    breaking backwards-compatibility -- as long as all parties are using
+    protobuf 2.3.0 or above, at least.
+  * The generic RPC service code generated by the C++, Java, and Python
+    generators can be disabled via file options:
+      option cc_generic_services = false;
+      option java_generic_services = false;
+      option py_generic_services = false;
+    This allows plugins to generate alternative code, possibly specific to some
+    particular RPC implementation.
+
+  protoc
+  * Now supports a plugin system for code generators.  Plugins can generate
+    code for new languages or inject additional code into the output of other
+    code generators.  Plugins are just binaries which accept a protocol buffer
+    on stdin and write a protocol buffer to stdout, so they may be written in
+    any language.  See src/google/protobuf/compiler/plugin.proto.
+    **WARNING**:  Plugins are experimental.  The interface may change in a
+    future version.
+  * If the output location ends in .zip or .jar, protoc will write its output
+    to a zip/jar archive instead of a directory.  For example:
+      protoc --java_out=myproto_srcs.jar --python_out=myproto.zip myproto.proto
+    Currently the archive contents are not compressed, though this could change
+    in the future.
+  * inf, -inf, and nan can now be used as default values for float and double
+    fields.
+
+  C++
+  * Various speed and code size optimizations.
+  * DynamicMessageFactory is now fully thread-safe.
+  * Message::Utf8DebugString() method is like DebugString() but avoids escaping
+    UTF-8 bytes.
+  * Compiled-in message types can now contain dynamic extensions, through use
+    of CodedInputStream::SetExtensionRegistry().
+  * Now compiles shared libraries (DLLs) by default on Cygwin and MinGW, to
+    match other platforms.  Use --disable-shared to avoid this.
+
+  Java
+  * parseDelimitedFrom() and mergeDelimitedFrom() now detect EOF and return
+    false/null instead of throwing an exception.
+  * Fixed some initialization ordering bugs.
+  * Fixes for OpenJDK 7.
+
+  Python
+  * 10-25 times faster than 2.2.0, still pure-Python.
+  * Calling a mutating method on a sub-message always instantiates the message
+    in its parent even if the mutating method doesn't actually mutate anything
+    (e.g. parsing from an empty string).
+  * Expanded descriptors a bit.
+
+2009-08-11 version 2.2.0:
+
+  C++
+  * Lite mode:  The "optimize_for = LITE_RUNTIME" option causes the compiler
+    to generate code which only depends libprotobuf-lite, which is much smaller
+    than libprotobuf but lacks descriptors, reflection, and some other features.
+  * Fixed bug where Message.Swap(Message) was only implemented for
+    optimize_for_speed.  Swap now properly implemented in both modes
+    (Issue 91).
+  * Added RemoveLast and SwapElements(index1, index2) to Reflection
+    interface for repeated elements.
+  * Added Swap(Message) to Reflection interface.
+  * Floating-point literals in generated code that are intended to be
+    single-precision now explicitly have 'f' suffix to avoid pedantic warnings
+    produced by some compilers.
+  * The [deprecated=true] option now causes the C++ code generator to generate
+    a GCC-style deprecation annotation (no-op on other compilers).
+  * google::protobuf::GetEnumDescriptor<SomeGeneratedEnumType>() returns the
+    EnumDescriptor for that type -- useful for templates which cannot call
+    SomeGeneratedEnumType_descriptor().
+  * Various optimizations and obscure bug fixes.
+
+  Java
+  * Lite mode:  The "optimize_for = LITE_RUNTIME" option causes the compiler
+    to generate code which only depends libprotobuf-lite, which is much smaller
+    than libprotobuf but lacks descriptors, reflection, and some other features.
+  * Lots of style cleanups.
+
+  Python
+  * Fixed endianness bug with floats and doubles.
+  * Text format parsing support.
+  * Fix bug with parsing packed repeated fields in embedded messages.
+  * Ability to initialize fields by passing keyword args to constructor.
+  * Support iterators in extend and __setslice__ for containers.
+
+2009-05-13 version 2.1.0:
+
+  General
+  * Repeated fields of primitive types (types other that string, group, and
+    nested messages) may now use the option [packed = true] to get a more
+    efficient encoding.  In the new encoding, the entire list is written
+    as a single byte blob using the "length-delimited" wire type.  Within
+    this blob, the individual values are encoded the same way they would
+    be normally except without a tag before each value (thus, they are
+    tightly "packed").
+  * For each field, the generated code contains an integer constant assigned
+    to the field number.  For example, the .proto file:
+      message Foo { optional int bar_baz = 123; }
+    would generate the following constants, all with the integer value 123:
+      C++:     Foo::kBarBazFieldNumber
+      Java:    Foo.BAR_BAZ_FIELD_NUMBER
+      Python:  Foo.BAR_BAZ_FIELD_NUMBER
+    Constants are also generated for extensions, with the same naming scheme.
+    These constants may be used as switch cases.
+  * Updated bundled Google Test to version 1.3.0.  Google Test is now bundled
+    in its verbatim form as a nested autoconf package, so you can drop in any
+    other version of Google Test if needed.
+  * optimize_for = SPEED is now the default, by popular demand.  Use
+    optimize_for = CODE_SIZE if code size is more important in your app.
+  * It is now an error to define a default value for a repeated field.
+    Previously, this was silently ignored (it had no effect on the generated
+    code).
+  * Fields can now be marked deprecated like:
+      optional int32 foo = 1 [deprecated = true];
+    Currently this does not have any actual effect, but in the future the code
+    generators may generate deprecation annotations in each language.
+  * Cross-compiling should now be possible using the --with-protoc option to
+    configure.  See README.txt for more info.
+
+  protoc
+  * --error_format=msvs option causes errors to be printed in Visual Studio
+    format, which should allow them to be clicked on in the build log to go
+    directly to the error location.
+  * The type name resolver will no longer resolve type names to fields.  For
+    example, this now works:
+      message Foo {}
+      message Bar {
+        optional int32 Foo = 1;
+        optional Foo baz = 2;
+      }
+    Previously, the type of "baz" would resolve to "Bar.Foo", and you'd get
+    an error because Bar.Foo is a field, not a type.  Now the type of "baz"
+    resolves to the message type Foo.  This change is unlikely to make a
+    difference to anyone who follows the Protocol Buffers style guide.
+
+  C++
+  * Several optimizations, including but not limited to:
+    - Serialization, especially to flat arrays, is 10%-50% faster, possibly
+      more for small objects.
+    - Several descriptor operations which previously required locking no longer
+      do.
+    - Descriptors are now constructed lazily on first use, rather than at
+      process startup time.  This should save memory in programs which do not
+      use descriptors or reflection.
+    - UnknownFieldSet completely redesigned to be more efficient (especially in
+      terms of memory usage).
+    - Various optimizations to reduce code size (though the serialization speed
+      optimizations increased code size).
+  * Message interface has method ParseFromBoundedZeroCopyStream() which parses
+    a limited number of bytes from an input stream rather than parsing until
+    EOF.
+  * GzipInputStream and GzipOutputStream support reading/writing gzip- or
+    zlib-compressed streams if zlib is available.
+    (google/protobuf/io/gzip_stream.h)
+  * DescriptorPool::FindAllExtensions() and corresponding
+    DescriptorDatabase::FindAllExtensions() can be used to enumerate all
+    extensions of a given type.
+  * For each enum type Foo, protoc will generate functions:
+      const string& Foo_Name(Foo value);
+      bool Foo_Parse(const string& name, Foo* result);
+    The former returns the name of the enum constant corresponding to the given
+    value while the latter finds the value corresponding to a name.
+  * RepeatedField and RepeatedPtrField now have back-insertion iterators.
+  * String fields now have setters that take a char* and a size, in addition
+    to the existing ones that took char* or const string&.
+  * DescriptorPool::AllowUnknownDependencies() may be used to tell
+    DescriptorPool to create placeholder descriptors for unknown entities
+    referenced in a FileDescriptorProto.  This can allow you to parse a .proto
+    file without having access to other .proto files that it imports, for
+    example.
+  * Updated gtest to latest version.  The gtest package is now included as a
+    nested autoconf package, so it should be able to drop new versions into the
+    "gtest" subdirectory without modification.
+
+  Java
+  * Fixed bug where Message.mergeFrom(Message) failed to merge extensions.
+  * Message interface has new method toBuilder() which is equivalent to
+    newBuilderForType().mergeFrom(this).
+  * All enums now implement the ProtocolMessageEnum interface.
+  * Setting a field to null now throws NullPointerException.
+  * Fixed tendency for TextFormat's parsing to overflow the stack when
+    parsing large string values.  The underlying problem is with Java's
+    regex implementation (which unfortunately uses recursive backtracking
+    rather than building an NFA).  Worked around by making use of possessive
+    quantifiers.
+  * Generated service classes now also generate pure interfaces.  For a service
+    Foo, Foo.Interface is a pure interface containing all of the service's
+    defined methods.  Foo.newReflectiveService() can be called to wrap an
+    instance of this interface in a class that implements the generic
+    RpcService interface, which provides reflection support that is usually
+    needed by RPC server implementations.
+  * RPC interfaces now support blocking operation in addition to non-blocking.
+    The protocol compiler generates separate blocking and non-blocking stubs
+    which operate against separate blocking and non-blocking RPC interfaces.
+    RPC implementations will have to implement the new interfaces in order to
+    support blocking mode.
+  * New I/O methods parseDelimitedFrom(), mergeDelimitedFrom(), and
+    writeDelimitedTo() read and write "delimited" messages from/to a stream,
+    meaning that the message size precedes the data.  This way, you can write
+    multiple messages to a stream without having to worry about delimiting
+    them yourself.
+  * Throw a more descriptive exception when build() is double-called.
+  * Add a method to query whether CodedInputStream is at the end of the input
+    stream.
+  * Add a method to reset a CodedInputStream's size counter; useful when
+    reading many messages with the same stream.
+  * equals() and hashCode() now account for unknown fields.
+
+  Python
+  * Added slicing support for repeated scalar fields. Added slice retrieval and
+    removal of repeated composite fields.
+  * Updated RPC interfaces to allow for blocking operation.  A client may
+    now pass None for a callback when making an RPC, in which case the
+    call will block until the response is received, and the response
+    object will be returned directly to the caller.  This interface change
+    cannot be used in practice until RPC implementations are updated to
+    implement it.
+  * Changes to input_stream.py should make protobuf compatible with appengine.
+
+2008-11-25 version 2.0.3:
+
+  protoc
+  * Enum values may now have custom options, using syntax similar to field
+    options.
+  * Fixed bug where .proto files which use custom options but don't actually
+    define them (i.e. they import another .proto file defining the options)
+    had to explicitly import descriptor.proto.
+  * Adjacent string literals in .proto files will now be concatenated, like in
+    C.
+  * If an input file is a Windows absolute path (e.g. "C:\foo\bar.proto") and
+    the import path only contains "." (or contains "." but does not contain
+    the file), protoc incorrectly thought that the file was under ".", because
+    it thought that the path was relative (since it didn't start with a slash).
+    This has been fixed.
+
+  C++
+  * Generated message classes now have a Swap() method which efficiently swaps
+    the contents of two objects.
+  * All message classes now have a SpaceUsed() method which returns an estimate
+    of the number of bytes of allocated memory currently owned by the object.
+    This is particularly useful when you are reusing a single message object
+    to improve performance but want to make sure it doesn't bloat up too large.
+  * New method Message::SerializeAsString() returns a string containing the
+    serialized data.  May be more convenient than calling
+    SerializeToString(string*).
+  * In debug mode, log error messages when string-type fields are found to
+    contain bytes that are not valid UTF-8.
+  * Fixed bug where a message with multiple extension ranges couldn't parse
+    extensions.
+  * Fixed bug where MergeFrom(const Message&) didn't do anything if invoked on
+    a message that contained no fields (but possibly contained extensions).
+  * Fixed ShortDebugString() to not be O(n^2).  Durr.
+  * Fixed crash in TextFormat parsing if the first token in the input caused a
+    tokenization error.
+  * Fixed obscure bugs in zero_copy_stream_impl.cc.
+  * Added support for HP C++ on Tru64.
+  * Only build tests on "make check", not "make".
+  * Fixed alignment issue that caused crashes when using DynamicMessage on
+    64-bit Sparc machines.
+  * Simplify template usage to work with MSVC 2003.
+  * Work around GCC 4.3.x x86_64 compiler bug that caused crashes on startup.
+    (This affected Fedora 9 in particular.)
+  * Now works on "Solaris 10 using recent Sun Studio".
+
+  Java
+  * New overload of mergeFrom() which parses a slice of a byte array instead
+    of the whole thing.
+  * New method ByteString.asReadOnlyByteBuffer() does what it sounds like.
+  * Improved performance of isInitialized() when optimizing for code size.
+
+  Python
+  * Corrected ListFields() signature in Message base class to match what
+    subclasses actually implement.
+  * Some minor refactoring.
+  * Don't pass self as first argument to superclass constructor (no longer
+    allowed in Python 2.6).
+
+2008-09-29 version 2.0.2:
+
+  General
+  * License changed from Apache 2.0 to New BSD.
+  * It is now possible to define custom "options", which are basically
+    annotations which may be placed on definitions in a .proto file.
+    For example, you might define a field option called "foo" like so:
+      import "google/protobuf/descriptor.proto"
+      extend google.protobuf.FieldOptions {
+        optional string foo = 12345;
+      }
+    Then you annotate a field using the "foo" option:
+      message MyMessage {
+        optional int32 some_field = 1 [(foo) = "bar"]
+      }
+    The value of this option is then visible via the message's
+    Descriptor:
+      const FieldDescriptor* field =
+        MyMessage::descriptor()->FindFieldByName("some_field");
+      assert(field->options().GetExtension(foo) == "bar");
+    This feature has been implemented and tested in C++ and Java.
+    Other languages may or may not need to do extra work to support
+    custom options, depending on how they construct descriptors.
+
+  C++
+  * Fixed some GCC warnings that only occur when using -pedantic.
+  * Improved static initialization code, making ordering more
+    predictable among other things.
+  * TextFormat will no longer accept messages which contain multiple
+    instances of a singular field.  Previously, the latter instance
+    would overwrite the former.
+  * Now works on systems that don't have hash_map.
+
+  Java
+  * Print @Override annotation in generated code where appropriate.
+
+  Python
+  * Strings now use the "unicode" type rather than the "str" type.
+    String fields may still be assigned ASCII "str" values; they will
+    automatically be converted.
+  * Adding a property to an object representing a repeated field now
+    raises an exception.  For example:
+      # No longer works (and never should have).
+      message.some_repeated_field.foo = 1
+
+  Windows
+  * We now build static libraries rather than DLLs by default on MSVC.
+    See vsprojects/readme.txt for more information.
+
+2008-08-15 version 2.0.1:
+
+  protoc
+  * New flags --encode and --decode can be used to convert between protobuf text
+    format and binary format from the command-line.
+  * New flag --descriptor_set_out can be used to write FileDescriptorProtos for
+    all parsed files directly into a single output file.  This is particularly
+    useful if you wish to parse .proto files from programs written in languages
+    other than C++: just run protoc as a background process and have it output
+    a FileDescriptorList, then parse that natively.
+  * Improved error message when an enum value's name conflicts with another
+    symbol defined in the enum type's scope, e.g. if two enum types declared
+    in the same scope have values with the same name.  This is disallowed for
+    compatibility with C++, but this wasn't clear from the error.
+  * Fixed absolute output paths on Windows.
+  * Allow trailing slashes in --proto_path mappings.
+
+  C++
+  * Reflection objects are now per-class rather than per-instance.  To make this
+    possible, the Reflection interface had to be changed such that all methods
+    take the Message instance as a parameter.  This change improves performance
+    significantly in memory-bandwidth-limited use cases, since it makes the
+    message objects smaller.  Note that source-incompatible interface changes
+    like this will not be made again after the library leaves beta.
+  * Heuristically detect sub-messages when printing unknown fields.
+  * Fix static initialization ordering bug that caused crashes at startup when
+    compiling on Mac with static linking.
+  * Fixed TokenizerTest when compiling with -DNDEBUG on Linux.
+  * Fixed incorrect definition of kint32min.
+  * Fix bytes type setter to work with byte sequences with embedded NULLs.
+  * Other irrelevant tweaks.
+
+  Java
+  * Fixed UnknownFieldSet's parsing of varints larger than 32 bits.
+  * Fixed TextFormat's parsing of "inf" and "nan".
+  * Fixed TextFormat's parsing of comments.
+  * Added info to Java POM that will be required when we upload the
+    package to a Maven repo.
+
+  Python
+  * MergeFrom(message) and CopyFrom(message) are now implemented.
+  * SerializeToString() raises an exception if the message is missing required
+    fields.
+  * Code organization improvements.
+  * Fixed doc comments for RpcController and RpcChannel, which had somehow been
+    swapped.
+  * Fixed text_format_test on Windows where floating-point exponents sometimes
+    contain extra zeros.
+  * Fix Python service CallMethod() implementation.
+
+  Other
+  * Improved readmes.
+  * VIM syntax highlighting improvements.
+
+2008-07-07 version 2.0.0:
+
+  * First public release.
diff --git a/src/third_party/protobuf-3/CONTRIBUTORS.txt b/src/third_party/protobuf-3/CONTRIBUTORS.txt
new file mode 100644
index 0000000..b8d97fc
--- /dev/null
+++ b/src/third_party/protobuf-3/CONTRIBUTORS.txt
@@ -0,0 +1,102 @@
+This file contains a list of people who have made large contributions
+to the public version of Protocol Buffers.
+
+Original Protocol Buffers design and implementation:
+  Sanjay Ghemawat <sanjay@google.com>
+  Jeff Dean <jeff@google.com>
+  Daniel Dulitz <daniel@google.com>
+  Craig Silverstein
+  Paul Haahr <haahr@google.com>
+  Corey Anderson <corin@google.com>
+  (and many others)
+
+Proto2 C++ and Java primary author:
+  Kenton Varda <kenton@google.com>
+
+Proto2 Python primary authors:
+  Will Robinson <robinson@google.com>
+  Petar Petrov <petar@google.com>
+
+Java Nano primary authors:
+  Brian Duff <bduff@google.com>
+  Tom Chao <chaot@google.com>
+  Max Cai <maxtroy@google.com>
+  Ulas Kirazci <ulas@google.com>
+
+Large code contributions:
+  Jason Hsueh <jasonh@google.com>
+  Joseph Schorr <jschorr@google.com>
+  Wenbo Zhu <wenboz@google.com>
+
+Large quantity of code reviews:
+  Scott Bruce <sbruce@google.com>
+  Frank Yellin
+  Neal Norwitz <nnorwitz@google.com>
+  Jeffrey Yasskin <jyasskin@google.com>
+  Ambrose Feinstein <ambrose@google.com>
+
+Documentation:
+  Lisa Carey <lcarey@google.com>
+
+Maven packaging:
+  Gregory Kick <gak@google.com>
+
+Patch contributors:
+  Kevin Ko <kevin.s.ko@gmail.com>
+    * Small patch to handle trailing slashes in --proto_path flag.
+  Johan Euphrosine <proppy@aminche.com>
+    * Small patch to fix Python CallMethod().
+  Ulrich Kunitz <kune@deine-taler.de>
+    * Small optimizations to Python serialization.
+  Leandro Lucarella <llucax@gmail.com>
+    * VI syntax highlighting tweaks.
+    * Fix compiler to not make output executable.
+  Dilip Joseph <dilip.antony.joseph@gmail.com>
+    * Heuristic detection of sub-messages when printing unknown fields in
+      text format.
+  Brian Atkinson <nairb774@gmail.com>
+    * Added @Override annotation to generated Java code where appropriate.
+  Vincent Choinière <Choiniere.Vincent@hydro.qc.ca>
+    * Tru64 support.
+  Monty Taylor <monty.taylor@gmail.com>
+    * Solaris 10 + Sun Studio fixes.
+  Alek Storm <alek.storm@gmail.com>
+    * Slicing support for repeated scalar fields for the Python API.
+  Oleg Smolsky <oleg.smolsky@gmail.com>
+    * MS Visual Studio error format option.
+    * Detect unordered_map in stl_hash.m4.
+  Brian Olson <brianolson@google.com>
+    * gzip/zlib I/O support.
+  Michael Poole <mdpoole@troilus.org>
+    * Fixed warnings about generated constructors not explicitly initializing
+      all fields (only present with certain compiler settings).
+    * Added generation of field number constants.
+  Wink Saville <wink@google.com>
+    * Fixed initialization ordering problem in logging code.
+  Will Pierce <willp@nuclei.com>
+    * Small patch improving performance of in Python serialization.
+  Alexandre Vassalotti <alexandre@peadrop.com>
+    * Emacs mode for Protocol Buffers (editors/protobuf-mode.el).
+  Scott Stafford <scott.stafford@gmail.com>
+    * Added Swap(), SwapElements(), and RemoveLast() to Reflection interface.
+  Alexander Melnikov <alm@sibmail.ru>
+    * HPUX support.
+  Oliver Jowett <oliver.jowett@gmail.com>
+    * Detect whether zlib is new enough in configure script.
+    * Fixes for Solaris 10 32/64-bit confusion.
+  Evan Jones <evanj@mit.edu>
+    * Optimize Java serialization code when writing a small message to a stream.
+    * Optimize Java serialization of strings so that UTF-8 encoding happens only
+      once per string per serialization call.
+    * Clean up some Java warnings.
+    * Fix bug with permanent callbacks that delete themselves when run.
+  Michael Kucharski <m.kucharski@gmail.com>
+    * Added CodedInputStream.getTotalBytesRead().
+  Kacper Kowalik <xarthisius.kk@gmail.com>
+    * Fixed m4/acx_pthread.m4 problem for some Linux distributions.
+  William Orr <will@worrbase.com>
+    * Fixed detection of sched_yield on Solaris.
+    * Added atomicops for Solaris
+  Andrew Paprocki <andrew@ishiboo.com>
+    * Fixed minor IBM xlC compiler build issues
+    * Added atomicops for AIX (POWER)
diff --git a/src/third_party/protobuf-3/LICENSE b/src/third_party/protobuf-3/LICENSE
new file mode 100644
index 0000000..f028c82
--- /dev/null
+++ b/src/third_party/protobuf-3/LICENSE
@@ -0,0 +1,42 @@
+This license applies to all parts of Protocol Buffers except the following:
+
+  - Atomicops support for generic gcc, located in
+    src/google/protobuf/stubs/atomicops_internals_generic_gcc.h.
+    This file is copyrighted by Red Hat Inc.
+
+  - Atomicops support for AIX/POWER, located in
+    src/google/protobuf/stubs/atomicops_internals_power.h.
+    This file is copyrighted by Bloomberg Finance LP.
+
+Copyright 2014, Google Inc.  All rights reserved.
+
+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.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
diff --git a/src/third_party/protobuf-3/Makefile.am b/src/third_party/protobuf-3/Makefile.am
new file mode 100644
index 0000000..3e98881
--- /dev/null
+++ b/src/third_party/protobuf-3/Makefile.am
@@ -0,0 +1,769 @@
+## Process this file with automake to produce Makefile.in
+
+ACLOCAL_AMFLAGS = -I m4
+
+AUTOMAKE_OPTIONS = foreign
+
+# Build . before src so that our all-local and clean-local hooks kicks in at
+# the right time.
+SUBDIRS = . src
+
+# Always include gmock in distributions.
+DIST_SUBDIRS = $(subdirs) src conformance benchmarks
+
+# Build gmock before we build protobuf tests.  We don't add gmock to SUBDIRS
+# because then "make check" would also build and run all of gmock's own tests,
+# which takes a lot of time and is generally not useful to us.  Also, we don't
+# want "make install" to recurse into gmock since we don't want to overwrite
+# the installed version of gmock if there is one.
+check-local:
+	@echo "Making lib/libgmock.a lib/libgmock_main.a in gmock"
+	@cd gmock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la
+	@cd gmock/gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la
+
+# We would like to clean gmock when "make clean" is invoked.  But we have to
+# be careful because clean-local is also invoked during "make distclean", but
+# "make distclean" already recurses into gmock because it's listed among the
+# DIST_SUBDIRS.  distclean will delete gmock/Makefile, so if we then try to
+# cd to the directory again and "make clean" it will fail.  So, check that the
+# Makefile exists before recursing.
+clean-local:
+	@if test -e gmock/Makefile; then \
+	  echo "Making clean in gmock"; \
+	  cd gmock && $(MAKE) $(AM_MAKEFLAGS) clean; \
+	fi; \
+	if test -e conformance/Makefile; then \
+	  echo "Making clean in conformance"; \
+	  cd conformance && $(MAKE) $(AM_MAKEFLAGS) clean; \
+	fi; \
+	if test -e benchmarks/Makefile; then \
+	  echo "Making clean in benchmarks"; \
+	  cd benchmarks && $(MAKE) $(AM_MAKEFLAGS) clean; \
+	fi; \
+	if test -e objectivec/DevTools; then \
+	  echo "Cleaning any ObjC pyc files"; \
+	  rm -f objectivec/DevTools/*.pyc; \
+	fi
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = protobuf.pc protobuf-lite.pc
+
+csharp_EXTRA_DIST=                                                           \
+  csharp/.gitignore                                                          \
+  csharp/CHANGES.txt                                                         \
+  csharp/README.md                                                           \
+  csharp/build_packages.bat                                                  \
+  csharp/buildall.sh                                                         \
+  csharp/generate_protos.sh                                                  \
+  csharp/keys/Google.Protobuf.public.snk                                     \
+  csharp/keys/README.md                                                      \
+  csharp/protos/unittest_issues.proto                                        \
+  csharp/src/AddressBook/AddPerson.cs                                        \
+  csharp/src/AddressBook/AddressBook.csproj                                  \
+  csharp/src/AddressBook/Addressbook.cs                                      \
+  csharp/src/AddressBook/ListPeople.cs                                       \
+  csharp/src/AddressBook/Program.cs                                          \
+  csharp/src/AddressBook/Properties/AssemblyInfo.cs                          \
+  csharp/src/AddressBook/SampleUsage.cs                                      \
+  csharp/src/AddressBook/app.config                                          \
+  csharp/src/Google.Protobuf.Conformance/App.config                          \
+  csharp/src/Google.Protobuf.Conformance/Conformance.cs                      \
+  csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj  \
+  csharp/src/Google.Protobuf.Conformance/Program.cs                          \
+  csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs          \
+  csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj        \
+  csharp/src/Google.Protobuf.JsonDump/Program.cs                             \
+  csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs             \
+  csharp/src/Google.Protobuf.JsonDump/app.config                             \
+  csharp/src/Google.Protobuf.Test/ByteStringTest.cs                          \
+  csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs              \
+  csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs                    \
+  csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs                   \
+  csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs                \
+  csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs           \
+  csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
+  csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs        \
+  csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs                    \
+  csharp/src/Google.Protobuf.Test/EqualityTester.cs                          \
+  csharp/src/Google.Protobuf.Test/FieldCodecTest.cs                          \
+  csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs                    \
+  csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj                \
+  csharp/src/Google.Protobuf.Test/IssuesTest.cs                              \
+  csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs                       \
+  csharp/src/Google.Protobuf.Test/JsonParserTest.cs                          \
+  csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs                       \
+  csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml                 \
+  csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs                 \
+  csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs              \
+  csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs              \
+  csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs             \
+  csharp/src/Google.Protobuf.Test/SampleEnum.cs                              \
+  csharp/src/Google.Protobuf.Test/SampleMessages.cs                          \
+  csharp/src/Google.Protobuf.Test/TestCornerCases.cs                         \
+  csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs            \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs         \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs   \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs               \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs               \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs       \
+  csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs                  \
+  csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs             \
+  csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs            \
+  csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs             \
+  csharp/src/Google.Protobuf.Test/packages.config                            \
+  csharp/src/Google.Protobuf.sln                                             \
+  csharp/src/Google.Protobuf/ByteArray.cs                                    \
+  csharp/src/Google.Protobuf/ByteString.cs                                   \
+  csharp/src/Google.Protobuf/CodedInputStream.cs                             \
+  csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs                \
+  csharp/src/Google.Protobuf/CodedOutputStream.cs                            \
+  csharp/src/Google.Protobuf/Collections/MapField.cs                         \
+  csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
+  csharp/src/Google.Protobuf/Collections/RepeatedField.cs                    \
+  csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs         \
+  csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs                 \
+  csharp/src/Google.Protobuf/FieldCodec.cs                                   \
+  csharp/src/Google.Protobuf/FrameworkPortability.cs                         \
+  csharp/src/Google.Protobuf/Google.Protobuf.csproj                          \
+  csharp/src/Google.Protobuf/Google.Protobuf.nuspec                          \
+  csharp/src/Google.Protobuf/IDeepCloneable.cs                               \
+  csharp/src/Google.Protobuf/IMessage.cs                                     \
+  csharp/src/Google.Protobuf/InvalidJsonException.cs                         \
+  csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs               \
+  csharp/src/Google.Protobuf/JsonFormatter.cs                                \
+  csharp/src/Google.Protobuf/JsonParser.cs                                   \
+  csharp/src/Google.Protobuf/JsonToken.cs                                    \
+  csharp/src/Google.Protobuf/JsonTokenizer.cs                                \
+  csharp/src/Google.Protobuf/LimitedInputStream.cs                           \
+  csharp/src/Google.Protobuf/MessageExtensions.cs                            \
+  csharp/src/Google.Protobuf/MessageParser.cs                                \
+  csharp/src/Google.Protobuf/ProtoPreconditions.cs                           \
+  csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs                      \
+  csharp/src/Google.Protobuf/Reflection/Descriptor.cs                        \
+  csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs     \
+  csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs               \
+  csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs                 \
+  csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs                   \
+  csharp/src/Google.Protobuf/Reflection/FieldType.cs                         \
+  csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs              \
+  csharp/src/Google.Protobuf/Reflection/IDescriptor.cs                       \
+  csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs                  \
+  csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs                  \
+  csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs                     \
+  csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs                   \
+  csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs             \
+  csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/PartialClasses.cs                    \
+  csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs                    \
+  csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs             \
+  csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs               \
+  csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs                      \
+  csharp/src/Google.Protobuf/WellKnownTypes/Any.cs                           \
+  csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs                    \
+  csharp/src/Google.Protobuf/WellKnownTypes/Api.cs                           \
+  csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs                      \
+  csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs               \
+  csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs                         \
+  csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs                     \
+  csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs                 \
+  csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs                        \
+  csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs                \
+  csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs                     \
+  csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs              \
+  csharp/src/Google.Protobuf/WellKnownTypes/Type.cs                          \
+  csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs                  \
+  csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs                      \
+  csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs               \
+  csharp/src/Google.Protobuf/WireFormat.cs                                   \
+  csharp/src/Google.Protobuf/packages.config                                 \
+  csharp/src/packages/repositories.config
+
+java_EXTRA_DIST=                                                                   \
+  java/README.md                                                                   \
+  java/core/generate-sources-build.xml                                             \
+  java/core/generate-test-sources-build.xml                                        \
+  java/core/pom.xml                                                                \
+  java/core/src/main/java/com/google/protobuf/AbstractMessage.java                 \
+  java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java             \
+  java/core/src/main/java/com/google/protobuf/AbstractParser.java                  \
+  java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java            \
+  java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java              \
+  java/core/src/main/java/com/google/protobuf/BlockingService.java                 \
+  java/core/src/main/java/com/google/protobuf/BooleanArrayList.java                \
+  java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java                \
+  java/core/src/main/java/com/google/protobuf/ByteOutput.java                      \
+  java/core/src/main/java/com/google/protobuf/ByteString.java                      \
+  java/core/src/main/java/com/google/protobuf/CodedInputStream.java                \
+  java/core/src/main/java/com/google/protobuf/CodedOutputStream.java               \
+  java/core/src/main/java/com/google/protobuf/Descriptors.java                     \
+  java/core/src/main/java/com/google/protobuf/DoubleArrayList.java                 \
+  java/core/src/main/java/com/google/protobuf/DynamicMessage.java                  \
+  java/core/src/main/java/com/google/protobuf/Extension.java                       \
+  java/core/src/main/java/com/google/protobuf/ExtensionLite.java                   \
+  java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java               \
+  java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java           \
+  java/core/src/main/java/com/google/protobuf/FieldSet.java                        \
+  java/core/src/main/java/com/google/protobuf/FloatArrayList.java                  \
+  java/core/src/main/java/com/google/protobuf/GeneratedMessage.java                \
+  java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java            \
+  java/core/src/main/java/com/google/protobuf/IntArrayList.java                    \
+  java/core/src/main/java/com/google/protobuf/Internal.java                        \
+  java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java  \
+  java/core/src/main/java/com/google/protobuf/LazyField.java                       \
+  java/core/src/main/java/com/google/protobuf/LazyFieldLite.java                   \
+  java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java             \
+  java/core/src/main/java/com/google/protobuf/LazyStringList.java                  \
+  java/core/src/main/java/com/google/protobuf/LongArrayList.java                   \
+  java/core/src/main/java/com/google/protobuf/MapEntry.java                        \
+  java/core/src/main/java/com/google/protobuf/MapEntryLite.java                    \
+  java/core/src/main/java/com/google/protobuf/MapField.java                        \
+  java/core/src/main/java/com/google/protobuf/MapFieldLite.java                    \
+  java/core/src/main/java/com/google/protobuf/Message.java                         \
+  java/core/src/main/java/com/google/protobuf/MessageLite.java                     \
+  java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java            \
+  java/core/src/main/java/com/google/protobuf/MessageLiteToString.java             \
+  java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java                \
+  java/core/src/main/java/com/google/protobuf/MessageReflection.java               \
+  java/core/src/main/java/com/google/protobuf/MutabilityOracle.java                \
+  java/core/src/main/java/com/google/protobuf/NioByteString.java                   \
+  java/core/src/main/java/com/google/protobuf/Parser.java                          \
+  java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java               \
+  java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java             \
+  java/core/src/main/java/com/google/protobuf/ProtocolStringList.java              \
+  java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java            \
+  java/core/src/main/java/com/google/protobuf/RopeByteString.java                  \
+  java/core/src/main/java/com/google/protobuf/RpcCallback.java                     \
+  java/core/src/main/java/com/google/protobuf/RpcChannel.java                      \
+  java/core/src/main/java/com/google/protobuf/RpcController.java                   \
+  java/core/src/main/java/com/google/protobuf/RpcUtil.java                         \
+  java/core/src/main/java/com/google/protobuf/Service.java                         \
+  java/core/src/main/java/com/google/protobuf/ServiceException.java                \
+  java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java              \
+  java/core/src/main/java/com/google/protobuf/SmallSortedMap.java                  \
+  java/core/src/main/java/com/google/protobuf/TextFormat.java                      \
+  java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java               \
+  java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java         \
+  java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java         \
+  java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java   \
+  java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java                 \
+  java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java             \
+  java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java      \
+  java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java            \
+  java/core/src/main/java/com/google/protobuf/Utf8.java                            \
+  java/core/src/main/java/com/google/protobuf/WireFormat.java                      \
+  java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java             \
+  java/core/src/test/java/com/google/protobuf/AnyTest.java                         \
+  java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java            \
+  java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java           \
+  java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java            \
+  java/core/src/test/java/com/google/protobuf/ByteStringTest.java                  \
+  java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java                   \
+  java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java            \
+  java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java           \
+  java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java             \
+  java/core/src/test/java/com/google/protobuf/DescriptorsTest.java                 \
+  java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java             \
+  java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java              \
+  java/core/src/test/java/com/google/protobuf/EnumTest.java                        \
+  java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java               \
+  java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java              \
+  java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java        \
+  java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java            \
+  java/core/src/test/java/com/google/protobuf/IntArrayListTest.java                \
+  java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java                 \
+  java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java             \
+  java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java               \
+  java/core/src/test/java/com/google/protobuf/LazyFieldTest.java                   \
+  java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java             \
+  java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java         \
+  java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java          \
+  java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java           \
+  java/core/src/test/java/com/google/protobuf/LiteTest.java                        \
+  java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java           \
+  java/core/src/test/java/com/google/protobuf/LongArrayListTest.java               \
+  java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java            \
+  java/core/src/test/java/com/google/protobuf/MapForProto2Test.java                \
+  java/core/src/test/java/com/google/protobuf/MapTest.java                         \
+  java/core/src/test/java/com/google/protobuf/MessageTest.java                     \
+  java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java              \
+  java/core/src/test/java/com/google/protobuf/NioByteStringTest.java               \
+  java/core/src/test/java/com/google/protobuf/ParserTest.java                      \
+  java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java           \
+  java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java        \
+  java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java     \
+  java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java              \
+  java/core/src/test/java/com/google/protobuf/ServiceTest.java                     \
+  java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java          \
+  java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java              \
+  java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java              \
+  java/core/src/test/java/com/google/protobuf/TestUtil.java                        \
+  java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java     \
+  java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java     \
+  java/core/src/test/java/com/google/protobuf/TextFormatTest.java                  \
+  java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java            \
+  java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java         \
+  java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java             \
+  java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java  \
+  java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java              \
+  java/core/src/test/java/com/google/protobuf/WireFormatTest.java                  \
+  java/core/src/test/proto/com/google/protobuf/any_test.proto                      \
+  java/core/src/test/proto/com/google/protobuf/field_presence_test.proto           \
+  java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto              \
+  java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto          \
+  java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto      \
+  java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto           \
+  java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto \
+  java/core/src/test/proto/com/google/protobuf/map_test.proto                      \
+  java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto           \
+  java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto          \
+  java/core/src/test/proto/com/google/protobuf/nested_extension.proto              \
+  java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto         \
+  java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto          \
+  java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto     \
+  java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto         \
+  java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto        \
+  java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto        \
+  java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto          \
+  java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto               \
+  java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto          \
+  java/core/src/test/proto/com/google/protobuf/test_custom_options.proto           \
+  java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto         \
+  java/lite/pom.xml                                                                \
+  java/pom.xml                                                                     \
+  java/util/pom.xml                                                                \
+  java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java              \
+  java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java              \
+  java/util/src/main/java/com/google/protobuf/util/JsonFormat.java                 \
+  java/util/src/main/java/com/google/protobuf/util/TimeUtil.java                   \
+  java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java          \
+  java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java          \
+  java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java             \
+  java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java               \
+  java/util/src/test/proto/com/google/protobuf/util/json_test.proto
+
+javanano_EXTRA_DIST=                                                                      \
+  javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java          \
+  javanano/src/main/java/com/google/protobuf/nano/FieldData.java                          \
+  javanano/src/main/java/com/google/protobuf/nano/FieldArray.java                         \
+  javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java                     \
+  javanano/src/main/java/com/google/protobuf/nano/Extension.java                          \
+  javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java           \
+  javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java                   \
+  javanano/src/main/java/com/google/protobuf/nano/MessageNano.java                        \
+  javanano/src/main/java/com/google/protobuf/nano/InternalNano.java                       \
+  javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java \
+  javanano/src/main/java/com/google/protobuf/nano/MapFactories.java                       \
+  javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java              \
+  javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java                 \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto          \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto     \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto                 \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto                     \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/NanoTest.java                           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto      \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto    \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto       \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto          \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto            \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto \
+  javanano/src/test/java/com/google/protobuf/nano/map_test.proto                          \
+  javanano/README.md                                                                      \
+  javanano/pom.xml
+
+objectivec_EXTRA_DIST=                                                       \
+  objectivec/DevTools/check_version_stamps.sh                                \
+  objectivec/DevTools/compile_testing_protos.sh                              \
+  objectivec/DevTools/full_mac_build.sh                                      \
+  objectivec/DevTools/pddm.py                                                \
+  objectivec/DevTools/pddm_tests.py                                          \
+  objectivec/generate_well_known_types.sh                                    \
+  objectivec/google/protobuf/Any.pbobjc.h                                    \
+  objectivec/google/protobuf/Any.pbobjc.m                                    \
+  objectivec/google/protobuf/Api.pbobjc.h                                    \
+  objectivec/google/protobuf/Api.pbobjc.m                                    \
+  objectivec/google/protobuf/Duration.pbobjc.h                               \
+  objectivec/google/protobuf/Duration.pbobjc.m                               \
+  objectivec/google/protobuf/Empty.pbobjc.h                                  \
+  objectivec/google/protobuf/Empty.pbobjc.m                                  \
+  objectivec/google/protobuf/FieldMask.pbobjc.h                              \
+  objectivec/google/protobuf/FieldMask.pbobjc.m                              \
+  objectivec/google/protobuf/SourceContext.pbobjc.h                          \
+  objectivec/google/protobuf/SourceContext.pbobjc.m                          \
+  objectivec/google/protobuf/Struct.pbobjc.h                                 \
+  objectivec/google/protobuf/Struct.pbobjc.m                                 \
+  objectivec/google/protobuf/Timestamp.pbobjc.h                              \
+  objectivec/google/protobuf/Timestamp.pbobjc.m                              \
+  objectivec/google/protobuf/Type.pbobjc.h                                   \
+  objectivec/google/protobuf/Type.pbobjc.m                                   \
+  objectivec/google/protobuf/Wrappers.pbobjc.h                               \
+  objectivec/google/protobuf/Wrappers.pbobjc.m                               \
+  objectivec/GPBArray.h                                                      \
+  objectivec/GPBArray.m                                                      \
+  objectivec/GPBArray_PackagePrivate.h                                       \
+  objectivec/GPBBootstrap.h                                                  \
+  objectivec/GPBCodedInputStream.h                                           \
+  objectivec/GPBCodedInputStream.m                                           \
+  objectivec/GPBCodedInputStream_PackagePrivate.h                            \
+  objectivec/GPBCodedOutputStream.h                                          \
+  objectivec/GPBCodedOutputStream.m                                          \
+  objectivec/GPBCodedOutputStream_PackagePrivate.h                           \
+  objectivec/GPBDescriptor.h                                                 \
+  objectivec/GPBDescriptor.m                                                 \
+  objectivec/GPBDescriptor_PackagePrivate.h                                  \
+  objectivec/GPBDictionary.h                                                 \
+  objectivec/GPBDictionary.m                                                 \
+  objectivec/GPBDictionary_PackagePrivate.h                                  \
+  objectivec/GPBExtensionInternals.h                                         \
+  objectivec/GPBExtensionInternals.m                                         \
+  objectivec/GPBExtensionRegistry.h                                          \
+  objectivec/GPBExtensionRegistry.m                                          \
+  objectivec/GPBMessage.h                                                    \
+  objectivec/GPBMessage.m                                                    \
+  objectivec/GPBMessage_PackagePrivate.h                                     \
+  objectivec/GPBProtocolBuffers.h                                            \
+  objectivec/GPBProtocolBuffers.m                                            \
+  objectivec/GPBProtocolBuffers_RuntimeSupport.h                             \
+  objectivec/GPBRootObject.h                                                 \
+  objectivec/GPBRootObject.m                                                 \
+  objectivec/GPBRootObject_PackagePrivate.h                                  \
+  objectivec/GPBRuntimeTypes.h                                               \
+  objectivec/GPBUnknownField.h                                               \
+  objectivec/GPBUnknownField.m                                               \
+  objectivec/GPBUnknownField_PackagePrivate.h                                \
+  objectivec/GPBUnknownFieldSet.h                                            \
+  objectivec/GPBUnknownFieldSet.m                                            \
+  objectivec/GPBUnknownFieldSet_PackagePrivate.h                             \
+  objectivec/GPBUtilities.h                                                  \
+  objectivec/GPBUtilities.m                                                  \
+  objectivec/GPBUtilities_PackagePrivate.h                                   \
+  objectivec/GPBWellKnownTypes.h                                             \
+  objectivec/GPBWellKnownTypes.m                                             \
+  objectivec/GPBWireFormat.h                                                 \
+  objectivec/GPBWireFormat.m                                                 \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj                   \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj                   \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+  objectivec/README.md                                                       \
+  objectivec/Tests/golden_message                                            \
+  objectivec/Tests/golden_packed_fields_message                              \
+  objectivec/Tests/GPBARCUnittestProtos.m                                    \
+  objectivec/Tests/GPBArrayTests.m                                           \
+  objectivec/Tests/GPBCodedInputStreamTests.m                                \
+  objectivec/Tests/GPBCodedOuputStreamTests.m                                \
+  objectivec/Tests/GPBConcurrencyTests.m                                     \
+  objectivec/Tests/GPBDescriptorTests.m                                      \
+  objectivec/Tests/GPBDictionaryTests+Bool.m                                 \
+  objectivec/Tests/GPBDictionaryTests+Int32.m                                \
+  objectivec/Tests/GPBDictionaryTests+Int64.m                                \
+  objectivec/Tests/GPBDictionaryTests+String.m                               \
+  objectivec/Tests/GPBDictionaryTests+UInt32.m                               \
+  objectivec/Tests/GPBDictionaryTests+UInt64.m                               \
+  objectivec/Tests/GPBDictionaryTests.pddm                                   \
+  objectivec/Tests/GPBMessageTests+Merge.m                                   \
+  objectivec/Tests/GPBMessageTests+Runtime.m                                 \
+  objectivec/Tests/GPBMessageTests+Serialization.m                           \
+  objectivec/Tests/GPBMessageTests.m                                         \
+  objectivec/Tests/GPBObjectiveCPlusPlusTest.mm                              \
+  objectivec/Tests/GPBPerfTests.m                                            \
+  objectivec/Tests/GPBSwiftTests.swift                                       \
+  objectivec/Tests/GPBTestUtilities.h                                        \
+  objectivec/Tests/GPBTestUtilities.m                                        \
+  objectivec/Tests/GPBUnittestProtos.m                                       \
+  objectivec/Tests/GPBUnknownFieldSetTest.m                                  \
+  objectivec/Tests/GPBUtilitiesTests.m                                       \
+  objectivec/Tests/GPBWellKnownTypesTest.m                                   \
+  objectivec/Tests/GPBWireFormatTests.m                                      \
+  objectivec/Tests/iOSTestHarness/AppDelegate.m                              \
+  objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings                 \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json      \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png          \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png       \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png          \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png       \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png        \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json \
+  objectivec/Tests/iOSTestHarness/Info.plist                                  \
+  objectivec/Tests/iOSTestHarness/LaunchScreen.xib                            \
+  objectivec/Tests/text_format_map_unittest_data.txt                          \
+  objectivec/Tests/text_format_unittest_data.txt                              \
+  objectivec/Tests/unittest_cycle.proto                                       \
+  objectivec/Tests/unittest_objc.proto                                        \
+  objectivec/Tests/unittest_objc_startup.proto                                \
+  objectivec/Tests/unittest_runtime_proto2.proto                              \
+  objectivec/Tests/unittest_runtime_proto3.proto                              \
+  objectivec/Tests/UnitTests-Bridging-Header.h                                \
+  objectivec/Tests/UnitTests-Info.plist                                       \
+  Protobuf.podspec
+
+python_EXTRA_DIST=                                                           \
+  python/MANIFEST.in                                                         \
+  python/google/__init__.py                                                  \
+  python/google/protobuf/__init__.py                                         \
+  python/google/protobuf/descriptor.py                                       \
+  python/google/protobuf/descriptor_database.py                              \
+  python/google/protobuf/descriptor_pool.py                                  \
+  python/google/protobuf/internal/__init__.py                                \
+  python/google/protobuf/internal/_parameterized.py                          \
+  python/google/protobuf/internal/any_test.proto                             \
+  python/google/protobuf/internal/any_test.proto                             \
+  python/google/protobuf/internal/api_implementation.cc                      \
+  python/google/protobuf/internal/api_implementation.py                      \
+  python/google/protobuf/internal/containers.py                              \
+  python/google/protobuf/internal/decoder.py                                 \
+  python/google/protobuf/internal/descriptor_database_test.py                \
+  python/google/protobuf/internal/descriptor_pool_test.py                    \
+  python/google/protobuf/internal/descriptor_pool_test1.proto                \
+  python/google/protobuf/internal/descriptor_pool_test2.proto                \
+  python/google/protobuf/internal/descriptor_test.py                         \
+  python/google/protobuf/internal/encoder.py                                 \
+  python/google/protobuf/internal/enum_type_wrapper.py                       \
+  python/google/protobuf/internal/factory_test1.proto                        \
+  python/google/protobuf/internal/factory_test2.proto                        \
+  python/google/protobuf/internal/generator_test.py                          \
+  python/google/protobuf/internal/import_test_package/__init__.py            \
+  python/google/protobuf/internal/import_test_package/inner.proto            \
+  python/google/protobuf/internal/import_test_package/outer.proto            \
+  python/google/protobuf/internal/json_format_test.py                        \
+  python/google/protobuf/internal/message_factory_test.py                    \
+  python/google/protobuf/internal/message_listener.py                        \
+  python/google/protobuf/internal/message_set_extensions.proto               \
+  python/google/protobuf/internal/message_test.py                            \
+  python/google/protobuf/internal/missing_enum_values.proto                  \
+  python/google/protobuf/internal/more_extensions.proto                      \
+  python/google/protobuf/internal/more_extensions_dynamic.proto              \
+  python/google/protobuf/internal/more_messages.proto                        \
+  python/google/protobuf/internal/packed_field_test.proto                    \
+  python/google/protobuf/internal/proto_builder_test.py                      \
+  python/google/protobuf/internal/python_message.py                          \
+  python/google/protobuf/internal/reflection_test.py                         \
+  python/google/protobuf/internal/service_reflection_test.py                 \
+  python/google/protobuf/internal/symbol_database_test.py                    \
+  python/google/protobuf/internal/test_bad_identifiers.proto                 \
+  python/google/protobuf/internal/test_util.py                               \
+  python/google/protobuf/internal/text_encoding_test.py                      \
+  python/google/protobuf/internal/text_format_test.py                        \
+  python/google/protobuf/internal/type_checkers.py                           \
+  python/google/protobuf/internal/unknown_fields_test.py                     \
+  python/google/protobuf/internal/well_known_types.py                        \
+  python/google/protobuf/internal/well_known_types.py                        \
+  python/google/protobuf/internal/well_known_types_test.py                   \
+  python/google/protobuf/internal/well_known_types_test.py                   \
+  python/google/protobuf/internal/wire_format.py                             \
+  python/google/protobuf/internal/wire_format_test.py                        \
+  python/google/protobuf/json_format.py                                      \
+  python/google/protobuf/message.py                                          \
+  python/google/protobuf/message_factory.py                                  \
+  python/google/protobuf/proto_builder.py                                    \
+  python/google/protobuf/pyext/README                                        \
+  python/google/protobuf/pyext/__init__.py                                   \
+  python/google/protobuf/pyext/cpp_message.py                                \
+  python/google/protobuf/pyext/descriptor.cc                                 \
+  python/google/protobuf/pyext/descriptor.h                                  \
+  python/google/protobuf/pyext/descriptor_containers.cc                      \
+  python/google/protobuf/pyext/descriptor_containers.h                       \
+  python/google/protobuf/pyext/descriptor_database.cc                        \
+  python/google/protobuf/pyext/descriptor_database.h                         \
+  python/google/protobuf/pyext/descriptor_pool.cc                            \
+  python/google/protobuf/pyext/descriptor_pool.h                             \
+  python/google/protobuf/pyext/extension_dict.cc                             \
+  python/google/protobuf/pyext/extension_dict.h                              \
+  python/google/protobuf/pyext/map_container.cc                              \
+  python/google/protobuf/pyext/map_container.h                               \
+  python/google/protobuf/pyext/message.cc                                    \
+  python/google/protobuf/pyext/message.h                                     \
+  python/google/protobuf/pyext/proto2_api_test.proto                         \
+  python/google/protobuf/pyext/python.proto                                  \
+  python/google/protobuf/pyext/python_protobuf.h                             \
+  python/google/protobuf/pyext/repeated_composite_container.cc               \
+  python/google/protobuf/pyext/repeated_composite_container.h                \
+  python/google/protobuf/pyext/repeated_scalar_container.cc                  \
+  python/google/protobuf/pyext/repeated_scalar_container.h                   \
+  python/google/protobuf/pyext/scoped_pyobject_ptr.h                         \
+  python/google/protobuf/reflection.py                                       \
+  python/google/protobuf/service.py                                          \
+  python/google/protobuf/service_reflection.py                               \
+  python/google/protobuf/symbol_database.py                                  \
+  python/google/protobuf/text_encoding.py                                    \
+  python/google/protobuf/text_format.py                                      \
+  python/mox.py                                                              \
+  python/setup.py                                                            \
+  python/stubout.py                                                          \
+  python/tox.ini                                                             \
+  python/README.md
+
+ruby_EXTRA_DIST=                                                             \
+  ruby/Gemfile                                                               \
+  ruby/Gemfile.lock                                                          \
+  ruby/.gitignore                                                            \
+  ruby/README.md                                                             \
+  ruby/Rakefile                                                              \
+  ruby/ext/google/protobuf_c/defs.c                                          \
+  ruby/ext/google/protobuf_c/encode_decode.c                                 \
+  ruby/ext/google/protobuf_c/extconf.rb                                      \
+  ruby/ext/google/protobuf_c/map.c                                           \
+  ruby/ext/google/protobuf_c/message.c                                       \
+  ruby/ext/google/protobuf_c/protobuf.c                                      \
+  ruby/ext/google/protobuf_c/protobuf.h                                      \
+  ruby/ext/google/protobuf_c/repeated_field.c                                \
+  ruby/ext/google/protobuf_c/storage.c                                       \
+  ruby/ext/google/protobuf_c/upb.c                                           \
+  ruby/ext/google/protobuf_c/upb.h                                           \
+  ruby/google-protobuf.gemspec                                               \
+  ruby/lib/google/protobuf/message_exts.rb                                   \
+  ruby/lib/google/protobuf/repeated_field.rb                                 \
+  ruby/lib/google/protobuf.rb                                                \
+  ruby/pom.xml                                                               \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java              \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java           \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java   \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java                 \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java      \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java                  \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java              \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java  \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java      \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java             \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java        \
+  ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/Utils.java                    \
+  ruby/src/main/java/google/ProtobufJavaService.java                         \
+  ruby/src/main/sentinel.proto                                               \
+  ruby/tests/basic.rb                                                        \
+  ruby/tests/repeated_field_test.rb                                          \
+  ruby/tests/stress.rb                                                       \
+  ruby/tests/generated_code.proto                                            \
+  ruby/tests/generated_code_test.rb                                          \
+  ruby/travis-test.sh
+
+js_EXTRA_DIST=              \
+  js/README.md              \
+  js/binary/arith.js        \
+  js/binary/arith_test.js   \
+  js/binary/constants.js    \
+  js/binary/decoder.js      \
+  js/binary/decoder_test.js \
+  js/binary/proto_test.js   \
+  js/binary/reader.js       \
+  js/binary/reader_test.js  \
+  js/binary/utils.js        \
+  js/binary/utils_test.js   \
+  js/binary/writer.js       \
+  js/binary/writer_test.js  \
+  js/data.proto             \
+  js/debug.js               \
+  js/debug_test.js          \
+  js/gulpfile.js            \
+  js/jasmine.json           \
+  js/message.js             \
+  js/message_test.js        \
+  js/node_loader.js         \
+  js/package.json           \
+  js/proto3_test.js         \
+  js/proto3_test.proto      \
+  js/test.proto             \
+  js/test2.proto            \
+  js/test3.proto            \
+  js/test4.proto            \
+  js/test5.proto            \
+  js/test_bootstrap.js      \
+  js/testbinary.proto       \
+  js/testempty.proto
+
+all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) $(js_EXTRA_DIST)
+
+EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST)   \
+  autogen.sh                             \
+  generate_descriptor_proto.sh           \
+  README.md                              \
+  LICENSE                                \
+  CONTRIBUTORS.txt                       \
+  CHANGES.txt                            \
+  update_file_lists.sh                   \
+  BUILD                                  \
+  gmock.BUILD                            \
+  WORKSPACE                              \
+  cmake/CMakeLists.txt                   \
+  cmake/README.md                        \
+  cmake/extract_includes.bat.in          \
+  cmake/install.cmake                    \
+  cmake/libprotobuf.cmake                \
+  cmake/libprotobuf-lite.cmake           \
+  cmake/libprotoc.cmake                  \
+  cmake/protobuf-config-version.cmake.in \
+  cmake/protobuf-config.cmake.in         \
+  cmake/protobuf-module.cmake.in         \
+  cmake/protoc.cmake                     \
+  cmake/tests.cmake                      \
+  editors/README.txt                     \
+  editors/proto.vim                      \
+  editors/protobuf-mode.el               \
+  examples/README.txt                    \
+  examples/Makefile                      \
+  examples/addressbook.proto             \
+  examples/add_person.cc                 \
+  examples/add_person.go                 \
+  examples/add_person_test.go            \
+  examples/list_people.cc                \
+  examples/list_people.go                \
+  examples/AddPerson.java                \
+  examples/ListPeople.java               \
+  examples/add_person.py                 \
+  examples/list_people.py                \
+  examples/list_people_test.go           \
+  protobuf.bzl                           \
+  six.BUILD                              \
+  util/python/BUILD
+
+# Deletes all the files generated by autogen.sh.
+MAINTAINERCLEANFILES =   \
+  aclocal.m4             \
+  ar-lib                 \
+  config.guess           \
+  config.sub             \
+  configure              \
+  depcomp                \
+  install-sh             \
+  ltmain.sh              \
+  Makefile.in            \
+  missing                \
+  mkinstalldirs          \
+  config.h.in            \
+  stamp.h.in             \
+  m4/ltsugar.m4          \
+  m4/libtool.m4          \
+  m4/ltversion.m4        \
+  m4/lt~obsolete.m4      \
+  m4/ltoptions.m4
diff --git a/src/third_party/protobuf-3/Protobuf.podspec b/src/third_party/protobuf-3/Protobuf.podspec
new file mode 100644
index 0000000..0bbd06d
--- /dev/null
+++ b/src/third_party/protobuf-3/Protobuf.podspec
@@ -0,0 +1,40 @@
+# This file describes to Cocoapods how to integrate the Objective-C runtime into a dependent
+# project.
+# Despite this file being specific to Objective-C, it needs to be on the root of the repository.
+# Otherwise, Cocoapods gives trouble like not picking up the license file correctly, or not letting
+# dependent projects use the :git notation to refer to the library.
+Pod::Spec.new do |s|
+  s.name     = 'Protobuf'
+  s.version  = '3.0.0-beta-2'
+  s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
+  s.homepage = 'https://github.com/google/protobuf'
+  s.license  = 'New BSD'
+  s.authors  = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
+
+  s.source = { :git => 'https://github.com/google/protobuf.git',
+               :tag => "v#{s.version}" }
+
+  s.source_files = 'objectivec/*.{h,m}',
+                   'objectivec/google/protobuf/Any.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/Api.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/Duration.pbobjc.h',
+                   'objectivec/google/protobuf/Empty.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/FieldMask.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/SourceContext.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/Struct.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/Timestamp.pbobjc.h',
+                   'objectivec/google/protobuf/Type.pbobjc.{h,m}',
+                   'objectivec/google/protobuf/Wrappers.pbobjc.{h,m}'
+  # Timestamp.pbobjc.m and Duration.pbobjc.m are #imported by GPBWellKnownTypes.m. So we can't
+  # compile them (duplicate symbols), but we need them available for the importing:
+  s.preserve_paths = 'objectivec/google/protobuf/Duration.pbobjc.m',
+                     'objectivec/google/protobuf/Timestamp.pbobjc.m'
+  # The following would cause duplicate symbol definitions. GPBProtocolBuffers is expected to be
+  # left out, as it's an umbrella implementation file.
+  s.exclude_files = 'objectivec/GPBProtocolBuffers.m'
+  s.header_mappings_dir = 'objectivec'
+
+  s.ios.deployment_target = '7.1'
+  s.osx.deployment_target = '10.9'
+  s.requires_arc = false
+end
diff --git a/src/third_party/protobuf-3/README.chromium b/src/third_party/protobuf-3/README.chromium
new file mode 100644
index 0000000..8838fbc
--- /dev/null
+++ b/src/third_party/protobuf-3/README.chromium
@@ -0,0 +1,78 @@
+Name: Protocol Buffers
+Short Name: protobuf
+URL: https://github.com/google/protobuf
+License: BSD
+License File: LICENSE
+Version: 3.0.0-beta-3
+Revision: 3470b6895aa659b7559ed678e029a5338e535f14
+Security Critical: yes
+
+Steps used to create the current version:
+1. Pull the release from https://github.com/google/protobuf/releases
+2. Add build files (BUILD.gn, proto_library.gni, protobuf.gyp,
+   protobuf_lite.gypi, protobuf_nacl.gyp).
+
+   Be sure to update the list of source files, as additional .cc files and
+   headers might have been added -- you need to find the transitive closure of
+   include files required by targets.
+
+   Other things to care about are defines required by protobuf on various
+   platforms, warnings generated by compilers, and new dependencies introduced.
+3. Get open-source library six.py from https://pypi.python.org/pypi/six/ and add
+   it to protobuf/third_party/six/six.py.
+4. Apply patches in patches/ (see the description below):
+
+   $ for patch in patches/*; do patch -s -p1 < $patch; done
+
+   For future releases, it will be worth looking into which patches still need
+   to be applied.
+5. Generate descriptor_pb2.py using something like the following steps. Make
+   sure you've regenerated your buildfiles and will build protoc from the
+   newly-modified sources above.
+
+   $ cd $SRC_DIR
+   $ ninja -C out/Debug protoc
+   $ cd third_party/protobuf/src
+   $ ../../../out/Debug/protoc --python_out=../python google/protobuf/descriptor.proto
+
+6. Add an __init__.py to protobuf/ that adds third_party/six/ to Python path.
+7. Update README.chromium.
+
+Description of the patches:
+
+- 0003-remove-static-initializers.patch
+
+  This patch removes all static initializers from Chromium. The change in Status
+  class is not completely compatible with upstream, but it's compatible enough
+  to work in Chromium, which doesn't use this functionality yet. The work on
+  upstreaming the removal of static initializers is in progress:
+  https://github.com/google/protobuf/issues/1404
+
+- 0004-fix-integer-types-and-shared-library-exports.patch
+
+  This patch makes protobuf int64 to be int64_t (as opposed to long long in
+  upstream), and similarly for other integer types. It also allows exporting
+  protobuf symbols in Linux .so libraries, so that protobuf can be built as a
+  component (see http://crrev.com/179806).
+
+- 0005-fix-include-js-generator.protobuf
+
+  During merge with internal branch, the <> in one of the #includes were
+  accidentally replaced with "", which results in a failure in checkdeps.
+
+  Fixed in https://github.com/google/protobuf/pull/1547.
+
+- 0007-uninline_googleonce.patch
+- 0008-uninline_get_empty_string.patch
+- 0009-uninline-arenastring.patch
+- 0010-uninline-generated-code.patch
+
+  These patches uninline some functions, resulting in a significant reduction
+  (somewhere between 500 KB and 1 MB) of binary size.
+
+- 0011-libprotobuf_export.patch
+
+  During merge with internal branch, the dll export attribute was accidentally
+  removed in C++11 mode.
+
+  Fixed in https://github.com/google/protobuf/pull/1549
diff --git a/src/third_party/protobuf-3/README.md b/src/third_party/protobuf-3/README.md
new file mode 100644
index 0000000..ba9c589
--- /dev/null
+++ b/src/third_party/protobuf-3/README.md
@@ -0,0 +1,77 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
+
+Copyright 2008 Google Inc.
+
+https://developers.google.com/protocol-buffers/
+
+Overview
+--------
+
+Protocol Buffers (a.k.a., protobuf) are Google's language-neutral,
+platform-neutral, extensible mechanism for serializing structured data. You
+can find [protobuf's documentation on the Google Developers site](https://developers.google.com/protocol-buffers/).
+
+This README file contains protobuf installation instructions. To install
+protobuf, you need to install the protocol compiler (used to compile .proto
+files) and the protobuf runtime for your chosen programming language.
+
+Protocol Compiler Installation
+------------------------------
+
+The protocol compiler is written in C++. If you are using C++, please follow
+the [C++ Installation Instructions](src/README.md) to install protoc along
+with the C++ runtime.
+
+For non-C++ users, the simplest way to install the protocol compiler is to
+download a pre-built binary from our release page:
+
+  [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases)
+
+In the downloads section of each release, you can find pre-built binaries in
+zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary
+as well as a set of standard .proto files distributed along with protobuf.
+
+If you are looking for an old version that is not available in the release
+page, check out the maven repo here:
+
+  [http://repo1.maven.org/maven2/com/google/protobuf/protoc/](http://repo1.maven.org/maven2/com/google/protobuf/protoc/)
+
+These pre-built binaries are only provided for released versions. If you want
+to use the github master version at HEAD, or you need to modify protobuf code,
+or you are using C++, it's recommended to build your own protoc binary from
+source.
+
+If you would like to build protoc binary from source, see the [C++ Installation
+Instructions](src/README.md).
+
+Protobuf Runtime Installation
+-----------------------------
+
+Protobuf supports several different programming languages. For each programming
+language, you can find instructions in the corresponding source directory about
+how to install protobuf runtime for that specific language:
+
+| Language                             | Source                                                |
+|--------------------------------------|-------------------------------------------------------|
+| C++ (include C++ runtime and protoc) | [src](src)                                            |
+| Java                                 | [java](java)                                          |
+| Python                               | [python](python)                                      |
+| Objective-C                          | [objectivec](objectivec)                              |
+| C#                                   | [csharp](csharp)                                      |
+| JavaNano                             | [javanano](javanano)                                  |
+| JavaScript                           | [js](js)                                              |
+| Ruby                                 | [ruby](ruby)                                          |
+| Go                                   | [golang/protobuf](https://github.com/golang/protobuf) |
+| PHP                                  | TBD                                                   |
+
+
+Usage
+-----
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+    https://developers.google.com/protocol-buffers/
diff --git a/src/third_party/protobuf-3/WORKSPACE b/src/third_party/protobuf-3/WORKSPACE
new file mode 100644
index 0000000..065dc81
--- /dev/null
+++ b/src/third_party/protobuf-3/WORKSPACE
@@ -0,0 +1,53 @@
+new_http_archive(
+    name = "gmock_archive",
+    url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
+    sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
+    build_file = "gmock.BUILD",
+)
+
+new_http_archive(
+    name = "six_archive",
+    url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
+    sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
+    build_file = "six.BUILD",
+)
+
+bind(
+    name = "python_headers",
+    actual = "//util/python:python_headers",
+)
+
+bind(
+    name = "gtest",
+    actual = "@gmock_archive//:gtest",
+)
+
+bind(
+    name = "gtest_main",
+    actual = "@gmock_archive//:gtest_main",
+)
+
+bind(
+    name = "six",
+    actual = "@six_archive//:six",
+)
+
+maven_jar(
+  name = "guava_maven",
+  artifact = "com.google.guava:guava:18.0",
+)
+
+bind(
+    name = "guava",
+    actual = "@guava_maven//jar",
+)
+
+maven_jar(
+  name = "gson_maven",
+  artifact = "com.google.code.gson:gson:2.3",
+)
+
+bind(
+    name = "gson",
+    actual = "@gson_maven//jar",
+)
diff --git a/src/third_party/protobuf-3/__init__.py b/src/third_party/protobuf-3/__init__.py
new file mode 100644
index 0000000..11e1cf2
--- /dev/null
+++ b/src/third_party/protobuf-3/__init__.py
@@ -0,0 +1,6 @@
+import sys
+import os
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+sys.path.insert(0, os.path.join(THIS_DIR, "third_party", "six"))
diff --git a/src/third_party/protobuf-3/appveyor.bat b/src/third_party/protobuf-3/appveyor.bat
new file mode 100644
index 0000000..9a46b92
--- /dev/null
+++ b/src/third_party/protobuf-3/appveyor.bat
@@ -0,0 +1,29 @@
+setlocal
+
+IF %language%==cpp GOTO build_cpp
+IF %language%==csharp GOTO build_csharp
+
+echo Unsupported language %language%. Exiting.
+goto :error
+
+:build_cpp
+echo Building C++
+mkdir build_msvc
+cd build_msvc
+cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
+msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
+cd %configuration%
+tests.exe || goto error
+goto :EOF
+
+:build_csharp
+echo Building C#
+cd csharp\src
+nuget restore
+msbuild Google.Protobuf.sln /p:Platform="Any CPU" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
+nunit-console Google.Protobuf.Test\bin\%configuration%\Google.Protobuf.Test.dll || goto error
+goto :EOF
+
+:error
+echo Failed!
+EXIT /b %ERRORLEVEL%
diff --git a/src/third_party/protobuf-3/appveyor.yml b/src/third_party/protobuf-3/appveyor.yml
new file mode 100644
index 0000000..c84ecae
--- /dev/null
+++ b/src/third_party/protobuf-3/appveyor.yml
@@ -0,0 +1,32 @@
+# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can
+# test more combinations but AppVeyor just takes too long to finish (each
+# combination takes ~15mins).
+platform:
+  - Win64
+
+configuration:
+  - Debug
+
+environment:
+  matrix:
+    - language: cpp
+      BUILD_DLL: ON
+
+    - language: csharp
+
+install:
+  - ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+  - 7z x gmock-1.7.0.zip
+  - rename gmock-1.7.0 gmock
+
+before_build:
+  - if %platform%==Win32 set generator=Visual Studio 12
+  - if %platform%==Win64 set generator=Visual Studio 12 Win64
+  - if %platform%==Win32 set vcplatform=Win32
+  - if %platform%==Win64 set vcplatform=x64
+
+build_script:
+  - CALL appveyor.bat
+
+skip_commits:
+  message: /.*\[skip appveyor\].*/
diff --git a/src/third_party/protobuf-3/autogen.sh b/src/third_party/protobuf-3/autogen.sh
new file mode 100755
index 0000000..5b4c29f
--- /dev/null
+++ b/src/third_party/protobuf-3/autogen.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Run this script to generate the configure script and other files that will
+# be included in the distribution.  These files are not checked in because they
+# are automatically generated.
+
+set -e
+
+if [ ! -z "$@" ]; then
+  for argument in "$@"; do
+    case $argument in
+	  # make curl silent
+      "-s")
+        curlopts="-s"
+        ;;
+    esac
+  done
+fi
+
+
+# Check that we're being run from the right directory.
+if test ! -f src/google/protobuf/stubs/common.h; then
+  cat >&2 << __EOF__
+Could not find source code.  Make sure you are running this script from the
+root of the distribution tree.
+__EOF__
+  exit 1
+fi
+
+# Check that gmock is present.  Usually it is already there since the
+# directory is set up as an SVN external.
+if test ! -e gmock; then
+  echo "Google Mock not present.  Fetching gmock-1.7.0 from the web..."
+  curl $curlopts -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+  unzip -q gmock-1.7.0.zip
+  rm gmock-1.7.0.zip
+  mv gmock-1.7.0 gmock
+fi
+
+set -ex
+
+# TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
+autoreconf -f -i -Wall,no-obsolete
+
+rm -rf autom4te.cache config.h.in~
+exit 0
diff --git a/src/third_party/protobuf-3/benchmarks/Makefile.am b/src/third_party/protobuf-3/benchmarks/Makefile.am
new file mode 100644
index 0000000..f730afe
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/Makefile.am
@@ -0,0 +1,69 @@
+
+benchmarks_protoc_inputs =                                     \
+  benchmarks.proto                                             \
+  benchmark_messages_proto3.proto
+
+benchmarks_protoc_inputs_proto2 =                              \
+  benchmark_messages_proto2.proto
+
+benchmarks_protoc_outputs =                                    \
+  benchmarks.pb.cc                                             \
+  benchmarks.pb.h                                              \
+  benchmark_messages_proto3.pb.cc                              \
+  benchmark_messages_proto3.pb.h
+
+benchmarks_protoc_outputs_proto2 =                             \
+  benchmark_messages_proto2.pb.cc                              \
+  benchmark_messages_proto2.pb.h
+
+bin_PROGRAMS = generate-datasets
+
+generate_datasets_LDADD = $(top_srcdir)/src/libprotobuf.la
+generate_datasets_SOURCES = generate_datasets.cc
+generate_datasets_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)
+nodist_generate_datasets_SOURCES =                             \
+  $(benchmarks_protoc_outputs)                                 \
+  $(benchmarks_protoc_outputs_proto2)
+
+# Explicit deps because BUILT_SOURCES are only done before a "make all/check"
+# so a direct "make test_cpp" could fail if parallel enough.
+# See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
+generate_datasets-generate_datasets.$(OBJEXT): benchmarks.pb.h
+
+$(benchmarks_protoc_outputs): protoc_middleman
+$(benchmarks_protoc_outputs_proto2): protoc_middleman2
+
+CLEANFILES =                                                   \
+  $(benchmarks_protoc_outputs)                                 \
+  $(benchmarks_protoc_outputs_proto2)                          \
+  protoc_middleman                                             \
+  protoc_middleman2                                            \
+  dataset.*
+
+MAINTAINERCLEANFILES =   \
+  Makefile.in
+
+if USE_EXTERNAL_PROTOC
+
+protoc_middleman: $(benchmarks_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs)
+	touch protoc_middleman
+
+protoc_middleman2: $(benchmarks_protoc_inputs_proto2)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs_proto2)
+	touch protoc_middleman2
+
+else
+
+# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
+# relative to srcdir, which may not be the same as the current directory when
+# building out-of-tree.
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd $(benchmarks_protoc_inputs) )
+	touch protoc_middleman
+
+protoc_middleman2: $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd $(benchmarks_protoc_inputs_proto2) )
+	touch protoc_middleman
+
+endif
diff --git a/src/third_party/protobuf-3/benchmarks/ProtoBench.java b/src/third_party/protobuf-3/benchmarks/ProtoBench.java
new file mode 100644
index 0000000..86d62fe
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/ProtoBench.java
@@ -0,0 +1,203 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2009 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.
+
+package com.google.protocolbuffers;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.reflect.Method;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.Message;
+
+public class ProtoBench {
+  
+  private static final long MIN_SAMPLE_TIME_MS = 2 * 1000;
+  private static final long TARGET_TIME_MS = 30 * 1000;
+
+  private ProtoBench() {
+    // Prevent instantiation
+  }
+  
+  public static void main(String[] args) {
+    if (args.length < 2 || (args.length % 2) != 0) {
+      System.err.println("Usage: ProtoBench <descriptor type name> <input data>");
+      System.err.println("The descriptor type name is the fully-qualified message name,");
+      System.err.println("e.g. com.google.protocolbuffers.benchmark.Message1");
+      System.err.println("(You can specify multiple pairs of descriptor type name and input data.)");
+      System.exit(1);
+    }
+    boolean success = true;
+    for (int i = 0; i < args.length; i += 2) {
+      success &= runTest(args[i], args[i + 1]);
+    }
+    System.exit(success ? 0 : 1);
+  }
+
+  /**
+   * Runs a single test. Error messages are displayed to stderr, and the return value
+   * indicates general success/failure.
+   */
+  public static boolean runTest(String type, String file) {
+    System.out.println("Benchmarking " + type + " with file " + file);
+    final Message defaultMessage;
+    try {
+      Class<?> clazz = Class.forName(type);
+      Method method = clazz.getDeclaredMethod("getDefaultInstance");
+      defaultMessage = (Message) method.invoke(null);
+    } catch (Exception e) {
+      // We want to do the same thing with all exceptions. Not generally nice,
+      // but this is slightly different.
+      System.err.println("Unable to get default message for " + type);
+      return false;
+    }
+    
+    try {
+      final byte[] inputData = readAllBytes(file);
+      final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputData);
+      final ByteString inputString = ByteString.copyFrom(inputData);
+      final Message sampleMessage = defaultMessage.newBuilderForType().mergeFrom(inputString).build();
+      FileOutputStream devNullTemp = null;
+      CodedOutputStream reuseDevNullTemp = null;
+      try {
+        devNullTemp = new FileOutputStream("/dev/null");
+        reuseDevNullTemp = CodedOutputStream.newInstance(devNullTemp);
+      } catch (FileNotFoundException e) {
+        // ignore: this is probably Windows, where /dev/null does not exist
+      }
+      final FileOutputStream devNull = devNullTemp;
+      final CodedOutputStream reuseDevNull = reuseDevNullTemp;
+      benchmark("Serialize to byte string", inputData.length, new Action() {
+        public void execute() { sampleMessage.toByteString(); }
+      });      
+      benchmark("Serialize to byte array", inputData.length, new Action() {
+        public void execute() { sampleMessage.toByteArray(); }
+      });
+      benchmark("Serialize to memory stream", inputData.length, new Action() {
+        public void execute() throws IOException { 
+          sampleMessage.writeTo(new ByteArrayOutputStream()); 
+        }
+      });
+      if (devNull != null) {
+        benchmark("Serialize to /dev/null with FileOutputStream", inputData.length, new Action() {
+          public void execute() throws IOException {
+            sampleMessage.writeTo(devNull);
+          }
+        });
+        benchmark("Serialize to /dev/null reusing FileOutputStream", inputData.length, new Action() {
+          public void execute() throws IOException {
+            sampleMessage.writeTo(reuseDevNull);
+            reuseDevNull.flush();  // force the write to the OutputStream
+          }
+        });
+      }
+      benchmark("Deserialize from byte string", inputData.length, new Action() {
+        public void execute() throws IOException { 
+          defaultMessage.newBuilderForType().mergeFrom(inputString).build();
+        }
+      });
+      benchmark("Deserialize from byte array", inputData.length, new Action() {
+        public void execute() throws IOException { 
+          defaultMessage.newBuilderForType()
+            .mergeFrom(CodedInputStream.newInstance(inputData)).build();
+        }
+      });
+      benchmark("Deserialize from memory stream", inputData.length, new Action() {
+        public void execute() throws IOException { 
+          defaultMessage.newBuilderForType()
+            .mergeFrom(CodedInputStream.newInstance(inputStream)).build();
+          inputStream.reset();
+        }
+      });
+      System.out.println();
+      return true;
+    } catch (Exception e) {
+      System.err.println("Error: " + e.getMessage());
+      System.err.println("Detailed exception information:");
+      e.printStackTrace(System.err);
+      return false;
+    }
+  }
+  
+  private static void benchmark(String name, long dataSize, Action action) throws IOException {
+    // Make sure it's JITted "reasonably" hard before running the first progress test
+    for (int i=0; i < 100; i++) {
+      action.execute();
+    }
+    
+    // Run it progressively more times until we've got a reasonable sample
+    int iterations = 1;
+    long elapsed = timeAction(action, iterations);
+    while (elapsed < MIN_SAMPLE_TIME_MS) {
+      iterations *= 2;
+      elapsed = timeAction(action, iterations);
+    }
+    
+    // Upscale the sample to the target time. Do this in floating point arithmetic
+    // to avoid overflow issues.
+    iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations);
+    elapsed = timeAction(action, iterations);
+    System.out.println(name + ": " + iterations + " iterations in "
+         + (elapsed/1000f) + "s; " 
+         + (iterations * dataSize) / (elapsed * 1024 * 1024 / 1000f) 
+         + "MB/s");
+  }
+  
+  private static long timeAction(Action action, int iterations) throws IOException {
+    System.gc();    
+    long start = System.currentTimeMillis();
+    for (int i = 0; i < iterations; i++) {
+      action.execute();
+    }
+    long end = System.currentTimeMillis();
+    return end - start;
+  }
+  
+  private static byte[] readAllBytes(String filename) throws IOException {
+    RandomAccessFile file = new RandomAccessFile(new File(filename), "r");
+    byte[] content = new byte[(int) file.length()];
+    file.readFully(content);
+    return content;
+  }
+
+  /**
+   * Interface used to capture a single action to benchmark.
+   */
+  interface Action {
+    void execute() throws IOException;
+  }
+}
diff --git a/src/third_party/protobuf-3/benchmarks/README.md b/src/third_party/protobuf-3/benchmarks/README.md
new file mode 100644
index 0000000..c902780
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/README.md
@@ -0,0 +1,28 @@
+
+# Protocol Buffers Benchmarks
+
+This directory contains benchmarking schemas and data sets that you
+can use to test a variety of performance scenarios against your
+protobuf language runtime.
+
+The schema for the datasets is described in `benchmarks.proto`.
+
+Generate the data sets like so:
+
+```
+$ make
+$ ./generate-datasets
+Wrote dataset: dataset.google_message1_proto3.pb
+Wrote dataset: dataset.google_message1_proto2.pb
+Wrote dataset: dataset.google_message2.pb
+$
+```
+
+Each data set will be written to its own file.  Benchmarks will
+likely want to run several benchmarks against each data set (parse,
+serialize, possibly JSON, possibly using different APIs, etc).
+
+We would like to add more data sets.  In general we will favor data sets
+that make the overall suite diverse without being too large or having
+too many similar tests.  Ideally everyone can run through the entire
+suite without the test run getting too long.
diff --git a/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto2.proto b/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto2.proto
new file mode 100644
index 0000000..01f67a1
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto2.proto
@@ -0,0 +1,141 @@
+// Benchmark messages for proto2.
+
+syntax = "proto2";
+
+package benchmarks.proto2;
+option java_package = "com.google.protobuf.benchmarks";
+
+// This is the default, but we specify it here explicitly.
+option optimize_for = SPEED;
+
+message GoogleMessage1 {
+  required string field1 = 1;
+  optional string field9 = 9;
+  optional string field18 = 18;
+  optional bool field80 = 80 [default=false];
+  optional bool field81 = 81 [default=true];
+  required int32 field2 = 2;
+  required int32 field3 = 3;
+  optional int32 field280 = 280;
+  optional int32 field6 = 6 [default=0];
+  optional int64 field22 = 22;
+  optional string field4 = 4;
+  repeated fixed64 field5 = 5;
+  optional bool field59 = 59 [default=false];
+  optional string field7 = 7;
+  optional int32 field16 = 16;
+  optional int32 field130 = 130 [default=0];
+  optional bool field12 = 12 [default=true];
+  optional bool field17 = 17 [default=true];
+  optional bool field13 = 13 [default=true];
+  optional bool field14 = 14 [default=true];
+  optional int32 field104 = 104 [default=0];
+  optional int32 field100 = 100 [default=0];
+  optional int32 field101 = 101 [default=0];
+  optional string field102 = 102;
+  optional string field103 = 103;
+  optional int32 field29 = 29 [default=0];
+  optional bool field30 = 30 [default=false];
+  optional int32 field60 = 60 [default=-1];
+  optional int32 field271 = 271 [default=-1];
+  optional int32 field272 = 272 [default=-1];
+  optional int32 field150 = 150;
+  optional int32 field23 = 23 [default=0];
+  optional bool field24 = 24 [default=false];
+  optional int32 field25 = 25 [default=0];
+  optional GoogleMessage1SubMessage field15 = 15;
+  optional bool field78 = 78;
+  optional int32 field67 = 67 [default=0];
+  optional int32 field68 = 68;
+  optional int32 field128 = 128 [default=0];
+  optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"];
+  optional int32 field131 = 131 [default=0];
+}
+
+message GoogleMessage1SubMessage {
+  optional int32 field1 = 1 [default=0];
+  optional int32 field2 = 2 [default=0];
+  optional int32 field3 = 3 [default=0];
+  optional string field15 = 15;
+  optional bool field12 = 12 [default=true];
+  optional int64 field13 = 13;
+  optional int64 field14 = 14;
+  optional int32 field16 = 16;
+  optional int32 field19 = 19 [default=2];
+  optional bool field20  = 20 [default=true];
+  optional bool field28 = 28 [default=true];
+  optional fixed64 field21 = 21;
+  optional int32 field22 = 22;
+  optional bool field23 = 23 [ default=false ];
+  optional bool field206 = 206 [default=false];
+  optional fixed32 field203 = 203;
+  optional int32 field204 = 204;
+  optional string field205 = 205;
+  optional uint64 field207 = 207;
+  optional uint64 field300 = 300;
+}
+
+message GoogleMessage2 {
+  optional string field1 = 1;
+  optional int64 field3 = 3;
+  optional int64 field4 = 4;
+  optional int64 field30 = 30;
+  optional bool field75  = 75 [default=false];
+  optional string field6 = 6;
+  optional bytes field2 = 2;
+  optional int32 field21 = 21 [default=0];
+  optional int32 field71 = 71;
+  optional float field25 = 25;
+  optional int32 field109 = 109 [default=0];
+  optional int32 field210 = 210 [default=0];
+  optional int32 field211 = 211 [default=0];
+  optional int32 field212 = 212 [default=0];
+  optional int32 field213 = 213 [default=0];
+  optional int32 field216 = 216 [default=0];
+  optional int32 field217 = 217 [default=0];
+  optional int32 field218 = 218 [default=0];
+  optional int32 field220 = 220 [default=0];
+  optional int32 field221 = 221 [default=0];
+  optional float field222 = 222 [default=0.0];
+  optional int32 field63 = 63;
+
+  repeated group Group1 = 10 {
+    required float field11 = 11;
+    optional float field26 = 26;
+    optional string field12 = 12;
+    optional string field13 = 13;
+    repeated string field14 = 14;
+    required uint64 field15 = 15;
+    optional int32 field5 = 5;
+    optional string field27 = 27;
+    optional int32 field28 = 28;
+    optional string field29 = 29;
+    optional string field16 = 16;
+    repeated string field22 = 22;
+    repeated int32 field73 = 73;
+    optional int32 field20 = 20 [default=0];
+    optional string field24 = 24;
+    optional GoogleMessage2GroupedMessage field31 = 31;
+  }
+  repeated string field128 = 128;
+  optional int64 field131 = 131;
+  repeated string field127 = 127;
+  optional int32 field129 = 129;
+  repeated int64 field130 = 130;
+  optional bool field205 = 205 [default=false];
+  optional bool field206 = 206 [default=false];
+}
+
+message GoogleMessage2GroupedMessage {
+  optional float field1 = 1;
+  optional float field2 = 2;
+  optional float field3 = 3 [default=0.0];
+  optional bool field4 = 4;
+  optional bool field5 = 5;
+  optional bool field6 = 6 [default=true];
+  optional bool field7 = 7 [default=false];
+  optional float field8 = 8;
+  optional bool field9 = 9;
+  optional float field10 = 10;
+  optional int64 field11 = 11;
+}
diff --git a/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto3.proto b/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto3.proto
new file mode 100644
index 0000000..32f5869
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/benchmark_messages_proto3.proto
@@ -0,0 +1,76 @@
+// Benchmark messages for proto3.
+
+syntax = "proto3";
+
+package benchmarks.proto3;
+option java_package = "com.google.protobuf.benchmarks";
+
+// This is the default, but we specify it here explicitly.
+option optimize_for = SPEED;
+
+message GoogleMessage1 {
+  string field1 = 1;
+  string field9 = 9;
+  string field18 = 18;
+  bool field80 = 80;
+  bool field81 = 81;
+  int32 field2 = 2;
+  int32 field3 = 3;
+  int32 field280 = 280;
+  int32 field6 = 6;
+  int64 field22 = 22;
+  string field4 = 4;
+  repeated fixed64 field5 = 5;
+  bool field59 = 59;
+  string field7 = 7;
+  int32 field16 = 16;
+  int32 field130 = 130;
+  bool field12 = 12;
+  bool field17 = 17;
+  bool field13 = 13;
+  bool field14 = 14;
+  int32 field104 = 104;
+  int32 field100 = 100;
+  int32 field101 = 101;
+  string field102 = 102;
+  string field103 = 103;
+  int32 field29 = 29;
+  bool field30 = 30;
+  int32 field60 = 60;
+  int32 field271 = 271;
+  int32 field272 = 272;
+  int32 field150 = 150;
+  int32 field23 = 23;
+  bool field24 = 24;
+  int32 field25 = 25;
+  GoogleMessage1SubMessage field15 = 15;
+  bool field78 = 78;
+  int32 field67 = 67;
+  int32 field68 = 68;
+  int32 field128 = 128;
+  string field129 = 129;
+  int32 field131 = 131;
+}
+
+message GoogleMessage1SubMessage {
+  int32 field1 = 1;
+  int32 field2 = 2;
+  int32 field3 = 3;
+  string field15 = 15;
+  bool field12 = 12;
+  int64 field13 = 13;
+  int64 field14 = 14;
+  int32 field16 = 16;
+  int32 field19 = 19;
+  bool field20  = 20;
+  bool field28 = 28;
+  fixed64 field21 = 21;
+  int32 field22 = 22;
+  bool field23 = 23;
+  bool field206 = 206;
+  fixed32 field203 = 203;
+  int32 field204 = 204;
+  string field205 = 205;
+  uint64 field207 = 207;
+  uint64 field300 = 300;
+}
diff --git a/src/third_party/protobuf-3/benchmarks/benchmarks.proto b/src/third_party/protobuf-3/benchmarks/benchmarks.proto
new file mode 100644
index 0000000..51c0b54
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/benchmarks.proto
@@ -0,0 +1,63 @@
+// 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.
+
+syntax = "proto3";
+package benchmarks;
+option java_package = "com.google.protobuf.benchmarks";
+
+message BenchmarkDataset {
+  // Name of the benchmark dataset.  This should be unique across all datasets.
+  // Should only contain word characters: [a-zA-Z0-9_]
+  string name = 1;
+
+  // Fully-qualified name of the protobuf message for this dataset.
+  // It will be one of the messages defined benchmark_messages_proto2.proto
+  // or benchmark_messages_proto3.proto.
+  //
+  // Implementations that do not support reflection can implement this with
+  // an explicit "if/else" chain that lists every known message defined
+  // in those files.
+  string message_name = 2;
+
+  // The payload(s) for this dataset.  They should be parsed or serialized
+  // in sequence, in a loop, ie.
+  //
+  //  while (!benchmarkDone) {  // Benchmark runner decides when to exit.
+  //    for (i = 0; i < benchmark.payload.length; i++) {
+  //      parse(benchmark.payload[i])
+  //    }
+  //  }
+  //
+  // This is intended to let datasets include a variety of data to provide
+  // potentially more realistic results than just parsing the same message
+  // over and over.  A single message parsed repeatedly could yield unusually
+  // good branch prediction performance.
+  repeated bytes payload = 3;
+}
diff --git a/src/third_party/protobuf-3/benchmarks/generate_datasets.cc b/src/third_party/protobuf-3/benchmarks/generate_datasets.cc
new file mode 100644
index 0000000..61e7adf
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/generate_datasets.cc
@@ -0,0 +1,117 @@
+// 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.
+
+#include <fstream>
+#include <iostream>
+#include "benchmarks.pb.h"
+
+using benchmarks::BenchmarkDataset;
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::Message;
+using google::protobuf::MessageFactory;
+
+std::set<std::string> names;
+
+const char *file_prefix = "dataset.";
+const char *file_suffix = ".pb";
+
+void WriteFileWithPayloads(const std::string& name,
+                           const std::string& message_name,
+                           const std::vector<std::string>& payload) {
+  if (!names.insert(name).second) {
+    std::cerr << "Duplicate test name: " << name << "\n";
+    abort();
+  }
+
+  // First verify that this message name exists in our set of benchmark messages
+  // and that these payloads are valid for the given message.
+  const Descriptor* d =
+      DescriptorPool::generated_pool()->FindMessageTypeByName(message_name);
+
+  if (!d) {
+    std::cerr << "For dataset " << name << ", no such message: "
+              << message_name << "\n";
+    abort();
+  }
+
+  Message* m = MessageFactory::generated_factory()->GetPrototype(d)->New();
+
+  for (size_t i = 0; i < payload.size(); i++) {
+    if (!m->ParseFromString(payload[i])) {
+      std::cerr << "For dataset " << name << ", payload[" << i << "] fails "
+                << "to parse\n";
+      abort();
+    }
+  }
+
+  BenchmarkDataset dataset;
+  dataset.set_name(name);
+  dataset.set_message_name(message_name);
+  for (size_t i = 0; i < payload.size(); i++) {
+    dataset.add_payload()->assign(payload[i]);
+  }
+
+  std::ofstream writer;
+  std::string fname = file_prefix + name + file_suffix;
+  writer.open(fname.c_str());
+  dataset.SerializeToOstream(&writer);
+  writer.close();
+
+  std::cerr << "Wrote dataset: " << fname << "\n";
+}
+
+void WriteFile(const std::string& name, const std::string& message_name,
+               const std::string& payload) {
+  std::vector<std::string> payloads;
+  payloads.push_back(payload);
+  WriteFileWithPayloads(name, message_name, payloads);
+}
+
+std::string ReadFile(const std::string& name) {
+  std::ifstream file(name.c_str());
+  GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name <<
+                                  "', please make sure you are running "
+                                  "this command from the benchmarks/ "
+                                  "directory.\n";
+  return std::string((std::istreambuf_iterator<char>(file)),
+                     std::istreambuf_iterator<char>());
+}
+
+int main() {
+  WriteFile("google_message1_proto3", "benchmarks.proto3.GoogleMessage1",
+            ReadFile("google_message1.dat"));
+  WriteFile("google_message1_proto2", "benchmarks.proto2.GoogleMessage1",
+            ReadFile("google_message1.dat"));
+
+  // Not in proto3 because it has a group, which is not supported.
+  WriteFile("google_message2", "benchmarks.proto2.GoogleMessage2",
+            ReadFile("google_message2.dat"));
+}
diff --git a/src/third_party/protobuf-3/benchmarks/google_message1.dat b/src/third_party/protobuf-3/benchmarks/google_message1.dat
new file mode 100644
index 0000000..bc0f064
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/google_message1.dat
Binary files differ
diff --git a/src/third_party/protobuf-3/benchmarks/google_message2.dat b/src/third_party/protobuf-3/benchmarks/google_message2.dat
new file mode 100644
index 0000000..06c0944
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/google_message2.dat
Binary files differ
diff --git a/src/third_party/protobuf-3/benchmarks/google_size.proto b/src/third_party/protobuf-3/benchmarks/google_size.proto
new file mode 100644
index 0000000..d2d319f
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/google_size.proto
@@ -0,0 +1,138 @@
+syntax = "proto2";
+
+package benchmarks;
+
+option java_outer_classname = "GoogleSize";
+option optimize_for = CODE_SIZE;
+
+message SizeMessage1 {
+  required string field1 = 1;
+  optional string field9 = 9;
+  optional string field18 = 18;
+  optional bool field80 = 80 [default=false];
+  optional bool field81 = 81 [default=true];
+  required int32 field2 = 2;
+  required int32 field3 = 3;
+  optional int32 field280 = 280;
+  optional int32 field6 = 6 [default=0];
+  optional int64 field22 = 22;
+  optional string field4 = 4;
+  repeated fixed64 field5 = 5;
+  optional bool field59 = 59 [default=false];
+  optional string field7 = 7;
+  optional int32 field16 = 16;
+  optional int32 field130 = 130 [default=0];
+  optional bool field12 = 12 [default=true];
+  optional bool field17 = 17 [default=true];
+  optional bool field13 = 13 [default=true];
+  optional bool field14 = 14 [default=true];
+  optional int32 field104 = 104 [default=0];
+  optional int32 field100 = 100 [default=0];
+  optional int32 field101 = 101 [default=0];
+  optional string field102 = 102;
+  optional string field103 = 103;
+  optional int32 field29 = 29 [default=0];
+  optional bool field30 = 30 [default=false];
+  optional int32 field60 = 60 [default=-1];
+  optional int32 field271 = 271 [default=-1];
+  optional int32 field272 = 272 [default=-1];
+  optional int32 field150 = 150;
+  optional int32 field23 = 23 [default=0];
+  optional bool field24 = 24 [default=false];
+  optional int32 field25 = 25 [default=0];
+  optional SizeMessage1SubMessage field15 = 15;
+  optional bool field78 = 78;
+  optional int32 field67 = 67 [default=0];
+  optional int32 field68 = 68;
+  optional int32 field128 = 128 [default=0];
+  optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"];
+  optional int32 field131 = 131 [default=0];
+}
+
+message SizeMessage1SubMessage {
+  optional int32 field1 = 1 [default=0];
+  optional int32 field2 = 2 [default=0];
+  optional int32 field3 = 3 [default=0];
+  optional string field15 = 15;
+  optional bool field12 = 12 [default=true];
+  optional int64 field13 = 13;
+  optional int64 field14 = 14;
+  optional int32 field16 = 16;
+  optional int32 field19 = 19 [default=2];
+  optional bool field20  = 20 [default=true];
+  optional bool field28 = 28 [default=true];
+  optional fixed64 field21 = 21;
+  optional int32 field22 = 22;
+  optional bool field23 = 23 [ default=false ];
+  optional bool field206 = 206 [default=false];
+  optional fixed32 field203 = 203;
+  optional int32 field204 = 204;
+  optional string field205 = 205;
+  optional uint64 field207 = 207;
+  optional uint64 field300 = 300;
+}
+
+message SizeMessage2 {
+  optional string field1 = 1;
+  optional int64 field3 = 3;
+  optional int64 field4 = 4;
+  optional int64 field30 = 30;
+  optional bool field75  = 75 [default=false];
+  optional string field6 = 6;
+  optional bytes field2 = 2;
+  optional int32 field21 = 21 [default=0];
+  optional int32 field71 = 71;
+  optional float field25 = 25;
+  optional int32 field109 = 109 [default=0];
+  optional int32 field210 = 210 [default=0];
+  optional int32 field211 = 211 [default=0];
+  optional int32 field212 = 212 [default=0];
+  optional int32 field213 = 213 [default=0];
+  optional int32 field216 = 216 [default=0];
+  optional int32 field217 = 217 [default=0];
+  optional int32 field218 = 218 [default=0];
+  optional int32 field220 = 220 [default=0];
+  optional int32 field221 = 221 [default=0];
+  optional float field222 = 222 [default=0.0];
+  optional int32 field63 = 63;
+
+  repeated group Group1 = 10 {
+    required float field11 = 11;
+    optional float field26 = 26;
+    optional string field12 = 12;
+    optional string field13 = 13;
+    repeated string field14 = 14;
+    required uint64 field15 = 15;
+    optional int32 field5 = 5;
+    optional string field27 = 27;
+    optional int32 field28 = 28;
+    optional string field29 = 29;
+    optional string field16 = 16;
+    repeated string field22 = 22;
+    repeated int32 field73 = 73;
+    optional int32 field20 = 20 [default=0];
+    optional string field24 = 24;
+    optional SizeMessage2GroupedMessage field31 = 31;
+  }
+  repeated string field128 = 128;
+  optional int64 field131 = 131;
+  repeated string field127 = 127;
+  optional int32 field129 = 129;
+  repeated int64 field130 = 130;
+  optional bool field205 = 205 [default=false];
+  optional bool field206 = 206 [default=false];
+}
+
+message SizeMessage2GroupedMessage {
+  optional float field1 = 1;
+  optional float field2 = 2;
+  optional float field3 = 3 [default=0.0];
+  optional bool field4 = 4;
+  optional bool field5 = 5;
+  optional bool field6 = 6 [default=true];
+  optional bool field7 = 7 [default=false];
+  optional float field8 = 8;
+  optional bool field9 = 9;
+  optional float field10 = 10;
+  optional int64 field11 = 11;
+}
diff --git a/src/third_party/protobuf-3/benchmarks/readme.txt b/src/third_party/protobuf-3/benchmarks/readme.txt
new file mode 100644
index 0000000..2c836d0
--- /dev/null
+++ b/src/third_party/protobuf-3/benchmarks/readme.txt
@@ -0,0 +1,50 @@
+Contents
+--------
+
+This folder contains three kinds of file:
+
+- Code, such as ProtoBench.java, to build the benchmarking framework.
+- Protocol buffer definitions (.proto files)
+- Sample data files
+
+If we end up with a lot of different benchmarks it may be worth
+separating these out info different directories, but while there are
+so few they might as well all be together.
+
+Running a benchmark (Java)
+--------------------------
+
+1) Build protoc and the Java protocol buffer library. The examples
+   below assume a jar file (protobuf.jar) has been built and copied
+   into this directory.
+
+2) Build ProtoBench:
+   $ javac -d tmp -cp protobuf.jar ProtoBench.java
+   
+3) Generate code for the relevant benchmark protocol buffer, e.g.
+   $ protoc --java_out=tmp google_size.proto google_speed.proto
+   
+4) Build the generated code, e.g.
+   $ cd tmp
+   $ javac -d . -cp ../protobuf.jar benchmarks/*.java
+           
+5) Run the test. Arguments are given in pairs - the first argument
+   is the descriptor type; the second is the filename. For example:
+   $ java -cp .;../protobuf.jar com.google.protocolbuffers.ProtoBench
+          benchmarks.GoogleSize$SizeMessage1 ../google_message1.dat
+          benchmarks.GoogleSpeed$SpeedMessage1 ../google_message1.dat
+          benchmarks.GoogleSize$SizeMessage2 ../google_message2.dat
+          benchmarks.GoogleSpeed$SpeedMessage2 ../google_message2.dat
+          
+6) Wait! Each test runs for around 30 seconds, and there are 6 tests
+   per class/data combination. The above command would therefore take
+   about 12 minutes to run.
+
+   
+Benchmarks available
+--------------------
+
+From Google:
+google_size.proto and google_speed.proto, messages
+google_message1.dat and google_message2.dat. The proto files are
+equivalent, but optimized differently.
diff --git a/src/third_party/protobuf-3/cmake/CMakeLists.txt b/src/third_party/protobuf-3/cmake/CMakeLists.txt
new file mode 100644
index 0000000..f32a0e4
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/CMakeLists.txt
@@ -0,0 +1,153 @@
+# Minimum CMake required
+cmake_minimum_required(VERSION 2.8)
+
+# Project
+project(protobuf C CXX)
+
+# CMake policies
+cmake_policy(SET CMP0022 NEW)
+
+# Options
+option(protobuf_VERBOSE "Enable for verbose output" OFF)
+option(protobuf_BUILD_TESTS "Build tests" ON)
+if (BUILD_SHARED_LIBS)
+  set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
+else (BUILD_SHARED_LIBS)
+  set(protobuf_BUILD_SHARED_LIBS_DEFAULT OFF)
+endif (BUILD_SHARED_LIBS)
+option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" ${protobuf_BUILD_SHARED_LIBS_DEFAULT})
+option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON)
+if (MSVC)
+  set(protobuf_WITH_ZLIB_DEFAULT OFF)
+else (MSVC)
+  set(protobuf_WITH_ZLIB_DEFAULT ON)
+endif (MSVC)
+option(protobuf_WITH_ZLIB "Build with zlib support" ${protobuf_WITH_ZLIB_DEFAULT})
+set(protobuf_DEBUG_POSTFIX "d"
+  CACHE STRING "Default debug postfix")
+
+# Path to main configure script
+set(protobuf_CONFIGURE_SCRIPT "../configure.ac")
+
+# Parse configure script
+set(protobuf_AC_INIT_REGEX
+  "^AC_INIT\\(\\[([^]]+)\\],\\[([^]]+)\\],\\[([^]]+)\\],\\[([^]]+)\\]\\)$")
+file(STRINGS "${protobuf_CONFIGURE_SCRIPT}" protobuf_AC_INIT_LINE
+  LIMIT_COUNT 1 REGEX "^AC_INIT")
+# Description
+string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\1"
+    protobuf_DESCRIPTION    "${protobuf_AC_INIT_LINE}")
+# Version
+string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\2"
+    protobuf_VERSION_STRING "${protobuf_AC_INIT_LINE}")
+# Contact
+string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\3"
+    protobuf_CONTACT        "${protobuf_AC_INIT_LINE}")
+# Parse version tweaks
+set(protobuf_VERSION_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$")
+string(REGEX REPLACE     "${protobuf_VERSION_REGEX}" "\\1"
+  protobuf_VERSION_MAJOR "${protobuf_VERSION_STRING}")
+string(REGEX REPLACE     "${protobuf_VERSION_REGEX}" "\\2"
+  protobuf_VERSION_MINOR "${protobuf_VERSION_STRING}")
+string(REGEX REPLACE     "${protobuf_VERSION_REGEX}" "\\3"
+  protobuf_VERSION_PATCH "${protobuf_VERSION_STRING}")
+# Package version
+set(protobuf_VERSION
+  "${protobuf_VERSION_MAJOR}.${protobuf_VERSION_MINOR}.${protobuf_VERSION_PATCH}")
+
+if(protobuf_VERBOSE)
+  message(STATUS "Configuration script parsing status [")
+  message(STATUS "  Description : ${protobuf_DESCRIPTION}")
+  message(STATUS "  Version     : ${protobuf_VERSION} (${protobuf_VERSION_STRING})")
+  message(STATUS "  Contact     : ${protobuf_CONTACT}")
+  message(STATUS "]")
+endif()
+
+add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)
+
+find_package(Threads REQUIRED)
+if (CMAKE_USE_PTHREADS_INIT)
+  add_definitions(-DHAVE_PTHREAD)
+endif (CMAKE_USE_PTHREADS_INIT)
+
+if (protobuf_WITH_ZLIB)
+  find_package(ZLIB)
+  if (ZLIB_FOUND)
+    set(HAVE_ZLIB 1)
+    # FindZLIB module define ZLIB_INCLUDE_DIRS variable
+    # Set ZLIB_INCLUDE_DIRECTORIES for compatible
+    set(ZLIB_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRECTORIES} ${ZLIB_INCLUDE_DIRS})
+    # Using imported target if exists
+    if (TARGET ZLIB::ZLIB)
+      set(ZLIB_LIBRARIES ZLIB::ZLIB)
+    endif (TARGET ZLIB::ZLIB)
+  else (ZLIB_FOUND)
+    set(HAVE_ZLIB 0)
+    # Explicitly set these to empty (override NOT_FOUND) so cmake doesn't
+    # complain when we use them later.
+    set(ZLIB_INCLUDE_DIRECTORIES)
+    set(ZLIB_LIBRARIES)
+  endif (ZLIB_FOUND)
+endif (protobuf_WITH_ZLIB)
+
+if (HAVE_ZLIB)
+  add_definitions(-DHAVE_ZLIB)
+endif (HAVE_ZLIB)
+
+if (protobuf_BUILD_SHARED_LIBS)
+  set(protobuf_SHARED_OR_STATIC "SHARED")
+else (protobuf_BUILD_SHARED_LIBS)
+  set(protobuf_SHARED_OR_STATIC "STATIC")
+  # In case we are building static libraries, link also the runtime library statically
+  # so that MSVCR*.DLL is not required at runtime.
+  # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+  # This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd
+  # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
+  if (MSVC AND protobuf_MSVC_STATIC_RUNTIME)
+    foreach(flag_var
+        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if(${flag_var} MATCHES "/MD")
+        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+      endif(${flag_var} MATCHES "/MD")
+    endforeach(flag_var)
+  endif (MSVC AND protobuf_MSVC_STATIC_RUNTIME)
+endif (protobuf_BUILD_SHARED_LIBS)
+
+if (MSVC)
+  # Build with multiple processes
+  add_definitions(/MP)
+  add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305)
+  # Allow big object
+  add_definitions(/bigobj)
+  string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR})
+  string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR})
+  configure_file(extract_includes.bat.in extract_includes.bat)
+endif (MSVC)
+
+get_filename_component(protobuf_source_dir ${protobuf_SOURCE_DIR} PATH)
+
+include_directories(
+  ${ZLIB_INCLUDE_DIRECTORIES}
+  ${protobuf_BINARY_DIR}
+  ${protobuf_source_dir}/src)
+
+if (MSVC)
+  # Add the "lib" prefix for generated .lib outputs.
+  set(LIB_PREFIX lib)
+else (MSVC)
+  # When building with "make", "lib" prefix will be added automatically by
+  # the build tool.
+  set(LIB_PREFIX)
+endif (MSVC)
+
+include(libprotobuf-lite.cmake)
+include(libprotobuf.cmake)
+include(libprotoc.cmake)
+include(protoc.cmake)
+
+if (protobuf_BUILD_TESTS)
+  include(tests.cmake)
+endif (protobuf_BUILD_TESTS)
+
+include(install.cmake)
diff --git a/src/third_party/protobuf-3/cmake/README.md b/src/third_party/protobuf-3/cmake/README.md
new file mode 100644
index 0000000..ba281d2
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/README.md
@@ -0,0 +1,336 @@
+This directory contains *CMake* files that can be used to build protobuf
+with *MSVC* on *Windows*. You can build the project from *Command Prompt*
+and using an *Visual Studio* IDE.
+
+You need to have [CMake](http://www.cmake.org), [Visual Studio](https://www.visualstudio.com)
+and optionally [Git](http://git-scm.com) installed on your computer before proceeding.
+
+Most of the instructions will be given to the *Сommand Prompt*, but the same
+actions can be performed using appropriate GUI tools.
+
+Environment Setup
+=================
+
+Open the appropriate *Command Prompt* from the *Start* menu.
+
+For example *VS2013 x64 Native Tools Command Prompt*:
+
+    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64>
+
+Change to your working directory:
+
+    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64>cd C:\Path\to
+    C:\Path\to>
+
+Where *C:\Path\to* is path to your real working directory.
+
+Create a folder where protobuf headers/libraries/binaries will be installed after built:
+
+    C:\Path\to>mkdir install
+
+If *cmake* command is not available from *Command Prompt*, add it to system *PATH* variable:
+
+    C:\Path\to>set PATH=%PATH%;C:\Program Files (x86)\CMake\bin
+
+If *git* command is not available from *Command Prompt*, add it to system *PATH* variable:
+
+    C:\Path\to>set PATH=%PATH%;C:\Program Files\Git\cmd
+
+Good. Now you are ready to continue.
+
+Getting Sources
+===============
+
+You can get the latest stable source packages from the
+[releases](https://github.com/google/protobuf/releases) page.
+Or you can type:
+
+     C:\Path\to> git clone -b [release_tag] https://github.com/google/protobuf.git
+
+Where *[release_tag]* is a git tag like *v3.0.0-beta-1* or a branch name like *master*
+if you want to get the latest code.
+
+Go to the project folder:
+
+     C:\Path\to>cd protobuf
+     C:\Path\to\protobuf>
+
+Protobuf unit-tests require gmock to build. If you download protobuf source code
+from the *releases* page, the *gmock* directory should already be there. If you checkout
+the code via `git clone`, this *gmock* directory won't exist and you will have to
+download it manually or skip building protobuf unit-tests.
+
+You can download gmock as follows:
+
+     C:\Path\to\protobuf>git clone -b release-1.7.0 https://github.com/google/googlemock.git gmock
+
+Then go to *gmock* folder and download gtest:
+
+     C:\Path\to\protobuf>cd gmock
+     C:\Path\to\protobuf\gmock>git clone -b release-1.7.0 https://github.com/google/googletest.git gtest
+
+If you absolutely don't want to build and run protobuf unit-tests, skip
+this steps and use protobuf at your own risk.
+
+Now go to *cmake* folder in protobuf sources:
+
+     C:\Path\to\protobuf\gmock>cd ..\cmake
+     C:\Path\to\protobuf\cmake>
+
+Good. Now you are ready to *CMake* configuration.
+
+CMake Configuration
+===================
+
+*CMake* supports a lot of different
+[generators](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
+for various native build systems.
+We are only interested in
+[Makefile](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#makefile-generators)
+and
+[Visual Studio](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
+generators.
+
+We will use shadow building to separate the temporary files from the protobuf source code.
+
+Create a temporary *build* folder and change your working directory to it:
+
+     C:\Path\to\protobuf\cmake>mkdir build & cd build
+     C:\Path\to\protobuf\cmake\build>
+
+The *Makefile* generator can build the project in only one configuration, so you need to build
+a separate folder for each configuration.
+
+To start using a *Release* configuration:
+
+     C:\Path\to\protobuf\cmake\build>mkdir release & cd release
+     C:\Path\to\protobuf\cmake\build\release>cmake -G "NMake Makefiles" ^
+     -DCMAKE_BUILD_TYPE=Release ^
+     -DCMAKE_INSTALL_PREFIX=../../../../install ^
+     ../..
+
+It will generate *nmake* *Makefile* in current directory.
+
+To use *Debug* configuration:
+
+     C:\Path\to\protobuf\cmake\build>mkdir debug & cd debug
+     C:\Path\to\protobuf\cmake\build\debug>cmake -G "NMake Makefiles" ^
+     -DCMAKE_BUILD_TYPE=Debug ^
+     -DCMAKE_INSTALL_PREFIX=../../../../install ^
+     ../..
+
+It will generate *nmake* *Makefile* in current directory.
+
+To create *Visual Studio* solution file:
+
+     C:\Path\to\protobuf\cmake\build>mkdir solution & cd solution
+     C:\Path\to\protobuf\cmake\build\solution>cmake -G "Visual Studio 12 2013 Win64" ^
+     -DCMAKE_INSTALL_PREFIX=../../../../install ^
+     ../..
+
+It will generate *Visual Studio* solution file *protobuf.sln* in current directory.
+
+If the *gmock* directory does not exist, and you do not want to build protobuf unit tests,
+you need to add *cmake* command argument `-Dprotobuf_BUILD_TESTS=OFF` to disable testing.
+
+Compiling
+=========
+
+To compile protobuf:
+
+     C:\Path\to\protobuf\cmake\build\release>nmake
+
+or
+
+     C:\Path\to\protobuf\cmake\build\debug>nmake
+
+And wait for the compilation to finish.
+
+If you prefer to use the IDE:
+
+  * Open the generated protobuf.sln file in Microsoft Visual Studio.
+  * Choose "Debug" or "Release" configuration as desired.
+  * From the Build menu, choose "Build Solution".
+
+And wait for the compilation to finish.
+
+Testing
+======
+
+To run unit-tests, first you must compile protobuf as described above.
+Then run:
+
+     C:\Path\to\protobuf\cmake\build\release>nmake check
+
+or
+
+     C:\Path\to\protobuf\cmake\build\debug>nmake check
+
+You can also build project *check* from Visual Studio solution.
+Yes, it may sound strange, but it works.
+
+You should see output similar to:
+
+     Running main() from gmock_main.cc
+     [==========] Running 1546 tests from 165 test cases.
+     
+     ...
+     
+     [==========] 1546 tests from 165 test cases ran. (2529 ms total)
+     [  PASSED  ] 1546 tests.
+
+To run specific tests:
+
+     C:\Path\to\protobuf>cmake\build\release\tests.exe --gtest_filter=AnyTest*
+     Running main() from gmock_main.cc
+     Note: Google Test filter = AnyTest*
+     [==========] Running 3 tests from 1 test case.
+     [----------] Global test environment set-up.
+     [----------] 3 tests from AnyTest
+     [ RUN      ] AnyTest.TestPackAndUnpack
+     [       OK ] AnyTest.TestPackAndUnpack (0 ms)
+     [ RUN      ] AnyTest.TestPackAndUnpackAny
+     [       OK ] AnyTest.TestPackAndUnpackAny (0 ms)
+     [ RUN      ] AnyTest.TestIs
+     [       OK ] AnyTest.TestIs (0 ms)
+     [----------] 3 tests from AnyTest (1 ms total)
+     
+     [----------] Global test environment tear-down
+     [==========] 3 tests from 1 test case ran. (2 ms total)
+     [  PASSED  ] 3 tests.
+
+Note that the tests must be run from the source folder.
+
+If all tests are passed, safely continue.
+
+Installing
+==========
+
+To install protobuf to the specified *install* folder:
+
+     C:\Path\to\protobuf\cmake\build\release>nmake install
+
+or
+
+     C:\Path\to\protobuf\cmake\build\debug>nmake install
+
+You can also build project *INSTALL* from Visual Studio solution.
+It sounds not so strange and it works.
+
+This will create the following folders under the *install* location:
+  * bin - that contains protobuf *protoc.exe* compiler;
+  * include - that contains C++ headers and protobuf *.proto files;
+  * lib - that contains linking libraries and *CMake* configuration files for *protobuf* package.
+
+Now you can if needed:
+  * Copy the contents of the include directory to wherever you want to put headers.
+  * Copy protoc.exe wherever you put build tools (probably somewhere in your PATH).
+  * Copy linking libraries libprotobuf[d].lib, libprotobuf-lite[d].lib, and libprotoc[d].lib wherever you put libraries.
+
+To avoid conflicts between the MSVC debug and release runtime libraries, when
+compiling a debug build of your application, you may need to link against a
+debug build of libprotobufd.lib with "d" postfix.  Similarly, release builds should link against
+release libprotobuf.lib library.
+
+DLLs vs. static linking
+=======================
+
+Static linking is now the default for the Protocol Buffer libraries.  Due to
+issues with Win32's use of a separate heap for each DLL, as well as binary
+compatibility issues between different versions of MSVC's STL library, it is
+recommended that you use static linkage only.  However, it is possible to
+build libprotobuf and libprotoc as DLLs if you really want.  To do this,
+do the following:
+
+  * Add an additional flag `-Dprotobuf_BUILD_SHARED_LIBS=ON` when invoking cmake
+  * Follow the same steps as described in the above section.
+  * When compiling your project, make sure to `#define PROTOBUF_USE_DLLS`.
+
+When distributing your software to end users, we strongly recommend that you
+do NOT install libprotobuf.dll or libprotoc.dll to any shared location.
+Instead, keep these libraries next to your binaries, in your application's
+own install directory.  C++ makes it very difficult to maintain binary
+compatibility between releases, so it is likely that future versions of these
+libraries will *not* be usable as drop-in replacements.
+
+If your project is itself a DLL intended for use by third-party software, we
+recommend that you do NOT expose protocol buffer objects in your library's
+public interface, and that you statically link protocol buffers into your
+library.
+
+ZLib support
+============
+
+If you want to include GzipInputStream and GzipOutputStream
+(google/protobuf/io/gzip_stream.h) in libprotobuf, you will need to do a few
+additional steps.
+
+Obtain a copy of the zlib library.  The pre-compiled DLL at zlib.net works.
+You need prepare it:
+
+  * Make sure zlib's two headers are in your `C:\Path\to\install\include` path
+  * Make sure zlib's linking libraries (*.lib file) is in your
+    `C:\Path\to\install\lib` library path.
+
+You can also compile it from source by yourself.
+
+Getting sources:
+
+     C:\Path\to>git clone -b v1.2.8 https://github.com/madler/zlib.git
+     C:\Path\to>cd zlib
+
+Compiling and Installing:
+
+     C:\Path\to\zlib>mkdir build & cd build
+     C:\Path\to\zlib\build>mkdir release & cd release
+     C:\Path\to\zlib\build\release>cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release ^
+     -DCMAKE_INSTALL_PREFIX=../../../install ../..
+     C:\Path\to\zlib\build\release>nmake & nmake install
+
+You can make *debug* version or use *Visual Studio* generator also as before for the
+protobuf project.
+
+Now add *bin* folder from *install* to system *PATH*:
+
+     C:\Path\to>set PATH=%PATH%;C:\Path\to\install\bin
+
+You need reconfigure protobuf with flag `-Dprotobuf_WITH_ZLIB=ON` when invoking cmake.
+
+Note that if you have compiled ZLIB yourself, as stated above,
+further disable the option `-Dprotobuf_MSVC_STATIC_RUNTIME=OFF`.
+
+If it reports NOTFOUND for zlib_include or zlib_lib, you might haven't put
+the headers or the .lib file in the right directory.
+
+Build and testing protobuf as usual.
+
+Notes on Compiler Warnings
+==========================
+
+The following warnings have been disabled while building the protobuf libraries
+and compiler.  You may have to disable some of them in your own project as
+well, or live with them.
+
+* C4018 - 'expression' : signed/unsigned mismatch
+* C4146 - unary minus operator applied to unsigned type, result still unsigned
+* C4244 - Conversion from 'type1' to 'type2', possible loss of data.
+* C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by
+  clients of class 'type2'
+* C4267 - Conversion from 'size_t' to 'type', possible loss of data.
+* C4305 - 'identifier' : truncation from 'type1' to 'type2'
+* C4355 - 'this' : used in base member initializer list
+* C4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
+* C4996 - 'function': was declared deprecated
+
+C4251 is of particular note, if you are compiling the Protocol Buffer library
+as a DLL (see previous section).  The protocol buffer library uses templates in
+its public interfaces.  MSVC does not provide any reasonable way to export
+template classes from a DLL.  However, in practice, it appears that exporting
+templates is not necessary anyway.  Since the complete definition of any
+template is available in the header files, anyone importing the DLL will just
+end up compiling instances of the templates into their own binary.  The
+Protocol Buffer implementation does not rely on static template members being
+unique, so there should be no problem with this, but MSVC prints warning
+nevertheless.  So, we disable it.  Unfortunately, this warning will also be
+produced when compiling code which merely uses protocol buffers, meaning you
+may have to disable it in your code too.
diff --git a/src/third_party/protobuf-3/cmake/extract_includes.bat.in b/src/third_party/protobuf-3/cmake/extract_includes.bat.in
new file mode 100644
index 0000000..b593e0c
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/extract_includes.bat.in
@@ -0,0 +1,124 @@
+mkdir include
+mkdir include\google
+mkdir include\google\protobuf
+mkdir include\google\protobuf\compiler
+mkdir include\google\protobuf\compiler\cpp
+mkdir include\google\protobuf\compiler\csharp
+mkdir include\google\protobuf\compiler\java
+mkdir include\google\protobuf\compiler\javanano
+mkdir include\google\protobuf\compiler\js
+mkdir include\google\protobuf\compiler\objectivec
+mkdir include\google\protobuf\compiler\python
+mkdir include\google\protobuf\compiler\ruby
+mkdir include\google\protobuf\io
+mkdir include\google\protobuf\stubs
+mkdir include\google\protobuf\util
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h include\google\protobuf\any.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h include\google\protobuf\any.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h include\google\protobuf\api.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h include\google\protobuf\arena.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h include\google\protobuf\compiler\csharp\csharp_names.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generator.h include\google\protobuf\compiler\js\js_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h include\google\protobuf\compiler\objectivec\objectivec_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h include\google\protobuf\compiler\objectivec\objectivec_helpers.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h include\google\protobuf\duration.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h include\google\protobuf\empty.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h include\google\protobuf\field_mask.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h include\google\protobuf\map.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h include\google\protobuf\message.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h include\google\protobuf\message_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h include\google\protobuf\metadata.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h include\google\protobuf\service.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h include\google\protobuf\source_context.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h include\google\protobuf\struct.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomic_sequence_num.h include\google\protobuf\stubs\atomic_sequence_num.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_power.h include\google\protobuf\stubs\atomicops_internals_power.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h include\google\protobuf\stubs\bytestream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h include\google\protobuf\stubs\callback.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h include\google\protobuf\stubs\logging.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h include\google\protobuf\stubs\macros.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h include\google\protobuf\stubs\mutex.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h include\google\protobuf\stubs\port.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\scoped_ptr.h include\google\protobuf\stubs\scoped_ptr.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h include\google\protobuf\stubs\shared_ptr.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h include\google\protobuf\stubs\status.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h include\google\protobuf\stubs\stringpiece.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h include\google\protobuf\timestamp.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h include\google\protobuf\util\field_comparator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_mask_util.h include\google\protobuf\util\field_mask_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h include\google\protobuf\util\json_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h include\google\protobuf\util\message_differencer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\time_util.h include\google\protobuf\util\time_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h include\google\protobuf\util\type_resolver.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h include\google\protobuf\util\type_resolver_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h include\google\protobuf\wrappers.pb.h
diff --git a/src/third_party/protobuf-3/cmake/install.cmake b/src/third_party/protobuf-3/cmake/install.cmake
new file mode 100644
index 0000000..dbb4265
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/install.cmake
@@ -0,0 +1,103 @@
+include(GNUInstallDirs)
+
+foreach(_library
+  libprotobuf-lite
+  libprotobuf
+  libprotoc)
+  set_property(TARGET ${_library}
+    PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+  install(TARGETS ${_library} EXPORT protobuf-targets
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
+endforeach()
+
+install(TARGETS protoc EXPORT protobuf-targets
+  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
+
+if(TRUE)
+  file(STRINGS extract_includes.bat.in _extract_strings
+    REGEX "^copy")
+  foreach(_extract_string ${_extract_strings})
+    string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""
+      _extract_string ${_extract_string})
+    string(REPLACE "\\" "/" _extract_string ${_extract_string})
+    string(REGEX MATCH "^[^ ]+"
+      _extract_from ${_extract_string})
+    string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"
+      _extract_to ${_extract_string})
+    get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)
+    get_filename_component(_extract_name ${_extract_to} NAME)
+    get_filename_component(_extract_to ${_extract_to} PATH)
+    string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"
+      _extract_to "${_extract_to}")
+    if(EXISTS "${_extract_from}")
+      install(FILES "${_extract_from}"
+        DESTINATION "${_extract_to}"
+        COMPONENT protobuf-headers
+        RENAME "${_extract_name}")
+    else()
+      message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
+        "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
+        "but there not exists. The file will not be installed.")
+    endif()
+  endforeach()
+endif()
+
+# Internal function for parsing auto tools scripts
+function(_protobuf_auto_list FILE_NAME VARIABLE)
+  file(STRINGS ${FILE_NAME} _strings)
+  set(_list)
+  foreach(_string ${_strings})
+    set(_found)
+    string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
+    if(_found)
+      string(LENGTH "${_found}" _length)
+      string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
+      foreach(_item ${_draft_list})
+        string(STRIP "${_item}" _item)
+        list(APPEND _list "${_item}")
+      endforeach()
+    endif()
+  endforeach()
+  set(${VARIABLE} ${_list} PARENT_SCOPE)
+endfunction()
+
+# Install well-known type proto files
+_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)
+foreach(_file ${nobase_dist_proto_DATA})
+  get_filename_component(_file_from "../src/${_file}" ABSOLUTE)
+  get_filename_component(_file_name ${_file} NAME)
+  get_filename_component(_file_path ${_file} PATH)
+  if(EXISTS "${_file_from}")
+    install(FILES "${_file_from}"
+      DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"
+      COMPONENT protobuf-protos
+      RENAME "${_file_name}")
+  else()
+    message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
+      "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "
+      "but there not exists. The file will not be installed.")
+  endif()
+endforeach()
+
+# Export configuration
+
+install(EXPORT protobuf-targets
+  DESTINATION "lib/cmake/protobuf"
+  COMPONENT protobuf-export)
+
+configure_file(protobuf-config.cmake.in
+  protobuf-config.cmake @ONLY)
+configure_file(protobuf-config-version.cmake.in
+  protobuf-config-version.cmake @ONLY)
+configure_file(protobuf-module.cmake.in
+  protobuf-module.cmake @ONLY)
+
+install(FILES
+  "${protobuf_BINARY_DIR}/protobuf-config.cmake"
+  "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
+  "${protobuf_BINARY_DIR}/protobuf-module.cmake"
+  DESTINATION "lib/cmake/protobuf"
+  COMPONENT protobuf-export)
diff --git a/src/third_party/protobuf-3/cmake/libprotobuf-lite.cmake b/src/third_party/protobuf-3/cmake/libprotobuf-lite.cmake
new file mode 100644
index 0000000..036b051
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/libprotobuf-lite.cmake
@@ -0,0 +1,38 @@
+set(libprotobuf_lite_files
+  ${protobuf_source_dir}/src/google/protobuf/arena.cc
+  ${protobuf_source_dir}/src/google/protobuf/arenastring.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/message_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/strutil.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/time.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.cc
+)
+
+add_library(libprotobuf-lite ${protobuf_SHARED_OR_STATIC}
+  ${libprotobuf_lite_files})
+target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT})
+target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src)
+if(MSVC AND protobuf_BUILD_SHARED_LIBS)
+  target_compile_definitions(libprotobuf-lite
+    PUBLIC  PROTOBUF_USE_DLLS
+    PRIVATE LIBPROTOBUF_EXPORTS)
+endif()
+set_target_properties(libprotobuf-lite PROPERTIES
+    OUTPUT_NAME ${LIB_PREFIX}protobuf-lite
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
diff --git a/src/third_party/protobuf-3/cmake/libprotobuf.cmake b/src/third_party/protobuf-3/cmake/libprotobuf.cmake
new file mode 100644
index 0000000..8930c1c
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/libprotobuf.cmake
@@ -0,0 +1,68 @@
+set(libprotobuf_files
+  ${protobuf_source_dir}/src/google/protobuf/any.cc
+  ${protobuf_source_dir}/src/google/protobuf/any.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/api.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/importer.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/parser.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_database.cc
+  ${protobuf_source_dir}/src/google/protobuf/duration.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/dynamic_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/empty.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set_heavy.cc
+  ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/printer.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/message.cc
+  ${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc
+  ${protobuf_source_dir}/src/google/protobuf/service.cc
+  ${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/struct.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc
+  ${protobuf_source_dir}/src/google/protobuf/text_format.cc
+  ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/type.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/unknown_field_set.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_comparator.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_mask_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/datapiece.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/error_listener.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/field_mask_utility.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_escaping.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/object_writer.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/proto_writer.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/utility.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/json_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/message_differencer.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/time_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format.cc
+  ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc
+)
+
+add_library(libprotobuf ${protobuf_SHARED_OR_STATIC}
+  ${libprotobuf_lite_files} ${libprotobuf_files})
+target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
+target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
+if(MSVC AND protobuf_BUILD_SHARED_LIBS)
+  target_compile_definitions(libprotobuf
+    PUBLIC  PROTOBUF_USE_DLLS
+    PRIVATE LIBPROTOBUF_EXPORTS)
+endif()
+set_target_properties(libprotobuf PROPERTIES
+    OUTPUT_NAME ${LIB_PREFIX}protobuf
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
diff --git a/src/third_party/protobuf-3/cmake/libprotoc.cmake b/src/third_party/protobuf-3/cmake/libprotoc.cmake
new file mode 100644
index 0000000..8df8986
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/libprotoc.cmake
@@ -0,0 +1,106 @@
+set(libprotoc_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_context.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_name_resolver.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_service.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/js/js_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.cc
+)
+
+add_library(libprotoc ${protobuf_SHARED_OR_STATIC}
+  ${libprotoc_files})
+target_link_libraries(libprotoc libprotobuf)
+if(MSVC AND protobuf_BUILD_SHARED_LIBS)
+  target_compile_definitions(libprotoc
+    PUBLIC  PROTOBUF_USE_DLLS
+    PRIVATE LIBPROTOC_EXPORTS)
+endif()
+set_target_properties(libprotoc PROPERTIES
+    COMPILE_DEFINITIONS LIBPROTOC_EXPORTS
+    OUTPUT_NAME ${LIB_PREFIX}protoc
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
diff --git a/src/third_party/protobuf-3/cmake/protobuf-config-version.cmake.in b/src/third_party/protobuf-3/cmake/protobuf-config-version.cmake.in
new file mode 100644
index 0000000..1f171c6
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/protobuf-config-version.cmake.in
@@ -0,0 +1 @@
+set(PACKAGE_VERSION @protobuf_VERSION@)
diff --git a/src/third_party/protobuf-3/cmake/protobuf-config.cmake.in b/src/third_party/protobuf-3/cmake/protobuf-config.cmake.in
new file mode 100644
index 0000000..bb0997b
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/protobuf-config.cmake.in
@@ -0,0 +1,27 @@
+# Version info variables
+set(PROTOBUF_VERSION        "@protobuf_VERSION@")
+set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
+
+# Current dir
+get_filename_component(_PROTOBUF_PACKAGE_PREFIX
+  "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+# Imported targets
+include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+  "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+  "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+  "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+
+# CMake FindProtobuf module compatible file
+if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
+  include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
+endif()
+
+# Cleanup temporary variables.
+set(_PROTOBUF_PACKAGE_PREFIX)
+set(_PROTOBUF_IMPORT_PREFIX)
diff --git a/src/third_party/protobuf-3/cmake/protobuf-module.cmake.in b/src/third_party/protobuf-3/cmake/protobuf-module.cmake.in
new file mode 100644
index 0000000..d81dc45
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/protobuf-module.cmake.in
@@ -0,0 +1,139 @@
+if(PROTOBUF_SRC_ROOT_FOLDER)
+  message(AUTHOR_WARNING "Variable PROTOBUF_SRC_ROOT_FOLDER defined, but not"
+    " used in CONFIG mode")
+endif()
+
+function(PROTOBUF_GENERATE_CPP SRCS HDRS)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
+    return()
+  endif()
+
+  if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(FIL ${ARGN})
+      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  else()
+    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  # Add well-known type protos include path
+  list(APPEND _protobuf_include_path
+    -I "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
+
+  if(DEFINED PROTOBUF_IMPORT_DIRS)
+    foreach(DIR ${PROTOBUF_IMPORT_DIRS})
+      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  endif()
+
+  set(${SRCS})
+  set(${HDRS})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
+    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
+
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
+             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
+      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
+      DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE}
+      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+      VERBATIM)
+  endforeach()
+
+  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
+  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+  set(${HDRS} ${${HDRS}} PARENT_SCOPE)
+endfunction()
+
+# Internal function: search for normal library as well as a debug one
+#    if the debug one is specified also include debug/optimized keywords
+#    in *_LIBRARIES variable
+function(_protobuf_find_libraries name filename)
+   get_target_property(${name}_LIBRARY lib${filename}
+     IMPORTED_LOCATION_RELEASE)
+   set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
+   get_target_property(${name}_LIBRARY_DEBUG lib${filename}
+     IMPORTED_LOCATION_DEBUG)
+   set(${name}_LIBRARY_DEBUG "${${name}_LIBRARY_DEBUG}" PARENT_SCOPE)
+
+   if(NOT ${name}_LIBRARY_DEBUG)
+      # There is no debug library
+      set(${name}_LIBRARY_DEBUG ${${name}_LIBRARY} PARENT_SCOPE)
+      set(${name}_LIBRARIES     ${${name}_LIBRARY} PARENT_SCOPE)
+   else()
+      # There IS a debug library
+      set(${name}_LIBRARIES
+          optimized ${${name}_LIBRARY}
+          debug     ${${name}_LIBRARY_DEBUG}
+          PARENT_SCOPE
+      )
+   endif()
+endfunction()
+
+# Internal function: find threads library
+function(_protobuf_find_threads)
+    set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+    find_package(Threads)
+    if(Threads_FOUND)
+        list(APPEND PROTOBUF_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+        set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARIES}" PARENT_SCOPE)
+    endif()
+endfunction()
+
+#
+# Main.
+#
+
+# By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
+# for each directory where a proto file is referenced.
+if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
+  set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
+endif()
+
+# The Protobuf library
+_protobuf_find_libraries(PROTOBUF protobuf)
+
+# The Protobuf Lite library
+_protobuf_find_libraries(PROTOBUF_LITE protobuf-lite)
+
+# The Protobuf Protoc Library
+_protobuf_find_libraries(PROTOBUF_PROTOC protoc)
+
+if(UNIX)
+  _protobuf_find_threads()
+endif()
+
+# Set the include directory
+set(PROTOBUF_INCLUDE_DIR "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
+
+# Set the protoc Executable
+get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
+  IMPORTED_LOCATION_RELEASE)
+if(NOT PROTOBUF_PROTOC_EXECUTABLE)
+  get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
+    IMPORTED_LOCATION_DEBUG)
+endif()
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
+    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+
+if(PROTOBUF_FOUND)
+    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
+endif()
diff --git a/src/third_party/protobuf-3/cmake/protoc.cmake b/src/third_party/protobuf-3/cmake/protoc.cmake
new file mode 100644
index 0000000..4f07c38
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/protoc.cmake
@@ -0,0 +1,6 @@
+set(protoc_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/main.cc
+)
+
+add_executable(protoc ${protoc_files})
+target_link_libraries(protoc libprotobuf libprotoc)
diff --git a/src/third_party/protobuf-3/cmake/tests.cmake b/src/third_party/protobuf-3/cmake/tests.cmake
new file mode 100644
index 0000000..76fdf8e
--- /dev/null
+++ b/src/third_party/protobuf-3/cmake/tests.cmake
@@ -0,0 +1,214 @@
+if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../gmock/CMakeLists.txt")
+  message(FATAL_ERROR "Cannot find gmock directory.")
+endif()
+
+option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
+  "Using absolute test_plugin path in tests" ON)
+
+include_directories(
+  ${protobuf_source_dir}/gmock
+  ${protobuf_source_dir}/gmock/gtest
+  ${protobuf_source_dir}/gmock/gtest/include
+  ${protobuf_source_dir}/gmock/include
+)
+
+add_library(gmock STATIC
+  ${protobuf_source_dir}/gmock/src/gmock-all.cc
+  ${protobuf_source_dir}/gmock/gtest/src/gtest-all.cc
+)
+add_library(gmock_main STATIC ${protobuf_source_dir}/gmock/src/gmock_main.cc)
+target_link_libraries(gmock_main gmock)
+
+set(lite_test_protos
+  google/protobuf/map_lite_unittest.proto
+  google/protobuf/unittest_import_lite.proto
+  google/protobuf/unittest_import_public_lite.proto
+  google/protobuf/unittest_lite.proto
+  google/protobuf/unittest_no_arena_lite.proto
+)
+
+set(tests_protos
+  google/protobuf/any_test.proto
+  google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+  google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
+  google/protobuf/map_proto2_unittest.proto
+  google/protobuf/map_unittest.proto
+  google/protobuf/unittest.proto
+  google/protobuf/unittest_arena.proto
+  google/protobuf/unittest_custom_options.proto
+  google/protobuf/unittest_drop_unknown_fields.proto
+  google/protobuf/unittest_embed_optimize_for.proto
+  google/protobuf/unittest_empty.proto
+  google/protobuf/unittest_import.proto
+  google/protobuf/unittest_import_public.proto
+  google/protobuf/unittest_lite_imports_nonlite.proto
+  google/protobuf/unittest_mset.proto
+  google/protobuf/unittest_mset_wire_format.proto
+  google/protobuf/unittest_no_arena.proto
+  google/protobuf/unittest_no_arena_import.proto
+  google/protobuf/unittest_no_field_presence.proto
+  google/protobuf/unittest_no_generic_services.proto
+  google/protobuf/unittest_optimize_for.proto
+  google/protobuf/unittest_preserve_unknown_enum.proto
+  google/protobuf/unittest_preserve_unknown_enum2.proto
+  google/protobuf/unittest_proto3_arena.proto
+  google/protobuf/unittest_proto3_arena_lite.proto
+  google/protobuf/unittest_proto3_lite.proto
+  google/protobuf/unittest_well_known_types.proto
+  google/protobuf/util/internal/testdata/anys.proto
+  google/protobuf/util/internal/testdata/books.proto
+  google/protobuf/util/internal/testdata/default_value.proto
+  google/protobuf/util/internal/testdata/default_value_test.proto
+  google/protobuf/util/internal/testdata/field_mask.proto
+  google/protobuf/util/internal/testdata/maps.proto
+  google/protobuf/util/internal/testdata/oneofs.proto
+  google/protobuf/util/internal/testdata/struct.proto
+  google/protobuf/util/internal/testdata/timestamp_duration.proto
+  google/protobuf/util/json_format_proto3.proto
+  google/protobuf/util/message_differencer_unittest.proto
+)
+
+macro(compile_proto_file filename)
+  get_filename_component(dirname ${filename} PATH)
+  get_filename_component(basename ${filename} NAME_WE)
+  add_custom_command(
+    OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc
+    DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+        --proto_path=${protobuf_source_dir}/src
+        --cpp_out=${protobuf_source_dir}/src
+  )
+endmacro(compile_proto_file)
+
+set(lite_test_proto_files)
+foreach(proto_file ${lite_test_protos})
+  compile_proto_file(${proto_file})
+  string(REPLACE .proto .pb.cc pb_file ${proto_file})
+  set(lite_test_proto_files ${lite_test_proto_files}
+      ${protobuf_source_dir}/src/${pb_file})
+endforeach(proto_file)
+
+set(tests_proto_files)
+foreach(proto_file ${tests_protos})
+  compile_proto_file(${proto_file})
+  string(REPLACE .proto .pb.cc pb_file ${proto_file})
+  set(tests_proto_files ${tests_proto_files}
+      ${protobuf_source_dir}/src/${pb_file})
+endforeach(proto_file)
+
+set(common_test_files
+  ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/googletest.cc
+)
+
+set(common_lite_test_files
+  ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_lite_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_util_lite.cc
+)
+
+set(tests_files
+  ${protobuf_source_dir}/src/google/protobuf/any_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/metadata_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/importer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/parser_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_database_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/drop_unknown_fields_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/dynamic_message_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/coded_stream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/printer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/tokenizer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_field_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/no_field_presence_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_arena_lite_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_comparator_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_mask_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/json_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/message_differencer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/time_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/well_known_types_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc
+)
+
+if(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
+  add_compile_options(-DGOOGLE_PROTOBUF_TEST_PLUGIN_PATH="$<TARGET_FILE:test_plugin>")
+endif()
+
+add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files})
+target_link_libraries(tests libprotoc libprotobuf gmock_main)
+
+set(test_plugin_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.h
+  ${protobuf_source_dir}/src/google/protobuf/compiler/test_plugin.cc
+)
+
+add_executable(test_plugin ${test_plugin_files})
+target_link_libraries(test_plugin libprotoc libprotobuf gmock)
+
+set(lite_test_files
+  ${protobuf_source_dir}/src/google/protobuf/lite_unittest.cc
+)
+add_executable(lite-test ${lite_test_files} ${common_lite_test_files} ${lite_test_proto_files})
+target_link_libraries(lite-test libprotobuf-lite)
+
+set(lite_arena_test_files
+  ${protobuf_source_dir}/src/google/protobuf/lite_arena_unittest.cc
+)
+add_executable(lite-arena-test ${lite_arena_test_files} ${common_lite_test_files} ${lite_test_proto_files})
+target_link_libraries(lite-arena-test libprotobuf-lite gmock_main)
+
+add_custom_target(check
+  COMMAND tests
+  WORKING_DIRECTORY ${protobuf_source_dir})
diff --git a/src/third_party/protobuf-3/configure.ac b/src/third_party/protobuf-3/configure.ac
new file mode 100644
index 0000000..bdc72ee
--- /dev/null
+++ b/src/third_party/protobuf-3/configure.ac
@@ -0,0 +1,184 @@
+## Process this file with autoconf to produce configure.
+## In general, the safest way to proceed is to run ./autogen.sh
+
+AC_PREREQ(2.59)
+
+# Note:  If you change the version, you must also update it in:
+# * java/pom.xml
+# * python/setup.py
+# * src/google/protobuf/stubs/common.h
+# * src/Makefile.am (Update -version-info for LDFLAGS if needed)
+#
+# In the SVN trunk, the version should always be the next anticipated release
+# version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
+# the size of one file name in the dist tarfile over the 99-char limit.)
+AC_INIT([Protocol Buffers],[3.0.0-beta-3],[protobuf@googlegroups.com],[protobuf])
+
+AM_MAINTAINER_MODE([enable])
+
+AC_CONFIG_SRCDIR(src/google/protobuf/message.cc)
+# The config file is generated but not used by the source code, since we only
+# need very few of them, e.g. HAVE_PTHREAD and HAVE_ZLIB. Those macros are
+# passed down in CXXFLAGS manually in src/Makefile.am
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
+case "$DIST_LANG" in
+  "") DIST_LANG=all ;;
+  all | cpp | csharp | java | python | javanano | objectivec | ruby | js) ;;
+  *) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
+esac
+AC_SUBST(DIST_LANG)
+
+# autoconf's default CXXFLAGS are usually "-g -O2".  These aren't necessarily
+# the best choice for libprotobuf.
+AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"],
+      [CFLAGS=""])
+AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],
+      [CXXFLAGS=""])
+
+AC_CANONICAL_TARGET
+
+AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
+
+AC_ARG_WITH([zlib],
+  [AS_HELP_STRING([--with-zlib],
+    [include classes for streaming compressed data in and out @<:@default=check@:>@])],
+  [],[with_zlib=check])
+
+AC_ARG_WITH([protoc],
+  [AS_HELP_STRING([--with-protoc=COMMAND],
+    [use the given protoc command instead of building a new one when building tests (useful for cross-compiling)])],
+  [],[with_protoc=no])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_LANG([C++])
+ACX_USE_SYSTEM_EXTENSIONS
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
+AC_PROG_OBJC
+
+# test_util.cc takes forever to compile with GCC and optimization turned on.
+AC_MSG_CHECKING([C++ compiler flags...])
+AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
+  AS_IF([test "$GCC" = "yes"],[
+    PROTOBUF_OPT_FLAG="-O2"
+    CXXFLAGS="${CXXFLAGS} -g"
+  ])
+
+  # Protocol Buffers contains several checks that are intended to be used only
+  # for debugging and which might hurt performance.  Most users are probably
+  # end users who don't want these checks, so add -DNDEBUG by default.
+  CXXFLAGS="$CXXFLAGS -DNDEBUG"
+
+  AC_MSG_RESULT([use default: $PROTOBUF_OPT_FLAG $CXXFLAGS])
+],[
+  AC_MSG_RESULT([use user-supplied: $CXXFLAGS])
+])
+
+AC_SUBST(PROTOBUF_OPT_FLAG)
+
+ACX_CHECK_SUNCC
+
+# Have to do libtool after SUNCC, other wise it "helpfully" adds Crun Cstd
+# to the link
+AC_PROG_LIBTOOL
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdlib.h unistd.h])
+
+# Checks for library functions.
+AC_FUNC_MEMCMP
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([ftruncate memset mkdir strchr strerror strtol])
+
+# Check for zlib.
+HAVE_ZLIB=0
+AS_IF([test "$with_zlib" != no], [
+  AC_MSG_CHECKING([zlib version])
+
+  # First check the zlib header version.
+  AC_COMPILE_IFELSE(
+    [AC_LANG_PROGRAM([[
+        #include <zlib.h>
+        #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
+        # error zlib version too old
+        #endif
+        ]], [])], [
+    AC_MSG_RESULT([ok (1.2.0.4 or later)])
+
+    # Also need to add -lz to the linker flags and make sure this succeeds.
+    AC_SEARCH_LIBS([zlibVersion], [z], [
+      AC_DEFINE([HAVE_ZLIB], [1], [Enable classes using zlib compression.])
+      HAVE_ZLIB=1
+    ], [
+      AS_IF([test "$with_zlib" != check], [
+        AC_MSG_FAILURE([--with-zlib was given, but no working zlib library was found])
+      ])
+    ])
+  ], [
+    AS_IF([test "$with_zlib" = check], [
+      AC_MSG_RESULT([headers missing or too old (requires 1.2.0.4)])
+    ], [
+      AC_MSG_FAILURE([--with-zlib was given, but zlib headers were not present or were too old (requires 1.2.0.4)])
+    ])
+  ])
+])
+AM_CONDITIONAL([HAVE_ZLIB], [test $HAVE_ZLIB = 1])
+
+AS_IF([test "$with_protoc" != "no"], [
+  PROTOC=$with_protoc
+  AS_IF([test "$with_protoc" = "yes"], [
+    # No argument given.  Use system protoc.
+    PROTOC=protoc
+  ])
+  AS_IF([echo "$PROTOC" | grep -q '^@<:@^/@:>@.*/'], [
+    # Does not start with a slash, but contains a slash.  So, it's a relative
+    # path (as opposed to an absolute path or an executable in $PATH).
+    # Since it will actually be executed from the src directory, prefix with
+    # the current directory.  We also insert $ac_top_build_prefix in case this
+    # is a nested package and --with-protoc was actually given on the outer
+    # package's configure script.
+    PROTOC=`pwd`/${ac_top_build_prefix}$PROTOC
+  ])
+  AC_SUBST([PROTOC])
+])
+AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"])
+
+ACX_PTHREAD
+AM_CONDITIONAL([HAVE_PTHREAD], [test "x$acx_pthread_ok" = "xyes"])
+
+# We still keep this for improving pbconfig.h for unsupported platforms.
+AC_CXX_STL_HASH
+
+case "$target_os" in
+  mingw* | cygwin* | win*)
+    ;;
+  *)
+    # Need to link against rt on Solaris
+    AC_SEARCH_LIBS([sched_yield], [rt], [], [AC_MSG_FAILURE([sched_yield was not found on your system])])
+    ;;
+esac
+
+# Enable ObjC support for conformance directory on OS X.
+OBJC_CONFORMANCE_TEST=0
+case "$target_os" in
+  darwin*)
+    OBJC_CONFORMANCE_TEST=1
+    ;;
+esac
+AM_CONDITIONAL([OBJC_CONFORMANCE_TEST], [test $OBJC_CONFORMANCE_TEST = 1])
+
+# HACK:  Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS,
+#   since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock
+#   too.
+export CFLAGS
+export CXXFLAGS
+AC_CONFIG_SUBDIRS([gmock])
+
+AC_CONFIG_FILES([Makefile src/Makefile benchmarks/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc])
+AC_OUTPUT
diff --git a/src/third_party/protobuf-3/conformance/ConformanceJava.java b/src/third_party/protobuf-3/conformance/ConformanceJava.java
new file mode 100644
index 0000000..43787ff
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/ConformanceJava.java
@@ -0,0 +1,142 @@
+
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.util.JsonFormat;
+import com.google.protobuf.util.JsonFormat.TypeRegistry;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+class ConformanceJava {
+  private int testCount = 0;
+  private TypeRegistry typeRegistry;
+
+  private boolean readFromStdin(byte[] buf, int len) throws Exception {
+    int ofs = 0;
+    while (len > 0) {
+      int read = System.in.read(buf, ofs, len);
+      if (read == -1) {
+        return false;  // EOF
+      }
+      ofs += read;
+      len -= read;
+    }
+
+    return true;
+  }
+
+  private void writeToStdout(byte[] buf) throws Exception {
+    System.out.write(buf);
+  }
+
+  // Returns -1 on EOF (the actual values will always be positive).
+  private int readLittleEndianIntFromStdin() throws Exception {
+    byte[] buf = new byte[4];
+    if (!readFromStdin(buf, 4)) {
+      return -1;
+    }
+    return (buf[0] & 0xff)
+        | ((buf[1] & 0xff) << 8)
+        | ((buf[2] & 0xff) << 16)
+        | ((buf[3] & 0xff) << 24);
+  }
+
+  private void writeLittleEndianIntToStdout(int val) throws Exception {
+    byte[] buf = new byte[4];
+    buf[0] = (byte)val;
+    buf[1] = (byte)(val >> 8);
+    buf[2] = (byte)(val >> 16);
+    buf[3] = (byte)(val >> 24);
+    writeToStdout(buf);
+  }
+
+  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+    Conformance.TestAllTypes testMessage;
+
+    switch (request.getPayloadCase()) {
+      case PROTOBUF_PAYLOAD: {
+        try {
+          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
+        } catch (InvalidProtocolBufferException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
+      case JSON_PAYLOAD: {
+        try {
+          Conformance.TestAllTypes.Builder builder = Conformance.TestAllTypes.newBuilder();
+          JsonFormat.parser().usingTypeRegistry(typeRegistry)
+              .merge(request.getJsonPayload(), builder);
+          testMessage = builder.build();
+        } catch (InvalidProtocolBufferException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
+      case PAYLOAD_NOT_SET: {
+        throw new RuntimeException("Request didn't have payload.");
+      }
+
+      default: {
+        throw new RuntimeException("Unexpected payload case.");
+      }
+    }
+
+    switch (request.getRequestedOutputFormat()) {
+      case UNSPECIFIED:
+        throw new RuntimeException("Unspecified output format.");
+
+      case PROTOBUF:
+        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+
+      case JSON:
+        try {
+          return Conformance.ConformanceResponse.newBuilder().setJsonPayload(
+              JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build();
+        } catch (InvalidProtocolBufferException | IllegalArgumentException e) {
+          return Conformance.ConformanceResponse.newBuilder().setSerializeError(
+              e.getMessage()).build();
+        }
+
+      default: {
+        throw new RuntimeException("Unexpected request output.");
+      }
+    }
+  }
+
+  private boolean doTestIo() throws Exception {
+    int bytes = readLittleEndianIntFromStdin();
+
+    if (bytes == -1) {
+      return false;  // EOF
+    }
+
+    byte[] serializedInput = new byte[bytes];
+
+    if (!readFromStdin(serializedInput, bytes)) {
+      throw new RuntimeException("Unexpected EOF from test program.");
+    }
+
+    Conformance.ConformanceRequest request =
+        Conformance.ConformanceRequest.parseFrom(serializedInput);
+    Conformance.ConformanceResponse response = doTest(request);
+    byte[] serializedOutput = response.toByteArray();
+
+    writeLittleEndianIntToStdout(serializedOutput.length);
+    writeToStdout(serializedOutput);
+
+    return true;
+  }
+
+  public void run() throws Exception {
+    typeRegistry = TypeRegistry.newBuilder().add(
+        Conformance.TestAllTypes.getDescriptor()).build();
+    while (doTestIo()) {
+      this.testCount++;
+    }
+
+    System.err.println("ConformanceJava: received EOF from test runner after " +
+        this.testCount + " tests");
+  }
+
+  public static void main(String[] args) throws Exception {
+    new ConformanceJava().run();
+  }
+}
diff --git a/src/third_party/protobuf-3/conformance/ConformanceJavaLite.java b/src/third_party/protobuf-3/conformance/ConformanceJavaLite.java
new file mode 100644
index 0000000..121dc7d
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/ConformanceJavaLite.java
@@ -0,0 +1,125 @@
+
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+class ConformanceJavaLite {
+  private int testCount = 0;
+
+  private boolean readFromStdin(byte[] buf, int len) throws Exception {
+    int ofs = 0;
+    while (len > 0) {
+      int read = System.in.read(buf, ofs, len);
+      if (read == -1) {
+        return false;  // EOF
+      }
+      ofs += read;
+      len -= read;
+    }
+
+    return true;
+  }
+
+  private void writeToStdout(byte[] buf) throws Exception {
+    System.out.write(buf);
+  }
+
+  // Returns -1 on EOF (the actual values will always be positive).
+  private int readLittleEndianIntFromStdin() throws Exception {
+    byte[] buf = new byte[4];
+    if (!readFromStdin(buf, 4)) {
+      return -1;
+    }
+    return (buf[0] & 0xff)
+        | ((buf[1] & 0xff) << 8)
+        | ((buf[2] & 0xff) << 16)
+        | ((buf[3] & 0xff) << 24);
+  }
+
+  private void writeLittleEndianIntToStdout(int val) throws Exception {
+    byte[] buf = new byte[4];
+    buf[0] = (byte)val;
+    buf[1] = (byte)(val >> 8);
+    buf[2] = (byte)(val >> 16);
+    buf[3] = (byte)(val >> 24);
+    writeToStdout(buf);
+  }
+
+  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+    Conformance.TestAllTypes testMessage;
+
+    switch (request.getPayloadCase()) {
+      case PROTOBUF_PAYLOAD: {
+        try {
+          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
+        } catch (InvalidProtocolBufferException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
+      case JSON_PAYLOAD: {
+        return Conformance.ConformanceResponse.newBuilder().setSkipped(
+            "Lite runtime does not suport Json Formant.").build();
+      }
+      case PAYLOAD_NOT_SET: {
+        throw new RuntimeException("Request didn't have payload.");
+      }
+
+      default: {
+        throw new RuntimeException("Unexpected payload case.");
+      }
+    }
+
+    switch (request.getRequestedOutputFormat()) {
+      case UNSPECIFIED:
+        throw new RuntimeException("Unspecified output format.");
+
+      case PROTOBUF:
+        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+
+      case JSON:
+        return Conformance.ConformanceResponse.newBuilder().setSkipped(
+            "Lite runtime does not suport Json Formant.").build();
+
+      default: {
+        throw new RuntimeException("Unexpected request output.");
+      }
+    }
+  }
+
+  private boolean doTestIo() throws Exception {
+    int bytes = readLittleEndianIntFromStdin();
+
+    if (bytes == -1) {
+      return false;  // EOF
+    }
+
+    byte[] serializedInput = new byte[bytes];
+
+    if (!readFromStdin(serializedInput, bytes)) {
+      throw new RuntimeException("Unexpected EOF from test program.");
+    }
+
+    Conformance.ConformanceRequest request =
+        Conformance.ConformanceRequest.parseFrom(serializedInput);
+    Conformance.ConformanceResponse response = doTest(request);
+    byte[] serializedOutput = response.toByteArray();
+
+    writeLittleEndianIntToStdout(serializedOutput.length);
+    writeToStdout(serializedOutput);
+
+    return true;
+  }
+
+  public void run() throws Exception {
+    while (doTestIo()) {
+      this.testCount++;
+    }
+
+    System.err.println("ConformanceJavaLite: received EOF from test runner after " +
+        this.testCount + " tests");
+  }
+
+  public static void main(String[] args) throws Exception {
+    new ConformanceJavaLite().run();
+  }
+}
diff --git a/src/third_party/protobuf-3/conformance/Makefile.am b/src/third_party/protobuf-3/conformance/Makefile.am
new file mode 100644
index 0000000..31a9e40
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/Makefile.am
@@ -0,0 +1,281 @@
+## Process this file with automake to produce Makefile.in
+
+conformance_protoc_inputs =                                    \
+  conformance.proto
+
+well_known_type_protoc_inputs =                                \
+  $(top_srcdir)/src/google/protobuf/any.proto                  \
+  $(top_srcdir)/src/google/protobuf/duration.proto             \
+  $(top_srcdir)/src/google/protobuf/field_mask.proto           \
+  $(top_srcdir)/src/google/protobuf/struct.proto               \
+  $(top_srcdir)/src/google/protobuf/timestamp.proto            \
+  $(top_srcdir)/src/google/protobuf/wrappers.proto
+
+
+protoc_outputs =                                               \
+  conformance.pb.cc                                            \
+  conformance.pb.h
+
+other_language_protoc_outputs =                                \
+  conformance_pb2.py                                           \
+  Conformance.pbobjc.h                                         \
+  Conformance.pbobjc.m                                         \
+  conformance.rb                                               \
+  com/google/protobuf/Any.java                                 \
+  com/google/protobuf/AnyOrBuilder.java                        \
+  com/google/protobuf/AnyProto.java                            \
+  com/google/protobuf/BoolValue.java                           \
+  com/google/protobuf/BoolValueOrBuilder.java                  \
+  com/google/protobuf/BytesValue.java                          \
+  com/google/protobuf/BytesValueOrBuilder.java                 \
+  com/google/protobuf/conformance/Conformance.java             \
+  com/google/protobuf/DoubleValue.java                         \
+  com/google/protobuf/DoubleValueOrBuilder.java                \
+  com/google/protobuf/Duration.java                            \
+  com/google/protobuf/DurationOrBuilder.java                   \
+  com/google/protobuf/DurationProto.java                       \
+  com/google/protobuf/FieldMask.java                           \
+  com/google/protobuf/FieldMaskOrBuilder.java                  \
+  com/google/protobuf/FieldMaskProto.java                      \
+  com/google/protobuf/FloatValue.java                          \
+  com/google/protobuf/FloatValueOrBuilder.java                 \
+  com/google/protobuf/Int32Value.java                          \
+  com/google/protobuf/Int32ValueOrBuilder.java                 \
+  com/google/protobuf/Int64Value.java                          \
+  com/google/protobuf/Int64ValueOrBuilder.java                 \
+  com/google/protobuf/ListValue.java                           \
+  com/google/protobuf/ListValueOrBuilder.java                  \
+  com/google/protobuf/NullValue.java                           \
+  com/google/protobuf/StringValue.java                         \
+  com/google/protobuf/StringValueOrBuilder.java                \
+  com/google/protobuf/Struct.java                              \
+  com/google/protobuf/StructOrBuilder.java                     \
+  com/google/protobuf/StructProto.java                         \
+  com/google/protobuf/Timestamp.java                           \
+  com/google/protobuf/TimestampOrBuilder.java                  \
+  com/google/protobuf/TimestampProto.java                      \
+  com/google/protobuf/UInt32Value.java                         \
+  com/google/protobuf/UInt32ValueOrBuilder.java                \
+  com/google/protobuf/UInt64Value.java                         \
+  com/google/protobuf/UInt64ValueOrBuilder.java                \
+  com/google/protobuf/Value.java                               \
+  com/google/protobuf/ValueOrBuilder.java                      \
+  com/google/protobuf/WrappersProto.java                       \
+  google/protobuf/any.pb.cc                                    \
+  google/protobuf/any.pb.h                                     \
+  google/protobuf/any.rb                                       \
+  google/protobuf/any_pb2.py                                   \
+  google/protobuf/duration.pb.cc                               \
+  google/protobuf/duration.pb.h                                \
+  google/protobuf/duration.rb                                  \
+  google/protobuf/duration_pb2.py                              \
+  google/protobuf/field_mask.pb.cc                             \
+  google/protobuf/field_mask.pb.h                              \
+  google/protobuf/field_mask.rb                                \
+  google/protobuf/field_mask_pb2.py                            \
+  google/protobuf/struct.pb.cc                                 \
+  google/protobuf/struct.pb.h                                  \
+  google/protobuf/struct.rb                                    \
+  google/protobuf/struct_pb2.py                                \
+  google/protobuf/timestamp.pb.cc                              \
+  google/protobuf/timestamp.pb.h                               \
+  google/protobuf/timestamp.rb                                 \
+  google/protobuf/timestamp_pb2.py                             \
+  google/protobuf/wrappers.pb.cc                               \
+  google/protobuf/wrappers.pb.h                                \
+  google/protobuf/wrappers.rb                                  \
+  google/protobuf/wrappers_pb2.py                              \
+  lite/com/google/protobuf/Any.java                            \
+  lite/com/google/protobuf/AnyOrBuilder.java                   \
+  lite/com/google/protobuf/AnyProto.java                       \
+  lite/com/google/protobuf/BoolValue.java                      \
+  lite/com/google/protobuf/BoolValueOrBuilder.java             \
+  lite/com/google/protobuf/BytesValue.java                     \
+  lite/com/google/protobuf/BytesValueOrBuilder.java            \
+  lite/com/google/protobuf/conformance/Conformance.java        \
+  lite/com/google/protobuf/DoubleValue.java                    \
+  lite/com/google/protobuf/DoubleValueOrBuilder.java           \
+  lite/com/google/protobuf/Duration.java                       \
+  lite/com/google/protobuf/DurationOrBuilder.java              \
+  lite/com/google/protobuf/DurationProto.java                  \
+  lite/com/google/protobuf/FieldMask.java                      \
+  lite/com/google/protobuf/FieldMaskOrBuilder.java             \
+  lite/com/google/protobuf/FieldMaskProto.java                 \
+  lite/com/google/protobuf/FloatValue.java                     \
+  lite/com/google/protobuf/FloatValueOrBuilder.java            \
+  lite/com/google/protobuf/Int32Value.java                     \
+  lite/com/google/protobuf/Int32ValueOrBuilder.java            \
+  lite/com/google/protobuf/Int64Value.java                     \
+  lite/com/google/protobuf/Int64ValueOrBuilder.java            \
+  lite/com/google/protobuf/ListValue.java                      \
+  lite/com/google/protobuf/ListValueOrBuilder.java             \
+  lite/com/google/protobuf/NullValue.java                      \
+  lite/com/google/protobuf/StringValue.java                    \
+  lite/com/google/protobuf/StringValueOrBuilder.java           \
+  lite/com/google/protobuf/Struct.java                         \
+  lite/com/google/protobuf/StructOrBuilder.java                \
+  lite/com/google/protobuf/StructProto.java                    \
+  lite/com/google/protobuf/Timestamp.java                      \
+  lite/com/google/protobuf/TimestampOrBuilder.java             \
+  lite/com/google/protobuf/TimestampProto.java                 \
+  lite/com/google/protobuf/UInt32Value.java                    \
+  lite/com/google/protobuf/UInt32ValueOrBuilder.java           \
+  lite/com/google/protobuf/UInt64Value.java                    \
+  lite/com/google/protobuf/UInt64ValueOrBuilder.java           \
+  lite/com/google/protobuf/Value.java                          \
+  lite/com/google/protobuf/ValueOrBuilder.java                 \
+  lite/com/google/protobuf/WrappersProto.java
+
+bin_PROGRAMS = conformance-test-runner conformance-cpp
+
+# All source files excepet C++/Objective-C ones should be explicitly listed
+# here because the autoconf tools don't include files of other languages
+# automatically.
+EXTRA_DIST =                  \
+  ConformanceJava.java        \
+  ConformanceJavaLite.java    \
+  README.md                   \
+  conformance.proto           \
+  conformance_python.py       \
+  conformance_ruby.rb         \
+  failure_list_cpp.txt        \
+  failure_list_csharp.txt     \
+  failure_list_java.txt       \
+  failure_list_objc.txt       \
+  failure_list_python.txt     \
+  failure_list_python_cpp.txt \
+  failure_list_python-post26.txt \
+  failure_list_ruby.txt
+
+conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la
+conformance_test_runner_SOURCES = conformance_test.h conformance_test.cc \
+                                  conformance_test_runner.cc             \
+                                  third_party/jsoncpp/json.h             \
+                                  third_party/jsoncpp/jsoncpp.cpp
+nodist_conformance_test_runner_SOURCES = conformance.pb.cc
+conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)
+conformance_test_runner_CXXFLAGS = -std=c++11
+# Explicit deps beacuse BUILT_SOURCES are only done before a "make all/check"
+# so a direct "make test_cpp" could fail if parallel enough.
+conformance_test_runner-conformance_test.$(OBJEXT): conformance.pb.h
+conformance_test_runner-conformance_test_runner.$(OBJEXT): conformance.pb.h
+
+conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la
+conformance_cpp_SOURCES = conformance_cpp.cc
+nodist_conformance_cpp_SOURCES = conformance.pb.cc
+conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
+# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
+# so a direct "make test_cpp" could fail if parallel enough.
+conformance_cpp-conformance_cpp.$(OBJEXT): conformance.pb.h
+
+if OBJC_CONFORMANCE_TEST
+
+bin_PROGRAMS += conformance-objc
+
+conformance_objc_SOURCES = conformance_objc.m ../objectivec/GPBProtocolBuffers.m
+nodist_conformance_objc_SOURCES = Conformance.pbobjc.m
+# On travis, the build fails without the isysroot because whatever system
+# headers are being found don't include generics support for
+# NSArray/NSDictionary, the only guess is their image at one time had an odd
+# setup for Xcode and old frameworks are being found.
+conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec -isysroot `xcrun --sdk macosx --show-sdk-path`
+conformance_objc_LDFLAGS = -framework Foundation
+# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
+# so a direct "make test_objc" could fail if parallel enough.
+conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h
+
+endif
+
+if USE_EXTERNAL_PROTOC
+
+# Some implementations include pre-generated versions of well-known types.
+protoc_middleman: $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. $(conformance_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. $(well_known_type_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
+	touch protoc_middleman
+
+else
+
+# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
+# relative to srcdir, which may not be the same as the current directory when
+# building out-of-tree.
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd $(conformance_protoc_inputs) )
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd $(well_known_type_protoc_inputs) )
+	@mkdir -p lite
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
+	touch protoc_middleman
+
+endif
+
+$(protoc_outputs): protoc_middleman
+
+$(other_language_protoc_outputs): protoc_middleman
+
+BUILT_SOURCES = $(protoc_outputs) $(other_language_protoc_outputs)
+
+CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp $(other_language_protoc_outputs)
+
+MAINTAINERCLEANFILES =   \
+  Makefile.in
+
+javac_middleman: ConformanceJava.java protoc_middleman $(other_language_protoc_outputs)
+	jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+	@touch javac_middleman
+
+conformance-java: javac_middleman
+	@echo "Writing shortcut script conformance-java..."
+	@echo '#! /bin/sh' > conformance-java
+	@jar=`ls ../java/util/target/*jar-with-dependencies.jar` && echo java -classpath .:../java/target/classes:$$jar ConformanceJava '$$@' >> conformance-java
+	@chmod +x conformance-java
+
+javac_middleman_lite: ConformanceJavaLite.java protoc_middleman $(other_language_protoc_outputs)
+	javac -classpath ../java/lite/target/classes:lite ConformanceJavaLite.java lite/com/google/protobuf/conformance/Conformance.java
+	@touch javac_middleman_lite
+
+conformance-java-lite: javac_middleman_lite
+	@echo "Writing shortcut script conformance-java-lite..."
+	@echo '#! /bin/sh' > conformance-java-lite
+	@echo java -classpath .:../java/lite/target/classes:lite ConformanceJavaLite '$$@' >> conformance-java-lite
+	@chmod +x conformance-java-lite
+
+# Currently the conformance code is alongside the rest of the C#
+# source, as it's easier to maintain there. We assume we've already
+# built that, so we just need a script to run it.
+conformance-csharp: $(other_language_protoc_outputs)
+	@echo "Writing shortcut script conformance-csharp..."
+	@echo '#! /bin/sh' > conformance-csharp
+	@echo 'mono ../csharp/src/Google.Protobuf.Conformance/bin/Release/Google.Protobuf.Conformance.exe "$$@"' >> conformance-csharp
+	@chmod +x conformance-csharp
+
+# Targets for actually running tests.
+test_cpp: protoc_middleman conformance-test-runner conformance-cpp
+	./conformance-test-runner --failure_list failure_list_cpp.txt ./conformance-cpp
+
+test_java: protoc_middleman conformance-test-runner conformance-java
+	./conformance-test-runner --failure_list failure_list_java.txt ./conformance-java
+
+test_java_lite: protoc_middleman conformance-test-runner conformance-java-lite
+	./conformance-test-runner ./conformance-java-lite
+
+test_csharp: protoc_middleman conformance-test-runner conformance-csharp
+	./conformance-test-runner --failure_list failure_list_csharp.txt ./conformance-csharp
+
+test_ruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
+	RUBYLIB=../ruby/lib:. ./conformance-test-runner --failure_list failure_list_ruby.txt ./conformance_ruby.rb
+
+# These depend on library paths being properly set up.  The easiest way to
+# run them is to just use "tox" from the python dir.
+test_python: protoc_middleman conformance-test-runner
+	./conformance-test-runner --failure_list failure_list_python.txt $(CONFORMANCE_PYTHON_EXTRA_FAILURES) ./conformance_python.py
+
+test_python_cpp: protoc_middleman conformance-test-runner
+	./conformance-test-runner --failure_list failure_list_python_cpp.txt $(CONFORMANCE_PYTHON_EXTRA_FAILURES) ./conformance_python.py
+
+if OBJC_CONFORMANCE_TEST
+
+test_objc: protoc_middleman conformance-test-runner conformance-objc
+	./conformance-test-runner --failure_list failure_list_objc.txt ./conformance-objc
+
+endif
diff --git a/src/third_party/protobuf-3/conformance/README.md b/src/third_party/protobuf-3/conformance/README.md
new file mode 100644
index 0000000..9388055
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/README.md
@@ -0,0 +1,45 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains conformance tests for testing completeness and
+correctness of Protocol Buffers implementations.  These tests are designed
+to be easy to run against any Protocol Buffers implementation.
+
+This directory contains the tester process `conformance-test`, which
+contains all of the tests themselves.  Then separate programs written
+in whatever language you want to test communicate with the tester
+program over a pipe.
+
+Before running any of these tests, make sure you run `make` in the base
+directory to build `protoc`, since all the tests depend on it.
+
+    $ make
+
+Then to run the tests against the C++ implementation, run:
+
+    $ cd conformance && make test_cpp
+
+More tests and languages will be added soon!
+
+Testing other Protocol Buffer implementations
+---------------------------------------------
+
+To run these tests against a new Protocol Buffers implementation, write a
+program in your language that uses the protobuf implementation you want
+to test.  This program should implement the testing protocol defined in
+[conformance.proto](https://github.com/google/protobuf/blob/master/conformance/conformance.proto).
+This is designed to be as easy as possible: the C++ version is only
+150 lines and is a good example for what this program should look like
+(see [conformance_cpp.cc](https://github.com/google/protobuf/blob/master/conformance/conformance_cpp.cc)).
+The program only needs to be able to read from stdin and write to stdout.
+
+Portability
+-----------
+
+Note that the test runner currently does not work on Windows.  Patches
+to fix this are welcome!  (But please get in touch first to settle on
+a general implementation strategy).
diff --git a/src/third_party/protobuf-3/conformance/conformance.proto b/src/third_party/protobuf-3/conformance/conformance.proto
new file mode 100644
index 0000000..fc96074
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance.proto
@@ -0,0 +1,273 @@
+// 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.
+
+syntax = "proto3";
+package conformance;
+option java_package = "com.google.protobuf.conformance";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+
+// This defines the conformance testing protocol.  This protocol exists between
+// the conformance test suite itself and the code being tested.  For each test,
+// the suite will send a ConformanceRequest message and expect a
+// ConformanceResponse message.
+//
+// You can either run the tests in two different ways:
+//
+//   1. in-process (using the interface in conformance_test.h).
+//
+//   2. as a sub-process communicating over a pipe.  Information about how to
+//      do this is in conformance_test_runner.cc.
+//
+// Pros/cons of the two approaches:
+//
+//   - running as a sub-process is much simpler for languages other than C/C++.
+//
+//   - running as a sub-process may be more tricky in unusual environments like
+//     iOS apps, where fork/stdin/stdout are not available.
+
+enum WireFormat {
+  UNSPECIFIED = 0;
+  PROTOBUF = 1;
+  JSON = 2;
+}
+
+// Represents a single test case's input.  The testee should:
+//
+//   1. parse this proto (which should always succeed)
+//   2. parse the protobuf or JSON payload in "payload" (which may fail)
+//   3. if the parse succeeded, serialize the message in the requested format.
+message ConformanceRequest {
+  // The payload (whether protobuf of JSON) is always for a TestAllTypes proto
+  // (see below).
+  oneof payload {
+    bytes protobuf_payload = 1;
+    string json_payload = 2;
+  }
+
+  // Which format should the testee serialize its message to?
+  WireFormat requested_output_format = 3;
+}
+
+// Represents a single test case's output.
+message ConformanceResponse {
+  oneof result {
+    // This string should be set to indicate parsing failed.  The string can
+    // provide more information about the parse error if it is available.
+    //
+    // Setting this string does not necessarily mean the testee failed the
+    // test.  Some of the test cases are intentionally invalid input.
+    string parse_error = 1;
+
+    // If the input was successfully parsed but errors occurred when
+    // serializing it to the requested output format, set the error message in
+    // this field.
+    string serialize_error = 6;
+
+    // This should be set if some other error occurred.  This will always
+    // indicate that the test failed.  The string can provide more information
+    // about the failure.
+    string runtime_error = 2;
+
+    // If the input was successfully parsed and the requested output was
+    // protobuf, serialize it to protobuf and set it in this field.
+    bytes protobuf_payload = 3;
+
+    // If the input was successfully parsed and the requested output was JSON,
+    // serialize to JSON and set it in this field.
+    string json_payload = 4;
+
+    // For when the testee skipped the test, likely because a certain feature
+    // wasn't supported, like JSON input/output.
+    string skipped = 5;
+  }
+}
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    int32 a = 1;
+    TestAllTypes corecursive = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  int32 optional_int32    =  1;
+  int64 optional_int64    =  2;
+  uint32 optional_uint32   =  3;
+  uint64 optional_uint64   =  4;
+  sint32 optional_sint32   =  5;
+  sint64 optional_sint64   =  6;
+  fixed32 optional_fixed32  =  7;
+  fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+  float optional_float    = 11;
+  double optional_double   = 12;
+  bool optional_bool     = 13;
+  string optional_string   = 14;
+  bytes optional_bytes    = 15;
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  TestAllTypes recursive_message = 27;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Map
+  map <   int32, int32>    map_int32_int32 = 56;
+  map <   int64, int64>    map_int64_int64 = 57;
+  map <  uint32, uint32>   map_uint32_uint32 = 58;
+  map <  uint64, uint64>   map_uint64_uint64 = 59;
+  map <  sint32, sint32>   map_sint32_sint32 = 60;
+  map <  sint64, sint64>   map_sint64_sint64 = 61;
+  map < fixed32, fixed32>  map_fixed32_fixed32 = 62;
+  map < fixed64, fixed64>  map_fixed64_fixed64 = 63;
+  map <sfixed32, sfixed32> map_sfixed32_sfixed32 = 64;
+  map <sfixed64, sfixed64> map_sfixed64_sfixed64 = 65;
+  map <   int32, float>    map_int32_float = 66;
+  map <   int32, double>   map_int32_double = 67;
+  map <    bool, bool>     map_bool_bool = 68;
+  map <  string, string>   map_string_string = 69;
+  map <  string, bytes>    map_string_bytes = 70;
+  map <  string, NestedMessage>  map_string_nested_message = 71;
+  map <  string, ForeignMessage> map_string_foreign_message = 72;
+  map <  string, NestedEnum>     map_string_nested_enum = 73;
+  map <  string, ForeignEnum>    map_string_foreign_enum = 74;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+
+  // Well-known types
+  google.protobuf.BoolValue optional_bool_wrapper = 201;
+  google.protobuf.Int32Value optional_int32_wrapper = 202;
+  google.protobuf.Int64Value optional_int64_wrapper = 203;
+  google.protobuf.UInt32Value optional_uint32_wrapper = 204;
+  google.protobuf.UInt64Value optional_uint64_wrapper = 205;
+  google.protobuf.FloatValue optional_float_wrapper = 206;
+  google.protobuf.DoubleValue optional_double_wrapper = 207;
+  google.protobuf.StringValue optional_string_wrapper = 208;
+  google.protobuf.BytesValue optional_bytes_wrapper = 209;
+
+  repeated google.protobuf.BoolValue repeated_bool_wrapper = 211;
+  repeated google.protobuf.Int32Value repeated_int32_wrapper = 212;
+  repeated google.protobuf.Int64Value repeated_int64_wrapper = 213;
+  repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214;
+  repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215;
+  repeated google.protobuf.FloatValue repeated_float_wrapper = 216;
+  repeated google.protobuf.DoubleValue repeated_double_wrapper = 217;
+  repeated google.protobuf.StringValue repeated_string_wrapper = 218;
+  repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219;
+
+  google.protobuf.Duration optional_duration = 301;
+  google.protobuf.Timestamp optional_timestamp = 302;
+  google.protobuf.FieldMask optional_field_mask = 303;
+  google.protobuf.Struct optional_struct = 304;
+  google.protobuf.Any optional_any = 305;
+  google.protobuf.Value optional_value = 306;
+
+  repeated google.protobuf.Duration repeated_duration = 311;
+  repeated google.protobuf.Timestamp repeated_timestamp = 312;
+  repeated google.protobuf.FieldMask repeated_fieldmask = 313;
+  repeated google.protobuf.Struct repeated_struct = 324;
+  repeated google.protobuf.Any repeated_any = 315;
+  repeated google.protobuf.Value repeated_value = 316;
+
+  // Test field-name-to-JSON-name convention.
+  int32 fieldname1 = 401;
+  int32 field_name2 = 402;
+  int32 _field_name3 = 403;
+  int32 field__name4_ = 404;
+  int32 field0name5 = 405;
+  int32 field_0_name6 = 406;
+  int32 fieldName7 = 407;
+  int32 FieldName8 = 408;
+  int32 field_Name9 = 409;
+  int32 Field_Name10 = 410;
+  int32 FIELD_NAME11 = 411;
+  int32 FIELD_name12 = 412;
+}
+
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 0;
+  FOREIGN_BAR = 1;
+  FOREIGN_BAZ = 2;
+}
diff --git a/src/third_party/protobuf-3/conformance/conformance_cpp.cc b/src/third_party/protobuf-3/conformance/conformance_cpp.cc
new file mode 100644
index 0000000..1a26549
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_cpp.cc
@@ -0,0 +1,207 @@
+// 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.
+
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "conformance.pb.h"
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/type_resolver_util.h>
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using conformance::TestAllTypes;
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::internal::scoped_ptr;
+using google::protobuf::util::BinaryToJsonString;
+using google::protobuf::util::JsonToBinaryString;
+using google::protobuf::util::NewTypeResolverForDescriptorPool;
+using google::protobuf::util::Status;
+using google::protobuf::util::TypeResolver;
+using std::string;
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+  return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+int test_count = 0;
+bool verbose = false;
+TypeResolver* type_resolver;
+string* type_url;
+
+
+bool CheckedRead(int fd, void *buf, size_t len) {
+  size_t ofs = 0;
+  while (len > 0) {
+    ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+    if (bytes_read == 0) return false;
+
+    if (bytes_read < 0) {
+      GOOGLE_LOG(FATAL) << "Error reading from test runner: " <<  strerror(errno);
+    }
+
+    len -= bytes_read;
+    ofs += bytes_read;
+  }
+
+  return true;
+}
+
+void CheckedWrite(int fd, const void *buf, size_t len) {
+  if (write(fd, buf, len) != len) {
+    GOOGLE_LOG(FATAL) << "Error writing to test runner: " << strerror(errno);
+  }
+}
+
+void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
+  TestAllTypes test_message;
+
+  switch (request.payload_case()) {
+    case ConformanceRequest::kProtobufPayload:
+      if (!test_message.ParseFromString(request.protobuf_payload())) {
+        // Getting parse details would involve something like:
+        //   http://stackoverflow.com/questions/22121922/how-can-i-get-more-details-about-errors-generated-during-protobuf-parsing-c
+        response->set_parse_error("Parse error (no more details available).");
+        return;
+      }
+      break;
+
+    case ConformanceRequest::kJsonPayload: {
+      string proto_binary;
+      Status status = JsonToBinaryString(type_resolver, *type_url,
+                                         request.json_payload(), &proto_binary);
+      if (!status.ok()) {
+        response->set_parse_error(string("Parse error: ") +
+                                  status.error_message().as_string());
+        return;
+      }
+
+      if (!test_message.ParseFromString(proto_binary)) {
+        response->set_runtime_error(
+            "Parsing JSON generates invalid proto output.");
+        return;
+      }
+      break;
+    }
+
+    case ConformanceRequest::PAYLOAD_NOT_SET:
+      GOOGLE_LOG(FATAL) << "Request didn't have payload.";
+      break;
+  }
+
+  switch (request.requested_output_format()) {
+    case conformance::UNSPECIFIED:
+      GOOGLE_LOG(FATAL) << "Unspecified output format";
+      break;
+
+    case conformance::PROTOBUF:
+      GOOGLE_CHECK(
+          test_message.SerializeToString(response->mutable_protobuf_payload()));
+      break;
+
+    case conformance::JSON: {
+      string proto_binary;
+      GOOGLE_CHECK(test_message.SerializeToString(&proto_binary));
+      Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
+                                         response->mutable_json_payload());
+      if (!status.ok()) {
+        response->set_serialize_error(
+            string("Failed to serialize JSON output: ") +
+            status.error_message().as_string());
+        return;
+      }
+      break;
+    }
+
+    default:
+      GOOGLE_LOG(FATAL) << "Unknown output format: "
+                        << request.requested_output_format();
+  }
+}
+
+bool DoTestIo() {
+  string serialized_input;
+  string serialized_output;
+  ConformanceRequest request;
+  ConformanceResponse response;
+  uint32_t bytes;
+
+  if (!CheckedRead(STDIN_FILENO, &bytes, sizeof(uint32_t))) {
+    // EOF.
+    return false;
+  }
+
+  serialized_input.resize(bytes);
+
+  if (!CheckedRead(STDIN_FILENO, (char*)serialized_input.c_str(), bytes)) {
+    GOOGLE_LOG(ERROR) << "Unexpected EOF on stdin. " << strerror(errno);
+  }
+
+  if (!request.ParseFromString(serialized_input)) {
+    GOOGLE_LOG(FATAL) << "Parse of ConformanceRequest proto failed.";
+    return false;
+  }
+
+  DoTest(request, &response);
+
+  response.SerializeToString(&serialized_output);
+
+  bytes = serialized_output.size();
+  CheckedWrite(STDOUT_FILENO, &bytes, sizeof(uint32_t));
+  CheckedWrite(STDOUT_FILENO, serialized_output.c_str(), bytes);
+
+  if (verbose) {
+    fprintf(stderr, "conformance-cpp: request=%s, response=%s\n",
+            request.ShortDebugString().c_str(),
+            response.ShortDebugString().c_str());
+  }
+
+  test_count++;
+
+  return true;
+}
+
+int main() {
+  type_resolver = NewTypeResolverForDescriptorPool(
+      kTypeUrlPrefix, DescriptorPool::generated_pool());
+  type_url = new string(GetTypeUrl(TestAllTypes::descriptor()));
+  while (1) {
+    if (!DoTestIo()) {
+      fprintf(stderr, "conformance-cpp: received EOF from test runner "
+                      "after %d tests, exiting\n", test_count);
+      return 0;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/conformance/conformance_objc.m b/src/third_party/protobuf-3/conformance/conformance_objc.m
new file mode 100644
index 0000000..1124bfe
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_objc.m
@@ -0,0 +1,179 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+
+#import "Conformance.pbobjc.h"
+
+static void Die(NSString *format, ...) __dead2;
+
+static BOOL verbose = NO;
+static int32_t testCount = 0;
+
+static void Die(NSString *format, ...) {
+  va_list args;
+  va_start(args, format);
+  NSString *msg = [[NSString alloc] initWithFormat:format arguments:args];
+  NSLog(@"%@", msg);
+  va_end(args);
+  [msg release];
+  exit(66);
+}
+
+static NSData *CheckedReadDataOfLength(NSFileHandle *handle, NSUInteger numBytes) {
+  NSData *data = [handle readDataOfLength:numBytes];
+  NSUInteger dataLen = data.length;
+  if (dataLen == 0) {
+    return nil;  // EOF.
+  }
+  if (dataLen != numBytes) {
+    Die(@"Failed to read the request length (%d), only got: %@",
+        numBytes, data);
+  }
+  return data;
+}
+
+static ConformanceResponse *DoTest(ConformanceRequest *request) {
+  ConformanceResponse *response = [ConformanceResponse message];
+  TestAllTypes *testMessage = nil;
+
+  switch (request.payloadOneOfCase) {
+    case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase:
+      Die(@"Request didn't have a payload: %@", request);
+      break;
+
+    case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
+      NSError *error = nil;
+      testMessage = [TestAllTypes parseFromData:request.protobufPayload
+                                          error:&error];
+      if (!testMessage) {
+        response.parseError =
+            [NSString stringWithFormat:@"Parse error: %@", error];
+      }
+      break;
+    }
+
+    case ConformanceRequest_Payload_OneOfCase_JsonPayload:
+      response.skipped = @"ObjC doesn't support parsing JSON";
+      break;
+  }
+
+  if (testMessage) {
+    switch (request.requestedOutputFormat) {
+      case WireFormat_GPBUnrecognizedEnumeratorValue:
+      case WireFormat_Unspecified:
+        Die(@"Unrecognized/unspecified output format: %@", request);
+        break;
+
+      case WireFormat_Protobuf:
+        response.protobufPayload = testMessage.data;
+        if (!response.protobufPayload) {
+          response.serializeError =
+            [NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
+        }
+        break;
+
+      case WireFormat_Json:
+        response.skipped = @"ObjC doesn't support generating JSON";
+        break;
+    }
+  }
+
+  return response;
+}
+
+static uint32_t UInt32FromLittleEndianData(NSData *data) {
+  if (data.length != sizeof(uint32_t)) {
+    Die(@"Data not the right size for uint32_t: %@", data);
+  }
+  uint32_t value;
+  memcpy(&value, data.bytes, sizeof(uint32_t));
+  return CFSwapInt32LittleToHost(value);
+}
+
+static NSData *UInt32ToLittleEndianData(uint32_t num) {
+  uint32_t value = CFSwapInt32HostToLittle(num);
+  return [NSData dataWithBytes:&value length:sizeof(uint32_t)];
+}
+
+static BOOL DoTestIo(NSFileHandle *input, NSFileHandle *output) {
+  // See conformance_test_runner.cc for the wire format.
+  NSData *data = CheckedReadDataOfLength(input, sizeof(uint32_t));
+  if (!data) {
+    // EOF.
+    return NO;
+  }
+  uint32_t numBytes = UInt32FromLittleEndianData(data);
+  data = CheckedReadDataOfLength(input, numBytes);
+  if (!data) {
+    Die(@"Failed to read request");
+  }
+
+  NSError *error = nil;
+  ConformanceRequest *request = [ConformanceRequest parseFromData:data
+                                                            error:&error];
+  if (!request) {
+    Die(@"Failed to parse the message data: %@", error);
+  }
+
+  ConformanceResponse *response = DoTest(request);
+  if (!response) {
+    Die(@"Failed to make a reply from %@", request);
+  }
+
+  data = response.data;
+  [output writeData:UInt32ToLittleEndianData((int32_t)data.length)];
+  [output writeData:data];
+
+  if (verbose) {
+    NSLog(@"Request: %@", request);
+    NSLog(@"Response: %@", response);
+  }
+
+  ++testCount;
+  return YES;
+}
+
+int main(int argc, const char *argv[]) {
+  @autoreleasepool {
+    NSFileHandle *input = [[NSFileHandle fileHandleWithStandardInput] retain];
+    NSFileHandle *output = [[NSFileHandle fileHandleWithStandardOutput] retain];
+
+    BOOL notDone = YES;
+    while (notDone) {
+      @autoreleasepool {
+        notDone = DoTestIo(input, output);
+      }
+    }
+
+    NSLog(@"Received EOF from test runner after %d tests, exiting.", testCount);
+  }
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/conformance/conformance_python.py b/src/third_party/protobuf-3/conformance/conformance_python.py
new file mode 100755
index 0000000..a490c8e
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_python.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""A conformance test implementation for the Python protobuf library.
+
+See conformance.proto for more information.
+"""
+
+import struct
+import sys
+import os
+from google.protobuf import message
+from google.protobuf import json_format
+import conformance_pb2
+
+sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
+sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
+
+test_count = 0
+verbose = False
+
+class ProtocolError(Exception):
+  pass
+
+def do_test(request):
+  test_message = conformance_pb2.TestAllTypes()
+  response = conformance_pb2.ConformanceResponse()
+  test_message = conformance_pb2.TestAllTypes()
+
+  try:
+    if request.WhichOneof('payload') == 'protobuf_payload':
+      try:
+        test_message.ParseFromString(request.protobuf_payload)
+      except message.DecodeError as e:
+        response.parse_error = str(e)
+        return response
+
+    elif request.WhichOneof('payload') == 'json_payload':
+      try:
+        json_format.Parse(request.json_payload, test_message)
+      except json_format.ParseError as e:
+        response.parse_error = str(e)
+        return response
+
+    else:
+      raise ProtocolError("Request didn't have payload.")
+
+    if request.requested_output_format == conformance_pb2.UNSPECIFIED:
+      raise ProtocolError("Unspecified output format")
+
+    elif request.requested_output_format == conformance_pb2.PROTOBUF:
+      response.protobuf_payload = test_message.SerializeToString()
+
+    elif request.requested_output_format == conformance_pb2.JSON:
+      response.json_payload = json_format.MessageToJson(test_message)
+
+  except Exception as e:
+    response.runtime_error = str(e)
+
+  return response
+
+def do_test_io():
+  length_bytes = sys.stdin.read(4)
+  if len(length_bytes) == 0:
+    return False   # EOF
+  elif len(length_bytes) != 4:
+    raise IOError("I/O error")
+
+  # "I" is "unsigned int", so this depends on running on a platform with
+  # 32-bit "unsigned int" type.  The Python struct module unfortunately
+  # has no format specifier for uint32_t.
+  length = struct.unpack("<I", length_bytes)[0]
+  serialized_request = sys.stdin.read(length)
+  if len(serialized_request) != length:
+    raise IOError("I/O error")
+
+  request = conformance_pb2.ConformanceRequest()
+  request.ParseFromString(serialized_request)
+
+  response = do_test(request)
+
+  serialized_response = response.SerializeToString()
+  sys.stdout.write(struct.pack("<I", len(serialized_response)))
+  sys.stdout.write(serialized_response)
+  sys.stdout.flush()
+
+  if verbose:
+    sys.stderr.write("conformance_python: request=%s, response=%s\n" % (
+                       request.ShortDebugString().c_str(),
+                       response.ShortDebugString().c_str()))
+
+  global test_count
+  test_count += 1
+
+  return True
+
+while True:
+  if not do_test_io():
+    sys.stderr.write("conformance_python: received EOF from test runner " +
+                     "after %s tests, exiting\n" % (test_count))
+    sys.exit(0)
diff --git a/src/third_party/protobuf-3/conformance/conformance_ruby.rb b/src/third_party/protobuf-3/conformance/conformance_ruby.rb
new file mode 100755
index 0000000..c716fac
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_ruby.rb
@@ -0,0 +1,122 @@
+#!/usr/bin/env ruby
+#
+# 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.
+
+require 'conformance'
+
+$test_count = 0
+$verbose = false
+
+def do_test(request)
+  test_message = Conformance::TestAllTypes.new
+  response = Conformance::ConformanceResponse.new
+
+  begin
+    case request.payload
+    when :protobuf_payload
+      begin
+        test_message =
+          Conformance::TestAllTypes.decode(request.protobuf_payload)
+      rescue Google::Protobuf::ParseError => err
+        response.parse_error = err.message.encode('utf-8')
+        return response
+      end
+
+    when :json_payload
+      begin
+        test_message = Conformance::TestAllTypes.decode_json(request.json_payload)
+      rescue Google::Protobuf::ParseError => err
+        response.parse_error = err.message.encode('utf-8')
+        return response
+      end
+
+    when nil
+      fail "Request didn't have payload"
+    end
+
+    case request.requested_output_format
+    when :UNSPECIFIED
+      fail 'Unspecified output format'
+
+    when :PROTOBUF
+      response.protobuf_payload = test_message.to_proto
+
+    when :JSON
+      response.json_payload = test_message.to_json
+
+    when nil
+      fail "Request didn't have requested output format"
+    end
+  rescue StandardError => err
+    response.runtime_error = err.message.encode('utf-8')
+  end
+
+  response
+end
+
+# Returns true if the test ran successfully, false on legitimate EOF.
+# If EOF is encountered in an unexpected place, raises IOError.
+def do_test_io
+  length_bytes = STDIN.read(4)
+  return false if length_bytes.nil?
+
+  length = length_bytes.unpack('V').first
+  serialized_request = STDIN.read(length)
+  if serialized_request.nil? || serialized_request.length != length
+    fail IOError
+  end
+
+  request = Conformance::ConformanceRequest.decode(serialized_request)
+
+  response = do_test(request)
+
+  serialized_response = Conformance::ConformanceResponse.encode(response)
+  STDOUT.write([serialized_response.length].pack('V'))
+  STDOUT.write(serialized_response)
+  STDOUT.flush
+
+  if $verbose
+    STDERR.puts("conformance_ruby: request=#{request.to_json}, " \
+                                 "response=#{response.to_json}\n")
+  end
+
+  $test_count += 1
+
+  true
+end
+
+loop do
+  unless do_test_io
+    STDERR.puts('conformance_ruby: received EOF from test runner ' \
+                "after #{$test_count} tests, exiting")
+    break
+  end
+end
diff --git a/src/third_party/protobuf-3/conformance/conformance_test.cc b/src/third_party/protobuf-3/conformance/conformance_test.cc
new file mode 100644
index 0000000..fc0605b
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_test.cc
@@ -0,0 +1,2006 @@
+// 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.
+
+#include <stdarg.h>
+#include <string>
+
+#include "conformance.pb.h"
+#include "conformance_test.h"
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <google/protobuf/wire_format_lite.h>
+
+#include "third_party/jsoncpp/json.h"
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using conformance::TestAllTypes;
+using conformance::WireFormat;
+using google::protobuf::Descriptor;
+using google::protobuf::FieldDescriptor;
+using google::protobuf::internal::WireFormatLite;
+using google::protobuf::TextFormat;
+using google::protobuf::util::DefaultFieldComparator;
+using google::protobuf::util::JsonToBinaryString;
+using google::protobuf::util::MessageDifferencer;
+using google::protobuf::util::NewTypeResolverForDescriptorPool;
+using google::protobuf::util::Status;
+using std::string;
+
+namespace {
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+  return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+/* Routines for building arbitrary protos *************************************/
+
+// We would use CodedOutputStream except that we want more freedom to build
+// arbitrary protos (even invalid ones).
+
+const string empty;
+
+string cat(const string& a, const string& b,
+           const string& c = empty,
+           const string& d = empty,
+           const string& e = empty,
+           const string& f = empty,
+           const string& g = empty,
+           const string& h = empty,
+           const string& i = empty,
+           const string& j = empty,
+           const string& k = empty,
+           const string& l = empty) {
+  string ret;
+  ret.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() +
+              g.size() + h.size() + i.size() + j.size() + k.size() + l.size());
+  ret.append(a);
+  ret.append(b);
+  ret.append(c);
+  ret.append(d);
+  ret.append(e);
+  ret.append(f);
+  ret.append(g);
+  ret.append(h);
+  ret.append(i);
+  ret.append(j);
+  ret.append(k);
+  ret.append(l);
+  return ret;
+}
+
+// The maximum number of bytes that it takes to encode a 64-bit varint.
+#define VARINT_MAX_LEN 10
+
+size_t vencode64(uint64_t val, char *buf) {
+  if (val == 0) { buf[0] = 0; return 1; }
+  size_t i = 0;
+  while (val) {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  }
+  return i;
+}
+
+string varint(uint64_t x) {
+  char buf[VARINT_MAX_LEN];
+  size_t len = vencode64(x, buf);
+  return string(buf, len);
+}
+
+// TODO: proper byte-swapping for big-endian machines.
+string fixed32(void *data) { return string(static_cast<char*>(data), 4); }
+string fixed64(void *data) { return string(static_cast<char*>(data), 8); }
+
+string delim(const string& buf) { return cat(varint(buf.size()), buf); }
+string uint32(uint32_t u32) { return fixed32(&u32); }
+string uint64(uint64_t u64) { return fixed64(&u64); }
+string flt(float f) { return fixed32(&f); }
+string dbl(double d) { return fixed64(&d); }
+string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); }
+string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); }
+
+string tag(uint32_t fieldnum, char wire_type) {
+  return varint((fieldnum << 3) | wire_type);
+}
+
+string submsg(uint32_t fn, const string& buf) {
+  return cat( tag(fn, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(buf) );
+}
+
+#define UNKNOWN_FIELD 666
+
+uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) {
+  const Descriptor* d = TestAllTypes().GetDescriptor();
+  for (int i = 0; i < d->field_count(); i++) {
+    const FieldDescriptor* f = d->field(i);
+    if (f->type() == type && f->is_repeated() == repeated) {
+      return f->number();
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type;
+  return 0;
+}
+
+string UpperCase(string str) {
+  for (int i = 0; i < str.size(); i++) {
+    str[i] = toupper(str[i]);
+  }
+  return str;
+}
+
+}  // anonymous namespace
+
+namespace google {
+namespace protobuf {
+
+void ConformanceTestSuite::ReportSuccess(const string& test_name) {
+  if (expected_to_fail_.erase(test_name) != 0) {
+    StringAppendF(&output_,
+                  "ERROR: test %s is in the failure list, but test succeeded.  "
+                  "Remove it from the failure list.\n",
+                  test_name.c_str());
+    unexpected_succeeding_tests_.insert(test_name);
+  }
+  successes_++;
+}
+
+void ConformanceTestSuite::ReportFailure(const string& test_name,
+                                         const ConformanceRequest& request,
+                                         const ConformanceResponse& response,
+                                         const char* fmt, ...) {
+  if (expected_to_fail_.erase(test_name) == 1) {
+    expected_failures_++;
+    if (!verbose_)
+      return;
+  } else {
+    StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
+    unexpected_failing_tests_.insert(test_name);
+  }
+  va_list args;
+  va_start(args, fmt);
+  StringAppendV(&output_, fmt, args);
+  va_end(args);
+  StringAppendF(&output_, " request=%s, response=%s\n",
+                request.ShortDebugString().c_str(),
+                response.ShortDebugString().c_str());
+}
+
+void ConformanceTestSuite::ReportSkip(const string& test_name,
+                                      const ConformanceRequest& request,
+                                      const ConformanceResponse& response) {
+  if (verbose_) {
+    StringAppendF(&output_, "SKIPPED, test=%s request=%s, response=%s\n",
+                  test_name.c_str(), request.ShortDebugString().c_str(),
+                  response.ShortDebugString().c_str());
+  }
+  skipped_.insert(test_name);
+}
+
+void ConformanceTestSuite::RunTest(const string& test_name,
+                                   const ConformanceRequest& request,
+                                   ConformanceResponse* response) {
+  if (test_names_.insert(test_name).second == false) {
+    GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name;
+  }
+
+  string serialized_request;
+  string serialized_response;
+  request.SerializeToString(&serialized_request);
+
+  runner_->RunTest(test_name, serialized_request, &serialized_response);
+
+  if (!response->ParseFromString(serialized_response)) {
+    response->Clear();
+    response->set_runtime_error("response proto could not be parsed.");
+  }
+
+  if (verbose_) {
+    StringAppendF(&output_, "conformance test: name=%s, request=%s, response=%s\n",
+                  test_name.c_str(),
+                  request.ShortDebugString().c_str(),
+                  response->ShortDebugString().c_str());
+  }
+}
+
+void ConformanceTestSuite::RunValidInputTest(
+    const string& test_name, const string& input, WireFormat input_format,
+    const string& equivalent_text_format, WireFormat requested_output) {
+  TestAllTypes reference_message;
+  GOOGLE_CHECK(
+      TextFormat::ParseFromString(equivalent_text_format, &reference_message))
+          << "Failed to parse data for test case: " << test_name
+          << ", data: " << equivalent_text_format;
+
+  ConformanceRequest request;
+  ConformanceResponse response;
+
+  switch (input_format) {
+    case conformance::PROTOBUF:
+      request.set_protobuf_payload(input);
+      break;
+
+    case conformance::JSON:
+      request.set_json_payload(input);
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Unspecified input format";
+  }
+
+  request.set_requested_output_format(requested_output);
+
+  RunTest(test_name, request, &response);
+
+  TestAllTypes test_message;
+
+  switch (response.result_case()) {
+    case ConformanceResponse::kParseError:
+    case ConformanceResponse::kRuntimeError:
+    case ConformanceResponse::kSerializeError:
+      ReportFailure(test_name, request, response,
+                    "Failed to parse JSON input or produce JSON output.");
+      return;
+
+    case ConformanceResponse::kSkipped:
+      ReportSkip(test_name, request, response);
+      return;
+
+    case ConformanceResponse::kJsonPayload: {
+      if (requested_output != conformance::JSON) {
+        ReportFailure(
+            test_name, request, response,
+            "Test was asked for protobuf output but provided JSON instead.");
+        return;
+      }
+      string binary_protobuf;
+      Status status =
+          JsonToBinaryString(type_resolver_.get(), type_url_,
+                             response.json_payload(), &binary_protobuf);
+      if (!status.ok()) {
+        ReportFailure(test_name, request, response,
+                      "JSON output we received from test was unparseable.");
+        return;
+      }
+
+      if (!test_message.ParseFromString(binary_protobuf)) {
+        ReportFailure(test_name, request, response,
+                      "INTERNAL ERROR: internal JSON->protobuf transcode "
+                      "yielded unparseable proto.");
+        return;
+      }
+
+      break;
+    }
+
+    case ConformanceResponse::kProtobufPayload: {
+      if (requested_output != conformance::PROTOBUF) {
+        ReportFailure(
+            test_name, request, response,
+            "Test was asked for JSON output but provided protobuf instead.");
+        return;
+      }
+
+      if (!test_message.ParseFromString(response.protobuf_payload())) {
+        ReportFailure(test_name, request, response,
+                      "Protobuf output we received from test was unparseable.");
+        return;
+      }
+
+      break;
+    }
+
+    default:
+      GOOGLE_LOG(FATAL) << test_name << ": unknown payload type: "
+                        << response.result_case();
+  }
+
+  MessageDifferencer differencer;
+  DefaultFieldComparator field_comparator;
+  field_comparator.set_treat_nan_as_equal(true);
+  differencer.set_field_comparator(&field_comparator);
+  string differences;
+  differencer.ReportDifferencesToString(&differences);
+
+  if (differencer.Compare(reference_message, test_message)) {
+    ReportSuccess(test_name);
+  } else {
+    ReportFailure(test_name, request, response,
+                  "Output was not equivalent to reference message: %s.",
+                  differences.c_str());
+  }
+}
+
+// Expect that this precise protobuf will cause a parse error.
+void ConformanceTestSuite::ExpectParseFailureForProto(
+    const string& proto, const string& test_name) {
+  ConformanceRequest request;
+  ConformanceResponse response;
+  request.set_protobuf_payload(proto);
+  string effective_test_name = "ProtobufInput." + test_name;
+
+  // We don't expect output, but if the program erroneously accepts the protobuf
+  // we let it send its response as this.  We must not leave it unspecified.
+  request.set_requested_output_format(conformance::PROTOBUF);
+
+  RunTest(effective_test_name, request, &response);
+  if (response.result_case() == ConformanceResponse::kParseError) {
+    ReportSuccess(effective_test_name);
+  } else if (response.result_case() == ConformanceResponse::kSkipped) {
+    ReportSkip(effective_test_name, request, response);
+  } else {
+    ReportFailure(effective_test_name, request, response,
+                  "Should have failed to parse, but didn't.");
+  }
+}
+
+// Expect that this protobuf will cause a parse error, even if it is followed
+// by valid protobuf data.  We can try running this twice: once with this
+// data verbatim and once with this data followed by some valid data.
+//
+// TODO(haberman): implement the second of these.
+void ConformanceTestSuite::ExpectHardParseFailureForProto(
+    const string& proto, const string& test_name) {
+  return ExpectParseFailureForProto(proto, test_name);
+}
+
+void ConformanceTestSuite::RunValidJsonTest(
+    const string& test_name, const string& input_json,
+    const string& equivalent_text_format) {
+  RunValidInputTest("JsonInput." + test_name + ".ProtobufOutput", input_json,
+                    conformance::JSON, equivalent_text_format,
+                    conformance::PROTOBUF);
+  RunValidInputTest("JsonInput." + test_name + ".JsonOutput", input_json,
+                    conformance::JSON, equivalent_text_format,
+                    conformance::JSON);
+}
+
+void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
+    const string& test_name, const TestAllTypes& input,
+    const string& equivalent_text_format) {
+  RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput",
+                    input.SerializeAsString(), conformance::PROTOBUF,
+                    equivalent_text_format, conformance::JSON);
+}
+
+// According to proto3 JSON specification, JSON serializers follow more strict
+// rules than parsers (e.g., a serializer must serialize int32 values as JSON
+// numbers while the parser is allowed to accept them as JSON strings). This
+// method allows strict checking on a proto3 JSON serializer by inspecting
+// the JSON output directly.
+void ConformanceTestSuite::RunValidJsonTestWithValidator(
+    const string& test_name, const string& input_json,
+    const Validator& validator) {
+  ConformanceRequest request;
+  ConformanceResponse response;
+  request.set_json_payload(input_json);
+  request.set_requested_output_format(conformance::JSON);
+
+  string effective_test_name = "JsonInput." + test_name + ".Validator";
+
+  RunTest(effective_test_name, request, &response);
+
+  if (response.result_case() == ConformanceResponse::kSkipped) {
+    ReportSkip(effective_test_name, request, response);
+    return;
+  }
+
+  if (response.result_case() != ConformanceResponse::kJsonPayload) {
+    ReportFailure(effective_test_name, request, response,
+                  "Expected JSON payload but got type %d.",
+                  response.result_case());
+    return;
+  }
+  Json::Reader reader;
+  Json::Value value;
+  if (!reader.parse(response.json_payload(), value)) {
+    ReportFailure(effective_test_name, request, response,
+                  "JSON payload cannot be parsed as valid JSON: %s",
+                  reader.getFormattedErrorMessages().c_str());
+    return;
+  }
+  if (!validator(value)) {
+    ReportFailure(effective_test_name, request, response,
+                  "JSON payload validation failed.");
+    return;
+  }
+  ReportSuccess(effective_test_name);
+}
+
+void ConformanceTestSuite::ExpectParseFailureForJson(
+    const string& test_name, const string& input_json) {
+  ConformanceRequest request;
+  ConformanceResponse response;
+  request.set_json_payload(input_json);
+  string effective_test_name = "JsonInput." + test_name;
+
+  // We don't expect output, but if the program erroneously accepts the protobuf
+  // we let it send its response as this.  We must not leave it unspecified.
+  request.set_requested_output_format(conformance::JSON);
+
+  RunTest(effective_test_name, request, &response);
+  if (response.result_case() == ConformanceResponse::kParseError) {
+    ReportSuccess(effective_test_name);
+  } else if (response.result_case() == ConformanceResponse::kSkipped) {
+    ReportSkip(effective_test_name, request, response);
+  } else {
+    ReportFailure(effective_test_name, request, response,
+                  "Should have failed to parse, but didn't.");
+  }
+}
+
+void ConformanceTestSuite::ExpectSerializeFailureForJson(
+    const string& test_name, const string& text_format) {
+  TestAllTypes payload_message;
+  GOOGLE_CHECK(
+      TextFormat::ParseFromString(text_format, &payload_message))
+          << "Failed to parse: " << text_format;
+
+  ConformanceRequest request;
+  ConformanceResponse response;
+  request.set_protobuf_payload(payload_message.SerializeAsString());
+  string effective_test_name = test_name + ".JsonOutput";
+  request.set_requested_output_format(conformance::JSON);
+
+  RunTest(effective_test_name, request, &response);
+  if (response.result_case() == ConformanceResponse::kSerializeError) {
+    ReportSuccess(effective_test_name);
+  } else if (response.result_case() == ConformanceResponse::kSkipped) {
+    ReportSkip(effective_test_name, request, response);
+  } else {
+    ReportFailure(effective_test_name, request, response,
+                  "Should have failed to serialize, but didn't.");
+  }
+}
+
+void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
+  // Incomplete values for each wire type.
+  static const string incompletes[6] = {
+    string("\x80"),     // VARINT
+    string("abcdefg"),  // 64BIT
+    string("\x80"),     // DELIMITED (partial length)
+    string(),           // START_GROUP (no value required)
+    string(),           // END_GROUP (no value required)
+    string("abc")       // 32BIT
+  };
+
+  uint32_t fieldnum = GetFieldNumberForType(type, false);
+  uint32_t rep_fieldnum = GetFieldNumberForType(type, true);
+  WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+      static_cast<WireFormatLite::FieldType>(type));
+  const string& incomplete = incompletes[wire_type];
+  const string type_name =
+      UpperCase(string(".") + FieldDescriptor::TypeName(type));
+
+  ExpectParseFailureForProto(
+      tag(fieldnum, wire_type),
+      "PrematureEofBeforeKnownNonRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      tag(rep_fieldnum, wire_type),
+      "PrematureEofBeforeKnownRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      tag(UNKNOWN_FIELD, wire_type),
+      "PrematureEofBeforeUnknownValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(fieldnum, wire_type), incomplete ),
+      "PrematureEofInsideKnownNonRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(rep_fieldnum, wire_type), incomplete ),
+      "PrematureEofInsideKnownRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(UNKNOWN_FIELD, wire_type), incomplete ),
+      "PrematureEofInsideUnknownValue" + type_name);
+
+  if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+    ExpectParseFailureForProto(
+        cat( tag(fieldnum, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name);
+
+    ExpectParseFailureForProto(
+        cat( tag(rep_fieldnum, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name);
+
+    // EOF in the middle of delimited data for unknown value.
+    ExpectParseFailureForProto(
+        cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForUnknownValue" + type_name);
+
+    if (type == FieldDescriptor::TYPE_MESSAGE) {
+      // Submessage ends in the middle of a value.
+      string incomplete_submsg =
+          cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT),
+                incompletes[WireFormatLite::WIRETYPE_VARINT] );
+      ExpectHardParseFailureForProto(
+          cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+               varint(incomplete_submsg.size()),
+               incomplete_submsg ),
+          "PrematureEofInSubmessageValue" + type_name);
+    }
+  } else if (type != FieldDescriptor::TYPE_GROUP) {
+    // Non-delimited, non-group: eligible for packing.
+
+    // Packed region ends in the middle of a value.
+    ExpectHardParseFailureForProto(
+        cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+             varint(incomplete.size()),
+             incomplete ),
+        "PrematureEofInPackedFieldValue" + type_name);
+
+    // EOF in the middle of packed region.
+    ExpectParseFailureForProto(
+        cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+             varint(1) ),
+        "PrematureEofInPackedField" + type_name);
+  }
+}
+
+void ConformanceTestSuite::SetFailureList(const vector<string>& failure_list) {
+  expected_to_fail_.clear();
+  std::copy(failure_list.begin(), failure_list.end(),
+            std::inserter(expected_to_fail_, expected_to_fail_.end()));
+}
+
+bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
+                                         const char* msg) {
+  if (set_to_check.empty()) {
+    return true;
+  } else {
+    StringAppendF(&output_, "\n");
+    StringAppendF(&output_, "%s:\n", msg);
+    for (set<string>::const_iterator iter = set_to_check.begin();
+         iter != set_to_check.end(); ++iter) {
+      StringAppendF(&output_, "  %s\n", iter->c_str());
+    }
+    StringAppendF(&output_, "\n");
+    return false;
+  }
+}
+
+bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
+                                    std::string* output) {
+  runner_ = runner;
+  successes_ = 0;
+  expected_failures_ = 0;
+  skipped_.clear();
+  test_names_.clear();
+  unexpected_failing_tests_.clear();
+  unexpected_succeeding_tests_.clear();
+  type_resolver_.reset(NewTypeResolverForDescriptorPool(
+      kTypeUrlPrefix, DescriptorPool::generated_pool()));
+  type_url_ = GetTypeUrl(TestAllTypes::descriptor());
+
+  output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
+
+  for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) {
+    if (i == FieldDescriptor::TYPE_GROUP) continue;
+    TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
+  }
+
+  RunValidJsonTest("HelloWorld", "{\"optionalString\":\"Hello, World!\"}",
+                   "optional_string: 'Hello, World!'");
+
+  // Test field name conventions.
+  RunValidJsonTest(
+      "FieldNameInSnakeCase",
+      R"({
+        "fieldname1": 1,
+        "fieldName2": 2,
+        "FieldName3": 3
+      })",
+      R"(
+        fieldname1: 1
+        field_name2: 2
+        _field_name3: 3
+      )");
+  RunValidJsonTest(
+      "FieldNameWithNumbers",
+      R"({
+        "field0name5": 5,
+        "field0Name6": 6
+      })",
+      R"(
+        field0name5: 5
+        field_0_name6: 6
+      )");
+  RunValidJsonTest(
+      "FieldNameWithMixedCases",
+      R"({
+        "fieldName7": 7,
+        "fieldName8": 8,
+        "fieldName9": 9,
+        "fieldName10": 10,
+        "fIELDNAME11": 11,
+        "fIELDName12": 12
+      })",
+      R"(
+        fieldName7: 7
+        FieldName8: 8
+        field_Name9: 9
+        Field_Name10: 10
+        FIELD_NAME11: 11
+        FIELD_name12: 12
+      )");
+  // Using the original proto field name in JSON is also allowed.
+  RunValidJsonTest(
+      "OriginalProtoFieldName",
+      R"({
+        "fieldname1": 1,
+        "field_name2": 2,
+        "_field_name3": 3,
+        "field0name5": 5,
+        "field_0_name6": 6,
+        "fieldName7": 7,
+        "FieldName8": 8,
+        "field_Name9": 9,
+        "Field_Name10": 10,
+        "FIELD_NAME11": 11,
+        "FIELD_name12": 12
+      })",
+      R"(
+        fieldname1: 1
+        field_name2: 2
+        _field_name3: 3
+        field0name5: 5
+        field_0_name6: 6
+        fieldName7: 7
+        FieldName8: 8
+        field_Name9: 9
+        Field_Name10: 10
+        FIELD_NAME11: 11
+        FIELD_name12: 12
+      )");
+  // Field names can be escaped.
+  RunValidJsonTest(
+      "FieldNameEscaped",
+      R"({"fieldn\u0061me1": 1})",
+      "fieldname1: 1");
+  // Field names must be quoted (or it's not valid JSON).
+  ExpectParseFailureForJson(
+      "FieldNameNotQuoted",
+      "{fieldname1: 1}");
+  // Trailing comma is not allowed (not valid JSON).
+  ExpectParseFailureForJson(
+      "TrailingCommaInAnObject",
+      R"({"fieldname1":1,})");
+  // JSON doesn't support comments.
+  ExpectParseFailureForJson(
+      "JsonWithComments",
+      R"({
+        // This is a comment.
+        "fieldname1": 1
+      })");
+  // Duplicated field names are not allowed.
+  ExpectParseFailureForJson(
+      "FieldNameDuplicate",
+      R"({
+        "optionalNestedMessage": {a: 1},
+        "optionalNestedMessage": {}
+      })");
+  ExpectParseFailureForJson(
+      "FieldNameDuplicateDifferentCasing1",
+      R"({
+        "optional_nested_message": {a: 1},
+        "optionalNestedMessage": {}
+      })");
+  ExpectParseFailureForJson(
+      "FieldNameDuplicateDifferentCasing2",
+      R"({
+        "optionalNestedMessage": {a: 1},
+        "optional_nested_message": {}
+      })");
+  // Serializers should use lowerCamelCase by default.
+  RunValidJsonTestWithValidator(
+      "FieldNameInLowerCamelCase",
+      R"({
+        "fieldname1": 1,
+        "fieldName2": 2,
+        "FieldName3": 3
+      })",
+      [](const Json::Value& value) {
+        return value.isMember("fieldname1") &&
+            value.isMember("fieldName2") &&
+            value.isMember("FieldName3");
+      });
+  RunValidJsonTestWithValidator(
+      "FieldNameWithNumbers",
+      R"({
+        "field0name5": 5,
+        "field0Name6": 6
+      })",
+      [](const Json::Value& value) {
+        return value.isMember("field0name5") &&
+            value.isMember("field0Name6");
+      });
+  RunValidJsonTestWithValidator(
+      "FieldNameWithMixedCases",
+      R"({
+        "fieldName7": 7,
+        "fieldName8": 8,
+        "fieldName9": 9,
+        "fieldName10": 10,
+        "fIELDNAME11": 11,
+        "fIELDName12": 12
+      })",
+      [](const Json::Value& value) {
+        return value.isMember("fieldName7") &&
+            value.isMember("fieldName8") &&
+            value.isMember("fieldName9") &&
+            value.isMember("fieldName10") &&
+            value.isMember("fIELDNAME11") &&
+            value.isMember("fIELDName12");
+      });
+
+  // Integer fields.
+  RunValidJsonTest(
+      "Int32FieldMaxValue",
+      R"({"optionalInt32": 2147483647})",
+      "optional_int32: 2147483647");
+  RunValidJsonTest(
+      "Int32FieldMinValue",
+      R"({"optionalInt32": -2147483648})",
+      "optional_int32: -2147483648");
+  RunValidJsonTest(
+      "Uint32FieldMaxValue",
+      R"({"optionalUint32": 4294967295})",
+      "optional_uint32: 4294967295");
+  RunValidJsonTest(
+      "Int64FieldMaxValue",
+      R"({"optionalInt64": "9223372036854775807"})",
+      "optional_int64: 9223372036854775807");
+  RunValidJsonTest(
+      "Int64FieldMinValue",
+      R"({"optionalInt64": "-9223372036854775808"})",
+      "optional_int64: -9223372036854775808");
+  RunValidJsonTest(
+      "Uint64FieldMaxValue",
+      R"({"optionalUint64": "18446744073709551615"})",
+      "optional_uint64: 18446744073709551615");
+  RunValidJsonTest(
+      "Int64FieldMaxValueNotQuoted",
+      R"({"optionalInt64": 9223372036854775807})",
+      "optional_int64: 9223372036854775807");
+  RunValidJsonTest(
+      "Int64FieldMinValueNotQuoted",
+      R"({"optionalInt64": -9223372036854775808})",
+      "optional_int64: -9223372036854775808");
+  RunValidJsonTest(
+      "Uint64FieldMaxValueNotQuoted",
+      R"({"optionalUint64": 18446744073709551615})",
+      "optional_uint64: 18446744073709551615");
+  // Values can be represented as JSON strings.
+  RunValidJsonTest(
+      "Int32FieldStringValue",
+      R"({"optionalInt32": "2147483647"})",
+      "optional_int32: 2147483647");
+  RunValidJsonTest(
+      "Int32FieldStringValueEscaped",
+      R"({"optionalInt32": "2\u003147483647"})",
+      "optional_int32: 2147483647");
+
+  // Parsers reject out-of-bound integer values.
+  ExpectParseFailureForJson(
+      "Int32FieldTooLarge",
+      R"({"optionalInt32": 2147483648})");
+  ExpectParseFailureForJson(
+      "Int32FieldTooSmall",
+      R"({"optionalInt32": -2147483649})");
+  ExpectParseFailureForJson(
+      "Uint32FieldTooLarge",
+      R"({"optionalUint32": 4294967296})");
+  ExpectParseFailureForJson(
+      "Int64FieldTooLarge",
+      R"({"optionalInt64": "9223372036854775808"})");
+  ExpectParseFailureForJson(
+      "Int64FieldTooSmall",
+      R"({"optionalInt64": "-9223372036854775809"})");
+  ExpectParseFailureForJson(
+      "Uint64FieldTooLarge",
+      R"({"optionalUint64": "18446744073709551616"})");
+  // Parser reject non-integer numeric values as well.
+  ExpectParseFailureForJson(
+      "Int32FieldNotInteger",
+      R"({"optionalInt32": 0.5})");
+  ExpectParseFailureForJson(
+      "Uint32FieldNotInteger",
+      R"({"optionalUint32": 0.5})");
+  ExpectParseFailureForJson(
+      "Int64FieldNotInteger",
+      R"({"optionalInt64": "0.5"})");
+  ExpectParseFailureForJson(
+      "Uint64FieldNotInteger",
+      R"({"optionalUint64": "0.5"})");
+
+  // Integers but represented as float values are accepted.
+  RunValidJsonTest(
+      "Int32FieldFloatTrailingZero",
+      R"({"optionalInt32": 100000.000})",
+      "optional_int32: 100000");
+  RunValidJsonTest(
+      "Int32FieldExponentialFormat",
+      R"({"optionalInt32": 1e5})",
+      "optional_int32: 100000");
+  RunValidJsonTest(
+      "Int32FieldMaxFloatValue",
+      R"({"optionalInt32": 2.147483647e9})",
+      "optional_int32: 2147483647");
+  RunValidJsonTest(
+      "Int32FieldMinFloatValue",
+      R"({"optionalInt32": -2.147483648e9})",
+      "optional_int32: -2147483648");
+  RunValidJsonTest(
+      "Uint32FieldMaxFloatValue",
+      R"({"optionalUint32": 4.294967295e9})",
+      "optional_uint32: 4294967295");
+
+  // Parser reject non-numeric values.
+  ExpectParseFailureForJson(
+      "Int32FieldNotNumber",
+      R"({"optionalInt32": "3x3"})");
+  ExpectParseFailureForJson(
+      "Uint32FieldNotNumber",
+      R"({"optionalUint32": "3x3"})");
+  ExpectParseFailureForJson(
+      "Int64FieldNotNumber",
+      R"({"optionalInt64": "3x3"})");
+  ExpectParseFailureForJson(
+      "Uint64FieldNotNumber",
+      R"({"optionalUint64": "3x3"})");
+  // JSON does not allow "+" on numric values.
+  ExpectParseFailureForJson(
+      "Int32FieldPlusSign",
+      R"({"optionalInt32": +1})");
+  // JSON doesn't allow leading 0s.
+  ExpectParseFailureForJson(
+      "Int32FieldLeadingZero",
+      R"({"optionalInt32": 01})");
+  ExpectParseFailureForJson(
+      "Int32FieldNegativeWithLeadingZero",
+      R"({"optionalInt32": -01})");
+  // String values must follow the same syntax rule. Specifically leading
+  // or traling spaces are not allowed.
+  ExpectParseFailureForJson(
+      "Int32FieldLeadingSpace",
+      R"({"optionalInt32": " 1"})");
+  ExpectParseFailureForJson(
+      "Int32FieldTrailingSpace",
+      R"({"optionalInt32": "1 "})");
+
+  // 64-bit values are serialized as strings.
+  RunValidJsonTestWithValidator(
+      "Int64FieldBeString",
+      R"({"optionalInt64": 1})",
+      [](const Json::Value& value) {
+        return value["optionalInt64"].type() == Json::stringValue &&
+            value["optionalInt64"].asString() == "1";
+      });
+  RunValidJsonTestWithValidator(
+      "Uint64FieldBeString",
+      R"({"optionalUint64": 1})",
+      [](const Json::Value& value) {
+        return value["optionalUint64"].type() == Json::stringValue &&
+            value["optionalUint64"].asString() == "1";
+      });
+
+  // Bool fields.
+  RunValidJsonTest(
+      "BoolFieldTrue",
+      R"({"optionalBool":true})",
+      "optional_bool: true");
+  RunValidJsonTest(
+      "BoolFieldFalse",
+      R"({"optionalBool":false})",
+      "optional_bool: false");
+
+  // Other forms are not allowed.
+  ExpectParseFailureForJson(
+      "BoolFieldIntegerZero",
+      R"({"optionalBool":0})");
+  ExpectParseFailureForJson(
+      "BoolFieldIntegerOne",
+      R"({"optionalBool":1})");
+  ExpectParseFailureForJson(
+      "BoolFieldCamelCaseTrue",
+      R"({"optionalBool":True})");
+  ExpectParseFailureForJson(
+      "BoolFieldCamelCaseFalse",
+      R"({"optionalBool":False})");
+  ExpectParseFailureForJson(
+      "BoolFieldAllCapitalTrue",
+      R"({"optionalBool":TRUE})");
+  ExpectParseFailureForJson(
+      "BoolFieldAllCapitalFalse",
+      R"({"optionalBool":FALSE})");
+  ExpectParseFailureForJson(
+      "BoolFieldDoubleQuotedTrue",
+      R"({"optionalBool":"true"})");
+  ExpectParseFailureForJson(
+      "BoolFieldDoubleQuotedFalse",
+      R"({"optionalBool":"false"})");
+
+  // Float fields.
+  RunValidJsonTest(
+      "FloatFieldMinPositiveValue",
+      R"({"optionalFloat": 1.175494e-38})",
+      "optional_float: 1.175494e-38");
+  RunValidJsonTest(
+      "FloatFieldMaxNegativeValue",
+      R"({"optionalFloat": -1.175494e-38})",
+      "optional_float: -1.175494e-38");
+  RunValidJsonTest(
+      "FloatFieldMaxPositiveValue",
+      R"({"optionalFloat": 3.402823e+38})",
+      "optional_float: 3.402823e+38");
+  RunValidJsonTest(
+      "FloatFieldMinNegativeValue",
+      R"({"optionalFloat": 3.402823e+38})",
+      "optional_float: 3.402823e+38");
+  // Values can be quoted.
+  RunValidJsonTest(
+      "FloatFieldQuotedValue",
+      R"({"optionalFloat": "1"})",
+      "optional_float: 1");
+  // Special values.
+  RunValidJsonTest(
+      "FloatFieldNan",
+      R"({"optionalFloat": "NaN"})",
+      "optional_float: nan");
+  RunValidJsonTest(
+      "FloatFieldInfinity",
+      R"({"optionalFloat": "Infinity"})",
+      "optional_float: inf");
+  RunValidJsonTest(
+      "FloatFieldNegativeInfinity",
+      R"({"optionalFloat": "-Infinity"})",
+      "optional_float: -inf");
+  // Non-cannonical Nan will be correctly normalized.
+  {
+    TestAllTypes message;
+    // IEEE floating-point standard 32-bit quiet NaN:
+    //   0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
+    message.set_optional_float(
+        WireFormatLite::DecodeFloat(0x7FA12345));
+    RunValidJsonTestWithProtobufInput(
+        "FloatFieldNormalizeQuietNan", message,
+        "optional_float: nan");
+    // IEEE floating-point standard 64-bit signaling NaN:
+    //   1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
+    message.set_optional_float(
+        WireFormatLite::DecodeFloat(0xFFB54321));
+    RunValidJsonTestWithProtobufInput(
+        "FloatFieldNormalizeSignalingNan", message,
+        "optional_float: nan");
+  }
+
+  // Special values must be quoted.
+  ExpectParseFailureForJson(
+      "FloatFieldNanNotQuoted",
+      R"({"optionalFloat": NaN})");
+  ExpectParseFailureForJson(
+      "FloatFieldInfinityNotQuoted",
+      R"({"optionalFloat": Infinity})");
+  ExpectParseFailureForJson(
+      "FloatFieldNegativeInfinityNotQuoted",
+      R"({"optionalFloat": -Infinity})");
+  // Parsers should reject out-of-bound values.
+  ExpectParseFailureForJson(
+      "FloatFieldTooSmall",
+      R"({"optionalFloat": -3.502823e+38})");
+  ExpectParseFailureForJson(
+      "FloatFieldTooLarge",
+      R"({"optionalFloat": 3.502823e+38})");
+
+  // Double fields.
+  RunValidJsonTest(
+      "DoubleFieldMinPositiveValue",
+      R"({"optionalDouble": 2.22507e-308})",
+      "optional_double: 2.22507e-308");
+  RunValidJsonTest(
+      "DoubleFieldMaxNegativeValue",
+      R"({"optionalDouble": -2.22507e-308})",
+      "optional_double: -2.22507e-308");
+  RunValidJsonTest(
+      "DoubleFieldMaxPositiveValue",
+      R"({"optionalDouble": 1.79769e+308})",
+      "optional_double: 1.79769e+308");
+  RunValidJsonTest(
+      "DoubleFieldMinNegativeValue",
+      R"({"optionalDouble": -1.79769e+308})",
+      "optional_double: -1.79769e+308");
+  // Values can be quoted.
+  RunValidJsonTest(
+      "DoubleFieldQuotedValue",
+      R"({"optionalDouble": "1"})",
+      "optional_double: 1");
+  // Speical values.
+  RunValidJsonTest(
+      "DoubleFieldNan",
+      R"({"optionalDouble": "NaN"})",
+      "optional_double: nan");
+  RunValidJsonTest(
+      "DoubleFieldInfinity",
+      R"({"optionalDouble": "Infinity"})",
+      "optional_double: inf");
+  RunValidJsonTest(
+      "DoubleFieldNegativeInfinity",
+      R"({"optionalDouble": "-Infinity"})",
+      "optional_double: -inf");
+  // Non-cannonical Nan will be correctly normalized.
+  {
+    TestAllTypes message;
+    message.set_optional_double(
+        WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL));
+    RunValidJsonTestWithProtobufInput(
+        "DoubleFieldNormalizeQuietNan", message,
+        "optional_double: nan");
+    message.set_optional_double(
+        WireFormatLite::DecodeDouble(0xFFFBCBA987654321LL));
+    RunValidJsonTestWithProtobufInput(
+        "DoubleFieldNormalizeSignalingNan", message,
+        "optional_double: nan");
+  }
+
+  // Special values must be quoted.
+  ExpectParseFailureForJson(
+      "DoubleFieldNanNotQuoted",
+      R"({"optionalDouble": NaN})");
+  ExpectParseFailureForJson(
+      "DoubleFieldInfinityNotQuoted",
+      R"({"optionalDouble": Infinity})");
+  ExpectParseFailureForJson(
+      "DoubleFieldNegativeInfinityNotQuoted",
+      R"({"optionalDouble": -Infinity})");
+
+  // Parsers should reject out-of-bound values.
+  ExpectParseFailureForJson(
+      "DoubleFieldTooSmall",
+      R"({"optionalDouble": -1.89769e+308})");
+  ExpectParseFailureForJson(
+      "DoubleFieldTooLarge",
+      R"({"optionalDouble": +1.89769e+308})");
+
+  // Enum fields.
+  RunValidJsonTest(
+      "EnumField",
+      R"({"optionalNestedEnum": "FOO"})",
+      "optional_nested_enum: FOO");
+  // Enum values must be represented as strings.
+  ExpectParseFailureForJson(
+      "EnumFieldNotQuoted",
+      R"({"optionalNestedEnum": FOO})");
+  // Numeric values are allowed.
+  RunValidJsonTest(
+      "EnumFieldNumericValueZero",
+      R"({"optionalNestedEnum": 0})",
+      "optional_nested_enum: FOO");
+  RunValidJsonTest(
+      "EnumFieldNumericValueNonZero",
+      R"({"optionalNestedEnum": 1})",
+      "optional_nested_enum: BAR");
+  // Unknown enum values are represented as numeric values.
+  RunValidJsonTestWithValidator(
+      "EnumFieldUnknownValue",
+      R"({"optionalNestedEnum": 123})",
+      [](const Json::Value& value) {
+        return value["optionalNestedEnum"].type() == Json::intValue &&
+            value["optionalNestedEnum"].asInt() == 123;
+      });
+
+  // String fields.
+  RunValidJsonTest(
+      "StringField",
+      R"({"optionalString": "Hello world!"})",
+      "optional_string: \"Hello world!\"");
+  RunValidJsonTest(
+      "StringFieldUnicode",
+      // Google in Chinese.
+      R"({"optionalString": "谷歌"})",
+      R"(optional_string: "谷歌")");
+  RunValidJsonTest(
+      "StringFieldEscape",
+      R"({"optionalString": "\"\\\/\b\f\n\r\t"})",
+      R"(optional_string: "\"\\/\b\f\n\r\t")");
+  RunValidJsonTest(
+      "StringFieldUnicodeEscape",
+      R"({"optionalString": "\u8C37\u6B4C"})",
+      R"(optional_string: "谷歌")");
+  RunValidJsonTest(
+      "StringFieldUnicodeEscapeWithLowercaseHexLetters",
+      R"({"optionalString": "\u8c37\u6b4c"})",
+      R"(optional_string: "谷歌")");
+  RunValidJsonTest(
+      "StringFieldSurrogatePair",
+      // The character is an emoji: grinning face with smiling eyes. 😁
+      R"({"optionalString": "\uD83D\uDE01"})",
+      R"(optional_string: "\xF0\x9F\x98\x81")");
+
+  // Unicode escapes must start with "\u" (lowercase u).
+  ExpectParseFailureForJson(
+      "StringFieldUppercaseEscapeLetter",
+      R"({"optionalString": "\U8C37\U6b4C"})");
+  ExpectParseFailureForJson(
+      "StringFieldInvalidEscape",
+      R"({"optionalString": "\uXXXX\u6B4C"})");
+  ExpectParseFailureForJson(
+      "StringFieldUnterminatedEscape",
+      R"({"optionalString": "\u8C3"})");
+  ExpectParseFailureForJson(
+      "StringFieldUnpairedHighSurrogate",
+      R"({"optionalString": "\uD800"})");
+  ExpectParseFailureForJson(
+      "StringFieldUnpairedLowSurrogate",
+      R"({"optionalString": "\uDC00"})");
+  ExpectParseFailureForJson(
+      "StringFieldSurrogateInWrongOrder",
+      R"({"optionalString": "\uDE01\uD83D"})");
+  ExpectParseFailureForJson(
+      "StringFieldNotAString",
+      R"({"optionalString": 12345})");
+
+  // Bytes fields.
+  RunValidJsonTest(
+      "BytesField",
+      R"({"optionalBytes": "AQI="})",
+      R"(optional_bytes: "\x01\x02")");
+  ExpectParseFailureForJson(
+      "BytesFieldNoPadding",
+      R"({"optionalBytes": "AQI"})");
+  ExpectParseFailureForJson(
+      "BytesFieldInvalidBase64Characters",
+      R"({"optionalBytes": "-_=="})");
+
+  // Message fields.
+  RunValidJsonTest(
+      "MessageField",
+      R"({"optionalNestedMessage": {"a": 1234}})",
+      "optional_nested_message: {a: 1234}");
+
+  // Oneof fields.
+  ExpectParseFailureForJson(
+      "OneofFieldDuplicate",
+      R"({"oneofUint32": 1, "oneofString": "test"})");
+
+  // Repeated fields.
+  RunValidJsonTest(
+      "PrimitiveRepeatedField",
+      R"({"repeatedInt32": [1, 2, 3, 4]})",
+      "repeated_int32: [1, 2, 3, 4]");
+  RunValidJsonTest(
+      "EnumRepeatedField",
+      R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})",
+      "repeated_nested_enum: [FOO, BAR, BAZ]");
+  RunValidJsonTest(
+      "StringRepeatedField",
+      R"({"repeatedString": ["Hello", "world"]})",
+      R"(repeated_string: ["Hello", "world"])");
+  RunValidJsonTest(
+      "BytesRepeatedField",
+      R"({"repeatedBytes": ["AAEC", "AQI="]})",
+      R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])");
+  RunValidJsonTest(
+      "MessageRepeatedField",
+      R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})",
+      "repeated_nested_message: {a: 1234}"
+      "repeated_nested_message: {a: 5678}");
+
+  // Repeated field elements are of incorrect type.
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingIntegersGotBool",
+      R"({"repeatedInt32": [1, false, 3, 4]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingIntegersGotString",
+      R"({"repeatedInt32": [1, 2, "name", 4]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage",
+      R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingStringsGotInt",
+      R"({"repeatedString": ["1", 2, "3", "4"]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingStringsGotBool",
+      R"({"repeatedString": ["1", "2", false, "4"]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingStringsGotMessage",
+      R"({"repeatedString": ["1", 2, "3", {"a": 4}]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingMessagesGotInt",
+      R"({"repeatedNestedMessage": [{"a": 1}, 2]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingMessagesGotBool",
+      R"({"repeatedNestedMessage": [{"a": 1}, false]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldWrongElementTypeExpectingMessagesGotString",
+      R"({"repeatedNestedMessage": [{"a": 1}, "2"]})");
+  // Trailing comma in the repeated field is not allowed.
+  ExpectParseFailureForJson(
+      "RepeatedFieldTrailingComma",
+      R"({"repeatedInt32": [1, 2, 3, 4,]})");
+
+  // Map fields.
+  RunValidJsonTest(
+      "Int32MapField",
+      R"({"mapInt32Int32": {"1": 2, "3": 4}})",
+      "map_int32_int32: {key: 1 value: 2}"
+      "map_int32_int32: {key: 3 value: 4}");
+  ExpectParseFailureForJson(
+      "Int32MapFieldKeyNotQuoted",
+      R"({"mapInt32Int32": {1: 2, 3: 4}})");
+  RunValidJsonTest(
+      "Uint32MapField",
+      R"({"mapUint32Uint32": {"1": 2, "3": 4}})",
+      "map_uint32_uint32: {key: 1 value: 2}"
+      "map_uint32_uint32: {key: 3 value: 4}");
+  ExpectParseFailureForJson(
+      "Uint32MapFieldKeyNotQuoted",
+      R"({"mapUint32Uint32": {1: 2, 3: 4}})");
+  RunValidJsonTest(
+      "Int64MapField",
+      R"({"mapInt64Int64": {"1": 2, "3": 4}})",
+      "map_int64_int64: {key: 1 value: 2}"
+      "map_int64_int64: {key: 3 value: 4}");
+  ExpectParseFailureForJson(
+      "Int64MapFieldKeyNotQuoted",
+      R"({"mapInt64Int64": {1: 2, 3: 4}})");
+  RunValidJsonTest(
+      "Uint64MapField",
+      R"({"mapUint64Uint64": {"1": 2, "3": 4}})",
+      "map_uint64_uint64: {key: 1 value: 2}"
+      "map_uint64_uint64: {key: 3 value: 4}");
+  ExpectParseFailureForJson(
+      "Uint64MapFieldKeyNotQuoted",
+      R"({"mapUint64Uint64": {1: 2, 3: 4}})");
+  RunValidJsonTest(
+      "BoolMapField",
+      R"({"mapBoolBool": {"true": true, "false": false}})",
+      "map_bool_bool: {key: true value: true}"
+      "map_bool_bool: {key: false value: false}");
+  ExpectParseFailureForJson(
+      "BoolMapFieldKeyNotQuoted",
+      R"({"mapBoolBool": {true: true, false: false}})");
+  RunValidJsonTest(
+      "MessageMapField",
+      R"({
+        "mapStringNestedMessage": {
+          "hello": {"a": 1234},
+          "world": {"a": 5678}
+        }
+      })",
+      R"(
+        map_string_nested_message: {
+          key: "hello"
+          value: {a: 1234}
+        }
+        map_string_nested_message: {
+          key: "world"
+          value: {a: 5678}
+        }
+      )");
+  // Since Map keys are represented as JSON strings, escaping should be allowed.
+  RunValidJsonTest(
+      "Int32MapEscapedKey",
+      R"({"mapInt32Int32": {"\u0031": 2}})",
+      "map_int32_int32: {key: 1 value: 2}");
+  RunValidJsonTest(
+      "Int64MapEscapedKey",
+      R"({"mapInt64Int64": {"\u0031": 2}})",
+      "map_int64_int64: {key: 1 value: 2}");
+  RunValidJsonTest(
+      "BoolMapEscapedKey",
+      R"({"mapBoolBool": {"tr\u0075e": true}})",
+      "map_bool_bool: {key: true value: true}");
+
+  // "null" is accepted for all fields types.
+  RunValidJsonTest(
+      "AllFieldAcceptNull",
+      R"({
+        "optionalInt32": null,
+        "optionalInt64": null,
+        "optionalUint32": null,
+        "optionalUint64": null,
+        "optionalBool": null,
+        "optionalString": null,
+        "optionalBytes": null,
+        "optionalNestedEnum": null,
+        "optionalNestedMessage": null,
+        "repeatedInt32": null,
+        "repeatedInt64": null,
+        "repeatedUint32": null,
+        "repeatedUint64": null,
+        "repeatedBool": null,
+        "repeatedString": null,
+        "repeatedBytes": null,
+        "repeatedNestedEnum": null,
+        "repeatedNestedMessage": null,
+        "mapInt32Int32": null,
+        "mapBoolBool": null,
+        "mapStringNestedMessage": null
+      })",
+      "");
+
+  // Repeated field elements cannot be null.
+  ExpectParseFailureForJson(
+      "RepeatedFieldPrimitiveElementIsNull",
+      R"({"repeatedInt32": [1, null, 2]})");
+  ExpectParseFailureForJson(
+      "RepeatedFieldMessageElementIsNull",
+      R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})");
+  // Map field keys cannot be null.
+  ExpectParseFailureForJson(
+      "MapFieldKeyIsNull",
+      R"({"mapInt32Int32": {null: 1}})");
+  // Map field values cannot be null.
+  ExpectParseFailureForJson(
+      "MapFieldValueIsNull",
+      R"({"mapInt32Int32": {"0": null}})");
+
+  // Wrapper types.
+  RunValidJsonTest(
+      "OptionalBoolWrapper",
+      R"({"optionalBoolWrapper": false})",
+      "optional_bool_wrapper: {value: false}");
+  RunValidJsonTest(
+      "OptionalInt32Wrapper",
+      R"({"optionalInt32Wrapper": 0})",
+      "optional_int32_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalUint32Wrapper",
+      R"({"optionalUint32Wrapper": 0})",
+      "optional_uint32_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalInt64Wrapper",
+      R"({"optionalInt64Wrapper": 0})",
+      "optional_int64_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalUint64Wrapper",
+      R"({"optionalUint64Wrapper": 0})",
+      "optional_uint64_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalFloatWrapper",
+      R"({"optionalFloatWrapper": 0})",
+      "optional_float_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalDoubleWrapper",
+      R"({"optionalDoubleWrapper": 0})",
+      "optional_double_wrapper: {value: 0}");
+  RunValidJsonTest(
+      "OptionalStringWrapper",
+      R"({"optionalStringWrapper": ""})",
+      R"(optional_string_wrapper: {value: ""})");
+  RunValidJsonTest(
+      "OptionalBytesWrapper",
+      R"({"optionalBytesWrapper": ""})",
+      R"(optional_bytes_wrapper: {value: ""})");
+  RunValidJsonTest(
+      "OptionalWrapperTypesWithNonDefaultValue",
+      R"({
+        "optionalBoolWrapper": true,
+        "optionalInt32Wrapper": 1,
+        "optionalUint32Wrapper": 1,
+        "optionalInt64Wrapper": "1",
+        "optionalUint64Wrapper": "1",
+        "optionalFloatWrapper": 1,
+        "optionalDoubleWrapper": 1,
+        "optionalStringWrapper": "1",
+        "optionalBytesWrapper": "AQI="
+      })",
+      R"(
+        optional_bool_wrapper: {value: true}
+        optional_int32_wrapper: {value: 1}
+        optional_uint32_wrapper: {value: 1}
+        optional_int64_wrapper: {value: 1}
+        optional_uint64_wrapper: {value: 1}
+        optional_float_wrapper: {value: 1}
+        optional_double_wrapper: {value: 1}
+        optional_string_wrapper: {value: "1"}
+        optional_bytes_wrapper: {value: "\x01\x02"}
+      )");
+  RunValidJsonTest(
+      "RepeatedBoolWrapper",
+      R"({"repeatedBoolWrapper": [true, false]})",
+      "repeated_bool_wrapper: {value: true}"
+      "repeated_bool_wrapper: {value: false}");
+  RunValidJsonTest(
+      "RepeatedInt32Wrapper",
+      R"({"repeatedInt32Wrapper": [0, 1]})",
+      "repeated_int32_wrapper: {value: 0}"
+      "repeated_int32_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedUint32Wrapper",
+      R"({"repeatedUint32Wrapper": [0, 1]})",
+      "repeated_uint32_wrapper: {value: 0}"
+      "repeated_uint32_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedInt64Wrapper",
+      R"({"repeatedInt64Wrapper": [0, 1]})",
+      "repeated_int64_wrapper: {value: 0}"
+      "repeated_int64_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedUint64Wrapper",
+      R"({"repeatedUint64Wrapper": [0, 1]})",
+      "repeated_uint64_wrapper: {value: 0}"
+      "repeated_uint64_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedFloatWrapper",
+      R"({"repeatedFloatWrapper": [0, 1]})",
+      "repeated_float_wrapper: {value: 0}"
+      "repeated_float_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedDoubleWrapper",
+      R"({"repeatedDoubleWrapper": [0, 1]})",
+      "repeated_double_wrapper: {value: 0}"
+      "repeated_double_wrapper: {value: 1}");
+  RunValidJsonTest(
+      "RepeatedStringWrapper",
+      R"({"repeatedStringWrapper": ["", "AQI="]})",
+      R"(
+        repeated_string_wrapper: {value: ""}
+        repeated_string_wrapper: {value: "AQI="}
+      )");
+  RunValidJsonTest(
+      "RepeatedBytesWrapper",
+      R"({"repeatedBytesWrapper": ["", "AQI="]})",
+      R"(
+        repeated_bytes_wrapper: {value: ""}
+        repeated_bytes_wrapper: {value: "\x01\x02"}
+      )");
+  RunValidJsonTest(
+      "WrapperTypesWithNullValue",
+      R"({
+        "optionalBoolWrapper": null,
+        "optionalInt32Wrapper": null,
+        "optionalUint32Wrapper": null,
+        "optionalInt64Wrapper": null,
+        "optionalUint64Wrapper": null,
+        "optionalFloatWrapper": null,
+        "optionalDoubleWrapper": null,
+        "optionalStringWrapper": null,
+        "optionalBytesWrapper": null,
+        "repeatedBoolWrapper": null,
+        "repeatedInt32Wrapper": null,
+        "repeatedUint32Wrapper": null,
+        "repeatedInt64Wrapper": null,
+        "repeatedUint64Wrapper": null,
+        "repeatedFloatWrapper": null,
+        "repeatedDoubleWrapper": null,
+        "repeatedStringWrapper": null,
+        "repeatedBytesWrapper": null
+      })",
+      "");
+
+  // Duration
+  RunValidJsonTest(
+      "DurationMinValue",
+      R"({"optionalDuration": "-315576000000.999999999s"})",
+      "optional_duration: {seconds: -315576000000 nanos: -999999999}");
+  RunValidJsonTest(
+      "DurationMaxValue",
+      R"({"optionalDuration": "315576000000.999999999s"})",
+      "optional_duration: {seconds: 315576000000 nanos: 999999999}");
+  RunValidJsonTest(
+      "DurationRepeatedValue",
+      R"({"repeatedDuration": ["1.5s", "-1.5s"]})",
+      "repeated_duration: {seconds: 1 nanos: 500000000}"
+      "repeated_duration: {seconds: -1 nanos: -500000000}");
+
+  ExpectParseFailureForJson(
+      "DurationMissingS",
+      R"({"optionalDuration": "1"})");
+  ExpectParseFailureForJson(
+      "DurationJsonInputTooSmall",
+      R"({"optionalDuration": "-315576000001.000000000s"})");
+  ExpectParseFailureForJson(
+      "DurationJsonInputTooLarge",
+      R"({"optionalDuration": "315576000001.000000000s"})");
+  ExpectSerializeFailureForJson(
+      "DurationProtoInputTooSmall",
+      "optional_duration: {seconds: -315576000001 nanos: 0}");
+  ExpectSerializeFailureForJson(
+      "DurationProtoInputTooLarge",
+      "optional_duration: {seconds: 315576000001 nanos: 0}");
+
+  RunValidJsonTestWithValidator(
+      "DurationHasZeroFractionalDigit",
+      R"({"optionalDuration": "1.000000000s"})",
+      [](const Json::Value& value) {
+        return value["optionalDuration"].asString() == "1s";
+      });
+  RunValidJsonTestWithValidator(
+      "DurationHas3FractionalDigits",
+      R"({"optionalDuration": "1.010000000s"})",
+      [](const Json::Value& value) {
+        return value["optionalDuration"].asString() == "1.010s";
+      });
+  RunValidJsonTestWithValidator(
+      "DurationHas6FractionalDigits",
+      R"({"optionalDuration": "1.000010000s"})",
+      [](const Json::Value& value) {
+        return value["optionalDuration"].asString() == "1.000010s";
+      });
+  RunValidJsonTestWithValidator(
+      "DurationHas9FractionalDigits",
+      R"({"optionalDuration": "1.000000010s"})",
+      [](const Json::Value& value) {
+        return value["optionalDuration"].asString() == "1.000000010s";
+      });
+
+  // Timestamp
+  RunValidJsonTest(
+      "TimestampMinValue",
+      R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})",
+      "optional_timestamp: {seconds: -62135596800}");
+  RunValidJsonTest(
+      "TimestampMaxValue",
+      R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})",
+      "optional_timestamp: {seconds: 253402300799 nanos: 999999999}");
+  RunValidJsonTest(
+      "TimestampRepeatedValue",
+      R"({
+        "repeatedTimestamp": [
+          "0001-01-01T00:00:00Z",
+          "9999-12-31T23:59:59.999999999Z"
+        ]
+      })",
+      "repeated_timestamp: {seconds: -62135596800}"
+      "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}");
+  RunValidJsonTest(
+      "TimestampWithPositiveOffset",
+      R"({"optionalTimestamp": "1970-01-01T08:00:00+08:00"})",
+      "optional_timestamp: {seconds: 0}");
+  RunValidJsonTest(
+      "TimestampWithNegativeOffset",
+      R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
+      "optional_timestamp: {seconds: 0}");
+
+  ExpectParseFailureForJson(
+      "TimestampJsonInputTooSmall",
+      R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})");
+  ExpectParseFailureForJson(
+      "TimestampJsonInputTooLarge",
+      R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})");
+  ExpectParseFailureForJson(
+      "TimestampJsonInputMissingZ",
+      R"({"optionalTimestamp": "0001-01-01T00:00:00"})");
+  ExpectParseFailureForJson(
+      "TimestampJsonInputMissingT",
+      R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})");
+  ExpectParseFailureForJson(
+      "TimestampJsonInputLowercaseZ",
+      R"({"optionalTimestamp": "0001-01-01T00:00:00z"})");
+  ExpectParseFailureForJson(
+      "TimestampJsonInputLowercaseT",
+      R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})");
+  ExpectSerializeFailureForJson(
+      "TimestampProtoInputTooSmall",
+      "optional_timestamp: {seconds: -62135596801}");
+  ExpectSerializeFailureForJson(
+      "TimestampProtoInputTooLarge",
+      "optional_timestamp: {seconds: 253402300800}");
+  RunValidJsonTestWithValidator(
+      "TimestampZeroNormalized",
+      R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
+      [](const Json::Value& value) {
+        return value["optionalTimestamp"].asString() ==
+            "1970-01-01T00:00:00Z";
+      });
+  RunValidJsonTestWithValidator(
+      "TimestampHasZeroFractionalDigit",
+      R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})",
+      [](const Json::Value& value) {
+        return value["optionalTimestamp"].asString() ==
+            "1970-01-01T00:00:00Z";
+      });
+  RunValidJsonTestWithValidator(
+      "TimestampHas3FractionalDigits",
+      R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})",
+      [](const Json::Value& value) {
+        return value["optionalTimestamp"].asString() ==
+            "1970-01-01T00:00:00.010Z";
+      });
+  RunValidJsonTestWithValidator(
+      "TimestampHas6FractionalDigits",
+      R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})",
+      [](const Json::Value& value) {
+        return value["optionalTimestamp"].asString() ==
+            "1970-01-01T00:00:00.000010Z";
+      });
+  RunValidJsonTestWithValidator(
+      "TimestampHas9FractionalDigits",
+      R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})",
+      [](const Json::Value& value) {
+        return value["optionalTimestamp"].asString() ==
+            "1970-01-01T00:00:00.000000010Z";
+      });
+
+  // FieldMask
+  RunValidJsonTest(
+      "FieldMask",
+      R"({"optionalFieldMask": "foo,barBaz"})",
+      R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})");
+  ExpectParseFailureForJson(
+      "FieldMaskInvalidCharacter",
+      R"({"optionalFieldMask": "foo,bar_bar"})");
+  ExpectSerializeFailureForJson(
+      "FieldMaskPathsDontRoundTrip",
+      R"(optional_field_mask: {paths: "fooBar"})");
+  ExpectSerializeFailureForJson(
+      "FieldMaskNumbersDontRoundTrip",
+      R"(optional_field_mask: {paths: "foo_3_bar"})");
+  ExpectSerializeFailureForJson(
+      "FieldMaskTooManyUnderscore",
+      R"(optional_field_mask: {paths: "foo__bar"})");
+
+  // Struct
+  RunValidJsonTest(
+      "Struct",
+      R"({
+        "optionalStruct": {
+          "nullValue": null,
+          "intValue": 1234,
+          "boolValue": true,
+          "doubleValue": 1234.5678,
+          "stringValue": "Hello world!",
+          "listValue": [1234, "5678"],
+          "objectValue": {
+            "value": 0
+          }
+        }
+      })",
+      R"(
+        optional_struct: {
+          fields: {
+            key: "nullValue"
+            value: {null_value: NULL_VALUE}
+          }
+          fields: {
+            key: "intValue"
+            value: {number_value: 1234}
+          }
+          fields: {
+            key: "boolValue"
+            value: {bool_value: true}
+          }
+          fields: {
+            key: "doubleValue"
+            value: {number_value: 1234.5678}
+          }
+          fields: {
+            key: "stringValue"
+            value: {string_value: "Hello world!"}
+          }
+          fields: {
+            key: "listValue"
+            value: {
+              list_value: {
+                values: {
+                  number_value: 1234
+                }
+                values: {
+                  string_value: "5678"
+                }
+              }
+            }
+          }
+          fields: {
+            key: "objectValue"
+            value: {
+              struct_value: {
+                fields: {
+                  key: "value"
+                  value: {
+                    number_value: 0
+                  }
+                }
+              }
+            }
+          }
+        }
+      )");
+  // Value
+  RunValidJsonTest(
+      "ValueAcceptInteger",
+      R"({"optionalValue": 1})",
+      "optional_value: { number_value: 1}");
+  RunValidJsonTest(
+      "ValueAcceptFloat",
+      R"({"optionalValue": 1.5})",
+      "optional_value: { number_value: 1.5}");
+  RunValidJsonTest(
+      "ValueAcceptBool",
+      R"({"optionalValue": false})",
+      "optional_value: { bool_value: false}");
+  RunValidJsonTest(
+      "ValueAcceptNull",
+      R"({"optionalValue": null})",
+      "optional_value: { null_value: NULL_VALUE}");
+  RunValidJsonTest(
+      "ValueAcceptString",
+      R"({"optionalValue": "hello"})",
+      R"(optional_value: { string_value: "hello"})");
+  RunValidJsonTest(
+      "ValueAcceptList",
+      R"({"optionalValue": [0, "hello"]})",
+      R"(
+        optional_value: {
+          list_value: {
+            values: {
+              number_value: 0
+            }
+            values: {
+              string_value: "hello"
+            }
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "ValueAcceptObject",
+      R"({"optionalValue": {"value": 1}})",
+      R"(
+        optional_value: {
+          struct_value: {
+            fields: {
+              key: "value"
+              value: {
+                number_value: 1
+              }
+            }
+          }
+        }
+      )");
+
+  // Any
+  RunValidJsonTest(
+      "Any",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/conformance.TestAllTypes",
+          "optionalInt32": 12345
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/conformance.TestAllTypes] {
+            optional_int32: 12345
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyNested",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Any",
+          "value": {
+            "@type": "type.googleapis.com/conformance.TestAllTypes",
+            "optionalInt32": 12345
+          }
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Any] {
+            [type.googleapis.com/conformance.TestAllTypes] {
+              optional_int32: 12345
+            }
+          }
+        }
+      )");
+  // The special "@type" tag is not required to appear first.
+  RunValidJsonTest(
+      "AnyUnorderedTypeTag",
+      R"({
+        "optionalAny": {
+          "optionalInt32": 12345,
+          "@type": "type.googleapis.com/conformance.TestAllTypes"
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/conformance.TestAllTypes] {
+            optional_int32: 12345
+          }
+        }
+      )");
+  // Well-known types in Any.
+  RunValidJsonTest(
+      "AnyWithInt32ValueWrapper",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Int32Value",
+          "value": 12345
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Int32Value] {
+            value: 12345
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithDuration",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Duration",
+          "value": "1.5s"
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Duration] {
+            seconds: 1
+            nanos: 500000000
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithTimestamp",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Timestamp",
+          "value": "1970-01-01T00:00:00Z"
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Timestamp] {
+            seconds: 0
+            nanos: 0
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithFieldMask",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.FieldMask",
+          "value": "foo,barBaz"
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.FieldMask] {
+            paths: ["foo", "bar_baz"]
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithStruct",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Struct",
+          "value": {
+            "foo": 1
+          }
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Struct] {
+            fields: {
+              key: "foo"
+              value: {
+                number_value: 1
+              }
+            }
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithValueForJsonObject",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Value",
+          "value": {
+            "foo": 1
+          }
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Value] {
+            struct_value: {
+              fields: {
+                key: "foo"
+                value: {
+                  number_value: 1
+                }
+              }
+            }
+          }
+        }
+      )");
+  RunValidJsonTest(
+      "AnyWithValueForInteger",
+      R"({
+        "optionalAny": {
+          "@type": "type.googleapis.com/google.protobuf.Value",
+          "value": 1
+        }
+      })",
+      R"(
+        optional_any: {
+          [type.googleapis.com/google.protobuf.Value] {
+            number_value: 1
+          }
+        }
+      )");
+
+  bool ok = true;
+  if (!CheckSetEmpty(expected_to_fail_,
+                     "These tests were listed in the failure list, but they "
+                     "don't exist.  Remove them from the failure list")) {
+    ok = false;
+  }
+  if (!CheckSetEmpty(unexpected_failing_tests_,
+                     "These tests failed.  If they can't be fixed right now, "
+                     "you can add them to the failure list so the overall "
+                     "suite can succeed")) {
+    ok = false;
+  }
+
+  // Sometimes the testee may be fixed before we update the failure list (e.g.,
+  // the testee is from a different component). We warn about this case but
+  // don't consider it an overall test failure.
+  CheckSetEmpty(unexpected_succeeding_tests_,
+                "These tests succeeded, even though they were listed in "
+                "the failure list.  Remove them from the failure list");
+
+  if (verbose_) {
+    CheckSetEmpty(skipped_,
+                  "These tests were skipped (probably because support for some "
+                  "features is not implemented)");
+  }
+
+  StringAppendF(&output_,
+                "CONFORMANCE SUITE %s: %d successes, %d skipped, "
+                "%d expected failures, %d unexpected failures.\n",
+                ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
+                expected_failures_, unexpected_failing_tests_.size());
+  StringAppendF(&output_, "\n");
+
+  output->assign(output_);
+
+  return ok;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/conformance/conformance_test.h b/src/third_party/protobuf-3/conformance/conformance_test.h
new file mode 100644
index 0000000..75fc97b
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_test.h
@@ -0,0 +1,178 @@
+// 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.
+
+
+// This file defines a protocol for running the conformance test suite
+// in-process.  In other words, the suite itself will run in the same process as
+// the code under test.
+//
+// For pros and cons of this approach, please see conformance.proto.
+
+#ifndef CONFORMANCE_CONFORMANCE_TEST_H
+#define CONFORMANCE_CONFORMANCE_TEST_H
+
+#include <functional>
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/wire_format_lite.h>
+
+#include "third_party/jsoncpp/json.h"
+
+namespace conformance {
+class ConformanceRequest;
+class ConformanceResponse;
+class TestAllTypes;
+}  // namespace conformance
+
+namespace google {
+namespace protobuf {
+
+class ConformanceTestRunner {
+ public:
+  virtual ~ConformanceTestRunner() {}
+
+  // Call to run a single conformance test.
+  //
+  // "input" is a serialized conformance.ConformanceRequest.
+  // "output" should be set to a serialized conformance.ConformanceResponse.
+  //
+  // If there is any error in running the test itself, set "runtime_error" in
+  // the response.
+  virtual void RunTest(const std::string& test_name,
+                       const std::string& input,
+                       std::string* output) = 0;
+};
+
+// Class representing the test suite itself.  To run it, implement your own
+// class derived from ConformanceTestRunner and then write code like:
+//
+//    class MyConformanceTestRunner : public ConformanceTestRunner {
+//     public:
+//      virtual void RunTest(...) {
+//        // INSERT YOUR FRAMEWORK-SPECIFIC CODE HERE.
+//      }
+//    };
+//
+//    int main() {
+//      MyConformanceTestRunner runner;
+//      google::protobuf::ConformanceTestSuite suite;
+//
+//      std::string output;
+//      suite.RunSuite(&runner, &output);
+//    }
+//
+class ConformanceTestSuite {
+ public:
+  ConformanceTestSuite() : verbose_(false) {}
+
+  void SetVerbose(bool verbose) { verbose_ = verbose; }
+
+  // Sets the list of tests that are expected to fail when RunSuite() is called.
+  // RunSuite() will fail unless the set of failing tests is exactly the same
+  // as this list.
+  void SetFailureList(const std::vector<std::string>& failure_list);
+
+  // Run all the conformance tests against the given test runner.
+  // Test output will be stored in "output".
+  //
+  // Returns true if the set of failing tests was exactly the same as the
+  // failure list.  If SetFailureList() was not called, returns true if all
+  // tests passed.
+  bool RunSuite(ConformanceTestRunner* runner, std::string* output);
+
+ private:
+  void ReportSuccess(const std::string& test_name);
+  void ReportFailure(const string& test_name,
+                     const conformance::ConformanceRequest& request,
+                     const conformance::ConformanceResponse& response,
+                     const char* fmt, ...);
+  void ReportSkip(const string& test_name,
+                  const conformance::ConformanceRequest& request,
+                  const conformance::ConformanceResponse& response);
+  void RunTest(const std::string& test_name,
+               const conformance::ConformanceRequest& request,
+               conformance::ConformanceResponse* response);
+  void RunValidInputTest(const string& test_name, const string& input,
+                         conformance::WireFormat input_format,
+                         const string& equivalent_text_format,
+                         conformance::WireFormat requested_output);
+  void RunValidJsonTest(const string& test_name, const string& input_json,
+                        const string& equivalent_text_format);
+  void RunValidJsonTestWithProtobufInput(const string& test_name,
+                                         const conformance::TestAllTypes& input,
+                                         const string& equivalent_text_format);
+
+  typedef std::function<bool(const Json::Value&)> Validator;
+  void RunValidJsonTestWithValidator(const string& test_name,
+                                     const string& input_json,
+                                     const Validator& validator);
+  void ExpectParseFailureForJson(const string& test_name,
+                                 const string& input_json);
+  void ExpectSerializeFailureForJson(const string& test_name,
+                                     const string& text_format);
+  void ExpectParseFailureForProto(const std::string& proto,
+                                  const std::string& test_name);
+  void ExpectHardParseFailureForProto(const std::string& proto,
+                                      const std::string& test_name);
+  void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type);
+  bool CheckSetEmpty(const set<string>& set_to_check, const char* msg);
+  ConformanceTestRunner* runner_;
+  int successes_;
+  int expected_failures_;
+  bool verbose_;
+  std::string output_;
+
+  // The set of test names that are expected to fail in this run, but haven't
+  // failed yet.
+  std::set<std::string> expected_to_fail_;
+
+  // The set of test names that have been run.  Used to ensure that there are no
+  // duplicate names in the suite.
+  std::set<std::string> test_names_;
+
+  // The set of tests that failed, but weren't expected to.
+  std::set<std::string> unexpected_failing_tests_;
+
+  // The set of tests that succeeded, but weren't expected to.
+  std::set<std::string> unexpected_succeeding_tests_;
+
+  // The set of tests that the testee opted out of;
+  std::set<std::string> skipped_;
+
+  google::protobuf::internal::scoped_ptr<google::protobuf::util::TypeResolver>
+      type_resolver_;
+  std::string type_url_;
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // CONFORMANCE_CONFORMANCE_TEST_H
diff --git a/src/third_party/protobuf-3/conformance/conformance_test_runner.cc b/src/third_party/protobuf-3/conformance/conformance_test_runner.cc
new file mode 100644
index 0000000..376a60b
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/conformance_test_runner.cc
@@ -0,0 +1,312 @@
+// 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.
+
+// This file contains a program for running the test suite in a separate
+// process.  The other alternative is to run the suite in-process.  See
+// conformance.proto for pros/cons of these two options.
+//
+// This program will fork the process under test and communicate with it over
+// its stdin/stdout:
+//
+//     +--------+   pipe   +----------+
+//     | tester | <------> | testee   |
+//     |        |          |          |
+//     |  C++   |          | any lang |
+//     +--------+          +----------+
+//
+// The tester contains all of the test cases and their expected output.
+// The testee is a simple program written in the target language that reads
+// each test case and attempts to produce acceptable output for it.
+//
+// Every test consists of a ConformanceRequest/ConformanceResponse
+// request/reply pair.  The protocol on the pipe is simply:
+//
+//   1. tester sends 4-byte length N (little endian)
+//   2. tester sends N bytes representing a ConformanceRequest proto
+//   3. testee sends 4-byte length M (little endian)
+//   4. testee sends M bytes representing a ConformanceResponse proto
+
+#include <algorithm>
+#include <errno.h>
+#include <fstream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include "conformance.pb.h"
+#include "conformance_test.h"
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using google::protobuf::internal::scoped_array;
+using google::protobuf::StringAppendF;
+using std::string;
+using std::vector;
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define CHECK_SYSCALL(call) \
+  if (call < 0) { \
+    perror(#call " " __FILE__ ":" TOSTRING(__LINE__)); \
+    exit(1); \
+  }
+
+// Test runner that spawns the process being tested and communicates with it
+// over a pipe.
+class ForkPipeRunner : public google::protobuf::ConformanceTestRunner {
+ public:
+  ForkPipeRunner(const std::string &executable)
+      : child_pid_(-1), executable_(executable) {}
+
+  virtual ~ForkPipeRunner() {}
+
+  void RunTest(const std::string& test_name,
+               const std::string& request,
+               std::string* response) {
+    if (child_pid_ < 0) {
+      SpawnTestProgram();
+    }
+
+    current_test_name_ = test_name;
+
+    uint32_t len = request.size();
+    CheckedWrite(write_fd_, &len, sizeof(uint32_t));
+    CheckedWrite(write_fd_, request.c_str(), request.size());
+
+    if (!TryRead(read_fd_, &len, sizeof(uint32_t))) {
+      // We failed to read from the child, assume a crash and try to reap.
+      GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_;
+
+      int status;
+      waitpid(child_pid_, &status, WEXITED);
+
+      string error_msg;
+      if (WIFEXITED(status)) {
+        StringAppendF(&error_msg,
+                      "child exited, status=%d", WEXITSTATUS(status));
+      } else if (WIFSIGNALED(status)) {
+        StringAppendF(&error_msg,
+                      "child killed by signal %d", WTERMSIG(status));
+      }
+      GOOGLE_LOG(INFO) << error_msg;
+      child_pid_ = -1;
+
+      conformance::ConformanceResponse response_obj;
+      response_obj.set_runtime_error(error_msg);
+      response_obj.SerializeToString(response);
+      return;
+    }
+
+    response->resize(len);
+    CheckedRead(read_fd_, (void*)response->c_str(), len);
+  }
+
+ private:
+  // TODO(haberman): make this work on Windows, instead of using these
+  // UNIX-specific APIs.
+  //
+  // There is a platform-agnostic API in
+  //    src/google/protobuf/compiler/subprocess.h
+  //
+  // However that API only supports sending a single message to the subprocess.
+  // We really want to be able to send messages and receive responses one at a
+  // time:
+  //
+  // 1. Spawning a new process for each test would take way too long for thousands
+  //    of tests and subprocesses like java that can take 100ms or more to start
+  //    up.
+  //
+  // 2. Sending all the tests in one big message and receiving all results in one
+  //    big message would take away our visibility about which test(s) caused a
+  //    crash or other fatal error.  It would also give us only a single failure
+  //    instead of all of them.
+  void SpawnTestProgram() {
+    int toproc_pipe_fd[2];
+    int fromproc_pipe_fd[2];
+    if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) {
+      perror("pipe");
+      exit(1);
+    }
+
+    pid_t pid = fork();
+    if (pid < 0) {
+      perror("fork");
+      exit(1);
+    }
+
+    if (pid) {
+      // Parent.
+      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+      write_fd_ = toproc_pipe_fd[1];
+      read_fd_ = fromproc_pipe_fd[0];
+      child_pid_ = pid;
+    } else {
+      // Child.
+      CHECK_SYSCALL(close(STDIN_FILENO));
+      CHECK_SYSCALL(close(STDOUT_FILENO));
+      CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO));
+      CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO));
+
+      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+      CHECK_SYSCALL(close(toproc_pipe_fd[1]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[0]));
+
+      scoped_array<char> executable(new char[executable_.size() + 1]);
+      memcpy(executable.get(), executable_.c_str(), executable_.size());
+      executable[executable_.size()] = '\0';
+
+      char *const argv[] = {executable.get(), NULL};
+      CHECK_SYSCALL(execv(executable.get(), argv));  // Never returns.
+    }
+  }
+
+  void CheckedWrite(int fd, const void *buf, size_t len) {
+    if (write(fd, buf, len) != len) {
+      GOOGLE_LOG(FATAL) << current_test_name_
+                        << ": error writing to test program: "
+                        << strerror(errno);
+    }
+  }
+
+  bool TryRead(int fd, void *buf, size_t len) {
+    size_t ofs = 0;
+    while (len > 0) {
+      ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+      if (bytes_read == 0) {
+        GOOGLE_LOG(ERROR) << current_test_name_
+                          << ": unexpected EOF from test program";
+        return false;
+      } else if (bytes_read < 0) {
+        GOOGLE_LOG(ERROR) << current_test_name_
+                          << ": error reading from test program: "
+                          << strerror(errno);
+        return false;
+      }
+
+      len -= bytes_read;
+      ofs += bytes_read;
+    }
+
+    return true;
+  }
+
+  void CheckedRead(int fd, void *buf, size_t len) {
+    if (!TryRead(fd, buf, len)) {
+      GOOGLE_LOG(FATAL) << current_test_name_
+                        << ": error reading from test program: "
+                        << strerror(errno);
+    }
+  }
+
+  int write_fd_;
+  int read_fd_;
+  pid_t child_pid_;
+  std::string executable_;
+  std::string current_test_name_;
+};
+
+void UsageError() {
+  fprintf(stderr,
+          "Usage: conformance-test-runner [options] <test-program>\n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr,
+          "  --failure_list <filename>   Use to specify list of tests\n");
+  fprintf(stderr,
+          "                              that are expected to fail.  File\n");
+  fprintf(stderr,
+          "                              should contain one test name per\n");
+  fprintf(stderr,
+          "                              line.  Use '#' for comments.\n");
+  exit(1);
+}
+
+void ParseFailureList(const char *filename, vector<string>* failure_list) {
+  std::ifstream infile(filename);
+
+  if (!infile.is_open()) {
+    fprintf(stderr, "Couldn't open failure list file: %s\n", filename);
+    exit(1);
+  }
+
+  for (string line; getline(infile, line);) {
+    // Remove whitespace.
+    line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
+               line.end());
+
+    // Remove comments.
+    line = line.substr(0, line.find("#"));
+
+    if (!line.empty()) {
+      failure_list->push_back(line);
+    }
+  }
+}
+
+int main(int argc, char *argv[]) {
+  char *program;
+  google::protobuf::ConformanceTestSuite suite;
+
+  vector<string> failure_list;
+
+  for (int arg = 1; arg < argc; ++arg) {
+    if (strcmp(argv[arg], "--failure_list") == 0) {
+      if (++arg == argc) UsageError();
+      ParseFailureList(argv[arg], &failure_list);
+    } else if (strcmp(argv[arg], "--verbose") == 0) {
+      suite.SetVerbose(true);
+    } else if (argv[arg][0] == '-') {
+      fprintf(stderr, "Unknown option: %s\n", argv[arg]);
+      UsageError();
+    } else {
+      if (arg != argc - 1) {
+        fprintf(stderr, "Too many arguments.\n");
+        UsageError();
+      }
+      program = argv[arg];
+    }
+  }
+
+  suite.SetFailureList(failure_list);
+  ForkPipeRunner runner(program);
+
+  std::string output;
+  bool ok = suite.RunSuite(&runner, &output);
+
+  fwrite(output.c_str(), 1, output.size(), stderr);
+
+  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/third_party/protobuf-3/conformance/failure_list_cpp.txt b/src/third_party/protobuf-3/conformance/failure_list_cpp.txt
new file mode 100644
index 0000000..2ddf831
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_cpp.txt
@@ -0,0 +1,106 @@
+# This is the list of conformance tests that are known to fail for the C++
+# implementation right now.  These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
+#
+# TODO(haberman): insert links to corresponding bugs tracking the issue.
+# Should we use GitHub issues or the Google-internal bug tracker?
+
+FieldMaskNumbersDontRoundTrip.JsonOutput
+FieldMaskPathsDontRoundTrip.JsonOutput
+FieldMaskTooManyUnderscore.JsonOutput
+JsonInput.AnyUnorderedTypeTag.JsonOutput
+JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForInteger.ProtobufOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+JsonInput.BoolFieldDoubleQuotedFalse
+JsonInput.BoolFieldDoubleQuotedTrue
+JsonInput.BoolFieldIntegerOne
+JsonInput.BoolFieldIntegerZero
+JsonInput.BytesFieldInvalidBase64Characters
+JsonInput.BytesFieldNoPadding
+JsonInput.DoubleFieldTooSmall
+JsonInput.DurationHasZeroFractionalDigit.Validator
+JsonInput.DurationJsonInputTooLarge
+JsonInput.DurationJsonInputTooSmall
+JsonInput.DurationMissingS
+JsonInput.EnumFieldUnknownValue.Validator
+JsonInput.FieldMaskInvalidCharacter
+JsonInput.FieldNameDuplicate
+JsonInput.FieldNameDuplicateDifferentCasing1
+JsonInput.FieldNameDuplicateDifferentCasing2
+JsonInput.FieldNameInLowerCamelCase.Validator
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
+JsonInput.FieldNameNotQuoted
+JsonInput.FloatFieldTooLarge
+JsonInput.FloatFieldTooSmall
+JsonInput.Int32FieldLeadingSpace
+JsonInput.Int32FieldLeadingZero
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinValue.JsonOutput
+JsonInput.Int32FieldMinValue.ProtobufOutput
+JsonInput.Int32FieldNegativeWithLeadingZero
+JsonInput.Int32FieldNotInteger
+JsonInput.Int32FieldNotNumber
+JsonInput.Int32FieldTooLarge
+JsonInput.Int32FieldTooSmall
+JsonInput.Int32FieldTrailingSpace
+JsonInput.Int64FieldNotInteger
+JsonInput.Int64FieldNotNumber
+JsonInput.Int64FieldTooLarge
+JsonInput.Int64FieldTooSmall
+JsonInput.MapFieldValueIsNull
+JsonInput.OneofFieldDuplicate
+JsonInput.RepeatedFieldMessageElementIsNull
+JsonInput.RepeatedFieldPrimitiveElementIsNull
+JsonInput.RepeatedFieldTrailingComma
+JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotMessage
+JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotString
+JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotBool
+JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
+JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotString
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotMessage
+JsonInput.StringFieldNotAString
+JsonInput.StringFieldSurrogateInWrongOrder
+JsonInput.StringFieldSurrogatePair.JsonOutput
+JsonInput.StringFieldSurrogatePair.ProtobufOutput
+JsonInput.StringFieldUnpairedHighSurrogate
+JsonInput.StringFieldUnpairedLowSurrogate
+JsonInput.StringFieldUppercaseEscapeLetter
+JsonInput.TimestampJsonInputLowercaseT
+JsonInput.TimestampJsonInputLowercaseZ
+JsonInput.TimestampJsonInputMissingT
+JsonInput.TimestampJsonInputMissingZ
+JsonInput.TimestampJsonInputTooLarge
+JsonInput.TimestampJsonInputTooSmall
+JsonInput.TrailingCommaInAnObject
+JsonInput.Uint32FieldNotInteger
+JsonInput.Uint32FieldNotNumber
+JsonInput.Uint32FieldTooLarge
+JsonInput.Uint64FieldNotInteger
+JsonInput.Uint64FieldNotNumber
+JsonInput.Uint64FieldTooLarge
+JsonInput.WrapperTypesWithNullValue.JsonOutput
+JsonInput.WrapperTypesWithNullValue.ProtobufOutput
+ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInPackedField.BOOL
+ProtobufInput.PrematureEofInPackedField.ENUM
+ProtobufInput.PrematureEofInPackedField.INT32
+ProtobufInput.PrematureEofInPackedField.INT64
+ProtobufInput.PrematureEofInPackedField.SINT32
+ProtobufInput.PrematureEofInPackedField.SINT64
+ProtobufInput.PrematureEofInPackedField.UINT32
+ProtobufInput.PrematureEofInPackedField.UINT64
+ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
+TimestampProtoInputTooLarge.JsonOutput
+TimestampProtoInputTooSmall.JsonOutput
diff --git a/src/third_party/protobuf-3/conformance/failure_list_csharp.txt b/src/third_party/protobuf-3/conformance/failure_list_csharp.txt
new file mode 100644
index 0000000..a46cee4
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_csharp.txt
@@ -0,0 +1,16 @@
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.FieldNameInLowerCamelCase.Validator
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
+JsonInput.FieldNameWithMixedCases.JsonOutput
+JsonInput.FieldNameWithMixedCases.ProtobufOutput
+JsonInput.FieldNameWithMixedCases.Validator
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinValue.JsonOutput
+JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
+JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
+JsonInput.OriginalProtoFieldName.JsonOutput
+JsonInput.StringFieldSurrogatePair.JsonOutput
+JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
+JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
diff --git a/src/third_party/protobuf-3/conformance/failure_list_java.txt b/src/third_party/protobuf-3/conformance/failure_list_java.txt
new file mode 100644
index 0000000..552c0cc
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_java.txt
@@ -0,0 +1,49 @@
+# This is the list of conformance tests that are known to fail for the Java
+# implementation right now.  These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
+
+FieldMaskNumbersDontRoundTrip.JsonOutput
+FieldMaskPathsDontRoundTrip.JsonOutput
+FieldMaskTooManyUnderscore.JsonOutput
+JsonInput.AnyWithFieldMask.ProtobufOutput
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.BoolFieldAllCapitalFalse
+JsonInput.BoolFieldAllCapitalTrue
+JsonInput.BoolFieldCamelCaseFalse
+JsonInput.BoolFieldCamelCaseTrue
+JsonInput.BoolFieldDoubleQuotedFalse
+JsonInput.BoolFieldDoubleQuotedTrue
+JsonInput.BoolMapFieldKeyNotQuoted
+JsonInput.DoubleFieldInfinityNotQuoted
+JsonInput.DoubleFieldNanNotQuoted
+JsonInput.DoubleFieldNegativeInfinityNotQuoted
+JsonInput.EnumFieldNotQuoted
+JsonInput.FieldMask.ProtobufOutput
+JsonInput.FieldMaskInvalidCharacter
+JsonInput.FieldNameDuplicate
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameNotQuoted
+JsonInput.FloatFieldInfinityNotQuoted
+JsonInput.FloatFieldNanNotQuoted
+JsonInput.FloatFieldNegativeInfinityNotQuoted
+JsonInput.Int32FieldLeadingZero
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinValue.JsonOutput
+JsonInput.Int32FieldNegativeWithLeadingZero
+JsonInput.Int32FieldPlusSign
+JsonInput.Int32MapFieldKeyNotQuoted
+JsonInput.Int64MapFieldKeyNotQuoted
+JsonInput.JsonWithComments
+JsonInput.OriginalProtoFieldName.JsonOutput
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+JsonInput.StringFieldNotAString
+JsonInput.StringFieldSurrogateInWrongOrder
+JsonInput.StringFieldUnpairedHighSurrogate
+JsonInput.StringFieldUnpairedLowSurrogate
+JsonInput.StringFieldUppercaseEscapeLetter
+JsonInput.Uint32MapFieldKeyNotQuoted
+JsonInput.Uint64MapFieldKeyNotQuoted
diff --git a/src/third_party/protobuf-3/conformance/failure_list_objc.txt b/src/third_party/protobuf-3/conformance/failure_list_objc.txt
new file mode 100644
index 0000000..5dac350
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_objc.txt
@@ -0,0 +1,4 @@
+# No tests currently failing.
+#
+# json input or output tests are skipped (in conformance_objc.m) as mobile
+# platforms don't support json wire format to avoid code bloat.
diff --git a/src/third_party/protobuf-3/conformance/failure_list_python-post26.txt b/src/third_party/protobuf-3/conformance/failure_list_python-post26.txt
new file mode 100644
index 0000000..19d99b0
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_python-post26.txt
@@ -0,0 +1,2 @@
+JsonInput.StringFieldSurrogateInWrongOrder
+JsonInput.StringFieldUnpairedHighSurrogate
diff --git a/src/third_party/protobuf-3/conformance/failure_list_python.txt b/src/third_party/protobuf-3/conformance/failure_list_python.txt
new file mode 100644
index 0000000..d2e5263
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_python.txt
@@ -0,0 +1,85 @@
+DurationProtoInputTooLarge.JsonOutput
+DurationProtoInputTooSmall.JsonOutput
+FieldMaskNumbersDontRoundTrip.JsonOutput
+FieldMaskPathsDontRoundTrip.JsonOutput
+FieldMaskTooManyUnderscore.JsonOutput
+JsonInput.Any.JsonOutput
+JsonInput.Any.ProtobufOutput
+JsonInput.AnyNested.JsonOutput
+JsonInput.AnyNested.ProtobufOutput
+JsonInput.AnyUnorderedTypeTag.JsonOutput
+JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+JsonInput.AnyWithDuration.JsonOutput
+JsonInput.AnyWithDuration.ProtobufOutput
+JsonInput.AnyWithFieldMask.JsonOutput
+JsonInput.AnyWithFieldMask.ProtobufOutput
+JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+JsonInput.AnyWithStruct.JsonOutput
+JsonInput.AnyWithStruct.ProtobufOutput
+JsonInput.AnyWithTimestamp.JsonOutput
+JsonInput.AnyWithTimestamp.ProtobufOutput
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForInteger.ProtobufOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+JsonInput.BytesFieldInvalidBase64Characters
+JsonInput.DoubleFieldInfinityNotQuoted
+JsonInput.DoubleFieldNanNotQuoted
+JsonInput.DoubleFieldNegativeInfinityNotQuoted
+JsonInput.DoubleFieldTooSmall
+JsonInput.DurationJsonInputTooLarge
+JsonInput.DurationJsonInputTooSmall
+JsonInput.DurationMissingS
+JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+JsonInput.EnumFieldNumericValueZero.JsonOutput
+JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+JsonInput.EnumFieldUnknownValue.Validator
+JsonInput.FieldMask.ProtobufOutput
+JsonInput.FieldMaskInvalidCharacter
+JsonInput.FieldNameInLowerCamelCase.Validator
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
+JsonInput.FloatFieldInfinityNotQuoted
+JsonInput.FloatFieldNanNotQuoted
+JsonInput.FloatFieldNegativeInfinityNotQuoted
+JsonInput.FloatFieldTooLarge
+JsonInput.FloatFieldTooSmall
+JsonInput.Int32FieldExponentialFormat.JsonOutput
+JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+JsonInput.Int32FieldMaxFloatValue.JsonOutput
+JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinValue.JsonOutput
+JsonInput.OriginalProtoFieldName.JsonOutput
+JsonInput.OriginalProtoFieldName.ProtobufOutput
+JsonInput.RepeatedFieldMessageElementIsNull
+JsonInput.RepeatedFieldPrimitiveElementIsNull
+JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+JsonInput.StringFieldSurrogatePair.JsonOutput
+JsonInput.StringFieldUnpairedLowSurrogate
+JsonInput.Struct.JsonOutput
+JsonInput.Struct.ProtobufOutput
+JsonInput.TimestampJsonInputLowercaseT
+JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+JsonInput.ValueAcceptBool.JsonOutput
+JsonInput.ValueAcceptBool.ProtobufOutput
+JsonInput.ValueAcceptFloat.JsonOutput
+JsonInput.ValueAcceptFloat.ProtobufOutput
+JsonInput.ValueAcceptInteger.JsonOutput
+JsonInput.ValueAcceptInteger.ProtobufOutput
+JsonInput.ValueAcceptList.JsonOutput
+JsonInput.ValueAcceptList.ProtobufOutput
+JsonInput.ValueAcceptNull.JsonOutput
+JsonInput.ValueAcceptNull.ProtobufOutput
+JsonInput.ValueAcceptObject.JsonOutput
+JsonInput.ValueAcceptObject.ProtobufOutput
+JsonInput.ValueAcceptString.JsonOutput
+JsonInput.ValueAcceptString.ProtobufOutput
+TimestampProtoInputTooLarge.JsonOutput
+TimestampProtoInputTooSmall.JsonOutput
diff --git a/src/third_party/protobuf-3/conformance/failure_list_python_cpp.txt b/src/third_party/protobuf-3/conformance/failure_list_python_cpp.txt
new file mode 100644
index 0000000..7b5e45f
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_python_cpp.txt
@@ -0,0 +1,110 @@
+# This is the list of conformance tests that are known to fail for the
+# Python/C++ implementation right now.  These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
+#
+# TODO(haberman): insert links to corresponding bugs tracking the issue.
+# Should we use GitHub issues or the Google-internal bug tracker?
+
+DurationProtoInputTooLarge.JsonOutput
+DurationProtoInputTooSmall.JsonOutput
+FieldMaskNumbersDontRoundTrip.JsonOutput
+FieldMaskPathsDontRoundTrip.JsonOutput
+FieldMaskTooManyUnderscore.JsonOutput
+JsonInput.Any.JsonOutput
+JsonInput.Any.ProtobufOutput
+JsonInput.AnyNested.JsonOutput
+JsonInput.AnyNested.ProtobufOutput
+JsonInput.AnyUnorderedTypeTag.JsonOutput
+JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+JsonInput.AnyWithDuration.JsonOutput
+JsonInput.AnyWithDuration.ProtobufOutput
+JsonInput.AnyWithFieldMask.JsonOutput
+JsonInput.AnyWithFieldMask.ProtobufOutput
+JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+JsonInput.AnyWithStruct.JsonOutput
+JsonInput.AnyWithStruct.ProtobufOutput
+JsonInput.AnyWithTimestamp.JsonOutput
+JsonInput.AnyWithTimestamp.ProtobufOutput
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForInteger.ProtobufOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+JsonInput.BytesFieldInvalidBase64Characters
+JsonInput.DoubleFieldInfinityNotQuoted
+JsonInput.DoubleFieldNanNotQuoted
+JsonInput.DoubleFieldNegativeInfinityNotQuoted
+JsonInput.DoubleFieldTooSmall
+JsonInput.DurationJsonInputTooLarge
+JsonInput.DurationJsonInputTooSmall
+JsonInput.DurationMissingS
+JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+JsonInput.EnumFieldNumericValueZero.JsonOutput
+JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+JsonInput.EnumFieldUnknownValue.Validator
+JsonInput.FieldMask.ProtobufOutput
+JsonInput.FieldMaskInvalidCharacter
+JsonInput.FieldNameInLowerCamelCase.Validator
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
+JsonInput.FloatFieldInfinityNotQuoted
+JsonInput.FloatFieldNanNotQuoted
+JsonInput.FloatFieldNegativeInfinityNotQuoted
+JsonInput.FloatFieldTooLarge
+JsonInput.FloatFieldTooSmall
+JsonInput.Int32FieldExponentialFormat.JsonOutput
+JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+JsonInput.Int32FieldMaxFloatValue.JsonOutput
+JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinValue.JsonOutput
+JsonInput.OriginalProtoFieldName.JsonOutput
+JsonInput.OriginalProtoFieldName.ProtobufOutput
+JsonInput.RepeatedFieldMessageElementIsNull
+JsonInput.RepeatedFieldPrimitiveElementIsNull
+JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+JsonInput.StringFieldSurrogatePair.JsonOutput
+JsonInput.StringFieldUnpairedLowSurrogate
+JsonInput.Struct.JsonOutput
+JsonInput.Struct.ProtobufOutput
+JsonInput.TimestampJsonInputLowercaseT
+JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+JsonInput.ValueAcceptBool.JsonOutput
+JsonInput.ValueAcceptBool.ProtobufOutput
+JsonInput.ValueAcceptFloat.JsonOutput
+JsonInput.ValueAcceptFloat.ProtobufOutput
+JsonInput.ValueAcceptInteger.JsonOutput
+JsonInput.ValueAcceptInteger.ProtobufOutput
+JsonInput.ValueAcceptList.JsonOutput
+JsonInput.ValueAcceptList.ProtobufOutput
+JsonInput.ValueAcceptNull.JsonOutput
+JsonInput.ValueAcceptNull.ProtobufOutput
+JsonInput.ValueAcceptObject.JsonOutput
+JsonInput.ValueAcceptObject.ProtobufOutput
+JsonInput.ValueAcceptString.JsonOutput
+JsonInput.ValueAcceptString.ProtobufOutput
+ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInPackedField.BOOL
+ProtobufInput.PrematureEofInPackedField.DOUBLE
+ProtobufInput.PrematureEofInPackedField.ENUM
+ProtobufInput.PrematureEofInPackedField.FIXED32
+ProtobufInput.PrematureEofInPackedField.FIXED64
+ProtobufInput.PrematureEofInPackedField.FLOAT
+ProtobufInput.PrematureEofInPackedField.INT32
+ProtobufInput.PrematureEofInPackedField.INT64
+ProtobufInput.PrematureEofInPackedField.SFIXED32
+ProtobufInput.PrematureEofInPackedField.SFIXED64
+ProtobufInput.PrematureEofInPackedField.SINT32
+ProtobufInput.PrematureEofInPackedField.SINT64
+ProtobufInput.PrematureEofInPackedField.UINT32
+ProtobufInput.PrematureEofInPackedField.UINT64
+TimestampProtoInputTooLarge.JsonOutput
+TimestampProtoInputTooSmall.JsonOutput
diff --git a/src/third_party/protobuf-3/conformance/failure_list_ruby.txt b/src/third_party/protobuf-3/conformance/failure_list_ruby.txt
new file mode 100644
index 0000000..7c12da0
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/failure_list_ruby.txt
@@ -0,0 +1,199 @@
+DurationProtoInputTooLarge.JsonOutput
+DurationProtoInputTooSmall.JsonOutput
+FieldMaskNumbersDontRoundTrip.JsonOutput
+FieldMaskPathsDontRoundTrip.JsonOutput
+FieldMaskTooManyUnderscore.JsonOutput
+JsonInput.Any.JsonOutput
+JsonInput.Any.ProtobufOutput
+JsonInput.AnyNested.JsonOutput
+JsonInput.AnyNested.ProtobufOutput
+JsonInput.AnyUnorderedTypeTag.JsonOutput
+JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+JsonInput.AnyWithDuration.JsonOutput
+JsonInput.AnyWithDuration.ProtobufOutput
+JsonInput.AnyWithFieldMask.JsonOutput
+JsonInput.AnyWithFieldMask.ProtobufOutput
+JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+JsonInput.AnyWithStruct.JsonOutput
+JsonInput.AnyWithStruct.ProtobufOutput
+JsonInput.AnyWithTimestamp.JsonOutput
+JsonInput.AnyWithTimestamp.ProtobufOutput
+JsonInput.AnyWithValueForInteger.JsonOutput
+JsonInput.AnyWithValueForInteger.ProtobufOutput
+JsonInput.AnyWithValueForJsonObject.JsonOutput
+JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+JsonInput.BoolFieldIntegerOne
+JsonInput.BoolFieldIntegerZero
+JsonInput.DoubleFieldInfinity.JsonOutput
+JsonInput.DoubleFieldInfinity.ProtobufOutput
+JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
+JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
+JsonInput.DoubleFieldMinNegativeValue.JsonOutput
+JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
+JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+JsonInput.DoubleFieldNan.JsonOutput
+JsonInput.DoubleFieldNan.ProtobufOutput
+JsonInput.DoubleFieldNegativeInfinity.JsonOutput
+JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
+JsonInput.DoubleFieldQuotedValue.JsonOutput
+JsonInput.DoubleFieldQuotedValue.ProtobufOutput
+JsonInput.DurationHas3FractionalDigits.Validator
+JsonInput.DurationHas6FractionalDigits.Validator
+JsonInput.DurationHas9FractionalDigits.Validator
+JsonInput.DurationHasZeroFractionalDigit.Validator
+JsonInput.DurationMaxValue.JsonOutput
+JsonInput.DurationMaxValue.ProtobufOutput
+JsonInput.DurationMinValue.JsonOutput
+JsonInput.DurationMinValue.ProtobufOutput
+JsonInput.DurationRepeatedValue.JsonOutput
+JsonInput.DurationRepeatedValue.ProtobufOutput
+JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+JsonInput.EnumFieldNumericValueZero.JsonOutput
+JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+JsonInput.EnumFieldUnknownValue.Validator
+JsonInput.FieldMask.JsonOutput
+JsonInput.FieldMask.ProtobufOutput
+JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameWithMixedCases.JsonOutput
+JsonInput.FieldNameWithMixedCases.ProtobufOutput
+JsonInput.FieldNameWithMixedCases.Validator
+JsonInput.FloatFieldInfinity.JsonOutput
+JsonInput.FloatFieldInfinity.ProtobufOutput
+JsonInput.FloatFieldNan.JsonOutput
+JsonInput.FloatFieldNan.ProtobufOutput
+JsonInput.FloatFieldNegativeInfinity.JsonOutput
+JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
+JsonInput.FloatFieldQuotedValue.JsonOutput
+JsonInput.FloatFieldQuotedValue.ProtobufOutput
+JsonInput.FloatFieldTooLarge
+JsonInput.FloatFieldTooSmall
+JsonInput.Int32FieldExponentialFormat.JsonOutput
+JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+JsonInput.Int32FieldMaxFloatValue.JsonOutput
+JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+JsonInput.Int32FieldMinFloatValue.JsonOutput
+JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.Int32FieldStringValue.JsonOutput
+JsonInput.Int32FieldStringValue.ProtobufOutput
+JsonInput.Int32FieldStringValueEscaped.JsonOutput
+JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
+JsonInput.Int32MapEscapedKey.JsonOutput
+JsonInput.Int32MapEscapedKey.ProtobufOutput
+JsonInput.Int32MapField.JsonOutput
+JsonInput.Int32MapField.ProtobufOutput
+JsonInput.Int64FieldBeString.Validator
+JsonInput.Int64FieldMaxValue.JsonOutput
+JsonInput.Int64FieldMaxValue.ProtobufOutput
+JsonInput.Int64FieldMinValue.JsonOutput
+JsonInput.Int64FieldMinValue.ProtobufOutput
+JsonInput.Int64MapEscapedKey.JsonOutput
+JsonInput.Int64MapEscapedKey.ProtobufOutput
+JsonInput.Int64MapField.JsonOutput
+JsonInput.Int64MapField.ProtobufOutput
+JsonInput.MessageField.JsonOutput
+JsonInput.MessageField.ProtobufOutput
+JsonInput.MessageMapField.JsonOutput
+JsonInput.MessageMapField.ProtobufOutput
+JsonInput.MessageRepeatedField.JsonOutput
+JsonInput.MessageRepeatedField.ProtobufOutput
+JsonInput.OptionalBoolWrapper.JsonOutput
+JsonInput.OptionalBoolWrapper.ProtobufOutput
+JsonInput.OptionalBytesWrapper.JsonOutput
+JsonInput.OptionalBytesWrapper.ProtobufOutput
+JsonInput.OptionalDoubleWrapper.JsonOutput
+JsonInput.OptionalDoubleWrapper.ProtobufOutput
+JsonInput.OptionalFloatWrapper.JsonOutput
+JsonInput.OptionalFloatWrapper.ProtobufOutput
+JsonInput.OptionalInt32Wrapper.JsonOutput
+JsonInput.OptionalInt32Wrapper.ProtobufOutput
+JsonInput.OptionalInt64Wrapper.JsonOutput
+JsonInput.OptionalInt64Wrapper.ProtobufOutput
+JsonInput.OptionalStringWrapper.JsonOutput
+JsonInput.OptionalStringWrapper.ProtobufOutput
+JsonInput.OptionalUint32Wrapper.JsonOutput
+JsonInput.OptionalUint32Wrapper.ProtobufOutput
+JsonInput.OptionalUint64Wrapper.JsonOutput
+JsonInput.OptionalUint64Wrapper.ProtobufOutput
+JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+JsonInput.OriginalProtoFieldName.JsonOutput
+JsonInput.PrimitiveRepeatedField.JsonOutput
+JsonInput.PrimitiveRepeatedField.ProtobufOutput
+JsonInput.RepeatedBoolWrapper.JsonOutput
+JsonInput.RepeatedBoolWrapper.ProtobufOutput
+JsonInput.RepeatedBytesWrapper.JsonOutput
+JsonInput.RepeatedBytesWrapper.ProtobufOutput
+JsonInput.RepeatedDoubleWrapper.JsonOutput
+JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+JsonInput.RepeatedFloatWrapper.JsonOutput
+JsonInput.RepeatedFloatWrapper.ProtobufOutput
+JsonInput.RepeatedInt32Wrapper.JsonOutput
+JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+JsonInput.RepeatedInt64Wrapper.JsonOutput
+JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+JsonInput.RepeatedStringWrapper.JsonOutput
+JsonInput.RepeatedStringWrapper.ProtobufOutput
+JsonInput.RepeatedUint32Wrapper.JsonOutput
+JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+JsonInput.RepeatedUint64Wrapper.JsonOutput
+JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+JsonInput.StringFieldNotAString
+JsonInput.StringFieldSurrogateInWrongOrder
+JsonInput.StringFieldSurrogatePair.JsonOutput
+JsonInput.StringFieldSurrogatePair.ProtobufOutput
+JsonInput.StringFieldUnpairedHighSurrogate
+JsonInput.StringFieldUnpairedLowSurrogate
+JsonInput.Struct.JsonOutput
+JsonInput.Struct.ProtobufOutput
+JsonInput.TimestampHas3FractionalDigits.Validator
+JsonInput.TimestampHas6FractionalDigits.Validator
+JsonInput.TimestampHas9FractionalDigits.Validator
+JsonInput.TimestampHasZeroFractionalDigit.Validator
+JsonInput.TimestampMaxValue.JsonOutput
+JsonInput.TimestampMaxValue.ProtobufOutput
+JsonInput.TimestampMinValue.JsonOutput
+JsonInput.TimestampMinValue.ProtobufOutput
+JsonInput.TimestampRepeatedValue.JsonOutput
+JsonInput.TimestampRepeatedValue.ProtobufOutput
+JsonInput.TimestampWithNegativeOffset.JsonOutput
+JsonInput.TimestampWithNegativeOffset.ProtobufOutput
+JsonInput.TimestampWithPositiveOffset.JsonOutput
+JsonInput.TimestampWithPositiveOffset.ProtobufOutput
+JsonInput.TimestampZeroNormalized.Validator
+JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+JsonInput.Uint32MapField.JsonOutput
+JsonInput.Uint32MapField.ProtobufOutput
+JsonInput.Uint64FieldBeString.Validator
+JsonInput.Uint64FieldMaxValue.JsonOutput
+JsonInput.Uint64FieldMaxValue.ProtobufOutput
+JsonInput.Uint64MapField.JsonOutput
+JsonInput.Uint64MapField.ProtobufOutput
+JsonInput.ValueAcceptBool.JsonOutput
+JsonInput.ValueAcceptBool.ProtobufOutput
+JsonInput.ValueAcceptFloat.JsonOutput
+JsonInput.ValueAcceptFloat.ProtobufOutput
+JsonInput.ValueAcceptInteger.JsonOutput
+JsonInput.ValueAcceptInteger.ProtobufOutput
+JsonInput.ValueAcceptList.JsonOutput
+JsonInput.ValueAcceptList.ProtobufOutput
+JsonInput.ValueAcceptNull.JsonOutput
+JsonInput.ValueAcceptNull.ProtobufOutput
+JsonInput.ValueAcceptObject.JsonOutput
+JsonInput.ValueAcceptObject.ProtobufOutput
+JsonInput.ValueAcceptString.JsonOutput
+JsonInput.ValueAcceptString.ProtobufOutput
+ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+TimestampProtoInputTooLarge.JsonOutput
+TimestampProtoInputTooSmall.JsonOutput
diff --git a/src/third_party/protobuf-3/conformance/third_party/jsoncpp/json.h b/src/third_party/protobuf-3/conformance/third_party/jsoncpp/json.h
new file mode 100644
index 0000000..42e7e7f
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/third_party/jsoncpp/json.h
@@ -0,0 +1,2075 @@
+/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json.h"
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_AMALGATED_H_INCLUDED
+# define JSON_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+// DO NOT EDIT. This file (and "version") is generated by CMake.
+// Run CMake configure step to update it.
+#ifndef JSON_VERSION_H_INCLUDED
+# define JSON_VERSION_H_INCLUDED
+
+# define JSONCPP_VERSION_STRING "1.6.5"
+# define JSONCPP_VERSION_MAJOR 1
+# define JSONCPP_VERSION_MINOR 6
+# define JSONCPP_VERSION_PATCH 5
+# define JSONCPP_VERSION_QUALIFIER
+# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#endif // JSON_VERSION_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER) // MSVC
+#  if _MSC_VER <= 1200 // MSVC 6
+    // Microsoft Visual Studio 6 only support conversion from __int64 to double
+    // (no conversion from unsigned __int64).
+#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
+    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+    // characters in the debug information)
+    // All projects I've ever seen with VS6 were using this globally (not bothering
+    // with pragma push/pop).
+#    pragma warning(disable : 4786)
+#  endif // MSVC 6
+
+#  if _MSC_VER >= 1500 // MSVC 2008
+    /// Indicates that the following function is deprecated.
+#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#  endif
+
+#endif // defined(_MSC_VER)
+
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
+#  endif  // GNUC version
+#endif // __clang__ || __GNUC__
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+namespace Json {
+typedef int Int;
+typedef unsigned int UInt;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif // if defined(_MSC_VER)
+typedef Int64 LargestInt;
+typedef UInt64 LargestUInt;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+} // end namespace Json
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+#define CPPTL_JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+/** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+class JSON_API Features {
+public:
+  /** \brief A configuration that allows all features and assumes all strings
+   * are UTF-8.
+   * - C & C++ comments are allowed
+   * - Root object can be any JSON value
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features all();
+
+  /** \brief A configuration that is strictly compatible with the JSON
+   * specification.
+   * - Comments are forbidden.
+   * - Root object must be either an array or an object value.
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features strictMode();
+
+  /** \brief Initialize the configuration like JsonConfig::allFeatures;
+   */
+  Features();
+
+  /// \c true if comments are allowed. Default: \c true.
+  bool allowComments_;
+
+  /// \c true if root must be either an array or an object value. Default: \c
+  /// false.
+  bool strictRoot_;
+
+  /// \c true if dropped null placeholders are allowed. Default: \c false.
+  bool allowDroppedNullPlaceholders_;
+
+  /// \c true if numeric object key are allowed. Default: \c false.
+  bool allowNumericKeys_;
+};
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_H_INCLUDED
+#define CPPTL_JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <string>
+#include <vector>
+#include <exception>
+
+#ifndef JSON_USE_CPPTL_SMALLMAP
+#include <map>
+#else
+#include <cpptl/smallmap.h>
+#endif
+#ifdef JSON_USE_CPPTL
+#include <cpptl/forwards.h>
+#endif
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+  Exception(std::string const& msg);
+  ~Exception() throw() override;
+  char const* what() const throw() override;
+protected:
+  std::string msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+  RuntimeError(std::string const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+  LogicError(std::string const& msg);
+};
+
+/// used internally
+void throwRuntimeError(std::string const& msg);
+/// used internally
+void throwLogicError(std::string const& msg);
+
+/** \brief Type of the value held by a Value object.
+ */
+enum ValueType {
+  nullValue = 0, ///< 'null' value
+  intValue,      ///< signed integer value
+  uintValue,     ///< unsigned integer value
+  realValue,     ///< double value
+  stringValue,   ///< UTF-8 string value
+  booleanValue,  ///< bool value
+  arrayValue,    ///< array value (ordered list)
+  objectValue    ///< object value (collection of name/value pairs).
+};
+
+enum CommentPlacement {
+  commentBefore = 0,      ///< a comment placed on the line before a value
+  commentAfterOnSameLine, ///< a comment just after a value on the same line
+  commentAfter, ///< a comment on the line after a value (only make sense for
+  /// root value)
+  numberOfCommentPlacement
+};
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+/** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+class JSON_API StaticString {
+public:
+  explicit StaticString(const char* czstring) : c_str_(czstring) {}
+
+  operator const char*() const { return c_str_; }
+
+  const char* c_str() const { return c_str_; }
+
+private:
+  const char* c_str_;
+};
+
+/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resized and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
+ */
+class JSON_API Value {
+  friend class ValueIteratorBase;
+public:
+  typedef std::vector<std::string> Members;
+  typedef ValueIterator iterator;
+  typedef ValueConstIterator const_iterator;
+  typedef Json::UInt UInt;
+  typedef Json::Int Int;
+#if defined(JSON_HAS_INT64)
+  typedef Json::UInt64 UInt64;
+  typedef Json::Int64 Int64;
+#endif // defined(JSON_HAS_INT64)
+  typedef Json::LargestInt LargestInt;
+  typedef Json::LargestUInt LargestUInt;
+  typedef Json::ArrayIndex ArrayIndex;
+
+  static const Value& null;  ///< We regret this reference to a global instance; prefer the simpler Value().
+  static const Value& nullRef;  ///< just a kludge for binary-compatibility; same as null
+  /// Minimum signed integer value that can be stored in a Json::Value.
+  static const LargestInt minLargestInt;
+  /// Maximum signed integer value that can be stored in a Json::Value.
+  static const LargestInt maxLargestInt;
+  /// Maximum unsigned integer value that can be stored in a Json::Value.
+  static const LargestUInt maxLargestUInt;
+
+  /// Minimum signed int value that can be stored in a Json::Value.
+  static const Int minInt;
+  /// Maximum signed int value that can be stored in a Json::Value.
+  static const Int maxInt;
+  /// Maximum unsigned int value that can be stored in a Json::Value.
+  static const UInt maxUInt;
+
+#if defined(JSON_HAS_INT64)
+  /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 minInt64;
+  /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 maxInt64;
+  /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+  static const UInt64 maxUInt64;
+#endif // defined(JSON_HAS_INT64)
+
+private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+  class CZString {
+  public:
+    enum DuplicationPolicy {
+      noDuplication = 0,
+      duplicate,
+      duplicateOnCopy
+    };
+    CZString(ArrayIndex index);
+    CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+    CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+    CZString(CZString&& other);
+#endif
+    ~CZString();
+    CZString& operator=(CZString other);
+    bool operator<(CZString const& other) const;
+    bool operator==(CZString const& other) const;
+    ArrayIndex index() const;
+    //const char* c_str() const; ///< \deprecated
+    char const* data() const;
+    unsigned length() const;
+    bool isStaticString() const;
+
+  private:
+    void swap(CZString& other);
+
+    struct StringStorage {
+      unsigned policy_: 2;
+      unsigned length_: 30; // 1GB max
+    };
+
+    char const* cstr_;  // actually, a prefixed string, unless policy is noDup
+    union {
+      ArrayIndex index_;
+      StringStorage storage_;
+    };
+  };
+
+public:
+#ifndef JSON_USE_CPPTL_SMALLMAP
+  typedef std::map<CZString, Value> ObjectValues;
+#else
+  typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#endif // ifndef JSON_USE_CPPTL_SMALLMAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+public:
+  /** \brief Create a default Value of the given type.
+
+    This is a very useful constructor.
+    To create an empty array, pass arrayValue.
+    To create an empty object, pass objectValue.
+    Another Value can then be set to this one by assignment.
+This is useful since clear() and resize() will not alter types.
+
+    Examples:
+\code
+Json::Value null_value; // null
+Json::Value arr_value(Json::arrayValue); // []
+Json::Value obj_value(Json::objectValue); // {}
+\endcode
+  */
+  Value(ValueType type = nullValue);
+  Value(Int value);
+  Value(UInt value);
+#if defined(JSON_HAS_INT64)
+  Value(Int64 value);
+  Value(UInt64 value);
+#endif // if defined(JSON_HAS_INT64)
+  Value(double value);
+  Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+  Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
+  /** \brief Constructs a value from a static string.
+
+   * Like other value string constructor but do not duplicate the string for
+   * internal storage. The given string must remain alive after the call to this
+   * constructor.
+   * \note This works only for null-terminated strings. (We cannot change the
+   *   size of this class, so we have nowhere to store the length,
+   *   which might be computed later for various operations.)
+   *
+   * Example of usage:
+   * \code
+   * static StaticString foo("some text");
+   * Json::Value aValue(foo);
+   * \endcode
+   */
+  Value(const StaticString& value);
+  Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too.
+#ifdef JSON_USE_CPPTL
+  Value(const CppTL::ConstString& value);
+#endif
+  Value(bool value);
+  /// Deep copy.
+  Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+  /// Move constructor
+  Value(Value&& other);
+#endif
+  ~Value();
+
+  /// Deep copy, then swap(other).
+  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
+  Value& operator=(Value other);
+  /// Swap everything.
+  void swap(Value& other);
+  /// Swap values but leave comments and source offsets in place.
+  void swapPayload(Value& other);
+
+  ValueType type() const;
+
+  /// Compare payload only, not comments etc.
+  bool operator<(const Value& other) const;
+  bool operator<=(const Value& other) const;
+  bool operator>=(const Value& other) const;
+  bool operator>(const Value& other) const;
+  bool operator==(const Value& other) const;
+  bool operator!=(const Value& other) const;
+  int compare(const Value& other) const;
+
+  const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+  std::string asString() const; ///< Embedded zeroes are possible.
+  /** Get raw char* of string-value.
+   *  \return false if !string. (Seg-fault if str or end are NULL.)
+   */
+  bool getString(
+      char const** begin, char const** end) const;
+#ifdef JSON_USE_CPPTL
+  CppTL::ConstString asConstString() const;
+#endif
+  Int asInt() const;
+  UInt asUInt() const;
+#if defined(JSON_HAS_INT64)
+  Int64 asInt64() const;
+  UInt64 asUInt64() const;
+#endif // if defined(JSON_HAS_INT64)
+  LargestInt asLargestInt() const;
+  LargestUInt asLargestUInt() const;
+  float asFloat() const;
+  double asDouble() const;
+  bool asBool() const;
+
+  bool isNull() const;
+  bool isBool() const;
+  bool isInt() const;
+  bool isInt64() const;
+  bool isUInt() const;
+  bool isUInt64() const;
+  bool isIntegral() const;
+  bool isDouble() const;
+  bool isNumeric() const;
+  bool isString() const;
+  bool isArray() const;
+  bool isObject() const;
+
+  bool isConvertibleTo(ValueType other) const;
+
+  /// Number of values in array or object
+  ArrayIndex size() const;
+
+  /// \brief Return true if empty array, empty object, or null;
+  /// otherwise, false.
+  bool empty() const;
+
+  /// Return isNull()
+  bool operator!() const;
+
+  /// Remove all object members and array elements.
+  /// \pre type() is arrayValue, objectValue, or nullValue
+  /// \post type() is unchanged
+  void clear();
+
+  /// Resize the array to size elements.
+  /// New elements are initialized to null.
+  /// May only be called on nullValue or arrayValue.
+  /// \pre type() is arrayValue or nullValue
+  /// \post type() is arrayValue
+  void resize(ArrayIndex size);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](ArrayIndex index);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](int index);
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](ArrayIndex index) const;
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](int index) const;
+
+  /// If the array contains at least index+1 elements, returns the element
+  /// value,
+  /// otherwise returns defaultValue.
+  Value get(ArrayIndex index, const Value& defaultValue) const;
+  /// Return true if index < size().
+  bool isValidIndex(ArrayIndex index) const;
+  /// \brief Append value to array at the end.
+  ///
+  /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+  Value& append(const Value& value);
+
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+  ///  Exceeding that will cause an exception.
+  Value& operator[](const char* key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const char* key) const;
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \param key may contain embedded nulls.
+  Value& operator[](const std::string& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  /// \param key may contain embedded nulls.
+  const Value& operator[](const std::string& key) const;
+  /** \brief Access an object value by name, create a null member if it does not
+   exist.
+
+   * If the object has no entry for that name, then the member name used to store
+   * the new entry is not duplicated.
+   * Example of use:
+   * \code
+   * Json::Value object;
+   * static const StaticString code("code");
+   * object[code] = 1234;
+   * \endcode
+   */
+  Value& operator[](const StaticString& key);
+#ifdef JSON_USE_CPPTL
+  /// Access an object value by name, create a null member if it does not exist.
+  Value& operator[](const CppTL::ConstString& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const CppTL::ConstString& key) const;
+#endif
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const char* key, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \note key may contain embedded nulls.
+  Value get(const char* begin, const char* end, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \param key may contain embedded nulls.
+  Value get(const std::string& key, const Value& defaultValue) const;
+#ifdef JSON_USE_CPPTL
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
+#endif
+  /// Most general and efficient version of isMember()const, get()const,
+  /// and operator[]const
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  Value const* find(char const* begin, char const* end) const;
+  /// Most general and efficient version of object-mutators.
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+  Value const* demand(char const* begin, char const* end);
+  /// \brief Remove and return the named member.
+  ///
+  /// Do nothing if it did not exist.
+  /// \return the removed Value, or null.
+  /// \pre type() is objectValue or nullValue
+  /// \post type() is unchanged
+  /// \deprecated
+  Value removeMember(const char* key);
+  /// Same as removeMember(const char*)
+  /// \param key may contain embedded nulls.
+  /// \deprecated
+  Value removeMember(const std::string& key);
+  /// Same as removeMember(const char* begin, const char* end, Value* removed),
+  /// but 'key' is null-terminated.
+  bool removeMember(const char* key, Value* removed);
+  /** \brief Remove the named map member.
+
+      Update 'removed' iff removed.
+      \param key may contain embedded nulls.
+      \return true iff removed (no exceptions)
+  */
+  bool removeMember(std::string const& key, Value* removed);
+  /// Same as removeMember(std::string const& key, Value* removed)
+  bool removeMember(const char* begin, const char* end, Value* removed);
+  /** \brief Remove the indexed array element.
+
+      O(n) expensive operations.
+      Update 'removed' iff removed.
+      \return true iff removed (no exceptions)
+  */
+  bool removeIndex(ArrayIndex i, Value* removed);
+
+  /// Return true if the object has a member named key.
+  /// \note 'key' must be null-terminated.
+  bool isMember(const char* key) const;
+  /// Return true if the object has a member named key.
+  /// \param key may contain embedded nulls.
+  bool isMember(const std::string& key) const;
+  /// Same as isMember(std::string const& key)const
+  bool isMember(const char* begin, const char* end) const;
+#ifdef JSON_USE_CPPTL
+  /// Return true if the object has a member named key.
+  bool isMember(const CppTL::ConstString& key) const;
+#endif
+
+  /// \brief Return a list of the member names.
+  ///
+  /// If null, return an empty list.
+  /// \pre type() is objectValue or nullValue
+  /// \post if type() was nullValue, it remains nullValue
+  Members getMemberNames() const;
+
+  //# ifdef JSON_USE_CPPTL
+  //      EnumMemberNames enumMemberNames() const;
+  //      EnumValues enumValues() const;
+  //# endif
+
+  /// \deprecated Always pass len.
+  JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.")
+  void setComment(const char* comment, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const char* comment, size_t len, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const std::string& comment, CommentPlacement placement);
+  bool hasComment(CommentPlacement placement) const;
+  /// Include delimiters and embedded newlines.
+  std::string getComment(CommentPlacement placement) const;
+
+  std::string toStyledString() const;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  iterator begin();
+  iterator end();
+
+  // Accessors for the [start, limit) range of bytes within the JSON text from
+  // which this value was parsed, if any.
+  void setOffsetStart(size_t start);
+  void setOffsetLimit(size_t limit);
+  size_t getOffsetStart() const;
+  size_t getOffsetLimit() const;
+
+private:
+  void initBasic(ValueType type, bool allocated = false);
+
+  Value& resolveReference(const char* key);
+  Value& resolveReference(const char* key, const char* end);
+
+  struct CommentInfo {
+    CommentInfo();
+    ~CommentInfo();
+
+    void setComment(const char* text, size_t len);
+
+    char* comment_;
+  };
+
+  // struct MemberNamesTransform
+  //{
+  //   typedef const char *result_type;
+  //   const char *operator()( const CZString &name ) const
+  //   {
+  //      return name.c_str();
+  //   }
+  //};
+
+  union ValueHolder {
+    LargestInt int_;
+    LargestUInt uint_;
+    double real_;
+    bool bool_;
+    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
+    ObjectValues* map_;
+  } value_;
+  ValueType type_ : 8;
+  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+                               // If not allocated_, string_ must be null-terminated.
+  CommentInfo* comments_;
+
+  // [start, limit) byte offsets in the source JSON text from which this Value
+  // was extracted.
+  size_t start_;
+  size_t limit_;
+};
+
+/** \brief Experimental and untested: represents an element of the "path" to
+ * access a node.
+ */
+class JSON_API PathArgument {
+public:
+  friend class Path;
+
+  PathArgument();
+  PathArgument(ArrayIndex index);
+  PathArgument(const char* key);
+  PathArgument(const std::string& key);
+
+private:
+  enum Kind {
+    kindNone = 0,
+    kindIndex,
+    kindKey
+  };
+  std::string key_;
+  ArrayIndex index_;
+  Kind kind_;
+};
+
+/** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+class JSON_API Path {
+public:
+  Path(const std::string& path,
+       const PathArgument& a1 = PathArgument(),
+       const PathArgument& a2 = PathArgument(),
+       const PathArgument& a3 = PathArgument(),
+       const PathArgument& a4 = PathArgument(),
+       const PathArgument& a5 = PathArgument());
+
+  const Value& resolve(const Value& root) const;
+  Value resolve(const Value& root, const Value& defaultValue) const;
+  /// Creates the "path" to access the specified node and returns a reference on
+  /// the node.
+  Value& make(Value& root) const;
+
+private:
+  typedef std::vector<const PathArgument*> InArgs;
+  typedef std::vector<PathArgument> Args;
+
+  void makePath(const std::string& path, const InArgs& in);
+  void addPathInArg(const std::string& path,
+                    const InArgs& in,
+                    InArgs::const_iterator& itInArg,
+                    PathArgument::Kind kind);
+  void invalidPath(const std::string& path, int location);
+
+  Args args_;
+};
+
+/** \brief base class for Value iterators.
+ *
+ */
+class JSON_API ValueIteratorBase {
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef ValueIteratorBase SelfType;
+
+  bool operator==(const SelfType& other) const { return isEqual(other); }
+
+  bool operator!=(const SelfType& other) const { return !isEqual(other); }
+
+  difference_type operator-(const SelfType& other) const {
+    return other.computeDistance(*this);
+  }
+
+  /// Return either the index or the member name of the referenced value as a
+  /// Value.
+  Value key() const;
+
+  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+  UInt index() const;
+
+  /// Return the member name of the referenced Value, or "" if it is not an
+  /// objectValue.
+  /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+  std::string name() const;
+
+  /// Return the member name of the referenced Value. "" if it is not an
+  /// objectValue.
+  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  JSONCPP_DEPRECATED("Use `key = name();` instead.")
+  char const* memberName() const;
+  /// Return the member name of the referenced Value, or NULL if it is not an
+  /// objectValue.
+  /// \note Better version than memberName(). Allows embedded nulls.
+  char const* memberName(char const** end) const;
+
+protected:
+  Value& deref() const;
+
+  void increment();
+
+  void decrement();
+
+  difference_type computeDistance(const SelfType& other) const;
+
+  bool isEqual(const SelfType& other) const;
+
+  void copy(const SelfType& other);
+
+private:
+  Value::ObjectValues::iterator current_;
+  // Indicates that iterator is for a null value.
+  bool isNull_;
+
+public:
+  // For some reason, BORLAND needs these at the end, rather
+  // than earlier. No idea why.
+  ValueIteratorBase();
+  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
+};
+
+/** \brief const iterator for object and array value.
+ *
+ */
+class JSON_API ValueConstIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef const Value value_type;
+  //typedef unsigned int size_t;
+  //typedef int difference_type;
+  typedef const Value& reference;
+  typedef const Value* pointer;
+  typedef ValueConstIterator SelfType;
+
+  ValueConstIterator();
+  ValueConstIterator(ValueIterator const& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const ValueIteratorBase& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+/** \brief Iterator for object and array value.
+ */
+class JSON_API ValueIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef Value value_type;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef Value& reference;
+  typedef Value* pointer;
+  typedef ValueIterator SelfType;
+
+  ValueIterator();
+  explicit ValueIterator(const ValueConstIterator& other);
+  ValueIterator(const ValueIterator& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const SelfType& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+} // namespace Json
+
+
+namespace std {
+/// Specialize std::swap() for Json::Value.
+template<>
+inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
+}
+
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+#define CPPTL_JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "features.h"
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <deque>
+#include <iosfwd>
+#include <stack>
+#include <string>
+#include <istream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
+ *Value.
+ *
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+class JSON_API Reader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+
+  /** \brief An error tagged with where in the JSON text it was encountered.
+   *
+   * The offsets give the [start, limit) range of bytes within the text. Note
+   * that this is bytes, not codepoints.
+   *
+   */
+  struct StructuredError {
+    size_t offset_start;
+    size_t offset_limit;
+    std::string message;
+  };
+
+  /** \brief Constructs a Reader allowing all features
+   * for parsing.
+   */
+  Reader();
+
+  /** \brief Constructs a Reader allowing the specified feature set
+   * for parsing.
+   */
+  Reader(const Features& features);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   * document.
+   * \param document UTF-8 encoded string containing the document to read.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   * back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   * Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   * error occurred.
+   */
+  bool
+  parse(const std::string& document, Value& root, bool collectComments = true);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *               Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+
+  /// \brief Parse from input stream.
+  /// \see Json::operator>>(std::istream&, Json::Value&).
+  bool parse(std::istream& is, Value& root, bool collectComments = true);
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+   */
+  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+  std::string getFormatedErrorMessages() const;
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   */
+  std::string getFormattedErrorMessages() const;
+
+  /** \brief Returns a vector of structured erros encounted while parsing.
+   * \return A (possibly empty) vector of StructuredError objects. Currently
+   *         only one error can be returned, but the caller should tolerate
+   * multiple
+   *         errors.  This can occur if the parser recovers from a non-fatal
+   *         parse error and then encounters additional errors.
+   */
+  std::vector<StructuredError> getStructuredErrors() const;
+
+  /** \brief Add a semantic error message.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \return \c true if the error was successfully added, \c false if the
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const std::string& message);
+
+  /** \brief Add a semantic error message with extra context.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \param extra Additional JSON Value location to contextualize the error
+   * \return \c true if the error was successfully added, \c false if either
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const std::string& message, const Value& extra);
+
+  /** \brief Return whether there are any errors.
+   * \return \c true if there are no errors to report \c false if
+   * errors have occurred.
+   */
+  bool good() const;
+
+private:
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    std::string message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  void readNumber();
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, std::string& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const std::string& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const std::string& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  std::string getLocationLineAndColumn(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  std::string document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  std::string commentsBefore_;
+  Features features_;
+  bool collectComments_;
+};  // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+  virtual ~CharReader() {}
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * The document must be a UTF-8 encoded string containing the document to read.
+   *
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *        Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param errs [out] Formatted error messages (if not NULL)
+   *        a user friendly string that lists errors in the parsed
+   * document.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  virtual bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, std::string* errs) = 0;
+
+  class JSON_API Factory {
+  public:
+    virtual ~Factory() {}
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual CharReader* newCharReader() const = 0;
+  };  // Factory
+};  // CharReader
+
+/** \brief Build a CharReader implementation.
+
+Usage:
+\code
+  using namespace Json;
+  CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  Value value;
+  std::string errs;
+  bool ok = parseFromStream(builder, std::cin, &value, &errs);
+\endcode
+*/
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    These are case-sensitive.
+    Available settings (case-sensitive):
+    - `"collectComments": false or true`
+      - true to collect comment and allow writing them
+        back during serialization, false to discard comments.
+        This parameter is ignored if allowComments is false.
+    - `"allowComments": false or true`
+      - true if comments are allowed.
+    - `"strictRoot": false or true`
+      - true if root must be either an array or an object value
+    - `"allowDroppedNullPlaceholders": false or true`
+      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
+    - `"allowNumericKeys": false or true`
+      - true if numeric object keys are allowed.
+    - `"allowSingleQuotes": false or true`
+      - true if '' are allowed for strings (both keys and values)
+    - `"stackLimit": integer`
+      - Exceeding stackLimit (recursive depth of `readValue()`) will
+        cause an exception.
+      - This is a security issue (seg-faults caused by deeply nested JSON),
+        so the default is low.
+    - `"failIfExtra": false or true`
+      - If true, `parse()` returns false when extra non-whitespace trails
+        the JSON value in the input string.
+    - `"rejectDupKeys": false or true`
+      - If true, `parse()` returns false when a key is duplicated within an object.
+    - `"allowSpecialFloats": false or true`
+      - If true, special float values (NaNs and infinities) are allowed 
+        and their values are lossfree restorable.
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  CharReaderBuilder();
+  ~CharReaderBuilder() override;
+
+  CharReader* newCharReader() const override;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](std::string key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+  /** Same as old Features::strictMode().
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+   */
+  static void strictMode(Json::Value* settings);
+};
+
+/** Consume entire stream and use its begin/end.
+  * Someday we might have a real StreamReader, but for now this
+  * is convenient.
+  */
+bool JSON_API parseFromStream(
+    CharReader::Factory const&,
+    std::istream&,
+    Value* root, std::string* errs);
+
+/** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+     "file": {
+     // The input stream JSON would be nested here.
+     }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+*/
+JSON_API std::istream& operator>>(std::istream&, Value&);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+#define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <vector>
+#include <string>
+#include <ostream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+class Value;
+
+/**
+
+Usage:
+\code
+  using namespace Json;
+  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
+    std::unique_ptr<StreamWriter> const writer(
+      factory.newStreamWriter());
+    writer->write(value, &std::cout);
+    std::cout << std::endl;  // add lf and flush
+  }
+\endcode
+*/
+class JSON_API StreamWriter {
+protected:
+  std::ostream* sout_;  // not owned; will not delete
+public:
+  StreamWriter();
+  virtual ~StreamWriter();
+  /** Write Value into document as configured in sub-class.
+      Do not take ownership of sout, but maintain a reference during function.
+      \pre sout != NULL
+      \return zero on success (For now, we always return zero, so check the stream instead.)
+      \throw std::exception possibly, depending on configuration
+   */
+  virtual int write(Value const& root, std::ostream* sout) = 0;
+
+  /** \brief A simple abstract factory.
+   */
+  class JSON_API Factory {
+  public:
+    virtual ~Factory();
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual StreamWriter* newStreamWriter() const = 0;
+  };  // Factory
+};  // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+
+
+/** \brief Build a StreamWriter implementation.
+
+Usage:
+\code
+  using namespace Json;
+  Value value = ...;
+  StreamWriterBuilder builder;
+  builder["commentStyle"] = "None";
+  builder["indentation"] = "   ";  // or whatever you like
+  std::unique_ptr<Json::StreamWriter> writer(
+      builder.newStreamWriter());
+  writer->write(value, &std::cout);
+  std::cout << std::endl;  // add lf and flush
+\endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    Available settings (case-sensitive):
+    - "commentStyle": "None" or "All"
+    - "indentation":  "<anything>"
+    - "enableYAMLCompatibility": false or true
+      - slightly change the whitespace around colons
+    - "dropNullPlaceholders": false or true
+      - Drop the "null" string from the writer's output for nullValues.
+        Strictly speaking, this is not valid JSON. But when the output is being
+        fed to a browser's Javascript, it makes for smaller output and the
+        browser can handle the output just fine.
+    - "useSpecialFloats": false or true
+      - If true, outputs non-finite floating point values in the following way:
+        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+        as "-Infinity".
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  StreamWriterBuilder();
+  ~StreamWriterBuilder() override;
+
+  /**
+   * \throw std::exception if something goes wrong (e.g. invalid settings)
+   */
+  StreamWriter* newStreamWriter() const override;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](std::string key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+};
+
+/** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ */
+class JSON_API Writer {
+public:
+  virtual ~Writer();
+
+  virtual std::string write(const Value& root) = 0;
+};
+
+/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
+ *without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human'
+ *consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API FastWriter : public Writer {
+
+public:
+  FastWriter();
+  ~FastWriter() override {}
+
+  void enableYAMLCompatibility();
+
+  /** \brief Drop the "null" string from the writer's output for nullValues.
+   * Strictly speaking, this is not valid JSON. But when the output is being
+   * fed to a browser's Javascript, it makes for smaller output and the
+   * browser can handle the output just fine.
+   */
+  void dropNullPlaceholders();
+
+  void omitEndingLineFeed();
+
+public: // overridden from Writer
+  std::string write(const Value& root) override;
+
+private:
+  void writeValue(const Value& value);
+
+  std::string document_;
+  bool yamlCompatiblityEnabled_;
+  bool dropNullPlaceholders_;
+  bool omitEndingLineFeed_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ *human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ *line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ *types,
+ *       and all the values fit on one lines, then print the array on a single
+ *line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ *#CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledWriter : public Writer {
+public:
+  StyledWriter();
+  ~StyledWriter() override {}
+
+public: // overridden from Writer
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param root Value to serialize.
+   * \return String containing the JSON document that represents the root value.
+   */
+  std::string write(const Value& root) override;
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const std::string& value);
+  void writeIndent();
+  void writeWithIndent(const std::string& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static std::string normalizeEOL(const std::string& text);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::string document_;
+  std::string indentString_;
+  int rightMargin_;
+  int indentSize_;
+  bool addChildValues_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ human friendly way,
+     to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ types,
+ *       and all the values fit on one lines, then print the array on a single
+ line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledStreamWriter {
+public:
+  StyledStreamWriter(std::string indentation = "\t");
+  ~StyledStreamWriter() {}
+
+public:
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param out Stream to write to. (Can be ostringstream, e.g.)
+   * \param root Value to serialize.
+   * \note There is no point in deriving from Writer, since write() should not
+   * return a value.
+   */
+  void write(std::ostream& out, const Value& root);
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const std::string& value);
+  void writeIndent();
+  void writeWithIndent(const std::string& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static std::string normalizeEOL(const std::string& text);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::ostream* document_;
+  std::string indentString_;
+  int rightMargin_;
+  std::string indentation_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+};
+
+#if defined(JSON_HAS_INT64)
+std::string JSON_API valueToString(Int value);
+std::string JSON_API valueToString(UInt value);
+#endif // if defined(JSON_HAS_INT64)
+std::string JSON_API valueToString(LargestInt value);
+std::string JSON_API valueToString(LargestUInt value);
+std::string JSON_API valueToString(double value);
+std::string JSON_API valueToString(bool value);
+std::string JSON_API valueToQuotedString(const char* value);
+
+/// \brief Output using the StyledStreamWriter.
+/// \see Json::operator>>()
+JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_WRITER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/assertions.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+#include <stdlib.h>
+#include <sstream>
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+/** It should not be possible for a maliciously designed file to
+ *  cause an abort() or seg-fault, so these macros are used only
+ *  for pre-condition violations and internal logic errors.
+ */
+#if JSON_USE_EXCEPTION
+
+// @todo <= add detail about condition in exception
+# define JSON_ASSERT(condition)                                                \
+  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
+
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    std::ostringstream oss; oss << message;                                    \
+    Json::throwLogicError(oss.str());                                          \
+    abort();                                                                   \
+  }
+
+#else // JSON_USE_EXCEPTION
+
+# define JSON_ASSERT(condition) assert(condition)
+
+// The call to assert() will show the failure message in debug builds. In
+// release builds we abort, for a core-dump or debugger.
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    std::ostringstream oss; oss << message;                                    \
+    assert(false && oss.str().c_str());                                        \
+    abort();                                                                   \
+  }
+
+
+#endif
+
+#define JSON_ASSERT_MESSAGE(condition, message)                                \
+  if (!(condition)) {                                                          \
+    JSON_FAIL_MESSAGE(message);                                                \
+  }
+
+#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/assertions.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_AMALGATED_H_INCLUDED
diff --git a/src/third_party/protobuf-3/conformance/third_party/jsoncpp/jsoncpp.cpp b/src/third_party/protobuf-3/conformance/third_party/jsoncpp/jsoncpp.cpp
new file mode 100644
index 0000000..f803962
--- /dev/null
+++ b/src/third_party/protobuf-3/conformance/third_party/jsoncpp/jsoncpp.cpp
@@ -0,0 +1,5192 @@
+/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json.h"
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+#include "third_party/jsoncpp/json.h"
+
+#ifndef JSON_IS_AMALGAMATION
+#error "Compile with -I PATH_TO_JSON_DIRECTORY"
+#endif
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+/* This header provides common string manipulation support, such as UTF-8,
+ * portable conversion from/to string...
+ *
+ * It is an internal header that must not be exposed.
+ */
+
+namespace Json {
+
+/// Converts a unicode code-point to UTF-8.
+static inline std::string codePointToUTF8(unsigned int cp) {
+  std::string result;
+
+  // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+  if (cp <= 0x7f) {
+    result.resize(1);
+    result[0] = static_cast<char>(cp);
+  } else if (cp <= 0x7FF) {
+    result.resize(2);
+    result[1] = static_cast<char>(0x80 | (0x3f & cp));
+    result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+  } else if (cp <= 0xFFFF) {
+    result.resize(3);
+    result[2] = static_cast<char>(0x80 | (0x3f & cp));
+    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+    result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
+  } else if (cp <= 0x10FFFF) {
+    result.resize(4);
+    result[3] = static_cast<char>(0x80 | (0x3f & cp));
+    result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+    result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+  }
+
+  return result;
+}
+
+/// Returns true if ch is a control character (in range [1,31]).
+static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
+
+enum {
+  /// Constant that specify the size of the buffer that must be passed to
+  /// uintToString.
+  uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
+};
+
+// Defines a char buffer for use with uintToString().
+typedef char UIntToStringBuffer[uintToStringBufferSize];
+
+/** Converts an unsigned integer to string.
+ * @param value Unsigned interger to convert to string
+ * @param current Input/Output string buffer.
+ *        Must have at least uintToStringBufferSize chars free.
+ */
+static inline void uintToString(LargestUInt value, char*& current) {
+  *--current = 0;
+  do {
+    *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
+    value /= 10;
+  } while (value != 0);
+}
+
+/** Change ',' to '.' everywhere in buffer.
+ *
+ * We had a sophisticated way, but it did not work in WinCE.
+ * @see https://github.com/open-source-parsers/jsoncpp/pull/9
+ */
+static inline void fixNumericLocale(char* begin, char* end) {
+  while (begin < end) {
+    if (*begin == ',') {
+      *begin = '.';
+    }
+    ++begin;
+  }
+}
+
+} // namespace Json {
+
+#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/reader.h>
+#include <json/value.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <istream>
+#include <sstream>
+#include <memory>
+#include <set>
+#include <limits>
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#define snprintf std::snprintf
+#endif
+
+#if defined(__QNXNTO__)
+#define sscanf std::sscanf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+static int const stackLimit_g = 1000;
+static int       stackDepth_g = 0;  // see readValue()
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<CharReader> CharReaderPtr;
+#else
+typedef std::auto_ptr<CharReader>   CharReaderPtr;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+    : allowComments_(true), strictRoot_(false),
+      allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+
+Features Features::all() { return Features(); }
+
+Features Features::strictMode() {
+  Features features;
+  features.allowComments_ = false;
+  features.strictRoot_ = true;
+  features.allowDroppedNullPlaceholders_ = false;
+  features.allowNumericKeys_ = false;
+  return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+static bool containsNewLine(Reader::Location begin, Reader::Location end) {
+  for (; begin < end; ++begin)
+    if (*begin == '\n' || *begin == '\r')
+      return true;
+  return false;
+}
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(), features_(Features::all()),
+      collectComments_() {}
+
+Reader::Reader(const Features& features)
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(), features_(features), collectComments_() {
+}
+
+bool
+Reader::parse(const std::string& document, Value& root, bool collectComments) {
+  document_ = document;
+  const char* begin = document_.c_str();
+  const char* end = begin + document_.length();
+  return parse(begin, end, root, collectComments);
+}
+
+bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
+  // std::istream_iterator<char> begin(sin);
+  // std::istream_iterator<char> end;
+  // Those would allow streamed input from a file, if parse() were a
+  // template function.
+
+  // Since std::string is reference-counted, this at least does not
+  // create an extra copy.
+  std::string doc;
+  std::getline(sin, doc, (char)EOF);
+  return parse(doc, root, collectComments);
+}
+
+bool Reader::parse(const char* beginDoc,
+                   const char* endDoc,
+                   Value& root,
+                   bool collectComments) {
+  if (!features_.allowComments_) {
+    collectComments = false;
+  }
+
+  begin_ = beginDoc;
+  end_ = endDoc;
+  collectComments_ = collectComments;
+  current_ = begin_;
+  lastValueEnd_ = 0;
+  lastValue_ = 0;
+  commentsBefore_ = "";
+  errors_.clear();
+  while (!nodes_.empty())
+    nodes_.pop();
+  nodes_.push(&root);
+
+  stackDepth_g = 0;  // Yes, this is bad coding, but options are limited.
+  bool successful = readValue();
+  Token token;
+  skipCommentTokens(token);
+  if (collectComments_ && !commentsBefore_.empty())
+    root.setComment(commentsBefore_, commentAfter);
+  if (features_.strictRoot_) {
+    if (!root.isArray() && !root.isObject()) {
+      // Set error location to start of doc, ideally should be first token found
+      // in doc
+      token.type_ = tokenError;
+      token.start_ = beginDoc;
+      token.end_ = endDoc;
+      addError(
+          "A valid JSON document must be either an array or an object value.",
+          token);
+      return false;
+    }
+  }
+  return successful;
+}
+
+bool Reader::readValue() {
+  // This is a non-reentrant way to support a stackLimit. Terrible!
+  // But this deprecated class has a security problem: Bad input can
+  // cause a seg-fault. This seems like a fair, binary-compatible way
+  // to prevent the problem.
+  if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+  ++stackDepth_g;
+
+  Token token;
+  skipCommentTokens(token);
+  bool successful = true;
+
+  if (collectComments_ && !commentsBefore_.empty()) {
+    currentValue().setComment(commentsBefore_, commentBefore);
+    commentsBefore_ = "";
+  }
+
+  switch (token.type_) {
+  case tokenObjectBegin:
+    successful = readObject(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenArrayBegin:
+    successful = readArray(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenNumber:
+    successful = decodeNumber(token);
+    break;
+  case tokenString:
+    successful = decodeString(token);
+    break;
+  case tokenTrue:
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenFalse:
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNull:
+    {
+    Value v;
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
+    if (features_.allowDroppedNullPlaceholders_) {
+      // "Un-read" the current token and mark the current value as a null
+      // token.
+      current_--;
+      Value v;
+      currentValue().swapPayload(v);
+      currentValue().setOffsetStart(current_ - begin_ - 1);
+      currentValue().setOffsetLimit(current_ - begin_);
+      break;
+    } // Else, fall through...
+  default:
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    return addError("Syntax error: value, object or array expected.", token);
+  }
+
+  if (collectComments_) {
+    lastValueEnd_ = current_;
+    lastValue_ = &currentValue();
+  }
+
+  --stackDepth_g;
+  return successful;
+}
+
+void Reader::skipCommentTokens(Token& token) {
+  if (features_.allowComments_) {
+    do {
+      readToken(token);
+    } while (token.type_ == tokenComment);
+  } else {
+    readToken(token);
+  }
+}
+
+bool Reader::readToken(Token& token) {
+  skipSpaces();
+  token.start_ = current_;
+  Char c = getNextChar();
+  bool ok = true;
+  switch (c) {
+  case '{':
+    token.type_ = tokenObjectBegin;
+    break;
+  case '}':
+    token.type_ = tokenObjectEnd;
+    break;
+  case '[':
+    token.type_ = tokenArrayBegin;
+    break;
+  case ']':
+    token.type_ = tokenArrayEnd;
+    break;
+  case '"':
+    token.type_ = tokenString;
+    ok = readString();
+    break;
+  case '/':
+    token.type_ = tokenComment;
+    ok = readComment();
+    break;
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9':
+  case '-':
+    token.type_ = tokenNumber;
+    readNumber();
+    break;
+  case 't':
+    token.type_ = tokenTrue;
+    ok = match("rue", 3);
+    break;
+  case 'f':
+    token.type_ = tokenFalse;
+    ok = match("alse", 4);
+    break;
+  case 'n':
+    token.type_ = tokenNull;
+    ok = match("ull", 3);
+    break;
+  case ',':
+    token.type_ = tokenArraySeparator;
+    break;
+  case ':':
+    token.type_ = tokenMemberSeparator;
+    break;
+  case 0:
+    token.type_ = tokenEndOfStream;
+    break;
+  default:
+    ok = false;
+    break;
+  }
+  if (!ok)
+    token.type_ = tokenError;
+  token.end_ = current_;
+  return true;
+}
+
+void Reader::skipSpaces() {
+  while (current_ != end_) {
+    Char c = *current_;
+    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+      ++current_;
+    else
+      break;
+  }
+}
+
+bool Reader::match(Location pattern, int patternLength) {
+  if (end_ - current_ < patternLength)
+    return false;
+  int index = patternLength;
+  while (index--)
+    if (current_[index] != pattern[index])
+      return false;
+  current_ += patternLength;
+  return true;
+}
+
+bool Reader::readComment() {
+  Location commentBegin = current_ - 1;
+  Char c = getNextChar();
+  bool successful = false;
+  if (c == '*')
+    successful = readCStyleComment();
+  else if (c == '/')
+    successful = readCppStyleComment();
+  if (!successful)
+    return false;
+
+  if (collectComments_) {
+    CommentPlacement placement = commentBefore;
+    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+      if (c != '*' || !containsNewLine(commentBegin, current_))
+        placement = commentAfterOnSameLine;
+    }
+
+    addComment(commentBegin, current_, placement);
+  }
+  return true;
+}
+
+static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
+  std::string normalized;
+  normalized.reserve(end - begin);
+  Reader::Location current = begin;
+  while (current != end) {
+    char c = *current++;
+    if (c == '\r') {
+      if (current != end && *current == '\n')
+         // convert dos EOL
+         ++current;
+      // convert Mac EOL
+      normalized += '\n';
+    } else {
+      normalized += c;
+    }
+  }
+  return normalized;
+}
+
+void
+Reader::addComment(Location begin, Location end, CommentPlacement placement) {
+  assert(collectComments_);
+  const std::string& normalized = normalizeEOL(begin, end);
+  if (placement == commentAfterOnSameLine) {
+    assert(lastValue_ != 0);
+    lastValue_->setComment(normalized, placement);
+  } else {
+    commentsBefore_ += normalized;
+  }
+}
+
+bool Reader::readCStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '*' && *current_ == '/')
+      break;
+  }
+  return getNextChar() == '/';
+}
+
+bool Reader::readCppStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
+      break;
+    }
+  }
+  return true;
+}
+
+void Reader::readNumber() {
+  const char *p = current_;
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : 0;
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+}
+
+bool Reader::readString() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '"')
+      break;
+  }
+  return c == '"';
+}
+
+bool Reader::readObject(Token& tokenStart) {
+  Token tokenName;
+  std::string name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  while (readToken(tokenName)) {
+    bool initialTokenOk = true;
+    while (tokenName.type_ == tokenComment && initialTokenOk)
+      initialTokenOk = readToken(tokenName);
+    if (!initialTokenOk)
+      break;
+    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+      return true;
+    name = "";
+    if (tokenName.type_ == tokenString) {
+      if (!decodeString(tokenName, name))
+        return recoverFromError(tokenObjectEnd);
+    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+      Value numberName;
+      if (!decodeNumber(tokenName, numberName))
+        return recoverFromError(tokenObjectEnd);
+      name = numberName.asString();
+    } else {
+      break;
+    }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+      return addErrorAndRecover(
+          "Missing ':' after object member name", colon, tokenObjectEnd);
+    }
+    Value& value = currentValue()[name];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenObjectEnd);
+
+    Token comma;
+    if (!readToken(comma) ||
+        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+         comma.type_ != tokenComment)) {
+      return addErrorAndRecover(
+          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+    }
+    bool finalizeTokenOk = true;
+    while (comma.type_ == tokenComment && finalizeTokenOk)
+      finalizeTokenOk = readToken(comma);
+    if (comma.type_ == tokenObjectEnd)
+      return true;
+  }
+  return addErrorAndRecover(
+      "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool Reader::readArray(Token& tokenStart) {
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  skipSpaces();
+  if (*current_ == ']') // empty array
+  {
+    Token endArray;
+    readToken(endArray);
+    return true;
+  }
+  int index = 0;
+  for (;;) {
+    Value& value = currentValue()[index++];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenArrayEnd);
+
+    Token token;
+    // Accept Comment after last item in the array.
+    ok = readToken(token);
+    while (token.type_ == tokenComment && ok) {
+      ok = readToken(token);
+    }
+    bool badTokenType =
+        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    if (!ok || badTokenType) {
+      return addErrorAndRecover(
+          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+    }
+    if (token.type_ == tokenArrayEnd)
+      break;
+  }
+  return true;
+}
+
+bool Reader::decodeNumber(Token& token) {
+  Value decoded;
+  if (!decodeNumber(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeNumber(Token& token, Value& decoded) {
+  // Attempts to parse the number as an integer. If the number is
+  // larger than the maximum supported value of an integer then
+  // we decode the number as a double.
+  Location current = token.start_;
+  bool isNegative = *current == '-';
+  if (isNegative)
+    ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  Value::LargestUInt maxIntegerValue =
+      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
+                 : Value::maxLargestUInt;
+  Value::LargestUInt threshold = maxIntegerValue / 10;
+  Value::LargestUInt value = 0;
+  while (current < token.end_) {
+    Char c = *current++;
+    if (c < '0' || c > '9')
+      return decodeDouble(token, decoded);
+    Value::UInt digit(c - '0');
+    if (value >= threshold) {
+      // We've hit or exceeded the max value divided by 10 (rounded down). If
+      // a) we've only just touched the limit, b) this is the last digit, and
+      // c) it's small enough to fit in that rounding delta, we're okay.
+      // Otherwise treat this number as a double to avoid overflow.
+      if (value > threshold || current != token.end_ ||
+          digit > maxIntegerValue % 10) {
+        return decodeDouble(token, decoded);
+      }
+    }
+    value = value * 10 + digit;
+  }
+  if (isNegative && value == maxIntegerValue)
+    decoded = Value::minLargestInt;
+  else if (isNegative)
+    decoded = -Value::LargestInt(value);
+  else if (value <= Value::LargestUInt(Value::maxInt))
+    decoded = Value::LargestInt(value);
+  else
+    decoded = value;
+  return true;
+}
+
+bool Reader::decodeDouble(Token& token) {
+  Value decoded;
+  if (!decodeDouble(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeDouble(Token& token, Value& decoded) {
+  double value = 0;
+  std::string buffer(token.start_, token.end_);
+  std::istringstream is(buffer);
+  if (!(is >> value))
+    return addError("'" + std::string(token.start_, token.end_) +
+                        "' is not a number.",
+                    token);
+  decoded = value;
+  return true;
+}
+
+bool Reader::decodeString(Token& token) {
+  std::string decoded_string;
+  if (!decodeString(token, decoded_string))
+    return false;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeString(Token& token, std::string& decoded) {
+  decoded.reserve(token.end_ - token.start_ - 2);
+  Location current = token.start_ + 1; // skip '"'
+  Location end = token.end_ - 1;       // do not include '"'
+  while (current != end) {
+    Char c = *current++;
+    if (c == '"')
+      break;
+    else if (c == '\\') {
+      if (current == end)
+        return addError("Empty escape sequence in string", token, current);
+      Char escape = *current++;
+      switch (escape) {
+      case '"':
+        decoded += '"';
+        break;
+      case '/':
+        decoded += '/';
+        break;
+      case '\\':
+        decoded += '\\';
+        break;
+      case 'b':
+        decoded += '\b';
+        break;
+      case 'f':
+        decoded += '\f';
+        break;
+      case 'n':
+        decoded += '\n';
+        break;
+      case 'r':
+        decoded += '\r';
+        break;
+      case 't':
+        decoded += '\t';
+        break;
+      case 'u': {
+        unsigned int unicode;
+        if (!decodeUnicodeCodePoint(token, current, end, unicode))
+          return false;
+        decoded += codePointToUTF8(unicode);
+      } break;
+      default:
+        return addError("Bad escape sequence in string", token, current);
+      }
+    } else {
+      decoded += c;
+    }
+  }
+  return true;
+}
+
+bool Reader::decodeUnicodeCodePoint(Token& token,
+                                    Location& current,
+                                    Location end,
+                                    unsigned int& unicode) {
+
+  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+    return false;
+  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+    // surrogate pairs
+    if (end - current < 6)
+      return addError(
+          "additional six characters expected to parse unicode surrogate pair.",
+          token,
+          current);
+    unsigned int surrogatePair;
+    if (*(current++) == '\\' && *(current++) == 'u') {
+      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+      } else
+        return false;
+    } else
+      return addError("expecting another \\u token to begin the second half of "
+                      "a unicode surrogate pair",
+                      token,
+                      current);
+  }
+  return true;
+}
+
+bool Reader::decodeUnicodeEscapeSequence(Token& token,
+                                         Location& current,
+                                         Location end,
+                                         unsigned int& unicode) {
+  if (end - current < 4)
+    return addError(
+        "Bad unicode escape sequence in string: four digits expected.",
+        token,
+        current);
+  unicode = 0;
+  for (int index = 0; index < 4; ++index) {
+    Char c = *current++;
+    unicode *= 16;
+    if (c >= '0' && c <= '9')
+      unicode += c - '0';
+    else if (c >= 'a' && c <= 'f')
+      unicode += c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      unicode += c - 'A' + 10;
+    else
+      return addError(
+          "Bad unicode escape sequence in string: hexadecimal digit expected.",
+          token,
+          current);
+  }
+  return true;
+}
+
+bool
+Reader::addError(const std::string& message, Token& token, Location extra) {
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = extra;
+  errors_.push_back(info);
+  return false;
+}
+
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+  int errorCount = int(errors_.size());
+  Token skip;
+  for (;;) {
+    if (!readToken(skip))
+      errors_.resize(errorCount); // discard errors caused by recovery
+    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+      break;
+  }
+  errors_.resize(errorCount);
+  return false;
+}
+
+bool Reader::addErrorAndRecover(const std::string& message,
+                                Token& token,
+                                TokenType skipUntilToken) {
+  addError(message, token);
+  return recoverFromError(skipUntilToken);
+}
+
+Value& Reader::currentValue() { return *(nodes_.top()); }
+
+Reader::Char Reader::getNextChar() {
+  if (current_ == end_)
+    return 0;
+  return *current_++;
+}
+
+void Reader::getLocationLineAndColumn(Location location,
+                                      int& line,
+                                      int& column) const {
+  Location current = begin_;
+  Location lastLineStart = current;
+  line = 0;
+  while (current < location && current != end_) {
+    Char c = *current++;
+    if (c == '\r') {
+      if (*current == '\n')
+        ++current;
+      lastLineStart = current;
+      ++line;
+    } else if (c == '\n') {
+      lastLineStart = current;
+      ++line;
+    }
+  }
+  // column & line start at 1
+  column = int(location - lastLineStart) + 1;
+  ++line;
+}
+
+std::string Reader::getLocationLineAndColumn(Location location) const {
+  int line, column;
+  getLocationLineAndColumn(location, line, column);
+  char buffer[18 + 16 + 16 + 1];
+  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  return buffer;
+}
+
+// Deprecated. Preserved for backward compatibility
+std::string Reader::getFormatedErrorMessages() const {
+  return getFormattedErrorMessages();
+}
+
+std::string Reader::getFormattedErrorMessages() const {
+  std::string formattedMessage;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    formattedMessage +=
+        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+    formattedMessage += "  " + error.message_ + "\n";
+    if (error.extra_)
+      formattedMessage +=
+          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+  }
+  return formattedMessage;
+}
+
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+  std::vector<Reader::StructuredError> allErrors;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    Reader::StructuredError structured;
+    structured.offset_start = error.token_.start_ - begin_;
+    structured.offset_limit = error.token_.end_ - begin_;
+    structured.message = error.message_;
+    allErrors.push_back(structured);
+  }
+  return allErrors;
+}
+
+bool Reader::pushError(const Value& value, const std::string& message) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = end_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = 0;
+  errors_.push_back(info);
+  return true;
+}
+
+bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length
+    || extra.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = begin_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = begin_ + extra.getOffsetStart();
+  errors_.push_back(info);
+  return true;
+}
+
+bool Reader::good() const {
+  return !errors_.size();
+}
+
+// exact copy of Features
+class OurFeatures {
+public:
+  static OurFeatures all();
+  bool allowComments_;
+  bool strictRoot_;
+  bool allowDroppedNullPlaceholders_;
+  bool allowNumericKeys_;
+  bool allowSingleQuotes_;
+  bool failIfExtra_;
+  bool rejectDupKeys_;
+  bool allowSpecialFloats_;
+  int stackLimit_;
+};  // OurFeatures
+
+// exact copy of Implementation of class Features
+// ////////////////////////////////
+
+OurFeatures OurFeatures::all() { return OurFeatures(); }
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+// exact copy of Reader, renamed to OurReader
+class OurReader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+  struct StructuredError {
+    size_t offset_start;
+    size_t offset_limit;
+    std::string message;
+  };
+
+  OurReader(OurFeatures const& features);
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+  std::string getFormattedErrorMessages() const;
+  std::vector<StructuredError> getStructuredErrors() const;
+  bool pushError(const Value& value, const std::string& message);
+  bool pushError(const Value& value, const std::string& message, const Value& extra);
+  bool good() const;
+
+private:
+  OurReader(OurReader const&);  // no impl
+  void operator=(OurReader const&);  // no impl
+
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenNaN,
+    tokenPosInf,
+    tokenNegInf,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    std::string message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  bool readStringSingleQuote();
+  bool readNumber(bool checkInf);
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, std::string& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const std::string& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const std::string& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  std::string getLocationLineAndColumn(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  std::string document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  std::string commentsBefore_;
+  int stackDepth_;
+
+  OurFeatures const features_;
+  bool collectComments_;
+};  // OurReader
+
+// complete copy of Read impl, for OurReader
+
+OurReader::OurReader(OurFeatures const& features)
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(),
+      stackDepth_(0),
+      features_(features), collectComments_() {
+}
+
+bool OurReader::parse(const char* beginDoc,
+                   const char* endDoc,
+                   Value& root,
+                   bool collectComments) {
+  if (!features_.allowComments_) {
+    collectComments = false;
+  }
+
+  begin_ = beginDoc;
+  end_ = endDoc;
+  collectComments_ = collectComments;
+  current_ = begin_;
+  lastValueEnd_ = 0;
+  lastValue_ = 0;
+  commentsBefore_ = "";
+  errors_.clear();
+  while (!nodes_.empty())
+    nodes_.pop();
+  nodes_.push(&root);
+
+  stackDepth_ = 0;
+  bool successful = readValue();
+  Token token;
+  skipCommentTokens(token);
+  if (features_.failIfExtra_) {
+    if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
+      addError("Extra non-whitespace after JSON value.", token);
+      return false;
+    }
+  }
+  if (collectComments_ && !commentsBefore_.empty())
+    root.setComment(commentsBefore_, commentAfter);
+  if (features_.strictRoot_) {
+    if (!root.isArray() && !root.isObject()) {
+      // Set error location to start of doc, ideally should be first token found
+      // in doc
+      token.type_ = tokenError;
+      token.start_ = beginDoc;
+      token.end_ = endDoc;
+      addError(
+          "A valid JSON document must be either an array or an object value.",
+          token);
+      return false;
+    }
+  }
+  return successful;
+}
+
+bool OurReader::readValue() {
+  if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+  ++stackDepth_;
+  Token token;
+  skipCommentTokens(token);
+  bool successful = true;
+
+  if (collectComments_ && !commentsBefore_.empty()) {
+    currentValue().setComment(commentsBefore_, commentBefore);
+    commentsBefore_ = "";
+  }
+
+  switch (token.type_) {
+  case tokenObjectBegin:
+    successful = readObject(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenArrayBegin:
+    successful = readArray(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenNumber:
+    successful = decodeNumber(token);
+    break;
+  case tokenString:
+    successful = decodeString(token);
+    break;
+  case tokenTrue:
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenFalse:
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNull:
+    {
+    Value v;
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNaN:
+    {
+    Value v(std::numeric_limits<double>::quiet_NaN());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenPosInf:
+    {
+    Value v(std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNegInf:
+    {
+    Value v(-std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
+    if (features_.allowDroppedNullPlaceholders_) {
+      // "Un-read" the current token and mark the current value as a null
+      // token.
+      current_--;
+      Value v;
+      currentValue().swapPayload(v);
+      currentValue().setOffsetStart(current_ - begin_ - 1);
+      currentValue().setOffsetLimit(current_ - begin_);
+      break;
+    } // else, fall through ...
+  default:
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    return addError("Syntax error: value, object or array expected.", token);
+  }
+
+  if (collectComments_) {
+    lastValueEnd_ = current_;
+    lastValue_ = &currentValue();
+  }
+
+  --stackDepth_;
+  return successful;
+}
+
+void OurReader::skipCommentTokens(Token& token) {
+  if (features_.allowComments_) {
+    do {
+      readToken(token);
+    } while (token.type_ == tokenComment);
+  } else {
+    readToken(token);
+  }
+}
+
+bool OurReader::readToken(Token& token) {
+  skipSpaces();
+  token.start_ = current_;
+  Char c = getNextChar();
+  bool ok = true;
+  switch (c) {
+  case '{':
+    token.type_ = tokenObjectBegin;
+    break;
+  case '}':
+    token.type_ = tokenObjectEnd;
+    break;
+  case '[':
+    token.type_ = tokenArrayBegin;
+    break;
+  case ']':
+    token.type_ = tokenArrayEnd;
+    break;
+  case '"':
+    token.type_ = tokenString;
+    ok = readString();
+    break;
+  case '\'':
+    if (features_.allowSingleQuotes_) {
+    token.type_ = tokenString;
+    ok = readStringSingleQuote();
+    break;
+    } // else continue
+  case '/':
+    token.type_ = tokenComment;
+    ok = readComment();
+    break;
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9':
+    token.type_ = tokenNumber;
+    readNumber(false);
+    break;
+  case '-':
+    if (readNumber(true)) {
+      token.type_ = tokenNumber;
+    } else {
+      token.type_ = tokenNegInf;
+      ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+    }
+    break;
+  case 't':
+    token.type_ = tokenTrue;
+    ok = match("rue", 3);
+    break;
+  case 'f':
+    token.type_ = tokenFalse;
+    ok = match("alse", 4);
+    break;
+  case 'n':
+    token.type_ = tokenNull;
+    ok = match("ull", 3);
+    break;
+  case 'N':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenNaN;
+      ok = match("aN", 2);
+    } else {
+      ok = false;
+    }
+    break;
+  case 'I':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenPosInf;
+      ok = match("nfinity", 7);
+    } else {
+      ok = false;
+    }
+    break;
+  case ',':
+    token.type_ = tokenArraySeparator;
+    break;
+  case ':':
+    token.type_ = tokenMemberSeparator;
+    break;
+  case 0:
+    token.type_ = tokenEndOfStream;
+    break;
+  default:
+    ok = false;
+    break;
+  }
+  if (!ok)
+    token.type_ = tokenError;
+  token.end_ = current_;
+  return true;
+}
+
+void OurReader::skipSpaces() {
+  while (current_ != end_) {
+    Char c = *current_;
+    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+      ++current_;
+    else
+      break;
+  }
+}
+
+bool OurReader::match(Location pattern, int patternLength) {
+  if (end_ - current_ < patternLength)
+    return false;
+  int index = patternLength;
+  while (index--)
+    if (current_[index] != pattern[index])
+      return false;
+  current_ += patternLength;
+  return true;
+}
+
+bool OurReader::readComment() {
+  Location commentBegin = current_ - 1;
+  Char c = getNextChar();
+  bool successful = false;
+  if (c == '*')
+    successful = readCStyleComment();
+  else if (c == '/')
+    successful = readCppStyleComment();
+  if (!successful)
+    return false;
+
+  if (collectComments_) {
+    CommentPlacement placement = commentBefore;
+    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+      if (c != '*' || !containsNewLine(commentBegin, current_))
+        placement = commentAfterOnSameLine;
+    }
+
+    addComment(commentBegin, current_, placement);
+  }
+  return true;
+}
+
+void
+OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+  assert(collectComments_);
+  const std::string& normalized = normalizeEOL(begin, end);
+  if (placement == commentAfterOnSameLine) {
+    assert(lastValue_ != 0);
+    lastValue_->setComment(normalized, placement);
+  } else {
+    commentsBefore_ += normalized;
+  }
+}
+
+bool OurReader::readCStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '*' && *current_ == '/')
+      break;
+  }
+  return getNextChar() == '/';
+}
+
+bool OurReader::readCppStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
+      break;
+    }
+  }
+  return true;
+}
+
+bool OurReader::readNumber(bool checkInf) {
+  const char *p = current_;
+  if (checkInf && p != end_ && *p == 'I') {
+    current_ = ++p;
+    return false;
+  }
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : 0;
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  return true;
+}
+bool OurReader::readString() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '"')
+      break;
+  }
+  return c == '"';
+}
+
+
+bool OurReader::readStringSingleQuote() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '\'')
+      break;
+  }
+  return c == '\'';
+}
+
+bool OurReader::readObject(Token& tokenStart) {
+  Token tokenName;
+  std::string name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  while (readToken(tokenName)) {
+    bool initialTokenOk = true;
+    while (tokenName.type_ == tokenComment && initialTokenOk)
+      initialTokenOk = readToken(tokenName);
+    if (!initialTokenOk)
+      break;
+    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+      return true;
+    name = "";
+    if (tokenName.type_ == tokenString) {
+      if (!decodeString(tokenName, name))
+        return recoverFromError(tokenObjectEnd);
+    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+      Value numberName;
+      if (!decodeNumber(tokenName, numberName))
+        return recoverFromError(tokenObjectEnd);
+      name = numberName.asString();
+    } else {
+      break;
+    }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+      return addErrorAndRecover(
+          "Missing ':' after object member name", colon, tokenObjectEnd);
+    }
+    if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
+    if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+      std::string msg = "Duplicate key: '" + name + "'";
+      return addErrorAndRecover(
+          msg, tokenName, tokenObjectEnd);
+    }
+    Value& value = currentValue()[name];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenObjectEnd);
+
+    Token comma;
+    if (!readToken(comma) ||
+        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+         comma.type_ != tokenComment)) {
+      return addErrorAndRecover(
+          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+    }
+    bool finalizeTokenOk = true;
+    while (comma.type_ == tokenComment && finalizeTokenOk)
+      finalizeTokenOk = readToken(comma);
+    if (comma.type_ == tokenObjectEnd)
+      return true;
+  }
+  return addErrorAndRecover(
+      "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool OurReader::readArray(Token& tokenStart) {
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  skipSpaces();
+  if (*current_ == ']') // empty array
+  {
+    Token endArray;
+    readToken(endArray);
+    return true;
+  }
+  int index = 0;
+  for (;;) {
+    Value& value = currentValue()[index++];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenArrayEnd);
+
+    Token token;
+    // Accept Comment after last item in the array.
+    ok = readToken(token);
+    while (token.type_ == tokenComment && ok) {
+      ok = readToken(token);
+    }
+    bool badTokenType =
+        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    if (!ok || badTokenType) {
+      return addErrorAndRecover(
+          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+    }
+    if (token.type_ == tokenArrayEnd)
+      break;
+  }
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token) {
+  Value decoded;
+  if (!decodeNumber(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
+  // Attempts to parse the number as an integer. If the number is
+  // larger than the maximum supported value of an integer then
+  // we decode the number as a double.
+  Location current = token.start_;
+  bool isNegative = *current == '-';
+  if (isNegative)
+    ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  Value::LargestUInt maxIntegerValue =
+      isNegative ? Value::LargestUInt(-Value::minLargestInt)
+                 : Value::maxLargestUInt;
+  Value::LargestUInt threshold = maxIntegerValue / 10;
+  Value::LargestUInt value = 0;
+  while (current < token.end_) {
+    Char c = *current++;
+    if (c < '0' || c > '9')
+      return decodeDouble(token, decoded);
+    Value::UInt digit(c - '0');
+    if (value >= threshold) {
+      // We've hit or exceeded the max value divided by 10 (rounded down). If
+      // a) we've only just touched the limit, b) this is the last digit, and
+      // c) it's small enough to fit in that rounding delta, we're okay.
+      // Otherwise treat this number as a double to avoid overflow.
+      if (value > threshold || current != token.end_ ||
+          digit > maxIntegerValue % 10) {
+        return decodeDouble(token, decoded);
+      }
+    }
+    value = value * 10 + digit;
+  }
+  if (isNegative)
+    decoded = -Value::LargestInt(value);
+  else if (value <= Value::LargestUInt(Value::maxInt))
+    decoded = Value::LargestInt(value);
+  else
+    decoded = value;
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token) {
+  Value decoded;
+  if (!decodeDouble(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
+  double value = 0;
+  const int bufferSize = 32;
+  int count;
+  int length = int(token.end_ - token.start_);
+
+  // Sanity check to avoid buffer overflow exploits.
+  if (length < 0) {
+    return addError("Unable to parse token length", token);
+  }
+
+  // Avoid using a string constant for the format control string given to
+  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
+  // info:
+  //
+  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
+  char format[] = "%lf";
+
+  if (length <= bufferSize) {
+    Char buffer[bufferSize + 1];
+    memcpy(buffer, token.start_, length);
+    buffer[length] = 0;
+    count = sscanf(buffer, format, &value);
+  } else {
+    std::string buffer(token.start_, token.end_);
+    count = sscanf(buffer.c_str(), format, &value);
+  }
+
+  if (count != 1)
+    return addError("'" + std::string(token.start_, token.end_) +
+                        "' is not a number.",
+                    token);
+  decoded = value;
+  return true;
+}
+
+bool OurReader::decodeString(Token& token) {
+  std::string decoded_string;
+  if (!decodeString(token, decoded_string))
+    return false;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeString(Token& token, std::string& decoded) {
+  decoded.reserve(token.end_ - token.start_ - 2);
+  Location current = token.start_ + 1; // skip '"'
+  Location end = token.end_ - 1;       // do not include '"'
+  while (current != end) {
+    Char c = *current++;
+    if (c == '"')
+      break;
+    else if (c == '\\') {
+      if (current == end)
+        return addError("Empty escape sequence in string", token, current);
+      Char escape = *current++;
+      switch (escape) {
+      case '"':
+        decoded += '"';
+        break;
+      case '/':
+        decoded += '/';
+        break;
+      case '\\':
+        decoded += '\\';
+        break;
+      case 'b':
+        decoded += '\b';
+        break;
+      case 'f':
+        decoded += '\f';
+        break;
+      case 'n':
+        decoded += '\n';
+        break;
+      case 'r':
+        decoded += '\r';
+        break;
+      case 't':
+        decoded += '\t';
+        break;
+      case 'u': {
+        unsigned int unicode;
+        if (!decodeUnicodeCodePoint(token, current, end, unicode))
+          return false;
+        decoded += codePointToUTF8(unicode);
+      } break;
+      default:
+        return addError("Bad escape sequence in string", token, current);
+      }
+    } else {
+      decoded += c;
+    }
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeCodePoint(Token& token,
+                                    Location& current,
+                                    Location end,
+                                    unsigned int& unicode) {
+
+  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+    return false;
+  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+    // surrogate pairs
+    if (end - current < 6)
+      return addError(
+          "additional six characters expected to parse unicode surrogate pair.",
+          token,
+          current);
+    unsigned int surrogatePair;
+    if (*(current++) == '\\' && *(current++) == 'u') {
+      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+      } else
+        return false;
+    } else
+      return addError("expecting another \\u token to begin the second half of "
+                      "a unicode surrogate pair",
+                      token,
+                      current);
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeEscapeSequence(Token& token,
+                                         Location& current,
+                                         Location end,
+                                         unsigned int& unicode) {
+  if (end - current < 4)
+    return addError(
+        "Bad unicode escape sequence in string: four digits expected.",
+        token,
+        current);
+  unicode = 0;
+  for (int index = 0; index < 4; ++index) {
+    Char c = *current++;
+    unicode *= 16;
+    if (c >= '0' && c <= '9')
+      unicode += c - '0';
+    else if (c >= 'a' && c <= 'f')
+      unicode += c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      unicode += c - 'A' + 10;
+    else
+      return addError(
+          "Bad unicode escape sequence in string: hexadecimal digit expected.",
+          token,
+          current);
+  }
+  return true;
+}
+
+bool
+OurReader::addError(const std::string& message, Token& token, Location extra) {
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = extra;
+  errors_.push_back(info);
+  return false;
+}
+
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+  int errorCount = int(errors_.size());
+  Token skip;
+  for (;;) {
+    if (!readToken(skip))
+      errors_.resize(errorCount); // discard errors caused by recovery
+    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+      break;
+  }
+  errors_.resize(errorCount);
+  return false;
+}
+
+bool OurReader::addErrorAndRecover(const std::string& message,
+                                Token& token,
+                                TokenType skipUntilToken) {
+  addError(message, token);
+  return recoverFromError(skipUntilToken);
+}
+
+Value& OurReader::currentValue() { return *(nodes_.top()); }
+
+OurReader::Char OurReader::getNextChar() {
+  if (current_ == end_)
+    return 0;
+  return *current_++;
+}
+
+void OurReader::getLocationLineAndColumn(Location location,
+                                      int& line,
+                                      int& column) const {
+  Location current = begin_;
+  Location lastLineStart = current;
+  line = 0;
+  while (current < location && current != end_) {
+    Char c = *current++;
+    if (c == '\r') {
+      if (*current == '\n')
+        ++current;
+      lastLineStart = current;
+      ++line;
+    } else if (c == '\n') {
+      lastLineStart = current;
+      ++line;
+    }
+  }
+  // column & line start at 1
+  column = int(location - lastLineStart) + 1;
+  ++line;
+}
+
+std::string OurReader::getLocationLineAndColumn(Location location) const {
+  int line, column;
+  getLocationLineAndColumn(location, line, column);
+  char buffer[18 + 16 + 16 + 1];
+  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  return buffer;
+}
+
+std::string OurReader::getFormattedErrorMessages() const {
+  std::string formattedMessage;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    formattedMessage +=
+        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+    formattedMessage += "  " + error.message_ + "\n";
+    if (error.extra_)
+      formattedMessage +=
+          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+  }
+  return formattedMessage;
+}
+
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+  std::vector<OurReader::StructuredError> allErrors;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    OurReader::StructuredError structured;
+    structured.offset_start = error.token_.start_ - begin_;
+    structured.offset_limit = error.token_.end_ - begin_;
+    structured.message = error.message_;
+    allErrors.push_back(structured);
+  }
+  return allErrors;
+}
+
+bool OurReader::pushError(const Value& value, const std::string& message) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = end_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = 0;
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length
+    || extra.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = begin_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = begin_ + extra.getOffsetStart();
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::good() const {
+  return !errors_.size();
+}
+
+
+class OurCharReader : public CharReader {
+  bool const collectComments_;
+  OurReader reader_;
+public:
+  OurCharReader(
+    bool collectComments,
+    OurFeatures const& features)
+  : collectComments_(collectComments)
+  , reader_(features)
+  {}
+  bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, std::string* errs) override {
+    bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+    if (errs) {
+      *errs = reader_.getFormattedErrorMessages();
+    }
+    return ok;
+  }
+};
+
+CharReaderBuilder::CharReaderBuilder()
+{
+  setDefaults(&settings_);
+}
+CharReaderBuilder::~CharReaderBuilder()
+{}
+CharReader* CharReaderBuilder::newCharReader() const
+{
+  bool collectComments = settings_["collectComments"].asBool();
+  OurFeatures features = OurFeatures::all();
+  features.allowComments_ = settings_["allowComments"].asBool();
+  features.strictRoot_ = settings_["strictRoot"].asBool();
+  features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+  features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+  features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+  features.stackLimit_ = settings_["stackLimit"].asInt();
+  features.failIfExtra_ = settings_["failIfExtra"].asBool();
+  features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+  features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+  return new OurCharReader(collectComments, features);
+}
+static void getValidReaderKeys(std::set<std::string>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("collectComments");
+  valid_keys->insert("allowComments");
+  valid_keys->insert("strictRoot");
+  valid_keys->insert("allowDroppedNullPlaceholders");
+  valid_keys->insert("allowNumericKeys");
+  valid_keys->insert("allowSingleQuotes");
+  valid_keys->insert("stackLimit");
+  valid_keys->insert("failIfExtra");
+  valid_keys->insert("rejectDupKeys");
+  valid_keys->insert("allowSpecialFloats");
+}
+bool CharReaderBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<std::string> valid_keys;
+  getValidReaderKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    std::string const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& CharReaderBuilder::operator[](std::string key)
+{
+  return settings_[key];
+}
+// static
+void CharReaderBuilder::strictMode(Json::Value* settings)
+{
+//! [CharReaderBuilderStrictMode]
+  (*settings)["allowComments"] = false;
+  (*settings)["strictRoot"] = true;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = true;
+  (*settings)["rejectDupKeys"] = true;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderStrictMode]
+}
+// static
+void CharReaderBuilder::setDefaults(Json::Value* settings)
+{
+//! [CharReaderBuilderDefaults]
+  (*settings)["collectComments"] = true;
+  (*settings)["allowComments"] = true;
+  (*settings)["strictRoot"] = false;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = false;
+  (*settings)["rejectDupKeys"] = false;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderDefaults]
+}
+
+//////////////////////////////////
+// global functions
+
+bool parseFromStream(
+    CharReader::Factory const& fact, std::istream& sin,
+    Value* root, std::string* errs)
+{
+  std::ostringstream ssin;
+  ssin << sin.rdbuf();
+  std::string doc = ssin.str();
+  char const* begin = doc.data();
+  char const* end = begin + doc.size();
+  // Note that we do not actually need a null-terminator.
+  CharReaderPtr const reader(fact.newCharReader());
+  return reader->parse(begin, end, root, errs);
+}
+
+std::istream& operator>>(std::istream& sin, Value& root) {
+  CharReaderBuilder b;
+  std::string errs;
+  bool ok = parseFromStream(b, sin, &root, &errs);
+  if (!ok) {
+    fprintf(stderr,
+            "Error from reader: %s",
+            errs.c_str());
+
+    throwRuntimeError(errs);
+  }
+  return sin;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+// included by json_value.cpp
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+    : current_(), isNull_(true) {
+}
+
+ValueIteratorBase::ValueIteratorBase(
+    const Value::ObjectValues::iterator& current)
+    : current_(current), isNull_(false) {}
+
+Value& ValueIteratorBase::deref() const {
+  return current_->second;
+}
+
+void ValueIteratorBase::increment() {
+  ++current_;
+}
+
+void ValueIteratorBase::decrement() {
+  --current_;
+}
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance(const SelfType& other) const {
+#ifdef JSON_USE_CPPTL_SMALLMAP
+  return other.current_ - current_;
+#else
+  // Iterator for null value are initialized using the default
+  // constructor, which initialize current_ to the default
+  // std::map::iterator. As begin() and end() are two instance
+  // of the default std::map::iterator, they can not be compared.
+  // To allow this, we handle this comparison specifically.
+  if (isNull_ && other.isNull_) {
+    return 0;
+  }
+
+  // Usage of std::distance is not portable (does not compile with Sun Studio 12
+  // RogueWave STL,
+  // which is the one used by default).
+  // Using a portable hand-made version for non random iterator instead:
+  //   return difference_type( std::distance( current_, other.current_ ) );
+  difference_type myDistance = 0;
+  for (Value::ObjectValues::iterator it = current_; it != other.current_;
+       ++it) {
+    ++myDistance;
+  }
+  return myDistance;
+#endif
+}
+
+bool ValueIteratorBase::isEqual(const SelfType& other) const {
+  if (isNull_) {
+    return other.isNull_;
+  }
+  return current_ == other.current_;
+}
+
+void ValueIteratorBase::copy(const SelfType& other) {
+  current_ = other.current_;
+  isNull_ = other.isNull_;
+}
+
+Value ValueIteratorBase::key() const {
+  const Value::CZString czstring = (*current_).first;
+  if (czstring.data()) {
+    if (czstring.isStaticString())
+      return Value(StaticString(czstring.data()));
+    return Value(czstring.data(), czstring.data() + czstring.length());
+  }
+  return Value(czstring.index());
+}
+
+UInt ValueIteratorBase::index() const {
+  const Value::CZString czstring = (*current_).first;
+  if (!czstring.data())
+    return czstring.index();
+  return Value::UInt(-1);
+}
+
+std::string ValueIteratorBase::name() const {
+  char const* keey;
+  char const* end;
+  keey = memberName(&end);
+  if (!keey) return std::string();
+  return std::string(keey, end);
+}
+
+char const* ValueIteratorBase::memberName() const {
+  const char* cname = (*current_).first.data();
+  return cname ? cname : "";
+}
+
+char const* ValueIteratorBase::memberName(char const** end) const {
+  const char* cname = (*current_).first.data();
+  if (!cname) {
+    *end = NULL;
+    return NULL;
+  }
+  *end = cname + (*current_).first.length();
+  return cname;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator() {}
+
+ValueConstIterator::ValueConstIterator(
+    const Value::ObjectValues::iterator& current)
+    : ValueIteratorBase(current) {}
+
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+    : ValueIteratorBase(other) {}
+
+ValueConstIterator& ValueConstIterator::
+operator=(const ValueIteratorBase& other) {
+  copy(other);
+  return *this;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator() {}
+
+ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
+    : ValueIteratorBase(current) {}
+
+ValueIterator::ValueIterator(const ValueConstIterator& other)
+    : ValueIteratorBase(other) {
+  throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
+
+ValueIterator::ValueIterator(const ValueIterator& other)
+    : ValueIteratorBase(other) {}
+
+ValueIterator& ValueIterator::operator=(const SelfType& other) {
+  copy(other);
+  return *this;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/value.h>
+#include <json/writer.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <math.h>
+#include <sstream>
+#include <utility>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+#include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#include <algorithm> // min()
+
+#define JSON_ASSERT_UNREACHABLE assert(false)
+
+namespace Json {
+
+// This is a walkaround to avoid the static initialization of Value::null.
+// kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
+// 8 (instead of 4) as a bit of future-proofing.
+#if defined(__ARMEL__)
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#else
+#define ALIGNAS(byte_alignment)
+#endif
+static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+const unsigned char& kNullRef = kNull[0];
+const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+const Value& Value::nullRef = null;
+
+const Int Value::minInt = Int(~(UInt(-1) / 2));
+const Int Value::maxInt = Int(UInt(-1) / 2);
+const UInt Value::maxUInt = UInt(-1);
+#if defined(JSON_HAS_INT64)
+const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
+const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
+const UInt64 Value::maxUInt64 = UInt64(-1);
+// The constant is hard-coded because some compiler have trouble
+// converting Value::maxUInt64 to a double correctly (AIX/xlC).
+// Assumes that UInt64 is a 64 bits integer.
+static const double maxUInt64AsDouble = 18446744073709551615.0;
+#endif // defined(JSON_HAS_INT64)
+const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
+const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+  return d >= min && d <= max;
+}
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+static inline double integerToDouble(Json::UInt64 value) {
+  return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
+}
+
+template <typename T> static inline double integerToDouble(T value) {
+  return static_cast<double>(value);
+}
+
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+  return d >= integerToDouble(min) && d <= integerToDouble(max);
+}
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+
+/** Duplicates the specified string value.
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
+ *              length is "unknown".
+ * @param length Length of the value. if equals to unknown, then it will be
+ *               computed using strlen(value).
+ * @return Pointer on the duplicate instance of string.
+ */
+static inline char* duplicateStringValue(const char* value,
+                                         size_t length) {
+  // Avoid an integer overflow in the call to malloc below by limiting length
+  // to a sane value.
+  if (length >= (size_t)Value::maxInt)
+    length = Value::maxInt - 1;
+
+  char* newString = static_cast<char*>(malloc(length + 1));
+  if (newString == NULL) {
+    throwRuntimeError(
+        "in Json::Value::duplicateStringValue(): "
+        "Failed to allocate string value buffer");
+  }
+  memcpy(newString, value, length);
+  newString[length] = 0;
+  return newString;
+}
+
+/* Record the length as a prefix.
+ */
+static inline char* duplicateAndPrefixStringValue(
+    const char* value,
+    unsigned int length)
+{
+  // Avoid an integer overflow in the call to malloc below by limiting length
+  // to a sane value.
+  JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
+                      "in Json::Value::duplicateAndPrefixStringValue(): "
+                      "length too big for prefixing");
+  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+  char* newString = static_cast<char*>(malloc(actualLength));
+  if (newString == 0) {
+    throwRuntimeError(
+        "in Json::Value::duplicateAndPrefixStringValue(): "
+        "Failed to allocate string value buffer");
+  }
+  *reinterpret_cast<unsigned*>(newString) = length;
+  memcpy(newString + sizeof(unsigned), value, length);
+  newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+  return newString;
+}
+inline static void decodePrefixedString(
+    bool isPrefixed, char const* prefixed,
+    unsigned* length, char const** value)
+{
+  if (!isPrefixed) {
+    *length = static_cast<unsigned>(strlen(prefixed));
+    *value = prefixed;
+  } else {
+    *length = *reinterpret_cast<unsigned const*>(prefixed);
+    *value = prefixed + sizeof(unsigned);
+  }
+}
+/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+ */
+static inline void releaseStringValue(char* value) { free(value); }
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "json_valueiterator.inl"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+Exception::Exception(std::string const& msg)
+  : msg_(msg)
+{}
+Exception::~Exception() throw()
+{}
+char const* Exception::what() const throw()
+{
+  return msg_.c_str();
+}
+RuntimeError::RuntimeError(std::string const& msg)
+  : Exception(msg)
+{}
+LogicError::LogicError(std::string const& msg)
+  : Exception(msg)
+{}
+void throwRuntimeError(std::string const& msg)
+{
+  throw RuntimeError(msg);
+}
+void throwLogicError(std::string const& msg)
+{
+  throw LogicError(msg);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+Value::CommentInfo::CommentInfo() : comment_(0) {}
+
+Value::CommentInfo::~CommentInfo() {
+  if (comment_)
+    releaseStringValue(comment_);
+}
+
+void Value::CommentInfo::setComment(const char* text, size_t len) {
+  if (comment_) {
+    releaseStringValue(comment_);
+    comment_ = 0;
+  }
+  JSON_ASSERT(text != 0);
+  JSON_ASSERT_MESSAGE(
+      text[0] == '\0' || text[0] == '/',
+      "in Json::Value::setComment(): Comments must start with /");
+  // It seems that /**/ style comments are acceptable as well.
+  comment_ = duplicateStringValue(text, len);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+// Notes: policy_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+    : cstr_(str) {
+  // allocate != duplicate
+  storage_.policy_ = allocate & 0x3;
+  storage_.length_ = ulength & 0x3FFFFFFF;
+}
+
+Value::CZString::CZString(const CZString& other)
+    : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
+                ? duplicateStringValue(other.cstr_, other.storage_.length_)
+                : other.cstr_) {
+  storage_.policy_ = (other.cstr_
+                 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
+                     ? noDuplication : duplicate)
+                 : static_cast<DuplicationPolicy>(other.storage_.policy_));
+  storage_.length_ = other.storage_.length_;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString::CZString(CZString&& other)
+  : cstr_(other.cstr_), index_(other.index_) {
+  other.cstr_ = nullptr;
+}
+#endif
+
+Value::CZString::~CZString() {
+  if (cstr_ && storage_.policy_ == duplicate)
+    releaseStringValue(const_cast<char*>(cstr_));
+}
+
+void Value::CZString::swap(CZString& other) {
+  std::swap(cstr_, other.cstr_);
+  std::swap(index_, other.index_);
+}
+
+Value::CZString& Value::CZString::operator=(CZString other) {
+  swap(other);
+  return *this;
+}
+
+bool Value::CZString::operator<(const CZString& other) const {
+  if (!cstr_) return index_ < other.index_;
+  //return strcmp(cstr_, other.cstr_) < 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  unsigned min_len = std::min(this_len, other_len);
+  int comp = memcmp(this->cstr_, other.cstr_, min_len);
+  if (comp < 0) return true;
+  if (comp > 0) return false;
+  return (this_len < other_len);
+}
+
+bool Value::CZString::operator==(const CZString& other) const {
+  if (!cstr_) return index_ == other.index_;
+  //return strcmp(cstr_, other.cstr_) == 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  if (this_len != other_len) return false;
+  int comp = memcmp(this->cstr_, other.cstr_, this_len);
+  return comp == 0;
+}
+
+ArrayIndex Value::CZString::index() const { return index_; }
+
+//const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value(ValueType vtype) {
+  initBasic(vtype);
+  switch (vtype) {
+  case nullValue:
+    break;
+  case intValue:
+  case uintValue:
+    value_.int_ = 0;
+    break;
+  case realValue:
+    value_.real_ = 0.0;
+    break;
+  case stringValue:
+    value_.string_ = 0;
+    break;
+  case arrayValue:
+  case objectValue:
+    value_.map_ = new ObjectValues();
+    break;
+  case booleanValue:
+    value_.bool_ = false;
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+}
+
+Value::Value(Int value) {
+  initBasic(intValue);
+  value_.int_ = value;
+}
+
+Value::Value(UInt value) {
+  initBasic(uintValue);
+  value_.uint_ = value;
+}
+#if defined(JSON_HAS_INT64)
+Value::Value(Int64 value) {
+  initBasic(intValue);
+  value_.int_ = value;
+}
+Value::Value(UInt64 value) {
+  initBasic(uintValue);
+  value_.uint_ = value;
+}
+#endif // defined(JSON_HAS_INT64)
+
+Value::Value(double value) {
+  initBasic(realValue);
+  value_.real_ = value;
+}
+
+Value::Value(const char* value) {
+  initBasic(stringValue, true);
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+}
+
+Value::Value(const char* beginValue, const char* endValue) {
+  initBasic(stringValue, true);
+  value_.string_ =
+      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+}
+
+Value::Value(const std::string& value) {
+  initBasic(stringValue, true);
+  value_.string_ =
+      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+}
+
+Value::Value(const StaticString& value) {
+  initBasic(stringValue);
+  value_.string_ = const_cast<char*>(value.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value::Value(const CppTL::ConstString& value) {
+  initBasic(stringValue, true);
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
+}
+#endif
+
+Value::Value(bool value) {
+  initBasic(booleanValue);
+  value_.bool_ = value;
+}
+
+Value::Value(Value const& other)
+    : type_(other.type_), allocated_(false)
+      ,
+      comments_(0), start_(other.start_), limit_(other.limit_)
+{
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+    value_ = other.value_;
+    break;
+  case stringValue:
+    if (other.value_.string_ && other.allocated_) {
+      unsigned len;
+      char const* str;
+      decodePrefixedString(other.allocated_, other.value_.string_,
+          &len, &str);
+      value_.string_ = duplicateAndPrefixStringValue(str, len);
+      allocated_ = true;
+    } else {
+      value_.string_ = other.value_.string_;
+      allocated_ = false;
+    }
+    break;
+  case arrayValue:
+  case objectValue:
+    value_.map_ = new ObjectValues(*other.value_.map_);
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  if (other.comments_) {
+    comments_ = new CommentInfo[numberOfCommentPlacement];
+    for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
+      const CommentInfo& otherComment = other.comments_[comment];
+      if (otherComment.comment_)
+        comments_[comment].setComment(
+            otherComment.comment_, strlen(otherComment.comment_));
+    }
+  }
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+// Move constructor
+Value::Value(Value&& other) {
+  initBasic(nullValue);
+  swap(other);
+}
+#endif
+
+Value::~Value() {
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+    break;
+  case stringValue:
+    if (allocated_)
+      releaseStringValue(value_.string_);
+    break;
+  case arrayValue:
+  case objectValue:
+    delete value_.map_;
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+
+  if (comments_)
+    delete[] comments_;
+}
+
+Value& Value::operator=(Value other) {
+  swap(other);
+  return *this;
+}
+
+void Value::swapPayload(Value& other) {
+  ValueType temp = type_;
+  type_ = other.type_;
+  other.type_ = temp;
+  std::swap(value_, other.value_);
+  int temp2 = allocated_;
+  allocated_ = other.allocated_;
+  other.allocated_ = temp2 & 0x1;
+}
+
+void Value::swap(Value& other) {
+  swapPayload(other);
+  std::swap(comments_, other.comments_);
+  std::swap(start_, other.start_);
+  std::swap(limit_, other.limit_);
+}
+
+ValueType Value::type() const { return type_; }
+
+int Value::compare(const Value& other) const {
+  if (*this < other)
+    return -1;
+  if (*this > other)
+    return 1;
+  return 0;
+}
+
+bool Value::operator<(const Value& other) const {
+  int typeDelta = type_ - other.type_;
+  if (typeDelta)
+    return typeDelta < 0 ? true : false;
+  switch (type_) {
+  case nullValue:
+    return false;
+  case intValue:
+    return value_.int_ < other.value_.int_;
+  case uintValue:
+    return value_.uint_ < other.value_.uint_;
+  case realValue:
+    return value_.real_ < other.value_.real_;
+  case booleanValue:
+    return value_.bool_ < other.value_.bool_;
+  case stringValue:
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      if (other.value_.string_) return true;
+      else return false;
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    unsigned min_len = std::min(this_len, other_len);
+    int comp = memcmp(this_str, other_str, min_len);
+    if (comp < 0) return true;
+    if (comp > 0) return false;
+    return (this_len < other_len);
+  }
+  case arrayValue:
+  case objectValue: {
+    int delta = int(value_.map_->size() - other.value_.map_->size());
+    if (delta)
+      return delta < 0;
+    return (*value_.map_) < (*other.value_.map_);
+  }
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  return false; // unreachable
+}
+
+bool Value::operator<=(const Value& other) const { return !(other < *this); }
+
+bool Value::operator>=(const Value& other) const { return !(*this < other); }
+
+bool Value::operator>(const Value& other) const { return other < *this; }
+
+bool Value::operator==(const Value& other) const {
+  // if ( type_ != other.type_ )
+  // GCC 2.95.3 says:
+  // attempt to take address of bit-field structure member `Json::Value::type_'
+  // Beats me, but a temp solves the problem.
+  int temp = other.type_;
+  if (type_ != temp)
+    return false;
+  switch (type_) {
+  case nullValue:
+    return true;
+  case intValue:
+    return value_.int_ == other.value_.int_;
+  case uintValue:
+    return value_.uint_ == other.value_.uint_;
+  case realValue:
+    return value_.real_ == other.value_.real_;
+  case booleanValue:
+    return value_.bool_ == other.value_.bool_;
+  case stringValue:
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      return (value_.string_ == other.value_.string_);
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    if (this_len != other_len) return false;
+    int comp = memcmp(this_str, other_str, this_len);
+    return comp == 0;
+  }
+  case arrayValue:
+  case objectValue:
+    return value_.map_->size() == other.value_.map_->size() &&
+           (*value_.map_) == (*other.value_.map_);
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  return false; // unreachable
+}
+
+bool Value::operator!=(const Value& other) const { return !(*this == other); }
+
+const char* Value::asCString() const {
+  JSON_ASSERT_MESSAGE(type_ == stringValue,
+                      "in Json::Value::asCString(): requires stringValue");
+  if (value_.string_ == 0) return 0;
+  unsigned this_len;
+  char const* this_str;
+  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  return this_str;
+}
+
+bool Value::getString(char const** str, char const** cend) const {
+  if (type_ != stringValue) return false;
+  if (value_.string_ == 0) return false;
+  unsigned length;
+  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
+  *cend = *str + length;
+  return true;
+}
+
+std::string Value::asString() const {
+  switch (type_) {
+  case nullValue:
+    return "";
+  case stringValue:
+  {
+    if (value_.string_ == 0) return "";
+    unsigned this_len;
+    char const* this_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    return std::string(this_str, this_len);
+  }
+  case booleanValue:
+    return value_.bool_ ? "true" : "false";
+  case intValue:
+    return valueToString(value_.int_);
+  case uintValue:
+    return valueToString(value_.uint_);
+  case realValue:
+    return valueToString(value_.real_);
+  default:
+    JSON_FAIL_MESSAGE("Type is not convertible to string");
+  }
+}
+
+#ifdef JSON_USE_CPPTL
+CppTL::ConstString Value::asConstString() const {
+  unsigned len;
+  char const* str;
+  decodePrefixedString(allocated_, value_.string_,
+      &len, &str);
+  return CppTL::ConstString(str, len);
+}
+#endif
+
+Value::Int Value::asInt() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+    return Int(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+    return Int(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+                        "double out of Int range");
+    return Int(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to Int.");
+}
+
+Value::UInt Value::asUInt() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+    return UInt(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+    return UInt(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+                        "double out of UInt range");
+    return UInt(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
+}
+
+#if defined(JSON_HAS_INT64)
+
+Value::Int64 Value::asInt64() const {
+  switch (type_) {
+  case intValue:
+    return Int64(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+    return Int64(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+                        "double out of Int64 range");
+    return Int64(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
+}
+
+Value::UInt64 Value::asUInt64() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+    return UInt64(value_.int_);
+  case uintValue:
+    return UInt64(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+                        "double out of UInt64 range");
+    return UInt64(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
+}
+#endif // if defined(JSON_HAS_INT64)
+
+LargestInt Value::asLargestInt() const {
+#if defined(JSON_NO_INT64)
+  return asInt();
+#else
+  return asInt64();
+#endif
+}
+
+LargestUInt Value::asLargestUInt() const {
+#if defined(JSON_NO_INT64)
+  return asUInt();
+#else
+  return asUInt64();
+#endif
+}
+
+double Value::asDouble() const {
+  switch (type_) {
+  case intValue:
+    return static_cast<double>(value_.int_);
+  case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return static_cast<double>(value_.uint_);
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+  case realValue:
+    return value_.real_;
+  case nullValue:
+    return 0.0;
+  case booleanValue:
+    return value_.bool_ ? 1.0 : 0.0;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to double.");
+}
+
+float Value::asFloat() const {
+  switch (type_) {
+  case intValue:
+    return static_cast<float>(value_.int_);
+  case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return static_cast<float>(value_.uint_);
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+  case realValue:
+    return static_cast<float>(value_.real_);
+  case nullValue:
+    return 0.0;
+  case booleanValue:
+    return value_.bool_ ? 1.0f : 0.0f;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to float.");
+}
+
+bool Value::asBool() const {
+  switch (type_) {
+  case booleanValue:
+    return value_.bool_;
+  case nullValue:
+    return false;
+  case intValue:
+    return value_.int_ ? true : false;
+  case uintValue:
+    return value_.uint_ ? true : false;
+  case realValue:
+    // This is kind of strange. Not recommended.
+    return (value_.real_ != 0.0) ? true : false;
+  default:
+    break;
+  }
+  JSON_FAIL_MESSAGE("Value is not convertible to bool.");
+}
+
+bool Value::isConvertibleTo(ValueType other) const {
+  switch (other) {
+  case nullValue:
+    return (isNumeric() && asDouble() == 0.0) ||
+           (type_ == booleanValue && value_.bool_ == false) ||
+           (type_ == stringValue && asString() == "") ||
+           (type_ == arrayValue && value_.map_->size() == 0) ||
+           (type_ == objectValue && value_.map_->size() == 0) ||
+           type_ == nullValue;
+  case intValue:
+    return isInt() ||
+           (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
+           type_ == booleanValue || type_ == nullValue;
+  case uintValue:
+    return isUInt() ||
+           (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
+           type_ == booleanValue || type_ == nullValue;
+  case realValue:
+    return isNumeric() || type_ == booleanValue || type_ == nullValue;
+  case booleanValue:
+    return isNumeric() || type_ == booleanValue || type_ == nullValue;
+  case stringValue:
+    return isNumeric() || type_ == booleanValue || type_ == stringValue ||
+           type_ == nullValue;
+  case arrayValue:
+    return type_ == arrayValue || type_ == nullValue;
+  case objectValue:
+    return type_ == objectValue || type_ == nullValue;
+  }
+  JSON_ASSERT_UNREACHABLE;
+  return false;
+}
+
+/// Number of values in array or object
+ArrayIndex Value::size() const {
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+  case stringValue:
+    return 0;
+  case arrayValue: // size of the array is highest index + 1
+    if (!value_.map_->empty()) {
+      ObjectValues::const_iterator itLast = value_.map_->end();
+      --itLast;
+      return (*itLast).first.index() + 1;
+    }
+    return 0;
+  case objectValue:
+    return ArrayIndex(value_.map_->size());
+  }
+  JSON_ASSERT_UNREACHABLE;
+  return 0; // unreachable;
+}
+
+bool Value::empty() const {
+  if (isNull() || isArray() || isObject())
+    return size() == 0u;
+  else
+    return false;
+}
+
+bool Value::operator!() const { return isNull(); }
+
+void Value::clear() {
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
+                          type_ == objectValue,
+                      "in Json::Value::clear(): requires complex value");
+  start_ = 0;
+  limit_ = 0;
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    value_.map_->clear();
+    break;
+  default:
+    break;
+  }
+}
+
+void Value::resize(ArrayIndex newSize) {
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+                      "in Json::Value::resize(): requires arrayValue");
+  if (type_ == nullValue)
+    *this = Value(arrayValue);
+  ArrayIndex oldSize = size();
+  if (newSize == 0)
+    clear();
+  else if (newSize > oldSize)
+    (*this)[newSize - 1];
+  else {
+    for (ArrayIndex index = newSize; index < oldSize; ++index) {
+      value_.map_->erase(index);
+    }
+    assert(size() == newSize);
+  }
+}
+
+Value& Value::operator[](ArrayIndex index) {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == arrayValue,
+      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+  if (type_ == nullValue)
+    *this = Value(arrayValue);
+  CZString key(index);
+  ObjectValues::iterator it = value_.map_->lower_bound(key);
+  if (it != value_.map_->end() && (*it).first == key)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(key, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  return (*it).second;
+}
+
+Value& Value::operator[](int index) {
+  JSON_ASSERT_MESSAGE(
+      index >= 0,
+      "in Json::Value::operator[](int index): index cannot be negative");
+  return (*this)[ArrayIndex(index)];
+}
+
+const Value& Value::operator[](ArrayIndex index) const {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == arrayValue,
+      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+  if (type_ == nullValue)
+    return nullRef;
+  CZString key(index);
+  ObjectValues::const_iterator it = value_.map_->find(key);
+  if (it == value_.map_->end())
+    return nullRef;
+  return (*it).second;
+}
+
+const Value& Value::operator[](int index) const {
+  JSON_ASSERT_MESSAGE(
+      index >= 0,
+      "in Json::Value::operator[](int index) const: index cannot be negative");
+  return (*this)[ArrayIndex(index)];
+}
+
+void Value::initBasic(ValueType vtype, bool allocated) {
+  type_ = vtype;
+  allocated_ = allocated;
+  comments_ = 0;
+  start_ = 0;
+  limit_ = 0;
+}
+
+// Access an object value by name, create a null member if it does not exist.
+// @pre Type of '*this' is object or null.
+// @param key is null-terminated.
+Value& Value::resolveReference(const char* key) {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::resolveReference(): requires objectValue");
+  if (type_ == nullValue)
+    *this = Value(objectValue);
+  CZString actualKey(
+      key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
+  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  if (it != value_.map_->end() && (*it).first == actualKey)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(actualKey, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  Value& value = (*it).second;
+  return value;
+}
+
+// @param key is not null-terminated.
+Value& Value::resolveReference(char const* key, char const* cend)
+{
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::resolveReference(key, end): requires objectValue");
+  if (type_ == nullValue)
+    *this = Value(objectValue);
+  CZString actualKey(
+      key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
+  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  if (it != value_.map_->end() && (*it).first == actualKey)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(actualKey, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  Value& value = (*it).second;
+  return value;
+}
+
+Value Value::get(ArrayIndex index, const Value& defaultValue) const {
+  const Value* value = &((*this)[index]);
+  return value == &nullRef ? defaultValue : *value;
+}
+
+bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
+
+Value const* Value::find(char const* key, char const* cend) const
+{
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
+  if (type_ == nullValue) return NULL;
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+  ObjectValues::const_iterator it = value_.map_->find(actualKey);
+  if (it == value_.map_->end()) return NULL;
+  return &(*it).second;
+}
+const Value& Value::operator[](const char* key) const
+{
+  Value const* found = find(key, key + strlen(key));
+  if (!found) return nullRef;
+  return *found;
+}
+Value const& Value::operator[](std::string const& key) const
+{
+  Value const* found = find(key.data(), key.data() + key.length());
+  if (!found) return nullRef;
+  return *found;
+}
+
+Value& Value::operator[](const char* key) {
+  return resolveReference(key, key + strlen(key));
+}
+
+Value& Value::operator[](const std::string& key) {
+  return resolveReference(key.data(), key.data() + key.length());
+}
+
+Value& Value::operator[](const StaticString& key) {
+  return resolveReference(key.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value& Value::operator[](const CppTL::ConstString& key) {
+  return resolveReference(key.c_str(), key.end_c_str());
+}
+Value const& Value::operator[](CppTL::ConstString const& key) const
+{
+  Value const* found = find(key.c_str(), key.end_c_str());
+  if (!found) return nullRef;
+  return *found;
+}
+#endif
+
+Value& Value::append(const Value& value) { return (*this)[size()] = value; }
+
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
+{
+  Value const* found = find(key, cend);
+  return !found ? defaultValue : *found;
+}
+Value Value::get(char const* key, Value const& defaultValue) const
+{
+  return get(key, key + strlen(key), defaultValue);
+}
+Value Value::get(std::string const& key, Value const& defaultValue) const
+{
+  return get(key.data(), key.data() + key.length(), defaultValue);
+}
+
+
+bool Value::removeMember(const char* key, const char* cend, Value* removed)
+{
+  if (type_ != objectValue) {
+    return false;
+  }
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+  ObjectValues::iterator it = value_.map_->find(actualKey);
+  if (it == value_.map_->end())
+    return false;
+  *removed = it->second;
+  value_.map_->erase(it);
+  return true;
+}
+bool Value::removeMember(const char* key, Value* removed)
+{
+  return removeMember(key, key + strlen(key), removed);
+}
+bool Value::removeMember(std::string const& key, Value* removed)
+{
+  return removeMember(key.data(), key.data() + key.length(), removed);
+}
+Value Value::removeMember(const char* key)
+{
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+                      "in Json::Value::removeMember(): requires objectValue");
+  if (type_ == nullValue)
+    return nullRef;
+
+  Value removed;  // null
+  removeMember(key, key + strlen(key), &removed);
+  return removed; // still null if removeMember() did nothing
+}
+Value Value::removeMember(const std::string& key)
+{
+  return removeMember(key.c_str());
+}
+
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+  if (type_ != arrayValue) {
+    return false;
+  }
+  CZString key(index);
+  ObjectValues::iterator it = value_.map_->find(key);
+  if (it == value_.map_->end()) {
+    return false;
+  }
+  *removed = it->second;
+  ArrayIndex oldSize = size();
+  // shift left all items left, into the place of the "removed"
+  for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+    CZString keey(i);
+    (*value_.map_)[keey] = (*this)[i + 1];
+  }
+  // erase the last one ("leftover")
+  CZString keyLast(oldSize - 1);
+  ObjectValues::iterator itLast = value_.map_->find(keyLast);
+  value_.map_->erase(itLast);
+  return true;
+}
+
+#ifdef JSON_USE_CPPTL
+Value Value::get(const CppTL::ConstString& key,
+                 const Value& defaultValue) const {
+  return get(key.c_str(), key.end_c_str(), defaultValue);
+}
+#endif
+
+bool Value::isMember(char const* key, char const* cend) const
+{
+  Value const* value = find(key, cend);
+  return NULL != value;
+}
+bool Value::isMember(char const* key) const
+{
+  return isMember(key, key + strlen(key));
+}
+bool Value::isMember(std::string const& key) const
+{
+  return isMember(key.data(), key.data() + key.length());
+}
+
+#ifdef JSON_USE_CPPTL
+bool Value::isMember(const CppTL::ConstString& key) const {
+  return isMember(key.c_str(), key.end_c_str());
+}
+#endif
+
+Value::Members Value::getMemberNames() const {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::getMemberNames(), value must be objectValue");
+  if (type_ == nullValue)
+    return Value::Members();
+  Members members;
+  members.reserve(value_.map_->size());
+  ObjectValues::const_iterator it = value_.map_->begin();
+  ObjectValues::const_iterator itEnd = value_.map_->end();
+  for (; it != itEnd; ++it) {
+    members.push_back(std::string((*it).first.data(),
+                                  (*it).first.length()));
+  }
+  return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+// EnumMemberNames
+// Value::enumMemberNames() const
+//{
+//   if ( type_ == objectValue )
+//   {
+//      return CppTL::Enum::any(  CppTL::Enum::transform(
+//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+//         MemberNamesTransform() ) );
+//   }
+//   return EnumMemberNames();
+//}
+//
+//
+// EnumValues
+// Value::enumValues() const
+//{
+//   if ( type_ == objectValue  ||  type_ == arrayValue )
+//      return CppTL::Enum::anyValues( *(value_.map_),
+//                                     CppTL::Type<const Value &>() );
+//   return EnumValues();
+//}
+//
+//# endif
+
+static bool IsIntegral(double d) {
+  double integral_part;
+  return modf(d, &integral_part) == 0.0;
+}
+
+bool Value::isNull() const { return type_ == nullValue; }
+
+bool Value::isBool() const { return type_ == booleanValue; }
+
+bool Value::isInt() const {
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= minInt && value_.int_ <= maxInt;
+  case uintValue:
+    return value_.uint_ <= UInt(maxInt);
+  case realValue:
+    return value_.real_ >= minInt && value_.real_ <= maxInt &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+  return false;
+}
+
+bool Value::isUInt() const {
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+  case uintValue:
+    return value_.uint_ <= maxUInt;
+  case realValue:
+    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+  return false;
+}
+
+bool Value::isInt64() const {
+#if defined(JSON_HAS_INT64)
+  switch (type_) {
+  case intValue:
+    return true;
+  case uintValue:
+    return value_.uint_ <= UInt64(maxInt64);
+  case realValue:
+    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+    // require the value to be strictly less than the limit.
+    return value_.real_ >= double(minInt64) &&
+           value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
+  default:
+    break;
+  }
+#endif // JSON_HAS_INT64
+  return false;
+}
+
+bool Value::isUInt64() const {
+#if defined(JSON_HAS_INT64)
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= 0;
+  case uintValue:
+    return true;
+  case realValue:
+    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+    // require the value to be strictly less than the limit.
+    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+#endif // JSON_HAS_INT64
+  return false;
+}
+
+bool Value::isIntegral() const {
+#if defined(JSON_HAS_INT64)
+  return isInt64() || isUInt64();
+#else
+  return isInt() || isUInt();
+#endif
+}
+
+bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
+
+bool Value::isNumeric() const { return isIntegral() || isDouble(); }
+
+bool Value::isString() const { return type_ == stringValue; }
+
+bool Value::isArray() const { return type_ == arrayValue; }
+
+bool Value::isObject() const { return type_ == objectValue; }
+
+void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
+  if (!comments_)
+    comments_ = new CommentInfo[numberOfCommentPlacement];
+  if ((len > 0) && (comment[len-1] == '\n')) {
+    // Always discard trailing newline, to aid indentation.
+    len -= 1;
+  }
+  comments_[placement].setComment(comment, len);
+}
+
+void Value::setComment(const char* comment, CommentPlacement placement) {
+  setComment(comment, strlen(comment), placement);
+}
+
+void Value::setComment(const std::string& comment, CommentPlacement placement) {
+  setComment(comment.c_str(), comment.length(), placement);
+}
+
+bool Value::hasComment(CommentPlacement placement) const {
+  return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+std::string Value::getComment(CommentPlacement placement) const {
+  if (hasComment(placement))
+    return comments_[placement].comment_;
+  return "";
+}
+
+void Value::setOffsetStart(size_t start) { start_ = start; }
+
+void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
+
+size_t Value::getOffsetStart() const { return start_; }
+
+size_t Value::getOffsetLimit() const { return limit_; }
+
+std::string Value::toStyledString() const {
+  StyledWriter writer;
+  return writer.write(*this);
+}
+
+Value::const_iterator Value::begin() const {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return const_iterator(value_.map_->begin());
+    break;
+  default:
+    break;
+  }
+  return const_iterator();
+}
+
+Value::const_iterator Value::end() const {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return const_iterator(value_.map_->end());
+    break;
+  default:
+    break;
+  }
+  return const_iterator();
+}
+
+Value::iterator Value::begin() {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return iterator(value_.map_->begin());
+    break;
+  default:
+    break;
+  }
+  return iterator();
+}
+
+Value::iterator Value::end() {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return iterator(value_.map_->end());
+    break;
+  default:
+    break;
+  }
+  return iterator();
+}
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+
+PathArgument::PathArgument(ArrayIndex index)
+    : key_(), index_(index), kind_(kindIndex) {}
+
+PathArgument::PathArgument(const char* key)
+    : key_(key), index_(), kind_(kindKey) {}
+
+PathArgument::PathArgument(const std::string& key)
+    : key_(key.c_str()), index_(), kind_(kindKey) {}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path(const std::string& path,
+           const PathArgument& a1,
+           const PathArgument& a2,
+           const PathArgument& a3,
+           const PathArgument& a4,
+           const PathArgument& a5) {
+  InArgs in;
+  in.push_back(&a1);
+  in.push_back(&a2);
+  in.push_back(&a3);
+  in.push_back(&a4);
+  in.push_back(&a5);
+  makePath(path, in);
+}
+
+void Path::makePath(const std::string& path, const InArgs& in) {
+  const char* current = path.c_str();
+  const char* end = current + path.length();
+  InArgs::const_iterator itInArg = in.begin();
+  while (current != end) {
+    if (*current == '[') {
+      ++current;
+      if (*current == '%')
+        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+      else {
+        ArrayIndex index = 0;
+        for (; current != end && *current >= '0' && *current <= '9'; ++current)
+          index = index * 10 + ArrayIndex(*current - '0');
+        args_.push_back(index);
+      }
+      if (current == end || *current++ != ']')
+        invalidPath(path, int(current - path.c_str()));
+    } else if (*current == '%') {
+      addPathInArg(path, in, itInArg, PathArgument::kindKey);
+      ++current;
+    } else if (*current == '.') {
+      ++current;
+    } else {
+      const char* beginName = current;
+      while (current != end && !strchr("[.", *current))
+        ++current;
+      args_.push_back(std::string(beginName, current));
+    }
+  }
+}
+
+void Path::addPathInArg(const std::string& /*path*/,
+                        const InArgs& in,
+                        InArgs::const_iterator& itInArg,
+                        PathArgument::Kind kind) {
+  if (itInArg == in.end()) {
+    // Error: missing argument %d
+  } else if ((*itInArg)->kind_ != kind) {
+    // Error: bad argument type
+  } else {
+    args_.push_back(**itInArg);
+  }
+}
+
+void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
+  // Error: invalid path.
+}
+
+const Value& Path::resolve(const Value& root) const {
+  const Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
+        // Error: unable to resolve path (array value expected at position...
+      }
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject()) {
+        // Error: unable to resolve path (object value expected at position...)
+      }
+      node = &((*node)[arg.key_]);
+      if (node == &Value::nullRef) {
+        // Error: unable to resolve path (object has no member named '' at
+        // position...)
+      }
+    }
+  }
+  return *node;
+}
+
+Value Path::resolve(const Value& root, const Value& defaultValue) const {
+  const Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray() || !node->isValidIndex(arg.index_))
+        return defaultValue;
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject())
+        return defaultValue;
+      node = &((*node)[arg.key_]);
+      if (node == &Value::nullRef)
+        return defaultValue;
+    }
+  }
+  return *node;
+}
+
+Value& Path::make(Value& root) const {
+  Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray()) {
+        // Error: node is not an array at position ...
+      }
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject()) {
+        // Error: node is not an object at position...
+      }
+      node = &((*node)[arg.key_]);
+    }
+  }
+  return *node;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/writer.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <iomanip>
+#include <memory>
+#include <sstream>
+#include <utility>
+#include <set>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#include <float.h>
+#define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
+#elif defined(_AIX)
+#if !defined(isfinite)
+#include <math.h>
+#define isfinite finite
+#endif
+#elif defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+                     _Isfinitef(x) : _IsFinite(x)))
+#else
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
+#else
+#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
+#define isfinite std::isfinite
+#endif
+#endif
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#define snprintf std::snprintf
+#endif
+
+#if defined(__BORLANDC__)  
+#include <float.h>
+#define isfinite _finite
+#define snprintf _snprintf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+#else
+typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
+#endif
+
+static bool containsControlCharacter(const char* str) {
+  while (*str) {
+    if (isControlCharacter(*(str++)))
+      return true;
+  }
+  return false;
+}
+
+static bool containsControlCharacter0(const char* str, unsigned len) {
+  char const* end = str + len;
+  while (end != str) {
+    if (isControlCharacter(*str) || 0==*str)
+      return true;
+    ++str;
+  }
+  return false;
+}
+
+std::string valueToString(LargestInt value) {
+  UIntToStringBuffer buffer;
+  char* current = buffer + sizeof(buffer);
+  if (value == Value::minLargestInt) {
+    uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
+    *--current = '-';
+  } else if (value < 0) {
+    uintToString(LargestUInt(-value), current);
+    *--current = '-';
+  } else {
+    uintToString(LargestUInt(value), current);
+  }
+  assert(current >= buffer);
+  return current;
+}
+
+std::string valueToString(LargestUInt value) {
+  UIntToStringBuffer buffer;
+  char* current = buffer + sizeof(buffer);
+  uintToString(value, current);
+  assert(current >= buffer);
+  return current;
+}
+
+#if defined(JSON_HAS_INT64)
+
+std::string valueToString(Int value) {
+  return valueToString(LargestInt(value));
+}
+
+std::string valueToString(UInt value) {
+  return valueToString(LargestUInt(value));
+}
+
+#endif // # if defined(JSON_HAS_INT64)
+
+std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) {
+  // Allocate a buffer that is more than large enough to store the 16 digits of
+  // precision requested below.
+  char buffer[32];
+  int len = -1;
+
+  char formatString[6];
+  sprintf(formatString, "%%.%dg", precision);
+
+  // Print into the buffer. We need not request the alternative representation
+  // that always has a decimal point because JSON doesn't distingish the
+  // concepts of reals and integers.
+  if (isfinite(value)) {
+    len = snprintf(buffer, sizeof(buffer), formatString, value);
+  } else {
+    // IEEE standard states that NaN values will not compare to themselves
+    if (value != value) {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+    } else if (value < 0) {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
+    } else {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
+    }
+    // For those, we do not need to call fixNumLoc, but it is fast.
+  }
+  assert(len >= 0);
+  fixNumericLocale(buffer, buffer + len);
+  return buffer;
+}
+
+std::string valueToString(double value) { return valueToString(value, false, 17); }
+
+std::string valueToString(bool value) { return value ? "true" : "false"; }
+
+std::string valueToQuotedString(const char* value) {
+  if (value == NULL)
+    return "";
+  // Not sure how to handle unicode...
+  if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
+      !containsControlCharacter(value))
+    return std::string("\"") + value + "\"";
+  // We have to walk value and escape any special characters.
+  // Appending to std::string is not efficient, but this should be rare.
+  // (Note: forward slashes are *not* rare, but I am not escaping them.)
+  std::string::size_type maxsize =
+      strlen(value) * 2 + 3; // allescaped+quotes+NULL
+  std::string result;
+  result.reserve(maxsize); // to avoid lots of mallocs
+  result += "\"";
+  for (const char* c = value; *c != 0; ++c) {
+    switch (*c) {
+    case '\"':
+      result += "\\\"";
+      break;
+    case '\\':
+      result += "\\\\";
+      break;
+    case '\b':
+      result += "\\b";
+      break;
+    case '\f':
+      result += "\\f";
+      break;
+    case '\n':
+      result += "\\n";
+      break;
+    case '\r':
+      result += "\\r";
+      break;
+    case '\t':
+      result += "\\t";
+      break;
+    // case '/':
+    // Even though \/ is considered a legal escape in JSON, a bare
+    // slash is also legal, so I see no reason to escape it.
+    // (I hope I am not misunderstanding something.
+    // blep notes: actually escaping \/ may be useful in javascript to avoid </
+    // sequence.
+    // Should add a flag to allow this compatibility mode and prevent this
+    // sequence from occurring.
+    default:
+      if (isControlCharacter(*c)) {
+        std::ostringstream oss;
+        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+            << std::setw(4) << static_cast<int>(*c);
+        result += oss.str();
+      } else {
+        result += *c;
+      }
+      break;
+    }
+  }
+  result += "\"";
+  return result;
+}
+
+// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
+static char const* strnpbrk(char const* s, char const* accept, size_t n) {
+  assert((s || !n) && accept);
+
+  char const* const end = s + n;
+  for (char const* cur = s; cur < end; ++cur) {
+    int const c = *cur;
+    for (char const* a = accept; *a; ++a) {
+      if (*a == c) {
+        return cur;
+      }
+    }
+  }
+  return NULL;
+}
+static std::string valueToQuotedStringN(const char* value, unsigned length) {
+  if (value == NULL)
+    return "";
+  // Not sure how to handle unicode...
+  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
+      !containsControlCharacter0(value, length))
+    return std::string("\"") + value + "\"";
+  // We have to walk value and escape any special characters.
+  // Appending to std::string is not efficient, but this should be rare.
+  // (Note: forward slashes are *not* rare, but I am not escaping them.)
+  std::string::size_type maxsize =
+      length * 2 + 3; // allescaped+quotes+NULL
+  std::string result;
+  result.reserve(maxsize); // to avoid lots of mallocs
+  result += "\"";
+  char const* end = value + length;
+  for (const char* c = value; c != end; ++c) {
+    switch (*c) {
+    case '\"':
+      result += "\\\"";
+      break;
+    case '\\':
+      result += "\\\\";
+      break;
+    case '\b':
+      result += "\\b";
+      break;
+    case '\f':
+      result += "\\f";
+      break;
+    case '\n':
+      result += "\\n";
+      break;
+    case '\r':
+      result += "\\r";
+      break;
+    case '\t':
+      result += "\\t";
+      break;
+    // case '/':
+    // Even though \/ is considered a legal escape in JSON, a bare
+    // slash is also legal, so I see no reason to escape it.
+    // (I hope I am not misunderstanding something.)
+    // blep notes: actually escaping \/ may be useful in javascript to avoid </
+    // sequence.
+    // Should add a flag to allow this compatibility mode and prevent this
+    // sequence from occurring.
+    default:
+      if ((isControlCharacter(*c)) || (*c == 0)) {
+        std::ostringstream oss;
+        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+            << std::setw(4) << static_cast<int>(*c);
+        result += oss.str();
+      } else {
+        result += *c;
+      }
+      break;
+    }
+  }
+  result += "\"";
+  return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer() {}
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+    : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+      omitEndingLineFeed_(false) {}
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+
+std::string FastWriter::write(const Value& root) {
+  document_ = "";
+  writeValue(root);
+  if (!omitEndingLineFeed_)
+    document_ += "\n";
+  return document_;
+}
+
+void FastWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    if (!dropNullPlaceholders_)
+      document_ += "null";
+    break;
+  case intValue:
+    document_ += valueToString(value.asLargestInt());
+    break;
+  case uintValue:
+    document_ += valueToString(value.asLargestUInt());
+    break;
+  case realValue:
+    document_ += valueToString(value.asDouble());
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+    break;
+  }
+  case booleanValue:
+    document_ += valueToString(value.asBool());
+    break;
+  case arrayValue: {
+    document_ += '[';
+    int size = value.size();
+    for (int index = 0; index < size; ++index) {
+      if (index > 0)
+        document_ += ',';
+      writeValue(value[index]);
+    }
+    document_ += ']';
+  } break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    document_ += '{';
+    for (Value::Members::iterator it = members.begin(); it != members.end();
+         ++it) {
+      const std::string& name = *it;
+      if (it != members.begin())
+        document_ += ',';
+      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
+      document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+      writeValue(value[name]);
+    }
+    document_ += '}';
+  } break;
+  }
+}
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+    : rightMargin_(74), indentSize_(3), addChildValues_() {}
+
+std::string StyledWriter::write(const Value& root) {
+  document_ = "";
+  addChildValues_ = false;
+  indentString_ = "";
+  writeCommentBeforeValue(root);
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  document_ += "\n";
+  return document_;
+}
+
+void StyledWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue("null");
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble()));
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        const std::string& name = *it;
+        const Value& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedString(name.c_str()));
+        document_ += " : ";
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        document_ += ',';
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void StyledWriter::writeArrayValue(const Value& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isArrayMultiLine = isMultineArray(value);
+    if (isArrayMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        const Value& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          writeIndent();
+          writeValue(childValue);
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        document_ += ',';
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      document_ += "[ ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          document_ += ", ";
+        document_ += childValues_[index];
+      }
+      document_ += " ]";
+    }
+  }
+}
+
+bool StyledWriter::isMultineArray(const Value& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    const Value& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void StyledWriter::pushValue(const std::string& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    document_ += value;
+}
+
+void StyledWriter::writeIndent() {
+  if (!document_.empty()) {
+    char last = document_[document_.length() - 1];
+    if (last == ' ') // already indented
+      return;
+    if (last != '\n') // Comments may add new-line
+      document_ += '\n';
+  }
+  document_ += indentString_;
+}
+
+void StyledWriter::writeWithIndent(const std::string& value) {
+  writeIndent();
+  document_ += value;
+}
+
+void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
+
+void StyledWriter::unindent() {
+  assert(int(indentString_.size()) >= indentSize_);
+  indentString_.resize(indentString_.size() - indentSize_);
+}
+
+void StyledWriter::writeCommentBeforeValue(const Value& root) {
+  if (!root.hasComment(commentBefore))
+    return;
+
+  document_ += "\n";
+  writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    document_ += *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      writeIndent();
+    ++iter;
+  }
+
+  // Comments are stripped of trailing newlines, so add one here
+  document_ += "\n";
+}
+
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+  if (root.hasComment(commentAfterOnSameLine))
+    document_ += " " + root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    document_ += "\n";
+    document_ += root.getComment(commentAfter);
+    document_ += "\n";
+  }
+}
+
+bool StyledWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter(std::string indentation)
+    : document_(NULL), rightMargin_(74), indentation_(indentation),
+      addChildValues_() {}
+
+void StyledStreamWriter::write(std::ostream& out, const Value& root) {
+  document_ = &out;
+  addChildValues_ = false;
+  indentString_ = "";
+  indented_ = true;
+  writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  *document_ << "\n";
+  document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue("null");
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble()));
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        const std::string& name = *it;
+        const Value& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedString(name.c_str()));
+        *document_ << " : ";
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *document_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void StyledStreamWriter::writeArrayValue(const Value& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isArrayMultiLine = isMultineArray(value);
+    if (isArrayMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        const Value& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          if (!indented_) writeIndent();
+          indented_ = true;
+          writeValue(childValue);
+          indented_ = false;
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *document_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      *document_ << "[ ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          *document_ << ", ";
+        *document_ << childValues_[index];
+      }
+      *document_ << " ]";
+    }
+  }
+}
+
+bool StyledStreamWriter::isMultineArray(const Value& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    const Value& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void StyledStreamWriter::pushValue(const std::string& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    *document_ << value;
+}
+
+void StyledStreamWriter::writeIndent() {
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
+  *document_ << '\n' << indentString_;
+}
+
+void StyledStreamWriter::writeWithIndent(const std::string& value) {
+  if (!indented_) writeIndent();
+  *document_ << value;
+  indented_ = false;
+}
+
+void StyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void StyledStreamWriter::unindent() {
+  assert(indentString_.size() >= indentation_.size());
+  indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+  if (!root.hasComment(commentBefore))
+    return;
+
+  if (!indented_) writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *document_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would include newline
+      *document_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
+}
+
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+  if (root.hasComment(commentAfterOnSameLine))
+    *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    writeIndent();
+    *document_ << root.getComment(commentAfter);
+  }
+  indented_ = false;
+}
+
+bool StyledStreamWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+//////////////////////////
+// BuiltStyledStreamWriter
+
+/// Scoped enums are not available until C++11.
+struct CommentStyle {
+  /// Decide whether to write comments.
+  enum Enum {
+    None,  ///< Drop all comments.
+    Most,  ///< Recover odd behavior of previous versions (not implemented yet).
+    All  ///< Keep all comments.
+  };
+};
+
+struct BuiltStyledStreamWriter : public StreamWriter
+{
+  BuiltStyledStreamWriter(
+      std::string const& indentation,
+      CommentStyle::Enum cs,
+      std::string const& colonSymbol,
+      std::string const& nullSymbol,
+      std::string const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision);
+  int write(Value const& root, std::ostream* sout) override;
+private:
+  void writeValue(Value const& value);
+  void writeArrayValue(Value const& value);
+  bool isMultineArray(Value const& value);
+  void pushValue(std::string const& value);
+  void writeIndent();
+  void writeWithIndent(std::string const& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(Value const& root);
+  void writeCommentAfterValueOnSameLine(Value const& root);
+  static bool hasCommentForValue(const Value& value);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::string indentString_;
+  int rightMargin_;
+  std::string indentation_;
+  CommentStyle::Enum cs_;
+  std::string colonSymbol_;
+  std::string nullSymbol_;
+  std::string endingLineFeedSymbol_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+  bool useSpecialFloats_ : 1;
+  unsigned int precision_;
+};
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(
+      std::string const& indentation,
+      CommentStyle::Enum cs,
+      std::string const& colonSymbol,
+      std::string const& nullSymbol,
+      std::string const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision)
+  : rightMargin_(74)
+  , indentation_(indentation)
+  , cs_(cs)
+  , colonSymbol_(colonSymbol)
+  , nullSymbol_(nullSymbol)
+  , endingLineFeedSymbol_(endingLineFeedSymbol)
+  , addChildValues_(false)
+  , indented_(false)
+  , useSpecialFloats_(useSpecialFloats)
+  , precision_(precision)
+{
+}
+int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
+{
+  sout_ = sout;
+  addChildValues_ = false;
+  indented_ = true;
+  indentString_ = "";
+  writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  *sout_ << endingLineFeedSymbol_;
+  sout_ = NULL;
+  return 0;
+}
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue(nullSymbol_);
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+    break;
+  case stringValue:
+  {
+    // Is NULL is possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        std::string const& name = *it;
+        Value const& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+        *sout_ << colonSymbol_;
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+    if (isMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        Value const& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          if (!indented_) writeIndent();
+          indented_ = true;
+          writeValue(childValue);
+          indented_ = false;
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      *sout_ << "[";
+      if (!indentation_.empty()) *sout_ << " ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          *sout_ << ", ";
+        *sout_ << childValues_[index];
+      }
+      if (!indentation_.empty()) *sout_ << " ";
+      *sout_ << "]";
+    }
+  }
+}
+
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    Value const& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void BuiltStyledStreamWriter::pushValue(std::string const& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    *sout_ << value;
+}
+
+void BuiltStyledStreamWriter::writeIndent() {
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
+
+  if (!indentation_.empty()) {
+    // In this case, drop newlines too.
+    *sout_ << '\n' << indentString_;
+  }
+}
+
+void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
+  if (!indented_) writeIndent();
+  *sout_ << value;
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void BuiltStyledStreamWriter::unindent() {
+  assert(indentString_.size() >= indentation_.size());
+  indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (!root.hasComment(commentBefore))
+    return;
+
+  if (!indented_) writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *sout_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would write extra newline
+      *sout_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (root.hasComment(commentAfterOnSameLine))
+    *sout_ << " " + root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    writeIndent();
+    *sout_ << root.getComment(commentAfter);
+  }
+}
+
+// static
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+///////////////
+// StreamWriter
+
+StreamWriter::StreamWriter()
+    : sout_(NULL)
+{
+}
+StreamWriter::~StreamWriter()
+{
+}
+StreamWriter::Factory::~Factory()
+{}
+StreamWriterBuilder::StreamWriterBuilder()
+{
+  setDefaults(&settings_);
+}
+StreamWriterBuilder::~StreamWriterBuilder()
+{}
+StreamWriter* StreamWriterBuilder::newStreamWriter() const
+{
+  std::string indentation = settings_["indentation"].asString();
+  std::string cs_str = settings_["commentStyle"].asString();
+  bool eyc = settings_["enableYAMLCompatibility"].asBool();
+  bool dnp = settings_["dropNullPlaceholders"].asBool();
+  bool usf = settings_["useSpecialFloats"].asBool(); 
+  unsigned int pre = settings_["precision"].asUInt();
+  CommentStyle::Enum cs = CommentStyle::All;
+  if (cs_str == "All") {
+    cs = CommentStyle::All;
+  } else if (cs_str == "None") {
+    cs = CommentStyle::None;
+  } else {
+    throwRuntimeError("commentStyle must be 'All' or 'None'");
+  }
+  std::string colonSymbol = " : ";
+  if (eyc) {
+    colonSymbol = ": ";
+  } else if (indentation.empty()) {
+    colonSymbol = ":";
+  }
+  std::string nullSymbol = "null";
+  if (dnp) {
+    nullSymbol = "";
+  }
+  if (pre > 17) pre = 17;
+  std::string endingLineFeedSymbol = "";
+  return new BuiltStyledStreamWriter(
+      indentation, cs,
+      colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+}
+static void getValidWriterKeys(std::set<std::string>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("indentation");
+  valid_keys->insert("commentStyle");
+  valid_keys->insert("enableYAMLCompatibility");
+  valid_keys->insert("dropNullPlaceholders");
+  valid_keys->insert("useSpecialFloats");
+  valid_keys->insert("precision");
+}
+bool StreamWriterBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<std::string> valid_keys;
+  getValidWriterKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    std::string const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& StreamWriterBuilder::operator[](std::string key)
+{
+  return settings_[key];
+}
+// static
+void StreamWriterBuilder::setDefaults(Json::Value* settings)
+{
+  //! [StreamWriterBuilderDefaults]
+  (*settings)["commentStyle"] = "All";
+  (*settings)["indentation"] = "\t";
+  (*settings)["enableYAMLCompatibility"] = false;
+  (*settings)["dropNullPlaceholders"] = false;
+  (*settings)["useSpecialFloats"] = false;
+  (*settings)["precision"] = 17;
+  //! [StreamWriterBuilderDefaults]
+}
+
+std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
+  std::ostringstream sout;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
+  return sout.str();
+}
+
+std::ostream& operator<<(std::ostream& sout, Value const& root) {
+  StreamWriterBuilder builder;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
+  return sout;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
diff --git a/src/third_party/protobuf-3/csharp/CHANGES.txt b/src/third_party/protobuf-3/csharp/CHANGES.txt
new file mode 100644
index 0000000..a87cd4d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/CHANGES.txt
@@ -0,0 +1,148 @@
+===============================================================================
+Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet
+(skeet@pobox.com) based on the work of many talented people.
+
+===============================================================================
+RELEASE NOTES - Code imported into Google's main protobuf repository
+===============================================================================
+
+Everything below note this represents history of protobuf-csharp-port project
+before the code was merged into csharp/ subtree of GitHub google/protobuf
+repository.
+Frozen legacy version of the original project is available in
+https://github.com/jskeet/protobuf-csharp-port.
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.555
+===============================================================================
+
+Changes:
+- Upgrade solution format to Visual Studio 2012.
+- Add the ability to print a builder (not just a message)
+- TextGenerator introduces a new overload of PrintTo
+- Munge protoc's error format into a VS-C#-compatible output format.
+- Work to make ProtoGen clone that acts as a protoc.exe plugin.
+- Added the AllowPartiallyTrustedCallers attribute
+- Optimized enum parsing.
+
+Fixes:
+- Fix for bug in limited input stream's Position, Introduced Position on 
+  output stream
+- Fix for writing a character to a JSON output overflows allocated buffer
+- Optimize FromBase64String to return Empty when presented with empty string.
+- Use string.Concat instead of operator to avoid potential import problems
+- Issue 81: quoting for NUnit parameters.
+- Issue 56: NuGet package is noisy
+- Issue 70: Portable library project has some invalid Nunit-based code.
+- Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily
+- Issue 84: warning CS0219: The variable `size' is assigned but never used
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.521
+===============================================================================
+
+Changes:
+- Add generated_code_attributes option, defaulted to false
+- Added support for Portable library
+- Added 'Unsafe' static type in ByteString to allow direct buffer access
+
+Fixes:
+- Issue 50: The XML serializer will fail to deserialize a message with empty 
+  child message
+- Issue 45: Use of 'item' as a field name causes AmbiguousMatchException
+- Issue 49: Generated nested static Types class should be partial
+- Issue 38: Disable CLSCompliant warnings (3021)
+- Issue 40: proto_path does not work for command-line file names
+- Issue 54: should retire all bytes in buffer (bufferSize)
+- Issue 43: Fix to correct identical 'umbrella_classname' options from trying 
+  to write to the same filename.
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.473
+===============================================================================
+
+Features:
+- Added option service_generator_type to control service generation with
+  NONE, GENERIC, INTERFACE, or IRPCDISPATCH
+- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking
+  services and implementations.
+- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the 
+  location of protoc.exe.
+- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow
+  custom implementation of writers with both speed and size optimizations.
+- Addition of the "Google.ProtoBuffers.Serialization" assembly to support
+  reading and writing messages to/from XML, JSON, IDictionary<,> and others.
+- Several performance related fixes and tweeks
+- Issue 3:	Add option to mark generated code with attribute
+- Issue 20:	Support for decorating classes [Serializable]
+- Issue 21:	Decorate fields with [deprecated=true] as [System.Obsolete]
+- Issue 22:	Reusable Builder classes
+- Issue 24:	Support for using Json/Xml formats with ICodedInputStream
+- Issue 25: Added support for NuGet packages
+- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1
+
+Fixes:
+- Issue 13:	Message with Field same name as message causes uncompilable .cs
+- Issue 16:	Does not integrate well with other tooling
+- Issue 19:	Support for negative enum values
+- Issue 26:	AddRange in GeneratedBuilder iterates twice.
+- Issue 27:	Remove XML documentation output from test projects to clear 
+  warnings/errors.
+- Issue 28: Circular message dependencies result in null default values for 
+  Message fields.
+- Issue 29: Message classes generated have a public default constructor.  You
+  can disable private ctor generation with the option generate_private_ctor.
+- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \
+- Big-endian support for float, and double on Silverlight
+- Packed and Unpacked parsing allow for all repeated, as per version 2.3
+- Fix for leaving Builder a public ctor on internal classes for use with
+  generic "where T: new()" constraints.
+
+Other:
+- Changed the code signing key to a privately held key
+- Reformatted all code and line-endings to C# defaults
+- Reworking of performance benchmarks to produce reliable results, option /v2
+- Issue 34: Silverlight assemblies are now unit tested
+
+===============================================================================
+RELEASE NOTES - Version 2.3.0.277
+===============================================================================
+
+Features:
+- Added cls_compliance option to generate attributes indicating 
+  non-CLS-compliance.
+- Added file_extension option to control the generated output file's extension.
+- Added umbrella_namespace option to place the umbrella class into a nested
+  namespace to address issues with proto files having the same name as a 
+  message it contains.
+- Added output_directory option to set the output path for the source file(s).
+- Added ignore_google_protobuf option to avoid generating code for includes 
+  from the google.protobuf package.
+- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to
+  generate code with "option optimize_for = LITE_RUNTIME;".
+- Added ability to invoke protoc.exe from within ProtoGen.exe.
+- Upgraded to protoc.exe (2.3) compiler.
+
+Fixes:
+- Issue 9:	Class cannot be static and sealed error
+- Issue 12:	default value for enumerate fields must be filled out
+
+Other:
+- Rewrite of build using MSbuild instead of NAnt
+- Moved to NUnit Version 2.2.8.0
+- Changed to using secure .snk for releases
+
+===============================================================================
+RELEASE NOTES - Version 0.9.1
+===============================================================================
+
+Fixes:
+- issue 10:	Incorrect encoding of packed fields when serialized
+
+===============================================================================
+RELEASE NOTES - Version 0.9.0
+===============================================================================
+
+- Initial release
+
+===============================================================================
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/Google.Protobuf.Tools.nuspec b/src/third_party/protobuf-3/csharp/Google.Protobuf.Tools.nuspec
new file mode 100644
index 0000000..e4240da
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/Google.Protobuf.Tools.nuspec
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package>
+  <metadata>
+    <id>Google.Protobuf.Tools</id>
+    <title>Google Protocol Buffers tools</title>
+    <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
+    <description>See project site for more info.</description>
+    <version>3.0.0-beta3</version>
+    <authors>Google Inc.</authors>
+    <owners>protobuf-packages</owners>
+    <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
+    <projectUrl>https://github.com/google/protobuf</projectUrl>
+    <requireLicenseAcceptance>false</requireLicenseAcceptance>
+    <releaseNotes>Tools for Protocol Buffers</releaseNotes>
+    <copyright>Copyright 2015, Google Inc.</copyright>
+    <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags>
+  </metadata>
+  <files>
+    <file src="protoc\windows_x86\protoc.exe" target="tools\windows_x86\protoc.exe" />
+    <file src="protoc\windows_x64\protoc.exe" target="tools\windows_x64\protoc.exe" />
+    <file src="protoc\linux_x86\protoc" target="tools\linux_x86\protoc" />
+    <file src="protoc\linux_x64\protoc" target="tools\linux_x64\protoc" />
+    <file src="protoc\macosx_x86\protoc" target="tools\macosx_x86\protoc" />
+    <file src="protoc\macosx_x64\protoc" target="tools\macosx_x64\protoc" />
+    <file src="..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\api.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\duration.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\empty.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\struct.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\type.proto" target="tools\google\protobuf" />
+    <file src="..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" />
+  </files>
+</package>
diff --git a/src/third_party/protobuf-3/csharp/README.md b/src/third_party/protobuf-3/csharp/README.md
new file mode 100644
index 0000000..8c3993e
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/README.md
@@ -0,0 +1,70 @@
+This directory contains the C# Protocol Buffers runtime library.
+
+Status: Beta - ready for external testing
+=========================================
+
+Usage
+=====
+
+The easiest way how to use C# protobufs is via the `Google.Protobuf`
+NuGet package. Just add the NuGet package to your VS project.
+
+Besides C# runtime library, the NuGet package also contains 
+precompiled version of `protoc.exe` and a copy of well known `.proto`
+files under the package's `tools` directory.
+
+To generate C# files from your `.proto` files, invoke `protoc` with the 
+`--csharp_out` option.
+
+Supported platforms
+===================
+
+The runtime library is built as a portable class library, supporting:
+
+- .NET 4.5
+- Windows 8
+- Windows Phone Silverlight 8
+- Windows Phone 8.1
+- .NET Core
+
+You should be able to use Protocol Buffers in Visual Studio 2012 and
+all later versions. This includes all code generated by `protoc`,
+which only uses features from C# 3 and earlier.
+
+Building
+========
+
+Open the `src/Google.Protobuf.sln` solution in Visual Studio 2015 or
+later. You should be able to run the NUnit test from Test Explorer
+(you might need to install NUnit Visual Studio add-in).
+
+Although *users* of this project are only expected to have Visual
+Studio 2012 or later, *developers* of the library are required to
+have Visual Studio 2015 or later, as the library uses C# 6 features
+in its implementation. These features have no impact when using the
+compiled code - they're only relevant when building the
+`Google.Protobuf` assembly.
+
+History of C# protobufs
+=======================
+
+This subtree was originally imported from https://github.com/jskeet/protobuf-csharp-port
+and represents the latest development version of C# protobufs, that will now be developed
+and maintained by Google. All the development will be done in open, under this repository
+(https://github.com/google/protobuf).
+
+The previous project differs from this project in a number of ways:
+
+- The old code only supported proto2; the new code only supports
+proto3 (so no unknown fields, no required/optional distinction, no
+extensions)
+- The old code was based on immutable message types and builders for
+them
+- The old code did not support maps or `oneof`
+- The old code had its own JSON representation, whereas the new code
+uses the standard protobuf JSON representation
+- The old code had no notion of the "well-known types" which have
+special support in the new code
+- The old project supported some older platforms (such as older
+versions of Silverlight) which are not currently supported in the
+new project
diff --git a/src/third_party/protobuf-3/csharp/build_packages.bat b/src/third_party/protobuf-3/csharp/build_packages.bat
new file mode 100644
index 0000000..1502f06
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/build_packages.bat
@@ -0,0 +1,13 @@
+@rem Builds Google.Protobuf NuGet packages
+
+@rem Adjust the location of nuget.exe
+set NUGET=C:\nuget\nuget.exe
+
+@rem Build src/Google.Protobuf.sln solution in Release configuration first.
+%NUGET% pack src\Google.Protobuf\Google.Protobuf.nuspec -Symbols || goto :error
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/src/third_party/protobuf-3/csharp/buildall.sh b/src/third_party/protobuf-3/csharp/buildall.sh
new file mode 100755
index 0000000..45af705
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/buildall.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Use mono to build solution and run all tests.
+
+# Adjust these to reflect the location of nunit-console in your system.
+NUNIT_CONSOLE=nunit-console
+
+# The rest you can leave intact
+CONFIG=Release
+SRC=$(dirname $0)/src
+
+set -ex
+
+echo Building the solution.
+xbuild /p:Configuration=$CONFIG $SRC/Google.Protobuf.sln
+
+echo Running tests.
+$NUNIT_CONSOLE $SRC/Google.Protobuf.Test/bin/$CONFIG/Google.Protobuf.Test.dll
diff --git a/src/third_party/protobuf-3/csharp/generate_protos.sh b/src/third_party/protobuf-3/csharp/generate_protos.sh
new file mode 100755
index 0000000..d979aa5
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/generate_protos.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# Generates C# source files from .proto files.
+# You first need to make sure protoc has been built (see instructions on
+# building protoc in root of this repository)
+
+set -ex
+
+# cd to repository root
+pushd $(dirname $0)/..
+
+# Protocol buffer compiler to use. If the PROTOC variable is set,
+# use that. Otherwise, probe for expected locations under both
+# Windows and Unix.
+if [ -z "$PROTOC" ]; then
+  # TODO(jonskeet): Use an array and a for loop instead?
+  if [ -x cmake/build/Debug/protoc.exe ]; then
+    PROTOC=cmake/build/Debug/protoc.exe
+  elif [ -x cmake/build/Release/protoc.exe ]; then
+    PROTOC=cmake/build/Release/protoc.exe
+  elif [ -x src/protoc ]; then
+    PROTOC=src/protoc
+  else
+    echo "Unable to find protocol buffer compiler."
+    exit 1
+  fi
+fi
+
+# descriptor.proto and well-known types
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \
+    --csharp_opt=base_namespace=Google.Protobuf \
+    src/google/protobuf/descriptor.proto \
+    src/google/protobuf/any.proto \
+    src/google/protobuf/api.proto \
+    src/google/protobuf/duration.proto \
+    src/google/protobuf/empty.proto \
+    src/google/protobuf/field_mask.proto \
+    src/google/protobuf/source_context.proto \
+    src/google/protobuf/struct.proto \
+    src/google/protobuf/timestamp.proto \
+    src/google/protobuf/type.proto \
+    src/google/protobuf/wrappers.proto
+
+# Test protos where the namespace matches the target location
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test \
+    --csharp_opt=base_namespace=Google.Protobuf \
+    src/google/protobuf/map_unittest_proto3.proto \
+    src/google/protobuf/unittest_proto3.proto \
+    src/google/protobuf/unittest_import_proto3.proto \
+    src/google/protobuf/unittest_import_public_proto3.proto \
+    src/google/protobuf/unittest_well_known_types.proto
+
+# Different base namespace to the protos above
+$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \
+    --csharp_opt=base_namespace=UnitTest.Issues \
+    csharp/protos/unittest_issues.proto
+
+# AddressBook sample protos
+$PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \
+    examples/addressbook.proto
+
+$PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \
+    conformance/conformance.proto
diff --git a/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.public.snk b/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.public.snk
new file mode 100644
index 0000000..59cd369
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.public.snk
Binary files differ
diff --git a/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.snk b/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.snk
new file mode 100644
index 0000000..7515443
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/keys/Google.Protobuf.snk
Binary files differ
diff --git a/src/third_party/protobuf-3/csharp/keys/README.md b/src/third_party/protobuf-3/csharp/keys/README.md
new file mode 100644
index 0000000..ede6735
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/keys/README.md
@@ -0,0 +1,9 @@
+Contents
+--------
+
+- Google.Protobuf.public.snk:
+  Public key to verify strong name of Google.Protobuf assemblies.
+- Google.Protobuf.snk:
+  Signing key to provide strong name of Google.Protobuf assemblies.
+  As per [Microsoft guidance](https://msdn.microsoft.com/en-us/library/wd40t7ad(v=vs.110).aspx)
+  signing key should be checked into the repository.
diff --git a/src/third_party/protobuf-3/csharp/protos/unittest_issues.proto b/src/third_party/protobuf-3/csharp/protos/unittest_issues.proto
new file mode 100644
index 0000000..6c9f763
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/protos/unittest_issues.proto
@@ -0,0 +1,126 @@
+syntax = "proto3";
+
+// These proto descriptors have at one time been reported as an issue or defect.
+// They are kept here to replicate the issue, and continue to verify the fix.
+
+// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified
+option csharp_namespace = "UnitTest.Issues.TestProtos";
+
+package unittest_issues;
+option optimize_for = SPEED;
+
+// Issue 307: when generating doubly-nested types, any references
+// should be of the form A.Types.B.Types.C.
+message Issue307 {
+  message NestedOnce {
+    message NestedTwice {
+    }
+  }
+}
+
+// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13
+// New issue 309: https://github.com/google/protobuf/issues/309
+ 
+// message A {
+//    optional int32 _A = 1;
+// }
+
+// message B {
+//    optional int32 B_ = 1;
+// }
+
+//message AB {
+//    optional int32 a_b = 1;
+//}
+
+// Similar issue with numeric names
+// Java code failed too, so probably best for this to be a restriction.
+// See https://github.com/google/protobuf/issues/308
+// message NumberField {
+//    optional int32 _01 = 1;
+// }
+
+// issue 19 - negative enum values
+
+enum NegativeEnum {
+    NEGATIVE_ENUM_ZERO = 0;
+    FiveBelow = -5;
+    MinusOne = -1;
+}
+
+message NegativeEnumMessage {
+    NegativeEnum value = 1;
+    repeated NegativeEnum values = 2 [packed = false];
+    repeated NegativeEnum packed_values = 3 [packed=true];
+}
+
+// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
+// Decorate fields with [deprecated=true] as [System.Obsolete]
+
+message DeprecatedChild {
+}
+
+enum DeprecatedEnum {
+    DEPRECATED_ZERO = 0;
+    one = 1;
+}
+
+message DeprecatedFieldsMessage {
+    int32 PrimitiveValue = 1 [deprecated = true];
+    repeated int32 PrimitiveArray = 2 [deprecated = true];
+
+    DeprecatedChild MessageValue = 3 [deprecated = true];
+    repeated DeprecatedChild MessageArray = 4 [deprecated = true];
+
+    DeprecatedEnum EnumValue = 5 [deprecated = true];
+    repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
+}
+
+// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
+message ItemField {
+  int32 item = 1;
+}
+
+message ReservedNames {
+  // Force a nested type called Types
+  message SomeNestedType {
+  }
+
+  int32 types = 1;
+  int32 descriptor = 2;
+}
+
+message TestJsonFieldOrdering {
+  // These fields are deliberately not declared in numeric
+  // order, and the oneof fields aren't contiguous either.
+  // This allows for reasonably robust tests of JSON output
+  // ordering.
+  // TestFieldOrderings in unittest_proto3.proto is similar,
+  // but doesn't include oneofs.
+  // TODO: Consider adding oneofs to TestFieldOrderings, although
+  // that will require fixing other tests in multiple platforms.
+  // Alternatively, consider just adding this to
+  // unittest_proto3.proto if multiple platforms want it.
+  
+  int32 plain_int32 = 4;
+
+  oneof o1 {
+    string o1_string = 2;
+    int32 o1_int32 = 5;
+  }
+  
+  string plain_string = 1;
+  
+  oneof o2 {
+    int32 o2_int32 = 6;
+    string o2_string = 3;
+  }
+  
+}
+
+message TestJsonName {
+  // Message for testing the effects for of the json_name option
+  string name = 1;
+  string description = 2 [json_name = "desc"];
+  string guid = 3 [json_name = "exid"];
+}
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/AddPerson.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/AddPerson.cs
new file mode 100644
index 0000000..484f1ea
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/AddPerson.cs
@@ -0,0 +1,132 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class AddPerson
+    {
+        /// <summary>
+        /// Builds a person based on user input
+        /// </summary>
+        private static Person PromptForAddress(TextReader input, TextWriter output)
+        {
+            Person person = new Person();
+
+            output.Write("Enter person ID: ");
+            person.Id = int.Parse(input.ReadLine());
+
+            output.Write("Enter name: ");
+            person.Name = input.ReadLine();
+
+            output.Write("Enter email address (blank for none): ");
+            string email = input.ReadLine();
+            if (email.Length > 0)
+            {
+                person.Email = email;
+            }
+
+            while (true)
+            {
+                output.Write("Enter a phone number (or leave blank to finish): ");
+                string number = input.ReadLine();
+                if (number.Length == 0)
+                {
+                    break;
+                }
+
+                Person.Types.PhoneNumber phoneNumber = new Person.Types.PhoneNumber { Number = number };
+
+                output.Write("Is this a mobile, home, or work phone? ");
+                String type = input.ReadLine();
+                switch (type)
+                {
+                    case "mobile":
+                        phoneNumber.Type = Person.Types.PhoneType.Mobile;
+                        break;
+                    case "home":
+                        phoneNumber.Type = Person.Types.PhoneType.Home;
+                        break;
+                    case "work":
+                        phoneNumber.Type = Person.Types.PhoneType.Work;
+                        break;
+                    default:
+                        output.Write("Unknown phone type. Using default.");
+                        break;
+                }
+
+                person.Phones.Add(phoneNumber);
+            }
+            return person;
+        }
+
+        /// <summary>
+        /// Entry point - loads an existing addressbook or creates a new one,
+        /// then writes it back to the file.
+        /// </summary>
+        public static int Main(string[] args)
+        {
+            if (args.Length != 1)
+            {
+                Console.Error.WriteLine("Usage:  AddPerson ADDRESS_BOOK_FILE");
+                return -1;
+            }
+
+            AddressBook addressBook;
+
+            if (File.Exists(args[0]))
+            {
+                using (Stream file = File.OpenRead(args[0]))
+                {
+                    addressBook = AddressBook.Parser.ParseFrom(file);
+                }
+            }
+            else
+            {
+                Console.WriteLine("{0}: File not found. Creating a new file.", args[0]);
+                addressBook = new AddressBook();
+            }
+
+            // Add an address.
+            addressBook.People.Add(PromptForAddress(Console.In, Console.Out));
+
+            // Write the new address book back to disk.
+            using (Stream output = File.OpenWrite(args[0]))
+            {
+                addressBook.WriteTo(output);
+            }
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/AddressBook.csproj b/src/third_party/protobuf-3/csharp/src/AddressBook/AddressBook.csproj
new file mode 100644
index 0000000..021647f
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/AddressBook.csproj
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A31F5FB2-4FF3-432A-B35B-5CD203606311}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.Examples.AddressBook</RootNamespace>
+    <AssemblyName>AddressBook</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>Google.Protobuf.Examples.AddressBook.Program</StartupObject>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AddPerson.cs" />
+    <Compile Include="Addressbook.cs" />
+    <Compile Include="SampleUsage.cs" />
+    <Compile Include="ListPeople.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/Addressbook.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/Addressbook.cs
new file mode 100644
index 0000000..362e1cb
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/Addressbook.cs
@@ -0,0 +1,473 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: addressbook.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.Examples.AddressBook {
+
+  /// <summary>Holder for reflection information generated from addressbook.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class AddressbookReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for addressbook.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static AddressbookReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu",
+            "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l",
+            "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u",
+            "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y",
+            "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA",
+            "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl",
+            "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y",
+            "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt",
+            "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  [START messages]
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Person : pb::IMessage<Person> {
+    private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
+    public static pb::MessageParser<Person> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Examples.AddressBook.AddressbookReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Person() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Person(Person other) : this() {
+      name_ = other.name_;
+      id_ = other.id_;
+      email_ = other.email_;
+      phones_ = other.phones_.Clone();
+    }
+
+    public Person Clone() {
+      return new Person(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "id" field.</summary>
+    public const int IdFieldNumber = 2;
+    private int id_;
+    /// <summary>
+    ///  Unique ID number for this person.
+    /// </summary>
+    public int Id {
+      get { return id_; }
+      set {
+        id_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "email" field.</summary>
+    public const int EmailFieldNumber = 3;
+    private string email_ = "";
+    public string Email {
+      get { return email_; }
+      set {
+        email_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "phones" field.</summary>
+    public const int PhonesFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> _repeated_phones_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> phones_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber>();
+    public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> Phones {
+      get { return phones_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Person);
+    }
+
+    public bool Equals(Person other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Id != other.Id) return false;
+      if (Email != other.Email) return false;
+      if(!phones_.Equals(other.phones_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Id != 0) hash ^= Id.GetHashCode();
+      if (Email.Length != 0) hash ^= Email.GetHashCode();
+      hash ^= phones_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Id != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Id);
+      }
+      if (Email.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Email);
+      }
+      phones_.WriteTo(output, _repeated_phones_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Id != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Id);
+      }
+      if (Email.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
+      }
+      size += phones_.CalculateSize(_repeated_phones_codec);
+      return size;
+    }
+
+    public void MergeFrom(Person other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Id != 0) {
+        Id = other.Id;
+      }
+      if (other.Email.Length != 0) {
+        Email = other.Email;
+      }
+      phones_.Add(other.phones_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Id = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            Email = input.ReadString();
+            break;
+          }
+          case 34: {
+            phones_.AddEntriesFrom(input, _repeated_phones_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the Person message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum PhoneType {
+        [pbr::OriginalName("MOBILE")] Mobile = 0,
+        [pbr::OriginalName("HOME")] Home = 1,
+        [pbr::OriginalName("WORK")] Work = 2,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
+        private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
+        public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Examples.AddressBook.Person.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public PhoneNumber() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public PhoneNumber(PhoneNumber other) : this() {
+          number_ = other.number_;
+          type_ = other.type_;
+        }
+
+        public PhoneNumber Clone() {
+          return new PhoneNumber(this);
+        }
+
+        /// <summary>Field number for the "number" field.</summary>
+        public const int NumberFieldNumber = 1;
+        private string number_ = "";
+        public string Number {
+          get { return number_; }
+          set {
+            number_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "type" field.</summary>
+        public const int TypeFieldNumber = 2;
+        private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = 0;
+        public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type {
+          get { return type_; }
+          set {
+            type_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as PhoneNumber);
+        }
+
+        public bool Equals(PhoneNumber other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Number != other.Number) return false;
+          if (Type != other.Type) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Number.Length != 0) hash ^= Number.GetHashCode();
+          if (Type != 0) hash ^= Type.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Number.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Number);
+          }
+          if (Type != 0) {
+            output.WriteRawTag(16);
+            output.WriteEnum((int) Type);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Number.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Number);
+          }
+          if (Type != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
+          }
+          return size;
+        }
+
+        public void MergeFrom(PhoneNumber other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Number.Length != 0) {
+            Number = other.Number;
+          }
+          if (other.Type != 0) {
+            Type = other.Type;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 10: {
+                Number = input.ReadString();
+                break;
+              }
+              case 16: {
+                type_ = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Our address book file is just one of these.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class AddressBook : pb::IMessage<AddressBook> {
+    private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
+    public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Examples.AddressBook.AddressbookReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public AddressBook() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public AddressBook(AddressBook other) : this() {
+      people_ = other.people_.Clone();
+    }
+
+    public AddressBook Clone() {
+      return new AddressBook(this);
+    }
+
+    /// <summary>Field number for the "people" field.</summary>
+    public const int PeopleFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person> _repeated_people_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Examples.AddressBook.Person.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> people_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person>();
+    public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> People {
+      get { return people_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as AddressBook);
+    }
+
+    public bool Equals(AddressBook other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!people_.Equals(other.people_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= people_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      people_.WriteTo(output, _repeated_people_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += people_.CalculateSize(_repeated_people_codec);
+      return size;
+    }
+
+    public void MergeFrom(AddressBook other) {
+      if (other == null) {
+        return;
+      }
+      people_.Add(other.people_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            people_.AddEntriesFrom(input, _repeated_people_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/ListPeople.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/ListPeople.cs
new file mode 100644
index 0000000..7157228
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/ListPeople.cs
@@ -0,0 +1,99 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class ListPeople
+    {
+        /// <summary>
+        /// Iterates though all people in the AddressBook and prints info about them.
+        /// </summary>
+        private static void Print(AddressBook addressBook)
+        {
+            foreach (Person person in addressBook.People)
+            {
+                Console.WriteLine("Person ID: {0}", person.Id);
+                Console.WriteLine("  Name: {0}", person.Name);
+                if (person.Email != "")
+                {
+                    Console.WriteLine("  E-mail address: {0}", person.Email);
+                }
+
+                foreach (Person.Types.PhoneNumber phoneNumber in person.Phones)
+                {
+                    switch (phoneNumber.Type)
+                    {
+                        case Person.Types.PhoneType.Mobile:
+                            Console.Write("  Mobile phone #: ");
+                            break;
+                        case Person.Types.PhoneType.Home:
+                            Console.Write("  Home phone #: ");
+                            break;
+                        case Person.Types.PhoneType.Work:
+                            Console.Write("  Work phone #: ");
+                            break;
+                    }
+                    Console.WriteLine(phoneNumber.Number);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Entry point - loads the addressbook and then displays it.
+        /// </summary>
+        public static int Main(string[] args)
+        {
+            if (args.Length != 1)
+            {
+                Console.Error.WriteLine("Usage:  ListPeople ADDRESS_BOOK_FILE");
+                return 1;
+            }
+
+            if (!File.Exists(args[0]))
+            {
+                Console.WriteLine("{0} doesn't exist. Add a person to create the file first.", args[0]);
+                return 0;
+            }
+
+            // Read the existing address book.
+            using (Stream stream = File.OpenRead(args[0]))
+            {
+                AddressBook addressBook = AddressBook.Parser.ParseFrom(stream);
+                Print(addressBook);
+            }
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/Program.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/Program.cs
new file mode 100644
index 0000000..8164f44
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/Program.cs
@@ -0,0 +1,95 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    /// <summary>
+    /// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour
+    /// to individual actions. Each action has its own Main method, so that it can be used as an
+    /// invidual complete program.
+    /// </summary>
+    internal class Program
+    {
+        private static int Main(string[] args)
+        {
+            if (args.Length > 1)
+            {
+                Console.Error.WriteLine("Usage: AddressBook [file]");
+                Console.Error.WriteLine("If the filename isn't specified, \"addressbook.data\" is used instead.");
+                return 1;
+            }
+            string addressBookFile = args.Length > 0 ? args[0] : "addressbook.data";
+
+            bool stopping = false;
+            while (!stopping)
+            {
+                Console.WriteLine("Options:");
+                Console.WriteLine("  L: List contents");
+                Console.WriteLine("  A: Add new person");
+                Console.WriteLine("  Q: Quit");
+                Console.Write("Action? ");
+                Console.Out.Flush();
+                char choice = Console.ReadKey().KeyChar;
+                Console.WriteLine();
+                try
+                {
+                    switch (choice)
+                    {
+                        case 'A':
+                        case 'a':
+                            AddPerson.Main(new string[] {addressBookFile});
+                            break;
+                        case 'L':
+                        case 'l':
+                            ListPeople.Main(new string[] {addressBookFile});
+                            break;
+                        case 'Q':
+                        case 'q':
+                            stopping = true;
+                            break;
+                        default:
+                            Console.WriteLine("Unknown option: {0}", choice);
+                            break;
+                    }
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine("Exception executing action: {0}", e);
+                }
+                Console.WriteLine();
+            }
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/Properties/AssemblyInfo.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1452f7a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("AddressBook")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AddressBook")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/SampleUsage.cs b/src/third_party/protobuf-3/csharp/src/AddressBook/SampleUsage.cs
new file mode 100644
index 0000000..aad7d70
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/SampleUsage.cs
@@ -0,0 +1,73 @@
+#region Copyright notice and license
+// 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.
+#endregion
+    
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class SampleUsage
+    {
+        private static void Main()
+        {
+            byte[] bytes;
+            // Create a new person
+            Person person = new Person
+            {
+                Id = 1,
+                Name = "Foo",
+                Email = "foo@bar",
+                Phones = { new Person.Types.PhoneNumber { Number = "555-1212" } }
+            };
+            using (MemoryStream stream = new MemoryStream())
+            {
+                // Save the person to a stream
+                person.WriteTo(stream);
+                bytes = stream.ToArray();
+            }
+            Person copy = Person.Parser.ParseFrom(bytes);
+
+            AddressBook book = new AddressBook
+            {
+                People = { copy }
+            };
+            bytes = book.ToByteArray();
+            // And read the address book back again
+            AddressBook restored = AddressBook.Parser.ParseFrom(bytes);
+            // The message performs a deep-comparison on equality:
+            if (restored.People.Count != 1 || !person.Equals(restored.People[0]))
+            {
+                throw new ApplicationException("There is a bad person in here!");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/AddressBook/app.config b/src/third_party/protobuf-3/csharp/src/AddressBook/app.config
new file mode 100644
index 0000000..a80813a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/AddressBook/app.config
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<configuration>
+	<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/App.config b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Conformance.cs
new file mode 100644
index 0000000..1674a67
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -0,0 +1,3708 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: conformance.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Conformance {
+
+  /// <summary>Holder for reflection information generated from conformance.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class ConformanceReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for conformance.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static ConformanceReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UaGWdvb2dsZS9wcm90",
+            "b2J1Zi9hbnkucHJvdG8aHmdvb2dsZS9wcm90b2J1Zi9kdXJhdGlvbi5wcm90",
+            "bxogZ29vZ2xlL3Byb3RvYnVmL2ZpZWxkX21hc2sucHJvdG8aHGdvb2dsZS9w",
+            "cm90b2J1Zi9zdHJ1Y3QucHJvdG8aH2dvb2dsZS9wcm90b2J1Zi90aW1lc3Rh",
+            "bXAucHJvdG8aHmdvb2dsZS9wcm90b2J1Zi93cmFwcGVycy5wcm90byKNAQoS",
+            "Q29uZm9ybWFuY2VSZXF1ZXN0EhoKEHByb3RvYnVmX3BheWxvYWQYASABKAxI",
+            "ABIWCgxqc29uX3BheWxvYWQYAiABKAlIABI4ChdyZXF1ZXN0ZWRfb3V0cHV0",
+            "X2Zvcm1hdBgDIAEoDjIXLmNvbmZvcm1hbmNlLldpcmVGb3JtYXRCCQoHcGF5",
+            "bG9hZCKxAQoTQ29uZm9ybWFuY2VSZXNwb25zZRIVCgtwYXJzZV9lcnJvchgB",
+            "IAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgAEhcKDXJ1bnRpbWVf",
+            "ZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2FkGAMgASgMSAASFgoM",
+            "anNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgFIAEoCUgAQggKBnJl",
+            "c3VsdCLVMgoMVGVzdEFsbFR5cGVzEhYKDm9wdGlvbmFsX2ludDMyGAEgASgF",
+            "EhYKDm9wdGlvbmFsX2ludDY0GAIgASgDEhcKD29wdGlvbmFsX3VpbnQzMhgD",
+            "IAEoDRIXCg9vcHRpb25hbF91aW50NjQYBCABKAQSFwoPb3B0aW9uYWxfc2lu",
+            "dDMyGAUgASgREhcKD29wdGlvbmFsX3NpbnQ2NBgGIAEoEhIYChBvcHRpb25h",
+            "bF9maXhlZDMyGAcgASgHEhgKEG9wdGlvbmFsX2ZpeGVkNjQYCCABKAYSGQoR",
+            "b3B0aW9uYWxfc2ZpeGVkMzIYCSABKA8SGQoRb3B0aW9uYWxfc2ZpeGVkNjQY",
+            "CiABKBASFgoOb3B0aW9uYWxfZmxvYXQYCyABKAISFwoPb3B0aW9uYWxfZG91",
+            "YmxlGAwgASgBEhUKDW9wdGlvbmFsX2Jvb2wYDSABKAgSFwoPb3B0aW9uYWxf",
+            "c3RyaW5nGA4gASgJEhYKDm9wdGlvbmFsX2J5dGVzGA8gASgMEkgKF29wdGlv",
+            "bmFsX25lc3RlZF9tZXNzYWdlGBIgASgLMicuY29uZm9ybWFuY2UuVGVzdEFs",
+            "bFR5cGVzLk5lc3RlZE1lc3NhZ2USPQoYb3B0aW9uYWxfZm9yZWlnbl9tZXNz",
+            "YWdlGBMgASgLMhsuY29uZm9ybWFuY2UuRm9yZWlnbk1lc3NhZ2USQgoUb3B0",
+            "aW9uYWxfbmVzdGVkX2VudW0YFSABKA4yJC5jb25mb3JtYW5jZS5UZXN0QWxs",
+            "VHlwZXMuTmVzdGVkRW51bRI3ChVvcHRpb25hbF9mb3JlaWduX2VudW0YFiAB",
+            "KA4yGC5jb25mb3JtYW5jZS5Gb3JlaWduRW51bRIhChVvcHRpb25hbF9zdHJp",
+            "bmdfcGllY2UYGCABKAlCAggCEhkKDW9wdGlvbmFsX2NvcmQYGSABKAlCAggB",
+            "EjQKEXJlY3Vyc2l2ZV9tZXNzYWdlGBsgASgLMhkuY29uZm9ybWFuY2UuVGVz",
+            "dEFsbFR5cGVzEhYKDnJlcGVhdGVkX2ludDMyGB8gAygFEhYKDnJlcGVhdGVk",
+            "X2ludDY0GCAgAygDEhcKD3JlcGVhdGVkX3VpbnQzMhghIAMoDRIXCg9yZXBl",
+            "YXRlZF91aW50NjQYIiADKAQSFwoPcmVwZWF0ZWRfc2ludDMyGCMgAygREhcK",
+            "D3JlcGVhdGVkX3NpbnQ2NBgkIAMoEhIYChByZXBlYXRlZF9maXhlZDMyGCUg",
+            "AygHEhgKEHJlcGVhdGVkX2ZpeGVkNjQYJiADKAYSGQoRcmVwZWF0ZWRfc2Zp",
+            "eGVkMzIYJyADKA8SGQoRcmVwZWF0ZWRfc2ZpeGVkNjQYKCADKBASFgoOcmVw",
+            "ZWF0ZWRfZmxvYXQYKSADKAISFwoPcmVwZWF0ZWRfZG91YmxlGCogAygBEhUK",
+            "DXJlcGVhdGVkX2Jvb2wYKyADKAgSFwoPcmVwZWF0ZWRfc3RyaW5nGCwgAygJ",
+            "EhYKDnJlcGVhdGVkX2J5dGVzGC0gAygMEkgKF3JlcGVhdGVkX25lc3RlZF9t",
+            "ZXNzYWdlGDAgAygLMicuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk5lc3Rl",
+            "ZE1lc3NhZ2USPQoYcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlGDEgAygLMhsu",
+            "Y29uZm9ybWFuY2UuRm9yZWlnbk1lc3NhZ2USQgoUcmVwZWF0ZWRfbmVzdGVk",
+            "X2VudW0YMyADKA4yJC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVk",
+            "RW51bRI3ChVyZXBlYXRlZF9mb3JlaWduX2VudW0YNCADKA4yGC5jb25mb3Jt",
+            "YW5jZS5Gb3JlaWduRW51bRIhChVyZXBlYXRlZF9zdHJpbmdfcGllY2UYNiAD",
+            "KAlCAggCEhkKDXJlcGVhdGVkX2NvcmQYNyADKAlCAggBEkUKD21hcF9pbnQz",
+            "Ml9pbnQzMhg4IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJ",
+            "bnQzMkludDMyRW50cnkSRQoPbWFwX2ludDY0X2ludDY0GDkgAygLMiwuY29u",
+            "Zm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDY0SW50NjRFbnRyeRJJChFt",
+            "YXBfdWludDMyX3VpbnQzMhg6IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxU",
+            "eXBlcy5NYXBVaW50MzJVaW50MzJFbnRyeRJJChFtYXBfdWludDY0X3VpbnQ2",
+            "NBg7IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBVaW50NjRV",
+            "aW50NjRFbnRyeRJJChFtYXBfc2ludDMyX3NpbnQzMhg8IAMoCzIuLmNvbmZv",
+            "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTaW50MzJTaW50MzJFbnRyeRJJChFt",
+            "YXBfc2ludDY0X3NpbnQ2NBg9IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxU",
+            "eXBlcy5NYXBTaW50NjRTaW50NjRFbnRyeRJNChNtYXBfZml4ZWQzMl9maXhl",
+            "ZDMyGD4gAygLMjAuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEZpeGVk",
+            "MzJGaXhlZDMyRW50cnkSTQoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBg/IAMoCzIw",
+            "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBGaXhlZDY0Rml4ZWQ2NEVu",
+            "dHJ5ElEKFW1hcF9zZml4ZWQzMl9zZml4ZWQzMhhAIAMoCzIyLmNvbmZvcm1h",
+            "bmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkSUQoV",
+            "bWFwX3NmaXhlZDY0X3NmaXhlZDY0GEEgAygLMjIuY29uZm9ybWFuY2UuVGVz",
+            "dEFsbFR5cGVzLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJFCg9tYXBfaW50",
+            "MzJfZmxvYXQYQiADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFw",
+            "SW50MzJGbG9hdEVudHJ5EkcKEG1hcF9pbnQzMl9kb3VibGUYQyADKAsyLS5j",
+            "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwSW50MzJEb3VibGVFbnRyeRJB",
+            "Cg1tYXBfYm9vbF9ib29sGEQgAygLMiouY29uZm9ybWFuY2UuVGVzdEFsbFR5",
+            "cGVzLk1hcEJvb2xCb29sRW50cnkSSQoRbWFwX3N0cmluZ19zdHJpbmcYRSAD",
+            "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nU3RyaW5n",
+            "RW50cnkSRwoQbWFwX3N0cmluZ19ieXRlcxhGIAMoCzItLmNvbmZvcm1hbmNl",
+            "LlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdCeXRlc0VudHJ5ElgKGW1hcF9zdHJp",
+            "bmdfbmVzdGVkX21lc3NhZ2UYRyADKAsyNS5jb25mb3JtYW5jZS5UZXN0QWxs",
+            "VHlwZXMuTWFwU3RyaW5nTmVzdGVkTWVzc2FnZUVudHJ5EloKGm1hcF9zdHJp",
+            "bmdfZm9yZWlnbl9tZXNzYWdlGEggAygLMjYuY29uZm9ybWFuY2UuVGVzdEFs",
+            "bFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25NZXNzYWdlRW50cnkSUgoWbWFwX3N0",
+            "cmluZ19uZXN0ZWRfZW51bRhJIAMoCzIyLmNvbmZvcm1hbmNlLlRlc3RBbGxU",
+            "eXBlcy5NYXBTdHJpbmdOZXN0ZWRFbnVtRW50cnkSVAoXbWFwX3N0cmluZ19m",
+            "b3JlaWduX2VudW0YSiADKAsyMy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu",
+            "TWFwU3RyaW5nRm9yZWlnbkVudW1FbnRyeRIWCgxvbmVvZl91aW50MzIYbyAB",
+            "KA1IABJHChRvbmVvZl9uZXN0ZWRfbWVzc2FnZRhwIAEoCzInLmNvbmZvcm1h",
+            "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlSAASFgoMb25lb2Zfc3Ry",
+            "aW5nGHEgASgJSAASFQoLb25lb2ZfYnl0ZXMYciABKAxIABI6ChVvcHRpb25h",
+            "bF9ib29sX3dyYXBwZXIYyQEgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJvb2xW",
+            "YWx1ZRI8ChZvcHRpb25hbF9pbnQzMl93cmFwcGVyGMoBIAEoCzIbLmdvb2ds",
+            "ZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFm9wdGlvbmFsX2ludDY0X3dyYXBw",
+            "ZXIYywEgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoXb3B0",
+            "aW9uYWxfdWludDMyX3dyYXBwZXIYzAEgASgLMhwuZ29vZ2xlLnByb3RvYnVm",
+            "LlVJbnQzMlZhbHVlEj4KF29wdGlvbmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEo",
+            "CzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZvcHRpb25hbF9m",
+            "bG9hdF93cmFwcGVyGM4BIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZh",
+            "bHVlEj4KF29wdGlvbmFsX2RvdWJsZV93cmFwcGVyGM8BIAEoCzIcLmdvb2ds",
+            "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3Jh",
+            "cHBlchjQASABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSPAoW",
+            "b3B0aW9uYWxfYnl0ZXNfd3JhcHBlchjRASABKAsyGy5nb29nbGUucHJvdG9i",
+            "dWYuQnl0ZXNWYWx1ZRI6ChVyZXBlYXRlZF9ib29sX3dyYXBwZXIY0wEgAygL",
+            "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQz",
+            "Ml93cmFwcGVyGNQBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl",
+            "EjwKFnJlcGVhdGVkX2ludDY0X3dyYXBwZXIY1QEgAygLMhsuZ29vZ2xlLnBy",
+            "b3RvYnVmLkludDY0VmFsdWUSPgoXcmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY",
+            "1gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVh",
+            "dGVkX3VpbnQ2NF93cmFwcGVyGNcBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5V",
+            "SW50NjRWYWx1ZRI8ChZyZXBlYXRlZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIb",
+            "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJs",
+            "ZV93cmFwcGVyGNkBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1",
+            "ZRI+ChdyZXBlYXRlZF9zdHJpbmdfd3JhcHBlchjaASADKAsyHC5nb29nbGUu",
+            "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBl",
+            "chjbASADKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRp",
+            "b25hbF9kdXJhdGlvbhitAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp",
+            "b24SNwoSb3B0aW9uYWxfdGltZXN0YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90",
+            "b2J1Zi5UaW1lc3RhbXASOAoTb3B0aW9uYWxfZmllbGRfbWFzaxivAiABKAsy",
+            "Gi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD29wdGlvbmFsX3N0cnVj",
+            "dBiwAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDG9wdGlvbmFs",
+            "X2FueRixAiABKAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDm9wdGlvbmFs",
+            "X3ZhbHVlGLICIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI1ChFyZXBl",
+            "YXRlZF9kdXJhdGlvbhi3AiADKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp",
+            "b24SNwoScmVwZWF0ZWRfdGltZXN0YW1wGLgCIAMoCzIaLmdvb2dsZS5wcm90",
+            "b2J1Zi5UaW1lc3RhbXASNwoScmVwZWF0ZWRfZmllbGRtYXNrGLkCIAMoCzIa",
+            "Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSMQoPcmVwZWF0ZWRfc3RydWN0",
+            "GMQCIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSKwoMcmVwZWF0ZWRf",
+            "YW55GLsCIAMoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkSLwoOcmVwZWF0ZWRf",
+            "dmFsdWUYvAIgAygLMhYuZ29vZ2xlLnByb3RvYnVmLlZhbHVlEhMKCmZpZWxk",
+            "bmFtZTEYkQMgASgFEhQKC2ZpZWxkX25hbWUyGJIDIAEoBRIVCgxfZmllbGRf",
+            "bmFtZTMYkwMgASgFEhYKDWZpZWxkX19uYW1lNF8YlAMgASgFEhQKC2ZpZWxk",
+            "MG5hbWU1GJUDIAEoBRIWCg1maWVsZF8wX25hbWU2GJYDIAEoBRITCgpmaWVs",
+            "ZE5hbWU3GJcDIAEoBRITCgpGaWVsZE5hbWU4GJgDIAEoBRIUCgtmaWVsZF9O",
+            "YW1lORiZAyABKAUSFQoMRmllbGRfTmFtZTEwGJoDIAEoBRIVCgxGSUVMRF9O",
+            "QU1FMTEYmwMgASgFEhUKDEZJRUxEX25hbWUxMhicAyABKAUaSgoNTmVzdGVk",
+            "TWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIgASgLMhkuY29u",
+            "Zm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50MzJFbnRyeRIL",
+            "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50",
+            "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h",
+            "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo",
+            "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K",
+            "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr",
+            "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2",
+            "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw",
+            "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB",
+            "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG",
+            "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50",
+            "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4",
+            "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ",
+            "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh",
+            "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB",
+            "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL",
+            "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0",
+            "cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoT",
+            "TWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiAB",
+            "KAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkY",
+            "ASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5UZXN0QWxsVHlw",
+            "ZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9yZWlnbk1lc3Nh",
+            "Z2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsyGy5jb25mb3Jt",
+            "YW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5nTmVzdGVkRW51",
+            "bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIkLmNvbmZvcm1h",
+            "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlNYXBTdHJpbmdG",
+            "b3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1ZRgCIAEoDjIY",
+            "LmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcK",
+            "A0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BQg0K",
+            "C29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqNQoK",
+            "V2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoE",
+            "SlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAASDwoLRk9S",
+            "RUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5nb29nbGUucHJv",
+            "dG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.ForeignEnum), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes), global::Conformance.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), global::Conformance.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null),
+            null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ForeignMessage), global::Conformance.ForeignMessage.Parser, new[]{ "C" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum WireFormat {
+    [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0,
+    [pbr::OriginalName("PROTOBUF")] Protobuf = 1,
+    [pbr::OriginalName("JSON")] Json = 2,
+  }
+
+  public enum ForeignEnum {
+    [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 0,
+    [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 1,
+    [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  Represents a single test case's input.  The testee should:
+  ///
+  ///    1. parse this proto (which should always succeed)
+  ///    2. parse the protobuf or JSON payload in "payload" (which may fail)
+  ///    3. if the parse succeeded, serialize the message in the requested format.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
+    private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
+    public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ConformanceRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ConformanceRequest(ConformanceRequest other) : this() {
+      requestedOutputFormat_ = other.requestedOutputFormat_;
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case PayloadOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+      }
+
+    }
+
+    public ConformanceRequest Clone() {
+      return new ConformanceRequest(this);
+    }
+
+    /// <summary>Field number for the "protobuf_payload" field.</summary>
+    public const int ProtobufPayloadFieldNumber = 1;
+    public pb::ByteString ProtobufPayload {
+      get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; }
+      set {
+        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        payloadCase_ = PayloadOneofCase.ProtobufPayload;
+      }
+    }
+
+    /// <summary>Field number for the "json_payload" field.</summary>
+    public const int JsonPayloadFieldNumber = 2;
+    public string JsonPayload {
+      get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; }
+      set {
+        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        payloadCase_ = PayloadOneofCase.JsonPayload;
+      }
+    }
+
+    /// <summary>Field number for the "requested_output_format" field.</summary>
+    public const int RequestedOutputFormatFieldNumber = 3;
+    private global::Conformance.WireFormat requestedOutputFormat_ = 0;
+    /// <summary>
+    ///  Which format should the testee serialize its message to?
+    /// </summary>
+    public global::Conformance.WireFormat RequestedOutputFormat {
+      get { return requestedOutputFormat_; }
+      set {
+        requestedOutputFormat_ = value;
+      }
+    }
+
+    private object payload_;
+    /// <summary>Enum of possible cases for the "payload" oneof.</summary>
+    public enum PayloadOneofCase {
+      None = 0,
+      ProtobufPayload = 1,
+      JsonPayload = 2,
+    }
+    private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
+    public PayloadOneofCase PayloadCase {
+      get { return payloadCase_; }
+    }
+
+    public void ClearPayload() {
+      payloadCase_ = PayloadOneofCase.None;
+      payload_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ConformanceRequest);
+    }
+
+    public bool Equals(ConformanceRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ProtobufPayload != other.ProtobufPayload) return false;
+      if (JsonPayload != other.JsonPayload) return false;
+      if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
+      if (PayloadCase != other.PayloadCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
+      if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
+      hash ^= (int) payloadCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
+        output.WriteRawTag(10);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
+        output.WriteRawTag(18);
+        output.WriteString(JsonPayload);
+      }
+      if (RequestedOutputFormat != 0) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) RequestedOutputFormat);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
+      }
+      if (RequestedOutputFormat != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ConformanceRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.RequestedOutputFormat != 0) {
+        RequestedOutputFormat = other.RequestedOutputFormat;
+      }
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case PayloadOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 18: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 24: {
+            requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Represents a single test case's output.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
+    private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
+    public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ConformanceResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ConformanceResponse(ConformanceResponse other) : this() {
+      switch (other.ResultCase) {
+        case ResultOneofCase.ParseError:
+          ParseError = other.ParseError;
+          break;
+        case ResultOneofCase.SerializeError:
+          SerializeError = other.SerializeError;
+          break;
+        case ResultOneofCase.RuntimeError:
+          RuntimeError = other.RuntimeError;
+          break;
+        case ResultOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case ResultOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+        case ResultOneofCase.Skipped:
+          Skipped = other.Skipped;
+          break;
+      }
+
+    }
+
+    public ConformanceResponse Clone() {
+      return new ConformanceResponse(this);
+    }
+
+    /// <summary>Field number for the "parse_error" field.</summary>
+    public const int ParseErrorFieldNumber = 1;
+    /// <summary>
+    ///  This string should be set to indicate parsing failed.  The string can
+    ///  provide more information about the parse error if it is available.
+    ///
+    ///  Setting this string does not necessarily mean the testee failed the
+    ///  test.  Some of the test cases are intentionally invalid input.
+    /// </summary>
+    public string ParseError {
+      get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.ParseError;
+      }
+    }
+
+    /// <summary>Field number for the "serialize_error" field.</summary>
+    public const int SerializeErrorFieldNumber = 6;
+    /// <summary>
+    ///  If the input was successfully parsed but errors occurred when
+    ///  serializing it to the requested output format, set the error message in
+    ///  this field.
+    /// </summary>
+    public string SerializeError {
+      get { return resultCase_ == ResultOneofCase.SerializeError ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.SerializeError;
+      }
+    }
+
+    /// <summary>Field number for the "runtime_error" field.</summary>
+    public const int RuntimeErrorFieldNumber = 2;
+    /// <summary>
+    ///  This should be set if some other error occurred.  This will always
+    ///  indicate that the test failed.  The string can provide more information
+    ///  about the failure.
+    /// </summary>
+    public string RuntimeError {
+      get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.RuntimeError;
+      }
+    }
+
+    /// <summary>Field number for the "protobuf_payload" field.</summary>
+    public const int ProtobufPayloadFieldNumber = 3;
+    /// <summary>
+    ///  If the input was successfully parsed and the requested output was
+    ///  protobuf, serialize it to protobuf and set it in this field.
+    /// </summary>
+    public pb::ByteString ProtobufPayload {
+      get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.ProtobufPayload;
+      }
+    }
+
+    /// <summary>Field number for the "json_payload" field.</summary>
+    public const int JsonPayloadFieldNumber = 4;
+    /// <summary>
+    ///  If the input was successfully parsed and the requested output was JSON,
+    ///  serialize to JSON and set it in this field.
+    /// </summary>
+    public string JsonPayload {
+      get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.JsonPayload;
+      }
+    }
+
+    /// <summary>Field number for the "skipped" field.</summary>
+    public const int SkippedFieldNumber = 5;
+    /// <summary>
+    ///  For when the testee skipped the test, likely because a certain feature
+    ///  wasn't supported, like JSON input/output.
+    /// </summary>
+    public string Skipped {
+      get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.Skipped;
+      }
+    }
+
+    private object result_;
+    /// <summary>Enum of possible cases for the "result" oneof.</summary>
+    public enum ResultOneofCase {
+      None = 0,
+      ParseError = 1,
+      SerializeError = 6,
+      RuntimeError = 2,
+      ProtobufPayload = 3,
+      JsonPayload = 4,
+      Skipped = 5,
+    }
+    private ResultOneofCase resultCase_ = ResultOneofCase.None;
+    public ResultOneofCase ResultCase {
+      get { return resultCase_; }
+    }
+
+    public void ClearResult() {
+      resultCase_ = ResultOneofCase.None;
+      result_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ConformanceResponse);
+    }
+
+    public bool Equals(ConformanceResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ParseError != other.ParseError) return false;
+      if (SerializeError != other.SerializeError) return false;
+      if (RuntimeError != other.RuntimeError) return false;
+      if (ProtobufPayload != other.ProtobufPayload) return false;
+      if (JsonPayload != other.JsonPayload) return false;
+      if (Skipped != other.Skipped) return false;
+      if (ResultCase != other.ResultCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode();
+      if (resultCase_ == ResultOneofCase.SerializeError) hash ^= SerializeError.GetHashCode();
+      if (resultCase_ == ResultOneofCase.RuntimeError) hash ^= RuntimeError.GetHashCode();
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
+      if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
+      if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
+      hash ^= (int) resultCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (resultCase_ == ResultOneofCase.ParseError) {
+        output.WriteRawTag(10);
+        output.WriteString(ParseError);
+      }
+      if (resultCase_ == ResultOneofCase.RuntimeError) {
+        output.WriteRawTag(18);
+        output.WriteString(RuntimeError);
+      }
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
+        output.WriteRawTag(26);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (resultCase_ == ResultOneofCase.JsonPayload) {
+        output.WriteRawTag(34);
+        output.WriteString(JsonPayload);
+      }
+      if (resultCase_ == ResultOneofCase.Skipped) {
+        output.WriteRawTag(42);
+        output.WriteString(Skipped);
+      }
+      if (resultCase_ == ResultOneofCase.SerializeError) {
+        output.WriteRawTag(50);
+        output.WriteString(SerializeError);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (resultCase_ == ResultOneofCase.ParseError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(ParseError);
+      }
+      if (resultCase_ == ResultOneofCase.SerializeError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(SerializeError);
+      }
+      if (resultCase_ == ResultOneofCase.RuntimeError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeError);
+      }
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
+      }
+      if (resultCase_ == ResultOneofCase.JsonPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
+      }
+      if (resultCase_ == ResultOneofCase.Skipped) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ConformanceResponse other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.ResultCase) {
+        case ResultOneofCase.ParseError:
+          ParseError = other.ParseError;
+          break;
+        case ResultOneofCase.SerializeError:
+          SerializeError = other.SerializeError;
+          break;
+        case ResultOneofCase.RuntimeError:
+          RuntimeError = other.RuntimeError;
+          break;
+        case ResultOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case ResultOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+        case ResultOneofCase.Skipped:
+          Skipped = other.Skipped;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            ParseError = input.ReadString();
+            break;
+          }
+          case 18: {
+            RuntimeError = input.ReadString();
+            break;
+          }
+          case 26: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 34: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 42: {
+            Skipped = input.ReadString();
+            break;
+          }
+          case 50: {
+            SerializeError = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  This proto includes every type of field in both singular and repeated
+  ///  forms.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+    private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
+    public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestAllTypes(TestAllTypes other) : this() {
+      optionalInt32_ = other.optionalInt32_;
+      optionalInt64_ = other.optionalInt64_;
+      optionalUint32_ = other.optionalUint32_;
+      optionalUint64_ = other.optionalUint64_;
+      optionalSint32_ = other.optionalSint32_;
+      optionalSint64_ = other.optionalSint64_;
+      optionalFixed32_ = other.optionalFixed32_;
+      optionalFixed64_ = other.optionalFixed64_;
+      optionalSfixed32_ = other.optionalSfixed32_;
+      optionalSfixed64_ = other.optionalSfixed64_;
+      optionalFloat_ = other.optionalFloat_;
+      optionalDouble_ = other.optionalDouble_;
+      optionalBool_ = other.optionalBool_;
+      optionalString_ = other.optionalString_;
+      optionalBytes_ = other.optionalBytes_;
+      OptionalNestedMessage = other.optionalNestedMessage_ != null ? other.OptionalNestedMessage.Clone() : null;
+      OptionalForeignMessage = other.optionalForeignMessage_ != null ? other.OptionalForeignMessage.Clone() : null;
+      optionalNestedEnum_ = other.optionalNestedEnum_;
+      optionalForeignEnum_ = other.optionalForeignEnum_;
+      optionalStringPiece_ = other.optionalStringPiece_;
+      optionalCord_ = other.optionalCord_;
+      RecursiveMessage = other.recursiveMessage_ != null ? other.RecursiveMessage.Clone() : null;
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedUint32_ = other.repeatedUint32_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+      repeatedSint32_ = other.repeatedSint32_.Clone();
+      repeatedSint64_ = other.repeatedSint64_.Clone();
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedSfixed32_ = other.repeatedSfixed32_.Clone();
+      repeatedSfixed64_ = other.repeatedSfixed64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedDouble_ = other.repeatedDouble_.Clone();
+      repeatedBool_ = other.repeatedBool_.Clone();
+      repeatedString_ = other.repeatedString_.Clone();
+      repeatedBytes_ = other.repeatedBytes_.Clone();
+      repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone();
+      repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone();
+      repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone();
+      repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone();
+      repeatedStringPiece_ = other.repeatedStringPiece_.Clone();
+      repeatedCord_ = other.repeatedCord_.Clone();
+      mapInt32Int32_ = other.mapInt32Int32_.Clone();
+      mapInt64Int64_ = other.mapInt64Int64_.Clone();
+      mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
+      mapUint64Uint64_ = other.mapUint64Uint64_.Clone();
+      mapSint32Sint32_ = other.mapSint32Sint32_.Clone();
+      mapSint64Sint64_ = other.mapSint64Sint64_.Clone();
+      mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone();
+      mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone();
+      mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone();
+      mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone();
+      mapInt32Float_ = other.mapInt32Float_.Clone();
+      mapInt32Double_ = other.mapInt32Double_.Clone();
+      mapBoolBool_ = other.mapBoolBool_.Clone();
+      mapStringString_ = other.mapStringString_.Clone();
+      mapStringBytes_ = other.mapStringBytes_.Clone();
+      mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone();
+      mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone();
+      mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone();
+      mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone();
+      OptionalBoolWrapper = other.OptionalBoolWrapper;
+      OptionalInt32Wrapper = other.OptionalInt32Wrapper;
+      OptionalInt64Wrapper = other.OptionalInt64Wrapper;
+      OptionalUint32Wrapper = other.OptionalUint32Wrapper;
+      OptionalUint64Wrapper = other.OptionalUint64Wrapper;
+      OptionalFloatWrapper = other.OptionalFloatWrapper;
+      OptionalDoubleWrapper = other.OptionalDoubleWrapper;
+      OptionalStringWrapper = other.OptionalStringWrapper;
+      OptionalBytesWrapper = other.OptionalBytesWrapper;
+      repeatedBoolWrapper_ = other.repeatedBoolWrapper_.Clone();
+      repeatedInt32Wrapper_ = other.repeatedInt32Wrapper_.Clone();
+      repeatedInt64Wrapper_ = other.repeatedInt64Wrapper_.Clone();
+      repeatedUint32Wrapper_ = other.repeatedUint32Wrapper_.Clone();
+      repeatedUint64Wrapper_ = other.repeatedUint64Wrapper_.Clone();
+      repeatedFloatWrapper_ = other.repeatedFloatWrapper_.Clone();
+      repeatedDoubleWrapper_ = other.repeatedDoubleWrapper_.Clone();
+      repeatedStringWrapper_ = other.repeatedStringWrapper_.Clone();
+      repeatedBytesWrapper_ = other.repeatedBytesWrapper_.Clone();
+      OptionalDuration = other.optionalDuration_ != null ? other.OptionalDuration.Clone() : null;
+      OptionalTimestamp = other.optionalTimestamp_ != null ? other.OptionalTimestamp.Clone() : null;
+      OptionalFieldMask = other.optionalFieldMask_ != null ? other.OptionalFieldMask.Clone() : null;
+      OptionalStruct = other.optionalStruct_ != null ? other.OptionalStruct.Clone() : null;
+      OptionalAny = other.optionalAny_ != null ? other.OptionalAny.Clone() : null;
+      OptionalValue = other.optionalValue_ != null ? other.OptionalValue.Clone() : null;
+      repeatedDuration_ = other.repeatedDuration_.Clone();
+      repeatedTimestamp_ = other.repeatedTimestamp_.Clone();
+      repeatedFieldmask_ = other.repeatedFieldmask_.Clone();
+      repeatedStruct_ = other.repeatedStruct_.Clone();
+      repeatedAny_ = other.repeatedAny_.Clone();
+      repeatedValue_ = other.repeatedValue_.Clone();
+      fieldname1_ = other.fieldname1_;
+      fieldName2_ = other.fieldName2_;
+      FieldName3_ = other.FieldName3_;
+      fieldName4_ = other.fieldName4_;
+      field0Name5_ = other.field0Name5_;
+      field0Name6_ = other.field0Name6_;
+      fieldName7_ = other.fieldName7_;
+      fieldName8_ = other.fieldName8_;
+      fieldName9_ = other.fieldName9_;
+      fieldName10_ = other.fieldName10_;
+      fIELDNAME11_ = other.fIELDNAME11_;
+      fIELDName12_ = other.fIELDName12_;
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage.Clone();
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public TestAllTypes Clone() {
+      return new TestAllTypes(this);
+    }
+
+    /// <summary>Field number for the "optional_int32" field.</summary>
+    public const int OptionalInt32FieldNumber = 1;
+    private int optionalInt32_;
+    /// <summary>
+    ///  Singular
+    /// </summary>
+    public int OptionalInt32 {
+      get { return optionalInt32_; }
+      set {
+        optionalInt32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_int64" field.</summary>
+    public const int OptionalInt64FieldNumber = 2;
+    private long optionalInt64_;
+    public long OptionalInt64 {
+      get { return optionalInt64_; }
+      set {
+        optionalInt64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_uint32" field.</summary>
+    public const int OptionalUint32FieldNumber = 3;
+    private uint optionalUint32_;
+    public uint OptionalUint32 {
+      get { return optionalUint32_; }
+      set {
+        optionalUint32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_uint64" field.</summary>
+    public const int OptionalUint64FieldNumber = 4;
+    private ulong optionalUint64_;
+    public ulong OptionalUint64 {
+      get { return optionalUint64_; }
+      set {
+        optionalUint64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_sint32" field.</summary>
+    public const int OptionalSint32FieldNumber = 5;
+    private int optionalSint32_;
+    public int OptionalSint32 {
+      get { return optionalSint32_; }
+      set {
+        optionalSint32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_sint64" field.</summary>
+    public const int OptionalSint64FieldNumber = 6;
+    private long optionalSint64_;
+    public long OptionalSint64 {
+      get { return optionalSint64_; }
+      set {
+        optionalSint64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_fixed32" field.</summary>
+    public const int OptionalFixed32FieldNumber = 7;
+    private uint optionalFixed32_;
+    public uint OptionalFixed32 {
+      get { return optionalFixed32_; }
+      set {
+        optionalFixed32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_fixed64" field.</summary>
+    public const int OptionalFixed64FieldNumber = 8;
+    private ulong optionalFixed64_;
+    public ulong OptionalFixed64 {
+      get { return optionalFixed64_; }
+      set {
+        optionalFixed64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_sfixed32" field.</summary>
+    public const int OptionalSfixed32FieldNumber = 9;
+    private int optionalSfixed32_;
+    public int OptionalSfixed32 {
+      get { return optionalSfixed32_; }
+      set {
+        optionalSfixed32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_sfixed64" field.</summary>
+    public const int OptionalSfixed64FieldNumber = 10;
+    private long optionalSfixed64_;
+    public long OptionalSfixed64 {
+      get { return optionalSfixed64_; }
+      set {
+        optionalSfixed64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_float" field.</summary>
+    public const int OptionalFloatFieldNumber = 11;
+    private float optionalFloat_;
+    public float OptionalFloat {
+      get { return optionalFloat_; }
+      set {
+        optionalFloat_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_double" field.</summary>
+    public const int OptionalDoubleFieldNumber = 12;
+    private double optionalDouble_;
+    public double OptionalDouble {
+      get { return optionalDouble_; }
+      set {
+        optionalDouble_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_bool" field.</summary>
+    public const int OptionalBoolFieldNumber = 13;
+    private bool optionalBool_;
+    public bool OptionalBool {
+      get { return optionalBool_; }
+      set {
+        optionalBool_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_string" field.</summary>
+    public const int OptionalStringFieldNumber = 14;
+    private string optionalString_ = "";
+    public string OptionalString {
+      get { return optionalString_; }
+      set {
+        optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "optional_bytes" field.</summary>
+    public const int OptionalBytesFieldNumber = 15;
+    private pb::ByteString optionalBytes_ = pb::ByteString.Empty;
+    public pb::ByteString OptionalBytes {
+      get { return optionalBytes_; }
+      set {
+        optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "optional_nested_message" field.</summary>
+    public const int OptionalNestedMessageFieldNumber = 18;
+    private global::Conformance.TestAllTypes.Types.NestedMessage optionalNestedMessage_;
+    public global::Conformance.TestAllTypes.Types.NestedMessage OptionalNestedMessage {
+      get { return optionalNestedMessage_; }
+      set {
+        optionalNestedMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_foreign_message" field.</summary>
+    public const int OptionalForeignMessageFieldNumber = 19;
+    private global::Conformance.ForeignMessage optionalForeignMessage_;
+    public global::Conformance.ForeignMessage OptionalForeignMessage {
+      get { return optionalForeignMessage_; }
+      set {
+        optionalForeignMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_nested_enum" field.</summary>
+    public const int OptionalNestedEnumFieldNumber = 21;
+    private global::Conformance.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = 0;
+    public global::Conformance.TestAllTypes.Types.NestedEnum OptionalNestedEnum {
+      get { return optionalNestedEnum_; }
+      set {
+        optionalNestedEnum_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_foreign_enum" field.</summary>
+    public const int OptionalForeignEnumFieldNumber = 22;
+    private global::Conformance.ForeignEnum optionalForeignEnum_ = 0;
+    public global::Conformance.ForeignEnum OptionalForeignEnum {
+      get { return optionalForeignEnum_; }
+      set {
+        optionalForeignEnum_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_string_piece" field.</summary>
+    public const int OptionalStringPieceFieldNumber = 24;
+    private string optionalStringPiece_ = "";
+    public string OptionalStringPiece {
+      get { return optionalStringPiece_; }
+      set {
+        optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "optional_cord" field.</summary>
+    public const int OptionalCordFieldNumber = 25;
+    private string optionalCord_ = "";
+    public string OptionalCord {
+      get { return optionalCord_; }
+      set {
+        optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "recursive_message" field.</summary>
+    public const int RecursiveMessageFieldNumber = 27;
+    private global::Conformance.TestAllTypes recursiveMessage_;
+    public global::Conformance.TestAllTypes RecursiveMessage {
+      get { return recursiveMessage_; }
+      set {
+        recursiveMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "repeated_int32" field.</summary>
+    public const int RepeatedInt32FieldNumber = 31;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(250);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Repeated
+    /// </summary>
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    /// <summary>Field number for the "repeated_int64" field.</summary>
+    public const int RepeatedInt64FieldNumber = 32;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(258);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint32" field.</summary>
+    public const int RepeatedUint32FieldNumber = 33;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedUint32_codec
+        = pb::FieldCodec.ForUInt32(266);
+    private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedUint32 {
+      get { return repeatedUint32_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint64" field.</summary>
+    public const int RepeatedUint64FieldNumber = 34;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(274);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    /// <summary>Field number for the "repeated_sint32" field.</summary>
+    public const int RepeatedSint32FieldNumber = 35;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSint32_codec
+        = pb::FieldCodec.ForSInt32(282);
+    private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSint32 {
+      get { return repeatedSint32_; }
+    }
+
+    /// <summary>Field number for the "repeated_sint64" field.</summary>
+    public const int RepeatedSint64FieldNumber = 36;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSint64_codec
+        = pb::FieldCodec.ForSInt64(290);
+    private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSint64 {
+      get { return repeatedSint64_; }
+    }
+
+    /// <summary>Field number for the "repeated_fixed32" field.</summary>
+    public const int RepeatedFixed32FieldNumber = 37;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(298);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    /// <summary>Field number for the "repeated_fixed64" field.</summary>
+    public const int RepeatedFixed64FieldNumber = 38;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(306);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    /// <summary>Field number for the "repeated_sfixed32" field.</summary>
+    public const int RepeatedSfixed32FieldNumber = 39;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(314);
+    private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSfixed32 {
+      get { return repeatedSfixed32_; }
+    }
+
+    /// <summary>Field number for the "repeated_sfixed64" field.</summary>
+    public const int RepeatedSfixed64FieldNumber = 40;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(322);
+    private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSfixed64 {
+      get { return repeatedSfixed64_; }
+    }
+
+    /// <summary>Field number for the "repeated_float" field.</summary>
+    public const int RepeatedFloatFieldNumber = 41;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(330);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    /// <summary>Field number for the "repeated_double" field.</summary>
+    public const int RepeatedDoubleFieldNumber = 42;
+    private static readonly pb::FieldCodec<double> _repeated_repeatedDouble_codec
+        = pb::FieldCodec.ForDouble(338);
+    private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> RepeatedDouble {
+      get { return repeatedDouble_; }
+    }
+
+    /// <summary>Field number for the "repeated_bool" field.</summary>
+    public const int RepeatedBoolFieldNumber = 43;
+    private static readonly pb::FieldCodec<bool> _repeated_repeatedBool_codec
+        = pb::FieldCodec.ForBool(346);
+    private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> RepeatedBool {
+      get { return repeatedBool_; }
+    }
+
+    /// <summary>Field number for the "repeated_string" field.</summary>
+    public const int RepeatedStringFieldNumber = 44;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedString_codec
+        = pb::FieldCodec.ForString(354);
+    private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedString {
+      get { return repeatedString_; }
+    }
+
+    /// <summary>Field number for the "repeated_bytes" field.</summary>
+    public const int RepeatedBytesFieldNumber = 45;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytes_codec
+        = pb::FieldCodec.ForBytes(362);
+    private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
+      get { return repeatedBytes_; }
+    }
+
+    /// <summary>Field number for the "repeated_nested_message" field.</summary>
+    public const int RepeatedNestedMessageFieldNumber = 48;
+    private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
+        = pb::FieldCodec.ForMessage(386, global::Conformance.TestAllTypes.Types.NestedMessage.Parser);
+    private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage>();
+    public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
+      get { return repeatedNestedMessage_; }
+    }
+
+    /// <summary>Field number for the "repeated_foreign_message" field.</summary>
+    public const int RepeatedForeignMessageFieldNumber = 49;
+    private static readonly pb::FieldCodec<global::Conformance.ForeignMessage> _repeated_repeatedForeignMessage_codec
+        = pb::FieldCodec.ForMessage(394, global::Conformance.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Conformance.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Conformance.ForeignMessage>();
+    public pbc::RepeatedField<global::Conformance.ForeignMessage> RepeatedForeignMessage {
+      get { return repeatedForeignMessage_; }
+    }
+
+    /// <summary>Field number for the "repeated_nested_enum" field.</summary>
+    public const int RepeatedNestedEnumFieldNumber = 51;
+    private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum>();
+    public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
+      get { return repeatedNestedEnum_; }
+    }
+
+    /// <summary>Field number for the "repeated_foreign_enum" field.</summary>
+    public const int RepeatedForeignEnumFieldNumber = 52;
+    private static readonly pb::FieldCodec<global::Conformance.ForeignEnum> _repeated_repeatedForeignEnum_codec
+        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Conformance.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Conformance.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Conformance.ForeignEnum>();
+    public pbc::RepeatedField<global::Conformance.ForeignEnum> RepeatedForeignEnum {
+      get { return repeatedForeignEnum_; }
+    }
+
+    /// <summary>Field number for the "repeated_string_piece" field.</summary>
+    public const int RepeatedStringPieceFieldNumber = 54;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedStringPiece_codec
+        = pb::FieldCodec.ForString(434);
+    private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedStringPiece {
+      get { return repeatedStringPiece_; }
+    }
+
+    /// <summary>Field number for the "repeated_cord" field.</summary>
+    public const int RepeatedCordFieldNumber = 55;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedCord_codec
+        = pb::FieldCodec.ForString(442);
+    private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedCord {
+      get { return repeatedCord_; }
+    }
+
+    /// <summary>Field number for the "map_int32_int32" field.</summary>
+    public const int MapInt32Int32FieldNumber = 56;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 450);
+    private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
+    /// <summary>
+    ///  Map
+    /// </summary>
+    public pbc::MapField<int, int> MapInt32Int32 {
+      get { return mapInt32Int32_; }
+    }
+
+    /// <summary>Field number for the "map_int64_int64" field.</summary>
+    public const int MapInt64Int64FieldNumber = 57;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 458);
+    private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapInt64Int64 {
+      get { return mapInt64Int64_; }
+    }
+
+    /// <summary>Field number for the "map_uint32_uint32" field.</summary>
+    public const int MapUint32Uint32FieldNumber = 58;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 466);
+    private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapUint32Uint32 {
+      get { return mapUint32Uint32_; }
+    }
+
+    /// <summary>Field number for the "map_uint64_uint64" field.</summary>
+    public const int MapUint64Uint64FieldNumber = 59;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 474);
+    private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapUint64Uint64 {
+      get { return mapUint64Uint64_; }
+    }
+
+    /// <summary>Field number for the "map_sint32_sint32" field.</summary>
+    public const int MapSint32Sint32FieldNumber = 60;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 482);
+    private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSint32Sint32 {
+      get { return mapSint32Sint32_; }
+    }
+
+    /// <summary>Field number for the "map_sint64_sint64" field.</summary>
+    public const int MapSint64Sint64FieldNumber = 61;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 490);
+    private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSint64Sint64 {
+      get { return mapSint64Sint64_; }
+    }
+
+    /// <summary>Field number for the "map_fixed32_fixed32" field.</summary>
+    public const int MapFixed32Fixed32FieldNumber = 62;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 498);
+    private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapFixed32Fixed32 {
+      get { return mapFixed32Fixed32_; }
+    }
+
+    /// <summary>Field number for the "map_fixed64_fixed64" field.</summary>
+    public const int MapFixed64Fixed64FieldNumber = 63;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 506);
+    private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
+      get { return mapFixed64Fixed64_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed32_sfixed32" field.</summary>
+    public const int MapSfixed32Sfixed32FieldNumber = 64;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 514);
+    private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSfixed32Sfixed32 {
+      get { return mapSfixed32Sfixed32_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed64_sfixed64" field.</summary>
+    public const int MapSfixed64Sfixed64FieldNumber = 65;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 522);
+    private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSfixed64Sfixed64 {
+      get { return mapSfixed64Sfixed64_; }
+    }
+
+    /// <summary>Field number for the "map_int32_float" field.</summary>
+    public const int MapInt32FloatFieldNumber = 66;
+    private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec
+        = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 530);
+    private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
+    public pbc::MapField<int, float> MapInt32Float {
+      get { return mapInt32Float_; }
+    }
+
+    /// <summary>Field number for the "map_int32_double" field.</summary>
+    public const int MapInt32DoubleFieldNumber = 67;
+    private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec
+        = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 538);
+    private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
+    public pbc::MapField<int, double> MapInt32Double {
+      get { return mapInt32Double_; }
+    }
+
+    /// <summary>Field number for the "map_bool_bool" field.</summary>
+    public const int MapBoolBoolFieldNumber = 68;
+    private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec
+        = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 546);
+    private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
+    public pbc::MapField<bool, bool> MapBoolBool {
+      get { return mapBoolBool_; }
+    }
+
+    /// <summary>Field number for the "map_string_string" field.</summary>
+    public const int MapStringStringFieldNumber = 69;
+    private static readonly pbc::MapField<string, string>.Codec _map_mapStringString_codec
+        = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 554);
+    private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
+    public pbc::MapField<string, string> MapStringString {
+      get { return mapStringString_; }
+    }
+
+    /// <summary>Field number for the "map_string_bytes" field.</summary>
+    public const int MapStringBytesFieldNumber = 70;
+    private static readonly pbc::MapField<string, pb::ByteString>.Codec _map_mapStringBytes_codec
+        = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForBytes(18), 562);
+    private readonly pbc::MapField<string, pb::ByteString> mapStringBytes_ = new pbc::MapField<string, pb::ByteString>();
+    public pbc::MapField<string, pb::ByteString> MapStringBytes {
+      get { return mapStringBytes_; }
+    }
+
+    /// <summary>Field number for the "map_string_nested_message" field.</summary>
+    public const int MapStringNestedMessageFieldNumber = 71;
+    private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec _map_mapStringNestedMessage_codec
+        = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.TestAllTypes.Types.NestedMessage.Parser), 570);
+    private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>();
+    public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> MapStringNestedMessage {
+      get { return mapStringNestedMessage_; }
+    }
+
+    /// <summary>Field number for the "map_string_foreign_message" field.</summary>
+    public const int MapStringForeignMessageFieldNumber = 72;
+    private static readonly pbc::MapField<string, global::Conformance.ForeignMessage>.Codec _map_mapStringForeignMessage_codec
+        = new pbc::MapField<string, global::Conformance.ForeignMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.ForeignMessage.Parser), 578);
+    private readonly pbc::MapField<string, global::Conformance.ForeignMessage> mapStringForeignMessage_ = new pbc::MapField<string, global::Conformance.ForeignMessage>();
+    public pbc::MapField<string, global::Conformance.ForeignMessage> MapStringForeignMessage {
+      get { return mapStringForeignMessage_; }
+    }
+
+    /// <summary>Field number for the "map_string_nested_enum" field.</summary>
+    public const int MapStringNestedEnumFieldNumber = 73;
+    private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec _map_mapStringNestedEnum_codec
+        = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x), 586);
+    private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>();
+    public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> MapStringNestedEnum {
+      get { return mapStringNestedEnum_; }
+    }
+
+    /// <summary>Field number for the "map_string_foreign_enum" field.</summary>
+    public const int MapStringForeignEnumFieldNumber = 74;
+    private static readonly pbc::MapField<string, global::Conformance.ForeignEnum>.Codec _map_mapStringForeignEnum_codec
+        = new pbc::MapField<string, global::Conformance.ForeignEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.ForeignEnum) x), 594);
+    private readonly pbc::MapField<string, global::Conformance.ForeignEnum> mapStringForeignEnum_ = new pbc::MapField<string, global::Conformance.ForeignEnum>();
+    public pbc::MapField<string, global::Conformance.ForeignEnum> MapStringForeignEnum {
+      get { return mapStringForeignEnum_; }
+    }
+
+    /// <summary>Field number for the "oneof_uint32" field.</summary>
+    public const int OneofUint32FieldNumber = 111;
+    public uint OneofUint32 {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = OneofFieldOneofCase.OneofUint32;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_nested_message" field.</summary>
+    public const int OneofNestedMessageFieldNumber = 112;
+    public global::Conformance.TestAllTypes.Types.NestedMessage OneofNestedMessage {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Conformance.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_string" field.</summary>
+    public const int OneofStringFieldNumber = 113;
+    public string OneofString {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
+      set {
+        oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofString;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_bytes" field.</summary>
+    public const int OneofBytesFieldNumber = 114;
+    public pb::ByteString OneofBytes {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
+      set {
+        oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofBytes;
+      }
+    }
+
+    /// <summary>Field number for the "optional_bool_wrapper" field.</summary>
+    public const int OptionalBoolWrapperFieldNumber = 201;
+    private static readonly pb::FieldCodec<bool?> _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper<bool>(1610);
+    private bool? optionalBoolWrapper_;
+    /// <summary>
+    ///  Well-known types
+    /// </summary>
+    public bool? OptionalBoolWrapper {
+      get { return optionalBoolWrapper_; }
+      set {
+        optionalBoolWrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_int32_wrapper" field.</summary>
+    public const int OptionalInt32WrapperFieldNumber = 202;
+    private static readonly pb::FieldCodec<int?> _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper<int>(1618);
+    private int? optionalInt32Wrapper_;
+    public int? OptionalInt32Wrapper {
+      get { return optionalInt32Wrapper_; }
+      set {
+        optionalInt32Wrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_int64_wrapper" field.</summary>
+    public const int OptionalInt64WrapperFieldNumber = 203;
+    private static readonly pb::FieldCodec<long?> _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper<long>(1626);
+    private long? optionalInt64Wrapper_;
+    public long? OptionalInt64Wrapper {
+      get { return optionalInt64Wrapper_; }
+      set {
+        optionalInt64Wrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_uint32_wrapper" field.</summary>
+    public const int OptionalUint32WrapperFieldNumber = 204;
+    private static readonly pb::FieldCodec<uint?> _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper<uint>(1634);
+    private uint? optionalUint32Wrapper_;
+    public uint? OptionalUint32Wrapper {
+      get { return optionalUint32Wrapper_; }
+      set {
+        optionalUint32Wrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_uint64_wrapper" field.</summary>
+    public const int OptionalUint64WrapperFieldNumber = 205;
+    private static readonly pb::FieldCodec<ulong?> _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper<ulong>(1642);
+    private ulong? optionalUint64Wrapper_;
+    public ulong? OptionalUint64Wrapper {
+      get { return optionalUint64Wrapper_; }
+      set {
+        optionalUint64Wrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_float_wrapper" field.</summary>
+    public const int OptionalFloatWrapperFieldNumber = 206;
+    private static readonly pb::FieldCodec<float?> _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper<float>(1650);
+    private float? optionalFloatWrapper_;
+    public float? OptionalFloatWrapper {
+      get { return optionalFloatWrapper_; }
+      set {
+        optionalFloatWrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_double_wrapper" field.</summary>
+    public const int OptionalDoubleWrapperFieldNumber = 207;
+    private static readonly pb::FieldCodec<double?> _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper<double>(1658);
+    private double? optionalDoubleWrapper_;
+    public double? OptionalDoubleWrapper {
+      get { return optionalDoubleWrapper_; }
+      set {
+        optionalDoubleWrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_string_wrapper" field.</summary>
+    public const int OptionalStringWrapperFieldNumber = 208;
+    private static readonly pb::FieldCodec<string> _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper<string>(1666);
+    private string optionalStringWrapper_;
+    public string OptionalStringWrapper {
+      get { return optionalStringWrapper_; }
+      set {
+        optionalStringWrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_bytes_wrapper" field.</summary>
+    public const int OptionalBytesWrapperFieldNumber = 209;
+    private static readonly pb::FieldCodec<pb::ByteString> _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1674);
+    private pb::ByteString optionalBytesWrapper_;
+    public pb::ByteString OptionalBytesWrapper {
+      get { return optionalBytesWrapper_; }
+      set {
+        optionalBytesWrapper_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "repeated_bool_wrapper" field.</summary>
+    public const int RepeatedBoolWrapperFieldNumber = 211;
+    private static readonly pb::FieldCodec<bool?> _repeated_repeatedBoolWrapper_codec
+        = pb::FieldCodec.ForStructWrapper<bool>(1690);
+    private readonly pbc::RepeatedField<bool?> repeatedBoolWrapper_ = new pbc::RepeatedField<bool?>();
+    public pbc::RepeatedField<bool?> RepeatedBoolWrapper {
+      get { return repeatedBoolWrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_int32_wrapper" field.</summary>
+    public const int RepeatedInt32WrapperFieldNumber = 212;
+    private static readonly pb::FieldCodec<int?> _repeated_repeatedInt32Wrapper_codec
+        = pb::FieldCodec.ForStructWrapper<int>(1698);
+    private readonly pbc::RepeatedField<int?> repeatedInt32Wrapper_ = new pbc::RepeatedField<int?>();
+    public pbc::RepeatedField<int?> RepeatedInt32Wrapper {
+      get { return repeatedInt32Wrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_int64_wrapper" field.</summary>
+    public const int RepeatedInt64WrapperFieldNumber = 213;
+    private static readonly pb::FieldCodec<long?> _repeated_repeatedInt64Wrapper_codec
+        = pb::FieldCodec.ForStructWrapper<long>(1706);
+    private readonly pbc::RepeatedField<long?> repeatedInt64Wrapper_ = new pbc::RepeatedField<long?>();
+    public pbc::RepeatedField<long?> RepeatedInt64Wrapper {
+      get { return repeatedInt64Wrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint32_wrapper" field.</summary>
+    public const int RepeatedUint32WrapperFieldNumber = 214;
+    private static readonly pb::FieldCodec<uint?> _repeated_repeatedUint32Wrapper_codec
+        = pb::FieldCodec.ForStructWrapper<uint>(1714);
+    private readonly pbc::RepeatedField<uint?> repeatedUint32Wrapper_ = new pbc::RepeatedField<uint?>();
+    public pbc::RepeatedField<uint?> RepeatedUint32Wrapper {
+      get { return repeatedUint32Wrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint64_wrapper" field.</summary>
+    public const int RepeatedUint64WrapperFieldNumber = 215;
+    private static readonly pb::FieldCodec<ulong?> _repeated_repeatedUint64Wrapper_codec
+        = pb::FieldCodec.ForStructWrapper<ulong>(1722);
+    private readonly pbc::RepeatedField<ulong?> repeatedUint64Wrapper_ = new pbc::RepeatedField<ulong?>();
+    public pbc::RepeatedField<ulong?> RepeatedUint64Wrapper {
+      get { return repeatedUint64Wrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_float_wrapper" field.</summary>
+    public const int RepeatedFloatWrapperFieldNumber = 216;
+    private static readonly pb::FieldCodec<float?> _repeated_repeatedFloatWrapper_codec
+        = pb::FieldCodec.ForStructWrapper<float>(1730);
+    private readonly pbc::RepeatedField<float?> repeatedFloatWrapper_ = new pbc::RepeatedField<float?>();
+    public pbc::RepeatedField<float?> RepeatedFloatWrapper {
+      get { return repeatedFloatWrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_double_wrapper" field.</summary>
+    public const int RepeatedDoubleWrapperFieldNumber = 217;
+    private static readonly pb::FieldCodec<double?> _repeated_repeatedDoubleWrapper_codec
+        = pb::FieldCodec.ForStructWrapper<double>(1738);
+    private readonly pbc::RepeatedField<double?> repeatedDoubleWrapper_ = new pbc::RepeatedField<double?>();
+    public pbc::RepeatedField<double?> RepeatedDoubleWrapper {
+      get { return repeatedDoubleWrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_string_wrapper" field.</summary>
+    public const int RepeatedStringWrapperFieldNumber = 218;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedStringWrapper_codec
+        = pb::FieldCodec.ForClassWrapper<string>(1746);
+    private readonly pbc::RepeatedField<string> repeatedStringWrapper_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedStringWrapper {
+      get { return repeatedStringWrapper_; }
+    }
+
+    /// <summary>Field number for the "repeated_bytes_wrapper" field.</summary>
+    public const int RepeatedBytesWrapperFieldNumber = 219;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytesWrapper_codec
+        = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1754);
+    private readonly pbc::RepeatedField<pb::ByteString> repeatedBytesWrapper_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> RepeatedBytesWrapper {
+      get { return repeatedBytesWrapper_; }
+    }
+
+    /// <summary>Field number for the "optional_duration" field.</summary>
+    public const int OptionalDurationFieldNumber = 301;
+    private global::Google.Protobuf.WellKnownTypes.Duration optionalDuration_;
+    public global::Google.Protobuf.WellKnownTypes.Duration OptionalDuration {
+      get { return optionalDuration_; }
+      set {
+        optionalDuration_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_timestamp" field.</summary>
+    public const int OptionalTimestampFieldNumber = 302;
+    private global::Google.Protobuf.WellKnownTypes.Timestamp optionalTimestamp_;
+    public global::Google.Protobuf.WellKnownTypes.Timestamp OptionalTimestamp {
+      get { return optionalTimestamp_; }
+      set {
+        optionalTimestamp_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_field_mask" field.</summary>
+    public const int OptionalFieldMaskFieldNumber = 303;
+    private global::Google.Protobuf.WellKnownTypes.FieldMask optionalFieldMask_;
+    public global::Google.Protobuf.WellKnownTypes.FieldMask OptionalFieldMask {
+      get { return optionalFieldMask_; }
+      set {
+        optionalFieldMask_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_struct" field.</summary>
+    public const int OptionalStructFieldNumber = 304;
+    private global::Google.Protobuf.WellKnownTypes.Struct optionalStruct_;
+    public global::Google.Protobuf.WellKnownTypes.Struct OptionalStruct {
+      get { return optionalStruct_; }
+      set {
+        optionalStruct_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_any" field.</summary>
+    public const int OptionalAnyFieldNumber = 305;
+    private global::Google.Protobuf.WellKnownTypes.Any optionalAny_;
+    public global::Google.Protobuf.WellKnownTypes.Any OptionalAny {
+      get { return optionalAny_; }
+      set {
+        optionalAny_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_value" field.</summary>
+    public const int OptionalValueFieldNumber = 306;
+    private global::Google.Protobuf.WellKnownTypes.Value optionalValue_;
+    public global::Google.Protobuf.WellKnownTypes.Value OptionalValue {
+      get { return optionalValue_; }
+      set {
+        optionalValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "repeated_duration" field.</summary>
+    public const int RepeatedDurationFieldNumber = 311;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Duration> _repeated_repeatedDuration_codec
+        = pb::FieldCodec.ForMessage(2490, global::Google.Protobuf.WellKnownTypes.Duration.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> repeatedDuration_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> RepeatedDuration {
+      get { return repeatedDuration_; }
+    }
+
+    /// <summary>Field number for the "repeated_timestamp" field.</summary>
+    public const int RepeatedTimestampFieldNumber = 312;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Timestamp> _repeated_repeatedTimestamp_codec
+        = pb::FieldCodec.ForMessage(2498, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> repeatedTimestamp_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> RepeatedTimestamp {
+      get { return repeatedTimestamp_; }
+    }
+
+    /// <summary>Field number for the "repeated_fieldmask" field.</summary>
+    public const int RepeatedFieldmaskFieldNumber = 313;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.FieldMask> _repeated_repeatedFieldmask_codec
+        = pb::FieldCodec.ForMessage(2506, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> repeatedFieldmask_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> RepeatedFieldmask {
+      get { return repeatedFieldmask_; }
+    }
+
+    /// <summary>Field number for the "repeated_struct" field.</summary>
+    public const int RepeatedStructFieldNumber = 324;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Struct> _repeated_repeatedStruct_codec
+        = pb::FieldCodec.ForMessage(2594, global::Google.Protobuf.WellKnownTypes.Struct.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> repeatedStruct_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> RepeatedStruct {
+      get { return repeatedStruct_; }
+    }
+
+    /// <summary>Field number for the "repeated_any" field.</summary>
+    public const int RepeatedAnyFieldNumber = 315;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Any> _repeated_repeatedAny_codec
+        = pb::FieldCodec.ForMessage(2522, global::Google.Protobuf.WellKnownTypes.Any.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> repeatedAny_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> RepeatedAny {
+      get { return repeatedAny_; }
+    }
+
+    /// <summary>Field number for the "repeated_value" field.</summary>
+    public const int RepeatedValueFieldNumber = 316;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Value> _repeated_repeatedValue_codec
+        = pb::FieldCodec.ForMessage(2530, global::Google.Protobuf.WellKnownTypes.Value.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> repeatedValue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> RepeatedValue {
+      get { return repeatedValue_; }
+    }
+
+    /// <summary>Field number for the "fieldname1" field.</summary>
+    public const int Fieldname1FieldNumber = 401;
+    private int fieldname1_;
+    /// <summary>
+    ///  Test field-name-to-JSON-name convention.
+    /// </summary>
+    public int Fieldname1 {
+      get { return fieldname1_; }
+      set {
+        fieldname1_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field_name2" field.</summary>
+    public const int FieldName2FieldNumber = 402;
+    private int fieldName2_;
+    public int FieldName2 {
+      get { return fieldName2_; }
+      set {
+        fieldName2_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "_field_name3" field.</summary>
+    public const int FieldName3FieldNumber = 403;
+    private int FieldName3_;
+    public int FieldName3 {
+      get { return FieldName3_; }
+      set {
+        FieldName3_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field__name4_" field.</summary>
+    public const int FieldName4FieldNumber = 404;
+    private int fieldName4_;
+    public int FieldName4 {
+      get { return fieldName4_; }
+      set {
+        fieldName4_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field0name5" field.</summary>
+    public const int Field0Name5FieldNumber = 405;
+    private int field0Name5_;
+    public int Field0Name5 {
+      get { return field0Name5_; }
+      set {
+        field0Name5_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field_0_name6" field.</summary>
+    public const int Field0Name6FieldNumber = 406;
+    private int field0Name6_;
+    public int Field0Name6 {
+      get { return field0Name6_; }
+      set {
+        field0Name6_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "fieldName7" field.</summary>
+    public const int FieldName7FieldNumber = 407;
+    private int fieldName7_;
+    public int FieldName7 {
+      get { return fieldName7_; }
+      set {
+        fieldName7_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "FieldName8" field.</summary>
+    public const int FieldName8FieldNumber = 408;
+    private int fieldName8_;
+    public int FieldName8 {
+      get { return fieldName8_; }
+      set {
+        fieldName8_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field_Name9" field.</summary>
+    public const int FieldName9FieldNumber = 409;
+    private int fieldName9_;
+    public int FieldName9 {
+      get { return fieldName9_; }
+      set {
+        fieldName9_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "Field_Name10" field.</summary>
+    public const int FieldName10FieldNumber = 410;
+    private int fieldName10_;
+    public int FieldName10 {
+      get { return fieldName10_; }
+      set {
+        fieldName10_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "FIELD_NAME11" field.</summary>
+    public const int FIELDNAME11FieldNumber = 411;
+    private int fIELDNAME11_;
+    public int FIELDNAME11 {
+      get { return fIELDNAME11_; }
+      set {
+        fIELDNAME11_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "FIELD_name12" field.</summary>
+    public const int FIELDName12FieldNumber = 412;
+    private int fIELDName12_;
+    public int FIELDName12 {
+      get { return fIELDName12_; }
+      set {
+        fIELDName12_ = value;
+      }
+    }
+
+    private object oneofField_;
+    /// <summary>Enum of possible cases for the "oneof_field" oneof.</summary>
+    public enum OneofFieldOneofCase {
+      None = 0,
+      OneofUint32 = 111,
+      OneofNestedMessage = 112,
+      OneofString = 113,
+      OneofBytes = 114,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestAllTypes);
+    }
+
+    public bool Equals(TestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (OptionalInt32 != other.OptionalInt32) return false;
+      if (OptionalInt64 != other.OptionalInt64) return false;
+      if (OptionalUint32 != other.OptionalUint32) return false;
+      if (OptionalUint64 != other.OptionalUint64) return false;
+      if (OptionalSint32 != other.OptionalSint32) return false;
+      if (OptionalSint64 != other.OptionalSint64) return false;
+      if (OptionalFixed32 != other.OptionalFixed32) return false;
+      if (OptionalFixed64 != other.OptionalFixed64) return false;
+      if (OptionalSfixed32 != other.OptionalSfixed32) return false;
+      if (OptionalSfixed64 != other.OptionalSfixed64) return false;
+      if (OptionalFloat != other.OptionalFloat) return false;
+      if (OptionalDouble != other.OptionalDouble) return false;
+      if (OptionalBool != other.OptionalBool) return false;
+      if (OptionalString != other.OptionalString) return false;
+      if (OptionalBytes != other.OptionalBytes) return false;
+      if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false;
+      if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false;
+      if (OptionalNestedEnum != other.OptionalNestedEnum) return false;
+      if (OptionalForeignEnum != other.OptionalForeignEnum) return false;
+      if (OptionalStringPiece != other.OptionalStringPiece) return false;
+      if (OptionalCord != other.OptionalCord) return false;
+      if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false;
+      if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false;
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false;
+      if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false;
+      if(!repeatedBool_.Equals(other.repeatedBool_)) return false;
+      if(!repeatedString_.Equals(other.repeatedString_)) return false;
+      if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false;
+      if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false;
+      if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false;
+      if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false;
+      if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false;
+      if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false;
+      if(!repeatedCord_.Equals(other.repeatedCord_)) return false;
+      if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false;
+      if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false;
+      if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false;
+      if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false;
+      if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false;
+      if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false;
+      if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false;
+      if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false;
+      if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false;
+      if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false;
+      if (!MapInt32Float.Equals(other.MapInt32Float)) return false;
+      if (!MapInt32Double.Equals(other.MapInt32Double)) return false;
+      if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
+      if (!MapStringString.Equals(other.MapStringString)) return false;
+      if (!MapStringBytes.Equals(other.MapStringBytes)) return false;
+      if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false;
+      if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false;
+      if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false;
+      if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false;
+      if (OneofUint32 != other.OneofUint32) return false;
+      if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;
+      if (OneofString != other.OneofString) return false;
+      if (OneofBytes != other.OneofBytes) return false;
+      if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
+      if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
+      if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
+      if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false;
+      if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false;
+      if (OptionalFloatWrapper != other.OptionalFloatWrapper) return false;
+      if (OptionalDoubleWrapper != other.OptionalDoubleWrapper) return false;
+      if (OptionalStringWrapper != other.OptionalStringWrapper) return false;
+      if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false;
+      if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false;
+      if(!repeatedInt32Wrapper_.Equals(other.repeatedInt32Wrapper_)) return false;
+      if(!repeatedInt64Wrapper_.Equals(other.repeatedInt64Wrapper_)) return false;
+      if(!repeatedUint32Wrapper_.Equals(other.repeatedUint32Wrapper_)) return false;
+      if(!repeatedUint64Wrapper_.Equals(other.repeatedUint64Wrapper_)) return false;
+      if(!repeatedFloatWrapper_.Equals(other.repeatedFloatWrapper_)) return false;
+      if(!repeatedDoubleWrapper_.Equals(other.repeatedDoubleWrapper_)) return false;
+      if(!repeatedStringWrapper_.Equals(other.repeatedStringWrapper_)) return false;
+      if(!repeatedBytesWrapper_.Equals(other.repeatedBytesWrapper_)) return false;
+      if (!object.Equals(OptionalDuration, other.OptionalDuration)) return false;
+      if (!object.Equals(OptionalTimestamp, other.OptionalTimestamp)) return false;
+      if (!object.Equals(OptionalFieldMask, other.OptionalFieldMask)) return false;
+      if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false;
+      if (!object.Equals(OptionalAny, other.OptionalAny)) return false;
+      if (!object.Equals(OptionalValue, other.OptionalValue)) return false;
+      if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false;
+      if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false;
+      if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false;
+      if(!repeatedStruct_.Equals(other.repeatedStruct_)) return false;
+      if(!repeatedAny_.Equals(other.repeatedAny_)) return false;
+      if(!repeatedValue_.Equals(other.repeatedValue_)) return false;
+      if (Fieldname1 != other.Fieldname1) return false;
+      if (FieldName2 != other.FieldName2) return false;
+      if (FieldName3 != other.FieldName3) return false;
+      if (FieldName4 != other.FieldName4) return false;
+      if (Field0Name5 != other.Field0Name5) return false;
+      if (Field0Name6 != other.Field0Name6) return false;
+      if (FieldName7 != other.FieldName7) return false;
+      if (FieldName8 != other.FieldName8) return false;
+      if (FieldName9 != other.FieldName9) return false;
+      if (FieldName10 != other.FieldName10) return false;
+      if (FIELDNAME11 != other.FIELDNAME11) return false;
+      if (FIELDName12 != other.FIELDName12) return false;
+      if (OneofFieldCase != other.OneofFieldCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
+      if (OptionalInt64 != 0L) hash ^= OptionalInt64.GetHashCode();
+      if (OptionalUint32 != 0) hash ^= OptionalUint32.GetHashCode();
+      if (OptionalUint64 != 0UL) hash ^= OptionalUint64.GetHashCode();
+      if (OptionalSint32 != 0) hash ^= OptionalSint32.GetHashCode();
+      if (OptionalSint64 != 0L) hash ^= OptionalSint64.GetHashCode();
+      if (OptionalFixed32 != 0) hash ^= OptionalFixed32.GetHashCode();
+      if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode();
+      if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode();
+      if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode();
+      if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode();
+      if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode();
+      if (OptionalBool != false) hash ^= OptionalBool.GetHashCode();
+      if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode();
+      if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode();
+      if (OptionalNestedEnum != 0) hash ^= OptionalNestedEnum.GetHashCode();
+      if (OptionalForeignEnum != 0) hash ^= OptionalForeignEnum.GetHashCode();
+      if (OptionalStringPiece.Length != 0) hash ^= OptionalStringPiece.GetHashCode();
+      if (OptionalCord.Length != 0) hash ^= OptionalCord.GetHashCode();
+      if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedUint32_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      hash ^= repeatedSint32_.GetHashCode();
+      hash ^= repeatedSint64_.GetHashCode();
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedSfixed32_.GetHashCode();
+      hash ^= repeatedSfixed64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedDouble_.GetHashCode();
+      hash ^= repeatedBool_.GetHashCode();
+      hash ^= repeatedString_.GetHashCode();
+      hash ^= repeatedBytes_.GetHashCode();
+      hash ^= repeatedNestedMessage_.GetHashCode();
+      hash ^= repeatedForeignMessage_.GetHashCode();
+      hash ^= repeatedNestedEnum_.GetHashCode();
+      hash ^= repeatedForeignEnum_.GetHashCode();
+      hash ^= repeatedStringPiece_.GetHashCode();
+      hash ^= repeatedCord_.GetHashCode();
+      hash ^= MapInt32Int32.GetHashCode();
+      hash ^= MapInt64Int64.GetHashCode();
+      hash ^= MapUint32Uint32.GetHashCode();
+      hash ^= MapUint64Uint64.GetHashCode();
+      hash ^= MapSint32Sint32.GetHashCode();
+      hash ^= MapSint64Sint64.GetHashCode();
+      hash ^= MapFixed32Fixed32.GetHashCode();
+      hash ^= MapFixed64Fixed64.GetHashCode();
+      hash ^= MapSfixed32Sfixed32.GetHashCode();
+      hash ^= MapSfixed64Sfixed64.GetHashCode();
+      hash ^= MapInt32Float.GetHashCode();
+      hash ^= MapInt32Double.GetHashCode();
+      hash ^= MapBoolBool.GetHashCode();
+      hash ^= MapStringString.GetHashCode();
+      hash ^= MapStringBytes.GetHashCode();
+      hash ^= MapStringNestedMessage.GetHashCode();
+      hash ^= MapStringForeignMessage.GetHashCode();
+      hash ^= MapStringNestedEnum.GetHashCode();
+      hash ^= MapStringForeignEnum.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
+      if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
+      if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
+      if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
+      if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode();
+      if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode();
+      if (optionalFloatWrapper_ != null) hash ^= OptionalFloatWrapper.GetHashCode();
+      if (optionalDoubleWrapper_ != null) hash ^= OptionalDoubleWrapper.GetHashCode();
+      if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode();
+      if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode();
+      hash ^= repeatedBoolWrapper_.GetHashCode();
+      hash ^= repeatedInt32Wrapper_.GetHashCode();
+      hash ^= repeatedInt64Wrapper_.GetHashCode();
+      hash ^= repeatedUint32Wrapper_.GetHashCode();
+      hash ^= repeatedUint64Wrapper_.GetHashCode();
+      hash ^= repeatedFloatWrapper_.GetHashCode();
+      hash ^= repeatedDoubleWrapper_.GetHashCode();
+      hash ^= repeatedStringWrapper_.GetHashCode();
+      hash ^= repeatedBytesWrapper_.GetHashCode();
+      if (optionalDuration_ != null) hash ^= OptionalDuration.GetHashCode();
+      if (optionalTimestamp_ != null) hash ^= OptionalTimestamp.GetHashCode();
+      if (optionalFieldMask_ != null) hash ^= OptionalFieldMask.GetHashCode();
+      if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode();
+      if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode();
+      if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode();
+      hash ^= repeatedDuration_.GetHashCode();
+      hash ^= repeatedTimestamp_.GetHashCode();
+      hash ^= repeatedFieldmask_.GetHashCode();
+      hash ^= repeatedStruct_.GetHashCode();
+      hash ^= repeatedAny_.GetHashCode();
+      hash ^= repeatedValue_.GetHashCode();
+      if (Fieldname1 != 0) hash ^= Fieldname1.GetHashCode();
+      if (FieldName2 != 0) hash ^= FieldName2.GetHashCode();
+      if (FieldName3 != 0) hash ^= FieldName3.GetHashCode();
+      if (FieldName4 != 0) hash ^= FieldName4.GetHashCode();
+      if (Field0Name5 != 0) hash ^= Field0Name5.GetHashCode();
+      if (Field0Name6 != 0) hash ^= Field0Name6.GetHashCode();
+      if (FieldName7 != 0) hash ^= FieldName7.GetHashCode();
+      if (FieldName8 != 0) hash ^= FieldName8.GetHashCode();
+      if (FieldName9 != 0) hash ^= FieldName9.GetHashCode();
+      if (FieldName10 != 0) hash ^= FieldName10.GetHashCode();
+      if (FIELDNAME11 != 0) hash ^= FIELDNAME11.GetHashCode();
+      if (FIELDName12 != 0) hash ^= FIELDName12.GetHashCode();
+      hash ^= (int) oneofFieldCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (OptionalInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (OptionalUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (OptionalUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (OptionalSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (OptionalSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (OptionalFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (OptionalFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (OptionalSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (OptionalSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (OptionalFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (OptionalDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (OptionalBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (OptionalString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (OptionalBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(OptionalForeignMessage);
+      }
+      if (OptionalNestedEnum != 0) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (OptionalForeignEnum != 0) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (OptionalStringPiece.Length != 0) {
+        output.WriteRawTag(194, 1);
+        output.WriteString(OptionalStringPiece);
+      }
+      if (OptionalCord.Length != 0) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        output.WriteRawTag(218, 1);
+        output.WriteMessage(RecursiveMessage);
+      }
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec);
+      repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec);
+      repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec);
+      repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec);
+      mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(output, _map_mapStringString_codec);
+      mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec);
+      mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec);
+      mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec);
+      mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec);
+      mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+      if (optionalBoolWrapper_ != null) {
+        _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper);
+      }
+      if (optionalInt32Wrapper_ != null) {
+        _single_optionalInt32Wrapper_codec.WriteTagAndValue(output, OptionalInt32Wrapper);
+      }
+      if (optionalInt64Wrapper_ != null) {
+        _single_optionalInt64Wrapper_codec.WriteTagAndValue(output, OptionalInt64Wrapper);
+      }
+      if (optionalUint32Wrapper_ != null) {
+        _single_optionalUint32Wrapper_codec.WriteTagAndValue(output, OptionalUint32Wrapper);
+      }
+      if (optionalUint64Wrapper_ != null) {
+        _single_optionalUint64Wrapper_codec.WriteTagAndValue(output, OptionalUint64Wrapper);
+      }
+      if (optionalFloatWrapper_ != null) {
+        _single_optionalFloatWrapper_codec.WriteTagAndValue(output, OptionalFloatWrapper);
+      }
+      if (optionalDoubleWrapper_ != null) {
+        _single_optionalDoubleWrapper_codec.WriteTagAndValue(output, OptionalDoubleWrapper);
+      }
+      if (optionalStringWrapper_ != null) {
+        _single_optionalStringWrapper_codec.WriteTagAndValue(output, OptionalStringWrapper);
+      }
+      if (optionalBytesWrapper_ != null) {
+        _single_optionalBytesWrapper_codec.WriteTagAndValue(output, OptionalBytesWrapper);
+      }
+      repeatedBoolWrapper_.WriteTo(output, _repeated_repeatedBoolWrapper_codec);
+      repeatedInt32Wrapper_.WriteTo(output, _repeated_repeatedInt32Wrapper_codec);
+      repeatedInt64Wrapper_.WriteTo(output, _repeated_repeatedInt64Wrapper_codec);
+      repeatedUint32Wrapper_.WriteTo(output, _repeated_repeatedUint32Wrapper_codec);
+      repeatedUint64Wrapper_.WriteTo(output, _repeated_repeatedUint64Wrapper_codec);
+      repeatedFloatWrapper_.WriteTo(output, _repeated_repeatedFloatWrapper_codec);
+      repeatedDoubleWrapper_.WriteTo(output, _repeated_repeatedDoubleWrapper_codec);
+      repeatedStringWrapper_.WriteTo(output, _repeated_repeatedStringWrapper_codec);
+      repeatedBytesWrapper_.WriteTo(output, _repeated_repeatedBytesWrapper_codec);
+      if (optionalDuration_ != null) {
+        output.WriteRawTag(234, 18);
+        output.WriteMessage(OptionalDuration);
+      }
+      if (optionalTimestamp_ != null) {
+        output.WriteRawTag(242, 18);
+        output.WriteMessage(OptionalTimestamp);
+      }
+      if (optionalFieldMask_ != null) {
+        output.WriteRawTag(250, 18);
+        output.WriteMessage(OptionalFieldMask);
+      }
+      if (optionalStruct_ != null) {
+        output.WriteRawTag(130, 19);
+        output.WriteMessage(OptionalStruct);
+      }
+      if (optionalAny_ != null) {
+        output.WriteRawTag(138, 19);
+        output.WriteMessage(OptionalAny);
+      }
+      if (optionalValue_ != null) {
+        output.WriteRawTag(146, 19);
+        output.WriteMessage(OptionalValue);
+      }
+      repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec);
+      repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec);
+      repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec);
+      repeatedAny_.WriteTo(output, _repeated_repeatedAny_codec);
+      repeatedValue_.WriteTo(output, _repeated_repeatedValue_codec);
+      repeatedStruct_.WriteTo(output, _repeated_repeatedStruct_codec);
+      if (Fieldname1 != 0) {
+        output.WriteRawTag(136, 25);
+        output.WriteInt32(Fieldname1);
+      }
+      if (FieldName2 != 0) {
+        output.WriteRawTag(144, 25);
+        output.WriteInt32(FieldName2);
+      }
+      if (FieldName3 != 0) {
+        output.WriteRawTag(152, 25);
+        output.WriteInt32(FieldName3);
+      }
+      if (FieldName4 != 0) {
+        output.WriteRawTag(160, 25);
+        output.WriteInt32(FieldName4);
+      }
+      if (Field0Name5 != 0) {
+        output.WriteRawTag(168, 25);
+        output.WriteInt32(Field0Name5);
+      }
+      if (Field0Name6 != 0) {
+        output.WriteRawTag(176, 25);
+        output.WriteInt32(Field0Name6);
+      }
+      if (FieldName7 != 0) {
+        output.WriteRawTag(184, 25);
+        output.WriteInt32(FieldName7);
+      }
+      if (FieldName8 != 0) {
+        output.WriteRawTag(192, 25);
+        output.WriteInt32(FieldName8);
+      }
+      if (FieldName9 != 0) {
+        output.WriteRawTag(200, 25);
+        output.WriteInt32(FieldName9);
+      }
+      if (FieldName10 != 0) {
+        output.WriteRawTag(208, 25);
+        output.WriteInt32(FieldName10);
+      }
+      if (FIELDNAME11 != 0) {
+        output.WriteRawTag(216, 25);
+        output.WriteInt32(FIELDNAME11);
+      }
+      if (FIELDName12 != 0) {
+        output.WriteRawTag(224, 25);
+        output.WriteInt32(FIELDName12);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (OptionalInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+      }
+      if (OptionalInt64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64);
+      }
+      if (OptionalUint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32);
+      }
+      if (OptionalUint64 != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64);
+      }
+      if (OptionalSint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32);
+      }
+      if (OptionalSint64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64);
+      }
+      if (OptionalFixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (OptionalFixed64 != 0UL) {
+        size += 1 + 8;
+      }
+      if (OptionalSfixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (OptionalSfixed64 != 0L) {
+        size += 1 + 8;
+      }
+      if (OptionalFloat != 0F) {
+        size += 1 + 4;
+      }
+      if (OptionalDouble != 0D) {
+        size += 1 + 8;
+      }
+      if (OptionalBool != false) {
+        size += 1 + 1;
+      }
+      if (OptionalString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString);
+      }
+      if (OptionalBytes.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage);
+      }
+      if (OptionalNestedEnum != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum);
+      }
+      if (OptionalForeignEnum != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum);
+      }
+      if (OptionalStringPiece.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece);
+      }
+      if (OptionalCord.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage);
+      }
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec);
+      size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec);
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec);
+      size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec);
+      size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec);
+      size += repeatedString_.CalculateSize(_repeated_repeatedString_codec);
+      size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec);
+      size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec);
+      size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec);
+      size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec);
+      size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec);
+      size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec);
+      size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec);
+      size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
+      size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec);
+      size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec);
+      size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec);
+      size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec);
+      size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec);
+      size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec);
+      size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec);
+      size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec);
+      size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec);
+      size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec);
+      size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec);
+      size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
+      size += mapStringString_.CalculateSize(_map_mapStringString_codec);
+      size += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec);
+      size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec);
+      size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec);
+      size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec);
+      size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes);
+      }
+      if (optionalBoolWrapper_ != null) {
+        size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper);
+      }
+      if (optionalInt32Wrapper_ != null) {
+        size += _single_optionalInt32Wrapper_codec.CalculateSizeWithTag(OptionalInt32Wrapper);
+      }
+      if (optionalInt64Wrapper_ != null) {
+        size += _single_optionalInt64Wrapper_codec.CalculateSizeWithTag(OptionalInt64Wrapper);
+      }
+      if (optionalUint32Wrapper_ != null) {
+        size += _single_optionalUint32Wrapper_codec.CalculateSizeWithTag(OptionalUint32Wrapper);
+      }
+      if (optionalUint64Wrapper_ != null) {
+        size += _single_optionalUint64Wrapper_codec.CalculateSizeWithTag(OptionalUint64Wrapper);
+      }
+      if (optionalFloatWrapper_ != null) {
+        size += _single_optionalFloatWrapper_codec.CalculateSizeWithTag(OptionalFloatWrapper);
+      }
+      if (optionalDoubleWrapper_ != null) {
+        size += _single_optionalDoubleWrapper_codec.CalculateSizeWithTag(OptionalDoubleWrapper);
+      }
+      if (optionalStringWrapper_ != null) {
+        size += _single_optionalStringWrapper_codec.CalculateSizeWithTag(OptionalStringWrapper);
+      }
+      if (optionalBytesWrapper_ != null) {
+        size += _single_optionalBytesWrapper_codec.CalculateSizeWithTag(OptionalBytesWrapper);
+      }
+      size += repeatedBoolWrapper_.CalculateSize(_repeated_repeatedBoolWrapper_codec);
+      size += repeatedInt32Wrapper_.CalculateSize(_repeated_repeatedInt32Wrapper_codec);
+      size += repeatedInt64Wrapper_.CalculateSize(_repeated_repeatedInt64Wrapper_codec);
+      size += repeatedUint32Wrapper_.CalculateSize(_repeated_repeatedUint32Wrapper_codec);
+      size += repeatedUint64Wrapper_.CalculateSize(_repeated_repeatedUint64Wrapper_codec);
+      size += repeatedFloatWrapper_.CalculateSize(_repeated_repeatedFloatWrapper_codec);
+      size += repeatedDoubleWrapper_.CalculateSize(_repeated_repeatedDoubleWrapper_codec);
+      size += repeatedStringWrapper_.CalculateSize(_repeated_repeatedStringWrapper_codec);
+      size += repeatedBytesWrapper_.CalculateSize(_repeated_repeatedBytesWrapper_codec);
+      if (optionalDuration_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalDuration);
+      }
+      if (optionalTimestamp_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalTimestamp);
+      }
+      if (optionalFieldMask_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalFieldMask);
+      }
+      if (optionalStruct_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalStruct);
+      }
+      if (optionalAny_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalAny);
+      }
+      if (optionalValue_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue);
+      }
+      size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec);
+      size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec);
+      size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec);
+      size += repeatedStruct_.CalculateSize(_repeated_repeatedStruct_codec);
+      size += repeatedAny_.CalculateSize(_repeated_repeatedAny_codec);
+      size += repeatedValue_.CalculateSize(_repeated_repeatedValue_codec);
+      if (Fieldname1 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Fieldname1);
+      }
+      if (FieldName2 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName2);
+      }
+      if (FieldName3 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName3);
+      }
+      if (FieldName4 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName4);
+      }
+      if (Field0Name5 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name5);
+      }
+      if (Field0Name6 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name6);
+      }
+      if (FieldName7 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName7);
+      }
+      if (FieldName8 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName8);
+      }
+      if (FieldName9 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName9);
+      }
+      if (FieldName10 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName10);
+      }
+      if (FIELDNAME11 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME11);
+      }
+      if (FIELDName12 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.OptionalInt32 != 0) {
+        OptionalInt32 = other.OptionalInt32;
+      }
+      if (other.OptionalInt64 != 0L) {
+        OptionalInt64 = other.OptionalInt64;
+      }
+      if (other.OptionalUint32 != 0) {
+        OptionalUint32 = other.OptionalUint32;
+      }
+      if (other.OptionalUint64 != 0UL) {
+        OptionalUint64 = other.OptionalUint64;
+      }
+      if (other.OptionalSint32 != 0) {
+        OptionalSint32 = other.OptionalSint32;
+      }
+      if (other.OptionalSint64 != 0L) {
+        OptionalSint64 = other.OptionalSint64;
+      }
+      if (other.OptionalFixed32 != 0) {
+        OptionalFixed32 = other.OptionalFixed32;
+      }
+      if (other.OptionalFixed64 != 0UL) {
+        OptionalFixed64 = other.OptionalFixed64;
+      }
+      if (other.OptionalSfixed32 != 0) {
+        OptionalSfixed32 = other.OptionalSfixed32;
+      }
+      if (other.OptionalSfixed64 != 0L) {
+        OptionalSfixed64 = other.OptionalSfixed64;
+      }
+      if (other.OptionalFloat != 0F) {
+        OptionalFloat = other.OptionalFloat;
+      }
+      if (other.OptionalDouble != 0D) {
+        OptionalDouble = other.OptionalDouble;
+      }
+      if (other.OptionalBool != false) {
+        OptionalBool = other.OptionalBool;
+      }
+      if (other.OptionalString.Length != 0) {
+        OptionalString = other.OptionalString;
+      }
+      if (other.OptionalBytes.Length != 0) {
+        OptionalBytes = other.OptionalBytes;
+      }
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
+          optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage();
+        }
+        OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
+      }
+      if (other.optionalForeignMessage_ != null) {
+        if (optionalForeignMessage_ == null) {
+          optionalForeignMessage_ = new global::Conformance.ForeignMessage();
+        }
+        OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
+      }
+      if (other.OptionalNestedEnum != 0) {
+        OptionalNestedEnum = other.OptionalNestedEnum;
+      }
+      if (other.OptionalForeignEnum != 0) {
+        OptionalForeignEnum = other.OptionalForeignEnum;
+      }
+      if (other.OptionalStringPiece.Length != 0) {
+        OptionalStringPiece = other.OptionalStringPiece;
+      }
+      if (other.OptionalCord.Length != 0) {
+        OptionalCord = other.OptionalCord;
+      }
+      if (other.recursiveMessage_ != null) {
+        if (recursiveMessage_ == null) {
+          recursiveMessage_ = new global::Conformance.TestAllTypes();
+        }
+        RecursiveMessage.MergeFrom(other.RecursiveMessage);
+      }
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedUint32_.Add(other.repeatedUint32_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+      repeatedSint32_.Add(other.repeatedSint32_);
+      repeatedSint64_.Add(other.repeatedSint64_);
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedSfixed32_.Add(other.repeatedSfixed32_);
+      repeatedSfixed64_.Add(other.repeatedSfixed64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedDouble_.Add(other.repeatedDouble_);
+      repeatedBool_.Add(other.repeatedBool_);
+      repeatedString_.Add(other.repeatedString_);
+      repeatedBytes_.Add(other.repeatedBytes_);
+      repeatedNestedMessage_.Add(other.repeatedNestedMessage_);
+      repeatedForeignMessage_.Add(other.repeatedForeignMessage_);
+      repeatedNestedEnum_.Add(other.repeatedNestedEnum_);
+      repeatedForeignEnum_.Add(other.repeatedForeignEnum_);
+      repeatedStringPiece_.Add(other.repeatedStringPiece_);
+      repeatedCord_.Add(other.repeatedCord_);
+      mapInt32Int32_.Add(other.mapInt32Int32_);
+      mapInt64Int64_.Add(other.mapInt64Int64_);
+      mapUint32Uint32_.Add(other.mapUint32Uint32_);
+      mapUint64Uint64_.Add(other.mapUint64Uint64_);
+      mapSint32Sint32_.Add(other.mapSint32Sint32_);
+      mapSint64Sint64_.Add(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.Add(other.mapInt32Float_);
+      mapInt32Double_.Add(other.mapInt32Double_);
+      mapBoolBool_.Add(other.mapBoolBool_);
+      mapStringString_.Add(other.mapStringString_);
+      mapStringBytes_.Add(other.mapStringBytes_);
+      mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
+      mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
+      mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
+      mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
+      if (other.optionalBoolWrapper_ != null) {
+        if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) {
+          OptionalBoolWrapper = other.OptionalBoolWrapper;
+        }
+      }
+      if (other.optionalInt32Wrapper_ != null) {
+        if (optionalInt32Wrapper_ == null || other.OptionalInt32Wrapper != 0) {
+          OptionalInt32Wrapper = other.OptionalInt32Wrapper;
+        }
+      }
+      if (other.optionalInt64Wrapper_ != null) {
+        if (optionalInt64Wrapper_ == null || other.OptionalInt64Wrapper != 0L) {
+          OptionalInt64Wrapper = other.OptionalInt64Wrapper;
+        }
+      }
+      if (other.optionalUint32Wrapper_ != null) {
+        if (optionalUint32Wrapper_ == null || other.OptionalUint32Wrapper != 0) {
+          OptionalUint32Wrapper = other.OptionalUint32Wrapper;
+        }
+      }
+      if (other.optionalUint64Wrapper_ != null) {
+        if (optionalUint64Wrapper_ == null || other.OptionalUint64Wrapper != 0UL) {
+          OptionalUint64Wrapper = other.OptionalUint64Wrapper;
+        }
+      }
+      if (other.optionalFloatWrapper_ != null) {
+        if (optionalFloatWrapper_ == null || other.OptionalFloatWrapper != 0F) {
+          OptionalFloatWrapper = other.OptionalFloatWrapper;
+        }
+      }
+      if (other.optionalDoubleWrapper_ != null) {
+        if (optionalDoubleWrapper_ == null || other.OptionalDoubleWrapper != 0D) {
+          OptionalDoubleWrapper = other.OptionalDoubleWrapper;
+        }
+      }
+      if (other.optionalStringWrapper_ != null) {
+        if (optionalStringWrapper_ == null || other.OptionalStringWrapper != "") {
+          OptionalStringWrapper = other.OptionalStringWrapper;
+        }
+      }
+      if (other.optionalBytesWrapper_ != null) {
+        if (optionalBytesWrapper_ == null || other.OptionalBytesWrapper != pb::ByteString.Empty) {
+          OptionalBytesWrapper = other.OptionalBytesWrapper;
+        }
+      }
+      repeatedBoolWrapper_.Add(other.repeatedBoolWrapper_);
+      repeatedInt32Wrapper_.Add(other.repeatedInt32Wrapper_);
+      repeatedInt64Wrapper_.Add(other.repeatedInt64Wrapper_);
+      repeatedUint32Wrapper_.Add(other.repeatedUint32Wrapper_);
+      repeatedUint64Wrapper_.Add(other.repeatedUint64Wrapper_);
+      repeatedFloatWrapper_.Add(other.repeatedFloatWrapper_);
+      repeatedDoubleWrapper_.Add(other.repeatedDoubleWrapper_);
+      repeatedStringWrapper_.Add(other.repeatedStringWrapper_);
+      repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_);
+      if (other.optionalDuration_ != null) {
+        if (optionalDuration_ == null) {
+          optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+        }
+        OptionalDuration.MergeFrom(other.OptionalDuration);
+      }
+      if (other.optionalTimestamp_ != null) {
+        if (optionalTimestamp_ == null) {
+          optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+        }
+        OptionalTimestamp.MergeFrom(other.OptionalTimestamp);
+      }
+      if (other.optionalFieldMask_ != null) {
+        if (optionalFieldMask_ == null) {
+          optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+        }
+        OptionalFieldMask.MergeFrom(other.OptionalFieldMask);
+      }
+      if (other.optionalStruct_ != null) {
+        if (optionalStruct_ == null) {
+          optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+        }
+        OptionalStruct.MergeFrom(other.OptionalStruct);
+      }
+      if (other.optionalAny_ != null) {
+        if (optionalAny_ == null) {
+          optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
+        }
+        OptionalAny.MergeFrom(other.OptionalAny);
+      }
+      if (other.optionalValue_ != null) {
+        if (optionalValue_ == null) {
+          optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
+        }
+        OptionalValue.MergeFrom(other.OptionalValue);
+      }
+      repeatedDuration_.Add(other.repeatedDuration_);
+      repeatedTimestamp_.Add(other.repeatedTimestamp_);
+      repeatedFieldmask_.Add(other.repeatedFieldmask_);
+      repeatedStruct_.Add(other.repeatedStruct_);
+      repeatedAny_.Add(other.repeatedAny_);
+      repeatedValue_.Add(other.repeatedValue_);
+      if (other.Fieldname1 != 0) {
+        Fieldname1 = other.Fieldname1;
+      }
+      if (other.FieldName2 != 0) {
+        FieldName2 = other.FieldName2;
+      }
+      if (other.FieldName3 != 0) {
+        FieldName3 = other.FieldName3;
+      }
+      if (other.FieldName4 != 0) {
+        FieldName4 = other.FieldName4;
+      }
+      if (other.Field0Name5 != 0) {
+        Field0Name5 = other.Field0Name5;
+      }
+      if (other.Field0Name6 != 0) {
+        Field0Name6 = other.Field0Name6;
+      }
+      if (other.FieldName7 != 0) {
+        FieldName7 = other.FieldName7;
+      }
+      if (other.FieldName8 != 0) {
+        FieldName8 = other.FieldName8;
+      }
+      if (other.FieldName9 != 0) {
+        FieldName9 = other.FieldName9;
+      }
+      if (other.FieldName10 != 0) {
+        FieldName10 = other.FieldName10;
+      }
+      if (other.FIELDNAME11 != 0) {
+        FIELDNAME11 = other.FIELDNAME11;
+      }
+      if (other.FIELDName12 != 0) {
+        FIELDName12 = other.FIELDName12;
+      }
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage;
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(optionalNestedMessage_);
+            break;
+          }
+          case 154: {
+            if (optionalForeignMessage_ == null) {
+              optionalForeignMessage_ = new global::Conformance.ForeignMessage();
+            }
+            input.ReadMessage(optionalForeignMessage_);
+            break;
+          }
+          case 168: {
+            optionalNestedEnum_ = (global::Conformance.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            optionalForeignEnum_ = (global::Conformance.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 194: {
+            OptionalStringPiece = input.ReadString();
+            break;
+          }
+          case 202: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 218: {
+            if (recursiveMessage_ == null) {
+              recursiveMessage_ = new global::Conformance.TestAllTypes();
+            }
+            input.ReadMessage(recursiveMessage_);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec);
+            break;
+          }
+          case 442: {
+            repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec);
+            break;
+          }
+          case 450: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 458: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 466: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 474: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 482: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 490: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 498: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 506: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 514: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 522: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 530: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 538: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 546: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 554: {
+            mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec);
+            break;
+          }
+          case 562: {
+            mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec);
+            break;
+          }
+          case 570: {
+            mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec);
+            break;
+          }
+          case 578: {
+            mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec);
+            break;
+          }
+          case 586: {
+            mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec);
+            break;
+          }
+          case 594: {
+            mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Conformance.TestAllTypes.Types.NestedMessage subBuilder = new global::Conformance.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+          case 1610: {
+            bool? value = _single_optionalBoolWrapper_codec.Read(input);
+            if (optionalBoolWrapper_ == null || value != false) {
+              OptionalBoolWrapper = value;
+            }
+            break;
+          }
+          case 1618: {
+            int? value = _single_optionalInt32Wrapper_codec.Read(input);
+            if (optionalInt32Wrapper_ == null || value != 0) {
+              OptionalInt32Wrapper = value;
+            }
+            break;
+          }
+          case 1626: {
+            long? value = _single_optionalInt64Wrapper_codec.Read(input);
+            if (optionalInt64Wrapper_ == null || value != 0L) {
+              OptionalInt64Wrapper = value;
+            }
+            break;
+          }
+          case 1634: {
+            uint? value = _single_optionalUint32Wrapper_codec.Read(input);
+            if (optionalUint32Wrapper_ == null || value != 0) {
+              OptionalUint32Wrapper = value;
+            }
+            break;
+          }
+          case 1642: {
+            ulong? value = _single_optionalUint64Wrapper_codec.Read(input);
+            if (optionalUint64Wrapper_ == null || value != 0UL) {
+              OptionalUint64Wrapper = value;
+            }
+            break;
+          }
+          case 1650: {
+            float? value = _single_optionalFloatWrapper_codec.Read(input);
+            if (optionalFloatWrapper_ == null || value != 0F) {
+              OptionalFloatWrapper = value;
+            }
+            break;
+          }
+          case 1658: {
+            double? value = _single_optionalDoubleWrapper_codec.Read(input);
+            if (optionalDoubleWrapper_ == null || value != 0D) {
+              OptionalDoubleWrapper = value;
+            }
+            break;
+          }
+          case 1666: {
+            string value = _single_optionalStringWrapper_codec.Read(input);
+            if (optionalStringWrapper_ == null || value != "") {
+              OptionalStringWrapper = value;
+            }
+            break;
+          }
+          case 1674: {
+            pb::ByteString value = _single_optionalBytesWrapper_codec.Read(input);
+            if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) {
+              OptionalBytesWrapper = value;
+            }
+            break;
+          }
+          case 1690: {
+            repeatedBoolWrapper_.AddEntriesFrom(input, _repeated_repeatedBoolWrapper_codec);
+            break;
+          }
+          case 1698: {
+            repeatedInt32Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt32Wrapper_codec);
+            break;
+          }
+          case 1706: {
+            repeatedInt64Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt64Wrapper_codec);
+            break;
+          }
+          case 1714: {
+            repeatedUint32Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint32Wrapper_codec);
+            break;
+          }
+          case 1722: {
+            repeatedUint64Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint64Wrapper_codec);
+            break;
+          }
+          case 1730: {
+            repeatedFloatWrapper_.AddEntriesFrom(input, _repeated_repeatedFloatWrapper_codec);
+            break;
+          }
+          case 1738: {
+            repeatedDoubleWrapper_.AddEntriesFrom(input, _repeated_repeatedDoubleWrapper_codec);
+            break;
+          }
+          case 1746: {
+            repeatedStringWrapper_.AddEntriesFrom(input, _repeated_repeatedStringWrapper_codec);
+            break;
+          }
+          case 1754: {
+            repeatedBytesWrapper_.AddEntriesFrom(input, _repeated_repeatedBytesWrapper_codec);
+            break;
+          }
+          case 2410: {
+            if (optionalDuration_ == null) {
+              optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+            }
+            input.ReadMessage(optionalDuration_);
+            break;
+          }
+          case 2418: {
+            if (optionalTimestamp_ == null) {
+              optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(optionalTimestamp_);
+            break;
+          }
+          case 2426: {
+            if (optionalFieldMask_ == null) {
+              optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            }
+            input.ReadMessage(optionalFieldMask_);
+            break;
+          }
+          case 2434: {
+            if (optionalStruct_ == null) {
+              optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+            }
+            input.ReadMessage(optionalStruct_);
+            break;
+          }
+          case 2442: {
+            if (optionalAny_ == null) {
+              optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(optionalAny_);
+            break;
+          }
+          case 2450: {
+            if (optionalValue_ == null) {
+              optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
+            }
+            input.ReadMessage(optionalValue_);
+            break;
+          }
+          case 2490: {
+            repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec);
+            break;
+          }
+          case 2498: {
+            repeatedTimestamp_.AddEntriesFrom(input, _repeated_repeatedTimestamp_codec);
+            break;
+          }
+          case 2506: {
+            repeatedFieldmask_.AddEntriesFrom(input, _repeated_repeatedFieldmask_codec);
+            break;
+          }
+          case 2522: {
+            repeatedAny_.AddEntriesFrom(input, _repeated_repeatedAny_codec);
+            break;
+          }
+          case 2530: {
+            repeatedValue_.AddEntriesFrom(input, _repeated_repeatedValue_codec);
+            break;
+          }
+          case 2594: {
+            repeatedStruct_.AddEntriesFrom(input, _repeated_repeatedStruct_codec);
+            break;
+          }
+          case 3208: {
+            Fieldname1 = input.ReadInt32();
+            break;
+          }
+          case 3216: {
+            FieldName2 = input.ReadInt32();
+            break;
+          }
+          case 3224: {
+            FieldName3 = input.ReadInt32();
+            break;
+          }
+          case 3232: {
+            FieldName4 = input.ReadInt32();
+            break;
+          }
+          case 3240: {
+            Field0Name5 = input.ReadInt32();
+            break;
+          }
+          case 3248: {
+            Field0Name6 = input.ReadInt32();
+            break;
+          }
+          case 3256: {
+            FieldName7 = input.ReadInt32();
+            break;
+          }
+          case 3264: {
+            FieldName8 = input.ReadInt32();
+            break;
+          }
+          case 3272: {
+            FieldName9 = input.ReadInt32();
+            break;
+          }
+          case 3280: {
+            FieldName10 = input.ReadInt32();
+            break;
+          }
+          case 3288: {
+            FIELDNAME11 = input.ReadInt32();
+            break;
+          }
+          case 3296: {
+            FIELDName12 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the TestAllTypes message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum NestedEnum {
+        [pbr::OriginalName("FOO")] Foo = 0,
+        [pbr::OriginalName("BAR")] Bar = 1,
+        [pbr::OriginalName("BAZ")] Baz = 2,
+        /// <summary>
+        ///  Intentionally negative.
+        /// </summary>
+        [pbr::OriginalName("NEG")] Neg = -1,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Conformance.TestAllTypes.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          a_ = other.a_;
+          Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        /// <summary>Field number for the "a" field.</summary>
+        public const int AFieldNumber = 1;
+        private int a_;
+        public int A {
+          get { return a_; }
+          set {
+            a_ = value;
+          }
+        }
+
+        /// <summary>Field number for the "corecursive" field.</summary>
+        public const int CorecursiveFieldNumber = 2;
+        private global::Conformance.TestAllTypes corecursive_;
+        public global::Conformance.TestAllTypes Corecursive {
+          get { return corecursive_; }
+          set {
+            corecursive_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (A != other.A) return false;
+          if (!object.Equals(Corecursive, other.Corecursive)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (A != 0) hash ^= A.GetHashCode();
+          if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (A != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (corecursive_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Corecursive);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (A != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
+          }
+          if (corecursive_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.A != 0) {
+            A = other.A;
+          }
+          if (other.corecursive_ != null) {
+            if (corecursive_ == null) {
+              corecursive_ = new global::Conformance.TestAllTypes();
+            }
+            Corecursive.MergeFrom(other.Corecursive);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (corecursive_ == null) {
+                  corecursive_ = new global::Conformance.TestAllTypes();
+                }
+                input.ReadMessage(corecursive_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+    private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ForeignMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ForeignMessage(ForeignMessage other) : this() {
+      c_ = other.c_;
+    }
+
+    public ForeignMessage Clone() {
+      return new ForeignMessage(this);
+    }
+
+    /// <summary>Field number for the "c" field.</summary>
+    public const int CFieldNumber = 1;
+    private int c_;
+    public int C {
+      get { return c_; }
+      set {
+        c_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ForeignMessage);
+    }
+
+    public bool Equals(ForeignMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (C != other.C) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (C != 0) hash ^= C.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (C != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ForeignMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.C != 0) {
+        C = other.C;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
new file mode 100644
index 0000000..82f728d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{0607D1B8-80D6-4B35-9857-1263C1B32B94}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.Conformance</RootNamespace>
+    <AssemblyName>Google.Protobuf.Conformance</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Microsoft.CSharp" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Conformance.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908bdce-d925-43f3-94ac-a531e6df2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Program.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Program.cs
new file mode 100644
index 0000000..19827c4
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Program.cs
@@ -0,0 +1,142 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Conformance;
+using Google.Protobuf.Reflection;
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Conformance
+{
+    /// <summary>
+    /// Conformance tests. The test runner will provide JSON or proto data on stdin,
+    /// and this program will produce its output on stdout.
+    /// </summary>
+    class Program
+    {
+        private static void Main(string[] args)
+        {
+            // This way we get the binary streams instead of readers/writers.
+            var input = new BinaryReader(Console.OpenStandardInput());
+            var output = new BinaryWriter(Console.OpenStandardOutput());
+            var typeRegistry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
+
+            int count = 0;
+            while (RunTest(input, output, typeRegistry))
+            {
+                count++;
+            }
+            Console.Error.WriteLine("Received EOF after {0} tests", count);
+        }
+
+        private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
+        {
+            int? size = ReadInt32(input);
+            if (size == null)
+            {
+                return false;
+            }
+            byte[] inputData = input.ReadBytes(size.Value);
+            if (inputData.Length != size.Value)
+            {
+                throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
+            }
+            ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
+            ConformanceResponse response = PerformRequest(request, typeRegistry);
+            byte[] outputData = response.ToByteArray();
+            output.Write(outputData.Length);
+            output.Write(outputData);
+            // Ready for another test...
+            return true;
+        }
+
+        private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
+        {
+            TestAllTypes message;
+            try
+            {
+                switch (request.PayloadCase)
+                {
+                    case ConformanceRequest.PayloadOneofCase.JsonPayload:
+                        var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
+                        message = parser.Parse<TestAllTypes>(request.JsonPayload);
+                        break;
+                    case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
+                        message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
+                        break;
+                    default:
+                        throw new Exception("Unsupported request payload: " + request.PayloadCase);
+                }
+            }
+            catch (InvalidProtocolBufferException e)
+            {
+                return new ConformanceResponse { ParseError = e.Message };
+            }
+            catch (InvalidJsonException e)
+            {
+                return new ConformanceResponse { ParseError = e.Message };
+            }
+            try
+            {
+                switch (request.RequestedOutputFormat)
+                {
+                    case global::Conformance.WireFormat.Json:
+                        var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry));
+                        return new ConformanceResponse { JsonPayload = formatter.Format(message) };
+                    case global::Conformance.WireFormat.Protobuf:
+                        return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
+                    default:
+                        throw new Exception("Unsupported request output format: " + request.PayloadCase);
+                }
+            }
+            catch (InvalidOperationException e)
+            {
+                return new ConformanceResponse { SerializeError = e.Message };
+            }
+        }
+
+        private static int? ReadInt32(BinaryReader input)
+        {
+            byte[] bytes = input.ReadBytes(4);
+            if (bytes.Length == 0)
+            {
+                // Cleanly reached the end of the stream
+                return null;
+            }
+            if (bytes.Length != 4)
+            {
+                throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4");
+            }
+            return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d22e90f
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.Reflection;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Google.Protobuf.Conformance")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Google.Protobuf.Conformance")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
new file mode 100644
index 0000000..67acf66
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D7282E99-2DC3-405B-946F-177DB2FD2AE2}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.JsonDump</RootNamespace>
+    <AssemblyName>Google.Protobuf.JsonDump</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Program.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Program.cs
new file mode 100644
index 0000000..e8a6073
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Program.cs
@@ -0,0 +1,72 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.ProtoDump
+{
+    /// <summary>
+    /// Small utility to load a binary message and dump it in JSON format.
+    /// </summary>
+    internal class Program
+    {
+        private static int Main(string[] args)
+        {
+            if (args.Length != 2)
+            {
+                Console.Error.WriteLine("Usage: Google.Protobuf.JsonDump <descriptor type name> <input data>");
+                Console.Error.WriteLine("The descriptor type name is the fully-qualified message name,");
+                Console.Error.WriteLine("including assembly e.g. ProjectNamespace.Message,Company.Project");
+                return 1;
+            }
+            Type type = Type.GetType(args[0]);
+            if (type == null)
+            {
+                Console.Error.WriteLine("Unable to load type {0}.", args[0]);
+                return 1;
+            }
+            if (!typeof(IMessage).IsAssignableFrom(type))
+            {
+                Console.Error.WriteLine("Type {0} doesn't implement IMessage.", args[0]);
+                return 1;
+            }
+            IMessage message = (IMessage) Activator.CreateInstance(type);
+            using (var input = File.OpenRead(args[1]))
+            {
+                message.MergeFrom(input);
+            }
+            Console.WriteLine(message);
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0a29d2d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("ProtoDump")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ProtoDump")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/app.config b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/app.config
new file mode 100644
index 0000000..51278a4
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.JsonDump/app.config
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
new file mode 100644
index 0000000..8935b78
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
@@ -0,0 +1,171 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Text;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class ByteStringTest
+    {
+        [Test]
+        public void Equality()
+        {
+            ByteString b1 = ByteString.CopyFrom(1, 2, 3);
+            ByteString b2 = ByteString.CopyFrom(1, 2, 3);
+            ByteString b3 = ByteString.CopyFrom(1, 2, 4);
+            ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4);
+            EqualityTester.AssertEquality(b1, b1);
+            EqualityTester.AssertEquality(b1, b2);
+            EqualityTester.AssertInequality(b1, b3);
+            EqualityTester.AssertInequality(b1, b4);
+            EqualityTester.AssertInequality(b1, null);
+#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
+            Assert.IsTrue(b1 == b1);
+            Assert.IsTrue(b1 == b2);
+            Assert.IsFalse(b1 == b3);
+            Assert.IsFalse(b1 == b4);
+            Assert.IsFalse(b1 == null);
+            Assert.IsTrue((ByteString) null == null);
+            Assert.IsFalse(b1 != b1);
+            Assert.IsFalse(b1 != b2);
+#pragma warning disable 1718
+            Assert.IsTrue(b1 != b3);
+            Assert.IsTrue(b1 != b4);
+            Assert.IsTrue(b1 != null);
+            Assert.IsFalse((ByteString) null != null);
+        }
+
+        [Test]
+        public void EmptyByteStringHasZeroSize()
+        {
+            Assert.AreEqual(0, ByteString.Empty.Length);
+        }
+
+        [Test]
+        public void CopyFromStringWithExplicitEncoding()
+        {
+            ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
+            Assert.AreEqual(4, bs.Length);
+            Assert.AreEqual(65, bs[0]);
+            Assert.AreEqual(0, bs[1]);
+            Assert.AreEqual(66, bs[2]);
+            Assert.AreEqual(0, bs[3]);
+        }
+
+        [Test]
+        public void IsEmptyWhenEmpty()
+        {
+            Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
+        }
+
+        [Test]
+        public void IsEmptyWhenNotEmpty()
+        {
+            Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
+        }
+
+        [Test]
+        public void CopyFromByteArrayCopiesContents()
+        {
+            byte[] data = new byte[1];
+            data[0] = 10;
+            ByteString bs = ByteString.CopyFrom(data);
+            Assert.AreEqual(10, bs[0]);
+            data[0] = 5;
+            Assert.AreEqual(10, bs[0]);
+        }
+
+        [Test]
+        public void ToByteArrayCopiesContents()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("Hello");
+            byte[] data = bs.ToByteArray();
+            Assert.AreEqual((byte)'H', data[0]);
+            Assert.AreEqual((byte)'H', bs[0]);
+            data[0] = 0;
+            Assert.AreEqual(0, data[0]);
+            Assert.AreEqual((byte)'H', bs[0]);
+        }
+
+        [Test]
+        public void CopyFromUtf8UsesUtf8()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
+            Assert.AreEqual(3, bs.Length);
+            Assert.AreEqual(0xe2, bs[0]);
+            Assert.AreEqual(0x82, bs[1]);
+            Assert.AreEqual(0xac, bs[2]);
+        }
+
+        [Test]
+        public void CopyFromPortion()
+        {
+            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
+            ByteString bs = ByteString.CopyFrom(data, 2, 3);
+            Assert.AreEqual(3, bs.Length);
+            Assert.AreEqual(2, bs[0]);
+            Assert.AreEqual(3, bs[1]);
+        }
+
+        [Test]
+        public void ToStringUtf8()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
+            Assert.AreEqual("\u20ac", bs.ToStringUtf8());
+        }
+
+        [Test]
+        public void ToStringWithExplicitEncoding()
+        {
+            ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
+            Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
+        }
+
+        [Test]
+        public void FromBase64_WithText()
+        {
+            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
+            string base64 = Convert.ToBase64String(data);
+            ByteString bs = ByteString.FromBase64(base64);
+            Assert.AreEqual(data, bs.ToByteArray());
+        }
+
+        [Test]
+        public void FromBase64_Empty()
+        {
+            // Optimization which also fixes issue 61.
+            Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs
new file mode 100644
index 0000000..23af288
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs
@@ -0,0 +1,53 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    internal static class CodedInputStreamExtensions
+    {
+        public static void AssertNextTag(this CodedInputStream input, uint expectedTag)
+        {
+            uint tag = input.ReadTag();
+            Assert.AreEqual(expectedTag, tag);
+        }
+
+        public static T ReadMessage<T>(this CodedInputStream stream, MessageParser<T> parser)
+            where T : IMessage<T>
+        {
+            var message = parser.CreateTemplate();
+            stream.ReadMessage(message);
+            return message;
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
new file mode 100644
index 0000000..d628ecc
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -0,0 +1,598 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class CodedInputStreamTest
+    {
+        /// <summary>
+        /// Helper to construct a byte array from a bunch of bytes.  The inputs are
+        /// actually ints so that I can use hex notation and not get stupid errors
+        /// about precision.
+        /// </summary>
+        private static byte[] Bytes(params int[] bytesAsInts)
+        {
+            byte[] bytes = new byte[bytesAsInts.Length];
+            for (int i = 0; i < bytesAsInts.Length; i++)
+            {
+                bytes[i] = (byte) bytesAsInts[i];
+            }
+            return bytes;
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64()
+        /// </summary>
+        private static void AssertReadVarint(byte[] data, ulong value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual((uint) value, input.ReadRawVarint32());
+
+            input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawVarint64());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
+                Assert.AreEqual((uint) value, input.ReadRawVarint32());
+
+                input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
+                Assert.AreEqual(value, input.ReadRawVarint64());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+
+            // Try reading directly from a MemoryStream. We want to verify that it
+            // doesn't read past the end of the input, so write an extra byte - this
+            // lets us test the position at the end.
+            MemoryStream memoryStream = new MemoryStream();
+            memoryStream.Write(data, 0, data.Length);
+            memoryStream.WriteByte(0);
+            memoryStream.Position = 0;
+            Assert.AreEqual((uint) value, CodedInputStream.ReadRawVarint32(memoryStream));
+            Assert.AreEqual(data.Length, memoryStream.Position);
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
+        /// expects them to fail with an InvalidProtocolBufferException whose
+        /// description matches the given one.
+        /// </summary>
+        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
+            Assert.AreEqual(expected.Message, exception.Message);
+
+            input = new CodedInputStream(data);
+            exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
+            Assert.AreEqual(expected.Message, exception.Message);
+
+            // Make sure we get the same error when reading directly from a Stream.
+            exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));
+            Assert.AreEqual(expected.Message, exception.Message);
+        }
+
+        [Test]
+        public void ReadVarint()
+        {
+            AssertReadVarint(Bytes(0x00), 0);
+            AssertReadVarint(Bytes(0x01), 1);
+            AssertReadVarint(Bytes(0x7f), 127);
+            // 14882
+            AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+            // 2961488830
+            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                             (0x0bL << 28));
+
+            // 64-bit
+            // 7256456126
+            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                             (0x1bL << 28));
+            // 41256202580718336
+            AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+                             (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+                             (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+            // 11964378330978735131
+            AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+                             (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+                             (0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
+                             (0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));
+
+            // Failures
+            AssertReadVarintFailure(
+                InvalidProtocolBufferException.MalformedVarint(),
+                Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+                      0x00));
+            AssertReadVarintFailure(
+                InvalidProtocolBufferException.TruncatedMessage(),
+                Bytes(0x80));
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawLittleEndian32() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertReadLittleEndian32(byte[] data, uint value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawLittleEndian32());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                input = new CodedInputStream(
+                    new SmallBlockInputStream(data, blockSize));
+                Assert.AreEqual(value, input.ReadRawLittleEndian32());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawLittleEndian64() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertReadLittleEndian64(byte[] data, ulong value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawLittleEndian64());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                input = new CodedInputStream(
+                    new SmallBlockInputStream(data, blockSize));
+                Assert.AreEqual(value, input.ReadRawLittleEndian64());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+        }
+
+        [Test]
+        public void ReadLittleEndian()
+        {
+            AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+            AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+            AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+                                     0x123456789abcdef0L);
+            AssertReadLittleEndian64(
+                Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
+        }
+
+        [Test]
+        public void DecodeZigZag32()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));
+            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
+            Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
+            Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
+            Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
+            Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
+        }
+
+        [Test]
+        public void DecodeZigZag64()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));
+            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
+            Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
+            Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
+            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+        }
+        
+        [Test]
+        public void ReadWholeMessage_VaryingBlockSizes()
+        {
+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
+
+            byte[] rawBytes = message.ToByteArray();
+            Assert.AreEqual(rawBytes.Length, message.CalculateSize());
+            TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);
+            Assert.AreEqual(message, message2);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+            {
+                message2 = TestAllTypes.Parser.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
+                Assert.AreEqual(message, message2);
+            }
+        }
+                
+        [Test]
+        public void ReadHugeBlob()
+        {
+            // Allocate and initialize a 1MB blob.
+            byte[] blob = new byte[1 << 20];
+            for (int i = 0; i < blob.Length; i++)
+            {
+                blob[i] = (byte) i;
+            }
+
+            // Make a message containing it.
+            var message = new TestAllTypes { SingleBytes = ByteString.CopyFrom(blob) };
+
+            // Serialize and parse it.  Make sure to parse from an InputStream, not
+            // directly from a ByteString, so that CodedInputStream uses buffered
+            // reading.
+            TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(message.ToByteString());
+
+            Assert.AreEqual(message, message2);
+        }
+
+        [Test]
+        public void ReadMaliciouslyLargeBlob()
+        {
+            MemoryStream ms = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(ms);
+
+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(tag);
+            output.WriteRawVarint32(0x7FFFFFFF);
+            output.WriteRawBytes(new byte[32]); // Pad with a few random bytes.
+            output.Flush();
+            ms.Position = 0;
+
+            CodedInputStream input = new CodedInputStream(ms);
+            Assert.AreEqual(tag, input.ReadTag());
+
+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
+        }
+
+        internal static TestRecursiveMessage MakeRecursiveMessage(int depth)
+        {
+            if (depth == 0)
+            {
+                return new TestRecursiveMessage { I = 5 };
+            }
+            else
+            {
+                return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) };
+            }
+        }
+
+        internal static void AssertMessageDepth(TestRecursiveMessage message, int depth)
+        {
+            if (depth == 0)
+            {
+                Assert.IsNull(message.A);
+                Assert.AreEqual(5, message.I);
+            }
+            else
+            {
+                Assert.IsNotNull(message.A);
+                AssertMessageDepth(message.A, depth - 1);
+            }
+        }
+
+        [Test]
+        public void MaliciousRecursion()
+        {
+            ByteString data64 = MakeRecursiveMessage(64).ToByteString();
+            ByteString data65 = MakeRecursiveMessage(65).ToByteString();
+
+            AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64);
+
+            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65));
+
+            CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63);
+            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));
+        }
+
+        [Test]
+        public void SizeLimit()
+        {
+            // Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
+            // apply to the latter case.
+            MemoryStream ms = new MemoryStream(SampleMessages.CreateFullTestAllTypes().ToByteArray());
+            CodedInputStream input = CodedInputStream.CreateWithLimits(ms, 16, 100);
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(input));
+        }
+
+        /// <summary>
+        /// Tests that if we read an string that contains invalid UTF-8, no exception
+        /// is thrown.  Instead, the invalid bytes are replaced with the Unicode
+        /// "replacement character" U+FFFD.
+        /// </summary>
+        [Test]
+        public void ReadInvalidUtf8()
+        {
+            MemoryStream ms = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(ms);
+
+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(tag);
+            output.WriteRawVarint32(1);
+            output.WriteRawBytes(new byte[] {0x80});
+            output.Flush();
+            ms.Position = 0;
+
+            CodedInputStream input = new CodedInputStream(ms);
+
+            Assert.AreEqual(tag, input.ReadTag());
+            string text = input.ReadString();
+            Assert.AreEqual('\ufffd', text[0]);
+        }
+
+        /// <summary>
+        /// A stream which limits the number of bytes it reads at a time.
+        /// We use this to make sure that CodedInputStream doesn't screw up when
+        /// reading in small blocks.
+        /// </summary>
+        private sealed class SmallBlockInputStream : MemoryStream
+        {
+            private readonly int blockSize;
+
+            public SmallBlockInputStream(byte[] data, int blockSize)
+                : base(data)
+            {
+                this.blockSize = blockSize;
+            }
+
+            public override int Read(byte[] buffer, int offset, int count)
+            {
+                return base.Read(buffer, offset, Math.Min(count, blockSize));
+            }
+        }
+
+        [Test]
+        public void TestNegativeEnum()
+        {
+            byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
+            CodedInputStream input = new CodedInputStream(bytes);
+            Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        //Issue 71:	CodedInputStream.ReadBytes go to slow path unnecessarily
+        [Test]
+        public void TestSlowPathAvoidance()
+        {
+            using (var ms = new MemoryStream())
+            {
+                CodedOutputStream output = new CodedOutputStream(ms);
+                output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+                output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+                output.Flush();
+
+                ms.Position = 0;
+                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0);
+
+                uint tag = input.ReadTag();
+                Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
+                Assert.AreEqual(100, input.ReadBytes().Length);
+
+                tag = input.ReadTag();
+                Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
+                Assert.AreEqual(100, input.ReadBytes().Length);
+            }
+        }
+
+        [Test]
+        public void Tag0Throws()
+        {
+            var input = new CodedInputStream(new byte[] { 0 });
+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadTag());
+        }
+
+        [Test]
+        public void SkipGroup()
+        {
+            // Create an output stream with a group in:
+            // Field 1: string "field 1"
+            // Field 2: group containing:
+            //   Field 1: fixed int32 value 100
+            //   Field 2: string "ignore me"
+            //   Field 3: nested group containing
+            //      Field 1: fixed int64 value 1000
+            // Field 3: string "field 3"
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteString("field 1");
+            
+            // The outer group...
+            output.WriteTag(2, WireFormat.WireType.StartGroup);
+            output.WriteTag(1, WireFormat.WireType.Fixed32);
+            output.WriteFixed32(100);
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteString("ignore me");
+            // The nested group...
+            output.WriteTag(3, WireFormat.WireType.StartGroup);
+            output.WriteTag(1, WireFormat.WireType.Fixed64);
+            output.WriteFixed64(1000);
+            // Note: Not sure the field number is relevant for end group...
+            output.WriteTag(3, WireFormat.WireType.EndGroup);
+
+            // End the outer group
+            output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+            output.WriteTag(3, WireFormat.WireType.LengthDelimited);
+            output.WriteString("field 3");
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag());
+            Assert.AreEqual("field 1", input.ReadString());
+            Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag());
+            input.SkipLastField(); // Should consume the whole group, including the nested one.
+            Assert.AreEqual(WireFormat.MakeTag(3, WireFormat.WireType.LengthDelimited), input.ReadTag());
+            Assert.AreEqual("field 3", input.ReadString());
+        }
+
+        [Test]
+        public void SkipGroup_WrongEndGroupTag()
+        {
+            // Create an output stream with:
+            // Field 1: string "field 1"
+            // Start group 2
+            //   Field 3: fixed int32
+            // End group 4 (should give an error)
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteString("field 1");
+
+            // The outer group...
+            output.WriteTag(2, WireFormat.WireType.StartGroup);
+            output.WriteTag(3, WireFormat.WireType.Fixed32);
+            output.WriteFixed32(100);
+            output.WriteTag(4, WireFormat.WireType.EndGroup);
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag());
+            Assert.AreEqual("field 1", input.ReadString());
+            Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag());
+            Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField);
+        }
+
+        [Test]
+        public void RogueEndGroupTag()
+        {
+            // If we have an end-group tag without a leading start-group tag, generated
+            // code will just call SkipLastField... so that should fail.
+
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.EndGroup);
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.EndGroup), input.ReadTag());
+            Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField);
+        }
+
+        [Test]
+        public void EndOfStreamReachedWhileSkippingGroup()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.StartGroup);
+            output.WriteTag(2, WireFormat.WireType.StartGroup);
+            output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            input.ReadTag();
+            Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField);
+        }
+
+        [Test]
+        public void RecursionLimitAppliedWhileSkippingGroup()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+            {
+                output.WriteTag(1, WireFormat.WireType.StartGroup);
+            }
+            for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+            {
+                output.WriteTag(1, WireFormat.WireType.EndGroup);
+            }
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.StartGroup), input.ReadTag());
+            Assert.Throws<InvalidProtocolBufferException>(input.SkipLastField);
+        }
+
+        [Test]
+        public void Construction_Invalid()
+        {
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream((byte[]) null));
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream(null, 0, 0));
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream((Stream) null));
+            Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 100, 0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 5, 10));
+        }
+
+        [Test]
+        public void CreateWithLimits_InvalidLimits()
+        {
+            var stream = new MemoryStream();
+            Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 0, 1));
+            Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 1, 0));
+        }
+
+        [Test]
+        public void Dispose_DisposesUnderlyingStream()
+        {
+            var memoryStream = new MemoryStream();
+            Assert.IsTrue(memoryStream.CanRead);
+            using (var cis = new CodedInputStream(memoryStream))
+            {
+            }
+            Assert.IsFalse(memoryStream.CanRead); // Disposed
+        }
+
+        [Test]
+        public void Dispose_WithLeaveOpen()
+        {
+            var memoryStream = new MemoryStream();
+            Assert.IsTrue(memoryStream.CanRead);
+            using (var cis = new CodedInputStream(memoryStream, true))
+            {
+            }
+            Assert.IsTrue(memoryStream.CanRead); // We left the stream open
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
new file mode 100644
index 0000000..83bcb17
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -0,0 +1,419 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class CodedOutputStreamTest
+    {
+        /// <summary>
+        /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
+        /// checks that the result matches the given bytes
+        /// </summary>
+        private static void AssertWriteVarint(byte[] data, ulong value)
+        {
+            // Only do 32-bit write if the value fits in 32 bits.
+            if ((value >> 32) == 0)
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput);
+                output.WriteRawVarint32((uint) value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+                // Also try computing size.
+                Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
+            }
+
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput);
+                output.WriteRawVarint64(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+
+                // Also try computing size.
+                Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
+            }
+
+            // Try different buffer sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                // Only do 32-bit write if the value fits in 32 bits.
+                if ((value >> 32) == 0)
+                {
+                    MemoryStream rawOutput = new MemoryStream();
+                    CodedOutputStream output =
+                        new CodedOutputStream(rawOutput, bufferSize);
+                    output.WriteRawVarint32((uint) value);
+                    output.Flush();
+                    Assert.AreEqual(data, rawOutput.ToArray());
+                }
+
+                {
+                    MemoryStream rawOutput = new MemoryStream();
+                    CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
+                    output.WriteRawVarint64(value);
+                    output.Flush();
+                    Assert.AreEqual(data, rawOutput.ToArray());
+                }
+            }
+        }
+
+        /// <summary>
+        /// Tests WriteRawVarint32() and WriteRawVarint64()
+        /// </summary>
+        [Test]
+        public void WriteVarint()
+        {
+            AssertWriteVarint(new byte[] {0x00}, 0);
+            AssertWriteVarint(new byte[] {0x01}, 1);
+            AssertWriteVarint(new byte[] {0x7f}, 127);
+            // 14882
+            AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
+            // 2961488830
+            AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
+                              (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                              (0x0bL << 28));
+
+            // 64-bit
+            // 7256456126
+            AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
+                              (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                              (0x1bL << 28));
+            // 41256202580718336
+            AssertWriteVarint(
+                new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
+                (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+                (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
+            // 11964378330978735131
+            AssertWriteVarint(
+                new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
+                unchecked((ulong)
+                          ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+                           (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+                           (0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
+        }
+
+        /// <summary>
+        /// Parses the given bytes using WriteRawLittleEndian32() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertWriteLittleEndian32(byte[] data, uint value)
+        {
+            MemoryStream rawOutput = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(rawOutput);
+            output.WriteRawLittleEndian32(value);
+            output.Flush();
+            Assert.AreEqual(data, rawOutput.ToArray());
+
+            // Try different buffer sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                rawOutput = new MemoryStream();
+                output = new CodedOutputStream(rawOutput, bufferSize);
+                output.WriteRawLittleEndian32(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+            }
+        }
+
+        /// <summary>
+        /// Parses the given bytes using WriteRawLittleEndian64() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertWriteLittleEndian64(byte[] data, ulong value)
+        {
+            MemoryStream rawOutput = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(rawOutput);
+            output.WriteRawLittleEndian64(value);
+            output.Flush();
+            Assert.AreEqual(data, rawOutput.ToArray());
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                rawOutput = new MemoryStream();
+                output = new CodedOutputStream(rawOutput, blockSize);
+                output.WriteRawLittleEndian64(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+            }
+        }
+
+        /// <summary>
+        /// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
+        /// </summary>
+        [Test]
+        public void WriteLittleEndian()
+        {
+            AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
+            AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
+
+            AssertWriteLittleEndian64(
+                new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
+                0x123456789abcdef0L);
+            AssertWriteLittleEndian64(
+                new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
+                0x9abcdef012345678UL);
+        }
+
+        [Test]
+        public void WriteWholeMessage_VaryingBlockSizes()
+        {
+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
+
+            byte[] rawBytes = message.ToByteArray();
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
+                message.WriteTo(output);
+                output.Flush();
+                Assert.AreEqual(rawBytes, rawOutput.ToArray());
+            }
+        }
+        
+        [Test]
+        public void EncodeZigZag32()
+        {
+            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0));
+            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1));
+            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1));
+            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2));
+            Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
+            Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));
+            Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
+            Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));
+        }
+
+        [Test]
+        public void EncodeZigZag64()
+        {
+            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0));
+            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1));
+            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1));
+            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2));
+            Assert.AreEqual(0x000000007FFFFFFEuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
+            Assert.AreEqual(0x000000007FFFFFFFuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
+            Assert.AreEqual(0x00000000FFFFFFFEuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
+            Assert.AreEqual(0x00000000FFFFFFFFuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
+            Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
+            Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
+        }
+
+        [Test]
+        public void RoundTripZigZag32()
+        {
+            // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
+            // were chosen semi-randomly via keyboard bashing.
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
+            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
+            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
+        }
+
+        [Test]
+        public void RoundTripZigZag64()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
+            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
+            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
+
+            Assert.AreEqual(856912304801416L,
+                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
+            Assert.AreEqual(-75123905439571256L,
+                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
+        }
+
+        [Test]
+        public void TestNegativeEnumNoTag()
+        {
+            Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
+            Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
+
+            byte[] bytes = new byte[10];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            output.WriteEnum((int) SampleEnum.NegativeValue);
+
+            Assert.AreEqual(0, output.SpaceLeft);
+            Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
+        }
+
+        [Test]
+        public void TestCodedInputOutputPosition()
+        {
+            byte[] content = new byte[110];
+            for (int i = 0; i < content.Length; i++)
+                content[i] = (byte)i;
+
+            byte[] child = new byte[120];
+            {
+                MemoryStream ms = new MemoryStream(child);
+                CodedOutputStream cout = new CodedOutputStream(ms, 20);
+                // Field 11: numeric value: 500
+                cout.WriteTag(11, WireFormat.WireType.Varint);
+                Assert.AreEqual(1, cout.Position);
+                cout.WriteInt32(500);
+                Assert.AreEqual(3, cout.Position);
+                //Field 12: length delimited 120 bytes
+                cout.WriteTag(12, WireFormat.WireType.LengthDelimited);
+                Assert.AreEqual(4, cout.Position);
+                cout.WriteBytes(ByteString.CopyFrom(content));
+                Assert.AreEqual(115, cout.Position);
+                // Field 13: fixed numeric value: 501
+                cout.WriteTag(13, WireFormat.WireType.Fixed32);
+                Assert.AreEqual(116, cout.Position);
+                cout.WriteSFixed32(501);
+                Assert.AreEqual(120, cout.Position);
+                cout.Flush();
+            }
+
+            byte[] bytes = new byte[130];
+            {
+                CodedOutputStream cout = new CodedOutputStream(bytes);
+                // Field 1: numeric value: 500
+                cout.WriteTag(1, WireFormat.WireType.Varint);
+                Assert.AreEqual(1, cout.Position);
+                cout.WriteInt32(500);
+                Assert.AreEqual(3, cout.Position);
+                //Field 2: length delimited 120 bytes
+                cout.WriteTag(2, WireFormat.WireType.LengthDelimited);
+                Assert.AreEqual(4, cout.Position);
+                cout.WriteBytes(ByteString.CopyFrom(child));
+                Assert.AreEqual(125, cout.Position);
+                // Field 3: fixed numeric value: 500
+                cout.WriteTag(3, WireFormat.WireType.Fixed32);
+                Assert.AreEqual(126, cout.Position);
+                cout.WriteSFixed32(501);
+                Assert.AreEqual(130, cout.Position);
+                cout.Flush();
+            }
+            // Now test Input stream:
+            {
+                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0);
+                Assert.AreEqual(0, cin.Position);
+                // Field 1:
+                uint tag = cin.ReadTag();
+                Assert.AreEqual(1, tag >> 3);
+                Assert.AreEqual(1, cin.Position);
+                Assert.AreEqual(500, cin.ReadInt32());
+                Assert.AreEqual(3, cin.Position);
+                //Field 2:
+                tag = cin.ReadTag();
+                Assert.AreEqual(2, tag >> 3);
+                Assert.AreEqual(4, cin.Position);
+                int childlen = cin.ReadLength();
+                Assert.AreEqual(120, childlen);
+                Assert.AreEqual(5, cin.Position);
+                int oldlimit = cin.PushLimit((int)childlen);
+                Assert.AreEqual(5, cin.Position);
+                // Now we are reading child message
+                {
+                    // Field 11: numeric value: 500
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(11, tag >> 3);
+                    Assert.AreEqual(6, cin.Position);
+                    Assert.AreEqual(500, cin.ReadInt32());
+                    Assert.AreEqual(8, cin.Position);
+                    //Field 12: length delimited 120 bytes
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(12, tag >> 3);
+                    Assert.AreEqual(9, cin.Position);
+                    ByteString bstr = cin.ReadBytes();
+                    Assert.AreEqual(110, bstr.Length);
+                    Assert.AreEqual((byte) 109, bstr[109]);
+                    Assert.AreEqual(120, cin.Position);
+                    // Field 13: fixed numeric value: 501
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(13, tag >> 3);
+                    // ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
+                    Assert.AreEqual(121, cin.Position);
+                    Assert.AreEqual(501, cin.ReadSFixed32());
+                    Assert.AreEqual(125, cin.Position);
+                    Assert.IsTrue(cin.IsAtEnd);
+                }
+                cin.PopLimit(oldlimit);
+                Assert.AreEqual(125, cin.Position);
+                // Field 3: fixed numeric value: 501
+                tag = cin.ReadTag();
+                Assert.AreEqual(3, tag >> 3);
+                Assert.AreEqual(126, cin.Position);
+                Assert.AreEqual(501, cin.ReadSFixed32());
+                Assert.AreEqual(130, cin.Position);
+                Assert.IsTrue(cin.IsAtEnd);
+            }
+        }
+
+        [Test]
+        public void Dispose_DisposesUnderlyingStream()
+        {
+            var memoryStream = new MemoryStream();
+            Assert.IsTrue(memoryStream.CanWrite);
+            using (var cos = new CodedOutputStream(memoryStream))
+            {
+                cos.WriteRawByte(0);
+                Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
+            }
+            Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream
+            Assert.IsFalse(memoryStream.CanWrite); // Disposed
+        }
+
+        [Test]
+        public void Dispose_WithLeaveOpen()
+        {
+            var memoryStream = new MemoryStream();
+            Assert.IsTrue(memoryStream.CanWrite);
+            using (var cos = new CodedOutputStream(memoryStream, true))
+            {
+                cos.WriteRawByte(0);
+                Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
+            }
+            Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream
+            Assert.IsTrue(memoryStream.CanWrite); // We left the stream open
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
new file mode 100644
index 0000000..9c84590
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
@@ -0,0 +1,532 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System.Collections;
+using System.Linq;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Tests for MapField which aren't reliant on the encoded format -
+    /// tests for serialization/deserialization are part of GeneratedMessageTest.
+    /// </summary>
+    public class MapFieldTest
+    {
+        [Test]
+        public void Clone_ClonesMessages()
+        {
+            var message = new ForeignMessage { C = 20 };
+            var map = new MapField<string, ForeignMessage> { { "x", message } };
+            var clone = map.Clone();
+            map["x"].C = 30;
+            Assert.AreEqual(20, clone["x"].C);
+        }
+
+        [Test]
+        public void NullValuesProhibited()
+        {
+            TestNullValues<int?>(0);
+            TestNullValues("");
+            TestNullValues(new TestAllTypes());
+        }
+
+        private void TestNullValues<T>(T nonNullValue)
+        {
+            var map = new MapField<int, T>();
+            var nullValue = (T) (object) null;
+            Assert.Throws<ArgumentNullException>(() => map.Add(0, nullValue));
+            Assert.Throws<ArgumentNullException>(() => map[0] = nullValue);
+            map.Add(1, nonNullValue);
+            map[1] = nonNullValue;
+        }
+
+        [Test]
+        public void Add_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map.Add(null, new ForeignMessage()));
+        }
+
+        [Test]
+        public void Indexer_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map[null] = new ForeignMessage());
+        }
+        
+        [Test]
+        public void AddPreservesInsertionOrder()
+        {
+            var map = new MapField<string, string>();
+            map.Add("a", "v1");
+            map.Add("b", "v2");
+            map.Add("c", "v3");
+            map.Remove("b");
+            map.Add("d", "v4");
+            CollectionAssert.AreEqual(new[] { "a", "c", "d" }, map.Keys);
+            CollectionAssert.AreEqual(new[] { "v1", "v3", "v4" }, map.Values);
+        }
+
+        [Test]
+        public void EqualityIsOrderInsensitive()
+        {
+            var map1 = new MapField<string, string>();
+            map1.Add("a", "v1");
+            map1.Add("b", "v2");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("b", "v2");
+            map2.Add("a", "v1");
+
+            EqualityTester.AssertEquality(map1, map2);
+        }
+
+        [Test]
+        public void EqualityIsKeySensitive()
+        {
+            var map1 = new MapField<string, string>();
+            map1.Add("first key", "v1");
+            map1.Add("second key", "v2");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("third key", "v1");
+            map2.Add("fourth key", "v2");
+
+            EqualityTester.AssertInequality(map1, map2);
+        }
+
+        [Test]
+        public void Equality_Simple()
+        {
+            var map = new MapField<string, string>();
+            EqualityTester.AssertEquality(map, map);
+            EqualityTester.AssertInequality(map, null);
+            Assert.IsFalse(map.Equals(new object()));
+        }
+
+        [Test]
+        public void EqualityIsValueSensitive()
+        {
+            // Note: Without some care, it's a little easier than one might
+            // hope to see hash collisions, but only in some environments...
+            var map1 = new MapField<string, string>();
+            map1.Add("a", "first value");
+            map1.Add("b", "second value");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("a", "third value");
+            map2.Add("b", "fourth value");
+
+            EqualityTester.AssertInequality(map1, map2);
+        }
+
+        [Test]
+        public void Add_Dictionary()
+        {
+            var map1 = new MapField<string, string>
+            {
+                { "x", "y" },
+                { "a", "b" }
+            };
+            var map2 = new MapField<string, string>
+            {
+                { "before", "" },
+                map1,
+                { "after", "" }
+            };
+            var expected = new MapField<string, string>
+            {
+                { "before", "" },
+                { "x", "y" },
+                { "a", "b" },
+                { "after", "" }
+            };
+            Assert.AreEqual(expected, map2);
+            CollectionAssert.AreEqual(new[] { "before", "x", "a", "after" }, map2.Keys);
+        }
+
+        // General IDictionary<TKey, TValue> behavior tests
+        [Test]
+        public void Add_KeyAlreadyExists()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            Assert.Throws<ArgumentException>(() => map.Add("foo", "baz"));
+        }
+
+        [Test]
+        public void Add_Pair()
+        {
+            var map = new MapField<string, string>();
+            ICollection<KeyValuePair<string, string>> collection = map;
+            collection.Add(NewKeyValuePair("x", "y"));
+            Assert.AreEqual("y", map["x"]);
+            Assert.Throws<ArgumentException>(() => collection.Add(NewKeyValuePair("x", "z")));
+        }
+
+        [Test]
+        public void Contains_Pair()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            ICollection<KeyValuePair<string, string>> collection = map;
+            Assert.IsTrue(collection.Contains(NewKeyValuePair("x", "y")));
+            Assert.IsFalse(collection.Contains(NewKeyValuePair("x", "z")));
+            Assert.IsFalse(collection.Contains(NewKeyValuePair("z", "y")));
+        }
+
+        [Test]
+        public void Remove_Key()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(map.Remove("missing"));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsTrue(map.Remove("foo"));
+            Assert.AreEqual(0, map.Count);
+            Assert.Throws<ArgumentNullException>(() => map.Remove(null));
+        }
+
+        [Test]
+        public void Remove_Pair()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            ICollection<KeyValuePair<string, string>> collection = map;
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(collection.Remove(NewKeyValuePair("wrong key", "bar")));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(collection.Remove(NewKeyValuePair("foo", "wrong value")));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsTrue(collection.Remove(NewKeyValuePair("foo", "bar")));
+            Assert.AreEqual(0, map.Count);
+            Assert.Throws<ArgumentException>(() => collection.Remove(new KeyValuePair<string, string>(null, "")));
+        }
+
+        [Test]
+        public void CopyTo_Pair()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            ICollection<KeyValuePair<string, string>> collection = map;
+            KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[3];
+            collection.CopyTo(array, 1);
+            Assert.AreEqual(NewKeyValuePair("foo", "bar"), array[1]);
+        }
+
+        [Test]
+        public void Clear()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual(1, map.Count);
+            map.Clear();
+            Assert.AreEqual(0, map.Count);
+            map.Add("x", "y");
+            Assert.AreEqual(1, map.Count);
+        }
+
+        [Test]
+        public void Indexer_Get()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual("y", map["x"]);
+            Assert.Throws<KeyNotFoundException>(() => { var ignored = map["z"]; });
+        }
+
+        [Test]
+        public void Indexer_Set()
+        {
+            var map = new MapField<string, string>();
+            map["x"] = "y";
+            Assert.AreEqual("y", map["x"]);
+            map["x"] = "z"; // This won't throw, unlike Add.
+            Assert.AreEqual("z", map["x"]);
+        }
+
+        [Test]
+        public void GetEnumerator_NonGeneric()
+        {
+            IEnumerable map = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { new KeyValuePair<string, string>("x", "y") },
+                map.Cast<object>().ToList());
+        }
+
+        // Test for the explicitly-implemented non-generic IDictionary interface
+        [Test]
+        public void IDictionary_GetEnumerator()
+        {
+            IDictionary map = new MapField<string, string> { { "x", "y" } };
+            var enumerator = map.GetEnumerator();
+
+            // Commented assertions show an ideal situation - it looks like
+            // the LinkedList enumerator doesn't throw when you ask for the current entry
+            // at an inappropriate time; fixing this would be more work than it's worth.
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key);
+            Assert.AreEqual("y", enumerator.Value);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Current);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Entry);
+            Assert.IsFalse(enumerator.MoveNext());
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            enumerator.Reset();
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key); // Assume the rest are okay
+        }
+
+        [Test]
+        public void IDictionary_Add()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Add("a", "b");
+            Assert.AreEqual("b", map["a"]);
+            Assert.Throws<ArgumentException>(() => dictionary.Add("a", "duplicate"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add(new object(), "key is bad"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add("value is bad", new object()));
+        }
+
+        [Test]
+        public void IDictionary_Contains()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+
+            Assert.IsFalse(dictionary.Contains("a"));
+            Assert.IsFalse(dictionary.Contains(5));
+            // Surprising, but IDictionary.Contains is only about keys.
+            Assert.IsFalse(dictionary.Contains(new DictionaryEntry("x", "y")));
+            Assert.IsTrue(dictionary.Contains("x"));
+        }
+
+        [Test]
+        public void IDictionary_Remove()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Remove("a");
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(5);
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(new DictionaryEntry("x", "y"));
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove("x");
+            Assert.AreEqual(0, dictionary.Count);
+            Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null));
+        }
+
+        [Test]
+        public void IDictionary_CopyTo()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            var array = new DictionaryEntry[3];
+            dictionary.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
+                array);
+            var objectArray = new object[3];
+            dictionary.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
+                objectArray);
+        }
+
+        [Test]
+        public void IDictionary_IsFixedSize()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            Assert.IsFalse(dictionary.IsFixedSize);
+        }
+
+        [Test]
+        public void IDictionary_Keys()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "x" }, dictionary.Keys);
+        }
+
+        [Test]
+        public void IDictionary_Values()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "y" }, dictionary.Values);
+        }
+
+        [Test]
+        public void IDictionary_IsSynchronized()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.IsFalse(dictionary.IsSynchronized);
+        }
+
+        [Test]
+        public void IDictionary_SyncRoot()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreSame(dictionary, dictionary.SyncRoot);
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Get()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual("y", dictionary["x"]);
+            Assert.IsNull(dictionary["a"]);
+            Assert.IsNull(dictionary[5]);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null].GetHashCode());
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Set()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            map["a"] = "b";
+            Assert.AreEqual("b", map["a"]);
+            map["a"] = "c";
+            Assert.AreEqual("c", map["a"]);
+            Assert.Throws<InvalidCastException>(() => dictionary[5] = "x");
+            Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z");
+            Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null);
+        }
+
+        [Test]
+        public void KeysReturnsLiveView()
+        {
+            var map = new MapField<string, string>();
+            var keys = map.Keys;
+            CollectionAssert.AreEqual(new string[0], keys);
+            map["foo"] = "bar";
+            map["x"] = "y";
+            CollectionAssert.AreEqual(new[] { "foo", "x" }, keys);
+        }
+
+        [Test]
+        public void ValuesReturnsLiveView()
+        {
+            var map = new MapField<string, string>();
+            var values = map.Values;
+            CollectionAssert.AreEqual(new string[0], values);
+            map["foo"] = "bar";
+            map["x"] = "y";
+            CollectionAssert.AreEqual(new[] { "bar", "y" }, values);
+        }
+
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void ViewsAreReadOnly()
+        {
+            var map = new MapField<string, string>();
+            var keys = map.Keys;
+            Assert.IsTrue(keys.IsReadOnly);
+            Assert.Throws<NotSupportedException>(() => keys.Clear());
+            Assert.Throws<NotSupportedException>(() => keys.Remove("a"));
+            Assert.Throws<NotSupportedException>(() => keys.Add("a"));
+        }
+
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void ViewCopyTo()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var keys = map.Keys;
+            var array = new string[4];
+            Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
+            Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
+            keys.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
+        }
+        
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void NonGenericViewCopyTo()
+        {
+            IDictionary map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            ICollection keys = map.Keys;
+            // Note the use of the Array type here rather than string[]
+            Array array = new string[4];
+            Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
+            Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
+            keys.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
+        }
+
+        [Test]
+        public void KeysContains()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var keys = map.Keys;
+            Assert.IsTrue(keys.Contains("foo"));
+            Assert.IsFalse(keys.Contains("bar")); // It's a value!
+            Assert.IsFalse(keys.Contains("1"));
+            // Keys can't be null, so we should prevent contains check
+            Assert.Throws<ArgumentNullException>(() => keys.Contains(null));
+        }
+
+        [Test]
+        public void ValuesContains()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var values = map.Values;
+            Assert.IsTrue(values.Contains("bar"));
+            Assert.IsFalse(values.Contains("foo")); // It's a key!
+            Assert.IsFalse(values.Contains("1"));
+            // Values can be null, so this makes sense
+            Assert.IsFalse(values.Contains(null));
+        }
+
+        [Test]
+        public void ToString_StringToString()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            Assert.AreEqual("{ \"foo\": \"bar\", \"x\": \"y\" }", map.ToString());
+        }
+
+        [Test]
+        public void ToString_UnsupportedKeyType()
+        {
+            var map = new MapField<byte, string> { { 10, "foo" } };
+            Assert.Throws<ArgumentException>(() => map.ToString());
+        }
+
+        private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
+        {
+            return new KeyValuePair<TKey, TValue>(key, value);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
new file mode 100644
index 0000000..8ed54cf
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
@@ -0,0 +1,660 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Google.Protobuf.TestProtos;
+using Google.Protobuf.WellKnownTypes;
+using NUnit.Framework;
+
+namespace Google.Protobuf.Collections
+{
+    public class RepeatedFieldTest
+    {
+        [Test]
+        public void NullValuesRejected()
+        {
+            var list = new RepeatedField<string>();
+            Assert.Throws<ArgumentNullException>(() => list.Add((string)null));
+            Assert.Throws<ArgumentNullException>(() => list.Add((IEnumerable<string>)null));
+            Assert.Throws<ArgumentNullException>(() => list.Add((RepeatedField<string>)null));
+            Assert.Throws<ArgumentNullException>(() => list.Contains(null));
+            Assert.Throws<ArgumentNullException>(() => list.IndexOf(null));
+        }
+
+        [Test]
+        public void Add_SingleItem()
+        {
+            var list = new RepeatedField<string>();
+            list.Add("foo");
+            Assert.AreEqual(1, list.Count);
+            Assert.AreEqual("foo", list[0]);
+        }
+
+        [Test]
+        public void Add_Sequence()
+        {
+            var list = new RepeatedField<string>();
+            list.Add(new[] { "foo", "bar" });
+            Assert.AreEqual(2, list.Count);
+            Assert.AreEqual("foo", list[0]);
+            Assert.AreEqual("bar", list[1]);
+        }
+
+        [Test]
+        public void Add_RepeatedField()
+        {
+            var list = new RepeatedField<string> { "original" };
+            list.Add(new RepeatedField<string> { "foo", "bar" });
+            Assert.AreEqual(3, list.Count);
+            Assert.AreEqual("original", list[0]);
+            Assert.AreEqual("foo", list[1]);
+            Assert.AreEqual("bar", list[2]);
+        }
+
+        [Test]
+        public void RemoveAt_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            list.RemoveAt(1);
+            CollectionAssert.AreEqual(new[] { "first", "third" }, list);
+            // Just check that these don't throw...
+            list.RemoveAt(list.Count - 1); // Now the count will be 1...
+            list.RemoveAt(0);
+            Assert.AreEqual(0, list.Count);
+        }
+
+        [Test]
+        public void RemoveAt_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(-1));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(3));
+        }
+
+        [Test]
+        public void Insert_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+            list.Insert(3, "end");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second", "end" }, list);
+            list.Insert(0, "start");
+            CollectionAssert.AreEqual(new[] { "start", "first", "middle", "second", "end" }, list);
+        }
+
+        [Test]
+        public void Insert_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, "foo"));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(3, "foo"));
+            Assert.Throws<ArgumentNullException>(() => list.Insert(0, null));
+        }
+
+        [Test]
+        public void Equals_RepeatedField()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((RepeatedField<string>) null));
+            Assert.IsTrue(list.Equals(list));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals(new RepeatedField<string> { "first", "second" }));
+        }
+
+        [Test]
+        public void Equals_Object()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((object) null));
+            Assert.IsTrue(list.Equals((object) list));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals((object) new RepeatedField<string> { "first", "second" }));
+            Assert.IsFalse(list.Equals(new object()));
+        }
+
+        [Test]
+        public void GetEnumerator_GenericInterface()
+        {
+            IEnumerable<string> list = new RepeatedField<string> { "first", "second" };
+            // Select gets rid of the optimizations in ToList...
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Select(x => x).ToList());
+        }
+
+        [Test]
+        public void GetEnumerator_NonGenericInterface()
+        {
+            IEnumerable list = new RepeatedField<string> { "first", "second" };
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Cast<object>().ToList());
+        }
+
+        [Test]
+        public void CopyTo()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, stringArray);
+        }
+
+        [Test]
+        public void Indexer_Get()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual("first", list[0]);
+            Assert.AreEqual("second", list[1]);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1].GetHashCode());
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2].GetHashCode());
+        }
+
+        [Test]
+        public void Indexer_Set()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list[0] = "changed";
+            Assert.AreEqual("changed", list[0]);
+            Assert.Throws<ArgumentNullException>(() => list[0] = null);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1] = "bad");
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2] = "bad");
+        }
+
+        [Test]
+        public void Clone_ReturnsMutable()
+        {
+            var list = new RepeatedField<int> { 0 };
+            var clone = list.Clone();
+            clone[0] = 1;
+        }
+
+        [Test]
+        public void Enumerator()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            using (var enumerator = list.GetEnumerator())
+            {
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("first", enumerator.Current);
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("second", enumerator.Current);
+                Assert.IsFalse(enumerator.MoveNext());
+                Assert.IsFalse(enumerator.MoveNext());
+            }
+        }
+
+        [Test]
+        public void AddEntriesFrom_PackedInt32()
+        {
+            uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var length = CodedOutputStream.ComputeInt32Size(10)
+                + CodedOutputStream.ComputeInt32Size(999)
+                + CodedOutputStream.ComputeInt32Size(-1000);
+            output.WriteTag(packedTag);
+            output.WriteRawVarint32((uint) length);
+            output.WriteInt32(10);
+            output.WriteInt32(999);
+            output.WriteInt32(-1000);
+            output.Flush();
+            stream.Position = 0;
+
+            // Deliberately "expecting" a non-packed tag, but we detect that the data is
+            // actually packed.
+            uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(packedTag);
+            field.AddEntriesFrom(input, FieldCodec.ForInt32(nonPackedTag));
+            CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_NonPackedInt32()
+        {
+            uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(10);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(999);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(-1000); // Just for variety...
+            output.Flush();
+            stream.Position = 0;
+
+            // Deliberately "expecting" a packed tag, but we detect that the data is
+            // actually not packed.
+            uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(nonPackedTag);
+            field.AddEntriesFrom(input, FieldCodec.ForInt32(packedTag));
+            CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_String()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteString("Foo");
+            output.WriteTag(tag);
+            output.WriteString("");
+            output.WriteTag(tag);
+            output.WriteString("Bar");
+            output.Flush();
+            stream.Position = 0;
+
+            var field = new RepeatedField<string>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            field.AddEntriesFrom(input, FieldCodec.ForString(tag));
+            CollectionAssert.AreEqual(new[] { "Foo", "", "Bar" }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_Message()
+        {
+            var message1 = new ForeignMessage { C = 2000 };
+            var message2 = new ForeignMessage { C = -250 };
+
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteMessage(message1);
+            output.WriteTag(tag);
+            output.WriteMessage(message2);
+            output.Flush();
+            stream.Position = 0;
+
+            var field = new RepeatedField<ForeignMessage>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            field.AddEntriesFrom(input, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
+            CollectionAssert.AreEqual(new[] { message1, message2}, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_PackedInt32()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int> { 10, 1000, 1000000 };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForInt32(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            var length = input.ReadLength();
+            Assert.AreEqual(10, input.ReadInt32());
+            Assert.AreEqual(1000, input.ReadInt32());
+            Assert.AreEqual(1000000, input.ReadInt32());
+            Assert.IsTrue(input.IsAtEnd);
+            Assert.AreEqual(1 + CodedOutputStream.ComputeLengthSize(length) + length, stream.Length);
+        }
+
+        [Test]
+        public void WriteTo_NonPackedInt32()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
+            var field = new RepeatedField<int> { 10, 1000, 1000000};
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForInt32(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual(10, input.ReadInt32());
+            input.AssertNextTag(tag);
+            Assert.AreEqual(1000, input.ReadInt32());
+            input.AssertNextTag(tag);
+            Assert.AreEqual(1000000, input.ReadInt32());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_String()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<string> { "Foo", "", "Bar" };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForString(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual("Foo", input.ReadString());
+            input.AssertNextTag(tag);
+            Assert.AreEqual("", input.ReadString());
+            input.AssertNextTag(tag);
+            Assert.AreEqual("Bar", input.ReadString());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_Message()
+        {
+            var message1 = new ForeignMessage { C = 20 };
+            var message2 = new ForeignMessage { C = 25 };
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<ForeignMessage> { message1, message2 };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual(message1, input.ReadMessage(ForeignMessage.Parser));
+            input.AssertNextTag(tag);
+            Assert.AreEqual(message2, input.ReadMessage(ForeignMessage.Parser));
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void CalculateSize_VariableSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Varint);
+            // 2 bytes for the first entry, 3 bytes for the second, 2 bytes for the third
+            Assert.AreEqual(7, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Fixed32);
+            // 5 bytes for the each entry
+            Assert.AreEqual(15, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_VariableSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1};
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length,
+            // 1 byte for the first entry, 2 bytes for the second, 1 byte for the third
+            Assert.AreEqual(6, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length, 4 bytes per entry
+            Assert.AreEqual(14, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
+
+        [Test]
+        public void TestNegativeEnumArray()
+        {
+            int arraySize = 1 + 1 + (11 * 5);
+            int msgSize = arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            uint tag = WireFormat.MakeTag(8, WireFormat.WireType.Varint);
+            for (int i = 0; i >= -5; i--)
+            {
+                output.WriteTag(tag);
+                output.WriteEnum(i);
+            }
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = new CodedInputStream(bytes);
+            tag = input.ReadTag();
+
+            RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
+            values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
+
+            Assert.AreEqual(6, values.Count);
+            Assert.AreEqual(SampleEnum.None, values[0]);
+            Assert.AreEqual(((SampleEnum)(-1)), values[1]);
+            Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
+            Assert.AreEqual(((SampleEnum)(-3)), values[3]);
+            Assert.AreEqual(((SampleEnum)(-4)), values[4]);
+            Assert.AreEqual(((SampleEnum)(-5)), values[5]);
+        }
+
+
+        [Test]
+        public void TestNegativeEnumPackedArray()
+        {
+            int arraySize = 1 + (10 * 5);
+            int msgSize = 1 + 1 + arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            // Length-delimited to show we want the packed representation
+            uint tag = WireFormat.MakeTag(8, WireFormat.WireType.LengthDelimited);
+            output.WriteTag(tag);
+            int size = 0;
+            for (int i = 0; i >= -5; i--)
+            {
+                size += CodedOutputStream.ComputeEnumSize(i);
+            }
+            output.WriteRawVarint32((uint)size);
+            for (int i = 0; i >= -5; i--)
+            {
+                output.WriteEnum(i);
+            }
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = new CodedInputStream(bytes);
+            tag = input.ReadTag();
+
+            RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
+            values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
+
+            Assert.AreEqual(6, values.Count);
+            Assert.AreEqual(SampleEnum.None, values[0]);
+            Assert.AreEqual(((SampleEnum)(-1)), values[1]);
+            Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
+            Assert.AreEqual(((SampleEnum)(-3)), values[3]);
+            Assert.AreEqual(((SampleEnum)(-4)), values[4]);
+            Assert.AreEqual(((SampleEnum)(-5)), values[5]);
+        }
+
+        // Fairly perfunctory tests for the non-generic IList implementation
+        [Test]
+        public void IList_Indexer()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.AreEqual("first", list[0]);
+            list[1] = "changed";
+            Assert.AreEqual("changed", field[1]);
+        }
+
+        [Test]
+        public void IList_Contains()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsTrue(list.Contains("second"));
+            Assert.IsFalse(list.Contains("third"));
+            Assert.IsFalse(list.Contains(new object()));
+        }
+
+        [Test]
+        public void IList_Add()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Add("third");
+            CollectionAssert.AreEqual(new[] { "first", "second", "third" }, list);
+        }
+
+        [Test]
+        public void IList_Remove()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Remove("third"); // No-op, no exception
+            list.Remove(new object()); // No-op, no exception
+            list.Remove("first");
+            CollectionAssert.AreEqual(new[] { "second" }, list);
+        }
+
+        [Test]
+        public void IList_IsFixedSize()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.IsFalse(list.IsFixedSize);
+        }
+
+        [Test]
+        public void IList_IndexOf()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual(1, list.IndexOf("second"));
+            Assert.AreEqual(-1, list.IndexOf("third"));
+            Assert.AreEqual(-1, list.IndexOf(new object()));
+        }
+
+        [Test]
+        public void IList_SyncRoot()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreSame(list, list.SyncRoot);
+        }
+
+        [Test]
+        public void IList_CopyTo()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first",  "second", null }, stringArray);
+
+            object[] objectArray = new object[4];
+            list.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, objectArray);
+
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new StringBuilder[4], 1));
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new int[4], 1));
+        }
+
+        [Test]
+        public void IList_IsSynchronized()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.IsSynchronized);
+        }
+
+        [Test]
+        public void IList_Insert()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+        }
+
+        [Test]
+        public void ToString_Integers()
+        {
+            var list = new RepeatedField<int> { 5, 10, 20 };
+            var text = list.ToString();
+            Assert.AreEqual("[ 5, 10, 20 ]", text);
+        }
+
+        [Test]
+        public void ToString_Strings()
+        {
+            var list = new RepeatedField<string> { "x", "y", "z" };
+            var text = list.ToString();
+            Assert.AreEqual("[ \"x\", \"y\", \"z\" ]", text);
+        }
+
+        [Test]
+        public void ToString_Messages()
+        {
+            var list = new RepeatedField<TestAllTypes> { new TestAllTypes { SingleDouble = 1.5 }, new TestAllTypes { SingleInt32 = 10 } };
+            var text = list.ToString();
+            Assert.AreEqual("[ { \"singleDouble\": 1.5 }, { \"singleInt32\": 10 } ]", text);
+        }
+
+        [Test]
+        public void ToString_Empty()
+        {
+            var list = new RepeatedField<TestAllTypes> { };
+            var text = list.ToString();
+            Assert.AreEqual("[ ]", text);
+        }
+
+        [Test]
+        public void ToString_InvalidElementType()
+        {
+            var list = new RepeatedField<decimal> { 15m };
+            Assert.Throws<ArgumentException>(() => list.ToString());
+        }
+
+        [Test]
+        public void ToString_Timestamp()
+        {
+            var list = new RepeatedField<Timestamp> { Timestamp.FromDateTime(new DateTime(2015, 10, 1, 12, 34, 56, DateTimeKind.Utc)) };
+            var text = list.ToString();
+            Assert.AreEqual("[ \"2015-10-01T12:34:56Z\" ]", text);
+        }
+
+        [Test]
+        public void ToString_Struct()
+        {
+            var message = new Struct { Fields = { { "foo", new Value { NumberValue = 20 } } } };
+            var list = new RepeatedField<Struct> { message };
+            var text = list.ToString();
+            Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs
new file mode 100644
index 0000000..df23a09
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs
@@ -0,0 +1,98 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using NUnit.Framework;
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    public class PropertyInfoExtensionsTest
+    {
+        public string PublicReadWrite { get; set; }
+        private string PrivateReadWrite { get; set; }
+        public string PublicReadPrivateWrite { get; private set; }
+        public string PrivateReadPublicWrite { private get; set; }
+        public string PublicReadOnly { get { return null; } }
+        private string PrivateReadOnly { get { return null; } }
+        public string PublicWriteOnly { set { } }
+        private string PrivateWriteOnly { set {  } }
+
+        [Test]
+        [TestCase("PublicReadWrite")]
+        [TestCase("PublicReadPrivateWrite")]
+        [TestCase("PublicReadOnly")]
+        public void GetGetMethod_Success(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNotNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PrivateReadWrite")]
+        [TestCase("PrivateReadPublicWrite")]
+        [TestCase("PrivateReadOnly")]
+        [TestCase("PublicWriteOnly")]
+        [TestCase("PrivateWriteOnly")]
+        public void GetGetMethod_NoAccessibleGetter(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PublicReadWrite")]
+        [TestCase("PrivateReadPublicWrite")]
+        [TestCase("PublicWriteOnly")]
+        public void GetSetMethod_Success(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNotNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PublicReadPrivateWrite")]
+        [TestCase("PrivateReadWrite")]
+        [TestCase("PrivateReadOnly")]
+        [TestCase("PublicReadOnly")]
+        [TestCase("PrivateWriteOnly")]
+        public void GetSetMethod_NoAccessibleGetter(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
+        }
+    }
+
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
new file mode 100644
index 0000000..f0c8d3b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
@@ -0,0 +1,133 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    public class TypeExtensionsTest
+    {
+        public class DerivedList : List<string> { }
+        public string PublicProperty { get; set; }
+        private string PrivateProperty { get; set; }
+
+        public void PublicMethod()
+        {
+        }
+
+        private void PrivateMethod()
+        {
+        }
+
+        [Test]
+        [TestCase(typeof(int), true)]
+        [TestCase(typeof(int?), true)]
+        [TestCase(typeof(Nullable<>), true)]
+        [TestCase(typeof(WireFormat.WireType), true)]
+        [TestCase(typeof(string), false)]
+        [TestCase(typeof(object), false)]
+        [TestCase(typeof(Enum), false)]
+        [TestCase(typeof(ValueType), false)]
+        [TestCase(typeof(TypeExtensionsTest), false)]
+        [TestCase(typeof(Action), false)]
+        [TestCase(typeof(Action<>), false)]
+        [TestCase(typeof(IDisposable), false)]
+        public void IsValueType(Type type, bool expected)
+        {
+            Assert.AreEqual(expected, TypeExtensions.IsValueType(type));
+        }
+
+        [Test]
+        [TestCase(typeof(object), typeof(string), true)]
+        [TestCase(typeof(object), typeof(int), true)]
+        [TestCase(typeof(string), typeof(string), true)]
+        [TestCase(typeof(string), typeof(object), false)]
+        [TestCase(typeof(string), typeof(int), false)]
+        [TestCase(typeof(int), typeof(int), true)]
+        [TestCase(typeof(ValueType), typeof(int), true)]
+        [TestCase(typeof(long), typeof(int), false)] // 
+        public void IsAssignableFrom(Type target, Type argument, bool expected)
+        {
+            Assert.AreEqual(expected, TypeExtensions.IsAssignableFrom(target, argument));
+        }
+
+        [Test]
+        [TestCase(typeof(DerivedList), "Count")] // Go up the type hierarchy
+        [TestCase(typeof(List<string>), "Count")]
+        [TestCase(typeof(List<>), "Count")]
+        [TestCase(typeof(TypeExtensionsTest), "PublicProperty")]
+        public void GetProperty_Success(Type type, string name)
+        {
+            var property = TypeExtensions.GetProperty(type, name);
+            Assert.IsNotNull(property);
+            Assert.AreEqual(name, property.Name);
+        }
+
+        [Test]
+        [TestCase(typeof(TypeExtensionsTest), "PrivateProperty")]
+        [TestCase(typeof(TypeExtensionsTest), "Garbage")]
+        public void GetProperty_NoSuchProperty(Type type, string name)
+        {
+            var property = TypeExtensions.GetProperty(type, name);
+            Assert.IsNull(property);
+        }
+
+        [Test]
+        [TestCase(typeof(DerivedList), "RemoveAt")] // Go up the type hierarchy
+        [TestCase(typeof(List<>), "RemoveAt")]
+        [TestCase(typeof(TypeExtensionsTest), "PublicMethod")]
+        public void GetMethod_Success(Type type, string name)
+        {
+            var method = TypeExtensions.GetMethod(type, name);
+            Assert.IsNotNull(method);
+            Assert.AreEqual(name, method.Name);
+        }
+
+        [Test]
+        [TestCase(typeof(TypeExtensionsTest), "PrivateMethod")]
+        [TestCase(typeof(TypeExtensionsTest), "GarbageMethod")]
+        public void GetMethod_NoSuchMethod(Type type, string name)
+        {
+            var method = TypeExtensions.GetMethod(type, name);
+            Assert.IsNull(method);
+        }
+
+        [Test]
+        [TestCase(typeof(List<string>), "IndexOf")]
+        public void GetMethod_Ambiguous(Type type, string name)
+        {
+            Assert.Throws<AmbiguousMatchException>(() => TypeExtensions.GetMethod(type, name));
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
new file mode 100644
index 0000000..8dfad8b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
@@ -0,0 +1,55 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+    
+using System;
+using System.Reflection;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class DeprecatedMemberTest
+    {
+        private static void AssertIsDeprecated(MemberInfo member)
+        {
+            Assert.NotNull(member);
+            Assert.IsTrue(member.IsDefined(typeof(ObsoleteAttribute), false), "Member not obsolete: " + member);
+        }
+
+        [Test]
+        public void TestDepreatedPrimitiveValue()
+        {
+            AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32"));
+        }
+
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/EqualityTester.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/EqualityTester.cs
new file mode 100644
index 0000000..a669bab
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/EqualityTester.cs
@@ -0,0 +1,64 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Helper methods when testing equality. NUnit's Assert.AreEqual and
+    /// Assert.AreNotEqual methods try to be clever with collections, which can
+    /// be annoying...
+    /// </summary>
+    internal static class EqualityTester
+    {
+        public static void AssertEquality<T>(T first, T second) where T : IEquatable<T>
+        {
+            Assert.IsTrue(first.Equals(second));
+            Assert.IsTrue(first.Equals((object) second));
+            Assert.AreEqual(first.GetHashCode(), second.GetHashCode());
+        }
+
+        public static void AssertInequality<T>(T first, T second) where T : IEquatable<T>
+        {
+            Assert.IsFalse(first.Equals(second));
+            Assert.IsFalse(first.Equals((object) second));
+            // While this isn't a requirement, the chances of this test failing due to
+            // coincidence rather than a bug are very small.
+            if (first != null && second != null)
+            {
+                Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
new file mode 100644
index 0000000..c616470
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
@@ -0,0 +1,195 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.Collections.Generic;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class FieldCodecTest
+    {
+#pragma warning disable 0414 // Used by tests via reflection - do not remove!
+        private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
+        {
+            new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
+            new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
+            new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
+            new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
+            new FieldCodecTestData<int>(FieldCodec.ForSInt32(100), -1000, "SInt32"),
+            new FieldCodecTestData<int>(FieldCodec.ForSFixed32(100), -1000, "SFixed32"),
+            new FieldCodecTestData<uint>(FieldCodec.ForUInt32(100), 1234, "UInt32"),
+            new FieldCodecTestData<uint>(FieldCodec.ForFixed32(100), 1234, "Fixed32"),
+            new FieldCodecTestData<long>(FieldCodec.ForInt64(100), -1000, "Int64"),
+            new FieldCodecTestData<long>(FieldCodec.ForSInt64(100), -1000, "SInt64"),
+            new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
+            new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
+            new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
+            new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
+            new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
+            new FieldCodecTestData<ForeignEnum>(
+                FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"),
+            new FieldCodecTestData<ForeignMessage>(
+                FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"),
+        };
+#pragma warning restore 0414
+
+        [Test, TestCaseSource("Codecs")]
+        public void RoundTripWithTag(ICodecTestData codec)
+        {
+            codec.TestRoundTripWithTag();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void RoundTripRaw(ICodecTestData codec)
+        {
+            codec.TestRoundTripRaw();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void CalculateSize(ICodecTestData codec)
+        {
+            codec.TestCalculateSizeWithTag();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void DefaultValue(ICodecTestData codec)
+        {
+            codec.TestDefaultValue();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void FixedSize(ICodecTestData codec)
+        {
+            codec.TestFixedSize();
+        }
+
+        // This is ugly, but it means we can have a non-generic interface.
+        // It feels like NUnit should support this better, but I don't know
+        // of any better ways right now.
+        public interface ICodecTestData
+        {
+            void TestRoundTripRaw();
+            void TestRoundTripWithTag();
+            void TestCalculateSizeWithTag();
+            void TestDefaultValue();
+            void TestFixedSize();
+        }
+
+        public class FieldCodecTestData<T> : ICodecTestData
+        {
+            private readonly FieldCodec<T> codec;
+            private readonly T sampleValue;
+            private readonly string name;
+
+            public FieldCodecTestData(FieldCodec<T> codec, T sampleValue, string name)
+            {
+                this.codec = codec;
+                this.sampleValue = sampleValue;
+                this.name = name;
+            }
+
+            public void TestRoundTripRaw()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.ValueWriter(codedOutput, sampleValue);
+                codedOutput.Flush();
+                stream.Position = 0;
+                var codedInput = new CodedInputStream(stream);
+                Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
+                Assert.IsTrue(codedInput.IsAtEnd);
+            }
+
+            public void TestRoundTripWithTag()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, sampleValue);
+                codedOutput.Flush();
+                stream.Position = 0;
+                var codedInput = new CodedInputStream(stream);
+                codedInput.AssertNextTag(codec.Tag);
+                Assert.AreEqual(sampleValue, codec.Read(codedInput));
+                Assert.IsTrue(codedInput.IsAtEnd);
+            }
+
+            public void TestCalculateSizeWithTag()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, sampleValue);
+                codedOutput.Flush();
+                Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue));
+            }
+
+            public void TestDefaultValue()
+            {
+                // WriteTagAndValue ignores default values
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
+                codedOutput.Flush();
+                Assert.AreEqual(0, stream.Position);
+                Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
+                if (typeof(T).IsValueType)
+                {
+                    Assert.AreEqual(default(T), codec.DefaultValue);
+                }
+
+                // The plain ValueWriter/ValueReader delegates don't.
+                if (codec.DefaultValue != null) // This part isn't appropriate for message types.
+                {
+                    codedOutput = new CodedOutputStream(stream);
+                    codec.ValueWriter(codedOutput, codec.DefaultValue);
+                    codedOutput.Flush();
+                    Assert.AreNotEqual(0, stream.Position);
+                    Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
+                    stream.Position = 0;
+                    var codedInput = new CodedInputStream(stream);
+                    Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
+                }
+            }
+
+            public void TestFixedSize()
+            {
+                Assert.AreEqual(name.Contains("Fixed"), codec.FixedSize != 0);
+            }
+
+            public override string ToString()
+            {
+                return name;
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
new file mode 100644
index 0000000..b029551
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -0,0 +1,723 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Google.Protobuf.WellKnownTypes;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests around the generated TestAllTypes message.
+    /// </summary>
+    public class GeneratedMessageTest
+    {
+        [Test]
+        public void EmptyMessageFieldDistinctFromMissingMessageField()
+        {
+            // This demonstrates what we're really interested in...
+            var message1 = new TestAllTypes { SingleForeignMessage = new ForeignMessage() };
+            var message2 = new TestAllTypes(); // SingleForeignMessage is null
+            EqualityTester.AssertInequality(message1, message2);
+        }
+
+        [Test]
+        public void DefaultValues()
+        {
+            // Single fields
+            var message = new TestAllTypes();
+            Assert.AreEqual(false, message.SingleBool);
+            Assert.AreEqual(ByteString.Empty, message.SingleBytes);
+            Assert.AreEqual(0.0, message.SingleDouble);
+            Assert.AreEqual(0, message.SingleFixed32);
+            Assert.AreEqual(0L, message.SingleFixed64);
+            Assert.AreEqual(0.0f, message.SingleFloat);
+            Assert.AreEqual(ForeignEnum.ForeignUnspecified, message.SingleForeignEnum);
+            Assert.IsNull(message.SingleForeignMessage);
+            Assert.AreEqual(ImportEnum.Unspecified, message.SingleImportEnum);
+            Assert.IsNull(message.SingleImportMessage);
+            Assert.AreEqual(0, message.SingleInt32);
+            Assert.AreEqual(0L, message.SingleInt64);
+            Assert.AreEqual(TestAllTypes.Types.NestedEnum.Unspecified, message.SingleNestedEnum);
+            Assert.IsNull(message.SingleNestedMessage);
+            Assert.IsNull(message.SinglePublicImportMessage);
+            Assert.AreEqual(0, message.SingleSfixed32);
+            Assert.AreEqual(0L, message.SingleSfixed64);
+            Assert.AreEqual(0, message.SingleSint32);
+            Assert.AreEqual(0L, message.SingleSint64);
+            Assert.AreEqual("", message.SingleString);
+            Assert.AreEqual(0U, message.SingleUint32);
+            Assert.AreEqual(0UL, message.SingleUint64);
+
+            // Repeated fields
+            Assert.AreEqual(0, message.RepeatedBool.Count);
+            Assert.AreEqual(0, message.RepeatedBytes.Count);
+            Assert.AreEqual(0, message.RepeatedDouble.Count);
+            Assert.AreEqual(0, message.RepeatedFixed32.Count);
+            Assert.AreEqual(0, message.RepeatedFixed64.Count);
+            Assert.AreEqual(0, message.RepeatedFloat.Count);
+            Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
+            Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
+            Assert.AreEqual(0, message.RepeatedImportEnum.Count);
+            Assert.AreEqual(0, message.RepeatedImportMessage.Count);
+            Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
+            Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
+            Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count);
+            Assert.AreEqual(0, message.RepeatedSfixed32.Count);
+            Assert.AreEqual(0, message.RepeatedSfixed64.Count);
+            Assert.AreEqual(0, message.RepeatedSint32.Count);
+            Assert.AreEqual(0, message.RepeatedSint64.Count);
+            Assert.AreEqual(0, message.RepeatedString.Count);
+            Assert.AreEqual(0, message.RepeatedUint32.Count);
+            Assert.AreEqual(0, message.RepeatedUint64.Count);
+
+            // Oneof fields
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+        }
+
+        [Test]
+        public void NullStringAndBytesRejected()
+        {
+            var message = new TestAllTypes();
+            Assert.Throws<ArgumentNullException>(() => message.SingleString = null);
+            Assert.Throws<ArgumentNullException>(() => message.OneofString = null);
+            Assert.Throws<ArgumentNullException>(() => message.SingleBytes = null);
+            Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null);
+        }
+
+        [Test]
+        public void RoundTrip_Empty()
+        {
+            var message = new TestAllTypes();
+            // Without setting any values, there's nothing to write.
+            byte[] bytes = message.ToByteArray();
+            Assert.AreEqual(0, bytes.Length);
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void RoundTrip_SingleValues()
+        {
+            var message = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.ForeignBar,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.ImportBaz,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void RoundTrip_RepeatedValues()
+        {
+            var message = new TestAllTypes
+            {
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { uint.MaxValue, 23 },
+                RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedForeignEnum = { ForeignEnum.ForeignFoo, ForeignEnum.ForeignBar },
+                RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
+                RepeatedImportEnum = { ImportEnum.ImportBaz, ImportEnum.Unspecified },
+                RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, long.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
+                RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { uint.MaxValue, uint.MinValue },
+                RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        // Note that not every map within map_unittest_proto3 is used. They all go through very
+        // similar code paths. The fact that all maps are present is validation that we have codecs
+        // for every type.
+        [Test]
+        public void RoundTrip_Maps()
+        {
+            var message = new TestMap
+            {
+                MapBoolBool = {
+                    { false, true },
+                    { true, false }
+                },
+                MapInt32Bytes = {
+                    { 5, ByteString.CopyFrom(6, 7, 8) },
+                    { 25, ByteString.CopyFrom(1, 2, 3, 4, 5) },
+                    { 10, ByteString.Empty }
+                },
+                MapInt32ForeignMessage = {
+                    { 0, new ForeignMessage { C = 10 } },
+                    { 5, new ForeignMessage() },
+                },
+                MapInt32Enum = {
+                    { 1, MapEnum.Bar },
+                    { 2000, MapEnum.Foo }
+                }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestMap parsed = TestMap.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void MapWithEmptyEntry()
+        {
+            var message = new TestMap
+            {
+                MapInt32Bytes = { { 0, ByteString.Empty } }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)
+
+            var parsed = TestMap.Parser.ParseFrom(bytes);
+            Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
+            Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
+        }
+
+        [Test]
+        public void MapWithOnlyValue()
+        {
+            // Hand-craft the stream to contain a single entry with just a value.
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+            output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
+            var nestedMessage = new ForeignMessage { C = 20 };
+            // Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
+            output.WriteLength(2 + nestedMessage.CalculateSize());
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteMessage(nestedMessage);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);
+        }
+
+        [Test]
+        public void MapWithOnlyKey_PrimitiveValue()
+        {
+            // Hand-craft the stream to contain a single entry with just a key.
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+            output.WriteTag(TestMap.MapInt32DoubleFieldNumber, WireFormat.WireType.LengthDelimited);
+            int key = 10;
+            output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(0.0, parsed.MapInt32Double[key]);
+        }
+
+        [Test]
+        public void MapWithOnlyKey_MessageValue()
+        {
+            // Hand-craft the stream to contain a single entry with just a key.
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+            output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
+            int key = 10;
+            output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);
+        }
+
+        [Test]
+        public void MapIgnoresExtraFieldsWithinEntryMessages()
+        {
+            // Hand-craft the stream to contain a single entry with three fields
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+
+            var key = 10; // Field 1 
+            var value = 20; // Field 2
+            var extra = 30; // Field 3
+
+            // Each field can be represented in a single byte, with a single byte tag.
+            // Total message size: 6 bytes.
+            output.WriteLength(6);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value);
+            output.WriteTag(3, WireFormat.WireType.Varint);
+            output.WriteInt32(extra);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value, parsed.MapInt32Int32[key]);
+        }
+
+        [Test]
+        public void MapFieldOrderIsIrrelevant()
+        {
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+
+            var key = 10;
+            var value = 20;
+
+            // Each field can be represented in a single byte, with a single byte tag.
+            // Total message size: 4 bytes.
+            output.WriteLength(4);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value, parsed.MapInt32Int32[key]);
+        }
+
+        [Test]
+        public void MapNonContiguousEntries()
+        {
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+
+            // Message structure:
+            // Entry for MapInt32Int32
+            // Entry for MapStringString
+            // Entry for MapInt32Int32
+
+            // First entry
+            var key1 = 10;
+            var value1 = 20;
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key1);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value1);
+
+            // Second entry
+            var key2 = "a";
+            var value2 = "b";
+            output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(6); // 3 bytes per entry: tag, size, character
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteString(key2);
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteString(value2);
+
+            // Third entry
+            var key3 = 15;
+            var value3 = 25;
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key3);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value3);
+
+            output.Flush();
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            var expected = new TestMap
+            {
+                MapInt32Int32 = { { key1, value1 }, { key3, value3 } },
+                MapStringString = { { key2, value2 } }
+            };
+            Assert.AreEqual(expected, parsed);
+        }
+
+        [Test]
+        public void DuplicateKeys_LastEntryWins()
+        {
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+
+            var key = 10;
+            var value1 = 20;
+            var value2 = 30;
+
+            // First entry
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value1);
+
+            // Second entry - same key, different value
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value2);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value2, parsed.MapInt32Int32[key]);
+        }
+
+        [Test]
+        public void CloneSingleNonMessageValues()
+        {
+            var original = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue
+            };
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.SingleInt32 = 150;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedNonMessageValues()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { uint.MaxValue, 23 },
+                RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, long.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { uint.MaxValue, uint.MinValue },
+                RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.RepeatedDouble.Add(25.5);
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneSingleMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
+            Assert.AreEqual(original, clone);
+
+            clone.SingleNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
+            Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
+            Assert.AreEqual(original, clone);
+
+            clone.RepeatedNestedMessage[0].Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneOneofField()
+        {
+            var original = new TestAllTypes
+            {
+                OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+
+            // We should have cloned the message
+            original.OneofNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void OneofProperties()
+        {
+            // Switch the oneof case between each of the different options, and check everything behaves
+            // as expected in each case.
+            var message = new TestAllTypes();
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+
+            message.OneofString = "sample";
+            Assert.AreEqual("sample", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+
+            var bytes = ByteString.CopyFrom(1, 2, 3);
+            message.OneofBytes = bytes;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(bytes, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
+
+            message.OneofUint32 = 20;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(20, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
+
+            var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
+            message.OneofNestedMessage = nestedMessage;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
+
+            message.ClearOneofField();
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
+        public void Oneof_DefaultValuesNotEqual()
+        {
+            var message1 = new TestAllTypes { OneofString = "" };
+            var message2 = new TestAllTypes { OneofUint32 = 0 };
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message1.OneofFieldCase);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
+            Assert.AreNotEqual(message1, message2);
+        }
+
+        [Test]
+        public void OneofSerialization_NonDefaultValue()
+        {
+            var message = new TestAllTypes();
+            message.OneofString = "this would take a bit of space";
+            message.OneofUint32 = 10;
+            var bytes = message.ToByteArray();
+            Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
+
+            var message2 = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, message2);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
+        }
+
+        [Test]
+        public void OneofSerialization_DefaultValue()
+        {
+            var message = new TestAllTypes();
+            message.OneofString = "this would take a bit of space";
+            message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
+            var bytes = message.ToByteArray();
+            Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
+
+            var message2 = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, message2);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
+        }
+
+        [Test]
+        public void IgnoreUnknownFields_RealDataStillRead()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var unusedFieldNumber = 23456;
+            Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
+            output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteString("ignore me");
+            message.WriteTo(output);
+            output.Flush();
+
+            stream.Position = 0;
+            var parsed = TestAllTypes.Parser.ParseFrom(stream);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void IgnoreUnknownFields_AllTypes()
+        {
+            // Simple way of ensuring we can skip all kinds of fields.
+            var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
+            var empty = Empty.Parser.ParseFrom(data);
+            Assert.AreEqual(new Empty(), empty);
+        }
+
+        // This was originally seen as a conformance test failure.
+        [Test]
+        public void TruncatedMessageFieldThrows()
+        {
+            // 130, 3 is the message tag
+            // 1 is the data length - but there's no data.
+            var data = new byte[] { 130, 3, 1 };
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
+        }
+
+        /// <summary>
+        /// Demonstrates current behaviour with an extraneous end group tag - see issue 688
+        /// for details; we may want to change this.
+        /// </summary>
+        [Test]
+        public void ExtraEndGroupThrows()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+
+            output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.WireType.Fixed32);
+            output.WriteFixed32(123);
+            output.WriteTag(100, WireFormat.WireType.EndGroup);
+
+            output.Flush();
+
+            stream.Position = 0;
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream));
+        }
+
+        [Test]
+        public void CustomDiagnosticMessage_DirectToStringCall()
+        {
+            var message = new ForeignMessage { C = 31 };
+            Assert.AreEqual("{ \"c\": 31, \"@cInHex\": \"1f\" }", message.ToString());
+            Assert.AreEqual("{ \"c\": 31 }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void CustomDiagnosticMessage_Nested()
+        {
+            var message = new TestAllTypes { SingleForeignMessage = new ForeignMessage { C = 16 } };
+            Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16, \"@cInHex\": \"10\" } }", message.ToString());
+            Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16 } }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void CustomDiagnosticMessage_DirectToTextWriterCall()
+        {
+            var message = new ForeignMessage { C = 31 };
+            var writer = new StringWriter();
+            JsonFormatter.Default.Format(message, writer);
+            Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
new file mode 100644
index 0000000..5d3de4a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf</RootNamespace>
+    <AssemblyName>Google.Protobuf.Test</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
+    <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ByteStringTest.cs" />
+    <Compile Include="CodedInputStreamExtensions.cs" />
+    <Compile Include="CodedInputStreamTest.cs" />
+    <Compile Include="CodedOutputStreamTest.cs" />
+    <Compile Include="Compatibility\PropertyInfoExtensionsTest.cs" />
+    <Compile Include="Compatibility\TypeExtensionsTest.cs" />
+    <Compile Include="EqualityTester.cs" />
+    <Compile Include="FieldCodecTest.cs" />
+    <Compile Include="GeneratedMessageTest.cs" />
+    <Compile Include="Collections\MapFieldTest.cs" />
+    <Compile Include="Collections\RepeatedFieldTest.cs" />
+    <Compile Include="JsonFormatterTest.cs" />
+    <Compile Include="JsonParserTest.cs" />
+    <Compile Include="JsonTokenizerTest.cs" />
+    <Compile Include="Reflection\DescriptorsTest.cs" />
+    <Compile Include="Reflection\FieldAccessTest.cs" />
+    <Compile Include="Reflection\TypeRegistryTest.cs" />
+    <Compile Include="SampleEnum.cs" />
+    <Compile Include="SampleMessages.cs" />
+    <Compile Include="TestProtos\ForeignMessagePartial.cs" />
+    <Compile Include="TestProtos\MapUnittestProto3.cs" />
+    <Compile Include="TestProtos\UnittestImportProto3.cs" />
+    <Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
+    <Compile Include="TestProtos\UnittestIssues.cs" />
+    <Compile Include="TestProtos\UnittestProto3.cs" />
+    <Compile Include="DeprecatedMemberTest.cs" />
+    <Compile Include="IssuesTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestCornerCases.cs" />
+    <Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
+    <Compile Include="WellKnownTypes\AnyTest.cs" />
+    <Compile Include="WellKnownTypes\DurationTest.cs" />
+    <Compile Include="WellKnownTypes\FieldMaskTest.cs" />
+    <Compile Include="WellKnownTypes\TimestampTest.cs" />
+    <Compile Include="WellKnownTypes\WrappersTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/IssuesTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/IssuesTest.cs
new file mode 100644
index 0000000..ddb23aa
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/IssuesTest.cs
@@ -0,0 +1,82 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+using UnitTest.Issues.TestProtos;
+using NUnit.Framework;
+
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests for issues which aren't easily compartmentalized into other unit tests.
+    /// </summary>
+    public class IssuesTest
+    {
+        // Issue 45
+        [Test]
+        public void FieldCalledItem()
+        {
+            ItemField message = new ItemField { Item = 3 };
+            FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
+            Assert.NotNull(field);
+            Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
+        }
+
+        [Test]
+        public void ReservedNames()
+        {
+            var message = new ReservedNames { Types_ = 10, Descriptor_ = 20 };
+            // Underscores aren't reflected in the JSON.
+            Assert.AreEqual("{ \"types\": 10, \"descriptor\": 20 }", message.ToString());
+        }
+
+        [Test]
+        public void JsonNameParseTest()
+        {
+            var settings = new JsonParser.Settings(10, TypeRegistry.FromFiles(UnittestIssuesReflection.Descriptor));
+            var parser = new JsonParser(settings);
+
+            // It is safe to use either original field name or explicitly specified json_name
+            Assert.AreEqual(new TestJsonName { Name = "test", Description = "test2", Guid = "test3" },
+                parser.Parse<TestJsonName>("{ \"name\": \"test\", \"desc\": \"test2\", \"guid\": \"test3\" }"));
+        }
+
+        [Test]
+        public void JsonNameFormatTest()
+        {
+            var message = new TestJsonName { Name = "test", Description = "test2", Guid = "test3" };
+            Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }",
+                JsonFormatter.Default.Format(message));
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
new file mode 100644
index 0000000..827a759
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
@@ -0,0 +1,526 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+using Google.Protobuf.WellKnownTypes;
+using Google.Protobuf.Reflection;
+
+using static Google.Protobuf.JsonParserTest; // For WrapInQuotes
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests for the JSON formatter. Note that in these tests, double quotes are replaced with apostrophes
+    /// for the sake of readability (embedding \" everywhere is painful). See the AssertJson method for details.
+    /// </summary>
+    public class JsonFormatterTest
+    {
+        [Test]
+        public void DefaultValues_WhenOmitted()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: false));
+
+            AssertJson("{ }", formatter.Format(new ForeignMessage()));
+            AssertJson("{ }", formatter.Format(new TestAllTypes()));
+            AssertJson("{ }", formatter.Format(new TestMap()));
+        }
+
+        [Test]
+        public void DefaultValues_WhenIncluded()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: true));
+            AssertJson("{ 'c': 0 }", formatter.Format(new ForeignMessage()));
+        }
+
+        [Test]
+        public void AllSingleFields()
+        {
+            var message = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.ForeignBar,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.ImportBaz,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test\twith\ttabs",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue,
+            };
+            var actualText = JsonFormatter.Default.Format(message);
+
+            // Fields in numeric order
+            var expectedText = "{ " +
+                "'singleInt32': 100, " +
+                "'singleInt64': '3210987654321', " +
+                "'singleUint32': 4294967295, " +
+                "'singleUint64': '18446744073709551615', " +
+                "'singleSint32': -456, " +
+                "'singleSint64': '-12345678901235', " +
+                "'singleFixed32': 23, " +
+                "'singleFixed64': '1234567890123', " +
+                "'singleSfixed32': -123, " +
+                "'singleSfixed64': '-12345678901234', " +
+                "'singleFloat': 12.25, " +
+                "'singleDouble': 23.5, " +
+                "'singleBool': true, " +
+                "'singleString': 'test\\twith\\ttabs', " +
+                "'singleBytes': 'AQIDBA==', " +
+                "'singleNestedMessage': { 'bb': 35 }, " +
+                "'singleForeignMessage': { 'c': 10 }, " +
+                "'singleImportMessage': { 'd': 20 }, " +
+                "'singleNestedEnum': 'FOO', " +
+                "'singleForeignEnum': 'FOREIGN_BAR', " +
+                "'singleImportEnum': 'IMPORT_BAZ', " +
+                "'singlePublicImportMessage': { 'e': 54 }" +
+                " }";
+            AssertJson(expectedText, actualText);
+        }
+
+        [Test]
+        public void RepeatedField()
+        {
+            AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }",
+                JsonFormatter.Default.Format(new TestAllTypes { RepeatedInt32 = { 1, 2, 3, 4, 5 } }));
+        }
+
+        [Test]
+        public void MapField_StringString()
+        {
+            AssertJson("{ 'mapStringString': { 'with spaces': 'bar', 'a': 'b' } }",
+                JsonFormatter.Default.Format(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } }));
+        }
+
+        [Test]
+        public void MapField_Int32Int32()
+        {
+            // The keys are quoted, but the values aren't.
+            AssertJson("{ 'mapInt32Int32': { '0': 1, '2': 3 } }",
+                JsonFormatter.Default.Format(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } }));
+        }
+
+        [Test]
+        public void MapField_BoolBool()
+        {
+            // The keys are quoted, but the values aren't.
+            AssertJson("{ 'mapBoolBool': { 'false': true, 'true': false } }",
+                JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } }));
+        }
+
+        [TestCase(1.0, "1")]
+        [TestCase(double.NaN, "'NaN'")]
+        [TestCase(double.PositiveInfinity, "'Infinity'")]
+        [TestCase(double.NegativeInfinity, "'-Infinity'")]
+        public void DoubleRepresentations(double value, string expectedValueText)
+        {
+            var message = new TestAllTypes { SingleDouble = value };
+            string actualText = JsonFormatter.Default.Format(message);
+            string expectedText = "{ 'singleDouble': " + expectedValueText + " }";
+            AssertJson(expectedText, actualText);
+        }
+
+        [Test]
+        public void UnknownEnumValueNumeric_SingleField()
+        {
+            var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 };
+            AssertJson("{ 'singleForeignEnum': 100 }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValueNumeric_RepeatedField()
+        {
+            var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.ForeignBaz, (ForeignEnum) 100, ForeignEnum.ForeignFoo } };
+            AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 100, 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValueNumeric_MapField()
+        {
+            var message = new TestMap { MapInt32Enum = { { 1, MapEnum.Foo }, { 2, (MapEnum) 100 }, { 3, MapEnum.Bar } } };
+            AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '2': 100, '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValue_RepeatedField_AllEntriesUnknown()
+        {
+            var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } };
+            AssertJson("{ 'repeatedForeignEnum': [ 200, 100 ] }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase("a\u17b4b", "a\\u17b4b")] // Explicit
+        [TestCase("a\u0601b", "a\\u0601b")] // Ranged
+        [TestCase("a\u0605b", "a\u0605b")] // Passthrough (note lack of double backslash...)
+        public void SimpleNonAscii(string text, string encoded)
+        {
+            var message = new TestAllTypes { SingleString = text };
+            AssertJson("{ 'singleString': '" + encoded + "' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void SurrogatePairEscaping()
+        {
+            var message = new TestAllTypes { SingleString = "a\uD801\uDC01b" };
+            AssertJson("{ 'singleString': 'a\\ud801\\udc01b' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void InvalidSurrogatePairsFail()
+        {
+            // Note: don't use TestCase for these, as the strings can't be reliably represented 
+            // See http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/
+
+            // Lone low surrogate
+            var message = new TestAllTypes { SingleString = "a\uDC01b" };
+            Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
+
+            // Lone high surrogate
+            message = new TestAllTypes { SingleString = "a\uD801b" };
+            Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase("foo_bar", "fooBar")]
+        [TestCase("bananaBanana", "bananaBanana")]
+        [TestCase("BANANABanana", "bananaBanana")]
+        public void ToCamelCase(string original, string expected)
+        {
+            Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original));
+        }
+
+        [Test]
+        [TestCase(null, "{ }")]
+        [TestCase("x", "{ 'fooString': 'x' }")]
+        [TestCase("", "{ 'fooString': '' }")]
+        public void Oneof(string fooStringValue, string expectedJson)
+        {
+            var message = new TestOneof();
+            if (fooStringValue != null)
+            {
+                message.FooString = fooStringValue;
+            }
+
+            // We should get the same result both with and without "format default values".
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
+            AssertJson(expectedJson, formatter.Format(message));
+            formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            AssertJson(expectedJson, formatter.Format(message));
+        }
+
+        [Test]
+        public void WrapperFormatting_Single()
+        {
+            // Just a few examples, handling both classes and value types, and
+            // default vs non-default values
+            var message = new TestWellKnownTypes
+            {
+                Int64Field = 10,
+                Int32Field = 0,
+                BytesField = ByteString.FromBase64("ABCD"),
+                StringField = ""
+            };
+            var expectedJson = "{ 'int64Field': '10', 'int32Field': 0, 'stringField': '', 'bytesField': 'ABCD' }";
+            AssertJson(expectedJson, JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void WrapperFormatting_Message()
+        {
+            Assert.AreEqual("\"\"", JsonFormatter.Default.Format(new StringValue()));
+            Assert.AreEqual("0", JsonFormatter.Default.Format(new Int32Value()));
+        }
+
+        [Test]
+        public void WrapperFormatting_IncludeNull()
+        {
+            // The actual JSON here is very large because there are lots of fields. Just test a couple of them.
+            var message = new TestWellKnownTypes { Int32Field = 10 };
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            var actualJson = formatter.Format(message);
+            Assert.IsTrue(actualJson.Contains("\"int64Field\": null"));
+            Assert.IsFalse(actualJson.Contains("\"int32Field\": null"));
+        }
+
+        [Test]
+        public void OutputIsInNumericFieldOrder_NoDefaults()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
+            var message = new TestJsonFieldOrdering { PlainString = "p1", PlainInt32 = 2 };
+            AssertJson("{ 'plainString': 'p1', 'plainInt32': 2 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
+        }
+
+        [Test]
+        public void OutputIsInNumericFieldOrder_WithDefaults()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            var message = new TestJsonFieldOrdering();
+            AssertJson("{ 'plainString': '', 'plainInt32': 0 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
+        }
+
+        [Test]
+        [TestCase("1970-01-01T00:00:00Z", 0)]
+        [TestCase("1970-01-01T00:00:00.000000001Z", 1)]
+        [TestCase("1970-01-01T00:00:00.000000010Z", 10)]
+        [TestCase("1970-01-01T00:00:00.000000100Z", 100)]
+        [TestCase("1970-01-01T00:00:00.000001Z", 1000)]
+        [TestCase("1970-01-01T00:00:00.000010Z", 10000)]
+        [TestCase("1970-01-01T00:00:00.000100Z", 100000)]
+        [TestCase("1970-01-01T00:00:00.001Z", 1000000)]
+        [TestCase("1970-01-01T00:00:00.010Z", 10000000)]
+        [TestCase("1970-01-01T00:00:00.100Z", 100000000)]
+        [TestCase("1970-01-01T00:00:00.120Z", 120000000)]
+        [TestCase("1970-01-01T00:00:00.123Z", 123000000)]
+        [TestCase("1970-01-01T00:00:00.123400Z", 123400000)]
+        [TestCase("1970-01-01T00:00:00.123450Z", 123450000)]
+        [TestCase("1970-01-01T00:00:00.123456Z", 123456000)]
+        [TestCase("1970-01-01T00:00:00.123456700Z", 123456700)]
+        [TestCase("1970-01-01T00:00:00.123456780Z", 123456780)]
+        [TestCase("1970-01-01T00:00:00.123456789Z", 123456789)]
+        public void TimestampStandalone(string expected, int nanos)
+        {
+            Assert.AreEqual(WrapInQuotes(expected), new Timestamp { Nanos = nanos }.ToString());
+        }
+
+        [Test]
+        public void TimestampStandalone_FromDateTime()
+        {
+            // One before and one after the Unix epoch, more easily represented via DateTime.
+            Assert.AreEqual("\"1673-06-19T12:34:56Z\"",
+                new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp().ToString());
+            Assert.AreEqual("\"2015-07-31T10:29:34Z\"",
+                new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString());
+        }
+
+        [Test]
+        [TestCase(-1, -1)] // Would be valid as duration
+        [TestCase(1, Timestamp.MaxNanos + 1)]
+        [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)]
+        [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, 0)]
+        public void TimestampStandalone_NonNormalized(long seconds, int nanoseconds)
+        {
+            var timestamp = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+            Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(timestamp));
+        }
+
+        [Test]
+        public void TimestampField()
+        {
+            var message = new TestWellKnownTypes { TimestampField = new Timestamp() };
+            AssertJson("{ 'timestampField': '1970-01-01T00:00:00Z' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase(0, 0, "0s")]
+        [TestCase(1, 0, "1s")]
+        [TestCase(-1, 0, "-1s")]
+        [TestCase(0, 1, "0.000000001s")]
+        [TestCase(0, 10, "0.000000010s")]
+        [TestCase(0, 100, "0.000000100s")]
+        [TestCase(0, 1000, "0.000001s")]
+        [TestCase(0, 10000, "0.000010s")]
+        [TestCase(0, 100000, "0.000100s")]
+        [TestCase(0, 1000000, "0.001s")]
+        [TestCase(0, 10000000, "0.010s")]
+        [TestCase(0, 100000000, "0.100s")]
+        [TestCase(0, 120000000, "0.120s")]
+        [TestCase(0, 123000000, "0.123s")]
+        [TestCase(0, 123400000, "0.123400s")]
+        [TestCase(0, 123450000, "0.123450s")]
+        [TestCase(0, 123456000, "0.123456s")]
+        [TestCase(0, 123456700, "0.123456700s")]
+        [TestCase(0, 123456780, "0.123456780s")]
+        [TestCase(0, 123456789, "0.123456789s")]
+        [TestCase(0, -100000000, "-0.100s")]
+        [TestCase(1, 100000000, "1.100s")]
+        [TestCase(-1, -100000000, "-1.100s")]
+        public void DurationStandalone(long seconds, int nanoseconds, string expected)
+        {
+            var json = JsonFormatter.Default.Format(new Duration { Seconds = seconds, Nanos = nanoseconds });
+            Assert.AreEqual(WrapInQuotes(expected), json);
+        }
+
+        [Test]
+        [TestCase(1, 2123456789)]
+        [TestCase(1, -100000000)]
+        public void DurationStandalone_NonNormalized(long seconds, int nanoseconds)
+        {
+            var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+            Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(duration));
+        }
+
+        [Test]
+        public void DurationField()
+        {
+            var message = new TestWellKnownTypes { DurationField = new Duration() };
+            AssertJson("{ 'durationField': '0s' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void StructSample()
+        {
+            var message = new Struct
+            {
+                Fields =
+                {
+                    { "a", Value.ForNull() },
+                    { "b", Value.ForBool(false) },
+                    { "c", Value.ForNumber(10.5) },
+                    { "d", Value.ForString("text") },
+                    { "e", Value.ForList(Value.ForString("t1"), Value.ForNumber(5)) },
+                    { "f", Value.ForStruct(new Struct { Fields = { { "nested", Value.ForString("value") } } }) }
+                }
+            };
+            AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
+        }
+
+        [Test]
+        [TestCase("foo__bar")]
+        [TestCase("foo_3_ar")]
+        [TestCase("fooBar")]
+        public void FieldMaskInvalid(string input)
+        {
+            var mask = new FieldMask { Paths = { input } };
+            Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(mask));
+        }
+
+        [Test]
+        public void FieldMaskStandalone()
+        {
+            var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } };
+            Assert.AreEqual("\",single,withUnderscore,nested.field.name,nested..doubleDot\"", fieldMask.ToString());
+
+            // Invalid, but we shouldn't create broken JSON...
+            fieldMask = new FieldMask { Paths = { "x\\y" } };
+            Assert.AreEqual(@"""x\\y""", fieldMask.ToString());
+        }
+
+        [Test]
+        public void FieldMaskField()
+        {
+            var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } };
+            AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message));
+        }
+
+        // SourceContext is an example of a well-known type with no special JSON handling
+        [Test]
+        public void SourceContextStandalone()
+        {
+            var message = new SourceContext { FileName = "foo.proto" };
+            AssertJson("{ 'fileName': 'foo.proto' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void AnyWellKnownType()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(Timestamp.Descriptor)));
+            var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp();
+            var any = Any.Pack(timestamp);
+            AssertJson("{ '@type': 'type.googleapis.com/google.protobuf.Timestamp', 'value': '1673-06-19T12:34:56Z' }", formatter.Format(any));
+        }
+
+        [Test]
+        public void AnyMessageType()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
+            var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } };
+            var any = Any.Pack(message);
+            AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any));
+        }
+
+        [Test]
+        public void AnyMessageType_CustomPrefix()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
+            var message = new TestAllTypes { SingleInt32 = 10 };
+            var any = Any.Pack(message, "foo.bar/baz");
+            AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any));
+        }
+
+        [Test]
+        public void AnyNested()
+        {
+            var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor);
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry));
+
+            // Nest an Any as the value of an Any.
+            var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 };
+            var nestedMessage = Any.Pack(doubleNestedMessage);
+            var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) };
+            AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 20 } } }",
+                formatter.Format(message));
+        }
+
+        [Test]
+        public void AnyUnknownType()
+        {
+            // The default type registry doesn't have any types in it.
+            var message = new TestAllTypes();
+            var any = Any.Pack(message);
+            Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(any));
+        }
+
+        /// <summary>
+        /// Checks that the actual JSON is the same as the expected JSON - but after replacing
+        /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
+        /// to read.
+        /// </summary>
+        private static void AssertJson(string expectedJsonWithApostrophes, string actualJson)
+        {
+            var expectedJson = expectedJsonWithApostrophes.Replace("'", "\"");
+            Assert.AreEqual(expectedJson, actualJson);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
new file mode 100644
index 0000000..c3ad851
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -0,0 +1,936 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+using Google.Protobuf.TestProtos;
+using Google.Protobuf.WellKnownTypes;
+using NUnit.Framework;
+using System;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Unit tests for JSON parsing.
+    /// </summary>
+    public class JsonParserTest
+    {
+        // Sanity smoke test
+        [Test]
+        public void AllTypesRoundtrip()
+        {
+            AssertRoundtrip(SampleMessages.CreateFullTestAllTypes());
+        }
+
+        [Test]
+        public void Maps()
+        {
+            AssertRoundtrip(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } });
+            AssertRoundtrip(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } });
+            AssertRoundtrip(new TestMap { MapBoolBool = { { false, true }, { true, false } } });
+        }
+
+        [Test]
+        [TestCase(" 1 ")]
+        [TestCase("+1")]
+        [TestCase("1,000")]
+        [TestCase("1.5")]
+        public void IntegerMapKeysAreStrict(string keyText)
+        {
+            // Test that integer parsing is strict. We assume that if this is correct for int32,
+            // it's correct for other numeric key types.
+            var json = "{ \"mapInt32Int32\": { \"" + keyText + "\" : \"1\" } }";
+            Assert.Throws<InvalidProtocolBufferException>(() => JsonParser.Default.Parse<TestMap>(json));
+        }
+
+        [Test]
+        public void OriginalFieldNameAccepted()
+        {
+            var json = "{ \"single_int32\": 10 }";
+            var expected = new TestAllTypes { SingleInt32 = 10 };
+            Assert.AreEqual(expected, TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void SourceContextRoundtrip()
+        {
+            AssertRoundtrip(new SourceContext { FileName = "foo.proto" });
+        }
+
+        [Test]
+        public void SingularWrappers_DefaultNonNullValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "",
+                BytesField = ByteString.Empty,
+                BoolField = false,
+                FloatField = 0f,
+                DoubleField = 0d,
+                Int32Field = 0,
+                Int64Field = 0,
+                Uint32Field = 0,
+                Uint64Field = 0
+            };
+            AssertRoundtrip(message);
+        }
+
+        [Test]
+        public void SingularWrappers_NonDefaultValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "x",
+                BytesField = ByteString.CopyFrom(1, 2, 3),
+                BoolField = true,
+                FloatField = 12.5f,
+                DoubleField = 12.25d,
+                Int32Field = 1,
+                Int64Field = 2,
+                Uint32Field = 3,
+                Uint64Field = 4
+            };
+            AssertRoundtrip(message);
+        }
+
+        [Test]
+        public void SingularWrappers_ExplicitNulls()
+        {
+            // When we parse the "valueField": null part, we remember it... basically, it's one case
+            // where explicit default values don't fully roundtrip.
+            var message = new TestWellKnownTypes { ValueField = Value.ForNull() };
+            var json = new JsonFormatter(new JsonFormatter.Settings(true)).Format(message);
+            var parsed = JsonParser.Default.Parse<TestWellKnownTypes>(json);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        [TestCase(typeof(Int32Value), "32", 32)]
+        [TestCase(typeof(Int64Value), "32", 32L)]
+        [TestCase(typeof(UInt32Value), "32", 32U)]
+        [TestCase(typeof(UInt64Value), "32", 32UL)]
+        [TestCase(typeof(StringValue), "\"foo\"", "foo")]
+        [TestCase(typeof(FloatValue), "1.5", 1.5f)]
+        [TestCase(typeof(DoubleValue), "1.5", 1.5d)]
+        public void Wrappers_Standalone(System.Type wrapperType, string json, object expectedValue)
+        {
+            IMessage parsed = (IMessage)Activator.CreateInstance(wrapperType);
+            IMessage expected = (IMessage)Activator.CreateInstance(wrapperType);
+            JsonParser.Default.Merge(parsed, "null");
+            Assert.AreEqual(expected, parsed);
+
+            JsonParser.Default.Merge(parsed, json);
+            expected.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.SetValue(expected, expectedValue);
+            Assert.AreEqual(expected, parsed);
+        }
+
+        [Test]
+        public void ExplicitNullValue()
+        {
+            string json = "{\"valueField\": null}";
+            var message = JsonParser.Default.Parse<TestWellKnownTypes>(json);
+            Assert.AreEqual(new TestWellKnownTypes { ValueField = Value.ForNull() }, message);
+        }
+
+        [Test]
+        public void BytesWrapper_Standalone()
+        {
+            ByteString data = ByteString.CopyFrom(1, 2, 3);
+            // Can't do this with attributes...
+            var parsed = JsonParser.Default.Parse<BytesValue>(WrapInQuotes(data.ToBase64()));
+            var expected = new BytesValue { Value = data };
+            Assert.AreEqual(expected, parsed);
+        }
+
+        [Test]
+        public void RepeatedWrappers()
+        {
+            var message = new RepeatedWellKnownTypes
+            {
+                BoolField = { true, false },
+                BytesField = { ByteString.CopyFrom(1, 2, 3), ByteString.CopyFrom(4, 5, 6), ByteString.Empty },
+                DoubleField = { 12.5, -1.5, 0d },
+                FloatField = { 123.25f, -20f, 0f },
+                Int32Field = { int.MaxValue, int.MinValue, 0 },
+                Int64Field = { long.MaxValue, long.MinValue, 0L },
+                StringField = { "First", "Second", "" },
+                Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
+                Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
+            };
+            AssertRoundtrip(message);
+        }
+
+        [Test]
+        public void RepeatedField_NullElementProhibited()
+        {
+            string json = "{ \"repeated_foreign_message\": [null] }";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void RepeatedField_NullOverallValueAllowed()
+        {
+            string json = "{ \"repeated_foreign_message\": null }";
+            Assert.AreEqual(new TestAllTypes(), TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("{ \"mapInt32Int32\": { \"10\": null }")]
+        [TestCase("{ \"mapStringString\": { \"abc\": null }")]
+        [TestCase("{ \"mapInt32ForeignMessage\": { \"10\": null }")]
+        public void MapField_NullValueProhibited(string json)
+        {
+            Assert.Throws<InvalidProtocolBufferException>(() => TestMap.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void MapField_NullOverallValueAllowed()
+        {
+            string json = "{ \"mapInt32Int32\": null }";
+            Assert.AreEqual(new TestMap(), TestMap.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void IndividualWrapperTypes()
+        {
+            Assert.AreEqual(new StringValue { Value = "foo" }, StringValue.Parser.ParseJson("\"foo\""));
+            Assert.AreEqual(new Int32Value { Value = 1 }, Int32Value.Parser.ParseJson("1"));
+            // Can parse strings directly too
+            Assert.AreEqual(new Int32Value { Value = 1 }, Int32Value.Parser.ParseJson("\"1\""));
+        }
+
+        private static void AssertRoundtrip<T>(T message) where T : IMessage<T>, new()
+        {
+            var clone = message.Clone();
+            var json = JsonFormatter.Default.Format(message);
+            var parsed = JsonParser.Default.Parse<T>(json);
+            Assert.AreEqual(clone, parsed);
+        }
+
+        [Test]
+        [TestCase("0", 0)]
+        [TestCase("-0", 0)] // Not entirely clear whether we intend to allow this...
+        [TestCase("1", 1)]
+        [TestCase("-1", -1)]
+        [TestCase("2147483647", 2147483647)]
+        [TestCase("-2147483648", -2147483648)]
+        public void StringToInt32_Valid(string jsonValue, int expectedParsedValue)
+        {
+            string json = "{ \"singleInt32\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleInt32);
+        }
+
+        [Test]
+        [TestCase("+0")]
+        [TestCase(" 1")]
+        [TestCase("1 ")]
+        [TestCase("00")]
+        [TestCase("-00")]
+        [TestCase("--1")]
+        [TestCase("+1")]
+        [TestCase("1.5")]
+        [TestCase("1e10")]
+        [TestCase("2147483648")]
+        [TestCase("-2147483649")]
+        public void StringToInt32_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleInt32\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0U)]
+        [TestCase("1", 1U)]
+        [TestCase("4294967295", 4294967295U)]
+        public void StringToUInt32_Valid(string jsonValue, uint expectedParsedValue)
+        {
+            string json = "{ \"singleUint32\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleUint32);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("-1")]
+        [TestCase("4294967296")]
+        public void StringToUInt32_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleUint32\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0L)]
+        [TestCase("1", 1L)]
+        [TestCase("-1", -1L)]
+        [TestCase("9223372036854775807", 9223372036854775807)]
+        [TestCase("-9223372036854775808", -9223372036854775808)]
+        public void StringToInt64_Valid(string jsonValue, long expectedParsedValue)
+        {
+            string json = "{ \"singleInt64\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleInt64);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("-9223372036854775809")]
+        [TestCase("9223372036854775808")]
+        public void StringToInt64_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleInt64\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0UL)]
+        [TestCase("1", 1UL)]
+        [TestCase("18446744073709551615", 18446744073709551615)]
+        public void StringToUInt64_Valid(string jsonValue, ulong expectedParsedValue)
+        {
+            string json = "{ \"singleUint64\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleUint64);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("-1")]
+        [TestCase("18446744073709551616")]
+        public void StringToUInt64_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleUint64\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0d)]
+        [TestCase("1", 1d)]
+        [TestCase("1.000000", 1d)]
+        [TestCase("1.0000000000000000000000001", 1d)] // We don't notice that we haven't preserved the exact value
+        [TestCase("-1", -1d)]
+        [TestCase("1e1", 10d)]
+        [TestCase("1e01", 10d)] // Leading decimals are allowed in exponents
+        [TestCase("1E1", 10d)] // Either case is fine
+        [TestCase("-1e1", -10d)]
+        [TestCase("1.5e1", 15d)]
+        [TestCase("-1.5e1", -15d)]
+        [TestCase("15e-1", 1.5d)]
+        [TestCase("-15e-1", -1.5d)]
+        [TestCase("1.79769e308", 1.79769e308)]
+        [TestCase("-1.79769e308", -1.79769e308)]
+        [TestCase("Infinity", double.PositiveInfinity)]
+        [TestCase("-Infinity", double.NegativeInfinity)]
+        [TestCase("NaN", double.NaN)]
+        public void StringToDouble_Valid(string jsonValue, double expectedParsedValue)
+        {
+            string json = "{ \"singleDouble\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleDouble);
+        }
+
+        [Test]
+        [TestCase("1.7977e308")]
+        [TestCase("-1.7977e308")]
+        [TestCase("1e309")]
+        [TestCase("1,0")]
+        [TestCase("1.0.0")]
+        [TestCase("+1")]
+        [TestCase("00")]
+        [TestCase("01")]
+        [TestCase("-00")]
+        [TestCase("-01")]
+        [TestCase("--1")]
+        [TestCase(" Infinity")]
+        [TestCase(" -Infinity")]
+        [TestCase("NaN ")]
+        [TestCase("Infinity ")]
+        [TestCase("-Infinity ")]
+        [TestCase(" NaN")]
+        [TestCase("INFINITY")]
+        [TestCase("nan")]
+        [TestCase("\u00BD")] // 1/2 as a single Unicode character. Just sanity checking...
+        public void StringToDouble_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleDouble\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0f)]
+        [TestCase("1", 1f)]
+        [TestCase("1.000000", 1f)]
+        [TestCase("-1", -1f)]
+        [TestCase("3.402823e38", 3.402823e38f)]
+        [TestCase("-3.402823e38", -3.402823e38f)]
+        [TestCase("1.5e1", 15f)]
+        [TestCase("15e-1", 1.5f)]
+        public void StringToFloat_Valid(string jsonValue, float expectedParsedValue)
+        {
+            string json = "{ \"singleFloat\": \"" + jsonValue + "\"}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleFloat);
+        }
+
+        [Test]
+        [TestCase("3.402824e38")]
+        [TestCase("-3.402824e38")]
+        [TestCase("1,0")]
+        [TestCase("1.0.0")]
+        [TestCase("+1")]
+        [TestCase("00")]
+        [TestCase("--1")]
+        public void StringToFloat_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleFloat\": \"" + jsonValue + "\"}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0)]
+        [TestCase("-0", 0)] // Not entirely clear whether we intend to allow this...
+        [TestCase("1", 1)]
+        [TestCase("-1", -1)]
+        [TestCase("2147483647", 2147483647)]
+        [TestCase("-2147483648", -2147483648)]
+        [TestCase("1e1", 10)]
+        [TestCase("-1e1", -10)]
+        [TestCase("10.00", 10)]
+        [TestCase("-10.00", -10)]
+        public void NumberToInt32_Valid(string jsonValue, int expectedParsedValue)
+        {
+            string json = "{ \"singleInt32\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleInt32);
+        }
+
+        [Test]
+        [TestCase("+0", typeof(InvalidJsonException))]
+        [TestCase("00", typeof(InvalidJsonException))]
+        [TestCase("-00", typeof(InvalidJsonException))]
+        [TestCase("--1", typeof(InvalidJsonException))]
+        [TestCase("+1", typeof(InvalidJsonException))]
+        [TestCase("1.5", typeof(InvalidProtocolBufferException))]
+        // Value is out of range
+        [TestCase("1e10", typeof(InvalidProtocolBufferException))]
+        [TestCase("2147483648", typeof(InvalidProtocolBufferException))]
+        [TestCase("-2147483649", typeof(InvalidProtocolBufferException))]
+        public void NumberToInt32_Invalid(string jsonValue, System.Type expectedExceptionType)
+        {
+            string json = "{ \"singleInt32\": " + jsonValue + "}";
+            Assert.Throws(expectedExceptionType, () => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0U)]
+        [TestCase("1", 1U)]
+        [TestCase("4294967295", 4294967295U)]
+        public void NumberToUInt32_Valid(string jsonValue, uint expectedParsedValue)
+        {
+            string json = "{ \"singleUint32\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleUint32);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("-1")]
+        [TestCase("4294967296")]
+        public void NumberToUInt32_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleUint32\": " + jsonValue + "}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0L)]
+        [TestCase("1", 1L)]
+        [TestCase("-1", -1L)]
+        // long.MaxValue isn't actually representable as a double. This string value is the highest
+        // representable value which isn't greater than long.MaxValue.
+        [TestCase("9223372036854774784", 9223372036854774784)]
+        [TestCase("-9223372036854775808", -9223372036854775808)]
+        public void NumberToInt64_Valid(string jsonValue, long expectedParsedValue)
+        {
+            string json = "{ \"singleInt64\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleInt64);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("9223372036854775808")]
+        // Theoretical bound would be -9223372036854775809, but when that is parsed to a double
+        // we end up with the exact value of long.MinValue due to lack of precision. The value here
+        // is the "next double down".
+        [TestCase("-9223372036854780000")]
+        public void NumberToInt64_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleInt64\": " + jsonValue + "}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0UL)]
+        [TestCase("1", 1UL)]
+        // ulong.MaxValue isn't representable as a double. This value is the largest double within
+        // the range of ulong.
+        [TestCase("18446744073709549568", 18446744073709549568UL)]
+        public void NumberToUInt64_Valid(string jsonValue, ulong expectedParsedValue)
+        {
+            string json = "{ \"singleUint64\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleUint64);
+        }
+
+        // Assume that anything non-bounds-related is covered in the Int32 case
+        [Test]
+        [TestCase("-1")]
+        [TestCase("18446744073709551616")]
+        public void NumberToUInt64_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleUint64\": " + jsonValue + "}";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0d)]
+        [TestCase("1", 1d)]
+        [TestCase("1.000000", 1d)]
+        [TestCase("1.0000000000000000000000001", 1d)] // We don't notice that we haven't preserved the exact value
+        [TestCase("-1", -1d)]
+        [TestCase("1e1", 10d)]
+        [TestCase("1e01", 10d)] // Leading decimals are allowed in exponents
+        [TestCase("1E1", 10d)] // Either case is fine
+        [TestCase("-1e1", -10d)]
+        [TestCase("1.5e1", 15d)]
+        [TestCase("-1.5e1", -15d)]
+        [TestCase("15e-1", 1.5d)]
+        [TestCase("-15e-1", -1.5d)]
+        [TestCase("1.79769e308", 1.79769e308)]
+        [TestCase("-1.79769e308", -1.79769e308)]
+        public void NumberToDouble_Valid(string jsonValue, double expectedParsedValue)
+        {
+            string json = "{ \"singleDouble\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleDouble);
+        }
+
+        [Test]
+        [TestCase("1.7977e308")]
+        [TestCase("-1.7977e308")]
+        [TestCase("1e309")]
+        [TestCase("1,0")]
+        [TestCase("1.0.0")]
+        [TestCase("+1")]
+        [TestCase("00")]
+        [TestCase("--1")]
+        [TestCase("\u00BD")] // 1/2 as a single Unicode character. Just sanity checking...
+        public void NumberToDouble_Invalid(string jsonValue)
+        {
+            string json = "{ \"singleDouble\": " + jsonValue + "}";
+            Assert.Throws<InvalidJsonException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("0", 0f)]
+        [TestCase("1", 1f)]
+        [TestCase("1.000000", 1f)]
+        [TestCase("-1", -1f)]
+        [TestCase("3.402823e38", 3.402823e38f)]
+        [TestCase("-3.402823e38", -3.402823e38f)]
+        [TestCase("1.5e1", 15f)]
+        [TestCase("15e-1", 1.5f)]
+        public void NumberToFloat_Valid(string jsonValue, float expectedParsedValue)
+        {
+            string json = "{ \"singleFloat\": " + jsonValue + "}";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(expectedParsedValue, parsed.SingleFloat);
+        }
+
+        [Test]
+        [TestCase("3.402824e38", typeof(InvalidProtocolBufferException))]
+        [TestCase("-3.402824e38", typeof(InvalidProtocolBufferException))]
+        [TestCase("1,0", typeof(InvalidJsonException))]
+        [TestCase("1.0.0", typeof(InvalidJsonException))]
+        [TestCase("+1", typeof(InvalidJsonException))]
+        [TestCase("00", typeof(InvalidJsonException))]
+        [TestCase("--1", typeof(InvalidJsonException))]
+        public void NumberToFloat_Invalid(string jsonValue, System.Type expectedExceptionType)
+        {
+            string json = "{ \"singleFloat\": " + jsonValue + "}";
+            Assert.Throws(expectedExceptionType, () => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        // The simplest way of testing that the value has parsed correctly is to reformat it,
+        // as we trust the formatting. In many cases that will give the same result as the input,
+        // so in those cases we accept an expectedFormatted value of null. Sometimes the results
+        // will be different though, due to a different number of digits being provided.
+        [Test]
+        // Z offset
+        [TestCase("2015-10-09T14:46:23.123456789Z", null)]
+        [TestCase("2015-10-09T14:46:23.123456Z", null)]
+        [TestCase("2015-10-09T14:46:23.123Z", null)]
+        [TestCase("2015-10-09T14:46:23Z", null)]
+        [TestCase("2015-10-09T14:46:23.123456000Z", "2015-10-09T14:46:23.123456Z")]
+        [TestCase("2015-10-09T14:46:23.1234560Z", "2015-10-09T14:46:23.123456Z")]
+        [TestCase("2015-10-09T14:46:23.123000000Z", "2015-10-09T14:46:23.123Z")]
+        [TestCase("2015-10-09T14:46:23.1230Z", "2015-10-09T14:46:23.123Z")]
+        [TestCase("2015-10-09T14:46:23.00Z", "2015-10-09T14:46:23Z")]
+
+        // +00:00 offset
+        [TestCase("2015-10-09T14:46:23.123456789+00:00", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T14:46:23.123456+00:00", "2015-10-09T14:46:23.123456Z")]
+        [TestCase("2015-10-09T14:46:23.123+00:00", "2015-10-09T14:46:23.123Z")]
+        [TestCase("2015-10-09T14:46:23+00:00", "2015-10-09T14:46:23Z")]
+        [TestCase("2015-10-09T14:46:23.123456000+00:00", "2015-10-09T14:46:23.123456Z")]
+        [TestCase("2015-10-09T14:46:23.1234560+00:00", "2015-10-09T14:46:23.123456Z")]
+        [TestCase("2015-10-09T14:46:23.123000000+00:00", "2015-10-09T14:46:23.123Z")]
+        [TestCase("2015-10-09T14:46:23.1230+00:00", "2015-10-09T14:46:23.123Z")]
+        [TestCase("2015-10-09T14:46:23.00+00:00", "2015-10-09T14:46:23Z")]
+
+        // Other offsets (assume by now that the subsecond handling is okay)
+        [TestCase("2015-10-09T15:46:23.123456789+01:00", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T13:46:23.123456789-01:00", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T15:16:23.123456789+00:30", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T14:16:23.123456789-00:30", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T16:31:23.123456789+01:45", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-09T13:01:23.123456789-01:45", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-10T08:46:23.123456789+18:00", "2015-10-09T14:46:23.123456789Z")]
+        [TestCase("2015-10-08T20:46:23.123456789-18:00", "2015-10-09T14:46:23.123456789Z")]
+
+        // Leap years and min/max
+        [TestCase("2016-02-29T14:46:23.123456789Z", null)]
+        [TestCase("2000-02-29T14:46:23.123456789Z", null)]
+        [TestCase("0001-01-01T00:00:00Z", null)]
+        [TestCase("9999-12-31T23:59:59.999999999Z", null)]
+        public void Timestamp_Valid(string jsonValue, string expectedFormatted)
+        {
+            expectedFormatted = expectedFormatted ?? jsonValue;
+            string json = WrapInQuotes(jsonValue);
+            var parsed = Timestamp.Parser.ParseJson(json);
+            Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
+        }
+
+        [Test]
+        [TestCase("2015-10-09 14:46:23.123456789Z", Description = "No T between date and time")]
+        [TestCase("2015/10/09T14:46:23.123456789Z", Description = "Wrong date separators")]
+        [TestCase("2015-10-09T14.46.23.123456789Z", Description = "Wrong time separators")]
+        [TestCase("2015-10-09T14:46:23,123456789Z", Description = "Wrong fractional second separators (valid ISO-8601 though)")]
+        [TestCase(" 2015-10-09T14:46:23.123456789Z", Description = "Whitespace at start")]
+        [TestCase("2015-10-09T14:46:23.123456789Z ", Description = "Whitespace at end")]
+        [TestCase("2015-10-09T14:46:23.1234567890", Description = "Too many digits")]
+        [TestCase("2015-10-09T14:46:23.123456789", Description = "No offset")]
+        [TestCase("2015-13-09T14:46:23.123456789Z", Description = "Invalid month")]
+        [TestCase("2015-10-32T14:46:23.123456789Z", Description = "Invalid day")]
+        [TestCase("2015-10-09T24:00:00.000000000Z", Description = "Invalid hour (valid ISO-8601 though)")]
+        [TestCase("2015-10-09T14:60:23.123456789Z", Description = "Invalid minutes")]
+        [TestCase("2015-10-09T14:46:60.123456789Z", Description = "Invalid seconds")]
+        [TestCase("2015-10-09T14:46:23.123456789+18:01", Description = "Offset too large (positive)")]
+        [TestCase("2015-10-09T14:46:23.123456789-18:01", Description = "Offset too large (negative)")]
+        [TestCase("2015-10-09T14:46:23.123456789-00:00", Description = "Local offset (-00:00) makes no sense here")]
+        [TestCase("0001-01-01T00:00:00+00:01", Description = "Value before earliest when offset applied")]
+        [TestCase("9999-12-31T23:59:59.999999999-00:01", Description = "Value after latest when offset applied")]
+        [TestCase("2100-02-29T14:46:23.123456789Z", Description = "Feb 29th on a non-leap-year")]
+        public void Timestamp_Invalid(string jsonValue)
+        {
+            string json = WrapInQuotes(jsonValue);
+            Assert.Throws<InvalidProtocolBufferException>(() => Timestamp.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void StructValue_Null()
+        {
+            Assert.AreEqual(new Value { NullValue = 0 }, Value.Parser.ParseJson("null"));
+        }
+
+        [Test]
+        public void StructValue_String()
+        {
+            Assert.AreEqual(new Value { StringValue = "hi" }, Value.Parser.ParseJson("\"hi\""));
+        }
+
+        [Test]
+        public void StructValue_Bool()
+        {
+            Assert.AreEqual(new Value { BoolValue = true }, Value.Parser.ParseJson("true"));
+            Assert.AreEqual(new Value { BoolValue = false }, Value.Parser.ParseJson("false"));
+        }
+
+        [Test]
+        public void StructValue_List()
+        {
+            Assert.AreEqual(Value.ForList(Value.ForNumber(1), Value.ForString("x")), Value.Parser.ParseJson("[1, \"x\"]"));
+        }
+
+        [Test]
+        public void ParseListValue()
+        {
+            Assert.AreEqual(new ListValue { Values = { Value.ForNumber(1), Value.ForString("x") } }, ListValue.Parser.ParseJson("[1, \"x\"]"));
+        }
+
+        [Test]
+        public void StructValue_Struct()
+        {
+            Assert.AreEqual(
+                Value.ForStruct(new Struct { Fields = { { "x", Value.ForNumber(1) }, { "y", Value.ForString("z") } } }),
+                Value.Parser.ParseJson("{ \"x\": 1, \"y\": \"z\" }"));
+        }
+
+        [Test]
+        public void ParseStruct()
+        {
+            Assert.AreEqual(new Struct { Fields = { { "x", Value.ForNumber(1) }, { "y", Value.ForString("z") } } },
+                Struct.Parser.ParseJson("{ \"x\": 1, \"y\": \"z\" }"));
+        }
+
+        // TODO for duration parsing: upper and lower bounds.
+        // +/- 315576000000 seconds
+
+        [Test]
+        [TestCase("1.123456789s", null)]
+        [TestCase("1.123456s", null)]
+        [TestCase("1.123s", null)]
+        [TestCase("1.12300s", "1.123s")]
+        [TestCase("1.12345s", "1.123450s")]
+        [TestCase("1s", null)]
+        [TestCase("-1.123456789s", null)]
+        [TestCase("-1.123456s", null)]
+        [TestCase("-1.123s", null)]
+        [TestCase("-1s", null)]
+        [TestCase("0.123s", null)]
+        [TestCase("-0.123s", null)]
+        [TestCase("123456.123s", null)]
+        [TestCase("-123456.123s", null)]
+        // Upper and lower bounds
+        [TestCase("315576000000s", null)]
+        [TestCase("-315576000000s", null)]
+        public void Duration_Valid(string jsonValue, string expectedFormatted)
+        {
+            expectedFormatted = expectedFormatted ?? jsonValue;
+            string json = WrapInQuotes(jsonValue);
+            var parsed = Duration.Parser.ParseJson(json);
+            Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
+        }
+
+        // The simplest way of testing that the value has parsed correctly is to reformat it,
+        // as we trust the formatting. In many cases that will give the same result as the input,
+        // so in those cases we accept an expectedFormatted value of null. Sometimes the results
+        // will be different though, due to a different number of digits being provided.
+        [Test]
+        [TestCase("1.1234567890s", Description = "Too many digits")]
+        [TestCase("1.123456789", Description = "No suffix")]
+        [TestCase("1.123456789ss", Description = "Too much suffix")]
+        [TestCase("1.123456789S", Description = "Upper case suffix")]
+        [TestCase("+1.123456789s", Description = "Leading +")]
+        [TestCase(".123456789s", Description = "No integer before the fraction")]
+        [TestCase("1,123456789s", Description = "Comma as decimal separator")]
+        [TestCase("1x1.123456789s", Description = "Non-digit in integer part")]
+        [TestCase("1.1x3456789s", Description = "Non-digit in fractional part")]
+        [TestCase(" 1.123456789s", Description = "Whitespace before fraction")]
+        [TestCase("1.123456789s ", Description = "Whitespace after value")]
+        [TestCase("01.123456789s", Description = "Leading zero (positive)")]
+        [TestCase("-01.123456789s", Description = "Leading zero (negative)")]
+        [TestCase("--0.123456789s", Description = "Double minus sign")]
+        // Violate upper/lower bounds in various ways
+        [TestCase("315576000001s", Description = "Integer part too large")]
+        [TestCase("3155760000000s", Description = "Integer part too long (positive)")]
+        [TestCase("-3155760000000s", Description = "Integer part too long (negative)")]
+        public void Duration_Invalid(string jsonValue)
+        {
+            string json = WrapInQuotes(jsonValue);
+            Assert.Throws<InvalidProtocolBufferException>(() => Duration.Parser.ParseJson(json));
+        }
+
+        // Not as many tests for field masks as I'd like; more to be added when we have more
+        // detailed specifications.
+
+        [Test]
+        [TestCase("")]
+        [TestCase("foo", "foo")]
+        [TestCase("foo,bar", "foo", "bar")]
+        [TestCase("foo.bar", "foo.bar")]
+        [TestCase("fooBar", "foo_bar")]
+        [TestCase("fooBar.bazQux", "foo_bar.baz_qux")]
+        public void FieldMask_Valid(string jsonValue, params string[] expectedPaths)
+        {
+            string json = WrapInQuotes(jsonValue);
+            var parsed = FieldMask.Parser.ParseJson(json);
+            CollectionAssert.AreEqual(expectedPaths, parsed.Paths);
+        }
+
+        [Test]
+        [TestCase("foo_bar")]
+        public void FieldMask_Invalid(string jsonValue)
+        {
+            string json = WrapInQuotes(jsonValue);
+            Assert.Throws<InvalidProtocolBufferException>(() => FieldMask.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void Any_RegularMessage()
+        {
+            var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
+            var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } };
+            var original = Any.Pack(message);
+            var json = formatter.Format(original); // This is tested in JsonFormatterTest
+            var parser = new JsonParser(new JsonParser.Settings(10, registry));
+            Assert.AreEqual(original, parser.Parse<Any>(json));
+            string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest.TestAllTypes\" }";
+            Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson));
+        }
+
+        [Test]
+        public void Any_CustomPrefix()
+        {
+            var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
+            var message = new TestAllTypes { SingleInt32 = 10 };
+            var original = Any.Pack(message, "custom.prefix/middle-part");
+            var parser = new JsonParser(new JsonParser.Settings(10, registry));
+            string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest.TestAllTypes\", \"singleInt32\": 10 }";
+            Assert.AreEqual(original, parser.Parse<Any>(json));
+        }
+
+        [Test]
+        public void Any_UnknownType()
+        {
+            string json = "{ \"@type\": \"type.googleapis.com/bogus\" }";
+            Assert.Throws<InvalidOperationException>(() => Any.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void Any_NoTypeUrl()
+        {
+            string json = "{ \"foo\": \"bar\" }";
+            Assert.Throws<InvalidProtocolBufferException>(() => Any.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void Any_WellKnownType()
+        {
+            var registry = TypeRegistry.FromMessages(Timestamp.Descriptor);
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry));
+            var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp();
+            var original = Any.Pack(timestamp);
+            var json = formatter.Format(original); // This is tested in JsonFormatterTest
+            var parser = new JsonParser(new JsonParser.Settings(10, registry));
+            Assert.AreEqual(original, parser.Parse<Any>(json));
+            string valueFirstJson = "{ \"value\": \"1673-06-19T12:34:56Z\", \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\" }";
+            Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson));
+        }
+
+        [Test]
+        public void Any_Nested()
+        {
+            var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor);
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry));
+            var parser = new JsonParser(new JsonParser.Settings(10, registry));
+            var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 };
+            var nestedMessage = Any.Pack(doubleNestedMessage);
+            var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) };
+            var json = formatter.Format(message);
+            // Use the descriptor-based parser just for a change.
+            Assert.AreEqual(message, parser.Parse(json, TestWellKnownTypes.Descriptor));
+        }
+
+        [Test]
+        public void DataAfterObject()
+        {
+            string json = "{} 10";
+            Assert.Throws<InvalidJsonException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        /// <summary>
+        /// JSON equivalent to <see cref="CodedInputStreamTest.MaliciousRecursion"/>
+        /// </summary>
+        [Test]
+        public void MaliciousRecursion()
+        {
+            string data64 = CodedInputStreamTest.MakeRecursiveMessage(64).ToString();
+            string data65 = CodedInputStreamTest.MakeRecursiveMessage(65).ToString();
+
+            var parser64 = new JsonParser(new JsonParser.Settings(64));
+            CodedInputStreamTest.AssertMessageDepth(parser64.Parse<TestRecursiveMessage>(data64), 64);
+            Assert.Throws<InvalidProtocolBufferException>(() => parser64.Parse<TestRecursiveMessage>(data65));
+
+            var parser63 = new JsonParser(new JsonParser.Settings(63));
+            Assert.Throws<InvalidProtocolBufferException>(() => parser63.Parse<TestRecursiveMessage>(data64));
+        }
+
+        [Test]
+        [TestCase("AQI")]
+        [TestCase("_-==")]
+        public void Bytes_InvalidBase64(string badBase64)
+        {
+            string json = "{ \"singleBytes\": \"" + badBase64 + "\" }";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        [TestCase("\"FOREIGN_BAR\"", ForeignEnum.ForeignBar)]
+        [TestCase("5", ForeignEnum.ForeignBar)]
+        [TestCase("100", (ForeignEnum)100)]
+        public void EnumValid(string value, ForeignEnum expectedValue)
+        {
+            string json = "{ \"singleForeignEnum\": " + value + " }";
+            var parsed = TestAllTypes.Parser.ParseJson(json);
+            Assert.AreEqual(new TestAllTypes { SingleForeignEnum = expectedValue }, parsed);
+        }
+
+        [Test]
+        [TestCase("\"NOT_A_VALID_VALUE\"")]
+        [TestCase("5.5")]
+        public void Enum_Invalid(string value)
+        {
+            string json = "{ \"singleForeignEnum\": " + value + " }";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
+        public void OneofDuplicate_Invalid()
+        {
+            string json = "{ \"oneofString\": \"x\", \"oneofUint32\": 10 }";
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+        }
+
+        /// <summary>
+        /// Various tests use strings which have quotes round them for parsing or as the result
+        /// of formatting, but without those quotes being specified in the tests (for the sake of readability).
+        /// This method simply returns the input, wrapped in double quotes.
+        /// </summary>
+        internal static string WrapInQuotes(string text)
+        {
+            return '"' + text + '"';
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
new file mode 100644
index 0000000..527ab33
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
@@ -0,0 +1,408 @@
+#region Copyright notice and license
+// 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.
+#endregion
+using NUnit.Framework;
+using System;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    public class JsonTokenizerTest
+    {
+        [Test]
+        public void EmptyObjectValue()
+        {
+            AssertTokens("{}", JsonToken.StartObject, JsonToken.EndObject);
+        }
+
+        [Test]
+        public void EmptyArrayValue()
+        {
+            AssertTokens("[]", JsonToken.StartArray, JsonToken.EndArray);
+        }
+
+        [Test]
+        [TestCase("foo", "foo")]
+        [TestCase("tab\\t", "tab\t")]
+        [TestCase("line\\nfeed", "line\nfeed")]
+        [TestCase("carriage\\rreturn", "carriage\rreturn")]
+        [TestCase("back\\bspace", "back\bspace")]
+        [TestCase("form\\ffeed", "form\ffeed")]
+        [TestCase("escaped\\/slash", "escaped/slash")]
+        [TestCase("escaped\\\\backslash", "escaped\\backslash")]
+        [TestCase("escaped\\\"quote", "escaped\"quote")]
+        [TestCase("foo {}[] bar", "foo {}[] bar")]
+        [TestCase("foo\\u09aFbar", "foo\u09afbar")] // Digits, upper hex, lower hex
+        [TestCase("ab\ud800\udc00cd", "ab\ud800\udc00cd")]
+        [TestCase("ab\\ud800\\udc00cd", "ab\ud800\udc00cd")]
+        public void StringValue(string json, string expectedValue)
+        {
+            AssertTokensNoReplacement("\"" + json + "\"", JsonToken.Value(expectedValue));
+        }
+
+        // Valid surrogate pairs, with mixed escaping. These test cases can't be expressed
+        // using TestCase as they have no valid UTF-8 representation.
+        // It's unclear exactly how we should handle a mixture of escaped or not: that can't
+        // come from UTF-8 text, but could come from a .NET string. For the moment,
+        // treat it as valid in the obvious way.
+        [Test]
+        public void MixedSurrogatePairs()
+        {
+            string expected = "\ud800\udc00";
+            AssertTokens("'\\ud800\udc00'", JsonToken.Value(expected));
+            AssertTokens("'\ud800\\udc00'", JsonToken.Value(expected));
+        }
+
+        [Test]
+        public void ObjectDepth()
+        {
+            string json = "{ \"foo\": { \"x\": 1, \"y\": [ 0 ] } }";
+            var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json));
+            // If we had more tests like this, I'd introduce a helper method... but for one test, it's not worth it.
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.StartObject, tokenizer.Next());
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.Name("foo"), tokenizer.Next());
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.StartObject, tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.Name("x"), tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.Value(1), tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.Name("y"), tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.StartArray, tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth); // Depth hasn't changed in array
+            Assert.AreEqual(JsonToken.Value(0), tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.EndArray, tokenizer.Next());
+            Assert.AreEqual(2, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.EndObject, tokenizer.Next());
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.EndObject, tokenizer.Next());
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+            Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next());
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+        }
+
+        [Test]
+        public void ObjectDepth_WithPushBack()
+        {
+            string json = "{}";
+            var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json));
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+            var token = tokenizer.Next();
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+            // When we push back a "start object", we should effectively be back to the previous depth.
+            tokenizer.PushBack(token);
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+            // Read the same token again, and get back to depth 1
+            token = tokenizer.Next();
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+
+            // Now the same in reverse, with EndObject
+            token = tokenizer.Next();
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+            tokenizer.PushBack(token);
+            Assert.AreEqual(1, tokenizer.ObjectDepth);
+            tokenizer.Next();
+            Assert.AreEqual(0, tokenizer.ObjectDepth);
+        }
+
+        [Test]
+        [TestCase("embedded tab\t")]
+        [TestCase("embedded CR\r")]
+        [TestCase("embedded LF\n")]
+        [TestCase("embedded bell\u0007")]
+        [TestCase("bad escape\\a")]
+        [TestCase("incomplete escape\\")]
+        [TestCase("incomplete Unicode escape\\u000")]
+        [TestCase("invalid Unicode escape\\u000H")]
+        // Surrogate pair handling, both in raw .NET strings and escaped. We only need
+        // to detect this in strings, as non-ASCII characters anywhere other than in strings
+        // will already lead to parsing errors.
+        [TestCase("\\ud800")]
+        [TestCase("\\udc00")]
+        [TestCase("\\ud800x")]
+        [TestCase("\\udc00x")]
+        [TestCase("\\udc00\\ud800y")]
+        public void InvalidStringValue(string json)
+        {
+            AssertThrowsAfter("\"" + json + "\"");
+        }
+
+        // Tests for invalid strings that can't be expressed in attributes,
+        // as the constants can't be expressed as UTF-8 strings.
+        [Test]
+        public void InvalidSurrogatePairs()
+        {
+            AssertThrowsAfter("\"\ud800x\"");
+            AssertThrowsAfter("\"\udc00y\"");
+            AssertThrowsAfter("\"\udc00\ud800y\"");
+        }
+
+        [Test]
+        [TestCase("0", 0)]
+        [TestCase("-0", 0)] // We don't distinguish between positive and negative 0
+        [TestCase("1", 1)]
+        [TestCase("-1", -1)]
+        // From here on, assume leading sign is okay...
+        [TestCase("1.125", 1.125)]
+        [TestCase("1.0", 1)]
+        [TestCase("1e5", 100000)]
+        [TestCase("1e000000", 1)] // Weird, but not prohibited by the spec
+        [TestCase("1E5", 100000)]
+        [TestCase("1e+5", 100000)]
+        [TestCase("1E-5", 0.00001)]
+        [TestCase("123E-2", 1.23)]
+        [TestCase("123.45E3", 123450)]
+        [TestCase("   1   ", 1)]
+        public void NumberValue(string json, double expectedValue)
+        {
+            AssertTokens(json, JsonToken.Value(expectedValue));
+        }
+
+        [Test]
+        [TestCase("00")]
+        [TestCase(".5")]
+        [TestCase("1.")]
+        [TestCase("1e")]
+        [TestCase("1e-")]
+        [TestCase("--")]
+        [TestCase("--1")]
+        [TestCase("-1.7977e308")]
+        [TestCase("1.7977e308")]
+        public void InvalidNumberValue(string json)
+        {
+            AssertThrowsAfter(json);
+        }
+
+        [Test]
+        [TestCase("nul")]
+        [TestCase("nothing")]
+        [TestCase("truth")]
+        [TestCase("fALSEhood")]
+        public void InvalidLiterals(string json)
+        {
+            AssertThrowsAfter(json);
+        }
+
+        [Test]
+        public void NullValue()
+        {
+            AssertTokens("null", JsonToken.Null);
+        }
+
+        [Test]
+        public void TrueValue()
+        {
+            AssertTokens("true", JsonToken.True);
+        }
+
+        [Test]
+        public void FalseValue()
+        {
+            AssertTokens("false", JsonToken.False);
+        }
+
+        [Test]
+        public void SimpleObject()
+        {
+            AssertTokens("{'x': 'y'}",
+                JsonToken.StartObject, JsonToken.Name("x"), JsonToken.Value("y"), JsonToken.EndObject);
+        }
+        
+        [Test]
+        [TestCase("[10, 20", 3)]
+        [TestCase("[10,", 2)]
+        [TestCase("[10:20]", 2)]
+        [TestCase("[", 1)]
+        [TestCase("[,", 1)]
+        [TestCase("{", 1)]
+        [TestCase("{,", 1)]
+        [TestCase("{[", 1)]
+        [TestCase("{{", 1)]
+        [TestCase("{0", 1)]
+        [TestCase("{null", 1)]
+        [TestCase("{false", 1)]
+        [TestCase("{true", 1)]
+        [TestCase("}", 0)]
+        [TestCase("]", 0)]
+        [TestCase(",", 0)]
+        [TestCase("'foo' 'bar'", 1)]
+        [TestCase(":", 0)]
+        [TestCase("'foo", 0)] // Incomplete string
+        [TestCase("{ 'foo' }", 2)]
+        [TestCase("{ x:1", 1)] // Property names must be quoted
+        [TestCase("{]", 1)]
+        [TestCase("[}", 1)]
+        [TestCase("[1,", 2)]
+        [TestCase("{'x':0]", 3)]
+        [TestCase("{ 'foo': }", 2)]
+        [TestCase("{ 'foo':'bar', }", 3)]
+        public void InvalidStructure(string json, int expectedValidTokens)
+        {
+            // Note: we don't test that the earlier tokens are exactly as expected,
+            // partly because that's hard to parameterize.
+            var reader = new StringReader(json.Replace('\'', '"'));
+            var tokenizer = JsonTokenizer.FromTextReader(reader);
+            for (int i = 0; i < expectedValidTokens; i++)
+            {
+                Assert.IsNotNull(tokenizer.Next());
+            }
+            Assert.Throws<InvalidJsonException>(() => tokenizer.Next());
+        }
+
+        [Test]
+        public void ArrayMixedType()
+        {
+            AssertTokens("[1, 'foo', null, false, true, [2], {'x':'y' }]",
+                JsonToken.StartArray,
+                JsonToken.Value(1),
+                JsonToken.Value("foo"),
+                JsonToken.Null,
+                JsonToken.False,
+                JsonToken.True,
+                JsonToken.StartArray,
+                JsonToken.Value(2),
+                JsonToken.EndArray,
+                JsonToken.StartObject,
+                JsonToken.Name("x"),
+                JsonToken.Value("y"),
+                JsonToken.EndObject,
+                JsonToken.EndArray);
+        }
+
+        [Test]
+        public void ObjectMixedType()
+        {
+            AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, 
+                           'f': [2], 'g': {'x':'y' }}",
+                JsonToken.StartObject,
+                JsonToken.Name("a"),
+                JsonToken.Value(1),
+                JsonToken.Name("b"),
+                JsonToken.Value("bar"),
+                JsonToken.Name("c"),
+                JsonToken.Null,
+                JsonToken.Name("d"),
+                JsonToken.False,
+                JsonToken.Name("e"),
+                JsonToken.True,
+                JsonToken.Name("f"),
+                JsonToken.StartArray,
+                JsonToken.Value(2),
+                JsonToken.EndArray,
+                JsonToken.Name("g"),
+                JsonToken.StartObject,
+                JsonToken.Name("x"),
+                JsonToken.Value("y"),
+                JsonToken.EndObject,
+                JsonToken.EndObject);
+        }
+
+        [Test]
+        public void NextAfterEndDocumentThrows()
+        {
+            var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null"));
+            Assert.AreEqual(JsonToken.Null, tokenizer.Next());
+            Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next());
+            Assert.Throws<InvalidOperationException>(() => tokenizer.Next());
+        }
+
+        [Test]
+        public void CanPushBackEndDocument()
+        {
+            var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null"));
+            Assert.AreEqual(JsonToken.Null, tokenizer.Next());
+            Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next());
+            tokenizer.PushBack(JsonToken.EndDocument);
+            Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next());
+            Assert.Throws<InvalidOperationException>(() => tokenizer.Next());
+        }
+       
+        /// <summary>
+        /// Asserts that the specified JSON is tokenized into the given sequence of tokens.
+        /// All apostrophes are first converted to double quotes, allowing any tests
+        /// that don't need to check actual apostrophe handling to use apostrophes in the JSON, avoiding
+        /// messy string literal escaping. The "end document" token is not specified in the list of 
+        /// expected tokens, but is implicit.
+        /// </summary>
+        private static void AssertTokens(string json, params JsonToken[] expectedTokens)
+        {
+            AssertTokensNoReplacement(json.Replace('\'', '"'), expectedTokens);
+        }
+
+        /// <summary>
+        /// Asserts that the specified JSON is tokenized into the given sequence of tokens.
+        /// Unlike <see cref="AssertTokens(string, JsonToken[])"/>, this does not perform any character
+        /// replacement on the specified JSON, and should be used when the text contains apostrophes which
+        /// are expected to be used *as* apostrophes. The "end document" token is not specified in the list of 
+        /// expected tokens, but is implicit.
+        /// </summary>
+        private static void AssertTokensNoReplacement(string json, params JsonToken[] expectedTokens)
+        {
+            var reader = new StringReader(json);
+            var tokenizer = JsonTokenizer.FromTextReader(reader);
+            for (int i = 0; i < expectedTokens.Length; i++)
+            {
+                var actualToken = tokenizer.Next();
+                if (actualToken == JsonToken.EndDocument)
+                {
+                    Assert.Fail("Expected {0} but reached end of token stream", expectedTokens[i]);
+                }
+                Assert.AreEqual(expectedTokens[i], actualToken);
+            }
+            var finalToken = tokenizer.Next();
+            if (finalToken != JsonToken.EndDocument)
+            {
+                Assert.Fail("Expected token stream to be exhausted; received {0}", finalToken);
+            }
+        }
+
+        private static void AssertThrowsAfter(string json, params JsonToken[] expectedTokens)
+        {
+            var reader = new StringReader(json);
+            var tokenizer = JsonTokenizer.FromTextReader(reader);
+            for (int i = 0; i < expectedTokens.Length; i++)
+            {
+                var actualToken = tokenizer.Next();
+                if (actualToken == JsonToken.EndDocument)
+                {
+                    Assert.Fail("Expected {0} but reached end of document", expectedTokens[i]);
+                }
+                Assert.AreEqual(expectedTokens[i], actualToken);
+            }
+            Assert.Throws<InvalidJsonException>(() => tokenizer.Next());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml
new file mode 100644
index 0000000..6712a11
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml
@@ -0,0 +1,6 @@
+<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+>
+    <Deployment.Parts>
+    </Deployment.Parts>
+</Deployment>
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f50940e
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Google.Protobuf.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Google.Protobuf.Test")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
new file mode 100644
index 0000000..52d5a67
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
@@ -0,0 +1,259 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System.Linq;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the
+    /// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...)
+    /// </summary>
+    public class DescriptorsTest
+    {
+        [Test]
+        public void FileDescriptor()
+        {
+            FileDescriptor file = UnittestProto3Reflection.Descriptor;
+
+            Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name);
+            Assert.AreEqual("protobuf_unittest", file.Package);
+
+            Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
+            Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name);
+
+            // unittest.proto doesn't have any public imports, but unittest_import.proto does.
+            Assert.AreEqual(0, file.PublicDependencies.Count);
+            Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count);
+            Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]);
+
+            Assert.AreEqual(1, file.Dependencies.Count);
+            Assert.AreEqual(UnittestImportProto3Reflection.Descriptor, file.Dependencies[0]);
+
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            Assert.AreSame(typeof(TestAllTypes), messageType.ClrType);
+            Assert.AreSame(TestAllTypes.Parser, messageType.Parser);
+            Assert.AreEqual(messageType, file.MessageTypes[0]);
+            Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
+            Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
+            Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes"));
+            for (int i = 0; i < file.MessageTypes.Count; i++)
+            {
+                Assert.AreEqual(i, file.MessageTypes[i].Index);
+            }
+
+            Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
+            Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
+            Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum"));
+            Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count);
+            Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name);
+            for (int i = 0; i < file.EnumTypes.Count; i++)
+            {
+                Assert.AreEqual(i, file.EnumTypes[i].Index);
+            }
+
+            Assert.AreEqual(10, file.SerializedData[0]);
+        }
+
+        [Test]
+        public void MessageDescriptor()
+        {
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
+
+            Assert.AreEqual("TestAllTypes", messageType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName);
+            Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File);
+            Assert.IsNull(messageType.ContainingType);
+            Assert.IsNull(messageType.Proto.Options);
+
+            Assert.AreEqual("TestAllTypes", messageType.Name);
+
+            Assert.AreEqual("NestedMessage", nestedType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName);
+            Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
+            Assert.AreEqual(messageType, nestedType.ContainingType);
+
+            FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0];
+            Assert.AreEqual("single_int32", field.Name);
+            Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32"));
+            Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
+            Assert.AreEqual(field, messageType.FindFieldByNumber(1));
+            Assert.Null(messageType.FindFieldByNumber(571283));
+            var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder();
+            for (int i = 0; i < fieldsInDeclarationOrder.Count; i++)
+            {
+                Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index);
+            }
+
+            Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
+            Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
+            Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType"));
+            for (int i = 0; i < messageType.NestedTypes.Count; i++)
+            {
+                Assert.AreEqual(i, messageType.NestedTypes[i].Index);
+            }
+
+            Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum"));
+            Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType"));
+            for (int i = 0; i < messageType.EnumTypes.Count; i++)
+            {
+                Assert.AreEqual(i, messageType.EnumTypes[i].Index);
+            }
+        }
+
+        [Test]
+        public void FieldDescriptor()
+        {
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32");
+            FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum");
+            FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message");
+
+            Assert.AreEqual("single_int32", primitiveField.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32",
+                            primitiveField.FullName);
+            Assert.AreEqual(1, primitiveField.FieldNumber);
+            Assert.AreEqual(messageType, primitiveField.ContainingType);
+            Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File);
+            Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
+            Assert.IsNull(primitiveField.Proto.Options);
+            
+            Assert.AreEqual("single_nested_enum", enumField.Name);
+            Assert.AreEqual(FieldType.Enum, enumField.FieldType);
+            // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType);
+
+            Assert.AreEqual("single_foreign_message", messageField.Name);
+            Assert.AreEqual(FieldType.Message, messageField.FieldType);
+            Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
+        }
+
+        [Test]
+        public void FieldDescriptorLabel()
+        {
+            FieldDescriptor singleField =
+                TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32");
+            FieldDescriptor repeatedField =
+                TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
+
+            Assert.IsFalse(singleField.IsRepeated);
+            Assert.IsTrue(repeatedField.IsRepeated);
+        }
+
+        [Test]
+        public void EnumDescriptor()
+        {
+            // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor
+            EnumDescriptor enumType = UnittestProto3Reflection.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum");
+            EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
+
+            Assert.AreEqual("ForeignEnum", enumType.Name);
+            Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName);
+            Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File);
+            Assert.Null(enumType.ContainingType);
+            Assert.Null(enumType.Proto.Options);
+
+            Assert.AreEqual("NestedEnum", nestedType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
+                            nestedType.FullName);
+            Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
+            Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
+
+            EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
+            Assert.AreEqual(value, enumType.Values[1]);
+            Assert.AreEqual("FOREIGN_FOO", value.Name);
+            Assert.AreEqual(4, value.Number);
+            Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number);
+            Assert.AreEqual(value, enumType.FindValueByNumber(4));
+            Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
+            for (int i = 0; i < enumType.Values.Count; i++)
+            {
+                Assert.AreEqual(i, enumType.Values[i].Index);
+            }
+        }
+
+        [Test]
+        public void OneofDescriptor()
+        {
+            OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
+            Assert.AreEqual("oneof_field", descriptor.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName);
+
+            var expectedFields = new[] {
+                TestAllTypes.OneofBytesFieldNumber,
+                TestAllTypes.OneofNestedMessageFieldNumber,
+                TestAllTypes.OneofStringFieldNumber,
+                TestAllTypes.OneofUint32FieldNumber }
+                .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
+                .ToList();
+            foreach (var field in expectedFields)
+            {
+                Assert.AreSame(descriptor, field.ContainingOneof);
+            }
+
+            CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
+        }
+
+        [Test]
+        public void MapEntryMessageDescriptor()
+        {
+            var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0];
+            Assert.IsNull(descriptor.Parser);
+            Assert.IsNull(descriptor.ClrType);
+            Assert.IsNull(descriptor.Fields[1].Accessor);
+        }
+
+        // From TestFieldOrdering:
+        // string my_string = 11;
+        // int64 my_int = 1;
+        // float my_float = 101;
+        // NestedMessage single_nested_message = 200;
+        [Test]
+        public void FieldListOrderings()
+        { 
+            var fields = TestFieldOrderings.Descriptor.Fields;
+            Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber));
+            Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber));
+        }
+
+
+        [Test]
+        public void DescriptorProtoFileDescriptor()
+        {
+            var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor;
+            Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
new file mode 100644
index 0000000..a488af3
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
@@ -0,0 +1,218 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Reflection
+{
+    public class FieldAccessTest
+    {
+        [Test]
+        public void GetValue()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
+
+            // Just one example for repeated fields - they're all just returning the list
+            var list = (IList) fields[TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
+            Assert.AreEqual(message.RepeatedInt32, list);
+            Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...
+
+            // Just a single map field, for the same reason
+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
+            fields = TestMap.Descriptor.Fields;
+            var dictionary = (IDictionary) fields[TestMap.MapStringStringFieldNumber].Accessor.GetValue(mapMessage);
+            Assert.AreEqual(mapMessage.MapStringString, dictionary);
+            Assert.AreEqual("value1", dictionary["key1"]);
+        }
+
+        [Test]
+        public void Clear()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            fields[TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
+
+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
+            {
+                SingleBool = false,
+                SingleInt32 = 0,
+                SingleString = "",
+                SingleBytes = ByteString.Empty,
+                SingleForeignEnum = 0,
+                SingleForeignMessage = null,
+            };
+            expected.RepeatedDouble.Clear();
+
+            Assert.AreEqual(expected, message);
+
+            // Separately, maps.
+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
+            fields = TestMap.Descriptor.Fields;
+            fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage);
+            Assert.AreEqual(0, mapMessage.MapStringString.Count);
+        }
+
+        [Test]
+        public void SetValue_SingleFields()
+        {
+            // Just a sample (primitives, messages, enums, strings, byte strings)
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
+            fields[TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
+            fields[TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
+            fields[TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
+            fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo);
+            fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
+            fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
+
+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
+            {
+                SingleBool = false,
+                SingleInt32 = 500,
+                SingleString = "It's a string",
+                SingleBytes = ByteString.CopyFrom(99, 98, 97),
+                SingleForeignEnum = ForeignEnum.ForeignFoo,
+                SingleForeignMessage = new ForeignMessage { C = 12345 },
+                SingleDouble = 20150701.5
+            };
+
+            Assert.AreEqual(expected, message);
+        }
+
+        [Test]
+        public void SetValue_SingleFields_WrongType()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
+        }
+
+        [Test]
+        public void SetValue_MapFields()
+        {
+            IMessage message = new TestMap();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
+        }
+
+        [Test]
+        public void SetValue_RepeatedFields()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
+        }
+
+        [Test]
+        public void GetValue_IncorrectType()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
+        }
+
+        [Test]
+        public void Oneof()
+        {
+            var message = new TestAllTypes();
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.AreEqual(1, descriptor.Oneofs.Count);
+            var oneof = descriptor.Oneofs[0];
+            Assert.AreEqual("oneof_field", oneof.Name);
+            Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            message.OneofString = "foo";
+            Assert.AreSame(descriptor.Fields[TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            message.OneofUint32 = 10;
+            Assert.AreSame(descriptor.Fields[TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            oneof.Accessor.Clear(message);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
+        public void FieldDescriptor_ByName()
+        {
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.AreSame(
+                descriptor.Fields[TestAllTypes.SingleBoolFieldNumber],
+                descriptor.Fields["single_bool"]);
+        }
+
+        [Test]
+        public void FieldDescriptor_NotFound()
+        {
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
+            Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
+        }        
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs
new file mode 100644
index 0000000..5be7ca2
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs
@@ -0,0 +1,94 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.TestProtos;
+using Google.Protobuf.WellKnownTypes;
+using NUnit.Framework;
+
+namespace Google.Protobuf.Reflection
+{
+    public class TypeRegistryTest
+    {
+        // Most of our tests use messages. Simple test that we really can use files...
+        [Test]
+        public void CreateWithFileDescriptor()
+        {
+            var registry = TypeRegistry.FromFiles(DurationReflection.Descriptor, StructReflection.Descriptor);
+            AssertDescriptorPresent(registry, Duration.Descriptor);
+            AssertDescriptorPresent(registry, ListValue.Descriptor);
+            AssertDescriptorAbsent(registry, Timestamp.Descriptor);
+        }
+
+        [Test]
+        public void TypesFromSameFile()
+        {
+            // Just for kicks, let's start with a nested type
+            var registry = TypeRegistry.FromMessages(TestAllTypes.Types.NestedMessage.Descriptor);
+            // Top-level...
+            AssertDescriptorPresent(registry, TestFieldOrderings.Descriptor);
+            // ... and nested (not the same as the original NestedMessage!)
+            AssertDescriptorPresent(registry, TestFieldOrderings.Types.NestedMessage.Descriptor);
+        }
+
+        [Test]
+        public void DependenciesAreIncluded()
+        {
+            var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
+            // Direct dependencies
+            AssertDescriptorPresent(registry, ImportMessage.Descriptor);
+            // Public dependencies
+            AssertDescriptorPresent(registry, PublicImportMessage.Descriptor);
+        }
+
+        [Test]
+        public void DuplicateFiles()
+        {
+            // Duplicates via dependencies and simply via repetition
+            var registry = TypeRegistry.FromFiles(
+                UnittestProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor,
+                TimestampReflection.Descriptor, TimestampReflection.Descriptor);
+            AssertDescriptorPresent(registry, TestAllTypes.Descriptor);
+            AssertDescriptorPresent(registry, ImportMessage.Descriptor);
+            AssertDescriptorPresent(registry, Timestamp.Descriptor);
+        }
+
+        private static void AssertDescriptorPresent(TypeRegistry registry, MessageDescriptor descriptor)
+        {
+            Assert.AreSame(descriptor, registry.Find(descriptor.FullName));
+        }
+
+        private static void AssertDescriptorAbsent(TypeRegistry registry, MessageDescriptor descriptor)
+        {
+            Assert.IsNull(registry.Find(descriptor.FullName));
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleEnum.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleEnum.cs
new file mode 100644
index 0000000..77447af
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleEnum.cs
@@ -0,0 +1,42 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+    
+namespace Google.Protobuf
+{
+    // Just a sample enum with positive and negative values to be used in tests.
+    internal enum SampleEnum
+    {
+        NegativeValue = -2,
+        None = 0,
+        PositiveValue = 3
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleMessages.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleMessages.cs
new file mode 100644
index 0000000..ffa4e2a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/SampleMessages.cs
@@ -0,0 +1,99 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using Google.Protobuf.TestProtos;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Helper methods to create sample instances of types generated from unit test messages.
+    /// </summary>
+    public class SampleMessages
+    {
+        /// <summary>
+        /// Creates a new sample TestAllTypes message with all fields populated.
+        /// The "oneof" field is populated with the string property (OneofString).
+        /// </summary>
+        public static TestAllTypes CreateFullTestAllTypes()
+        {
+            return new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.ForeignBar,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.ImportBaz,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = UInt32.MaxValue,
+                SingleUint64 = UInt64.MaxValue,
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { UInt32.MaxValue, 23 },
+                RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedForeignEnum = { ForeignEnum.ForeignFoo, ForeignEnum.ForeignBar },
+                RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
+                RepeatedImportEnum = { ImportEnum.ImportBaz, ImportEnum.Unspecified },
+                RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, Int64.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
+                RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue },
+                RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue },
+                OneofString = "Oneof string"
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestCornerCases.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestCornerCases.cs
new file mode 100644
index 0000000..fd75b19
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestCornerCases.cs
@@ -0,0 +1,62 @@
+#region Copyright notice and license
+// 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.
+#endregion
+    
+using UnitTest.Issues.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class TestCornerCases
+    {
+        [Test]
+        public void TestRoundTripNegativeEnums()
+        {
+            NegativeEnumMessage msg = new NegativeEnumMessage
+            {
+                Value = NegativeEnum.MinusOne,
+                Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
+                PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
+            };
+
+            Assert.AreEqual(58, msg.CalculateSize());
+
+            byte[] bytes = new byte[58];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+
+            msg.WriteTo(output);
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            NegativeEnumMessage copy = NegativeEnumMessage.Parser.ParseFrom(bytes);
+            Assert.AreEqual(msg, copy);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs
new file mode 100644
index 0000000..5663a69
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs
@@ -0,0 +1,45 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+#endregion
+
+namespace Google.Protobuf.TestProtos
+{
+    /// <summary>
+    /// A message with custom diagnostics (to test that they work).
+    /// </summary>
+    public partial class ForeignMessage : ICustomDiagnosticMessage
+    {
+        public string ToDiagnosticString()
+        {
+            return $"{{ \"c\": {C}, \"@cInHex\": \"{C:x}\" }}";
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
new file mode 100644
index 0000000..3ba4a2b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
@@ -0,0 +1,1471 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/map_unittest_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/map_unittest_proto3.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class MapUnittestProto3Reflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/map_unittest_proto3.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static MapUnittestProto3Reflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Cilnb29nbGUvcHJvdG9idWYvbWFwX3VuaXR0ZXN0X3Byb3RvMy5wcm90bxIR",
+            "cHJvdG9idWZfdW5pdHRlc3QaJWdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9w",
+            "cm90bzMucHJvdG8ilhIKB1Rlc3RNYXASRgoPbWFwX2ludDMyX2ludDMyGAEg",
+            "AygLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkludDMy",
+            "RW50cnkSRgoPbWFwX2ludDY0X2ludDY0GAIgAygLMi0ucHJvdG9idWZfdW5p",
+            "dHRlc3QuVGVzdE1hcC5NYXBJbnQ2NEludDY0RW50cnkSSgoRbWFwX3VpbnQz",
+            "Ml91aW50MzIYAyADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
+            "cFVpbnQzMlVpbnQzMkVudHJ5EkoKEW1hcF91aW50NjRfdWludDY0GAQgAygL",
+            "Mi8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBVaW50NjRVaW50NjRF",
+            "bnRyeRJKChFtYXBfc2ludDMyX3NpbnQzMhgFIAMoCzIvLnByb3RvYnVmX3Vu",
+            "aXR0ZXN0LlRlc3RNYXAuTWFwU2ludDMyU2ludDMyRW50cnkSSgoRbWFwX3Np",
+            "bnQ2NF9zaW50NjQYBiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFw",
+            "Lk1hcFNpbnQ2NFNpbnQ2NEVudHJ5Ek4KE21hcF9maXhlZDMyX2ZpeGVkMzIY",
+            "ByADKAsyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcEZpeGVkMzJG",
+            "aXhlZDMyRW50cnkSTgoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBgIIAMoCzIxLnBy",
+            "b3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy",
+            "eRJSChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYCSADKAsyMy5wcm90b2J1Zl91",
+            "bml0dGVzdC5UZXN0TWFwLk1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRJSChVt",
+            "YXBfc2ZpeGVkNjRfc2ZpeGVkNjQYCiADKAsyMy5wcm90b2J1Zl91bml0dGVz",
+            "dC5UZXN0TWFwLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJGCg9tYXBfaW50",
+            "MzJfZmxvYXQYCyADKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
+            "cEludDMyRmxvYXRFbnRyeRJIChBtYXBfaW50MzJfZG91YmxlGAwgAygLMi4u",
+            "cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkRvdWJsZUVudHJ5",
+            "EkIKDW1hcF9ib29sX2Jvb2wYDSADKAsyKy5wcm90b2J1Zl91bml0dGVzdC5U",
+            "ZXN0TWFwLk1hcEJvb2xCb29sRW50cnkSSgoRbWFwX3N0cmluZ19zdHJpbmcY",
+            "DiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcFN0cmluZ1N0",
+            "cmluZ0VudHJ5EkYKD21hcF9pbnQzMl9ieXRlcxgPIAMoCzItLnByb3RvYnVm",
+            "X3VuaXR0ZXN0LlRlc3RNYXAuTWFwSW50MzJCeXRlc0VudHJ5EkQKDm1hcF9p",
+            "bnQzMl9lbnVtGBAgAygLMiwucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5N",
+            "YXBJbnQzMkVudW1FbnRyeRJZChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdl",
+            "GBEgAygLMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkZv",
+            "cmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl",
+            "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu",
+            "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu",
+            "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4",
+            "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs",
+            "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB",
+            "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50",
+            "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl",
+            "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC",
+            "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF",
+            "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL",
+            "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0",
+            "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB",
+            "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY",
+            "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF",
+            "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl",
+            "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n",
+            "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo0ChJNYXBJ",
+            "bnQzMkJ5dGVzRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgMOgI4",
+            "ARpPChFNYXBJbnQzMkVudW1FbnRyeRILCgNrZXkYASABKAUSKQoFdmFsdWUY",
+            "AiABKA4yGi5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtOgI4ARpgChtNYXBJ",
+            "bnQzMkZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5GAEgASgFEjAKBXZhbHVl",
+            "GAIgASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2U6AjgB",
+            "IkEKEVRlc3RNYXBTdWJtZXNzYWdlEiwKCHRlc3RfbWFwGAEgASgLMhoucHJv",
+            "dG9idWZfdW5pdHRlc3QuVGVzdE1hcCK8AQoOVGVzdE1lc3NhZ2VNYXASUQoR",
+            "bWFwX2ludDMyX21lc3NhZ2UYASADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5U",
+            "ZXN0TWVzc2FnZU1hcC5NYXBJbnQzMk1lc3NhZ2VFbnRyeRpXChRNYXBJbnQz",
+            "Mk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSLgoFdmFsdWUYAiABKAsyHy5w",
+            "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXM6AjgBIuMBCg9UZXN0U2Ft",
+            "ZVR5cGVNYXASOgoEbWFwMRgBIAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+            "c3RTYW1lVHlwZU1hcC5NYXAxRW50cnkSOgoEbWFwMhgCIAMoCzIsLnByb3Rv",
+            "YnVmX3VuaXR0ZXN0LlRlc3RTYW1lVHlwZU1hcC5NYXAyRW50cnkaKwoJTWFw",
+            "MUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaKwoJTWFw",
+            "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi5BAKDFRl",
+            "c3RBcmVuYU1hcBJLCg9tYXBfaW50MzJfaW50MzIYASADKAsyMi5wcm90b2J1",
+            "Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EksK",
+            "D21hcF9pbnQ2NF9pbnQ2NBgCIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+            "c3RBcmVuYU1hcC5NYXBJbnQ2NEludDY0RW50cnkSTwoRbWFwX3VpbnQzMl91",
+            "aW50MzIYAyADKAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAu",
+            "TWFwVWludDMyVWludDMyRW50cnkSTwoRbWFwX3VpbnQ2NF91aW50NjQYBCAD",
+            "KAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwVWludDY0",
+            "VWludDY0RW50cnkSTwoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNC5wcm90",
+            "b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDMyU2ludDMyRW50",
+            "cnkSTwoRbWFwX3NpbnQ2NF9zaW50NjQYBiADKAsyNC5wcm90b2J1Zl91bml0",
+            "dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSUwoTbWFw",
+            "X2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzI2LnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+            "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElMKE21hcF9maXhl",
+            "ZDY0X2ZpeGVkNjQYCCADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJl",
+            "bmFNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJXChVtYXBfc2ZpeGVkMzJf",
+            "c2ZpeGVkMzIYCSADKAsyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFN",
+            "YXAuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5ElcKFW1hcF9zZml4ZWQ2NF9z",
+            "Zml4ZWQ2NBgKIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1h",
+            "cC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSSwoPbWFwX2ludDMyX2Zsb2F0",
+            "GAsgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcElu",
+            "dDMyRmxvYXRFbnRyeRJNChBtYXBfaW50MzJfZG91YmxlGAwgAygLMjMucHJv",
+            "dG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcEludDMyRG91YmxlRW50",
+            "cnkSRwoNbWFwX2Jvb2xfYm9vbBgNIAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0",
+            "LlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkkKDm1hcF9pbnQzMl9l",
+            "bnVtGA4gAygLMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1h",
+            "cEludDMyRW51bUVudHJ5El4KGW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UY",
+            "DyADKAsyOy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50",
+            "MzJGb3JlaWduTWVzc2FnZUVudHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRIL",
+            "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50",
+            "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h",
+            "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo",
+            "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K",
+            "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr",
+            "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2",
+            "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw",
+            "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB",
+            "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG",
+            "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50",
+            "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4",
+            "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ",
+            "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh",
+            "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB",
+            "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL",
+            "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGk8KEU1hcEludDMyRW51",
+            "bUVudHJ5EgsKA2tleRgBIAEoBRIpCgV2YWx1ZRgCIAEoDjIaLnByb3RvYnVm",
+            "X3VuaXR0ZXN0Lk1hcEVudW06AjgBGmAKG01hcEludDMyRm9yZWlnbk1lc3Nh",
+            "Z2VFbnRyeRILCgNrZXkYASABKAUSMAoFdmFsdWUYAiABKAsyIS5wcm90b2J1",
+            "Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZToCOAEi5AEKH01lc3NhZ2VDb250",
+            "YWluaW5nRW51bUNhbGxlZFR5cGUSSgoEdHlwZRgBIAMoCzI8LnByb3RvYnVm",
+            "X3VuaXR0ZXN0Lk1lc3NhZ2VDb250YWluaW5nRW51bUNhbGxlZFR5cGUuVHlw",
+            "ZUVudHJ5Gl8KCVR5cGVFbnRyeRILCgNrZXkYASABKAUSQQoFdmFsdWUYAiAB",
+            "KAsyMi5wcm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ0VudW1D",
+            "YWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9PEAAinQEKH01lc3Nh",
+            "Z2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTAoFZW50cnkYASADKAsyPS5w",
+            "cm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ01hcENhbGxlZEVu",
+            "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF",
+            "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS",
+            "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv",
+            "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), global::Google.Protobuf.TestProtos.TestMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), global::Google.Protobuf.TestProtos.TestMapSubmessage.Parser, new[]{ "TestMap" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), global::Google.Protobuf.TestProtos.TestMessageMap.Parser, new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), global::Google.Protobuf.TestProtos.TestSameTypeMap.Parser, new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), global::Google.Protobuf.TestProtos.TestArenaMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser, new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedClrTypeInfo[] { null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Parser, new[]{ "Entry" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, })
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum MapEnum {
+    [pbr::OriginalName("MAP_ENUM_FOO")] Foo = 0,
+    [pbr::OriginalName("MAP_ENUM_BAR")] Bar = 1,
+    [pbr::OriginalName("MAP_ENUM_BAZ")] Baz = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  Tests maps.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMap : pb::IMessage<TestMap> {
+    private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
+    public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMap(TestMap other) : this() {
+      mapInt32Int32_ = other.mapInt32Int32_.Clone();
+      mapInt64Int64_ = other.mapInt64Int64_.Clone();
+      mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
+      mapUint64Uint64_ = other.mapUint64Uint64_.Clone();
+      mapSint32Sint32_ = other.mapSint32Sint32_.Clone();
+      mapSint64Sint64_ = other.mapSint64Sint64_.Clone();
+      mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone();
+      mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone();
+      mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone();
+      mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone();
+      mapInt32Float_ = other.mapInt32Float_.Clone();
+      mapInt32Double_ = other.mapInt32Double_.Clone();
+      mapBoolBool_ = other.mapBoolBool_.Clone();
+      mapStringString_ = other.mapStringString_.Clone();
+      mapInt32Bytes_ = other.mapInt32Bytes_.Clone();
+      mapInt32Enum_ = other.mapInt32Enum_.Clone();
+      mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+    }
+
+    public TestMap Clone() {
+      return new TestMap(this);
+    }
+
+    /// <summary>Field number for the "map_int32_int32" field.</summary>
+    public const int MapInt32Int32FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapInt32Int32 {
+      get { return mapInt32Int32_; }
+    }
+
+    /// <summary>Field number for the "map_int64_int64" field.</summary>
+    public const int MapInt64Int64FieldNumber = 2;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18);
+    private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapInt64Int64 {
+      get { return mapInt64Int64_; }
+    }
+
+    /// <summary>Field number for the "map_uint32_uint32" field.</summary>
+    public const int MapUint32Uint32FieldNumber = 3;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26);
+    private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapUint32Uint32 {
+      get { return mapUint32Uint32_; }
+    }
+
+    /// <summary>Field number for the "map_uint64_uint64" field.</summary>
+    public const int MapUint64Uint64FieldNumber = 4;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34);
+    private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapUint64Uint64 {
+      get { return mapUint64Uint64_; }
+    }
+
+    /// <summary>Field number for the "map_sint32_sint32" field.</summary>
+    public const int MapSint32Sint32FieldNumber = 5;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42);
+    private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSint32Sint32 {
+      get { return mapSint32Sint32_; }
+    }
+
+    /// <summary>Field number for the "map_sint64_sint64" field.</summary>
+    public const int MapSint64Sint64FieldNumber = 6;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50);
+    private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSint64Sint64 {
+      get { return mapSint64Sint64_; }
+    }
+
+    /// <summary>Field number for the "map_fixed32_fixed32" field.</summary>
+    public const int MapFixed32Fixed32FieldNumber = 7;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58);
+    private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapFixed32Fixed32 {
+      get { return mapFixed32Fixed32_; }
+    }
+
+    /// <summary>Field number for the "map_fixed64_fixed64" field.</summary>
+    public const int MapFixed64Fixed64FieldNumber = 8;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66);
+    private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
+      get { return mapFixed64Fixed64_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed32_sfixed32" field.</summary>
+    public const int MapSfixed32Sfixed32FieldNumber = 9;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74);
+    private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSfixed32Sfixed32 {
+      get { return mapSfixed32Sfixed32_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed64_sfixed64" field.</summary>
+    public const int MapSfixed64Sfixed64FieldNumber = 10;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82);
+    private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSfixed64Sfixed64 {
+      get { return mapSfixed64Sfixed64_; }
+    }
+
+    /// <summary>Field number for the "map_int32_float" field.</summary>
+    public const int MapInt32FloatFieldNumber = 11;
+    private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec
+        = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90);
+    private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
+    public pbc::MapField<int, float> MapInt32Float {
+      get { return mapInt32Float_; }
+    }
+
+    /// <summary>Field number for the "map_int32_double" field.</summary>
+    public const int MapInt32DoubleFieldNumber = 12;
+    private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec
+        = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98);
+    private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
+    public pbc::MapField<int, double> MapInt32Double {
+      get { return mapInt32Double_; }
+    }
+
+    /// <summary>Field number for the "map_bool_bool" field.</summary>
+    public const int MapBoolBoolFieldNumber = 13;
+    private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec
+        = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106);
+    private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
+    public pbc::MapField<bool, bool> MapBoolBool {
+      get { return mapBoolBool_; }
+    }
+
+    /// <summary>Field number for the "map_string_string" field.</summary>
+    public const int MapStringStringFieldNumber = 14;
+    private static readonly pbc::MapField<string, string>.Codec _map_mapStringString_codec
+        = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 114);
+    private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
+    public pbc::MapField<string, string> MapStringString {
+      get { return mapStringString_; }
+    }
+
+    /// <summary>Field number for the "map_int32_bytes" field.</summary>
+    public const int MapInt32BytesFieldNumber = 15;
+    private static readonly pbc::MapField<int, pb::ByteString>.Codec _map_mapInt32Bytes_codec
+        = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForBytes(18), 122);
+    private readonly pbc::MapField<int, pb::ByteString> mapInt32Bytes_ = new pbc::MapField<int, pb::ByteString>();
+    public pbc::MapField<int, pb::ByteString> MapInt32Bytes {
+      get { return mapInt32Bytes_; }
+    }
+
+    /// <summary>Field number for the "map_int32_enum" field.</summary>
+    public const int MapInt32EnumFieldNumber = 16;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec _map_mapInt32Enum_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 130);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
+      get { return mapInt32Enum_; }
+    }
+
+    /// <summary>Field number for the "map_int32_foreign_message" field.</summary>
+    public const int MapInt32ForeignMessageFieldNumber = 17;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec _map_mapInt32ForeignMessage_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 138);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
+      get { return mapInt32ForeignMessage_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMap);
+    }
+
+    public bool Equals(TestMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false;
+      if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false;
+      if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false;
+      if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false;
+      if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false;
+      if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false;
+      if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false;
+      if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false;
+      if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false;
+      if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false;
+      if (!MapInt32Float.Equals(other.MapInt32Float)) return false;
+      if (!MapInt32Double.Equals(other.MapInt32Double)) return false;
+      if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
+      if (!MapStringString.Equals(other.MapStringString)) return false;
+      if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false;
+      if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
+      if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Int32.GetHashCode();
+      hash ^= MapInt64Int64.GetHashCode();
+      hash ^= MapUint32Uint32.GetHashCode();
+      hash ^= MapUint64Uint64.GetHashCode();
+      hash ^= MapSint32Sint32.GetHashCode();
+      hash ^= MapSint64Sint64.GetHashCode();
+      hash ^= MapFixed32Fixed32.GetHashCode();
+      hash ^= MapFixed64Fixed64.GetHashCode();
+      hash ^= MapSfixed32Sfixed32.GetHashCode();
+      hash ^= MapSfixed64Sfixed64.GetHashCode();
+      hash ^= MapInt32Float.GetHashCode();
+      hash ^= MapInt32Double.GetHashCode();
+      hash ^= MapBoolBool.GetHashCode();
+      hash ^= MapStringString.GetHashCode();
+      hash ^= MapInt32Bytes.GetHashCode();
+      hash ^= MapInt32Enum.GetHashCode();
+      hash ^= MapInt32ForeignMessage.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(output, _map_mapStringString_codec);
+      mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec);
+      mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
+      size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec);
+      size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec);
+      size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec);
+      size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec);
+      size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec);
+      size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec);
+      size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec);
+      size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec);
+      size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec);
+      size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec);
+      size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec);
+      size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
+      size += mapStringString_.CalculateSize(_map_mapStringString_codec);
+      size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec);
+      size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
+      size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Int32_.Add(other.mapInt32Int32_);
+      mapInt64Int64_.Add(other.mapInt64Int64_);
+      mapUint32Uint32_.Add(other.mapUint32Uint32_);
+      mapUint64Uint64_.Add(other.mapUint64Uint64_);
+      mapSint32Sint32_.Add(other.mapSint32Sint32_);
+      mapSint64Sint64_.Add(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.Add(other.mapInt32Float_);
+      mapInt32Double_.Add(other.mapInt32Double_);
+      mapBoolBool_.Add(other.mapBoolBool_);
+      mapStringString_.Add(other.mapStringString_);
+      mapInt32Bytes_.Add(other.mapInt32Bytes_);
+      mapInt32Enum_.Add(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec);
+            break;
+          }
+          case 122: {
+            mapInt32Bytes_.AddEntriesFrom(input, _map_mapInt32Bytes_codec);
+            break;
+          }
+          case 130: {
+            mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 138: {
+            mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
+    private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
+    public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMapSubmessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMapSubmessage(TestMapSubmessage other) : this() {
+      TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
+    }
+
+    public TestMapSubmessage Clone() {
+      return new TestMapSubmessage(this);
+    }
+
+    /// <summary>Field number for the "test_map" field.</summary>
+    public const int TestMapFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMap testMap_;
+    public global::Google.Protobuf.TestProtos.TestMap TestMap {
+      get { return testMap_; }
+      set {
+        testMap_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMapSubmessage);
+    }
+
+    public bool Equals(TestMapSubmessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(TestMap, other.TestMap)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (testMap_ != null) hash ^= TestMap.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (testMap_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(TestMap);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (testMap_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMapSubmessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.testMap_ != null) {
+        if (testMap_ == null) {
+          testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+        }
+        TestMap.MergeFrom(other.TestMap);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (testMap_ == null) {
+              testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+            }
+            input.ReadMessage(testMap_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
+    private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
+    public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMessageMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMessageMap(TestMessageMap other) : this() {
+      mapInt32Message_ = other.mapInt32Message_.Clone();
+    }
+
+    public TestMessageMap Clone() {
+      return new TestMessageMap(this);
+    }
+
+    /// <summary>Field number for the "map_int32_message" field.</summary>
+    public const int MapInt32MessageFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>.Codec _map_mapInt32Message_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.TestAllTypes.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> mapInt32Message_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> MapInt32Message {
+      get { return mapInt32Message_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMessageMap);
+    }
+
+    public bool Equals(TestMessageMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Message.Equals(other.MapInt32Message)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Message.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestMessageMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Message_.Add(other.mapInt32Message_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Two map fields share the same entry default instance.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
+    private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
+    public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestSameTypeMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestSameTypeMap(TestSameTypeMap other) : this() {
+      map1_ = other.map1_.Clone();
+      map2_ = other.map2_.Clone();
+    }
+
+    public TestSameTypeMap Clone() {
+      return new TestSameTypeMap(this);
+    }
+
+    /// <summary>Field number for the "map1" field.</summary>
+    public const int Map1FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_map1_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> map1_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Map1 {
+      get { return map1_; }
+    }
+
+    /// <summary>Field number for the "map2" field.</summary>
+    public const int Map2FieldNumber = 2;
+    private static readonly pbc::MapField<int, int>.Codec _map_map2_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 18);
+    private readonly pbc::MapField<int, int> map2_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Map2 {
+      get { return map2_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestSameTypeMap);
+    }
+
+    public bool Equals(TestSameTypeMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Map1.Equals(other.Map1)) return false;
+      if (!Map2.Equals(other.Map2)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Map1.GetHashCode();
+      hash ^= Map2.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      map1_.WriteTo(output, _map_map1_codec);
+      map2_.WriteTo(output, _map_map2_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += map1_.CalculateSize(_map_map1_codec);
+      size += map2_.CalculateSize(_map_map2_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestSameTypeMap other) {
+      if (other == null) {
+        return;
+      }
+      map1_.Add(other.map1_);
+      map2_.Add(other.map2_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            map1_.AddEntriesFrom(input, _map_map1_codec);
+            break;
+          }
+          case 18: {
+            map2_.AddEntriesFrom(input, _map_map2_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
+    private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
+    public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestArenaMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestArenaMap(TestArenaMap other) : this() {
+      mapInt32Int32_ = other.mapInt32Int32_.Clone();
+      mapInt64Int64_ = other.mapInt64Int64_.Clone();
+      mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
+      mapUint64Uint64_ = other.mapUint64Uint64_.Clone();
+      mapSint32Sint32_ = other.mapSint32Sint32_.Clone();
+      mapSint64Sint64_ = other.mapSint64Sint64_.Clone();
+      mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone();
+      mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone();
+      mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone();
+      mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone();
+      mapInt32Float_ = other.mapInt32Float_.Clone();
+      mapInt32Double_ = other.mapInt32Double_.Clone();
+      mapBoolBool_ = other.mapBoolBool_.Clone();
+      mapInt32Enum_ = other.mapInt32Enum_.Clone();
+      mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+    }
+
+    public TestArenaMap Clone() {
+      return new TestArenaMap(this);
+    }
+
+    /// <summary>Field number for the "map_int32_int32" field.</summary>
+    public const int MapInt32Int32FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapInt32Int32 {
+      get { return mapInt32Int32_; }
+    }
+
+    /// <summary>Field number for the "map_int64_int64" field.</summary>
+    public const int MapInt64Int64FieldNumber = 2;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18);
+    private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapInt64Int64 {
+      get { return mapInt64Int64_; }
+    }
+
+    /// <summary>Field number for the "map_uint32_uint32" field.</summary>
+    public const int MapUint32Uint32FieldNumber = 3;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26);
+    private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapUint32Uint32 {
+      get { return mapUint32Uint32_; }
+    }
+
+    /// <summary>Field number for the "map_uint64_uint64" field.</summary>
+    public const int MapUint64Uint64FieldNumber = 4;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34);
+    private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapUint64Uint64 {
+      get { return mapUint64Uint64_; }
+    }
+
+    /// <summary>Field number for the "map_sint32_sint32" field.</summary>
+    public const int MapSint32Sint32FieldNumber = 5;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42);
+    private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSint32Sint32 {
+      get { return mapSint32Sint32_; }
+    }
+
+    /// <summary>Field number for the "map_sint64_sint64" field.</summary>
+    public const int MapSint64Sint64FieldNumber = 6;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50);
+    private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSint64Sint64 {
+      get { return mapSint64Sint64_; }
+    }
+
+    /// <summary>Field number for the "map_fixed32_fixed32" field.</summary>
+    public const int MapFixed32Fixed32FieldNumber = 7;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58);
+    private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapFixed32Fixed32 {
+      get { return mapFixed32Fixed32_; }
+    }
+
+    /// <summary>Field number for the "map_fixed64_fixed64" field.</summary>
+    public const int MapFixed64Fixed64FieldNumber = 8;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66);
+    private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
+      get { return mapFixed64Fixed64_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed32_sfixed32" field.</summary>
+    public const int MapSfixed32Sfixed32FieldNumber = 9;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74);
+    private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSfixed32Sfixed32 {
+      get { return mapSfixed32Sfixed32_; }
+    }
+
+    /// <summary>Field number for the "map_sfixed64_sfixed64" field.</summary>
+    public const int MapSfixed64Sfixed64FieldNumber = 10;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82);
+    private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSfixed64Sfixed64 {
+      get { return mapSfixed64Sfixed64_; }
+    }
+
+    /// <summary>Field number for the "map_int32_float" field.</summary>
+    public const int MapInt32FloatFieldNumber = 11;
+    private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec
+        = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90);
+    private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
+    public pbc::MapField<int, float> MapInt32Float {
+      get { return mapInt32Float_; }
+    }
+
+    /// <summary>Field number for the "map_int32_double" field.</summary>
+    public const int MapInt32DoubleFieldNumber = 12;
+    private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec
+        = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98);
+    private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
+    public pbc::MapField<int, double> MapInt32Double {
+      get { return mapInt32Double_; }
+    }
+
+    /// <summary>Field number for the "map_bool_bool" field.</summary>
+    public const int MapBoolBoolFieldNumber = 13;
+    private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec
+        = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106);
+    private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
+    public pbc::MapField<bool, bool> MapBoolBool {
+      get { return mapBoolBool_; }
+    }
+
+    /// <summary>Field number for the "map_int32_enum" field.</summary>
+    public const int MapInt32EnumFieldNumber = 14;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec _map_mapInt32Enum_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 114);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
+      get { return mapInt32Enum_; }
+    }
+
+    /// <summary>Field number for the "map_int32_foreign_message" field.</summary>
+    public const int MapInt32ForeignMessageFieldNumber = 15;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec _map_mapInt32ForeignMessage_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 122);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
+      get { return mapInt32ForeignMessage_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestArenaMap);
+    }
+
+    public bool Equals(TestArenaMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false;
+      if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false;
+      if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false;
+      if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false;
+      if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false;
+      if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false;
+      if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false;
+      if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false;
+      if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false;
+      if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false;
+      if (!MapInt32Float.Equals(other.MapInt32Float)) return false;
+      if (!MapInt32Double.Equals(other.MapInt32Double)) return false;
+      if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
+      if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
+      if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Int32.GetHashCode();
+      hash ^= MapInt64Int64.GetHashCode();
+      hash ^= MapUint32Uint32.GetHashCode();
+      hash ^= MapUint64Uint64.GetHashCode();
+      hash ^= MapSint32Sint32.GetHashCode();
+      hash ^= MapSint64Sint64.GetHashCode();
+      hash ^= MapFixed32Fixed32.GetHashCode();
+      hash ^= MapFixed64Fixed64.GetHashCode();
+      hash ^= MapSfixed32Sfixed32.GetHashCode();
+      hash ^= MapSfixed64Sfixed64.GetHashCode();
+      hash ^= MapInt32Float.GetHashCode();
+      hash ^= MapInt32Double.GetHashCode();
+      hash ^= MapBoolBool.GetHashCode();
+      hash ^= MapInt32Enum.GetHashCode();
+      hash ^= MapInt32ForeignMessage.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
+      mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
+      size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec);
+      size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec);
+      size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec);
+      size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec);
+      size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec);
+      size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec);
+      size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec);
+      size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec);
+      size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec);
+      size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec);
+      size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec);
+      size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
+      size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
+      size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestArenaMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Int32_.Add(other.mapInt32Int32_);
+      mapInt64Int64_.Add(other.mapInt64Int64_);
+      mapUint32Uint32_.Add(other.mapUint32Uint32_);
+      mapUint64Uint64_.Add(other.mapUint64Uint64_);
+      mapSint32Sint32_.Add(other.mapSint32Sint32_);
+      mapSint64Sint64_.Add(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.Add(other.mapInt32Float_);
+      mapInt32Double_.Add(other.mapInt32Double_);
+      mapBoolBool_.Add(other.mapBoolBool_);
+      mapInt32Enum_.Add(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 122: {
+            mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Previously, message containing enum called Type cannot be used as value of
+  ///  map field.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
+    private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
+    public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MessageContainingEnumCalledType() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
+      type_ = other.type_.Clone();
+    }
+
+    public MessageContainingEnumCalledType Clone() {
+      return new MessageContainingEnumCalledType(this);
+    }
+
+    /// <summary>Field number for the "type" field.</summary>
+    public const int TypeFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>.Codec _map_type_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> type_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> Type {
+      get { return type_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MessageContainingEnumCalledType);
+    }
+
+    public bool Equals(MessageContainingEnumCalledType other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Type.Equals(other.Type)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Type.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      type_.WriteTo(output, _map_type_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += type_.CalculateSize(_map_type_codec);
+      return size;
+    }
+
+    public void MergeFrom(MessageContainingEnumCalledType other) {
+      if (other == null) {
+        return;
+      }
+      type_.Add(other.type_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            type_.AddEntriesFrom(input, _map_type_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the MessageContainingEnumCalledType message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum Type {
+        [pbr::OriginalName("TYPE_FOO")] Foo = 0,
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Previously, message cannot contain map field called "entry".
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
+    private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
+    public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MessageContainingMapCalledEntry() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
+      entry_ = other.entry_.Clone();
+    }
+
+    public MessageContainingMapCalledEntry Clone() {
+      return new MessageContainingMapCalledEntry(this);
+    }
+
+    /// <summary>Field number for the "entry" field.</summary>
+    public const int EntryFieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_entry_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> entry_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Entry {
+      get { return entry_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MessageContainingMapCalledEntry);
+    }
+
+    public bool Equals(MessageContainingMapCalledEntry other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Entry.Equals(other.Entry)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Entry.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      entry_.WriteTo(output, _map_entry_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += entry_.CalculateSize(_map_entry_codec);
+      return size;
+    }
+
+    public void MergeFrom(MessageContainingMapCalledEntry other) {
+      if (other == null) {
+        return;
+      }
+      entry_.Add(other.entry_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            entry_.AddEntriesFrom(input, _map_entry_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
new file mode 100644
index 0000000..263e17c0
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
@@ -0,0 +1,161 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_import_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/unittest_import_proto3.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestImportProto3Reflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/unittest_import_proto3.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestImportProto3Reflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90",
+            "bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv",
+            "dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0",
+            "TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO",
+            "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB",
+            "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl",
+            "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv",
+            "Mw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), global::Google.Protobuf.TestProtos.ImportMessage.Parser, new[]{ "D" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum ImportEnum {
+    [pbr::OriginalName("IMPORT_ENUM_UNSPECIFIED")] Unspecified = 0,
+    [pbr::OriginalName("IMPORT_FOO")] ImportFoo = 7,
+    [pbr::OriginalName("IMPORT_BAR")] ImportBar = 8,
+    [pbr::OriginalName("IMPORT_BAZ")] ImportBaz = 9,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
+    private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
+    public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ImportMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ImportMessage(ImportMessage other) : this() {
+      d_ = other.d_;
+    }
+
+    public ImportMessage Clone() {
+      return new ImportMessage(this);
+    }
+
+    /// <summary>Field number for the "d" field.</summary>
+    public const int DFieldNumber = 1;
+    private int d_;
+    public int D {
+      get { return d_; }
+      set {
+        d_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ImportMessage);
+    }
+
+    public bool Equals(ImportMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (D != other.D) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (D != 0) hash ^= D.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (D != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(D);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (D != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ImportMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.D != 0) {
+        D = other.D;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            D = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
new file mode 100644
index 0000000..b471a8c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
@@ -0,0 +1,147 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_import_public_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/unittest_import_public_proto3.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestImportPublicProto3Reflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/unittest_import_public_proto3.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestImportPublicProto3Reflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90",
+            "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ",
+            "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1",
+            "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), global::Google.Protobuf.TestProtos.PublicImportMessage.Parser, new[]{ "E" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
+    private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
+    public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public PublicImportMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public PublicImportMessage(PublicImportMessage other) : this() {
+      e_ = other.e_;
+    }
+
+    public PublicImportMessage Clone() {
+      return new PublicImportMessage(this);
+    }
+
+    /// <summary>Field number for the "e" field.</summary>
+    public const int EFieldNumber = 1;
+    private int e_;
+    public int E {
+      get { return e_; }
+      set {
+        e_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as PublicImportMessage);
+    }
+
+    public bool Equals(PublicImportMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (E != other.E) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (E != 0) hash ^= E.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (E != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(E);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (E != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
+      }
+      return size;
+    }
+
+    public void MergeFrom(PublicImportMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.E != 0) {
+        E = other.E;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            E = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
new file mode 100644
index 0000000..7d4451b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
@@ -0,0 +1,1569 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: unittest_issues.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace UnitTest.Issues.TestProtos {
+
+  /// <summary>Holder for reflection information generated from unittest_issues.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestIssuesReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for unittest_issues.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestIssuesReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ",
+            "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh",
+            "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz",
+            "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p",
+            "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO",
+            "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj",
+            "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt",
+            "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC",
+            "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
+            "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu",
+            "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1",
+            "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES",
+            "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0",
+            "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl",
+            "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa",
+            "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT",
+            "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv",
+            "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p",
+            "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y",
+            "IksKDFRlc3RKc29uTmFtZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9u",
+            "GAIgASgJUgRkZXNjEhIKBGd1aWQYAyABKAlSBGV4aWQqVQoMTmVnYXRpdmVF",
+            "bnVtEhYKEk5FR0FUSVZFX0VOVU1fWkVSTxAAEhYKCUZpdmVCZWxvdxD7////",
+            "//////8BEhUKCE1pbnVzT25lEP///////////wEqLgoORGVwcmVjYXRlZEVu",
+            "dW0SEwoPREVQUkVDQVRFRF9aRVJPEAASBwoDb25lEAFCH0gBqgIaVW5pdFRl",
+            "c3QuSXNzdWVzLlRlc3RQcm90b3NiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null)})}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum NegativeEnum {
+    [pbr::OriginalName("NEGATIVE_ENUM_ZERO")] Zero = 0,
+    [pbr::OriginalName("FiveBelow")] FiveBelow = -5,
+    [pbr::OriginalName("MinusOne")] MinusOne = -1,
+  }
+
+  public enum DeprecatedEnum {
+    [pbr::OriginalName("DEPRECATED_ZERO")] DeprecatedZero = 0,
+    [pbr::OriginalName("one")] One = 1,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  Issue 307: when generating doubly-nested types, any references
+  ///  should be of the form A.Types.B.Types.C.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Issue307 : pb::IMessage<Issue307> {
+    private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
+    public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Issue307() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Issue307(Issue307 other) : this() {
+    }
+
+    public Issue307 Clone() {
+      return new Issue307(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Issue307);
+    }
+
+    public bool Equals(Issue307 other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(Issue307 other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the Issue307 message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
+        private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
+        public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedOnce() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedOnce(NestedOnce other) : this() {
+        }
+
+        public NestedOnce Clone() {
+          return new NestedOnce(this);
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedOnce);
+        }
+
+        public bool Equals(NestedOnce other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          return size;
+        }
+
+        public void MergeFrom(NestedOnce other) {
+          if (other == null) {
+            return;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+            }
+          }
+        }
+
+        #region Nested types
+        /// <summary>Container for nested types declared in the NestedOnce message type.</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        public static partial class Types {
+          [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+          public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
+            private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
+            public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
+
+            public static pbr::MessageDescriptor Descriptor {
+              get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
+            }
+
+            pbr::MessageDescriptor pb::IMessage.Descriptor {
+              get { return Descriptor; }
+            }
+
+            public NestedTwice() {
+              OnConstruction();
+            }
+
+            partial void OnConstruction();
+
+            public NestedTwice(NestedTwice other) : this() {
+            }
+
+            public NestedTwice Clone() {
+              return new NestedTwice(this);
+            }
+
+            public override bool Equals(object other) {
+              return Equals(other as NestedTwice);
+            }
+
+            public bool Equals(NestedTwice other) {
+              if (ReferenceEquals(other, null)) {
+                return false;
+              }
+              if (ReferenceEquals(other, this)) {
+                return true;
+              }
+              return true;
+            }
+
+            public override int GetHashCode() {
+              int hash = 1;
+              return hash;
+            }
+
+            public override string ToString() {
+              return pb::JsonFormatter.ToDiagnosticString(this);
+            }
+
+            public void WriteTo(pb::CodedOutputStream output) {
+            }
+
+            public int CalculateSize() {
+              int size = 0;
+              return size;
+            }
+
+            public void MergeFrom(NestedTwice other) {
+              if (other == null) {
+                return;
+              }
+            }
+
+            public void MergeFrom(pb::CodedInputStream input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  default:
+                    input.SkipLastField();
+                    break;
+                }
+              }
+            }
+
+          }
+
+        }
+        #endregion
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
+    private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
+    public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public NegativeEnumMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public NegativeEnumMessage(NegativeEnumMessage other) : this() {
+      value_ = other.value_;
+      values_ = other.values_.Clone();
+      packedValues_ = other.packedValues_.Clone();
+    }
+
+    public NegativeEnumMessage Clone() {
+      return new NegativeEnumMessage(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = 0;
+    public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "values" field.</summary>
+    public const int ValuesFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_values_codec
+        = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
+      get { return values_; }
+    }
+
+    /// <summary>Field number for the "packed_values" field.</summary>
+    public const int PackedValuesFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_packedValues_codec
+        = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
+      get { return packedValues_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as NegativeEnumMessage);
+    }
+
+    public bool Equals(NegativeEnumMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      if(!values_.Equals(other.values_)) return false;
+      if(!packedValues_.Equals(other.packedValues_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0) hash ^= Value.GetHashCode();
+      hash ^= values_.GetHashCode();
+      hash ^= packedValues_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Value);
+      }
+      values_.WriteTo(output, _repeated_values_codec);
+      packedValues_.WriteTo(output, _repeated_packedValues_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
+      }
+      size += values_.CalculateSize(_repeated_values_codec);
+      size += packedValues_.CalculateSize(_repeated_packedValues_codec);
+      return size;
+    }
+
+    public void MergeFrom(NegativeEnumMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0) {
+        Value = other.Value;
+      }
+      values_.Add(other.values_);
+      packedValues_.Add(other.packedValues_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
+            break;
+          }
+          case 18:
+          case 16: {
+            values_.AddEntriesFrom(input, _repeated_values_codec);
+            break;
+          }
+          case 26:
+          case 24: {
+            packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
+    private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
+    public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DeprecatedChild() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DeprecatedChild(DeprecatedChild other) : this() {
+    }
+
+    public DeprecatedChild Clone() {
+      return new DeprecatedChild(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DeprecatedChild);
+    }
+
+    public bool Equals(DeprecatedChild other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(DeprecatedChild other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
+    private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
+    public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DeprecatedFieldsMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() {
+      primitiveValue_ = other.primitiveValue_;
+      primitiveArray_ = other.primitiveArray_.Clone();
+      MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null;
+      messageArray_ = other.messageArray_.Clone();
+      enumValue_ = other.enumValue_;
+      enumArray_ = other.enumArray_.Clone();
+    }
+
+    public DeprecatedFieldsMessage Clone() {
+      return new DeprecatedFieldsMessage(this);
+    }
+
+    /// <summary>Field number for the "PrimitiveValue" field.</summary>
+    public const int PrimitiveValueFieldNumber = 1;
+    private int primitiveValue_;
+    [global::System.ObsoleteAttribute()]
+    public int PrimitiveValue {
+      get { return primitiveValue_; }
+      set {
+        primitiveValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "PrimitiveArray" field.</summary>
+    public const int PrimitiveArrayFieldNumber = 2;
+    private static readonly pb::FieldCodec<int> _repeated_primitiveArray_codec
+        = pb::FieldCodec.ForInt32(18);
+    private readonly pbc::RepeatedField<int> primitiveArray_ = new pbc::RepeatedField<int>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<int> PrimitiveArray {
+      get { return primitiveArray_; }
+    }
+
+    /// <summary>Field number for the "MessageValue" field.</summary>
+    public const int MessageValueFieldNumber = 3;
+    private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_;
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
+      get { return messageValue_; }
+      set {
+        messageValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "MessageArray" field.</summary>
+    public const int MessageArrayFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedChild> _repeated_messageArray_codec
+        = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArray {
+      get { return messageArray_; }
+    }
+
+    /// <summary>Field number for the "EnumValue" field.</summary>
+    public const int EnumValueFieldNumber = 5;
+    private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = 0;
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
+      get { return enumValue_; }
+      set {
+        enumValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "EnumArray" field.</summary>
+    public const int EnumArrayFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedEnum> _repeated_enumArray_codec
+        = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
+      get { return enumArray_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DeprecatedFieldsMessage);
+    }
+
+    public bool Equals(DeprecatedFieldsMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PrimitiveValue != other.PrimitiveValue) return false;
+      if(!primitiveArray_.Equals(other.primitiveArray_)) return false;
+      if (!object.Equals(MessageValue, other.MessageValue)) return false;
+      if(!messageArray_.Equals(other.messageArray_)) return false;
+      if (EnumValue != other.EnumValue) return false;
+      if(!enumArray_.Equals(other.enumArray_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode();
+      hash ^= primitiveArray_.GetHashCode();
+      if (messageValue_ != null) hash ^= MessageValue.GetHashCode();
+      hash ^= messageArray_.GetHashCode();
+      if (EnumValue != 0) hash ^= EnumValue.GetHashCode();
+      hash ^= enumArray_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PrimitiveValue != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveValue);
+      }
+      primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec);
+      if (messageValue_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(MessageValue);
+      }
+      messageArray_.WriteTo(output, _repeated_messageArray_codec);
+      if (EnumValue != 0) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) EnumValue);
+      }
+      enumArray_.WriteTo(output, _repeated_enumArray_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PrimitiveValue != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
+      }
+      size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec);
+      if (messageValue_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
+      }
+      size += messageArray_.CalculateSize(_repeated_messageArray_codec);
+      if (EnumValue != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
+      }
+      size += enumArray_.CalculateSize(_repeated_enumArray_codec);
+      return size;
+    }
+
+    public void MergeFrom(DeprecatedFieldsMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PrimitiveValue != 0) {
+        PrimitiveValue = other.PrimitiveValue;
+      }
+      primitiveArray_.Add(other.primitiveArray_);
+      if (other.messageValue_ != null) {
+        if (messageValue_ == null) {
+          messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+        }
+        MessageValue.MergeFrom(other.MessageValue);
+      }
+      messageArray_.Add(other.messageArray_);
+      if (other.EnumValue != 0) {
+        EnumValue = other.EnumValue;
+      }
+      enumArray_.Add(other.enumArray_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            PrimitiveValue = input.ReadInt32();
+            break;
+          }
+          case 18:
+          case 16: {
+            primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec);
+            break;
+          }
+          case 26: {
+            if (messageValue_ == null) {
+              messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+            }
+            input.ReadMessage(messageValue_);
+            break;
+          }
+          case 34: {
+            messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec);
+            break;
+          }
+          case 40: {
+            enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
+            break;
+          }
+          case 50:
+          case 48: {
+            enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ItemField : pb::IMessage<ItemField> {
+    private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
+    public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ItemField() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ItemField(ItemField other) : this() {
+      item_ = other.item_;
+    }
+
+    public ItemField Clone() {
+      return new ItemField(this);
+    }
+
+    /// <summary>Field number for the "item" field.</summary>
+    public const int ItemFieldNumber = 1;
+    private int item_;
+    public int Item {
+      get { return item_; }
+      set {
+        item_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ItemField);
+    }
+
+    public bool Equals(ItemField other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Item != other.Item) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Item != 0) hash ^= Item.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Item != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Item);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Item != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ItemField other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Item != 0) {
+        Item = other.Item;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Item = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ReservedNames : pb::IMessage<ReservedNames> {
+    private static readonly pb::MessageParser<ReservedNames> _parser = new pb::MessageParser<ReservedNames>(() => new ReservedNames());
+    public static pb::MessageParser<ReservedNames> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ReservedNames() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ReservedNames(ReservedNames other) : this() {
+      types_ = other.types_;
+      descriptor_ = other.descriptor_;
+    }
+
+    public ReservedNames Clone() {
+      return new ReservedNames(this);
+    }
+
+    /// <summary>Field number for the "types" field.</summary>
+    public const int Types_FieldNumber = 1;
+    private int types_;
+    public int Types_ {
+      get { return types_; }
+      set {
+        types_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "descriptor" field.</summary>
+    public const int Descriptor_FieldNumber = 2;
+    private int descriptor_;
+    public int Descriptor_ {
+      get { return descriptor_; }
+      set {
+        descriptor_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ReservedNames);
+    }
+
+    public bool Equals(ReservedNames other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Types_ != other.Types_) return false;
+      if (Descriptor_ != other.Descriptor_) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Types_ != 0) hash ^= Types_.GetHashCode();
+      if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Types_ != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Types_);
+      }
+      if (Descriptor_ != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Descriptor_);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Types_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Types_);
+      }
+      if (Descriptor_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ReservedNames other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Types_ != 0) {
+        Types_ = other.Types_;
+      }
+      if (other.Descriptor_ != 0) {
+        Descriptor_ = other.Descriptor_;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Types_ = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Descriptor_ = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the ReservedNames message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      /// <summary>
+      ///  Force a nested type called Types
+      /// </summary>
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
+        private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
+        public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public SomeNestedType() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public SomeNestedType(SomeNestedType other) : this() {
+        }
+
+        public SomeNestedType Clone() {
+          return new SomeNestedType(this);
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as SomeNestedType);
+        }
+
+        public bool Equals(SomeNestedType other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          return size;
+        }
+
+        public void MergeFrom(SomeNestedType other) {
+          if (other == null) {
+            return;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  These fields are deliberately not declared in numeric
+  ///  order, and the oneof fields aren't contiguous either.
+  ///  This allows for reasonably robust tests of JSON output
+  ///  ordering.
+  ///  TestFieldOrderings in unittest_proto3.proto is similar,
+  ///  but doesn't include oneofs.
+  ///  TODO: Consider adding oneofs to TestFieldOrderings, although
+  ///  that will require fixing other tests in multiple platforms.
+  ///  Alternatively, consider just adding this to
+  ///  unittest_proto3.proto if multiple platforms want it.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
+    private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
+    public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestJsonFieldOrdering() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() {
+      plainInt32_ = other.plainInt32_;
+      plainString_ = other.plainString_;
+      switch (other.O1Case) {
+        case O1OneofCase.O1String:
+          O1String = other.O1String;
+          break;
+        case O1OneofCase.O1Int32:
+          O1Int32 = other.O1Int32;
+          break;
+      }
+
+      switch (other.O2Case) {
+        case O2OneofCase.O2Int32:
+          O2Int32 = other.O2Int32;
+          break;
+        case O2OneofCase.O2String:
+          O2String = other.O2String;
+          break;
+      }
+
+    }
+
+    public TestJsonFieldOrdering Clone() {
+      return new TestJsonFieldOrdering(this);
+    }
+
+    /// <summary>Field number for the "plain_int32" field.</summary>
+    public const int PlainInt32FieldNumber = 4;
+    private int plainInt32_;
+    public int PlainInt32 {
+      get { return plainInt32_; }
+      set {
+        plainInt32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "o1_string" field.</summary>
+    public const int O1StringFieldNumber = 2;
+    public string O1String {
+      get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; }
+      set {
+        o1_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        o1Case_ = O1OneofCase.O1String;
+      }
+    }
+
+    /// <summary>Field number for the "o1_int32" field.</summary>
+    public const int O1Int32FieldNumber = 5;
+    public int O1Int32 {
+      get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; }
+      set {
+        o1_ = value;
+        o1Case_ = O1OneofCase.O1Int32;
+      }
+    }
+
+    /// <summary>Field number for the "plain_string" field.</summary>
+    public const int PlainStringFieldNumber = 1;
+    private string plainString_ = "";
+    public string PlainString {
+      get { return plainString_; }
+      set {
+        plainString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "o2_int32" field.</summary>
+    public const int O2Int32FieldNumber = 6;
+    public int O2Int32 {
+      get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; }
+      set {
+        o2_ = value;
+        o2Case_ = O2OneofCase.O2Int32;
+      }
+    }
+
+    /// <summary>Field number for the "o2_string" field.</summary>
+    public const int O2StringFieldNumber = 3;
+    public string O2String {
+      get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; }
+      set {
+        o2_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        o2Case_ = O2OneofCase.O2String;
+      }
+    }
+
+    private object o1_;
+    /// <summary>Enum of possible cases for the "o1" oneof.</summary>
+    public enum O1OneofCase {
+      None = 0,
+      O1String = 2,
+      O1Int32 = 5,
+    }
+    private O1OneofCase o1Case_ = O1OneofCase.None;
+    public O1OneofCase O1Case {
+      get { return o1Case_; }
+    }
+
+    public void ClearO1() {
+      o1Case_ = O1OneofCase.None;
+      o1_ = null;
+    }
+
+    private object o2_;
+    /// <summary>Enum of possible cases for the "o2" oneof.</summary>
+    public enum O2OneofCase {
+      None = 0,
+      O2Int32 = 6,
+      O2String = 3,
+    }
+    private O2OneofCase o2Case_ = O2OneofCase.None;
+    public O2OneofCase O2Case {
+      get { return o2Case_; }
+    }
+
+    public void ClearO2() {
+      o2Case_ = O2OneofCase.None;
+      o2_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestJsonFieldOrdering);
+    }
+
+    public bool Equals(TestJsonFieldOrdering other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PlainInt32 != other.PlainInt32) return false;
+      if (O1String != other.O1String) return false;
+      if (O1Int32 != other.O1Int32) return false;
+      if (PlainString != other.PlainString) return false;
+      if (O2Int32 != other.O2Int32) return false;
+      if (O2String != other.O2String) return false;
+      if (O1Case != other.O1Case) return false;
+      if (O2Case != other.O2Case) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode();
+      if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode();
+      if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode();
+      if (PlainString.Length != 0) hash ^= PlainString.GetHashCode();
+      if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode();
+      if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode();
+      hash ^= (int) o1Case_;
+      hash ^= (int) o2Case_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PlainString.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(PlainString);
+      }
+      if (o1Case_ == O1OneofCase.O1String) {
+        output.WriteRawTag(18);
+        output.WriteString(O1String);
+      }
+      if (o2Case_ == O2OneofCase.O2String) {
+        output.WriteRawTag(26);
+        output.WriteString(O2String);
+      }
+      if (PlainInt32 != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(PlainInt32);
+      }
+      if (o1Case_ == O1OneofCase.O1Int32) {
+        output.WriteRawTag(40);
+        output.WriteInt32(O1Int32);
+      }
+      if (o2Case_ == O2OneofCase.O2Int32) {
+        output.WriteRawTag(48);
+        output.WriteInt32(O2Int32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PlainInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32);
+      }
+      if (o1Case_ == O1OneofCase.O1String) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String);
+      }
+      if (o1Case_ == O1OneofCase.O1Int32) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32);
+      }
+      if (PlainString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString);
+      }
+      if (o2Case_ == O2OneofCase.O2Int32) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32);
+      }
+      if (o2Case_ == O2OneofCase.O2String) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestJsonFieldOrdering other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PlainInt32 != 0) {
+        PlainInt32 = other.PlainInt32;
+      }
+      if (other.PlainString.Length != 0) {
+        PlainString = other.PlainString;
+      }
+      switch (other.O1Case) {
+        case O1OneofCase.O1String:
+          O1String = other.O1String;
+          break;
+        case O1OneofCase.O1Int32:
+          O1Int32 = other.O1Int32;
+          break;
+      }
+
+      switch (other.O2Case) {
+        case O2OneofCase.O2Int32:
+          O2Int32 = other.O2Int32;
+          break;
+        case O2OneofCase.O2String:
+          O2String = other.O2String;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            PlainString = input.ReadString();
+            break;
+          }
+          case 18: {
+            O1String = input.ReadString();
+            break;
+          }
+          case 26: {
+            O2String = input.ReadString();
+            break;
+          }
+          case 32: {
+            PlainInt32 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            O1Int32 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            O2Int32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestJsonName : pb::IMessage<TestJsonName> {
+    private static readonly pb::MessageParser<TestJsonName> _parser = new pb::MessageParser<TestJsonName>(() => new TestJsonName());
+    public static pb::MessageParser<TestJsonName> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestJsonName() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestJsonName(TestJsonName other) : this() {
+      name_ = other.name_;
+      description_ = other.description_;
+      guid_ = other.guid_;
+    }
+
+    public TestJsonName Clone() {
+      return new TestJsonName(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  Message for testing the effects for of the json_name option
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "description" field.</summary>
+    public const int DescriptionFieldNumber = 2;
+    private string description_ = "";
+    public string Description {
+      get { return description_; }
+      set {
+        description_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "guid" field.</summary>
+    public const int GuidFieldNumber = 3;
+    private string guid_ = "";
+    public string Guid {
+      get { return guid_; }
+      set {
+        guid_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestJsonName);
+    }
+
+    public bool Equals(TestJsonName other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Description != other.Description) return false;
+      if (Guid != other.Guid) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Description.Length != 0) hash ^= Description.GetHashCode();
+      if (Guid.Length != 0) hash ^= Guid.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Description.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Description);
+      }
+      if (Guid.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Guid);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Description.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Description);
+      }
+      if (Guid.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Guid);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestJsonName other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Description.Length != 0) {
+        Description = other.Description;
+      }
+      if (other.Guid.Length != 0) {
+        Guid = other.Guid;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Description = input.ReadString();
+            break;
+          }
+          case 26: {
+            Guid = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
new file mode 100644
index 0000000..b8d159b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
@@ -0,0 +1,6064 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/unittest_proto3.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestProto3Reflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/unittest_proto3.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestProto3Reflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zLnByb3RvEhFwcm90",
+            "b2J1Zl91bml0dGVzdBosZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9y",
+            "dF9wcm90bzMucHJvdG8i8A8KDFRlc3RBbGxUeXBlcxIUCgxzaW5nbGVfaW50",
+            "MzIYASABKAUSFAoMc2luZ2xlX2ludDY0GAIgASgDEhUKDXNpbmdsZV91aW50",
+            "MzIYAyABKA0SFQoNc2luZ2xlX3VpbnQ2NBgEIAEoBBIVCg1zaW5nbGVfc2lu",
+            "dDMyGAUgASgREhUKDXNpbmdsZV9zaW50NjQYBiABKBISFgoOc2luZ2xlX2Zp",
+            "eGVkMzIYByABKAcSFgoOc2luZ2xlX2ZpeGVkNjQYCCABKAYSFwoPc2luZ2xl",
+            "X3NmaXhlZDMyGAkgASgPEhcKD3NpbmdsZV9zZml4ZWQ2NBgKIAEoEBIUCgxz",
+            "aW5nbGVfZmxvYXQYCyABKAISFQoNc2luZ2xlX2RvdWJsZRgMIAEoARITCgtz",
+            "aW5nbGVfYm9vbBgNIAEoCBIVCg1zaW5nbGVfc3RyaW5nGA4gASgJEhQKDHNp",
+            "bmdsZV9ieXRlcxgPIAEoDBJMChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYEiAB",
+            "KAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz",
+            "c2FnZRJBChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdlGBMgASgLMiEucHJvdG9i",
+            "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USRgoVc2luZ2xlX2ltcG9ydF9t",
+            "ZXNzYWdlGBQgASgLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9y",
+            "dE1lc3NhZ2USRgoSc2luZ2xlX25lc3RlZF9lbnVtGBUgASgOMioucHJvdG9i",
+            "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SOwoTc2luZ2xl",
+            "X2ZvcmVpZ25fZW51bRgWIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVp",
+            "Z25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51bRgXIAEoDjIkLnByb3RvYnVm",
+            "X3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtElMKHHNpbmdsZV9wdWJsaWNf",
+            "aW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBv",
+            "cnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo",
+            "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY",
+            "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np",
+            "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0",
+            "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK",
+            "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0",
+            "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv",
+            "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk",
+            "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJOChdyZXBl",
+            "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0",
+            "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkMKGHJlcGVhdGVkX2ZvcmVp",
+            "Z25fbWVzc2FnZRgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25N",
+            "ZXNzYWdlEkgKF3JlcGVhdGVkX2ltcG9ydF9tZXNzYWdlGDIgAygLMicucHJv",
+            "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2USSAoUcmVwZWF0",
+            "ZWRfbmVzdGVkX2VudW0YMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0",
+            "QWxsVHlwZXMuTmVzdGVkRW51bRI9ChVyZXBlYXRlZF9mb3JlaWduX2VudW0Y",
+            "NCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRJCChRyZXBl",
+            "YXRlZF9pbXBvcnRfZW51bRg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2lt",
+            "cG9ydC5JbXBvcnRFbnVtElUKHnJlcGVhdGVkX3B1YmxpY19pbXBvcnRfbWVz",
+            "c2FnZRg2IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJ",
+            "bXBvcnRNZXNzYWdlEhYKDG9uZW9mX3VpbnQzMhhvIAEoDUgAEk0KFG9uZW9m",
+            "X25lc3RlZF9tZXNzYWdlGHAgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVz",
+            "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxvbmVvZl9zdHJpbmcYcSAB",
+            "KAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsKDU5lc3RlZE1lc3NhZ2US",
+            "CgoCYmIYASABKAUiVgoKTmVzdGVkRW51bRIbChdORVNURURfRU5VTV9VTlNQ",
+            "RUNJRklFRBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/",
+            "//////////8BQg0KC29uZW9mX2ZpZWxkIrsBChJOZXN0ZWRUZXN0QWxsVHlw",
+            "ZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRU",
+            "ZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3RvYnVmX3VuaXR0",
+            "ZXN0LlRlc3RBbGxUeXBlcxI9Cg5yZXBlYXRlZF9jaGlsZBgDIAMoCzIlLnBy",
+            "b3RvYnVmX3VuaXR0ZXN0Lk5lc3RlZFRlc3RBbGxUeXBlcyI0ChRUZXN0RGVw",
+            "cmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIb",
+            "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFIjAKElRlc3RSZXNlcnZlZEZp",
+            "ZWxkc0oECAIQA0oECA8QEEoECAkQDFIDYmFyUgNiYXoiWgoRVGVzdEZvcmVp",
+            "Z25OZXN0ZWQSRQoOZm9yZWlnbl9uZXN0ZWQYASABKAsyLS5wcm90b2J1Zl91",
+            "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVh",
+            "bGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJV",
+            "ChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZf",
+            "dW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRU",
+            "ZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3Vu",
+            "aXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1",
+            "cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0",
+            "dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSLrAgoXVGVz",
+            "dENhbWVsQ2FzZUZpZWxkTmFtZXMSFgoOUHJpbWl0aXZlRmllbGQYASABKAUS",
+            "EwoLU3RyaW5nRmllbGQYAiABKAkSMQoJRW51bUZpZWxkGAMgASgOMh4ucHJv",
+            "dG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SNwoMTWVzc2FnZUZpZWxkGAQg",
+            "ASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USHgoWUmVw",
+            "ZWF0ZWRQcmltaXRpdmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0Zp",
+            "ZWxkGAggAygJEjkKEVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMh4ucHJvdG9i",
+            "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SPwoUUmVwZWF0ZWRNZXNzYWdlRmll",
+            "bGQYCiADKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSLH",
+            "AQoSVGVzdEZpZWxkT3JkZXJpbmdzEhEKCW15X3N0cmluZxgLIAEoCRIOCgZt",
+            "eV9pbnQYASABKAMSEAoIbXlfZmxvYXQYZSABKAISUwoVc2luZ2xlX25lc3Rl",
+            "ZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVs",
+            "ZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoC",
+            "b28YAiABKAMSCgoCYmIYASABKAUiSwoRU3BhcnNlRW51bU1lc3NhZ2USNgoL",
+            "c3BhcnNlX2VudW0YASABKA4yIS5wcm90b2J1Zl91bml0dGVzdC5UZXN0U3Bh",
+            "cnNlRW51bSIZCglPbmVTdHJpbmcSDAoEZGF0YRgBIAEoCSIaCgpNb3JlU3Ry",
+            "aW5nEgwKBGRhdGEYASADKAkiGAoIT25lQnl0ZXMSDAoEZGF0YRgBIAEoDCIZ",
+            "CglNb3JlQnl0ZXMSDAoEZGF0YRgBIAEoDCIcCgxJbnQzMk1lc3NhZ2USDAoE",
+            "ZGF0YRgBIAEoBSIdCg1VaW50MzJNZXNzYWdlEgwKBGRhdGEYASABKA0iHAoM",
+            "SW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAMiHQoNVWludDY0TWVzc2FnZRIM",
+            "CgRkYXRhGAEgASgEIhsKC0Jvb2xNZXNzYWdlEgwKBGRhdGEYASABKAgicwoJ",
+            "VGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIg",
+            "ASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVz",
+            "dC5UZXN0QWxsVHlwZXNIAEIFCgNmb28iqgMKD1Rlc3RQYWNrZWRUeXBlcxIY",
+            "CgxwYWNrZWRfaW50MzIYWiADKAVCAhABEhgKDHBhY2tlZF9pbnQ2NBhbIAMo",
+            "A0ICEAESGQoNcGFja2VkX3VpbnQzMhhcIAMoDUICEAESGQoNcGFja2VkX3Vp",
+            "bnQ2NBhdIAMoBEICEAESGQoNcGFja2VkX3NpbnQzMhheIAMoEUICEAESGQoN",
+            "cGFja2VkX3NpbnQ2NBhfIAMoEkICEAESGgoOcGFja2VkX2ZpeGVkMzIYYCAD",
+            "KAdCAhABEhoKDnBhY2tlZF9maXhlZDY0GGEgAygGQgIQARIbCg9wYWNrZWRf",
+            "c2ZpeGVkMzIYYiADKA9CAhABEhsKD3BhY2tlZF9zZml4ZWQ2NBhjIAMoEEIC",
+            "EAESGAoMcGFja2VkX2Zsb2F0GGQgAygCQgIQARIZCg1wYWNrZWRfZG91Ymxl",
+            "GGUgAygBQgIQARIXCgtwYWNrZWRfYm9vbBhmIAMoCEICEAESNwoLcGFja2Vk",
+            "X2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUIC",
+            "EAEiyAMKEVRlc3RVbnBhY2tlZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFog",
+            "AygFQgIQABIaCg51bnBhY2tlZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNr",
+            "ZWRfdWludDMyGFwgAygNQgIQABIbCg91bnBhY2tlZF91aW50NjQYXSADKARC",
+            "AhAAEhsKD3VucGFja2VkX3NpbnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRf",
+            "c2ludDY0GF8gAygSQgIQABIcChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQ",
+            "ABIcChB1bnBhY2tlZF9maXhlZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9z",
+            "Zml4ZWQzMhhiIAMoD0ICEAASHQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBC",
+            "AhAAEhoKDnVucGFja2VkX2Zsb2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9k",
+            "b3VibGUYZSADKAFCAhAAEhkKDXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjkK",
+            "DXVucGFja2VkX2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl",
+            "aWduRW51bUICEAAiwAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRh",
+            "Z1NpemVzEhgKEHJlcGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRf",
+            "aW50MzIYDSADKAUSGQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVw",
+            "ZWF0ZWRfaW50NjQY/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAIS",
+            "GQoPcmVwZWF0ZWRfdWludDY0GP//DyADKAQiKAobVGVzdENvbW1lbnRJbmpl",
+            "Y3Rpb25NZXNzYWdlEgkKAWEYASABKAkiDAoKRm9vUmVxdWVzdCINCgtGb29S",
+            "ZXNwb25zZSISChBGb29DbGllbnRNZXNzYWdlIhIKEEZvb1NlcnZlck1lc3Nh",
+            "Z2UiDAoKQmFyUmVxdWVzdCINCgtCYXJSZXNwb25zZSpZCgtGb3JlaWduRW51",
+            "bRIXChNGT1JFSUdOX1VOU1BFQ0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIP",
+            "CgtGT1JFSUdOX0JBUhAFEg8KC0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1X",
+            "aXRoRHVwVmFsdWUSKAokVEVTVF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BF",
+            "Q0lGSUVEEAASCAoERk9PMRABEggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08y",
+            "EAESCAoEQkFSMhACGgIQASqdAQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9T",
+            "UEFSU0VfRU5VTV9VTlNQRUNJRklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BB",
+            "UlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////",
+            "////ARIVCghTUEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9HEAIymQEK",
+            "C1Rlc3RTZXJ2aWNlEkQKA0ZvbxIdLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jl",
+            "cXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXIS",
+            "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p",
+            "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB",
+            "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), global::Google.Protobuf.TestProtos.TestAllTypes.Parser, new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), global::Google.Protobuf.TestProtos.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), global::Google.Protobuf.TestProtos.ForeignMessage.Parser, new[]{ "C" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), global::Google.Protobuf.TestProtos.TestReservedFields.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), global::Google.Protobuf.TestProtos.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), global::Google.Protobuf.TestProtos.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), global::Google.Protobuf.TestProtos.TestMutualRecursionA.Parser, new[]{ "Bb" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), global::Google.Protobuf.TestProtos.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), global::Google.Protobuf.TestProtos.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), global::Google.Protobuf.TestProtos.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), global::Google.Protobuf.TestProtos.OneString.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), global::Google.Protobuf.TestProtos.MoreString.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), global::Google.Protobuf.TestProtos.OneBytes.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), global::Google.Protobuf.TestProtos.MoreBytes.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), global::Google.Protobuf.TestProtos.Int32Message.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), global::Google.Protobuf.TestProtos.Uint32Message.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), global::Google.Protobuf.TestProtos.Int64Message.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), global::Google.Protobuf.TestProtos.Uint64Message.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), global::Google.Protobuf.TestProtos.BoolMessage.Parser, new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), global::Google.Protobuf.TestProtos.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), global::Google.Protobuf.TestProtos.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), global::Google.Protobuf.TestProtos.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), global::Google.Protobuf.TestProtos.FooRequest.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), global::Google.Protobuf.TestProtos.FooResponse.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), global::Google.Protobuf.TestProtos.FooClientMessage.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), global::Google.Protobuf.TestProtos.FooServerMessage.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), global::Google.Protobuf.TestProtos.BarRequest.Parser, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), global::Google.Protobuf.TestProtos.BarResponse.Parser, null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum ForeignEnum {
+    [pbr::OriginalName("FOREIGN_UNSPECIFIED")] ForeignUnspecified = 0,
+    [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 4,
+    [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 5,
+    [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 6,
+  }
+
+  /// <summary>
+  ///  Test an enum that has multiple values with the same number.
+  /// </summary>
+  public enum TestEnumWithDupValue {
+    [pbr::OriginalName("TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED")] Unspecified = 0,
+    [pbr::OriginalName("FOO1")] Foo1 = 1,
+    [pbr::OriginalName("BAR1")] Bar1 = 2,
+    [pbr::OriginalName("BAZ")] Baz = 3,
+    [pbr::OriginalName("FOO2")] Foo2 = 1,
+    [pbr::OriginalName("BAR2")] Bar2 = 2,
+  }
+
+  /// <summary>
+  ///  Test an enum with large, unordered values.
+  /// </summary>
+  public enum TestSparseEnum {
+    [pbr::OriginalName("TEST_SPARSE_ENUM_UNSPECIFIED")] Unspecified = 0,
+    [pbr::OriginalName("SPARSE_A")] SparseA = 123,
+    [pbr::OriginalName("SPARSE_B")] SparseB = 62374,
+    [pbr::OriginalName("SPARSE_C")] SparseC = 12589234,
+    [pbr::OriginalName("SPARSE_D")] SparseD = -15,
+    [pbr::OriginalName("SPARSE_E")] SparseE = -53452,
+    /// <summary>
+    ///  In proto3, value 0 must be the first one specified
+    ///  SPARSE_F = 0;
+    /// </summary>
+    [pbr::OriginalName("SPARSE_G")] SparseG = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  This proto includes every type of field in both singular and repeated
+  ///  forms.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+    private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
+    public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestAllTypes(TestAllTypes other) : this() {
+      singleInt32_ = other.singleInt32_;
+      singleInt64_ = other.singleInt64_;
+      singleUint32_ = other.singleUint32_;
+      singleUint64_ = other.singleUint64_;
+      singleSint32_ = other.singleSint32_;
+      singleSint64_ = other.singleSint64_;
+      singleFixed32_ = other.singleFixed32_;
+      singleFixed64_ = other.singleFixed64_;
+      singleSfixed32_ = other.singleSfixed32_;
+      singleSfixed64_ = other.singleSfixed64_;
+      singleFloat_ = other.singleFloat_;
+      singleDouble_ = other.singleDouble_;
+      singleBool_ = other.singleBool_;
+      singleString_ = other.singleString_;
+      singleBytes_ = other.singleBytes_;
+      SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null;
+      SingleForeignMessage = other.singleForeignMessage_ != null ? other.SingleForeignMessage.Clone() : null;
+      SingleImportMessage = other.singleImportMessage_ != null ? other.SingleImportMessage.Clone() : null;
+      singleNestedEnum_ = other.singleNestedEnum_;
+      singleForeignEnum_ = other.singleForeignEnum_;
+      singleImportEnum_ = other.singleImportEnum_;
+      SinglePublicImportMessage = other.singlePublicImportMessage_ != null ? other.SinglePublicImportMessage.Clone() : null;
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedUint32_ = other.repeatedUint32_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+      repeatedSint32_ = other.repeatedSint32_.Clone();
+      repeatedSint64_ = other.repeatedSint64_.Clone();
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedSfixed32_ = other.repeatedSfixed32_.Clone();
+      repeatedSfixed64_ = other.repeatedSfixed64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedDouble_ = other.repeatedDouble_.Clone();
+      repeatedBool_ = other.repeatedBool_.Clone();
+      repeatedString_ = other.repeatedString_.Clone();
+      repeatedBytes_ = other.repeatedBytes_.Clone();
+      repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone();
+      repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone();
+      repeatedImportMessage_ = other.repeatedImportMessage_.Clone();
+      repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone();
+      repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone();
+      repeatedImportEnum_ = other.repeatedImportEnum_.Clone();
+      repeatedPublicImportMessage_ = other.repeatedPublicImportMessage_.Clone();
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage.Clone();
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public TestAllTypes Clone() {
+      return new TestAllTypes(this);
+    }
+
+    /// <summary>Field number for the "single_int32" field.</summary>
+    public const int SingleInt32FieldNumber = 1;
+    private int singleInt32_;
+    /// <summary>
+    ///  Singular
+    /// </summary>
+    public int SingleInt32 {
+      get { return singleInt32_; }
+      set {
+        singleInt32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_int64" field.</summary>
+    public const int SingleInt64FieldNumber = 2;
+    private long singleInt64_;
+    public long SingleInt64 {
+      get { return singleInt64_; }
+      set {
+        singleInt64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_uint32" field.</summary>
+    public const int SingleUint32FieldNumber = 3;
+    private uint singleUint32_;
+    public uint SingleUint32 {
+      get { return singleUint32_; }
+      set {
+        singleUint32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_uint64" field.</summary>
+    public const int SingleUint64FieldNumber = 4;
+    private ulong singleUint64_;
+    public ulong SingleUint64 {
+      get { return singleUint64_; }
+      set {
+        singleUint64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_sint32" field.</summary>
+    public const int SingleSint32FieldNumber = 5;
+    private int singleSint32_;
+    public int SingleSint32 {
+      get { return singleSint32_; }
+      set {
+        singleSint32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_sint64" field.</summary>
+    public const int SingleSint64FieldNumber = 6;
+    private long singleSint64_;
+    public long SingleSint64 {
+      get { return singleSint64_; }
+      set {
+        singleSint64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_fixed32" field.</summary>
+    public const int SingleFixed32FieldNumber = 7;
+    private uint singleFixed32_;
+    public uint SingleFixed32 {
+      get { return singleFixed32_; }
+      set {
+        singleFixed32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_fixed64" field.</summary>
+    public const int SingleFixed64FieldNumber = 8;
+    private ulong singleFixed64_;
+    public ulong SingleFixed64 {
+      get { return singleFixed64_; }
+      set {
+        singleFixed64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_sfixed32" field.</summary>
+    public const int SingleSfixed32FieldNumber = 9;
+    private int singleSfixed32_;
+    public int SingleSfixed32 {
+      get { return singleSfixed32_; }
+      set {
+        singleSfixed32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_sfixed64" field.</summary>
+    public const int SingleSfixed64FieldNumber = 10;
+    private long singleSfixed64_;
+    public long SingleSfixed64 {
+      get { return singleSfixed64_; }
+      set {
+        singleSfixed64_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_float" field.</summary>
+    public const int SingleFloatFieldNumber = 11;
+    private float singleFloat_;
+    public float SingleFloat {
+      get { return singleFloat_; }
+      set {
+        singleFloat_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_double" field.</summary>
+    public const int SingleDoubleFieldNumber = 12;
+    private double singleDouble_;
+    public double SingleDouble {
+      get { return singleDouble_; }
+      set {
+        singleDouble_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_bool" field.</summary>
+    public const int SingleBoolFieldNumber = 13;
+    private bool singleBool_;
+    public bool SingleBool {
+      get { return singleBool_; }
+      set {
+        singleBool_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_string" field.</summary>
+    public const int SingleStringFieldNumber = 14;
+    private string singleString_ = "";
+    public string SingleString {
+      get { return singleString_; }
+      set {
+        singleString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "single_bytes" field.</summary>
+    public const int SingleBytesFieldNumber = 15;
+    private pb::ByteString singleBytes_ = pb::ByteString.Empty;
+    public pb::ByteString SingleBytes {
+      get { return singleBytes_; }
+      set {
+        singleBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "single_nested_message" field.</summary>
+    public const int SingleNestedMessageFieldNumber = 18;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage {
+      get { return singleNestedMessage_; }
+      set {
+        singleNestedMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_foreign_message" field.</summary>
+    public const int SingleForeignMessageFieldNumber = 19;
+    private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_;
+    public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage {
+      get { return singleForeignMessage_; }
+      set {
+        singleForeignMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_import_message" field.</summary>
+    public const int SingleImportMessageFieldNumber = 20;
+    private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_;
+    public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage {
+      get { return singleImportMessage_; }
+      set {
+        singleImportMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_nested_enum" field.</summary>
+    public const int SingleNestedEnumFieldNumber = 21;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = 0;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum {
+      get { return singleNestedEnum_; }
+      set {
+        singleNestedEnum_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_foreign_enum" field.</summary>
+    public const int SingleForeignEnumFieldNumber = 22;
+    private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = 0;
+    public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum {
+      get { return singleForeignEnum_; }
+      set {
+        singleForeignEnum_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_import_enum" field.</summary>
+    public const int SingleImportEnumFieldNumber = 23;
+    private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = 0;
+    public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum {
+      get { return singleImportEnum_; }
+      set {
+        singleImportEnum_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_public_import_message" field.</summary>
+    public const int SinglePublicImportMessageFieldNumber = 26;
+    private global::Google.Protobuf.TestProtos.PublicImportMessage singlePublicImportMessage_;
+    /// <summary>
+    ///  Defined in unittest_import_public.proto
+    /// </summary>
+    public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage {
+      get { return singlePublicImportMessage_; }
+      set {
+        singlePublicImportMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "repeated_int32" field.</summary>
+    public const int RepeatedInt32FieldNumber = 31;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(250);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Repeated
+    /// </summary>
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    /// <summary>Field number for the "repeated_int64" field.</summary>
+    public const int RepeatedInt64FieldNumber = 32;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(258);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint32" field.</summary>
+    public const int RepeatedUint32FieldNumber = 33;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedUint32_codec
+        = pb::FieldCodec.ForUInt32(266);
+    private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedUint32 {
+      get { return repeatedUint32_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint64" field.</summary>
+    public const int RepeatedUint64FieldNumber = 34;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(274);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    /// <summary>Field number for the "repeated_sint32" field.</summary>
+    public const int RepeatedSint32FieldNumber = 35;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSint32_codec
+        = pb::FieldCodec.ForSInt32(282);
+    private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSint32 {
+      get { return repeatedSint32_; }
+    }
+
+    /// <summary>Field number for the "repeated_sint64" field.</summary>
+    public const int RepeatedSint64FieldNumber = 36;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSint64_codec
+        = pb::FieldCodec.ForSInt64(290);
+    private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSint64 {
+      get { return repeatedSint64_; }
+    }
+
+    /// <summary>Field number for the "repeated_fixed32" field.</summary>
+    public const int RepeatedFixed32FieldNumber = 37;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(298);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    /// <summary>Field number for the "repeated_fixed64" field.</summary>
+    public const int RepeatedFixed64FieldNumber = 38;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(306);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    /// <summary>Field number for the "repeated_sfixed32" field.</summary>
+    public const int RepeatedSfixed32FieldNumber = 39;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(314);
+    private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSfixed32 {
+      get { return repeatedSfixed32_; }
+    }
+
+    /// <summary>Field number for the "repeated_sfixed64" field.</summary>
+    public const int RepeatedSfixed64FieldNumber = 40;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(322);
+    private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSfixed64 {
+      get { return repeatedSfixed64_; }
+    }
+
+    /// <summary>Field number for the "repeated_float" field.</summary>
+    public const int RepeatedFloatFieldNumber = 41;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(330);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    /// <summary>Field number for the "repeated_double" field.</summary>
+    public const int RepeatedDoubleFieldNumber = 42;
+    private static readonly pb::FieldCodec<double> _repeated_repeatedDouble_codec
+        = pb::FieldCodec.ForDouble(338);
+    private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> RepeatedDouble {
+      get { return repeatedDouble_; }
+    }
+
+    /// <summary>Field number for the "repeated_bool" field.</summary>
+    public const int RepeatedBoolFieldNumber = 43;
+    private static readonly pb::FieldCodec<bool> _repeated_repeatedBool_codec
+        = pb::FieldCodec.ForBool(346);
+    private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> RepeatedBool {
+      get { return repeatedBool_; }
+    }
+
+    /// <summary>Field number for the "repeated_string" field.</summary>
+    public const int RepeatedStringFieldNumber = 44;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedString_codec
+        = pb::FieldCodec.ForString(354);
+    private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedString {
+      get { return repeatedString_; }
+    }
+
+    /// <summary>Field number for the "repeated_bytes" field.</summary>
+    public const int RepeatedBytesFieldNumber = 45;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytes_codec
+        = pb::FieldCodec.ForBytes(362);
+    private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
+      get { return repeatedBytes_; }
+    }
+
+    /// <summary>Field number for the "repeated_nested_message" field.</summary>
+    public const int RepeatedNestedMessageFieldNumber = 48;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
+        = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
+      get { return repeatedNestedMessage_; }
+    }
+
+    /// <summary>Field number for the "repeated_foreign_message" field.</summary>
+    public const int RepeatedForeignMessageFieldNumber = 49;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignMessage> _repeated_repeatedForeignMessage_codec
+        = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedForeignMessage {
+      get { return repeatedForeignMessage_; }
+    }
+
+    /// <summary>Field number for the "repeated_import_message" field.</summary>
+    public const int RepeatedImportMessageFieldNumber = 50;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ImportMessage> _repeated_repeatedImportMessage_codec
+        = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.ImportMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> repeatedImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> RepeatedImportMessage {
+      get { return repeatedImportMessage_; }
+    }
+
+    /// <summary>Field number for the "repeated_nested_enum" field.</summary>
+    public const int RepeatedNestedEnumFieldNumber = 51;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
+      get { return repeatedNestedEnum_; }
+    }
+
+    /// <summary>Field number for the "repeated_foreign_enum" field.</summary>
+    public const int RepeatedForeignEnumFieldNumber = 52;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedForeignEnum_codec
+        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedForeignEnum {
+      get { return repeatedForeignEnum_; }
+    }
+
+    /// <summary>Field number for the "repeated_import_enum" field.</summary>
+    public const int RepeatedImportEnumFieldNumber = 53;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ImportEnum> _repeated_repeatedImportEnum_codec
+        = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> RepeatedImportEnum {
+      get { return repeatedImportEnum_; }
+    }
+
+    /// <summary>Field number for the "repeated_public_import_message" field.</summary>
+    public const int RepeatedPublicImportMessageFieldNumber = 54;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.PublicImportMessage> _repeated_repeatedPublicImportMessage_codec
+        = pb::FieldCodec.ForMessage(434, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage> repeatedPublicImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage>();
+    /// <summary>
+    ///  Defined in unittest_import_public.proto
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage> RepeatedPublicImportMessage {
+      get { return repeatedPublicImportMessage_; }
+    }
+
+    /// <summary>Field number for the "oneof_uint32" field.</summary>
+    public const int OneofUint32FieldNumber = 111;
+    public uint OneofUint32 {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = OneofFieldOneofCase.OneofUint32;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_nested_message" field.</summary>
+    public const int OneofNestedMessageFieldNumber = 112;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_string" field.</summary>
+    public const int OneofStringFieldNumber = 113;
+    public string OneofString {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
+      set {
+        oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofString;
+      }
+    }
+
+    /// <summary>Field number for the "oneof_bytes" field.</summary>
+    public const int OneofBytesFieldNumber = 114;
+    public pb::ByteString OneofBytes {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
+      set {
+        oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofBytes;
+      }
+    }
+
+    private object oneofField_;
+    /// <summary>Enum of possible cases for the "oneof_field" oneof.</summary>
+    public enum OneofFieldOneofCase {
+      None = 0,
+      OneofUint32 = 111,
+      OneofNestedMessage = 112,
+      OneofString = 113,
+      OneofBytes = 114,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestAllTypes);
+    }
+
+    public bool Equals(TestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (SingleInt32 != other.SingleInt32) return false;
+      if (SingleInt64 != other.SingleInt64) return false;
+      if (SingleUint32 != other.SingleUint32) return false;
+      if (SingleUint64 != other.SingleUint64) return false;
+      if (SingleSint32 != other.SingleSint32) return false;
+      if (SingleSint64 != other.SingleSint64) return false;
+      if (SingleFixed32 != other.SingleFixed32) return false;
+      if (SingleFixed64 != other.SingleFixed64) return false;
+      if (SingleSfixed32 != other.SingleSfixed32) return false;
+      if (SingleSfixed64 != other.SingleSfixed64) return false;
+      if (SingleFloat != other.SingleFloat) return false;
+      if (SingleDouble != other.SingleDouble) return false;
+      if (SingleBool != other.SingleBool) return false;
+      if (SingleString != other.SingleString) return false;
+      if (SingleBytes != other.SingleBytes) return false;
+      if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false;
+      if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false;
+      if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false;
+      if (SingleNestedEnum != other.SingleNestedEnum) return false;
+      if (SingleForeignEnum != other.SingleForeignEnum) return false;
+      if (SingleImportEnum != other.SingleImportEnum) return false;
+      if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false;
+      if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false;
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false;
+      if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false;
+      if(!repeatedBool_.Equals(other.repeatedBool_)) return false;
+      if(!repeatedString_.Equals(other.repeatedString_)) return false;
+      if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false;
+      if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false;
+      if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false;
+      if(!repeatedImportMessage_.Equals(other.repeatedImportMessage_)) return false;
+      if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false;
+      if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false;
+      if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false;
+      if(!repeatedPublicImportMessage_.Equals(other.repeatedPublicImportMessage_)) return false;
+      if (OneofUint32 != other.OneofUint32) return false;
+      if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;
+      if (OneofString != other.OneofString) return false;
+      if (OneofBytes != other.OneofBytes) return false;
+      if (OneofFieldCase != other.OneofFieldCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode();
+      if (SingleInt64 != 0L) hash ^= SingleInt64.GetHashCode();
+      if (SingleUint32 != 0) hash ^= SingleUint32.GetHashCode();
+      if (SingleUint64 != 0UL) hash ^= SingleUint64.GetHashCode();
+      if (SingleSint32 != 0) hash ^= SingleSint32.GetHashCode();
+      if (SingleSint64 != 0L) hash ^= SingleSint64.GetHashCode();
+      if (SingleFixed32 != 0) hash ^= SingleFixed32.GetHashCode();
+      if (SingleFixed64 != 0UL) hash ^= SingleFixed64.GetHashCode();
+      if (SingleSfixed32 != 0) hash ^= SingleSfixed32.GetHashCode();
+      if (SingleSfixed64 != 0L) hash ^= SingleSfixed64.GetHashCode();
+      if (SingleFloat != 0F) hash ^= SingleFloat.GetHashCode();
+      if (SingleDouble != 0D) hash ^= SingleDouble.GetHashCode();
+      if (SingleBool != false) hash ^= SingleBool.GetHashCode();
+      if (SingleString.Length != 0) hash ^= SingleString.GetHashCode();
+      if (SingleBytes.Length != 0) hash ^= SingleBytes.GetHashCode();
+      if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode();
+      if (singleForeignMessage_ != null) hash ^= SingleForeignMessage.GetHashCode();
+      if (singleImportMessage_ != null) hash ^= SingleImportMessage.GetHashCode();
+      if (SingleNestedEnum != 0) hash ^= SingleNestedEnum.GetHashCode();
+      if (SingleForeignEnum != 0) hash ^= SingleForeignEnum.GetHashCode();
+      if (SingleImportEnum != 0) hash ^= SingleImportEnum.GetHashCode();
+      if (singlePublicImportMessage_ != null) hash ^= SinglePublicImportMessage.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedUint32_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      hash ^= repeatedSint32_.GetHashCode();
+      hash ^= repeatedSint64_.GetHashCode();
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedSfixed32_.GetHashCode();
+      hash ^= repeatedSfixed64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedDouble_.GetHashCode();
+      hash ^= repeatedBool_.GetHashCode();
+      hash ^= repeatedString_.GetHashCode();
+      hash ^= repeatedBytes_.GetHashCode();
+      hash ^= repeatedNestedMessage_.GetHashCode();
+      hash ^= repeatedForeignMessage_.GetHashCode();
+      hash ^= repeatedImportMessage_.GetHashCode();
+      hash ^= repeatedNestedEnum_.GetHashCode();
+      hash ^= repeatedForeignEnum_.GetHashCode();
+      hash ^= repeatedImportEnum_.GetHashCode();
+      hash ^= repeatedPublicImportMessage_.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
+      hash ^= (int) oneofFieldCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (SingleInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(SingleInt32);
+      }
+      if (SingleInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(SingleInt64);
+      }
+      if (SingleUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(SingleUint32);
+      }
+      if (SingleUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(SingleUint64);
+      }
+      if (SingleSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(SingleSint32);
+      }
+      if (SingleSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(SingleSint64);
+      }
+      if (SingleFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(SingleFixed32);
+      }
+      if (SingleFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(SingleFixed64);
+      }
+      if (SingleSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(SingleSfixed32);
+      }
+      if (SingleSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(SingleSfixed64);
+      }
+      if (SingleFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(SingleFloat);
+      }
+      if (SingleDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(SingleDouble);
+      }
+      if (SingleBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(SingleBool);
+      }
+      if (SingleString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(SingleString);
+      }
+      if (SingleBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(SingleBytes);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(SingleNestedMessage);
+      }
+      if (singleForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(SingleForeignMessage);
+      }
+      if (singleImportMessage_ != null) {
+        output.WriteRawTag(162, 1);
+        output.WriteMessage(SingleImportMessage);
+      }
+      if (SingleNestedEnum != 0) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) SingleNestedEnum);
+      }
+      if (SingleForeignEnum != 0) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) SingleForeignEnum);
+      }
+      if (SingleImportEnum != 0) {
+        output.WriteRawTag(184, 1);
+        output.WriteEnum((int) SingleImportEnum);
+      }
+      if (singlePublicImportMessage_ != null) {
+        output.WriteRawTag(210, 1);
+        output.WriteMessage(SinglePublicImportMessage);
+      }
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec);
+      repeatedImportMessage_.WriteTo(output, _repeated_repeatedImportMessage_codec);
+      repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec);
+      repeatedImportEnum_.WriteTo(output, _repeated_repeatedImportEnum_codec);
+      repeatedPublicImportMessage_.WriteTo(output, _repeated_repeatedPublicImportMessage_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (SingleInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(SingleInt32);
+      }
+      if (SingleInt64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(SingleInt64);
+      }
+      if (SingleUint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SingleUint32);
+      }
+      if (SingleUint64 != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SingleUint64);
+      }
+      if (SingleSint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt32Size(SingleSint32);
+      }
+      if (SingleSint64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt64Size(SingleSint64);
+      }
+      if (SingleFixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (SingleFixed64 != 0UL) {
+        size += 1 + 8;
+      }
+      if (SingleSfixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (SingleSfixed64 != 0L) {
+        size += 1 + 8;
+      }
+      if (SingleFloat != 0F) {
+        size += 1 + 4;
+      }
+      if (SingleDouble != 0D) {
+        size += 1 + 8;
+      }
+      if (SingleBool != false) {
+        size += 1 + 1;
+      }
+      if (SingleString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(SingleString);
+      }
+      if (SingleBytes.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(SingleBytes);
+      }
+      if (singleNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage);
+      }
+      if (singleForeignMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleForeignMessage);
+      }
+      if (singleImportMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleImportMessage);
+      }
+      if (SingleNestedEnum != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleNestedEnum);
+      }
+      if (SingleForeignEnum != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleForeignEnum);
+      }
+      if (SingleImportEnum != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleImportEnum);
+      }
+      if (singlePublicImportMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SinglePublicImportMessage);
+      }
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec);
+      size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec);
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec);
+      size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec);
+      size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec);
+      size += repeatedString_.CalculateSize(_repeated_repeatedString_codec);
+      size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec);
+      size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec);
+      size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec);
+      size += repeatedImportMessage_.CalculateSize(_repeated_repeatedImportMessage_codec);
+      size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec);
+      size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec);
+      size += repeatedImportEnum_.CalculateSize(_repeated_repeatedImportEnum_codec);
+      size += repeatedPublicImportMessage_.CalculateSize(_repeated_repeatedPublicImportMessage_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.SingleInt32 != 0) {
+        SingleInt32 = other.SingleInt32;
+      }
+      if (other.SingleInt64 != 0L) {
+        SingleInt64 = other.SingleInt64;
+      }
+      if (other.SingleUint32 != 0) {
+        SingleUint32 = other.SingleUint32;
+      }
+      if (other.SingleUint64 != 0UL) {
+        SingleUint64 = other.SingleUint64;
+      }
+      if (other.SingleSint32 != 0) {
+        SingleSint32 = other.SingleSint32;
+      }
+      if (other.SingleSint64 != 0L) {
+        SingleSint64 = other.SingleSint64;
+      }
+      if (other.SingleFixed32 != 0) {
+        SingleFixed32 = other.SingleFixed32;
+      }
+      if (other.SingleFixed64 != 0UL) {
+        SingleFixed64 = other.SingleFixed64;
+      }
+      if (other.SingleSfixed32 != 0) {
+        SingleSfixed32 = other.SingleSfixed32;
+      }
+      if (other.SingleSfixed64 != 0L) {
+        SingleSfixed64 = other.SingleSfixed64;
+      }
+      if (other.SingleFloat != 0F) {
+        SingleFloat = other.SingleFloat;
+      }
+      if (other.SingleDouble != 0D) {
+        SingleDouble = other.SingleDouble;
+      }
+      if (other.SingleBool != false) {
+        SingleBool = other.SingleBool;
+      }
+      if (other.SingleString.Length != 0) {
+        SingleString = other.SingleString;
+      }
+      if (other.SingleBytes.Length != 0) {
+        SingleBytes = other.SingleBytes;
+      }
+      if (other.singleNestedMessage_ != null) {
+        if (singleNestedMessage_ == null) {
+          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+        }
+        SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
+      }
+      if (other.singleForeignMessage_ != null) {
+        if (singleForeignMessage_ == null) {
+          singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+        }
+        SingleForeignMessage.MergeFrom(other.SingleForeignMessage);
+      }
+      if (other.singleImportMessage_ != null) {
+        if (singleImportMessage_ == null) {
+          singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+        }
+        SingleImportMessage.MergeFrom(other.SingleImportMessage);
+      }
+      if (other.SingleNestedEnum != 0) {
+        SingleNestedEnum = other.SingleNestedEnum;
+      }
+      if (other.SingleForeignEnum != 0) {
+        SingleForeignEnum = other.SingleForeignEnum;
+      }
+      if (other.SingleImportEnum != 0) {
+        SingleImportEnum = other.SingleImportEnum;
+      }
+      if (other.singlePublicImportMessage_ != null) {
+        if (singlePublicImportMessage_ == null) {
+          singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+        }
+        SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage);
+      }
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedUint32_.Add(other.repeatedUint32_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+      repeatedSint32_.Add(other.repeatedSint32_);
+      repeatedSint64_.Add(other.repeatedSint64_);
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedSfixed32_.Add(other.repeatedSfixed32_);
+      repeatedSfixed64_.Add(other.repeatedSfixed64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedDouble_.Add(other.repeatedDouble_);
+      repeatedBool_.Add(other.repeatedBool_);
+      repeatedString_.Add(other.repeatedString_);
+      repeatedBytes_.Add(other.repeatedBytes_);
+      repeatedNestedMessage_.Add(other.repeatedNestedMessage_);
+      repeatedForeignMessage_.Add(other.repeatedForeignMessage_);
+      repeatedImportMessage_.Add(other.repeatedImportMessage_);
+      repeatedNestedEnum_.Add(other.repeatedNestedEnum_);
+      repeatedForeignEnum_.Add(other.repeatedForeignEnum_);
+      repeatedImportEnum_.Add(other.repeatedImportEnum_);
+      repeatedPublicImportMessage_.Add(other.repeatedPublicImportMessage_);
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage;
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            SingleInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            SingleInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            SingleUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            SingleUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            SingleSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            SingleSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            SingleFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            SingleFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            SingleSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            SingleSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            SingleFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            SingleDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            SingleBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            SingleString = input.ReadString();
+            break;
+          }
+          case 122: {
+            SingleBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (singleNestedMessage_ == null) {
+              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(singleNestedMessage_);
+            break;
+          }
+          case 154: {
+            if (singleForeignMessage_ == null) {
+              singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(singleForeignMessage_);
+            break;
+          }
+          case 162: {
+            if (singleImportMessage_ == null) {
+              singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+            }
+            input.ReadMessage(singleImportMessage_);
+            break;
+          }
+          case 168: {
+            singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 184: {
+            singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
+            break;
+          }
+          case 210: {
+            if (singlePublicImportMessage_ == null) {
+              singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+            }
+            input.ReadMessage(singlePublicImportMessage_);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 402: {
+            repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 426:
+          case 424: {
+            repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedPublicImportMessage_.AddEntriesFrom(input, _repeated_repeatedPublicImportMessage_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the TestAllTypes message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum NestedEnum {
+        [pbr::OriginalName("NESTED_ENUM_UNSPECIFIED")] Unspecified = 0,
+        [pbr::OriginalName("FOO")] Foo = 1,
+        [pbr::OriginalName("BAR")] Bar = 2,
+        [pbr::OriginalName("BAZ")] Baz = 3,
+        /// <summary>
+        ///  Intentionally negative.
+        /// </summary>
+        [pbr::OriginalName("NEG")] Neg = -1,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          bb_ = other.bb_;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        /// <summary>Field number for the "bb" field.</summary>
+        public const int BbFieldNumber = 1;
+        private int bb_;
+        /// <summary>
+        ///  The field name "b" fails to compile in proto1 because it conflicts with
+        ///  a local variable named "b" in one of the generated methods.  Doh.
+        ///  This file needs to compile in proto1 to test backwards-compatibility.
+        /// </summary>
+        public int Bb {
+          get { return bb_; }
+          set {
+            bb_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Bb != other.Bb) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Bb != 0) hash ^= Bb.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Bb != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Bb != 0) {
+            Bb = other.Bb;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  This proto includes a recusively nested message.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
+    private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
+    public static pb::MessageParser<NestedTestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public NestedTestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public NestedTestAllTypes(NestedTestAllTypes other) : this() {
+      Child = other.child_ != null ? other.Child.Clone() : null;
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
+      repeatedChild_ = other.repeatedChild_.Clone();
+    }
+
+    public NestedTestAllTypes Clone() {
+      return new NestedTestAllTypes(this);
+    }
+
+    /// <summary>Field number for the "child" field.</summary>
+    public const int ChildFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_;
+    public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child {
+      get { return child_; }
+      set {
+        child_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "payload" field.</summary>
+    public const int PayloadFieldNumber = 2;
+    private global::Google.Protobuf.TestProtos.TestAllTypes payload_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "repeated_child" field.</summary>
+    public const int RepeatedChildFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.NestedTestAllTypes> _repeated_repeatedChild_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> repeatedChild_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> RepeatedChild {
+      get { return repeatedChild_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as NestedTestAllTypes);
+    }
+
+    public bool Equals(NestedTestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Child, other.Child)) return false;
+      if (!object.Equals(Payload, other.Payload)) return false;
+      if(!repeatedChild_.Equals(other.repeatedChild_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (child_ != null) hash ^= Child.GetHashCode();
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      hash ^= repeatedChild_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (child_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Child);
+      }
+      if (payload_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Payload);
+      }
+      repeatedChild_.WriteTo(output, _repeated_repeatedChild_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (child_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child);
+      }
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec);
+      return size;
+    }
+
+    public void MergeFrom(NestedTestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.child_ != null) {
+        if (child_ == null) {
+          child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+        }
+        Child.MergeFrom(other.Child);
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+        }
+        Payload.MergeFrom(other.Payload);
+      }
+      repeatedChild_.Add(other.repeatedChild_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (child_ == null) {
+              child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+            }
+            input.ReadMessage(child_);
+            break;
+          }
+          case 18: {
+            if (payload_ == null) {
+              payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            }
+            input.ReadMessage(payload_);
+            break;
+          }
+          case 26: {
+            repeatedChild_.AddEntriesFrom(input, _repeated_repeatedChild_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields> {
+    private static readonly pb::MessageParser<TestDeprecatedFields> _parser = new pb::MessageParser<TestDeprecatedFields>(() => new TestDeprecatedFields());
+    public static pb::MessageParser<TestDeprecatedFields> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestDeprecatedFields() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestDeprecatedFields(TestDeprecatedFields other) : this() {
+      deprecatedInt32_ = other.deprecatedInt32_;
+    }
+
+    public TestDeprecatedFields Clone() {
+      return new TestDeprecatedFields(this);
+    }
+
+    /// <summary>Field number for the "deprecated_int32" field.</summary>
+    public const int DeprecatedInt32FieldNumber = 1;
+    private int deprecatedInt32_;
+    [global::System.ObsoleteAttribute()]
+    public int DeprecatedInt32 {
+      get { return deprecatedInt32_; }
+      set {
+        deprecatedInt32_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestDeprecatedFields);
+    }
+
+    public bool Equals(TestDeprecatedFields other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (DeprecatedInt32 != other.DeprecatedInt32) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (DeprecatedInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DeprecatedInt32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (DeprecatedInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestDeprecatedFields other) {
+      if (other == null) {
+        return;
+      }
+      if (other.DeprecatedInt32 != 0) {
+        DeprecatedInt32 = other.DeprecatedInt32;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            DeprecatedInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Define these after TestAllTypes to make sure the compiler can handle
+  ///  that.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+    private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ForeignMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ForeignMessage(ForeignMessage other) : this() {
+      c_ = other.c_;
+    }
+
+    public ForeignMessage Clone() {
+      return new ForeignMessage(this);
+    }
+
+    /// <summary>Field number for the "c" field.</summary>
+    public const int CFieldNumber = 1;
+    private int c_;
+    public int C {
+      get { return c_; }
+      set {
+        c_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ForeignMessage);
+    }
+
+    public bool Equals(ForeignMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (C != other.C) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (C != 0) hash ^= C.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (C != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ForeignMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.C != 0) {
+        C = other.C;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields> {
+    private static readonly pb::MessageParser<TestReservedFields> _parser = new pb::MessageParser<TestReservedFields>(() => new TestReservedFields());
+    public static pb::MessageParser<TestReservedFields> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestReservedFields() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestReservedFields(TestReservedFields other) : this() {
+    }
+
+    public TestReservedFields Clone() {
+      return new TestReservedFields(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestReservedFields);
+    }
+
+    public bool Equals(TestReservedFields other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(TestReservedFields other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test that we can use NestedMessage from outside TestAllTypes.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested> {
+    private static readonly pb::MessageParser<TestForeignNested> _parser = new pb::MessageParser<TestForeignNested>(() => new TestForeignNested());
+    public static pb::MessageParser<TestForeignNested> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestForeignNested() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestForeignNested(TestForeignNested other) : this() {
+      ForeignNested = other.foreignNested_ != null ? other.ForeignNested.Clone() : null;
+    }
+
+    public TestForeignNested Clone() {
+      return new TestForeignNested(this);
+    }
+
+    /// <summary>Field number for the "foreign_nested" field.</summary>
+    public const int ForeignNestedFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested {
+      get { return foreignNested_; }
+      set {
+        foreignNested_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestForeignNested);
+    }
+
+    public bool Equals(TestForeignNested other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(ForeignNested, other.ForeignNested)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (foreignNested_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(ForeignNested);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (foreignNested_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestForeignNested other) {
+      if (other == null) {
+        return;
+      }
+      if (other.foreignNested_ != null) {
+        if (foreignNested_ == null) {
+          foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+        }
+        ForeignNested.MergeFrom(other.ForeignNested);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (foreignNested_ == null) {
+              foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(foreignNested_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test that really large tag numbers don't break anything.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber> {
+    private static readonly pb::MessageParser<TestReallyLargeTagNumber> _parser = new pb::MessageParser<TestReallyLargeTagNumber>(() => new TestReallyLargeTagNumber());
+    public static pb::MessageParser<TestReallyLargeTagNumber> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestReallyLargeTagNumber() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() {
+      a_ = other.a_;
+      bb_ = other.bb_;
+    }
+
+    public TestReallyLargeTagNumber Clone() {
+      return new TestReallyLargeTagNumber(this);
+    }
+
+    /// <summary>Field number for the "a" field.</summary>
+    public const int AFieldNumber = 1;
+    private int a_;
+    /// <summary>
+    ///  The largest possible tag number is 2^28 - 1, since the wire format uses
+    ///  three bits to communicate wire type.
+    /// </summary>
+    public int A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "bb" field.</summary>
+    public const int BbFieldNumber = 268435455;
+    private int bb_;
+    public int Bb {
+      get { return bb_; }
+      set {
+        bb_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestReallyLargeTagNumber);
+    }
+
+    public bool Equals(TestReallyLargeTagNumber other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (A != other.A) return false;
+      if (Bb != other.Bb) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (A != 0) hash ^= A.GetHashCode();
+      if (Bb != 0) hash ^= Bb.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (A != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (Bb != 0) {
+        output.WriteRawTag(248, 255, 255, 255, 7);
+        output.WriteInt32(Bb);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (A != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
+      }
+      if (Bb != 0) {
+        size += 5 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestReallyLargeTagNumber other) {
+      if (other == null) {
+        return;
+      }
+      if (other.A != 0) {
+        A = other.A;
+      }
+      if (other.Bb != 0) {
+        Bb = other.Bb;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 2147483640: {
+            Bb = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage> {
+    private static readonly pb::MessageParser<TestRecursiveMessage> _parser = new pb::MessageParser<TestRecursiveMessage>(() => new TestRecursiveMessage());
+    public static pb::MessageParser<TestRecursiveMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestRecursiveMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestRecursiveMessage(TestRecursiveMessage other) : this() {
+      A = other.a_ != null ? other.A.Clone() : null;
+      i_ = other.i_;
+    }
+
+    public TestRecursiveMessage Clone() {
+      return new TestRecursiveMessage(this);
+    }
+
+    /// <summary>Field number for the "a" field.</summary>
+    public const int AFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_;
+    public global::Google.Protobuf.TestProtos.TestRecursiveMessage A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "i" field.</summary>
+    public const int IFieldNumber = 2;
+    private int i_;
+    public int I {
+      get { return i_; }
+      set {
+        i_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestRecursiveMessage);
+    }
+
+    public bool Equals(TestRecursiveMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(A, other.A)) return false;
+      if (I != other.I) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (a_ != null) hash ^= A.GetHashCode();
+      if (I != 0) hash ^= I.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (I != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(I);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (a_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
+      }
+      if (I != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(I);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestRecursiveMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.a_ != null) {
+        if (a_ == null) {
+          a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+        }
+        A.MergeFrom(other.A);
+      }
+      if (other.I != 0) {
+        I = other.I;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (a_ == null) {
+              a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+            }
+            input.ReadMessage(a_);
+            break;
+          }
+          case 16: {
+            I = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test that mutual recursion works.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA> {
+    private static readonly pb::MessageParser<TestMutualRecursionA> _parser = new pb::MessageParser<TestMutualRecursionA>(() => new TestMutualRecursionA());
+    public static pb::MessageParser<TestMutualRecursionA> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[8]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMutualRecursionA() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMutualRecursionA(TestMutualRecursionA other) : this() {
+      Bb = other.bb_ != null ? other.Bb.Clone() : null;
+    }
+
+    public TestMutualRecursionA Clone() {
+      return new TestMutualRecursionA(this);
+    }
+
+    /// <summary>Field number for the "bb" field.</summary>
+    public const int BbFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_;
+    public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb {
+      get { return bb_; }
+      set {
+        bb_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMutualRecursionA);
+    }
+
+    public bool Equals(TestMutualRecursionA other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Bb, other.Bb)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (bb_ != null) hash ^= Bb.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (bb_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Bb);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (bb_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMutualRecursionA other) {
+      if (other == null) {
+        return;
+      }
+      if (other.bb_ != null) {
+        if (bb_ == null) {
+          bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+        }
+        Bb.MergeFrom(other.Bb);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (bb_ == null) {
+              bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+            }
+            input.ReadMessage(bb_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB> {
+    private static readonly pb::MessageParser<TestMutualRecursionB> _parser = new pb::MessageParser<TestMutualRecursionB>(() => new TestMutualRecursionB());
+    public static pb::MessageParser<TestMutualRecursionB> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[9]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMutualRecursionB() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMutualRecursionB(TestMutualRecursionB other) : this() {
+      A = other.a_ != null ? other.A.Clone() : null;
+      optionalInt32_ = other.optionalInt32_;
+    }
+
+    public TestMutualRecursionB Clone() {
+      return new TestMutualRecursionB(this);
+    }
+
+    /// <summary>Field number for the "a" field.</summary>
+    public const int AFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_;
+    public global::Google.Protobuf.TestProtos.TestMutualRecursionA A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_int32" field.</summary>
+    public const int OptionalInt32FieldNumber = 2;
+    private int optionalInt32_;
+    public int OptionalInt32 {
+      get { return optionalInt32_; }
+      set {
+        optionalInt32_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMutualRecursionB);
+    }
+
+    public bool Equals(TestMutualRecursionB other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(A, other.A)) return false;
+      if (OptionalInt32 != other.OptionalInt32) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (a_ != null) hash ^= A.GetHashCode();
+      if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(OptionalInt32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (a_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
+      }
+      if (OptionalInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMutualRecursionB other) {
+      if (other == null) {
+        return;
+      }
+      if (other.a_ != null) {
+        if (a_ == null) {
+          a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+        }
+        A.MergeFrom(other.A);
+      }
+      if (other.OptionalInt32 != 0) {
+        OptionalInt32 = other.OptionalInt32;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (a_ == null) {
+              a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+            }
+            input.ReadMessage(a_);
+            break;
+          }
+          case 16: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test message with CamelCase field names.  This violates Protocol Buffer
+  ///  standard style.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames> {
+    private static readonly pb::MessageParser<TestCamelCaseFieldNames> _parser = new pb::MessageParser<TestCamelCaseFieldNames>(() => new TestCamelCaseFieldNames());
+    public static pb::MessageParser<TestCamelCaseFieldNames> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[10]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestCamelCaseFieldNames() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() {
+      primitiveField_ = other.primitiveField_;
+      stringField_ = other.stringField_;
+      enumField_ = other.enumField_;
+      MessageField = other.messageField_ != null ? other.MessageField.Clone() : null;
+      repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone();
+      repeatedStringField_ = other.repeatedStringField_.Clone();
+      repeatedEnumField_ = other.repeatedEnumField_.Clone();
+      repeatedMessageField_ = other.repeatedMessageField_.Clone();
+    }
+
+    public TestCamelCaseFieldNames Clone() {
+      return new TestCamelCaseFieldNames(this);
+    }
+
+    /// <summary>Field number for the "PrimitiveField" field.</summary>
+    public const int PrimitiveFieldFieldNumber = 1;
+    private int primitiveField_;
+    public int PrimitiveField {
+      get { return primitiveField_; }
+      set {
+        primitiveField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "StringField" field.</summary>
+    public const int StringFieldFieldNumber = 2;
+    private string stringField_ = "";
+    public string StringField {
+      get { return stringField_; }
+      set {
+        stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "EnumField" field.</summary>
+    public const int EnumFieldFieldNumber = 3;
+    private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = 0;
+    public global::Google.Protobuf.TestProtos.ForeignEnum EnumField {
+      get { return enumField_; }
+      set {
+        enumField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "MessageField" field.</summary>
+    public const int MessageFieldFieldNumber = 4;
+    private global::Google.Protobuf.TestProtos.ForeignMessage messageField_;
+    public global::Google.Protobuf.TestProtos.ForeignMessage MessageField {
+      get { return messageField_; }
+      set {
+        messageField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "RepeatedPrimitiveField" field.</summary>
+    public const int RepeatedPrimitiveFieldFieldNumber = 7;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedPrimitiveField_codec
+        = pb::FieldCodec.ForInt32(58);
+    private readonly pbc::RepeatedField<int> repeatedPrimitiveField_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedPrimitiveField {
+      get { return repeatedPrimitiveField_; }
+    }
+
+    /// <summary>Field number for the "RepeatedStringField" field.</summary>
+    public const int RepeatedStringFieldFieldNumber = 8;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedStringField_codec
+        = pb::FieldCodec.ForString(66);
+    private readonly pbc::RepeatedField<string> repeatedStringField_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedStringField {
+      get { return repeatedStringField_; }
+    }
+
+    /// <summary>Field number for the "RepeatedEnumField" field.</summary>
+    public const int RepeatedEnumFieldFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedEnumField_codec
+        = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedEnumField {
+      get { return repeatedEnumField_; }
+    }
+
+    /// <summary>Field number for the "RepeatedMessageField" field.</summary>
+    public const int RepeatedMessageFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignMessage> _repeated_repeatedMessageField_codec
+        = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedMessageField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedMessageField {
+      get { return repeatedMessageField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestCamelCaseFieldNames);
+    }
+
+    public bool Equals(TestCamelCaseFieldNames other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PrimitiveField != other.PrimitiveField) return false;
+      if (StringField != other.StringField) return false;
+      if (EnumField != other.EnumField) return false;
+      if (!object.Equals(MessageField, other.MessageField)) return false;
+      if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false;
+      if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false;
+      if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false;
+      if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode();
+      if (StringField.Length != 0) hash ^= StringField.GetHashCode();
+      if (EnumField != 0) hash ^= EnumField.GetHashCode();
+      if (messageField_ != null) hash ^= MessageField.GetHashCode();
+      hash ^= repeatedPrimitiveField_.GetHashCode();
+      hash ^= repeatedStringField_.GetHashCode();
+      hash ^= repeatedEnumField_.GetHashCode();
+      hash ^= repeatedMessageField_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PrimitiveField != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveField);
+      }
+      if (StringField.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(StringField);
+      }
+      if (EnumField != 0) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) EnumField);
+      }
+      if (messageField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(MessageField);
+      }
+      repeatedPrimitiveField_.WriteTo(output, _repeated_repeatedPrimitiveField_codec);
+      repeatedStringField_.WriteTo(output, _repeated_repeatedStringField_codec);
+      repeatedEnumField_.WriteTo(output, _repeated_repeatedEnumField_codec);
+      repeatedMessageField_.WriteTo(output, _repeated_repeatedMessageField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PrimitiveField != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveField);
+      }
+      if (StringField.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField);
+      }
+      if (EnumField != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField);
+      }
+      if (messageField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField);
+      }
+      size += repeatedPrimitiveField_.CalculateSize(_repeated_repeatedPrimitiveField_codec);
+      size += repeatedStringField_.CalculateSize(_repeated_repeatedStringField_codec);
+      size += repeatedEnumField_.CalculateSize(_repeated_repeatedEnumField_codec);
+      size += repeatedMessageField_.CalculateSize(_repeated_repeatedMessageField_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestCamelCaseFieldNames other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PrimitiveField != 0) {
+        PrimitiveField = other.PrimitiveField;
+      }
+      if (other.StringField.Length != 0) {
+        StringField = other.StringField;
+      }
+      if (other.EnumField != 0) {
+        EnumField = other.EnumField;
+      }
+      if (other.messageField_ != null) {
+        if (messageField_ == null) {
+          messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+        }
+        MessageField.MergeFrom(other.MessageField);
+      }
+      repeatedPrimitiveField_.Add(other.repeatedPrimitiveField_);
+      repeatedStringField_.Add(other.repeatedStringField_);
+      repeatedEnumField_.Add(other.repeatedEnumField_);
+      repeatedMessageField_.Add(other.repeatedMessageField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            PrimitiveField = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            StringField = input.ReadString();
+            break;
+          }
+          case 24: {
+            enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 34: {
+            if (messageField_ == null) {
+              messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(messageField_);
+            break;
+          }
+          case 58:
+          case 56: {
+            repeatedPrimitiveField_.AddEntriesFrom(input, _repeated_repeatedPrimitiveField_codec);
+            break;
+          }
+          case 66: {
+            repeatedStringField_.AddEntriesFrom(input, _repeated_repeatedStringField_codec);
+            break;
+          }
+          case 74:
+          case 72: {
+            repeatedEnumField_.AddEntriesFrom(input, _repeated_repeatedEnumField_codec);
+            break;
+          }
+          case 82: {
+            repeatedMessageField_.AddEntriesFrom(input, _repeated_repeatedMessageField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  We list fields out of order, to ensure that we're using field number and not
+  ///  field index to determine serialization order.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestFieldOrderings : pb::IMessage<TestFieldOrderings> {
+    private static readonly pb::MessageParser<TestFieldOrderings> _parser = new pb::MessageParser<TestFieldOrderings>(() => new TestFieldOrderings());
+    public static pb::MessageParser<TestFieldOrderings> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[11]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestFieldOrderings() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestFieldOrderings(TestFieldOrderings other) : this() {
+      myString_ = other.myString_;
+      myInt_ = other.myInt_;
+      myFloat_ = other.myFloat_;
+      SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null;
+    }
+
+    public TestFieldOrderings Clone() {
+      return new TestFieldOrderings(this);
+    }
+
+    /// <summary>Field number for the "my_string" field.</summary>
+    public const int MyStringFieldNumber = 11;
+    private string myString_ = "";
+    public string MyString {
+      get { return myString_; }
+      set {
+        myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "my_int" field.</summary>
+    public const int MyIntFieldNumber = 1;
+    private long myInt_;
+    public long MyInt {
+      get { return myInt_; }
+      set {
+        myInt_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "my_float" field.</summary>
+    public const int MyFloatFieldNumber = 101;
+    private float myFloat_;
+    public float MyFloat {
+      get { return myFloat_; }
+      set {
+        myFloat_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "single_nested_message" field.</summary>
+    public const int SingleNestedMessageFieldNumber = 200;
+    private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_;
+    public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage {
+      get { return singleNestedMessage_; }
+      set {
+        singleNestedMessage_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestFieldOrderings);
+    }
+
+    public bool Equals(TestFieldOrderings other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (MyString != other.MyString) return false;
+      if (MyInt != other.MyInt) return false;
+      if (MyFloat != other.MyFloat) return false;
+      if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (MyString.Length != 0) hash ^= MyString.GetHashCode();
+      if (MyInt != 0L) hash ^= MyInt.GetHashCode();
+      if (MyFloat != 0F) hash ^= MyFloat.GetHashCode();
+      if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (MyInt != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(MyInt);
+      }
+      if (MyString.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(MyString);
+      }
+      if (MyFloat != 0F) {
+        output.WriteRawTag(173, 6);
+        output.WriteFloat(MyFloat);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(194, 12);
+        output.WriteMessage(SingleNestedMessage);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (MyString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString);
+      }
+      if (MyInt != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(MyInt);
+      }
+      if (MyFloat != 0F) {
+        size += 2 + 4;
+      }
+      if (singleNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestFieldOrderings other) {
+      if (other == null) {
+        return;
+      }
+      if (other.MyString.Length != 0) {
+        MyString = other.MyString;
+      }
+      if (other.MyInt != 0L) {
+        MyInt = other.MyInt;
+      }
+      if (other.MyFloat != 0F) {
+        MyFloat = other.MyFloat;
+      }
+      if (other.singleNestedMessage_ != null) {
+        if (singleNestedMessage_ == null) {
+          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+        }
+        SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            MyInt = input.ReadInt64();
+            break;
+          }
+          case 90: {
+            MyString = input.ReadString();
+            break;
+          }
+          case 813: {
+            MyFloat = input.ReadFloat();
+            break;
+          }
+          case 1602: {
+            if (singleNestedMessage_ == null) {
+              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+            }
+            input.ReadMessage(singleNestedMessage_);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the TestFieldOrderings message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          oo_ = other.oo_;
+          bb_ = other.bb_;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        /// <summary>Field number for the "oo" field.</summary>
+        public const int OoFieldNumber = 2;
+        private long oo_;
+        public long Oo {
+          get { return oo_; }
+          set {
+            oo_ = value;
+          }
+        }
+
+        /// <summary>Field number for the "bb" field.</summary>
+        public const int BbFieldNumber = 1;
+        private int bb_;
+        /// <summary>
+        ///  The field name "b" fails to compile in proto1 because it conflicts with
+        ///  a local variable named "b" in one of the generated methods.  Doh.
+        ///  This file needs to compile in proto1 to test backwards-compatibility.
+        /// </summary>
+        public int Bb {
+          get { return bb_; }
+          set {
+            bb_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Oo != other.Oo) return false;
+          if (Bb != other.Bb) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Oo != 0L) hash ^= Oo.GetHashCode();
+          if (Bb != 0) hash ^= Bb.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (Oo != 0L) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Oo);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Oo != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Oo);
+          }
+          if (Bb != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Oo != 0L) {
+            Oo = other.Oo;
+          }
+          if (other.Bb != 0) {
+            Bb = other.Bb;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Oo = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage> {
+    private static readonly pb::MessageParser<SparseEnumMessage> _parser = new pb::MessageParser<SparseEnumMessage>(() => new SparseEnumMessage());
+    public static pb::MessageParser<SparseEnumMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[12]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SparseEnumMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SparseEnumMessage(SparseEnumMessage other) : this() {
+      sparseEnum_ = other.sparseEnum_;
+    }
+
+    public SparseEnumMessage Clone() {
+      return new SparseEnumMessage(this);
+    }
+
+    /// <summary>Field number for the "sparse_enum" field.</summary>
+    public const int SparseEnumFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = 0;
+    public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum {
+      get { return sparseEnum_; }
+      set {
+        sparseEnum_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SparseEnumMessage);
+    }
+
+    public bool Equals(SparseEnumMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (SparseEnum != other.SparseEnum) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (SparseEnum != 0) hash ^= SparseEnum.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (SparseEnum != 0) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) SparseEnum);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (SparseEnum != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SparseEnumMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.SparseEnum != 0) {
+        SparseEnum = other.SparseEnum;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test String and Bytes: string is for valid UTF-8 strings
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneString : pb::IMessage<OneString> {
+    private static readonly pb::MessageParser<OneString> _parser = new pb::MessageParser<OneString>(() => new OneString());
+    public static pb::MessageParser<OneString> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[13]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneString() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneString(OneString other) : this() {
+      data_ = other.data_;
+    }
+
+    public OneString Clone() {
+      return new OneString(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private string data_ = "";
+    public string Data {
+      get { return data_; }
+      set {
+        data_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneString);
+    }
+
+    public bool Equals(OneString other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneString other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MoreString : pb::IMessage<MoreString> {
+    private static readonly pb::MessageParser<MoreString> _parser = new pb::MessageParser<MoreString>(() => new MoreString());
+    public static pb::MessageParser<MoreString> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[14]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MoreString() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MoreString(MoreString other) : this() {
+      data_ = other.data_.Clone();
+    }
+
+    public MoreString Clone() {
+      return new MoreString(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private static readonly pb::FieldCodec<string> _repeated_data_codec
+        = pb::FieldCodec.ForString(10);
+    private readonly pbc::RepeatedField<string> data_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> Data {
+      get { return data_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MoreString);
+    }
+
+    public bool Equals(MoreString other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!data_.Equals(other.data_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= data_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      data_.WriteTo(output, _repeated_data_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += data_.CalculateSize(_repeated_data_codec);
+      return size;
+    }
+
+    public void MergeFrom(MoreString other) {
+      if (other == null) {
+        return;
+      }
+      data_.Add(other.data_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            data_.AddEntriesFrom(input, _repeated_data_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneBytes : pb::IMessage<OneBytes> {
+    private static readonly pb::MessageParser<OneBytes> _parser = new pb::MessageParser<OneBytes>(() => new OneBytes());
+    public static pb::MessageParser<OneBytes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[15]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneBytes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneBytes(OneBytes other) : this() {
+      data_ = other.data_;
+    }
+
+    public OneBytes Clone() {
+      return new OneBytes(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private pb::ByteString data_ = pb::ByteString.Empty;
+    public pb::ByteString Data {
+      get { return data_; }
+      set {
+        data_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneBytes);
+    }
+
+    public bool Equals(OneBytes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneBytes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MoreBytes : pb::IMessage<MoreBytes> {
+    private static readonly pb::MessageParser<MoreBytes> _parser = new pb::MessageParser<MoreBytes>(() => new MoreBytes());
+    public static pb::MessageParser<MoreBytes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[16]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MoreBytes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MoreBytes(MoreBytes other) : this() {
+      data_ = other.data_;
+    }
+
+    public MoreBytes Clone() {
+      return new MoreBytes(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private pb::ByteString data_ = pb::ByteString.Empty;
+    public pb::ByteString Data {
+      get { return data_; }
+      set {
+        data_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MoreBytes);
+    }
+
+    public bool Equals(MoreBytes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(MoreBytes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test int32, uint32, int64, uint64, and bool are all compatible
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int32Message : pb::IMessage<Int32Message> {
+    private static readonly pb::MessageParser<Int32Message> _parser = new pb::MessageParser<Int32Message>(() => new Int32Message());
+    public static pb::MessageParser<Int32Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[17]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int32Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int32Message(Int32Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Int32Message Clone() {
+      return new Int32Message(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private int data_;
+    public int Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int32Message);
+    }
+
+    public bool Equals(Int32Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int32Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Uint32Message : pb::IMessage<Uint32Message> {
+    private static readonly pb::MessageParser<Uint32Message> _parser = new pb::MessageParser<Uint32Message>(() => new Uint32Message());
+    public static pb::MessageParser<Uint32Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[18]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Uint32Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Uint32Message(Uint32Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Uint32Message Clone() {
+      return new Uint32Message(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private uint data_;
+    public uint Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Uint32Message);
+    }
+
+    public bool Equals(Uint32Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Uint32Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int64Message : pb::IMessage<Int64Message> {
+    private static readonly pb::MessageParser<Int64Message> _parser = new pb::MessageParser<Int64Message>(() => new Int64Message());
+    public static pb::MessageParser<Int64Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[19]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int64Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int64Message(Int64Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Int64Message Clone() {
+      return new Int64Message(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private long data_;
+    public long Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int64Message);
+    }
+
+    public bool Equals(Int64Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0L) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int64Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0L) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Uint64Message : pb::IMessage<Uint64Message> {
+    private static readonly pb::MessageParser<Uint64Message> _parser = new pb::MessageParser<Uint64Message>(() => new Uint64Message());
+    public static pb::MessageParser<Uint64Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[20]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Uint64Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Uint64Message(Uint64Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Uint64Message Clone() {
+      return new Uint64Message(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private ulong data_;
+    public ulong Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Uint64Message);
+    }
+
+    public bool Equals(Uint64Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0UL) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0UL) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Uint64Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0UL) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BoolMessage : pb::IMessage<BoolMessage> {
+    private static readonly pb::MessageParser<BoolMessage> _parser = new pb::MessageParser<BoolMessage>(() => new BoolMessage());
+    public static pb::MessageParser<BoolMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[21]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BoolMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BoolMessage(BoolMessage other) : this() {
+      data_ = other.data_;
+    }
+
+    public BoolMessage Clone() {
+      return new BoolMessage(this);
+    }
+
+    /// <summary>Field number for the "data" field.</summary>
+    public const int DataFieldNumber = 1;
+    private bool data_;
+    public bool Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BoolMessage);
+    }
+
+    public bool Equals(BoolMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != false) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(BoolMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != false) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test oneofs.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestOneof : pb::IMessage<TestOneof> {
+    private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
+    public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[22]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestOneof() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestOneof(TestOneof other) : this() {
+      switch (other.FooCase) {
+        case FooOneofCase.FooInt:
+          FooInt = other.FooInt;
+          break;
+        case FooOneofCase.FooString:
+          FooString = other.FooString;
+          break;
+        case FooOneofCase.FooMessage:
+          FooMessage = other.FooMessage.Clone();
+          break;
+      }
+
+    }
+
+    public TestOneof Clone() {
+      return new TestOneof(this);
+    }
+
+    /// <summary>Field number for the "foo_int" field.</summary>
+    public const int FooIntFieldNumber = 1;
+    public int FooInt {
+      get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; }
+      set {
+        foo_ = value;
+        fooCase_ = FooOneofCase.FooInt;
+      }
+    }
+
+    /// <summary>Field number for the "foo_string" field.</summary>
+    public const int FooStringFieldNumber = 2;
+    public string FooString {
+      get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; }
+      set {
+        foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        fooCase_ = FooOneofCase.FooString;
+      }
+    }
+
+    /// <summary>Field number for the "foo_message" field.</summary>
+    public const int FooMessageFieldNumber = 3;
+    public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage {
+      get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; }
+      set {
+        foo_ = value;
+        fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage;
+      }
+    }
+
+    private object foo_;
+    /// <summary>Enum of possible cases for the "foo" oneof.</summary>
+    public enum FooOneofCase {
+      None = 0,
+      FooInt = 1,
+      FooString = 2,
+      FooMessage = 3,
+    }
+    private FooOneofCase fooCase_ = FooOneofCase.None;
+    public FooOneofCase FooCase {
+      get { return fooCase_; }
+    }
+
+    public void ClearFoo() {
+      fooCase_ = FooOneofCase.None;
+      foo_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestOneof);
+    }
+
+    public bool Equals(TestOneof other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (FooInt != other.FooInt) return false;
+      if (FooString != other.FooString) return false;
+      if (!object.Equals(FooMessage, other.FooMessage)) return false;
+      if (FooCase != other.FooCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooString) hash ^= FooString.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
+      hash ^= (int) fooCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (fooCase_ == FooOneofCase.FooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (fooCase_ == FooOneofCase.FooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (fooCase_ == FooOneofCase.FooInt) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt);
+      }
+      if (fooCase_ == FooOneofCase.FooString) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestOneof other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.FooCase) {
+        case FooOneofCase.FooInt:
+          FooInt = other.FooInt;
+          break;
+        case FooOneofCase.FooString:
+          FooString = other.FooString;
+          break;
+        case FooOneofCase.FooMessage:
+          FooMessage = other.FooMessage;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes> {
+    private static readonly pb::MessageParser<TestPackedTypes> _parser = new pb::MessageParser<TestPackedTypes>(() => new TestPackedTypes());
+    public static pb::MessageParser<TestPackedTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[23]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestPackedTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestPackedTypes(TestPackedTypes other) : this() {
+      packedInt32_ = other.packedInt32_.Clone();
+      packedInt64_ = other.packedInt64_.Clone();
+      packedUint32_ = other.packedUint32_.Clone();
+      packedUint64_ = other.packedUint64_.Clone();
+      packedSint32_ = other.packedSint32_.Clone();
+      packedSint64_ = other.packedSint64_.Clone();
+      packedFixed32_ = other.packedFixed32_.Clone();
+      packedFixed64_ = other.packedFixed64_.Clone();
+      packedSfixed32_ = other.packedSfixed32_.Clone();
+      packedSfixed64_ = other.packedSfixed64_.Clone();
+      packedFloat_ = other.packedFloat_.Clone();
+      packedDouble_ = other.packedDouble_.Clone();
+      packedBool_ = other.packedBool_.Clone();
+      packedEnum_ = other.packedEnum_.Clone();
+    }
+
+    public TestPackedTypes Clone() {
+      return new TestPackedTypes(this);
+    }
+
+    /// <summary>Field number for the "packed_int32" field.</summary>
+    public const int PackedInt32FieldNumber = 90;
+    private static readonly pb::FieldCodec<int> _repeated_packedInt32_codec
+        = pb::FieldCodec.ForInt32(722);
+    private readonly pbc::RepeatedField<int> packedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedInt32 {
+      get { return packedInt32_; }
+    }
+
+    /// <summary>Field number for the "packed_int64" field.</summary>
+    public const int PackedInt64FieldNumber = 91;
+    private static readonly pb::FieldCodec<long> _repeated_packedInt64_codec
+        = pb::FieldCodec.ForInt64(730);
+    private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedInt64 {
+      get { return packedInt64_; }
+    }
+
+    /// <summary>Field number for the "packed_uint32" field.</summary>
+    public const int PackedUint32FieldNumber = 92;
+    private static readonly pb::FieldCodec<uint> _repeated_packedUint32_codec
+        = pb::FieldCodec.ForUInt32(738);
+    private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> PackedUint32 {
+      get { return packedUint32_; }
+    }
+
+    /// <summary>Field number for the "packed_uint64" field.</summary>
+    public const int PackedUint64FieldNumber = 93;
+    private static readonly pb::FieldCodec<ulong> _repeated_packedUint64_codec
+        = pb::FieldCodec.ForUInt64(746);
+    private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> PackedUint64 {
+      get { return packedUint64_; }
+    }
+
+    /// <summary>Field number for the "packed_sint32" field.</summary>
+    public const int PackedSint32FieldNumber = 94;
+    private static readonly pb::FieldCodec<int> _repeated_packedSint32_codec
+        = pb::FieldCodec.ForSInt32(754);
+    private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedSint32 {
+      get { return packedSint32_; }
+    }
+
+    /// <summary>Field number for the "packed_sint64" field.</summary>
+    public const int PackedSint64FieldNumber = 95;
+    private static readonly pb::FieldCodec<long> _repeated_packedSint64_codec
+        = pb::FieldCodec.ForSInt64(762);
+    private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedSint64 {
+      get { return packedSint64_; }
+    }
+
+    /// <summary>Field number for the "packed_fixed32" field.</summary>
+    public const int PackedFixed32FieldNumber = 96;
+    private static readonly pb::FieldCodec<uint> _repeated_packedFixed32_codec
+        = pb::FieldCodec.ForFixed32(770);
+    private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> PackedFixed32 {
+      get { return packedFixed32_; }
+    }
+
+    /// <summary>Field number for the "packed_fixed64" field.</summary>
+    public const int PackedFixed64FieldNumber = 97;
+    private static readonly pb::FieldCodec<ulong> _repeated_packedFixed64_codec
+        = pb::FieldCodec.ForFixed64(778);
+    private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> PackedFixed64 {
+      get { return packedFixed64_; }
+    }
+
+    /// <summary>Field number for the "packed_sfixed32" field.</summary>
+    public const int PackedSfixed32FieldNumber = 98;
+    private static readonly pb::FieldCodec<int> _repeated_packedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(786);
+    private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedSfixed32 {
+      get { return packedSfixed32_; }
+    }
+
+    /// <summary>Field number for the "packed_sfixed64" field.</summary>
+    public const int PackedSfixed64FieldNumber = 99;
+    private static readonly pb::FieldCodec<long> _repeated_packedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(794);
+    private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedSfixed64 {
+      get { return packedSfixed64_; }
+    }
+
+    /// <summary>Field number for the "packed_float" field.</summary>
+    public const int PackedFloatFieldNumber = 100;
+    private static readonly pb::FieldCodec<float> _repeated_packedFloat_codec
+        = pb::FieldCodec.ForFloat(802);
+    private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> PackedFloat {
+      get { return packedFloat_; }
+    }
+
+    /// <summary>Field number for the "packed_double" field.</summary>
+    public const int PackedDoubleFieldNumber = 101;
+    private static readonly pb::FieldCodec<double> _repeated_packedDouble_codec
+        = pb::FieldCodec.ForDouble(810);
+    private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> PackedDouble {
+      get { return packedDouble_; }
+    }
+
+    /// <summary>Field number for the "packed_bool" field.</summary>
+    public const int PackedBoolFieldNumber = 102;
+    private static readonly pb::FieldCodec<bool> _repeated_packedBool_codec
+        = pb::FieldCodec.ForBool(818);
+    private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> PackedBool {
+      get { return packedBool_; }
+    }
+
+    /// <summary>Field number for the "packed_enum" field.</summary>
+    public const int PackedEnumFieldNumber = 103;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_packedEnum_codec
+        = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> PackedEnum {
+      get { return packedEnum_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestPackedTypes);
+    }
+
+    public bool Equals(TestPackedTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!packedInt32_.Equals(other.packedInt32_)) return false;
+      if(!packedInt64_.Equals(other.packedInt64_)) return false;
+      if(!packedUint32_.Equals(other.packedUint32_)) return false;
+      if(!packedUint64_.Equals(other.packedUint64_)) return false;
+      if(!packedSint32_.Equals(other.packedSint32_)) return false;
+      if(!packedSint64_.Equals(other.packedSint64_)) return false;
+      if(!packedFixed32_.Equals(other.packedFixed32_)) return false;
+      if(!packedFixed64_.Equals(other.packedFixed64_)) return false;
+      if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false;
+      if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false;
+      if(!packedFloat_.Equals(other.packedFloat_)) return false;
+      if(!packedDouble_.Equals(other.packedDouble_)) return false;
+      if(!packedBool_.Equals(other.packedBool_)) return false;
+      if(!packedEnum_.Equals(other.packedEnum_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= packedInt32_.GetHashCode();
+      hash ^= packedInt64_.GetHashCode();
+      hash ^= packedUint32_.GetHashCode();
+      hash ^= packedUint64_.GetHashCode();
+      hash ^= packedSint32_.GetHashCode();
+      hash ^= packedSint64_.GetHashCode();
+      hash ^= packedFixed32_.GetHashCode();
+      hash ^= packedFixed64_.GetHashCode();
+      hash ^= packedSfixed32_.GetHashCode();
+      hash ^= packedSfixed64_.GetHashCode();
+      hash ^= packedFloat_.GetHashCode();
+      hash ^= packedDouble_.GetHashCode();
+      hash ^= packedBool_.GetHashCode();
+      hash ^= packedEnum_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      packedInt32_.WriteTo(output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(output, _repeated_packedBool_codec);
+      packedEnum_.WriteTo(output, _repeated_packedEnum_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += packedInt32_.CalculateSize(_repeated_packedInt32_codec);
+      size += packedInt64_.CalculateSize(_repeated_packedInt64_codec);
+      size += packedUint32_.CalculateSize(_repeated_packedUint32_codec);
+      size += packedUint64_.CalculateSize(_repeated_packedUint64_codec);
+      size += packedSint32_.CalculateSize(_repeated_packedSint32_codec);
+      size += packedSint64_.CalculateSize(_repeated_packedSint64_codec);
+      size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec);
+      size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec);
+      size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec);
+      size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec);
+      size += packedFloat_.CalculateSize(_repeated_packedFloat_codec);
+      size += packedDouble_.CalculateSize(_repeated_packedDouble_codec);
+      size += packedBool_.CalculateSize(_repeated_packedBool_codec);
+      size += packedEnum_.CalculateSize(_repeated_packedEnum_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestPackedTypes other) {
+      if (other == null) {
+        return;
+      }
+      packedInt32_.Add(other.packedInt32_);
+      packedInt64_.Add(other.packedInt64_);
+      packedUint32_.Add(other.packedUint32_);
+      packedUint64_.Add(other.packedUint64_);
+      packedSint32_.Add(other.packedSint32_);
+      packedSint64_.Add(other.packedSint64_);
+      packedFixed32_.Add(other.packedFixed32_);
+      packedFixed64_.Add(other.packedFixed64_);
+      packedSfixed32_.Add(other.packedSfixed32_);
+      packedSfixed64_.Add(other.packedSfixed64_);
+      packedFloat_.Add(other.packedFloat_);
+      packedDouble_.Add(other.packedDouble_);
+      packedBool_.Add(other.packedBool_);
+      packedEnum_.Add(other.packedEnum_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 722:
+          case 720: {
+            packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A message with the same fields as TestPackedTypes, but without packing. Used
+  ///  to test packed &lt;-> unpacked wire compatibility.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes> {
+    private static readonly pb::MessageParser<TestUnpackedTypes> _parser = new pb::MessageParser<TestUnpackedTypes>(() => new TestUnpackedTypes());
+    public static pb::MessageParser<TestUnpackedTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[24]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestUnpackedTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestUnpackedTypes(TestUnpackedTypes other) : this() {
+      unpackedInt32_ = other.unpackedInt32_.Clone();
+      unpackedInt64_ = other.unpackedInt64_.Clone();
+      unpackedUint32_ = other.unpackedUint32_.Clone();
+      unpackedUint64_ = other.unpackedUint64_.Clone();
+      unpackedSint32_ = other.unpackedSint32_.Clone();
+      unpackedSint64_ = other.unpackedSint64_.Clone();
+      unpackedFixed32_ = other.unpackedFixed32_.Clone();
+      unpackedFixed64_ = other.unpackedFixed64_.Clone();
+      unpackedSfixed32_ = other.unpackedSfixed32_.Clone();
+      unpackedSfixed64_ = other.unpackedSfixed64_.Clone();
+      unpackedFloat_ = other.unpackedFloat_.Clone();
+      unpackedDouble_ = other.unpackedDouble_.Clone();
+      unpackedBool_ = other.unpackedBool_.Clone();
+      unpackedEnum_ = other.unpackedEnum_.Clone();
+    }
+
+    public TestUnpackedTypes Clone() {
+      return new TestUnpackedTypes(this);
+    }
+
+    /// <summary>Field number for the "unpacked_int32" field.</summary>
+    public const int UnpackedInt32FieldNumber = 90;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedInt32_codec
+        = pb::FieldCodec.ForInt32(720);
+    private readonly pbc::RepeatedField<int> unpackedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedInt32 {
+      get { return unpackedInt32_; }
+    }
+
+    /// <summary>Field number for the "unpacked_int64" field.</summary>
+    public const int UnpackedInt64FieldNumber = 91;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedInt64_codec
+        = pb::FieldCodec.ForInt64(728);
+    private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedInt64 {
+      get { return unpackedInt64_; }
+    }
+
+    /// <summary>Field number for the "unpacked_uint32" field.</summary>
+    public const int UnpackedUint32FieldNumber = 92;
+    private static readonly pb::FieldCodec<uint> _repeated_unpackedUint32_codec
+        = pb::FieldCodec.ForUInt32(736);
+    private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> UnpackedUint32 {
+      get { return unpackedUint32_; }
+    }
+
+    /// <summary>Field number for the "unpacked_uint64" field.</summary>
+    public const int UnpackedUint64FieldNumber = 93;
+    private static readonly pb::FieldCodec<ulong> _repeated_unpackedUint64_codec
+        = pb::FieldCodec.ForUInt64(744);
+    private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> UnpackedUint64 {
+      get { return unpackedUint64_; }
+    }
+
+    /// <summary>Field number for the "unpacked_sint32" field.</summary>
+    public const int UnpackedSint32FieldNumber = 94;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedSint32_codec
+        = pb::FieldCodec.ForSInt32(752);
+    private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedSint32 {
+      get { return unpackedSint32_; }
+    }
+
+    /// <summary>Field number for the "unpacked_sint64" field.</summary>
+    public const int UnpackedSint64FieldNumber = 95;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedSint64_codec
+        = pb::FieldCodec.ForSInt64(760);
+    private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedSint64 {
+      get { return unpackedSint64_; }
+    }
+
+    /// <summary>Field number for the "unpacked_fixed32" field.</summary>
+    public const int UnpackedFixed32FieldNumber = 96;
+    private static readonly pb::FieldCodec<uint> _repeated_unpackedFixed32_codec
+        = pb::FieldCodec.ForFixed32(773);
+    private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> UnpackedFixed32 {
+      get { return unpackedFixed32_; }
+    }
+
+    /// <summary>Field number for the "unpacked_fixed64" field.</summary>
+    public const int UnpackedFixed64FieldNumber = 97;
+    private static readonly pb::FieldCodec<ulong> _repeated_unpackedFixed64_codec
+        = pb::FieldCodec.ForFixed64(777);
+    private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> UnpackedFixed64 {
+      get { return unpackedFixed64_; }
+    }
+
+    /// <summary>Field number for the "unpacked_sfixed32" field.</summary>
+    public const int UnpackedSfixed32FieldNumber = 98;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(789);
+    private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedSfixed32 {
+      get { return unpackedSfixed32_; }
+    }
+
+    /// <summary>Field number for the "unpacked_sfixed64" field.</summary>
+    public const int UnpackedSfixed64FieldNumber = 99;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(793);
+    private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedSfixed64 {
+      get { return unpackedSfixed64_; }
+    }
+
+    /// <summary>Field number for the "unpacked_float" field.</summary>
+    public const int UnpackedFloatFieldNumber = 100;
+    private static readonly pb::FieldCodec<float> _repeated_unpackedFloat_codec
+        = pb::FieldCodec.ForFloat(805);
+    private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> UnpackedFloat {
+      get { return unpackedFloat_; }
+    }
+
+    /// <summary>Field number for the "unpacked_double" field.</summary>
+    public const int UnpackedDoubleFieldNumber = 101;
+    private static readonly pb::FieldCodec<double> _repeated_unpackedDouble_codec
+        = pb::FieldCodec.ForDouble(809);
+    private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> UnpackedDouble {
+      get { return unpackedDouble_; }
+    }
+
+    /// <summary>Field number for the "unpacked_bool" field.</summary>
+    public const int UnpackedBoolFieldNumber = 102;
+    private static readonly pb::FieldCodec<bool> _repeated_unpackedBool_codec
+        = pb::FieldCodec.ForBool(816);
+    private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> UnpackedBool {
+      get { return unpackedBool_; }
+    }
+
+    /// <summary>Field number for the "unpacked_enum" field.</summary>
+    public const int UnpackedEnumFieldNumber = 103;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_unpackedEnum_codec
+        = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> UnpackedEnum {
+      get { return unpackedEnum_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestUnpackedTypes);
+    }
+
+    public bool Equals(TestUnpackedTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false;
+      if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false;
+      if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false;
+      if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false;
+      if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false;
+      if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false;
+      if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false;
+      if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false;
+      if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false;
+      if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false;
+      if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false;
+      if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false;
+      if(!unpackedBool_.Equals(other.unpackedBool_)) return false;
+      if(!unpackedEnum_.Equals(other.unpackedEnum_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= unpackedInt32_.GetHashCode();
+      hash ^= unpackedInt64_.GetHashCode();
+      hash ^= unpackedUint32_.GetHashCode();
+      hash ^= unpackedUint64_.GetHashCode();
+      hash ^= unpackedSint32_.GetHashCode();
+      hash ^= unpackedSint64_.GetHashCode();
+      hash ^= unpackedFixed32_.GetHashCode();
+      hash ^= unpackedFixed64_.GetHashCode();
+      hash ^= unpackedSfixed32_.GetHashCode();
+      hash ^= unpackedSfixed64_.GetHashCode();
+      hash ^= unpackedFloat_.GetHashCode();
+      hash ^= unpackedDouble_.GetHashCode();
+      hash ^= unpackedBool_.GetHashCode();
+      hash ^= unpackedEnum_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec);
+      unpackedEnum_.WriteTo(output, _repeated_unpackedEnum_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec);
+      size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec);
+      size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec);
+      size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec);
+      size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec);
+      size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec);
+      size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec);
+      size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec);
+      size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec);
+      size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec);
+      size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec);
+      size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec);
+      size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec);
+      size += unpackedEnum_.CalculateSize(_repeated_unpackedEnum_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestUnpackedTypes other) {
+      if (other == null) {
+        return;
+      }
+      unpackedInt32_.Add(other.unpackedInt32_);
+      unpackedInt64_.Add(other.unpackedInt64_);
+      unpackedUint32_.Add(other.unpackedUint32_);
+      unpackedUint64_.Add(other.unpackedUint64_);
+      unpackedSint32_.Add(other.unpackedSint32_);
+      unpackedSint64_.Add(other.unpackedSint64_);
+      unpackedFixed32_.Add(other.unpackedFixed32_);
+      unpackedFixed64_.Add(other.unpackedFixed64_);
+      unpackedSfixed32_.Add(other.unpackedSfixed32_);
+      unpackedSfixed64_.Add(other.unpackedSfixed64_);
+      unpackedFloat_.Add(other.unpackedFloat_);
+      unpackedDouble_.Add(other.unpackedDouble_);
+      unpackedBool_.Add(other.unpackedBool_);
+      unpackedEnum_.Add(other.unpackedEnum_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 722:
+          case 720: {
+            unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes> {
+    private static readonly pb::MessageParser<TestRepeatedScalarDifferentTagSizes> _parser = new pb::MessageParser<TestRepeatedScalarDifferentTagSizes>(() => new TestRepeatedScalarDifferentTagSizes());
+    public static pb::MessageParser<TestRepeatedScalarDifferentTagSizes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[25]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestRepeatedScalarDifferentTagSizes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() {
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+    }
+
+    public TestRepeatedScalarDifferentTagSizes Clone() {
+      return new TestRepeatedScalarDifferentTagSizes(this);
+    }
+
+    /// <summary>Field number for the "repeated_fixed32" field.</summary>
+    public const int RepeatedFixed32FieldNumber = 12;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(98);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    /// <summary>
+    ///  Parsing repeated fixed size values used to fail. This message needs to be
+    ///  used in order to get a tag of the right size; all of the repeated fields
+    ///  in TestAllTypes didn't trigger the check.
+    /// </summary>
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    /// <summary>Field number for the "repeated_int32" field.</summary>
+    public const int RepeatedInt32FieldNumber = 13;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(106);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Check for a varint type, just for good measure.
+    /// </summary>
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    /// <summary>Field number for the "repeated_fixed64" field.</summary>
+    public const int RepeatedFixed64FieldNumber = 2046;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(16370);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    /// <summary>
+    ///  These have two-byte tags.
+    /// </summary>
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    /// <summary>Field number for the "repeated_int64" field.</summary>
+    public const int RepeatedInt64FieldNumber = 2047;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(16378);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    /// <summary>Field number for the "repeated_float" field.</summary>
+    public const int RepeatedFloatFieldNumber = 262142;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(2097138);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    /// <summary>
+    ///  Three byte tags.
+    /// </summary>
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    /// <summary>Field number for the "repeated_uint64" field.</summary>
+    public const int RepeatedUint64FieldNumber = 262143;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(2097146);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestRepeatedScalarDifferentTagSizes);
+    }
+
+    public bool Equals(TestRepeatedScalarDifferentTagSizes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) {
+      if (other == null) {
+        return;
+      }
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 98:
+          case 101: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 106:
+          case 104: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 16370:
+          case 16369: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 16378:
+          case 16376: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 2097138:
+          case 2097141: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 2097146:
+          case 2097144: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage> {
+    private static readonly pb::MessageParser<TestCommentInjectionMessage> _parser = new pb::MessageParser<TestCommentInjectionMessage>(() => new TestCommentInjectionMessage());
+    public static pb::MessageParser<TestCommentInjectionMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[26]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestCommentInjectionMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() {
+      a_ = other.a_;
+    }
+
+    public TestCommentInjectionMessage Clone() {
+      return new TestCommentInjectionMessage(this);
+    }
+
+    /// <summary>Field number for the "a" field.</summary>
+    public const int AFieldNumber = 1;
+    private string a_ = "";
+    /// <summary>
+    ///  */ &lt;- This should not close the generated doc comment
+    /// </summary>
+    public string A {
+      get { return a_; }
+      set {
+        a_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestCommentInjectionMessage);
+    }
+
+    public bool Equals(TestCommentInjectionMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (A != other.A) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (A.Length != 0) hash ^= A.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (A.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(A);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (A.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(A);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestCommentInjectionMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.A.Length != 0) {
+        A = other.A;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            A = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Test that RPC services work.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooRequest : pb::IMessage<FooRequest> {
+    private static readonly pb::MessageParser<FooRequest> _parser = new pb::MessageParser<FooRequest>(() => new FooRequest());
+    public static pb::MessageParser<FooRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[27]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooRequest(FooRequest other) : this() {
+    }
+
+    public FooRequest Clone() {
+      return new FooRequest(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooRequest);
+    }
+
+    public bool Equals(FooRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooRequest other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooResponse : pb::IMessage<FooResponse> {
+    private static readonly pb::MessageParser<FooResponse> _parser = new pb::MessageParser<FooResponse>(() => new FooResponse());
+    public static pb::MessageParser<FooResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[28]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooResponse(FooResponse other) : this() {
+    }
+
+    public FooResponse Clone() {
+      return new FooResponse(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooResponse);
+    }
+
+    public bool Equals(FooResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooResponse other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage> {
+    private static readonly pb::MessageParser<FooClientMessage> _parser = new pb::MessageParser<FooClientMessage>(() => new FooClientMessage());
+    public static pb::MessageParser<FooClientMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[29]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooClientMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooClientMessage(FooClientMessage other) : this() {
+    }
+
+    public FooClientMessage Clone() {
+      return new FooClientMessage(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooClientMessage);
+    }
+
+    public bool Equals(FooClientMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooClientMessage other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage> {
+    private static readonly pb::MessageParser<FooServerMessage> _parser = new pb::MessageParser<FooServerMessage>(() => new FooServerMessage());
+    public static pb::MessageParser<FooServerMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[30]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooServerMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooServerMessage(FooServerMessage other) : this() {
+    }
+
+    public FooServerMessage Clone() {
+      return new FooServerMessage(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooServerMessage);
+    }
+
+    public bool Equals(FooServerMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooServerMessage other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BarRequest : pb::IMessage<BarRequest> {
+    private static readonly pb::MessageParser<BarRequest> _parser = new pb::MessageParser<BarRequest>(() => new BarRequest());
+    public static pb::MessageParser<BarRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[31]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BarRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BarRequest(BarRequest other) : this() {
+    }
+
+    public BarRequest Clone() {
+      return new BarRequest(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BarRequest);
+    }
+
+    public bool Equals(BarRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(BarRequest other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BarResponse : pb::IMessage<BarResponse> {
+    private static readonly pb::MessageParser<BarResponse> _parser = new pb::MessageParser<BarResponse>(() => new BarResponse());
+    public static pb::MessageParser<BarResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[32]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BarResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BarResponse(BarResponse other) : this() {
+    }
+
+    public BarResponse Clone() {
+      return new BarResponse(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BarResponse);
+    }
+
+    public bool Equals(BarResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(BarResponse other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
new file mode 100644
index 0000000..ae12f4a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
@@ -0,0 +1,2413 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_well_known_types.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/unittest_well_known_types.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestWellKnownTypesReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/unittest_well_known_types.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestWellKnownTypesReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ci9nb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfd2VsbF9rbm93bl90eXBlcy5w",
+            "cm90bxIRcHJvdG9idWZfdW5pdHRlc3QaGWdvb2dsZS9wcm90b2J1Zi9hbnku",
+            "cHJvdG8aGWdvb2dsZS9wcm90b2J1Zi9hcGkucHJvdG8aHmdvb2dsZS9wcm90",
+            "b2J1Zi9kdXJhdGlvbi5wcm90bxobZ29vZ2xlL3Byb3RvYnVmL2VtcHR5LnBy",
+            "b3RvGiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxokZ29vZ2xl",
+            "L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i",
+            "dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy",
+            "b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv",
+            "YnVmL3dyYXBwZXJzLnByb3RvIr4HChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ",
+            "YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf",
+            "ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u",
+            "X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt",
+            "cHR5X2ZpZWxkGAQgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5EjQKEGZp",
+            "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
+            "YXNrEjwKFHNvdXJjZV9jb250ZXh0X2ZpZWxkGAYgASgLMh4uZ29vZ2xlLnBy",
+            "b3RvYnVmLlNvdXJjZUNvbnRleHQSLQoMc3RydWN0X2ZpZWxkGAcgASgLMhcu",
+            "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIzCg90aW1lc3RhbXBfZmllbGQYCCAB",
+            "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEikKCnR5cGVfZmllbGQY",
+            "CSABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZRIyCgxkb3VibGVfZmllbGQY",
+            "CiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMAoLZmxvYXRf",
+            "ZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRIwCgtp",
+            "bnQ2NF9maWVsZBgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
+            "EjIKDHVpbnQ2NF9maWVsZBgNIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50",
+            "NjRWYWx1ZRIwCgtpbnQzMl9maWVsZBgOIAEoCzIbLmdvb2dsZS5wcm90b2J1",
+            "Zi5JbnQzMlZhbHVlEjIKDHVpbnQzMl9maWVsZBgPIAEoCzIcLmdvb2dsZS5w",
+            "cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v",
+            "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy",
+            "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY",
+            "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRIrCgt2YWx1ZV9m",
+            "aWVsZBgTIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSKVBwoWUmVwZWF0",
+            "ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu",
+            "cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90",
+            "b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv",
+            "dG9idWYuRHVyYXRpb24SKwoLZW1wdHlfZmllbGQYBCADKAsyFi5nb29nbGUu",
+            "cHJvdG9idWYuRW1wdHkSNAoQZmllbGRfbWFza19maWVsZBgFIAMoCzIaLmdv",
+            "b2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSPAoUc291cmNlX2NvbnRleHRfZmll",
+            "bGQYBiADKAsyHi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBItCgxz",
+            "dHJ1Y3RfZmllbGQYByADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EjMK",
+            "D3RpbWVzdGFtcF9maWVsZBgIIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l",
+            "c3RhbXASKQoKdHlwZV9maWVsZBgJIAMoCzIVLmdvb2dsZS5wcm90b2J1Zi5U",
+            "eXBlEjIKDGRvdWJsZV9maWVsZBgKIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5E",
+            "b3VibGVWYWx1ZRIwCgtmbG9hdF9maWVsZBgLIAMoCzIbLmdvb2dsZS5wcm90",
+            "b2J1Zi5GbG9hdFZhbHVlEjAKC2ludDY0X2ZpZWxkGAwgAygLMhsuZ29vZ2xl",
+            "LnByb3RvYnVmLkludDY0VmFsdWUSMgoMdWludDY0X2ZpZWxkGA0gAygLMhwu",
+            "Z29vZ2xlLnByb3RvYnVmLlVJbnQ2NFZhbHVlEjAKC2ludDMyX2ZpZWxkGA4g",
+            "AygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMgoMdWludDMyX2Zp",
+            "ZWxkGA8gAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEi4KCmJv",
+            "b2xfZmllbGQYECADKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlEjIK",
+            "DHN0cmluZ19maWVsZBgRIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW",
+            "YWx1ZRIwCgtieXRlc19maWVsZBgSIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5C",
+            "eXRlc1ZhbHVlIsUHChNPbmVvZldlbGxLbm93blR5cGVzEikKCWFueV9maWVs",
+            "ZBgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlIABIpCglhcGlfZmllbGQY",
+            "AiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpSAASMwoOZHVyYXRpb25fZmll",
+            "bGQYAyABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb25IABItCgtlbXB0",
+            "eV9maWVsZBgEIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAEjYKEGZp",
+            "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
+            "YXNrSAASPgoUc291cmNlX2NvbnRleHRfZmllbGQYBiABKAsyHi5nb29nbGUu",
+            "cHJvdG9idWYuU291cmNlQ29udGV4dEgAEi8KDHN0cnVjdF9maWVsZBgHIAEo",
+            "CzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIABI1Cg90aW1lc3RhbXBfZmll",
+            "bGQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAASKwoKdHlw",
+            "ZV9maWVsZBgJIAEoCzIVLmdvb2dsZS5wcm90b2J1Zi5UeXBlSAASNAoMZG91",
+            "YmxlX2ZpZWxkGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVl",
+            "SAASMgoLZmxvYXRfZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxv",
+            "YXRWYWx1ZUgAEjIKC2ludDY0X2ZpZWxkGAwgASgLMhsuZ29vZ2xlLnByb3Rv",
+            "YnVmLkludDY0VmFsdWVIABI0Cgx1aW50NjRfZmllbGQYDSABKAsyHC5nb29n",
+            "bGUucHJvdG9idWYuVUludDY0VmFsdWVIABIyCgtpbnQzMl9maWVsZBgOIAEo",
+            "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlSAASNAoMdWludDMyX2Zp",
+            "ZWxkGA8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlSAASMAoK",
+            "Ym9vbF9maWVsZBgQIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWVI",
+            "ABI0CgxzdHJpbmdfZmllbGQYESABKAsyHC5nb29nbGUucHJvdG9idWYuU3Ry",
+            "aW5nVmFsdWVIABIyCgtieXRlc19maWVsZBgSIAEoCzIbLmdvb2dsZS5wcm90",
+            "b2J1Zi5CeXRlc1ZhbHVlSABCDQoLb25lb2ZfZmllbGQilhYKEU1hcFdlbGxL",
+            "bm93blR5cGVzEkUKCWFueV9maWVsZBgBIAMoCzIyLnByb3RvYnVmX3VuaXR0",
+            "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkFueUZpZWxkRW50cnkSRQoJYXBpX2Zp",
+            "ZWxkGAIgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlw",
+            "ZXMuQXBpRmllbGRFbnRyeRJPCg5kdXJhdGlvbl9maWVsZBgDIAMoCzI3LnBy",
+            "b3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkR1cmF0aW9uRmll",
+            "bGRFbnRyeRJJCgtlbXB0eV9maWVsZBgEIAMoCzI0LnByb3RvYnVmX3VuaXR0",
+            "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkVtcHR5RmllbGRFbnRyeRJSChBmaWVs",
+            "ZF9tYXNrX2ZpZWxkGAUgAygLMjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
+            "bEtub3duVHlwZXMuRmllbGRNYXNrRmllbGRFbnRyeRJaChRzb3VyY2VfY29u",
+            "dGV4dF9maWVsZBgGIAMoCzI8LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxL",
+            "bm93blR5cGVzLlNvdXJjZUNvbnRleHRGaWVsZEVudHJ5EksKDHN0cnVjdF9m",
+            "aWVsZBgHIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5",
+            "cGVzLlN0cnVjdEZpZWxkRW50cnkSUQoPdGltZXN0YW1wX2ZpZWxkGAggAygL",
+            "MjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVGltZXN0",
+            "YW1wRmllbGRFbnRyeRJHCgp0eXBlX2ZpZWxkGAkgAygLMjMucHJvdG9idWZf",
+            "dW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVHlwZUZpZWxkRW50cnkSSwoM",
+            "ZG91YmxlX2ZpZWxkGAogAygLMjUucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
+            "bEtub3duVHlwZXMuRG91YmxlRmllbGRFbnRyeRJJCgtmbG9hdF9maWVsZBgL",
+            "IAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkZs",
+            "b2F0RmllbGRFbnRyeRJJCgtpbnQ2NF9maWVsZBgMIAMoCzI0LnByb3RvYnVm",
+            "X3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkludDY0RmllbGRFbnRyeRJL",
+            "Cgx1aW50NjRfZmllbGQYDSADKAsyNS5wcm90b2J1Zl91bml0dGVzdC5NYXBX",
+            "ZWxsS25vd25UeXBlcy5VaW50NjRGaWVsZEVudHJ5EkkKC2ludDMyX2ZpZWxk",
+            "GA4gAygLMjQucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMu",
+            "SW50MzJGaWVsZEVudHJ5EksKDHVpbnQzMl9maWVsZBgPIAMoCzI1LnByb3Rv",
+            "YnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLlVpbnQzMkZpZWxkRW50",
+            "cnkSRwoKYm9vbF9maWVsZBgQIAMoCzIzLnByb3RvYnVmX3VuaXR0ZXN0Lk1h",
+            "cFdlbGxLbm93blR5cGVzLkJvb2xGaWVsZEVudHJ5EksKDHN0cmluZ19maWVs",
+            "ZBgRIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVz",
+            "LlN0cmluZ0ZpZWxkRW50cnkSSQoLYnl0ZXNfZmllbGQYEiADKAsyNC5wcm90",
+            "b2J1Zl91bml0dGVzdC5NYXBXZWxsS25vd25UeXBlcy5CeXRlc0ZpZWxkRW50",
+            "cnkaRQoNQW55RmllbGRFbnRyeRILCgNrZXkYASABKAUSIwoFdmFsdWUYAiAB",
+            "KAsyFC5nb29nbGUucHJvdG9idWYuQW55OgI4ARpFCg1BcGlGaWVsZEVudHJ5",
+            "EgsKA2tleRgBIAEoBRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1",
+            "Zi5BcGk6AjgBGk8KEkR1cmF0aW9uRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
+            "KAoFdmFsdWUYAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb246AjgB",
+            "GkkKD0VtcHR5RmllbGRFbnRyeRILCgNrZXkYASABKAUSJQoFdmFsdWUYAiAB",
+            "KAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHk6AjgBGlEKE0ZpZWxkTWFza0Zp",
+            "ZWxkRW50cnkSCwoDa2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xl",
+            "LnByb3RvYnVmLkZpZWxkTWFzazoCOAEaWQoXU291cmNlQ29udGV4dEZpZWxk",
+            "RW50cnkSCwoDa2V5GAEgASgFEi0KBXZhbHVlGAIgASgLMh4uZ29vZ2xlLnBy",
+            "b3RvYnVmLlNvdXJjZUNvbnRleHQ6AjgBGksKEFN0cnVjdEZpZWxkRW50cnkS",
+            "CwoDa2V5GAEgASgFEiYKBXZhbHVlGAIgASgLMhcuZ29vZ2xlLnByb3RvYnVm",
+            "LlN0cnVjdDoCOAEaUQoTVGltZXN0YW1wRmllbGRFbnRyeRILCgNrZXkYASAB",
+            "KAUSKQoFdmFsdWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w",
+            "OgI4ARpHCg5UeXBlRmllbGRFbnRyeRILCgNrZXkYASABKAUSJAoFdmFsdWUY",
+            "AiABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZToCOAEaUAoQRG91YmxlRmll",
+            "bGRFbnRyeRILCgNrZXkYASABKAUSKwoFdmFsdWUYAiABKAsyHC5nb29nbGUu",
+            "cHJvdG9idWYuRG91YmxlVmFsdWU6AjgBGk4KD0Zsb2F0RmllbGRFbnRyeRIL",
+            "CgNrZXkYASABKAUSKgoFdmFsdWUYAiABKAsyGy5nb29nbGUucHJvdG9idWYu",
+            "RmxvYXRWYWx1ZToCOAEaTgoPSW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEo",
+            "BRIqCgV2YWx1ZRgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
+            "OgI4ARpQChBVaW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1",
+            "ZRgCIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZToCOAEaTgoP",
+            "SW50MzJGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIqCgV2YWx1ZRgCIAEoCzIb",
+            "Lmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlOgI4ARpQChBVaW50MzJGaWVs",
+            "ZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1ZRgCIAEoCzIcLmdvb2dsZS5w",
+            "cm90b2J1Zi5VSW50MzJWYWx1ZToCOAEaTAoOQm9vbEZpZWxkRW50cnkSCwoD",
+            "a2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJv",
+            "b2xWYWx1ZToCOAEaUAoQU3RyaW5nRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
+            "KwoFdmFsdWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWU6",
+            "AjgBGk4KD0J5dGVzRmllbGRFbnRyeRILCgNrZXkYASABKAUSKgoFdmFsdWUY",
+            "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t",
+            "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz",
+            "dFByb3Rvc2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", "ValueField" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, })
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  Test that we can include all well-known types.
+  ///  Each wrapper type is included separately, as languages
+  ///  map handle different wrappers in different ways.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
+    private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
+    public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestWellKnownTypes(TestWellKnownTypes other) : this() {
+      AnyField = other.anyField_ != null ? other.AnyField.Clone() : null;
+      ApiField = other.apiField_ != null ? other.ApiField.Clone() : null;
+      DurationField = other.durationField_ != null ? other.DurationField.Clone() : null;
+      EmptyField = other.emptyField_ != null ? other.EmptyField.Clone() : null;
+      FieldMaskField = other.fieldMaskField_ != null ? other.FieldMaskField.Clone() : null;
+      SourceContextField = other.sourceContextField_ != null ? other.SourceContextField.Clone() : null;
+      StructField = other.structField_ != null ? other.StructField.Clone() : null;
+      TimestampField = other.timestampField_ != null ? other.TimestampField.Clone() : null;
+      TypeField = other.typeField_ != null ? other.TypeField.Clone() : null;
+      DoubleField = other.DoubleField;
+      FloatField = other.FloatField;
+      Int64Field = other.Int64Field;
+      Uint64Field = other.Uint64Field;
+      Int32Field = other.Int32Field;
+      Uint32Field = other.Uint32Field;
+      BoolField = other.BoolField;
+      StringField = other.StringField;
+      BytesField = other.BytesField;
+      ValueField = other.valueField_ != null ? other.ValueField.Clone() : null;
+    }
+
+    public TestWellKnownTypes Clone() {
+      return new TestWellKnownTypes(this);
+    }
+
+    /// <summary>Field number for the "any_field" field.</summary>
+    public const int AnyFieldFieldNumber = 1;
+    private global::Google.Protobuf.WellKnownTypes.Any anyField_;
+    public global::Google.Protobuf.WellKnownTypes.Any AnyField {
+      get { return anyField_; }
+      set {
+        anyField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "api_field" field.</summary>
+    public const int ApiFieldFieldNumber = 2;
+    private global::Google.Protobuf.WellKnownTypes.Api apiField_;
+    public global::Google.Protobuf.WellKnownTypes.Api ApiField {
+      get { return apiField_; }
+      set {
+        apiField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "duration_field" field.</summary>
+    public const int DurationFieldFieldNumber = 3;
+    private global::Google.Protobuf.WellKnownTypes.Duration durationField_;
+    public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
+      get { return durationField_; }
+      set {
+        durationField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "empty_field" field.</summary>
+    public const int EmptyFieldFieldNumber = 4;
+    private global::Google.Protobuf.WellKnownTypes.Empty emptyField_;
+    public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
+      get { return emptyField_; }
+      set {
+        emptyField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "field_mask_field" field.</summary>
+    public const int FieldMaskFieldFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.FieldMask fieldMaskField_;
+    public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
+      get { return fieldMaskField_; }
+      set {
+        fieldMaskField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "source_context_field" field.</summary>
+    public const int SourceContextFieldFieldNumber = 6;
+    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContextField_;
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
+      get { return sourceContextField_; }
+      set {
+        sourceContextField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "struct_field" field.</summary>
+    public const int StructFieldFieldNumber = 7;
+    private global::Google.Protobuf.WellKnownTypes.Struct structField_;
+    public global::Google.Protobuf.WellKnownTypes.Struct StructField {
+      get { return structField_; }
+      set {
+        structField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "timestamp_field" field.</summary>
+    public const int TimestampFieldFieldNumber = 8;
+    private global::Google.Protobuf.WellKnownTypes.Timestamp timestampField_;
+    public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
+      get { return timestampField_; }
+      set {
+        timestampField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "type_field" field.</summary>
+    public const int TypeFieldFieldNumber = 9;
+    private global::Google.Protobuf.WellKnownTypes.Type typeField_;
+    public global::Google.Protobuf.WellKnownTypes.Type TypeField {
+      get { return typeField_; }
+      set {
+        typeField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "double_field" field.</summary>
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _single_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
+    private double? doubleField_;
+    public double? DoubleField {
+      get { return doubleField_; }
+      set {
+        doubleField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "float_field" field.</summary>
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _single_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
+    private float? floatField_;
+    public float? FloatField {
+      get { return floatField_; }
+      set {
+        floatField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "int64_field" field.</summary>
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _single_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
+    private long? int64Field_;
+    public long? Int64Field {
+      get { return int64Field_; }
+      set {
+        int64Field_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uint64_field" field.</summary>
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    private ulong? uint64Field_;
+    public ulong? Uint64Field {
+      get { return uint64Field_; }
+      set {
+        uint64Field_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "int32_field" field.</summary>
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _single_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
+    private int? int32Field_;
+    public int? Int32Field {
+      get { return int32Field_; }
+      set {
+        int32Field_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uint32_field" field.</summary>
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
+    private uint? uint32Field_;
+    public uint? Uint32Field {
+      get { return uint32Field_; }
+      set {
+        uint32Field_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "bool_field" field.</summary>
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _single_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
+    private bool? boolField_;
+    public bool? BoolField {
+      get { return boolField_; }
+      set {
+        boolField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "string_field" field.</summary>
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _single_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
+    private string stringField_;
+    public string StringField {
+      get { return stringField_; }
+      set {
+        stringField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "bytes_field" field.</summary>
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _single_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    private pb::ByteString bytesField_;
+    public pb::ByteString BytesField {
+      get { return bytesField_; }
+      set {
+        bytesField_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "value_field" field.</summary>
+    public const int ValueFieldFieldNumber = 19;
+    private global::Google.Protobuf.WellKnownTypes.Value valueField_;
+    /// <summary>
+    ///  Part of struct, but useful to be able to test separately
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Value ValueField {
+      get { return valueField_; }
+      set {
+        valueField_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestWellKnownTypes);
+    }
+
+    public bool Equals(TestWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(AnyField, other.AnyField)) return false;
+      if (!object.Equals(ApiField, other.ApiField)) return false;
+      if (!object.Equals(DurationField, other.DurationField)) return false;
+      if (!object.Equals(EmptyField, other.EmptyField)) return false;
+      if (!object.Equals(FieldMaskField, other.FieldMaskField)) return false;
+      if (!object.Equals(SourceContextField, other.SourceContextField)) return false;
+      if (!object.Equals(StructField, other.StructField)) return false;
+      if (!object.Equals(TimestampField, other.TimestampField)) return false;
+      if (!object.Equals(TypeField, other.TypeField)) return false;
+      if (DoubleField != other.DoubleField) return false;
+      if (FloatField != other.FloatField) return false;
+      if (Int64Field != other.Int64Field) return false;
+      if (Uint64Field != other.Uint64Field) return false;
+      if (Int32Field != other.Int32Field) return false;
+      if (Uint32Field != other.Uint32Field) return false;
+      if (BoolField != other.BoolField) return false;
+      if (StringField != other.StringField) return false;
+      if (BytesField != other.BytesField) return false;
+      if (!object.Equals(ValueField, other.ValueField)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (anyField_ != null) hash ^= AnyField.GetHashCode();
+      if (apiField_ != null) hash ^= ApiField.GetHashCode();
+      if (durationField_ != null) hash ^= DurationField.GetHashCode();
+      if (emptyField_ != null) hash ^= EmptyField.GetHashCode();
+      if (fieldMaskField_ != null) hash ^= FieldMaskField.GetHashCode();
+      if (sourceContextField_ != null) hash ^= SourceContextField.GetHashCode();
+      if (structField_ != null) hash ^= StructField.GetHashCode();
+      if (timestampField_ != null) hash ^= TimestampField.GetHashCode();
+      if (typeField_ != null) hash ^= TypeField.GetHashCode();
+      if (doubleField_ != null) hash ^= DoubleField.GetHashCode();
+      if (floatField_ != null) hash ^= FloatField.GetHashCode();
+      if (int64Field_ != null) hash ^= Int64Field.GetHashCode();
+      if (uint64Field_ != null) hash ^= Uint64Field.GetHashCode();
+      if (int32Field_ != null) hash ^= Int32Field.GetHashCode();
+      if (uint32Field_ != null) hash ^= Uint32Field.GetHashCode();
+      if (boolField_ != null) hash ^= BoolField.GetHashCode();
+      if (stringField_ != null) hash ^= StringField.GetHashCode();
+      if (bytesField_ != null) hash ^= BytesField.GetHashCode();
+      if (valueField_ != null) hash ^= ValueField.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (anyField_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (apiField_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (durationField_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (emptyField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (fieldMaskField_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (sourceContextField_ != null) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (structField_ != null) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (timestampField_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (typeField_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (doubleField_ != null) {
+        _single_doubleField_codec.WriteTagAndValue(output, DoubleField);
+      }
+      if (floatField_ != null) {
+        _single_floatField_codec.WriteTagAndValue(output, FloatField);
+      }
+      if (int64Field_ != null) {
+        _single_int64Field_codec.WriteTagAndValue(output, Int64Field);
+      }
+      if (uint64Field_ != null) {
+        _single_uint64Field_codec.WriteTagAndValue(output, Uint64Field);
+      }
+      if (int32Field_ != null) {
+        _single_int32Field_codec.WriteTagAndValue(output, Int32Field);
+      }
+      if (uint32Field_ != null) {
+        _single_uint32Field_codec.WriteTagAndValue(output, Uint32Field);
+      }
+      if (boolField_ != null) {
+        _single_boolField_codec.WriteTagAndValue(output, BoolField);
+      }
+      if (stringField_ != null) {
+        _single_stringField_codec.WriteTagAndValue(output, StringField);
+      }
+      if (bytesField_ != null) {
+        _single_bytesField_codec.WriteTagAndValue(output, BytesField);
+      }
+      if (valueField_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(ValueField);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (anyField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AnyField);
+      }
+      if (apiField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ApiField);
+      }
+      if (durationField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DurationField);
+      }
+      if (emptyField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(EmptyField);
+      }
+      if (fieldMaskField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FieldMaskField);
+      }
+      if (sourceContextField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContextField);
+      }
+      if (structField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructField);
+      }
+      if (timestampField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TimestampField);
+      }
+      if (typeField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TypeField);
+      }
+      if (doubleField_ != null) {
+        size += _single_doubleField_codec.CalculateSizeWithTag(DoubleField);
+      }
+      if (floatField_ != null) {
+        size += _single_floatField_codec.CalculateSizeWithTag(FloatField);
+      }
+      if (int64Field_ != null) {
+        size += _single_int64Field_codec.CalculateSizeWithTag(Int64Field);
+      }
+      if (uint64Field_ != null) {
+        size += _single_uint64Field_codec.CalculateSizeWithTag(Uint64Field);
+      }
+      if (int32Field_ != null) {
+        size += _single_int32Field_codec.CalculateSizeWithTag(Int32Field);
+      }
+      if (uint32Field_ != null) {
+        size += _single_uint32Field_codec.CalculateSizeWithTag(Uint32Field);
+      }
+      if (boolField_ != null) {
+        size += _single_boolField_codec.CalculateSizeWithTag(BoolField);
+      }
+      if (stringField_ != null) {
+        size += _single_stringField_codec.CalculateSizeWithTag(StringField);
+      }
+      if (bytesField_ != null) {
+        size += _single_bytesField_codec.CalculateSizeWithTag(BytesField);
+      }
+      if (valueField_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.anyField_ != null) {
+        if (anyField_ == null) {
+          anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+        }
+        AnyField.MergeFrom(other.AnyField);
+      }
+      if (other.apiField_ != null) {
+        if (apiField_ == null) {
+          apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+        }
+        ApiField.MergeFrom(other.ApiField);
+      }
+      if (other.durationField_ != null) {
+        if (durationField_ == null) {
+          durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+        }
+        DurationField.MergeFrom(other.DurationField);
+      }
+      if (other.emptyField_ != null) {
+        if (emptyField_ == null) {
+          emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+        }
+        EmptyField.MergeFrom(other.EmptyField);
+      }
+      if (other.fieldMaskField_ != null) {
+        if (fieldMaskField_ == null) {
+          fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+        }
+        FieldMaskField.MergeFrom(other.FieldMaskField);
+      }
+      if (other.sourceContextField_ != null) {
+        if (sourceContextField_ == null) {
+          sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+        }
+        SourceContextField.MergeFrom(other.SourceContextField);
+      }
+      if (other.structField_ != null) {
+        if (structField_ == null) {
+          structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+        }
+        StructField.MergeFrom(other.StructField);
+      }
+      if (other.timestampField_ != null) {
+        if (timestampField_ == null) {
+          timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+        }
+        TimestampField.MergeFrom(other.TimestampField);
+      }
+      if (other.typeField_ != null) {
+        if (typeField_ == null) {
+          typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+        }
+        TypeField.MergeFrom(other.TypeField);
+      }
+      if (other.doubleField_ != null) {
+        if (doubleField_ == null || other.DoubleField != 0D) {
+          DoubleField = other.DoubleField;
+        }
+      }
+      if (other.floatField_ != null) {
+        if (floatField_ == null || other.FloatField != 0F) {
+          FloatField = other.FloatField;
+        }
+      }
+      if (other.int64Field_ != null) {
+        if (int64Field_ == null || other.Int64Field != 0L) {
+          Int64Field = other.Int64Field;
+        }
+      }
+      if (other.uint64Field_ != null) {
+        if (uint64Field_ == null || other.Uint64Field != 0UL) {
+          Uint64Field = other.Uint64Field;
+        }
+      }
+      if (other.int32Field_ != null) {
+        if (int32Field_ == null || other.Int32Field != 0) {
+          Int32Field = other.Int32Field;
+        }
+      }
+      if (other.uint32Field_ != null) {
+        if (uint32Field_ == null || other.Uint32Field != 0) {
+          Uint32Field = other.Uint32Field;
+        }
+      }
+      if (other.boolField_ != null) {
+        if (boolField_ == null || other.BoolField != false) {
+          BoolField = other.BoolField;
+        }
+      }
+      if (other.stringField_ != null) {
+        if (stringField_ == null || other.StringField != "") {
+          StringField = other.StringField;
+        }
+      }
+      if (other.bytesField_ != null) {
+        if (bytesField_ == null || other.BytesField != pb::ByteString.Empty) {
+          BytesField = other.BytesField;
+        }
+      }
+      if (other.valueField_ != null) {
+        if (valueField_ == null) {
+          valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+        }
+        ValueField.MergeFrom(other.ValueField);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (anyField_ == null) {
+              anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(anyField_);
+            break;
+          }
+          case 18: {
+            if (apiField_ == null) {
+              apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+            }
+            input.ReadMessage(apiField_);
+            break;
+          }
+          case 26: {
+            if (durationField_ == null) {
+              durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+            }
+            input.ReadMessage(durationField_);
+            break;
+          }
+          case 34: {
+            if (emptyField_ == null) {
+              emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+            }
+            input.ReadMessage(emptyField_);
+            break;
+          }
+          case 42: {
+            if (fieldMaskField_ == null) {
+              fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            }
+            input.ReadMessage(fieldMaskField_);
+            break;
+          }
+          case 50: {
+            if (sourceContextField_ == null) {
+              sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(sourceContextField_);
+            break;
+          }
+          case 58: {
+            if (structField_ == null) {
+              structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+            }
+            input.ReadMessage(structField_);
+            break;
+          }
+          case 66: {
+            if (timestampField_ == null) {
+              timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(timestampField_);
+            break;
+          }
+          case 74: {
+            if (typeField_ == null) {
+              typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+            }
+            input.ReadMessage(typeField_);
+            break;
+          }
+          case 82: {
+            double? value = _single_doubleField_codec.Read(input);
+            if (doubleField_ == null || value != 0D) {
+              DoubleField = value;
+            }
+            break;
+          }
+          case 90: {
+            float? value = _single_floatField_codec.Read(input);
+            if (floatField_ == null || value != 0F) {
+              FloatField = value;
+            }
+            break;
+          }
+          case 98: {
+            long? value = _single_int64Field_codec.Read(input);
+            if (int64Field_ == null || value != 0L) {
+              Int64Field = value;
+            }
+            break;
+          }
+          case 106: {
+            ulong? value = _single_uint64Field_codec.Read(input);
+            if (uint64Field_ == null || value != 0UL) {
+              Uint64Field = value;
+            }
+            break;
+          }
+          case 114: {
+            int? value = _single_int32Field_codec.Read(input);
+            if (int32Field_ == null || value != 0) {
+              Int32Field = value;
+            }
+            break;
+          }
+          case 122: {
+            uint? value = _single_uint32Field_codec.Read(input);
+            if (uint32Field_ == null || value != 0) {
+              Uint32Field = value;
+            }
+            break;
+          }
+          case 130: {
+            bool? value = _single_boolField_codec.Read(input);
+            if (boolField_ == null || value != false) {
+              BoolField = value;
+            }
+            break;
+          }
+          case 138: {
+            string value = _single_stringField_codec.Read(input);
+            if (stringField_ == null || value != "") {
+              StringField = value;
+            }
+            break;
+          }
+          case 146: {
+            pb::ByteString value = _single_bytesField_codec.Read(input);
+            if (bytesField_ == null || value != pb::ByteString.Empty) {
+              BytesField = value;
+            }
+            break;
+          }
+          case 154: {
+            if (valueField_ == null) {
+              valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+            }
+            input.ReadMessage(valueField_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A repeated field for each well-known type.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
+    private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
+    public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public RepeatedWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public RepeatedWellKnownTypes(RepeatedWellKnownTypes other) : this() {
+      anyField_ = other.anyField_.Clone();
+      apiField_ = other.apiField_.Clone();
+      durationField_ = other.durationField_.Clone();
+      emptyField_ = other.emptyField_.Clone();
+      fieldMaskField_ = other.fieldMaskField_.Clone();
+      sourceContextField_ = other.sourceContextField_.Clone();
+      structField_ = other.structField_.Clone();
+      timestampField_ = other.timestampField_.Clone();
+      typeField_ = other.typeField_.Clone();
+      doubleField_ = other.doubleField_.Clone();
+      floatField_ = other.floatField_.Clone();
+      int64Field_ = other.int64Field_.Clone();
+      uint64Field_ = other.uint64Field_.Clone();
+      int32Field_ = other.int32Field_.Clone();
+      uint32Field_ = other.uint32Field_.Clone();
+      boolField_ = other.boolField_.Clone();
+      stringField_ = other.stringField_.Clone();
+      bytesField_ = other.bytesField_.Clone();
+    }
+
+    public RepeatedWellKnownTypes Clone() {
+      return new RepeatedWellKnownTypes(this);
+    }
+
+    /// <summary>Field number for the "any_field" field.</summary>
+    public const int AnyFieldFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Any> _repeated_anyField_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.WellKnownTypes.Any.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> AnyField {
+      get { return anyField_; }
+    }
+
+    /// <summary>Field number for the "api_field" field.</summary>
+    public const int ApiFieldFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Api> _repeated_apiField_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> ApiField {
+      get { return apiField_; }
+    }
+
+    /// <summary>Field number for the "duration_field" field.</summary>
+    public const int DurationFieldFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Duration> _repeated_durationField_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Duration.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
+      get { return durationField_; }
+    }
+
+    /// <summary>Field number for the "empty_field" field.</summary>
+    public const int EmptyFieldFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Empty> _repeated_emptyField_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Empty.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
+      get { return emptyField_; }
+    }
+
+    /// <summary>Field number for the "field_mask_field" field.</summary>
+    public const int FieldMaskFieldFieldNumber = 5;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.FieldMask> _repeated_fieldMaskField_codec
+        = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
+      get { return fieldMaskField_; }
+    }
+
+    /// <summary>Field number for the "source_context_field" field.</summary>
+    public const int SourceContextFieldFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.SourceContext> _repeated_sourceContextField_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
+      get { return sourceContextField_; }
+    }
+
+    /// <summary>Field number for the "struct_field" field.</summary>
+    public const int StructFieldFieldNumber = 7;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Struct> _repeated_structField_codec
+        = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.WellKnownTypes.Struct.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> StructField {
+      get { return structField_; }
+    }
+
+    /// <summary>Field number for the "timestamp_field" field.</summary>
+    public const int TimestampFieldFieldNumber = 8;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Timestamp> _repeated_timestampField_codec
+        = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
+      get { return timestampField_; }
+    }
+
+    /// <summary>Field number for the "type_field" field.</summary>
+    public const int TypeFieldFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Type> _repeated_typeField_codec
+        = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Type.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> TypeField {
+      get { return typeField_; }
+    }
+
+    /// <summary>Field number for the "double_field" field.</summary>
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _repeated_doubleField_codec
+        = pb::FieldCodec.ForStructWrapper<double>(82);
+    private readonly pbc::RepeatedField<double?> doubleField_ = new pbc::RepeatedField<double?>();
+    /// <summary>
+    ///  These don't actually make a lot of sense, but they're not prohibited...
+    /// </summary>
+    public pbc::RepeatedField<double?> DoubleField {
+      get { return doubleField_; }
+    }
+
+    /// <summary>Field number for the "float_field" field.</summary>
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _repeated_floatField_codec
+        = pb::FieldCodec.ForStructWrapper<float>(90);
+    private readonly pbc::RepeatedField<float?> floatField_ = new pbc::RepeatedField<float?>();
+    public pbc::RepeatedField<float?> FloatField {
+      get { return floatField_; }
+    }
+
+    /// <summary>Field number for the "int64_field" field.</summary>
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _repeated_int64Field_codec
+        = pb::FieldCodec.ForStructWrapper<long>(98);
+    private readonly pbc::RepeatedField<long?> int64Field_ = new pbc::RepeatedField<long?>();
+    public pbc::RepeatedField<long?> Int64Field {
+      get { return int64Field_; }
+    }
+
+    /// <summary>Field number for the "uint64_field" field.</summary>
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _repeated_uint64Field_codec
+        = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    private readonly pbc::RepeatedField<ulong?> uint64Field_ = new pbc::RepeatedField<ulong?>();
+    public pbc::RepeatedField<ulong?> Uint64Field {
+      get { return uint64Field_; }
+    }
+
+    /// <summary>Field number for the "int32_field" field.</summary>
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _repeated_int32Field_codec
+        = pb::FieldCodec.ForStructWrapper<int>(114);
+    private readonly pbc::RepeatedField<int?> int32Field_ = new pbc::RepeatedField<int?>();
+    public pbc::RepeatedField<int?> Int32Field {
+      get { return int32Field_; }
+    }
+
+    /// <summary>Field number for the "uint32_field" field.</summary>
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _repeated_uint32Field_codec
+        = pb::FieldCodec.ForStructWrapper<uint>(122);
+    private readonly pbc::RepeatedField<uint?> uint32Field_ = new pbc::RepeatedField<uint?>();
+    public pbc::RepeatedField<uint?> Uint32Field {
+      get { return uint32Field_; }
+    }
+
+    /// <summary>Field number for the "bool_field" field.</summary>
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _repeated_boolField_codec
+        = pb::FieldCodec.ForStructWrapper<bool>(130);
+    private readonly pbc::RepeatedField<bool?> boolField_ = new pbc::RepeatedField<bool?>();
+    public pbc::RepeatedField<bool?> BoolField {
+      get { return boolField_; }
+    }
+
+    /// <summary>Field number for the "string_field" field.</summary>
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _repeated_stringField_codec
+        = pb::FieldCodec.ForClassWrapper<string>(138);
+    private readonly pbc::RepeatedField<string> stringField_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> StringField {
+      get { return stringField_; }
+    }
+
+    /// <summary>Field number for the "bytes_field" field.</summary>
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_bytesField_codec
+        = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    private readonly pbc::RepeatedField<pb::ByteString> bytesField_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> BytesField {
+      get { return bytesField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as RepeatedWellKnownTypes);
+    }
+
+    public bool Equals(RepeatedWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!anyField_.Equals(other.anyField_)) return false;
+      if(!apiField_.Equals(other.apiField_)) return false;
+      if(!durationField_.Equals(other.durationField_)) return false;
+      if(!emptyField_.Equals(other.emptyField_)) return false;
+      if(!fieldMaskField_.Equals(other.fieldMaskField_)) return false;
+      if(!sourceContextField_.Equals(other.sourceContextField_)) return false;
+      if(!structField_.Equals(other.structField_)) return false;
+      if(!timestampField_.Equals(other.timestampField_)) return false;
+      if(!typeField_.Equals(other.typeField_)) return false;
+      if(!doubleField_.Equals(other.doubleField_)) return false;
+      if(!floatField_.Equals(other.floatField_)) return false;
+      if(!int64Field_.Equals(other.int64Field_)) return false;
+      if(!uint64Field_.Equals(other.uint64Field_)) return false;
+      if(!int32Field_.Equals(other.int32Field_)) return false;
+      if(!uint32Field_.Equals(other.uint32Field_)) return false;
+      if(!boolField_.Equals(other.boolField_)) return false;
+      if(!stringField_.Equals(other.stringField_)) return false;
+      if(!bytesField_.Equals(other.bytesField_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= anyField_.GetHashCode();
+      hash ^= apiField_.GetHashCode();
+      hash ^= durationField_.GetHashCode();
+      hash ^= emptyField_.GetHashCode();
+      hash ^= fieldMaskField_.GetHashCode();
+      hash ^= sourceContextField_.GetHashCode();
+      hash ^= structField_.GetHashCode();
+      hash ^= timestampField_.GetHashCode();
+      hash ^= typeField_.GetHashCode();
+      hash ^= doubleField_.GetHashCode();
+      hash ^= floatField_.GetHashCode();
+      hash ^= int64Field_.GetHashCode();
+      hash ^= uint64Field_.GetHashCode();
+      hash ^= int32Field_.GetHashCode();
+      hash ^= uint32Field_.GetHashCode();
+      hash ^= boolField_.GetHashCode();
+      hash ^= stringField_.GetHashCode();
+      hash ^= bytesField_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      anyField_.WriteTo(output, _repeated_anyField_codec);
+      apiField_.WriteTo(output, _repeated_apiField_codec);
+      durationField_.WriteTo(output, _repeated_durationField_codec);
+      emptyField_.WriteTo(output, _repeated_emptyField_codec);
+      fieldMaskField_.WriteTo(output, _repeated_fieldMaskField_codec);
+      sourceContextField_.WriteTo(output, _repeated_sourceContextField_codec);
+      structField_.WriteTo(output, _repeated_structField_codec);
+      timestampField_.WriteTo(output, _repeated_timestampField_codec);
+      typeField_.WriteTo(output, _repeated_typeField_codec);
+      doubleField_.WriteTo(output, _repeated_doubleField_codec);
+      floatField_.WriteTo(output, _repeated_floatField_codec);
+      int64Field_.WriteTo(output, _repeated_int64Field_codec);
+      uint64Field_.WriteTo(output, _repeated_uint64Field_codec);
+      int32Field_.WriteTo(output, _repeated_int32Field_codec);
+      uint32Field_.WriteTo(output, _repeated_uint32Field_codec);
+      boolField_.WriteTo(output, _repeated_boolField_codec);
+      stringField_.WriteTo(output, _repeated_stringField_codec);
+      bytesField_.WriteTo(output, _repeated_bytesField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += anyField_.CalculateSize(_repeated_anyField_codec);
+      size += apiField_.CalculateSize(_repeated_apiField_codec);
+      size += durationField_.CalculateSize(_repeated_durationField_codec);
+      size += emptyField_.CalculateSize(_repeated_emptyField_codec);
+      size += fieldMaskField_.CalculateSize(_repeated_fieldMaskField_codec);
+      size += sourceContextField_.CalculateSize(_repeated_sourceContextField_codec);
+      size += structField_.CalculateSize(_repeated_structField_codec);
+      size += timestampField_.CalculateSize(_repeated_timestampField_codec);
+      size += typeField_.CalculateSize(_repeated_typeField_codec);
+      size += doubleField_.CalculateSize(_repeated_doubleField_codec);
+      size += floatField_.CalculateSize(_repeated_floatField_codec);
+      size += int64Field_.CalculateSize(_repeated_int64Field_codec);
+      size += uint64Field_.CalculateSize(_repeated_uint64Field_codec);
+      size += int32Field_.CalculateSize(_repeated_int32Field_codec);
+      size += uint32Field_.CalculateSize(_repeated_uint32Field_codec);
+      size += boolField_.CalculateSize(_repeated_boolField_codec);
+      size += stringField_.CalculateSize(_repeated_stringField_codec);
+      size += bytesField_.CalculateSize(_repeated_bytesField_codec);
+      return size;
+    }
+
+    public void MergeFrom(RepeatedWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      anyField_.Add(other.anyField_);
+      apiField_.Add(other.apiField_);
+      durationField_.Add(other.durationField_);
+      emptyField_.Add(other.emptyField_);
+      fieldMaskField_.Add(other.fieldMaskField_);
+      sourceContextField_.Add(other.sourceContextField_);
+      structField_.Add(other.structField_);
+      timestampField_.Add(other.timestampField_);
+      typeField_.Add(other.typeField_);
+      doubleField_.Add(other.doubleField_);
+      floatField_.Add(other.floatField_);
+      int64Field_.Add(other.int64Field_);
+      uint64Field_.Add(other.uint64Field_);
+      int32Field_.Add(other.int32Field_);
+      uint32Field_.Add(other.uint32Field_);
+      boolField_.Add(other.boolField_);
+      stringField_.Add(other.stringField_);
+      bytesField_.Add(other.bytesField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(input, _repeated_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(input, _repeated_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(input, _repeated_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(input, _repeated_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(input, _repeated_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(input, _repeated_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(input, _repeated_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(input, _repeated_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(input, _repeated_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(input, _repeated_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(input, _repeated_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(input, _repeated_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(input, _repeated_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(input, _repeated_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(input, _repeated_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(input, _repeated_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(input, _repeated_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
+    private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
+    public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneofWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneofWellKnownTypes(OneofWellKnownTypes other) : this() {
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.AnyField:
+          AnyField = other.AnyField.Clone();
+          break;
+        case OneofFieldOneofCase.ApiField:
+          ApiField = other.ApiField.Clone();
+          break;
+        case OneofFieldOneofCase.DurationField:
+          DurationField = other.DurationField.Clone();
+          break;
+        case OneofFieldOneofCase.EmptyField:
+          EmptyField = other.EmptyField.Clone();
+          break;
+        case OneofFieldOneofCase.FieldMaskField:
+          FieldMaskField = other.FieldMaskField.Clone();
+          break;
+        case OneofFieldOneofCase.SourceContextField:
+          SourceContextField = other.SourceContextField.Clone();
+          break;
+        case OneofFieldOneofCase.StructField:
+          StructField = other.StructField.Clone();
+          break;
+        case OneofFieldOneofCase.TimestampField:
+          TimestampField = other.TimestampField.Clone();
+          break;
+        case OneofFieldOneofCase.TypeField:
+          TypeField = other.TypeField.Clone();
+          break;
+        case OneofFieldOneofCase.DoubleField:
+          DoubleField = other.DoubleField;
+          break;
+        case OneofFieldOneofCase.FloatField:
+          FloatField = other.FloatField;
+          break;
+        case OneofFieldOneofCase.Int64Field:
+          Int64Field = other.Int64Field;
+          break;
+        case OneofFieldOneofCase.Uint64Field:
+          Uint64Field = other.Uint64Field;
+          break;
+        case OneofFieldOneofCase.Int32Field:
+          Int32Field = other.Int32Field;
+          break;
+        case OneofFieldOneofCase.Uint32Field:
+          Uint32Field = other.Uint32Field;
+          break;
+        case OneofFieldOneofCase.BoolField:
+          BoolField = other.BoolField;
+          break;
+        case OneofFieldOneofCase.StringField:
+          StringField = other.StringField;
+          break;
+        case OneofFieldOneofCase.BytesField:
+          BytesField = other.BytesField;
+          break;
+      }
+
+    }
+
+    public OneofWellKnownTypes Clone() {
+      return new OneofWellKnownTypes(this);
+    }
+
+    /// <summary>Field number for the "any_field" field.</summary>
+    public const int AnyFieldFieldNumber = 1;
+    public global::Google.Protobuf.WellKnownTypes.Any AnyField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.AnyField ? (global::Google.Protobuf.WellKnownTypes.Any) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.AnyField;
+      }
+    }
+
+    /// <summary>Field number for the "api_field" field.</summary>
+    public const int ApiFieldFieldNumber = 2;
+    public global::Google.Protobuf.WellKnownTypes.Api ApiField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.ApiField ? (global::Google.Protobuf.WellKnownTypes.Api) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.ApiField;
+      }
+    }
+
+    /// <summary>Field number for the "duration_field" field.</summary>
+    public const int DurationFieldFieldNumber = 3;
+    public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.DurationField ? (global::Google.Protobuf.WellKnownTypes.Duration) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.DurationField;
+      }
+    }
+
+    /// <summary>Field number for the "empty_field" field.</summary>
+    public const int EmptyFieldFieldNumber = 4;
+    public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.EmptyField ? (global::Google.Protobuf.WellKnownTypes.Empty) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.EmptyField;
+      }
+    }
+
+    /// <summary>Field number for the "field_mask_field" field.</summary>
+    public const int FieldMaskFieldFieldNumber = 5;
+    public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField ? (global::Google.Protobuf.WellKnownTypes.FieldMask) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.FieldMaskField;
+      }
+    }
+
+    /// <summary>Field number for the "source_context_field" field.</summary>
+    public const int SourceContextFieldFieldNumber = 6;
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.SourceContextField ? (global::Google.Protobuf.WellKnownTypes.SourceContext) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.SourceContextField;
+      }
+    }
+
+    /// <summary>Field number for the "struct_field" field.</summary>
+    public const int StructFieldFieldNumber = 7;
+    public global::Google.Protobuf.WellKnownTypes.Struct StructField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.StructField ? (global::Google.Protobuf.WellKnownTypes.Struct) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.StructField;
+      }
+    }
+
+    /// <summary>Field number for the "timestamp_field" field.</summary>
+    public const int TimestampFieldFieldNumber = 8;
+    public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.TimestampField ? (global::Google.Protobuf.WellKnownTypes.Timestamp) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.TimestampField;
+      }
+    }
+
+    /// <summary>Field number for the "type_field" field.</summary>
+    public const int TypeFieldFieldNumber = 9;
+    public global::Google.Protobuf.WellKnownTypes.Type TypeField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.TypeField ? (global::Google.Protobuf.WellKnownTypes.Type) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.TypeField;
+      }
+    }
+
+    /// <summary>Field number for the "double_field" field.</summary>
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _oneof_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
+    public double? DoubleField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.DoubleField ? (double?) oneofField_ : (double?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.DoubleField;
+      }
+    }
+
+    /// <summary>Field number for the "float_field" field.</summary>
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _oneof_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
+    public float? FloatField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.FloatField ? (float?) oneofField_ : (float?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.FloatField;
+      }
+    }
+
+    /// <summary>Field number for the "int64_field" field.</summary>
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _oneof_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
+    public long? Int64Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Int64Field ? (long?) oneofField_ : (long?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Int64Field;
+      }
+    }
+
+    /// <summary>Field number for the "uint64_field" field.</summary>
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _oneof_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    public ulong? Uint64Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Uint64Field ? (ulong?) oneofField_ : (ulong?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Uint64Field;
+      }
+    }
+
+    /// <summary>Field number for the "int32_field" field.</summary>
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _oneof_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
+    public int? Int32Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Int32Field ? (int?) oneofField_ : (int?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Int32Field;
+      }
+    }
+
+    /// <summary>Field number for the "uint32_field" field.</summary>
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _oneof_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
+    public uint? Uint32Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Uint32Field ? (uint?) oneofField_ : (uint?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Uint32Field;
+      }
+    }
+
+    /// <summary>Field number for the "bool_field" field.</summary>
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _oneof_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
+    public bool? BoolField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.BoolField ? (bool?) oneofField_ : (bool?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.BoolField;
+      }
+    }
+
+    /// <summary>Field number for the "string_field" field.</summary>
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _oneof_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
+    public string StringField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.StringField ? (string) oneofField_ : (string) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.StringField;
+      }
+    }
+
+    /// <summary>Field number for the "bytes_field" field.</summary>
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _oneof_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    public pb::ByteString BytesField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.BytesField ? (pb::ByteString) oneofField_ : (pb::ByteString) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.BytesField;
+      }
+    }
+
+    private object oneofField_;
+    /// <summary>Enum of possible cases for the "oneof_field" oneof.</summary>
+    public enum OneofFieldOneofCase {
+      None = 0,
+      AnyField = 1,
+      ApiField = 2,
+      DurationField = 3,
+      EmptyField = 4,
+      FieldMaskField = 5,
+      SourceContextField = 6,
+      StructField = 7,
+      TimestampField = 8,
+      TypeField = 9,
+      DoubleField = 10,
+      FloatField = 11,
+      Int64Field = 12,
+      Uint64Field = 13,
+      Int32Field = 14,
+      Uint32Field = 15,
+      BoolField = 16,
+      StringField = 17,
+      BytesField = 18,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneofWellKnownTypes);
+    }
+
+    public bool Equals(OneofWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(AnyField, other.AnyField)) return false;
+      if (!object.Equals(ApiField, other.ApiField)) return false;
+      if (!object.Equals(DurationField, other.DurationField)) return false;
+      if (!object.Equals(EmptyField, other.EmptyField)) return false;
+      if (!object.Equals(FieldMaskField, other.FieldMaskField)) return false;
+      if (!object.Equals(SourceContextField, other.SourceContextField)) return false;
+      if (!object.Equals(StructField, other.StructField)) return false;
+      if (!object.Equals(TimestampField, other.TimestampField)) return false;
+      if (!object.Equals(TypeField, other.TypeField)) return false;
+      if (DoubleField != other.DoubleField) return false;
+      if (FloatField != other.FloatField) return false;
+      if (Int64Field != other.Int64Field) return false;
+      if (Uint64Field != other.Uint64Field) return false;
+      if (Int32Field != other.Int32Field) return false;
+      if (Uint32Field != other.Uint32Field) return false;
+      if (BoolField != other.BoolField) return false;
+      if (StringField != other.StringField) return false;
+      if (BytesField != other.BytesField) return false;
+      if (OneofFieldCase != other.OneofFieldCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) hash ^= AnyField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) hash ^= ApiField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) hash ^= DurationField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) hash ^= EmptyField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) hash ^= FieldMaskField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) hash ^= SourceContextField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) hash ^= TypeField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= DoubleField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= FloatField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) hash ^= Int64Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) hash ^= Uint64Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) hash ^= Int32Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) hash ^= Uint32Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) hash ^= BoolField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) hash ^= StringField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) hash ^= BytesField.GetHashCode();
+      hash ^= (int) oneofFieldCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) {
+        _oneof_doubleField_codec.WriteTagAndValue(output, (double?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) {
+        _oneof_floatField_codec.WriteTagAndValue(output, (float?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) {
+        _oneof_int64Field_codec.WriteTagAndValue(output, (long?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) {
+        _oneof_uint64Field_codec.WriteTagAndValue(output, (ulong?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) {
+        _oneof_int32Field_codec.WriteTagAndValue(output, (int?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) {
+        _oneof_uint32Field_codec.WriteTagAndValue(output, (uint?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) {
+        _oneof_boolField_codec.WriteTagAndValue(output, (bool?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) {
+        _oneof_stringField_codec.WriteTagAndValue(output, (string) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
+        _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AnyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ApiField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DurationField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(EmptyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FieldMaskField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContextField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TimestampField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TypeField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) {
+        size += _oneof_doubleField_codec.CalculateSizeWithTag(DoubleField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) {
+        size += _oneof_floatField_codec.CalculateSizeWithTag(FloatField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) {
+        size += _oneof_int64Field_codec.CalculateSizeWithTag(Int64Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) {
+        size += _oneof_uint64Field_codec.CalculateSizeWithTag(Uint64Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) {
+        size += _oneof_int32Field_codec.CalculateSizeWithTag(Int32Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) {
+        size += _oneof_uint32Field_codec.CalculateSizeWithTag(Uint32Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) {
+        size += _oneof_boolField_codec.CalculateSizeWithTag(BoolField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) {
+        size += _oneof_stringField_codec.CalculateSizeWithTag(StringField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
+        size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneofWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.AnyField:
+          AnyField = other.AnyField;
+          break;
+        case OneofFieldOneofCase.ApiField:
+          ApiField = other.ApiField;
+          break;
+        case OneofFieldOneofCase.DurationField:
+          DurationField = other.DurationField;
+          break;
+        case OneofFieldOneofCase.EmptyField:
+          EmptyField = other.EmptyField;
+          break;
+        case OneofFieldOneofCase.FieldMaskField:
+          FieldMaskField = other.FieldMaskField;
+          break;
+        case OneofFieldOneofCase.SourceContextField:
+          SourceContextField = other.SourceContextField;
+          break;
+        case OneofFieldOneofCase.StructField:
+          StructField = other.StructField;
+          break;
+        case OneofFieldOneofCase.TimestampField:
+          TimestampField = other.TimestampField;
+          break;
+        case OneofFieldOneofCase.TypeField:
+          TypeField = other.TypeField;
+          break;
+        case OneofFieldOneofCase.DoubleField:
+          DoubleField = other.DoubleField;
+          break;
+        case OneofFieldOneofCase.FloatField:
+          FloatField = other.FloatField;
+          break;
+        case OneofFieldOneofCase.Int64Field:
+          Int64Field = other.Int64Field;
+          break;
+        case OneofFieldOneofCase.Uint64Field:
+          Uint64Field = other.Uint64Field;
+          break;
+        case OneofFieldOneofCase.Int32Field:
+          Int32Field = other.Int32Field;
+          break;
+        case OneofFieldOneofCase.Uint32Field:
+          Uint32Field = other.Uint32Field;
+          break;
+        case OneofFieldOneofCase.BoolField:
+          BoolField = other.BoolField;
+          break;
+        case OneofFieldOneofCase.StringField:
+          StringField = other.StringField;
+          break;
+        case OneofFieldOneofCase.BytesField:
+          BytesField = other.BytesField;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
+            if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+              subBuilder.MergeFrom(AnyField);
+            }
+            input.ReadMessage(subBuilder);
+            AnyField = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Google.Protobuf.WellKnownTypes.Api subBuilder = new global::Google.Protobuf.WellKnownTypes.Api();
+            if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+              subBuilder.MergeFrom(ApiField);
+            }
+            input.ReadMessage(subBuilder);
+            ApiField = subBuilder;
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.WellKnownTypes.Duration subBuilder = new global::Google.Protobuf.WellKnownTypes.Duration();
+            if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+              subBuilder.MergeFrom(DurationField);
+            }
+            input.ReadMessage(subBuilder);
+            DurationField = subBuilder;
+            break;
+          }
+          case 34: {
+            global::Google.Protobuf.WellKnownTypes.Empty subBuilder = new global::Google.Protobuf.WellKnownTypes.Empty();
+            if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+              subBuilder.MergeFrom(EmptyField);
+            }
+            input.ReadMessage(subBuilder);
+            EmptyField = subBuilder;
+            break;
+          }
+          case 42: {
+            global::Google.Protobuf.WellKnownTypes.FieldMask subBuilder = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+              subBuilder.MergeFrom(FieldMaskField);
+            }
+            input.ReadMessage(subBuilder);
+            FieldMaskField = subBuilder;
+            break;
+          }
+          case 50: {
+            global::Google.Protobuf.WellKnownTypes.SourceContext subBuilder = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+              subBuilder.MergeFrom(SourceContextField);
+            }
+            input.ReadMessage(subBuilder);
+            SourceContextField = subBuilder;
+            break;
+          }
+          case 58: {
+            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
+            if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+              subBuilder.MergeFrom(StructField);
+            }
+            input.ReadMessage(subBuilder);
+            StructField = subBuilder;
+            break;
+          }
+          case 66: {
+            global::Google.Protobuf.WellKnownTypes.Timestamp subBuilder = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+              subBuilder.MergeFrom(TimestampField);
+            }
+            input.ReadMessage(subBuilder);
+            TimestampField = subBuilder;
+            break;
+          }
+          case 74: {
+            global::Google.Protobuf.WellKnownTypes.Type subBuilder = new global::Google.Protobuf.WellKnownTypes.Type();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+              subBuilder.MergeFrom(TypeField);
+            }
+            input.ReadMessage(subBuilder);
+            TypeField = subBuilder;
+            break;
+          }
+          case 82: {
+            DoubleField = _oneof_doubleField_codec.Read(input);
+            break;
+          }
+          case 90: {
+            FloatField = _oneof_floatField_codec.Read(input);
+            break;
+          }
+          case 98: {
+            Int64Field = _oneof_int64Field_codec.Read(input);
+            break;
+          }
+          case 106: {
+            Uint64Field = _oneof_uint64Field_codec.Read(input);
+            break;
+          }
+          case 114: {
+            Int32Field = _oneof_int32Field_codec.Read(input);
+            break;
+          }
+          case 122: {
+            Uint32Field = _oneof_uint32Field_codec.Read(input);
+            break;
+          }
+          case 130: {
+            BoolField = _oneof_boolField_codec.Read(input);
+            break;
+          }
+          case 138: {
+            StringField = _oneof_stringField_codec.Read(input);
+            break;
+          }
+          case 146: {
+            BytesField = _oneof_bytesField_codec.Read(input);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A map field for each well-known type. We only
+  ///  need to worry about the value part of the map being the
+  ///  well-known types, as messages can't be map keys.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
+    private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
+    public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MapWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MapWellKnownTypes(MapWellKnownTypes other) : this() {
+      anyField_ = other.anyField_.Clone();
+      apiField_ = other.apiField_.Clone();
+      durationField_ = other.durationField_.Clone();
+      emptyField_ = other.emptyField_.Clone();
+      fieldMaskField_ = other.fieldMaskField_.Clone();
+      sourceContextField_ = other.sourceContextField_.Clone();
+      structField_ = other.structField_.Clone();
+      timestampField_ = other.timestampField_.Clone();
+      typeField_ = other.typeField_.Clone();
+      doubleField_ = other.doubleField_.Clone();
+      floatField_ = other.floatField_.Clone();
+      int64Field_ = other.int64Field_.Clone();
+      uint64Field_ = other.uint64Field_.Clone();
+      int32Field_ = other.int32Field_.Clone();
+      uint32Field_ = other.uint32Field_.Clone();
+      boolField_ = other.boolField_.Clone();
+      stringField_ = other.stringField_.Clone();
+      bytesField_ = other.bytesField_.Clone();
+    }
+
+    public MapWellKnownTypes Clone() {
+      return new MapWellKnownTypes(this);
+    }
+
+    /// <summary>Field number for the "any_field" field.</summary>
+    public const int AnyFieldFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>.Codec _map_anyField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Any.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> AnyField {
+      get { return anyField_; }
+    }
+
+    /// <summary>Field number for the "api_field" field.</summary>
+    public const int ApiFieldFieldNumber = 2;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>.Codec _map_apiField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser), 18);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> ApiField {
+      get { return apiField_; }
+    }
+
+    /// <summary>Field number for the "duration_field" field.</summary>
+    public const int DurationFieldFieldNumber = 3;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>.Codec _map_durationField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Duration.Parser), 26);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
+      get { return durationField_; }
+    }
+
+    /// <summary>Field number for the "empty_field" field.</summary>
+    public const int EmptyFieldFieldNumber = 4;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>.Codec _map_emptyField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Empty.Parser), 34);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
+      get { return emptyField_; }
+    }
+
+    /// <summary>Field number for the "field_mask_field" field.</summary>
+    public const int FieldMaskFieldFieldNumber = 5;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>.Codec _map_fieldMaskField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser), 42);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
+      get { return fieldMaskField_; }
+    }
+
+    /// <summary>Field number for the "source_context_field" field.</summary>
+    public const int SourceContextFieldFieldNumber = 6;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>.Codec _map_sourceContextField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser), 50);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
+      get { return sourceContextField_; }
+    }
+
+    /// <summary>Field number for the "struct_field" field.</summary>
+    public const int StructFieldFieldNumber = 7;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>.Codec _map_structField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Struct.Parser), 58);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> StructField {
+      get { return structField_; }
+    }
+
+    /// <summary>Field number for the "timestamp_field" field.</summary>
+    public const int TimestampFieldFieldNumber = 8;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>.Codec _map_timestampField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser), 66);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
+      get { return timestampField_; }
+    }
+
+    /// <summary>Field number for the "type_field" field.</summary>
+    public const int TypeFieldFieldNumber = 9;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>.Codec _map_typeField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Type.Parser), 74);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> TypeField {
+      get { return typeField_; }
+    }
+
+    /// <summary>Field number for the "double_field" field.</summary>
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pbc::MapField<int, double?>.Codec _map_doubleField_codec
+        = new pbc::MapField<int, double?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<double>(18), 82);
+    private readonly pbc::MapField<int, double?> doubleField_ = new pbc::MapField<int, double?>();
+    public pbc::MapField<int, double?> DoubleField {
+      get { return doubleField_; }
+    }
+
+    /// <summary>Field number for the "float_field" field.</summary>
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pbc::MapField<int, float?>.Codec _map_floatField_codec
+        = new pbc::MapField<int, float?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<float>(18), 90);
+    private readonly pbc::MapField<int, float?> floatField_ = new pbc::MapField<int, float?>();
+    public pbc::MapField<int, float?> FloatField {
+      get { return floatField_; }
+    }
+
+    /// <summary>Field number for the "int64_field" field.</summary>
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pbc::MapField<int, long?>.Codec _map_int64Field_codec
+        = new pbc::MapField<int, long?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<long>(18), 98);
+    private readonly pbc::MapField<int, long?> int64Field_ = new pbc::MapField<int, long?>();
+    public pbc::MapField<int, long?> Int64Field {
+      get { return int64Field_; }
+    }
+
+    /// <summary>Field number for the "uint64_field" field.</summary>
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pbc::MapField<int, ulong?>.Codec _map_uint64Field_codec
+        = new pbc::MapField<int, ulong?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<ulong>(18), 106);
+    private readonly pbc::MapField<int, ulong?> uint64Field_ = new pbc::MapField<int, ulong?>();
+    public pbc::MapField<int, ulong?> Uint64Field {
+      get { return uint64Field_; }
+    }
+
+    /// <summary>Field number for the "int32_field" field.</summary>
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pbc::MapField<int, int?>.Codec _map_int32Field_codec
+        = new pbc::MapField<int, int?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<int>(18), 114);
+    private readonly pbc::MapField<int, int?> int32Field_ = new pbc::MapField<int, int?>();
+    public pbc::MapField<int, int?> Int32Field {
+      get { return int32Field_; }
+    }
+
+    /// <summary>Field number for the "uint32_field" field.</summary>
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pbc::MapField<int, uint?>.Codec _map_uint32Field_codec
+        = new pbc::MapField<int, uint?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<uint>(18), 122);
+    private readonly pbc::MapField<int, uint?> uint32Field_ = new pbc::MapField<int, uint?>();
+    public pbc::MapField<int, uint?> Uint32Field {
+      get { return uint32Field_; }
+    }
+
+    /// <summary>Field number for the "bool_field" field.</summary>
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pbc::MapField<int, bool?>.Codec _map_boolField_codec
+        = new pbc::MapField<int, bool?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<bool>(18), 130);
+    private readonly pbc::MapField<int, bool?> boolField_ = new pbc::MapField<int, bool?>();
+    public pbc::MapField<int, bool?> BoolField {
+      get { return boolField_; }
+    }
+
+    /// <summary>Field number for the "string_field" field.</summary>
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pbc::MapField<int, string>.Codec _map_stringField_codec
+        = new pbc::MapField<int, string>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<string>(18), 138);
+    private readonly pbc::MapField<int, string> stringField_ = new pbc::MapField<int, string>();
+    public pbc::MapField<int, string> StringField {
+      get { return stringField_; }
+    }
+
+    /// <summary>Field number for the "bytes_field" field.</summary>
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pbc::MapField<int, pb::ByteString>.Codec _map_bytesField_codec
+        = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<pb::ByteString>(18), 146);
+    private readonly pbc::MapField<int, pb::ByteString> bytesField_ = new pbc::MapField<int, pb::ByteString>();
+    public pbc::MapField<int, pb::ByteString> BytesField {
+      get { return bytesField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MapWellKnownTypes);
+    }
+
+    public bool Equals(MapWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!AnyField.Equals(other.AnyField)) return false;
+      if (!ApiField.Equals(other.ApiField)) return false;
+      if (!DurationField.Equals(other.DurationField)) return false;
+      if (!EmptyField.Equals(other.EmptyField)) return false;
+      if (!FieldMaskField.Equals(other.FieldMaskField)) return false;
+      if (!SourceContextField.Equals(other.SourceContextField)) return false;
+      if (!StructField.Equals(other.StructField)) return false;
+      if (!TimestampField.Equals(other.TimestampField)) return false;
+      if (!TypeField.Equals(other.TypeField)) return false;
+      if (!DoubleField.Equals(other.DoubleField)) return false;
+      if (!FloatField.Equals(other.FloatField)) return false;
+      if (!Int64Field.Equals(other.Int64Field)) return false;
+      if (!Uint64Field.Equals(other.Uint64Field)) return false;
+      if (!Int32Field.Equals(other.Int32Field)) return false;
+      if (!Uint32Field.Equals(other.Uint32Field)) return false;
+      if (!BoolField.Equals(other.BoolField)) return false;
+      if (!StringField.Equals(other.StringField)) return false;
+      if (!BytesField.Equals(other.BytesField)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= AnyField.GetHashCode();
+      hash ^= ApiField.GetHashCode();
+      hash ^= DurationField.GetHashCode();
+      hash ^= EmptyField.GetHashCode();
+      hash ^= FieldMaskField.GetHashCode();
+      hash ^= SourceContextField.GetHashCode();
+      hash ^= StructField.GetHashCode();
+      hash ^= TimestampField.GetHashCode();
+      hash ^= TypeField.GetHashCode();
+      hash ^= DoubleField.GetHashCode();
+      hash ^= FloatField.GetHashCode();
+      hash ^= Int64Field.GetHashCode();
+      hash ^= Uint64Field.GetHashCode();
+      hash ^= Int32Field.GetHashCode();
+      hash ^= Uint32Field.GetHashCode();
+      hash ^= BoolField.GetHashCode();
+      hash ^= StringField.GetHashCode();
+      hash ^= BytesField.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      anyField_.WriteTo(output, _map_anyField_codec);
+      apiField_.WriteTo(output, _map_apiField_codec);
+      durationField_.WriteTo(output, _map_durationField_codec);
+      emptyField_.WriteTo(output, _map_emptyField_codec);
+      fieldMaskField_.WriteTo(output, _map_fieldMaskField_codec);
+      sourceContextField_.WriteTo(output, _map_sourceContextField_codec);
+      structField_.WriteTo(output, _map_structField_codec);
+      timestampField_.WriteTo(output, _map_timestampField_codec);
+      typeField_.WriteTo(output, _map_typeField_codec);
+      doubleField_.WriteTo(output, _map_doubleField_codec);
+      floatField_.WriteTo(output, _map_floatField_codec);
+      int64Field_.WriteTo(output, _map_int64Field_codec);
+      uint64Field_.WriteTo(output, _map_uint64Field_codec);
+      int32Field_.WriteTo(output, _map_int32Field_codec);
+      uint32Field_.WriteTo(output, _map_uint32Field_codec);
+      boolField_.WriteTo(output, _map_boolField_codec);
+      stringField_.WriteTo(output, _map_stringField_codec);
+      bytesField_.WriteTo(output, _map_bytesField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += anyField_.CalculateSize(_map_anyField_codec);
+      size += apiField_.CalculateSize(_map_apiField_codec);
+      size += durationField_.CalculateSize(_map_durationField_codec);
+      size += emptyField_.CalculateSize(_map_emptyField_codec);
+      size += fieldMaskField_.CalculateSize(_map_fieldMaskField_codec);
+      size += sourceContextField_.CalculateSize(_map_sourceContextField_codec);
+      size += structField_.CalculateSize(_map_structField_codec);
+      size += timestampField_.CalculateSize(_map_timestampField_codec);
+      size += typeField_.CalculateSize(_map_typeField_codec);
+      size += doubleField_.CalculateSize(_map_doubleField_codec);
+      size += floatField_.CalculateSize(_map_floatField_codec);
+      size += int64Field_.CalculateSize(_map_int64Field_codec);
+      size += uint64Field_.CalculateSize(_map_uint64Field_codec);
+      size += int32Field_.CalculateSize(_map_int32Field_codec);
+      size += uint32Field_.CalculateSize(_map_uint32Field_codec);
+      size += boolField_.CalculateSize(_map_boolField_codec);
+      size += stringField_.CalculateSize(_map_stringField_codec);
+      size += bytesField_.CalculateSize(_map_bytesField_codec);
+      return size;
+    }
+
+    public void MergeFrom(MapWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      anyField_.Add(other.anyField_);
+      apiField_.Add(other.apiField_);
+      durationField_.Add(other.durationField_);
+      emptyField_.Add(other.emptyField_);
+      fieldMaskField_.Add(other.fieldMaskField_);
+      sourceContextField_.Add(other.sourceContextField_);
+      structField_.Add(other.structField_);
+      timestampField_.Add(other.timestampField_);
+      typeField_.Add(other.typeField_);
+      doubleField_.Add(other.doubleField_);
+      floatField_.Add(other.floatField_);
+      int64Field_.Add(other.int64Field_);
+      uint64Field_.Add(other.uint64Field_);
+      int32Field_.Add(other.int32Field_);
+      uint32Field_.Add(other.uint32Field_);
+      boolField_.Add(other.boolField_);
+      stringField_.Add(other.stringField_);
+      bytesField_.Add(other.bytesField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(input, _map_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(input, _map_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(input, _map_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(input, _map_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(input, _map_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(input, _map_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(input, _map_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(input, _map_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(input, _map_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(input, _map_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(input, _map_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(input, _map_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(input, _map_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(input, _map_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(input, _map_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(input, _map_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(input, _map_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(input, _map_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
new file mode 100644
index 0000000..f21be7d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
@@ -0,0 +1,116 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class AnyTest
+    {
+        [Test]
+        public void Pack()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            Assert.AreEqual("type.googleapis.com/protobuf_unittest.TestAllTypes", any.TypeUrl);
+            Assert.AreEqual(message.CalculateSize(), any.Value.Length);
+        }
+
+        [Test]
+        public void Pack_WithCustomPrefix()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message, "foo.bar/baz");
+            Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl);
+            Assert.AreEqual(message.CalculateSize(), any.Value.Length);
+        }
+
+        [Test]
+        public void Pack_WithCustomPrefixTrailingSlash()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message, "foo.bar/baz/");
+            Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl);
+            Assert.AreEqual(message.CalculateSize(), any.Value.Length);
+        }
+
+        [Test]
+        public void Unpack_WrongType()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            Assert.Throws<InvalidProtocolBufferException>(() => any.Unpack<TestOneof>());
+        }
+
+        [Test]
+        public void Unpack_Success()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            var unpacked = any.Unpack<TestAllTypes>();
+            Assert.AreEqual(message, unpacked);
+        }
+
+        [Test]
+        public void Unpack_CustomPrefix_Success()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message, "foo.bar/baz");
+            var unpacked = any.Unpack<TestAllTypes>();
+            Assert.AreEqual(message, unpacked);
+        }
+
+        [Test]
+        public void ToString_WithValues()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            var text = any.ToString();
+            Assert.That(text, Is.StringContaining("\"@value\": \"" + message.ToByteString().ToBase64() + "\""));
+        }
+
+        [Test]
+        public void ToString_Empty()
+        {
+            var any = new Any();
+            Assert.AreEqual("{ \"@type\": \"\", \"@value\": \"\" }", any.ToString());
+        }
+
+        [Test]
+        public void ToString_MessageContainingAny()
+        {
+            var message = new TestWellKnownTypes { AnyField = new Any() };
+            Assert.AreEqual("{ \"anyField\": { \"@type\": \"\", \"@value\": \"\" } }", message.ToString());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
new file mode 100644
index 0000000..141faf8
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
@@ -0,0 +1,132 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using NUnit.Framework;
+using System;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class DurationTest
+    {
+        [Test]
+        public void ToTimeSpan()
+        {
+            Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 1 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = -1 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromMilliseconds(1), new Duration { Nanos = 1000000 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromMilliseconds(-1), new Duration { Nanos = -1000000 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(1), new Duration { Nanos = 100 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(-1), new Duration { Nanos = -100 }.ToTimeSpan());
+
+            // Rounding is towards 0
+            Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan());
+        }
+
+        [Test]
+        public void Addition()
+        {
+            Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = -2, Nanos = -100000000 },
+                new Duration { Seconds = -1, Nanos = -600000000 } + new Duration { Nanos = -500000000 });
+            Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = -500000000 });
+
+            // Non-normalized durations, or non-normalized intermediate results
+            Assert.AreEqual(new Duration { Seconds = 1 },
+                new Duration { Seconds = 1, Nanos = -500000000 } + new Duration { Nanos = 500000000 });
+
+            Assert.AreEqual(new Duration { Nanos = -900000000 },
+                new Duration { Seconds = -1, Nanos = -100000000 } + new Duration { Nanos = 200000000 });
+            Assert.AreEqual(new Duration { Nanos = 900000000 },
+                new Duration { Seconds = 1, Nanos = 100000000 } + new Duration { Nanos = -200000000 });
+        }
+
+        [Test]
+        public void Subtraction()
+        {
+            Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = -1, Nanos = -100000000 },
+                new Duration { Seconds = -1, Nanos = -600000000 } - new Duration { Nanos = -500000000 });
+            Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = -500000000 });
+
+            // Non-normalized durations
+            Assert.AreEqual(new Duration(),
+                new Duration { Seconds = 1, Nanos = -500000000 } - new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = 1 },
+                new Duration { Nanos = 2000000000 } - new Duration { Nanos = 1000000000 });
+        }
+
+        [Test]
+        public void FromTimeSpan()
+        {
+            Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1)));
+            Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1)));
+        }
+
+        [Test]
+        [TestCase(0, Duration.MaxNanoseconds + 1)]
+        [TestCase(0, Duration.MinNanoseconds - 1)]
+        [TestCase(Duration.MinSeconds - 1, 0)]
+        [TestCase(Duration.MaxSeconds + 1, 0)]
+        [TestCase(1, -1)]
+        [TestCase(-1, 1)]
+        public void ToTimeSpan_Invalid(long seconds, int nanoseconds)
+        {
+            var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+            Assert.Throws<InvalidOperationException>(() => duration.ToTimeSpan());
+        }
+
+        [Test]
+        [TestCase(0, Duration.MaxNanoseconds)]
+        [TestCase(0, Duration.MinNanoseconds)]
+        [TestCase(Duration.MinSeconds, Duration.MinNanoseconds)]
+        [TestCase(Duration.MaxSeconds, Duration.MaxNanoseconds)]
+        public void ToTimeSpan_Valid(long seconds, int nanoseconds)
+        {
+            // Only testing that these values don't throw, unlike their similar tests in ToTimeSpan_Invalid
+            var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+            duration.ToTimeSpan();
+        }
+
+        [Test]
+        public void ToString_NonNormalized()
+        {
+            // Just a single example should be sufficient...
+            var duration = new Duration { Seconds = 1, Nanos = -1 };
+            Assert.AreEqual("{ \"@warning\": \"Invalid Duration\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
new file mode 100644
index 0000000..89bc827
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
@@ -0,0 +1,62 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+#endregion
+
+
+using NUnit.Framework;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class FieldMaskTest
+    {
+        [Test]
+        [TestCase("foo__bar")]
+        [TestCase("foo_3_ar")]
+        [TestCase("fooBar")]
+        public void ToString_Invalid(string input)
+        {
+            var mask = new FieldMask { Paths = { input } };
+            var text = mask.ToString();
+            // More specific test below
+            Assert.That(text, Is.StringContaining("@warning"));
+            Assert.That(text, Is.StringContaining(input));
+        }
+
+        [Test]
+        public void ToString_Invalid_Precise()
+        {
+            var mask = new FieldMask { Paths = { "x", "foo__bar", @"x\y" } };
+            Assert.AreEqual(
+                "{ \"@warning\": \"Invalid FieldMask\", \"paths\": [ \"x\", \"foo__bar\", \"x\\\\y\" ] }",
+                mask.ToString());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
new file mode 100644
index 0000000..9ecd24c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
@@ -0,0 +1,115 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using NUnit.Framework;
+using System;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class TimestampTest
+    {
+        [Test]
+        public void FromAndToDateTime()
+        {
+            DateTime utcMin = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+            DateTime utcMax = DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
+            AssertRoundtrip(new Timestamp { Seconds = -62135596800 }, utcMin);
+            AssertRoundtrip(new Timestamp { Seconds = 253402300799, Nanos = 999999900 }, utcMax);
+            AssertRoundtrip(new Timestamp(), new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Nanos = 1000000}, new DateTime(1970, 1, 1, 0, 0, 0, 1, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = -1, Nanos = 999000000 }, new DateTime(1969, 12, 31, 23, 59, 59, 999, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = 3600 }, new DateTime(1970, 1, 1, 1, 0, 0, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = -3600 }, new DateTime(1969, 12, 31, 23, 0, 0, DateTimeKind.Utc));
+        }
+
+        [Test]
+        public void ToDateTimeTruncation()
+        {
+            var t1 = new Timestamp { Seconds = 1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
+            Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc).AddMilliseconds(1), t1.ToDateTime());
+
+            var t2 = new Timestamp { Seconds = -1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
+            Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 59).AddMilliseconds(1), t2.ToDateTime());
+        }
+
+        [Test]
+        [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, Timestamp.MaxNanos)]
+        [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)]
+        [TestCase(0, -1)]
+        [TestCase(0, Timestamp.MaxNanos + 1)]
+        public void ToDateTime_OutOfRange(long seconds, int nanoseconds)
+        {
+            var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+            Assert.Throws<InvalidOperationException>(() => value.ToDateTime());
+        }
+
+        // 1ns larger or smaller than the above values
+        [Test]
+        [TestCase(Timestamp.UnixSecondsAtBclMinValue, 0)]
+        [TestCase(Timestamp.UnixSecondsAtBclMaxValue, Timestamp.MaxNanos)]
+        [TestCase(0, 0)]
+        [TestCase(0, Timestamp.MaxNanos)]
+        public void ToDateTime_ValidBoundaries(long seconds, int nanoseconds)
+        {
+            var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+            value.ToDateTime();
+        }
+
+        private static void AssertRoundtrip(Timestamp timestamp, DateTime dateTime)
+        {
+            Assert.AreEqual(timestamp, Timestamp.FromDateTime(dateTime));
+            Assert.AreEqual(dateTime, timestamp.ToDateTime());
+            Assert.AreEqual(DateTimeKind.Utc, timestamp.ToDateTime().Kind);
+        }
+
+        [Test]
+        public void Arithmetic()
+        {
+            Timestamp t1 = new Timestamp { Seconds = 10000, Nanos = 5000 };
+            Timestamp t2 = new Timestamp { Seconds = 8000, Nanos = 10000 };
+            Duration difference = new Duration { Seconds = 1999, Nanos = Duration.NanosecondsPerSecond - 5000 };
+            Assert.AreEqual(difference, t1 - t2);
+            Assert.AreEqual(-difference, t2 - t1);
+            
+            Assert.AreEqual(t1, t2 + difference);
+            Assert.AreEqual(t2, t1 - difference);
+        }
+
+        [Test]
+        public void ToString_NonNormalized()
+        {
+            // Just a single example should be sufficient...
+            var duration = new Timestamp { Seconds = 1, Nanos = -1 };
+            Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
new file mode 100644
index 0000000..5b7185d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
@@ -0,0 +1,421 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System.Collections;
+using System.IO;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class WrappersTest
+    {
+        [Test]
+        public void NullIsDefault()
+        {
+            var message = new TestWellKnownTypes();
+            Assert.IsNull(message.StringField);
+            Assert.IsNull(message.BytesField);
+            Assert.IsNull(message.BoolField);
+            Assert.IsNull(message.FloatField);
+            Assert.IsNull(message.DoubleField);
+            Assert.IsNull(message.Int32Field);
+            Assert.IsNull(message.Int64Field);
+            Assert.IsNull(message.Uint32Field);
+            Assert.IsNull(message.Uint64Field);
+        }
+
+        [Test]
+        public void NonDefaultSingleValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "x",
+                BytesField = ByteString.CopyFrom(1, 2, 3),
+                BoolField = true,
+                FloatField = 12.5f,
+                DoubleField = 12.25d,
+                Int32Field = 1,
+                Int64Field = 2,
+                Uint32Field = 3,
+                Uint64Field = 4
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual("x", parsed.StringField);
+            Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField);
+            Assert.AreEqual(true, parsed.BoolField);
+            Assert.AreEqual(12.5f, parsed.FloatField);
+            Assert.AreEqual(12.25d, parsed.DoubleField);
+            Assert.AreEqual(1, parsed.Int32Field);
+            Assert.AreEqual(2L, parsed.Int64Field);
+            Assert.AreEqual(3U, parsed.Uint32Field);
+            Assert.AreEqual(4UL, parsed.Uint64Field);
+        }
+
+        [Test]
+        public void NonNullDefaultIsPreservedThroughSerialization()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "",
+                BytesField = ByteString.Empty,
+                BoolField = false,
+                FloatField = 0f,
+                DoubleField = 0d,
+                Int32Field = 0,
+                Int64Field = 0,
+                Uint32Field = 0,
+                Uint64Field = 0
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual("", parsed.StringField);
+            Assert.AreEqual(ByteString.Empty, parsed.BytesField);
+            Assert.AreEqual(false, parsed.BoolField);
+            Assert.AreEqual(0f, parsed.FloatField);
+            Assert.AreEqual(0d, parsed.DoubleField);
+            Assert.AreEqual(0, parsed.Int32Field);
+            Assert.AreEqual(0L, parsed.Int64Field);
+            Assert.AreEqual(0U, parsed.Uint32Field);
+            Assert.AreEqual(0UL, parsed.Uint64Field);
+        }
+
+        [Test]
+        public void RepeatedWrappersProhibitNullItems()
+        {
+            var message = new RepeatedWellKnownTypes();
+            Assert.Throws<ArgumentNullException>(() => message.BoolField.Add((bool?) null));
+            Assert.Throws<ArgumentNullException>(() => message.Int32Field.Add((int?) null));
+            Assert.Throws<ArgumentNullException>(() => message.StringField.Add((string) null));
+            Assert.Throws<ArgumentNullException>(() => message.BytesField.Add((ByteString) null));
+        }
+
+        [Test]
+        public void RepeatedWrappersSerializeDeserialize()
+        {
+            var message = new RepeatedWellKnownTypes
+            {
+                BoolField = { true, false },
+                BytesField = { ByteString.CopyFrom(1, 2, 3), ByteString.CopyFrom(4, 5, 6), ByteString.Empty },
+                DoubleField = { 12.5, -1.5, 0d },
+                FloatField = { 123.25f, -20f, 0f },
+                Int32Field = { int.MaxValue, int.MinValue, 0 },
+                Int64Field = { long.MaxValue, long.MinValue, 0L },                
+                StringField = { "First", "Second", "" },
+                Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
+                Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
+            };
+            var bytes = message.ToByteArray();
+            var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual(message, parsed);
+            // Just to test a single value for sanity...
+            Assert.AreEqual("Second", message.StringField[1]);
+        }
+
+        [Test]
+        public void RepeatedWrappersBinaryFormat()
+        {
+            // At one point we accidentally used a packed format for repeated wrappers, which is wrong (and weird).
+            // This test is just to prove that we use the right format.
+
+            var rawOutput = new MemoryStream();
+            var output = new CodedOutputStream(rawOutput);
+            // Write a value of 5
+            output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(2);
+            output.WriteTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint);
+            output.WriteInt32(5);
+            // Write a value of 0 (empty message)
+            output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(0);
+            output.Flush();
+            var expectedBytes = rawOutput.ToArray();
+
+            var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } };
+            var actualBytes = message.ToByteArray();
+            Assert.AreEqual(expectedBytes, actualBytes);
+        }
+
+        [Test]
+        public void MapWrappersSerializeDeserialize()
+        {
+            // Note: no null values here, as they are prohibited in map fields
+            // (despite being representable).
+            var message = new MapWellKnownTypes
+            {
+                BoolField = { { 10, false }, { 20, true } },
+                BytesField = {
+                    { -1, ByteString.CopyFrom(1, 2, 3) },
+                    { 10, ByteString.CopyFrom(4, 5, 6) },
+                    { 1000, ByteString.Empty },
+                },
+                DoubleField = { { 1, 12.5 }, { 10, -1.5 }, { 20, 0d } },
+                FloatField = { { 2, 123.25f }, { 3, -20f }, { 4, 0f } },
+                Int32Field = { { 5, int.MaxValue }, { 6, int.MinValue }, { 7, 0 } },
+                Int64Field = { { 8, long.MaxValue }, { 9, long.MinValue }, { 10, 0L } },
+                StringField = { { 11, "First" }, { 12, "Second" }, { 13, "" } },
+                Uint32Field = { { 15, uint.MaxValue }, { 16, uint.MinValue }, { 17, 0U } },
+                Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } },
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual(message, parsed);
+            // Just to test a single value for sanity...
+            Assert.AreEqual("Second", message.StringField[12]);
+        }
+
+        [Test]
+        public void Reflection_SingleValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "x",
+                BytesField = ByteString.CopyFrom(1, 2, 3),
+                BoolField = true,
+                FloatField = 12.5f,
+                DoubleField = 12.25d,
+                Int32Field = 1,
+                Int64Field = 2,
+                Uint32Field = 3,
+                Uint64Field = 4
+            };
+            var fields = TestWellKnownTypes.Descriptor.Fields;
+
+            Assert.AreEqual("x", fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), fields[TestWellKnownTypes.BytesFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(true, fields[TestWellKnownTypes.BoolFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(12.5f, fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(12.25d, fields[TestWellKnownTypes.DoubleFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(1, fields[TestWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(2L, fields[TestWellKnownTypes.Int64FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(3U, fields[TestWellKnownTypes.Uint32FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(4UL, fields[TestWellKnownTypes.Uint64FieldFieldNumber].Accessor.GetValue(message));
+
+            // And a couple of null fields...
+            message.StringField = null;
+            message.FloatField = null;
+            Assert.IsNull(fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
+            Assert.IsNull(fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
+        }
+
+        [Test]
+        public void Reflection_RepeatedFields()
+        {
+            // Just a single example... note that we can't have a null value here
+            var message = new RepeatedWellKnownTypes { Int32Field = { 1, 2 } };
+            var fields = RepeatedWellKnownTypes.Descriptor.Fields;
+            var list = (IList) fields[RepeatedWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
+            CollectionAssert.AreEqual(new[] { 1, 2 }, list);
+        }
+
+        [Test]
+        public void Reflection_MapFields()
+        {
+            // Just a single example... note that we can't have a null value here despite the value type being int?
+            var message = new MapWellKnownTypes { Int32Field = { { 1, 2 } } };
+            var fields = MapWellKnownTypes.Descriptor.Fields;
+            var dictionary = (IDictionary) fields[MapWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
+            Assert.AreEqual(2, dictionary[1]);
+        }
+
+        [Test]
+        public void Oneof()
+        {
+            var message = new OneofWellKnownTypes { EmptyField = new Empty() };
+            // Start off with a non-wrapper
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.EmptyField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.StringField = "foo";
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.StringField = "foo";
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.DoubleField = 0.0f;
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.DoubleField = 1.0f;
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.ClearOneofField();
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+        }
+
+        private void AssertOneofRoundTrip(OneofWellKnownTypes message)
+        {
+            // Normal roundtrip, but explicitly checking the case...
+            var bytes = message.ToByteArray();
+            var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+            Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase);
+        }
+
+        [Test]
+        [TestCase("x", "y", "y")]
+        [TestCase("x", "", "x")]
+        [TestCase("x", null, "x")]
+        [TestCase("", "y", "y")]
+        [TestCase("", "", "")]
+        [TestCase("", null, "")]
+        [TestCase(null, "y", "y")]
+        [TestCase(null, "", "")]
+        [TestCase(null, null, null)]
+        public void Merging(string original, string merged, string expected)
+        {
+            var originalMessage = new TestWellKnownTypes { StringField = original };
+            var mergingMessage = new TestWellKnownTypes { StringField = merged };
+            originalMessage.MergeFrom(mergingMessage);
+            Assert.AreEqual(expected, originalMessage.StringField);
+
+            // Try it using MergeFrom(CodedInputStream) too...
+            originalMessage = new TestWellKnownTypes { StringField = original };
+            originalMessage.MergeFrom(mergingMessage.ToByteArray());
+            Assert.AreEqual(expected, originalMessage.StringField);
+        }
+
+        // Merging is odd with wrapper types, due to the way that default values aren't emitted in
+        // the binary stream. In fact we cheat a little bit - a message with an explicitly present default
+        // value will have that default value ignored. See issue 615. Fixing this would require significant upheaval to
+        // the FieldCodec side of things.
+        [Test]
+        public void MergingStreamExplicitValue()
+        {
+            var message = new TestWellKnownTypes { Int32Field = 5 };
+
+            // Create a byte array which has the data of an Int32Value explicitly containing a value of 0.
+            // This wouldn't normally happen.
+            byte[] bytes;
+            var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint);
+            using (var stream = new MemoryStream())
+            {
+                var coded = new CodedOutputStream(stream);
+                coded.WriteTag(wrapperTag);
+                coded.WriteLength(2); // valueTag + a value 0, each one byte
+                coded.WriteTag(valueTag);
+                coded.WriteInt32(0);
+                coded.Flush();
+                bytes = stream.ToArray();
+            }
+
+            message.MergeFrom(bytes);
+            // A normal implementation would have 0 now, as the explicit default would have been overwritten the 5.
+            // With the FieldCodec for Nullable<int>, we can't tell the difference between an implicit 0 and an explicit 0.
+            Assert.AreEqual(5, message.Int32Field);
+        }
+
+        [Test]
+        public void MergingStreamNoValue()
+        {
+            var message = new TestWellKnownTypes { Int32Field = 5 };
+
+            // Create a byte array which an Int32 field, but with no value.
+            var bytes = new TestWellKnownTypes { Int32Field = 0 }.ToByteArray();
+            Assert.AreEqual(2, bytes.Length); // The tag for Int32Field is a single byte, then a byte indicating a 0-length message.
+            message.MergeFrom(bytes);
+
+            // The "implicit" 0 did *not* overwrite the value.
+            // (This is the correct behaviour.)
+            Assert.AreEqual(5, message.Int32Field);
+        }
+
+        // All permutations of origin/merging value being null, zero (default) or non-default.
+        // As this is the in-memory version, we don't need to worry about the difference between implicit and explicit 0.
+        [Test]
+        [TestCase(null, null, null)]
+        [TestCase(null, 0, 0)]
+        [TestCase(null, 5, 5)]
+        [TestCase(0, null, 0)]
+        [TestCase(0, 0, 0)]
+        [TestCase(0, 5, 5)]
+        [TestCase(5, null, 5)]
+        [TestCase(5, 0, 5)]
+        [TestCase(5, 10, 10)]
+        public void MergingMessageWithZero(int? originValue, int? mergingValue, int? expectedResult)
+        {
+            // This differs from the MergingStreamCornerCase because when we merge message *objects*,
+            // we ignore default values from the "source".
+            var message1 = new TestWellKnownTypes { Int32Field = originValue };
+            var message2 = new TestWellKnownTypes { Int32Field = mergingValue };
+            message1.MergeFrom(message2);
+            Assert.AreEqual(expectedResult, message1.Int32Field);
+        }
+
+        [Test]
+        public void UnknownFieldInWrapper()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint);
+            var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint);
+
+            output.WriteTag(wrapperTag);
+            output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte
+            output.WriteTag(unknownTag);
+            output.WriteInt32((int) valueTag); // Sneakily "pretend" it's a tag when it's really a value
+            output.WriteTag(valueTag);
+            output.WriteInt32(6);
+
+            output.Flush();
+            stream.Position = 0;
+            
+            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
+            Assert.AreEqual(6, message.Int32Field);
+        }
+
+        [Test]
+        public void ClearWithReflection()
+        {
+            // String and Bytes are the tricky ones here, as the CLR type of the property
+            // is the same between the wrapper and non-wrapper types.
+            var message = new TestWellKnownTypes { StringField = "foo" };
+            TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message);
+            Assert.IsNull(message.StringField);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/packages.config b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/packages.config
new file mode 100644
index 0000000..c765399
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf.Test/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NUnit" version="2.6.4" targetFramework="net45" userInstalled="true" />
+  <package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" userInstalled="true" />
+</packages>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteArray.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteArray.cs
new file mode 100644
index 0000000..b199627
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteArray.cs
@@ -0,0 +1,79 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy
+    /// </summary>
+    internal static class ByteArray
+    {
+        /// <summary>
+        /// The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy
+        /// </summary>
+        private const int CopyThreshold = 12;
+
+        /// <summary>
+        /// Determines which copy routine to use based on the number of bytes to be copied.
+        /// </summary>
+        internal static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
+        {
+            if (count > CopyThreshold)
+            {
+                Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);
+            }
+            else
+            {
+                int stop = srcOffset + count;
+                for (int i = srcOffset; i < stop; i++)
+                {
+                    dst[dstOffset++] = src[i];
+                }
+            }
+        }
+
+        /// <summary>
+        /// Reverses the order of bytes in the array
+        /// </summary>
+        internal static void Reverse(byte[] bytes)
+        {
+            for (int first = 0, last = bytes.Length - 1; first < last; first++, last--)
+            {
+                byte temp = bytes[first];
+                bytes[first] = bytes[last];
+                bytes[last] = temp;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteString.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteString.cs
new file mode 100644
index 0000000..11ad621
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ByteString.cs
@@ -0,0 +1,345 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Immutable array of bytes.
+    /// </summary>
+    public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
+    {
+        private static readonly ByteString empty = new ByteString(new byte[0]);
+
+        private readonly byte[] bytes;
+
+        /// <summary>
+        /// Unsafe operations that can cause IO Failure and/or other catestrophic side-effects.
+        /// </summary>
+        internal static class Unsafe
+        {
+            /// <summary>
+            /// Constructs a new ByteString from the given byte array. The array is
+            /// *not* copied, and must not be modified after this constructor is called.
+            /// </summary>
+            internal static ByteString FromBytes(byte[] bytes)
+            {
+                return new ByteString(bytes);
+            }
+
+            /// <summary>
+            /// Provides direct, unrestricted access to the bytes contained in this instance.
+            /// You must not modify or resize the byte array returned by this method.
+            /// </summary>
+            internal static byte[] GetBuffer(ByteString bytes)
+            {
+                return bytes.bytes;
+            }
+        }
+
+        /// <summary>
+        /// Internal use only.  Ensure that the provided array is not mutated and belongs to this instance.
+        /// </summary>
+        internal static ByteString AttachBytes(byte[] bytes)
+        {
+            return new ByteString(bytes);
+        }
+
+        /// <summary>
+        /// Constructs a new ByteString from the given byte array. The array is
+        /// *not* copied, and must not be modified after this constructor is called.
+        /// </summary>
+        private ByteString(byte[] bytes)
+        {
+            this.bytes = bytes;
+        }
+
+        /// <summary>
+        /// Returns an empty ByteString.
+        /// </summary>
+        public static ByteString Empty
+        {
+            get { return empty; }
+        }
+
+        /// <summary>
+        /// Returns the length of this ByteString in bytes.
+        /// </summary>
+        public int Length
+        {
+            get { return bytes.Length; }
+        }
+
+        /// <summary>
+        /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
+        /// </summary>
+        public bool IsEmpty
+        {
+            get { return Length == 0; }
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a byte array.
+        /// </summary>
+        /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
+        /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
+        public byte[] ToByteArray()
+        {
+            return (byte[]) bytes.Clone();
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a standard base64 representation.
+        /// </summary>
+        /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
+        public string ToBase64()
+        {
+            return Convert.ToBase64String(bytes);
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
+        /// </summary>
+        public static ByteString FromBase64(string bytes)
+        {
+            // By handling the empty string explicitly, we not only optimize but we fix a
+            // problem on CF 2.0. See issue 61 for details.
+            return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from the given array. The contents
+        /// are copied, so further modifications to the array will not
+        /// be reflected in the returned ByteString.
+        /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
+        /// which is primarily useful for testing.
+        /// </summary>
+        public static ByteString CopyFrom(params byte[] bytes)
+        {
+            return new ByteString((byte[]) bytes.Clone());
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
+        /// </summary>
+        public static ByteString CopyFrom(byte[] bytes, int offset, int count)
+        {
+            byte[] portion = new byte[count];
+            ByteArray.Copy(bytes, offset, portion, 0, count);
+            return new ByteString(portion);
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text with
+        /// the given encoding.
+        /// </summary>
+        public static ByteString CopyFrom(string text, Encoding encoding)
+        {
+            return new ByteString(encoding.GetBytes(text));
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
+        /// </summary>
+        public static ByteString CopyFromUtf8(string text)
+        {
+            return CopyFrom(text, Encoding.UTF8);
+        }
+
+        /// <summary>
+        /// Retuns the byte at the given index.
+        /// </summary>
+        public byte this[int index]
+        {
+            get { return bytes[index]; }
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with the given encoding.
+        /// </remarks>
+        /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
+        public string ToString(Encoding encoding)
+        {
+            return encoding.GetString(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with UTF-8.
+        /// </remarks>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
+        public string ToStringUtf8()
+        {
+            return ToString(Encoding.UTF8);
+        }
+
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
+        public IEnumerator<byte> GetEnumerator()
+        {
+            return ((IEnumerable<byte>) bytes).GetEnumerator();
+        }
+
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        /// <summary>
+        /// Creates a CodedInputStream from this ByteString's data.
+        /// </summary>
+        public CodedInputStream CreateCodedInput()
+        {
+            // We trust CodedInputStream not to reveal the provided byte array or modify it
+            return new CodedInputStream(bytes);
+        }
+
+        /// <summary>
+        /// Compares two byte strings for equality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
+        public static bool operator ==(ByteString lhs, ByteString rhs)
+        {
+            if (ReferenceEquals(lhs, rhs))
+            {
+                return true;
+            }
+            if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
+            {
+                return false;
+            }
+            if (lhs.bytes.Length != rhs.bytes.Length)
+            {
+                return false;
+            }
+            for (int i = 0; i < lhs.Length; i++)
+            {
+                if (rhs.bytes[i] != lhs.bytes[i])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Compares two byte strings for inequality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
+        public static bool operator !=(ByteString lhs, ByteString rhs)
+        {
+            return !(lhs == rhs);
+        }
+
+        /// <summary>
+        /// Compares this byte string with another object.
+        /// </summary>
+        /// <param name="obj">The object to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            return this == (obj as ByteString);
+        }
+
+        /// <summary>
+        /// Returns a hash code for this object. Two equal byte strings
+        /// will return the same hash code.
+        /// </summary>
+        /// <returns>A hash code for this object.</returns>
+        public override int GetHashCode()
+        {
+            int ret = 23;
+            foreach (byte b in bytes)
+            {
+                ret = (ret << 8) | b;
+            }
+            return ret;
+        }
+
+        /// <summary>
+        /// Compares this byte string with another.
+        /// </summary>
+        /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
+        public bool Equals(ByteString other)
+        {
+            return this == other;
+        }
+
+        /// <summary>
+        /// Used internally by CodedOutputStream to avoid creating a copy for the write
+        /// </summary>
+        internal void WriteRawBytesTo(CodedOutputStream outputStream)
+        {
+            outputStream.WriteRawBytes(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Copies the entire byte array to the destination array provided at the offset specified.
+        /// </summary>
+        public void CopyTo(byte[] array, int position)
+        {
+            ByteArray.Copy(bytes, 0, array, position, bytes.Length);
+        }
+
+        /// <summary>
+        /// Writes the entire byte array to the provided stream
+        /// </summary>
+        public void WriteTo(Stream outputStream)
+        {
+            outputStream.Write(bytes, 0, bytes.Length);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedInputStream.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedInputStream.cs
new file mode 100644
index 0000000..3484457
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -0,0 +1,1277 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Collections;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Reads and decodes protocol message fields.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// This class is generally used by generated code to read appropriate
+    /// primitives from the stream. It effectively encapsulates the lowest
+    /// levels of protocol buffer format.
+    /// </para>
+    /// <para>
+    /// Repeated fields and map fields are not handled by this class; use <see cref="RepeatedField{T}"/>
+    /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.
+    /// </para>
+    /// </remarks>
+    public sealed class CodedInputStream : IDisposable
+    {
+        /// <summary>
+        /// Whether to leave the underlying stream open when disposing of this stream.
+        /// This is always true when there's no stream.
+        /// </summary>
+        private readonly bool leaveOpen;
+
+        /// <summary>
+        /// Buffer of data read from the stream or provided at construction time.
+        /// </summary>
+        private readonly byte[] buffer;
+
+        /// <summary>
+        /// The index of the buffer at which we need to refill from the stream (if there is one).
+        /// </summary>
+        private int bufferSize;
+
+        private int bufferSizeAfterLimit = 0;
+        /// <summary>
+        /// The position within the current buffer (i.e. the next byte to read)
+        /// </summary>
+        private int bufferPos = 0;
+
+        /// <summary>
+        /// The stream to read further input from, or null if the byte array buffer was provided
+        /// directly on construction, with no further data available.
+        /// </summary>
+        private readonly Stream input;
+
+        /// <summary>
+        /// The last tag we read. 0 indicates we've read to the end of the stream
+        /// (or haven't read anything yet).
+        /// </summary>
+        private uint lastTag = 0;
+
+        /// <summary>
+        /// The next tag, used to store the value read by PeekTag.
+        /// </summary>
+        private uint nextTag = 0;
+        private bool hasNextTag = false;
+
+        internal const int DefaultRecursionLimit = 64;
+        internal const int DefaultSizeLimit = 64 << 20; // 64MB
+        internal const int BufferSize = 4096;
+
+        /// <summary>
+        /// The total number of bytes read before the current buffer. The
+        /// total bytes read up to the current position can be computed as
+        /// totalBytesRetired + bufferPos.
+        /// </summary>
+        private int totalBytesRetired = 0;
+
+        /// <summary>
+        /// The absolute position of the end of the current message.
+        /// </summary> 
+        private int currentLimit = int.MaxValue;
+
+        private int recursionDepth = 0;
+
+        private readonly int recursionLimit;
+        private readonly int sizeLimit;
+
+        #region Construction
+        // Note that the checks are performed such that we don't end up checking obviously-valid things
+        // like non-null references for arrays we've just created.
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given byte array.
+        /// </summary>
+        public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
+        {            
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice.
+        /// </summary>
+        public CodedInputStream(byte[] buffer, int offset, int length)
+            : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
+        {            
+            if (offset < 0 || offset > buffer.Length)
+            {
+                throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer");
+            }
+            if (length < 0 || offset + length > buffer.Length)
+            {
+                throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer");
+            }
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream, which will be disposed
+        /// when the returned object is disposed.
+        /// </summary>
+        /// <param name="input">The stream to read from.</param>
+        public CodedInputStream(Stream input) : this(input, false)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream.
+        /// </summary>
+        /// <param name="input">The stream to read from.</param>
+        /// <param name="leaveOpen"><c>true</c> to leave <paramref name="input"/> open when the returned
+        /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the
+        /// returned object is disposed.</param>
+        public CodedInputStream(Stream input, bool leaveOpen)
+            : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0)
+        {
+            this.leaveOpen = leaveOpen;
+        }
+        
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given
+        /// stream and buffer, using the default limits.
+        /// </summary>
+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize)
+        {
+            this.input = input;
+            this.buffer = buffer;
+            this.bufferPos = bufferPos;
+            this.bufferSize = bufferSize;
+            this.sizeLimit = DefaultSizeLimit;
+            this.recursionLimit = DefaultRecursionLimit;
+        }
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given
+        /// stream and buffer, using the specified limits.
+        /// </summary>
+        /// <remarks>
+        /// This chains to the version with the default limits instead of vice versa to avoid
+        /// having to check that the default values are valid every time.
+        /// </remarks>
+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit)
+            : this(input, buffer, bufferPos, bufferSize)
+        {
+            if (sizeLimit <= 0)
+            {
+                throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive");
+            }
+            if (recursionLimit <= 0)
+            {
+                throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");
+            }
+            this.sizeLimit = sizeLimit;
+            this.recursionLimit = recursionLimit;
+        }
+        #endregion
+
+        /// <summary>
+        /// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading
+        /// from an input stream.
+        /// </summary>
+        /// <remarks>
+        /// This method exists separately from the constructor to reduce the number of constructor overloads.
+        /// It is likely to be used considerably less frequently than the constructors, as the default limits
+        /// are suitable for most use cases.
+        /// </remarks>
+        /// <param name="input">The input stream to read from</param>
+        /// <param name="sizeLimit">The total limit of data to read from the stream.</param>
+        /// <param name="recursionLimit">The maximum recursion depth to allow while reading.</param>
+        /// <returns>A <c>CodedInputStream</c> reading from <paramref name="input"/> with the specified size
+        /// and recursion limits.</returns>
+        public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit)
+        {
+            return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit);
+        }
+
+        /// <summary>
+        /// Returns the current position in the input stream, or the position in the input buffer
+        /// </summary>
+        public long Position 
+        {
+            get
+            {
+                if (input != null)
+                {
+                    return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos);
+                }
+                return bufferPos;
+            }
+        }
+
+        /// <summary>
+        /// Returns the last tag read, or 0 if no tags have been read or we've read beyond
+        /// the end of the stream.
+        /// </summary>
+        internal uint LastTag { get { return lastTag; } }
+
+        /// <summary>
+        /// Returns the size limit for this stream.
+        /// </summary>
+        /// <remarks>
+        /// This limit is applied when reading from the underlying stream, as a sanity check. It is
+        /// not applied when reading from a byte array data source without an underlying stream.
+        /// The default value is 64MB.
+        /// </remarks>
+        /// <value>
+        /// The size limit.
+        /// </value>
+        public int SizeLimit { get { return sizeLimit; } }
+
+        /// <summary>
+        /// Returns the recursion limit for this stream. This limit is applied whilst reading messages,
+        /// to avoid maliciously-recursive data.
+        /// </summary>
+        /// <remarks>
+        /// The default limit is 64.
+        /// </remarks>
+        /// <value>
+        /// The recursion limit for this stream.
+        /// </value>
+        public int RecursionLimit { get { return recursionLimit; } }
+
+        /// <summary>
+        /// Disposes of this instance, potentially closing any underlying stream.
+        /// </summary>
+        /// <remarks>
+        /// As there is no flushing to perform here, disposing of a <see cref="CodedInputStream"/> which
+        /// was constructed with the <c>leaveOpen</c> option parameter set to <c>true</c> (or one which
+        /// was constructed to read from a byte array) has no effect.
+        /// </remarks>
+        public void Dispose()
+        {
+            if (!leaveOpen)
+            {
+                input.Dispose();
+            }
+        }
+
+        #region Validation
+        /// <summary>
+        /// Verifies that the last call to ReadTag() returned tag 0 - in other words,
+        /// we've reached the end of the stream when we expected to.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">The 
+        /// tag read was not the one specified</exception>
+        internal void CheckReadEndOfStreamTag()
+        {
+            if (lastTag != 0)
+            {
+                throw InvalidProtocolBufferException.MoreDataAvailable();
+            }
+        }
+        #endregion
+
+        #region Reading of tags etc
+
+        /// <summary>
+        /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the
+        /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the
+        /// same value.)
+        /// </summary>
+        public uint PeekTag()
+        {
+            if (hasNextTag)
+            {
+                return nextTag;
+            }
+
+            uint savedLast = lastTag;
+            nextTag = ReadTag();
+            hasNextTag = true;
+            lastTag = savedLast; // Undo the side effect of ReadTag
+            return nextTag;
+        }
+
+        /// <summary>
+        /// Reads a field tag, returning the tag of 0 for "end of stream".
+        /// </summary>
+        /// <remarks>
+        /// If this method returns 0, it doesn't necessarily mean the end of all
+        /// the data in this CodedInputStream; it may be the end of the logical stream
+        /// for an embedded message, for example.
+        /// </remarks>
+        /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>
+        public uint ReadTag()
+        {
+            if (hasNextTag)
+            {
+                lastTag = nextTag;
+                hasNextTag = false;
+                return lastTag;
+            }
+
+            // Optimize for the incredibly common case of having at least two bytes left in the buffer,
+            // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
+            if (bufferPos + 2 <= bufferSize)
+            {
+                int tmp = buffer[bufferPos++];
+                if (tmp < 128)
+                {
+                    lastTag = (uint)tmp;
+                }
+                else
+                {
+                    int result = tmp & 0x7f;
+                    if ((tmp = buffer[bufferPos++]) < 128)
+                    {
+                        result |= tmp << 7;
+                        lastTag = (uint) result;
+                    }
+                    else
+                    {
+                        // Nope, rewind and go the potentially slow route.
+                        bufferPos -= 2;
+                        lastTag = ReadRawVarint32();
+                    }
+                }
+            }
+            else
+            {
+                if (IsAtEnd)
+                {
+                    lastTag = 0;
+                    return 0; // This is the only case in which we return 0.
+                }
+
+                lastTag = ReadRawVarint32();
+            }
+            if (lastTag == 0)
+            {
+                // If we actually read zero, that's not a valid tag.
+                throw InvalidProtocolBufferException.InvalidTag();
+            }
+            return lastTag;
+        }
+
+        /// <summary>
+        /// Skips the data for the field with the tag we've just read.
+        /// This should be called directly after <see cref="ReadTag"/>, when
+        /// the caller wishes to skip an unknown field.
+        /// </summary>
+        /// <remarks>
+        /// This method throws <see cref="InvalidProtocolBufferException"/> if the last-read tag was an end-group tag.
+        /// If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the
+        /// start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly
+        /// resulting in an error if an end-group tag has not been paired with an earlier start-group tag.
+        /// </remarks>
+        /// <exception cref="InvalidProtocolBufferException">The last tag was an end-group tag</exception>
+        /// <exception cref="InvalidOperationException">The last read operation read to the end of the logical stream</exception>
+        public void SkipLastField()
+        {
+            if (lastTag == 0)
+            {
+                throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");
+            }
+            switch (WireFormat.GetTagWireType(lastTag))
+            {
+                case WireFormat.WireType.StartGroup:
+                    SkipGroup(lastTag);
+                    break;
+                case WireFormat.WireType.EndGroup:
+                    throw new InvalidProtocolBufferException(
+                        "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing");
+                case WireFormat.WireType.Fixed32:
+                    ReadFixed32();
+                    break;
+                case WireFormat.WireType.Fixed64:
+                    ReadFixed64();
+                    break;
+                case WireFormat.WireType.LengthDelimited:
+                    var length = ReadLength();
+                    SkipRawBytes(length);
+                    break;
+                case WireFormat.WireType.Varint:
+                    ReadRawVarint32();
+                    break;
+            }
+        }
+
+        private void SkipGroup(uint startGroupTag)
+        {
+            // Note: Currently we expect this to be the way that groups are read. We could put the recursion
+            // depth changes into the ReadTag method instead, potentially...
+            recursionDepth++;
+            if (recursionDepth >= recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            uint tag;
+            while (true)
+            {
+                tag = ReadTag();
+                if (tag == 0)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                // Can't call SkipLastField for this case- that would throw.
+                if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup)
+                {
+                    break;
+                }
+                // This recursion will allow us to handle nested groups.
+                SkipLastField();
+            }
+            int startField = WireFormat.GetTagFieldNumber(startGroupTag);
+            int endField = WireFormat.GetTagFieldNumber(tag);
+            if (startField != endField)
+            {
+                throw new InvalidProtocolBufferException(
+                    $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}");
+            }
+            recursionDepth--;
+        }
+
+        /// <summary>
+        /// Reads a double field from the stream.
+        /// </summary>
+        public double ReadDouble()
+        {
+            return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
+        }
+
+        /// <summary>
+        /// Reads a float field from the stream.
+        /// </summary>
+        public float ReadFloat()
+        {
+            if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
+            {
+                float ret = BitConverter.ToSingle(buffer, bufferPos);
+                bufferPos += 4;
+                return ret;
+            }
+            else
+            {
+                byte[] rawBytes = ReadRawBytes(4);
+                if (!BitConverter.IsLittleEndian)
+                {
+                    ByteArray.Reverse(rawBytes);
+                }
+                return BitConverter.ToSingle(rawBytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// Reads a uint64 field from the stream.
+        /// </summary>
+        public ulong ReadUInt64()
+        {
+            return ReadRawVarint64();
+        }
+
+        /// <summary>
+        /// Reads an int64 field from the stream.
+        /// </summary>
+        public long ReadInt64()
+        {
+            return (long) ReadRawVarint64();
+        }
+
+        /// <summary>
+        /// Reads an int32 field from the stream.
+        /// </summary>
+        public int ReadInt32()
+        {
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads a fixed64 field from the stream.
+        /// </summary>
+        public ulong ReadFixed64()
+        {
+            return ReadRawLittleEndian64();
+        }
+
+        /// <summary>
+        /// Reads a fixed32 field from the stream.
+        /// </summary>
+        public uint ReadFixed32()
+        {
+            return ReadRawLittleEndian32();
+        }
+
+        /// <summary>
+        /// Reads a bool field from the stream.
+        /// </summary>
+        public bool ReadBool()
+        {
+            return ReadRawVarint32() != 0;
+        }
+
+        /// <summary>
+        /// Reads a string field from the stream.
+        /// </summary>
+        public string ReadString()
+        {
+            int length = ReadLength();
+            // No need to read any data for an empty string.
+            if (length == 0)
+            {
+                return "";
+            }
+            if (length <= bufferSize - bufferPos)
+            {
+                // Fast path:  We already have the bytes in a contiguous buffer, so
+                //   just copy directly from it.
+                String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
+                bufferPos += length;
+                return result;
+            }
+            // Slow path: Build a byte array first then copy it.
+            return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
+        }
+
+        /// <summary>
+        /// Reads an embedded message field value from the stream.
+        /// </summary>   
+        public void ReadMessage(IMessage builder)
+        {
+            int length = ReadLength();
+            if (recursionDepth >= recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            int oldLimit = PushLimit(length);
+            ++recursionDepth;
+            builder.MergeFrom(this);
+            CheckReadEndOfStreamTag();
+            // Check that we've read exactly as much data as expected.
+            if (!ReachedLimit)
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            --recursionDepth;
+            PopLimit(oldLimit);
+        }
+
+        /// <summary>
+        /// Reads a bytes field value from the stream.
+        /// </summary>   
+        public ByteString ReadBytes()
+        {
+            int length = ReadLength();
+            if (length <= bufferSize - bufferPos && length > 0)
+            {
+                // Fast path:  We already have the bytes in a contiguous buffer, so
+                //   just copy directly from it.
+                ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
+                bufferPos += length;
+                return result;
+            }
+            else
+            {
+                // Slow path:  Build a byte array and attach it to a new ByteString.
+                return ByteString.AttachBytes(ReadRawBytes(length));
+            }
+        }
+
+        /// <summary>
+        /// Reads a uint32 field value from the stream.
+        /// </summary>   
+        public uint ReadUInt32()
+        {
+            return ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads an enum field value from the stream. If the enum is valid for type T,
+        /// then the ref value is set and it returns true.  Otherwise the unknown output
+        /// value is set and this method returns false.
+        /// </summary>   
+        public int ReadEnum()
+        {
+            // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads an sfixed32 field value from the stream.
+        /// </summary>   
+        public int ReadSFixed32()
+        {
+            return (int) ReadRawLittleEndian32();
+        }
+
+        /// <summary>
+        /// Reads an sfixed64 field value from the stream.
+        /// </summary>   
+        public long ReadSFixed64()
+        {
+            return (long) ReadRawLittleEndian64();
+        }
+
+        /// <summary>
+        /// Reads an sint32 field value from the stream.
+        /// </summary>   
+        public int ReadSInt32()
+        {
+            return DecodeZigZag32(ReadRawVarint32());
+        }
+
+        /// <summary>
+        /// Reads an sint64 field value from the stream.
+        /// </summary>   
+        public long ReadSInt64()
+        {
+            return DecodeZigZag64(ReadRawVarint64());
+        }
+
+        /// <summary>
+        /// Reads a length for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This is internally just reading a varint, but this method exists
+        /// to make the calling code clearer.
+        /// </remarks>
+        public int ReadLength()
+        {
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
+        /// the tag is consumed and the method returns <c>true</c>; otherwise, the
+        /// stream is left in the original position and the method returns <c>false</c>.
+        /// </summary>
+        public bool MaybeConsumeTag(uint tag)
+        {
+            if (PeekTag() == tag)
+            {
+                hasNextTag = false;
+                return true;
+            }
+            return false;
+        }
+
+        #endregion
+
+        #region Underlying reading primitives
+
+        /// <summary>
+        /// Same code as ReadRawVarint32, but read each byte individually, checking for
+        /// buffer overflow.
+        /// </summary>
+        private uint SlowReadRawVarint32()
+        {
+            int tmp = ReadRawByte();
+            if (tmp < 128)
+            {
+                return (uint) tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = ReadRawByte()) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = ReadRawByte()) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = ReadRawByte()) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = ReadRawByte()) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte() < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint) result;
+        }
+
+        /// <summary>
+        /// Reads a raw Varint from the stream.  If larger than 32 bits, discard the upper bits.
+        /// This method is optimised for the case where we've got lots of data in the buffer.
+        /// That means we can check the size just once, then just read directly from the buffer
+        /// without constant rechecking of the buffer length.
+        /// </summary>
+        internal uint ReadRawVarint32()
+        {
+            if (bufferPos + 5 > bufferSize)
+            {
+                return SlowReadRawVarint32();
+            }
+
+            int tmp = buffer[bufferPos++];
+            if (tmp < 128)
+            {
+                return (uint) tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = buffer[bufferPos++]) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = buffer[bufferPos++]) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = buffer[bufferPos++]) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = buffer[bufferPos++]) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            // Note that this has to use ReadRawByte() as we only ensure we've
+                            // got at least 5 bytes at the start of the method. This lets us
+                            // use the fast path in more cases, and we rarely hit this section of code.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte() < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint) result;
+        }
+
+        /// <summary>
+        /// Reads a varint from the input one byte at a time, so that it does not
+        /// read any bytes after the end of the varint. If you simply wrapped the
+        /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
+        /// then you would probably end up reading past the end of the varint since
+        /// CodedInputStream buffers its input.
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        internal static uint ReadRawVarint32(Stream input)
+        {
+            int result = 0;
+            int offset = 0;
+            for (; offset < 32; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                result |= (b & 0x7f) << offset;
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            // Keep reading up to 64 bits.
+            for (; offset < 64; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Reads a raw varint from the stream.
+        /// </summary>
+        internal ulong ReadRawVarint64()
+        {
+            int shift = 0;
+            ulong result = 0;
+            while (shift < 64)
+            {
+                byte b = ReadRawByte();
+                result |= (ulong) (b & 0x7F) << shift;
+                if ((b & 0x80) == 0)
+                {
+                    return result;
+                }
+                shift += 7;
+            }
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Reads a 32-bit little-endian integer from the stream.
+        /// </summary>
+        internal uint ReadRawLittleEndian32()
+        {
+            uint b1 = ReadRawByte();
+            uint b2 = ReadRawByte();
+            uint b3 = ReadRawByte();
+            uint b4 = ReadRawByte();
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
+        }
+
+        /// <summary>
+        /// Reads a 64-bit little-endian integer from the stream.
+        /// </summary>
+        internal ulong ReadRawLittleEndian64()
+        {
+            ulong b1 = ReadRawByte();
+            ulong b2 = ReadRawByte();
+            ulong b3 = ReadRawByte();
+            ulong b4 = ReadRawByte();
+            ulong b5 = ReadRawByte();
+            ulong b6 = ReadRawByte();
+            ulong b7 = ReadRawByte();
+            ulong b8 = ReadRawByte();
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
+                   | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
+        }
+
+        /// <summary>
+        /// Decode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static int DecodeZigZag32(uint n)
+        {
+            return (int)(n >> 1) ^ -(int)(n & 1);
+        }
+
+        /// <summary>
+        /// Decode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static long DecodeZigZag64(ulong n)
+        {
+            return (long)(n >> 1) ^ -(long)(n & 1);
+        }
+        #endregion
+
+        #region Internal reading and buffer management
+
+        /// <summary>
+        /// Sets currentLimit to (current position) + byteLimit. This is called
+        /// when descending into a length-delimited embedded message. The previous
+        /// limit is returned.
+        /// </summary>
+        /// <returns>The old limit.</returns>
+        internal int PushLimit(int byteLimit)
+        {
+            if (byteLimit < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+            byteLimit += totalBytesRetired + bufferPos;
+            int oldLimit = currentLimit;
+            if (byteLimit > oldLimit)
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            currentLimit = byteLimit;
+
+            RecomputeBufferSizeAfterLimit();
+
+            return oldLimit;
+        }
+
+        private void RecomputeBufferSizeAfterLimit()
+        {
+            bufferSize += bufferSizeAfterLimit;
+            int bufferEnd = totalBytesRetired + bufferSize;
+            if (bufferEnd > currentLimit)
+            {
+                // Limit is in current buffer.
+                bufferSizeAfterLimit = bufferEnd - currentLimit;
+                bufferSize -= bufferSizeAfterLimit;
+            }
+            else
+            {
+                bufferSizeAfterLimit = 0;
+            }
+        }
+
+        /// <summary>
+        /// Discards the current limit, returning the previous limit.
+        /// </summary>
+        internal void PopLimit(int oldLimit)
+        {
+            currentLimit = oldLimit;
+            RecomputeBufferSizeAfterLimit();
+        }
+
+        /// <summary>
+        /// Returns whether or not all the data before the limit has been read.
+        /// </summary>
+        /// <returns></returns>
+        internal bool ReachedLimit
+        {
+            get
+            {
+                if (currentLimit == int.MaxValue)
+                {
+                    return false;
+                }
+                int currentAbsolutePosition = totalBytesRetired + bufferPos;
+                return currentAbsolutePosition >= currentLimit;
+            }
+        }
+
+        /// <summary>
+        /// Returns true if the stream has reached the end of the input. This is the
+        /// case if either the end of the underlying input source has been reached or
+        /// the stream has reached a limit created using PushLimit.
+        /// </summary>
+        public bool IsAtEnd
+        {
+            get { return bufferPos == bufferSize && !RefillBuffer(false); }
+        }
+
+        /// <summary>
+        /// Called when buffer is empty to read more bytes from the
+        /// input.  If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
+        /// either there will be at least one byte in the buffer when it returns
+        /// or it will throw an exception.  If <paramref name="mustSucceed"/> is false,
+        /// RefillBuffer() returns false if no more bytes were available.
+        /// </summary>
+        /// <param name="mustSucceed"></param>
+        /// <returns></returns>
+        private bool RefillBuffer(bool mustSucceed)
+        {
+            if (bufferPos < bufferSize)
+            {
+                throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
+            }
+
+            if (totalBytesRetired + bufferSize == currentLimit)
+            {
+                // Oops, we hit a limit.
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            totalBytesRetired += bufferSize;
+
+            bufferPos = 0;
+            bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
+            if (bufferSize < 0)
+            {
+                throw new InvalidOperationException("Stream.Read returned a negative count");
+            }
+            if (bufferSize == 0)
+            {
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                RecomputeBufferSizeAfterLimit();
+                int totalBytesRead =
+                    totalBytesRetired + bufferSize + bufferSizeAfterLimit;
+                if (totalBytesRead > sizeLimit || totalBytesRead < 0)
+                {
+                    throw InvalidProtocolBufferException.SizeLimitExceeded();
+                }
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// Read one byte from the input.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        internal byte ReadRawByte()
+        {
+            if (bufferPos == bufferSize)
+            {
+                RefillBuffer(true);
+            }
+            return buffer[bufferPos++];
+        }
+
+        /// <summary>
+        /// Reads a fixed size of bytes from the input.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        internal byte[] ReadRawBytes(int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            if (totalBytesRetired + bufferPos + size > currentLimit)
+            {
+                // Read to the end of the stream (up to the current limit) anyway.
+                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+                // Then fail.
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+
+            if (size <= bufferSize - bufferPos)
+            {
+                // We have all the bytes we need already.
+                byte[] bytes = new byte[size];
+                ByteArray.Copy(buffer, bufferPos, bytes, 0, size);
+                bufferPos += size;
+                return bytes;
+            }
+            else if (size < buffer.Length)
+            {
+                // Reading more bytes than are in the buffer, but not an excessive number
+                // of bytes.  We can safely allocate the resulting array ahead of time.
+
+                // First copy what we have.
+                byte[] bytes = new byte[size];
+                int pos = bufferSize - bufferPos;
+                ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);
+                bufferPos = bufferSize;
+
+                // We want to use RefillBuffer() and then copy from the buffer into our
+                // byte array rather than reading directly into our byte array because
+                // the input may be unbuffered.
+                RefillBuffer(true);
+
+                while (size - pos > bufferSize)
+                {
+                    Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);
+                    pos += bufferSize;
+                    bufferPos = bufferSize;
+                    RefillBuffer(true);
+                }
+
+                ByteArray.Copy(buffer, 0, bytes, pos, size - pos);
+                bufferPos = size - pos;
+
+                return bytes;
+            }
+            else
+            {
+                // The size is very large.  For security reasons, we can't allocate the
+                // entire byte array yet.  The size comes directly from the input, so a
+                // maliciously-crafted message could provide a bogus very large size in
+                // order to trick the app into allocating a lot of memory.  We avoid this
+                // by allocating and reading only a small chunk at a time, so that the
+                // malicious message must actually *be* extremely large to cause
+                // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
+
+                // Remember the buffer markers since we'll have to copy the bytes out of
+                // it later.
+                int originalBufferPos = bufferPos;
+                int originalBufferSize = bufferSize;
+
+                // Mark the current buffer consumed.
+                totalBytesRetired += bufferSize;
+                bufferPos = 0;
+                bufferSize = 0;
+
+                // Read all the rest of the bytes we need.
+                int sizeLeft = size - (originalBufferSize - originalBufferPos);
+                List<byte[]> chunks = new List<byte[]>();
+
+                while (sizeLeft > 0)
+                {
+                    byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];
+                    int pos = 0;
+                    while (pos < chunk.Length)
+                    {
+                        int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
+                        if (n <= 0)
+                        {
+                            throw InvalidProtocolBufferException.TruncatedMessage();
+                        }
+                        totalBytesRetired += n;
+                        pos += n;
+                    }
+                    sizeLeft -= chunk.Length;
+                    chunks.Add(chunk);
+                }
+
+                // OK, got everything.  Now concatenate it all into one buffer.
+                byte[] bytes = new byte[size];
+
+                // Start by copying the leftover bytes from this.buffer.
+                int newPos = originalBufferSize - originalBufferPos;
+                ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);
+
+                // And now all the chunks.
+                foreach (byte[] chunk in chunks)
+                {
+                    Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
+                    newPos += chunk.Length;
+                }
+
+                // Done.
+                return bytes;
+            }
+        }
+
+        /// <summary>
+        /// Reads and discards <paramref name="size"/> bytes.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">the end of the stream
+        /// or the current limit was reached</exception>
+        private void SkipRawBytes(int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            if (totalBytesRetired + bufferPos + size > currentLimit)
+            {
+                // Read to the end of the stream anyway.
+                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+                // Then fail.
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+
+            if (size <= bufferSize - bufferPos)
+            {
+                // We have all the bytes we need already.
+                bufferPos += size;
+            }
+            else
+            {
+                // Skipping more bytes than are in the buffer.  First skip what we have.
+                int pos = bufferSize - bufferPos;
+
+                // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)
+                // totalBytesRetired += pos;
+                totalBytesRetired += bufferSize;
+                
+                bufferPos = 0;
+                bufferSize = 0;
+
+                // Then skip directly from the InputStream for the rest.
+                if (pos < size)
+                {
+                    if (input == null)
+                    {
+                        throw InvalidProtocolBufferException.TruncatedMessage();
+                    }
+                    SkipImpl(size - pos);
+                    totalBytesRetired += size - pos;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Abstraction of skipping to cope with streams which can't really skip.
+        /// </summary>
+        private void SkipImpl(int amountToSkip)
+        {
+            if (input.CanSeek)
+            {
+                long previousPosition = input.Position;
+                input.Position += amountToSkip;
+                if (input.Position != previousPosition + amountToSkip)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+            }
+            else
+            {
+                byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];
+                while (amountToSkip > 0)
+                {
+                    int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));
+                    if (bytesRead <= 0)
+                    {
+                        throw InvalidProtocolBufferException.TruncatedMessage();
+                    }
+                    amountToSkip -= bytesRead;
+                }
+            }
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
new file mode 100644
index 0000000..e22937c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
@@ -0,0 +1,304 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    // This part of CodedOutputStream provides all the static entry points that are used
+    // by generated code and internally to compute the size of messages prior to being
+    // written to an instance of CodedOutputStream.
+    public sealed partial class CodedOutputStream
+    {
+        private const int LittleEndian64Size = 8;
+        private const int LittleEndian32Size = 4;        
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// double field, including the tag.
+        /// </summary>
+        public static int ComputeDoubleSize(double value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// float field, including the tag.
+        /// </summary>
+        public static int ComputeFloatSize(float value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// uint64 field, including the tag.
+        /// </summary>
+        public static int ComputeUInt64Size(ulong value)
+        {
+            return ComputeRawVarint64Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// int64 field, including the tag.
+        /// </summary>
+        public static int ComputeInt64Size(long value)
+        {
+            return ComputeRawVarint64Size((ulong) value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// int32 field, including the tag.
+        /// </summary>
+        public static int ComputeInt32Size(int value)
+        {
+            if (value >= 0)
+            {
+                return ComputeRawVarint32Size((uint) value);
+            }
+            else
+            {
+                // Must sign-extend.
+                return 10;
+            }
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// fixed64 field, including the tag.
+        /// </summary>
+        public static int ComputeFixed64Size(ulong value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// fixed32 field, including the tag.
+        /// </summary>
+        public static int ComputeFixed32Size(uint value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// bool field, including the tag.
+        /// </summary>
+        public static int ComputeBoolSize(bool value)
+        {
+            return 1;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// string field, including the tag.
+        /// </summary>
+        public static int ComputeStringSize(String value)
+        {
+            int byteArraySize = Utf8Encoding.GetByteCount(value);
+            return ComputeLengthSize(byteArraySize) + byteArraySize;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// group field, including the tag.
+        /// </summary>
+        public static int ComputeGroupSize(IMessage value)
+        {
+            return value.CalculateSize();
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// embedded message field, including the tag.
+        /// </summary>
+        public static int ComputeMessageSize(IMessage value)
+        {
+            int size = value.CalculateSize();
+            return ComputeLengthSize(size) + size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// bytes field, including the tag.
+        /// </summary>
+        public static int ComputeBytesSize(ByteString value)
+        {
+            return ComputeLengthSize(value.Length) + value.Length;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// uint32 field, including the tag.
+        /// </summary>
+        public static int ComputeUInt32Size(uint value)
+        {
+            return ComputeRawVarint32Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// enum field, including the tag. The caller is responsible for
+        /// converting the enum value to its numeric value.
+        /// </summary>
+        public static int ComputeEnumSize(int value)
+        {
+            // Currently just a pass-through, but it's nice to separate it logically.
+            return ComputeInt32Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sfixed32 field, including the tag.
+        /// </summary>
+        public static int ComputeSFixed32Size(int value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sfixed64 field, including the tag.
+        /// </summary>
+        public static int ComputeSFixed64Size(long value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sint32 field, including the tag.
+        /// </summary>
+        public static int ComputeSInt32Size(int value)
+        {
+            return ComputeRawVarint32Size(EncodeZigZag32(value));
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sint64 field, including the tag.
+        /// </summary>
+        public static int ComputeSInt64Size(long value)
+        {
+            return ComputeRawVarint64Size(EncodeZigZag64(value));
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a length,
+        /// as written by <see cref="WriteLength"/>.
+        /// </summary>
+        public static int ComputeLengthSize(int length)
+        {
+            return ComputeRawVarint32Size((uint) length);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a varint.
+        /// </summary>
+        public static int ComputeRawVarint32Size(uint value)
+        {
+            if ((value & (0xffffffff << 7)) == 0)
+            {
+                return 1;
+            }
+            if ((value & (0xffffffff << 14)) == 0)
+            {
+                return 2;
+            }
+            if ((value & (0xffffffff << 21)) == 0)
+            {
+                return 3;
+            }
+            if ((value & (0xffffffff << 28)) == 0)
+            {
+                return 4;
+            }
+            return 5;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a varint.
+        /// </summary>
+        public static int ComputeRawVarint64Size(ulong value)
+        {
+            if ((value & (0xffffffffffffffffL << 7)) == 0)
+            {
+                return 1;
+            }
+            if ((value & (0xffffffffffffffffL << 14)) == 0)
+            {
+                return 2;
+            }
+            if ((value & (0xffffffffffffffffL << 21)) == 0)
+            {
+                return 3;
+            }
+            if ((value & (0xffffffffffffffffL << 28)) == 0)
+            {
+                return 4;
+            }
+            if ((value & (0xffffffffffffffffL << 35)) == 0)
+            {
+                return 5;
+            }
+            if ((value & (0xffffffffffffffffL << 42)) == 0)
+            {
+                return 6;
+            }
+            if ((value & (0xffffffffffffffffL << 49)) == 0)
+            {
+                return 7;
+            }
+            if ((value & (0xffffffffffffffffL << 56)) == 0)
+            {
+                return 8;
+            }
+            if ((value & (0xffffffffffffffffL << 63)) == 0)
+            {
+                return 9;
+            }
+            return 10;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a tag.
+        /// </summary>
+        public static int ComputeTagSize(int fieldNumber)
+        {
+            return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.cs
new file mode 100644
index 0000000..827f039
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/CodedOutputStream.cs
@@ -0,0 +1,761 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Collections;
+using System;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Encodes and writes protocol message fields.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// This class is generally used by generated code to write appropriate
+    /// primitives to the stream. It effectively encapsulates the lowest
+    /// levels of protocol buffer format. Unlike some other implementations,
+    /// this does not include combined "write tag and value" methods. Generated
+    /// code knows the exact byte representations of the tags they're going to write,
+    /// so there's no need to re-encode them each time. Manually-written code calling
+    /// this class should just call one of the <c>WriteTag</c> overloads before each value.
+    /// </para>
+    /// <para>
+    /// Repeated fields and map fields are not handled by this class; use <c>RepeatedField&lt;T&gt;</c>
+    /// and <c>MapField&lt;TKey, TValue&gt;</c> to serialize such fields.
+    /// </para>
+    /// </remarks>
+    public sealed partial class CodedOutputStream : IDisposable
+    {
+        // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
+        internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
+
+        /// <summary>
+        /// The buffer size used by CreateInstance(Stream).
+        /// </summary>
+        public static readonly int DefaultBufferSize = 4096;
+
+        private readonly bool leaveOpen;
+        private readonly byte[] buffer;
+        private readonly int limit;
+        private int position;
+        private readonly Stream output;
+
+        #region Construction
+        /// <summary>
+        /// Creates a new CodedOutputStream that writes directly to the given
+        /// byte array. If more bytes are written than fit in the array,
+        /// OutOfSpaceException will be thrown.
+        /// </summary>
+        public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream that writes directly to the given
+        /// byte array slice. If more bytes are written than fit in the array,
+        /// OutOfSpaceException will be thrown.
+        /// </summary>
+        private CodedOutputStream(byte[] buffer, int offset, int length)
+        {
+            this.output = null;
+            this.buffer = buffer;
+            this.position = offset;
+            this.limit = offset + length;
+            leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
+        }
+
+        private CodedOutputStream(Stream output, byte[] buffer, bool leaveOpen)
+        {
+            this.output = ProtoPreconditions.CheckNotNull(output, nameof(output));
+            this.buffer = buffer;
+            this.position = 0;
+            this.limit = buffer.Length;
+            this.leaveOpen = leaveOpen;
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="CodedOutputStream" /> which write to the given stream, and disposes of that
+        /// stream when the returned <c>CodedOutputStream</c> is disposed.
+        /// </summary>
+        /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param>
+        public CodedOutputStream(Stream output) : this(output, DefaultBufferSize, false)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream which write to the given stream and uses
+        /// the specified buffer size.
+        /// </summary>
+        /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param>
+        /// <param name="bufferSize">The size of buffer to use internally.</param>
+        public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize], false)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream which write to the given stream.
+        /// </summary>
+        /// <param name="output">The stream to write to.</param>
+        /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed;
+        /// if <c>false</c>, the provided stream is disposed as well.</param>
+        public CodedOutputStream(Stream output, bool leaveOpen) : this(output, DefaultBufferSize, leaveOpen)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream which write to the given stream and uses
+        /// the specified buffer size.
+        /// </summary>
+        /// <param name="output">The stream to write to.</param>
+        /// <param name="bufferSize">The size of buffer to use internally.</param>
+        /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed;
+        /// if <c>false</c>, the provided stream is disposed as well.</param>
+        public CodedOutputStream(Stream output, int bufferSize, bool leaveOpen) : this(output, new byte[bufferSize], leaveOpen)
+        {
+        }
+        #endregion
+
+        /// <summary>
+        /// Returns the current position in the stream, or the position in the output buffer
+        /// </summary>
+        public long Position
+        {
+            get
+            {
+                if (output != null)
+                {
+                    return output.Position + position;
+                }
+                return position;
+            }
+        }
+
+        #region Writing of values (not including tags)
+
+        /// <summary>
+        /// Writes a double field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteDouble(double value)
+        {
+            WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
+        }
+
+        /// <summary>
+        /// Writes a float field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFloat(float value)
+        {
+            byte[] rawBytes = BitConverter.GetBytes(value);
+            if (!BitConverter.IsLittleEndian)
+            {
+                ByteArray.Reverse(rawBytes);
+            }
+
+            if (limit - position >= 4)
+            {
+                buffer[position++] = rawBytes[0];
+                buffer[position++] = rawBytes[1];
+                buffer[position++] = rawBytes[2];
+                buffer[position++] = rawBytes[3];
+            }
+            else
+            {
+                WriteRawBytes(rawBytes, 0, 4);
+            }
+        }
+
+        /// <summary>
+        /// Writes a uint64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt64(ulong value)
+        {
+            WriteRawVarint64(value);
+        }
+
+        /// <summary>
+        /// Writes an int64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt64(long value)
+        {
+            WriteRawVarint64((ulong) value);
+        }
+
+        /// <summary>
+        /// Writes an int32 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt32(int value)
+        {
+            if (value >= 0)
+            {
+                WriteRawVarint32((uint) value);
+            }
+            else
+            {
+                // Must sign-extend.
+                WriteRawVarint64((ulong) value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a fixed64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed64(ulong value)
+        {
+            WriteRawLittleEndian64(value);
+        }
+
+        /// <summary>
+        /// Writes a fixed32 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed32(uint value)
+        {
+            WriteRawLittleEndian32(value);
+        }
+
+        /// <summary>
+        /// Writes a bool field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBool(bool value)
+        {
+            WriteRawByte(value ? (byte) 1 : (byte) 0);
+        }
+
+        /// <summary>
+        /// Writes a string field value, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteString(string value)
+        {
+            // Optimise the case where we have enough space to write
+            // the string directly to the buffer, which should be common.
+            int length = Utf8Encoding.GetByteCount(value);
+            WriteLength(length);
+            if (limit - position >= length)
+            {
+                if (length == value.Length) // Must be all ASCII...
+                {
+                    for (int i = 0; i < length; i++)
+                    {
+                        buffer[position + i] = (byte)value[i];
+                    }
+                }
+                else
+                {
+                    Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position);
+                }
+                position += length;
+            }
+            else
+            {
+                byte[] bytes = Utf8Encoding.GetBytes(value);
+                WriteRawBytes(bytes);
+            }
+        }
+
+        /// <summary>
+        /// Writes a message, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteMessage(IMessage value)
+        {
+            WriteLength(value.CalculateSize());
+            value.WriteTo(this);
+        }
+
+        /// <summary>
+        /// Write a byte string, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBytes(ByteString value)
+        {
+            WriteLength(value.Length);
+            value.WriteRawBytesTo(this);
+        }
+
+        /// <summary>
+        /// Writes a uint32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt32(uint value)
+        {
+            WriteRawVarint32(value);
+        }
+
+        /// <summary>
+        /// Writes an enum value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteEnum(int value)
+        {
+            WriteInt32(value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        public void WriteSFixed32(int value)
+        {
+            WriteRawLittleEndian32((uint) value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed64 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSFixed64(long value)
+        {
+            WriteRawLittleEndian64((ulong) value);
+        }
+
+        /// <summary>
+        /// Writes an sint32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt32(int value)
+        {
+            WriteRawVarint32(EncodeZigZag32(value));
+        }
+
+        /// <summary>
+        /// Writes an sint64 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt64(long value)
+        {
+            WriteRawVarint64(EncodeZigZag64(value));
+        }
+
+        /// <summary>
+        /// Writes a length (in bytes) for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This method simply writes a rawint, but exists for clarity in calling code.
+        /// </remarks>
+        /// <param name="length">Length value, in bytes.</param>
+        public void WriteLength(int length)
+        {
+            WriteRawVarint32((uint) length);
+        }
+
+        #endregion
+
+        #region Raw tag writing
+        /// <summary>
+        /// Encodes and writes a tag.
+        /// </summary>
+        /// <param name="fieldNumber">The number of the field to write the tag for</param>
+        /// <param name="type">The wire format type of the tag to write</param>
+        public void WriteTag(int fieldNumber, WireFormat.WireType type)
+        {
+            WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
+        }
+
+        /// <summary>
+        /// Writes an already-encoded tag.
+        /// </summary>
+        /// <param name="tag">The encoded tag</param>
+        public void WriteTag(uint tag)
+        {
+            WriteRawVarint32(tag);
+        }
+
+        /// <summary>
+        /// Writes the given single-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The encoded tag</param>
+        public void WriteRawTag(byte b1)
+        {
+            WriteRawByte(b1);
+        }
+
+        /// <summary>
+        /// Writes the given two-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+        }
+
+        /// <summary>
+        /// Writes the given three-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+        }
+
+        /// <summary>
+        /// Writes the given four-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+            WriteRawByte(b4);
+        }
+
+        /// <summary>
+        /// Writes the given five-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        /// <param name="b5">The fifth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+            WriteRawByte(b4);
+            WriteRawByte(b5);
+        }
+        #endregion
+
+        #region Underlying writing primitives
+        /// <summary>
+        /// Writes a 32 bit value as a varint. The fast route is taken when
+        /// there's enough buffer space left to whizz through without checking
+        /// for each byte; otherwise, we resort to calling WriteRawByte each time.
+        /// </summary>
+        internal void WriteRawVarint32(uint value)
+        {
+            // Optimize for the common case of a single byte value
+            if (value < 128 && position < limit)
+            {
+                buffer[position++] = (byte)value;
+                return;
+            }
+
+            while (value > 127 && position < limit)
+            {
+                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+                value >>= 7;
+            }
+            while (value > 127)
+            {
+                WriteRawByte((byte) ((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+            if (position < limit)
+            {
+                buffer[position++] = (byte) value;
+            }
+            else
+            {
+                WriteRawByte((byte) value);
+            }
+        }
+
+        internal void WriteRawVarint64(ulong value)
+        {
+            while (value > 127 && position < limit)
+            {
+                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+                value >>= 7;
+            }
+            while (value > 127)
+            {
+                WriteRawByte((byte) ((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+            if (position < limit)
+            {
+                buffer[position++] = (byte) value;
+            }
+            else
+            {
+                WriteRawByte((byte) value);
+            }
+        }
+
+        internal void WriteRawLittleEndian32(uint value)
+        {
+            if (position + 4 > limit)
+            {
+                WriteRawByte((byte) value);
+                WriteRawByte((byte) (value >> 8));
+                WriteRawByte((byte) (value >> 16));
+                WriteRawByte((byte) (value >> 24));
+            }
+            else
+            {
+                buffer[position++] = ((byte) value);
+                buffer[position++] = ((byte) (value >> 8));
+                buffer[position++] = ((byte) (value >> 16));
+                buffer[position++] = ((byte) (value >> 24));
+            }
+        }
+
+        internal void WriteRawLittleEndian64(ulong value)
+        {
+            if (position + 8 > limit)
+            {
+                WriteRawByte((byte) value);
+                WriteRawByte((byte) (value >> 8));
+                WriteRawByte((byte) (value >> 16));
+                WriteRawByte((byte) (value >> 24));
+                WriteRawByte((byte) (value >> 32));
+                WriteRawByte((byte) (value >> 40));
+                WriteRawByte((byte) (value >> 48));
+                WriteRawByte((byte) (value >> 56));
+            }
+            else
+            {
+                buffer[position++] = ((byte) value);
+                buffer[position++] = ((byte) (value >> 8));
+                buffer[position++] = ((byte) (value >> 16));
+                buffer[position++] = ((byte) (value >> 24));
+                buffer[position++] = ((byte) (value >> 32));
+                buffer[position++] = ((byte) (value >> 40));
+                buffer[position++] = ((byte) (value >> 48));
+                buffer[position++] = ((byte) (value >> 56));
+            }
+        }
+
+        internal void WriteRawByte(byte value)
+        {
+            if (position == limit)
+            {
+                RefreshBuffer();
+            }
+
+            buffer[position++] = value;
+        }
+
+        internal void WriteRawByte(uint value)
+        {
+            WriteRawByte((byte) value);
+        }
+
+        /// <summary>
+        /// Writes out an array of bytes.
+        /// </summary>
+        internal void WriteRawBytes(byte[] value)
+        {
+            WriteRawBytes(value, 0, value.Length);
+        }
+
+        /// <summary>
+        /// Writes out part of an array of bytes.
+        /// </summary>
+        internal void WriteRawBytes(byte[] value, int offset, int length)
+        {
+            if (limit - position >= length)
+            {
+                ByteArray.Copy(value, offset, buffer, position, length);
+                // We have room in the current buffer.
+                position += length;
+            }
+            else
+            {
+                // Write extends past current buffer.  Fill the rest of this buffer and
+                // flush.
+                int bytesWritten = limit - position;
+                ByteArray.Copy(value, offset, buffer, position, bytesWritten);
+                offset += bytesWritten;
+                length -= bytesWritten;
+                position = limit;
+                RefreshBuffer();
+
+                // Now deal with the rest.
+                // Since we have an output stream, this is our buffer
+                // and buffer offset == 0
+                if (length <= limit)
+                {
+                    // Fits in new buffer.
+                    ByteArray.Copy(value, offset, buffer, 0, length);
+                    position = length;
+                }
+                else
+                {
+                    // Write is very big.  Let's do it all at once.
+                    output.Write(value, offset, length);
+                }
+            }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// Encode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static uint EncodeZigZag32(int n)
+        {
+            // Note:  the right-shift must be arithmetic
+            return (uint) ((n << 1) ^ (n >> 31));
+        }
+
+        /// <summary>
+        /// Encode a 64-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static ulong EncodeZigZag64(long n)
+        {
+            return (ulong) ((n << 1) ^ (n >> 63));
+        }
+
+        private void RefreshBuffer()
+        {
+            if (output == null)
+            {
+                // We're writing to a single buffer.
+                throw new OutOfSpaceException();
+            }
+
+            // Since we have an output stream, this is our buffer
+            // and buffer offset == 0
+            output.Write(buffer, 0, position);
+            position = 0;
+        }
+
+        /// <summary>
+        /// Indicates that a CodedOutputStream wrapping a flat byte array
+        /// ran out of space.
+        /// </summary>
+        public sealed class OutOfSpaceException : IOException
+        {
+            internal OutOfSpaceException()
+                : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
+            {
+            }
+        }
+
+        /// <summary>
+        /// Flushes any buffered data and optionally closes the underlying stream, if any.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// By default, any underlying stream is closed by this method. To configure this behaviour,
+        /// use a constructor overload with a <c>leaveOpen</c> parameter. If this instance does not
+        /// have an underlying stream, this method does nothing.
+        /// </para>
+        /// <para>
+        /// For the sake of efficiency, calling this method does not prevent future write calls - but
+        /// if a later write ends up writing to a stream which has been disposed, that is likely to
+        /// fail. It is recommend that you not call any other methods after this.
+        /// </para>
+        /// </remarks>
+        public void Dispose()
+        {
+            Flush();
+            if (!leaveOpen)
+            {
+                output.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Flushes any buffered data to the underlying stream (if there is one).
+        /// </summary>
+        public void Flush()
+        {
+            if (output != null)
+            {
+                RefreshBuffer();
+            }
+        }
+
+        /// <summary>
+        /// Verifies that SpaceLeft returns zero. It's common to create a byte array
+        /// that is exactly big enough to hold a message, then write to it with
+        /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
+        /// the message was actually as big as expected, which can help bugs.
+        /// </summary>
+        public void CheckNoSpaceLeft()
+        {
+            if (SpaceLeft != 0)
+            {
+                throw new InvalidOperationException("Did not write as much data as expected.");
+            }
+        }
+
+        /// <summary>
+        /// If writing to a flat array, returns the space left in the array. Otherwise,
+        /// throws an InvalidOperationException.
+        /// </summary>
+        public int SpaceLeft
+        {
+            get
+            {
+                if (output == null)
+                {
+                    return limit - position;
+                }
+                else
+                {
+                    throw new InvalidOperationException(
+                        "SpaceLeft can only be called on CodedOutputStreams that are " +
+                        "writing to a flat array.");
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/MapField.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/MapField.cs
new file mode 100644
index 0000000..993a89d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -0,0 +1,760 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Google.Protobuf.Compatibility;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Representation of a map field in a Protocol Buffer message.
+    /// </summary>
+    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
+    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
+    /// <remarks>
+    /// <para>
+    /// This implementation preserves insertion order for simplicity of testing
+    /// code using maps fields. Overwriting an existing entry does not change the
+    /// position of that entry within the map. Equality is not order-sensitive.
+    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />.
+    /// </para>
+    /// <para>
+    /// Null values are not permitted in the map, either for wrapper types or regular messages.
+    /// If a map is deserialized from a data stream and the value is missing from an entry, a default value
+    /// is created instead. For primitive types, that is the regular default value (0, the empty string and so
+    /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length
+    /// encoded value for the field.
+    /// </para>
+    /// <para>
+    /// This implementation does not generally prohibit the use of key/value types which are not
+    /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code>) but nor does it guarantee
+    /// that all operations will work in such cases.
+    /// </para>
+    /// </remarks>
+    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
+    {
+        // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
+        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
+            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
+        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
+
+        /// <summary>
+        /// Creates a deep clone of this object.
+        /// </summary>
+        /// <returns>
+        /// A deep clone of this object.
+        /// </returns>
+        public MapField<TKey, TValue> Clone()
+        {
+            var clone = new MapField<TKey, TValue>();
+            // Keys are never cloneable. Values might be.
+            if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue)))
+            {
+                foreach (var pair in list)
+                {
+                    clone.Add(pair.Key, ((IDeepCloneable<TValue>)pair.Value).Clone());
+                }
+            }
+            else
+            {
+                // Nothing is cloneable, so we don't need to worry.
+                clone.Add(this);
+            }
+            return clone;
+        }
+
+        /// <summary>
+        /// Adds the specified key/value pair to the map.
+        /// </summary>
+        /// <remarks>
+        /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer.
+        /// </remarks>
+        /// <param name="key">The key to add</param>
+        /// <param name="value">The value to add.</param>
+        /// <exception cref="System.ArgumentException">The given key already exists in map.</exception>
+        public void Add(TKey key, TValue value)
+        {
+            // Validation of arguments happens in ContainsKey and the indexer
+            if (ContainsKey(key))
+            {
+                throw new ArgumentException("Key already exists in map", "key");
+            }
+            this[key] = value;
+        }
+
+        /// <summary>
+        /// Determines whether the specified key is present in the map.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns>
+        public bool ContainsKey(TKey key)
+        {
+            ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+            return map.ContainsKey(key);
+        }
+
+        private bool ContainsValue(TValue value)
+        {
+            var comparer = EqualityComparer<TValue>.Default;
+            return list.Any(pair => comparer.Equals(pair.Value, value));
+        }
+
+        /// <summary>
+        /// Removes the entry identified by the given key from the map.
+        /// </summary>
+        /// <param name="key">The key indicating the entry to remove from the map.</param>
+        /// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns>
+        public bool Remove(TKey key)
+        {
+            ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(key, out node))
+            {
+                map.Remove(key);
+                node.List.Remove(node);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Gets the value associated with the specified key.
+        /// </summary>
+        /// <param name="key">The key whose value to get.</param>
+        /// <param name="value">When this method returns, the value associated with the specified key, if the key is found;
+        /// otherwise, the default value for the type of the <paramref name="value"/> parameter.
+        /// This parameter is passed uninitialized.</param>
+        /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(key, out node))
+            {
+                value = node.Value.Value;
+                return true;
+            }
+            else
+            {
+                value = default(TValue);
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the value associated with the specified key.
+        /// </summary>
+        /// <param name="key">The key of the value to get or set.</param>
+        /// <exception cref="KeyNotFoundException">The property is retrieved and key does not exist in the collection.</exception>
+        /// <returns>The value associated with the specified key. If the specified key is not found,
+        /// a get operation throws a <see cref="KeyNotFoundException"/>, and a set operation creates a new element with the specified key.</returns>
+        public TValue this[TKey key]
+        {
+            get
+            {
+                ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+                TValue value;
+                if (TryGetValue(key, out value))
+                {
+                    return value;
+                }
+                throw new KeyNotFoundException();
+            }
+            set
+            {
+                ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+                // value == null check here is redundant, but avoids boxing.
+                if (value == null)
+                {
+                    ProtoPreconditions.CheckNotNullUnconstrained(value, "value");
+                }
+                LinkedListNode<KeyValuePair<TKey, TValue>> node;
+                var pair = new KeyValuePair<TKey, TValue>(key, value);
+                if (map.TryGetValue(key, out node))
+                {
+                    node.Value = pair;
+                }
+                else
+                {
+                    node = list.AddLast(pair);
+                    map[key] = node;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets a collection containing the keys in the map.
+        /// </summary>
+        public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }
+
+        /// <summary>
+        /// Gets a collection containing the values in the map.
+        /// </summary>
+        public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }
+
+        /// <summary>
+        /// Adds the specified entries to the map. The keys and values are not automatically cloned.
+        /// </summary>
+        /// <param name="entries">The entries to add to the map.</param>
+        public void Add(IDictionary<TKey, TValue> entries)
+        {
+            ProtoPreconditions.CheckNotNull(entries, "entries");
+            foreach (var pair in entries)
+            {
+                Add(pair.Key, pair.Value);
+            }
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// An enumerator that can be used to iterate through the collection.
+        /// </returns>
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return list.GetEnumerator();
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through a collection.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
+        /// </returns>
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        /// <summary>
+        /// Adds the specified item to the map.
+        /// </summary>
+        /// <param name="item">The item to add to the map.</param>
+        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
+        {
+            Add(item.Key, item.Value);
+        }
+
+        /// <summary>
+        /// Removes all items from the map.
+        /// </summary>
+        public void Clear()
+        {
+            list.Clear();
+            map.Clear();
+        }
+
+        /// <summary>
+        /// Determines whether map contains an entry equivalent to the given key/value pair.
+        /// </summary>
+        /// <param name="item">The key/value pair to find.</param>
+        /// <returns></returns>
+        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+        {
+            TValue value;
+            return TryGetValue(item.Key, out value)
+                && EqualityComparer<TValue>.Default.Equals(item.Value, value);
+        }
+
+        /// <summary>
+        /// Copies the key/value pairs in this map to an array.
+        /// </summary>
+        /// <param name="array">The array to copy the entries into.</param>
+        /// <param name="arrayIndex">The index of the array at which to start copying values.</param>
+        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            list.CopyTo(array, arrayIndex);
+        }
+
+        /// <summary>
+        /// Removes the specified key/value pair from the map.
+        /// </summary>
+        /// <remarks>Both the key and the value must be found for the entry to be removed.</remarks>
+        /// <param name="item">The key/value pair to remove.</param>
+        /// <returns><c>true</c> if the key/value pair was found and removed; <c>false</c> otherwise.</returns>
+        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+        {
+            if (item.Key == null)
+            {
+                throw new ArgumentException("Key is null", "item");
+            }
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(item.Key, out node) &&
+                EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
+            {
+                map.Remove(item.Key);
+                node.List.Remove(node);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Gets the number of elements contained in the map.
+        /// </summary>
+        public int Count { get { return list.Count; } }
+
+        /// <summary>
+        /// Gets a value indicating whether the map is read-only.
+        /// </summary>
+        public bool IsReadOnly { get { return false; } }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
+        /// </summary>
+        /// <param name="other">The <see cref="System.Object" /> to compare with this instance.</param>
+        /// <returns>
+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool Equals(object other)
+        {
+            return Equals(other as MapField<TKey, TValue>);
+        }
+
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
+        public override int GetHashCode()
+        {
+            var valueComparer = EqualityComparer<TValue>.Default;
+            int hash = 0;
+            foreach (var pair in list)
+            {
+                hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value);
+            }
+            return hash;
+        }
+
+        /// <summary>
+        /// Compares this map with another for equality.
+        /// </summary>
+        /// <remarks>
+        /// The order of the key/value pairs in the maps is not deemed significant in this comparison.
+        /// </remarks>
+        /// <param name="other">The map to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal map; <c>false</c> otherwise.</returns>
+        public bool Equals(MapField<TKey, TValue> other)
+        {
+            if (other == null)
+            {
+                return false;
+            }
+            if (other == this)
+            {
+                return true;
+            }
+            if (other.Count != this.Count)
+            {
+                return false;
+            }
+            var valueComparer = EqualityComparer<TValue>.Default;
+            foreach (var pair in this)
+            {
+                TValue value;
+                if (!other.TryGetValue(pair.Key, out value))
+                {
+                    return false;
+                }
+                if (!valueComparer.Equals(value, pair.Value))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Adds entries to the map from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// It is assumed that the stream is initially positioned after the tag specified by the codec.
+        /// This method will continue reading entries from the stream until the end is reached, or
+        /// a different tag is encountered.
+        /// </remarks>
+        /// <param name="input">Stream to read from</param>
+        /// <param name="codec">Codec describing how the key/value pairs are encoded</param>
+        public void AddEntriesFrom(CodedInputStream input, Codec codec)
+        {
+            var adapter = new Codec.MessageAdapter(codec);
+            do
+            {
+                adapter.Reset();
+                input.ReadMessage(adapter);
+                this[adapter.Key] = adapter.Value;
+            } while (input.MaybeConsumeTag(codec.MapTag));
+        }
+
+        /// <summary>
+        /// Writes the contents of this map to the given coded output stream, using the specified codec
+        /// to encode each entry.
+        /// </summary>
+        /// <param name="output">The output stream to write to.</param>
+        /// <param name="codec">The codec to use for each entry.</param>
+        public void WriteTo(CodedOutputStream output, Codec codec)
+        {
+            var message = new Codec.MessageAdapter(codec);
+            foreach (var entry in list)
+            {
+                message.Key = entry.Key;
+                message.Value = entry.Value;
+                output.WriteTag(codec.MapTag);
+                output.WriteMessage(message);
+            }
+        }
+
+        /// <summary>
+        /// Calculates the size of this map based on the given entry codec.
+        /// </summary>
+        /// <param name="codec">The codec to use to encode each entry.</param>
+        /// <returns></returns>
+        public int CalculateSize(Codec codec)
+        {
+            if (Count == 0)
+            {
+                return 0;
+            }
+            var message = new Codec.MessageAdapter(codec);
+            int size = 0;
+            foreach (var entry in list)
+            {
+                message.Key = entry.Key;
+                message.Value = entry.Value;
+                size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
+                size += CodedOutputStream.ComputeMessageSize(message);
+            }
+            return size;
+        }
+
+        /// <summary>
+        /// Returns a string representation of this repeated field, in the same
+        /// way as it would be represented by the default JSON formatter.
+        /// </summary>
+        public override string ToString()
+        {
+            var writer = new StringWriter();
+            JsonFormatter.Default.WriteDictionary(writer, this);
+            return writer.ToString();
+        }
+
+        #region IDictionary explicit interface implementation
+        void IDictionary.Add(object key, object value)
+        {
+            Add((TKey)key, (TValue)value);
+        }
+
+        bool IDictionary.Contains(object key)
+        {
+            if (!(key is TKey))
+            {
+                return false;
+            }
+            return ContainsKey((TKey)key);
+        }
+
+        IDictionaryEnumerator IDictionary.GetEnumerator()
+        {
+            return new DictionaryEnumerator(GetEnumerator());
+        }
+
+        void IDictionary.Remove(object key)
+        {
+            ProtoPreconditions.CheckNotNull(key, "key");
+            if (!(key is TKey))
+            {
+                return;
+            }
+            Remove((TKey)key);
+        }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            // This is ugly and slow as heck, but with any luck it will never be used anyway.
+            ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList();
+            temp.CopyTo(array, index);
+        }
+
+        bool IDictionary.IsFixedSize { get { return false; } }
+
+        ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
+
+        ICollection IDictionary.Values { get { return (ICollection)Values; } }
+
+        bool ICollection.IsSynchronized { get { return false; } }
+
+        object ICollection.SyncRoot { get { return this; } }
+
+        object IDictionary.this[object key]
+        {
+            get
+            {
+                ProtoPreconditions.CheckNotNull(key, "key");
+                if (!(key is TKey))
+                {
+                    return null;
+                }
+                TValue value;
+                TryGetValue((TKey)key, out value);
+                return value;
+            }
+
+            set
+            {
+                this[(TKey)key] = (TValue)value;
+            }
+        }
+        #endregion
+
+        private class DictionaryEnumerator : IDictionaryEnumerator
+        {
+            private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
+
+            internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
+            {
+                this.enumerator = enumerator;
+            }
+
+            public bool MoveNext()
+            {
+                return enumerator.MoveNext();
+            }
+
+            public void Reset()
+            {
+                enumerator.Reset();
+            }
+
+            public object Current { get { return Entry; } }
+            public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
+            public object Key { get { return enumerator.Current.Key; } }
+            public object Value { get { return enumerator.Current.Value; } }
+        }
+
+        /// <summary>
+        /// A codec for a specific map field. This contains all the information required to encode and
+        /// decode the nested messages.
+        /// </summary>
+        public sealed class Codec
+        {
+            private readonly FieldCodec<TKey> keyCodec;
+            private readonly FieldCodec<TValue> valueCodec;
+            private readonly uint mapTag;
+
+            /// <summary>
+            /// Creates a new entry codec based on a separate key codec and value codec,
+            /// and the tag to use for each map entry.
+            /// </summary>
+            /// <param name="keyCodec">The key codec.</param>
+            /// <param name="valueCodec">The value codec.</param>
+            /// <param name="mapTag">The map tag to use to introduce each map entry.</param>
+            public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)
+            {
+                this.keyCodec = keyCodec;
+                this.valueCodec = valueCodec;
+                this.mapTag = mapTag;
+            }
+
+            /// <summary>
+            /// The tag used in the enclosing message to indicate map entries.
+            /// </summary>
+            internal uint MapTag { get { return mapTag; } }
+
+            /// <summary>
+            /// A mutable message class, used for parsing and serializing. This
+            /// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
+            /// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
+            /// This is nested inside Codec as it's tightly coupled to the associated codec,
+            /// and it's simpler if it has direct access to all its fields.
+            /// </summary>
+            internal class MessageAdapter : IMessage
+            {
+                private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
+
+                private readonly Codec codec;
+                internal TKey Key { get; set; }
+                internal TValue Value { get; set; }
+
+                internal MessageAdapter(Codec codec)
+                {
+                    this.codec = codec;
+                }
+
+                internal void Reset()
+                {
+                    Key = codec.keyCodec.DefaultValue;
+                    Value = codec.valueCodec.DefaultValue;
+                }
+
+                public void MergeFrom(CodedInputStream input)
+                {
+                    uint tag;
+                    while ((tag = input.ReadTag()) != 0)
+                    {
+                        if (tag == codec.keyCodec.Tag)
+                        {
+                            Key = codec.keyCodec.Read(input);
+                        }
+                        else if (tag == codec.valueCodec.Tag)
+                        {
+                            Value = codec.valueCodec.Read(input);
+                        }
+                        else 
+                        {
+                            input.SkipLastField();
+                        }
+                    }
+
+                    // Corner case: a map entry with a key but no value, where the value type is a message.
+                    // Read it as if we'd seen an input stream with no data (i.e. create a "default" message).
+                    if (Value == null)
+                    {
+                        Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
+                    }
+                }
+
+                public void WriteTo(CodedOutputStream output)
+                {
+                    codec.keyCodec.WriteTagAndValue(output, Key);
+                    codec.valueCodec.WriteTagAndValue(output, Value);
+                }
+
+                public int CalculateSize()
+                {
+                    return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
+                }
+
+                MessageDescriptor IMessage.Descriptor { get { return null; } }
+            }
+        }
+
+        private class MapView<T> : ICollection<T>, ICollection
+        {
+            private readonly MapField<TKey, TValue> parent;
+            private readonly Func<KeyValuePair<TKey, TValue>, T> projection;
+            private readonly Func<T, bool> containsCheck;
+
+            internal MapView(
+                MapField<TKey, TValue> parent,
+                Func<KeyValuePair<TKey, TValue>, T> projection,
+                Func<T, bool> containsCheck)
+            {
+                this.parent = parent;
+                this.projection = projection;
+                this.containsCheck = containsCheck;
+            }
+
+            public int Count { get { return parent.Count; } }
+
+            public bool IsReadOnly { get { return true; } }
+
+            public bool IsSynchronized { get { return false; } }
+
+            public object SyncRoot { get { return parent; } }
+
+            public void Add(T item)
+            {
+                throw new NotSupportedException();
+            }
+
+            public void Clear()
+            {
+                throw new NotSupportedException();
+            }
+
+            public bool Contains(T item)
+            {
+                return containsCheck(item);
+            }
+
+            public void CopyTo(T[] array, int arrayIndex)
+            {
+                if (arrayIndex < 0)
+                {
+                    throw new ArgumentOutOfRangeException("arrayIndex");
+                }
+                if (arrayIndex + Count  >= array.Length)
+                {
+                    throw new ArgumentException("Not enough space in the array", "array");
+                }
+                foreach (var item in this)
+                {
+                    array[arrayIndex++] = item;
+                }
+            }
+
+            public IEnumerator<T> GetEnumerator()
+            {
+                return parent.list.Select(projection).GetEnumerator();
+            }
+
+            public bool Remove(T item)
+            {
+                throw new NotSupportedException();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
+
+            public void CopyTo(Array array, int index)
+            {
+                if (index < 0)
+                {
+                    throw new ArgumentOutOfRangeException("index");
+                }
+                if (index + Count >= array.Length)
+                {
+                    throw new ArgumentException("Not enough space in the array", "array");
+                }
+                foreach (var item in this)
+                {
+                    array.SetValue(item, index++);
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs
new file mode 100644
index 0000000..28530a2
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs
@@ -0,0 +1,147 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Read-only wrapper around another dictionary.
+    /// </summary>
+    internal sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
+    {
+        private readonly IDictionary<TKey, TValue> wrapped;
+
+        public ReadOnlyDictionary(IDictionary<TKey, TValue> wrapped)
+        {
+            this.wrapped = wrapped;
+        }
+
+        public void Add(TKey key, TValue value)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public bool ContainsKey(TKey key)
+        {
+            return wrapped.ContainsKey(key);
+        }
+
+        public ICollection<TKey> Keys
+        {
+            get { return wrapped.Keys; }
+        }
+
+        public bool Remove(TKey key)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            return wrapped.TryGetValue(key, out value);
+        }
+
+        public ICollection<TValue> Values
+        {
+            get { return wrapped.Values; }
+        }
+
+        public TValue this[TKey key]
+        {
+            get { return wrapped[key]; }
+            set { throw new InvalidOperationException(); }
+        }
+
+        public void Add(KeyValuePair<TKey, TValue> item)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public void Clear()
+        {
+            throw new InvalidOperationException();
+        }
+
+        public bool Contains(KeyValuePair<TKey, TValue> item)
+        {
+            return wrapped.Contains(item);
+        }
+
+        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            wrapped.CopyTo(array, arrayIndex);
+        }
+
+        public int Count
+        {
+            get { return wrapped.Count; }
+        }
+
+        public bool IsReadOnly
+        {
+            get { return true; }
+        }
+
+        public bool Remove(KeyValuePair<TKey, TValue> item)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return wrapped.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return ((IEnumerable) wrapped).GetEnumerator();
+        }
+
+        public override bool Equals(object obj)
+        {
+            return wrapped.Equals(obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return wrapped.GetHashCode();
+        }
+
+        public override string ToString()
+        {
+            return wrapped.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
new file mode 100644
index 0000000..d1db856
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -0,0 +1,568 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// The contents of a repeated field: essentially, a collection with some extra
+    /// restrictions (no null values) and capabilities (deep cloning).
+    /// </summary>
+    /// <remarks>
+    /// This implementation does not generally prohibit the use of types which are not
+    /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases.
+    /// </remarks>
+    /// <typeparam name="T">The element type of the repeated field.</typeparam>
+    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
+    {
+        private static readonly T[] EmptyArray = new T[0];
+        private const int MinArraySize = 8;
+
+        private T[] array = EmptyArray;
+        private int count = 0;
+
+        /// <summary>
+        /// Creates a deep clone of this repeated field.
+        /// </summary>
+        /// <remarks>
+        /// If the field type is
+        /// a message type, each element is also cloned; otherwise, it is
+        /// assumed that the field type is primitive (including string and
+        /// bytes, both of which are immutable) and so a simple copy is
+        /// equivalent to a deep clone.
+        /// </remarks>
+        /// <returns>A deep clone of this repeated field.</returns>
+        public RepeatedField<T> Clone()
+        {
+            RepeatedField<T> clone = new RepeatedField<T>();
+            if (array != EmptyArray)
+            {
+                clone.array = (T[])array.Clone();
+                IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
+                if (cloneableArray != null)
+                {
+                    for (int i = 0; i < count; i++)
+                    {
+                        clone.array[i] = cloneableArray[i].Clone();
+                    }
+                }
+            }
+            clone.count = count;
+            return clone;
+        }
+
+        /// <summary>
+        /// Adds the entries from the given input stream, decoding them with the specified codec.
+        /// </summary>
+        /// <param name="input">The input stream to read from.</param>
+        /// <param name="codec">The codec to use in order to read each entry.</param>
+        public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)
+        {
+            // TODO: Inline some of the Add code, so we can avoid checking the size on every
+            // iteration.
+            uint tag = input.LastTag;
+            var reader = codec.ValueReader;
+            // Non-nullable value types can be packed or not.
+            if (FieldCodec<T>.IsPackedRepeatedField(tag))
+            {
+                int length = input.ReadLength();
+                if (length > 0)
+                {
+                    int oldLimit = input.PushLimit(length);
+                    while (!input.ReachedLimit)
+                    {
+                        Add(reader(input));
+                    }
+                    input.PopLimit(oldLimit);
+                }
+                // Empty packed field. Odd, but valid - just ignore.
+            }
+            else
+            {
+                // Not packed... (possibly not packable)
+                do
+                {
+                    Add(reader(input));
+                } while (input.MaybeConsumeTag(tag));
+            }
+        }
+
+        /// <summary>
+        /// Calculates the size of this collection based on the given codec.
+        /// </summary>
+        /// <param name="codec">The codec to use when encoding each field.</param>
+        /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>,
+        /// using the same codec.</returns>
+        public int CalculateSize(FieldCodec<T> codec)
+        {
+            if (count == 0)
+            {
+                return 0;
+            }
+            uint tag = codec.Tag;
+            if (codec.PackedRepeatedField)
+            {
+                int dataSize = CalculatePackedDataSize(codec);
+                return CodedOutputStream.ComputeRawVarint32Size(tag) +
+                    CodedOutputStream.ComputeLengthSize(dataSize) +
+                    dataSize;
+            }
+            else
+            {
+                var sizeCalculator = codec.ValueSizeCalculator;
+                int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
+                for (int i = 0; i < count; i++)
+                {
+                    size += sizeCalculator(array[i]);
+                }
+                return size;
+            }
+        }
+
+        private int CalculatePackedDataSize(FieldCodec<T> codec)
+        {
+            int fixedSize = codec.FixedSize;
+            if (fixedSize == 0)
+            {
+                var calculator = codec.ValueSizeCalculator;
+                int tmp = 0;
+                for (int i = 0; i < count; i++)
+                {
+                    tmp += calculator(array[i]);
+                }
+                return tmp;
+            }
+            else
+            {
+                return fixedSize * Count;
+            }
+        }
+
+        /// <summary>
+        /// Writes the contents of this collection to the given <see cref="CodedOutputStream"/>,
+        /// encoding each value using the specified codec.
+        /// </summary>
+        /// <param name="output">The output stream to write to.</param>
+        /// <param name="codec">The codec to use when encoding each value.</param>
+        public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)
+        {
+            if (count == 0)
+            {
+                return;
+            }
+            var writer = codec.ValueWriter;
+            var tag = codec.Tag;
+            if (codec.PackedRepeatedField)
+            {
+                // Packed primitive type
+                uint size = (uint)CalculatePackedDataSize(codec);
+                output.WriteTag(tag);
+                output.WriteRawVarint32(size);
+                for (int i = 0; i < count; i++)
+                {
+                    writer(output, array[i]);
+                }
+            }
+            else
+            {
+                // Not packed: a simple tag/value pair for each value.
+                // Can't use codec.WriteTagAndValue, as that omits default values.
+                for (int i = 0; i < count; i++)
+                {
+                    output.WriteTag(tag);
+                    writer(output, array[i]);
+                }
+            }
+        }
+
+        private void EnsureSize(int size)
+        {
+            if (array.Length < size)
+            {
+                size = Math.Max(size, MinArraySize);
+                int newSize = Math.Max(array.Length * 2, size);
+                var tmp = new T[newSize];
+                Array.Copy(array, 0, tmp, 0, array.Length);
+                array = tmp;
+            }
+        }
+
+        /// <summary>
+        /// Adds the specified item to the collection.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        public void Add(T item)
+        {
+            if (item == null)
+            {
+                throw new ArgumentNullException("item");
+            }
+            EnsureSize(count + 1);
+            array[count++] = item;
+        }
+
+        /// <summary>
+        /// Removes all items from the collection.
+        /// </summary>
+        public void Clear()
+        {
+            array = EmptyArray;
+            count = 0;
+        }
+
+        /// <summary>
+        /// Determines whether this collection contains the given item.
+        /// </summary>
+        /// <param name="item">The item to find.</param>
+        /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>
+        public bool Contains(T item)
+        {
+            return IndexOf(item) != -1;
+        }
+
+        /// <summary>
+        /// Copies this collection to the given array.
+        /// </summary>
+        /// <param name="array">The array to copy to.</param>
+        /// <param name="arrayIndex">The first index of the array to copy to.</param>
+        public void CopyTo(T[] array, int arrayIndex)
+        {
+            Array.Copy(this.array, 0, array, arrayIndex, count);
+        }
+
+        /// <summary>
+        /// Removes the specified item from the collection
+        /// </summary>
+        /// <param name="item">The item to remove.</param>
+        /// <returns><c>true</c> if the item was found and removed; <c>false</c> otherwise.</returns>
+        public bool Remove(T item)
+        {
+            int index = IndexOf(item);
+            if (index == -1)
+            {
+                return false;
+            }            
+            Array.Copy(array, index + 1, array, index, count - index - 1);
+            count--;
+            array[count] = default(T);
+            return true;
+        }
+
+        /// <summary>
+        /// Gets the number of elements contained in the collection.
+        /// </summary>
+        public int Count { get { return count; } }
+
+        /// <summary>
+        /// Gets a value indicating whether the collection is read-only.
+        /// </summary>
+        public bool IsReadOnly { get { return false; } }
+
+        // TODO: Remove this overload and just handle it in the one below, at execution time?
+
+        /// <summary>
+        /// Adds all of the specified values into this collection.
+        /// </summary>
+        /// <param name="values">The values to add to this collection.</param>
+        public void Add(RepeatedField<T> values)
+        {
+            if (values == null)
+            {
+                throw new ArgumentNullException("values");
+            }
+            EnsureSize(count + values.count);
+            // We know that all the values will be valid, because it's a RepeatedField.
+            Array.Copy(values.array, 0, array, count, values.count);
+            count += values.count;
+        }
+
+        /// <summary>
+        /// Adds all of the specified values into this collection.
+        /// </summary>
+        /// <param name="values">The values to add to this collection.</param>
+        public void Add(IEnumerable<T> values)
+        {
+            if (values == null)
+            {
+                throw new ArgumentNullException("values");
+            }
+            // TODO: Check for ICollection and get the Count, to optimize?
+            foreach (T item in values)
+            {
+                Add(item);
+            }
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// An enumerator that can be used to iterate through the collection.
+        /// </returns>
+        public IEnumerator<T> GetEnumerator()
+        {
+            for (int i = 0; i < count; i++)
+            {
+                yield return array[i];
+            }
+        }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
+        /// </summary>
+        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
+        /// <returns>
+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as RepeatedField<T>);
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through a collection.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
+        /// </returns>
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
+        public override int GetHashCode()
+        {
+            int hash = 0;
+            for (int i = 0; i < count; i++)
+            {
+                hash = hash * 31 + array[i].GetHashCode();
+            }
+            return hash;
+        }
+
+        /// <summary>
+        /// Compares this repeated field with another for equality.
+        /// </summary>
+        /// <param name="other">The repeated field to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>
+        public bool Equals(RepeatedField<T> other)
+        {
+            if (ReferenceEquals(other, null))
+            {
+                return false;
+            }
+            if (ReferenceEquals(other, this))
+            {
+                return true;
+            }
+            if (other.Count != this.Count)
+            {
+                return false;
+            }
+            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            for (int i = 0; i < count; i++)
+            {
+                if (!comparer.Equals(array[i], other.array[i]))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the index of the given item within the collection, or -1 if the item is not
+        /// present.
+        /// </summary>
+        /// <param name="item">The item to find in the collection.</param>
+        /// <returns>The zero-based index of the item, or -1 if it is not found.</returns>
+        public int IndexOf(T item)
+        {
+            if (item == null)
+            {
+                throw new ArgumentNullException("item");
+            }
+            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            for (int i = 0; i < count; i++)
+            {
+                if (comparer.Equals(array[i], item))
+                {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Inserts the given item at the specified index.
+        /// </summary>
+        /// <param name="index">The index at which to insert the item.</param>
+        /// <param name="item">The item to insert.</param>
+        public void Insert(int index, T item)
+        {
+            if (item == null)
+            {
+                throw new ArgumentNullException("item");
+            }
+            if (index < 0 || index > count)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+            EnsureSize(count + 1);
+            Array.Copy(array, index, array, index + 1, count - index);
+            array[index] = item;
+            count++;
+        }
+
+        /// <summary>
+        /// Removes the item at the given index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the item to remove.</param>
+        public void RemoveAt(int index)
+        {
+            if (index < 0 || index >= count)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+            Array.Copy(array, index + 1, array, index, count - index - 1);
+            count--;
+            array[count] = default(T);
+        }
+
+        /// <summary>
+        /// Returns a string representation of this repeated field, in the same
+        /// way as it would be represented by the default JSON formatter.
+        /// </summary>
+        public override string ToString()
+        {
+            var writer = new StringWriter();
+            JsonFormatter.Default.WriteList(writer, this);
+            return writer.ToString();
+        }
+
+        /// <summary>
+        /// Gets or sets the item at the specified index.
+        /// </summary>
+        /// <value>
+        /// The element at the specified index.
+        /// </value>
+        /// <param name="index">The zero-based index of the element to get or set.</param>
+        /// <returns>The item at the specified index.</returns>
+        public T this[int index]
+        {
+            get
+            {
+                if (index < 0 || index >= count)
+                {
+                    throw new ArgumentOutOfRangeException("index");
+                }
+                return array[index];
+            }
+            set
+            {
+                if (index < 0 || index >= count)
+                {
+                    throw new ArgumentOutOfRangeException("index");
+                }
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+                array[index] = value;
+            }
+        }
+
+        #region Explicit interface implementation for IList and ICollection.
+        bool IList.IsFixedSize { get { return false; } }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            Array.Copy(this.array, 0, array, index, count);
+        }
+
+        bool ICollection.IsSynchronized { get { return false; } }
+
+        object ICollection.SyncRoot { get { return this; } }
+
+        object IList.this[int index]
+        {
+            get { return this[index]; }
+            set { this[index] = (T)value; }
+        }
+
+        int IList.Add(object value)
+        {
+            Add((T) value);
+            return count - 1;
+        }
+
+        bool IList.Contains(object value)
+        {
+            return (value is T && Contains((T)value));
+        }
+
+        int IList.IndexOf(object value)
+        {
+            if (!(value is T))
+            {
+                return -1;
+            }
+            return IndexOf((T)value);
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            Insert(index, (T) value);
+        }
+
+        void IList.Remove(object value)
+        {
+            if (!(value is T))
+            {
+                return;
+            }
+            Remove((T)value);
+        }
+        #endregion        
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
new file mode 100644
index 0000000..8a6fefa
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
@@ -0,0 +1,64 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    /// <summary>
+    /// Extension methods for <see cref="PropertyInfo"/>, effectively providing
+    /// the familiar members from previous desktop framework versions while
+    /// targeting the newer releases, .NET Core etc.
+    /// </summary>
+    internal static class PropertyInfoExtensions
+    {
+        /// <summary>
+        /// Returns the public getter of a property, or null if there is no such getter
+        /// (either because it's read-only, or the getter isn't public).
+        /// </summary>
+        internal static MethodInfo GetGetMethod(this PropertyInfo target)
+        {
+            var method = target.GetMethod;
+            return method != null && method.IsPublic ? method : null;
+        }
+
+        /// <summary>
+        /// Returns the public setter of a property, or null if there is no such setter
+        /// (either because it's write-only, or the setter isn't public).
+        /// </summary>
+        internal static MethodInfo GetSetMethod(this PropertyInfo target)
+        {
+            var method = target.SetMethod;
+            return method != null && method.IsPublic ? method : null;
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
new file mode 100644
index 0000000..762a29e
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
@@ -0,0 +1,113 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    /// <summary>
+    /// Provides extension methods on Type that just proxy to TypeInfo.
+    /// These are used to support the new type system from .NET 4.5, without
+    /// having calls to GetTypeInfo all over the place. While the methods here are meant to be
+    /// broadly compatible with the desktop framework, there are some subtle differences in behaviour - but
+    /// they're not expected to affect our use cases. While the class is internal, that should be fine: we can
+    /// evaluate each new use appropriately.
+    /// </summary>
+    internal static class TypeExtensions
+    {
+        /// <summary>
+        /// Returns true if the target type is a value type, including a nullable value type or an enum, or false
+        /// if it's a reference type (class, delegate, interface - including System.ValueType and System.Enum).
+        /// </summary>
+        internal static bool IsValueType(this Type target)
+        {
+            return target.GetTypeInfo().IsValueType;
+        }
+
+        /// <summary>
+        /// See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom
+        /// </summary>
+        internal static bool IsAssignableFrom(this Type target, Type c)
+        {
+            return target.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
+        }
+
+        /// <summary>
+        /// Returns a representation of the public property associated with the given name in the given type,
+        /// including inherited properties or null if there is no such public property.
+        /// Here, "public property" means a property where either the getter, or the setter, or both, is public.
+        /// </summary>
+        internal static PropertyInfo GetProperty(this Type target, string name)
+        {
+            // GetDeclaredProperty only returns properties declared in the given type, so we need to recurse.
+            while (target != null)
+            {
+                var typeInfo = target.GetTypeInfo();
+                var ret = typeInfo.GetDeclaredProperty(name);
+                if (ret != null && ((ret.CanRead && ret.GetMethod.IsPublic) || (ret.CanWrite && ret.SetMethod.IsPublic)))
+                {
+                    return ret;
+                }
+                target = typeInfo.BaseType;
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Returns a representation of the public method associated with the given name in the given type,
+        /// including inherited methods.
+        /// </summary>
+        /// <remarks>
+        /// This has a few differences compared with Type.GetMethod in the desktop framework. It will throw
+        /// if there is an ambiguous match even between a private method and a public one, but it *won't* throw
+        /// if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and
+        /// class Child : Base declares public void Foo(long)).
+        /// </remarks>
+        /// <exception cref="AmbiguousMatchException">One type in the hierarchy declared more than one method with the same name</exception>
+        internal static MethodInfo GetMethod(this Type target, string name)
+        {
+            // GetDeclaredMethod only returns methods declared in the given type, so we need to recurse.
+            while (target != null)
+            {
+                var typeInfo = target.GetTypeInfo();
+                var ret = typeInfo.GetDeclaredMethod(name);
+                if (ret != null && ret.IsPublic)
+                {
+                    return ret;
+                }
+                target = typeInfo.BaseType;
+            }
+            return null;
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FieldCodec.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FieldCodec.cs
new file mode 100644
index 0000000..9831308
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FieldCodec.cs
@@ -0,0 +1,473 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.Compatibility;
+using Google.Protobuf.WellKnownTypes;
+using System;
+using System.Collections.Generic;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Factory methods for <see cref="FieldCodec{T}"/>.
+    /// </summary>
+    public static class FieldCodec
+    {
+        // TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...)
+
+        /// <summary>
+        /// Retrieves a codec suitable for a string field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<string> ForString(uint tag)
+        {
+            return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a bytes field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<ByteString> ForBytes(uint tag)
+        {
+            return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a bool field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<bool> ForBool(uint tag)
+        {
+            return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an int32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<int> ForInt32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an sint32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<int> ForSInt32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a fixed32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<uint> ForFixed32(uint tag)
+        {
+            return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an sfixed32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<int> ForSFixed32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a uint32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<uint> ForUInt32(uint tag)
+        {
+            return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an int64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<long> ForInt64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an sint64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<long> ForSInt64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a fixed64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<ulong> ForFixed64(uint tag)
+        {
+            return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for an sfixed64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<long> ForSFixed64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a uint64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<ulong> ForUInt64(uint tag)
+        {
+            return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a float field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<float> ForFloat(uint tag)
+        {
+            return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a double field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<double> ForDouble(uint tag)
+        {
+            return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag);
+        }
+
+        // Enums are tricky. We can probably use expression trees to build these delegates automatically,
+        // but it's easy to generate the code for it.
+
+        /// <summary>
+        /// Retrieves a codec suitable for an enum field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param>
+        /// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
+        {
+            return new FieldCodec<T>(input => fromInt32(
+                input.ReadEnum()),
+                (output, value) => output.WriteEnum(toInt32(value)),
+                value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag);
+        }
+
+        /// <summary>
+        /// Retrieves a codec suitable for a message field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <param name="parser">A parser to use for the message type.</param>
+        /// <returns>A codec for the given tag.</returns>
+        public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T>
+        {
+            return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; },
+                (output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag);
+        }
+
+        /// <summary>
+        /// Creates a codec for a wrapper type of a class - which must be string or ByteString.
+        /// </summary>
+        public static FieldCodec<T> ForClassWrapper<T>(uint tag) where T : class
+        {
+            var nestedCodec = WrapperCodecs.GetCodec<T>();
+            return new FieldCodec<T>(
+                input => WrapperCodecs.Read<T>(input, nestedCodec),
+                (output, value) => WrapperCodecs.Write<T>(output, value, nestedCodec),
+                value => WrapperCodecs.CalculateSize<T>(value, nestedCodec),
+                tag,
+                null); // Default value for the wrapper
+        }
+
+        /// <summary>
+        /// Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64,
+        /// Bool, Single or Double.
+        /// </summary>
+        public static FieldCodec<T?> ForStructWrapper<T>(uint tag) where T : struct
+        {
+            var nestedCodec = WrapperCodecs.GetCodec<T>();
+            return new FieldCodec<T?>(
+                input => WrapperCodecs.Read<T>(input, nestedCodec),
+                (output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec),
+                value => value == null ? 0 : WrapperCodecs.CalculateSize<T>(value.Value, nestedCodec),
+                tag,
+                null); // Default value for the wrapper
+        }
+
+        /// <summary>
+        /// Helper code to create codecs for wrapper types.
+        /// </summary>
+        /// <remarks>
+        /// Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it
+        /// slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place,
+        /// we can refactor later if we come up with something cleaner.
+        /// </remarks>
+        private static class WrapperCodecs
+        {
+            private static readonly Dictionary<System.Type, object> Codecs = new Dictionary<System.Type, object>
+            {
+                { typeof(bool), ForBool(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
+                { typeof(int), ForInt32(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
+                { typeof(long), ForInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
+                { typeof(uint), ForUInt32(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
+                { typeof(ulong), ForUInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
+                { typeof(float), ForFloat(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) },
+                { typeof(double), ForDouble(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) },
+                { typeof(string), ForString(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) },
+                { typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
+            };
+
+            /// <summary>
+            /// Returns a field codec which effectively wraps a value of type T in a message.
+            /// 
+            /// </summary>
+            internal static FieldCodec<T> GetCodec<T>()
+            {
+                object value;
+                if (!Codecs.TryGetValue(typeof(T), out value))
+                {
+                    throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T));
+                }
+                return (FieldCodec<T>) value;
+            }
+
+            internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec)
+            {
+                int length = input.ReadLength();
+                int oldLimit = input.PushLimit(length);
+
+                uint tag;
+                T value = codec.DefaultValue;
+                while ((tag = input.ReadTag()) != 0)
+                {
+                    if (tag == codec.Tag)
+                    {
+                        value = codec.Read(input);
+                    }
+                    else
+                    {
+                        input.SkipLastField();
+                    }
+
+                }
+                input.CheckReadEndOfStreamTag();
+                input.PopLimit(oldLimit);
+
+                return value;
+            }
+
+            internal static void Write<T>(CodedOutputStream output, T value, FieldCodec<T> codec)
+            {
+                output.WriteLength(codec.CalculateSizeWithTag(value));
+                codec.WriteTagAndValue(output, value);
+            }
+
+            internal  static int CalculateSize<T>(T value, FieldCodec<T> codec)
+            {
+                int fieldLength = codec.CalculateSizeWithTag(value);
+                return CodedOutputStream.ComputeLengthSize(fieldLength) + fieldLength;
+            }
+        }
+    }
+
+    /// <summary>
+    /// <para>
+    /// An encode/decode pair for a single field. This effectively encapsulates
+    /// all the information needed to read or write the field value from/to a coded
+    /// stream.
+    /// </para>
+    /// <para>
+    /// This class is public and has to be as it is used by generated code, but its public
+    /// API is very limited - just what the generated code needs to call directly.
+    /// </para>
+    /// </summary>
+    /// <remarks>
+    /// This never writes default values to the stream, and does not address "packedness"
+    /// in repeated fields itself, other than to know whether or not the field *should* be packed.
+    /// </remarks>
+    public sealed class FieldCodec<T>
+    {
+        private static readonly T DefaultDefault;
+        private static readonly bool TypeSupportsPacking = typeof(T).IsValueType() && Nullable.GetUnderlyingType(typeof(T)) == null;
+
+        static FieldCodec()
+        {
+            if (typeof(T) == typeof(string))
+            {
+                DefaultDefault = (T)(object)"";
+            }
+            else if (typeof(T) == typeof(ByteString))
+            {
+                DefaultDefault = (T)(object)ByteString.Empty;
+            }
+            // Otherwise it's the default value of the CLR type
+        }
+
+        internal static bool IsPackedRepeatedField(uint tag) =>
+            TypeSupportsPacking && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited;
+
+        internal bool PackedRepeatedField { get; }
+
+        /// <summary>
+        /// Returns a delegate to write a value (unconditionally) to a coded output stream.
+        /// </summary>
+        internal Action<CodedOutputStream, T> ValueWriter { get; }
+
+        /// <summary>
+        /// Returns the size calculator for just a value.
+        /// </summary>
+        internal Func<T, int> ValueSizeCalculator { get; }
+
+        /// <summary>
+        /// Returns a delegate to read a value from a coded input stream. It is assumed that
+        /// the stream is already positioned on the appropriate tag.
+        /// </summary>
+        internal Func<CodedInputStream, T> ValueReader { get; }
+
+        /// <summary>
+        /// Returns the fixed size for an entry, or 0 if sizes vary.
+        /// </summary>
+        internal int FixedSize { get; }
+
+        /// <summary>
+        /// Gets the tag of the codec.
+        /// </summary>
+        /// <value>
+        /// The tag of the codec.
+        /// </value>
+        internal uint Tag { get; }
+
+        /// <summary>
+        /// Default value for this codec. Usually the same for every instance of the same type, but
+        /// for string/ByteString wrapper fields the codec's default value is null, whereas for
+        /// other string/ByteString fields it's "" or ByteString.Empty.
+        /// </summary>
+        /// <value>
+        /// The default value of the codec's type.
+        /// </value>
+        internal T DefaultValue { get; }
+
+        private readonly int tagSize;
+        
+        internal FieldCodec(
+                Func<CodedInputStream, T> reader,
+                Action<CodedOutputStream, T> writer,
+                int fixedSize,
+                uint tag) : this(reader, writer, _ => fixedSize, tag)
+        {
+            FixedSize = fixedSize;
+        }
+
+        internal FieldCodec(
+            Func<CodedInputStream, T> reader,
+            Action<CodedOutputStream, T> writer,
+            Func<T, int> sizeCalculator,
+            uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault)
+        {
+        }
+
+        internal FieldCodec(
+            Func<CodedInputStream, T> reader,
+            Action<CodedOutputStream, T> writer,
+            Func<T, int> sizeCalculator,
+            uint tag,
+            T defaultValue)
+        {
+            ValueReader = reader;
+            ValueWriter = writer;
+            ValueSizeCalculator = sizeCalculator;
+            FixedSize = 0;
+            Tag = tag;
+            DefaultValue = defaultValue;
+            tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
+            // Detect packed-ness once, so we can check for it within RepeatedField<T>.
+            PackedRepeatedField = IsPackedRepeatedField(tag);
+        }
+
+        /// <summary>
+        /// Write a tag and the given value, *if* the value is not the default.
+        /// </summary>
+        public void WriteTagAndValue(CodedOutputStream output, T value)
+        {
+            if (!IsDefault(value))
+            {
+                output.WriteTag(Tag);
+                ValueWriter(output, value);
+            }
+        }
+
+        /// <summary>
+        /// Reads a value of the codec type from the given <see cref="CodedInputStream"/>.
+        /// </summary>
+        /// <param name="input">The input stream to read from.</param>
+        /// <returns>The value read from the stream.</returns>
+        public T Read(CodedInputStream input) => ValueReader(input);
+
+        /// <summary>
+        /// Calculates the size required to write the given value, with a tag,
+        /// if the value is not the default.
+        /// </summary>
+        public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
+
+        private bool IsDefault(T value) => EqualityComparer<T>.Default.Equals(value, DefaultValue);
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FrameworkPortability.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FrameworkPortability.cs
new file mode 100644
index 0000000..c8060f6
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/FrameworkPortability.cs
@@ -0,0 +1,49 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Text.RegularExpressions;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Class containing helpful workarounds for various platform compatibility
+    /// </summary>
+    internal static class FrameworkPortability
+    {
+        // The value of RegexOptions.Compiled is 8. We can test for the presence at
+        // execution time using Enum.IsDefined, so a single build will do the right thing
+        // on each platform. (RegexOptions.Compiled isn't supported by PCLs.)
+        internal static readonly RegexOptions CompiledRegexWhereAvailable =
+            Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None;
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.csproj
new file mode 100644
index 0000000..fdd97dd
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf</RootNamespace>
+    <AssemblyName>Google.Protobuf</AssemblyName>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DocumentationFile>bin\Debug\Google.Protobuf.xml</DocumentationFile>
+    <NoWarn>
+    </NoWarn>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
+    <NoWarn>
+    </NoWarn>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
+    <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
+    <NoWarn>
+    </NoWarn>
+    <DefineConstants>TRACE;SIGNED</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ByteArray.cs" />
+    <Compile Include="ByteString.cs" />
+    <Compile Include="CodedOutputStream.ComputeSize.cs" />
+    <Compile Include="CodedInputStream.cs" />
+    <Compile Include="CodedOutputStream.cs" />
+    <Compile Include="Collections\MapField.cs" />
+    <Compile Include="Collections\ReadOnlyDictionary.cs" />
+    <Compile Include="Collections\RepeatedField.cs" />
+    <Compile Include="Compatibility\PropertyInfoExtensions.cs" />
+    <Compile Include="Compatibility\TypeExtensions.cs" />
+    <Compile Include="FieldCodec.cs" />
+    <Compile Include="FrameworkPortability.cs" />
+    <Compile Include="ICustomDiagnosticMessage.cs" />
+    <Compile Include="IDeepCloneable.cs" />
+    <Compile Include="InvalidJsonException.cs" />
+    <Compile Include="JsonFormatter.cs" />
+    <Compile Include="JsonParser.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonTokenizer.cs" />
+    <Compile Include="MessageExtensions.cs" />
+    <Compile Include="IMessage.cs" />
+    <Compile Include="InvalidProtocolBufferException.cs" />
+    <Compile Include="LimitedInputStream.cs" />
+    <Compile Include="MessageParser.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Reflection\Descriptor.cs" />
+    <Compile Include="Reflection\DescriptorBase.cs" />
+    <Compile Include="Reflection\DescriptorPool.cs" />
+    <Compile Include="Reflection\DescriptorUtil.cs" />
+    <Compile Include="Reflection\DescriptorValidationException.cs" />
+    <Compile Include="Reflection\EnumDescriptor.cs" />
+    <Compile Include="Reflection\EnumValueDescriptor.cs" />
+    <Compile Include="Reflection\FieldAccessorBase.cs" />
+    <Compile Include="Reflection\FieldDescriptor.cs" />
+    <Compile Include="Reflection\FieldType.cs" />
+    <Compile Include="Reflection\FileDescriptor.cs" />
+    <Compile Include="Reflection\GeneratedClrTypeInfo.cs" />
+    <Compile Include="Reflection\IDescriptor.cs" />
+    <Compile Include="Reflection\IFieldAccessor.cs" />
+    <Compile Include="Reflection\MapFieldAccessor.cs" />
+    <Compile Include="Reflection\MessageDescriptor.cs" />
+    <Compile Include="Reflection\MethodDescriptor.cs" />
+    <Compile Include="Reflection\OneofAccessor.cs" />
+    <Compile Include="Reflection\OneofDescriptor.cs" />
+    <Compile Include="Reflection\OriginalNameAttribute.cs" />
+    <Compile Include="Reflection\PackageDescriptor.cs" />
+    <Compile Include="Reflection\PartialClasses.cs" />
+    <Compile Include="Reflection\ReflectionUtil.cs" />
+    <Compile Include="Reflection\RepeatedFieldAccessor.cs" />
+    <Compile Include="Reflection\ServiceDescriptor.cs" />
+    <Compile Include="Reflection\SingleFieldAccessor.cs" />
+    <Compile Include="ProtoPreconditions.cs" />
+    <Compile Include="Reflection\TypeRegistry.cs" />
+    <Compile Include="WellKnownTypes\Any.cs" />
+    <Compile Include="WellKnownTypes\AnyPartial.cs" />
+    <Compile Include="WellKnownTypes\Api.cs" />
+    <Compile Include="WellKnownTypes\Duration.cs" />
+    <Compile Include="WellKnownTypes\DurationPartial.cs" />
+    <Compile Include="WellKnownTypes\Empty.cs" />
+    <Compile Include="WellKnownTypes\FieldMask.cs" />
+    <Compile Include="WellKnownTypes\FieldMaskPartial.cs" />
+    <Compile Include="WellKnownTypes\SourceContext.cs" />
+    <Compile Include="WellKnownTypes\Struct.cs" />
+    <Compile Include="WellKnownTypes\TimeExtensions.cs" />
+    <Compile Include="WellKnownTypes\Timestamp.cs" />
+    <Compile Include="WellKnownTypes\TimestampPartial.cs" />
+    <Compile Include="WellKnownTypes\Type.cs" />
+    <Compile Include="WellKnownTypes\ValuePartial.cs" />
+    <Compile Include="WellKnownTypes\Wrappers.cs" />
+    <Compile Include="WellKnownTypes\WrappersPartial.cs" />
+    <Compile Include="WireFormat.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Google.Protobuf.nuspec" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <Import Project="..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets" Condition="Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets'))" />
+  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.nuspec
new file mode 100644
index 0000000..90e3da3
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Google.Protobuf.nuspec
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package>
+  <metadata>
+    <id>Google.Protobuf</id>
+    <title>Google Protocol Buffers C#</title>
+    <summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary>
+    <description>See project site for more info.</description>
+    <version>3.0.0-beta3</version>
+    <authors>Google Inc.</authors>
+    <owners>protobuf-packages</owners>
+    <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
+    <projectUrl>https://github.com/google/protobuf</projectUrl>
+    <requireLicenseAcceptance>false</requireLicenseAcceptance>
+    <releaseNotes>C# proto3 support</releaseNotes>
+    <copyright>Copyright 2015, Google Inc.</copyright>
+    <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags>
+    <dependencies>
+      <!-- Dependencies for older, monolithic-assembly platforms -->
+      <group targetFramework="net45" />
+      <group targetFramework="wp8" />
+      <group targetFramework="win8" />
+      <group targetFramework="wpa81" />
+      <group targetFramework="xamarin.ios" />
+      <group targetFramework="monotouch" />
+      <group targetFramework="monoandroid" />
+      <!-- Dependencies for newer, more granular platforms (.NET Core etc) -->
+      <group targetFramework="dotnet">
+        <dependency id="System.Collections" version="4.0.0" />
+        <dependency id="System.Diagnostics.Debug" version="4.0.0" />
+        <dependency id="System.Globalization" version="4.0.0" />
+        <dependency id="System.IO" version="4.0.0" />
+        <dependency id="System.Linq" version="4.0.0" />
+        <dependency id="System.Linq.Expressions" version="4.0.0" />
+        <dependency id="System.ObjectModel" version="4.0.0" />
+        <dependency id="System.Reflection" version="4.0.0" />
+        <dependency id="System.Reflection.Extensions" version="4.0.0" />
+        <dependency id="System.Runtime" version="4.0.0" />
+        <dependency id="System.Runtime.Extensions" version="4.0.0" />
+        <dependency id="System.Text.Encoding" version="4.0.0" />
+        <dependency id="System.Text.RegularExpressions" version="4.0.0" />
+        <dependency id="System.Threading" version="4.0.0" />
+      </group>
+    </dependencies>
+  </metadata>
+  <files>
+    <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" />
+    <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" />
+    <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" />
+    <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/dotnet" />
+    <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/dotnet" />
+    <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/dotnet" />
+    <file src="**\*.cs" target="src" />
+  </files>
+</package>
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs
new file mode 100644
index 0000000..a009056
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs
@@ -0,0 +1,69 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+#endregion
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// A message type that has a custom string format for diagnostic purposes.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// Calling <see cref="object.ToString"/> on a generated message type normally
+    /// returns the JSON representation. If a message type implements this interface,
+    /// then the <see cref="ToDiagnosticString"/> method will be called instead of the regular
+    /// JSON formatting code, but only when <c>ToString()</c> is called either on the message itself
+    /// or on another message which contains it. This does not affect the normal JSON formatting of
+    /// the message.
+    /// </para>
+    /// <para>
+    /// For example, if you create a proto message representing a GUID, the internal
+    /// representation may be a <c>bytes</c> field or four <c>fixed32</c> fields. However, when debugging
+    /// it may be more convenient to see a result in the same format as <see cref="System.Guid"/> provides.
+    /// </para>
+    /// <para>This interface extends <see cref="IMessage"/> to avoid it accidentally being implemented
+    /// on types other than messages, where it would not be used by anything in the framework.</para>
+    /// </remarks>
+    public interface ICustomDiagnosticMessage : IMessage
+    {
+        /// <summary>
+        /// Returns a string representation of this object, for diagnostic purposes.
+        /// </summary>
+        /// <remarks>
+        /// This method is called when a message is formatted as part of a <see cref="object.ToString"/>
+        /// call. It does not affect the JSON representation used by <see cref="JsonFormatter"/> other than
+        /// in calls to <see cref="JsonFormatter.ToDiagnosticString(IMessage)"/>. While it is recommended
+        /// that the result is valid JSON, this is never assumed by the Protobuf library.
+        /// </remarks>
+        /// <returns>A string representation of this object, for diagnostic purposes.</returns>
+        string ToDiagnosticString();
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IDeepCloneable.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IDeepCloneable.cs
new file mode 100644
index 0000000..c9c71bb
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IDeepCloneable.cs
@@ -0,0 +1,54 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Generic interface for a deeply cloneable type.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// All generated messages implement this interface, but so do some non-message types.
+    /// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
+    /// it is simpler to keep this as a separate interface.
+    /// </para>
+    /// </remarks>
+    /// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
+    public interface IDeepCloneable<T>
+    {
+        /// <summary>
+        /// Creates a deep clone of this object.
+        /// </summary>
+        /// <returns>A deep clone of this object.</returns>
+        T Clone();
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IMessage.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IMessage.cs
new file mode 100644
index 0000000..3e644c1
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/IMessage.cs
@@ -0,0 +1,87 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using Google.Protobuf.Reflection;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Interface for a Protocol Buffers message, supporting
+    /// basic operations required for serialization.
+    /// </summary>
+    public interface IMessage
+    {
+        /// <summary>
+        /// Merges the data from the specified coded input stream with the current message.
+        /// </summary>
+        /// <remarks>See the user guide for precise merge semantics.</remarks>
+        /// <param name="input"></param>
+        void MergeFrom(CodedInputStream input);
+
+        /// <summary>
+        /// Writes the data to the given coded output stream.
+        /// </summary>
+        /// <param name="output">Coded output stream to write the data to. Must not be null.</param>
+        void WriteTo(CodedOutputStream output);
+
+        /// <summary>
+        /// Calculates the size of this message in Protocol Buffer wire format, in bytes.
+        /// </summary>
+        /// <returns>The number of bytes required to write this message
+        /// to a coded output stream.</returns>
+        int CalculateSize();
+
+        /// <summary>
+        /// Descriptor for this message. All instances are expected to return the same descriptor,
+        /// and for generated types this will be an explicitly-implemented member, returning the
+        /// same value as the static property declared on the type.
+        /// </summary>
+        MessageDescriptor Descriptor { get; }
+    }
+
+    /// <summary>
+    /// Generic interface for a Protocol Buffers message,
+    /// where the type parameter is expected to be the same type as
+    /// the implementation class.
+    /// </summary>
+    /// <typeparam name="T">The message type.</typeparam>
+    public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T> where T : IMessage<T>
+    {
+        /// <summary>
+        /// Merges the given message into this one.
+        /// </summary>
+        /// <remarks>See the user guide for precise merge semantics.</remarks>
+        /// <param name="message">The message to merge with this one. Must not be null.</param>
+        void MergeFrom(T message);
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidJsonException.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidJsonException.cs
new file mode 100644
index 0000000..b543420
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidJsonException.cs
@@ -0,0 +1,53 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Thrown when an attempt is made to parse invalid JSON, e.g. using
+    /// a non-string property key, or including a redundant comma. Parsing a protocol buffer
+    /// message represented in JSON using <see cref="JsonParser"/> can throw both this
+    /// exception and <see cref="InvalidProtocolBufferException"/> depending on the situation. This
+    /// exception is only thrown for "pure JSON" errors, whereas <c>InvalidProtocolBufferException</c>
+    /// is thrown when the JSON may be valid in and of itself, but cannot be parsed as a protocol buffer
+    /// message.
+    /// </summary>
+    public sealed class InvalidJsonException : IOException
+    {
+        internal InvalidJsonException(string message)
+            : base(message)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
new file mode 100644
index 0000000..a6aefb6
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
@@ -0,0 +1,129 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Thrown when a protocol message being parsed is invalid in some way,
+    /// e.g. it contains a malformed varint or a negative byte length.
+    /// </summary>
+    public sealed class InvalidProtocolBufferException : IOException
+    {
+        internal InvalidProtocolBufferException(string message)
+            : base(message)
+        {
+        }
+
+        internal InvalidProtocolBufferException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+        internal static InvalidProtocolBufferException MoreDataAvailable()
+        {
+            return new InvalidProtocolBufferException(
+                "Completed reading a message while more data was available in the stream.");
+        }
+
+        internal static InvalidProtocolBufferException TruncatedMessage()
+        {
+            return new InvalidProtocolBufferException(
+                "While parsing a protocol message, the input ended unexpectedly " +
+                "in the middle of a field.  This could mean either than the " +
+                "input has been truncated or that an embedded message " +
+                "misreported its own length.");
+        }
+
+        internal static InvalidProtocolBufferException NegativeSize()
+        {
+            return new InvalidProtocolBufferException(
+                "CodedInputStream encountered an embedded string or message " +
+                "which claimed to have negative size.");
+        }
+
+        internal static InvalidProtocolBufferException MalformedVarint()
+        {
+            return new InvalidProtocolBufferException(
+                "CodedInputStream encountered a malformed varint.");
+        }
+
+        /// <summary>
+        /// Creates an exception for an error condition of an invalid tag being encountered.
+        /// </summary>
+        internal static InvalidProtocolBufferException InvalidTag()
+        {
+            return new InvalidProtocolBufferException(
+                "Protocol message contained an invalid tag (zero).");
+        }
+
+        internal static InvalidProtocolBufferException InvalidBase64(Exception innerException)
+        {
+            return new InvalidProtocolBufferException("Invalid base64 data", innerException);
+        }
+
+        internal static InvalidProtocolBufferException InvalidEndTag()
+        {
+            return new InvalidProtocolBufferException(
+                "Protocol message end-group tag did not match expected tag.");
+        }
+
+        internal static InvalidProtocolBufferException RecursionLimitExceeded()
+        {
+            return new InvalidProtocolBufferException(
+                "Protocol message had too many levels of nesting.  May be malicious.  " +
+                "Use CodedInputStream.SetRecursionLimit() to increase the depth limit.");
+        }
+
+        internal static InvalidProtocolBufferException JsonRecursionLimitExceeded()
+        {
+            return new InvalidProtocolBufferException(
+                "Protocol message had too many levels of nesting.  May be malicious.  " +
+                "Use JsonParser.Settings to increase the depth limit.");
+        }
+
+        internal static InvalidProtocolBufferException SizeLimitExceeded()
+        {
+            return new InvalidProtocolBufferException(
+                "Protocol message was too large.  May be malicious.  " +
+                "Use CodedInputStream.SetSizeLimit() to increase the size limit.");
+        }
+
+        internal static InvalidProtocolBufferException InvalidMessageStreamTag()
+        {
+            return new InvalidProtocolBufferException(
+                "Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonFormatter.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonFormatter.cs
new file mode 100644
index 0000000..8377247
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -0,0 +1,912 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Text;
+using Google.Protobuf.Reflection;
+using Google.Protobuf.WellKnownTypes;
+using System.IO;
+using System.Linq;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Reflection-based converter from messages to JSON.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// Instances of this class are thread-safe, with no mutable state.
+    /// </para>
+    /// <para>
+    /// This is a simple start to get JSON formatting working. As it's reflection-based,
+    /// it's not as quick as baking calls into generated messages - but is a simpler implementation.
+    /// (This code is generally not heavily optimized.)
+    /// </para>
+    /// </remarks>
+    public sealed class JsonFormatter
+    {
+        internal const string AnyTypeUrlField = "@type";
+        internal const string AnyDiagnosticValueField = "@value";
+        internal const string AnyWellKnownTypeValueField = "value";
+        private const string TypeUrlPrefix = "type.googleapis.com";
+        private const string NameValueSeparator = ": ";
+        private const string PropertySeparator = ", ";
+
+        /// <summary>
+        /// Returns a formatter using the default settings.
+        /// </summary>
+        public static JsonFormatter Default { get; } = new JsonFormatter(Settings.Default);
+
+        // A JSON formatter which *only* exists 
+        private static readonly JsonFormatter diagnosticFormatter = new JsonFormatter(Settings.Default);
+
+        /// <summary>
+        /// The JSON representation of the first 160 characters of Unicode.
+        /// Empty strings are replaced by the static constructor.
+        /// </summary>
+        private static readonly string[] CommonRepresentations = {
+            // C0 (ASCII and derivatives) control characters
+            "\\u0000", "\\u0001", "\\u0002", "\\u0003",  // 0x00
+          "\\u0004", "\\u0005", "\\u0006", "\\u0007",
+          "\\b",     "\\t",     "\\n",     "\\u000b",
+          "\\f",     "\\r",     "\\u000e", "\\u000f",
+          "\\u0010", "\\u0011", "\\u0012", "\\u0013",  // 0x10
+          "\\u0014", "\\u0015", "\\u0016", "\\u0017",
+          "\\u0018", "\\u0019", "\\u001a", "\\u001b",
+          "\\u001c", "\\u001d", "\\u001e", "\\u001f",
+            // Escaping of " and \ are required by www.json.org string definition.
+            // Escaping of < and > are required for HTML security.
+            "", "", "\\\"", "", "",        "", "",        "",  // 0x20
+          "", "", "",     "", "",        "", "",        "",
+          "", "", "",     "", "",        "", "",        "",  // 0x30
+          "", "", "",     "", "\\u003c", "", "\\u003e", "",
+          "", "", "",     "", "",        "", "",        "",  // 0x40
+          "", "", "",     "", "",        "", "",        "",
+          "", "", "",     "", "",        "", "",        "",  // 0x50
+          "", "", "",     "", "\\\\",    "", "",        "",
+          "", "", "",     "", "",        "", "",        "",  // 0x60
+          "", "", "",     "", "",        "", "",        "",
+          "", "", "",     "", "",        "", "",        "",  // 0x70
+          "", "", "",     "", "",        "", "",        "\\u007f",
+            // C1 (ISO 8859 and Unicode) extended control characters
+            "\\u0080", "\\u0081", "\\u0082", "\\u0083",  // 0x80
+          "\\u0084", "\\u0085", "\\u0086", "\\u0087",
+          "\\u0088", "\\u0089", "\\u008a", "\\u008b",
+          "\\u008c", "\\u008d", "\\u008e", "\\u008f",
+          "\\u0090", "\\u0091", "\\u0092", "\\u0093",  // 0x90
+          "\\u0094", "\\u0095", "\\u0096", "\\u0097",
+          "\\u0098", "\\u0099", "\\u009a", "\\u009b",
+          "\\u009c", "\\u009d", "\\u009e", "\\u009f"
+        };
+
+        static JsonFormatter()
+        {
+            for (int i = 0; i < CommonRepresentations.Length; i++)
+            {
+                if (CommonRepresentations[i] == "")
+                {
+                    CommonRepresentations[i] = ((char) i).ToString();
+                }
+            }
+        }
+
+        private readonly Settings settings;
+
+        private bool DiagnosticOnly => ReferenceEquals(this, diagnosticFormatter);
+
+        /// <summary>
+        /// Creates a new formatted with the given settings.
+        /// </summary>
+        /// <param name="settings">The settings.</param>
+        public JsonFormatter(Settings settings)
+        {
+            this.settings = settings;
+        }
+
+        /// <summary>
+        /// Formats the specified message as JSON.
+        /// </summary>
+        /// <param name="message">The message to format.</param>
+        /// <returns>The formatted message.</returns>
+        public string Format(IMessage message)
+        {
+            var writer = new StringWriter();
+            Format(message, writer);
+            return writer.ToString();
+        }
+
+        /// <summary>
+        /// Formats the specified message as JSON.
+        /// </summary>
+        /// <param name="message">The message to format.</param>
+        /// <param name="writer">The TextWriter to write the formatted message to.</param>
+        /// <returns>The formatted message.</returns>
+        public void Format(IMessage message, TextWriter writer)
+        {
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(writer, nameof(writer));
+
+            if (message.Descriptor.IsWellKnownType)
+            {
+                WriteWellKnownTypeValue(writer, message.Descriptor, message);
+            }
+            else
+            {
+                WriteMessage(writer, message);
+            }
+        }
+
+        /// <summary>
+        /// Converts a message to JSON for diagnostic purposes with no extra context.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// This differs from calling <see cref="Format(IMessage)"/> on the default JSON
+        /// formatter in its handling of <see cref="Any"/>. As no type registry is available
+        /// in <see cref="object.ToString"/> calls, the normal way of resolving the type of
+        /// an <c>Any</c> message cannot be applied. Instead, a JSON property named <c>@value</c>
+        /// is included with the base64 data from the <see cref="Any.Value"/> property of the message.
+        /// </para>
+        /// <para>The value returned by this method is only designed to be used for diagnostic
+        /// purposes. It may not be parsable by <see cref="JsonParser"/>, and may not be parsable
+        /// by other Protocol Buffer implementations.</para>
+        /// </remarks>
+        /// <param name="message">The message to format for diagnostic purposes.</param>
+        /// <returns>The diagnostic-only JSON representation of the message</returns>
+        public static string ToDiagnosticString(IMessage message)
+        {
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            return diagnosticFormatter.Format(message);
+        }
+
+        private void WriteMessage(TextWriter writer, IMessage message)
+        {
+            if (message == null)
+            {
+                WriteNull(writer);
+                return;
+            }
+            if (DiagnosticOnly)
+            {
+                ICustomDiagnosticMessage customDiagnosticMessage = message as ICustomDiagnosticMessage;
+                if (customDiagnosticMessage != null)
+                {
+                    writer.Write(customDiagnosticMessage.ToDiagnosticString());
+                    return;
+                }
+            }
+            writer.Write("{ ");
+            bool writtenFields = WriteMessageFields(writer, message, false);
+            writer.Write(writtenFields ? " }" : "}");
+        }
+
+        private bool WriteMessageFields(TextWriter writer, IMessage message, bool assumeFirstFieldWritten)
+        {
+            var fields = message.Descriptor.Fields;
+            bool first = !assumeFirstFieldWritten;
+            // First non-oneof fields
+            foreach (var field in fields.InFieldNumberOrder())
+            {
+                var accessor = field.Accessor;
+                if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field)
+                {
+                    continue;
+                }
+                // Omit default values unless we're asked to format them, or they're oneofs (where the default
+                // value is still formatted regardless, because that's how we preserve the oneof case).
+                object value = accessor.GetValue(message);
+                if (field.ContainingOneof == null && !settings.FormatDefaultValues && IsDefaultValue(accessor, value))
+                {
+                    continue;
+                }
+
+                // Okay, all tests complete: let's write the field value...
+                if (!first)
+                {
+                    writer.Write(PropertySeparator);
+                }
+
+                WriteString(writer, accessor.Descriptor.JsonName);
+                writer.Write(NameValueSeparator);
+                WriteValue(writer, value);
+
+                first = false;
+            }
+            return !first;
+        }
+
+        /// <summary>
+        /// Camel-case converter with added strictness for field mask formatting.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
+        private static string ToCamelCaseForFieldMask(string input)
+        {
+            for (int i = 0; i < input.Length; i++)
+            {
+                char c = input[i];
+                if (c >= 'A' && c <= 'Z')
+                {
+                    throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
+                }
+                if (c == '_' && i < input.Length - 1)
+                {
+                    char next = input[i + 1];
+                    if (next < 'a' || next > 'z')
+                    {
+                        throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
+                    }
+                }
+            }
+            return ToCamelCase(input);
+        }
+
+        // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
+        // TODO: Use the new field in FieldDescriptor.
+        internal static string ToCamelCase(string input)
+        {
+            bool capitalizeNext = false;
+            bool wasCap = true;
+            bool isCap = false;
+            bool firstWord = true;
+            StringBuilder result = new StringBuilder(input.Length);
+
+            for (int i = 0; i < input.Length; i++, wasCap = isCap)
+            {
+                isCap = char.IsUpper(input[i]);
+                if (input[i] == '_')
+                {
+                    capitalizeNext = true;
+                    if (result.Length != 0)
+                    {
+                        firstWord = false;
+                    }
+                    continue;
+                }
+                else if (firstWord)
+                {
+                    // Consider when the current character B is capitalized,
+                    // first word ends when:
+                    // 1) following a lowercase:   "...aB..."
+                    // 2) followed by a lowercase: "...ABc..."
+                    if (result.Length != 0 && isCap &&
+                        (!wasCap || (i + 1 < input.Length && char.IsLower(input[i + 1]))))
+                    {
+                        firstWord = false;
+                    }
+                    else
+                    {
+                        result.Append(char.ToLowerInvariant(input[i]));
+                        continue;
+                    }
+                }
+                else if (capitalizeNext)
+                {
+                    capitalizeNext = false;
+                    if (char.IsLower(input[i]))
+                    {
+                        result.Append(char.ToUpperInvariant(input[i]));
+                        continue;
+                    }
+                }
+                result.Append(input[i]);
+            }
+            return result.ToString();
+        }
+        
+        private static void WriteNull(TextWriter writer)
+        {
+            writer.Write("null");
+        }
+
+        private static bool IsDefaultValue(IFieldAccessor accessor, object value)
+        {
+            if (accessor.Descriptor.IsMap)
+            {
+                IDictionary dictionary = (IDictionary) value;
+                return dictionary.Count == 0;
+            }
+            if (accessor.Descriptor.IsRepeated)
+            {
+                IList list = (IList) value;
+                return list.Count == 0;
+            }
+            switch (accessor.Descriptor.FieldType)
+            {
+                case FieldType.Bool:
+                    return (bool) value == false;
+                case FieldType.Bytes:
+                    return (ByteString) value == ByteString.Empty;
+                case FieldType.String:
+                    return (string) value == "";
+                case FieldType.Double:
+                    return (double) value == 0.0;
+                case FieldType.SInt32:
+                case FieldType.Int32:
+                case FieldType.SFixed32:
+                case FieldType.Enum:
+                    return (int) value == 0;
+                case FieldType.Fixed32:
+                case FieldType.UInt32:
+                    return (uint) value == 0;
+                case FieldType.Fixed64:
+                case FieldType.UInt64:
+                    return (ulong) value == 0;
+                case FieldType.SFixed64:
+                case FieldType.Int64:
+                case FieldType.SInt64:
+                    return (long) value == 0;
+                case FieldType.Float:
+                    return (float) value == 0f;
+                case FieldType.Message:
+                case FieldType.Group: // Never expect to get this, but...
+                    return value == null;
+                default:
+                    throw new ArgumentException("Invalid field type");
+            }
+        }
+        
+        private void WriteValue(TextWriter writer, object value)
+        {
+            if (value == null)
+            {
+                WriteNull(writer);
+            }
+            else if (value is bool)
+            {
+                writer.Write((bool)value ? "true" : "false");
+            }
+            else if (value is ByteString)
+            {
+                // Nothing in Base64 needs escaping
+                writer.Write('"');
+                writer.Write(((ByteString)value).ToBase64());
+                writer.Write('"');
+            }
+            else if (value is string)
+            {
+                WriteString(writer, (string)value);
+            }
+            else if (value is IDictionary)
+            {
+                WriteDictionary(writer, (IDictionary)value);
+            }
+            else if (value is IList)
+            {
+                WriteList(writer, (IList)value);
+            }
+            else if (value is int || value is uint)
+            {
+                IFormattable formattable = (IFormattable) value;
+                writer.Write(formattable.ToString("d", CultureInfo.InvariantCulture));
+            }
+            else if (value is long || value is ulong)
+            {
+                writer.Write('"');
+                IFormattable formattable = (IFormattable) value;
+                writer.Write(formattable.ToString("d", CultureInfo.InvariantCulture));
+                writer.Write('"');
+            }
+            else if (value is System.Enum)
+            {
+                string name = OriginalEnumValueHelper.GetOriginalName(value);
+                if (name != null)
+                {
+                    WriteString(writer, name);
+                }
+                else
+                {
+                    WriteValue(writer, (int)value);
+                }
+            }
+            else if (value is float || value is double)
+            {
+                string text = ((IFormattable) value).ToString("r", CultureInfo.InvariantCulture);
+                if (text == "NaN" || text == "Infinity" || text == "-Infinity")
+                {
+                    writer.Write('"');
+                    writer.Write(text);
+                    writer.Write('"');
+                }
+                else
+                {
+                    writer.Write(text);
+                }
+            }
+            else if (value is IMessage)
+            {
+                IMessage message = (IMessage) value;
+                if (message.Descriptor.IsWellKnownType)
+                {
+                    WriteWellKnownTypeValue(writer, message.Descriptor, value);
+                }
+                else
+                {
+                    WriteMessage(writer, (IMessage)value);
+                }
+            }
+            else
+            {
+                throw new ArgumentException("Unable to format value of type " + value.GetType());
+            }
+        }
+
+        /// <summary>
+        /// Central interception point for well-known type formatting. Any well-known types which
+        /// don't need special handling can fall back to WriteMessage. We avoid assuming that the
+        /// values are using the embedded well-known types, in order to allow for dynamic messages
+        /// in the future.
+        /// </summary>
+        private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value)
+        {
+            // Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*,
+            // this would do the right thing.
+            if (value == null)
+            {
+                WriteNull(writer);
+                return;
+            }
+            // For wrapper types, the value will either be the (possibly boxed) "native" value,
+            // or the message itself if we're formatting it at the top level (e.g. just calling ToString on the object itself).
+            // If it's the message form, we can extract the value first, which *will* be the (possibly boxed) native value,
+            // and then proceed, writing it as if we were definitely in a field. (We never need to wrap it in an extra string...
+            // WriteValue will do the right thing.)
+            if (descriptor.IsWrapperType)
+            {
+                if (value is IMessage)
+                {
+                    var message = (IMessage) value;
+                    value = message.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.GetValue(message);
+                }
+                WriteValue(writer, value);
+                return;
+            }
+            if (descriptor.FullName == Timestamp.Descriptor.FullName)
+            {
+                WriteTimestamp(writer, (IMessage)value);
+                return;
+            }
+            if (descriptor.FullName == Duration.Descriptor.FullName)
+            {
+                WriteDuration(writer, (IMessage)value);
+                return;
+            }
+            if (descriptor.FullName == FieldMask.Descriptor.FullName)
+            {
+                WriteFieldMask(writer, (IMessage)value);
+                return;
+            }
+            if (descriptor.FullName == Struct.Descriptor.FullName)
+            {
+                WriteStruct(writer, (IMessage)value);
+                return;
+            }
+            if (descriptor.FullName == ListValue.Descriptor.FullName)
+            {
+                var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor;
+                WriteList(writer, (IList)fieldAccessor.GetValue((IMessage)value));
+                return;
+            }
+            if (descriptor.FullName == Value.Descriptor.FullName)
+            {
+                WriteStructFieldValue(writer, (IMessage)value);
+                return;
+            }
+            if (descriptor.FullName == Any.Descriptor.FullName)
+            {
+                WriteAny(writer, (IMessage)value);
+                return;
+            }
+            WriteMessage(writer, (IMessage)value);
+        }
+
+        private void WriteTimestamp(TextWriter writer, IMessage value)
+        {
+            // TODO: In the common case where this *is* using the built-in Timestamp type, we could
+            // avoid all the reflection at this point, by casting to Timestamp. In the interests of
+            // avoiding subtle bugs, don't do that until we've implemented DynamicMessage so that we can prove
+            // it still works in that case.
+            int nanos = (int) value.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.GetValue(value);
+            long seconds = (long) value.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.GetValue(value);
+            writer.Write(Timestamp.ToJson(seconds, nanos, DiagnosticOnly));
+        }
+
+        private void WriteDuration(TextWriter writer, IMessage value)
+        {
+            // TODO: Same as for WriteTimestamp
+            int nanos = (int) value.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.GetValue(value);
+            long seconds = (long) value.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.GetValue(value);
+            writer.Write(Duration.ToJson(seconds, nanos, DiagnosticOnly));
+        }
+
+        private void WriteFieldMask(TextWriter writer, IMessage value)
+        {
+            var paths = (IList<string>) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
+            writer.Write(FieldMask.ToJson(paths, DiagnosticOnly));
+        }
+
+        private void WriteAny(TextWriter writer, IMessage value)
+        {
+            if (DiagnosticOnly)
+            {
+                WriteDiagnosticOnlyAny(writer, value);
+                return;
+            }
+
+            string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value);
+            ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value);
+            string typeName = Any.GetTypeName(typeUrl);
+            MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName);
+            if (descriptor == null)
+            {
+                throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'");
+            }
+            IMessage message = descriptor.Parser.ParseFrom(data);
+            writer.Write("{ ");
+            WriteString(writer, AnyTypeUrlField);
+            writer.Write(NameValueSeparator);
+            WriteString(writer, typeUrl);
+
+            if (descriptor.IsWellKnownType)
+            {
+                writer.Write(PropertySeparator);
+                WriteString(writer, AnyWellKnownTypeValueField);
+                writer.Write(NameValueSeparator);
+                WriteWellKnownTypeValue(writer, descriptor, message);
+            }
+            else
+            {
+                WriteMessageFields(writer, message, true);
+            }
+            writer.Write(" }");
+        }
+
+        private void WriteDiagnosticOnlyAny(TextWriter writer, IMessage value)
+        {
+            string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value);
+            ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value);
+            writer.Write("{ ");
+            WriteString(writer, AnyTypeUrlField);
+            writer.Write(NameValueSeparator);
+            WriteString(writer, typeUrl);
+            writer.Write(PropertySeparator);
+            WriteString(writer, AnyDiagnosticValueField);
+            writer.Write(NameValueSeparator);
+            writer.Write('"');
+            writer.Write(data.ToBase64());
+            writer.Write('"');
+            writer.Write(" }");
+        }        
+
+        private void WriteStruct(TextWriter writer, IMessage message)
+        {
+            writer.Write("{ ");
+            IDictionary fields = (IDictionary) message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message);
+            bool first = true;
+            foreach (DictionaryEntry entry in fields)
+            {
+                string key = (string) entry.Key;
+                IMessage value = (IMessage) entry.Value;
+                if (string.IsNullOrEmpty(key) || value == null)
+                {
+                    throw new InvalidOperationException("Struct fields cannot have an empty key or a null value.");
+                }
+
+                if (!first)
+                {
+                    writer.Write(PropertySeparator);
+                }
+                WriteString(writer, key);
+                writer.Write(NameValueSeparator);
+                WriteStructFieldValue(writer, value);
+                first = false;
+            }
+            writer.Write(first ? "}" : " }");
+        }
+
+        private void WriteStructFieldValue(TextWriter writer, IMessage message)
+        {
+            var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message);
+            if (specifiedField == null)
+            {
+                throw new InvalidOperationException("Value message must contain a value for the oneof.");
+            }
+
+            object value = specifiedField.Accessor.GetValue(message);
+            
+            switch (specifiedField.FieldNumber)
+            {
+                case Value.BoolValueFieldNumber:
+                case Value.StringValueFieldNumber:
+                case Value.NumberValueFieldNumber:
+                    WriteValue(writer, value);
+                    return;
+                case Value.StructValueFieldNumber:
+                case Value.ListValueFieldNumber:
+                    // Structs and ListValues are nested messages, and already well-known types.
+                    var nestedMessage = (IMessage) specifiedField.Accessor.GetValue(message);
+                    WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage);
+                    return;
+                case Value.NullValueFieldNumber:
+                    WriteNull(writer);
+                    return;
+                default:
+                    throw new InvalidOperationException("Unexpected case in struct field: " + specifiedField.FieldNumber);
+            }
+        }
+
+        internal void WriteList(TextWriter writer, IList list)
+        {
+            writer.Write("[ ");
+            bool first = true;
+            foreach (var value in list)
+            {
+                if (!first)
+                {
+                    writer.Write(PropertySeparator);
+                }
+                WriteValue(writer, value);
+                first = false;
+            }
+            writer.Write(first ? "]" : " ]");
+        }
+
+        internal void WriteDictionary(TextWriter writer, IDictionary dictionary)
+        {
+            writer.Write("{ ");
+            bool first = true;
+            // This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal.
+            foreach (DictionaryEntry pair in dictionary)
+            {
+                if (!first)
+                {
+                    writer.Write(PropertySeparator);
+                }
+                string keyText;
+                if (pair.Key is string)
+                {
+                    keyText = (string) pair.Key;
+                }
+                else if (pair.Key is bool)
+                {
+                    keyText = (bool) pair.Key ? "true" : "false";
+                }
+                else if (pair.Key is int || pair.Key is uint | pair.Key is long || pair.Key is ulong)
+                {
+                    keyText = ((IFormattable) pair.Key).ToString("d", CultureInfo.InvariantCulture);
+                }
+                else
+                {
+                    if (pair.Key == null)
+                    {
+                        throw new ArgumentException("Dictionary has entry with null key");
+                    }
+                    throw new ArgumentException("Unhandled dictionary key type: " + pair.Key.GetType());
+                }
+                WriteString(writer, keyText);
+                writer.Write(NameValueSeparator);
+                WriteValue(writer, pair.Value);
+                first = false;
+            }
+            writer.Write(first ? "}" : " }");
+        }
+
+        /// <summary>
+        /// Returns whether or not a singular value can be represented in JSON.
+        /// Currently only relevant for enums, where unknown values can't be represented.
+        /// For repeated/map fields, this always returns true.
+        /// </summary>
+        private bool CanWriteSingleValue(object value)
+        {
+            if (value is System.Enum)
+            {
+                return System.Enum.IsDefined(value.GetType(), value);
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Writes a string (including leading and trailing double quotes) to a builder, escaping as required.
+        /// </summary>
+        /// <remarks>
+        /// Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc.
+        /// </remarks>
+        internal static void WriteString(TextWriter writer, string text)
+        {
+            writer.Write('"');
+            for (int i = 0; i < text.Length; i++)
+            {
+                char c = text[i];
+                if (c < 0xa0)
+                {
+                    writer.Write(CommonRepresentations[c]);
+                    continue;
+                }
+                if (char.IsHighSurrogate(c))
+                {
+                    // Encountered first part of a surrogate pair.
+                    // Check that we have the whole pair, and encode both parts as hex.
+                    i++;
+                    if (i == text.Length || !char.IsLowSurrogate(text[i]))
+                    {
+                        throw new ArgumentException("String contains low surrogate not followed by high surrogate");
+                    }
+                    HexEncodeUtf16CodeUnit(writer, c);
+                    HexEncodeUtf16CodeUnit(writer, text[i]);
+                    continue;
+                }
+                else if (char.IsLowSurrogate(c))
+                {
+                    throw new ArgumentException("String contains high surrogate not preceded by low surrogate");
+                }
+                switch ((uint) c)
+                {
+                    // These are not required by json spec
+                    // but used to prevent security bugs in javascript.
+                    case 0xfeff:  // Zero width no-break space
+                    case 0xfff9:  // Interlinear annotation anchor
+                    case 0xfffa:  // Interlinear annotation separator
+                    case 0xfffb:  // Interlinear annotation terminator
+
+                    case 0x00ad:  // Soft-hyphen
+                    case 0x06dd:  // Arabic end of ayah
+                    case 0x070f:  // Syriac abbreviation mark
+                    case 0x17b4:  // Khmer vowel inherent Aq
+                    case 0x17b5:  // Khmer vowel inherent Aa
+                        HexEncodeUtf16CodeUnit(writer, c);
+                        break;
+
+                    default:
+                        if ((c >= 0x0600 && c <= 0x0603) ||  // Arabic signs
+                            (c >= 0x200b && c <= 0x200f) ||  // Zero width etc.
+                            (c >= 0x2028 && c <= 0x202e) ||  // Separators etc.
+                            (c >= 0x2060 && c <= 0x2064) ||  // Invisible etc.
+                            (c >= 0x206a && c <= 0x206f))
+                        {
+                            HexEncodeUtf16CodeUnit(writer, c);
+                        }
+                        else
+                        {
+                            // No handling of surrogates here - that's done earlier
+                            writer.Write(c);
+                        }
+                        break;
+                }
+            }
+            writer.Write('"');
+        }
+
+        private const string Hex = "0123456789abcdef";
+        private static void HexEncodeUtf16CodeUnit(TextWriter writer, char c)
+        {
+            writer.Write("\\u");
+            writer.Write(Hex[(c >> 12) & 0xf]);
+            writer.Write(Hex[(c >> 8) & 0xf]);
+            writer.Write(Hex[(c >> 4) & 0xf]);
+            writer.Write(Hex[(c >> 0) & 0xf]);
+        }
+
+        /// <summary>
+        /// Settings controlling JSON formatting.
+        /// </summary>
+        public sealed class Settings
+        {
+            /// <summary>
+            /// Default settings, as used by <see cref="JsonFormatter.Default"/>
+            /// </summary>
+            public static Settings Default { get; }
+
+            // Workaround for the Mono compiler complaining about XML comments not being on
+            // valid language elements.
+            static Settings()
+            {
+                Default = new Settings(false);
+            }
+
+            /// <summary>
+            /// Whether fields whose values are the default for the field type (e.g. 0 for integers)
+            /// should be formatted (true) or omitted (false).
+            /// </summary>
+            public bool FormatDefaultValues { get; }
+
+            /// <summary>
+            /// The type registry used to format <see cref="Any"/> messages.
+            /// </summary>
+            public TypeRegistry TypeRegistry { get; }
+
+            // TODO: Work out how we're going to scale this to multiple settings. "WithXyz" methods?
+
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified formatting of default values
+            /// and an empty type registry.
+            /// </summary>
+            /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param>
+            public Settings(bool formatDefaultValues) : this(formatDefaultValues, TypeRegistry.Empty)
+            {
+            }
+
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified formatting of default values
+            /// and type registry.
+            /// </summary>
+            /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param>
+            /// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages.</param>
+            public Settings(bool formatDefaultValues, TypeRegistry typeRegistry)
+            {
+                FormatDefaultValues = formatDefaultValues;
+                TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry));
+            }
+        }
+
+        // Effectively a cache of mapping from enum values to the original name as specified in the proto file,
+        // fetched by reflection.
+        // The need for this is unfortunate, as is its unbounded size, but realistically it shouldn't cause issues.
+        private static class OriginalEnumValueHelper
+        {
+            // TODO: In the future we might want to use ConcurrentDictionary, at the point where all
+            // the platforms we target have it.
+            private static readonly Dictionary<System.Type, Dictionary<object, string>> dictionaries
+                = new Dictionary<System.Type, Dictionary<object, string>>();
+            
+            internal static string GetOriginalName(object value)
+            {
+                var enumType = value.GetType();
+                Dictionary<object, string> nameMapping;
+                lock (dictionaries)
+                {
+                    if (!dictionaries.TryGetValue(enumType, out nameMapping))
+                    {
+                        nameMapping = GetNameMapping(enumType);
+                        dictionaries[enumType] = nameMapping;
+                    }
+                }
+
+                string originalName;
+                // If this returns false, originalName will be null, which is what we want.
+                nameMapping.TryGetValue(value, out originalName);
+                return originalName;
+            }
+
+            private static Dictionary<object, string> GetNameMapping(System.Type enumType) =>
+                enumType.GetTypeInfo().DeclaredFields
+                    .Where(f => f.IsStatic)
+                    .ToDictionary(f => f.GetValue(null),
+                                  f => f.GetCustomAttributes<OriginalNameAttribute>()
+                                        .FirstOrDefault()
+                                        // If the attribute hasn't been applied, fall back to the name of the field.
+                                        ?.Name ?? f.Name);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonParser.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonParser.cs
new file mode 100644
index 0000000..d738ebb
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonParser.cs
@@ -0,0 +1,1018 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+using Google.Protobuf.WellKnownTypes;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Reflection-based converter from JSON to messages.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// Instances of this class are thread-safe, with no mutable state.
+    /// </para>
+    /// <para>
+    /// This is a simple start to get JSON parsing working. As it's reflection-based,
+    /// it's not as quick as baking calls into generated messages - but is a simpler implementation.
+    /// (This code is generally not heavily optimized.)
+    /// </para>
+    /// </remarks>
+    public sealed class JsonParser
+    {
+        // Note: using 0-9 instead of \d to ensure no non-ASCII digits.
+        // This regex isn't a complete validator, but will remove *most* invalid input. We rely on parsing to do the rest.
+        private static readonly Regex TimestampRegex = new Regex(@"^(?<datetime>[0-9]{4}-[01][0-9]-[0-3][0-9]T[012][0-9]:[0-5][0-9]:[0-5][0-9])(?<subseconds>\.[0-9]{1,9})?(?<offset>(Z|[+-][0-1][0-9]:[0-5][0-9]))$", FrameworkPortability.CompiledRegexWhereAvailable);
+        private static readonly Regex DurationRegex = new Regex(@"^(?<sign>-)?(?<int>[0-9]{1,12})(?<subseconds>\.[0-9]{1,9})?s$", FrameworkPortability.CompiledRegexWhereAvailable);
+        private static readonly int[] SubsecondScalingFactors = { 0, 100000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
+        private static readonly char[] FieldMaskPathSeparators = new[] { ',' };
+
+        private static readonly JsonParser defaultInstance = new JsonParser(Settings.Default);
+
+        // TODO: Consider introducing a class containing parse state of the parser, tokenizer and depth. That would simplify these handlers
+        // and the signatures of various methods.
+        private static readonly Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
+            WellKnownTypeHandlers = new Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
+        {
+            { Timestamp.Descriptor.FullName, (parser, message, tokenizer) => MergeTimestamp(message, tokenizer.Next()) },
+            { Duration.Descriptor.FullName, (parser, message, tokenizer) => MergeDuration(message, tokenizer.Next()) },
+            { Value.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeStructValue(message, tokenizer) },
+            { ListValue.Descriptor.FullName, (parser, message, tokenizer) =>
+                parser.MergeRepeatedField(message, message.Descriptor.Fields[ListValue.ValuesFieldNumber], tokenizer) },
+            { Struct.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeStruct(message, tokenizer) },
+            { Any.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeAny(message, tokenizer) },
+            { FieldMask.Descriptor.FullName, (parser, message, tokenizer) => MergeFieldMask(message, tokenizer.Next()) },
+            { Int32Value.Descriptor.FullName, MergeWrapperField },
+            { Int64Value.Descriptor.FullName, MergeWrapperField },
+            { UInt32Value.Descriptor.FullName, MergeWrapperField },
+            { UInt64Value.Descriptor.FullName, MergeWrapperField },
+            { FloatValue.Descriptor.FullName, MergeWrapperField },
+            { DoubleValue.Descriptor.FullName, MergeWrapperField },
+            { BytesValue.Descriptor.FullName, MergeWrapperField },
+            { StringValue.Descriptor.FullName, MergeWrapperField }
+        };
+
+        // Convenience method to avoid having to repeat the same code multiple times in the above
+        // dictionary initialization.
+        private static void MergeWrapperField(JsonParser parser, IMessage message, JsonTokenizer tokenizer)
+        {
+            parser.MergeField(message, message.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber], tokenizer);
+        }
+
+        /// <summary>
+        /// Returns a formatter using the default settings.
+        /// </summary>
+        public static JsonParser Default { get { return defaultInstance; } }
+
+        private readonly Settings settings;
+
+        /// <summary>
+        /// Creates a new formatted with the given settings.
+        /// </summary>
+        /// <param name="settings">The settings.</param>
+        public JsonParser(Settings settings)
+        {
+            this.settings = settings;
+        }
+
+        /// <summary>
+        /// Parses <paramref name="json"/> and merges the information into the given message.
+        /// </summary>
+        /// <param name="message">The message to merge the JSON information into.</param>
+        /// <param name="json">The JSON to parse.</param>
+        internal void Merge(IMessage message, string json)
+        {
+            Merge(message, new StringReader(json));
+        }
+
+        /// <summary>
+        /// Parses JSON read from <paramref name="jsonReader"/> and merges the information into the given message.
+        /// </summary>
+        /// <param name="message">The message to merge the JSON information into.</param>
+        /// <param name="jsonReader">Reader providing the JSON to parse.</param>
+        internal void Merge(IMessage message, TextReader jsonReader)
+        {
+            var tokenizer = JsonTokenizer.FromTextReader(jsonReader);
+            Merge(message, tokenizer);
+            var lastToken = tokenizer.Next();
+            if (lastToken != JsonToken.EndDocument)
+            {
+                throw new InvalidProtocolBufferException("Expected end of JSON after object");
+            }
+        }
+
+        /// <summary>
+        /// Merges the given message using data from the given tokenizer. In most cases, the next
+        /// token should be a "start object" token, but wrapper types and nullity can invalidate
+        /// that assumption. This is implemented as an LL(1) recursive descent parser over the stream
+        /// of tokens provided by the tokenizer. This token stream is assumed to be valid JSON, with the
+        /// tokenizer performing that validation - but not every token stream is valid "protobuf JSON".
+        /// </summary>
+        private void Merge(IMessage message, JsonTokenizer tokenizer)
+        {
+            if (tokenizer.ObjectDepth > settings.RecursionLimit)
+            {
+                throw InvalidProtocolBufferException.JsonRecursionLimitExceeded();
+            }
+            if (message.Descriptor.IsWellKnownType)
+            {
+                Action<JsonParser, IMessage, JsonTokenizer> handler;
+                if (WellKnownTypeHandlers.TryGetValue(message.Descriptor.FullName, out handler))
+                {
+                    handler(this, message, tokenizer);
+                    return;
+                }
+                // Well-known types with no special handling continue in the normal way.
+            }
+            var token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StartObject)
+            {
+                throw new InvalidProtocolBufferException("Expected an object");
+            }
+            var descriptor = message.Descriptor;
+            var jsonFieldMap = descriptor.Fields.ByJsonName();
+            // All the oneof fields we've already accounted for - we can only see each of them once.
+            // The set is created lazily to avoid the overhead of creating a set for every message
+            // we parsed, when oneofs are relatively rare.
+            HashSet<OneofDescriptor> seenOneofs = null;
+            while (true)
+            {
+                token = tokenizer.Next();
+                if (token.Type == JsonToken.TokenType.EndObject)
+                {
+                    return;
+                }
+                if (token.Type != JsonToken.TokenType.Name)
+                {
+                    throw new InvalidOperationException("Unexpected token type " + token.Type);
+                }
+                string name = token.StringValue;
+                FieldDescriptor field;
+                if (jsonFieldMap.TryGetValue(name, out field))
+                {
+                    if (field.ContainingOneof != null)
+                    {
+                        if (seenOneofs == null)
+                        {
+                            seenOneofs = new HashSet<OneofDescriptor>();
+                        }
+                        if (!seenOneofs.Add(field.ContainingOneof))
+                        {
+                            throw new InvalidProtocolBufferException($"Multiple values specified for oneof {field.ContainingOneof.Name}");
+                        }
+                    }
+                    MergeField(message, field, tokenizer);
+                }
+                else
+                {
+                    // TODO: Is this what we want to do? If not, we'll need to skip the value,
+                    // which may be an object or array. (We might want to put code in the tokenizer
+                    // to do that.)
+                    throw new InvalidProtocolBufferException("Unknown field: " + name);
+                }
+            }
+        }
+
+        private void MergeField(IMessage message, FieldDescriptor field, JsonTokenizer tokenizer)
+        {
+            var token = tokenizer.Next();
+            if (token.Type == JsonToken.TokenType.Null)
+            {
+                // Clear the field if we see a null token, unless it's for a singular field of type
+                // google.protobuf.Value.
+                // Note: different from Java API, which just ignores it.
+                // TODO: Bring it more in line? Discuss...
+                if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field))
+                {
+                    field.Accessor.Clear(message);
+                    return;
+                }
+            }
+            tokenizer.PushBack(token);
+
+            if (field.IsMap)
+            {
+                MergeMapField(message, field, tokenizer);
+            }
+            else if (field.IsRepeated)
+            {
+                MergeRepeatedField(message, field, tokenizer);
+            }
+            else
+            {
+                var value = ParseSingleValue(field, tokenizer);
+                field.Accessor.SetValue(message, value);
+            }
+        }
+
+        private void MergeRepeatedField(IMessage message, FieldDescriptor field, JsonTokenizer tokenizer)
+        {
+            var token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StartArray)
+            {
+                throw new InvalidProtocolBufferException("Repeated field value was not an array. Token type: " + token.Type);
+            }
+
+            IList list = (IList) field.Accessor.GetValue(message);
+            while (true)
+            {
+                token = tokenizer.Next();
+                if (token.Type == JsonToken.TokenType.EndArray)
+                {
+                    return;
+                }
+                tokenizer.PushBack(token);
+                if (token.Type == JsonToken.TokenType.Null)
+                {
+                    throw new InvalidProtocolBufferException("Repeated field elements cannot be null");
+                }
+                list.Add(ParseSingleValue(field, tokenizer));
+            }
+        }
+
+        private void MergeMapField(IMessage message, FieldDescriptor field, JsonTokenizer tokenizer)
+        {
+            // Map fields are always objects, even if the values are well-known types: ParseSingleValue handles those.
+            var token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StartObject)
+            {
+                throw new InvalidProtocolBufferException("Expected an object to populate a map");
+            }
+
+            var type = field.MessageType;
+            var keyField = type.FindFieldByNumber(1);
+            var valueField = type.FindFieldByNumber(2);
+            if (keyField == null || valueField == null)
+            {
+                throw new InvalidProtocolBufferException("Invalid map field: " + field.FullName);
+            }
+            IDictionary dictionary = (IDictionary) field.Accessor.GetValue(message);
+
+            while (true)
+            {
+                token = tokenizer.Next();
+                if (token.Type == JsonToken.TokenType.EndObject)
+                {
+                    return;
+                }
+                object key = ParseMapKey(keyField, token.StringValue);
+                object value = ParseSingleValue(valueField, tokenizer);
+                if (value == null)
+                {
+                    throw new InvalidProtocolBufferException("Map values must not be null");
+                }
+                dictionary[key] = value;
+            }
+        }
+
+        private static bool IsGoogleProtobufValueField(FieldDescriptor field)
+        {
+            return field.FieldType == FieldType.Message &&
+                field.MessageType.FullName == Value.Descriptor.FullName;
+        }
+
+        private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer)
+        {
+            var token = tokenizer.Next();
+            if (token.Type == JsonToken.TokenType.Null)
+            {
+                // TODO: In order to support dynamic messages, we should really build this up
+                // dynamically.
+                if (IsGoogleProtobufValueField(field))
+                {
+                    return Value.ForNull();
+                }
+                return null;
+            }
+
+            var fieldType = field.FieldType;
+            if (fieldType == FieldType.Message)
+            {
+                // Parse wrapper types as their constituent types.
+                // TODO: What does this mean for null?
+                if (field.MessageType.IsWrapperType)
+                {
+                    field = field.MessageType.Fields[WrappersReflection.WrapperValueFieldNumber];
+                    fieldType = field.FieldType;
+                }
+                else
+                {
+                    // TODO: Merge the current value in message? (Public API currently doesn't make this relevant as we don't expose merging.)
+                    tokenizer.PushBack(token);
+                    IMessage subMessage = NewMessageForField(field);
+                    Merge(subMessage, tokenizer);
+                    return subMessage;
+                }
+            }
+
+            switch (token.Type)
+            {
+                case JsonToken.TokenType.True:
+                case JsonToken.TokenType.False:
+                    if (fieldType == FieldType.Bool)
+                    {
+                        return token.Type == JsonToken.TokenType.True;
+                    }
+                    // Fall through to "we don't support this type for this case"; could duplicate the behaviour of the default
+                    // case instead, but this way we'd only need to change one place.
+                    goto default;
+                case JsonToken.TokenType.StringValue:
+                    return ParseSingleStringValue(field, token.StringValue);
+                // Note: not passing the number value itself here, as we may end up storing the string value in the token too.
+                case JsonToken.TokenType.Number:
+                    return ParseSingleNumberValue(field, token);
+                case JsonToken.TokenType.Null:
+                    throw new NotImplementedException("Haven't worked out what to do for null yet");
+                default:
+                    throw new InvalidProtocolBufferException("Unsupported JSON token type " + token.Type + " for field type " + fieldType);
+            }
+        }
+
+        /// <summary>
+        /// Parses <paramref name="json"/> into a new message.
+        /// </summary>
+        /// <typeparam name="T">The type of message to create.</typeparam>
+        /// <param name="json">The JSON to parse.</param>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public T Parse<T>(string json) where T : IMessage, new()
+        {
+            ProtoPreconditions.CheckNotNull(json, nameof(json));
+            return Parse<T>(new StringReader(json));
+        }
+
+        /// <summary>
+        /// Parses JSON read from <paramref name="jsonReader"/> into a new message.
+        /// </summary>
+        /// <typeparam name="T">The type of message to create.</typeparam>
+        /// <param name="jsonReader">Reader providing the JSON to parse.</param>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public T Parse<T>(TextReader jsonReader) where T : IMessage, new()
+        {
+            ProtoPreconditions.CheckNotNull(jsonReader, nameof(jsonReader));
+            T message = new T();
+            Merge(message, jsonReader);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses <paramref name="json"/> into a new message.
+        /// </summary>
+        /// <param name="json">The JSON to parse.</param>
+        /// <param name="descriptor">Descriptor of message type to parse.</param>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public IMessage Parse(string json, MessageDescriptor descriptor)
+        {
+            ProtoPreconditions.CheckNotNull(json, nameof(json));
+            ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor));
+            return Parse(new StringReader(json), descriptor);
+        }
+
+        /// <summary>
+        /// Parses JSON read from <paramref name="jsonReader"/> into a new message.
+        /// </summary>
+        /// <param name="jsonReader">Reader providing the JSON to parse.</param>
+        /// <param name="descriptor">Descriptor of message type to parse.</param>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public IMessage Parse(TextReader jsonReader, MessageDescriptor descriptor)
+        {
+            ProtoPreconditions.CheckNotNull(jsonReader, nameof(jsonReader));
+            ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor));
+            IMessage message = descriptor.Parser.CreateTemplate();
+            Merge(message, jsonReader);
+            return message;
+        }
+
+        private void MergeStructValue(IMessage message, JsonTokenizer tokenizer)
+        {
+            var firstToken = tokenizer.Next();
+            var fields = message.Descriptor.Fields;
+            switch (firstToken.Type)
+            {
+                case JsonToken.TokenType.Null:
+                    fields[Value.NullValueFieldNumber].Accessor.SetValue(message, 0);
+                    return;
+                case JsonToken.TokenType.StringValue:
+                    fields[Value.StringValueFieldNumber].Accessor.SetValue(message, firstToken.StringValue);
+                    return;
+                case JsonToken.TokenType.Number:
+                    fields[Value.NumberValueFieldNumber].Accessor.SetValue(message, firstToken.NumberValue);
+                    return;
+                case JsonToken.TokenType.False:
+                case JsonToken.TokenType.True:
+                    fields[Value.BoolValueFieldNumber].Accessor.SetValue(message, firstToken.Type == JsonToken.TokenType.True);
+                    return;
+                case JsonToken.TokenType.StartObject:
+                    {
+                        var field = fields[Value.StructValueFieldNumber];
+                        var structMessage = NewMessageForField(field);
+                        tokenizer.PushBack(firstToken);
+                        Merge(structMessage, tokenizer);
+                        field.Accessor.SetValue(message, structMessage);
+                        return;
+                    }
+                case JsonToken.TokenType.StartArray:
+                    {
+                        var field = fields[Value.ListValueFieldNumber];
+                        var list = NewMessageForField(field);
+                        tokenizer.PushBack(firstToken);
+                        Merge(list, tokenizer);
+                        field.Accessor.SetValue(message, list);
+                        return;
+                    }
+                default:
+                    throw new InvalidOperationException("Unexpected token type: " + firstToken.Type);
+            }
+        }
+
+        private void MergeStruct(IMessage message, JsonTokenizer tokenizer)
+        {
+            var token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StartObject)
+            {
+                throw new InvalidProtocolBufferException("Expected object value for Struct");
+            }
+            tokenizer.PushBack(token);
+
+            var field = message.Descriptor.Fields[Struct.FieldsFieldNumber];
+            MergeMapField(message, field, tokenizer);
+        }
+
+        private void MergeAny(IMessage message, JsonTokenizer tokenizer)
+        {
+            // Record the token stream until we see the @type property. At that point, we can take the value, consult
+            // the type registry for the relevant message, and replay the stream, omitting the @type property.
+            var tokens = new List<JsonToken>();
+
+            var token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StartObject)
+            {
+                throw new InvalidProtocolBufferException("Expected object value for Any");
+            }
+            int typeUrlObjectDepth = tokenizer.ObjectDepth;
+
+            // The check for the property depth protects us from nested Any values which occur before the type URL
+            // for *this* Any.
+            while (token.Type != JsonToken.TokenType.Name ||
+                token.StringValue != JsonFormatter.AnyTypeUrlField ||
+                tokenizer.ObjectDepth != typeUrlObjectDepth)
+            {
+                tokens.Add(token);
+                token = tokenizer.Next();
+
+                if (tokenizer.ObjectDepth < typeUrlObjectDepth)
+                {
+                    throw new InvalidProtocolBufferException("Any message with no @type");
+                }
+            }
+
+            // Don't add the @type property or its value to the recorded token list
+            token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.StringValue)
+            {
+                throw new InvalidProtocolBufferException("Expected string value for Any.@type");
+            }
+            string typeUrl = token.StringValue;
+            string typeName = Any.GetTypeName(typeUrl);
+
+            MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName);
+            if (descriptor == null)
+            {
+                throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'");
+            }
+
+            // Now replay the token stream we've already read and anything that remains of the object, just parsing it
+            // as normal. Our original tokenizer should end up at the end of the object.
+            var replay = JsonTokenizer.FromReplayedTokens(tokens, tokenizer);
+            var body = descriptor.Parser.CreateTemplate();
+            if (descriptor.IsWellKnownType)
+            {
+                MergeWellKnownTypeAnyBody(body, replay);
+            }
+            else
+            {
+                Merge(body, replay);
+            }
+            var data = body.ToByteString();
+
+            // Now that we have the message data, we can pack it into an Any (the message received as a parameter).
+            message.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.SetValue(message, typeUrl);
+            message.Descriptor.Fields[Any.ValueFieldNumber].Accessor.SetValue(message, data);
+        }
+
+        // Well-known types end up in a property called "value" in the JSON. As there's no longer a @type property
+        // in the given JSON token stream, we should *only* have tokens of start-object, name("value"), the value
+        // itself, and then end-object.
+        private void MergeWellKnownTypeAnyBody(IMessage body, JsonTokenizer tokenizer)
+        {
+            var token = tokenizer.Next(); // Definitely start-object; checked in previous method
+            token = tokenizer.Next();
+            // TODO: What about an absent Int32Value, for example?
+            if (token.Type != JsonToken.TokenType.Name || token.StringValue != JsonFormatter.AnyWellKnownTypeValueField)
+            {
+                throw new InvalidProtocolBufferException($"Expected '{JsonFormatter.AnyWellKnownTypeValueField}' property for well-known type Any body");
+            }
+            Merge(body, tokenizer);
+            token = tokenizer.Next();
+            if (token.Type != JsonToken.TokenType.EndObject)
+            {
+                throw new InvalidProtocolBufferException($"Expected end-object token after @type/value for well-known type");
+            }
+        }
+
+        #region Utility methods which don't depend on the state (or settings) of the parser.
+        private static object ParseMapKey(FieldDescriptor field, string keyText)
+        {
+            switch (field.FieldType)
+            {
+                case FieldType.Bool:
+                    if (keyText == "true")
+                    {
+                        return true;
+                    }
+                    if (keyText == "false")
+                    {
+                        return false;
+                    }
+                    throw new InvalidProtocolBufferException("Invalid string for bool map key: " + keyText);
+                case FieldType.String:
+                    return keyText;
+                case FieldType.Int32:
+                case FieldType.SInt32:
+                case FieldType.SFixed32:
+                    return ParseNumericString(keyText, int.Parse);
+                case FieldType.UInt32:
+                case FieldType.Fixed32:
+                    return ParseNumericString(keyText, uint.Parse);
+                case FieldType.Int64:
+                case FieldType.SInt64:
+                case FieldType.SFixed64:
+                    return ParseNumericString(keyText, long.Parse);
+                case FieldType.UInt64:
+                case FieldType.Fixed64:
+                    return ParseNumericString(keyText, ulong.Parse);
+                default:
+                    throw new InvalidProtocolBufferException("Invalid field type for map: " + field.FieldType);
+            }
+        }
+
+        private static object ParseSingleNumberValue(FieldDescriptor field, JsonToken token)
+        {
+            double value = token.NumberValue;
+            checked
+            {
+                try
+                {
+                    switch (field.FieldType)
+                    {
+                        case FieldType.Int32:
+                        case FieldType.SInt32:
+                        case FieldType.SFixed32:
+                            CheckInteger(value);
+                            return (int) value;
+                        case FieldType.UInt32:
+                        case FieldType.Fixed32:
+                            CheckInteger(value);
+                            return (uint) value;
+                        case FieldType.Int64:
+                        case FieldType.SInt64:
+                        case FieldType.SFixed64:
+                            CheckInteger(value);
+                            return (long) value;
+                        case FieldType.UInt64:
+                        case FieldType.Fixed64:
+                            CheckInteger(value);
+                            return (ulong) value;
+                        case FieldType.Double:
+                            return value;
+                        case FieldType.Float:
+                            if (double.IsNaN(value))
+                            {
+                                return float.NaN;
+                            }
+                            if (value > float.MaxValue || value < float.MinValue)
+                            {
+                                if (double.IsPositiveInfinity(value))
+                                {
+                                    return float.PositiveInfinity;
+                                }
+                                if (double.IsNegativeInfinity(value))
+                                {
+                                    return float.NegativeInfinity;
+                                }
+                                throw new InvalidProtocolBufferException($"Value out of range: {value}");
+                            }
+                            return (float) value;
+                        case FieldType.Enum:
+                            CheckInteger(value);
+                            // Just return it as an int, and let the CLR convert it.
+                            // Note that we deliberately don't check that it's a known value.
+                            return (int) value;
+                        default:
+                            throw new InvalidProtocolBufferException($"Unsupported conversion from JSON number for field type {field.FieldType}");
+                    }
+                }
+                catch (OverflowException)
+                {
+                    throw new InvalidProtocolBufferException($"Value out of range: {value}");
+                }
+            }
+        }
+
+        private static void CheckInteger(double value)
+        {
+            if (double.IsInfinity(value) || double.IsNaN(value))
+            {
+                throw new InvalidProtocolBufferException($"Value not an integer: {value}");
+            }
+            if (value != Math.Floor(value))
+            {
+                throw new InvalidProtocolBufferException($"Value not an integer: {value}");
+            }            
+        }
+
+        private static object ParseSingleStringValue(FieldDescriptor field, string text)
+        {
+            switch (field.FieldType)
+            {
+                case FieldType.String:
+                    return text;
+                case FieldType.Bytes:
+                    try
+                    {
+                        return ByteString.FromBase64(text);
+                    }
+                    catch (FormatException e)
+                    {
+                        throw InvalidProtocolBufferException.InvalidBase64(e);
+                    }
+                case FieldType.Int32:
+                case FieldType.SInt32:
+                case FieldType.SFixed32:
+                    return ParseNumericString(text, int.Parse);
+                case FieldType.UInt32:
+                case FieldType.Fixed32:
+                    return ParseNumericString(text, uint.Parse);
+                case FieldType.Int64:
+                case FieldType.SInt64:
+                case FieldType.SFixed64:
+                    return ParseNumericString(text, long.Parse);
+                case FieldType.UInt64:
+                case FieldType.Fixed64:
+                    return ParseNumericString(text, ulong.Parse);
+                case FieldType.Double:
+                    double d = ParseNumericString(text, double.Parse);
+                    ValidateInfinityAndNan(text, double.IsPositiveInfinity(d), double.IsNegativeInfinity(d), double.IsNaN(d));
+                    return d;
+                case FieldType.Float:
+                    float f = ParseNumericString(text, float.Parse);
+                    ValidateInfinityAndNan(text, float.IsPositiveInfinity(f), float.IsNegativeInfinity(f), float.IsNaN(f));
+                    return f;
+                case FieldType.Enum:
+                    var enumValue = field.EnumType.FindValueByName(text);
+                    if (enumValue == null)
+                    {
+                        throw new InvalidProtocolBufferException($"Invalid enum value: {text} for enum type: {field.EnumType.FullName}");
+                    }
+                    // Just return it as an int, and let the CLR convert it.
+                    return enumValue.Number;
+                default:
+                    throw new InvalidProtocolBufferException($"Unsupported conversion from JSON string for field type {field.FieldType}");
+            }
+        }
+
+        /// <summary>
+        /// Creates a new instance of the message type for the given field.
+        /// </summary>
+        private static IMessage NewMessageForField(FieldDescriptor field)
+        {
+            return field.MessageType.Parser.CreateTemplate();
+        }
+
+        private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser)
+        {
+            // Can't prohibit this with NumberStyles.
+            if (text.StartsWith("+"))
+            {
+                throw new InvalidProtocolBufferException($"Invalid numeric value: {text}");
+            }
+            if (text.StartsWith("0") && text.Length > 1)
+            {
+                if (text[1] >= '0' && text[1] <= '9')
+                {
+                    throw new InvalidProtocolBufferException($"Invalid numeric value: {text}");
+                }
+            }
+            else if (text.StartsWith("-0") && text.Length > 2)
+            {
+                if (text[2] >= '0' && text[2] <= '9')
+                {
+                    throw new InvalidProtocolBufferException($"Invalid numeric value: {text}");
+                }
+            }
+            try
+            {
+                return parser(text, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture);
+            }
+            catch (FormatException)
+            {
+                throw new InvalidProtocolBufferException($"Invalid numeric value for type: {text}");
+            }
+            catch (OverflowException)
+            {
+                throw new InvalidProtocolBufferException($"Value out of range: {text}");
+            }
+        }
+
+        /// <summary>
+        /// Checks that any infinite/NaN values originated from the correct text.
+        /// This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the
+        /// way that Mono parses out-of-range values as infinity.
+        /// </summary>
+        private static void ValidateInfinityAndNan(string text, bool isPositiveInfinity, bool isNegativeInfinity, bool isNaN)
+        {
+            if ((isPositiveInfinity && text != "Infinity") ||
+                (isNegativeInfinity && text != "-Infinity") ||
+                (isNaN && text != "NaN"))
+            {
+                throw new InvalidProtocolBufferException($"Invalid numeric value: {text}");
+            }
+        }
+
+        private static void MergeTimestamp(IMessage message, JsonToken token)
+        {
+            if (token.Type != JsonToken.TokenType.StringValue)
+            {
+                throw new InvalidProtocolBufferException("Expected string value for Timestamp");
+            }
+            var match = TimestampRegex.Match(token.StringValue);
+            if (!match.Success)
+            {
+                throw new InvalidProtocolBufferException($"Invalid Timestamp value: {token.StringValue}");
+            }
+            var dateTime = match.Groups["datetime"].Value;
+            var subseconds = match.Groups["subseconds"].Value;
+            var offset = match.Groups["offset"].Value;
+
+            try
+            {
+                DateTime parsed = DateTime.ParseExact(
+                    dateTime,
+                    "yyyy-MM-dd'T'HH:mm:ss",
+                    CultureInfo.InvariantCulture,
+                    DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+                // TODO: It would be nice not to have to create all these objects... easy to optimize later though.
+                Timestamp timestamp = Timestamp.FromDateTime(parsed);
+                int nanosToAdd = 0;
+                if (subseconds != "")
+                {
+                    // This should always work, as we've got 1-9 digits.
+                    int parsedFraction = int.Parse(subseconds.Substring(1), CultureInfo.InvariantCulture);
+                    nanosToAdd = parsedFraction * SubsecondScalingFactors[subseconds.Length];
+                }
+                int secondsToAdd = 0;
+                if (offset != "Z")
+                {
+                    // This is the amount we need to *subtract* from the local time to get to UTC - hence - => +1 and vice versa.
+                    int sign = offset[0] == '-' ? 1 : -1;
+                    int hours = int.Parse(offset.Substring(1, 2), CultureInfo.InvariantCulture);
+                    int minutes = int.Parse(offset.Substring(4, 2));
+                    int totalMinutes = hours * 60 + minutes;
+                    if (totalMinutes > 18 * 60)
+                    {
+                        throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
+                    }
+                    if (totalMinutes == 0 && sign == 1)
+                    {
+                        // This is an offset of -00:00, which means "unknown local offset". It makes no sense for a timestamp.
+                        throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
+                    }
+                    // We need to *subtract* the offset from local time to get UTC.
+                    secondsToAdd = sign * totalMinutes * 60;
+                }
+                // Ensure we've got the right signs. Currently unnecessary, but easy to do.
+                if (secondsToAdd < 0 && nanosToAdd > 0)
+                {
+                    secondsToAdd++;
+                    nanosToAdd = nanosToAdd - Duration.NanosecondsPerSecond;
+                }
+                if (secondsToAdd != 0 || nanosToAdd != 0)
+                {
+                    timestamp += new Duration { Nanos = nanosToAdd, Seconds = secondsToAdd };
+                    // The resulting timestamp after offset change would be out of our expected range. Currently the Timestamp message doesn't validate this
+                    // anywhere, but we shouldn't parse it.
+                    if (timestamp.Seconds < Timestamp.UnixSecondsAtBclMinValue || timestamp.Seconds > Timestamp.UnixSecondsAtBclMaxValue)
+                    {
+                        throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
+                    }
+                }
+                message.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.SetValue(message, timestamp.Seconds);
+                message.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.SetValue(message, timestamp.Nanos);
+            }
+            catch (FormatException)
+            {
+                throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
+            }
+        }
+
+        private static void MergeDuration(IMessage message, JsonToken token)
+        {
+            if (token.Type != JsonToken.TokenType.StringValue)
+            {
+                throw new InvalidProtocolBufferException("Expected string value for Duration");
+            }
+            var match = DurationRegex.Match(token.StringValue);
+            if (!match.Success)
+            {
+                throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
+            }
+            var sign = match.Groups["sign"].Value;
+            var secondsText = match.Groups["int"].Value;
+            // Prohibit leading insignficant zeroes
+            if (secondsText[0] == '0' && secondsText.Length > 1)
+            {
+                throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
+            }
+            var subseconds = match.Groups["subseconds"].Value;
+            var multiplier = sign == "-" ? -1 : 1;
+
+            try
+            {
+                long seconds = long.Parse(secondsText, CultureInfo.InvariantCulture) * multiplier;
+                int nanos = 0;
+                if (subseconds != "")
+                {
+                    // This should always work, as we've got 1-9 digits.
+                    int parsedFraction = int.Parse(subseconds.Substring(1));
+                    nanos = parsedFraction * SubsecondScalingFactors[subseconds.Length] * multiplier;
+                }
+                if (!Duration.IsNormalized(seconds, nanos))
+                {
+                    throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}");
+                }
+                message.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.SetValue(message, seconds);
+                message.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.SetValue(message, nanos);
+            }
+            catch (FormatException)
+            {
+                throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}");
+            }
+        }
+
+        private static void MergeFieldMask(IMessage message, JsonToken token)
+        {
+            if (token.Type != JsonToken.TokenType.StringValue)
+            {
+                throw new InvalidProtocolBufferException("Expected string value for FieldMask");
+            }
+            // TODO: Do we *want* to remove empty entries? Probably okay to treat "" as "no paths", but "foo,,bar"?
+            string[] jsonPaths = token.StringValue.Split(FieldMaskPathSeparators, StringSplitOptions.RemoveEmptyEntries);
+            IList messagePaths = (IList) message.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(message);
+            foreach (var path in jsonPaths)
+            {
+                messagePaths.Add(ToSnakeCase(path));
+            }
+        }
+        
+        // Ported from src/google/protobuf/util/internal/utility.cc
+        private static string ToSnakeCase(string text)
+        {
+            var builder = new StringBuilder(text.Length * 2);
+            // Note: this is probably unnecessary now, but currently retained to be as close as possible to the
+            // C++, whilst still throwing an exception on underscores.
+            bool wasNotUnderscore = false;  // Initialize to false for case 1 (below)
+            bool wasNotCap = false;
+
+            for (int i = 0; i < text.Length; i++)
+            {
+                char c = text[i];
+                if (c >= 'A' && c <= 'Z') // ascii_isupper
+                {
+                    // Consider when the current character B is capitalized:
+                    // 1) At beginning of input:   "B..." => "b..."
+                    //    (e.g. "Biscuit" => "biscuit")
+                    // 2) Following a lowercase:   "...aB..." => "...a_b..."
+                    //    (e.g. "gBike" => "g_bike")
+                    // 3) At the end of input:     "...AB" => "...ab"
+                    //    (e.g. "GoogleLAB" => "google_lab")
+                    // 4) Followed by a lowercase: "...ABc..." => "...a_bc..."
+                    //    (e.g. "GBike" => "g_bike")
+                    if (wasNotUnderscore &&               //            case 1 out
+                        (wasNotCap ||                     // case 2 in, case 3 out
+                         (i + 1 < text.Length &&         //            case 3 out
+                          (text[i + 1] >= 'a' && text[i + 1] <= 'z')))) // ascii_islower(text[i + 1])
+                    {  // case 4 in
+                       // We add an underscore for case 2 and case 4.
+                        builder.Append('_');
+                    }
+                    // ascii_tolower, but we already know that c *is* an upper case ASCII character...
+                    builder.Append((char) (c + 'a' - 'A'));
+                    wasNotUnderscore = true;
+                    wasNotCap = false;
+                }
+                else
+                {
+                    builder.Append(c);
+                    if (c == '_')
+                    {
+                        throw new InvalidProtocolBufferException($"Invalid field mask: {text}");
+                    }
+                    wasNotUnderscore = true;
+                    wasNotCap = true;
+                }
+            }
+            return builder.ToString();
+        }
+        #endregion
+
+        /// <summary>
+        /// Settings controlling JSON parsing.
+        /// </summary>
+        public sealed class Settings
+        {
+            /// <summary>
+            /// Default settings, as used by <see cref="JsonParser.Default"/>. This has the same default
+            /// recursion limit as <see cref="CodedInputStream"/>, and an empty type registry.
+            /// </summary>
+            public static Settings Default { get; }
+
+            // Workaround for the Mono compiler complaining about XML comments not being on
+            // valid language elements.
+            static Settings()
+            {
+                Default = new Settings(CodedInputStream.DefaultRecursionLimit);
+            }
+
+            /// <summary>
+            /// The maximum depth of messages to parse. Note that this limit only applies to parsing
+            /// messages, not collections - so a message within a collection within a message only counts as
+            /// depth 2, not 3.
+            /// </summary>
+            public int RecursionLimit { get; }
+
+            /// <summary>
+            /// The type registry used to parse <see cref="Any"/> messages.
+            /// </summary>
+            public TypeRegistry TypeRegistry { get; }
+
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified recursion limit.
+            /// </summary>
+            /// <param name="recursionLimit">The maximum depth of messages to parse</param>
+            public Settings(int recursionLimit) : this(recursionLimit, TypeRegistry.Empty)
+            {
+            }
+
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified recursion limit and type registry.
+            /// </summary>
+            /// <param name="recursionLimit">The maximum depth of messages to parse</param>
+            /// <param name="typeRegistry">The type registry used to parse <see cref="Any"/> messages</param>
+            public Settings(int recursionLimit, TypeRegistry typeRegistry)
+            {
+                RecursionLimit = recursionLimit;
+                TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry));
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonToken.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonToken.cs
new file mode 100644
index 0000000..6c0138c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonToken.cs
@@ -0,0 +1,166 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    internal sealed class JsonToken : IEquatable<JsonToken>
+    {
+        // Tokens with no value can be reused.
+        private static readonly JsonToken _true = new JsonToken(TokenType.True);
+        private static readonly JsonToken _false = new JsonToken(TokenType.False);
+        private static readonly JsonToken _null = new JsonToken(TokenType.Null);
+        private static readonly JsonToken startObject = new JsonToken(TokenType.StartObject);
+        private static readonly JsonToken endObject = new JsonToken(TokenType.EndObject);
+        private static readonly JsonToken startArray = new JsonToken(TokenType.StartArray);
+        private static readonly JsonToken endArray = new JsonToken(TokenType.EndArray);
+        private static readonly JsonToken endDocument = new JsonToken(TokenType.EndDocument);
+
+        internal static JsonToken Null { get { return _null; } }
+        internal static JsonToken False { get { return _false; } }
+        internal static JsonToken True { get { return _true; } }
+        internal static JsonToken StartObject{ get { return startObject; } }
+        internal static JsonToken EndObject { get { return endObject; } }
+        internal static JsonToken StartArray { get { return startArray; } }
+        internal static JsonToken EndArray { get { return endArray; } }
+        internal static JsonToken EndDocument { get { return endDocument; } }
+
+        internal static JsonToken Name(string name)
+        {
+            return new JsonToken(TokenType.Name, stringValue: name);
+        }
+
+        internal static JsonToken Value(string value)
+        {
+            return new JsonToken(TokenType.StringValue, stringValue: value);
+        }
+
+        internal static JsonToken Value(double value)
+        {
+            return new JsonToken(TokenType.Number, numberValue: value);
+        }
+
+        internal enum TokenType
+        {
+            Null,
+            False,
+            True,
+            StringValue,
+            Number,
+            Name,
+            StartObject,
+            EndObject,
+            StartArray,
+            EndArray,
+            EndDocument
+        }
+
+        // A value is a string, number, array, object, null, true or false
+        // Arrays and objects have start/end
+        // A document consists of a value
+        // Objects are name/value sequences.
+
+        private readonly TokenType type;
+        private readonly string stringValue;
+        private readonly double numberValue;
+
+        internal TokenType Type { get { return type; } }
+        internal string StringValue { get { return stringValue; } }
+        internal double NumberValue { get { return numberValue; } }
+
+        private JsonToken(TokenType type, string stringValue = null, double numberValue = 0)
+        {
+            this.type = type;
+            this.stringValue = stringValue;
+            this.numberValue = numberValue;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as JsonToken);
+        }
+
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                int hash = 17;
+                hash = hash * 31 + (int) type;
+                hash = hash * 31 + stringValue == null ? 0 : stringValue.GetHashCode();
+                hash = hash * 31 + numberValue.GetHashCode();
+                return hash;
+            }
+        }
+
+        public override string ToString()
+        {
+            switch (type)
+            {
+                case TokenType.Null:
+                    return "null";
+                case TokenType.True:
+                    return "true";
+                case TokenType.False:
+                    return "false";
+                case TokenType.Name:
+                    return "name (" + stringValue + ")";
+                case TokenType.StringValue:
+                    return "value (" + stringValue + ")";
+                case TokenType.Number:
+                    return "number (" + numberValue + ")";
+                case TokenType.StartObject:
+                    return "start-object";
+                case TokenType.EndObject:
+                    return "end-object";
+                case TokenType.StartArray:
+                    return "start-array";
+                case TokenType.EndArray:
+                    return "end-array";
+                case TokenType.EndDocument:
+                    return "end-document";
+                default:
+                    throw new InvalidOperationException("Token is of unknown type " + type);
+            }
+        }
+
+        public bool Equals(JsonToken other)
+        {
+            if (ReferenceEquals(other, null))
+            {
+                return false;
+            }
+            // Note use of other.numberValue.Equals rather than ==, so that NaN compares appropriately.
+            return other.type == type && other.stringValue == stringValue && other.numberValue.Equals(numberValue);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonTokenizer.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonTokenizer.cs
new file mode 100644
index 0000000..09a6d43
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/JsonTokenizer.cs
@@ -0,0 +1,738 @@
+#region Copyright notice and license
+// 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.
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Simple but strict JSON tokenizer, rigidly following RFC 7159.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// This tokenizer is stateful, and only returns "useful" tokens - names, values etc.
+    /// It does not create tokens for the separator between names and values, or for the comma
+    /// between values. It validates the token stream as it goes - so callers can assume that the
+    /// tokens it produces are appropriate. For example, it would never produce "start object, end array."
+    /// </para>
+    /// <para>Implementation details: the base class handles single token push-back and </para>
+    /// <para>Not thread-safe.</para>
+    /// </remarks>
+    internal abstract class JsonTokenizer
+    {
+        private JsonToken bufferedToken;
+
+        /// <summary>
+        ///  Creates a tokenizer that reads from the given text reader.
+        /// </summary>
+        internal static JsonTokenizer FromTextReader(TextReader reader)
+        {
+            return new JsonTextTokenizer(reader);
+        }
+
+        /// <summary>
+        /// Creates a tokenizer that first replays the given list of tokens, then continues reading
+        /// from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back
+        /// on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was
+        /// created for the sake of Any parsing.
+        /// </summary>
+        internal static JsonTokenizer FromReplayedTokens(IList<JsonToken> tokens, JsonTokenizer continuation)
+        {
+            return new JsonReplayTokenizer(tokens, continuation);
+        }
+
+        /// <summary>
+        /// Returns the depth of the stack, purely in objects (not collections).
+        /// Informally, this is the number of remaining unclosed '{' characters we have.
+        /// </summary>
+        internal int ObjectDepth { get; private set; }
+
+        // TODO: Why do we allow a different token to be pushed back? It might be better to always remember the previous
+        // token returned, and allow a parameterless Rewind() method (which could only be called once, just like the current PushBack).
+        internal void PushBack(JsonToken token)
+        {
+            if (bufferedToken != null)
+            {
+                throw new InvalidOperationException("Can't push back twice");
+            }
+            bufferedToken = token;
+            if (token.Type == JsonToken.TokenType.StartObject)
+            {
+                ObjectDepth--;
+            }
+            else if (token.Type == JsonToken.TokenType.EndObject)
+            {
+                ObjectDepth++;
+            }
+        }
+
+        /// <summary>
+        /// Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream,
+        /// after which point <c>Next()</c> should not be called again.
+        /// </summary>
+        /// <remarks>This implementation provides single-token buffering, and calls <see cref="NextImpl"/> if there is no buffered token.</remarks>
+        /// <returns>The next token in the stream. This is never null.</returns>
+        /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception>
+        /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception>
+        internal JsonToken Next()
+        {
+            JsonToken tokenToReturn;
+            if (bufferedToken != null)
+            {
+                tokenToReturn = bufferedToken;
+                bufferedToken = null;
+            }
+            else
+            {
+                tokenToReturn = NextImpl();
+            }
+            if (tokenToReturn.Type == JsonToken.TokenType.StartObject)
+            {
+                ObjectDepth++;
+            }
+            else if (tokenToReturn.Type == JsonToken.TokenType.EndObject)
+            {
+                ObjectDepth--;
+            }
+            return tokenToReturn;
+        }
+
+        /// <summary>
+        /// Returns the next JSON token in the stream, when requested by the base class. (The <see cref="Next"/> method delegates
+        /// to this if it doesn't have a buffered token.)
+        /// </summary>
+        /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception>
+        /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception>
+        protected abstract JsonToken NextImpl();
+
+        /// <summary>
+        /// Tokenizer which first exhausts a list of tokens, then consults another tokenizer.
+        /// </summary>
+        private class JsonReplayTokenizer : JsonTokenizer
+        {
+            private readonly IList<JsonToken> tokens;
+            private readonly JsonTokenizer nextTokenizer;
+            private int nextTokenIndex;
+
+            internal JsonReplayTokenizer(IList<JsonToken> tokens, JsonTokenizer nextTokenizer)
+            {
+                this.tokens = tokens;
+                this.nextTokenizer = nextTokenizer;
+            }
+
+            // FIXME: Object depth not maintained...
+            protected override JsonToken NextImpl()
+            {
+                if (nextTokenIndex >= tokens.Count)
+                {
+                    return nextTokenizer.Next();
+                }
+                return tokens[nextTokenIndex++];
+            }
+        }
+
+        /// <summary>
+        /// Tokenizer which does all the *real* work of parsing JSON.
+        /// </summary>
+        private sealed class JsonTextTokenizer : JsonTokenizer
+        {
+            // The set of states in which a value is valid next token.
+            private static readonly State ValueStates = State.ArrayStart | State.ArrayAfterComma | State.ObjectAfterColon | State.StartOfDocument;
+
+            private readonly Stack<ContainerType> containerStack = new Stack<ContainerType>();
+            private readonly PushBackReader reader;
+            private State state;
+
+            internal JsonTextTokenizer(TextReader reader)
+            {
+                this.reader = new PushBackReader(reader);
+                state = State.StartOfDocument;
+                containerStack.Push(ContainerType.Document);
+            }
+
+            /// <remarks>
+            /// This method essentially just loops through characters skipping whitespace, validating and
+            /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon)
+            /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point
+            /// it returns the token. Although the method is large, it would be relatively hard to break down further... most
+            /// of it is the large switch statement, which sometimes returns and sometimes doesn't.
+            /// </remarks>
+            protected override JsonToken NextImpl()
+            {
+                if (state == State.ReaderExhausted)
+                {
+                    throw new InvalidOperationException("Next() called after end of document");
+                }
+                while (true)
+                {
+                    var next = reader.Read();
+                    if (next == null)
+                    {
+                        ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: ");
+                        state = State.ReaderExhausted;
+                        return JsonToken.EndDocument;
+                    }
+                    switch (next.Value)
+                    {
+                        // Skip whitespace between tokens
+                        case ' ':
+                        case '\t':
+                        case '\r':
+                        case '\n':
+                            break;
+                        case ':':
+                            ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: ");
+                            state = State.ObjectAfterColon;
+                            break;
+                        case ',':
+                            ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: ");
+                            state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma;
+                            break;
+                        case '"':
+                            string stringValue = ReadString();
+                            if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0)
+                            {
+                                state = State.ObjectBeforeColon;
+                                return JsonToken.Name(stringValue);
+                            }
+                            else
+                            {
+                                ValidateAndModifyStateForValue("Invalid state to read a double quote: ");
+                                return JsonToken.Value(stringValue);
+                            }
+                        case '{':
+                            ValidateState(ValueStates, "Invalid state to read an open brace: ");
+                            state = State.ObjectStart;
+                            containerStack.Push(ContainerType.Object);
+                            return JsonToken.StartObject;
+                        case '}':
+                            ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: ");
+                            PopContainer();
+                            return JsonToken.EndObject;
+                        case '[':
+                            ValidateState(ValueStates, "Invalid state to read an open square bracket: ");
+                            state = State.ArrayStart;
+                            containerStack.Push(ContainerType.Array);
+                            return JsonToken.StartArray;
+                        case ']':
+                            ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: ");
+                            PopContainer();
+                            return JsonToken.EndArray;
+                        case 'n': // Start of null
+                            ConsumeLiteral("null");
+                            ValidateAndModifyStateForValue("Invalid state to read a null literal: ");
+                            return JsonToken.Null;
+                        case 't': // Start of true
+                            ConsumeLiteral("true");
+                            ValidateAndModifyStateForValue("Invalid state to read a true literal: ");
+                            return JsonToken.True;
+                        case 'f': // Start of false
+                            ConsumeLiteral("false");
+                            ValidateAndModifyStateForValue("Invalid state to read a false literal: ");
+                            return JsonToken.False;
+                        case '-': // Start of a number
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                        case '8':
+                        case '9':
+                            double number = ReadNumber(next.Value);
+                            ValidateAndModifyStateForValue("Invalid state to read a number token: ");
+                            return JsonToken.Value(number);
+                        default:
+                            throw new InvalidJsonException("Invalid first character of token: " + next.Value);
+                    }
+                }
+            }
+
+            private void ValidateState(State validStates, string errorPrefix)
+            {
+                if ((validStates & state) == 0)
+                {
+                    throw reader.CreateException(errorPrefix + state);
+                }
+            }
+
+            /// <summary>
+            /// Reads a string token. It is assumed that the opening " has already been read.
+            /// </summary>
+            private string ReadString()
+            {
+                var value = new StringBuilder();
+                bool haveHighSurrogate = false;
+                while (true)
+                {
+                    char c = reader.ReadOrFail("Unexpected end of text while reading string");
+                    if (c < ' ')
+                    {
+                        throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in string literal: U+{0:x4}", (int) c));
+                    }
+                    if (c == '"')
+                    {
+                        if (haveHighSurrogate)
+                        {
+                            throw reader.CreateException("Invalid use of surrogate pair code units");
+                        }
+                        return value.ToString();
+                    }
+                    if (c == '\\')
+                    {
+                        c = ReadEscapedCharacter();
+                    }
+                    // TODO: Consider only allowing surrogate pairs that are either both escaped,
+                    // or both not escaped. It would be a very odd text stream that contained a "lone" high surrogate
+                    // followed by an escaped low surrogate or vice versa... and that couldn't even be represented in UTF-8.
+                    if (haveHighSurrogate != char.IsLowSurrogate(c))
+                    {
+                        throw reader.CreateException("Invalid use of surrogate pair code units");
+                    }
+                    haveHighSurrogate = char.IsHighSurrogate(c);
+                    value.Append(c);
+                }
+            }
+
+            /// <summary>
+            /// Reads an escaped character. It is assumed that the leading backslash has already been read.
+            /// </summary>
+            private char ReadEscapedCharacter()
+            {
+                char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence");
+                switch (c)
+                {
+                    case 'n':
+                        return '\n';
+                    case '\\':
+                        return '\\';
+                    case 'b':
+                        return '\b';
+                    case 'f':
+                        return '\f';
+                    case 'r':
+                        return '\r';
+                    case 't':
+                        return '\t';
+                    case '"':
+                        return '"';
+                    case '/':
+                        return '/';
+                    case 'u':
+                        return ReadUnicodeEscape();
+                    default:
+                        throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c));
+                }
+            }
+
+            /// <summary>
+            /// Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read.
+            /// </summary>
+            private char ReadUnicodeEscape()
+            {
+                int result = 0;
+                for (int i = 0; i < 4; i++)
+                {
+                    char c = reader.ReadOrFail("Unexpected end of text while reading Unicode escape sequence");
+                    int nybble;
+                    if (c >= '0' && c <= '9')
+                    {
+                        nybble = c - '0';
+                    }
+                    else if (c >= 'a' && c <= 'f')
+                    {
+                        nybble = c - 'a' + 10;
+                    }
+                    else if (c >= 'A' && c <= 'F')
+                    {
+                        nybble = c - 'A' + 10;
+                    }
+                    else
+                    {
+                        throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c));
+                    }
+                    result = (result << 4) + nybble;
+                }
+                return (char) result;
+            }
+
+            /// <summary>
+            /// Consumes a text-only literal, throwing an exception if the read text doesn't match it.
+            /// It is assumed that the first letter of the literal has already been read.
+            /// </summary>
+            private void ConsumeLiteral(string text)
+            {
+                for (int i = 1; i < text.Length; i++)
+                {
+                    char? next = reader.Read();
+                    if (next == null)
+                    {
+                        throw reader.CreateException("Unexpected end of text while reading literal token " + text);
+                    }
+                    if (next.Value != text[i])
+                    {
+                        throw reader.CreateException("Unexpected character while reading literal token " + text);
+                    }
+                }
+            }
+
+            private double ReadNumber(char initialCharacter)
+            {
+                StringBuilder builder = new StringBuilder();
+                if (initialCharacter == '-')
+                {
+                    builder.Append("-");
+                }
+                else
+                {
+                    reader.PushBack(initialCharacter);
+                }
+                // Each method returns the character it read that doesn't belong in that part,
+                // so we know what to do next, including pushing the character back at the end.
+                // null is returned for "end of text".
+                char? next = ReadInt(builder);
+                if (next == '.')
+                {
+                    next = ReadFrac(builder);
+                }
+                if (next == 'e' || next == 'E')
+                {
+                    next = ReadExp(builder);
+                }
+                // If we read a character which wasn't part of the number, push it back so we can read it again
+                // to parse the next token.
+                if (next != null)
+                {
+                    reader.PushBack(next.Value);
+                }
+
+                // TODO: What exception should we throw if the value can't be represented as a double?
+                try
+                {
+                    return double.Parse(builder.ToString(),
+                        NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent,
+                        CultureInfo.InvariantCulture);
+                }
+                catch (OverflowException)
+                {
+                    throw reader.CreateException("Numeric value out of range: " + builder);
+                }
+            }
+
+            private char? ReadInt(StringBuilder builder)
+            {
+                char first = reader.ReadOrFail("Invalid numeric literal");
+                if (first < '0' || first > '9')
+                {
+                    throw reader.CreateException("Invalid numeric literal");
+                }
+                builder.Append(first);
+                int digitCount;
+                char? next = ConsumeDigits(builder, out digitCount);
+                if (first == '0' && digitCount != 0)
+                {
+                    throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value.");
+                }
+                return next;
+            }
+
+            private char? ReadFrac(StringBuilder builder)
+            {
+                builder.Append('.'); // Already consumed this
+                int digitCount;
+                char? next = ConsumeDigits(builder, out digitCount);
+                if (digitCount == 0)
+                {
+                    throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits");
+                }
+                return next;
+            }
+
+            private char? ReadExp(StringBuilder builder)
+            {
+                builder.Append('E'); // Already consumed this (or 'e')
+                char? next = reader.Read();
+                if (next == null)
+                {
+                    throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits");
+                }
+                if (next == '-' || next == '+')
+                {
+                    builder.Append(next.Value);
+                }
+                else
+                {
+                    reader.PushBack(next.Value);
+                }
+                int digitCount;
+                next = ConsumeDigits(builder, out digitCount);
+                if (digitCount == 0)
+                {
+                    throw reader.CreateException("Invalid numeric literal: exponent without value");
+                }
+                return next;
+            }
+
+            private char? ConsumeDigits(StringBuilder builder, out int count)
+            {
+                count = 0;
+                while (true)
+                {
+                    char? next = reader.Read();
+                    if (next == null || next.Value < '0' || next.Value > '9')
+                    {
+                        return next;
+                    }
+                    count++;
+                    builder.Append(next.Value);
+                }
+            }
+
+            /// <summary>
+            /// Validates that we're in a valid state to read a value (using the given error prefix if necessary)
+            /// and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty.
+            /// </summary>
+            private void ValidateAndModifyStateForValue(string errorPrefix)
+            {
+                ValidateState(ValueStates, errorPrefix);
+                switch (state)
+                {
+                    case State.StartOfDocument:
+                        state = State.ExpectedEndOfDocument;
+                        return;
+                    case State.ObjectAfterColon:
+                        state = State.ObjectAfterProperty;
+                        return;
+                    case State.ArrayStart:
+                    case State.ArrayAfterComma:
+                        state = State.ArrayAfterValue;
+                        return;
+                    default:
+                        throw new InvalidOperationException("ValidateAndModifyStateForValue does not handle all value states (and should)");
+                }
+            }
+
+            /// <summary>
+            /// Pops the top-most container, and sets the state to the appropriate one for the end of a value
+            /// in the parent container.
+            /// </summary>
+            private void PopContainer()
+            {
+                containerStack.Pop();
+                var parent = containerStack.Peek();
+                switch (parent)
+                {
+                    case ContainerType.Object:
+                        state = State.ObjectAfterProperty;
+                        break;
+                    case ContainerType.Array:
+                        state = State.ArrayAfterValue;
+                        break;
+                    case ContainerType.Document:
+                        state = State.ExpectedEndOfDocument;
+                        break;
+                    default:
+                        throw new InvalidOperationException("Unexpected container type: " + parent);
+                }
+            }
+
+            private enum ContainerType
+            {
+                Document, Object, Array
+            }
+
+            /// <summary>
+            /// Possible states of the tokenizer.
+            /// </summary>
+            /// <remarks>
+            /// <para>This is a flags enum purely so we can simply and efficiently represent a set of valid states
+            /// for checking.</para>
+            /// <para>
+            /// Each is documented with an example,
+            /// where ^ represents the current position within the text stream. The examples all use string values,
+            /// but could be any value, including nested objects/arrays.
+            /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects).
+            /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which 
+            /// point there's an immediate transition to ExpectedEndOfDocument,  ObjectAfterProperty or ArrayAfterValue.
+            /// </para>
+            /// <para>
+            /// These states were derived manually by reading RFC 7159 carefully.
+            /// </para>
+            /// </remarks>
+            [Flags]
+            private enum State
+            {
+                /// <summary>
+                /// ^ { "foo": "bar" }
+                /// Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue"
+                /// </summary>
+                StartOfDocument = 1 << 0,
+                /// <summary>
+                /// { "foo": "bar" } ^
+                /// After the value in a document. Next states: ReaderExhausted
+                /// </summary>
+                ExpectedEndOfDocument = 1 << 1,
+                /// <summary>
+                /// { "foo": "bar" } ^ (and already read to the end of the reader)
+                /// Terminal state.
+                /// </summary>
+                ReaderExhausted = 1 << 2,
+                /// <summary>
+                /// { ^ "foo": "bar" }
+                /// Before the *first* property in an object.
+                /// Next states:
+                /// "AfterValue" (empty object)
+                /// ObjectBeforeColon (read a name)
+                /// </summary>
+                ObjectStart = 1 << 3,
+                /// <summary>
+                /// { "foo" ^ : "bar", "x": "y" }
+                /// Next state: ObjectAfterColon
+                /// </summary>
+                ObjectBeforeColon = 1 << 4,
+                /// <summary>
+                /// { "foo" : ^ "bar", "x": "y" }
+                /// Before any property other than the first in an object.
+                /// (Equivalently: after any property in an object) 
+                /// Next states:
+                /// "AfterValue" (value is simple)
+                /// ObjectStart (value is object)
+                /// ArrayStart (value is array)
+                /// </summary>
+                ObjectAfterColon = 1 << 5,
+                /// <summary>
+                /// { "foo" : "bar" ^ , "x" : "y" }
+                /// At the end of a property, so expecting either a comma or end-of-object
+                /// Next states: ObjectAfterComma or "AfterValue"
+                /// </summary>
+                ObjectAfterProperty = 1 << 6,
+                /// <summary>
+                /// { "foo":"bar", ^ "x":"y" }
+                /// Read the comma after the previous property, so expecting another property.
+                /// This is like ObjectStart, but closing brace isn't valid here
+                /// Next state: ObjectBeforeColon.
+                /// </summary>
+                ObjectAfterComma = 1 << 7,
+                /// <summary>
+                /// [ ^ "foo", "bar" ]
+                /// Before the *first* value in an array.
+                /// Next states:
+                /// "AfterValue" (read a value)
+                /// "AfterValue" (end of array; will pop stack)
+                /// </summary>
+                ArrayStart = 1 << 8,
+                /// <summary>
+                /// [ "foo" ^ , "bar" ]
+                /// After any value in an array, so expecting either a comma or end-of-array
+                /// Next states: ArrayAfterComma or "AfterValue"
+                /// </summary>
+                ArrayAfterValue = 1 << 9,
+                /// <summary>
+                /// [ "foo", ^ "bar" ]
+                /// After a comma in an array, so there *must* be another value (simple or complex).
+                /// Next states: "AfterValue" (simple value), StartObject, StartArray
+                /// </summary>
+                ArrayAfterComma = 1 << 10
+            }
+
+            /// <summary>
+            /// Wrapper around a text reader allowing small amounts of buffering and location handling.
+            /// </summary>
+            private class PushBackReader
+            {
+                // TODO: Add locations for errors etc.
+
+                private readonly TextReader reader;
+
+                internal PushBackReader(TextReader reader)
+                {
+                    // TODO: Wrap the reader in a BufferedReader?
+                    this.reader = reader;
+                }
+
+                /// <summary>
+                /// The buffered next character, if we have one.
+                /// </summary>
+                private char? nextChar;
+
+                /// <summary>
+                /// Returns the next character in the stream, or null if we have reached the end.
+                /// </summary>
+                /// <returns></returns>
+                internal char? Read()
+                {
+                    if (nextChar != null)
+                    {
+                        char? tmp = nextChar;
+                        nextChar = null;
+                        return tmp;
+                    }
+                    int next = reader.Read();
+                    return next == -1 ? null : (char?) next;
+                }
+
+                internal char ReadOrFail(string messageOnFailure)
+                {
+                    char? next = Read();
+                    if (next == null)
+                    {
+                        throw CreateException(messageOnFailure);
+                    }
+                    return next.Value;
+                }
+
+                internal void PushBack(char c)
+                {
+                    if (nextChar != null)
+                    {
+                        throw new InvalidOperationException("Cannot push back when already buffering a character");
+                    }
+                    nextChar = c;
+                }
+
+                /// <summary>
+                /// Creates a new exception appropriate for the current state of the reader.
+                /// </summary>
+                internal InvalidJsonException CreateException(string message)
+                {
+                    // TODO: Keep track of and use the location.
+                    return new InvalidJsonException(message);
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/LimitedInputStream.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/LimitedInputStream.cs
new file mode 100644
index 0000000..f11d19d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/LimitedInputStream.cs
@@ -0,0 +1,110 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+    
+using System;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Stream implementation which proxies another stream, only allowing a certain amount
+    /// of data to be read. Note that this is only used to read delimited streams, so it
+    /// doesn't attempt to implement everything.
+    /// </summary>
+    internal sealed class LimitedInputStream : Stream
+    {
+        private readonly Stream proxied;
+        private int bytesLeft;
+
+        internal LimitedInputStream(Stream proxied, int size)
+        {
+            this.proxied = proxied;
+            bytesLeft = size;
+        }
+
+        public override bool CanRead
+        {
+            get { return true; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return false; }
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override long Length
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        public override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (bytesLeft > 0)
+            {
+                int bytesRead = proxied.Read(buffer, offset, Math.Min(bytesLeft, count));
+                bytesLeft -= bytesRead;
+                return bytesRead;
+            }
+            return 0;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            throw new NotSupportedException();
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageExtensions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageExtensions.cs
new file mode 100644
index 0000000..047156c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageExtensions.cs
@@ -0,0 +1,157 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Extension methods on <see cref="IMessage"/> and <see cref="IMessage{T}"/>.
+    /// </summary>
+    public static class MessageExtensions
+    {
+        /// <summary>
+        /// Merges data from the given byte array into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
+        public static void MergeFrom(this IMessage message, byte[] data)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(data, "data");
+            CodedInputStream input = new CodedInputStream(data);
+            message.MergeFrom(input);
+            input.CheckReadEndOfStreamTag();
+        }
+
+        /// <summary>
+        /// Merges data from the given byte string into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
+        public static void MergeFrom(this IMessage message, ByteString data)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(data, "data");
+            CodedInputStream input = data.CreateCodedInput();
+            message.MergeFrom(input);
+            input.CheckReadEndOfStreamTag();
+        }
+
+        /// <summary>
+        /// Merges data from the given stream into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
+        public static void MergeFrom(this IMessage message, Stream input)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(input, "input");
+            CodedInputStream codedInput = new CodedInputStream(input);
+            message.MergeFrom(codedInput);
+            codedInput.CheckReadEndOfStreamTag();
+        }
+
+        /// <summary>
+        /// Merges length-delimited data from the given stream into an existing message.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
+        public static void MergeDelimitedFrom(this IMessage message, Stream input)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(input, "input");
+            int size = (int) CodedInputStream.ReadRawVarint32(input);
+            Stream limitedStream = new LimitedInputStream(input, size);
+            message.MergeFrom(limitedStream);
+        }
+
+        /// <summary>
+        /// Converts the given message into a byte array in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to convert.</param>
+        /// <returns>The message data as a byte array.</returns>
+        public static byte[] ToByteArray(this IMessage message)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            byte[] result = new byte[message.CalculateSize()];
+            CodedOutputStream output = new CodedOutputStream(result);
+            message.WriteTo(output);
+            output.CheckNoSpaceLeft();
+            return result;
+        }
+
+        /// <summary>
+        /// Writes the given message data to the given stream in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to write to the stream.</param>
+        /// <param name="output">The stream to write to.</param>
+        public static void WriteTo(this IMessage message, Stream output)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(output, "output");
+            CodedOutputStream codedOutput = new CodedOutputStream(output);
+            message.WriteTo(codedOutput);
+            codedOutput.Flush();
+        }
+
+        /// <summary>
+        /// Writes the length and then data of the given message to a stream.
+        /// </summary>
+        /// <param name="message">The message to write.</param>
+        /// <param name="output">The output stream to write to.</param>
+        public static void WriteDelimitedTo(this IMessage message, Stream output)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(output, "output");
+            CodedOutputStream codedOutput = new CodedOutputStream(output);
+            codedOutput.WriteRawVarint32((uint)message.CalculateSize());
+            message.WriteTo(codedOutput);
+            codedOutput.Flush();
+        }
+
+        /// <summary>
+        /// Converts the given message into a byte string in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to convert.</param>
+        /// <returns>The message data as a byte string.</returns>
+        public static ByteString ToByteString(this IMessage message)
+        {
+            ProtoPreconditions.CheckNotNull(message, "message");
+            return ByteString.AttachBytes(message.ToByteArray());
+        }        
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageParser.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageParser.cs
new file mode 100644
index 0000000..8889638
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/MessageParser.cs
@@ -0,0 +1,267 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+    
+using System;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// A general message parser, typically used by reflection-based code as all the methods
+    /// return simple <see cref="IMessage"/>.
+    /// </summary>
+    public class MessageParser
+    {
+        private Func<IMessage> factory;
+
+        internal MessageParser(Func<IMessage> factory)
+        {
+            this.factory = factory;
+        }
+
+        /// <summary>
+        /// Creates a template instance ready for population.
+        /// </summary>
+        /// <returns>An empty message.</returns>
+        internal IMessage CreateTemplate()
+        {
+            return factory();
+        }
+
+        /// <summary>
+        /// Parses a message from a byte array.
+        /// </summary>
+        /// <param name="data">The byte array containing the message. Must not be null.</param>
+        /// <returns>The newly parsed message.</returns>
+        public IMessage ParseFrom(byte[] data)
+        {
+            ProtoPreconditions.CheckNotNull(data, "data");
+            IMessage message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given byte string.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(ByteString data)
+        {
+            ProtoPreconditions.CheckNotNull(data, "data");
+            IMessage message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(Stream input)
+        {
+            IMessage message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a length-delimited message from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseDelimitedFrom(Stream input)
+        {
+            IMessage message = factory();
+            message.MergeDelimitedFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given coded input stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public IMessage ParseFrom(CodedInputStream input)
+        {
+            IMessage message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given JSON.
+        /// </summary>
+        /// <param name="json">The JSON to parse.</param>
+        /// <returns>The parsed message.</returns>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public IMessage ParseJson(string json)
+        {
+            IMessage message = factory();
+            JsonParser.Default.Merge(message, json);
+            return message;
+        }
+    }
+
+    /// <summary>
+    /// A parser for a specific message type.
+    /// </summary>
+    /// <remarks>
+    /// <p>
+    /// This delegates most behavior to the
+    /// <see cref="IMessage.MergeFrom"/> implementation within the original type, but
+    /// provides convenient overloads to parse from a variety of sources.
+    /// </p>
+    /// <p>
+    /// Most applications will never need to create their own instances of this type;
+    /// instead, use the static <c>Parser</c> property of a generated message type to obtain a
+    /// parser for that type.
+    /// </p>
+    /// </remarks>
+    /// <typeparam name="T">The type of message to be parsed.</typeparam>
+    public sealed class MessageParser<T> : MessageParser where T : IMessage<T>
+    {
+        // Implementation note: all the methods here *could* just delegate up to the base class and cast the result.
+        // The current implementation avoids a virtual method call and a cast, which *may* be significant in some cases.
+        // Benchmarking work is required to measure the significance - but it's only a few lines of code in any case.
+        // The API wouldn't change anyway - just the implementation - so this work can be deferred.
+        private readonly Func<T> factory; 
+
+        /// <summary>
+        /// Creates a new parser.
+        /// </summary>
+        /// <remarks>
+        /// The factory method is effectively an optimization over using a generic constraint
+        /// to require a parameterless constructor: delegates are significantly faster to execute.
+        /// </remarks>
+        /// <param name="factory">Function to invoke when a new, empty message is required.</param>
+        public MessageParser(Func<T> factory) : base(() => factory())
+        {
+            this.factory = factory;
+        }
+
+        /// <summary>
+        /// Creates a template instance ready for population.
+        /// </summary>
+        /// <returns>An empty message.</returns>
+        internal new T CreateTemplate()
+        {
+            return factory();
+        }
+
+        /// <summary>
+        /// Parses a message from a byte array.
+        /// </summary>
+        /// <param name="data">The byte array containing the message. Must not be null.</param>
+        /// <returns>The newly parsed message.</returns>
+        public new T ParseFrom(byte[] data)
+        {
+            ProtoPreconditions.CheckNotNull(data, "data");
+            T message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given byte string.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public new T ParseFrom(ByteString data)
+        {
+            ProtoPreconditions.CheckNotNull(data, "data");
+            T message = factory();
+            message.MergeFrom(data);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public new T ParseFrom(Stream input)
+        {
+            T message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a length-delimited message from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public new T ParseDelimitedFrom(Stream input)
+        {
+            T message = factory();
+            message.MergeDelimitedFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given coded input stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
+        public new T ParseFrom(CodedInputStream input)
+        {
+            T message = factory();
+            message.MergeFrom(input);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given JSON.
+        /// </summary>
+        /// <param name="json">The JSON to parse.</param>
+        /// <returns>The parsed message.</returns>
+        /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
+        /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception>
+        public new T ParseJson(string json)
+        {
+            T message = factory();
+            JsonParser.Default.Merge(message, json);
+            return message;
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ad852eb
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
@@ -0,0 +1,67 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Google.Protobuf")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Google.Protobuf")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+#if !NCRUNCH
+[assembly: AllowPartiallyTrustedCallers]
+#endif
+
+#if SIGNED
+[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
+    "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
+    "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
+    "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
+    "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
+    "c5ae9cb6")]
+#else
+[assembly: InternalsVisibleTo("Google.Protobuf.Test")]
+#endif
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
+[assembly: AssemblyInformationalVersion("3.0.0-beta3")]
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ProtoPreconditions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ProtoPreconditions.cs
new file mode 100644
index 0000000..abaeb9b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/ProtoPreconditions.cs
@@ -0,0 +1,79 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Helper methods for throwing exceptions when preconditions are not met.
+    /// </summary>
+    /// <remarks>
+    /// This class is used internally and by generated code; it is not particularly
+    /// expected to be used from application code, although nothing prevents it
+    /// from being used that way.
+    /// </remarks>
+    public static class ProtoPreconditions
+    {
+        /// <summary>
+        /// Throws an ArgumentNullException if the given value is null, otherwise
+        /// return the value to the caller.
+        /// </summary>
+        public static T CheckNotNull<T>(T value, string name) where T : class
+        {
+            if (value == null)
+            {
+                throw new ArgumentNullException(name);
+            }
+            return value;
+        }
+
+        /// <summary>
+        /// Throws an ArgumentNullException if the given value is null, otherwise
+        /// return the value to the caller.
+        /// </summary>
+        /// <remarks>
+        /// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
+        /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
+        /// with a value type - but it gets in the way if either you want to use it with a nullable
+        /// value type, or you want to use it with an unconstrained type parameter.
+        /// </remarks>
+        internal static T CheckNotNullUnconstrained<T>(T value, string name)
+        {
+            if (value == null)
+            {
+                throw new ArgumentNullException(name);
+            }
+            return value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
new file mode 100644
index 0000000..fa138df
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -0,0 +1,5421 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.Reflection {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/descriptor.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal static partial class DescriptorReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/descriptor.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static DescriptorReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy",
+            "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n",
+            "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLbAwoTRmlsZURl",
+            "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS",
+            "EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo",
+            "BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg",
+            "AygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90bxI3CgllbnVt",
+            "X3R5cGUYBSADKAsyJC5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQ",
+            "cm90bxI4CgdzZXJ2aWNlGAYgAygLMicuZ29vZ2xlLnByb3RvYnVmLlNlcnZp",
+            "Y2VEZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAcgAygLMiUuZ29vZ2xl",
+            "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
+            "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
+            "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
+            "bxIOCgZzeW50YXgYDCABKAki8AQKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
+            "GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
+            "RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
+            "cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
+            "IAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8SNwoJZW51",
+            "bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9y",
+            "UHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8uZ29vZ2xlLnByb3Rv",
+            "YnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5nZRI5CgpvbmVvZl9k",
+            "ZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9mRGVzY3JpcHRvclBy",
+            "b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
+            "ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
+            "dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
+            "ZWRfbmFtZRgKIAMoCRosCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
+            "BRILCgNlbmQYAiABKAUaKwoNUmVzZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEo",
+            "BRILCgNlbmQYAiABKAUivAUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5h",
+            "bWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29v",
+            "Z2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5",
+            "cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJv",
+            "dG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkS",
+            "FQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIR",
+            "Cglqc29uX25hbWUYCiABKAkSLgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5w",
+            "cm90b2J1Zi5GaWVsZE9wdGlvbnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQ",
+            "ARIOCgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlO",
+            "VDY0EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZ",
+            "UEVfRklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkS",
+            "DgoKVFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllU",
+            "RVMQDBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVf",
+            "U0ZJWEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQ",
+            "ERIPCgtUWVBFX1NJTlQ2NBASIkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFM",
+            "EAESEgoOTEFCRUxfUkVRVUlSRUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIiQK",
+            "FE9uZW9mRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkijAEKE0VudW1E",
+            "ZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIp",
+            "Lmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoH",
+            "b3B0aW9ucxgDIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucyJs",
+            "ChhFbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZu",
+            "dW1iZXIYAiABKAUSMgoHb3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1",
+            "Zi5FbnVtVmFsdWVPcHRpb25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3Rv",
+            "EgwKBG5hbWUYASABKAkSNgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3Rv",
+            "YnVmLk1ldGhvZERlc2NyaXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8u",
+            "Z29vZ2xlLnByb3RvYnVmLlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNj",
+            "cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJ",
+            "EhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29n",
+            "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5n",
+            "GAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxz",
+            "ZSKHBQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGph",
+            "dmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmls",
+            "ZXMYCiABKAg6BWZhbHNlEiwKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9o",
+            "YXNoGBQgASgIOgVmYWxzZRIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg",
+            "ASgIOgVmYWxzZRJGCgxvcHRpbWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJv",
+            "dG9idWYuRmlsZU9wdGlvbnMuT3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19w",
+            "YWNrYWdlGAsgASgJEiIKE2NjX2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZh",
+            "bHNlEiQKFWphdmFfZ2VuZXJpY19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoT",
+            "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl",
+            "ZBgXIAEoCDoFZmFsc2USHwoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoFZmFs",
+            "c2USGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVz",
+            "cGFjZRglIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n",
+            "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6",
+            "ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJ",
+            "TUUQAyoJCOgHEICAgIACSgQIJhAnIuYBCg5NZXNzYWdlT3B0aW9ucxImChdt",
+            "ZXNzYWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3Rh",
+            "bmRhcmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVw",
+            "cmVjYXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVu",
+            "aW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5V",
+            "bmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIimAMKDEZpZWxkT3B0aW9u",
+            "cxI6CgVjdHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
+            "bnMuQ1R5cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYg",
+            "ASgOMiQuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpT",
+            "X05PUk1BTBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMg",
+            "ASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJl",
+            "dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy",
+            "ZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoM",
+            "U1RSSU5HX1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpT",
+            "X1NUUklORxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAIijQEKC0VudW1P",
+            "cHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyAB",
+            "KAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv",
+            "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi",
+            "fQoQRW51bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxz",
+            "ZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJv",
+            "dG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZp",
+            "Y2VPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50",
+            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
+            "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiegoNTWV0aG9kT3B0aW9ucxIZ",
+            "CgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w",
+            "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w",
+            "dGlvbioJCOgHEICAgIACIp4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5h",
+            "bWUYAiADKAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlv",
+            "bi5OYW1lUGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0",
+            "aXZlX2ludF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSAB",
+            "KAMSFAoMZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEo",
+            "DBIXCg9hZ2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFt",
+            "ZV9wYXJ0GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNl",
+            "Q29kZUluZm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYu",
+            "U291cmNlQ29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgY",
+            "ASADKAVCAhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVu",
+            "dHMYAyABKAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGlu",
+            "Z19kZXRhY2hlZF9jb21tZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUlu",
+            "Zm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5l",
+            "cmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0",
+            "aBgBIAMoBUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyAB",
+            "KAUSCwoDZW5kGAQgASgFQlgKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2Ny",
+            "aXB0b3JQcm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdvb2dsZS5Qcm90",
+            "b2J1Zi5SZWZsZWN0aW9u"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null)})
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  The protocol compiler can output a FileDescriptorSet containing the .proto
+  ///  files it parses.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
+    private static readonly pb::MessageParser<FileDescriptorSet> _parser = new pb::MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
+    public static pb::MessageParser<FileDescriptorSet> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FileDescriptorSet() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FileDescriptorSet(FileDescriptorSet other) : this() {
+      file_ = other.file_.Clone();
+    }
+
+    public FileDescriptorSet Clone() {
+      return new FileDescriptorSet(this);
+    }
+
+    /// <summary>Field number for the "file" field.</summary>
+    public const int FileFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.FileDescriptorProto> _repeated_file_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Reflection.FileDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> File {
+      get { return file_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FileDescriptorSet);
+    }
+
+    public bool Equals(FileDescriptorSet other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!file_.Equals(other.file_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= file_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      file_.WriteTo(output, _repeated_file_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += file_.CalculateSize(_repeated_file_codec);
+      return size;
+    }
+
+    public void MergeFrom(FileDescriptorSet other) {
+      if (other == null) {
+        return;
+      }
+      file_.Add(other.file_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            file_.AddEntriesFrom(input, _repeated_file_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes a complete .proto file.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
+    private static readonly pb::MessageParser<FileDescriptorProto> _parser = new pb::MessageParser<FileDescriptorProto>(() => new FileDescriptorProto());
+    public static pb::MessageParser<FileDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FileDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FileDescriptorProto(FileDescriptorProto other) : this() {
+      name_ = other.name_;
+      package_ = other.package_;
+      dependency_ = other.dependency_.Clone();
+      publicDependency_ = other.publicDependency_.Clone();
+      weakDependency_ = other.weakDependency_.Clone();
+      messageType_ = other.messageType_.Clone();
+      enumType_ = other.enumType_.Clone();
+      service_ = other.service_.Clone();
+      extension_ = other.extension_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      SourceCodeInfo = other.sourceCodeInfo_ != null ? other.SourceCodeInfo.Clone() : null;
+      syntax_ = other.syntax_;
+    }
+
+    public FileDescriptorProto Clone() {
+      return new FileDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  file name, relative to root of source tree
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "package" field.</summary>
+    public const int PackageFieldNumber = 2;
+    private string package_ = "";
+    /// <summary>
+    ///  e.g. "foo", "foo.bar", etc.
+    /// </summary>
+    public string Package {
+      get { return package_; }
+      set {
+        package_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "dependency" field.</summary>
+    public const int DependencyFieldNumber = 3;
+    private static readonly pb::FieldCodec<string> _repeated_dependency_codec
+        = pb::FieldCodec.ForString(26);
+    private readonly pbc::RepeatedField<string> dependency_ = new pbc::RepeatedField<string>();
+    /// <summary>
+    ///  Names of files imported by this file.
+    /// </summary>
+    public pbc::RepeatedField<string> Dependency {
+      get { return dependency_; }
+    }
+
+    /// <summary>Field number for the "public_dependency" field.</summary>
+    public const int PublicDependencyFieldNumber = 10;
+    private static readonly pb::FieldCodec<int> _repeated_publicDependency_codec
+        = pb::FieldCodec.ForInt32(80);
+    private readonly pbc::RepeatedField<int> publicDependency_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Indexes of the public imported files in the dependency list above.
+    /// </summary>
+    public pbc::RepeatedField<int> PublicDependency {
+      get { return publicDependency_; }
+    }
+
+    /// <summary>Field number for the "weak_dependency" field.</summary>
+    public const int WeakDependencyFieldNumber = 11;
+    private static readonly pb::FieldCodec<int> _repeated_weakDependency_codec
+        = pb::FieldCodec.ForInt32(88);
+    private readonly pbc::RepeatedField<int> weakDependency_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Indexes of the weak imported files in the dependency list.
+    ///  For Google-internal migration only. Do not use.
+    /// </summary>
+    public pbc::RepeatedField<int> WeakDependency {
+      get { return weakDependency_; }
+    }
+
+    /// <summary>Field number for the "message_type" field.</summary>
+    public const int MessageTypeFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.DescriptorProto> _repeated_messageType_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Reflection.DescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> messageType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto>();
+    /// <summary>
+    ///  All top-level definitions in this file.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> MessageType {
+      get { return messageType_; }
+    }
+
+    /// <summary>Field number for the "enum_type" field.</summary>
+    public const int EnumTypeFieldNumber = 5;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.EnumDescriptorProto> _repeated_enumType_codec
+        = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> EnumType {
+      get { return enumType_; }
+    }
+
+    /// <summary>Field number for the "service" field.</summary>
+    public const int ServiceFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.ServiceDescriptorProto> _repeated_service_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto> service_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto> Service {
+      get { return service_; }
+    }
+
+    /// <summary>Field number for the "extension" field.</summary>
+    public const int ExtensionFieldNumber = 7;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.FieldDescriptorProto> _repeated_extension_codec
+        = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Extension {
+      get { return extension_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 8;
+    private global::Google.Protobuf.Reflection.FileOptions options_;
+    public global::Google.Protobuf.Reflection.FileOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "source_code_info" field.</summary>
+    public const int SourceCodeInfoFieldNumber = 9;
+    private global::Google.Protobuf.Reflection.SourceCodeInfo sourceCodeInfo_;
+    /// <summary>
+    ///  This field contains optional information about the original source code.
+    ///  You may safely remove this entire field without harming runtime
+    ///  functionality of the descriptors -- the information is needed only by
+    ///  development tools.
+    /// </summary>
+    public global::Google.Protobuf.Reflection.SourceCodeInfo SourceCodeInfo {
+      get { return sourceCodeInfo_; }
+      set {
+        sourceCodeInfo_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "syntax" field.</summary>
+    public const int SyntaxFieldNumber = 12;
+    private string syntax_ = "";
+    /// <summary>
+    ///  The syntax of the proto file.
+    ///  The supported values are "proto2" and "proto3".
+    /// </summary>
+    public string Syntax {
+      get { return syntax_; }
+      set {
+        syntax_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FileDescriptorProto);
+    }
+
+    public bool Equals(FileDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Package != other.Package) return false;
+      if(!dependency_.Equals(other.dependency_)) return false;
+      if(!publicDependency_.Equals(other.publicDependency_)) return false;
+      if(!weakDependency_.Equals(other.weakDependency_)) return false;
+      if(!messageType_.Equals(other.messageType_)) return false;
+      if(!enumType_.Equals(other.enumType_)) return false;
+      if(!service_.Equals(other.service_)) return false;
+      if(!extension_.Equals(other.extension_)) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false;
+      if (Syntax != other.Syntax) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Package.Length != 0) hash ^= Package.GetHashCode();
+      hash ^= dependency_.GetHashCode();
+      hash ^= publicDependency_.GetHashCode();
+      hash ^= weakDependency_.GetHashCode();
+      hash ^= messageType_.GetHashCode();
+      hash ^= enumType_.GetHashCode();
+      hash ^= service_.GetHashCode();
+      hash ^= extension_.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
+      if (Syntax.Length != 0) hash ^= Syntax.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Package.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Package);
+      }
+      dependency_.WriteTo(output, _repeated_dependency_codec);
+      messageType_.WriteTo(output, _repeated_messageType_codec);
+      enumType_.WriteTo(output, _repeated_enumType_codec);
+      service_.WriteTo(output, _repeated_service_codec);
+      extension_.WriteTo(output, _repeated_extension_codec);
+      if (options_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(Options);
+      }
+      if (sourceCodeInfo_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(SourceCodeInfo);
+      }
+      publicDependency_.WriteTo(output, _repeated_publicDependency_codec);
+      weakDependency_.WriteTo(output, _repeated_weakDependency_codec);
+      if (Syntax.Length != 0) {
+        output.WriteRawTag(98);
+        output.WriteString(Syntax);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Package.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Package);
+      }
+      size += dependency_.CalculateSize(_repeated_dependency_codec);
+      size += publicDependency_.CalculateSize(_repeated_publicDependency_codec);
+      size += weakDependency_.CalculateSize(_repeated_weakDependency_codec);
+      size += messageType_.CalculateSize(_repeated_messageType_codec);
+      size += enumType_.CalculateSize(_repeated_enumType_codec);
+      size += service_.CalculateSize(_repeated_service_codec);
+      size += extension_.CalculateSize(_repeated_extension_codec);
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      if (sourceCodeInfo_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceCodeInfo);
+      }
+      if (Syntax.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Syntax);
+      }
+      return size;
+    }
+
+    public void MergeFrom(FileDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Package.Length != 0) {
+        Package = other.Package;
+      }
+      dependency_.Add(other.dependency_);
+      publicDependency_.Add(other.publicDependency_);
+      weakDependency_.Add(other.weakDependency_);
+      messageType_.Add(other.messageType_);
+      enumType_.Add(other.enumType_);
+      service_.Add(other.service_);
+      extension_.Add(other.extension_);
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.FileOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+      if (other.sourceCodeInfo_ != null) {
+        if (sourceCodeInfo_ == null) {
+          sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo();
+        }
+        SourceCodeInfo.MergeFrom(other.SourceCodeInfo);
+      }
+      if (other.Syntax.Length != 0) {
+        Syntax = other.Syntax;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Package = input.ReadString();
+            break;
+          }
+          case 26: {
+            dependency_.AddEntriesFrom(input, _repeated_dependency_codec);
+            break;
+          }
+          case 34: {
+            messageType_.AddEntriesFrom(input, _repeated_messageType_codec);
+            break;
+          }
+          case 42: {
+            enumType_.AddEntriesFrom(input, _repeated_enumType_codec);
+            break;
+          }
+          case 50: {
+            service_.AddEntriesFrom(input, _repeated_service_codec);
+            break;
+          }
+          case 58: {
+            extension_.AddEntriesFrom(input, _repeated_extension_codec);
+            break;
+          }
+          case 66: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.FileOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+          case 74: {
+            if (sourceCodeInfo_ == null) {
+              sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo();
+            }
+            input.ReadMessage(sourceCodeInfo_);
+            break;
+          }
+          case 82:
+          case 80: {
+            publicDependency_.AddEntriesFrom(input, _repeated_publicDependency_codec);
+            break;
+          }
+          case 90:
+          case 88: {
+            weakDependency_.AddEntriesFrom(input, _repeated_weakDependency_codec);
+            break;
+          }
+          case 98: {
+            Syntax = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes a message type.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
+    private static readonly pb::MessageParser<DescriptorProto> _parser = new pb::MessageParser<DescriptorProto>(() => new DescriptorProto());
+    public static pb::MessageParser<DescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DescriptorProto(DescriptorProto other) : this() {
+      name_ = other.name_;
+      field_ = other.field_.Clone();
+      extension_ = other.extension_.Clone();
+      nestedType_ = other.nestedType_.Clone();
+      enumType_ = other.enumType_.Clone();
+      extensionRange_ = other.extensionRange_.Clone();
+      oneofDecl_ = other.oneofDecl_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      reservedRange_ = other.reservedRange_.Clone();
+      reservedName_ = other.reservedName_.Clone();
+    }
+
+    public DescriptorProto Clone() {
+      return new DescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "field" field.</summary>
+    public const int FieldFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.FieldDescriptorProto> _repeated_field_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> field_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Field {
+      get { return field_; }
+    }
+
+    /// <summary>Field number for the "extension" field.</summary>
+    public const int ExtensionFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.FieldDescriptorProto> _repeated_extension_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Extension {
+      get { return extension_; }
+    }
+
+    /// <summary>Field number for the "nested_type" field.</summary>
+    public const int NestedTypeFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.DescriptorProto> _repeated_nestedType_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.Reflection.DescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> nestedType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> NestedType {
+      get { return nestedType_; }
+    }
+
+    /// <summary>Field number for the "enum_type" field.</summary>
+    public const int EnumTypeFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.EnumDescriptorProto> _repeated_enumType_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> EnumType {
+      get { return enumType_; }
+    }
+
+    /// <summary>Field number for the "extension_range" field.</summary>
+    public const int ExtensionRangeFieldNumber = 5;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange> _repeated_extensionRange_codec
+        = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange> ExtensionRange {
+      get { return extensionRange_; }
+    }
+
+    /// <summary>Field number for the "oneof_decl" field.</summary>
+    public const int OneofDeclFieldNumber = 8;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.OneofDescriptorProto> _repeated_oneofDecl_codec
+        = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto> oneofDecl_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto> OneofDecl {
+      get { return oneofDecl_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 7;
+    private global::Google.Protobuf.Reflection.MessageOptions options_;
+    public global::Google.Protobuf.Reflection.MessageOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "reserved_range" field.</summary>
+    public const int ReservedRangeFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange> _repeated_reservedRange_codec
+        = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange> reservedRange_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange> ReservedRange {
+      get { return reservedRange_; }
+    }
+
+    /// <summary>Field number for the "reserved_name" field.</summary>
+    public const int ReservedNameFieldNumber = 10;
+    private static readonly pb::FieldCodec<string> _repeated_reservedName_codec
+        = pb::FieldCodec.ForString(82);
+    private readonly pbc::RepeatedField<string> reservedName_ = new pbc::RepeatedField<string>();
+    /// <summary>
+    ///  Reserved field names, which may not be used by fields in the same message.
+    ///  A given name may only be reserved once.
+    /// </summary>
+    public pbc::RepeatedField<string> ReservedName {
+      get { return reservedName_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DescriptorProto);
+    }
+
+    public bool Equals(DescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!field_.Equals(other.field_)) return false;
+      if(!extension_.Equals(other.extension_)) return false;
+      if(!nestedType_.Equals(other.nestedType_)) return false;
+      if(!enumType_.Equals(other.enumType_)) return false;
+      if(!extensionRange_.Equals(other.extensionRange_)) return false;
+      if(!oneofDecl_.Equals(other.oneofDecl_)) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      if(!reservedRange_.Equals(other.reservedRange_)) return false;
+      if(!reservedName_.Equals(other.reservedName_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= field_.GetHashCode();
+      hash ^= extension_.GetHashCode();
+      hash ^= nestedType_.GetHashCode();
+      hash ^= enumType_.GetHashCode();
+      hash ^= extensionRange_.GetHashCode();
+      hash ^= oneofDecl_.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      hash ^= reservedRange_.GetHashCode();
+      hash ^= reservedName_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      field_.WriteTo(output, _repeated_field_codec);
+      nestedType_.WriteTo(output, _repeated_nestedType_codec);
+      enumType_.WriteTo(output, _repeated_enumType_codec);
+      extensionRange_.WriteTo(output, _repeated_extensionRange_codec);
+      extension_.WriteTo(output, _repeated_extension_codec);
+      if (options_ != null) {
+        output.WriteRawTag(58);
+        output.WriteMessage(Options);
+      }
+      oneofDecl_.WriteTo(output, _repeated_oneofDecl_codec);
+      reservedRange_.WriteTo(output, _repeated_reservedRange_codec);
+      reservedName_.WriteTo(output, _repeated_reservedName_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += field_.CalculateSize(_repeated_field_codec);
+      size += extension_.CalculateSize(_repeated_extension_codec);
+      size += nestedType_.CalculateSize(_repeated_nestedType_codec);
+      size += enumType_.CalculateSize(_repeated_enumType_codec);
+      size += extensionRange_.CalculateSize(_repeated_extensionRange_codec);
+      size += oneofDecl_.CalculateSize(_repeated_oneofDecl_codec);
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
+      size += reservedName_.CalculateSize(_repeated_reservedName_codec);
+      return size;
+    }
+
+    public void MergeFrom(DescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      field_.Add(other.field_);
+      extension_.Add(other.extension_);
+      nestedType_.Add(other.nestedType_);
+      enumType_.Add(other.enumType_);
+      extensionRange_.Add(other.extensionRange_);
+      oneofDecl_.Add(other.oneofDecl_);
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.MessageOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+      reservedRange_.Add(other.reservedRange_);
+      reservedName_.Add(other.reservedName_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            field_.AddEntriesFrom(input, _repeated_field_codec);
+            break;
+          }
+          case 26: {
+            nestedType_.AddEntriesFrom(input, _repeated_nestedType_codec);
+            break;
+          }
+          case 34: {
+            enumType_.AddEntriesFrom(input, _repeated_enumType_codec);
+            break;
+          }
+          case 42: {
+            extensionRange_.AddEntriesFrom(input, _repeated_extensionRange_codec);
+            break;
+          }
+          case 50: {
+            extension_.AddEntriesFrom(input, _repeated_extension_codec);
+            break;
+          }
+          case 58: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.MessageOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+          case 66: {
+            oneofDecl_.AddEntriesFrom(input, _repeated_oneofDecl_codec);
+            break;
+          }
+          case 74: {
+            reservedRange_.AddEntriesFrom(input, _repeated_reservedRange_codec);
+            break;
+          }
+          case 82: {
+            reservedName_.AddEntriesFrom(input, _repeated_reservedName_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the DescriptorProto message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      internal sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
+        private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
+        public static pb::MessageParser<ExtensionRange> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public ExtensionRange() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public ExtensionRange(ExtensionRange other) : this() {
+          start_ = other.start_;
+          end_ = other.end_;
+        }
+
+        public ExtensionRange Clone() {
+          return new ExtensionRange(this);
+        }
+
+        /// <summary>Field number for the "start" field.</summary>
+        public const int StartFieldNumber = 1;
+        private int start_;
+        public int Start {
+          get { return start_; }
+          set {
+            start_ = value;
+          }
+        }
+
+        /// <summary>Field number for the "end" field.</summary>
+        public const int EndFieldNumber = 2;
+        private int end_;
+        public int End {
+          get { return end_; }
+          set {
+            end_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as ExtensionRange);
+        }
+
+        public bool Equals(ExtensionRange other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Start != other.Start) return false;
+          if (End != other.End) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Start != 0) hash ^= Start.GetHashCode();
+          if (End != 0) hash ^= End.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Start != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Start);
+          }
+          if (End != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(End);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Start != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start);
+          }
+          if (End != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
+          }
+          return size;
+        }
+
+        public void MergeFrom(ExtensionRange other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Start != 0) {
+            Start = other.Start;
+          }
+          if (other.End != 0) {
+            End = other.End;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Start = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      /// <summary>
+      ///  Range of reserved tag numbers. Reserved tag numbers may not be used by
+      ///  fields or extension ranges in the same message. Reserved ranges may
+      ///  not overlap.
+      /// </summary>
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      internal sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
+        private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
+        public static pb::MessageParser<ReservedRange> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[1]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public ReservedRange() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public ReservedRange(ReservedRange other) : this() {
+          start_ = other.start_;
+          end_ = other.end_;
+        }
+
+        public ReservedRange Clone() {
+          return new ReservedRange(this);
+        }
+
+        /// <summary>Field number for the "start" field.</summary>
+        public const int StartFieldNumber = 1;
+        private int start_;
+        /// <summary>
+        ///  Inclusive.
+        /// </summary>
+        public int Start {
+          get { return start_; }
+          set {
+            start_ = value;
+          }
+        }
+
+        /// <summary>Field number for the "end" field.</summary>
+        public const int EndFieldNumber = 2;
+        private int end_;
+        /// <summary>
+        ///  Exclusive.
+        /// </summary>
+        public int End {
+          get { return end_; }
+          set {
+            end_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as ReservedRange);
+        }
+
+        public bool Equals(ReservedRange other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Start != other.Start) return false;
+          if (End != other.End) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Start != 0) hash ^= Start.GetHashCode();
+          if (End != 0) hash ^= End.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Start != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Start);
+          }
+          if (End != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(End);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Start != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start);
+          }
+          if (End != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
+          }
+          return size;
+        }
+
+        public void MergeFrom(ReservedRange other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Start != 0) {
+            Start = other.Start;
+          }
+          if (other.End != 0) {
+            End = other.End;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Start = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Describes a field within a message.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
+    private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
+    public static pb::MessageParser<FieldDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FieldDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FieldDescriptorProto(FieldDescriptorProto other) : this() {
+      name_ = other.name_;
+      number_ = other.number_;
+      label_ = other.label_;
+      type_ = other.type_;
+      typeName_ = other.typeName_;
+      extendee_ = other.extendee_;
+      defaultValue_ = other.defaultValue_;
+      oneofIndex_ = other.oneofIndex_;
+      jsonName_ = other.jsonName_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public FieldDescriptorProto Clone() {
+      return new FieldDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "number" field.</summary>
+    public const int NumberFieldNumber = 3;
+    private int number_;
+    public int Number {
+      get { return number_; }
+      set {
+        number_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "label" field.</summary>
+    public const int LabelFieldNumber = 4;
+    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_ = 0;
+    public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label Label {
+      get { return label_; }
+      set {
+        label_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "type" field.</summary>
+    public const int TypeFieldNumber = 5;
+    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_ = 0;
+    /// <summary>
+    ///  If type_name is set, this need not be set.  If both this and type_name
+    ///  are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+    /// </summary>
+    public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type Type {
+      get { return type_; }
+      set {
+        type_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "type_name" field.</summary>
+    public const int TypeNameFieldNumber = 6;
+    private string typeName_ = "";
+    /// <summary>
+    ///  For message and enum types, this is the name of the type.  If the name
+    ///  starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+    ///  rules are used to find the type (i.e. first the nested types within this
+    ///  message are searched, then within the parent, on up to the root
+    ///  namespace).
+    /// </summary>
+    public string TypeName {
+      get { return typeName_; }
+      set {
+        typeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "extendee" field.</summary>
+    public const int ExtendeeFieldNumber = 2;
+    private string extendee_ = "";
+    /// <summary>
+    ///  For extensions, this is the name of the type being extended.  It is
+    ///  resolved in the same manner as type_name.
+    /// </summary>
+    public string Extendee {
+      get { return extendee_; }
+      set {
+        extendee_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "default_value" field.</summary>
+    public const int DefaultValueFieldNumber = 7;
+    private string defaultValue_ = "";
+    /// <summary>
+    ///  For numeric types, contains the original text representation of the value.
+    ///  For booleans, "true" or "false".
+    ///  For strings, contains the default text contents (not escaped in any way).
+    ///  For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+    ///  TODO(kenton):  Base-64 encode?
+    /// </summary>
+    public string DefaultValue {
+      get { return defaultValue_; }
+      set {
+        defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "oneof_index" field.</summary>
+    public const int OneofIndexFieldNumber = 9;
+    private int oneofIndex_;
+    /// <summary>
+    ///  If set, gives the index of a oneof in the containing type's oneof_decl
+    ///  list.  This field is a member of that oneof.
+    /// </summary>
+    public int OneofIndex {
+      get { return oneofIndex_; }
+      set {
+        oneofIndex_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "json_name" field.</summary>
+    public const int JsonNameFieldNumber = 10;
+    private string jsonName_ = "";
+    /// <summary>
+    ///  JSON name of this field. The value is set by protocol compiler. If the
+    ///  user has set a "json_name" option on this field, that option's value
+    ///  will be used. Otherwise, it's deduced from the field's name by converting
+    ///  it to camelCase.
+    /// </summary>
+    public string JsonName {
+      get { return jsonName_; }
+      set {
+        jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 8;
+    private global::Google.Protobuf.Reflection.FieldOptions options_;
+    public global::Google.Protobuf.Reflection.FieldOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FieldDescriptorProto);
+    }
+
+    public bool Equals(FieldDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Number != other.Number) return false;
+      if (Label != other.Label) return false;
+      if (Type != other.Type) return false;
+      if (TypeName != other.TypeName) return false;
+      if (Extendee != other.Extendee) return false;
+      if (DefaultValue != other.DefaultValue) return false;
+      if (OneofIndex != other.OneofIndex) return false;
+      if (JsonName != other.JsonName) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Number != 0) hash ^= Number.GetHashCode();
+      if (Label != 0) hash ^= Label.GetHashCode();
+      if (Type != 0) hash ^= Type.GetHashCode();
+      if (TypeName.Length != 0) hash ^= TypeName.GetHashCode();
+      if (Extendee.Length != 0) hash ^= Extendee.GetHashCode();
+      if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
+      if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode();
+      if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Extendee.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Extendee);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Number);
+      }
+      if (Label != 0) {
+        output.WriteRawTag(32);
+        output.WriteEnum((int) Label);
+      }
+      if (Type != 0) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) Type);
+      }
+      if (TypeName.Length != 0) {
+        output.WriteRawTag(50);
+        output.WriteString(TypeName);
+      }
+      if (DefaultValue.Length != 0) {
+        output.WriteRawTag(58);
+        output.WriteString(DefaultValue);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(Options);
+      }
+      if (OneofIndex != 0) {
+        output.WriteRawTag(72);
+        output.WriteInt32(OneofIndex);
+      }
+      if (JsonName.Length != 0) {
+        output.WriteRawTag(82);
+        output.WriteString(JsonName);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Number != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
+      }
+      if (Label != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Label);
+      }
+      if (Type != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
+      }
+      if (TypeName.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeName);
+      }
+      if (Extendee.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Extendee);
+      }
+      if (DefaultValue.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
+      }
+      if (OneofIndex != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofIndex);
+      }
+      if (JsonName.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
+      }
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      return size;
+    }
+
+    public void MergeFrom(FieldDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Number != 0) {
+        Number = other.Number;
+      }
+      if (other.Label != 0) {
+        Label = other.Label;
+      }
+      if (other.Type != 0) {
+        Type = other.Type;
+      }
+      if (other.TypeName.Length != 0) {
+        TypeName = other.TypeName;
+      }
+      if (other.Extendee.Length != 0) {
+        Extendee = other.Extendee;
+      }
+      if (other.DefaultValue.Length != 0) {
+        DefaultValue = other.DefaultValue;
+      }
+      if (other.OneofIndex != 0) {
+        OneofIndex = other.OneofIndex;
+      }
+      if (other.JsonName.Length != 0) {
+        JsonName = other.JsonName;
+      }
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.FieldOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Extendee = input.ReadString();
+            break;
+          }
+          case 24: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            label_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum();
+            break;
+          }
+          case 40: {
+            type_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum();
+            break;
+          }
+          case 50: {
+            TypeName = input.ReadString();
+            break;
+          }
+          case 58: {
+            DefaultValue = input.ReadString();
+            break;
+          }
+          case 66: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.FieldOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+          case 72: {
+            OneofIndex = input.ReadInt32();
+            break;
+          }
+          case 82: {
+            JsonName = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the FieldDescriptorProto message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      internal enum Type {
+        /// <summary>
+        ///  0 is reserved for errors.
+        ///  Order is weird for historical reasons.
+        /// </summary>
+        [pbr::OriginalName("TYPE_DOUBLE")] Double = 1,
+        [pbr::OriginalName("TYPE_FLOAT")] Float = 2,
+        /// <summary>
+        ///  Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+        ///  negative values are likely.
+        /// </summary>
+        [pbr::OriginalName("TYPE_INT64")] Int64 = 3,
+        [pbr::OriginalName("TYPE_UINT64")] Uint64 = 4,
+        /// <summary>
+        ///  Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+        ///  negative values are likely.
+        /// </summary>
+        [pbr::OriginalName("TYPE_INT32")] Int32 = 5,
+        [pbr::OriginalName("TYPE_FIXED64")] Fixed64 = 6,
+        [pbr::OriginalName("TYPE_FIXED32")] Fixed32 = 7,
+        [pbr::OriginalName("TYPE_BOOL")] Bool = 8,
+        [pbr::OriginalName("TYPE_STRING")] String = 9,
+        /// <summary>
+        ///  Tag-delimited aggregate.
+        /// </summary>
+        [pbr::OriginalName("TYPE_GROUP")] Group = 10,
+        /// <summary>
+        ///  Length-delimited aggregate.
+        /// </summary>
+        [pbr::OriginalName("TYPE_MESSAGE")] Message = 11,
+        /// <summary>
+        ///  New in version 2.
+        /// </summary>
+        [pbr::OriginalName("TYPE_BYTES")] Bytes = 12,
+        [pbr::OriginalName("TYPE_UINT32")] Uint32 = 13,
+        [pbr::OriginalName("TYPE_ENUM")] Enum = 14,
+        [pbr::OriginalName("TYPE_SFIXED32")] Sfixed32 = 15,
+        [pbr::OriginalName("TYPE_SFIXED64")] Sfixed64 = 16,
+        /// <summary>
+        ///  Uses ZigZag encoding.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SINT32")] Sint32 = 17,
+        /// <summary>
+        ///  Uses ZigZag encoding.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SINT64")] Sint64 = 18,
+      }
+
+      internal enum Label {
+        /// <summary>
+        ///  0 is reserved for errors
+        /// </summary>
+        [pbr::OriginalName("LABEL_OPTIONAL")] Optional = 1,
+        [pbr::OriginalName("LABEL_REQUIRED")] Required = 2,
+        /// <summary>
+        ///  TODO(sanjay): Should we add LABEL_MAP?
+        /// </summary>
+        [pbr::OriginalName("LABEL_REPEATED")] Repeated = 3,
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Describes a oneof.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
+    private static readonly pb::MessageParser<OneofDescriptorProto> _parser = new pb::MessageParser<OneofDescriptorProto>(() => new OneofDescriptorProto());
+    public static pb::MessageParser<OneofDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneofDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneofDescriptorProto(OneofDescriptorProto other) : this() {
+      name_ = other.name_;
+    }
+
+    public OneofDescriptorProto Clone() {
+      return new OneofDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneofDescriptorProto);
+    }
+
+    public bool Equals(OneofDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneofDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes an enum type.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
+    private static readonly pb::MessageParser<EnumDescriptorProto> _parser = new pb::MessageParser<EnumDescriptorProto>(() => new EnumDescriptorProto());
+    public static pb::MessageParser<EnumDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EnumDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EnumDescriptorProto(EnumDescriptorProto other) : this() {
+      name_ = other.name_;
+      value_ = other.value_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public EnumDescriptorProto Clone() {
+      return new EnumDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.EnumValueDescriptorProto> _repeated_value_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto> value_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto> Value {
+      get { return value_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private global::Google.Protobuf.Reflection.EnumOptions options_;
+    public global::Google.Protobuf.Reflection.EnumOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EnumDescriptorProto);
+    }
+
+    public bool Equals(EnumDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!value_.Equals(other.value_)) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= value_.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      value_.WriteTo(output, _repeated_value_codec);
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += value_.CalculateSize(_repeated_value_codec);
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      return size;
+    }
+
+    public void MergeFrom(EnumDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      value_.Add(other.value_);
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.EnumOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            value_.AddEntriesFrom(input, _repeated_value_codec);
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.EnumOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes a value within an enum.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
+    private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
+    public static pb::MessageParser<EnumValueDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EnumValueDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EnumValueDescriptorProto(EnumValueDescriptorProto other) : this() {
+      name_ = other.name_;
+      number_ = other.number_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public EnumValueDescriptorProto Clone() {
+      return new EnumValueDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "number" field.</summary>
+    public const int NumberFieldNumber = 2;
+    private int number_;
+    public int Number {
+      get { return number_; }
+      set {
+        number_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private global::Google.Protobuf.Reflection.EnumValueOptions options_;
+    public global::Google.Protobuf.Reflection.EnumValueOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EnumValueDescriptorProto);
+    }
+
+    public bool Equals(EnumValueDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Number != other.Number) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Number != 0) hash ^= Number.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Number);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Number != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
+      }
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      return size;
+    }
+
+    public void MergeFrom(EnumValueDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Number != 0) {
+        Number = other.Number;
+      }
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.EnumValueOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.EnumValueOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes a service.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
+    private static readonly pb::MessageParser<ServiceDescriptorProto> _parser = new pb::MessageParser<ServiceDescriptorProto>(() => new ServiceDescriptorProto());
+    public static pb::MessageParser<ServiceDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServiceDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServiceDescriptorProto(ServiceDescriptorProto other) : this() {
+      name_ = other.name_;
+      method_ = other.method_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public ServiceDescriptorProto Clone() {
+      return new ServiceDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "method" field.</summary>
+    public const int MethodFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.MethodDescriptorProto> _repeated_method_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto> method_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto> Method {
+      get { return method_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private global::Google.Protobuf.Reflection.ServiceOptions options_;
+    public global::Google.Protobuf.Reflection.ServiceOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServiceDescriptorProto);
+    }
+
+    public bool Equals(ServiceDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!method_.Equals(other.method_)) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= method_.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      method_.WriteTo(output, _repeated_method_codec);
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += method_.CalculateSize(_repeated_method_codec);
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ServiceDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      method_.Add(other.method_);
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.ServiceOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            method_.AddEntriesFrom(input, _repeated_method_codec);
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.ServiceOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Describes a method of a service.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
+    private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
+    public static pb::MessageParser<MethodDescriptorProto> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[8]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MethodDescriptorProto() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MethodDescriptorProto(MethodDescriptorProto other) : this() {
+      name_ = other.name_;
+      inputType_ = other.inputType_;
+      outputType_ = other.outputType_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      clientStreaming_ = other.clientStreaming_;
+      serverStreaming_ = other.serverStreaming_;
+    }
+
+    public MethodDescriptorProto Clone() {
+      return new MethodDescriptorProto(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "input_type" field.</summary>
+    public const int InputTypeFieldNumber = 2;
+    private string inputType_ = "";
+    /// <summary>
+    ///  Input and output type names.  These are resolved in the same way as
+    ///  FieldDescriptorProto.type_name, but must refer to a message type.
+    /// </summary>
+    public string InputType {
+      get { return inputType_; }
+      set {
+        inputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "output_type" field.</summary>
+    public const int OutputTypeFieldNumber = 3;
+    private string outputType_ = "";
+    public string OutputType {
+      get { return outputType_; }
+      set {
+        outputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 4;
+    private global::Google.Protobuf.Reflection.MethodOptions options_;
+    public global::Google.Protobuf.Reflection.MethodOptions Options {
+      get { return options_; }
+      set {
+        options_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "client_streaming" field.</summary>
+    public const int ClientStreamingFieldNumber = 5;
+    private bool clientStreaming_;
+    /// <summary>
+    ///  Identifies if client streams multiple client messages
+    /// </summary>
+    public bool ClientStreaming {
+      get { return clientStreaming_; }
+      set {
+        clientStreaming_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "server_streaming" field.</summary>
+    public const int ServerStreamingFieldNumber = 6;
+    private bool serverStreaming_;
+    /// <summary>
+    ///  Identifies if server streams multiple server messages
+    /// </summary>
+    public bool ServerStreaming {
+      get { return serverStreaming_; }
+      set {
+        serverStreaming_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MethodDescriptorProto);
+    }
+
+    public bool Equals(MethodDescriptorProto other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (InputType != other.InputType) return false;
+      if (OutputType != other.OutputType) return false;
+      if (!object.Equals(Options, other.Options)) return false;
+      if (ClientStreaming != other.ClientStreaming) return false;
+      if (ServerStreaming != other.ServerStreaming) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (InputType.Length != 0) hash ^= InputType.GetHashCode();
+      if (OutputType.Length != 0) hash ^= OutputType.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      if (ClientStreaming != false) hash ^= ClientStreaming.GetHashCode();
+      if (ServerStreaming != false) hash ^= ServerStreaming.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (InputType.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(InputType);
+      }
+      if (OutputType.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(OutputType);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(Options);
+      }
+      if (ClientStreaming != false) {
+        output.WriteRawTag(40);
+        output.WriteBool(ClientStreaming);
+      }
+      if (ServerStreaming != false) {
+        output.WriteRawTag(48);
+        output.WriteBool(ServerStreaming);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (InputType.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(InputType);
+      }
+      if (OutputType.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OutputType);
+      }
+      if (options_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+      }
+      if (ClientStreaming != false) {
+        size += 1 + 1;
+      }
+      if (ServerStreaming != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(MethodDescriptorProto other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.InputType.Length != 0) {
+        InputType = other.InputType;
+      }
+      if (other.OutputType.Length != 0) {
+        OutputType = other.OutputType;
+      }
+      if (other.options_ != null) {
+        if (options_ == null) {
+          options_ = new global::Google.Protobuf.Reflection.MethodOptions();
+        }
+        Options.MergeFrom(other.Options);
+      }
+      if (other.ClientStreaming != false) {
+        ClientStreaming = other.ClientStreaming;
+      }
+      if (other.ServerStreaming != false) {
+        ServerStreaming = other.ServerStreaming;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            InputType = input.ReadString();
+            break;
+          }
+          case 26: {
+            OutputType = input.ReadString();
+            break;
+          }
+          case 34: {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.MethodOptions();
+            }
+            input.ReadMessage(options_);
+            break;
+          }
+          case 40: {
+            ClientStreaming = input.ReadBool();
+            break;
+          }
+          case 48: {
+            ServerStreaming = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class FileOptions : pb::IMessage<FileOptions> {
+    private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
+    public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[9]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FileOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FileOptions(FileOptions other) : this() {
+      javaPackage_ = other.javaPackage_;
+      javaOuterClassname_ = other.javaOuterClassname_;
+      javaMultipleFiles_ = other.javaMultipleFiles_;
+      javaGenerateEqualsAndHash_ = other.javaGenerateEqualsAndHash_;
+      javaStringCheckUtf8_ = other.javaStringCheckUtf8_;
+      optimizeFor_ = other.optimizeFor_;
+      goPackage_ = other.goPackage_;
+      ccGenericServices_ = other.ccGenericServices_;
+      javaGenericServices_ = other.javaGenericServices_;
+      pyGenericServices_ = other.pyGenericServices_;
+      deprecated_ = other.deprecated_;
+      ccEnableArenas_ = other.ccEnableArenas_;
+      objcClassPrefix_ = other.objcClassPrefix_;
+      csharpNamespace_ = other.csharpNamespace_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public FileOptions Clone() {
+      return new FileOptions(this);
+    }
+
+    /// <summary>Field number for the "java_package" field.</summary>
+    public const int JavaPackageFieldNumber = 1;
+    private string javaPackage_ = "";
+    /// <summary>
+    ///  Sets the Java package where classes generated from this .proto will be
+    ///  placed.  By default, the proto package is used, but this is often
+    ///  inappropriate because proto packages do not normally start with backwards
+    ///  domain names.
+    /// </summary>
+    public string JavaPackage {
+      get { return javaPackage_; }
+      set {
+        javaPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "java_outer_classname" field.</summary>
+    public const int JavaOuterClassnameFieldNumber = 8;
+    private string javaOuterClassname_ = "";
+    /// <summary>
+    ///  If set, all the classes from the .proto file are wrapped in a single
+    ///  outer class with the given name.  This applies to both Proto1
+    ///  (equivalent to the old "--one_java_file" option) and Proto2 (where
+    ///  a .proto always translates to a single class, but you may want to
+    ///  explicitly choose the class name).
+    /// </summary>
+    public string JavaOuterClassname {
+      get { return javaOuterClassname_; }
+      set {
+        javaOuterClassname_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "java_multiple_files" field.</summary>
+    public const int JavaMultipleFilesFieldNumber = 10;
+    private bool javaMultipleFiles_;
+    /// <summary>
+    ///  If set true, then the Java code generator will generate a separate .java
+    ///  file for each top-level message, enum, and service defined in the .proto
+    ///  file.  Thus, these types will *not* be nested inside the outer class
+    ///  named by java_outer_classname.  However, the outer class will still be
+    ///  generated to contain the file's getDescriptor() method as well as any
+    ///  top-level extensions defined in the file.
+    /// </summary>
+    public bool JavaMultipleFiles {
+      get { return javaMultipleFiles_; }
+      set {
+        javaMultipleFiles_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "java_generate_equals_and_hash" field.</summary>
+    public const int JavaGenerateEqualsAndHashFieldNumber = 20;
+    private bool javaGenerateEqualsAndHash_;
+    /// <summary>
+    ///  If set true, then the Java code generator will generate equals() and
+    ///  hashCode() methods for all messages defined in the .proto file.
+    ///  This increases generated code size, potentially substantially for large
+    ///  protos, which may harm a memory-constrained application.
+    ///  - In the full runtime this is a speed optimization, as the
+    ///  AbstractMessage base class includes reflection-based implementations of
+    ///  these methods.
+    ///  - In the lite runtime, setting this option changes the semantics of
+    ///  equals() and hashCode() to more closely match those of the full runtime;
+    ///  the generated methods compute their results based on field values rather
+    ///  than object identity. (Implementations should not assume that hashcodes
+    ///  will be consistent across runtimes or versions of the protocol compiler.)
+    /// </summary>
+    public bool JavaGenerateEqualsAndHash {
+      get { return javaGenerateEqualsAndHash_; }
+      set {
+        javaGenerateEqualsAndHash_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "java_string_check_utf8" field.</summary>
+    public const int JavaStringCheckUtf8FieldNumber = 27;
+    private bool javaStringCheckUtf8_;
+    /// <summary>
+    ///  If set true, then the Java2 code generator will generate code that
+    ///  throws an exception whenever an attempt is made to assign a non-UTF-8
+    ///  byte sequence to a string field.
+    ///  Message reflection will do the same.
+    ///  However, an extension field still accepts non-UTF-8 byte sequences.
+    ///  This option has no effect on when used with the lite runtime.
+    /// </summary>
+    public bool JavaStringCheckUtf8 {
+      get { return javaStringCheckUtf8_; }
+      set {
+        javaStringCheckUtf8_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optimize_for" field.</summary>
+    public const int OptimizeForFieldNumber = 9;
+    private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_ = 0;
+    public global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeFor {
+      get { return optimizeFor_; }
+      set {
+        optimizeFor_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "go_package" field.</summary>
+    public const int GoPackageFieldNumber = 11;
+    private string goPackage_ = "";
+    /// <summary>
+    ///  Sets the Go package where structs generated from this .proto will be
+    ///  placed. If omitted, the Go package will be derived from the following:
+    ///    - The basename of the package import path, if provided.
+    ///    - Otherwise, the package statement in the .proto file, if present.
+    ///    - Otherwise, the basename of the .proto file, without extension.
+    /// </summary>
+    public string GoPackage {
+      get { return goPackage_; }
+      set {
+        goPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "cc_generic_services" field.</summary>
+    public const int CcGenericServicesFieldNumber = 16;
+    private bool ccGenericServices_;
+    /// <summary>
+    ///  Should generic services be generated in each language?  "Generic" services
+    ///  are not specific to any particular RPC system.  They are generated by the
+    ///  main code generators in each language (without additional plugins).
+    ///  Generic services were the only kind of service generation supported by
+    ///  early versions of google.protobuf.
+    ///
+    ///  Generic services are now considered deprecated in favor of using plugins
+    ///  that generate code specific to your particular RPC system.  Therefore,
+    ///  these default to false.  Old code which depends on generic services should
+    ///  explicitly set them to true.
+    /// </summary>
+    public bool CcGenericServices {
+      get { return ccGenericServices_; }
+      set {
+        ccGenericServices_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "java_generic_services" field.</summary>
+    public const int JavaGenericServicesFieldNumber = 17;
+    private bool javaGenericServices_;
+    public bool JavaGenericServices {
+      get { return javaGenericServices_; }
+      set {
+        javaGenericServices_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "py_generic_services" field.</summary>
+    public const int PyGenericServicesFieldNumber = 18;
+    private bool pyGenericServices_;
+    public bool PyGenericServices {
+      get { return pyGenericServices_; }
+      set {
+        pyGenericServices_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 23;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this file deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for everything in the file, or it will be completely ignored; in the very
+    ///  least, this is a formalization for deprecating files.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "cc_enable_arenas" field.</summary>
+    public const int CcEnableArenasFieldNumber = 31;
+    private bool ccEnableArenas_;
+    /// <summary>
+    ///  Enables the use of arenas for the proto messages in this file. This applies
+    ///  only to generated classes for C++.
+    /// </summary>
+    public bool CcEnableArenas {
+      get { return ccEnableArenas_; }
+      set {
+        ccEnableArenas_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "objc_class_prefix" field.</summary>
+    public const int ObjcClassPrefixFieldNumber = 36;
+    private string objcClassPrefix_ = "";
+    /// <summary>
+    ///  Sets the objective c class prefix which is prepended to all objective c
+    ///  generated classes from this .proto. There is no default.
+    /// </summary>
+    public string ObjcClassPrefix {
+      get { return objcClassPrefix_; }
+      set {
+        objcClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "csharp_namespace" field.</summary>
+    public const int CsharpNamespaceFieldNumber = 37;
+    private string csharpNamespace_ = "";
+    /// <summary>
+    ///  Namespace for generated classes; defaults to the package.
+    /// </summary>
+    public string CsharpNamespace {
+      get { return csharpNamespace_; }
+      set {
+        csharpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FileOptions);
+    }
+
+    public bool Equals(FileOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (JavaPackage != other.JavaPackage) return false;
+      if (JavaOuterClassname != other.JavaOuterClassname) return false;
+      if (JavaMultipleFiles != other.JavaMultipleFiles) return false;
+      if (JavaGenerateEqualsAndHash != other.JavaGenerateEqualsAndHash) return false;
+      if (JavaStringCheckUtf8 != other.JavaStringCheckUtf8) return false;
+      if (OptimizeFor != other.OptimizeFor) return false;
+      if (GoPackage != other.GoPackage) return false;
+      if (CcGenericServices != other.CcGenericServices) return false;
+      if (JavaGenericServices != other.JavaGenericServices) return false;
+      if (PyGenericServices != other.PyGenericServices) return false;
+      if (Deprecated != other.Deprecated) return false;
+      if (CcEnableArenas != other.CcEnableArenas) return false;
+      if (ObjcClassPrefix != other.ObjcClassPrefix) return false;
+      if (CsharpNamespace != other.CsharpNamespace) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (JavaPackage.Length != 0) hash ^= JavaPackage.GetHashCode();
+      if (JavaOuterClassname.Length != 0) hash ^= JavaOuterClassname.GetHashCode();
+      if (JavaMultipleFiles != false) hash ^= JavaMultipleFiles.GetHashCode();
+      if (JavaGenerateEqualsAndHash != false) hash ^= JavaGenerateEqualsAndHash.GetHashCode();
+      if (JavaStringCheckUtf8 != false) hash ^= JavaStringCheckUtf8.GetHashCode();
+      if (OptimizeFor != 0) hash ^= OptimizeFor.GetHashCode();
+      if (GoPackage.Length != 0) hash ^= GoPackage.GetHashCode();
+      if (CcGenericServices != false) hash ^= CcGenericServices.GetHashCode();
+      if (JavaGenericServices != false) hash ^= JavaGenericServices.GetHashCode();
+      if (PyGenericServices != false) hash ^= PyGenericServices.GetHashCode();
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (CcEnableArenas != false) hash ^= CcEnableArenas.GetHashCode();
+      if (ObjcClassPrefix.Length != 0) hash ^= ObjcClassPrefix.GetHashCode();
+      if (CsharpNamespace.Length != 0) hash ^= CsharpNamespace.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (JavaPackage.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(JavaPackage);
+      }
+      if (JavaOuterClassname.Length != 0) {
+        output.WriteRawTag(66);
+        output.WriteString(JavaOuterClassname);
+      }
+      if (OptimizeFor != 0) {
+        output.WriteRawTag(72);
+        output.WriteEnum((int) OptimizeFor);
+      }
+      if (JavaMultipleFiles != false) {
+        output.WriteRawTag(80);
+        output.WriteBool(JavaMultipleFiles);
+      }
+      if (GoPackage.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(GoPackage);
+      }
+      if (CcGenericServices != false) {
+        output.WriteRawTag(128, 1);
+        output.WriteBool(CcGenericServices);
+      }
+      if (JavaGenericServices != false) {
+        output.WriteRawTag(136, 1);
+        output.WriteBool(JavaGenericServices);
+      }
+      if (PyGenericServices != false) {
+        output.WriteRawTag(144, 1);
+        output.WriteBool(PyGenericServices);
+      }
+      if (JavaGenerateEqualsAndHash != false) {
+        output.WriteRawTag(160, 1);
+        output.WriteBool(JavaGenerateEqualsAndHash);
+      }
+      if (Deprecated != false) {
+        output.WriteRawTag(184, 1);
+        output.WriteBool(Deprecated);
+      }
+      if (JavaStringCheckUtf8 != false) {
+        output.WriteRawTag(216, 1);
+        output.WriteBool(JavaStringCheckUtf8);
+      }
+      if (CcEnableArenas != false) {
+        output.WriteRawTag(248, 1);
+        output.WriteBool(CcEnableArenas);
+      }
+      if (ObjcClassPrefix.Length != 0) {
+        output.WriteRawTag(162, 2);
+        output.WriteString(ObjcClassPrefix);
+      }
+      if (CsharpNamespace.Length != 0) {
+        output.WriteRawTag(170, 2);
+        output.WriteString(CsharpNamespace);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (JavaPackage.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaPackage);
+      }
+      if (JavaOuterClassname.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaOuterClassname);
+      }
+      if (JavaMultipleFiles != false) {
+        size += 1 + 1;
+      }
+      if (JavaGenerateEqualsAndHash != false) {
+        size += 2 + 1;
+      }
+      if (JavaStringCheckUtf8 != false) {
+        size += 2 + 1;
+      }
+      if (OptimizeFor != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) OptimizeFor);
+      }
+      if (GoPackage.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(GoPackage);
+      }
+      if (CcGenericServices != false) {
+        size += 2 + 1;
+      }
+      if (JavaGenericServices != false) {
+        size += 2 + 1;
+      }
+      if (PyGenericServices != false) {
+        size += 2 + 1;
+      }
+      if (Deprecated != false) {
+        size += 2 + 1;
+      }
+      if (CcEnableArenas != false) {
+        size += 2 + 1;
+      }
+      if (ObjcClassPrefix.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(ObjcClassPrefix);
+      }
+      if (CsharpNamespace.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(CsharpNamespace);
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(FileOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.JavaPackage.Length != 0) {
+        JavaPackage = other.JavaPackage;
+      }
+      if (other.JavaOuterClassname.Length != 0) {
+        JavaOuterClassname = other.JavaOuterClassname;
+      }
+      if (other.JavaMultipleFiles != false) {
+        JavaMultipleFiles = other.JavaMultipleFiles;
+      }
+      if (other.JavaGenerateEqualsAndHash != false) {
+        JavaGenerateEqualsAndHash = other.JavaGenerateEqualsAndHash;
+      }
+      if (other.JavaStringCheckUtf8 != false) {
+        JavaStringCheckUtf8 = other.JavaStringCheckUtf8;
+      }
+      if (other.OptimizeFor != 0) {
+        OptimizeFor = other.OptimizeFor;
+      }
+      if (other.GoPackage.Length != 0) {
+        GoPackage = other.GoPackage;
+      }
+      if (other.CcGenericServices != false) {
+        CcGenericServices = other.CcGenericServices;
+      }
+      if (other.JavaGenericServices != false) {
+        JavaGenericServices = other.JavaGenericServices;
+      }
+      if (other.PyGenericServices != false) {
+        PyGenericServices = other.PyGenericServices;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      if (other.CcEnableArenas != false) {
+        CcEnableArenas = other.CcEnableArenas;
+      }
+      if (other.ObjcClassPrefix.Length != 0) {
+        ObjcClassPrefix = other.ObjcClassPrefix;
+      }
+      if (other.CsharpNamespace.Length != 0) {
+        CsharpNamespace = other.CsharpNamespace;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            JavaPackage = input.ReadString();
+            break;
+          }
+          case 66: {
+            JavaOuterClassname = input.ReadString();
+            break;
+          }
+          case 72: {
+            optimizeFor_ = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum();
+            break;
+          }
+          case 80: {
+            JavaMultipleFiles = input.ReadBool();
+            break;
+          }
+          case 90: {
+            GoPackage = input.ReadString();
+            break;
+          }
+          case 128: {
+            CcGenericServices = input.ReadBool();
+            break;
+          }
+          case 136: {
+            JavaGenericServices = input.ReadBool();
+            break;
+          }
+          case 144: {
+            PyGenericServices = input.ReadBool();
+            break;
+          }
+          case 160: {
+            JavaGenerateEqualsAndHash = input.ReadBool();
+            break;
+          }
+          case 184: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 216: {
+            JavaStringCheckUtf8 = input.ReadBool();
+            break;
+          }
+          case 248: {
+            CcEnableArenas = input.ReadBool();
+            break;
+          }
+          case 290: {
+            ObjcClassPrefix = input.ReadString();
+            break;
+          }
+          case 298: {
+            CsharpNamespace = input.ReadString();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the FileOptions message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      /// <summary>
+      ///  Generated classes can be optimized for speed or code size.
+      /// </summary>
+      internal enum OptimizeMode {
+        /// <summary>
+        ///  Generate complete code for parsing, serialization,
+        /// </summary>
+        [pbr::OriginalName("SPEED")] Speed = 1,
+        /// <summary>
+        ///  etc.
+        /// </summary>
+        [pbr::OriginalName("CODE_SIZE")] CodeSize = 2,
+        /// <summary>
+        ///  Generate code using MessageLite and the lite runtime.
+        /// </summary>
+        [pbr::OriginalName("LITE_RUNTIME")] LiteRuntime = 3,
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class MessageOptions : pb::IMessage<MessageOptions> {
+    private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
+    public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[10]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MessageOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MessageOptions(MessageOptions other) : this() {
+      messageSetWireFormat_ = other.messageSetWireFormat_;
+      noStandardDescriptorAccessor_ = other.noStandardDescriptorAccessor_;
+      deprecated_ = other.deprecated_;
+      mapEntry_ = other.mapEntry_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public MessageOptions Clone() {
+      return new MessageOptions(this);
+    }
+
+    /// <summary>Field number for the "message_set_wire_format" field.</summary>
+    public const int MessageSetWireFormatFieldNumber = 1;
+    private bool messageSetWireFormat_;
+    /// <summary>
+    ///  Set true to use the old proto1 MessageSet wire format for extensions.
+    ///  This is provided for backwards-compatibility with the MessageSet wire
+    ///  format.  You should not use this for any other reason:  It's less
+    ///  efficient, has fewer features, and is more complicated.
+    ///
+    ///  The message must be defined exactly as follows:
+    ///    message Foo {
+    ///      option message_set_wire_format = true;
+    ///      extensions 4 to max;
+    ///    }
+    ///  Note that the message cannot have any defined fields; MessageSets only
+    ///  have extensions.
+    ///
+    ///  All extensions of your type must be singular messages; e.g. they cannot
+    ///  be int32s, enums, or repeated messages.
+    ///
+    ///  Because this is an option, the above two restrictions are not enforced by
+    ///  the protocol compiler.
+    /// </summary>
+    public bool MessageSetWireFormat {
+      get { return messageSetWireFormat_; }
+      set {
+        messageSetWireFormat_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "no_standard_descriptor_accessor" field.</summary>
+    public const int NoStandardDescriptorAccessorFieldNumber = 2;
+    private bool noStandardDescriptorAccessor_;
+    /// <summary>
+    ///  Disables the generation of the standard "descriptor()" accessor, which can
+    ///  conflict with a field of the same name.  This is meant to make migration
+    ///  from proto1 easier; new code should avoid fields named "descriptor".
+    /// </summary>
+    public bool NoStandardDescriptorAccessor {
+      get { return noStandardDescriptorAccessor_; }
+      set {
+        noStandardDescriptorAccessor_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 3;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this message deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for the message, or it will be completely ignored; in the very least,
+    ///  this is a formalization for deprecating messages.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "map_entry" field.</summary>
+    public const int MapEntryFieldNumber = 7;
+    private bool mapEntry_;
+    /// <summary>
+    ///  Whether the message is an automatically generated map entry type for the
+    ///  maps field.
+    ///
+    ///  For maps fields:
+    ///      map&lt;KeyType, ValueType> map_field = 1;
+    ///  The parsed descriptor looks like:
+    ///      message MapFieldEntry {
+    ///          option map_entry = true;
+    ///          optional KeyType key = 1;
+    ///          optional ValueType value = 2;
+    ///      }
+    ///      repeated MapFieldEntry map_field = 1;
+    ///
+    ///  Implementations may choose not to generate the map_entry=true message, but
+    ///  use a native map in the target language to hold the keys and values.
+    ///  The reflection APIs in such implementions still need to work as
+    ///  if the field is a repeated message field.
+    ///
+    ///  NOTE: Do not set the option in .proto files. Always use the maps syntax
+    ///  instead. The option should only be implicitly set by the proto compiler
+    ///  parser.
+    /// </summary>
+    public bool MapEntry {
+      get { return mapEntry_; }
+      set {
+        mapEntry_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MessageOptions);
+    }
+
+    public bool Equals(MessageOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (MessageSetWireFormat != other.MessageSetWireFormat) return false;
+      if (NoStandardDescriptorAccessor != other.NoStandardDescriptorAccessor) return false;
+      if (Deprecated != other.Deprecated) return false;
+      if (MapEntry != other.MapEntry) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (MessageSetWireFormat != false) hash ^= MessageSetWireFormat.GetHashCode();
+      if (NoStandardDescriptorAccessor != false) hash ^= NoStandardDescriptorAccessor.GetHashCode();
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (MapEntry != false) hash ^= MapEntry.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (MessageSetWireFormat != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(MessageSetWireFormat);
+      }
+      if (NoStandardDescriptorAccessor != false) {
+        output.WriteRawTag(16);
+        output.WriteBool(NoStandardDescriptorAccessor);
+      }
+      if (Deprecated != false) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      if (MapEntry != false) {
+        output.WriteRawTag(56);
+        output.WriteBool(MapEntry);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (MessageSetWireFormat != false) {
+        size += 1 + 1;
+      }
+      if (NoStandardDescriptorAccessor != false) {
+        size += 1 + 1;
+      }
+      if (Deprecated != false) {
+        size += 1 + 1;
+      }
+      if (MapEntry != false) {
+        size += 1 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(MessageOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.MessageSetWireFormat != false) {
+        MessageSetWireFormat = other.MessageSetWireFormat;
+      }
+      if (other.NoStandardDescriptorAccessor != false) {
+        NoStandardDescriptorAccessor = other.NoStandardDescriptorAccessor;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      if (other.MapEntry != false) {
+        MapEntry = other.MapEntry;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            MessageSetWireFormat = input.ReadBool();
+            break;
+          }
+          case 16: {
+            NoStandardDescriptorAccessor = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 56: {
+            MapEntry = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class FieldOptions : pb::IMessage<FieldOptions> {
+    private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
+    public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[11]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FieldOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FieldOptions(FieldOptions other) : this() {
+      ctype_ = other.ctype_;
+      packed_ = other.packed_;
+      jstype_ = other.jstype_;
+      lazy_ = other.lazy_;
+      deprecated_ = other.deprecated_;
+      weak_ = other.weak_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public FieldOptions Clone() {
+      return new FieldOptions(this);
+    }
+
+    /// <summary>Field number for the "ctype" field.</summary>
+    public const int CtypeFieldNumber = 1;
+    private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_ = 0;
+    /// <summary>
+    ///  The ctype option instructs the C++ code generator to use a different
+    ///  representation of the field than it normally would.  See the specific
+    ///  options below.  This option is not yet implemented in the open source
+    ///  release -- sorry, we'll try to include it in a future version!
+    /// </summary>
+    public global::Google.Protobuf.Reflection.FieldOptions.Types.CType Ctype {
+      get { return ctype_; }
+      set {
+        ctype_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "packed" field.</summary>
+    public const int PackedFieldNumber = 2;
+    private bool packed_;
+    /// <summary>
+    ///  The packed option can be enabled for repeated primitive fields to enable
+    ///  a more efficient representation on the wire. Rather than repeatedly
+    ///  writing the tag and type for each element, the entire array is encoded as
+    ///  a single length-delimited blob. In proto3, only explicit setting it to
+    ///  false will avoid using packed encoding.
+    /// </summary>
+    public bool Packed {
+      get { return packed_; }
+      set {
+        packed_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "jstype" field.</summary>
+    public const int JstypeFieldNumber = 6;
+    private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_ = 0;
+    /// <summary>
+    ///  The jstype option determines the JavaScript type used for values of the
+    ///  field.  The option is permitted only for 64 bit integral and fixed types
+    ///  (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
+    ///  represented as JavaScript strings.  This avoids loss of precision that can
+    ///  happen when a large value is converted to a floating point JavaScript
+    ///  numbers.  Specifying JS_NUMBER for the jstype causes the generated
+    ///  JavaScript code to use the JavaScript "number" type instead of strings.
+    ///  This option is an enum to permit additional types to be added,
+    ///  e.g. goog.math.Integer.
+    /// </summary>
+    public global::Google.Protobuf.Reflection.FieldOptions.Types.JSType Jstype {
+      get { return jstype_; }
+      set {
+        jstype_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "lazy" field.</summary>
+    public const int LazyFieldNumber = 5;
+    private bool lazy_;
+    /// <summary>
+    ///  Should this field be parsed lazily?  Lazy applies only to message-type
+    ///  fields.  It means that when the outer message is initially parsed, the
+    ///  inner message's contents will not be parsed but instead stored in encoded
+    ///  form.  The inner message will actually be parsed when it is first accessed.
+    ///
+    ///  This is only a hint.  Implementations are free to choose whether to use
+    ///  eager or lazy parsing regardless of the value of this option.  However,
+    ///  setting this option true suggests that the protocol author believes that
+    ///  using lazy parsing on this field is worth the additional bookkeeping
+    ///  overhead typically needed to implement it.
+    ///
+    ///  This option does not affect the public interface of any generated code;
+    ///  all method signatures remain the same.  Furthermore, thread-safety of the
+    ///  interface is not affected by this option; const methods remain safe to
+    ///  call from multiple threads concurrently, while non-const methods continue
+    ///  to require exclusive access.
+    ///
+    ///  Note that implementations may choose not to check required fields within
+    ///  a lazy sub-message.  That is, calling IsInitialized() on the outher message
+    ///  may return true even if the inner message has missing required fields.
+    ///  This is necessary because otherwise the inner message would have to be
+    ///  parsed in order to perform the check, defeating the purpose of lazy
+    ///  parsing.  An implementation which chooses not to check required fields
+    ///  must be consistent about it.  That is, for any particular sub-message, the
+    ///  implementation must either *always* check its required fields, or *never*
+    ///  check its required fields, regardless of whether or not the message has
+    ///  been parsed.
+    /// </summary>
+    public bool Lazy {
+      get { return lazy_; }
+      set {
+        lazy_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 3;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this field deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for accessors, or it will be completely ignored; in the very least, this
+    ///  is a formalization for deprecating fields.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "weak" field.</summary>
+    public const int WeakFieldNumber = 10;
+    private bool weak_;
+    /// <summary>
+    ///  For Google-internal migration only. Do not use.
+    /// </summary>
+    public bool Weak {
+      get { return weak_; }
+      set {
+        weak_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FieldOptions);
+    }
+
+    public bool Equals(FieldOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Ctype != other.Ctype) return false;
+      if (Packed != other.Packed) return false;
+      if (Jstype != other.Jstype) return false;
+      if (Lazy != other.Lazy) return false;
+      if (Deprecated != other.Deprecated) return false;
+      if (Weak != other.Weak) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Ctype != 0) hash ^= Ctype.GetHashCode();
+      if (Packed != false) hash ^= Packed.GetHashCode();
+      if (Jstype != 0) hash ^= Jstype.GetHashCode();
+      if (Lazy != false) hash ^= Lazy.GetHashCode();
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (Weak != false) hash ^= Weak.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Ctype != 0) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Ctype);
+      }
+      if (Packed != false) {
+        output.WriteRawTag(16);
+        output.WriteBool(Packed);
+      }
+      if (Deprecated != false) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      if (Lazy != false) {
+        output.WriteRawTag(40);
+        output.WriteBool(Lazy);
+      }
+      if (Jstype != 0) {
+        output.WriteRawTag(48);
+        output.WriteEnum((int) Jstype);
+      }
+      if (Weak != false) {
+        output.WriteRawTag(80);
+        output.WriteBool(Weak);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Ctype != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Ctype);
+      }
+      if (Packed != false) {
+        size += 1 + 1;
+      }
+      if (Jstype != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Jstype);
+      }
+      if (Lazy != false) {
+        size += 1 + 1;
+      }
+      if (Deprecated != false) {
+        size += 1 + 1;
+      }
+      if (Weak != false) {
+        size += 1 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(FieldOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Ctype != 0) {
+        Ctype = other.Ctype;
+      }
+      if (other.Packed != false) {
+        Packed = other.Packed;
+      }
+      if (other.Jstype != 0) {
+        Jstype = other.Jstype;
+      }
+      if (other.Lazy != false) {
+        Lazy = other.Lazy;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      if (other.Weak != false) {
+        Weak = other.Weak;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            ctype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum();
+            break;
+          }
+          case 16: {
+            Packed = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 40: {
+            Lazy = input.ReadBool();
+            break;
+          }
+          case 48: {
+            jstype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum();
+            break;
+          }
+          case 80: {
+            Weak = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the FieldOptions message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      internal enum CType {
+        /// <summary>
+        ///  Default mode.
+        /// </summary>
+        [pbr::OriginalName("STRING")] String = 0,
+        [pbr::OriginalName("CORD")] Cord = 1,
+        [pbr::OriginalName("STRING_PIECE")] StringPiece = 2,
+      }
+
+      internal enum JSType {
+        /// <summary>
+        ///  Use the default type.
+        /// </summary>
+        [pbr::OriginalName("JS_NORMAL")] JsNormal = 0,
+        /// <summary>
+        ///  Use JavaScript strings.
+        /// </summary>
+        [pbr::OriginalName("JS_STRING")] JsString = 1,
+        /// <summary>
+        ///  Use JavaScript numbers.
+        /// </summary>
+        [pbr::OriginalName("JS_NUMBER")] JsNumber = 2,
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class EnumOptions : pb::IMessage<EnumOptions> {
+    private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
+    public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[12]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EnumOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EnumOptions(EnumOptions other) : this() {
+      allowAlias_ = other.allowAlias_;
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public EnumOptions Clone() {
+      return new EnumOptions(this);
+    }
+
+    /// <summary>Field number for the "allow_alias" field.</summary>
+    public const int AllowAliasFieldNumber = 2;
+    private bool allowAlias_;
+    /// <summary>
+    ///  Set this option to true to allow mapping different tag names to the same
+    ///  value.
+    /// </summary>
+    public bool AllowAlias {
+      get { return allowAlias_; }
+      set {
+        allowAlias_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 3;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this enum deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for the enum, or it will be completely ignored; in the very least, this
+    ///  is a formalization for deprecating enums.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EnumOptions);
+    }
+
+    public bool Equals(EnumOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (AllowAlias != other.AllowAlias) return false;
+      if (Deprecated != other.Deprecated) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (AllowAlias != false) hash ^= AllowAlias.GetHashCode();
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (AllowAlias != false) {
+        output.WriteRawTag(16);
+        output.WriteBool(AllowAlias);
+      }
+      if (Deprecated != false) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (AllowAlias != false) {
+        size += 1 + 1;
+      }
+      if (Deprecated != false) {
+        size += 1 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(EnumOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.AllowAlias != false) {
+        AllowAlias = other.AllowAlias;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 16: {
+            AllowAlias = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions> {
+    private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
+    public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[13]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EnumValueOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EnumValueOptions(EnumValueOptions other) : this() {
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public EnumValueOptions Clone() {
+      return new EnumValueOptions(this);
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 1;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this enum value deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for the enum value, or it will be completely ignored; in the very least,
+    ///  this is a formalization for deprecating enum values.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EnumValueOptions);
+    }
+
+    public bool Equals(EnumValueOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Deprecated != other.Deprecated) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Deprecated != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Deprecated != false) {
+        size += 1 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(EnumValueOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class ServiceOptions : pb::IMessage<ServiceOptions> {
+    private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
+    public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[14]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServiceOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServiceOptions(ServiceOptions other) : this() {
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public ServiceOptions Clone() {
+      return new ServiceOptions(this);
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 33;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this service deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for the service, or it will be completely ignored; in the very least,
+    ///  this is a formalization for deprecating services.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServiceOptions);
+    }
+
+    public bool Equals(ServiceOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Deprecated != other.Deprecated) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Deprecated != false) {
+        output.WriteRawTag(136, 2);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Deprecated != false) {
+        size += 2 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(ServiceOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 264: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class MethodOptions : pb::IMessage<MethodOptions> {
+    private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
+    public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[15]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MethodOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MethodOptions(MethodOptions other) : this() {
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public MethodOptions Clone() {
+      return new MethodOptions(this);
+    }
+
+    /// <summary>Field number for the "deprecated" field.</summary>
+    public const int DeprecatedFieldNumber = 33;
+    private bool deprecated_;
+    /// <summary>
+    ///  Is this method deprecated?
+    ///  Depending on the target platform, this can emit Deprecated annotations
+    ///  for the method, or it will be completely ignored; in the very least,
+    ///  this is a formalization for deprecating methods.
+    /// </summary>
+    public bool Deprecated {
+      get { return deprecated_; }
+      set {
+        deprecated_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    ///  The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MethodOptions);
+    }
+
+    public bool Equals(MethodOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Deprecated != other.Deprecated) return false;
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Deprecated != false) {
+        output.WriteRawTag(136, 2);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Deprecated != false) {
+        size += 2 + 1;
+      }
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    public void MergeFrom(MethodOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Deprecated != false) {
+        Deprecated = other.Deprecated;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 264: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A message representing a option the parser does not recognize. This only
+  ///  appears in options protos created by the compiler::Parser class.
+  ///  DescriptorPool resolves these when building Descriptor objects. Therefore,
+  ///  options protos in descriptor objects (e.g. returned by Descriptor::options(),
+  ///  or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+  ///  in them.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
+    private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
+    public static pb::MessageParser<UninterpretedOption> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[16]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public UninterpretedOption() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public UninterpretedOption(UninterpretedOption other) : this() {
+      name_ = other.name_.Clone();
+      identifierValue_ = other.identifierValue_;
+      positiveIntValue_ = other.positiveIntValue_;
+      negativeIntValue_ = other.negativeIntValue_;
+      doubleValue_ = other.doubleValue_;
+      stringValue_ = other.stringValue_;
+      aggregateValue_ = other.aggregateValue_;
+    }
+
+    public UninterpretedOption Clone() {
+      return new UninterpretedOption(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart> _repeated_name_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart>();
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart> Name {
+      get { return name_; }
+    }
+
+    /// <summary>Field number for the "identifier_value" field.</summary>
+    public const int IdentifierValueFieldNumber = 3;
+    private string identifierValue_ = "";
+    /// <summary>
+    ///  The value of the uninterpreted option, in whatever type the tokenizer
+    ///  identified it as during parsing. Exactly one of these should be set.
+    /// </summary>
+    public string IdentifierValue {
+      get { return identifierValue_; }
+      set {
+        identifierValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "positive_int_value" field.</summary>
+    public const int PositiveIntValueFieldNumber = 4;
+    private ulong positiveIntValue_;
+    public ulong PositiveIntValue {
+      get { return positiveIntValue_; }
+      set {
+        positiveIntValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "negative_int_value" field.</summary>
+    public const int NegativeIntValueFieldNumber = 5;
+    private long negativeIntValue_;
+    public long NegativeIntValue {
+      get { return negativeIntValue_; }
+      set {
+        negativeIntValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "double_value" field.</summary>
+    public const int DoubleValueFieldNumber = 6;
+    private double doubleValue_;
+    public double DoubleValue {
+      get { return doubleValue_; }
+      set {
+        doubleValue_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "string_value" field.</summary>
+    public const int StringValueFieldNumber = 7;
+    private pb::ByteString stringValue_ = pb::ByteString.Empty;
+    public pb::ByteString StringValue {
+      get { return stringValue_; }
+      set {
+        stringValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "aggregate_value" field.</summary>
+    public const int AggregateValueFieldNumber = 8;
+    private string aggregateValue_ = "";
+    public string AggregateValue {
+      get { return aggregateValue_; }
+      set {
+        aggregateValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as UninterpretedOption);
+    }
+
+    public bool Equals(UninterpretedOption other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!name_.Equals(other.name_)) return false;
+      if (IdentifierValue != other.IdentifierValue) return false;
+      if (PositiveIntValue != other.PositiveIntValue) return false;
+      if (NegativeIntValue != other.NegativeIntValue) return false;
+      if (DoubleValue != other.DoubleValue) return false;
+      if (StringValue != other.StringValue) return false;
+      if (AggregateValue != other.AggregateValue) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= name_.GetHashCode();
+      if (IdentifierValue.Length != 0) hash ^= IdentifierValue.GetHashCode();
+      if (PositiveIntValue != 0UL) hash ^= PositiveIntValue.GetHashCode();
+      if (NegativeIntValue != 0L) hash ^= NegativeIntValue.GetHashCode();
+      if (DoubleValue != 0D) hash ^= DoubleValue.GetHashCode();
+      if (StringValue.Length != 0) hash ^= StringValue.GetHashCode();
+      if (AggregateValue.Length != 0) hash ^= AggregateValue.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      name_.WriteTo(output, _repeated_name_codec);
+      if (IdentifierValue.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(IdentifierValue);
+      }
+      if (PositiveIntValue != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(PositiveIntValue);
+      }
+      if (NegativeIntValue != 0L) {
+        output.WriteRawTag(40);
+        output.WriteInt64(NegativeIntValue);
+      }
+      if (DoubleValue != 0D) {
+        output.WriteRawTag(49);
+        output.WriteDouble(DoubleValue);
+      }
+      if (StringValue.Length != 0) {
+        output.WriteRawTag(58);
+        output.WriteBytes(StringValue);
+      }
+      if (AggregateValue.Length != 0) {
+        output.WriteRawTag(66);
+        output.WriteString(AggregateValue);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += name_.CalculateSize(_repeated_name_codec);
+      if (IdentifierValue.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(IdentifierValue);
+      }
+      if (PositiveIntValue != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(PositiveIntValue);
+      }
+      if (NegativeIntValue != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(NegativeIntValue);
+      }
+      if (DoubleValue != 0D) {
+        size += 1 + 8;
+      }
+      if (StringValue.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(StringValue);
+      }
+      if (AggregateValue.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(AggregateValue);
+      }
+      return size;
+    }
+
+    public void MergeFrom(UninterpretedOption other) {
+      if (other == null) {
+        return;
+      }
+      name_.Add(other.name_);
+      if (other.IdentifierValue.Length != 0) {
+        IdentifierValue = other.IdentifierValue;
+      }
+      if (other.PositiveIntValue != 0UL) {
+        PositiveIntValue = other.PositiveIntValue;
+      }
+      if (other.NegativeIntValue != 0L) {
+        NegativeIntValue = other.NegativeIntValue;
+      }
+      if (other.DoubleValue != 0D) {
+        DoubleValue = other.DoubleValue;
+      }
+      if (other.StringValue.Length != 0) {
+        StringValue = other.StringValue;
+      }
+      if (other.AggregateValue.Length != 0) {
+        AggregateValue = other.AggregateValue;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 18: {
+            name_.AddEntriesFrom(input, _repeated_name_codec);
+            break;
+          }
+          case 26: {
+            IdentifierValue = input.ReadString();
+            break;
+          }
+          case 32: {
+            PositiveIntValue = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            NegativeIntValue = input.ReadInt64();
+            break;
+          }
+          case 49: {
+            DoubleValue = input.ReadDouble();
+            break;
+          }
+          case 58: {
+            StringValue = input.ReadBytes();
+            break;
+          }
+          case 66: {
+            AggregateValue = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the UninterpretedOption message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      /// <summary>
+      ///  The name of the uninterpreted option.  Each string represents a segment in
+      ///  a dot-separated name.  is_extension is true iff a segment represents an
+      ///  extension (denoted with parentheses in options specs in .proto files).
+      ///  E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+      ///  "foo.(bar.baz).qux".
+      /// </summary>
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      internal sealed partial class NamePart : pb::IMessage<NamePart> {
+        private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
+        public static pb::MessageParser<NamePart> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Reflection.UninterpretedOption.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NamePart() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NamePart(NamePart other) : this() {
+          namePart_ = other.namePart_;
+          isExtension_ = other.isExtension_;
+        }
+
+        public NamePart Clone() {
+          return new NamePart(this);
+        }
+
+        /// <summary>Field number for the "name_part" field.</summary>
+        public const int NamePart_FieldNumber = 1;
+        private string namePart_ = "";
+        public string NamePart_ {
+          get { return namePart_; }
+          set {
+            namePart_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "is_extension" field.</summary>
+        public const int IsExtensionFieldNumber = 2;
+        private bool isExtension_;
+        public bool IsExtension {
+          get { return isExtension_; }
+          set {
+            isExtension_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NamePart);
+        }
+
+        public bool Equals(NamePart other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (NamePart_ != other.NamePart_) return false;
+          if (IsExtension != other.IsExtension) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (NamePart_.Length != 0) hash ^= NamePart_.GetHashCode();
+          if (IsExtension != false) hash ^= IsExtension.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (NamePart_.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(NamePart_);
+          }
+          if (IsExtension != false) {
+            output.WriteRawTag(16);
+            output.WriteBool(IsExtension);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (NamePart_.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(NamePart_);
+          }
+          if (IsExtension != false) {
+            size += 1 + 1;
+          }
+          return size;
+        }
+
+        public void MergeFrom(NamePart other) {
+          if (other == null) {
+            return;
+          }
+          if (other.NamePart_.Length != 0) {
+            NamePart_ = other.NamePart_;
+          }
+          if (other.IsExtension != false) {
+            IsExtension = other.IsExtension;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 10: {
+                NamePart_ = input.ReadString();
+                break;
+              }
+              case 16: {
+                IsExtension = input.ReadBool();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Encapsulates information about the original source file from which a
+  ///  FileDescriptorProto was generated.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
+    private static readonly pb::MessageParser<SourceCodeInfo> _parser = new pb::MessageParser<SourceCodeInfo>(() => new SourceCodeInfo());
+    public static pb::MessageParser<SourceCodeInfo> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[17]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SourceCodeInfo() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SourceCodeInfo(SourceCodeInfo other) : this() {
+      location_ = other.location_.Clone();
+    }
+
+    public SourceCodeInfo Clone() {
+      return new SourceCodeInfo(this);
+    }
+
+    /// <summary>Field number for the "location" field.</summary>
+    public const int LocationFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location> _repeated_location_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location> location_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location>();
+    /// <summary>
+    ///  A Location identifies a piece of source code in a .proto file which
+    ///  corresponds to a particular definition.  This information is intended
+    ///  to be useful to IDEs, code indexers, documentation generators, and similar
+    ///  tools.
+    ///
+    ///  For example, say we have a file like:
+    ///    message Foo {
+    ///      optional string foo = 1;
+    ///    }
+    ///  Let's look at just the field definition:
+    ///    optional string foo = 1;
+    ///    ^       ^^     ^^  ^  ^^^
+    ///    a       bc     de  f  ghi
+    ///  We have the following locations:
+    ///    span   path               represents
+    ///    [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+    ///    [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+    ///    [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+    ///    [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+    ///    [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+    ///
+    ///  Notes:
+    ///  - A location may refer to a repeated field itself (i.e. not to any
+    ///    particular index within it).  This is used whenever a set of elements are
+    ///    logically enclosed in a single code segment.  For example, an entire
+    ///    extend block (possibly containing multiple extension definitions) will
+    ///    have an outer location whose path refers to the "extensions" repeated
+    ///    field without an index.
+    ///  - Multiple locations may have the same path.  This happens when a single
+    ///    logical declaration is spread out across multiple places.  The most
+    ///    obvious example is the "extend" block again -- there may be multiple
+    ///    extend blocks in the same scope, each of which will have the same path.
+    ///  - A location's span is not always a subset of its parent's span.  For
+    ///    example, the "extendee" of an extension declaration appears at the
+    ///    beginning of the "extend" block and is shared by all extensions within
+    ///    the block.
+    ///  - Just because a location's span is a subset of some other location's span
+    ///    does not mean that it is a descendent.  For example, a "group" defines
+    ///    both a type and a field in a single declaration.  Thus, the locations
+    ///    corresponding to the type and field and their components will overlap.
+    ///  - Code which tries to interpret locations should probably be designed to
+    ///    ignore those that it doesn't understand, as more types of locations could
+    ///    be recorded in the future.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location> Location {
+      get { return location_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SourceCodeInfo);
+    }
+
+    public bool Equals(SourceCodeInfo other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!location_.Equals(other.location_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= location_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      location_.WriteTo(output, _repeated_location_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += location_.CalculateSize(_repeated_location_codec);
+      return size;
+    }
+
+    public void MergeFrom(SourceCodeInfo other) {
+      if (other == null) {
+        return;
+      }
+      location_.Add(other.location_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            location_.AddEntriesFrom(input, _repeated_location_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the SourceCodeInfo message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      internal sealed partial class Location : pb::IMessage<Location> {
+        private static readonly pb::MessageParser<Location> _parser = new pb::MessageParser<Location>(() => new Location());
+        public static pb::MessageParser<Location> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Reflection.SourceCodeInfo.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public Location() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public Location(Location other) : this() {
+          path_ = other.path_.Clone();
+          span_ = other.span_.Clone();
+          leadingComments_ = other.leadingComments_;
+          trailingComments_ = other.trailingComments_;
+          leadingDetachedComments_ = other.leadingDetachedComments_.Clone();
+        }
+
+        public Location Clone() {
+          return new Location(this);
+        }
+
+        /// <summary>Field number for the "path" field.</summary>
+        public const int PathFieldNumber = 1;
+        private static readonly pb::FieldCodec<int> _repeated_path_codec
+            = pb::FieldCodec.ForInt32(10);
+        private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>();
+        /// <summary>
+        ///  Identifies which part of the FileDescriptorProto was defined at this
+        ///  location.
+        ///
+        ///  Each element is a field number or an index.  They form a path from
+        ///  the root FileDescriptorProto to the place where the definition.  For
+        ///  example, this path:
+        ///    [ 4, 3, 2, 7, 1 ]
+        ///  refers to:
+        ///    file.message_type(3)  // 4, 3
+        ///        .field(7)         // 2, 7
+        ///        .name()           // 1
+        ///  This is because FileDescriptorProto.message_type has field number 4:
+        ///    repeated DescriptorProto message_type = 4;
+        ///  and DescriptorProto.field has field number 2:
+        ///    repeated FieldDescriptorProto field = 2;
+        ///  and FieldDescriptorProto.name has field number 1:
+        ///    optional string name = 1;
+        ///
+        ///  Thus, the above path gives the location of a field name.  If we removed
+        ///  the last element:
+        ///    [ 4, 3, 2, 7 ]
+        ///  this path refers to the whole field declaration (from the beginning
+        ///  of the label to the terminating semicolon).
+        /// </summary>
+        public pbc::RepeatedField<int> Path {
+          get { return path_; }
+        }
+
+        /// <summary>Field number for the "span" field.</summary>
+        public const int SpanFieldNumber = 2;
+        private static readonly pb::FieldCodec<int> _repeated_span_codec
+            = pb::FieldCodec.ForInt32(18);
+        private readonly pbc::RepeatedField<int> span_ = new pbc::RepeatedField<int>();
+        /// <summary>
+        ///  Always has exactly three or four elements: start line, start column,
+        ///  end line (optional, otherwise assumed same as start line), end column.
+        ///  These are packed into a single field for efficiency.  Note that line
+        ///  and column numbers are zero-based -- typically you will want to add
+        ///  1 to each before displaying to a user.
+        /// </summary>
+        public pbc::RepeatedField<int> Span {
+          get { return span_; }
+        }
+
+        /// <summary>Field number for the "leading_comments" field.</summary>
+        public const int LeadingCommentsFieldNumber = 3;
+        private string leadingComments_ = "";
+        /// <summary>
+        ///  If this SourceCodeInfo represents a complete declaration, these are any
+        ///  comments appearing before and after the declaration which appear to be
+        ///  attached to the declaration.
+        ///
+        ///  A series of line comments appearing on consecutive lines, with no other
+        ///  tokens appearing on those lines, will be treated as a single comment.
+        ///
+        ///  leading_detached_comments will keep paragraphs of comments that appear
+        ///  before (but not connected to) the current element. Each paragraph,
+        ///  separated by empty lines, will be one comment element in the repeated
+        ///  field.
+        ///
+        ///  Only the comment content is provided; comment markers (e.g. //) are
+        ///  stripped out.  For block comments, leading whitespace and an asterisk
+        ///  will be stripped from the beginning of each line other than the first.
+        ///  Newlines are included in the output.
+        ///
+        ///  Examples:
+        ///
+        ///    optional int32 foo = 1;  // Comment attached to foo.
+        ///    // Comment attached to bar.
+        ///    optional int32 bar = 2;
+        ///
+        ///    optional string baz = 3;
+        ///    // Comment attached to baz.
+        ///    // Another line attached to baz.
+        ///
+        ///    // Comment attached to qux.
+        ///    //
+        ///    // Another line attached to qux.
+        ///    optional double qux = 4;
+        ///
+        ///    // Detached comment for corge. This is not leading or trailing comments
+        ///    // to qux or corge because there are blank lines separating it from
+        ///    // both.
+        ///
+        ///    // Detached comment for corge paragraph 2.
+        ///
+        ///    optional string corge = 5;
+        ///    /* Block comment attached
+        ///     * to corge.  Leading asterisks
+        ///     * will be removed. */
+        ///    /* Block comment attached to
+        ///     * grault. */
+        ///    optional int32 grault = 6;
+        ///
+        ///    // ignored detached comments.
+        /// </summary>
+        public string LeadingComments {
+          get { return leadingComments_; }
+          set {
+            leadingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "trailing_comments" field.</summary>
+        public const int TrailingCommentsFieldNumber = 4;
+        private string trailingComments_ = "";
+        public string TrailingComments {
+          get { return trailingComments_; }
+          set {
+            trailingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "leading_detached_comments" field.</summary>
+        public const int LeadingDetachedCommentsFieldNumber = 6;
+        private static readonly pb::FieldCodec<string> _repeated_leadingDetachedComments_codec
+            = pb::FieldCodec.ForString(50);
+        private readonly pbc::RepeatedField<string> leadingDetachedComments_ = new pbc::RepeatedField<string>();
+        public pbc::RepeatedField<string> LeadingDetachedComments {
+          get { return leadingDetachedComments_; }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as Location);
+        }
+
+        public bool Equals(Location other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if(!path_.Equals(other.path_)) return false;
+          if(!span_.Equals(other.span_)) return false;
+          if (LeadingComments != other.LeadingComments) return false;
+          if (TrailingComments != other.TrailingComments) return false;
+          if(!leadingDetachedComments_.Equals(other.leadingDetachedComments_)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          hash ^= path_.GetHashCode();
+          hash ^= span_.GetHashCode();
+          if (LeadingComments.Length != 0) hash ^= LeadingComments.GetHashCode();
+          if (TrailingComments.Length != 0) hash ^= TrailingComments.GetHashCode();
+          hash ^= leadingDetachedComments_.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          path_.WriteTo(output, _repeated_path_codec);
+          span_.WriteTo(output, _repeated_span_codec);
+          if (LeadingComments.Length != 0) {
+            output.WriteRawTag(26);
+            output.WriteString(LeadingComments);
+          }
+          if (TrailingComments.Length != 0) {
+            output.WriteRawTag(34);
+            output.WriteString(TrailingComments);
+          }
+          leadingDetachedComments_.WriteTo(output, _repeated_leadingDetachedComments_codec);
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          size += path_.CalculateSize(_repeated_path_codec);
+          size += span_.CalculateSize(_repeated_span_codec);
+          if (LeadingComments.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(LeadingComments);
+          }
+          if (TrailingComments.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(TrailingComments);
+          }
+          size += leadingDetachedComments_.CalculateSize(_repeated_leadingDetachedComments_codec);
+          return size;
+        }
+
+        public void MergeFrom(Location other) {
+          if (other == null) {
+            return;
+          }
+          path_.Add(other.path_);
+          span_.Add(other.span_);
+          if (other.LeadingComments.Length != 0) {
+            LeadingComments = other.LeadingComments;
+          }
+          if (other.TrailingComments.Length != 0) {
+            TrailingComments = other.TrailingComments;
+          }
+          leadingDetachedComments_.Add(other.leadingDetachedComments_);
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 10:
+              case 8: {
+                path_.AddEntriesFrom(input, _repeated_path_codec);
+                break;
+              }
+              case 18:
+              case 16: {
+                span_.AddEntriesFrom(input, _repeated_span_codec);
+                break;
+              }
+              case 26: {
+                LeadingComments = input.ReadString();
+                break;
+              }
+              case 34: {
+                TrailingComments = input.ReadString();
+                break;
+              }
+              case 50: {
+                leadingDetachedComments_.AddEntriesFrom(input, _repeated_leadingDetachedComments_codec);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Describes the relationship between generated code and its original source
+  ///  file. A GeneratedCodeInfo message is associated with only one generated
+  ///  source file, but may contain references to different source .proto files.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  internal sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo> {
+    private static readonly pb::MessageParser<GeneratedCodeInfo> _parser = new pb::MessageParser<GeneratedCodeInfo>(() => new GeneratedCodeInfo());
+    public static pb::MessageParser<GeneratedCodeInfo> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[18]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public GeneratedCodeInfo() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public GeneratedCodeInfo(GeneratedCodeInfo other) : this() {
+      annotation_ = other.annotation_.Clone();
+    }
+
+    public GeneratedCodeInfo Clone() {
+      return new GeneratedCodeInfo(this);
+    }
+
+    /// <summary>Field number for the "annotation" field.</summary>
+    public const int AnnotationFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> _repeated_annotation_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> annotation_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation>();
+    /// <summary>
+    ///  An Annotation connects some span of text in generated code to an element
+    ///  of its generating .proto file.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> Annotation {
+      get { return annotation_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as GeneratedCodeInfo);
+    }
+
+    public bool Equals(GeneratedCodeInfo other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!annotation_.Equals(other.annotation_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= annotation_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      annotation_.WriteTo(output, _repeated_annotation_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += annotation_.CalculateSize(_repeated_annotation_codec);
+      return size;
+    }
+
+    public void MergeFrom(GeneratedCodeInfo other) {
+      if (other == null) {
+        return;
+      }
+      annotation_.Add(other.annotation_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            annotation_.AddEntriesFrom(input, _repeated_annotation_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the GeneratedCodeInfo message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      internal sealed partial class Annotation : pb::IMessage<Annotation> {
+        private static readonly pb::MessageParser<Annotation> _parser = new pb::MessageParser<Annotation>(() => new Annotation());
+        public static pb::MessageParser<Annotation> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Reflection.GeneratedCodeInfo.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public Annotation() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public Annotation(Annotation other) : this() {
+          path_ = other.path_.Clone();
+          sourceFile_ = other.sourceFile_;
+          begin_ = other.begin_;
+          end_ = other.end_;
+        }
+
+        public Annotation Clone() {
+          return new Annotation(this);
+        }
+
+        /// <summary>Field number for the "path" field.</summary>
+        public const int PathFieldNumber = 1;
+        private static readonly pb::FieldCodec<int> _repeated_path_codec
+            = pb::FieldCodec.ForInt32(10);
+        private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>();
+        /// <summary>
+        ///  Identifies the element in the original source .proto file. This field
+        ///  is formatted the same as SourceCodeInfo.Location.path.
+        /// </summary>
+        public pbc::RepeatedField<int> Path {
+          get { return path_; }
+        }
+
+        /// <summary>Field number for the "source_file" field.</summary>
+        public const int SourceFileFieldNumber = 2;
+        private string sourceFile_ = "";
+        /// <summary>
+        ///  Identifies the filesystem path to the original source .proto.
+        /// </summary>
+        public string SourceFile {
+          get { return sourceFile_; }
+          set {
+            sourceFile_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        /// <summary>Field number for the "begin" field.</summary>
+        public const int BeginFieldNumber = 3;
+        private int begin_;
+        /// <summary>
+        ///  Identifies the starting offset in bytes in the generated code
+        ///  that relates to the identified object.
+        /// </summary>
+        public int Begin {
+          get { return begin_; }
+          set {
+            begin_ = value;
+          }
+        }
+
+        /// <summary>Field number for the "end" field.</summary>
+        public const int EndFieldNumber = 4;
+        private int end_;
+        /// <summary>
+        ///  Identifies the ending offset in bytes in the generated code that
+        ///  relates to the identified offset. The end offset should be one past
+        ///  the last relevant byte (so the length of the text = end - begin).
+        /// </summary>
+        public int End {
+          get { return end_; }
+          set {
+            end_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as Annotation);
+        }
+
+        public bool Equals(Annotation other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if(!path_.Equals(other.path_)) return false;
+          if (SourceFile != other.SourceFile) return false;
+          if (Begin != other.Begin) return false;
+          if (End != other.End) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          hash ^= path_.GetHashCode();
+          if (SourceFile.Length != 0) hash ^= SourceFile.GetHashCode();
+          if (Begin != 0) hash ^= Begin.GetHashCode();
+          if (End != 0) hash ^= End.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          path_.WriteTo(output, _repeated_path_codec);
+          if (SourceFile.Length != 0) {
+            output.WriteRawTag(18);
+            output.WriteString(SourceFile);
+          }
+          if (Begin != 0) {
+            output.WriteRawTag(24);
+            output.WriteInt32(Begin);
+          }
+          if (End != 0) {
+            output.WriteRawTag(32);
+            output.WriteInt32(End);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          size += path_.CalculateSize(_repeated_path_codec);
+          if (SourceFile.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceFile);
+          }
+          if (Begin != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Begin);
+          }
+          if (End != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
+          }
+          return size;
+        }
+
+        public void MergeFrom(Annotation other) {
+          if (other == null) {
+            return;
+          }
+          path_.Add(other.path_);
+          if (other.SourceFile.Length != 0) {
+            SourceFile = other.SourceFile;
+          }
+          if (other.Begin != 0) {
+            Begin = other.Begin;
+          }
+          if (other.End != 0) {
+            End = other.End;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 10:
+              case 8: {
+                path_.AddEntriesFrom(input, _repeated_path_codec);
+                break;
+              }
+              case 18: {
+                SourceFile = input.ReadString();
+                break;
+              }
+              case 24: {
+                Begin = input.ReadInt32();
+                break;
+              }
+              case 32: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs
new file mode 100644
index 0000000..194041a
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs
@@ -0,0 +1,85 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Base class for nearly all descriptors, providing common functionality.
+    /// </summary>
+    public abstract class DescriptorBase : IDescriptor
+    {
+        private readonly FileDescriptor file;
+        private readonly string fullName;
+        private readonly int index;
+
+        internal DescriptorBase(FileDescriptor file, string fullName, int index)
+        {
+            this.file = file;
+            this.fullName = fullName;
+            this.index = index;
+        }
+
+        /// <value>
+        /// The index of this descriptor within its parent descriptor. 
+        /// </value>
+        /// <remarks>
+        /// This returns the index of this descriptor within its parent, for
+        /// this descriptor's type. (There can be duplicate values for different
+        /// types, e.g. one enum type with index 0 and one message type with index 0.)
+        /// </remarks>
+        public int Index
+        {
+            get { return index; }
+        }
+
+        /// <summary>
+        /// Returns the name of the entity (field, message etc) being described.
+        /// </summary>
+        public abstract string Name { get; }
+
+        /// <summary>
+        /// The fully qualified name of the descriptor's target.
+        /// </summary>
+        public string FullName
+        {
+            get { return fullName; }
+        }
+
+        /// <value>
+        /// The file this descriptor was declared in.
+        /// </value>
+        public FileDescriptor File
+        {
+            get { return file; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
new file mode 100644
index 0000000..99ca4bf
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
@@ -0,0 +1,368 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Contains lookup tables containing all the descriptors defined in a particular file.
+    /// </summary>
+    internal sealed class DescriptorPool
+    {
+        private readonly IDictionary<string, IDescriptor> descriptorsByName =
+            new Dictionary<string, IDescriptor>();
+
+        private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+            new Dictionary<DescriptorIntPair, FieldDescriptor>();
+
+        private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
+            new Dictionary<DescriptorIntPair, EnumValueDescriptor>();
+
+        private readonly HashSet<FileDescriptor> dependencies;
+
+        internal DescriptorPool(FileDescriptor[] dependencyFiles)
+        {
+            dependencies = new HashSet<FileDescriptor>();
+            for (int i = 0; i < dependencyFiles.Length; i++)
+            {
+                dependencies.Add(dependencyFiles[i]);
+                ImportPublicDependencies(dependencyFiles[i]);
+            }
+
+            foreach (FileDescriptor dependency in dependencyFiles)
+            {
+                AddPackage(dependency.Package, dependency);
+            }
+        }
+
+        private void ImportPublicDependencies(FileDescriptor file)
+        {
+            foreach (FileDescriptor dependency in file.PublicDependencies)
+            {
+                if (dependencies.Add(dependency))
+                {
+                    ImportPublicDependencies(dependency);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finds a symbol of the given name within the pool.
+        /// </summary>
+        /// <typeparam name="T">The type of symbol to look for</typeparam>
+        /// <param name="fullName">Fully-qualified name to look up</param>
+        /// <returns>The symbol with the given name and type,
+        /// or null if the symbol doesn't exist or has the wrong type</returns>
+        internal T FindSymbol<T>(string fullName) where T : class
+        {
+            IDescriptor result;
+            descriptorsByName.TryGetValue(fullName, out result);
+            T descriptor = result as T;
+            if (descriptor != null)
+            {
+                return descriptor;
+            }
+
+            // dependencies contains direct dependencies and any *public* dependencies
+            // of those dependencies (transitively)... so we don't need to recurse here.
+            foreach (FileDescriptor dependency in dependencies)
+            {
+                dependency.DescriptorPool.descriptorsByName.TryGetValue(fullName, out result);
+                descriptor = result as T;
+                if (descriptor != null)
+                {
+                    return descriptor;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Adds a package to the symbol tables. If a package by the same name
+        /// already exists, that is fine, but if some other kind of symbol
+        /// exists under the same name, an exception is thrown. If the package
+        /// has multiple components, this also adds the parent package(s).
+        /// </summary>
+        internal void AddPackage(string fullName, FileDescriptor file)
+        {
+            int dotpos = fullName.LastIndexOf('.');
+            String name;
+            if (dotpos != -1)
+            {
+                AddPackage(fullName.Substring(0, dotpos), file);
+                name = fullName.Substring(dotpos + 1);
+            }
+            else
+            {
+                name = fullName;
+            }
+
+            IDescriptor old;
+            if (descriptorsByName.TryGetValue(fullName, out old))
+            {
+                if (!(old is PackageDescriptor))
+                {
+                    throw new DescriptorValidationException(file,
+                                                            "\"" + name +
+                                                            "\" is already defined (as something other than a " +
+                                                            "package) in file \"" + old.File.Name + "\".");
+                }
+            }
+            descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file);
+        }
+
+        /// <summary>
+        /// Adds a symbol to the symbol table.
+        /// </summary>
+        /// <exception cref="DescriptorValidationException">The symbol already existed
+        /// in the symbol table.</exception>
+        internal void AddSymbol(IDescriptor descriptor)
+        {
+            ValidateSymbolName(descriptor);
+            String fullName = descriptor.FullName;
+
+            IDescriptor old;
+            if (descriptorsByName.TryGetValue(fullName, out old))
+            {
+                int dotPos = fullName.LastIndexOf('.');
+                string message;
+                if (descriptor.File == old.File)
+                {
+                    if (dotPos == -1)
+                    {
+                        message = "\"" + fullName + "\" is already defined.";
+                    }
+                    else
+                    {
+                        message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" +
+                                  fullName.Substring(0, dotPos) + "\".";
+                    }
+                }
+                else
+                {
+                    message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\".";
+                }
+                throw new DescriptorValidationException(descriptor, message);
+            }
+            descriptorsByName[fullName] = descriptor;
+        }
+
+        private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$",
+                                                                  FrameworkPortability.CompiledRegexWhereAvailable);
+
+        /// <summary>
+        /// Verifies that the descriptor's name is valid (i.e. it contains
+        /// only letters, digits and underscores, and does not start with a digit).
+        /// </summary>
+        /// <param name="descriptor"></param>
+        private static void ValidateSymbolName(IDescriptor descriptor)
+        {
+            if (descriptor.Name == "")
+            {
+                throw new DescriptorValidationException(descriptor, "Missing name.");
+            }
+            if (!ValidationRegex.IsMatch(descriptor.Name))
+            {
+                throw new DescriptorValidationException(descriptor,
+                                                        "\"" + descriptor.Name + "\" is not a valid identifier.");
+            }
+        }
+
+        /// <summary>
+        /// Returns the field with the given number in the given descriptor,
+        /// or null if it can't be found.
+        /// </summary>
+        internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number)
+        {
+            FieldDescriptor ret;
+            fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret);
+            return ret;
+        }
+
+        internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number)
+        {
+            EnumValueDescriptor ret;
+            enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret);
+            return ret;
+        }
+
+        /// <summary>
+        /// Adds a field to the fieldsByNumber table.
+        /// </summary>
+        /// <exception cref="DescriptorValidationException">A field with the same
+        /// containing type and number already exists.</exception>
+        internal void AddFieldByNumber(FieldDescriptor field)
+        {
+            DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber);
+            FieldDescriptor old;
+            if (fieldsByNumber.TryGetValue(key, out old))
+            {
+                throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
+                                                               "has already been used in \"" +
+                                                               field.ContainingType.FullName +
+                                                               "\" by field \"" + old.Name + "\".");
+            }
+            fieldsByNumber[key] = field;
+        }
+
+        /// <summary>
+        /// Adds an enum value to the enumValuesByNumber table. If an enum value
+        /// with the same type and number already exists, this method does nothing.
+        /// (This is allowed; the first value defined with the number takes precedence.)
+        /// </summary>
+        internal void AddEnumValueByNumber(EnumValueDescriptor enumValue)
+        {
+            DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number);
+            if (!enumValuesByNumber.ContainsKey(key))
+            {
+                enumValuesByNumber[key] = enumValue;
+            }
+        }
+
+        /// <summary>
+        /// Looks up a descriptor by name, relative to some other descriptor.
+        /// The name may be fully-qualified (with a leading '.'), partially-qualified,
+        /// or unqualified. C++-like name lookup semantics are used to search for the
+        /// matching descriptor.
+        /// </summary>
+        /// <remarks>
+        /// This isn't heavily optimized, but it's only used during cross linking anyway.
+        /// If it starts being used more widely, we should look at performance more carefully.
+        /// </remarks>
+        internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo)
+        {
+            IDescriptor result;
+            if (name.StartsWith("."))
+            {
+                // Fully-qualified name.
+                result = FindSymbol<IDescriptor>(name.Substring(1));
+            }
+            else
+            {
+                // If "name" is a compound identifier, we want to search for the
+                // first component of it, then search within it for the rest.
+                int firstPartLength = name.IndexOf('.');
+                string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength);
+
+                // We will search each parent scope of "relativeTo" looking for the
+                // symbol.
+                StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName);
+
+                while (true)
+                {
+                    // Chop off the last component of the scope.
+
+                    int dotpos = scopeToTry.ToString().LastIndexOf(".");
+                    if (dotpos == -1)
+                    {
+                        result = FindSymbol<IDescriptor>(name);
+                        break;
+                    }
+                    else
+                    {
+                        scopeToTry.Length = dotpos + 1;
+
+                        // Append firstPart and try to find.
+                        scopeToTry.Append(firstPart);
+                        result = FindSymbol<IDescriptor>(scopeToTry.ToString());
+
+                        if (result != null)
+                        {
+                            if (firstPartLength != -1)
+                            {
+                                // We only found the first part of the symbol.  Now look for
+                                // the whole thing.  If this fails, we *don't* want to keep
+                                // searching parent scopes.
+                                scopeToTry.Length = dotpos + 1;
+                                scopeToTry.Append(name);
+                                result = FindSymbol<IDescriptor>(scopeToTry.ToString());
+                            }
+                            break;
+                        }
+
+                        // Not found.  Remove the name so we can try again.
+                        scopeToTry.Length = dotpos;
+                    }
+                }
+            }
+
+            if (result == null)
+            {
+                throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined.");
+            }
+            else
+            {
+                return result;
+            }
+        }
+
+        /// <summary>
+        /// Struct used to hold the keys for the fieldByNumber table.
+        /// </summary>
+        private struct DescriptorIntPair : IEquatable<DescriptorIntPair>
+        {
+            private readonly int number;
+            private readonly IDescriptor descriptor;
+
+            internal DescriptorIntPair(IDescriptor descriptor, int number)
+            {
+                this.number = number;
+                this.descriptor = descriptor;
+            }
+
+            public bool Equals(DescriptorIntPair other)
+            {
+                return descriptor == other.descriptor
+                       && number == other.number;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (obj is DescriptorIntPair)
+                {
+                    return Equals((DescriptorIntPair) obj);
+                }
+                return false;
+            }
+
+            public override int GetHashCode()
+            {
+                return descriptor.GetHashCode()*((1 << 16) - 1) + number;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs
new file mode 100644
index 0000000..f5570fc
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs
@@ -0,0 +1,64 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Internal class containing utility methods when working with descriptors.
+    /// </summary>
+    internal static class DescriptorUtil
+    {
+        /// <summary>
+        /// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert
+        /// arrays.
+        /// </summary>
+        internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index);
+
+        /// <summary>
+        /// Converts the given array into a read-only list, applying the specified conversion to
+        /// each input element.
+        /// </summary>
+        internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>
+            (IList<TInput> input, IndexedConverter<TInput, TOutput> converter)
+        {
+            TOutput[] array = new TOutput[input.Count];
+            for (int i = 0; i < array.Length; i++)
+            {
+                array[i] = converter(input[i], i);
+            }
+            return new ReadOnlyCollection<TOutput>(array);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs
new file mode 100644
index 0000000..143671d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs
@@ -0,0 +1,80 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Thrown when building descriptors fails because the source DescriptorProtos
+    /// are not valid.
+    /// </summary>
+    public sealed class DescriptorValidationException : Exception
+    {
+        private readonly String name;
+        private readonly string description;
+
+        /// <value>
+        /// The full name of the descriptor where the error occurred.
+        /// </value>
+        public String ProblemSymbolName
+        {
+            get { return name; }
+        }
+
+        /// <value>
+        /// A human-readable description of the error. (The Message property
+        /// is made up of the descriptor's name and this description.)
+        /// </value>
+        public string Description
+        {
+            get { return description; }
+        }
+
+        internal DescriptorValidationException(IDescriptor problemDescriptor, string description) :
+            base(problemDescriptor.FullName + ": " + description)
+        {
+            // Note that problemDescriptor may be partially uninitialized, so we
+            // don't want to expose it directly to the user.  So, we only provide
+            // the name and the original proto.
+            name = problemDescriptor.FullName;
+            this.description = description;
+        }
+
+        internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) :
+            base(problemDescriptor.FullName + ": " + description, cause)
+        {
+            name = problemDescriptor.FullName;
+            this.description = description;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
new file mode 100644
index 0000000..c732c93
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
@@ -0,0 +1,116 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Descriptor for an enum type in a .proto file.
+    /// </summary>
+    public sealed class EnumDescriptor : DescriptorBase
+    {
+        private readonly EnumDescriptorProto proto;
+        private readonly MessageDescriptor containingType;
+        private readonly IList<EnumValueDescriptor> values;
+        private readonly Type clrType;
+
+        internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type clrType)
+            : base(file, file.ComputeFullName(parent, proto.Name), index)
+        {
+            this.proto = proto;
+            this.clrType = clrType;
+            containingType = parent;
+
+            if (proto.Value.Count == 0)
+            {
+                // We cannot allow enums with no values because this would mean there
+                // would be no valid default value for fields of this type.
+                throw new DescriptorValidationException(this, "Enums must contain at least one value.");
+            }
+
+            values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value,
+                                                           (value, i) => new EnumValueDescriptor(value, file, this, i));
+
+            File.DescriptorPool.AddSymbol(this);
+        }
+
+        internal EnumDescriptorProto Proto { get { return proto; } }
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name { get { return proto.Name; } }
+
+        /// <summary>
+        /// The CLR type for this enum. For generated code, this will be a CLR enum type.
+        /// </summary>
+        public Type ClrType { get { return clrType; } }
+
+        /// <value>
+        /// If this is a nested type, get the outer descriptor, otherwise null.
+        /// </value>
+        public MessageDescriptor ContainingType
+        {
+            get { return containingType; }
+        }
+
+        /// <value>
+        /// An unmodifiable list of defined value descriptors for this enum.
+        /// </value>
+        public IList<EnumValueDescriptor> Values
+        {
+            get { return values; }
+        }
+
+        /// <summary>
+        /// Finds an enum value by number. If multiple enum values have the
+        /// same number, this returns the first defined value with that number.
+        /// If there is no value for the given number, this returns <c>null</c>.
+        /// </summary>
+        public EnumValueDescriptor FindValueByNumber(int number)
+        {
+            return File.DescriptorPool.FindEnumValueByNumber(this, number);
+        }
+
+        /// <summary>
+        /// Finds an enum value by name.
+        /// </summary>
+        /// <param name="name">The unqualified name of the value (e.g. "FOO").</param>
+        /// <returns>The value's descriptor, or null if not found.</returns>
+        public EnumValueDescriptor FindValueByName(string name)
+        {
+            return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
new file mode 100644
index 0000000..b212ce9
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
@@ -0,0 +1,70 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Descriptor for a single enum value within an enum in a .proto file.
+    /// </summary>
+    public sealed class EnumValueDescriptor : DescriptorBase                                            
+    {
+        private readonly EnumDescriptor enumDescriptor;
+        private readonly EnumValueDescriptorProto proto;
+
+        internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
+                                     EnumDescriptor parent, int index)
+            : base(file, parent.FullName + "." + proto.Name, index)
+        {
+            this.proto = proto;
+            enumDescriptor = parent;
+            file.DescriptorPool.AddSymbol(this);
+            file.DescriptorPool.AddEnumValueByNumber(this);
+        }
+
+        internal EnumValueDescriptorProto Proto { get { return proto; } }
+
+        /// <summary>
+        /// Returns the name of the enum value described by this object.
+        /// </summary>
+        public override string Name { get { return proto.Name; } }
+
+        /// <summary>
+        /// Returns the number associated with this enum value.
+        /// </summary>
+        public int Number { get { return Proto.Number; } }
+
+        /// <summary>
+        /// Returns the enum descriptor that this value is part of.
+        /// </summary>
+        public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
new file mode 100644
index 0000000..82ce505
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
@@ -0,0 +1,63 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Reflection;
+using Google.Protobuf.Compatibility;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Base class for field accessors.
+    /// </summary>
+    internal abstract class FieldAccessorBase : IFieldAccessor
+    {
+        private readonly Func<IMessage, object> getValueDelegate;
+        private readonly FieldDescriptor descriptor;
+
+        internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor)
+        {
+            this.descriptor = descriptor;
+            getValueDelegate = ReflectionUtil.CreateFuncIMessageObject(property.GetGetMethod());
+        }
+
+        public FieldDescriptor Descriptor { get { return descriptor; } }
+
+        public object GetValue(IMessage message)
+        {
+            return getValueDelegate(message);
+        }
+
+        public abstract void Clear(IMessage message);
+        public abstract void SetValue(IMessage message, object value);
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
new file mode 100644
index 0000000..6c6f6ee
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
@@ -0,0 +1,343 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Compatibility;
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Descriptor for a field or extension within a message in a .proto file.
+    /// </summary>
+    public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescriptor>
+    {
+        private EnumDescriptor enumType;
+        private MessageDescriptor messageType;
+        private FieldType fieldType;
+        private readonly string propertyName; // Annoyingly, needed in Crosslink.
+        private IFieldAccessor accessor;
+
+        /// <summary>
+        /// Get the field's containing message type.
+        /// </summary>
+        public MessageDescriptor ContainingType { get; }
+
+        /// <summary>
+        /// Returns the oneof containing this field, or <c>null</c> if it is not part of a oneof.
+        /// </summary>
+        public OneofDescriptor ContainingOneof { get; }
+
+        /// <summary>
+        /// The effective JSON name for this field. This is usually the lower-camel-cased form of the field name,
+        /// but can be overridden using the <c>json_name</c> option in the .proto file.
+        /// </summary>
+        public string JsonName { get; }
+
+        internal FieldDescriptorProto Proto { get; }
+
+        internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
+                                 MessageDescriptor parent, int index, string propertyName)
+            : base(file, file.ComputeFullName(parent, proto.Name), index)
+        {
+            Proto = proto;
+            if (proto.Type != 0)
+            {
+                fieldType = GetFieldTypeFromProtoType(proto.Type);
+            }
+
+            if (FieldNumber <= 0)
+            {
+                throw new DescriptorValidationException(this, "Field numbers must be positive integers.");
+            }
+            ContainingType = parent;
+            // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction.
+            if (proto.OneofIndex != -1)
+            {
+                if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
+                {
+                    throw new DescriptorValidationException(this,
+                        $"FieldDescriptorProto.oneof_index is out of range for type {parent.Name}");
+                }
+                ContainingOneof = parent.Oneofs[proto.OneofIndex];
+            }
+
+            file.DescriptorPool.AddSymbol(this);
+            // We can't create the accessor until we've cross-linked, unfortunately, as we
+            // may not know whether the type of the field is a map or not. Remember the property name
+            // for later.
+            // We could trust the generated code and check whether the type of the property is
+            // a MapField, but that feels a tad nasty.
+            this.propertyName = propertyName;
+            JsonName =  Proto.JsonName == "" ? JsonFormatter.ToCamelCase(Proto.Name) : Proto.JsonName;
+        }
+    
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name => Proto.Name;
+
+        /// <summary>
+        /// Returns the accessor for this field.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// While a <see cref="FieldDescriptor"/> describes the field, it does not provide
+        /// any way of obtaining or changing the value of the field within a specific message;
+        /// that is the responsibility of the accessor.
+        /// </para>
+        /// <para>
+        /// The value returned by this property will be non-null for all regular fields. However,
+        /// if a message containing a map field is introspected, the list of nested messages will include
+        /// an auto-generated nested key/value pair message for the field. This is not represented in any
+        /// generated type, and the value of the map field itself is represented by a dictionary in the
+        /// reflection API. There are never instances of those "hidden" messages, so no accessor is provided
+        /// and this property will return null.
+        /// </para>
+        /// </remarks>
+        public IFieldAccessor Accessor => accessor;
+        
+        /// <summary>
+        /// Maps a field type as included in the .proto file to a FieldType.
+        /// </summary>
+        private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type)
+        {
+            switch (type)
+            {
+                case FieldDescriptorProto.Types.Type.Double:
+                    return FieldType.Double;
+                case FieldDescriptorProto.Types.Type.Float:
+                    return FieldType.Float;
+                case FieldDescriptorProto.Types.Type.Int64:
+                    return FieldType.Int64;
+                case FieldDescriptorProto.Types.Type.Uint64:
+                    return FieldType.UInt64;
+                case FieldDescriptorProto.Types.Type.Int32:
+                    return FieldType.Int32;
+                case FieldDescriptorProto.Types.Type.Fixed64:
+                    return FieldType.Fixed64;
+                case FieldDescriptorProto.Types.Type.Fixed32:
+                    return FieldType.Fixed32;
+                case FieldDescriptorProto.Types.Type.Bool:
+                    return FieldType.Bool;
+                case FieldDescriptorProto.Types.Type.String:
+                    return FieldType.String;
+                case FieldDescriptorProto.Types.Type.Group:
+                    return FieldType.Group;
+                case FieldDescriptorProto.Types.Type.Message:
+                    return FieldType.Message;
+                case FieldDescriptorProto.Types.Type.Bytes:
+                    return FieldType.Bytes;
+                case FieldDescriptorProto.Types.Type.Uint32:
+                    return FieldType.UInt32;
+                case FieldDescriptorProto.Types.Type.Enum:
+                    return FieldType.Enum;
+                case FieldDescriptorProto.Types.Type.Sfixed32:
+                    return FieldType.SFixed32;
+                case FieldDescriptorProto.Types.Type.Sfixed64:
+                    return FieldType.SFixed64;
+                case FieldDescriptorProto.Types.Type.Sint32:
+                    return FieldType.SInt32;
+                case FieldDescriptorProto.Types.Type.Sint64:
+                    return FieldType.SInt64;
+                default:
+                    throw new ArgumentException("Invalid type specified");
+            }
+        }
+
+        /// <summary>
+        /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise.
+        /// </summary>
+        public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.Repeated;
+
+        /// <summary>
+        /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise.
+        /// </summary>
+        public bool IsMap => fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry;
+
+        /// <summary>
+        /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
+        /// </summary>
+        public bool IsPacked => 
+            // Note the || rather than && here - we're effectively defaulting to packed, because that *is*
+            // the default in proto3, which is all we support. We may give the wrong result for the protos
+            // within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked
+            // within the runtime.
+            Proto.Options == null || Proto.Options.Packed;
+        
+        /// <summary>
+        /// Returns the type of the field.
+        /// </summary>
+        public FieldType FieldType => fieldType;
+
+        /// <summary>
+        /// Returns the field number declared in the proto file.
+        /// </summary>
+        public int FieldNumber => Proto.Number;
+
+        /// <summary>
+        /// Compares this descriptor with another one, ordering in "canonical" order
+        /// which simply means ascending order by field number. <paramref name="other"/>
+        /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
+        /// both fields must be the same.
+        /// </summary>
+        public int CompareTo(FieldDescriptor other)
+        {
+            if (other.ContainingType != ContainingType)
+            {
+                throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " +
+                                            "for fields of the same message type.");
+            }
+            return FieldNumber - other.FieldNumber;
+        }
+
+        /// <summary>
+        /// For enum fields, returns the field's type.
+        /// </summary>
+        public EnumDescriptor EnumType
+        {
+            get
+            {
+                if (fieldType != FieldType.Enum)
+                {
+                    throw new InvalidOperationException("EnumType is only valid for enum fields.");
+                }
+                return enumType;
+            }
+        }
+
+        /// <summary>
+        /// For embedded message and group fields, returns the field's type.
+        /// </summary>
+        public MessageDescriptor MessageType
+        {
+            get
+            {
+                if (fieldType != FieldType.Message)
+                {
+                    throw new InvalidOperationException("MessageType is only valid for message fields.");
+                }
+                return messageType;
+            }
+        }
+
+        /// <summary>
+        /// Look up and cross-link all field types etc.
+        /// </summary>
+        internal void CrossLink()
+        {
+            if (Proto.TypeName != "")
+            {
+                IDescriptor typeDescriptor =
+                    File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
+
+                if (Proto.Type != 0)
+                {
+                    // Choose field type based on symbol.
+                    if (typeDescriptor is MessageDescriptor)
+                    {
+                        fieldType = FieldType.Message;
+                    }
+                    else if (typeDescriptor is EnumDescriptor)
+                    {
+                        fieldType = FieldType.Enum;
+                    }
+                    else
+                    {
+                        throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a type.");
+                    }
+                }
+
+                if (fieldType == FieldType.Message)
+                {
+                    if (!(typeDescriptor is MessageDescriptor))
+                    {
+                        throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type.");
+                    }
+                    messageType = (MessageDescriptor) typeDescriptor;
+
+                    if (Proto.DefaultValue != "")
+                    {
+                        throw new DescriptorValidationException(this, "Messages can't have default values.");
+                    }
+                }
+                else if (fieldType == FieldType.Enum)
+                {
+                    if (!(typeDescriptor is EnumDescriptor))
+                    {
+                        throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not an enum type.");
+                    }
+                    enumType = (EnumDescriptor) typeDescriptor;
+                }
+                else
+                {
+                    throw new DescriptorValidationException(this, "Field with primitive type has type_name.");
+                }
+            }
+            else
+            {
+                if (fieldType == FieldType.Message || fieldType == FieldType.Enum)
+                {
+                    throw new DescriptorValidationException(this, "Field with message or enum type missing type_name.");
+                }
+            }
+
+            // Note: no attempt to perform any default value parsing
+
+            File.DescriptorPool.AddFieldByNumber(this);
+
+            if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat)
+            {
+                throw new DescriptorValidationException(this, "MessageSet format is not supported.");
+            }
+            accessor = CreateAccessor();
+        }
+
+        private IFieldAccessor CreateAccessor()
+        {
+            // If we're given no property name, that's because we really don't want an accessor.
+            // (At the moment, that means it's a map entry message...)
+            if (propertyName == null)
+            {
+                return null;
+            }
+            var property = ContainingType.ClrType.GetProperty(propertyName);
+            if (property == null)
+            {
+                throw new DescriptorValidationException(this, $"Property {propertyName} not found in {ContainingType.ClrType}");
+            }
+            return IsMap ? new MapFieldAccessor(property, this)
+                : IsRepeated ? new RepeatedFieldAccessor(property, this)
+                : (IFieldAccessor) new SingleFieldAccessor(property, this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldType.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldType.cs
new file mode 100644
index 0000000..1658e34
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FieldType.cs
@@ -0,0 +1,113 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Enumeration of all the possible field types.
+    /// </summary>
+    public enum FieldType
+    {
+        /// <summary>
+        /// The <c>double</c> field type.
+        /// </summary>
+        Double,
+        /// <summary>
+        /// The <c>float</c> field type.
+        /// </summary>
+        Float,
+        /// <summary>
+        /// The <c>int64</c> field type.
+        /// </summary>
+        Int64,
+        /// <summary>
+        /// The <c>uint64</c> field type.
+        /// </summary>
+        UInt64,
+        /// <summary>
+        /// The <c>int32</c> field type.
+        /// </summary>
+        Int32,
+        /// <summary>
+        /// The <c>fixed64</c> field type.
+        /// </summary>
+        Fixed64,
+        /// <summary>
+        /// The <c>fixed32</c> field type.
+        /// </summary>
+        Fixed32,
+        /// <summary>
+        /// The <c>bool</c> field type.
+        /// </summary>
+        Bool,
+        /// <summary>
+        /// The <c>string</c> field type.
+        /// </summary>
+        String,
+        /// <summary>
+        /// The field type used for groups (not supported in this implementation).
+        /// </summary>
+        Group,
+        /// <summary>
+        /// The field type used for message fields.
+        /// </summary>
+        Message,
+        /// <summary>
+        /// The <c>bytes</c> field type.
+        /// </summary>
+        Bytes,
+        /// <summary>
+        /// The <c>uint32</c> field type.
+        /// </summary>
+        UInt32,
+        /// <summary>
+        /// The <c>sfixed32</c> field type.
+        /// </summary>
+        SFixed32,
+        /// <summary>
+        /// The <c>sfixed64</c> field type.
+        /// </summary>
+        SFixed64,
+        /// <summary>
+        /// The <c>sint32</c> field type.
+        /// </summary>
+        SInt32,
+        /// <summary>
+        /// The <c>sint64</c> field type.
+        /// </summary>
+        SInt64,
+        /// <summary>
+        /// The field type used for enum fields.
+        /// </summary>
+        Enum
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
new file mode 100644
index 0000000..ab7cd92
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -0,0 +1,344 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Describes a .proto file, including everything defined within.
+    /// IDescriptor is implemented such that the File property returns this descriptor,
+    /// and the FullName is the same as the Name.
+    /// </summary>
+    public sealed class FileDescriptor : IDescriptor
+    {
+        private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo)
+        {
+            SerializedData = descriptorData;
+            DescriptorPool = pool;
+            Proto = proto;
+            Dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone());
+
+            PublicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies);
+
+            pool.AddPackage(Package, this);
+
+            MessageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType,
+                                                                 (message, index) =>
+                                                                 new MessageDescriptor(message, this, null, index, generatedCodeInfo.NestedTypes[index]));
+
+            EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType,
+                                                              (enumType, index) =>
+                                                              new EnumDescriptor(enumType, this, null, index, generatedCodeInfo.NestedEnums[index]));
+
+            Services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service,
+                                                             (service, index) =>
+                                                             new ServiceDescriptor(service, this, index));
+        }
+
+        /// <summary>
+        /// Computes the full name of a descriptor within this file, with an optional parent message.
+        /// </summary>
+        internal string ComputeFullName(MessageDescriptor parent, string name)
+        {
+            if (parent != null)
+            {
+                return parent.FullName + "." + name;
+            }
+            if (Package.Length > 0)
+            {
+                return Package + "." + name;
+            }
+            return name;
+        }
+
+        /// <summary>
+        /// Extracts public dependencies from direct dependencies. This is a static method despite its
+        /// first parameter, as the value we're in the middle of constructing is only used for exceptions.
+        /// </summary>
+        private static IList<FileDescriptor> DeterminePublicDependencies(FileDescriptor @this, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies)
+        {
+            var nameToFileMap = new Dictionary<string, FileDescriptor>();
+            foreach (var file in dependencies)
+            {
+                nameToFileMap[file.Name] = file;
+            }
+            var publicDependencies = new List<FileDescriptor>();
+            for (int i = 0; i < proto.PublicDependency.Count; i++)
+            {
+                int index = proto.PublicDependency[i];
+                if (index < 0 || index >= proto.Dependency.Count)
+                {
+                    throw new DescriptorValidationException(@this, "Invalid public dependency index.");
+                }
+                string name = proto.Dependency[index];
+                FileDescriptor file = nameToFileMap[name];
+                if (file == null)
+                {
+                    if (!allowUnknownDependencies)
+                    {
+                        throw new DescriptorValidationException(@this, "Invalid public dependency: " + name);
+                    }
+                    // Ignore unknown dependencies.
+                }
+                else
+                {
+                    publicDependencies.Add(file);
+                }
+            }
+            return new ReadOnlyCollection<FileDescriptor>(publicDependencies);
+        }
+
+        /// <value>
+        /// The descriptor in its protocol message representation.
+        /// </value>
+        internal FileDescriptorProto Proto { get; }
+
+        /// <value>
+        /// The file name.
+        /// </value>
+        public string Name => Proto.Name;
+
+        /// <summary>
+        /// The package as declared in the .proto file. This may or may not
+        /// be equivalent to the .NET namespace of the generated classes.
+        /// </summary>
+        public string Package => Proto.Package;
+
+        /// <value>
+        /// Unmodifiable list of top-level message types declared in this file.
+        /// </value>
+        public IList<MessageDescriptor> MessageTypes { get; }
+
+        /// <value>
+        /// Unmodifiable list of top-level enum types declared in this file.
+        /// </value>
+        public IList<EnumDescriptor> EnumTypes { get; }
+
+        /// <value>
+        /// Unmodifiable list of top-level services declared in this file.
+        /// </value>
+        public IList<ServiceDescriptor> Services { get; }
+
+        /// <value>
+        /// Unmodifiable list of this file's dependencies (imports).
+        /// </value>
+        public IList<FileDescriptor> Dependencies { get; }
+
+        /// <value>
+        /// Unmodifiable list of this file's public dependencies (public imports).
+        /// </value>
+        public IList<FileDescriptor> PublicDependencies { get; }
+
+        /// <value>
+        /// The original serialized binary form of this descriptor.
+        /// </value>
+        public ByteString SerializedData { get; }
+
+        /// <value>
+        /// Implementation of IDescriptor.FullName - just returns the same as Name.
+        /// </value>
+        string IDescriptor.FullName => Name;
+
+        /// <value>
+        /// Implementation of IDescriptor.File - just returns this descriptor.
+        /// </value>
+        FileDescriptor IDescriptor.File => this;
+
+        /// <value>
+        /// Pool containing symbol descriptors.
+        /// </value>
+        internal DescriptorPool DescriptorPool { get; }
+
+        /// <summary>
+        /// Finds a type (message, enum, service or extension) in the file by name. Does not find nested types.
+        /// </summary>
+        /// <param name="name">The unqualified type name to look for.</param>
+        /// <typeparam name="T">The type of descriptor to look for</typeparam>
+        /// <returns>The type's descriptor, or null if not found.</returns>
+        public T FindTypeByName<T>(String name)
+            where T : class, IDescriptor
+        {
+            // Don't allow looking up nested types.  This will make optimization
+            // easier later.
+            if (name.IndexOf('.') != -1)
+            {
+                return null;
+            }
+            if (Package.Length > 0)
+            {
+                name = Package + "." + name;
+            }
+            T result = DescriptorPool.FindSymbol<T>(name);
+            if (result != null && result.File == this)
+            {
+                return result;
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Builds a FileDescriptor from its protocol buffer representation.
+        /// </summary>
+        /// <param name="descriptorData">The original serialized descriptor data.
+        /// We have only limited proto2 support, so serializing FileDescriptorProto
+        /// would not necessarily give us this.</param>
+        /// <param name="proto">The protocol message form of the FileDescriptor.</param>
+        /// <param name="dependencies">FileDescriptors corresponding to all of the
+        /// file's dependencies, in the exact order listed in the .proto file. May be null,
+        /// in which case it is treated as an empty array.</param>
+        /// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param>
+        /// <param name="generatedCodeInfo">Details about generated code, for the purposes of reflection.</param>
+        /// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not
+        /// a valid descriptor. This can occur for a number of reasons, such as a field
+        /// having an undefined type or because two messages were defined with the same name.</exception>
+        private static FileDescriptor BuildFrom(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo)
+        {
+            // Building descriptors involves two steps: translating and linking.
+            // In the translation step (implemented by FileDescriptor's
+            // constructor), we build an object tree mirroring the
+            // FileDescriptorProto's tree and put all of the descriptors into the
+            // DescriptorPool's lookup tables.  In the linking step, we look up all
+            // type references in the DescriptorPool, so that, for example, a
+            // FieldDescriptor for an embedded message contains a pointer directly
+            // to the Descriptor for that message's type.  We also detect undefined
+            // types in the linking step.
+            if (dependencies == null)
+            {
+                dependencies = new FileDescriptor[0];
+            }
+
+            DescriptorPool pool = new DescriptorPool(dependencies);
+            FileDescriptor result = new FileDescriptor(descriptorData, proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo);
+
+            // Validate that the dependencies we've been passed (as FileDescriptors) are actually the ones we
+            // need.
+            if (dependencies.Length != proto.Dependency.Count)
+            {
+                throw new DescriptorValidationException(
+                    result,
+                    "Dependencies passed to FileDescriptor.BuildFrom() don't match " +
+                    "those listed in the FileDescriptorProto.");
+            }
+            for (int i = 0; i < proto.Dependency.Count; i++)
+            {
+                if (dependencies[i].Name != proto.Dependency[i])
+                {
+                    throw new DescriptorValidationException(
+                        result,
+                        "Dependencies passed to FileDescriptor.BuildFrom() don't match " +
+                        "those listed in the FileDescriptorProto. Expected: " +
+                        proto.Dependency[i] + " but was: " + dependencies[i].Name);
+                }
+            }
+
+            result.CrossLink();
+            return result;
+        }
+
+        private void CrossLink()
+        {
+            foreach (MessageDescriptor message in MessageTypes)
+            {
+                message.CrossLink();
+            }
+
+            foreach (ServiceDescriptor service in Services)
+            {
+                service.CrossLink();
+            }
+        }
+
+        /// <summary>
+        /// Creates a descriptor for generated code.
+        /// </summary>
+        /// <remarks>
+        /// This method is only designed to be used by the results of generating code with protoc,
+        /// which creates the appropriate dependencies etc. It has to be public because the generated
+        /// code is "external", but should not be called directly by end users.
+        /// </remarks>
+        public static FileDescriptor FromGeneratedCode(
+            byte[] descriptorData,
+            FileDescriptor[] dependencies,
+            GeneratedClrTypeInfo generatedCodeInfo)
+        {
+            FileDescriptorProto proto;
+            try
+            {
+                proto = FileDescriptorProto.Parser.ParseFrom(descriptorData);
+            }
+            catch (InvalidProtocolBufferException e)
+            {
+                throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e);
+            }
+
+            try
+            {
+                // When building descriptors for generated code, we allow unknown
+                // dependencies by default.
+                return BuildFrom(ByteString.CopyFrom(descriptorData), proto, dependencies, true, generatedCodeInfo);
+            }
+            catch (DescriptorValidationException e)
+            {
+                throw new ArgumentException($"Invalid embedded descriptor for \"{proto.Name}\".", e);
+            }
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String" /> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="System.String" /> that represents this instance.
+        /// </returns>
+        public override string ToString()
+        {
+            return $"FileDescriptor for {Name}";
+        }
+
+        /// <summary>
+        /// Returns the file descriptor for descriptor.proto.
+        /// </summary>
+        /// <remarks>
+        /// This is used for protos which take a direct dependency on <c>descriptor.proto</c>, typically for
+        /// annotations. While <c>descriptor.proto</c> is a proto2 file, it is built into the Google.Protobuf
+        /// runtime for reflection purposes. The messages are internal to the runtime as they would require
+        /// proto2 semantics for full support, but the file descriptor is available via this property. The
+        /// C# codegen in protoc automatically uses this property when it detects a dependency on <c>descriptor.proto</c>.
+        /// </remarks>
+        /// <value>
+        /// The file descriptor for <c>descriptor.proto</c>.
+        /// </value>
+        public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs
new file mode 100644
index 0000000..fe5db65
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs
@@ -0,0 +1,103 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Extra information provided by generated code when initializing a message or file descriptor.
+    /// These are constructed as required, and are not long-lived. Hand-written code should
+    /// never need to use this type.
+    /// </summary>
+    public sealed class GeneratedClrTypeInfo
+    {
+        private static readonly string[] EmptyNames = new string[0];
+        private static readonly GeneratedClrTypeInfo[] EmptyCodeInfo = new GeneratedClrTypeInfo[0];
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
+        /// </summary>
+        public Type ClrType { get; private set; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the parser for message descriptors.
+        /// </summary>
+        public MessageParser Parser { get; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order)
+        /// for fields in the message for message descriptors.
+        /// </summary>
+        public string[] PropertyNames { get; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order)
+        /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo",
+        /// there will be a "FooCase" property and a "ClearFoo" method.
+        /// </summary>
+        public string[] OneofNames { get; }
+
+        /// <summary>
+        /// The reflection information for types within this file/message descriptor. Elements may be null
+        /// if there is no corresponding generated type, e.g. for map entry types.
+        /// </summary>
+        public GeneratedClrTypeInfo[] NestedTypes { get; }
+
+        /// <summary>
+        /// The CLR types for enums within this file/message descriptor.
+        /// </summary>
+        public Type[] NestedEnums { get; }
+
+        /// <summary>
+        /// Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names.
+        /// Each array parameter may be null, to indicate a lack of values.
+        /// The parameter order is designed to make it feasible to format the generated code readably.
+        /// </summary>
+        public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes)
+        {
+            NestedTypes = nestedTypes ?? EmptyCodeInfo;
+            NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes;
+            ClrType = clrType;
+            Parser = parser;
+            PropertyNames = propertyNames ?? EmptyNames;
+            OneofNames = oneofNames ?? EmptyNames;
+        }
+
+        /// <summary>
+        /// Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums.
+        /// </summary>
+        public GeneratedClrTypeInfo(Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes)
+            : this(null, null, null, null, nestedEnums, nestedTypes)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs
new file mode 100644
index 0000000..318d58c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs
@@ -0,0 +1,55 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Interface implemented by all descriptor types.
+    /// </summary>
+    public interface IDescriptor
+    {
+        /// <summary>
+        /// Returns the name of the entity (message, field etc) being described.
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// Returns the fully-qualified name of the entity being described.
+        /// </summary>
+        string FullName { get; }
+
+        /// <summary>
+        /// Returns the descriptor for the .proto file that this entity is part of.
+        /// </summary>
+        FileDescriptor File { get; }
+    }    
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
new file mode 100644
index 0000000..cfe56fd
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
@@ -0,0 +1,71 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Allows fields to be reflectively accessed.
+    /// </summary>
+    public interface IFieldAccessor
+    {
+        /// <summary>
+        /// Returns the descriptor associated with this field.
+        /// </summary>
+        FieldDescriptor Descriptor { get; }
+
+        /// <summary>
+        /// Clears the field in the specified message. (For repeated fields,
+        /// this clears the list.)
+        /// </summary>
+        void Clear(IMessage message);
+
+        /// <summary>
+        /// Fetches the field value. For repeated values, this will be an
+        /// <see cref="IList"/> implementation. For map values, this will be an
+        /// <see cref="IDictionary"/> implementation.
+        /// </summary>
+        object GetValue(IMessage message);
+
+        /// <summary>
+        /// Mutator for single "simple" fields only.
+        /// </summary>
+        /// <remarks>
+        /// Repeated fields are mutated by fetching the value and manipulating it as a list.
+        /// Map fields are mutated by fetching the value and manipulating it as a dictionary.
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">The field is not a "simple" field.</exception>
+        void SetValue(IMessage message, object value);
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
new file mode 100644
index 0000000..9ed7f8c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Reflection;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Accessor for map fields.
+    /// </summary>
+    internal sealed class MapFieldAccessor : FieldAccessorBase
+    {
+        internal MapFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
+        {
+        }
+
+        public override void Clear(IMessage message)
+        {
+            IDictionary list = (IDictionary) GetValue(message);
+            list.Clear();
+        }
+
+        public override void SetValue(IMessage message, object value)
+        {
+            throw new InvalidOperationException("SetValue is not implemented for map fields");
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
new file mode 100644
index 0000000..f5a835e
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -0,0 +1,317 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Describes a message type.
+    /// </summary>
+    public sealed class MessageDescriptor : DescriptorBase
+    {
+        private static readonly HashSet<string> WellKnownTypeNames = new HashSet<string>
+        {
+            "google/protobuf/any.proto",
+            "google/protobuf/api.proto",
+            "google/protobuf/duration.proto",
+            "google/protobuf/empty.proto",
+            "google/protobuf/wrappers.proto",
+            "google/protobuf/timestamp.proto",
+            "google/protobuf/field_mask.proto",
+            "google/protobuf/source_context.proto",
+            "google/protobuf/struct.proto",
+            "google/protobuf/type.proto",
+        };
+
+        private readonly IList<FieldDescriptor> fieldsInDeclarationOrder;
+        private readonly IList<FieldDescriptor> fieldsInNumberOrder;
+        private readonly IDictionary<string, FieldDescriptor> jsonFieldMap;
+        
+        internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedClrTypeInfo generatedCodeInfo)
+            : base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
+        {
+            Proto = proto;
+            Parser = generatedCodeInfo?.Parser;
+            ClrType = generatedCodeInfo?.ClrType;
+            ContainingType = parent;
+
+            // Note use of generatedCodeInfo. rather than generatedCodeInfo?. here... we don't expect
+            // to see any nested oneofs, types or enums in "not actually generated" code... we do
+            // expect fields though (for map entry messages).
+            Oneofs = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.OneofDecl,
+                (oneof, index) =>
+                new OneofDescriptor(oneof, file, this, index, generatedCodeInfo.OneofNames[index]));
+
+            NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.NestedType,
+                (type, index) =>
+                new MessageDescriptor(type, file, this, index, generatedCodeInfo.NestedTypes[index]));
+
+            EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.EnumType,
+                (type, index) =>
+                new EnumDescriptor(type, file, this, index, generatedCodeInfo.NestedEnums[index]));
+
+            fieldsInDeclarationOrder = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.Field,
+                (field, index) =>
+                new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index]));
+            fieldsInNumberOrder = new ReadOnlyCollection<FieldDescriptor>(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray());
+            // TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.)
+            jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder);
+            file.DescriptorPool.AddSymbol(this);
+            Fields = new FieldCollection(this);
+        }
+
+        private static ReadOnlyDictionary<string, FieldDescriptor> CreateJsonFieldMap(IList<FieldDescriptor> fields)
+        {
+            var map = new Dictionary<string, FieldDescriptor>();
+            foreach (var field in fields)
+            {
+                map[field.Name] = field;
+                map[field.JsonName] = field;
+            }
+            return new ReadOnlyDictionary<string, FieldDescriptor>(map);
+        }
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name => Proto.Name;
+
+        internal DescriptorProto Proto { get; }
+
+        /// <summary>
+        /// The CLR type used to represent message instances from this descriptor.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// The value returned by this property will be non-null for all regular fields. However,
+        /// if a message containing a map field is introspected, the list of nested messages will include
+        /// an auto-generated nested key/value pair message for the field. This is not represented in any
+        /// generated type, so this property will return null in such cases.
+        /// </para>
+        /// <para>
+        /// For wrapper types (<see cref="Google.Protobuf.WellKnownTypes.StringValue"/> and the like), the type returned here
+        /// will be the generated message type, not the native type used by reflection for fields of those types. Code
+        /// using reflection should call <see cref="IsWrapperType"/> to determine whether a message descriptor represents
+        /// a wrapper type, and handle the result appropriately.
+        /// </para>
+        /// </remarks>
+        public Type ClrType { get; }
+
+        /// <summary>
+        /// A parser for this message type.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As <see cref="MessageDescriptor"/> is not generic, this cannot be statically
+        /// typed to the relevant type, but it should produce objects of a type compatible with <see cref="ClrType"/>.
+        /// </para>
+        /// <para>
+        /// The value returned by this property will be non-null for all regular fields. However,
+        /// if a message containing a map field is introspected, the list of nested messages will include
+        /// an auto-generated nested key/value pair message for the field. No message parser object is created for
+        /// such messages, so this property will return null in such cases.
+        /// </para>
+        /// <para>
+        /// For wrapper types (<see cref="Google.Protobuf.WellKnownTypes.StringValue"/> and the like), the parser returned here
+        /// will be the generated message type, not the native type used by reflection for fields of those types. Code
+        /// using reflection should call <see cref="IsWrapperType"/> to determine whether a message descriptor represents
+        /// a wrapper type, and handle the result appropriately.
+        /// </para>
+        /// </remarks>
+        public MessageParser Parser { get; }
+
+        /// <summary>
+        /// Returns whether this message is one of the "well known types" which may have runtime/protoc support.
+        /// </summary>
+        internal bool IsWellKnownType => File.Package == "google.protobuf" && WellKnownTypeNames.Contains(File.Name);
+
+        /// <summary>
+        /// Returns whether this message is one of the "wrapper types" used for fields which represent primitive values
+        /// with the addition of presence.
+        /// </summary>
+        internal bool IsWrapperType => File.Package == "google.protobuf" && File.Name == "google/protobuf/wrappers.proto";
+
+        /// <value>
+        /// If this is a nested type, get the outer descriptor, otherwise null.
+        /// </value>
+        public MessageDescriptor ContainingType { get; }
+
+        /// <value>
+        /// A collection of fields, which can be retrieved by name or field number.
+        /// </value>
+        public FieldCollection Fields { get; }
+
+        /// <value>
+        /// An unmodifiable list of this message type's nested types.
+        /// </value>
+        public IList<MessageDescriptor> NestedTypes { get; }
+
+        /// <value>
+        /// An unmodifiable list of this message type's enum types.
+        /// </value>
+        public IList<EnumDescriptor> EnumTypes { get; }
+
+        /// <value>
+        /// An unmodifiable list of the "oneof" field collections in this message type.
+        /// </value>
+        public IList<OneofDescriptor> Oneofs { get; }
+
+        /// <summary>
+        /// Finds a field by field name.
+        /// </summary>
+        /// <param name="name">The unqualified name of the field (e.g. "foo").</param>
+        /// <returns>The field's descriptor, or null if not found.</returns>
+        public FieldDescriptor FindFieldByName(String name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
+
+        /// <summary>
+        /// Finds a field by field number.
+        /// </summary>
+        /// <param name="number">The field number within this message type.</param>
+        /// <returns>The field's descriptor, or null if not found.</returns>
+        public FieldDescriptor FindFieldByNumber(int number) => File.DescriptorPool.FindFieldByNumber(this, number);
+
+        /// <summary>
+        /// Finds a nested descriptor by name. The is valid for fields, nested
+        /// message types, oneofs and enums.
+        /// </summary>
+        /// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param>
+        /// <returns>The descriptor, or null if not found.</returns>
+        public T FindDescriptor<T>(string name)  where T : class, IDescriptor =>
+            File.DescriptorPool.FindSymbol<T>(FullName + "." + name);
+
+        /// <summary>
+        /// Looks up and cross-links all fields and nested types.
+        /// </summary>
+        internal void CrossLink()
+        {
+            foreach (MessageDescriptor message in NestedTypes)
+            {
+                message.CrossLink();
+            }
+
+            foreach (FieldDescriptor field in fieldsInDeclarationOrder)
+            {
+                field.CrossLink();
+            }
+
+            foreach (OneofDescriptor oneof in Oneofs)
+            {
+                oneof.CrossLink();
+            }
+        }
+
+        /// <summary>
+        /// A collection to simplify retrieving the field accessor for a particular field.
+        /// </summary>
+        public sealed class FieldCollection
+        {
+            private readonly MessageDescriptor messageDescriptor;
+
+            internal FieldCollection(MessageDescriptor messageDescriptor)
+            {
+                this.messageDescriptor = messageDescriptor;
+            }
+
+            /// <value>
+            /// Returns the fields in the message as an immutable list, in the order in which they
+            /// are declared in the source .proto file.
+            /// </value>
+            public IList<FieldDescriptor> InDeclarationOrder() => messageDescriptor.fieldsInDeclarationOrder;
+
+            /// <value>
+            /// Returns the fields in the message as an immutable list, in ascending field number
+            /// order. Field numbers need not be contiguous, so there is no direct mapping from the
+            /// index in the list to the field number; to retrieve a field by field number, it is better
+            /// to use the <see cref="FieldCollection"/> indexer.
+            /// </value>
+            public IList<FieldDescriptor> InFieldNumberOrder() => messageDescriptor.fieldsInNumberOrder;
+
+            // TODO: consider making this public in the future. (Being conservative for now...)
+
+            /// <value>
+            /// Returns a read-only dictionary mapping the field names in this message as they're available
+            /// in the JSON representation to the field descriptors. For example, a field <c>foo_bar</c>
+            /// in the message would result two entries, one with a key <c>fooBar</c> and one with a key
+            /// <c>foo_bar</c>, both referring to the same field.
+            /// </value>
+            internal IDictionary<string, FieldDescriptor> ByJsonName() => messageDescriptor.jsonFieldMap;
+
+            /// <summary>
+            /// Retrieves the descriptor for the field with the given number.
+            /// </summary>
+            /// <param name="number">Number of the field to retrieve the descriptor for</param>
+            /// <returns>The accessor for the given field</returns>
+            /// <exception cref="KeyNotFoundException">The message descriptor does not contain a field
+            /// with the given number</exception>
+            public FieldDescriptor this[int number]
+            {
+                get
+                {
+                    var fieldDescriptor = messageDescriptor.FindFieldByNumber(number);
+                    if (fieldDescriptor == null)
+                    {
+                        throw new KeyNotFoundException("No such field number");
+                    }
+                    return fieldDescriptor;
+                }
+            }
+
+            /// <summary>
+            /// Retrieves the descriptor for the field with the given name.
+            /// </summary>
+            /// <param name="name">Name of the field to retrieve the descriptor for</param>
+            /// <returns>The descriptor for the given field</returns>
+            /// <exception cref="KeyNotFoundException">The message descriptor does not contain a field
+            /// with the given name</exception>
+            public FieldDescriptor this[string name]
+            {
+                get
+                {
+                    var fieldDescriptor = messageDescriptor.FindFieldByName(name);
+                    if (fieldDescriptor == null)
+                    {
+                        throw new KeyNotFoundException("No such field name");
+                    }
+                    return fieldDescriptor;
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
new file mode 100644
index 0000000..f9539f6
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
@@ -0,0 +1,103 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Describes a single method in a service.
+    /// </summary>
+    public sealed class MethodDescriptor : DescriptorBase
+    {
+        private readonly MethodDescriptorProto proto;
+        private readonly ServiceDescriptor service;
+        private MessageDescriptor inputType;
+        private MessageDescriptor outputType;
+
+        /// <value>
+        /// The service this method belongs to.
+        /// </value>
+        public ServiceDescriptor Service { get { return service; } }
+
+        /// <value>
+        /// The method's input type.
+        /// </value>
+        public MessageDescriptor InputType { get { return inputType; } }
+
+        /// <value>
+        /// The method's input type.
+        /// </value>
+        public MessageDescriptor OutputType { get { return outputType; } }
+
+        /// <value>
+        /// Indicates if client streams multiple requests.
+        /// </value>
+        public bool IsClientStreaming { get { return proto.ClientStreaming; } }
+
+        /// <value>
+        /// Indicates if server streams multiple responses.
+        /// </value>
+        public bool IsServerStreaming { get { return proto.ServerStreaming; } }
+
+        internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,
+                                  ServiceDescriptor parent, int index)
+            : base(file, parent.FullName + "." + proto.Name, index)
+        {
+            this.proto = proto;
+            service = parent;
+            file.DescriptorPool.AddSymbol(this);
+        }
+
+        internal MethodDescriptorProto Proto { get { return proto; } }
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name { get { return proto.Name; } }
+
+        internal void CrossLink()
+        {
+            IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
+            if (!(lookup is MessageDescriptor))
+            {
+                throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type.");
+            }
+            inputType = (MessageDescriptor) lookup;
+
+            lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this);
+            if (!(lookup is MessageDescriptor))
+            {
+                throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type.");
+            }
+            outputType = (MessageDescriptor) lookup;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
new file mode 100644
index 0000000..8714ab1
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
@@ -0,0 +1,90 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Reflection;
+using Google.Protobuf.Compatibility;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Reflection access for a oneof, allowing clear and "get case" actions.
+    /// </summary>
+    public sealed class OneofAccessor
+    {
+        private readonly Func<IMessage, int> caseDelegate;
+        private readonly Action<IMessage> clearDelegate;
+        private OneofDescriptor descriptor;
+
+        internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) 
+        {
+            if (!caseProperty.CanRead)
+            {
+                throw new ArgumentException("Cannot read from property");
+            }
+            this.descriptor = descriptor;
+            caseDelegate = ReflectionUtil.CreateFuncIMessageT<int>(caseProperty.GetGetMethod());
+
+            this.descriptor = descriptor;
+            clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
+        }
+
+        /// <summary>
+        /// Gets the descriptor for this oneof.
+        /// </summary>
+        /// <value>
+        /// The descriptor of the oneof.
+        /// </value>
+        public OneofDescriptor Descriptor { get { return descriptor; } }
+
+        /// <summary>
+        /// Clears the oneof in the specified message.
+        /// </summary>
+        public void Clear(IMessage message)
+        {
+            clearDelegate(message);
+        }
+
+        /// <summary>
+        /// Indicates which field in the oneof is set for specified message
+        /// </summary>
+        public FieldDescriptor GetCaseFieldDescriptor(IMessage message)
+        {
+            int fieldNumber = caseDelegate(message);
+            if (fieldNumber > 0)
+            {
+                return descriptor.ContainingType.FindFieldByNumber(fieldNumber);
+            }
+            return null;
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
new file mode 100644
index 0000000..22020ac
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
@@ -0,0 +1,122 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Google.Protobuf.Compatibility;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Describes a "oneof" field collection in a message type: a set of
+    /// fields of which at most one can be set in any particular message.
+    /// </summary>
+    public sealed class OneofDescriptor : DescriptorBase
+    {
+        private readonly OneofDescriptorProto proto;
+        private MessageDescriptor containingType;
+        private IList<FieldDescriptor> fields;
+        private readonly OneofAccessor accessor;
+
+        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string clrName)
+            : base(file, file.ComputeFullName(parent, proto.Name), index)
+        {
+            this.proto = proto;
+            containingType = parent;
+
+            file.DescriptorPool.AddSymbol(this);
+            accessor = CreateAccessor(clrName);
+        }
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name { get { return proto.Name; } }
+
+        /// <summary>
+        /// Gets the message type containing this oneof.
+        /// </summary>
+        /// <value>
+        /// The message type containing this oneof.
+        /// </value>
+        public MessageDescriptor ContainingType
+        {
+            get { return containingType; }
+        }
+
+        /// <summary>
+        /// Gets the fields within this oneof, in declaration order.
+        /// </summary>
+        /// <value>
+        /// The fields within this oneof, in declaration order.
+        /// </value>
+        public IList<FieldDescriptor> Fields { get { return fields; } }
+
+        /// <summary>
+        /// Gets an accessor for reflective access to the values associated with the oneof
+        /// in a particular message.
+        /// </summary>
+        /// <value>
+        /// The accessor used for reflective access.
+        /// </value>
+        public OneofAccessor Accessor { get { return accessor; } }
+
+        internal void CrossLink()
+        {
+            List<FieldDescriptor> fieldCollection = new List<FieldDescriptor>();
+            foreach (var field in ContainingType.Fields.InDeclarationOrder())
+            {
+                if (field.ContainingOneof == this)
+                {
+                    fieldCollection.Add(field);
+                }
+            }
+            fields = new ReadOnlyCollection<FieldDescriptor>(fieldCollection);
+        }
+
+        private OneofAccessor CreateAccessor(string clrName)
+        {
+            var caseProperty = containingType.ClrType.GetProperty(clrName + "Case");
+            if (caseProperty == null)
+            {
+                throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}");
+            }
+            var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName);
+            if (clearMethod == null)
+            {
+                throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}");
+            }
+
+            return new OneofAccessor(caseProperty, clearMethod, this);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs
new file mode 100644
index 0000000..27f9ab9
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs
@@ -0,0 +1,58 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Specifies the original name (in the .proto file) of a named element,
+    /// such as an enum value.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field)]
+    public class OriginalNameAttribute : Attribute
+    {
+        /// <summary>
+        /// The name of the element in the .proto file.
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// Constructs a new attribute instance for the given name.
+        /// </summary>
+        /// <param name="name">The name of the element in the .proto file.</param>
+        public OriginalNameAttribute(string name)
+        {
+            Name = ProtoPreconditions.CheckNotNull(name, nameof(name));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs
new file mode 100644
index 0000000..e547d83
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs
@@ -0,0 +1,68 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Represents a package in the symbol table.  We use PackageDescriptors
+    /// just as placeholders so that someone cannot define, say, a message type
+    /// that has the same name as an existing package.
+    /// </summary>
+    internal sealed class PackageDescriptor : IDescriptor
+    {
+        private readonly string name;
+        private readonly string fullName;
+        private readonly FileDescriptor file;
+
+        internal PackageDescriptor(string name, string fullName, FileDescriptor file)
+        {
+            this.file = file;
+            this.fullName = fullName;
+            this.name = name;
+        }
+
+        public string Name
+        {
+            get { return name; }
+        }
+
+        public string FullName
+        {
+            get { return fullName; }
+        }
+
+        public FileDescriptor File
+        {
+            get { return file; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
new file mode 100644
index 0000000..6c28541
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
@@ -0,0 +1,59 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+// This file just contains partial classes for any autogenerated classes that need additional support.
+namespace Google.Protobuf.Reflection
+{
+    internal partial class FieldDescriptorProto
+    {
+        // We can't tell the difference between "explicitly set to 0" and "not set"
+        // in proto3, but we need to tell the difference for OneofIndex. descriptor.proto
+        // is really a proto2 file, but the runtime doesn't know about proto2 semantics...
+        // We fake it by defaulting to -1.
+        partial void OnConstruction()
+        {
+            OneofIndex = -1;
+        }
+    }
+
+    internal partial class FieldOptions
+    {
+        // We can't tell the difference between "explicitly set to false" and "not set"
+        // in proto3, but we need to tell the difference for FieldDescriptor.IsPacked.
+        // This won't work if we ever need to support proto2, but at that point we'll be
+        // able to remove this hack and use field presence instead. 
+        partial void OnConstruction()
+        {
+            Packed = true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
new file mode 100644
index 0000000..df820ca
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
@@ -0,0 +1,107 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// The methods in this class are somewhat evil, and should not be tampered with lightly.
+    /// Basically they allow the creation of relatively weakly typed delegates from MethodInfos
+    /// which are more strongly typed. They do this by creating an appropriate strongly typed
+    /// delegate from the MethodInfo, and then calling that within an anonymous method.
+    /// Mind-bending stuff (at least to your humble narrator) but the resulting delegates are
+    /// very fast compared with calling Invoke later on.
+    /// </summary>
+    internal static class ReflectionUtil
+    {
+        /// <summary>
+        /// Empty Type[] used when calling GetProperty to force property instead of indexer fetching.
+        /// </summary>
+        internal static readonly Type[] EmptyTypes = new Type[0];
+
+        /// <summary>
+        /// Creates a delegate which will cast the argument to the appropriate method target type,
+        /// call the method on it, then convert the result to object.
+        /// </summary>
+        internal static Func<IMessage, object> CreateFuncIMessageObject(MethodInfo method)
+        {
+            ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p");
+            Expression downcast = Expression.Convert(parameter, method.DeclaringType);
+            Expression call = Expression.Call(downcast, method);
+            Expression upcast = Expression.Convert(call, typeof(object));
+            return Expression.Lambda<Func<IMessage, object>>(upcast, parameter).Compile();
+        }
+
+        /// <summary>
+        /// Creates a delegate which will cast the argument to the appropriate method target type,
+        /// call the method on it, then convert the result to the specified type.
+        /// </summary>
+        internal static Func<IMessage, T> CreateFuncIMessageT<T>(MethodInfo method)
+        {
+            ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p");
+            Expression downcast = Expression.Convert(parameter, method.DeclaringType);
+            Expression call = Expression.Call(downcast, method);
+            Expression upcast = Expression.Convert(call, typeof(T));
+            return Expression.Lambda<Func<IMessage, T>>(upcast, parameter).Compile();
+        }
+
+        /// <summary>
+        /// Creates a delegate which will execute the given method after casting the first argument to
+        /// the target type of the method, and the second argument to the first parameter type of the method.
+        /// </summary>
+        internal static Action<IMessage, object> CreateActionIMessageObject(MethodInfo method)
+        {
+            ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target");
+            ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg");
+            Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
+            Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType);
+            Expression call = Expression.Call(castTarget, method, castArgument);
+            return Expression.Lambda<Action<IMessage, object>>(call, targetParameter, argParameter).Compile();
+        }
+
+        /// <summary>
+        /// Creates a delegate which will execute the given method after casting the first argument to
+        /// the target type of the method.
+        /// </summary>
+        internal static Action<IMessage> CreateActionIMessage(MethodInfo method)
+        {
+            ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target");
+            Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
+            Expression call = Expression.Call(castTarget, method);
+            return Expression.Lambda<Action<IMessage>>(call, targetParameter).Compile();
+        }        
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
new file mode 100644
index 0000000..bd40847
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
@@ -0,0 +1,60 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Reflection;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Accessor for repeated fields.
+    /// </summary>
+    internal sealed class RepeatedFieldAccessor : FieldAccessorBase
+    {
+        internal RepeatedFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
+        {
+        }
+
+        public override void Clear(IMessage message)
+        {
+            IList list = (IList) GetValue(message);
+            list.Clear();
+        }
+
+        public override void SetValue(IMessage message, object value)
+        {
+            throw new InvalidOperationException("SetValue is not implemented for repeated fields");
+        }
+
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
new file mode 100644
index 0000000..cc0a501
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
@@ -0,0 +1,89 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Describes a service type.
+    /// </summary>
+    public sealed class ServiceDescriptor : DescriptorBase
+    {
+        private readonly ServiceDescriptorProto proto;
+        private readonly IList<MethodDescriptor> methods;
+
+        internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
+            : base(file, file.ComputeFullName(null, proto.Name), index)
+        {
+            this.proto = proto;
+            methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
+                                                            (method, i) => new MethodDescriptor(method, file, this, i));
+
+            file.DescriptorPool.AddSymbol(this);
+        }
+
+        /// <summary>
+        /// The brief name of the descriptor's target.
+        /// </summary>
+        public override string Name { get { return proto.Name; } }
+
+        internal ServiceDescriptorProto Proto { get { return proto; } }
+
+        /// <value>
+        /// An unmodifiable list of methods in this service.
+        /// </value>
+        public IList<MethodDescriptor> Methods
+        {
+            get { return methods; }
+        }
+
+        /// <summary>
+        /// Finds a method by name.
+        /// </summary>
+        /// <param name="name">The unqualified name of the method (e.g. "Foo").</param>
+        /// <returns>The method's decsriptor, or null if not found.</returns>
+        public MethodDescriptor FindMethodByName(String name)
+        {
+            return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
+        }
+
+        internal void CrossLink()
+        {
+            foreach (MethodDescriptor method in methods)
+            {
+                method.CrossLink();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
new file mode 100644
index 0000000..bbac217
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
@@ -0,0 +1,81 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Reflection;
+using Google.Protobuf.Compatibility;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Accessor for single fields.
+    /// </summary>
+    internal sealed class SingleFieldAccessor : FieldAccessorBase
+    {
+        // All the work here is actually done in the constructor - it creates the appropriate delegates.
+        // There are various cases to consider, based on the property type (message, string/bytes, or "genuine" primitive)
+        // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default
+        // values.
+
+        private readonly Action<IMessage, object> setValueDelegate;
+        private readonly Action<IMessage> clearDelegate;
+
+        internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
+        {
+            if (!property.CanWrite)
+            {
+                throw new ArgumentException("Not all required properties/methods available");
+            }
+            setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
+
+            var clrType = property.PropertyType;
+            
+            // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
+            object defaultValue =
+                descriptor.FieldType == FieldType.Message ? null
+                : clrType == typeof(string) ? ""
+                : clrType == typeof(ByteString) ? ByteString.Empty
+                : Activator.CreateInstance(clrType);
+            clearDelegate = message => SetValue(message, defaultValue);
+        }
+
+        public override void Clear(IMessage message)
+        {
+            clearDelegate(message);
+        }
+
+        public override void SetValue(IMessage message, object value)
+        {
+            setValueDelegate(message, value);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
new file mode 100644
index 0000000..e94e3e6
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
@@ -0,0 +1,183 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// An immutable registry of types which can be looked up by their full name.
+    /// </summary>
+    public sealed class TypeRegistry
+    {
+        /// <summary>
+        /// An empty type registry, containing no types.
+        /// </summary>
+        public static TypeRegistry Empty { get; } = new TypeRegistry(new Dictionary<string, MessageDescriptor>());
+
+        private readonly Dictionary<string, MessageDescriptor> fullNameToMessageMap;
+
+        private TypeRegistry(Dictionary<string, MessageDescriptor> fullNameToMessageMap)
+        {
+            this.fullNameToMessageMap = fullNameToMessageMap;
+        }
+
+        /// <summary>
+        /// Attempts to find a message descriptor by its full name.
+        /// </summary>
+        /// <param name="fullName">The full name of the message, which is the dot-separated
+        /// combination of package, containing messages and message name</param>
+        /// <returns>The message descriptor corresponding to <paramref name="fullName"/> or null
+        /// if there is no such message descriptor.</returns>
+        public MessageDescriptor Find(string fullName)
+        {
+            MessageDescriptor ret;
+            // Ignore the return value as ret will end up with the right value either way.
+            fullNameToMessageMap.TryGetValue(fullName, out ret);
+            return ret;
+        }
+
+        /// <summary>
+        /// Creates a type registry from the specified set of file descriptors.
+        /// </summary>
+        /// <remarks>
+        /// This is a convenience overload for <see cref="FromFiles(IEnumerable{FileDescriptor})"/>
+        /// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>.
+        /// </remarks>
+        /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
+        /// <returns>A type registry for the given files.</returns>
+        public static TypeRegistry FromFiles(params FileDescriptor[] fileDescriptors)
+        {
+            return FromFiles((IEnumerable<FileDescriptor>) fileDescriptors);
+        }
+
+        /// <summary>
+        /// Creates a type registry from the specified set of file descriptors.
+        /// </summary>
+        /// <remarks>
+        /// All message types within all the specified files are added to the registry, and
+        /// the dependencies of the specified files are also added, recursively.
+        /// </remarks>
+        /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
+        /// <returns>A type registry for the given files.</returns>
+        public static TypeRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors)
+        {
+            ProtoPreconditions.CheckNotNull(fileDescriptors, nameof(fileDescriptors));
+            var builder = new Builder();
+            foreach (var file in fileDescriptors)
+            {
+                builder.AddFile(file);
+            }
+            return builder.Build();
+        }
+
+        /// <summary>
+        /// Creates a type registry from the file descriptor parents of the specified set of message descriptors.
+        /// </summary>
+        /// <remarks>
+        /// This is a convenience overload for <see cref="FromMessages(IEnumerable{MessageDescriptor})"/>
+        /// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>.
+        /// </remarks>
+        /// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry.
+        /// Must not contain null values.</param>
+        /// <returns>A type registry for the given files.</returns>
+        public static TypeRegistry FromMessages(params MessageDescriptor[] messageDescriptors)
+        {
+            return FromMessages((IEnumerable<MessageDescriptor>) messageDescriptors);
+        }
+
+        /// <summary>
+        /// Creates a type registry from the file descriptor parents of the specified set of message descriptors.
+        /// </summary>
+        /// <remarks>
+        /// The specified message descriptors are only used to identify their file descriptors; the returned registry
+        /// contains all the types within the file descriptors which contain the specified message descriptors (and
+        /// the dependencies of those files), not just the specified messages.
+        /// </remarks>
+        /// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry.
+        /// Must not contain null values.</param>
+        /// <returns>A type registry for the given files.</returns>
+        public static TypeRegistry FromMessages(IEnumerable<MessageDescriptor> messageDescriptors)
+        {
+            ProtoPreconditions.CheckNotNull(messageDescriptors, nameof(messageDescriptors));
+            return FromFiles(messageDescriptors.Select(md => md.File));
+        }
+
+        /// <summary>
+        /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls.
+        /// </summary>
+        private class Builder
+        {
+            private readonly Dictionary<string, MessageDescriptor> types;
+            private readonly HashSet<string> fileDescriptorNames;
+
+            internal Builder()
+            {
+                types = new Dictionary<string, MessageDescriptor>();
+                fileDescriptorNames = new HashSet<string>();
+            }
+
+            internal void AddFile(FileDescriptor fileDescriptor)
+            {
+                if (!fileDescriptorNames.Add(fileDescriptor.Name))
+                {
+                    return;
+                }
+                foreach (var dependency in fileDescriptor.Dependencies)
+                {
+                    AddFile(dependency);
+                }
+                foreach (var message in fileDescriptor.MessageTypes)
+                {
+                    AddMessage(message);
+                }
+            }
+
+            private void AddMessage(MessageDescriptor messageDescriptor)
+            {
+                foreach (var nestedType in messageDescriptor.NestedTypes)
+                {
+                    AddMessage(nestedType);
+                }
+                // This will overwrite any previous entry. Given that each file should
+                // only be added once, this could be a problem such as package A.B with type C,
+                // and package A with type B.C... it's unclear what we should do in that case.
+                types[messageDescriptor.FullName] = messageDescriptor;
+            }
+
+            internal TypeRegistry Build()
+            {
+                return new TypeRegistry(types);
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
new file mode 100644
index 0000000..871a383
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
@@ -0,0 +1,261 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/any.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/any.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class AnyReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/any.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static AnyReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi",
+            "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQnIKE2Nv",
+            "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaJWdpdGh1Yi5jb20vZ29s",
+            "YW5nL3Byb3RvYnVmL3B0eXBlcy9hbnmgAQGiAgNHUEKqAh5Hb29nbGUuUHJv",
+            "dG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), global::Google.Protobuf.WellKnownTypes.Any.Parser, new[]{ "TypeUrl", "Value" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  `Any` contains an arbitrary serialized protocol buffer message along with a
+  ///  URL that describes the type of the serialized message.
+  ///
+  ///  Protobuf library provides support to pack/unpack Any values in the form
+  ///  of utility functions or additional generated methods of the Any type.
+  ///
+  ///  Example 1: Pack and unpack a message in C++.
+  ///
+  ///      Foo foo = ...;
+  ///      Any any;
+  ///      any.PackFrom(foo);
+  ///      ...
+  ///      if (any.UnpackTo(&amp;foo)) {
+  ///        ...
+  ///      }
+  ///
+  ///  Example 2: Pack and unpack a message in Java.
+  ///
+  ///      Foo foo = ...;
+  ///      Any any = Any.pack(foo);
+  ///      ...
+  ///      if (any.is(Foo.class)) {
+  ///        foo = any.unpack(Foo.class);
+  ///      }
+  ///
+  ///  The pack methods provided by protobuf library will by default use
+  ///  'type.googleapis.com/full.type.name' as the type URL and the unpack
+  ///  methods only use the fully qualified type name after the last '/'
+  ///  in the type URL, for example "foo.bar.com/x/y.z" will yield type
+  ///  name "y.z".
+  ///
+  ///  JSON
+  ///  ====
+  ///  The JSON representation of an `Any` value uses the regular
+  ///  representation of the deserialized, embedded message, with an
+  ///  additional field `@type` which contains the type URL. Example:
+  ///
+  ///      package google.profile;
+  ///      message Person {
+  ///        string first_name = 1;
+  ///        string last_name = 2;
+  ///      }
+  ///
+  ///      {
+  ///        "@type": "type.googleapis.com/google.profile.Person",
+  ///        "firstName": &lt;string>,
+  ///        "lastName": &lt;string>
+  ///      }
+  ///
+  ///  If the embedded message type is well-known and has a custom JSON
+  ///  representation, that representation will be embedded adding a field
+  ///  `value` which holds the custom JSON in addition to the `@type`
+  ///  field. Example (for message [google.protobuf.Duration][]):
+  ///
+  ///      {
+  ///        "@type": "type.googleapis.com/google.protobuf.Duration",
+  ///        "value": "1.212s"
+  ///      }
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Any : pb::IMessage<Any> {
+    private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
+    public static pb::MessageParser<Any> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Any() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Any(Any other) : this() {
+      typeUrl_ = other.typeUrl_;
+      value_ = other.value_;
+    }
+
+    public Any Clone() {
+      return new Any(this);
+    }
+
+    /// <summary>Field number for the "type_url" field.</summary>
+    public const int TypeUrlFieldNumber = 1;
+    private string typeUrl_ = "";
+    /// <summary>
+    ///  A URL/resource name whose content describes the type of the
+    ///  serialized protocol buffer message.
+    ///
+    ///  For URLs which use the schema `http`, `https`, or no schema, the
+    ///  following restrictions and interpretations apply:
+    ///
+    ///  * If no schema is provided, `https` is assumed.
+    ///  * The last segment of the URL's path must represent the fully
+    ///    qualified name of the type (as in `path/google.protobuf.Duration`).
+    ///    The name should be in a canonical form (e.g., leading "." is
+    ///    not accepted).
+    ///  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+    ///    value in binary format, or produce an error.
+    ///  * Applications are allowed to cache lookup results based on the
+    ///    URL, or have them precompiled into a binary to avoid any
+    ///    lookup. Therefore, binary compatibility needs to be preserved
+    ///    on changes to types. (Use versioned type names to manage
+    ///    breaking changes.)
+    ///
+    ///  Schemas other than `http`, `https` (or the empty schema) might be
+    ///  used with implementation specific semantics.
+    /// </summary>
+    public string TypeUrl {
+      get { return typeUrl_; }
+      set {
+        typeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 2;
+    private pb::ByteString value_ = pb::ByteString.Empty;
+    /// <summary>
+    ///  Must be a valid serialized protocol buffer of the above specified type.
+    /// </summary>
+    public pb::ByteString Value {
+      get { return value_; }
+      set {
+        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Any);
+    }
+
+    public bool Equals(Any other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (TypeUrl != other.TypeUrl) return false;
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
+      if (Value.Length != 0) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (TypeUrl.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(TypeUrl);
+      }
+      if (Value.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteBytes(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (TypeUrl.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeUrl);
+      }
+      if (Value.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Any other) {
+      if (other == null) {
+        return;
+      }
+      if (other.TypeUrl.Length != 0) {
+        TypeUrl = other.TypeUrl;
+      }
+      if (other.Value.Length != 0) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            TypeUrl = input.ReadString();
+            break;
+          }
+          case 18: {
+            Value = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
new file mode 100644
index 0000000..f4fac73
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
@@ -0,0 +1,107 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public partial class Any
+    {
+        private const string DefaultPrefix = "type.googleapis.com";
+
+        // This could be moved to MessageDescriptor if we wanted to, but keeping it here means
+        // all the Any-specific code is in the same place.
+        private static string GetTypeUrl(MessageDescriptor descriptor, string prefix) =>
+            prefix.EndsWith("/") ? prefix + descriptor.FullName : prefix + "/" + descriptor.FullName;
+
+        /// <summary>
+        /// Retrieves the type name for a type URL. This is always just the last part of the URL,
+        /// after the trailing slash. No validation of anything before the trailing slash is performed.
+        /// If the type URL does not include a slash, an empty string is returned rather than an exception
+        /// being thrown; this won't match any types, and the calling code is probably in a better position
+        /// to give a meaningful error.
+        /// There is no handling of fragments or queries  at the moment.
+        /// </summary>
+        /// <param name="typeUrl">The URL to extract the type name from</param>
+        /// <returns>The type name</returns>
+        internal static string GetTypeName(string typeUrl)
+        {
+            int lastSlash = typeUrl.LastIndexOf('/');
+            return lastSlash == -1 ? "" : typeUrl.Substring(lastSlash + 1);
+        }
+
+        /// <summary>
+        /// Unpacks the content of this Any message into the target message type,
+        /// which must match the type URL within this Any message.
+        /// </summary>
+        /// <typeparam name="T">The type of message to unpack the content into.</typeparam>
+        /// <returns>The unpacked message.</returns>
+        /// <exception cref="InvalidProtocolBufferException">The target message type doesn't match the type URL in this message</exception>
+        public T Unpack<T>() where T : IMessage, new()
+        {
+            // Note: this doesn't perform as well is it might. We could take a MessageParser<T> in an alternative overload,
+            // which would be expected to perform slightly better... although the difference is likely to be negligible.
+            T target = new T();
+            if (GetTypeName(TypeUrl) != target.Descriptor.FullName)
+            {
+                throw new InvalidProtocolBufferException(
+                    $"Full type name for {target.Descriptor.Name} is {target.Descriptor.FullName}; Any message's type url is {TypeUrl}");
+            }
+            target.MergeFrom(Value);
+            return target;
+        }
+
+        /// <summary>
+        /// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
+        /// </summary>
+        /// <param name="message">The message to pack.</param>
+        /// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
+        public static Any Pack(IMessage message) => Pack(message, DefaultPrefix);
+
+        /// <summary>
+        /// Packs the specified message into an Any message using the specified type URL prefix.
+        /// </summary>
+        /// <param name="message">The message to pack.</param>
+        /// <param name="typeUrlPrefix">The prefix for the type URL.</param>
+        /// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
+        public static Any Pack(IMessage message, string typeUrlPrefix)
+        {
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(typeUrlPrefix, nameof(typeUrlPrefix));
+            return new Any
+            {
+                TypeUrl = GetTypeUrl(message.Descriptor, typeUrlPrefix),
+                Value = message.ToByteString()
+            };
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
new file mode 100644
index 0000000..e568a2c
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
@@ -0,0 +1,847 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/api.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/api.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class ApiReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/api.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static ApiReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Chlnb29nbGUvcHJvdG9idWYvYXBpLnByb3RvEg9nb29nbGUucHJvdG9idWYa",
+            "JGdvb2dsZS9wcm90b2J1Zi9zb3VyY2VfY29udGV4dC5wcm90bxoaZ29vZ2xl",
+            "L3Byb3RvYnVmL3R5cGUucHJvdG8igQIKA0FwaRIMCgRuYW1lGAEgASgJEigK",
+            "B21ldGhvZHMYAiADKAsyFy5nb29nbGUucHJvdG9idWYuTWV0aG9kEigKB29w",
+            "dGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9uEg8KB3ZlcnNp",
+            "b24YBCABKAkSNgoOc291cmNlX2NvbnRleHQYBSABKAsyHi5nb29nbGUucHJv",
+            "dG9idWYuU291cmNlQ29udGV4dBImCgZtaXhpbnMYBiADKAsyFi5nb29nbGUu",
+            "cHJvdG9idWYuTWl4aW4SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3Rv",
+            "YnVmLlN5bnRheCLVAQoGTWV0aG9kEgwKBG5hbWUYASABKAkSGAoQcmVxdWVz",
+            "dF90eXBlX3VybBgCIAEoCRIZChFyZXF1ZXN0X3N0cmVhbWluZxgDIAEoCBIZ",
+            "ChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25zZV9zdHJlYW1p",
+            "bmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5P",
+            "cHRpb24SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3RvYnVmLlN5bnRh",
+            "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCSwoTY29t",
+            "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAaABAaICA0dQQqoCHkdvb2ds",
+            "ZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), global::Google.Protobuf.WellKnownTypes.Api.Parser, new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), global::Google.Protobuf.WellKnownTypes.Method.Parser, new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), global::Google.Protobuf.WellKnownTypes.Mixin.Parser, new[]{ "Name", "Root" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  Api is a light-weight descriptor for a protocol buffer service.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Api : pb::IMessage<Api> {
+    private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
+    public static pb::MessageParser<Api> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Api() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Api(Api other) : this() {
+      name_ = other.name_;
+      methods_ = other.methods_.Clone();
+      options_ = other.options_.Clone();
+      version_ = other.version_;
+      SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+      mixins_ = other.mixins_.Clone();
+      syntax_ = other.syntax_;
+    }
+
+    public Api Clone() {
+      return new Api(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  The fully qualified name of this api, including package name
+    ///  followed by the api's simple name.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "methods" field.</summary>
+    public const int MethodsFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Method> _repeated_methods_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Method.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method> methods_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method>();
+    /// <summary>
+    ///  The methods of this api, in unspecified order.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method> Methods {
+      get { return methods_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  Any metadata attached to the API.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    /// <summary>Field number for the "version" field.</summary>
+    public const int VersionFieldNumber = 4;
+    private string version_ = "";
+    /// <summary>
+    ///  A version string for this api. If specified, must have the form
+    ///  `major-version.minor-version`, as in `1.10`. If the minor version
+    ///  is omitted, it defaults to zero. If the entire version field is
+    ///  empty, the major version is derived from the package name, as
+    ///  outlined below. If the field is not empty, the version in the
+    ///  package name will be verified to be consistent with what is
+    ///  provided here.
+    ///
+    ///  The versioning schema uses [semantic
+    ///  versioning](http://semver.org) where the major version number
+    ///  indicates a breaking change and the minor version an additive,
+    ///  non-breaking change. Both version numbers are signals to users
+    ///  what to expect from different versions, and should be carefully
+    ///  chosen based on the product plan.
+    ///
+    ///  The major version is also reflected in the package name of the
+    ///  API, which must end in `v&lt;major-version>`, as in
+    ///  `google.feature.v1`. For major versions 0 and 1, the suffix can
+    ///  be omitted. Zero major versions must only be used for
+    ///  experimental, none-GA apis.
+    /// </summary>
+    public string Version {
+      get { return version_; }
+      set {
+        version_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "source_context" field.</summary>
+    public const int SourceContextFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContext_;
+    /// <summary>
+    ///  Source context for the protocol buffer service represented by this
+    ///  message.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
+      get { return sourceContext_; }
+      set {
+        sourceContext_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "mixins" field.</summary>
+    public const int MixinsFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Mixin> _repeated_mixins_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.Mixin.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> mixins_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin>();
+    /// <summary>
+    ///  Included APIs. See [Mixin][].
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> Mixins {
+      get { return mixins_; }
+    }
+
+    /// <summary>Field number for the "syntax" field.</summary>
+    public const int SyntaxFieldNumber = 7;
+    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0;
+    /// <summary>
+    ///  The source syntax of the service.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+      get { return syntax_; }
+      set {
+        syntax_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Api);
+    }
+
+    public bool Equals(Api other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!methods_.Equals(other.methods_)) return false;
+      if(!options_.Equals(other.options_)) return false;
+      if (Version != other.Version) return false;
+      if (!object.Equals(SourceContext, other.SourceContext)) return false;
+      if(!mixins_.Equals(other.mixins_)) return false;
+      if (Syntax != other.Syntax) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= methods_.GetHashCode();
+      hash ^= options_.GetHashCode();
+      if (Version.Length != 0) hash ^= Version.GetHashCode();
+      if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
+      hash ^= mixins_.GetHashCode();
+      if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      methods_.WriteTo(output, _repeated_methods_codec);
+      options_.WriteTo(output, _repeated_options_codec);
+      if (Version.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(Version);
+      }
+      if (sourceContext_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(SourceContext);
+      }
+      mixins_.WriteTo(output, _repeated_mixins_codec);
+      if (Syntax != 0) {
+        output.WriteRawTag(56);
+        output.WriteEnum((int) Syntax);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += methods_.CalculateSize(_repeated_methods_codec);
+      size += options_.CalculateSize(_repeated_options_codec);
+      if (Version.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Version);
+      }
+      if (sourceContext_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
+      }
+      size += mixins_.CalculateSize(_repeated_mixins_codec);
+      if (Syntax != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Api other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      methods_.Add(other.methods_);
+      options_.Add(other.options_);
+      if (other.Version.Length != 0) {
+        Version = other.Version;
+      }
+      if (other.sourceContext_ != null) {
+        if (sourceContext_ == null) {
+          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+        }
+        SourceContext.MergeFrom(other.SourceContext);
+      }
+      mixins_.Add(other.mixins_);
+      if (other.Syntax != 0) {
+        Syntax = other.Syntax;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            methods_.AddEntriesFrom(input, _repeated_methods_codec);
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+          case 34: {
+            Version = input.ReadString();
+            break;
+          }
+          case 42: {
+            if (sourceContext_ == null) {
+              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(sourceContext_);
+            break;
+          }
+          case 50: {
+            mixins_.AddEntriesFrom(input, _repeated_mixins_codec);
+            break;
+          }
+          case 56: {
+            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Method represents a method of an api.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Method : pb::IMessage<Method> {
+    private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
+    public static pb::MessageParser<Method> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Method() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Method(Method other) : this() {
+      name_ = other.name_;
+      requestTypeUrl_ = other.requestTypeUrl_;
+      requestStreaming_ = other.requestStreaming_;
+      responseTypeUrl_ = other.responseTypeUrl_;
+      responseStreaming_ = other.responseStreaming_;
+      options_ = other.options_.Clone();
+      syntax_ = other.syntax_;
+    }
+
+    public Method Clone() {
+      return new Method(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  The simple name of this method.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "request_type_url" field.</summary>
+    public const int RequestTypeUrlFieldNumber = 2;
+    private string requestTypeUrl_ = "";
+    /// <summary>
+    ///  A URL of the input message type.
+    /// </summary>
+    public string RequestTypeUrl {
+      get { return requestTypeUrl_; }
+      set {
+        requestTypeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "request_streaming" field.</summary>
+    public const int RequestStreamingFieldNumber = 3;
+    private bool requestStreaming_;
+    /// <summary>
+    ///  If true, the request is streamed.
+    /// </summary>
+    public bool RequestStreaming {
+      get { return requestStreaming_; }
+      set {
+        requestStreaming_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "response_type_url" field.</summary>
+    public const int ResponseTypeUrlFieldNumber = 4;
+    private string responseTypeUrl_ = "";
+    /// <summary>
+    ///  The URL of the output message type.
+    /// </summary>
+    public string ResponseTypeUrl {
+      get { return responseTypeUrl_; }
+      set {
+        responseTypeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "response_streaming" field.</summary>
+    public const int ResponseStreamingFieldNumber = 5;
+    private bool responseStreaming_;
+    /// <summary>
+    ///  If true, the response is streamed.
+    /// </summary>
+    public bool ResponseStreaming {
+      get { return responseStreaming_; }
+      set {
+        responseStreaming_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  Any metadata attached to the method.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    /// <summary>Field number for the "syntax" field.</summary>
+    public const int SyntaxFieldNumber = 7;
+    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0;
+    /// <summary>
+    ///  The source syntax of this method.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+      get { return syntax_; }
+      set {
+        syntax_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Method);
+    }
+
+    public bool Equals(Method other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (RequestTypeUrl != other.RequestTypeUrl) return false;
+      if (RequestStreaming != other.RequestStreaming) return false;
+      if (ResponseTypeUrl != other.ResponseTypeUrl) return false;
+      if (ResponseStreaming != other.ResponseStreaming) return false;
+      if(!options_.Equals(other.options_)) return false;
+      if (Syntax != other.Syntax) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (RequestTypeUrl.Length != 0) hash ^= RequestTypeUrl.GetHashCode();
+      if (RequestStreaming != false) hash ^= RequestStreaming.GetHashCode();
+      if (ResponseTypeUrl.Length != 0) hash ^= ResponseTypeUrl.GetHashCode();
+      if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode();
+      hash ^= options_.GetHashCode();
+      if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (RequestTypeUrl.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(RequestTypeUrl);
+      }
+      if (RequestStreaming != false) {
+        output.WriteRawTag(24);
+        output.WriteBool(RequestStreaming);
+      }
+      if (ResponseTypeUrl.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(ResponseTypeUrl);
+      }
+      if (ResponseStreaming != false) {
+        output.WriteRawTag(40);
+        output.WriteBool(ResponseStreaming);
+      }
+      options_.WriteTo(output, _repeated_options_codec);
+      if (Syntax != 0) {
+        output.WriteRawTag(56);
+        output.WriteEnum((int) Syntax);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (RequestTypeUrl.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(RequestTypeUrl);
+      }
+      if (RequestStreaming != false) {
+        size += 1 + 1;
+      }
+      if (ResponseTypeUrl.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(ResponseTypeUrl);
+      }
+      if (ResponseStreaming != false) {
+        size += 1 + 1;
+      }
+      size += options_.CalculateSize(_repeated_options_codec);
+      if (Syntax != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Method other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.RequestTypeUrl.Length != 0) {
+        RequestTypeUrl = other.RequestTypeUrl;
+      }
+      if (other.RequestStreaming != false) {
+        RequestStreaming = other.RequestStreaming;
+      }
+      if (other.ResponseTypeUrl.Length != 0) {
+        ResponseTypeUrl = other.ResponseTypeUrl;
+      }
+      if (other.ResponseStreaming != false) {
+        ResponseStreaming = other.ResponseStreaming;
+      }
+      options_.Add(other.options_);
+      if (other.Syntax != 0) {
+        Syntax = other.Syntax;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            RequestTypeUrl = input.ReadString();
+            break;
+          }
+          case 24: {
+            RequestStreaming = input.ReadBool();
+            break;
+          }
+          case 34: {
+            ResponseTypeUrl = input.ReadString();
+            break;
+          }
+          case 40: {
+            ResponseStreaming = input.ReadBool();
+            break;
+          }
+          case 50: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+          case 56: {
+            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Declares an API to be included in this API. The including API must
+  ///  redeclare all the methods from the included API, but documentation
+  ///  and options are inherited as follows:
+  ///
+  ///  - If after comment and whitespace stripping, the documentation
+  ///    string of the redeclared method is empty, it will be inherited
+  ///    from the original method.
+  ///
+  ///  - Each annotation belonging to the service config (http,
+  ///    visibility) which is not set in the redeclared method will be
+  ///    inherited.
+  ///
+  ///  - If an http annotation is inherited, the path pattern will be
+  ///    modified as follows. Any version prefix will be replaced by the
+  ///    version of the including API plus the [root][] path if specified.
+  ///
+  ///  Example of a simple mixin:
+  ///
+  ///      package google.acl.v1;
+  ///      service AccessControl {
+  ///        // Get the underlying ACL object.
+  ///        rpc GetAcl(GetAclRequest) returns (Acl) {
+  ///          option (google.api.http).get = "/v1/{resource=**}:getAcl";
+  ///        }
+  ///      }
+  ///
+  ///      package google.storage.v2;
+  ///      service Storage {
+  ///        rpc GetAcl(GetAclRequest) returns (Acl);
+  ///
+  ///        // Get a data record.
+  ///        rpc GetData(GetDataRequest) returns (Data) {
+  ///          option (google.api.http).get = "/v2/{resource=**}";
+  ///        }
+  ///      }
+  ///
+  ///  Example of a mixin configuration:
+  ///
+  ///      apis:
+  ///      - name: google.storage.v2.Storage
+  ///        mixins:
+  ///        - name: google.acl.v1.AccessControl
+  ///
+  ///  The mixin construct implies that all methods in `AccessControl` are
+  ///  also declared with same name and request/response types in
+  ///  `Storage`. A documentation generator or annotation processor will
+  ///  see the effective `Storage.GetAcl` method after inherting
+  ///  documentation and annotations as follows:
+  ///
+  ///      service Storage {
+  ///        // Get the underlying ACL object.
+  ///        rpc GetAcl(GetAclRequest) returns (Acl) {
+  ///          option (google.api.http).get = "/v2/{resource=**}:getAcl";
+  ///        }
+  ///        ...
+  ///      }
+  ///
+  ///  Note how the version in the path pattern changed from `v1` to `v2`.
+  ///
+  ///  If the `root` field in the mixin is specified, it should be a
+  ///  relative path under which inherited HTTP paths are placed. Example:
+  ///
+  ///      apis:
+  ///      - name: google.storage.v2.Storage
+  ///        mixins:
+  ///        - name: google.acl.v1.AccessControl
+  ///          root: acls
+  ///
+  ///  This implies the following inherited HTTP annotation:
+  ///
+  ///      service Storage {
+  ///        // Get the underlying ACL object.
+  ///        rpc GetAcl(GetAclRequest) returns (Acl) {
+  ///          option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+  ///        }
+  ///        ...
+  ///      }
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Mixin : pb::IMessage<Mixin> {
+    private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
+    public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Mixin() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Mixin(Mixin other) : this() {
+      name_ = other.name_;
+      root_ = other.root_;
+    }
+
+    public Mixin Clone() {
+      return new Mixin(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  The fully qualified name of the API which is included.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "root" field.</summary>
+    public const int RootFieldNumber = 2;
+    private string root_ = "";
+    /// <summary>
+    ///  If non-empty specifies a path under which inherited HTTP paths
+    ///  are rooted.
+    /// </summary>
+    public string Root {
+      get { return root_; }
+      set {
+        root_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Mixin);
+    }
+
+    public bool Equals(Mixin other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Root != other.Root) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Root.Length != 0) hash ^= Root.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Root.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Root);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Root.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Root);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Mixin other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Root.Length != 0) {
+        Root = other.Root;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Root = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
new file mode 100644
index 0000000..f17358f
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
@@ -0,0 +1,230 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/duration.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/duration.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class DurationReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/duration.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static DurationReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90",
+            "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg",
+            "ASgFQnwKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAVoq",
+            "Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL2R1cmF0aW9uoAEB",
+            "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90",
+            "bzM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), global::Google.Protobuf.WellKnownTypes.Duration.Parser, new[]{ "Seconds", "Nanos" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  A Duration represents a signed, fixed-length span of time represented
+  ///  as a count of seconds and fractions of seconds at nanosecond
+  ///  resolution. It is independent of any calendar and concepts like "day"
+  ///  or "month". It is related to Timestamp in that the difference between
+  ///  two Timestamp values is a Duration and it can be added or subtracted
+  ///  from a Timestamp. Range is approximately +-10,000 years.
+  ///
+  ///  Example 1: Compute Duration from two Timestamps in pseudo code.
+  ///
+  ///      Timestamp start = ...;
+  ///      Timestamp end = ...;
+  ///      Duration duration = ...;
+  ///
+  ///      duration.seconds = end.seconds - start.seconds;
+  ///      duration.nanos = end.nanos - start.nanos;
+  ///
+  ///      if (duration.seconds &lt; 0 &amp;&amp; duration.nanos > 0) {
+  ///        duration.seconds += 1;
+  ///        duration.nanos -= 1000000000;
+  ///      } else if (durations.seconds > 0 &amp;&amp; duration.nanos &lt; 0) {
+  ///        duration.seconds -= 1;
+  ///        duration.nanos += 1000000000;
+  ///      }
+  ///
+  ///  Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+  ///
+  ///      Timestamp start = ...;
+  ///      Duration duration = ...;
+  ///      Timestamp end = ...;
+  ///
+  ///      end.seconds = start.seconds + duration.seconds;
+  ///      end.nanos = start.nanos + duration.nanos;
+  ///
+  ///      if (end.nanos &lt; 0) {
+  ///        end.seconds -= 1;
+  ///        end.nanos += 1000000000;
+  ///      } else if (end.nanos >= 1000000000) {
+  ///        end.seconds += 1;
+  ///        end.nanos -= 1000000000;
+  ///      }
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Duration : pb::IMessage<Duration> {
+    private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
+    public static pb::MessageParser<Duration> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Duration() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Duration(Duration other) : this() {
+      seconds_ = other.seconds_;
+      nanos_ = other.nanos_;
+    }
+
+    public Duration Clone() {
+      return new Duration(this);
+    }
+
+    /// <summary>Field number for the "seconds" field.</summary>
+    public const int SecondsFieldNumber = 1;
+    private long seconds_;
+    /// <summary>
+    ///  Signed seconds of the span of time. Must be from -315,576,000,000
+    ///  to +315,576,000,000 inclusive.
+    /// </summary>
+    public long Seconds {
+      get { return seconds_; }
+      set {
+        seconds_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "nanos" field.</summary>
+    public const int NanosFieldNumber = 2;
+    private int nanos_;
+    /// <summary>
+    ///  Signed fractions of a second at nanosecond resolution of the span
+    ///  of time. Durations less than one second are represented with a 0
+    ///  `seconds` field and a positive or negative `nanos` field. For durations
+    ///  of one second or more, a non-zero value for the `nanos` field must be
+    ///  of the same sign as the `seconds` field. Must be from -999,999,999
+    ///  to +999,999,999 inclusive.
+    /// </summary>
+    public int Nanos {
+      get { return nanos_; }
+      set {
+        nanos_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Duration);
+    }
+
+    public bool Equals(Duration other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Seconds != other.Seconds) return false;
+      if (Nanos != other.Nanos) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Seconds != 0L) hash ^= Seconds.GetHashCode();
+      if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Seconds != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Seconds);
+      }
+      if (Nanos != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Nanos);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Seconds != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Seconds);
+      }
+      if (Nanos != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Duration other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Seconds != 0L) {
+        Seconds = other.Seconds;
+      }
+      if (other.Nanos != 0) {
+        Nanos = other.Nanos;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Seconds = input.ReadInt64();
+            break;
+          }
+          case 16: {
+            Nanos = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
new file mode 100644
index 0000000..f164bfd
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
@@ -0,0 +1,270 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Text;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    // Manually-written partial class for the Duration well-known type,
+    // providing a conversion to TimeSpan and convenience operators.
+    public partial class Duration : ICustomDiagnosticMessage
+    {
+        /// <summary>
+        /// The number of nanoseconds in a second.
+        /// </summary>
+        public const int NanosecondsPerSecond = 1000000000;
+        /// <summary>
+        /// The number of nanoseconds in a BCL tick (as used by <see cref="TimeSpan"/> and <see cref="DateTime"/>).
+        /// </summary>
+        public const int NanosecondsPerTick = 100;
+
+        /// <summary>
+        /// The maximum permitted number of seconds.
+        /// </summary>
+        public const long MaxSeconds = 315576000000L;
+
+        /// <summary>
+        /// The minimum permitted number of seconds.
+        /// </summary>
+        public const long MinSeconds = -315576000000L;
+
+        internal const int MaxNanoseconds = NanosecondsPerSecond - 1;
+        internal const int MinNanoseconds = -NanosecondsPerSecond + 1;
+
+        internal static bool IsNormalized(long seconds, int nanoseconds)
+        {
+            // Simple boundaries
+            if (seconds < MinSeconds || seconds > MaxSeconds ||
+                nanoseconds < MinNanoseconds || nanoseconds > MaxNanoseconds)
+            {
+                return false;
+            }
+            // We only have a problem is one is strictly negative and the other is
+            // strictly positive.
+            return Math.Sign(seconds) * Math.Sign(nanoseconds) != -1;
+        }
+
+        /// <summary>
+        /// Converts this <see cref="Duration"/> to a <see cref="TimeSpan"/>.
+        /// </summary>
+        /// <remarks>If the duration is not a precise number of ticks, it is truncated towards 0.</remarks>
+        /// <returns>The value of this duration, as a <c>TimeSpan</c>.</returns>
+        /// <exception cref="InvalidOperationException">This value isn't a valid normalized duration, as
+        /// described in the documentation.</exception>
+        public TimeSpan ToTimeSpan()
+        {
+            checked
+            {
+                if (!IsNormalized(Seconds, Nanos))
+                {
+                    throw new InvalidOperationException("Duration was not a valid normalized duration");
+                }
+                long ticks = Seconds * TimeSpan.TicksPerSecond + Nanos / NanosecondsPerTick;
+                return TimeSpan.FromTicks(ticks);
+            }
+        }
+
+        /// <summary>
+        /// Converts the given <see cref="TimeSpan"/> to a <see cref="Duration"/>.
+        /// </summary>
+        /// <param name="timeSpan">The <c>TimeSpan</c> to convert.</param>
+        /// <returns>The value of the given <c>TimeSpan</c>, as a <c>Duration</c>.</returns>
+        public static Duration FromTimeSpan(TimeSpan timeSpan)
+        {
+            checked
+            {
+                long ticks = timeSpan.Ticks;
+                long seconds = ticks / TimeSpan.TicksPerSecond;
+                int nanos = (int) (ticks % TimeSpan.TicksPerSecond) * NanosecondsPerTick;
+                return new Duration { Seconds = seconds, Nanos = nanos };
+            }
+        }
+
+        /// <summary>
+        /// Returns the result of negating the duration. For example, the negation of 5 minutes is -5 minutes.
+        /// </summary>
+        /// <param name="value">The duration to negate. Must not be null.</param>
+        /// <returns>The negated value of this duration.</returns>
+        public static Duration operator -(Duration value)
+        {
+            ProtoPreconditions.CheckNotNull(value, "value");
+            checked
+            {
+                return Normalize(-value.Seconds, -value.Nanos);
+            }
+        }
+
+        /// <summary>
+        /// Adds the two specified <see cref="Duration"/> values together.
+        /// </summary>
+        /// <param name="lhs">The first value to add. Must not be null.</param>
+        /// <param name="rhs">The second value to add. Must not be null.</param>
+        /// <returns></returns>
+        public static Duration operator +(Duration lhs, Duration rhs)
+        {
+            ProtoPreconditions.CheckNotNull(lhs, "lhs");
+            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            checked
+            {
+                return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos);
+            }
+        }
+
+        /// <summary>
+        /// Subtracts one <see cref="Duration"/> from another.
+        /// </summary>
+        /// <param name="lhs">The duration to subtract from. Must not be null.</param>
+        /// <param name="rhs">The duration to subtract. Must not be null.</param>
+        /// <returns>The difference between the two specified durations.</returns>
+        public static Duration operator -(Duration lhs, Duration rhs)
+        {
+            ProtoPreconditions.CheckNotNull(lhs, "lhs");
+            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            checked
+            {
+                return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
+            }
+        }
+        
+        /// <summary>
+        /// Creates a duration with the normalized values from the given number of seconds and
+        /// nanoseconds, conforming with the description in the proto file.
+        /// </summary>
+        internal static Duration Normalize(long seconds, int nanoseconds)
+        {
+            // Ensure that nanoseconds is in the range (-1,000,000,000, +1,000,000,000)
+            int extraSeconds = nanoseconds / NanosecondsPerSecond;
+            seconds += extraSeconds;
+            nanoseconds -= extraSeconds * NanosecondsPerSecond;
+
+            // Now make sure that Sign(seconds) == Sign(nanoseconds) if Sign(seconds) != 0.
+            if (seconds < 0 && nanoseconds > 0)
+            {
+                seconds += 1;
+                nanoseconds -= NanosecondsPerSecond;
+            }
+            else if (seconds > 0 && nanoseconds < 0)
+            {
+                seconds -= 1;
+                nanoseconds += NanosecondsPerSecond;
+            }
+            return new Duration { Seconds = seconds, Nanos = nanoseconds };
+        }
+
+        /// <summary>
+        /// Converts a duration specified in seconds/nanoseconds to a string.
+        /// </summary>
+        /// <remarks>
+        /// If the value is a normalized duration in the range described in <c>duration.proto</c>,
+        /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+        /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+        /// </remarks>
+        /// <param name="seconds">Seconds portion of the duration.</param>
+        /// <param name="nanoseconds">Nanoseconds portion of the duration.</param>
+        /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+        /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+        internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly)
+        {
+            if (IsNormalized(seconds, nanoseconds))
+            {
+                var builder = new StringBuilder();
+                builder.Append('"');
+                // The seconds part will normally provide the minus sign if we need it, but not if it's 0...
+                if (seconds == 0 && nanoseconds < 0)
+                {
+                    builder.Append('-');
+                }
+
+                builder.Append(seconds.ToString("d", CultureInfo.InvariantCulture));
+                AppendNanoseconds(builder, Math.Abs(nanoseconds));
+                builder.Append("s\"");
+                return builder.ToString();
+            }
+            if (diagnosticOnly)
+            {
+                // Note: the double braces here are escaping for braces in format strings.
+                return string.Format(CultureInfo.InvariantCulture,
+                    "{{ \"@warning\": \"Invalid Duration\", \"seconds\": \"{0}\", \"nanos\": {1} }}",
+                    seconds,
+                    nanoseconds);
+            }
+            else
+            {
+                throw new InvalidOperationException("Non-normalized duration value");
+            }
+        }
+
+        /// <summary>
+        /// Returns a string representation of this <see cref="Duration"/> for diagnostic purposes.
+        /// </summary>
+        /// <remarks>
+        /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+        /// when the value is non-normalized or out of range, a JSON object representation will be returned
+        /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+        /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+        /// values.
+        /// </remarks>
+        /// <returns>A string representation of this value.</returns>
+        public string ToDiagnosticString()
+        {
+            return ToJson(Seconds, Nanos, true);
+        }
+
+        /// <summary>
+        /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which
+        /// case no "." is appended), or 3 6 or 9 digits. This is internal for use in Timestamp as well
+        /// as Duration.
+        /// </summary>
+        internal static void AppendNanoseconds(StringBuilder builder, int nanos)
+        {
+            if (nanos != 0)
+            {
+                builder.Append('.');
+                // Output to 3, 6 or 9 digits.
+                if (nanos % 1000000 == 0)
+                {
+                    builder.Append((nanos / 1000000).ToString("d3", CultureInfo.InvariantCulture));
+                }
+                else if (nanos % 1000 == 0)
+                {
+                    builder.Append((nanos / 1000).ToString("d6", CultureInfo.InvariantCulture));
+                }
+                else
+                {
+                    builder.Append(nanos.ToString("d9", CultureInfo.InvariantCulture));
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
new file mode 100644
index 0000000..e08ea24
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
@@ -0,0 +1,132 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/empty.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/empty.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class EmptyReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/empty.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static EmptyReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1",
+            "ZiIHCgVFbXB0eUJ5ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv",
+            "UAFaJ2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy9lbXB0eaAB",
+            "AfgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
+            "cHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), global::Google.Protobuf.WellKnownTypes.Empty.Parser, null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  A generic empty message that you can re-use to avoid defining duplicated
+  ///  empty messages in your APIs. A typical example is to use it as the request
+  ///  or the response type of an API method. For instance:
+  ///
+  ///      service Foo {
+  ///        rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+  ///      }
+  ///
+  ///  The JSON representation for `Empty` is empty JSON object `{}`.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Empty : pb::IMessage<Empty> {
+    private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+    public static pb::MessageParser<Empty> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Empty() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Empty(Empty other) : this() {
+    }
+
+    public Empty Clone() {
+      return new Empty(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Empty);
+    }
+
+    public bool Equals(Empty other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(Empty other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
new file mode 100644
index 0000000..6f0a64d
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
@@ -0,0 +1,292 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/field_mask.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class FieldMaskReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/field_mask.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static FieldMaskReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy",
+            "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUJRChNjb20uZ29v",
+            "Z2xlLnByb3RvYnVmQg5GaWVsZE1hc2tQcm90b1ABoAEBogIDR1BCqgIeR29v",
+            "Z2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), global::Google.Protobuf.WellKnownTypes.FieldMask.Parser, new[]{ "Paths" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  `FieldMask` represents a set of symbolic field paths, for example:
+  ///
+  ///      paths: "f.a"
+  ///      paths: "f.b.d"
+  ///
+  ///  Here `f` represents a field in some root message, `a` and `b`
+  ///  fields in the message found in `f`, and `d` a field found in the
+  ///  message in `f.b`.
+  ///
+  ///  Field masks are used to specify a subset of fields that should be
+  ///  returned by a get operation or modified by an update operation.
+  ///  Field masks also have a custom JSON encoding (see below).
+  ///
+  ///  # Field Masks in Projections
+  ///
+  ///  When used in the context of a projection, a response message or
+  ///  sub-message is filtered by the API to only contain those fields as
+  ///  specified in the mask. For example, if the mask in the previous
+  ///  example is applied to a response message as follows:
+  ///
+  ///      f {
+  ///        a : 22
+  ///        b {
+  ///          d : 1
+  ///          x : 2
+  ///        }
+  ///        y : 13
+  ///      }
+  ///      z: 8
+  ///
+  ///  The result will not contain specific values for fields x,y and z
+  ///  (their value will be set to the default, and omitted in proto text
+  ///  output):
+  ///
+  ///      f {
+  ///        a : 22
+  ///        b {
+  ///          d : 1
+  ///        }
+  ///      }
+  ///
+  ///  A repeated field is not allowed except at the last position of a
+  ///  field mask.
+  ///
+  ///  If a FieldMask object is not present in a get operation, the
+  ///  operation applies to all fields (as if a FieldMask of all fields
+  ///  had been specified).
+  ///
+  ///  Note that a field mask does not necessarily apply to the
+  ///  top-level response message. In case of a REST get operation, the
+  ///  field mask applies directly to the response, but in case of a REST
+  ///  list operation, the mask instead applies to each individual message
+  ///  in the returned resource list. In case of a REST custom method,
+  ///  other definitions may be used. Where the mask applies will be
+  ///  clearly documented together with its declaration in the API.  In
+  ///  any case, the effect on the returned resource/resources is required
+  ///  behavior for APIs.
+  ///
+  ///  # Field Masks in Update Operations
+  ///
+  ///  A field mask in update operations specifies which fields of the
+  ///  targeted resource are going to be updated. The API is required
+  ///  to only change the values of the fields as specified in the mask
+  ///  and leave the others untouched. If a resource is passed in to
+  ///  describe the updated values, the API ignores the values of all
+  ///  fields not covered by the mask.
+  ///
+  ///  In order to reset a field's value to the default, the field must
+  ///  be in the mask and set to the default value in the provided resource.
+  ///  Hence, in order to reset all fields of a resource, provide a default
+  ///  instance of the resource and set all fields in the mask, or do
+  ///  not provide a mask as described below.
+  ///
+  ///  If a field mask is not present on update, the operation applies to
+  ///  all fields (as if a field mask of all fields has been specified).
+  ///  Note that in the presence of schema evolution, this may mean that
+  ///  fields the client does not know and has therefore not filled into
+  ///  the request will be reset to their default. If this is unwanted
+  ///  behavior, a specific service may require a client to always specify
+  ///  a field mask, producing an error if not.
+  ///
+  ///  As with get operations, the location of the resource which
+  ///  describes the updated values in the request message depends on the
+  ///  operation kind. In any case, the effect of the field mask is
+  ///  required to be honored by the API.
+  ///
+  ///  ## Considerations for HTTP REST
+  ///
+  ///  The HTTP kind of an update operation which uses a field mask must
+  ///  be set to PATCH instead of PUT in order to satisfy HTTP semantics
+  ///  (PUT must only be used for full updates).
+  ///
+  ///  # JSON Encoding of Field Masks
+  ///
+  ///  In JSON, a field mask is encoded as a single string where paths are
+  ///  separated by a comma. Fields name in each path are converted
+  ///  to/from lower-camel naming conventions.
+  ///
+  ///  As an example, consider the following message declarations:
+  ///
+  ///      message Profile {
+  ///        User user = 1;
+  ///        Photo photo = 2;
+  ///      }
+  ///      message User {
+  ///        string display_name = 1;
+  ///        string address = 2;
+  ///      }
+  ///
+  ///  In proto a field mask for `Profile` may look as such:
+  ///
+  ///      mask {
+  ///        paths: "user.display_name"
+  ///        paths: "photo"
+  ///      }
+  ///
+  ///  In JSON, the same mask is represented as below:
+  ///
+  ///      {
+  ///        mask: "user.displayName,photo"
+  ///      }
+  ///
+  ///  # Field Masks and Oneof Fields
+  ///
+  ///  Field masks treat fields in oneofs just as regular fields. Consider the
+  ///  following message:
+  ///
+  ///      message SampleMessage {
+  ///        oneof test_oneof {
+  ///          string name = 4;
+  ///          SubMessage sub_message = 9;
+  ///        }
+  ///      }
+  ///
+  ///  The field mask can be:
+  ///
+  ///      mask {
+  ///        paths: "name"
+  ///      }
+  ///
+  ///  Or:
+  ///
+  ///      mask {
+  ///        paths: "sub_message"
+  ///      }
+  ///
+  ///  Note that oneof type names ("test_oneof" in this case) cannot be used in
+  ///  paths.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FieldMask : pb::IMessage<FieldMask> {
+    private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
+    public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FieldMask() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FieldMask(FieldMask other) : this() {
+      paths_ = other.paths_.Clone();
+    }
+
+    public FieldMask Clone() {
+      return new FieldMask(this);
+    }
+
+    /// <summary>Field number for the "paths" field.</summary>
+    public const int PathsFieldNumber = 1;
+    private static readonly pb::FieldCodec<string> _repeated_paths_codec
+        = pb::FieldCodec.ForString(10);
+    private readonly pbc::RepeatedField<string> paths_ = new pbc::RepeatedField<string>();
+    /// <summary>
+    ///  The set of field mask paths.
+    /// </summary>
+    public pbc::RepeatedField<string> Paths {
+      get { return paths_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FieldMask);
+    }
+
+    public bool Equals(FieldMask other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!paths_.Equals(other.paths_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= paths_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      paths_.WriteTo(output, _repeated_paths_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += paths_.CalculateSize(_repeated_paths_codec);
+      return size;
+    }
+
+    public void MergeFrom(FieldMask other) {
+      if (other == null) {
+        return;
+      }
+      paths_.Add(other.paths_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            paths_.AddEntriesFrom(input, _repeated_paths_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
new file mode 100644
index 0000000..4bd62cf
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
@@ -0,0 +1,123 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    // Manually-written partial class for the FieldMask well-known type.
+    public partial class FieldMask : ICustomDiagnosticMessage
+    {
+        /// <summary>
+        /// Converts a timestamp  specified in seconds/nanoseconds to a string.
+        /// </summary>
+        /// <remarks>
+        /// If the value is a normalized duration in the range described in <c>field_mask.proto</c>,
+        /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+        /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+        /// </remarks>
+        /// <param name="paths">Paths in the field mask</param>
+        /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+        /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+        internal static string ToJson(IList<string> paths, bool diagnosticOnly)
+        {
+            var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p));
+            if (firstInvalid == null)
+            {
+                var writer = new StringWriter();
+                JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToCamelCase)));
+                return writer.ToString();
+            }
+            else
+            {
+                if (diagnosticOnly)
+                {
+                    var writer = new StringWriter();
+                    writer.Write("{ \"@warning\": \"Invalid FieldMask\", \"paths\": ");
+                    JsonFormatter.Default.WriteList(writer, (IList)paths);
+                    writer.Write(" }");
+                    return writer.ToString();
+                }
+                else
+                {
+                    throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {firstInvalid}");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Camel-case converter with added strictness for field mask formatting.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
+        private static bool ValidatePath(string input)
+        {
+            for (int i = 0; i < input.Length; i++)
+            {
+                char c = input[i];
+                if (c >= 'A' && c <= 'Z')
+                {
+                    return false;
+                }
+                if (c == '_' && i < input.Length - 1)
+                {
+                    char next = input[i + 1];
+                    if (next < 'a' || next > 'z')
+                    {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Returns a string representation of this <see cref="FieldMask"/> for diagnostic purposes.
+        /// </summary>
+        /// <remarks>
+        /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+        /// when the value is non-normalized or out of range, a JSON object representation will be returned
+        /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+        /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+        /// values.
+        /// </remarks>
+        /// <returns>A string representation of this value.</returns>
+        public string ToDiagnosticString()
+        {
+            return ToJson(Paths, true);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
new file mode 100644
index 0000000..a235ece
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
@@ -0,0 +1,156 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/source_context.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class SourceContextReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/source_context.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static SourceContextReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds",
+            "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo",
+            "CUJVChNjb20uZ29vZ2xlLnByb3RvYnVmQhJTb3VyY2VDb250ZXh0UHJvdG9Q",
+            "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
+            "cHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), global::Google.Protobuf.WellKnownTypes.SourceContext.Parser, new[]{ "FileName" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  `SourceContext` represents information about the source of a
+  ///  protobuf element, like the file in which it is defined.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class SourceContext : pb::IMessage<SourceContext> {
+    private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
+    public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SourceContext() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SourceContext(SourceContext other) : this() {
+      fileName_ = other.fileName_;
+    }
+
+    public SourceContext Clone() {
+      return new SourceContext(this);
+    }
+
+    /// <summary>Field number for the "file_name" field.</summary>
+    public const int FileNameFieldNumber = 1;
+    private string fileName_ = "";
+    /// <summary>
+    ///  The path-qualified name of the .proto file that contained the associated
+    ///  protobuf element.  For example: `"google/protobuf/source.proto"`.
+    /// </summary>
+    public string FileName {
+      get { return fileName_; }
+      set {
+        fileName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SourceContext);
+    }
+
+    public bool Equals(SourceContext other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (FileName != other.FileName) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (FileName.Length != 0) hash ^= FileName.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (FileName.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(FileName);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (FileName.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(FileName);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SourceContext other) {
+      if (other == null) {
+        return;
+      }
+      if (other.FileName.Length != 0) {
+        FileName = other.FileName;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            FileName = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
new file mode 100644
index 0000000..edc8940
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
@@ -0,0 +1,600 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/struct.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/struct.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class StructReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/struct.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static StructReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Chxnb29nbGUvcHJvdG9idWYvc3RydWN0LnByb3RvEg9nb29nbGUucHJvdG9i",
+            "dWYihAEKBlN0cnVjdBIzCgZmaWVsZHMYASADKAsyIy5nb29nbGUucHJvdG9i",
+            "dWYuU3RydWN0LkZpZWxkc0VudHJ5GkUKC0ZpZWxkc0VudHJ5EgsKA2tleRgB",
+            "IAEoCRIlCgV2YWx1ZRgCIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZToC",
+            "OAEi6gEKBVZhbHVlEjAKCm51bGxfdmFsdWUYASABKA4yGi5nb29nbGUucHJv",
+            "dG9idWYuTnVsbFZhbHVlSAASFgoMbnVtYmVyX3ZhbHVlGAIgASgBSAASFgoM",
+            "c3RyaW5nX3ZhbHVlGAMgASgJSAASFAoKYm9vbF92YWx1ZRgEIAEoCEgAEi8K",
+            "DHN0cnVjdF92YWx1ZRgFIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RI",
+            "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW",
+            "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW",
+            "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W",
+            "QUxVRRAAQoEBChNjb20uZ29vZ2xlLnByb3RvYnVmQgtTdHJ1Y3RQcm90b1AB",
+            "WjFnaXRodWIuY29tL2dvbGFuZy9wcm90b2J1Zi9wdHlwZXMvc3RydWN0O3N0",
+            "cnVjdHBioAEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5",
+            "cGVzYgZwcm90bzM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  /// <summary>
+  ///  `NullValue` is a singleton enumeration to represent the null value for the
+  ///  `Value` type union.
+  ///
+  ///   The JSON representation for `NullValue` is JSON `null`.
+  /// </summary>
+  public enum NullValue {
+    /// <summary>
+    ///  Null value.
+    /// </summary>
+    [pbr::OriginalName("NULL_VALUE")] NullValue = 0,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  `Struct` represents a structured data value, consisting of fields
+  ///  which map to dynamically typed values. In some languages, `Struct`
+  ///  might be supported by a native representation. For example, in
+  ///  scripting languages like JS a struct is represented as an
+  ///  object. The details of that representation are described together
+  ///  with the proto support for the language.
+  ///
+  ///  The JSON representation for `Struct` is JSON object.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Struct : pb::IMessage<Struct> {
+    private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
+    public static pb::MessageParser<Struct> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Struct() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Struct(Struct other) : this() {
+      fields_ = other.fields_.Clone();
+    }
+
+    public Struct Clone() {
+      return new Struct(this);
+    }
+
+    /// <summary>Field number for the "fields" field.</summary>
+    public const int FieldsFieldNumber = 1;
+    private static readonly pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>.Codec _map_fields_codec
+        = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Value.Parser), 10);
+    private readonly pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> fields_ = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>();
+    /// <summary>
+    ///  Unordered map of dynamically typed values.
+    /// </summary>
+    public pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> Fields {
+      get { return fields_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Struct);
+    }
+
+    public bool Equals(Struct other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Fields.Equals(other.Fields)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Fields.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      fields_.WriteTo(output, _map_fields_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += fields_.CalculateSize(_map_fields_codec);
+      return size;
+    }
+
+    public void MergeFrom(Struct other) {
+      if (other == null) {
+        return;
+      }
+      fields_.Add(other.fields_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            fields_.AddEntriesFrom(input, _map_fields_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  `Value` represents a dynamically typed value which can be either
+  ///  null, a number, a string, a boolean, a recursive struct value, or a
+  ///  list of values. A producer of value is expected to set one of that
+  ///  variants, absence of any variant indicates an error.
+  ///
+  ///  The JSON representation for `Value` is JSON value.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Value : pb::IMessage<Value> {
+    private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
+    public static pb::MessageParser<Value> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Value() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Value(Value other) : this() {
+      switch (other.KindCase) {
+        case KindOneofCase.NullValue:
+          NullValue = other.NullValue;
+          break;
+        case KindOneofCase.NumberValue:
+          NumberValue = other.NumberValue;
+          break;
+        case KindOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+        case KindOneofCase.BoolValue:
+          BoolValue = other.BoolValue;
+          break;
+        case KindOneofCase.StructValue:
+          StructValue = other.StructValue.Clone();
+          break;
+        case KindOneofCase.ListValue:
+          ListValue = other.ListValue.Clone();
+          break;
+      }
+
+    }
+
+    public Value Clone() {
+      return new Value(this);
+    }
+
+    /// <summary>Field number for the "null_value" field.</summary>
+    public const int NullValueFieldNumber = 1;
+    /// <summary>
+    ///  Represents a null value.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.NullValue NullValue {
+      get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : 0; }
+      set {
+        kind_ = value;
+        kindCase_ = KindOneofCase.NullValue;
+      }
+    }
+
+    /// <summary>Field number for the "number_value" field.</summary>
+    public const int NumberValueFieldNumber = 2;
+    /// <summary>
+    ///  Represents a double value.
+    /// </summary>
+    public double NumberValue {
+      get { return kindCase_ == KindOneofCase.NumberValue ? (double) kind_ : 0D; }
+      set {
+        kind_ = value;
+        kindCase_ = KindOneofCase.NumberValue;
+      }
+    }
+
+    /// <summary>Field number for the "string_value" field.</summary>
+    public const int StringValueFieldNumber = 3;
+    /// <summary>
+    ///  Represents a string value.
+    /// </summary>
+    public string StringValue {
+      get { return kindCase_ == KindOneofCase.StringValue ? (string) kind_ : ""; }
+      set {
+        kind_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        kindCase_ = KindOneofCase.StringValue;
+      }
+    }
+
+    /// <summary>Field number for the "bool_value" field.</summary>
+    public const int BoolValueFieldNumber = 4;
+    /// <summary>
+    ///  Represents a boolean value.
+    /// </summary>
+    public bool BoolValue {
+      get { return kindCase_ == KindOneofCase.BoolValue ? (bool) kind_ : false; }
+      set {
+        kind_ = value;
+        kindCase_ = KindOneofCase.BoolValue;
+      }
+    }
+
+    /// <summary>Field number for the "struct_value" field.</summary>
+    public const int StructValueFieldNumber = 5;
+    /// <summary>
+    ///  Represents a structured value.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Struct StructValue {
+      get { return kindCase_ == KindOneofCase.StructValue ? (global::Google.Protobuf.WellKnownTypes.Struct) kind_ : null; }
+      set {
+        kind_ = value;
+        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.StructValue;
+      }
+    }
+
+    /// <summary>Field number for the "list_value" field.</summary>
+    public const int ListValueFieldNumber = 6;
+    /// <summary>
+    ///  Represents a repeated `Value`.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.ListValue ListValue {
+      get { return kindCase_ == KindOneofCase.ListValue ? (global::Google.Protobuf.WellKnownTypes.ListValue) kind_ : null; }
+      set {
+        kind_ = value;
+        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.ListValue;
+      }
+    }
+
+    private object kind_;
+    /// <summary>Enum of possible cases for the "kind" oneof.</summary>
+    public enum KindOneofCase {
+      None = 0,
+      NullValue = 1,
+      NumberValue = 2,
+      StringValue = 3,
+      BoolValue = 4,
+      StructValue = 5,
+      ListValue = 6,
+    }
+    private KindOneofCase kindCase_ = KindOneofCase.None;
+    public KindOneofCase KindCase {
+      get { return kindCase_; }
+    }
+
+    public void ClearKind() {
+      kindCase_ = KindOneofCase.None;
+      kind_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Value);
+    }
+
+    public bool Equals(Value other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (NullValue != other.NullValue) return false;
+      if (NumberValue != other.NumberValue) return false;
+      if (StringValue != other.StringValue) return false;
+      if (BoolValue != other.BoolValue) return false;
+      if (!object.Equals(StructValue, other.StructValue)) return false;
+      if (!object.Equals(ListValue, other.ListValue)) return false;
+      if (KindCase != other.KindCase) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.NumberValue) hash ^= NumberValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.StringValue) hash ^= StringValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.BoolValue) hash ^= BoolValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode();
+      hash ^= (int) kindCase_;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (kindCase_ == KindOneofCase.NullValue) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) NullValue);
+      }
+      if (kindCase_ == KindOneofCase.NumberValue) {
+        output.WriteRawTag(17);
+        output.WriteDouble(NumberValue);
+      }
+      if (kindCase_ == KindOneofCase.StringValue) {
+        output.WriteRawTag(26);
+        output.WriteString(StringValue);
+      }
+      if (kindCase_ == KindOneofCase.BoolValue) {
+        output.WriteRawTag(32);
+        output.WriteBool(BoolValue);
+      }
+      if (kindCase_ == KindOneofCase.StructValue) {
+        output.WriteRawTag(42);
+        output.WriteMessage(StructValue);
+      }
+      if (kindCase_ == KindOneofCase.ListValue) {
+        output.WriteRawTag(50);
+        output.WriteMessage(ListValue);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (kindCase_ == KindOneofCase.NullValue) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue);
+      }
+      if (kindCase_ == KindOneofCase.NumberValue) {
+        size += 1 + 8;
+      }
+      if (kindCase_ == KindOneofCase.StringValue) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
+      }
+      if (kindCase_ == KindOneofCase.BoolValue) {
+        size += 1 + 1;
+      }
+      if (kindCase_ == KindOneofCase.StructValue) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructValue);
+      }
+      if (kindCase_ == KindOneofCase.ListValue) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Value other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.KindCase) {
+        case KindOneofCase.NullValue:
+          NullValue = other.NullValue;
+          break;
+        case KindOneofCase.NumberValue:
+          NumberValue = other.NumberValue;
+          break;
+        case KindOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+        case KindOneofCase.BoolValue:
+          BoolValue = other.BoolValue;
+          break;
+        case KindOneofCase.StructValue:
+          StructValue = other.StructValue;
+          break;
+        case KindOneofCase.ListValue:
+          ListValue = other.ListValue;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            kind_ = input.ReadEnum();
+            kindCase_ = KindOneofCase.NullValue;
+            break;
+          }
+          case 17: {
+            NumberValue = input.ReadDouble();
+            break;
+          }
+          case 26: {
+            StringValue = input.ReadString();
+            break;
+          }
+          case 32: {
+            BoolValue = input.ReadBool();
+            break;
+          }
+          case 42: {
+            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
+            if (kindCase_ == KindOneofCase.StructValue) {
+              subBuilder.MergeFrom(StructValue);
+            }
+            input.ReadMessage(subBuilder);
+            StructValue = subBuilder;
+            break;
+          }
+          case 50: {
+            global::Google.Protobuf.WellKnownTypes.ListValue subBuilder = new global::Google.Protobuf.WellKnownTypes.ListValue();
+            if (kindCase_ == KindOneofCase.ListValue) {
+              subBuilder.MergeFrom(ListValue);
+            }
+            input.ReadMessage(subBuilder);
+            ListValue = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  `ListValue` is a wrapper around a repeated field of values.
+  ///
+  ///  The JSON representation for `ListValue` is JSON array.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ListValue : pb::IMessage<ListValue> {
+    private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
+    public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ListValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ListValue(ListValue other) : this() {
+      values_ = other.values_.Clone();
+    }
+
+    public ListValue Clone() {
+      return new ListValue(this);
+    }
+
+    /// <summary>Field number for the "values" field.</summary>
+    public const int ValuesFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Value> _repeated_values_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.WellKnownTypes.Value.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> values_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value>();
+    /// <summary>
+    ///  Repeated field of dynamically typed values.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> Values {
+      get { return values_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ListValue);
+    }
+
+    public bool Equals(ListValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!values_.Equals(other.values_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= values_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      values_.WriteTo(output, _repeated_values_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += values_.CalculateSize(_repeated_values_codec);
+      return size;
+    }
+
+    public void MergeFrom(ListValue other) {
+      if (other == null) {
+        return;
+      }
+      values_.Add(other.values_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            values_.AddEntriesFrom(input, _repeated_values_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
new file mode 100644
index 0000000..dd485d3
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
@@ -0,0 +1,80 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    /// <summary>
+    /// Extension methods on BCL time-related types, converting to protobuf types.
+    /// </summary>
+    public static class TimeExtensions
+    {
+        /// <summary>
+        /// Converts the given <see cref="DateTime"/> to a <see cref="Timestamp"/>.
+        /// </summary>
+        /// <param name="dateTime">The date and time to convert to a timestamp.</param>
+        /// <exception cref="ArgumentException">The <paramref name="dateTime"/> value has a <see cref="DateTime.Kind"/>other than <c>Utc</c>.</exception>
+        /// <returns>The converted timestamp.</returns>
+        public static Timestamp ToTimestamp(this DateTime dateTime)
+        {
+            return Timestamp.FromDateTime(dateTime);
+        }
+
+        /// <summary>
+        /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>
+        /// </summary>
+        /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time
+        /// is represented) but is not a separate part of the resulting value. In other words, there is no
+        /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks>
+        /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param>
+        /// <returns>The converted timestamp.</returns>
+        public static Timestamp ToTimestamp(this DateTimeOffset dateTimeOffset)
+        {
+            return Timestamp.FromDateTimeOffset(dateTimeOffset);
+        }
+
+        /// <summary>
+        /// Converts the given <see cref="TimeSpan"/> to a <see cref="Duration"/>.
+        /// </summary>
+        /// <param name="timeSpan">The time span to convert.</param>
+        /// <returns>The converted duration.</returns>
+        public static Duration ToDuration(this TimeSpan timeSpan)
+        {
+            return Duration.FromTimeSpan(timeSpan);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
new file mode 100644
index 0000000..053b88b
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
@@ -0,0 +1,241 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/timestamp.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class TimestampReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/timestamp.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static TimestampReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv",
+            "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY",
+            "AiABKAVCgQEKE2NvbS5nb29nbGUucHJvdG9idWZCDlRpbWVzdGFtcFByb3Rv",
+            "UAFaK2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy90aW1lc3Rh",
+            "bXCgAQH4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw",
+            "ZXNiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), global::Google.Protobuf.WellKnownTypes.Timestamp.Parser, new[]{ "Seconds", "Nanos" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  A Timestamp represents a point in time independent of any time zone
+  ///  or calendar, represented as seconds and fractions of seconds at
+  ///  nanosecond resolution in UTC Epoch time. It is encoded using the
+  ///  Proleptic Gregorian Calendar which extends the Gregorian calendar
+  ///  backwards to year one. It is encoded assuming all minutes are 60
+  ///  seconds long, i.e. leap seconds are "smeared" so that no leap second
+  ///  table is needed for interpretation. Range is from
+  ///  0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+  ///  By restricting to that range, we ensure that we can convert to
+  ///  and from  RFC 3339 date strings.
+  ///  See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+  ///
+  ///  Example 1: Compute Timestamp from POSIX `time()`.
+  ///
+  ///      Timestamp timestamp;
+  ///      timestamp.set_seconds(time(NULL));
+  ///      timestamp.set_nanos(0);
+  ///
+  ///  Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+  ///
+  ///      struct timeval tv;
+  ///      gettimeofday(&amp;tv, NULL);
+  ///
+  ///      Timestamp timestamp;
+  ///      timestamp.set_seconds(tv.tv_sec);
+  ///      timestamp.set_nanos(tv.tv_usec * 1000);
+  ///
+  ///  Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+  ///
+  ///      FILETIME ft;
+  ///      GetSystemTimeAsFileTime(&amp;ft);
+  ///      UINT64 ticks = (((UINT64)ft.dwHighDateTime) &lt;&lt; 32) | ft.dwLowDateTime;
+  ///
+  ///      // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+  ///      // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+  ///      Timestamp timestamp;
+  ///      timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+  ///      timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+  ///
+  ///  Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+  ///
+  ///      long millis = System.currentTimeMillis();
+  ///
+  ///      Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+  ///          .setNanos((int) ((millis % 1000) * 1000000)).build();
+  ///
+  ///  Example 5: Compute Timestamp from current time in Python.
+  ///
+  ///      now = time.time()
+  ///      seconds = int(now)
+  ///      nanos = int((now - seconds) * 10**9)
+  ///      timestamp = Timestamp(seconds=seconds, nanos=nanos)
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Timestamp : pb::IMessage<Timestamp> {
+    private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
+    public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Timestamp() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Timestamp(Timestamp other) : this() {
+      seconds_ = other.seconds_;
+      nanos_ = other.nanos_;
+    }
+
+    public Timestamp Clone() {
+      return new Timestamp(this);
+    }
+
+    /// <summary>Field number for the "seconds" field.</summary>
+    public const int SecondsFieldNumber = 1;
+    private long seconds_;
+    /// <summary>
+    ///  Represents seconds of UTC time since Unix epoch
+    ///  1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+    ///  9999-12-31T23:59:59Z inclusive.
+    /// </summary>
+    public long Seconds {
+      get { return seconds_; }
+      set {
+        seconds_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "nanos" field.</summary>
+    public const int NanosFieldNumber = 2;
+    private int nanos_;
+    /// <summary>
+    ///  Non-negative fractions of a second at nanosecond resolution. Negative
+    ///  second values with fractions must still have non-negative nanos values
+    ///  that count forward in time. Must be from 0 to 999,999,999
+    ///  inclusive.
+    /// </summary>
+    public int Nanos {
+      get { return nanos_; }
+      set {
+        nanos_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Timestamp);
+    }
+
+    public bool Equals(Timestamp other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Seconds != other.Seconds) return false;
+      if (Nanos != other.Nanos) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Seconds != 0L) hash ^= Seconds.GetHashCode();
+      if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Seconds != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Seconds);
+      }
+      if (Nanos != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Nanos);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Seconds != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Seconds);
+      }
+      if (Nanos != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Timestamp other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Seconds != 0L) {
+        Seconds = other.Seconds;
+      }
+      if (other.Nanos != 0) {
+        Nanos = other.Nanos;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Seconds = input.ReadInt64();
+            break;
+          }
+          case 16: {
+            Nanos = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
new file mode 100644
index 0000000..aa40347
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
@@ -0,0 +1,241 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Text;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public partial class Timestamp : ICustomDiagnosticMessage
+    {
+        private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+        // Constants determined programmatically, but then hard-coded so they can be constant expressions.
+        private const long BclSecondsAtUnixEpoch = 62135596800;
+        internal const long UnixSecondsAtBclMaxValue = 253402300799;
+        internal const long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch;
+        internal const int MaxNanos = Duration.NanosecondsPerSecond - 1;
+
+        private static bool IsNormalized(long seconds, int nanoseconds) =>
+            nanoseconds >= 0 &&
+            nanoseconds <= MaxNanos &&
+            seconds >= UnixSecondsAtBclMinValue &&
+            seconds <= UnixSecondsAtBclMaxValue;
+
+        /// <summary>
+        /// Returns the difference between one <see cref="Timestamp"/> and another, as a <see cref="Duration"/>.
+        /// </summary>
+        /// <param name="lhs">The timestamp to subtract from. Must not be null.</param>
+        /// <param name="rhs">The timestamp to subtract. Must not be null.</param>
+        /// <returns>The difference between the two specified timestamps.</returns>
+        public static Duration operator -(Timestamp lhs, Timestamp rhs)
+        {
+            ProtoPreconditions.CheckNotNull(lhs, "lhs");
+            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            checked
+            {
+                return Duration.Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
+            }
+        }
+
+        /// <summary>
+        /// Adds a <see cref="Duration"/> to a <see cref="Timestamp"/>, to obtain another <c>Timestamp</c>.
+        /// </summary>
+        /// <param name="lhs">The timestamp to add the duration to. Must not be null.</param>
+        /// <param name="rhs">The duration to add. Must not be null.</param>
+        /// <returns>The result of adding the duration to the timestamp.</returns>
+        public static Timestamp operator +(Timestamp lhs, Duration rhs)
+        {
+            ProtoPreconditions.CheckNotNull(lhs, "lhs");
+            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            checked
+            {
+                return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos);
+            }
+        }
+
+        /// <summary>
+        /// Subtracts a <see cref="Duration"/> from a <see cref="Timestamp"/>, to obtain another <c>Timestamp</c>.
+        /// </summary>
+        /// <param name="lhs">The timestamp to subtract the duration from. Must not be null.</param>
+        /// <param name="rhs">The duration to subtract.</param>
+        /// <returns>The result of subtracting the duration from the timestamp.</returns>
+        public static Timestamp operator -(Timestamp lhs, Duration rhs)
+        {
+            ProtoPreconditions.CheckNotNull(lhs, "lhs");
+            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            checked
+            {
+                return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
+            }
+        }
+
+        /// <summary>
+        /// Converts this timestamp into a <see cref="DateTime"/>.
+        /// </summary>
+        /// <remarks>
+        /// The resulting <c>DateTime</c> will always have a <c>Kind</c> of <c>Utc</c>.
+        /// If the timestamp is not a precise number of ticks, it will be truncated towards the start
+        /// of time. For example, a timestamp with a <see cref="Nanos"/> value of 99 will result in a
+        /// <see cref="DateTime"/> value precisely on a second.
+        /// </remarks>
+        /// <returns>This timestamp as a <c>DateTime</c>.</returns>
+        /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is
+        /// incorrectly normalized or is outside the valid range.</exception>
+        public DateTime ToDateTime()
+        {
+            if (!IsNormalized(Seconds, Nanos))
+            {
+                throw new InvalidOperationException(@"Timestamp contains invalid values: Seconds={Seconds}; Nanos={Nanos}");
+            }
+            return UnixEpoch.AddSeconds(Seconds).AddTicks(Nanos / Duration.NanosecondsPerTick);
+        }
+
+        /// <summary>
+        /// Converts this timestamp into a <see cref="DateTimeOffset"/>.
+        /// </summary>
+        /// <remarks>
+        /// The resulting <c>DateTimeOffset</c> will always have an <c>Offset</c> of zero.
+        /// If the timestamp is not a precise number of ticks, it will be truncated towards the start
+        /// of time. For example, a timestamp with a <see cref="Nanos"/> value of 99 will result in a
+        /// <see cref="DateTimeOffset"/> value precisely on a second.
+        /// </remarks>
+        /// <returns>This timestamp as a <c>DateTimeOffset</c>.</returns>
+        /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is
+        /// incorrectly normalized or is outside the valid range.</exception>
+        public DateTimeOffset ToDateTimeOffset()
+        {
+            return new DateTimeOffset(ToDateTime(), TimeSpan.Zero);
+        }
+
+        /// <summary>
+        /// Converts the specified <see cref="DateTime"/> to a <see cref="Timestamp"/>.
+        /// </summary>
+        /// <param name="dateTime"></param>
+        /// <exception cref="ArgumentException">The <c>Kind</c> of <paramref name="dateTime"/> is not <c>DateTimeKind.Utc</c>.</exception>
+        /// <returns>The converted timestamp.</returns>
+        public static Timestamp FromDateTime(DateTime dateTime)
+        {
+            if (dateTime.Kind != DateTimeKind.Utc)
+            {
+                throw new ArgumentException("Conversion from DateTime to Timestamp requires the DateTime kind to be Utc", "dateTime");
+            }
+            // Do the arithmetic using DateTime.Ticks, which is always non-negative, making things simpler.
+            long secondsSinceBclEpoch = dateTime.Ticks / TimeSpan.TicksPerSecond;
+            int nanoseconds = (int)  (dateTime.Ticks % TimeSpan.TicksPerSecond) * Duration.NanosecondsPerTick;
+            return new Timestamp { Seconds = secondsSinceBclEpoch - BclSecondsAtUnixEpoch, Nanos = nanoseconds };
+        }
+
+        /// <summary>
+        /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>
+        /// </summary>
+        /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time
+        /// is represented) but is not a separate part of the resulting value. In other words, there is no
+        /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks>
+        /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param>
+        /// <returns>The converted timestamp.</returns>
+        public static Timestamp FromDateTimeOffset(DateTimeOffset dateTimeOffset)
+        {
+            // We don't need to worry about this having negative ticks: DateTimeOffset is constrained to handle
+            // values whose *UTC* value is in the range of DateTime.
+            return FromDateTime(dateTimeOffset.UtcDateTime);
+        }
+
+        internal static Timestamp Normalize(long seconds, int nanoseconds)
+        {
+            int extraSeconds = nanoseconds / Duration.NanosecondsPerSecond;
+            seconds += extraSeconds;
+            nanoseconds -= extraSeconds * Duration.NanosecondsPerSecond;
+
+            if (nanoseconds < 0)
+            {
+                nanoseconds += Duration.NanosecondsPerSecond;
+                seconds--;
+            }
+            return new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+        }
+
+        /// <summary>
+        /// Converts a timestamp specified in seconds/nanoseconds to a string.
+        /// </summary>
+        /// <remarks>
+        /// If the value is a normalized duration in the range described in <c>timestamp.proto</c>,
+        /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+        /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+        /// </remarks>
+        /// <param name="seconds">Seconds portion of the duration.</param>
+        /// <param name="nanoseconds">Nanoseconds portion of the duration.</param>
+        /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+        /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+        internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly)
+        {
+            if (IsNormalized(seconds, nanoseconds))
+            {
+                // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value)
+                DateTime dateTime = UnixEpoch.AddSeconds(seconds);
+                var builder = new StringBuilder();
+                builder.Append('"');
+                builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture));
+                Duration.AppendNanoseconds(builder, nanoseconds);
+                builder.Append("Z\"");
+                return builder.ToString();
+            }
+            if (diagnosticOnly)
+            {
+                return string.Format(CultureInfo.InvariantCulture,
+                    "{{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"{0}\", \"nanos\": {1} }}",
+                    seconds,
+                    nanoseconds);
+            }
+            else
+            {
+                throw new InvalidOperationException("Non-normalized timestamp value");
+            }
+        }
+
+        /// <summary>
+        /// Returns a string representation of this <see cref="Timestamp"/> for diagnostic purposes.
+        /// </summary>
+        /// <remarks>
+        /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+        /// when the value is non-normalized or out of range, a JSON object representation will be returned
+        /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+        /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+        /// values.
+        /// </remarks>
+        /// <returns>A string representation of this value.</returns>
+        public string ToDiagnosticString()
+        {
+            return ToJson(Seconds, Nanos, true);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
new file mode 100644
index 0000000..657c246
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
@@ -0,0 +1,1347 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/type.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/type.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class TypeReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/type.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static TypeReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Chpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxIPZ29vZ2xlLnByb3RvYnVm",
+            "Ghlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvGiRnb29nbGUvcHJvdG9idWYv",
+            "c291cmNlX2NvbnRleHQucHJvdG8i1wEKBFR5cGUSDAoEbmFtZRgBIAEoCRIm",
+            "CgZmaWVsZHMYAiADKAsyFi5nb29nbGUucHJvdG9idWYuRmllbGQSDgoGb25l",
+            "b2ZzGAMgAygJEigKB29wdGlvbnMYBCADKAsyFy5nb29nbGUucHJvdG9idWYu",
+            "T3B0aW9uEjYKDnNvdXJjZV9jb250ZXh0GAUgASgLMh4uZ29vZ2xlLnByb3Rv",
+            "YnVmLlNvdXJjZUNvbnRleHQSJwoGc3ludGF4GAYgASgOMhcuZ29vZ2xlLnBy",
+            "b3RvYnVmLlN5bnRheCLVBQoFRmllbGQSKQoEa2luZBgBIAEoDjIbLmdvb2ds",
+            "ZS5wcm90b2J1Zi5GaWVsZC5LaW5kEjcKC2NhcmRpbmFsaXR5GAIgASgOMiIu",
+            "Z29vZ2xlLnByb3RvYnVmLkZpZWxkLkNhcmRpbmFsaXR5Eg4KBm51bWJlchgD",
+            "IAEoBRIMCgRuYW1lGAQgASgJEhAKCHR5cGVfdXJsGAYgASgJEhMKC29uZW9m",
+            "X2luZGV4GAcgASgFEg4KBnBhY2tlZBgIIAEoCBIoCgdvcHRpb25zGAkgAygL",
+            "MhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhIRCglqc29uX25hbWUYCiABKAkS",
+            "FQoNZGVmYXVsdF92YWx1ZRgLIAEoCSLIAgoES2luZBIQCgxUWVBFX1VOS05P",
+            "V04QABIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxPQVQQAhIOCgpUWVBF",
+            "X0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBFX0lOVDMyEAUSEAoM",
+            "VFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcSDQoJVFlQRV9CT09M",
+            "EAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQEAoSEAoMVFlQRV9N",
+            "RVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMyEA0SDQoJ",
+            "VFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVfU0ZJWEVE",
+            "NjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIidAoLQ2Fy",
+            "ZGluYWxpdHkSFwoTQ0FSRElOQUxJVFlfVU5LTk9XThAAEhgKFENBUkRJTkFM",
+            "SVRZX09QVElPTkFMEAESGAoUQ0FSRElOQUxJVFlfUkVRVUlSRUQQAhIYChRD",
+            "QVJESU5BTElUWV9SRVBFQVRFRBADIs4BCgRFbnVtEgwKBG5hbWUYASABKAkS",
+            "LQoJZW51bXZhbHVlGAIgAygLMhouZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1",
+            "ZRIoCgdvcHRpb25zGAMgAygLMhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhI2",
+            "Cg5zb3VyY2VfY29udGV4dBgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5Tb3Vy",
+            "Y2VDb250ZXh0EicKBnN5bnRheBgFIAEoDjIXLmdvb2dsZS5wcm90b2J1Zi5T",
+            "eW50YXgiUwoJRW51bVZhbHVlEgwKBG5hbWUYASABKAkSDgoGbnVtYmVyGAIg",
+            "ASgFEigKB29wdGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9u",
+            "IjsKBk9wdGlvbhIMCgRuYW1lGAEgASgJEiMKBXZhbHVlGAIgASgLMhQuZ29v",
+            "Z2xlLnByb3RvYnVmLkFueSouCgZTeW50YXgSEQoNU1lOVEFYX1BST1RPMhAA",
+            "EhEKDVNZTlRBWF9QUk9UTzMQAUJMChNjb20uZ29vZ2xlLnByb3RvYnVmQglU",
+            "eXBlUHJvdG9QAaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25v",
+            "d25UeXBlc2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName", "DefaultValue" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  /// <summary>
+  ///  The syntax in which a protocol buffer element is defined.
+  /// </summary>
+  public enum Syntax {
+    /// <summary>
+    ///  Syntax `proto2`.
+    /// </summary>
+    [pbr::OriginalName("SYNTAX_PROTO2")] Proto2 = 0,
+    /// <summary>
+    ///  Syntax `proto3`.
+    /// </summary>
+    [pbr::OriginalName("SYNTAX_PROTO3")] Proto3 = 1,
+  }
+
+  #endregion
+
+  #region Messages
+  /// <summary>
+  ///  A protocol buffer message type.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Type : pb::IMessage<Type> {
+    private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
+    public static pb::MessageParser<Type> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Type() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Type(Type other) : this() {
+      name_ = other.name_;
+      fields_ = other.fields_.Clone();
+      oneofs_ = other.oneofs_.Clone();
+      options_ = other.options_.Clone();
+      SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+      syntax_ = other.syntax_;
+    }
+
+    public Type Clone() {
+      return new Type(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  The fully qualified message name.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "fields" field.</summary>
+    public const int FieldsFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Field> _repeated_fields_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Field.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field> fields_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field>();
+    /// <summary>
+    ///  The list of fields.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field> Fields {
+      get { return fields_; }
+    }
+
+    /// <summary>Field number for the "oneofs" field.</summary>
+    public const int OneofsFieldNumber = 3;
+    private static readonly pb::FieldCodec<string> _repeated_oneofs_codec
+        = pb::FieldCodec.ForString(26);
+    private readonly pbc::RepeatedField<string> oneofs_ = new pbc::RepeatedField<string>();
+    /// <summary>
+    ///  The list of types appearing in `oneof` definitions in this type.
+    /// </summary>
+    public pbc::RepeatedField<string> Oneofs {
+      get { return oneofs_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  The protocol buffer options.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    /// <summary>Field number for the "source_context" field.</summary>
+    public const int SourceContextFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContext_;
+    /// <summary>
+    ///  The source context.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
+      get { return sourceContext_; }
+      set {
+        sourceContext_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "syntax" field.</summary>
+    public const int SyntaxFieldNumber = 6;
+    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0;
+    /// <summary>
+    ///  The source syntax.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+      get { return syntax_; }
+      set {
+        syntax_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Type);
+    }
+
+    public bool Equals(Type other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!fields_.Equals(other.fields_)) return false;
+      if(!oneofs_.Equals(other.oneofs_)) return false;
+      if(!options_.Equals(other.options_)) return false;
+      if (!object.Equals(SourceContext, other.SourceContext)) return false;
+      if (Syntax != other.Syntax) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= fields_.GetHashCode();
+      hash ^= oneofs_.GetHashCode();
+      hash ^= options_.GetHashCode();
+      if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
+      if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      fields_.WriteTo(output, _repeated_fields_codec);
+      oneofs_.WriteTo(output, _repeated_oneofs_codec);
+      options_.WriteTo(output, _repeated_options_codec);
+      if (sourceContext_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(SourceContext);
+      }
+      if (Syntax != 0) {
+        output.WriteRawTag(48);
+        output.WriteEnum((int) Syntax);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += fields_.CalculateSize(_repeated_fields_codec);
+      size += oneofs_.CalculateSize(_repeated_oneofs_codec);
+      size += options_.CalculateSize(_repeated_options_codec);
+      if (sourceContext_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
+      }
+      if (Syntax != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Type other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      fields_.Add(other.fields_);
+      oneofs_.Add(other.oneofs_);
+      options_.Add(other.options_);
+      if (other.sourceContext_ != null) {
+        if (sourceContext_ == null) {
+          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+        }
+        SourceContext.MergeFrom(other.SourceContext);
+      }
+      if (other.Syntax != 0) {
+        Syntax = other.Syntax;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            fields_.AddEntriesFrom(input, _repeated_fields_codec);
+            break;
+          }
+          case 26: {
+            oneofs_.AddEntriesFrom(input, _repeated_oneofs_codec);
+            break;
+          }
+          case 34: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+          case 42: {
+            if (sourceContext_ == null) {
+              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(sourceContext_);
+            break;
+          }
+          case 48: {
+            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A single field of a message type.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Field : pb::IMessage<Field> {
+    private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
+    public static pb::MessageParser<Field> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Field() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Field(Field other) : this() {
+      kind_ = other.kind_;
+      cardinality_ = other.cardinality_;
+      number_ = other.number_;
+      name_ = other.name_;
+      typeUrl_ = other.typeUrl_;
+      oneofIndex_ = other.oneofIndex_;
+      packed_ = other.packed_;
+      options_ = other.options_.Clone();
+      jsonName_ = other.jsonName_;
+      defaultValue_ = other.defaultValue_;
+    }
+
+    public Field Clone() {
+      return new Field(this);
+    }
+
+    /// <summary>Field number for the "kind" field.</summary>
+    public const int KindFieldNumber = 1;
+    private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = 0;
+    /// <summary>
+    ///  The field type.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Field.Types.Kind Kind {
+      get { return kind_; }
+      set {
+        kind_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "cardinality" field.</summary>
+    public const int CardinalityFieldNumber = 2;
+    private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = 0;
+    /// <summary>
+    ///  The field cardinality.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality Cardinality {
+      get { return cardinality_; }
+      set {
+        cardinality_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "number" field.</summary>
+    public const int NumberFieldNumber = 3;
+    private int number_;
+    /// <summary>
+    ///  The field number.
+    /// </summary>
+    public int Number {
+      get { return number_; }
+      set {
+        number_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 4;
+    private string name_ = "";
+    /// <summary>
+    ///  The field name.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "type_url" field.</summary>
+    public const int TypeUrlFieldNumber = 6;
+    private string typeUrl_ = "";
+    /// <summary>
+    ///  The field type URL, without the scheme, for message or enumeration
+    ///  types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+    /// </summary>
+    public string TypeUrl {
+      get { return typeUrl_; }
+      set {
+        typeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "oneof_index" field.</summary>
+    public const int OneofIndexFieldNumber = 7;
+    private int oneofIndex_;
+    /// <summary>
+    ///  The index of the field type in `Type.oneofs`, for message or enumeration
+    ///  types. The first type has index 1; zero means the type is not in the list.
+    /// </summary>
+    public int OneofIndex {
+      get { return oneofIndex_; }
+      set {
+        oneofIndex_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "packed" field.</summary>
+    public const int PackedFieldNumber = 8;
+    private bool packed_;
+    /// <summary>
+    ///  Whether to use alternative packed wire representation.
+    /// </summary>
+    public bool Packed {
+      get { return packed_; }
+      set {
+        packed_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  The protocol buffer options.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    /// <summary>Field number for the "json_name" field.</summary>
+    public const int JsonNameFieldNumber = 10;
+    private string jsonName_ = "";
+    /// <summary>
+    ///  The field JSON name.
+    /// </summary>
+    public string JsonName {
+      get { return jsonName_; }
+      set {
+        jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "default_value" field.</summary>
+    public const int DefaultValueFieldNumber = 11;
+    private string defaultValue_ = "";
+    /// <summary>
+    ///  The string value of the default value of this field. Proto2 syntax only.
+    /// </summary>
+    public string DefaultValue {
+      get { return defaultValue_; }
+      set {
+        defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Field);
+    }
+
+    public bool Equals(Field other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Kind != other.Kind) return false;
+      if (Cardinality != other.Cardinality) return false;
+      if (Number != other.Number) return false;
+      if (Name != other.Name) return false;
+      if (TypeUrl != other.TypeUrl) return false;
+      if (OneofIndex != other.OneofIndex) return false;
+      if (Packed != other.Packed) return false;
+      if(!options_.Equals(other.options_)) return false;
+      if (JsonName != other.JsonName) return false;
+      if (DefaultValue != other.DefaultValue) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Kind != 0) hash ^= Kind.GetHashCode();
+      if (Cardinality != 0) hash ^= Cardinality.GetHashCode();
+      if (Number != 0) hash ^= Number.GetHashCode();
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
+      if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode();
+      if (Packed != false) hash ^= Packed.GetHashCode();
+      hash ^= options_.GetHashCode();
+      if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
+      if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Kind != 0) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Kind);
+      }
+      if (Cardinality != 0) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) Cardinality);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Number);
+      }
+      if (Name.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(Name);
+      }
+      if (TypeUrl.Length != 0) {
+        output.WriteRawTag(50);
+        output.WriteString(TypeUrl);
+      }
+      if (OneofIndex != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(OneofIndex);
+      }
+      if (Packed != false) {
+        output.WriteRawTag(64);
+        output.WriteBool(Packed);
+      }
+      options_.WriteTo(output, _repeated_options_codec);
+      if (JsonName.Length != 0) {
+        output.WriteRawTag(82);
+        output.WriteString(JsonName);
+      }
+      if (DefaultValue.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(DefaultValue);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Kind != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Kind);
+      }
+      if (Cardinality != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Cardinality);
+      }
+      if (Number != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
+      }
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (TypeUrl.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeUrl);
+      }
+      if (OneofIndex != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofIndex);
+      }
+      if (Packed != false) {
+        size += 1 + 1;
+      }
+      size += options_.CalculateSize(_repeated_options_codec);
+      if (JsonName.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
+      }
+      if (DefaultValue.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Field other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Kind != 0) {
+        Kind = other.Kind;
+      }
+      if (other.Cardinality != 0) {
+        Cardinality = other.Cardinality;
+      }
+      if (other.Number != 0) {
+        Number = other.Number;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.TypeUrl.Length != 0) {
+        TypeUrl = other.TypeUrl;
+      }
+      if (other.OneofIndex != 0) {
+        OneofIndex = other.OneofIndex;
+      }
+      if (other.Packed != false) {
+        Packed = other.Packed;
+      }
+      options_.Add(other.options_);
+      if (other.JsonName.Length != 0) {
+        JsonName = other.JsonName;
+      }
+      if (other.DefaultValue.Length != 0) {
+        DefaultValue = other.DefaultValue;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
+            break;
+          }
+          case 16: {
+            cardinality_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
+            break;
+          }
+          case 24: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            Name = input.ReadString();
+            break;
+          }
+          case 50: {
+            TypeUrl = input.ReadString();
+            break;
+          }
+          case 56: {
+            OneofIndex = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Packed = input.ReadBool();
+            break;
+          }
+          case 74: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+          case 82: {
+            JsonName = input.ReadString();
+            break;
+          }
+          case 90: {
+            DefaultValue = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the Field message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      /// <summary>
+      ///  Basic field types.
+      /// </summary>
+      public enum Kind {
+        /// <summary>
+        ///  Field type unknown.
+        /// </summary>
+        [pbr::OriginalName("TYPE_UNKNOWN")] TypeUnknown = 0,
+        /// <summary>
+        ///  Field type double.
+        /// </summary>
+        [pbr::OriginalName("TYPE_DOUBLE")] TypeDouble = 1,
+        /// <summary>
+        ///  Field type float.
+        /// </summary>
+        [pbr::OriginalName("TYPE_FLOAT")] TypeFloat = 2,
+        /// <summary>
+        ///  Field type int64.
+        /// </summary>
+        [pbr::OriginalName("TYPE_INT64")] TypeInt64 = 3,
+        /// <summary>
+        ///  Field type uint64.
+        /// </summary>
+        [pbr::OriginalName("TYPE_UINT64")] TypeUint64 = 4,
+        /// <summary>
+        ///  Field type int32.
+        /// </summary>
+        [pbr::OriginalName("TYPE_INT32")] TypeInt32 = 5,
+        /// <summary>
+        ///  Field type fixed64.
+        /// </summary>
+        [pbr::OriginalName("TYPE_FIXED64")] TypeFixed64 = 6,
+        /// <summary>
+        ///  Field type fixed32.
+        /// </summary>
+        [pbr::OriginalName("TYPE_FIXED32")] TypeFixed32 = 7,
+        /// <summary>
+        ///  Field type bool.
+        /// </summary>
+        [pbr::OriginalName("TYPE_BOOL")] TypeBool = 8,
+        /// <summary>
+        ///  Field type string.
+        /// </summary>
+        [pbr::OriginalName("TYPE_STRING")] TypeString = 9,
+        /// <summary>
+        ///  Field type group. Proto2 syntax only, and deprecated.
+        /// </summary>
+        [pbr::OriginalName("TYPE_GROUP")] TypeGroup = 10,
+        /// <summary>
+        ///  Field type message.
+        /// </summary>
+        [pbr::OriginalName("TYPE_MESSAGE")] TypeMessage = 11,
+        /// <summary>
+        ///  Field type bytes.
+        /// </summary>
+        [pbr::OriginalName("TYPE_BYTES")] TypeBytes = 12,
+        /// <summary>
+        ///  Field type uint32.
+        /// </summary>
+        [pbr::OriginalName("TYPE_UINT32")] TypeUint32 = 13,
+        /// <summary>
+        ///  Field type enum.
+        /// </summary>
+        [pbr::OriginalName("TYPE_ENUM")] TypeEnum = 14,
+        /// <summary>
+        ///  Field type sfixed32.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SFIXED32")] TypeSfixed32 = 15,
+        /// <summary>
+        ///  Field type sfixed64.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SFIXED64")] TypeSfixed64 = 16,
+        /// <summary>
+        ///  Field type sint32.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SINT32")] TypeSint32 = 17,
+        /// <summary>
+        ///  Field type sint64.
+        /// </summary>
+        [pbr::OriginalName("TYPE_SINT64")] TypeSint64 = 18,
+      }
+
+      /// <summary>
+      ///  Whether a field is optional, required, or repeated.
+      /// </summary>
+      public enum Cardinality {
+        /// <summary>
+        ///  For fields with unknown cardinality.
+        /// </summary>
+        [pbr::OriginalName("CARDINALITY_UNKNOWN")] Unknown = 0,
+        /// <summary>
+        ///  For optional fields.
+        /// </summary>
+        [pbr::OriginalName("CARDINALITY_OPTIONAL")] Optional = 1,
+        /// <summary>
+        ///  For required fields. Proto2 syntax only.
+        /// </summary>
+        [pbr::OriginalName("CARDINALITY_REQUIRED")] Required = 2,
+        /// <summary>
+        ///  For repeated fields.
+        /// </summary>
+        [pbr::OriginalName("CARDINALITY_REPEATED")] Repeated = 3,
+      }
+
+    }
+    #endregion
+
+  }
+
+  /// <summary>
+  ///  Enum type definition.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Enum : pb::IMessage<Enum> {
+    private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
+    public static pb::MessageParser<Enum> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Enum() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Enum(Enum other) : this() {
+      name_ = other.name_;
+      enumvalue_ = other.enumvalue_.Clone();
+      options_ = other.options_.Clone();
+      SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+      syntax_ = other.syntax_;
+    }
+
+    public Enum Clone() {
+      return new Enum(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  Enum type name.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "enumvalue" field.</summary>
+    public const int EnumvalueFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.EnumValue> _repeated_enumvalue_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.EnumValue.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue> enumvalue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue>();
+    /// <summary>
+    ///  Enum value definitions.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue> Enumvalue {
+      get { return enumvalue_; }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  Protocol buffer options.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    /// <summary>Field number for the "source_context" field.</summary>
+    public const int SourceContextFieldNumber = 4;
+    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContext_;
+    /// <summary>
+    ///  The source context.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
+      get { return sourceContext_; }
+      set {
+        sourceContext_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "syntax" field.</summary>
+    public const int SyntaxFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0;
+    /// <summary>
+    ///  The source syntax.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+      get { return syntax_; }
+      set {
+        syntax_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Enum);
+    }
+
+    public bool Equals(Enum other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if(!enumvalue_.Equals(other.enumvalue_)) return false;
+      if(!options_.Equals(other.options_)) return false;
+      if (!object.Equals(SourceContext, other.SourceContext)) return false;
+      if (Syntax != other.Syntax) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      hash ^= enumvalue_.GetHashCode();
+      hash ^= options_.GetHashCode();
+      if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
+      if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      enumvalue_.WriteTo(output, _repeated_enumvalue_codec);
+      options_.WriteTo(output, _repeated_options_codec);
+      if (sourceContext_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(SourceContext);
+      }
+      if (Syntax != 0) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) Syntax);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      size += enumvalue_.CalculateSize(_repeated_enumvalue_codec);
+      size += options_.CalculateSize(_repeated_options_codec);
+      if (sourceContext_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
+      }
+      if (Syntax != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Enum other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      enumvalue_.Add(other.enumvalue_);
+      options_.Add(other.options_);
+      if (other.sourceContext_ != null) {
+        if (sourceContext_ == null) {
+          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+        }
+        SourceContext.MergeFrom(other.SourceContext);
+      }
+      if (other.Syntax != 0) {
+        Syntax = other.Syntax;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            enumvalue_.AddEntriesFrom(input, _repeated_enumvalue_codec);
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+          case 34: {
+            if (sourceContext_ == null) {
+              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(sourceContext_);
+            break;
+          }
+          case 40: {
+            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Enum value definition.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class EnumValue : pb::IMessage<EnumValue> {
+    private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
+    public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public EnumValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public EnumValue(EnumValue other) : this() {
+      name_ = other.name_;
+      number_ = other.number_;
+      options_ = other.options_.Clone();
+    }
+
+    public EnumValue Clone() {
+      return new EnumValue(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  Enum value name.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "number" field.</summary>
+    public const int NumberFieldNumber = 2;
+    private int number_;
+    /// <summary>
+    ///  Enum value number.
+    /// </summary>
+    public int Number {
+      get { return number_; }
+      set {
+        number_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "options" field.</summary>
+    public const int OptionsFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
+    /// <summary>
+    ///  Protocol buffer options.
+    /// </summary>
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
+      get { return options_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as EnumValue);
+    }
+
+    public bool Equals(EnumValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Number != other.Number) return false;
+      if(!options_.Equals(other.options_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Number != 0) hash ^= Number.GetHashCode();
+      hash ^= options_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Number);
+      }
+      options_.WriteTo(output, _repeated_options_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Number != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
+      }
+      size += options_.CalculateSize(_repeated_options_codec);
+      return size;
+    }
+
+    public void MergeFrom(EnumValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Number != 0) {
+        Number = other.Number;
+      }
+      options_.Add(other.options_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(input, _repeated_options_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  A protocol buffer option, which can be attached to a message, field,
+  ///  enumeration, etc.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Option : pb::IMessage<Option> {
+    private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
+    public static pb::MessageParser<Option> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Option() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Option(Option other) : this() {
+      name_ = other.name_;
+      Value = other.value_ != null ? other.Value.Clone() : null;
+    }
+
+    public Option Clone() {
+      return new Option(this);
+    }
+
+    /// <summary>Field number for the "name" field.</summary>
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    /// <summary>
+    ///  The option's name. For example, `"java_package"`.
+    /// </summary>
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 2;
+    private global::Google.Protobuf.WellKnownTypes.Any value_;
+    /// <summary>
+    ///  The option's value. For example, `"com.google.protobuf"`.
+    /// </summary>
+    public global::Google.Protobuf.WellKnownTypes.Any Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Option);
+    }
+
+    public bool Equals(Option other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (!object.Equals(Value, other.Value)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (value_ != null) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (value_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (value_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Option other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.value_ != null) {
+        if (value_ == null) {
+          value_ = new global::Google.Protobuf.WellKnownTypes.Any();
+        }
+        Value.MergeFrom(other.Value);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            if (value_ == null) {
+              value_ = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(value_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs
new file mode 100644
index 0000000..d34b560
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs
@@ -0,0 +1,99 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public partial class Value
+    {
+        /// <summary>
+        /// Convenience method to create a Value message with a string value.
+        /// </summary>
+        /// <param name="value">Value to set for the StringValue property.</param>
+        /// <returns>A newly-created Value message with the given value.</returns>
+        public static Value ForString(string value)
+        {
+            ProtoPreconditions.CheckNotNull(value, "value");
+            return new Value { StringValue = value };
+        }
+
+        /// <summary>
+        /// Convenience method to create a Value message with a number value.
+        /// </summary>
+        /// <param name="value">Value to set for the NumberValue property.</param>
+        /// <returns>A newly-created Value message with the given value.</returns>
+        public static Value ForNumber(double value)
+        {
+            return new Value { NumberValue = value };
+        }
+
+        /// <summary>
+        /// Convenience method to create a Value message with a Boolean value.
+        /// </summary>
+        /// <param name="value">Value to set for the BoolValue property.</param>
+        /// <returns>A newly-created Value message with the given value.</returns>
+        public static Value ForBool(bool value)
+        {
+            return new Value { BoolValue = value };
+        }
+
+        /// <summary>
+        /// Convenience method to create a Value message with a null initial value.
+        /// </summary>
+        /// <returns>A newly-created Value message a null initial value.</returns>
+        public static Value ForNull()
+        {
+            return new Value { NullValue = 0 };
+        }
+
+        /// <summary>
+        /// Convenience method to create a Value message with an initial list of values.
+        /// </summary>
+        /// <remarks>The values provided are not cloned; the references are copied directly.</remarks>
+        /// <returns>A newly-created Value message an initial list value.</returns>
+        public static Value ForList(params Value[] values)
+        {
+            ProtoPreconditions.CheckNotNull(values, "values");
+            return new Value { ListValue = new ListValue { Values = { values } } };
+        }
+
+        /// <summary>
+        /// Convenience method to create a Value message with an initial struct value
+        /// </summary>
+        /// <remarks>The value provided is not cloned; the reference is copied directly.</remarks>
+        /// <returns>A newly-created Value message an initial struct value.</returns>
+        public static Value ForStruct(Struct value)
+        {
+            ProtoPreconditions.CheckNotNull(value, "value");
+            return new Value { StructValue = value };
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
new file mode 100644
index 0000000..c8867d0
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
@@ -0,0 +1,1057 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.WellKnownTypes {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/wrappers.proto</summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class WrappersReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/wrappers.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static WrappersReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ch5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8SD2dvb2dsZS5wcm90",
+            "b2J1ZiIcCgtEb3VibGVWYWx1ZRINCgV2YWx1ZRgBIAEoASIbCgpGbG9hdFZh",
+            "bHVlEg0KBXZhbHVlGAEgASgCIhsKCkludDY0VmFsdWUSDQoFdmFsdWUYASAB",
+            "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1",
+            "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo",
+            "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS",
+            "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJ/",
+            "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAFaKmdpdGh1",
+            "Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy93cmFwcGVyc6ABAfgBAaIC",
+            "A0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.DoubleValue), global::Google.Protobuf.WellKnownTypes.DoubleValue.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FloatValue), global::Google.Protobuf.WellKnownTypes.FloatValue.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int64Value), global::Google.Protobuf.WellKnownTypes.Int64Value.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt64Value), global::Google.Protobuf.WellKnownTypes.UInt64Value.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int32Value), global::Google.Protobuf.WellKnownTypes.Int32Value.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt32Value), global::Google.Protobuf.WellKnownTypes.UInt32Value.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BoolValue), global::Google.Protobuf.WellKnownTypes.BoolValue.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.StringValue), global::Google.Protobuf.WellKnownTypes.StringValue.Parser, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BytesValue), global::Google.Protobuf.WellKnownTypes.BytesValue.Parser, new[]{ "Value" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  ///  Wrapper message for `double`.
+  ///
+  ///  The JSON representation for `DoubleValue` is JSON number.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DoubleValue : pb::IMessage<DoubleValue> {
+    private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
+    public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DoubleValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DoubleValue(DoubleValue other) : this() {
+      value_ = other.value_;
+    }
+
+    public DoubleValue Clone() {
+      return new DoubleValue(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private double value_;
+    /// <summary>
+    ///  The double value.
+    /// </summary>
+    public double Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DoubleValue);
+    }
+
+    public bool Equals(DoubleValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0D) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(DoubleValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0D) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            Value = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `float`.
+  ///
+  ///  The JSON representation for `FloatValue` is JSON number.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FloatValue : pb::IMessage<FloatValue> {
+    private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
+    public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FloatValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FloatValue(FloatValue other) : this() {
+      value_ = other.value_;
+    }
+
+    public FloatValue Clone() {
+      return new FloatValue(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private float value_;
+    /// <summary>
+    ///  The float value.
+    /// </summary>
+    public float Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FloatValue);
+    }
+
+    public bool Equals(FloatValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0F) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0F) {
+        output.WriteRawTag(13);
+        output.WriteFloat(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0F) {
+        size += 1 + 4;
+      }
+      return size;
+    }
+
+    public void MergeFrom(FloatValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0F) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 13: {
+            Value = input.ReadFloat();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `int64`.
+  ///
+  ///  The JSON representation for `Int64Value` is JSON string.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int64Value : pb::IMessage<Int64Value> {
+    private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
+    public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int64Value() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int64Value(Int64Value other) : this() {
+      value_ = other.value_;
+    }
+
+    public Int64Value Clone() {
+      return new Int64Value(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private long value_;
+    /// <summary>
+    ///  The int64 value.
+    /// </summary>
+    public long Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int64Value);
+    }
+
+    public bool Equals(Int64Value other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0L) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int64Value other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0L) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Value = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `uint64`.
+  ///
+  ///  The JSON representation for `UInt64Value` is JSON string.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class UInt64Value : pb::IMessage<UInt64Value> {
+    private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
+    public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public UInt64Value() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public UInt64Value(UInt64Value other) : this() {
+      value_ = other.value_;
+    }
+
+    public UInt64Value Clone() {
+      return new UInt64Value(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private ulong value_;
+    /// <summary>
+    ///  The uint64 value.
+    /// </summary>
+    public ulong Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as UInt64Value);
+    }
+
+    public bool Equals(UInt64Value other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0UL) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0UL) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(UInt64Value other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0UL) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Value = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `int32`.
+  ///
+  ///  The JSON representation for `Int32Value` is JSON number.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int32Value : pb::IMessage<Int32Value> {
+    private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
+    public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int32Value() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int32Value(Int32Value other) : this() {
+      value_ = other.value_;
+    }
+
+    public Int32Value Clone() {
+      return new Int32Value(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private int value_;
+    /// <summary>
+    ///  The int32 value.
+    /// </summary>
+    public int Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int32Value);
+    }
+
+    public bool Equals(Int32Value other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int32Value other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Value = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `uint32`.
+  ///
+  ///  The JSON representation for `UInt32Value` is JSON number.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class UInt32Value : pb::IMessage<UInt32Value> {
+    private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
+    public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public UInt32Value() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public UInt32Value(UInt32Value other) : this() {
+      value_ = other.value_;
+    }
+
+    public UInt32Value Clone() {
+      return new UInt32Value(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private uint value_;
+    /// <summary>
+    ///  The uint32 value.
+    /// </summary>
+    public uint Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as UInt32Value);
+    }
+
+    public bool Equals(UInt32Value other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != 0) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != 0) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(UInt32Value other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != 0) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Value = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `bool`.
+  ///
+  ///  The JSON representation for `BoolValue` is JSON `true` and `false`.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BoolValue : pb::IMessage<BoolValue> {
+    private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
+    public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BoolValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BoolValue(BoolValue other) : this() {
+      value_ = other.value_;
+    }
+
+    public BoolValue Clone() {
+      return new BoolValue(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private bool value_;
+    /// <summary>
+    ///  The bool value.
+    /// </summary>
+    public bool Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BoolValue);
+    }
+
+    public bool Equals(BoolValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != false) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(BoolValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != false) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Value = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `string`.
+  ///
+  ///  The JSON representation for `StringValue` is JSON string.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class StringValue : pb::IMessage<StringValue> {
+    private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
+    public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public StringValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public StringValue(StringValue other) : this() {
+      value_ = other.value_;
+    }
+
+    public StringValue Clone() {
+      return new StringValue(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private string value_ = "";
+    /// <summary>
+    ///  The string value.
+    /// </summary>
+    public string Value {
+      get { return value_; }
+      set {
+        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as StringValue);
+    }
+
+    public bool Equals(StringValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value.Length != 0) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(StringValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value.Length != 0) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Value = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  /// <summary>
+  ///  Wrapper message for `bytes`.
+  ///
+  ///  The JSON representation for `BytesValue` is JSON string.
+  /// </summary>
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BytesValue : pb::IMessage<BytesValue> {
+    private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
+    public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[8]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BytesValue() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BytesValue(BytesValue other) : this() {
+      value_ = other.value_;
+    }
+
+    public BytesValue Clone() {
+      return new BytesValue(this);
+    }
+
+    /// <summary>Field number for the "value" field.</summary>
+    public const int ValueFieldNumber = 1;
+    private pb::ByteString value_ = pb::ByteString.Empty;
+    /// <summary>
+    ///  The bytes value.
+    /// </summary>
+    public pb::ByteString Value {
+      get { return value_; }
+      set {
+        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BytesValue);
+    }
+
+    public bool Equals(BytesValue other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value.Length != 0) hash ^= Value.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Value);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
+      }
+      return size;
+    }
+
+    public void MergeFrom(BytesValue other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value.Length != 0) {
+        Value = other.Value;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Value = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs
new file mode 100644
index 0000000..9f620eb
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs
@@ -0,0 +1,42 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public static partial class WrappersReflection
+    {
+        /// <summary>
+        /// Field number for the single "value" field in all wrapper types.
+        /// </summary>
+        internal const int WrapperValueFieldNumber = Int32Value.ValueFieldNumber;
+    }
+}
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WireFormat.cs b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WireFormat.cs
new file mode 100644
index 0000000..e884da5
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/WireFormat.cs
@@ -0,0 +1,104 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// This class is used internally by the Protocol Buffer Library and generated
+    /// message implementations. It is public only for the sake of those generated
+    /// messages. Others should not use this class directly.
+    /// <para>
+    /// This class contains constants and helper functions useful for dealing with
+    /// the Protocol Buffer wire format.
+    /// </para>
+    /// </summary>
+    public static class WireFormat
+    {
+        /// <summary>
+        /// Wire types within protobuf encoding.
+        /// </summary>
+        public enum WireType : uint
+        {
+            /// <summary>
+            /// Variable-length integer.
+            /// </summary>
+            Varint = 0,
+            /// <summary>
+            /// A fixed-length 64-bit value.
+            /// </summary>
+            Fixed64 = 1,
+            /// <summary>
+            /// A length-delimited value, i.e. a length followed by that many bytes of data.
+            /// </summary>
+            LengthDelimited = 2,
+            /// <summary>
+            /// A "start group" value - not supported by this implementation.
+            /// </summary>
+            StartGroup = 3,
+            /// <summary>
+            /// An "end group" value - not supported by this implementation.
+            /// </summary>
+            EndGroup = 4,
+            /// <summary>
+            /// A fixed-length 32-bit value.
+            /// </summary>
+            Fixed32 = 5
+        }
+        
+        private const int TagTypeBits = 3;
+        private const uint TagTypeMask = (1 << TagTypeBits) - 1;
+
+        /// <summary>
+        /// Given a tag value, determines the wire type (lower 3 bits).
+        /// </summary>
+        public static WireType GetTagWireType(uint tag)
+        {
+            return (WireType) (tag & TagTypeMask);
+        }
+
+        /// <summary>
+        /// Given a tag value, determines the field number (the upper 29 bits).
+        /// </summary>
+        public static int GetTagFieldNumber(uint tag)
+        {
+            return (int) tag >> TagTypeBits;
+        }
+
+        /// <summary>
+        /// Makes a tag value given a field number and wire type.
+        /// </summary>
+        public static uint MakeTag(int fieldNumber, WireType wireType)
+        {
+            return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
+        }        
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/Google.Protobuf/packages.config b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/packages.config
new file mode 100644
index 0000000..40b8fd9
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/Google.Protobuf/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NuSpec.ReferenceGenerator" version="1.4.1" targetFramework="portable45-net45+win8+wp8+wpa81" developmentDependency="true" />
+</packages>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/csharp/src/packages/repositories.config b/src/third_party/protobuf-3/csharp/src/packages/repositories.config
new file mode 100644
index 0000000..7037941
--- /dev/null
+++ b/src/third_party/protobuf-3/csharp/src/packages/repositories.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<repositories>
+  <repository path="..\Google.Protobuf.Test\packages.config" />
+</repositories>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/docs/swift/DesignDoc.md b/src/third_party/protobuf-3/docs/swift/DesignDoc.md
new file mode 100644
index 0000000..364a4d3
--- /dev/null
+++ b/src/third_party/protobuf-3/docs/swift/DesignDoc.md
@@ -0,0 +1,674 @@
+# Protocol Buffers in Swift
+
+## Objective
+
+This document describes the user-facing API and internal implementation of
+proto2 and proto3 messages in Apple’s Swift programming language.
+
+One of the key goals of protobufs is to provide idiomatic APIs for each
+language. In that vein, **interoperability with Objective-C is a non-goal of
+this proposal.** Protobuf users who need to pass messages between Objective-C
+and Swift code in the same application should use the existing Objective-C proto
+library. The goal of the effort described here is to provide an API for protobuf
+messages that uses features specific to Swift—optional types, algebraic
+enumerated types, value types, and so forth—in a natural way that will delight,
+rather than surprise, users of the language.
+
+## Naming
+
+*   By convention, both typical protobuf message names and Swift structs/classes
+    are `UpperCamelCase`, so for most messages, the name of a message can be the
+    same as the name of its generated type. (However, see the discussion below
+    about prefixes under [Packages](#packages).)
+
+*   Enum cases in protobufs typically are `UPPERCASE_WITH_UNDERSCORES`, whereas
+    in Swift they are `lowerCamelCase` (as of the Swift 3 API design
+    guidelines). We will transform the names to match Swift convention, using
+    a whitelist similar to the Objective-C compiler plugin to handle commonly
+    used acronyms.
+
+*   Typical fields in proto messages are `lowercase_with_underscores`, while in
+    Swift they are `lowerCamelCase`. We will transform the names to match
+    Swift convention by removing the underscores and uppercasing the subsequent
+    letter.
+
+## Swift reserved words
+
+Swift has a large set of reserved words—some always reserved and some
+contextually reserved (that is, they can be used as identifiers in contexts
+where they would not be confused). As of Swift 2.2, the set of always-reserved
+words is:
+
+```
+_, #available, #column, #else, #elseif, #endif, #file, #function, #if, #line,
+#selector, as, associatedtype, break, case, catch, class, continue, default,
+defer, deinit, do, dynamicType, else, enum, extension, fallthrough, false, for,
+func, guard, if, import, in, init, inout, internal, is, let, nil, operator,
+private, protocol, public, repeat, rethrows, return, self, Self, static,
+struct, subscript, super, switch, throw, throws, true, try, typealias, var,
+where, while
+```
+
+The set of contextually reserved words is:
+
+```
+associativity, convenience, dynamic, didSet, final, get, infix, indirect,
+lazy, left, mutating, none, nonmutating, optional, override, postfix,
+precedence, prefix, Protocol, required, right, set, Type, unowned, weak,
+willSet
+```
+
+It is possible to use any reserved word as an identifier by escaping it with
+backticks (for example, ``let `class` = 5``). Other name-mangling schemes would
+require us to transform the names themselves (for example, by appending an
+underscore), which requires us to then ensure that the new name does not collide
+with something else in the same namespace.
+
+While the backtick feature may not be widely known by all Swift developers, a
+small amount of user education can address this and it seems like the best
+approach. We can unconditionally surround all property names with backticks to
+simplify generation.
+
+Some remapping will still be required, though, to avoid collisions between
+generated properties and the names of methods and properties defined in the base
+protocol/implementation of messages.
+
+# Features of Protocol Buffers
+
+This section describes how the features of the protocol buffer syntaxes (proto2
+and proto3) map to features in Swift—what the code generated from a proto will
+look like, and how it will be implemented in the underlying library.
+
+## Packages
+
+Modules are the main form of namespacing in Swift, but they are not declared
+using syntactic constructs like namespaces in C++ or packages in Java. Instead,
+they are tied to build targets in Xcode (or, in the future with open-source
+Swift, declarations in a Swift Package Manager manifest). They also do not
+easily support nesting submodules (Clang module maps support this, but pure
+Swift does not yet provide a way to define submodules).
+
+We will generate types with fully-qualified underscore-delimited names. For
+example, a message `Baz` in package `foo.bar` would generate a struct named
+`Foo_Bar_Baz`. For each fully-qualified proto message, there will be exactly one
+unique type symbol emitted in the generated binary.
+
+Users are likely to balk at the ugliness of underscore-delimited names for every
+generated type. To improve upon this situation, we will add a new string file
+level option, `swift_package_typealias`, that can be added to `.proto` files.
+When present, this will cause `typealias`es to be added to the generated Swift
+messages that replace the package name prefix with the provided string. For
+example, the following `.proto` file:
+
+```protobuf
+option swift_package_typealias = "FBP";
+package foo.bar;
+
+message Baz {
+  // Message fields
+}
+```
+
+would generate the following Swift source:
+
+```swift
+public struct Foo_Bar_Baz {
+  // Message fields and other methods
+}
+
+typealias FBPBaz = Foo_Bar_Baz
+```
+
+It should be noted that this type alias is recorded in the generated
+`.swiftmodule` so that code importing the module can refer to it, but it does
+not cause a new symbol to be generated in the compiled binary (i.e., we do not
+risk compiled size bloat by adding `typealias`es for every type).
+
+Other strategies to handle packages that were considered and rejected can be
+found in [Appendix A](#appendix-a-rejected-strategies-to-handle-packages).
+
+## Messages
+
+Proto messages are natural value types and we will generate messages as structs
+instead of classes. Users will benefit from Swift’s built-in behavior with
+regard to mutability. We will define a `ProtoMessage` protocol that defines the
+common methods and properties for all messages (such as serialization) and also
+lets users treat messages polymorphically. Any shared method implementations
+that do not differ between individual messages can be implemented in a protocol
+extension.
+
+The backing storage itself for fields of a message will be managed by a
+`ProtoFieldStorage` type that uses an internal dictionary keyed by field number,
+and whose values are the value of the field with that number (up-cast to Swift’s
+`Any` type). This class will provide type-safe getters and setters so that
+generated messages can manipulate this storage, and core serialization logic
+will live here as well. Furthermore, factoring the storage out into a separate
+type, rather than inlining the fields as stored properties in the message
+itself, lets us implement copy-on-write efficiently to support passing around
+large messages. (Furthermore, because the messages themselves are value types,
+inlining fields is not possible if the fields are submessages of the same type,
+or a type that eventually includes a submessage of the same type.)
+
+### Required fields (proto2 only)
+
+Required fields in proto2 messages seem like they could be naturally represented
+by non-optional properties in Swift, but this presents some problems/concerns.
+
+Serialization APIs permit partial serialization, which allows required fields to
+remain unset. Furthermore, other language APIs still provide `has*` and `clear*`
+methods for required fields, and knowing whether a property has a value when the
+message is in memory is still useful.
+
+For example, an e-mail draft message may have the “to” address required on the
+wire, but when the user constructs it in memory, it doesn’t make sense to force
+a value until they provide one. We only want to force a value to be present when
+the message is serialized to the wire. Using non-optional properties prevents
+this use case, and makes client usage awkward because the user would be forced
+to select a sentinel or placeholder value for any required fields at the time
+the message was created.
+
+### Default values
+
+In proto2, fields can have a default value specified that may be a value other
+than the default value for its corresponding language type (for example, a
+default value of 5 instead of 0 for an integer). When reading a field that is
+not explicitly set, the user expects to get that value. This makes Swift
+optionals (i.e., `Foo?`) unsuitable for fields in general. Unfortunately, we
+cannot implement our own “enhanced optional” type without severely complicating
+usage (Swift’s use of type inference and its lack of implicit conversions would
+require manual unwrapping of every property value).
+
+Instead, we can use **implicitly unwrapped optionals.** For example, a property
+generated for a field of type `int32` would have Swift type `Int32!`. These
+properties would behave with the following characteristics, which mirror the
+nil-resettable properties used elsewhere in Apple’s SDKs (for example,
+`UIView.tintColor`):
+
+*   Assigning a non-nil value to a property sets the field to that value.
+*   Assigning nil to a property clears the field (its internal representation is
+    nilled out).
+*   Reading the value of a property returns its value if it is set, or returns
+    its default value if it is not set. Reading a property never returns nil.
+
+The final point in the list above implies that the optional cannot be checked to
+determine if the field is set to a value other than its default: it will never
+be nil. Instead, we must provide `has*` methods for each field to allow the user
+to check this. These methods will be public in proto2. In proto3, these methods
+will be private (if generated at all), since the user can test the returned
+value against the zero value for that type.
+
+### Autocreation of nested messages
+
+For convenience, dotting into an unset field representing a nested message will
+return an instance of that message with default values. As in the Objective-C
+implementation, this does not actually cause the field to be set until the
+returned message is mutated. Fortunately, thanks to the way mutability of value
+types is implemented in Swift, the language automatically handles the
+reassignment-on-mutation for us. A static singleton instance containing default
+values can be associated with each message that can be returned when reading, so
+copies are only made by the Swift runtime when mutation occurs. For example,
+given the following proto:
+
+```protobuf
+message Node {
+  Node child = 1;
+  string value = 2 [default = "foo"];
+}
+```
+
+The following Swift code would act as commented, where setting deeply nested
+properties causes the copies and mutations to occur as the assignment statement
+is unwound:
+
+```swift
+var node = Node()
+
+let s = node.child.child.value
+// 1. node.child returns the "default Node".
+// 2. Reading .child on the result of (1) returns the same default Node.
+// 3. Reading .value on the result of (2) returns the default value "foo".
+
+node.child.child.value = "bar"
+// 4. Setting .value on the default Node causes a copy to be made and sets
+//    the property on that copy. Subsequently, the language updates the
+//    value of "node.child.child" to point to that copy.
+// 5. Updating "node.child.child" in (4) requires another copy, because
+//    "node.child" was also the instance of the default node. The copy is
+//    assigned back to "node.child".
+// 6. Setting "node.child" in (5) is a simple value reassignment, since
+//    "node" is a mutable var.
+```
+
+In other words, the generated messages do not internally have to manage parental
+relationships to backfill the appropriate properties on mutation. Swift provides
+this for free.
+
+## Scalar value fields
+
+Proto scalar value fields will map to Swift types in the following way:
+
+.proto Type | Swift Type
+----------- | -------------------
+`double`    | `Double`
+`float`     | `Float`
+`int32`     | `Int32`
+`int64`     | `Int64`
+`uint32`    | `UInt32`
+`uint64`    | `UInt64`
+`sint32`    | `Int32`
+`sint64`    | `Int64`
+`fixed32`   | `UInt32`
+`fixed64`   | `UInt64`
+`sfixed32`  | `Int32`
+`sfixed64`  | `Int64`
+`bool`      | `Bool`
+`string`    | `String`
+`bytes`     | `Foundation.NSData`
+
+The proto spec defines a number of integral types that map to the same Swift
+type; for example, `intXX`, `sintXX`, and `sfixedXX` are all signed integers,
+and `uintXX` and `fixedXX` are both unsigned integers. No other language
+implementation distinguishes these further, so we do not do so either. The
+rationale is that the various types only serve to distinguish how the value is
+**encoded on the wire**; once loaded in memory, the user is not concerned about
+these variations.
+
+Swift’s lack of implicit conversions among types will make it slightly annoying
+to use these types in a context expecting an `Int`, or vice-versa, but since
+this is a data-interchange format with explicitly-sized fields, we should not
+hide that information from the user. Users will have to explicitly write
+`Int(message.myField)`, for example.
+
+## Embedded message fields
+
+Embedded message fields can be represented using an optional variable of the
+generated message type. Thus, the message
+
+```protobuf
+message Foo {
+  Bar bar = 1;
+}
+```
+
+would be represented in Swift as
+
+```swift
+public struct Foo: ProtoMessage {
+  public var bar: Bar! {
+    get { ... }
+    set { ... }
+  }
+}
+```
+
+If the user explicitly sets `bar` to nil, or if it was never set when read from
+the wire, retrieving the value of `bar` would return a default, statically
+allocated instance of `Bar` containing default values for its fields. This
+achieves the desired behavior for default values in the same way that scalar
+fields are designed, and also allows users to deep-drill into complex object
+graphs to get or set fields without checking for nil at each step.
+
+## Enum fields
+
+The design and implementation of enum fields will differ somewhat drastically
+depending on whether the message being generated is a proto2 or proto3 message.
+
+### proto2 enums
+
+For proto2, we do not need to be concerned about unknown enum values, so we can
+use the simple raw-value enum syntax provided by Swift. So the following enum in
+proto2:
+
+```protobuf
+enum ContentType {
+  TEXT = 0;
+  IMAGE = 1;
+}
+```
+
+would become this Swift enum:
+
+```swift
+public enum ContentType: Int32, NilLiteralConvertible {
+  case text = 0
+  case image = 1
+
+  public init(nilLiteral: ()) {
+    self = .text
+  }
+}
+```
+
+See below for the discussion about `NilLiteralConvertible`.
+
+### proto3 enums
+
+For proto3, we need to be able to preserve unknown enum values that may come
+across the wire so that they can be written back if unmodified. We can
+accomplish this in Swift by using a case with an associated value for unknowns.
+So the following enum in proto3:
+
+```protobuf
+enum ContentType {
+  TEXT = 0;
+  IMAGE = 1;
+}
+```
+
+would become this Swift enum:
+
+```swift
+public enum ContentType: RawRepresentable, NilLiteralConvertible {
+  case text
+  case image
+  case UNKNOWN_VALUE(Int32)
+
+  public typealias RawValue = Int32
+
+  public init(nilLiteral: ()) {
+    self = .text
+  }
+
+  public init(rawValue: RawValue) {
+    switch rawValue {
+      case 0: self = .text
+      case 1: self = .image
+      default: self = .UNKNOWN_VALUE(rawValue)
+  }
+
+  public var rawValue: RawValue {
+    switch self {
+      case .text: return 0
+      case .image: return 1
+      case .UNKNOWN_VALUE(let value): return value
+    }
+  }
+}
+```
+
+Note that the use of a parameterized case prevents us from inheriting from the
+raw `Int32` type; Swift does not allow an enum with a raw type to have cases
+with arguments. Instead, we must implement the raw value initializer and
+computed property manually. The `UNKNOWN_VALUE` case is explicitly chosen to be
+"ugly" so that it stands out and does not conflict with other possible case
+names.
+
+Using this approach, proto3 consumers must always have a default case or handle
+the `.UNKNOWN_VALUE` case to satisfy case exhaustion in a switch statement; the
+Swift compiler considers it an error if switch statements are not exhaustive.
+
+### NilLiteralConvertible conformance
+
+This is required to clean up the usage of enum-typed properties in switch
+statements. Unlike other field types, enum properties cannot be
+implicitly-unwrapped optionals without requiring that uses in switch statements
+be explicitly unwrapped. For example, if we consider a message with the enum
+above, this usage will fail to compile:
+
+```swift
+// Without NilLiteralConvertible conformance on ContentType
+public struct SomeMessage: ProtoMessage {
+  public var contentType: ContentType! { ... }
+}
+
+// ERROR: no case named text or image
+switch someMessage.contentType {
+  case .text: { ... }
+  case .image: { ... }
+}
+```
+
+Even though our implementation guarantees that `contentType` will never be nil,
+if it is an optional type, its cases would be `some` and `none`, not the cases
+of the underlying enum type. In order to use it in this context, the user must
+write `someMessage.contentType!` in their switch statement.
+
+Making the enum itself `NilLiteralConvertible` permits us to make the property
+non-optional, so the user can still set it to nil to clear it (i.e., reset it to
+its default value), while eliminating the need to explicitly unwrap it in a
+switch statement.
+
+```swift
+// With NilLiteralConvertible conformance on ContentType
+public struct SomeMessage: ProtoMessage {
+  // Note that the property type is no longer optional
+  public var contentType: ContentType { ... }
+}
+
+// OK: Compiles and runs as expected
+switch someMessage.contentType {
+  case .text: { ... }
+  case .image: { ... }
+}
+
+// The enum can be reset to its default value this way
+someMessage.contentType = nil
+```
+
+One minor oddity with this approach is that nil will be auto-converted to the
+default value of the enum in any context, not just field assignment. In other
+words, this is valid:
+
+```swift
+func foo(contentType: ContentType) { ... }
+foo(nil) // Inside foo, contentType == .text
+```
+
+That being said, the advantage of being able to simultaneously support
+nil-resettability and switch-without-unwrapping outweighs this side effect,
+especially if appropriately documented. It is our hope that a new form of
+resettable properties will be added to Swift that eliminates this inconsistency.
+Some community members have already drafted or sent proposals for review that
+would benefit our designs:
+
+*   [SE-0030: Property Behaviors]
+    (https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md)
+*   [Drafted: Resettable Properties]
+    (https://github.com/patters/swift-evolution/blob/master/proposals/0000-resettable-properties.md)
+
+### Enum aliases
+
+The `allow_alias` option in protobuf slightly complicates the use of Swift enums
+to represent that type, because raw values of cases in an enum must be unique.
+Swift lets us define static variables in an enum that alias actual cases. For
+example, the following protobuf enum:
+
+```protobuf
+enum Foo {
+  option allow_alias = true;
+  BAR = 0;
+  BAZ = 0;
+}
+```
+
+will be represented in Swift as:
+
+```swift
+public enum Foo: Int32, NilLiteralConvertible {
+  case bar = 0
+  static public let baz = bar
+
+  // ... etc.
+}
+
+// Can still use .baz shorthand to reference the alias in contexts
+// where the type is inferred
+```
+
+That is, we use the first name as the actual case and use static variables for
+the other aliases. One drawback to this approach is that the static aliases
+cannot be used as cases in a switch statement (the compiler emits the error
+*“Enum case ‘baz’ not found in type ‘Foo’”*). However, in our own code bases,
+there are only a few places where enum aliases are not mere renamings of an
+older value, but they also don’t appear to be the type of value that one would
+expect to switch on (for example, a group of named constants representing
+metrics rather than a set of options), so this restriction is not significant.
+
+This strategy also implies that changing the name of an enum and adding the old
+name as an alias below the new name will be a breaking change in the generated
+Swift code.
+
+## Oneof types
+
+The `oneof` feature represents a “variant/union” data type that maps nicely to
+Swift enums with associated values (algebraic types). These fields can also be
+accessed independently though, and, specifically in the case of proto2, it’s
+reasonable to expect access to default values when accessing a field that is not
+explicitly set.
+
+Taking all this into account, we can represent a `oneof` in Swift with two sets
+of constructs:
+
+*   Properties in the message that correspond to the `oneof` fields.
+*   A nested enum named after the `oneof` and which provides the corresponding
+    field values as case arguments.
+
+This approach fulfills the needs of proto consumers by providing a
+Swift-idiomatic way of simultaneously checking which field is set and accessing
+its value, providing individual properties to access the default values
+(important for proto2), and safely allows a field to be moved into a `oneof`
+without breaking clients.
+
+Consider the following proto:
+
+```protobuf
+message MyMessage {
+  oneof record {
+    string name = 1 [default = "unnamed"];
+    int32 id_number = 2 [default = 0];
+  }
+}
+```
+
+In Swift, we would generate an enum, a property for that enum, and properties
+for the fields themselves:
+
+```swift
+public struct MyMessage: ProtoMessage {
+  public enum Record: NilLiteralConvertible {
+    case name(String)
+    case idNumber(Int32)
+    case NOT_SET
+
+    public init(nilLiteral: ()) { self = .NOT_SET }
+  }
+
+  // This is the "Swifty" way of accessing the value
+  public var record: Record { ... }
+
+  // Direct access to the underlying fields
+  public var name: String! { ... }
+  public var idNumber: Int32! { ... }
+}
+```
+
+This makes both usage patterns possible:
+
+```swift
+// Usage 1: Case-based dispatch
+switch message.record {
+  case .name(let name):
+    // Do something with name if it was explicitly set
+  case .idNumber(let id):
+    // Do something with id_number if it was explicitly set
+  case .NOT_SET:
+    // Do something if it’s not set
+}
+
+// Usage 2: Direct access for default value fallback
+// Sets the label text to the name if it was explicitly set, or to
+// "unnamed" (the default value for the field) if id_number was set
+// instead
+let myLabel = UILabel()
+myLabel.text = message.name
+```
+
+As with proto enums, the generated `oneof` enum conforms to
+`NilLiteralConvertible` to avoid switch statement issues. Setting the property
+to nil will clear it (i.e., reset it to `NOT_SET`).
+
+## Unknown Fields (proto2 only)
+
+To be written.
+
+## Extensions (proto2 only)
+
+To be written.
+
+## Reflection and Descriptors
+
+We will not include reflection or descriptors in the first version of the Swift
+library. The use cases for reflection on mobile are not as strong and the static
+data to represent the descriptors would add bloat when we wish to keep the code
+size small.
+
+In the future, we will investigate whether they can be included as extensions
+which might be able to be excluded from a build and/or automatically dead
+stripped by the compiler if they are not used.
+
+## Appendix A: Rejected strategies to handle packages
+
+### Each package is its own Swift module
+
+Each proto package could be declared as its own Swift module, replacing dots
+with underscores (e.g., package `foo.bar` becomes module `Foo_Bar`). Then, users
+would simply import modules containing whatever proto modules they want to use
+and refer to the generated types by their short names.
+
+**This solution is simply not possible, however.** Swift modules cannot
+circularly reference each other, but there is no restriction against proto
+packages doing so. Circular imports are forbidden (e.g., `foo.proto` importing
+`bar.proto` importing `foo.proto`), but nothing prevents package `foo` from
+using a type in package `bar` which uses a different type in package `foo`, as
+long as there is no import cycle. If these packages were generated as Swift
+modules, then `Foo` would contain an `import Bar` statement and `Bar` would
+contain an `import Foo` statement, and there is no way to compile this.
+
+### Ad hoc namespacing with structs
+
+We can “fake” namespaces in Swift by declaring empty structs with private
+initializers. Since modules are constructed based on compiler arguments, not by
+syntactic constructs, and because there is no pure Swift way to define
+submodules (even though Clang module maps support this), there is no
+source-drive way to group generated code into namespaces aside from this
+approach.
+
+Types can be added to those intermediate package structs using Swift extensions.
+For example, a message `Baz` in package `foo.bar` could be represented in Swift
+as follows:
+
+```swift
+public struct Foo {
+  private init() {}
+}
+
+public extension Foo {
+  public struct Bar {
+    private init() {}
+  }
+}
+
+public extension Foo.Bar {
+  public struct Baz {
+    // Message fields and other methods
+  }
+}
+
+let baz = Foo.Bar.Baz()
+```
+
+Each of these constructs would actually be defined in a separate file; Swift
+lets us keep them separate and add multiple structs to a single “namespace”
+through extensions.
+
+Unfortunately, these intermediate structs generate symbols of their own
+(metatype information in the data segment). This becomes problematic if multiple
+build targets contain Swift sources generated from different messages in the
+same package. At link time, these symbols would collide, resulting in multiple
+definition errors.
+
+This approach also has the disadvantage that there is no automatic “short” way
+to refer to the generated messages at the deepest nesting levels; since this use
+of structs is a hack around the lack of namespaces, there is no equivalent to
+import (Java) or using (C++) to simplify this. Users would have to declare type
+aliases to make this cleaner, or we would have to generate them for users.
diff --git a/src/third_party/protobuf-3/docs/third_party.md b/src/third_party/protobuf-3/docs/third_party.md
new file mode 100644
index 0000000..69ed6a3
--- /dev/null
+++ b/src/third_party/protobuf-3/docs/third_party.md
@@ -0,0 +1,147 @@
+# Third-Party Add-ons for Protocol Buffers
+
+This page lists code related to Protocol Buffers which is developed and maintained by third parties.  You may find this code useful, but note that **these projects are not affiliated with or endorsed by Google (unless explicitly marked)**; try them at your own risk.  Also note that many projects here are in the early stages of development and not production-ready.
+
+If you have a project that should be listed here, please [send us a pull request](https://github.com/google/protobuf/pulls) to update this page.
+
+## Programming Languages
+
+These are projects we know about implementing Protocol Buffers for other programming languages:
+* Action Script: http://code.google.com/p/protobuf-actionscript3/
+* Action Script: https://code.google.com/p/protoc-gen-as3/
+* Action Script: https://github.com/matrix3d/JProtoc
+* C: https://github.com/protobuf-c/protobuf-c
+* C: http://koti.kapsi.fi/jpa/nanopb/
+* C: https://github.com/cloudwu/pbc/
+* C: https://github.com/haberman/upb/wiki
+* C: https://github.com/squidfunk/protobluff
+* C++: https://github.com/google/protobuf (Google-official implementation)
+* C/C++: http://spbc.sf.net/
+* C#: http://code.google.com/p/protobuf-csharp-port
+* C#: http://code.google.com/p/protosharp/
+* C#: https://silentorbit.com/protobuf/
+* C#/.NET/WCF/VB: http://code.google.com/p/protobuf-net/
+* Clojure: http://github.com/ninjudd/clojure-protobuf
+* Common Lisp: http://www.prism.gatech.edu/~ndantam3/docs/s-protobuf/
+* Common Lisp: http://github.com/brown/protobuf
+* D: https://github.com/msoucy/dproto
+* D: http://256.makerslocal.org/wiki/index.php/ProtocolBuffer
+* D: https://github.com/opticron/ProtocolBuffer
+* Dart: https://github.com/dart-lang/dart-protobuf (runtime) https://github.com/dart-lang/dart-protoc-plugin (code generator)
+* Delphi: http://sourceforge.net/projects/protobuf-delphi/
+* Delphi: http://fundementals.sourceforge.net/dl.html
+* Elixir: https://github.com/jeremyong/exprotoc
+* Erlang: http://github.com/ngerakines/erlang_protobuffs/tree/master
+* Erlang: http://piqi.org/
+* Erlang: https://code.google.com/p/protoc-gen-erl/
+* Erlang: https://github.com/basho/erlang_protobuffs
+* Go: https://github.com/golang/protobuf (Google-official implementation)
+* Go: http://code.google.com/p/goprotobuf/
+* Go: https://github.com/akunspy/gopbuf
+* Haskell: http://hackage.haskell.org/package/hprotoc
+* Haxe: https://github.com/Atry/protoc-gen-haxe
+* Java: https://github.com/google/protobuf (Google-official implementation)
+* Java/Android: https://github.com/square/wire
+* Java ME: http://code.google.com/p/protobuf-javame/
+* Java ME: http://swingme.sourceforge.net/encode.shtml
+* Java ME: http://github.com/ponderingpanda/protobuf-j2me
+* Java ME: http://code.google.com/p/protobuf-j2me/
+* Javascript: http://code.google.com/p/protobuf-js/
+* Javascript: http://github.com/sirikata/protojs
+* Javascript: https://github.com/dcodeIO/ProtoBuf.js
+* Javascript: http://code.google.com/p/protobuf-for-node/
+* Javascript: http://code.google.com/p/protostuff/
+* Julia: https://github.com/tanmaykm/ProtoBuf.jl
+* Lua: http://code.google.com/p/protoc-gen-lua/
+* Lua: http://github.com/indygreg/lua-protobuf
+* Lua: https://github.com/Neopallium/lua-pb
+* Matlab: http://code.google.com/p/protobuf-matlab/
+* Mercury: http://code.google.com/p/protobuf-mercury/
+* Objective C: http://code.google.com/p/protobuf-objc/
+* Objective C: https://github.com/alexeyxo/protobuf-objc
+* OCaml: http://piqi.org/
+* Perl: http://groups.google.com/group/protobuf-perl
+* Perl: http://search.cpan.org/perldoc?Google::ProtocolBuffers
+* Perl/XS: http://code.google.com/p/protobuf-perlxs/
+* PHP: http://code.google.com/p/pb4php/
+* PHP: https://github.com/allegro/php-protobuf/
+* PHP: https://github.com/chobie/php-protocolbuffers
+* PHP: http://drslump.github.com/Protobuf-PHP
+* Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html
+* Python: https://github.com/google/protobuf (Google-official implementation)
+* Python: http://eigenein.github.com/protobuf/
+* R: http://cran.r-project.org/package=RProtoBuf
+* Ruby: http://code.google.com/p/ruby-protobuf/
+* Ruby: http://github.com/mozy/ruby-protocol-buffers
+* Ruby: https://github.com/bmizerany/beefcake/tree/master/lib/beefcake
+* Ruby: https://github.com/localshred/protobuf
+* Rust: https://github.com/stepancheg/rust-protobuf/
+* Scala: http://github.com/jeffplaisance/scala-protobuf
+* Scala: http://code.google.com/p/protobuf-scala
+* Scala: https://github.com/SandroGrzicic/ScalaBuff
+* Scala: http://trueaccord.github.io/ScalaPB/
+* Swift: https://github.com/alexeyxo/protobuf-swift
+* Vala: https://launchpad.net/protobuf-vala
+* Visual Basic: http://code.google.com/p/protobuf-net/
+
+## RPC Implementations
+
+GRPC (http://www.grpc.io/) is Google's RPC implementation for Protocol Buffers. There are other third-party RPC implementations as well.  Some of these actually work with Protocol Buffers service definitions (defined using the `service` keyword in `.proto` files) while others just use Protocol Buffers message objects.
+
+* https://github.com/grpc/grpc (C++, Node.js, Python, Ruby, Objective-C, PHP, C#, Google-official implementation)
+* http://zeroc.com/ice.html (Multiple languages)
+* http://code.google.com/p/protobuf-net/ (C#/.NET/WCF/VB)
+* https://launchpad.net/txprotobuf/ (Python)
+* https://github.com/modeswitch/protobuf-rpc (Python)
+* http://code.google.com/p/protobuf-socket-rpc/ (Java, Python)
+* http://code.google.com/p/proto-streamer/ (Java)
+* http://code.google.com/p/server1/ (C++)
+* http://deltavsoft.com/RcfUserGuide/Protobufs (C++)
+* http://code.google.com/p/protobuf-mina-rpc/ (Python client, Java server)
+* http://code.google.com/p/casocklib/ (C++)
+* http://code.google.com/p/cxf-protobuf/ (Java)
+* http://code.google.com/p/protobuf-remote/ (C++/C#)
+* http://code.google.com/p/protobuf-rpc-pro/ (Java)
+* https://code.google.com/p/protorpc/ (Go/C++)
+* https://code.google.com/p/eneter-protobuf-serializer/ (Java/.NET)
+* http://www.deltavsoft.com/RCFProto.html (C++/Java/Python/C#)
+* https://github.com/robbinfan/claire-protorpc (C++)
+* https://github.com/BaiduPS/sofa-pbrpc (C++)
+* https://github.com/ebencheung/arab (C++)
+* http://code.google.com/p/protobuf-csharp-rpc/ (C#)
+* https://github.com/thesamet/rpcz (C++/Python, based on ZeroMQ)
+* https://github.com/w359405949/libmaid (C++, Python)
+* https://github.com/madwyn/libpbrpc (C++)
+
+## Other Utilities
+
+There are miscellaneous other things you may find useful as a Protocol Buffers developer.
+
+* [NetBeans IDE plugin](http://code.google.com/p/protobuf-netbeans-plugin/)
+* [Wireshark/Ethereal packet sniffer plugin](http://code.google.com/p/protobuf-wireshark/)
+* [Alternate encodings (JSON, XML, HTML) for Java protobufs](http://code.google.com/p/protobuf-java-format/)
+* [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec)
+* [Editor for serialized protobufs](http://code.google.com/p/protobufeditor/)
+* [Intellij IDEA plugin](http://github.com/nnmatveev/idea-plugin-protobuf)
+* [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle)
+* [Oracle PL SQL plugin](http://code.google.com/p/protocol-buffer-plsql/)
+* [Eclipse editor for protobuf (from Google)](http://code.google.com/p/protobuf-dt/)
+* [C++ Builder compatible protobuf](https://github.com/saadware/protobuf-cppbuilder)
+* Maven Protocol Compiler Plugin
+    * https://github.com/sergei-ivanov/maven-protoc-plugin/
+    * http://igor-petruk.github.com/protobuf-maven-plugin/
+    * http://code.google.com/p/maven-protoc-plugin/
+    * https://github.com/os72/protoc-jar-maven-plugin
+* [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/estan/protoc-gen-doc)
+* [DocBook generator for .proto files](http://code.google.com/p/protoc-gen-docbook/)
+* [Protobuf for nginx module](https://github.com/dbcode/protobuf-nginx/)
+* [RSpec matchers and Cucumber step defs for testing Protocol Buffers](https://github.com/connamara/protobuf_spec)
+* [Sbt plugin for Protocol Buffers](https://github.com/Atry/sbt-cppp)
+* [Gradle Protobuf Plugin](https://github.com/aantono/gradle-plugin-protobuf)
+* [Multi-platform executable JAR and Java API for protoc](https://github.com/os72/protoc-jar)
+* [Python scripts to convert between Protocol Buffers and JSON](https://github.com/NextTuesday/py-pb-converters)
+* [Visual Studio Language Service support for Protocol Buffers](http://visualstudiogallery.msdn.microsoft.com/4bc0f38c-b058-4e05-ae38-155e053c19c5)
+* [C++ library for serialization/de-serialization between Protocol Buffers and JSON.](https://github.com/yinqiwen/pbjson)
+* [ProtoBuf with Java EE7 Expression Language 3.0; pure Java ProtoBuf Parser and Builder.](https://github.com/protobufel/protobuf-el)
+* [Notepad++ Syntax Highlighting for .proto files](https://github.com/chai2010/notepadplus-protobuf)
+* [Linter for .proto files](https://github.com/ckaznocha/protoc-gen-lint)
diff --git a/src/third_party/protobuf-3/editors/README.txt b/src/third_party/protobuf-3/editors/README.txt
new file mode 100644
index 0000000..3e9fc79
--- /dev/null
+++ b/src/third_party/protobuf-3/editors/README.txt
@@ -0,0 +1,5 @@
+This directory contains syntax highlighting and configuration files for editors
+to properly display Protocol Buffer files.
+
+See each file's header comment for directions on how to use it with the
+appropriate editor.
diff --git a/src/third_party/protobuf-3/editors/proto.vim b/src/third_party/protobuf-3/editors/proto.vim
new file mode 100644
index 0000000..7f1aeb7
--- /dev/null
+++ b/src/third_party/protobuf-3/editors/proto.vim
@@ -0,0 +1,105 @@
+" 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.
+
+" This is the Vim syntax file for Google Protocol Buffers.
+"
+" Usage:
+"
+" 1. cp proto.vim ~/.vim/syntax/
+" 2. Add the following to ~/.vimrc:
+"
+" augroup filetype
+"   au! BufRead,BufNewFile *.proto setfiletype proto
+" augroup end
+"
+" Or just create a new file called ~/.vim/ftdetect/proto.vim with the
+" previous lines on it.
+
+if version < 600
+  syntax clear
+elseif exists("b:current_syntax")
+  finish
+endif
+
+syn case match
+
+syn keyword pbTodo       contained TODO FIXME XXX
+syn cluster pbCommentGrp contains=pbTodo
+
+syn keyword pbSyntax     syntax import option
+syn keyword pbStructure  package message group oneof
+syn keyword pbRepeat     optional required repeated
+syn keyword pbDefault    default
+syn keyword pbExtend     extend extensions to max reserved
+syn keyword pbRPC        service rpc returns
+
+syn keyword pbType      int32 int64 uint32 uint64 sint32 sint64
+syn keyword pbType      fixed32 fixed64 sfixed32 sfixed64
+syn keyword pbType      float double bool string bytes
+syn keyword pbTypedef   enum
+syn keyword pbBool      true false
+
+syn match   pbInt     /-\?\<\d\+\>/
+syn match   pbInt     /\<0[xX]\x+\>/
+syn match   pbFloat   /\<-\?\d*\(\.\d*\)\?/
+syn region  pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp
+syn region  pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp
+syn region  pbString  start=/"/ skip=/\\./ end=/"/
+syn region  pbString  start=/'/ skip=/\\./ end=/'/
+
+if version >= 508 || !exists("did_proto_syn_inits")
+  if version < 508
+    let did_proto_syn_inits = 1
+    command -nargs=+ HiLink hi link <args>
+  else
+    command -nargs=+ HiLink hi def link <args>
+  endif
+
+  HiLink pbTodo         Todo
+
+  HiLink pbSyntax       Include
+  HiLink pbStructure    Structure
+  HiLink pbRepeat       Repeat
+  HiLink pbDefault      Keyword
+  HiLink pbExtend       Keyword
+  HiLink pbRPC          Keyword
+  HiLink pbType         Type
+  HiLink pbTypedef      Typedef
+  HiLink pbBool         Boolean
+
+  HiLink pbInt          Number
+  HiLink pbFloat        Float
+  HiLink pbComment      Comment
+  HiLink pbString       String
+
+  delcommand HiLink
+endif
+
+let b:current_syntax = "proto"
diff --git a/src/third_party/protobuf-3/editors/protobuf-mode.el b/src/third_party/protobuf-3/editors/protobuf-mode.el
new file mode 100644
index 0000000..f615a0a
--- /dev/null
+++ b/src/third_party/protobuf-3/editors/protobuf-mode.el
@@ -0,0 +1,220 @@
+;;; protobuf-mode.el --- major mode for editing protocol buffers.
+
+;; Author: Alexandre Vassalotti <alexandre@peadrop.com>
+;; Created: 23-Apr-2009
+;; Version: 0.3
+;; Keywords: google protobuf languages
+
+;; 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.
+
+;;; Commentary:
+
+;; Installation:
+;;   - Put `protobuf-mode.el' in your Emacs load-path.
+;;   - Add this line to your .emacs file:
+;;       (require 'protobuf-mode)
+;;
+;; You can customize this mode just like any mode derived from CC Mode.  If
+;; you want to add customizations specific to protobuf-mode, you can use the
+;; `protobuf-mode-hook'. For example, the following would make protocol-mode
+;; use 2-space indentation:
+;;
+;;   (defconst my-protobuf-style
+;;     '((c-basic-offset . 2)
+;;       (indent-tabs-mode . nil)))
+;;
+;;   (add-hook 'protobuf-mode-hook
+;;     (lambda () (c-add-style "my-style" my-protobuf-style t)))
+;;
+;; Refer to the documentation of CC Mode for more information about
+;; customization details and how to use this mode.
+;;
+;; TODO:
+;;   - Make highlighting for enum values work properly.
+;;   - Fix the parser to recognize extensions as identifiers and not
+;;     as casts.
+;;   - Improve the parsing of option assignment lists. For example:
+;;       optional int32 foo = 1 [(my_field_option) = 4.5];
+;;   - Add support for fully-qualified identifiers (e.g., with a leading ".").
+
+;;; Code:
+
+(require 'cc-mode)
+
+(eval-when-compile
+  (require 'cc-langs)
+  (require 'cc-fonts))
+
+;; This mode does not inherit properties from other modes. So, we do not use 
+;; the usual `c-add-language' function.
+(eval-and-compile
+  (put 'protobuf-mode 'c-mode-prefix "protobuf-"))
+
+;; The following code uses of the `c-lang-defconst' macro define syntactic
+;; features of protocol buffer language.  Refer to the documentation in the
+;; cc-langs.el file for information about the meaning of the -kwds variables.
+
+(c-lang-defconst c-primitive-type-kwds
+  protobuf '("double" "float" "int32" "int64" "uint32" "uint64" "sint32"
+             "sint64" "fixed32" "fixed64" "sfixed32" "sfixed64" "bool"
+             "string" "bytes" "group"))
+
+(c-lang-defconst c-modifier-kwds
+  protobuf '("required" "optional" "repeated"))
+
+(c-lang-defconst c-class-decl-kwds
+  protobuf '("message" "enum" "service"))
+
+(c-lang-defconst c-constant-kwds
+  protobuf '("true" "false"))
+
+(c-lang-defconst c-other-decl-kwds
+  protobuf '("package" "import"))
+
+(c-lang-defconst c-other-kwds
+  protobuf '("default" "max"))
+
+(c-lang-defconst c-identifier-ops
+  ;; Handle extended identifiers like google.protobuf.MessageOptions
+  protobuf '((left-assoc ".")))
+
+;; The following keywords do not fit well in keyword classes defined by
+;; cc-mode.  So, we approximate as best we can.
+
+(c-lang-defconst c-type-list-kwds
+  protobuf '("extensions" "to" "reserved"))
+
+(c-lang-defconst c-typeless-decl-kwds
+  protobuf '("extend" "rpc" "option" "returns"))
+
+
+;; Here we remove default syntax for loops, if-statements and other C
+;; syntactic features that are not supported by the protocol buffer language.
+
+(c-lang-defconst c-brace-list-decl-kwds
+  ;; Remove syntax for C-style enumerations.
+  protobuf nil)
+
+(c-lang-defconst c-block-stmt-1-kwds
+  ;; Remove syntax for "do" and "else" keywords.
+  protobuf nil)
+
+(c-lang-defconst c-block-stmt-2-kwds
+  ;; Remove syntax for "for", "if", "switch" and "while" keywords.
+  protobuf nil)
+
+(c-lang-defconst c-simple-stmt-kwds
+  ;; Remove syntax for "break", "continue", "goto" and "return" keywords.
+  protobuf nil)
+
+(c-lang-defconst c-paren-stmt-kwds
+  ;; Remove special case for the "(;;)" in for-loops.
+  protobuf nil)
+
+(c-lang-defconst c-label-kwds
+  ;; Remove case label syntax for the "case" and "default" keywords.
+  protobuf nil)
+
+(c-lang-defconst c-before-label-kwds
+  ;; Remove special case for the label in a goto statement.
+  protobuf nil)
+
+(c-lang-defconst c-cpp-matchers
+  ;; Disable all the C preprocessor syntax.
+  protobuf nil)
+
+(c-lang-defconst c-decl-prefix-re
+  ;; Same as for C, except it does not match "(". This is needed for disabling
+  ;; the syntax for casts.
+  protobuf "\\([\{\};,]+\\)")
+
+
+;; Add support for variable levels of syntax highlighting.
+
+(defconst protobuf-font-lock-keywords-1 (c-lang-const c-matchers-1 protobuf)
+  "Minimal highlighting for protobuf-mode.")
+
+(defconst protobuf-font-lock-keywords-2 (c-lang-const c-matchers-2 protobuf)
+  "Fast normal highlighting for protobuf-mode.")
+
+(defconst protobuf-font-lock-keywords-3 (c-lang-const c-matchers-3 protobuf)
+  "Accurate normal highlighting for protobuf-mode.")
+
+(defvar protobuf-font-lock-keywords protobuf-font-lock-keywords-3
+  "Default expressions to highlight in protobuf-mode.")
+
+;; Our syntax table is auto-generated from the keyword classes we defined
+;; previously with the `c-lang-const' macro.
+(defvar protobuf-mode-syntax-table nil
+  "Syntax table used in protobuf-mode buffers.")
+(or protobuf-mode-syntax-table
+    (setq protobuf-mode-syntax-table
+          (funcall (c-lang-const c-make-mode-syntax-table protobuf))))
+
+(defvar protobuf-mode-abbrev-table nil
+  "Abbreviation table used in protobuf-mode buffers.")
+
+(defvar protobuf-mode-map nil
+  "Keymap used in protobuf-mode buffers.")
+(or protobuf-mode-map
+    (setq protobuf-mode-map (c-make-inherited-keymap)))
+
+(easy-menu-define protobuf-menu protobuf-mode-map
+  "Protocol Buffers Mode Commands"
+  (cons "Protocol Buffers" (c-lang-const c-mode-menu protobuf)))
+
+;;;###autoload (add-to-list 'auto-mode-alist '("\\.proto\\'" . protobuf-mode))
+
+;;;###autoload
+(defun protobuf-mode ()
+  "Major mode for editing Protocol Buffers description language.
+
+The hook `c-mode-common-hook' is run with no argument at mode
+initialization, then `protobuf-mode-hook'.
+
+Key bindings:
+\\{protobuf-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (set-syntax-table protobuf-mode-syntax-table)
+  (setq major-mode 'protobuf-mode
+        mode-name "Protocol-Buffers"
+        local-abbrev-table protobuf-mode-abbrev-table
+        abbrev-mode t)
+  (use-local-map protobuf-mode-map)
+  (c-initialize-cc-mode t)
+  (if (fboundp 'c-make-emacs-variables-local)
+      (c-make-emacs-variables-local))
+  (c-init-language-vars protobuf-mode)
+  (c-common-init 'protobuf-mode)
+  (easy-menu-add protobuf-menu)
+  (c-run-mode-hooks 'c-mode-common-hook 'protobuf-mode-hook)
+  (c-update-modeline))
+
+(provide 'protobuf-mode)
+
+;;; protobuf-mode.el ends here
diff --git a/src/third_party/protobuf-3/examples/AddPerson.java b/src/third_party/protobuf-3/examples/AddPerson.java
new file mode 100644
index 0000000..c262ab7
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/AddPerson.java
@@ -0,0 +1,95 @@
+// See README.txt for information and build instructions.
+
+import com.example.tutorial.AddressBookProtos.AddressBook;
+import com.example.tutorial.AddressBookProtos.Person;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+class AddPerson {
+  // This function fills in a Person message based on user input.
+  static Person PromptForAddress(BufferedReader stdin,
+                                 PrintStream stdout) throws IOException {
+    Person.Builder person = Person.newBuilder();
+
+    stdout.print("Enter person ID: ");
+    person.setId(Integer.valueOf(stdin.readLine()));
+
+    stdout.print("Enter name: ");
+    person.setName(stdin.readLine());
+
+    stdout.print("Enter email address (blank for none): ");
+    String email = stdin.readLine();
+    if (email.length() > 0) {
+      person.setEmail(email);
+    }
+
+    while (true) {
+      stdout.print("Enter a phone number (or leave blank to finish): ");
+      String number = stdin.readLine();
+      if (number.length() == 0) {
+        break;
+      }
+
+      Person.PhoneNumber.Builder phoneNumber =
+        Person.PhoneNumber.newBuilder().setNumber(number);
+
+      stdout.print("Is this a mobile, home, or work phone? ");
+      String type = stdin.readLine();
+      if (type.equals("mobile")) {
+        phoneNumber.setType(Person.PhoneType.MOBILE);
+      } else if (type.equals("home")) {
+        phoneNumber.setType(Person.PhoneType.HOME);
+      } else if (type.equals("work")) {
+        phoneNumber.setType(Person.PhoneType.WORK);
+      } else {
+        stdout.println("Unknown phone type.  Using default.");
+      }
+
+      person.addPhones(phoneNumber);
+    }
+
+    return person.build();
+  }
+
+  // Main function:  Reads the entire address book from a file,
+  //   adds one person based on user input, then writes it back out to the same
+  //   file.
+  public static void main(String[] args) throws Exception {
+    if (args.length != 1) {
+      System.err.println("Usage:  AddPerson ADDRESS_BOOK_FILE");
+      System.exit(-1);
+    }
+
+    AddressBook.Builder addressBook = AddressBook.newBuilder();
+
+    // Read the existing address book.
+    try {
+      FileInputStream input = new FileInputStream(args[0]);
+      try {
+        addressBook.mergeFrom(input);
+      } finally {
+        try { input.close(); } catch (Throwable ignore) {}
+      }
+    } catch (FileNotFoundException e) {
+      System.out.println(args[0] + ": File not found.  Creating a new file.");
+    }
+
+    // Add an address.
+    addressBook.addPeople(
+      PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
+                       System.out));
+
+    // Write the new address book back to disk.
+    FileOutputStream output = new FileOutputStream(args[0]);
+    try {
+      addressBook.build().writeTo(output);
+    } finally {
+      output.close();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/examples/ListPeople.java b/src/third_party/protobuf-3/examples/ListPeople.java
new file mode 100644
index 0000000..7892430
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/ListPeople.java
@@ -0,0 +1,50 @@
+// See README.txt for information and build instructions.
+
+import com.example.tutorial.AddressBookProtos.AddressBook;
+import com.example.tutorial.AddressBookProtos.Person;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+class ListPeople {
+  // Iterates though all people in the AddressBook and prints info about them.
+  static void Print(AddressBook addressBook) {
+    for (Person person: addressBook.getPeopleList()) {
+      System.out.println("Person ID: " + person.getId());
+      System.out.println("  Name: " + person.getName());
+      if (!person.getEmail().isEmpty()) {
+        System.out.println("  E-mail address: " + person.getEmail());
+      }
+
+      for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
+        switch (phoneNumber.getType()) {
+          case MOBILE:
+            System.out.print("  Mobile phone #: ");
+            break;
+          case HOME:
+            System.out.print("  Home phone #: ");
+            break;
+          case WORK:
+            System.out.print("  Work phone #: ");
+            break;
+        }
+        System.out.println(phoneNumber.getNumber());
+      }
+    }
+  }
+
+  // Main function:  Reads the entire address book from a file and prints all
+  //   the information inside.
+  public static void main(String[] args) throws Exception {
+    if (args.length != 1) {
+      System.err.println("Usage:  ListPeople ADDRESS_BOOK_FILE");
+      System.exit(-1);
+    }
+
+    // Read the existing address book.
+    AddressBook addressBook =
+      AddressBook.parseFrom(new FileInputStream(args[0]));
+
+    Print(addressBook);
+  }
+}
diff --git a/src/third_party/protobuf-3/examples/README.txt b/src/third_party/protobuf-3/examples/README.txt
new file mode 100644
index 0000000..b33f8414
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/README.txt
@@ -0,0 +1,54 @@
+This directory contains example code that uses Protocol Buffers to manage an
+address book.  Two programs are provided, each with three different
+implementations, one written in each of C++, Java, and Python.  The add_person
+example adds a new person to an address book, prompting the user to input
+the person's information.  The list_people example lists people already in the
+address book.  The examples use the exact same format in all three languages,
+so you can, for example, use add_person_java to create an address book and then
+use list_people_python to read it.
+
+You must install the protobuf package before you can build these.
+
+To build all the examples (on a unix-like system), simply run "make".  This
+creates the following executable files in the current directory:
+  add_person_cpp     list_people_cpp
+  add_person_java    list_people_java
+  add_person_python  list_people_python
+
+If you only want to compile examples in one language, use "make cpp"*,
+"make java", or "make python".
+
+All of these programs simply take an address book file as their parameter.
+The add_person programs will create the file if it doesn't already exist.
+
+These examples are part of the Protocol Buffers tutorial, located at:
+  https://developers.google.com/protocol-buffers/docs/tutorials
+
+* Note that on some platforms you may have to edit the Makefile and remove
+"-lpthread" from the linker commands (perhaps replacing it with something else).
+We didn't do this automatically because we wanted to keep the example simple.
+
+## Go ##
+
+The Go example requires a plugin to the protocol buffer compiler, so it is not
+build with all the other examples.  See:
+  https://github.com/golang/protobuf
+for more information about Go protocol buffer support.
+
+First, install the Protocol Buffers compiler (protoc).
+Then, install the Go Protocol Buffers plugin
+($GOPATH/bin must be in your $PATH for protoc to find it):
+  go get github.com/golang/protobuf/protoc-gen-go
+
+Build the Go samples in this directory with "make go".  This creates the
+following executable files in the current directory:
+  add_person_go      list_people_go
+To run the example:
+  ./add_person_go addressbook.data
+to add a person to the protocol buffer encoded file addressbook.data.  The file
+is created if it does not exist.  To view the data, run:
+  ./list_people_go addressbook.data
+
+Observe that the C++, Python, and Java examples in this directory run in a
+similar way and can view/modify files created by the Go example and vice
+versa.
diff --git a/src/third_party/protobuf-3/examples/add_person.cc b/src/third_party/protobuf-3/examples/add_person.cc
new file mode 100644
index 0000000..9bec4b3
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/add_person.cc
@@ -0,0 +1,95 @@
+// See README.txt for information and build instructions.
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include "addressbook.pb.h"
+using namespace std;
+
+// This function fills in a Person message based on user input.
+void PromptForAddress(tutorial::Person* person) {
+  cout << "Enter person ID number: ";
+  int id;
+  cin >> id;
+  person->set_id(id);
+  cin.ignore(256, '\n');
+
+  cout << "Enter name: ";
+  getline(cin, *person->mutable_name());
+
+  cout << "Enter email address (blank for none): ";
+  string email;
+  getline(cin, email);
+  if (!email.empty()) {
+    person->set_email(email);
+  }
+
+  while (true) {
+    cout << "Enter a phone number (or leave blank to finish): ";
+    string number;
+    getline(cin, number);
+    if (number.empty()) {
+      break;
+    }
+
+    tutorial::Person::PhoneNumber* phone_number = person->add_phones();
+    phone_number->set_number(number);
+
+    cout << "Is this a mobile, home, or work phone? ";
+    string type;
+    getline(cin, type);
+    if (type == "mobile") {
+      phone_number->set_type(tutorial::Person::MOBILE);
+    } else if (type == "home") {
+      phone_number->set_type(tutorial::Person::HOME);
+    } else if (type == "work") {
+      phone_number->set_type(tutorial::Person::WORK);
+    } else {
+      cout << "Unknown phone type.  Using default." << endl;
+    }
+  }
+}
+
+// Main function:  Reads the entire address book from a file,
+//   adds one person based on user input, then writes it back out to the same
+//   file.
+int main(int argc, char* argv[]) {
+  // Verify that the version of the library that we linked against is
+  // compatible with the version of the headers we compiled against.
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  if (argc != 2) {
+    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
+    return -1;
+  }
+
+  tutorial::AddressBook address_book;
+
+  {
+    // Read the existing address book.
+    fstream input(argv[1], ios::in | ios::binary);
+    if (!input) {
+      cout << argv[1] << ": File not found.  Creating a new file." << endl;
+    } else if (!address_book.ParseFromIstream(&input)) {
+      cerr << "Failed to parse address book." << endl;
+      return -1;
+    }
+  }
+
+  // Add an address.
+  PromptForAddress(address_book.add_people());
+
+  {
+    // Write the new address book back to disk.
+    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
+    if (!address_book.SerializeToOstream(&output)) {
+      cerr << "Failed to write address book." << endl;
+      return -1;
+    }
+  }
+
+  // Optional:  Delete all global objects allocated by libprotobuf.
+  google::protobuf::ShutdownProtobufLibrary();
+
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/examples/add_person.go b/src/third_party/protobuf-3/examples/add_person.go
new file mode 100644
index 0000000..4f2e7f7
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/add_person.go
@@ -0,0 +1,133 @@
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"strings"
+
+	"github.com/golang/protobuf/proto"
+	pb "github.com/google/protobuf/examples/tutorial"
+)
+
+func promptForAddress(r io.Reader) (*pb.Person, error) {
+	// A protocol buffer can be created like any struct.
+	p := &pb.Person{}
+
+	rd := bufio.NewReader(r)
+	fmt.Print("Enter person ID number: ")
+	// An int32 field in the .proto file is represented as an int32 field
+	// in the generated Go struct.
+	if _, err := fmt.Fscanf(rd, "%d\n", &p.Id); err != nil {
+		return p, err
+	}
+
+	fmt.Print("Enter name: ")
+	name, err := rd.ReadString('\n')
+	if err != nil {
+		return p, err
+	}
+	// A string field in the .proto file results in a string field in Go.
+	// We trim the whitespace because rd.ReadString includes the trailing
+	// newline character in its output.
+	p.Name = strings.TrimSpace(name)
+
+	fmt.Print("Enter email address (blank for none): ")
+	email, err := rd.ReadString('\n')
+	if err != nil {
+		return p, err
+	}
+	p.Email = strings.TrimSpace(email)
+
+	for {
+		fmt.Print("Enter a phone number (or leave blank to finish): ")
+		phone, err := rd.ReadString('\n')
+		if err != nil {
+			return p, err
+		}
+		phone = strings.TrimSpace(phone)
+		if phone == "" {
+			break
+		}
+		// The PhoneNumber message type is nested within the Person
+		// message in the .proto file.  This results in a Go struct
+		// named using the name of the parent prefixed to the name of
+		// the nested message.  Just as with pb.Person, it can be
+		// created like any other struct.
+		pn := &pb.Person_PhoneNumber{
+			Number: phone,
+		}
+
+		fmt.Print("Is this a mobile, home, or work phone? ")
+		ptype, err := rd.ReadString('\n')
+		if err != nil {
+			return p, err
+		}
+		ptype = strings.TrimSpace(ptype)
+
+		// A proto enum results in a Go constant for each enum value.
+		switch ptype {
+		case "mobile":
+			pn.Type = pb.Person_MOBILE
+		case "home":
+			pn.Type = pb.Person_HOME
+		case "work":
+			pn.Type = pb.Person_WORK
+		default:
+			fmt.Printf("Unknown phone type %q.  Using default.\n", ptype)
+		}
+
+		// A repeated proto field maps to a slice field in Go.  We can
+		// append to it like any other slice.
+		p.Phones = append(p.Phones, pn)
+	}
+
+	return p, nil
+}
+
+// Main reads the entire address book from a file, adds one person based on
+// user input, then writes it back out to the same file.
+func main() {
+	if len(os.Args) != 2 {
+		log.Fatalf("Usage:  %s ADDRESS_BOOK_FILE\n", os.Args[0])
+	}
+	fname := os.Args[1]
+
+	// Read the existing address book.
+	in, err := ioutil.ReadFile(fname)
+	if err != nil {
+		if os.IsNotExist(err) {
+			fmt.Printf("%s: File not found.  Creating new file.\n", fname)
+		} else {
+			log.Fatalln("Error reading file:", err)
+		}
+	}
+
+	// [START marshal_proto]
+	book := &pb.AddressBook{}
+	// [START_EXCLUDE]
+	if err := proto.Unmarshal(in, book); err != nil {
+		log.Fatalln("Failed to parse address book:", err)
+	}
+
+	// Add an address.
+	addr, err := promptForAddress(os.Stdin)
+	if err != nil {
+		log.Fatalln("Error with address:", err)
+	}
+	book.People = append(book.People, addr)
+	// [END_EXCLUDE]
+
+	// Write the new address book back to disk.
+	out, err := proto.Marshal(book)
+	if err != nil {
+		log.Fatalln("Failed to encode address book:", err)
+	}
+	if err := ioutil.WriteFile(fname, out, 0644); err != nil {
+		log.Fatalln("Failed to write address book:", err)
+	}
+	// [END marshal_proto]
+}
diff --git a/src/third_party/protobuf-3/examples/add_person.py b/src/third_party/protobuf-3/examples/add_person.py
new file mode 100755
index 0000000..0b69857
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/add_person.py
@@ -0,0 +1,56 @@
+#! /usr/bin/env python
+
+# See README.txt for information and build instructions.
+
+import addressbook_pb2
+import sys
+
+# This function fills in a Person message based on user input.
+def PromptForAddress(person):
+  person.id = int(raw_input("Enter person ID number: "))
+  person.name = raw_input("Enter name: ")
+
+  email = raw_input("Enter email address (blank for none): ")
+  if email != "":
+    person.email = email
+
+  while True:
+    number = raw_input("Enter a phone number (or leave blank to finish): ")
+    if number == "":
+      break
+
+    phone_number = person.phones.add()
+    phone_number.number = number
+
+    type = raw_input("Is this a mobile, home, or work phone? ")
+    if type == "mobile":
+      phone_number.type = addressbook_pb2.Person.MOBILE
+    elif type == "home":
+      phone_number.type = addressbook_pb2.Person.HOME
+    elif type == "work":
+      phone_number.type = addressbook_pb2.Person.WORK
+    else:
+      print "Unknown phone type; leaving as default value."
+
+# Main procedure:  Reads the entire address book from a file,
+#   adds one person based on user input, then writes it back out to the same
+#   file.
+if len(sys.argv) != 2:
+  print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
+  sys.exit(-1)
+
+address_book = addressbook_pb2.AddressBook()
+
+# Read the existing address book.
+try:
+  with open(sys.argv[1], "rb") as f:
+    address_book.ParseFromString(f.read())
+except IOError:
+  print sys.argv[1] + ": File not found.  Creating a new file."
+
+# Add an address.
+PromptForAddress(address_book.people.add())
+
+# Write the new address book back to disk.
+with open(sys.argv[1], "wb") as f:
+  f.write(address_book.SerializeToString())
diff --git a/src/third_party/protobuf-3/examples/add_person_test.go b/src/third_party/protobuf-3/examples/add_person_test.go
new file mode 100644
index 0000000..0507db6
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/add_person_test.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/golang/protobuf/proto"
+	pb "github.com/google/protobuf/examples/tutorial"
+)
+
+func TestPromptForAddressReturnsAddress(t *testing.T) {
+	in := `12345
+Example Name
+name@example.com
+123-456-7890
+home
+222-222-2222
+mobile
+111-111-1111
+work
+777-777-7777
+unknown
+
+`
+	got, err := promptForAddress(strings.NewReader(in))
+	if err != nil {
+		t.Fatalf("promptForAddress(%q) had unexpected error: %s", in, err.Error())
+	}
+	if got.Id != 12345 {
+		t.Errorf("promptForAddress(%q) got %d, want ID %d", in, got.Id, 12345)
+	}
+	if got.Name != "Example Name" {
+		t.Errorf("promptForAddress(%q) => want name %q, got %q", "Example Name", got.Name)
+	}
+	if got.Email != "name@example.com" {
+		t.Errorf("promptForAddress(%q) => want email %q, got %q", "name@example.com", got.Email)
+	}
+
+	want := []*pb.Person_PhoneNumber{
+		{Number: "123-456-7890", Type: pb.Person_HOME},
+		{Number: "222-222-2222", Type: pb.Person_MOBILE},
+		{Number: "111-111-1111", Type: pb.Person_WORK},
+		{Number: "777-777-7777", Type: pb.Person_MOBILE},
+	}
+	if len(got.Phones) != len(want) {
+		t.Errorf("want %d phone numbers, got %d", len(want), len(got.Phones))
+	}
+	phones := len(got.Phones)
+	if phones > len(want) {
+		phones = len(want)
+	}
+	for i := 0; i < phones; i++ {
+		if !proto.Equal(got.Phones[i], want[i]) {
+			t.Errorf("want phone %q, got %q", *want[i], *got.Phones[i])
+		}
+
+	}
+}
diff --git a/src/third_party/protobuf-3/examples/addressbook.proto b/src/third_party/protobuf-3/examples/addressbook.proto
new file mode 100644
index 0000000..23cc2f9
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/addressbook.proto
@@ -0,0 +1,47 @@
+// See README.txt for information and build instructions.
+//
+// Note: START and END tags are used in comments to define sections used in
+// tutorials.  They are not part of the syntax for Protocol Buffers.
+//
+// To get an in-depth walkthrough of this file and the related examples, see:
+// https://developers.google.com/protocol-buffers/docs/tutorials
+
+// [START declaration]
+syntax = "proto3";
+package tutorial;
+// [END declaration]
+
+// [START java_declaration]
+option java_package = "com.example.tutorial";
+option java_outer_classname = "AddressBookProtos";
+// [END java_declaration]
+
+// [START csharp_declaration]
+option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
+// [END csharp_declaration]
+
+// [START messages]
+message Person {
+  string name = 1;
+  int32 id = 2;  // Unique ID number for this person.
+  string email = 3;
+
+  enum PhoneType {
+    MOBILE = 0;
+    HOME = 1;
+    WORK = 2;
+  }
+
+  message PhoneNumber {
+    string number = 1;
+    PhoneType type = 2;
+  }
+
+  repeated PhoneNumber phones = 4;
+}
+
+// Our address book file is just one of these.
+message AddressBook {
+  repeated Person people = 1;
+}
+// [END messages]
diff --git a/src/third_party/protobuf-3/examples/list_people.cc b/src/third_party/protobuf-3/examples/list_people.cc
new file mode 100644
index 0000000..68e5666
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/list_people.cc
@@ -0,0 +1,68 @@
+// See README.txt for information and build instructions.
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include "addressbook.pb.h"
+using namespace std;
+
+// Iterates though all people in the AddressBook and prints info about them.
+void ListPeople(const tutorial::AddressBook& address_book) {
+  for (int i = 0; i < address_book.people_size(); i++) {
+    const tutorial::Person& person = address_book.people(i);
+
+    cout << "Person ID: " << person.id() << endl;
+    cout << "  Name: " << person.name() << endl;
+    if (person.email() != "") {
+      cout << "  E-mail address: " << person.email() << endl;
+    }
+
+    for (int j = 0; j < person.phones_size(); j++) {
+      const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
+
+      switch (phone_number.type()) {
+        case tutorial::Person::MOBILE:
+          cout << "  Mobile phone #: ";
+          break;
+        case tutorial::Person::HOME:
+          cout << "  Home phone #: ";
+          break;
+        case tutorial::Person::WORK:
+          cout << "  Work phone #: ";
+          break;
+      }
+      cout << phone_number.number() << endl;
+    }
+  }
+}
+
+// Main function:  Reads the entire address book from a file and prints all
+//   the information inside.
+int main(int argc, char* argv[]) {
+  // Verify that the version of the library that we linked against is
+  // compatible with the version of the headers we compiled against.
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  if (argc != 2) {
+    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
+    return -1;
+  }
+
+  tutorial::AddressBook address_book;
+
+  {
+    // Read the existing address book.
+    fstream input(argv[1], ios::in | ios::binary);
+    if (!address_book.ParseFromIstream(&input)) {
+      cerr << "Failed to parse address book." << endl;
+      return -1;
+    }
+  }
+
+  ListPeople(address_book);
+
+  // Optional:  Delete all global objects allocated by libprotobuf.
+  google::protobuf::ShutdownProtobufLibrary();
+
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/examples/list_people.go b/src/third_party/protobuf-3/examples/list_people.go
new file mode 100644
index 0000000..70bc589
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/list_people.go
@@ -0,0 +1,61 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+
+	"github.com/golang/protobuf/proto"
+	pb "github.com/google/protobuf/examples/tutorial"
+)
+
+func writePerson(w io.Writer, p *pb.Person) {
+	fmt.Fprintln(w, "Person ID:", p.Id)
+	fmt.Fprintln(w, "  Name:", p.Name)
+	if p.Email != "" {
+		fmt.Fprintln(w, "  E-mail address:", p.Email)
+	}
+
+	for _, pn := range p.Phones {
+		switch pn.Type {
+		case pb.Person_MOBILE:
+			fmt.Fprint(w, "  Mobile phone #: ")
+		case pb.Person_HOME:
+			fmt.Fprint(w, "  Home phone #: ")
+		case pb.Person_WORK:
+			fmt.Fprint(w, "  Work phone #: ")
+		}
+		fmt.Fprintln(w, pn.Number)
+	}
+}
+
+func listPeople(w io.Writer, book *pb.AddressBook) {
+	for _, p := range book.People {
+		writePerson(w, p)
+	}
+}
+
+// Main reads the entire address book from a file and prints all the
+// information inside.
+func main() {
+	if len(os.Args) != 2 {
+		log.Fatalf("Usage:  %s ADDRESS_BOOK_FILE\n", os.Args[0])
+	}
+	fname := os.Args[1]
+
+	// [START unmarshal_proto]
+	// Read the existing address book.
+	in, err := ioutil.ReadFile(fname)
+	if err != nil {
+		log.Fatalln("Error reading file:", err)
+	}
+	book := &pb.AddressBook{}
+	if err := proto.Unmarshal(in, book); err != nil {
+		log.Fatalln("Failed to parse address book:", err)
+	}
+	// [END unmarshal_proto]
+
+	listPeople(os.Stdout, book)
+}
diff --git a/src/third_party/protobuf-3/examples/list_people.py b/src/third_party/protobuf-3/examples/list_people.py
new file mode 100755
index 0000000..f131872
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/list_people.py
@@ -0,0 +1,37 @@
+#! /usr/bin/env python
+
+# See README.txt for information and build instructions.
+
+import addressbook_pb2
+import sys
+
+# Iterates though all people in the AddressBook and prints info about them.
+def ListPeople(address_book):
+  for person in address_book.people:
+    print "Person ID:", person.id
+    print "  Name:", person.name
+    if person.email != "":
+      print "  E-mail address:", person.email
+
+    for phone_number in person.phones:
+      if phone_number.type == addressbook_pb2.Person.MOBILE:
+        print "  Mobile phone #:",
+      elif phone_number.type == addressbook_pb2.Person.HOME:
+        print "  Home phone #:",
+      elif phone_number.type == addressbook_pb2.Person.WORK:
+        print "  Work phone #:",
+      print phone_number.number
+
+# Main procedure:  Reads the entire address book from a file and prints all
+#   the information inside.
+if len(sys.argv) != 2:
+  print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
+  sys.exit(-1)
+
+address_book = addressbook_pb2.AddressBook()
+
+# Read the existing address book.
+with open(sys.argv[1], "rb") as f:
+  address_book.ParseFromString(f.read())
+
+ListPeople(address_book)
diff --git a/src/third_party/protobuf-3/examples/list_people_test.go b/src/third_party/protobuf-3/examples/list_people_test.go
new file mode 100644
index 0000000..87d6ad6
--- /dev/null
+++ b/src/third_party/protobuf-3/examples/list_people_test.go
@@ -0,0 +1,120 @@
+package main
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+
+	pb "github.com/google/protobuf/examples/tutorial"
+)
+
+func TestWritePersonWritesPerson(t *testing.T) {
+	buf := new(bytes.Buffer)
+	// [START populate_proto]
+	p := pb.Person{
+		Id:    1234,
+		Name:  "John Doe",
+		Email: "jdoe@example.com",
+		Phones: []*pb.Person_PhoneNumber{
+			{Number: "555-4321", Type: pb.Person_HOME},
+		},
+	}
+	// [END populate_proto]
+	writePerson(buf, &p)
+	got := buf.String()
+	want := `Person ID: 1234
+  Name: John Doe
+  E-mail address: jdoe@example.com
+  Home phone #: 555-4321
+`
+	if got != want {
+		t.Errorf("writePerson(%s) =>\n\t%q, want %q", p.String(), got, want)
+	}
+}
+
+func TestListPeopleWritesList(t *testing.T) {
+	buf := new(bytes.Buffer)
+	in := pb.AddressBook{[]*pb.Person{
+		{
+			Name:  "John Doe",
+			Id:    101,
+			Email: "john@example.com",
+		},
+		{
+			Name: "Jane Doe",
+			Id:   102,
+		},
+		{
+			Name:  "Jack Doe",
+			Id:    201,
+			Email: "jack@example.com",
+			Phones: []*pb.Person_PhoneNumber{
+				{Number: "555-555-5555", Type: pb.Person_WORK},
+			},
+		},
+		{
+			Name:  "Jack Buck",
+			Id:    301,
+			Email: "buck@example.com",
+			Phones: []*pb.Person_PhoneNumber{
+				{Number: "555-555-0000", Type: pb.Person_HOME},
+				{Number: "555-555-0001", Type: pb.Person_MOBILE},
+				{Number: "555-555-0002", Type: pb.Person_WORK},
+			},
+		},
+		{
+			Name:  "Janet Doe",
+			Id:    1001,
+			Email: "janet@example.com",
+			Phones: []*pb.Person_PhoneNumber{
+				{Number: "555-777-0000"},
+				{Number: "555-777-0001", Type: pb.Person_HOME},
+			},
+		},
+	}}
+	listPeople(buf, &in)
+	want := strings.Split(`Person ID: 101
+  Name: John Doe
+  E-mail address: john@example.com
+Person ID: 102
+  Name: Jane Doe
+Person ID: 201
+  Name: Jack Doe
+  E-mail address: jack@example.com
+  Work phone #: 555-555-5555
+Person ID: 301
+  Name: Jack Buck
+  E-mail address: buck@example.com
+  Home phone #: 555-555-0000
+  Mobile phone #: 555-555-0001
+  Work phone #: 555-555-0002
+Person ID: 1001
+  Name: Janet Doe
+  E-mail address: janet@example.com
+  Mobile phone #: 555-777-0000
+  Home phone #: 555-777-0001
+`, "\n")
+	got := strings.Split(buf.String(), "\n")
+	if len(got) != len(want) {
+		t.Errorf(
+			"listPeople(%s) =>\n\t%q has %d lines, want %d",
+			in.String(),
+			buf.String(),
+			len(got),
+			len(want))
+	}
+	lines := len(got)
+	if lines > len(want) {
+		lines = len(want)
+	}
+	for i := 0; i < lines; i++ {
+		if got[i] != want[i] {
+			t.Errorf(
+				"listPeople(%s) =>\n\tline %d %q, want %q",
+				in.String(),
+				i,
+				got[i],
+				want[i])
+		}
+	}
+}
diff --git a/src/third_party/protobuf-3/generate_descriptor_proto.sh b/src/third_party/protobuf-3/generate_descriptor_proto.sh
new file mode 100755
index 0000000..c170c83
--- /dev/null
+++ b/src/third_party/protobuf-3/generate_descriptor_proto.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+# Run this script to regenerate descriptor.pb.{h,cc} after the protocol
+# compiler changes.  Since these files are compiled into the protocol compiler
+# itself, they cannot be generated automatically by a make rule.  "make check"
+# will fail if these files do not match what the protocol compiler would
+# generate.
+#
+# HINT:  Flags passed to generate_descriptor_proto.sh will be passed directly
+#   to make when building protoc.  This is particularly useful for passing
+#   -j4 to run 4 jobs simultaneously.
+
+if test ! -e src/google/protobuf/stubs/common.h; then
+  cat >&2 << __EOF__
+Could not find source code.  Make sure you are running this script from the
+root of the distribution tree.
+__EOF__
+  exit 1
+fi
+
+if test ! -e src/Makefile; then
+  cat >&2 << __EOF__
+Could not find src/Makefile.  You must run ./configure (and perhaps
+./autogen.sh) first.
+__EOF__
+  exit 1
+fi
+
+cd src
+
+declare -a RUNTIME_PROTO_FILES=(\
+  google/protobuf/any.proto \
+  google/protobuf/api.proto \
+  google/protobuf/descriptor.proto \
+  google/protobuf/duration.proto \
+  google/protobuf/empty.proto \
+  google/protobuf/field_mask.proto \
+  google/protobuf/source_context.proto \
+  google/protobuf/struct.proto \
+  google/protobuf/timestamp.proto \
+  google/protobuf/type.proto \
+  google/protobuf/wrappers.proto)
+
+CORE_PROTO_IS_CORRECT=0
+PROCESS_ROUND=1
+TMP=$(mktemp -d)
+echo "Updating descriptor protos..."
+while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
+do
+  echo "Round $PROCESS_ROUND"
+  CORE_PROTO_IS_CORRECT=1
+
+  make $@ protoc
+  if test $? -ne 0; then
+    echo "Failed to build protoc."
+    exit 1
+  fi
+
+  ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
+  ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP google/protobuf/compiler/plugin.proto
+
+  for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
+    BASE_NAME=${PROTO_FILE%.*}
+    diff ${BASE_NAME}.pb.h $TMP/${BASE_NAME}.pb.h > /dev/null
+    if test $? -ne 0; then
+      CORE_PROTO_IS_CORRECT=0
+    fi
+    diff ${BASE_NAME}.pb.cc $TMP/${BASE_NAME}.pb.cc > /dev/null
+    if test $? -ne 0; then
+      CORE_PROTO_IS_CORRECT=0
+    fi
+  done
+
+  diff google/protobuf/compiler/plugin.pb.h $TMP/google/protobuf/compiler/plugin.pb.h > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+  diff google/protobuf/compiler/plugin.pb.cc $TMP/google/protobuf/compiler/plugin.pb.cc > /dev/null
+  if test $? -ne 0; then
+    CORE_PROTO_IS_CORRECT=0
+  fi
+
+  # Only override the output if the files are different to avoid re-compilation
+  # of the protoc.
+  if [ $CORE_PROTO_IS_CORRECT -ne 1 ]; then
+    for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
+      BASE_NAME=${PROTO_FILE%.*}
+      mv $TMP/${BASE_NAME}.pb.h ${BASE_NAME}.pb.h
+      mv $TMP/${BASE_NAME}.pb.cc ${BASE_NAME}.pb.cc
+    done
+    mv $TMP/google/protobuf/compiler/plugin.pb.* google/protobuf/compiler/
+  fi
+
+  PROCESS_ROUND=$((PROCESS_ROUND + 1))
+done
+cd ..
+
+if test -x objectivec/generate_well_known_types.sh; then
+  echo "Generating messages for objc."
+  objectivec/generate_well_known_types.sh $@
+fi
+
+if test -x csharp/generate_protos.sh; then
+  echo "Generating messages for C#."
+  csharp/generate_protos.sh $@
+fi
diff --git a/src/third_party/protobuf-3/gmock.BUILD b/src/third_party/protobuf-3/gmock.BUILD
new file mode 100644
index 0000000..82abf27
--- /dev/null
+++ b/src/third_party/protobuf-3/gmock.BUILD
@@ -0,0 +1,28 @@
+cc_library(
+    name = "gtest",
+    srcs = [
+        "gmock-1.7.0/gtest/src/gtest-all.cc",
+        "gmock-1.7.0/src/gmock-all.cc",
+    ],
+    hdrs = glob([
+        "gmock-1.7.0/**/*.h",
+        "gmock-1.7.0/gtest/src/*.cc",
+        "gmock-1.7.0/src/*.cc",
+    ]),
+    includes = [
+        "gmock-1.7.0",
+        "gmock-1.7.0/gtest",
+        "gmock-1.7.0/gtest/include",
+        "gmock-1.7.0/include",
+    ],
+    linkopts = ["-pthread"],
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "gtest_main",
+    srcs = ["gmock-1.7.0/src/gmock_main.cc"],
+    linkopts = ["-pthread"],
+    visibility = ["//visibility:public"],
+    deps = [":gtest"],
+)
diff --git a/src/third_party/protobuf-3/java/README.md b/src/third_party/protobuf-3/java/README.md
new file mode 100644
index 0000000..060d9ac
--- /dev/null
+++ b/src/third_party/protobuf-3/java/README.md
@@ -0,0 +1,102 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the Java Protocol Buffers runtime library.
+
+Installation - With Maven
+=========================
+
+The Protocol Buffers build is managed using Maven.  If you would
+rather build without Maven, see below.
+
+1) Install Apache Maven if you don't have it:
+
+     http://maven.apache.org/
+
+2) Build the C++ code, or obtain a binary distribution of protoc.  If
+   you install a binary distribution, make sure that it is the same
+   version as this package.  If in doubt, run:
+
+     $ protoc --version
+
+   You will need to place the protoc executable in ../src.  (If you
+   built it yourself, it should already be there.)
+
+3) Run the tests:
+
+     $ mvn test
+
+   If some tests fail, this library may not work correctly on your
+   system.  Continue at your own risk.
+
+4) Install the library into your Maven repository:
+
+     $ mvn install
+
+5) If you do not use Maven to manage your own build, you can build a
+   .jar file to use:
+
+     $ mvn package
+
+   The .jar will be placed in the "target" directory.
+
+Installation - 'Lite' Version - With Maven
+==========================================
+
+Building the 'lite' version of the Java Protocol Buffers library is
+the same as building the full version, except that all commands are
+run using the 'lite' profile.  (see
+http://maven.apache.org/guides/introduction/introduction-to-profiles.html)
+
+E.g. to install the lite version of the jar, you would run:
+
+    $ mvn install -P lite
+
+The resulting artifact has the 'lite' classifier.  To reference it
+for dependency resolution, you would specify it as:
+
+```
+  <dependency>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-java</artifactId>
+    <version>${version}</version>
+    <classifier>lite</classifier>
+  </dependency>
+```
+
+Installation - Without Maven
+============================
+
+If you would rather not install Maven to build the library, you may
+follow these instructions instead.  Note that these instructions skip
+running unit tests.
+
+1) Build the C++ code, or obtain a binary distribution of protoc.  If
+   you install a binary distribution, make sure that it is the same
+   version as this package.  If in doubt, run:
+
+     $ protoc --version
+
+   If you built the C++ code without installing, the compiler binary
+   should be located in ../src.
+
+2) Invoke protoc to build DescriptorProtos.java:
+
+     $ protoc --java_out=src/main/java -I../src \
+         ../src/google/protobuf/descriptor.proto
+
+3) Compile the code in src/main/java using whatever means you prefer.
+
+4) Install the classes wherever you prefer.
+
+Usage
+=====
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+  https://developers.google.com/protocol-buffers/
diff --git a/src/third_party/protobuf-3/java/core/generate-sources-build.xml b/src/third_party/protobuf-3/java/core/generate-sources-build.xml
new file mode 100644
index 0000000..0996e5f
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/generate-sources-build.xml
@@ -0,0 +1,20 @@
+<project name="generate-sources">
+    <echo message="Running protoc ..."/>
+    <mkdir dir="${generated.sources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=${generated.sources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+    </exec>
+</project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/java/core/generate-test-sources-build.xml b/src/third_party/protobuf-3/java/core/generate-test-sources-build.xml
new file mode 100644
index 0000000..ab415db
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/generate-test-sources-build.xml
@@ -0,0 +1,43 @@
+<project name="generate-test-sources">
+    <mkdir dir="${generated.testsources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=${generated.testsources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="--proto_path=${test.proto.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
+    </exec>
+</project>
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/java/core/pom.xml b/src/third_party/protobuf-3/java/core/pom.xml
new file mode 100644
index 0000000..0d4c5c7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/pom.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>3.0.0-beta-3</version>
+  </parent>
+
+  <artifactId>protobuf-java</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Protocol Buffers [Core]</name>
+  <description>
+    Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an
+    efficient yet extensible format.
+  </description>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <!-- Include core protos in the bundle as resources -->
+    <resources>
+      <resource>
+        <directory>${protobuf.source.dir}</directory>
+        <includes>
+          <include>google/protobuf/any.proto</include>
+          <include>google/protobuf/api.proto</include>
+          <include>google/protobuf/descriptor.proto</include>
+          <include>google/protobuf/duration.proto</include>
+          <include>google/protobuf/empty.proto</include>
+          <include>google/protobuf/field_mask.proto</include>
+          <include>google/protobuf/source_context.proto</include>
+          <include>google/protobuf/struct.proto</include>
+          <include>google/protobuf/timestamp.proto</include>
+          <include>google/protobuf/type.proto</include>
+          <include>google/protobuf/wrappers.proto</include>
+          <include>google/protobuf/compiler/plugin.proto</include>
+        </includes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <!-- Use Antrun plugin to generate sources with protoc -->
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <!-- Generate core protos -->
+          <execution>
+            <id>generate-sources</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+
+          <!-- Generate the test protos -->
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-test-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Add the generated sources to the build -->
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <generatedSourcesDirectory>${generated.sources.dir}</generatedSourcesDirectory>
+          <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory>
+        </configuration>
+      </plugin>
+
+      <!-- OSGI bundle configuration -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+            <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
+            <Export-Package>com.google.protobuf;version=${project.version}</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
new file mode 100644
index 0000000..03c0d57
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -0,0 +1,553 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Internal.EnumLite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A partial implementation of the {@link Message} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessage
+    // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+    extends AbstractMessageLite
+    implements Message {
+  
+  @Override
+  public boolean isInitialized() {
+    return MessageReflection.isInitialized(this);
+  }
+
+
+  @Override
+  public List<String> findInitializationErrors() {
+    return MessageReflection.findMissingFields(this);
+  }
+
+  @Override
+  public String getInitializationErrorString() {
+    return MessageReflection.delimitWithCommas(findInitializationErrors());
+  }
+
+  /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+  @Override
+  public boolean hasOneof(OneofDescriptor oneof) {
+    throw new UnsupportedOperationException("hasOneof() is not implemented.");
+  }
+
+  /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+  @Override
+  public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+    throw new UnsupportedOperationException(
+        "getOneofFieldDescriptor() is not implemented.");
+  }
+
+  @Override
+  public final String toString() {
+    return TextFormat.printToString(this);
+  }
+
+  @Override
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    MessageReflection.writeMessageTo(this, getAllFields(), output, false);
+  }
+
+  protected int memoizedSize = -1;
+
+  @Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) {
+      return size;
+    }
+
+    memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
+    return memoizedSize;
+  }
+
+  @Override
+  public boolean equals(final Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof Message)) {
+      return false;
+    }
+    final Message otherMessage = (Message) other;
+    if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
+      return false;
+    }
+    return compareFields(getAllFields(), otherMessage.getAllFields()) &&
+        getUnknownFields().equals(otherMessage.getUnknownFields());
+  }
+
+  @Override
+  public int hashCode() {
+    int hash = memoizedHashCode;
+    if (hash == 0) {
+      hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      hash = hashFields(hash, getAllFields());
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+    }
+    return hash;
+  }
+  
+  private static ByteString toByteString(Object value) {
+    if (value instanceof byte[]) {
+      return ByteString.copyFrom((byte[]) value);
+    } else {
+      return (ByteString) value;
+    }
+  }
+ 
+  /**
+   * Compares two bytes fields. The parameters must be either a byte array or a
+   * ByteString object. They can be of different type though.
+   */
+  private static boolean compareBytes(Object a, Object b) {
+    if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[])a, (byte[])b);
+    }
+    return toByteString(a).equals(toByteString(b));
+  }
+  
+  /**
+   * Converts a list of MapEntry messages into a Map used for equals() and
+   * hashCode().
+   */
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static Map convertMapEntryListToMap(List list) {
+    if (list.isEmpty()) {
+      return Collections.emptyMap();
+    }
+    Map result = new HashMap();
+    Iterator iterator = list.iterator();
+    Message entry = (Message) iterator.next();
+    Descriptors.Descriptor descriptor = entry.getDescriptorForType();
+    Descriptors.FieldDescriptor key = descriptor.findFieldByName("key");
+    Descriptors.FieldDescriptor value = descriptor.findFieldByName("value");
+    Object fieldValue = entry.getField(value);
+    if (fieldValue instanceof EnumValueDescriptor) {
+      fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+    }
+    result.put(entry.getField(key), fieldValue);
+    while (iterator.hasNext()) {
+      entry = (Message) iterator.next();
+      fieldValue = entry.getField(value);
+      if (fieldValue instanceof EnumValueDescriptor) {
+        fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+      }
+      result.put(entry.getField(key), fieldValue);
+    }
+    return result;
+  }
+  
+  /**
+   * Compares two map fields. The parameters must be a list of MapEntry
+   * messages.
+   */
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static boolean compareMapField(Object a, Object b) {
+    Map ma = convertMapEntryListToMap((List) a);
+    Map mb = convertMapEntryListToMap((List) b);
+    return MapFieldLite.equals(ma, mb);
+  }
+  
+  /**
+   * Compares two set of fields.
+   * This method is used to implement {@link AbstractMessage#equals(Object)}
+   * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
+   * of bytes fields because immutable messages and mutable messages use
+   * different Java type to reprensent a bytes field and this method should be
+   * able to compare immutable messages, mutable messages and also an immutable
+   * message to a mutable message.
+   */
+  static boolean compareFields(Map<FieldDescriptor, Object> a,
+      Map<FieldDescriptor, Object> b) {
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (FieldDescriptor descriptor : a.keySet()) {
+      if (!b.containsKey(descriptor)) {
+        return false;
+      }
+      Object value1 = a.get(descriptor);
+      Object value2 = b.get(descriptor);
+      if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
+        if (descriptor.isRepeated()) {
+          List list1 = (List) value1;
+          List list2 = (List) value2;
+          if (list1.size() != list2.size()) {
+            return false;
+          }
+          for (int i = 0; i < list1.size(); i++) {
+            if (!compareBytes(list1.get(i), list2.get(i))) {
+              return false;
+            }
+          }
+        } else {
+          // Compares a singular bytes field.
+          if (!compareBytes(value1, value2)) {
+            return false;
+          }
+        }
+      } else if (descriptor.isMapField()) {
+        if (!compareMapField(value1, value2)) {
+          return false;
+        }
+      } else {
+        // Compare non-bytes fields.
+        if (!value1.equals(value2)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+  
+  /**
+   * Calculates the hash code of a map field. {@code value} must be a list of
+   * MapEntry messages.
+   */
+  @SuppressWarnings("unchecked")
+  private static int hashMapField(Object value) {
+    return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value));
+  }
+
+  /** Get a hash code for given fields and values, using the given seed. */
+  @SuppressWarnings("unchecked")
+  protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+    for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+      FieldDescriptor field = entry.getKey();
+      Object value = entry.getValue();
+      hash = (37 * hash) + field.getNumber();
+      if (field.isMapField()) {
+        hash = (53 * hash) + hashMapField(value);
+      } else if (field.getType() != FieldDescriptor.Type.ENUM){
+        hash = (53 * hash) + value.hashCode();
+      } else if (field.isRepeated()) {
+        List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+        hash = (53 * hash) + Internal.hashEnumList(list);
+      } else {
+        hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
+      }
+    }
+    return hash;
+  }
+
+  /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException with missing field information.
+   */
+  @Override
+  UninitializedMessageException newUninitializedMessageException() {
+    return Builder.newUninitializedMessageException(this);
+  }
+
+  // =================================================================
+
+  /**
+   * A partial implementation of the {@link Message.Builder} interface which
+   * implements as many methods of that interface as possible in terms of
+   * other methods.
+   */
+  @SuppressWarnings("unchecked")
+  public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+      extends AbstractMessageLite.Builder
+      implements Message.Builder {
+    // The compiler produces an error if this is not declared explicitly.
+    @Override
+    public abstract BuilderType clone();
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public boolean hasOneof(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException("hasOneof() is not implemented.");
+    }
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException(
+          "getOneofFieldDescriptor() is not implemented.");
+    }
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public BuilderType clearOneof(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException("clearOneof() is not implemented.");
+    }
+
+    @Override
+    public BuilderType clear() {
+      for (final Map.Entry<FieldDescriptor, Object> entry :
+           getAllFields().entrySet()) {
+        clearField(entry.getKey());
+      }
+      return (BuilderType) this;
+    }
+
+    @Override
+    public List<String> findInitializationErrors() {
+      return MessageReflection.findMissingFields(this);
+    }
+
+    @Override
+    public String getInitializationErrorString() {
+      return MessageReflection.delimitWithCommas(findInitializationErrors());
+    }
+    
+    @Override
+    protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+      return mergeFrom((Message) other);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final Message other) {
+      if (other.getDescriptorForType() != getDescriptorForType()) {
+        throw new IllegalArgumentException(
+          "mergeFrom(Message) can only merge messages of the same type.");
+      }
+
+      // Note:  We don't attempt to verify that other's fields have valid
+      //   types.  Doing so would be a losing battle.  We'd have to verify
+      //   all sub-messages as well, and we'd have to make copies of all of
+      //   them to insure that they don't change after verification (since
+      //   the Message interface itself cannot enforce immutability of
+      //   implementations).
+      // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
+      //   which allows people to make secure deep copies of messages.
+
+      for (final Map.Entry<FieldDescriptor, Object> entry :
+           other.getAllFields().entrySet()) {
+        final FieldDescriptor field = entry.getKey();
+        if (field.isRepeated()) {
+          for (final Object element : (List)entry.getValue()) {
+            addRepeatedField(field, element);
+          }
+        } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          final Message existingValue = (Message)getField(field);
+          if (existingValue == existingValue.getDefaultInstanceForType()) {
+            setField(field, entry.getValue());
+          } else {
+            setField(field,
+              existingValue.newBuilderForType()
+                .mergeFrom(existingValue)
+                .mergeFrom((Message)entry.getValue())
+                .build());
+          }
+        } else {
+          setField(field, entry.getValue());
+        }
+      }
+
+      mergeUnknownFields(other.getUnknownFields());
+
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input)
+                                 throws IOException {
+      return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      final UnknownFieldSet.Builder unknownFields =
+        UnknownFieldSet.newBuilder(getUnknownFields());
+      while (true) {
+        final int tag = input.readTag();
+        if (tag == 0) {
+          break;
+        }
+
+        MessageReflection.BuilderAdapter builderAdapter =
+            new MessageReflection.BuilderAdapter(this);
+        if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+                                              extensionRegistry,
+                                              getDescriptorForType(),
+                                              builderAdapter,
+                                              tag)) {
+          // end group tag
+          break;
+        }
+      }
+      setUnknownFields(unknownFields.build());
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
+      setUnknownFields(
+        UnknownFieldSet.newBuilder(getUnknownFields())
+                       .mergeFrom(unknownFields)
+                       .build());
+      return (BuilderType) this;
+    }
+
+    @Override
+    public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+      throw new UnsupportedOperationException(
+          "getFieldBuilder() called on an unsupported message type.");
+    }
+
+    @Override
+    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+      throw new UnsupportedOperationException(
+          "getRepeatedFieldBuilder() called on an unsupported message type.");
+    }
+
+    @Override
+    public String toString() {
+      return TextFormat.printToString(this);
+    }
+
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(Message message) {
+      return new UninitializedMessageException(
+          MessageReflection.findMissingFields(message));
+    }
+
+    // ===============================================================
+    // The following definitions seem to be required in order to make javac
+    // not produce weird errors like:
+    //
+    // java/com/google/protobuf/DynamicMessage.java:203: types
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> and
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+    //   define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+    //   return types.
+    //
+    // Strangely, these lines are only needed if javac is invoked separately
+    // on AbstractMessage.java and AbstractMessageLite.java.  If javac is
+    // invoked on both simultaneously, it works.  (Or maybe the important
+    // point is whether or not DynamicMessage.java is compiled together with
+    // AbstractMessageLite.java -- not sure.)  I suspect this is a compiler
+    // bug.
+
+    @Override
+    public BuilderType mergeFrom(final ByteString data)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final ByteString data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, off, len);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final InputStream input)
+        throws IOException {
+      return (BuilderType) super.mergeFrom(input);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return (BuilderType) super.mergeFrom(input, extensionRegistry);
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(final InputStream input)
+        throws IOException {
+      return super.mergeDelimitedFrom(input);
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return super.mergeDelimitedFrom(input, extensionRegistry);
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
new file mode 100644
index 0000000..43736dd
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -0,0 +1,386 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite<
+    MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+    BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>> 
+        implements MessageLite {
+  protected int memoizedHashCode = 0;
+  
+  @Override
+  public ByteString toByteString() {
+    try {
+      final ByteString.CodedBuilder out =
+        ByteString.newCodedBuilder(getSerializedSize());
+      writeTo(out.getCodedOutput());
+      return out.build();
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a ByteString threw an IOException (should " +
+        "never happen).", e);
+    }
+  }
+
+  @Override
+  public byte[] toByteArray() {
+    try {
+      final byte[] result = new byte[getSerializedSize()];
+      final CodedOutputStream output = CodedOutputStream.newInstance(result);
+      writeTo(output);
+      output.checkNoSpaceLeft();
+      return result;
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a byte array threw an IOException " +
+        "(should never happen).", e);
+    }
+  }
+
+  @Override
+  public void writeTo(final OutputStream output) throws IOException {
+    final int bufferSize =
+        CodedOutputStream.computePreferredBufferSize(getSerializedSize());
+    final CodedOutputStream codedOutput =
+        CodedOutputStream.newInstance(output, bufferSize);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  @Override
+  public void writeDelimitedTo(final OutputStream output) throws IOException {
+    final int serialized = getSerializedSize();
+    final int bufferSize = CodedOutputStream.computePreferredBufferSize(
+        CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
+    final CodedOutputStream codedOutput =
+        CodedOutputStream.newInstance(output, bufferSize);
+    codedOutput.writeRawVarint32(serialized);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+
+  /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException.
+   */
+  UninitializedMessageException newUninitializedMessageException() {
+    return new UninitializedMessageException(this);
+  }
+
+  protected static void checkByteStringIsUtf8(ByteString byteString)
+      throws IllegalArgumentException {
+    if (!byteString.isValidUtf8()) {
+      throw new IllegalArgumentException("Byte string is not UTF-8.");
+    }
+  }
+
+  protected static <T> void addAll(final Iterable<T> values,
+      final Collection<? super T> list) {
+    Builder.addAll(values, list);
+  }
+  
+  /**
+   * A partial implementation of the {@link Message.Builder} interface which
+   * implements as many methods of that interface as possible in terms of
+   * other methods.
+   */
+  @SuppressWarnings("unchecked")
+  public abstract static class Builder<
+      MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+      BuilderType extends Builder<MessageType, BuilderType>>
+      implements MessageLite.Builder {
+    // The compiler produces an error if this is not declared explicitly.
+    @Override
+    public abstract BuilderType clone();
+
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
+      return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
+    }
+
+    // Re-defined here for return type covariance.
+    @Override
+    public abstract BuilderType mergeFrom(
+        final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    @Override
+    public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final ByteString data, final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final int off,
+        final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput, extensionRegistry);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    /**
+     * An InputStream implementations which reads from some other InputStream
+     * but is limited to a particular number of bytes.  Used by
+     * mergeDelimitedFrom().  This is intentionally package-private so that
+     * UnknownFieldSet can share it.
+     */
+    static final class LimitedInputStream extends FilterInputStream {
+      private int limit;
+
+      LimitedInputStream(InputStream in, int limit) {
+        super(in);
+        this.limit = limit;
+      }
+
+      @Override
+      public int available() throws IOException {
+        return Math.min(super.available(), limit);
+      }
+
+      @Override
+      public int read() throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        final int result = super.read();
+        if (result >= 0) {
+          --limit;
+        }
+        return result;
+      }
+
+      @Override
+      public int read(final byte[] b, final int off, int len)
+                      throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        len = Math.min(len, limit);
+        final int result = super.read(b, off, len);
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+
+      @Override
+      public long skip(final long n) throws IOException {
+        final long result = super.skip(Math.min(n, limit));
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+      final int firstByte = input.read();
+      if (firstByte == -1) {
+        return false;
+      }
+      final int size = CodedInputStream.readRawVarint32(firstByte, input);
+      final InputStream limitedInput = new LimitedInputStream(input, size);
+      mergeFrom(limitedInput, extensionRegistry);
+      return true;
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
+      return mergeDelimitedFrom(input,
+          ExtensionRegistryLite.getEmptyRegistry());
+    }
+    
+    @Override
+    @SuppressWarnings("unchecked") // isInstance takes care of this
+    public BuilderType mergeFrom(final MessageLite other) {
+      if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+        throw new IllegalArgumentException(
+            "mergeFrom(MessageLite) can only merge messages of the same type.");
+      }
+        
+      return internalMergeFrom((MessageType) other);
+    }
+    
+    protected abstract BuilderType internalMergeFrom(MessageType message);
+
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(MessageLite message) {
+      return new UninitializedMessageException(message);
+    }
+
+    /**
+     * Adds the {@code values} to the {@code list}.  This is a helper method
+     * used by generated code.  Users should ignore it.
+     *
+     * @throws NullPointerException if {@code values} or any of the elements of
+     * {@code values} is null. When that happens, some elements of
+     * {@code values} may have already been added to the result {@code list}.
+     */
+    protected static <T> void addAll(final Iterable<T> values,
+                                     final Collection<? super T> list) {
+      if (values == null) {
+        throw new NullPointerException();
+      }
+      if (values instanceof LazyStringList) {
+        // For StringOrByteStringLists, check the underlying elements to avoid
+        // forcing conversions of ByteStrings to Strings.
+        checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+        list.addAll((Collection<T>) values);
+      } else if (values instanceof Collection) {
+        checkForNullValues(values);
+        list.addAll((Collection<T>) values);
+      } else {
+        for (final T value : values) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          list.add(value);
+        }
+      }
+    }
+
+    private static void checkForNullValues(final Iterable<?> values) {
+      for (final Object value : values) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+      }
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractParser.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractParser.java
new file mode 100644
index 0000000..66b0ee3
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractParser.java
@@ -0,0 +1,258 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+    implements Parser<MessageType> {
+  /**
+   * Creates an UninitializedMessageException for MessageType.
+   */
+  private UninitializedMessageException
+      newUninitializedMessageException(MessageType message) {
+    if (message instanceof AbstractMessageLite) {
+      return ((AbstractMessageLite) message).newUninitializedMessageException();
+    }
+    return new UninitializedMessageException(message);
+  }
+
+  /**
+   * Helper method to check if message is initialized.
+   *
+   * @throws InvalidProtocolBufferException if it is not initialized.
+   * @return The message to check.
+   */
+  private MessageType checkMessageInitialized(MessageType message)
+      throws InvalidProtocolBufferException {
+    if (message != null && !message.isInitialized()) {
+      throw newUninitializedMessageException(message)
+          .asInvalidProtocolBufferException()
+          .setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  private static final ExtensionRegistryLite EMPTY_REGISTRY
+      = ExtensionRegistryLite.getEmptyRegistry();
+
+  @Override
+  public MessageType parsePartialFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    MessageType message;
+    try {
+      CodedInputStream input = data.newCodedInput();
+      message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+
+  @Override
+  public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    try {
+      CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+      MessageType message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(data, off, len, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    CodedInputStream codedInput = CodedInputStream.newInstance(input);
+    MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+    try {
+      codedInput.checkLastTagWas(0);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  @Override
+  public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialDelimitedFrom(
+      InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    int size;
+    try {
+      int firstByte = input.read();
+      if (firstByte == -1) {
+        return null;
+      }
+      size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (IOException e) {
+      throw new InvalidProtocolBufferException(e.getMessage());
+    }
+    InputStream limitedInput = new LimitedInputStream(input, size);
+    return parsePartialFrom(limitedInput, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parsePartialDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialDelimitedFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parseDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
new file mode 100644
index 0000000..b17db6e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -0,0 +1,180 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.ProtobufList;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
+ * {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
+ */
+abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+
+  protected static final int DEFAULT_CAPACITY = 10;
+
+  /**
+   * Whether or not this list is modifiable.
+   */
+  private boolean isMutable;
+
+  /**
+   * Constructs a mutable list by default.
+   */
+  AbstractProtobufList() {
+    isMutable = true;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof List)) {
+      return false;
+    }
+    // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+    // based approach in our super class. Otherwise our index based approach will avoid those
+    // allocations.
+    if (!(o instanceof RandomAccess)) {
+      return super.equals(o);
+    }
+
+    List<?> other = (List<?>) o;
+    final int size = size();
+    if (size != other.size()) {
+      return false;
+    }
+    for (int i = 0; i < size; i++) {
+      if (!get(i).equals(other.get(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    final int size = size();
+    int hashCode = 1;
+    for (int i = 0; i < size; i++) {
+      hashCode = (31 * hashCode) + get(i).hashCode();
+    }
+    return hashCode;
+  }
+
+  @Override
+  public boolean add(E e) {
+    ensureIsMutable();
+    return super.add(e);
+  }
+
+  @Override
+  public void add(int index, E element) {
+    ensureIsMutable();
+    super.add(index, element);
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends E> c) {
+    ensureIsMutable();
+    return super.addAll(c);
+  }
+  
+  @Override
+  public boolean addAll(int index, Collection<? extends E> c) {
+    ensureIsMutable();
+    return super.addAll(index, c);
+  }
+
+  @Override
+  public void clear() {
+    ensureIsMutable();
+    super.clear();
+  }
+  
+  @Override
+  public boolean isModifiable() {
+    return isMutable;
+  }
+  
+  @Override
+  public final void makeImmutable() {
+    isMutable = false;
+  }
+  
+  @Override
+  public E remove(int index) {
+    ensureIsMutable();
+    return super.remove(index);
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    return super.remove(o);
+  }
+  
+  @Override
+  public boolean removeAll(Collection<?> c) {
+    ensureIsMutable();
+    return super.removeAll(c);
+  }
+  
+  @Override
+  public boolean retainAll(Collection<?> c) {
+    ensureIsMutable();
+    return super.retainAll(c);
+  }
+  
+  @Override
+  public E set(int index, E element) {
+    ensureIsMutable();
+    return super.set(index, element);
+  }
+  
+  /**
+   * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are
+   * responsible for invoking this method on mutate operations.
+   */
+  protected void ensureIsMutable() {
+    if (!isMutable) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java
new file mode 100644
index 0000000..d535efb
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java
@@ -0,0 +1,51 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * <p>Abstract interface for a blocking RPC channel.  {@code BlockingRpcChannel}
+ * is the blocking equivalent to {@link RpcChannel}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingRpcChannel {
+  /**
+   * Call the given method of the remote service and blocks until it returns.
+   * {@code callBlockingMethod()} is the blocking equivalent to
+   * {@link RpcChannel#callMethod}.
+   */
+  Message callBlockingMethod(
+      Descriptors.MethodDescriptor method,
+      RpcController controller,
+      Message request,
+      Message responsePrototype) throws ServiceException;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingService.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingService.java
new file mode 100644
index 0000000..d01f0b8
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BlockingService.java
@@ -0,0 +1,64 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Blocking equivalent to {@link Service}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingService {
+  /**
+   * Equivalent to {@link Service#getDescriptorForType}.
+   */
+  Descriptors.ServiceDescriptor getDescriptorForType();
+
+  /**
+   * Equivalent to {@link Service#callMethod}, except that
+   * {@code callBlockingMethod()} returns the result of the RPC or throws a
+   * {@link ServiceException} if there is a failure, rather than passing the
+   * information to a callback.
+   */
+  Message callBlockingMethod(Descriptors.MethodDescriptor method,
+                             RpcController controller,
+                             Message request) throws ServiceException;
+
+  /**
+   * Equivalent to {@link Service#getRequestPrototype}.
+   */
+  Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+  /**
+   * Equivalent to {@link Service#getResponsePrototype}.
+   */
+  Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
new file mode 100644
index 0000000..8b2820b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -0,0 +1,270 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.BooleanList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link BooleanList} on top of a primitive array.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class BooleanArrayList
+    extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess {
+  
+  private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  public static BooleanArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+  
+  /**
+   * The backing store for the list.
+   */
+  private boolean[] array;
+
+  /**
+   * The size of the list distinct from the length of the array. That is, it is the number of
+   * elements set in the list.
+   */
+  private int size;
+
+  /**
+   * Constructs a new mutable {@code BooleanArrayList} with default capacity.
+   */
+  BooleanArrayList() {
+    this(new boolean[DEFAULT_CAPACITY], 0);
+  }
+
+  /**
+   * Constructs a new mutable {@code BooleanArrayList}.
+   */
+  private BooleanArrayList(boolean[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof BooleanArrayList)) {
+      return super.equals(o);
+    }
+    BooleanArrayList other = (BooleanArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final boolean[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Internal.hashBoolean(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public BooleanList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new BooleanArrayList(Arrays.copyOf(array, capacity), size);
+  }
+
+  @Override
+  public Boolean get(int index) {
+    return getBoolean(index);
+  }
+
+  @Override
+  public boolean getBoolean(int index) {
+    ensureIndexInRange(index);
+    return array[index];
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Boolean set(int index, Boolean element) {
+    return setBoolean(index, element);
+  }
+
+  @Override
+  public boolean setBoolean(int index, boolean element) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    boolean previousValue = array[index];
+    array[index] = element;
+    return previousValue;
+  }
+
+  @Override
+  public void add(int index, Boolean element) {
+    addBoolean(index, element);
+  }
+
+  /**
+   * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+   */
+  @Override
+  public void addBoolean(boolean element) {
+    addBoolean(size, element);
+  }
+
+  /**
+   * Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element.
+   */
+  private void addBoolean(int index, boolean element) {
+    ensureIsMutable();
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+    
+    if (size < array.length) {
+      // Shift everything over to make room
+      System.arraycopy(array, index, array, index + 1, size - index);
+    } else {
+      // Resize to 1.5x the size
+      int length = ((size * 3) / 2) + 1;
+      boolean[] newArray = new boolean[length];
+      
+      // Copy the first part directly
+      System.arraycopy(array, 0, newArray, 0, index);
+      
+      // Copy the rest shifted over by one to make room
+      System.arraycopy(array, index, newArray, index + 1, size - index);
+      array = newArray;
+    }
+
+    array[index] = element;
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends Boolean> collection) {
+    ensureIsMutable();
+    
+    if (collection == null) {
+      throw new NullPointerException();
+    }
+    
+    // We specialize when adding another BooleanArrayList to avoid boxing elements.
+    if (!(collection instanceof BooleanArrayList)) {
+      return super.addAll(collection);
+    }
+    
+    BooleanArrayList list = (BooleanArrayList) collection;
+    if (list.size == 0) {
+      return false;
+    }
+    
+    int overflow = Integer.MAX_VALUE - size;
+    if (overflow < list.size) {
+      // We can't actually represent a list this large.
+      throw new OutOfMemoryError();
+    }
+    
+    int newSize = size + list.size;
+    if (newSize > array.length) {
+      array = Arrays.copyOf(array, newSize);
+    }
+    
+    System.arraycopy(list.array, 0, array, size, list.size);
+    size = newSize;
+    modCount++;
+    return true;
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    for (int i = 0; i < size; i++) {
+      if (o.equals(array[i])) {
+        System.arraycopy(array, i + 1, array, i, size - i);
+        size--;
+        modCount++;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Boolean remove(int index) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    boolean value = array[index];
+    System.arraycopy(array, index + 1, array, index, size - index);
+    size--;
+    modCount++;
+    return value;
+  }
+
+  /**
+   * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+   * {@link IndexOutOfBoundsException} if it is not.
+   * 
+   * @param index the index to verify is in range
+   */
+  private void ensureIndexInRange(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+  }
+
+  private String makeOutOfBoundsExceptionMessage(int index) {
+    return "Index:" + index + ", Size:" + size;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
new file mode 100644
index 0000000..0cc3817
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
@@ -0,0 +1,145 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.ref.SoftReference;
+import java.nio.ByteBuffer;
+
+/**
+ * Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s.
+ */
+final class ByteBufferWriter {
+  private ByteBufferWriter() {}
+
+  /**
+   * Minimum size for a cached buffer. This prevents us from allocating buffers that are too
+   * small to be easily reused.
+   */
+  // TODO(nathanmittler): tune this property or allow configuration?
+  private static final int MIN_CACHED_BUFFER_SIZE = 1024;
+
+  /**
+   * Maximum size for a cached buffer. If a larger buffer is required, it will be allocated
+   * but not cached.
+   */
+  // TODO(nathanmittler): tune this property or allow configuration?
+  private static final int MAX_CACHED_BUFFER_SIZE = 16 * 1024;
+
+  /**
+   * The fraction of the requested buffer size under which the buffer will be reallocated.
+   */
+  // TODO(nathanmittler): tune this property or allow configuration?
+  private static final float BUFFER_REALLOCATION_THRESHOLD = 0.5f;
+
+  /**
+   * Keeping a soft reference to a thread-local buffer. This buffer is used for writing a
+   * {@link ByteBuffer} to an {@link OutputStream} when no zero-copy alternative was available.
+   * Using a "soft" reference since VMs may keep this reference around longer than "weak"
+   * (e.g. HotSpot will maintain soft references until memory pressure warrants collection).
+   */
+  private static final ThreadLocal<SoftReference<byte[]>> BUFFER =
+      new ThreadLocal<SoftReference<byte[]>>();
+
+  /**
+   * For testing purposes only. Clears the cached buffer to force a new allocation on the next
+   * invocation.
+   */
+  static void clearCachedBuffer() {
+    BUFFER.set(null);
+  }
+
+  /**
+   * Writes the remaining content of the buffer to the given stream. The buffer {@code position}
+   * will remain unchanged by this method.
+   */
+  static void write(ByteBuffer buffer, OutputStream output) throws IOException {
+    final int initialPos = buffer.position();
+    try {
+      if (buffer.hasArray()) {
+        // Optimized write for array-backed buffers.
+        // Note that we're taking the risk that a malicious OutputStream could modify the array.
+        output.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
+      } else if (output instanceof FileOutputStream) {
+        // Use a channel to write out the ByteBuffer. This will automatically empty the buffer.
+        ((FileOutputStream) output).getChannel().write(buffer);
+      } else {
+        // Read all of the data from the buffer to an array.
+        // TODO(nathanmittler): Consider performance improvements for other "known" stream types.
+        final byte[] array = getOrCreateBuffer(buffer.remaining());
+        while (buffer.hasRemaining()) {
+          int length = min(buffer.remaining(), array.length);
+          buffer.get(array, 0, length);
+          output.write(array, 0, length);
+        }
+      }
+    } finally {
+      // Restore the initial position.
+      buffer.position(initialPos);
+    }
+  }
+
+  private static byte[] getOrCreateBuffer(int requestedSize) {
+    requestedSize = max(requestedSize, MIN_CACHED_BUFFER_SIZE);
+
+    byte[] buffer = getBuffer();
+    // Only allocate if we need to.
+    if (buffer == null || needToReallocate(requestedSize, buffer.length)) {
+      buffer = new byte[requestedSize];
+
+      // Only cache the buffer if it's not too big.
+      if (requestedSize <= MAX_CACHED_BUFFER_SIZE) {
+        setBuffer(buffer);
+      }
+    }
+    return buffer;
+  }
+
+  private static boolean needToReallocate(int requestedSize, int bufferLength) {
+    // First check against just the requested length to avoid the multiply.
+    return bufferLength < requestedSize
+        && bufferLength < requestedSize * BUFFER_REALLOCATION_THRESHOLD;
+  }
+
+  private static byte[] getBuffer() {
+    SoftReference<byte[]> sr = BUFFER.get();
+    return sr == null ? null : sr.get();
+  }
+
+  private static void setBuffer(byte[] value) {
+    BUFFER.set(new SoftReference<byte[]>(value));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteOutput.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteOutput.java
new file mode 100644
index 0000000..8b7b04c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteOutput.java
@@ -0,0 +1,116 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * An output target for raw bytes. This interface provides semantics that support two types of
+ * writing:
+ *
+ * <p/><b>Traditional write operations:</b>
+ * (as defined by {@link java.io.OutputStream}) where the target method is responsible for either
+ * copying the data or completing the write before returning from the method call.
+ *
+ * <p/><b>Lazy write operations:</b> where the caller guarantees that it will never modify the
+ * provided buffer and it can therefore be considered immutable. The target method is free to
+ * maintain a reference to the buffer beyond the scope of the method call (e.g. until the write
+ * operation completes).
+ */
+@ExperimentalApi
+public abstract class ByteOutput {
+  /**
+   * Writes a single byte.
+   *
+   * @param value the byte to be written
+   * @throws IOException thrown if an error occurred while writing
+   */
+  public abstract void write(byte value) throws IOException;
+
+  /**
+   * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will
+   * not be processed prior to the return of this method call, since {@code value} may be
+   * reused/altered by the caller.
+   *
+   * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+   * programming error and will lead to data corruption which will be difficult to debug.
+   *
+   * @param value the bytes to be written
+   * @param offset the offset of the start of the writable range
+   * @param length the number of bytes to write starting from {@code offset}
+   * @throws IOException thrown if an error occurred while writing
+   */
+  public abstract void write(byte[] value, int offset, int length) throws IOException;
+
+  /**
+   * Writes a sequence of bytes. The {@link ByteOutput} is free to retain a reference to the value
+   * beyond the scope of this method call (e.g. write later) since it is considered immutable and is
+   * guaranteed not to change by the caller.
+   *
+   * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+   * programming error and will lead to data corruption which will be difficult to debug.
+   *
+   * @param value the bytes to be written
+   * @param offset the offset of the start of the writable range
+   * @param length the number of bytes to write starting from {@code offset}
+   * @throws IOException thrown if an error occurred while writing
+   */
+  public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
+
+  /**
+   * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will
+   * not be processed prior to the return of this method call, since {@code value} may be
+   * reused/altered by the caller.
+   *
+   * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+   * programming error and will lead to data corruption which will be difficult to debug.
+   *
+   * @param value the bytes to be written. Upon returning from this call, the {@code position} of
+   * this buffer will be set to the {@code limit}
+   * @throws IOException thrown if an error occurred while writing
+   */
+  public abstract void write(ByteBuffer value) throws IOException;
+
+  /**
+   * Writes a sequence of bytes. The {@link ByteOutput} is free to retain a reference to the value
+   * beyond the scope of this method call (e.g. write later) since it is considered immutable and is
+   * guaranteed not to change by the caller.
+   *
+   * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+   * programming error and will lead to data corruption which will be difficult to debug.
+   *
+   * @param value the bytes to be written. Upon returning from this call, the {@code position} of
+   * this buffer will be set to the {@code limit}
+   * @throws IOException thrown if an error occurred while writing
+   */
+  public abstract void writeLazy(ByteBuffer value) throws IOException;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteString.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteString.java
new file mode 100644
index 0000000..62c9450
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -0,0 +1,1544 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Immutable sequence of bytes.  Substring is supported by sharing the reference
+ * to the immutable underlying bytes, as with {@link String}.  Concatenation is
+ * likewise supported without copying (long strings) by building a tree of
+ * pieces in {@link RopeByteString}.
+ * <p>
+ * Like {@link String}, the contents of a {@link ByteString} can never be
+ * observed to change, not even in the presence of a data race or incorrect
+ * API usage in the client code.
+ *
+ * @author crazybob@google.com Bob Lee
+ * @author kenton@google.com Kenton Varda
+ * @author carlanton@google.com Carl Haverl
+ * @author martinrb@google.com Martin Buchholz
+ */
+public abstract class ByteString implements Iterable<Byte>, Serializable {
+
+  /**
+   * When two strings to be concatenated have a combined length shorter than
+   * this, we just copy their bytes on {@link #concat(ByteString)}.
+   * The trade-off is copy size versus the overhead of creating tree nodes
+   * in {@link RopeByteString}.
+   */
+  static final int CONCATENATE_BY_COPY_SIZE = 128;
+
+  /**
+   * When copying an InputStream into a ByteString with .readFrom(),
+   * the chunks in the underlying rope start at 256 bytes, but double
+   * each iteration up to 8192 bytes.
+   */
+  static final int MIN_READ_FROM_CHUNK_SIZE = 0x100;  // 256b
+  static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000;  // 8k
+
+  /**
+   * Empty {@code ByteString}.
+   */
+  public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
+  
+  /** 
+   * An interface to efficiently copy {@code byte[]}.
+   * 
+   * <p>One of the noticable costs of copying a byte[] into a new array using 
+   * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown 
+   * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this
+   * expensive nullification and provide substantial performance gain. Unfortunately this does not
+   * hold on Android runtimes and could make the copy slightly slower due to additional code in
+   * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier
+   * for Hotspot and Android runtimes. 
+   */
+  private interface ByteArrayCopier {
+    /**
+     * Copies the specified range of the specified array into a new array
+     */
+    byte[] copyFrom(byte[] bytes, int offset, int size);
+  }
+  
+  /** Implementation of {@code ByteArrayCopier} which uses {@link System#arraycopy}. */
+  private static final class SystemByteArrayCopier implements ByteArrayCopier {
+    @Override
+    public byte[] copyFrom(byte[] bytes, int offset, int size) {
+      byte[] copy = new byte[size];
+      System.arraycopy(bytes, offset, copy, 0, size);
+      return copy;
+    }
+  }
+  
+  /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfRange}. */
+  private static final class ArraysByteArrayCopier implements ByteArrayCopier {
+    @Override
+    public byte[] copyFrom(byte[] bytes, int offset, int size) {
+      return Arrays.copyOfRange(bytes, offset, offset + size);
+    }
+  }
+  
+  private static final ByteArrayCopier byteArrayCopier;
+  static {
+    boolean isAndroid = true;
+    try {
+      Class.forName("android.content.Context");
+    } catch (ClassNotFoundException e) {
+      isAndroid = false;
+    }
+    
+    byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
+  }
+
+  /**
+   * Cached hash value. Intentionally accessed via a data race, which
+   * is safe because of the Java Memory Model's "no out-of-thin-air values"
+   * guarantees for ints. A value of 0 implies that the hash has not been set.
+   */
+  private int hash = 0;
+
+  // This constructor is here to prevent subclassing outside of this package,
+  ByteString() {}
+
+  /**
+   * Gets the byte at the given index. This method should be used only for
+   * random access to individual bytes. To access bytes sequentially, use the
+   * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
+   * #substring(int, int)} first if necessary.
+   *
+   * @param index index of byte
+   * @return the value
+   * @throws IndexOutOfBoundsException {@code index < 0 or index >= size}
+   */
+  public abstract byte byteAt(int index);
+
+  /**
+   * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
+   * To avoid auto-boxing, you may get the iterator manually and call
+   * {@link ByteIterator#nextByte()}.
+   *
+   * @return the iterator
+   */
+  @Override
+  public final ByteIterator iterator() {
+    return new ByteIterator() {
+      private int position = 0;
+      private final int limit = size();
+
+      @Override
+      public boolean hasNext() {
+        return position < limit;
+      }
+
+      @Override
+      public Byte next() {
+        // Boxing calls Byte.valueOf(byte), which does not instantiate.
+        return nextByte();
+      }
+
+      @Override
+      public byte nextByte() {
+        try {
+          return byteAt(position++);
+        } catch (IndexOutOfBoundsException e) {
+          throw new NoSuchElementException(e.getMessage());
+        }
+      }
+
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+
+  /**
+   * This interface extends {@code Iterator<Byte>}, so that we can return an
+   * unboxed {@code byte}.
+   */
+  public interface ByteIterator extends Iterator<Byte> {
+    /**
+     * An alternative to {@link Iterator#next()} that returns an
+     * unboxed primitive {@code byte}.
+     *
+     * @return the next {@code byte} in the iteration
+     * @throws NoSuchElementException if the iteration has no more elements
+     */
+    byte nextByte();
+  }
+
+  /**
+   * Gets the number of bytes.
+   *
+   * @return size in bytes
+   */
+  public abstract int size();
+
+  /**
+   * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
+   *
+   * @return true if this is zero bytes long
+   */
+  public final boolean isEmpty() {
+    return size() == 0;
+  }
+
+  // =================================================================
+  // ByteString -> substring
+
+  /**
+   * Return the substring from {@code beginIndex}, inclusive, to the end of the
+   * string.
+   *
+   * @param beginIndex start at this index
+   * @return substring sharing underlying data
+   * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
+   *     {@code beginIndex > size()}.
+   */
+  public final ByteString substring(int beginIndex) {
+    return substring(beginIndex, size());
+  }
+
+  /**
+   * Return the substring from {@code beginIndex}, inclusive, to {@code
+   * endIndex}, exclusive.
+   *
+   * @param beginIndex start at this index
+   * @param endIndex   the last character is the one before this index
+   * @return substring sharing underlying data
+   * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
+   *     {@code endIndex > size()}, or {@code beginIndex > endIndex}.
+   */
+  public abstract ByteString substring(int beginIndex, int endIndex);
+
+  /**
+   * Tests if this bytestring starts with the specified prefix.
+   * Similar to {@link String#startsWith(String)}
+   *
+   * @param prefix the prefix.
+   * @return <code>true</code> if the byte sequence represented by the
+   *         argument is a prefix of the byte sequence represented by
+   *         this string; <code>false</code> otherwise.
+   */
+  public final boolean startsWith(ByteString prefix) {
+    return size() >= prefix.size() &&
+           substring(0, prefix.size()).equals(prefix);
+  }
+
+  /**
+   * Tests if this bytestring ends with the specified suffix.
+   * Similar to {@link String#endsWith(String)}
+   *
+   * @param suffix the suffix.
+   * @return <code>true</code> if the byte sequence represented by the
+   *         argument is a suffix of the byte sequence represented by
+   *         this string; <code>false</code> otherwise.
+   */
+  public final boolean endsWith(ByteString suffix) {
+    return size() >= suffix.size() &&
+        substring(size() - suffix.size()).equals(suffix);
+  }
+
+  // =================================================================
+  // byte[] -> ByteString
+
+  /**
+   * Copies the given bytes into a {@code ByteString}.
+   *
+   * @param bytes source array
+   * @param offset offset in source array
+   * @param size number of bytes to copy
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(byte[] bytes, int offset, int size) {
+    return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
+  }
+
+  /**
+   * Copies the given bytes into a {@code ByteString}.
+   *
+   * @param bytes to copy
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(byte[] bytes) {
+    return copyFrom(bytes, 0, bytes.length);
+  }
+  
+  /**
+   * Wraps the given bytes into a {@code ByteString}. Intended for internal only
+   * usage to force a classload of ByteString before LiteralByteString.
+   */
+  static ByteString wrap(byte[] bytes) {
+    // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
+    return new LiteralByteString(bytes);
+  }
+
+  /**
+   * Wraps the given bytes into a {@code ByteString}. Intended for internal only
+   * usage to force a classload of ByteString before BoundedByteString and
+   * LiteralByteString.
+   */
+  static ByteString wrap(byte[] bytes, int offset, int length) {
+    return new BoundedByteString(bytes, offset, length);
+  }
+
+  /**
+   * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
+   * a {@code ByteString}.
+   *
+   * @param bytes source buffer
+   * @param size number of bytes to copy
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(ByteBuffer bytes, int size) {
+    byte[] copy = new byte[size];
+    bytes.get(copy);
+    return new LiteralByteString(copy);
+  }
+
+  /**
+   * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
+   * a {@code ByteString}.
+   *
+   * @param bytes sourceBuffer
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(ByteBuffer bytes) {
+    return copyFrom(bytes, bytes.remaining());
+  }
+
+  /**
+   * Encodes {@code text} into a sequence of bytes using the named charset
+   * and returns the result as a {@code ByteString}.
+   *
+   * @param text source string
+   * @param charsetName encoding to use
+   * @return new {@code ByteString}
+   * @throws UnsupportedEncodingException if the encoding isn't found
+   */
+  public static ByteString copyFrom(String text, String charsetName)
+      throws UnsupportedEncodingException {
+    return new LiteralByteString(text.getBytes(charsetName));
+  }
+
+  /**
+   * Encodes {@code text} into a sequence of bytes using the named charset
+   * and returns the result as a {@code ByteString}.
+   *
+   * @param text source string
+   * @param charset encode using this charset
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(String text, Charset charset) {
+    return new LiteralByteString(text.getBytes(charset));
+  }
+
+  /**
+   * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
+   * result as a {@code ByteString}.
+   *
+   * @param text source string
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFromUtf8(String text) {
+    return new LiteralByteString(text.getBytes(Internal.UTF_8));
+  }
+
+  // =================================================================
+  // InputStream -> ByteString
+
+  /**
+   * Completely reads the given stream's bytes into a
+   * {@code ByteString}, blocking if necessary until all bytes are
+   * read through to the end of the stream.
+   *
+   * <b>Performance notes:</b> The returned {@code ByteString} is an
+   * immutable tree of byte arrays ("chunks") of the stream data.  The
+   * first chunk is small, with subsequent chunks each being double
+   * the size, up to 8K.
+   * 
+   * <p>Each byte read from the input stream will be copied twice to ensure
+   * that the resulting ByteString is truly immutable.
+   *
+   * @param streamToDrain The source stream, which is read completely
+   *     but not closed.
+   * @return A new {@code ByteString} which is made up of chunks of
+   *     various sizes, depending on the behavior of the underlying
+   *     stream.
+   * @throws IOException IOException is thrown if there is a problem
+   *     reading the underlying stream.
+   */
+  public static ByteString readFrom(InputStream streamToDrain)
+      throws IOException {
+    return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
+  }
+
+  /**
+   * Completely reads the given stream's bytes into a
+   * {@code ByteString}, blocking if necessary until all bytes are
+   * read through to the end of the stream.
+   *
+   * <b>Performance notes:</b> The returned {@code ByteString} is an
+   * immutable tree of byte arrays ("chunks") of the stream data.  The
+   * chunkSize parameter sets the size of these byte arrays.
+   *
+   * <p>Each byte read from the input stream will be copied twice to ensure
+   * that the resulting ByteString is truly immutable.
+   *
+   * @param streamToDrain The source stream, which is read completely
+   *     but not closed.
+   * @param chunkSize The size of the chunks in which to read the
+   *     stream.
+   * @return A new {@code ByteString} which is made up of chunks of
+   *     the given size.
+   * @throws IOException IOException is thrown if there is a problem
+   *     reading the underlying stream.
+   */
+  public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
+      throws IOException {
+    return readFrom(streamToDrain, chunkSize, chunkSize);
+  }
+
+  // Helper method that takes the chunk size range as a parameter.
+  public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
+      int maxChunkSize) throws IOException {
+    Collection<ByteString> results = new ArrayList<ByteString>();
+
+    // copy the inbound bytes into a list of chunks; the chunk size
+    // grows exponentially to support both short and long streams.
+    int chunkSize = minChunkSize;
+    while (true) {
+      ByteString chunk = readChunk(streamToDrain, chunkSize);
+      if (chunk == null) {
+        break;
+      }
+      results.add(chunk);
+      chunkSize = Math.min(chunkSize * 2, maxChunkSize);
+    }
+
+    return ByteString.copyFrom(results);
+  }
+
+  /**
+   * Blocks until a chunk of the given size can be made from the
+   * stream, or EOF is reached.  Calls read() repeatedly in case the
+   * given stream implementation doesn't completely fill the given
+   * buffer in one read() call.
+   *
+   * @return A chunk of the desired size, or else a chunk as large as
+   * was available when end of stream was reached. Returns null if the
+   * given stream had no more data in it.
+   */
+  private static ByteString readChunk(InputStream in, final int chunkSize)
+      throws IOException {
+      final byte[] buf = new byte[chunkSize];
+      int bytesRead = 0;
+      while (bytesRead < chunkSize) {
+        final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
+        if (count == -1) {
+          break;
+        }
+        bytesRead += count;
+      }
+
+      if (bytesRead == 0) {
+        return null;
+      }
+
+      // Always make a copy since InputStream could steal a reference to buf.
+      return ByteString.copyFrom(buf, 0, bytesRead);
+  }
+
+  // =================================================================
+  // Multiple ByteStrings -> One ByteString
+
+  /**
+   * Concatenate the given {@code ByteString} to this one. Short concatenations,
+   * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
+   * produced by copying the underlying bytes (as per Rope.java, <a
+   * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+   * BAP95 </a>. In general, the concatenate involves no copying.
+   *
+   * @param other string to concatenate
+   * @return a new {@code ByteString} instance
+   */
+  public final ByteString concat(ByteString other) {
+    if (Integer.MAX_VALUE - size() < other.size()) {
+      throw new IllegalArgumentException("ByteString would be too long: " +
+          size() + "+" + other.size());
+    }
+
+    return RopeByteString.concatenate(this, other);
+  }
+
+  /**
+   * Concatenates all byte strings in the iterable and returns the result.
+   * This is designed to run in O(list size), not O(total bytes).
+   *
+   * <p>The returned {@code ByteString} is not necessarily a unique object.
+   * If the list is empty, the returned object is the singleton empty
+   * {@code ByteString}.  If the list has only one element, that
+   * {@code ByteString} will be returned without copying.
+   *
+   * @param byteStrings strings to be concatenated
+   * @return new {@code ByteString}
+   */
+  public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
+    // Determine the size;
+    final int size;
+    if (!(byteStrings instanceof Collection)) {
+      int tempSize = 0;
+      for (Iterator<ByteString> iter = byteStrings.iterator(); iter.hasNext();
+          iter.next(), ++tempSize) {
+      }
+      size = tempSize;
+    } else {
+      size = ((Collection<ByteString>) byteStrings).size();
+    }
+
+    if (size == 0) {
+      return EMPTY;
+    }
+
+    return balancedConcat(byteStrings.iterator(), size);
+  }
+
+  // Internal function used by copyFrom(Iterable<ByteString>).
+  // Create a balanced concatenation of the next "length" elements from the
+  // iterable.
+  private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
+    assert length >= 1;
+    ByteString result;
+    if (length == 1) {
+      result = iterator.next();
+    } else {
+      int halfLength = length >>> 1;
+      ByteString left = balancedConcat(iterator, halfLength);
+      ByteString right = balancedConcat(iterator, length - halfLength);
+      result = left.concat(right);
+    }
+    return result;
+  }
+
+  // =================================================================
+  // ByteString -> byte[]
+
+  /**
+   * Copies bytes into a buffer at the given offset.
+   *
+   * @param target buffer to copy into
+   * @param offset in the target buffer
+   * @throws IndexOutOfBoundsException if the offset is negative or too large
+   */
+  public void copyTo(byte[] target, int offset) {
+    copyTo(target, 0, offset, size());
+  }
+
+  /**
+   * Copies bytes into a buffer.
+   *
+   * @param target       buffer to copy into
+   * @param sourceOffset offset within these bytes
+   * @param targetOffset offset within the target buffer
+   * @param numberToCopy number of bytes to copy
+   * @throws IndexOutOfBoundsException if an offset or size is negative or too
+   *     large
+   */
+  public final void copyTo(byte[] target, int sourceOffset, int targetOffset,
+      int numberToCopy) {
+    checkRange(sourceOffset, sourceOffset + numberToCopy, size());
+    checkRange(targetOffset, targetOffset + numberToCopy, target.length);
+    if (numberToCopy > 0) {
+      copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+    }
+  }
+
+  /**
+   * Internal (package private) implementation of
+   * {@link #copyTo(byte[],int,int,int)}.
+   * It assumes that all error checking has already been performed and that
+   * {@code numberToCopy > 0}.
+   */
+  protected abstract void copyToInternal(byte[] target, int sourceOffset,
+      int targetOffset, int numberToCopy);
+
+  /**
+   * Copies bytes into a ByteBuffer.
+   *
+   * @param target ByteBuffer to copy into.
+   * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
+   * @throws java.nio.BufferOverflowException if the {@code target}'s
+   *     remaining() space is not large enough to hold the data.
+   */
+  public abstract void copyTo(ByteBuffer target);
+
+  /**
+   * Copies bytes to a {@code byte[]}.
+   *
+   * @return copied bytes
+   */
+  public final byte[] toByteArray() {
+    final int size = size();
+    if (size == 0) {
+      return Internal.EMPTY_BYTE_ARRAY;
+    }
+    byte[] result = new byte[size];
+    copyToInternal(result, 0, 0, size);
+    return result;
+  }
+
+  /**
+   * Writes a copy of the contents of this byte string to the specified output stream argument.
+   *
+   * @param  out  the output stream to which to write the data.
+   * @throws IOException  if an I/O error occurs.
+   */
+  public abstract void writeTo(OutputStream out) throws IOException;
+
+  /**
+   * Writes a specified part of this byte string to an output stream.
+   *
+   * @param  out  the output stream to which to write the data.
+   * @param  sourceOffset offset within these bytes
+   * @param  numberToWrite number of bytes to write
+   * @throws IOException  if an I/O error occurs.
+   * @throws IndexOutOfBoundsException if an offset or size is negative or too large
+   */
+  final void writeTo(OutputStream out, int sourceOffset, int numberToWrite)
+      throws IOException {
+    checkRange(sourceOffset, sourceOffset + numberToWrite, size());
+    if (numberToWrite > 0) {
+      writeToInternal(out, sourceOffset, numberToWrite);
+    }
+  }
+
+  /**
+   * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes
+   * all error checking has already been done.
+   */
+  abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)
+      throws IOException;
+
+  /**
+   * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling
+   * this method may result in multiple operations on the target {@link ByteOutput}.
+   *
+   * <p>This method may expose internal backing buffers of the {@link ByteString} to the {@link
+   * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
+   * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
+   *
+   * @param  byteOutput  the output target to receive the bytes
+   * @throws IOException  if an I/O error occurs
+   * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput)
+   */
+  abstract void writeTo(ByteOutput byteOutput) throws IOException;
+
+  /**
+   * Constructs a read-only {@code java.nio.ByteBuffer} whose content
+   * is equal to the contents of this byte string.
+   * The result uses the same backing array as the byte string, if possible.
+   *
+   * @return wrapped bytes
+   */
+  public abstract ByteBuffer asReadOnlyByteBuffer();
+
+  /**
+   * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
+   * such that the concatenation of their contents is equal to the contents
+   * of this byte string.  The result uses the same backing arrays as the
+   * byte string.
+   * <p>
+   * By returning a list, implementations of this method may be able to avoid
+   * copying even when there are multiple backing arrays.
+   *
+   * @return a list of wrapped bytes
+   */
+  public abstract List<ByteBuffer> asReadOnlyByteBufferList();
+
+  /**
+   * Constructs a new {@code String} by decoding the bytes using the
+   * specified charset.
+   *
+   * @param charsetName encode using this charset
+   * @return new string
+   * @throws UnsupportedEncodingException if charset isn't recognized
+   */
+  public final String toString(String charsetName)
+      throws UnsupportedEncodingException {
+    try {
+      return toString(Charset.forName(charsetName));
+    } catch (UnsupportedCharsetException e) {
+      UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName);
+      exception.initCause(e);
+      throw exception;
+    }
+  }
+
+  /**
+   * Constructs a new {@code String} by decoding the bytes using the
+   * specified charset. Returns the same empty String if empty.
+   *
+   * @param charset encode using this charset
+   * @return new string
+   */
+  public final String toString(Charset charset) {
+    return size() == 0 ? "" : toStringInternal(charset);
+  }
+
+  /**
+   * Constructs a new {@code String} by decoding the bytes using the
+   * specified charset.
+   *
+   * @param charset encode using this charset
+   * @return new string
+   */
+  protected abstract String toStringInternal(Charset charset);
+
+  // =================================================================
+  // UTF-8 decoding
+
+  /**
+   * Constructs a new {@code String} by decoding the bytes as UTF-8.
+   *
+   * @return new string using UTF-8 encoding
+   */
+  public final String toStringUtf8() {
+    return toString(Internal.UTF_8);
+  }
+
+  /**
+   * Tells whether this {@code ByteString} represents a well-formed UTF-8
+   * byte sequence, such that the original bytes can be converted to a
+   * String object and then round tripped back to bytes without loss.
+   *
+   * <p>More precisely, returns {@code true} whenever: <pre> {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }</pre>
+   *
+   * <p>This method returns {@code false} for "overlong" byte sequences,
+   * as well as for 3-byte sequences that would map to a surrogate
+   * character, in accordance with the restricted definition of UTF-8
+   * introduced in Unicode 3.1.  Note that the UTF-8 decoder included in
+   * Oracle's JDK has been modified to also reject "overlong" byte
+   * sequences, but (as of 2011) still accepts 3-byte surrogate
+   * character byte sequences.
+   *
+   * <p>See the Unicode Standard,<br>
+   * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
+   * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+   *
+   * @return whether the bytes in this {@code ByteString} are a
+   * well-formed UTF-8 byte sequence
+   */
+  public abstract boolean isValidUtf8();
+
+  /**
+   * Tells whether the given byte sequence is a well-formed, malformed, or
+   * incomplete UTF-8 byte sequence.  This method accepts and returns a partial
+   * state result, allowing the bytes for a complete UTF-8 byte sequence to be
+   * composed from multiple {@code ByteString} segments.
+   *
+   * @param state either {@code 0} (if this is the initial decoding operation)
+   *     or the value returned from a call to a partial decoding method for the
+   *     previous bytes
+   * @param offset offset of the first byte to check
+   * @param length number of bytes to check
+   *
+   * @return {@code -1} if the partial byte sequence is definitely malformed,
+   * {@code 0} if it is well-formed (no additional input needed), or, if the
+   * byte sequence is "incomplete", i.e. apparently terminated in the middle of
+   * a character, an opaque integer "state" value containing enough information
+   * to decode the character when passed to a subsequent invocation of a
+   * partial decoding method.
+   */
+  protected abstract int partialIsValidUtf8(int state, int offset, int length);
+
+  // =================================================================
+  // equals() and hashCode()
+
+  @Override
+  public abstract boolean equals(Object o);
+
+  /**
+   * Base class for leaf {@link ByteString}s (i.e. non-ropes).
+   */
+  abstract static class LeafByteString extends ByteString {
+    @Override
+    protected final int getTreeDepth() {
+      return 0;
+    }
+
+    @Override
+    protected final boolean isBalanced() {
+      return true;
+    }
+
+    /**
+     * Check equality of the substring of given length of this object starting at
+     * zero with another {@code ByteString} substring starting at offset.
+     *
+     * @param other  what to compare a substring in
+     * @param offset offset into other
+     * @param length number of bytes to compare
+     * @return true for equality of substrings, else false.
+     */
+    abstract boolean equalsRange(ByteString other, int offset, int length);
+  }
+
+  /**
+   * Compute the hashCode using the traditional algorithm from {@link
+   * ByteString}.
+   *
+   * @return hashCode value
+   */
+  @Override
+  public final int hashCode() {
+    int h = hash;
+
+    if (h == 0) {
+      int size = size();
+      h = partialHash(size, 0, size);
+      if (h == 0) {
+        h = 1;
+      }
+      hash = h;
+    }
+    return h;
+  }
+
+  // =================================================================
+  // Input stream
+
+  /**
+   * Creates an {@code InputStream} which can be used to read the bytes.
+   * <p>
+   * The {@link InputStream} returned by this method is guaranteed to be
+   * completely non-blocking.  The method {@link InputStream#available()}
+   * returns the number of bytes remaining in the stream. The methods
+   * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
+   * and {@link InputStream#skip(long)} will read/skip as many bytes as are
+   * available.  The method {@link InputStream#markSupported()} returns
+   * {@code true}.
+   * <p>
+   * The methods in the returned {@link InputStream} might <b>not</b> be
+   * thread safe.
+   *
+   * @return an input stream that returns the bytes of this byte string.
+   */
+  public abstract InputStream newInput();
+
+  /**
+   * Creates a {@link CodedInputStream} which can be used to read the bytes.
+   * Using this is often more efficient than creating a {@link CodedInputStream}
+   * that wraps the result of {@link #newInput()}.
+   *
+   * @return stream based on wrapped data
+   */
+  public abstract CodedInputStream newCodedInput();
+
+  // =================================================================
+  // Output stream
+
+  /**
+   * Creates a new {@link Output} with the given initial capacity. Call {@link
+   * Output#toByteString()} to create the {@code ByteString} instance.
+   * <p>
+   * A {@link ByteString.Output} offers the same functionality as a
+   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+   * rather than a {@code byte} array.
+   *
+   * @param initialCapacity estimate of number of bytes to be written
+   * @return {@code OutputStream} for building a {@code ByteString}
+   */
+  public static Output newOutput(int initialCapacity) {
+    return new Output(initialCapacity);
+  }
+
+  /**
+   * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
+   * the {@code ByteString} instance.
+   * <p>
+   * A {@link ByteString.Output} offers the same functionality as a
+   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+   * rather than a {@code byte array}.
+   *
+   * @return {@code OutputStream} for building a {@code ByteString}
+   */
+  public static Output newOutput() {
+    return new Output(CONCATENATE_BY_COPY_SIZE);
+  }
+
+  /**
+   * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
+   * create the {@code ByteString} instance.
+   */
+  public static final class Output extends OutputStream {
+    // Implementation note.
+    // The public methods of this class must be synchronized.  ByteStrings
+    // are guaranteed to be immutable.  Without some sort of locking, it could
+    // be possible for one thread to call toByteSring(), while another thread
+    // is still modifying the underlying byte array.
+
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+    // argument passed by user, indicating initial capacity.
+    private final int initialCapacity;
+    // ByteStrings to be concatenated to create the result
+    private final ArrayList<ByteString> flushedBuffers;
+    // Total number of bytes in the ByteStrings of flushedBuffers
+    private int flushedBuffersTotalBytes;
+    // Current buffer to which we are writing
+    private byte[] buffer;
+    // Location in buffer[] to which we write the next byte.
+    private int bufferPos;
+
+    /**
+     * Creates a new ByteString output stream with the specified
+     * initial capacity.
+     *
+     * @param initialCapacity  the initial capacity of the output stream.
+     */
+    Output(int initialCapacity) {
+      if (initialCapacity < 0) {
+        throw new IllegalArgumentException("Buffer size < 0");
+      }
+      this.initialCapacity = initialCapacity;
+      this.flushedBuffers = new ArrayList<ByteString>();
+      this.buffer = new byte[initialCapacity];
+    }
+
+    @Override
+    public synchronized void write(int b) {
+      if (bufferPos == buffer.length) {
+        flushFullBuffer(1);
+      }
+      buffer[bufferPos++] = (byte)b;
+    }
+
+    @Override
+    public synchronized void write(byte[] b, int offset, int length)  {
+      if (length <= buffer.length - bufferPos) {
+        // The bytes can fit into the current buffer.
+        System.arraycopy(b, offset, buffer, bufferPos, length);
+        bufferPos += length;
+      } else {
+        // Use up the current buffer
+        int copySize  = buffer.length - bufferPos;
+        System.arraycopy(b, offset, buffer, bufferPos, copySize);
+        offset += copySize;
+        length -= copySize;
+        // Flush the buffer, and get a new buffer at least big enough to cover
+        // what we still need to output
+        flushFullBuffer(length);
+        System.arraycopy(b, offset, buffer, 0 /* count */, length);
+        bufferPos = length;
+      }
+    }
+
+    /**
+     * Creates a byte string. Its size is the current size of this output
+     * stream and its output has been copied to it.
+     *
+     * @return  the current contents of this output stream, as a byte string.
+     */
+    public synchronized ByteString toByteString() {
+      flushLastBuffer();
+      return ByteString.copyFrom(flushedBuffers);
+    }
+
+    /**
+     * Implement java.util.Arrays.copyOf() for jdk 1.5.
+     */
+    private byte[] copyArray(byte[] buffer, int length) {
+      byte[] result = new byte[length];
+      System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
+      return result;
+    }
+
+    /**
+     * Writes the complete contents of this byte array output stream to
+     * the specified output stream argument.
+     *
+     * @param out the output stream to which to write the data.
+     * @throws IOException  if an I/O error occurs.
+     */
+    public void writeTo(OutputStream out) throws IOException {
+      ByteString[] cachedFlushBuffers;
+      byte[] cachedBuffer;
+      int cachedBufferPos;
+      synchronized (this) {
+        // Copy the information we need into local variables so as to hold
+        // the lock for as short a time as possible.
+        cachedFlushBuffers =
+            flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
+        cachedBuffer = buffer;
+        cachedBufferPos = bufferPos;
+      }
+      for (ByteString byteString : cachedFlushBuffers) {
+        byteString.writeTo(out);
+      }
+
+      out.write(copyArray(cachedBuffer, cachedBufferPos));
+    }
+
+    /**
+     * Returns the current size of the output stream.
+     *
+     * @return  the current size of the output stream
+     */
+    public synchronized int size() {
+      return flushedBuffersTotalBytes + bufferPos;
+    }
+
+    /**
+     * Resets this stream, so that all currently accumulated output in the
+     * output stream is discarded. The output stream can be used again,
+     * reusing the already allocated buffer space.
+     */
+    public synchronized void reset() {
+      flushedBuffers.clear();
+      flushedBuffersTotalBytes = 0;
+      bufferPos = 0;
+    }
+
+    @Override
+    public String toString() {
+      return String.format("<ByteString.Output@%s size=%d>",
+          Integer.toHexString(System.identityHashCode(this)), size());
+    }
+
+    /**
+     * Internal function used by writers.  The current buffer is full, and the
+     * writer needs a new buffer whose size is at least the specified minimum
+     * size.
+     */
+    private void flushFullBuffer(int minSize)  {
+      flushedBuffers.add(new LiteralByteString(buffer));
+      flushedBuffersTotalBytes += buffer.length;
+      // We want to increase our total capacity by 50%, but as a minimum,
+      // the new buffer should also at least be >= minSize and
+      // >= initial Capacity.
+      int newSize = Math.max(initialCapacity,
+          Math.max(minSize, flushedBuffersTotalBytes >>> 1));
+      buffer = new byte[newSize];
+      bufferPos = 0;
+    }
+
+    /**
+     * Internal function used by {@link #toByteString()}. The current buffer may
+     * or may not be full, but it needs to be flushed.
+     */
+    private void flushLastBuffer()  {
+      if (bufferPos < buffer.length) {
+        if (bufferPos > 0) {
+          byte[] bufferCopy = copyArray(buffer, bufferPos);
+          flushedBuffers.add(new LiteralByteString(bufferCopy));
+        }
+        // We reuse this buffer for further writes.
+      } else {
+        // Buffer is completely full.  Huzzah.
+        flushedBuffers.add(new LiteralByteString(buffer));
+        // 99% of the time, we're not going to use this OutputStream again.
+        // We set buffer to an empty byte stream so that we're handling this
+        // case without wasting space.  In the rare case that more writes
+        // *do* occur, this empty buffer will be flushed and an appropriately
+        // sized new buffer will be created.
+        buffer = EMPTY_BYTE_ARRAY;
+      }
+      flushedBuffersTotalBytes += bufferPos;
+      bufferPos = 0;
+    }
+  }
+
+  /**
+   * Constructs a new {@code ByteString} builder, which allows you to
+   * efficiently construct a {@code ByteString} by writing to a {@link
+   * CodedOutputStream}. Using this is much more efficient than calling {@code
+   * newOutput()} and wrapping that in a {@code CodedOutputStream}.
+   *
+   * <p>This is package-private because it's a somewhat confusing interface.
+   * Users can call {@link Message#toByteString()} instead of calling this
+   * directly.
+   *
+   * @param size The target byte size of the {@code ByteString}.  You must write
+   *     exactly this many bytes before building the result.
+   * @return the builder
+   */
+  static CodedBuilder newCodedBuilder(int size) {
+    return new CodedBuilder(size);
+  }
+
+  /** See {@link ByteString#newCodedBuilder(int)}. */
+  static final class CodedBuilder {
+    private final CodedOutputStream output;
+    private final byte[] buffer;
+
+    private CodedBuilder(int size) {
+      buffer = new byte[size];
+      output = CodedOutputStream.newInstance(buffer);
+    }
+
+    public ByteString build() {
+      output.checkNoSpaceLeft();
+
+      // We can be confident that the CodedOutputStream will not modify the
+      // underlying bytes anymore because it already wrote all of them.  So,
+      // no need to make a copy.
+      return new LiteralByteString(buffer);
+    }
+
+    public CodedOutputStream getCodedOutput() {
+      return output;
+    }
+  }
+
+  // =================================================================
+  // Methods {@link RopeByteString} needs on instances, which aren't part of the
+  // public API.
+
+  /**
+   * Return the depth of the tree representing this {@code ByteString}, if any,
+   * whose root is this node. If this is a leaf node, return 0.
+   *
+   * @return tree depth or zero
+   */
+  protected abstract int getTreeDepth();
+
+  /**
+   * Return {@code true} if this ByteString is literal (a leaf node) or a
+   * flat-enough tree in the sense of {@link RopeByteString}.
+   *
+   * @return true if the tree is flat enough
+   */
+  protected abstract boolean isBalanced();
+
+  /**
+   * Return the cached hash code if available.
+   *
+   * @return value of cached hash code or 0 if not computed yet
+   */
+  protected final int peekCachedHashCode() {
+    return hash;
+  }
+
+  /**
+   * Compute the hash across the value bytes starting with the given hash, and
+   * return the result.  This is used to compute the hash across strings
+   * represented as a set of pieces by allowing the hash computation to be
+   * continued from piece to piece.
+   *
+   * @param h starting hash value
+   * @param offset offset into this value to start looking at data values
+   * @param length number of data values to include in the hash computation
+   * @return ending hash value
+   */
+  protected abstract int partialHash(int h, int offset, int length);
+
+  /**
+   * Checks that the given index falls within the specified array size.
+   *
+   * @param index the index position to be tested
+   * @param size the length of the array
+   * @throws IndexOutOfBoundsException if the index does not fall within the array.
+   */
+  static void checkIndex(int index, int size) {
+    if ((index | (size - (index + 1))) < 0) {
+      if (index < 0) {
+        throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
+      }
+      throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size);
+    }
+  }
+
+  /**
+   * Checks that the given range falls within the bounds of an array
+   *
+   * @param startIndex the start index of the range (inclusive)
+   * @param endIndex the end index of the range (exclusive)
+   * @param size the size of the array.
+   * @return the length of the range.
+   * @throws IndexOutOfBoundsException some or all of the range falls outside of the array.
+   */
+  static int checkRange(int startIndex, int endIndex, int size) {
+    final int length = endIndex - startIndex;
+    if ((startIndex | endIndex | length | (size - endIndex)) < 0) {
+      if (startIndex < 0) {
+        throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0");
+      }
+      if (endIndex < startIndex) {
+        throw new IndexOutOfBoundsException(
+            "Beginning index larger than ending index: " + startIndex + ", " + endIndex);
+      }
+      // endIndex >= size
+      throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size);
+    }
+    return length;
+  }
+
+  @Override
+  public final String toString() {
+    return String.format("<ByteString@%s size=%d>",
+        Integer.toHexString(System.identityHashCode(this)), size());
+  }
+  
+  /**
+   * This class implements a {@link com.google.protobuf.ByteString} backed by a
+   * single array of bytes, contiguous in memory. It supports substring by
+   * pointing to only a sub-range of the underlying byte array, meaning that a
+   * substring will reference the full byte-array of the string it's made from,
+   * exactly as with {@link String}.
+   *
+   * @author carlanton@google.com (Carl Haverl)
+   */
+  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
+  // static initializer loads LiteralByteString and another thread loads LiteralByteString.
+  private static class LiteralByteString extends ByteString.LeafByteString {
+    private static final long serialVersionUID = 1L;
+
+    protected final byte[] bytes;
+
+    /**
+     * Creates a {@code LiteralByteString} backed by the given array, without
+     * copying.
+     *
+     * @param bytes array to wrap
+     */
+    LiteralByteString(byte[] bytes) {
+      this.bytes = bytes;
+    }
+
+    @Override
+    public byte byteAt(int index) {
+      // Unlike most methods in this class, this one is a direct implementation
+      // ignoring the potential offset because we need to do range-checking in the
+      // substring case anyway.
+      return bytes[index];
+    }
+
+    @Override
+    public int size() {
+      return bytes.length;
+    }
+
+    // =================================================================
+    // ByteString -> substring
+
+    @Override
+    public final ByteString substring(int beginIndex, int endIndex) {
+      final int length = checkRange(beginIndex, endIndex, size());
+
+      if (length == 0) {
+        return ByteString.EMPTY;
+      }
+
+      return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
+    }
+
+    // =================================================================
+    // ByteString -> byte[]
+
+    @Override
+    protected void copyToInternal(
+        byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
+      // Optimized form, not for subclasses, since we don't call
+      // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
+      // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
+      System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
+    }
+
+    @Override
+    public final void copyTo(ByteBuffer target) {
+      target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
+    }
+
+    @Override
+    public final ByteBuffer asReadOnlyByteBuffer() {
+      return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
+    }
+
+    @Override
+    public final List<ByteBuffer> asReadOnlyByteBufferList() {
+      return Collections.singletonList(asReadOnlyByteBuffer());
+    }
+
+    @Override
+    public final void writeTo(OutputStream outputStream) throws IOException {
+      outputStream.write(toByteArray());
+    }
+
+    @Override
+    final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
+        throws IOException {
+      outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
+    }
+
+    @Override
+    final void writeTo(ByteOutput output) throws IOException {
+      output.writeLazy(bytes, getOffsetIntoBytes(), size());
+    }
+
+    @Override
+    protected final String toStringInternal(Charset charset) {
+      return new String(bytes, getOffsetIntoBytes(), size(), charset);
+    }
+
+    // =================================================================
+    // UTF-8 decoding
+
+    @Override
+    public final boolean isValidUtf8() {
+      int offset = getOffsetIntoBytes();
+      return Utf8.isValidUtf8(bytes, offset, offset + size());
+    }
+
+    @Override
+    protected final int partialIsValidUtf8(int state, int offset, int length) {
+      int index = getOffsetIntoBytes() + offset;
+      return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
+    }
+
+    // =================================================================
+    // equals() and hashCode()
+
+    @Override
+    public final boolean equals(Object other) {
+      if (other == this) {
+        return true;
+      }
+      if (!(other instanceof ByteString)) {
+        return false;
+      }
+
+      if (size() != ((ByteString) other).size()) {
+        return false;
+      }
+      if (size() == 0) {
+        return true;
+      }
+
+      if (other instanceof LiteralByteString) {
+        LiteralByteString otherAsLiteral = (LiteralByteString) other;
+        // If we know the hash codes and they are not equal, we know the byte
+        // strings are not equal.
+        int thisHash = peekCachedHashCode();
+        int thatHash = otherAsLiteral.peekCachedHashCode();
+        if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
+          return false;
+        }
+
+        return equalsRange((LiteralByteString) other, 0, size());
+      } else {
+        // RopeByteString and NioByteString.
+        return other.equals(this);
+      }
+    }
+
+    /**
+     * Check equality of the substring of given length of this object starting at
+     * zero with another {@code LiteralByteString} substring starting at offset.
+     *
+     * @param other  what to compare a substring in
+     * @param offset offset into other
+     * @param length number of bytes to compare
+     * @return true for equality of substrings, else false.
+     */
+    @Override
+    final boolean equalsRange(ByteString other, int offset, int length) {
+      if (length > other.size()) {
+        throw new IllegalArgumentException("Length too large: " + length + size());
+      }
+      if (offset + length > other.size()) {
+        throw new IllegalArgumentException(
+            "Ran off end of other: " + offset + ", " + length + ", " + other.size());
+      }
+
+      if (other instanceof LiteralByteString) {
+        LiteralByteString lbsOther = (LiteralByteString) other;
+        byte[] thisBytes = bytes;
+        byte[] otherBytes = lbsOther.bytes;
+        int thisLimit = getOffsetIntoBytes() + length;
+        for (
+            int thisIndex = getOffsetIntoBytes(),
+                otherIndex = lbsOther.getOffsetIntoBytes() + offset;
+            (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
+          if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+      return other.substring(offset, offset + length).equals(substring(0, length));
+    }
+
+    @Override
+    protected final int partialHash(int h, int offset, int length) {
+      return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length);
+    }
+
+    // =================================================================
+    // Input stream
+
+    @Override
+    public final InputStream newInput() {
+      return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
+    }
+
+    @Override
+    public final CodedInputStream newCodedInput() {
+      // We trust CodedInputStream not to modify the bytes, or to give anyone
+      // else access to them.
+      return CodedInputStream.newInstance(
+          bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */);
+    }
+
+    // =================================================================
+    // Internal methods
+
+    /**
+     * Offset into {@code bytes[]} to use, non-zero for substrings.
+     *
+     * @return always 0 for this class
+     */
+    protected int getOffsetIntoBytes() {
+      return 0;
+    }
+  }
+  
+  /**
+   * This class is used to represent the substring of a {@link ByteString} over a
+   * single byte array. In terms of the public API of {@link ByteString}, you end
+   * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
+   * ByteString#substring(int, int)}.
+   *
+   * <p>This class contains most of the overhead involved in creating a substring
+   * from a {@link LiteralByteString}.  The overhead involves some range-checking
+   * and two extra fields.
+   *
+   * @author carlanton@google.com (Carl Haverl)
+   */
+  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
+  // static initializer loads LiteralByteString and another thread loads BoundedByteString.
+  private static final class BoundedByteString extends LiteralByteString {
+
+    private final int bytesOffset;
+    private final int bytesLength;
+
+    /**
+     * Creates a {@code BoundedByteString} backed by the sub-range of given array,
+     * without copying.
+     *
+     * @param bytes  array to wrap
+     * @param offset index to first byte to use in bytes
+     * @param length number of bytes to use from bytes
+     * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
+     *                                  or if {@code offset + length >
+     *                                  bytes.length}.
+     */
+    BoundedByteString(byte[] bytes, int offset, int length) {
+      super(bytes);
+      checkRange(offset, offset + length, bytes.length);
+
+      this.bytesOffset = offset;
+      this.bytesLength = length;
+    }
+
+    /**
+     * Gets the byte at the given index.
+     * Throws {@link ArrayIndexOutOfBoundsException}
+     * for backwards-compatibility reasons although it would more properly be
+     * {@link IndexOutOfBoundsException}.
+     *
+     * @param index index of byte
+     * @return the value
+     * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+     */
+    @Override
+    public byte byteAt(int index) {
+      // We must check the index ourselves as we cannot rely on Java array index
+      // checking for substrings.
+      checkIndex(index, size());
+      return bytes[bytesOffset + index];
+    }
+
+    @Override
+    public int size() {
+      return bytesLength;
+    }
+
+    @Override
+    protected int getOffsetIntoBytes() {
+      return bytesOffset;
+    }
+
+    // =================================================================
+    // ByteString -> byte[]
+
+    @Override
+    protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset,
+        int numberToCopy) {
+      System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
+          targetOffset, numberToCopy);
+    }
+
+    // =================================================================
+    // Serializable
+
+    private static final long serialVersionUID = 1L;
+
+    Object writeReplace() {
+      return ByteString.wrap(toByteArray());
+    }
+
+    private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
+      throw new InvalidObjectException(
+          "BoundedByteStream instances are not to be serialized directly");
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
new file mode 100644
index 0000000..e886065
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -0,0 +1,1302 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Reads and decodes protocol message fields.
+ *
+ * This class contains two kinds of methods:  methods that read specific
+ * protocol message constructs and field types (e.g. {@link #readTag()} and
+ * {@link #readInt32()}) and methods that read low-level values (e.g.
+ * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
+ * encoded protocol messages, you should use the former methods, but if you are
+ * reading some other format of your own design, use the latter.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class CodedInputStream {
+  /**
+   * Create a new CodedInputStream wrapping the given InputStream.
+   */
+  public static CodedInputStream newInstance(final InputStream input) {
+    return new CodedInputStream(input, BUFFER_SIZE);
+  }
+  
+  /**
+   * Create a new CodedInputStream wrapping the given InputStream.
+   */
+  static CodedInputStream newInstance(final InputStream input, int bufferSize) {
+    return new CodedInputStream(input, bufferSize);
+  }
+
+  /**
+   * Create a new CodedInputStream wrapping the given byte array.
+   */
+  public static CodedInputStream newInstance(final byte[] buf) {
+    return newInstance(buf, 0, buf.length);
+  }
+
+  /**
+   * Create a new CodedInputStream wrapping the given byte array slice.
+   */
+  public static CodedInputStream newInstance(final byte[] buf, final int off,
+                                             final int len) {
+    return newInstance(buf, off, len, false /* bufferIsImmutable */);
+  }
+  
+  /**
+   * Create a new CodedInputStream wrapping the given byte array slice.
+   */
+  static CodedInputStream newInstance(
+      final byte[] buf, final int off, final int len, final boolean bufferIsImmutable) {
+    CodedInputStream result = new CodedInputStream(buf, off, len, bufferIsImmutable);
+    try {
+      // Some uses of CodedInputStream can be more efficient if they know
+      // exactly how many bytes are available.  By pushing the end point of the
+      // buffer as a limit, we allow them to get this information via
+      // getBytesUntilLimit().  Pushing a limit that we know is at the end of
+      // the stream can never hurt, since we can never past that point anyway.
+      result.pushLimit(len);
+    } catch (InvalidProtocolBufferException ex) {
+      // The only reason pushLimit() might throw an exception here is if len
+      // is negative. Normally pushLimit()'s parameter comes directly off the
+      // wire, so it's important to catch exceptions in case of corrupt or
+      // malicious data. However, in this case, we expect that len is not a
+      // user-supplied value, so we can assume that it being negative indicates
+      // a programming error. Therefore, throwing an unchecked exception is
+      // appropriate.
+      throw new IllegalArgumentException(ex);
+    }
+    return result;
+  }
+
+  /**
+   * Create a new CodedInputStream wrapping the given ByteBuffer. The data
+   * starting from the ByteBuffer's current position to its limit will be read.
+   * The returned CodedInputStream may or may not share the underlying data
+   * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the
+   * CodedInputStream is in use.
+   * Note that the ByteBuffer's position won't be changed by this function.
+   * Concurrent calls with the same ByteBuffer object are safe if no other
+   * thread is trying to alter the ByteBuffer's status.
+   */
+  public static CodedInputStream newInstance(ByteBuffer buf) {
+    if (buf.hasArray()) {
+      return newInstance(buf.array(), buf.arrayOffset() + buf.position(),
+          buf.remaining());
+    } else {
+      ByteBuffer temp = buf.duplicate();
+      byte[] buffer = new byte[temp.remaining()];
+      temp.get(buffer);
+      return newInstance(buffer);
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  /**
+   * Attempt to read a field tag, returning zero if we have reached EOF.
+   * Protocol message parsers use this to read tags, since a protocol message
+   * may legally end wherever a tag occurs, and zero is not a valid tag number.
+   */
+  public int readTag() throws IOException {
+    if (isAtEnd()) {
+      lastTag = 0;
+      return 0;
+    }
+
+    lastTag = readRawVarint32();
+    if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+      // If we actually read zero (or any tag number corresponding to field
+      // number zero), that's not a valid tag.
+      throw InvalidProtocolBufferException.invalidTag();
+    }
+    return lastTag;
+  }
+
+  /**
+   * Verifies that the last call to readTag() returned the given tag value.
+   * This is used to verify that a nested group ended with the correct
+   * end tag.
+   *
+   * @throws InvalidProtocolBufferException {@code value} does not match the
+   *                                        last tag.
+   */
+  public void checkLastTagWas(final int value)
+                              throws InvalidProtocolBufferException {
+    if (lastTag != value) {
+      throw InvalidProtocolBufferException.invalidEndTag();
+    }
+  }
+
+  public int getLastTag() {
+    return lastTag;
+  }
+
+  /**
+   * Reads and discards a single field, given its tag value.
+   *
+   * @return {@code false} if the tag is an endgroup tag, in which case
+   *         nothing is skipped.  Otherwise, returns {@code true}.
+   */
+  public boolean skipField(final int tag) throws IOException {
+    switch (WireFormat.getTagWireType(tag)) {
+      case WireFormat.WIRETYPE_VARINT:
+        skipRawVarint();
+        return true;
+      case WireFormat.WIRETYPE_FIXED64:
+        skipRawBytes(8);
+        return true;
+      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+        skipRawBytes(readRawVarint32());
+        return true;
+      case WireFormat.WIRETYPE_START_GROUP:
+        skipMessage();
+        checkLastTagWas(
+          WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
+                             WireFormat.WIRETYPE_END_GROUP));
+        return true;
+      case WireFormat.WIRETYPE_END_GROUP:
+        return false;
+      case WireFormat.WIRETYPE_FIXED32:
+        skipRawBytes(4);
+        return true;
+      default:
+        throw InvalidProtocolBufferException.invalidWireType();
+    }
+  }
+
+  /**
+   * Reads a single field and writes it to output in wire format,
+   * given its tag value.
+   *
+   * @return {@code false} if the tag is an endgroup tag, in which case
+   *         nothing is skipped.  Otherwise, returns {@code true}.
+   */
+  public boolean skipField(final int tag, final CodedOutputStream output)
+      throws IOException {
+    switch (WireFormat.getTagWireType(tag)) {
+      case WireFormat.WIRETYPE_VARINT: {
+        long value = readInt64();
+        output.writeRawVarint32(tag);
+        output.writeUInt64NoTag(value);
+        return true;
+      }
+      case WireFormat.WIRETYPE_FIXED64: {
+        long value = readRawLittleEndian64();
+        output.writeRawVarint32(tag);
+        output.writeFixed64NoTag(value);
+        return true;
+      }
+      case WireFormat.WIRETYPE_LENGTH_DELIMITED: {
+        ByteString value = readBytes();
+        output.writeRawVarint32(tag);
+        output.writeBytesNoTag(value);
+        return true;
+      }
+      case WireFormat.WIRETYPE_START_GROUP: {
+        output.writeRawVarint32(tag);
+        skipMessage(output);
+        int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
+                                        WireFormat.WIRETYPE_END_GROUP);
+        checkLastTagWas(endtag);
+        output.writeRawVarint32(endtag);
+        return true;
+      }
+      case WireFormat.WIRETYPE_END_GROUP: {
+        return false;
+      }
+      case WireFormat.WIRETYPE_FIXED32: {
+        int value = readRawLittleEndian32();
+        output.writeRawVarint32(tag);
+        output.writeFixed32NoTag(value);
+        return true;
+      }
+      default:
+        throw InvalidProtocolBufferException.invalidWireType();
+    }
+  }
+
+  /**
+   * Reads and discards an entire message.  This will read either until EOF
+   * or until an endgroup tag, whichever comes first.
+   */
+  public void skipMessage() throws IOException {
+    while (true) {
+      final int tag = readTag();
+      if (tag == 0 || !skipField(tag)) {
+        return;
+      }
+    }
+  }
+
+  /**
+   * Reads an entire message and writes it to output in wire format.
+   * This will read either until EOF or until an endgroup tag,
+   * whichever comes first.
+   */
+  public void skipMessage(CodedOutputStream output) throws IOException {
+    while (true) {
+      final int tag = readTag();
+      if (tag == 0 || !skipField(tag, output)) {
+        return;
+      }
+    }
+  }
+
+  /**
+   * Collects the bytes skipped and returns the data in a ByteBuffer.
+   */
+  private class SkippedDataSink implements RefillCallback {
+    private int lastPos = bufferPos;
+    private ByteArrayOutputStream byteArrayStream;
+
+    @Override
+    public void onRefill() {
+      if (byteArrayStream == null) {
+        byteArrayStream = new ByteArrayOutputStream();
+      }
+      byteArrayStream.write(buffer, lastPos, bufferPos - lastPos);
+      lastPos = 0;
+    }
+
+    /**
+     * Gets skipped data in a ByteBuffer. This method should only be
+     * called once.
+     */
+    ByteBuffer getSkippedData() {
+      if (byteArrayStream == null) {
+        return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos);
+      } else {
+        byteArrayStream.write(buffer, lastPos, bufferPos);
+        return ByteBuffer.wrap(byteArrayStream.toByteArray());
+      }
+    }
+  }
+
+
+  // -----------------------------------------------------------------
+
+  /** Read a {@code double} field value from the stream. */
+  public double readDouble() throws IOException {
+    return Double.longBitsToDouble(readRawLittleEndian64());
+  }
+
+  /** Read a {@code float} field value from the stream. */
+  public float readFloat() throws IOException {
+    return Float.intBitsToFloat(readRawLittleEndian32());
+  }
+
+  /** Read a {@code uint64} field value from the stream. */
+  public long readUInt64() throws IOException {
+    return readRawVarint64();
+  }
+
+  /** Read an {@code int64} field value from the stream. */
+  public long readInt64() throws IOException {
+    return readRawVarint64();
+  }
+
+  /** Read an {@code int32} field value from the stream. */
+  public int readInt32() throws IOException {
+    return readRawVarint32();
+  }
+
+  /** Read a {@code fixed64} field value from the stream. */
+  public long readFixed64() throws IOException {
+    return readRawLittleEndian64();
+  }
+
+  /** Read a {@code fixed32} field value from the stream. */
+  public int readFixed32() throws IOException {
+    return readRawLittleEndian32();
+  }
+
+  /** Read a {@code bool} field value from the stream. */
+  public boolean readBool() throws IOException {
+    return readRawVarint64() != 0;
+  }
+
+  /**
+   * Read a {@code string} field value from the stream.
+   * If the stream contains malformed UTF-8,
+   * replace the offending bytes with the standard UTF-8 replacement character.
+   */
+  public String readString() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path:  We already have the bytes in a contiguous buffer, so
+      //   just copy directly from it.
+      final String result = new String(buffer, bufferPos, size, Internal.UTF_8);
+      bufferPos += size;
+      return result;
+    } else if (size == 0) {
+      return "";
+    } else if (size <= bufferSize) {
+      refillBuffer(size);
+      String result = new String(buffer, bufferPos, size, Internal.UTF_8);
+      bufferPos += size;
+      return result;
+    } else {
+      // Slow path:  Build a byte array first then copy it.
+      return new String(readRawBytesSlowPath(size), Internal.UTF_8);
+    }
+  }
+
+  /**
+   * Read a {@code string} field value from the stream.
+   * If the stream contains malformed UTF-8,
+   * throw exception {@link InvalidProtocolBufferException}.
+   */
+  public String readStringRequireUtf8() throws IOException {
+    final int size = readRawVarint32();
+    final byte[] bytes;
+    final int oldPos = bufferPos;
+    final int pos;
+    if (size <= (bufferSize - oldPos) && size > 0) {
+      // Fast path:  We already have the bytes in a contiguous buffer, so
+      //   just copy directly from it.
+      bytes = buffer;
+      bufferPos = oldPos + size;
+      pos = oldPos;
+    } else if (size == 0) {
+      return "";
+    } else if (size <= bufferSize) {
+      refillBuffer(size);
+      bytes = buffer;
+      pos = 0;
+      bufferPos = pos + size;
+    } else {
+      // Slow path:  Build a byte array first then copy it.
+      bytes = readRawBytesSlowPath(size);
+      pos = 0;
+    }
+    // TODO(martinrb): We could save a pass by validating while decoding.
+    if (!Utf8.isValidUtf8(bytes, pos, pos + size)) {
+      throw InvalidProtocolBufferException.invalidUtf8();
+    }
+    return new String(bytes, pos, size, Internal.UTF_8);
+  }
+
+  /** Read a {@code group} field value from the stream. */
+  public void readGroup(final int fieldNumber,
+                        final MessageLite.Builder builder,
+                        final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    ++recursionDepth;
+    builder.mergeFrom(this, extensionRegistry);
+    checkLastTagWas(
+      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+    --recursionDepth;
+  }
+
+
+  /** Read a {@code group} field value from the stream. */
+  public <T extends MessageLite> T readGroup(
+      final int fieldNumber,
+      final Parser<T> parser,
+      final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    ++recursionDepth;
+    T result = parser.parsePartialFrom(this, extensionRegistry);
+    checkLastTagWas(
+      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+    --recursionDepth;
+    return result;
+  }
+
+  /**
+   * Reads a {@code group} field value from the stream and merges it into the
+   * given {@link UnknownFieldSet}.
+   *
+   * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
+   *             you can just call {@link #readGroup}.
+   */
+  @Deprecated
+  public void readUnknownGroup(final int fieldNumber,
+                               final MessageLite.Builder builder)
+      throws IOException {
+    // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
+    // is safe to pass null here.  (We can't call
+    // ExtensionRegistry.getEmptyRegistry() because that would make this
+    // class depend on ExtensionRegistry, which is not part of the lite
+    // library.)
+    readGroup(fieldNumber, builder, null);
+  }
+
+  /** Read an embedded message field value from the stream. */
+  public void readMessage(final MessageLite.Builder builder,
+                          final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    final int length = readRawVarint32();
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    final int oldLimit = pushLimit(length);
+    ++recursionDepth;
+    builder.mergeFrom(this, extensionRegistry);
+    checkLastTagWas(0);
+    --recursionDepth;
+    popLimit(oldLimit);
+  }
+
+
+  /** Read an embedded message field value from the stream. */
+  public <T extends MessageLite> T readMessage(
+      final Parser<T> parser,
+      final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    int length = readRawVarint32();
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    final int oldLimit = pushLimit(length);
+    ++recursionDepth;
+    T result = parser.parsePartialFrom(this, extensionRegistry);
+    checkLastTagWas(0);
+    --recursionDepth;
+    popLimit(oldLimit);
+    return result;
+  }
+
+  /** Read a {@code bytes} field value from the stream. */
+  public ByteString readBytes() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path:  We already have the bytes in a contiguous buffer, so
+      //   just copy directly from it.
+      final ByteString result = bufferIsImmutable && enableAliasing
+          ? ByteString.wrap(buffer, bufferPos, size)
+          : ByteString.copyFrom(buffer, bufferPos, size);
+      bufferPos += size;
+      return result;
+    } else if (size == 0) {
+      return ByteString.EMPTY;
+    } else {
+      // Slow path:  Build a byte array first then copy it.
+      return ByteString.wrap(readRawBytesSlowPath(size));
+    }
+  }
+
+  /** Read a {@code bytes} field value from the stream. */
+  public byte[] readByteArray() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path: We already have the bytes in a contiguous buffer, so
+      // just copy directly from it.
+      final byte[] result =
+          Arrays.copyOfRange(buffer, bufferPos, bufferPos + size);
+      bufferPos += size;
+      return result;
+    } else {
+      // Slow path: Build a byte array first then copy it.
+      return readRawBytesSlowPath(size);
+    }
+  }
+
+  /** Read a {@code bytes} field value from the stream. */
+  public ByteBuffer readByteBuffer() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path: We already have the bytes in a contiguous buffer.
+      // When aliasing is enabled, we can return a ByteBuffer pointing directly
+      // into the underlying byte array without copy if the CodedInputStream is
+      // constructed from a byte array. If aliasing is disabled or the input is
+      // from an InputStream or ByteString, we have to make a copy of the bytes.
+      ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing
+          ? ByteBuffer.wrap(buffer, bufferPos, size).slice()
+          : ByteBuffer.wrap(Arrays.copyOfRange(
+              buffer, bufferPos, bufferPos + size));
+      bufferPos += size;
+      return result;
+    } else if (size == 0) {
+      return Internal.EMPTY_BYTE_BUFFER;
+    } else {
+      // Slow path: Build a byte array first then copy it.
+      return ByteBuffer.wrap(readRawBytesSlowPath(size));
+    }
+  }
+
+  /** Read a {@code uint32} field value from the stream. */
+  public int readUInt32() throws IOException {
+    return readRawVarint32();
+  }
+
+  /**
+   * Read an enum field value from the stream.  Caller is responsible
+   * for converting the numeric value to an actual enum.
+   */
+  public int readEnum() throws IOException {
+    return readRawVarint32();
+  }
+
+  /** Read an {@code sfixed32} field value from the stream. */
+  public int readSFixed32() throws IOException {
+    return readRawLittleEndian32();
+  }
+
+  /** Read an {@code sfixed64} field value from the stream. */
+  public long readSFixed64() throws IOException {
+    return readRawLittleEndian64();
+  }
+
+  /** Read an {@code sint32} field value from the stream. */
+  public int readSInt32() throws IOException {
+    return decodeZigZag32(readRawVarint32());
+  }
+
+  /** Read an {@code sint64} field value from the stream. */
+  public long readSInt64() throws IOException {
+    return decodeZigZag64(readRawVarint64());
+  }
+
+  // =================================================================
+
+  /**
+   * Read a raw Varint from the stream.  If larger than 32 bits, discard the
+   * upper bits.
+   */
+  public int readRawVarint32() throws IOException {
+    // See implementation notes for readRawVarint64
+ fastpath: {
+      int pos = bufferPos;
+
+      if (bufferSize == pos) {
+        break fastpath;
+      }
+
+      final byte[] buffer = this.buffer;
+      int x;
+      if ((x = buffer[pos++]) >= 0) {
+        bufferPos = pos;
+        return x;
+      } else if (bufferSize - pos < 9) {
+        break fastpath;
+      } else if ((x ^= (buffer[pos++] << 7)) < 0) {
+        x ^= (~0 << 7);
+      } else if ((x ^= (buffer[pos++] << 14)) >= 0) {
+        x ^= (~0 << 7) ^ (~0 << 14);
+      } else if ((x ^= (buffer[pos++] << 21)) < 0) {
+        x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
+      } else {
+        int y = buffer[pos++];
+        x ^= y << 28;
+        x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
+        if (y < 0 &&
+            buffer[pos++] < 0 &&
+            buffer[pos++] < 0 &&
+            buffer[pos++] < 0 &&
+            buffer[pos++] < 0 &&
+            buffer[pos++] < 0) {
+          break fastpath;  // Will throw malformedVarint()
+        }
+      }
+      bufferPos = pos;
+      return x;
+    }
+    return (int) readRawVarint64SlowPath();
+  }
+
+  private void skipRawVarint() throws IOException {
+    if (bufferSize - bufferPos >= 10) {
+      final byte[] buffer = this.buffer;
+      int pos = bufferPos;
+      for (int i = 0; i < 10; i++) {
+        if (buffer[pos++] >= 0) {
+          bufferPos = pos;
+          return;
+        }
+      }
+    }
+    skipRawVarintSlowPath();
+  }
+
+  private void skipRawVarintSlowPath() throws IOException {
+    for (int i = 0; i < 10; i++) {
+      if (readRawByte() >= 0) {
+        return;
+      }
+    }
+    throw InvalidProtocolBufferException.malformedVarint();
+  }
+
+  /**
+   * Reads a varint from the input one byte at a time, so that it does not
+   * read any bytes after the end of the varint.  If you simply wrapped the
+   * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
+   * then you would probably end up reading past the end of the varint since
+   * CodedInputStream buffers its input.
+   */
+  static int readRawVarint32(final InputStream input) throws IOException {
+    final int firstByte = input.read();
+    if (firstByte == -1) {
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+    return readRawVarint32(firstByte, input);
+  }
+
+  /**
+   * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
+   * has already read one byte.  This allows the caller to determine if EOF
+   * has been reached before attempting to read.
+   */
+  public static int readRawVarint32(
+      final int firstByte, final InputStream input) throws IOException {
+    if ((firstByte & 0x80) == 0) {
+      return firstByte;
+    }
+
+    int result = firstByte & 0x7f;
+    int offset = 7;
+    for (; offset < 32; offset += 7) {
+      final int b = input.read();
+      if (b == -1) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
+      result |= (b & 0x7f) << offset;
+      if ((b & 0x80) == 0) {
+        return result;
+      }
+    }
+    // Keep reading up to 64 bits.
+    for (; offset < 64; offset += 7) {
+      final int b = input.read();
+      if (b == -1) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
+      if ((b & 0x80) == 0) {
+        return result;
+      }
+    }
+    throw InvalidProtocolBufferException.malformedVarint();
+  }
+
+  /** Read a raw Varint from the stream. */
+  public long readRawVarint64() throws IOException {
+    // Implementation notes:
+    //
+    // Optimized for one-byte values, expected to be common.
+    // The particular code below was selected from various candidates
+    // empirically, by winning VarintBenchmark.
+    //
+    // Sign extension of (signed) Java bytes is usually a nuisance, but
+    // we exploit it here to more easily obtain the sign of bytes read.
+    // Instead of cleaning up the sign extension bits by masking eagerly,
+    // we delay until we find the final (positive) byte, when we clear all
+    // accumulated bits with one xor.  We depend on javac to constant fold.
+ fastpath: {
+      int pos = bufferPos;
+
+      if (bufferSize == pos) {
+        break fastpath;
+      }
+
+      final byte[] buffer = this.buffer;
+      long x;
+      int y;
+      if ((y = buffer[pos++]) >= 0) {
+        bufferPos = pos;
+        return y;
+      } else if (bufferSize - pos < 9) {
+        break fastpath;
+      } else if ((y ^= (buffer[pos++] << 7)) < 0) {
+        x = y ^ (~0 << 7);
+      } else if ((y ^= (buffer[pos++] << 14)) >= 0) {
+        x = y ^ ((~0 << 7) ^ (~0 << 14));
+      } else if ((y ^= (buffer[pos++] << 21)) < 0) {
+        x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+      } else if ((x = ((long) y) ^ ((long) buffer[pos++] << 28)) >= 0L) {
+        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+      } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) {
+        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
+      } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) {
+        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
+      } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) {
+        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
+            ^ (~0L << 49);
+      } else {
+        x ^= ((long) buffer[pos++] << 56);
+        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
+            ^ (~0L << 49) ^ (~0L << 56);
+        if (x < 0L) {
+          if (buffer[pos++] < 0L) {
+            break fastpath;  // Will throw malformedVarint()
+          }
+        }
+      }
+      bufferPos = pos;
+      return x;
+    }
+    return readRawVarint64SlowPath();
+  }
+
+  /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
+  /* Visible for testing */
+  long readRawVarint64SlowPath() throws IOException {
+    long result = 0;
+    for (int shift = 0; shift < 64; shift += 7) {
+      final byte b = readRawByte();
+      result |= (long) (b & 0x7F) << shift;
+      if ((b & 0x80) == 0) {
+        return result;
+      }
+    }
+    throw InvalidProtocolBufferException.malformedVarint();
+  }
+
+  /** Read a 32-bit little-endian integer from the stream. */
+  public int readRawLittleEndian32() throws IOException {
+    int pos = bufferPos;
+
+    // hand-inlined ensureAvailable(4);
+    if (bufferSize - pos < 4) {
+      refillBuffer(4);
+      pos = bufferPos;
+    }
+
+    final byte[] buffer = this.buffer;
+    bufferPos = pos + 4;
+    return (((buffer[pos]     & 0xff))       |
+            ((buffer[pos + 1] & 0xff) <<  8) |
+            ((buffer[pos + 2] & 0xff) << 16) |
+            ((buffer[pos + 3] & 0xff) << 24));
+  }
+
+  /** Read a 64-bit little-endian integer from the stream. */
+  public long readRawLittleEndian64() throws IOException {
+    int pos = bufferPos;
+
+    // hand-inlined ensureAvailable(8);
+    if (bufferSize - pos < 8) {
+      refillBuffer(8);
+      pos = bufferPos;
+    }
+
+    final byte[] buffer = this.buffer;
+    bufferPos = pos + 8;
+    return ((((long) buffer[pos]     & 0xffL))       |
+            (((long) buffer[pos + 1] & 0xffL) <<  8) |
+            (((long) buffer[pos + 2] & 0xffL) << 16) |
+            (((long) buffer[pos + 3] & 0xffL) << 24) |
+            (((long) buffer[pos + 4] & 0xffL) << 32) |
+            (((long) buffer[pos + 5] & 0xffL) << 40) |
+            (((long) buffer[pos + 6] & 0xffL) << 48) |
+            (((long) buffer[pos + 7] & 0xffL) << 56));
+  }
+
+  /**
+   * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n An unsigned 32-bit integer, stored in a signed int because
+   *          Java has no explicit unsigned support.
+   * @return A signed 32-bit integer.
+   */
+  public static int decodeZigZag32(final int n) {
+    return (n >>> 1) ^ -(n & 1);
+  }
+
+  /**
+   * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n An unsigned 64-bit integer, stored in a signed int because
+   *          Java has no explicit unsigned support.
+   * @return A signed 64-bit integer.
+   */
+  public static long decodeZigZag64(final long n) {
+    return (n >>> 1) ^ -(n & 1);
+  }
+
+  // -----------------------------------------------------------------
+
+  private final byte[] buffer;
+  private final boolean bufferIsImmutable;
+  private int bufferSize;
+  private int bufferSizeAfterLimit;
+  private int bufferPos;
+  private final InputStream input;
+  private int lastTag;
+  private boolean enableAliasing = false;
+
+  /**
+   * The total number of bytes read before the current buffer.  The total
+   * bytes read up to the current position can be computed as
+   * {@code totalBytesRetired + bufferPos}.  This value may be negative if
+   * reading started in the middle of the current buffer (e.g. if the
+   * constructor that takes a byte array and an offset was used).
+   */
+  private int totalBytesRetired;
+
+  /** The absolute position of the end of the current message. */
+  private int currentLimit = Integer.MAX_VALUE;
+
+  /** See setRecursionLimit() */
+  private int recursionDepth;
+  private int recursionLimit = DEFAULT_RECURSION_LIMIT;
+
+  /** See setSizeLimit() */
+  private int sizeLimit = DEFAULT_SIZE_LIMIT;
+
+  private static final int DEFAULT_RECURSION_LIMIT = 100;
+  private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
+  private static final int BUFFER_SIZE = 4096;
+
+  private CodedInputStream(
+      final byte[] buffer, final int off, final int len, boolean bufferIsImmutable) {
+    this.buffer = buffer;
+    bufferSize = off + len;
+    bufferPos = off;
+    totalBytesRetired = -off;
+    input = null;
+    this.bufferIsImmutable = bufferIsImmutable;
+  }
+
+  private CodedInputStream(final InputStream input, int bufferSize) {
+    buffer = new byte[bufferSize];
+    bufferSize = 0;
+    bufferPos = 0;
+    totalBytesRetired = 0;
+    this.input = input;
+    bufferIsImmutable = false;
+  }
+
+  public void enableAliasing(boolean enabled) {
+    this.enableAliasing = enabled;
+  }
+
+  /**
+   * Set the maximum message recursion depth.  In order to prevent malicious
+   * messages from causing stack overflows, {@code CodedInputStream} limits
+   * how deeply messages may be nested.  The default limit is 64.
+   *
+   * @return the old limit.
+   */
+  public int setRecursionLimit(final int limit) {
+    if (limit < 0) {
+      throw new IllegalArgumentException(
+        "Recursion limit cannot be negative: " + limit);
+    }
+    final int oldLimit = recursionLimit;
+    recursionLimit = limit;
+    return oldLimit;
+  }
+
+  /**
+   * Set the maximum message size.  In order to prevent malicious
+   * messages from exhausting memory or causing integer overflows,
+   * {@code CodedInputStream} limits how large a message may be.
+   * The default limit is 64MB.  You should set this limit as small
+   * as you can without harming your app's functionality.  Note that
+   * size limits only apply when reading from an {@code InputStream}, not
+   * when constructed around a raw byte array (nor with
+   * {@link ByteString#newCodedInput}).
+   * <p>
+   * If you want to read several messages from a single CodedInputStream, you
+   * could call {@link #resetSizeCounter()} after each one to avoid hitting the
+   * size limit.
+   *
+   * @return the old limit.
+   */
+  public int setSizeLimit(final int limit) {
+    if (limit < 0) {
+      throw new IllegalArgumentException(
+        "Size limit cannot be negative: " + limit);
+    }
+    final int oldLimit = sizeLimit;
+    sizeLimit = limit;
+    return oldLimit;
+  }
+
+  /**
+   * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
+   */
+  public void resetSizeCounter() {
+    totalBytesRetired = -bufferPos;
+  }
+
+  /**
+   * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
+   * is called when descending into a length-delimited embedded message.
+   *
+   * <p>Note that {@code pushLimit()} does NOT affect how many bytes the
+   * {@code CodedInputStream} reads from an underlying {@code InputStream} when
+   * refreshing its buffer.  If you need to prevent reading past a certain
+   * point in the underlying {@code InputStream} (e.g. because you expect it to
+   * contain more data after the end of the message which you need to handle
+   * differently) then you must place a wrapper around your {@code InputStream}
+   * which limits the amount of data that can be read from it.
+   *
+   * @return the old limit.
+   */
+  public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
+    if (byteLimit < 0) {
+      throw InvalidProtocolBufferException.negativeSize();
+    }
+    byteLimit += totalBytesRetired + bufferPos;
+    final int oldLimit = currentLimit;
+    if (byteLimit > oldLimit) {
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+    currentLimit = byteLimit;
+
+    recomputeBufferSizeAfterLimit();
+
+    return oldLimit;
+  }
+
+  private void recomputeBufferSizeAfterLimit() {
+    bufferSize += bufferSizeAfterLimit;
+    final int bufferEnd = totalBytesRetired + bufferSize;
+    if (bufferEnd > currentLimit) {
+      // Limit is in current buffer.
+      bufferSizeAfterLimit = bufferEnd - currentLimit;
+      bufferSize -= bufferSizeAfterLimit;
+    } else {
+      bufferSizeAfterLimit = 0;
+    }
+  }
+
+  /**
+   * Discards the current limit, returning to the previous limit.
+   *
+   * @param oldLimit The old limit, as returned by {@code pushLimit}.
+   */
+  public void popLimit(final int oldLimit) {
+    currentLimit = oldLimit;
+    recomputeBufferSizeAfterLimit();
+  }
+
+  /**
+   * Returns the number of bytes to be read before the current limit.
+   * If no limit is set, returns -1.
+   */
+  public int getBytesUntilLimit() {
+    if (currentLimit == Integer.MAX_VALUE) {
+      return -1;
+    }
+
+    final int currentAbsolutePosition = totalBytesRetired + bufferPos;
+    return currentLimit - currentAbsolutePosition;
+  }
+
+  /**
+   * Returns true if the stream has reached the end of the input.  This is the
+   * case if either the end of the underlying input source has been reached or
+   * if the stream has reached a limit created using {@link #pushLimit(int)}.
+   */
+  public boolean isAtEnd() throws IOException {
+    return bufferPos == bufferSize && !tryRefillBuffer(1);
+  }
+
+  /**
+   * The total bytes read up to the current position. Calling
+   * {@link #resetSizeCounter()} resets this value to zero.
+   */
+  public int getTotalBytesRead() {
+      return totalBytesRetired + bufferPos;
+  }
+
+  private interface RefillCallback {
+    void onRefill();
+  }
+
+  private RefillCallback refillCallback = null;
+
+  /**
+   * Reads more bytes from the input, making at least {@code n} bytes available
+   * in the buffer.  Caller must ensure that the requested space is not yet
+   * available, and that the requested space is less than BUFFER_SIZE.
+   *
+   * @throws InvalidProtocolBufferException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  private void refillBuffer(int n) throws IOException {
+    if (!tryRefillBuffer(n)) {
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+  }
+
+  /**
+   * Tries to read more bytes from the input, making at least {@code n} bytes
+   * available in the buffer.  Caller must ensure that the requested space is
+   * not yet available, and that the requested space is less than BUFFER_SIZE.
+   *
+   * @return {@code true} if the bytes could be made available; {@code false}
+   *         if the end of the stream or the current limit was reached.
+   */
+  private boolean tryRefillBuffer(int n) throws IOException {
+    if (bufferPos + n <= bufferSize) {
+      throw new IllegalStateException(
+          "refillBuffer() called when " + n +
+          " bytes were already available in buffer");
+    }
+
+    if (totalBytesRetired + bufferPos + n > currentLimit) {
+      // Oops, we hit a limit.
+      return false;
+    }
+
+    if (refillCallback != null) {
+      refillCallback.onRefill();
+    }
+
+    if (input != null) {
+      int pos = bufferPos;
+      if (pos > 0) {
+        if (bufferSize > pos) {
+          System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos);
+        }
+        totalBytesRetired += pos;
+        bufferSize -= pos;
+        bufferPos = 0;
+      }
+
+      int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
+      if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
+        throw new IllegalStateException(
+            "InputStream#read(byte[]) returned invalid result: " + bytesRead +
+            "\nThe InputStream implementation is buggy.");
+      }
+      if (bytesRead > 0) {
+        bufferSize += bytesRead;
+        // Integer-overflow-conscious check against sizeLimit
+        if (totalBytesRetired + n - sizeLimit > 0) {
+          throw InvalidProtocolBufferException.sizeLimitExceeded();
+        }
+        recomputeBufferSizeAfterLimit();
+        return (bufferSize >= n) ? true : tryRefillBuffer(n);
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Read one byte from the input.
+   *
+   * @throws InvalidProtocolBufferException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public byte readRawByte() throws IOException {
+    if (bufferPos == bufferSize) {
+      refillBuffer(1);
+    }
+    return buffer[bufferPos++];
+  }
+
+  /**
+   * Read a fixed size of bytes from the input.
+   *
+   * @throws InvalidProtocolBufferException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public byte[] readRawBytes(final int size) throws IOException {
+    final int pos = bufferPos;
+    if (size <= (bufferSize - pos) && size > 0) {
+      bufferPos = pos + size;
+      return Arrays.copyOfRange(buffer, pos, pos + size);
+    } else {
+      return readRawBytesSlowPath(size);
+    }
+  }
+
+  /**
+   * Exactly like readRawBytes, but caller must have already checked the fast
+   * path: (size <= (bufferSize - pos) && size > 0)
+   */
+  private byte[] readRawBytesSlowPath(final int size) throws IOException {
+    if (size <= 0) {
+      if (size == 0) {
+        return Internal.EMPTY_BYTE_ARRAY;
+      } else {
+        throw InvalidProtocolBufferException.negativeSize();
+      }
+    }
+
+    // Verify that the message size so far has not exceeded sizeLimit.
+    int currentMessageSize = totalBytesRetired + bufferPos + size;
+    if (currentMessageSize > sizeLimit) {
+      throw InvalidProtocolBufferException.sizeLimitExceeded();
+    }
+
+    // Verify that the message size so far has not exceeded currentLimit.
+    if (currentMessageSize > currentLimit) {
+      // Read to the end of the stream anyway.
+      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+
+    // We need the input stream to proceed.
+    if (input == null) {
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+
+    final int originalBufferPos = bufferPos;
+    final int bufferedBytes = bufferSize - bufferPos;
+
+    // Mark the current buffer consumed.
+    totalBytesRetired += bufferSize;
+    bufferPos = 0;
+    bufferSize = 0;
+
+    // Determine the number of bytes we need to read from the input stream.
+    int sizeLeft = size - bufferedBytes;
+    // TODO(nathanmittler): Consider using a value larger than BUFFER_SIZE.
+    if (sizeLeft < BUFFER_SIZE || sizeLeft <= input.available()) {
+      // Either the bytes we need are known to be available, or the required buffer is
+      // within an allowed threshold - go ahead and allocate the buffer now.
+      final byte[] bytes = new byte[size];
+
+      // Copy all of the buffered bytes to the result buffer.
+      System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+
+      // Fill the remaining bytes from the input stream.
+      int pos = bufferedBytes;
+      while (pos < bytes.length) {
+        int n = input.read(bytes, pos, size - pos);
+        if (n == -1) {
+          throw InvalidProtocolBufferException.truncatedMessage();
+        }
+        totalBytesRetired += n;
+        pos += n;
+      }
+
+      return bytes;
+    }
+
+    // The size is very large.  For security reasons, we can't allocate the
+    // entire byte array yet.  The size comes directly from the input, so a
+    // maliciously-crafted message could provide a bogus very large size in
+    // order to trick the app into allocating a lot of memory.  We avoid this
+    // by allocating and reading only a small chunk at a time, so that the
+    // malicious message must actually *be* extremely large to cause
+    // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
+    final List<byte[]> chunks = new ArrayList<byte[]>();
+
+    while (sizeLeft > 0) {
+      // TODO(nathanmittler): Consider using a value larger than BUFFER_SIZE.
+      final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
+      int pos = 0;
+      while (pos < chunk.length) {
+        final int n = input.read(chunk, pos, chunk.length - pos);
+        if (n == -1) {
+          throw InvalidProtocolBufferException.truncatedMessage();
+        }
+        totalBytesRetired += n;
+        pos += n;
+      }
+      sizeLeft -= chunk.length;
+      chunks.add(chunk);
+    }
+
+    // OK, got everything.  Now concatenate it all into one buffer.
+    final byte[] bytes = new byte[size];
+
+    // Start by copying the leftover bytes from this.buffer.
+    System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+
+    // And now all the chunks.
+    int pos = bufferedBytes;
+    for (final byte[] chunk : chunks) {
+      System.arraycopy(chunk, 0, bytes, pos, chunk.length);
+      pos += chunk.length;
+    }
+
+    // Done.
+    return bytes;
+  }
+
+  /**
+   * Reads and discards {@code size} bytes.
+   *
+   * @throws InvalidProtocolBufferException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public void skipRawBytes(final int size) throws IOException {
+    if (size <= (bufferSize - bufferPos) && size >= 0) {
+      // We have all the bytes we need already.
+      bufferPos += size;
+    } else {
+      skipRawBytesSlowPath(size);
+    }
+  }
+
+  /**
+   * Exactly like skipRawBytes, but caller must have already checked the fast
+   * path: (size <= (bufferSize - pos) && size >= 0)
+   */
+  private void skipRawBytesSlowPath(final int size) throws IOException {
+    if (size < 0) {
+      throw InvalidProtocolBufferException.negativeSize();
+    }
+
+    if (totalBytesRetired + bufferPos + size > currentLimit) {
+      // Read to the end of the stream anyway.
+      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+      // Then fail.
+      throw InvalidProtocolBufferException.truncatedMessage();
+    }
+
+    // Skipping more bytes than are in the buffer.  First skip what we have.
+    int pos = bufferSize - bufferPos;
+    bufferPos = bufferSize;
+
+    // Keep refilling the buffer until we get to the point we wanted to skip to.
+    // This has the side effect of ensuring the limits are updated correctly.
+    refillBuffer(1);
+    while (size - pos > bufferSize) {
+      pos += bufferSize;
+      bufferPos = bufferSize;
+      refillBuffer(1);
+    }
+
+    bufferPos = size - pos;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
new file mode 100644
index 0000000..ad174d0
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -0,0 +1,2664 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.lang.Math.max;
+
+import com.google.protobuf.Utf8.UnpairedSurrogateException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Encodes and writes protocol message fields.
+ *
+ * <p>This class contains two kinds of methods:  methods that write specific
+ * protocol message constructs and field types (e.g. {@link #writeTag} and
+ * {@link #writeInt32}) and methods that write low-level values (e.g.
+ * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
+ * writing encoded protocol messages, you should use the former methods, but if
+ * you are writing some other format of your own design, use the latter.
+ *
+ * <p>This class is totally unsynchronized.
+ */
+public abstract class CodedOutputStream extends ByteOutput {
+  private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
+  private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+  private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
+  private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+
+  private static final int FIXED_32_SIZE = 4;
+  private static final int FIXED_64_SIZE = 8;
+  private static final int MAX_VARINT_SIZE = 10;
+
+  /**
+   * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
+   */
+  @Deprecated
+  public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
+
+  /**
+   * The buffer size used in {@link #newInstance(OutputStream)}.
+   */
+  public static final int DEFAULT_BUFFER_SIZE = 4096;
+
+  /**
+   * Returns the buffer size to efficiently write dataLength bytes to this
+   * CodedOutputStream. Used by AbstractMessageLite.
+   *
+   * @return the buffer size to efficiently write dataLength bytes to this
+   *         CodedOutputStream.
+   */
+  static int computePreferredBufferSize(int dataLength) {
+    if (dataLength > DEFAULT_BUFFER_SIZE) {
+      return DEFAULT_BUFFER_SIZE;
+    }
+    return dataLength;
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}.
+   *
+   * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+   * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+   * difficult to debug.
+   */
+  public static CodedOutputStream newInstance(final OutputStream output) {
+    return newInstance(output, DEFAULT_BUFFER_SIZE);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given
+   * buffer size.
+   *
+   * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+   * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+   * difficult to debug.
+   */
+  public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) {
+    return new OutputStreamEncoder(output, bufferSize);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes directly to the given
+   * byte array.  If more bytes are written than fit in the array,
+   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
+   * array is faster than writing to an {@code OutputStream}.  See also
+   * {@link ByteString#newCodedBuilder}.
+   */
+  public static CodedOutputStream newInstance(final byte[] flatArray) {
+    return newInstance(flatArray, 0, flatArray.length);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes directly to the given
+   * byte array slice.  If more bytes are written than fit in the slice,
+   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
+   * array is faster than writing to an {@code OutputStream}.  See also
+   * {@link ByteString#newCodedBuilder}.
+   */
+  public static CodedOutputStream newInstance(
+      final byte[] flatArray, final int offset, final int length) {
+    return new ArrayEncoder(flatArray, offset, length);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
+   */
+  public static CodedOutputStream newInstance(ByteBuffer byteBuffer) {
+    if (byteBuffer.hasArray()) {
+      return new NioHeapEncoder(byteBuffer);
+    }
+    return new NioEncoder(byteBuffer);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
+   *
+   * @deprecated the size parameter is no longer used since use of an internal buffer is useless
+   * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)}
+   * instead.
+   */
+  @Deprecated
+  public static CodedOutputStream newInstance(ByteBuffer byteBuffer,
+      @SuppressWarnings("unused") int unused) {
+    return newInstance(byteBuffer);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}.
+   *
+   * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
+   * so may result in corrupted data, which would be difficult to debug.
+   *
+   * @param byteOutput the output target for encoded bytes.
+   * @param bufferSize the size of the internal scratch buffer to be used for string encoding.
+   * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded
+   * string.
+   */
+  static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) {
+    if (bufferSize < 0) {
+      throw new IllegalArgumentException("bufferSize must be positive");
+    }
+
+    return new ByteOutputEncoder(byteOutput, bufferSize);
+  }
+
+  // Disallow construction outside of this class.
+  private CodedOutputStream() {
+  }
+
+  // -----------------------------------------------------------------
+
+  /** Encode and write a tag. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeTag(int fieldNumber, int wireType) throws IOException;
+
+  /** Write an {@code int32} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeInt32(int fieldNumber, int value) throws IOException;
+
+  /** Write a {@code uint32} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeUInt32(int fieldNumber, int value) throws IOException;
+
+  /** Write a {@code sint32} field, including tag, to the stream. */
+  public final void writeSInt32(final int fieldNumber, final int value) throws IOException {
+    writeUInt32(fieldNumber, encodeZigZag32(value));
+  }
+
+  /** Write a {@code fixed32} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeFixed32(int fieldNumber, int value) throws IOException;
+
+  /** Write an {@code sfixed32} field, including tag, to the stream. */
+  public final void writeSFixed32(final int fieldNumber, final int value) throws IOException {
+    writeFixed32(fieldNumber, value);
+  }
+
+  /** Write an {@code int64} field, including tag, to the stream. */
+  public final void writeInt64(final int fieldNumber, final long value) throws IOException {
+    writeUInt64(fieldNumber, value);
+  }
+
+  /** Write a {@code uint64} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeUInt64(int fieldNumber, long value) throws IOException;
+
+  /** Write an {@code sint64} field, including tag, to the stream. */
+  public final void writeSInt64(final int fieldNumber, final long value) throws IOException {
+    writeUInt64(fieldNumber, encodeZigZag64(value));
+  }
+
+  /** Write a {@code fixed64} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeFixed64(int fieldNumber, long value) throws IOException;
+
+  /** Write an {@code sfixed64} field, including tag, to the stream. */
+  public final void writeSFixed64(final int fieldNumber, final long value) throws IOException {
+    writeFixed64(fieldNumber, value);
+  }
+
+  /** Write a {@code float} field, including tag, to the stream. */
+  public final void writeFloat(final int fieldNumber, final float value) throws IOException {
+    writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
+  }
+
+  /** Write a {@code double} field, including tag, to the stream. */
+  public final void writeDouble(final int fieldNumber, final double value) throws IOException {
+    writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
+  }
+
+  /** Write a {@code bool} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeBool(int fieldNumber, boolean value) throws IOException;
+
+  /**
+   * Write an enum field, including tag, to the stream. The provided value is the numeric
+   * value used to represent the enum value on the wire (not the enum ordinal value).
+   */
+  public final void writeEnum(final int fieldNumber, final int value) throws IOException {
+    writeInt32(fieldNumber, value);
+  }
+
+  /** Write a {@code string} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeString(int fieldNumber, String value) throws IOException;
+
+  /** Write a {@code bytes} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException;
+
+  /** Write a {@code bytes} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException;
+
+  /** Write a {@code bytes} field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
+      throws IOException;
+
+  /**
+   * Write a {@code bytes} field, including tag, to the stream.
+   * This method will write all content of the ByteBuffer regardless of the
+   * current position and limit (i.e., the number of bytes to be written is
+   * value.capacity(), not value.remaining()). Furthermore, this method doesn't
+   * alter the state of the passed-in ByteBuffer. Its position, limit, mark,
+   * etc. will remain unchanged. If you only want to write the remaining bytes
+   * of a ByteBuffer, you can call
+   * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}.
+   */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException;
+
+  /**
+   * Write a single byte.
+   */
+  public final void writeRawByte(final byte value) throws IOException {
+    write(value);
+  }
+
+  /** Write a single byte, represented by an integer value. */
+  public final void writeRawByte(final int value) throws IOException {
+    write((byte) value);
+  }
+
+  /** Write an array of bytes. */
+  public final void writeRawBytes(final byte[] value) throws IOException {
+    write(value, 0, value.length);
+  }
+
+  /**
+   * Write part of an array of bytes.
+   */
+  public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
+    write(value, offset, length);
+  }
+
+  /** Write a byte string. */
+  public final void writeRawBytes(final ByteString value) throws IOException {
+    value.writeTo(this);
+  }
+
+  /**
+   * Write a ByteBuffer. This method will write all content of the ByteBuffer
+   * regardless of the current position and limit (i.e., the number of bytes
+   * to be written is value.capacity(), not value.remaining()). Furthermore,
+   * this method doesn't alter the state of the passed-in ByteBuffer. Its
+   * position, limit, mark, etc. will remain unchanged. If you only want to
+   * write the remaining bytes of a ByteBuffer, you can call
+   * {@code writeRawBytes(byteBuffer.slice())}.
+   */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeRawBytes(final ByteBuffer value) throws IOException;
+
+  /** Write an embedded message field, including tag, to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeMessage(final int fieldNumber, final MessageLite value)
+      throws IOException;
+
+  /**
+   * Write a MessageSet extension field to the stream.  For historical reasons,
+   * the wire format differs from normal fields.
+   */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+      throws IOException;
+
+  /**
+   * Write an unparsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+      throws IOException;
+
+  // -----------------------------------------------------------------
+
+  /** Write an {@code int32} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeInt32NoTag(final int value) throws IOException;
+
+  /** Write a {@code uint32} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeUInt32NoTag(int value) throws IOException;
+
+  /** Write a {@code sint32} field to the stream. */
+  public final void writeSInt32NoTag(final int value) throws IOException {
+    writeUInt32NoTag(encodeZigZag32(value));
+  }
+
+  /** Write a {@code fixed32} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeFixed32NoTag(int value) throws IOException;
+
+  /** Write a {@code sfixed32} field to the stream. */
+  public final void writeSFixed32NoTag(final int value) throws IOException {
+    writeFixed32NoTag(value);
+  }
+
+  /** Write an {@code int64} field to the stream. */
+  public final void writeInt64NoTag(final long value) throws IOException {
+    writeUInt64NoTag(value);
+  }
+
+  /** Write a {@code uint64} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeUInt64NoTag(long value) throws IOException;
+
+  /** Write a {@code sint64} field to the stream. */
+  public final void writeSInt64NoTag(final long value) throws IOException {
+    writeUInt64NoTag(encodeZigZag64(value));
+  }
+
+  /** Write a {@code fixed64} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeFixed64NoTag(long value) throws IOException;
+
+  /** Write a {@code sfixed64} field to the stream. */
+  public final void writeSFixed64NoTag(final long value) throws IOException {
+    writeFixed64NoTag(value);
+  }
+
+  /** Write a {@code float} field to the stream. */
+  public final void writeFloatNoTag(final float value) throws IOException {
+    writeFixed32NoTag(Float.floatToRawIntBits(value));
+  }
+
+  /** Write a {@code double} field to the stream. */
+  public final void writeDoubleNoTag(final double value) throws IOException {
+    writeFixed64NoTag(Double.doubleToRawLongBits(value));
+  }
+
+  /** Write a {@code bool} field to the stream. */
+  public final void writeBoolNoTag(final boolean value) throws IOException {
+    write((byte) (value ? 1 : 0));
+  }
+
+  /**
+   * Write an enum field to the stream. The provided value is the numeric
+   * value used to represent the enum value on the wire (not the enum ordinal value).
+   */
+  public final void writeEnumNoTag(final int value) throws IOException {
+    writeInt32NoTag(value);
+  }
+
+  /** Write a {@code string} field to the stream. */
+  // TODO(dweis): Document behavior on ill-formed UTF-16 input.
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeStringNoTag(String value) throws IOException;
+
+  /** Write a {@code bytes} field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeBytesNoTag(final ByteString value) throws IOException;
+
+  /** Write a {@code bytes} field to the stream. */
+  public final void writeByteArrayNoTag(final byte[] value) throws IOException {
+    writeByteArrayNoTag(value, 0, value.length);
+  }
+
+  /** Write an embedded message field to the stream. */
+  // Abstract to avoid overhead of additional virtual method calls.
+  public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
+
+  //=================================================================
+
+  @ExperimentalApi
+  @Override
+  public abstract void write(byte value) throws IOException;
+
+  @ExperimentalApi
+  @Override
+  public abstract void write(byte[] value, int offset, int length) throws IOException;
+
+  @ExperimentalApi
+  @Override
+  public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
+
+  @Override
+  public abstract void write(ByteBuffer value) throws IOException;
+
+  @ExperimentalApi
+  @Override
+  public abstract void writeLazy(ByteBuffer value) throws IOException;
+
+  // =================================================================
+  // =================================================================
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int32} field, including tag.
+   */
+  public static int computeInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint32} field, including tag.
+   */
+  public static int computeUInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint32} field, including tag.
+   */
+  public static int computeSInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed32} field, including tag.
+   */
+  public static int computeFixed32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed32} field, including tag.
+   */
+  public static int computeSFixed32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int64} field, including tag.
+   */
+  public static int computeInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint64} field, including tag.
+   */
+  public static int computeUInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint64} field, including tag.
+   */
+  public static int computeSInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed64} field, including tag.
+   */
+  public static int computeFixed64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed64} field, including tag.
+   */
+  public static int computeSFixed64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code float} field, including tag.
+   */
+  public static int computeFloatSize(final int fieldNumber, final float value) {
+    return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code double} field, including tag.
+   */
+  public static int computeDoubleSize(final int fieldNumber, final double value) {
+    return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bool} field, including tag.
+   */
+  public static int computeBoolSize(final int fieldNumber, final boolean value) {
+    return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * enum field, including tag. The provided value is the numeric
+   * value used to represent the enum value on the wire (not the enum ordinal value).
+   */
+  public static int computeEnumSize(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code string} field, including tag.
+   */
+  public static int computeStringSize(final int fieldNumber, final String value) {
+    return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field, including tag.
+   */
+  public static int computeBytesSize(final int fieldNumber, final ByteString value) {
+    return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field, including tag.
+   */
+  public static int computeByteArraySize(final int fieldNumber, final byte[] value) {
+    return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field, including tag.
+   */
+  public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) {
+    return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * embedded message in lazy field, including tag.
+   */
+  public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) {
+    return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * embedded message field, including tag.
+   */
+  public static int computeMessageSize(final int fieldNumber, final MessageLite value) {
+    return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * MessageSet extension to the stream.  For historical reasons,
+   * the wire format differs from normal fields.
+   */
+  public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) {
+    return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+        + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+        + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * unparsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+  public static int computeRawMessageSetExtensionSize(
+      final int fieldNumber, final ByteString value) {
+    return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+        + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+        + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * lazily parsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+  public static int computeLazyFieldMessageSetExtensionSize(
+      final int fieldNumber, final LazyFieldLite value) {
+    return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+        + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+        + computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+  }
+
+  // -----------------------------------------------------------------
+
+  /** Compute the number of bytes that would be needed to encode a tag. */
+  public static int computeTagSize(final int fieldNumber) {
+    return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0));
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int32} field, including tag.
+   */
+  public static int computeInt32SizeNoTag(final int value) {
+    if (value >= 0) {
+      return computeUInt32SizeNoTag(value);
+    } else {
+      // Must sign-extend.
+      return MAX_VARINT_SIZE;
+    }
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint32} field.
+   */
+  public static int computeUInt32SizeNoTag(final int value) {
+    if ((value & (~0 <<  7)) == 0) {
+      return 1;
+    }
+    if ((value & (~0 << 14)) == 0) {
+      return 2;
+    }
+    if ((value & (~0 << 21)) == 0) {
+      return 3;
+    }
+    if ((value & (~0 << 28)) == 0) {
+      return 4;
+    }
+    return 5;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint32} field.
+   */
+  public static int computeSInt32SizeNoTag(final int value) {
+    return computeUInt32SizeNoTag(encodeZigZag32(value));
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed32} field.
+   */
+  public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
+    return FIXED_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed32} field.
+   */
+  public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
+    return FIXED_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int64} field, including tag.
+   */
+  public static int computeInt64SizeNoTag(final long value) {
+    return computeUInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint64} field, including tag.
+   */
+  public static int computeUInt64SizeNoTag(long value) {
+    // handle two popular special cases up front ...
+    if ((value & (~0L << 7)) == 0L) {
+      return 1;
+    }
+    if (value < 0L) {
+      return 10;
+    }
+    // ... leaving us with 8 remaining, which we can divide and conquer
+    int n = 2;
+    if ((value & (~0L << 35)) != 0L) {
+      n += 4; value >>>= 28;
+    }
+    if ((value & (~0L << 21)) != 0L) {
+      n += 2; value >>>= 14;
+    }
+    if ((value & (~0L << 14)) != 0L) {
+      n += 1;
+    }
+    return n;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint64} field.
+   */
+  public static int computeSInt64SizeNoTag(final long value) {
+    return computeUInt64SizeNoTag(encodeZigZag64(value));
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed64} field.
+   */
+  public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
+    return FIXED_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed64} field.
+   */
+  public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
+    return FIXED_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code float} field, including tag.
+   */
+  public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
+    return FIXED_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code double} field, including tag.
+   */
+  public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
+    return FIXED_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bool} field.
+   */
+  public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) {
+    return 1;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an enum field.
+   * The provided value is the numeric value used to represent the enum value on the wire
+   * (not the enum ordinal value).
+   */
+  public static int computeEnumSizeNoTag(final int value) {
+    return computeInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code string} field.
+   */
+  public static int computeStringSizeNoTag(final String value) {
+    int length;
+    try {
+      length = Utf8.encodedLength(value);
+    } catch (UnpairedSurrogateException e) {
+      // TODO(dweis): Consider using nio Charset methods instead.
+      final byte[] bytes = value.getBytes(Internal.UTF_8);
+      length = bytes.length;
+    }
+
+    return computeLengthDelimitedFieldSize(length);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an embedded
+   * message stored in lazy field.
+   */
+  public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
+    return computeLengthDelimitedFieldSize(value.getSerializedSize());
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field.
+   */
+  public static int computeBytesSizeNoTag(final ByteString value) {
+    return computeLengthDelimitedFieldSize(value.size());
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field.
+   */
+  public static int computeByteArraySizeNoTag(final byte[] value) {
+    return computeLengthDelimitedFieldSize(value.length);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field.
+   */
+  public static int computeByteBufferSizeNoTag(final ByteBuffer value) {
+    return computeLengthDelimitedFieldSize(value.capacity());
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an embedded
+   * message field.
+   */
+  public static int computeMessageSizeNoTag(final MessageLite value) {
+    return computeLengthDelimitedFieldSize(value.getSerializedSize());
+  }
+
+  private static int computeLengthDelimitedFieldSize(int fieldLength) {
+    return computeUInt32SizeNoTag(fieldLength) + fieldLength;
+  }
+
+  /**
+   * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n A signed 32-bit integer.
+   * @return An unsigned 32-bit integer, stored in a signed int because
+   *         Java has no explicit unsigned support.
+   */
+  public static int encodeZigZag32(final int n) {
+    // Note:  the right-shift must be arithmetic
+    return (n << 1) ^ (n >> 31);
+  }
+
+  /**
+   * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n A signed 64-bit integer.
+   * @return An unsigned 64-bit integer, stored in a signed int because
+   *         Java has no explicit unsigned support.
+   */
+  public static long encodeZigZag64(final long n) {
+    // Note:  the right-shift must be arithmetic
+    return (n << 1) ^ (n >> 63);
+  }
+
+  // =================================================================
+
+  /**
+   * Flushes the stream and forces any buffered bytes to be written.  This
+   * does not flush the underlying OutputStream.
+   */
+  public abstract void flush() throws IOException;
+
+  /**
+   * If writing to a flat array, return the space left in the array.
+   * Otherwise, throws {@code UnsupportedOperationException}.
+   */
+  public abstract int spaceLeft();
+
+  /**
+   * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
+   * a byte array that is exactly big enough to hold a message, then write to
+   * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
+   * after writing verifies that the message was actually as big as expected,
+   * which can help catch bugs.
+   */
+  public final void checkNoSpaceLeft() {
+    if (spaceLeft() != 0) {
+      throw new IllegalStateException("Did not write as much data as expected.");
+    }
+  }
+
+  /**
+   * If you create a CodedOutputStream around a simple flat array, you must
+   * not attempt to write more bytes than the array has space.  Otherwise,
+   * this exception will be thrown.
+   */
+  public static class OutOfSpaceException extends IOException {
+    private static final long serialVersionUID = -6947486886997889499L;
+
+    private static final String MESSAGE =
+        "CodedOutputStream was writing to a flat byte array and ran out of space.";
+
+    OutOfSpaceException() {
+      super(MESSAGE);
+    }
+
+    OutOfSpaceException(Throwable cause) {
+      super(MESSAGE, cause);
+    }
+  }
+
+  /**
+   * Get the total number of bytes successfully written to this stream.  The
+   * returned value is not guaranteed to be accurate if exceptions have been
+   * found in the middle of writing.
+   */
+  public abstract int getTotalBytesWritten();
+
+  // =================================================================
+
+  /** Write a {@code bytes} field to the stream. Visible for testing. */
+  abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
+      throws IOException;
+
+  final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause)
+      throws IOException {
+    logger.log(Level.WARNING,
+        "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause);
+
+    // Unfortunately there does not appear to be any way to tell Java to encode
+    // UTF-8 directly into our buffer, so we have to let it create its own byte
+    // array and then copy.
+    // TODO(dweis): Consider using nio Charset methods instead.
+    final byte[] bytes = value.getBytes(Internal.UTF_8);
+    try {
+      writeUInt32NoTag(bytes.length);
+      writeLazy(bytes, 0, bytes.length);
+    } catch (IndexOutOfBoundsException e) {
+      throw new OutOfSpaceException(e);
+    } catch (OutOfSpaceException e) {
+      throw e;
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * Write a {@code group} field, including tag, to the stream.
+   *
+   * @deprecated groups are deprecated.
+   */
+  @Deprecated
+  public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
+    writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+    writeGroupNoTag(value);
+    writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+  }
+
+  /**
+   * Write a {@code group} field to the stream.
+   *
+   * @deprecated groups are deprecated.
+   */
+  @Deprecated
+  public final void writeGroupNoTag(final MessageLite value) throws IOException {
+    value.writeTo(this);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code group} field, including tag.
+   *
+   * @deprecated groups are deprecated.
+   */
+  @Deprecated
+  public static int computeGroupSize(final int fieldNumber, final MessageLite value) {
+    return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code group} field.
+   */
+  @Deprecated
+  public static int computeGroupSizeNoTag(final MessageLite value) {
+    return value.getSerializedSize();
+  }
+
+  /**
+   * Encode and write a varint.  {@code value} is treated as
+   * unsigned, so it won't be sign-extended if negative.
+   *
+   * @deprecated use {@link #writeUInt32NoTag} instead.
+   */
+  @Deprecated
+  public final void writeRawVarint32(int value) throws IOException {
+    writeUInt32NoTag(value);
+  }
+
+  /**
+   * Encode and write a varint.
+   *
+   * @deprecated use {@link #writeUInt64NoTag} instead.
+   */
+  @Deprecated
+  public final void writeRawVarint64(long value) throws IOException {
+    writeUInt64NoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a varint.
+   * {@code value} is treated as unsigned, so it won't be sign-extended if
+   * negative.
+   *
+   * @deprecated use {@link #computeUInt32SizeNoTag(int)} instead.
+   */
+  @Deprecated
+  public static int computeRawVarint32Size(final int value) {
+    return computeUInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a varint.
+   *
+   * @deprecated use {@link #computeUInt64SizeNoTag(long)} instead.
+   */
+  @Deprecated
+  public static int computeRawVarint64Size(long value) {
+    return computeUInt64SizeNoTag(value);
+  }
+
+  /**
+   * Write a little-endian 32-bit integer.
+   *
+   * @deprecated Use {@link #writeFixed32NoTag} instead.
+   */
+  @Deprecated
+  public final void writeRawLittleEndian32(final int value) throws IOException {
+    writeFixed32NoTag(value);
+  }
+
+  /**
+   * Write a little-endian 64-bit integer.
+   *
+   * @deprecated Use {@link #writeFixed64NoTag} instead.
+   */
+  @Deprecated
+  public final void writeRawLittleEndian64(final long value) throws IOException {
+    writeFixed64NoTag(value);
+  }
+
+  // =================================================================
+
+  /**
+   * A {@link CodedOutputStream} that writes directly to a byte array.
+   */
+  private static class ArrayEncoder extends CodedOutputStream {
+    private final byte[] buffer;
+    private final int offset;
+    private final int limit;
+    private int position;
+
+    ArrayEncoder(byte[] buffer, int offset, int length) {
+      if (buffer == null) {
+        throw new NullPointerException("buffer");
+      }
+      if ((offset | length | (buffer.length - (offset + length))) < 0) {
+        throw new IllegalArgumentException(String.format(
+            "Array range is invalid. Buffer.length=%d, offset=%d, length=%d",
+            buffer.length, offset, length));
+      }
+      this.buffer = buffer;
+      this.offset = offset;
+      position = offset;
+      limit = offset + length;
+    }
+
+    @Override
+    public final void writeTag(final int fieldNumber, final int wireType) throws IOException {
+      writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+    }
+
+    @Override
+    public final void writeInt32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeInt32NoTag(value);
+    }
+
+    @Override
+    public final void writeUInt32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeUInt32NoTag(value);
+    }
+
+    @Override
+    public final void writeFixed32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+      writeFixed32NoTag(value);
+    }
+
+    @Override
+    public final void writeUInt64(final int fieldNumber, final long value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeUInt64NoTag(value);
+    }
+
+    @Override
+    public final void writeFixed64(final int fieldNumber, final long value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+      writeFixed64NoTag(value);
+    }
+
+    @Override
+    public final void writeBool(final int fieldNumber, final boolean value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      write((byte) (value ? 1 : 0));
+    }
+
+    @Override
+    public final void writeString(final int fieldNumber, final String value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeStringNoTag(value);
+    }
+
+    @Override
+    public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeBytesNoTag(value);
+    }
+
+    @Override
+    public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+      writeByteArray(fieldNumber, value, 0, value.length);
+    }
+
+    @Override
+    public final void writeByteArray(
+        final int fieldNumber, final byte[] value, final int offset, final int length)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeByteArrayNoTag(value, offset, length);
+    }
+
+    @Override
+    public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeUInt32NoTag(value.capacity());
+      writeRawBytes(value);
+    }
+
+    @Override
+    public final void writeBytesNoTag(final ByteString value) throws IOException {
+      writeUInt32NoTag(value.size());
+      value.writeTo(this);
+    }
+
+    @Override
+    public final void writeByteArrayNoTag(final byte[] value, int offset, int length)
+        throws IOException {
+      writeUInt32NoTag(length);
+      write(value, offset, length);
+    }
+
+    @Override
+    public final void writeRawBytes(final ByteBuffer value) throws IOException {
+      if (value.hasArray()) {
+        write(value.array(), value.arrayOffset(), value.capacity());
+      } else {
+        ByteBuffer duplicated = value.duplicate();
+        duplicated.clear();
+        write(duplicated);
+      }
+    }
+
+    @Override
+    public final void writeMessage(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeMessageNoTag(value);
+    }
+
+    @Override
+    public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public final void writeMessageNoTag(final MessageLite value) throws IOException {
+      writeUInt32NoTag(value.getSerializedSize());
+      value.writeTo(this);
+    }
+
+    @Override
+    public final void write(byte value) throws IOException {
+      try {
+        buffer[position++] = value;
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(new IndexOutOfBoundsException(
+            String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+      }
+    }
+
+    @Override
+    public final void writeInt32NoTag(int value) throws IOException {
+      if (value >= 0) {
+        writeUInt32NoTag(value);
+      } else {
+        // Must sign-extend.
+        writeUInt64NoTag(value);
+      }
+    }
+
+    @Override
+    public final void writeUInt32NoTag(int value) throws IOException {
+      if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+        long pos = ARRAY_BASE_OFFSET + position;
+        while (true) {
+          if ((value & ~0x7F) == 0) {
+            UNSAFE.putByte(buffer, pos++, (byte) value);
+            position++;
+            return;
+          } else {
+            UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+            position++;
+            value >>>= 7;
+          }
+        }
+      } else {
+        try {
+          while (true) {
+            if ((value & ~0x7F) == 0) {
+              buffer[position++] = (byte) value;
+              return;
+            } else {
+              buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+              value >>>= 7;
+            }
+          }
+        } catch (IndexOutOfBoundsException e) {
+          throw new OutOfSpaceException(
+              new IndexOutOfBoundsException(
+                  String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+        }
+      }
+    }
+
+    @Override
+    public final void writeFixed32NoTag(int value) throws IOException {
+      try {
+        buffer[position++] = (byte) (value & 0xFF);
+        buffer[position++] = (byte) ((value >> 8) & 0xFF);
+        buffer[position++] = (byte) ((value >> 16) & 0xFF);
+        buffer[position++] = (byte) ((value >> 24) & 0xFF);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(
+            new IndexOutOfBoundsException(
+                String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+      }
+    }
+
+    @Override
+    public final void writeUInt64NoTag(long value) throws IOException {
+      if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+        long pos = ARRAY_BASE_OFFSET + position;
+        while (true) {
+          if ((value & ~0x7FL) == 0) {
+            UNSAFE.putByte(buffer, pos++, (byte) value);
+            position++;
+            return;
+          } else {
+            UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+            position++;
+            value >>>= 7;
+          }
+        }
+      } else {
+        try {
+          while (true) {
+            if ((value & ~0x7FL) == 0) {
+              buffer[position++] = (byte) value;
+              return;
+            } else {
+              buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+              value >>>= 7;
+            }
+          }
+        } catch (IndexOutOfBoundsException e) {
+          throw new OutOfSpaceException(
+              new IndexOutOfBoundsException(
+                  String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+        }
+      }
+    }
+
+    @Override
+    public final void writeFixed64NoTag(long value) throws IOException {
+      try {
+        buffer[position++] = (byte) ((int) (value) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+        buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(
+            new IndexOutOfBoundsException(
+                String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+      }
+    }
+
+    @Override
+    public final void write(byte[] value, int offset, int length) throws IOException {
+      try {
+        System.arraycopy(value, offset, buffer, position, length);
+        position += length;
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(
+            new IndexOutOfBoundsException(
+                String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
+      }
+    }
+
+    @Override
+    public final void writeLazy(byte[] value, int offset, int length) throws IOException {
+      write(value, offset, length);
+    }
+
+    @Override
+    public final void write(ByteBuffer value) throws IOException {
+      final int length = value.remaining();
+      try {
+        value.get(buffer, position, length);
+        position += length;
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(
+            new IndexOutOfBoundsException(
+                String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
+      }
+    }
+
+    @Override
+    public final void writeLazy(ByteBuffer value) throws IOException {
+      write(value);
+    }
+
+    @Override
+    public final void writeStringNoTag(String value) throws IOException {
+      final int oldPosition = position;
+      try {
+        // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+        // and at most 3 times of it. We take advantage of this in both branches below.
+        final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+        final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+        final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+        if (minLengthVarIntSize == maxLengthVarIntSize) {
+          position = oldPosition + minLengthVarIntSize;
+          int newPosition = Utf8.encode(value, buffer, position, spaceLeft());
+          // Since this class is stateful and tracks the position, we rewind and store the state,
+          // prepend the length, then reset it back to the end of the string.
+          position = oldPosition;
+          int length = newPosition - oldPosition - minLengthVarIntSize;
+          writeUInt32NoTag(length);
+          position = newPosition;
+        } else {
+          int length = Utf8.encodedLength(value);
+          writeUInt32NoTag(length);
+          position = Utf8.encode(value, buffer, position, spaceLeft());
+        }
+      } catch (UnpairedSurrogateException e) {
+        // Roll back the change - we fall back to inefficient path.
+        position = oldPosition;
+
+        // TODO(nathanmittler): We should throw an IOException here instead.
+        inefficientWriteStringNoTag(value, e);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void flush() {
+      // Do nothing.
+    }
+
+    @Override
+    public final int spaceLeft() {
+      return limit - position;
+    }
+
+    @Override
+    public final int getTotalBytesWritten() {
+      return position - offset;
+    }
+  }
+
+  /**
+   * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are
+   * done directly to the underlying array. The buffer position is only updated after a flush.
+   */
+  private static final class NioHeapEncoder extends ArrayEncoder {
+    private final ByteBuffer byteBuffer;
+    private int initialPosition;
+
+    NioHeapEncoder(ByteBuffer byteBuffer) {
+      super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(),
+          byteBuffer.remaining());
+      this.byteBuffer = byteBuffer;
+      this.initialPosition = byteBuffer.position();
+    }
+
+    @Override
+    public void flush() {
+      // Update the position on the buffer.
+      byteBuffer.position(initialPosition + getTotalBytesWritten());
+    }
+  }
+
+  /**
+   * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}.
+   */
+  private static final class NioEncoder extends CodedOutputStream {
+    private final ByteBuffer originalBuffer;
+    private final ByteBuffer buffer;
+    private final int initialPosition;
+
+    NioEncoder(ByteBuffer buffer) {
+      this.originalBuffer = buffer;
+      this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+      initialPosition = buffer.position();
+    }
+
+    @Override
+    public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+      writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+    }
+
+    @Override
+    public void writeInt32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeInt32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeUInt32NoTag(value);
+    }
+
+    @Override
+    public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+      writeFixed32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      writeUInt64NoTag(value);
+    }
+
+    @Override
+    public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+      writeFixed64NoTag(value);
+    }
+
+    @Override
+    public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      write((byte) (value ? 1 : 0));
+    }
+
+    @Override
+    public void writeString(final int fieldNumber, final String value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeStringNoTag(value);
+    }
+
+    @Override
+    public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeBytesNoTag(value);
+    }
+
+    @Override
+    public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+      writeByteArray(fieldNumber, value, 0, value.length);
+    }
+
+    @Override
+    public void writeByteArray(
+        final int fieldNumber, final byte[] value, final int offset, final int length)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeByteArrayNoTag(value, offset, length);
+    }
+
+    @Override
+    public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeUInt32NoTag(value.capacity());
+      writeRawBytes(value);
+    }
+
+    @Override
+    public void writeMessage(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeMessageNoTag(value);
+    }
+
+    @Override
+    public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeMessageNoTag(final MessageLite value) throws IOException {
+      writeUInt32NoTag(value.getSerializedSize());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void write(byte value) throws IOException {
+      try {
+        buffer.put(value);
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeBytesNoTag(final ByteString value) throws IOException {
+      writeUInt32NoTag(value.size());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+      writeUInt32NoTag(length);
+      write(value, offset, length);
+    }
+
+    @Override
+    public void writeRawBytes(final ByteBuffer value) throws IOException {
+      if (value.hasArray()) {
+        write(value.array(), value.arrayOffset(), value.capacity());
+      } else {
+        ByteBuffer duplicated = value.duplicate();
+        duplicated.clear();
+        write(duplicated);
+      }
+    }
+
+    @Override
+    public void writeInt32NoTag(int value) throws IOException {
+      if (value >= 0) {
+        writeUInt32NoTag(value);
+      } else {
+        // Must sign-extend.
+        writeUInt64NoTag(value);
+      }
+    }
+
+    @Override
+    public void writeUInt32NoTag(int value) throws IOException {
+      try {
+        while (true) {
+          if ((value & ~0x7F) == 0) {
+            buffer.put((byte) value);
+            return;
+          } else {
+            buffer.put((byte) ((value & 0x7F) | 0x80));
+            value >>>= 7;
+          }
+        }
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeFixed32NoTag(int value) throws IOException {
+      try {
+        buffer.putInt(value);
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeUInt64NoTag(long value) throws IOException {
+      try {
+        while (true) {
+          if ((value & ~0x7FL) == 0) {
+            buffer.put((byte) value);
+            return;
+          } else {
+            buffer.put((byte) (((int) value & 0x7F) | 0x80));
+            value >>>= 7;
+          }
+        }
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeFixed64NoTag(long value) throws IOException {
+      try {
+        buffer.putLong(value);
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void write(byte[] value, int offset, int length) throws IOException {
+      try {
+        buffer.put(value, offset, length);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(e);
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeLazy(byte[] value, int offset, int length) throws IOException {
+      write(value, offset, length);
+    }
+
+    @Override
+    public void write(ByteBuffer value) throws IOException {
+      try {
+        buffer.put(value);
+      } catch (BufferOverflowException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void writeLazy(ByteBuffer value) throws IOException {
+      write(value);
+    }
+
+    @Override
+    public void writeStringNoTag(String value) throws IOException {
+      final int startPos = buffer.position();
+      try {
+        // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+        // and at most 3 times of it. We take advantage of this in both branches below.
+        final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+        final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
+        final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+        if (minLengthVarIntSize == maxLengthVarIntSize) {
+          // Save the current position and increment past the length field. We'll come back
+          // and write the length field after the encoding is complete.
+          final int startOfBytes = buffer.position() + minLengthVarIntSize;
+          buffer.position(startOfBytes);
+
+          // Encode the string.
+          encode(value);
+
+          // Now go back to the beginning and write the length.
+          int endOfBytes = buffer.position();
+          buffer.position(startPos);
+          writeUInt32NoTag(endOfBytes - startOfBytes);
+
+          // Reposition the buffer past the written data.
+          buffer.position(endOfBytes);
+        } else {
+          final int length = Utf8.encodedLength(value);
+          writeUInt32NoTag(length);
+          encode(value);
+        }
+      } catch (UnpairedSurrogateException e) {
+        // Roll back the change and convert to an IOException.
+        buffer.position(startPos);
+
+        // TODO(nathanmittler): We should throw an IOException here instead.
+        inefficientWriteStringNoTag(value, e);
+      } catch (IllegalArgumentException e) {
+        // Thrown by buffer.position() if out of range.
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void flush() {
+      // Update the position of the original buffer.
+      originalBuffer.position(buffer.position());
+    }
+
+    @Override
+    public int spaceLeft() {
+      return buffer.remaining();
+    }
+
+    @Override
+    public int getTotalBytesWritten() {
+      return buffer.position() - initialPosition;
+    }
+
+    private void encode(String value) throws IOException {
+      try {
+        Utf8.encodeUtf8(value, buffer);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+  }
+
+  /**
+   * Abstract base class for buffered encoders.
+   */
+  private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
+    final byte[] buffer;
+    final int limit;
+    int position;
+    int totalBytesWritten;
+
+    AbstractBufferedEncoder(int bufferSize) {
+      if (bufferSize < 0) {
+        throw new IllegalArgumentException("bufferSize must be >= 0");
+      }
+      // As an optimization, we require that the buffer be able to store at least 2
+      // varints so that we can buffer any integer write (tag + value). This reduces the
+      // number of range checks for a single write to 1 (i.e. if there is not enough space
+      // to buffer the tag+value, flush and then buffer it).
+      this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)];
+      this.limit = buffer.length;
+    }
+
+    @Override
+    public final int spaceLeft() {
+      throw new UnsupportedOperationException(
+          "spaceLeft() can only be called on CodedOutputStreams that are "
+              + "writing to a flat array or ByteBuffer.");
+    }
+
+    @Override
+    public final int getTotalBytesWritten() {
+      return totalBytesWritten;
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void buffer(byte value) {
+      buffer[position++] = value;
+      totalBytesWritten++;
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferTag(final int fieldNumber, final int wireType) {
+      bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferInt32NoTag(final int value) {
+      if (value >= 0) {
+        bufferUInt32NoTag(value);
+      } else {
+        // Must sign-extend.
+        bufferUInt64NoTag(value);
+      }
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferUInt32NoTag(int value) {
+      if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+        final long originalPos = ARRAY_BASE_OFFSET + position;
+        long pos = originalPos;
+        while (true) {
+          if ((value & ~0x7F) == 0) {
+            UNSAFE.putByte(buffer, pos++, (byte) value);
+            break;
+          } else {
+            UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+            value >>>= 7;
+          }
+        }
+        int delta = (int) (pos - originalPos);
+        position += delta;
+        totalBytesWritten += delta;
+      } else {
+        while (true) {
+          if ((value & ~0x7F) == 0) {
+            buffer[position++] = (byte) value;
+            totalBytesWritten++;
+            return;
+          } else {
+            buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+            totalBytesWritten++;
+            value >>>= 7;
+          }
+        }
+      }
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferUInt64NoTag(long value) {
+      if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+        final long originalPos = ARRAY_BASE_OFFSET + position;
+        long pos = originalPos;
+        while (true) {
+          if ((value & ~0x7FL) == 0) {
+            UNSAFE.putByte(buffer, pos++, (byte) value);
+            break;
+          } else {
+            UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+            value >>>= 7;
+          }
+        }
+        int delta = (int) (pos - originalPos);
+        position += delta;
+        totalBytesWritten += delta;
+      } else {
+        while (true) {
+          if ((value & ~0x7FL) == 0) {
+            buffer[position++] = (byte) value;
+            totalBytesWritten++;
+            return;
+          } else {
+            buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+            totalBytesWritten++;
+            value >>>= 7;
+          }
+        }
+      }
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferFixed32NoTag(int value) {
+      buffer[position++] = (byte) (value & 0xFF);
+      buffer[position++] = (byte) ((value >> 8) & 0xFF);
+      buffer[position++] = (byte) ((value >> 16) & 0xFF);
+      buffer[position++] = (byte) ((value >> 24) & 0xFF);
+      totalBytesWritten += FIXED_32_SIZE;
+    }
+
+    /**
+     * This method does not perform bounds checking on the array. Checking array bounds is the
+     * responsibility of the caller.
+     */
+    final void bufferFixed64NoTag(long value) {
+      buffer[position++] = (byte) (value & 0xFF);
+      buffer[position++] = (byte) ((value >> 8) & 0xFF);
+      buffer[position++] = (byte) ((value >> 16) & 0xFF);
+      buffer[position++] = (byte) ((value >> 24) & 0xFF);
+      buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+      buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+      buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+      buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+      totalBytesWritten += FIXED_64_SIZE;
+    }
+  }
+
+  /**
+   * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to
+   * support string encoding operations. All other writes are just passed through to the
+   * {@link ByteOutput}.
+   */
+  private static final class ByteOutputEncoder extends AbstractBufferedEncoder {
+    private final ByteOutput out;
+
+    ByteOutputEncoder(ByteOutput out, int bufferSize) {
+      super(bufferSize);
+      if (out == null) {
+        throw new NullPointerException("out");
+      }
+      this.out = out;
+    }
+
+    @Override
+    public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+      writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+    }
+
+    @Override
+    public void writeInt32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferInt32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferUInt32NoTag(value);
+    }
+
+    @Override
+    public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+      bufferFixed32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferUInt64NoTag(value);
+    }
+
+    @Override
+    public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+      bufferFixed64NoTag(value);
+    }
+
+    @Override
+    public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      buffer((byte) (value ? 1 : 0));
+    }
+
+    @Override
+    public void writeString(final int fieldNumber, final String value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeStringNoTag(value);
+    }
+
+    @Override
+    public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeBytesNoTag(value);
+    }
+
+    @Override
+    public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+      writeByteArray(fieldNumber, value, 0, value.length);
+    }
+
+    @Override
+    public void writeByteArray(
+        final int fieldNumber, final byte[] value, final int offset, final int length)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeByteArrayNoTag(value, offset, length);
+    }
+
+    @Override
+    public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeUInt32NoTag(value.capacity());
+      writeRawBytes(value);
+    }
+
+    @Override
+    public void writeBytesNoTag(final ByteString value) throws IOException {
+      writeUInt32NoTag(value.size());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+      writeUInt32NoTag(length);
+      write(value, offset, length);
+    }
+
+    @Override
+    public void writeRawBytes(final ByteBuffer value) throws IOException {
+      if (value.hasArray()) {
+        write(value.array(), value.arrayOffset(), value.capacity());
+      } else {
+        ByteBuffer duplicated = value.duplicate();
+        duplicated.clear();
+        write(duplicated);
+      }
+    }
+
+    @Override
+    public void writeMessage(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeMessageNoTag(value);
+    }
+
+    @Override
+    public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeMessageNoTag(final MessageLite value) throws IOException {
+      writeUInt32NoTag(value.getSerializedSize());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void write(byte value) throws IOException {
+      if (position == limit) {
+        doFlush();
+      }
+
+      buffer(value);
+    }
+
+    @Override
+    public void writeInt32NoTag(int value) throws IOException {
+      if (value >= 0) {
+        writeUInt32NoTag(value);
+      } else {
+        // Must sign-extend.
+        writeUInt64NoTag(value);
+      }
+    }
+
+    @Override
+    public void writeUInt32NoTag(int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE);
+      bufferUInt32NoTag(value);
+    }
+
+    @Override
+    public void writeFixed32NoTag(final int value) throws IOException {
+      flushIfNotAvailable(FIXED_32_SIZE);
+      bufferFixed32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt64NoTag(long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE);
+      bufferUInt64NoTag(value);
+    }
+
+    @Override
+    public void writeFixed64NoTag(final long value) throws IOException {
+      flushIfNotAvailable(FIXED_64_SIZE);
+      bufferFixed64NoTag(value);
+    }
+
+    @Override
+    public void writeStringNoTag(String value) throws IOException {
+      // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+      // and at most 3 times of it. We take advantage of this in both branches below.
+      final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+      final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+      // If we are streaming and the potential length is too big to fit in our buffer, we take the
+      // slower path.
+      if (maxLengthVarIntSize + maxLength > limit) {
+        // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+        // does the same internally and then does *another copy* to return a byte[] of exactly the
+        // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+        // UTF-8 encoded bytes.
+        final byte[] encodedBytes = new byte[maxLength];
+        int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+        writeUInt32NoTag(actualLength);
+        writeLazy(encodedBytes, 0, actualLength);
+        return;
+      }
+
+      // Fast path: we have enough space available in our buffer for the string...
+      if (maxLengthVarIntSize + maxLength > limit - position) {
+        // Flush to free up space.
+        doFlush();
+      }
+
+      final int oldPosition = position;
+      try {
+        // Optimize for the case where we know this length results in a constant varint length as
+        // this saves a pass for measuring the length of the string.
+        final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+
+        if (minLengthVarIntSize == maxLengthVarIntSize) {
+          position = oldPosition + minLengthVarIntSize;
+          int newPosition = Utf8.encode(value, buffer, position, limit - position);
+          // Since this class is stateful and tracks the position, we rewind and store the state,
+          // prepend the length, then reset it back to the end of the string.
+          position = oldPosition;
+          int length = newPosition - oldPosition - minLengthVarIntSize;
+          bufferUInt32NoTag(length);
+          position = newPosition;
+          totalBytesWritten += length;
+        } else {
+          int length = Utf8.encodedLength(value);
+          bufferUInt32NoTag(length);
+          position = Utf8.encode(value, buffer, position, length);
+          totalBytesWritten += length;
+        }
+      } catch (UnpairedSurrogateException e) {
+        // Roll back the change and convert to an IOException.
+        totalBytesWritten -= position - oldPosition;
+        position = oldPosition;
+
+        // TODO(nathanmittler): We should throw an IOException here instead.
+        inefficientWriteStringNoTag(value, e);
+      } catch (IndexOutOfBoundsException e) {
+        throw new OutOfSpaceException(e);
+      }
+    }
+
+    @Override
+    public void flush() throws IOException {
+      if (position > 0) {
+        // Flush the buffer.
+        doFlush();
+      }
+    }
+
+    @Override
+    public void write(byte[] value, int offset, int length) throws IOException {
+      flush();
+      out.write(value, offset, length);
+      totalBytesWritten += length;
+    }
+
+    @Override
+    public void writeLazy(byte[] value, int offset, int length) throws IOException {
+      flush();
+      out.writeLazy(value, offset, length);
+      totalBytesWritten += length;
+    }
+
+    @Override
+    public void write(ByteBuffer value) throws IOException {
+      flush();
+      int length = value.remaining();
+      out.write(value);
+      totalBytesWritten += length;
+    }
+
+    @Override
+    public void writeLazy(ByteBuffer value) throws IOException {
+      flush();
+      int length = value.remaining();
+      out.writeLazy(value);
+      totalBytesWritten += length;
+    }
+
+    private void flushIfNotAvailable(int requiredSize) throws IOException {
+      if (limit - position < requiredSize) {
+        doFlush();
+      }
+    }
+
+    private void doFlush() throws IOException {
+      out.write(buffer, 0, position);
+      position = 0;
+    }
+  }
+
+  /**
+   * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal
+   * buffering to optimize writes to the {@link OutputStream}.
+   */
+  private static final class OutputStreamEncoder extends AbstractBufferedEncoder {
+    private final OutputStream out;
+
+    OutputStreamEncoder(OutputStream out, int bufferSize) {
+      super(bufferSize);
+      if (out == null) {
+        throw new NullPointerException("out");
+      }
+      this.out = out;
+    }
+
+    @Override
+    public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+      writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+    }
+
+    @Override
+    public void writeInt32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferInt32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferUInt32NoTag(value);
+    }
+
+    @Override
+    public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+      bufferFixed32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      bufferUInt64NoTag(value);
+    }
+
+    @Override
+    public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+      bufferFixed64NoTag(value);
+    }
+
+    @Override
+    public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+      bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+      buffer((byte) (value ? 1 : 0));
+    }
+
+    @Override
+    public void writeString(final int fieldNumber, final String value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeStringNoTag(value);
+    }
+
+    @Override
+    public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeBytesNoTag(value);
+    }
+
+    @Override
+    public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+      writeByteArray(fieldNumber, value, 0, value.length);
+    }
+
+    @Override
+    public void writeByteArray(
+        final int fieldNumber, final byte[] value, final int offset, final int length)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeByteArrayNoTag(value, offset, length);
+    }
+
+    @Override
+    public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeUInt32NoTag(value.capacity());
+      writeRawBytes(value);
+    }
+
+    @Override
+    public void writeBytesNoTag(final ByteString value) throws IOException {
+      writeUInt32NoTag(value.size());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+      writeUInt32NoTag(length);
+      write(value, offset, length);
+    }
+
+    @Override
+    public void writeRawBytes(final ByteBuffer value) throws IOException {
+      if (value.hasArray()) {
+        write(value.array(), value.arrayOffset(), value.capacity());
+      } else {
+        ByteBuffer duplicated = value.duplicate();
+        duplicated.clear();
+        write(duplicated);
+      }
+    }
+
+    @Override
+    public void writeMessage(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+      writeMessageNoTag(value);
+    }
+
+    @Override
+    public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+        throws IOException {
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+      writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+      writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+      writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+    }
+
+    @Override
+    public void writeMessageNoTag(final MessageLite value) throws IOException {
+      writeUInt32NoTag(value.getSerializedSize());
+      value.writeTo(this);
+    }
+
+    @Override
+    public void write(byte value) throws IOException {
+      if (position == limit) {
+        doFlush();
+      }
+
+      buffer(value);
+    }
+
+    @Override
+    public void writeInt32NoTag(int value) throws IOException {
+      if (value >= 0) {
+        writeUInt32NoTag(value);
+      } else {
+        // Must sign-extend.
+        writeUInt64NoTag(value);
+      }
+    }
+
+    @Override
+    public void writeUInt32NoTag(int value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE);
+      bufferUInt32NoTag(value);
+    }
+
+    @Override
+    public void writeFixed32NoTag(final int value) throws IOException {
+      flushIfNotAvailable(FIXED_32_SIZE);
+      bufferFixed32NoTag(value);
+    }
+
+    @Override
+    public void writeUInt64NoTag(long value) throws IOException {
+      flushIfNotAvailable(MAX_VARINT_SIZE);
+      bufferUInt64NoTag(value);
+    }
+
+    @Override
+    public void writeFixed64NoTag(final long value) throws IOException {
+      flushIfNotAvailable(FIXED_64_SIZE);
+      bufferFixed64NoTag(value);
+    }
+
+    @Override
+    public void writeStringNoTag(String value) throws IOException {
+      try {
+        // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+        // and at most 3 times of it. We take advantage of this in both branches below.
+        final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+        final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+        // If we are streaming and the potential length is too big to fit in our buffer, we take the
+        // slower path.
+        if (maxLengthVarIntSize + maxLength > limit) {
+          // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+          // does the same internally and then does *another copy* to return a byte[] of exactly the
+          // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+          // UTF-8 encoded bytes.
+          final byte[] encodedBytes = new byte[maxLength];
+          int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+          writeUInt32NoTag(actualLength);
+          writeLazy(encodedBytes, 0, actualLength);
+          return;
+        }
+
+        // Fast path: we have enough space available in our buffer for the string...
+        if (maxLengthVarIntSize + maxLength > limit - position) {
+          // Flush to free up space.
+          doFlush();
+        }
+
+        // Optimize for the case where we know this length results in a constant varint length as
+        // this saves a pass for measuring the length of the string.
+        final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+        int oldPosition = position;
+        final int length;
+        try {
+          if (minLengthVarIntSize == maxLengthVarIntSize) {
+            position = oldPosition + minLengthVarIntSize;
+            int newPosition = Utf8.encode(value, buffer, position, limit - position);
+            // Since this class is stateful and tracks the position, we rewind and store the
+            // state, prepend the length, then reset it back to the end of the string.
+            position = oldPosition;
+            length = newPosition - oldPosition - minLengthVarIntSize;
+            bufferUInt32NoTag(length);
+            position = newPosition;
+          } else {
+            length = Utf8.encodedLength(value);
+            bufferUInt32NoTag(length);
+            position = Utf8.encode(value, buffer, position, length);
+          }
+          totalBytesWritten += length;
+        } catch (UnpairedSurrogateException e) {
+          // Be extra careful and restore the original position for retrying the write with the
+          // less efficient path.
+          totalBytesWritten -= position - oldPosition;
+          position = oldPosition;
+          throw e;
+        } catch (ArrayIndexOutOfBoundsException e) {
+          throw new OutOfSpaceException(e);
+        }
+      } catch (UnpairedSurrogateException e) {
+        inefficientWriteStringNoTag(value, e);
+      }
+    }
+
+    @Override
+    public void flush() throws IOException {
+      if (position > 0) {
+        // Flush the buffer.
+        doFlush();
+      }
+    }
+
+    @Override
+    public void write(byte[] value, int offset, int length)
+        throws IOException {
+      if (limit - position >= length) {
+        // We have room in the current buffer.
+        System.arraycopy(value, offset, buffer, position, length);
+        position += length;
+        totalBytesWritten += length;
+      } else {
+        // Write extends past current buffer.  Fill the rest of this buffer and
+        // flush.
+        final int bytesWritten = limit - position;
+        System.arraycopy(value, offset, buffer, position, bytesWritten);
+        offset += bytesWritten;
+        length -= bytesWritten;
+        position = limit;
+        totalBytesWritten += bytesWritten;
+        doFlush();
+
+        // Now deal with the rest.
+        // Since we have an output stream, this is our buffer
+        // and buffer offset == 0
+        if (length <= limit) {
+          // Fits in new buffer.
+          System.arraycopy(value, offset, buffer, 0, length);
+          position = length;
+        } else {
+          // Write is very big.  Let's do it all at once.
+          out.write(value, offset, length);
+        }
+        totalBytesWritten += length;
+      }
+    }
+
+    @Override
+    public void writeLazy(byte[] value, int offset, int length) throws IOException {
+      write(value, offset, length);
+    }
+
+    @Override
+    public void write(ByteBuffer value) throws IOException {
+      int length = value.remaining();
+      if (limit - position >= length) {
+        // We have room in the current buffer.
+        value.get(buffer, position, length);
+        position += length;
+        totalBytesWritten += length;
+      } else {
+        // Write extends past current buffer.  Fill the rest of this buffer and
+        // flush.
+        final int bytesWritten = limit - position;
+        value.get(buffer, position, bytesWritten);
+        length -= bytesWritten;
+        position = limit;
+        totalBytesWritten += bytesWritten;
+        doFlush();
+
+        // Now deal with the rest.
+        // Since we have an output stream, this is our buffer
+        // and buffer offset == 0
+        while (length > limit) {
+          // Copy data into the buffer before writing it to OutputStream.
+          value.get(buffer, 0, limit);
+          out.write(buffer, 0, limit);
+          length -= limit;
+          totalBytesWritten += limit;
+        }
+        value.get(buffer, 0, length);
+        position = length;
+        totalBytesWritten += length;
+      }
+    }
+
+    @Override
+    public void writeLazy(ByteBuffer value) throws IOException {
+      write(value);
+    }
+
+    private void flushIfNotAvailable(int requiredSize) throws IOException {
+      if (limit - position < requiredSize) {
+        doFlush();
+      }
+    }
+
+    private void doFlush() throws IOException {
+      out.write(buffer, 0, position);
+      position = 0;
+    }
+  }
+
+  /**
+   * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
+   * platform.
+   */
+  private static sun.misc.Unsafe getUnsafe() {
+    sun.misc.Unsafe unsafe = null;
+    try {
+      unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+        @Override
+        public sun.misc.Unsafe run() throws Exception {
+          Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+          for (Field f : k.getDeclaredFields()) {
+            f.setAccessible(true);
+            Object x = f.get(null);
+            if (k.isInstance(x)) {
+              return k.cast(x);
+            }
+          }
+          // The sun.misc.Unsafe field does not exist.
+          return null;
+        }
+      });
+    } catch (Throwable e) {
+      // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
+      // for Unsafe.
+    }
+
+    logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
+        unsafe != null ? "available" : "unavailable");
+    return unsafe;
+  }
+
+  /**
+   * Indicates whether or not unsafe array operations are supported on this platform.
+   */
+  // TODO(nathanmittler): Add support for Android's MemoryBlock.
+  private static boolean supportsUnsafeArrayOperations() {
+    boolean supported = false;
+    if (UNSAFE != null) {
+      try {
+        UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class);
+        UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class);
+        supported = true;
+      } catch (Throwable e) {
+        // Do nothing.
+      }
+    }
+    logger.log(Level.FINEST, "Unsafe array operations: {}",
+        supported ? "available" : "unavailable");
+    return supported;
+  }
+
+  /**
+   * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
+   * available.
+   */
+  private static <T> int byteArrayBaseOffset() {
+    return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Descriptors.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Descriptors.java
new file mode 100644
index 0000000..e00ea34
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -0,0 +1,2548 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.DescriptorProtos.*;
+import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.logging.Logger;
+
+/**
+ * Contains a collection of classes which describe protocol message types.
+ *
+ * Every message type has a {@link Descriptor}, which lists all
+ * its fields and other information about a type.  You can get a message
+ * type's descriptor by calling {@code MessageType.getDescriptor()}, or
+ * (given a message object of the type) {@code message.getDescriptorForType()}.
+ * Furthermore, each message is associated with a {@link FileDescriptor} for
+ * a relevant {@code .proto} file. You can obtain it by calling
+ * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors
+ * for all the messages defined in that file, and file descriptors for all the
+ * imported {@code .proto} files.
+ *
+ * Descriptors are built from DescriptorProtos, as defined in
+ * {@code google/protobuf/descriptor.proto}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class Descriptors {
+  private static final Logger logger =
+      Logger.getLogger(Descriptors.class.getName());
+  /**
+   * Describes a {@code .proto} file, including everything defined within.
+   * That includes, in particular, descriptors for all the messages and
+   * file descriptors for all other imported {@code .proto} files
+   * (dependencies).
+   */
+  public static final class FileDescriptor extends GenericDescriptor {
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public FileDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the file name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /** Returns this object. */
+    @Override
+    public FileDescriptor getFile() {
+      return this;
+    }
+
+    /** Returns the same as getName(). */
+    @Override
+    public String getFullName() {
+      return proto.getName();
+    }
+
+    /**
+     * Get the proto package name.  This is the package name given by the
+     * {@code package} statement in the {@code .proto} file, which differs
+     * from the Java package.
+     */
+    public String getPackage() { return proto.getPackage(); }
+
+    /** Get the {@code FileOptions}, defined in {@code descriptor.proto}. */
+    public FileOptions getOptions() { return proto.getOptions(); }
+
+    /** Get a list of top-level message types declared in this file. */
+    public List<Descriptor> getMessageTypes() {
+      return Collections.unmodifiableList(Arrays.asList(messageTypes));
+    }
+
+    /** Get a list of top-level enum types declared in this file. */
+    public List<EnumDescriptor> getEnumTypes() {
+      return Collections.unmodifiableList(Arrays.asList(enumTypes));
+    }
+
+    /** Get a list of top-level services declared in this file. */
+    public List<ServiceDescriptor> getServices() {
+      return Collections.unmodifiableList(Arrays.asList(services));
+    }
+
+    /** Get a list of top-level extensions declared in this file. */
+    public List<FieldDescriptor> getExtensions() {
+      return Collections.unmodifiableList(Arrays.asList(extensions));
+    }
+
+    /** Get a list of this file's dependencies (imports). */
+    public List<FileDescriptor> getDependencies() {
+      return Collections.unmodifiableList(Arrays.asList(dependencies));
+    }
+
+    /** Get a list of this file's public dependencies (public imports). */
+    public List<FileDescriptor> getPublicDependencies() {
+      return Collections.unmodifiableList(Arrays.asList(publicDependencies));
+    }
+
+    /** The syntax of the .proto file. */
+    public enum Syntax {
+      UNKNOWN("unknown"),
+      PROTO2("proto2"),
+      PROTO3("proto3");
+
+      Syntax(String name) {
+        this.name = name;
+      }
+      private final String name;
+    }
+
+    /** Get the syntax of the .proto file. */
+    public Syntax getSyntax() {
+      if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
+        return Syntax.PROTO3;
+      }
+      return Syntax.PROTO2;
+    }
+
+    /**
+     * Find a message type in the file by name.  Does not find nested types.
+     *
+     * @param name The unqualified type name to look for.
+     * @return The message type's descriptor, or {@code null} if not found.
+     */
+    public Descriptor findMessageTypeByName(String name) {
+      // Don't allow looking up nested types.  This will make optimization
+      // easier later.
+      if (name.indexOf('.') != -1) {
+        return null;
+      }
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
+      if (result != null && result instanceof Descriptor &&
+          result.getFile() == this) {
+        return (Descriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Find an enum type in the file by name.  Does not find nested types.
+     *
+     * @param name The unqualified type name to look for.
+     * @return The enum type's descriptor, or {@code null} if not found.
+     */
+    public EnumDescriptor findEnumTypeByName(String name) {
+      // Don't allow looking up nested types.  This will make optimization
+      // easier later.
+      if (name.indexOf('.') != -1) {
+        return null;
+      }
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
+      if (result != null && result instanceof EnumDescriptor &&
+          result.getFile() == this) {
+        return (EnumDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Find a service type in the file by name.
+     *
+     * @param name The unqualified type name to look for.
+     * @return The service type's descriptor, or {@code null} if not found.
+     */
+    public ServiceDescriptor findServiceByName(String name) {
+      // Don't allow looking up nested types.  This will make optimization
+      // easier later.
+      if (name.indexOf('.') != -1) {
+        return null;
+      }
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
+      if (result != null && result instanceof ServiceDescriptor &&
+          result.getFile() == this) {
+        return (ServiceDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Find an extension in the file by name.  Does not find extensions nested
+     * inside message types.
+     *
+     * @param name The unqualified extension name to look for.
+     * @return The extension's descriptor, or {@code null} if not found.
+     */
+    public FieldDescriptor findExtensionByName(String name) {
+      if (name.indexOf('.') != -1) {
+        return null;
+      }
+      if (getPackage().length() > 0) {
+        name = getPackage() + '.' + name;
+      }
+      final GenericDescriptor result = pool.findSymbol(name);
+      if (result != null && result instanceof FieldDescriptor &&
+          result.getFile() == this) {
+        return (FieldDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Construct a {@code FileDescriptor}.
+     *
+     * @param proto The protocol message form of the FileDescriptor.
+     * @param dependencies {@code FileDescriptor}s corresponding to all of
+     *                     the file's dependencies.
+     * @throws DescriptorValidationException {@code proto} is not a valid
+     *           descriptor.  This can occur for a number of reasons, e.g.
+     *           because a field has an undefined type or because two messages
+     *           were defined with the same name.
+     */
+    public static FileDescriptor buildFrom(final FileDescriptorProto proto,
+                                           final FileDescriptor[] dependencies)
+                                    throws DescriptorValidationException {
+      return buildFrom(proto, dependencies, false);
+    }
+
+
+    /**
+     * Construct a {@code FileDescriptor}.
+     *
+     * @param proto The protocol message form of the FileDescriptor.
+     * @param dependencies {@code FileDescriptor}s corresponding to all of
+     *                     the file's dependencies.
+     * @param allowUnknownDependencies If true, non-exist dependenncies will be
+     *           ignored and undefined message types will be replaced with a
+     *           placeholder type.
+     * @throws DescriptorValidationException {@code proto} is not a valid
+     *           descriptor.  This can occur for a number of reasons, e.g.
+     *           because a field has an undefined type or because two messages
+     *           were defined with the same name.
+     */
+    public static FileDescriptor buildFrom(
+        final FileDescriptorProto proto, final FileDescriptor[] dependencies,
+        final boolean allowUnknownDependencies)
+        throws DescriptorValidationException {
+      // Building descriptors involves two steps:  translating and linking.
+      // In the translation step (implemented by FileDescriptor's
+      // constructor), we build an object tree mirroring the
+      // FileDescriptorProto's tree and put all of the descriptors into the
+      // DescriptorPool's lookup tables.  In the linking step, we look up all
+      // type references in the DescriptorPool, so that, for example, a
+      // FieldDescriptor for an embedded message contains a pointer directly
+      // to the Descriptor for that message's type.  We also detect undefined
+      // types in the linking step.
+      final DescriptorPool pool = new DescriptorPool(
+          dependencies, allowUnknownDependencies);
+      final FileDescriptor result = new FileDescriptor(
+          proto, dependencies, pool, allowUnknownDependencies);
+      result.crossLink();
+      return result;
+    }
+
+    /**
+     * This method is to be called by generated code only.  It is equivalent
+     * to {@code buildFrom} except that the {@code FileDescriptorProto} is
+     * encoded in protocol buffer wire format.
+     */
+    public static void internalBuildGeneratedFileFrom(
+        final String[] descriptorDataParts,
+        final FileDescriptor[] dependencies,
+        final InternalDescriptorAssigner descriptorAssigner) {
+      // Hack:  We can't embed a raw byte array inside generated Java code
+      //   (at least, not efficiently), but we can embed Strings.  So, the
+      //   protocol compiler embeds the FileDescriptorProto as a giant
+      //   string literal which is passed to this function to construct the
+      //   file's FileDescriptor.  The string literal contains only 8-bit
+      //   characters, each one representing a byte of the FileDescriptorProto's
+      //   serialized form.  So, if we convert it to bytes in ISO-8859-1, we
+      //   should get the original bytes that we want.
+
+      // descriptorData may contain multiple strings in order to get around the
+      // Java 64k string literal limit.
+      StringBuilder descriptorData = new StringBuilder();
+      for (String part : descriptorDataParts) {
+        descriptorData.append(part);
+      }
+
+      final byte[] descriptorBytes;
+      descriptorBytes = descriptorData.toString().getBytes(Internal.ISO_8859_1);
+
+      FileDescriptorProto proto;
+      try {
+        proto = FileDescriptorProto.parseFrom(descriptorBytes);
+      } catch (InvalidProtocolBufferException e) {
+        throw new IllegalArgumentException(
+          "Failed to parse protocol buffer descriptor for generated code.", e);
+      }
+
+      final FileDescriptor result;
+      try {
+        // When building descriptors for generated code, we allow unknown
+        // dependencies by default.
+        result = buildFrom(proto, dependencies, true);
+      } catch (DescriptorValidationException e) {
+        throw new IllegalArgumentException(
+          "Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
+      }
+
+      final ExtensionRegistry registry =
+          descriptorAssigner.assignDescriptors(result);
+
+      if (registry != null) {
+        // We must re-parse the proto using the registry.
+        try {
+          proto = FileDescriptorProto.parseFrom(descriptorBytes, registry);
+        } catch (InvalidProtocolBufferException e) {
+          throw new IllegalArgumentException(
+            "Failed to parse protocol buffer descriptor for generated code.",
+            e);
+        }
+
+        result.setProto(proto);
+      }
+    }
+
+    /**
+     * This method is to be called by generated code only.  It uses Java
+     * reflection to load the dependencies' descriptors.
+     */
+    public static void internalBuildGeneratedFileFrom(
+        final String[] descriptorDataParts,
+        final Class<?> descriptorOuterClass,
+        final String[] dependencies,
+        final String[] dependencyFileNames,
+        final InternalDescriptorAssigner descriptorAssigner) {
+      List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+      for (int i = 0; i < dependencies.length; i++) {
+        try {
+          Class<?> clazz =
+              descriptorOuterClass.getClassLoader().loadClass(dependencies[i]);
+          descriptors.add(
+              (FileDescriptor) clazz.getField("descriptor").get(null));
+        } catch (Exception e) {
+          // We allow unknown dependencies by default. If a dependency cannot
+          // be found we only generate a warning.
+          logger.warning("Descriptors for \"" + dependencyFileNames[i] +
+              "\" can not be found.");
+        }
+      }
+      FileDescriptor[] descriptorArray = new FileDescriptor[descriptors.size()];
+      descriptors.toArray(descriptorArray);
+      internalBuildGeneratedFileFrom(
+          descriptorDataParts, descriptorArray, descriptorAssigner);
+    }
+
+    /**
+     * This method is to be called by generated code only.  It is used to
+     * update the FileDescriptorProto associated with the descriptor by
+     * parsing it again with the given ExtensionRegistry. This is needed to
+     * recognize custom options.
+     */
+    public static void internalUpdateFileDescriptor(
+        final FileDescriptor descriptor,
+        final ExtensionRegistry registry) {
+      ByteString bytes = descriptor.proto.toByteString();
+      FileDescriptorProto proto;
+      try {
+        proto = FileDescriptorProto.parseFrom(bytes, registry);
+      } catch (InvalidProtocolBufferException e) {
+        throw new IllegalArgumentException(
+          "Failed to parse protocol buffer descriptor for generated code.", e);
+      }
+      descriptor.setProto(proto);
+    }
+
+    /**
+     * This class should be used by generated code only.  When calling
+     * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller
+     * provides a callback implementing this interface.  The callback is called
+     * after the FileDescriptor has been constructed, in order to assign all
+     * the global variables defined in the generated code which point at parts
+     * of the FileDescriptor.  The callback returns an ExtensionRegistry which
+     * contains any extensions which might be used in the descriptor -- that
+     * is, extensions of the various "Options" messages defined in
+     * descriptor.proto.  The callback may also return null to indicate that
+     * no extensions are used in the descriptor.
+     */
+    public interface InternalDescriptorAssigner {
+      ExtensionRegistry assignDescriptors(FileDescriptor root);
+    }
+
+    private FileDescriptorProto proto;
+    private final Descriptor[] messageTypes;
+    private final EnumDescriptor[] enumTypes;
+    private final ServiceDescriptor[] services;
+    private final FieldDescriptor[] extensions;
+    private final FileDescriptor[] dependencies;
+    private final FileDescriptor[] publicDependencies;
+    private final DescriptorPool pool;
+
+    private FileDescriptor(final FileDescriptorProto proto,
+                           final FileDescriptor[] dependencies,
+                           final DescriptorPool pool,
+                           boolean allowUnknownDependencies)
+                    throws DescriptorValidationException {
+      this.pool = pool;
+      this.proto = proto;
+      this.dependencies = dependencies.clone();
+      HashMap<String, FileDescriptor> nameToFileMap =
+          new HashMap<String, FileDescriptor>();
+      for (FileDescriptor file : dependencies) {
+        nameToFileMap.put(file.getName(), file);
+      }
+      List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
+      for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
+        int index = proto.getPublicDependency(i);
+        if (index < 0 || index >= proto.getDependencyCount()) {
+          throw new DescriptorValidationException(this,
+              "Invalid public dependency index.");
+        }
+        String name = proto.getDependency(index);
+        FileDescriptor file = nameToFileMap.get(name);
+        if (file == null) {
+          if (!allowUnknownDependencies) {
+            throw new DescriptorValidationException(this,
+                "Invalid public dependency: " + name);
+          }
+          // Ignore unknown dependencies.
+        } else {
+          publicDependencies.add(file);
+        }
+      }
+      this.publicDependencies = new FileDescriptor[publicDependencies.size()];
+      publicDependencies.toArray(this.publicDependencies);
+
+      pool.addPackage(getPackage(), this);
+
+      messageTypes = new Descriptor[proto.getMessageTypeCount()];
+      for (int i = 0; i < proto.getMessageTypeCount(); i++) {
+        messageTypes[i] =
+          new Descriptor(proto.getMessageType(i), this, null, i);
+      }
+
+      enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+      for (int i = 0; i < proto.getEnumTypeCount(); i++) {
+        enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), this, null, i);
+      }
+
+      services = new ServiceDescriptor[proto.getServiceCount()];
+      for (int i = 0; i < proto.getServiceCount(); i++) {
+        services[i] = new ServiceDescriptor(proto.getService(i), this, i);
+      }
+
+      extensions = new FieldDescriptor[proto.getExtensionCount()];
+      for (int i = 0; i < proto.getExtensionCount(); i++) {
+        extensions[i] = new FieldDescriptor(
+          proto.getExtension(i), this, null, i, true);
+      }
+    }
+
+    /**
+     * Create a placeholder FileDescriptor for a message Descriptor.
+     */
+    FileDescriptor(String packageName, Descriptor message)
+        throws DescriptorValidationException {
+      this.pool = new DescriptorPool(new FileDescriptor[0], true);
+      this.proto = FileDescriptorProto.newBuilder()
+          .setName(message.getFullName() + ".placeholder.proto")
+          .setPackage(packageName).addMessageType(message.toProto()).build();
+      this.dependencies = new FileDescriptor[0];
+      this.publicDependencies = new FileDescriptor[0];
+
+      messageTypes = new Descriptor[] {message};
+      enumTypes = new EnumDescriptor[0];
+      services = new ServiceDescriptor[0];
+      extensions = new FieldDescriptor[0];
+
+      pool.addPackage(packageName, this);
+      pool.addSymbol(message);
+    }
+
+    /** Look up and cross-link all field types, etc. */
+    private void crossLink() throws DescriptorValidationException {
+      for (final Descriptor messageType : messageTypes) {
+        messageType.crossLink();
+      }
+
+      for (final ServiceDescriptor service : services) {
+        service.crossLink();
+      }
+
+      for (final FieldDescriptor extension : extensions) {
+        extension.crossLink();
+      }
+    }
+
+    /**
+     * Replace our {@link FileDescriptorProto} with the given one, which is
+     * identical except that it might contain extensions that weren't present
+     * in the original.  This method is needed for bootstrapping when a file
+     * defines custom options.  The options may be defined in the file itself,
+     * so we can't actually parse them until we've constructed the descriptors,
+     * but to construct the descriptors we have to have parsed the descriptor
+     * protos.  So, we have to parse the descriptor protos a second time after
+     * constructing the descriptors.
+     */
+    private void setProto(final FileDescriptorProto proto) {
+      this.proto = proto;
+
+      for (int i = 0; i < messageTypes.length; i++) {
+        messageTypes[i].setProto(proto.getMessageType(i));
+      }
+
+      for (int i = 0; i < enumTypes.length; i++) {
+        enumTypes[i].setProto(proto.getEnumType(i));
+      }
+
+      for (int i = 0; i < services.length; i++) {
+        services[i].setProto(proto.getService(i));
+      }
+
+      for (int i = 0; i < extensions.length; i++) {
+        extensions[i].setProto(proto.getExtension(i));
+      }
+    }
+
+    boolean supportsUnknownEnumValue() {
+      return getSyntax() == Syntax.PROTO3;
+    }
+  }
+
+  // =================================================================
+
+  /** Describes a message type. */
+  public static final class Descriptor extends GenericDescriptor {
+    /**
+     * Get the index of this descriptor within its parent.  In other words,
+     * given a {@link FileDescriptor} {@code file}, the following is true:
+     * <pre>
+     *   for all i in [0, file.getMessageTypeCount()):
+     *     file.getMessageType(i).getIndex() == i
+     * </pre>
+     * Similarly, for a {@link Descriptor} {@code messageType}:
+     * <pre>
+     *   for all i in [0, messageType.getNestedTypeCount()):
+     *     messageType.getNestedType(i).getIndex() == i
+     * </pre>
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public DescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the type's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /**
+     * Get the type's fully-qualified name, within the proto language's
+     * namespace.  This differs from the Java name.  For example, given this
+     * {@code .proto}:
+     * <pre>
+     *   package foo.bar;
+     *   option java_package = "com.example.protos"
+     *   message Baz {}
+     * </pre>
+     * {@code Baz}'s full name is "foo.bar.Baz".
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the {@link FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** If this is a nested type, get the outer descriptor, otherwise null. */
+    public Descriptor getContainingType() { return containingType; }
+
+    /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */
+    public MessageOptions getOptions() { return proto.getOptions(); }
+
+    /** Get a list of this message type's fields. */
+    public List<FieldDescriptor> getFields() {
+      return Collections.unmodifiableList(Arrays.asList(fields));
+    }
+
+    /** Get a list of this message type's oneofs. */
+    public List<OneofDescriptor> getOneofs() {
+      return Collections.unmodifiableList(Arrays.asList(oneofs));
+    }
+
+    /** Get a list of this message type's extensions. */
+    public List<FieldDescriptor> getExtensions() {
+      return Collections.unmodifiableList(Arrays.asList(extensions));
+    }
+
+    /** Get a list of message types nested within this one. */
+    public List<Descriptor> getNestedTypes() {
+      return Collections.unmodifiableList(Arrays.asList(nestedTypes));
+    }
+
+    /** Get a list of enum types nested within this one. */
+    public List<EnumDescriptor> getEnumTypes() {
+      return Collections.unmodifiableList(Arrays.asList(enumTypes));
+    }
+
+    /** Determines if the given field number is an extension. */
+    public boolean isExtensionNumber(final int number) {
+      for (final DescriptorProto.ExtensionRange range :
+          proto.getExtensionRangeList()) {
+        if (range.getStart() <= number && number < range.getEnd()) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /** Determines if the given field number is reserved. */
+    public boolean isReservedNumber(final int number) {
+      for (final DescriptorProto.ReservedRange range :
+          proto.getReservedRangeList()) {
+        if (range.getStart() <= number && number < range.getEnd()) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /** Determines if the given field name is reserved. */
+    public boolean isReservedName(final String name) {
+      if (name == null) {
+        throw new NullPointerException();
+      }
+      for (final String reservedName : proto.getReservedNameList()) {
+        if (reservedName.equals(name)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /**
+     * Indicates whether the message can be extended.  That is, whether it has
+     * any "extensions x to y" ranges declared on it.
+     */
+    public boolean isExtendable() {
+      return proto.getExtensionRangeList().size() != 0;
+    }
+
+    /**
+     * Finds a field by name.
+     * @param name The unqualified name of the field (e.g. "foo").
+     * @return The field's descriptor, or {@code null} if not found.
+     */
+    public FieldDescriptor findFieldByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
+      if (result != null && result instanceof FieldDescriptor) {
+        return (FieldDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Finds a field by field number.
+     * @param number The field number within this message type.
+     * @return The field's descriptor, or {@code null} if not found.
+     */
+    public FieldDescriptor findFieldByNumber(final int number) {
+      return file.pool.fieldsByNumber.get(
+        new DescriptorPool.DescriptorIntPair(this, number));
+    }
+
+    /**
+     * Finds a nested message type by name.
+     * @param name The unqualified name of the nested type (e.g. "Foo").
+     * @return The types's descriptor, or {@code null} if not found.
+     */
+    public Descriptor findNestedTypeByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
+      if (result != null && result instanceof Descriptor) {
+        return (Descriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Finds a nested enum type by name.
+     * @param name The unqualified name of the nested type (e.g. "Foo").
+     * @return The types's descriptor, or {@code null} if not found.
+     */
+    public EnumDescriptor findEnumTypeByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
+      if (result != null && result instanceof EnumDescriptor) {
+        return (EnumDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    private final int index;
+    private DescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+    private final Descriptor containingType;
+    private final Descriptor[] nestedTypes;
+    private final EnumDescriptor[] enumTypes;
+    private final FieldDescriptor[] fields;
+    private final FieldDescriptor[] extensions;
+    private final OneofDescriptor[] oneofs;
+
+    // Used to create a placeholder when the type cannot be found.
+    Descriptor(final String fullname) throws DescriptorValidationException {
+      String name = fullname;
+      String packageName = "";
+      int pos = fullname.lastIndexOf('.');
+      if (pos != -1) {
+        name = fullname.substring(pos + 1);
+        packageName = fullname.substring(0, pos);
+      }
+      this.index = 0;
+      this.proto = DescriptorProto.newBuilder().setName(name).addExtensionRange(
+          DescriptorProto.ExtensionRange.newBuilder().setStart(1)
+          .setEnd(536870912).build()).build();
+      this.fullName = fullname;
+      this.containingType = null;
+
+      this.nestedTypes = new Descriptor[0];
+      this.enumTypes = new EnumDescriptor[0];
+      this.fields = new FieldDescriptor[0];
+      this.extensions = new FieldDescriptor[0];
+      this.oneofs = new OneofDescriptor[0];
+
+      // Create a placeholder FileDescriptor to hold this message.
+      this.file = new FileDescriptor(packageName, this);
+    }
+
+    private Descriptor(final DescriptorProto proto,
+                       final FileDescriptor file,
+                       final Descriptor parent,
+                       final int index)
+                throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      fullName = computeFullName(file, parent, proto.getName());
+      this.file = file;
+      containingType = parent;
+
+      oneofs = new OneofDescriptor[proto.getOneofDeclCount()];
+      for (int i = 0; i < proto.getOneofDeclCount(); i++) {
+        oneofs[i] = new OneofDescriptor(
+          proto.getOneofDecl(i), file, this, i);
+      }
+
+      nestedTypes = new Descriptor[proto.getNestedTypeCount()];
+      for (int i = 0; i < proto.getNestedTypeCount(); i++) {
+        nestedTypes[i] = new Descriptor(
+          proto.getNestedType(i), file, this, i);
+      }
+
+      enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+      for (int i = 0; i < proto.getEnumTypeCount(); i++) {
+        enumTypes[i] = new EnumDescriptor(
+          proto.getEnumType(i), file, this, i);
+      }
+
+      fields = new FieldDescriptor[proto.getFieldCount()];
+      for (int i = 0; i < proto.getFieldCount(); i++) {
+        fields[i] = new FieldDescriptor(
+          proto.getField(i), file, this, i, false);
+      }
+
+      extensions = new FieldDescriptor[proto.getExtensionCount()];
+      for (int i = 0; i < proto.getExtensionCount(); i++) {
+        extensions[i] = new FieldDescriptor(
+          proto.getExtension(i), file, this, i, true);
+      }
+
+      for (int i = 0; i < proto.getOneofDeclCount(); i++) {
+        oneofs[i].fields = new FieldDescriptor[oneofs[i].getFieldCount()];
+        oneofs[i].fieldCount = 0;
+      }
+      for (int i = 0; i < proto.getFieldCount(); i++) {
+        OneofDescriptor oneofDescriptor = fields[i].getContainingOneof();
+        if (oneofDescriptor != null) {
+          oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i];
+        }
+      }
+
+      file.pool.addSymbol(this);
+    }
+
+    /** Look up and cross-link all field types, etc. */
+    private void crossLink() throws DescriptorValidationException {
+      for (final Descriptor nestedType : nestedTypes) {
+        nestedType.crossLink();
+      }
+
+      for (final FieldDescriptor field : fields) {
+        field.crossLink();
+      }
+
+      for (final FieldDescriptor extension : extensions) {
+        extension.crossLink();
+      }
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final DescriptorProto proto) {
+      this.proto = proto;
+
+      for (int i = 0; i < nestedTypes.length; i++) {
+        nestedTypes[i].setProto(proto.getNestedType(i));
+      }
+
+      for (int i = 0; i < enumTypes.length; i++) {
+        enumTypes[i].setProto(proto.getEnumType(i));
+      }
+
+      for (int i = 0; i < fields.length; i++) {
+        fields[i].setProto(proto.getField(i));
+      }
+
+      for (int i = 0; i < extensions.length; i++) {
+        extensions[i].setProto(proto.getExtension(i));
+      }
+    }
+  }
+
+  // =================================================================
+
+  /** Describes a field of a message type. */
+  public static final class FieldDescriptor
+        extends GenericDescriptor
+        implements Comparable<FieldDescriptor>,
+                 FieldSet.FieldDescriptorLite<FieldDescriptor> {
+    /**
+     * Get the index of this descriptor within its parent.
+     * @see Descriptors.Descriptor#getIndex()
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public FieldDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the field's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /** Get the field's number. */
+    @Override
+    public int getNumber() {
+      return proto.getNumber();
+    }
+
+    /**
+     * Get the field's fully-qualified name.
+     * @see Descriptors.Descriptor#getFullName()
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the JSON name of this field. */
+    public String getJsonName() {
+      return jsonName;
+    }
+
+    /**
+     * Get the field's java type.  This is just for convenience.  Every
+     * {@code FieldDescriptorProto.Type} maps to exactly one Java type.
+     */
+    public JavaType getJavaType() { return type.getJavaType(); }
+
+    /** For internal use only. */
+    @Override
+    public WireFormat.JavaType getLiteJavaType() {
+      return getLiteType().getJavaType();
+    }
+
+    /** Get the {@code FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** Get the field's declared type. */
+    public Type getType() { return type; }
+
+    /** For internal use only. */
+    @Override
+    public WireFormat.FieldType getLiteType() {
+      return table[type.ordinal()];
+    }
+
+    /** For internal use only. */
+    public boolean needsUtf8Check() {
+      if (type != Type.STRING) {
+        return false;
+      }
+      if (getContainingType().getOptions().getMapEntry()) {
+        // Always enforce strict UTF-8 checking for map fields.
+        return true;
+      }
+      if (getFile().getSyntax() == Syntax.PROTO3) {
+        return true;
+      }
+      return getFile().getOptions().getJavaStringCheckUtf8();
+    }
+
+    public boolean isMapField() {
+      return getType() == Type.MESSAGE && isRepeated()
+          && getMessageType().getOptions().getMapEntry();
+    }
+
+    // I'm pretty sure values() constructs a new array every time, since there
+    // is nothing stopping the caller from mutating the array.  Therefore we
+    // make a static copy here.
+    private static final WireFormat.FieldType[] table =
+        WireFormat.FieldType.values();
+
+    /** Is this field declared required? */
+    public boolean isRequired() {
+      return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
+    }
+
+    /** Is this field declared optional? */
+    public boolean isOptional() {
+      return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL;
+    }
+
+    /** Is this field declared repeated? */
+    @Override
+    public boolean isRepeated() {
+      return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
+    }
+
+    /** Does this field have the {@code [packed = true]} option or is this field
+     *  packable in proto3 and not explicitly setted to unpacked?
+     */
+    @Override
+    public boolean isPacked() {
+      if (!isPackable()) {
+        return false;
+      }
+      if (getFile().getSyntax() == FileDescriptor.Syntax.PROTO2) {
+        return getOptions().getPacked();
+      } else {
+        return !getOptions().hasPacked() || getOptions().getPacked();
+      }
+    }
+
+    /** Can this field be packed? i.e. is it a repeated primitive field? */
+    public boolean isPackable() {
+      return isRepeated() && getLiteType().isPackable();
+    }
+
+    /** Returns true if the field had an explicitly-defined default value. */
+    public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
+
+    /**
+     * Returns the field's default value.  Valid for all types except for
+     * messages and groups.  For all other types, the object returned is of
+     * the same class that would returned by Message.getField(this).
+     */
+    public Object getDefaultValue() {
+      if (getJavaType() == JavaType.MESSAGE) {
+        throw new UnsupportedOperationException(
+          "FieldDescriptor.getDefaultValue() called on an embedded message " +
+          "field.");
+      }
+      return defaultValue;
+    }
+
+    /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */
+    public FieldOptions getOptions() { return proto.getOptions(); }
+
+    /** Is this field an extension? */
+    public boolean isExtension() { return proto.hasExtendee(); }
+
+    /**
+     * Get the field's containing type. For extensions, this is the type being
+     * extended, not the location where the extension was defined.  See
+     * {@link #getExtensionScope()}.
+     */
+    public Descriptor getContainingType() { return containingType; }
+
+    /** Get the field's containing oneof. */
+    public OneofDescriptor getContainingOneof() { return containingOneof; }
+
+    /**
+     * For extensions defined nested within message types, gets the outer
+     * type.  Not valid for non-extension fields.  For example, consider
+     * this {@code .proto} file:
+     * <pre>
+     *   message Foo {
+     *     extensions 1000 to max;
+     *   }
+     *   extend Foo {
+     *     optional int32 baz = 1234;
+     *   }
+     *   message Bar {
+     *     extend Foo {
+     *       optional int32 qux = 4321;
+     *     }
+     *   }
+     * </pre>
+     * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}.
+     * However, {@code baz}'s extension scope is {@code null} while
+     * {@code qux}'s extension scope is {@code Bar}.
+     */
+    public Descriptor getExtensionScope() {
+      if (!isExtension()) {
+        throw new UnsupportedOperationException(
+          "This field is not an extension.");
+      }
+      return extensionScope;
+    }
+
+    /** For embedded message and group fields, gets the field's type. */
+    public Descriptor getMessageType() {
+      if (getJavaType() != JavaType.MESSAGE) {
+        throw new UnsupportedOperationException(
+          "This field is not of message type.");
+      }
+      return messageType;
+    }
+
+    /** For enum fields, gets the field's type. */
+    @Override
+    public EnumDescriptor getEnumType() {
+      if (getJavaType() != JavaType.ENUM) {
+        throw new UnsupportedOperationException(
+          "This field is not of enum type.");
+      }
+      return enumType;
+    }
+
+    /**
+     * Compare with another {@code FieldDescriptor}.  This orders fields in
+     * "canonical" order, which simply means ascending order by field number.
+     * {@code other} must be a field of the same type -- i.e.
+     * {@code getContainingType()} must return the same {@code Descriptor} for
+     * both fields.
+     *
+     * @return negative, zero, or positive if {@code this} is less than,
+     *         equal to, or greater than {@code other}, respectively.
+     */
+    @Override
+    public int compareTo(final FieldDescriptor other) {
+      if (other.containingType != containingType) {
+        throw new IllegalArgumentException(
+          "FieldDescriptors can only be compared to other FieldDescriptors " +
+          "for fields of the same message type.");
+      }
+      return getNumber() - other.getNumber();
+    }
+
+    @Override
+    public String toString() {
+      return getFullName();
+    }
+
+    private final int index;
+
+    private FieldDescriptorProto proto;
+    private final String fullName;
+    private final String jsonName;
+    private final FileDescriptor file;
+    private final Descriptor extensionScope;
+
+    // Possibly initialized during cross-linking.
+    private Type type;
+    private Descriptor containingType;
+    private Descriptor messageType;
+    private OneofDescriptor containingOneof;
+    private EnumDescriptor enumType;
+    private Object defaultValue;
+
+    public enum Type {
+      DOUBLE  (JavaType.DOUBLE     ),
+      FLOAT   (JavaType.FLOAT      ),
+      INT64   (JavaType.LONG       ),
+      UINT64  (JavaType.LONG       ),
+      INT32   (JavaType.INT        ),
+      FIXED64 (JavaType.LONG       ),
+      FIXED32 (JavaType.INT        ),
+      BOOL    (JavaType.BOOLEAN    ),
+      STRING  (JavaType.STRING     ),
+      GROUP   (JavaType.MESSAGE    ),
+      MESSAGE (JavaType.MESSAGE    ),
+      BYTES   (JavaType.BYTE_STRING),
+      UINT32  (JavaType.INT        ),
+      ENUM    (JavaType.ENUM       ),
+      SFIXED32(JavaType.INT        ),
+      SFIXED64(JavaType.LONG       ),
+      SINT32  (JavaType.INT        ),
+      SINT64  (JavaType.LONG       );
+
+      Type(final JavaType javaType) {
+        this.javaType = javaType;
+      }
+
+      private JavaType javaType;
+
+      public FieldDescriptorProto.Type toProto() {
+        return FieldDescriptorProto.Type.forNumber(ordinal() + 1);
+      }
+      public JavaType getJavaType() { return javaType; }
+
+      public static Type valueOf(final FieldDescriptorProto.Type type) {
+        return values()[type.getNumber() - 1];
+      }
+    }
+
+    static {
+      // Refuse to init if someone added a new declared type.
+      if (Type.values().length != FieldDescriptorProto.Type.values().length) {
+        throw new RuntimeException(""
+            + "descriptor.proto has a new declared type but Descriptors.java "
+            + "wasn't updated.");
+      }
+    }
+
+    public enum JavaType {
+      INT(0),
+      LONG(0L),
+      FLOAT(0F),
+      DOUBLE(0D),
+      BOOLEAN(false),
+      STRING(""),
+      BYTE_STRING(ByteString.EMPTY),
+      ENUM(null),
+      MESSAGE(null);
+
+      JavaType(final Object defaultDefault) {
+        this.defaultDefault = defaultDefault;
+      }
+
+      /**
+       * The default default value for fields of this type, if it's a primitive
+       * type.  This is meant for use inside this file only, hence is private.
+       */
+      private final Object defaultDefault;
+    }
+
+    // TODO(xiaofeng): Implement it consistently across different languages. See b/24751348.
+    private static String fieldNameToLowerCamelCase(String name) {
+      StringBuilder result = new StringBuilder(name.length());
+      boolean isNextUpperCase = false;
+      for (int i = 0; i < name.length(); i++) {
+        Character ch = name.charAt(i);
+        if (Character.isLowerCase(ch)) {
+          if (isNextUpperCase) {
+            result.append(Character.toUpperCase(ch));
+          } else {
+            result.append(ch);
+          }
+          isNextUpperCase = false;
+        } else if (Character.isUpperCase(ch)) {
+          if (i == 0) {
+            // Force first letter to lower-case.
+            result.append(Character.toLowerCase(ch));
+          } else {
+            // Capital letters after the first are left as-is.
+            result.append(ch);
+          }
+          isNextUpperCase = false;
+        } else if (Character.isDigit(ch)) {
+          result.append(ch);
+          isNextUpperCase = false;
+        } else {
+          isNextUpperCase = true;
+        }
+      }
+      return result.toString();
+    }
+
+    private FieldDescriptor(final FieldDescriptorProto proto,
+                            final FileDescriptor file,
+                            final Descriptor parent,
+                            final int index,
+                            final boolean isExtension)
+                     throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      fullName = computeFullName(file, parent, proto.getName());
+      this.file = file;
+      if (proto.hasJsonName()) {
+        jsonName = proto.getJsonName();
+      } else {
+        jsonName = fieldNameToLowerCamelCase(proto.getName());
+      }
+
+      if (proto.hasType()) {
+        type = Type.valueOf(proto.getType());
+      }
+
+      if (getNumber() <= 0) {
+        throw new DescriptorValidationException(this,
+          "Field numbers must be positive integers.");
+      }
+
+      if (isExtension) {
+        if (!proto.hasExtendee()) {
+          throw new DescriptorValidationException(this,
+            "FieldDescriptorProto.extendee not set for extension field.");
+        }
+        containingType = null;  // Will be filled in when cross-linking
+        if (parent != null) {
+          extensionScope = parent;
+        } else {
+          extensionScope = null;
+        }
+
+        if (proto.hasOneofIndex()) {
+          throw new DescriptorValidationException(this,
+            "FieldDescriptorProto.oneof_index set for extension field.");
+        }
+        containingOneof = null;
+      } else {
+        if (proto.hasExtendee()) {
+          throw new DescriptorValidationException(this,
+            "FieldDescriptorProto.extendee set for non-extension field.");
+        }
+        containingType = parent;
+
+        if (proto.hasOneofIndex()) {
+          if (proto.getOneofIndex() < 0 ||
+              proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) {
+            throw new DescriptorValidationException(this,
+              "FieldDescriptorProto.oneof_index is out of range for type "
+              + parent.getName());
+          }
+          containingOneof = parent.getOneofs().get(proto.getOneofIndex());
+          containingOneof.fieldCount++;
+        } else {
+          containingOneof = null;
+        }
+        extensionScope = null;
+      }
+
+      file.pool.addSymbol(this);
+    }
+
+    /** Look up and cross-link all field types, etc. */
+    private void crossLink() throws DescriptorValidationException {
+      if (proto.hasExtendee()) {
+        final GenericDescriptor extendee =
+          file.pool.lookupSymbol(proto.getExtendee(), this,
+              DescriptorPool.SearchFilter.TYPES_ONLY);
+        if (!(extendee instanceof Descriptor)) {
+          throw new DescriptorValidationException(this,
+              '\"' + proto.getExtendee() + "\" is not a message type.");
+        }
+        containingType = (Descriptor)extendee;
+
+        if (!getContainingType().isExtensionNumber(getNumber())) {
+          throw new DescriptorValidationException(this,
+              '\"' + getContainingType().getFullName() +
+              "\" does not declare " + getNumber() +
+              " as an extension number.");
+        }
+      }
+
+      if (proto.hasTypeName()) {
+        final GenericDescriptor typeDescriptor =
+          file.pool.lookupSymbol(proto.getTypeName(), this,
+              DescriptorPool.SearchFilter.TYPES_ONLY);
+
+        if (!proto.hasType()) {
+          // Choose field type based on symbol.
+          if (typeDescriptor instanceof Descriptor) {
+            type = Type.MESSAGE;
+          } else if (typeDescriptor instanceof EnumDescriptor) {
+            type = Type.ENUM;
+          } else {
+            throw new DescriptorValidationException(this,
+                '\"' + proto.getTypeName() + "\" is not a type.");
+          }
+        }
+
+        if (getJavaType() == JavaType.MESSAGE) {
+          if (!(typeDescriptor instanceof Descriptor)) {
+            throw new DescriptorValidationException(this,
+                '\"' + proto.getTypeName() + "\" is not a message type.");
+          }
+          messageType = (Descriptor)typeDescriptor;
+
+          if (proto.hasDefaultValue()) {
+            throw new DescriptorValidationException(this,
+              "Messages can't have default values.");
+          }
+        } else if (getJavaType() == JavaType.ENUM) {
+          if (!(typeDescriptor instanceof EnumDescriptor)) {
+            throw new DescriptorValidationException(this,
+                '\"' + proto.getTypeName() + "\" is not an enum type.");
+          }
+          enumType = (EnumDescriptor)typeDescriptor;
+        } else {
+          throw new DescriptorValidationException(this,
+            "Field with primitive type has type_name.");
+        }
+      } else {
+        if (getJavaType() == JavaType.MESSAGE ||
+            getJavaType() == JavaType.ENUM) {
+          throw new DescriptorValidationException(this,
+            "Field with message or enum type missing type_name.");
+        }
+      }
+
+      // Only repeated primitive fields may be packed.
+      if (proto.getOptions().getPacked() && !isPackable()) {
+        throw new DescriptorValidationException(this,
+          "[packed = true] can only be specified for repeated primitive " +
+          "fields.");
+      }
+
+      // We don't attempt to parse the default value until here because for
+      // enums we need the enum type's descriptor.
+      if (proto.hasDefaultValue()) {
+        if (isRepeated()) {
+          throw new DescriptorValidationException(this,
+            "Repeated fields cannot have default values.");
+        }
+
+        try {
+          switch (getType()) {
+            case INT32:
+            case SINT32:
+            case SFIXED32:
+              defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
+              break;
+            case UINT32:
+            case FIXED32:
+              defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
+              break;
+            case INT64:
+            case SINT64:
+            case SFIXED64:
+              defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
+              break;
+            case UINT64:
+            case FIXED64:
+              defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
+              break;
+            case FLOAT:
+              if (proto.getDefaultValue().equals("inf")) {
+                defaultValue = Float.POSITIVE_INFINITY;
+              } else if (proto.getDefaultValue().equals("-inf")) {
+                defaultValue = Float.NEGATIVE_INFINITY;
+              } else if (proto.getDefaultValue().equals("nan")) {
+                defaultValue = Float.NaN;
+              } else {
+                defaultValue = Float.valueOf(proto.getDefaultValue());
+              }
+              break;
+            case DOUBLE:
+              if (proto.getDefaultValue().equals("inf")) {
+                defaultValue = Double.POSITIVE_INFINITY;
+              } else if (proto.getDefaultValue().equals("-inf")) {
+                defaultValue = Double.NEGATIVE_INFINITY;
+              } else if (proto.getDefaultValue().equals("nan")) {
+                defaultValue = Double.NaN;
+              } else {
+                defaultValue = Double.valueOf(proto.getDefaultValue());
+              }
+              break;
+            case BOOL:
+              defaultValue = Boolean.valueOf(proto.getDefaultValue());
+              break;
+            case STRING:
+              defaultValue = proto.getDefaultValue();
+              break;
+            case BYTES:
+              try {
+                defaultValue =
+                  TextFormat.unescapeBytes(proto.getDefaultValue());
+              } catch (TextFormat.InvalidEscapeSequenceException e) {
+                throw new DescriptorValidationException(this,
+                  "Couldn't parse default value: " + e.getMessage(), e);
+              }
+              break;
+            case ENUM:
+              defaultValue = enumType.findValueByName(proto.getDefaultValue());
+              if (defaultValue == null) {
+                throw new DescriptorValidationException(this,
+                  "Unknown enum default value: \"" +
+                  proto.getDefaultValue() + '\"');
+              }
+              break;
+            case MESSAGE:
+            case GROUP:
+              throw new DescriptorValidationException(this,
+                "Message type had default value.");
+          }
+        } catch (NumberFormatException e) {
+          throw new DescriptorValidationException(this,
+              "Could not parse default value: \"" +
+              proto.getDefaultValue() + '\"', e);
+        }
+      } else {
+        // Determine the default default for this field.
+        if (isRepeated()) {
+          defaultValue = Collections.emptyList();
+        } else {
+          switch (getJavaType()) {
+            case ENUM:
+              // We guarantee elsewhere that an enum type always has at least
+              // one possible value.
+              defaultValue = enumType.getValues().get(0);
+              break;
+            case MESSAGE:
+              defaultValue = null;
+              break;
+            default:
+              defaultValue = getJavaType().defaultDefault;
+              break;
+          }
+        }
+      }
+
+      if (!isExtension()) {
+        file.pool.addFieldByNumber(this);
+      }
+
+      if (containingType != null &&
+          containingType.getOptions().getMessageSetWireFormat()) {
+        if (isExtension()) {
+          if (!isOptional() || getType() != Type.MESSAGE) {
+            throw new DescriptorValidationException(this,
+              "Extensions of MessageSets must be optional messages.");
+          }
+        } else {
+          throw new DescriptorValidationException(this,
+            "MessageSets cannot have fields, only extensions.");
+        }
+      }
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final FieldDescriptorProto proto) {
+      this.proto = proto;
+    }
+
+    /**
+     * For internal use only.  This is to satisfy the FieldDescriptorLite
+     * interface.
+     */
+    @Override
+    public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
+      // FieldDescriptors are only used with non-lite messages so we can just
+      // down-cast and call mergeFrom directly.
+      return ((Message.Builder) to).mergeFrom((Message) from);
+    }
+
+  }
+
+  // =================================================================
+
+  /** Describes an enum type. */
+  public static final class EnumDescriptor extends GenericDescriptor
+      implements Internal.EnumLiteMap<EnumValueDescriptor> {
+    /**
+     * Get the index of this descriptor within its parent.
+     * @see Descriptors.Descriptor#getIndex()
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public EnumDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the type's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /**
+     * Get the type's fully-qualified name.
+     * @see Descriptors.Descriptor#getFullName()
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the {@link FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** If this is a nested type, get the outer descriptor, otherwise null. */
+    public Descriptor getContainingType() { return containingType; }
+
+    /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */
+    public EnumOptions getOptions() { return proto.getOptions(); }
+
+    /** Get a list of defined values for this enum. */
+    public List<EnumValueDescriptor> getValues() {
+      return Collections.unmodifiableList(Arrays.asList(values));
+    }
+
+    /**
+     * Find an enum value by name.
+     * @param name The unqualified name of the value (e.g. "FOO").
+     * @return the value's descriptor, or {@code null} if not found.
+     */
+    public EnumValueDescriptor findValueByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
+      if (result != null && result instanceof EnumValueDescriptor) {
+        return (EnumValueDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Find an enum value by number.  If multiple enum values have the same
+     * number, this returns the first defined value with that number.
+     * @param number The value's number.
+     * @return the value's descriptor, or {@code null} if not found.
+     */
+    @Override
+    public EnumValueDescriptor findValueByNumber(final int number) {
+      return file.pool.enumValuesByNumber.get(
+        new DescriptorPool.DescriptorIntPair(this, number));
+    }
+
+    /**
+     * Get the enum value for a number. If no enum value has this number,
+     * construct an EnumValueDescriptor for it.
+     */
+    public EnumValueDescriptor findValueByNumberCreatingIfUnknown(final int number) {
+      EnumValueDescriptor result = findValueByNumber(number);
+      if (result != null) {
+        return result;
+      }
+      // The number represents an unknown enum value.
+      synchronized (this) {
+        // Descriptors are compared by object identity so for the same number
+        // we need to return the same EnumValueDescriptor object. This means
+        // we have to store created EnumValueDescriptors. However, as there
+        // are potentially 2G unknown enum values, storing all of these
+        // objects persistently will consume lots of memory for long-running
+        // services and it's also unnecessary as not many EnumValueDescriptors
+        // will be used at the same time.
+        //
+        // To solve the problem we take advantage of Java's weak references and
+        // rely on gc to release unused descriptors.
+        //
+        // Here is how it works:
+        //   * We store unknown EnumValueDescriptors in a WeakHashMap with the
+        //     value being a weak reference to the descriptor.
+        //   * The descriptor holds a strong reference to the key so as long
+        //     as the EnumValueDescriptor is in use, the key will be there
+        //     and the corresponding map entry will be there. Following-up
+        //     queries with the same number will return the same descriptor.
+        //   * If the user no longer uses an unknown EnumValueDescriptor,
+        //     it will be gc-ed since we only hold a weak reference to it in
+        //     the map. The key in the corresponding map entry will also be
+        //     gc-ed as the only strong reference to it is in the descriptor
+        //     which is just gc-ed. With the key being gone WeakHashMap will
+        //     then remove the whole entry. This way unknown descriptors will
+        //     be freed automatically and we don't need to do anything to
+        //     clean-up unused map entries.
+
+        // Note: We must use "new Integer(number)" here because we don't want
+        // these Integer objects to be cached.
+        Integer key = new Integer(number);
+        WeakReference<EnumValueDescriptor> reference = unknownValues.get(key);
+        if (reference != null) {
+          result = reference.get();
+        }
+        if (result == null) {
+          result = new EnumValueDescriptor(file, this, key);
+          unknownValues.put(key, new WeakReference<EnumValueDescriptor>(result));
+        }
+      }
+      return result;
+    }
+
+    // Used in tests only.
+    int getUnknownEnumValueDescriptorCount() {
+      return unknownValues.size();
+    }
+
+    private final int index;
+    private EnumDescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+    private final Descriptor containingType;
+    private EnumValueDescriptor[] values;
+    private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
+        new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
+
+    private EnumDescriptor(final EnumDescriptorProto proto,
+                           final FileDescriptor file,
+                           final Descriptor parent,
+                           final int index)
+                    throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      fullName = computeFullName(file, parent, proto.getName());
+      this.file = file;
+      containingType = parent;
+
+      if (proto.getValueCount() == 0) {
+        // We cannot allow enums with no values because this would mean there
+        // would be no valid default value for fields of this type.
+        throw new DescriptorValidationException(this,
+          "Enums must contain at least one value.");
+      }
+
+      values = new EnumValueDescriptor[proto.getValueCount()];
+      for (int i = 0; i < proto.getValueCount(); i++) {
+        values[i] = new EnumValueDescriptor(
+          proto.getValue(i), file, this, i);
+      }
+
+      file.pool.addSymbol(this);
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final EnumDescriptorProto proto) {
+      this.proto = proto;
+
+      for (int i = 0; i < values.length; i++) {
+        values[i].setProto(proto.getValue(i));
+      }
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * Describes one value within an enum type.  Note that multiple defined
+   * values may have the same number.  In generated Java code, all values
+   * with the same number after the first become aliases of the first.
+   * However, they still have independent EnumValueDescriptors.
+   */
+  public static final class EnumValueDescriptor extends GenericDescriptor
+      implements Internal.EnumLite {
+    /**
+     * Get the index of this descriptor within its parent.
+     * @see Descriptors.Descriptor#getIndex()
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public EnumValueDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the value's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /** Get the value's number. */
+    @Override
+    public int getNumber() {
+      return proto.getNumber();
+    }
+
+    @Override
+    public String toString() { return proto.getName(); }
+
+    /**
+     * Get the value's fully-qualified name.
+     * @see Descriptors.Descriptor#getFullName()
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the {@link FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** Get the value's enum type. */
+    public EnumDescriptor getType() { return type; }
+
+    /**
+     * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}.
+     */
+    public EnumValueOptions getOptions() { return proto.getOptions(); }
+
+    private final int index;
+    private EnumValueDescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+    private final EnumDescriptor type;
+
+    private EnumValueDescriptor(final EnumValueDescriptorProto proto,
+                                final FileDescriptor file,
+                                final EnumDescriptor parent,
+                                final int index)
+                         throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      this.file = file;
+      type = parent;
+
+      fullName = parent.getFullName() + '.' + proto.getName();
+
+      file.pool.addSymbol(this);
+      file.pool.addEnumValueByNumber(this);
+    }
+
+    private Integer number;
+    // Create an unknown enum value.
+    private EnumValueDescriptor(
+        final FileDescriptor file,
+        final EnumDescriptor parent,
+        final Integer number) {
+      String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number;
+      EnumValueDescriptorProto proto = EnumValueDescriptorProto
+          .newBuilder().setName(name).setNumber(number).build();
+      this.index = -1;
+      this.proto = proto;
+      this.file = file;
+      this.type = parent;
+      this.fullName = parent.getFullName() + '.' + proto.getName();
+      this.number = number;
+
+      // Don't add this descriptor into pool.
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final EnumValueDescriptorProto proto) {
+      this.proto = proto;
+    }
+  }
+
+  // =================================================================
+
+  /** Describes a service type. */
+  public static final class ServiceDescriptor extends GenericDescriptor {
+    /**
+     * Get the index of this descriptor within its parent.
+     * * @see Descriptors.Descriptor#getIndex()
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public ServiceDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the type's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /**
+     * Get the type's fully-qualified name.
+     * @see Descriptors.Descriptor#getFullName()
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the {@link FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */
+    public ServiceOptions getOptions() { return proto.getOptions(); }
+
+    /** Get a list of methods for this service. */
+    public List<MethodDescriptor> getMethods() {
+      return Collections.unmodifiableList(Arrays.asList(methods));
+    }
+
+    /**
+     * Find a method by name.
+     * @param name The unqualified name of the method (e.g. "Foo").
+     * @return the method's descriptor, or {@code null} if not found.
+     */
+    public MethodDescriptor findMethodByName(final String name) {
+      final GenericDescriptor result =
+          file.pool.findSymbol(fullName + '.' + name);
+      if (result != null && result instanceof MethodDescriptor) {
+        return (MethodDescriptor)result;
+      } else {
+        return null;
+      }
+    }
+
+    private final int index;
+    private ServiceDescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+    private MethodDescriptor[] methods;
+
+    private ServiceDescriptor(final ServiceDescriptorProto proto,
+                              final FileDescriptor file,
+                              final int index)
+                       throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      fullName = computeFullName(file, null, proto.getName());
+      this.file = file;
+
+      methods = new MethodDescriptor[proto.getMethodCount()];
+      for (int i = 0; i < proto.getMethodCount(); i++) {
+        methods[i] = new MethodDescriptor(
+          proto.getMethod(i), file, this, i);
+      }
+
+      file.pool.addSymbol(this);
+    }
+
+    private void crossLink() throws DescriptorValidationException {
+      for (final MethodDescriptor method : methods) {
+        method.crossLink();
+      }
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final ServiceDescriptorProto proto) {
+      this.proto = proto;
+
+      for (int i = 0; i < methods.length; i++) {
+        methods[i].setProto(proto.getMethod(i));
+      }
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * Describes one method within a service type.
+   */
+  public static final class MethodDescriptor extends GenericDescriptor {
+    /**
+     * Get the index of this descriptor within its parent.
+     * * @see Descriptors.Descriptor#getIndex()
+     */
+    public int getIndex() { return index; }
+
+    /** Convert the descriptor to its protocol message representation. */
+    @Override
+    public MethodDescriptorProto toProto() {
+      return proto;
+    }
+
+    /** Get the method's unqualified name. */
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
+
+    /**
+     * Get the method's fully-qualified name.
+     * @see Descriptors.Descriptor#getFullName()
+     */
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
+
+    /** Get the {@link FileDescriptor} containing this descriptor. */
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
+
+    /** Get the method's service type. */
+    public ServiceDescriptor getService() { return service; }
+
+    /** Get the method's input type. */
+    public Descriptor getInputType() { return inputType; }
+
+    /** Get the method's output type. */
+    public Descriptor getOutputType() { return outputType; }
+
+    /**
+     * Get the {@code MethodOptions}, defined in {@code descriptor.proto}.
+     */
+    public MethodOptions getOptions() { return proto.getOptions(); }
+
+    private final int index;
+    private MethodDescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+    private final ServiceDescriptor service;
+
+    // Initialized during cross-linking.
+    private Descriptor inputType;
+    private Descriptor outputType;
+
+    private MethodDescriptor(final MethodDescriptorProto proto,
+                             final FileDescriptor file,
+                             final ServiceDescriptor parent,
+                             final int index)
+                      throws DescriptorValidationException {
+      this.index = index;
+      this.proto = proto;
+      this.file = file;
+      service = parent;
+
+      fullName = parent.getFullName() + '.' + proto.getName();
+
+      file.pool.addSymbol(this);
+    }
+
+    private void crossLink() throws DescriptorValidationException {
+      final GenericDescriptor input =
+        file.pool.lookupSymbol(proto.getInputType(), this,
+            DescriptorPool.SearchFilter.TYPES_ONLY);
+      if (!(input instanceof Descriptor)) {
+        throw new DescriptorValidationException(this,
+            '\"' + proto.getInputType() + "\" is not a message type.");
+      }
+      inputType = (Descriptor)input;
+
+      final GenericDescriptor output =
+        file.pool.lookupSymbol(proto.getOutputType(), this,
+            DescriptorPool.SearchFilter.TYPES_ONLY);
+      if (!(output instanceof Descriptor)) {
+        throw new DescriptorValidationException(this,
+            '\"' + proto.getOutputType() + "\" is not a message type.");
+      }
+      outputType = (Descriptor)output;
+    }
+
+    /** See {@link FileDescriptor#setProto}. */
+    private void setProto(final MethodDescriptorProto proto) {
+      this.proto = proto;
+    }
+  }
+
+  // =================================================================
+
+  private static String computeFullName(final FileDescriptor file,
+                                        final Descriptor parent,
+                                        final String name) {
+    if (parent != null) {
+      return parent.getFullName() + '.' + name;
+    } else if (file.getPackage().length() > 0) {
+      return file.getPackage() + '.' + name;
+    } else {
+      return name;
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * All descriptors implement this to make it easier to implement tools like
+   * {@code DescriptorPool}.<p>
+   *
+   * This class is public so that the methods it exposes can be called from
+   * outside of this package. However, it should only be subclassed from
+   * nested classes of Descriptors.
+   */
+  public abstract static class GenericDescriptor {
+    public abstract Message toProto();
+    public abstract String getName();
+    public abstract String getFullName();
+    public abstract FileDescriptor getFile();
+  }
+
+  /**
+   * Thrown when building descriptors fails because the source DescriptorProtos
+   * are not valid.
+   */
+  public static class DescriptorValidationException extends Exception {
+    private static final long serialVersionUID = 5750205775490483148L;
+
+    /** Gets the full name of the descriptor where the error occurred. */
+    public String getProblemSymbolName() { return name; }
+
+    /**
+     * Gets the protocol message representation of the invalid descriptor.
+     */
+    public Message getProblemProto() { return proto; }
+
+    /**
+     * Gets a human-readable description of the error.
+     */
+    public String getDescription() { return description; }
+
+    private final String name;
+    private final Message proto;
+    private final String description;
+
+    private DescriptorValidationException(
+        final GenericDescriptor problemDescriptor,
+        final String description) {
+      super(problemDescriptor.getFullName() + ": " + description);
+
+      // Note that problemDescriptor may be partially uninitialized, so we
+      // don't want to expose it directly to the user.  So, we only provide
+      // the name and the original proto.
+      name = problemDescriptor.getFullName();
+      proto = problemDescriptor.toProto();
+      this.description = description;
+    }
+
+    private DescriptorValidationException(
+        final GenericDescriptor problemDescriptor,
+        final String description,
+        final Throwable cause) {
+      this(problemDescriptor, description);
+      initCause(cause);
+    }
+
+    private DescriptorValidationException(
+        final FileDescriptor problemDescriptor,
+        final String description) {
+      super(problemDescriptor.getName() + ": " + description);
+
+      // Note that problemDescriptor may be partially uninitialized, so we
+      // don't want to expose it directly to the user.  So, we only provide
+      // the name and the original proto.
+      name = problemDescriptor.getName();
+      proto = problemDescriptor.toProto();
+      this.description = description;
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * A private helper class which contains lookup tables containing all the
+   * descriptors defined in a particular file.
+   */
+  private static final class DescriptorPool {
+
+    /** Defines what subclass of descriptors to search in the descriptor pool.
+     */
+    enum SearchFilter {
+      TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
+    }
+
+    DescriptorPool(final FileDescriptor[] dependencies,
+        boolean allowUnknownDependencies) {
+      this.dependencies = new HashSet<FileDescriptor>();
+      this.allowUnknownDependencies = allowUnknownDependencies;
+
+      for (int i = 0; i < dependencies.length; i++) {
+        this.dependencies.add(dependencies[i]);
+        importPublicDependencies(dependencies[i]);
+      }
+
+      for (final FileDescriptor dependency : this.dependencies) {
+        try {
+          addPackage(dependency.getPackage(), dependency);
+        } catch (DescriptorValidationException e) {
+          // Can't happen, because addPackage() only fails when the name
+          // conflicts with a non-package, but we have not yet added any
+          // non-packages at this point.
+          assert false;
+        }
+      }
+    }
+
+    /** Find and put public dependencies of the file into dependencies set.*/
+    private void importPublicDependencies(final FileDescriptor file) {
+      for (FileDescriptor dependency : file.getPublicDependencies()) {
+        if (dependencies.add(dependency)) {
+          importPublicDependencies(dependency);
+        }
+      }
+    }
+
+    private final Set<FileDescriptor> dependencies;
+    private boolean allowUnknownDependencies;
+
+    private final Map<String, GenericDescriptor> descriptorsByName =
+      new HashMap<String, GenericDescriptor>();
+    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+      new HashMap<DescriptorIntPair, FieldDescriptor>();
+    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
+        = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+
+    /** Find a generic descriptor by fully-qualified name. */
+    GenericDescriptor findSymbol(final String fullName) {
+      return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
+    }
+
+    /** Find a descriptor by fully-qualified name and given option to only
+     * search valid field type descriptors.
+     */
+    GenericDescriptor findSymbol(final String fullName,
+                                 final SearchFilter filter) {
+      GenericDescriptor result = descriptorsByName.get(fullName);
+      if (result != null) {
+        if ((filter==SearchFilter.ALL_SYMBOLS) ||
+            ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+            ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+          return result;
+        }
+      }
+
+      for (final FileDescriptor dependency : dependencies) {
+        result = dependency.pool.descriptorsByName.get(fullName);
+        if (result != null) {
+          if ((filter==SearchFilter.ALL_SYMBOLS) ||
+              ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+              ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+            return result;
+          }
+        }
+      }
+
+      return null;
+    }
+
+    /** Checks if the descriptor is a valid type for a message field. */
+    boolean isType(GenericDescriptor descriptor) {
+      return (descriptor instanceof Descriptor) ||
+        (descriptor instanceof EnumDescriptor);
+    }
+
+    /** Checks if the descriptor is a valid namespace type. */
+    boolean isAggregate(GenericDescriptor descriptor) {
+      return (descriptor instanceof Descriptor) ||
+        (descriptor instanceof EnumDescriptor) ||
+        (descriptor instanceof PackageDescriptor) ||
+        (descriptor instanceof ServiceDescriptor);
+    }
+
+    /**
+     * Look up a type descriptor by name, relative to some other descriptor.
+     * The name may be fully-qualified (with a leading '.'),
+     * partially-qualified, or unqualified.  C++-like name lookup semantics
+     * are used to search for the matching descriptor.
+     */
+    GenericDescriptor lookupSymbol(final String name,
+                                   final GenericDescriptor relativeTo,
+                                   final DescriptorPool.SearchFilter filter)
+                            throws DescriptorValidationException {
+      // TODO(kenton):  This could be optimized in a number of ways.
+
+      GenericDescriptor result;
+      String fullname;
+      if (name.startsWith(".")) {
+        // Fully-qualified name.
+        fullname = name.substring(1);
+        result = findSymbol(fullname, filter);
+      } else {
+        // If "name" is a compound identifier, we want to search for the
+        // first component of it, then search within it for the rest.
+        // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
+        // defined in multiple parent scopes, we only want to find "Bar.baz" in
+        // the innermost one.  E.g., the following should produce an error:
+        //   message Bar { message Baz {} }
+        //   message Foo {
+        //     message Bar {
+        //     }
+        //     optional Bar.Baz baz = 1;
+        //   }
+        // So, we look for just "Foo" first, then look for "Bar.baz" within it
+        // if found.
+        final int firstPartLength = name.indexOf('.');
+        final String firstPart;
+        if (firstPartLength == -1) {
+          firstPart = name;
+        } else {
+          firstPart = name.substring(0, firstPartLength);
+        }
+
+        // We will search each parent scope of "relativeTo" looking for the
+        // symbol.
+        final StringBuilder scopeToTry =
+            new StringBuilder(relativeTo.getFullName());
+
+        while (true) {
+          // Chop off the last component of the scope.
+          final int dotpos = scopeToTry.lastIndexOf(".");
+          if (dotpos == -1) {
+            fullname = name;
+            result = findSymbol(name, filter);
+            break;
+          } else {
+            scopeToTry.setLength(dotpos + 1);
+
+            // Append firstPart and try to find
+            scopeToTry.append(firstPart);
+            result = findSymbol(scopeToTry.toString(),
+                DescriptorPool.SearchFilter.AGGREGATES_ONLY);
+
+            if (result != null) {
+              if (firstPartLength != -1) {
+                // We only found the first part of the symbol.  Now look for
+                // the whole thing.  If this fails, we *don't* want to keep
+                // searching parent scopes.
+                scopeToTry.setLength(dotpos + 1);
+                scopeToTry.append(name);
+                result = findSymbol(scopeToTry.toString(), filter);
+              }
+              fullname = scopeToTry.toString();
+              break;
+            }
+
+            // Not found.  Remove the name so we can try again.
+            scopeToTry.setLength(dotpos);
+          }
+        }
+      }
+
+      if (result == null) {
+        if (allowUnknownDependencies && filter == SearchFilter.TYPES_ONLY) {
+          logger.warning("The descriptor for message type \"" + name +
+              "\" can not be found and a placeholder is created for it");
+          // We create a dummy message descriptor here regardless of the
+          // expected type. If the type should be message, this dummy
+          // descriptor will work well and if the type should be enum, a
+          // DescriptorValidationException will be thrown latter. In either
+          // case, the code works as expected: we allow unknown message types
+          // but not unknwon enum types.
+          result = new Descriptor(fullname);
+          // Add the placeholder file as a dependency so we can find the
+          // placeholder symbol when resolving other references.
+          this.dependencies.add(result.getFile());
+          return result;
+        } else {
+          throw new DescriptorValidationException(relativeTo,
+              '\"' + name + "\" is not defined.");
+        }
+      } else {
+        return result;
+      }
+    }
+
+    /**
+     * Adds a symbol to the symbol table.  If a symbol with the same name
+     * already exists, throws an error.
+     */
+    void addSymbol(final GenericDescriptor descriptor)
+            throws DescriptorValidationException {
+      validateSymbolName(descriptor);
+
+      final String fullName = descriptor.getFullName();
+      final int dotpos = fullName.lastIndexOf('.');
+
+      final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
+      if (old != null) {
+        descriptorsByName.put(fullName, old);
+
+        if (descriptor.getFile() == old.getFile()) {
+          if (dotpos == -1) {
+            throw new DescriptorValidationException(descriptor,
+                '\"' + fullName + "\" is already defined.");
+          } else {
+            throw new DescriptorValidationException(descriptor,
+                '\"' + fullName.substring(dotpos + 1) +
+              "\" is already defined in \"" +
+              fullName.substring(0, dotpos) + "\".");
+          }
+        } else {
+          throw new DescriptorValidationException(descriptor,
+              '\"' + fullName + "\" is already defined in file \"" +
+            old.getFile().getName() + "\".");
+        }
+      }
+    }
+
+    /**
+     * Represents a package in the symbol table.  We use PackageDescriptors
+     * just as placeholders so that someone cannot define, say, a message type
+     * that has the same name as an existing package.
+     */
+    private static final class PackageDescriptor extends GenericDescriptor {
+      @Override
+      public Message toProto() {
+        return file.toProto();
+      }
+      @Override
+      public String getName() {
+        return name;
+      }
+      @Override
+      public String getFullName() {
+        return fullName;
+      }
+      @Override
+      public FileDescriptor getFile() {
+        return file;
+      }
+
+      PackageDescriptor(final String name, final String fullName,
+                        final FileDescriptor file) {
+        this.file = file;
+        this.fullName = fullName;
+        this.name = name;
+      }
+
+      private final String name;
+      private final String fullName;
+      private final FileDescriptor file;
+    }
+
+    /**
+     * Adds a package to the symbol tables.  If a package by the same name
+     * already exists, that is fine, but if some other kind of symbol exists
+     * under the same name, an exception is thrown.  If the package has
+     * multiple components, this also adds the parent package(s).
+     */
+    void addPackage(final String fullName, final FileDescriptor file)
+             throws DescriptorValidationException {
+      final int dotpos = fullName.lastIndexOf('.');
+      final String name;
+      if (dotpos == -1) {
+        name = fullName;
+      } else {
+        addPackage(fullName.substring(0, dotpos), file);
+        name = fullName.substring(dotpos + 1);
+      }
+
+      final GenericDescriptor old =
+        descriptorsByName.put(fullName,
+          new PackageDescriptor(name, fullName, file));
+      if (old != null) {
+        descriptorsByName.put(fullName, old);
+        if (!(old instanceof PackageDescriptor)) {
+          throw new DescriptorValidationException(file,
+              '\"' + name + "\" is already defined (as something other than a "
+              + "package) in file \"" + old.getFile().getName() + "\".");
+        }
+      }
+    }
+
+    /** A (GenericDescriptor, int) pair, used as a map key. */
+    private static final class DescriptorIntPair {
+      private final GenericDescriptor descriptor;
+      private final int number;
+
+      DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
+        this.descriptor = descriptor;
+        this.number = number;
+      }
+
+      @Override
+      public int hashCode() {
+        return descriptor.hashCode() * ((1 << 16) - 1) + number;
+      }
+      @Override
+      public boolean equals(final Object obj) {
+        if (!(obj instanceof DescriptorIntPair)) {
+          return false;
+        }
+        final DescriptorIntPair other = (DescriptorIntPair)obj;
+        return descriptor == other.descriptor && number == other.number;
+      }
+    }
+
+    /**
+     * Adds a field to the fieldsByNumber table.  Throws an exception if a
+     * field with the same containing type and number already exists.
+     */
+    void addFieldByNumber(final FieldDescriptor field)
+                   throws DescriptorValidationException {
+      final DescriptorIntPair key =
+        new DescriptorIntPair(field.getContainingType(), field.getNumber());
+      final FieldDescriptor old = fieldsByNumber.put(key, field);
+      if (old != null) {
+        fieldsByNumber.put(key, old);
+        throw new DescriptorValidationException(field,
+          "Field number " + field.getNumber() +
+          " has already been used in \"" +
+          field.getContainingType().getFullName() +
+          "\" by field \"" + old.getName() + "\".");
+      }
+    }
+
+    /**
+     * Adds an enum value to the enumValuesByNumber table.  If an enum value
+     * with the same type and number already exists, does nothing.  (This is
+     * allowed; the first value define with the number takes precedence.)
+     */
+    void addEnumValueByNumber(final EnumValueDescriptor value) {
+      final DescriptorIntPair key =
+        new DescriptorIntPair(value.getType(), value.getNumber());
+      final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
+      if (old != null) {
+        enumValuesByNumber.put(key, old);
+        // Not an error:  Multiple enum values may have the same number, but
+        // we only want the first one in the map.
+      }
+    }
+
+    /**
+     * Verifies that the descriptor's name is valid (i.e. it contains only
+     * letters, digits, and underscores, and does not start with a digit).
+     */
+    static void validateSymbolName(final GenericDescriptor descriptor)
+                                   throws DescriptorValidationException {
+      final String name = descriptor.getName();
+      if (name.length() == 0) {
+        throw new DescriptorValidationException(descriptor, "Missing name.");
+      } else {
+        boolean valid = true;
+        for (int i = 0; i < name.length(); i++) {
+          final char c = name.charAt(i);
+          // Non-ASCII characters are not valid in protobuf identifiers, even
+          // if they are letters or digits.
+          if (c >= 128) {
+            valid = false;
+          }
+          // First character must be letter or _.  Subsequent characters may
+          // be letters, numbers, or digits.
+          if (Character.isLetter(c) || c == '_' ||
+              (Character.isDigit(c) && i > 0)) {
+            // Valid
+          } else {
+            valid = false;
+          }
+        }
+        if (!valid) {
+          throw new DescriptorValidationException(descriptor,
+              '\"' + name + "\" is not a valid identifier.");
+        }
+      }
+    }
+  }
+
+  /** Describes an oneof of a message type. */
+  public static final class OneofDescriptor {
+    /** Get the index of this descriptor within its parent. */
+    public int getIndex() { return index; }
+
+    public String getName() { return proto.getName(); }
+
+    public FileDescriptor getFile() { return file; }
+
+    public String getFullName() { return fullName; }
+
+    public Descriptor getContainingType() { return containingType; }
+
+    public int getFieldCount() { return fieldCount; }
+
+    /** Get a list of this message type's fields. */
+    public List<FieldDescriptor> getFields() {
+      return Collections.unmodifiableList(Arrays.asList(fields));
+    }
+
+    public FieldDescriptor getField(int index) {
+      return fields[index];
+    }
+
+    private OneofDescriptor(final OneofDescriptorProto proto,
+                            final FileDescriptor file,
+                            final Descriptor parent,
+                            final int index)
+                     throws DescriptorValidationException {
+      this.proto = proto;
+      fullName = computeFullName(file, parent, proto.getName());
+      this.file = file;
+      this.index = index;
+
+      containingType = parent;
+      fieldCount = 0;
+    }
+
+    private final int index;
+    private OneofDescriptorProto proto;
+    private final String fullName;
+    private final FileDescriptor file;
+
+    private Descriptor containingType;
+    private int fieldCount;
+    private FieldDescriptor[] fields;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
new file mode 100644
index 0000000..a9543b8
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -0,0 +1,271 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.DoubleList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link DoubleList} on top of a primitive array.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class DoubleArrayList
+    extends AbstractProtobufList<Double> implements DoubleList, RandomAccess {
+  
+  private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  public static DoubleArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+  
+  /**
+   * The backing store for the list.
+   */
+  private double[] array;
+  
+  /**
+   * The size of the list distinct from the length of the array. That is, it is the number of
+   * elements set in the list.
+   */
+  private int size;
+
+  /**
+   * Constructs a new mutable {@code DoubleArrayList} with default capacity.
+   */
+  DoubleArrayList() {
+    this(new double[DEFAULT_CAPACITY], 0);
+  }
+
+  /**
+   * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}.
+   */
+  private DoubleArrayList(double[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof DoubleArrayList)) {
+      return super.equals(o);
+    }
+    DoubleArrayList other = (DoubleArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final double[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      long bits = Double.doubleToLongBits(array[i]);
+      result = (31 * result) + Internal.hashLong(bits);
+    }
+    return result;
+  }
+
+  @Override
+  public DoubleList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new DoubleArrayList(Arrays.copyOf(array, capacity), size);
+  }
+  
+  @Override
+  public Double get(int index) {
+    return getDouble(index);
+  }
+
+  @Override
+  public double getDouble(int index) {
+    ensureIndexInRange(index);
+    return array[index];
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Double set(int index, Double element) {
+    return setDouble(index, element);
+  }
+
+  @Override
+  public double setDouble(int index, double element) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    double previousValue = array[index];
+    array[index] = element;
+    return previousValue;
+  }
+
+  @Override
+  public void add(int index, Double element) {
+    addDouble(index, element);
+  }
+
+  /**
+   * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+   */
+  @Override
+  public void addDouble(double element) {
+    addDouble(size, element);
+  }
+
+  /**
+   * Like {@link #add(int, Double)} but more efficient in that it doesn't box the element.
+   */
+  private void addDouble(int index, double element) {
+    ensureIsMutable();
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+    
+    if (size < array.length) {
+      // Shift everything over to make room
+      System.arraycopy(array, index, array, index + 1, size - index);
+    } else {
+      // Resize to 1.5x the size
+      int length = ((size * 3) / 2) + 1;
+      double[] newArray = new double[length];
+      
+      // Copy the first part directly
+      System.arraycopy(array, 0, newArray, 0, index);
+      
+      // Copy the rest shifted over by one to make room
+      System.arraycopy(array, index, newArray, index + 1, size - index);
+      array = newArray;
+    }
+
+    array[index] = element;
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends Double> collection) {
+    ensureIsMutable();
+    
+    if (collection == null) {
+      throw new NullPointerException();
+    }
+    
+    // We specialize when adding another DoubleArrayList to avoid boxing elements.
+    if (!(collection instanceof DoubleArrayList)) {
+      return super.addAll(collection);
+    }
+    
+    DoubleArrayList list = (DoubleArrayList) collection;
+    if (list.size == 0) {
+      return false;
+    }
+    
+    int overflow = Integer.MAX_VALUE - size;
+    if (overflow < list.size) {
+      // We can't actually represent a list this large.
+      throw new OutOfMemoryError();
+    }
+    
+    int newSize = size + list.size;
+    if (newSize > array.length) {
+      array = Arrays.copyOf(array, newSize);
+    }
+    
+    System.arraycopy(list.array, 0, array, size, list.size);
+    size = newSize;
+    modCount++;
+    return true;
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    for (int i = 0; i < size; i++) {
+      if (o.equals(array[i])) {
+        System.arraycopy(array, i + 1, array, i, size - i);
+        size--;
+        modCount++;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Double remove(int index) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    double value = array[index];
+    System.arraycopy(array, index + 1, array, index, size - index);
+    size--;
+    modCount++;
+    return value;
+  }
+
+  /**
+   * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+   * {@link IndexOutOfBoundsException} if it is not.
+   * 
+   * @param index the index to verify is in range
+   */
+  private void ensureIndexInRange(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+  }
+
+  private String makeOutOfBoundsExceptionMessage(int index) {
+    return "Index:" + index + ", Size:" + size;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
new file mode 100644
index 0000000..859a9e8
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -0,0 +1,676 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An implementation of {@link Message} that can represent arbitrary types,
+ * given a {@link Descriptors.Descriptor}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class DynamicMessage extends AbstractMessage {
+  private final Descriptor type;
+  private final FieldSet<FieldDescriptor> fields;
+  private final FieldDescriptor[] oneofCases;
+  private final UnknownFieldSet unknownFields;
+  private int memoizedSize = -1;
+
+  /**
+   * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
+   * oneofCases stores the FieldDescriptor for each oneof to indicate
+   * which field is set. Caller should make sure the array is immutable.
+   *
+   * This constructor is package private and will be used in
+   * {@code DynamicMutableMessage} to convert a mutable message to an immutable
+   * message.
+   */
+  DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
+                 FieldDescriptor[] oneofCases,
+                 UnknownFieldSet unknownFields) {
+    this.type = type;
+    this.fields = fields;
+    this.oneofCases = oneofCases;
+    this.unknownFields = unknownFields;
+  }
+
+  /**
+   * Get a {@code DynamicMessage} representing the default instance of the
+   * given type.
+   */
+  public static DynamicMessage getDefaultInstance(Descriptor type) {
+    int oneofDeclCount = type.toProto().getOneofDeclCount();
+    FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount];
+    return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
+                              oneofCases,
+                              UnknownFieldSet.getDefaultInstance());
+  }
+
+
+  /** Parse a message of the given type from the given input stream. */
+  public static DynamicMessage parseFrom(Descriptor type,
+                                         CodedInputStream input)
+                                         throws IOException {
+    return newBuilder(type).mergeFrom(input).buildParsed();
+  }
+
+  /** Parse a message of the given type from the given input stream. */
+  public static DynamicMessage parseFrom(
+      Descriptor type,
+      CodedInputStream input,
+      ExtensionRegistry extensionRegistry)
+      throws IOException {
+    return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
+  }
+
+  /** Parse {@code data} as a message of the given type and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, ByteString data)
+                                         throws InvalidProtocolBufferException {
+    return newBuilder(type).mergeFrom(data).buildParsed();
+  }
+
+  /** Parse {@code data} as a message of the given type and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, ByteString data,
+                                         ExtensionRegistry extensionRegistry)
+                                         throws InvalidProtocolBufferException {
+    return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
+  }
+
+  /** Parse {@code data} as a message of the given type and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, byte[] data)
+                                         throws InvalidProtocolBufferException {
+    return newBuilder(type).mergeFrom(data).buildParsed();
+  }
+
+  /** Parse {@code data} as a message of the given type and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, byte[] data,
+                                         ExtensionRegistry extensionRegistry)
+                                         throws InvalidProtocolBufferException {
+    return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
+  }
+
+  /** Parse a message of the given type from {@code input} and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, InputStream input)
+                                         throws IOException {
+    return newBuilder(type).mergeFrom(input).buildParsed();
+  }
+
+  /** Parse a message of the given type from {@code input} and return it. */
+  public static DynamicMessage parseFrom(Descriptor type, InputStream input,
+                                         ExtensionRegistry extensionRegistry)
+                                         throws IOException {
+    return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
+  }
+
+  /** Construct a {@link Message.Builder} for the given type. */
+  public static Builder newBuilder(Descriptor type) {
+    return new Builder(type);
+  }
+
+  /**
+   * Construct a {@link Message.Builder} for a message of the same type as
+   * {@code prototype}, and initialize it with {@code prototype}'s contents.
+   */
+  public static Builder newBuilder(Message prototype) {
+    return new Builder(prototype.getDescriptorForType()).mergeFrom(prototype);
+  }
+
+  // -----------------------------------------------------------------
+  // Implementation of Message interface.
+
+  @Override
+  public Descriptor getDescriptorForType() {
+    return type;
+  }
+
+  @Override
+  public DynamicMessage getDefaultInstanceForType() {
+    return getDefaultInstance(type);
+  }
+
+  @Override
+  public Map<FieldDescriptor, Object> getAllFields() {
+    return fields.getAllFields();
+  }
+
+  @Override
+  public boolean hasOneof(OneofDescriptor oneof) {
+    verifyOneofContainingType(oneof);
+    FieldDescriptor field = oneofCases[oneof.getIndex()];
+    if (field == null) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+    verifyOneofContainingType(oneof);
+    return oneofCases[oneof.getIndex()];
+  }
+
+  @Override
+  public boolean hasField(FieldDescriptor field) {
+    verifyContainingType(field);
+    return fields.hasField(field);
+  }
+
+  @Override
+  public Object getField(FieldDescriptor field) {
+    verifyContainingType(field);
+    Object result = fields.getField(field);
+    if (result == null) {
+      if (field.isRepeated()) {
+        result = Collections.emptyList();
+      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        result = getDefaultInstance(field.getMessageType());
+      } else {
+        result = field.getDefaultValue();
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public int getRepeatedFieldCount(FieldDescriptor field) {
+    verifyContainingType(field);
+    return fields.getRepeatedFieldCount(field);
+  }
+
+  @Override
+  public Object getRepeatedField(FieldDescriptor field, int index) {
+    verifyContainingType(field);
+    return fields.getRepeatedField(field, index);
+  }
+
+  @Override
+  public UnknownFieldSet getUnknownFields() {
+    return unknownFields;
+  }
+
+  static boolean isInitialized(Descriptor type,
+                               FieldSet<FieldDescriptor> fields) {
+    // Check that all required fields are present.
+    for (final FieldDescriptor field : type.getFields()) {
+      if (field.isRequired()) {
+        if (!fields.hasField(field)) {
+          return false;
+        }
+      }
+    }
+
+    // Check that embedded messages are initialized.
+    return fields.isInitialized();
+  }
+
+  @Override
+  public boolean isInitialized() {
+    return isInitialized(type, fields);
+  }
+
+  @Override
+  public void writeTo(CodedOutputStream output) throws IOException {
+    if (type.getOptions().getMessageSetWireFormat()) {
+      fields.writeMessageSetTo(output);
+      unknownFields.writeAsMessageSetTo(output);
+    } else {
+      fields.writeTo(output);
+      unknownFields.writeTo(output);
+    }
+  }
+
+  @Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    if (type.getOptions().getMessageSetWireFormat()) {
+      size = fields.getMessageSetSerializedSize();
+      size += unknownFields.getSerializedSizeAsMessageSet();
+    } else {
+      size = fields.getSerializedSize();
+      size += unknownFields.getSerializedSize();
+    }
+
+    memoizedSize = size;
+    return size;
+  }
+
+  @Override
+  public Builder newBuilderForType() {
+    return new Builder(type);
+  }
+
+  @Override
+  public Builder toBuilder() {
+    return newBuilderForType().mergeFrom(this);
+  }
+
+  @Override
+  public Parser<DynamicMessage> getParserForType() {
+    return new AbstractParser<DynamicMessage>() {
+      @Override
+      public DynamicMessage parsePartialFrom(
+          CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+          throws InvalidProtocolBufferException {
+        Builder builder = newBuilder(type);
+        try {
+          builder.mergeFrom(input, extensionRegistry);
+        } catch (InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(builder.buildPartial());
+        } catch (IOException e) {
+          throw new InvalidProtocolBufferException(e.getMessage())
+              .setUnfinishedMessage(builder.buildPartial());
+        }
+        return builder.buildPartial();
+      }
+    };
+  }
+
+  /** Verifies that the field is a field of this message. */
+  private void verifyContainingType(FieldDescriptor field) {
+    if (field.getContainingType() != type) {
+      throw new IllegalArgumentException(
+        "FieldDescriptor does not match message type.");
+    }
+  }
+
+  /** Verifies that the oneof is an oneof of this message. */
+  private void verifyOneofContainingType(OneofDescriptor oneof) {
+    if (oneof.getContainingType() != type) {
+      throw new IllegalArgumentException(
+        "OneofDescriptor does not match message type.");
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * Builder for {@link DynamicMessage}s.
+   */
+  public static final class Builder extends AbstractMessage.Builder<Builder> {
+    private final Descriptor type;
+    private FieldSet<FieldDescriptor> fields;
+    private final FieldDescriptor[] oneofCases;
+    private UnknownFieldSet unknownFields;
+
+    /** Construct a {@code Builder} for the given type. */
+    private Builder(Descriptor type) {
+      this.type = type;
+      this.fields = FieldSet.newFieldSet();
+      this.unknownFields = UnknownFieldSet.getDefaultInstance();
+      this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
+    }
+
+    // ---------------------------------------------------------------
+    // Implementation of Message.Builder interface.
+
+    @Override
+    public Builder clear() {
+      if (fields.isImmutable()) {
+        fields = FieldSet.newFieldSet();
+      } else {
+        fields.clear();
+      }
+      unknownFields = UnknownFieldSet.getDefaultInstance();
+      return this;
+    }
+
+    @Override
+    public Builder mergeFrom(Message other) {
+      if (other instanceof DynamicMessage) {
+        // This should be somewhat faster than calling super.mergeFrom().
+        DynamicMessage otherDynamicMessage = (DynamicMessage) other;
+        if (otherDynamicMessage.type != type) {
+          throw new IllegalArgumentException(
+            "mergeFrom(Message) can only merge messages of the same type.");
+        }
+        ensureIsMutable();
+        fields.mergeFrom(otherDynamicMessage.fields);
+        mergeUnknownFields(otherDynamicMessage.unknownFields);
+        for (int i = 0; i < oneofCases.length; i++) {
+          if (oneofCases[i] == null) {
+            oneofCases[i] = otherDynamicMessage.oneofCases[i];
+          } else {
+            if ((otherDynamicMessage.oneofCases[i] != null)
+                && (oneofCases[i] != otherDynamicMessage.oneofCases[i])) {
+              fields.clearField(oneofCases[i]);
+              oneofCases[i] = otherDynamicMessage.oneofCases[i];
+            }
+          }
+        }
+        return this;
+      } else {
+        return super.mergeFrom(other);
+      }
+    }
+
+    @Override
+    public DynamicMessage build() {
+      if (!isInitialized()) {
+        throw newUninitializedMessageException(
+          new DynamicMessage(type, fields,
+              java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields));
+      }
+      return buildPartial();
+    }
+
+    /**
+     * Helper for DynamicMessage.parseFrom() methods to call.  Throws
+     * {@link InvalidProtocolBufferException} instead of
+     * {@link UninitializedMessageException}.
+     */
+    private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
+      if (!isInitialized()) {
+        throw newUninitializedMessageException(
+          new DynamicMessage(type, fields,
+              java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields))
+          .asInvalidProtocolBufferException();
+      }
+      return buildPartial();
+    }
+
+    @Override
+    public DynamicMessage buildPartial() {
+      fields.makeImmutable();
+      DynamicMessage result =
+        new DynamicMessage(type, fields,
+            java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields);
+      return result;
+    }
+
+    @Override
+    public Builder clone() {
+      Builder result = new Builder(type);
+      result.fields.mergeFrom(fields);
+      result.mergeUnknownFields(unknownFields);
+      System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length);
+      return result;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return DynamicMessage.isInitialized(type, fields);
+    }
+
+    @Override
+    public Descriptor getDescriptorForType() {
+      return type;
+    }
+
+    @Override
+    public DynamicMessage getDefaultInstanceForType() {
+      return getDefaultInstance(type);
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      return fields.getAllFields();
+    }
+
+    @Override
+    public Builder newBuilderForField(FieldDescriptor field) {
+      verifyContainingType(field);
+
+      if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+        throw new IllegalArgumentException(
+          "newBuilderForField is only valid for fields with message type.");
+      }
+
+      return new Builder(field.getMessageType());
+    }
+
+    @Override
+    public boolean hasOneof(OneofDescriptor oneof) {
+      verifyOneofContainingType(oneof);
+      FieldDescriptor field = oneofCases[oneof.getIndex()];
+      if (field == null) {
+        return false;
+      }
+      return true;
+    }
+
+    @Override
+    public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+      verifyOneofContainingType(oneof);
+      return oneofCases[oneof.getIndex()];
+    }
+
+    @Override
+    public Builder clearOneof(OneofDescriptor oneof) {
+      verifyOneofContainingType(oneof);
+      FieldDescriptor field = oneofCases[oneof.getIndex()];
+      if (field != null) {
+        clearField(field);
+      }
+      return this;
+    }
+
+    @Override
+    public boolean hasField(FieldDescriptor field) {
+      verifyContainingType(field);
+      return fields.hasField(field);
+    }
+
+    @Override
+    public Object getField(FieldDescriptor field) {
+      verifyContainingType(field);
+      Object result = fields.getField(field);
+      if (result == null) {
+        if (field.isRepeated()) {
+          result = Collections.emptyList();
+        } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          result = getDefaultInstance(field.getMessageType());
+        } else {
+          result = field.getDefaultValue();
+        }
+      }
+      return result;
+    }
+
+    @Override
+    public Builder setField(FieldDescriptor field, Object value) {
+      verifyContainingType(field);
+      ensureIsMutable();
+      // TODO(xiaofeng): This check should really be put in FieldSet.setField()
+      // where all other such checks are done. However, currently
+      // FieldSet.setField() permits Integer value for enum fields probably
+      // because of some internal features we support. Should figure it out
+      // and move this check to a more appropriate place.
+      if (field.getType() == FieldDescriptor.Type.ENUM) {
+        ensureEnumValueDescriptor(field, value);
+      }
+      OneofDescriptor oneofDescriptor = field.getContainingOneof();
+      if (oneofDescriptor != null) {
+        int index = oneofDescriptor.getIndex();
+        FieldDescriptor oldField = oneofCases[index];
+        if ((oldField != null) && (oldField != field)) {
+          fields.clearField(oldField);
+        }
+        oneofCases[index] = field;
+      }
+      fields.setField(field, value);
+      return this;
+    }
+
+    @Override
+    public Builder clearField(FieldDescriptor field) {
+      verifyContainingType(field);
+      ensureIsMutable();
+      OneofDescriptor oneofDescriptor = field.getContainingOneof();
+      if (oneofDescriptor != null) {
+        int index = oneofDescriptor.getIndex();
+        if (oneofCases[index] == field) {
+          oneofCases[index] = null;
+        }
+      }
+      fields.clearField(field);
+      return this;
+    }
+
+    @Override
+    public int getRepeatedFieldCount(FieldDescriptor field) {
+      verifyContainingType(field);
+      return fields.getRepeatedFieldCount(field);
+    }
+
+    @Override
+    public Object getRepeatedField(FieldDescriptor field, int index) {
+      verifyContainingType(field);
+      return fields.getRepeatedField(field, index);
+    }
+
+    @Override
+    public Builder setRepeatedField(FieldDescriptor field, int index, Object value) {
+      verifyContainingType(field);
+      ensureIsMutable();
+      fields.setRepeatedField(field, index, value);
+      return this;
+    }
+
+    @Override
+    public Builder addRepeatedField(FieldDescriptor field, Object value) {
+      verifyContainingType(field);
+      ensureIsMutable();
+      fields.addRepeatedField(field, value);
+      return this;
+    }
+
+    @Override
+    public UnknownFieldSet getUnknownFields() {
+      return unknownFields;
+    }
+
+    @Override
+    public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+      if (getDescriptorForType().getFile().getSyntax()
+          == Descriptors.FileDescriptor.Syntax.PROTO3) {
+        // Proto3 discards unknown fields.
+        return this;
+      }
+      this.unknownFields = unknownFields;
+      return this;
+    }
+
+    @Override
+    public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
+      if (getDescriptorForType().getFile().getSyntax()
+          == Descriptors.FileDescriptor.Syntax.PROTO3) {
+        // Proto3 discards unknown fields.
+        return this;
+      }
+      this.unknownFields =
+        UnknownFieldSet.newBuilder(this.unknownFields)
+                       .mergeFrom(unknownFields)
+                       .build();
+      return this;
+    }
+
+    /** Verifies that the field is a field of this message. */
+    private void verifyContainingType(FieldDescriptor field) {
+      if (field.getContainingType() != type) {
+        throw new IllegalArgumentException(
+          "FieldDescriptor does not match message type.");
+      }
+    }
+
+    /** Verifies that the oneof is an oneof of this message. */
+    private void verifyOneofContainingType(OneofDescriptor oneof) {
+      if (oneof.getContainingType() != type) {
+        throw new IllegalArgumentException(
+          "OneofDescriptor does not match message type.");
+      }
+    }
+
+    /** Verifies that the value is EnumValueDescriptor and matches Enum Type. */
+    private void ensureSingularEnumValueDescriptor(
+        FieldDescriptor field, Object value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      if (!(value instanceof EnumValueDescriptor)) {
+        throw new IllegalArgumentException(
+          "DynamicMessage should use EnumValueDescriptor to set Enum Value.");
+      }
+      // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
+      // set incorrect EnumValueDescriptors.
+      // EnumDescriptor fieldType = field.getEnumType();
+      // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType();
+      // if (fieldType != fieldValueType) {
+      //  throw new IllegalArgumentException(String.format(
+      //      "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value",
+      //      fieldType.getFullName(), fieldValueType.getFullName()));
+      // }
+    }
+
+    /** Verifies the value for an enum field. */
+    private void ensureEnumValueDescriptor(
+        FieldDescriptor field, Object value) {
+      if (field.isRepeated()) {
+        for (Object item : (List) value) {
+          ensureSingularEnumValueDescriptor(field, item);
+        }
+      } else {
+         ensureSingularEnumValueDescriptor(field, value);
+      }
+    }
+
+    private void ensureIsMutable() {
+      if (fields.isImmutable()) {
+        fields = fields.clone();
+      }
+    }
+
+    @Override
+    public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
+      // TODO(xiangl): need implementation for dynamic message
+      throw new UnsupportedOperationException(
+        "getFieldBuilder() called on a dynamic message type.");
+    }
+
+    @Override
+    public com.google.protobuf.Message.Builder getRepeatedFieldBuilder(FieldDescriptor field,
+        int index) {
+      throw new UnsupportedOperationException(
+        "getRepeatedFieldBuilder() called on a dynamic message type.");
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
new file mode 100644
index 0000000..3cd4c88
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
@@ -0,0 +1,66 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates a public API that can change at any time, and has no guarantee of API stability and
+ * backward-compatibility.
+ *
+ * <p>Usage guidelines:
+ * <ol>
+ * <li>This annotation is used only on public API. Internal interfaces should not use it.</li>
+ * <li>This annotation should only be added to new APIs. Adding it to an existing API is
+ * considered API-breaking.</li>
+ * <li>Removing this annotation from an API gives it stable status.</li>
+ * </ol>
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+    ElementType.ANNOTATION_TYPE,
+    ElementType.CONSTRUCTOR,
+    ElementType.FIELD,
+    ElementType.METHOD,
+    ElementType.PACKAGE,
+    ElementType.TYPE})
+@Documented
+public @interface ExperimentalApi {
+  /**
+   * Context information such as links to discussion thread, tracking issue etc.
+   */
+  String value() default "";
+}
+
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Extension.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Extension.java
new file mode 100644
index 0000000..08ec5b4
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Extension.java
@@ -0,0 +1,86 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Interface that generated extensions implement.
+ *
+ * @author liujisi@google.com (Jisi Liu)
+ */
+public abstract class Extension<ContainingType extends MessageLite, Type>
+    extends ExtensionLite<ContainingType, Type> {
+
+  /** Returns the descriptor of the extension. */
+  public abstract Descriptors.FieldDescriptor getDescriptor();
+
+  /** Returns whether or not this extension is a Lite Extension. */
+  @Override
+  final boolean isLite() {
+    return false;
+  }
+
+  // All the methods below are extension implementation details.
+
+  /**
+   * The API type that the extension is used for.
+   */
+  protected enum ExtensionType {
+    IMMUTABLE,
+    MUTABLE,
+    PROTO1,
+  }
+
+  protected ExtensionType getExtensionType() {
+    // TODO(liujisi): make this abstract after we fix proto1.
+    return ExtensionType.IMMUTABLE;
+  }
+
+  /**
+   * Type of a message extension.
+   */
+  public enum MessageType {
+    PROTO1,
+    PROTO2,
+  }
+  
+  /**
+   * If the extension is a message extension (i.e., getLiteType() == MESSAGE),
+   * returns the type of the message, otherwise undefined.
+   */
+  public MessageType getMessageType() {
+    return MessageType.PROTO2;
+  }
+
+  protected abstract Object fromReflectionType(Object value);
+  protected abstract Object singularFromReflectionType(Object value);
+  protected abstract Object toReflectionType(Object value);
+  protected abstract Object singularToReflectionType(Object value);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionLite.java
new file mode 100644
index 0000000..f8f5bd2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionLite.java
@@ -0,0 +1,63 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Lite interface that generated extensions implement.
+ * <p>
+ * Methods are for use by generated code only. You can hold a reference to
+ * extensions using this type name.
+ */
+public abstract class ExtensionLite<ContainingType extends MessageLite, Type> {
+
+  /** Returns the field number of the extension. */
+  public abstract int getNumber();
+
+  /** Returns the type of the field. */
+  public abstract WireFormat.FieldType getLiteType();
+
+  /** Returns whether it is a repeated field. */
+  public abstract boolean isRepeated();
+
+  /** Returns the default value of the extension field. */
+  public abstract Type getDefaultValue();
+
+  /**
+   * Returns the default instance of the extension field, if it's a message
+   * extension.
+   */
+  public abstract MessageLite getMessageDefaultInstance();
+  
+  /** Returns whether or not this extension is a Lite Extension. */
+  boolean isLite() {
+    return true;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
new file mode 100644
index 0000000..0067392
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -0,0 +1,392 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A table of known extensions, searchable by name or field number.  When
+ * parsing a protocol message that might have extensions, you must provide
+ * an {@code ExtensionRegistry} in which you have registered any extensions
+ * that you want to be able to parse.  Otherwise, those extensions will just
+ * be treated like unknown fields.
+ *
+ * <p>For example, if you had the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ *   extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ *   optional int32 bar;
+ * }
+ * </pre>
+ *
+ * Then you might write code like:
+ *
+ * <pre>
+ * ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ * registry.add(MyProto.bar);
+ * MyProto.Foo message = MyProto.Foo.parseFrom(input, registry);
+ * </pre>
+ *
+ * <p>Background:
+ *
+ * <p>You might wonder why this is necessary.  Two alternatives might come to
+ * mind.  First, you might imagine a system where generated extensions are
+ * automatically registered when their containing classes are loaded.  This
+ * is a popular technique, but is bad design; among other things, it creates a
+ * situation where behavior can change depending on what classes happen to be
+ * loaded.  It also introduces a security vulnerability, because an
+ * unprivileged class could cause its code to be called unexpectedly from a
+ * privileged class by registering itself as an extension of the right type.
+ *
+ * <p>Another option you might consider is lazy parsing: do not parse an
+ * extension until it is first requested, at which point the caller must
+ * provide a type to use.  This introduces a different set of problems.  First,
+ * it would require a mutex lock any time an extension was accessed, which
+ * would be slow.  Second, corrupt data would not be detected until first
+ * access, at which point it would be much harder to deal with it.  Third, it
+ * could violate the expectation that message objects are immutable, since the
+ * type provided could be any arbitrary message class.  An unprivileged user
+ * could take advantage of this to inject a mutable object into a message
+ * belonging to privileged code and create mischief.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistry extends ExtensionRegistryLite {
+  /** Construct a new, empty instance. */
+  public static ExtensionRegistry newInstance() {
+    return new ExtensionRegistry();
+  }
+
+  /** Get the unmodifiable singleton empty instance. */
+  public static ExtensionRegistry getEmptyRegistry() {
+    return EMPTY;
+  }
+
+
+  /** Returns an unmodifiable view of the registry. */
+  @Override
+  public ExtensionRegistry getUnmodifiable() {
+    return new ExtensionRegistry(this);
+  }
+
+  /** A (Descriptor, Message) pair, returned by lookup methods. */
+  public static final class ExtensionInfo {
+    /** The extension's descriptor. */
+    public final FieldDescriptor descriptor;
+
+    /**
+     * A default instance of the extension's type, if it has a message type.
+     * Otherwise, {@code null}.
+     */
+    public final Message defaultInstance;
+
+    private ExtensionInfo(final FieldDescriptor descriptor) {
+      this.descriptor = descriptor;
+      defaultInstance = null;
+    }
+    private ExtensionInfo(final FieldDescriptor descriptor,
+                          final Message defaultInstance) {
+      this.descriptor = descriptor;
+      this.defaultInstance = defaultInstance;
+    }
+  }
+
+  /**
+   * Deprecated. Use {@link #findImmutableExtensionByName(String)} instead.
+   */
+  public ExtensionInfo findExtensionByName(final String fullName) {
+    return findImmutableExtensionByName(fullName);
+  }
+
+  /**
+   * Find an extension for immutable APIs by fully-qualified field name,
+   * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
+   * match {@code fullName} if a match is found.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  public ExtensionInfo findImmutableExtensionByName(final String fullName) {
+    return immutableExtensionsByName.get(fullName);
+  }
+
+  /**
+   * Find an extension for mutable APIs by fully-qualified field name,
+   * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
+   * match {@code fullName} if a match is found.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  public ExtensionInfo findMutableExtensionByName(final String fullName) {
+    return mutableExtensionsByName.get(fullName);
+  }
+
+  /**
+   * Deprecated. Use {@link #findImmutableExtensionByNumber(
+   * Descriptors.Descriptor, int)}
+   */
+  public ExtensionInfo findExtensionByNumber(
+      final Descriptor containingType, final int fieldNumber) {
+    return findImmutableExtensionByNumber(containingType, fieldNumber);
+  }
+
+  /**
+   * Find an extension by containing type and field number for immutable APIs.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  public ExtensionInfo findImmutableExtensionByNumber(
+      final Descriptor containingType, final int fieldNumber) {
+    return immutableExtensionsByNumber.get(
+      new DescriptorIntPair(containingType, fieldNumber));
+  }
+
+  /**
+   * Find an extension by containing type and field number for mutable APIs.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  public ExtensionInfo findMutableExtensionByNumber(
+      final Descriptor containingType, final int fieldNumber) {
+    return mutableExtensionsByNumber.get(
+        new DescriptorIntPair(containingType, fieldNumber));
+  }
+
+  /**
+   * Find all extensions for mutable APIs by fully-qualified name of
+   * extended class. Note that this method is more computationally expensive
+   * than getting a single extension by name or number.
+   *
+   * @return Information about the extensions found, or {@code null} if there
+   *     are none.
+   */
+  public Set<ExtensionInfo> getAllMutableExtensionsByExtendedType(final String fullName) {
+    HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+    for (DescriptorIntPair pair : mutableExtensionsByNumber.keySet()) {
+      if (pair.descriptor.getFullName().equals(fullName)) {
+        extensions.add(mutableExtensionsByNumber.get(pair));
+      }
+    }
+    return extensions;
+  }
+
+  /**
+   * Find all extensions for immutable APIs by fully-qualified name of
+   * extended class. Note that this method is more computationally expensive
+   * than getting a single extension by name or number.
+   *
+   * @return Information about the extensions found, or {@code null} if there
+   *     are none.
+   */
+  public Set<ExtensionInfo> getAllImmutableExtensionsByExtendedType(final String fullName) {
+    HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+    for (DescriptorIntPair pair : immutableExtensionsByNumber.keySet()) {
+      if (pair.descriptor.getFullName().equals(fullName)) {
+        extensions.add(immutableExtensionsByNumber.get(pair));
+      }
+    }
+    return extensions;
+  }
+
+  /** Add an extension from a generated file to the registry. */
+  public void add(final Extension<?, ?> extension) {
+    if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE &&
+        extension.getExtensionType() != Extension.ExtensionType.MUTABLE) {
+      // do not support other extension types. ignore
+      return;
+    }
+    add(newExtensionInfo(extension), extension.getExtensionType());
+  }
+
+  static ExtensionInfo newExtensionInfo(final Extension<?, ?> extension) {
+    if (extension.getDescriptor().getJavaType() ==
+        FieldDescriptor.JavaType.MESSAGE) {
+      if (extension.getMessageDefaultInstance() == null) {
+        throw new IllegalStateException(
+            "Registered message-type extension had null default instance: " +
+                extension.getDescriptor().getFullName());
+      }
+      return new ExtensionInfo(extension.getDescriptor(),
+          (Message) extension.getMessageDefaultInstance());
+    } else {
+      return new ExtensionInfo(extension.getDescriptor(), null);
+    }
+  }
+
+  /** Add a non-message-type extension to the registry by descriptor. */
+  public void add(final FieldDescriptor type) {
+    if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+      throw new IllegalArgumentException(
+        "ExtensionRegistry.add() must be provided a default instance when " +
+        "adding an embedded message extension.");
+    }
+    ExtensionInfo info = new ExtensionInfo(type, null);
+    add(info, Extension.ExtensionType.IMMUTABLE);
+    add(info, Extension.ExtensionType.MUTABLE);
+  }
+
+  /** Add a message-type extension to the registry by descriptor. */
+  public void add(final FieldDescriptor type, final Message defaultInstance) {
+    if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+      throw new IllegalArgumentException(
+        "ExtensionRegistry.add() provided a default instance for a " +
+        "non-message extension.");
+    }
+      add(new ExtensionInfo(type, defaultInstance),
+          Extension.ExtensionType.IMMUTABLE);
+  }
+
+  // =================================================================
+  // Private stuff.
+
+  private ExtensionRegistry() {
+    this.immutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+    this.mutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+    this.immutableExtensionsByNumber =
+        new HashMap<DescriptorIntPair, ExtensionInfo>();
+    this.mutableExtensionsByNumber =
+        new HashMap<DescriptorIntPair, ExtensionInfo>();
+  }
+
+  private ExtensionRegistry(ExtensionRegistry other) {
+    super(other);
+    this.immutableExtensionsByName =
+        Collections.unmodifiableMap(other.immutableExtensionsByName);
+    this.mutableExtensionsByName =
+        Collections.unmodifiableMap(other.mutableExtensionsByName);
+    this.immutableExtensionsByNumber =
+        Collections.unmodifiableMap(other.immutableExtensionsByNumber);
+    this.mutableExtensionsByNumber =
+            Collections.unmodifiableMap(other.mutableExtensionsByNumber);
+  }
+
+  private final Map<String, ExtensionInfo> immutableExtensionsByName;
+  private final Map<String, ExtensionInfo> mutableExtensionsByName;
+  private final Map<DescriptorIntPair, ExtensionInfo> immutableExtensionsByNumber;
+  private final Map<DescriptorIntPair, ExtensionInfo> mutableExtensionsByNumber;
+
+  ExtensionRegistry(boolean empty) {
+    super(ExtensionRegistryLite.getEmptyRegistry());
+    this.immutableExtensionsByName =
+        Collections.<String, ExtensionInfo>emptyMap();
+    this.mutableExtensionsByName =
+        Collections.<String, ExtensionInfo>emptyMap();
+    this.immutableExtensionsByNumber =
+        Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+    this.mutableExtensionsByNumber =
+            Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+  }
+  private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true);
+
+  private void add(
+      final ExtensionInfo extension,
+      final Extension.ExtensionType extensionType) {
+    if (!extension.descriptor.isExtension()) {
+      throw new IllegalArgumentException(
+          "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
+              "(non-extension) field.");
+    }
+
+    Map<String, ExtensionInfo> extensionsByName;
+    Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
+    switch (extensionType) {
+      case IMMUTABLE:
+        extensionsByName = immutableExtensionsByName;
+        extensionsByNumber = immutableExtensionsByNumber;
+        break;
+      case MUTABLE:
+        extensionsByName = mutableExtensionsByName;
+        extensionsByNumber = mutableExtensionsByNumber;
+        break;
+      default:
+        // Ignore the unknown supported type.
+        return;
+    }
+
+    extensionsByName.put(extension.descriptor.getFullName(), extension);
+    extensionsByNumber.put(
+      new DescriptorIntPair(extension.descriptor.getContainingType(),
+                            extension.descriptor.getNumber()),
+      extension);
+
+    final FieldDescriptor field = extension.descriptor;
+    if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
+        field.getType() == FieldDescriptor.Type.MESSAGE &&
+        field.isOptional() &&
+        field.getExtensionScope() == field.getMessageType()) {
+      // This is an extension of a MessageSet type defined within the extension
+      // type's own scope.  For backwards-compatibility, allow it to be looked
+      // up by type name.
+      extensionsByName.put(field.getMessageType().getFullName(), extension);
+    }
+  }
+
+  /** A (GenericDescriptor, int) pair, used as a map key. */
+  private static final class DescriptorIntPair {
+    private final Descriptor descriptor;
+    private final int number;
+
+    DescriptorIntPair(final Descriptor descriptor, final int number) {
+      this.descriptor = descriptor;
+      this.number = number;
+    }
+
+    @Override
+    public int hashCode() {
+      return descriptor.hashCode() * ((1 << 16) - 1) + number;
+    }
+    @Override
+    public boolean equals(final Object obj) {
+      if (!(obj instanceof DescriptorIntPair)) {
+        return false;
+      }
+      final DescriptorIntPair other = (DescriptorIntPair)obj;
+      return descriptor == other.descriptor && number == other.number;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
new file mode 100644
index 0000000..65cf738
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -0,0 +1,185 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Equivalent to {@link ExtensionRegistry} but supports only "lite" types.
+ * <p>
+ * If all of your types are lite types, then you only need to use
+ * {@code ExtensionRegistryLite}.  Similarly, if all your types are regular
+ * types, then you only need {@link ExtensionRegistry}.  Typically it does not
+ * make sense to mix the two, since if you have any regular types in your
+ * program, you then require the full runtime and lose all the benefits of
+ * the lite runtime, so you might as well make all your types be regular types.
+ * However, in some cases (e.g. when depending on multiple third-party libraries
+ * where one uses lite types and one uses regular), you may find yourself
+ * wanting to mix the two.  In this case things get more complicated.
+ * <p>
+ * There are three factors to consider:  Whether the type being extended is
+ * lite, whether the embedded type (in the case of a message-typed extension)
+ * is lite, and whether the extension itself is lite.  Since all three are
+ * declared in different files, they could all be different.  Here are all
+ * the combinations and which type of registry to use:
+ * <pre>
+ *   Extended type     Inner type    Extension         Use registry
+ *   =======================================================================
+ *   lite              lite          lite              ExtensionRegistryLite
+ *   lite              regular       lite              ExtensionRegistry
+ *   regular           regular       regular           ExtensionRegistry
+ *   all other combinations                            not supported
+ * </pre>
+ * <p>
+ * Note that just as regular types are not allowed to contain lite-type fields,
+ * they are also not allowed to contain lite-type extensions.  This is because
+ * regular types must be fully accessible via reflection, which in turn means
+ * that all the inner messages must also support reflection.  On the other hand,
+ * since regular types implement the entire lite interface, there is no problem
+ * with embedding regular types inside lite types.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistryLite {
+
+  // Set true to enable lazy parsing feature for MessageSet.
+  //
+  // TODO(xiangl): Now we use a global flag to control whether enable lazy
+  // parsing feature for MessageSet, which may be too crude for some
+  // applications. Need to support this feature on smaller granularity.
+  private static volatile boolean eagerlyParseMessageSets = false;
+
+  public static boolean isEagerlyParseMessageSets() {
+    return eagerlyParseMessageSets;
+  }
+
+  public static void setEagerlyParseMessageSets(boolean isEagerlyParse) {
+    eagerlyParseMessageSets = isEagerlyParse;
+  }
+
+  /** Construct a new, empty instance. */
+  public static ExtensionRegistryLite newInstance() {
+    return new ExtensionRegistryLite();
+  }
+
+  /** Get the unmodifiable singleton empty instance. */
+  public static ExtensionRegistryLite getEmptyRegistry() {
+    return EMPTY;
+  }
+
+  /** Returns an unmodifiable view of the registry. */
+  public ExtensionRegistryLite getUnmodifiable() {
+    return new ExtensionRegistryLite(this);
+  }
+
+  /**
+   * Find an extension by containing type and field number.
+   *
+   * @return Information about the extension if found, or {@code null}
+   *         otherwise.
+   */
+  @SuppressWarnings("unchecked")
+  public <ContainingType extends MessageLite>
+      GeneratedMessageLite.GeneratedExtension<ContainingType, ?>
+        findLiteExtensionByNumber(
+          final ContainingType containingTypeDefaultInstance,
+          final int fieldNumber) {
+    return (GeneratedMessageLite.GeneratedExtension<ContainingType, ?>)
+      extensionsByNumber.get(
+        new ObjectIntPair(containingTypeDefaultInstance, fieldNumber));
+  }
+
+  /** Add an extension from a lite generated file to the registry. */
+  public final void add(
+      final GeneratedMessageLite.GeneratedExtension<?, ?> extension) {
+    extensionsByNumber.put(
+      new ObjectIntPair(extension.getContainingTypeDefaultInstance(),
+                        extension.getNumber()),
+      extension);
+  }
+
+  // =================================================================
+  // Private stuff.
+
+  // Constructors are package-private so that ExtensionRegistry can subclass
+  // this.
+
+  ExtensionRegistryLite() {
+    this.extensionsByNumber =
+        new HashMap<ObjectIntPair,
+                    GeneratedMessageLite.GeneratedExtension<?, ?>>();
+  }
+
+  ExtensionRegistryLite(ExtensionRegistryLite other) {
+    if (other == EMPTY) {
+      this.extensionsByNumber = Collections.emptyMap();
+    } else {
+      this.extensionsByNumber =
+        Collections.unmodifiableMap(other.extensionsByNumber);
+    }
+  }
+
+  private final Map<ObjectIntPair,
+                    GeneratedMessageLite.GeneratedExtension<?, ?>>
+      extensionsByNumber;
+
+  private ExtensionRegistryLite(boolean empty) {
+    this.extensionsByNumber = Collections.emptyMap();
+  }
+  private static final ExtensionRegistryLite EMPTY =
+    new ExtensionRegistryLite(true);
+
+  /** A (Object, int) pair, used as a map key. */
+  private static final class ObjectIntPair {
+    private final Object object;
+    private final int number;
+
+    ObjectIntPair(final Object object, final int number) {
+      this.object = object;
+      this.number = number;
+    }
+
+    @Override
+    public int hashCode() {
+      return System.identityHashCode(object) * ((1 << 16) - 1) + number;
+    }
+    @Override
+    public boolean equals(final Object obj) {
+      if (!(obj instanceof ObjectIntPair)) {
+        return false;
+      }
+      final ObjectIntPair other = (ObjectIntPair)obj;
+      return object == other.object && number == other.number;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FieldSet.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FieldSet.java
new file mode 100644
index 0000000..4e89709
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -0,0 +1,908 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.LazyField.LazyIterator;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class which represents an arbitrary set of fields of some message type.
+ * This is used to implement {@link DynamicMessage}, and also to represent
+ * extensions in {@link GeneratedMessage}.  This class is package-private,
+ * since outside users should probably be using {@link DynamicMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+final class FieldSet<FieldDescriptorType extends
+      FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
+  /**
+   * Interface for a FieldDescriptor or lite extension descriptor.  This
+   * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}.
+   */
+  public interface FieldDescriptorLite<T extends FieldDescriptorLite<T>>
+      extends Comparable<T> {
+    int getNumber();
+    WireFormat.FieldType getLiteType();
+    WireFormat.JavaType getLiteJavaType();
+    boolean isRepeated();
+    boolean isPacked();
+    Internal.EnumLiteMap<?> getEnumType();
+
+    // If getLiteJavaType() == MESSAGE, this merges a message object of the
+    // type into a builder of the type.  Returns {@code to}.
+    MessageLite.Builder internalMergeFrom(
+        MessageLite.Builder to, MessageLite from);
+  }
+
+  private final SmallSortedMap<FieldDescriptorType, Object> fields;
+  private boolean isImmutable;
+  private boolean hasLazyField = false;
+
+  /** Construct a new FieldSet. */
+  private FieldSet() {
+    this.fields = SmallSortedMap.newFieldMap(16);
+  }
+
+  /**
+   * Construct an empty FieldSet.  This is only used to initialize
+   * DEFAULT_INSTANCE.
+   */
+  private FieldSet(final boolean dummy) {
+    this.fields = SmallSortedMap.newFieldMap(0);
+    makeImmutable();
+  }
+
+  /** Construct a new FieldSet. */
+  public static <T extends FieldSet.FieldDescriptorLite<T>>
+      FieldSet<T> newFieldSet() {
+    return new FieldSet<T>();
+  }
+
+  /** Get an immutable empty FieldSet. */
+  @SuppressWarnings("unchecked")
+  public static <T extends FieldSet.FieldDescriptorLite<T>>
+      FieldSet<T> emptySet() {
+    return DEFAULT_INSTANCE;
+  }
+  @SuppressWarnings("rawtypes")
+  private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
+
+  /** Make this FieldSet immutable from this point forward. */
+  @SuppressWarnings("unchecked")
+  public void makeImmutable() {
+    if (isImmutable) {
+      return;
+    }
+    fields.makeImmutable();
+    isImmutable = true;
+  }
+
+  /**
+   * Returns whether the FieldSet is immutable. This is true if it is the
+   * {@link #emptySet} or if {@link #makeImmutable} were called.
+   *
+   * @return whether the FieldSet is immutable.
+   */
+  public boolean isImmutable() {
+    return isImmutable;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof FieldSet)) {
+      return false;
+    }
+    
+    FieldSet<?> other = (FieldSet<?>) o;
+    return other.fields.equals(other.fields);
+  }
+  
+  @Override
+  public int hashCode() {
+    return fields.hashCode();
+  }
+
+  /**
+   * Clones the FieldSet. The returned FieldSet will be mutable even if the
+   * original FieldSet was immutable.
+   *
+   * @return the newly cloned FieldSet
+   */
+  @Override
+  public FieldSet<FieldDescriptorType> clone() {
+    // We can't just call fields.clone because List objects in the map
+    // should not be shared.
+    FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet();
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
+      FieldDescriptorType descriptor = entry.getKey();
+      clone.setField(descriptor, entry.getValue());
+    }
+    for (Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      FieldDescriptorType descriptor = entry.getKey();
+      clone.setField(descriptor, entry.getValue());
+    }
+    clone.hasLazyField = hasLazyField;
+    return clone;
+  }
+
+
+  // =================================================================
+
+  /** See {@link Message.Builder#clear()}. */
+  public void clear() {
+    fields.clear();
+    hasLazyField = false;
+  }
+
+  /**
+   * Get a simple map containing all the fields.
+   */
+  public Map<FieldDescriptorType, Object> getAllFields() {
+    if (hasLazyField) {
+      SmallSortedMap<FieldDescriptorType, Object> result =
+          SmallSortedMap.newFieldMap(16);
+      for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+        cloneFieldEntry(result, fields.getArrayEntryAt(i));
+      }
+      for (Map.Entry<FieldDescriptorType, Object> entry :
+          fields.getOverflowEntries()) {
+        cloneFieldEntry(result, entry);
+      }
+      if (fields.isImmutable()) {
+        result.makeImmutable();
+      }
+      return result;
+    }
+    return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
+  }
+
+  private void cloneFieldEntry(Map<FieldDescriptorType, Object> map,
+      Map.Entry<FieldDescriptorType, Object> entry) {
+    FieldDescriptorType key = entry.getKey();
+    Object value = entry.getValue();
+    if (value instanceof LazyField) {
+      map.put(key, ((LazyField) value).getValue());
+    } else {
+      map.put(key, value);
+    }
+  }
+
+  /**
+   * Get an iterator to the field map. This iterator should not be leaked out
+   * of the protobuf library as it is not protected from mutation when fields
+   * is not immutable.
+   */
+  public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
+    if (hasLazyField) {
+      return new LazyIterator<FieldDescriptorType>(
+          fields.entrySet().iterator());
+    }
+    return fields.entrySet().iterator();
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message#hasField(Descriptors.FieldDescriptor)}.
+   */
+  public boolean hasField(final FieldDescriptorType descriptor) {
+    if (descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "hasField() can only be called on non-repeated fields.");
+    }
+
+    return fields.get(descriptor) != null;
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message#getField(Descriptors.FieldDescriptor)}.  This method
+   * returns {@code null} if the field is not set; in this case it is up
+   * to the caller to fetch the field's default value.
+   */
+  public Object getField(final FieldDescriptorType descriptor) {
+    Object o = fields.get(descriptor);
+    if (o instanceof LazyField) {
+      return ((LazyField) o).getValue();
+    }
+    return o;
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
+   */
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public void setField(final FieldDescriptorType descriptor,
+                       Object value) {
+    if (descriptor.isRepeated()) {
+      if (!(value instanceof List)) {
+        throw new IllegalArgumentException(
+          "Wrong object type used with protocol message reflection.");
+      }
+
+      // Wrap the contents in a new list so that the caller cannot change
+      // the list's contents after setting it.
+      final List newList = new ArrayList();
+      newList.addAll((List) value);
+      for (final Object element : newList) {
+        verifyType(descriptor.getLiteType(), element);
+      }
+      value = newList;
+    } else {
+      verifyType(descriptor.getLiteType(), value);
+    }
+
+    if (value instanceof LazyField) {
+      hasLazyField = true;
+    }
+    fields.put(descriptor, value);
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}.
+   */
+  public void clearField(final FieldDescriptorType descriptor) {
+    fields.remove(descriptor);
+    if (fields.isEmpty()) {
+      hasLazyField = false;
+    }
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
+   */
+  public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
+    if (!descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "getRepeatedField() can only be called on repeated fields.");
+    }
+
+    final Object value = getField(descriptor);
+    if (value == null) {
+      return 0;
+    } else {
+      return ((List<?>) value).size();
+    }
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}.
+   */
+  public Object getRepeatedField(final FieldDescriptorType descriptor,
+                                 final int index) {
+    if (!descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "getRepeatedField() can only be called on repeated fields.");
+    }
+
+    final Object value = getField(descriptor);
+
+    if (value == null) {
+      throw new IndexOutOfBoundsException();
+    } else {
+      return ((List<?>) value).get(index);
+    }
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
+   */
+  @SuppressWarnings("unchecked")
+  public void setRepeatedField(final FieldDescriptorType descriptor,
+                               final int index,
+                               final Object value) {
+    if (!descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "getRepeatedField() can only be called on repeated fields.");
+    }
+
+    final Object list = getField(descriptor);
+    if (list == null) {
+      throw new IndexOutOfBoundsException();
+    }
+
+    verifyType(descriptor.getLiteType(), value);
+    ((List<Object>) list).set(index, value);
+  }
+
+  /**
+   * Useful for implementing
+   * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}.
+   */
+  @SuppressWarnings("unchecked")
+  public void addRepeatedField(final FieldDescriptorType descriptor,
+                               final Object value) {
+    if (!descriptor.isRepeated()) {
+      throw new IllegalArgumentException(
+        "addRepeatedField() can only be called on repeated fields.");
+    }
+
+    verifyType(descriptor.getLiteType(), value);
+
+    final Object existingValue = getField(descriptor);
+    List<Object> list;
+    if (existingValue == null) {
+      list = new ArrayList<Object>();
+      fields.put(descriptor, list);
+    } else {
+      list = (List<Object>) existingValue;
+    }
+
+    list.add(value);
+  }
+
+  /**
+   * Verifies that the given object is of the correct type to be a valid
+   * value for the given field.  (For repeated fields, this checks if the
+   * object is the right type to be one element of the field.)
+   *
+   * @throws IllegalArgumentException The value is not of the right type.
+   */
+  private static void verifyType(final WireFormat.FieldType type,
+                                 final Object value) {
+    if (value == null) {
+      throw new NullPointerException();
+    }
+
+    boolean isValid = false;
+    switch (type.getJavaType()) {
+      case INT:          isValid = value instanceof Integer   ; break;
+      case LONG:         isValid = value instanceof Long      ; break;
+      case FLOAT:        isValid = value instanceof Float     ; break;
+      case DOUBLE:       isValid = value instanceof Double    ; break;
+      case BOOLEAN:      isValid = value instanceof Boolean   ; break;
+      case STRING:       isValid = value instanceof String    ; break;
+      case BYTE_STRING:
+        isValid = value instanceof ByteString || value instanceof byte[];
+        break;
+      case ENUM:
+        // TODO(kenton):  Caller must do type checking here, I guess.
+        isValid =
+            (value instanceof Integer || value instanceof Internal.EnumLite);
+        break;
+      case MESSAGE:
+        // TODO(kenton):  Caller must do type checking here, I guess.
+        isValid =
+            (value instanceof MessageLite) || (value instanceof LazyField);
+        break;
+    }
+
+    if (!isValid) {
+      // TODO(kenton):  When chaining calls to setField(), it can be hard to
+      //   tell from the stack trace which exact call failed, since the whole
+      //   chain is considered one line of code.  It would be nice to print
+      //   more information here, e.g. naming the field.  We used to do that.
+      //   But we can't now that FieldSet doesn't use descriptors.  Maybe this
+      //   isn't a big deal, though, since it would only really apply when using
+      //   reflection and generally people don't chain reflection setters.
+      throw new IllegalArgumentException(
+        "Wrong object type used with protocol message reflection.");
+    }
+  }
+
+  // =================================================================
+  // Parsing and serialization
+
+  /**
+   * See {@link Message#isInitialized()}.  Note:  Since {@code FieldSet}
+   * itself does not have any way of knowing about required fields that
+   * aren't actually present in the set, it is up to the caller to check
+   * that all required fields are present.
+   */
+  public boolean isInitialized() {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      if (!isInitialized(fields.getArrayEntryAt(i))) {
+        return false;
+      }
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      if (!isInitialized(entry)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @SuppressWarnings("unchecked")
+  private boolean isInitialized(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+      if (descriptor.isRepeated()) {
+        for (final MessageLite element:
+                 (List<MessageLite>) entry.getValue()) {
+          if (!element.isInitialized()) {
+            return false;
+          }
+        }
+      } else {
+        Object value = entry.getValue();
+        if (value instanceof MessageLite) {
+          if (!((MessageLite) value).isInitialized()) {
+            return false;
+          }
+        } else if (value instanceof LazyField) {
+          return true;
+        } else {
+          throw new IllegalArgumentException(
+              "Wrong object type used with protocol message reflection.");
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Given a field type, return the wire type.
+   *
+   * @returns One of the {@code WIRETYPE_} constants defined in
+   *          {@link WireFormat}.
+   */
+  static int getWireFormatForFieldType(final WireFormat.FieldType type,
+                                       boolean isPacked) {
+    if (isPacked) {
+      return WireFormat.WIRETYPE_LENGTH_DELIMITED;
+    } else {
+      return type.getWireType();
+    }
+  }
+
+  /**
+   * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another 
+   * {@link FieldSet}.
+   */
+  public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
+    for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
+      mergeFromField(other.fields.getArrayEntryAt(i));
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             other.fields.getOverflowEntries()) {
+      mergeFromField(entry);
+    }
+  }
+
+  private Object cloneIfMutable(Object value) {
+    if (value instanceof byte[]) {
+      byte[] bytes = (byte[]) value;
+      byte[] copy = new byte[bytes.length];
+      System.arraycopy(bytes, 0, copy, 0, bytes.length);
+      return copy;
+    } else {
+      return value;
+    }
+  }
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  private void mergeFromField(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    Object otherValue = entry.getValue();
+    if (otherValue instanceof LazyField) {
+      otherValue = ((LazyField) otherValue).getValue();
+    }
+
+    if (descriptor.isRepeated()) {
+      Object value = getField(descriptor);
+      if (value == null) {
+        value = new ArrayList();
+      }
+      for (Object element : (List) otherValue) {
+        ((List) value).add(cloneIfMutable(element));
+      }
+      fields.put(descriptor, value);
+    } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+      Object value = getField(descriptor);
+      if (value == null) {
+        fields.put(descriptor, cloneIfMutable(otherValue));
+      } else {
+        // Merge the messages.
+          value = descriptor.internalMergeFrom(
+                ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
+                .build();
+
+        fields.put(descriptor, value);
+      }
+    } else {
+      fields.put(descriptor, cloneIfMutable(otherValue));
+    }
+  }
+
+  // TODO(kenton):  Move static parsing and serialization methods into some
+  //   other class.  Probably WireFormat.
+
+  /**
+   * Read a field of any primitive type for immutable messages from a
+   * CodedInputStream. Enums, groups, and embedded messages are not handled by
+   * this method.
+   *
+   * @param input The stream from which to read.
+   * @param type Declared type of the field.
+   * @param checkUtf8 When true, check that the input is valid utf8.
+   * @return An object representing the field's value, of the exact
+   *         type which would be returned by
+   *         {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *         this field.
+   */
+  public static Object readPrimitiveField(
+      CodedInputStream input,
+      final WireFormat.FieldType type,
+      boolean checkUtf8) throws IOException {
+    if (checkUtf8) {
+      return WireFormat.readPrimitiveField(input, type,
+          WireFormat.Utf8Validation.STRICT);
+    } else {
+      return WireFormat.readPrimitiveField(input, type,
+          WireFormat.Utf8Validation.LOOSE);
+    }
+  }
+
+
+  /** See {@link Message#writeTo(CodedOutputStream)}. */
+  public void writeTo(final CodedOutputStream output)
+                      throws IOException {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      final Map.Entry<FieldDescriptorType, Object> entry =
+          fields.getArrayEntryAt(i);
+      writeField(entry.getKey(), entry.getValue(), output);
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+         fields.getOverflowEntries()) {
+      writeField(entry.getKey(), entry.getValue(), output);
+    }
+  }
+
+  /**
+   * Like {@link #writeTo} but uses MessageSet wire format.
+   */
+  public void writeMessageSetTo(final CodedOutputStream output)
+                                throws IOException {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      writeMessageSetTo(fields.getArrayEntryAt(i), output);
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      writeMessageSetTo(entry, output);
+    }
+  }
+
+  private void writeMessageSetTo(
+      final Map.Entry<FieldDescriptorType, Object> entry,
+      final CodedOutputStream output) throws IOException {
+    final FieldDescriptorType descriptor = entry.getKey();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+        !descriptor.isRepeated() && !descriptor.isPacked()) {
+      Object value = entry.getValue();
+      if (value instanceof LazyField) {
+        value = ((LazyField) value).getValue();
+      }
+      output.writeMessageSetExtension(entry.getKey().getNumber(),
+                                      (MessageLite) value);
+    } else {
+      writeField(descriptor, entry.getValue(), output);
+    }
+  }
+
+  /**
+   * Write a single tag-value pair to the stream.
+   *
+   * @param output The output stream.
+   * @param type   The field's type.
+   * @param number The field's number.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static void writeElement(final CodedOutputStream output,
+                                   final WireFormat.FieldType type,
+                                   final int number,
+                                   final Object value) throws IOException {
+    // Special case for groups, which need a start and end tag; other fields
+    // can just use writeTag() and writeFieldNoTag().
+    if (type == WireFormat.FieldType.GROUP) {
+        output.writeGroup(number, (MessageLite) value);
+    } else {
+      output.writeTag(number, getWireFormatForFieldType(type, false));
+      writeElementNoTag(output, type, value);
+    }
+  }
+
+  /**
+   * Write a field of arbitrary type, without its tag, to the stream.
+   *
+   * @param output The output stream.
+   * @param type The field's type.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  static void writeElementNoTag(
+      final CodedOutputStream output,
+      final WireFormat.FieldType type,
+      final Object value) throws IOException {
+    switch (type) {
+      case DOUBLE  : output.writeDoubleNoTag  ((Double     ) value); break;
+      case FLOAT   : output.writeFloatNoTag   ((Float      ) value); break;
+      case INT64   : output.writeInt64NoTag   ((Long       ) value); break;
+      case UINT64  : output.writeUInt64NoTag  ((Long       ) value); break;
+      case INT32   : output.writeInt32NoTag   ((Integer    ) value); break;
+      case FIXED64 : output.writeFixed64NoTag ((Long       ) value); break;
+      case FIXED32 : output.writeFixed32NoTag ((Integer    ) value); break;
+      case BOOL    : output.writeBoolNoTag    ((Boolean    ) value); break;
+      case GROUP   : output.writeGroupNoTag   ((MessageLite) value); break;
+      case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
+      case STRING:
+        if (value instanceof ByteString) {
+          output.writeBytesNoTag((ByteString) value);
+        } else {
+          output.writeStringNoTag((String) value);
+        }
+        break;
+      case BYTES:
+        if (value instanceof ByteString) {
+          output.writeBytesNoTag((ByteString) value);
+        } else {
+          output.writeByteArrayNoTag((byte[]) value);
+        }
+        break;
+      case UINT32  : output.writeUInt32NoTag  ((Integer    ) value); break;
+      case SFIXED32: output.writeSFixed32NoTag((Integer    ) value); break;
+      case SFIXED64: output.writeSFixed64NoTag((Long       ) value); break;
+      case SINT32  : output.writeSInt32NoTag  ((Integer    ) value); break;
+      case SINT64  : output.writeSInt64NoTag  ((Long       ) value); break;
+
+      case ENUM:
+        if (value instanceof Internal.EnumLite) {
+          output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
+        } else {
+          output.writeEnumNoTag(((Integer) value).intValue());
+        }
+        break;
+    }
+  }
+
+  /** Write a single field. */
+  public static void writeField(final FieldDescriptorLite<?> descriptor,
+                                final Object value,
+                                final CodedOutputStream output)
+                                throws IOException {
+    WireFormat.FieldType type = descriptor.getLiteType();
+    int number = descriptor.getNumber();
+    if (descriptor.isRepeated()) {
+      final List<?> valueList = (List<?>)value;
+      if (descriptor.isPacked()) {
+        output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+        // Compute the total data size so the length can be written.
+        int dataSize = 0;
+        for (final Object element : valueList) {
+          dataSize += computeElementSizeNoTag(type, element);
+        }
+        output.writeRawVarint32(dataSize);
+        // Write the data itself, without any tags.
+        for (final Object element : valueList) {
+          writeElementNoTag(output, type, element);
+        }
+      } else {
+        for (final Object element : valueList) {
+          writeElement(output, type, number, element);
+        }
+      }
+    } else {
+      if (value instanceof LazyField) {
+        writeElement(output, type, number, ((LazyField) value).getValue());
+      } else {
+        writeElement(output, type, number, value);
+      }
+    }
+  }
+
+  /**
+   * See {@link Message#getSerializedSize()}.  It's up to the caller to cache
+   * the resulting size if desired.
+   */
+  public int getSerializedSize() {
+    int size = 0;
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      final Map.Entry<FieldDescriptorType, Object> entry =
+          fields.getArrayEntryAt(i);
+      size += computeFieldSize(entry.getKey(), entry.getValue());
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+         fields.getOverflowEntries()) {
+      size += computeFieldSize(entry.getKey(), entry.getValue());
+    }
+    return size;
+  }
+
+  /**
+   * Like {@link #getSerializedSize} but uses MessageSet wire format.
+   */
+  public int getMessageSetSerializedSize() {
+    int size = 0;
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      size += getMessageSetSerializedSize(fields.getArrayEntryAt(i));
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      size += getMessageSetSerializedSize(entry);
+    }
+    return size;
+  }
+
+  private int getMessageSetSerializedSize(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    Object value = entry.getValue();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+        && !descriptor.isRepeated() && !descriptor.isPacked()) {
+      if (value instanceof LazyField) {
+        return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
+            entry.getKey().getNumber(), (LazyField) value);
+      } else {
+        return CodedOutputStream.computeMessageSetExtensionSize(
+            entry.getKey().getNumber(), (MessageLite) value);
+      }
+    } else {
+      return computeFieldSize(descriptor, value);
+    }
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * single tag/value pair of arbitrary type.
+   *
+   * @param type   The field's type.
+   * @param number The field's number.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  private static int computeElementSize(
+      final WireFormat.FieldType type,
+      final int number, final Object value) {
+    int tagSize = CodedOutputStream.computeTagSize(number);
+    if (type == WireFormat.FieldType.GROUP) {
+      // Only count the end group tag for proto2 messages as for proto1 the end
+      // group tag will be counted as a part of getSerializedSize().
+        tagSize *= 2;
+    }
+    return tagSize + computeElementSizeNoTag(type, value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * particular value of arbitrary type, excluding tag.
+   *
+   * @param type   The field's type.
+   * @param value  Object representing the field's value.  Must be of the exact
+   *               type which would be returned by
+   *               {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *               this field.
+   */
+  static int computeElementSizeNoTag(
+      final WireFormat.FieldType type, final Object value) {
+    switch (type) {
+      // Note:  Minor violation of 80-char limit rule here because this would
+      //   actually be harder to read if we wrapped the lines.
+      case DOUBLE  : return CodedOutputStream.computeDoubleSizeNoTag  ((Double     )value);
+      case FLOAT   : return CodedOutputStream.computeFloatSizeNoTag   ((Float      )value);
+      case INT64   : return CodedOutputStream.computeInt64SizeNoTag   ((Long       )value);
+      case UINT64  : return CodedOutputStream.computeUInt64SizeNoTag  ((Long       )value);
+      case INT32   : return CodedOutputStream.computeInt32SizeNoTag   ((Integer    )value);
+      case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long       )value);
+      case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer    )value);
+      case BOOL    : return CodedOutputStream.computeBoolSizeNoTag    ((Boolean    )value);
+      case GROUP   : return CodedOutputStream.computeGroupSizeNoTag   ((MessageLite)value);
+      case BYTES   :
+        if (value instanceof ByteString) {
+          return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+        } else {
+          return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
+        }
+      case STRING  :
+        if (value instanceof ByteString) {
+          return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+        } else {
+          return CodedOutputStream.computeStringSizeNoTag((String) value);
+        }
+      case UINT32  : return CodedOutputStream.computeUInt32SizeNoTag  ((Integer    )value);
+      case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer    )value);
+      case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long       )value);
+      case SINT32  : return CodedOutputStream.computeSInt32SizeNoTag  ((Integer    )value);
+      case SINT64  : return CodedOutputStream.computeSInt64SizeNoTag  ((Long       )value);
+
+      case MESSAGE:
+        if (value instanceof LazyField) {
+          return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
+        } else {
+          return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
+        }
+
+      case ENUM:
+        if (value instanceof Internal.EnumLite) {
+          return CodedOutputStream.computeEnumSizeNoTag(
+              ((Internal.EnumLite) value).getNumber());
+        } else {
+          return CodedOutputStream.computeEnumSizeNoTag((Integer) value);
+        }
+    }
+
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
+  }
+
+  /**
+   * Compute the number of bytes needed to encode a particular field.
+   */
+  public static int computeFieldSize(final FieldDescriptorLite<?> descriptor,
+                                     final Object value) {
+    WireFormat.FieldType type = descriptor.getLiteType();
+    int number = descriptor.getNumber();
+    if (descriptor.isRepeated()) {
+      if (descriptor.isPacked()) {
+        int dataSize = 0;
+        for (final Object element : (List<?>)value) {
+          dataSize += computeElementSizeNoTag(type, element);
+        }
+        return dataSize +
+            CodedOutputStream.computeTagSize(number) +
+            CodedOutputStream.computeRawVarint32Size(dataSize);
+      } else {
+        int size = 0;
+        for (final Object element : (List<?>)value) {
+          size += computeElementSize(type, number, element);
+        }
+        return size;
+      }
+    } else {
+      return computeElementSize(type, number, value);
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
new file mode 100644
index 0000000..63cb6d7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -0,0 +1,269 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.FloatList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link FloatList} on top of a primitive array.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess {
+  
+  private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  public static FloatArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+  
+  /**
+   * The backing store for the list.
+   */
+  private float[] array;
+  
+  /**
+   * The size of the list distinct from the length of the array. That is, it is the number of
+   * elements set in the list.
+   */
+  private int size;
+
+  /**
+   * Constructs a new mutable {@code FloatArrayList} with default capacity.
+   */
+  FloatArrayList() {
+    this(new float[DEFAULT_CAPACITY], 0);
+  }
+
+  /**
+   * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}.
+   */
+  private FloatArrayList(float[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof FloatArrayList)) {
+      return super.equals(o);
+    }
+    FloatArrayList other = (FloatArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final float[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Float.floatToIntBits(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public FloatList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new FloatArrayList(Arrays.copyOf(array, capacity), size);
+  }
+  
+  @Override
+  public Float get(int index) {
+    return getFloat(index);
+  }
+
+  @Override
+  public float getFloat(int index) {
+    ensureIndexInRange(index);
+    return array[index];
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Float set(int index, Float element) {
+    return setFloat(index, element);
+  }
+
+  @Override
+  public float setFloat(int index, float element) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    float previousValue = array[index];
+    array[index] = element;
+    return previousValue;
+  }
+
+  @Override
+  public void add(int index, Float element) {
+    addFloat(index, element);
+  }
+
+  /**
+   * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+   */
+  @Override
+  public void addFloat(float element) {
+    addFloat(size, element);
+  }
+
+  /**
+   * Like {@link #add(int, Float)} but more efficient in that it doesn't box the element.
+   */
+  private void addFloat(int index, float element) {
+    ensureIsMutable();
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+    
+    if (size < array.length) {
+      // Shift everything over to make room
+      System.arraycopy(array, index, array, index + 1, size - index);
+    } else {
+      // Resize to 1.5x the size
+      int length = ((size * 3) / 2) + 1;
+      float[] newArray = new float[length];
+      
+      // Copy the first part directly
+      System.arraycopy(array, 0, newArray, 0, index);
+      
+      // Copy the rest shifted over by one to make room
+      System.arraycopy(array, index, newArray, index + 1, size - index);
+      array = newArray;
+    }
+
+    array[index] = element;
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends Float> collection) {
+    ensureIsMutable();
+    
+    if (collection == null) {
+      throw new NullPointerException();
+    }
+    
+    // We specialize when adding another FloatArrayList to avoid boxing elements.
+    if (!(collection instanceof FloatArrayList)) {
+      return super.addAll(collection);
+    }
+    
+    FloatArrayList list = (FloatArrayList) collection;
+    if (list.size == 0) {
+      return false;
+    }
+    
+    int overflow = Integer.MAX_VALUE - size;
+    if (overflow < list.size) {
+      // We can't actually represent a list this large.
+      throw new OutOfMemoryError();
+    }
+    
+    int newSize = size + list.size;
+    if (newSize > array.length) {
+      array = Arrays.copyOf(array, newSize);
+    }
+    
+    System.arraycopy(list.array, 0, array, size, list.size);
+    size = newSize;
+    modCount++;
+    return true;
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    for (int i = 0; i < size; i++) {
+      if (o.equals(array[i])) {
+        System.arraycopy(array, i + 1, array, i, size - i);
+        size--;
+        modCount++;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Float remove(int index) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    float value = array[index];
+    System.arraycopy(array, index + 1, array, index, size - index);
+    size--;
+    modCount++;
+    return value;
+  }
+
+  /**
+   * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+   * {@link IndexOutOfBoundsException} if it is not.
+   * 
+   * @param index the index to verify is in range
+   */
+  private void ensureIndexInRange(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+  }
+
+  private String makeOutOfBoundsExceptionMessage(int index) {
+    return "Index:" + index + ", Size:" + size;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
new file mode 100644
index 0000000..790cb62
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -0,0 +1,2883 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * All generated protocol message classes extend this class.  This class
+ * implements most of the Message and Builder interfaces using Java reflection.
+ * Users can ignore this class and pretend that generated messages implement
+ * the Message interface directly.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessage extends AbstractMessage
+    implements Serializable {
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * For testing. Allows a test to disable the optimization that avoids using
+   * field builders for nested messages until they are requested. By disabling
+   * this optimization, existing tests can be reused to test the field builders.
+   */
+  protected static boolean alwaysUseFieldBuilders = false;
+
+  /** For use by generated code only.  */
+  protected UnknownFieldSet unknownFields;
+
+  protected GeneratedMessage() {
+    unknownFields = UnknownFieldSet.getDefaultInstance();
+  }
+
+  protected GeneratedMessage(Builder<?> builder) {
+    unknownFields = builder.getUnknownFields();
+  }
+
+  @Override
+  public Parser<? extends GeneratedMessage> getParserForType() {
+    throw new UnsupportedOperationException(
+        "This is supposed to be overridden by subclasses.");
+  }
+
+ /**
+  * For testing. Allows a test to disable the optimization that avoids using
+  * field builders for nested messages until they are requested. By disabling
+  * this optimization, existing tests can be reused to test the field builders.
+  * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+  */
+  static void enableAlwaysUseFieldBuildersForTesting() {
+    alwaysUseFieldBuilders = true;
+  }
+
+  /**
+   * Get the FieldAccessorTable for this type.  We can't have the message
+   * class pass this in to the constructor because of bootstrapping trouble
+   * with DescriptorProtos.
+   */
+  protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+  @Override
+  public Descriptor getDescriptorForType() {
+    return internalGetFieldAccessorTable().descriptor;
+  }
+
+  /**
+   * Internal helper to return a modifiable map containing all the fields.
+   * The returned Map is modifialbe so that the caller can add additional
+   * extension fields to implement {@link #getAllFields()}.
+   *
+   * @param getBytesForString whether to generate ByteString for string fields
+   */
+  private Map<FieldDescriptor, Object> getAllFieldsMutable(
+      boolean getBytesForString) {
+    final TreeMap<FieldDescriptor, Object> result =
+      new TreeMap<FieldDescriptor, Object>();
+    final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+    final List<FieldDescriptor> fields = descriptor.getFields();
+
+    for (int i = 0; i < fields.size(); i++) {
+      FieldDescriptor field = fields.get(i);
+      final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+      /*
+       * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+       * and it is not repeated. There is no need to iterate through the others.
+       */
+      if (oneofDescriptor != null) {
+        // Skip other fields in the Oneof we know are not set
+        i += oneofDescriptor.getFieldCount() - 1;
+        if (!hasOneof(oneofDescriptor)) {
+          // If no field is set in the Oneof, skip all the fields in the Oneof
+          continue;
+        }
+        // Get the pointer to the only field which is set in the Oneof
+        field = getOneofFieldDescriptor(oneofDescriptor);
+      } else {
+        // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+        if (field.isRepeated()) {
+          final List<?> value = (List<?>) getField(field);
+          if (!value.isEmpty()) {
+            result.put(field, value);
+          }
+          continue;
+        }
+        if (!hasField(field)) {
+          continue;
+        }
+      }
+      // Add the field to the map
+      if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+        result.put(field, getFieldRaw(field));
+      } else {
+        result.put(field, getField(field));
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public boolean isInitialized() {
+    for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+      // Check that all required fields are present.
+      if (field.isRequired()) {
+        if (!hasField(field)) {
+          return false;
+        }
+      }
+      // Check that embedded messages are initialized.
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        if (field.isRepeated()) {
+          @SuppressWarnings("unchecked") final
+          List<Message> messageList = (List<Message>) getField(field);
+          for (final Message element : messageList) {
+            if (!element.isInitialized()) {
+              return false;
+            }
+          }
+        } else {
+          if (hasField(field) && !((Message) getField(field)).isInitialized()) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  @Override
+  public Map<FieldDescriptor, Object> getAllFields() {
+    return Collections.unmodifiableMap(
+        getAllFieldsMutable(/* getBytesForString = */ false));
+  }
+
+  /**
+   * Returns a collection of all the fields in this message which are set
+   * and their corresponding values.  A singular ("required" or "optional")
+   * field is set iff hasField() returns true for that field.  A "repeated"
+   * field is set iff getRepeatedFieldCount() is greater than zero.  The
+   * values are exactly what would be returned by calling
+   * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field.  The map
+   * is guaranteed to be a sorted map, so iterating over it will return fields
+   * in order by field number.
+   */
+  Map<FieldDescriptor, Object> getAllFieldsRaw() {
+    return Collections.unmodifiableMap(
+        getAllFieldsMutable(/* getBytesForString = */ true));
+  }
+
+  @Override
+  public boolean hasOneof(final OneofDescriptor oneof) {
+    return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+  }
+
+  @Override
+  public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+    return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+  }
+
+  @Override
+  public boolean hasField(final FieldDescriptor field) {
+    return internalGetFieldAccessorTable().getField(field).has(this);
+  }
+
+  @Override
+  public Object getField(final FieldDescriptor field) {
+    return internalGetFieldAccessorTable().getField(field).get(this);
+  }
+
+  /**
+   * Obtains the value of the given field, or the default value if it is
+   * not set.  For primitive fields, the boxed primitive value is returned.
+   * For enum fields, the EnumValueDescriptor for the value is returned. For
+   * embedded message fields, the sub-message is returned.  For repeated
+   * fields, a java.util.List is returned. For present string fields, a
+   * ByteString is returned representing the bytes that the field contains.
+   */
+  Object getFieldRaw(final FieldDescriptor field) {
+    return internalGetFieldAccessorTable().getField(field).getRaw(this);
+  }
+
+  @Override
+  public int getRepeatedFieldCount(final FieldDescriptor field) {
+    return internalGetFieldAccessorTable().getField(field)
+      .getRepeatedCount(this);
+  }
+
+  @Override
+  public Object getRepeatedField(final FieldDescriptor field, final int index) {
+    return internalGetFieldAccessorTable().getField(field)
+      .getRepeated(this, index);
+  }
+
+  @Override
+  public UnknownFieldSet getUnknownFields() {
+    throw new UnsupportedOperationException(
+        "This is supposed to be overridden by subclasses.");
+  }
+
+  /**
+   * Called by subclasses to parse an unknown field.
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  protected boolean parseUnknownField(
+      CodedInputStream input,
+      UnknownFieldSet.Builder unknownFields,
+      ExtensionRegistryLite extensionRegistry,
+      int tag) throws IOException {
+    return unknownFields.mergeFieldFrom(tag, input);
+  }
+
+  protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
+      throws IOException {
+    try {
+      return parser.parseFrom(input);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
+      ExtensionRegistryLite extensions) throws IOException {
+    try {
+      return parser.parseFrom(input, extensions);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+      CodedInputStream input) throws IOException {
+    try {
+      return parser.parseFrom(input);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+      CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+    try {
+      return parser.parseFrom(input, extensions);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+      InputStream input) throws IOException {
+    try {
+      return parser.parseDelimitedFrom(input);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+      InputStream input, ExtensionRegistryLite extensions) throws IOException {
+    try {
+      return parser.parseDelimitedFrom(input, extensions);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.unwrapIOException();
+    }
+  }
+
+  @Override
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
+  }
+
+  @Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) {
+      return size;
+    }
+
+    memoizedSize = MessageReflection.getSerializedSize(
+        this, getAllFieldsRaw());
+    return memoizedSize;
+  }
+
+
+
+  /**
+   * Used by parsing constructors in generated classes.
+   */
+  protected void makeExtensionsImmutable() {
+    // Noop for messages without extensions.
+  }
+
+  protected abstract Message.Builder newBuilderForType(BuilderParent parent);
+
+  /**
+   * Interface for the parent of a Builder that allows the builder to
+   * communicate invalidations back to the parent for use when using nested
+   * builders.
+   */
+  protected interface BuilderParent {
+
+    /**
+     * A builder becomes dirty whenever a field is modified -- including fields
+     * in nested builders -- and becomes clean when build() is called.  Thus,
+     * when a builder becomes dirty, all its parents become dirty as well, and
+     * when it becomes clean, all its children become clean.  The dirtiness
+     * state is used to invalidate certain cached values.
+     * <br>
+     * To this end, a builder calls markAsDirty() on its parent whenever it
+     * transitions from clean to dirty.  The parent must propagate this call to
+     * its own parent, unless it was already dirty, in which case the
+     * grandparent must necessarily already be dirty as well.  The parent can
+     * only transition back to "clean" after calling build() on all children.
+     */
+    void markDirty();
+  }
+
+  @SuppressWarnings("unchecked")
+  public abstract static class Builder <BuilderType extends Builder<BuilderType>>
+      extends AbstractMessage.Builder<BuilderType> {
+
+    private BuilderParent builderParent;
+
+    private BuilderParentImpl meAsParent;
+
+    // Indicates that we've built a message and so we are now obligated
+    // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+    private boolean isClean;
+
+    private UnknownFieldSet unknownFields =
+        UnknownFieldSet.getDefaultInstance();
+
+    protected Builder() {
+      this(null);
+    }
+
+    protected Builder(BuilderParent builderParent) {
+      this.builderParent = builderParent;
+    }
+
+    void dispose() {
+      builderParent = null;
+    }
+
+    /**
+     * Called by the subclass when a message is built.
+     */
+    protected void onBuilt() {
+      if (builderParent != null) {
+        markClean();
+      }
+    }
+
+    /**
+     * Called by the subclass or a builder to notify us that a message was
+     * built and may be cached and therefore invalidations are needed.
+     */
+    protected void markClean() {
+      this.isClean = true;
+    }
+
+    /**
+     * Gets whether invalidations are needed
+     *
+     * @return whether invalidations are needed
+     */
+    protected boolean isClean() {
+      return isClean;
+    }
+
+    @Override
+    public BuilderType clone() {
+      BuilderType builder =
+          (BuilderType) getDefaultInstanceForType().newBuilderForType();
+      builder.mergeFrom(buildPartial());
+      return builder;
+    }
+
+    /**
+     * Called by the initialization and clear code paths to allow subclasses to
+     * reset any of their builtin fields back to the initial values.
+     */
+    @Override
+    public BuilderType clear() {
+      unknownFields = UnknownFieldSet.getDefaultInstance();
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /**
+     * Get the FieldAccessorTable for this type.  We can't have the message
+     * class pass this in to the constructor because of bootstrapping trouble
+     * with DescriptorProtos.
+     */
+    protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+    @Override
+    public Descriptor getDescriptorForType() {
+      return internalGetFieldAccessorTable().descriptor;
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      return Collections.unmodifiableMap(getAllFieldsMutable());
+    }
+
+    /** Internal helper which returns a mutable map. */
+    private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+      final TreeMap<FieldDescriptor, Object> result =
+        new TreeMap<FieldDescriptor, Object>();
+      final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+      final List<FieldDescriptor> fields = descriptor.getFields();
+
+      for (int i = 0; i < fields.size(); i++) {
+        FieldDescriptor field = fields.get(i);
+        final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+        /*
+         * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+         * and it is not repeated. There is no need to iterate through the others.
+         */
+        if (oneofDescriptor != null) {
+          // Skip other fields in the Oneof we know are not set
+          i += oneofDescriptor.getFieldCount() - 1;
+          if (!hasOneof(oneofDescriptor)) {
+            // If no field is set in the Oneof, skip all the fields in the Oneof
+            continue;
+          }
+          // Get the pointer to the only field which is set in the Oneof
+          field = getOneofFieldDescriptor(oneofDescriptor);
+        } else {
+          // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+          if (field.isRepeated()) {
+            final List<?> value = (List<?>) getField(field);
+            if (!value.isEmpty()) {
+              result.put(field, value);
+            }
+            continue;
+          }
+          if (!hasField(field)) {
+            continue;
+          }
+        }
+        // Add the field to the map
+        result.put(field, getField(field));
+      }
+      return result;
+    }
+
+    @Override
+    public Message.Builder newBuilderForField(final FieldDescriptor field) {
+      return internalGetFieldAccessorTable().getField(field).newBuilder();
+    }
+
+    @Override
+    public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+      return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+    }
+
+    @Override
+    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+      return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
+          this, index);
+    }
+
+    @Override
+    public boolean hasOneof(final OneofDescriptor oneof) {
+      return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+    }
+
+    @Override
+    public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+      return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+    }
+
+    @Override
+    public boolean hasField(final FieldDescriptor field) {
+      return internalGetFieldAccessorTable().getField(field).has(this);
+    }
+
+    @Override
+    public Object getField(final FieldDescriptor field) {
+      Object object = internalGetFieldAccessorTable().getField(field).get(this);
+      if (field.isRepeated()) {
+        // The underlying list object is still modifiable at this point.
+        // Make sure not to expose the modifiable list to the caller.
+        return Collections.unmodifiableList((List) object);
+      } else {
+        return object;
+      }
+    }
+
+    @Override
+    public BuilderType setField(final FieldDescriptor field, final Object value) {
+      internalGetFieldAccessorTable().getField(field).set(this, value);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType clearField(final FieldDescriptor field) {
+      internalGetFieldAccessorTable().getField(field).clear(this);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType clearOneof(final OneofDescriptor oneof) {
+      internalGetFieldAccessorTable().getOneof(oneof).clear(this);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
+      return internalGetFieldAccessorTable().getField(field)
+          .getRepeatedCount(this);
+    }
+
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
+      return internalGetFieldAccessorTable().getField(field)
+          .getRepeated(this, index);
+    }
+
+    @Override
+    public BuilderType setRepeatedField(
+        final FieldDescriptor field, final int index, final Object value) {
+      internalGetFieldAccessorTable().getField(field)
+        .setRepeated(this, index, value);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
+      internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
+      this.unknownFields = unknownFields;
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeUnknownFields(
+        final UnknownFieldSet unknownFields) {
+      this.unknownFields =
+        UnknownFieldSet.newBuilder(this.unknownFields)
+                       .mergeFrom(unknownFields)
+                       .build();
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+        // Check that all required fields are present.
+        if (field.isRequired()) {
+          if (!hasField(field)) {
+            return false;
+          }
+        }
+        // Check that embedded messages are initialized.
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          if (field.isRepeated()) {
+            @SuppressWarnings("unchecked") final
+            List<Message> messageList = (List<Message>) getField(field);
+            for (final Message element : messageList) {
+              if (!element.isInitialized()) {
+                return false;
+              }
+            }
+          } else {
+            if (hasField(field) &&
+                !((Message) getField(field)).isInitialized()) {
+              return false;
+            }
+          }
+        }
+      }
+      return true;
+    }
+
+    @Override
+    public final UnknownFieldSet getUnknownFields() {
+      return unknownFields;
+    }
+
+    /**
+     * Called by subclasses to parse an unknown field.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
+      return unknownFields.mergeFieldFrom(tag, input);
+    }
+
+    /**
+     * Implementation of {@link BuilderParent} for giving to our children. This
+     * small inner class makes it so we don't publicly expose the BuilderParent
+     * methods.
+     */
+    private class BuilderParentImpl implements BuilderParent {
+
+      @Override
+      public void markDirty() {
+        onChanged();
+      }
+    }
+
+    /**
+     * Gets the {@link BuilderParent} for giving to our children.
+     * @return The builder parent for our children.
+     */
+    protected BuilderParent getParentForChildren() {
+      if (meAsParent == null) {
+        meAsParent = new BuilderParentImpl();
+      }
+      return meAsParent;
+    }
+
+    /**
+     * Called when a the builder or one of its nested children has changed
+     * and any parent should be notified of its invalidation.
+     */
+    protected final void onChanged() {
+      if (isClean && builderParent != null) {
+        builderParent.markDirty();
+
+        // Don't keep dispatching invalidations until build is called again.
+        isClean = false;
+      }
+    }
+
+    /**
+     * Gets the map field with the given field number. This method should be
+     * overridden in the generated message class if the message contains map
+     * fields.
+     *
+     * Unlike other field types, reflection support for map fields can't be
+     * implemented based on generated public API because we need to access a
+     * map field as a list in reflection API but the generated API only allows
+     * us to access it as a map. This method returns the underlying map field
+     * directly and thus enables us to access the map field as a list.
+     */
+    @SuppressWarnings({"unused", "rawtypes"})
+    protected MapField internalGetMapField(int fieldNumber) {
+      // Note that we can't use descriptor names here because this method will
+      // be called when descriptor is being initialized.
+      throw new RuntimeException(
+          "No map fields found in " + getClass().getName());
+    }
+
+    /** Like {@link #internalGetMapField} but return a mutable version. */
+    @SuppressWarnings({"unused", "rawtypes"})
+    protected MapField internalGetMutableMapField(int fieldNumber) {
+      // Note that we can't use descriptor names here because this method will
+      // be called when descriptor is being initialized.
+      throw new RuntimeException(
+          "No map fields found in " + getClass().getName());
+    }
+  }
+
+  // =================================================================
+  // Extensions-related stuff
+
+  public interface ExtendableMessageOrBuilder<
+      MessageType extends ExtendableMessage> extends MessageOrBuilder {
+    // Re-define for return type covariance.
+    @Override
+    Message getDefaultInstanceForType();
+
+    /** Check if a singular extension is present. */
+    <Type> boolean hasExtension(
+        ExtensionLite<MessageType, Type> extension);
+
+    /** Get the number of elements in a repeated extension. */
+    <Type> int getExtensionCount(
+        ExtensionLite<MessageType, List<Type>> extension);
+
+    /** Get the value of an extension. */
+    <Type> Type getExtension(
+        ExtensionLite<MessageType, Type> extension);
+
+    /** Get one element of a repeated extension. */
+    <Type> Type getExtension(
+        ExtensionLite<MessageType, List<Type>> extension,
+        int index);
+  }
+
+  /**
+   * Generated message classes for message types that contain extension ranges
+   * subclass this.
+   *
+   * <p>This class implements type-safe accessors for extensions.  They
+   * implement all the same operations that you can do with normal fields --
+   * e.g. "has", "get", and "getCount" -- but for extensions.  The extensions
+   * are identified using instances of the class {@link GeneratedExtension};
+   * the protocol compiler generates a static instance of this class for every
+   * extension in its input.  Through the magic of generics, all is made
+   * type-safe.
+   *
+   * <p>For example, imagine you have the {@code .proto} file:
+   *
+   * <pre>
+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * </pre>
+   *
+   * <p>Then you might write code like:
+   *
+   * <pre>
+   * MyProto.Foo foo = getFoo();
+   * int i = foo.getExtension(MyProto.bar);
+   * </pre>
+   *
+   * <p>See also {@link ExtendableBuilder}.
+   */
+  public abstract static class ExtendableMessage<
+        MessageType extends ExtendableMessage>
+      extends GeneratedMessage
+      implements ExtendableMessageOrBuilder<MessageType> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final FieldSet<FieldDescriptor> extensions;
+
+    protected ExtendableMessage() {
+      this.extensions = FieldSet.newFieldSet();
+    }
+
+    protected ExtendableMessage(
+        ExtendableBuilder<MessageType, ?> builder) {
+      super(builder);
+      this.extensions = builder.buildExtensions();
+    }
+
+    private void verifyExtensionContainingType(
+        final Extension<MessageType, ?> extension) {
+      if (extension.getDescriptor().getContainingType() !=
+          getDescriptorForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "Extension is for type \"" +
+          extension.getDescriptor().getContainingType().getFullName() +
+          "\" which does not match message type \"" +
+          getDescriptorForType().getFullName() + "\".");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      return extensions.hasField(extension.getDescriptor());
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    @Override
+    public final <Type> int getExtensionCount(
+        final ExtensionLite<MessageType, List<Type>> extensionLite) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      return extensions.getRepeatedFieldCount(descriptor);
+    }
+
+    /** Get the value of an extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      final Object value = extensions.getField(descriptor);
+      if (value == null) {
+        if (descriptor.isRepeated()) {
+          return (Type) Collections.emptyList();
+        } else if (descriptor.getJavaType() ==
+                   FieldDescriptor.JavaType.MESSAGE) {
+          return (Type) extension.getMessageDefaultInstance();
+        } else {
+          return (Type) extension.fromReflectionType(
+              descriptor.getDefaultValue());
+        }
+      } else {
+        return (Type) extension.fromReflectionType(value);
+      }
+    }
+
+    /** Get one element of a repeated extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      return (Type) extension.singularFromReflectionType(
+          extensions.getRepeatedField(descriptor, index));
+    }
+
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return super.isInitialized() && extensionsAreInitialized();
+    }
+
+    @Override
+    protected boolean parseUnknownField(
+        CodedInputStream input,
+        UnknownFieldSet.Builder unknownFields,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      return MessageReflection.mergeFieldFrom(
+          input, unknownFields, extensionRegistry, getDescriptorForType(),
+          new MessageReflection.ExtensionAdapter(extensions), tag);
+    }
+
+
+    /**
+     * Used by parsing constructors in generated classes.
+     */
+    @Override
+    protected void makeExtensionsImmutable() {
+      extensions.makeImmutable();
+    }
+
+    /**
+     * Used by subclasses to serialize extensions.  Extension ranges may be
+     * interleaved with field numbers, but we must write them in canonical
+     * (sorted by field number) order.  ExtensionWriter helps us write
+     * individual ranges of extensions at once.
+     */
+    protected class ExtensionWriter {
+      // Imagine how much simpler this code would be if Java iterators had
+      // a way to get the next element without advancing the iterator.
+
+      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+        extensions.iterator();
+      private Map.Entry<FieldDescriptor, Object> next;
+      private final boolean messageSetWireFormat;
+
+      private ExtensionWriter(final boolean messageSetWireFormat) {
+        if (iter.hasNext()) {
+          next = iter.next();
+        }
+        this.messageSetWireFormat = messageSetWireFormat;
+      }
+
+      public void writeUntil(final int end, final CodedOutputStream output)
+                             throws IOException {
+        while (next != null && next.getKey().getNumber() < end) {
+          FieldDescriptor descriptor = next.getKey();
+          if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+                  WireFormat.JavaType.MESSAGE &&
+              !descriptor.isRepeated()) {
+            if (next instanceof LazyField.LazyEntry<?>) {
+              output.writeRawMessageSetExtension(descriptor.getNumber(),
+                  ((LazyField.LazyEntry<?>) next).getField().toByteString());
+            } else {
+              output.writeMessageSetExtension(descriptor.getNumber(),
+                                              (Message) next.getValue());
+            }
+          } else {
+            // TODO(xiangl): Taken care of following code, it may cause
+            // problem when we use LazyField for normal fields/extensions.
+            // Due to the optional field can be duplicated at the end of
+            // serialized bytes, which will make the serialized size change
+            // after lazy field parsed. So when we use LazyField globally,
+            // we need to change the following write method to write cached
+            // bytes directly rather than write the parsed message.
+            FieldSet.writeField(descriptor, next.getValue(), output);
+          }
+          if (iter.hasNext()) {
+            next = iter.next();
+          } else {
+            next = null;
+          }
+        }
+      }
+    }
+
+    protected ExtensionWriter newExtensionWriter() {
+      return new ExtensionWriter(false);
+    }
+    protected ExtensionWriter newMessageSetExtensionWriter() {
+      return new ExtensionWriter(true);
+    }
+
+    /** Called by subclasses to compute the size of extensions. */
+    protected int extensionsSerializedSize() {
+      return extensions.getSerializedSize();
+    }
+    protected int extensionsSerializedSizeAsMessageSet() {
+      return extensions.getMessageSetSerializedSize();
+    }
+
+    // ---------------------------------------------------------------
+    // Reflection
+
+    protected Map<FieldDescriptor, Object> getExtensionFields() {
+      return extensions.getAllFields();
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      final Map<FieldDescriptor, Object> result =
+          super.getAllFieldsMutable(/* getBytesForString = */ false);
+      result.putAll(getExtensionFields());
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+      final Map<FieldDescriptor, Object> result =
+          super.getAllFieldsMutable(/* getBytesForString = */ false);
+      result.putAll(getExtensionFields());
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public boolean hasField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.hasField(field);
+      } else {
+        return super.hasField(field);
+      }
+    }
+
+    @Override
+    public Object getField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        final Object value = extensions.getField(field);
+        if (value == null) {
+          if (field.isRepeated()) {
+            return Collections.emptyList();
+          } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            // Lacking an ExtensionRegistry, we have no way to determine the
+            // extension's real type, so we return a DynamicMessage.
+            return DynamicMessage.getDefaultInstance(field.getMessageType());
+          } else {
+            return field.getDefaultValue();
+          }
+        } else {
+          return value;
+        }
+      } else {
+        return super.getField(field);
+      }
+    }
+
+    @Override
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedFieldCount(field);
+      } else {
+        return super.getRepeatedFieldCount(field);
+      }
+    }
+
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field,
+                                   final int index) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedField(field, index);
+      } else {
+        return super.getRepeatedField(field, index);
+      }
+    }
+
+    private void verifyContainingType(final FieldDescriptor field) {
+      if (field.getContainingType() != getDescriptorForType()) {
+        throw new IllegalArgumentException(
+          "FieldDescriptor does not match message type.");
+      }
+    }
+  }
+
+  /**
+   * Generated message builders for message types that contain extension ranges
+   * subclass this.
+   *
+   * <p>This class implements type-safe accessors for extensions.  They
+   * implement all the same operations that you can do with normal fields --
+   * e.g. "get", "set", and "add" -- but for extensions.  The extensions are
+   * identified using instances of the class {@link GeneratedExtension}; the
+   * protocol compiler generates a static instance of this class for every
+   * extension in its input.  Through the magic of generics, all is made
+   * type-safe.
+   *
+   * <p>For example, imagine you have the {@code .proto} file:
+   *
+   * <pre>
+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * </pre>
+   *
+   * <p>Then you might write code like:
+   *
+   * <pre>
+   * MyProto.Foo foo =
+   *   MyProto.Foo.newBuilder()
+   *     .setExtension(MyProto.bar, 123)
+   *     .build();
+   * </pre>
+   *
+   * <p>See also {@link ExtendableMessage}.
+   */
+  @SuppressWarnings("unchecked")
+  public abstract static class ExtendableBuilder<
+        MessageType extends ExtendableMessage,
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+      extends Builder<BuilderType>
+      implements ExtendableMessageOrBuilder<MessageType> {
+
+    private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
+
+    protected ExtendableBuilder() {}
+
+    protected ExtendableBuilder(
+        BuilderParent parent) {
+      super(parent);
+    }
+
+    // For immutable message conversion.
+    void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
+      this.extensions = extensions;
+    }
+
+    @Override
+    public BuilderType clear() {
+      extensions = FieldSet.emptySet();
+      return super.clear();
+    }
+
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      return super.clone();
+    }
+
+    private void ensureExtensionsIsMutable() {
+      if (extensions.isImmutable()) {
+        extensions = extensions.clone();
+      }
+    }
+
+    private void verifyExtensionContainingType(
+        final Extension<MessageType, ?> extension) {
+      if (extension.getDescriptor().getContainingType() !=
+          getDescriptorForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "Extension is for type \"" +
+          extension.getDescriptor().getContainingType().getFullName() +
+          "\" which does not match message type \"" +
+          getDescriptorForType().getFullName() + "\".");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      return extensions.hasField(extension.getDescriptor());
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    @Override
+    public final <Type> int getExtensionCount(
+        final ExtensionLite<MessageType, List<Type>> extensionLite) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      return extensions.getRepeatedFieldCount(descriptor);
+    }
+
+    /** Get the value of an extension. */
+    @Override
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      final Object value = extensions.getField(descriptor);
+      if (value == null) {
+        if (descriptor.isRepeated()) {
+          return (Type) Collections.emptyList();
+        } else if (descriptor.getJavaType() ==
+                   FieldDescriptor.JavaType.MESSAGE) {
+          return (Type) extension.getMessageDefaultInstance();
+        } else {
+          return (Type) extension.fromReflectionType(
+              descriptor.getDefaultValue());
+        }
+      } else {
+        return (Type) extension.fromReflectionType(value);
+      }
+    }
+
+    /** Get one element of a repeated extension. */
+    @Override
+    public final <Type> Type getExtension(
+        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      return (Type) extension.singularFromReflectionType(
+          extensions.getRepeatedField(descriptor, index));
+    }
+
+    /** Set the value of an extension. */
+    public final <Type> BuilderType setExtension(
+        final ExtensionLite<MessageType, Type> extensionLite,
+        final Type value) {
+      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      extensions.setField(descriptor, extension.toReflectionType(value));
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /** Set the value of one element of a repeated extension. */
+    public final <Type> BuilderType setExtension(
+        final ExtensionLite<MessageType, List<Type>> extensionLite,
+        final int index, final Type value) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      extensions.setRepeatedField(
+        descriptor, index,
+        extension.singularToReflectionType(value));
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /** Append a value to a repeated extension. */
+    public final <Type> BuilderType addExtension(
+        final ExtensionLite<MessageType, List<Type>> extensionLite,
+        final Type value) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      extensions.addRepeatedField(
+          descriptor, extension.singularToReflectionType(value));
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /** Clear an extension. */
+    public final <Type> BuilderType clearExtension(
+        final ExtensionLite<MessageType, ?> extensionLite) {
+      Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.clearField(extension.getDescriptor());
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
+    /**
+     * Called by the build code path to create a copy of the extensions for
+     * building the message.
+     */
+    private FieldSet<FieldDescriptor> buildExtensions() {
+      extensions.makeImmutable();
+      return extensions;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return super.isInitialized() && extensionsAreInitialized();
+    }
+
+    /**
+     * Called by subclasses to parse an unknown field or an extension.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    @Override
+    protected boolean parseUnknownField(
+        final CodedInputStream input,
+        final UnknownFieldSet.Builder unknownFields,
+        final ExtensionRegistryLite extensionRegistry,
+        final int tag) throws IOException {
+      return MessageReflection.mergeFieldFrom(
+          input, unknownFields, extensionRegistry, getDescriptorForType(),
+          new MessageReflection.BuilderAdapter(this), tag);
+    }
+
+    // ---------------------------------------------------------------
+    // Reflection
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+      result.putAll(extensions.getAllFields());
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Object getField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        final Object value = extensions.getField(field);
+        if (value == null) {
+          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            // Lacking an ExtensionRegistry, we have no way to determine the
+            // extension's real type, so we return a DynamicMessage.
+            return DynamicMessage.getDefaultInstance(field.getMessageType());
+          } else {
+            return field.getDefaultValue();
+          }
+        } else {
+          return value;
+        }
+      } else {
+        return super.getField(field);
+      }
+    }
+
+    @Override
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedFieldCount(field);
+      } else {
+        return super.getRepeatedFieldCount(field);
+      }
+    }
+
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field,
+                                   final int index) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedField(field, index);
+      } else {
+        return super.getRepeatedField(field, index);
+      }
+    }
+
+    @Override
+    public boolean hasField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.hasField(field);
+      } else {
+        return super.hasField(field);
+      }
+    }
+
+    @Override
+    public BuilderType setField(final FieldDescriptor field,
+                                final Object value) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.setField(field, value);
+        onChanged();
+        return (BuilderType) this;
+      } else {
+        return super.setField(field, value);
+      }
+    }
+
+    @Override
+    public BuilderType clearField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.clearField(field);
+        onChanged();
+        return (BuilderType) this;
+      } else {
+        return super.clearField(field);
+      }
+    }
+
+    @Override
+    public BuilderType setRepeatedField(final FieldDescriptor field,
+                                        final int index, final Object value) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.setRepeatedField(field, index, value);
+        onChanged();
+        return (BuilderType) this;
+      } else {
+        return super.setRepeatedField(field, index, value);
+      }
+    }
+
+    @Override
+    public BuilderType addRepeatedField(final FieldDescriptor field,
+                                        final Object value) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.addRepeatedField(field, value);
+        onChanged();
+        return (BuilderType) this;
+      } else {
+        return super.addRepeatedField(field, value);
+      }
+    }
+
+    protected final void mergeExtensionFields(final ExtendableMessage other) {
+      ensureExtensionsIsMutable();
+      extensions.mergeFrom(other.extensions);
+      onChanged();
+    }
+
+    private void verifyContainingType(final FieldDescriptor field) {
+      if (field.getContainingType() != getDescriptorForType()) {
+        throw new IllegalArgumentException(
+          "FieldDescriptor does not match message type.");
+      }
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  /**
+   * Gets the descriptor for an extension. The implementation depends on whether
+   * the extension is scoped in the top level of a file or scoped in a Message.
+   */
+  static interface ExtensionDescriptorRetriever {
+    FieldDescriptor getDescriptor();
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends Message, Type>
+      GeneratedExtension<ContainingType, Type>
+      newMessageScopedGeneratedExtension(final Message scope,
+                                         final int descriptorIndex,
+                                         final Class singularType,
+                                         final Message defaultInstance) {
+    // For extensions scoped within a Message, we use the Message to resolve
+    // the outer class's descriptor, from which the extension descriptor is
+    // obtained.
+    return new GeneratedExtension<ContainingType, Type>(
+        new CachedDescriptorRetriever() {
+          @Override
+          public FieldDescriptor loadDescriptor() {
+            return scope.getDescriptorForType().getExtensions().get(descriptorIndex);
+          }
+        },
+        singularType,
+        defaultInstance,
+        Extension.ExtensionType.IMMUTABLE);
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends Message, Type>
+     GeneratedExtension<ContainingType, Type>
+     newFileScopedGeneratedExtension(final Class singularType,
+                                     final Message defaultInstance) {
+    // For extensions scoped within a file, we rely on the outer class's
+    // static initializer to call internalInit() on the extension when the
+    // descriptor is available.
+    return new GeneratedExtension<ContainingType, Type>(
+        null,  // ExtensionDescriptorRetriever is initialized in internalInit();
+        singularType,
+        defaultInstance,
+        Extension.ExtensionType.IMMUTABLE);
+  }
+
+  private abstract static class CachedDescriptorRetriever
+      implements ExtensionDescriptorRetriever {
+    private volatile FieldDescriptor descriptor;
+    protected abstract FieldDescriptor loadDescriptor();
+
+    @Override
+    public FieldDescriptor getDescriptor() {
+      if (descriptor == null) {
+        synchronized (this) {
+          if (descriptor == null) {
+            descriptor = loadDescriptor();
+          }
+        }
+      }
+      return descriptor;
+    }
+  }
+
+  /**
+   * Used in proto1 generated code only.
+   *
+   * After enabling bridge, we can define proto2 extensions (the extended type
+   * is a proto2 mutable message) in a proto1 .proto file. For these extensions
+   * we should generate proto2 GeneratedExtensions.
+   */
+  public static <ContainingType extends Message, Type>
+      GeneratedExtension<ContainingType, Type>
+      newMessageScopedGeneratedExtension(
+          final Message scope, final String name,
+          final Class singularType, final Message defaultInstance) {
+    // For extensions scoped within a Message, we use the Message to resolve
+    // the outer class's descriptor, from which the extension descriptor is
+    // obtained.
+    return new GeneratedExtension<ContainingType, Type>(
+        new CachedDescriptorRetriever() {
+          @Override
+          protected FieldDescriptor loadDescriptor() {
+            return scope.getDescriptorForType().findFieldByName(name);
+          }
+        },
+        singularType,
+        defaultInstance,
+        Extension.ExtensionType.MUTABLE);
+  }
+
+  /**
+   * Used in proto1 generated code only.
+   *
+   * After enabling bridge, we can define proto2 extensions (the extended type
+   * is a proto2 mutable message) in a proto1 .proto file. For these extensions
+   * we should generate proto2 GeneratedExtensions.
+   */
+  public static <ContainingType extends Message, Type>
+     GeneratedExtension<ContainingType, Type>
+     newFileScopedGeneratedExtension(
+         final Class singularType, final Message defaultInstance,
+         final String descriptorOuterClass, final String extensionName) {
+    // For extensions scoped within a file, we load the descriptor outer
+    // class and rely on it to get the FileDescriptor which then can be
+    // used to obtain the extension's FieldDescriptor.
+    return new GeneratedExtension<ContainingType, Type>(
+        new CachedDescriptorRetriever() {
+          @Override
+          protected FieldDescriptor loadDescriptor() {
+            try {
+              Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass);
+              FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null);
+              return file.findExtensionByName(extensionName);
+            } catch (Exception e) {
+              throw new RuntimeException(
+                  "Cannot load descriptors: "
+                      + descriptorOuterClass
+                      + " is not a valid descriptor class name",
+                  e);
+            }
+          }
+        },
+        singularType,
+        defaultInstance,
+        Extension.ExtensionType.MUTABLE);
+  }
+
+  /**
+   * Type used to represent generated extensions.  The protocol compiler
+   * generates a static singleton instance of this class for each extension.
+   *
+   * <p>For example, imagine you have the {@code .proto} file:
+   *
+   * <pre>
+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * </pre>
+   *
+   * <p>Then, {@code MyProto.Foo.bar} has type
+   * {@code GeneratedExtension<MyProto.Foo, Integer>}.
+   *
+   * <p>In general, users should ignore the details of this type, and simply use
+   * these static singletons as parameters to the extension accessors defined
+   * in {@link ExtendableMessage} and {@link ExtendableBuilder}.
+   */
+  public static class GeneratedExtension<
+      ContainingType extends Message, Type> extends
+      Extension<ContainingType, Type> {
+    // TODO(kenton):  Find ways to avoid using Java reflection within this
+    //   class.  Also try to avoid suppressing unchecked warnings.
+
+    // We can't always initialize the descriptor of a GeneratedExtension when
+    // we first construct it due to initialization order difficulties (namely,
+    // the descriptor may not have been constructed yet, since it is often
+    // constructed by the initializer of a separate module).
+    //
+    // In the case of nested extensions, we initialize the
+    // ExtensionDescriptorRetriever with an instance that uses the scoping
+    // Message's default instance to retrieve the extension's descriptor.
+    //
+    // In the case of non-nested extensions, we initialize the
+    // ExtensionDescriptorRetriever to null and rely on the outer class's static
+    // initializer to call internalInit() after the descriptor has been parsed.
+    GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
+        Class singularType,
+        Message messageDefaultInstance,
+        ExtensionType extensionType) {
+      if (Message.class.isAssignableFrom(singularType) &&
+          !singularType.isInstance(messageDefaultInstance)) {
+        throw new IllegalArgumentException(
+            "Bad messageDefaultInstance for " + singularType.getName());
+      }
+      this.descriptorRetriever = descriptorRetriever;
+      this.singularType = singularType;
+      this.messageDefaultInstance = messageDefaultInstance;
+
+      if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
+        this.enumValueOf = getMethodOrDie(singularType, "valueOf",
+                                          EnumValueDescriptor.class);
+        this.enumGetValueDescriptor =
+            getMethodOrDie(singularType, "getValueDescriptor");
+      } else {
+        this.enumValueOf = null;
+        this.enumGetValueDescriptor = null;
+      }
+      this.extensionType = extensionType;
+    }
+
+    /** For use by generated code only. */
+    public void internalInit(final FieldDescriptor descriptor) {
+      if (descriptorRetriever != null) {
+        throw new IllegalStateException("Already initialized.");
+      }
+      descriptorRetriever =
+          new ExtensionDescriptorRetriever() {
+            @Override
+            public FieldDescriptor getDescriptor() {
+              return descriptor;
+            }
+          };
+    }
+
+    private ExtensionDescriptorRetriever descriptorRetriever;
+    private final Class singularType;
+    private final Message messageDefaultInstance;
+    private final Method enumValueOf;
+    private final Method enumGetValueDescriptor;
+    private final ExtensionType extensionType;
+
+    @Override
+    public FieldDescriptor getDescriptor() {
+      if (descriptorRetriever == null) {
+        throw new IllegalStateException(
+            "getDescriptor() called before internalInit()");
+      }
+      return descriptorRetriever.getDescriptor();
+    }
+
+    /**
+     * If the extension is an embedded message or group, returns the default
+     * instance of the message.
+     */
+    @Override
+    public Message getMessageDefaultInstance() {
+      return messageDefaultInstance;
+    }
+
+    @Override
+    protected ExtensionType getExtensionType() {
+      return extensionType;
+    }
+
+    /**
+     * Convert from the type used by the reflection accessors to the type used
+     * by native accessors.  E.g., for enums, the reflection accessors use
+     * EnumValueDescriptors but the native accessors use the generated enum
+     * type.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    protected Object fromReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
+      if (descriptor.isRepeated()) {
+        if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
+            descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+          // Must convert the whole list.
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
+            result.add(singularFromReflectionType(element));
+          }
+          return result;
+        } else {
+          return value;
+        }
+      } else {
+        return singularFromReflectionType(value);
+      }
+    }
+
+    /**
+     * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
+     * type, this converts a single element.
+     */
+    @Override
+    protected Object singularFromReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
+      switch (descriptor.getJavaType()) {
+        case MESSAGE:
+          if (singularType.isInstance(value)) {
+            return value;
+          } else {
+            return messageDefaultInstance.newBuilderForType()
+                .mergeFrom((Message) value).build();
+          }
+        case ENUM:
+          return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
+        default:
+          return value;
+      }
+    }
+
+    /**
+     * Convert from the type used by the native accessors to the type used
+     * by reflection accessors.  E.g., for enums, the reflection accessors use
+     * EnumValueDescriptors but the native accessors use the generated enum
+     * type.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    protected Object toReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
+      if (descriptor.isRepeated()) {
+        if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+          // Must convert the whole list.
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
+            result.add(singularToReflectionType(element));
+          }
+          return result;
+        } else {
+          return value;
+        }
+      } else {
+        return singularToReflectionType(value);
+      }
+    }
+
+    /**
+     * Like {@link #toReflectionType(Object)}, but if the type is a repeated
+     * type, this converts a single element.
+     */
+    @Override
+    protected Object singularToReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
+      switch (descriptor.getJavaType()) {
+        case ENUM:
+          return invokeOrDie(enumGetValueDescriptor, value);
+        default:
+          return value;
+      }
+    }
+
+    @Override
+    public int getNumber() {
+      return getDescriptor().getNumber();
+    }
+
+    @Override
+    public WireFormat.FieldType getLiteType() {
+      return getDescriptor().getLiteType();
+    }
+
+    @Override
+    public boolean isRepeated() {
+      return getDescriptor().isRepeated();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Type getDefaultValue() {
+      if (isRepeated()) {
+        return (Type) Collections.emptyList();
+      }
+      if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        return (Type) messageDefaultInstance;
+      }
+      return (Type) singularFromReflectionType(
+          getDescriptor().getDefaultValue());
+    }
+  }
+
+  // =================================================================
+
+  /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+  @SuppressWarnings("unchecked")
+  private static Method getMethodOrDie(
+      final Class clazz, final String name, final Class... params) {
+    try {
+      return clazz.getMethod(name, params);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(
+        "Generated message class \"" + clazz.getName() +
+        "\" missing method \"" + name + "\".", e);
+    }
+  }
+
+  /** Calls invoke and throws a RuntimeException if it fails. */
+  private static Object invokeOrDie(
+      final Method method, final Object object, final Object... params) {
+    try {
+      return method.invoke(object, params);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(
+        "Couldn't use Java reflection to implement protocol message " +
+        "reflection.", e);
+    } catch (InvocationTargetException e) {
+      final Throwable cause = e.getCause();
+      if (cause instanceof RuntimeException) {
+        throw (RuntimeException) cause;
+      } else if (cause instanceof Error) {
+        throw (Error) cause;
+      } else {
+        throw new RuntimeException(
+          "Unexpected exception thrown by generated accessor method.", cause);
+      }
+    }
+  }
+
+  /**
+   * Gets the map field with the given field number. This method should be
+   * overridden in the generated message class if the message contains map
+   * fields.
+   *
+   * Unlike other field types, reflection support for map fields can't be
+   * implemented based on generated public API because we need to access a
+   * map field as a list in reflection API but the generated API only allows
+   * us to access it as a map. This method returns the underlying map field
+   * directly and thus enables us to access the map field as a list.
+   */
+  @SuppressWarnings({"rawtypes", "unused"})
+  protected MapField internalGetMapField(int fieldNumber) {
+    // Note that we can't use descriptor names here because this method will
+    // be called when descriptor is being initialized.
+    throw new RuntimeException(
+        "No map fields found in " + getClass().getName());
+  }
+
+  /**
+   * Users should ignore this class.  This class provides the implementation
+   * with access to the fields of a message object using Java reflection.
+   */
+  public static final class FieldAccessorTable {
+
+    /**
+     * Construct a FieldAccessorTable for a particular message class.  Only
+     * one FieldAccessorTable should ever be constructed per class.
+     *
+     * @param descriptor     The type's descriptor.
+     * @param camelCaseNames The camelcase names of all fields in the message.
+     *                       These are used to derive the accessor method names.
+     * @param messageClass   The message type.
+     * @param builderClass   The builder type.
+     */
+    public FieldAccessorTable(
+        final Descriptor descriptor,
+        final String[] camelCaseNames,
+        final Class<? extends GeneratedMessage> messageClass,
+        final Class<? extends Builder> builderClass) {
+      this(descriptor, camelCaseNames);
+      ensureFieldAccessorsInitialized(messageClass, builderClass);
+    }
+
+    /**
+     * Construct a FieldAccessorTable for a particular message class without
+     * initializing FieldAccessors.
+     */
+    public FieldAccessorTable(
+        final Descriptor descriptor,
+        final String[] camelCaseNames) {
+      this.descriptor = descriptor;
+      this.camelCaseNames = camelCaseNames;
+      fields = new FieldAccessor[descriptor.getFields().size()];
+      oneofs = new OneofAccessor[descriptor.getOneofs().size()];
+      initialized = false;
+    }
+
+    private boolean isMapFieldEnabled(FieldDescriptor field) {
+      boolean result = true;
+      return result;
+    }
+
+    /**
+     * Ensures the field accessors are initialized. This method is thread-safe.
+     *
+     * @param messageClass   The message type.
+     * @param builderClass   The builder type.
+     * @return this
+     */
+    public FieldAccessorTable ensureFieldAccessorsInitialized(
+        Class<? extends GeneratedMessage> messageClass,
+        Class<? extends Builder> builderClass) {
+      if (initialized) { return this; }
+      synchronized (this) {
+        if (initialized) { return this; }
+        int fieldsSize = fields.length;
+        for (int i = 0; i < fieldsSize; i++) {
+          FieldDescriptor field = descriptor.getFields().get(i);
+          String containingOneofCamelCaseName = null;
+          if (field.getContainingOneof() != null) {
+            containingOneofCamelCaseName =
+                camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
+          }
+          if (field.isRepeated()) {
+            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+              if (field.isMapField() && isMapFieldEnabled(field)) {
+                fields[i] = new MapFieldAccessor(
+                    field, camelCaseNames[i], messageClass, builderClass);
+              } else {
+                fields[i] = new RepeatedMessageFieldAccessor(
+                    field, camelCaseNames[i], messageClass, builderClass);
+              }
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+              fields[i] = new RepeatedEnumFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            } else {
+              fields[i] = new RepeatedFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            }
+          } else {
+            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+              fields[i] = new SingularMessageFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass,
+                  containingOneofCamelCaseName);
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+              fields[i] = new SingularEnumFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass,
+                  containingOneofCamelCaseName);
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+              fields[i] = new SingularStringFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass,
+                  containingOneofCamelCaseName);
+            } else {
+              fields[i] = new SingularFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass,
+                  containingOneofCamelCaseName);
+            }
+          }
+        }
+
+        int oneofsSize = oneofs.length;
+        for (int i = 0; i < oneofsSize; i++) {
+          oneofs[i] = new OneofAccessor(
+              descriptor, camelCaseNames[i + fieldsSize],
+              messageClass, builderClass);
+        }
+        initialized = true;
+        camelCaseNames = null;
+        return this;
+      }
+    }
+
+    private final Descriptor descriptor;
+    private final FieldAccessor[] fields;
+    private String[] camelCaseNames;
+    private final OneofAccessor[] oneofs;
+    private volatile boolean initialized;
+
+    /** Get the FieldAccessor for a particular field. */
+    private FieldAccessor getField(final FieldDescriptor field) {
+      if (field.getContainingType() != descriptor) {
+        throw new IllegalArgumentException(
+          "FieldDescriptor does not match message type.");
+      } else if (field.isExtension()) {
+        // If this type had extensions, it would subclass ExtendableMessage,
+        // which overrides the reflection interface to handle extensions.
+        throw new IllegalArgumentException(
+          "This type does not have extensions.");
+      }
+      return fields[field.getIndex()];
+    }
+
+    /** Get the OneofAccessor for a particular oneof. */
+    private OneofAccessor getOneof(final OneofDescriptor oneof) {
+      if (oneof.getContainingType() != descriptor) {
+        throw new IllegalArgumentException(
+          "OneofDescriptor does not match message type.");
+      }
+      return oneofs[oneof.getIndex()];
+    }
+
+    /**
+     * Abstract interface that provides access to a single field.  This is
+     * implemented differently depending on the field type and cardinality.
+     */
+    private interface FieldAccessor {
+      Object get(GeneratedMessage message);
+      Object get(GeneratedMessage.Builder builder);
+      Object getRaw(GeneratedMessage message);
+      Object getRaw(GeneratedMessage.Builder builder);
+      void set(Builder builder, Object value);
+      Object getRepeated(GeneratedMessage message, int index);
+      Object getRepeated(GeneratedMessage.Builder builder, int index);
+      Object getRepeatedRaw(GeneratedMessage message, int index);
+      Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
+      void setRepeated(Builder builder,
+                       int index, Object value);
+      void addRepeated(Builder builder, Object value);
+      boolean has(GeneratedMessage message);
+      boolean has(GeneratedMessage.Builder builder);
+      int getRepeatedCount(GeneratedMessage message);
+      int getRepeatedCount(GeneratedMessage.Builder builder);
+      void clear(Builder builder);
+      Message.Builder newBuilder();
+      Message.Builder getBuilder(GeneratedMessage.Builder builder);
+      Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
+                                         int index);
+    }
+
+    /** OneofAccessor provides access to a single oneof. */
+    private static class OneofAccessor {
+      OneofAccessor(
+          final Descriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        this.descriptor = descriptor;
+        caseMethod =
+            getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
+        caseMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
+        clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+      }
+
+      private final Descriptor descriptor;
+      private final Method caseMethod;
+      private final Method caseMethodBuilder;
+      private final Method clearMethod;
+
+      public boolean has(final GeneratedMessage message) {
+        if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
+          return false;
+        }
+        return true;
+      }
+
+      public boolean has(GeneratedMessage.Builder builder) {
+        if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
+          return false;
+        }
+        return true;
+      }
+
+      public FieldDescriptor get(final GeneratedMessage message) {
+        int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+        if (fieldNumber > 0) {
+          return descriptor.findFieldByNumber(fieldNumber);
+        }
+        return null;
+      }
+
+      public FieldDescriptor get(GeneratedMessage.Builder builder) {
+        int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+        if (fieldNumber > 0) {
+          return descriptor.findFieldByNumber(fieldNumber);
+        }
+        return null;
+      }
+
+      public void clear(final Builder builder) {
+        invokeOrDie(clearMethod, builder);
+      }
+    }
+
+    private static boolean supportFieldPresence(FileDescriptor file) {
+      return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
+    }
+
+    // ---------------------------------------------------------------
+
+    private static class SingularFieldAccessor implements FieldAccessor {
+      SingularFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass,
+          final String containingOneofCamelCaseName) {
+        field = descriptor;
+        isOneofField = descriptor.getContainingOneof() != null;
+        hasHasMethod = supportFieldPresence(descriptor.getFile())
+            || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
+        getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+        getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
+        type = getMethod.getReturnType();
+        setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
+        hasMethod =
+            hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+        hasMethodBuilder =
+            hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
+        clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+        caseMethod = isOneofField ? getMethodOrDie(
+            messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
+        caseMethodBuilder = isOneofField ? getMethodOrDie(
+            builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+      }
+
+      // Note:  We use Java reflection to call public methods rather than
+      //   access private fields directly as this avoids runtime security
+      //   checks.
+      protected final Class<?> type;
+      protected final Method getMethod;
+      protected final Method getMethodBuilder;
+      protected final Method setMethod;
+      protected final Method hasMethod;
+      protected final Method hasMethodBuilder;
+      protected final Method clearMethod;
+      protected final Method caseMethod;
+      protected final Method caseMethodBuilder;
+      protected final FieldDescriptor field;
+      protected final boolean isOneofField;
+      protected final boolean hasHasMethod;
+
+      private int getOneofFieldNumber(final GeneratedMessage message) {
+        return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+      }
+
+      private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
+        return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+      }
+
+      @Override
+      public Object get(final GeneratedMessage message) {
+        return invokeOrDie(getMethod, message);
+      }
+      @Override
+      public Object get(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getMethodBuilder, builder);
+      }
+      @Override
+      public Object getRaw(final GeneratedMessage message) {
+        return get(message);
+      }
+      @Override
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
+      @Override
+      public void set(final Builder builder, final Object value) {
+        invokeOrDie(setMethod, builder, value);
+      }
+      @Override
+      public Object getRepeated(final GeneratedMessage message, final int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedField() called on a singular field.");
+      }
+      @Override
+      public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldRaw() called on a singular field.");
+      }
+      @Override
+      public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedField() called on a singular field.");
+      }
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldRaw() called on a singular field.");
+      }
+      @Override
+      public void setRepeated(final Builder builder, final int index, final Object value) {
+        throw new UnsupportedOperationException(
+          "setRepeatedField() called on a singular field.");
+      }
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
+        throw new UnsupportedOperationException(
+          "addRepeatedField() called on a singular field.");
+      }
+      @Override
+      public boolean has(final GeneratedMessage message) {
+        if (!hasHasMethod) {
+          if (isOneofField) {
+            return getOneofFieldNumber(message) == field.getNumber();
+          }
+          return !get(message).equals(field.getDefaultValue());
+        }
+        return (Boolean) invokeOrDie(hasMethod, message);
+      }
+      @Override
+      public boolean has(GeneratedMessage.Builder builder) {
+        if (!hasHasMethod) {
+          if (isOneofField) {
+            return getOneofFieldNumber(builder) == field.getNumber();
+          }
+          return !get(builder).equals(field.getDefaultValue());
+        }
+        return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+      }
+      @Override
+      public int getRepeatedCount(final GeneratedMessage message) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldSize() called on a singular field.");
+      }
+      @Override
+      public int getRepeatedCount(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldSize() called on a singular field.");
+      }
+      @Override
+      public void clear(final Builder builder) {
+        invokeOrDie(clearMethod, builder);
+      }
+      @Override
+      public Message.Builder newBuilder() {
+        throw new UnsupportedOperationException(
+          "newBuilderForField() called on a non-Message type.");
+      }
+      @Override
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getFieldBuilder() called on a non-Message type.");
+      }
+      @Override
+      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldBuilder() called on a non-Message type.");
+      }
+    }
+
+    private static class RepeatedFieldAccessor implements FieldAccessor {
+      protected final Class type;
+      protected final Method getMethod;
+      protected final Method getMethodBuilder;
+      protected final Method getRepeatedMethod;
+      protected final Method getRepeatedMethodBuilder;
+      protected final Method setRepeatedMethod;
+      protected final Method addRepeatedMethod;
+      protected final Method getCountMethod;
+      protected final Method getCountMethodBuilder;
+      protected final Method clearMethod;
+
+      RepeatedFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        getMethod = getMethodOrDie(messageClass,
+                                   "get" + camelCaseName + "List");
+        getMethodBuilder = getMethodOrDie(builderClass,
+                                   "get" + camelCaseName + "List");
+        getRepeatedMethod =
+            getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+        getRepeatedMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
+        type = getRepeatedMethod.getReturnType();
+        setRepeatedMethod =
+            getMethodOrDie(builderClass, "set" + camelCaseName,
+                           Integer.TYPE, type);
+        addRepeatedMethod =
+            getMethodOrDie(builderClass, "add" + camelCaseName, type);
+        getCountMethod =
+            getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+        getCountMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+
+        clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+      }
+
+      @Override
+      public Object get(final GeneratedMessage message) {
+        return invokeOrDie(getMethod, message);
+      }
+      @Override
+      public Object get(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getMethodBuilder, builder);
+      }
+      @Override
+      public Object getRaw(final GeneratedMessage message) {
+        return get(message);
+      }
+      @Override
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
+      @Override
+      public void set(final Builder builder, final Object value) {
+        // Add all the elements individually.  This serves two purposes:
+        // 1) Verifies that each element has the correct type.
+        // 2) Insures that the caller cannot modify the list later on and
+        //    have the modifications be reflected in the message.
+        clear(builder);
+        for (final Object element : (List<?>) value) {
+          addRepeated(builder, element);
+        }
+      }
+      @Override
+      public Object getRepeated(final GeneratedMessage message, final int index) {
+        return invokeOrDie(getRepeatedMethod, message, index);
+      }
+      @Override
+      public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+        return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+      }
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage message, int index) {
+        return getRepeated(message, index);
+      }
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
+        return getRepeated(builder, index);
+      }
+      @Override
+      public void setRepeated(final Builder builder, final int index, final Object value) {
+        invokeOrDie(setRepeatedMethod, builder, index, value);
+      }
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
+        invokeOrDie(addRepeatedMethod, builder, value);
+      }
+      @Override
+      public boolean has(final GeneratedMessage message) {
+        throw new UnsupportedOperationException(
+          "hasField() called on a repeated field.");
+      }
+      @Override
+      public boolean has(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "hasField() called on a repeated field.");
+      }
+      @Override
+      public int getRepeatedCount(final GeneratedMessage message) {
+        return (Integer) invokeOrDie(getCountMethod, message);
+      }
+      @Override
+      public int getRepeatedCount(GeneratedMessage.Builder builder) {
+        return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+      }
+      @Override
+      public void clear(final Builder builder) {
+        invokeOrDie(clearMethod, builder);
+      }
+      @Override
+      public Message.Builder newBuilder() {
+        throw new UnsupportedOperationException(
+          "newBuilderForField() called on a non-Message type.");
+      }
+      @Override
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getFieldBuilder() called on a non-Message type.");
+      }
+      @Override
+      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldBuilder() called on a non-Message type.");
+      }
+    }
+
+    private static class MapFieldAccessor implements FieldAccessor {
+      MapFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        field = descriptor;
+        Method getDefaultInstanceMethod =
+            getMethodOrDie(messageClass, "getDefaultInstance");
+        MapField defaultMapField = getMapField(
+            (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
+        mapEntryMessageDefaultInstance =
+            defaultMapField.getMapEntryMessageDefaultInstance();
+      }
+
+      private final FieldDescriptor field;
+      private final Message mapEntryMessageDefaultInstance;
+
+      private MapField<?, ?> getMapField(GeneratedMessage message) {
+        return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
+      }
+
+      private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
+        return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
+      }
+
+      private MapField<?, ?> getMutableMapField(
+          GeneratedMessage.Builder builder) {
+        return (MapField<?, ?>) builder.internalGetMutableMapField(
+            field.getNumber());
+      }
+
+      @Override
+      public Object get(GeneratedMessage message) {
+        List result = new ArrayList();
+        for (int i = 0; i < getRepeatedCount(message); i++) {
+          result.add(getRepeated(message, i));
+        }
+        return Collections.unmodifiableList(result);
+      }
+
+      @Override
+      public Object get(Builder builder) {
+        List result = new ArrayList();
+        for (int i = 0; i < getRepeatedCount(builder); i++) {
+          result.add(getRepeated(builder, i));
+        }
+        return Collections.unmodifiableList(result);
+      }
+
+      @Override
+      public Object getRaw(GeneratedMessage message) {
+        return get(message);
+      }
+
+      @Override
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return get(builder);
+      }
+
+      @Override
+      public void set(Builder builder, Object value) {
+        clear(builder);
+        for (Object entry : (List) value) {
+          addRepeated(builder, entry);
+        }
+      }
+
+      @Override
+      public Object getRepeated(GeneratedMessage message, int index) {
+        return getMapField(message).getList().get(index);
+      }
+
+      @Override
+      public Object getRepeated(Builder builder, int index) {
+        return getMapField(builder).getList().get(index);
+      }
+
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage message, int index) {
+        return getRepeated(message, index);
+      }
+
+      @Override
+      public Object getRepeatedRaw(Builder builder, int index) {
+        return getRepeated(builder, index);
+      }
+
+      @Override
+      public void setRepeated(Builder builder, int index, Object value) {
+        getMutableMapField(builder).getMutableList().set(index, (Message) value);
+      }
+
+      @Override
+      public void addRepeated(Builder builder, Object value) {
+        getMutableMapField(builder).getMutableList().add((Message) value);
+      }
+
+      @Override
+      public boolean has(GeneratedMessage message) {
+        throw new UnsupportedOperationException(
+            "hasField() is not supported for repeated fields.");
+      }
+
+      @Override
+      public boolean has(Builder builder) {
+        throw new UnsupportedOperationException(
+            "hasField() is not supported for repeated fields.");
+      }
+
+      @Override
+      public int getRepeatedCount(GeneratedMessage message) {
+        return getMapField(message).getList().size();
+      }
+
+      @Override
+      public int getRepeatedCount(Builder builder) {
+        return getMapField(builder).getList().size();
+      }
+
+      @Override
+      public void clear(Builder builder) {
+        getMutableMapField(builder).getMutableList().clear();
+      }
+
+      @Override
+      public com.google.protobuf.Message.Builder newBuilder() {
+        return mapEntryMessageDefaultInstance.newBuilderForType();
+      }
+
+      @Override
+      public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
+        throw new UnsupportedOperationException(
+            "Nested builder not supported for map fields.");
+      }
+
+      @Override
+      public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
+        throw new UnsupportedOperationException(
+            "Nested builder not supported for map fields.");
+      }
+    }
+
+    // ---------------------------------------------------------------
+
+    private static final class SingularEnumFieldAccessor
+        extends SingularFieldAccessor {
+      SingularEnumFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass,
+          final String containingOneofCamelCaseName) {
+        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+
+        enumDescriptor = descriptor.getEnumType();
+
+        valueOfMethod = getMethodOrDie(type, "valueOf",
+                                       EnumValueDescriptor.class);
+        getValueDescriptorMethod =
+          getMethodOrDie(type, "getValueDescriptor");
+
+        supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+        if (supportUnknownEnumValue) {
+          getValueMethod =
+              getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+          getValueMethodBuilder =
+              getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+          setValueMethod =
+              getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+        }
+      }
+
+      private EnumDescriptor enumDescriptor;
+
+      private Method valueOfMethod;
+      private Method getValueDescriptorMethod;
+
+      private boolean supportUnknownEnumValue;
+      private Method getValueMethod;
+      private Method getValueMethodBuilder;
+      private Method setValueMethod;
+
+      @Override
+      public Object get(final GeneratedMessage message) {
+        if (supportUnknownEnumValue) {
+          int value = (Integer) invokeOrDie(getValueMethod, message);
+          return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+        }
+        return invokeOrDie(getValueDescriptorMethod, super.get(message));
+      }
+
+      @Override
+      public Object get(final GeneratedMessage.Builder builder) {
+        if (supportUnknownEnumValue) {
+          int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
+          return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+        }
+        return invokeOrDie(getValueDescriptorMethod, super.get(builder));
+      }
+
+      @Override
+      public void set(final Builder builder, final Object value) {
+        if (supportUnknownEnumValue) {
+          invokeOrDie(setValueMethod, builder,
+              ((EnumValueDescriptor) value).getNumber());
+          return;
+        }
+        super.set(builder, invokeOrDie(valueOfMethod, null, value));
+      }
+    }
+
+    private static final class RepeatedEnumFieldAccessor
+        extends RepeatedFieldAccessor {
+      RepeatedEnumFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        super(descriptor, camelCaseName, messageClass, builderClass);
+
+        enumDescriptor = descriptor.getEnumType();
+
+        valueOfMethod = getMethodOrDie(type, "valueOf",
+                                       EnumValueDescriptor.class);
+        getValueDescriptorMethod =
+          getMethodOrDie(type, "getValueDescriptor");
+
+        supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+        if (supportUnknownEnumValue) {
+          getRepeatedValueMethod =
+              getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
+          getRepeatedValueMethodBuilder =
+              getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
+          setRepeatedValueMethod =
+              getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
+          addRepeatedValueMethod =
+              getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
+        }
+      }
+      private EnumDescriptor enumDescriptor;
+
+      private final Method valueOfMethod;
+      private final Method getValueDescriptorMethod;
+
+      private boolean supportUnknownEnumValue;
+      private Method getRepeatedValueMethod;
+      private Method getRepeatedValueMethodBuilder;
+      private Method setRepeatedValueMethod;
+      private Method addRepeatedValueMethod;
+
+      @Override
+      @SuppressWarnings("unchecked")
+      public Object get(final GeneratedMessage message) {
+        final List newList = new ArrayList();
+        final int size = getRepeatedCount(message);
+        for (int i = 0; i < size; i++) {
+          newList.add(getRepeated(message, i));
+        }
+        return Collections.unmodifiableList(newList);
+      }
+
+      @Override
+      @SuppressWarnings("unchecked")
+      public Object get(final GeneratedMessage.Builder builder) {
+        final List newList = new ArrayList();
+        final int size = getRepeatedCount(builder);
+        for (int i = 0; i < size; i++) {
+          newList.add(getRepeated(builder, i));
+        }
+        return Collections.unmodifiableList(newList);
+      }
+
+      @Override
+      public Object getRepeated(final GeneratedMessage message,
+                                final int index) {
+        if (supportUnknownEnumValue) {
+          int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
+          return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+        }
+        return invokeOrDie(getValueDescriptorMethod,
+          super.getRepeated(message, index));
+      }
+      @Override
+      public Object getRepeated(final GeneratedMessage.Builder builder,
+                                final int index) {
+        if (supportUnknownEnumValue) {
+          int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
+          return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+        }
+        return invokeOrDie(getValueDescriptorMethod,
+          super.getRepeated(builder, index));
+      }
+      @Override
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
+        if (supportUnknownEnumValue) {
+          invokeOrDie(setRepeatedValueMethod, builder, index,
+              ((EnumValueDescriptor) value).getNumber());
+          return;
+        }
+        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+                          value));
+      }
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
+        if (supportUnknownEnumValue) {
+          invokeOrDie(addRepeatedValueMethod, builder,
+              ((EnumValueDescriptor) value).getNumber());
+          return;
+        }
+        super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
+      }
+    }
+
+    // ---------------------------------------------------------------
+
+    /**
+     * Field accessor for string fields.
+     *
+     * <p>This class makes getFooBytes() and setFooBytes() available for
+     * reflection API so that reflection based serialize/parse functions can
+     * access the raw bytes of the field to preserve non-UTF8 bytes in the
+     * string.
+     *
+     * <p>This ensures the serialize/parse round-trip safety, which is important
+     * for servers which forward messages.
+     */
+    private static final class SingularStringFieldAccessor
+        extends SingularFieldAccessor {
+      SingularStringFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass,
+          final String containingOneofCamelCaseName) {
+        super(descriptor, camelCaseName, messageClass, builderClass,
+            containingOneofCamelCaseName);
+        getBytesMethod = getMethodOrDie(messageClass,
+            "get" + camelCaseName + "Bytes");
+        getBytesMethodBuilder = getMethodOrDie(builderClass,
+            "get" + camelCaseName + "Bytes");
+        setBytesMethodBuilder = getMethodOrDie(builderClass,
+            "set" + camelCaseName + "Bytes", ByteString.class);
+      }
+
+      private final Method getBytesMethod;
+      private final Method getBytesMethodBuilder;
+      private final Method setBytesMethodBuilder;
+
+      @Override
+      public Object getRaw(final GeneratedMessage message) {
+        return invokeOrDie(getBytesMethod, message);
+      }
+
+      @Override
+      public Object getRaw(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getBytesMethodBuilder, builder);
+      }
+
+      @Override
+      public void set(GeneratedMessage.Builder builder, Object value) {
+        if (value instanceof ByteString) {
+          invokeOrDie(setBytesMethodBuilder, builder, value);
+        } else {
+          super.set(builder, value);
+        }
+      }
+    }
+
+    // ---------------------------------------------------------------
+
+    private static final class SingularMessageFieldAccessor
+        extends SingularFieldAccessor {
+      SingularMessageFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass,
+          final String containingOneofCamelCaseName) {
+        super(descriptor, camelCaseName, messageClass, builderClass,
+            containingOneofCamelCaseName);
+
+        newBuilderMethod = getMethodOrDie(type, "newBuilder");
+        getBuilderMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+      }
+
+      private final Method newBuilderMethod;
+      private final Method getBuilderMethodBuilder;
+
+      private Object coerceType(final Object value) {
+        if (type.isInstance(value)) {
+          return value;
+        } else {
+          // The value is not the exact right message type.  However, if it
+          // is an alternative implementation of the same type -- e.g. a
+          // DynamicMessage -- we should accept it.  In this case we can make
+          // a copy of the message.
+          return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+                  .mergeFrom((Message) value).buildPartial();
+        }
+      }
+
+      @Override
+      public void set(final Builder builder, final Object value) {
+        super.set(builder, coerceType(value));
+      }
+      @Override
+      public Message.Builder newBuilder() {
+        return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+      }
+      @Override
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+      }
+    }
+
+    private static final class RepeatedMessageFieldAccessor
+        extends RepeatedFieldAccessor {
+      RepeatedMessageFieldAccessor(
+          final FieldDescriptor descriptor, final String camelCaseName,
+          final Class<? extends GeneratedMessage> messageClass,
+          final Class<? extends Builder> builderClass) {
+        super(descriptor, camelCaseName, messageClass, builderClass);
+
+        newBuilderMethod = getMethodOrDie(type, "newBuilder");
+        getBuilderMethodBuilder = getMethodOrDie(builderClass,
+            "get" + camelCaseName + "Builder", Integer.TYPE);
+      }
+
+      private final Method newBuilderMethod;
+      private final Method getBuilderMethodBuilder;
+
+      private Object coerceType(final Object value) {
+        if (type.isInstance(value)) {
+          return value;
+        } else {
+          // The value is not the exact right message type.  However, if it
+          // is an alternative implementation of the same type -- e.g. a
+          // DynamicMessage -- we should accept it.  In this case we can make
+          // a copy of the message.
+          return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+                  .mergeFrom((Message) value).build();
+        }
+      }
+
+      @Override
+      public void setRepeated(final Builder builder,
+                              final int index, final Object value) {
+        super.setRepeated(builder, index, coerceType(value));
+      }
+      @Override
+      public void addRepeated(final Builder builder, final Object value) {
+        super.addRepeated(builder, coerceType(value));
+      }
+      @Override
+      public Message.Builder newBuilder() {
+        return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+      }
+      @Override
+      public Message.Builder getRepeatedBuilder(
+          final GeneratedMessage.Builder builder, final int index) {
+        return (Message.Builder) invokeOrDie(
+            getBuilderMethodBuilder, builder, index);
+      }
+    }
+  }
+
+  /**
+   * Replaces this object in the output stream with a serialized form.
+   * Part of Java's serialization magic.  Generated sub-classes must override
+   * this method by calling {@code return super.writeReplace();}
+   * @return a SerializedForm of this message
+   */
+  protected Object writeReplace() throws ObjectStreamException {
+    return new GeneratedMessageLite.SerializedForm(this);
+  }
+
+  /**
+   * Checks that the {@link Extension} is non-Lite and returns it as a
+   * {@link GeneratedExtension}.
+   */
+  private static <MessageType extends ExtendableMessage<MessageType>, T>
+    Extension<MessageType, T> checkNotLite(
+        ExtensionLite<MessageType, T> extension) {
+    if (extension.isLite()) {
+      throw new IllegalArgumentException("Expected non-lite extension.");
+    }
+
+    return (Extension<MessageType, T>) extension;
+  }
+  
+  protected static int computeStringSize(final int fieldNumber, final Object value) {
+    if (value instanceof String) {
+      return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
+    } else {
+      return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
+    }
+  }
+  
+  protected static int computeStringSizeNoTag(final Object value) {
+    if (value instanceof String) {
+      return CodedOutputStream.computeStringSizeNoTag((String) value);
+    } else {
+      return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+    }
+  }
+  
+  protected static void writeString(
+      CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
+    if (value instanceof String) {
+      output.writeString(fieldNumber, (String) value);
+    } else {
+      output.writeBytes(fieldNumber, (ByteString) value);
+    }
+  }
+  
+  protected static void writeStringNoTag(
+      CodedOutputStream output, final Object value) throws IOException {
+    if (value instanceof String) {
+      output.writeStringNoTag((String) value);
+    } else {
+      output.writeBytesNoTag((ByteString) value);
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
new file mode 100644
index 0000000..c5adc5a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -0,0 +1,2242 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException;
+import com.google.protobuf.Internal.BooleanList;
+import com.google.protobuf.Internal.DoubleList;
+import com.google.protobuf.Internal.FloatList;
+import com.google.protobuf.Internal.IntList;
+import com.google.protobuf.Internal.LongList;
+import com.google.protobuf.Internal.ProtobufList;
+import com.google.protobuf.WireFormat.FieldType;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Lite version of {@link GeneratedMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageLite<
+    MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+    BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> 
+        extends AbstractMessageLite<MessageType, BuilderType> {
+
+  /** For use by generated code only. Lazily initialized to reduce allocations. */
+  protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+  
+  /** For use by generated code only.  */
+  protected int memoizedSerializedSize = -1;
+  
+  @Override
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final Parser<MessageType> getParserForType() {
+    return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
+  }
+
+  @Override
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final MessageType getDefaultInstanceForType() {
+    return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
+  }
+
+  @Override
+  @SuppressWarnings("unchecked") // Guaranteed by runtime.
+  public final BuilderType newBuilderForType() {
+    return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
+  }
+
+  /**
+   * A reflective toString function. This is primarily intended as a developer aid, while keeping
+   * binary size down. The first line of the {@code toString()} representation includes a commented
+   * version of {@code super.toString()} to act as an indicator that this should not be relied on
+   * for comparisons.
+   * <p>
+   * NOTE: This method relies on the field getter methods not being stripped or renamed by proguard.
+   * If they are, the fields will not be included in the returned string representation.
+   * <p>
+   * NOTE: This implementation is liable to change in the future, and should not be relied on in
+   * code.
+   */
+  @Override
+  public String toString() {
+    return MessageLiteToString.toString(this, super.toString());
+  }
+
+  @SuppressWarnings("unchecked") // Guaranteed by runtime
+  @Override
+  public int hashCode() {
+    if (memoizedHashCode == 0) {
+      HashCodeVisitor visitor = new HashCodeVisitor();
+      visit(visitor, (MessageType) this);
+      memoizedHashCode = visitor.hashCode;
+    }
+    return memoizedHashCode;
+  }
+  
+  @SuppressWarnings("unchecked") // Guaranteed by runtime
+  int hashCode(HashCodeVisitor visitor) {
+    if (memoizedHashCode == 0) {
+      int inProgressHashCode = visitor.hashCode;
+      visitor.hashCode = 0;
+      visit(visitor, (MessageType) this);
+      memoizedHashCode = visitor.hashCode;
+      visitor.hashCode = inProgressHashCode;
+    }
+    return memoizedHashCode;
+  }
+  
+  @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    
+    if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+      return false;
+    }
+    
+    try {
+      visit(EqualsVisitor.INSTANCE, (MessageType) other);
+    } catch (NotEqualsException e) {
+      return false;
+    }
+    return true;
+  }
+  
+  /**
+   * Same as {@link #equals(Object)} but throws {@code NotEqualsException}.
+   */
+  @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+  boolean equals(EqualsVisitor visitor, MessageLite other) {
+    if (this == other) {
+      return true;
+    }
+    
+    if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+      return false;
+    }
+
+    visit(visitor, (MessageType) other);
+    return true;
+  }
+  
+  // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
+  // mutable during the parsing constructor and immutable after. This allows us to avoid
+  // any unnecessary intermediary allocations while reducing the generated code size.
+
+  /**
+   * Lazily initializes unknown fields.
+   */
+  private final void ensureUnknownFieldsInitialized() {
+    if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+      unknownFields = UnknownFieldSetLite.newInstance();
+    }
+  }
+  
+  /**
+   * Called by subclasses to parse an unknown field. For use by generated code only.
+   * 
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOException {
+    // This will avoid the allocation of unknown fields when a group tag is encountered.
+    if (WireFormat.getTagWireType(tag) == WireFormat.WIRETYPE_END_GROUP) {
+      return false;
+    }
+    
+    ensureUnknownFieldsInitialized();
+    return unknownFields.mergeFieldFrom(tag, input);
+  }
+
+  /**
+   * Called by subclasses to parse an unknown field. For use by generated code only.
+   */
+  protected void mergeVarintField(int tag, int value) {
+    ensureUnknownFieldsInitialized();
+    unknownFields.mergeVarintField(tag, value);
+  }
+  
+  /**
+   * Called by subclasses to parse an unknown field. For use by generated code only.
+   */
+  protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) {
+    ensureUnknownFieldsInitialized();
+    unknownFields.mergeLengthDelimitedField(fieldNumber, value);
+  }
+  
+  /**
+   * Called by subclasses to complete parsing. For use by generated code only.
+   */
+  protected void makeImmutable() {
+    dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+
+    unknownFields.makeImmutable();
+  }
+
+  @Override
+  public final boolean isInitialized() {
+    return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
+  }
+
+  @Override
+  public final BuilderType toBuilder() {
+    BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
+    builder.mergeFrom((MessageType) this);
+    return builder;
+  }
+
+  /**
+   * Defines which method path to invoke in {@link GeneratedMessageLite
+   * #dynamicMethod(MethodToInvoke, Object...)}.
+   * <p>
+   * For use by generated code only.
+   */
+  public static enum MethodToInvoke {
+    // Rely on/modify instance state
+    IS_INITIALIZED,
+    VISIT,
+    MERGE_FROM_STREAM,
+    MAKE_IMMUTABLE,
+
+    // Rely on static state
+    NEW_MUTABLE_INSTANCE,
+    NEW_BUILDER,
+    GET_DEFAULT_INSTANCE,
+    GET_PARSER;
+  }
+
+  /**
+   * A method that implements different types of operations described in {@link MethodToInvoke}.
+   * Theses different kinds of operations are required to implement message-level operations for
+   * builders in the runtime. This method bundles those operations to reduce the generated methods
+   * count.
+   * <ul>
+   * <li>{@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and
+   * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the
+   * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the
+   * implementation wraps it in a RuntimeException.
+   * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been
+   * made immutable. See {@code MAKE_IMMUTABLE}.
+   * <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to
+   * memoize. It returns {@code null} for false and the default instance for true. We optionally
+   * memoize to support the Builder case, where memoization is not desired.
+   * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
+   * <li>{@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and
+   * recursively iterates through the fields side by side between this and the instance.
+   * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state.
+   * </ul>
+   * This method, plus the implementation of the Builder, enables the Builder class to be proguarded
+   * away entirely on Android.
+   * <p>
+   * For use by generated code only.
+   */
+  protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);
+
+  /**
+   * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+   */
+  protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
+    return dynamicMethod(method, arg0, null);
+  }
+
+  /**
+   * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+   */
+  protected Object dynamicMethod(MethodToInvoke method) {
+    return dynamicMethod(method, null, null);
+  }
+
+  void visit(Visitor visitor, MessageType other) {
+    dynamicMethod(MethodToInvoke.VISIT, visitor, other);
+    unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields);
+  }
+  
+  /**
+   * Merge some unknown fields into the {@link UnknownFieldSetLite} for this
+   * message.
+   *
+   * <p>For use by generated code only.
+   */
+  protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
+    this.unknownFields = UnknownFieldSetLite.mutableCopyOf(this.unknownFields, unknownFields);
+  }
+
+  @SuppressWarnings("unchecked")
+  public abstract static class Builder<
+      MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+      BuilderType extends Builder<MessageType, BuilderType>>
+          extends AbstractMessageLite.Builder<MessageType, BuilderType> {
+
+    private final MessageType defaultInstance;
+    protected MessageType instance;
+    protected boolean isBuilt;
+
+    protected Builder(MessageType defaultInstance) {
+      this.defaultInstance = defaultInstance;
+      this.instance =
+          (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+      isBuilt = false;
+    }
+
+    /**
+     * Called before any method that would mutate the builder to ensure that it correctly copies
+     * any state before the write happens to preserve immutability guarantees.
+     */
+    protected void copyOnWrite() {
+      if (isBuilt) {
+        MessageType newInstance =
+            (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+        newInstance.visit(MergeFromVisitor.INSTANCE, instance);
+        instance = newInstance;
+        isBuilt = false;
+      }
+    }
+
+    @Override
+    public final boolean isInitialized() {
+      return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */);
+    }
+
+    @Override
+    public final BuilderType clear() {
+      // No need to copy on write since we're dropping the instance anyways.
+      instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType clone() {
+      BuilderType builder =
+          (BuilderType) getDefaultInstanceForType().newBuilderForType();
+      builder.mergeFrom(buildPartial());
+      return builder;
+    }
+
+    @Override
+    public MessageType buildPartial() {
+      if (isBuilt) {
+        return instance;
+      }
+      
+      instance.makeImmutable();
+      
+      isBuilt = true;
+      return instance;
+    }
+
+    @Override
+    public final MessageType build() {
+      MessageType result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+    
+    @Override
+    protected BuilderType internalMergeFrom(MessageType message) {
+      return mergeFrom(message);
+    }
+    
+    /** All subclasses implement this. */
+    public BuilderType mergeFrom(MessageType message) {
+      copyOnWrite();
+      instance.visit(MergeFromVisitor.INSTANCE, message);
+      return (BuilderType) this;
+    }
+    
+    @Override
+    public MessageType getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+    
+    @Override
+    public BuilderType mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      copyOnWrite();
+      try {
+        instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+      } catch (RuntimeException e) {
+        if (e.getCause() instanceof IOException) {
+          throw (IOException) e.getCause();
+        }
+        throw e;
+      }
+      return (BuilderType) this;
+    }
+  }
+
+
+  // =================================================================
+  // Extensions-related stuff
+
+  /**
+   * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}.
+   */
+  public interface ExtendableMessageOrBuilder<
+      MessageType extends ExtendableMessage<MessageType, BuilderType>,
+      BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+          extends MessageLiteOrBuilder {
+
+    /** Check if a singular extension is present. */
+    <Type> boolean hasExtension(
+        ExtensionLite<MessageType, Type> extension);
+
+    /** Get the number of elements in a repeated extension. */
+    <Type> int getExtensionCount(
+        ExtensionLite<MessageType, List<Type>> extension);
+
+    /** Get the value of an extension. */
+    <Type> Type getExtension(ExtensionLite<MessageType, Type> extension);
+
+    /** Get one element of a repeated extension. */
+    <Type> Type getExtension(
+        ExtensionLite<MessageType, List<Type>> extension,
+        int index);
+  }
+
+  /**
+   * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
+   */
+  public abstract static class ExtendableMessage<
+        MessageType extends ExtendableMessage<MessageType, BuilderType>,
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+            extends GeneratedMessageLite<MessageType, BuilderType>
+            implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
+
+    /**
+     * Represents the set of extensions on this message. For use by generated
+     * code only.
+     */
+    protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet();
+
+    protected final void mergeExtensionFields(final MessageType other) {
+      if (extensions.isImmutable()) {
+        extensions = extensions.clone();
+      }
+      extensions.mergeFrom(((ExtendableMessage) other).extensions);
+    }
+
+    @Override
+    final void visit(Visitor visitor, MessageType other) {
+      super.visit(visitor, other);
+      extensions = visitor.visitExtensions(extensions, other.extensions);
+    }
+    
+    /**
+     * Parse an unknown field or an extension. For use by generated code only.
+     * 
+     * <p>For use by generated code only.
+     * 
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    protected <MessageType extends MessageLite> boolean parseUnknownField(
+        MessageType defaultInstance,
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      int wireType = WireFormat.getTagWireType(tag);
+      int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+      // TODO(dweis): How much bytecode would be saved by not requiring the generated code to
+      //     provide the default instance?
+      GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber(
+          defaultInstance, fieldNumber);
+
+      boolean unknown = false;
+      boolean packed = false;
+      if (extension == null) {
+        unknown = true;  // Unknown field.
+      } else if (wireType == FieldSet.getWireFormatForFieldType(
+                   extension.descriptor.getLiteType(),
+                   false  /* isPacked */)) {
+        packed = false;  // Normal, unpacked value.
+      } else if (extension.descriptor.isRepeated &&
+                 extension.descriptor.type.isPackable() &&
+                 wireType == FieldSet.getWireFormatForFieldType(
+                   extension.descriptor.getLiteType(),
+                   true  /* isPacked */)) {
+        packed = true;  // Packed value.
+      } else {
+        unknown = true;  // Wrong wire type.
+      }
+
+      if (unknown) {  // Unknown field or wrong wire type.  Skip.
+        return parseUnknownField(tag, input);
+      }
+
+      if (packed) {
+        int length = input.readRawVarint32();
+        int limit = input.pushLimit(length);
+        if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+          while (input.getBytesUntilLimit() > 0) {
+            int rawValue = input.readEnum();
+            Object value =
+                extension.descriptor.getEnumType().findValueByNumber(rawValue);
+            if (value == null) {
+              // If the number isn't recognized as a valid value for this
+              // enum, drop it (don't even add it to unknownFields).
+              return true;
+            }
+            extensions.addRepeatedField(extension.descriptor,
+                                        extension.singularToFieldSetType(value));
+          }
+        } else {
+          while (input.getBytesUntilLimit() > 0) {
+            Object value =
+                FieldSet.readPrimitiveField(input,
+                                            extension.descriptor.getLiteType(),
+                                            /*checkUtf8=*/ false);
+            extensions.addRepeatedField(extension.descriptor, value);
+          }
+        }
+        input.popLimit(limit);
+      } else {
+        Object value;
+        switch (extension.descriptor.getLiteJavaType()) {
+          case MESSAGE: {
+            MessageLite.Builder subBuilder = null;
+            if (!extension.descriptor.isRepeated()) {
+              MessageLite existingValue =
+                  (MessageLite) extensions.getField(extension.descriptor);
+              if (existingValue != null) {
+                subBuilder = existingValue.toBuilder();
+              }
+            }
+            if (subBuilder == null) {
+              subBuilder = extension.getMessageDefaultInstance()
+                  .newBuilderForType();
+            }
+            if (extension.descriptor.getLiteType() ==
+                WireFormat.FieldType.GROUP) {
+              input.readGroup(extension.getNumber(),
+                              subBuilder, extensionRegistry);
+            } else {
+              input.readMessage(subBuilder, extensionRegistry);
+            }
+            value = subBuilder.build();
+            break;
+          }
+          case ENUM:
+            int rawValue = input.readEnum();
+            value = extension.descriptor.getEnumType()
+                             .findValueByNumber(rawValue);
+            // If the number isn't recognized as a valid value for this enum,
+            // write it to unknown fields object.
+            if (value == null) {
+              mergeVarintField(fieldNumber, rawValue);
+              return true;
+            }
+            break;
+          default:
+            value = FieldSet.readPrimitiveField(input,
+                extension.descriptor.getLiteType(),
+                /*checkUtf8=*/ false);
+            break;
+        }
+
+        if (extension.descriptor.isRepeated()) {
+          extensions.addRepeatedField(extension.descriptor,
+                                      extension.singularToFieldSetType(value));
+        } else {
+          extensions.setField(extension.descriptor,
+                              extension.singularToFieldSetType(value));
+        }
+      }
+
+      return true;
+    }
+    
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
+      if (extension.getContainingTypeDefaultInstance() !=
+          getDefaultInstanceForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "This extension is for a different message type.  Please make " +
+          "sure that you are not suppressing any generics type warnings.");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
+      GeneratedExtension<MessageType, Type> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      return extensions.hasField(extensionLite.descriptor);
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    @Override
+    public final <Type> int getExtensionCount(
+        final ExtensionLite<MessageType, List<Type>> extension) {
+      GeneratedExtension<MessageType, List<Type>> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      return extensions.getRepeatedFieldCount(extensionLite.descriptor);
+    }
+
+    /** Get the value of an extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
+      GeneratedExtension<MessageType, Type> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      final Object value = extensions.getField(extensionLite.descriptor);
+      if (value == null) {
+        return extensionLite.defaultValue;
+      } else {
+        return (Type) extensionLite.fromFieldSetType(value);
+      }
+    }
+
+    /** Get one element of a repeated extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
+      GeneratedExtension<MessageType, List<Type>> extensionLite =
+          checkIsLite(extension);
+
+      verifyExtensionContainingType(extensionLite);
+      return (Type) extensionLite.singularFromFieldSetType(
+          extensions.getRepeatedField(extensionLite.descriptor, index));
+    }
+
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
+    @Override
+    protected final void makeImmutable() {
+      super.makeImmutable();
+      
+      extensions.makeImmutable();
+    }
+
+    /**
+     * Used by subclasses to serialize extensions.  Extension ranges may be
+     * interleaved with field numbers, but we must write them in canonical
+     * (sorted by field number) order.  ExtensionWriter helps us write
+     * individual ranges of extensions at once.
+     */
+    protected class ExtensionWriter {
+      // Imagine how much simpler this code would be if Java iterators had
+      // a way to get the next element without advancing the iterator.
+
+      private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
+            extensions.iterator();
+      private Map.Entry<ExtensionDescriptor, Object> next;
+      private final boolean messageSetWireFormat;
+
+      private ExtensionWriter(boolean messageSetWireFormat) {
+        if (iter.hasNext()) {
+          next = iter.next();
+        }
+        this.messageSetWireFormat = messageSetWireFormat;
+      }
+
+      public void writeUntil(final int end, final CodedOutputStream output)
+                             throws IOException {
+        while (next != null && next.getKey().getNumber() < end) {
+          ExtensionDescriptor extension = next.getKey();
+          if (messageSetWireFormat && extension.getLiteJavaType() ==
+                  WireFormat.JavaType.MESSAGE &&
+              !extension.isRepeated()) {
+            output.writeMessageSetExtension(extension.getNumber(),
+                                            (MessageLite) next.getValue());
+          } else {
+            FieldSet.writeField(extension, next.getValue(), output);
+          }
+          if (iter.hasNext()) {
+            next = iter.next();
+          } else {
+            next = null;
+          }
+        }
+      }
+    }
+
+    protected ExtensionWriter newExtensionWriter() {
+      return new ExtensionWriter(false);
+    }
+    protected ExtensionWriter newMessageSetExtensionWriter() {
+      return new ExtensionWriter(true);
+    }
+
+    /** Called by subclasses to compute the size of extensions. */
+    protected int extensionsSerializedSize() {
+      return extensions.getSerializedSize();
+    }
+    protected int extensionsSerializedSizeAsMessageSet() {
+      return extensions.getMessageSetSerializedSize();
+    }
+  }
+
+  /**
+   * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
+   */
+  @SuppressWarnings("unchecked")
+  public abstract static class ExtendableBuilder<
+        MessageType extends ExtendableMessage<MessageType, BuilderType>,
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+      extends Builder<MessageType, BuilderType>
+      implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
+    protected ExtendableBuilder(MessageType defaultInstance) {
+      super(defaultInstance);
+      
+      // TODO(dweis): This is kind of an unnecessary clone since we construct a
+      //     new instance in the parent constructor which makes the extensions
+      //     immutable. This extra allocation shouldn't matter in practice
+      //     though.
+      instance.extensions = instance.extensions.clone();
+    }
+
+    // For immutable message conversion.
+    void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
+      copyOnWrite();
+      instance.extensions = extensions;
+    }
+
+    @Override
+    protected void copyOnWrite() {
+      if (!isBuilt) {
+        return;
+      }
+      
+      super.copyOnWrite();
+      instance.extensions = instance.extensions.clone();
+    }
+
+    @Override
+    public final MessageType buildPartial() {
+      if (isBuilt) {
+        return instance;
+      }
+
+      instance.extensions.makeImmutable();
+      return super.buildPartial();
+    }
+
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
+      if (extension.getContainingTypeDefaultInstance() !=
+          getDefaultInstanceForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "This extension is for a different message type.  Please make " +
+          "sure that you are not suppressing any generics type warnings.");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
+      return instance.hasExtension(extension);
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    @Override
+    public final <Type> int getExtensionCount(
+        final ExtensionLite<MessageType, List<Type>> extension) {
+      return instance.getExtensionCount(extension);
+    }
+
+    /** Get the value of an extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
+      return instance.getExtension(extension);
+    }
+
+    /** Get one element of a repeated extension. */
+    @Override
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
+      return instance.getExtension(extension, index);
+    }
+
+    // This is implemented here only to work around an apparent bug in the
+    // Java compiler and/or build system.  See bug #1898463.  The mere presence
+    // of this dummy clone() implementation makes it go away.
+    @Override
+    public BuilderType clone() {
+      return super.clone();
+    }
+    
+    /** Set the value of an extension. */
+    public final <Type> BuilderType setExtension(
+        final ExtensionLite<MessageType, Type> extension,
+        final Type value) {
+      GeneratedExtension<MessageType, Type> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      copyOnWrite();
+      instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
+      return (BuilderType) this;
+    }
+
+    /** Set the value of one element of a repeated extension. */
+    public final <Type> BuilderType setExtension(
+        final ExtensionLite<MessageType, List<Type>> extension,
+        final int index, final Type value) {
+      GeneratedExtension<MessageType, List<Type>> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      copyOnWrite();
+      instance.extensions.setRepeatedField(
+          extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
+      return (BuilderType) this;
+    }
+
+    /** Append a value to a repeated extension. */
+    public final <Type> BuilderType addExtension(
+        final ExtensionLite<MessageType, List<Type>> extension,
+        final Type value) {
+      GeneratedExtension<MessageType, List<Type>> extensionLite =
+          checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      copyOnWrite();
+      instance.extensions.addRepeatedField(
+          extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
+      return (BuilderType) this;
+    }
+
+    /** Clear an extension. */
+    public final <Type> BuilderType clearExtension(
+        final ExtensionLite<MessageType, ?> extension) {
+      GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension);
+      
+      verifyExtensionContainingType(extensionLite);
+      copyOnWrite();
+      instance.extensions.clearField(extensionLite.descriptor);
+      return (BuilderType) this;
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  /** For use by generated code only. */
+  public static <ContainingType extends MessageLite, Type>
+      GeneratedExtension<ContainingType, Type>
+          newSingularGeneratedExtension(
+              final ContainingType containingTypeDefaultInstance,
+              final Type defaultValue,
+              final MessageLite messageDefaultInstance,
+              final Internal.EnumLiteMap<?> enumTypeMap,
+              final int number,
+              final WireFormat.FieldType type,
+              final Class singularType) {
+    return new GeneratedExtension<ContainingType, Type>(
+        containingTypeDefaultInstance,
+        defaultValue,
+        messageDefaultInstance,
+        new ExtensionDescriptor(enumTypeMap, number, type,
+                                false /* isRepeated */,
+                                false /* isPacked */),
+        singularType);
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends MessageLite, Type>
+      GeneratedExtension<ContainingType, Type>
+          newRepeatedGeneratedExtension(
+              final ContainingType containingTypeDefaultInstance,
+              final MessageLite messageDefaultInstance,
+              final Internal.EnumLiteMap<?> enumTypeMap,
+              final int number,
+              final WireFormat.FieldType type,
+              final boolean isPacked,
+              final Class singularType) {
+    @SuppressWarnings("unchecked")  // Subclasses ensure Type is a List
+    Type emptyList = (Type) Collections.emptyList();
+    return new GeneratedExtension<ContainingType, Type>(
+        containingTypeDefaultInstance,
+        emptyList,
+        messageDefaultInstance,
+        new ExtensionDescriptor(
+            enumTypeMap, number, type, true /* isRepeated */, isPacked),
+        singularType);
+  }
+
+  static final class ExtensionDescriptor
+      implements FieldSet.FieldDescriptorLite<
+        ExtensionDescriptor> {
+    ExtensionDescriptor(
+        final Internal.EnumLiteMap<?> enumTypeMap,
+        final int number,
+        final WireFormat.FieldType type,
+        final boolean isRepeated,
+        final boolean isPacked) {
+      this.enumTypeMap = enumTypeMap;
+      this.number = number;
+      this.type = type;
+      this.isRepeated = isRepeated;
+      this.isPacked = isPacked;
+    }
+
+    final Internal.EnumLiteMap<?> enumTypeMap;
+    final int number;
+    final WireFormat.FieldType type;
+    final boolean isRepeated;
+    final boolean isPacked;
+
+    @Override
+    public int getNumber() {
+      return number;
+    }
+
+    @Override
+    public WireFormat.FieldType getLiteType() {
+      return type;
+    }
+
+    @Override
+    public WireFormat.JavaType getLiteJavaType() {
+      return type.getJavaType();
+    }
+
+    @Override
+    public boolean isRepeated() {
+      return isRepeated;
+    }
+
+    @Override
+    public boolean isPacked() {
+      return isPacked;
+    }
+
+    @Override
+    public Internal.EnumLiteMap<?> getEnumType() {
+      return enumTypeMap;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
+      return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
+    }
+
+
+    @Override
+    public int compareTo(ExtensionDescriptor other) {
+      return number - other.number;
+    }
+  }
+
+  // =================================================================
+
+  /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+  @SuppressWarnings("unchecked")
+  static Method getMethodOrDie(Class clazz, String name, Class... params) {
+    try {
+      return clazz.getMethod(name, params);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(
+        "Generated message class \"" + clazz.getName() +
+        "\" missing method \"" + name + "\".", e);
+    }
+  }
+
+  /** Calls invoke and throws a RuntimeException if it fails. */
+  static Object invokeOrDie(Method method, Object object, Object... params) {
+    try {
+      return method.invoke(object, params);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(
+        "Couldn't use Java reflection to implement protocol message " +
+        "reflection.", e);
+    } catch (InvocationTargetException e) {
+      final Throwable cause = e.getCause();
+      if (cause instanceof RuntimeException) {
+        throw (RuntimeException) cause;
+      } else if (cause instanceof Error) {
+        throw (Error) cause;
+      } else {
+        throw new RuntimeException(
+          "Unexpected exception thrown by generated accessor method.", cause);
+      }
+    }
+  }
+
+  /**
+   * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
+   *
+   * Users should ignore the contents of this class and only use objects of
+   * this type as parameters to extension accessors and ExtensionRegistry.add().
+   */
+  public static class GeneratedExtension<
+      ContainingType extends MessageLite, Type>
+          extends ExtensionLite<ContainingType, Type> {
+
+    /**
+     * Create a new instance with the given parameters.
+     *
+     * The last parameter {@code singularType} is only needed for enum types.
+     * We store integer values for enum types in a {@link ExtendableMessage}
+     * and use Java reflection to convert an integer value back into a concrete
+     * enum object.
+     */
+    GeneratedExtension(
+        final ContainingType containingTypeDefaultInstance,
+        final Type defaultValue,
+        final MessageLite messageDefaultInstance,
+        final ExtensionDescriptor descriptor,
+        final Class singularType) {
+      // Defensive checks to verify the correct initialization order of
+      // GeneratedExtensions and their related GeneratedMessages.
+      if (containingTypeDefaultInstance == null) {
+        throw new IllegalArgumentException(
+            "Null containingTypeDefaultInstance");
+      }
+      if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE &&
+          messageDefaultInstance == null) {
+        throw new IllegalArgumentException(
+            "Null messageDefaultInstance");
+      }
+      this.containingTypeDefaultInstance = containingTypeDefaultInstance;
+      this.defaultValue = defaultValue;
+      this.messageDefaultInstance = messageDefaultInstance;
+      this.descriptor = descriptor;
+    }
+
+    final ContainingType containingTypeDefaultInstance;
+    final Type defaultValue;
+    final MessageLite messageDefaultInstance;
+    final ExtensionDescriptor descriptor;
+
+    /**
+     * Default instance of the type being extended, used to identify that type.
+     */
+    public ContainingType getContainingTypeDefaultInstance() {
+      return containingTypeDefaultInstance;
+    }
+
+    /** Get the field number. */
+    @Override
+    public int getNumber() {
+      return descriptor.getNumber();
+    }
+
+
+    /**
+     * If the extension is an embedded message or group, returns the default
+     * instance of the message.
+     */
+    @Override
+    public MessageLite getMessageDefaultInstance() {
+      return messageDefaultInstance;
+    }
+
+    @SuppressWarnings("unchecked")
+    Object fromFieldSetType(final Object value) {
+      if (descriptor.isRepeated()) {
+        if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
+            result.add(singularFromFieldSetType(element));
+          }
+          return result;
+        } else {
+          return value;
+        }
+      } else {
+        return singularFromFieldSetType(value);
+      }
+    }
+
+    Object singularFromFieldSetType(final Object value) {
+      if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+        return descriptor.enumTypeMap.findValueByNumber((Integer) value);
+      } else {
+        return value;
+      }
+    }
+
+    @SuppressWarnings("unchecked")
+    Object toFieldSetType(final Object value) {
+      if (descriptor.isRepeated()) {
+        if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+          final List result = new ArrayList();
+          for (final Object element : (List) value) {
+            result.add(singularToFieldSetType(element));
+          }
+          return result;
+        } else {
+          return value;
+        }
+      } else {
+        return singularToFieldSetType(value);
+      }
+    }
+
+    Object singularToFieldSetType(final Object value) {
+      if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+        return ((Internal.EnumLite) value).getNumber();
+      } else {
+        return value;
+      }
+    }
+
+    @Override
+    public FieldType getLiteType() {
+      return descriptor.getLiteType();
+    }
+
+    @Override
+    public boolean isRepeated() {
+      return descriptor.isRepeated;
+    }
+
+    @Override
+    public Type getDefaultValue() {
+      return defaultValue;
+    }
+  }
+
+  /**
+   * A serialized (serializable) form of the generated message.  Stores the
+   * message as a class name and a byte array.
+   */
+  protected static final class SerializedForm implements Serializable {
+
+    public static SerializedForm of(MessageLite message) {
+      return new SerializedForm(message);
+    }
+    
+    private static final long serialVersionUID = 0L;
+
+    private final String messageClassName;
+    private final byte[] asBytes;
+
+    /**
+     * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}.
+     * @param regularForm the message to serialize
+     */
+    SerializedForm(MessageLite regularForm) {
+      messageClassName = regularForm.getClass().getName();
+      asBytes = regularForm.toByteArray();
+    }
+
+    /**
+     * When read from an ObjectInputStream, this method converts this object
+     * back to the regular form.  Part of Java's serialization magic.
+     * @return a GeneratedMessage of the type that was serialized
+     */
+    @SuppressWarnings("unchecked")
+    protected Object readResolve() throws ObjectStreamException {
+      try {
+        Class<?> messageClass = Class.forName(messageClassName);
+        java.lang.reflect.Field defaultInstanceField =
+            messageClass.getDeclaredField("DEFAULT_INSTANCE");
+        defaultInstanceField.setAccessible(true);
+        MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
+        return defaultInstance.newBuilderForType()
+            .mergeFrom(asBytes)
+            .buildPartial();
+      } catch (ClassNotFoundException e) {
+        throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
+      } catch (NoSuchFieldException e) {
+        throw new RuntimeException("Unable to find DEFAULT_INSTANCE in " + messageClassName, e);
+      } catch (SecurityException e) {
+        throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException("Unable to call parsePartialFrom", e);
+      } catch (InvalidProtocolBufferException e) {
+        throw new RuntimeException("Unable to understand proto buffer", e);
+      }
+    }
+  }
+  
+  /**
+   * Checks that the {@link Extension} is Lite and returns it as a
+   * {@link GeneratedExtension}.
+   */
+  private static <
+      MessageType extends ExtendableMessage<MessageType, BuilderType>,
+      BuilderType extends ExtendableBuilder<MessageType, BuilderType>,
+      T>
+    GeneratedExtension<MessageType, T> checkIsLite(
+        ExtensionLite<MessageType, T> extension) {
+    if (!extension.isLite()) {
+      throw new IllegalArgumentException("Expected a lite extension.");
+    }
+    
+    return (GeneratedExtension<MessageType, T>) extension;
+  }
+
+  /**
+   * A static helper method for checking if a message is initialized, optionally memoizing.
+   * <p>
+   * For use by generated code only.
+   */
+  protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
+      T message, boolean shouldMemoize) {
+    return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null;
+  } 
+  
+  protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
+    message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+  }
+
+  protected static IntList emptyIntList() {
+    return IntArrayList.emptyList();
+  }
+
+  protected static IntList mutableCopy(IntList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  protected static LongList emptyLongList() {
+    return LongArrayList.emptyList();
+  }
+  
+  protected static LongList mutableCopy(LongList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  protected static FloatList emptyFloatList() {
+    return FloatArrayList.emptyList();
+  }
+  
+  protected static FloatList mutableCopy(FloatList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  protected static DoubleList emptyDoubleList() {
+    return DoubleArrayList.emptyList();
+  }
+  
+  protected static DoubleList mutableCopy(DoubleList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  protected static BooleanList emptyBooleanList() {
+    return BooleanArrayList.emptyList();
+  }
+  
+  protected static BooleanList mutableCopy(BooleanList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  protected static <E> ProtobufList<E> emptyProtobufList() {
+    return ProtobufArrayList.emptyList();
+  }
+  
+  protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
+  /**
+   * A {@link Parser} implementation that delegates to the default instance.
+   * <p>
+   * For use by generated code only.
+   */
+  protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>>
+      extends AbstractParser<T> {
+    
+    private T defaultInstance;
+    
+    public DefaultInstanceBasedParser(T defaultInstance) {
+      this.defaultInstance = defaultInstance;
+    }
+    
+    @Override
+    public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry);
+    }
+  }
+  
+  /**
+   * A static helper method for parsing a partial from input using the extension registry and the
+   * instance.
+   */
+  // TODO(dweis): Should this verify that the last tag was 0?
+  static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+      T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+          throws InvalidProtocolBufferException {
+    @SuppressWarnings("unchecked") // Guaranteed by protoc
+    T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+    try {
+      result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+      result.makeImmutable();
+    } catch (RuntimeException e) {
+      if (e.getCause() instanceof InvalidProtocolBufferException) {
+        throw (InvalidProtocolBufferException) e.getCause();
+      }
+      throw e;
+    }
+    return result;
+  }
+  
+  protected static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+      T defaultInstance,
+      CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
+  }
+  
+  /**
+   * Helper method to check if message is initialized.
+   *
+   * @throws InvalidProtocolBufferException if it is not initialized.
+   * @return The message to check.
+   */
+  private static <T extends GeneratedMessageLite<T, ?>> T checkMessageInitialized(T message)
+      throws InvalidProtocolBufferException {
+    if (message != null && !message.isInitialized()) {
+      throw message.newUninitializedMessageException()
+          .asInvalidProtocolBufferException()
+          .setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, ByteString data)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parseFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
+  }
+  
+  // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
+  // ByteString.
+  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+      T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    T message;
+    try {
+      CodedInputStream input = data.newCodedInput();
+      message = parsePartialFrom(defaultInstance, input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+  
+  // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
+  // ByteString.
+  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+      T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    T message;
+    try {
+      CodedInputStream input = CodedInputStream.newInstance(data);
+      message = parsePartialFrom(defaultInstance, input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, byte[] data)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
+  }
+
+  // Does not validate last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, InputStream input)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input),
+            ExtensionRegistryLite.getEmptyRegistry()));
+  }
+
+  // Does not validate last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input), extensionRegistry));
+  }
+
+  // Does not validate last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parseFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
+  }
+
+  // Does not validate last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+      T defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, input, extensionRegistry));
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
+      T defaultInstance, InputStream input)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialDelimitedFrom(defaultInstance, input,
+            ExtensionRegistryLite.getEmptyRegistry()));
+  }
+
+  // Validates last tag.
+  protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
+      T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialDelimitedFrom(defaultInstance, input, extensionRegistry));
+  }
+  
+  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialDelimitedFrom(
+      T defaultInstance,
+      InputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    int size;
+    try {
+      int firstByte = input.read();
+      if (firstByte == -1) {
+        return null;
+      }
+      size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (IOException e) {
+      throw new InvalidProtocolBufferException(e.getMessage());
+    }
+    InputStream limitedInput = new LimitedInputStream(input, size);
+    CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
+    T message = parsePartialFrom(defaultInstance, codedInput, extensionRegistry);
+    try {
+      codedInput.checkLastTagWas(0);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  /**
+   * An abstract visitor that the generated code calls into that we use to implement various
+   * features. Fields that are not members of oneofs are always visited. Members of a oneof are only
+   * visited when they are the set oneof case value on the "other" proto. The visitOneofNotSet
+   * method is invoked if other's oneof case is not set.
+   */
+  protected interface Visitor {
+    boolean visitBoolean(boolean minePresent, boolean mine, boolean otherPresent, boolean other);
+    int visitInt(boolean minePresent, int mine, boolean otherPresent, int other);
+    double visitDouble(boolean minePresent, double mine, boolean otherPresent, double other);
+    float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other);
+    long visitLong(boolean minePresent, long mine, boolean otherPresent, long other);
+    String visitString(boolean minePresent, String mine, boolean otherPresent, String other);
+    ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other);
+
+    Object visitOneofBoolean(boolean minePresent, Object mine, Object other);
+    Object visitOneofInt(boolean minePresent, Object mine, Object other);
+    Object visitOneofDouble(boolean minePresent, Object mine, Object other);
+    Object visitOneofFloat(boolean minePresent, Object mine, Object other);
+    Object visitOneofLong(boolean minePresent, Object mine, Object other);
+    Object visitOneofString(boolean minePresent, Object mine, Object other);
+    Object visitOneofByteString(boolean minePresent, Object mine, Object other);
+    Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
+    Object visitOneofMessage(boolean minePresent, Object mine, Object other);
+    void visitOneofNotSet(boolean minePresent);
+    
+    /**
+     * Message fields use null sentinals.
+     */
+    <T extends MessageLite> T visitMessage(T mine, T other);
+    LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other);
+
+    <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
+    BooleanList visitBooleanList(BooleanList mine, BooleanList other);
+    IntList visitIntList(IntList mine, IntList other);
+    DoubleList visitDoubleList(DoubleList mine, DoubleList other);
+    FloatList visitFloatList(FloatList mine, FloatList other);
+    LongList visitLongList(LongList mine, LongList other);
+    FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine, FieldSet<ExtensionDescriptor> other);
+    UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other);
+    <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other);
+  }
+
+  /**
+   * Implements equals. Throws a {@link NotEqualsException} when not equal.
+   */
+  static class EqualsVisitor implements Visitor {
+
+    static final class NotEqualsException extends RuntimeException {}
+
+    static final EqualsVisitor INSTANCE = new EqualsVisitor();
+
+    static final NotEqualsException NOT_EQUALS = new NotEqualsException();
+
+    private EqualsVisitor() {}
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      if (minePresent != otherPresent || !mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      if (minePresent != otherPresent || !mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+    
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      if (minePresent) {
+        throw NOT_EQUALS;
+      }
+    }
+
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      if (mine == null && other == null) {
+        return null;
+      }
+
+      if (mine == null || other == null) {
+        throw NOT_EQUALS;
+      }
+
+      ((GeneratedMessageLite<?, ?>) mine).equals(this, other);
+
+      return mine;
+    }
+    
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      if (!minePresent && !otherPresent) {
+        return mine;
+      } else if (minePresent && otherPresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+  }
+
+  /**
+   * Implements hashCode by accumulating state.
+   */
+  private static class HashCodeVisitor implements Visitor {
+
+    // The caller must ensure that the visitor is invoked parameterized with this and this such that
+    // other is this. This is required due to how oneof cases are handled. See the class comment
+    // on Visitor for more information.
+    
+    private int hashCode = 0;
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      hashCode = (53 * hashCode) + Internal.hashBoolean(mine);
+      return mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      hashCode = (53 * hashCode) + mine;
+      return mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits(mine));
+      return mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      hashCode = (53 * hashCode) + Float.floatToIntBits(mine);
+      return mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(mine);
+      return mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashBoolean(((Boolean) mine));
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + (Integer) mine;
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits((Double) mine));
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Float.floatToIntBits((Float) mine);
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashLong((Long) mine);
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      return visitMessage((MessageLite) mine, (MessageLite) other);
+    }
+
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      if (minePresent) {
+        throw new IllegalStateException(); // Can't happen if other == this. 
+      }
+    }
+
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      final int protoHash;
+      if (mine != null) {
+        if (mine instanceof GeneratedMessageLite) {
+          protoHash = ((GeneratedMessageLite) mine).hashCode(this);
+        } else {
+          protoHash = mine.hashCode();
+        }
+      } else {
+        protoHash = 37;
+      }
+      hashCode = (53 * hashCode) + protoHash;
+      return mine;
+    }
+
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+    
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+  }
+
+  /**
+   * Implements field merging semantics over the visitor interface.
+   */
+  protected static class MergeFromVisitor implements Visitor {
+
+    public static final MergeFromVisitor INSTANCE = new MergeFromVisitor();
+
+    private MergeFromVisitor() {}
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent) {
+        LazyFieldLite lazy = (LazyFieldLite) mine;
+        lazy.merge((LazyFieldLite) other);
+        return lazy;
+      }
+      return other;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent) {
+        return visitMessage((MessageLite) mine, (MessageLite) other);
+      }
+      return other;
+    }
+    
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      return;
+    }
+
+    @SuppressWarnings("unchecked") // Guaranteed by runtime.
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      if (mine != null && other != null) {
+        return (T) mine.toBuilder().mergeFrom(other).build();
+      }
+
+      return mine != null ? mine : other;
+    }
+
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      // LazyFieldLite's are never null so we can just copy across. Necessary to avoid leakage
+      // from builder into immutable message.
+      // TODO(dweis): Change to null sentinels?
+      mine.merge(other);
+      return mine;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      if (mine.isImmutable()) {
+        mine = mine.clone();
+      }
+      mine.mergeFrom(other);
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      return other == UnknownFieldSetLite.getDefaultInstance()
+          ? mine : UnknownFieldSetLite.mutableCopyOf(mine, other);
+    }
+    
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      mine.mergeFrom(other);
+      return mine;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/IntArrayList.java
new file mode 100644
index 0000000..6d6ece5
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -0,0 +1,269 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.IntList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link IntList} on top of a primitive array.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess {
+  
+  private static final IntArrayList EMPTY_LIST = new IntArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  public static IntArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+  
+  /**
+   * The backing store for the list.
+   */
+  private int[] array;
+  
+  /**
+   * The size of the list distinct from the length of the array. That is, it is the number of
+   * elements set in the list.
+   */
+  private int size;
+
+  /**
+   * Constructs a new mutable {@code IntArrayList} with default capacity.
+   */
+  IntArrayList() {
+    this(new int[DEFAULT_CAPACITY], 0);
+  }
+
+  /**
+   * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}.
+   */
+  private IntArrayList(int[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof IntArrayList)) {
+      return super.equals(o);
+    }
+    IntArrayList other = (IntArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final int[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + array[i];
+    }
+    return result;
+  }
+
+  @Override
+  public IntList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new IntArrayList(Arrays.copyOf(array, capacity), size);
+  }
+  
+  @Override
+  public Integer get(int index) {
+    return getInt(index);
+  }
+
+  @Override
+  public int getInt(int index) {
+    ensureIndexInRange(index);
+    return array[index];
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Integer set(int index, Integer element) {
+    return setInt(index, element);
+  }
+
+  @Override
+  public int setInt(int index, int element) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    int previousValue = array[index];
+    array[index] = element;
+    return previousValue;
+  }
+
+  @Override
+  public void add(int index, Integer element) {
+    addInt(index, element);
+  }
+
+  /**
+   * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+   */
+  @Override
+  public void addInt(int element) {
+    addInt(size, element);
+  }
+
+  /**
+   * Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element.
+   */
+  private void addInt(int index, int element) {
+    ensureIsMutable();
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+    
+    if (size < array.length) {
+      // Shift everything over to make room
+      System.arraycopy(array, index, array, index + 1, size - index);
+    } else {
+      // Resize to 1.5x the size
+      int length = ((size * 3) / 2) + 1;
+      int[] newArray = new int[length];
+      
+      // Copy the first part directly
+      System.arraycopy(array, 0, newArray, 0, index);
+      
+      // Copy the rest shifted over by one to make room
+      System.arraycopy(array, index, newArray, index + 1, size - index);
+      array = newArray;
+    }
+
+    array[index] = element;
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends Integer> collection) {
+    ensureIsMutable();
+    
+    if (collection == null) {
+      throw new NullPointerException();
+    }
+    
+    // We specialize when adding another IntArrayList to avoid boxing elements.
+    if (!(collection instanceof IntArrayList)) {
+      return super.addAll(collection);
+    }
+    
+    IntArrayList list = (IntArrayList) collection;
+    if (list.size == 0) {
+      return false;
+    }
+    
+    int overflow = Integer.MAX_VALUE - size;
+    if (overflow < list.size) {
+      // We can't actually represent a list this large.
+      throw new OutOfMemoryError();
+    }
+    
+    int newSize = size + list.size;
+    if (newSize > array.length) {
+      array = Arrays.copyOf(array, newSize);
+    }
+    
+    System.arraycopy(list.array, 0, array, size, list.size);
+    size = newSize;
+    modCount++;
+    return true;
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    for (int i = 0; i < size; i++) {
+      if (o.equals(array[i])) {
+        System.arraycopy(array, i + 1, array, i, size - i);
+        size--;
+        modCount++;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Integer remove(int index) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    int value = array[index];
+    System.arraycopy(array, index + 1, array, index, size - index);
+    size--;
+    modCount++;
+    return value;
+  }
+
+  /**
+   * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+   * {@link IndexOutOfBoundsException} if it is not.
+   * 
+   * @param index the index to verify is in range
+   */
+  private void ensureIndexInRange(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+  }
+
+  private String makeOutOfBoundsExceptionMessage(int index) {
+    return "Index:" + index + ", Size:" + size;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Internal.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Internal.java
new file mode 100644
index 0000000..d1de375
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -0,0 +1,741 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.AbstractList;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.Set;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public final class Internal {
+
+  private Internal() {}
+
+  static final Charset UTF_8 = Charset.forName("UTF-8");
+  static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+  /**
+   * Helper called by generated code to construct default values for string
+   * fields.
+   * <p>
+   * The protocol compiler does not actually contain a UTF-8 decoder -- it
+   * just pushes UTF-8-encoded text around without touching it.  The one place
+   * where this presents a problem is when generating Java string literals.
+   * Unicode characters in the string literal would normally need to be encoded
+   * using a Unicode escape sequence, which would require decoding them.
+   * To get around this, protoc instead embeds the UTF-8 bytes into the
+   * generated code and leaves it to the runtime library to decode them.
+   * <p>
+   * It gets worse, though.  If protoc just generated a byte array, like:
+   *   new byte[] {0x12, 0x34, 0x56, 0x78}
+   * Java actually generates *code* which allocates an array and then fills
+   * in each value.  This is much less efficient than just embedding the bytes
+   * directly into the bytecode.  To get around this, we need another
+   * work-around.  String literals are embedded directly, so protoc actually
+   * generates a string literal corresponding to the bytes.  The easiest way
+   * to do this is to use the ISO-8859-1 character set, which corresponds to
+   * the first 256 characters of the Unicode range.  Protoc can then use
+   * good old CEscape to generate the string.
+   * <p>
+   * So we have a string literal which represents a set of bytes which
+   * represents another string.  This function -- stringDefaultValue --
+   * converts from the generated string to the string we actually want.  The
+   * generated code calls this automatically.
+   */
+  public static String stringDefaultValue(String bytes) {
+    return new String(bytes.getBytes(ISO_8859_1), UTF_8);
+  }
+
+  /**
+   * Helper called by generated code to construct default values for bytes
+   * fields.
+   * <p>
+   * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+   * In this case we only need the second of the two hacks -- allowing us to
+   * embed raw bytes as a string literal with ISO-8859-1 encoding.
+   */
+  public static ByteString bytesDefaultValue(String bytes) {
+    return ByteString.copyFrom(bytes.getBytes(ISO_8859_1));
+  }
+  /**
+   * Helper called by generated code to construct default values for bytes
+   * fields.
+   * <p>
+   * This is like {@link #bytesDefaultValue}, but returns a byte array.
+   */
+  public static byte[] byteArrayDefaultValue(String bytes) {
+    return bytes.getBytes(ISO_8859_1);
+  }
+
+  /**
+   * Helper called by generated code to construct default values for bytes
+   * fields.
+   * <p>
+   * This is like {@link #bytesDefaultValue}, but returns a ByteBuffer.
+   */
+  public static ByteBuffer byteBufferDefaultValue(String bytes) {
+    return ByteBuffer.wrap(byteArrayDefaultValue(bytes));
+  }
+
+  /**
+   * Create a new ByteBuffer and copy all the content of {@code source}
+   * ByteBuffer to the new ByteBuffer. The new ByteBuffer's limit and
+   * capacity will be source.capacity(), and its position will be 0.
+   * Note that the state of {@code source} ByteBuffer won't be changed.
+   */
+  public static ByteBuffer copyByteBuffer(ByteBuffer source) {
+    // Make a duplicate of the source ByteBuffer and read data from the
+    // duplicate. This is to avoid affecting the source ByteBuffer's state.
+    ByteBuffer temp = source.duplicate();
+    // We want to copy all the data in the source ByteBuffer, not just the
+    // remaining bytes.
+    temp.clear();
+    ByteBuffer result = ByteBuffer.allocate(temp.capacity());
+    result.put(temp);
+    result.clear();
+    return result;
+  }
+
+  /**
+   * Helper called by generated code to determine if a byte array is a valid
+   * UTF-8 encoded string such that the original bytes can be converted to
+   * a String object and then back to a byte array round tripping the bytes
+   * without loss.  More precisely, returns {@code true} whenever:
+   * <pre>   {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }</pre>
+   *
+   * <p>This method rejects "overlong" byte sequences, as well as
+   * 3-byte sequences that would map to a surrogate character, in
+   * accordance with the restricted definition of UTF-8 introduced in
+   * Unicode 3.1.  Note that the UTF-8 decoder included in Oracle's
+   * JDK has been modified to also reject "overlong" byte sequences,
+   * but currently (2011) still accepts 3-byte surrogate character
+   * byte sequences.
+   *
+   * <p>See the Unicode Standard,<br>
+   * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
+   * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+   *
+   * <p>As of 2011-02, this method simply returns the result of {@link
+   * ByteString#isValidUtf8()}.  Calling that method directly is preferred.
+   *
+   * @param byteString the string to check
+   * @return whether the byte array is round trippable
+   */
+  public static boolean isValidUtf8(ByteString byteString) {
+    return byteString.isValidUtf8();
+  }
+
+  /**
+   * Like {@link #isValidUtf8(ByteString)} but for byte arrays.
+   */
+  public static boolean isValidUtf8(byte[] byteArray) {
+    return Utf8.isValidUtf8(byteArray);
+  }
+
+  /**
+   * Helper method to get the UTF-8 bytes of a string.
+   */
+  public static byte[] toByteArray(String value) {
+    return value.getBytes(UTF_8);
+  }
+
+  /**
+   * Helper method to convert a byte array to a string using UTF-8 encoding.
+   */
+  public static String toStringUtf8(byte[] bytes) {
+    return new String(bytes, UTF_8);
+  }
+
+  /**
+   * Interface for an enum value or value descriptor, to be used in FieldSet.
+   * The lite library stores enum values directly in FieldSets but the full
+   * library stores EnumValueDescriptors in order to better support reflection.
+   */
+  public interface EnumLite {
+    int getNumber();
+  }
+
+  /**
+   * Interface for an object which maps integers to {@link EnumLite}s.
+   * {@link Descriptors.EnumDescriptor} implements this interface by mapping
+   * numbers to {@link Descriptors.EnumValueDescriptor}s.  Additionally,
+   * every generated enum type has a static method internalGetValueMap() which
+   * returns an implementation of this type that maps numbers to enum values.
+   */
+  public interface EnumLiteMap<T extends EnumLite> {
+    T findValueByNumber(int number);
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for longs.
+   * @see Long#hashCode()
+   */
+  public static int hashLong(long n) {
+    return (int) (n ^ (n >>> 32));
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for
+   * booleans.
+   * @see Boolean#hashCode()
+   */
+  public static int hashBoolean(boolean b) {
+    return b ? 1231 : 1237;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for enums.
+   * <p>
+   * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
+   * need to use the field number as the hash code to ensure compatibility
+   * between statically and dynamically generated enum objects.
+   */
+  public static int hashEnum(EnumLite e) {
+    return e.getNumber();
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for
+   * enum lists.
+   */
+  public static int hashEnumList(List<? extends EnumLite> list) {
+    int hash = 1;
+    for (EnumLite e : list) {
+      hash = 31 * hash + hashEnum(e);
+    }
+    return hash;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#equals(Object)} for bytes field.
+   */
+  public static boolean equals(List<byte[]> a, List<byte[]> b) {
+    if (a.size() != b.size()) return false;
+    for (int i = 0; i < a.size(); ++i) {
+      if (!Arrays.equals(a.get(i), b.get(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for bytes field.
+   */
+  public static int hashCode(List<byte[]> list) {
+    int hash = 1;
+    for (byte[] bytes : list) {
+      hash = 31 * hash + hashCode(bytes);
+    }
+    return hash;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for bytes field.
+   */
+  public static int hashCode(byte[] bytes) {
+    // The hash code for a byte array should be the same as the hash code for a
+    // ByteString with the same content. This is to ensure that the generated
+    // hashCode() method will return the same value as the pure reflection
+    // based hashCode() method.
+    return Internal.hashCode(bytes, 0, bytes.length);
+  }
+  
+  /**
+   * Helper method for implementing {@link LiteralByteString#hashCode()}.
+   */
+  static int hashCode(byte[] bytes, int offset, int length) {
+    // The hash code for a byte array should be the same as the hash code for a
+    // ByteString with the same content. This is to ensure that the generated
+    // hashCode() method will return the same value as the pure reflection
+    // based hashCode() method.
+    int h = Internal.partialHash(length, bytes, offset, length);
+    return h == 0 ? 1 : h;
+  }
+
+  /**
+   * Helper method for continuously hashing bytes.
+   */
+  static int partialHash(int h, byte[] bytes, int offset, int length) {
+    for (int i = offset; i < offset + length; i++) {
+      h = h * 31 + bytes[i];
+    }
+    return h;
+  }
+  
+  /**
+   * Helper method for implementing {@link Message#equals(Object)} for bytes
+   * field.
+   */
+  public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) {
+    if (a.capacity() != b.capacity()) {
+      return false;
+    }
+    // ByteBuffer.equals() will only compare the remaining bytes, but we want to
+    // compare all the content.
+    return a.duplicate().clear().equals(b.duplicate().clear());
+  }
+
+  /**
+   * Helper method for implementing {@link Message#equals(Object)} for bytes
+   * field.
+   */
+  public static boolean equalsByteBuffer(
+      List<ByteBuffer> a, List<ByteBuffer> b) {
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (int i = 0; i < a.size(); ++i) {
+      if (!equalsByteBuffer(a.get(i), b.get(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for bytes
+   * field.
+   */
+  public static int hashCodeByteBuffer(List<ByteBuffer> list) {
+    int hash = 1;
+    for (ByteBuffer bytes : list) {
+      hash = 31 * hash + hashCodeByteBuffer(bytes);
+    }
+    return hash;
+  }
+
+  private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()} for bytes
+   * field.
+   */
+  public static int hashCodeByteBuffer(ByteBuffer bytes) {
+    if (bytes.hasArray()) {
+      // Fast path.
+      int h = partialHash(bytes.capacity(), bytes.array(), bytes.arrayOffset(), bytes.capacity());
+      return h == 0 ? 1 : h;
+    } else {
+      // Read the data into a temporary byte array before calculating the
+      // hash value.
+      final int bufferSize = bytes.capacity() > DEFAULT_BUFFER_SIZE
+          ? DEFAULT_BUFFER_SIZE : bytes.capacity();
+      final byte[] buffer = new byte[bufferSize];
+      final ByteBuffer duplicated = bytes.duplicate();
+      duplicated.clear();
+      int h = bytes.capacity();
+      while (duplicated.remaining() > 0) {
+        final int length = duplicated.remaining() <= bufferSize ?
+            duplicated.remaining() : bufferSize;
+        duplicated.get(buffer, 0, length);
+        h = partialHash(h, buffer, 0, length);
+      }
+      return h == 0 ? 1 : h;
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T extends MessageLite> T getDefaultInstance(Class<T> clazz) {
+    try {
+      Method method = clazz.getMethod("getDefaultInstance");
+      return (T) method.invoke(method);
+    } catch (Exception e) {
+      throw new RuntimeException(
+          "Failed to get default instance for " + clazz, e);
+    }
+  }
+
+  /**
+   * An empty byte array constant used in generated code.
+   */
+  public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+  /**
+   * An empty byte array constant used in generated code.
+   */
+  public static final ByteBuffer EMPTY_BYTE_BUFFER =
+      ByteBuffer.wrap(EMPTY_BYTE_ARRAY);
+
+  /** An empty coded input stream constant used in generated code. */
+  public static final CodedInputStream EMPTY_CODED_INPUT_STREAM =
+      CodedInputStream.newInstance(EMPTY_BYTE_ARRAY);
+
+
+  /**
+   * Provides an immutable view of {@code List<T>} around a {@code List<F>}.
+   *
+   * Protobuf internal. Used in protobuf generated code only.
+   */
+  public static class ListAdapter<F, T> extends AbstractList<T> {
+    /**
+     * Convert individual elements of the List from F to T.
+     */
+    public interface Converter<F, T> {
+      T convert(F from);
+    }
+
+    private final List<F> fromList;
+    private final Converter<F, T> converter;
+
+    public ListAdapter(List<F> fromList, Converter<F, T> converter) {
+      this.fromList = fromList;
+      this.converter = converter;
+    }
+
+    @Override
+    public T get(int index) {
+      return converter.convert(fromList.get(index));
+    }
+
+    @Override
+    public int size() {
+      return fromList.size();
+    }
+  }
+
+  /**
+   * Wrap around a {@code Map<K, RealValue>} and provide a {@code Map<K, V>}
+   * interface.
+   */
+  public static class MapAdapter<K, V, RealValue> extends AbstractMap<K, V> {
+    /**
+     * An interface used to convert between two types.
+     */
+    public interface Converter<A, B> {
+      B doForward(A object);
+      A doBackward(B object);
+    }
+
+    public static <T extends EnumLite> Converter<Integer, T> newEnumConverter(
+        final EnumLiteMap<T> enumMap, final T unrecognizedValue) {
+      return new Converter<Integer, T>() {
+        @Override
+        public T doForward(Integer value) {
+          T result = enumMap.findValueByNumber(value);
+          return result == null ? unrecognizedValue : result;
+        }
+
+        @Override
+        public Integer doBackward(T value) {
+          return value.getNumber();
+        }
+      };
+    }
+
+    private final Map<K, RealValue> realMap;
+    private final Converter<RealValue, V> valueConverter;
+
+    public MapAdapter(Map<K, RealValue> realMap,
+        Converter<RealValue, V> valueConverter) {
+      this.realMap = realMap;
+      this.valueConverter = valueConverter;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public V get(Object key) {
+      RealValue result = realMap.get(key);
+      if (result == null) {
+        return null;
+      }
+      return valueConverter.doForward(result);
+    }
+
+    @Override
+    public V put(K key, V value) {
+      RealValue oldValue = realMap.put(key, valueConverter.doBackward(value));
+      if (oldValue == null) {
+        return null;
+      }
+      return valueConverter.doForward(oldValue);
+    }
+
+    @Override
+    public Set<java.util.Map.Entry<K, V>> entrySet() {
+      return new SetAdapter(realMap.entrySet());
+    }
+
+    private class SetAdapter extends AbstractSet<Map.Entry<K, V>> {
+      private final Set<Map.Entry<K, RealValue>> realSet;
+      public SetAdapter(Set<Map.Entry<K, RealValue>> realSet) {
+        this.realSet = realSet;
+      }
+
+      @Override
+      public Iterator<java.util.Map.Entry<K, V>> iterator() {
+        return new IteratorAdapter(realSet.iterator());
+      }
+
+      @Override
+      public int size() {
+        return realSet.size();
+      }
+    }
+
+    private class IteratorAdapter implements Iterator<Map.Entry<K, V>> {
+      private final Iterator<Map.Entry<K, RealValue>> realIterator;
+
+      public IteratorAdapter(
+          Iterator<Map.Entry<K, RealValue>> realIterator) {
+        this.realIterator = realIterator;
+      }
+
+      @Override
+      public boolean hasNext() {
+        return realIterator.hasNext();
+      }
+
+      @Override
+      public java.util.Map.Entry<K, V> next() {
+        return new EntryAdapter(realIterator.next());
+      }
+
+      @Override
+      public void remove() {
+        realIterator.remove();
+      }
+    }
+
+    private class EntryAdapter implements Map.Entry<K, V> {
+      private final Map.Entry<K, RealValue> realEntry;
+
+      public EntryAdapter(Map.Entry<K, RealValue> realEntry) {
+        this.realEntry = realEntry;
+      }
+
+      @Override
+      public K getKey() {
+        return realEntry.getKey();
+      }
+
+      @Override
+      public V getValue() {
+        return valueConverter.doForward(realEntry.getValue());
+      }
+
+      @Override
+      public V setValue(V value) {
+        RealValue oldValue = realEntry.setValue(
+            valueConverter.doBackward(value));
+        if (oldValue == null) {
+          return null;
+        }
+        return valueConverter.doForward(oldValue);
+      }
+    }
+  }
+
+  /**
+   * Extends {@link List} to add the capability to make the list immutable and inspect if it is
+   * modifiable.
+   * <p>
+   * All implementations must support efficient random access.
+   */
+  public static interface ProtobufList<E> extends List<E>, RandomAccess {
+
+    /**
+     * Makes this list immutable. All subsequent modifications will throw an
+     * {@link UnsupportedOperationException}.
+     */
+    void makeImmutable();
+
+    /**
+     * Returns whether this list can be modified via the publicly accessible {@link List} methods.
+     */
+    boolean isModifiable();
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    ProtobufList<E> mutableCopyWithCapacity(int capacity);
+  }
+
+  /**
+   * A {@link java.util.List} implementation that avoids boxing the elements into Integers if
+   * possible. Does not support null elements.
+   */
+  public static interface IntList extends ProtobufList<Integer> {
+
+    /**
+     * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+     */
+    int getInt(int index);
+
+    /**
+     * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+     */
+    void addInt(int element);
+
+    /**
+     * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element.
+     */
+    int setInt(int index, int element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    IntList mutableCopyWithCapacity(int capacity);
+  }
+
+  /**
+   * A {@link java.util.List} implementation that avoids boxing the elements into Booleans if
+   * possible. Does not support null elements.
+   */
+  public static interface BooleanList extends ProtobufList<Boolean> {
+
+    /**
+     * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+     */
+    boolean getBoolean(int index);
+
+    /**
+     * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+     */
+    void addBoolean(boolean element);
+
+    /**
+     * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element.
+     */
+    boolean setBoolean(int index, boolean element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    BooleanList mutableCopyWithCapacity(int capacity);
+  }
+
+  /**
+   * A {@link java.util.List} implementation that avoids boxing the elements into Longs if
+   * possible. Does not support null elements.
+   */
+  public static interface LongList extends ProtobufList<Long> {
+
+    /**
+     * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+     */
+    long getLong(int index);
+
+    /**
+     * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+     */
+    void addLong(long element);
+
+    /**
+     * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element.
+     */
+    long setLong(int index, long element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    LongList mutableCopyWithCapacity(int capacity);
+  }
+
+  /**
+   * A {@link java.util.List} implementation that avoids boxing the elements into Doubles if
+   * possible. Does not support null elements.
+   */
+  public static interface DoubleList extends ProtobufList<Double> {
+
+    /**
+     * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+     */
+    double getDouble(int index);
+
+    /**
+     * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+     */
+    void addDouble(double element);
+
+    /**
+     * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element.
+     */
+    double setDouble(int index, double element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    DoubleList mutableCopyWithCapacity(int capacity);
+  }
+
+  /**
+   * A {@link java.util.List} implementation that avoids boxing the elements into Floats if
+   * possible. Does not support null elements.
+   */
+  public static interface FloatList extends ProtobufList<Float> {
+
+    /**
+     * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+     */
+    float getFloat(int index);
+
+    /**
+     * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+     */
+    void addFloat(float element);
+
+    /**
+     * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element.
+     */
+    float setFloat(int index, float element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    FloatList mutableCopyWithCapacity(int capacity);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
new file mode 100644
index 0000000..85ce7b2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -0,0 +1,134 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a protocol message being parsed is invalid in some way,
+ * e.g. it contains a malformed varint or a negative byte length.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class InvalidProtocolBufferException extends IOException {
+  private static final long serialVersionUID = -1616151763072450476L;
+  private MessageLite unfinishedMessage = null;
+
+  public InvalidProtocolBufferException(final String description) {
+    super(description);
+  }
+
+  public InvalidProtocolBufferException(IOException e) {
+    super(e.getMessage(), e);
+  }
+
+  /**
+   * Attaches an unfinished message to the exception to support best-effort
+   * parsing in {@code Parser} interface.
+   *
+   * @return this
+   */
+  public InvalidProtocolBufferException setUnfinishedMessage(
+      MessageLite unfinishedMessage) {
+    this.unfinishedMessage = unfinishedMessage;
+    return this;
+  }
+
+  /**
+   * Returns the unfinished message attached to the exception, or null if
+   * no message is attached.
+   */
+  public MessageLite getUnfinishedMessage() {
+    return unfinishedMessage;
+  }
+
+  /**
+   * Unwraps the underlying {@link IOException} if this exception was caused by an I/O
+   * problem. Otherwise, returns {@code this}.
+   */
+  public IOException unwrapIOException() {
+    return getCause() instanceof IOException ? (IOException) getCause() : this;
+  }
+
+  static InvalidProtocolBufferException truncatedMessage() {
+    return new InvalidProtocolBufferException(
+      "While parsing a protocol message, the input ended unexpectedly " +
+      "in the middle of a field.  This could mean either that the " +
+      "input has been truncated or that an embedded message " +
+      "misreported its own length.");
+  }
+
+  static InvalidProtocolBufferException negativeSize() {
+    return new InvalidProtocolBufferException(
+      "CodedInputStream encountered an embedded string or message " +
+      "which claimed to have negative size.");
+  }
+
+  static InvalidProtocolBufferException malformedVarint() {
+    return new InvalidProtocolBufferException(
+      "CodedInputStream encountered a malformed varint.");
+  }
+
+  static InvalidProtocolBufferException invalidTag() {
+    return new InvalidProtocolBufferException(
+      "Protocol message contained an invalid tag (zero).");
+  }
+
+  static InvalidProtocolBufferException invalidEndTag() {
+    return new InvalidProtocolBufferException(
+      "Protocol message end-group tag did not match expected tag.");
+  }
+
+  static InvalidProtocolBufferException invalidWireType() {
+    return new InvalidProtocolBufferException(
+      "Protocol message tag had invalid wire type.");
+  }
+
+  static InvalidProtocolBufferException recursionLimitExceeded() {
+    return new InvalidProtocolBufferException(
+      "Protocol message had too many levels of nesting.  May be malicious.  " +
+      "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+  }
+
+  static InvalidProtocolBufferException sizeLimitExceeded() {
+    return new InvalidProtocolBufferException(
+      "Protocol message was too large.  May be malicious.  " +
+      "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+  }
+
+  static InvalidProtocolBufferException parseFailure() {
+    return new InvalidProtocolBufferException("Failed to parse the message.");
+  }
+
+  static InvalidProtocolBufferException invalidUtf8() {
+    return new InvalidProtocolBufferException("Protocol message had invalid UTF-8.");
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyField.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyField.java
new file mode 100644
index 0000000..98e13ca
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyField.java
@@ -0,0 +1,154 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+/**
+ * LazyField encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parse it on-demand.
+ *
+ * Most of key methods are implemented in {@link LazyFieldLite} but this class
+ * can contain default instance of the message to provide {@code hashCode()},
+ * {@code euqals()} and {@code toString()}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyField extends LazyFieldLite {
+
+  /**
+   * Carry a message's default instance which is used by {@code hashCode()}, {@code euqals()} and
+   * {@code toString()}.
+   */
+  private final MessageLite defaultInstance;
+
+  public LazyField(MessageLite defaultInstance,
+      ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    super(extensionRegistry, bytes);
+
+    this.defaultInstance = defaultInstance;
+  }
+
+  @Override
+  public boolean containsDefaultInstance() {
+    return super.containsDefaultInstance() || value == defaultInstance;
+  }
+
+  public MessageLite getValue() {
+    return getValue(defaultInstance);
+  }
+
+  @Override
+  public int hashCode() {
+    return getValue().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return getValue().equals(obj);
+  }
+
+  @Override
+  public String toString() {
+    return getValue().toString();
+  }
+
+  // ====================================================
+
+  /**
+   * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
+   * users iterate all fields from FieldSet.
+   */
+  static class LazyEntry<K> implements Entry<K, Object> {
+    private Entry<K, LazyField> entry;
+
+    private LazyEntry(Entry<K, LazyField> entry) {
+      this.entry = entry;
+    }
+
+    @Override
+    public K getKey() {
+      return entry.getKey();
+    }
+
+    @Override
+    public Object getValue() {
+      LazyField field = entry.getValue();
+      if (field == null) {
+        return null;
+      }
+      return field.getValue();
+    }
+
+    public LazyField getField() {
+      return entry.getValue();
+    }
+
+    @Override
+    public Object setValue(Object value) {
+      if (!(value instanceof MessageLite)) {
+        throw new IllegalArgumentException(
+            "LazyField now only used for MessageSet, "
+            + "and the value of MessageSet must be an instance of MessageLite");
+      }
+      return entry.getValue().setValue((MessageLite) value);
+    }
+  }
+
+  static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
+    private Iterator<Entry<K, Object>> iterator;
+
+    public LazyIterator(Iterator<Entry<K, Object>> iterator) {
+      this.iterator = iterator;
+    }
+
+    @Override
+    public boolean hasNext() {
+      return iterator.hasNext();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Entry<K, Object> next() {
+      Entry<K, ?> entry = iterator.next();
+      if (entry.getValue() instanceof LazyField) {
+        return new LazyEntry<K>((Entry<K, LazyField>) entry);
+      }
+      return (Entry<K, Object>) entry;
+    }
+
+    @Override
+    public void remove() {
+      iterator.remove();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
new file mode 100644
index 0000000..2febaac
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -0,0 +1,458 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parses it on-demand.
+ *
+ * LazyFieldLite is thread-compatible: concurrent reads are safe once the proto that this
+ * LazyFieldLite is a part of is no longer being mutated by its Builder. However, explicit
+ * synchronization is needed under read/write situations.
+ *
+ * When a LazyFieldLite is used in the context of a MessageLite object, its behavior is considered
+ * to be immutable and none of the setter methods in its API are expected to be invoked. All of the
+ * getters are expected to be thread-safe. When used in the context of a MessageLite.Builder,
+ * setters can be invoked, but there is no guarantee of thread safety.
+ * 
+ * TODO(yatin,dweis): Consider splitting this class's functionality and put the mutable methods
+ * into a separate builder class to allow us to give stronger compile-time guarantees.
+ *
+ * This class is internal implementation detail of the protobuf library, so you don't need to use it
+ * directly.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldLite {
+  private static final ExtensionRegistryLite EMPTY_REGISTRY =
+      ExtensionRegistryLite.getEmptyRegistry();
+
+  /**
+   * The value associated with the LazyFieldLite object is stored in one or more of the following
+   * three fields (delayedBytes, value, memoizedBytes). They should together be interpreted as
+   * follows.
+   * 1) delayedBytes can be non-null, while value and memoizedBytes is null. The object will be in
+   *    this state while the value for the object has not yet been parsed.
+   * 2) Both delayedBytes and value are non-null. The object transitions to this state as soon as
+   *    some caller needs to access the value (by invoking getValue()).
+   * 3) memoizedBytes is merely an optimization for calls to LazyFieldLite.toByteString() to avoid
+   *    recomputing the ByteString representation on each call. Instead, when the value is parsed
+   *    from delayedBytes, we will also assign the contents of delayedBytes to memoizedBytes (since
+   *    that is the ByteString representation of value).
+   * 4) Finally, if the LazyFieldLite was created directly with a parsed MessageLite value, then
+   *    delayedBytes will be null, and memoizedBytes will be initialized only upon the first call to
+   *    LazyFieldLite.toByteString().
+   *
+   * Given the above conditions, any caller that needs a serialized representation of this object
+   * must first check if the memoizedBytes or delayedBytes ByteString is non-null and use it
+   * directly; if both of those are null, it can look at the parsed value field. Similarly, any
+   * caller that needs a parsed value must first check if the value field is already non-null, if
+   * not it must parse the value from delayedBytes.
+   */
+
+  /**
+   * A delayed-parsed version of the contents of this field. When this field is non-null, then the
+   * "value" field is allowed to be null until the time that the value needs to be read.
+   *
+   * When delayedBytes is non-null then {@code extensionRegistry} is required to also be non-null.
+   * {@code value} and {@code memoizedBytes} will be initialized lazily.
+   */
+  private ByteString delayedBytes;
+
+  /**
+   * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It
+   * is only guaranteed to be non-null if this message was initialized using bytes and an
+   * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has
+   * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}.
+   */
+  private ExtensionRegistryLite extensionRegistry;
+
+  /**
+   * The parsed value. When this is null and a caller needs access to the MessageLite value, then
+   * {@code delayedBytes} will be parsed lazily at that time.
+   */
+  protected volatile MessageLite value;
+
+  /**
+   * The memoized bytes for {@code value}. This is an optimization for the toByteString() method to
+   * not have to recompute its return-value on each invocation.
+   * TODO(yatin): Figure out whether this optimization is actually necessary.
+   */
+  private volatile ByteString memoizedBytes;
+
+  /**
+   * Constructs a LazyFieldLite with bytes that will be parsed lazily.
+   */
+  public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    checkArguments(extensionRegistry, bytes);
+    this.extensionRegistry = extensionRegistry;
+    this.delayedBytes = bytes;
+  }
+
+  /**
+   * Constructs a LazyFieldLite with no contents, and no ability to parse extensions.
+   */
+  public LazyFieldLite() {
+  }
+
+  /**
+   * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse
+   * the extensions in the value as it has no ExtensionRegistry.
+   */
+  public static LazyFieldLite fromValue(MessageLite value) {
+    LazyFieldLite lf = new LazyFieldLite();
+    lf.setValue(value);
+    return lf;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof LazyFieldLite)) {
+      return false;
+    }
+
+    LazyFieldLite other = (LazyFieldLite) o;
+    
+    // Lazy fields do not work well with equals... If both are delayedBytes, we do not have a
+    // mechanism to deserialize them so we rely on bytes equality. Otherwise we coerce into an
+    // actual message (if necessary) and call equals on the message itself. This implies that two
+    // messages can by unequal but then be turned equal simply be invoking a getter on a lazy field.
+    MessageLite value1 = value;
+    MessageLite value2 = other.value;
+    if (value1 == null && value2 == null) {
+      return toByteString().equals(other.toByteString());
+    } else if (value1 != null && value2 != null) {
+      return value1.equals(value2);
+    } else if (value1 != null) {
+      return value1.equals(other.getValue(value1.getDefaultInstanceForType()));
+    } else {
+      return getValue(value2.getDefaultInstanceForType()).equals(value2);
+    }
+  }
+  
+  @Override
+  public int hashCode() {
+    // We can't provide a memoizable hash code for lazy fields. The byte strings may have different
+    // hash codes but evaluate to equivalent messages. And we have no facility for constructing
+    // a message here if we were not already holding a value.
+    return 1;
+  }
+  
+  /**
+   * Determines whether this LazyFieldLite instance represents the default instance of this type.
+   */
+  public boolean containsDefaultInstance() {
+    return memoizedBytes == ByteString.EMPTY
+        || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY);
+  }
+
+  /**
+   * Clears the value state of this instance.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void clear() {
+    // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another
+    // value, but there is no guarantee that it will contain all extensions that were directly set
+    // on the values that need to be merged.
+    delayedBytes = null;
+    value = null;
+    memoizedBytes = null;
+  }
+
+  /**
+   * Overrides the contents of this LazyField.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void set(LazyFieldLite other) {
+    this.delayedBytes = other.delayedBytes;
+    this.value = other.value;
+    this.memoizedBytes = other.memoizedBytes;
+    // If the other LazyFieldLite was created by directly setting the value rather than first by
+    // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing
+    // extensionRegistry, which has no guarantees that it has all the extensions that will be
+    // directly set on the value.
+    if (other.extensionRegistry != null) {
+      this.extensionRegistry = other.extensionRegistry;
+    }
+  }
+
+  /**
+   * Returns message instance. It may do some thread-safe delayed parsing of bytes.
+   *
+   * @param defaultInstance its message's default instance. It's also used to get parser for the
+   * message type.
+   */
+  public MessageLite getValue(MessageLite defaultInstance) {
+    ensureInitialized(defaultInstance);
+    return value;
+  }
+
+  /**
+   * Sets the value of the instance and returns the old value without delay parsing anything.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public MessageLite setValue(MessageLite value) {
+    MessageLite originalValue = this.value;
+    this.delayedBytes = null;
+    this.memoizedBytes = null;
+    this.value = value;
+    return originalValue;
+  }
+
+  /**
+   * Merges another instance's contents. In some cases may drop some extensions if both fields
+   * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this
+   * field will copy over that {@code ExtensionRegistry}.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void merge(LazyFieldLite other) {
+    if (other.containsDefaultInstance()) {
+      return;
+    }
+
+    if (this.containsDefaultInstance()) {
+      set(other);
+      return;
+    }
+
+    // If the other field has an extension registry but this does not, copy over the other extension
+    // registry.
+    if (this.extensionRegistry == null) {
+      this.extensionRegistry = other.extensionRegistry;
+    }
+
+    // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+    // the (probably rare) case that they have different extension registries there is a chance that
+    // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+    // to outway the benefits of combining the extension registries, which is not normally done for
+    // lite protos anyways.
+    if (this.delayedBytes != null && other.delayedBytes != null) {
+      this.delayedBytes = this.delayedBytes.concat(other.delayedBytes);
+      return;
+    }
+
+    // At least one is parsed and both contain data. We won't drop any extensions here directly, but
+    // in the case that the extension registries are not the same then we might in the future if we
+    // need to serialze and parse a message again.
+    if (this.value == null && other.value != null) {
+      setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry));
+      return;
+    } else if (this.value != null && other.value == null) {
+      setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry));
+      return;
+    }
+
+    // At this point we have two fully parsed messages. We can't merge directly from one to the
+    // other because only generated builder code contains methods to mergeFrom another parsed
+    // message. We have to serialize one instance and then merge the bytes into the other. This may
+    // drop extensions from one of the messages if one of the values had an extension set on it
+    // directly.
+    //
+    // To mitigate this we prefer serializing a message that has an extension registry, and
+    // therefore a chance that all extensions set on it are in that registry.
+    //
+    // NOTE: The check for other.extensionRegistry not being null must come first because at this
+    // point in time if other.extensionRegistry is not null then this.extensionRegistry will not be
+    // null either.
+    if (other.extensionRegistry != null) {
+      setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry));
+      return;
+    } else if (this.extensionRegistry != null) {
+      setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry));
+      return;
+    } else {
+      // All extensions from the other message will be dropped because we have no registry.
+      setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY));
+      return;
+    }
+  }
+  
+  /**
+   * Merges another instance's contents from a stream.
+   *
+   * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public void mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    if (this.containsDefaultInstance()) {
+      setByteString(input.readBytes(), extensionRegistry);
+      return;
+    }
+
+    // If the other field has an extension registry but this does not, copy over the other extension
+    // registry.
+    if (this.extensionRegistry == null) {
+      this.extensionRegistry = extensionRegistry;
+    }
+
+    // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+    // the (probably rare) case that they have different extension registries there is a chance that
+    // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+    // to outway the benefits of combining the extension registries, which is not normally done for
+    // lite protos anyways.
+    if (this.delayedBytes != null) {
+      setByteString(this.delayedBytes.concat(input.readBytes()), this.extensionRegistry);
+      return;
+    }
+
+    // We are parsed and both contain data. We won't drop any extensions here directly, but in the
+    // case that the extension registries are not the same then we might in the future if we
+    // need to serialize and parse a message again.
+    try {
+      setValue(value.toBuilder().mergeFrom(input, extensionRegistry).build());
+    } catch (InvalidProtocolBufferException e) {
+      // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+      // was invalid.
+    }
+  }
+
+  private static MessageLite mergeValueAndBytes(
+      MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) {
+    try {
+      return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build();
+    } catch (InvalidProtocolBufferException e) {
+      // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+      // was invalid.
+      return value;
+    }
+  }
+
+  /**
+   * Sets this field with bytes to delay-parse.
+   */
+  public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
+    checkArguments(extensionRegistry, bytes);
+    this.delayedBytes = bytes;
+    this.extensionRegistry = extensionRegistry;
+    this.value = null;
+    this.memoizedBytes = null;
+  }
+
+  /**
+   * Due to the optional field can be duplicated at the end of serialized
+   * bytes, which will make the serialized size changed after LazyField
+   * parsed. Be careful when using this method.
+   */
+  public int getSerializedSize() {
+    // We *must* return delayed bytes size if it was ever set because the dependent messages may
+    // have memoized serialized size based off of it.
+    if (memoizedBytes != null) {
+      return memoizedBytes.size();
+    } else if (delayedBytes != null) {
+      return delayedBytes.size();
+    } else if (value != null) {
+      return value.getSerializedSize();
+    } else {
+      return 0;
+    }
+  }
+
+  /**
+   * Returns a BytesString for this field in a thread-safe way.
+   */
+  public ByteString toByteString() {
+    if (memoizedBytes != null) {
+      return memoizedBytes;
+    }
+    // We *must* return delayed bytes if it was set because the dependent messages may have
+    // memoized serialized size based off of it.
+    if (delayedBytes != null) {
+      return delayedBytes;
+    }
+    synchronized (this) {
+      if (memoizedBytes != null) {
+        return memoizedBytes;
+      }
+      if (value == null) {
+        memoizedBytes = ByteString.EMPTY;
+      } else {
+        memoizedBytes = value.toByteString();
+      }
+      return memoizedBytes;
+    }
+  }
+
+  /**
+   * Might lazily parse the bytes that were previously passed in. Is thread-safe.
+   */
+  protected void ensureInitialized(MessageLite defaultInstance) {
+    if (value != null) {
+      return;
+    }
+    synchronized (this) {
+      if (value != null) {
+        return;
+      }
+      try {
+        if (delayedBytes != null) {
+          // The extensionRegistry shouldn't be null here since we have delayedBytes.
+          MessageLite parsedValue = defaultInstance.getParserForType()
+              .parseFrom(delayedBytes, extensionRegistry);
+          this.value = parsedValue;
+          this.memoizedBytes = delayedBytes;
+        } else {
+          this.value = defaultInstance;
+          this.memoizedBytes = ByteString.EMPTY;
+        }
+      } catch (InvalidProtocolBufferException e) {
+        // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto
+        // was invalid.
+        this.value = defaultInstance;
+        this.memoizedBytes = ByteString.EMPTY;
+      }
+    }
+  }
+
+
+  private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    if (extensionRegistry == null) {
+      throw new NullPointerException("found null ExtensionRegistry");
+    }
+    if (bytes == null) {
+      throw new NullPointerException("found null ByteString");
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
new file mode 100644
index 0000000..d474c51
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -0,0 +1,423 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps an ArrayList. Each
+ * element is one of String, ByteString, or byte[]. It caches the last one
+ * requested which is most likely the one needed next. This minimizes memory
+ * usage while satisfying the most common use cases.
+ * <p>
+ * <strong>Note that this implementation is not synchronized.</strong>
+ * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
+ * and at least one of the threads modifies the list structurally, it
+ * <i>must</i> be synchronized externally.  (A structural modification is
+ * any operation that adds or deletes one or more elements, or explicitly
+ * resizes the backing array; merely setting the value of an element is not
+ * a structural modification.)  This is typically accomplished by
+ * synchronizing on some object that naturally encapsulates the list.
+ * <p>
+ * If the implementation is accessed via concurrent reads, this is thread safe.
+ * Conversions are done in a thread safe manner. It's possible that the
+ * conversion may happen more than once if two threads attempt to access the
+ * same element and the modifications were not visible to each other, but this
+ * will not result in any corruption of the list or change in behavior other
+ * than performance.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayList extends AbstractProtobufList<String>
+    implements LazyStringList, RandomAccess {
+
+  private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  static LazyStringArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+
+  // For compatibility with older runtimes.
+  public static final LazyStringList EMPTY = EMPTY_LIST;
+
+  private final List<Object> list;
+
+  public LazyStringArrayList() {
+    this(DEFAULT_CAPACITY);
+  }
+
+  public LazyStringArrayList(int intialCapacity) {
+    this(new ArrayList<Object>(intialCapacity));
+  }
+
+  public LazyStringArrayList(LazyStringList from) {
+    list = new ArrayList<Object>(from.size());
+    addAll(from);
+  }
+
+  public LazyStringArrayList(List<String> from) {
+    this(new ArrayList<Object>(from));
+  }
+  
+  private LazyStringArrayList(ArrayList<Object> list) {
+    this.list = list;
+  }
+
+  @Override
+  public LazyStringArrayList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size()) {
+      throw new IllegalArgumentException();
+    }
+    ArrayList<Object> newList = new ArrayList<Object>(capacity);
+    newList.addAll(list);
+    return new LazyStringArrayList(newList);
+  }
+
+  @Override
+  public String get(int index) {
+    Object o = list.get(index);
+    if (o instanceof String) {
+      return (String) o;
+    } else if (o instanceof ByteString) {
+      ByteString bs = (ByteString) o;
+      String s = bs.toStringUtf8();
+      if (bs.isValidUtf8()) {
+        list.set(index, s);
+      }
+      return s;
+    } else {
+      byte[] ba = (byte[]) o;
+      String s = Internal.toStringUtf8(ba);
+      if (Internal.isValidUtf8(ba)) {
+        list.set(index, s);
+      }
+      return s;
+    }
+  }
+
+  @Override
+  public int size() {
+    return list.size();
+  }
+
+  @Override
+  public String set(int index, String s) {
+    ensureIsMutable();
+    Object o = list.set(index, s);
+    return asString(o);
+  }
+
+  @Override
+  public void add(int index, String element) {
+    ensureIsMutable();
+    list.add(index, element);
+    modCount++;
+  }
+  
+  private void add(int index, ByteString element) {
+    ensureIsMutable();
+    list.add(index, element);
+    modCount++;
+  }
+  
+  private void add(int index, byte[] element) {
+    ensureIsMutable();
+    list.add(index, element);
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends String> c) {
+    // The default implementation of AbstractCollection.addAll(Collection)
+    // delegates to add(Object). This implementation instead delegates to
+    // addAll(int, Collection), which makes a special case for Collections
+    // which are instances of LazyStringList.
+    return addAll(size(), c);
+  }
+
+  @Override
+  public boolean addAll(int index, Collection<? extends String> c) {
+    ensureIsMutable();
+    // When copying from another LazyStringList, directly copy the underlying
+    // elements rather than forcing each element to be decoded to a String.
+    Collection<?> collection = c instanceof LazyStringList
+        ? ((LazyStringList) c).getUnderlyingElements() : c;
+    boolean ret = list.addAll(index, collection);
+    modCount++;
+    return ret;
+  }
+
+  @Override
+  public boolean addAllByteString(Collection<? extends ByteString> values) {
+    ensureIsMutable();
+    boolean ret = list.addAll(values);
+    modCount++;
+    return ret;
+  }
+
+  @Override
+  public boolean addAllByteArray(Collection<byte[]> c) {
+    ensureIsMutable();
+    boolean ret = list.addAll(c);
+    modCount++;
+    return ret;
+  }
+
+  @Override
+  public String remove(int index) {
+    ensureIsMutable();
+    Object o = list.remove(index);
+    modCount++;
+    return asString(o);
+  }
+
+  @Override
+  public void clear() {
+    ensureIsMutable();
+    list.clear();
+    modCount++;
+  }
+
+  @Override
+  public void add(ByteString element) {
+    ensureIsMutable();
+    list.add(element);
+    modCount++;
+  }
+  
+  @Override
+  public void add(byte[] element) {
+    ensureIsMutable();
+    list.add(element);
+    modCount++;
+  }
+
+  @Override
+  public Object getRaw(int index) {
+    return list.get(index);
+  }
+  
+  @Override
+  public ByteString getByteString(int index) {
+    Object o = list.get(index);
+    ByteString b = asByteString(o);
+    if (b != o) {
+      list.set(index, b);
+    }
+    return b;
+  }
+  
+  @Override
+  public byte[] getByteArray(int index) {
+    Object o = list.get(index);
+    byte[] b = asByteArray(o);
+    if (b != o) {
+      list.set(index, b);
+    }
+    return b;
+  }
+
+  @Override
+  public void set(int index, ByteString s) {
+    setAndReturn(index, s);
+  }
+  
+  private Object setAndReturn(int index, ByteString s) {
+    ensureIsMutable();
+    return list.set(index, s);
+  }
+
+  @Override
+  public void set(int index, byte[] s) {
+    setAndReturn(index, s);
+  }
+  
+  private Object setAndReturn(int index, byte[] s) {
+    ensureIsMutable();
+    return list.set(index, s);
+  }
+
+  private static String asString(Object o) {
+    if (o instanceof String) {
+      return (String) o;
+    } else if (o instanceof ByteString) {
+      return ((ByteString) o).toStringUtf8();
+    } else {
+      return Internal.toStringUtf8((byte[]) o);
+    }
+  }
+  
+  private static ByteString asByteString(Object o) {
+    if (o instanceof ByteString) {
+      return (ByteString) o;
+    } else if (o instanceof String) {
+      return ByteString.copyFromUtf8((String) o);
+    } else {
+      return ByteString.copyFrom((byte[]) o);
+    }
+  }
+  
+  private static byte[] asByteArray(Object o) {
+    if (o instanceof byte[]) {
+      return (byte[]) o;
+    } else if (o instanceof String) {
+      return Internal.toByteArray((String) o);
+    } else {
+      return ((ByteString) o).toByteArray();
+    }
+  }
+
+  @Override
+  public List<?> getUnderlyingElements() {
+    return Collections.unmodifiableList(list);
+  }
+
+  @Override
+  public void mergeFrom(LazyStringList other) {
+    ensureIsMutable();
+    for (Object o : other.getUnderlyingElements()) {
+      if (o instanceof byte[]) {
+        byte[] b = (byte[]) o;
+        // Byte array's content is mutable so they should be copied rather than
+        // shared when merging from one message to another.
+        list.add(Arrays.copyOf(b, b.length));
+      } else {
+        list.add(o);
+      }
+    }
+  }
+
+  private static class ByteArrayListView extends AbstractList<byte[]>
+      implements RandomAccess {
+    private final LazyStringArrayList list;
+    
+    ByteArrayListView(LazyStringArrayList list) {
+      this.list = list;
+    }
+    
+    @Override
+    public byte[] get(int index) {
+      return list.getByteArray(index);
+    }
+
+    @Override
+    public int size() {
+      return list.size();
+    }
+
+    @Override
+    public byte[] set(int index, byte[] s) {
+      Object o = list.setAndReturn(index, s);
+      modCount++;
+      return asByteArray(o);
+    }
+
+    @Override
+    public void add(int index, byte[] s) {
+      list.add(index, s);
+      modCount++;
+    }
+
+    @Override
+    public byte[] remove(int index) {
+      Object o = list.remove(index);
+      modCount++;
+      return asByteArray(o);
+    }
+  }
+  
+  @Override
+  public List<byte[]> asByteArrayList() {
+    return new ByteArrayListView(this);
+  }
+
+  private static class ByteStringListView extends AbstractList<ByteString>
+      implements RandomAccess {
+    private final LazyStringArrayList list;
+
+    ByteStringListView(LazyStringArrayList list) {
+      this.list = list;
+    }
+
+    @Override
+    public ByteString get(int index) {
+      return list.getByteString(index);
+    }
+
+    @Override
+    public int size() {
+      return list.size();
+    }
+
+    @Override
+    public ByteString set(int index, ByteString s) {
+      Object o = list.setAndReturn(index, s);
+      modCount++;
+      return asByteString(o);
+    }
+
+    @Override
+    public void add(int index, ByteString s) {
+      list.add(index, s);
+      modCount++;
+    }
+
+    @Override
+    public ByteString remove(int index) {
+      Object o = list.remove(index);
+      modCount++;
+      return asByteString(o);
+    }
+  }
+
+  @Override
+  public List<ByteString> asByteStringList() {
+    return new ByteStringListView(this);
+  }
+
+  @Override
+  public LazyStringList getUnmodifiableView() {
+    if (isModifiable()) {
+      return new UnmodifiableLazyStringList(this);
+    }
+    return this;
+  }
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringList.java
new file mode 100644
index 0000000..3eeedca
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LazyStringList.java
@@ -0,0 +1,174 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * An interface extending {@code List<String>} that also provides access to the
+ * items of the list as UTF8-encoded ByteString or byte[] objects. This is
+ * used by the protocol buffer implementation to support lazily converting bytes
+ * parsed over the wire to String objects until needed and also increases the
+ * efficiency of serialization if the String was never requested as the
+ * ByteString or byte[] is already cached. The ByteString methods are used in
+ * immutable API only and byte[] methods used in mutable API only for they use
+ * different representations for string/bytes fields.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface LazyStringList extends ProtocolStringList {
+
+  /**
+   * Returns the element at the specified position in this list as a ByteString.
+   *
+   * @param index index of the element to return
+   * @return the element at the specified position in this list
+   * @throws IndexOutOfBoundsException if the index is out of range
+   *         ({@code index < 0 || index >= size()})
+   */
+  ByteString getByteString(int index);
+
+  /**
+   * Returns the element at the specified position in this list as an Object
+   * that will either be a String or a ByteString.
+   *
+   * @param index index of the element to return
+   * @return the element at the specified position in this list
+   * @throws IndexOutOfBoundsException if the index is out of range
+   *         ({@code index < 0 || index >= size()})
+   */
+  Object getRaw(int index);
+
+  /**
+   * Returns the element at the specified position in this list as byte[].
+   *
+   * @param index index of the element to return
+   * @return the element at the specified position in this list
+   * @throws IndexOutOfBoundsException if the index is out of range
+   *         ({@code index < 0 || index >= size()})
+   */
+  byte[] getByteArray(int index);
+
+  /**
+   * Appends the specified element to the end of this list (optional
+   * operation).
+   *
+   * @param element element to be appended to this list
+   * @throws UnsupportedOperationException if the <tt>add</tt> operation
+   *         is not supported by this list
+   */
+  void add(ByteString element);
+
+  /**
+   * Appends the specified element to the end of this list (optional
+   * operation).
+   *
+   * @param element element to be appended to this list
+   * @throws UnsupportedOperationException if the <tt>add</tt> operation
+   *         is not supported by this list
+   */
+  void add(byte[] element);
+
+  /**
+   * Replaces the element at the specified position in this list with the
+   * specified element (optional operation).
+   *
+   * @param index index of the element to replace
+   * @param element the element to be stored at the specified position
+   * @throws UnsupportedOperationException if the <tt>set</tt> operation
+   *         is not supported by this list
+   *         IndexOutOfBoundsException if the index is out of range
+   *         ({@code index < 0 || index >= size()})
+   */
+  void set(int index, ByteString element);
+  
+  /**
+   * Replaces the element at the specified position in this list with the
+   * specified element (optional operation).
+   *
+   * @param index index of the element to replace
+   * @param element the element to be stored at the specified position
+   * @throws UnsupportedOperationException if the <tt>set</tt> operation
+   *         is not supported by this list
+   *         IndexOutOfBoundsException if the index is out of range
+   *         ({@code index < 0 || index >= size()})
+   */
+  void set(int index, byte[] element);
+
+  /**
+   * Appends all elements in the specified ByteString collection to the end of
+   * this list.
+   *
+   * @param c collection whose elements are to be added to this list
+   * @return true if this list changed as a result of the call
+   * @throws UnsupportedOperationException if the <tt>addAllByteString</tt>
+   *         operation is not supported by this list
+   */
+  boolean addAllByteString(Collection<? extends ByteString> c);
+
+  /**
+   * Appends all elements in the specified byte[] collection to the end of
+   * this list.
+   *
+   * @param c collection whose elements are to be added to this list
+   * @return true if this list changed as a result of the call
+   * @throws UnsupportedOperationException if the <tt>addAllByteArray</tt>
+   *         operation is not supported by this list
+   */
+  boolean addAllByteArray(Collection<byte[]> c);
+
+  /**
+   * Returns an unmodifiable List of the underlying elements, each of which is
+   * either a {@code String} or its equivalent UTF-8 encoded {@code ByteString}
+   * or byte[]. It is an error for the caller to modify the returned
+   * List, and attempting to do so will result in an
+   * {@link UnsupportedOperationException}.
+   */
+  List<?> getUnderlyingElements();
+
+  /**
+   * Merges all elements from another LazyStringList into this one. This method
+   * differs from {@link #addAll(Collection)} on that underlying byte arrays are
+   * copied instead of reference shared. Immutable API doesn't need to use this
+   * method as byte[] is not used there at all.
+   */
+  void mergeFrom(LazyStringList other);
+
+  /**
+   * Returns a mutable view of this list. Changes to the view will be made into
+   * the original list. This method is used in mutable API only.
+   */
+  List<byte[]> asByteArrayList();
+
+  /** Returns an unmodifiable view of the list. */
+  LazyStringList getUnmodifiableView();
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LongArrayList.java
new file mode 100644
index 0000000..bc4475d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -0,0 +1,269 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.LongList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LongList} on top of a primitive array.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess {
+  
+  private static final LongArrayList EMPTY_LIST = new LongArrayList();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  public static LongArrayList emptyList() {
+    return EMPTY_LIST;
+  }
+  
+  /**
+   * The backing store for the list.
+   */
+  private long[] array;
+  
+  /**
+   * The size of the list distinct from the length of the array. That is, it is the number of
+   * elements set in the list.
+   */
+  private int size;
+
+  /**
+   * Constructs a new mutable {@code LongArrayList} with default capacity.
+   */
+  LongArrayList() {
+    this(new long[DEFAULT_CAPACITY], 0);
+  }
+
+  /**
+   * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}.
+   */
+  private LongArrayList(long[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof IntArrayList)) {
+      return super.equals(o);
+    }
+    LongArrayList other = (LongArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final long[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Internal.hashLong(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public LongList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new LongArrayList(Arrays.copyOf(array, capacity), size);
+  }
+  
+  @Override
+  public Long get(int index) {
+    return getLong(index);
+  }
+
+  @Override
+  public long getLong(int index) {
+    ensureIndexInRange(index);
+    return array[index];
+  }
+
+  @Override
+  public int size() {
+    return size;
+  }
+
+  @Override
+  public Long set(int index, Long element) {
+    return setLong(index, element);
+  }
+
+  @Override
+  public long setLong(int index, long element) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    long previousValue = array[index];
+    array[index] = element;
+    return previousValue;
+  }
+
+  @Override
+  public void add(int index, Long element) {
+    addLong(index, element);
+  }
+
+  /**
+   * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+   */
+  @Override
+  public void addLong(long element) {
+    addLong(size, element);
+  }
+
+  /**
+   * Like {@link #add(int, Long)} but more efficient in that it doesn't box the element.
+   */
+  private void addLong(int index, long element) {
+    ensureIsMutable();
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+    
+    if (size < array.length) {
+      // Shift everything over to make room
+      System.arraycopy(array, index, array, index + 1, size - index);
+    } else {
+      // Resize to 1.5x the size
+      int length = ((size * 3) / 2) + 1;
+      long[] newArray = new long[length];
+      
+      // Copy the first part directly
+      System.arraycopy(array, 0, newArray, 0, index);
+      
+      // Copy the rest shifted over by one to make room
+      System.arraycopy(array, index, newArray, index + 1, size - index);
+      array = newArray;
+    }
+
+    array[index] = element;
+    size++;
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends Long> collection) {
+    ensureIsMutable();
+    
+    if (collection == null) {
+      throw new NullPointerException();
+    }
+    
+    // We specialize when adding another LongArrayList to avoid boxing elements.
+    if (!(collection instanceof LongArrayList)) {
+      return super.addAll(collection);
+    }
+    
+    LongArrayList list = (LongArrayList) collection;
+    if (list.size == 0) {
+      return false;
+    }
+    
+    int overflow = Integer.MAX_VALUE - size;
+    if (overflow < list.size) {
+      // We can't actually represent a list this large.
+      throw new OutOfMemoryError();
+    }
+    
+    int newSize = size + list.size;
+    if (newSize > array.length) {
+      array = Arrays.copyOf(array, newSize);
+    }
+    
+    System.arraycopy(list.array, 0, array, size, list.size);
+    size = newSize;
+    modCount++;
+    return true;
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    for (int i = 0; i < size; i++) {
+      if (o.equals(array[i])) {
+        System.arraycopy(array, i + 1, array, i, size - i);
+        size--;
+        modCount++;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Long remove(int index) {
+    ensureIsMutable();
+    ensureIndexInRange(index);
+    long value = array[index];
+    System.arraycopy(array, index + 1, array, index, size - index);
+    size--;
+    modCount++;
+    return value;
+  }
+
+  /**
+   * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+   * {@link IndexOutOfBoundsException} if it is not.
+   * 
+   * @param index the index to verify is in range
+   */
+  private void ensureIndexInRange(int index) {
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+    }
+  }
+
+  private String makeOutOfBoundsExceptionMessage(int index) {
+    return "Index:" + index + ", Size:" + size;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntry.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntry.java
new file mode 100644
index 0000000..31414bb
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntry.java
@@ -0,0 +1,433 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Implements MapEntry messages.
+ * 
+ * In reflection API, map fields will be treated as repeated message fields and
+ * each map entry is accessed as a message. This MapEntry class is used to
+ * represent these map entry messages in reflection API.
+ * 
+ * Protobuf internal. Users shouldn't use this class.
+ */
+public final class MapEntry<K, V> extends AbstractMessage {
+  private static class Metadata<K, V> {
+    public final Descriptor descriptor;  
+    public final MapEntry<K, V> defaultInstance;
+    public final AbstractParser<MapEntry<K, V>> parser;
+    
+    public Metadata(
+        final Descriptor descriptor, final MapEntry<K, V> defaultInstance) {
+      this.descriptor = descriptor;
+      this.defaultInstance = defaultInstance;
+      final Metadata<K, V> thisMetadata = this;
+      this.parser = new AbstractParser<MapEntry<K, V>>() {
+        private final Parser<MapEntryLite<K, V>> dataParser =
+            defaultInstance.data.getParserForType();
+        @Override
+        public MapEntry<K, V> parsePartialFrom(
+            CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+            throws InvalidProtocolBufferException {
+          MapEntryLite<K, V> data =
+              dataParser.parsePartialFrom(input, extensionRegistry);
+          return new MapEntry<K, V>(thisMetadata, data);
+        }
+        
+      };
+    }
+  }
+  
+  private final Metadata<K, V> metadata;
+  private final MapEntryLite<K, V> data;
+  
+  /** Create a default MapEntry instance. */
+  private MapEntry(Descriptor descriptor,
+      WireFormat.FieldType keyType, K defaultKey,
+      WireFormat.FieldType valueType, V defaultValue) {
+    this.data = MapEntryLite.newDefaultInstance(
+        keyType, defaultKey, valueType, defaultValue);
+    this.metadata = new Metadata<K, V>(descriptor, this); 
+  }
+  
+  /** Create a new MapEntry message. */
+  private MapEntry(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
+    this.metadata = metadata;
+    this.data = data;
+  }
+  
+  /**
+   * Create a default MapEntry instance. A default MapEntry instance should be
+   * created only once for each map entry message type. Generated code should
+   * store the created default instance and use it later to create new MapEntry
+   * messages of the same type. 
+   */
+  public static <K, V> MapEntry<K, V> newDefaultInstance(
+      Descriptor descriptor,
+      WireFormat.FieldType keyType, K defaultKey,
+      WireFormat.FieldType valueType, V defaultValue) {
+    return new MapEntry<K, V>(
+        descriptor, keyType, defaultKey, valueType, defaultValue);
+  }
+  
+  public K getKey() {
+    return data.getKey();
+  }
+  
+  public V getValue() {
+    return data.getValue();
+  }
+  
+  @Override
+  public int getSerializedSize() {
+    return data.getSerializedSize();
+  }
+  
+  @Override
+  public void writeTo(CodedOutputStream output) throws IOException {
+    data.writeTo(output);
+  }
+  
+  @Override
+  public boolean isInitialized() {
+    return data.isInitialized();
+  }
+  
+  @Override
+  public Parser<MapEntry<K, V>> getParserForType() {
+    return metadata.parser;
+  }
+
+  @Override
+  public Builder<K, V> newBuilderForType() {
+    return new Builder<K, V>(metadata);
+  }
+  
+  @Override
+  public Builder<K, V> toBuilder() {
+    return new Builder<K, V>(metadata, data);
+  }
+
+  @Override
+  public MapEntry<K, V> getDefaultInstanceForType() {
+    return metadata.defaultInstance;
+  }
+
+  @Override
+  public Descriptor getDescriptorForType() {
+    return metadata.descriptor;
+  }
+
+  @Override
+  public Map<FieldDescriptor, Object> getAllFields() {
+    final TreeMap<FieldDescriptor, Object> result =
+        new TreeMap<FieldDescriptor, Object>();
+    for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+      if (hasField(field)) {
+        result.put(field, getField(field));
+      }
+    }
+    return Collections.unmodifiableMap(result);
+  }
+  
+  private void checkFieldDescriptor(FieldDescriptor field) {
+    if (field.getContainingType() != metadata.descriptor) {
+      throw new RuntimeException(
+          "Wrong FieldDescriptor \"" + field.getFullName()
+          + "\" used in message \"" + metadata.descriptor.getFullName()); 
+    }
+  }
+
+  @Override
+  public boolean hasField(FieldDescriptor field) {
+    checkFieldDescriptor(field);;
+    // A MapEntry always contains two fields.
+    return true;
+  }
+
+  @Override
+  public Object getField(FieldDescriptor field) {
+    checkFieldDescriptor(field);
+    Object result = field.getNumber() == 1 ? getKey() : getValue();
+    // Convert enums to EnumValueDescriptor.
+    if (field.getType() == FieldDescriptor.Type.ENUM) {
+      result = field.getEnumType().findValueByNumberCreatingIfUnknown(
+          (java.lang.Integer) result);
+    }
+    return result;
+  }
+
+  @Override
+  public int getRepeatedFieldCount(FieldDescriptor field) {
+    throw new RuntimeException(
+        "There is no repeated field in a map entry message.");
+  }
+
+  @Override
+  public Object getRepeatedField(FieldDescriptor field, int index) {
+    throw new RuntimeException(
+        "There is no repeated field in a map entry message.");
+  }
+
+  @Override
+  public UnknownFieldSet getUnknownFields() {
+    return UnknownFieldSet.getDefaultInstance();
+  }
+
+  /**
+   * Builder to create {@link MapEntry} messages.
+   */
+  public static class Builder<K, V>
+      extends AbstractMessage.Builder<Builder<K, V>> {
+    private final Metadata<K, V> metadata;
+    private MapEntryLite<K, V> data;
+    private MapEntryLite.Builder<K, V> dataBuilder;
+    
+    private Builder(Metadata<K, V> metadata) {
+      this.metadata = metadata;
+      this.data = metadata.defaultInstance.data;
+      this.dataBuilder = null;
+    }
+    
+    private Builder(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
+      this.metadata = metadata;
+      this.data = data;
+      this.dataBuilder = null;
+    }
+    
+    public K getKey() {
+      return dataBuilder == null ? data.getKey() : dataBuilder.getKey();
+    }
+    
+    public V getValue() {
+      return dataBuilder == null ? data.getValue() : dataBuilder.getValue();
+    }
+    
+    private void ensureMutable() {
+      if (dataBuilder == null) {
+        dataBuilder = data.toBuilder();
+      }
+    }
+    
+    public Builder<K, V> setKey(K key) {
+      ensureMutable();
+      dataBuilder.setKey(key);
+      return this;
+    }
+    
+    public Builder<K, V> clearKey() {
+      ensureMutable();
+      dataBuilder.clearKey();
+      return this;
+    }
+    
+    public Builder<K, V> setValue(V value) {
+      ensureMutable();
+      dataBuilder.setValue(value);
+      return this;
+    }
+    
+    public Builder<K, V> clearValue() {
+      ensureMutable();
+      dataBuilder.clearValue();
+      return this;
+    }
+
+    @Override
+    public MapEntry<K, V> build() {
+      MapEntry<K, V> result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @Override
+    public MapEntry<K, V> buildPartial() {
+      if (dataBuilder != null) {
+        data = dataBuilder.buildPartial();
+        dataBuilder = null;
+      }
+      return new MapEntry<K, V>(metadata, data);
+    }
+
+    @Override
+    public Descriptor getDescriptorForType() {
+      return metadata.descriptor;
+    }
+    
+    private void checkFieldDescriptor(FieldDescriptor field) {
+      if (field.getContainingType() != metadata.descriptor) {
+        throw new RuntimeException(
+            "Wrong FieldDescriptor \"" + field.getFullName()
+            + "\" used in message \"" + metadata.descriptor.getFullName()); 
+      }
+    }
+
+    @Override
+    public com.google.protobuf.Message.Builder newBuilderForField(
+        FieldDescriptor field) {
+      checkFieldDescriptor(field);;
+      // This method should be called for message fields and in a MapEntry
+      // message only the value field can possibly be a message field.
+      if (field.getNumber() != 2
+          || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+        throw new RuntimeException(
+            "\"" + field.getFullName() + "\" is not a message value field.");
+      }
+      return ((Message) data.getValue()).newBuilderForType();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Builder<K, V> setField(FieldDescriptor field, Object value) {
+      checkFieldDescriptor(field);
+      if (field.getNumber() == 1) {
+        setKey((K) value);
+      } else {
+        if (field.getType() == FieldDescriptor.Type.ENUM) {
+          value = ((EnumValueDescriptor) value).getNumber();
+        }
+        setValue((V) value);
+      }
+      return this;
+    }
+
+    @Override
+    public Builder<K, V> clearField(FieldDescriptor field) {
+      checkFieldDescriptor(field);
+      if (field.getNumber() == 1) {
+        clearKey();
+      } else {
+        clearValue();
+      }
+      return this;
+    }
+
+    @Override
+    public Builder<K, V> setRepeatedField(FieldDescriptor field, int index,
+        Object value) {
+      throw new RuntimeException(
+          "There is no repeated field in a map entry message.");
+    }
+
+    @Override
+    public Builder<K, V> addRepeatedField(FieldDescriptor field, Object value) {
+      throw new RuntimeException(
+          "There is no repeated field in a map entry message.");
+    }
+
+    @Override
+    public Builder<K, V> setUnknownFields(UnknownFieldSet unknownFields) {
+      // Unknown fields are discarded for MapEntry message.
+      return this;
+    }
+
+    @Override
+    public MapEntry<K, V> getDefaultInstanceForType() {
+      return metadata.defaultInstance;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      if (dataBuilder != null) {
+        return dataBuilder.isInitialized();
+      } else {
+        return data.isInitialized();
+      }
+    }
+
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      final TreeMap<FieldDescriptor, Object> result =
+          new TreeMap<FieldDescriptor, Object>();
+      for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+        if (hasField(field)) {
+          result.put(field, getField(field));
+        }
+      }
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public boolean hasField(FieldDescriptor field) {
+      checkFieldDescriptor(field);
+      return true;
+    }
+
+    @Override
+    public Object getField(FieldDescriptor field) {
+      checkFieldDescriptor(field);
+      Object result = field.getNumber() == 1 ? getKey() : getValue();
+      // Convert enums to EnumValueDescriptor.
+      if (field.getType() == FieldDescriptor.Type.ENUM) {
+        result = field.getEnumType().findValueByNumberCreatingIfUnknown(
+            (java.lang.Integer) result);
+      }
+      return result;
+    }
+
+    @Override
+    public int getRepeatedFieldCount(FieldDescriptor field) {
+      throw new RuntimeException(
+          "There is no repeated field in a map entry message.");
+    }
+    
+    @Override
+    public Object getRepeatedField(FieldDescriptor field, int index) {
+      throw new RuntimeException(
+          "There is no repeated field in a map entry message.");
+    }
+    
+    @Override
+    public UnknownFieldSet getUnknownFields() {
+      return UnknownFieldSet.getDefaultInstance();
+    }
+
+    @Override
+    public Builder<K, V> clone() {
+      if (dataBuilder == null) {
+        return new Builder<K, V>(metadata, data);
+      } else {
+        return new Builder<K, V>(metadata, dataBuilder.build());
+      }
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntryLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
new file mode 100644
index 0000000..12c64ab
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
@@ -0,0 +1,337 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * Implements the lite version of map entry messages.
+ * 
+ * This class serves as an utility class to help do serialization/parsing of
+ * map entries. It's used in generated code and also in the full version
+ * MapEntry message.
+ * 
+ * Protobuf internal. Users shouldn't use.
+ */
+public class MapEntryLite<K, V>
+    extends AbstractMessageLite<MapEntryLite<K, V>, MapEntryLite.Builder<K, V>> {
+  private static class Metadata<K, V> {
+    public final MapEntryLite<K, V> defaultInstance;
+    public final WireFormat.FieldType keyType;
+    public final WireFormat.FieldType valueType;
+    public final Parser<MapEntryLite<K, V>> parser;
+    public Metadata(
+        MapEntryLite<K, V> defaultInstance,
+        WireFormat.FieldType keyType,
+        WireFormat.FieldType valueType) {
+      this.defaultInstance = defaultInstance; 
+      this.keyType = keyType;
+      this.valueType = valueType;
+      final Metadata<K, V> finalThis = this;
+      this.parser = new AbstractParser<MapEntryLite<K, V>>() {
+        @Override
+        public MapEntryLite<K, V> parsePartialFrom(
+            CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+            throws InvalidProtocolBufferException {
+          return new MapEntryLite<K, V>(finalThis, input, extensionRegistry);
+        }
+      };
+    }
+  }
+  
+  private static final int KEY_FIELD_NUMBER = 1;
+  private static final int VALUE_FIELD_NUMBER = 2;
+  
+  private final Metadata<K, V> metadata;
+  private final K key;
+  private final V value;
+  
+  /** Creates a default MapEntryLite message instance. */
+  private MapEntryLite(
+      WireFormat.FieldType keyType, K defaultKey,
+      WireFormat.FieldType valueType, V defaultValue) {
+    this.metadata = new Metadata<K, V>(this, keyType, valueType);
+    this.key = defaultKey;
+    this.value = defaultValue;
+  }
+  
+  /** Creates a new MapEntryLite message. */
+  private MapEntryLite(Metadata<K, V> metadata, K key, V value) {
+    this.metadata = metadata;
+    this.key = key;
+    this.value = value;
+  }
+  
+  public K getKey() {
+    return key;
+  }
+  
+  public V getValue() {
+    return value;
+  }
+
+  /**
+   * Creates a default MapEntryLite message instance.
+   * 
+   * This method is used by generated code to create the default instance for
+   * a map entry message. The created default instance should be used to create
+   * new map entry messages of the same type. For each map entry message, only
+   * one default instance should be created. 
+   */
+  public static <K, V> MapEntryLite<K, V> newDefaultInstance(
+      WireFormat.FieldType keyType, K defaultKey,
+      WireFormat.FieldType valueType, V defaultValue) {
+    return new MapEntryLite<K, V>(
+        keyType, defaultKey, valueType, defaultValue);
+  }
+  
+  @Override
+  public void writeTo(CodedOutputStream output) throws IOException {
+    writeField(KEY_FIELD_NUMBER, metadata.keyType, key, output);
+    writeField(VALUE_FIELD_NUMBER, metadata.valueType, value, output);
+  }
+
+  private void writeField(
+      int number, WireFormat.FieldType type, Object value,
+      CodedOutputStream output) throws IOException {
+    output.writeTag(number, type.getWireType());
+    FieldSet.writeElementNoTag(output, type, value);
+  }
+
+  private volatile int cachedSerializedSize = -1;
+  @Override
+  public int getSerializedSize() {
+    if (cachedSerializedSize != -1) {
+      return cachedSerializedSize;
+    }
+    int size = 0;
+    size += getFieldSize(KEY_FIELD_NUMBER, metadata.keyType, key);
+    size += getFieldSize(VALUE_FIELD_NUMBER, metadata.valueType, value);
+    cachedSerializedSize = size;
+    return size;
+  }
+
+  private int getFieldSize(
+      int number, WireFormat.FieldType type, Object value) {
+    return CodedOutputStream.computeTagSize(number)
+        + FieldSet.computeElementSizeNoTag(type, value);
+  }
+  
+  /** Parsing constructor. */
+  private MapEntryLite(
+      Metadata<K, V> metadata,
+      CodedInputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    try {
+      K key = metadata.defaultInstance.key;
+      V value = metadata.defaultInstance.value;
+      while (true) {
+        int tag = input.readTag();
+        if (tag == 0) {
+          break;
+        }
+        if (tag == WireFormat.makeTag(
+                KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
+          key = mergeField(
+              input, extensionRegistry, metadata.keyType, key);
+        } else if (tag == WireFormat.makeTag(
+                       VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
+          value = mergeField(
+              input, extensionRegistry, metadata.valueType, value);
+        } else {
+          if (!input.skipField(tag)) {
+            break;
+          }
+        }
+      }
+      this.metadata = metadata;
+      this.key = key;
+      this.value = value;
+    } catch (InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (IOException e) {
+      throw new InvalidProtocolBufferException(e.getMessage())
+          .setUnfinishedMessage(this);
+    }
+  }
+  
+  @SuppressWarnings("unchecked")
+  private <T> T mergeField(
+      CodedInputStream input, ExtensionRegistryLite extensionRegistry,
+      WireFormat.FieldType type, T value) throws IOException {
+    switch (type) {
+      case MESSAGE:
+        MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder();
+        input.readMessage(subBuilder, extensionRegistry);
+        return (T) subBuilder.buildPartial();
+      case ENUM:
+        return (T) (java.lang.Integer) input.readEnum();
+      case GROUP:
+        throw new RuntimeException("Groups are not allowed in maps.");
+      default:
+        return (T) FieldSet.readPrimitiveField(input, type, true);
+    }
+  }
+
+  @Override
+  public Parser<MapEntryLite<K, V>> getParserForType() {
+    return metadata.parser;
+  }
+
+  @Override
+  public Builder<K, V> newBuilderForType() {
+    return new Builder<K, V>(metadata);
+  }
+
+  @Override
+  public Builder<K, V> toBuilder() {
+    return new Builder<K, V>(metadata, key, value);
+  }
+
+  @Override
+  public MapEntryLite<K, V> getDefaultInstanceForType() {
+    return metadata.defaultInstance;
+  }
+
+  @Override
+  public boolean isInitialized() {
+    if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
+      return ((MessageLite) value).isInitialized();
+    }
+    return true;
+  }
+
+  /**
+   * Builder used to create {@link MapEntryLite} messages.
+   */
+  public static class Builder<K, V>
+      extends AbstractMessageLite.Builder<MapEntryLite<K, V>, Builder<K, V>> {
+    private final Metadata<K, V> metadata;
+    private K key;
+    private V value;
+    
+    private Builder(Metadata<K, V> metadata) {
+      this.metadata = metadata;
+      this.key = metadata.defaultInstance.key;
+      this.value = metadata.defaultInstance.value;
+    }
+    
+    public K getKey() {
+      return key;
+    }
+    
+    public V getValue() {
+      return value;
+    }
+    
+    public Builder<K, V> setKey(K key) {
+      this.key = key;
+      return this;
+    }
+    
+    public Builder<K, V> setValue(V value) {
+      this.value = value;
+      return this;
+    }
+    
+    public Builder<K, V> clearKey() {
+      this.key = metadata.defaultInstance.key;
+      return this;
+    }
+    
+    public Builder<K, V> clearValue() {
+      this.value = metadata.defaultInstance.value;
+      return this;
+    }
+
+    @Override
+    public Builder<K, V> clear() {
+      this.key = metadata.defaultInstance.key;
+      this.value = metadata.defaultInstance.value;
+      return this;
+    }
+
+    @Override
+    public MapEntryLite<K, V> build() {
+      MapEntryLite<K, V> result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @Override
+    public MapEntryLite<K, V> buildPartial() {
+      return new MapEntryLite<K, V>(metadata, key, value);
+    }
+
+    @Override
+    public MessageLite getDefaultInstanceForType() {
+      return metadata.defaultInstance;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
+        return ((MessageLite) value).isInitialized();
+      }
+      return true;
+    }
+
+    private Builder(Metadata<K, V> metadata, K key, V value) {
+      this.metadata = metadata;
+      this.key = key;
+      this.value = value;
+    }
+    
+    @Override
+    public Builder<K, V> clone() {
+      return new Builder<K, V>(metadata, key, value);
+    }
+
+    @Override
+    public Builder<K, V> mergeFrom(
+        CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      MapEntryLite<K, V> entry =
+          new MapEntryLite<K, V>(metadata, input, extensionRegistry);
+      this.key = entry.key;
+      this.value = entry.value;
+      return this;
+    }
+
+    @Override
+    protected Builder<K, V> internalMergeFrom(MapEntryLite<K, V> message) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapField.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapField.java
new file mode 100644
index 0000000..907f0f7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapField.java
@@ -0,0 +1,289 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.MapFieldLite.MutatabilityAwareMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal representation of map fields in generated messages.
+ * 
+ * This class supports accessing the map field as a {@link Map} to be used in
+ * generated API and also supports accessing the field as a {@link List} to be
+ * used in reflection API. It keeps track of where the data is currently stored
+ * and do necessary conversions between map and list.  
+ * 
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ * 
+ * THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap()
+ * and getList() concurrently in multiple threads. If write-access is needed,
+ * all access must be synchronized.
+ */
+public class MapField<K, V> implements MutabilityOracle {
+  /**
+   * Indicates where the data of this map field is currently stored.
+   * 
+   * MAP: Data is stored in mapData.
+   * LIST: Data is stored in listData.
+   * BOTH: mapData and listData have the same data.
+   *
+   * When the map field is accessed (through generated API or reflection API),
+   * it will shift between these 3 modes:
+   * 
+   *          getMap()   getList()   getMutableMap()   getMutableList()
+   *   MAP      MAP        BOTH          MAP               LIST
+   *   LIST     BOTH       LIST          MAP               LIST
+   *   BOTH     BOTH       BOTH          MAP               LIST
+   *   
+   * As the map field changes its mode, the list/map reference returned in a
+   * previous method call may be invalidated. 
+   */
+  private enum StorageMode {MAP, LIST, BOTH}
+
+  private volatile boolean isMutable;
+  private volatile StorageMode mode;
+  private MutatabilityAwareMap<K, V> mapData;
+  private List<Message> listData;
+  
+  // Convert between a map entry Message and a key-value pair.
+  private static interface Converter<K, V> {
+    Message convertKeyAndValueToMessage(K key, V value);
+    void convertMessageToKeyAndValue(Message message, Map<K, V> map);
+    
+    Message getMessageDefaultInstance();
+  }
+  
+  private static class ImmutableMessageConverter<K, V> implements Converter<K, V> {
+    private final MapEntry<K, V> defaultEntry;
+    public ImmutableMessageConverter(MapEntry<K, V> defaultEntry) {
+      this.defaultEntry = defaultEntry;
+    }
+    
+    @Override
+    public Message convertKeyAndValueToMessage(K key, V value) {
+      return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
+    }
+    
+    @Override
+    public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+      MapEntry<K, V> entry = (MapEntry<K, V>) message;
+      map.put(entry.getKey(), entry.getValue());
+    }
+
+    @Override
+    public Message getMessageDefaultInstance() {
+      return defaultEntry;
+    }
+  }
+  
+
+  private final Converter<K, V> converter;
+  
+  private MapField(
+      Converter<K, V> converter,
+      StorageMode mode,
+      Map<K, V> mapData) {
+    this.converter = converter;
+    this.isMutable = true;
+    this.mode = mode;
+    this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+    this.listData = null;
+  }
+    
+  private MapField(
+      MapEntry<K, V> defaultEntry,
+      StorageMode mode,
+      Map<K, V> mapData) {
+    this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData);
+  }
+  
+  
+  /** Returns an immutable empty MapField. */
+  public static <K, V> MapField<K, V> emptyMapField(
+      MapEntry<K, V> defaultEntry) {
+    return new MapField<K, V>(
+        defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap());
+  }
+  
+  
+  /** Creates a new mutable empty MapField. */
+  public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) {
+    return new MapField<K, V>(
+        defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
+  }
+  
+  
+  private Message convertKeyAndValueToMessage(K key, V value) {
+    return converter.convertKeyAndValueToMessage(key, value);
+  }
+  
+  @SuppressWarnings("unchecked")
+  private void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+    converter.convertMessageToKeyAndValue(message, map);
+  }
+
+  private List<Message> convertMapToList(MutatabilityAwareMap<K, V> mapData) {
+    List<Message> listData = new ArrayList<Message>();
+    for (Map.Entry<K, V> entry : mapData.entrySet()) {
+      listData.add(
+          convertKeyAndValueToMessage(
+              entry.getKey(), entry.getValue()));
+    }
+    return listData;
+  }
+
+  private MutatabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
+    Map<K, V> mapData = new LinkedHashMap<K, V>();
+    for (Message item : listData) {
+      convertMessageToKeyAndValue(item, mapData);
+    }
+    return new MutatabilityAwareMap<K, V>(this, mapData);
+  }
+  
+  /** Returns the content of this MapField as a read-only Map. */
+  public Map<K, V> getMap() {
+    if (mode == StorageMode.LIST) {
+      synchronized (this) {
+        if (mode == StorageMode.LIST) {
+          mapData = convertListToMap(listData);
+          mode = StorageMode.BOTH;
+        }
+      }
+    }
+    return Collections.unmodifiableMap(mapData);
+  }
+  
+  /** Gets a mutable Map view of this MapField. */
+  public Map<K, V> getMutableMap() {
+    if (mode != StorageMode.MAP) {
+      if (mode == StorageMode.LIST) {
+        mapData = convertListToMap(listData);
+      }
+      listData = null;
+      mode = StorageMode.MAP; 
+    }
+    return mapData;
+  }
+  
+  public void mergeFrom(MapField<K, V> other) {
+    getMutableMap().putAll(MapFieldLite.copy(other.getMap()));
+  }
+  
+  public void clear() {
+    mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>());
+    mode = StorageMode.MAP;
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Override
+  public boolean equals(Object object) {
+    if (!(object instanceof MapField)) {
+      return false;
+    }
+    MapField<K, V> other = (MapField<K, V>) object;
+    return MapFieldLite.<K, V>equals(getMap(), other.getMap());
+  }
+  
+  @Override
+  public int hashCode() {
+    return MapFieldLite.<K, V>calculateHashCodeForMap(getMap());
+  }
+  
+  /** Returns a deep copy of this MapField. */
+  public MapField<K, V> copy() {
+    return new MapField<K, V>(
+        converter, StorageMode.MAP, MapFieldLite.copy(getMap()));
+  }
+  
+  /** Gets the content of this MapField as a read-only List. */
+  List<Message> getList() {
+    if (mode == StorageMode.MAP) {
+      synchronized (this) {
+        if (mode == StorageMode.MAP) {
+          listData = convertMapToList(mapData);
+          mode = StorageMode.BOTH;
+        }
+      }
+    }
+    return Collections.unmodifiableList(listData);
+  }
+  
+  /** Gets a mutable List view of this MapField. */
+  List<Message> getMutableList() {
+    if (mode != StorageMode.LIST) {
+      if (mode == StorageMode.MAP) {
+        listData = convertMapToList(mapData);
+      }
+      mapData = null;
+      mode = StorageMode.LIST;
+    }
+    return listData;
+  }
+  
+  /**
+   * Gets the default instance of the message stored in the list view of this
+   * map field.
+   */
+  Message getMapEntryMessageDefaultInstance() {
+    return converter.getMessageDefaultInstance();
+  }
+  
+  /**
+   * Makes this list immutable. All subsequent modifications will throw an
+   * {@link UnsupportedOperationException}.
+   */
+  public void makeImmutable() {
+    isMutable = false;
+  }
+  
+  /**
+   * Returns whether this field can be modified.
+   */
+  public boolean isMutable() {
+    return isMutable;
+  }
+  
+  /* (non-Javadoc)
+   * @see com.google.protobuf.MutabilityOracle#ensureMutable()
+   */
+  @Override
+  public void ensureMutable() {
+    if (!isMutable()) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapFieldLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
new file mode 100644
index 0000000..960b633
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -0,0 +1,549 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.EnumLite;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Internal representation of map fields in generated lite-runtime messages.
+ * 
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ */
+public final class MapFieldLite<K, V> implements MutabilityOracle {
+  private MutatabilityAwareMap<K, V> mapData;
+  private boolean isMutable;
+  
+  private MapFieldLite(Map<K, V> mapData) {
+    this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+    this.isMutable = true;
+  }
+  
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static final MapFieldLite EMPTY_MAP_FIELD =
+      new MapFieldLite(Collections.emptyMap());
+  static {
+    EMPTY_MAP_FIELD.makeImmutable();
+  }
+  
+  /** Returns an singleton immutable empty MapFieldLite instance. */
+  @SuppressWarnings({"unchecked", "cast"})
+  public static <K, V> MapFieldLite<K, V> emptyMapField() {
+    return (MapFieldLite<K, V>) EMPTY_MAP_FIELD;
+  }
+  
+  /** Creates a new MapFieldLite instance. */
+  public static <K, V> MapFieldLite<K, V> newMapField() {
+    return new MapFieldLite<K, V>(new LinkedHashMap<K, V>());
+  }
+  
+  /** Gets the content of this MapField as a read-only Map. */
+  public Map<K, V> getMap() {
+    return Collections.unmodifiableMap(mapData);
+  }
+  
+  /** Gets a mutable Map view of this MapField. */
+  public Map<K, V> getMutableMap() {
+    return mapData;
+  }
+  
+  public void mergeFrom(MapFieldLite<K, V> other) {
+    mapData.putAll(copy(other.mapData));
+  }
+  
+  public void clear() {
+    mapData.clear();
+  }
+  
+  private static boolean equals(Object a, Object b) {
+    if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[]) a, (byte[]) b);
+    }
+    return a.equals(b);
+  }
+  
+  /**
+   * Checks whether two {@link Map}s are equal. We don't use the default equals
+   * method of {@link Map} because it compares by identity not by content for
+   * byte arrays.
+   */
+  static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+    if (a == b) {
+      return true;
+    }
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (Map.Entry<K, V> entry : a.entrySet()) {
+      if (!b.containsKey(entry.getKey())) {
+        return false;
+      }
+      if (!equals(entry.getValue(), b.get(entry.getKey()))) {
+        return false;
+      }
+    }
+    return true;
+  }
+  
+  /**
+   * Checks whether two map fields are equal.
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public boolean equals(Object object) {
+    if (!(object instanceof MapFieldLite)) {
+      return false;
+    }
+    MapFieldLite<K, V> other = (MapFieldLite<K, V>) object;
+    return equals(mapData, other.mapData);
+  }
+  
+  private static int calculateHashCodeForObject(Object a) {
+    if (a instanceof byte[]) {
+      return Internal.hashCode((byte[]) a);
+    }
+    // Enums should be stored as integers internally.
+    if (a instanceof EnumLite) {
+      throw new UnsupportedOperationException();
+    }
+    return a.hashCode();
+  }
+
+  /**
+   * Calculates the hash code for a {@link Map}. We don't use the default hash
+   * code method of {@link Map} because for byte arrays and protobuf enums it
+   * use {@link Object#hashCode()}.
+   */
+  static <K, V> int calculateHashCodeForMap(Map<K, V> a) {
+    int result = 0;
+    for (Map.Entry<K, V> entry : a.entrySet()) {
+      result += calculateHashCodeForObject(entry.getKey())
+          ^ calculateHashCodeForObject(entry.getValue());
+    }
+    return result;    
+  }
+  
+  @Override
+  public int hashCode() {
+    return calculateHashCodeForMap(mapData);
+  }
+  
+  private static Object copy(Object object) {
+    if (object instanceof byte[]) {
+      byte[] data = (byte[]) object;
+      return Arrays.copyOf(data, data.length);
+    }
+    return object;
+  }
+  
+  /**
+   * Makes a deep copy of a {@link Map}. Immutable objects in the map will be
+   * shared (e.g., integers, strings, immutable messages) and mutable ones will
+   * have a copy (e.g., byte arrays, mutable messages).
+   */
+  @SuppressWarnings("unchecked")
+  static <K, V> Map<K, V> copy(Map<K, V> map) {
+    Map<K, V> result = new LinkedHashMap<K, V>();
+    for (Map.Entry<K, V> entry : map.entrySet()) {
+      result.put(entry.getKey(), (V) copy(entry.getValue()));
+    }
+    return result;
+  }
+  
+  /** Returns a deep copy of this map field. */
+  public MapFieldLite<K, V> copy() {
+    return new MapFieldLite<K, V>(copy(mapData));
+  }
+  
+  /**
+   * Makes this field immutable. All subsequent modifications will throw an
+   * {@link UnsupportedOperationException}.
+   */
+  public void makeImmutable() {
+    isMutable = false;
+  }
+  
+  /**
+   * Returns whether this field can be modified.
+   */
+  public boolean isMutable() {
+    return isMutable;
+  }
+  
+  @Override
+  public void ensureMutable() {
+    if (!isMutable()) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  /**
+   * An internal map that checks for mutability before delegating.
+   */
+  static class MutatabilityAwareMap<K, V> implements Map<K, V> {    
+    private final MutabilityOracle mutabilityOracle;
+    private final Map<K, V> delegate;
+    
+    MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate) {
+      this.mutabilityOracle = mutabilityOracle;
+      this.delegate = delegate;
+    }
+
+    @Override
+    public int size() {
+      return delegate.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return delegate.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+      return delegate.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(Object value) {
+      return delegate.containsValue(value);
+    }
+
+    @Override
+    public V get(Object key) {
+      return delegate.get(key);
+    }
+
+    @Override
+    public V put(K key, V value) {
+      mutabilityOracle.ensureMutable();
+      return delegate.put(key, value);
+    }
+
+    @Override
+    public V remove(Object key) {
+      mutabilityOracle.ensureMutable();
+      return delegate.remove(key);
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> m) {
+      mutabilityOracle.ensureMutable();
+      delegate.putAll(m);
+    }
+
+    @Override
+    public void clear() {
+      mutabilityOracle.ensureMutable();
+      delegate.clear();
+    }
+
+    @Override
+    public Set<K> keySet() {
+      return new MutatabilityAwareSet<K>(mutabilityOracle, delegate.keySet());
+    }
+
+    @Override
+    public Collection<V> values() {
+      return new MutatabilityAwareCollection<V>(mutabilityOracle, delegate.values());
+    }
+
+    @Override
+    public Set<java.util.Map.Entry<K, V>> entrySet() {
+      return new MutatabilityAwareSet<Entry<K, V>>(mutabilityOracle, delegate.entrySet());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      return delegate.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+      return delegate.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return delegate.toString();
+    }
+  }
+
+  /**
+   * An internal collection that checks for mutability before delegating.
+   */
+  private static class MutatabilityAwareCollection<E> implements Collection<E> {
+    private final MutabilityOracle mutabilityOracle;
+    private final Collection<E> delegate;
+    
+    MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate) {
+      this.mutabilityOracle = mutabilityOracle;
+      this.delegate = delegate;
+    }
+
+    @Override
+    public int size() {
+      return delegate.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return delegate.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+      return delegate.contains(o);
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+    }
+
+    @Override
+    public Object[] toArray() {
+      return delegate.toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+      return delegate.toArray(a);
+    }
+
+    @Override
+    public boolean add(E e) {
+      // Unsupported operation in the delegate.
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean remove(Object o) {
+      mutabilityOracle.ensureMutable();
+      return delegate.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+      return delegate.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+      // Unsupported operation in the delegate.
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+      mutabilityOracle.ensureMutable();
+      return delegate.removeAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+      mutabilityOracle.ensureMutable();
+      return delegate.retainAll(c);
+    }
+
+    @Override
+    public void clear() {
+      mutabilityOracle.ensureMutable();
+      delegate.clear();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      return delegate.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+      return delegate.hashCode();
+    }
+    
+    @Override
+    public String toString() {
+      return delegate.toString();
+    }
+  }
+
+  /**
+   * An internal set that checks for mutability before delegating.
+   */
+  private static class MutatabilityAwareSet<E> implements Set<E> {
+    private final MutabilityOracle mutabilityOracle;
+    private final Set<E> delegate;
+    
+    MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate) {
+      this.mutabilityOracle = mutabilityOracle;
+      this.delegate = delegate;
+    }
+
+    @Override
+    public int size() {
+      return delegate.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return delegate.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+      return delegate.contains(o);
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+      return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+    }
+
+    @Override
+    public Object[] toArray() {
+      return delegate.toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+      return delegate.toArray(a);
+    }
+
+    @Override
+    public boolean add(E e) {
+      mutabilityOracle.ensureMutable();
+      return delegate.add(e);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+      mutabilityOracle.ensureMutable();
+      return delegate.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+      return delegate.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+      mutabilityOracle.ensureMutable();
+      return delegate.addAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+      mutabilityOracle.ensureMutable();
+      return delegate.retainAll(c);
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+      mutabilityOracle.ensureMutable();
+      return delegate.removeAll(c);
+    }
+
+    @Override
+    public void clear() {
+      mutabilityOracle.ensureMutable();
+      delegate.clear();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      return delegate.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+      return delegate.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return delegate.toString();
+    }
+  }
+  
+  /**
+   * An internal iterator that checks for mutability before delegating.
+   */
+  private static class MutatabilityAwareIterator<E> implements Iterator<E> {
+    private final MutabilityOracle mutabilityOracle;
+    private final Iterator<E> delegate;
+    
+    MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate) {
+      this.mutabilityOracle = mutabilityOracle;
+      this.delegate = delegate;
+    }
+
+    @Override
+    public boolean hasNext() {
+      return delegate.hasNext();
+    }
+
+    @Override
+    public E next() {
+      return delegate.next();
+    }
+
+    @Override
+    public void remove() {
+      mutabilityOracle.ensureMutable();
+      delegate.remove();
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+      return delegate.equals(obj);
+    }
+    
+    @Override
+    public int hashCode() {
+      return delegate.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return delegate.toString();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Message.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Message.java
new file mode 100644
index 0000000..94590fb
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Message.java
@@ -0,0 +1,292 @@
+// 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.
+
+// TODO(kenton):  Use generics?  E.g. Builder<BuilderType extends Builder>, then
+//   mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ * <p>
+ * See also {@link MessageLite}, which defines most of the methods that typical
+ * users care about.  {@link Message} adds to it methods that are not available
+ * in the "lite" runtime.  The biggest added features are introspection and
+ * reflection -- i.e., getting descriptors for the message type and accessing
+ * the field values dynamically.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface Message extends MessageLite, MessageOrBuilder {
+
+  // (From MessageLite, re-declared here only for return type covariance.)
+  @Override
+  Parser<? extends Message> getParserForType();
+
+
+  // -----------------------------------------------------------------
+  // Comparison and hashing
+
+  /**
+   * Compares the specified object with this message for equality.  Returns
+   * {@code true} if the given object is a message of the same type (as
+   * defined by {@code getDescriptorForType()}) and has identical values for
+   * all of its fields.  Subclasses must implement this; inheriting
+   * {@code Object.equals()} is incorrect.
+   *
+   * @param other object to be compared for equality with this message
+   * @return {@code true} if the specified object is equal to this message
+   */
+  @Override
+  boolean equals(Object other);
+
+  /**
+   * Returns the hash code value for this message.  The hash code of a message
+   * should mix the message's type (object identity of the descriptor) with its
+   * contents (known and unknown field values).  Subclasses must implement this;
+   * inheriting {@code Object.hashCode()} is incorrect.
+   *
+   * @return the hash code value for this message
+   * @see Map#hashCode()
+   */
+  @Override
+  int hashCode();
+
+  // -----------------------------------------------------------------
+  // Convenience methods.
+
+  /**
+   * Converts the message to a string in protocol buffer text format. This is
+   * just a trivial wrapper around {@link
+   * TextFormat#printToString(MessageOrBuilder)}.
+   */
+  @Override
+  String toString();
+
+  // =================================================================
+  // Builders
+
+  // (From MessageLite, re-declared here only for return type covariance.)
+  @Override
+  Builder newBuilderForType();
+
+  @Override
+  Builder toBuilder();
+
+  /**
+   * Abstract interface implemented by Protocol Message builders.
+   */
+  interface Builder extends MessageLite.Builder, MessageOrBuilder {
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
+    @Override
+    Builder clear();
+
+    /**
+     * Merge {@code other} into the message being built.  {@code other} must
+     * have the exact same type as {@code this} (i.e.
+     * {@code getDescriptorForType() == other.getDescriptorForType()}).
+     *
+     * Merging occurs as follows.  For each field:<br>
+     * * For singular primitive fields, if the field is set in {@code other},
+     *   then {@code other}'s value overwrites the value in this message.<br>
+     * * For singular message fields, if the field is set in {@code other},
+     *   it is merged into the corresponding sub-message of this message
+     *   using the same merging rules.<br>
+     * * For repeated fields, the elements in {@code other} are concatenated
+     *   with the elements in this message.
+     * * For oneof groups, if the other message has one of the fields set,
+     *   the group of this message is cleared and replaced by the field
+     *   of the other message, so that the oneof constraint is preserved.
+     *
+     * This is equivalent to the {@code Message::MergeFrom} method in C++.
+     */
+    Builder mergeFrom(Message other);
+
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
+    @Override
+    Message build();
+
+    @Override
+    Message buildPartial();
+
+    @Override
+    Builder clone();
+
+    @Override
+    Builder mergeFrom(CodedInputStream input) throws IOException;
+
+    @Override
+    Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    /**
+     * Get the message's type's descriptor.
+     * See {@link Message#getDescriptorForType()}.
+     */
+    @Override
+    Descriptors.Descriptor getDescriptorForType();
+
+    /**
+     * Create a Builder for messages of the appropriate type for the given
+     * field.  Messages built with this can then be passed to setField(),
+     * setRepeatedField(), or addRepeatedField().
+     */
+    Builder newBuilderForField(Descriptors.FieldDescriptor field);
+
+    /**
+     * Get a nested builder instance for the given field.
+     * <p>
+     * Normally, we hold a reference to the immutable message object for the
+     * message type field. Some implementations(the generated message builders),
+     * however, can also hold a reference to the builder object (a nested
+     * builder) for the field.
+     * <p>
+     * If the field is already backed up by a nested builder, the nested builder
+     * will be returned. Otherwise, a new field builder will be created and
+     * returned. The original message field (if exist) will be merged into the
+     * field builder, which will then be nested into its parent builder.
+     * <p>
+     * NOTE: implementations that do not support nested builders will throw
+     * <code>UnsupportedOperationException</code>.
+     */
+    Builder getFieldBuilder(Descriptors.FieldDescriptor field);
+
+    /**
+     * Get a nested builder instance for the given repeated field instance.
+     * <p>
+     * Normally, we hold a reference to the immutable message object for the
+     * message type field. Some implementations(the generated message builders),
+     * however, can also hold a reference to the builder object (a nested
+     * builder) for the field.
+     * <p>
+     * If the field is already backed up by a nested builder, the nested builder
+     * will be returned. Otherwise, a new field builder will be created and
+     * returned. The original message field (if exist) will be merged into the
+     * field builder, which will then be nested into its parent builder.
+     * <p>
+     * NOTE: implementations that do not support nested builders will throw
+     * <code>UnsupportedOperationException</code>.
+     */
+    Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field,
+                                    int index);
+
+    /**
+     * Sets a field to the given value.  The value must be of the correct type
+     * for this field, i.e. the same type that
+     * {@link Message#getField(Descriptors.FieldDescriptor)} would return.
+     */
+    Builder setField(Descriptors.FieldDescriptor field, Object value);
+
+    /**
+     * Clears the field.  This is exactly equivalent to calling the generated
+     * "clear" accessor method corresponding to the field.
+     */
+    Builder clearField(Descriptors.FieldDescriptor field);
+
+    /**
+     * Clears the oneof.  This is exactly equivalent to calling the generated
+     * "clear" accessor method corresponding to the oneof.
+     */
+    Builder clearOneof(Descriptors.OneofDescriptor oneof);
+
+    /**
+     * Sets an element of a repeated field to the given value.  The value must
+     * be of the correct type for this field, i.e. the same type that
+     * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would
+     * return.
+     * @throws IllegalArgumentException The field is not a repeated field, or
+     *           {@code field.getContainingType() != getDescriptorForType()}.
+     */
+    Builder setRepeatedField(Descriptors.FieldDescriptor field,
+                             int index, Object value);
+
+    /**
+     * Like {@code setRepeatedField}, but appends the value as a new element.
+     * @throws IllegalArgumentException The field is not a repeated field, or
+     *           {@code field.getContainingType() != getDescriptorForType()}.
+     */
+    Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
+
+    /** Set the {@link UnknownFieldSet} for this message. */
+    Builder setUnknownFields(UnknownFieldSet unknownFields);
+
+    /**
+     * Merge some unknown fields into the {@link UnknownFieldSet} for this
+     * message.
+     */
+    Builder mergeUnknownFields(UnknownFieldSet unknownFields);
+
+    // ---------------------------------------------------------------
+    // Convenience methods.
+
+    // (From MessageLite.Builder, re-declared here only for return type
+    // covariance.)
+    @Override
+    Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(InputStream input) throws IOException;
+
+    @Override
+    Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    @Override
+    boolean mergeDelimitedFrom(InputStream input) throws IOException;
+
+    @Override
+    boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLite.java
new file mode 100644
index 0000000..88f531d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLite.java
@@ -0,0 +1,341 @@
+// 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.
+
+// TODO(kenton):  Use generics?  E.g. Builder<BuilderType extends Builder>, then
+//   mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * <p>This interface is implemented by all protocol message objects.  Non-lite
+ * messages additionally implement the Message interface, which is a subclass
+ * of MessageLite.  Use MessageLite instead when you only need the subset of
+ * features which it supports -- namely, nothing that uses descriptors or
+ * reflection.  You can instruct the protocol compiler to generate classes
+ * which implement only MessageLite, not the full Message interface, by adding
+ * the follow line to the .proto file:
+ * <pre>
+ *   option optimize_for = LITE_RUNTIME;
+ * </pre>
+ *
+ * <p>This is particularly useful on resource-constrained systems where the
+ * full protocol buffers runtime library is too big.
+ *
+ * <p>Note that on non-constrained systems (e.g. servers) when you need to link
+ * in lots of protocol definitions, a better way to reduce total code footprint
+ * is to use {@code optimize_for = CODE_SIZE}.  This will make the generated
+ * code smaller while still supporting all the same features (at the expense of
+ * speed).  {@code optimize_for = LITE_RUNTIME} is best when you only have a
+ * small number of message types linked into your binary, in which case the
+ * size of the protocol buffers runtime itself is the biggest problem.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface MessageLite extends MessageLiteOrBuilder {
+
+
+  /**
+   * Serializes the message and writes it to {@code output}.  This does not
+   * flush or close the stream.
+   */
+  void writeTo(CodedOutputStream output) throws IOException;
+
+  /**
+   * Get the number of bytes required to encode this message.  The result
+   * is only computed on the first call and memoized after that.
+   */
+  int getSerializedSize();
+
+
+  /**
+   * Gets the parser for a message of the same type as this message.
+   */
+  Parser<? extends MessageLite> getParserForType();
+
+  // -----------------------------------------------------------------
+  // Convenience methods.
+
+  /**
+   * Serializes the message to a {@code ByteString} and returns it. This is
+   * just a trivial wrapper around
+   * {@link #writeTo(CodedOutputStream)}.
+   */
+  ByteString toByteString();
+
+  /**
+   * Serializes the message to a {@code byte} array and returns it.  This is
+   * just a trivial wrapper around
+   * {@link #writeTo(CodedOutputStream)}.
+   */
+  byte[] toByteArray();
+
+  /**
+   * Serializes the message and writes it to {@code output}.  This is just a
+   * trivial wrapper around {@link #writeTo(CodedOutputStream)}.  This does
+   * not flush or close the stream.
+   * <p>
+   * NOTE:  Protocol Buffers are not self-delimiting.  Therefore, if you write
+   * any more data to the stream after the message, you must somehow ensure
+   * that the parser on the receiving end does not interpret this as being
+   * part of the protocol message.  This can be done e.g. by writing the size
+   * of the message before the data, then making sure to limit the input to
+   * that size on the receiving end (e.g. by wrapping the InputStream in one
+   * which limits the input).  Alternatively, just use
+   * {@link #writeDelimitedTo(OutputStream)}.
+   */
+  void writeTo(OutputStream output) throws IOException;
+
+  /**
+   * Like {@link #writeTo(OutputStream)}, but writes the size of the message
+   * as a varint before writing the data.  This allows more data to be written
+   * to the stream after the message without the need to delimit the message
+   * data yourself.  Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
+   * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
+   * to parse messages written by this method.
+   */
+  void writeDelimitedTo(OutputStream output) throws IOException;
+
+
+  // =================================================================
+  // Builders
+
+  /**
+   * Constructs a new builder for a message of the same type as this message.
+   */
+  Builder newBuilderForType();
+
+  /**
+   * Constructs a builder initialized with the current message.  Use this to
+   * derive a new message from the current one.
+   */
+  Builder toBuilder();
+
+  /**
+   * Abstract interface implemented by Protocol Message builders.
+   */
+  interface Builder extends MessageLiteOrBuilder, Cloneable {
+    /** Resets all fields to their default values. */
+    Builder clear();
+
+    /**
+     * Constructs the message based on the state of the Builder. Subsequent
+     * changes to the Builder will not affect the returned message.
+     * @throws UninitializedMessageException The message is missing one or more
+     *         required fields (i.e. {@link #isInitialized()} returns false).
+     *         Use {@link #buildPartial()} to bypass this check.
+     */
+    MessageLite build();
+
+    /**
+     * Like {@link #build()}, but does not throw an exception if the message
+     * is missing required fields.  Instead, a partial message is returned.
+     * Subsequent changes to the Builder will not affect the returned message.
+     */
+    MessageLite buildPartial();
+
+    /**
+     * Clones the Builder.
+     * @see Object#clone()
+     */
+    Builder clone();
+
+    /**
+     * Parses a message of this type from the input and merges it with this
+     * message.
+     *
+     * <p>Warning:  This does not verify that all required fields are present in
+     * the input message.  If you call {@link #build()} without setting all
+     * required fields, it will throw an {@link UninitializedMessageException},
+     * which is a {@code RuntimeException} and thus might not be caught.  There
+     * are a few good ways to deal with this:
+     * <ul>
+     *   <li>Call {@link #isInitialized()} to verify that all required fields
+     *       are set before building.
+     *   <li>Use {@code buildPartial()} to build, which ignores missing
+     *       required fields.
+     * </ul>
+     *
+     * <p>Note:  The caller should call
+     * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+     * verify that the last tag seen was the appropriate end-group tag,
+     * or zero for EOF.
+     */
+    Builder mergeFrom(CodedInputStream input) throws IOException;
+
+    /**
+     * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
+     * parses extensions.  The extensions that you want to be able to parse
+     * must be registered in {@code extensionRegistry}.  Extensions not in
+     * the registry will be treated as unknown fields.
+     */
+    Builder mergeFrom(CodedInputStream input,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws IOException;
+
+    // ---------------------------------------------------------------
+    // Convenience methods.
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(ByteString data,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(byte[] data, int off, int len)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(byte[] data,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(byte[] data, int off, int len,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws InvalidProtocolBufferException;
+
+    /**
+     * Parse a message of this type from {@code input} and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.  Note that this method always
+     * reads the <i>entire</i> input (unless it throws an exception).  If you
+     * want it to stop earlier, you will need to wrap your input in some
+     * wrapper stream that limits reading.  Or, use
+     * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message
+     * and {@link #mergeDelimitedFrom(InputStream)} to read it.
+     * <p>
+     * Despite usually reading the entire input, this does not close the stream.
+     *
+     * @return this
+     */
+    Builder mergeFrom(InputStream input) throws IOException;
+
+    /**
+     * Parse a message of this type from {@code input} and merge it with the
+     * message being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+     *
+     * @return this
+     */
+    Builder mergeFrom(InputStream input,
+                      ExtensionRegistryLite extensionRegistry)
+                      throws IOException;
+    
+    /**
+     * Merge {@code other} into the message being built.  {@code other} must
+     * have the exact same type as {@code this} (i.e.
+     * {@code getClass().equals(getDefaultInstanceForType().getClass())}).
+     *
+     * Merging occurs as follows.  For each field:<br>
+     * * For singular primitive fields, if the field is set in {@code other},
+     *   then {@code other}'s value overwrites the value in this message.<br>
+     * * For singular message fields, if the field is set in {@code other},
+     *   it is merged into the corresponding sub-message of this message
+     *   using the same merging rules.<br>
+     * * For repeated fields, the elements in {@code other} are concatenated
+     *   with the elements in this message.
+     * * For oneof groups, if the other message has one of the fields set,
+     *   the group of this message is cleared and replaced by the field
+     *   of the other message, so that the oneof constraint is preserved.
+     *
+     * This is equivalent to the {@code Message::MergeFrom} method in C++.
+     */
+    Builder mergeFrom(MessageLite other);
+
+    /**
+     * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
+     * Instead, the size of the message (encoded as a varint) is read first,
+     * then the message data.  Use
+     * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
+     * this format.
+     *
+     * @return True if successful, or false if the stream is at EOF when the
+     *         method starts.  Any other error (including reaching EOF during
+     *         parsing) will cause an exception to be thrown.
+     */
+    boolean mergeDelimitedFrom(InputStream input)
+                               throws IOException;
+
+    /**
+     * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
+     */
+    boolean mergeDelimitedFrom(InputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+                               throws IOException;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
new file mode 100644
index 0000000..818386c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -0,0 +1,60 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Base interface for methods common to {@link MessageLite}
+ * and {@link MessageLite.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageLiteOrBuilder {
+  /**
+   * Get an instance of the type with no fields set. Because no fields are set,
+   * all getters for singular fields will return default values and repeated
+   * fields will appear empty.
+   * This may or may not be a singleton.  This differs from the
+   * {@code getDefaultInstance()} method of generated message classes in that
+   * this method is an abstract method of the {@code MessageLite} interface
+   * whereas {@code getDefaultInstance()} is a static method of a specific
+   * class.  They return the same thing.
+   */
+  MessageLite getDefaultInstanceForType();
+
+  /**
+   * Returns true if all required fields in the message and all embedded
+   * messages are set, false otherwise.
+   *
+   * <p>See also: {@link MessageOrBuilder#getInitializationErrorString()}
+   */
+  boolean isInitialized();
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
new file mode 100644
index 0000000..4384765
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
@@ -0,0 +1,239 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Helps generate {@link String} representations of {@link MessageLite} protos.
+ */
+// TODO(dweis): Fix map fields.
+final class MessageLiteToString {
+
+  private static final String LIST_SUFFIX = "List";
+  private static final String BUILDER_LIST_SUFFIX = "OrBuilderList";
+  private static final String BYTES_SUFFIX = "Bytes";
+  
+  /**
+   * Returns a {@link String} representation of the {@link MessageLite} object.  The first line of
+   * the {@code String} representation representation includes a comment string to uniquely identify
+   * the objcet instance. This acts as an indicator that this should not be relied on for
+   * comparisons.
+   *
+   * <p>For use by generated code only.
+   */
+  static String toString(MessageLite messageLite, String commentString) {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("# ").append(commentString);
+    reflectivePrintWithIndent(messageLite, buffer, 0);
+    return buffer.toString();
+  }
+
+  /**
+   * Reflectively prints the {@link MessageLite} to the buffer at given {@code indent} level.
+   *
+   * @param buffer the buffer to write to
+   * @param indent the number of spaces to indent the proto by
+   */
+  private static void reflectivePrintWithIndent(
+      MessageLite messageLite, StringBuilder buffer, int indent) {
+    // Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and
+    // getFooList() which might be useful for building an object's string representation.
+    Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>();
+    Map<String, Method> nameToMethod = new HashMap<String, Method>();
+    Set<String> getters = new TreeSet<String>();
+    for (Method method : messageLite.getClass().getDeclaredMethods()) {
+      nameToMethod.put(method.getName(), method);
+      if (method.getParameterTypes().length == 0) {
+        nameToNoArgMethod.put(method.getName(), method);
+
+        if (method.getName().startsWith("get")) {
+          getters.add(method.getName());
+        }
+      }
+    }
+
+    for (String getter : getters) {
+      String suffix = getter.replaceFirst("get", "");
+      if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) {
+        String camelCase = suffix.substring(0, 1).toLowerCase()
+            + suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
+        // Try to reflectively get the value and toString() the field as if it were repeated. This
+        // only works if the method names have not be proguarded out or renamed.
+        Method listMethod = nameToNoArgMethod.get("get" + suffix);
+        if (listMethod != null) {
+          printField(
+              buffer,
+              indent,
+              camelCaseToSnakeCase(camelCase),
+              GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
+          continue;
+        }
+      }
+
+      Method setter = nameToMethod.get("set" + suffix);
+      if (setter == null) {
+        continue;
+      }
+      if (suffix.endsWith(BYTES_SUFFIX)
+          && nameToNoArgMethod.containsKey(
+              "get" + suffix.substring(0, suffix.length() - "Bytes".length()))) {
+        // Heuristic to skip bytes based accessors for string fields.
+        continue;
+      }
+      
+      String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
+
+      // Try to reflectively get the value and toString() the field as if it were optional. This
+      // only works if the method names have not be proguarded out or renamed.
+      Method getMethod = nameToNoArgMethod.get("get" + suffix);
+      Method hasMethod = nameToNoArgMethod.get("has" + suffix);
+      // TODO(dweis): Fix proto3 semantics.
+      if (getMethod != null) {
+        Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
+        final boolean hasValue = hasMethod == null
+            ? !isDefaultValue(value)
+            : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
+         // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
+        if (hasValue) {
+          printField(
+              buffer,
+              indent,
+              camelCaseToSnakeCase(camelCase),
+              value);
+        }
+        continue;
+      }
+    }
+
+    if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) {
+      Iterator<Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object>> iter =
+          ((GeneratedMessageLite.ExtendableMessage<?, ?>) messageLite).extensions.iterator();
+      while (iter.hasNext()) {
+        Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object> entry = iter.next();
+        printField(buffer, indent, "[" + entry.getKey().getNumber() + "]", entry.getValue());
+      }
+    }
+
+    if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields != null) {
+      ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent);
+    }
+  }
+  
+  private static boolean isDefaultValue(Object o) {
+    if (o instanceof Boolean) {
+      return !((Boolean) o);
+    }
+    if (o instanceof Integer) {
+      return ((Integer) o) == 0;
+    }
+    if (o instanceof Float) {
+      return ((Float) o) == 0f;
+    }
+    if (o instanceof Double) {
+      return ((Double) o) == 0d;
+    }
+    if (o instanceof String) {
+      return o.equals("");
+    }
+    if (o instanceof ByteString) {
+      return o.equals(ByteString.EMPTY);
+    }
+    if (o instanceof MessageLite) { // Can happen in oneofs.
+      return o == ((MessageLite) o).getDefaultInstanceForType();
+    }
+    if (o instanceof java.lang.Enum<?>) { // Catches oneof enums.
+      return ((java.lang.Enum<?>) o).ordinal() == 0;
+    }
+    
+    return false;
+  }
+
+  /**
+   * Formats a text proto field.
+   *
+   * <p>For use by generated code only.
+   *
+   * @param buffer the buffer to write to
+   * @param indent the number of spaces the proto should be indented by
+   * @param name the field name (in lower underscore case)
+   * @param object the object value of the field
+   */
+  static final void printField(StringBuilder buffer, int indent, String name, Object object) {
+    if (object instanceof List<?>) {
+      List<?> list = (List<?>) object;
+      for (Object entry : list) {
+        printField(buffer, indent, name, entry);
+      }
+      return;
+    }
+
+    buffer.append('\n');
+    for (int i = 0; i < indent; i++) {
+      buffer.append(' ');
+    }
+    buffer.append(name);
+
+    if (object instanceof String) {
+      buffer.append(": \"").append(TextFormatEscaper.escapeText((String) object)).append('"');
+    } else if (object instanceof ByteString) {
+      buffer.append(": \"").append(TextFormatEscaper.escapeBytes((ByteString) object)).append('"');
+    } else if (object instanceof GeneratedMessageLite) {
+      buffer.append(" {");
+      reflectivePrintWithIndent((GeneratedMessageLite<?, ?>) object, buffer, indent + 2);
+      buffer.append("\n");
+      for (int i = 0; i < indent; i++) {
+        buffer.append(' ');
+      }
+      buffer.append("}");
+    } else {
+      buffer.append(": ").append(object.toString());
+    }
+  }
+  
+  private static final String camelCaseToSnakeCase(String camelCase) {
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < camelCase.length(); i++) {
+      char ch = camelCase.charAt(i);
+      if (Character.isUpperCase(ch)) {
+        builder.append("_");
+      }
+      builder.append(Character.toLowerCase(ch));
+    }
+    return builder.toString();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
new file mode 100644
index 0000000..5e7d782
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -0,0 +1,143 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base interface for methods common to {@link Message} and
+ * {@link Message.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageOrBuilder extends MessageLiteOrBuilder {
+
+  // (From MessageLite, re-declared here only for return type covariance.)
+  @Override
+  Message getDefaultInstanceForType();
+
+  /**
+   * Returns a list of field paths (e.g. "foo.bar.baz") of required fields
+   * which are not set in this message.  You should call
+   * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+   * are any missing fields, as that method is likely to be much faster
+   * than this one even when the message is fully-initialized.
+   */
+  List<String> findInitializationErrors();
+
+  /**
+   * Returns a comma-delimited list of required fields which are not set
+   * in this message object.  You should call
+   * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+   * are any missing fields, as that method is likely to be much faster
+   * than this one even when the message is fully-initialized.
+   */
+  String getInitializationErrorString();
+
+  /**
+   * Get the message's type's descriptor.  This differs from the
+   * {@code getDescriptor()} method of generated message classes in that
+   * this method is an abstract method of the {@code Message} interface
+   * whereas {@code getDescriptor()} is a static method of a specific class.
+   * They return the same thing.
+   */
+  Descriptors.Descriptor getDescriptorForType();
+
+  /**
+   * Returns a collection of all the fields in this message which are set
+   * and their corresponding values.  A singular ("required" or "optional")
+   * field is set iff hasField() returns true for that field.  A "repeated"
+   * field is set iff getRepeatedFieldCount() is greater than zero.  The
+   * values are exactly what would be returned by calling
+   * {@link #getField(Descriptors.FieldDescriptor)} for each field.  The map
+   * is guaranteed to be a sorted map, so iterating over it will return fields
+   * in order by field number.
+   * <br>
+   * If this is for a builder, the returned map may or may not reflect future
+   * changes to the builder.  Either way, the returned map is itself
+   * unmodifiable.
+   */
+  Map<Descriptors.FieldDescriptor, Object> getAllFields();
+
+  /**
+   * Returns true if the given oneof is set.
+   * @throws IllegalArgumentException if
+   *           {@code oneof.getContainingType() != getDescriptorForType()}.
+   */
+  boolean hasOneof(Descriptors.OneofDescriptor oneof);
+
+  /**
+   * Obtains the FieldDescriptor if the given oneof is set. Returns null
+   * if no field is set.
+   */
+  Descriptors.FieldDescriptor getOneofFieldDescriptor(
+      Descriptors.OneofDescriptor oneof);
+
+  /**
+   * Returns true if the given field is set.  This is exactly equivalent to
+   * calling the generated "has" accessor method corresponding to the field.
+   * @throws IllegalArgumentException The field is a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  boolean hasField(Descriptors.FieldDescriptor field);
+
+  /**
+   * Obtains the value of the given field, or the default value if it is
+   * not set.  For primitive fields, the boxed primitive value is returned.
+   * For enum fields, the EnumValueDescriptor for the value is returned. For
+   * embedded message fields, the sub-message is returned.  For repeated
+   * fields, a java.util.List is returned.
+   */
+  Object getField(Descriptors.FieldDescriptor field);
+
+  /**
+   * Gets the number of elements of a repeated field.  This is exactly
+   * equivalent to calling the generated "Count" accessor method corresponding
+   * to the field.
+   * @throws IllegalArgumentException The field is not a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
+
+  /**
+   * Gets an element of a repeated field.  For primitive fields, the boxed
+   * primitive value is returned.  For enum fields, the EnumValueDescriptor
+   * for the value is returned. For embedded message fields, the sub-message
+   * is returned.
+   * @throws IllegalArgumentException The field is not a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
+
+  /** Get the {@link UnknownFieldSet} for this message. */
+  UnknownFieldSet getUnknownFields();
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageReflection.java
new file mode 100644
index 0000000..7b791d9
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MessageReflection.java
@@ -0,0 +1,993 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Reflection utility methods shared by both mutable and immutable messages.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+class MessageReflection {
+
+  static void writeMessageTo(
+      Message message,
+      Map<FieldDescriptor, Object> fields,
+      CodedOutputStream output,
+      boolean alwaysWriteRequiredFields)
+      throws IOException {
+    final boolean isMessageSet =
+        message.getDescriptorForType().getOptions().getMessageSetWireFormat();
+    if (alwaysWriteRequiredFields) {
+      fields = new TreeMap<FieldDescriptor, Object>(fields);
+      for (final FieldDescriptor field :
+          message.getDescriptorForType().getFields()) {
+        if (field.isRequired() && !fields.containsKey(field)) {
+          fields.put(field, message.getField(field));
+        }
+      }
+    }
+    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+        fields.entrySet()) {
+      final Descriptors.FieldDescriptor field = entry.getKey();
+      final Object value = entry.getValue();
+      if (isMessageSet && field.isExtension() &&
+          field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+          !field.isRepeated()) {
+        output.writeMessageSetExtension(field.getNumber(), (Message) value);
+      } else {
+        FieldSet.writeField(field, value, output);
+      }
+    }
+
+    final UnknownFieldSet unknownFields = message.getUnknownFields();
+    if (isMessageSet) {
+      unknownFields.writeAsMessageSetTo(output);
+    } else {
+      unknownFields.writeTo(output);
+    }
+  }
+
+  static int getSerializedSize(
+      Message message,
+      Map<FieldDescriptor, Object> fields) {
+    int size = 0;
+    final boolean isMessageSet =
+        message.getDescriptorForType().getOptions().getMessageSetWireFormat();
+
+    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+        fields.entrySet()) {
+      final Descriptors.FieldDescriptor field = entry.getKey();
+      final Object value = entry.getValue();
+      if (isMessageSet && field.isExtension() &&
+          field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+          !field.isRepeated()) {
+        size += CodedOutputStream.computeMessageSetExtensionSize(
+            field.getNumber(), (Message) value);
+      } else {
+        size += FieldSet.computeFieldSize(field, value);
+      }
+    }
+
+    final UnknownFieldSet unknownFields = message.getUnknownFields();
+    if (isMessageSet) {
+      size += unknownFields.getSerializedSizeAsMessageSet();
+    } else {
+      size += unknownFields.getSerializedSize();
+    }
+    return size;
+  }
+
+  static String delimitWithCommas(List<String> parts) {
+    StringBuilder result = new StringBuilder();
+    for (String part : parts) {
+      if (result.length() > 0) {
+        result.append(", ");
+      }
+      result.append(part);
+    }
+    return result.toString();
+  }
+
+  @SuppressWarnings("unchecked")
+  static boolean isInitialized(MessageOrBuilder message) {
+    // Check that all required fields are present.
+    for (final Descriptors.FieldDescriptor field : message
+        .getDescriptorForType()
+        .getFields()) {
+      if (field.isRequired()) {
+        if (!message.hasField(field)) {
+          return false;
+        }
+      }
+    }
+
+    // Check that embedded messages are initialized.
+    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+        message.getAllFields().entrySet()) {
+      final Descriptors.FieldDescriptor field = entry.getKey();
+      if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+        if (field.isRepeated()) {
+          for (final Message element
+              : (List<Message>) entry.getValue()) {
+            if (!element.isInitialized()) {
+              return false;
+            }
+          }
+        } else {
+          if (!((Message) entry.getValue()).isInitialized()) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  private static String subMessagePrefix(final String prefix,
+      final Descriptors.FieldDescriptor field,
+      final int index) {
+    final StringBuilder result = new StringBuilder(prefix);
+    if (field.isExtension()) {
+      result.append('(')
+          .append(field.getFullName())
+          .append(')');
+    } else {
+      result.append(field.getName());
+    }
+    if (index != -1) {
+      result.append('[')
+          .append(index)
+          .append(']');
+    }
+    result.append('.');
+    return result.toString();
+  }
+
+  private static void findMissingFields(final MessageOrBuilder message,
+      final String prefix,
+      final List<String> results) {
+    for (final Descriptors.FieldDescriptor field :
+        message.getDescriptorForType().getFields()) {
+      if (field.isRequired() && !message.hasField(field)) {
+        results.add(prefix + field.getName());
+      }
+    }
+
+    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+        message.getAllFields().entrySet()) {
+      final Descriptors.FieldDescriptor field = entry.getKey();
+      final Object value = entry.getValue();
+
+      if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+        if (field.isRepeated()) {
+          int i = 0;
+          for (final Object element : (List) value) {
+            findMissingFields((MessageOrBuilder) element,
+                subMessagePrefix(prefix, field, i++),
+                results);
+          }
+        } else {
+          if (message.hasField(field)) {
+            findMissingFields((MessageOrBuilder) value,
+                subMessagePrefix(prefix, field, -1),
+                results);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Populates {@code this.missingFields} with the full "path" of each missing
+   * required field in the given message.
+   */
+  static List<String> findMissingFields(
+      final MessageOrBuilder message) {
+    final List<String> results = new ArrayList<String>();
+    findMissingFields(message, "", results);
+    return results;
+  }
+
+  static interface MergeTarget {
+    enum ContainerType {
+      MESSAGE, EXTENSION_SET
+    }
+
+    /**
+     * Returns the descriptor for the target.
+     */
+    public Descriptors.Descriptor getDescriptorForType();
+
+    public ContainerType getContainerType();
+
+    public ExtensionRegistry.ExtensionInfo findExtensionByName(
+        ExtensionRegistry registry, String name);
+
+    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+        ExtensionRegistry registry, Descriptors.Descriptor containingType,
+        int fieldNumber);
+
+    /**
+     * Obtains the value of the given field, or the default value if it is not
+     * set.  For primitive fields, the boxed primitive value is returned. For
+     * enum fields, the EnumValueDescriptor for the value is returned. For
+     * embedded message fields, the sub-message is returned.  For repeated
+     * fields, a java.util.List is returned.
+     */
+    public Object getField(Descriptors.FieldDescriptor field);
+
+    /**
+     * Returns true if the given field is set.  This is exactly equivalent to
+     * calling the generated "has" accessor method corresponding to the field.
+     *
+     * @throws IllegalArgumentException The field is a repeated field, or {@code
+     *     field.getContainingType() != getDescriptorForType()}.
+     */
+    boolean hasField(Descriptors.FieldDescriptor field);
+
+    /**
+     * Sets a field to the given value.  The value must be of the correct type
+     * for this field, i.e. the same type that
+     * {@link Message#getField(Descriptors.FieldDescriptor)}
+     * would return.
+     */
+    MergeTarget setField(Descriptors.FieldDescriptor field, Object value);
+
+    /**
+     * Clears the field.  This is exactly equivalent to calling the generated
+     * "clear" accessor method corresponding to the field.
+     */
+    MergeTarget clearField(Descriptors.FieldDescriptor field);
+
+    /**
+     * Sets an element of a repeated field to the given value.  The value must
+     * be of the correct type for this field, i.e. the same type that {@link
+     * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return.
+     *
+     * @throws IllegalArgumentException The field is not a repeated field, or
+     *                                  {@code field.getContainingType() !=
+     *                                  getDescriptorForType()}.
+     */
+    MergeTarget setRepeatedField(Descriptors.FieldDescriptor field,
+        int index, Object value);
+
+    /**
+     * Like {@code setRepeatedField}, but appends the value as a new element.
+     *
+     * @throws IllegalArgumentException The field is not a repeated field, or
+     *                                  {@code field.getContainingType() !=
+     *                                  getDescriptorForType()}.
+     */
+    MergeTarget addRepeatedField(Descriptors.FieldDescriptor field,
+        Object value);
+
+    /**
+     * Returns true if the given oneof is set.
+     *
+     * @throws IllegalArgumentException if
+     *           {@code oneof.getContainingType() != getDescriptorForType()}.
+     */
+    boolean hasOneof(Descriptors.OneofDescriptor oneof);
+
+    /**
+     * Clears the oneof.  This is exactly equivalent to calling the generated
+     * "clear" accessor method corresponding to the oneof.
+     */
+    MergeTarget clearOneof(Descriptors.OneofDescriptor oneof);
+
+    /**
+     * Obtains the FieldDescriptor if the given oneof is set. Returns null
+     * if no field is set.
+     */
+    Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof);
+
+    /**
+     * Parse the input stream into a sub field group defined based on either
+     * FieldDescriptor or the default instance.
+     */
+    Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+        throws IOException;
+
+    /**
+     * Parse the input stream into a sub field message defined based on either
+     * FieldDescriptor or the default instance.
+     */
+    Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+        throws IOException;
+
+    /**
+     * Parse from a ByteString into a sub field message defined based on either
+     * FieldDescriptor or the default instance.  There isn't a varint indicating
+     * the length of the message at the beginning of the input ByteString.
+     */
+    Object parseMessageFromBytes(
+        ByteString bytes, ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+        throws IOException;
+
+    /**
+     * Returns the UTF8 validation level for the field.
+     */
+    WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor
+        descriptor);
+
+    /**
+     * Returns a new merge target for a sub-field. When defaultInstance is
+     * provided, it indicates the descriptor is for an extension type, and
+     * implementations should create a new instance from the defaultInstance
+     * prototype directly.
+     */
+    MergeTarget newMergeTargetForField(
+        Descriptors.FieldDescriptor descriptor,
+        Message defaultInstance);
+
+    /**
+     * Finishes the merge and returns the underlying object.
+     */
+    Object finish();
+    
+  }
+
+  static class BuilderAdapter implements MergeTarget {
+
+    private final Message.Builder builder;
+
+    @Override
+    public Descriptors.Descriptor getDescriptorForType() {
+      return builder.getDescriptorForType();
+    }
+
+    public BuilderAdapter(Message.Builder builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    public Object getField(Descriptors.FieldDescriptor field) {
+      return builder.getField(field);
+    }
+
+    @Override
+    public boolean hasField(Descriptors.FieldDescriptor field) {
+      return builder.hasField(field);
+    }
+
+    @Override
+    public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
+      builder.setField(field, value);
+      return this;
+    }
+
+    @Override
+    public MergeTarget clearField(Descriptors.FieldDescriptor field) {
+      builder.clearField(field);
+      return this;
+    }
+
+    @Override
+    public MergeTarget setRepeatedField(
+        Descriptors.FieldDescriptor field, int index, Object value) {
+      builder.setRepeatedField(field, index, value);
+      return this;
+    }
+
+    @Override
+    public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+      builder.addRepeatedField(field, value);
+      return this;
+    }
+
+    @Override
+    public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
+      return builder.hasOneof(oneof);
+    }
+
+    @Override
+    public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
+      builder.clearOneof(oneof);
+      return this;
+    }
+
+    @Override
+    public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
+      return builder.getOneofFieldDescriptor(oneof);
+    }
+
+    @Override
+    public ContainerType getContainerType() {
+      return ContainerType.MESSAGE;
+    }
+
+    @Override
+    public ExtensionRegistry.ExtensionInfo findExtensionByName(
+        ExtensionRegistry registry, String name) {
+      return registry.findImmutableExtensionByName(name);
+    }
+
+    @Override
+    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+        ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
+      return registry.findImmutableExtensionByNumber(containingType,
+          fieldNumber);
+    }
+
+    @Override
+    public Object parseGroup(
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder;
+      // When default instance is not null. The field is an extension field.
+      if (defaultInstance != null) {
+        subBuilder = defaultInstance.newBuilderForType();
+      } else {
+        subBuilder = builder.newBuilderForField(field);
+      }
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public Object parseMessage(
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder;
+      // When default instance is not null. The field is an extension field.
+      if (defaultInstance != null) {
+        subBuilder = defaultInstance.newBuilderForType();
+      } else {
+        subBuilder = builder.newBuilderForField(field);
+      }
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      input.readMessage(subBuilder, extensionRegistry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public Object parseMessageFromBytes(
+        ByteString bytes,
+        ExtensionRegistryLite extensionRegistry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder;
+      // When default instance is not null. The field is an extension field.
+      if (defaultInstance != null) {
+        subBuilder = defaultInstance.newBuilderForType();
+      } else {
+        subBuilder = builder.newBuilderForField(field);
+      }
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      subBuilder.mergeFrom(bytes, extensionRegistry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public MergeTarget newMergeTargetForField(
+        Descriptors.FieldDescriptor field, Message defaultInstance) {
+      if (defaultInstance != null) {
+        return new BuilderAdapter(
+            defaultInstance.newBuilderForType());
+      } else {
+        return new BuilderAdapter(builder.newBuilderForField(field));
+      }
+    }
+
+    @Override
+    public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+      if (descriptor.needsUtf8Check()) {
+        return WireFormat.Utf8Validation.STRICT;
+      }
+      // TODO(liujisi): support lazy strings for repeated fields.
+      if (!descriptor.isRepeated()
+          && builder instanceof GeneratedMessage.Builder) {
+        return WireFormat.Utf8Validation.LAZY;
+      }
+      return WireFormat.Utf8Validation.LOOSE;
+    }
+
+    @Override
+    public Object finish() {
+      return builder.buildPartial();
+    }
+    
+  }
+
+
+  static class ExtensionAdapter implements MergeTarget {
+
+    private final FieldSet<Descriptors.FieldDescriptor> extensions;
+
+    ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> extensions) {
+      this.extensions = extensions;
+    }
+
+    @Override
+    public Descriptors.Descriptor getDescriptorForType() {
+      throw new UnsupportedOperationException(
+          "getDescriptorForType() called on FieldSet object");
+    }
+
+    @Override
+    public Object getField(Descriptors.FieldDescriptor field) {
+      return extensions.getField(field);
+    }
+
+    @Override
+    public boolean hasField(Descriptors.FieldDescriptor field) {
+      return extensions.hasField(field);
+    }
+
+    @Override
+    public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
+      extensions.setField(field, value);
+      return this;
+    }
+
+    @Override
+    public MergeTarget clearField(Descriptors.FieldDescriptor field) {
+      extensions.clearField(field);
+      return this;
+    }
+
+    @Override
+    public MergeTarget setRepeatedField(
+        Descriptors.FieldDescriptor field, int index, Object value) {
+      extensions.setRepeatedField(field, index, value);
+      return this;
+    }
+
+    @Override
+    public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+      extensions.addRepeatedField(field, value);
+      return this;
+    }
+
+    @Override
+    public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
+      return false;
+    }
+
+    @Override
+    public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
+      // Nothing to clear.
+      return this;
+    }
+
+    @Override
+    public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
+      return null;
+    }
+
+    @Override
+    public ContainerType getContainerType() {
+      return ContainerType.EXTENSION_SET;
+    }
+
+    @Override
+    public ExtensionRegistry.ExtensionInfo findExtensionByName(
+        ExtensionRegistry registry, String name) {
+      return registry.findImmutableExtensionByName(name);
+    }
+
+    @Override
+    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+        ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
+      return registry.findImmutableExtensionByNumber(containingType,
+          fieldNumber);
+    }
+
+    @Override
+    public Object parseGroup(
+        CodedInputStream input,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder =
+          defaultInstance.newBuilderForType();
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      input.readGroup(field.getNumber(), subBuilder, registry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public Object parseMessage(
+        CodedInputStream input,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder =
+          defaultInstance.newBuilderForType();
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      input.readMessage(subBuilder, registry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public Object parseMessageFromBytes(
+        ByteString bytes,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
+      Message.Builder subBuilder =  defaultInstance.newBuilderForType();
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
+      }
+      subBuilder.mergeFrom(bytes, registry);
+      return subBuilder.buildPartial();
+    }
+
+    @Override
+    public MergeTarget newMergeTargetForField(
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
+      throw new UnsupportedOperationException(
+          "newMergeTargetForField() called on FieldSet object");
+    }
+
+    @Override
+    public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+      if (descriptor.needsUtf8Check()) {
+        return WireFormat.Utf8Validation.STRICT;
+      }
+      // TODO(liujisi): support lazy strings for ExtesnsionSet.
+      return WireFormat.Utf8Validation.LOOSE;
+    }
+
+    @Override
+    public Object finish() {
+      throw new UnsupportedOperationException(
+          "finish() called on FieldSet object");
+    }
+    
+  }
+
+  /**
+   * Parses a single field into MergeTarget. The target can be Message.Builder,
+   * FieldSet or MutableMessage.
+   *
+   * Package-private because it is used by GeneratedMessage.ExtendableMessage.
+   *
+   * @param tag The tag, which should have already been read.
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  static boolean mergeFieldFrom(
+      CodedInputStream input,
+      UnknownFieldSet.Builder unknownFields,
+      ExtensionRegistryLite extensionRegistry,
+      Descriptors.Descriptor type,
+      MergeTarget target,
+      int tag) throws IOException {
+    if (type.getOptions().getMessageSetWireFormat() &&
+        tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
+      mergeMessageSetExtensionFromCodedStream(
+          input, unknownFields, extensionRegistry, type, target);
+      return true;
+    }
+
+    final int wireType = WireFormat.getTagWireType(tag);
+    final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+    final Descriptors.FieldDescriptor field;
+    Message defaultInstance = null;
+
+    if (type.isExtensionNumber(fieldNumber)) {
+      // extensionRegistry may be either ExtensionRegistry or
+      // ExtensionRegistryLite.  Since the type we are parsing is a full
+      // message, only a full ExtensionRegistry could possibly contain
+      // extensions of it.  Otherwise we will treat the registry as if it
+      // were empty.
+      if (extensionRegistry instanceof ExtensionRegistry) {
+        final ExtensionRegistry.ExtensionInfo extension =
+            target.findExtensionByNumber((ExtensionRegistry) extensionRegistry,
+                type, fieldNumber);
+        if (extension == null) {
+          field = null;
+        } else {
+          field = extension.descriptor;
+          defaultInstance = extension.defaultInstance;
+          if (defaultInstance == null &&
+              field.getJavaType()
+                  == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+            throw new IllegalStateException(
+                "Message-typed extension lacked default instance: " +
+                    field.getFullName());
+          }
+        }
+      } else {
+        field = null;
+      }
+    } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) {
+      field = type.findFieldByNumber(fieldNumber);
+    } else {
+      field = null;
+    }
+
+    boolean unknown = false;
+    boolean packed = false;
+    if (field == null) {
+      unknown = true;  // Unknown field.
+    } else if (wireType == FieldSet.getWireFormatForFieldType(
+        field.getLiteType(),
+        false  /* isPacked */)) {
+      packed = false;
+    } else if (field.isPackable() &&
+        wireType == FieldSet.getWireFormatForFieldType(
+            field.getLiteType(),
+            true  /* isPacked */)) {
+      packed = true;
+    } else {
+      unknown = true;  // Unknown wire type.
+    }
+
+    if (unknown) {  // Unknown field or wrong wire type.  Skip.
+      return unknownFields.mergeFieldFrom(tag, input);
+    }
+
+    if (packed) {
+      final int length = input.readRawVarint32();
+      final int limit = input.pushLimit(length);
+      if (field.getLiteType() == WireFormat.FieldType.ENUM) {
+        while (input.getBytesUntilLimit() > 0) {
+          final int rawValue = input.readEnum();
+          if (field.getFile().supportsUnknownEnumValue()) {
+            target.addRepeatedField(field,
+                field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue));
+          } else {
+            final Object value = field.getEnumType().findValueByNumber(rawValue);
+            if (value == null) {
+              // If the number isn't recognized as a valid value for this
+              // enum, drop it (don't even add it to unknownFields).
+              return true;
+            }
+            target.addRepeatedField(field, value);
+          }
+        }
+      } else {
+        while (input.getBytesUntilLimit() > 0) {
+          final Object value = WireFormat.readPrimitiveField(
+              input, field.getLiteType(), target.getUtf8Validation(field));
+          target.addRepeatedField(field, value);
+        }
+      }
+      input.popLimit(limit);
+    } else {
+      final Object value;
+      switch (field.getType()) {
+        case GROUP: {
+          value = target
+              .parseGroup(input, extensionRegistry, field, defaultInstance);
+          break;
+        }
+        case MESSAGE: {
+          value = target
+              .parseMessage(input, extensionRegistry, field, defaultInstance);
+          break;
+        }
+        case ENUM:
+          final int rawValue = input.readEnum();
+          if (field.getFile().supportsUnknownEnumValue()) {
+            value = field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue);
+          } else {
+            value = field.getEnumType().findValueByNumber(rawValue);
+            // If the number isn't recognized as a valid value for this enum,
+            // drop it.
+            if (value == null) {
+              unknownFields.mergeVarintField(fieldNumber, rawValue);
+              return true;
+            }
+          }
+          break;
+        default:
+          value = WireFormat.readPrimitiveField(
+              input, field.getLiteType(), target.getUtf8Validation(field));
+          break;
+      }
+
+      if (field.isRepeated()) {
+        target.addRepeatedField(field, value);
+      } else {
+        target.setField(field, value);
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into
+   * MergeTarget.
+   */
+  private static void mergeMessageSetExtensionFromCodedStream(
+      CodedInputStream input,
+      UnknownFieldSet.Builder unknownFields,
+      ExtensionRegistryLite extensionRegistry,
+      Descriptors.Descriptor type,
+      MergeTarget target) throws IOException {
+
+    // The wire format for MessageSet is:
+    //   message MessageSet {
+    //     repeated group Item = 1 {
+    //       required int32 typeId = 2;
+    //       required bytes message = 3;
+    //     }
+    //   }
+    // "typeId" is the extension's field number.  The extension can only be
+    // a message type, where "message" contains the encoded bytes of that
+    // message.
+    //
+    // In practice, we will probably never see a MessageSet item in which
+    // the message appears before the type ID, or where either field does not
+    // appear exactly once.  However, in theory such cases are valid, so we
+    // should be prepared to accept them.
+
+    int typeId = 0;
+    ByteString rawBytes = null; // If we encounter "message" before "typeId"
+    ExtensionRegistry.ExtensionInfo extension = null;
+
+    // Read bytes from input, if we get it's type first then parse it eagerly,
+    // otherwise we store the raw bytes in a local variable.
+    while (true) {
+      final int tag = input.readTag();
+      if (tag == 0) {
+        break;
+      }
+
+      if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+        typeId = input.readUInt32();
+        if (typeId != 0) {
+          // extensionRegistry may be either ExtensionRegistry or
+          // ExtensionRegistryLite. Since the type we are parsing is a full
+          // message, only a full ExtensionRegistry could possibly contain
+          // extensions of it. Otherwise we will treat the registry as if it
+          // were empty.
+          if (extensionRegistry instanceof ExtensionRegistry) {
+            extension = target.findExtensionByNumber(
+                (ExtensionRegistry) extensionRegistry, type, typeId);
+          }
+        }
+
+      } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+        if (typeId != 0) {
+          if (extension != null &&
+              ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+            // We already know the type, so we can parse directly from the
+            // input with no copying.  Hooray!
+            eagerlyMergeMessageSetExtension(
+                input, extension, extensionRegistry, target);
+            rawBytes = null;
+            continue;
+          }
+        }
+        // We haven't seen a type ID yet or we want parse message lazily.
+        rawBytes = input.readBytes();
+
+      } else { // Unknown tag. Skip it.
+        if (!input.skipField(tag)) {
+          break; // End of group
+        }
+      }
+    }
+    input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
+
+    // Process the raw bytes.
+    if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
+      if (extension != null) { // We known the type
+        mergeMessageSetExtensionFromBytes(
+            rawBytes, extension, extensionRegistry, target);
+      } else { // We don't know how to parse this. Ignore it.
+        if (rawBytes != null) {
+          unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
+              .addLengthDelimited(rawBytes).build());
+        }
+      }
+    }
+  }
+
+  private static void mergeMessageSetExtensionFromBytes(
+      ByteString rawBytes,
+      ExtensionRegistry.ExtensionInfo extension,
+      ExtensionRegistryLite extensionRegistry,
+      MergeTarget target) throws IOException {
+
+    Descriptors.FieldDescriptor field = extension.descriptor;
+    boolean hasOriginalValue = target.hasField(field);
+
+    if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+      // If the field already exists, we just parse the field.
+      Object value = target.parseMessageFromBytes(
+          rawBytes, extensionRegistry,field, extension.defaultInstance);
+      target.setField(field, value);
+    } else {
+      // Use LazyField to load MessageSet lazily.
+      LazyField lazyField = new LazyField(
+          extension.defaultInstance, extensionRegistry, rawBytes);
+      target.setField(field, lazyField);
+    }
+  }
+
+  private static void eagerlyMergeMessageSetExtension(
+      CodedInputStream input,
+      ExtensionRegistry.ExtensionInfo extension,
+      ExtensionRegistryLite extensionRegistry,
+      MergeTarget target) throws IOException {
+    Descriptors.FieldDescriptor field = extension.descriptor;
+    Object value = target.parseMessage(input, extensionRegistry, field,
+                                       extension.defaultInstance);
+    target.setField(field, value);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java
new file mode 100644
index 0000000..82b723c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java
@@ -0,0 +1,48 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Verifies that an object is mutable, throwing if not.
+ */
+interface MutabilityOracle {
+  static final MutabilityOracle IMMUTABLE = new MutabilityOracle() {
+    @Override
+    public void ensureMutable() {
+      throw new UnsupportedOperationException();
+    }
+  };
+
+  /**
+   * Throws an {@link UnsupportedOperationException} if not mutable.
+   */
+  void ensureMutable();
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/NioByteString.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/NioByteString.java
new file mode 100644
index 0000000..6163c7b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/NioByteString.java
@@ -0,0 +1,290 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link ByteString} that wraps around a {@link ByteBuffer}.
+ */
+final class NioByteString extends ByteString.LeafByteString {
+  private final ByteBuffer buffer;
+
+  NioByteString(ByteBuffer buffer) {
+    if (buffer == null) {
+      throw new NullPointerException("buffer");
+    }
+
+    this.buffer = buffer.slice().order(ByteOrder.nativeOrder());
+  }
+
+  // =================================================================
+  // Serializable
+
+  /**
+   * Magic method that lets us override serialization behavior.
+   */
+  private Object writeReplace() {
+    return ByteString.copyFrom(buffer.slice());
+  }
+
+  /**
+   * Magic method that lets us override deserialization behavior.
+   */
+  private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
+    throw new InvalidObjectException("NioByteString instances are not to be serialized directly");
+  }
+
+  // =================================================================
+
+  @Override
+  public byte byteAt(int index) {
+    try {
+      return buffer.get(index);
+    } catch (ArrayIndexOutOfBoundsException e) {
+      throw e;
+    } catch (IndexOutOfBoundsException e) {
+      throw new ArrayIndexOutOfBoundsException(e.getMessage());
+    }
+  }
+
+  @Override
+  public int size() {
+    return buffer.remaining();
+  }
+
+  @Override
+  public ByteString substring(int beginIndex, int endIndex) {
+    try {
+      ByteBuffer slice = slice(beginIndex, endIndex);
+      return new NioByteString(slice);
+    } catch (ArrayIndexOutOfBoundsException e) {
+      throw e;
+    } catch (IndexOutOfBoundsException e) {
+      throw new ArrayIndexOutOfBoundsException(e.getMessage());
+    }
+  }
+
+  @Override
+  protected void copyToInternal(
+      byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
+    ByteBuffer slice = buffer.slice();
+    slice.position(sourceOffset);
+    slice.get(target, targetOffset, numberToCopy);
+  }
+
+  @Override
+  public void copyTo(ByteBuffer target) {
+    target.put(buffer.slice());
+  }
+
+  @Override
+  public void writeTo(OutputStream out) throws IOException {
+    out.write(toByteArray());
+  }
+
+  @Override
+  boolean equalsRange(ByteString other, int offset, int length) {
+    return substring(0, length).equals(other.substring(offset, offset + length));
+  }
+
+  @Override
+  void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) throws IOException {
+    if (buffer.hasArray()) {
+      // Optimized write for array-backed buffers.
+      // Note that we're taking the risk that a malicious OutputStream could modify the array.
+      int bufferOffset = buffer.arrayOffset() + buffer.position() + sourceOffset;
+      out.write(buffer.array(), bufferOffset, numberToWrite);
+      return;
+    }
+
+    ByteBufferWriter.write(slice(sourceOffset, sourceOffset + numberToWrite), out);
+  }
+
+  @Override
+  void writeTo(ByteOutput output) throws IOException {
+    output.writeLazy(buffer.slice());
+  }
+
+  @Override
+  public ByteBuffer asReadOnlyByteBuffer() {
+    return buffer.asReadOnlyBuffer();
+  }
+
+  @Override
+  public List<ByteBuffer> asReadOnlyByteBufferList() {
+    return Collections.singletonList(asReadOnlyByteBuffer());
+  }
+
+  @Override
+  protected String toStringInternal(Charset charset) {
+    final byte[] bytes;
+    final int offset;
+    final int length;
+    if (buffer.hasArray()) {
+      bytes = buffer.array();
+      offset = buffer.arrayOffset() + buffer.position();
+      length = buffer.remaining();
+    } else {
+      // TODO(nathanmittler): Can we optimize this?
+      bytes = toByteArray();
+      offset = 0;
+      length = bytes.length;
+    }
+    return new String(bytes, offset, length, charset);
+  }
+
+  @Override
+  public boolean isValidUtf8() {
+    return Utf8.isValidUtf8(buffer);
+  }
+
+  @Override
+  protected int partialIsValidUtf8(int state, int offset, int length) {
+    return Utf8.partialIsValidUtf8(state, buffer, offset, offset + length);
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof ByteString)) {
+      return false;
+    }
+    ByteString otherString = ((ByteString) other);
+    if (size() != otherString.size()) {
+      return false;
+    }
+    if (size() == 0) {
+      return true;
+    }
+    if (other instanceof NioByteString) {
+      return buffer.equals(((NioByteString) other).buffer);
+    }
+    if (other instanceof RopeByteString) {
+      return other.equals(this);
+    }
+    return buffer.equals(otherString.asReadOnlyByteBuffer());
+  }
+
+  @Override
+  protected int partialHash(int h, int offset, int length) {
+    for (int i = offset; i < offset + length; i++) {
+      h = h * 31 + buffer.get(i);
+    }
+    return h;
+  }
+
+  @Override
+  public InputStream newInput() {
+    return new InputStream() {
+      private final ByteBuffer buf = buffer.slice();
+
+      @Override
+      public void mark(int readlimit) {
+        buf.mark();
+      }
+
+      @Override
+      public boolean markSupported() {
+        return true;
+      }
+
+      @Override
+      public void reset() throws IOException {
+        try {
+          buf.reset();
+        } catch (InvalidMarkException e) {
+          throw new IOException(e);
+        }
+      }
+
+      @Override
+      public int available() throws IOException {
+        return buf.remaining();
+      }
+
+      @Override
+      public int read() throws IOException {
+        if (!buf.hasRemaining()) {
+          return -1;
+        }
+        return buf.get() & 0xFF;
+      }
+
+      @Override
+      public int read(byte[] bytes, int off, int len) throws IOException {
+        if (!buf.hasRemaining()) {
+          return -1;
+        }
+
+        len = Math.min(len, buf.remaining());
+        buf.get(bytes, off, len);
+        return len;
+      }
+    };
+  }
+
+  @Override
+  public CodedInputStream newCodedInput() {
+    return CodedInputStream.newInstance(buffer);
+  }
+
+  /**
+   * Creates a slice of a range of this buffer.
+   *
+   * @param beginIndex the beginning index of the slice (inclusive).
+   * @param endIndex the end index of the slice (exclusive).
+   * @return the requested slice.
+   */
+  private ByteBuffer slice(int beginIndex, int endIndex) {
+    if (beginIndex < buffer.position() || endIndex > buffer.limit() || beginIndex > endIndex) {
+      throw new IllegalArgumentException(
+          String.format("Invalid indices [%d, %d]", beginIndex, endIndex));
+    }
+
+    ByteBuffer slice = buffer.slice();
+    slice.position(beginIndex - buffer.position());
+    slice.limit(endIndex - buffer.position());
+    return slice;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Parser.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Parser.java
new file mode 100644
index 0000000..6db6924
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Parser.java
@@ -0,0 +1,272 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.InputStream;
+
+/**
+ * Abstract interface for parsing Protocol Messages.
+ *
+ * The implementation should be stateless and thread-safe.
+ *
+ * <p>All methods may throw {@link InvalidProtocolBufferException}. In the event of invalid data,
+ * like an encoding error, the cause of the thrown exception will be {@code null}. However, if an
+ * I/O problem occurs, an exception is thrown with an {@link IOException} cause.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public interface Parser<MessageType> {
+
+  // NB(jh): Other parts of the protobuf API that parse messages distinguish between an I/O problem
+  // (like failure reading bytes from a socket) and invalid data (encoding error) via the type of
+  // thrown exception. But it would be source-incompatible to make the methods in this interface do
+  // so since they were originally spec'ed to only throw InvalidProtocolBufferException. So callers
+  // must inspect the cause of the exception to distinguish these two cases.
+
+  /**
+   * Parses a message of {@code MessageType} from the input.
+   *
+   * <p>Note:  The caller should call
+   * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+   * verify that the last tag seen was the appropriate end-group tag,
+   * or zero for EOF.
+   */
+  public MessageType parseFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions.
+   * The extensions that you want to be able to parse must be registered in
+   * {@code extensionRegistry}. Extensions not in the registry will be treated
+   * as unknown fields.
+   */
+  public MessageType parseFrom(CodedInputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(CodedInputStream input,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  // ---------------------------------------------------------------
+  // Convenience methods.
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(ByteString data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(ByteString data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(ByteString data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(ByteString data,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(byte[] data, int off, int len,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(byte[] data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(byte[] data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[], int, int)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data, int off, int len,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[])}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[], ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parse a message of {@code MessageType} from {@code input}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   * Note that this method always reads the <i>entire</i> input (unless it
+   * throws an exception).  If you want it to stop earlier, you will need to
+   * wrap your input in some wrapper stream that limits reading.  Or, use
+   * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your
+   * message and {@link #parseDelimitedFrom(InputStream)} to read it.
+   * <p>
+   * Despite usually reading the entire input, this does not close the stream.
+   */
+  public MessageType parseFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses a message of {@code MessageType} from {@code input}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(InputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(InputStream input,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream)}, but does not read util EOF.
+   * Instead, the size of message (encoded as a varint) is read first,
+   * then the message data. Use
+   * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
+   * messages in this format.
+   *
+   * @return Parsed message if successful, or null if the stream is at EOF when
+   *         the method starts. Any other error (including reaching EOF during
+   *         parsing) will cause an exception to be thrown.
+   */
+  public MessageType parseDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions.
+   */
+  public MessageType parseDelimitedFrom(InputStream input,
+                                        ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialDelimitedFrom(
+      InputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
new file mode 100644
index 0000000..81255ec
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
@@ -0,0 +1,105 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.ProtobufList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements {@link ProtobufList} for non-primitive and {@link String} types.
+ */
+final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
+
+  private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>();
+  static {
+    EMPTY_LIST.makeImmutable();
+  }
+  
+  @SuppressWarnings("unchecked") // Guaranteed safe by runtime.
+  public static <E> ProtobufArrayList<E> emptyList() {
+    return (ProtobufArrayList<E>) EMPTY_LIST;
+  }
+  
+  private final List<E> list;
+
+  ProtobufArrayList() {
+    this(new ArrayList<E>(DEFAULT_CAPACITY));
+  }
+  
+  private ProtobufArrayList(List<E> list) {
+    this.list = list;
+  }
+
+  @Override
+  public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) {
+    if (capacity < size()) {
+      throw new IllegalArgumentException();
+    }
+    List<E> newList = new ArrayList<E>(capacity);
+    newList.addAll(list);
+    return new ProtobufArrayList<E>(newList);
+  }
+  
+  @Override
+  public void add(int index, E element) {
+    ensureIsMutable();
+    list.add(index, element);
+    modCount++;
+  }
+
+  @Override
+  public E get(int index) {
+    return list.get(index);
+  }
+  
+  @Override
+  public E remove(int index) {
+    ensureIsMutable();
+    E toReturn = list.remove(index);
+    modCount++;
+    return toReturn;
+  }
+  
+  @Override
+  public E set(int index, E element) {
+    ensureIsMutable();
+    E toReturn = list.set(index, element);
+    modCount++;
+    return toReturn;
+  }
+
+  @Override
+  public int size() {
+    return list.size();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
new file mode 100644
index 0000000..a596d30
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
@@ -0,0 +1,59 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+
+/**
+ * Interface of useful methods added to all enums generated by the protocol
+ * compiler.
+ */
+public interface ProtocolMessageEnum extends Internal.EnumLite {
+
+  /**
+   * Return the value's numeric value as defined in the .proto file.
+   */
+  @Override
+  int getNumber();
+
+  /**
+   * Return the value's descriptor, which contains information such as
+   * value name, number, and type.
+   */
+  EnumValueDescriptor getValueDescriptor();
+
+  /**
+   * Return the enum type's descriptor, which contains information
+   * about each defined value, etc.
+   */
+  EnumDescriptor getDescriptorForType();
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java
new file mode 100644
index 0000000..d553b41
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java
@@ -0,0 +1,48 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.List;
+
+/**
+ * An interface extending {@code List<String>} used for repeated string fields
+ * to provide optional access to the data as a list of ByteStrings. The
+ * underlying implementation stores values as either ByteStrings or Strings
+ * (see {@link LazyStringArrayList}) depending on how the value was initialized
+ * or last read, and it is often more efficient to deal with lists of
+ * ByteStrings when handling protos that have been deserialized from bytes.
+ */
+public interface ProtocolStringList extends List<String> {
+
+  /** Returns a view of the data as a list of ByteStrings. */
+  List<ByteString> asByteStringList();
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
new file mode 100644
index 0000000..29f567d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -0,0 +1,708 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@code RepeatedFieldBuilder} implements a structure that a protocol
+ * message uses to hold a repeated field of other protocol messages. It supports
+ * the classical use case of adding immutable {@link Message}'s to the
+ * repeated field and is highly optimized around this (no extra memory
+ * allocations and sharing of immutable arrays).
+ * <br>
+ * It also supports the additional use case of adding a {@link Message.Builder}
+ * to the repeated field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilder
+    <MType extends GeneratedMessage,
+     BType extends GeneratedMessage.Builder,
+     IType extends MessageOrBuilder>
+    implements GeneratedMessage.BuilderParent {
+
+  // Parent to send changes to.
+  private GeneratedMessage.BuilderParent parent;
+
+  // List of messages. Never null. It may be immutable, in which case
+  // isMessagesListMutable will be false. See note below.
+  private List<MType> messages;
+
+  // Whether messages is an mutable array that can be modified.
+  private boolean isMessagesListMutable;
+
+  // List of builders. May be null, in which case, no nested builders were
+  // created. If not null, entries represent the builder for that index.
+  private List<SingleFieldBuilder<MType, BType, IType>> builders;
+
+  // Here are the invariants for messages and builders:
+  // 1. messages is never null and its count corresponds to the number of items
+  //    in the repeated field.
+  // 2. If builders is non-null, messages and builders MUST always
+  //    contain the same number of items.
+  // 3. Entries in either array can be null, but for any index, there MUST be
+  //    either a Message in messages or a builder in builders.
+  // 4. If the builder at an index is non-null, the builder is
+  //    authoritative. This is the case where a Builder was set on the index.
+  //    Any message in the messages array MUST be ignored.
+  // t. If the builder at an index is null, the message in the messages
+  //    list is authoritative. This is the case where a Message (not a Builder)
+  //    was set directly for an index.
+
+  // Indicates that we've built a message and so we are now obligated
+  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+  private boolean isClean;
+
+  // A view of this builder that exposes a List interface of messages. This is
+  // initialized on demand. This is fully backed by this object and all changes
+  // are reflected in it. Access to any item converts it to a message if it
+  // was a builder.
+  private MessageExternalList<MType, BType, IType> externalMessageList;
+
+  // A view of this builder that exposes a List interface of builders. This is
+  // initialized on demand. This is fully backed by this object and all changes
+  // are reflected in it. Access to any item converts it to a builder if it
+  // was a message.
+  private BuilderExternalList<MType, BType, IType> externalBuilderList;
+
+  // A view of this builder that exposes a List interface of the interface
+  // implemented by messages and builders. This is initialized on demand. This
+  // is fully backed by this object and all changes are reflected in it.
+  // Access to any item returns either a builder or message depending on
+  // what is most efficient.
+  private MessageOrBuilderExternalList<MType, BType, IType>
+      externalMessageOrBuilderList;
+
+  /**
+   * Constructs a new builder with an empty list of messages.
+   *
+   * @param messages the current list of messages
+   * @param isMessagesListMutable Whether the messages list is mutable
+   * @param parent a listener to notify of changes
+   * @param isClean whether the builder is initially marked clean
+   */
+  public RepeatedFieldBuilder(
+      List<MType> messages,
+      boolean isMessagesListMutable,
+      GeneratedMessage.BuilderParent parent,
+      boolean isClean) {
+    this.messages = messages;
+    this.isMessagesListMutable = isMessagesListMutable;
+    this.parent = parent;
+    this.isClean = isClean;
+  }
+
+  public void dispose() {
+    // Null out parent so we stop sending it invalidations.
+    parent = null;
+  }
+
+  /**
+   * Ensures that the list of messages is mutable so it can be updated. If it's
+   * immutable, a copy is made.
+   */
+  private void ensureMutableMessageList() {
+    if (!isMessagesListMutable) {
+      messages = new ArrayList<MType>(messages);
+      isMessagesListMutable = true;
+    }
+  }
+
+  /**
+   * Ensures that the list of builders is not null. If it's null, the list is
+   * created and initialized to be the same size as the messages list with
+   * null entries.
+   */
+  private void ensureBuilders() {
+    if (this.builders == null) {
+      this.builders =
+          new ArrayList<SingleFieldBuilder<MType, BType, IType>>(
+              messages.size());
+      for (int i = 0; i < messages.size(); i++) {
+        builders.add(null);
+      }
+    }
+  }
+
+  /**
+   * Gets the count of items in the list.
+   *
+   * @return the count of items in the list.
+   */
+  public int getCount() {
+    return messages.size();
+  }
+
+  /**
+   * Gets whether the list is empty.
+   *
+   * @return whether the list is empty
+   */
+  public boolean isEmpty() {
+    return messages.isEmpty();
+  }
+
+  /**
+   * Get the message at the specified index. If the message is currently stored
+   * as a {@code Builder}, it is converted to a {@code Message} by
+   * calling {@link Message.Builder#buildPartial} on it.
+   *
+   * @param index the index of the message to get
+   * @return the message for the specified index
+   */
+  public MType getMessage(int index) {
+    return getMessage(index, false);
+  }
+
+  /**
+   * Get the message at the specified index. If the message is currently stored
+   * as a {@code Builder}, it is converted to a {@code Message} by
+   * calling {@link Message.Builder#buildPartial} on it.
+   *
+   * @param index the index of the message to get
+   * @param forBuild this is being called for build so we want to make sure
+   *     we SingleFieldBuilder.build to send dirty invalidations
+   * @return the message for the specified index
+   */
+  private MType getMessage(int index, boolean forBuild) {
+    if (this.builders == null) {
+      // We don't have any builders -- return the current Message.
+      // This is the case where no builder was created, so we MUST have a
+      // Message.
+      return messages.get(index);
+    }
+
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      // We don't have a builder -- return the current message.
+      // This is the case where no builder was created for the entry at index,
+      // so we MUST have a message.
+      return messages.get(index);
+
+    } else {
+      return forBuild ? builder.build() : builder.getMessage();
+    }
+  }
+
+  /**
+   * Gets a builder for the specified index. If no builder has been created for
+   * that index, a builder is created on demand by calling
+   * {@link Message#toBuilder}.
+   *
+   * @param index the index of the message to get
+   * @return The builder for that index
+   */
+  public BType getBuilder(int index) {
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      MType message = messages.get(index);
+      builder = new SingleFieldBuilder<MType, BType, IType>(
+          message, this, isClean);
+      builders.set(index, builder);
+    }
+    return builder.getBuilder();
+  }
+
+  /**
+   * Gets the base class interface for the specified index. This may either be
+   * a builder or a message. It will return whatever is more efficient.
+   *
+   * @param index the index of the message to get
+   * @return the message or builder for the index as the base class interface
+   */
+  @SuppressWarnings("unchecked")
+  public IType getMessageOrBuilder(int index) {
+    if (this.builders == null) {
+      // We don't have any builders -- return the current Message.
+      // This is the case where no builder was created, so we MUST have a
+      // Message.
+      return (IType) messages.get(index);
+    }
+
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      // We don't have a builder -- return the current message.
+      // This is the case where no builder was created for the entry at index,
+      // so we MUST have a message.
+      return (IType) messages.get(index);
+
+    } else {
+      return builder.getMessageOrBuilder();
+    }
+  }
+
+  /**
+   * Sets a  message at the specified index replacing the existing item at
+   * that index.
+   *
+   * @param index the index to set.
+   * @param message the message to set
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> setMessage(
+      int index, MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.set(index, message);
+    if (builders != null) {
+      SingleFieldBuilder<MType, BType, IType> entry =
+          builders.set(index, null);
+      if (entry != null) {
+        entry.dispose();
+      }
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends the specified element to the end of this list.
+   *
+   * @param message the message to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+      MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.add(message);
+    if (builders != null) {
+      builders.add(null);
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Inserts the specified message at the specified position in this list.
+   * Shifts the element currently at that position (if any) and any subsequent
+   * elements to the right (adds one to their indices).
+   *
+   * @param index the index at which to insert the message
+   * @param message the message to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+      int index, MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.add(index, message);
+    if (builders != null) {
+      builders.add(index, null);
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends all of the messages in the specified collection to the end of
+   * this list, in the order that they are returned by the specified
+   * collection's iterator.
+   *
+   * @param values the messages to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
+      Iterable<? extends MType> values) {
+    for (final MType value : values) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+    }
+
+    // If we can inspect the size, we can more efficiently add messages.
+    int size = -1;
+    if (values instanceof Collection) {
+      @SuppressWarnings("unchecked") final
+      Collection<MType> collection = (Collection<MType>) values;
+      if (collection.size() == 0) {
+        return this;
+      }
+      size = collection.size();
+    }
+    ensureMutableMessageList();
+
+    if (size >= 0 && messages instanceof ArrayList) {
+      ((ArrayList<MType>) messages)
+          .ensureCapacity(messages.size() + size);
+    }
+
+    for (MType value : values) {
+      addMessage(value);
+    }
+
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends a new builder to the end of this list and returns the builder.
+   *
+   * @param message the message to add which is the basis of the builder
+   * @return the new builder
+   */
+  public BType addBuilder(MType message) {
+    ensureMutableMessageList();
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder =
+        new SingleFieldBuilder<MType, BType, IType>(
+            message, this, isClean);
+    messages.add(null);
+    builders.add(builder);
+    onChanged();
+    incrementModCounts();
+    return builder.getBuilder();
+  }
+
+  /**
+   * Inserts a new builder at the specified position in this list.
+   * Shifts the element currently at that position (if any) and any subsequent
+   * elements to the right (adds one to their indices).
+   *
+   * @param index the index at which to insert the builder
+   * @param message the message to add which is the basis of the builder
+   * @return the builder
+   */
+  public BType addBuilder(int index, MType message) {
+    ensureMutableMessageList();
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder =
+        new SingleFieldBuilder<MType, BType, IType>(
+            message, this, isClean);
+    messages.add(index, null);
+    builders.add(index, builder);
+    onChanged();
+    incrementModCounts();
+    return builder.getBuilder();
+  }
+
+  /**
+   * Removes the element at the specified position in this list. Shifts any
+   * subsequent elements to the left (subtracts one from their indices).
+   * Returns the element that was removed from the list.
+   *
+   * @param index the index at which to remove the message
+   */
+  public void remove(int index) {
+    ensureMutableMessageList();
+    messages.remove(index);
+    if (builders != null) {
+      SingleFieldBuilder<MType, BType, IType> entry =
+          builders.remove(index);
+      if (entry != null) {
+        entry.dispose();
+      }
+    }
+    onChanged();
+    incrementModCounts();
+  }
+
+  /**
+   * Removes all of the elements from this list.
+   * The list will be empty after this call returns.
+   */
+  public void clear() {
+    messages = Collections.emptyList();
+    isMessagesListMutable = false;
+    if (builders != null) {
+      for (SingleFieldBuilder<MType, BType, IType> entry :
+          builders) {
+        if (entry != null) {
+          entry.dispose();
+        }
+      }
+      builders = null;
+    }
+    onChanged();
+    incrementModCounts();
+  }
+
+  /**
+   * Builds the list of messages from the builder and returns them.
+   *
+   * @return an immutable list of messages
+   */
+  public List<MType> build() {
+    // Now that build has been called, we are required to dispatch
+    // invalidations.
+    isClean = true;
+
+    if (!isMessagesListMutable && builders == null) {
+      // We still have an immutable list and we never created a builder.
+      return messages;
+    }
+
+    boolean allMessagesInSync = true;
+    if (!isMessagesListMutable) {
+      // We still have an immutable list. Let's see if any of them are out
+      // of sync with their builders.
+      for (int i = 0; i < messages.size(); i++) {
+        Message message = messages.get(i);
+        SingleFieldBuilder<MType, BType, IType> builder = builders.get(i);
+        if (builder != null) {
+          if (builder.build() != message) {
+            allMessagesInSync = false;
+            break;
+          }
+        }
+      }
+      if (allMessagesInSync) {
+        // Immutable list is still in sync.
+        return messages;
+      }
+    }
+
+    // Need to make sure messages is up to date
+    ensureMutableMessageList();
+    for (int i = 0; i < messages.size(); i++) {
+      messages.set(i, getMessage(i, true));
+    }
+
+    // We're going to return our list as immutable so we mark that we can
+    // no longer update it.
+    messages = Collections.unmodifiableList(messages);
+    isMessagesListMutable = false;
+    return messages;
+  }
+
+  /**
+   * Gets a view of the builder as a list of messages. The returned list is live
+   * and will reflect any changes to the underlying builder.
+   *
+   * @return the messages in the list
+   */
+  public List<MType> getMessageList() {
+    if (externalMessageList == null) {
+      externalMessageList =
+          new MessageExternalList<MType, BType, IType>(this);
+    }
+    return externalMessageList;
+  }
+
+  /**
+   * Gets a view of the builder as a list of builders. This returned list is
+   * live and will reflect any changes to the underlying builder.
+   *
+   * @return the builders in the list
+   */
+  public List<BType> getBuilderList() {
+    if (externalBuilderList == null) {
+      externalBuilderList =
+          new BuilderExternalList<MType, BType, IType>(this);
+    }
+    return externalBuilderList;
+  }
+
+  /**
+   * Gets a view of the builder as a list of MessageOrBuilders. This returned
+   * list is live and will reflect any changes to the underlying builder.
+   *
+   * @return the builders in the list
+   */
+  public List<IType> getMessageOrBuilderList() {
+    if (externalMessageOrBuilderList == null) {
+      externalMessageOrBuilderList =
+          new MessageOrBuilderExternalList<MType, BType, IType>(this);
+    }
+    return externalMessageOrBuilderList;
+  }
+
+  /**
+   * Called when a the builder or one of its nested children has changed
+   * and any parent should be notified of its invalidation.
+   */
+  private void onChanged() {
+    if (isClean && parent != null) {
+      parent.markDirty();
+
+      // Don't keep dispatching invalidations until build is called again.
+      isClean = false;
+    }
+  }
+
+  @Override
+  public void markDirty() {
+    onChanged();
+  }
+
+  /**
+   * Increments the mod counts so that an ConcurrentModificationException can
+   * be thrown if calling code tries to modify the builder while its iterating
+   * the list.
+   */
+  private void incrementModCounts() {
+    if (externalMessageList != null) {
+      externalMessageList.incrementModCount();
+    }
+    if (externalBuilderList != null) {
+      externalBuilderList.incrementModCount();
+    }
+    if (externalMessageOrBuilderList != null) {
+      externalMessageOrBuilderList.incrementModCount();
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of messages.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class MessageExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<MType> implements List<MType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    MessageExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    @Override
+    public MType get(int index) {
+      return builder.getMessage(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of builders.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class BuilderExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<BType> implements List<BType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    BuilderExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    @Override
+    public BType get(int index) {
+      return builder.getBuilder(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of builders.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class MessageOrBuilderExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<IType> implements List<IType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    MessageOrBuilderExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    @Override
+    public IType get(int index) {
+      return builder.getMessageOrBuilder(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RopeByteString.java
new file mode 100644
index 0000000..3f3e9bd
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -0,0 +1,896 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+/**
+ * Class to represent {@code ByteStrings} formed by concatenation of other
+ * ByteStrings, without copying the data in the pieces. The concatenation is
+ * represented as a tree whose leaf nodes are each a
+ * {@link com.google.protobuf.ByteString.LeafByteString}.
+ *
+ * <p>Most of the operation here is inspired by the now-famous paper <a
+ * href="https://web.archive.org/web/20060202015456/http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a> Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and
+ * michael plass
+ *
+ * <p>The algorithms described in the paper have been implemented for character
+ * strings in {@code com.google.common.string.Rope} and in the c++ class {@code
+ * cord.cc}.
+ *
+ * <p>Fundamentally the Rope algorithm represents the collection of pieces as a
+ * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum
+ * sequence length, sequences that are too short relative to their depth cause a
+ * tree rebalance.  More precisely, a tree of depth d is "balanced" in the
+ * terminology of BAP95 if its length is at least F(d+2), where F(n) is the
+ * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum
+ * lengths 1, 2, 3, 5, 8, 13,...
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+final class RopeByteString extends ByteString {
+
+  /**
+   * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of
+   * depth n is "balanced", i.e flat enough, if its length is at least Fn+2,
+   * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at
+   * least 2, of depth 4 must have length >= 8, etc.
+   *
+   * <p>There's nothing special about using the Fibonacci numbers for this, but
+   * they are a reasonable sequence for encapsulating the idea that we are OK
+   * with longer strings being encoded in deeper binary trees.
+   *
+   * <p>For 32-bit integers, this array has length 46.
+   */
+  private static final int[] minLengthByDepth;
+
+  static {
+    // Dynamically generate the list of Fibonacci numbers the first time this
+    // class is accessed.
+    List<Integer> numbers = new ArrayList<Integer>();
+
+    // we skip the first Fibonacci number (1).  So instead of: 1 1 2 3 5 8 ...
+    // we have: 1 2 3 5 8 ...
+    int f1 = 1;
+    int f2 = 1;
+
+    // get all the values until we roll over.
+    while (f2 > 0) {
+      numbers.add(f2);
+      int temp = f1 + f2;
+      f1 = f2;
+      f2 = temp;
+    }
+
+    // we include this here so that we can index this array to [x + 1] in the
+    // loops below.
+    numbers.add(Integer.MAX_VALUE);
+    minLengthByDepth = new int[numbers.size()];
+    for (int i = 0; i < minLengthByDepth.length; i++) {
+      // unbox all the values
+      minLengthByDepth[i] = numbers.get(i);
+    }
+  }
+
+  private final int totalLength;
+  private final ByteString left;
+  private final ByteString right;
+  private final int leftLength;
+  private final int treeDepth;
+
+  /**
+   * Create a new RopeByteString, which can be thought of as a new tree node, by
+   * recording references to the two given strings.
+   *
+   * @param left  string on the left of this node, should have {@code size() >
+   *              0}
+   * @param right string on the right of this node, should have {@code size() >
+   *              0}
+   */
+  private RopeByteString(ByteString left, ByteString right) {
+    this.left = left;
+    this.right = right;
+    leftLength = left.size();
+    totalLength = leftLength + right.size();
+    treeDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+  }
+
+  /**
+   * Concatenate the given strings while performing various optimizations to
+   * slow the growth rate of tree depth and tree node count. The result is
+   * either a {@link com.google.protobuf.ByteString.LeafByteString} or a
+   * {@link RopeByteString} depending on which optimizations, if any, were
+   * applied.
+   *
+   * <p>Small pieces of length less than {@link
+   * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in
+   * BAP95.  Large pieces are referenced without copy.
+   *
+   * @param left  string on the left
+   * @param right string on the right
+   * @return concatenation representing the same sequence as the given strings
+   */
+  static ByteString concatenate(ByteString left, ByteString right) {
+    if (right.size() == 0) {
+      return left;
+    }
+
+    if (left.size() == 0) {
+      return right;
+    }
+
+    final int newLength = left.size() + right.size();
+    if (newLength < ByteString.CONCATENATE_BY_COPY_SIZE) {
+      // Optimization from BAP95: For short (leaves in paper, but just short
+      // here) total length, do a copy of data to a new leaf.
+      return concatenateBytes(left, right);
+    }
+
+    if (left instanceof RopeByteString) {
+      final RopeByteString leftRope = (RopeByteString) left;
+      if (leftRope.right.size() + right.size() < CONCATENATE_BY_COPY_SIZE) {
+        // Optimization from BAP95: As an optimization of the case where the
+        // ByteString is constructed by repeated concatenate, recognize the case
+        // where a short string is concatenated to a left-hand node whose
+        // right-hand branch is short.  In the paper this applies to leaves, but
+        // we just look at the length here. This has the advantage of shedding
+        // references to unneeded data when substrings have been taken.
+        //
+        // When we recognize this case, we do a copy of the data and create a
+        // new parent node so that the depth of the result is the same as the
+        // given left tree.
+        ByteString newRight = concatenateBytes(leftRope.right, right);
+        return new RopeByteString(leftRope.left, newRight);
+      }
+
+      if (leftRope.left.getTreeDepth() > leftRope.right.getTreeDepth()
+          && leftRope.getTreeDepth() > right.getTreeDepth()) {
+        // Typically for concatenate-built strings the left-side is deeper than
+        // the right.  This is our final attempt to concatenate without
+        // increasing the tree depth.  We'll redo the node on the RHS.  This
+        // is yet another optimization for building the string by repeatedly
+        // concatenating on the right.
+        ByteString newRight = new RopeByteString(leftRope.right, right);
+        return new RopeByteString(leftRope.left, newRight);
+      }
+    }
+
+    // Fine, we'll add a node and increase the tree depth--unless we rebalance ;^)
+    int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+    if (newLength >= minLengthByDepth[newDepth]) {
+      // The tree is shallow enough, so don't rebalance
+      return new RopeByteString(left, right);
+    }
+
+    return new Balancer().balance(left, right);
+  }
+
+  /**
+   * Concatenates two strings by copying data values. This is called in a few
+   * cases in order to reduce the growth of the number of tree nodes.
+   *
+   * @param left  string on the left
+   * @param right string on the right
+   * @return string formed by copying data bytes
+   */
+  private static ByteString concatenateBytes(ByteString left,
+      ByteString right) {
+    int leftSize = left.size();
+    int rightSize = right.size();
+    byte[] bytes = new byte[leftSize + rightSize];
+    left.copyTo(bytes, 0, 0, leftSize);
+    right.copyTo(bytes, 0, leftSize, rightSize);
+    return ByteString.wrap(bytes);  // Constructor wraps bytes
+  }
+
+  /**
+   * Create a new RopeByteString for testing only while bypassing all the
+   * defenses of {@link #concatenate(ByteString, ByteString)}. This allows
+   * testing trees of specific structure. We are also able to insert empty
+   * leaves, though these are dis-allowed, so that we can make sure the
+   * implementation can withstand their presence.
+   *
+   * @param left  string on the left of this node
+   * @param right string on the right of this node
+   * @return an unsafe instance for testing only
+   */
+  static RopeByteString newInstanceForTest(ByteString left, ByteString right) {
+    return new RopeByteString(left, right);
+  }
+
+  /**
+   * Gets the byte at the given index.
+   * Throws {@link ArrayIndexOutOfBoundsException} for backwards-compatibility
+   * reasons although it would more properly be {@link
+   * IndexOutOfBoundsException}.
+   *
+   * @param index index of byte
+   * @return the value
+   * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+   */
+  @Override
+  public byte byteAt(int index) {
+    checkIndex(index, totalLength);
+
+    // Find the relevant piece by recursive descent
+    if (index < leftLength) {
+      return left.byteAt(index);
+    }
+
+    return right.byteAt(index - leftLength);
+  }
+
+  @Override
+  public int size() {
+    return totalLength;
+  }
+
+  // =================================================================
+  // Pieces
+
+  @Override
+  protected int getTreeDepth() {
+    return treeDepth;
+  }
+
+  /**
+   * Determines if the tree is balanced according to BAP95, which means the tree
+   * is flat-enough with respect to the bounds. Note that this definition of
+   * balanced is one where sub-trees of balanced trees are not necessarily
+   * balanced.
+   *
+   * @return true if the tree is balanced
+   */
+  @Override
+  protected boolean isBalanced() {
+    return totalLength >= minLengthByDepth[treeDepth];
+  }
+
+  /**
+   * Takes a substring of this one. This involves recursive descent along the
+   * left and right edges of the substring, and referencing any wholly contained
+   * segments in between. Any leaf nodes entirely uninvolved in the substring
+   * will not be referenced by the substring.
+   *
+   * <p>Substrings of {@code length < 2} should result in at most a single
+   * recursive call chain, terminating at a leaf node. Thus the result will be a
+   * {@link com.google.protobuf.ByteString.LeafByteString}.
+   *
+   * @param beginIndex start at this index
+   * @param endIndex   the last character is the one before this index
+   * @return substring leaf node or tree
+   */
+  @Override
+  public ByteString substring(int beginIndex, int endIndex) {
+    final int length = checkRange(beginIndex, endIndex, totalLength);
+
+    if (length == 0) {
+      // Empty substring
+      return ByteString.EMPTY;
+    }
+
+    if (length == totalLength) {
+      // The whole string
+      return this;
+    }
+
+    // Proper substring
+    if (endIndex <= leftLength) {
+      // Substring on the left
+      return left.substring(beginIndex, endIndex);
+    }
+
+    if (beginIndex >= leftLength) {
+      // Substring on the right
+      return right.substring(beginIndex - leftLength, endIndex - leftLength);
+    }
+
+    // Split substring
+    ByteString leftSub = left.substring(beginIndex);
+    ByteString rightSub = right.substring(0, endIndex - leftLength);
+    // Intentionally not rebalancing, since in many cases these two
+    // substrings will already be less deep than the top-level
+    // RopeByteString we're taking a substring of.
+    return new RopeByteString(leftSub, rightSub);
+  }
+
+  // =================================================================
+  // ByteString -> byte[]
+
+  @Override
+  protected void copyToInternal(byte[] target, int sourceOffset,
+      int targetOffset, int numberToCopy) {
+   if (sourceOffset + numberToCopy <= leftLength) {
+      left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+    } else if (sourceOffset >= leftLength) {
+      right.copyToInternal(target, sourceOffset - leftLength, targetOffset,
+          numberToCopy);
+    } else {
+      int leftLength = this.leftLength - sourceOffset;
+      left.copyToInternal(target, sourceOffset, targetOffset, leftLength);
+      right.copyToInternal(target, 0, targetOffset + leftLength,
+          numberToCopy - leftLength);
+    }
+  }
+
+  @Override
+  public void copyTo(ByteBuffer target) {
+    left.copyTo(target);
+    right.copyTo(target);
+  }
+
+  @Override
+  public ByteBuffer asReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer = ByteBuffer.wrap(toByteArray());
+    return byteBuffer.asReadOnlyBuffer();
+  }
+
+  @Override
+  public List<ByteBuffer> asReadOnlyByteBufferList() {
+    // Walk through the list of LeafByteString's that make up this
+    // rope, and add each one as a read-only ByteBuffer.
+    List<ByteBuffer> result = new ArrayList<ByteBuffer>();
+    PieceIterator pieces = new PieceIterator(this);
+    while (pieces.hasNext()) {
+      LeafByteString byteString = pieces.next();
+      result.add(byteString.asReadOnlyByteBuffer());
+    }
+    return result;
+  }
+
+  @Override
+  public void writeTo(OutputStream outputStream) throws IOException {
+    left.writeTo(outputStream);
+    right.writeTo(outputStream);
+  }
+
+  @Override
+  void writeToInternal(OutputStream out, int sourceOffset,
+      int numberToWrite) throws IOException {
+    if (sourceOffset + numberToWrite <= leftLength) {
+      left.writeToInternal(out, sourceOffset, numberToWrite);
+    } else if (sourceOffset >= leftLength) {
+      right.writeToInternal(out, sourceOffset - leftLength, numberToWrite);
+    } else {
+      int numberToWriteInLeft = leftLength - sourceOffset;
+      left.writeToInternal(out, sourceOffset, numberToWriteInLeft);
+      right.writeToInternal(out, 0, numberToWrite - numberToWriteInLeft);
+    }
+  }
+
+  @Override
+  void writeTo(ByteOutput output) throws IOException {
+    left.writeTo(output);
+    right.writeTo(output);
+  }
+
+  @Override
+  protected String toStringInternal(Charset charset) {
+    return new String(toByteArray(), charset);
+  }
+
+  // =================================================================
+  // UTF-8 decoding
+
+  @Override
+  public boolean isValidUtf8() {
+    int leftPartial = left.partialIsValidUtf8(Utf8.COMPLETE, 0, leftLength);
+    int state = right.partialIsValidUtf8(leftPartial, 0, right.size());
+    return state == Utf8.COMPLETE;
+  }
+
+  @Override
+  protected int partialIsValidUtf8(int state, int offset, int length) {
+    int toIndex = offset + length;
+    if (toIndex <= leftLength) {
+      return left.partialIsValidUtf8(state, offset, length);
+    } else if (offset >= leftLength) {
+      return right.partialIsValidUtf8(state, offset - leftLength, length);
+    } else {
+      int leftLength = this.leftLength - offset;
+      int leftPartial = left.partialIsValidUtf8(state, offset, leftLength);
+      return right.partialIsValidUtf8(leftPartial, 0, length - leftLength);
+    }
+  }
+
+  // =================================================================
+  // equals() and hashCode()
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof ByteString)) {
+      return false;
+    }
+
+    ByteString otherByteString = (ByteString) other;
+    if (totalLength != otherByteString.size()) {
+      return false;
+    }
+    if (totalLength == 0) {
+      return true;
+    }
+
+    // You don't really want to be calling equals on long strings, but since
+    // we cache the hashCode, we effectively cache inequality. We use the cached
+    // hashCode if it's already computed.  It's arguable we should compute the
+    // hashCode here, and if we're going to be testing a bunch of byteStrings,
+    // it might even make sense.
+    int thisHash = peekCachedHashCode();
+    int thatHash = otherByteString.peekCachedHashCode();
+    if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
+      return false;
+    }
+
+    return equalsFragments(otherByteString);
+  }
+
+  /**
+   * Determines if this string is equal to another of the same length by
+   * iterating over the leaf nodes. On each step of the iteration, the
+   * overlapping segments of the leaves are compared.
+   *
+   * @param other string of the same length as this one
+   * @return true if the values of this string equals the value of the given
+   *         one
+   */
+  private boolean equalsFragments(ByteString other) {
+    int thisOffset = 0;
+    Iterator<LeafByteString> thisIter = new PieceIterator(this);
+    LeafByteString thisString = thisIter.next();
+
+    int thatOffset = 0;
+    Iterator<LeafByteString> thatIter = new PieceIterator(other);
+    LeafByteString thatString = thatIter.next();
+
+    int pos = 0;
+    while (true) {
+      int thisRemaining = thisString.size() - thisOffset;
+      int thatRemaining = thatString.size() - thatOffset;
+      int bytesToCompare = Math.min(thisRemaining, thatRemaining);
+
+      // At least one of the offsets will be zero
+      boolean stillEqual = (thisOffset == 0)
+          ? thisString.equalsRange(thatString, thatOffset, bytesToCompare)
+          : thatString.equalsRange(thisString, thisOffset, bytesToCompare);
+      if (!stillEqual) {
+        return false;
+      }
+
+      pos += bytesToCompare;
+      if (pos >= totalLength) {
+        if (pos == totalLength) {
+          return true;
+        }
+        throw new IllegalStateException();
+      }
+      // We always get to the end of at least one of the pieces
+      if (bytesToCompare == thisRemaining) { // If reached end of this
+        thisOffset = 0;
+        thisString = thisIter.next();
+      } else {
+        thisOffset += bytesToCompare;
+      }
+      if (bytesToCompare == thatRemaining) { // If reached end of that
+        thatOffset = 0;
+        thatString = thatIter.next();
+      } else {
+        thatOffset += bytesToCompare;
+      }
+    }
+  }
+
+  @Override
+  protected int partialHash(int h, int offset, int length) {
+    int toIndex = offset + length;
+    if (toIndex <= leftLength) {
+      return left.partialHash(h, offset, length);
+    } else if (offset >= leftLength) {
+      return right.partialHash(h, offset - leftLength, length);
+    } else {
+      int leftLength = this.leftLength - offset;
+      int leftPartial = left.partialHash(h, offset, leftLength);
+      return right.partialHash(leftPartial, 0, length - leftLength);
+    }
+  }
+
+  // =================================================================
+  // Input stream
+
+  @Override
+  public CodedInputStream newCodedInput() {
+    return CodedInputStream.newInstance(new RopeInputStream());
+  }
+
+  @Override
+  public InputStream newInput() {
+    return new RopeInputStream();
+  }
+
+  /**
+   * This class implements the balancing algorithm of BAP95. In the paper the
+   * authors use an array to keep track of pieces, while here we use a stack.
+   * The tree is balanced by traversing subtrees in left to right order, and the
+   * stack always contains the part of the string we've traversed so far.
+   *
+   * <p>One surprising aspect of the algorithm is the result of balancing is not
+   * necessarily balanced, though it is nearly balanced.  For details, see
+   * BAP95.
+   */
+  private static class Balancer {
+    // Stack containing the part of the string, starting from the left, that
+    // we've already traversed.  The final string should be the equivalent of
+    // concatenating the strings on the stack from bottom to top.
+    private final Stack<ByteString> prefixesStack = new Stack<ByteString>();
+
+    private ByteString balance(ByteString left, ByteString right) {
+      doBalance(left);
+      doBalance(right);
+
+      // Sweep stack to gather the result
+      ByteString partialString = prefixesStack.pop();
+      while (!prefixesStack.isEmpty()) {
+        ByteString newLeft = prefixesStack.pop();
+        partialString = new RopeByteString(newLeft, partialString);
+      }
+      // We should end up with a RopeByteString since at a minimum we will
+      // create one from concatenating left and right
+      return partialString;
+    }
+
+    private void doBalance(ByteString root) {
+      // BAP95: Insert balanced subtrees whole. This means the result might not
+      // be balanced, leading to repeated rebalancings on concatenate. However,
+      // these rebalancings are shallow due to ignoring balanced subtrees, and
+      // relatively few calls to insert() result.
+      if (root.isBalanced()) {
+        insert(root);
+      } else if (root instanceof RopeByteString) {
+        RopeByteString rbs = (RopeByteString) root;
+        doBalance(rbs.left);
+        doBalance(rbs.right);
+      } else {
+        throw new IllegalArgumentException(
+            "Has a new type of ByteString been created? Found " +
+                root.getClass());
+      }
+    }
+
+    /**
+     * Push a string on the balance stack (BAP95).  BAP95 uses an array and
+     * calls the elements in the array 'bins'.  We instead use a stack, so the
+     * 'bins' of lengths are represented by differences between the elements of
+     * minLengthByDepth.
+     *
+     * <p>If the length bin for our string, and all shorter length bins, are
+     * empty, we just push it on the stack.  Otherwise, we need to start
+     * concatenating, putting the given string in the "middle" and continuing
+     * until we land in an empty length bin that matches the length of our
+     * concatenation.
+     *
+     * @param byteString string to place on the balance stack
+     */
+    private void insert(ByteString byteString) {
+      int depthBin = getDepthBinForLength(byteString.size());
+      int binEnd = minLengthByDepth[depthBin + 1];
+
+      // BAP95: Concatenate all trees occupying bins representing the length of
+      // our new piece or of shorter pieces, to the extent that is possible.
+      // The goal is to clear the bin which our piece belongs in, but that may
+      // not be entirely possible if there aren't enough longer bins occupied.
+      if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) {
+        prefixesStack.push(byteString);
+      } else {
+        int binStart = minLengthByDepth[depthBin];
+
+        // Concatenate the subtrees of shorter length
+        ByteString newTree = prefixesStack.pop();
+        while (!prefixesStack.isEmpty()
+            && prefixesStack.peek().size() < binStart) {
+          ByteString left = prefixesStack.pop();
+          newTree = new RopeByteString(left, newTree);
+        }
+
+        // Concatenate the given string
+        newTree = new RopeByteString(newTree, byteString);
+
+        // Continue concatenating until we land in an empty bin
+        while (!prefixesStack.isEmpty()) {
+          depthBin = getDepthBinForLength(newTree.size());
+          binEnd = minLengthByDepth[depthBin + 1];
+          if (prefixesStack.peek().size() < binEnd) {
+            ByteString left = prefixesStack.pop();
+            newTree = new RopeByteString(left, newTree);
+          } else {
+            break;
+          }
+        }
+        prefixesStack.push(newTree);
+      }
+    }
+
+    private int getDepthBinForLength(int length) {
+      int depth = Arrays.binarySearch(minLengthByDepth, length);
+      if (depth < 0) {
+        // It wasn't an exact match, so convert to the index of the containing
+        // fragment, which is one less even than the insertion point.
+        int insertionPoint = -(depth + 1);
+        depth = insertionPoint - 1;
+      }
+
+      return depth;
+    }
+  }
+
+  /**
+   * This class is a continuable tree traversal, which keeps the state
+   * information which would exist on the stack in a recursive traversal instead
+   * on a stack of "Bread Crumbs". The maximum depth of the stack in this
+   * iterator is the same as the depth of the tree being traversed.
+   *
+   * <p>This iterator is used to implement
+   * {@link RopeByteString#equalsFragments(ByteString)}.
+   */
+  private static class PieceIterator implements Iterator<LeafByteString> {
+
+    private final Stack<RopeByteString> breadCrumbs =
+        new Stack<RopeByteString>();
+    private LeafByteString next;
+
+    private PieceIterator(ByteString root) {
+      next = getLeafByLeft(root);
+    }
+
+    private LeafByteString getLeafByLeft(ByteString root) {
+      ByteString pos = root;
+      while (pos instanceof RopeByteString) {
+        RopeByteString rbs = (RopeByteString) pos;
+        breadCrumbs.push(rbs);
+        pos = rbs.left;
+      }
+      return (LeafByteString) pos;
+    }
+
+    private LeafByteString getNextNonEmptyLeaf() {
+      while (true) {
+        // Almost always, we go through this loop exactly once.  However, if
+        // we discover an empty string in the rope, we toss it and try again.
+        if (breadCrumbs.isEmpty()) {
+          return null;
+        } else {
+          LeafByteString result = getLeafByLeft(breadCrumbs.pop().right);
+          if (!result.isEmpty()) {
+            return result;
+          }
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext() {
+      return next != null;
+    }
+
+    /**
+     * Returns the next item and advances one
+     * {@link com.google.protobuf.ByteString.LeafByteString}.
+     *
+     * @return next non-empty LeafByteString or {@code null}
+     */
+    @Override
+    public LeafByteString next() {
+      if (next == null) {
+        throw new NoSuchElementException();
+      }
+      LeafByteString result = next;
+      next = getNextNonEmptyLeaf();
+      return result;
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  // =================================================================
+  // Serializable
+
+  private static final long serialVersionUID = 1L;
+
+  Object writeReplace() {
+    return ByteString.wrap(toByteArray());
+  }
+
+  private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
+    throw new InvalidObjectException(
+        "RopeByteStream instances are not to be serialized directly");
+  }
+
+  /**
+   * This class is the {@link RopeByteString} equivalent for
+   * {@link ByteArrayInputStream}.
+   */
+  private class RopeInputStream extends InputStream {
+    // Iterates through the pieces of the rope
+    private PieceIterator pieceIterator;
+    // The current piece
+    private LeafByteString currentPiece;
+    // The size of the current piece
+    private int currentPieceSize;
+    // The index of the next byte to read in the current piece
+    private int currentPieceIndex;
+    // The offset of the start of the current piece in the rope byte string
+    private int currentPieceOffsetInRope;
+    // Offset in the buffer at which user called mark();
+    private int mark;
+
+    public RopeInputStream() {
+      initialize();
+    }
+
+    @Override
+    public int read(byte b[], int offset, int length)  {
+      if (b == null) {
+        throw new NullPointerException();
+      } else if (offset < 0 || length < 0 || length > b.length - offset) {
+        throw new IndexOutOfBoundsException();
+      }
+      return readSkipInternal(b, offset, length);
+    }
+
+    @Override
+    public long skip(long length) {
+      if (length < 0) {
+        throw new IndexOutOfBoundsException();
+      } else if (length > Integer.MAX_VALUE) {
+        length = Integer.MAX_VALUE;
+      }
+      return readSkipInternal(null, 0, (int) length);
+    }
+
+    /**
+     * Internal implementation of read and skip.  If b != null, then read the
+     * next {@code length} bytes into the buffer {@code b} at
+     * offset {@code offset}.  If b == null, then skip the next {@code length}
+     * bytes.
+     * <p>
+     * This method assumes that all error checking has already happened.
+     * <p>
+     * Returns the actual number of bytes read or skipped.
+     */
+    private int readSkipInternal(byte b[], int offset, int length)  {
+      int bytesRemaining = length;
+      while (bytesRemaining > 0) {
+        advanceIfCurrentPieceFullyRead();
+        if (currentPiece == null) {
+          if (bytesRemaining == length) {
+             // We didn't manage to read anything
+             return -1;
+           }
+          break;
+        } else {
+          // Copy the bytes from this piece.
+          int currentPieceRemaining = currentPieceSize - currentPieceIndex;
+          int count = Math.min(currentPieceRemaining, bytesRemaining);
+          if (b != null) {
+            currentPiece.copyTo(b, currentPieceIndex, offset, count);
+            offset += count;
+          }
+          currentPieceIndex += count;
+          bytesRemaining -= count;
+        }
+      }
+       // Return the number of bytes read.
+      return length - bytesRemaining;
+    }
+
+    @Override
+    public int read() throws IOException {
+      advanceIfCurrentPieceFullyRead();
+      if (currentPiece == null) {
+        return -1;
+      } else {
+        return currentPiece.byteAt(currentPieceIndex++) & 0xFF;
+      }
+    }
+
+    @Override
+    public int available() throws IOException {
+      int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
+      return RopeByteString.this.size() - bytesRead;
+    }
+
+    @Override
+    public boolean markSupported() {
+      return true;
+    }
+
+    @Override
+    public void mark(int readAheadLimit) {
+      // Set the mark to our position in the byte string
+      mark = currentPieceOffsetInRope + currentPieceIndex;
+    }
+
+    @Override
+    public synchronized void reset() {
+      // Just reinitialize and skip the specified number of bytes.
+      initialize();
+      readSkipInternal(null, 0, mark);
+    }
+
+    /** Common initialization code used by both the constructor and reset() */
+    private void initialize() {
+      pieceIterator = new PieceIterator(RopeByteString.this);
+      currentPiece = pieceIterator.next();
+      currentPieceSize = currentPiece.size();
+      currentPieceIndex = 0;
+      currentPieceOffsetInRope = 0;
+    }
+
+    /**
+     * Skips to the next piece if we have read all the data in the current
+     * piece.  Sets currentPiece to null if we have reached the end of the
+     * input.
+     */
+    private void advanceIfCurrentPieceFullyRead() {
+      if (currentPiece != null && currentPieceIndex == currentPieceSize) {
+        // Generally, we can only go through this loop at most once, since
+        // empty strings can't end up in a rope.  But better to test.
+        currentPieceOffsetInRope += currentPieceSize;
+        currentPieceIndex = 0;
+        if (pieceIterator.hasNext()) {
+          currentPiece = pieceIterator.next();
+          currentPieceSize = currentPiece.size();
+        } else {
+          currentPiece = null;
+          currentPieceSize = 0;
+        }
+      }
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcCallback.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcCallback.java
new file mode 100644
index 0000000..1075296
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcCallback.java
@@ -0,0 +1,47 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Interface for an RPC callback, normally called when an RPC completes.
+ * {@code ParameterType} is normally the method's response message type.
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation.  This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcCallback<ParameterType> {
+  void run(ParameterType parameter);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcChannel.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcChannel.java
new file mode 100644
index 0000000..f272f4a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcChannel.java
@@ -0,0 +1,71 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * <p>Abstract interface for an RPC channel.  An {@code RpcChannel} represents a
+ * communication line to a {@link Service} which can be used to call that
+ * {@link Service}'s methods.  The {@link Service} may be running on another
+ * machine.  Normally, you should not call an {@code RpcChannel} directly, but
+ * instead construct a stub {@link Service} wrapping it.  Example:
+ *
+ * <pre>
+ *   RpcChannel channel = rpcImpl.newChannel("remotehost.example.com:1234");
+ *   RpcController controller = rpcImpl.newController();
+ *   MyService service = MyService.newStub(channel);
+ *   service.myMethod(controller, request, callback);
+ * </pre>
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation.  This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcChannel {
+  /**
+   * Call the given method of the remote service.  This method is similar to
+   * {@code Service.callMethod()} with one important difference:  the caller
+   * decides the types of the {@code Message} objects, not the callee.  The
+   * request may be of any type as long as
+   * {@code request.getDescriptor() == method.getInputType()}.
+   * The response passed to the callback will be of the same type as
+   * {@code responsePrototype} (which must have
+   * {@code getDescriptor() == method.getOutputType()}).
+   */
+  void callMethod(Descriptors.MethodDescriptor method,
+                  RpcController controller,
+                  Message request,
+                  Message responsePrototype,
+                  RpcCallback<Message> done);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcController.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcController.java
new file mode 100644
index 0000000..a92dd7b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcController.java
@@ -0,0 +1,118 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * <p>An {@code RpcController} mediates a single method call.  The primary
+ * purpose of the controller is to provide a way to manipulate settings
+ * specific to the RPC implementation and to find out about RPC-level errors.
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation.  This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * <p>The methods provided by the {@code RpcController} interface are intended
+ * to be a "least common denominator" set of features which we expect all
+ * implementations to support.  Specific implementations may provide more
+ * advanced features (e.g. deadline propagation).
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcController {
+  // -----------------------------------------------------------------
+  // These calls may be made from the client side only.  Their results
+  // are undefined on the server side (may throw RuntimeExceptions).
+
+  /**
+   * Resets the RpcController to its initial state so that it may be reused in
+   * a new call.  This can be called from the client side only.  It must not
+   * be called while an RPC is in progress.
+   */
+  void reset();
+
+  /**
+   * After a call has finished, returns true if the call failed.  The possible
+   * reasons for failure depend on the RPC implementation.  {@code failed()}
+   * most only be called on the client side, and must not be called before a
+   * call has finished.
+   */
+  boolean failed();
+
+  /**
+   * If {@code failed()} is {@code true}, returns a human-readable description
+   * of the error.
+   */
+  String errorText();
+
+  /**
+   * Advises the RPC system that the caller desires that the RPC call be
+   * canceled.  The RPC system may cancel it immediately, may wait awhile and
+   * then cancel it, or may not even cancel the call at all.  If the call is
+   * canceled, the "done" callback will still be called and the RpcController
+   * will indicate that the call failed at that time.
+   */
+  void startCancel();
+
+  // -----------------------------------------------------------------
+  // These calls may be made from the server side only.  Their results
+  // are undefined on the client side (may throw RuntimeExceptions).
+
+  /**
+   * Causes {@code failed()} to return true on the client side.  {@code reason}
+   * will be incorporated into the message returned by {@code errorText()}.
+   * If you find you need to return machine-readable information about
+   * failures, you should incorporate it into your response protocol buffer
+   * and should NOT call {@code setFailed()}.
+   */
+  void setFailed(String reason);
+
+  /**
+   * If {@code true}, indicates that the client canceled the RPC, so the server
+   * may as well give up on replying to it.  This method must be called on the
+   * server side only.  The server should still call the final "done" callback.
+   */
+  boolean isCanceled();
+
+  /**
+   * Asks that the given callback be called when the RPC is canceled.  The
+   * parameter passed to the callback will always be {@code null}.  The
+   * callback will always be called exactly once.  If the RPC completes without
+   * being canceled, the callback will be called after completion.  If the RPC
+   * has already been canceled when NotifyOnCancel() is called, the callback
+   * will be called immediately.
+   *
+   * <p>{@code notifyOnCancel()} must be called no more than once per request.
+   * It must be called on the server side only.
+   */
+  void notifyOnCancel(RpcCallback<Object> callback);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcUtil.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcUtil.java
new file mode 100644
index 0000000..f7d555a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/RpcUtil.java
@@ -0,0 +1,136 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Grab-bag of utility functions useful when dealing with RPCs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class RpcUtil {
+  private RpcUtil() {}
+
+  /**
+   * Take an {@code RpcCallback<Message>} and convert it to an
+   * {@code RpcCallback} accepting a specific message type.  This is always
+   * type-safe (parameter type contravariance).
+   */
+  @SuppressWarnings("unchecked")
+  public static <Type extends Message> RpcCallback<Type>
+  specializeCallback(final RpcCallback<Message> originalCallback) {
+    return (RpcCallback<Type>)originalCallback;
+    // The above cast works, but only due to technical details of the Java
+    // implementation.  A more theoretically correct -- but less efficient --
+    // implementation would be as follows:
+    //   return new RpcCallback<Type>() {
+    //     public void run(Type parameter) {
+    //       originalCallback.run(parameter);
+    //     }
+    //   };
+  }
+
+  /**
+   * Take an {@code RpcCallback} accepting a specific message type and convert
+   * it to an {@code RpcCallback<Message>}.  The generalized callback will
+   * accept any message object which has the same descriptor, and will convert
+   * it to the correct class before calling the original callback.  However,
+   * if the generalized callback is given a message with a different descriptor,
+   * an exception will be thrown.
+   */
+  public static <Type extends Message>
+  RpcCallback<Message> generalizeCallback(
+      final RpcCallback<Type> originalCallback,
+      final Class<Type> originalClass,
+      final Type defaultInstance) {
+    return new RpcCallback<Message>() {
+      @Override
+      public void run(final Message parameter) {
+        Type typedParameter;
+        try {
+          typedParameter = originalClass.cast(parameter);
+        } catch (ClassCastException ignored) {
+          typedParameter = copyAsType(defaultInstance, parameter);
+        }
+        originalCallback.run(typedParameter);
+      }
+    };
+  }
+
+  /**
+   * Creates a new message of type "Type" which is a copy of "source".  "source"
+   * must have the same descriptor but may be a different class (e.g.
+   * DynamicMessage).
+   */
+  @SuppressWarnings("unchecked")
+  private static <Type extends Message> Type copyAsType(
+      final Type typeDefaultInstance, final Message source) {
+    return (Type) typeDefaultInstance
+        .newBuilderForType().mergeFrom(source).build();
+  }
+
+  /**
+   * Creates a callback which can only be called once.  This may be useful for
+   * security, when passing a callback to untrusted code:  most callbacks do
+   * not expect to be called more than once, so doing so may expose bugs if it
+   * is not prevented.
+   */
+  public static <ParameterType>
+    RpcCallback<ParameterType> newOneTimeCallback(
+      final RpcCallback<ParameterType> originalCallback) {
+    return new RpcCallback<ParameterType>() {
+      private boolean alreadyCalled = false;
+
+      @Override
+      public void run(final ParameterType parameter) {
+        synchronized (this) {
+          if (alreadyCalled) {
+            throw new AlreadyCalledException();
+          }
+          alreadyCalled = true;
+        }
+
+        originalCallback.run(parameter);
+      }
+    };
+  }
+
+  /**
+   * Exception thrown when a one-time callback is called more than once.
+   */
+  public static final class AlreadyCalledException extends RuntimeException {
+    private static final long serialVersionUID = 5469741279507848266L;
+
+    public AlreadyCalledException() {
+      super("This RpcCallback was already called and cannot be called " +
+            "multiple times.");
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Service.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Service.java
new file mode 100644
index 0000000..ba7b033
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Service.java
@@ -0,0 +1,117 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Abstract base interface for protocol-buffer-based RPC services.  Services
+ * themselves are abstract classes (implemented either by servers or as
+ * stubs), but they subclass this base interface.  The methods of this
+ * interface can be used to call the methods of the service without knowing
+ * its exact type at compile time (analogous to the Message interface).
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation.  This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface Service {
+  /**
+   * Get the {@code ServiceDescriptor} describing this service and its methods.
+   */
+  Descriptors.ServiceDescriptor getDescriptorForType();
+
+  /**
+   * <p>Call a method of the service specified by MethodDescriptor.  This is
+   * normally implemented as a simple {@code switch()} that calls the standard
+   * definitions of the service's methods.
+   *
+   * <p>Preconditions:
+   * <ul>
+   *   <li>{@code method.getService() == getDescriptorForType()}
+   *   <li>{@code request} is of the exact same class as the object returned by
+   *       {@code getRequestPrototype(method)}.
+   *   <li>{@code controller} is of the correct type for the RPC implementation
+   *       being used by this Service.  For stubs, the "correct type" depends
+   *       on the RpcChannel which the stub is using.  Server-side Service
+   *       implementations are expected to accept whatever type of
+   *       {@code RpcController} the server-side RPC implementation uses.
+   * </ul>
+   *
+   * <p>Postconditions:
+   * <ul>
+   *   <li>{@code done} will be called when the method is complete.  This may be
+   *       before {@code callMethod()} returns or it may be at some point in
+   *       the future.
+   *   <li>The parameter to {@code done} is the response.  It must be of the
+   *       exact same type as would be returned by
+   *       {@code getResponsePrototype(method)}.
+   *   <li>If the RPC failed, the parameter to {@code done} will be
+   *       {@code null}.  Further details about the failure can be found by
+   *       querying {@code controller}.
+   * </ul>
+   */
+  void callMethod(Descriptors.MethodDescriptor method,
+                  RpcController controller,
+                  Message request,
+                  RpcCallback<Message> done);
+
+  /**
+   * <p>{@code callMethod()} requires that the request passed in is of a
+   * particular subclass of {@code Message}.  {@code getRequestPrototype()}
+   * gets the default instances of this type for a given method.  You can then
+   * call {@code Message.newBuilderForType()} on this instance to
+   * construct a builder to build an object which you can then pass to
+   * {@code callMethod()}.
+   *
+   * <p>Example:
+   * <pre>
+   *   MethodDescriptor method =
+   *     service.getDescriptorForType().findMethodByName("Foo");
+   *   Message request =
+   *     stub.getRequestPrototype(method).newBuilderForType()
+   *         .mergeFrom(input).build();
+   *   service.callMethod(method, request, callback);
+   * </pre>
+   */
+  Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+  /**
+   * Like {@code getRequestPrototype()}, but gets a prototype of the response
+   * message.  {@code getResponsePrototype()} is generally not needed because
+   * the {@code Service} implementation constructs the response message itself,
+   * but it may be useful in some cases to know ahead of time what type of
+   * object will be returned.
+   */
+  Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ServiceException.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ServiceException.java
new file mode 100644
index 0000000..00d5707
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/ServiceException.java
@@ -0,0 +1,52 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Thrown by blocking RPC methods when a failure occurs.
+ *
+ * @author cpovirk@google.com (Chris Povirk)
+ */
+public class ServiceException extends Exception {
+  private static final long serialVersionUID = -1219262335729891920L;
+
+  public ServiceException(final String message) {
+    super(message);
+  }
+
+  public ServiceException(final Throwable cause) {
+    super(cause);
+  }
+
+  public ServiceException(final String message, final Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
new file mode 100644
index 0000000..941b5de
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -0,0 +1,241 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * {@code SingleFieldBuilder} implements a structure that a protocol
+ * message uses to hold a single field of another protocol message. It supports
+ * the classical use case of setting an immutable {@link Message} as the value
+ * of the field and is highly optimized around this.
+ * <br>
+ * It also supports the additional use case of setting a {@link Message.Builder}
+ * as the field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilder
+    <MType extends GeneratedMessage,
+     BType extends GeneratedMessage.Builder,
+     IType extends MessageOrBuilder>
+    implements GeneratedMessage.BuilderParent {
+
+  // Parent to send changes to.
+  private GeneratedMessage.BuilderParent parent;
+
+  // Invariant: one of builder or message fields must be non-null.
+
+  // If set, this is the case where we are backed by a builder. In this case,
+  // message field represents a cached message for the builder (or null if
+  // there is no cached message).
+  private BType builder;
+
+  // If builder is non-null, this represents a cached message from the builder.
+  // If builder is null, this is the authoritative message for the field.
+  private MType message;
+
+  // Indicates that we've built a message and so we are now obligated
+  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+  private boolean isClean;
+
+  public SingleFieldBuilder(
+      MType message,
+      GeneratedMessage.BuilderParent parent,
+      boolean isClean) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    this.message = message;
+    this.parent = parent;
+    this.isClean = isClean;
+  }
+
+  public void dispose() {
+    // Null out parent so we stop sending it invalidations.
+    parent = null;
+  }
+
+  /**
+   * Get the message for the field. If the message is currently stored
+   * as a {@code Builder}, it is converted to a {@code Message} by
+   * calling {@link Message.Builder#buildPartial} on it. If no message has
+   * been set, returns the default instance of the message.
+   *
+   * @return the message for the field
+   */
+  @SuppressWarnings("unchecked")
+  public MType getMessage() {
+    if (message == null) {
+      // If message is null, the invariant is that we must be have a builder.
+      message = (MType) builder.buildPartial();
+    }
+    return message;
+  }
+
+  /**
+   * Builds the message and returns it.
+   *
+   * @return the message
+   */
+  public MType build() {
+    // Now that build has been called, we are required to dispatch
+    // invalidations.
+    isClean = true;
+    return getMessage();
+  }
+
+  /**
+   * Gets a builder for the field. If no builder has been created yet, a
+   * builder is created on demand by calling {@link Message#toBuilder}.
+   *
+   * @return The builder for the field
+   */
+  @SuppressWarnings("unchecked")
+  public BType getBuilder() {
+    if (builder == null) {
+      // builder.mergeFrom() on a fresh builder
+      // does not create any sub-objects with independent clean/dirty states,
+      // therefore setting the builder itself to clean without actually calling
+      // build() cannot break any invariants.
+      builder = (BType) message.newBuilderForType(this);
+      builder.mergeFrom(message); // no-op if message is the default message
+      builder.markClean();
+    }
+    return builder;
+  }
+
+  /**
+   * Gets the base class interface for the field. This may either be a builder
+   * or a message. It will return whatever is more efficient.
+   *
+   * @return the message or builder for the field as the base class interface
+   */
+  @SuppressWarnings("unchecked")
+  public IType getMessageOrBuilder() {
+    if (builder != null) {
+      return  (IType) builder;
+    } else {
+      return (IType) message;
+    }
+  }
+
+  /**
+   * Sets a  message for the field replacing any existing value.
+   *
+   * @param message the message to set
+   * @return the builder
+   */
+  public SingleFieldBuilder<MType, BType, IType> setMessage(
+      MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    this.message = message;
+    if (builder != null) {
+      builder.dispose();
+      builder = null;
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Merges the field from another field.
+   *
+   * @param value the value to merge from
+   * @return the builder
+   */
+  public SingleFieldBuilder<MType, BType, IType> mergeFrom(
+      MType value) {
+    if (builder == null && message == message.getDefaultInstanceForType()) {
+      message = value;
+    } else {
+      getBuilder().mergeFrom(value);
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Clears the value of the field.
+   *
+   * @return the builder
+   */
+  @SuppressWarnings("unchecked")
+  public SingleFieldBuilder<MType, BType, IType> clear() {
+    message = (MType) (message != null ?
+        message.getDefaultInstanceForType() :
+        builder.getDefaultInstanceForType());
+    if (builder != null) {
+      builder.dispose();
+      builder = null;
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Called when a the builder or one of its nested children has changed
+   * and any parent should be notified of its invalidation.
+   */
+  private void onChanged() {
+    // If builder is null, this is the case where onChanged is being called
+    // from setMessage or clear.
+    if (builder != null) {
+      message = null;
+    }
+    if (isClean && parent != null) {
+      parent.markDirty();
+
+      // Don't keep dispatching invalidations until build is called again.
+      isClean = false;
+    }
+  }
+
+  @Override
+  public void markDirty() {
+    onChanged();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
new file mode 100644
index 0000000..409fec1
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -0,0 +1,670 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * A custom map implementation from FieldDescriptor to Object optimized to
+ * minimize the number of memory allocations for instances with a small number
+ * of mappings. The implementation stores the first {@code k} mappings in an
+ * array for a configurable value of {@code k}, allowing direct access to the
+ * corresponding {@code Entry}s without the need to create an Iterator. The
+ * remaining entries are stored in an overflow map. Iteration over the entries
+ * in the map should be done as follows:
+ *
+ * <pre>   {@code
+ * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
+ *   process(fieldMap.getArrayEntryAt(i));
+ * }
+ * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
+ *   process(entry);
+ * }
+ * }</pre>
+ *
+ * The resulting iteration is in order of ascending field tag number. The
+ * object returned by {@link #entrySet()} adheres to the same contract but is
+ * less efficient as it necessarily involves creating an object for iteration.
+ * <p>
+ * The tradeoff for this memory efficiency is that the worst case running time
+ * of the {@code put()} operation is {@code O(k + lg n)}, which happens when
+ * entries are added in descending order. {@code k} should be chosen such that
+ * it covers enough common cases without adversely affecting larger maps. In
+ * practice, the worst case scenario does not happen for extensions because
+ * extension fields are serialized and deserialized in order of ascending tag
+ * number, but the worst case scenario can happen for DynamicMessages.
+ * <p>
+ * The running time for all other operations is similar to that of
+ * {@code TreeMap}.
+ * <p>
+ * Instances are not thread-safe until {@link #makeImmutable()} is called,
+ * after which any modifying operation will result in an
+ * {@link UnsupportedOperationException}.
+ *
+ * @author darick@google.com Darick Tong
+ */
+// This class is final for all intents and purposes because the constructor is
+// private. However, the FieldDescriptor-specific logic is encapsulated in
+// a subclass to aid testability of the core logic.
+class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
+
+  /**
+   * Creates a new instance for mapping FieldDescriptors to their values.
+   * The {@link #makeImmutable()} implementation will convert the List values
+   * of any repeated fields to unmodifiable lists.
+   *
+   * @param arraySize The size of the entry array containing the
+   *        lexicographically smallest mappings.
+   */
+  static <FieldDescriptorType extends
+      FieldSet.FieldDescriptorLite<FieldDescriptorType>>
+      SmallSortedMap<FieldDescriptorType, Object> newFieldMap(int arraySize) {
+    return new SmallSortedMap<FieldDescriptorType, Object>(arraySize) {
+      @Override
+      @SuppressWarnings("unchecked")
+      public void makeImmutable() {
+        if (!isImmutable()) {
+          for (int i = 0; i < getNumArrayEntries(); i++) {
+            final Map.Entry<FieldDescriptorType, Object> entry =
+                getArrayEntryAt(i);
+            if (entry.getKey().isRepeated()) {
+              final List value = (List) entry.getValue();
+              entry.setValue(Collections.unmodifiableList(value));
+            }
+          }
+          for (Map.Entry<FieldDescriptorType, Object> entry :
+                   getOverflowEntries()) {
+            if (entry.getKey().isRepeated()) {
+              final List value = (List) entry.getValue();
+              entry.setValue(Collections.unmodifiableList(value));
+            }
+          }
+        }
+        super.makeImmutable();
+      }
+    };
+  }
+
+  /**
+   * Creates a new instance for testing.
+   *
+   * @param arraySize The size of the entry array containing the
+   *        lexicographically smallest mappings.
+   */
+  static <K extends Comparable<K>, V> SmallSortedMap<K, V> newInstanceForTest(
+      int arraySize) {
+    return new SmallSortedMap<K, V>(arraySize);
+  }
+
+  private final int maxArraySize;
+  // The "entry array" is actually a List because generic arrays are not
+  // allowed. ArrayList also nicely handles the entry shifting on inserts and
+  // removes.
+  private List<Entry> entryList;
+  private Map<K, V> overflowEntries;
+  private boolean isImmutable;
+  // The EntrySet is a stateless view of the Map. It's initialized the first
+  // time it is requested and reused henceforth.
+  private volatile EntrySet lazyEntrySet;
+
+  /**
+   * @code arraySize Size of the array in which the lexicographically smallest
+   *       mappings are stored. (i.e. the {@code k} referred to in the class
+   *       documentation).
+   */
+  private SmallSortedMap(int arraySize) {
+    this.maxArraySize = arraySize;
+    this.entryList = Collections.emptyList();
+    this.overflowEntries = Collections.emptyMap();
+  }
+
+  /** Make this map immutable from this point forward. */
+  public void makeImmutable() {
+    if (!isImmutable) {
+      // Note: There's no need to wrap the entryList in an unmodifiableList
+      // because none of the list's accessors are exposed. The iterator() of
+      // overflowEntries, on the other hand, is exposed so it must be made
+      // unmodifiable.
+      overflowEntries = overflowEntries.isEmpty() ?
+          Collections.<K, V>emptyMap() :
+          Collections.unmodifiableMap(overflowEntries);
+      isImmutable = true;
+    }
+  }
+
+  /** @return Whether {@link #makeImmutable()} has been called. */
+  public boolean isImmutable() {
+    return isImmutable;
+  }
+
+  /** @return The number of entries in the entry array. */
+  public int getNumArrayEntries() {
+    return entryList.size();
+  }
+
+  /** @return The array entry at the given {@code index}. */
+  public Map.Entry<K, V> getArrayEntryAt(int index) {
+    return entryList.get(index);
+  }
+
+  /** @return There number of overflow entries. */
+  public int getNumOverflowEntries() {
+    return overflowEntries.size();
+  }
+
+  /** @return An iterable over the overflow entries. */
+  public Iterable<Map.Entry<K, V>> getOverflowEntries() {
+    return overflowEntries.isEmpty() ?
+        EmptySet.<Map.Entry<K, V>>iterable() :
+        overflowEntries.entrySet();
+  }
+
+  @Override
+  public int size() {
+    return entryList.size() + overflowEntries.size();
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean containsKey(Object o) {
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    return binarySearchInArray(key) >= 0 || overflowEntries.containsKey(key);
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public V get(Object o) {
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      return entryList.get(index).getValue();
+    }
+    return overflowEntries.get(key);
+  }
+
+  @Override
+  public V put(K key, V value) {
+    checkMutable();
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      // Replace existing array entry.
+      return entryList.get(index).setValue(value);
+    }
+    ensureEntryArrayMutable();
+    final int insertionPoint = -(index + 1);
+    if (insertionPoint >= maxArraySize) {
+      // Put directly in overflow.
+      return getOverflowEntriesMutable().put(key, value);
+    }
+    // Insert new Entry in array.
+    if (entryList.size() == maxArraySize) {
+      // Shift the last array entry into overflow.
+      final Entry lastEntryInArray = entryList.remove(maxArraySize - 1);
+      getOverflowEntriesMutable().put(lastEntryInArray.getKey(),
+                                      lastEntryInArray.getValue());
+    }
+    entryList.add(insertionPoint, new Entry(key, value));
+    return null;
+  }
+
+  @Override
+  public void clear() {
+    checkMutable();
+    if (!entryList.isEmpty()) {
+      entryList.clear();
+    }
+    if (!overflowEntries.isEmpty()) {
+      overflowEntries.clear();
+    }
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public V remove(Object o) {
+    checkMutable();
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      return removeArrayEntryAt(index);
+    }
+    // overflowEntries might be Collections.unmodifiableMap(), so only
+    // call remove() if it is non-empty.
+    if (overflowEntries.isEmpty()) {
+      return null;
+    } else {
+      return overflowEntries.remove(key);
+    }
+  }
+
+  private V removeArrayEntryAt(int index) {
+    checkMutable();
+    final V removed = entryList.remove(index).getValue();
+    if (!overflowEntries.isEmpty()) {
+      // Shift the first entry in the overflow to be the last entry in the
+      // array.
+      final Iterator<Map.Entry<K, V>> iterator =
+          getOverflowEntriesMutable().entrySet().iterator();
+      entryList.add(new Entry(iterator.next()));
+      iterator.remove();
+    }
+    return removed;
+  }
+
+  /**
+   * @param key The key to find in the entry array.
+   * @return The returned integer position follows the same semantics as the
+   *     value returned by {@link java.util.Arrays#binarySearch()}.
+   */
+  private int binarySearchInArray(K key) {
+    int left = 0;
+    int right = entryList.size() - 1;
+
+    // Optimization: For the common case in which entries are added in
+    // ascending tag order, check the largest element in the array before
+    // doing a full binary search.
+    if (right >= 0) {
+      int cmp = key.compareTo(entryList.get(right).getKey());
+      if (cmp > 0) {
+        return -(right + 2);  // Insert point is after "right".
+      } else if (cmp == 0) {
+        return right;
+      }
+    }
+
+    while (left <= right) {
+      int mid = (left + right) / 2;
+      int cmp = key.compareTo(entryList.get(mid).getKey());
+      if (cmp < 0) {
+        right = mid - 1;
+      } else if (cmp > 0) {
+        left = mid + 1;
+      } else {
+        return mid;
+      }
+    }
+    return -(left + 1);
+  }
+
+  /**
+   * Similar to the AbstractMap implementation of {@code keySet()} and
+   * {@code values()}, the entry set is created the first time this method is
+   * called, and returned in response to all subsequent calls.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Map.Entry<K, V>> entrySet() {
+    if (lazyEntrySet == null) {
+      lazyEntrySet = new EntrySet();
+    }
+    return lazyEntrySet;
+  }
+
+  /**
+   * @throws UnsupportedOperationException if {@link #makeImmutable()} has
+   *         has been called.
+   */
+  private void checkMutable() {
+    if (isImmutable) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  /**
+   * @return a {@link SortedMap} to which overflow entries mappings can be
+   *         added or removed.
+   * @throws UnsupportedOperationException if {@link #makeImmutable()} has been
+   *         called.
+   */
+  @SuppressWarnings("unchecked")
+  private SortedMap<K, V> getOverflowEntriesMutable() {
+    checkMutable();
+    if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) {
+      overflowEntries = new TreeMap<K, V>();
+    }
+    return (SortedMap<K, V>) overflowEntries;
+  }
+
+  /**
+   * Lazily creates the entry list. Any code that adds to the list must first
+   * call this method.
+   */
+  private void ensureEntryArrayMutable() {
+    checkMutable();
+    if (entryList.isEmpty() && !(entryList instanceof ArrayList)) {
+      entryList = new ArrayList<Entry>(maxArraySize);
+    }
+  }
+
+  /**
+   * Entry implementation that implements Comparable in order to support
+   * binary search within the entry array. Also checks mutability in
+   * {@link #setValue()}.
+   */
+  private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
+
+    private final K key;
+    private V value;
+
+    Entry(Map.Entry<K, V> copy) {
+      this(copy.getKey(), copy.getValue());
+    }
+
+    Entry(K key, V value) {
+      this.key = key;
+      this.value = value;
+    }
+
+    @Override
+    public K getKey() {
+      return key;
+    }
+
+    @Override
+    public V getValue() {
+      return value;
+    }
+
+    @Override
+    public int compareTo(Entry other) {
+      return getKey().compareTo(other.getKey());
+    }
+
+    @Override
+    public V setValue(V newValue) {
+      checkMutable();
+      final V oldValue = this.value;
+      this.value = newValue;
+      return oldValue;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (o == this) {
+        return true;
+      }
+      if (!(o instanceof Map.Entry)) {
+        return false;
+      }
+      @SuppressWarnings("unchecked")
+      Map.Entry<?, ?> other = (Map.Entry<?, ?>) o;
+      return equals(key, other.getKey()) && equals(value, other.getValue());
+    }
+
+    @Override
+    public int hashCode() {
+      return (key == null ? 0 : key.hashCode()) ^
+          (value == null ? 0 : value.hashCode());
+    }
+
+    @Override
+    public String toString() {
+      return key + "=" + value;
+    }
+
+    /** equals() that handles null values. */
+    private boolean equals(Object o1, Object o2) {
+      return o1 == null ? o2 == null : o1.equals(o2);
+    }
+  }
+
+  /**
+   * Stateless view of the entries in the field map.
+   */
+  private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+
+    @Override
+    public Iterator<Map.Entry<K, V>> iterator() {
+      return new EntryIterator();
+    }
+
+    @Override
+    public int size() {
+      return SmallSortedMap.this.size();
+    }
+
+    /**
+     * Throws a {@link ClassCastException} if o is not of the expected type.
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean contains(Object o) {
+      @SuppressWarnings("unchecked")
+      final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+      final V existing = get(entry.getKey());
+      final V value = entry.getValue();
+      return existing == value ||
+          (existing != null && existing.equals(value));
+    }
+
+    @Override
+    public boolean add(Map.Entry<K, V> entry) {
+      if (!contains(entry)) {
+        put(entry.getKey(), entry.getValue());
+        return true;
+      }
+      return false;
+    }
+
+    /**
+     * Throws a {@link ClassCastException} if o is not of the expected type.
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean remove(Object o) {
+      @SuppressWarnings("unchecked")
+      final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+      if (contains(entry)) {
+        SmallSortedMap.this.remove(entry.getKey());
+        return true;
+      }
+      return false;
+    }
+
+    @Override
+    public void clear() {
+      SmallSortedMap.this.clear();
+    }
+  }
+
+  /**
+   * Iterator implementation that switches from the entry array to the overflow
+   * entries appropriately.
+   */
+  private class EntryIterator implements Iterator<Map.Entry<K, V>> {
+
+    private int pos = -1;
+    private boolean nextCalledBeforeRemove;
+    private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
+
+    @Override
+    public boolean hasNext() {
+      return (pos + 1) < entryList.size() ||
+          getOverflowIterator().hasNext();
+    }
+
+    @Override
+    public Map.Entry<K, V> next() {
+      nextCalledBeforeRemove = true;
+      // Always increment pos so that we know whether the last returned value
+      // was from the array or from overflow.
+      if (++pos < entryList.size()) {
+        return entryList.get(pos);
+      }
+      return getOverflowIterator().next();
+    }
+
+    @Override
+    public void remove() {
+      if (!nextCalledBeforeRemove) {
+        throw new IllegalStateException("remove() was called before next()");
+      }
+      nextCalledBeforeRemove = false;
+      checkMutable();
+
+      if (pos < entryList.size()) {
+        removeArrayEntryAt(pos--);
+      } else {
+        getOverflowIterator().remove();
+      }
+    }
+
+    /**
+     * It is important to create the overflow iterator only after the array
+     * entries have been iterated over because the overflow entry set changes
+     * when the client calls remove() on the array entries, which invalidates
+     * any existing iterators.
+     */
+    private Iterator<Map.Entry<K, V>> getOverflowIterator() {
+      if (lazyOverflowIterator == null) {
+        lazyOverflowIterator = overflowEntries.entrySet().iterator();
+      }
+      return lazyOverflowIterator;
+    }
+  }
+
+  /**
+   * Helper class that holds immutable instances of an Iterable/Iterator that
+   * we return when the overflow entries is empty. This eliminates the creation
+   * of an Iterator object when there is nothing to iterate over.
+   */
+  private static class EmptySet {
+
+    private static final Iterator<Object> ITERATOR =
+        new Iterator<Object>() {
+          @Override
+          public boolean hasNext() {
+            return false;
+          }
+          @Override
+          public Object next() {
+            throw new NoSuchElementException();
+          }
+          @Override
+          public void remove() {
+            throw new UnsupportedOperationException();
+          }
+        };
+
+    private static final Iterable<Object> ITERABLE =
+        new Iterable<Object>() {
+          @Override
+          public Iterator<Object> iterator() {
+            return ITERATOR;
+          }
+        };
+
+    @SuppressWarnings("unchecked")
+    static <T> Iterable<T> iterable() {
+      return (Iterable<T>) ITERABLE;
+    }
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof SmallSortedMap)) {
+      return super.equals(o);
+    }
+    
+    SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o;
+    final int size = size();
+    if (size != other.size()) {
+      return false;
+    }
+    
+    // Best effort try to avoid allocating an entry set.
+    final int numArrayEntries = getNumArrayEntries();
+    if (numArrayEntries != other.getNumArrayEntries()) {
+      return entrySet().equals(other.entrySet());
+    }
+    
+    for (int i = 0; i < numArrayEntries; i++) {
+      if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) {
+        return false;
+      }
+    }
+    
+    if (numArrayEntries != size) {
+      return overflowEntries.equals(other.overflowEntries);
+    }
+    
+    
+    return true;
+  }
+  
+  @Override
+  public int hashCode() {
+    int h = 0;
+    final int listSize = getNumArrayEntries();
+    for (int i = 0; i < listSize; i++) {
+      h += entryList.get(i).hashCode();
+    }
+    // Avoid the iterator allocation if possible.
+    if (getNumOverflowEntries() > 0) {
+      h += overflowEntries.hashCode();
+    }
+    return h;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormat.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormat.java
new file mode 100644
index 0000000..c1c328f
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -0,0 +1,2071 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Provide text parsing and formatting support for proto2 instances.
+ * The implementation largely follows google/protobuf/text_format.cc.
+ *
+ * @author wenboz@google.com Wenbo Zhu
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TextFormat {
+  private TextFormat() {}
+
+  private static final Logger logger =
+      Logger.getLogger(TextFormat.class.getName());
+
+  private static final Printer DEFAULT_PRINTER = new Printer();
+  private static final Printer SINGLE_LINE_PRINTER =
+      (new Printer()).setSingleLineMode(true);
+  private static final Printer UNICODE_PRINTER =
+      (new Printer()).setEscapeNonAscii(false);
+
+  /**
+   * Outputs a textual representation of the Protocol Message supplied into
+   * the parameter output. (This representation is the new version of the
+   * classic "ProtocolPrinter" output from the original Protocol Buffer system)
+   */
+  public static void print(
+      final MessageOrBuilder message, final Appendable output)
+      throws IOException {
+    DEFAULT_PRINTER.print(message, new TextGenerator(output));
+  }
+
+  /** Outputs a textual representation of {@code fields} to {@code output}. */
+  public static void print(final UnknownFieldSet fields,
+                           final Appendable output)
+                           throws IOException {
+    DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+  }
+
+  /**
+   * Same as {@code print()}, except that non-ASCII characters are not
+   * escaped.
+   */
+  public static void printUnicode(
+      final MessageOrBuilder message, final Appendable output)
+      throws IOException {
+    UNICODE_PRINTER.print(message, new TextGenerator(output));
+  }
+
+  /**
+   * Same as {@code print()}, except that non-ASCII characters are not
+   * escaped.
+   */
+  public static void printUnicode(final UnknownFieldSet fields,
+                                  final Appendable output)
+                                  throws IOException {
+    UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+  }
+
+  /**
+   * Generates a human readable form of this message, useful for debugging and
+   * other purposes, with no newline characters.
+   */
+  public static String shortDebugString(final MessageOrBuilder message) {
+    try {
+      final StringBuilder sb = new StringBuilder();
+      SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
+      // Single line mode currently might have an extra space at the end.
+      return sb.toString().trim();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Generates a human readable form of the field, useful for debugging
+   * and other purposes, with no newline characters.
+   */
+  public static String shortDebugString(final FieldDescriptor field,
+                                        final Object value) {
+    try {
+      final StringBuilder sb = new StringBuilder();
+      SINGLE_LINE_PRINTER.printField(field, value, new TextGenerator(sb));
+      return sb.toString().trim();
+    } catch (IOException e) {
+        throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Generates a human readable form of the unknown fields, useful for debugging
+   * and other purposes, with no newline characters.
+   */
+  public static String shortDebugString(final UnknownFieldSet fields) {
+    try {
+      final StringBuilder sb = new StringBuilder();
+      SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb));
+      // Single line mode currently might have an extra space at the end.
+      return sb.toString().trim();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Like {@code print()}, but writes directly to a {@code String} and
+   * returns it.
+   */
+  public static String printToString(final MessageOrBuilder message) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      print(message, text);
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Like {@code print()}, but writes directly to a {@code String} and
+   * returns it.
+   */
+  public static String printToString(final UnknownFieldSet fields) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      print(fields, text);
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Same as {@code printToString()}, except that non-ASCII characters
+   * in string type fields are not escaped in backslash+octals.
+   */
+  public static String printToUnicodeString(final MessageOrBuilder message) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      UNICODE_PRINTER.print(message, new TextGenerator(text));
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Same as {@code printToString()}, except that non-ASCII characters
+   * in string type fields are not escaped in backslash+octals.
+   */
+  public static String printToUnicodeString(final UnknownFieldSet fields) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  public static void printField(final FieldDescriptor field,
+                                final Object value,
+                                final Appendable output)
+                                throws IOException {
+    DEFAULT_PRINTER.printField(field, value, new TextGenerator(output));
+  }
+
+  public static String printFieldToString(final FieldDescriptor field,
+                                          final Object value) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      printField(field, value, text);
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Outputs a textual representation of the value of given field value.
+   *
+   * @param field the descriptor of the field
+   * @param value the value of the field
+   * @param output the output to which to append the formatted value
+   * @throws ClassCastException if the value is not appropriate for the
+   *     given field descriptor
+   * @throws IOException if there is an exception writing to the output
+   */
+  public static void printFieldValue(final FieldDescriptor field,
+                                     final Object value,
+                                     final Appendable output)
+                                     throws IOException {
+    DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output));
+  }
+
+  /**
+   * Outputs a textual representation of the value of an unknown field.
+   *
+   * @param tag the field's tag number
+   * @param value the value of the field
+   * @param output the output to which to append the formatted value
+   * @throws ClassCastException if the value is not appropriate for the
+   *     given field descriptor
+   * @throws IOException if there is an exception writing to the output
+   */
+  public static void printUnknownFieldValue(final int tag,
+                                            final Object value,
+                                            final Appendable output)
+                                            throws IOException {
+    printUnknownFieldValue(tag, value, new TextGenerator(output));
+  }
+
+  private static void printUnknownFieldValue(final int tag,
+                                             final Object value,
+                                             final TextGenerator generator)
+                                             throws IOException {
+    switch (WireFormat.getTagWireType(tag)) {
+      case WireFormat.WIRETYPE_VARINT:
+        generator.print(unsignedToString((Long) value));
+        break;
+      case WireFormat.WIRETYPE_FIXED32:
+        generator.print(
+            String.format((Locale) null, "0x%08x", (Integer) value));
+        break;
+      case WireFormat.WIRETYPE_FIXED64:
+        generator.print(String.format((Locale) null, "0x%016x", (Long) value));
+        break;
+      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+        generator.print("\"");
+        generator.print(escapeBytes((ByteString) value));
+        generator.print("\"");
+        break;
+      case WireFormat.WIRETYPE_START_GROUP:
+        DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator);
+        break;
+      default:
+        throw new IllegalArgumentException("Bad tag: " + tag);
+    }
+  }
+
+  /** Helper class for converting protobufs to text. */
+  private static final class Printer {
+    /** Whether to omit newlines from the output. */
+    boolean singleLineMode = false;
+
+    /** Whether to escape non ASCII characters with backslash and octal. */
+    boolean escapeNonAscii = true;
+
+    private Printer() {}
+
+    /** Setter of singleLineMode */
+    private Printer setSingleLineMode(boolean singleLineMode) {
+      this.singleLineMode = singleLineMode;
+      return this;
+    }
+
+    /** Setter of escapeNonAscii */
+    private Printer setEscapeNonAscii(boolean escapeNonAscii) {
+      this.escapeNonAscii = escapeNonAscii;
+      return this;
+    }
+
+    private void print(
+        final MessageOrBuilder message, final TextGenerator generator)
+        throws IOException {
+      for (Map.Entry<FieldDescriptor, Object> field
+          : message.getAllFields().entrySet()) {
+        printField(field.getKey(), field.getValue(), generator);
+      }
+      printUnknownFields(message.getUnknownFields(), generator);
+    }
+
+    private void printField(final FieldDescriptor field, final Object value,
+        final TextGenerator generator) throws IOException {
+      if (field.isRepeated()) {
+        // Repeated field.  Print each element.
+        for (Object element : (List<?>) value) {
+          printSingleField(field, element, generator);
+        }
+      } else {
+        printSingleField(field, value, generator);
+      }
+    }
+
+    private void printSingleField(final FieldDescriptor field,
+                                  final Object value,
+                                  final TextGenerator generator)
+                                  throws IOException {
+      if (field.isExtension()) {
+        generator.print("[");
+        // We special-case MessageSet elements for compatibility with proto1.
+        if (field.getContainingType().getOptions().getMessageSetWireFormat()
+            && (field.getType() == FieldDescriptor.Type.MESSAGE)
+            && (field.isOptional())
+            // object equality
+            && (field.getExtensionScope() == field.getMessageType())) {
+          generator.print(field.getMessageType().getFullName());
+        } else {
+          generator.print(field.getFullName());
+        }
+        generator.print("]");
+      } else {
+        if (field.getType() == FieldDescriptor.Type.GROUP) {
+          // Groups must be serialized with their original capitalization.
+          generator.print(field.getMessageType().getName());
+        } else {
+          generator.print(field.getName());
+        }
+      }
+
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        if (singleLineMode) {
+          generator.print(" { ");
+        } else {
+          generator.print(" {\n");
+          generator.indent();
+        }
+      } else {
+        generator.print(": ");
+      }
+
+      printFieldValue(field, value, generator);
+
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        if (singleLineMode) {
+          generator.print("} ");
+        } else {
+          generator.outdent();
+          generator.print("}\n");
+        }
+      } else {
+        if (singleLineMode) {
+          generator.print(" ");
+        } else {
+          generator.print("\n");
+        }
+      }
+    }
+
+    private void printFieldValue(final FieldDescriptor field,
+                                 final Object value,
+                                 final TextGenerator generator)
+                                 throws IOException {
+      switch (field.getType()) {
+        case INT32:
+        case SINT32:
+        case SFIXED32:
+          generator.print(((Integer) value).toString());
+          break;
+
+        case INT64:
+        case SINT64:
+        case SFIXED64:
+          generator.print(((Long) value).toString());
+          break;
+
+        case BOOL:
+          generator.print(((Boolean) value).toString());
+          break;
+
+        case FLOAT:
+          generator.print(((Float) value).toString());
+          break;
+
+        case DOUBLE:
+          generator.print(((Double) value).toString());
+          break;
+
+        case UINT32:
+        case FIXED32:
+          generator.print(unsignedToString((Integer) value));
+          break;
+
+        case UINT64:
+        case FIXED64:
+          generator.print(unsignedToString((Long) value));
+          break;
+
+        case STRING:
+          generator.print("\"");
+          generator.print(escapeNonAscii
+              ? TextFormatEscaper.escapeText((String) value)
+              : escapeDoubleQuotesAndBackslashes((String) value)
+                  .replace("\n", "\\n"));
+          generator.print("\"");
+          break;
+
+        case BYTES:
+          generator.print("\"");
+          if (value instanceof ByteString) {
+            generator.print(escapeBytes((ByteString) value));
+          } else {
+            generator.print(escapeBytes((byte[]) value));
+          }
+          generator.print("\"");
+          break;
+
+        case ENUM:
+          generator.print(((EnumValueDescriptor) value).getName());
+          break;
+
+        case MESSAGE:
+        case GROUP:
+          print((Message) value, generator);
+          break;
+      }
+    }
+
+    private void printUnknownFields(final UnknownFieldSet unknownFields,
+                                    final TextGenerator generator)
+                                    throws IOException {
+      for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+               unknownFields.asMap().entrySet()) {
+        final int number = entry.getKey();
+        final UnknownFieldSet.Field field = entry.getValue();
+        printUnknownField(number, WireFormat.WIRETYPE_VARINT,
+            field.getVarintList(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_FIXED32,
+            field.getFixed32List(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_FIXED64,
+            field.getFixed64List(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_LENGTH_DELIMITED,
+            field.getLengthDelimitedList(), generator);
+        for (final UnknownFieldSet value : field.getGroupList()) {
+          generator.print(entry.getKey().toString());
+          if (singleLineMode) {
+            generator.print(" { ");
+          } else {
+            generator.print(" {\n");
+            generator.indent();
+          }
+          printUnknownFields(value, generator);
+          if (singleLineMode) {
+            generator.print("} ");
+          } else {
+            generator.outdent();
+            generator.print("}\n");
+          }
+        }
+      }
+    }
+
+    private void printUnknownField(final int number,
+                                   final int wireType,
+                                   final List<?> values,
+                                   final TextGenerator generator)
+                                   throws IOException {
+      for (final Object value : values) {
+        generator.print(String.valueOf(number));
+        generator.print(": ");
+        printUnknownFieldValue(wireType, value, generator);
+        generator.print(singleLineMode ? " " : "\n");
+      }
+    }
+  }
+
+  /** Convert an unsigned 32-bit integer to a string. */
+  public static String unsignedToString(final int value) {
+    if (value >= 0) {
+      return Integer.toString(value);
+    } else {
+      return Long.toString(value & 0x00000000FFFFFFFFL);
+    }
+  }
+
+  /** Convert an unsigned 64-bit integer to a string. */
+  public static String unsignedToString(final long value) {
+    if (value >= 0) {
+      return Long.toString(value);
+    } else {
+      // Pull off the most-significant bit so that BigInteger doesn't think
+      // the number is negative, then set it again using setBit().
+      return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL)
+                       .setBit(63).toString();
+    }
+  }
+
+  /**
+   * An inner class for writing text to the output stream.
+   */
+  private static final class TextGenerator {
+    private final Appendable output;
+    private final StringBuilder indent = new StringBuilder();
+    private boolean atStartOfLine = true;
+
+    private TextGenerator(final Appendable output) {
+      this.output = output;
+    }
+
+    /**
+     * Indent text by two spaces.  After calling Indent(), two spaces will be
+     * inserted at the beginning of each line of text.  Indent() may be called
+     * multiple times to produce deeper indents.
+     */
+    public void indent() {
+      indent.append("  ");
+    }
+
+    /**
+     * Reduces the current indent level by two spaces, or crashes if the indent
+     * level is zero.
+     */
+    public void outdent() {
+      final int length = indent.length();
+      if (length == 0) {
+        throw new IllegalArgumentException(
+            " Outdent() without matching Indent().");
+      }
+      indent.delete(length - 2, length);
+    }
+
+    /**
+     * Print text to the output stream.
+     */
+    public void print(final CharSequence text) throws IOException {
+      final int size = text.length();
+      int pos = 0;
+
+      for (int i = 0; i < size; i++) {
+        if (text.charAt(i) == '\n') {
+          write(text.subSequence(pos, i + 1));
+          pos = i + 1;
+          atStartOfLine = true;
+        }
+      }
+      write(text.subSequence(pos, size));
+    }
+
+    private void write(final CharSequence data) throws IOException {
+      if (data.length() == 0) {
+        return;
+      }
+      if (atStartOfLine) {
+        atStartOfLine = false;
+        output.append(indent);
+      }
+      output.append(data);
+    }
+  }
+
+  // =================================================================
+  // Parsing
+
+  /**
+   * Represents a stream of tokens parsed from a {@code String}.
+   *
+   * <p>The Java standard library provides many classes that you might think
+   * would be useful for implementing this, but aren't.  For example:
+   *
+   * <ul>
+   * <li>{@code java.io.StreamTokenizer}:  This almost does what we want -- or,
+   *   at least, something that would get us close to what we want -- except
+   *   for one fatal flaw:  It automatically un-escapes strings using Java
+   *   escape sequences, which do not include all the escape sequences we
+   *   need to support (e.g. '\x').
+   * <li>{@code java.util.Scanner}:  This seems like a great way at least to
+   *   parse regular expressions out of a stream (so we wouldn't have to load
+   *   the entire input into a single string before parsing).  Sadly,
+   *   {@code Scanner} requires that tokens be delimited with some delimiter.
+   *   Thus, although the text "foo:" should parse to two tokens ("foo" and
+   *   ":"), {@code Scanner} would recognize it only as a single token.
+   *   Furthermore, {@code Scanner} provides no way to inspect the contents
+   *   of delimiters, making it impossible to keep track of line and column
+   *   numbers.
+   * </ul>
+   *
+   * <p>Luckily, Java's regular expression support does manage to be useful to
+   * us.  (Barely:  We need {@code Matcher.usePattern()}, which is new in
+   * Java 1.5.)  So, we can use that, at least.  Unfortunately, this implies
+   * that we need to have the entire input in one contiguous string.
+   */
+  private static final class Tokenizer {
+    private final CharSequence text;
+    private final Matcher matcher;
+    private String currentToken;
+
+    // The character index within this.text at which the current token begins.
+    private int pos = 0;
+
+    // The line and column numbers of the current token.
+    private int line = 0;
+    private int column = 0;
+
+    // The line and column numbers of the previous token (allows throwing
+    // errors *after* consuming).
+    private int previousLine = 0;
+    private int previousColumn = 0;
+
+    // We use possessive quantifiers (*+ and ++) because otherwise the Java
+    // regex matcher has stack overflows on large inputs.
+    private static final Pattern WHITESPACE =
+      Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
+    private static final Pattern TOKEN = Pattern.compile(
+      "[a-zA-Z_][0-9a-zA-Z_+-]*+|" +                // an identifier
+      "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" +             // a number
+      "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" +       // a double-quoted string
+      "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)",         // a single-quoted string
+      Pattern.MULTILINE);
+
+    private static final Pattern DOUBLE_INFINITY = Pattern.compile(
+      "-?inf(inity)?",
+      Pattern.CASE_INSENSITIVE);
+    private static final Pattern FLOAT_INFINITY = Pattern.compile(
+      "-?inf(inity)?f?",
+      Pattern.CASE_INSENSITIVE);
+    private static final Pattern FLOAT_NAN = Pattern.compile(
+      "nanf?",
+      Pattern.CASE_INSENSITIVE);
+
+    /** Construct a tokenizer that parses tokens from the given text. */
+    private Tokenizer(final CharSequence text) {
+      this.text = text;
+      this.matcher = WHITESPACE.matcher(text);
+      skipWhitespace();
+      nextToken();
+    }
+
+    int getLine() {
+      return line;
+    }
+
+    int getColumn() {
+      return column;
+    }
+
+    /** Are we at the end of the input? */
+    public boolean atEnd() {
+      return currentToken.length() == 0;
+    }
+
+    /** Advance to the next token. */
+    public void nextToken() {
+      previousLine = line;
+      previousColumn = column;
+
+      // Advance the line counter to the current position.
+      while (pos < matcher.regionStart()) {
+        if (text.charAt(pos) == '\n') {
+          ++line;
+          column = 0;
+        } else {
+          ++column;
+        }
+        ++pos;
+      }
+
+      // Match the next token.
+      if (matcher.regionStart() == matcher.regionEnd()) {
+        // EOF
+        currentToken = "";
+      } else {
+        matcher.usePattern(TOKEN);
+        if (matcher.lookingAt()) {
+          currentToken = matcher.group();
+          matcher.region(matcher.end(), matcher.regionEnd());
+        } else {
+          // Take one character.
+          currentToken = String.valueOf(text.charAt(pos));
+          matcher.region(pos + 1, matcher.regionEnd());
+        }
+
+        skipWhitespace();
+      }
+    }
+
+    /**
+     * Skip over any whitespace so that the matcher region starts at the next
+     * token.
+     */
+    private void skipWhitespace() {
+      matcher.usePattern(WHITESPACE);
+      if (matcher.lookingAt()) {
+        matcher.region(matcher.end(), matcher.regionEnd());
+      }
+    }
+
+    /**
+     * If the next token exactly matches {@code token}, consume it and return
+     * {@code true}.  Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsume(final String token) {
+      if (currentToken.equals(token)) {
+        nextToken();
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token exactly matches {@code token}, consume it.  Otherwise,
+     * throw a {@link ParseException}.
+     */
+    public void consume(final String token) throws ParseException {
+      if (!tryConsume(token)) {
+        throw parseException("Expected \"" + token + "\".");
+      }
+    }
+
+    /**
+     * Returns {@code true} if the next token is an integer, but does
+     * not consume it.
+     */
+    public boolean lookingAtInteger() {
+      if (currentToken.length() == 0) {
+        return false;
+      }
+
+      final char c = currentToken.charAt(0);
+      return ('0' <= c && c <= '9')
+          || c == '-' || c == '+';
+    }
+
+    /**
+     * Returns {@code true} if the current token's text is equal to that
+     * specified.
+     */
+    public boolean lookingAt(String text) {
+      return currentToken.equals(text);
+    }
+
+    /**
+     * If the next token is an identifier, consume it and return its value.
+     * Otherwise, throw a {@link ParseException}.
+     */
+    public String consumeIdentifier() throws ParseException {
+      for (int i = 0; i < currentToken.length(); i++) {
+        final char c = currentToken.charAt(i);
+        if (('a' <= c && c <= 'z')
+            || ('A' <= c && c <= 'Z')
+            || ('0' <= c && c <= '9')
+            || (c == '_') || (c == '.')) {
+          // OK
+        } else {
+          throw parseException(
+              "Expected identifier. Found '" + currentToken + "'");
+        }
+      }
+
+      final String result = currentToken;
+      nextToken();
+      return result;
+    }
+
+    /**
+     * If the next token is an identifier, consume it and return {@code true}.
+     * Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsumeIdentifier() {
+      try {
+        consumeIdentifier();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a 32-bit signed integer, consume it and return its
+     * value.  Otherwise, throw a {@link ParseException}.
+     */
+    public int consumeInt32() throws ParseException {
+      try {
+        final int result = parseInt32(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw integerParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a 32-bit unsigned integer, consume it and return its
+     * value.  Otherwise, throw a {@link ParseException}.
+     */
+    public int consumeUInt32() throws ParseException {
+      try {
+        final int result = parseUInt32(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw integerParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a 64-bit signed integer, consume it and return its
+     * value.  Otherwise, throw a {@link ParseException}.
+     */
+    public long consumeInt64() throws ParseException {
+      try {
+        final long result = parseInt64(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw integerParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a 64-bit signed integer, consume it and return
+     * {@code true}.  Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsumeInt64() {
+      try {
+        consumeInt64();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a 64-bit unsigned integer, consume it and return its
+     * value.  Otherwise, throw a {@link ParseException}.
+     */
+    public long consumeUInt64() throws ParseException {
+      try {
+        final long result = parseUInt64(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw integerParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a 64-bit unsigned integer, consume it and return
+     * {@code true}.  Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsumeUInt64() {
+      try {
+        consumeUInt64();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a double, consume it and return its value.
+     * Otherwise, throw a {@link ParseException}.
+     */
+    public double consumeDouble() throws ParseException {
+      // We need to parse infinity and nan separately because
+      // Double.parseDouble() does not accept "inf", "infinity", or "nan".
+      if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
+        final boolean negative = currentToken.startsWith("-");
+        nextToken();
+        return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+      }
+      if (currentToken.equalsIgnoreCase("nan")) {
+        nextToken();
+        return Double.NaN;
+      }
+      try {
+        final double result = Double.parseDouble(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw floatParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a double, consume it and return {@code true}.
+     * Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsumeDouble() {
+      try {
+        consumeDouble();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a float, consume it and return its value.
+     * Otherwise, throw a {@link ParseException}.
+     */
+    public float consumeFloat() throws ParseException {
+      // We need to parse infinity and nan separately because
+      // Float.parseFloat() does not accept "inf", "infinity", or "nan".
+      if (FLOAT_INFINITY.matcher(currentToken).matches()) {
+        final boolean negative = currentToken.startsWith("-");
+        nextToken();
+        return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+      }
+      if (FLOAT_NAN.matcher(currentToken).matches()) {
+        nextToken();
+        return Float.NaN;
+      }
+      try {
+        final float result = Float.parseFloat(currentToken);
+        nextToken();
+        return result;
+      } catch (NumberFormatException e) {
+        throw floatParseException(e);
+      }
+    }
+
+    /**
+     * If the next token is a float, consume it and return {@code true}.
+     * Otherwise, return {@code false} without doing anything.
+     */
+    public boolean tryConsumeFloat() {
+      try {
+        consumeFloat();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a boolean, consume it and return its value.
+     * Otherwise, throw a {@link ParseException}.
+     */
+    public boolean consumeBoolean() throws ParseException {
+      if (currentToken.equals("true")
+          || currentToken.equals("True")
+          || currentToken.equals("t")
+          || currentToken.equals("1")) {
+        nextToken();
+        return true;
+      } else if (currentToken.equals("false")
+          || currentToken.equals("False")
+          || currentToken.equals("f")
+          || currentToken.equals("0")) {
+        nextToken();
+        return false;
+      } else {
+        throw parseException("Expected \"true\" or \"false\".");
+      }
+    }
+
+    /**
+     * If the next token is a string, consume it and return its (unescaped)
+     * value.  Otherwise, throw a {@link ParseException}.
+     */
+    public String consumeString() throws ParseException {
+      return consumeByteString().toStringUtf8();
+    }
+
+    /**
+     * If the next token is a string, consume it and return true.  Otherwise,
+     * return false.
+     */
+    public boolean tryConsumeString() {
+      try {
+        consumeString();
+        return true;
+      } catch (ParseException e) {
+        return false;
+      }
+    }
+
+    /**
+     * If the next token is a string, consume it, unescape it as a
+     * {@link ByteString}, and return it.  Otherwise, throw a
+     * {@link ParseException}.
+     */
+    public ByteString consumeByteString() throws ParseException {
+      List<ByteString> list = new ArrayList<ByteString>();
+      consumeByteString(list);
+      while (currentToken.startsWith("'") || currentToken.startsWith("\"")) {
+        consumeByteString(list);
+      }
+      return ByteString.copyFrom(list);
+    }
+
+    /**
+     * Like {@link #consumeByteString()} but adds each token of the string to
+     * the given list.  String literals (whether bytes or text) may come in
+     * multiple adjacent tokens which are automatically concatenated, like in
+     * C or Python.
+     */
+    private void consumeByteString(List<ByteString> list)
+        throws ParseException {
+      final char quote = currentToken.length() > 0
+          ? currentToken.charAt(0)
+          : '\0';
+      if (quote != '\"' && quote != '\'') {
+        throw parseException("Expected string.");
+      }
+
+      if (currentToken.length() < 2
+          || currentToken.charAt(currentToken.length() - 1) != quote) {
+        throw parseException("String missing ending quote.");
+      }
+
+      try {
+        final String escaped =
+            currentToken.substring(1, currentToken.length() - 1);
+        final ByteString result = unescapeBytes(escaped);
+        nextToken();
+        list.add(result);
+      } catch (InvalidEscapeSequenceException e) {
+        throw parseException(e.getMessage());
+      }
+    }
+
+    /**
+     * Returns a {@link ParseException} with the current line and column
+     * numbers in the description, suitable for throwing.
+     */
+    public ParseException parseException(final String description) {
+      // Note:  People generally prefer one-based line and column numbers.
+      return new ParseException(
+        line + 1, column + 1, description);
+    }
+
+    /**
+     * Returns a {@link ParseException} with the line and column numbers of
+     * the previous token in the description, suitable for throwing.
+     */
+    public ParseException parseExceptionPreviousToken(
+        final String description) {
+      // Note:  People generally prefer one-based line and column numbers.
+      return new ParseException(
+        previousLine + 1, previousColumn + 1, description);
+    }
+
+    /**
+     * Constructs an appropriate {@link ParseException} for the given
+     * {@code NumberFormatException} when trying to parse an integer.
+     */
+    private ParseException integerParseException(
+        final NumberFormatException e) {
+      return parseException("Couldn't parse integer: " + e.getMessage());
+    }
+
+    /**
+     * Constructs an appropriate {@link ParseException} for the given
+     * {@code NumberFormatException} when trying to parse a float or double.
+     */
+    private ParseException floatParseException(final NumberFormatException e) {
+      return parseException("Couldn't parse number: " + e.getMessage());
+    }
+
+    /**
+     * Returns a {@link UnknownFieldParseException} with the line and column
+     * numbers of the previous token in the description, and the unknown field
+     * name, suitable for throwing.
+     */
+    public UnknownFieldParseException unknownFieldParseExceptionPreviousToken(
+        final String unknownField, final String description) {
+      // Note:  People generally prefer one-based line and column numbers.
+      return new UnknownFieldParseException(
+        previousLine + 1, previousColumn + 1, unknownField, description);
+    }
+  }
+
+  /** Thrown when parsing an invalid text format message. */
+  public static class ParseException extends IOException {
+    private static final long serialVersionUID = 3196188060225107702L;
+
+    private final int line;
+    private final int column;
+
+    /** Create a new instance, with -1 as the line and column numbers. */
+    public ParseException(final String message) {
+      this(-1, -1, message);
+    }
+
+    /**
+     * Create a new instance
+     *
+     * @param line the line number where the parse error occurred,
+     * using 1-offset.
+     * @param column the column number where the parser error occurred,
+     * using 1-offset.
+     */
+    public ParseException(final int line, final int column,
+        final String message) {
+      super(Integer.toString(line) + ":" + column + ": " + message);
+      this.line = line;
+      this.column = column;
+    }
+
+    /**
+     * Return the line where the parse exception occurred, or -1 when
+     * none is provided. The value is specified as 1-offset, so the first
+     * line is line 1.
+     */
+    public int getLine() {
+      return line;
+    }
+
+    /**
+     * Return the column where the parse exception occurred, or -1 when
+     * none is provided. The value is specified as 1-offset, so the first
+     * line is line 1.
+     */
+    public int getColumn() {
+      return column;
+    }
+  }
+
+  /**
+   * Thrown when encountering an unknown field while parsing
+   * a text format message.
+   */
+  public static class UnknownFieldParseException extends ParseException {
+    private final String unknownField;
+
+    /**
+     * Create a new instance, with -1 as the line and column numbers, and an
+     * empty unknown field name.
+     */
+    public UnknownFieldParseException(final String message) {
+      this(-1, -1, "", message);
+    }
+
+    /**
+     * Create a new instance
+     *
+     * @param line the line number where the parse error occurred,
+     * using 1-offset.
+     * @param column the column number where the parser error occurred,
+     * using 1-offset.
+     * @param unknownField the name of the unknown field found while parsing.
+     */
+    public UnknownFieldParseException(final int line, final int column,
+        final String unknownField, final String message) {
+      super(line, column, message);
+      this.unknownField = unknownField;
+    }
+
+    /**
+     * Return the name of the unknown field encountered while parsing the
+     * protocol buffer string.
+     */
+    public String getUnknownField() {
+      return unknownField;
+    }
+  }
+
+  private static final Parser PARSER = Parser.newBuilder().build();
+
+  /**
+   * Return a {@link Parser} instance which can parse text-format
+   * messages. The returned instance is thread-safe.
+   */
+  public static Parser getParser() {
+    return PARSER;
+  }
+
+  /**
+   * Parse a text-format message from {@code input} and merge the contents
+   * into {@code builder}.
+   */
+  public static void merge(final Readable input,
+                           final Message.Builder builder)
+                           throws IOException {
+    PARSER.merge(input, builder);
+  }
+
+  /**
+   * Parse a text-format message from {@code input} and merge the contents
+   * into {@code builder}.
+   */
+  public static void merge(final CharSequence input,
+                           final Message.Builder builder)
+                           throws ParseException {
+    PARSER.merge(input, builder);
+  }
+
+  /**
+   * Parse a text-format message from {@code input} and merge the contents
+   * into {@code builder}.  Extensions will be recognized if they are
+   * registered in {@code extensionRegistry}.
+   */
+  public static void merge(final Readable input,
+                           final ExtensionRegistry extensionRegistry,
+                           final Message.Builder builder)
+                           throws IOException {
+    PARSER.merge(input, extensionRegistry, builder);
+  }
+
+
+  /**
+   * Parse a text-format message from {@code input} and merge the contents
+   * into {@code builder}.  Extensions will be recognized if they are
+   * registered in {@code extensionRegistry}.
+   */
+  public static void merge(final CharSequence input,
+                           final ExtensionRegistry extensionRegistry,
+                           final Message.Builder builder)
+                           throws ParseException {
+    PARSER.merge(input, extensionRegistry, builder);
+  }
+
+
+  /**
+   * Parser for text-format proto2 instances. This class is thread-safe.
+   * The implementation largely follows google/protobuf/text_format.cc.
+   *
+   * <p>Use {@link TextFormat#getParser()} to obtain the default parser, or
+   * {@link Builder} to control the parser behavior.
+   */
+  public static class Parser {
+    /**
+     * Determines if repeated values for non-repeated fields and
+     * oneofs are permitted. For example, given required/optional field "foo"
+     * and a oneof containing "baz" and "qux":
+     * <ul>
+     * <li>"foo: 1 foo: 2"
+     * <li>"baz: 1 qux: 2"
+     * <li>merging "foo: 2" into a proto in which foo is already set, or
+     * <li>merging "qux: 2" into a proto in which baz is already set.
+     * </ul>
+     */
+    public enum SingularOverwritePolicy {
+      /** The last value is retained. */
+      ALLOW_SINGULAR_OVERWRITES,
+      /** An error is issued. */
+      FORBID_SINGULAR_OVERWRITES
+    }
+
+    private final boolean allowUnknownFields;
+    private final SingularOverwritePolicy singularOverwritePolicy;
+    private TextFormatParseInfoTree.Builder parseInfoTreeBuilder;
+
+    private Parser(
+        boolean allowUnknownFields, SingularOverwritePolicy singularOverwritePolicy,
+        TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
+      this.allowUnknownFields = allowUnknownFields;
+      this.singularOverwritePolicy = singularOverwritePolicy;
+      this.parseInfoTreeBuilder = parseInfoTreeBuilder;
+    }
+
+    /**
+     * Returns a new instance of {@link Builder}.
+     */
+    public static Builder newBuilder() {
+      return new Builder();
+    }
+
+    /**
+     * Builder that can be used to obtain new instances of {@link Parser}.
+     */
+    public static class Builder {
+      private boolean allowUnknownFields = false;
+      private SingularOverwritePolicy singularOverwritePolicy =
+          SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
+      private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
+
+
+      /**
+       * Sets parser behavior when a non-repeated field appears more than once.
+       */
+      public Builder setSingularOverwritePolicy(SingularOverwritePolicy p) {
+        this.singularOverwritePolicy = p;
+        return this;
+      }
+
+      public Builder setParseInfoTreeBuilder(
+          TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
+        this.parseInfoTreeBuilder = parseInfoTreeBuilder;
+        return this;
+      }
+
+      public Parser build() {
+        return new Parser(
+            allowUnknownFields, singularOverwritePolicy, parseInfoTreeBuilder);
+      }
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents
+     * into {@code builder}.
+     */
+    public void merge(final Readable input,
+                      final Message.Builder builder)
+                      throws IOException {
+      merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents
+     * into {@code builder}.
+     */
+    public void merge(final CharSequence input,
+                      final Message.Builder builder)
+                      throws ParseException {
+      merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents
+     * into {@code builder}.  Extensions will be recognized if they are
+     * registered in {@code extensionRegistry}.
+     */
+    public void merge(final Readable input,
+                      final ExtensionRegistry extensionRegistry,
+                      final Message.Builder builder)
+                      throws IOException {
+      // Read the entire input to a String then parse that.
+
+      // If StreamTokenizer were not quite so crippled, or if there were a kind
+      // of Reader that could read in chunks that match some particular regex,
+      // or if we wanted to write a custom Reader to tokenize our stream, then
+      // we would not have to read to one big String.  Alas, none of these is
+      // the case.  Oh well.
+
+      merge(toStringBuilder(input), extensionRegistry, builder);
+    }
+
+
+    private static final int BUFFER_SIZE = 4096;
+
+    // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
+    // overhead is worthwhile
+    private static StringBuilder toStringBuilder(final Readable input)
+        throws IOException {
+      final StringBuilder text = new StringBuilder();
+      final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
+      while (true) {
+        final int n = input.read(buffer);
+        if (n == -1) {
+          break;
+        }
+        buffer.flip();
+        text.append(buffer, 0, n);
+      }
+      return text;
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents
+     * into {@code builder}.  Extensions will be recognized if they are
+     * registered in {@code extensionRegistry}.
+     */
+    public void merge(final CharSequence input,
+                      final ExtensionRegistry extensionRegistry,
+                      final Message.Builder builder)
+                      throws ParseException {
+      final Tokenizer tokenizer = new Tokenizer(input);
+      MessageReflection.BuilderAdapter target =
+          new MessageReflection.BuilderAdapter(builder);
+
+      while (!tokenizer.atEnd()) {
+        mergeField(tokenizer, extensionRegistry, target);
+      }
+    }
+
+
+    /**
+     * Parse a single field from {@code tokenizer} and merge it into
+     * {@code builder}.
+     */
+    private void mergeField(final Tokenizer tokenizer,
+                            final ExtensionRegistry extensionRegistry,
+                            final MessageReflection.MergeTarget target)
+                            throws ParseException {
+      mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder);
+    }
+
+    /**
+     * Parse a single field from {@code tokenizer} and merge it into
+     * {@code builder}.
+     */
+    private void mergeField(final Tokenizer tokenizer,
+                            final ExtensionRegistry extensionRegistry,
+                            final MessageReflection.MergeTarget target,
+                            TextFormatParseInfoTree.Builder parseTreeBuilder)
+                            throws ParseException {
+      FieldDescriptor field = null;
+      int startLine = tokenizer.getLine();
+      int startColumn = tokenizer.getColumn();
+      final Descriptor type = target.getDescriptorForType();
+      ExtensionRegistry.ExtensionInfo extension = null;
+
+      if (tokenizer.tryConsume("[")) {
+        // An extension.
+        final StringBuilder name =
+            new StringBuilder(tokenizer.consumeIdentifier());
+        while (tokenizer.tryConsume(".")) {
+          name.append('.');
+          name.append(tokenizer.consumeIdentifier());
+        }
+
+        extension = target.findExtensionByName(
+            extensionRegistry, name.toString());
+
+        if (extension == null) {
+          if (!allowUnknownFields) {
+            throw tokenizer.parseExceptionPreviousToken(
+              "Extension \"" + name + "\" not found in the ExtensionRegistry.");
+          } else {
+            logger.warning(
+              "Extension \"" + name + "\" not found in the ExtensionRegistry.");
+          }
+        } else {
+          if (extension.descriptor.getContainingType() != type) {
+            throw tokenizer.parseExceptionPreviousToken(
+              "Extension \"" + name + "\" does not extend message type \""
+              + type.getFullName() + "\".");
+          }
+          field = extension.descriptor;
+        }
+
+        tokenizer.consume("]");
+      } else {
+        final String name = tokenizer.consumeIdentifier();
+        field = type.findFieldByName(name);
+
+        // Group names are expected to be capitalized as they appear in the
+        // .proto file, which actually matches their type names, not their field
+        // names.
+        if (field == null) {
+          // Explicitly specify US locale so that this code does not break when
+          // executing in Turkey.
+          final String lowerName = name.toLowerCase(Locale.US);
+          field = type.findFieldByName(lowerName);
+          // If the case-insensitive match worked but the field is NOT a group,
+          if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
+            field = null;
+          }
+        }
+        // Again, special-case group names as described above.
+        if (field != null && field.getType() == FieldDescriptor.Type.GROUP
+            && !field.getMessageType().getName().equals(name)) {
+          field = null;
+        }
+
+        if (field == null) {
+          if (!allowUnknownFields) {
+            throw tokenizer.unknownFieldParseExceptionPreviousToken(
+              name,
+              "Message type \"" + type.getFullName()
+              + "\" has no field named \"" + name + "\".");
+          } else {
+            logger.warning(
+              "Message type \"" + type.getFullName()
+              + "\" has no field named \"" + name + "\".");
+          }
+        }
+      }
+
+      // Skips unknown fields.
+      if (field == null) {
+        // Try to guess the type of this field.
+        // If this field is not a message, there should be a ":" between the
+        // field name and the field value and also the field value should not
+        // start with "{" or "<" which indicates the beginning of a message body.
+        // If there is no ":" or there is a "{" or "<" after ":", this field has
+        // to be a message or the input is ill-formed.
+        if (tokenizer.tryConsume(":")
+            && !tokenizer.lookingAt("{")
+            && !tokenizer.lookingAt("<")) {
+          skipFieldValue(tokenizer);
+        } else {
+          skipFieldMessage(tokenizer);
+        }
+        return;
+      }
+
+      // Handle potential ':'.
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        tokenizer.tryConsume(":");  // optional
+        if (parseTreeBuilder != null) {
+          TextFormatParseInfoTree.Builder childParseTreeBuilder =
+              parseTreeBuilder.getBuilderForSubMessageField(field);
+          consumeFieldValues(tokenizer, extensionRegistry, target, field, extension,
+              childParseTreeBuilder);
+        } else {
+          consumeFieldValues(tokenizer, extensionRegistry, target, field, extension,
+              parseTreeBuilder);
+        }
+      } else {
+        tokenizer.consume(":");  // required
+        consumeFieldValues(
+            tokenizer, extensionRegistry, target, field, extension, parseTreeBuilder);
+      }
+
+      if (parseTreeBuilder != null) {
+        parseTreeBuilder.setLocation(
+            field, TextFormatParseLocation.create(startLine, startColumn));
+      }
+
+      // For historical reasons, fields may optionally be separated by commas or
+      // semicolons.
+      if (!tokenizer.tryConsume(";")) {
+        tokenizer.tryConsume(",");
+      }
+    }
+
+    /**
+     * Parse a one or more field values from {@code tokenizer} and merge it into
+     * {@code builder}.
+     */
+    private void consumeFieldValues(
+        final Tokenizer tokenizer,
+        final ExtensionRegistry extensionRegistry,
+        final MessageReflection.MergeTarget target,
+        final FieldDescriptor field,
+        final ExtensionRegistry.ExtensionInfo extension,
+        final TextFormatParseInfoTree.Builder parseTreeBuilder)
+        throws ParseException {
+      // Support specifying repeated field values as a comma-separated list.
+      // Ex."foo: [1, 2, 3]"
+      if (field.isRepeated() && tokenizer.tryConsume("[")) {
+        while (true) {
+          consumeFieldValue(tokenizer, extensionRegistry, target, field, extension,
+              parseTreeBuilder);
+          if (tokenizer.tryConsume("]")) {
+            // End of list.
+            break;
+          }
+          tokenizer.consume(",");
+        }
+      } else {
+        consumeFieldValue(
+            tokenizer, extensionRegistry, target, field, extension, parseTreeBuilder);
+      }
+    }
+
+    /**
+     * Parse a single field value from {@code tokenizer} and merge it into
+     * {@code builder}.
+     */
+    private void consumeFieldValue(
+        final Tokenizer tokenizer,
+        final ExtensionRegistry extensionRegistry,
+        final MessageReflection.MergeTarget target,
+        final FieldDescriptor field,
+        final ExtensionRegistry.ExtensionInfo extension,
+        final TextFormatParseInfoTree.Builder parseTreeBuilder)
+        throws ParseException {
+      Object value = null;
+
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        final String endToken;
+        if (tokenizer.tryConsume("<")) {
+          endToken = ">";
+        } else {
+          tokenizer.consume("{");
+          endToken = "}";
+        }
+
+        final MessageReflection.MergeTarget subField;
+        subField = target.newMergeTargetForField(field,
+            (extension == null) ? null : extension.defaultInstance);
+
+        while (!tokenizer.tryConsume(endToken)) {
+          if (tokenizer.atEnd()) {
+            throw tokenizer.parseException(
+              "Expected \"" + endToken + "\".");
+          }
+          mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder);
+        }
+
+        value = subField.finish();
+
+      } else {
+        switch (field.getType()) {
+          case INT32:
+          case SINT32:
+          case SFIXED32:
+            value = tokenizer.consumeInt32();
+            break;
+
+          case INT64:
+          case SINT64:
+          case SFIXED64:
+            value = tokenizer.consumeInt64();
+            break;
+
+          case UINT32:
+          case FIXED32:
+            value = tokenizer.consumeUInt32();
+            break;
+
+          case UINT64:
+          case FIXED64:
+            value = tokenizer.consumeUInt64();
+            break;
+
+          case FLOAT:
+            value = tokenizer.consumeFloat();
+            break;
+
+          case DOUBLE:
+            value = tokenizer.consumeDouble();
+            break;
+
+          case BOOL:
+            value = tokenizer.consumeBoolean();
+            break;
+
+          case STRING:
+            value = tokenizer.consumeString();
+            break;
+
+          case BYTES:
+            value = tokenizer.consumeByteString();
+            break;
+
+          case ENUM:
+            final EnumDescriptor enumType = field.getEnumType();
+
+            if (tokenizer.lookingAtInteger()) {
+              final int number = tokenizer.consumeInt32();
+              value = enumType.findValueByNumber(number);
+              if (value == null) {
+                throw tokenizer.parseExceptionPreviousToken(
+                  "Enum type \"" + enumType.getFullName()
+                  + "\" has no value with number " + number + '.');
+              }
+            } else {
+              final String id = tokenizer.consumeIdentifier();
+              value = enumType.findValueByName(id);
+              if (value == null) {
+                throw tokenizer.parseExceptionPreviousToken(
+                  "Enum type \"" + enumType.getFullName()
+                  + "\" has no value named \"" + id + "\".");
+              }
+            }
+
+            break;
+
+          case MESSAGE:
+          case GROUP:
+            throw new RuntimeException("Can't get here.");
+        }
+      }
+
+      if (field.isRepeated()) {
+        target.addRepeatedField(field, value);
+      } else if ((singularOverwritePolicy
+              == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+          && target.hasField(field)) {
+        throw tokenizer.parseExceptionPreviousToken("Non-repeated field \""
+            + field.getFullName() + "\" cannot be overwritten.");
+      } else if ((singularOverwritePolicy
+              == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+          && field.getContainingOneof() != null
+          && target.hasOneof(field.getContainingOneof())) {
+        Descriptors.OneofDescriptor oneof = field.getContainingOneof();
+        throw tokenizer.parseExceptionPreviousToken("Field \""
+            + field.getFullName() + "\" is specified along with field \""
+            + target.getOneofFieldDescriptor(oneof).getFullName()
+            + "\", another member of oneof \"" + oneof.getName() + "\".");
+      } else {
+        target.setField(field, value);
+      }
+    }
+
+    /**
+     * Skips the next field including the field's name and value.
+     */
+    private void skipField(Tokenizer tokenizer) throws ParseException {
+      if (tokenizer.tryConsume("[")) {
+        // Extension name.
+        do {
+          tokenizer.consumeIdentifier();
+        } while (tokenizer.tryConsume("."));
+        tokenizer.consume("]");
+      } else {
+        tokenizer.consumeIdentifier();
+      }
+
+      // Try to guess the type of this field.
+      // If this field is not a message, there should be a ":" between the
+      // field name and the field value and also the field value should not
+      // start with "{" or "<" which indicates the beginning of a message body.
+      // If there is no ":" or there is a "{" or "<" after ":", this field has
+      // to be a message or the input is ill-formed.
+      if (tokenizer.tryConsume(":")
+          && !tokenizer.lookingAt("<")
+          && !tokenizer.lookingAt("{")) {
+        skipFieldValue(tokenizer);
+      } else {
+        skipFieldMessage(tokenizer);
+      }
+      // For historical reasons, fields may optionally be separated by commas or
+      // semicolons.
+      if (!tokenizer.tryConsume(";")) {
+        tokenizer.tryConsume(",");
+      }
+    }
+
+    /**
+     * Skips the whole body of a message including the beginning delimiter and
+     * the ending delimiter.
+     */
+    private void skipFieldMessage(Tokenizer tokenizer) throws ParseException {
+      final String delimiter;
+      if (tokenizer.tryConsume("<")) {
+        delimiter = ">";
+      } else {
+        tokenizer.consume("{");
+        delimiter = "}";
+      }
+      while (!tokenizer.lookingAt(">") && !tokenizer.lookingAt("}")) {
+        skipField(tokenizer);
+      }
+      tokenizer.consume(delimiter);
+    }
+
+    /**
+     * Skips a field value.
+     */
+    private void skipFieldValue(Tokenizer tokenizer) throws ParseException {
+      if (tokenizer.tryConsumeString()) {
+        while (tokenizer.tryConsumeString()) {}
+        return;
+      }
+      if (!tokenizer.tryConsumeIdentifier()   // includes enum & boolean
+          && !tokenizer.tryConsumeInt64()     // includes int32
+          && !tokenizer.tryConsumeUInt64()    // includes uint32
+          && !tokenizer.tryConsumeDouble()
+          && !tokenizer.tryConsumeFloat()) {
+        throw tokenizer.parseException(
+            "Invalid field value: " + tokenizer.currentToken);
+      }
+    }
+  }
+
+  // =================================================================
+  // Utility functions
+  //
+  // Some of these methods are package-private because Descriptors.java uses
+  // them.
+
+  /**
+   * Escapes bytes in the format used in protocol buffer text format, which
+   * is the same as the format used for C string literals.  All bytes
+   * that are not printable 7-bit ASCII characters are escaped, as well as
+   * backslash, single-quote, and double-quote characters.  Characters for
+   * which no defined short-hand escape sequence is defined will be escaped
+   * using 3-digit octal sequences.
+   */
+  public static String escapeBytes(ByteString input) {
+    return TextFormatEscaper.escapeBytes(input);
+  }
+
+  /**
+   * Like {@link #escapeBytes(ByteString)}, but used for byte array.
+   */
+  public static String escapeBytes(byte[] input) {
+    return TextFormatEscaper.escapeBytes(input);
+  }
+
+  /**
+   * Un-escape a byte sequence as escaped using
+   * {@link #escapeBytes(ByteString)}.  Two-digit hex escapes (starting with
+   * "\x") are also recognized.
+   */
+  public static ByteString unescapeBytes(final CharSequence charString)
+      throws InvalidEscapeSequenceException {
+    // First convert the Java character sequence to UTF-8 bytes.
+    ByteString input = ByteString.copyFromUtf8(charString.toString());
+    // Then unescape certain byte sequences introduced by ASCII '\\'.  The valid
+    // escapes can all be expressed with ASCII characters, so it is safe to
+    // operate on bytes here.
+    //
+    // Unescaping the input byte array will result in a byte sequence that's no
+    // longer than the input.  That's because each escape sequence is between
+    // two and four bytes long and stands for a single byte.
+    final byte[] result = new byte[input.size()];
+    int pos = 0;
+    for (int i = 0; i < input.size(); i++) {
+      byte c = input.byteAt(i);
+      if (c == '\\') {
+        if (i + 1 < input.size()) {
+          ++i;
+          c = input.byteAt(i);
+          if (isOctal(c)) {
+            // Octal escape.
+            int code = digitValue(c);
+            if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
+              ++i;
+              code = code * 8 + digitValue(input.byteAt(i));
+            }
+            if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
+              ++i;
+              code = code * 8 + digitValue(input.byteAt(i));
+            }
+            // TODO: Check that 0 <= code && code <= 0xFF.
+            result[pos++] = (byte) code;
+          } else {
+            switch (c) {
+              case 'a' : result[pos++] = 0x07; break;
+              case 'b' : result[pos++] = '\b'; break;
+              case 'f' : result[pos++] = '\f'; break;
+              case 'n' : result[pos++] = '\n'; break;
+              case 'r' : result[pos++] = '\r'; break;
+              case 't' : result[pos++] = '\t'; break;
+              case 'v' : result[pos++] = 0x0b; break;
+              case '\\': result[pos++] = '\\'; break;
+              case '\'': result[pos++] = '\''; break;
+              case '"' : result[pos++] = '\"'; break;
+
+              case 'x':
+                // hex escape
+                int code = 0;
+                if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
+                  ++i;
+                  code = digitValue(input.byteAt(i));
+                } else {
+                  throw new InvalidEscapeSequenceException(
+                      "Invalid escape sequence: '\\x' with no digits");
+                }
+                if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
+                  ++i;
+                  code = code * 16 + digitValue(input.byteAt(i));
+                }
+                result[pos++] = (byte) code;
+                break;
+
+              default:
+                throw new InvalidEscapeSequenceException(
+                    "Invalid escape sequence: '\\" + (char) c + '\'');
+            }
+          }
+        } else {
+          throw new InvalidEscapeSequenceException(
+              "Invalid escape sequence: '\\' at end of string.");
+        }
+      } else {
+        result[pos++] = c;
+      }
+    }
+
+    return result.length == pos
+        ? ByteString.wrap(result)  // This reference has not been out of our control.
+        : ByteString.copyFrom(result, 0, pos);
+  }
+
+  /**
+   * Thrown by {@link TextFormat#unescapeBytes} and
+   * {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
+   */
+  public static class InvalidEscapeSequenceException extends IOException {
+    private static final long serialVersionUID = -8164033650142593304L;
+
+    InvalidEscapeSequenceException(final String description) {
+      super(description);
+    }
+  }
+
+  /**
+   * Like {@link #escapeBytes(ByteString)}, but escapes a text string.
+   * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
+   * individually as a 3-digit octal escape.  Yes, it's weird.
+   */
+  static String escapeText(final String input) {
+    return escapeBytes(ByteString.copyFromUtf8(input));
+  }
+
+  /**
+   * Escape double quotes and backslashes in a String for unicode output of a message.
+   */
+  public static String escapeDoubleQuotesAndBackslashes(final String input) {
+    return TextFormatEscaper.escapeDoubleQuotesAndBackslashes(input);
+  }
+
+  /**
+   * Un-escape a text string as escaped using {@link #escapeText(String)}.
+   * Two-digit hex escapes (starting with "\x") are also recognized.
+   */
+  static String unescapeText(final String input)
+                             throws InvalidEscapeSequenceException {
+    return unescapeBytes(input).toStringUtf8();
+  }
+
+  /** Is this an octal digit? */
+  private static boolean isOctal(final byte c) {
+    return '0' <= c && c <= '7';
+  }
+
+  /** Is this a hex digit? */
+  private static boolean isHex(final byte c) {
+    return ('0' <= c && c <= '9')
+        || ('a' <= c && c <= 'f')
+        || ('A' <= c && c <= 'F');
+  }
+
+  /**
+   * Interpret a character as a digit (in any base up to 36) and return the
+   * numeric value.  This is like {@code Character.digit()} but we don't accept
+   * non-ASCII digits.
+   */
+  private static int digitValue(final byte c) {
+    if ('0' <= c && c <= '9') {
+      return c - '0';
+    } else if ('a' <= c && c <= 'z') {
+      return c - 'a' + 10;
+    } else {
+      return c - 'A' + 10;
+    }
+  }
+
+  /**
+   * Parse a 32-bit signed integer from the text.  Unlike the Java standard
+   * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+   * and "0" to signify hexadecimal and octal numbers, respectively.
+   */
+  static int parseInt32(final String text) throws NumberFormatException {
+    return (int) parseInteger(text, true, false);
+  }
+
+  /**
+   * Parse a 32-bit unsigned integer from the text.  Unlike the Java standard
+   * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+   * and "0" to signify hexadecimal and octal numbers, respectively.  The
+   * result is coerced to a (signed) {@code int} when returned since Java has
+   * no unsigned integer type.
+   */
+  static int parseUInt32(final String text) throws NumberFormatException {
+    return (int) parseInteger(text, false, false);
+  }
+
+  /**
+   * Parse a 64-bit signed integer from the text.  Unlike the Java standard
+   * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+   * and "0" to signify hexadecimal and octal numbers, respectively.
+   */
+  static long parseInt64(final String text) throws NumberFormatException {
+    return parseInteger(text, true, true);
+  }
+
+  /**
+   * Parse a 64-bit unsigned integer from the text.  Unlike the Java standard
+   * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+   * and "0" to signify hexadecimal and octal numbers, respectively.  The
+   * result is coerced to a (signed) {@code long} when returned since Java has
+   * no unsigned long type.
+   */
+  static long parseUInt64(final String text) throws NumberFormatException {
+    return parseInteger(text, false, true);
+  }
+
+  private static long parseInteger(final String text,
+                                   final boolean isSigned,
+                                   final boolean isLong)
+                                   throws NumberFormatException {
+    int pos = 0;
+
+    boolean negative = false;
+    if (text.startsWith("-", pos)) {
+      if (!isSigned) {
+        throw new NumberFormatException("Number must be positive: " + text);
+      }
+      ++pos;
+      negative = true;
+    }
+
+    int radix = 10;
+    if (text.startsWith("0x", pos)) {
+      pos += 2;
+      radix = 16;
+    } else if (text.startsWith("0", pos)) {
+      radix = 8;
+    }
+
+    final String numberText = text.substring(pos);
+
+    long result = 0;
+    if (numberText.length() < 16) {
+      // Can safely assume no overflow.
+      result = Long.parseLong(numberText, radix);
+      if (negative) {
+        result = -result;
+      }
+
+      // Check bounds.
+      // No need to check for 64-bit numbers since they'd have to be 16 chars
+      // or longer to overflow.
+      if (!isLong) {
+        if (isSigned) {
+          if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
+            throw new NumberFormatException(
+              "Number out of range for 32-bit signed integer: " + text);
+          }
+        } else {
+          if (result >= (1L << 32) || result < 0) {
+            throw new NumberFormatException(
+              "Number out of range for 32-bit unsigned integer: " + text);
+          }
+        }
+      }
+    } else {
+      BigInteger bigValue = new BigInteger(numberText, radix);
+      if (negative) {
+        bigValue = bigValue.negate();
+      }
+
+      // Check bounds.
+      if (!isLong) {
+        if (isSigned) {
+          if (bigValue.bitLength() > 31) {
+            throw new NumberFormatException(
+              "Number out of range for 32-bit signed integer: " + text);
+          }
+        } else {
+          if (bigValue.bitLength() > 32) {
+            throw new NumberFormatException(
+              "Number out of range for 32-bit unsigned integer: " + text);
+          }
+        }
+      } else {
+        if (isSigned) {
+          if (bigValue.bitLength() > 63) {
+            throw new NumberFormatException(
+              "Number out of range for 64-bit signed integer: " + text);
+          }
+        } else {
+          if (bigValue.bitLength() > 64) {
+            throw new NumberFormatException(
+              "Number out of range for 64-bit unsigned integer: " + text);
+          }
+        }
+      }
+
+      result = bigValue.longValue();
+    }
+
+    return result;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java
new file mode 100644
index 0000000..da9cead
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java
@@ -0,0 +1,137 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Provide text format escaping support for proto2 instances.
+ */
+final class TextFormatEscaper {
+  private TextFormatEscaper() {}
+
+  private interface ByteSequence {
+    int size();
+    byte byteAt(int offset);
+  }
+
+  /**
+   * Escapes bytes in the format used in protocol buffer text format, which
+   * is the same as the format used for C string literals.  All bytes
+   * that are not printable 7-bit ASCII characters are escaped, as well as
+   * backslash, single-quote, and double-quote characters.  Characters for
+   * which no defined short-hand escape sequence is defined will be escaped
+   * using 3-digit octal sequences.
+   */
+  static String escapeBytes(final ByteSequence input) {
+    final StringBuilder builder = new StringBuilder(input.size());
+    for (int i = 0; i < input.size(); i++) {
+      final byte b = input.byteAt(i);
+      switch (b) {
+        // Java does not recognize \a or \v, apparently.
+        case 0x07: builder.append("\\a"); break;
+        case '\b': builder.append("\\b"); break;
+        case '\f': builder.append("\\f"); break;
+        case '\n': builder.append("\\n"); break;
+        case '\r': builder.append("\\r"); break;
+        case '\t': builder.append("\\t"); break;
+        case 0x0b: builder.append("\\v"); break;
+        case '\\': builder.append("\\\\"); break;
+        case '\'': builder.append("\\\'"); break;
+        case '"' : builder.append("\\\""); break;
+        default:
+          // Only ASCII characters between 0x20 (space) and 0x7e (tilde) are
+          // printable.  Other byte values must be escaped.
+          if (b >= 0x20 && b <= 0x7e) {
+            builder.append((char) b);
+          } else {
+            builder.append('\\');
+            builder.append((char) ('0' + ((b >>> 6) & 3)));
+            builder.append((char) ('0' + ((b >>> 3) & 7)));
+            builder.append((char) ('0' + (b & 7)));
+          }
+          break;
+      }
+    }
+    return builder.toString();
+  }
+
+  /**
+   * Escapes bytes in the format used in protocol buffer text format, which
+   * is the same as the format used for C string literals.  All bytes
+   * that are not printable 7-bit ASCII characters are escaped, as well as
+   * backslash, single-quote, and double-quote characters.  Characters for
+   * which no defined short-hand escape sequence is defined will be escaped
+   * using 3-digit octal sequences.
+   */
+  static String escapeBytes(final ByteString input) {
+    return escapeBytes(new ByteSequence() {
+      @Override
+      public int size() {
+        return input.size();
+      }
+      @Override
+      public byte byteAt(int offset) {
+        return input.byteAt(offset);
+      }
+    });
+  }
+
+  /**
+   * Like {@link #escapeBytes(ByteString)}, but used for byte array.
+   */
+  static String escapeBytes(final byte[] input) {
+    return escapeBytes(new ByteSequence() {
+      @Override
+      public int size() {
+        return input.length;
+      }
+      @Override
+      public byte byteAt(int offset) {
+        return input[offset];
+      }
+    });
+  }
+
+  /**
+   * Like {@link #escapeBytes(ByteString)}, but escapes a text string.
+   * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
+   * individually as a 3-digit octal escape.  Yes, it's weird.
+   */
+  static String escapeText(final String input) {
+    return escapeBytes(ByteString.copyFromUtf8(input));
+  }
+
+  /**
+   * Escape double quotes and backslashes in a String for unicode output of a message.
+   */
+  static String escapeDoubleQuotesAndBackslashes(final String input) {
+    return input.replace("\\", "\\\\").replace("\"", "\\\"");
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
new file mode 100644
index 0000000..2ecf912
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
@@ -0,0 +1,225 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+
+/**
+ * Data structure which is populated with the locations of each field value parsed from the text.
+ *
+ * <p>The locations of primary fields values are retrieved by {@code getLocation} or
+ * {@code getLocations}.  The locations of sub message values are within nested
+ * {@code TextFormatParseInfoTree}s and are retrieve by {@getNestedTree} or {code @getNestedTrees}.
+ *
+ * <p>The {@code TextFormatParseInfoTree} is created by a Builder.
+ */
+public class TextFormatParseInfoTree {
+
+  // Defines a mapping between each field's descriptor to the list of locations where
+  // its value(s) were was encountered.
+  private Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField;
+
+  // Defines a mapping between a field's descriptor to a list of TextFormatParseInfoTrees for
+  // sub message location information.
+  Map<FieldDescriptor, List<TextFormatParseInfoTree>> subtreesFromField;
+
+  /**
+   * Construct a {@code TextFormatParseInfoTree}.
+   *
+   * @param locationsFromField a map of fields to location in the source code
+   * @param subtreeBuildersFromField a map of fields to parse tree location information builders
+   */
+  private TextFormatParseInfoTree(
+      Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField,
+      Map<FieldDescriptor, List<TextFormatParseInfoTree.Builder>> subtreeBuildersFromField) {
+
+    // The maps are unmodifiable.  The values in the maps are unmodifiable.
+    Map<FieldDescriptor, List<TextFormatParseLocation>> locs =
+        new HashMap<FieldDescriptor, List<TextFormatParseLocation>>();
+    for (Entry<FieldDescriptor, List<TextFormatParseLocation>> kv : locationsFromField.entrySet()) {
+      locs.put(kv.getKey(), Collections.unmodifiableList(kv.getValue()));
+    }
+    this.locationsFromField = Collections.unmodifiableMap(locs);
+
+    Map<FieldDescriptor, List<TextFormatParseInfoTree>> subs =
+        new HashMap<FieldDescriptor, List<TextFormatParseInfoTree>>();
+    for (Entry<FieldDescriptor, List<Builder>> kv : subtreeBuildersFromField.entrySet()) {
+      List<TextFormatParseInfoTree> submessagesOfField = new ArrayList<TextFormatParseInfoTree>();
+      for (Builder subBuilder : kv.getValue()) {
+        submessagesOfField.add(subBuilder.build());
+      }
+      subs.put(kv.getKey(), Collections.unmodifiableList(submessagesOfField));
+    }
+    this.subtreesFromField = Collections.unmodifiableMap(subs);
+  }
+
+ /**
+  * Retrieve all the locations of a field.
+  *
+  * @param fieldDescriptor the the @{link FieldDescriptor} of the desired field
+  * @return a list of the locations of values of the field.  If there are not values
+  *         or the field doesn't exist, an empty list is returned.
+  */
+  public List<TextFormatParseLocation> getLocations(final FieldDescriptor fieldDescriptor) {
+    List<TextFormatParseLocation> result = locationsFromField.get(fieldDescriptor);
+    return (result == null) ? Collections.<TextFormatParseLocation>emptyList() : result;
+  }
+
+  /**
+   * Get the location in the source of a field's value.
+   *
+   * <p>Returns the {@link TextFormatParseLocation} for index-th value of the field in the parsed
+   * text.
+   *
+   * @param fieldDescriptor the @{link FieldDescriptor} of the desired field
+   * @param index the index of the value.
+   * @return the {@link TextFormatParseLocation} of the value
+   * @throws IllegalArgumentException index is out of range
+   */
+  public TextFormatParseLocation getLocation(final FieldDescriptor fieldDescriptor, int index) {
+    return getFromList(getLocations(fieldDescriptor), index, fieldDescriptor);
+  }
+
+  /**
+   * Retrieve a list of all the location information trees for a sub message field.
+   *
+   * @param fieldDescriptor the @{link FieldDescriptor} of the desired field
+   * @return A list of {@link TextFormatParseInfoTree}
+   */
+  public List<TextFormatParseInfoTree> getNestedTrees(final FieldDescriptor fieldDescriptor) {
+    List<TextFormatParseInfoTree> result = subtreesFromField.get(fieldDescriptor);
+    return result == null ? Collections.<TextFormatParseInfoTree>emptyList() : result;
+  }
+
+  /**
+   * Returns the parse info tree for the given field, which must be a message type.
+   *
+   * @param fieldDescriptor the @{link FieldDescriptor} of the desired sub message
+   * @param index the index of message value.
+   * @return the {@code ParseInfoTree} of the message value. {@code null} is returned if the field
+   *         doesn't exist or the index is out of range.
+   * @throws IllegalArgumentException if index is out of range
+   */
+  public TextFormatParseInfoTree getNestedTree(final FieldDescriptor fieldDescriptor, int index) {
+    return getFromList(getNestedTrees(fieldDescriptor), index, fieldDescriptor);
+  }
+
+  /**
+   * Create a builder for a {@code ParseInfoTree}.
+   *
+   * @return the builder
+   */
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  private static <T> T getFromList(List<T> list, int index, FieldDescriptor fieldDescriptor) {
+    if (index >= list.size() || index < 0)  {
+      throw new IllegalArgumentException(String.format("Illegal index field: %s, index %d",
+          fieldDescriptor == null ? "<null>" : fieldDescriptor.getName(), index));
+    }
+    return list.get(index);
+  }
+
+  /**
+   * Builder for a {@link TextFormatParseInfoTree}.
+   */
+  public static class Builder {
+
+    private Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField;
+
+    // Defines a mapping between a field's descriptor to a list of ParseInfoTrees builders for
+    // sub message location information.
+    private Map<FieldDescriptor, List<Builder>> subtreeBuildersFromField;
+
+     /**
+     * Create a root level {@ParseInfoTree} builder.
+     */
+    private Builder() {
+      locationsFromField = new HashMap<FieldDescriptor, List<TextFormatParseLocation>>();
+      subtreeBuildersFromField = new HashMap<FieldDescriptor, List<Builder>>();
+    }
+
+    /**
+     * Record the starting location of a single value for a field.
+     *
+     * @param fieldDescriptor the field
+     * @param location source code location information
+     */
+    public Builder setLocation(
+        final FieldDescriptor fieldDescriptor, TextFormatParseLocation location) {
+      List<TextFormatParseLocation> fieldLocations = locationsFromField.get(fieldDescriptor);
+      if (fieldLocations == null) {
+        fieldLocations = new ArrayList<TextFormatParseLocation>();
+        locationsFromField.put(fieldDescriptor, fieldLocations);
+      }
+      fieldLocations.add(location);
+      return this;
+    }
+
+    /**
+     * Set for a sub message.
+     *
+     * <p>A new builder is created for a sub message. The builder that is returned is a new builder.
+     * The return is <emph>not</emph> the invoked {@code builder.getBuilderForSubMessageField}.
+     *
+     * @param fieldDescriptor the field whose value is the submessage
+     * @return a new Builder for the sub message
+     */
+    public Builder getBuilderForSubMessageField(final FieldDescriptor fieldDescriptor) {
+      List<Builder> submessageBuilders = subtreeBuildersFromField.get(fieldDescriptor);
+      if (submessageBuilders == null) {
+        submessageBuilders = new ArrayList<Builder>();
+        subtreeBuildersFromField.put(fieldDescriptor, submessageBuilders);
+      }
+      Builder subtreeBuilder = new Builder();
+      submessageBuilders.add(subtreeBuilder);
+      return subtreeBuilder;
+    }
+
+    /**
+     * Build the {@code TextFormatParseInfoTree}.
+     *
+     * @return the {@code TextFormatParseInfoTree}
+     */
+    public TextFormatParseInfoTree build() {
+      return new TextFormatParseInfoTree(locationsFromField, subtreeBuildersFromField);
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java
new file mode 100644
index 0000000..cce286e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java
@@ -0,0 +1,104 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Arrays;
+
+/**
+ * A location in the source code.
+ *
+ * <p>A location is the starting line number and starting column number.
+ */
+public final class TextFormatParseLocation {
+
+  /**
+   * The empty location.
+   */
+  public static final TextFormatParseLocation EMPTY = new TextFormatParseLocation(-1, -1);
+
+  /**
+   * Create a location.
+   *
+   * @param line the starting line number
+   * @param column the starting column number
+   * @return a {@code ParseLocation}
+   */
+  static TextFormatParseLocation create(int line, int column) {
+    if (line == -1 && column == -1) {
+      return EMPTY;
+    }
+    if (line < 0 || column < 0) {
+      throw new IllegalArgumentException(
+          String.format("line and column values must be >= 0: line %d, column: %d", line, column));
+    }
+    return new TextFormatParseLocation(line, column);
+  }
+
+  private final int line;
+  private final int column;
+
+  private TextFormatParseLocation(int line, int column) {
+    this.line = line;
+    this.column = column;
+  }
+
+  public int getLine() {
+    return line;
+  }
+
+  public int getColumn() {
+    return column;
+  }
+
+  @Override
+  public String toString() {
+    return String.format("ParseLocation{line=%d, column=%d}", line, column);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof TextFormatParseLocation)) {
+      return false;
+    }
+    TextFormatParseLocation that = (TextFormatParseLocation) o;
+    return (this.line == that.getLine())
+         && (this.column == that.getColumn());
+  }
+
+  @Override
+  public int hashCode() {
+    int[] values = {line, column};
+    return Arrays.hashCode(values);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java
new file mode 100644
index 0000000..5714c06
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java
@@ -0,0 +1,99 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Thrown when attempting to build a protocol message that is missing required
+ * fields.  This is a {@code RuntimeException} because it normally represents
+ * a programming error:  it happens when some code which constructs a message
+ * fails to set all the fields.  {@code parseFrom()} methods <b>do not</b>
+ * throw this; they throw an {@link InvalidProtocolBufferException} if
+ * required fields are missing, because it is not a programming error to
+ * receive an incomplete message.  In other words,
+ * {@code UninitializedMessageException} should never be thrown by correct
+ * code, but {@code InvalidProtocolBufferException} might be.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class UninitializedMessageException extends RuntimeException {
+  private static final long serialVersionUID = -7466929953374883507L;
+
+  public UninitializedMessageException(final MessageLite message) {
+    super("Message was missing required fields.  (Lite runtime could not " +
+          "determine which fields were missing).");
+    missingFields = null;
+  }
+
+  public UninitializedMessageException(final List<String> missingFields) {
+    super(buildDescription(missingFields));
+    this.missingFields = missingFields;
+  }
+
+  private final List<String> missingFields;
+
+  /**
+   * Get a list of human-readable names of required fields missing from this
+   * message.  Each name is a full path to a field, e.g. "foo.bar[5].baz".
+   * Returns null if the lite runtime was used, since it lacks the ability to
+   * find missing fields.
+   */
+  public List<String> getMissingFields() {
+    return Collections.unmodifiableList(missingFields);
+  }
+
+  /**
+   * Converts this exception to an {@link InvalidProtocolBufferException}.
+   * When a parsed message is missing required fields, this should be thrown
+   * instead of {@code UninitializedMessageException}.
+   */
+  public InvalidProtocolBufferException asInvalidProtocolBufferException() {
+    return new InvalidProtocolBufferException(getMessage());
+  }
+
+  /** Construct the description string for this exception. */
+  private static String buildDescription(final List<String> missingFields) {
+    final StringBuilder description =
+      new StringBuilder("Message missing required fields: ");
+    boolean first = true;
+    for (final String field : missingFields) {
+      if (first) {
+        first = false;
+      } else {
+        description.append(", ");
+      }
+      description.append(field);
+    }
+    return description.toString();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
new file mode 100644
index 0000000..c906420
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -0,0 +1,1035 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * {@code UnknownFieldSet} is used to keep track of fields which were seen when
+ * parsing a protocol message but whose field numbers or types are unrecognized.
+ * This most frequently occurs when new fields are added to a message type
+ * and then messages containing those fields are read by old software that was
+ * compiled before the new types were added.
+ *
+ * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
+ * {@link Message.Builder} contains an {@link Builder}).
+ *
+ * <p>Most users will never need to use this class.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class UnknownFieldSet implements MessageLite {
+  private UnknownFieldSet() {}
+
+  /** Create a new {@link Builder}. */
+  public static Builder newBuilder() {
+    return Builder.create();
+  }
+
+  /**
+   * Create a new {@link Builder} and initialize it to be a copy
+   * of {@code copyFrom}.
+   */
+  public static Builder newBuilder(final UnknownFieldSet copyFrom) {
+    return newBuilder().mergeFrom(copyFrom);
+  }
+
+  /** Get an empty {@code UnknownFieldSet}. */
+  public static UnknownFieldSet getDefaultInstance() {
+    return defaultInstance;
+  }
+  @Override
+  public UnknownFieldSet getDefaultInstanceForType() {
+    return defaultInstance;
+  }
+  private static final UnknownFieldSet defaultInstance =
+    new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
+
+  /**
+   * Construct an {@code UnknownFieldSet} around the given map.  The map is
+   * expected to be immutable.
+   */
+  private UnknownFieldSet(final Map<Integer, Field> fields) {
+    this.fields = fields;
+  }
+  private Map<Integer, Field> fields;
+
+
+  @Override
+  public boolean equals(final Object other) {
+    if (this == other) {
+      return true;
+    }
+    return (other instanceof UnknownFieldSet) &&
+           fields.equals(((UnknownFieldSet) other).fields);
+  }
+
+  @Override
+  public int hashCode() {
+    return fields.hashCode();
+  }
+
+  /** Get a map of fields in the set by number. */
+  public Map<Integer, Field> asMap() {
+    return fields;
+  }
+
+  /** Check if the given field number is present in the set. */
+  public boolean hasField(final int number) {
+    return fields.containsKey(number);
+  }
+
+  /**
+   * Get a field by number.  Returns an empty field if not present.  Never
+   * returns {@code null}.
+   */
+  public Field getField(final int number) {
+    final Field result = fields.get(number);
+    return (result == null) ? Field.getDefaultInstance() : result;
+  }
+
+  /** Serializes the set and writes it to {@code output}. */
+  @Override
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+      entry.getValue().writeTo(entry.getKey(), output);
+    }
+  }
+
+  /**
+   * Converts the set to a string in protocol buffer text format. This is
+   * just a trivial wrapper around
+   * {@link TextFormat#printToString(UnknownFieldSet)}.
+   */
+  @Override
+  public String toString() {
+    return TextFormat.printToString(this);
+  }
+
+  /**
+   * Serializes the message to a {@code ByteString} and returns it. This is
+   * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+   */
+  @Override
+  public ByteString toByteString() {
+    try {
+      final ByteString.CodedBuilder out =
+        ByteString.newCodedBuilder(getSerializedSize());
+      writeTo(out.getCodedOutput());
+      return out.build();
+    } catch (final IOException e) {
+      throw new RuntimeException(
+        "Serializing to a ByteString threw an IOException (should " +
+        "never happen).", e);
+    }
+  }
+
+  /**
+   * Serializes the message to a {@code byte} array and returns it.  This is
+   * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+   */
+  @Override
+  public byte[] toByteArray() {
+    try {
+      final byte[] result = new byte[getSerializedSize()];
+      final CodedOutputStream output = CodedOutputStream.newInstance(result);
+      writeTo(output);
+      output.checkNoSpaceLeft();
+      return result;
+    } catch (final IOException e) {
+      throw new RuntimeException(
+        "Serializing to a byte array threw an IOException " +
+        "(should never happen).", e);
+    }
+  }
+
+  /**
+   * Serializes the message and writes it to {@code output}.  This is just a
+   * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+   */
+  @Override
+  public void writeTo(final OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  @Override
+  public void writeDelimitedTo(OutputStream output) throws IOException {
+    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+    codedOutput.writeRawVarint32(getSerializedSize());
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  /** Get the number of bytes required to encode this set. */
+  @Override
+  public int getSerializedSize() {
+    int result = 0;
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+      result += entry.getValue().getSerializedSize(entry.getKey());
+    }
+    return result;
+  }
+
+  /**
+   * Serializes the set and writes it to {@code output} using
+   * {@code MessageSet} wire format.
+   */
+  public void writeAsMessageSetTo(final CodedOutputStream output)
+      throws IOException {
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+      entry.getValue().writeAsMessageSetExtensionTo(
+        entry.getKey(), output);
+    }
+  }
+
+  /**
+   * Get the number of bytes required to encode this set using
+   * {@code MessageSet} wire format.
+   */
+  public int getSerializedSizeAsMessageSet() {
+    int result = 0;
+    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+      result += entry.getValue().getSerializedSizeAsMessageSetExtension(
+        entry.getKey());
+    }
+    return result;
+  }
+
+  @Override
+  public boolean isInitialized() {
+    // UnknownFieldSets do not have required fields, so they are always
+    // initialized.
+    return true;
+  }
+
+  /** Parse an {@code UnknownFieldSet} from the given input stream. */
+  public static UnknownFieldSet parseFrom(final CodedInputStream input)
+                                          throws IOException {
+    return newBuilder().mergeFrom(input).build();
+  }
+
+  /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+  public static UnknownFieldSet parseFrom(final ByteString data)
+      throws InvalidProtocolBufferException {
+    return newBuilder().mergeFrom(data).build();
+  }
+
+  /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+  public static UnknownFieldSet parseFrom(final byte[] data)
+      throws InvalidProtocolBufferException {
+    return newBuilder().mergeFrom(data).build();
+  }
+
+  /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
+  public static UnknownFieldSet parseFrom(final InputStream input)
+                                          throws IOException {
+    return newBuilder().mergeFrom(input).build();
+  }
+
+  @Override
+  public Builder newBuilderForType() {
+    return newBuilder();
+  }
+
+  @Override
+  public Builder toBuilder() {
+    return newBuilder().mergeFrom(this);
+  }
+
+  /**
+   * Builder for {@link UnknownFieldSet}s.
+   *
+   * <p>Note that this class maintains {@link Field.Builder}s for all fields
+   * in the set.  Thus, adding one element to an existing {@link Field} does not
+   * require making a copy.  This is important for efficient parsing of
+   * unknown repeated fields.  However, it implies that {@link Field}s cannot
+   * be constructed independently, nor can two {@link UnknownFieldSet}s share
+   * the same {@code Field} object.
+   *
+   * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
+   */
+  public static final class Builder implements MessageLite.Builder {
+    // This constructor should never be called directly (except from 'create').
+    private Builder() {}
+
+    private Map<Integer, Field> fields;
+
+    // Optimization:  We keep around a builder for the last field that was
+    //   modified so that we can efficiently add to it multiple times in a
+    //   row (important when parsing an unknown repeated field).
+    private int lastFieldNumber;
+    private Field.Builder lastField;
+
+    private static Builder create() {
+      Builder builder = new Builder();
+      builder.reinitialize();
+      return builder;
+    }
+
+    /**
+     * Get a field builder for the given field number which includes any
+     * values that already exist.
+     */
+    private Field.Builder getFieldBuilder(final int number) {
+      if (lastField != null) {
+        if (number == lastFieldNumber) {
+          return lastField;
+        }
+        // Note:  addField() will reset lastField and lastFieldNumber.
+        addField(lastFieldNumber, lastField.build());
+      }
+      if (number == 0) {
+        return null;
+      } else {
+        final Field existing = fields.get(number);
+        lastFieldNumber = number;
+        lastField = Field.newBuilder();
+        if (existing != null) {
+          lastField.mergeFrom(existing);
+        }
+        return lastField;
+      }
+    }
+
+    /**
+     * Build the {@link UnknownFieldSet} and return it.
+     *
+     * <p>Once {@code build()} has been called, the {@code Builder} will no
+     * longer be usable.  Calling any method after {@code build()} will result
+     * in undefined behavior and can cause a {@code NullPointerException} to be
+     * thrown.
+     */
+    @Override
+    public UnknownFieldSet build() {
+      getFieldBuilder(0);  // Force lastField to be built.
+      final UnknownFieldSet result;
+      if (fields.isEmpty()) {
+        result = getDefaultInstance();
+      } else {
+        result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
+      }
+      fields = null;
+      return result;
+    }
+
+    @Override
+    public UnknownFieldSet buildPartial() {
+      // No required fields, so this is the same as build().
+      return build();
+    }
+
+    @Override
+    public Builder clone() {
+      getFieldBuilder(0);  // Force lastField to be built.
+      return UnknownFieldSet.newBuilder().mergeFrom(
+          new UnknownFieldSet(fields));
+    }
+
+    @Override
+    public UnknownFieldSet getDefaultInstanceForType() {
+      return UnknownFieldSet.getDefaultInstance();
+    }
+
+    private void reinitialize() {
+      fields = Collections.emptyMap();
+      lastFieldNumber = 0;
+      lastField = null;
+    }
+
+    /** Reset the builder to an empty set. */
+    @Override
+    public Builder clear() {
+      reinitialize();
+      return this;
+    }
+    
+    /** Clear fields from the set with a given field number. */
+    public Builder clearField(final int number) {
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      if (lastField != null && lastFieldNumber == number) {
+        // Discard this.
+        lastField = null;
+        lastFieldNumber = 0;
+      }
+      if (fields.containsKey(number)) {
+        fields.remove(number);
+      }
+      return this;
+    }
+
+    /**
+     * Merge the fields from {@code other} into this set.  If a field number
+     * exists in both sets, {@code other}'s values for that field will be
+     * appended to the values in this set.
+     */
+    public Builder mergeFrom(final UnknownFieldSet other) {
+      if (other != getDefaultInstance()) {
+        for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
+          mergeField(entry.getKey(), entry.getValue());
+        }
+      }
+      return this;
+    }
+
+    /**
+     * Add a field to the {@code UnknownFieldSet}.  If a field with the same
+     * number already exists, the two are merged.
+     */
+    public Builder mergeField(final int number, final Field field) {
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      if (hasField(number)) {
+        getFieldBuilder(number).mergeFrom(field);
+      } else {
+        // Optimization:  We could call getFieldBuilder(number).mergeFrom(field)
+        // in this case, but that would create a copy of the Field object.
+        // We'd rather reuse the one passed to us, so call addField() instead.
+        addField(number, field);
+      }
+      return this;
+    }
+
+    /**
+     * Convenience method for merging a new field containing a single varint
+     * value.  This is used in particular when an unknown enum value is
+     * encountered.
+     */
+    public Builder mergeVarintField(final int number, final int value) {
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      getFieldBuilder(number).addVarint(value);
+      return this;
+    }
+
+
+    /**
+     * Convenience method for merging a length-delimited field.
+     *
+     * <p>For use by generated code only.
+     */
+    public Builder mergeLengthDelimitedField(
+        final int number, final ByteString value) {  
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      getFieldBuilder(number).addLengthDelimited(value);
+      return this;
+    }
+
+    /** Check if the given field number is present in the set. */
+    public boolean hasField(final int number) {
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      return number == lastFieldNumber || fields.containsKey(number);
+    }
+
+    /**
+     * Add a field to the {@code UnknownFieldSet}.  If a field with the same
+     * number already exists, it is removed.
+     */
+    public Builder addField(final int number, final Field field) {
+      if (number == 0) {
+        throw new IllegalArgumentException("Zero is not a valid field number.");
+      }
+      if (lastField != null && lastFieldNumber == number) {
+        // Discard this.
+        lastField = null;
+        lastFieldNumber = 0;
+      }
+      if (fields.isEmpty()) {
+        fields = new TreeMap<Integer,Field>();
+      }
+      fields.put(number, field);
+      return this;
+    }
+
+    /**
+     * Get all present {@code Field}s as an immutable {@code Map}.  If more
+     * fields are added, the changes may or may not be reflected in this map.
+     */
+    public Map<Integer, Field> asMap() {
+      getFieldBuilder(0);  // Force lastField to be built.
+      return Collections.unmodifiableMap(fields);
+    }
+
+    /**
+     * Parse an entire message from {@code input} and merge its fields into
+     * this set.
+     */
+    @Override
+    public Builder mergeFrom(final CodedInputStream input) throws IOException {
+      while (true) {
+        final int tag = input.readTag();
+        if (tag == 0 || !mergeFieldFrom(tag, input)) {
+          break;
+        }
+      }
+      return this;
+    }
+
+    /**
+     * Parse a single field from {@code input} and merge it into this set.
+     * @param tag The field's tag number, which was already parsed.
+     * @return {@code false} if the tag is an end group tag.
+     */
+    public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
+                                  throws IOException {
+      final int number = WireFormat.getTagFieldNumber(tag);
+      switch (WireFormat.getTagWireType(tag)) {
+        case WireFormat.WIRETYPE_VARINT:
+          getFieldBuilder(number).addVarint(input.readInt64());
+          return true;
+        case WireFormat.WIRETYPE_FIXED64:
+          getFieldBuilder(number).addFixed64(input.readFixed64());
+          return true;
+        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+          getFieldBuilder(number).addLengthDelimited(input.readBytes());
+          return true;
+        case WireFormat.WIRETYPE_START_GROUP:
+          final Builder subBuilder = newBuilder();
+          input.readGroup(number, subBuilder,
+                          ExtensionRegistry.getEmptyRegistry());
+          getFieldBuilder(number).addGroup(subBuilder.build());
+          return true;
+        case WireFormat.WIRETYPE_END_GROUP:
+          return false;
+        case WireFormat.WIRETYPE_FIXED32:
+          getFieldBuilder(number).addFixed32(input.readFixed32());
+          return true;
+        default:
+          throw InvalidProtocolBufferException.invalidWireType();
+      }
+    }
+
+    /**
+     * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+     * set being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    @Override
+    public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return this;
+      } catch (final InvalidProtocolBufferException e) {
+        throw e;
+      } catch (final IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    /**
+     * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+     * set being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    @Override
+    public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = CodedInputStream.newInstance(data);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return this;
+      } catch (final InvalidProtocolBufferException e) {
+        throw e;
+      } catch (final IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    /**
+     * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
+     * set being built.  This is just a small wrapper around
+     * {@link #mergeFrom(CodedInputStream)}.
+     */
+    @Override
+    public Builder mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput);
+      codedInput.checkLastTagWas(0);
+      return this;
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(InputStream input) throws IOException {
+      final int firstByte = input.read();
+      if (firstByte == -1) {
+        return false;
+      }
+      final int size = CodedInputStream.readRawVarint32(firstByte, input);
+      final InputStream limitedInput = new LimitedInputStream(input, size);
+      mergeFrom(limitedInput);
+      return true;
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeDelimitedFrom(input);
+    }
+
+    @Override
+    public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(input);
+    }
+
+    @Override
+    public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data);
+    }
+
+    @Override
+    public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data);
+    }
+
+    @Override
+    public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(data, off, len);
+    }
+
+    @Override
+    public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      // UnknownFieldSet has no extensions.
+      return mergeFrom(input);
+    }
+
+    @Override
+    public Builder mergeFrom(MessageLite m) {
+      if (m instanceof UnknownFieldSet) {
+        return mergeFrom((UnknownFieldSet) m);
+      }
+      throw new IllegalArgumentException(
+          "mergeFrom(MessageLite) can only merge messages of the same type.");
+    }
+
+    @Override
+    public boolean isInitialized() {
+      // UnknownFieldSets do not have required fields, so they are always
+      // initialized.
+      return true;
+    }
+  }
+
+  /**
+   * Represents a single field in an {@code UnknownFieldSet}.
+   *
+   * <p>A {@code Field} consists of five lists of values.  The lists correspond
+   * to the five "wire types" used in the protocol buffer binary format.
+   * The wire type of each field can be determined from the encoded form alone,
+   * without knowing the field's declared type.  So, we are able to parse
+   * unknown values at least this far and separate them.  Normally, only one
+   * of the five lists will contain any values, since it is impossible to
+   * define a valid message type that declares two different types for the
+   * same field number.  However, the code is designed to allow for the case
+   * where the same unknown field number is encountered using multiple different
+   * wire types.
+   *
+   * <p>{@code Field} is an immutable class.  To construct one, you must use a
+   * {@link Builder}.
+   *
+   * @see UnknownFieldSet
+   */
+  public static final class Field {
+    private Field() {}
+
+    /** Construct a new {@link Builder}. */
+    public static Builder newBuilder() {
+      return Builder.create();
+    }
+
+    /**
+     * Construct a new {@link Builder} and initialize it to a copy of
+     * {@code copyFrom}.
+     */
+    public static Builder newBuilder(final Field copyFrom) {
+      return newBuilder().mergeFrom(copyFrom);
+    }
+
+    /** Get an empty {@code Field}. */
+    public static Field getDefaultInstance() {
+      return fieldDefaultInstance;
+    }
+    private static final Field fieldDefaultInstance = newBuilder().build();
+
+    /** Get the list of varint values for this field. */
+    public List<Long> getVarintList()               { return varint;          }
+
+    /** Get the list of fixed32 values for this field. */
+    public List<Integer> getFixed32List()           { return fixed32;         }
+
+    /** Get the list of fixed64 values for this field. */
+    public List<Long> getFixed64List()              { return fixed64;         }
+
+    /** Get the list of length-delimited values for this field. */
+    public List<ByteString> getLengthDelimitedList() { return lengthDelimited; }
+
+    /**
+     * Get the list of embedded group values for this field.  These are
+     * represented using {@link UnknownFieldSet}s rather than {@link Message}s
+     * since the group's type is presumably unknown.
+     */
+    public List<UnknownFieldSet> getGroupList()      { return group;           }
+
+    @Override
+    public boolean equals(final Object other) {
+      if (this == other) {
+        return true;
+      }
+      if (!(other instanceof Field)) {
+        return false;
+      }
+      return Arrays.equals(getIdentityArray(),
+          ((Field) other).getIdentityArray());
+    }
+
+    @Override
+    public int hashCode() {
+      return Arrays.hashCode(getIdentityArray());
+    }
+
+    /**
+     * Returns the array of objects to be used to uniquely identify this
+     * {@link Field} instance.
+     */
+    private Object[] getIdentityArray() {
+      return new Object[] {
+          varint,
+          fixed32,
+          fixed64,
+          lengthDelimited,
+          group};
+    }
+
+    /**
+     * Serializes the field, including field number, and writes it to
+     * {@code output}.
+     */
+    public void writeTo(final int fieldNumber, final CodedOutputStream output)
+                        throws IOException {
+      for (final long value : varint) {
+        output.writeUInt64(fieldNumber, value);
+      }
+      for (final int value : fixed32) {
+        output.writeFixed32(fieldNumber, value);
+      }
+      for (final long value : fixed64) {
+        output.writeFixed64(fieldNumber, value);
+      }
+      for (final ByteString value : lengthDelimited) {
+        output.writeBytes(fieldNumber, value);
+      }
+      for (final UnknownFieldSet value : group) {
+        output.writeGroup(fieldNumber, value);
+      }
+    }
+
+    /**
+     * Get the number of bytes required to encode this field, including field
+     * number.
+     */
+    public int getSerializedSize(final int fieldNumber) {
+      int result = 0;
+      for (final long value : varint) {
+        result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
+      }
+      for (final int value : fixed32) {
+        result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
+      }
+      for (final long value : fixed64) {
+        result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
+      }
+      for (final ByteString value : lengthDelimited) {
+        result += CodedOutputStream.computeBytesSize(fieldNumber, value);
+      }
+      for (final UnknownFieldSet value : group) {
+        result += CodedOutputStream.computeGroupSize(fieldNumber, value);
+      }
+      return result;
+    }
+
+    /**
+     * Serializes the field, including field number, and writes it to
+     * {@code output}, using {@code MessageSet} wire format.
+     */
+    public void writeAsMessageSetExtensionTo(
+        final int fieldNumber,
+        final CodedOutputStream output)
+        throws IOException {
+      for (final ByteString value : lengthDelimited) {
+        output.writeRawMessageSetExtension(fieldNumber, value);
+      }
+    }
+
+    /**
+     * Get the number of bytes required to encode this field, including field
+     * number, using {@code MessageSet} wire format.
+     */
+    public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
+      int result = 0;
+      for (final ByteString value : lengthDelimited) {
+        result += CodedOutputStream.computeRawMessageSetExtensionSize(
+          fieldNumber, value);
+      }
+      return result;
+    }
+
+    private List<Long> varint;
+    private List<Integer> fixed32;
+    private List<Long> fixed64;
+    private List<ByteString> lengthDelimited;
+    private List<UnknownFieldSet> group;
+
+    /**
+     * Used to build a {@link Field} within an {@link UnknownFieldSet}.
+     *
+     * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
+     */
+    public static final class Builder {
+      // This constructor should never be called directly (except from 'create').
+      private Builder() {}
+
+      private static Builder create() {
+        Builder builder = new Builder();
+        builder.result = new Field();
+        return builder;
+      }
+
+      private Field result;
+
+      /**
+       * Build the field.  After {@code build()} has been called, the
+       * {@code Builder} is no longer usable.  Calling any other method will
+       * result in undefined behavior and can cause a
+       * {@code NullPointerException} to be thrown.
+       */
+      public Field build() {
+        if (result.varint == null) {
+          result.varint = Collections.emptyList();
+        } else {
+          result.varint = Collections.unmodifiableList(result.varint);
+        }
+        if (result.fixed32 == null) {
+          result.fixed32 = Collections.emptyList();
+        } else {
+          result.fixed32 = Collections.unmodifiableList(result.fixed32);
+        }
+        if (result.fixed64 == null) {
+          result.fixed64 = Collections.emptyList();
+        } else {
+          result.fixed64 = Collections.unmodifiableList(result.fixed64);
+        }
+        if (result.lengthDelimited == null) {
+          result.lengthDelimited = Collections.emptyList();
+        } else {
+          result.lengthDelimited =
+            Collections.unmodifiableList(result.lengthDelimited);
+        }
+        if (result.group == null) {
+          result.group = Collections.emptyList();
+        } else {
+          result.group = Collections.unmodifiableList(result.group);
+        }
+
+        final Field returnMe = result;
+        result = null;
+        return returnMe;
+      }
+
+      /** Discard the field's contents. */
+      public Builder clear() {
+        result = new Field();
+        return this;
+      }
+
+      /**
+       * Merge the values in {@code other} into this field.  For each list
+       * of values, {@code other}'s values are append to the ones in this
+       * field.
+       */
+      public Builder mergeFrom(final Field other) {
+        if (!other.varint.isEmpty()) {
+          if (result.varint == null) {
+            result.varint = new ArrayList<Long>();
+          }
+          result.varint.addAll(other.varint);
+        }
+        if (!other.fixed32.isEmpty()) {
+          if (result.fixed32 == null) {
+            result.fixed32 = new ArrayList<Integer>();
+          }
+          result.fixed32.addAll(other.fixed32);
+        }
+        if (!other.fixed64.isEmpty()) {
+          if (result.fixed64 == null) {
+            result.fixed64 = new ArrayList<Long>();
+          }
+          result.fixed64.addAll(other.fixed64);
+        }
+        if (!other.lengthDelimited.isEmpty()) {
+          if (result.lengthDelimited == null) {
+            result.lengthDelimited = new ArrayList<ByteString>();
+          }
+          result.lengthDelimited.addAll(other.lengthDelimited);
+        }
+        if (!other.group.isEmpty()) {
+          if (result.group == null) {
+            result.group = new ArrayList<UnknownFieldSet>();
+          }
+          result.group.addAll(other.group);
+        }
+        return this;
+      }
+
+      /** Add a varint value. */
+      public Builder addVarint(final long value) {
+        if (result.varint == null) {
+          result.varint = new ArrayList<Long>();
+        }
+        result.varint.add(value);
+        return this;
+      }
+
+      /** Add a fixed32 value. */
+      public Builder addFixed32(final int value) {
+        if (result.fixed32 == null) {
+          result.fixed32 = new ArrayList<Integer>();
+        }
+        result.fixed32.add(value);
+        return this;
+      }
+
+      /** Add a fixed64 value. */
+      public Builder addFixed64(final long value) {
+        if (result.fixed64 == null) {
+          result.fixed64 = new ArrayList<Long>();
+        }
+        result.fixed64.add(value);
+        return this;
+      }
+
+      /** Add a length-delimited value. */
+      public Builder addLengthDelimited(final ByteString value) {
+        if (result.lengthDelimited == null) {
+          result.lengthDelimited = new ArrayList<ByteString>();
+        }
+        result.lengthDelimited.add(value);
+        return this;
+      }
+
+      /** Add an embedded group. */
+      public Builder addGroup(final UnknownFieldSet value) {
+        if (result.group == null) {
+          result.group = new ArrayList<UnknownFieldSet>();
+        }
+        result.group.add(value);
+        return this;
+      }
+    }
+  }
+
+  /**
+   * Parser to implement MessageLite interface.
+   */
+  public static final class Parser extends AbstractParser<UnknownFieldSet> {
+    @Override
+    public UnknownFieldSet parsePartialFrom(
+        CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (IOException e) {
+        throw new InvalidProtocolBufferException(e.getMessage())
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  }
+
+  private static final Parser PARSER = new Parser();
+  @Override
+  public final Parser getParserForType() {
+    return PARSER;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
new file mode 100644
index 0000000..9500f90
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -0,0 +1,378 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * {@code UnknownFieldSetLite} is used to keep track of fields which were seen
+ * when parsing a protocol message but whose field numbers or types are
+ * unrecognized. This most frequently occurs when new fields are added to a
+ * message type and then messages containing those fields are read by old
+ * software that was compiled before the new types were added.
+ *
+ * <p>For use by generated code only.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public final class UnknownFieldSetLite {
+  
+  // Arbitrarily chosen.
+  // TODO(dweis): Tune this number?
+  private static final int MIN_CAPACITY = 8;
+
+  private static final UnknownFieldSetLite DEFAULT_INSTANCE =
+      new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */);
+
+  /**
+   * Get an empty {@code UnknownFieldSetLite}.
+   *
+   * <p>For use by generated code only.
+   */
+  public static UnknownFieldSetLite getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+  
+  /**
+   * Returns a new mutable instance.
+   */
+  static UnknownFieldSetLite newInstance() {
+    return new UnknownFieldSetLite();
+  }
+
+  /**
+   * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and
+   * {@code second}.
+   */
+  static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) {
+    int count = first.count + second.count;
+    int[] tags = Arrays.copyOf(first.tags, count);
+    System.arraycopy(second.tags, 0, tags, first.count, second.count);
+    Object[] objects = Arrays.copyOf(first.objects, count);
+    System.arraycopy(second.objects, 0, objects, first.count, second.count);
+    return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */);
+  }
+  
+  /**
+   * The number of elements in the set.
+   */
+  private int count;
+  
+  /**
+   * The tag numbers for the elements in the set.
+   */
+  private int[] tags;
+  
+  /**
+   * The boxed values of the elements in the set.
+   */
+  private Object[] objects;
+  
+  /**
+   * The lazily computed serialized size of the set.
+   */
+  private int memoizedSerializedSize = -1;
+  
+  /**
+   * Indicates that this object is mutable. 
+   */
+  private boolean isMutable;
+
+  /**
+   * Constructs a mutable {@code UnknownFieldSetLite}.
+   */
+  private UnknownFieldSetLite() {
+    this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */);
+  }
+  
+  /**
+   * Constructs the {@code UnknownFieldSetLite}.
+   */
+  private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) {
+    this.count = count;
+    this.tags = tags;
+    this.objects = objects;
+    this.isMutable = isMutable;
+  }
+  
+  /**
+   * Marks this object as immutable.
+   * 
+   * <p>Future calls to methods that attempt to modify this object will throw.
+   */
+  public void makeImmutable() {
+    this.isMutable = false;
+  }
+  
+  /**
+   * Throws an {@link UnsupportedOperationException} if immutable.
+   */
+  void checkMutable() {
+    if (!isMutable) {
+      throw new UnsupportedOperationException(); 
+    }
+  }
+
+  /**
+   * Serializes the set and writes it to {@code output}.
+   *
+   * <p>For use by generated code only.
+   */
+  public void writeTo(CodedOutputStream output) throws IOException {
+    for (int i = 0; i < count; i++) {
+      int tag = tags[i];
+      int fieldNumber = WireFormat.getTagFieldNumber(tag);
+      switch (WireFormat.getTagWireType(tag)) {
+        case WireFormat.WIRETYPE_VARINT:
+          output.writeUInt64(fieldNumber, (Long) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_FIXED32:
+          output.writeFixed32(fieldNumber, (Integer) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_FIXED64:
+          output.writeFixed64(fieldNumber, (Long) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+          output.writeBytes(fieldNumber, (ByteString) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_START_GROUP:
+          output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+          ((UnknownFieldSetLite) objects[i]).writeTo(output);
+          output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+          break;
+        default:
+          throw InvalidProtocolBufferException.invalidWireType();
+      }
+    }
+  }
+
+  /**
+   * Get the number of bytes required to encode this set.
+   *
+   * <p>For use by generated code only.
+   */
+  public int getSerializedSize() {
+    int size = memoizedSerializedSize;
+    if (size != -1) {
+      return size;
+    }
+    
+    size = 0;
+    for (int i = 0; i < count; i++) {
+      int tag = tags[i];
+      int fieldNumber = WireFormat.getTagFieldNumber(tag);
+      switch (WireFormat.getTagWireType(tag)) {
+        case WireFormat.WIRETYPE_VARINT:
+          size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_FIXED32:
+          size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_FIXED64:
+          size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+          size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]);
+          break;
+        case WireFormat.WIRETYPE_START_GROUP:
+          size +=  CodedOutputStream.computeTagSize(fieldNumber) * 2
+              + ((UnknownFieldSetLite) objects[i]).getSerializedSize();
+          break;
+        default:
+          throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType());
+      }
+    }
+    
+    memoizedSerializedSize = size;
+    
+    return size;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (!(obj instanceof UnknownFieldSetLite)) {
+      return false;
+    }
+    
+    UnknownFieldSetLite other = (UnknownFieldSetLite) obj;    
+    if (count != other.count
+        // TODO(dweis): Only have to compare up to count but at worst 2x worse than we need to do.
+        || !Arrays.equals(tags, other.tags)
+        || !Arrays.deepEquals(objects, other.objects)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 17;
+    
+    hashCode = 31 * hashCode + count;
+    hashCode = 31 * hashCode + Arrays.hashCode(tags);
+    hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
+    
+    return hashCode;
+  }
+
+  /**
+   * Prints a String representation of the unknown field set.
+   *
+   * <p>For use by generated code only.
+   *
+   * @param buffer the buffer to write to
+   * @param indent the number of spaces the fields should be indented by
+   */
+  final void printWithIndent(StringBuilder buffer, int indent) {
+    for (int i = 0; i < count; i++) {
+      int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
+      MessageLiteToString.printField(buffer, indent, String.valueOf(fieldNumber), objects[i]);
+    }
+  }
+
+  private void storeField(int tag, Object value) {
+    ensureCapacity();
+    
+    tags[count] = tag;
+    objects[count] = value;
+    count++;
+  }
+  
+  /**
+   * Ensures that our arrays are long enough to store more metadata.
+   */
+  private void ensureCapacity() {
+    if (count == tags.length) {        
+      int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
+      int newLength = count + increment;
+        
+      tags = Arrays.copyOf(tags, newLength);
+      objects = Arrays.copyOf(objects, newLength);
+    }
+  }
+  
+  /**
+   * Parse a single field from {@code input} and merge it into this set.
+   *
+   * <p>For use by generated code only.
+   *
+   * @param tag The field's tag number, which was already parsed.
+   * @return {@code false} if the tag is an end group tag.
+   */
+  boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException {
+    checkMutable();
+    final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+    switch (WireFormat.getTagWireType(tag)) {
+      case WireFormat.WIRETYPE_VARINT:
+        storeField(tag, input.readInt64());
+        return true;
+      case WireFormat.WIRETYPE_FIXED32:
+        storeField(tag, input.readFixed32());
+        return true;
+      case WireFormat.WIRETYPE_FIXED64:
+        storeField(tag, input.readFixed64());
+        return true;
+      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+        storeField(tag, input.readBytes());
+        return true;
+      case WireFormat.WIRETYPE_START_GROUP:
+        final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite();
+        subFieldSet.mergeFrom(input);
+        input.checkLastTagWas(
+            WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+        storeField(tag, subFieldSet);
+        return true;
+      case WireFormat.WIRETYPE_END_GROUP:
+        return false;
+      default:
+        throw InvalidProtocolBufferException.invalidWireType();
+    }
+  }
+
+  /**
+   * Convenience method for merging a new field containing a single varint
+   * value. This is used in particular when an unknown enum value is
+   * encountered.
+   *
+   * <p>For use by generated code only.
+   */
+  UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) {
+    checkMutable();
+    if (fieldNumber == 0) {
+      throw new IllegalArgumentException("Zero is not a valid field number.");
+    }
+
+    storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
+    
+    return this;
+  }
+
+  /**
+   * Convenience method for merging a length-delimited field.
+   *
+   * <p>For use by generated code only.
+   */
+  UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) {  
+    checkMutable();
+    if (fieldNumber == 0) {
+      throw new IllegalArgumentException("Zero is not a valid field number.");
+    }
+
+    storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
+    
+    return this;
+  }
+  
+  /**
+   * Parse an entire message from {@code input} and merge its fields into
+   * this set.
+   */
+  private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException {
+    // Ensures initialization in mergeFieldFrom.
+    while (true) {
+      final int tag = input.readTag();
+      if (tag == 0 || !mergeFieldFrom(tag, input)) {
+        break;
+      }
+    }
+    return this;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
new file mode 100644
index 0000000..30e8791
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -0,0 +1,210 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps another
+ * {@link LazyStringList} such that it cannot be modified via the wrapper.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringList extends AbstractList<String>
+    implements LazyStringList, RandomAccess {
+
+  private final LazyStringList list;
+
+  public UnmodifiableLazyStringList(LazyStringList list) {
+    this.list = list;
+  }
+
+  @Override
+  public String get(int index) {
+    return list.get(index);
+  }
+  
+  @Override
+  public Object getRaw(int index) {
+    return list.getRaw(index);
+  }
+
+  @Override
+  public int size() {
+    return list.size();
+  }
+
+  @Override
+  public ByteString getByteString(int index) {
+    return list.getByteString(index);
+  }
+
+  @Override
+  public void add(ByteString element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void set(int index, ByteString element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean addAllByteString(Collection<? extends ByteString> element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public byte[] getByteArray(int index) {
+    return list.getByteArray(index);
+  }
+
+  @Override
+  public void add(byte[] element) {
+    throw new UnsupportedOperationException();
+  }
+  
+  @Override
+  public void set(int index, byte[] element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean addAllByteArray(Collection<byte[]> element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public ListIterator<String> listIterator(final int index) {
+    return new ListIterator<String>() {
+      ListIterator<String> iter = list.listIterator(index);
+
+      @Override
+      public boolean hasNext() {
+        return iter.hasNext();
+      }
+
+      @Override
+      public String next() {
+        return iter.next();
+      }
+
+      @Override
+      public boolean hasPrevious() {
+        return iter.hasPrevious();
+      }
+
+      @Override
+      public String previous() {
+        return iter.previous();
+      }
+
+      @Override
+      public int nextIndex() {
+        return iter.nextIndex();
+      }
+
+      @Override
+      public int previousIndex() {
+        return iter.previousIndex();
+      }
+
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void set(String o) {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void add(String o) {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+
+  @Override
+  public Iterator<String> iterator() {
+    return new Iterator<String>() {
+      Iterator<String> iter = list.iterator();
+
+      @Override
+      public boolean hasNext() {
+        return iter.hasNext();
+      }
+
+      @Override
+      public String next() {
+        return iter.next();
+      }
+
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+
+  @Override
+  public List<?> getUnderlyingElements() {
+    // The returned value is already unmodifiable.
+    return list.getUnderlyingElements();
+  }
+
+  @Override
+  public void mergeFrom(LazyStringList other) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public List<byte[]> asByteArrayList() {
+    return Collections.unmodifiableList(list.asByteArrayList());
+  }
+
+  @Override
+  public List<ByteString> asByteStringList() {
+    return Collections.unmodifiableList(list.asByteStringList());
+  }
+
+  @Override
+  public LazyStringList getUnmodifiableView() {
+    return this;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
new file mode 100644
index 0000000..0fbf4d4
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
@@ -0,0 +1,84 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Provides a number of unsafe byte operations to be used by advanced applications with high
+ * performance requirements. These methods are referred to as "unsafe" due to the fact that they
+ * potentially expose the backing buffer of a {@link ByteString} to the application.
+ *
+ * <p><strong>DISCLAIMER:</strong> The methods in this class should only be called if it is
+ * guaranteed that the buffer backing the {@link ByteString} will never change! Mutation of a
+ * {@link ByteString} can lead to unexpected and undesirable consequences in your application,
+ * and will likely be difficult to debug. Proceed with caution!
+ */
+@ExperimentalApi
+public final class UnsafeByteOperations {
+  private UnsafeByteOperations() {}
+
+  /**
+   * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer.
+   *
+   * @param buffer the Java NIO buffer to be wrapped
+   * @return a {@link ByteString} backed by the provided buffer
+   */
+  public static ByteString unsafeWrap(ByteBuffer buffer) {
+    if (buffer.hasArray()) {
+      final int offset = buffer.arrayOffset();
+      return ByteString.wrap(buffer.array(), offset + buffer.position(), buffer.remaining());
+    } else {
+      return new NioByteString(buffer);
+    }
+  }
+
+  /**
+   * Writes the given {@link ByteString} to the provided {@link ByteOutput}. Calling this method may
+   * result in multiple operations on the target {@link ByteOutput}
+   * (i.e. for roped {@link ByteString}s).
+   *
+   * <p>This method exposes the internal backing buffer(s) of the {@link ByteString} to the {@link
+   * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
+   * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
+   *
+   * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
+   * so may result in corrupted data, which would be difficult to debug.
+   *
+   * @param bytes the {@link ByteString} to be written
+   * @param  output  the output to receive the bytes
+   * @throws IOException  if an I/O error occurs
+   */
+  public static void unsafeWriteTo(ByteString bytes, ByteOutput output) throws IOException {
+    bytes.writeTo(output);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Utf8.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Utf8.java
new file mode 100644
index 0000000..308c69e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -0,0 +1,1683 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.lang.Character.MAX_SURROGATE;
+import static java.lang.Character.MIN_SURROGATE;
+import static java.lang.Character.isSurrogatePair;
+import static java.lang.Character.toCodePoint;
+
+import java.lang.reflect.Field;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A set of low-level, high-performance static utility methods related
+ * to the UTF-8 character encoding.  This class has no dependencies
+ * outside of the core JDK libraries.
+ *
+ * <p>There are several variants of UTF-8.  The one implemented by
+ * this class is the restricted definition of UTF-8 introduced in
+ * Unicode 3.1, which mandates the rejection of "overlong" byte
+ * sequences as well as rejection of 3-byte surrogate codepoint byte
+ * sequences.  Note that the UTF-8 decoder included in Oracle's JDK
+ * has been modified to also reject "overlong" byte sequences, but (as
+ * of 2011) still accepts 3-byte surrogate codepoint byte sequences.
+ *
+ * <p>The byte sequences considered valid by this class are exactly
+ * those that can be roundtrip converted to Strings and back to bytes
+ * using the UTF-8 charset, without loss: <pre> {@code
+ * Arrays.equals(bytes, new String(bytes, Internal.UTF_8).getBytes(Internal.UTF_8))
+ * }</pre>
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>This class supports decoding of partial byte sequences, so that the
+ * bytes in a complete UTF-8 byte sequences can be stored in multiple
+ * segments.  Methods typically return {@link #MALFORMED} if the partial
+ * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is
+ * well-formed in the absence of additional input, or if the byte sequence
+ * apparently terminated in the middle of a character, an opaque integer
+ * "state" value containing enough information to decode the character when
+ * passed to a subsequent invocation of a partial decoding method.
+ *
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+// TODO(nathanmittler): Copy changes in this class back to Guava
+final class Utf8 {
+  private static final Logger logger = Logger.getLogger(Utf8.class.getName());
+
+  /**
+   * UTF-8 is a runtime hot spot so we attempt to provide heavily optimized implementations
+   * depending on what is available on the platform. The processor is the platform-optimized
+   * delegate for which all methods are delegated directly to.
+   */
+  private static final Processor processor =
+      UnsafeProcessor.isAvailable() ? new UnsafeProcessor() : new SafeProcessor();
+
+  /**
+   * A mask used when performing unsafe reads to determine if a long value contains any non-ASCII
+   * characters (i.e. any byte >= 0x80).
+   */
+  private static final long ASCII_MASK_LONG = 0x8080808080808080L;
+
+  /**
+   * Maximum number of bytes per Java UTF-16 char in UTF-8.
+   * @see java.nio.charset.CharsetEncoder#maxBytesPerChar()
+   */
+  static final int MAX_BYTES_PER_CHAR = 3;
+
+  /**
+   * State value indicating that the byte sequence is well-formed and
+   * complete (no further bytes are needed to complete a character).
+   */
+  public static final int COMPLETE = 0;
+
+  /**
+   * State value indicating that the byte sequence is definitely not
+   * well-formed.
+   */
+  public static final int MALFORMED = -1;
+
+  /**
+   * Used by {@code Unsafe} UTF-8 string validation logic to determine the minimum string length
+   * above which to employ an optimized algorithm for counting ASCII characters. The reason for this
+   * threshold is that for small strings, the optimization may not be beneficial or may even
+   * negatively impact performance since it requires additional logic to avoid unaligned reads
+   * (when calling {@code Unsafe.getLong}). This threshold guarantees that even if the initial
+   * offset is unaligned, we're guaranteed to make at least one call to {@code Unsafe.getLong()}
+   * which provides a performance improvement that entirely subsumes the cost of the additional
+   * logic.
+   */
+  private static final int UNSAFE_COUNT_ASCII_THRESHOLD = 16;
+
+  // Other state values include the partial bytes of the incomplete
+  // character to be decoded in the simplest way: we pack the bytes
+  // into the state int in little-endian order.  For example:
+  //
+  // int state = byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+  //
+  // Such a state is unpacked thus (note the ~ operation for byte2 to
+  // undo byte1's sign-extension bits):
+  //
+  // int byte1 = (byte) state;
+  // int byte2 = (byte) ~(state >> 8);
+  // int byte3 = (byte) (state >> 16);
+  //
+  // We cannot store a zero byte in the state because it would be
+  // indistinguishable from the absence of a byte.  But we don't need
+  // to, because partial bytes must always be negative.  When building
+  // a state, we ensure that byte1 is negative and subsequent bytes
+  // are valid trailing bytes.
+
+  /**
+   * Returns {@code true} if the given byte array is a well-formed
+   * UTF-8 byte sequence.
+   *
+   * <p>This is a convenience method, equivalent to a call to {@code
+   * isValidUtf8(bytes, 0, bytes.length)}.
+   */
+  public static boolean isValidUtf8(byte[] bytes) {
+    return processor.isValidUtf8(bytes, 0, bytes.length);
+  }
+
+  /**
+   * Returns {@code true} if the given byte array slice is a
+   * well-formed UTF-8 byte sequence.  The range of bytes to be
+   * checked extends from index {@code index}, inclusive, to {@code
+   * limit}, exclusive.
+   *
+   * <p>This is a convenience method, equivalent to {@code
+   * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+   */
+  public static boolean isValidUtf8(byte[] bytes, int index, int limit) {
+    return processor.isValidUtf8(bytes, index, limit);
+  }
+
+  /**
+   * Tells whether the given byte array slice is a well-formed,
+   * malformed, or incomplete UTF-8 byte sequence.  The range of bytes
+   * to be checked extends from index {@code index}, inclusive, to
+   * {@code limit}, exclusive.
+   *
+   * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+   * operation) or the value returned from a call to a partial decoding method
+   * for the previous bytes
+   *
+   * @return {@link #MALFORMED} if the partial byte sequence is
+   * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+   * (no additional input needed), or if the byte sequence is
+   * "incomplete", i.e. apparently terminated in the middle of a character,
+   * an opaque integer "state" value containing enough information to
+   * decode the character when passed to a subsequent invocation of a
+   * partial decoding method.
+   */
+  public static int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) {
+    return processor.partialIsValidUtf8(state, bytes, index, limit);
+  }
+
+  private static int incompleteStateFor(int byte1) {
+    return (byte1 > (byte) 0xF4) ?
+        MALFORMED : byte1;
+  }
+
+  private static int incompleteStateFor(int byte1, int byte2) {
+    return (byte1 > (byte) 0xF4 ||
+            byte2 > (byte) 0xBF) ?
+        MALFORMED : byte1 ^ (byte2 << 8);
+  }
+
+  private static int incompleteStateFor(int byte1, int byte2, int byte3) {
+    return (byte1 > (byte) 0xF4 ||
+            byte2 > (byte) 0xBF ||
+            byte3 > (byte) 0xBF) ?
+        MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+  }
+
+  private static int incompleteStateFor(byte[] bytes, int index, int limit) {
+    int byte1 = bytes[index - 1];
+    switch (limit - index) {
+      case 0: return incompleteStateFor(byte1);
+      case 1: return incompleteStateFor(byte1, bytes[index]);
+      case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]);
+      default: throw new AssertionError();
+    }
+  }
+
+  private static int incompleteStateFor(
+      final ByteBuffer buffer, final int byte1, final int index, final int remaining) {
+    switch (remaining) {
+      case 0:
+        return incompleteStateFor(byte1);
+      case 1:
+        return incompleteStateFor(byte1, buffer.get(index));
+      case 2:
+        return incompleteStateFor(byte1, buffer.get(index), buffer.get(index + 1));
+      default:
+        throw new AssertionError();
+    }
+  }
+
+  // These UTF-8 handling methods are copied from Guava's Utf8 class with a modification to throw
+  // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
+  // fallback to more lenient behavior.
+  
+  static class UnpairedSurrogateException extends IllegalArgumentException {
+    private UnpairedSurrogateException(int index, int length) {
+      super("Unpaired surrogate at index " + index + " of " + length);
+    }
+  }
+
+  /**
+   * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+   * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+   * both time and space.
+   *
+   * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+   *     surrogates)
+   */
+  static int encodedLength(CharSequence sequence) {
+    // Warning to maintainers: this implementation is highly optimized.
+    int utf16Length = sequence.length();
+    int utf8Length = utf16Length;
+    int i = 0;
+
+    // This loop optimizes for pure ASCII.
+    while (i < utf16Length && sequence.charAt(i) < 0x80) {
+      i++;
+    }
+
+    // This loop optimizes for chars less than 0x800.
+    for (; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += ((0x7f - c) >>> 31);  // branch free!
+      } else {
+        utf8Length += encodedLengthGeneral(sequence, i);
+        break;
+      }
+    }
+
+    if (utf8Length < utf16Length) {
+      // Necessary and sufficient condition for overflow because of maximum 3x expansion
+      throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+              + (utf8Length + (1L << 32)));
+    }
+    return utf8Length;
+  }
+
+  private static int encodedLengthGeneral(CharSequence sequence, int start) {
+    int utf16Length = sequence.length();
+    int utf8Length = 0;
+    for (int i = start; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += (0x7f - c) >>> 31; // branch free!
+      } else {
+        utf8Length += 2;
+        // jdk7+: if (Character.isSurrogate(c)) {
+        if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+          // Check that we have a well-formed surrogate pair.
+          int cp = Character.codePointAt(sequence, i);
+          if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            throw new UnpairedSurrogateException(i, utf16Length);
+          }
+          i++;
+        }
+      }
+    }
+    return utf8Length;
+  }
+
+  static int encode(CharSequence in, byte[] out, int offset, int length) {
+    return processor.encodeUtf8(in, out, offset, length);
+  }
+  // End Guava UTF-8 methods.
+
+  /**
+   * Determines if the given {@link ByteBuffer} is a valid UTF-8 string.
+   *
+   * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+   * and the capabilities of the platform.
+   *
+   * @param buffer the buffer to check.
+   * @see Utf8#isValidUtf8(byte[], int, int)
+   */
+  static boolean isValidUtf8(ByteBuffer buffer) {
+    return processor.isValidUtf8(buffer, buffer.position(), buffer.remaining());
+  }
+
+  /**
+   * Determines if the given {@link ByteBuffer} is a partially valid UTF-8 string.
+   *
+   * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+   * and the capabilities of the platform.
+   *
+   * @param buffer the buffer to check.
+   * @see Utf8#partialIsValidUtf8(int, byte[], int, int)
+   */
+  static int partialIsValidUtf8(int state, ByteBuffer buffer, int index, int limit) {
+    return processor.partialIsValidUtf8(state, buffer, index, limit);
+  }
+
+  /**
+   * Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
+   *
+   * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+   * and the capabilities of the platform.
+   *
+   * @param in the source string to be encoded
+   * @param out the target buffer to receive the encoded string.
+   * @see Utf8#encode(CharSequence, byte[], int, int)
+   */
+  static void encodeUtf8(CharSequence in, ByteBuffer out) {
+    processor.encodeUtf8(in, out);
+  }
+
+  /**
+   * Counts (approximately) the number of consecutive ASCII characters in the given buffer.
+   * The byte order of the {@link ByteBuffer} does not matter, so performance can be improved if
+   * native byte order is used (i.e. no byte-swapping in {@link ByteBuffer#getLong(int)}).
+   *
+   * @param buffer the buffer to be scanned for ASCII chars
+   * @param index the starting index of the scan
+   * @param limit the limit within buffer for the scan
+   * @return the number of ASCII characters found. The stopping position will be at or
+   * before the first non-ASCII byte.
+   */
+  private static int estimateConsecutiveAscii(ByteBuffer buffer, int index, int limit) {
+    int i = index;
+    final int lim = limit - 7;
+    // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+    // To speed things up further, we're reading longs instead of bytes so we use a mask to
+    // determine if any byte in the current long is non-ASCII.
+    for (; i < lim && (buffer.getLong(i) & ASCII_MASK_LONG) == 0; i += 8) {}
+    return i - index;
+  }
+
+  /**
+   * A processor of UTF-8 strings, providing methods for checking validity and encoding.
+   */
+  // TODO(nathanmittler): Add support for Memory/MemoryBlock on Android.
+  abstract static class Processor {
+    /**
+     * Returns {@code true} if the given byte array slice is a
+     * well-formed UTF-8 byte sequence.  The range of bytes to be
+     * checked extends from index {@code index}, inclusive, to {@code
+     * limit}, exclusive.
+     *
+     * <p>This is a convenience method, equivalent to {@code
+     * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+     */
+    final boolean isValidUtf8(byte[] bytes, int index, int limit) {
+      return partialIsValidUtf8(COMPLETE, bytes, index, limit) == COMPLETE;
+    }
+
+    /**
+     * Tells whether the given byte array slice is a well-formed,
+     * malformed, or incomplete UTF-8 byte sequence.  The range of bytes
+     * to be checked extends from index {@code index}, inclusive, to
+     * {@code limit}, exclusive.
+     *
+     * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+     * operation) or the value returned from a call to a partial decoding method
+     * for the previous bytes
+     *
+     * @return {@link #MALFORMED} if the partial byte sequence is
+     * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+     * (no additional input needed), or if the byte sequence is
+     * "incomplete", i.e. apparently terminated in the middle of a character,
+     * an opaque integer "state" value containing enough information to
+     * decode the character when passed to a subsequent invocation of a
+     * partial decoding method.
+     */
+    abstract int partialIsValidUtf8(int state, byte[] bytes, int index, int limit);
+
+    /**
+     * Returns {@code true} if the given portion of the {@link ByteBuffer} is a
+     * well-formed UTF-8 byte sequence.  The range of bytes to be
+     * checked extends from index {@code index}, inclusive, to {@code
+     * limit}, exclusive.
+     *
+     * <p>This is a convenience method, equivalent to {@code
+     * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+     */
+    final boolean isValidUtf8(ByteBuffer buffer, int index, int limit) {
+      return partialIsValidUtf8(COMPLETE, buffer, index, limit) == COMPLETE;
+    }
+
+    /**
+     * Indicates whether or not the given buffer contains a valid UTF-8 string.
+     *
+     * @param buffer the buffer to check.
+     * @return {@code true} if the given buffer contains a valid UTF-8 string.
+     */
+    final int partialIsValidUtf8(
+        final int state, final ByteBuffer buffer, int index, final int limit) {
+      if (buffer.hasArray()) {
+        final int offset = buffer.arrayOffset();
+        return partialIsValidUtf8(state, buffer.array(), offset + index, offset + limit);
+      } else if (buffer.isDirect()){
+        return partialIsValidUtf8Direct(state, buffer, index, limit);
+      }
+      return partialIsValidUtf8Default(state, buffer, index, limit);
+    }
+
+    /**
+     * Performs validation for direct {@link ByteBuffer} instances.
+     */
+    abstract int partialIsValidUtf8Direct(
+        final int state, final ByteBuffer buffer, int index, final int limit);
+
+    /**
+     * Performs validation for {@link ByteBuffer} instances using the {@link ByteBuffer} API rather
+     * than potentially faster approaches. This first completes validation for the current
+     * character (provided by {@code state}) and then finishes validation for the sequence.
+     */
+    final int partialIsValidUtf8Default(
+        final int state, final ByteBuffer buffer, int index, final int limit) {
+      if (state != COMPLETE) {
+        // The previous decoding operation was incomplete (or malformed).
+        // We look for a well-formed sequence consisting of bytes from
+        // the previous decoding operation (stored in state) together
+        // with bytes from the array slice.
+        //
+        // We expect such "straddler characters" to be rare.
+
+        if (index >= limit) { // No bytes? No progress.
+          return state;
+        }
+
+        byte byte1 = (byte) state;
+        // byte1 is never ASCII.
+        if (byte1 < (byte) 0xE0) {
+          // two-byte form
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              // byte2 trailing-byte test
+              || buffer.get(index++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // three-byte form
+
+          // Get byte2 from saved state or array
+          byte byte2 = (byte) ~(state >> 8);
+          if (byte2 == 0) {
+            byte2 = buffer.get(index++);
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          }
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // illegal surrogate codepoint?
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || buffer.get(index++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // four-byte form
+
+          // Get byte2 and byte3 from saved state or array
+          byte byte2 = (byte) ~(state >> 8);
+          byte byte3 = 0;
+          if (byte2 == 0) {
+            byte2 = buffer.get(index++);
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          } else {
+            byte3 = (byte) (state >> 16);
+          }
+          if (byte3 == 0) {
+            byte3 = buffer.get(index++);
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2, byte3);
+            }
+          }
+
+          // If we were called with state == MALFORMED, then byte1 is 0xFF,
+          // which never occurs in well-formed UTF-8, and so we will return
+          // MALFORMED again below.
+
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || byte3 > (byte) 0xBF
+              // byte4 trailing-byte test
+              || buffer.get(index++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+
+      // Finish validation for the sequence.
+      return partialIsValidUtf8(buffer, index, limit);
+    }
+
+    /**
+     * Performs validation for {@link ByteBuffer} instances using the {@link ByteBuffer} API rather
+     * than potentially faster approaches.
+     */
+    private static int partialIsValidUtf8(final ByteBuffer buffer, int index, final int limit) {
+      index += estimateConsecutiveAscii(buffer, index, limit);
+
+      for (;;) {
+        // Optimize for interior runs of ASCII bytes.
+        // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+        // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+        int byte1;
+        do {
+          if (index >= limit) {
+            return COMPLETE;
+          }
+        } while ((byte1 = buffer.get(index++)) >= 0);
+
+        // If we're here byte1 is not ASCII. Only need to handle 2-4 byte forms.
+        if (byte1 < (byte) 0xE0) {
+          // Two-byte form (110xxxxx 10xxxxxx)
+          if (index >= limit) {
+            // Incomplete sequence
+            return byte1;
+          }
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2 || buffer.get(index) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+          index++;
+        } else if (byte1 < (byte) 0xF0) {
+          // Three-byte form (1110xxxx 10xxxxxx 10xxxxxx)
+          if (index >= limit - 1) {
+            // Incomplete sequence
+            return incompleteStateFor(buffer, byte1, index, limit - index);
+          }
+
+          final byte byte2 = buffer.get(index++);
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // check for illegal surrogate codepoints
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || buffer.get(index) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+          index++;
+        } else {
+          // Four-byte form (1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+          if (index >= limit - 2) {
+            // Incomplete sequence
+            return incompleteStateFor(buffer, byte1, index, limit - index);
+          }
+
+          // TODO(nathanmittler): Consider using getInt() to improve performance.
+          final int byte2 = buffer.get(index++);
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || buffer.get(index++) > (byte) 0xBF
+              // byte4 trailing-byte test
+              || buffer.get(index++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+    }
+
+    /**
+     * Encodes an input character sequence ({@code in}) to UTF-8 in the target array ({@code out}).
+     * For a string, this method is similar to
+     * <pre>{@code
+     * byte[] a = string.getBytes(UTF_8);
+     * System.arraycopy(a, 0, bytes, offset, a.length);
+     * return offset + a.length;
+     * }</pre>
+     *
+     * but is more efficient in both time and space. One key difference is that this method
+     * requires paired surrogates, and therefore does not support chunking.
+     * While {@code String.getBytes(UTF_8)} replaces unpaired surrogates with the default
+     * replacement character, this method throws {@link UnpairedSurrogateException}.
+     *
+     * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+     * compute the exact amount needed, or leave room for 
+     * {@code Utf8.MAX_BYTES_PER_CHAR * sequence.length()}, which is the largest possible number
+     * of bytes that any input can be encoded to.
+     *
+     * @param in the input character sequence to be encoded
+     * @param out the target array
+     * @param offset the starting offset in {@code bytes} to start writing at
+     * @param length the length of the {@code bytes}, starting from {@code offset}
+     * @throws UnpairedSurrogateException if {@code sequence} contains ill-formed UTF-16 (unpaired
+     *     surrogates)
+     * @throws ArrayIndexOutOfBoundsException if {@code sequence} encoded in UTF-8 is longer than
+     *     {@code bytes.length - offset}
+     * @return the new offset, equivalent to {@code offset + Utf8.encodedLength(sequence)}
+     */
+    abstract int encodeUtf8(CharSequence in, byte[] out, int offset, int length);
+
+    /**
+     * Encodes an input character sequence ({@code in}) to UTF-8 in the target buffer ({@code out}).
+     * Upon returning from this method, the {@code out} position will point to the position after
+     * the last encoded byte. This method requires paired surrogates, and therefore does not
+     * support chunking.
+     *
+     * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+     * compute the exact amount needed, or leave room for
+     * {@code Utf8.MAX_BYTES_PER_CHAR * in.length()}, which is the largest possible number
+     * of bytes that any input can be encoded to.
+     *
+     * @param in the source character sequence to be encoded
+     * @param out the target buffer
+     * @throws UnpairedSurrogateException if {@code in} contains ill-formed UTF-16 (unpaired
+     *     surrogates)
+     * @throws ArrayIndexOutOfBoundsException if {@code in} encoded in UTF-8 is longer than
+     *     {@code out.remaining()}
+     */
+    final void encodeUtf8(CharSequence in, ByteBuffer out) {
+      if (out.hasArray()) {
+        final int offset = out.arrayOffset();
+        int endIndex =
+            Utf8.encode(in, out.array(), offset + out.position(), out.remaining());
+        out.position(endIndex - offset);
+      } else if (out.isDirect()) {
+        encodeUtf8Direct(in, out);
+      } else {
+        encodeUtf8Default(in, out);
+      }
+    }
+
+    /**
+     * Encodes the input character sequence to a direct {@link ByteBuffer} instance.
+     */
+    abstract void encodeUtf8Direct(CharSequence in, ByteBuffer out);
+
+    /**
+     * Encodes the input character sequence to a {@link ByteBuffer} instance using the {@link
+     * ByteBuffer} API, rather than potentially faster approaches.
+     */
+    final void encodeUtf8Default(CharSequence in, ByteBuffer out) {
+      final int inLength = in.length();
+      int outIx = out.position();
+      int inIx = 0;
+
+      // Since ByteBuffer.putXXX() already checks boundaries for us, no need to explicitly check
+      // access. Assume the buffer is big enough and let it handle the out of bounds exception
+      // if it occurs.
+      try {
+        // Designed to take advantage of
+        // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+        for (char c; inIx < inLength && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+          out.put(outIx + inIx, (byte) c);
+        }
+        if (inIx == inLength) {
+          // Successfully encoded the entire string.
+          out.position(outIx + inIx);
+          return;
+        }
+
+        outIx += inIx;
+        for (char c; inIx < inLength; ++inIx, ++outIx) {
+          c = in.charAt(inIx);
+          if (c < 0x80) {
+            // One byte (0xxx xxxx)
+            out.put(outIx, (byte) c);
+          } else if (c < 0x800) {
+            // Two bytes (110x xxxx 10xx xxxx)
+
+            // Benchmarks show put performs better than putShort here (for HotSpot).
+            out.put(outIx++, (byte) (0xC0 | (c >>> 6)));
+            out.put(outIx, (byte) (0x80 | (0x3F & c)));
+          } else if (c < MIN_SURROGATE || MAX_SURROGATE < c) {
+            // Three bytes (1110 xxxx 10xx xxxx 10xx xxxx)
+            // Maximum single-char code point is 0xFFFF, 16 bits.
+
+            // Benchmarks show put performs better than putShort here (for HotSpot).
+            out.put(outIx++, (byte) (0xE0 | (c >>> 12)));
+            out.put(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+            out.put(outIx, (byte) (0x80 | (0x3F & c)));
+          } else {
+            // Four bytes (1111 xxxx 10xx xxxx 10xx xxxx 10xx xxxx)
+
+            // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+            // bytes
+            final char low;
+            if (inIx + 1 == inLength || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+              throw new UnpairedSurrogateException(inIx, inLength);
+            }
+            // TODO(nathanmittler): Consider using putInt() to improve performance.
+            int codePoint = toCodePoint(c, low);
+            out.put(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+            out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+            out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+            out.put(outIx, (byte) (0x80 | (0x3F & codePoint)));
+          }
+        }
+
+        // Successfully encoded the entire string.
+        out.position(outIx);
+      } catch (IndexOutOfBoundsException e) {
+        // TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead.
+
+        // If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
+        // use inIx to determine the bad write index.
+        int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
+        throw new ArrayIndexOutOfBoundsException(
+            "Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
+      }
+    }
+  }
+
+  /**
+   * {@link Processor} implementation that does not use any {@code sun.misc.Unsafe} methods.
+   */
+  static final class SafeProcessor extends Processor {
+    @Override
+    int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) {
+      if (state != COMPLETE) {
+        // The previous decoding operation was incomplete (or malformed).
+        // We look for a well-formed sequence consisting of bytes from
+        // the previous decoding operation (stored in state) together
+        // with bytes from the array slice.
+        //
+        // We expect such "straddler characters" to be rare.
+
+        if (index >= limit) {  // No bytes? No progress.
+          return state;
+        }
+        int byte1 = (byte) state;
+        // byte1 is never ASCII.
+        if (byte1 < (byte) 0xE0) {
+          // two-byte form
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              // byte2 trailing-byte test
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // three-byte form
+
+          // Get byte2 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          if (byte2 == 0) {
+            byte2 = bytes[index++];
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          }
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // illegal surrogate codepoint?
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // four-byte form
+
+          // Get byte2 and byte3 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          int byte3 = 0;
+          if (byte2 == 0) {
+            byte2 = bytes[index++];
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          } else {
+            byte3 = (byte) (state >> 16);
+          }
+          if (byte3 == 0) {
+            byte3 = bytes[index++];
+            if (index >= limit) {
+              return incompleteStateFor(byte1, byte2, byte3);
+            }
+          }
+
+          // If we were called with state == MALFORMED, then byte1 is 0xFF,
+          // which never occurs in well-formed UTF-8, and so we will return
+          // MALFORMED again below.
+
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || byte3 > (byte) 0xBF
+              // byte4 trailing-byte test
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+
+      return partialIsValidUtf8(bytes, index, limit);
+    }
+
+    @Override
+    int partialIsValidUtf8Direct(int state, ByteBuffer buffer, int index, int limit) {
+      // For safe processing, we have to use the ByteBuffer API.
+      return partialIsValidUtf8Default(state, buffer, index, limit);
+    }
+
+    @Override
+    int encodeUtf8(CharSequence in, byte[] out, int offset, int length) {
+      int utf16Length = in.length();
+      int j = offset;
+      int i = 0;
+      int limit = offset + length;
+      // Designed to take advantage of
+      // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+      for (char c; i < utf16Length && i + j < limit && (c = in.charAt(i)) < 0x80; i++) {
+        out[j + i] = (byte) c;
+      }
+      if (i == utf16Length) {
+        return j + utf16Length;
+      }
+      j += i;
+      for (char c; i < utf16Length; i++) {
+        c = in.charAt(i);
+        if (c < 0x80 && j < limit) {
+          out[j++] = (byte) c;
+        } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+          out[j++] = (byte) ((0xF << 6) | (c >>> 6));
+          out[j++] = (byte) (0x80 | (0x3F & c));
+        } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+          // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+          out[j++] = (byte) ((0xF << 5) | (c >>> 12));
+          out[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+          out[j++] = (byte) (0x80 | (0x3F & c));
+        } else if (j <= limit - 4) {
+          // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+          // four UTF-8 bytes
+          final char low;
+          if (i + 1 == in.length()
+                  || !Character.isSurrogatePair(c, (low = in.charAt(++i)))) {
+            throw new UnpairedSurrogateException((i - 1), utf16Length);
+          }
+          int codePoint = Character.toCodePoint(c, low);
+          out[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+          out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+          out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+          out[j++] = (byte) (0x80 | (0x3F & codePoint));
+        } else {
+          // If we are surrogates and we're not a surrogate pair, always throw an
+          // UnpairedSurrogateException instead of an ArrayOutOfBoundsException.
+          if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
+              && (i + 1 == in.length()
+                  || !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
+            throw new UnpairedSurrogateException(i, utf16Length);
+          }
+          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+        }
+      }
+      return j;
+    }
+
+    @Override
+    void encodeUtf8Direct(CharSequence in, ByteBuffer out) {
+      // For safe processing, we have to use the ByteBuffer API.
+      encodeUtf8Default(in, out);
+    }
+
+    private static int partialIsValidUtf8(byte[] bytes, int index, int limit) {
+      // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
+      // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+      while (index < limit && bytes[index] >= 0) {
+        index++;
+      }
+
+      return (index >= limit) ? COMPLETE : partialIsValidUtf8NonAscii(bytes, index, limit);
+    }
+
+    private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit) {
+      for (;;) {
+        int byte1, byte2;
+
+        // Optimize for interior runs of ASCII bytes.
+        do {
+          if (index >= limit) {
+            return COMPLETE;
+          }
+        } while ((byte1 = bytes[index++]) >= 0);
+
+        if (byte1 < (byte) 0xE0) {
+          // two-byte form
+
+          if (index >= limit) {
+            // Incomplete sequence
+            return byte1;
+          }
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // three-byte form
+
+          if (index >= limit - 1) { // incomplete sequence
+            return incompleteStateFor(bytes, index, limit);
+          }
+          if ((byte2 = bytes[index++]) > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // check for illegal surrogate codepoints
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // four-byte form
+
+          if (index >= limit - 2) {  // incomplete sequence
+            return incompleteStateFor(bytes, index, limit);
+          }
+          if ((byte2 = bytes[index++]) > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || bytes[index++] > (byte) 0xBF
+              // byte4 trailing-byte test
+              || bytes[index++] > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * {@link Processor} that uses {@code sun.misc.Unsafe} where possible to improve performance.
+   */
+  static final class UnsafeProcessor extends Processor {
+    private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+    private static final long BUFFER_ADDRESS_OFFSET =
+        fieldOffset(field(Buffer.class, "address"));
+    private static final int ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+
+    /**
+     * We only use Unsafe operations if we have access to direct {@link ByteBuffer}'s address
+     * and the array base offset is a multiple of 8 (needed by Unsafe.getLong()).
+     */
+    private static final boolean AVAILABLE =
+        BUFFER_ADDRESS_OFFSET != -1 && ARRAY_BASE_OFFSET % 8 == 0;
+
+    /**
+     * Indicates whether or not all required unsafe operations are supported on this platform.
+     */
+    static boolean isAvailable() {
+      return AVAILABLE;
+    }
+
+    @Override
+    int partialIsValidUtf8(int state, byte[] bytes, final int index, final int limit) {
+      if ((index | limit | bytes.length - limit) < 0) {
+        throw new ArrayIndexOutOfBoundsException(
+            String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
+      }
+      long offset = ARRAY_BASE_OFFSET + index;
+      final long offsetLimit = ARRAY_BASE_OFFSET + limit;
+      if (state != COMPLETE) {
+        // The previous decoding operation was incomplete (or malformed).
+        // We look for a well-formed sequence consisting of bytes from
+        // the previous decoding operation (stored in state) together
+        // with bytes from the array slice.
+        //
+        // We expect such "straddler characters" to be rare.
+
+        if (offset >= offsetLimit) {  // No bytes? No progress.
+          return state;
+        }
+        int byte1 = (byte) state;
+        // byte1 is never ASCII.
+        if (byte1 < (byte) 0xE0) {
+          // two-byte form
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              // byte2 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // three-byte form
+
+          // Get byte2 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          if (byte2 == 0) {
+            byte2 = UNSAFE.getByte(bytes, offset++);
+            if (offset >= offsetLimit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          }
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // illegal surrogate codepoint?
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // four-byte form
+
+          // Get byte2 and byte3 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          int byte3 = 0;
+          if (byte2 == 0) {
+            byte2 = UNSAFE.getByte(bytes, offset++);
+            if (offset >= offsetLimit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          } else {
+            byte3 = (byte) (state >> 16);
+          }
+          if (byte3 == 0) {
+            byte3 = UNSAFE.getByte(bytes, offset++);
+            if (offset >= offsetLimit) {
+              return incompleteStateFor(byte1, byte2, byte3);
+            }
+          }
+
+          // If we were called with state == MALFORMED, then byte1 is 0xFF,
+          // which never occurs in well-formed UTF-8, and so we will return
+          // MALFORMED again below.
+
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || byte3 > (byte) 0xBF
+              // byte4 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+
+      return partialIsValidUtf8(bytes, offset, (int) (offsetLimit - offset));
+    }
+
+    @Override
+    int partialIsValidUtf8Direct(
+        final int state, ByteBuffer buffer, final int index, final int limit) {
+      if ((index | limit | buffer.limit() - limit) < 0) {
+        throw new ArrayIndexOutOfBoundsException(
+            String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(), index, limit));
+      }
+      long address = addressOffset(buffer) + index;
+      final long addressLimit = address + (limit - index);
+      if (state != COMPLETE) {
+        // The previous decoding operation was incomplete (or malformed).
+        // We look for a well-formed sequence consisting of bytes from
+        // the previous decoding operation (stored in state) together
+        // with bytes from the array slice.
+        //
+        // We expect such "straddler characters" to be rare.
+
+        if (address >= addressLimit) { // No bytes? No progress.
+          return state;
+        }
+
+        final int byte1 = (byte) state;
+        // byte1 is never ASCII.
+        if (byte1 < (byte) 0xE0) {
+          // two-byte form
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              // byte2 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // three-byte form
+
+          // Get byte2 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          if (byte2 == 0) {
+            byte2 = UNSAFE.getByte(address++);
+            if (address >= addressLimit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          }
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // illegal surrogate codepoint?
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // four-byte form
+
+          // Get byte2 and byte3 from saved state or array
+          int byte2 = (byte) ~(state >> 8);
+          int byte3 = 0;
+          if (byte2 == 0) {
+            byte2 = UNSAFE.getByte(address++);
+            if (address >= addressLimit) {
+              return incompleteStateFor(byte1, byte2);
+            }
+          } else {
+            byte3 = (byte) (state >> 16);
+          }
+          if (byte3 == 0) {
+            byte3 = UNSAFE.getByte(address++);
+            if (address >= addressLimit) {
+              return incompleteStateFor(byte1, byte2, byte3);
+            }
+          }
+
+          // If we were called with state == MALFORMED, then byte1 is 0xFF,
+          // which never occurs in well-formed UTF-8, and so we will return
+          // MALFORMED again below.
+
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || byte3 > (byte) 0xBF
+              // byte4 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+
+      return partialIsValidUtf8(address, (int) (addressLimit - address));
+    }
+
+    @Override
+    int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
+      long outIx = ARRAY_BASE_OFFSET + offset;
+      final long outLimit = outIx + length;
+      final int inLimit = in.length();
+      if (inLimit > length || out.length - length < offset) {
+        // Not even enough room for an ASCII-encoded string.
+        throw new ArrayIndexOutOfBoundsException(
+            "Failed writing " + in.charAt(inLimit - 1) + " at index " + (offset + length));
+      }
+
+      // Designed to take advantage of
+      // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+      int inIx = 0;
+      for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+        UNSAFE.putByte(out, outIx++, (byte) c);
+      }
+      if (inIx == inLimit) {
+        // We're done, it was ASCII encoded.
+        return (int) (outIx - ARRAY_BASE_OFFSET);
+      }
+
+      for (char c; inIx < inLimit; ++inIx) {
+        c = in.charAt(inIx);
+        if (c < 0x80 && outIx < outLimit) {
+          UNSAFE.putByte(out, outIx++, (byte) c);
+        } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
+          UNSAFE.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+        } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
+          // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+          UNSAFE.putByte(out, outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+        } else if (outIx <= outLimit - 4L) {
+          // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+          // bytes
+          final char low;
+          if (inIx + 1 == inLimit || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+            throw new UnpairedSurrogateException((inIx - 1), inLimit);
+          }
+          int codePoint = toCodePoint(c, low);
+          UNSAFE.putByte(out, outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+          UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & codePoint)));
+        } else {
+          if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
+              && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
+            // We are surrogates and we're not a surrogate pair.
+            throw new UnpairedSurrogateException(inIx, inLimit);
+          }
+          // Not enough space in the output buffer.
+          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+        }
+      }
+
+      // All bytes have been encoded.
+      return (int) (outIx - ARRAY_BASE_OFFSET);
+    }
+
+    @Override
+    void encodeUtf8Direct(CharSequence in, ByteBuffer out) {
+      final long address = addressOffset(out);
+      long outIx = address + out.position();
+      final long outLimit = address + out.limit();
+      final int inLimit = in.length();
+      if (inLimit > outLimit - outIx) {
+        // Not even enough room for an ASCII-encoded string.
+        throw new ArrayIndexOutOfBoundsException(
+            "Failed writing " + in.charAt(inLimit - 1) + " at index " + out.limit());
+      }
+
+      // Designed to take advantage of
+      // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+      int inIx = 0;
+      for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+        UNSAFE.putByte(outIx++, (byte) c);
+      }
+      if (inIx == inLimit) {
+        // We're done, it was ASCII encoded.
+        out.position((int) (outIx - address));
+        return;
+      }
+
+      for (char c; inIx < inLimit; ++inIx) {
+        c = in.charAt(inIx);
+        if (c < 0x80 && outIx < outLimit) {
+          UNSAFE.putByte(outIx++, (byte) c);
+        } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
+          UNSAFE.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+        } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
+          // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+          UNSAFE.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+        } else if (outIx <= outLimit - 4L) {
+          // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+          // bytes
+          final char low;
+          if (inIx + 1 == inLimit || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+            throw new UnpairedSurrogateException((inIx - 1), inLimit);
+          }
+          int codePoint = toCodePoint(c, low);
+          UNSAFE.putByte(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+          UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & codePoint)));
+        } else {
+          if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
+              && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
+            // We are surrogates and we're not a surrogate pair.
+            throw new UnpairedSurrogateException(inIx, inLimit);
+          }
+          // Not enough space in the output buffer.
+          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+        }
+      }
+
+      // All bytes have been encoded.
+      out.position((int) (outIx - address));
+    }
+
+    /**
+     * Counts (approximately) the number of consecutive ASCII characters starting from the given
+     * position, using the most efficient method available to the platform.
+     *
+     * @param bytes the array containing the character sequence
+     * @param offset the offset position of the index (same as index + arrayBaseOffset)
+     * @param maxChars the maximum number of characters to count
+     * @return the number of ASCII characters found. The stopping position will be at or
+     * before the first non-ASCII byte.
+     */
+    private static int unsafeEstimateConsecutiveAscii(
+        byte[] bytes, long offset, final int maxChars) {
+      int remaining = maxChars;
+      if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
+        // Don't bother with small strings.
+        return 0;
+      }
+
+      // Read bytes until 8-byte aligned so that we can read longs in the loop below.
+      // Byte arrays are already either 8 or 16-byte aligned, so we just need to make sure that
+      // the index (relative to the start of the array) is also 8-byte aligned. We do this by
+      // ANDing the index with 7 to determine the number of bytes that need to be read before
+      // we're 8-byte aligned.
+      final int unaligned = (int) offset & 7;
+      for (int j = unaligned; j > 0; j--) {
+        if (UNSAFE.getByte(bytes, offset++) < 0) {
+          return unaligned - j;
+        }
+      }
+
+      // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+      // To speed things up further, we're reading longs instead of bytes so we use a mask to
+      // determine if any byte in the current long is non-ASCII.
+      remaining -= unaligned;
+      for (; remaining >= 8 && (UNSAFE.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
+          offset += 8, remaining -= 8) {}
+      return maxChars - remaining;
+    }
+
+    /**
+     * Same as {@link Utf8#estimateConsecutiveAscii(ByteBuffer, int, int)} except that it uses the
+     * most efficient method available to the platform.
+     */
+    private static int unsafeEstimateConsecutiveAscii(long address, final int maxChars) {
+      int remaining = maxChars;
+      if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
+        // Don't bother with small strings.
+        return 0;
+      }
+
+      // Read bytes until 8-byte aligned so that we can read longs in the loop below.
+      // We do this by ANDing the address with 7 to determine the number of bytes that need to
+      // be read before we're 8-byte aligned.
+      final int unaligned = (int) address & 7;
+      for (int j = unaligned; j > 0; j--) {
+        if (UNSAFE.getByte(address++) < 0) {
+          return unaligned - j;
+        }
+      }
+
+      // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+      // To speed things up further, we're reading longs instead of bytes so we use a mask to
+      // determine if any byte in the current long is non-ASCII.
+      remaining -= unaligned;
+      for (; remaining >= 8 && (UNSAFE.getLong(address) & ASCII_MASK_LONG) == 0;
+          address += 8, remaining -= 8) {}
+      return maxChars - remaining;
+    }
+
+    private static int partialIsValidUtf8(final byte[] bytes, long offset, int remaining) {
+      // Skip past ASCII characters as quickly as possible. 
+      final int skipped = unsafeEstimateConsecutiveAscii(bytes, offset, remaining);
+      remaining -= skipped;
+      offset += skipped;
+
+      for (;;) {
+        // Optimize for interior runs of ASCII bytes.
+        // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+        // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+        int byte1 = 0;
+        for (; remaining > 0 && (byte1 = UNSAFE.getByte(bytes, offset++)) >= 0; --remaining) {
+        }
+        if (remaining == 0) {
+          return COMPLETE;
+        }
+        remaining--;
+
+        // If we're here byte1 is not ASCII. Only need to handle 2-4 byte forms.
+        if (byte1 < (byte) 0xE0) {
+          // Two-byte form (110xxxxx 10xxxxxx)
+          if (remaining == 0) {
+            // Incomplete sequence
+            return byte1;
+          }
+          remaining--;
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // Three-byte form (1110xxxx 10xxxxxx 10xxxxxx)
+          if (remaining < 2) {
+            // Incomplete sequence
+            return unsafeIncompleteStateFor(bytes, byte1, offset, remaining);
+          }
+          remaining -= 2;
+
+          final int byte2;
+          if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // check for illegal surrogate codepoints
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // Four-byte form (1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+          if (remaining < 3) {
+            // Incomplete sequence
+            return unsafeIncompleteStateFor(bytes, byte1, offset, remaining);
+          }
+          remaining -= 3;
+
+          final int byte2;
+          if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF
+              // byte4 trailing-byte test
+              || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+    }
+
+    private static int partialIsValidUtf8(long address, int remaining) {
+      // Skip past ASCII characters as quickly as possible.
+      final int skipped = unsafeEstimateConsecutiveAscii(address, remaining);
+      address += skipped;
+      remaining -= skipped;
+
+      for (;;) {
+        // Optimize for interior runs of ASCII bytes.
+        // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+        // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+        int byte1 = 0;
+        for (; remaining > 0 && (byte1 = UNSAFE.getByte(address++)) >= 0; --remaining) {
+        }
+        if (remaining == 0) {
+          return COMPLETE;
+        }
+        remaining--;
+
+        if (byte1 < (byte) 0xE0) {
+          // Two-byte form
+
+          if (remaining == 0) {
+            // Incomplete sequence
+            return byte1;
+          }
+          remaining--;
+
+          // Simultaneously checks for illegal trailing-byte in
+          // leading position and overlong 2-byte form.
+          if (byte1 < (byte) 0xC2 || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else if (byte1 < (byte) 0xF0) {
+          // Three-byte form
+
+          if (remaining < 2) {
+            // Incomplete sequence
+            return unsafeIncompleteStateFor(address, byte1, remaining);
+          }
+          remaining -= 2;
+
+          final byte byte2 = UNSAFE.getByte(address++);
+          if (byte2 > (byte) 0xBF
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // check for illegal surrogate codepoints
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        } else {
+          // Four-byte form
+
+          if (remaining < 3) {
+            // Incomplete sequence
+            return unsafeIncompleteStateFor(address, byte1, remaining);
+          }
+          remaining -= 3;
+
+          final byte byte2 = UNSAFE.getByte(address++);
+          if (byte2 > (byte) 0xBF
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              // if (byte1 > (byte) 0xF4 ||
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              // byte3 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF
+              // byte4 trailing-byte test
+              || UNSAFE.getByte(address++) > (byte) 0xBF) {
+            return MALFORMED;
+          }
+        }
+      }
+    }
+
+    private static int unsafeIncompleteStateFor(byte[] bytes, int byte1, long offset,
+        int remaining) {
+      switch (remaining) {
+        case 0: {
+          return incompleteStateFor(byte1);
+        }
+        case 1: {
+          return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset));
+        }
+        case 2: {
+          return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset),
+              UNSAFE.getByte(bytes, offset + 1));
+        }
+        default: {
+          throw new AssertionError();
+        }
+      }
+    }
+
+    private static int unsafeIncompleteStateFor(long address, final int byte1, int remaining) {
+      switch (remaining) {
+        case 0: {
+          return incompleteStateFor(byte1);
+        }
+        case 1: {
+          return incompleteStateFor(byte1, UNSAFE.getByte(address));
+        }
+        case 2: {
+          return incompleteStateFor(byte1, UNSAFE.getByte(address), UNSAFE.getByte(address + 1));
+        }
+        default: {
+          throw new AssertionError();
+        }
+      }
+    }
+
+    /**
+     * Gets the field with the given name within the class, or {@code null} if not found. If
+     * found, the field is made accessible.
+     */
+    private static Field field(Class<?> clazz, String fieldName) {
+      Field field;
+      try {
+        field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+      } catch (Throwable t) {
+        // Failed to access the fields.
+        field = null;
+      }
+      logger.log(Level.FINEST, "{0}.{1}: {2}",
+          new Object[] {clazz.getName(), fieldName, (field != null ? "available" : "unavailable")});
+      return field;
+    }
+
+    /**
+     * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
+     * available.
+     */
+    private static long fieldOffset(Field field) {
+      return field == null || UNSAFE == null ? -1 : UNSAFE.objectFieldOffset(field);
+    }
+
+    /**
+     * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
+     * available.
+     */
+    private static <T> int byteArrayBaseOffset() {
+      return UNSAFE == null ? -1 : UNSAFE.arrayBaseOffset(byte[].class);
+    }
+
+    /**
+     * Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}.
+     */
+    private static long addressOffset(ByteBuffer buffer) {
+      return UNSAFE.getLong(buffer, BUFFER_ADDRESS_OFFSET);
+    }
+
+    /**
+     * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
+     * platform.
+     */
+    private static sun.misc.Unsafe getUnsafe() {
+      sun.misc.Unsafe unsafe = null;
+      try {
+        unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+          @Override
+          public sun.misc.Unsafe run() throws Exception {
+            Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+            // Check that this platform supports all of the required unsafe methods.
+            checkRequiredMethods(k);
+
+            for (Field f : k.getDeclaredFields()) {
+              f.setAccessible(true);
+              Object x = f.get(null);
+              if (k.isInstance(x)) {
+                return k.cast(x);
+              }
+            }
+            // The sun.misc.Unsafe field does not exist.
+            return null;
+          }
+        });
+      } catch (Throwable e) {
+        // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
+        // for Unsafe.
+      }
+
+      logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
+          unsafe != null ? "available" : "unavailable");
+      return unsafe;
+    }
+
+    /**
+     * Verifies that all required methods of {@code sun.misc.Unsafe} are available on this platform.
+     */
+    private static void checkRequiredMethods(Class<sun.misc.Unsafe> clazz)
+        throws NoSuchMethodException, SecurityException {
+      // Needed for Unsafe byte[] access
+      clazz.getMethod("arrayBaseOffset", Class.class);
+      clazz.getMethod("getByte", Object.class, long.class);
+      clazz.getMethod("putByte", Object.class, long.class, byte.class);
+      clazz.getMethod("getLong", Object.class, long.class);
+
+      // Needed for Unsafe Direct ByteBuffer access
+      clazz.getMethod("objectFieldOffset", Field.class);
+      clazz.getMethod("getByte", long.class);
+      clazz.getMethod("getLong", Object.class, long.class);
+      clazz.getMethod("putByte", long.class, byte.class);
+      clazz.getMethod("getLong", long.class);
+    }
+  }
+
+  private Utf8() {}
+}
diff --git a/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/WireFormat.java b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/WireFormat.java
new file mode 100644
index 0000000..6a58b08
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/main/java/com/google/protobuf/WireFormat.java
@@ -0,0 +1,256 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * This class is used internally by the Protocol Buffer library and generated
+ * message implementations.  It is public only because those generated messages
+ * do not reside in the {@code protobuf} package.  Others should not use this
+ * class directly.
+ *
+ * This class contains constants and helper functions useful for dealing with
+ * the Protocol Buffer wire format.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class WireFormat {
+  // Do not allow instantiation.
+  private WireFormat() {}
+
+  public static final int WIRETYPE_VARINT           = 0;
+  public static final int WIRETYPE_FIXED64          = 1;
+  public static final int WIRETYPE_LENGTH_DELIMITED = 2;
+  public static final int WIRETYPE_START_GROUP      = 3;
+  public static final int WIRETYPE_END_GROUP        = 4;
+  public static final int WIRETYPE_FIXED32          = 5;
+
+  static final int TAG_TYPE_BITS = 3;
+  static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
+
+  /** Given a tag value, determines the wire type (the lower 3 bits). */
+  public static int getTagWireType(final int tag) {
+    return tag & TAG_TYPE_MASK;
+  }
+
+  /** Given a tag value, determines the field number (the upper 29 bits). */
+  public static int getTagFieldNumber(final int tag) {
+    return tag >>> TAG_TYPE_BITS;
+  }
+
+  /** Makes a tag value given a field number and wire type. */
+  static int makeTag(final int fieldNumber, final int wireType) {
+    return (fieldNumber << TAG_TYPE_BITS) | wireType;
+  }
+
+  /**
+   * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}.  This is
+   * only here to support the lite runtime and should not be used by users.
+   */
+  public enum JavaType {
+    INT(0),
+    LONG(0L),
+    FLOAT(0F),
+    DOUBLE(0D),
+    BOOLEAN(false),
+    STRING(""),
+    BYTE_STRING(ByteString.EMPTY),
+    ENUM(null),
+    MESSAGE(null);
+
+    JavaType(final Object defaultDefault) {
+      this.defaultDefault = defaultDefault;
+    }
+
+    /**
+     * The default default value for fields of this type, if it's a primitive
+     * type.
+     */
+    Object getDefaultDefault() {
+      return defaultDefault;
+    }
+
+    private final Object defaultDefault;
+  }
+
+  /**
+   * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}.  This is
+   * only here to support the lite runtime and should not be used by users.
+   */
+  public enum FieldType {
+    DOUBLE  (JavaType.DOUBLE     , WIRETYPE_FIXED64         ),
+    FLOAT   (JavaType.FLOAT      , WIRETYPE_FIXED32         ),
+    INT64   (JavaType.LONG       , WIRETYPE_VARINT          ),
+    UINT64  (JavaType.LONG       , WIRETYPE_VARINT          ),
+    INT32   (JavaType.INT        , WIRETYPE_VARINT          ),
+    FIXED64 (JavaType.LONG       , WIRETYPE_FIXED64         ),
+    FIXED32 (JavaType.INT        , WIRETYPE_FIXED32         ),
+    BOOL    (JavaType.BOOLEAN    , WIRETYPE_VARINT          ),
+    STRING  (JavaType.STRING     , WIRETYPE_LENGTH_DELIMITED) {
+      @Override
+      public boolean isPackable() {
+        return false; }
+    },
+    GROUP   (JavaType.MESSAGE    , WIRETYPE_START_GROUP     ) {
+      @Override
+      public boolean isPackable() {
+        return false; }
+    },
+    MESSAGE (JavaType.MESSAGE    , WIRETYPE_LENGTH_DELIMITED) {
+      @Override
+      public boolean isPackable() {
+        return false; }
+    },
+    BYTES   (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
+      @Override
+      public boolean isPackable() {
+        return false; }
+    },
+    UINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
+    ENUM    (JavaType.ENUM       , WIRETYPE_VARINT          ),
+    SFIXED32(JavaType.INT        , WIRETYPE_FIXED32         ),
+    SFIXED64(JavaType.LONG       , WIRETYPE_FIXED64         ),
+    SINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
+    SINT64  (JavaType.LONG       , WIRETYPE_VARINT          );
+
+    FieldType(final JavaType javaType, final int wireType) {
+      this.javaType = javaType;
+      this.wireType = wireType;
+    }
+
+    private final JavaType javaType;
+    private final int wireType;
+
+    public JavaType getJavaType() { return javaType; }
+    public int getWireType() { return wireType; }
+
+    public boolean isPackable() { return true; }
+  }
+
+  // Field numbers for fields in MessageSet wire format.
+  static final int MESSAGE_SET_ITEM    = 1;
+  static final int MESSAGE_SET_TYPE_ID = 2;
+  static final int MESSAGE_SET_MESSAGE = 3;
+
+  // Tag numbers.
+  static final int MESSAGE_SET_ITEM_TAG =
+    makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
+  static final int MESSAGE_SET_ITEM_END_TAG =
+    makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
+  static final int MESSAGE_SET_TYPE_ID_TAG =
+    makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
+  static final int MESSAGE_SET_MESSAGE_TAG =
+    makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
+
+  /**
+   * Validation level for handling incoming string field data which potentially
+   * contain non-UTF8 bytes.
+   */
+  enum Utf8Validation {
+    /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
+    LOOSE {
+      @Override
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readString();
+      }
+    },
+    /** Eagerly parses to String; throws an IOException on invalid bytes. */
+    STRICT {
+      @Override
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readStringRequireUtf8();
+      }
+    },
+    /** Keep data as ByteString; validation/conversion to String is lazy. */
+    LAZY {
+      @Override
+      Object readString(CodedInputStream input) throws IOException {
+        return input.readBytes();
+      }
+    };
+
+    /** Read a string field from the input with the proper UTF8 validation. */
+    abstract Object readString(CodedInputStream input) throws IOException;
+  }
+
+  /**
+   * Read a field of any primitive type for immutable messages from a
+   * CodedInputStream. Enums, groups, and embedded messages are not handled by
+   * this method.
+   *
+   * @param input The stream from which to read.
+   * @param type Declared type of the field.
+   * @param utf8Validation Different string UTF8 validation level for handling
+   *                       string fields.
+   * @return An object representing the field's value, of the exact
+   *         type which would be returned by
+   *         {@link Message#getField(Descriptors.FieldDescriptor)} for
+   *         this field.
+   */
+  static Object readPrimitiveField(
+      CodedInputStream input,
+      FieldType type,
+      Utf8Validation utf8Validation) throws IOException {
+    switch (type) {
+      case DOUBLE  : return input.readDouble  ();
+      case FLOAT   : return input.readFloat   ();
+      case INT64   : return input.readInt64   ();
+      case UINT64  : return input.readUInt64  ();
+      case INT32   : return input.readInt32   ();
+      case FIXED64 : return input.readFixed64 ();
+      case FIXED32 : return input.readFixed32 ();
+      case BOOL    : return input.readBool    ();
+      case BYTES   : return input.readBytes   ();
+      case UINT32  : return input.readUInt32  ();
+      case SFIXED32: return input.readSFixed32();
+      case SFIXED64: return input.readSFixed64();
+      case SINT32  : return input.readSInt32  ();
+      case SINT64  : return input.readSInt64  ();
+
+      case STRING  : return utf8Validation.readString(input);
+      case GROUP:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle nested groups.");
+      case MESSAGE:
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle embedded messages.");
+      case ENUM:
+        // We don't handle enums because we don't know what to do if the
+        // value is not recognized.
+        throw new IllegalArgumentException(
+          "readPrimitiveField() cannot handle enums.");
+    }
+
+    throw new RuntimeException(
+      "There is no way to get here, but the compiler thinks otherwise.");
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
new file mode 100644
index 0000000..7dc9fc1
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -0,0 +1,551 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+/**
+ * Unit test for {@link AbstractMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class AbstractMessageTest extends TestCase {
+  /**
+   * Extends AbstractMessage and wraps some other message object.  The methods
+   * of the Message interface which aren't explicitly implemented by
+   * AbstractMessage are forwarded to the wrapped object.  This allows us to
+   * test that AbstractMessage's implementations work even if the wrapped
+   * object does not use them.
+   */
+  private static class AbstractMessageWrapper extends AbstractMessage {
+    private final Message wrappedMessage;
+
+    public AbstractMessageWrapper(Message wrappedMessage) {
+      this.wrappedMessage = wrappedMessage;
+    }
+
+    @Override
+    public Descriptors.Descriptor getDescriptorForType() {
+      return wrappedMessage.getDescriptorForType();
+    }
+    @Override
+    public AbstractMessageWrapper getDefaultInstanceForType() {
+      return new AbstractMessageWrapper(
+        wrappedMessage.getDefaultInstanceForType());
+    }
+    @Override
+    public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+      return wrappedMessage.getAllFields();
+    }
+    @Override
+    public boolean hasField(Descriptors.FieldDescriptor field) {
+      return wrappedMessage.hasField(field);
+    }
+    @Override
+    public Object getField(Descriptors.FieldDescriptor field) {
+      return wrappedMessage.getField(field);
+    }
+    @Override
+    public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+      return wrappedMessage.getRepeatedFieldCount(field);
+    }
+    @Override
+    public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
+      return wrappedMessage.getRepeatedField(field, index);
+    }
+    @Override
+    public UnknownFieldSet getUnknownFields() {
+      return wrappedMessage.getUnknownFields();
+    }
+    @Override
+    public Builder newBuilderForType() {
+      return new Builder(wrappedMessage.newBuilderForType());
+    }
+    @Override
+    public Builder toBuilder() {
+      return new Builder(wrappedMessage.toBuilder());
+    }
+
+    static class Builder extends AbstractMessage.Builder<Builder> {
+      private final Message.Builder wrappedBuilder;
+
+      public Builder(Message.Builder wrappedBuilder) {
+        this.wrappedBuilder = wrappedBuilder;
+      }
+
+      @Override
+      public AbstractMessageWrapper build() {
+        return new AbstractMessageWrapper(wrappedBuilder.build());
+      }
+      @Override
+      public AbstractMessageWrapper buildPartial() {
+        return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
+      }
+      @Override
+      public Builder clone() {
+        return new Builder(wrappedBuilder.clone());
+      }
+      @Override
+      public boolean isInitialized() {
+        return clone().buildPartial().isInitialized();
+      }
+      @Override
+      public Descriptors.Descriptor getDescriptorForType() {
+        return wrappedBuilder.getDescriptorForType();
+      }
+      @Override
+      public AbstractMessageWrapper getDefaultInstanceForType() {
+        return new AbstractMessageWrapper(
+          wrappedBuilder.getDefaultInstanceForType());
+      }
+      @Override
+      public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+        return wrappedBuilder.getAllFields();
+      }
+      @Override
+      public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
+        return new Builder(wrappedBuilder.newBuilderForField(field));
+      }
+      @Override
+      public boolean hasField(Descriptors.FieldDescriptor field) {
+        return wrappedBuilder.hasField(field);
+      }
+      @Override
+      public Object getField(Descriptors.FieldDescriptor field) {
+        return wrappedBuilder.getField(field);
+      }
+      @Override
+      public Builder setField(Descriptors.FieldDescriptor field, Object value) {
+        wrappedBuilder.setField(field, value);
+        return this;
+      }
+      @Override
+      public Builder clearField(Descriptors.FieldDescriptor field) {
+        wrappedBuilder.clearField(field);
+        return this;
+      }
+      @Override
+      public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+        return wrappedBuilder.getRepeatedFieldCount(field);
+      }
+      @Override
+      public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
+        return wrappedBuilder.getRepeatedField(field, index);
+      }
+      @Override
+      public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) {
+        wrappedBuilder.setRepeatedField(field, index, value);
+        return this;
+      }
+      @Override
+      public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+        wrappedBuilder.addRepeatedField(field, value);
+        return this;
+      }
+      @Override
+      public UnknownFieldSet getUnknownFields() {
+        return wrappedBuilder.getUnknownFields();
+      }
+      @Override
+      public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+        wrappedBuilder.setUnknownFields(unknownFields);
+        return this;
+      }
+      @Override
+      public Message.Builder getFieldBuilder(FieldDescriptor field) {
+        return wrappedBuilder.getFieldBuilder(field);
+      }
+    }
+    @Override
+    public Parser<? extends Message> getParserForType() {
+      return wrappedMessage.getParserForType();
+    }
+  }
+
+  // =================================================================
+
+  TestUtil.ReflectionTester reflectionTester =
+    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+  TestUtil.ReflectionTester extensionsReflectionTester =
+    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+                                  TestUtil.getExtensionRegistry());
+
+  public void testClear() throws Exception {
+    AbstractMessageWrapper message =
+      new AbstractMessageWrapper.Builder(
+          TestAllTypes.newBuilder(TestUtil.getAllSet()))
+        .clear().build();
+    TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
+  }
+
+  public void testCopy() throws Exception {
+    AbstractMessageWrapper message =
+      new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
+        .mergeFrom(TestUtil.getAllSet()).build();
+    TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+  }
+
+  public void testSerializedSize() throws Exception {
+    TestAllTypes message = TestUtil.getAllSet();
+    Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+    assertEquals(message.getSerializedSize(),
+                 abstractMessage.getSerializedSize());
+  }
+
+  public void testSerialization() throws Exception {
+    Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+    TestUtil.assertAllFieldsSet(
+      TestAllTypes.parseFrom(abstractMessage.toByteString()));
+
+    assertEquals(TestUtil.getAllSet().toByteString(),
+                 abstractMessage.toByteString());
+  }
+
+  public void testParsing() throws Exception {
+    AbstractMessageWrapper.Builder builder =
+      new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
+    AbstractMessageWrapper message =
+      builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
+    TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+  }
+
+  public void testParsingUninitialized() throws Exception {
+    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+    builder.getOptionalMessageBuilder().setDummy2(10);
+    ByteString bytes = builder.buildPartial().toByteString();
+    Message.Builder abstractMessageBuilder =
+        new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+    // mergeFrom() should not throw initialization error.
+    abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+    try {
+      abstractMessageBuilder.mergeFrom(bytes).build();
+      fail();
+    } catch (UninitializedMessageException ex) {
+      // pass
+    }
+
+    // test DynamicMessage directly.
+    Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+        TestRequiredForeign.getDescriptor());
+    // mergeFrom() should not throw initialization error.
+    dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+    try {
+      dynamicMessageBuilder.mergeFrom(bytes).build();
+      fail();
+    } catch (UninitializedMessageException ex) {
+      // pass
+    }
+  }
+
+  public void testPackedSerialization() throws Exception {
+    Message abstractMessage =
+        new AbstractMessageWrapper(TestUtil.getPackedSet());
+
+    TestUtil.assertPackedFieldsSet(
+      TestPackedTypes.parseFrom(abstractMessage.toByteString()));
+
+    assertEquals(TestUtil.getPackedSet().toByteString(),
+                 abstractMessage.toByteString());
+  }
+
+  public void testPackedParsing() throws Exception {
+    AbstractMessageWrapper.Builder builder =
+      new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+    AbstractMessageWrapper message =
+      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+    TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+  }
+
+  public void testUnpackedSerialization() throws Exception {
+    Message abstractMessage =
+      new AbstractMessageWrapper(TestUtil.getUnpackedSet());
+
+    TestUtil.assertUnpackedFieldsSet(
+      TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
+
+    assertEquals(TestUtil.getUnpackedSet().toByteString(),
+                 abstractMessage.toByteString());
+  }
+
+  public void testParsePackedToUnpacked() throws Exception {
+    AbstractMessageWrapper.Builder builder =
+      new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+    AbstractMessageWrapper message =
+      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+    TestUtil.assertUnpackedFieldsSet(
+      (TestUnpackedTypes) message.wrappedMessage);
+  }
+
+  public void testParseUnpackedToPacked() throws Exception {
+    AbstractMessageWrapper.Builder builder =
+      new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+    AbstractMessageWrapper message =
+      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+    TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+  }
+
+  public void testUnpackedParsing() throws Exception {
+    AbstractMessageWrapper.Builder builder =
+      new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+    AbstractMessageWrapper message =
+      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+    TestUtil.assertUnpackedFieldsSet(
+      (TestUnpackedTypes) message.wrappedMessage);
+  }
+
+  public void testOptimizedForSize() throws Exception {
+    // We're mostly only checking that this class was compiled successfully.
+    TestOptimizedForSize message =
+      TestOptimizedForSize.newBuilder().setI(1).build();
+    message = TestOptimizedForSize.parseFrom(message.toByteString());
+    assertEquals(2, message.getSerializedSize());
+  }
+
+  // -----------------------------------------------------------------
+  // Tests for isInitialized().
+
+  private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+    TestRequired.getDefaultInstance();
+  private static final TestRequired TEST_REQUIRED_INITIALIZED =
+    TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+  public void testIsInitialized() throws Exception {
+    TestRequired.Builder builder = TestRequired.newBuilder();
+    AbstractMessageWrapper.Builder abstractBuilder =
+      new AbstractMessageWrapper.Builder(builder);
+
+    assertFalse(abstractBuilder.isInitialized());
+    assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
+    builder.setA(1);
+    assertFalse(abstractBuilder.isInitialized());
+    assertEquals("b, c", abstractBuilder.getInitializationErrorString());
+    builder.setB(1);
+    assertFalse(abstractBuilder.isInitialized());
+    assertEquals("c", abstractBuilder.getInitializationErrorString());
+    builder.setC(1);
+    assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
+  }
+
+  public void testForeignIsInitialized() throws Exception {
+    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+    AbstractMessageWrapper.Builder abstractBuilder =
+      new AbstractMessageWrapper.Builder(builder);
+
+    assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
+
+    builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(abstractBuilder.isInitialized());
+    assertEquals(
+        "optional_message.a, optional_message.b, optional_message.c",
+        abstractBuilder.getInitializationErrorString());
+
+    builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+    assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
+
+    builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(abstractBuilder.isInitialized());
+    assertEquals(
+        "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+        abstractBuilder.getInitializationErrorString());
+
+    builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+    assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
+  }
+
+  // -----------------------------------------------------------------
+  // Tests for mergeFrom
+
+  static final TestAllTypes MERGE_SOURCE =
+    TestAllTypes.newBuilder()
+      .setOptionalInt32(1)
+      .setOptionalString("foo")
+      .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+      .addRepeatedString("bar")
+      .build();
+
+  static final TestAllTypes MERGE_DEST =
+    TestAllTypes.newBuilder()
+      .setOptionalInt64(2)
+      .setOptionalString("baz")
+      .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+      .addRepeatedString("qux")
+      .build();
+
+  static final String MERGE_RESULT_TEXT =
+      "optional_int32: 1\n" +
+      "optional_int64: 2\n" +
+      "optional_string: \"foo\"\n" +
+      "optional_foreign_message {\n" +
+      "  c: 3\n" +
+      "}\n" +
+      "repeated_string: \"qux\"\n" +
+      "repeated_string: \"bar\"\n";
+
+  public void testMergeFrom() throws Exception {
+    AbstractMessageWrapper result =
+      new AbstractMessageWrapper.Builder(
+        TestAllTypes.newBuilder(MERGE_DEST))
+      .mergeFrom(MERGE_SOURCE).build();
+
+    assertEquals(MERGE_RESULT_TEXT, result.toString());
+  }
+
+  // -----------------------------------------------------------------
+  // Tests for equals and hashCode
+
+  public void testEqualsAndHashCode() throws Exception {
+    TestAllTypes a = TestUtil.getAllSet();
+    TestAllTypes b = TestAllTypes.newBuilder().build();
+    TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
+    TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
+    TestAllExtensions e = TestUtil.getAllExtensionsSet();
+    TestAllExtensions f = TestAllExtensions.newBuilder(e)
+        .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
+
+    checkEqualsIsConsistent(a);
+    checkEqualsIsConsistent(b);
+    checkEqualsIsConsistent(c);
+    checkEqualsIsConsistent(d);
+    checkEqualsIsConsistent(e);
+    checkEqualsIsConsistent(f);
+
+    checkNotEqual(a, b);
+    checkNotEqual(a, c);
+    checkNotEqual(a, d);
+    checkNotEqual(a, e);
+    checkNotEqual(a, f);
+
+    checkNotEqual(b, c);
+    checkNotEqual(b, d);
+    checkNotEqual(b, e);
+    checkNotEqual(b, f);
+
+    checkNotEqual(c, d);
+    checkNotEqual(c, e);
+    checkNotEqual(c, f);
+
+    checkNotEqual(d, e);
+    checkNotEqual(d, f);
+
+    checkNotEqual(e, f);
+
+    // Deserializing into the TestEmptyMessage such that every field
+    // is an {@link UnknownFieldSet.Field}.
+    UnittestProto.TestEmptyMessage eUnknownFields =
+        UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+    UnittestProto.TestEmptyMessage fUnknownFields =
+        UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
+    checkNotEqual(eUnknownFields, fUnknownFields);
+    checkEqualsIsConsistent(eUnknownFields);
+    checkEqualsIsConsistent(fUnknownFields);
+
+    // Subsequent reconstitutions should be identical
+    UnittestProto.TestEmptyMessage eUnknownFields2 =
+        UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+    checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
+  }
+
+
+  /**
+   * Asserts that the given proto has symmetric equals and hashCode methods.
+   */
+  private void checkEqualsIsConsistent(Message message) {
+    // Object should be equal to itself.
+    assertEquals(message, message);
+
+    // Object should be equal to a dynamic copy of itself.
+    DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
+    checkEqualsIsConsistent(message, dynamic);
+  }
+
+  /**
+   * Asserts that the given protos are equal and have the same hash code.
+   */
+  private void checkEqualsIsConsistent(Message message1, Message message2) {
+    assertEquals(message1, message2);
+    assertEquals(message2, message1);
+    assertEquals(message2.hashCode(), message1.hashCode());
+  }
+
+  /**
+   * Asserts that the given protos are not equal and have different hash codes.
+   *
+   * @warning It's valid for non-equal objects to have the same hash code, so
+   *   this test is stricter than it needs to be. However, this should happen
+   *   relatively rarely.
+   */
+  private void checkNotEqual(Message m1, Message m2) {
+    String equalsError = String.format("%s should not be equal to %s", m1, m2);
+    assertFalse(equalsError, m1.equals(m2));
+    assertFalse(equalsError, m2.equals(m1));
+
+    assertFalse(
+        String.format("%s should have a different hash code from %s", m1, m2),
+        m1.hashCode() == m2.hashCode());
+  }
+
+  public void testCheckByteStringIsUtf8OnUtf8() {
+    ByteString byteString = ByteString.copyFromUtf8("some text");
+    AbstractMessageLite.checkByteStringIsUtf8(byteString);
+    // No exception thrown.
+  }
+
+  public void testCheckByteStringIsUtf8OnNonUtf8() {
+    ByteString byteString =
+        ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+    try {
+      AbstractMessageLite.checkByteStringIsUtf8(byteString);
+      fail("Expected AbstractMessageLite.checkByteStringIsUtf8 to throw IllegalArgumentException");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AnyTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AnyTest.java
new file mode 100644
index 0000000..cf91ed9
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/AnyTest.java
@@ -0,0 +1,137 @@
+// 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.
+
+package com.google.protobuf;
+
+import any_test.AnyTestProto.TestAny;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for Any message.
+ */
+public class AnyTest extends TestCase {
+  public void testAnyGeneratedApi() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder()
+        .setValue(Any.pack(message)).build();
+
+    assertTrue(container.getValue().is(TestAllTypes.class));
+    assertFalse(container.getValue().is(TestAny.class));
+
+    TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+    TestUtil.assertAllFieldsSet(result);
+
+
+    // Unpacking to a wrong type will throw an exception.
+    try {
+      TestAny wrongMessage = container.getValue().unpack(TestAny.class);
+      fail("Exception is expected.");
+    } catch (InvalidProtocolBufferException e) {
+      // expected.
+    }
+
+    // Test that unpacking throws an exception if parsing fails.
+    TestAny.Builder containerBuilder = container.toBuilder();
+    containerBuilder.getValueBuilder().setValue(
+        ByteString.copyFrom(new byte[]{0x11}));
+    container = containerBuilder.build();
+    try {
+      TestAllTypes parsingFailed = container.getValue().unpack(TestAllTypes.class);
+      fail("Exception is expected.");
+    } catch (InvalidProtocolBufferException e) {
+      // expected.
+    }
+  }
+
+  public void testCustomTypeUrls() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder()
+        .setValue(Any.pack(message, "xxx.com")).build();
+
+    assertEquals(
+        "xxx.com/" + TestAllTypes.getDescriptor().getFullName(),
+        container.getValue().getTypeUrl());
+
+    assertTrue(container.getValue().is(TestAllTypes.class));
+    assertFalse(container.getValue().is(TestAny.class));
+
+    TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+    TestUtil.assertAllFieldsSet(result);
+
+    container = TestAny.newBuilder()
+        .setValue(Any.pack(message, "yyy.com/")).build();
+
+    assertEquals(
+        "yyy.com/" + TestAllTypes.getDescriptor().getFullName(),
+        container.getValue().getTypeUrl());
+
+    assertTrue(container.getValue().is(TestAllTypes.class));
+    assertFalse(container.getValue().is(TestAny.class));
+
+    result = container.getValue().unpack(TestAllTypes.class);
+    TestUtil.assertAllFieldsSet(result);
+
+    container = TestAny.newBuilder()
+        .setValue(Any.pack(message, "")).build();
+
+    assertEquals(
+        "/" + TestAllTypes.getDescriptor().getFullName(),
+        container.getValue().getTypeUrl());
+
+    assertTrue(container.getValue().is(TestAllTypes.class));
+    assertFalse(container.getValue().is(TestAny.class));
+
+    result = container.getValue().unpack(TestAllTypes.class);
+    TestUtil.assertAllFieldsSet(result);
+  }
+
+  public void testCachedUnpackResult() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder()
+        .setValue(Any.pack(message)).build();
+
+    assertTrue(container.getValue().is(TestAllTypes.class));
+
+    TestAllTypes result1 = container.getValue().unpack(TestAllTypes.class);
+    TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class);
+    assertTrue(result1 == result2);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
new file mode 100644
index 0000000..24b96c6
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
@@ -0,0 +1,455 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link BooleanArrayList}.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class BooleanArrayListTest extends TestCase {
+  
+  private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true);
+  private static final BooleanArrayList TERTIARY_LIST =
+      newImmutableBooleanArrayList(true, true, false);
+  
+  private BooleanArrayList list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new BooleanArrayList();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(BooleanArrayList.emptyList());
+  }
+  
+  public void testMakeImmutable() {
+    list.addBoolean(true);
+    list.addBoolean(false);
+    list.addBoolean(true);
+    list.addBoolean(true);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+  
+  public void testModificationWithIteration() {
+    list.addAll(asList(true, false, false, true));
+    Iterator<Boolean> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(true, (boolean) list.get(0));
+    assertEquals(true, (boolean) iterator.next());
+    list.set(0, true);
+    assertEquals(false, (boolean) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, false);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testGet() {
+    assertEquals(true, (boolean) TERTIARY_LIST.get(0));
+    assertEquals(true, (boolean) TERTIARY_LIST.get(1));
+    assertEquals(false, (boolean) TERTIARY_LIST.get(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testGetInt() {
+    assertEquals(true, TERTIARY_LIST.getBoolean(0));
+    assertEquals(true, TERTIARY_LIST.getBoolean(1));
+    assertEquals(false, TERTIARY_LIST.getBoolean(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSize() {
+    assertEquals(0, BooleanArrayList.emptyList().size());
+    assertEquals(1, UNARY_LIST.size());
+    assertEquals(3, TERTIARY_LIST.size());
+
+    list.addBoolean(true);
+    list.addBoolean(false);
+    list.addBoolean(false);
+    list.addBoolean(false);
+    assertEquals(4, list.size());
+    
+    list.remove(0);
+    assertEquals(3, list.size());
+    
+    list.add(true);
+    assertEquals(4, list.size());
+  }
+  
+  public void testSet() {
+    list.addBoolean(false);
+    list.addBoolean(false);
+    
+    assertEquals(false, (boolean) list.set(0, true));
+    assertEquals(true, list.getBoolean(0));
+
+    assertEquals(false, (boolean) list.set(1, false));
+    assertEquals(false, list.getBoolean(1));
+    
+    try {
+      list.set(-1, true);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.set(2, false);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSetInt() {
+    list.addBoolean(true);
+    list.addBoolean(true);
+    
+    assertEquals(true, list.setBoolean(0, false));
+    assertEquals(false, list.getBoolean(0));
+
+    assertEquals(true, list.setBoolean(1, false));
+    assertEquals(false, list.getBoolean(1));
+    
+    try {
+      list.setBoolean(-1, false);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.setBoolean(2, true);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAdd() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.add(true));
+    assertEquals(asList(true), list);
+
+    assertTrue(list.add(false));
+    list.add(0, false);
+    assertEquals(asList(false, true, false), list);
+    
+    list.add(0, false);
+    list.add(0, true);
+    // Force a resize by getting up to 11 elements.
+    for (int i = 0; i < 6; i++) {
+      list.add(true);
+    }
+    assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list);
+    
+    try {
+      list.add(-1, false);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.add(4, true);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAddInt() {
+    assertEquals(0, list.size());
+
+    list.addBoolean(true);
+    assertEquals(asList(true), list);
+
+    list.addBoolean(false);
+    assertEquals(asList(true, false), list);
+  }
+  
+  public void testAddAll() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.addAll(Collections.singleton(false)));
+    assertEquals(1, list.size());
+    assertEquals(false, (boolean) list.get(0));
+    assertEquals(false, list.getBoolean(0));
+    
+    assertTrue(list.addAll(asList(true, false, false, false, true)));
+    assertEquals(asList(false, true, false, false, false, true), list);
+    
+    assertTrue(list.addAll(TERTIARY_LIST));
+    assertEquals(asList(false, true, false, false, false, true, true, true, false), list);
+
+    assertFalse(list.addAll(Collections.<Boolean>emptyList()));
+    assertFalse(list.addAll(BooleanArrayList.emptyList()));
+  }
+  
+  public void testRemove() {
+    list.addAll(TERTIARY_LIST);
+    assertEquals(true, (boolean) list.remove(0));
+    assertEquals(asList(true, false), list);
+
+    assertTrue(list.remove(Boolean.TRUE));
+    assertEquals(asList(false), list);
+
+    assertFalse(list.remove(Boolean.TRUE));
+    assertEquals(asList(false), list);
+
+    assertEquals(false, (boolean) list.remove(0));
+    assertEquals(asList(), list);
+    
+    try {
+      list.remove(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  private void assertImmutable(BooleanArrayList list) {
+    try {
+      list.add(false);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, true);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Boolean>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(false));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new BooleanArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(true));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Boolean>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addBoolean(true);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.<Boolean>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(Boolean.TRUE));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.<Boolean>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(Boolean.TRUE));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, true);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.setBoolean(0, false);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) {
+    BooleanArrayList list = new BooleanArrayList();
+    for (boolean element : elements) {
+      list.addBoolean(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
new file mode 100644
index 0000000..db10ee7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -0,0 +1,100 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}.  The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "BoundedByteString";
+    byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+    int from = 100;
+    int to = sourceBytes.length - 100;
+    stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+    referenceBytes = new byte[to - from];
+    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+    expectedHashCode = 727575887;
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+    ByteString chopped = unicode.substring(2, unicode.size() - 6);
+    assertEquals(classUnderTest + ".substring() must have the expected type",
+        classUnderTest, getActualClassName(chopped));
+
+    String roundTripString = chopped.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString.substring(2, testString.length() - 6), roundTripString);
+  }
+
+  @Override
+  public void testCharsetToString() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+    ByteString chopped = unicode.substring(2, unicode.size() - 6);
+    assertEquals(classUnderTest + ".substring() must have the expected type",
+        classUnderTest, getActualClassName(chopped));
+
+    String roundTripString = chopped.toString(Internal.UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString.substring(2, testString.length() - 6), roundTripString);
+  }
+
+  @Override
+  public void testJavaSerialization() throws Exception {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream oos = new ObjectOutputStream(out);
+    oos.writeObject(stringUnderTest);
+    oos.close();
+    byte[] pickled = out.toByteArray();
+    InputStream in = new ByteArrayInputStream(pickled);
+    ObjectInputStream ois = new ObjectInputStream(in);
+    Object o = ois.readObject();
+    assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+    assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java
new file mode 100644
index 0000000..cbe742e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java
@@ -0,0 +1,81 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Tests for {@link ByteBufferWriter}.
+ */
+public class ByteBufferWriterTest extends TestCase {
+
+  public void testHeapBuffer() throws IOException {
+    // Test a small and large buffer.
+    testWrite(ByteBuffer.allocate(100));
+    testWrite(ByteBuffer.allocate(1024 * 100));
+  }
+
+  public void testDirectBuffer() throws IOException {
+    // Test a small and large buffer.
+    testWrite(ByteBuffer.allocateDirect(100));
+    testWrite(ByteBuffer.allocateDirect(1024 * 100));
+  }
+
+  private void testWrite(ByteBuffer buffer) throws IOException {
+    fillRandom(buffer);
+    ByteArrayOutputStream os = new ByteArrayOutputStream(buffer.remaining());
+    ByteBufferWriter.write(buffer, os);
+    assertEquals(0, buffer.position());
+    assertTrue(Arrays.equals(toArray(buffer), os.toByteArray()));
+  }
+
+  private void fillRandom(ByteBuffer buf) {
+    byte[] bytes = new byte[buf.remaining()];
+    new Random().nextBytes(bytes);
+    buf.put(bytes);
+    buf.flip();
+    return;
+  }
+
+  private byte[] toArray(ByteBuffer buf) {
+    int originalPosition = buf.position();
+    byte[] bytes = new byte[buf.remaining()];
+    buf.get(bytes);
+    buf.position(originalPosition);
+    return bytes;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
new file mode 100644
index 0000000..ad9f266
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -0,0 +1,774 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.ByteString.Output;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+  private static final Charset UTF_16 = Charset.forName("UTF-16");
+
+  static byte[] getTestBytes(int size, long seed) {
+    Random random = new Random(seed);
+    byte[] result = new byte[size];
+    random.nextBytes(result);
+    return result;
+  }
+
+  private byte[] getTestBytes(int size) {
+    return getTestBytes(size, 445566L);
+  }
+
+  private byte[] getTestBytes() {
+    return getTestBytes(1000);
+  }
+
+  // Compare the entire left array with a subset of the right array.
+  private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+    boolean stillEqual = (left.length == length);
+    for (int i = 0; (stillEqual && i < length); ++i) {
+      stillEqual = (left[i] == right[rightOffset + i]);
+    }
+    return stillEqual;
+  }
+
+  // Returns true only if the given two arrays have identical contents.
+  private boolean isArray(byte[] left, byte[] right) {
+    return left.length == right.length && isArrayRange(left, right, 0, left.length);
+  }
+
+  public void testSubstring_BeginIndex() {
+    byte[] bytes = getTestBytes();
+    ByteString substring = ByteString.copyFrom(bytes).substring(500);
+    assertTrue("substring must contain the tail of the string",
+        isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+  }
+
+  public void testCopyFrom_BytesOffsetSize() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+    assertTrue("copyFrom sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+  }
+
+  public void testCopyFrom_Bytes() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes);
+    assertTrue("copyFrom must contain the expected bytes",
+        isArray(byteString.toByteArray(), bytes));
+  }
+
+  public void testCopyFrom_ByteBufferSize() {
+    byte[] bytes = getTestBytes();
+    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+    byteBuffer.put(bytes);
+    byteBuffer.position(500);
+    ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+  }
+
+  public void testCopyFrom_ByteBuffer() {
+    byte[] bytes = getTestBytes();
+    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+    byteBuffer.put(bytes);
+    byteBuffer.position(500);
+    ByteString byteString = ByteString.copyFrom(byteBuffer);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+  }
+
+  public void testCopyFrom_StringEncoding() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+    byte[] testBytes = testString.getBytes(UTF_16);
+    assertTrue("copyFrom string must respect the charset",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+  }
+
+  public void testCopyFrom_Utf8() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString byteString = ByteString.copyFromUtf8(testString);
+    byte[] testBytes = testString.getBytes(Internal.UTF_8);
+    assertTrue("copyFromUtf8 string must respect the charset",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+  }
+
+  public void testCopyFrom_Iterable() {
+    byte[] testBytes = getTestBytes(77777, 113344L);
+    final List<ByteString> pieces = makeConcretePieces(testBytes);
+    // Call copyFrom() on a Collection
+    ByteString byteString = ByteString.copyFrom(pieces);
+    assertTrue("copyFrom a List must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+    // Call copyFrom on an iteration that's not a collection
+    ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+      @Override
+      public Iterator<ByteString> iterator() {
+        return pieces.iterator();
+      }
+    });
+    assertEquals("copyFrom from an Iteration must contain the expected bytes",
+        byteString, byteStringAlt);
+  }
+
+  public void testCopyTo_TargetOffset() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes);
+    byte[] target = new byte[bytes.length + 1000];
+    byteString.copyTo(target, 400);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(bytes, target, 400, bytes.length));
+  }
+
+  public void testReadFrom_emptyStream() throws IOException {
+    ByteString byteString =
+        ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+    assertSame("reading an empty stream must result in the EMPTY constant "
+        + "byte string", ByteString.EMPTY, byteString);
+  }
+
+  public void testReadFrom_smallStream() throws IOException {
+    assertReadFrom(getTestBytes(10));
+  }
+
+  public void testReadFrom_mutating() throws IOException {
+    byte[] capturedArray = null;
+    EvilInputStream eis = new EvilInputStream();
+    ByteString byteString = ByteString.readFrom(eis);
+
+    capturedArray = eis.capturedArray;
+    byte[] originalValue = byteString.toByteArray();
+    for (int x = 0; x < capturedArray.length; ++x) {
+      capturedArray[x] = (byte) 0;
+    }
+
+    byte[] newValue = byteString.toByteArray();
+    assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+        Arrays.equals(originalValue, newValue));
+  }
+
+  // Tests sizes that are near the rope copy-out threshold.
+  public void testReadFrom_mediumStream() throws IOException {
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1));
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE));
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1));
+    assertReadFrom(getTestBytes(200));
+  }
+
+  // Tests sizes that are over multi-segment rope threshold.
+  public void testReadFrom_largeStream() throws IOException {
+    assertReadFrom(getTestBytes(0x100));
+    assertReadFrom(getTestBytes(0x101));
+    assertReadFrom(getTestBytes(0x110));
+    assertReadFrom(getTestBytes(0x1000));
+    assertReadFrom(getTestBytes(0x1001));
+    assertReadFrom(getTestBytes(0x1010));
+    assertReadFrom(getTestBytes(0x10000));
+    assertReadFrom(getTestBytes(0x10001));
+    assertReadFrom(getTestBytes(0x10010));
+  }
+
+  // Tests sizes that are near the read buffer size.
+  public void testReadFrom_byteBoundaries() throws IOException {
+    final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE;
+    final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE;
+
+    assertReadFrom(getTestBytes(min - 1));
+    assertReadFrom(getTestBytes(min));
+    assertReadFrom(getTestBytes(min + 1));
+
+    assertReadFrom(getTestBytes(min * 2 - 1));
+    assertReadFrom(getTestBytes(min * 2));
+    assertReadFrom(getTestBytes(min * 2 + 1));
+
+    assertReadFrom(getTestBytes(min * 4 - 1));
+    assertReadFrom(getTestBytes(min * 4));
+    assertReadFrom(getTestBytes(min * 4 + 1));
+
+    assertReadFrom(getTestBytes(min * 8 - 1));
+    assertReadFrom(getTestBytes(min * 8));
+    assertReadFrom(getTestBytes(min * 8 + 1));
+
+    assertReadFrom(getTestBytes(max - 1));
+    assertReadFrom(getTestBytes(max));
+    assertReadFrom(getTestBytes(max + 1));
+
+    assertReadFrom(getTestBytes(max * 2 - 1));
+    assertReadFrom(getTestBytes(max * 2));
+    assertReadFrom(getTestBytes(max * 2 + 1));
+  }
+
+  // Tests that IOExceptions propagate through ByteString.readFrom().
+  public void testReadFrom_IOExceptions() {
+    try {
+      ByteString.readFrom(new FailStream());
+      fail("readFrom must throw the underlying IOException");
+
+    } catch (IOException e) {
+      assertEquals("readFrom must throw the expected exception",
+                   "synthetic failure", e.getMessage());
+    }
+  }
+
+  // Tests that ByteString.readFrom works with streams that don't
+  // always fill their buffers.
+  public void testReadFrom_reluctantStream() throws IOException {
+    final byte[] data = getTestBytes(0x1000);
+
+    ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), data));
+
+    // Same test as above, but with some specific chunk sizes.
+    assertReadFromReluctantStream(data, 100);
+    assertReadFromReluctantStream(data, 248);
+    assertReadFromReluctantStream(data, 249);
+    assertReadFromReluctantStream(data, 250);
+    assertReadFromReluctantStream(data, 251);
+    assertReadFromReluctantStream(data, 0x1000);
+    assertReadFromReluctantStream(data, 0x1001);
+  }
+
+  // Fails unless ByteString.readFrom reads the bytes correctly from a
+  // reluctant stream with the given chunkSize parameter.
+  private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+      throws IOException {
+    ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(b.toByteArray(), bytes));
+  }
+
+  // Tests that ByteString.readFrom works with streams that implement
+  // available().
+  public void testReadFrom_available() throws IOException {
+    final byte[] data = getTestBytes(0x1001);
+
+    ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), data));
+  }
+
+  // Fails unless ByteString.readFrom reads the bytes correctly.
+  private void assertReadFrom(byte[] bytes) throws IOException {
+    ByteString byteString =
+        ByteString.readFrom(new ByteArrayInputStream(bytes));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), bytes));
+  }
+
+  // A stream that fails when read.
+  private static final class FailStream extends InputStream {
+    @Override public int read() throws IOException {
+      throw new IOException("synthetic failure");
+    }
+  }
+
+  // A stream that simulates blocking by only producing 250 characters
+  // per call to read(byte[]).
+  private static class ReluctantStream extends InputStream {
+    protected final byte[] data;
+    protected int pos = 0;
+
+    public ReluctantStream(byte[] data) {
+      this.data = data;
+    }
+
+    @Override public int read() {
+      if (pos == data.length) {
+        return -1;
+      } else {
+        return data[pos++];
+      }
+    }
+
+    @Override public int read(byte[] buf) {
+      return read(buf, 0, buf.length);
+    }
+
+    @Override public int read(byte[] buf, int offset, int size) {
+      if (pos == data.length) {
+        return -1;
+      }
+      int count = Math.min(Math.min(size, data.length - pos), 250);
+      System.arraycopy(data, pos, buf, offset, count);
+      pos += count;
+      return count;
+    }
+  }
+
+  // Same as above, but also implements available().
+  private static final class AvailableStream extends ReluctantStream {
+    public AvailableStream(byte[] data) {
+      super(data);
+    }
+
+    @Override public int available() {
+      return Math.min(250, data.length - pos);
+    }
+  }
+
+  // A stream which exposes the byte array passed into read(byte[], int, int).
+  private static class EvilInputStream extends InputStream {
+    public byte[] capturedArray = null;
+
+    @Override
+    public int read(byte[] buf, int off, int len) {
+      if (capturedArray != null) {
+        return -1;
+      } else {
+        capturedArray = buf;
+        for (int x = 0; x < len; ++x) {
+          buf[x] = (byte) x;
+        }
+        return len;
+      }
+    }
+
+    @Override
+    public int read() {
+      // Purposefully do nothing.
+      return -1;
+    }
+  }
+
+  // A stream which exposes the byte array passed into write(byte[], int, int).
+  private static class EvilOutputStream extends OutputStream {
+    public byte[] capturedArray = null;
+
+    @Override
+    public void write(byte[] buf, int off, int len) {
+      if (capturedArray == null) {
+        capturedArray = buf;
+      }
+    }
+
+    @Override
+    public void write(int ignored) {
+      // Purposefully do nothing.
+    }
+  }
+
+  public void testToStringUtf8() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    byte[] testBytes = testString.getBytes(Internal.UTF_8);
+    ByteString byteString = ByteString.copyFrom(testBytes);
+    assertEquals("copyToStringUtf8 must respect the charset",
+        testString, byteString.toStringUtf8());
+  }
+
+  public void testNewOutput_InitialCapacity() throws IOException {
+    byte[] bytes = getTestBytes();
+    ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+    output.write(bytes);
+    ByteString byteString = output.toByteString();
+    assertTrue(
+        "String built from newOutput(int) must contain the expected bytes",
+        isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+  }
+
+  // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+  // write sizes
+  public void testNewOutput_ArrayWrite() {
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+                         2 * length, 3 * length};
+    int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+    for (int bufferSize : bufferSizes) {
+      for (int writeSize : writeSizes) {
+        // Test writing the entire output writeSize bytes at a time.
+        ByteString.Output output = ByteString.newOutput(bufferSize);
+        for (int i = 0; i < length; i += writeSize) {
+          output.write(bytes, i, Math.min(writeSize, length - i));
+        }
+        ByteString byteString = output.toByteString();
+        assertTrue("String built from newOutput() must contain the expected bytes",
+            isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+      }
+    }
+  }
+
+  // Test newOutput() using a variety of buffer sizes, but writing all the
+  // characters using write(byte);
+  public void testNewOutput_WriteChar() {
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {0, 1, 128, 256, length / 2,
+                         length - 1, length, length + 1,
+                         2 * length, 3 * length};
+    for (int bufferSize : bufferSizes) {
+      ByteString.Output output = ByteString.newOutput(bufferSize);
+      for (byte byteValue : bytes) {
+        output.write(byteValue);
+      }
+      ByteString byteString = output.toByteString();
+      assertTrue("String built from newOutput() must contain the expected bytes",
+          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+    }
+  }
+
+  // Test newOutput() in which we write the bytes using a variety of methods
+  // and sizes, and in which we repeatedly call toByteString() in the middle.
+  public void testNewOutput_Mixed() {
+    Random rng = new Random(1);
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {0, 1, 128, 256, length / 2,
+                         length - 1, length, length + 1,
+                         2 * length, 3 * length};
+
+    for (int bufferSize : bufferSizes) {
+      // Test writing the entire output using a mixture of write sizes and
+      // methods;
+      ByteString.Output output = ByteString.newOutput(bufferSize);
+      int position = 0;
+      while (position < bytes.length) {
+        if (rng.nextBoolean()) {
+          int count = 1 + rng.nextInt(bytes.length - position);
+          output.write(bytes, position, count);
+          position += count;
+        } else {
+          output.write(bytes[position]);
+          position++;
+        }
+        assertEquals("size() returns the right value", position, output.size());
+        assertTrue("newOutput() substring must have correct bytes",
+            isArrayRange(output.toByteString().toByteArray(),
+                bytes, 0, position));
+      }
+      ByteString byteString = output.toByteString();
+      assertTrue("String built from newOutput() must contain the expected bytes",
+          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+    }
+  }
+
+  public void testNewOutputEmpty() {
+    // Make sure newOutput() correctly builds empty byte strings
+    ByteString byteString = ByteString.newOutput().toByteString();
+    assertEquals(ByteString.EMPTY, byteString);
+  }
+
+  public void testNewOutput_Mutating() throws IOException {
+    Output os = ByteString.newOutput(5);
+    os.write(new byte[] {1, 2, 3, 4, 5});
+    EvilOutputStream eos = new EvilOutputStream();
+    os.writeTo(eos);
+    byte[] capturedArray = eos.capturedArray;
+    ByteString byteString = os.toByteString();
+    byte[] oldValue = byteString.toByteArray();
+    Arrays.fill(capturedArray, (byte) 0);
+    byte[] newValue = byteString.toByteArray();
+    assertTrue("Output must not provide access to the underlying byte array",
+        Arrays.equals(oldValue, newValue));
+  }
+
+  public void testNewCodedBuilder() throws IOException {
+    byte[] bytes = getTestBytes();
+    ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length);
+    builder.getCodedOutput().writeRawBytes(bytes);
+    ByteString byteString = builder.build();
+    assertTrue("String built from newCodedBuilder() must contain the expected bytes",
+        isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+  }
+
+  public void testSubstringParity() {
+    byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+    int start = 512 * 1024 - 3333;
+    int end   = 512 * 1024 + 7777;
+    ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+    boolean ok = true;
+    for (int i = start; ok && i < end; ++i) {
+      ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+    }
+    assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+    ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+    assertTrue("Substring must be equal to literal string",
+        concreteSubstring.equals(literalString));
+    assertEquals("Substring must have same hashcode as literal string",
+        literalString.hashCode(), concreteSubstring.hashCode());
+  }
+
+  public void testCompositeSubstring() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+    ByteString listString = ByteString.copyFrom(pieces);
+
+    int from = 1000;
+    int to = 40000;
+    ByteString compositeSubstring = listString.substring(from, to);
+    byte[] substringBytes = compositeSubstring.toByteArray();
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < to - from; ++i) {
+      stillEqual = referenceBytes[from + i] == substringBytes[i];
+    }
+    assertTrue("Substring must return correct bytes", stillEqual);
+
+    stillEqual = true;
+    for (int i = 0; stillEqual && i < to - from; ++i) {
+      stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+    }
+    assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+    ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+    assertTrue("Composite substring must equal a literal substring over the same bytes",
+        compositeSubstring.equals(literalSubstring));
+    assertTrue("Literal substring must equal a composite substring over the same bytes",
+        literalSubstring.equals(compositeSubstring));
+
+    assertEquals("We must get the same hashcodes for composite and literal substrings",
+        literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+    assertFalse("We can't be equal to a proper substring",
+        compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+  }
+
+  public void testCopyFromList() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+    ByteString listString = ByteString.copyFrom(pieces);
+
+    assertTrue("Composite string must be equal to literal string",
+        listString.equals(literalString));
+    assertEquals("Composite string must have same hashcode as literal string",
+        literalString.hashCode(), listString.hashCode());
+  }
+
+  public void testConcat() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+    Iterator<ByteString> iter = pieces.iterator();
+    ByteString concatenatedString = iter.next();
+    while (iter.hasNext()) {
+      concatenatedString = concatenatedString.concat(iter.next());
+    }
+
+    assertTrue("Concatenated string must be equal to literal string",
+        concatenatedString.equals(literalString));
+    assertEquals("Concatenated string must have same hashcode as literal string",
+        literalString.hashCode(), concatenatedString.hashCode());
+  }
+
+  /**
+   * Test the Rope implementation can deal with Empty nodes, even though we
+   * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}.
+   */
+  public void testConcat_empty() {
+    byte[] referenceBytes = getTestBytes(7748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString);
+    ByteString temp = RopeByteString.newInstanceForTest(
+        RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY),
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString));
+    ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY);
+
+    assertTrue("String with concatenated nulls must equal simple concatenate",
+        duo.equals(quintet));
+    assertEquals("String with concatenated nulls have same hashcode as simple concatenate",
+        duo.hashCode(), quintet.hashCode());
+
+    ByteString.ByteIterator duoIter = duo.iterator();
+    ByteString.ByteIterator quintetIter = quintet.iterator();
+    boolean stillEqual = true;
+    while (stillEqual && quintetIter.hasNext()) {
+      stillEqual = (duoIter.nextByte() == quintetIter.nextByte());
+    }
+    assertTrue("We must get the same characters by iterating", stillEqual);
+    assertFalse("Iterator must be exhausted", duoIter.hasNext());
+    try {
+      duoIter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+    try {
+      quintetIter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+
+    // Test that even if we force empty strings in as rope leaves in this
+    // configuration, we always get a (possibly Bounded) LiteralByteString
+    // for a length 1 substring.
+    //
+    // It is possible, using the testing factory method to create deeply nested
+    // trees of empty leaves, to make a string that will fail this test.
+    for (int i = 1; i < duo.size(); ++i) {
+      assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+          duo.substring(i - 1, i) instanceof ByteString.LeafByteString);
+    }
+    for (int i = 1; i < quintet.size(); ++i) {
+      assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+          quintet.substring(i - 1, i) instanceof ByteString.LeafByteString);
+    }
+  }
+
+  public void testStartsWith() {
+    byte[] bytes = getTestBytes(1000, 1234L);
+    ByteString string = ByteString.copyFrom(bytes);
+    ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+    ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+    assertTrue(string.startsWith(ByteString.EMPTY));
+    assertTrue(string.startsWith(string));
+    assertTrue(string.startsWith(prefix));
+    assertFalse(string.startsWith(suffix));
+    assertFalse(prefix.startsWith(suffix));
+    assertFalse(suffix.startsWith(prefix));
+    assertFalse(ByteString.EMPTY.startsWith(prefix));
+    assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+  }
+
+  public void testEndsWith() {
+    byte[] bytes = getTestBytes(1000, 1234L);
+    ByteString string = ByteString.copyFrom(bytes);
+    ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+    ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+    assertTrue(string.endsWith(ByteString.EMPTY));
+    assertTrue(string.endsWith(string));
+    assertTrue(string.endsWith(suffix));
+    assertFalse(string.endsWith(prefix));
+    assertFalse(suffix.endsWith(prefix));
+    assertFalse(prefix.endsWith(suffix));
+    assertFalse(ByteString.EMPTY.endsWith(suffix));
+    assertTrue(ByteString.EMPTY.endsWith(ByteString.EMPTY));
+  }
+
+  static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+    List<ByteString> pieces = new ArrayList<ByteString>();
+    // Starting length should be small enough that we'll do some concatenating by
+    // copying if we just concatenate all these pieces together.
+    for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+      length = (length << 1) - 1;
+      if (start + length > referenceBytes.length) {
+        length = referenceBytes.length - start;
+      }
+      pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+    }
+    return pieces;
+  }
+
+  private byte[] substringUsingWriteTo(
+      ByteString data, int offset, int length) throws IOException {
+    ByteArrayOutputStream output = new ByteArrayOutputStream();
+    data.writeTo(output, offset, length);
+    return output.toByteArray();
+  }
+
+  public void testWriteToOutputStream() throws Exception {
+    // Choose a size large enough so when two ByteStrings are concatenated they
+    // won't be merged into one byte array due to some optimizations.
+    final int dataSize = ByteString.CONCATENATE_BY_COPY_SIZE + 1;
+    byte[] data1 = new byte[dataSize];
+    for (int i = 0; i < data1.length; i++) {
+      data1[i] = (byte) 1;
+    }
+    data1[1] = (byte) 11;
+    // Test LiteralByteString.writeTo(OutputStream,int,int)
+    ByteString left = ByteString.wrap(data1);
+    byte[] result = substringUsingWriteTo(left, 1, 1);
+    assertEquals(1, result.length);
+    assertEquals((byte) 11, result[0]);
+
+    byte[] data2 = new byte[dataSize];
+    for (int i = 0; i < data1.length; i++) {
+      data2[i] = (byte) 2;
+    }
+    ByteString right = ByteString.wrap(data2);
+    // Concatenate two ByteStrings to create a RopeByteString.
+    ByteString root = left.concat(right);
+    // Make sure we are actually testing a RopeByteString with a simple tree
+    // structure.
+    assertEquals(1, root.getTreeDepth());
+    // Write parts of the left node.
+    result = substringUsingWriteTo(root, 0, dataSize);
+    assertEquals(dataSize, result.length);
+    assertEquals((byte) 1, result[0]);
+    assertEquals((byte) 1, result[dataSize - 1]);
+    // Write parts of the right node.
+    result = substringUsingWriteTo(root, dataSize, dataSize);
+    assertEquals(dataSize, result.length);
+    assertEquals((byte) 2, result[0]);
+    assertEquals((byte) 2, result[dataSize - 1]);
+    // Write a segment of bytes that runs across both nodes.
+    result = substringUsingWriteTo(root, dataSize / 2, dataSize);
+    assertEquals(dataSize, result.length);
+    assertEquals((byte) 1, result[0]);
+    assertEquals((byte) 1, result[dataSize - dataSize / 2 - 1]);
+    assertEquals((byte) 2, result[dataSize - dataSize / 2]);
+    assertEquals((byte) 2, result[dataSize - 1]);
+  }
+  
+  /**
+   * Tests ByteString uses Arrays based byte copier when running under Hotstop VM.
+   */
+  public void testByteArrayCopier() throws Exception {
+    Field field = ByteString.class.getDeclaredField("byteArrayCopier");
+    field.setAccessible(true);
+    Object byteArrayCopier = field.get(null);
+    assertNotNull(byteArrayCopier);
+    assertTrue(
+        byteArrayCopier.toString(),
+        byteArrayCopier.getClass().getSimpleName().endsWith("ArraysByteArrayCopier"));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
new file mode 100644
index 0000000..cc65d19
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
@@ -0,0 +1,141 @@
+// 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.
+
+package com.google.protobuf;
+
+import proto2_test_check_utf8.TestCheckUtf8.BytesWrapper;
+import proto2_test_check_utf8.TestCheckUtf8.StringWrapper;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize;
+
+import junit.framework.TestCase;
+
+/**
+ * Test that protos generated with file option java_string_check_utf8 do in
+ * fact perform appropriate UTF-8 checks.
+ *
+ * @author jbaum@google.com (Jacob Butcher)
+ */
+public class CheckUtf8Test extends TestCase {
+
+  private static final String UTF8_BYTE_STRING_TEXT = "some text";
+  private static final ByteString UTF8_BYTE_STRING =
+      ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT);
+  private static final ByteString NON_UTF8_BYTE_STRING =
+      ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+
+  public void testBuildRequiredStringWithGoodUtf8() throws Exception {
+    assertEquals(UTF8_BYTE_STRING_TEXT,
+                 StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq());
+  }
+
+  public void testParseRequiredStringWithGoodUtf8() throws Exception {
+    ByteString serialized =
+        BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString();
+    assertEquals(UTF8_BYTE_STRING_TEXT, StringWrapper.parser().parseFrom(serialized).getReq());
+  }
+
+  public void testBuildRequiredStringWithBadUtf8() throws Exception {
+    try {
+      StringWrapper.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testBuildOptionalStringWithBadUtf8() throws Exception {
+    try {
+      StringWrapper.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testBuildRepeatedStringWithBadUtf8() throws Exception {
+    try {
+      StringWrapper.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testParseRequiredStringWithBadUtf8() throws Exception {
+    ByteString serialized =
+        BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+    try {
+      StringWrapper.parser().parseFrom(serialized);
+      fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+    } catch (InvalidProtocolBufferException exception) {
+      assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testBuildRequiredStringWithBadUtf8Size() throws Exception {
+    try {
+      StringWrapperSize.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testBuildOptionalStringWithBadUtf8Size() throws Exception {
+    try {
+      StringWrapperSize.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testBuildRepeatedStringWithBadUtf8Size() throws Exception {
+    try {
+      StringWrapperSize.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+      fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+    } catch (IllegalArgumentException exception) {
+      assertEquals("Byte string is not UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testParseRequiredStringWithBadUtf8Size() throws Exception {
+    ByteString serialized =
+        BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+    try {
+      StringWrapperSize.parser().parseFrom(serialized);
+      fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+    } catch (InvalidProtocolBufferException exception) {
+      assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+    }
+  }
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
new file mode 100644
index 0000000..ca940ce
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -0,0 +1,821 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.BoolMessage;
+import protobuf_unittest.UnittestProto.Int32Message;
+import protobuf_unittest.UnittestProto.Int64Message;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRecursiveMessage;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Unit test for {@link CodedInputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedInputStreamTest extends TestCase {
+  /**
+   * Helper to construct a byte array from a bunch of bytes.  The inputs are
+   * actually ints so that I can use hex notation and not get stupid errors
+   * about precision.
+   */
+  private byte[] bytes(int... bytesAsInts) {
+    byte[] bytes = new byte[bytesAsInts.length];
+    for (int i = 0; i < bytesAsInts.length; i++) {
+      bytes[i] = (byte) bytesAsInts[i];
+    }
+    return bytes;
+  }
+
+  /**
+   * An InputStream which limits the number of bytes it reads at a time.
+   * We use this to make sure that CodedInputStream doesn't screw up when
+   * reading in small blocks.
+   */
+  private static final class SmallBlockInputStream extends FilterInputStream {
+    private final int blockSize;
+
+    public SmallBlockInputStream(byte[] data, int blockSize) {
+      this(new ByteArrayInputStream(data), blockSize);
+    }
+
+    public SmallBlockInputStream(InputStream in, int blockSize) {
+      super(in);
+      this.blockSize = blockSize;
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+      return super.read(b, 0, Math.min(b.length, blockSize));
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+      return super.read(b, off, Math.min(len, blockSize));
+    }
+  }
+
+  private void assertDataConsumed(byte[] data, CodedInputStream input)
+      throws IOException {
+    assertEquals(data.length, input.getTotalBytesRead());
+    assertTrue(input.isAtEnd());
+  }
+
+  /**
+   * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+   * checks that the result matches the given value.
+   */
+  private void assertReadVarint(byte[] data, long value) throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(data);
+    assertEquals((int) value, input.readRawVarint32());
+    assertDataConsumed(data, input);
+
+    input = CodedInputStream.newInstance(data);
+    assertEquals(value, input.readRawVarint64());
+    assertDataConsumed(data, input);
+
+    input = CodedInputStream.newInstance(data);
+    assertEquals(value, input.readRawVarint64SlowPath());
+    assertDataConsumed(data, input);
+
+    input = CodedInputStream.newInstance(data);
+    assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT));
+    assertDataConsumed(data, input);
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertEquals((int) value, input.readRawVarint32());
+      assertDataConsumed(data, input);
+
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertEquals(value, input.readRawVarint64());
+      assertDataConsumed(data, input);
+
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertEquals(value, input.readRawVarint64SlowPath());
+      assertDataConsumed(data, input);
+
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT));
+      assertDataConsumed(data, input);
+    }
+
+    // Try reading direct from an InputStream.  We want to verify that it
+    // doesn't read past the end of the input, so we copy to a new, bigger
+    // array first.
+    byte[] longerData = new byte[data.length + 1];
+    System.arraycopy(data, 0, longerData, 0, data.length);
+    InputStream rawInput = new ByteArrayInputStream(longerData);
+    assertEquals((int) value, CodedInputStream.readRawVarint32(rawInput));
+    assertEquals(1, rawInput.available());
+  }
+
+  /**
+   * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+   * expects them to fail with an InvalidProtocolBufferException whose
+   * description matches the given one.
+   */
+  private void assertReadVarintFailure(
+      InvalidProtocolBufferException expected, byte[] data)
+      throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(data);
+    try {
+      input.readRawVarint32();
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals(expected.getMessage(), e.getMessage());
+    }
+
+    input = CodedInputStream.newInstance(data);
+    try {
+      input.readRawVarint64();
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals(expected.getMessage(), e.getMessage());
+    }
+
+    input = CodedInputStream.newInstance(data);
+    try {
+      input.readRawVarint64SlowPath();
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals(expected.getMessage(), e.getMessage());
+    }
+
+    // Make sure we get the same error when reading direct from an InputStream.
+    try {
+      CodedInputStream.readRawVarint32(new ByteArrayInputStream(data));
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals(expected.getMessage(), e.getMessage());
+    }
+  }
+
+  /** Tests readRawVarint32() and readRawVarint64(). */
+  public void testReadVarint() throws Exception {
+    assertReadVarint(bytes(0x00), 0);
+    assertReadVarint(bytes(0x01), 1);
+    assertReadVarint(bytes(0x7f), 127);
+    // 14882
+    assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+    // 2961488830
+    assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+      (0x0bL << 28));
+
+    // 64-bit
+    // 7256456126
+    assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+      (0x1bL << 28));
+    // 41256202580718336
+    assertReadVarint(
+      bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+      (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+      (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+    // 11964378330978735131
+    assertReadVarint(
+      bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+      (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+      (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+      (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+
+    // Failures
+    assertReadVarintFailure(
+      InvalidProtocolBufferException.malformedVarint(),
+      bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+            0x00));
+    assertReadVarintFailure(
+      InvalidProtocolBufferException.truncatedMessage(),
+      bytes(0x80));
+  }
+
+  /**
+   * Parses the given bytes using readRawLittleEndian32() and checks
+   * that the result matches the given value.
+   */
+  private void assertReadLittleEndian32(byte[] data, int value)
+                                        throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(data);
+    assertEquals(value, input.readRawLittleEndian32());
+    assertTrue(input.isAtEnd());
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertEquals(value, input.readRawLittleEndian32());
+      assertTrue(input.isAtEnd());
+    }
+  }
+
+  /**
+   * Parses the given bytes using readRawLittleEndian64() and checks
+   * that the result matches the given value.
+   */
+  private void assertReadLittleEndian64(byte[] data, long value)
+                                        throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(data);
+    assertEquals(value, input.readRawLittleEndian64());
+    assertTrue(input.isAtEnd());
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(data, blockSize));
+      assertEquals(value, input.readRawLittleEndian64());
+      assertTrue(input.isAtEnd());
+    }
+  }
+
+  /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
+  public void testReadLittleEndian() throws Exception {
+    assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+    assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+    assertReadLittleEndian64(
+      bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+      0x123456789abcdef0L);
+    assertReadLittleEndian64(
+      bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
+      0x9abcdef012345678L);
+  }
+
+  /** Test decodeZigZag32() and decodeZigZag64(). */
+  public void testDecodeZigZag() throws Exception {
+    assertEquals( 0, CodedInputStream.decodeZigZag32(0));
+    assertEquals(-1, CodedInputStream.decodeZigZag32(1));
+    assertEquals( 1, CodedInputStream.decodeZigZag32(2));
+    assertEquals(-2, CodedInputStream.decodeZigZag32(3));
+    assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
+    assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
+    assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
+    assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
+
+    assertEquals( 0, CodedInputStream.decodeZigZag64(0));
+    assertEquals(-1, CodedInputStream.decodeZigZag64(1));
+    assertEquals( 1, CodedInputStream.decodeZigZag64(2));
+    assertEquals(-2, CodedInputStream.decodeZigZag64(3));
+    assertEquals(0x000000003FFFFFFFL,
+                 CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
+    assertEquals(0xFFFFFFFFC0000000L,
+                 CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
+    assertEquals(0x000000007FFFFFFFL,
+                 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
+    assertEquals(0xFFFFFFFF80000000L,
+                 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
+    assertEquals(0x7FFFFFFFFFFFFFFFL,
+                 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+    assertEquals(0x8000000000000000L,
+                 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+  }
+
+  /** Tests reading and parsing a whole message with every field type. */
+  public void testReadWholeMessage() throws Exception {
+    TestAllTypes message = TestUtil.getAllSet();
+
+    byte[] rawBytes = message.toByteArray();
+    assertEquals(rawBytes.length, message.getSerializedSize());
+
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+    TestUtil.assertAllFieldsSet(message2);
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+      message2 = TestAllTypes.parseFrom(
+        new SmallBlockInputStream(rawBytes, blockSize));
+      TestUtil.assertAllFieldsSet(message2);
+    }
+  }
+
+  /** Tests skipField(). */
+  public void testSkipWholeMessage() throws Exception {
+    TestAllTypes message = TestUtil.getAllSet();
+    byte[] rawBytes = message.toByteArray();
+
+    // Create two parallel inputs.  Parse one as unknown fields while using
+    // skipField() to skip each field on the other.  Expect the same tags.
+    CodedInputStream input1 = CodedInputStream.newInstance(rawBytes);
+    CodedInputStream input2 = CodedInputStream.newInstance(rawBytes);
+    UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
+
+    while (true) {
+      int tag = input1.readTag();
+      assertEquals(tag, input2.readTag());
+      if (tag == 0) {
+        break;
+      }
+      unknownFields.mergeFieldFrom(tag, input1);
+      input2.skipField(tag);
+    }
+  }
+
+
+  /**
+   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
+   * exactly up to a limit, this should not break things.
+   */
+  public void testSkipRawBytesBug() throws Exception {
+    byte[] rawBytes = new byte[] { 1, 2 };
+    CodedInputStream input = CodedInputStream.newInstance(rawBytes);
+
+    int limit = input.pushLimit(1);
+    input.skipRawBytes(1);
+    input.popLimit(limit);
+    assertEquals(2, input.readRawByte());
+  }
+
+  /**
+   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
+   * past the end of a buffer with a limit that has been set past the end of
+   * that buffer, this should not break things.
+   */
+  public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+    byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+    CodedInputStream input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(rawBytes, 3));
+
+    int limit = input.pushLimit(4);
+    // In order to expose the bug we need to read at least one byte to prime the
+    // buffer inside the CodedInputStream.
+    assertEquals(1, input.readRawByte());
+    // Skip to the end of the limit.
+    input.skipRawBytes(3);
+    assertTrue(input.isAtEnd());
+    input.popLimit(limit);
+    assertEquals(5, input.readRawByte());
+  }
+
+  public void testReadHugeBlob() throws Exception {
+    // Allocate and initialize a 1MB blob.
+    byte[] blob = new byte[1 << 20];
+    for (int i = 0; i < blob.length; i++) {
+      blob[i] = (byte) i;
+    }
+
+    // Make a message containing it.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    builder.setOptionalBytes(ByteString.copyFrom(blob));
+    TestAllTypes message = builder.build();
+
+    // Serialize and parse it.  Make sure to parse from an InputStream, not
+    // directly from a ByteString, so that CodedInputStream uses buffered
+    // reading.
+    TestAllTypes message2 =
+      TestAllTypes.parseFrom(message.toByteString().newInput());
+
+    assertEquals(message.getOptionalBytes(), message2.getOptionalBytes());
+
+    // Make sure all the other fields were parsed correctly.
+    TestAllTypes message3 = TestAllTypes.newBuilder(message2)
+      .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
+      .build();
+    TestUtil.assertAllFieldsSet(message3);
+  }
+
+  public void testReadMaliciouslyLargeBlob() throws Exception {
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(0x7FFFFFFF);
+    output.writeRawBytes(new byte[32]);  // Pad with a few random bytes.
+    output.flush();
+
+    CodedInputStream input = rawOutput.toByteString().newCodedInput();
+    assertEquals(tag, input.readTag());
+
+    try {
+      input.readBytes();
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException e) {
+      // success.
+    }
+  }
+
+  private TestRecursiveMessage makeRecursiveMessage(int depth) {
+    if (depth == 0) {
+      return TestRecursiveMessage.newBuilder().setI(5).build();
+    } else {
+      return TestRecursiveMessage.newBuilder()
+        .setA(makeRecursiveMessage(depth - 1)).build();
+    }
+  }
+
+  private void assertMessageDepth(TestRecursiveMessage message, int depth) {
+    if (depth == 0) {
+      assertFalse(message.hasA());
+      assertEquals(5, message.getI());
+    } else {
+      assertTrue(message.hasA());
+      assertMessageDepth(message.getA(), depth - 1);
+    }
+  }
+
+  public void testMaliciousRecursion() throws Exception {
+    ByteString data100 = makeRecursiveMessage(100).toByteString();
+    ByteString data101 = makeRecursiveMessage(101).toByteString();
+
+    assertMessageDepth(TestRecursiveMessage.parseFrom(data100), 100);
+
+    try {
+      TestRecursiveMessage.parseFrom(data101);
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException e) {
+      // success.
+    }
+
+    CodedInputStream input = data100.newCodedInput();
+    input.setRecursionLimit(8);
+    try {
+      TestRecursiveMessage.parseFrom(input);
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException e) {
+      // success.
+    }
+  }
+
+  private void checkSizeLimitExceeded(InvalidProtocolBufferException e) {
+      assertEquals(
+          InvalidProtocolBufferException.sizeLimitExceeded().getMessage(),
+          e.getMessage());
+  }
+
+  public void testSizeLimit() throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(
+            TestUtil.getAllSet().toByteString().newInput(), 16));
+    input.setSizeLimit(16);
+
+    try {
+      TestAllTypes.parseFrom(input);
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException expected) {
+      checkSizeLimitExceeded(expected);
+    }
+  }
+
+  public void testResetSizeCounter() throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(new byte[256], 8));
+    input.setSizeLimit(16);
+    input.readRawBytes(16);
+    assertEquals(16, input.getTotalBytesRead());
+
+    try {
+      input.readRawByte();
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException expected) {
+      checkSizeLimitExceeded(expected);
+    }
+
+    input.resetSizeCounter();
+    assertEquals(0, input.getTotalBytesRead());
+    input.readRawByte();  // No exception thrown.
+    input.resetSizeCounter();
+    assertEquals(0, input.getTotalBytesRead());
+    input.readRawBytes(16);
+    assertEquals(16, input.getTotalBytesRead());
+    input.resetSizeCounter();
+
+    try {
+      input.readRawBytes(17);  // Hits limit again.
+      fail("Should have thrown an exception!");
+    } catch (InvalidProtocolBufferException expected) {
+      checkSizeLimitExceeded(expected);
+    }
+  }
+
+  public void testSizeLimitMultipleMessages() throws Exception {
+    byte[] bytes = new byte[256];
+    for (int i = 0; i < bytes.length; i++) {
+      bytes[i] = (byte) i;
+    }
+    CodedInputStream input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(bytes, 7));
+    input.setSizeLimit(16);
+    for (int i = 0; i < 256 / 16; i++) {
+      byte[] message = input.readRawBytes(16);
+      for (int j = 0; j < message.length; j++) {
+        assertEquals(i * 16 + j, message[j] & 0xff);
+      }
+      assertEquals(16, input.getTotalBytesRead());
+      input.resetSizeCounter();
+      assertEquals(0, input.getTotalBytesRead());
+    }
+  }
+
+  public void testReadString() throws Exception {
+    String lorem = "Lorem ipsum dolor sit amet ";
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < 4096; i += lorem.length()) {
+      builder.append(lorem);
+    }
+    lorem = builder.toString().substring(0, 4096);
+    byte[] bytes = lorem.getBytes("UTF-8");
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.flush();
+
+    CodedInputStream input =
+        CodedInputStream.newInstance(
+            new ByteArrayInputStream(rawOutput.toByteString().toByteArray()));
+    assertEquals(tag, input.readTag());
+    String text = input.readString();
+    assertEquals(lorem, text);
+  }
+
+  public void testReadStringRequireUtf8() throws Exception {
+    String lorem = "Lorem ipsum dolor sit amet ";
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < 4096; i += lorem.length()) {
+      builder.append(lorem);
+    }
+    lorem = builder.toString().substring(0, 4096);
+    byte[] bytes = lorem.getBytes("UTF-8");
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.flush();
+
+    CodedInputStream input =
+        CodedInputStream.newInstance(
+            new ByteArrayInputStream(rawOutput.toByteString().toByteArray()));
+    assertEquals(tag, input.readTag());
+    String text = input.readStringRequireUtf8();
+    assertEquals(lorem, text);
+  }
+
+  /**
+   * Tests that if we readString invalid UTF-8 bytes, no exception
+   * is thrown.  Instead, the invalid bytes are replaced with the Unicode
+   * "replacement character" U+FFFD.
+   */
+  public void testReadStringInvalidUtf8() throws Exception {
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[] { (byte) 0x80 });
+    output.flush();
+
+    CodedInputStream input = rawOutput.toByteString().newCodedInput();
+    assertEquals(tag, input.readTag());
+    String text = input.readString();
+    assertEquals(0xfffd, text.charAt(0));
+  }
+
+  /**
+   * Tests that if we readStringRequireUtf8 invalid UTF-8 bytes, an
+   * InvalidProtocolBufferException is thrown.
+   */
+  public void testReadStringRequireUtf8InvalidUtf8() throws Exception {
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[] { (byte) 0x80 });
+    output.flush();
+
+    CodedInputStream input = rawOutput.toByteString().newCodedInput();
+    assertEquals(tag, input.readTag());
+    try {
+      input.readStringRequireUtf8();
+      fail("Expected invalid UTF-8 exception.");
+    } catch (InvalidProtocolBufferException exception) {
+      assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+    }
+  }
+
+  public void testReadFromSlice() throws Exception {
+    byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+    CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
+    assertEquals(0, in.getTotalBytesRead());
+    for (int i = 3; i < 8; i++) {
+      assertEquals(i, in.readRawByte());
+      assertEquals(i - 2, in.getTotalBytesRead());
+    }
+    // eof
+    assertEquals(0, in.readTag());
+    assertEquals(5, in.getTotalBytesRead());
+  }
+
+  public void testInvalidTag() throws Exception {
+    // Any tag number which corresponds to field number zero is invalid and
+    // should throw InvalidProtocolBufferException.
+    for (int i = 0; i < 8; i++) {
+      try {
+        CodedInputStream.newInstance(bytes(i)).readTag();
+        fail("Should have thrown an exception.");
+      } catch (InvalidProtocolBufferException e) {
+        assertEquals(InvalidProtocolBufferException.invalidTag().getMessage(),
+                     e.getMessage());
+      }
+    }
+  }
+
+  public void testReadByteArray() throws Exception {
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+    // Zero-sized bytes field.
+    output.writeRawVarint32(0);
+    // One one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[] { (byte) 23 });
+    // Another one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[] { (byte) 45 });
+    // A bytes field large enough that won't fit into the 4K buffer.
+    final int bytesLength = 16 * 1024;
+    byte[] bytes = new byte[bytesLength];
+    bytes[0] = (byte) 67;
+    bytes[bytesLength - 1] = (byte) 89;
+    output.writeRawVarint32(bytesLength);
+    output.writeRawBytes(bytes);
+
+    output.flush();
+    CodedInputStream inputStream = rawOutput.toByteString().newCodedInput();
+
+    byte[] result = inputStream.readByteArray();
+    assertEquals(0, result.length);
+    result = inputStream.readByteArray();
+    assertEquals(1, result.length);
+    assertEquals((byte) 23, result[0]);
+    result = inputStream.readByteArray();
+    assertEquals(1, result.length);
+    assertEquals((byte) 45, result[0]);
+    result = inputStream.readByteArray();
+    assertEquals(bytesLength, result.length);
+    assertEquals((byte) 67, result[0]);
+    assertEquals((byte) 89, result[bytesLength - 1]);
+  }
+
+  public void testReadByteBuffer() throws Exception {
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+    // Zero-sized bytes field.
+    output.writeRawVarint32(0);
+    // One one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[]{(byte) 23});
+    // Another one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[]{(byte) 45});
+    // A bytes field large enough that won't fit into the 4K buffer.
+    final int bytesLength = 16 * 1024;
+    byte[] bytes = new byte[bytesLength];
+    bytes[0] = (byte) 67;
+    bytes[bytesLength - 1] = (byte) 89;
+    output.writeRawVarint32(bytesLength);
+    output.writeRawBytes(bytes);
+
+    output.flush();
+    CodedInputStream inputStream = rawOutput.toByteString().newCodedInput();
+
+    ByteBuffer result = inputStream.readByteBuffer();
+    assertEquals(0, result.capacity());
+    result = inputStream.readByteBuffer();
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 23, result.get());
+    result = inputStream.readByteBuffer();
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 45, result.get());
+    result = inputStream.readByteBuffer();
+    assertEquals(bytesLength, result.capacity());
+    assertEquals((byte) 67, result.get());
+    result.position(bytesLength - 1);
+    assertEquals((byte) 89, result.get());
+  }
+
+  public void testReadByteBufferAliasing() throws Exception {
+    ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream);
+    // Zero-sized bytes field.
+    output.writeRawVarint32(0);
+    // One one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[]{(byte) 23});
+    // Another one-byte bytes field
+    output.writeRawVarint32(1);
+    output.writeRawBytes(new byte[]{(byte) 45});
+    // A bytes field large enough that won't fit into the 4K buffer.
+    final int bytesLength = 16 * 1024;
+    byte[] bytes = new byte[bytesLength];
+    bytes[0] = (byte) 67;
+    bytes[bytesLength - 1] = (byte) 89;
+    output.writeRawVarint32(bytesLength);
+    output.writeRawBytes(bytes);
+    output.flush();
+    byte[] data = byteArrayStream.toByteArray();
+
+    // Without aliasing
+    CodedInputStream inputStream = CodedInputStream.newInstance(data);
+    ByteBuffer result = inputStream.readByteBuffer();
+    assertEquals(0, result.capacity());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() != data);
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 23, result.get());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() != data);
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 45, result.get());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() != data);
+    assertEquals(bytesLength, result.capacity());
+    assertEquals((byte) 67, result.get());
+    result.position(bytesLength - 1);
+    assertEquals((byte) 89, result.get());
+
+    // Enable aliasing
+    inputStream = CodedInputStream.newInstance(data);
+    inputStream.enableAliasing(true);
+    result = inputStream.readByteBuffer();
+    assertEquals(0, result.capacity());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() == data);
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 23, result.get());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() == data);
+    assertEquals(1, result.capacity());
+    assertEquals((byte) 45, result.get());
+    result = inputStream.readByteBuffer();
+    assertTrue(result.array() == data);
+    assertEquals(bytesLength, result.capacity());
+    assertEquals((byte) 67, result.get());
+    result.position(bytesLength - 1);
+    assertEquals((byte) 89, result.get());
+  }
+
+  public void testCompatibleTypes() throws Exception {
+    long data = 0x100000000L;
+    Int64Message message = Int64Message.newBuilder().setData(data).build();
+    ByteString serialized = message.toByteString();
+
+    // Test int64(long) is compatible with bool(boolean)
+    BoolMessage msg2 = BoolMessage.parseFrom(serialized);
+    assertTrue(msg2.getData());
+
+    // Test int64(long) is compatible with int32(int)
+    Int32Message msg3 = Int32Message.parseFrom(serialized);
+    assertEquals((int) data, msg3.getData());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
new file mode 100644
index 0000000..33aa435
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -0,0 +1,776 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.CodedOutputStream.OutOfSpaceException;
+import protobuf_unittest.UnittestProto.SparseEnumMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit test for {@link CodedOutputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedOutputStreamTest extends TestCase {
+  private interface Coder {
+    CodedOutputStream stream();
+
+    byte[] toByteArray();
+
+    OutputType getOutputType();
+  }
+
+  private static final class OutputStreamCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final ByteArrayOutputStream output;
+
+    OutputStreamCoder(int size) {
+      output = new ByteArrayOutputStream();
+      stream = CodedOutputStream.newInstance(output, size);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      return output.toByteArray();
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.STREAM;
+    }
+  }
+
+  private static final class ArrayCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final byte[] bytes;
+
+    ArrayCoder(int size) {
+      bytes = new byte[size];
+      stream = CodedOutputStream.newInstance(bytes);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      return Arrays.copyOf(bytes, stream.getTotalBytesWritten());
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.ARRAY;
+    }
+  }
+
+  private static final class NioHeapCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final ByteBuffer buffer;
+    private final int initialPosition;
+
+    NioHeapCoder(int size) {
+      this(size, 0);
+    }
+
+    NioHeapCoder(int size, int initialPosition) {
+      this.initialPosition = initialPosition;
+      buffer = ByteBuffer.allocate(size);
+      buffer.position(initialPosition);
+      stream = CodedOutputStream.newInstance(buffer);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      ByteBuffer dup = buffer.duplicate();
+      dup.position(initialPosition);
+      dup.limit(buffer.position());
+
+      byte[] bytes = new byte[dup.remaining()];
+      dup.get(bytes);
+      return bytes;
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.NIO_HEAP;
+    }
+  }
+
+  private static final class NioDirectCoder implements Coder {
+    private final int initialPosition;
+    private final CodedOutputStream stream;
+    private final ByteBuffer buffer;
+
+    NioDirectCoder(int size) {
+      this(size, 0);
+    }
+
+    NioDirectCoder(int size, int initialPosition) {
+      this.initialPosition = initialPosition;
+      buffer = ByteBuffer.allocateDirect(size);
+      buffer.position(initialPosition);
+      stream = CodedOutputStream.newInstance(buffer);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      ByteBuffer dup = buffer.duplicate();
+      dup.position(initialPosition);
+      dup.limit(buffer.position());
+
+      byte[] bytes = new byte[dup.remaining()];
+      dup.get(bytes);
+      return bytes;
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.NIO_DIRECT;
+    }
+  }
+
+  private enum OutputType {
+    ARRAY() {
+      @Override
+      Coder newCoder(int size) {
+        return new ArrayCoder(size);
+      }
+    },
+    NIO_HEAP() {
+      @Override
+      Coder newCoder(int size) {
+        return new NioHeapCoder(size);
+      }
+    },
+    NIO_DIRECT() {
+      @Override
+      Coder newCoder(int size) {
+        return new NioDirectCoder(size);
+      }
+    },
+    STREAM() {
+      @Override
+      Coder newCoder(int size) {
+        return new OutputStreamCoder(size);
+      }
+    };
+
+    abstract Coder newCoder(int size);
+  }
+
+  /** Checks that invariants are maintained for varint round trip input and output. */
+  public void testVarintRoundTrips() throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      assertVarintRoundTrip(outputType, 0L);
+      for (int bits = 0; bits < 64; bits++) {
+        long value = 1L << bits;
+        assertVarintRoundTrip(outputType, value);
+        assertVarintRoundTrip(outputType, value + 1);
+        assertVarintRoundTrip(outputType, value - 1);
+        assertVarintRoundTrip(outputType, -value);
+      }
+    }
+  }
+
+  /** Tests writeRawVarint32() and writeRawVarint64(). */
+  public void testWriteVarint() throws Exception {
+    assertWriteVarint(bytes(0x00), 0);
+    assertWriteVarint(bytes(0x01), 1);
+    assertWriteVarint(bytes(0x7f), 127);
+    // 14882
+    assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+    // 2961488830
+    assertWriteVarint(
+        bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+        (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bL << 28));
+
+    // 64-bit
+    // 7256456126
+    assertWriteVarint(
+        bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+        (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bL << 28));
+    // 41256202580718336
+    assertWriteVarint(
+        bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+        (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43L << 28) | (0x49L << 35)
+        | (0x24L << 42) | (0x49L << 49));
+    // 11964378330978735131
+    assertWriteVarint(
+        bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+        (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bL << 28) | (0x56L << 35)
+        | (0x00L << 42) | (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+  }
+
+  /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
+  public void testWriteLittleEndian() throws Exception {
+    assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+    assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+    assertWriteLittleEndian64(
+        bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L);
+    assertWriteLittleEndian64(
+        bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L);
+  }
+
+  /** Test encodeZigZag32() and encodeZigZag64(). */
+  public void testEncodeZigZag() throws Exception {
+    assertEquals(0, CodedOutputStream.encodeZigZag32(0));
+    assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
+    assertEquals(2, CodedOutputStream.encodeZigZag32(1));
+    assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
+    assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
+    assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
+    assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
+    assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
+
+    assertEquals(0, CodedOutputStream.encodeZigZag64(0));
+    assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
+    assertEquals(2, CodedOutputStream.encodeZigZag64(1));
+    assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
+    assertEquals(0x000000007FFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
+    assertEquals(0x000000007FFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
+    assertEquals(0x00000000FFFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
+    assertEquals(0x00000000FFFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
+    assertEquals(0xFFFFFFFFFFFFFFFEL, CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
+    assertEquals(0xFFFFFFFFFFFFFFFFL, CodedOutputStream.encodeZigZag64(0x8000000000000000L));
+
+    // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
+    // were chosen semi-randomly via keyboard bashing.
+    assertEquals(0, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
+    assertEquals(1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
+    assertEquals(-1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
+    assertEquals(14927, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
+    assertEquals(-3612, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
+
+    assertEquals(0, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
+    assertEquals(1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
+    assertEquals(-1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
+    assertEquals(14927, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
+    assertEquals(-3612, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
+
+    assertEquals(
+        856912304801416L,
+        CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(856912304801416L)));
+    assertEquals(
+        -75123905439571256L,
+        CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-75123905439571256L)));
+  }
+
+  /** Tests writing a whole message with every field type. */
+  public void testWriteWholeMessage() throws Exception {
+    final byte[] expectedBytes = TestUtil.getGoldenMessage().toByteArray();
+    TestAllTypes message = TestUtil.getAllSet();
+
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      assertEqualBytes(outputType, expectedBytes, rawBytes);
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, expectedBytes, coder.toByteArray());
+    }
+  }
+
+  /**
+   * Tests writing a whole message with every packed field type. Ensures the
+   * wire format of packed fields is compatible with C++.
+   */
+  public void testWriteWholePackedFieldsMessage() throws Exception {
+    byte[] expectedBytes = TestUtil.getGoldenPackedFieldsMessage().toByteArray();
+    TestPackedTypes message = TestUtil.getPackedSet();
+
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      assertEqualBytes(outputType, expectedBytes, rawBytes);
+    }
+  }
+
+  /**
+   * Test writing a message containing a negative enum value. This used to
+   * fail because the size was not properly computed as a sign-extended varint.
+   */
+  public void testWriteMessageWithNegativeEnumValue() throws Exception {
+    SparseEnumMessage message =
+        SparseEnumMessage.newBuilder().setSparseEnum(TestSparseEnum.SPARSE_E).build();
+    assertTrue(message.getSparseEnum().getNumber() < 0);
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+      assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+    }
+  }
+
+  /** Test getTotalBytesWritten() */
+  public void testGetTotalBytesWritten() throws Exception {
+    Coder coder = OutputType.STREAM.newCoder(4 * 1024);
+
+    // Write some some bytes (more than the buffer can hold) and verify that totalWritten
+    // is correct.
+    byte[] value = "abcde".getBytes(Internal.UTF_8);
+    for (int i = 0; i < 1024; ++i) {
+      coder.stream().writeRawBytes(value, 0, value.length);
+    }
+    assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten());
+
+    // Now write an encoded string.
+    String string =
+        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+    // Ensure we take the slower fast path.
+    assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length())
+        != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+
+    coder.stream().writeStringNoTag(string);
+    int stringSize = CodedOutputStream.computeStringSizeNoTag(string);
+
+    // Verify that the total bytes written is correct
+    assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalBytesWritten());
+  }
+
+  // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
+  //    this case.
+  public void testWriteStringNoTag_fastpath() throws Exception {
+    int bufferSize = 153;
+    String threeBytesPer = "\u0981";
+    String string = threeBytesPer;
+    for (int i = 0; i < 50; i++) {
+      string += threeBytesPer;
+    }
+    // These checks ensure we will tickle the slower fast path.
+    assertEquals(1, CodedOutputStream.computeUInt32SizeNoTag(string.length()));
+    assertEquals(
+        2, CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+    assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR);
+
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(bufferSize + 2);
+      coder.stream().writeStringNoTag(string);
+      coder.stream().flush();
+    }
+  }
+
+  public void testWriteToByteBuffer() throws Exception {
+    final int bufferSize = 16 * 1024;
+    ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
+    CodedOutputStream codedStream = CodedOutputStream.newInstance(buffer);
+    // Write raw bytes into the ByteBuffer.
+    final int length1 = 5000;
+    for (int i = 0; i < length1; i++) {
+      codedStream.writeRawByte((byte) 1);
+    }
+    final int length2 = 8 * 1024;
+    byte[] data = new byte[length2];
+    for (int i = 0; i < length2; i++) {
+      data[i] = (byte) 2;
+    }
+    codedStream.writeRawBytes(data);
+    final int length3 = bufferSize - length1 - length2;
+    for (int i = 0; i < length3; i++) {
+      codedStream.writeRawByte((byte) 3);
+    }
+    codedStream.flush();
+
+    // Check that data is correctly written to the ByteBuffer.
+    assertEquals(0, buffer.remaining());
+    buffer.flip();
+    for (int i = 0; i < length1; i++) {
+      assertEquals((byte) 1, buffer.get());
+    }
+    for (int i = 0; i < length2; i++) {
+      assertEquals((byte) 2, buffer.get());
+    }
+    for (int i = 0; i < length3; i++) {
+      assertEquals((byte) 3, buffer.get());
+    }
+  }
+
+  public void testWriteByteBuffer() throws Exception {
+    byte[] value = "abcde".getBytes(Internal.UTF_8);
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream);
+    ByteBuffer byteBuffer = ByteBuffer.wrap(value, 0, 1);
+    // This will actually write 5 bytes into the CodedOutputStream as the
+    // ByteBuffer's capacity() is 5.
+    codedStream.writeRawBytes(byteBuffer);
+    // The above call shouldn't affect the ByteBuffer's state.
+    assertEquals(0, byteBuffer.position());
+    assertEquals(1, byteBuffer.limit());
+
+    // The correct way to write part of an array using ByteBuffer.
+    codedStream.writeRawBytes(ByteBuffer.wrap(value, 2, 1).slice());
+
+    codedStream.flush();
+    byte[] result = outputStream.toByteArray();
+    assertEquals(6, result.length);
+    for (int i = 0; i < 5; i++) {
+      assertEquals(value[i], result[i]);
+    }
+    assertEquals(value[2], result[5]);
+  }
+
+  public void testWriteByteArrayWithOffsets() throws Exception {
+    byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);
+    byte[] destination = new byte[4];
+    CodedOutputStream codedStream = CodedOutputStream.newInstance(destination);
+    codedStream.writeByteArrayNoTag(fullArray, 2, 2);
+    assertEqualBytes(OutputType.ARRAY, bytes(0x02, 0x33, 0x44, 0x00), destination);
+    assertEquals(3, codedStream.getTotalBytesWritten());
+  }
+
+  public void testSerializeUtf8_MultipleSmallWrites() throws Exception {
+    final String source = "abcdefghijklmnopqrstuvwxyz";
+
+    // Generate the expected output if the source string is written 2 bytes at a time.
+    ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream();
+    for (int pos = 0; pos < source.length(); pos += 2) {
+      String substr = source.substring(pos, pos + 2);
+      expectedBytesStream.write(2);
+      expectedBytesStream.write(substr.getBytes(Internal.UTF_8));
+    }
+    final byte[] expectedBytes = expectedBytesStream.toByteArray();
+
+    // For each output type, write the source string 2 bytes at a time and verify the output.
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(expectedBytes.length);
+      for (int pos = 0; pos < source.length(); pos += 2) {
+        String substr = source.substring(pos, pos + 2);
+        coder.stream().writeStringNoTag(substr);
+      }
+      coder.stream().flush();
+      assertEqualBytes(outputType, expectedBytes, coder.toByteArray());
+    }
+  }
+
+  public void testSerializeInvalidUtf8() throws Exception {
+    String[] invalidStrings = new String[] {newString(Character.MIN_HIGH_SURROGATE),
+        "foobar" + newString(Character.MIN_HIGH_SURROGATE), newString(Character.MIN_LOW_SURROGATE),
+        "foobar" + newString(Character.MIN_LOW_SURROGATE),
+        newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)};
+
+    CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
+    CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]);
+    CodedOutputStream outputWithByteBuffer =
+        CodedOutputStream.newInstance(ByteBuffer.allocate(10000));
+    for (String s : invalidStrings) {
+      // TODO(dweis): These should all fail; instead they are corrupting data.
+      CodedOutputStream.computeStringSizeNoTag(s);
+      outputWithStream.writeStringNoTag(s);
+      outputWithArray.writeStringNoTag(s);
+      outputWithByteBuffer.writeStringNoTag(s);
+    }
+  }
+
+  // TODO(nathanmittler): This test can be deleted once we properly throw IOException while
+  // encoding invalid UTF-8 strings.
+  public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception {
+    final int notEnoughBytes = 4;
+    CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[notEnoughBytes]);
+    CodedOutputStream outputWithByteBuffer =
+        CodedOutputStream.newInstance(ByteBuffer.allocate(notEnoughBytes));
+
+    String invalidString = newString(Character.MIN_HIGH_SURROGATE, 'f', 'o', 'o', 'b', 'a', 'r');
+    try {
+      outputWithArray.writeStringNoTag(invalidString);
+      fail("Expected OutOfSpaceException");
+    } catch (OutOfSpaceException e) {
+      assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+    }
+    try {
+      outputWithByteBuffer.writeStringNoTag(invalidString);
+      fail("Expected OutOfSpaceException");
+    } catch (OutOfSpaceException e) {
+      assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+    }
+  }
+
+  /** Regression test for https://github.com/google/protobuf/issues/292 */
+  public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+    String testCase = "Foooooooo";
+    assertEquals(
+        CodedOutputStream.computeUInt32SizeNoTag(testCase.length()),
+        CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3));
+    assertEquals(11, CodedOutputStream.computeStringSize(1, testCase));
+    // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+    // An array of size 1 will cause a failure when trying to write the varint.
+    for (OutputType outputType :
+        new OutputType[] {OutputType.ARRAY, OutputType.NIO_HEAP, OutputType.NIO_DIRECT}) {
+      for (int i = 0; i < 11; i++) {
+        Coder coder = outputType.newCoder(i);
+        try {
+          coder.stream().writeString(1, testCase);
+          fail("Should have thrown an out of space exception");
+        } catch (CodedOutputStream.OutOfSpaceException expected) {
+        }
+      }
+    }
+  }
+
+  public void testDifferentStringLengths() throws Exception {
+    // Test string serialization roundtrip using strings of the following lengths,
+    // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+    // char, hence causing the length delimiter varint to sometimes require more
+    // bytes for the Unicode strings than the ASCII string of the same length.
+    int[] lengths = new int[] {
+        0,
+        1,
+        (1 << 4) - 1, // 1 byte for ASCII and Unicode
+        (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+        (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+        (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+        (1 << 17) - 1,
+        // 3 bytes for ASCII and Unicode
+    };
+    for (OutputType outputType : OutputType.values()) {
+      for (int i : lengths) {
+        testEncodingOfString(outputType, 'q', i); // 1 byte per char
+        testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char
+        testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char
+      }
+    }
+  }
+
+  public void testNioEncodersWithInitialOffsets() throws Exception {
+    String value = "abc";
+    for (Coder coder : new Coder[] {new NioHeapCoder(10, 2), new NioDirectCoder(10, 2)}) {
+      coder.stream().writeStringNoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(coder.getOutputType(), new byte[]{3, 'a', 'b', 'c'}, coder.toByteArray());
+    }
+  }
+
+  /**
+   * Parses the given bytes using writeRawLittleEndian32() and checks
+   * that the result matches the given value.
+   */
+  private static void assertWriteLittleEndian32(byte[] data, int value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(data.length);
+      coder.stream().writeFixed32NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(outputType, data, coder.toByteArray());
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      coder.stream().writeFixed32NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+    }
+  }
+
+  /**
+   * Parses the given bytes using writeRawLittleEndian64() and checks
+   * that the result matches the given value.
+   */
+  private static void assertWriteLittleEndian64(byte[] data, long value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(data.length);
+      coder.stream().writeFixed64NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(outputType, data, coder.toByteArray());
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      coder.stream().writeFixed64NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+    }
+  }
+
+  private static String newString(char... chars) {
+    return new String(chars);
+  }
+
+  private static void testEncodingOfString(OutputType outputType, char c, int length)
+      throws Exception {
+    String fullString = fullString(c, length);
+    TestAllTypes testAllTypes = TestAllTypes.newBuilder().setOptionalString(fullString).build();
+    Coder coder = outputType.newCoder(testAllTypes.getSerializedSize());
+    testAllTypes.writeTo(coder.stream());
+    coder.stream().flush();
+    assertEquals(
+        "OuputType: " + outputType,
+        fullString,
+        TestAllTypes.parseFrom(coder.toByteArray()).getOptionalString());
+  }
+
+  private static String fullString(char c, int length) {
+    char[] result = new char[length];
+    Arrays.fill(result, c);
+    return new String(result);
+  }
+
+  /**
+   * Helper to construct a byte array from a bunch of bytes.  The inputs are
+   * actually ints so that I can use hex notation and not get stupid errors
+   * about precision.
+   */
+  private static byte[] bytes(int... bytesAsInts) {
+    byte[] bytes = new byte[bytesAsInts.length];
+    for (int i = 0; i < bytesAsInts.length; i++) {
+      bytes[i] = (byte) bytesAsInts[i];
+    }
+    return bytes;
+  }
+
+  /** Arrays.asList() does not work with arrays of primitives.  :( */
+  private static List<Byte> toList(byte[] bytes) {
+    List<Byte> result = new ArrayList<Byte>();
+    for (byte b : bytes) {
+      result.add(b);
+    }
+    return result;
+  }
+
+  private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) {
+    assertEquals(outputType.name(), toList(a), toList(b));
+  }
+
+  /**
+   * Writes the given value using writeRawVarint32() and writeRawVarint64() and
+   * checks that the result matches the given bytes.
+   */
+  private static void assertWriteVarint(byte[] data, long value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      // Only test 32-bit write if the value fits into an int.
+      if (value == (int) value) {
+        Coder coder = outputType.newCoder(10);
+        coder.stream().writeUInt32NoTag((int) value);
+        coder.stream().flush();
+        assertEqualBytes(outputType, data, coder.toByteArray());
+
+        // Also try computing size.
+        assertEquals(data.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+      }
+
+      {
+        Coder coder = outputType.newCoder(10);
+        coder.stream().writeUInt64NoTag(value);
+        coder.stream().flush();
+        assertEqualBytes(outputType, data, coder.toByteArray());
+
+        // Also try computing size.
+        assertEquals(data.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+      }
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      // Only test 32-bit write if the value fits into an int.
+      if (value == (int) value) {
+        Coder coder = OutputType.STREAM.newCoder(blockSize);
+        coder.stream().writeUInt64NoTag((int) value);
+        coder.stream().flush();
+        assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+
+        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+        CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, blockSize);
+        output.writeUInt32NoTag((int) value);
+        output.flush();
+        assertEqualBytes(OutputType.STREAM, data, rawOutput.toByteArray());
+      }
+
+      {
+        Coder coder = OutputType.STREAM.newCoder(blockSize);
+        coder.stream().writeUInt64NoTag(value);
+        coder.stream().flush();
+        assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+      }
+    }
+  }
+
+  private static void assertVarintRoundTrip(OutputType outputType, long value) throws Exception {
+    {
+      Coder coder = outputType.newCoder(10);
+      coder.stream().writeUInt64NoTag(value);
+      coder.stream().flush();
+      byte[] bytes = coder.toByteArray();
+      assertEquals(
+          outputType.name(), bytes.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+      assertEquals(outputType.name(), value, input.readRawVarint64());
+    }
+
+    if (value == (int) value) {
+      Coder coder = outputType.newCoder(10);
+      coder.stream().writeUInt32NoTag((int) value);
+      coder.stream().flush();
+      byte[] bytes = coder.toByteArray();
+      assertEquals(
+          outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+      assertEquals(outputType.name(), value, input.readRawVarint32());
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
new file mode 100644
index 0000000..ce85ae2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
@@ -0,0 +1,81 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestDeprecatedFields;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+
+/**
+ * Test field deprecation
+ * 
+ * @author birdo@google.com (Roberto Scaramuzzi)
+ */
+public class DeprecatedFieldTest extends TestCase {
+  private String[] deprecatedGetterNames = {
+      "hasDeprecatedInt32",
+      "getDeprecatedInt32"};
+  
+  private String[] deprecatedBuilderGetterNames = {
+      "hasDeprecatedInt32",
+      "getDeprecatedInt32",
+      "clearDeprecatedInt32"};
+  
+  private String[] deprecatedBuilderSetterNames = {
+      "setDeprecatedInt32"}; 
+  
+  public void testDeprecatedField() throws Exception {
+    Class<?> deprecatedFields = TestDeprecatedFields.class;
+    Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
+    for (String name : deprecatedGetterNames) {
+      Method method = deprecatedFields.getMethod(name);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+    for (String name : deprecatedBuilderGetterNames) {
+      Method method = deprecatedFieldsBuilder.getMethod(name);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+    for (String name : deprecatedBuilderSetterNames) {
+      Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+  }
+  
+  private boolean isDeprecated(AnnotatedElement annotated) {
+    return annotated.isAnnotationPresent(Deprecated.class);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
new file mode 100644
index 0000000..ef89b38
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -0,0 +1,800 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Descriptors.ServiceDescriptor;
+import com.google.protobuf.test.UnittestImport;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportEnumForMap;
+import protobuf_unittest.TestCustomOptions;
+import protobuf_unittest.UnittestCustomOptions;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestReservedFields;
+import protobuf_unittest.UnittestProto.TestService;
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit test for {@link Descriptors}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DescriptorsTest extends TestCase {
+
+  // Regression test for bug where referencing a FieldDescriptor.Type value
+  // before a FieldDescriptorProto.Type value would yield a
+  // ExceptionInInitializerError.
+  @SuppressWarnings("unused")
+  private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+  public void testFieldTypeEnumMapping() throws Exception {
+    assertEquals(FieldDescriptor.Type.values().length,
+        FieldDescriptorProto.Type.values().length);
+    for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+      FieldDescriptorProto.Type protoType = type.toProto();
+      assertEquals("TYPE_" + type.name(), protoType.name());
+      assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+    }
+  }
+
+  public void testFileDescriptor() throws Exception {
+    FileDescriptor file = UnittestProto.getDescriptor();
+
+    assertEquals("google/protobuf/unittest.proto", file.getName());
+    assertEquals("protobuf_unittest", file.getPackage());
+
+    assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
+    assertEquals("google/protobuf/unittest.proto",
+                 file.toProto().getName());
+
+    assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
+                 file.getDependencies());
+
+    Descriptor messageType = TestAllTypes.getDescriptor();
+    assertEquals(messageType, file.getMessageTypes().get(0));
+    assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
+    assertNull(file.findMessageTypeByName("NoSuchType"));
+    assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
+    for (int i = 0; i < file.getMessageTypes().size(); i++) {
+      assertEquals(i, file.getMessageTypes().get(i).getIndex());
+    }
+
+    EnumDescriptor enumType = ForeignEnum.getDescriptor();
+    assertEquals(enumType, file.getEnumTypes().get(0));
+    assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
+    assertNull(file.findEnumTypeByName("NoSuchType"));
+    assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
+    assertEquals(Arrays.asList(ImportEnum.getDescriptor(),
+                               ImportEnumForMap.getDescriptor()),
+                 UnittestImport.getDescriptor().getEnumTypes());
+    for (int i = 0; i < file.getEnumTypes().size(); i++) {
+      assertEquals(i, file.getEnumTypes().get(i).getIndex());
+    }
+
+    ServiceDescriptor service = TestService.getDescriptor();
+    assertEquals(service, file.getServices().get(0));
+    assertEquals(service, file.findServiceByName("TestService"));
+    assertNull(file.findServiceByName("NoSuchType"));
+    assertNull(file.findServiceByName("protobuf_unittest.TestService"));
+    assertEquals(Collections.emptyList(),
+                 UnittestImport.getDescriptor().getServices());
+    for (int i = 0; i < file.getServices().size(); i++) {
+      assertEquals(i, file.getServices().get(i).getIndex());
+    }
+
+    FieldDescriptor extension =
+      UnittestProto.optionalInt32Extension.getDescriptor();
+    assertEquals(extension, file.getExtensions().get(0));
+    assertEquals(extension,
+                 file.findExtensionByName("optional_int32_extension"));
+    assertNull(file.findExtensionByName("no_such_ext"));
+    assertNull(file.findExtensionByName(
+      "protobuf_unittest.optional_int32_extension"));
+    assertEquals(Collections.emptyList(),
+                 UnittestImport.getDescriptor().getExtensions());
+    for (int i = 0; i < file.getExtensions().size(); i++) {
+      assertEquals(i, file.getExtensions().get(i).getIndex());
+    }
+  }
+
+  public void testDescriptor() throws Exception {
+    Descriptor messageType = TestAllTypes.getDescriptor();
+    Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
+
+    assertEquals("TestAllTypes", messageType.getName());
+    assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
+    assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
+    assertNull(messageType.getContainingType());
+    assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
+                 messageType.getOptions());
+    assertEquals("TestAllTypes", messageType.toProto().getName());
+
+    assertEquals("NestedMessage", nestedType.getName());
+    assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
+                 nestedType.getFullName());
+    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+    assertEquals(messageType, nestedType.getContainingType());
+
+    FieldDescriptor field = messageType.getFields().get(0);
+    assertEquals("optional_int32", field.getName());
+    assertEquals(field, messageType.findFieldByName("optional_int32"));
+    assertNull(messageType.findFieldByName("no_such_field"));
+    assertEquals(field, messageType.findFieldByNumber(1));
+    assertNull(messageType.findFieldByNumber(571283));
+    for (int i = 0; i < messageType.getFields().size(); i++) {
+      assertEquals(i, messageType.getFields().get(i).getIndex());
+    }
+
+    assertEquals(nestedType, messageType.getNestedTypes().get(0));
+    assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
+    assertNull(messageType.findNestedTypeByName("NoSuchType"));
+    for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
+      assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
+    }
+
+    EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+    assertEquals(enumType, messageType.getEnumTypes().get(0));
+    assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
+    assertNull(messageType.findEnumTypeByName("NoSuchType"));
+    for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
+      assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
+    }
+  }
+
+  public void testFieldDescriptor() throws Exception {
+    Descriptor messageType = TestAllTypes.getDescriptor();
+    FieldDescriptor primitiveField =
+      messageType.findFieldByName("optional_int32");
+    FieldDescriptor enumField =
+      messageType.findFieldByName("optional_nested_enum");
+    FieldDescriptor messageField =
+      messageType.findFieldByName("optional_foreign_message");
+    FieldDescriptor cordField =
+      messageType.findFieldByName("optional_cord");
+    FieldDescriptor extension =
+      UnittestProto.optionalInt32Extension.getDescriptor();
+    FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
+
+    assertEquals("optional_int32", primitiveField.getName());
+    assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
+                 primitiveField.getFullName());
+    assertEquals(1, primitiveField.getNumber());
+    assertEquals(messageType, primitiveField.getContainingType());
+    assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
+    assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
+    assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
+    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+                 primitiveField.getOptions());
+    assertFalse(primitiveField.isExtension());
+    assertEquals("optional_int32", primitiveField.toProto().getName());
+
+    assertEquals("optional_nested_enum", enumField.getName());
+    assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
+    assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
+    assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
+                 enumField.getEnumType());
+
+    assertEquals("optional_foreign_message", messageField.getName());
+    assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
+    assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
+    assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
+
+    assertEquals("optional_cord", cordField.getName());
+    assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
+    assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
+    assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
+                 cordField.getOptions().getCtype());
+
+    assertEquals("optional_int32_extension", extension.getName());
+    assertEquals("protobuf_unittest.optional_int32_extension",
+                 extension.getFullName());
+    assertEquals(1, extension.getNumber());
+    assertEquals(TestAllExtensions.getDescriptor(),
+                 extension.getContainingType());
+    assertEquals(UnittestProto.getDescriptor(), extension.getFile());
+    assertEquals(FieldDescriptor.Type.INT32, extension.getType());
+    assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
+    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+                 extension.getOptions());
+    assertTrue(extension.isExtension());
+    assertEquals(null, extension.getExtensionScope());
+    assertEquals("optional_int32_extension", extension.toProto().getName());
+
+    assertEquals("single", nestedExtension.getName());
+    assertEquals("protobuf_unittest.TestRequired.single",
+                 nestedExtension.getFullName());
+    assertEquals(TestRequired.getDescriptor(),
+                 nestedExtension.getExtensionScope());
+  }
+
+  public void testFieldDescriptorLabel() throws Exception {
+    FieldDescriptor requiredField =
+      TestRequired.getDescriptor().findFieldByName("a");
+    FieldDescriptor optionalField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+    FieldDescriptor repeatedField =
+      TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+
+    assertTrue(requiredField.isRequired());
+    assertFalse(requiredField.isRepeated());
+    assertFalse(optionalField.isRequired());
+    assertFalse(optionalField.isRepeated());
+    assertFalse(repeatedField.isRequired());
+    assertTrue(repeatedField.isRepeated());
+  }
+  
+  public void testFieldDescriptorJsonName() throws Exception {
+    FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
+    FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+    FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+    assertEquals("a", requiredField.getJsonName());
+    assertEquals("optionalInt32", optionalField.getJsonName());
+    assertEquals("repeatedInt32", repeatedField.getJsonName());
+  }
+
+  public void testFieldDescriptorDefault() throws Exception {
+    Descriptor d = TestAllTypes.getDescriptor();
+    assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
+    assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
+    assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
+    assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
+
+    d = TestExtremeDefaultValues.getDescriptor();
+    assertEquals(
+      ByteString.copyFrom(
+        "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
+      d.findFieldByName("escaped_bytes").getDefaultValue());
+    assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
+    assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
+  }
+
+  public void testEnumDescriptor() throws Exception {
+    EnumDescriptor enumType = ForeignEnum.getDescriptor();
+    EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
+
+    assertEquals("ForeignEnum", enumType.getName());
+    assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
+    assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
+    assertNull(enumType.getContainingType());
+    assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
+                 enumType.getOptions());
+
+    assertEquals("NestedEnum", nestedType.getName());
+    assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
+                 nestedType.getFullName());
+    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+    assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
+
+    EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
+    assertEquals(value, enumType.getValues().get(0));
+    assertEquals("FOREIGN_FOO", value.getName());
+    assertEquals("FOREIGN_FOO", value.toString());
+    assertEquals(4, value.getNumber());
+    assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
+    assertEquals(value, enumType.findValueByNumber(4));
+    assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
+    for (int i = 0; i < enumType.getValues().size(); i++) {
+      assertEquals(i, enumType.getValues().get(i).getIndex());
+    }
+  }
+
+  public void testServiceDescriptor() throws Exception {
+    ServiceDescriptor service = TestService.getDescriptor();
+
+    assertEquals("TestService", service.getName());
+    assertEquals("protobuf_unittest.TestService", service.getFullName());
+    assertEquals(UnittestProto.getDescriptor(), service.getFile());
+
+
+    MethodDescriptor fooMethod = service.getMethods().get(0);
+    assertEquals("Foo", fooMethod.getName());
+    assertEquals(UnittestProto.FooRequest.getDescriptor(),
+                 fooMethod.getInputType());
+    assertEquals(UnittestProto.FooResponse.getDescriptor(),
+                 fooMethod.getOutputType());
+    assertEquals(fooMethod, service.findMethodByName("Foo"));
+
+    MethodDescriptor barMethod = service.getMethods().get(1);
+    assertEquals("Bar", barMethod.getName());
+    assertEquals(UnittestProto.BarRequest.getDescriptor(),
+                 barMethod.getInputType());
+    assertEquals(UnittestProto.BarResponse.getDescriptor(),
+                 barMethod.getOutputType());
+    assertEquals(barMethod, service.findMethodByName("Bar"));
+
+    assertNull(service.findMethodByName("NoSuchMethod"));
+
+    for (int i = 0; i < service.getMethods().size(); i++) {
+      assertEquals(i, service.getMethods().get(i).getIndex());
+    }
+  }
+
+
+  public void testCustomOptions() throws Exception {
+    // Get the descriptor indirectly from a dependent proto class. This is to
+    // ensure that when a proto class is loaded, custom options defined in its
+    // dependencies are also properly initialized.
+    Descriptor descriptor =
+        TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
+        .findFieldByName("field").getMessageType();
+
+    assertTrue(
+      descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
+    assertEquals(Integer.valueOf(-56),
+      descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
+
+    FieldDescriptor field = descriptor.findFieldByName("field1");
+    assertNotNull(field);
+
+    assertTrue(
+      field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
+    assertEquals(Long.valueOf(8765432109L),
+      field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
+
+    EnumDescriptor enumType =
+      UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
+
+    assertTrue(
+      enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
+    assertEquals(Integer.valueOf(-789),
+      enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
+
+    ServiceDescriptor service =
+      UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
+
+    assertTrue(
+      service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
+    assertEquals(Long.valueOf(-9876543210L),
+      service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
+
+    MethodDescriptor method = service.findMethodByName("Foo");
+    assertNotNull(method);
+
+    assertTrue(
+      method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
+    assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
+      method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
+  }
+
+  /**
+   * Test that the FieldDescriptor.Type enum is the same as the
+   * WireFormat.FieldType enum.
+   */
+  public void testFieldTypeTablesMatch() throws Exception {
+    FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+    WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+    assertEquals(values1.length, values2.length);
+
+    for (int i = 0; i < values1.length; i++) {
+      assertEquals(values1[i].toString(), values2[i].toString());
+    }
+  }
+
+  /**
+   * Test that the FieldDescriptor.JavaType enum is the same as the
+   * WireFormat.JavaType enum.
+   */
+  public void testJavaTypeTablesMatch() throws Exception {
+    FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+    WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+    assertEquals(values1.length, values2.length);
+
+    for (int i = 0; i < values1.length; i++) {
+      assertEquals(values1[i].toString(), values2[i].toString());
+    }
+  }
+
+  public void testEnormousDescriptor() throws Exception {
+    // The descriptor for this file is larger than 64k, yet it did not cause
+    // a compiler error due to an over-long string literal.
+    assertTrue(
+        UnittestEnormousDescriptor.getDescriptor()
+          .toProto().getSerializedSize() > 65536);
+  }
+
+  /**
+   * Tests that the DescriptorValidationException works as intended.
+   */
+  public void testDescriptorValidatorException() throws Exception {
+    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+      .setName("foo.proto")
+      .addMessageType(DescriptorProto.newBuilder()
+      .setName("Foo")
+        .addField(FieldDescriptorProto.newBuilder()
+          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+          .setType(FieldDescriptorProto.Type.TYPE_INT32)
+          .setName("foo")
+          .setNumber(1)
+          .setDefaultValue("invalid")
+          .build())
+        .build())
+      .build();
+    try {
+      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+          new FileDescriptor[0]);
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      // Expected; check that the error message contains some useful hints
+      assertTrue(e.getMessage().indexOf("foo") != -1);
+      assertTrue(e.getMessage().indexOf("Foo") != -1);
+      assertTrue(e.getMessage().indexOf("invalid") != -1);
+      assertTrue(e.getCause() instanceof NumberFormatException);
+      assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+    }
+  }
+
+  /**
+   * Tests the translate/crosslink for an example where a message field's name
+   * and type name are the same.
+   */
+  public void testDescriptorComplexCrosslink() throws Exception {
+    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+      .setName("foo.proto")
+      .addMessageType(DescriptorProto.newBuilder()
+        .setName("Foo")
+        .addField(FieldDescriptorProto.newBuilder()
+          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+          .setType(FieldDescriptorProto.Type.TYPE_INT32)
+          .setName("foo")
+          .setNumber(1)
+          .build())
+        .build())
+      .addMessageType(DescriptorProto.newBuilder()
+        .setName("Bar")
+        .addField(FieldDescriptorProto.newBuilder()
+          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+          .setTypeName("Foo")
+          .setName("Foo")
+          .setNumber(1)
+          .build())
+        .build())
+      .build();
+    // translate and crosslink
+    FileDescriptor file =
+      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+          new FileDescriptor[0]);
+    // verify resulting descriptors
+    assertNotNull(file);
+    List<Descriptor> msglist = file.getMessageTypes();
+    assertNotNull(msglist);
+    assertTrue(msglist.size() == 2);
+    boolean barFound = false;
+    for (Descriptor desc : msglist) {
+      if (desc.getName().equals("Bar")) {
+        barFound = true;
+        assertNotNull(desc.getFields());
+        List<FieldDescriptor> fieldlist = desc.getFields();
+        assertNotNull(fieldlist);
+        assertTrue(fieldlist.size() == 1);
+        assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+        assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+      }
+    }
+    assertTrue(barFound);
+  }
+
+  public void testDependencyOrder() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto").build();
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .addDependency("foo.proto")
+        .build();
+    FileDescriptorProto bazProto = FileDescriptorProto.newBuilder()
+        .setName("baz.proto")
+        .addDependency("foo.proto")
+        .addDependency("bar.proto")
+        .addPublicDependency(0)
+        .addPublicDependency(1)
+        .build();
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+        new FileDescriptor[0]);
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto,
+        new FileDescriptor[] {fooFile});
+
+    // Items in the FileDescriptor array can be in any order.
+    Descriptors.FileDescriptor.buildFrom(bazProto,
+        new FileDescriptor[] {fooFile, barFile});
+    Descriptors.FileDescriptor.buildFrom(bazProto,
+        new FileDescriptor[] {barFile, fooFile});
+  }
+
+  public void testInvalidPublicDependency() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto").build();
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("boo.proto")
+        .addDependency("foo.proto")
+        .addPublicDependency(1)  // Error, should be 0.
+        .build();
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+        new FileDescriptor[0]);
+    try {
+      Descriptors.FileDescriptor.buildFrom(barProto,
+          new FileDescriptor[] {fooFile});
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      assertTrue(
+          e.getMessage().indexOf("Invalid public dependency index.") != -1);
+    }
+  }
+
+  public void testUnknownFieldsDenied() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+
+    try {
+      Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      assertTrue(e.getMessage().indexOf("Bar") != -1);
+      assertTrue(e.getMessage().indexOf("is not defined") != -1);
+    }
+  }
+
+  public void testUnknownFieldsAllowed() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("bar.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+    Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
+  }
+
+  public void testHiddenDependency() throws Exception {
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+        .build();
+    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+        .setName("forward.proto")
+        .addDependency("bar.proto")
+        .build();
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("forward.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+        forwardProto, new FileDescriptor[] {barFile});
+
+    try {
+      Descriptors.FileDescriptor.buildFrom(
+          fooProto, new FileDescriptor[] {forwardFile});
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      assertTrue(e.getMessage().indexOf("Bar") != -1);
+      assertTrue(e.getMessage().indexOf("is not defined") != -1);
+    }
+  }
+
+  public void testPublicDependency() throws Exception {
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+        .build();
+    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+        .setName("forward.proto")
+        .addDependency("bar.proto")
+        .addPublicDependency(0)
+        .build();
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("forward.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+        forwardProto, new FileDescriptor[]{barFile});
+    Descriptors.FileDescriptor.buildFrom(
+        fooProto, new FileDescriptor[] {forwardFile});
+  }
+
+  /**
+   * Tests the translate/crosslink for an example with a more complex namespace
+   * referencing.
+   */
+  public void testComplexNamespacePublicDependency() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .setPackage("a.b.c.d.bar.shared")
+        .addEnumType(EnumDescriptorProto.newBuilder()
+            .setName("MyEnum")
+            .addValue(EnumValueDescriptorProto.newBuilder()
+                .setName("BLAH")
+                .setNumber(1)))
+        .build();
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("bar.proto")
+        .setPackage("a.b.c.d.foo.shared")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("MyMessage")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+                .setTypeName("bar.shared.MyEnum")
+                .setName("MyField")
+                .setNumber(1)))
+        .build();
+    // translate and crosslink
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+        fooProto, new FileDescriptor[0]);
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[]{fooFile});
+    // verify resulting descriptors
+    assertNotNull(barFile);
+    List<Descriptor> msglist = barFile.getMessageTypes();
+    assertNotNull(msglist);
+    assertTrue(msglist.size() == 1);
+    Descriptor desc = msglist.get(0);
+    if (desc.getName().equals("MyMessage")) {
+      assertNotNull(desc.getFields());
+      List<FieldDescriptor> fieldlist = desc.getFields();
+      assertNotNull(fieldlist);
+      assertTrue(fieldlist.size() == 1);
+      FieldDescriptor field = fieldlist.get(0);
+      assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+      assertTrue(field.getEnumType().getName().equals("MyEnum"));
+      assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+      assertTrue(field.getEnumType().getFile().getPackage().equals(
+          "a.b.c.d.bar.shared"));
+    }
+  }
+
+  public void testOneofDescriptor() throws Exception {
+    Descriptor messageType = TestAllTypes.getDescriptor();
+    FieldDescriptor field =
+        messageType.findFieldByName("oneof_nested_message");
+    OneofDescriptor oneofDescriptor = field.getContainingOneof();
+    assertNotNull(oneofDescriptor);
+    assertSame(oneofDescriptor, messageType.getOneofs().get(0));
+    assertEquals("oneof_field", oneofDescriptor.getName());
+
+    assertEquals(4, oneofDescriptor.getFieldCount());
+    assertSame(oneofDescriptor.getField(1), field);
+
+    assertEquals(4, oneofDescriptor.getFields().size());
+    assertEquals(oneofDescriptor.getFields().get(1), field);
+  }
+
+  public void testMessageDescriptorExtensions() throws Exception {
+    assertFalse(TestAllTypes.getDescriptor().isExtendable());
+    assertTrue(TestAllExtensions.getDescriptor().isExtendable());
+    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable());
+
+    assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3));
+    assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3));
+    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42));
+    assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43));
+    assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142));
+    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
+  }
+
+  public void testReservedFields() {
+    Descriptor d = TestReservedFields.getDescriptor();
+    assertTrue(d.isReservedNumber(2));
+    assertFalse(d.isReservedNumber(8));
+    assertTrue(d.isReservedNumber(9));
+    assertTrue(d.isReservedNumber(10));
+    assertTrue(d.isReservedNumber(11));
+    assertFalse(d.isReservedNumber(12));
+    assertFalse(d.isReservedName("foo"));
+    assertTrue(d.isReservedName("bar"));
+    assertTrue(d.isReservedName("baz"));
+  }
+
+  public void testToString() {
+    assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
+        UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
+            UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString());
+  }
+
+  public void testPackedEnumField() throws Exception {
+    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addEnumType(EnumDescriptorProto.newBuilder()
+          .setName("Enum")
+          .addValue(EnumValueDescriptorProto.newBuilder()
+            .setName("FOO")
+            .setNumber(1)
+            .build())
+          .build())
+        .addMessageType(DescriptorProto.newBuilder()
+          .setName("Message")
+          .addField(FieldDescriptorProto.newBuilder()
+            .setName("foo")
+            .setTypeName("Enum")
+            .setNumber(1)
+            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+            .setOptions(DescriptorProtos.FieldOptions.newBuilder()
+              .setPacked(true)
+              .build())
+            .build())
+          .build())
+        .build();
+    Descriptors.FileDescriptor.buildFrom(
+        fileDescriptorProto, new FileDescriptor[0]);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
new file mode 100644
index 0000000..85b418c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
@@ -0,0 +1,459 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link DoubleArrayList}.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class DoubleArrayListTest extends TestCase {
+  
+  private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1);
+  private static final DoubleArrayList TERTIARY_LIST =
+      newImmutableDoubleArrayList(1, 2, 3);
+  
+  private DoubleArrayList list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new DoubleArrayList();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(DoubleArrayList.emptyList());
+  }
+  
+  public void testMakeImmutable() {
+    list.addDouble(2);
+    list.addDouble(4);
+    list.addDouble(6);
+    list.addDouble(8);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+  
+  public void testModificationWithIteration() {
+    list.addAll(asList(1D, 2D, 3D, 4D));
+    Iterator<Double> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(1D, (double) list.get(0));
+    assertEquals(1D, (double) iterator.next());
+    list.set(0, 1D);
+    assertEquals(2D, (double) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, 0D);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testGet() {
+    assertEquals(1D, (double) TERTIARY_LIST.get(0));
+    assertEquals(2D, (double) TERTIARY_LIST.get(1));
+    assertEquals(3D, (double) TERTIARY_LIST.get(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testGetInt() {
+    assertEquals(1D, TERTIARY_LIST.getDouble(0));
+    assertEquals(2D, TERTIARY_LIST.getDouble(1));
+    assertEquals(3D, TERTIARY_LIST.getDouble(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSize() {
+    assertEquals(0, DoubleArrayList.emptyList().size());
+    assertEquals(1, UNARY_LIST.size());
+    assertEquals(3, TERTIARY_LIST.size());
+
+    list.addDouble(2);
+    list.addDouble(4);
+    list.addDouble(6);
+    list.addDouble(8);
+    assertEquals(4, list.size());
+    
+    list.remove(0);
+    assertEquals(3, list.size());
+    
+    list.add(16D);
+    assertEquals(4, list.size());
+  }
+  
+  public void testSet() {
+    list.addDouble(2);
+    list.addDouble(4);
+    
+    assertEquals(2D, (double) list.set(0, 0D));
+    assertEquals(0D, list.getDouble(0));
+
+    assertEquals(4D, (double) list.set(1, 0D));
+    assertEquals(0D, list.getDouble(1));
+    
+    try {
+      list.set(-1, 0D);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.set(2, 0D);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSetInt() {
+    list.addDouble(2);
+    list.addDouble(4);
+    
+    assertEquals(2D, list.setDouble(0, 0));
+    assertEquals(0D, list.getDouble(0));
+
+    assertEquals(4D, list.setDouble(1, 0));
+    assertEquals(0D, list.getDouble(1));
+    
+    try {
+      list.setDouble(-1, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.setDouble(2, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAdd() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.add(2D));
+    assertEquals(asList(2D), list);
+
+    assertTrue(list.add(3D));
+    list.add(0, 4D);
+    assertEquals(asList(4D, 2D, 3D), list);
+    
+    list.add(0, 1D);
+    list.add(0, 0D);
+    // Force a resize by getting up to 11 elements.
+    for (int i = 0; i < 6; i++) {
+      list.add(Double.valueOf(5 + i));
+    }
+    assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list);
+    
+    try {
+      list.add(-1, 5D);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.add(4, 5D);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAddInt() {
+    assertEquals(0, list.size());
+
+    list.addDouble(2);
+    assertEquals(asList(2D), list);
+
+    list.addDouble(3);
+    assertEquals(asList(2D, 3D), list);
+  }
+  
+  public void testAddAll() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.addAll(Collections.singleton(1D)));
+    assertEquals(1, list.size());
+    assertEquals(1D, (double) list.get(0));
+    assertEquals(1D, list.getDouble(0));
+    
+    assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D)));
+    assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list);
+    
+    assertTrue(list.addAll(TERTIARY_LIST));
+    assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list);
+
+    assertFalse(list.addAll(Collections.<Double>emptyList()));
+    assertFalse(list.addAll(DoubleArrayList.emptyList()));
+  }
+  
+  public void testRemove() {
+    list.addAll(TERTIARY_LIST);
+    assertEquals(1D, (double) list.remove(0));
+    assertEquals(asList(2D, 3D), list);
+
+    assertTrue(list.remove(Double.valueOf(3)));
+    assertEquals(asList(2D), list);
+
+    assertFalse(list.remove(Double.valueOf(3)));
+    assertEquals(asList(2D), list);
+
+    assertEquals(2D, (double) list.remove(0));
+    assertEquals(asList(), list);
+    
+    try {
+      list.remove(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  private void assertImmutable(DoubleArrayList list) {
+    if (list.contains(1D)) {
+      throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+    }
+    
+    try {
+      list.add(1D);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, 1D);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Double>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(1D));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new DoubleArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(1D));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Double>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addDouble(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.<Double>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(1D));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.retainAll(Collections.<Double>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(1D));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, 0D);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.setDouble(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static DoubleArrayList newImmutableDoubleArrayList(double... elements) {
+    DoubleArrayList list = new DoubleArrayList();
+    for (double element : elements) {
+      list.addDouble(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
new file mode 100644
index 0000000..8f3a74c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -0,0 +1,326 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Unit test for {@link DynamicMessage}.  See also {@link MessageTest}, which
+ * tests some {@link DynamicMessage} functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DynamicMessageTest extends TestCase {
+  TestUtil.ReflectionTester reflectionTester =
+    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+  TestUtil.ReflectionTester extensionsReflectionTester =
+    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+                                  TestUtil.getExtensionRegistry());
+  TestUtil.ReflectionTester packedReflectionTester =
+    new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
+
+  public void testDynamicMessageAccessors() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Message message = builder.build();
+    reflectionTester.assertAllFieldsSetViaReflection(message);
+  }
+
+  public void testSettersAfterBuild() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    Message firstMessage = builder.build();
+    // double build()
+    builder.build();
+    // clear() after build()
+    builder.clear();
+    // setters after build()
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Message message = builder.build();
+    reflectionTester.assertAllFieldsSetViaReflection(message);
+    // repeated setters after build()
+    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    message = builder.build();
+    reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+    // firstMessage shouldn't have been modified.
+    reflectionTester.assertClearViaReflection(firstMessage);
+  }
+
+  public void testUnknownFields() throws Exception {
+    Message.Builder builder =
+        DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+    builder.setUnknownFields(UnknownFieldSet.newBuilder()
+        .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+        .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+        .build());
+    Message message = builder.build();
+    assertEquals(2, message.getUnknownFields().asMap().size());
+    // clone() with unknown fields
+    Message.Builder newBuilder = builder.clone();
+    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+    // clear() with unknown fields
+    newBuilder.clear();
+    assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+    // serialize/parse with unknown fields
+    newBuilder.mergeFrom(message.toByteString());
+    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+  }
+
+  public void testDynamicMessageSettersRejectNull() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.assertReflectionSettersRejectNull(builder);
+  }
+
+  public void testDynamicMessageExtensionAccessors() throws Exception {
+    // We don't need to extensively test DynamicMessage's handling of
+    // extensions because, frankly, it doesn't do anything special with them.
+    // It treats them just like any other fields.
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+    extensionsReflectionTester.setAllFieldsViaReflection(builder);
+    Message message = builder.build();
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+  }
+
+  public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+    extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+  }
+
+  public void testDynamicMessageRepeatedSetters() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.setAllFieldsViaReflection(builder);
+    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    Message message = builder.build();
+    reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+  }
+
+  public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+  }
+
+  public void testDynamicMessageDefaults() throws Exception {
+    reflectionTester.assertClearViaReflection(
+      DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
+    reflectionTester.assertClearViaReflection(
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
+  }
+
+  public void testDynamicMessageSerializedSize() throws Exception {
+    TestAllTypes message = TestUtil.getAllSet();
+
+    Message.Builder dynamicBuilder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
+    Message dynamicMessage = dynamicBuilder.build();
+
+    assertEquals(message.getSerializedSize(),
+                 dynamicMessage.getSerializedSize());
+  }
+
+  public void testDynamicMessageSerialization() throws Exception {
+    Message.Builder builder =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Message message = builder.build();
+
+    ByteString rawBytes = message.toByteString();
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+    TestUtil.assertAllFieldsSet(message2);
+
+    // In fact, the serialized forms should be exactly the same, byte-for-byte.
+    assertEquals(TestUtil.getAllSet().toByteString(), rawBytes);
+  }
+
+  public void testDynamicMessageParsing() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    ByteString rawBytes = message.toByteString();
+
+    Message message2 =
+      DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
+    reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+    // Test Parser interface.
+    Message message3 = message2.getParserForType().parseFrom(rawBytes);
+    reflectionTester.assertAllFieldsSetViaReflection(message3);
+  }
+
+  public void testDynamicMessageExtensionParsing() throws Exception {
+    ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+    Message message = DynamicMessage.parseFrom(
+        TestAllExtensions.getDescriptor(), rawBytes,
+        TestUtil.getExtensionRegistry());
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+    // Test Parser interface.
+    Message message2 = message.getParserForType().parseFrom(
+        rawBytes, TestUtil.getExtensionRegistry());
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
+  }
+
+  public void testDynamicMessagePackedSerialization() throws Exception {
+    Message.Builder builder =
+        DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
+    packedReflectionTester.setPackedFieldsViaReflection(builder);
+    Message message = builder.build();
+
+    ByteString rawBytes = message.toByteString();
+    TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+    TestUtil.assertPackedFieldsSet(message2);
+
+    // In fact, the serialized forms should be exactly the same, byte-for-byte.
+    assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
+  }
+
+  public void testDynamicMessagePackedParsing() throws Exception {
+    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+    TestUtil.setPackedFields(builder);
+    TestPackedTypes message = builder.build();
+
+    ByteString rawBytes = message.toByteString();
+
+    Message message2 =
+      DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
+    packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+    // Test Parser interface.
+    Message message3 = message2.getParserForType().parseFrom(rawBytes);
+    packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
+  }
+
+  public void testDynamicMessageCopy() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    DynamicMessage copy = DynamicMessage.newBuilder(message).build();
+    reflectionTester.assertAllFieldsSetViaReflection(copy);
+
+    // Test oneof behavior
+    FieldDescriptor bytesField =
+        TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+    FieldDescriptor uint32Field =
+        TestAllTypes.getDescriptor().findFieldByName("oneof_uint32");
+    assertTrue(copy.hasField(bytesField));
+    assertFalse(copy.hasField(uint32Field));
+    DynamicMessage copy2 =
+        DynamicMessage.newBuilder(message).setField(uint32Field, 123).build();
+    assertFalse(copy2.hasField(bytesField));
+    assertTrue(copy2.hasField(uint32Field));
+    assertEquals(123, copy2.getField(uint32Field));
+  }
+
+  public void testToBuilder() throws Exception {
+    DynamicMessage.Builder builder =
+        DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    reflectionTester.setAllFieldsViaReflection(builder);
+    int unknownFieldNum = 9;
+    long unknownFieldVal = 90;
+    builder.setUnknownFields(UnknownFieldSet.newBuilder()
+        .addField(unknownFieldNum,
+            UnknownFieldSet.Field.newBuilder()
+                .addVarint(unknownFieldVal).build())
+        .build());
+    DynamicMessage message = builder.build();
+
+    DynamicMessage derived = message.toBuilder().build();
+    reflectionTester.assertAllFieldsSetViaReflection(derived);
+    assertEquals(Arrays.asList(unknownFieldVal),
+        derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
+  }
+
+  public void testDynamicOneofMessage() throws Exception {
+    DynamicMessage.Builder builder =
+        DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0);
+    assertFalse(builder.hasOneof(oneof));
+    assertSame(null, builder.getOneofFieldDescriptor(oneof));
+
+    reflectionTester.setAllFieldsViaReflection(builder);
+    assertTrue(builder.hasOneof(oneof));
+    FieldDescriptor field = oneof.getField(3);
+    assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+    DynamicMessage message = builder.buildPartial();
+    assertTrue(message.hasOneof(oneof));
+
+    DynamicMessage.Builder mergedBuilder =
+        DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    FieldDescriptor mergedField = oneof.getField(0);
+    mergedBuilder.setField(mergedField, 123);
+    assertTrue(mergedBuilder.hasField(mergedField));
+    mergedBuilder.mergeFrom(message);
+    assertTrue(mergedBuilder.hasField(field));
+    assertFalse(mergedBuilder.hasField(mergedField));
+
+    builder.clearOneof(oneof);
+    assertSame(null, builder.getOneofFieldDescriptor(oneof));
+    message = builder.build();
+    assertSame(null, message.getOneofFieldDescriptor(oneof));
+  }
+
+  // Regression test for a bug that makes setField() not work for repeated
+  // enum fields.
+  public void testSettersForRepeatedEnumField() throws Exception {
+    DynamicMessage.Builder builder =
+        DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    FieldDescriptor repeatedEnumField =
+        TestAllTypes.getDescriptor().findFieldByName(
+            "repeated_nested_enum");
+    EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor();
+    builder.setField(repeatedEnumField, enumDescriptor.getValues());
+    DynamicMessage message = builder.build();
+    assertEquals(
+        enumDescriptor.getValues(), message.getField(repeatedEnumField));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/EnumTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/EnumTest.java
new file mode 100644
index 0000000..14c7406
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/EnumTest.java
@@ -0,0 +1,76 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+public class EnumTest extends TestCase {
+  
+  public void testForNumber() {
+    ForeignEnum e = ForeignEnum.forNumber(ForeignEnum.FOREIGN_BAR.getNumber());
+    assertEquals(ForeignEnum.FOREIGN_BAR, e);
+
+    e = ForeignEnum.forNumber(1000);
+    assertEquals(null, e);
+  }
+  
+  public void testForNumber_oneof() {
+    TestAllTypes.OneofFieldCase e = TestAllTypes.OneofFieldCase.forNumber(
+        TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber());
+    assertEquals(TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE, e);
+
+    e = TestAllTypes.OneofFieldCase.forNumber(1000);
+    assertEquals(null, e);
+  }
+  
+  public void testForNumberLite() {
+    ForeignEnumLite e = ForeignEnumLite.forNumber(ForeignEnumLite.FOREIGN_LITE_BAR.getNumber());
+    assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, e);
+
+    e = ForeignEnumLite.forNumber(1000);
+    assertEquals(null, e);
+  }
+  
+  public void testForNumberLite_oneof() {
+    TestAllTypesLite.OneofFieldCase e = TestAllTypesLite.OneofFieldCase.forNumber(
+        TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber());
+    assertEquals(TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE, e);
+
+    e = TestAllTypesLite.OneofFieldCase.forNumber(1000);
+    assertEquals(null, e);
+  }
+}
+
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
new file mode 100644
index 0000000..304cec4
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -0,0 +1,373 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
+import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that doesn't support field presence test for optional
+ * non-message fields.
+ */
+public class FieldPresenceTest extends TestCase {
+  private static boolean hasMethod(Class<?> clazz, String name) {
+    try {
+      if (clazz.getMethod(name) != null) {
+        return true;
+      } else {
+        return false;
+      }
+    } catch (NoSuchMethodException e) {
+      return false;
+    }
+  }
+
+  private static void assertHasMethodRemoved(
+      Class<?> classWithFieldPresence,
+      Class<?> classWithoutFieldPresence,
+      String camelName) {
+    assertTrue(hasMethod(classWithFieldPresence, "get" + camelName));
+    assertTrue(hasMethod(classWithFieldPresence, "has" + camelName));
+    assertTrue(hasMethod(classWithoutFieldPresence, "get" + camelName));
+    assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName));
+  }
+
+  public void testHasMethod() {
+    // Optional non-message fields don't have a hasFoo() method generated.
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OptionalInt32");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OptionalString");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OptionalBytes");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OptionalNestedEnum");
+
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OptionalInt32");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OptionalString");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OptionalBytes");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OptionalNestedEnum");
+
+    // message fields still have the hasFoo() method generated.
+    assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
+    assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
+
+    // oneof fields don't have hasFoo() methods (even for message types).
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OneofUint32");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OneofString");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OneofBytes");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.class,
+        TestAllTypes.class,
+        "OneofNestedMessage");
+
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OneofUint32");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OneofString");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OneofBytes");
+    assertHasMethodRemoved(
+        UnittestProto.TestAllTypes.Builder.class,
+        TestAllTypes.Builder.class,
+        "OneofNestedMessage");
+  }
+
+  public void testOneofEquals() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes message1 = builder.build();
+    // Set message2's oneof_uint32 field to defalut value. The two
+    // messages should be different when check with oneof case.
+    builder.setOneofUint32(0);
+    TestAllTypes message2 = builder.build();
+    assertFalse(message1.equals(message2));
+  }
+
+  public void testFieldPresence() {
+    // Optional non-message fields set to their default value are treated the
+    // same way as not set.
+
+    // Serialization will ignore such fields.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalInt32(0);
+    builder.setOptionalString("");
+    builder.setOptionalBytes(ByteString.EMPTY);
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+    TestAllTypes message = builder.build();
+    assertEquals(0, message.getSerializedSize());
+
+    // mergeFrom() will ignore such fields.
+    TestAllTypes.Builder a = TestAllTypes.newBuilder();
+    a.setOptionalInt32(1);
+    a.setOptionalString("x");
+    a.setOptionalBytes(ByteString.copyFromUtf8("y"));
+    a.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+    TestAllTypes.Builder b = TestAllTypes.newBuilder();
+    b.setOptionalInt32(0);
+    b.setOptionalString("");
+    b.setOptionalBytes(ByteString.EMPTY);
+    b.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+    a.mergeFrom(b.build());
+    message = a.build();
+    assertEquals(1, message.getOptionalInt32());
+    assertEquals("x", message.getOptionalString());
+    assertEquals(ByteString.copyFromUtf8("y"), message.getOptionalBytes());
+    assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
+
+    // equals()/hashCode() should produce the same results.
+    TestAllTypes empty = TestAllTypes.newBuilder().build();
+    message = builder.build();
+    assertTrue(empty.equals(message));
+    assertTrue(message.equals(empty));
+    assertEquals(empty.hashCode(), message.hashCode());
+  }
+
+  public void testFieldPresenceByReflection() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+    FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+    FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+    FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+
+    // Field not present.
+    TestAllTypes message = TestAllTypes.newBuilder().build();
+    assertFalse(message.hasField(optionalInt32Field));
+    assertFalse(message.hasField(optionalStringField));
+    assertFalse(message.hasField(optionalBytesField));
+    assertFalse(message.hasField(optionalNestedEnumField));
+    assertEquals(0, message.getAllFields().size());
+
+    // Field set to default value is seen as not present.
+    message = TestAllTypes.newBuilder()
+        .setOptionalInt32(0)
+        .setOptionalString("")
+        .setOptionalBytes(ByteString.EMPTY)
+        .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO)
+        .build();
+    assertFalse(message.hasField(optionalInt32Field));
+    assertFalse(message.hasField(optionalStringField));
+    assertFalse(message.hasField(optionalBytesField));
+    assertFalse(message.hasField(optionalNestedEnumField));
+    assertEquals(0, message.getAllFields().size());
+
+    // Field set to non-default value is seen as present.
+    message = TestAllTypes.newBuilder()
+        .setOptionalInt32(1)
+        .setOptionalString("x")
+        .setOptionalBytes(ByteString.copyFromUtf8("y"))
+        .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR)
+        .build();
+    assertTrue(message.hasField(optionalInt32Field));
+    assertTrue(message.hasField(optionalStringField));
+    assertTrue(message.hasField(optionalBytesField));
+    assertTrue(message.hasField(optionalNestedEnumField));
+    assertEquals(4, message.getAllFields().size());
+  }
+
+  public void testMessageField() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    assertFalse(builder.hasOptionalNestedMessage());
+    assertFalse(builder.build().hasOptionalNestedMessage());
+
+    TestAllTypes.NestedMessage.Builder nestedBuilder =
+        builder.getOptionalNestedMessageBuilder();
+    assertTrue(builder.hasOptionalNestedMessage());
+    assertTrue(builder.build().hasOptionalNestedMessage());
+
+    nestedBuilder.setValue(1);
+    assertEquals(1, builder.build().getOptionalNestedMessage().getValue());
+
+    builder.clearOptionalNestedMessage();
+    assertFalse(builder.hasOptionalNestedMessage());
+    assertFalse(builder.build().hasOptionalNestedMessage());
+
+    // Unlike non-message fields, if we set a message field to its default value (i.e.,
+    // default instance), the field should be seen as present.
+    builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+    assertTrue(builder.hasOptionalNestedMessage());
+    assertTrue(builder.build().hasOptionalNestedMessage());
+  }
+
+  public void testSerializeAndParse() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalInt32(1234);
+    builder.setOptionalString("hello");
+    builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+    // Set an oneof field to its default value and expect it to be serialized (i.e.,
+    // an oneof field set to the default value should be treated as present).
+    builder.setOneofInt32(0);
+    ByteString data = builder.build().toByteString();
+
+    TestAllTypes message = TestAllTypes.parseFrom(data);
+    assertEquals(1234, message.getOptionalInt32());
+    assertEquals("hello", message.getOptionalString());
+    // Fields not set will have the default value.
+    assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+    assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum());
+    // The message field is set despite that it's set with a default instance.
+    assertTrue(message.hasOptionalNestedMessage());
+    assertEquals(0, message.getOptionalNestedMessage().getValue());
+    // The oneof field set to its default value is also present.
+    assertEquals(
+        TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase());
+  }
+
+  // Regression test for b/16173397
+  // Make sure we haven't screwed up the code generation for repeated fields.
+  public void testRepeatedFields() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalInt32(1234);
+    builder.setOptionalString("hello");
+    builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+    builder.addRepeatedInt32(4321);
+    builder.addRepeatedString("world");
+    builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+    ByteString data = builder.build().toByteString();
+
+    TestOptionalFieldsOnly optionalOnlyMessage = TestOptionalFieldsOnly.parseFrom(data);
+    assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+    assertEquals("hello", optionalOnlyMessage.getOptionalString());
+    assertTrue(optionalOnlyMessage.hasOptionalNestedMessage());
+    assertEquals(0, optionalOnlyMessage.getOptionalNestedMessage().getValue());
+
+    TestRepeatedFieldsOnly repeatedOnlyMessage = TestRepeatedFieldsOnly.parseFrom(data);
+    assertEquals(1, repeatedOnlyMessage.getRepeatedInt32Count());
+    assertEquals(4321, repeatedOnlyMessage.getRepeatedInt32(0));
+    assertEquals(1, repeatedOnlyMessage.getRepeatedStringCount());
+    assertEquals("world", repeatedOnlyMessage.getRepeatedString(0));
+    assertEquals(1, repeatedOnlyMessage.getRepeatedNestedMessageCount());
+    assertEquals(0, repeatedOnlyMessage.getRepeatedNestedMessage(0).getValue());
+  }
+
+  public void testIsInitialized() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    // Test optional proto2 message fields.
+    UnittestProto.TestRequired.Builder proto2Builder =
+        builder.getOptionalProto2MessageBuilder();
+    assertFalse(builder.isInitialized());
+    assertFalse(builder.buildPartial().isInitialized());
+
+    proto2Builder.setA(1).setB(2).setC(3);
+    assertTrue(builder.isInitialized());
+    assertTrue(builder.buildPartial().isInitialized());
+
+    // Test oneof proto2 message fields.
+    proto2Builder = builder.getOneofProto2MessageBuilder();
+    assertFalse(builder.isInitialized());
+    assertFalse(builder.buildPartial().isInitialized());
+
+    proto2Builder.setA(1).setB(2).setC(3);
+    assertTrue(builder.isInitialized());
+    assertTrue(builder.buildPartial().isInitialized());
+
+    // Test repeated proto2 message fields.
+    proto2Builder = builder.addRepeatedProto2MessageBuilder();
+    assertFalse(builder.isInitialized());
+    assertFalse(builder.buildPartial().isInitialized());
+
+    proto2Builder.setA(1).setB(2).setC(3);
+    assertTrue(builder.isInitialized());
+    assertTrue(builder.buildPartial().isInitialized());
+  }
+
+
+  // Test that unknown fields are dropped.
+  public void testUnknownFields() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalInt32(1234);
+    builder.addRepeatedInt32(5678);
+    TestAllTypes message = builder.build();
+    ByteString data = message.toByteString();
+
+    TestOptionalFieldsOnly optionalOnlyMessage =
+        TestOptionalFieldsOnly.parseFrom(data);
+    // UnknownFieldSet should be empty.
+    assertEquals(
+        0, optionalOnlyMessage.getUnknownFields().toByteString().size());
+    assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+    message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString());
+    assertEquals(1234, message.getOptionalInt32());
+    // The repeated field is discarded because it's unknown to the optional-only
+    // message.
+    assertEquals(0, message.getRepeatedInt32Count());
+
+    DynamicMessage dynamicOptionalOnlyMessage =
+        DynamicMessage.getDefaultInstance(
+            TestOptionalFieldsOnly.getDescriptor())
+        .getParserForType().parseFrom(data);
+    assertEquals(
+        0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size());
+    assertEquals(optionalOnlyMessage.toByteString(),
+        dynamicOptionalOnlyMessage.toByteString());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
new file mode 100644
index 0000000..88a7574
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
@@ -0,0 +1,459 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link FloatArrayList}.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class FloatArrayListTest extends TestCase {
+  
+  private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1);
+  private static final FloatArrayList TERTIARY_LIST =
+      newImmutableFloatArrayList(1, 2, 3);
+  
+  private FloatArrayList list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new FloatArrayList();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(FloatArrayList.emptyList());
+  }
+  
+  public void testMakeImmutable() {
+    list.addFloat(2);
+    list.addFloat(4);
+    list.addFloat(6);
+    list.addFloat(8);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+  
+  public void testModificationWithIteration() {
+    list.addAll(asList(1F, 2F, 3F, 4F));
+    Iterator<Float> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(1F, (float) list.get(0));
+    assertEquals(1F, (float) iterator.next());
+    list.set(0, 1F);
+    assertEquals(2F, (float) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, 0F);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testGet() {
+    assertEquals(1F, (float) TERTIARY_LIST.get(0));
+    assertEquals(2F, (float) TERTIARY_LIST.get(1));
+    assertEquals(3F, (float) TERTIARY_LIST.get(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testGetFloat() {
+    assertEquals(1F, TERTIARY_LIST.getFloat(0));
+    assertEquals(2F, TERTIARY_LIST.getFloat(1));
+    assertEquals(3F, TERTIARY_LIST.getFloat(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSize() {
+    assertEquals(0, FloatArrayList.emptyList().size());
+    assertEquals(1, UNARY_LIST.size());
+    assertEquals(3, TERTIARY_LIST.size());
+
+    list.addFloat(2);
+    list.addFloat(4);
+    list.addFloat(6);
+    list.addFloat(8);
+    assertEquals(4, list.size());
+    
+    list.remove(0);
+    assertEquals(3, list.size());
+    
+    list.add(16F);
+    assertEquals(4, list.size());
+  }
+  
+  public void testSet() {
+    list.addFloat(2);
+    list.addFloat(4);
+    
+    assertEquals(2F, (float) list.set(0, 0F));
+    assertEquals(0F, list.getFloat(0));
+
+    assertEquals(4F, (float) list.set(1, 0F));
+    assertEquals(0F, list.getFloat(1));
+    
+    try {
+      list.set(-1, 0F);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.set(2, 0F);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSetFloat() {
+    list.addFloat(2);
+    list.addFloat(4);
+    
+    assertEquals(2F, list.setFloat(0, 0));
+    assertEquals(0F, list.getFloat(0));
+
+    assertEquals(4F, list.setFloat(1, 0));
+    assertEquals(0F, list.getFloat(1));
+    
+    try {
+      list.setFloat(-1, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.setFloat(2, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAdd() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.add(2F));
+    assertEquals(asList(2F), list);
+
+    assertTrue(list.add(3F));
+    list.add(0, 4F);
+    assertEquals(asList(4F, 2F, 3F), list);
+    
+    list.add(0, 1F);
+    list.add(0, 0F);
+    // Force a resize by getting up to 11 elements.
+    for (int i = 0; i < 6; i++) {
+      list.add(Float.valueOf(5 + i));
+    }
+    assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list);
+    
+    try {
+      list.add(-1, 5F);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.add(4, 5F);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAddFloat() {
+    assertEquals(0, list.size());
+
+    list.addFloat(2);
+    assertEquals(asList(2F), list);
+
+    list.addFloat(3);
+    assertEquals(asList(2F, 3F), list);
+  }
+  
+  public void testAddAll() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.addAll(Collections.singleton(1F)));
+    assertEquals(1, list.size());
+    assertEquals(1F, (float) list.get(0));
+    assertEquals(1F, list.getFloat(0));
+    
+    assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F)));
+    assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list);
+    
+    assertTrue(list.addAll(TERTIARY_LIST));
+    assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list);
+
+    assertFalse(list.addAll(Collections.<Float>emptyList()));
+    assertFalse(list.addAll(FloatArrayList.emptyList()));
+  }
+  
+  public void testRemove() {
+    list.addAll(TERTIARY_LIST);
+    assertEquals(1F, (float) list.remove(0));
+    assertEquals(asList(2F, 3F), list);
+
+    assertTrue(list.remove(Float.valueOf(3)));
+    assertEquals(asList(2F), list);
+
+    assertFalse(list.remove(Float.valueOf(3)));
+    assertEquals(asList(2F), list);
+
+    assertEquals(2F, (float) list.remove(0));
+    assertEquals(asList(), list);
+    
+    try {
+      list.remove(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  private void assertImmutable(FloatArrayList list) {
+    if (list.contains(1F)) {
+      throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+    }
+    
+    try {
+      list.add(1F);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, 1F);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Float>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(1F));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new FloatArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(1F));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Float>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addFloat(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.<Float>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(1F));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.<Float>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(1F));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, 0F);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.setFloat(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static FloatArrayList newImmutableFloatArrayList(int... elements) {
+    FloatArrayList list = new FloatArrayList();
+    for (int element : elements) {
+      list.addFloat(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
new file mode 100644
index 0000000..b7eaebf
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
@@ -0,0 +1,48 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * A prerun for a test suite that allows running the full protocol buffer
+ * tests in a mode that disables the optimization for not using
+ * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
+ * requested. This allows us to run all the tests through both code paths
+ * and ensures that both code paths produce identical results.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class ForceFieldBuildersPreRun implements Runnable {
+
+  @Override
+  public void run() {
+    GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
new file mode 100644
index 0000000..a9b8b63
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -0,0 +1,1676 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.test.UnittestImport;
+import protobuf_unittest.EnumWithNoOuter;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.MultipleFilesTestProto;
+import protobuf_unittest.NestedExtension.MyNestedExtension;
+import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite;
+import protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
+import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
+import protobuf_unittest.NonNestedExtensionLite;
+import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended;
+import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite;
+import protobuf_unittest.OuterClassNameTest2OuterClass;
+import protobuf_unittest.OuterClassNameTest3OuterClass;
+import protobuf_unittest.OuterClassNameTestOuterClass;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Unit test for generated messages and generated code.  See also
+ * {@link MessageTest}, which tests some generated message functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class GeneratedMessageTest extends TestCase {
+  TestUtil.ReflectionTester reflectionTester =
+    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+  public void testDefaultInstance() throws Exception {
+    assertSame(TestAllTypes.getDefaultInstance(),
+               TestAllTypes.getDefaultInstance().getDefaultInstanceForType());
+    assertSame(TestAllTypes.getDefaultInstance(),
+               TestAllTypes.newBuilder().getDefaultInstanceForType());
+  }
+
+  public void testMessageOrBuilder() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+    TestUtil.assertAllFieldsSet(message);
+  }
+
+  public void testUsingBuilderMultipleTimes() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    // primitive field scalar and repeated
+    builder.setOptionalSfixed64(100);
+    builder.addRepeatedInt32(100);
+    // enum field scalar and repeated
+    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    // proto field scalar and repeated
+    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
+    builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
+
+    TestAllTypes value1 = builder.build();
+
+    assertEquals(100, value1.getOptionalSfixed64());
+    assertEquals(100, value1.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getRepeatedImportEnum(0));
+    assertEquals(1, value1.getOptionalForeignMessage().getC());
+    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+    // Make sure that builder didn't update previously created values
+    builder.setOptionalSfixed64(200);
+    builder.setRepeatedInt32(0, 200);
+    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
+    builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
+    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
+    builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
+
+    TestAllTypes value2 = builder.build();
+
+    // Make sure value1 didn't change.
+    assertEquals(100, value1.getOptionalSfixed64());
+    assertEquals(100, value1.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getRepeatedImportEnum(0));
+    assertEquals(1, value1.getOptionalForeignMessage().getC());
+    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+    // Make sure value2 is correct
+    assertEquals(200, value2.getOptionalSfixed64());
+    assertEquals(200, value2.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+        value2.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+        value2.getRepeatedImportEnum(0));
+    assertEquals(2, value2.getOptionalForeignMessage().getC());
+    assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
+  }
+
+  public void testProtosShareRepeatedArraysIfDidntChange() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addRepeatedInt32(100);
+    builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+
+    TestAllTypes value1 = builder.build();
+    TestAllTypes value2 = value1.toBuilder().build();
+
+    assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List());
+    assertSame(value1.getRepeatedForeignMessageList(),
+        value2.getRepeatedForeignMessageList());
+  }
+
+  public void testRepeatedArraysAreImmutable() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addRepeatedInt32(100);
+    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+    assertIsUnmodifiable(builder.getRepeatedInt32List());
+    assertIsUnmodifiable(builder.getRepeatedImportEnumList());
+    assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(builder.getRepeatedFloatList());
+
+
+    TestAllTypes value = builder.build();
+    assertIsUnmodifiable(value.getRepeatedInt32List());
+    assertIsUnmodifiable(value.getRepeatedImportEnumList());
+    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(value.getRepeatedFloatList());
+  }
+
+  public void testParsedMessagesAreImmutable() throws Exception {
+    TestAllTypes value = TestAllTypes.parser().parseFrom(TestUtil.getAllSet().toByteString());
+    assertIsUnmodifiable(value.getRepeatedInt32List());
+    assertIsUnmodifiable(value.getRepeatedInt64List());
+    assertIsUnmodifiable(value.getRepeatedUint32List());
+    assertIsUnmodifiable(value.getRepeatedUint64List());
+    assertIsUnmodifiable(value.getRepeatedSint32List());
+    assertIsUnmodifiable(value.getRepeatedSint64List());
+    assertIsUnmodifiable(value.getRepeatedFixed32List());
+    assertIsUnmodifiable(value.getRepeatedFixed64List());
+    assertIsUnmodifiable(value.getRepeatedSfixed32List());
+    assertIsUnmodifiable(value.getRepeatedSfixed64List());
+    assertIsUnmodifiable(value.getRepeatedFloatList());
+    assertIsUnmodifiable(value.getRepeatedDoubleList());
+    assertIsUnmodifiable(value.getRepeatedBoolList());
+    assertIsUnmodifiable(value.getRepeatedStringList());
+    assertIsUnmodifiable(value.getRepeatedBytesList());
+    assertIsUnmodifiable(value.getRepeatedGroupList());
+    assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(value.getRepeatedImportMessageList());
+    assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+    assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+    assertIsUnmodifiable(value.getRepeatedImportEnumList());
+  }
+
+  private void assertIsUnmodifiable(List<?> list) {
+    if (list == Collections.emptyList()) {
+      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+    } else {
+      try {
+        list.clear();
+        fail("List wasn't immutable");
+      } catch (UnsupportedOperationException e) {
+        // good
+      }
+    }
+  }
+
+  public void testSettersRejectNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      builder.setOptionalString(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.setOptionalBytes(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.setOptionalNestedMessage(
+          (TestAllTypes.NestedMessage.Builder) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.setOptionalNestedEnum(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.addRepeatedString(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.addRepeatedBytes(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.addRepeatedNestedMessage(
+          (TestAllTypes.NestedMessage.Builder) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.addRepeatedNestedEnum(null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+  }
+
+  public void testRepeatedSetters() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestUtil.modifyRepeatedFields(builder);
+    TestAllTypes message = builder.build();
+    TestUtil.assertRepeatedFieldsModified(message);
+  }
+
+  public void testRepeatedSettersRejectNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    builder.addRepeatedString("one");
+    builder.addRepeatedString("two");
+    try {
+      builder.setRepeatedString(1, null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    builder.addRepeatedBytes(TestUtil.toBytes("one"));
+    builder.addRepeatedBytes(TestUtil.toBytes("two"));
+    try {
+      builder.setRepeatedBytes(1, null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    builder.addRepeatedNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+    builder.addRepeatedNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
+    try {
+      builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.setRepeatedNestedMessage(
+          1, (TestAllTypes.NestedMessage.Builder) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+    try {
+      builder.setRepeatedNestedEnum(1, null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+  }
+
+  public void testRepeatedAppend() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
+    builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+
+    ForeignMessage foreignMessage =
+        ForeignMessage.newBuilder().setC(12).build();
+    builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
+
+    TestAllTypes message = builder.build();
+    assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
+    assertEquals(message.getRepeatedForeignEnumList(),
+        Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+    assertEquals(1, message.getRepeatedForeignMessageCount());
+    assertEquals(12, message.getRepeatedForeignMessage(0).getC());
+  }
+
+  public void testRepeatedAppendRejectsNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    ForeignMessage foreignMessage =
+        ForeignMessage.newBuilder().setC(12).build();
+    try {
+      builder.addAllRepeatedForeignMessage(
+          Arrays.asList(foreignMessage, (ForeignMessage) null));
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    try {
+      builder.addAllRepeatedForeignEnum(
+          Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    try {
+      builder.addAllRepeatedString(Arrays.asList("one", null));
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+
+    try {
+      builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+  }
+  
+  public void testRepeatedAppendIterateOnlyOnce() throws Exception {
+    // Create a Iterable that can only be iterated once.
+    Iterable<String> stringIterable = new Iterable<String>() {
+      private boolean called = false;
+      @Override
+      public Iterator<String> iterator() {
+        if (called) {
+          throw new IllegalStateException();
+        }
+        called = true;
+        return Arrays.asList("one", "two", "three").iterator();
+      }
+    };
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addAllRepeatedString(stringIterable);
+    assertEquals(3, builder.getRepeatedStringCount());
+    assertEquals("one", builder.getRepeatedString(0));
+    assertEquals("two", builder.getRepeatedString(1));
+    assertEquals("three", builder.getRepeatedString(2));
+
+    try {
+      builder.addAllRepeatedString(stringIterable);
+      fail("Exception was not thrown");
+    } catch (IllegalStateException e) {
+      // We expect this exception.
+    }
+  }
+
+  public void testMergeFromOtherRejectsNull() throws Exception {
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      builder.mergeFrom((TestAllTypes) null);
+      fail("Exception was not thrown");
+    } catch (NullPointerException e) {
+      // We expect this exception.
+    }
+  }
+
+  public void testSettingForeignMessageUsingBuilder() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder()
+        // Pass builder for foreign message instance.
+        .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123))
+        .build();
+    TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+        // Create expected version passing foreign message instance explicitly.
+        .setOptionalForeignMessage(
+            ForeignMessage.newBuilder().setC(123).build())
+        .build();
+    // TODO(ngd): Upgrade to using real #equals method once implemented
+    assertEquals(expectedMessage.toString(), message.toString());
+  }
+
+  public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder()
+        // Pass builder for foreign message instance.
+        .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456))
+        .build();
+    TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+        // Create expected version passing foreign message instance explicitly.
+        .addRepeatedForeignMessage(
+            ForeignMessage.newBuilder().setC(456).build())
+        .build();
+    assertEquals(expectedMessage.toString(), message.toString());
+  }
+
+  public void testDefaults() throws Exception {
+    TestUtil.assertClear(TestAllTypes.getDefaultInstance());
+    TestUtil.assertClear(TestAllTypes.newBuilder().build());
+
+    TestExtremeDefaultValues message =
+        TestExtremeDefaultValues.getDefaultInstance();
+    assertEquals("\u1234", message.getUtf8String());
+    assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+    assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+    assertTrue(Double.isNaN(message.getNanDouble()));
+    assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+    assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+    assertTrue(Float.isNaN(message.getNanFloat()));
+    assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
+  }
+
+  public void testClear() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.assertClear(builder);
+    TestUtil.setAllFields(builder);
+    builder.clear();
+    TestUtil.assertClear(builder);
+  }
+
+  public void testReflectionGetters() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    reflectionTester.assertAllFieldsSetViaReflection(builder);
+
+    TestAllTypes message = builder.build();
+    reflectionTester.assertAllFieldsSetViaReflection(message);
+  }
+
+  public void testReflectionSetters() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.setAllFieldsViaReflection(builder);
+    TestUtil.assertAllFieldsSet(builder);
+
+    TestAllTypes message = builder.build();
+    TestUtil.assertAllFieldsSet(message);
+  }
+
+  public void testReflectionSettersRejectNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.assertReflectionSettersRejectNull(builder);
+  }
+
+  public void testReflectionRepeatedSetters() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.setAllFieldsViaReflection(builder);
+    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    TestUtil.assertRepeatedFieldsModified(builder);
+
+    TestAllTypes message = builder.build();
+    TestUtil.assertRepeatedFieldsModified(message);
+  }
+
+  public void testReflectionRepeatedSettersRejectNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+  }
+
+  public void testReflectionDefaults() throws Exception {
+    reflectionTester.assertClearViaReflection(
+      TestAllTypes.getDefaultInstance());
+    reflectionTester.assertClearViaReflection(
+      TestAllTypes.newBuilder().build());
+  }
+
+  public void testReflectionGetOneof() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Descriptors.OneofDescriptor oneof =
+        TestAllTypes.getDescriptor().getOneofs().get(0);
+    Descriptors.FieldDescriptor field =
+        TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+    assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+    TestAllTypes message = builder.build();
+    assertSame(field, message.getOneofFieldDescriptor(oneof));
+  }
+
+  public void testReflectionClearOneof() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Descriptors.OneofDescriptor oneof =
+        TestAllTypes.getDescriptor().getOneofs().get(0);
+    Descriptors.FieldDescriptor field =
+        TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+
+    assertTrue(builder.hasOneof(oneof));
+    assertTrue(builder.hasField(field));
+    builder.clearOneof(oneof);
+    assertFalse(builder.hasOneof(oneof));
+    assertFalse(builder.hasField(field));
+  }
+
+  public void testEnumInterface() throws Exception {
+    assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
+        instanceof ProtocolMessageEnum);
+  }
+
+  public void testEnumMap() throws Exception {
+    Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+    for (ForeignEnum value : ForeignEnum.values()) {
+      assertEquals(value, map.findValueByNumber(value.getNumber()));
+    }
+
+    assertTrue(map.findValueByNumber(12345) == null);
+  }
+
+  public void testParsePackedToUnpacked() throws Exception {
+    TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+    TestUnpackedTypes message =
+      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+    TestUtil.assertUnpackedFieldsSet(message);
+  }
+
+  public void testParseUnpackedToPacked() throws Exception {
+    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+    TestPackedTypes message =
+      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+    TestUtil.assertPackedFieldsSet(message);
+  }
+
+  // =================================================================
+  // Extensions.
+
+  TestUtil.ReflectionTester extensionsReflectionTester =
+    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+                                  TestUtil.getExtensionRegistry());
+
+  public void testExtensionMessageOrBuilder() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    TestUtil.setAllExtensions(builder);
+    TestAllExtensions message = builder.build();
+    TestUtil.assertAllExtensionsSet(message);
+  }
+
+  public void testExtensionRepeatedSetters() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    TestUtil.setAllExtensions(builder);
+    TestUtil.modifyRepeatedExtensions(builder);
+    TestAllExtensions message = builder.build();
+    TestUtil.assertRepeatedExtensionsModified(message);
+  }
+
+  public void testExtensionDefaults() throws Exception {
+    TestUtil.assertExtensionsClear(TestAllExtensions.getDefaultInstance());
+    TestUtil.assertExtensionsClear(TestAllExtensions.newBuilder().build());
+  }
+
+  public void testUnsetRepeatedExtensionGetField() {
+    TestAllExtensions message = TestAllExtensions.getDefaultInstance();
+    Object value;
+
+    value = message.getField(UnittestProto.repeatedStringExtension.getDescriptor());
+    assertTrue(value instanceof List);
+    assertTrue(((List<?>) value).isEmpty());
+    assertIsUnmodifiable((List<?>) value);
+
+    value = message.getField(UnittestProto.repeatedNestedMessageExtension.getDescriptor());
+    assertTrue(value instanceof List);
+    assertTrue(((List<?>) value).isEmpty());
+    assertIsUnmodifiable((List<?>) value);
+  }
+
+  public void testExtensionReflectionGetters() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    TestUtil.setAllExtensions(builder);
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
+
+    TestAllExtensions message = builder.build();
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+  }
+
+  public void testExtensionReflectionSetters() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    extensionsReflectionTester.setAllFieldsViaReflection(builder);
+    TestUtil.assertAllExtensionsSet(builder);
+
+    TestAllExtensions message = builder.build();
+    TestUtil.assertAllExtensionsSet(message);
+  }
+
+  public void testExtensionReflectionSettersRejectNull() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+  }
+
+  public void testExtensionReflectionRepeatedSetters() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    extensionsReflectionTester.setAllFieldsViaReflection(builder);
+    extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    TestUtil.assertRepeatedExtensionsModified(builder);
+
+    TestAllExtensions message = builder.build();
+    TestUtil.assertRepeatedExtensionsModified(message);
+  }
+
+  public void testExtensionReflectionRepeatedSettersRejectNull()
+      throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
+        builder);
+  }
+
+  public void testExtensionReflectionDefaults() throws Exception {
+    extensionsReflectionTester.assertClearViaReflection(
+      TestAllExtensions.getDefaultInstance());
+    extensionsReflectionTester.assertClearViaReflection(
+      TestAllExtensions.newBuilder().build());
+  }
+
+  public void testClearExtension() throws Exception {
+    // clearExtension() is not actually used in TestUtil, so try it manually.
+    assertFalse(
+      TestAllExtensions.newBuilder()
+        .setExtension(UnittestProto.optionalInt32Extension, 1)
+        .clearExtension(UnittestProto.optionalInt32Extension)
+        .hasExtension(UnittestProto.optionalInt32Extension));
+    assertEquals(0,
+      TestAllExtensions.newBuilder()
+        .addExtension(UnittestProto.repeatedInt32Extension, 1)
+        .clearExtension(UnittestProto.repeatedInt32Extension)
+        .getExtensionCount(UnittestProto.repeatedInt32Extension));
+  }
+
+  public void testExtensionCopy() throws Exception {
+    TestAllExtensions original = TestUtil.getAllExtensionsSet();
+    TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+    TestUtil.assertAllExtensionsSet(copy);
+  }
+
+  public void testExtensionMergeFrom() throws Exception {
+    TestAllExtensions original =
+      TestAllExtensions.newBuilder()
+        .setExtension(UnittestProto.optionalInt32Extension, 1).build();
+    TestAllExtensions merged =
+        TestAllExtensions.newBuilder().mergeFrom(original).build();
+    assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
+    assertEquals(
+        1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
+  }
+
+  // =================================================================
+  // Lite Extensions.
+
+  // We test lite extensions directly because they have a separate
+  // implementation from full extensions.  In contrast, we do not test
+  // lite fields directly since they are implemented exactly the same as
+  // regular fields.
+
+  public void testLiteExtensionMessageOrBuilder() throws Exception {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    TestUtilLite.setAllExtensions(builder);
+    TestUtil.assertAllExtensionsSet(builder);
+
+    TestAllExtensionsLite message = builder.build();
+    TestUtil.assertAllExtensionsSet(message);
+  }
+
+  public void testLiteExtensionRepeatedSetters() throws Exception {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    TestUtilLite.setAllExtensions(builder);
+    TestUtilLite.modifyRepeatedExtensions(builder);
+    TestUtil.assertRepeatedExtensionsModified(builder);
+
+    TestAllExtensionsLite message = builder.build();
+    TestUtil.assertRepeatedExtensionsModified(message);
+  }
+
+  public void testLiteExtensionDefaults() throws Exception {
+    TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
+    TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
+  }
+
+  public void testClearLiteExtension() throws Exception {
+    // clearExtension() is not actually used in TestUtil, so try it manually.
+    assertFalse(
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
+        .clearExtension(UnittestLite.optionalInt32ExtensionLite)
+        .hasExtension(UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(0,
+      TestAllExtensionsLite.newBuilder()
+        .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
+        .clearExtension(UnittestLite.repeatedInt32ExtensionLite)
+        .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
+  }
+
+  public void testLiteExtensionCopy() throws Exception {
+    TestAllExtensionsLite original = TestUtilLite.getAllLiteExtensionsSet();
+    TestAllExtensionsLite copy =
+        TestAllExtensionsLite.newBuilder(original).build();
+    TestUtil.assertAllExtensionsSet(copy);
+  }
+
+  public void testLiteExtensionMergeFrom() throws Exception {
+    TestAllExtensionsLite original =
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
+    TestAllExtensionsLite merged =
+        TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
+    assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
+  }
+
+  // =================================================================
+  // multiple_files_test
+
+  // Test that custom options of an file level enum are properly initialized.
+  // This test needs to be put before any other access to MultipleFilesTestProto
+  // or messages defined in multiple_files_test.proto because the class loading
+  // order affects initialization process of custom options.
+  public void testEnumValueOptionsInMultipleFilesMode() throws Exception {
+    assertEquals(12345, EnumWithNoOuter.FOO.getValueDescriptor().getOptions()
+        .getExtension(MultipleFilesTestProto.enumValueOption).intValue());
+  }
+
+  public void testMultipleFilesOption() throws Exception {
+    // We mostly just want to check that things compile.
+    MessageWithNoOuter message =
+      MessageWithNoOuter.newBuilder()
+        .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1))
+        .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1))
+        .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
+        .setForeignEnum(EnumWithNoOuter.BAR)
+        .build();
+    assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString()));
+
+    assertEquals(MultipleFilesTestProto.getDescriptor(),
+                 MessageWithNoOuter.getDescriptor().getFile());
+
+    Descriptors.FieldDescriptor field =
+      MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum");
+    assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(),
+                 message.getField(field));
+
+    assertEquals(MultipleFilesTestProto.getDescriptor(),
+                 ServiceWithNoOuter.getDescriptor().getFile());
+
+    assertFalse(
+      TestAllExtensions.getDefaultInstance().hasExtension(
+        MultipleFilesTestProto.extensionWithOuter));
+  }
+
+  public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize()
+    throws Exception {
+    TestOptionalOptimizedForSize message =
+        TestOptionalOptimizedForSize.getDefaultInstance();
+    assertTrue(message.isInitialized());
+
+    message = TestOptionalOptimizedForSize.newBuilder().setO(
+        TestRequiredOptimizedForSize.newBuilder().buildPartial()
+        ).buildPartial();
+    assertFalse(message.isInitialized());
+
+    message = TestOptionalOptimizedForSize.newBuilder().setO(
+        TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()
+        ).buildPartial();
+    assertTrue(message.isInitialized());
+  }
+
+  public void testUninitializedExtensionInOptimizedForSize()
+      throws Exception {
+    TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+    builder.setExtension(TestOptimizedForSize.testExtension2,
+        TestRequiredOptimizedForSize.newBuilder().buildPartial());
+    assertFalse(builder.isInitialized());
+    assertFalse(builder.buildPartial().isInitialized());
+
+    builder = TestOptimizedForSize.newBuilder();
+    builder.setExtension(TestOptimizedForSize.testExtension2,
+        TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial());
+    assertTrue(builder.isInitialized());
+    assertTrue(builder.buildPartial().isInitialized());
+  }
+
+  public void testToBuilder() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+    TestUtil.assertAllFieldsSet(message);
+    TestUtil.assertAllFieldsSet(message.toBuilder().build());
+  }
+
+  public void testFieldConstantValues() throws Exception {
+    assertEquals(TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1);
+    assertEquals(TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1);
+    assertEquals(TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16);
+    assertEquals(TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18);
+    assertEquals(TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21);
+    assertEquals(TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31);
+    assertEquals(TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46);
+    assertEquals(TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48);
+    assertEquals(TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51);
+  }
+
+  public void testExtensionConstantValues() throws Exception {
+    assertEquals(UnittestProto.TestRequired.SINGLE_FIELD_NUMBER, 1000);
+    assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001);
+    assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1);
+    assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16);
+    assertEquals(
+      UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18);
+    assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21);
+    assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31);
+    assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46);
+    assertEquals(
+      UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
+    assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
+  }
+
+  public void testRecursiveMessageDefaultInstance() throws Exception {
+    UnittestProto.TestRecursiveMessage message =
+        UnittestProto.TestRecursiveMessage.getDefaultInstance();
+    assertTrue(message != null);
+    assertNotNull(message.getA());
+    assertTrue(message.getA() == message);
+  }
+
+  public void testSerialize() throws Exception {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes expected = builder.build();
+    ObjectOutputStream out = new ObjectOutputStream(baos);
+    try {
+      out.writeObject(expected);
+    } finally {
+      out.close();
+    }
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    ObjectInputStream in = new ObjectInputStream(bais);
+    TestAllTypes actual = (TestAllTypes) in.readObject();
+    assertEquals(expected, actual);
+  }
+
+  public void testSerializePartial() throws Exception {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes expected = builder.buildPartial();
+    ObjectOutputStream out = new ObjectOutputStream(baos);
+    try {
+      out.writeObject(expected);
+    } finally {
+      out.close();
+    }
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    ObjectInputStream in = new ObjectInputStream(bais);
+    TestAllTypes actual = (TestAllTypes) in.readObject();
+    assertEquals(expected, actual);
+  }
+
+  public void testEnumValues() {
+     assertEquals(
+         TestAllTypes.NestedEnum.BAR.getNumber(),
+         TestAllTypes.NestedEnum.BAR_VALUE);
+    assertEquals(
+        TestAllTypes.NestedEnum.BAZ.getNumber(),
+        TestAllTypes.NestedEnum.BAZ_VALUE);
+    assertEquals(
+        TestAllTypes.NestedEnum.FOO.getNumber(),
+        TestAllTypes.NestedEnum.FOO_VALUE);
+  }
+
+  public void testNonNestedExtensionInitialization() {
+    assertTrue(NonNestedExtension.nonNestedExtension
+               .getMessageDefaultInstance() instanceof MyNonNestedExtension);
+    assertEquals("nonNestedExtension",
+                 NonNestedExtension.nonNestedExtension.getDescriptor().getName());
+  }
+
+  public void testNestedExtensionInitialization() {
+    assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
+               instanceof MessageToBeExtended);
+    assertEquals("recursiveExtension",
+                 MyNestedExtension.recursiveExtension.getDescriptor().getName());
+  }
+
+  public void testNonNestedExtensionLiteInitialization() {
+    assertTrue(NonNestedExtensionLite.nonNestedExtensionLite
+               .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite);
+  }
+
+  public void testNestedExtensionLiteInitialization() {
+    assertTrue(MyNestedExtensionLite.recursiveExtensionLite
+               .getMessageDefaultInstance() instanceof MessageLiteToBeExtended);
+  }
+
+  public void testInvalidations() throws Exception {
+    GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+    TestAllTypes.NestedMessage nestedMessage1 =
+        TestAllTypes.NestedMessage.newBuilder().build();
+    TestAllTypes.NestedMessage nestedMessage2 =
+        TestAllTypes.NestedMessage.newBuilder().build();
+
+    // Set all three flavors (enum, primitive, message and singular/repeated)
+    // and verify no invalidations fired
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+    TestAllTypes.Builder builder = (TestAllTypes.Builder)
+        ((GeneratedMessage) TestAllTypes.getDefaultInstance()).
+            newBuilderForType(mockParent);
+    builder.setOptionalInt32(1);
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+    builder.setOptionalNestedMessage(nestedMessage1);
+    builder.addRepeatedInt32(1);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+    builder.addRepeatedNestedMessage(nestedMessage1);
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    // Now tell it we want changes and make sure it's only fired once
+    // And do this for each flavor
+
+    // primitive single
+    builder.buildPartial();
+    builder.setOptionalInt32(2);
+    builder.setOptionalInt32(3);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    // enum single
+    builder.buildPartial();
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+    assertEquals(2, mockParent.getInvalidationCount());
+
+    // message single
+    builder.buildPartial();
+    builder.setOptionalNestedMessage(nestedMessage2);
+    builder.setOptionalNestedMessage(nestedMessage1);
+    assertEquals(3, mockParent.getInvalidationCount());
+
+    // primitive repeated
+    builder.buildPartial();
+    builder.addRepeatedInt32(2);
+    builder.addRepeatedInt32(3);
+    assertEquals(4, mockParent.getInvalidationCount());
+
+    // enum repeated
+    builder.buildPartial();
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    assertEquals(5, mockParent.getInvalidationCount());
+
+    // message repeated
+    builder.buildPartial();
+    builder.addRepeatedNestedMessage(nestedMessage2);
+    builder.addRepeatedNestedMessage(nestedMessage1);
+    assertEquals(6, mockParent.getInvalidationCount());
+
+  }
+
+  public void testInvalidations_Extensions() throws Exception {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+    TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
+        ((GeneratedMessage) TestAllExtensions.getDefaultInstance()).
+            newBuilderForType(mockParent);
+
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2);
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    // Now tell it we want changes and make sure it's only fired once
+    builder.buildPartial();
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 2);
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 3);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    builder.buildPartial();
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 4);
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 1, 5);
+    assertEquals(2, mockParent.getInvalidationCount());
+
+    builder.buildPartial();
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    assertEquals(3, mockParent.getInvalidationCount());
+  }
+
+  public void testBaseMessageOrBuilder() {
+    // Mostly just makes sure the base interface exists and has some methods.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes message = builder.buildPartial();
+    TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
+    TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
+
+    assertEquals(
+        messageAsInterface.getDefaultBool(),
+        messageAsInterface.getDefaultBool());
+    assertEquals(
+        messageAsInterface.getOptionalDouble(),
+        messageAsInterface.getOptionalDouble());
+  }
+
+  public void testMessageOrBuilderGetters() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    // single fields
+    assertSame(ForeignMessage.getDefaultInstance(),
+        builder.getOptionalForeignMessageOrBuilder());
+    ForeignMessage.Builder subBuilder =
+        builder.getOptionalForeignMessageBuilder();
+    assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
+
+    // repeated fields
+    ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
+    ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
+    ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
+    builder.addRepeatedForeignMessage(m0);
+    builder.addRepeatedForeignMessage(m1);
+    builder.addRepeatedForeignMessage(m2);
+    assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
+    assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
+    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+    ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
+    ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
+    assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
+    assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
+    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+
+    List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
+        builder.getRepeatedForeignMessageOrBuilderList();
+    assertSame(b0, messageOrBuilderList.get(0));
+    assertSame(b1, messageOrBuilderList.get(1));
+    assertSame(m2, messageOrBuilderList.get(2));
+  }
+
+  public void testGetFieldBuilder() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("optional_nested_message");
+    FieldDescriptor foreignFieldDescriptor =
+        descriptor.findFieldByName("optional_foreign_message");
+    FieldDescriptor importFieldDescriptor =
+        descriptor.findFieldByName("optional_import_message");
+
+    // Mutate the message with new field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+    Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+        .mergeFrom((Message) builder1.getField(fieldDescriptor));
+    FieldDescriptor subFieldDescriptor1 =
+        fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder1.setField(subFieldDescriptor1, 1);
+    builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+        foreignFieldDescriptor)
+        .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+    FieldDescriptor subForeignFieldDescriptor1 =
+        foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+    builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+        importFieldDescriptor)
+        .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+    FieldDescriptor subImportFieldDescriptor1 =
+        importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+    builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+    Message newMessage1 = builder1.build();
+
+    // Mutate the message with existing field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+    Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+    FieldDescriptor subFieldDescriptor2 =
+        fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder2.setField(subFieldDescriptor2, 1);
+    builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+        foreignFieldDescriptor)
+        .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+    FieldDescriptor subForeignFieldDescriptor2 =
+        foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+    builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+        importFieldDescriptor)
+        .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+    FieldDescriptor subImportFieldDescriptor2 =
+        importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+    builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+    Message newMessage2 = builder2.build();
+
+    // These two messages should be equal.
+    assertEquals(newMessage1, newMessage2);
+  }
+
+  public void testGetFieldBuilderWithInitializedValue() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("optional_nested_message");
+
+    // Before setting field, builder is initialized by default value. 
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    NestedMessage.Builder fieldBuilder =
+        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+    assertEquals(0, fieldBuilder.getBb());
+
+    // Setting field value with new field builder instance.
+    builder = TestAllTypes.newBuilder();
+    NestedMessage.Builder newFieldBuilder =
+        builder.getOptionalNestedMessageBuilder();
+    newFieldBuilder.setBb(2);
+    // Then get the field builder instance by getFieldBuilder().
+    fieldBuilder =
+        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+    // It should contain new value.
+    assertEquals(2, fieldBuilder.getBb());
+    // These two builder should be equal.
+    assertSame(fieldBuilder, newFieldBuilder);
+  }
+
+  public void testGetFieldBuilderNotSupportedException() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("optional_nested_enum"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("repeated_nested_enum"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("repeated_nested_message"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+  }
+
+  // Test that when the default outer class name conflicts with another type
+  // defined in the proto the compiler will append a suffix to avoid the
+  // conflict.
+  public void testConflictingOuterClassName() {
+    // We just need to make sure we can refer to the outer class with the
+    // expected name. There is nothing else to test.
+    OuterClassNameTestOuterClass.OuterClassNameTest message =
+        OuterClassNameTestOuterClass.OuterClassNameTest.newBuilder().build();
+    assertTrue(message.getDescriptorForType() ==
+        OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor());
+
+    OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2
+        message2 = OuterClassNameTest2OuterClass.TestMessage2.NestedMessage
+            .OuterClassNameTest2.newBuilder().build();
+    assertEquals(0, message2.getSerializedSize());
+
+    OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3
+        enumValue = OuterClassNameTest3OuterClass.TestMessage3.NestedMessage
+            .OuterClassNameTest3.DUMMY_VALUE;
+    assertEquals(1, enumValue.getNumber());
+  }
+
+  // =================================================================
+  // oneof generated code test
+  public void testOneofEnumCase() throws Exception {
+    TestOneof2 message = TestOneof2.newBuilder()
+        .setFooInt(123).setFooString("foo").setFooCord("bar").build();
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+  }
+
+  public void testClearOneof() throws Exception {
+    TestOneof2.Builder builder = TestOneof2.newBuilder().setFooInt(123);
+    assertEquals(TestOneof2.FooCase.FOO_INT, builder.getFooCase());
+    builder.clearFoo();
+    assertEquals(TestOneof2.FooCase.FOO_NOT_SET, builder.getFooCase());
+  }
+
+  public void testSetOneofClearsOthers() throws Exception {
+    TestOneof2.Builder builder = TestOneof2.newBuilder();
+    TestOneof2 message =
+        builder.setFooInt(123).setFooString("foo").buildPartial();
+    assertTrue(message.hasFooString());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooCord("bar").buildPartial();
+    assertTrue(message.hasFooCord());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooStringPiece("baz").buildPartial();
+    assertTrue(message.hasFooStringPiece());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooBytes(TestUtil.toBytes("qux")).buildPartial();
+    assertTrue(message.hasFooBytes());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooEnum(TestOneof2.NestedEnum.FOO).buildPartial();
+    assertTrue(message.hasFooEnum());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooMessage(
+        TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).buildPartial();
+    assertTrue(message.hasFooMessage());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+
+    message = builder.setFooInt(123).buildPartial();
+    assertTrue(message.hasFooInt());
+    TestUtil.assertAtMostOneFieldSetOneof(message);
+  }
+
+  public void testOneofTypes() throws Exception {
+    // Primitive
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooInt(), 0);
+      assertFalse(builder.hasFooInt());
+      assertTrue(builder.setFooInt(123).hasFooInt());
+      assertEquals(builder.getFooInt(), 123);
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooInt());
+      assertEquals(message.getFooInt(), 123);
+
+      assertFalse(builder.clearFooInt().hasFooInt());
+      TestOneof2 message2 = builder.build();
+      assertFalse(message2.hasFooInt());
+      assertEquals(message2.getFooInt(), 0);
+    }
+
+    // Enum
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO);
+      assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum());
+      assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR);
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooEnum());
+      assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR);
+
+      assertFalse(builder.clearFooEnum().hasFooEnum());
+      TestOneof2 message2 = builder.build();
+      assertFalse(message2.hasFooEnum());
+      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO);
+    }
+
+    // String
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooString(), "");
+      builder.setFooString("foo");
+      assertTrue(builder.hasFooString());
+      assertEquals(builder.getFooString(), "foo");
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooString());
+      assertEquals(message.getFooString(), "foo");
+      assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo"));
+
+      assertFalse(builder.clearFooString().hasFooString());
+      TestOneof2 message2 = builder.buildPartial();
+      assertFalse(message2.hasFooString());
+      assertEquals(message2.getFooString(), "");
+      assertEquals(message2.getFooStringBytes(), TestUtil.toBytes(""));
+
+      // Get method should not change the oneof value.
+      builder.setFooInt(123);
+      assertEquals(builder.getFooString(), "");
+      assertEquals(builder.getFooStringBytes(), TestUtil.toBytes(""));
+      assertEquals(123, builder.getFooInt());
+
+      message = builder.build();
+      assertEquals(message.getFooString(), "");
+      assertEquals(message.getFooStringBytes(), TestUtil.toBytes(""));
+      assertEquals(123, message.getFooInt());
+    }
+
+    // Cord
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooCord(), "");
+      builder.setFooCord("foo");
+      assertTrue(builder.hasFooCord());
+      assertEquals(builder.getFooCord(), "foo");
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooCord());
+      assertEquals(message.getFooCord(), "foo");
+      assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo"));
+
+      assertFalse(builder.clearFooCord().hasFooCord());
+      TestOneof2 message2 = builder.build();
+      assertFalse(message2.hasFooCord());
+      assertEquals(message2.getFooCord(), "");
+      assertEquals(message2.getFooCordBytes(), TestUtil.toBytes(""));
+    }
+
+    // StringPiece
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooStringPiece(), "");
+      builder.setFooStringPiece("foo");
+      assertTrue(builder.hasFooStringPiece());
+      assertEquals(builder.getFooStringPiece(), "foo");
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooStringPiece());
+      assertEquals(message.getFooStringPiece(), "foo");
+      assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo"));
+
+      assertFalse(builder.clearFooStringPiece().hasFooStringPiece());
+      TestOneof2 message2 = builder.build();
+      assertFalse(message2.hasFooStringPiece());
+      assertEquals(message2.getFooStringPiece(), "");
+      assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes(""));
+    }
+
+    // Message
+    {
+      // set
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      assertEquals(builder.getFooMessage().getQuxInt(), 0);
+      builder.setFooMessage(
+          TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
+      assertTrue(builder.hasFooMessage());
+      assertEquals(builder.getFooMessage().getQuxInt(), 234);
+      TestOneof2 message = builder.buildPartial();
+      assertTrue(message.hasFooMessage());
+      assertEquals(message.getFooMessage().getQuxInt(), 234);
+
+      // clear
+      assertFalse(builder.clearFooMessage().hasFooString());
+      message = builder.build();
+      assertFalse(message.hasFooMessage());
+      assertEquals(message.getFooMessage().getQuxInt(), 0);
+
+      // nested builder
+      builder = TestOneof2.newBuilder();
+      assertSame(builder.getFooMessageOrBuilder(),
+          TestOneof2.NestedMessage.getDefaultInstance());
+      assertFalse(builder.hasFooMessage());
+      builder.getFooMessageBuilder().setQuxInt(123);
+      assertTrue(builder.hasFooMessage());
+      assertEquals(builder.getFooMessage().getQuxInt(), 123);
+      message = builder.build();
+      assertTrue(message.hasFooMessage());
+      assertEquals(message.getFooMessage().getQuxInt(), 123);
+    }
+
+    // LazyMessage is tested in LazyMessageLiteTest.java
+  }
+
+  public void testOneofMerge() throws Exception {
+    // Primitive Type
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooInt(123).build();
+      TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+      assertTrue(message2.hasFooInt());
+      assertEquals(message2.getFooInt(), 123);
+    }
+
+    // String
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooString("foo").build();
+      TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+      assertTrue(message2.hasFooString());
+      assertEquals(message2.getFooString(), "foo");
+    }
+
+    // Enum
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+      TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+      assertTrue(message2.hasFooEnum());
+      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+    }
+
+    // Message
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooMessage(
+          TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+      TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+      assertTrue(message2.hasFooMessage());
+      assertEquals(message2.getFooMessage().getQuxInt(), 234);
+    }
+  }
+
+  public void testOneofSerialization() throws Exception {
+    // Primitive Type
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooInt(123).build();
+      ByteString serialized = message.toByteString();
+      TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+      assertTrue(message2.hasFooInt());
+      assertEquals(message2.getFooInt(), 123);
+    }
+
+    // String
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooString("foo").build();
+      ByteString serialized = message.toByteString();
+      TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+      assertTrue(message2.hasFooString());
+      assertEquals(message2.getFooString(), "foo");
+    }
+
+    // Enum
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+      ByteString serialized = message.toByteString();
+      TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+      assertTrue(message2.hasFooEnum());
+      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+    }
+
+    // Message
+    {
+      TestOneof2.Builder builder = TestOneof2.newBuilder();
+      TestOneof2 message = builder.setFooMessage(
+          TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+      ByteString serialized = message.toByteString();
+      TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+      assertTrue(message2.hasFooMessage());
+      assertEquals(message2.getFooMessage().getQuxInt(), 234);
+    }
+  }
+
+  public void testOneofNestedBuilderOnChangePropagation() {
+    NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder();
+    TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder();
+    builder.getOneofNestedMessageBuilder();
+    assertTrue(builder.hasOneofNestedMessage());
+    assertTrue(parentBuilder.hasPayload());
+    NestedTestAllTypes message = parentBuilder.build();
+    assertTrue(message.hasPayload());
+    assertTrue(message.getPayload().hasOneofNestedMessage());
+  }
+
+  public void testGetRepeatedFieldBuilder() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("repeated_nested_message");
+    FieldDescriptor foreignFieldDescriptor =
+        descriptor.findFieldByName("repeated_foreign_message");
+    FieldDescriptor importFieldDescriptor =
+        descriptor.findFieldByName("repeated_import_message");
+
+    // Mutate the message with new field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+    Message.Builder fieldBuilder1 = builder1.newBuilderForField(
+        fieldDescriptor);
+    FieldDescriptor subFieldDescriptor1 =
+        fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder1.setField(subFieldDescriptor1, 1);
+    builder1.addRepeatedField(fieldDescriptor, fieldBuilder1.build());
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+        foreignFieldDescriptor);
+    FieldDescriptor subForeignFieldDescriptor1 =
+        foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+    builder1.addRepeatedField(foreignFieldDescriptor,
+        foreignFieldBuilder1.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+        importFieldDescriptor);
+    FieldDescriptor subImportFieldDescriptor1 =
+        importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+    builder1.addRepeatedField(importFieldDescriptor,
+        importFieldBuilder1.build());
+
+    Message newMessage1 = builder1.build();
+
+    // Mutate the message with existing field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+    builder2.addRepeatedNestedMessageBuilder();
+    Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder(
+        fieldDescriptor, 0);
+    FieldDescriptor subFieldDescriptor2 =
+        fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder2.setField(subFieldDescriptor2, 1);
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+        foreignFieldDescriptor);
+    FieldDescriptor subForeignFieldDescriptor2 =
+        foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+    builder2.addRepeatedField(foreignFieldDescriptor,
+        foreignFieldBuilder2.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+        importFieldDescriptor);
+    FieldDescriptor subImportFieldDescriptor2 =
+        importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+    builder2.addRepeatedField(importFieldDescriptor,
+        importFieldBuilder2.build());
+
+    Message newMessage2 = builder2.build();
+
+    // These two messages should be equal.
+    assertEquals(newMessage1, newMessage2);
+  }
+
+  public void testGetRepeatedFieldBuilderWithInitializedValue() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("repeated_nested_message");
+
+    // Before setting field, builder is initialized by default value. 
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addRepeatedNestedMessageBuilder();
+    NestedMessage.Builder fieldBuilder =
+        (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+    assertEquals(0, fieldBuilder.getBb());
+
+    // Setting field value with new field builder instance.
+    builder = TestAllTypes.newBuilder();
+    NestedMessage.Builder newFieldBuilder =
+        builder.addRepeatedNestedMessageBuilder();
+    newFieldBuilder.setBb(2);
+    // Then get the field builder instance by getRepeatedFieldBuilder().
+    fieldBuilder =
+        (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+    // It should contain new value.
+    assertEquals(2, fieldBuilder.getBb());
+    // These two builder should be equal.
+    assertSame(fieldBuilder, newFieldBuilder);
+  }
+
+  public void testGetRepeatedFieldBuilderNotSupportedException() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0);
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getRepeatedFieldBuilder(
+          descriptor.findFieldByName("repeated_nested_enum"), 0);
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0);
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getRepeatedFieldBuilder(
+          descriptor.findFieldByName("optional_nested_enum"), 0);
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getRepeatedFieldBuilder(
+          descriptor.findFieldByName("optional_nested_message"), 0);
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
new file mode 100644
index 0000000..efb8f3e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
@@ -0,0 +1,459 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link IntArrayList}.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class IntArrayListTest extends TestCase {
+  
+  private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1);
+  private static final IntArrayList TERTIARY_LIST =
+      newImmutableIntArrayList(1, 2, 3);
+  
+  private IntArrayList list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new IntArrayList();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(IntArrayList.emptyList(), IntArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(IntArrayList.emptyList());
+  }
+  
+  public void testMakeImmutable() {
+    list.addInt(2);
+    list.addInt(4);
+    list.addInt(6);
+    list.addInt(8);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+
+  public void testModificationWithIteration() {
+    list.addAll(asList(1, 2, 3, 4));
+    Iterator<Integer> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(1, (int) list.get(0));
+    assertEquals(1, (int) iterator.next());
+    list.set(0, 1);
+    assertEquals(2, (int) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+
+    iterator = list.iterator();
+    list.add(0, 0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testGet() {
+    assertEquals(1, (int) TERTIARY_LIST.get(0));
+    assertEquals(2, (int) TERTIARY_LIST.get(1));
+    assertEquals(3, (int) TERTIARY_LIST.get(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testGetInt() {
+    assertEquals(1, TERTIARY_LIST.getInt(0));
+    assertEquals(2, TERTIARY_LIST.getInt(1));
+    assertEquals(3, TERTIARY_LIST.getInt(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSize() {
+    assertEquals(0, IntArrayList.emptyList().size());
+    assertEquals(1, UNARY_LIST.size());
+    assertEquals(3, TERTIARY_LIST.size());
+
+    list.addInt(2);
+    list.addInt(4);
+    list.addInt(6);
+    list.addInt(8);
+    assertEquals(4, list.size());
+    
+    list.remove(0);
+    assertEquals(3, list.size());
+    
+    list.add(16);
+    assertEquals(4, list.size());
+  }
+  
+  public void testSet() {
+    list.addInt(2);
+    list.addInt(4);
+    
+    assertEquals(2, (int) list.set(0, 0));
+    assertEquals(0, list.getInt(0));
+
+    assertEquals(4, (int) list.set(1, 0));
+    assertEquals(0, list.getInt(1));
+    
+    try {
+      list.set(-1, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.set(2, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSetInt() {
+    list.addInt(2);
+    list.addInt(4);
+    
+    assertEquals(2, list.setInt(0, 0));
+    assertEquals(0, list.getInt(0));
+
+    assertEquals(4, list.setInt(1, 0));
+    assertEquals(0, list.getInt(1));
+    
+    try {
+      list.setInt(-1, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.setInt(2, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAdd() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.add(2));
+    assertEquals(asList(2), list);
+
+    assertTrue(list.add(3));
+    list.add(0, 4);
+    assertEquals(asList(4, 2, 3), list);
+    
+    list.add(0, 1);
+    list.add(0, 0);
+    // Force a resize by getting up to 11 elements.
+    for (int i = 0; i < 6; i++) {
+      list.add(5 + i);
+    }
+    assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list);
+    
+    try {
+      list.add(-1, 5);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.add(4, 5);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAddInt() {
+    assertEquals(0, list.size());
+
+    list.addInt(2);
+    assertEquals(asList(2), list);
+
+    list.addInt(3);
+    assertEquals(asList(2, 3), list);
+  }
+  
+  public void testAddAll() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.addAll(Collections.singleton(1)));
+    assertEquals(1, list.size());
+    assertEquals(1, (int) list.get(0));
+    assertEquals(1, list.getInt(0));
+    
+    assertTrue(list.addAll(asList(2, 3, 4, 5, 6)));
+    assertEquals(asList(1, 2, 3, 4, 5, 6), list);
+    
+    assertTrue(list.addAll(TERTIARY_LIST));
+    assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list);
+
+    assertFalse(list.addAll(Collections.<Integer>emptyList()));
+    assertFalse(list.addAll(IntArrayList.emptyList()));
+  }
+  
+  public void testRemove() {
+    list.addAll(TERTIARY_LIST);
+    assertEquals(1, (int) list.remove(0));
+    assertEquals(asList(2, 3), list);
+
+    assertTrue(list.remove(Integer.valueOf(3)));
+    assertEquals(asList(2), list);
+
+    assertFalse(list.remove(Integer.valueOf(3)));
+    assertEquals(asList(2), list);
+
+    assertEquals(2, (int) list.remove(0));
+    assertEquals(asList(), list);
+    
+    try {
+      list.remove(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  private void assertImmutable(IntArrayList list) {
+    if (list.contains(1)) {
+      throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+    }
+    
+    try {
+      list.add(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, 1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new IntArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addInt(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.setInt(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static IntArrayList newImmutableIntArrayList(int... elements) {
+    IntArrayList list = new IntArrayList();
+    for (int element : elements) {
+      list.addInt(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
new file mode 100644
index 0000000..756049b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
@@ -0,0 +1,186 @@
+// 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.
+
+package com.google.protobuf;
+
+import static com.google.protobuf.IsValidUtf8TestUtil.DIRECT_NIO_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT;
+import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT;
+import static com.google.protobuf.IsValidUtf8TestUtil.HEAP_NIO_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.LITERAL_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.testBytes;
+
+import com.google.protobuf.IsValidUtf8TestUtil.ByteStringFactory;
+import com.google.protobuf.IsValidUtf8TestUtil.Shard;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
+ * brute force tests that actually test every permutation of one byte, two byte,
+ * and three byte sequences to ensure that the method produces the right result
+ * for every possible byte encoding where "right" means it's consistent with
+ * java's UTF-8 string encoding/decoding such that the method returns true for
+ * any sequence that will round trip when converted to a String and then back to
+ * bytes and will return false for any sequence that will not round trip.
+ * See also {@link IsValidUtf8FourByteTest}. It also includes some
+ * other more targeted tests.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+public class IsValidUtf8Test extends TestCase {
+  /**
+   * Tests that round tripping of all two byte permutations work.
+   */
+  public void testIsValidUtf8_1Byte() {
+    testBytes(LITERAL_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+    testBytes(HEAP_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+    testBytes(DIRECT_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+  }
+
+  /**
+   * Tests that round tripping of all two byte permutations work.
+   */
+  public void testIsValidUtf8_2Bytes() {
+    testBytes(LITERAL_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+    testBytes(HEAP_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+    testBytes(DIRECT_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+  }
+
+  /**
+   * Tests that round tripping of all three byte permutations work.
+   */
+  public void testIsValidUtf8_3Bytes() {
+    // Travis' OOM killer doesn't like this test
+    if (System.getenv("TRAVIS") == null) {
+      testBytes(LITERAL_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+      testBytes(HEAP_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+      testBytes(DIRECT_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+    }
+  }
+
+  /**
+   * Tests that round tripping of a sample of four byte permutations work.
+   * All permutations are prohibitively expensive to test for automated runs;
+   * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
+   * tests specific four-byte cases.
+   */
+  public void testIsValidUtf8_4BytesSamples() {
+    // Valid 4 byte.
+    assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);
+
+    // Bad trailing bytes
+    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
+    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);
+
+    // Special cases for byte2
+    assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
+    assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
+  }
+
+  /**
+   * Tests some hard-coded test cases.
+   */
+  public void testSomeSequences() {
+    // Empty
+    assertTrue(asBytes("").isValidUtf8());
+
+    // One-byte characters, including control characters
+    assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());
+
+    // Two-byte characters
+    assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());
+
+    // Three-byte characters
+    assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());
+
+    // Four-byte characters
+    assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());
+
+    // Mixed string
+    assertTrue(asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62").isValidUtf8());
+
+    // Not a valid string
+    assertInvalidUtf8(-1, 0, -1, 0);
+  }
+
+  private byte[] toByteArray(int... bytes) {
+    byte[] realBytes = new byte[bytes.length];
+    for (int i = 0; i < bytes.length; i++) {
+      realBytes[i] = (byte) bytes[i];
+    }
+    return realBytes;
+  }
+
+  private void assertValidUtf8(ByteStringFactory factory, int[] bytes, boolean not) {
+    byte[] realBytes = toByteArray(bytes);
+    assertTrue(not ^ Utf8.isValidUtf8(realBytes));
+    assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
+    ByteString leaf = factory.newByteString(realBytes);
+    ByteString sub = leaf.substring(0, bytes.length);
+    assertTrue(not ^ leaf.isValidUtf8());
+    assertTrue(not ^ sub.isValidUtf8());
+    ByteString[] ropes = {
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, leaf),
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
+        RopeByteString.newInstanceForTest(leaf, ByteString.EMPTY),
+        RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
+        RopeByteString.newInstanceForTest(sub, leaf)};
+    for (ByteString rope : ropes) {
+      assertTrue(not ^ rope.isValidUtf8());
+    }
+  }
+
+  private void assertValidUtf8(int... bytes) {
+    assertValidUtf8(LITERAL_FACTORY, bytes, false);
+    assertValidUtf8(HEAP_NIO_FACTORY, bytes, false);
+    assertValidUtf8(DIRECT_NIO_FACTORY, bytes, false);
+  }
+
+  private void assertInvalidUtf8(int... bytes) {
+    assertValidUtf8(LITERAL_FACTORY, bytes, true);
+    assertValidUtf8(HEAP_NIO_FACTORY, bytes, true);
+    assertValidUtf8(DIRECT_NIO_FACTORY, bytes, true);
+  }
+
+  private static ByteString asBytes(String s) {
+    return ByteString.copyFromUtf8(s);
+  }
+
+  public void testShardsHaveExpectedRoundTrippables() {
+    // A sanity check.
+    int actual = 0;
+    for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
+      actual += shard.expected;
+    }
+    assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
new file mode 100644
index 0000000..16a808b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
@@ -0,0 +1,448 @@
+// 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.
+
+package com.google.protobuf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.ref.SoftReference;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Logger;
+
+/**
+ * Shared testing code for {@link IsValidUtf8Test} and
+ * {@link IsValidUtf8FourByteTest}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+final class IsValidUtf8TestUtil {
+  private static Logger logger = Logger.getLogger(IsValidUtf8TestUtil.class.getName());
+
+  private IsValidUtf8TestUtil() {}
+
+  static interface ByteStringFactory {
+    ByteString newByteString(byte[] bytes);
+  }
+
+  static final ByteStringFactory LITERAL_FACTORY = new ByteStringFactory() {
+    @Override
+    public ByteString newByteString(byte[] bytes) {
+      return ByteString.wrap(bytes);
+    }
+  };
+
+  static final ByteStringFactory HEAP_NIO_FACTORY = new ByteStringFactory() {
+    @Override
+    public ByteString newByteString(byte[] bytes) {
+      return new NioByteString(ByteBuffer.wrap(bytes));
+    }
+  };
+
+  private static ThreadLocal<SoftReference<ByteBuffer>> directBuffer =
+      new ThreadLocal<SoftReference<ByteBuffer>>();
+
+  /**
+   * Factory for direct {@link ByteBuffer} instances. To reduce direct memory usage, this
+   * uses a thread local direct buffer. This means that each call will overwrite the buffer's
+   * contents from the previous call, so the calling code must be careful not to continue using
+   * a buffer returned from a previous invocation.
+   */
+  static final ByteStringFactory DIRECT_NIO_FACTORY = new ByteStringFactory() {
+    @Override
+    public ByteString newByteString(byte[] bytes) {
+      SoftReference<ByteBuffer> ref = directBuffer.get();
+      ByteBuffer buffer = ref == null ? null : ref.get();
+      if (buffer == null || buffer.capacity() < bytes.length) {
+        buffer = ByteBuffer.allocateDirect(bytes.length);
+        directBuffer.set(new SoftReference<ByteBuffer>(buffer));
+      }
+      buffer.clear();
+      buffer.put(bytes);
+      buffer.flip();
+      return new NioByteString(buffer);
+    }
+  };
+
+  // 128 - [chars 0x0000 to 0x007f]
+  static final long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1;
+
+  // 128
+  static final long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT = ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 1920 [chars 0x0080 to 0x07FF]
+  static final long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1;
+
+  // 18,304
+  static final long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+      // Both bytes are one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) +
+      // The possible number of two byte characters
+      TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 2048
+  static final long THREE_BYTE_SURROGATES = 2 * 1024;
+
+  // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+  static final long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+      0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES;
+
+  // 2,650,112
+  static final long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+      // All one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) +
+      // One two byte character and a one byte character
+      2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Three byte characters
+      THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 1,048,576 [chars 0x10000L to 0x10FFFF]
+  static final long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1;
+
+  // 289,571,839
+  static final long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT =
+      // All one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) +
+      // One and three byte characters
+      2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Two two byte characters
+      TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Permutations of one and two byte characters
+      3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS
+      * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS
+      +
+      // Four byte characters
+      FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  static final class Shard {
+    final long index;
+    final long start;
+    final long lim;
+    final long expected;
+
+
+    public Shard(long index, long start, long lim, long expected) {
+      assertTrue(start < lim);
+      this.index = index;
+      this.start = start;
+      this.lim = lim;
+      this.expected = expected;
+    }
+  }
+
+  static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES =
+      generateFourByteShardsExpectedRunnables();
+
+  private static long[] generateFourByteShardsExpectedRunnables() {
+    long[] expected = new long[128];
+
+    // 0-63 are all 5300224
+    for (int i = 0; i <= 63; i++) {
+      expected[i] = 5300224;
+    }
+
+    // 97-111 are all 2342912
+    for (int i = 97; i <= 111; i++) {
+      expected[i] = 2342912;
+    }
+
+    // 113-117 are all 1048576
+    for (int i = 113; i <= 117; i++) {
+      expected[i] = 1048576;
+    }
+
+    // One offs
+    expected[112] = 786432;
+    expected[118] = 786432;
+    expected[119] = 1048576;
+    expected[120] = 458752;
+    expected[121] = 524288;
+    expected[122] = 65536;
+
+    // Anything not assigned was the default 0.
+    return expected;
+  }
+
+  static final List<Shard> FOUR_BYTE_SHARDS =
+      generateFourByteShards(128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES);
+
+
+  private static List<Shard> generateFourByteShards(int numShards, long[] expected) {
+    assertEquals(numShards, expected.length);
+    List<Shard> shards = new ArrayList<Shard>(numShards);
+    long LIM = 1L << 32;
+    long increment = LIM / numShards;
+    assertTrue(LIM % numShards == 0);
+    for (int i = 0; i < numShards; i++) {
+      shards.add(new Shard(i, increment * i, increment * (i + 1), expected[i]));
+    }
+    return shards;
+  }
+
+  /**
+   * Helper to run the loop to test all the permutations for the number of bytes
+   * specified.
+   *
+   * @param factory the factory for {@link ByteString} instances.
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   */
+  static void testBytes(ByteStringFactory factory, int numBytes, long expectedCount) {
+    testBytes(factory, numBytes, expectedCount, 0, -1);
+  }
+
+  /**
+   * Helper to run the loop to test all the permutations for the number of bytes
+   * specified. This overload is useful for debugging to get the loop to start
+   * at a certain character.
+   *
+   * @param factory the factory for {@link ByteString} instances.
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   * @param start the starting bytes encoded as a long as big-endian
+   * @param lim the limit of bytes to process encoded as a long as big-endian,
+   *     or -1 to mean the max limit for numBytes
+   */
+  static void testBytes(
+      ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) {
+    Random rnd = new Random();
+    byte[] bytes = new byte[numBytes];
+
+    if (lim == -1) {
+      lim = 1L << (numBytes * 8);
+    }
+    long count = 0;
+    long countRoundTripped = 0;
+    for (long byteChar = start; byteChar < lim; byteChar++) {
+      long tmpByteChar = byteChar;
+      for (int i = 0; i < numBytes; i++) {
+        bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+        tmpByteChar = tmpByteChar >> 8;
+      }
+      ByteString bs = factory.newByteString(bytes);
+      boolean isRoundTrippable = bs.isValidUtf8();
+      String s = new String(bytes, Internal.UTF_8);
+      byte[] bytesReencoded = s.getBytes(Internal.UTF_8);
+      boolean bytesEqual = Arrays.equals(bytes, bytesReencoded);
+
+      if (bytesEqual != isRoundTrippable) {
+        outputFailure(byteChar, bytes, bytesReencoded);
+      }
+
+      // Check agreement with static Utf8 methods.
+      assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes));
+      assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes));
+
+      // Test partial sequences.
+      // Partition numBytes into three segments (not necessarily non-empty).
+      int i = rnd.nextInt(numBytes);
+      int j = rnd.nextInt(numBytes);
+      if (j < i) {
+        int tmp = i;
+        i = j;
+        j = tmp;
+      }
+      int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i);
+      int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j);
+      int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes);
+      if (isRoundTrippable != (state3 == Utf8.COMPLETE)) {
+        System.out.printf("state=%04x %04x %04x i=%d j=%d%n", state1, state2, state3, i, j);
+        outputFailure(byteChar, bytes, bytesReencoded);
+      }
+      assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE));
+
+      // Test ropes built out of small partial sequences
+      ByteString rope = RopeByteString.newInstanceForTest(
+          bs.substring(0, i),
+          RopeByteString.newInstanceForTest(bs.substring(i, j), bs.substring(j, numBytes)));
+      assertSame(RopeByteString.class, rope.getClass());
+
+      ByteString[] byteStrings = {bs, bs.substring(0, numBytes), rope};
+      for (ByteString x : byteStrings) {
+        assertEquals(isRoundTrippable, x.isValidUtf8());
+        assertEquals(state3, x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes));
+
+        assertEquals(state1, x.partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+        assertEquals(state1, x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+        assertEquals(state2, x.partialIsValidUtf8(state1, i, j - i));
+        assertEquals(state2, x.substring(i, j).partialIsValidUtf8(state1, 0, j - i));
+        assertEquals(state3, x.partialIsValidUtf8(state2, j, numBytes - j));
+        assertEquals(state3, x.substring(j, numBytes).partialIsValidUtf8(state2, 0, numBytes - j));
+      }
+
+      // ByteString reduplication should not affect its UTF-8 validity.
+      ByteString ropeADope = RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes));
+      assertEquals(isRoundTrippable, ropeADope.isValidUtf8());
+
+      if (isRoundTrippable) {
+        countRoundTripped++;
+      }
+      count++;
+      if (byteChar != 0 && byteChar % 1000000L == 0) {
+        logger.info("Processed " + (byteChar / 1000000L) + " million characters");
+      }
+    }
+    logger.info("Round tripped " + countRoundTripped + " of " + count);
+    assertEquals(expectedCount, countRoundTripped);
+  }
+
+  /**
+   * Variation of {@link #testBytes} that does less allocation using the
+   * low-level encoders/decoders directly. Checked in because it's useful for
+   * debugging when trying to process bytes faster, but since it doesn't use the
+   * actual String class, it's possible for incompatibilities to develop
+   * (although unlikely).
+   *
+   * @param factory the factory for {@link ByteString} instances.
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   * @param start the starting bytes encoded as a long as big-endian
+   * @param lim the limit of bytes to process encoded as a long as big-endian,
+   *     or -1 to mean the max limit for numBytes
+   */
+  static void testBytesUsingByteBuffers(
+      ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) {
+    CharsetDecoder decoder =
+        Internal.UTF_8.newDecoder()
+            .onMalformedInput(CodingErrorAction.REPLACE)
+            .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    CharsetEncoder encoder =
+        Internal.UTF_8.newEncoder()
+            .onMalformedInput(CodingErrorAction.REPLACE)
+            .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    byte[] bytes = new byte[numBytes];
+    int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1;
+    char[] charsDecoded = new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1];
+    int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1;
+    byte[] bytesReencoded = new byte[maxBytes];
+
+    ByteBuffer bb = ByteBuffer.wrap(bytes);
+    CharBuffer cb = CharBuffer.wrap(charsDecoded);
+    ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded);
+    if (lim == -1) {
+      lim = 1L << (numBytes * 8);
+    }
+    long count = 0;
+    long countRoundTripped = 0;
+    for (long byteChar = start; byteChar < lim; byteChar++) {
+      bb.rewind();
+      bb.limit(bytes.length);
+      cb.rewind();
+      cb.limit(charsDecoded.length);
+      bbReencoded.rewind();
+      bbReencoded.limit(bytesReencoded.length);
+      encoder.reset();
+      decoder.reset();
+      long tmpByteChar = byteChar;
+      for (int i = 0; i < bytes.length; i++) {
+        bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+        tmpByteChar = tmpByteChar >> 8;
+      }
+      boolean isRoundTrippable = factory.newByteString(bytes).isValidUtf8();
+      CoderResult result = decoder.decode(bb, cb, true);
+      assertFalse(result.isError());
+      result = decoder.flush(cb);
+      assertFalse(result.isError());
+
+      int charLen = cb.position();
+      cb.rewind();
+      cb.limit(charLen);
+      result = encoder.encode(cb, bbReencoded, true);
+      assertFalse(result.isError());
+      result = encoder.flush(bbReencoded);
+      assertFalse(result.isError());
+
+      boolean bytesEqual = true;
+      int bytesLen = bbReencoded.position();
+      if (bytesLen != numBytes) {
+        bytesEqual = false;
+      } else {
+        for (int i = 0; i < numBytes; i++) {
+          if (bytes[i] != bytesReencoded[i]) {
+            bytesEqual = false;
+            break;
+          }
+        }
+      }
+      if (bytesEqual != isRoundTrippable) {
+        outputFailure(byteChar, bytes, bytesReencoded, bytesLen);
+      }
+
+      count++;
+      if (isRoundTrippable) {
+        countRoundTripped++;
+      }
+      if (byteChar != 0 && byteChar % 1000000 == 0) {
+        logger.info("Processed " + (byteChar / 1000000) + " million characters");
+      }
+    }
+    logger.info("Round tripped " + countRoundTripped + " of " + count);
+    assertEquals(expectedCount, countRoundTripped);
+  }
+
+  private static void outputFailure(long byteChar, byte[] bytes, byte[] after) {
+    outputFailure(byteChar, bytes, after, after.length);
+  }
+
+  private static void outputFailure(long byteChar, byte[] bytes, byte[] after, int len) {
+    fail("Failure: (" + Long.toHexString(byteChar) + ") " + toHexString(bytes) + " => "
+        + toHexString(after, len));
+  }
+
+  private static String toHexString(byte[] b) {
+    return toHexString(b, b.length);
+  }
+
+  private static String toHexString(byte[] b, int len) {
+    StringBuilder s = new StringBuilder();
+    s.append("\"");
+    for (int i = 0; i < len; i++) {
+      if (i > 0) {
+        s.append(" ");
+      }
+      s.append(String.format("%02x", b[i] & 0xFF));
+    }
+    s.append("\"");
+    return s.toString();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
new file mode 100644
index 0000000..8d1de6d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -0,0 +1,272 @@
+// 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.
+
+package com.google.protobuf;
+
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Unit test for {@link LazyFieldLite}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldLiteTest extends TestCase {
+
+  public void testGetValue() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testGetValueEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+  }
+
+  public void testSetValue() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+    message = lazyField.getValue(TestAllTypes.getDefaultInstance());
+    changeValue(lazyField);
+    assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testSetValueEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+    MessageLite value = lazyField.getValue(TestAllExtensions.getDefaultInstance());
+    changeValue(lazyField);
+    assertEquals(value, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+  }
+
+  public void testGetSerializedSize() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+    changeValue(lazyField);
+    assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+  }
+
+  public void testGetSerializedSizeEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+    changeValue(lazyField);
+    assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+  }
+
+  public void testGetByteString() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message.toByteString(), lazyField.toByteString());
+    changeValue(lazyField);
+    assertNotEqual(message.toByteString(), lazyField.toByteString());
+  }
+
+  public void testGetByteStringEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+    assertEquals(message.toByteString(), lazyField.toByteString());
+    changeValue(lazyField);
+    assertNotEqual(message.toByteString(), lazyField.toByteString());
+  }
+
+  public void testMergeExtensions() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyFieldLite original = createLazyFieldLiteFromMessage(message);
+    LazyFieldLite merged = new LazyFieldLite();
+    merged.merge(original);
+    TestAllExtensions value = (TestAllExtensions) merged.getValue(
+        TestAllExtensions.getDefaultInstance());
+    assertEquals(message, value);
+  }
+
+  public void testEmptyLazyField() throws Exception {
+    LazyFieldLite field = new LazyFieldLite();
+    assertEquals(0, field.getSerializedSize());
+    assertEquals(ByteString.EMPTY, field.toByteString());
+  }
+
+  public void testInvalidProto() throws Exception {
+    // Silently fails and uses the default instance.
+    LazyFieldLite field = new LazyFieldLite(
+        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    assertEquals(
+        TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
+    assertEquals(0, field.getSerializedSize());
+    assertEquals(ByteString.EMPTY, field.toByteString());
+  }
+
+  public void testMergeBeforeParsing() throws Exception {
+    TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1);
+    TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+    LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+
+    field1.merge(field2);
+    TestAllTypes expected =
+        TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeOneNotParsed() throws Exception {
+    // Test a few different paths that involve one message that was not parsed.
+    TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+    TestAllTypes expected =
+        TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+
+    LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
+    field1.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+    field1.merge(field2);
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+
+    // Now reverse which one is parsed first.
+    field1 = LazyFieldLite.fromValue(message1);
+    field2 = createLazyFieldLiteFromMessage(message2);
+    field2.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    field1.merge(field2);
+    assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeInvalid() throws Exception {
+    // Test a few different paths that involve one message that was not parsed.
+    TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+    LazyFieldLite valid = LazyFieldLite.fromValue(message);
+    LazyFieldLite invalid = new LazyFieldLite(
+        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    invalid.merge(valid);
+
+    // We swallow the exception and just use the set field.
+    assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance()));
+  }
+
+  public void testMergeKeepsExtensionsWhenPossible() throws Exception {
+    // In this test we attempt to only use the empty registry, which will strip out all extensions
+    // when serializing and then parsing. We verify that each code path will attempt to not
+    // serialize and parse a message that was set directly without going through the
+    // extensionRegistry.
+    TestAllExtensions messageWithExtensions =
+        TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build();
+    TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build();
+
+    ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry();
+
+    LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions);
+    field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage));
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // Now reverse the order of the merging.
+    field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    field.merge(LazyFieldLite.fromValue(messageWithExtensions));
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // Now try parsing the empty field first.
+    field = LazyFieldLite.fromValue(messageWithExtensions);
+    LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    other.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    field.merge(other);
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+    // And again reverse.
+    field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+    field.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    other = LazyFieldLite.fromValue(messageWithExtensions);
+    field.merge(other);
+    assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+  }
+
+  public void testMergeMightLoseExtensions() throws Exception {
+    // Test that we don't know about the extensions when parsing.
+    TestAllExtensions message1 =
+        TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build();
+    TestAllExtensions message2 =
+        TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build();
+
+    LazyFieldLite field = LazyFieldLite.fromValue(message1);
+    field.merge(LazyFieldLite.fromValue(message2));
+
+    // We lose the extensions from message 2 because we have to serialize it and then parse it
+    // again, using the empty registry this time.
+    TestAllExtensions value =
+        (TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance());
+    assertTrue(value.hasExtension(optionalInt32Extension));
+    assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension));
+    assertFalse(value.hasExtension(optionalInt64Extension));
+
+    // The field is still there, it is just unknown.
+    assertTrue(value.getUnknownFields()
+        .hasField(optionalInt64Extension.getDescriptor().getNumber()));
+  }
+
+
+  // Help methods.
+
+  private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
+    return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message);
+  }
+
+  private LazyFieldLite createLazyFieldLiteFromMessage(
+      ExtensionRegistryLite extensionRegistry, MessageLite message) {
+    ByteString bytes = message.toByteString();
+    return new LazyFieldLite(extensionRegistry, bytes);
+  }
+
+  private void changeValue(LazyFieldLite lazyField) {
+    TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+    builder.addRepeatedBool(true);
+    MessageLite newMessage = builder.build();
+    lazyField.setValue(newMessage);
+  }
+
+  private void assertNotEqual(Object unexpected, Object actual) {
+    assertFalse(unexpected == actual
+        || (unexpected != null && unexpected.equals(actual)));
+  }
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
new file mode 100644
index 0000000..ce473ae
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
@@ -0,0 +1,122 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Unit test for {@link LazyField}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldTest extends TestCase {
+  public void testHashCode() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyField lazyField =
+        createLazyFieldFromMessage(message);
+    assertEquals(message.hashCode(), lazyField.hashCode());
+    lazyField.getValue();
+    assertEquals(message.hashCode(), lazyField.hashCode());
+    changeValue(lazyField);
+    // make sure two messages have different hash code
+    assertNotEqual(message.hashCode(), lazyField.hashCode());
+  }
+
+  public void testHashCodeEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyField lazyField = createLazyFieldFromMessage(message);
+    assertEquals(message.hashCode(), lazyField.hashCode());
+    lazyField.getValue();
+    assertEquals(message.hashCode(), lazyField.hashCode());
+    changeValue(lazyField);
+    // make sure two messages have different hash code
+    assertNotEqual(message.hashCode(), lazyField.hashCode());
+  }
+
+  public void testGetValue() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyField lazyField = createLazyFieldFromMessage(message);
+    assertEquals(message, lazyField.getValue());
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue());
+  }
+
+  public void testGetValueEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyField lazyField = createLazyFieldFromMessage(message);
+    assertEquals(message, lazyField.getValue());
+    changeValue(lazyField);
+    assertNotEqual(message, lazyField.getValue());
+  }
+
+  public void testEqualsObject() {
+    MessageLite message = TestUtil.getAllSet();
+    LazyField lazyField = createLazyFieldFromMessage(message);
+    assertTrue(lazyField.equals(message));
+    changeValue(lazyField);
+    assertFalse(lazyField.equals(message));
+    assertFalse(message.equals(lazyField.getValue()));
+  }
+
+  public void testEqualsObjectEx() throws Exception {
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    LazyField lazyField = createLazyFieldFromMessage(message);
+    assertTrue(lazyField.equals(message));
+    changeValue(lazyField);
+    assertFalse(lazyField.equals(message));
+    assertFalse(message.equals(lazyField.getValue()));
+  }
+
+  // Help methods.
+
+  private LazyField createLazyFieldFromMessage(MessageLite message) {
+    ByteString bytes = message.toByteString();
+    return new LazyField(message.getDefaultInstanceForType(),
+        TestUtil.getExtensionRegistry(), bytes);
+  }
+
+  private void changeValue(LazyField lazyField) {
+    TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+    builder.addRepeatedBool(true);
+    MessageLite newMessage = builder.build();
+    lazyField.setValue(newMessage);
+  }
+
+  private void assertNotEqual(Object unexpected, Object actual) {
+    assertFalse(unexpected == actual
+        || (unexpected != null && unexpected.equals(actual)));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
new file mode 100644
index 0000000..afe0fff
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -0,0 +1,307 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.LazyFieldsLite.LazyExtension;
+import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+
+/**
+ * Unit test for messages with lazy fields.
+ *
+ * @author niwasaki@google.com (Naoki Iwasaki)
+ */
+public class LazyMessageLiteTest extends TestCase {
+
+  private Parser<LazyInnerMessageLite> originalLazyInnerMessageLiteParser;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+
+  public void testSetValues() {
+    LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+        .setNum(3)
+        .build();
+    LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+        .setNum(2)
+        .setNested(nested)
+        .build();
+    LazyMessageLite outer = LazyMessageLite.newBuilder()
+        .setNum(1)
+        .setInner(inner)
+        .setOneofNum(123)
+        .setOneofInner(inner)
+        .build();
+
+    assertEquals(1, outer.getNum());
+    assertEquals(421, outer.getNumWithDefault());
+
+    assertEquals(2, outer.getInner().getNum());
+    assertEquals(42, outer.getInner().getNumWithDefault());
+
+    assertEquals(3, outer.getInner().getNested().getNum());
+    assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+    assertFalse(outer.hasOneofNum());
+    assertTrue(outer.hasOneofInner());
+
+    assertEquals(2, outer.getOneofInner().getNum());
+    assertEquals(42, outer.getOneofInner().getNumWithDefault());
+    assertEquals(3, outer.getOneofInner().getNested().getNum());
+    assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+  }
+
+  public void testSetRepeatedValues() {
+    LazyMessageLite outer = LazyMessageLite.newBuilder()
+        .setNum(1)
+        .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+        .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+        .build();
+
+    assertEquals(1, outer.getNum());
+    assertEquals(2, outer.getRepeatedInnerCount());
+    assertEquals(119, outer.getRepeatedInner(0).getNum());
+    assertEquals(122, outer.getRepeatedInner(1).getNum());
+  }
+
+  public void testAddAll() {
+    ArrayList<LazyInnerMessageLite> inners = new ArrayList<LazyInnerMessageLite>();
+    int count = 4;
+    for (int i = 0; i < count; i++) {
+      LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+          .setNum(i)
+          .build();
+      inners.add(inner);
+    }
+
+    LazyMessageLite outer = LazyMessageLite.newBuilder()
+        .addAllRepeatedInner(inners)
+        .build();
+    assertEquals(count, outer.getRepeatedInnerCount());
+    for (int i = 0; i < count; i++) {
+      assertEquals(i, outer.getRepeatedInner(i).getNum());
+    }
+  }
+
+  public void testGetDefaultValues() {
+    LazyMessageLite outer = LazyMessageLite.newBuilder()
+        .build();
+
+    assertEquals(0, outer.getNum());
+    assertEquals(421, outer.getNumWithDefault());
+
+    assertEquals(0, outer.getInner().getNum());
+    assertEquals(42, outer.getInner().getNumWithDefault());
+
+    assertEquals(0, outer.getInner().getNested().getNum());
+    assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+    assertEquals(0, outer.getOneofNum());
+
+    assertEquals(0, outer.getOneofInner().getNum());
+    assertEquals(42, outer.getOneofInner().getNumWithDefault());
+    assertEquals(0, outer.getOneofInner().getNested().getNum());
+    assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+  }
+
+  public void testClearValues() {
+    LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+        .setNum(115)
+        .build();
+
+    LazyMessageLite.Builder outerBuilder = LazyMessageLite.newBuilder();
+
+    assertEquals(0, outerBuilder.build().getNum());
+
+
+    // Set/Clear num
+    outerBuilder.setNum(100);
+
+    assertEquals(100, outerBuilder.build().getNum());
+    assertEquals(421, outerBuilder.build().getNumWithDefault());
+    assertFalse(outerBuilder.build().hasInner());
+
+    outerBuilder.clearNum();
+
+    assertEquals(0, outerBuilder.build().getNum());
+    assertEquals(421, outerBuilder.build().getNumWithDefault());
+    assertFalse(outerBuilder.build().hasInner());
+
+
+    // Set/Clear all
+    outerBuilder.setNum(100)
+        .setInner(inner)
+        .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+        .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+        .setOneofInner(LazyInnerMessageLite.newBuilder().setNum(123));
+
+    LazyMessageLite outer = outerBuilder.build();
+    assertEquals(100, outer.getNum());
+    assertEquals(421, outer.getNumWithDefault());
+    assertTrue(outer.hasInner());
+    assertEquals(115, outer.getInner().getNum());
+    assertEquals(2, outer.getRepeatedInnerCount());
+    assertEquals(119, outer.getRepeatedInner(0).getNum());
+    assertEquals(122, outer.getRepeatedInner(1).getNum());
+    assertTrue(outer.hasOneofInner());
+    assertEquals(123, outer.getOneofInner().getNum());
+
+    outerBuilder.clear();
+
+    outer = outerBuilder.build();
+
+    assertEquals(0, outer.getNum());
+    assertEquals(421, outer.getNumWithDefault());
+    assertFalse(outer.hasInner());
+    assertEquals(0, outer.getRepeatedInnerCount());
+    assertFalse(outer.hasOneofInner());
+    assertEquals(0, outer.getOneofInner().getNum());
+  }
+
+  public void testMergeValues() {
+    LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+        .setNumWithDefault(122)
+        .build();
+
+    LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder()
+        .setNum(115)
+        .build();
+    LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+        .setNum(119)
+        .setInner(innerMerging)
+        .setOneofInner(innerMerging)
+        .build();
+
+    LazyMessageLite merged = LazyMessageLite
+        .newBuilder(outerBase)
+        .mergeFrom(outerMerging)
+        .build();
+    assertEquals(119, merged.getNum());
+    assertEquals(122, merged.getNumWithDefault());
+    assertEquals(115, merged.getInner().getNum());
+    assertEquals(42, merged.getInner().getNumWithDefault());
+    assertEquals(115, merged.getOneofInner().getNum());
+    assertEquals(42, merged.getOneofInner().getNumWithDefault());
+  }
+
+  public void testMergeDefaultValues() {
+    LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder()
+        .setNum(115)
+        .build();
+    LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+        .setNum(119)
+        .setNumWithDefault(122)
+        .setInner(innerBase)
+        .setOneofInner(innerBase)
+        .build();
+
+    LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+        .build();
+
+    LazyMessageLite merged = LazyMessageLite
+        .newBuilder(outerBase)
+        .mergeFrom(outerMerging)
+        .build();
+    // Merging default-instance shouldn't overwrite values in the base message.
+    assertEquals(119, merged.getNum());
+    assertEquals(122, merged.getNumWithDefault());
+    assertEquals(115, merged.getInner().getNum());
+    assertEquals(42, merged.getInner().getNumWithDefault());
+    assertEquals(115, merged.getOneofInner().getNum());
+    assertEquals(42, merged.getOneofInner().getNumWithDefault());
+  }
+
+  public void testSerialize() throws InvalidProtocolBufferException {
+    LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+        .setNum(3)
+        .build();
+    LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+        .setNum(2)
+        .setNested(nested)
+        .build();
+    LazyMessageLite outer = LazyMessageLite.newBuilder()
+        .setNum(1)
+        .setInner(inner)
+        .setOneofInner(inner)
+        .build();
+
+    ByteString bytes = outer.toByteString();
+    assertEquals(bytes.size(), outer.getSerializedSize());
+
+    LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes);
+
+    assertEquals(1, deserialized.getNum());
+    assertEquals(421,  deserialized.getNumWithDefault());
+
+    assertEquals(2,  deserialized.getInner().getNum());
+    assertEquals(42,  deserialized.getInner().getNumWithDefault());
+
+    assertEquals(3,  deserialized.getInner().getNested().getNum());
+    assertEquals(4,  deserialized.getInner().getNested().getNumWithDefault());
+
+    assertEquals(2,  deserialized.getOneofInner().getNum());
+    assertEquals(42,  deserialized.getOneofInner().getNumWithDefault());
+    assertEquals(3,  deserialized.getOneofInner().getNested().getNum());
+    assertEquals(4,  deserialized.getOneofInner().getNested().getNumWithDefault());
+
+    assertEquals(bytes, deserialized.toByteString());
+  }
+
+  public void testExtensions() throws Exception {
+    LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder();
+    innerBuilder.setExtension(
+        LazyExtension.extension, LazyExtension.newBuilder()
+        .setName("name").build());
+    assertTrue(innerBuilder.hasExtension(LazyExtension.extension));
+    assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName());
+
+    LazyInnerMessageLite innerMessage = innerBuilder.build();
+    assertTrue(innerMessage.hasExtension(LazyExtension.extension));
+    assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName());
+
+    LazyMessageLite lite = LazyMessageLite.newBuilder()
+        .setInner(innerMessage).build();
+    assertTrue(lite.getInner().hasExtension(LazyExtension.extension));
+    assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
new file mode 100644
index 0000000..0f42ac5
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -0,0 +1,362 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests for {@link LazyStringArrayList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayListTest extends TestCase {
+
+  private static String STRING_A = "A";
+  private static String STRING_B = "B";
+  private static String STRING_C = "C";
+
+  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+  public void testJustStrings() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.add(STRING_B);
+    list.add(STRING_C);
+
+    assertEquals(3, list.size());
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_B, list.get(1));
+    assertSame(STRING_C, list.get(2));
+
+    list.set(1, STRING_C);
+    assertSame(STRING_C, list.get(1));
+
+    list.remove(1);
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_C, list.get(1));
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    assertEquals(BYTE_STRING_A, byteStringList.get(0));
+    assertEquals(BYTE_STRING_C, byteStringList.get(1));
+
+    // Underlying list should be transformed.
+    assertSame(byteStringList.get(0), list.getByteString(0));
+    assertSame(byteStringList.get(1), list.getByteString(1));
+  }
+
+  public void testJustByteString() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(BYTE_STRING_A);
+    list.add(BYTE_STRING_B);
+    list.add(BYTE_STRING_C);
+
+    assertEquals(3, list.size());
+    assertSame(BYTE_STRING_A, list.getByteString(0));
+    assertSame(BYTE_STRING_B, list.getByteString(1));
+    assertSame(BYTE_STRING_C, list.getByteString(2));
+
+    list.remove(1);
+    assertSame(BYTE_STRING_A, list.getByteString(0));
+    assertSame(BYTE_STRING_C, list.getByteString(1));
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    assertSame(BYTE_STRING_A, byteStringList.get(0));
+    assertSame(BYTE_STRING_C, byteStringList.get(1));
+  }
+
+  public void testConversionBackAndForth() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.add(BYTE_STRING_B);
+    list.add(BYTE_STRING_C);
+
+    // String a should be the same because it was originally a string
+    assertSame(STRING_A, list.get(0));
+
+    // String b and c should be different because the string has to be computed
+    // from the ByteString
+    String bPrime = list.get(1);
+    assertNotSame(STRING_B, bPrime);
+    assertEquals(STRING_B, bPrime);
+    String cPrime = list.get(2);
+    assertNotSame(STRING_C, cPrime);
+    assertEquals(STRING_C, cPrime);
+
+    // String c and c should stay the same once cached.
+    assertSame(bPrime, list.get(1));
+    assertSame(cPrime, list.get(2));
+
+    // ByteString needs to be computed from string for both a and b
+    ByteString aPrimeByteString = list.getByteString(0);
+    assertEquals(BYTE_STRING_A, aPrimeByteString);
+    ByteString bPrimeByteString = list.getByteString(1);
+    assertNotSame(BYTE_STRING_B, bPrimeByteString);
+    assertEquals(BYTE_STRING_B, list.getByteString(1));
+
+    // Once cached, ByteString should stay cached.
+    assertSame(aPrimeByteString, list.getByteString(0));
+    assertSame(bPrimeByteString, list.getByteString(1));
+  }
+
+  public void testCopyConstructorCopiesByReference() {
+    LazyStringArrayList list1 = new LazyStringArrayList();
+    list1.add(STRING_A);
+    list1.add(BYTE_STRING_B);
+    list1.add(BYTE_STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList(list1);
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(BYTE_STRING_B, list2.getByteString(1));
+    assertSame(BYTE_STRING_C, list2.getByteString(2));
+  }
+
+  public void testListCopyConstructor() {
+    List<String> list1 = new ArrayList<String>();
+    list1.add(STRING_A);
+    list1.add(STRING_B);
+    list1.add(STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList(list1);
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(STRING_B, list2.get(1));
+    assertSame(STRING_C, list2.get(2));
+  }
+
+  public void testAddAllCopiesByReferenceIfPossible() {
+    LazyStringArrayList list1 = new LazyStringArrayList();
+    list1.add(STRING_A);
+    list1.add(BYTE_STRING_B);
+    list1.add(BYTE_STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList();
+    list2.addAll(list1);
+
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(BYTE_STRING_B, list2.getByteString(1));
+    assertSame(BYTE_STRING_C, list2.getByteString(2));
+  }
+  
+  public void testModificationWithIteration() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.addAll(asList(STRING_A, STRING_B, STRING_C));
+    Iterator<String> iterator = list.iterator();
+    assertEquals(3, list.size());
+    assertEquals(STRING_A, list.get(0));
+    assertEquals(STRING_A, iterator.next());
+    
+    // Does not structurally modify.
+    iterator = list.iterator();
+    list.set(0, STRING_B);
+    iterator.next();
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, STRING_C);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testMakeImmutable() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.add(STRING_B);
+    list.add(STRING_C);
+    list.makeImmutable();
+    assertGenericListImmutable(list, STRING_A);
+    
+    // LazyStringArrayList has extra methods not covered in the generic
+    // assertion.
+    
+    try {
+      list.add(BYTE_STRING_A.toByteArray());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(BYTE_STRING_A);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAllByteArray(asList(BYTE_STRING_A.toByteArray()));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAllByteString(asList(BYTE_STRING_A));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.mergeFrom(new LazyStringArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, BYTE_STRING_A.toByteArray());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, BYTE_STRING_A);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  public void testImmutabilityPropagation() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.makeImmutable();
+
+    assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A);
+    
+    // Arrays use reference equality so need to retrieve the underlying value
+    // to properly test deep immutability.
+    List<byte[]> byteArrayList = list.asByteArrayList();
+    assertGenericListImmutable(byteArrayList, byteArrayList.get(0));
+  }
+  
+  private static <T> void assertGenericListImmutable(List<T> list, T value) {
+    try {
+      list.add(value);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, value);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(asList(value));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, asList(value));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(value);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(asList(value));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(asList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(asList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, value);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
new file mode 100644
index 0000000..0ef414a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -0,0 +1,132 @@
+// 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.
+
+package com.google.protobuf;
+
+
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
+ * strings works correctly.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringEndToEndTest extends TestCase {
+
+  private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
+      ByteString.copyFrom(new byte[] {
+          114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
+          0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+
+  private ByteString encodedTestAllTypes;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+        .setOptionalString("foo")
+        .addRepeatedString("bar")
+        .addRepeatedString("baz")
+        .build()
+        .toByteString();
+  }
+
+  /**
+   * Tests that an invalid UTF8 string will roundtrip through a parse
+   * and serialization.
+   */
+  public void testParseAndSerialize() throws InvalidProtocolBufferException {
+    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+    ByteString bytes = tV2.toByteString();
+    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+
+    tV2.getOptionalString();
+    bytes = tV2.toByteString();
+    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+  }
+
+  public void testParseAndWrite() throws IOException {
+    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+    byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
+    CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
+    tV2.writeTo(outputStream);
+    outputStream.flush();
+    assertEquals(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
+        ByteString.copyFrom(sink));
+  }
+  
+  public void testCaching() {
+    String a = "a";
+    String b = "b";
+    String c = "c";
+    UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder()
+        .setOptionalString(a)
+        .addRepeatedString(b)
+        .addRepeatedString(c)
+        .build();
+
+    // String should be the one we passed it.
+    assertSame(a, proto.getOptionalString());
+    assertSame(b, proto.getRepeatedString(0));
+    assertSame(c, proto.getRepeatedString(1));
+
+
+    // Ensure serialization keeps strings cached.
+    proto.toByteString();
+
+    // And now the string should stay cached.
+    assertSame(a, proto.getOptionalString());
+    assertSame(b, proto.getRepeatedString(0));
+    assertSame(c, proto.getRepeatedString(1));
+  }
+
+  public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+    UnittestProto.TestAllTypes proto =
+        UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+    ByteString optional = proto.getOptionalStringBytes();
+    assertSame(optional, proto.getOptionalStringBytes());
+    assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+    ByteString repeated0 = proto.getRepeatedStringBytes(0);
+    ByteString repeated1 = proto.getRepeatedStringBytes(1);
+    assertSame(repeated0, proto.getRepeatedStringBytes(0));
+    assertSame(repeated1, proto.getRepeatedStringBytes(1));
+    assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+    assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
new file mode 100644
index 0000000..29e8d87
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
@@ -0,0 +1,125 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
+
+import junit.framework.TestCase;
+
+/**
+ * Test generate equal and hash methods for the lite runtime.
+ *
+ * @author pbogle@google.com Phil Bogle
+ */
+public class LiteEqualsAndHashTest extends TestCase {
+
+  public void testEquals() throws Exception {
+    // Since the generated equals and hashCode methods for lite messages are a
+    // mostly complete subset of those for regular messages, we can mostly assume
+    // that the generated methods are already thoroughly tested by the regular tests.
+
+    // This test mostly just verifies is that a proto with
+    // optimize_for = LITE_RUNTIME and java_generates_equals_and_hash_compiles
+    // correctly when linked only against the lite library.
+
+    // We do however do some basic testing to make sure that equals is actually
+    // overriden to test for value equality rather than simple object equality.
+
+    // Check that two identical objs are equal.
+    Foo foo1a = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo1b = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo2 = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo2"))
+        .build();
+
+    // Check that equals is doing value rather than object equality.
+    assertEquals(foo1a, foo1b);
+    assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+    // Check that a diffeent object is not equal.
+    assertFalse(foo1a.equals(foo2));
+
+    // Check that two objects which have different types but the same field values are not
+    // considered to be equal.
+    Bar bar = Bar.newBuilder().setName("bar").build();
+    BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+    assertFalse(bar.equals(barPrime));
+  }
+
+  public void testOneofEquals() throws Exception {
+    TestOneofEquals.Builder builder = TestOneofEquals.newBuilder();
+    TestOneofEquals message1 = builder.build();
+    // Set message2's name field to default value. The two messages should be different when we
+    // check with the oneof case.
+    builder.setName("");
+    TestOneofEquals message2 = builder.build();
+    assertFalse(message1.equals(message2));
+  }
+
+  public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+    Foo fooWithOnlyValue = Foo.newBuilder()
+        .setValue(1)
+        .build();
+
+    Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+        .setValue(1)
+        .setExtension(Bar.fooExt, Bar.newBuilder()
+            .setName("name")
+            .build())
+        .build();
+
+    Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+    assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+    assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+  }
+
+  private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+    assertFalse(o1.equals(o2));
+    assertFalse(o1.hashCode() == o2.hashCode());
+  }
+
+  public void testRecursiveHashcode() {
+    // This tests that we don't infinite loop.
+    TestRecursiveOneof.getDefaultInstance().hashCode();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteTest.java
new file mode 100644
index 0000000..88c3e0b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteTest.java
@@ -0,0 +1,2229 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Test lite runtime.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class LiteTest extends TestCase {
+  @Override
+  public void setUp() throws Exception {
+    // Test that nested extensions are initialized correctly even if the outer
+    // class has not been accessed directly.  This was once a bug with lite
+    // messages.
+    //
+    // We put this in setUp() rather than in its own test method because we
+    // need to make sure it runs before any actual tests.
+    assertTrue(TestNestedExtensionLite.nestedExtension != null);
+  }
+
+  public void testLite() throws Exception {
+    // Since lite messages are a subset of regular messages, we can mostly
+    // assume that the functionality of lite messages is already thoroughly
+    // tested by the regular tests.  All this test really verifies is that
+    // a proto with optimize_for = LITE_RUNTIME compiles correctly when
+    // linked only against the lite library.  That is all tested at compile
+    // time, leaving not much to do in this method.  Let's just do some random
+    // stuff to make sure the lite message is actually here and usable.
+
+    TestAllTypesLite message =
+      TestAllTypesLite.newBuilder()
+                      .setOptionalInt32(123)
+                      .addRepeatedString("hello")
+                      .setOptionalNestedMessage(
+                          TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+                      .build();
+
+    ByteString data = message.toByteString();
+
+    TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
+
+    assertEquals(123, message2.getOptionalInt32());
+    assertEquals(1, message2.getRepeatedStringCount());
+    assertEquals("hello", message2.getRepeatedString(0));
+    assertEquals(7, message2.getOptionalNestedMessage().getBb());
+  }
+
+  public void testLiteExtensions() throws Exception {
+    // TODO(kenton):  Unlike other features of the lite library, extensions are
+    //   implemented completely differently from the regular library.  We
+    //   should probably test them more thoroughly.
+
+    TestAllExtensionsLite message =
+      TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
+        .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+            TestAllTypesLite.NestedEnum.BAZ)
+        .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+        .build();
+
+    // Test copying a message, since coping extensions actually does use a
+    // different code path between lite and regular libraries, and as of this
+    // writing, parsing hasn't been implemented yet.
+    TestAllExtensionsLite message2 = message.toBuilder().build();
+
+    assertEquals(123, (int) message2.getExtension(
+        UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(1, message2.getExtensionCount(
+        UnittestLite.repeatedStringExtensionLite));
+    assertEquals(1, message2.getExtension(
+        UnittestLite.repeatedStringExtensionLite).size());
+    assertEquals("hello", message2.getExtension(
+        UnittestLite.repeatedStringExtensionLite, 0));
+    assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
+        UnittestLite.optionalNestedEnumExtensionLite));
+    assertEquals(7, message2.getExtension(
+        UnittestLite.optionalNestedMessageExtensionLite).getBb());
+  }
+  
+  
+  public void testClone() {
+    TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder()
+        .setOptionalInt32(123);
+    assertEquals(
+        expected.getOptionalInt32(), expected.clone().getOptionalInt32());
+   
+    TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 123);
+    assertEquals(
+        expected2.getExtension(UnittestLite.optionalInt32ExtensionLite),
+        expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite));
+  }
+  
+  public void testAddAll() {
+    try {
+      TestAllTypesLite.newBuilder()
+          .addAllRepeatedBytes(null);
+      fail();
+    } catch (NullPointerException e) {
+      // expected.
+    }
+  }
+  
+  public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+    // Since builders are implemented as a thin wrapper around a message
+    // instance, we attempt to verify that we can't cause the builder to modify
+    // a produced message.
+
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+    TestAllTypesLite message = builder.build();
+    TestAllTypesLite messageAfterBuild;
+    builder.setOptionalBool(true);
+    assertEquals(false, message.getOptionalBool());
+    assertEquals(true, builder.getOptionalBool());
+    messageAfterBuild = builder.build();
+    assertEquals(true, messageAfterBuild.getOptionalBool());
+    assertEquals(false, message.getOptionalBool());
+    builder.clearOptionalBool();
+    assertEquals(false, builder.getOptionalBool());
+    assertEquals(true, messageAfterBuild.getOptionalBool());
+
+    message = builder.build();
+    builder.setOptionalBytes(ByteString.copyFromUtf8("hi"));
+    assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+    assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+    assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+    builder.clearOptionalBytes();
+    assertEquals(ByteString.EMPTY, builder.getOptionalBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+
+    message = builder.build();
+    builder.setOptionalCord("hi");
+    assertEquals("", message.getOptionalCord());
+    assertEquals("hi", builder.getOptionalCord());
+    messageAfterBuild = builder.build();
+    assertEquals("hi", messageAfterBuild.getOptionalCord());
+    assertEquals("", message.getOptionalCord());
+    builder.clearOptionalCord();
+    assertEquals("", builder.getOptionalCord());
+    assertEquals("hi", messageAfterBuild.getOptionalCord());
+
+    message = builder.build();
+    builder.setOptionalCordBytes(ByteString.copyFromUtf8("no"));
+    assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+    assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalCordBytes());
+    assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+    builder.clearOptionalCord();
+    assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalCordBytes());
+    
+    message = builder.build();
+    builder.setOptionalDouble(1);
+    assertEquals(0D, message.getOptionalDouble());
+    assertEquals(1D, builder.getOptionalDouble());
+    messageAfterBuild = builder.build();
+    assertEquals(1D, messageAfterBuild.getOptionalDouble());
+    assertEquals(0D, message.getOptionalDouble());
+    builder.clearOptionalDouble();
+    assertEquals(0D, builder.getOptionalDouble());
+    assertEquals(1D, messageAfterBuild.getOptionalDouble());
+    
+    message = builder.build();
+    builder.setOptionalFixed32(1);
+    assertEquals(0, message.getOptionalFixed32());
+    assertEquals(1, builder.getOptionalFixed32());
+    messageAfterBuild = builder.build();
+    assertEquals(1, messageAfterBuild.getOptionalFixed32());
+    assertEquals(0, message.getOptionalFixed32());
+    builder.clearOptionalFixed32();
+    assertEquals(0, builder.getOptionalFixed32());
+    assertEquals(1, messageAfterBuild.getOptionalFixed32());
+    
+    message = builder.build();
+    builder.setOptionalFixed64(1);
+    assertEquals(0L, message.getOptionalFixed64());
+    assertEquals(1L, builder.getOptionalFixed64());
+    messageAfterBuild = builder.build();
+    assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+    assertEquals(0L, message.getOptionalFixed64());
+    builder.clearOptionalFixed64();
+    assertEquals(0L, builder.getOptionalFixed64());
+    assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+
+    message = builder.build();
+    builder.setOptionalFloat(1);
+    assertEquals(0F, message.getOptionalFloat());
+    assertEquals(1F, builder.getOptionalFloat());
+    messageAfterBuild = builder.build();
+    assertEquals(1F, messageAfterBuild.getOptionalFloat());
+    assertEquals(0F, message.getOptionalFloat());
+    builder.clearOptionalFloat();
+    assertEquals(0F, builder.getOptionalFloat());
+    assertEquals(1F, messageAfterBuild.getOptionalFloat());
+
+    message = builder.build();
+    builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_BAR,
+        messageAfterBuild.getOptionalForeignEnum());
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+    builder.clearOptionalForeignEnum();
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum());
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_BAR,
+        messageAfterBuild.getOptionalForeignEnum());
+
+    message = builder.build();
+    ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder()
+        .setC(1)
+        .build();
+    builder.setOptionalForeignMessage(foreignMessage);
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        message.getOptionalForeignMessage());
+    assertEquals(foreignMessage, builder.getOptionalForeignMessage());
+    messageAfterBuild = builder.build();
+    assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        message.getOptionalForeignMessage());
+    builder.clearOptionalForeignMessage();
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        builder.getOptionalForeignMessage());
+    assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+
+    message = builder.build();
+    ForeignMessageLite.Builder foreignMessageBuilder =
+        ForeignMessageLite.newBuilder()
+            .setC(3);
+    builder.setOptionalForeignMessage(foreignMessageBuilder);
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        message.getOptionalForeignMessage());
+    assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage());
+    messageAfterBuild = builder.build();
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        message.getOptionalForeignMessage());
+    builder.clearOptionalForeignMessage();
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        builder.getOptionalForeignMessage());
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+
+    message = builder.build();
+    OptionalGroup optionalGroup = OptionalGroup.newBuilder()
+        .setA(1)
+        .build();
+    builder.setOptionalGroup(optionalGroup);
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+    assertEquals(optionalGroup, builder.getOptionalGroup());
+    messageAfterBuild = builder.build();
+    assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+    builder.clearOptionalGroup();
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+    assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+
+    message = builder.build();
+    OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder()
+        .setA(3);
+    builder.setOptionalGroup(optionalGroupBuilder);
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+    assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup());
+    messageAfterBuild = builder.build();
+    assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+    builder.clearOptionalGroup();
+    assertEquals(
+        OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+    assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
+
+    message = builder.build();
+    builder.setOptionalInt32(1);
+    assertEquals(0, message.getOptionalInt32());
+    assertEquals(1, builder.getOptionalInt32());
+    messageAfterBuild = builder.build();
+    assertEquals(1, messageAfterBuild.getOptionalInt32());
+    assertEquals(0, message.getOptionalInt32());
+    builder.clearOptionalInt32();
+    assertEquals(0, builder.getOptionalInt32());
+    assertEquals(1, messageAfterBuild.getOptionalInt32());
+
+    message = builder.build();
+    builder.setOptionalInt64(1);
+    assertEquals(0L, message.getOptionalInt64());
+    assertEquals(1L, builder.getOptionalInt64());
+    messageAfterBuild = builder.build();
+    assertEquals(1L, messageAfterBuild.getOptionalInt64());
+    assertEquals(0L, message.getOptionalInt64());
+    builder.clearOptionalInt64();
+    assertEquals(0L, builder.getOptionalInt64());
+    assertEquals(1L, messageAfterBuild.getOptionalInt64());
+    
+    message = builder.build();
+    NestedMessage nestedMessage = NestedMessage.newBuilder()
+        .setBb(1)
+        .build();
+    builder.setOptionalLazyMessage(nestedMessage);
+    assertEquals(
+        NestedMessage.getDefaultInstance(),
+        message.getOptionalLazyMessage());
+    assertEquals(nestedMessage, builder.getOptionalLazyMessage());
+    messageAfterBuild = builder.build();
+    assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+    assertEquals(
+        NestedMessage.getDefaultInstance(),
+        message.getOptionalLazyMessage());
+    builder.clearOptionalLazyMessage();
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+    assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+
+    message = builder.build();
+    NestedMessage.Builder nestedMessageBuilder =
+        NestedMessage.newBuilder()
+            .setBb(3);
+    builder.setOptionalLazyMessage(nestedMessageBuilder);
+    assertEquals(
+        NestedMessage.getDefaultInstance(),
+        message.getOptionalLazyMessage());
+    assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage());
+    messageAfterBuild = builder.build();
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
+    assertEquals(
+        NestedMessage.getDefaultInstance(),
+        message.getOptionalLazyMessage());
+    builder.clearOptionalLazyMessage();
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
+
+    message = builder.build();
+    builder.setOptionalSfixed32(1);
+    assertEquals(0, message.getOptionalSfixed32());
+    assertEquals(1, builder.getOptionalSfixed32());
+    messageAfterBuild = builder.build();
+    assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+    assertEquals(0, message.getOptionalSfixed32());
+    builder.clearOptionalSfixed32();
+    assertEquals(0, builder.getOptionalSfixed32());
+    assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+
+    message = builder.build();
+    builder.setOptionalSfixed64(1);
+    assertEquals(0L, message.getOptionalSfixed64());
+    assertEquals(1L, builder.getOptionalSfixed64());
+    messageAfterBuild = builder.build();
+    assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+    assertEquals(0L, message.getOptionalSfixed64());
+    builder.clearOptionalSfixed64();
+    assertEquals(0L, builder.getOptionalSfixed64());
+    assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+
+    message = builder.build();
+    builder.setOptionalSint32(1);
+    assertEquals(0, message.getOptionalSint32());
+    assertEquals(1, builder.getOptionalSint32());
+    messageAfterBuild = builder.build();
+    assertEquals(1, messageAfterBuild.getOptionalSint32());
+    builder.clearOptionalSint32();
+    assertEquals(0, builder.getOptionalSint32());
+    assertEquals(1, messageAfterBuild.getOptionalSint32());
+
+    message = builder.build();
+    builder.setOptionalSint64(1);
+    assertEquals(0L, message.getOptionalSint64());
+    assertEquals(1L, builder.getOptionalSint64());
+    messageAfterBuild = builder.build();
+    assertEquals(1L, messageAfterBuild.getOptionalSint64());
+    assertEquals(0L, message.getOptionalSint64());
+    builder.clearOptionalSint64();
+    assertEquals(0L, builder.getOptionalSint64());
+    assertEquals(1L, messageAfterBuild.getOptionalSint64());
+
+    message = builder.build();
+    builder.setOptionalString("hi");
+    assertEquals("", message.getOptionalString());
+    assertEquals("hi", builder.getOptionalString());
+    messageAfterBuild = builder.build();
+    assertEquals("hi", messageAfterBuild.getOptionalString());
+    assertEquals("", message.getOptionalString());
+    builder.clearOptionalString();
+    assertEquals("", builder.getOptionalString());
+    assertEquals("hi", messageAfterBuild.getOptionalString());
+
+    message = builder.build();
+    builder.setOptionalStringBytes(ByteString.copyFromUtf8("no"));
+    assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalStringBytes());
+    assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+    builder.clearOptionalString();
+    assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalStringBytes());
+    
+    message = builder.build();
+    builder.setOptionalStringPiece("hi");
+    assertEquals("", message.getOptionalStringPiece());
+    assertEquals("hi", builder.getOptionalStringPiece());
+    messageAfterBuild = builder.build();
+    assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+    assertEquals("", message.getOptionalStringPiece());
+    builder.clearOptionalStringPiece();
+    assertEquals("", builder.getOptionalStringPiece());
+    assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+
+    message = builder.build();
+    builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no"));
+    assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalStringPieceBytes());
+    assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+    builder.clearOptionalStringPiece();
+    assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes());
+    assertEquals(
+        ByteString.copyFromUtf8("no"),
+        messageAfterBuild.getOptionalStringPieceBytes());
+
+    message = builder.build();
+    builder.setOptionalUint32(1);
+    assertEquals(0, message.getOptionalUint32());
+    assertEquals(1, builder.getOptionalUint32());
+    messageAfterBuild = builder.build();
+    assertEquals(1, messageAfterBuild.getOptionalUint32());
+    assertEquals(0, message.getOptionalUint32());
+    builder.clearOptionalUint32();
+    assertEquals(0, builder.getOptionalUint32());
+    assertEquals(1, messageAfterBuild.getOptionalUint32());
+
+    message = builder.build();
+    builder.setOptionalUint64(1);
+    assertEquals(0L, message.getOptionalUint64());
+    assertEquals(1L, builder.getOptionalUint64());
+    messageAfterBuild = builder.build();
+    assertEquals(1L, messageAfterBuild.getOptionalUint64());
+    assertEquals(0L, message.getOptionalUint64());
+    builder.clearOptionalUint64();
+    assertEquals(0L, builder.getOptionalUint64());
+    assertEquals(1L, messageAfterBuild.getOptionalUint64());
+
+    message = builder.build();
+    builder.addAllRepeatedBool(singletonList(true));
+    assertEquals(emptyList(), message.getRepeatedBoolList());
+    assertEquals(singletonList(true), builder.getRepeatedBoolList());
+    assertEquals(emptyList(), message.getRepeatedBoolList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedBool();
+    assertEquals(emptyList(), builder.getRepeatedBoolList());
+    assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+    message = builder.build();
+    builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi")));
+    assertEquals(emptyList(), message.getRepeatedBytesList());
+    assertEquals(
+        singletonList(ByteString.copyFromUtf8("hi")),
+        builder.getRepeatedBytesList());
+    assertEquals(emptyList(), message.getRepeatedBytesList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedBytes();
+    assertEquals(emptyList(), builder.getRepeatedBytesList());
+    assertEquals(
+        singletonList(ByteString.copyFromUtf8("hi")),
+        messageAfterBuild.getRepeatedBytesList());
+
+    message = builder.build();
+    builder.addAllRepeatedCord(singletonList("hi"));
+    assertEquals(emptyList(), message.getRepeatedCordList());
+    assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+    assertEquals(emptyList(), message.getRepeatedCordList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedCord();
+    assertEquals(emptyList(), builder.getRepeatedCordList());
+    assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+    message = builder.build();
+    builder.addAllRepeatedDouble(singletonList(1D));
+    assertEquals(emptyList(), message.getRepeatedDoubleList());
+    assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+    assertEquals(emptyList(), message.getRepeatedDoubleList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedDouble();
+    assertEquals(emptyList(), builder.getRepeatedDoubleList());
+    assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+    message = builder.build();
+    builder.addAllRepeatedFixed32(singletonList(1));
+    assertEquals(emptyList(), message.getRepeatedFixed32List());
+    assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+    assertEquals(emptyList(), message.getRepeatedFixed32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFixed32();
+    assertEquals(emptyList(), builder.getRepeatedFixed32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+    message = builder.build();
+    builder.addAllRepeatedFixed64(singletonList(1L));
+    assertEquals(emptyList(), message.getRepeatedFixed64List());
+    assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+    assertEquals(emptyList(), message.getRepeatedFixed64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFixed64();
+    assertEquals(emptyList(), builder.getRepeatedFixed64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+    message = builder.build();
+    builder.addAllRepeatedFloat(singletonList(1F));
+    assertEquals(emptyList(), message.getRepeatedFloatList());
+    assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+    assertEquals(emptyList(), message.getRepeatedFloatList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFloat();
+    assertEquals(emptyList(), builder.getRepeatedFloatList());
+    assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+    message = builder.build();
+    builder.addAllRepeatedForeignEnum(
+        singletonList(ForeignEnumLite.FOREIGN_LITE_BAR));
+    assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+    assertEquals(
+        singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+        builder.getRepeatedForeignEnumList());
+    assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedForeignEnum();
+    assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+    assertEquals(
+        singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+        messageAfterBuild.getRepeatedForeignEnumList());
+
+    message = builder.build();
+    builder.addAllRepeatedForeignMessage(singletonList(foreignMessage));
+    assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+    assertEquals(
+        singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+    assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedForeignMessage();
+    assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+    assertEquals(
+        singletonList(foreignMessage),
+        messageAfterBuild.getRepeatedForeignMessageList());
+
+    message = builder.build();
+    builder.addAllRepeatedGroup(
+        singletonList(RepeatedGroup.getDefaultInstance()));
+    assertEquals(emptyList(), message.getRepeatedGroupList());
+    assertEquals(
+        singletonList(RepeatedGroup.getDefaultInstance()),
+        builder.getRepeatedGroupList());
+    assertEquals(emptyList(), message.getRepeatedGroupList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedGroup();
+    assertEquals(emptyList(), builder.getRepeatedGroupList());
+    assertEquals(
+        singletonList(RepeatedGroup.getDefaultInstance()),
+        messageAfterBuild.getRepeatedGroupList());
+
+    message = builder.build();
+    builder.addAllRepeatedInt32(singletonList(1));
+    assertEquals(emptyList(), message.getRepeatedInt32List());
+    assertEquals(singletonList(1), builder.getRepeatedInt32List());
+    assertEquals(emptyList(), message.getRepeatedInt32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedInt32();
+    assertEquals(emptyList(), builder.getRepeatedInt32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+    message = builder.build();
+    builder.addAllRepeatedInt64(singletonList(1L));
+    assertEquals(emptyList(), message.getRepeatedInt64List());
+    assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+    assertEquals(emptyList(), message.getRepeatedInt64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedInt64();
+    assertEquals(emptyList(), builder.getRepeatedInt64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+    message = builder.build();
+    builder.addAllRepeatedLazyMessage(singletonList(nestedMessage));
+    assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+    assertEquals(
+        singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+    assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedLazyMessage();
+    assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+    assertEquals(
+        singletonList(nestedMessage),
+        messageAfterBuild.getRepeatedLazyMessageList());
+
+    message = builder.build();
+    builder.addAllRepeatedSfixed32(singletonList(1));
+    assertEquals(emptyList(), message.getRepeatedSfixed32List());
+    assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+    assertEquals(emptyList(), message.getRepeatedSfixed32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSfixed32();
+    assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+    message = builder.build();
+    builder.addAllRepeatedSfixed64(singletonList(1L));
+    assertEquals(emptyList(), message.getRepeatedSfixed64List());
+    assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+    assertEquals(emptyList(), message.getRepeatedSfixed64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSfixed64();
+    assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+    assertEquals(
+        singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+    message = builder.build();
+    builder.addAllRepeatedSint32(singletonList(1));
+    assertEquals(emptyList(), message.getRepeatedSint32List());
+    assertEquals(singletonList(1), builder.getRepeatedSint32List());
+    assertEquals(emptyList(), message.getRepeatedSint32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSint32();
+    assertEquals(emptyList(), builder.getRepeatedSint32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+    message = builder.build();
+    builder.addAllRepeatedSint64(singletonList(1L));
+    assertEquals(emptyList(), message.getRepeatedSint64List());
+    assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+    assertEquals(emptyList(), message.getRepeatedSint64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSint64();
+    assertEquals(emptyList(), builder.getRepeatedSint64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+    message = builder.build();
+    builder.addAllRepeatedString(singletonList("hi"));
+    assertEquals(emptyList(), message.getRepeatedStringList());
+    assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+    assertEquals(emptyList(), message.getRepeatedStringList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedString();
+    assertEquals(emptyList(), builder.getRepeatedStringList());
+    assertEquals(
+        singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+    message = builder.build();
+    builder.addAllRepeatedStringPiece(singletonList("hi"));
+    assertEquals(emptyList(), message.getRepeatedStringPieceList());
+    assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+    assertEquals(emptyList(), message.getRepeatedStringPieceList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedStringPiece();
+    assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+    assertEquals(
+        singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+    message = builder.build();
+    builder.addAllRepeatedUint32(singletonList(1));
+    assertEquals(emptyList(), message.getRepeatedUint32List());
+    assertEquals(singletonList(1), builder.getRepeatedUint32List());
+    assertEquals(emptyList(), message.getRepeatedUint32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedUint32();
+    assertEquals(emptyList(), builder.getRepeatedUint32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+    message = builder.build();
+    builder.addAllRepeatedUint64(singletonList(1L));
+    assertEquals(emptyList(), message.getRepeatedUint64List());
+    assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+    assertEquals(emptyList(), message.getRepeatedUint64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedUint64();
+    assertEquals(emptyList(), builder.getRepeatedUint64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+    message = builder.build();
+    builder.addRepeatedBool(true);
+    assertEquals(emptyList(), message.getRepeatedBoolList());
+    assertEquals(singletonList(true), builder.getRepeatedBoolList());
+    assertEquals(emptyList(), message.getRepeatedBoolList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedBool();
+    assertEquals(emptyList(), builder.getRepeatedBoolList());
+    assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+    message = builder.build();
+    builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+    assertEquals(emptyList(), message.getRepeatedBytesList());
+    assertEquals(
+        singletonList(ByteString.copyFromUtf8("hi")),
+        builder.getRepeatedBytesList());
+    assertEquals(emptyList(), message.getRepeatedBytesList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedBytes();
+    assertEquals(emptyList(), builder.getRepeatedBytesList());
+    assertEquals(
+        singletonList(ByteString.copyFromUtf8("hi")),
+        messageAfterBuild.getRepeatedBytesList());
+
+    message = builder.build();
+    builder.addRepeatedCord("hi");
+    assertEquals(emptyList(), message.getRepeatedCordList());
+    assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+    assertEquals(emptyList(), message.getRepeatedCordList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedCord();
+    assertEquals(emptyList(), builder.getRepeatedCordList());
+    assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+    message = builder.build();
+    builder.addRepeatedDouble(1D);
+    assertEquals(emptyList(), message.getRepeatedDoubleList());
+    assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+    assertEquals(emptyList(), message.getRepeatedDoubleList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedDouble();
+    assertEquals(emptyList(), builder.getRepeatedDoubleList());
+    assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+    message = builder.build();
+    builder.addRepeatedFixed32(1);
+    assertEquals(emptyList(), message.getRepeatedFixed32List());
+    assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+    assertEquals(emptyList(), message.getRepeatedFixed32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFixed32();
+    assertEquals(emptyList(), builder.getRepeatedFixed32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+    message = builder.build();
+    builder.addRepeatedFixed64(1L);
+    assertEquals(emptyList(), message.getRepeatedFixed64List());
+    assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+    assertEquals(emptyList(), message.getRepeatedFixed64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFixed64();
+    assertEquals(emptyList(), builder.getRepeatedFixed64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+    message = builder.build();
+    builder.addRepeatedFloat(1F);
+    assertEquals(emptyList(), message.getRepeatedFloatList());
+    assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+    assertEquals(emptyList(), message.getRepeatedFloatList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedFloat();
+    assertEquals(emptyList(), builder.getRepeatedFloatList());
+    assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+    message = builder.build();
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+    assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+    assertEquals(
+        singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+        builder.getRepeatedForeignEnumList());
+    assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedForeignEnum();
+    assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+    assertEquals(
+        singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+        messageAfterBuild.getRepeatedForeignEnumList());
+
+    message = builder.build();
+    builder.addRepeatedForeignMessage(foreignMessage);
+    assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+    assertEquals(
+        singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+    assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+    messageAfterBuild = builder.build();
+    builder.removeRepeatedForeignMessage(0);
+    assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+    assertEquals(
+        singletonList(foreignMessage),
+        messageAfterBuild.getRepeatedForeignMessageList());
+
+    message = builder.build();
+    builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance());
+    assertEquals(emptyList(), message.getRepeatedGroupList());
+    assertEquals(
+        singletonList(RepeatedGroup.getDefaultInstance()),
+        builder.getRepeatedGroupList());
+    assertEquals(emptyList(), message.getRepeatedGroupList());
+    messageAfterBuild = builder.build();
+    builder.removeRepeatedGroup(0);
+    assertEquals(emptyList(), builder.getRepeatedGroupList());
+    assertEquals(
+        singletonList(RepeatedGroup.getDefaultInstance()),
+        messageAfterBuild.getRepeatedGroupList());
+
+    message = builder.build();
+    builder.addRepeatedInt32(1);
+    assertEquals(emptyList(), message.getRepeatedInt32List());
+    assertEquals(singletonList(1), builder.getRepeatedInt32List());
+    assertEquals(emptyList(), message.getRepeatedInt32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedInt32();
+    assertEquals(emptyList(), builder.getRepeatedInt32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+    message = builder.build();
+    builder.addRepeatedInt64(1L);
+    assertEquals(emptyList(), message.getRepeatedInt64List());
+    assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+    assertEquals(emptyList(), message.getRepeatedInt64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedInt64();
+    assertEquals(emptyList(), builder.getRepeatedInt64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+    message = builder.build();
+    builder.addRepeatedLazyMessage(nestedMessage);
+    assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+    assertEquals(
+        singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+    assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+    messageAfterBuild = builder.build();
+    builder.removeRepeatedLazyMessage(0);
+    assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+    assertEquals(
+        singletonList(nestedMessage),
+        messageAfterBuild.getRepeatedLazyMessageList());
+
+    message = builder.build();
+    builder.addRepeatedSfixed32(1);
+    assertEquals(emptyList(), message.getRepeatedSfixed32List());
+    assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+    assertEquals(emptyList(), message.getRepeatedSfixed32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSfixed32();
+    assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+    message = builder.build();
+    builder.addRepeatedSfixed64(1L);
+    assertEquals(emptyList(), message.getRepeatedSfixed64List());
+    assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+    assertEquals(emptyList(), message.getRepeatedSfixed64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSfixed64();
+    assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+    assertEquals(
+        singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+    message = builder.build();
+    builder.addRepeatedSint32(1);
+    assertEquals(emptyList(), message.getRepeatedSint32List());
+    assertEquals(singletonList(1), builder.getRepeatedSint32List());
+    assertEquals(emptyList(), message.getRepeatedSint32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSint32();
+    assertEquals(emptyList(), builder.getRepeatedSint32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+    message = builder.build();
+    builder.addRepeatedSint64(1L);
+    assertEquals(emptyList(), message.getRepeatedSint64List());
+    assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+    assertEquals(emptyList(), message.getRepeatedSint64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedSint64();
+    assertEquals(emptyList(), builder.getRepeatedSint64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+    message = builder.build();
+    builder.addRepeatedString("hi");
+    assertEquals(emptyList(), message.getRepeatedStringList());
+    assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+    assertEquals(emptyList(), message.getRepeatedStringList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedString();
+    assertEquals(emptyList(), builder.getRepeatedStringList());
+    assertEquals(
+        singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+    message = builder.build();
+    builder.addRepeatedStringPiece("hi");
+    assertEquals(emptyList(), message.getRepeatedStringPieceList());
+    assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+    assertEquals(emptyList(), message.getRepeatedStringPieceList());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedStringPiece();
+    assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+    assertEquals(
+        singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+    message = builder.build();
+    builder.addRepeatedUint32(1);
+    assertEquals(emptyList(), message.getRepeatedUint32List());
+    assertEquals(singletonList(1), builder.getRepeatedUint32List());
+    assertEquals(emptyList(), message.getRepeatedUint32List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedUint32();
+    assertEquals(emptyList(), builder.getRepeatedUint32List());
+    assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+    message = builder.build();
+    builder.addRepeatedUint64(1L);
+    assertEquals(emptyList(), message.getRepeatedUint64List());
+    assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+    assertEquals(emptyList(), message.getRepeatedUint64List());
+    messageAfterBuild = builder.build();
+    builder.clearRepeatedUint64();
+    assertEquals(emptyList(), builder.getRepeatedUint64List());
+    assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+    
+    message = builder.build();
+    builder.addRepeatedBool(true);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedBoolCount());
+    builder.setRepeatedBool(0, false);
+    assertEquals(true, messageAfterBuild.getRepeatedBool(0));
+    assertEquals(false, builder.getRepeatedBool(0));
+    builder.clearRepeatedBool();
+    
+    message = builder.build();
+    builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedBytesCount());
+    builder.setRepeatedBytes(0, ByteString.EMPTY);
+    assertEquals(
+        ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0));
+    assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0));
+    builder.clearRepeatedBytes();
+
+    message = builder.build();
+    builder.addRepeatedCord("hi");
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedCordCount());
+    builder.setRepeatedCord(0, "");
+    assertEquals("hi", messageAfterBuild.getRepeatedCord(0));
+    assertEquals("", builder.getRepeatedCord(0));
+    builder.clearRepeatedCord();
+    message = builder.build();
+
+    builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi"));
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedCordCount());
+    builder.setRepeatedCord(0, "");
+    assertEquals(
+        ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0));
+    assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0));
+    builder.clearRepeatedCord();
+
+    message = builder.build();
+    builder.addRepeatedDouble(1D);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedDoubleCount());
+    builder.setRepeatedDouble(0, 0D);
+    assertEquals(1D, messageAfterBuild.getRepeatedDouble(0));
+    assertEquals(0D, builder.getRepeatedDouble(0));
+    builder.clearRepeatedDouble();
+
+    message = builder.build();
+    builder.addRepeatedFixed32(1);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedFixed32Count());
+    builder.setRepeatedFixed32(0, 0);
+    assertEquals(1, messageAfterBuild.getRepeatedFixed32(0));
+    assertEquals(0, builder.getRepeatedFixed32(0));
+    builder.clearRepeatedFixed32();
+
+    message = builder.build();
+    builder.addRepeatedFixed64(1L);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedFixed64Count());
+    builder.setRepeatedFixed64(0, 0L);
+    assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0));
+    assertEquals(0L, builder.getRepeatedFixed64(0));
+    builder.clearRepeatedFixed64();
+
+    message = builder.build();
+    builder.addRepeatedFloat(1F);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedFloatCount());
+    builder.setRepeatedFloat(0, 0F);
+    assertEquals(1F, messageAfterBuild.getRepeatedFloat(0));
+    assertEquals(0F, builder.getRepeatedFloat(0));
+    builder.clearRepeatedFloat();
+
+    message = builder.build();
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedForeignEnumCount());
+    builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO);
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_BAR,
+        messageAfterBuild.getRepeatedForeignEnum(0));
+    assertEquals(
+        ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0));
+    builder.clearRepeatedForeignEnum();
+
+    message = builder.build();
+    builder.addRepeatedForeignMessage(foreignMessage);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedForeignMessageCount());
+    builder.setRepeatedForeignMessage(
+        0, ForeignMessageLite.getDefaultInstance());
+    assertEquals(
+        foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        builder.getRepeatedForeignMessage(0));
+    builder.clearRepeatedForeignMessage();
+    
+    message = builder.build();
+    builder.addRepeatedForeignMessage(foreignMessageBuilder);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedForeignMessageCount());
+    builder.setRepeatedForeignMessage(
+        0, ForeignMessageLite.getDefaultInstance());
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0));
+    assertEquals(
+        ForeignMessageLite.getDefaultInstance(),
+        builder.getRepeatedForeignMessage(0));
+    builder.clearRepeatedForeignMessage();
+
+    message = builder.build();
+    builder.addRepeatedForeignMessage(0, foreignMessage);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedForeignMessageCount());
+    builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
+    assertEquals(
+        foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+    assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0));
+    builder.clearRepeatedForeignMessage();
+
+    message = builder.build();
+    RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder()
+        .setA(1)
+        .build();
+    builder.addRepeatedGroup(repeatedGroup);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedGroupCount());
+    builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+    assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+    assertEquals(
+        RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+    builder.clearRepeatedGroup();
+    
+    message = builder.build();
+    builder.addRepeatedGroup(0, repeatedGroup);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedGroupCount());
+    builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+    assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+    assertEquals(
+        RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+    builder.clearRepeatedGroup();
+    
+    message = builder.build();
+    RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder()
+        .setA(3);
+    builder.addRepeatedGroup(repeatedGroupBuilder);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedGroupCount());
+    builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+    assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
+    assertEquals(
+        RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+    builder.clearRepeatedGroup();
+    
+    message = builder.build();
+    builder.addRepeatedGroup(0, repeatedGroupBuilder);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedGroupCount());
+    builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+    assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
+    assertEquals(
+        RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+    builder.clearRepeatedGroup();
+
+    message = builder.build();
+    builder.addRepeatedInt32(1);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedInt32Count());
+    builder.setRepeatedInt32(0, 0);
+    assertEquals(1, messageAfterBuild.getRepeatedInt32(0));
+    assertEquals(0, builder.getRepeatedInt32(0));
+    builder.clearRepeatedInt32();
+
+    message = builder.build();
+    builder.addRepeatedInt64(1L);
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedInt64Count());
+    builder.setRepeatedInt64(0, 0L);
+    assertEquals(1L, messageAfterBuild.getRepeatedInt64(0));
+    assertEquals(0L, builder.getRepeatedInt64(0));
+    builder.clearRepeatedInt64();
+    
+    message = builder.build();
+    builder.addRepeatedLazyMessage(nestedMessage);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedLazyMessageCount());
+    builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+    assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+    builder.clearRepeatedLazyMessage();
+    
+    message = builder.build();
+    builder.addRepeatedLazyMessage(0, nestedMessage);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedLazyMessageCount());
+    builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+    assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+    builder.clearRepeatedLazyMessage();
+    
+    message = builder.build();
+    builder.addRepeatedLazyMessage(nestedMessageBuilder);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedLazyMessageCount());
+    builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+    builder.clearRepeatedLazyMessage();
+    
+    message = builder.build();
+    builder.addRepeatedLazyMessage(0, nestedMessageBuilder);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedLazyMessageCount());
+    builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
+    assertEquals(
+        NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+    builder.clearRepeatedLazyMessage();
+
+    message = builder.build();
+    builder.addRepeatedSfixed32(1);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedSfixed32Count());
+    builder.setRepeatedSfixed32(0, 0);
+    assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0));
+    assertEquals(0, builder.getRepeatedSfixed32(0));
+    builder.clearRepeatedSfixed32();
+
+    message = builder.build();
+    builder.addRepeatedSfixed64(1L);
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedSfixed64Count());
+    builder.setRepeatedSfixed64(0, 0L);
+    assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0));
+    assertEquals(0L, builder.getRepeatedSfixed64(0));
+    builder.clearRepeatedSfixed64();
+
+    message = builder.build();
+    builder.addRepeatedSint32(1);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedSint32Count());
+    builder.setRepeatedSint32(0, 0);
+    assertEquals(1, messageAfterBuild.getRepeatedSint32(0));
+    assertEquals(0, builder.getRepeatedSint32(0));
+    builder.clearRepeatedSint32();
+
+    message = builder.build();
+    builder.addRepeatedSint64(1L);
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedSint64Count());
+    builder.setRepeatedSint64(0, 0L);
+    assertEquals(1L, messageAfterBuild.getRepeatedSint64(0));
+    assertEquals(0L, builder.getRepeatedSint64(0));
+    builder.clearRepeatedSint64();
+
+    message = builder.build();
+    builder.addRepeatedString("hi");
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedStringCount());
+    builder.setRepeatedString(0, "");
+    assertEquals("hi", messageAfterBuild.getRepeatedString(0));
+    assertEquals("", builder.getRepeatedString(0));
+    builder.clearRepeatedString();
+
+    message = builder.build();
+    builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi"));
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedStringCount());
+    builder.setRepeatedString(0, "");
+    assertEquals(
+        ByteString.copyFromUtf8("hi"),
+        messageAfterBuild.getRepeatedStringBytes(0));
+    assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0));
+    builder.clearRepeatedString();
+
+    message = builder.build();
+    builder.addRepeatedStringPiece("hi");
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedStringPieceCount());
+    builder.setRepeatedStringPiece(0, "");
+    assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0));
+    assertEquals("", builder.getRepeatedStringPiece(0));
+    builder.clearRepeatedStringPiece();
+
+    message = builder.build();
+    builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi"));
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedStringPieceCount());
+    builder.setRepeatedStringPiece(0, "");
+    assertEquals(
+        ByteString.copyFromUtf8("hi"),
+        messageAfterBuild.getRepeatedStringPieceBytes(0));
+    assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0));
+    builder.clearRepeatedStringPiece();
+
+    message = builder.build();
+    builder.addRepeatedUint32(1);
+    messageAfterBuild = builder.build();
+    assertEquals(0, message.getRepeatedUint32Count());
+    builder.setRepeatedUint32(0, 0);
+    assertEquals(1, messageAfterBuild.getRepeatedUint32(0));
+    assertEquals(0, builder.getRepeatedUint32(0));
+    builder.clearRepeatedUint32();
+
+    message = builder.build();
+    builder.addRepeatedUint64(1L);
+    messageAfterBuild = builder.build();
+    assertEquals(0L, message.getRepeatedUint64Count());
+    builder.setRepeatedUint64(0, 0L);
+    assertEquals(1L, messageAfterBuild.getRepeatedUint64(0));
+    assertEquals(0L, builder.getRepeatedUint64(0));
+    builder.clearRepeatedUint64();
+
+    message = builder.build();
+    assertEquals(0, message.getSerializedSize());
+    builder.mergeFrom(TestAllTypesLite.newBuilder()
+        .setOptionalBool(true)
+        .build());
+    assertEquals(0, message.getSerializedSize());
+    assertEquals(true, builder.build().getOptionalBool());
+    builder.clearOptionalBool();
+
+    message = builder.build();
+    assertEquals(0, message.getSerializedSize());
+    builder.mergeFrom(TestAllTypesLite.newBuilder()
+        .setOptionalBool(true)
+        .build());
+    assertEquals(0, message.getSerializedSize());
+    assertEquals(true, builder.build().getOptionalBool());
+    builder.clear();
+    assertEquals(0, builder.build().getSerializedSize());
+
+    message = builder.build();
+    assertEquals(0, message.getSerializedSize());
+    builder.mergeOptionalForeignMessage(foreignMessage);
+    assertEquals(0, message.getSerializedSize());
+    assertEquals(
+        foreignMessage.getC(),
+        builder.build().getOptionalForeignMessage().getC());
+    builder.clearOptionalForeignMessage();
+
+    message = builder.build();
+    assertEquals(0, message.getSerializedSize());
+    builder.mergeOptionalLazyMessage(nestedMessage);
+    assertEquals(0, message.getSerializedSize());
+    assertEquals(
+        nestedMessage.getBb(),
+        builder.build().getOptionalLazyMessage().getBb());
+    builder.clearOptionalLazyMessage();
+    
+    message = builder.build();
+    builder.setOneofString("hi");
+    assertEquals(
+        OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase());
+    assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase());
+    assertEquals("hi", builder.getOneofString());
+    messageAfterBuild = builder.build();
+    assertEquals(
+        OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+    assertEquals("hi", messageAfterBuild.getOneofString());
+    builder.setOneofUint32(1);
+    assertEquals(
+        OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+    assertEquals("hi", messageAfterBuild.getOneofString());
+    assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
+    assertEquals(1, builder.getOneofUint32());
+    TestAllTypesLiteOrBuilder messageOrBuilder = builder;
+    assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase());
+    
+    TestAllExtensionsLite.Builder extendableMessageBuilder =
+        TestAllExtensionsLite.newBuilder();
+    TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build();
+    extendableMessageBuilder.setExtension(
+        UnittestLite.optionalInt32ExtensionLite, 1);
+    assertFalse(extendableMessage.hasExtension(
+        UnittestLite.optionalInt32ExtensionLite));
+    extendableMessage = extendableMessageBuilder.build();
+    assertEquals(
+        1, (int) extendableMessageBuilder.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        1, (int) extendableMessage.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    extendableMessageBuilder.setExtension(
+        UnittestLite.optionalInt32ExtensionLite, 3);
+    assertEquals(
+        3, (int) extendableMessageBuilder.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        1, (int) extendableMessage.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    extendableMessage = extendableMessageBuilder.build();
+    assertEquals(
+        3, (int) extendableMessageBuilder.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        3, (int) extendableMessage.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    
+    // No extension registry, so it should be in unknown fields.
+    extendableMessage =
+        TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray());
+    assertFalse(extendableMessage.hasExtension(
+        UnittestLite.optionalInt32ExtensionLite));
+    
+    extendableMessageBuilder = extendableMessage.toBuilder();
+    extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11)
+        .build());
+    
+    extendableMessage = extendableMessageBuilder.build();
+    ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+    UnittestLite.registerAllExtensions(registry);
+    extendableMessage = TestAllExtensionsLite.parseFrom(
+        extendableMessage.toByteArray(), registry);
+    
+    // The unknown field was preserved.
+    assertEquals(
+        3, (int) extendableMessage.getExtension(
+            UnittestLite.optionalInt32ExtensionLite));
+    assertEquals(
+        11, (int) extendableMessage.getExtension(
+            UnittestLite.optionalFixed32ExtensionLite));
+  }
+
+  public void testToStringDefaultInstance() throws Exception {
+    assertToStringEquals("", TestAllTypesLite.getDefaultInstance());
+  }
+
+  public void testToStringPrimitives() throws Exception {
+    TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+        .setOptionalInt32(1)
+        .setOptionalInt64(9223372036854775807L)
+        .build();
+    assertToStringEquals("optional_int32: 1\noptional_int64: 9223372036854775807", proto);
+
+    proto = TestAllTypesLite.newBuilder()
+        .setOptionalBool(true)
+        .setOptionalNestedEnum(TestAllTypesLite.NestedEnum.BAZ)
+        .build();
+    assertToStringEquals("optional_bool: true\noptional_nested_enum: BAZ", proto);
+
+    proto = TestAllTypesLite.newBuilder()
+        .setOptionalFloat(2.72f)
+        .setOptionalDouble(3.14)
+        .build();
+    assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto);
+  }
+
+  public void testToStringStringFields() throws Exception {
+    TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+        .setOptionalString("foo\"bar\nbaz\\")
+        .build();
+    assertToStringEquals("optional_string: \"foo\\\"bar\\nbaz\\\\\"", proto);
+
+    proto = TestAllTypesLite.newBuilder()
+        .setOptionalString("\u6587")
+        .build();
+    assertToStringEquals("optional_string: \"\\346\\226\\207\"", proto);
+  }
+
+  public void testToStringNestedMessage() throws Exception {
+    TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+        .setOptionalNestedMessage(TestAllTypesLite.NestedMessage.getDefaultInstance())
+        .build();
+    assertToStringEquals("optional_nested_message {\n}", proto);
+
+    proto = TestAllTypesLite.newBuilder()
+        .setOptionalNestedMessage(
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+        .build();
+    assertToStringEquals("optional_nested_message {\n  bb: 7\n}", proto);
+  }
+
+  public void testToStringRepeatedFields() throws Exception {
+    TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+        .addRepeatedInt32(32)
+        .addRepeatedInt32(32)
+        .addRepeatedInt64(64)
+        .build();
+    assertToStringEquals("repeated_int32: 32\nrepeated_int32: 32\nrepeated_int64: 64", proto);
+
+    proto = TestAllTypesLite.newBuilder()
+        .addRepeatedLazyMessage(
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+        .addRepeatedLazyMessage(
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(8))
+        .build();
+    assertToStringEquals(
+        "repeated_lazy_message {\n  bb: 7\n}\nrepeated_lazy_message {\n  bb: 8\n}",
+        proto);
+  }
+
+  public void testToStringForeignFields() throws Exception {
+    TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+        .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .setOptionalForeignMessage(
+            ForeignMessageLite.newBuilder()
+            .setC(3))
+        .build();
+    assertToStringEquals(
+        "optional_foreign_enum: FOREIGN_LITE_BAR\noptional_foreign_message {\n  c: 3\n}",
+        proto);
+  }
+
+  public void testToStringExtensions() throws Exception {
+    TestAllExtensionsLite message = TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "spam")
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs")
+        .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+            TestAllTypesLite.NestedEnum.BAZ)
+        .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+        .build();
+    assertToStringEquals(
+        "[1]: 123\n[18] {\n  bb: 7\n}\n[21]: 3\n[44]: \"spam\"\n[44]: \"eggs\"",
+        message);
+  }
+
+  public void testToStringUnknownFields() throws Exception {
+    TestAllExtensionsLite messageWithExtensions = TestAllExtensionsLite.newBuilder()
+        .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "spam")
+        .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs")
+        .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+            TestAllTypesLite.NestedEnum.BAZ)
+        .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+            TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+        .build();
+    TestAllExtensionsLite messageWithUnknownFields = TestAllExtensionsLite.parseFrom(
+        messageWithExtensions.toByteArray());
+    assertToStringEquals(
+        "1: 123\n18: \"\\b\\a\"\n21: 3\n44: \"spam\"\n44: \"eggs\"",
+        messageWithUnknownFields);
+  }
+  
+  public void testToStringLazyMessage() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1).build())
+        .build();
+    assertToStringEquals("optional_lazy_message {\n  bb: 1\n}", message);
+  }
+  
+  public void testToStringGroup() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOptionalGroup(OptionalGroup.newBuilder().setA(1).build())
+        .build();
+    assertToStringEquals("optional_group {\n  a: 1\n}", message);
+  }
+  
+  public void testToStringOneof() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOneofString("hello")
+        .build();
+    assertToStringEquals("oneof_string: \"hello\"", message);
+  }
+
+  // Asserts that the toString() representation of the message matches the expected. This verifies
+  // the first line starts with a comment; but, does not factor in said comment as part of the
+  // comparison as it contains unstable addresses.
+  private static void assertToStringEquals(String expected, MessageLite message) {
+    String toString = message.toString();
+    assertEquals('#', toString.charAt(0));
+    if (toString.indexOf("\n") >= 0) {
+      toString = toString.substring(toString.indexOf("\n") + 1);
+    } else {
+      toString = "";
+    }
+    assertEquals(expected, toString);
+  }
+  
+  public void testParseLazy() throws Exception {
+    ByteString bb = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.newBuilder()
+            .setBb(11)
+            .build())
+        .build().toByteString();
+    ByteString cc = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.newBuilder()
+            .setCc(22)
+            .build())
+        .build().toByteString();
+    
+    ByteString concat = bb.concat(cc);
+    TestAllTypesLite message = TestAllTypesLite.parseFrom(concat);
+
+    assertEquals(11, message.getOptionalLazyMessage().getBb());
+    assertEquals(22L, message.getOptionalLazyMessage().getCc());
+  }
+  
+  public void testParseLazy_oneOf() throws Exception {
+    ByteString bb = TestAllTypesLite.newBuilder()
+        .setOneofLazyNestedMessage(NestedMessage.newBuilder()
+            .setBb(11)
+            .build())
+        .build().toByteString();
+    ByteString cc = TestAllTypesLite.newBuilder()
+        .setOneofLazyNestedMessage(NestedMessage.newBuilder()
+            .setCc(22)
+            .build())
+        .build().toByteString();
+    
+    ByteString concat = bb.concat(cc);
+    TestAllTypesLite message = TestAllTypesLite.parseFrom(concat);
+
+    assertEquals(11, message.getOneofLazyNestedMessage().getBb());
+    assertEquals(22L, message.getOneofLazyNestedMessage().getCc());
+  }
+
+  public void testMergeFromStream_repeatedField() throws Exception {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+        .addRepeatedString("hello");
+    builder.mergeFrom(CodedInputStream.newInstance(builder.build().toByteArray()));
+
+    assertEquals(2, builder.getRepeatedStringCount());
+  }
+
+  public void testMergeFromStream_invalidBytes() throws Exception {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+        .setDefaultBool(true);
+    try {
+      builder.mergeFrom(CodedInputStream.newInstance("Invalid bytes".getBytes(Internal.UTF_8)));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {}
+  }
+  
+  public void testMergeFrom_sanity() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    byte[] bytes = one.toByteArray();
+    TestAllTypesLite two = TestAllTypesLite.parseFrom(bytes);
+    
+    one = one.toBuilder().mergeFrom(one).build();
+    two = two.toBuilder().mergeFrom(bytes).build();
+    assertEquals(one, two);
+    assertEquals(two, one);
+    assertEquals(one.hashCode(), two.hashCode());
+  }
+  
+  public void testEquals_notEqual() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    byte[] bytes = one.toByteArray();
+    TestAllTypesLite two = one.toBuilder().mergeFrom(one).mergeFrom(bytes).build();
+    
+    assertFalse(one.equals(two));
+    assertFalse(two.equals(one));
+    
+    assertFalse(one.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(one));
+    
+    TestAllTypesLite oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofLazyNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalForeignMessage(ForeignMessageLite.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalGroup(OptionalGroup.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalPublicImportMessage(PublicImportMessageLite.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedLazyMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+  }
+
+  public void testEquals() throws Exception {
+    // Check that two identical objs are equal.
+    Foo foo1a = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo1b = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo2 = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo2"))
+        .build();
+
+    // Check that equals is doing value rather than object equality.
+    assertEquals(foo1a, foo1b);
+    assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+    // Check that a diffeent object is not equal.
+    assertFalse(foo1a.equals(foo2));
+
+    // Check that two objects which have different types but the same field values are not
+    // considered to be equal.
+    Bar bar = Bar.newBuilder().setName("bar").build();
+    BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+    assertFalse(bar.equals(barPrime));
+  }
+
+  public void testOneofEquals() throws Exception {
+    TestOneofEquals.Builder builder = TestOneofEquals.newBuilder();
+    TestOneofEquals message1 = builder.build();
+    // Set message2's name field to default value. The two messages should be different when we
+    // check with the oneof case.
+    builder.setName("");
+    TestOneofEquals message2 = builder.build();
+    assertFalse(message1.equals(message2));
+  }
+  
+  public void testEquals_sanity() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    TestAllTypesLite two = TestAllTypesLite.parseFrom(one.toByteArray());
+    assertEquals(one, two);
+    assertEquals(one.hashCode(), two.hashCode());
+    
+    assertEquals(
+        one.toBuilder().mergeFrom(two).build(),
+        two.toBuilder().mergeFrom(two.toByteArray()).build());
+  }
+
+  public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+    Foo fooWithOnlyValue = Foo.newBuilder()
+        .setValue(1)
+        .build();
+
+    Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+        .setValue(1)
+        .setExtension(Bar.fooExt, Bar.newBuilder()
+            .setName("name")
+            .build())
+        .build();
+
+    Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+    assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+    assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+  }
+  
+  // Test to ensure we avoid a class cast exception with oneofs.
+  public void testEquals_oneOfMessages() {
+    TestAllTypesLite mine = TestAllTypesLite.newBuilder()
+        .setOneofString("Hello")
+        .build();
+    
+    TestAllTypesLite other = TestAllTypesLite.newBuilder()
+        .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    
+    assertFalse(mine.equals(other));
+    assertFalse(other.equals(mine));
+  }
+
+  private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+    assertFalse(o1.equals(o2));
+    assertFalse(o1.hashCode() == o2.hashCode());
+  }
+
+  public void testRecursiveHashcode() {
+    // This tests that we don't infinite loop.
+    TestRecursiveOneof.getDefaultInstance().hashCode();
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
new file mode 100644
index 0000000..2e7792a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -0,0 +1,545 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Test {@code LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@code LiteralByteString}
+ * such as {@code BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+  protected static final String UTF_8 = "UTF-8";
+
+  protected String classUnderTest;
+  protected byte[] referenceBytes;
+  protected ByteString stringUnderTest;
+  protected int expectedHashCode;
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "LiteralByteString";
+    referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+    stringUnderTest = ByteString.copyFrom(referenceBytes);
+    expectedHashCode = 331161852;
+  }
+
+  public void testExpectedType() {
+    String actualClassName = getActualClassName(stringUnderTest);
+    assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
+  }
+
+  protected String getActualClassName(Object object) {
+    return object.getClass().getSimpleName();
+  }
+
+  public void testByteAt() {
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+      stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+    }
+    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+  }
+
+  public void testByteIterator() {
+    boolean stillEqual = true;
+    ByteString.ByteIterator iter = stringUnderTest.iterator();
+    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+      stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+    }
+    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+    assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+    try {
+      iter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+  }
+
+  public void testByteIterable() {
+    boolean stillEqual = true;
+    int j = 0;
+    for (byte quantum : stringUnderTest) {
+      stillEqual = (referenceBytes[j] == quantum);
+      ++j;
+    }
+    assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+    assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+  }
+
+  public void testSize() {
+    assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+        stringUnderTest.size());
+  }
+
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
+  }
+
+  public void testIsBalanced() {
+    assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
+  }
+
+  public void testCopyTo_ByteArrayOffsetLength() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+    int sourceOffset = 213;
+    stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < length; ++i) {
+      stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+    }
+    assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+  }
+
+  public void testCopyTo_ByteArrayOffsetLengthErrors() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+
+    try {
+      // Copy one too many bytes
+      stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+          destinationOffset, length);
+      fail("Should have thrown an exception when copying too many bytes of a "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative sourceOffset
+      stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+      fail("Should have thrown an exception when given a negative sourceOffset in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative destinationOffset
+      stringUnderTest.copyTo(destination, 0, -1, length);
+      fail("Should have thrown an exception when given a negative destinationOffset in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative size
+      stringUnderTest.copyTo(destination, 0, 0, -1);
+      fail("Should have thrown an exception when given a negative size in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large sourceOffset
+      stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large destinationOffset
+      stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+  }
+
+  public void testCopyTo_ByteBuffer() {
+    ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+    stringUnderTest.copyTo(myBuffer);
+    assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+        Arrays.equals(referenceBytes, myBuffer.array()));
+  }
+
+  public void testMarkSupported() {
+    InputStream stream = stringUnderTest.newInput();
+    assertTrue(classUnderTest + ".newInput() must support marking", stream.markSupported());
+  }
+
+  public void testMarkAndReset() throws IOException {
+    int fraction = stringUnderTest.size() / 3;
+
+    InputStream stream = stringUnderTest.newInput();
+    stream.mark(stringUnderTest.size()); // First, mark() the end.
+
+    skipFully(stream, fraction); // Skip a large fraction, but not all.
+    int available = stream.available();
+    assertTrue(
+        classUnderTest + ": after skipping to the 'middle', half the bytes are available",
+        (stringUnderTest.size() - fraction) == available);
+    stream.reset();
+
+    skipFully(stream, stringUnderTest.size()); // Skip to the end.
+    available = stream.available();
+    assertTrue(
+        classUnderTest + ": after skipping to the end, no more bytes are available",
+        0 == available);
+  }
+
+  /**
+   * Discards {@code n} bytes of data from the input stream. This method
+   * will block until the full amount has been skipped. Does not close the
+   * stream.
+   * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+   *
+   * @param in the input stream to read from
+   * @param n the number of bytes to skip
+   * @throws EOFException if this stream reaches the end before skipping all
+   *     the bytes
+   * @throws IOException if an I/O error occurs, or the stream does not
+   *     support skipping
+   */
+  static void skipFully(InputStream in, long n) throws IOException {
+    long toSkip = n;
+    while (n > 0) {
+      long amt = in.skip(n);
+      if (amt == 0) {
+        // Force a blocking read to avoid infinite loop
+        if (in.read() == -1) {
+          long skipped = toSkip - n;
+          throw new EOFException("reached end of stream after skipping "
+              + skipped + " bytes; " + toSkip + " bytes expected");
+        }
+        n--;
+      } else {
+        n -= amt;
+      }
+    }
+  }
+
+  public void testAsReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+    byte[] roundTripBytes = new byte[referenceBytes.length];
+    assertTrue(byteBuffer.remaining() == referenceBytes.length);
+    assertTrue(byteBuffer.isReadOnly());
+    byteBuffer.get(roundTripBytes);
+    assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testAsReadOnlyByteBufferList() {
+    List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+    int bytesSeen = 0;
+    byte[] roundTripBytes = new byte[referenceBytes.length];
+    for (ByteBuffer byteBuffer : byteBuffers) {
+      int thisLength = byteBuffer.remaining();
+      assertTrue(byteBuffer.isReadOnly());
+      assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+      byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+      bytesSeen += thisLength;
+    }
+    assertTrue(bytesSeen == referenceBytes.length);
+    assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testToByteArray() {
+    byte[] roundTripBytes = stringUnderTest.toByteArray();
+    assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testWriteTo() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    stringUnderTest.writeTo(bos);
+    byte[] roundTripBytes = bos.toByteArray();
+    assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException {
+    OutputStream os = new OutputStream() {
+      @Override
+      public void write(byte[] b, int off, int len) {
+        Arrays.fill(b, off, off + len, (byte) 0);
+      }
+
+      @Override
+      public void write(int b) {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    stringUnderTest.writeTo(os);
+    assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+        Arrays.equals(referenceBytes, stringUnderTest.toByteArray()));
+  }
+
+  public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException {
+    OutputStream os = new OutputStream() {
+      @Override
+      public void write(byte[] b, int off, int len) {
+        Arrays.fill(b, off, off + len, (byte) 0);
+      }
+
+      @Override
+      public void write(int b) {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    stringUnderTest.writeToInternal(os, 0, stringUnderTest.size());
+    byte[] allZeros = new byte[stringUnderTest.size()];
+    assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array",
+        Arrays.equals(allZeros, stringUnderTest.toByteArray()));
+  }
+
+  public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException {
+    ByteOutput out = new ByteOutput() {
+      @Override
+      public void write(byte value) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void write(byte[] value, int offset, int length) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void writeLazy(byte[] value, int offset, int length) throws IOException {
+        Arrays.fill(value, offset, offset + length, (byte) 0);
+      }
+
+      @Override
+      public void write(ByteBuffer value) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void writeLazy(ByteBuffer value) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    stringUnderTest.writeTo(out);
+    byte[] allZeros = new byte[stringUnderTest.size()];
+    assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array",
+        Arrays.equals(allZeros, stringUnderTest.toByteArray()));
+  }
+
+  public void testNewOutput() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    ByteString.Output output = ByteString.newOutput();
+    stringUnderTest.writeTo(output);
+    assertEquals("Output Size returns correct result",
+        output.size(), stringUnderTest.size());
+    output.writeTo(bos);
+    assertTrue("Output.writeTo() must give back the same bytes",
+        Arrays.equals(referenceBytes, bos.toByteArray()));
+
+    // write the output stream to itself! This should cause it to double
+    output.writeTo(output);
+    assertEquals("Writing an output stream to itself is successful",
+        stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+    output.reset();
+    assertEquals("Output.reset() resets the output", 0, output.size());
+    assertEquals("Output.reset() resets the output",
+        ByteString.EMPTY, output.toByteString());
+  }
+
+  public void testToString() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+  }
+
+  public void testCharsetToString() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+    String roundTripString = unicode.toString(Internal.UTF_8);
+    assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+  }
+
+  public void testToString_returnsCanonicalEmptyString() {
+    assertSame(classUnderTest + " must be the same string references",
+        ByteString.EMPTY.toString(Internal.UTF_8),
+        ByteString.wrap(new byte[]{}).toString(Internal.UTF_8));
+  }
+
+  public void testToString_raisesException() {
+    try {
+      ByteString.EMPTY.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+
+    try {
+      ByteString.wrap(referenceBytes).toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+  }
+
+  public void testEquals() {
+    assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
+    assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
+    assertFalse(classUnderTest + " must not equal the empty string",
+        stringUnderTest.equals(ByteString.EMPTY));
+    assertEquals(classUnderTest + " empty strings must be equal",
+        ByteString.wrap(new byte[]{}), stringUnderTest.substring(55, 55));
+    assertEquals(classUnderTest + " must equal another string with the same value",
+        stringUnderTest, ByteString.wrap(referenceBytes));
+
+    byte[] mungedBytes = new byte[referenceBytes.length];
+    System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
+    mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
+    assertFalse(classUnderTest + " must not equal every string with the same length",
+        stringUnderTest.equals(ByteString.wrap(mungedBytes)));
+  }
+
+  public void testHashCode() {
+    int hash = stringUnderTest.hashCode();
+    assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+  }
+
+  public void testPeekCachedHashCode() {
+    assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
+        stringUnderTest.peekCachedHashCode());
+    stringUnderTest.hashCode();
+    assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
+        expectedHashCode, stringUnderTest.peekCachedHashCode());
+  }
+
+  public void testPartialHash() {
+    // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+    // This test would fail if the expected hash were 1.  It's not.
+    int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
+    assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
+        expectedHashCode, hash);
+  }
+
+  public void testNewInput() throws IOException {
+    InputStream input = stringUnderTest.newInput();
+    assertEquals("InputStream.available() returns correct value",
+        stringUnderTest.size(), input.available());
+    boolean stillEqual = true;
+    for (byte referenceByte : referenceBytes) {
+      int expectedInt = (referenceByte & 0xFF);
+      stillEqual = (expectedInt == input.read());
+    }
+    assertEquals("InputStream.available() returns correct value",
+        0, input.available());
+    assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+    assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+  }
+
+  public void testNewInput_skip() throws IOException {
+    InputStream input = stringUnderTest.newInput();
+    int stringSize = stringUnderTest.size();
+    int nearEndIndex = stringSize * 2 / 3;
+    long skipped1 = input.skip(nearEndIndex);
+    assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+    assertEquals("InputStream.available()",
+        stringSize - skipped1, input.available());
+    assertTrue("InputStream.mark() is available", input.markSupported());
+    input.mark(0);
+    assertEquals("InputStream.skip(), read()",
+        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+    assertEquals("InputStream.available()",
+                 stringSize - skipped1 - 1, input.available());
+    long skipped2 = input.skip(stringSize);
+    assertEquals("InputStream.skip() incomplete",
+        skipped2, stringSize - skipped1 - 1);
+    assertEquals("InputStream.skip(), no more input", 0, input.available());
+    assertEquals("InputStream.skip(), no more input", -1, input.read());
+    input.reset();
+    assertEquals("InputStream.reset() succeded",
+                 stringSize - skipped1, input.available());
+    assertEquals("InputStream.reset(), read()",
+        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+  }
+
+  public void testNewCodedInput() throws IOException {
+    CodedInputStream cis = stringUnderTest.newCodedInput();
+    byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+    assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+        Arrays.equals(referenceBytes, roundTripBytes));
+    assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+  }
+
+  /**
+   * Make sure we keep things simple when concatenating with empty. See also
+   * {@link ByteStringTest#testConcat_empty()}.
+   */
+  public void testConcat_empty() {
+    assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+        stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+    assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+        ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+  }
+
+  public void testJavaSerialization() throws Exception {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream oos = new ObjectOutputStream(out);
+    oos.writeObject(stringUnderTest);
+    oos.close();
+    byte[] pickled = out.toByteArray();
+    InputStream in = new ByteArrayInputStream(pickled);
+    ObjectInputStream ois = new ObjectInputStream(in);
+    Object o = ois.readObject();
+    assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+    assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
new file mode 100644
index 0000000..0a8f9ed
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
@@ -0,0 +1,459 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link LongArrayList}.
+ * 
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class LongArrayListTest extends TestCase {
+  
+  private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1);
+  private static final LongArrayList TERTIARY_LIST =
+      newImmutableLongArrayList(1, 2, 3);
+  
+  private LongArrayList list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new LongArrayList();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(LongArrayList.emptyList(), LongArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(LongArrayList.emptyList());
+  }
+  
+  public void testMakeImmutable() {
+    list.addLong(2);
+    list.addLong(4);
+    list.addLong(6);
+    list.addLong(8);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+  
+  public void testModificationWithIteration() {
+    list.addAll(asList(1L, 2L, 3L, 4L));
+    Iterator<Long> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(1, (long) list.get(0));
+    assertEquals(1, (long) iterator.next());
+    list.set(0, 1L);
+    assertEquals(2, (long) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, 0L);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testGet() {
+    assertEquals(1, (long) TERTIARY_LIST.get(0));
+    assertEquals(2, (long) TERTIARY_LIST.get(1));
+    assertEquals(3, (long) TERTIARY_LIST.get(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testGetLong() {
+    assertEquals(1, TERTIARY_LIST.getLong(0));
+    assertEquals(2, TERTIARY_LIST.getLong(1));
+    assertEquals(3, TERTIARY_LIST.getLong(2));
+    
+    try {
+      TERTIARY_LIST.get(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      TERTIARY_LIST.get(3);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSize() {
+    assertEquals(0, LongArrayList.emptyList().size());
+    assertEquals(1, UNARY_LIST.size());
+    assertEquals(3, TERTIARY_LIST.size());
+
+    list.addLong(2);
+    list.addLong(4);
+    list.addLong(6);
+    list.addLong(8);
+    assertEquals(4, list.size());
+    
+    list.remove(0);
+    assertEquals(3, list.size());
+    
+    list.add(16L);
+    assertEquals(4, list.size());
+  }
+  
+  public void testSet() {
+    list.addLong(2);
+    list.addLong(4);
+    
+    assertEquals(2, (long) list.set(0, 0L));
+    assertEquals(0, list.getLong(0));
+
+    assertEquals(4, (long) list.set(1, 0L));
+    assertEquals(0, list.getLong(1));
+    
+    try {
+      list.set(-1, 0L);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.set(2, 0L);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testSetLong() {
+    list.addLong(2);
+    list.addLong(4);
+    
+    assertEquals(2, list.setLong(0, 0));
+    assertEquals(0, list.getLong(0));
+
+    assertEquals(4, list.setLong(1, 0));
+    assertEquals(0, list.getLong(1));
+    
+    try {
+      list.setLong(-1, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+
+    try {
+      list.setLong(2, 0);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAdd() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.add(2L));
+    assertEquals(asList(2L), list);
+
+    assertTrue(list.add(3L));
+    list.add(0, 4L);
+    assertEquals(asList(4L, 2L, 3L), list);
+    
+    list.add(0, 1L);
+    list.add(0, 0L);
+    // Force a resize by getting up to 11 elements.
+    for (int i = 0; i < 6; i++) {
+      list.add(Long.valueOf(5 + i));
+    }
+    assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list);
+    
+    try {
+      list.add(-1, 5L);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.add(4, 5L);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  public void testAddLong() {
+    assertEquals(0, list.size());
+
+    list.addLong(2);
+    assertEquals(asList(2L), list);
+
+    list.addLong(3);
+    assertEquals(asList(2L, 3L), list);
+  }
+  
+  public void testAddAll() {
+    assertEquals(0, list.size());
+
+    assertTrue(list.addAll(Collections.singleton(1L)));
+    assertEquals(1, list.size());
+    assertEquals(1, (long) list.get(0));
+    assertEquals(1, list.getLong(0));
+    
+    assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L)));
+    assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list);
+    
+    assertTrue(list.addAll(TERTIARY_LIST));
+    assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list);
+
+    assertFalse(list.addAll(Collections.<Long>emptyList()));
+    assertFalse(list.addAll(LongArrayList.emptyList()));
+  }
+  
+  public void testRemove() {
+    list.addAll(TERTIARY_LIST);
+    assertEquals(1, (long) list.remove(0));
+    assertEquals(asList(2L, 3L), list);
+
+    assertTrue(list.remove(3L));
+    assertEquals(asList(2L), list);
+
+    assertFalse(list.remove(3L));
+    assertEquals(asList(2L), list);
+
+    assertEquals(2, (long) list.remove(0));
+    assertEquals(asList(), list);
+    
+    try {
+      list.remove(-1);
+      fail();
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(0);
+    } catch (IndexOutOfBoundsException e) {
+      // expected
+    }
+  }
+  
+  private void assertImmutable(LongArrayList list) {
+    if (list.contains(1L)) {
+      throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+    }
+    
+    try {
+      list.add(1L);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, 1L);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Long>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(1L));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new LongArrayList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(1L));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Long>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addLong(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.<Long>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(1L));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.<Long>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(1L));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, 0L);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.setLong(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static LongArrayList newImmutableLongArrayList(long... elements) {
+    LongArrayList list = new LongArrayList();
+    for (long element : elements) {
+      list.addLong(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
new file mode 100644
index 0000000..d79d002
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -0,0 +1,458 @@
+// 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.
+
+package com.google.protobuf;
+
+import map_lite_test.MapForProto2TestProto.TestMap;
+import map_lite_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapForProto2LiteTest extends TestCase {
+  private void setMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 11);
+    builder.getMutableInt32ToInt32Field().put(2, 22);
+    builder.getMutableInt32ToInt32Field().put(3, 33);
+
+    builder.getMutableInt32ToStringField().put(1, "11");
+    builder.getMutableInt32ToStringField().put(2, "22");
+    builder.getMutableInt32ToStringField().put(3, "33");
+    
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+    builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+    builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+    
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+    
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(11).build());
+    builder.getMutableInt32ToMessageField().put(
+        2, MessageValue.newBuilder().setValue(22).build());
+    builder.getMutableInt32ToMessageField().put(
+        3, MessageValue.newBuilder().setValue(33).build());
+    
+    builder.getMutableStringToInt32Field().put("1", 11);
+    builder.getMutableStringToInt32Field().put("2", 22);
+    builder.getMutableStringToInt32Field().put("3", 33);
+  }
+
+  private void copyMapValues(TestMap source, TestMap.Builder destination) {
+    destination
+        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+        .putAllInt32ToStringField(source.getInt32ToStringField())
+        .putAllInt32ToBytesField(source.getInt32ToBytesField())
+        .putAllInt32ToEnumField(source.getInt32ToEnumField())
+        .putAllInt32ToMessageField(source.getInt32ToMessageField())
+        .putAllStringToInt32Field(source.getStringToInt32Field());
+  }
+
+  private void assertMapValuesSet(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("11", message.getInt32ToStringField().get(1));
+    assertEquals("22", message.getInt32ToStringField().get(2));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+    
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+  }
+
+  private void updateMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 111);
+    builder.getMutableInt32ToInt32Field().remove(2);
+    builder.getMutableInt32ToInt32Field().put(4, 44);
+
+    builder.getMutableInt32ToStringField().put(1, "111");
+    builder.getMutableInt32ToStringField().remove(2);
+    builder.getMutableInt32ToStringField().put(4, "44");
+    
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+    builder.getMutableInt32ToBytesField().remove(2);
+    builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+    
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().remove(2);
+    builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+    
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(111).build());
+    builder.getMutableInt32ToMessageField().remove(2);
+    builder.getMutableInt32ToMessageField().put(
+        4, MessageValue.newBuilder().setValue(44).build());
+    
+    builder.getMutableStringToInt32Field().put("1", 111);
+    builder.getMutableStringToInt32Field().remove("2");
+    builder.getMutableStringToInt32Field().put("4", 44);
+  }
+
+  private void assertMapValuesUpdated(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("111", message.getInt32ToStringField().get(1));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals("44", message.getInt32ToStringField().get(4));
+    
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+  }
+
+  private void assertMapValuesCleared(TestMap message) {
+    assertEquals(0, message.getInt32ToInt32Field().size());
+    assertEquals(0, message.getInt32ToStringField().size());
+    assertEquals(0, message.getInt32ToBytesField().size());
+    assertEquals(0, message.getInt32ToEnumField().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32Field().size());
+  }
+
+  public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+    // Since builders are implemented as a thin wrapper around a message
+    // instance, we attempt to verify that we can't cause the builder to modify
+    // a produced message.
+    
+    TestMap.Builder builder = TestMap.newBuilder();
+    TestMap message = builder.build();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertTrue(message.getInt32ToInt32Field().isEmpty());
+    message = builder.build();
+    try {
+      intMap.put(2, 3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    builder.getMutableInt32ToInt32Field().put(2, 3);
+    assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+  }
+  
+  public void testMutableMapLifecycle() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.put(2, 3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    builder.getMutableInt32ToInt32Field().put(2, 3);
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+    Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+    enumMap.put(1, TestMap.EnumValue.BAR);
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+    try {
+      enumMap.put(2, TestMap.EnumValue.FOO);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+    assertEquals(
+        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+        builder.getInt32ToEnumField());
+    
+    Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+    stringMap.put(1, "1");
+    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+    try {
+      stringMap.put(2, "2");
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+    builder.getMutableInt32ToStringField().put(2, "2");
+    assertEquals(
+        newMap(1, "1", 2, "2"),
+        builder.getInt32ToStringField());
+    
+    Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+    messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.build().getInt32ToMessageField());
+    try {
+      messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+    builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(
+        newMap(1, TestMap.MessageValue.getDefaultInstance(),
+            2, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+  }
+
+  public void testMutableMapLifecycle_collections() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.remove(2);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.keySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), intMap);
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+  }
+
+  public void testGettersAndSetters() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    TestMap message = builder.build();
+    assertMapValuesCleared(message);
+    
+    builder = message.toBuilder();
+    setMapValues(builder);
+    message = builder.build();
+    assertMapValuesSet(message);
+    
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertMapValuesUpdated(message);
+    
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertMapValuesCleared(message);
+  }
+
+  public void testPutAll() throws Exception {
+    TestMap.Builder sourceBuilder = TestMap.newBuilder();
+    setMapValues(sourceBuilder);
+    TestMap source = sourceBuilder.build();
+
+    TestMap.Builder destination = TestMap.newBuilder();
+    copyMapValues(source, destination);
+    assertMapValuesSet(destination.build());
+  }
+
+  public void testSerializeAndParse() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesSet(message);
+    
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesUpdated(message);
+    
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesCleared(message);
+  }
+  
+  public void testMergeFrom() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    
+    TestMap.Builder other = TestMap.newBuilder();
+    other.mergeFrom(message);
+    assertMapValuesSet(other.build());
+  }
+
+  public void testEqualsAndHashCode() throws Exception {
+    // Test that generated equals() and hashCode() will disregard the order
+    // of map entries when comparing/hashing map fields.
+    
+    // We can't control the order of elements in a HashMap. The best we can do
+    // here is to add elements in different order.
+    TestMap.Builder b1 = TestMap.newBuilder();
+    b1.getMutableInt32ToInt32Field().put(1, 2);
+    b1.getMutableInt32ToInt32Field().put(3, 4);
+    b1.getMutableInt32ToInt32Field().put(5, 6);
+    TestMap m1 = b1.build();
+    
+    TestMap.Builder b2 = TestMap.newBuilder();
+    b2.getMutableInt32ToInt32Field().put(5, 6);
+    b2.getMutableInt32ToInt32Field().put(1, 2);
+    b2.getMutableInt32ToInt32Field().put(3, 4);
+    TestMap m2 = b2.build();
+    
+    assertEquals(m1, m2);
+    assertEquals(m1.hashCode(), m2.hashCode());
+    
+    // Make sure we did compare map fields.
+    b2.getMutableInt32ToInt32Field().put(1, 0);
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+    // to be different.
+  }
+
+  public void testUnknownEnumValues() throws Exception {
+    TestUnknownEnumValue.Builder builder =
+        TestUnknownEnumValue.newBuilder();
+    builder.getMutableInt32ToInt32Field().put(1, 1);
+    builder.getMutableInt32ToInt32Field().put(2, 54321);
+    ByteString data = builder.build().toByteString();
+
+    TestMap message = TestMap.parseFrom(data);
+    // Entries with unknown enum values will be stored into UnknownFieldSet so
+    // there is only one entry in the map.
+    assertEquals(1, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    // Serializing and parsing should preserve the unknown entry.
+    data = message.toByteString();
+    TestUnknownEnumValue messageWithUnknownEnums =
+        TestUnknownEnumValue.parseFrom(data);
+    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+  }
+
+
+  public void testIterationOrder() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    assertEquals(Arrays.asList("1", "2", "3"),
+        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    return map;
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
new file mode 100644
index 0000000..73154c0
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -0,0 +1,683 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapForProto2TestProto.TestMap;
+import map_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
+import map_test.MapForProto2TestProto.TestRecursiveMap;
+import map_test.MapForProto2TestProto.TestUnknownEnumValue;
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields in proto2 protos.
+ */
+public class MapForProto2Test extends TestCase {
+  private void setMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 11);
+    builder.getMutableInt32ToInt32Field().put(2, 22);
+    builder.getMutableInt32ToInt32Field().put(3, 33);
+
+    builder.getMutableInt32ToStringField().put(1, "11");
+    builder.getMutableInt32ToStringField().put(2, "22");
+    builder.getMutableInt32ToStringField().put(3, "33");
+    
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+    builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+    builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+    
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+    
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(11).build());
+    builder.getMutableInt32ToMessageField().put(
+        2, MessageValue.newBuilder().setValue(22).build());
+    builder.getMutableInt32ToMessageField().put(
+        3, MessageValue.newBuilder().setValue(33).build());
+    
+    builder.getMutableStringToInt32Field().put("1", 11);
+    builder.getMutableStringToInt32Field().put("2", 22);
+    builder.getMutableStringToInt32Field().put("3", 33);
+  }
+
+  private void copyMapValues(TestMap source, TestMap.Builder destination) {
+    destination
+        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+        .putAllInt32ToStringField(source.getInt32ToStringField())
+        .putAllInt32ToBytesField(source.getInt32ToBytesField())
+        .putAllInt32ToEnumField(source.getInt32ToEnumField())
+        .putAllInt32ToMessageField(source.getInt32ToMessageField())
+        .putAllStringToInt32Field(source.getStringToInt32Field());
+  }
+
+  private void assertMapValuesSet(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("11", message.getInt32ToStringField().get(1));
+    assertEquals("22", message.getInt32ToStringField().get(2));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+    
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+  }
+
+  private void updateMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 111);
+    builder.getMutableInt32ToInt32Field().remove(2);
+    builder.getMutableInt32ToInt32Field().put(4, 44);
+
+    builder.getMutableInt32ToStringField().put(1, "111");
+    builder.getMutableInt32ToStringField().remove(2);
+    builder.getMutableInt32ToStringField().put(4, "44");
+    
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+    builder.getMutableInt32ToBytesField().remove(2);
+    builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+    
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().remove(2);
+    builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+    
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(111).build());
+    builder.getMutableInt32ToMessageField().remove(2);
+    builder.getMutableInt32ToMessageField().put(
+        4, MessageValue.newBuilder().setValue(44).build());
+    
+    builder.getMutableStringToInt32Field().put("1", 111);
+    builder.getMutableStringToInt32Field().remove("2");
+    builder.getMutableStringToInt32Field().put("4", 44);
+  }
+
+  private void assertMapValuesUpdated(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("111", message.getInt32ToStringField().get(1));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals("44", message.getInt32ToStringField().get(4));
+    
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+  }
+
+  private void assertMapValuesCleared(TestMap message) {
+    assertEquals(0, message.getInt32ToInt32Field().size());
+    assertEquals(0, message.getInt32ToStringField().size());
+    assertEquals(0, message.getInt32ToBytesField().size());
+    assertEquals(0, message.getInt32ToEnumField().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32Field().size());
+  }
+  
+  public void testMutableMapLifecycle() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.put(2, 3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    builder.getMutableInt32ToInt32Field().put(2, 3);
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+    Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+    enumMap.put(1, TestMap.EnumValue.BAR);
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+    try {
+      enumMap.put(2, TestMap.EnumValue.FOO);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+    assertEquals(
+        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+        builder.getInt32ToEnumField());
+    
+    Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+    stringMap.put(1, "1");
+    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+    try {
+      stringMap.put(2, "2");
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+    builder.getMutableInt32ToStringField().put(2, "2");
+    assertEquals(
+        newMap(1, "1", 2, "2"),
+        builder.getInt32ToStringField());
+    
+    Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+    messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.build().getInt32ToMessageField());
+    try {
+      messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+    builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(
+        newMap(1, TestMap.MessageValue.getDefaultInstance(),
+            2, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+  }
+
+  public void testMutableMapLifecycle_collections() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.remove(2);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.keySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), intMap);
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+  }
+
+  public void testGettersAndSetters() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    TestMap message = builder.build();
+    assertMapValuesCleared(message);
+    
+    builder = message.toBuilder();
+    setMapValues(builder);
+    message = builder.build();
+    assertMapValuesSet(message);
+    
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertMapValuesUpdated(message);
+    
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertMapValuesCleared(message);
+  }
+
+  public void testPutAll() throws Exception {
+    TestMap.Builder sourceBuilder = TestMap.newBuilder();
+    setMapValues(sourceBuilder);
+    TestMap source = sourceBuilder.build();
+
+    TestMap.Builder destination = TestMap.newBuilder();
+    copyMapValues(source, destination);
+    assertMapValuesSet(destination.build());
+  }
+
+  public void testSerializeAndParse() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesSet(message);
+    
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesUpdated(message);
+    
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesCleared(message);
+  }
+  
+  public void testMergeFrom() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    
+    TestMap.Builder other = TestMap.newBuilder();
+    other.mergeFrom(message);
+    assertMapValuesSet(other.build());
+  }
+
+  public void testEqualsAndHashCode() throws Exception {
+    // Test that generated equals() and hashCode() will disregard the order
+    // of map entries when comparing/hashing map fields.
+    
+    // We can't control the order of elements in a HashMap. The best we can do
+    // here is to add elements in different order.
+    TestMap.Builder b1 = TestMap.newBuilder();
+    b1.getMutableInt32ToInt32Field().put(1, 2);
+    b1.getMutableInt32ToInt32Field().put(3, 4);
+    b1.getMutableInt32ToInt32Field().put(5, 6);
+    TestMap m1 = b1.build();
+    
+    TestMap.Builder b2 = TestMap.newBuilder();
+    b2.getMutableInt32ToInt32Field().put(5, 6);
+    b2.getMutableInt32ToInt32Field().put(1, 2);
+    b2.getMutableInt32ToInt32Field().put(3, 4);
+    TestMap m2 = b2.build();
+    
+    assertEquals(m1, m2);
+    assertEquals(m1.hashCode(), m2.hashCode());
+    
+    // Make sure we did compare map fields.
+    b2.getMutableInt32ToInt32Field().put(1, 0);
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+    // to be different.
+  }
+  
+  
+  // The following methods are used to test reflection API.
+  
+  private static FieldDescriptor f(String name) {
+    return TestMap.getDescriptor().findFieldByName(name);
+  }
+  
+  private static Object getFieldValue(Message mapEntry, String name) {
+    FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+    return mapEntry.getField(field);
+  }
+  
+  private static Message.Builder setFieldValue(
+      Message.Builder mapEntry, String name, Object value) {
+    FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+    mapEntry.setField(field, value);
+    return mapEntry;
+  }
+  
+  private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+    FieldDescriptor field = f(name);
+    for (Object entry : (List<?>) message.getField(field)) {
+      Message mapEntry = (Message) entry;
+      Object key = getFieldValue(mapEntry, "key");
+      Object value = getFieldValue(mapEntry, "value");
+      assertTrue(values.containsKey(key));
+      assertEquals(value, values.get(key));
+    }
+    assertEquals(values.size(), message.getRepeatedFieldCount(field));
+    for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+      Message mapEntry = (Message) message.getRepeatedField(field, i);
+      Object key = getFieldValue(mapEntry, "key");
+      Object value = getFieldValue(mapEntry, "value");
+      assertTrue(values.containsKey(key));
+      assertEquals(value, values.get(key));
+    }
+  }
+  
+  private static <KeyType, ValueType>
+  Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+    FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+    Message.Builder entryBuilder = builder.newBuilderForField(field);
+    FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+    FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+    entryBuilder.setField(keyField, key);
+    entryBuilder.setField(valueField, value);
+    return entryBuilder.build();
+  }
+  
+  private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+    List<Message> entryList = new ArrayList<Message>();
+    for (Map.Entry<?, ?> entry : values.entrySet()) {
+      entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+    }
+    FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+    builder.setField(field, entryList);
+  }
+  
+  private static <KeyType, ValueType>
+  Map<KeyType, ValueType> mapForValues(
+      KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+    Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
+
+  public void testReflectionApi() throws Exception {
+    // In reflection API, map fields are just repeated message fields.
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableInt32ToInt32Field().put(1, 2);
+    builder.getMutableInt32ToInt32Field().put(3, 4);
+    builder.getMutableInt32ToMessageField().put(
+        11, MessageValue.newBuilder().setValue(22).build());
+    builder.getMutableInt32ToMessageField().put(
+        33, MessageValue.newBuilder().setValue(44).build());
+    TestMap message = builder.build();
+
+    // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+    assertHasMapValues(message, "int32_to_int32_field",
+        mapForValues(1, 2, 3, 4));
+    assertHasMapValues(message, "int32_to_message_field",
+        mapForValues(
+            11, MessageValue.newBuilder().setValue(22).build(),
+            33, MessageValue.newBuilder().setValue(44).build()));
+    
+    // Test clearField()
+    builder.clearField(f("int32_to_int32_field"));
+    builder.clearField(f("int32_to_message_field"));
+    message = builder.build();
+    assertEquals(0, message.getInt32ToInt32Field().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
+    
+    // Test setField()
+    setMapValues(builder, "int32_to_int32_field",
+        mapForValues(11, 22, 33, 44));
+    setMapValues(builder, "int32_to_message_field",
+        mapForValues(
+            111, MessageValue.newBuilder().setValue(222).build(),
+            333, MessageValue.newBuilder().setValue(444).build()));
+    message = builder.build();
+    assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+    assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+    assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+    assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+    
+    // Test addRepeatedField
+    builder.addRepeatedField(f("int32_to_int32_field"),
+        newMapEntry(builder, "int32_to_int32_field", 55, 66));
+    builder.addRepeatedField(f("int32_to_message_field"),
+        newMapEntry(builder, "int32_to_message_field", 555,
+            MessageValue.newBuilder().setValue(666).build()));
+    message = builder.build();
+    assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+    // Test addRepeatedField (overriding existing values)
+    builder.addRepeatedField(f("int32_to_int32_field"),
+        newMapEntry(builder, "int32_to_int32_field", 55, 55));
+    builder.addRepeatedField(f("int32_to_message_field"),
+        newMapEntry(builder, "int32_to_message_field", 555,
+            MessageValue.newBuilder().setValue(555).build()));
+    message = builder.build();
+    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+    
+    // Test setRepeatedField
+    for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+      Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+      int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+      int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+      // Swap key with value for each entry.
+      Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+      setFieldValue(mapEntryBuilder, "key", oldValue);
+      setFieldValue(mapEntryBuilder, "value", oldKey);
+      builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+    }
+    message = builder.build();
+    assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+  }
+  
+  public void testTextFormat() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    
+    String textData = TextFormat.printToString(message);
+    
+    builder = TestMap.newBuilder();
+    TextFormat.merge(textData, builder);
+    message = builder.build();
+    
+    assertMapValuesSet(message);
+  }
+  
+  public void testDynamicMessage() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    
+    Message dynamicDefaultInstance =
+        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    Message dynamicMessage = dynamicDefaultInstance
+        .newBuilderForType().mergeFrom(message.toByteString()).build();
+    
+    assertEquals(message, dynamicMessage);
+    assertEquals(message.hashCode(), dynamicMessage.hashCode());
+  }
+  
+  public void testReflectionEqualsAndHashCode() throws Exception {
+    // Test that generated equals() and hashCode() will disregard the order
+    // of map entries when comparing/hashing map fields.
+
+    // We use DynamicMessage to test reflection based equals()/hashCode().
+    Message dynamicDefaultInstance =
+        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    FieldDescriptor field = f("int32_to_int32_field");
+    
+    Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+    Message m1 = b1.build();
+    
+    Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+    Message m2 = b2.build();
+    
+    assertEquals(m1, m2);
+    assertEquals(m1.hashCode(), m2.hashCode());
+    
+    // Make sure we did compare map fields.
+    b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+    // to be different.
+  }
+  
+  public void testUnknownEnumValues() throws Exception {
+    TestUnknownEnumValue.Builder builder =
+        TestUnknownEnumValue.newBuilder();
+    builder.getMutableInt32ToInt32Field().put(1, 1);
+    builder.getMutableInt32ToInt32Field().put(2, 54321);
+    ByteString data = builder.build().toByteString();
+
+    TestMap message = TestMap.parseFrom(data);
+    // Entries with unknown enum values will be stored into UnknownFieldSet so
+    // there is only one entry in the map.
+    assertEquals(1, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    // UnknownFieldSet should not be empty.
+    assertFalse(message.getUnknownFields().asMap().isEmpty());
+    // Serializing and parsing should preserve the unknown entry.
+    data = message.toByteString();
+    TestUnknownEnumValue messageWithUnknownEnums =
+        TestUnknownEnumValue.parseFrom(data);
+    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+  }
+
+
+  public void testRequiredMessage() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableRequiredMessageMap().put(0,
+        MessageWithRequiredFields.newBuilder().buildPartial());
+    TestMap message = builder.buildPartial();
+    assertFalse(message.isInitialized());
+
+    builder.getMutableRequiredMessageMap().put(0,
+        MessageWithRequiredFields.newBuilder().setValue(1).build());
+    message = builder.build();
+    assertTrue(message.isInitialized());
+  }
+
+  public void testRecursiveMap() throws Exception {
+    TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
+    builder.getMutableRecursiveMapField().put(
+        1, TestRecursiveMap.newBuilder().setValue(2).build());
+    builder.getMutableRecursiveMapField().put(
+        3, TestRecursiveMap.newBuilder().setValue(4).build());
+    ByteString data = builder.build().toByteString();
+
+    TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
+    assertEquals(2, message.getRecursiveMapField().get(1).getValue());
+    assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+  }
+
+  public void testIterationOrder() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    assertEquals(Arrays.asList("1", "2", "3"),
+        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+  }
+
+  // Regression test for b/20494788
+  public void testMapInitializationOrder() throws Exception {
+    assertEquals("RedactAllTypes", map_test.RedactAllTypes
+        .getDefaultInstance().getDescriptorForType().getName());
+
+    map_test.Message1.Builder builder =
+        map_test.Message1.newBuilder();
+    builder.getMutableMapField().put("key", true);
+    map_test.Message1 message = builder.build();
+    Message mapEntry = (Message) message.getRepeatedField(
+        message.getDescriptorForType().findFieldByName("map_field"), 0);
+    assertEquals(2, mapEntry.getAllFields().size());
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    return map;
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
+}
+
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapTest.java
new file mode 100644
index 0000000..1dc5787
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -0,0 +1,782 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapTestProto.TestMap;
+import map_test.MapTestProto.TestMap.MessageValue;
+import map_test.MapTestProto.TestOnChangeEventPropagation;
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapTest extends TestCase {
+  private void setMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 11);
+    builder.getMutableInt32ToInt32Field().put(2, 22);
+    builder.getMutableInt32ToInt32Field().put(3, 33);
+
+    builder.getMutableInt32ToStringField().put(1, "11");
+    builder.getMutableInt32ToStringField().put(2, "22");
+    builder.getMutableInt32ToStringField().put(3, "33");
+
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+    builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+    builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(11).build());
+    builder.getMutableInt32ToMessageField().put(
+        2, MessageValue.newBuilder().setValue(22).build());
+    builder.getMutableInt32ToMessageField().put(
+        3, MessageValue.newBuilder().setValue(33).build());
+
+    builder.getMutableStringToInt32Field().put("1", 11);
+    builder.getMutableStringToInt32Field().put("2", 22);
+    builder.getMutableStringToInt32Field().put("3", 33);
+  }
+
+  private void copyMapValues(TestMap source, TestMap.Builder destination) {
+    destination
+        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+        .putAllInt32ToStringField(source.getInt32ToStringField())
+        .putAllInt32ToBytesField(source.getInt32ToBytesField())
+        .putAllInt32ToEnumField(source.getInt32ToEnumField())
+        .putAllInt32ToMessageField(source.getInt32ToMessageField())
+        .putAllStringToInt32Field(source.getStringToInt32Field());
+  }
+
+  private void assertMapValuesSet(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("11", message.getInt32ToStringField().get(1));
+    assertEquals("22", message.getInt32ToStringField().get(2));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+  }
+
+  private void updateMapValues(TestMap.Builder builder) {
+    builder.getMutableInt32ToInt32Field().put(1, 111);
+    builder.getMutableInt32ToInt32Field().remove(2);
+    builder.getMutableInt32ToInt32Field().put(4, 44);
+
+    builder.getMutableInt32ToStringField().put(1, "111");
+    builder.getMutableInt32ToStringField().remove(2);
+    builder.getMutableInt32ToStringField().put(4, "44");
+
+    builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+    builder.getMutableInt32ToBytesField().remove(2);
+    builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+    builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+    builder.getMutableInt32ToEnumField().remove(2);
+    builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+    builder.getMutableInt32ToMessageField().put(
+        1, MessageValue.newBuilder().setValue(111).build());
+    builder.getMutableInt32ToMessageField().remove(2);
+    builder.getMutableInt32ToMessageField().put(
+        4, MessageValue.newBuilder().setValue(44).build());
+
+    builder.getMutableStringToInt32Field().put("1", 111);
+    builder.getMutableStringToInt32Field().remove("2");
+    builder.getMutableStringToInt32Field().put("4", 44);
+  }
+
+  private void assertMapValuesUpdated(TestMap message) {
+    assertEquals(3, message.getInt32ToInt32Field().size());
+    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+    assertEquals(3, message.getInt32ToStringField().size());
+    assertEquals("111", message.getInt32ToStringField().get(1));
+    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals("44", message.getInt32ToStringField().get(4));
+
+    assertEquals(3, message.getInt32ToBytesField().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+    assertEquals(3, message.getInt32ToEnumField().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+    assertEquals(3, message.getInt32ToMessageField().size());
+    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+    assertEquals(3, message.getStringToInt32Field().size());
+    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+  }
+
+  private void assertMapValuesCleared(TestMap message) {
+    assertEquals(0, message.getInt32ToInt32Field().size());
+    assertEquals(0, message.getInt32ToStringField().size());
+    assertEquals(0, message.getInt32ToBytesField().size());
+    assertEquals(0, message.getInt32ToEnumField().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32Field().size());
+  }
+  
+  public void testMutableMapLifecycle() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.put(2, 3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    builder.getMutableInt32ToInt32Field().put(2, 3);
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+    Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+    enumMap.put(1, TestMap.EnumValue.BAR);
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+    try {
+      enumMap.put(2, TestMap.EnumValue.FOO);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+    builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+    assertEquals(
+        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+        builder.getInt32ToEnumField());
+    
+    Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+    stringMap.put(1, "1");
+    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+    try {
+      stringMap.put(2, "2");
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+    builder.getMutableInt32ToStringField().put(2, "2");
+    assertEquals(
+        newMap(1, "1", 2, "2"),
+        builder.getInt32ToStringField());
+    
+    Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+    messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.build().getInt32ToMessageField());
+    try {
+      messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+    builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+    assertEquals(
+        newMap(1, TestMap.MessageValue.getDefaultInstance(),
+            2, TestMap.MessageValue.getDefaultInstance()),
+        builder.getInt32ToMessageField());
+  }
+
+  public void testMutableMapLifecycle_collections() {
+    TestMap.Builder builder = TestMap.newBuilder();
+    Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+    intMap.put(1, 2);
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+    try {
+      intMap.remove(2);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.entrySet().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.keySet().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    try {
+      intMap.values().iterator().remove();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(newMap(1, 2), intMap);
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+  }
+  
+  public void testGettersAndSetters() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    TestMap message = builder.build();
+    assertMapValuesCleared(message);
+
+    builder = message.toBuilder();
+    setMapValues(builder);
+    message = builder.build();
+    assertMapValuesSet(message);
+
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertMapValuesUpdated(message);
+
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertMapValuesCleared(message);
+  }
+
+  public void testPutAll() throws Exception {
+    TestMap.Builder sourceBuilder = TestMap.newBuilder();
+    setMapValues(sourceBuilder);
+    TestMap source = sourceBuilder.build();
+
+    TestMap.Builder destination = TestMap.newBuilder();
+    copyMapValues(source, destination);
+    assertMapValuesSet(destination.build());
+  }
+
+  public void testPutAllForUnknownEnumValues() throws Exception {
+    TestMap.Builder sourceBuilder = TestMap.newBuilder();
+    sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0);
+    sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1);
+    sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000);  // unknown value.
+    TestMap source = sourceBuilder.build();
+
+    TestMap.Builder destinationBuilder = TestMap.newBuilder();
+    destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+    TestMap destination = destinationBuilder.build();
+
+    assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
+    assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
+    assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+  }
+
+  public void testSerializeAndParse() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesSet(message);
+
+    builder = message.toBuilder();
+    updateMapValues(builder);
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesUpdated(message);
+
+    builder = message.toBuilder();
+    builder.clear();
+    message = builder.build();
+    assertEquals(message.getSerializedSize(), message.toByteString().size());
+    message = TestMap.parser().parseFrom(message.toByteString());
+    assertMapValuesCleared(message);
+  }
+
+  public void testMergeFrom() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    TestMap.Builder other = TestMap.newBuilder();
+    other.mergeFrom(message);
+    assertMapValuesSet(other.build());
+  }
+
+  public void testEqualsAndHashCode() throws Exception {
+    // Test that generated equals() and hashCode() will disregard the order
+    // of map entries when comparing/hashing map fields.
+
+    // We can't control the order of elements in a HashMap. The best we can do
+    // here is to add elements in different order.
+    TestMap.Builder b1 = TestMap.newBuilder();
+    b1.getMutableInt32ToInt32Field().put(1, 2);
+    b1.getMutableInt32ToInt32Field().put(3, 4);
+    b1.getMutableInt32ToInt32Field().put(5, 6);
+    TestMap m1 = b1.build();
+
+    TestMap.Builder b2 = TestMap.newBuilder();
+    b2.getMutableInt32ToInt32Field().put(5, 6);
+    b2.getMutableInt32ToInt32Field().put(1, 2);
+    b2.getMutableInt32ToInt32Field().put(3, 4);
+    TestMap m2 = b2.build();
+
+    assertEquals(m1, m2);
+    assertEquals(m1.hashCode(), m2.hashCode());
+
+    // Make sure we did compare map fields.
+    b2.getMutableInt32ToInt32Field().put(1, 0);
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+    // to be different.
+
+    // Regression test for b/18549190: if a map is a subset of the other map,
+    // equals() should return false.
+    b2.getMutableInt32ToInt32Field().remove(1);
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    assertFalse(m2.equals(m1));
+  }
+
+  public void testNestedBuilderOnChangeEventPropagation() {
+    TestOnChangeEventPropagation.Builder parent =
+        TestOnChangeEventPropagation.newBuilder();
+    parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
+    TestOnChangeEventPropagation message = parent.build();
+    assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Make a change using nested builder.
+    parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
+
+    // Should be able to observe the change.
+    message = parent.build();
+    assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Make another change using mergeFrom()
+    TestMap.Builder other = TestMap.newBuilder();
+    other.getMutableInt32ToInt32Field().put(1, 4);
+    parent.getOptionalMessageBuilder().mergeFrom(other.build());
+
+    // Should be able to observe the change.
+    message = parent.build();
+    assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Make yet another change by clearing the nested builder.
+    parent.getOptionalMessageBuilder().clear();
+
+    // Should be able to observe the change.
+    message = parent.build();
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+  }
+
+  public void testNestedBuilderOnChangeEventPropagationReflection() {
+    FieldDescriptor intMapField = f("int32_to_int32_field");
+    // Create an outer message builder with nested builder.
+    TestOnChangeEventPropagation.Builder parentBuilder =
+        TestOnChangeEventPropagation.newBuilder();
+    TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+    // Create a map entry message.
+    TestMap.Builder entryBuilder = TestMap.newBuilder();
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
+
+    // Put the entry into the nested builder.
+    testMapBuilder.addRepeatedField(
+        intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    TestOnChangeEventPropagation message = parentBuilder.build();
+    assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+    // Change the entry value.
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.setRepeatedField(
+        intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(4,
+        message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Clear the nested builder.
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.clearField(intMapField);
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+  }
+
+  // The following methods are used to test reflection API.
+
+  private static FieldDescriptor f(String name) {
+    return TestMap.getDescriptor().findFieldByName(name);
+  }
+
+  private static Object getFieldValue(Message mapEntry, String name) {
+    FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+    return mapEntry.getField(field);
+  }
+
+  private static Message.Builder setFieldValue(
+      Message.Builder mapEntry, String name, Object value) {
+    FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+    mapEntry.setField(field, value);
+    return mapEntry;
+  }
+
+  private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+    FieldDescriptor field = f(name);
+    for (Object entry : (List<?>) message.getField(field)) {
+      Message mapEntry = (Message) entry;
+      Object key = getFieldValue(mapEntry, "key");
+      Object value = getFieldValue(mapEntry, "value");
+      assertTrue(values.containsKey(key));
+      assertEquals(value, values.get(key));
+    }
+    assertEquals(values.size(), message.getRepeatedFieldCount(field));
+    for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+      Message mapEntry = (Message) message.getRepeatedField(field, i);
+      Object key = getFieldValue(mapEntry, "key");
+      Object value = getFieldValue(mapEntry, "value");
+      assertTrue(values.containsKey(key));
+      assertEquals(value, values.get(key));
+    }
+  }
+
+  private static <KeyType, ValueType>
+  Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+    FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+    Message.Builder entryBuilder = builder.newBuilderForField(field);
+    FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+    FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+    entryBuilder.setField(keyField, key);
+    entryBuilder.setField(valueField, value);
+    return entryBuilder.build();
+  }
+
+  private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+    List<Message> entryList = new ArrayList<Message>();
+    for (Map.Entry<?, ?> entry : values.entrySet()) {
+      entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+    }
+    FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+    builder.setField(field, entryList);
+  }
+
+  private static <KeyType, ValueType>
+  Map<KeyType, ValueType> mapForValues(
+      KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+    Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
+
+  public void testReflectionApi() throws Exception {
+    // In reflection API, map fields are just repeated message fields.
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableInt32ToInt32Field().put(1, 2);
+    builder.getMutableInt32ToInt32Field().put(3, 4);
+    builder.getMutableInt32ToMessageField().put(
+        11, MessageValue.newBuilder().setValue(22).build());
+    builder.getMutableInt32ToMessageField().put(
+        33, MessageValue.newBuilder().setValue(44).build());
+    TestMap message = builder.build();
+
+    // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+    assertHasMapValues(message, "int32_to_int32_field",
+        mapForValues(1, 2, 3, 4));
+    assertHasMapValues(message, "int32_to_message_field",
+        mapForValues(
+            11, MessageValue.newBuilder().setValue(22).build(),
+            33, MessageValue.newBuilder().setValue(44).build()));
+
+    // Test clearField()
+    builder.clearField(f("int32_to_int32_field"));
+    builder.clearField(f("int32_to_message_field"));
+    message = builder.build();
+    assertEquals(0, message.getInt32ToInt32Field().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
+
+    // Test setField()
+    setMapValues(builder, "int32_to_int32_field",
+        mapForValues(11, 22, 33, 44));
+    setMapValues(builder, "int32_to_message_field",
+        mapForValues(
+            111, MessageValue.newBuilder().setValue(222).build(),
+            333, MessageValue.newBuilder().setValue(444).build()));
+    message = builder.build();
+    assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+    assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+    assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+    assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+    // Test addRepeatedField
+    builder.addRepeatedField(f("int32_to_int32_field"),
+        newMapEntry(builder, "int32_to_int32_field", 55, 66));
+    builder.addRepeatedField(f("int32_to_message_field"),
+        newMapEntry(builder, "int32_to_message_field", 555,
+            MessageValue.newBuilder().setValue(666).build()));
+    message = builder.build();
+    assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+    // Test addRepeatedField (overriding existing values)
+    builder.addRepeatedField(f("int32_to_int32_field"),
+        newMapEntry(builder, "int32_to_int32_field", 55, 55));
+    builder.addRepeatedField(f("int32_to_message_field"),
+        newMapEntry(builder, "int32_to_message_field", 555,
+            MessageValue.newBuilder().setValue(555).build()));
+    message = builder.build();
+    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+    // Test setRepeatedField
+    for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+      Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+      int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+      int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+      // Swap key with value for each entry.
+      Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+      setFieldValue(mapEntryBuilder, "key", oldValue);
+      setFieldValue(mapEntryBuilder, "value", oldKey);
+      builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+    }
+    message = builder.build();
+    assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+    assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+  }
+
+  public void testTextFormat() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    String textData = TextFormat.printToString(message);
+
+    builder = TestMap.newBuilder();
+    TextFormat.merge(textData, builder);
+    message = builder.build();
+
+    assertMapValuesSet(message);
+  }
+
+  public void testDynamicMessage() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    Message dynamicDefaultInstance =
+        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    Message dynamicMessage = dynamicDefaultInstance
+        .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+    assertEquals(message, dynamicMessage);
+    assertEquals(message.hashCode(), dynamicMessage.hashCode());
+  }
+
+  public void testReflectionEqualsAndHashCode() throws Exception {
+    // Test that generated equals() and hashCode() will disregard the order
+    // of map entries when comparing/hashing map fields.
+
+    // We use DynamicMessage to test reflection based equals()/hashCode().
+    Message dynamicDefaultInstance =
+        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    FieldDescriptor field = f("int32_to_int32_field");
+
+    Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+    b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+    Message m1 = b1.build();
+
+    Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+    b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+    Message m2 = b2.build();
+
+    assertEquals(m1, m2);
+    assertEquals(m1.hashCode(), m2.hashCode());
+
+    // Make sure we did compare map fields.
+    b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+    m2 = b2.build();
+    assertFalse(m1.equals(m2));
+    // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+    // to be different.
+  }
+
+  public void testUnknownEnumValues() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableInt32ToEnumFieldValue().put(0, 0);
+    builder.getMutableInt32ToEnumFieldValue().put(1, 1);
+    builder.getMutableInt32ToEnumFieldValue().put(2, 1000);  // unknown value.
+    TestMap message = builder.build();
+
+    assertEquals(TestMap.EnumValue.FOO,
+        message.getInt32ToEnumField().get(0));
+    assertEquals(TestMap.EnumValue.BAR,
+        message.getInt32ToEnumField().get(1));
+    assertEquals(TestMap.EnumValue.UNRECOGNIZED,
+        message.getInt32ToEnumField().get(2));
+    assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+
+    // Unknown enum values should be preserved after:
+    //   1. Serialization and parsing.
+    //   2. toBuild().
+    //   3. mergeFrom().
+    message = TestMap.parseFrom(message.toByteString());
+    assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+    builder = message.toBuilder();
+    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+    builder = TestMap.newBuilder().mergeFrom(message);
+    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+
+    // hashCode()/equals() should take unknown enum values into account.
+    builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
+    TestMap message2 = builder.build();
+    assertFalse(message.hashCode() == message2.hashCode());
+    assertFalse(message.equals(message2));
+    // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
+    // should be the same.
+    assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
+  }
+
+  public void testUnknownEnumValuesInReflectionApi() throws Exception {
+    Descriptor descriptor = TestMap.getDescriptor();
+    EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
+    FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
+
+    Map<Integer, Integer> data = new HashMap<Integer, Integer>();
+    data.put(0, 0);
+    data.put(1, 1);
+    data.put(2, 1000);  // unknown value.
+
+    TestMap.Builder builder = TestMap.newBuilder();
+    for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
+      builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
+    }
+
+    // Try to read unknown enum values using reflection API.
+    for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
+      Message mapEntry = (Message) builder.getRepeatedField(field, i);
+      int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+      int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
+      assertEquals(data.get(key).intValue(), value);
+      Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+      // Increase the value by 1.
+      setFieldValue(mapEntryBuilder, "value",
+          enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
+      builder.setRepeatedField(field, i, mapEntryBuilder.build());
+    }
+
+    // Verify that enum values have been successfully updated.
+    TestMap message = builder.build();
+    for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
+      assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
+    }
+  }
+
+  public void testIterationOrder() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    setMapValues(builder);
+    TestMap message = builder.build();
+
+    assertEquals(Arrays.asList("1", "2", "3"),
+        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    return map;
+  }
+  
+  private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MessageTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MessageTest.java
new file mode 100644
index 0000000..dcd1aba
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/MessageTest.java
@@ -0,0 +1,353 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Misc. unit tests for message operations that apply to both generated
+ * and dynamic messages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class MessageTest extends TestCase {
+  // =================================================================
+  // Message-merging tests.
+
+  static final TestAllTypes MERGE_SOURCE =
+    TestAllTypes.newBuilder()
+      .setOptionalInt32(1)
+      .setOptionalString("foo")
+      .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+      .addRepeatedString("bar")
+      .build();
+
+  static final TestAllTypes MERGE_DEST =
+    TestAllTypes.newBuilder()
+      .setOptionalInt64(2)
+      .setOptionalString("baz")
+      .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+      .addRepeatedString("qux")
+      .build();
+
+  static final String MERGE_RESULT_TEXT =
+      "optional_int32: 1\n" +
+      "optional_int64: 2\n" +
+      "optional_string: \"foo\"\n" +
+      "optional_foreign_message {\n" +
+      "  c: 3\n" +
+      "}\n" +
+      "repeated_string: \"qux\"\n" +
+      "repeated_string: \"bar\"\n";
+
+  public void testMergeFrom() throws Exception {
+    TestAllTypes result =
+      TestAllTypes.newBuilder(MERGE_DEST)
+        .mergeFrom(MERGE_SOURCE).build();
+
+    assertEquals(MERGE_RESULT_TEXT, result.toString());
+  }
+
+  /**
+   * Test merging a DynamicMessage into a GeneratedMessage.  As long as they
+   * have the same descriptor, this should work, but it is an entirely different
+   * code path.
+   */
+  public void testMergeFromDynamic() throws Exception {
+    TestAllTypes result =
+      TestAllTypes.newBuilder(MERGE_DEST)
+        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+        .build();
+
+    assertEquals(MERGE_RESULT_TEXT, result.toString());
+  }
+
+  /** Test merging two DynamicMessages. */
+  public void testDynamicMergeFrom() throws Exception {
+    DynamicMessage result =
+      DynamicMessage.newBuilder(MERGE_DEST)
+        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+        .build();
+
+    assertEquals(MERGE_RESULT_TEXT, result.toString());
+  }
+
+  // =================================================================
+  // Required-field-related tests.
+
+  private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+    TestRequired.getDefaultInstance();
+  private static final TestRequired TEST_REQUIRED_INITIALIZED =
+    TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+  public void testRequired() throws Exception {
+    TestRequired.Builder builder = TestRequired.newBuilder();
+
+    assertFalse(builder.isInitialized());
+    builder.setA(1);
+    assertFalse(builder.isInitialized());
+    builder.setB(1);
+    assertFalse(builder.isInitialized());
+    builder.setC(1);
+    assertTrue(builder.isInitialized());
+  }
+
+  public void testRequiredForeign() throws Exception {
+    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+
+    assertTrue(builder.isInitialized());
+
+    builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+
+    builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+  }
+
+  public void testRequiredExtension() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+
+    assertTrue(builder.isInitialized());
+
+    builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+
+    builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+  }
+
+  public void testRequiredDynamic() throws Exception {
+    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+    DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+    assertFalse(builder.isInitialized());
+    builder.setField(descriptor.findFieldByName("a"), 1);
+    assertFalse(builder.isInitialized());
+    builder.setField(descriptor.findFieldByName("b"), 1);
+    assertFalse(builder.isInitialized());
+    builder.setField(descriptor.findFieldByName("c"), 1);
+    assertTrue(builder.isInitialized());
+  }
+
+  public void testRequiredDynamicForeign() throws Exception {
+    Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
+    DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+    assertTrue(builder.isInitialized());
+
+    builder.setField(descriptor.findFieldByName("optional_message"),
+                     TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setField(descriptor.findFieldByName("optional_message"),
+                     TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+
+    builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
+                             TEST_REQUIRED_UNINITIALIZED);
+    assertFalse(builder.isInitialized());
+
+    builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
+                             TEST_REQUIRED_INITIALIZED);
+    assertTrue(builder.isInitialized());
+  }
+
+  public void testUninitializedException() throws Exception {
+    try {
+      TestRequired.newBuilder().build();
+      fail("Should have thrown an exception.");
+    } catch (UninitializedMessageException e) {
+      assertEquals("Message missing required fields: a, b, c", e.getMessage());
+    }
+  }
+
+  public void testBuildPartial() throws Exception {
+    // We're mostly testing that no exception is thrown.
+    TestRequired message = TestRequired.newBuilder().buildPartial();
+    assertFalse(message.isInitialized());
+  }
+
+  public void testNestedUninitializedException() throws Exception {
+    try {
+      TestRequiredForeign.newBuilder()
+        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .build();
+      fail("Should have thrown an exception.");
+    } catch (UninitializedMessageException e) {
+      assertEquals(
+        "Message missing required fields: " +
+        "optional_message.a, " +
+        "optional_message.b, " +
+        "optional_message.c, " +
+        "repeated_message[0].a, " +
+        "repeated_message[0].b, " +
+        "repeated_message[0].c, " +
+        "repeated_message[1].a, " +
+        "repeated_message[1].b, " +
+        "repeated_message[1].c",
+        e.getMessage());
+    }
+  }
+
+  public void testBuildNestedPartial() throws Exception {
+    // We're mostly testing that no exception is thrown.
+    TestRequiredForeign message =
+      TestRequiredForeign.newBuilder()
+        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .buildPartial();
+    assertFalse(message.isInitialized());
+  }
+
+  public void testParseUnititialized() throws Exception {
+    try {
+      TestRequired.parseFrom(ByteString.EMPTY);
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals("Message missing required fields: a, b, c", e.getMessage());
+    }
+  }
+
+  public void testParseNestedUnititialized() throws Exception {
+    ByteString data =
+      TestRequiredForeign.newBuilder()
+        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+        .buildPartial().toByteString();
+
+    try {
+      TestRequiredForeign.parseFrom(data);
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals(
+        "Message missing required fields: " +
+        "optional_message.a, " +
+        "optional_message.b, " +
+        "optional_message.c, " +
+        "repeated_message[0].a, " +
+        "repeated_message[0].b, " +
+        "repeated_message[0].c, " +
+        "repeated_message[1].a, " +
+        "repeated_message[1].b, " +
+        "repeated_message[1].c",
+        e.getMessage());
+    }
+  }
+
+  public void testDynamicUninitializedException() throws Exception {
+    try {
+      DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
+      fail("Should have thrown an exception.");
+    } catch (UninitializedMessageException e) {
+      assertEquals("Message missing required fields: a, b, c", e.getMessage());
+    }
+  }
+
+  public void testDynamicBuildPartial() throws Exception {
+    // We're mostly testing that no exception is thrown.
+    DynamicMessage message =
+      DynamicMessage.newBuilder(TestRequired.getDescriptor())
+        .buildPartial();
+    assertFalse(message.isInitialized());
+  }
+
+  public void testDynamicParseUnititialized() throws Exception {
+    try {
+      Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+      DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
+      fail("Should have thrown an exception.");
+    } catch (InvalidProtocolBufferException e) {
+      assertEquals("Message missing required fields: a, b, c", e.getMessage());
+    }
+  }
+  
+  /** Test reading unset repeated message from DynamicMessage. */
+  public void testDynamicRepeatedMessageNull() throws Exception {
+    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+    DynamicMessage result =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+        .build();
+
+    assertTrue(result.getField(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")), 0);
+  }
+  
+  /** Test reading repeated message from DynamicMessage. */
+  public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+    TestAllTypes REPEATED_NESTED =
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(1)
+        .setOptionalString("foo")
+        .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+        .addRepeatedString("bar")
+        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+        .build();
+    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+    DynamicMessage result =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+        .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+        .build();
+
+    assertTrue(result.getField(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")), 2);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
new file mode 100644
index 0000000..542e28c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
@@ -0,0 +1,185 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.Vehicle;
+import protobuf_unittest.Wheel;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test cases that exercise end-to-end use cases involving
+ * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class NestedBuildersTest extends TestCase {
+
+  public void testMessagesAndBuilders() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(1);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(2);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(3);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(4);
+    vehicleBuilder.getEngineBuilder()
+        .setLiters(10);
+
+    Vehicle vehicle = vehicleBuilder.build();
+    assertEquals(4, vehicle.getWheelCount());
+    for (int i = 0; i < 4; i++) {
+      Wheel wheel = vehicle.getWheel(i);
+      assertEquals(4, wheel.getRadius());
+      assertEquals(i + 1, wheel.getWidth());
+    }
+    assertEquals(10, vehicle.getEngine().getLiters());
+
+    for (int i = 0; i < 4; i++) {
+      vehicleBuilder.getWheelBuilder(i)
+          .setRadius(5)
+          .setWidth(i + 10);
+    }
+    vehicleBuilder.getEngineBuilder().setLiters(20);
+
+    vehicle = vehicleBuilder.build();
+    for (int i = 0; i < 4; i++) {
+      Wheel wheel = vehicle.getWheel(i);
+      assertEquals(5, wheel.getRadius());
+      assertEquals(i + 10, wheel.getWidth());
+    }
+    assertEquals(20, vehicle.getEngine().getLiters());
+    assertTrue(vehicle.hasEngine());
+  }
+
+  public void testMessagesAreCached() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(1)
+        .setWidth(2);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(3)
+        .setWidth(4);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(5)
+        .setWidth(6);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(7)
+        .setWidth(8);
+
+    // Make sure messages are cached.
+    List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
+    for (int i = 0; i < wheels.size(); i++) {
+      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+    }
+
+    // Now get builders and check they didn't change.
+    for (int i = 0; i < wheels.size(); i++) {
+      vehicleBuilder.getWheel(i);
+    }
+    for (int i = 0; i < wheels.size(); i++) {
+      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+    }
+
+    // Change just one
+    vehicleBuilder.getWheelBuilder(3)
+        .setRadius(20).setWidth(20);
+
+    // Now get wheels and check that only that one changed
+    for (int i = 0; i < wheels.size(); i++) {
+      if (i < 3) {
+        assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+      } else {
+        assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
+      }
+    }
+  }
+
+  public void testRemove_WithNestedBuilders() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(1)
+        .setWidth(1);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(2)
+        .setWidth(2);
+    vehicleBuilder.removeWheel(0);
+
+    assertEquals(1, vehicleBuilder.getWheelCount());
+    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+  }
+
+  public void testRemove_WithNestedMessages() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheel(Wheel.newBuilder()
+        .setRadius(1)
+        .setWidth(1));
+    vehicleBuilder.addWheel(Wheel.newBuilder()
+        .setRadius(2)
+        .setWidth(2));
+    vehicleBuilder.removeWheel(0);
+
+    assertEquals(1, vehicleBuilder.getWheelCount());
+    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+  }
+
+  public void testMerge() {
+    Vehicle vehicle1 = Vehicle.newBuilder()
+        .addWheel(Wheel.newBuilder().setRadius(1).build())
+        .addWheel(Wheel.newBuilder().setRadius(2).build())
+        .build();
+
+    Vehicle vehicle2 = Vehicle.newBuilder()
+        .mergeFrom(vehicle1)
+        .build();
+    // List should be the same -- no allocation
+    assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
+
+    Vehicle vehicle3 = vehicle1.toBuilder().build();
+    assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
+  }
+
+  public void testGettingBuilderMarksFieldAsHaving() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.getEngineBuilder();
+    Vehicle vehicle = vehicleBuilder.buildPartial();
+    assertTrue(vehicle.hasEngine());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
new file mode 100644
index 0000000..6be5b93
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
@@ -0,0 +1,620 @@
+// 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.
+
+package com.google.protobuf;
+
+import static com.google.protobuf.Internal.UTF_8;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Tests for {@link NioByteString}.
+ */
+public class NioByteStringTest extends TestCase {
+  private static final ByteString EMPTY = new NioByteString(ByteBuffer.wrap(new byte[0]));
+  private static final String CLASSNAME = NioByteString.class.getSimpleName();
+  private static final byte[] BYTES = ByteStringTest.getTestBytes(1234, 11337766L);
+  private static final int EXPECTED_HASH = ByteString.wrap(BYTES).hashCode();
+
+  private final ByteBuffer backingBuffer = ByteBuffer.wrap(BYTES.clone());
+  private final ByteString testString = new NioByteString(backingBuffer);
+
+  public void testExpectedType() {
+    String actualClassName = getActualClassName(testString);
+    assertEquals(CLASSNAME + " should match type exactly", CLASSNAME, actualClassName);
+  }
+
+  protected String getActualClassName(Object object) {
+    String actualClassName = object.getClass().getName();
+    actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+    return actualClassName;
+  }
+
+  public void testByteAt() {
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+      stillEqual = (BYTES[i] == testString.byteAt(i));
+    }
+    assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+  }
+
+  public void testByteIterator() {
+    boolean stillEqual = true;
+    ByteString.ByteIterator iter = testString.iterator();
+    for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+      stillEqual = (iter.hasNext() && BYTES[i] == iter.nextByte());
+    }
+    assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+    assertFalse(CLASSNAME + " must have exhausted the itertor", iter.hasNext());
+
+    try {
+      iter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+  }
+
+  public void testByteIterable() {
+    boolean stillEqual = true;
+    int j = 0;
+    for (byte quantum : testString) {
+      stillEqual = (BYTES[j] == quantum);
+      ++j;
+    }
+    assertTrue(CLASSNAME + " must capture the right bytes as Bytes", stillEqual);
+    assertEquals(CLASSNAME + " iterable character count", BYTES.length, j);
+  }
+
+  public void testSize() {
+    assertEquals(CLASSNAME + " must have the expected size", BYTES.length,
+        testString.size());
+  }
+
+  public void testGetTreeDepth() {
+    assertEquals(CLASSNAME + " must have depth 0", 0, testString.getTreeDepth());
+  }
+
+  public void testIsBalanced() {
+    assertTrue(CLASSNAME + " is technically balanced", testString.isBalanced());
+  }
+
+  public void testCopyTo_ByteArrayOffsetLength() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+    int sourceOffset = 213;
+    testString.copyTo(destination, sourceOffset, destinationOffset, length);
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < length; ++i) {
+      stillEqual = BYTES[i + sourceOffset] == destination[i + destinationOffset];
+    }
+    assertTrue(CLASSNAME + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+  }
+
+  public void testCopyTo_ByteArrayOffsetLengthErrors() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+
+    try {
+      // Copy one too many bytes
+      testString.copyTo(destination, testString.size() + 1 - length,
+          destinationOffset, length);
+      fail("Should have thrown an exception when copying too many bytes of a "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative sourceOffset
+      testString.copyTo(destination, -1, destinationOffset, length);
+      fail("Should have thrown an exception when given a negative sourceOffset in "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative destinationOffset
+      testString.copyTo(destination, 0, -1, length);
+      fail("Should have thrown an exception when given a negative destinationOffset in "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative size
+      testString.copyTo(destination, 0, 0, -1);
+      fail("Should have thrown an exception when given a negative size in "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large sourceOffset
+      testString.copyTo(destination, 2 * testString.size(), 0, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large destinationOffset
+      testString.copyTo(destination, 0, 2 * destination.length, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + CLASSNAME);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+  }
+
+  public void testCopyTo_ByteBuffer() {
+    // Same length.
+    ByteBuffer myBuffer = ByteBuffer.allocate(BYTES.length);
+    testString.copyTo(myBuffer);
+    myBuffer.flip();
+    assertEquals(CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes",
+        backingBuffer, myBuffer);
+
+    // Target buffer bigger than required.
+    myBuffer = ByteBuffer.allocate(testString.size() + 1);
+    testString.copyTo(myBuffer);
+    myBuffer.flip();
+    assertEquals(backingBuffer, myBuffer);
+
+    // Target buffer has no space.
+    myBuffer = ByteBuffer.allocate(0);
+    try {
+      testString.copyTo(myBuffer);
+      fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+    } catch (BufferOverflowException e) {
+      // Expected.
+    }
+
+    // Target buffer too small.
+    myBuffer = ByteBuffer.allocate(1);
+    try {
+      testString.copyTo(myBuffer);
+      fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+    } catch (BufferOverflowException e) {
+      // Expected.
+    }
+  }
+
+  public void testMarkSupported() {
+    InputStream stream = testString.newInput();
+    assertTrue(CLASSNAME + ".newInput() must support marking", stream.markSupported());
+  }
+
+  public void testMarkAndReset() throws IOException {
+    int fraction = testString.size() / 3;
+
+    InputStream stream = testString.newInput();
+    stream.mark(testString.size()); // First, mark() the end.
+
+    skipFully(stream, fraction); // Skip a large fraction, but not all.
+    assertEquals(
+        CLASSNAME + ": after skipping to the 'middle', half the bytes are available",
+        (testString.size() - fraction), stream.available());
+    stream.reset();
+    assertEquals(
+        CLASSNAME + ": after resetting, all bytes are available",
+        testString.size(), stream.available());
+
+    skipFully(stream, testString.size()); // Skip to the end.
+    assertEquals(
+        CLASSNAME + ": after skipping to the end, no more bytes are available",
+        0, stream.available());
+  }
+
+  /**
+   * Discards {@code n} bytes of data from the input stream. This method
+   * will block until the full amount has been skipped. Does not close the
+   * stream.
+   * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+   *
+   * @param in the input stream to read from
+   * @param n the number of bytes to skip
+   * @throws EOFException if this stream reaches the end before skipping all
+   *     the bytes
+   * @throws IOException if an I/O error occurs, or the stream does not
+   *     support skipping
+   */
+  static void skipFully(InputStream in, long n) throws IOException {
+    long toSkip = n;
+    while (n > 0) {
+      long amt = in.skip(n);
+      if (amt == 0) {
+        // Force a blocking read to avoid infinite loop
+        if (in.read() == -1) {
+          long skipped = toSkip - n;
+          throw new EOFException("reached end of stream after skipping "
+              + skipped + " bytes; " + toSkip + " bytes expected");
+        }
+        n--;
+      } else {
+        n -= amt;
+      }
+    }
+  }
+
+  public void testAsReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer = testString.asReadOnlyByteBuffer();
+    byte[] roundTripBytes = new byte[BYTES.length];
+    assertTrue(byteBuffer.remaining() == BYTES.length);
+    assertTrue(byteBuffer.isReadOnly());
+    byteBuffer.get(roundTripBytes);
+    assertTrue(CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes",
+        Arrays.equals(BYTES, roundTripBytes));
+  }
+
+  public void testAsReadOnlyByteBufferList() {
+    List<ByteBuffer> byteBuffers = testString.asReadOnlyByteBufferList();
+    int bytesSeen = 0;
+    byte[] roundTripBytes = new byte[BYTES.length];
+    for (ByteBuffer byteBuffer : byteBuffers) {
+      int thisLength = byteBuffer.remaining();
+      assertTrue(byteBuffer.isReadOnly());
+      assertTrue(bytesSeen + thisLength <= BYTES.length);
+      byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+      bytesSeen += thisLength;
+    }
+    assertTrue(bytesSeen == BYTES.length);
+    assertTrue(CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes",
+        Arrays.equals(BYTES, roundTripBytes));
+  }
+
+  public void testToByteArray() {
+    byte[] roundTripBytes = testString.toByteArray();
+    assertTrue(CLASSNAME + ".toByteArray() must give back the same bytes",
+        Arrays.equals(BYTES, roundTripBytes));
+  }
+
+  public void testWriteTo() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    testString.writeTo(bos);
+    byte[] roundTripBytes = bos.toByteArray();
+    assertTrue(CLASSNAME + ".writeTo() must give back the same bytes",
+        Arrays.equals(BYTES, roundTripBytes));
+  }
+
+  public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException {
+    OutputStream os = new OutputStream() {
+      @Override
+      public void write(byte[] b, int off, int len) {
+        Arrays.fill(b, off, off + len, (byte) 0);
+      }
+
+      @Override
+      public void write(int b) {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    byte[] original = Arrays.copyOf(BYTES, BYTES.length);
+    testString.writeTo(os);
+    assertTrue(CLASSNAME + ".writeTo() must NOT grant access to underlying buffer",
+        Arrays.equals(original, BYTES));
+  }
+
+  public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException {
+    OutputStream os = new OutputStream() {
+      @Override
+      public void write(byte[] b, int off, int len) {
+        Arrays.fill(b, off, off + len, (byte) 0);
+      }
+
+      @Override
+      public void write(int b) {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    testString.writeToInternal(os, 0, testString.size());
+    byte[] allZeros = new byte[testString.size()];
+    assertTrue(CLASSNAME + ".writeToInternal() must grant access to underlying buffer",
+        Arrays.equals(allZeros, backingBuffer.array()));
+  }
+
+  public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException {
+    ByteOutput out = new ByteOutput() {
+      @Override
+      public void write(byte value) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void write(byte[] value, int offset, int length) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void writeLazy(byte[] value, int offset, int length) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void write(ByteBuffer value) throws IOException {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void writeLazy(ByteBuffer value) throws IOException {
+        Arrays.fill(value.array(), value.arrayOffset(), value.arrayOffset() + value.limit(),
+            (byte) 0);
+      }
+    };
+
+    testString.writeTo(out);
+    byte[] allZeros = new byte[testString.size()];
+    assertTrue(CLASSNAME + ".writeTo() must grant access to underlying buffer",
+        Arrays.equals(allZeros, backingBuffer.array()));
+  }
+
+  public void testNewOutput() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    ByteString.Output output = ByteString.newOutput();
+    testString.writeTo(output);
+    assertEquals("Output Size returns correct result",
+        output.size(), testString.size());
+    output.writeTo(bos);
+    assertTrue("Output.writeTo() must give back the same bytes",
+        Arrays.equals(BYTES, bos.toByteArray()));
+
+    // write the output stream to itself! This should cause it to double
+    output.writeTo(output);
+    assertEquals("Writing an output stream to itself is successful",
+        testString.concat(testString), output.toByteString());
+
+    output.reset();
+    assertEquals("Output.reset() resets the output", 0, output.size());
+    assertEquals("Output.reset() resets the output",
+        EMPTY, output.toByteString());
+  }
+
+  public void testToString() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = forString(testString);
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+  }
+
+  public void testCharsetToString() {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString unicode = forString(testString);
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+  }
+
+  public void testToString_returnsCanonicalEmptyString() {
+    assertSame(CLASSNAME + " must be the same string references",
+        EMPTY.toString(UTF_8),
+        new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8));
+  }
+
+  public void testToString_raisesException() {
+    try {
+      EMPTY.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+
+    try {
+      testString.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+  }
+
+  public void testEquals() {
+    assertEquals(CLASSNAME + " must not equal null", false, testString.equals(null));
+    assertEquals(CLASSNAME + " must equal self", testString, testString);
+    assertFalse(CLASSNAME + " must not equal the empty string",
+        testString.equals(EMPTY));
+    assertEquals(CLASSNAME + " empty strings must be equal",
+        EMPTY, testString.substring(55, 55));
+    assertEquals(CLASSNAME + " must equal another string with the same value",
+        testString, new NioByteString(backingBuffer));
+
+    byte[] mungedBytes = mungedBytes();
+    assertFalse(CLASSNAME + " must not equal every string with the same length",
+        testString.equals(new NioByteString(ByteBuffer.wrap(mungedBytes))));
+  }
+
+  public void testEqualsLiteralByteString() {
+    ByteString literal = ByteString.copyFrom(BYTES);
+    assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal,
+        testString);
+    assertEquals(CLASSNAME + " must equal LiteralByteString with same value", testString,
+        literal);
+    assertFalse(CLASSNAME + " must not equal the empty string",
+        testString.equals(ByteString.EMPTY));
+    assertEquals(CLASSNAME + " empty strings must be equal",
+        ByteString.EMPTY, testString.substring(55, 55));
+
+    literal = ByteString.copyFrom(mungedBytes());
+    assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+        testString.equals(literal));
+    assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+        literal.equals(testString));
+  }
+
+  public void testEqualsRopeByteString() {
+    ByteString p1 = ByteString.copyFrom(BYTES, 0, 5);
+    ByteString p2 = ByteString.copyFrom(BYTES, 5, BYTES.length - 5);
+    ByteString rope = p1.concat(p2);
+
+    assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope,
+        testString);
+    assertEquals(CLASSNAME + " must equal RopeByteString with same value", testString,
+        rope);
+    assertFalse(CLASSNAME + " must not equal the empty string",
+        testString.equals(ByteString.EMPTY.concat(ByteString.EMPTY)));
+    assertEquals(CLASSNAME + " empty strings must be equal",
+        ByteString.EMPTY.concat(ByteString.EMPTY), testString.substring(55, 55));
+
+    byte[] mungedBytes = mungedBytes();
+    p1 = ByteString.copyFrom(mungedBytes, 0, 5);
+    p2 = ByteString.copyFrom(mungedBytes, 5, mungedBytes.length - 5);
+    rope = p1.concat(p2);
+    assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+        testString.equals(rope));
+    assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+        rope.equals(testString));
+  }
+
+  private byte[] mungedBytes() {
+    byte[] mungedBytes = new byte[BYTES.length];
+    System.arraycopy(BYTES, 0, mungedBytes, 0, BYTES.length);
+    mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
+    return mungedBytes;
+  }
+
+  public void testHashCode() {
+    int hash = testString.hashCode();
+    assertEquals(CLASSNAME + " must have expected hashCode", EXPECTED_HASH, hash);
+  }
+
+  public void testPeekCachedHashCode() {
+    ByteString newString = new NioByteString(backingBuffer);
+    assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0,
+        newString.peekCachedHashCode());
+    newString.hashCode();
+    assertEquals(CLASSNAME + ".peekCachedHashCode should return zero at first",
+        EXPECTED_HASH, newString.peekCachedHashCode());
+  }
+
+  public void testPartialHash() {
+    // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+    // This test would fail if the expected hash were 1.  It's not.
+    int hash = testString.partialHash(testString.size(), 0, testString.size());
+    assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode",
+        EXPECTED_HASH, hash);
+  }
+
+  public void testNewInput() throws IOException {
+    InputStream input = testString.newInput();
+    assertEquals("InputStream.available() returns correct value",
+        testString.size(), input.available());
+    boolean stillEqual = true;
+    for (byte referenceByte : BYTES) {
+      int expectedInt = (referenceByte & 0xFF);
+      stillEqual = (expectedInt == input.read());
+    }
+    assertEquals("InputStream.available() returns correct value",
+        0, input.available());
+    assertTrue(CLASSNAME + " must give the same bytes from the InputStream", stillEqual);
+    assertEquals(CLASSNAME + " InputStream must now be exhausted", -1, input.read());
+  }
+
+  public void testNewInput_skip() throws IOException {
+    InputStream input = testString.newInput();
+    int stringSize = testString.size();
+    int nearEndIndex = stringSize * 2 / 3;
+    long skipped1 = input.skip(nearEndIndex);
+    assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+    assertEquals("InputStream.available()",
+        stringSize - skipped1, input.available());
+    assertTrue("InputStream.mark() is available", input.markSupported());
+    input.mark(0);
+    assertEquals("InputStream.skip(), read()",
+        testString.byteAt(nearEndIndex) & 0xFF, input.read());
+    assertEquals("InputStream.available()",
+        stringSize - skipped1 - 1, input.available());
+    long skipped2 = input.skip(stringSize);
+    assertEquals("InputStream.skip() incomplete",
+        skipped2, stringSize - skipped1 - 1);
+    assertEquals("InputStream.skip(), no more input", 0, input.available());
+    assertEquals("InputStream.skip(), no more input", -1, input.read());
+    input.reset();
+    assertEquals("InputStream.reset() succeded",
+        stringSize - skipped1, input.available());
+    assertEquals("InputStream.reset(), read()",
+        testString.byteAt(nearEndIndex) & 0xFF, input.read());
+  }
+
+  public void testNewCodedInput() throws IOException {
+    CodedInputStream cis = testString.newCodedInput();
+    byte[] roundTripBytes = cis.readRawBytes(BYTES.length);
+    assertTrue(CLASSNAME + " must give the same bytes back from the CodedInputStream",
+        Arrays.equals(BYTES, roundTripBytes));
+    assertTrue(CLASSNAME + " CodedInputStream must now be exhausted", cis.isAtEnd());
+  }
+
+  /**
+   * Make sure we keep things simple when concatenating with empty. See also
+   * {@link ByteStringTest#testConcat_empty()}.
+   */
+  public void testConcat_empty() {
+    assertSame(CLASSNAME + " concatenated with empty must give " + CLASSNAME,
+        testString.concat(EMPTY), testString);
+    assertSame("empty concatenated with " + CLASSNAME + " must give " + CLASSNAME,
+        EMPTY.concat(testString), testString);
+  }
+
+  public void testJavaSerialization() throws Exception {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream oos = new ObjectOutputStream(out);
+    oos.writeObject(testString);
+    oos.close();
+    byte[] pickled = out.toByteArray();
+    InputStream in = new ByteArrayInputStream(pickled);
+    ObjectInputStream ois = new ObjectInputStream(in);
+    Object o = ois.readObject();
+    assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+    assertEquals("Should get an equal ByteString back", testString, o);
+  }
+
+  private static ByteString forString(String str) {
+    return new NioByteString(ByteBuffer.wrap(str.getBytes(UTF_8)));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
new file mode 100644
index 0000000..bf1f1d7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
@@ -0,0 +1,273 @@
+// 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.
+
+package com.google.protobuf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Tests the exceptions thrown when parsing from a stream. The methods on the {@link Parser}
+ * interface are specified to only throw {@link InvalidProtocolBufferException}. But we really want
+ * to distinguish between invalid protos vs. actual I/O errors (like failures reading from a
+ * socket, etc.). So, when we're not using the parser directly, an {@link IOException} should be
+ * thrown where appropriate, instead of always an {@link InvalidProtocolBufferException}.
+ *
+ * @author jh@squareup.com (Joshua Humphries)
+ */
+@RunWith(JUnit4.class)
+public class ParseExceptionsTest {
+
+  private interface ParseTester {
+    DescriptorProto parse(InputStream in) throws IOException;
+  }
+
+  private byte serializedProto[];
+
+  private void setup() {
+    serializedProto = DescriptorProto.getDescriptor().toProto().toByteArray();
+  }
+
+  private void setupDelimited() {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    try {
+      DescriptorProto.getDescriptor().toProto().writeDelimitedTo(bos);
+    } catch (IOException e) {
+      fail("Exception not expected: " + e);
+    }
+    serializedProto = bos.toByteArray();
+  }
+
+  @Test public void message_parseFrom_InputStream() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseFrom(in);
+          }
+        });
+  }
+
+  @Test public void message_parseFrom_InputStreamAndExtensionRegistry() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseFrom(in, ExtensionRegistry.newInstance());
+          }
+        });
+  }
+
+  @Test public void message_parseFrom_CodedInputStream() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseFrom(CodedInputStream.newInstance(in));
+          }
+        });
+  }
+
+  @Test public void message_parseFrom_CodedInputStreamAndExtensionRegistry() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseFrom(
+                CodedInputStream.newInstance(in), ExtensionRegistry.newInstance());
+          }
+        });
+  }
+
+  @Test public void message_parseDelimitedFrom_InputStream() {
+    setupDelimited();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseDelimitedFrom(in);
+          }
+        });
+  }
+
+  @Test public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() {
+    setupDelimited();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.parseDelimitedFrom(in, ExtensionRegistry.newInstance());
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeFrom_InputStream() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.newBuilder().mergeFrom(in).build();
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.newBuilder()
+                .mergeFrom(in, ExtensionRegistry.newInstance())
+                .build();
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeFrom_CodedInputStream() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.newBuilder().mergeFrom(CodedInputStream.newInstance(in)).build();
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeFrom_CodedInputStreamAndExtensionRegistry() {
+    setup();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            return DescriptorProto.newBuilder()
+                .mergeFrom(CodedInputStream.newInstance(in), ExtensionRegistry.newInstance())
+                .build();
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeDelimitedFrom_InputStream() {
+    setupDelimited();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+            builder.mergeDelimitedFrom(in);
+            return builder.build();
+          }
+        });
+  }
+
+  @Test public void messageBuilder_mergeDelimitedFrom_InputStreamAndExtensionRegistry() {
+    setupDelimited();
+    verifyExceptions(
+        new ParseTester() {
+          @Override
+          public DescriptorProto parse(InputStream in) throws IOException {
+            DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+            builder.mergeDelimitedFrom(in, ExtensionRegistry.newInstance());
+            return builder.build();
+          }
+        });
+  }
+
+  private void verifyExceptions(ParseTester parseTester) {
+    // No exception
+    try {
+      assertEquals(DescriptorProto.getDescriptor().toProto(),
+          parseTester.parse(new ByteArrayInputStream(serializedProto)));
+    } catch (IOException e) {
+      fail("No exception expected: " + e);
+    }
+
+    // IOException
+    try {
+      // using a "broken" stream that will throw part-way through reading the message
+      parseTester.parse(broken(new ByteArrayInputStream(serializedProto)));
+      fail("IOException expected but not thrown");
+    } catch (IOException e) {
+      assertFalse(e instanceof InvalidProtocolBufferException);
+    }
+
+    // InvalidProtocolBufferException
+    try {
+      // make the serialized proto invalid
+      for (int i = 0; i < 50; i++) {
+        serializedProto[i] = -1;
+      }
+      parseTester.parse(new ByteArrayInputStream(serializedProto));
+      fail("InvalidProtocolBufferException expected but not thrown");
+    } catch (IOException e) {
+      assertTrue(e instanceof InvalidProtocolBufferException);
+    }
+  }
+
+  private InputStream broken(InputStream i) {
+    return new FilterInputStream(i) {
+      int count = 0;
+
+      @Override public int read() throws IOException {
+        if (count++ >= 50) {
+          throw new IOException("I'm broken!");
+        }
+        return super.read();
+      }
+
+      @Override public int read(byte b[], int off, int len) throws IOException {
+        if ((count += len) >= 50) {
+          throw new IOException("I'm broken!");
+        }
+        return super.read(b, off, len);
+      }
+    };
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParserTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParserTest.java
new file mode 100644
index 0000000..30842d2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ParserTest.java
@@ -0,0 +1,377 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.TestParsingMergeLite;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto.TestRequired;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+  public void testGeneratedMessageParserSingleton() throws Exception {
+    for (int i = 0; i < 10; i++) {
+      assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
+    }
+  }
+
+  private void assertRoundTripEquals(MessageLite message,
+                                     ExtensionRegistryLite registry)
+      throws Exception {
+    final byte[] data = message.toByteArray();
+    final int offset = 20;
+    final int length = data.length;
+    final int padding = 30;
+    Parser<? extends MessageLite> parser = message.getParserForType();
+    assertMessageEquals(message, parser.parseFrom(data, registry));
+    assertMessageEquals(message, parser.parseFrom(
+        generatePaddingArray(data, offset, padding),
+        offset, length, registry));
+    assertMessageEquals(message, parser.parseFrom(
+        message.toByteString(), registry));
+    assertMessageEquals(message, parser.parseFrom(
+        new ByteArrayInputStream(data), registry));
+    assertMessageEquals(message, parser.parseFrom(
+        CodedInputStream.newInstance(data), registry));
+  }
+
+  @SuppressWarnings("unchecked")
+  private void assertRoundTripEquals(MessageLite message) throws Exception {
+    final byte[] data = message.toByteArray();
+    final int offset = 20;
+    final int length = data.length;
+    final int padding = 30;
+
+    Parser<MessageLite> parser =
+        (Parser<MessageLite>) message.getParserForType();
+    assertMessageEquals(message, parser.parseFrom(data));
+    assertMessageEquals(message, parser.parseFrom(
+        generatePaddingArray(data, offset, padding),
+        offset, length));
+    assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+    assertMessageEquals(message, parser.parseFrom(
+        new ByteArrayInputStream(data)));
+    assertMessageEquals(message, parser.parseFrom(
+        CodedInputStream.newInstance(data)));
+  }
+
+  private void assertMessageEquals(
+      MessageLite expected, MessageLite actual)
+      throws Exception {
+    if (expected instanceof Message) {
+      assertEquals(expected, actual);
+    } else {
+      assertEquals(expected.toByteString(), actual.toByteString());
+    }
+  }
+
+  private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+    byte[] result = new byte[offset + data.length + padding];
+    System.arraycopy(data, 0, result, offset, data.length);
+    return result;
+  }
+
+  public void testNormalMessage() throws Exception {
+    assertRoundTripEquals(TestUtil.getAllSet());
+  }
+
+
+  public void testParsePartial() throws Exception {
+    assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
+  }
+
+  private <T extends MessageLite> void assertParsePartial(
+      Parser<T> parser, T partialMessage) throws Exception {
+    final String errorString =
+        "Should throw exceptions when the parsed message isn't initialized.";
+
+    // parsePartialFrom should pass.
+    byte[] data = partialMessage.toByteArray();
+    assertEquals(partialMessage, parser.parsePartialFrom(data));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        partialMessage.toByteString()));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        new ByteArrayInputStream(data)));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        CodedInputStream.newInstance(data)));
+
+    // parseFrom(ByteArray)
+    try {
+      parser.parseFrom(partialMessage.toByteArray());
+      fail(errorString);
+    } catch (InvalidProtocolBufferException e) {
+      // pass.
+    }
+
+    // parseFrom(ByteString)
+    try {
+      parser.parseFrom(partialMessage.toByteString());
+      fail(errorString);
+    } catch (InvalidProtocolBufferException e) {
+      // pass.
+    }
+
+    // parseFrom(InputStream)
+    try {
+      parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+      fail(errorString);
+    } catch (IOException e) {
+      // pass.
+    }
+
+    // parseFrom(CodedInputStream)
+    try {
+      parser.parseFrom(CodedInputStream.newInstance(
+          partialMessage.toByteArray()));
+      fail(errorString);
+    } catch (IOException e) {
+      // pass.
+    }
+  }
+
+  public void testParseExtensions() throws Exception {
+    assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
+                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(
+        TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+  }
+
+  public void testParsePacked() throws Exception {
+    assertRoundTripEquals(TestUtil.getPackedSet());
+    assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
+                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(
+        TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+  }
+
+  public void testParseDelimitedTo() throws Exception {
+    // Write normal Message.
+    TestAllTypes normalMessage = TestUtil.getAllSet();
+    ByteArrayOutputStream output = new ByteArrayOutputStream();
+    normalMessage.writeDelimitedTo(output);
+
+    // Write MessageLite with packed extension fields.
+    TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet();
+    packedMessage.writeDelimitedTo(output);
+
+    InputStream input = new ByteArrayInputStream(output.toByteArray());
+    assertMessageEquals(
+        normalMessage,
+        normalMessage.getParserForType().parseDelimitedFrom(input));
+    assertMessageEquals(
+        packedMessage,
+        packedMessage
+            .getParserForType()
+            .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
+  }
+
+  public void testParseUnknownFields() throws Exception {
+    // All fields will be treated as unknown fields in emptyMessage.
+    TestEmptyMessage emptyMessage =
+        TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
+    assertEquals(
+        TestUtil.getAllSet().toByteString(),
+        emptyMessage.toByteString());
+  }
+
+
+  public void testOptimizeForSize() throws Exception {
+    TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+    builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+    builder.setExtension(TestOptimizedForSize.testExtension, 56);
+    builder.setExtension(TestOptimizedForSize.testExtension2,
+        TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+    TestOptimizedForSize message = builder.build();
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestOptimizeFor.registerAllExtensions(registry);
+
+    assertRoundTripEquals(message, registry);
+  }
+
+  /** Helper method for {@link #testParsingMerge()}.*/
+  private void assertMessageMerged(TestAllTypes allTypes)
+      throws Exception {
+    assertEquals(3, allTypes.getOptionalInt32());
+    assertEquals(2, allTypes.getOptionalInt64());
+    assertEquals("hello", allTypes.getOptionalString());
+  }
+
+  /** Helper method for {@link #testParsingMergeLite()}.*/
+  private void assertMessageMerged(TestAllTypesLite allTypes)
+      throws Exception {
+    assertEquals(3, allTypes.getOptionalInt32());
+    assertEquals(2, allTypes.getOptionalInt64());
+    assertEquals("hello", allTypes.getOptionalString());
+  }
+
+  public void testParsingMerge() throws Exception {
+    // Build messages.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+    builder.clear();
+    TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+    builder.clear();
+    TestAllTypes msg3 = builder.setOptionalInt32(3)
+        .setOptionalString("hello").build();
+
+    // Build groups.
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg3).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg3).build();
+
+    // Assign and serialize RepeatedFieldsGenerator.
+    ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+        .addField1(msg1).addField1(msg2).addField1(msg3)
+        .addField2(msg1).addField2(msg2).addField2(msg3)
+        .addField3(msg1).addField3(msg2).addField3(msg3)
+        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+        .build().toByteString();
+
+    // Parse TestParsingMerge.
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestProto.registerAllExtensions(registry);
+    TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
+
+    // Required and optional fields should be merged.
+    assertMessageMerged(parsingMerge.getRequiredAllTypes());
+    assertMessageMerged(parsingMerge.getOptionalAllTypes());
+    assertMessageMerged(
+        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+    assertMessageMerged(parsingMerge.getExtension(
+        TestParsingMerge.optionalExt));
+
+    // Repeated fields should not be merged.
+    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+    assertEquals(3, parsingMerge.getRepeatedGroupCount());
+    assertEquals(3, parsingMerge.getExtensionCount(
+        TestParsingMerge.repeatedExt));
+  }
+
+  public void testParsingMergeLite() throws Exception {
+    // Build messages.
+    TestAllTypesLite.Builder builder =
+        TestAllTypesLite.newBuilder();
+    TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
+    builder.clear();
+    TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
+    builder.clear();
+    TestAllTypesLite msg3 = builder.setOptionalInt32(3)
+        .setOptionalString("hello").build();
+
+    // Build groups.
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg3).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg3).build();
+
+    // Assign and serialize RepeatedFieldsGenerator.
+    ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
+        .addField1(msg1).addField1(msg2).addField1(msg3)
+        .addField2(msg1).addField2(msg2).addField2(msg3)
+        .addField3(msg1).addField3(msg2).addField3(msg3)
+        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+        .build().toByteString();
+
+    // Parse TestParsingMergeLite.
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestLite.registerAllExtensions(registry);
+    TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
+
+    // Required and optional fields should be merged.
+    assertMessageMerged(parsingMerge.getRequiredAllTypes());
+    assertMessageMerged(parsingMerge.getOptionalAllTypes());
+    assertMessageMerged(
+        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+    assertMessageMerged(parsingMerge.getExtension(
+        TestParsingMergeLite.optionalExt));
+
+    // Repeated fields should not be merged.
+    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+    assertEquals(3, parsingMerge.getRepeatedGroupCount());
+    assertEquals(3, parsingMerge.getExtensionCount(
+        TestParsingMergeLite.repeatedExt));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
new file mode 100644
index 0000000..3f45e22
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
@@ -0,0 +1,289 @@
+// 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.
+
+package com.google.protobuf;
+
+import static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests for {@link ProtobufArrayList}.
+ */
+public class ProtobufArrayListTest extends TestCase {
+  
+  private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1);
+  private static final ProtobufArrayList<Integer> TERTIARY_LIST =
+      newImmutableProtoArrayList(1, 2, 3);
+  
+  private ProtobufArrayList<Integer> list;
+  
+  @Override
+  protected void setUp() throws Exception {
+    list = new ProtobufArrayList<Integer>();
+  }
+  
+  public void testEmptyListReturnsSameInstance() {
+    assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList());
+  }
+  
+  public void testEmptyListIsImmutable() {
+    assertImmutable(ProtobufArrayList.<Integer>emptyList());
+  }
+  
+  public void testModificationWithIteration() {
+    list.addAll(asList(1, 2, 3, 4));
+    Iterator<Integer> iterator = list.iterator();
+    assertEquals(4, list.size());
+    assertEquals(1, (int) list.get(0));
+    assertEquals(1, (int) iterator.next());
+    
+    list.remove(0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.set(0, 1);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+    
+    iterator = list.iterator();
+    list.add(0, 0);
+    try {
+      iterator.next();
+      fail();
+    } catch (ConcurrentModificationException e) {
+      // expected
+    }
+  }
+  
+  public void testMakeImmutable() {
+    list.add(2);
+    list.add(4);
+    list.add(6);
+    list.add(8);
+    list.makeImmutable();
+    assertImmutable(list);
+  }
+  
+  public void testRemove() {
+    list.add(2);
+    list.add(4);
+    list.add(6);
+
+    list.remove(1);
+    assertEquals(asList(2, 6), list);
+
+    list.remove(1);
+    assertEquals(asList(2), list);
+
+    list.remove(0);
+    assertEquals(asList(), list);
+  }
+  
+  public void testGet() {
+    list.add(2);
+    list.add(6);
+    
+    assertEquals(2, (int) list.get(0));
+    assertEquals(6, (int) list.get(1));
+  }
+  
+  public void testSet() {
+    list.add(2);
+    list.add(6);
+    
+    list.set(0, 1);
+    assertEquals(1, (int) list.get(0));
+    list.set(1, 2);
+    assertEquals(2, (int) list.get(1));
+  }
+
+  private void assertImmutable(List<Integer> list) {
+    if (list.contains(1)) {
+      throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+    }
+    
+    try {
+      list.add(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.add(0, 1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(Collections.singletonList(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(new ProtobufArrayList<Integer>());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.addAll(0, Collections.<Integer>emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    } 
+
+    try {
+      list.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+
+    try {
+      list.remove(1);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.remove(new Object());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.removeAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.emptyList());
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(Collections.singleton(1));
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.retainAll(UNARY_LIST);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    
+    try {
+      list.set(0, 0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+  
+  private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) {
+    ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>();
+    for (int element : elements) {
+      list.add(element);
+    }
+    list.makeImmutable();
+    return list;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
new file mode 100644
index 0000000..49d5232
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
@@ -0,0 +1,190 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilderTest extends TestCase {
+
+  public void testBasicUse() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    List<TestAllTypes> list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+
+    // Make sure it doesn't change.
+    List<TestAllTypes> list2 = builder.build();
+    assertSame(list, list2);
+    assertEquals(0, mockParent.getInvalidationCount());
+  }
+
+  public void testGoingBackAndForth() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    // Convert to list
+    List<TestAllTypes> list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+
+    // Update 0th item
+    assertEquals(0, mockParent.getInvalidationCount());
+    builder.getBuilder(0).setOptionalString("foo");
+    assertEquals(1, mockParent.getInvalidationCount());
+    list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+      assertEquals("foo", list.get(0).getOptionalString());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+    assertEquals(1, mockParent.getInvalidationCount());
+  }
+
+  public void testVariousMethods() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
+    builder.addBuilder(0, TestAllTypes.getDefaultInstance())
+        .setOptionalInt32(0);
+    builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
+
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+    assertEquals(2, builder.getMessage(2).getOptionalInt32());
+    assertEquals(3, builder.getMessage(3).getOptionalInt32());
+
+    assertEquals(0, mockParent.getInvalidationCount());
+    List<TestAllTypes> messages = builder.build();
+    assertEquals(4, messages.size());
+    assertSame(messages, builder.build()); // expect same list
+
+    // Remove a message.
+    builder.remove(2);
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(3, builder.getCount());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+    assertEquals(3, builder.getMessage(2).getOptionalInt32());
+
+    // Remove a builder.
+    builder.remove(0);
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(2, builder.getCount());
+    assertEquals(1, builder.getMessage(0).getOptionalInt32());
+    assertEquals(3, builder.getMessage(1).getOptionalInt32());
+
+    // Test clear.
+    builder.clear();
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(0, builder.getCount());
+    assertTrue(builder.isEmpty());
+  }
+
+  public void testLists() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    builder.addMessage(0,
+        TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    // Use list of builders.
+    List<TestAllTypes.Builder> builders = builder.getBuilderList();
+    assertEquals(0, builders.get(0).getOptionalInt32());
+    assertEquals(1, builders.get(1).getOptionalInt32());
+    builders.get(0).setOptionalInt32(10);
+    builders.get(1).setOptionalInt32(11);
+
+    // Use list of protos
+    List<TestAllTypes> protos = builder.getMessageList();
+    assertEquals(10, protos.get(0).getOptionalInt32());
+    assertEquals(11, protos.get(1).getOptionalInt32());
+
+    // Add an item to the builders and verify it's updated in both
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
+    assertEquals(3, builders.size());
+    assertEquals(3, protos.size());
+  }
+
+  private void assertIsUnmodifiable(List<?> list) {
+    if (list == Collections.emptyList()) {
+      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+    } else {
+      try {
+        list.clear();
+        fail("List wasn't immutable");
+      } catch (UnsupportedOperationException e) {
+        // good
+      }
+    }
+  }
+
+  private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+      TestAllTypesOrBuilder>
+      newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) {
+    return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
+        parent, false);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
new file mode 100644
index 0000000..dc56f2e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
@@ -0,0 +1,127 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "RopeByteString";
+    byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+    ByteString sourceString = iter.next();
+    while (iter.hasNext()) {
+      sourceString = sourceString.concat(iter.next());
+    }
+
+    int from = 1130;
+    int to = sourceBytes.length - 5555;
+    stringUnderTest = sourceString.substring(from, to);
+    referenceBytes = new byte[to - from];
+    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+    expectedHashCode = -1259260680;
+  }
+
+  @Override
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have the expected tree depth",
+        3, stringUnderTest.getTreeDepth());
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    // Do the substring part
+    testString = testString.substring(2, testString.length() - 6);
+    unicode = unicode.substring(2, unicode.size() - 6);
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+
+  @Override
+  public void testCharsetToString() {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    // Do the substring part
+    testString = testString.substring(2, testString.length() - 6);
+    unicode = unicode.substring(2, unicode.size() - 6);
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(Internal.UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
new file mode 100644
index 0000000..4ec3a40
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -0,0 +1,189 @@
+// 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.
+ *
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "RopeByteString";
+    referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+    stringUnderTest = iter.next();
+    while (iter.hasNext()) {
+      stringUnderTest = stringUnderTest.concat(iter.next());
+    }
+    expectedHashCode = -1214197238;
+  }
+
+  @Override
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have the expected tree depth",
+        4, stringUnderTest.getTreeDepth());
+  }
+
+  public void testBalance() {
+    int numberOfPieces = 10000;
+    int pieceSize = 64;
+    byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+    // Build up a big ByteString from smaller pieces to force a rebalance
+    ByteString concatenated = ByteString.EMPTY;
+    for (int i = 0; i < numberOfPieces; ++i) {
+      concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+    }
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(concatenated));
+    assertTrue(classUnderTest + " underlying bytes must match after balancing",
+        Arrays.equals(testBytes, concatenated.toByteArray()));
+    ByteString testString = ByteString.copyFrom(testBytes);
+    assertTrue(classUnderTest + " balanced string must equal flat string",
+        concatenated.equals(testString));
+    assertTrue(classUnderTest + " flat string must equal balanced string",
+        testString.equals(concatenated));
+    assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+        testString.hashCode(), concatenated.hashCode());
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+
+  @Override
+  public void testCharsetToString() {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(Internal.UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+
+  @Override
+  public void testToString_returnsCanonicalEmptyString() {
+    RopeByteString ropeByteString =
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+    assertSame(classUnderTest + " must be the same string references",
+        ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8));
+  }
+
+  @Override
+  public void testToString_raisesException() {
+    try {
+      ByteString byteString =
+          RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+      byteString.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+
+    try {
+      ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"),
+          ByteString.copyFromUtf8("bar"));
+      byteString.toString("invalid");
+      fail("Should have thrown an exception.");
+    } catch (UnsupportedEncodingException expected) {
+      // This is success
+    }
+  }
+
+  @Override
+  public void testJavaSerialization() throws Exception {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    ObjectOutputStream oos = new ObjectOutputStream(out);
+    oos.writeObject(stringUnderTest);
+    oos.close();
+    byte[] pickled = out.toByteArray();
+    InputStream in = new ByteArrayInputStream(pickled);
+    ObjectInputStream ois = new ObjectInputStream(in);
+    Object o = ois.readObject();
+    assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+    assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ServiceTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ServiceTest.java
new file mode 100644
index 0000000..b902737
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/ServiceTest.java
@@ -0,0 +1,326 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestProto.BarRequest;
+import protobuf_unittest.UnittestProto.BarResponse;
+import protobuf_unittest.UnittestProto.FooRequest;
+import protobuf_unittest.UnittestProto.FooResponse;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestService;
+
+import junit.framework.TestCase;
+
+import org.easymock.classextension.EasyMock;
+import org.easymock.IArgumentMatcher;
+import org.easymock.classextension.IMocksControl;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Tests services and stubs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ServiceTest extends TestCase {
+  private IMocksControl control;
+  private RpcController mockController;
+
+  private final Descriptors.MethodDescriptor fooDescriptor =
+    TestService.getDescriptor().getMethods().get(0);
+  private final Descriptors.MethodDescriptor barDescriptor =
+    TestService.getDescriptor().getMethods().get(1);
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    control = EasyMock.createStrictControl();
+    mockController = control.createMock(RpcController.class);
+  }
+
+  // =================================================================
+
+  /** Tests Service.callMethod(). */
+  public void testCallMethod() throws Exception {
+    FooRequest fooRequest = FooRequest.newBuilder().build();
+    BarRequest barRequest = BarRequest.newBuilder().build();
+    MockCallback<Message> fooCallback = new MockCallback<Message>();
+    MockCallback<Message> barCallback = new MockCallback<Message>();
+    TestService mockService = control.createMock(TestService.class);
+
+    mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
+                    this.<FooResponse>wrapsCallback(fooCallback));
+    mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
+                    this.<BarResponse>wrapsCallback(barCallback));
+    control.replay();
+
+    mockService.callMethod(fooDescriptor, mockController,
+                           fooRequest, fooCallback);
+    mockService.callMethod(barDescriptor, mockController,
+                           barRequest, barCallback);
+    control.verify();
+  }
+
+  /** Tests Service.get{Request,Response}Prototype(). */
+  public void testGetPrototype() throws Exception {
+    TestService mockService = control.createMock(TestService.class);
+
+    assertSame(mockService.getRequestPrototype(fooDescriptor),
+               FooRequest.getDefaultInstance());
+    assertSame(mockService.getResponsePrototype(fooDescriptor),
+               FooResponse.getDefaultInstance());
+    assertSame(mockService.getRequestPrototype(barDescriptor),
+               BarRequest.getDefaultInstance());
+    assertSame(mockService.getResponsePrototype(barDescriptor),
+               BarResponse.getDefaultInstance());
+  }
+
+  /** Tests generated stubs. */
+  public void testStub() throws Exception {
+    FooRequest fooRequest = FooRequest.newBuilder().build();
+    BarRequest barRequest = BarRequest.newBuilder().build();
+    MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
+    MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
+    RpcChannel mockChannel = control.createMock(RpcChannel.class);
+    TestService stub = TestService.newStub(mockChannel);
+
+    mockChannel.callMethod(
+      EasyMock.same(fooDescriptor),
+      EasyMock.same(mockController),
+      EasyMock.same(fooRequest),
+      EasyMock.same(FooResponse.getDefaultInstance()),
+      this.<Message>wrapsCallback(fooCallback));
+    mockChannel.callMethod(
+      EasyMock.same(barDescriptor),
+      EasyMock.same(mockController),
+      EasyMock.same(barRequest),
+      EasyMock.same(BarResponse.getDefaultInstance()),
+      this.<Message>wrapsCallback(barCallback));
+    control.replay();
+
+    stub.foo(mockController, fooRequest, fooCallback);
+    stub.bar(mockController, barRequest, barCallback);
+    control.verify();
+  }
+
+  /** Tests generated blocking stubs. */
+  public void testBlockingStub() throws Exception {
+    FooRequest fooRequest = FooRequest.newBuilder().build();
+    BarRequest barRequest = BarRequest.newBuilder().build();
+    BlockingRpcChannel mockChannel =
+        control.createMock(BlockingRpcChannel.class);
+    TestService.BlockingInterface stub =
+        TestService.newBlockingStub(mockChannel);
+
+    FooResponse fooResponse = FooResponse.newBuilder().build();
+    BarResponse barResponse = BarResponse.newBuilder().build();
+
+    EasyMock.expect(mockChannel.callBlockingMethod(
+      EasyMock.same(fooDescriptor),
+      EasyMock.same(mockController),
+      EasyMock.same(fooRequest),
+      EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
+    EasyMock.expect(mockChannel.callBlockingMethod(
+      EasyMock.same(barDescriptor),
+      EasyMock.same(mockController),
+      EasyMock.same(barRequest),
+      EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+    control.replay();
+
+    assertSame(fooResponse, stub.foo(mockController, fooRequest));
+    assertSame(barResponse, stub.bar(mockController, barRequest));
+    control.verify();
+  }
+
+  public void testNewReflectiveService() {
+    ServiceWithNoOuter.Interface impl =
+        control.createMock(ServiceWithNoOuter.Interface.class);
+    RpcController controller = control.createMock(RpcController.class);
+    Service service = ServiceWithNoOuter.newReflectiveService(impl);
+
+    MethodDescriptor fooMethod =
+        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+    MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+    RpcCallback<Message> callback =
+        new RpcCallback<Message>() {
+          @Override
+          public void run(Message parameter) {
+            // No reason this should be run.
+            fail();
+          }
+        };
+    RpcCallback<TestAllTypes> specializedCallback =
+        RpcUtil.specializeCallback(callback);
+
+    impl.foo(EasyMock.same(controller), EasyMock.same(request),
+        EasyMock.same(specializedCallback));
+    EasyMock.expectLastCall();
+
+    control.replay();
+
+    service.callMethod(fooMethod, controller, request, callback);
+
+    control.verify();
+  }
+
+  public void testNewReflectiveBlockingService() throws ServiceException {
+    ServiceWithNoOuter.BlockingInterface impl =
+        control.createMock(ServiceWithNoOuter.BlockingInterface.class);
+    RpcController controller = control.createMock(RpcController.class);
+    BlockingService service =
+        ServiceWithNoOuter.newReflectiveBlockingService(impl);
+
+    MethodDescriptor fooMethod =
+        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+    MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+
+    TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
+    EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
+        .andReturn(expectedResponse);
+
+    control.replay();
+
+    Message response =
+        service.callBlockingMethod(fooMethod, controller, request);
+    assertEquals(expectedResponse, response);
+
+    control.verify();
+  }
+
+  public void testNoGenericServices() throws Exception {
+    // Non-services should be usable.
+    UnittestNoGenericServices.TestMessage message =
+      UnittestNoGenericServices.TestMessage.newBuilder()
+        .setA(123)
+        .setExtension(UnittestNoGenericServices.testExtension, 456)
+        .build();
+    assertEquals(123, message.getA());
+    assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+    // Build a list of the class names nested in UnittestNoGenericServices.
+    String outerName = "google.protobuf.no_generic_services_test." +
+                       "UnittestNoGenericServices";
+    Class<?> outerClass = Class.forName(outerName);
+
+    Set<String> innerClassNames = new HashSet<String>();
+    for (Class<?> innerClass : outerClass.getClasses()) {
+      String fullName = innerClass.getName();
+      // Figure out the unqualified name of the inner class.
+      // Note:  Surprisingly, the full name of an inner class will be separated
+      //   from the outer class name by a '$' rather than a '.'.  This is not
+      //   mentioned in the documentation for java.lang.Class.  I don't want to
+      //   make assumptions, so I'm just going to accept any character as the
+      //   separator.
+      assertTrue(fullName.startsWith(outerName));
+
+      if (!Service.class.isAssignableFrom(innerClass) &&
+          !Message.class.isAssignableFrom(innerClass) &&
+          !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+        // Ignore any classes not generated by the base code generator.
+        continue;
+      }
+
+      innerClassNames.add(fullName.substring(outerName.length() + 1));
+    }
+
+    // No service class should have been generated.
+    assertTrue(innerClassNames.contains("TestMessage"));
+    assertTrue(innerClassNames.contains("TestEnum"));
+    assertFalse(innerClassNames.contains("TestService"));
+
+    // But descriptors are there.
+    FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+    assertEquals(1, file.getServices().size());
+    assertEquals("TestService", file.getServices().get(0).getName());
+    assertEquals(1, file.getServices().get(0).getMethods().size());
+    assertEquals("Foo",
+        file.getServices().get(0).getMethods().get(0).getName());
+  }
+
+  // =================================================================
+
+  /**
+   * wrapsCallback() is an EasyMock argument predicate.  wrapsCallback(c)
+   * matches a callback if calling that callback causes c to be called.
+   * In other words, c wraps the given callback.
+   */
+  private <Type extends Message> RpcCallback<Type> wrapsCallback(
+      MockCallback<?> callback) {
+    EasyMock.reportMatcher(new WrapsCallback(callback));
+    return null;
+  }
+
+  /** The parameter to wrapsCallback() must be a MockCallback. */
+  private static class MockCallback<Type extends Message>
+      implements RpcCallback<Type> {
+    private boolean called = false;
+
+    public boolean isCalled() { return called; }
+
+    public void reset() { called = false; }
+    @Override
+    public void run(Type message) {
+      called = true; }
+  }
+
+  /** Implementation of the wrapsCallback() argument matcher. */
+  private static class WrapsCallback implements IArgumentMatcher {
+    private MockCallback<?> callback;
+
+    public WrapsCallback(MockCallback<?> callback) {
+      this.callback = callback;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean matches(Object actual) {
+      if (!(actual instanceof RpcCallback)) {
+        return false;
+      }
+      RpcCallback actualCallback = (RpcCallback)actual;
+
+      callback.reset();
+      actualCallback.run(null);
+      return callback.isCalled();
+    }
+
+    @Override
+    public void appendTo(StringBuffer buffer) {
+      buffer.append("wrapsCallback(mockCallback)");
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
new file mode 100644
index 0000000..58b8000
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
@@ -0,0 +1,155 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilderTest extends TestCase {
+
+  public void testBasicUseAndInvalidations() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    assertEquals(TestAllTypes.getDefaultInstance(),
+        builder.getBuilder().buildPartial());
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    builder.getBuilder().setOptionalInt32(10);
+    assertEquals(0, mockParent.getInvalidationCount());
+    TestAllTypes message = builder.build();
+    assertEquals(10, message.getOptionalInt32());
+
+    // Test that we receive invalidations now that build has been called.
+    assertEquals(0, mockParent.getInvalidationCount());
+    builder.getBuilder().setOptionalInt32(20);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    // Test that we don't keep getting invalidations on every change
+    builder.getBuilder().setOptionalInt32(30);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+  }
+
+  public void testSetMessage() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertEquals(0, builder.getMessage().getOptionalInt32());
+
+    // Update message using the builder
+    builder.getBuilder().setOptionalInt32(1);
+    assertEquals(0, mockParent.getInvalidationCount());
+    assertEquals(1, builder.getBuilder().getOptionalInt32());
+    assertEquals(1, builder.getMessage().getOptionalInt32());
+    builder.build();
+    builder.getBuilder().setOptionalInt32(2);
+    assertEquals(2, builder.getBuilder().getOptionalInt32());
+    assertEquals(2, builder.getMessage().getOptionalInt32());
+
+    // Make sure message stays cached
+    assertSame(builder.getMessage(), builder.getMessage());
+  }
+
+  public void testClear() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    builder.clear();
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+    builder.getBuilder().setOptionalInt32(1);
+    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    builder.clear();
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+  }
+
+  public void testMerge() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+
+    // Merge into default field.
+    builder.mergeFrom(TestAllTypes.getDefaultInstance());
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+    // Merge into non-default field on existing builder.
+    builder.getBuilder().setOptionalInt32(2);
+    builder.mergeFrom(TestAllTypes.newBuilder()
+        .setOptionalDouble(4.0)
+        .buildPartial());
+    assertEquals(2, builder.getMessage().getOptionalInt32());
+    assertEquals(4.0, builder.getMessage().getOptionalDouble());
+
+    // Merge into non-default field on existing message
+    builder.setMessage(TestAllTypes.newBuilder()
+        .setOptionalInt32(10)
+        .buildPartial());
+    builder.mergeFrom(TestAllTypes.newBuilder()
+        .setOptionalDouble(5.0)
+        .buildPartial());
+    assertEquals(10, builder.getMessage().getOptionalInt32());
+    assertEquals(5.0, builder.getMessage().getOptionalDouble());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
new file mode 100644
index 0000000..e96ecd6
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
@@ -0,0 +1,423 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author darick@google.com Darick Tong
+ */
+public class SmallSortedMapTest extends TestCase {
+  // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
+  // here for JDK 1.5 users.
+  private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
+    private final K key;
+    private V value;
+
+    SimpleEntry(K key, V value) {
+      this.key = key;
+      this.value = value;
+    }
+
+    @Override
+    public K getKey() {
+      return key;
+    }
+
+    @Override
+    public V getValue() {
+      return value;
+    }
+
+    @Override
+    public V setValue(V value) {
+      V oldValue = this.value;
+      this.value = value;
+      return oldValue;
+    }
+
+    private static boolean eq(Object o1, Object o2) {
+      return o1 == null ? o2 == null : o1.equals(o2);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (!(o instanceof Map.Entry))
+        return false;
+      Map.Entry e = (Map.Entry) o;
+      return eq(key, e.getKey()) && eq(value, e.getValue());
+    }
+
+    @Override
+    public int hashCode() {
+      return ((key == null) ? 0 : key.hashCode()) ^
+          ((value == null) ? 0 : value.hashCode());
+    }
+  }
+
+  public void testPutAndGetArrayEntriesOnly() {
+    runPutAndGetTest(3);
+  }
+
+  public void testPutAndGetOverflowEntries() {
+    runPutAndGetTest(6);
+  }
+
+  private void runPutAndGetTest(int numElements) {
+    // Test with even and odd arraySize
+    SmallSortedMap<Integer, Integer> map1 =
+        SmallSortedMap.newInstanceForTest(3);
+    SmallSortedMap<Integer, Integer> map2 =
+        SmallSortedMap.newInstanceForTest(4);
+    SmallSortedMap<Integer, Integer> map3 =
+        SmallSortedMap.newInstanceForTest(3);
+    SmallSortedMap<Integer, Integer> map4 =
+        SmallSortedMap.newInstanceForTest(4);
+
+    // Test with puts in ascending order.
+    for (int i = 0; i < numElements; i++) {
+      assertNull(map1.put(i, i + 1));
+      assertNull(map2.put(i, i + 1));
+    }
+    // Test with puts in descending order.
+    for (int i = numElements - 1; i >= 0; i--) {
+      assertNull(map3.put(i, i + 1));
+      assertNull(map4.put(i, i + 1));
+    }
+
+    assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
+    assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
+    assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
+    assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
+
+    List<SmallSortedMap<Integer, Integer>> allMaps =
+        new ArrayList<SmallSortedMap<Integer, Integer>>();
+    allMaps.add(map1);
+    allMaps.add(map2);
+    allMaps.add(map3);
+    allMaps.add(map4);
+
+    for (SmallSortedMap<Integer, Integer> map : allMaps) {
+      assertEquals(numElements, map.size());
+      for (int i = 0; i < numElements; i++) {
+        assertEquals(new Integer(i + 1), map.get(i));
+      }
+    }
+
+    assertEquals(map1, map2);
+    assertEquals(map2, map3);
+    assertEquals(map3, map4);
+  }
+
+  public void testReplacingPut() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+      assertNull(map.remove(i + 1));
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 1), map.put(i, i + 2));
+    }
+  }
+
+  public void testRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+      assertNull(map.remove(i + 1));
+    }
+
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(3, map.getNumOverflowEntries());
+    assertEquals(6,  map.size());
+    assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
+
+    assertEquals(new Integer(2), map.remove(1));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(2, map.getNumOverflowEntries());
+    assertEquals(5,  map.size());
+    assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
+
+    assertEquals(new Integer(5), map.remove(4));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(1, map.getNumOverflowEntries());
+    assertEquals(4,  map.size());
+    assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
+
+    assertEquals(new Integer(4), map.remove(3));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(3, map.size());
+    assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
+
+    assertNull(map.remove(3));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(3, map.size());
+
+    assertEquals(new Integer(1), map.remove(0));
+    assertEquals(2, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(2, map.size());
+  }
+
+  public void testClear() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.clear();
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testGetArrayEntryAndOverflowEntries() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    assertEquals(3, map.getNumArrayEntries());
+    for (int i = 0; i < 3; i++) {
+      Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    Iterator<Map.Entry<Integer, Integer>> it =
+        map.getOverflowEntries().iterator();
+    for (int i = 3; i < 6; i++) {
+      assertTrue(it.hasNext());
+      Map.Entry<Integer, Integer> entry = it.next();
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    assertFalse(it.hasNext());
+  }
+
+  public void testEntrySetContains() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(
+          entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
+      assertFalse(
+          entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
+    }
+  }
+
+  public void testEntrySetAdd() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry =
+          new SimpleEntry<Integer, Integer>(i, i + 1);
+      assertTrue(entrySet.add(entry));
+      assertFalse(entrySet.add(entry));
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 1), map.get(i));
+    }
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(3, map.getNumOverflowEntries());
+    assertEquals(6, map.size());
+  }
+
+  public void testEntrySetRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry =
+          new SimpleEntry<Integer, Integer>(i, i + 1);
+      assertTrue(entrySet.remove(entry));
+      assertFalse(entrySet.remove(entry));
+    }
+    assertTrue(map.isEmpty());
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testEntrySetClear() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.entrySet().clear();
+    assertTrue(map.isEmpty());
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testEntrySetIteratorNext() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(it.hasNext());
+      Map.Entry<Integer, Integer> entry = it.next();
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    assertFalse(it.hasNext());
+  }
+
+  public void testEntrySetIteratorRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(map.containsKey(i));
+      it.next();
+      it.remove();
+      assertFalse(map.containsKey(i));
+      assertEquals(6 - i - 1, map.size());
+    }
+  }
+
+  public void testMapEntryModification() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry = it.next();
+      entry.setValue(i + 23);
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 23), map.get(i));
+    }
+  }
+
+  public void testMakeImmutable() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.makeImmutable();
+    assertEquals(new Integer(1), map.get(0));
+    assertEquals(6, map.size());
+
+    try {
+      map.put(23, 23);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Map<Integer, Integer> other = new HashMap<Integer, Integer>();
+    other.put(23, 23);
+    try {
+      map.putAll(other);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      map.remove(0);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      map.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    try {
+      entrySet.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
+    while (it.hasNext()) {
+      Map.Entry<Integer, Integer> entry = it.next();
+      try {
+        entry.setValue(0);
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+      try {
+        it.remove();
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+
+    Set<Integer> keySet = map.keySet();
+    try {
+      keySet.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Iterator<Integer> keys = keySet.iterator();
+    while (keys.hasNext()) {
+      Integer key = keys.next();
+      try {
+        keySet.remove(key);
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+      try {
+        keys.remove();
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+  }
+
+  private Set<Integer> makeSortedKeySet(Integer... keys) {
+    return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
new file mode 100644
index 0000000..2c60fe0
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -0,0 +1,96 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when
+ * compiling protocol buffers that have names that would otherwise conflict
+ * if not fully qualified (like @Deprecated and @Override).
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class TestBadIdentifiers extends TestCase {
+
+  public void testCompilation() {
+    // If this compiles, it means the generation was correct.
+    TestBadIdentifiersProto.Deprecated.newBuilder();
+    TestBadIdentifiersProto.Override.newBuilder();
+  }
+
+  public void testGetDescriptor() {
+    Descriptors.FileDescriptor fileDescriptor =
+        TestBadIdentifiersProto.getDescriptor();
+    String descriptorField = TestBadIdentifiersProto.Descriptor
+        .getDefaultInstance().getDescriptor();
+    Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+        .getDefaultInstance().getDescriptorForType();
+    String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+        .NestedDescriptor.getDefaultInstance().getDescriptor();
+    Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+        .Descriptor.NestedDescriptor.getDefaultInstance()
+        .getDescriptorForType();
+  }
+
+  public void testConflictingFieldNames() throws Exception {
+    TestBadIdentifiersProto.TestConflictingFieldNames message =
+        TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance();
+    // Make sure generated accessors are properly named.
+    assertEquals(0, message.getInt32Field1Count());
+    assertEquals(0, message.getEnumField2Count());
+    assertEquals(0, message.getStringField3Count());
+    assertEquals(0, message.getBytesField4Count());
+    assertEquals(0, message.getMessageField5Count());
+
+    assertEquals(0, message.getInt32FieldCount11());
+    assertEquals(0, message.getEnumFieldCount12().getNumber());
+    assertEquals("", message.getStringFieldCount13());
+    assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
+    assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
+
+    assertEquals(0, message.getInt32Field21Count());
+    assertEquals(0, message.getEnumField22Count());
+    assertEquals(0, message.getStringField23Count());
+    assertEquals(0, message.getBytesField24Count());
+    assertEquals(0, message.getMessageField25Count());
+
+    assertEquals(0, message.getInt32Field1List().size());
+    assertEquals(0, message.getInt32FieldList31());
+
+    assertEquals(0, message.getInt64FieldCount());
+    assertEquals(0L, message.getExtension(
+        TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue());
+    assertEquals(0L, message.getExtension(
+        TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
+
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtil.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtil.java
new file mode 100644
index 0000000..08b2a76
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -0,0 +1,3857 @@
+// 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.
+
+package com.google.protobuf;
+
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
+import static protobuf_unittest.UnittestProto.defaultBoolExtension;
+import static protobuf_unittest.UnittestProto.defaultBytesExtension;
+import static protobuf_unittest.UnittestProto.defaultCordExtension;
+import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
+import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultFloatExtension;
+import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
+// The static imports are to avoid 100+ char lines.  The following is roughly equivalent to
+// import static protobuf_unittest.UnittestProto.*;
+import static protobuf_unittest.UnittestProto.defaultInt32Extension;
+import static protobuf_unittest.UnittestProto.defaultInt64Extension;
+import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultSint32Extension;
+import static protobuf_unittest.UnittestProto.defaultSint64Extension;
+import static protobuf_unittest.UnittestProto.defaultStringExtension;
+import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
+import static protobuf_unittest.UnittestProto.defaultUint32Extension;
+import static protobuf_unittest.UnittestProto.defaultUint64Extension;
+import static protobuf_unittest.UnittestProto.oneofBytesExtension;
+import static protobuf_unittest.UnittestProto.oneofNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.oneofStringExtension;
+import static protobuf_unittest.UnittestProto.oneofUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalBoolExtension;
+import static protobuf_unittest.UnittestProto.optionalBytesExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
+import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalFloatExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalGroupExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalSint32Extension;
+import static protobuf_unittest.UnittestProto.optionalSint64Extension;
+import static protobuf_unittest.UnittestProto.optionalStringExtension;
+import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
+import static protobuf_unittest.UnittestProto.optionalUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalUint64Extension;
+import static protobuf_unittest.UnittestProto.packedBoolExtension;
+import static protobuf_unittest.UnittestProto.packedDoubleExtension;
+import static protobuf_unittest.UnittestProto.packedEnumExtension;
+import static protobuf_unittest.UnittestProto.packedFixed32Extension;
+import static protobuf_unittest.UnittestProto.packedFixed64Extension;
+import static protobuf_unittest.UnittestProto.packedFloatExtension;
+import static protobuf_unittest.UnittestProto.packedInt32Extension;
+import static protobuf_unittest.UnittestProto.packedInt64Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.packedSint32Extension;
+import static protobuf_unittest.UnittestProto.packedSint64Extension;
+import static protobuf_unittest.UnittestProto.packedUint32Extension;
+import static protobuf_unittest.UnittestProto.packedUint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
+import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
+import static protobuf_unittest.UnittestProto.repeatedCordExtension;
+import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
+import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
+import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedStringExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
+import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Contains methods for setting all fields of {@code TestAllTypes} to
+ * some values as well as checking that all the fields are set to those values.
+ * These are useful for testing various protocol message features, e.g.
+ * set all fields of a message, serialize it, parse it, and check that all
+ * fields are set.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TestUtil {
+  private TestUtil() {}
+
+  /** Helper to convert a String to ByteString. */
+  static ByteString toBytes(String str) {
+    return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+  }
+
+  /**
+   * Get a {@code TestAllTypes} with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypes.Builder)}.
+   */
+  public static TestAllTypes getAllSet() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    setAllFields(builder);
+    return builder.build();
+  }
+
+  /**
+   * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypes.Builder)}.
+   */
+  public static TestAllTypes.Builder getAllSetBuilder() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    setAllFields(builder);
+    return builder;
+  }
+
+  /**
+   * Get a {@code TestAllExtensions} with all fields set as they would be by
+   * {@link #setAllExtensions(TestAllExtensions.Builder)}.
+   */
+  public static TestAllExtensions getAllExtensionsSet() {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    setAllExtensions(builder);
+    return builder.build();
+  }
+
+  public static TestPackedTypes getPackedSet() {
+    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+    setPackedFields(builder);
+    return builder.build();
+  }
+
+  public static TestUnpackedTypes getUnpackedSet() {
+    TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+    setUnpackedFields(builder);
+    return builder.build();
+  }
+
+  public static TestPackedExtensions getPackedExtensionsSet() {
+    TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
+    setPackedExtensions(builder);
+    return builder.build();
+  }
+
+  /**
+   * Set every field of {@code message} to the values expected by
+   * {@code assertAllFieldsSet()}.
+   */
+  public static void setAllFields(TestAllTypes.Builder message) {
+    message.setOptionalInt32   (101);
+    message.setOptionalInt64   (102);
+    message.setOptionalUint32  (103);
+    message.setOptionalUint64  (104);
+    message.setOptionalSint32  (105);
+    message.setOptionalSint64  (106);
+    message.setOptionalFixed32 (107);
+    message.setOptionalFixed64 (108);
+    message.setOptionalSfixed32(109);
+    message.setOptionalSfixed64(110);
+    message.setOptionalFloat   (111);
+    message.setOptionalDouble  (112);
+    message.setOptionalBool    (true);
+    message.setOptionalString  ("115");
+    message.setOptionalBytes   (toBytes("116"));
+
+    message.setOptionalGroup(
+      TestAllTypes.OptionalGroup.newBuilder().setA(117).build());
+    message.setOptionalNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+    message.setOptionalForeignMessage(
+      ForeignMessage.newBuilder().setC(119).build());
+    message.setOptionalImportMessage(
+      ImportMessage.newBuilder().setD(120).build());
+    message.setOptionalPublicImportMessage(
+      PublicImportMessage.newBuilder().setE(126).build());
+    message.setOptionalLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+    message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
+    message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
+    message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
+
+    message.setOptionalStringPiece("124");
+    message.setOptionalCord("125");
+
+    // -----------------------------------------------------------------
+
+    message.addRepeatedInt32   (201);
+    message.addRepeatedInt64   (202);
+    message.addRepeatedUint32  (203);
+    message.addRepeatedUint64  (204);
+    message.addRepeatedSint32  (205);
+    message.addRepeatedSint64  (206);
+    message.addRepeatedFixed32 (207);
+    message.addRepeatedFixed64 (208);
+    message.addRepeatedSfixed32(209);
+    message.addRepeatedSfixed64(210);
+    message.addRepeatedFloat   (211);
+    message.addRepeatedDouble  (212);
+    message.addRepeatedBool    (true);
+    message.addRepeatedString  ("215");
+    message.addRepeatedBytes   (toBytes("216"));
+
+    message.addRepeatedGroup(
+      TestAllTypes.RepeatedGroup.newBuilder().setA(217).build());
+    message.addRepeatedNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+    message.addRepeatedForeignMessage(
+      ForeignMessage.newBuilder().setC(219).build());
+    message.addRepeatedImportMessage(
+      ImportMessage.newBuilder().setD(220).build());
+    message.addRepeatedLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+    message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
+    message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
+    message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR);
+
+    message.addRepeatedStringPiece("224");
+    message.addRepeatedCord("225");
+
+    // Add a second one of each field.
+    message.addRepeatedInt32   (301);
+    message.addRepeatedInt64   (302);
+    message.addRepeatedUint32  (303);
+    message.addRepeatedUint64  (304);
+    message.addRepeatedSint32  (305);
+    message.addRepeatedSint64  (306);
+    message.addRepeatedFixed32 (307);
+    message.addRepeatedFixed64 (308);
+    message.addRepeatedSfixed32(309);
+    message.addRepeatedSfixed64(310);
+    message.addRepeatedFloat   (311);
+    message.addRepeatedDouble  (312);
+    message.addRepeatedBool    (false);
+    message.addRepeatedString  ("315");
+    message.addRepeatedBytes   (toBytes("316"));
+
+    message.addRepeatedGroup(
+      TestAllTypes.RepeatedGroup.newBuilder().setA(317).build());
+    message.addRepeatedNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+    message.addRepeatedForeignMessage(
+      ForeignMessage.newBuilder().setC(319).build());
+    message.addRepeatedImportMessage(
+      ImportMessage.newBuilder().setD(320).build());
+    message.addRepeatedLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+    message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
+    message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
+    message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ);
+
+    message.addRepeatedStringPiece("324");
+    message.addRepeatedCord("325");
+
+    // -----------------------------------------------------------------
+
+    message.setDefaultInt32   (401);
+    message.setDefaultInt64   (402);
+    message.setDefaultUint32  (403);
+    message.setDefaultUint64  (404);
+    message.setDefaultSint32  (405);
+    message.setDefaultSint64  (406);
+    message.setDefaultFixed32 (407);
+    message.setDefaultFixed64 (408);
+    message.setDefaultSfixed32(409);
+    message.setDefaultSfixed64(410);
+    message.setDefaultFloat   (411);
+    message.setDefaultDouble  (412);
+    message.setDefaultBool    (false);
+    message.setDefaultString  ("415");
+    message.setDefaultBytes   (toBytes("416"));
+
+    message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
+    message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
+    message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
+
+    message.setDefaultStringPiece("424");
+    message.setDefaultCord("425");
+
+    message.setOneofUint32(601);
+    message.setOneofNestedMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+    message.setOneofString("603");
+    message.setOneofBytes(toBytes("604"));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Modify the repeated fields of {@code message} to contain the values
+   * expected by {@code assertRepeatedFieldsModified()}.
+   */
+  public static void modifyRepeatedFields(TestAllTypes.Builder message) {
+    message.setRepeatedInt32   (1, 501);
+    message.setRepeatedInt64   (1, 502);
+    message.setRepeatedUint32  (1, 503);
+    message.setRepeatedUint64  (1, 504);
+    message.setRepeatedSint32  (1, 505);
+    message.setRepeatedSint64  (1, 506);
+    message.setRepeatedFixed32 (1, 507);
+    message.setRepeatedFixed64 (1, 508);
+    message.setRepeatedSfixed32(1, 509);
+    message.setRepeatedSfixed64(1, 510);
+    message.setRepeatedFloat   (1, 511);
+    message.setRepeatedDouble  (1, 512);
+    message.setRepeatedBool    (1, true);
+    message.setRepeatedString  (1, "515");
+    message.setRepeatedBytes   (1, toBytes("516"));
+
+    message.setRepeatedGroup(1,
+      TestAllTypes.RepeatedGroup.newBuilder().setA(517).build());
+    message.setRepeatedNestedMessage(1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+    message.setRepeatedForeignMessage(1,
+      ForeignMessage.newBuilder().setC(519).build());
+    message.setRepeatedImportMessage(1,
+      ImportMessage.newBuilder().setD(520).build());
+    message.setRepeatedLazyMessage(1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+    message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
+    message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
+    message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO);
+
+    message.setRepeatedStringPiece(1, "524");
+    message.setRepeatedCord(1, "525");
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are set to the values assigned by {@code setAllFields}.
+   */
+  public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
+    Assert.assertTrue(message.hasOptionalInt32   ());
+    Assert.assertTrue(message.hasOptionalInt64   ());
+    Assert.assertTrue(message.hasOptionalUint32  ());
+    Assert.assertTrue(message.hasOptionalUint64  ());
+    Assert.assertTrue(message.hasOptionalSint32  ());
+    Assert.assertTrue(message.hasOptionalSint64  ());
+    Assert.assertTrue(message.hasOptionalFixed32 ());
+    Assert.assertTrue(message.hasOptionalFixed64 ());
+    Assert.assertTrue(message.hasOptionalSfixed32());
+    Assert.assertTrue(message.hasOptionalSfixed64());
+    Assert.assertTrue(message.hasOptionalFloat   ());
+    Assert.assertTrue(message.hasOptionalDouble  ());
+    Assert.assertTrue(message.hasOptionalBool    ());
+    Assert.assertTrue(message.hasOptionalString  ());
+    Assert.assertTrue(message.hasOptionalBytes   ());
+
+    Assert.assertTrue(message.hasOptionalGroup         ());
+    Assert.assertTrue(message.hasOptionalNestedMessage ());
+    Assert.assertTrue(message.hasOptionalForeignMessage());
+    Assert.assertTrue(message.hasOptionalImportMessage ());
+
+    Assert.assertTrue(message.getOptionalGroup         ().hasA());
+    Assert.assertTrue(message.getOptionalNestedMessage ().hasBb());
+    Assert.assertTrue(message.getOptionalForeignMessage().hasC());
+    Assert.assertTrue(message.getOptionalImportMessage ().hasD());
+
+    Assert.assertTrue(message.hasOptionalNestedEnum ());
+    Assert.assertTrue(message.hasOptionalForeignEnum());
+    Assert.assertTrue(message.hasOptionalImportEnum ());
+
+    Assert.assertTrue(message.hasOptionalStringPiece());
+    Assert.assertTrue(message.hasOptionalCord());
+
+    Assert.assertEquals(101  , message.getOptionalInt32   ());
+    Assert.assertEquals(102  , message.getOptionalInt64   ());
+    Assert.assertEquals(103  , message.getOptionalUint32  ());
+    Assert.assertEquals(104  , message.getOptionalUint64  ());
+    Assert.assertEquals(105  , message.getOptionalSint32  ());
+    Assert.assertEquals(106  , message.getOptionalSint64  ());
+    Assert.assertEquals(107  , message.getOptionalFixed32 ());
+    Assert.assertEquals(108  , message.getOptionalFixed64 ());
+    Assert.assertEquals(109  , message.getOptionalSfixed32());
+    Assert.assertEquals(110  , message.getOptionalSfixed64());
+    Assert.assertEquals(111  , message.getOptionalFloat   (), 0.0);
+    Assert.assertEquals(112  , message.getOptionalDouble  (), 0.0);
+    Assert.assertEquals(true , message.getOptionalBool    ());
+    Assert.assertEquals("115", message.getOptionalString  ());
+    Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
+
+    Assert.assertEquals(117, message.getOptionalGroup              ().getA());
+    Assert.assertEquals(118, message.getOptionalNestedMessage      ().getBb());
+    Assert.assertEquals(119, message.getOptionalForeignMessage     ().getC());
+    Assert.assertEquals(120, message.getOptionalImportMessage      ().getD());
+    Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+    Assert.assertEquals(127, message.getOptionalLazyMessage        ().getBb());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
+    Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
+
+    Assert.assertEquals("124", message.getOptionalStringPiece());
+    Assert.assertEquals("125", message.getOptionalCord());
+
+    // -----------------------------------------------------------------
+
+    Assert.assertEquals(2, message.getRepeatedInt32Count   ());
+    Assert.assertEquals(2, message.getRepeatedInt64Count   ());
+    Assert.assertEquals(2, message.getRepeatedUint32Count  ());
+    Assert.assertEquals(2, message.getRepeatedUint64Count  ());
+    Assert.assertEquals(2, message.getRepeatedSint32Count  ());
+    Assert.assertEquals(2, message.getRepeatedSint64Count  ());
+    Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+    Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+    Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+    Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+    Assert.assertEquals(2, message.getRepeatedFloatCount   ());
+    Assert.assertEquals(2, message.getRepeatedDoubleCount  ());
+    Assert.assertEquals(2, message.getRepeatedBoolCount    ());
+    Assert.assertEquals(2, message.getRepeatedStringCount  ());
+    Assert.assertEquals(2, message.getRepeatedBytesCount   ());
+
+    Assert.assertEquals(2, message.getRepeatedGroupCount         ());
+    Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+    Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
+    Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
+    Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
+    Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
+
+    Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+    Assert.assertEquals(2, message.getRepeatedCordCount());
+
+    Assert.assertEquals(201  , message.getRepeatedInt32   (0));
+    Assert.assertEquals(202  , message.getRepeatedInt64   (0));
+    Assert.assertEquals(203  , message.getRepeatedUint32  (0));
+    Assert.assertEquals(204  , message.getRepeatedUint64  (0));
+    Assert.assertEquals(205  , message.getRepeatedSint32  (0));
+    Assert.assertEquals(206  , message.getRepeatedSint64  (0));
+    Assert.assertEquals(207  , message.getRepeatedFixed32 (0));
+    Assert.assertEquals(208  , message.getRepeatedFixed64 (0));
+    Assert.assertEquals(209  , message.getRepeatedSfixed32(0));
+    Assert.assertEquals(210  , message.getRepeatedSfixed64(0));
+    Assert.assertEquals(211  , message.getRepeatedFloat   (0), 0.0);
+    Assert.assertEquals(212  , message.getRepeatedDouble  (0), 0.0);
+    Assert.assertEquals(true , message.getRepeatedBool    (0));
+    Assert.assertEquals("215", message.getRepeatedString  (0));
+    Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+    Assert.assertEquals(217, message.getRepeatedGroup         (0).getA());
+    Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+    Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+    Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+    Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+    Assert.assertEquals("225", message.getRepeatedCord(0));
+
+    Assert.assertEquals(301  , message.getRepeatedInt32   (1));
+    Assert.assertEquals(302  , message.getRepeatedInt64   (1));
+    Assert.assertEquals(303  , message.getRepeatedUint32  (1));
+    Assert.assertEquals(304  , message.getRepeatedUint64  (1));
+    Assert.assertEquals(305  , message.getRepeatedSint32  (1));
+    Assert.assertEquals(306  , message.getRepeatedSint64  (1));
+    Assert.assertEquals(307  , message.getRepeatedFixed32 (1));
+    Assert.assertEquals(308  , message.getRepeatedFixed64 (1));
+    Assert.assertEquals(309  , message.getRepeatedSfixed32(1));
+    Assert.assertEquals(310  , message.getRepeatedSfixed64(1));
+    Assert.assertEquals(311  , message.getRepeatedFloat   (1), 0.0);
+    Assert.assertEquals(312  , message.getRepeatedDouble  (1), 0.0);
+    Assert.assertEquals(false, message.getRepeatedBool    (1));
+    Assert.assertEquals("315", message.getRepeatedString  (1));
+    Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1));
+
+    Assert.assertEquals(317, message.getRepeatedGroup         (1).getA());
+    Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
+    Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
+    Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+    Assert.assertEquals(327, message.getRepeatedLazyMessage   (1).getBb());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
+    Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1));
+
+    Assert.assertEquals("324", message.getRepeatedStringPiece(1));
+    Assert.assertEquals("325", message.getRepeatedCord(1));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertTrue(message.hasDefaultInt32   ());
+    Assert.assertTrue(message.hasDefaultInt64   ());
+    Assert.assertTrue(message.hasDefaultUint32  ());
+    Assert.assertTrue(message.hasDefaultUint64  ());
+    Assert.assertTrue(message.hasDefaultSint32  ());
+    Assert.assertTrue(message.hasDefaultSint64  ());
+    Assert.assertTrue(message.hasDefaultFixed32 ());
+    Assert.assertTrue(message.hasDefaultFixed64 ());
+    Assert.assertTrue(message.hasDefaultSfixed32());
+    Assert.assertTrue(message.hasDefaultSfixed64());
+    Assert.assertTrue(message.hasDefaultFloat   ());
+    Assert.assertTrue(message.hasDefaultDouble  ());
+    Assert.assertTrue(message.hasDefaultBool    ());
+    Assert.assertTrue(message.hasDefaultString  ());
+    Assert.assertTrue(message.hasDefaultBytes   ());
+
+    Assert.assertTrue(message.hasDefaultNestedEnum ());
+    Assert.assertTrue(message.hasDefaultForeignEnum());
+    Assert.assertTrue(message.hasDefaultImportEnum ());
+
+    Assert.assertTrue(message.hasDefaultStringPiece());
+    Assert.assertTrue(message.hasDefaultCord());
+
+    Assert.assertEquals(401  , message.getDefaultInt32   ());
+    Assert.assertEquals(402  , message.getDefaultInt64   ());
+    Assert.assertEquals(403  , message.getDefaultUint32  ());
+    Assert.assertEquals(404  , message.getDefaultUint64  ());
+    Assert.assertEquals(405  , message.getDefaultSint32  ());
+    Assert.assertEquals(406  , message.getDefaultSint64  ());
+    Assert.assertEquals(407  , message.getDefaultFixed32 ());
+    Assert.assertEquals(408  , message.getDefaultFixed64 ());
+    Assert.assertEquals(409  , message.getDefaultSfixed32());
+    Assert.assertEquals(410  , message.getDefaultSfixed64());
+    Assert.assertEquals(411  , message.getDefaultFloat   (), 0.0);
+    Assert.assertEquals(412  , message.getDefaultDouble  (), 0.0);
+    Assert.assertEquals(false, message.getDefaultBool    ());
+    Assert.assertEquals("415", message.getDefaultString  ());
+    Assert.assertEquals(toBytes("416"), message.getDefaultBytes());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
+    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
+    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
+
+    Assert.assertEquals("424", message.getDefaultStringPiece());
+    Assert.assertEquals("425", message.getDefaultCord());
+
+    Assert.assertEquals(TestAllTypes.OneofFieldCase.ONEOF_BYTES, message.getOneofFieldCase());
+    Assert.assertFalse(message.hasOneofUint32());
+    Assert.assertFalse(message.hasOneofNestedMessage());
+    Assert.assertFalse(message.hasOneofString());
+    Assert.assertTrue(message.hasOneofBytes());
+
+    Assert.assertEquals(toBytes("604"), message.getOneofBytes());
+  }
+
+  // -------------------------------------------------------------------
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are cleared, and that getting the fields returns their
+   * default values.
+   */
+  public static void assertClear(TestAllTypesOrBuilder message) {
+    // hasBlah() should initially be false for all optional fields.
+    Assert.assertFalse(message.hasOptionalInt32   ());
+    Assert.assertFalse(message.hasOptionalInt64   ());
+    Assert.assertFalse(message.hasOptionalUint32  ());
+    Assert.assertFalse(message.hasOptionalUint64  ());
+    Assert.assertFalse(message.hasOptionalSint32  ());
+    Assert.assertFalse(message.hasOptionalSint64  ());
+    Assert.assertFalse(message.hasOptionalFixed32 ());
+    Assert.assertFalse(message.hasOptionalFixed64 ());
+    Assert.assertFalse(message.hasOptionalSfixed32());
+    Assert.assertFalse(message.hasOptionalSfixed64());
+    Assert.assertFalse(message.hasOptionalFloat   ());
+    Assert.assertFalse(message.hasOptionalDouble  ());
+    Assert.assertFalse(message.hasOptionalBool    ());
+    Assert.assertFalse(message.hasOptionalString  ());
+    Assert.assertFalse(message.hasOptionalBytes   ());
+
+    Assert.assertFalse(message.hasOptionalGroup         ());
+    Assert.assertFalse(message.hasOptionalNestedMessage ());
+    Assert.assertFalse(message.hasOptionalForeignMessage());
+    Assert.assertFalse(message.hasOptionalImportMessage ());
+
+    Assert.assertFalse(message.hasOptionalNestedEnum ());
+    Assert.assertFalse(message.hasOptionalForeignEnum());
+    Assert.assertFalse(message.hasOptionalImportEnum ());
+
+    Assert.assertFalse(message.hasOptionalStringPiece());
+    Assert.assertFalse(message.hasOptionalCord());
+
+    // Optional fields without defaults are set to zero or something like it.
+    Assert.assertEquals(0    , message.getOptionalInt32   ());
+    Assert.assertEquals(0    , message.getOptionalInt64   ());
+    Assert.assertEquals(0    , message.getOptionalUint32  ());
+    Assert.assertEquals(0    , message.getOptionalUint64  ());
+    Assert.assertEquals(0    , message.getOptionalSint32  ());
+    Assert.assertEquals(0    , message.getOptionalSint64  ());
+    Assert.assertEquals(0    , message.getOptionalFixed32 ());
+    Assert.assertEquals(0    , message.getOptionalFixed64 ());
+    Assert.assertEquals(0    , message.getOptionalSfixed32());
+    Assert.assertEquals(0    , message.getOptionalSfixed64());
+    Assert.assertEquals(0    , message.getOptionalFloat   (), 0.0);
+    Assert.assertEquals(0    , message.getOptionalDouble  (), 0.0);
+    Assert.assertEquals(false, message.getOptionalBool    ());
+    Assert.assertEquals(""   , message.getOptionalString  ());
+    Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+
+    // Embedded messages should also be clear.
+    Assert.assertFalse(message.getOptionalGroup              ().hasA());
+    Assert.assertFalse(message.getOptionalNestedMessage      ().hasBb());
+    Assert.assertFalse(message.getOptionalForeignMessage     ().hasC());
+    Assert.assertFalse(message.getOptionalImportMessage      ().hasD());
+    Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+    Assert.assertFalse(message.getOptionalLazyMessage        ().hasBb());
+
+    Assert.assertEquals(0, message.getOptionalGroup              ().getA());
+    Assert.assertEquals(0, message.getOptionalNestedMessage      ().getBb());
+    Assert.assertEquals(0, message.getOptionalForeignMessage     ().getC());
+    Assert.assertEquals(0, message.getOptionalImportMessage      ().getD());
+    Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+    Assert.assertEquals(0, message.getOptionalLazyMessage        ().getBb());
+
+    // Enums without defaults are set to the first value in the enum.
+    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
+    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum());
+    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum());
+
+    Assert.assertEquals("", message.getOptionalStringPiece());
+    Assert.assertEquals("", message.getOptionalCord());
+
+    // Repeated fields are empty.
+    Assert.assertEquals(0, message.getRepeatedInt32Count   ());
+    Assert.assertEquals(0, message.getRepeatedInt64Count   ());
+    Assert.assertEquals(0, message.getRepeatedUint32Count  ());
+    Assert.assertEquals(0, message.getRepeatedUint64Count  ());
+    Assert.assertEquals(0, message.getRepeatedSint32Count  ());
+    Assert.assertEquals(0, message.getRepeatedSint64Count  ());
+    Assert.assertEquals(0, message.getRepeatedFixed32Count ());
+    Assert.assertEquals(0, message.getRepeatedFixed64Count ());
+    Assert.assertEquals(0, message.getRepeatedSfixed32Count());
+    Assert.assertEquals(0, message.getRepeatedSfixed64Count());
+    Assert.assertEquals(0, message.getRepeatedFloatCount   ());
+    Assert.assertEquals(0, message.getRepeatedDoubleCount  ());
+    Assert.assertEquals(0, message.getRepeatedBoolCount    ());
+    Assert.assertEquals(0, message.getRepeatedStringCount  ());
+    Assert.assertEquals(0, message.getRepeatedBytesCount   ());
+
+    Assert.assertEquals(0, message.getRepeatedGroupCount         ());
+    Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
+    Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
+    Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(0, message.getRepeatedLazyMessageCount   ());
+    Assert.assertEquals(0, message.getRepeatedNestedEnumCount    ());
+    Assert.assertEquals(0, message.getRepeatedForeignEnumCount   ());
+    Assert.assertEquals(0, message.getRepeatedImportEnumCount    ());
+
+    Assert.assertEquals(0, message.getRepeatedStringPieceCount());
+    Assert.assertEquals(0, message.getRepeatedCordCount());
+
+    // hasBlah() should also be false for all default fields.
+    Assert.assertFalse(message.hasDefaultInt32   ());
+    Assert.assertFalse(message.hasDefaultInt64   ());
+    Assert.assertFalse(message.hasDefaultUint32  ());
+    Assert.assertFalse(message.hasDefaultUint64  ());
+    Assert.assertFalse(message.hasDefaultSint32  ());
+    Assert.assertFalse(message.hasDefaultSint64  ());
+    Assert.assertFalse(message.hasDefaultFixed32 ());
+    Assert.assertFalse(message.hasDefaultFixed64 ());
+    Assert.assertFalse(message.hasDefaultSfixed32());
+    Assert.assertFalse(message.hasDefaultSfixed64());
+    Assert.assertFalse(message.hasDefaultFloat   ());
+    Assert.assertFalse(message.hasDefaultDouble  ());
+    Assert.assertFalse(message.hasDefaultBool    ());
+    Assert.assertFalse(message.hasDefaultString  ());
+    Assert.assertFalse(message.hasDefaultBytes   ());
+
+    Assert.assertFalse(message.hasDefaultNestedEnum ());
+    Assert.assertFalse(message.hasDefaultForeignEnum());
+    Assert.assertFalse(message.hasDefaultImportEnum ());
+
+    Assert.assertFalse(message.hasDefaultStringPiece());
+    Assert.assertFalse(message.hasDefaultCord());
+
+    // Fields with defaults have their default values (duh).
+    Assert.assertEquals( 41    , message.getDefaultInt32   ());
+    Assert.assertEquals( 42    , message.getDefaultInt64   ());
+    Assert.assertEquals( 43    , message.getDefaultUint32  ());
+    Assert.assertEquals( 44    , message.getDefaultUint64  ());
+    Assert.assertEquals(-45    , message.getDefaultSint32  ());
+    Assert.assertEquals( 46    , message.getDefaultSint64  ());
+    Assert.assertEquals( 47    , message.getDefaultFixed32 ());
+    Assert.assertEquals( 48    , message.getDefaultFixed64 ());
+    Assert.assertEquals( 49    , message.getDefaultSfixed32());
+    Assert.assertEquals(-50    , message.getDefaultSfixed64());
+    Assert.assertEquals( 51.5  , message.getDefaultFloat   (), 0.0);
+    Assert.assertEquals( 52e3  , message.getDefaultDouble  (), 0.0);
+    Assert.assertEquals(true   , message.getDefaultBool    ());
+    Assert.assertEquals("hello", message.getDefaultString  ());
+    Assert.assertEquals(toBytes("world"), message.getDefaultBytes());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
+    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
+
+    Assert.assertEquals("abc", message.getDefaultStringPiece());
+    Assert.assertEquals("123", message.getDefaultCord());
+
+    Assert.assertFalse(message.hasOneofUint32());
+    Assert.assertFalse(message.hasOneofNestedMessage());
+    Assert.assertFalse(message.hasOneofString());
+    Assert.assertFalse(message.hasOneofBytes());
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are set to the values assigned by {@code setAllFields}
+   * followed by {@code modifyRepeatedFields}.
+   */
+  public static void assertRepeatedFieldsModified(
+      TestAllTypesOrBuilder message) {
+    // ModifyRepeatedFields only sets the second repeated element of each
+    // field.  In addition to verifying this, we also verify that the first
+    // element and size were *not* modified.
+    Assert.assertEquals(2, message.getRepeatedInt32Count   ());
+    Assert.assertEquals(2, message.getRepeatedInt64Count   ());
+    Assert.assertEquals(2, message.getRepeatedUint32Count  ());
+    Assert.assertEquals(2, message.getRepeatedUint64Count  ());
+    Assert.assertEquals(2, message.getRepeatedSint32Count  ());
+    Assert.assertEquals(2, message.getRepeatedSint64Count  ());
+    Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+    Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+    Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+    Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+    Assert.assertEquals(2, message.getRepeatedFloatCount   ());
+    Assert.assertEquals(2, message.getRepeatedDoubleCount  ());
+    Assert.assertEquals(2, message.getRepeatedBoolCount    ());
+    Assert.assertEquals(2, message.getRepeatedStringCount  ());
+    Assert.assertEquals(2, message.getRepeatedBytesCount   ());
+
+    Assert.assertEquals(2, message.getRepeatedGroupCount         ());
+    Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+    Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
+    Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
+    Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
+    Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
+
+    Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+    Assert.assertEquals(2, message.getRepeatedCordCount());
+
+    Assert.assertEquals(201  , message.getRepeatedInt32   (0));
+    Assert.assertEquals(202L , message.getRepeatedInt64   (0));
+    Assert.assertEquals(203  , message.getRepeatedUint32  (0));
+    Assert.assertEquals(204L , message.getRepeatedUint64  (0));
+    Assert.assertEquals(205  , message.getRepeatedSint32  (0));
+    Assert.assertEquals(206L , message.getRepeatedSint64  (0));
+    Assert.assertEquals(207  , message.getRepeatedFixed32 (0));
+    Assert.assertEquals(208L , message.getRepeatedFixed64 (0));
+    Assert.assertEquals(209  , message.getRepeatedSfixed32(0));
+    Assert.assertEquals(210L , message.getRepeatedSfixed64(0));
+    Assert.assertEquals(211F , message.getRepeatedFloat   (0));
+    Assert.assertEquals(212D , message.getRepeatedDouble  (0));
+    Assert.assertEquals(true , message.getRepeatedBool    (0));
+    Assert.assertEquals("215", message.getRepeatedString  (0));
+    Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+    Assert.assertEquals(217, message.getRepeatedGroup         (0).getA());
+    Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+    Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+    Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+    Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+    Assert.assertEquals("225", message.getRepeatedCord(0));
+
+    // Actually verify the second (modified) elements now.
+    Assert.assertEquals(501  , message.getRepeatedInt32   (1));
+    Assert.assertEquals(502L , message.getRepeatedInt64   (1));
+    Assert.assertEquals(503  , message.getRepeatedUint32  (1));
+    Assert.assertEquals(504L , message.getRepeatedUint64  (1));
+    Assert.assertEquals(505  , message.getRepeatedSint32  (1));
+    Assert.assertEquals(506L , message.getRepeatedSint64  (1));
+    Assert.assertEquals(507  , message.getRepeatedFixed32 (1));
+    Assert.assertEquals(508L , message.getRepeatedFixed64 (1));
+    Assert.assertEquals(509  , message.getRepeatedSfixed32(1));
+    Assert.assertEquals(510L , message.getRepeatedSfixed64(1));
+    Assert.assertEquals(511F , message.getRepeatedFloat   (1));
+    Assert.assertEquals(512D , message.getRepeatedDouble  (1));
+    Assert.assertEquals(true , message.getRepeatedBool    (1));
+    Assert.assertEquals("515", message.getRepeatedString  (1));
+    Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1));
+
+    Assert.assertEquals(517, message.getRepeatedGroup         (1).getA());
+    Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
+    Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
+    Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+    Assert.assertEquals(527, message.getRepeatedLazyMessage   (1).getBb());
+
+    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
+    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
+    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1));
+
+    Assert.assertEquals("524", message.getRepeatedStringPiece(1));
+    Assert.assertEquals("525", message.getRepeatedCord(1));
+  }
+
+  /**
+   * Set every field of {@code message} to a unique value.
+   */
+  public static void setPackedFields(TestPackedTypes.Builder message) {
+    message.addPackedInt32   (601);
+    message.addPackedInt64   (602);
+    message.addPackedUint32  (603);
+    message.addPackedUint64  (604);
+    message.addPackedSint32  (605);
+    message.addPackedSint64  (606);
+    message.addPackedFixed32 (607);
+    message.addPackedFixed64 (608);
+    message.addPackedSfixed32(609);
+    message.addPackedSfixed64(610);
+    message.addPackedFloat   (611);
+    message.addPackedDouble  (612);
+    message.addPackedBool    (true);
+    message.addPackedEnum    (ForeignEnum.FOREIGN_BAR);
+    // Add a second one of each field.
+    message.addPackedInt32   (701);
+    message.addPackedInt64   (702);
+    message.addPackedUint32  (703);
+    message.addPackedUint64  (704);
+    message.addPackedSint32  (705);
+    message.addPackedSint64  (706);
+    message.addPackedFixed32 (707);
+    message.addPackedFixed64 (708);
+    message.addPackedSfixed32(709);
+    message.addPackedSfixed64(710);
+    message.addPackedFloat   (711);
+    message.addPackedDouble  (712);
+    message.addPackedBool    (false);
+    message.addPackedEnum    (ForeignEnum.FOREIGN_BAZ);
+  }
+
+  /**
+   * Set every field of {@code message} to a unique value. Must correspond with
+   * the values applied by {@code setPackedFields}.
+   */
+  public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+    message.addUnpackedInt32   (601);
+    message.addUnpackedInt64   (602);
+    message.addUnpackedUint32  (603);
+    message.addUnpackedUint64  (604);
+    message.addUnpackedSint32  (605);
+    message.addUnpackedSint64  (606);
+    message.addUnpackedFixed32 (607);
+    message.addUnpackedFixed64 (608);
+    message.addUnpackedSfixed32(609);
+    message.addUnpackedSfixed64(610);
+    message.addUnpackedFloat   (611);
+    message.addUnpackedDouble  (612);
+    message.addUnpackedBool    (true);
+    message.addUnpackedEnum    (ForeignEnum.FOREIGN_BAR);
+    // Add a second one of each field.
+    message.addUnpackedInt32   (701);
+    message.addUnpackedInt64   (702);
+    message.addUnpackedUint32  (703);
+    message.addUnpackedUint64  (704);
+    message.addUnpackedSint32  (705);
+    message.addUnpackedSint64  (706);
+    message.addUnpackedFixed32 (707);
+    message.addUnpackedFixed64 (708);
+    message.addUnpackedSfixed32(709);
+    message.addUnpackedSfixed64(710);
+    message.addUnpackedFloat   (711);
+    message.addUnpackedDouble  (712);
+    message.addUnpackedBool    (false);
+    message.addUnpackedEnum    (ForeignEnum.FOREIGN_BAZ);
+  }
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are set to the values assigned by {@code setPackedFields}.
+   */
+  public static void assertPackedFieldsSet(TestPackedTypes message) {
+    Assert.assertEquals(2, message.getPackedInt32Count   ());
+    Assert.assertEquals(2, message.getPackedInt64Count   ());
+    Assert.assertEquals(2, message.getPackedUint32Count  ());
+    Assert.assertEquals(2, message.getPackedUint64Count  ());
+    Assert.assertEquals(2, message.getPackedSint32Count  ());
+    Assert.assertEquals(2, message.getPackedSint64Count  ());
+    Assert.assertEquals(2, message.getPackedFixed32Count ());
+    Assert.assertEquals(2, message.getPackedFixed64Count ());
+    Assert.assertEquals(2, message.getPackedSfixed32Count());
+    Assert.assertEquals(2, message.getPackedSfixed64Count());
+    Assert.assertEquals(2, message.getPackedFloatCount   ());
+    Assert.assertEquals(2, message.getPackedDoubleCount  ());
+    Assert.assertEquals(2, message.getPackedBoolCount    ());
+    Assert.assertEquals(2, message.getPackedEnumCount   ());
+    Assert.assertEquals(601  , message.getPackedInt32   (0));
+    Assert.assertEquals(602  , message.getPackedInt64   (0));
+    Assert.assertEquals(603  , message.getPackedUint32  (0));
+    Assert.assertEquals(604  , message.getPackedUint64  (0));
+    Assert.assertEquals(605  , message.getPackedSint32  (0));
+    Assert.assertEquals(606  , message.getPackedSint64  (0));
+    Assert.assertEquals(607  , message.getPackedFixed32 (0));
+    Assert.assertEquals(608  , message.getPackedFixed64 (0));
+    Assert.assertEquals(609  , message.getPackedSfixed32(0));
+    Assert.assertEquals(610  , message.getPackedSfixed64(0));
+    Assert.assertEquals(611  , message.getPackedFloat   (0), 0.0);
+    Assert.assertEquals(612  , message.getPackedDouble  (0), 0.0);
+    Assert.assertEquals(true , message.getPackedBool    (0));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+    Assert.assertEquals(701  , message.getPackedInt32   (1));
+    Assert.assertEquals(702  , message.getPackedInt64   (1));
+    Assert.assertEquals(703  , message.getPackedUint32  (1));
+    Assert.assertEquals(704  , message.getPackedUint64  (1));
+    Assert.assertEquals(705  , message.getPackedSint32  (1));
+    Assert.assertEquals(706  , message.getPackedSint64  (1));
+    Assert.assertEquals(707  , message.getPackedFixed32 (1));
+    Assert.assertEquals(708  , message.getPackedFixed64 (1));
+    Assert.assertEquals(709  , message.getPackedSfixed32(1));
+    Assert.assertEquals(710  , message.getPackedSfixed64(1));
+    Assert.assertEquals(711  , message.getPackedFloat   (1), 0.0);
+    Assert.assertEquals(712  , message.getPackedDouble  (1), 0.0);
+    Assert.assertEquals(false, message.getPackedBool    (1));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+  }
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all fields of
+   * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+   */
+  public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+    Assert.assertEquals(2, message.getUnpackedInt32Count   ());
+    Assert.assertEquals(2, message.getUnpackedInt64Count   ());
+    Assert.assertEquals(2, message.getUnpackedUint32Count  ());
+    Assert.assertEquals(2, message.getUnpackedUint64Count  ());
+    Assert.assertEquals(2, message.getUnpackedSint32Count  ());
+    Assert.assertEquals(2, message.getUnpackedSint64Count  ());
+    Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+    Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+    Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+    Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+    Assert.assertEquals(2, message.getUnpackedFloatCount   ());
+    Assert.assertEquals(2, message.getUnpackedDoubleCount  ());
+    Assert.assertEquals(2, message.getUnpackedBoolCount    ());
+    Assert.assertEquals(2, message.getUnpackedEnumCount   ());
+    Assert.assertEquals(601  , message.getUnpackedInt32   (0));
+    Assert.assertEquals(602  , message.getUnpackedInt64   (0));
+    Assert.assertEquals(603  , message.getUnpackedUint32  (0));
+    Assert.assertEquals(604  , message.getUnpackedUint64  (0));
+    Assert.assertEquals(605  , message.getUnpackedSint32  (0));
+    Assert.assertEquals(606  , message.getUnpackedSint64  (0));
+    Assert.assertEquals(607  , message.getUnpackedFixed32 (0));
+    Assert.assertEquals(608  , message.getUnpackedFixed64 (0));
+    Assert.assertEquals(609  , message.getUnpackedSfixed32(0));
+    Assert.assertEquals(610  , message.getUnpackedSfixed64(0));
+    Assert.assertEquals(611  , message.getUnpackedFloat   (0), 0.0);
+    Assert.assertEquals(612  , message.getUnpackedDouble  (0), 0.0);
+    Assert.assertEquals(true , message.getUnpackedBool    (0));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+    Assert.assertEquals(701  , message.getUnpackedInt32   (1));
+    Assert.assertEquals(702  , message.getUnpackedInt64   (1));
+    Assert.assertEquals(703  , message.getUnpackedUint32  (1));
+    Assert.assertEquals(704  , message.getUnpackedUint64  (1));
+    Assert.assertEquals(705  , message.getUnpackedSint32  (1));
+    Assert.assertEquals(706  , message.getUnpackedSint64  (1));
+    Assert.assertEquals(707  , message.getUnpackedFixed32 (1));
+    Assert.assertEquals(708  , message.getUnpackedFixed64 (1));
+    Assert.assertEquals(709  , message.getUnpackedSfixed32(1));
+    Assert.assertEquals(710  , message.getUnpackedSfixed64(1));
+    Assert.assertEquals(711  , message.getUnpackedFloat   (1), 0.0);
+    Assert.assertEquals(712  , message.getUnpackedDouble  (1), 0.0);
+    Assert.assertEquals(false, message.getUnpackedBool    (1));
+    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+  }
+
+  // ===================================================================
+  // Like above, but for extensions
+
+  // Java gets confused with things like assertEquals(int, Integer):  it can't
+  // decide whether to call assertEquals(int, int) or assertEquals(Object,
+  // Object).  So we define these methods to help it.
+  private static void assertEqualsExactType(int a, int b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(long a, long b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(float a, float b) {
+    Assert.assertEquals(a, b, 0.0);
+  }
+  private static void assertEqualsExactType(double a, double b) {
+    Assert.assertEquals(a, b, 0.0);
+  }
+  private static void assertEqualsExactType(boolean a, boolean b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(String a, String b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ByteString a, ByteString b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
+                                            TestAllTypes.NestedEnum b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a,
+                                            TestAllTypesLite.NestedEnum b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ForeignEnumLite a,
+                                            ForeignEnumLite b) {
+    Assert.assertEquals(a, b);
+  }
+  private static void assertEqualsExactType(ImportEnumLite a,
+                                            ImportEnumLite b) {
+    Assert.assertEquals(a, b);
+  }
+
+  /**
+   * Get an unmodifiable {@link ExtensionRegistry} containing all the
+   * extensions of {@code TestAllExtensions}.
+   */
+  public static ExtensionRegistry getExtensionRegistry() {
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    registerAllExtensions(registry);
+    return registry.getUnmodifiable();
+  }
+
+  /**
+   * Register all of {@code TestAllExtensions}'s extensions with the
+   * given {@link ExtensionRegistry}.
+   */
+  public static void registerAllExtensions(ExtensionRegistry registry) {
+    UnittestProto.registerAllExtensions(registry);
+    TestUtilLite.registerAllExtensionsLite(registry);
+  }
+
+  /**
+   * Set every field of {@code message} to the values expected by
+   * {@code assertAllExtensionsSet()}.
+   */
+  public static void setAllExtensions(TestAllExtensions.Builder message) {
+    message.setExtension(optionalInt32Extension   , 101);
+    message.setExtension(optionalInt64Extension   , 102L);
+    message.setExtension(optionalUint32Extension  , 103);
+    message.setExtension(optionalUint64Extension  , 104L);
+    message.setExtension(optionalSint32Extension  , 105);
+    message.setExtension(optionalSint64Extension  , 106L);
+    message.setExtension(optionalFixed32Extension , 107);
+    message.setExtension(optionalFixed64Extension , 108L);
+    message.setExtension(optionalSfixed32Extension, 109);
+    message.setExtension(optionalSfixed64Extension, 110L);
+    message.setExtension(optionalFloatExtension   , 111F);
+    message.setExtension(optionalDoubleExtension  , 112D);
+    message.setExtension(optionalBoolExtension    , true);
+    message.setExtension(optionalStringExtension  , "115");
+    message.setExtension(optionalBytesExtension   , toBytes("116"));
+
+    message.setExtension(optionalGroupExtension,
+      OptionalGroup_extension.newBuilder().setA(117).build());
+    message.setExtension(optionalNestedMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+    message.setExtension(optionalForeignMessageExtension,
+      ForeignMessage.newBuilder().setC(119).build());
+    message.setExtension(optionalImportMessageExtension,
+      ImportMessage.newBuilder().setD(120).build());
+    message.setExtension(optionalPublicImportMessageExtension,
+      PublicImportMessage.newBuilder().setE(126).build());
+    message.setExtension(optionalLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+    message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+    message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+    message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+    message.setExtension(optionalStringPieceExtension, "124");
+    message.setExtension(optionalCordExtension, "125");
+
+    // -----------------------------------------------------------------
+
+    message.addExtension(repeatedInt32Extension   , 201);
+    message.addExtension(repeatedInt64Extension   , 202L);
+    message.addExtension(repeatedUint32Extension  , 203);
+    message.addExtension(repeatedUint64Extension  , 204L);
+    message.addExtension(repeatedSint32Extension  , 205);
+    message.addExtension(repeatedSint64Extension  , 206L);
+    message.addExtension(repeatedFixed32Extension , 207);
+    message.addExtension(repeatedFixed64Extension , 208L);
+    message.addExtension(repeatedSfixed32Extension, 209);
+    message.addExtension(repeatedSfixed64Extension, 210L);
+    message.addExtension(repeatedFloatExtension   , 211F);
+    message.addExtension(repeatedDoubleExtension  , 212D);
+    message.addExtension(repeatedBoolExtension    , true);
+    message.addExtension(repeatedStringExtension  , "215");
+    message.addExtension(repeatedBytesExtension   , toBytes("216"));
+
+    message.addExtension(repeatedGroupExtension,
+      RepeatedGroup_extension.newBuilder().setA(217).build());
+    message.addExtension(repeatedNestedMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+    message.addExtension(repeatedForeignMessageExtension,
+      ForeignMessage.newBuilder().setC(219).build());
+    message.addExtension(repeatedImportMessageExtension,
+      ImportMessage.newBuilder().setD(220).build());
+    message.addExtension(repeatedLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+    message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
+    message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
+    message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
+
+    message.addExtension(repeatedStringPieceExtension, "224");
+    message.addExtension(repeatedCordExtension, "225");
+
+    // Add a second one of each field.
+    message.addExtension(repeatedInt32Extension   , 301);
+    message.addExtension(repeatedInt64Extension   , 302L);
+    message.addExtension(repeatedUint32Extension  , 303);
+    message.addExtension(repeatedUint64Extension  , 304L);
+    message.addExtension(repeatedSint32Extension  , 305);
+    message.addExtension(repeatedSint64Extension  , 306L);
+    message.addExtension(repeatedFixed32Extension , 307);
+    message.addExtension(repeatedFixed64Extension , 308L);
+    message.addExtension(repeatedSfixed32Extension, 309);
+    message.addExtension(repeatedSfixed64Extension, 310L);
+    message.addExtension(repeatedFloatExtension   , 311F);
+    message.addExtension(repeatedDoubleExtension  , 312D);
+    message.addExtension(repeatedBoolExtension    , false);
+    message.addExtension(repeatedStringExtension  , "315");
+    message.addExtension(repeatedBytesExtension   , toBytes("316"));
+
+    message.addExtension(repeatedGroupExtension,
+      RepeatedGroup_extension.newBuilder().setA(317).build());
+    message.addExtension(repeatedNestedMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+    message.addExtension(repeatedForeignMessageExtension,
+      ForeignMessage.newBuilder().setC(319).build());
+    message.addExtension(repeatedImportMessageExtension,
+      ImportMessage.newBuilder().setD(320).build());
+    message.addExtension(repeatedLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+    message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+    message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+    message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+    message.addExtension(repeatedStringPieceExtension, "324");
+    message.addExtension(repeatedCordExtension, "325");
+
+    // -----------------------------------------------------------------
+
+    message.setExtension(defaultInt32Extension   , 401);
+    message.setExtension(defaultInt64Extension   , 402L);
+    message.setExtension(defaultUint32Extension  , 403);
+    message.setExtension(defaultUint64Extension  , 404L);
+    message.setExtension(defaultSint32Extension  , 405);
+    message.setExtension(defaultSint64Extension  , 406L);
+    message.setExtension(defaultFixed32Extension , 407);
+    message.setExtension(defaultFixed64Extension , 408L);
+    message.setExtension(defaultSfixed32Extension, 409);
+    message.setExtension(defaultSfixed64Extension, 410L);
+    message.setExtension(defaultFloatExtension   , 411F);
+    message.setExtension(defaultDoubleExtension  , 412D);
+    message.setExtension(defaultBoolExtension    , false);
+    message.setExtension(defaultStringExtension  , "415");
+    message.setExtension(defaultBytesExtension   , toBytes("416"));
+
+    message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
+    message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
+    message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
+
+    message.setExtension(defaultStringPieceExtension, "424");
+    message.setExtension(defaultCordExtension, "425");
+
+    message.setExtension(oneofUint32Extension, 601);
+    message.setExtension(oneofNestedMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+    message.setExtension(oneofStringExtension, "603");
+    message.setExtension(oneofBytesExtension, toBytes("604"));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Modify the repeated extensions of {@code message} to contain the values
+   * expected by {@code assertRepeatedExtensionsModified()}.
+   */
+  public static void modifyRepeatedExtensions(
+      TestAllExtensions.Builder message) {
+    message.setExtension(repeatedInt32Extension   , 1, 501);
+    message.setExtension(repeatedInt64Extension   , 1, 502L);
+    message.setExtension(repeatedUint32Extension  , 1, 503);
+    message.setExtension(repeatedUint64Extension  , 1, 504L);
+    message.setExtension(repeatedSint32Extension  , 1, 505);
+    message.setExtension(repeatedSint64Extension  , 1, 506L);
+    message.setExtension(repeatedFixed32Extension , 1, 507);
+    message.setExtension(repeatedFixed64Extension , 1, 508L);
+    message.setExtension(repeatedSfixed32Extension, 1, 509);
+    message.setExtension(repeatedSfixed64Extension, 1, 510L);
+    message.setExtension(repeatedFloatExtension   , 1, 511F);
+    message.setExtension(repeatedDoubleExtension  , 1, 512D);
+    message.setExtension(repeatedBoolExtension    , 1, true);
+    message.setExtension(repeatedStringExtension  , 1, "515");
+    message.setExtension(repeatedBytesExtension   , 1, toBytes("516"));
+
+    message.setExtension(repeatedGroupExtension, 1,
+      RepeatedGroup_extension.newBuilder().setA(517).build());
+    message.setExtension(repeatedNestedMessageExtension, 1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+    message.setExtension(repeatedForeignMessageExtension, 1,
+      ForeignMessage.newBuilder().setC(519).build());
+    message.setExtension(repeatedImportMessageExtension, 1,
+      ImportMessage.newBuilder().setD(520).build());
+    message.setExtension(repeatedLazyMessageExtension, 1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+    message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
+    message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
+    message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
+
+    message.setExtension(repeatedStringPieceExtension, 1, "524");
+    message.setExtension(repeatedCordExtension, 1, "525");
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}.
+   */
+  public static void assertAllExtensionsSet(
+      TestAllExtensionsOrBuilder message) {
+    Assert.assertTrue(message.hasExtension(optionalInt32Extension   ));
+    Assert.assertTrue(message.hasExtension(optionalInt64Extension   ));
+    Assert.assertTrue(message.hasExtension(optionalUint32Extension  ));
+    Assert.assertTrue(message.hasExtension(optionalUint64Extension  ));
+    Assert.assertTrue(message.hasExtension(optionalSint32Extension  ));
+    Assert.assertTrue(message.hasExtension(optionalSint64Extension  ));
+    Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
+    Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
+    Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
+    Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
+    Assert.assertTrue(message.hasExtension(optionalFloatExtension   ));
+    Assert.assertTrue(message.hasExtension(optionalDoubleExtension  ));
+    Assert.assertTrue(message.hasExtension(optionalBoolExtension    ));
+    Assert.assertTrue(message.hasExtension(optionalStringExtension  ));
+    Assert.assertTrue(message.hasExtension(optionalBytesExtension   ));
+
+    Assert.assertTrue(message.hasExtension(optionalGroupExtension         ));
+    Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
+    Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
+    Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
+
+    Assert.assertTrue(message.getExtension(optionalGroupExtension         ).hasA());
+    Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
+    Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
+    Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
+
+    Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
+    Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
+    Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
+
+    Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
+    Assert.assertTrue(message.hasExtension(optionalCordExtension));
+
+    assertEqualsExactType(101  , message.getExtension(optionalInt32Extension   ));
+    assertEqualsExactType(102L , message.getExtension(optionalInt64Extension   ));
+    assertEqualsExactType(103  , message.getExtension(optionalUint32Extension  ));
+    assertEqualsExactType(104L , message.getExtension(optionalUint64Extension  ));
+    assertEqualsExactType(105  , message.getExtension(optionalSint32Extension  ));
+    assertEqualsExactType(106L , message.getExtension(optionalSint64Extension  ));
+    assertEqualsExactType(107  , message.getExtension(optionalFixed32Extension ));
+    assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
+    assertEqualsExactType(109  , message.getExtension(optionalSfixed32Extension));
+    assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
+    assertEqualsExactType(111F , message.getExtension(optionalFloatExtension   ));
+    assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension  ));
+    assertEqualsExactType(true , message.getExtension(optionalBoolExtension    ));
+    assertEqualsExactType("115", message.getExtension(optionalStringExtension  ));
+    assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
+
+    assertEqualsExactType(117, message.getExtension(optionalGroupExtension              ).getA());
+    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension      ).getBb());
+    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension     ).getC());
+    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension      ).getD());
+    assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+    assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension        ).getBb());
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+      message.getExtension(optionalNestedEnumExtension));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+      message.getExtension(optionalForeignEnumExtension));
+    assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+      message.getExtension(optionalImportEnumExtension));
+
+    assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
+    assertEqualsExactType("125", message.getExtension(optionalCordExtension));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32Extension   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32Extension  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32Extension  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32Extension , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32Extension, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtension  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtension         , 0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtension, 0));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+      message.getExtension(repeatedForeignEnumExtension, 0));
+    assertEqualsExactType(ImportEnum.IMPORT_BAR,
+      message.getExtension(repeatedImportEnumExtension, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+    assertEqualsExactType(301  , message.getExtension(repeatedInt32Extension   , 1));
+    assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension   , 1));
+    assertEqualsExactType(303  , message.getExtension(repeatedUint32Extension  , 1));
+    assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension  , 1));
+    assertEqualsExactType(305  , message.getExtension(repeatedSint32Extension  , 1));
+    assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension  , 1));
+    assertEqualsExactType(307  , message.getExtension(repeatedFixed32Extension , 1));
+    assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
+    assertEqualsExactType(309  , message.getExtension(repeatedSfixed32Extension, 1));
+    assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
+    assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension   , 1));
+    assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension  , 1));
+    assertEqualsExactType(false, message.getExtension(repeatedBoolExtension    , 1));
+    assertEqualsExactType("315", message.getExtension(repeatedStringExtension  , 1));
+    assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
+
+    assertEqualsExactType(317, message.getExtension(repeatedGroupExtension         , 1).getA());
+    assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+    assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+    assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+    assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+      message.getExtension(repeatedNestedEnumExtension, 1));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+      message.getExtension(repeatedForeignEnumExtension, 1));
+    assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+      message.getExtension(repeatedImportEnumExtension, 1));
+
+    assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
+    assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertTrue(message.hasExtension(defaultInt32Extension   ));
+    Assert.assertTrue(message.hasExtension(defaultInt64Extension   ));
+    Assert.assertTrue(message.hasExtension(defaultUint32Extension  ));
+    Assert.assertTrue(message.hasExtension(defaultUint64Extension  ));
+    Assert.assertTrue(message.hasExtension(defaultSint32Extension  ));
+    Assert.assertTrue(message.hasExtension(defaultSint64Extension  ));
+    Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
+    Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
+    Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
+    Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
+    Assert.assertTrue(message.hasExtension(defaultFloatExtension   ));
+    Assert.assertTrue(message.hasExtension(defaultDoubleExtension  ));
+    Assert.assertTrue(message.hasExtension(defaultBoolExtension    ));
+    Assert.assertTrue(message.hasExtension(defaultStringExtension  ));
+    Assert.assertTrue(message.hasExtension(defaultBytesExtension   ));
+
+    Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
+    Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
+    Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
+
+    Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
+    Assert.assertTrue(message.hasExtension(defaultCordExtension));
+
+    assertEqualsExactType(401  , message.getExtension(defaultInt32Extension   ));
+    assertEqualsExactType(402L , message.getExtension(defaultInt64Extension   ));
+    assertEqualsExactType(403  , message.getExtension(defaultUint32Extension  ));
+    assertEqualsExactType(404L , message.getExtension(defaultUint64Extension  ));
+    assertEqualsExactType(405  , message.getExtension(defaultSint32Extension  ));
+    assertEqualsExactType(406L , message.getExtension(defaultSint64Extension  ));
+    assertEqualsExactType(407  , message.getExtension(defaultFixed32Extension ));
+    assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
+    assertEqualsExactType(409  , message.getExtension(defaultSfixed32Extension));
+    assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
+    assertEqualsExactType(411F , message.getExtension(defaultFloatExtension   ));
+    assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension  ));
+    assertEqualsExactType(false, message.getExtension(defaultBoolExtension    ));
+    assertEqualsExactType("415", message.getExtension(defaultStringExtension  ));
+    assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+      message.getExtension(defaultNestedEnumExtension ));
+    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+      message.getExtension(defaultForeignEnumExtension));
+    assertEqualsExactType(ImportEnum.IMPORT_FOO,
+      message.getExtension(defaultImportEnumExtension));
+
+    assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
+    assertEqualsExactType("425", message.getExtension(defaultCordExtension));
+
+    Assert.assertTrue(message.hasExtension(oneofBytesExtension));
+
+    assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtension));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are cleared, and that getting the extensions returns their
+   * default values.
+   */
+  public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
+    // hasBlah() should initially be false for all optional fields.
+    Assert.assertFalse(message.hasExtension(optionalInt32Extension   ));
+    Assert.assertFalse(message.hasExtension(optionalInt64Extension   ));
+    Assert.assertFalse(message.hasExtension(optionalUint32Extension  ));
+    Assert.assertFalse(message.hasExtension(optionalUint64Extension  ));
+    Assert.assertFalse(message.hasExtension(optionalSint32Extension  ));
+    Assert.assertFalse(message.hasExtension(optionalSint64Extension  ));
+    Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
+    Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
+    Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
+    Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
+    Assert.assertFalse(message.hasExtension(optionalFloatExtension   ));
+    Assert.assertFalse(message.hasExtension(optionalDoubleExtension  ));
+    Assert.assertFalse(message.hasExtension(optionalBoolExtension    ));
+    Assert.assertFalse(message.hasExtension(optionalStringExtension  ));
+    Assert.assertFalse(message.hasExtension(optionalBytesExtension   ));
+
+    Assert.assertFalse(message.hasExtension(optionalGroupExtension         ));
+    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
+    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
+    Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
+
+    Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
+    Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
+    Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
+
+    Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
+    Assert.assertFalse(message.hasExtension(optionalCordExtension));
+
+    // Optional fields without defaults are set to zero or something like it.
+    assertEqualsExactType(0    , message.getExtension(optionalInt32Extension   ));
+    assertEqualsExactType(0L   , message.getExtension(optionalInt64Extension   ));
+    assertEqualsExactType(0    , message.getExtension(optionalUint32Extension  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalUint64Extension  ));
+    assertEqualsExactType(0    , message.getExtension(optionalSint32Extension  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalSint64Extension  ));
+    assertEqualsExactType(0    , message.getExtension(optionalFixed32Extension ));
+    assertEqualsExactType(0L   , message.getExtension(optionalFixed64Extension ));
+    assertEqualsExactType(0    , message.getExtension(optionalSfixed32Extension));
+    assertEqualsExactType(0L   , message.getExtension(optionalSfixed64Extension));
+    assertEqualsExactType(0F   , message.getExtension(optionalFloatExtension   ));
+    assertEqualsExactType(0D   , message.getExtension(optionalDoubleExtension  ));
+    assertEqualsExactType(false, message.getExtension(optionalBoolExtension    ));
+    assertEqualsExactType(""   , message.getExtension(optionalStringExtension  ));
+    assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
+
+    // Embedded messages should also be clear.
+    Assert.assertFalse(message.getExtension(optionalGroupExtension         ).hasA());
+    Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
+    Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
+    Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
+
+    assertEqualsExactType(0, message.getExtension(optionalGroupExtension         ).getA());
+    assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
+    assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
+    assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
+
+    // Enums without defaults are set to the first value in the enum.
+    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+      message.getExtension(optionalNestedEnumExtension ));
+    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+      message.getExtension(optionalForeignEnumExtension));
+    assertEqualsExactType(ImportEnum.IMPORT_FOO,
+      message.getExtension(optionalImportEnumExtension));
+
+    assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
+    assertEqualsExactType("", message.getExtension(optionalCordExtension));
+
+    // Repeated fields are empty.
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension   ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension         ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension    ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
+
+    // Repeated fields are empty via getExtension().size().
+    Assert.assertEquals(0, message.getExtension(repeatedInt32Extension   ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedInt64Extension   ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedUint32Extension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedUint64Extension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedSint32Extension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedSint64Extension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size());
+    Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size());
+    Assert.assertEquals(0, message.getExtension(repeatedFloatExtension   ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedBoolExtension    ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedStringExtension  ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedBytesExtension   ).size());
+
+    Assert.assertEquals(0, message.getExtension(repeatedGroupExtension         ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
+    Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension   ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension    ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension   ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension    ).size());
+
+    Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size());
+    Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size());
+
+    // hasBlah() should also be false for all default fields.
+    Assert.assertFalse(message.hasExtension(defaultInt32Extension   ));
+    Assert.assertFalse(message.hasExtension(defaultInt64Extension   ));
+    Assert.assertFalse(message.hasExtension(defaultUint32Extension  ));
+    Assert.assertFalse(message.hasExtension(defaultUint64Extension  ));
+    Assert.assertFalse(message.hasExtension(defaultSint32Extension  ));
+    Assert.assertFalse(message.hasExtension(defaultSint64Extension  ));
+    Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
+    Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
+    Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
+    Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
+    Assert.assertFalse(message.hasExtension(defaultFloatExtension   ));
+    Assert.assertFalse(message.hasExtension(defaultDoubleExtension  ));
+    Assert.assertFalse(message.hasExtension(defaultBoolExtension    ));
+    Assert.assertFalse(message.hasExtension(defaultStringExtension  ));
+    Assert.assertFalse(message.hasExtension(defaultBytesExtension   ));
+
+    Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
+    Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
+    Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
+
+    Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
+    Assert.assertFalse(message.hasExtension(defaultCordExtension));
+
+    // Fields with defaults have their default values (duh).
+    assertEqualsExactType( 41    , message.getExtension(defaultInt32Extension   ));
+    assertEqualsExactType( 42L   , message.getExtension(defaultInt64Extension   ));
+    assertEqualsExactType( 43    , message.getExtension(defaultUint32Extension  ));
+    assertEqualsExactType( 44L   , message.getExtension(defaultUint64Extension  ));
+    assertEqualsExactType(-45    , message.getExtension(defaultSint32Extension  ));
+    assertEqualsExactType( 46L   , message.getExtension(defaultSint64Extension  ));
+    assertEqualsExactType( 47    , message.getExtension(defaultFixed32Extension ));
+    assertEqualsExactType( 48L   , message.getExtension(defaultFixed64Extension ));
+    assertEqualsExactType( 49    , message.getExtension(defaultSfixed32Extension));
+    assertEqualsExactType(-50L   , message.getExtension(defaultSfixed64Extension));
+    assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension   ));
+    assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension  ));
+    assertEqualsExactType(true   , message.getExtension(defaultBoolExtension    ));
+    assertEqualsExactType("hello", message.getExtension(defaultStringExtension  ));
+    assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+      message.getExtension(defaultNestedEnumExtension ));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+      message.getExtension(defaultForeignEnumExtension));
+    assertEqualsExactType(ImportEnum.IMPORT_BAR,
+      message.getExtension(defaultImportEnumExtension));
+
+    assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
+    assertEqualsExactType("123", message.getExtension(defaultCordExtension));
+
+    Assert.assertFalse(message.hasExtension(oneofUint32Extension));
+    Assert.assertFalse(message.hasExtension(oneofNestedMessageExtension));
+    Assert.assertFalse(message.hasExtension(oneofStringExtension));
+    Assert.assertFalse(message.hasExtension(oneofBytesExtension));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}
+   * followed by {@code modifyRepeatedExtensions}.
+   */
+  public static void assertRepeatedExtensionsModified(
+      TestAllExtensionsOrBuilder message) {
+    // ModifyRepeatedFields only sets the second repeated element of each
+    // field.  In addition to verifying this, we also verify that the first
+    // element and size were *not* modified.
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32Extension   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32Extension  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32Extension  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32Extension , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32Extension, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtension  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtension         , 0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtension, 0));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+      message.getExtension(repeatedForeignEnumExtension, 0));
+    assertEqualsExactType(ImportEnum.IMPORT_BAR,
+      message.getExtension(repeatedImportEnumExtension, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+    // Actually verify the second (modified) elements now.
+    assertEqualsExactType(501  , message.getExtension(repeatedInt32Extension   , 1));
+    assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension   , 1));
+    assertEqualsExactType(503  , message.getExtension(repeatedUint32Extension  , 1));
+    assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension  , 1));
+    assertEqualsExactType(505  , message.getExtension(repeatedSint32Extension  , 1));
+    assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension  , 1));
+    assertEqualsExactType(507  , message.getExtension(repeatedFixed32Extension , 1));
+    assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
+    assertEqualsExactType(509  , message.getExtension(repeatedSfixed32Extension, 1));
+    assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
+    assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension   , 1));
+    assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension  , 1));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 1));
+    assertEqualsExactType("515", message.getExtension(repeatedStringExtension  , 1));
+    assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
+
+    assertEqualsExactType(517, message.getExtension(repeatedGroupExtension         , 1).getA());
+    assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+    assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+    assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+    assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
+
+    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+      message.getExtension(repeatedNestedEnumExtension, 1));
+    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+      message.getExtension(repeatedForeignEnumExtension, 1));
+    assertEqualsExactType(ImportEnum.IMPORT_FOO,
+      message.getExtension(repeatedImportEnumExtension, 1));
+
+    assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
+    assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
+  }
+
+  public static void setPackedExtensions(TestPackedExtensions.Builder message) {
+    message.addExtension(packedInt32Extension   , 601);
+    message.addExtension(packedInt64Extension   , 602L);
+    message.addExtension(packedUint32Extension  , 603);
+    message.addExtension(packedUint64Extension  , 604L);
+    message.addExtension(packedSint32Extension  , 605);
+    message.addExtension(packedSint64Extension  , 606L);
+    message.addExtension(packedFixed32Extension , 607);
+    message.addExtension(packedFixed64Extension , 608L);
+    message.addExtension(packedSfixed32Extension, 609);
+    message.addExtension(packedSfixed64Extension, 610L);
+    message.addExtension(packedFloatExtension   , 611F);
+    message.addExtension(packedDoubleExtension  , 612D);
+    message.addExtension(packedBoolExtension    , true);
+    message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
+    // Add a second one of each field.
+    message.addExtension(packedInt32Extension   , 701);
+    message.addExtension(packedInt64Extension   , 702L);
+    message.addExtension(packedUint32Extension  , 703);
+    message.addExtension(packedUint64Extension  , 704L);
+    message.addExtension(packedSint32Extension  , 705);
+    message.addExtension(packedSint64Extension  , 706L);
+    message.addExtension(packedFixed32Extension , 707);
+    message.addExtension(packedFixed64Extension , 708L);
+    message.addExtension(packedSfixed32Extension, 709);
+    message.addExtension(packedSfixed64Extension, 710L);
+    message.addExtension(packedFloatExtension   , 711F);
+    message.addExtension(packedDoubleExtension  , 712D);
+    message.addExtension(packedBoolExtension    , false);
+    message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
+  }
+
+  public static void assertPackedExtensionsSet(TestPackedExtensions message) {
+    Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
+    Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension    ));
+    Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
+    assertEqualsExactType(601  , message.getExtension(packedInt32Extension   , 0));
+    assertEqualsExactType(602L , message.getExtension(packedInt64Extension   , 0));
+    assertEqualsExactType(603  , message.getExtension(packedUint32Extension  , 0));
+    assertEqualsExactType(604L , message.getExtension(packedUint64Extension  , 0));
+    assertEqualsExactType(605  , message.getExtension(packedSint32Extension  , 0));
+    assertEqualsExactType(606L , message.getExtension(packedSint64Extension  , 0));
+    assertEqualsExactType(607  , message.getExtension(packedFixed32Extension , 0));
+    assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
+    assertEqualsExactType(609  , message.getExtension(packedSfixed32Extension, 0));
+    assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
+    assertEqualsExactType(611F , message.getExtension(packedFloatExtension   , 0));
+    assertEqualsExactType(612D , message.getExtension(packedDoubleExtension  , 0));
+    assertEqualsExactType(true , message.getExtension(packedBoolExtension    , 0));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+                          message.getExtension(packedEnumExtension, 0));
+    assertEqualsExactType(701  , message.getExtension(packedInt32Extension   , 1));
+    assertEqualsExactType(702L , message.getExtension(packedInt64Extension   , 1));
+    assertEqualsExactType(703  , message.getExtension(packedUint32Extension  , 1));
+    assertEqualsExactType(704L , message.getExtension(packedUint64Extension  , 1));
+    assertEqualsExactType(705  , message.getExtension(packedSint32Extension  , 1));
+    assertEqualsExactType(706L , message.getExtension(packedSint64Extension  , 1));
+    assertEqualsExactType(707  , message.getExtension(packedFixed32Extension , 1));
+    assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
+    assertEqualsExactType(709  , message.getExtension(packedSfixed32Extension, 1));
+    assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
+    assertEqualsExactType(711F , message.getExtension(packedFloatExtension   , 1));
+    assertEqualsExactType(712D , message.getExtension(packedDoubleExtension  , 1));
+    assertEqualsExactType(false, message.getExtension(packedBoolExtension    , 1));
+    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+                          message.getExtension(packedEnumExtension, 1));
+  }
+
+  // ===================================================================
+  // Lite extensions
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}.
+   */
+  public static void assertAllExtensionsSet(
+      TestAllExtensionsLiteOrBuilder message) {
+    Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite    ));
+    Assert.assertTrue(message.hasExtension(optionalStringExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite   ));
+
+    Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite         ));
+    Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite ));
+
+    Assert.assertTrue(message.getExtension(optionalGroupExtensionLite         ).hasA());
+    Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+    Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+    Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+    Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite ));
+    Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite ));
+
+    Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite));
+    Assert.assertTrue(message.hasExtension(optionalCordExtensionLite));
+
+    assertEqualsExactType(101  , message.getExtension(optionalInt32ExtensionLite   ));
+    assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite   ));
+    assertEqualsExactType(103  , message.getExtension(optionalUint32ExtensionLite  ));
+    assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite  ));
+    assertEqualsExactType(105  , message.getExtension(optionalSint32ExtensionLite  ));
+    assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite  ));
+    assertEqualsExactType(107  , message.getExtension(optionalFixed32ExtensionLite ));
+    assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite ));
+    assertEqualsExactType(109  , message.getExtension(optionalSfixed32ExtensionLite));
+    assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite));
+    assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite   ));
+    assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite  ));
+    assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite    ));
+    assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite  ));
+    assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite));
+
+    assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite         ).getA());
+    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
+    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+    assertEqualsExactType(126, message.getExtension(
+        optionalPublicImportMessageExtensionLite).getE());
+    assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+      message.getExtension(optionalNestedEnumExtensionLite));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+      message.getExtension(optionalForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+      message.getExtension(optionalImportEnumExtensionLite));
+
+    assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite));
+    assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32ExtensionLite   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32ExtensionLite  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32ExtensionLite  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32ExtensionLite , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite         ,0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite   ,0).getBb());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtensionLite, 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(repeatedForeignEnumExtensionLite, 0));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+    assertEqualsExactType(301  , message.getExtension(repeatedInt32ExtensionLite   , 1));
+    assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite   , 1));
+    assertEqualsExactType(303  , message.getExtension(repeatedUint32ExtensionLite  , 1));
+    assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite  , 1));
+    assertEqualsExactType(305  , message.getExtension(repeatedSint32ExtensionLite  , 1));
+    assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite  , 1));
+    assertEqualsExactType(307  , message.getExtension(repeatedFixed32ExtensionLite , 1));
+    assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+    assertEqualsExactType(309  , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite   , 1));
+    assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite  , 1));
+    assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite    , 1));
+    assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite  , 1));
+    assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+    assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite         ,1).getA());
+    assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+    assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+    assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+    assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite   ,1).getBb());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+      message.getExtension(repeatedNestedEnumExtensionLite, 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+      message.getExtension(repeatedForeignEnumExtensionLite, 1));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+      message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+    assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1));
+    assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1));
+
+    // -----------------------------------------------------------------
+
+    Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite   ));
+    Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite    ));
+    Assert.assertTrue(message.hasExtension(defaultStringExtensionLite  ));
+    Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite   ));
+
+    Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite ));
+    Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite ));
+
+    Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite));
+    Assert.assertTrue(message.hasExtension(defaultCordExtensionLite));
+
+    assertEqualsExactType(401  , message.getExtension(defaultInt32ExtensionLite   ));
+    assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite   ));
+    assertEqualsExactType(403  , message.getExtension(defaultUint32ExtensionLite  ));
+    assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite  ));
+    assertEqualsExactType(405  , message.getExtension(defaultSint32ExtensionLite  ));
+    assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite  ));
+    assertEqualsExactType(407  , message.getExtension(defaultFixed32ExtensionLite ));
+    assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite ));
+    assertEqualsExactType(409  , message.getExtension(defaultSfixed32ExtensionLite));
+    assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite));
+    assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite   ));
+    assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite  ));
+    assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite    ));
+    assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite  ));
+    assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite));
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(defaultNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(defaultForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(defaultImportEnumExtensionLite));
+
+    assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
+    assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+
+    Assert.assertTrue(message.hasExtension(oneofBytesExtensionLite));
+
+    assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtensionLite));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are cleared, and that getting the extensions returns their
+   * default values.
+   */
+  public static void assertExtensionsClear(
+      TestAllExtensionsLiteOrBuilder message) {
+    // hasBlah() should initially be false for all optional fields.
+    Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite    ));
+    Assert.assertFalse(message.hasExtension(optionalStringExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite   ));
+
+    Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite              ));
+    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite      ));
+    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite     ));
+    Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite      ));
+    Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite        ));
+
+    Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite ));
+
+    Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalCordExtensionLite));
+
+    // Optional fields without defaults are set to zero or something like it.
+    assertEqualsExactType(0    , message.getExtension(optionalInt32ExtensionLite   ));
+    assertEqualsExactType(0L   , message.getExtension(optionalInt64ExtensionLite   ));
+    assertEqualsExactType(0    , message.getExtension(optionalUint32ExtensionLite  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalUint64ExtensionLite  ));
+    assertEqualsExactType(0    , message.getExtension(optionalSint32ExtensionLite  ));
+    assertEqualsExactType(0L   , message.getExtension(optionalSint64ExtensionLite  ));
+    assertEqualsExactType(0    , message.getExtension(optionalFixed32ExtensionLite ));
+    assertEqualsExactType(0L   , message.getExtension(optionalFixed64ExtensionLite ));
+    assertEqualsExactType(0    , message.getExtension(optionalSfixed32ExtensionLite));
+    assertEqualsExactType(0L   , message.getExtension(optionalSfixed64ExtensionLite));
+    assertEqualsExactType(0F   , message.getExtension(optionalFloatExtensionLite   ));
+    assertEqualsExactType(0D   , message.getExtension(optionalDoubleExtensionLite  ));
+    assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite    ));
+    assertEqualsExactType(""   , message.getExtension(optionalStringExtensionLite  ));
+    assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
+
+    // Embedded messages should also be clear.
+    Assert.assertFalse(message.getExtension(optionalGroupExtensionLite              ).hasA());
+    Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite      ).hasBb());
+    Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite     ).hasC());
+    Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite      ).hasD());
+    Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE());
+    Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite        ).hasBb());
+
+    assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite         ).getA());
+    assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+    assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
+    assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+    assertEqualsExactType(0, message.getExtension(
+        optionalPublicImportMessageExtensionLite).getE());
+    assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite   ).getBb());
+
+    // Enums without defaults are set to the first value in the enum.
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(optionalNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(optionalForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(optionalImportEnumExtensionLite));
+
+    assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite));
+    assertEqualsExactType("", message.getExtension(optionalCordExtensionLite));
+
+    // Repeated fields are empty.
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite));
+
+    // hasBlah() should also be false for all default fields.
+    Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite   ));
+    Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite    ));
+    Assert.assertFalse(message.hasExtension(defaultStringExtensionLite  ));
+    Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite   ));
+
+    Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite ));
+    Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite ));
+
+    Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite));
+    Assert.assertFalse(message.hasExtension(defaultCordExtensionLite));
+
+    // Fields with defaults have their default values (duh).
+    assertEqualsExactType( 41    , message.getExtension(defaultInt32ExtensionLite   ));
+    assertEqualsExactType( 42L   , message.getExtension(defaultInt64ExtensionLite   ));
+    assertEqualsExactType( 43    , message.getExtension(defaultUint32ExtensionLite  ));
+    assertEqualsExactType( 44L   , message.getExtension(defaultUint64ExtensionLite  ));
+    assertEqualsExactType(-45    , message.getExtension(defaultSint32ExtensionLite  ));
+    assertEqualsExactType( 46L   , message.getExtension(defaultSint64ExtensionLite  ));
+    assertEqualsExactType( 47    , message.getExtension(defaultFixed32ExtensionLite ));
+    assertEqualsExactType( 48L   , message.getExtension(defaultFixed64ExtensionLite ));
+    assertEqualsExactType( 49    , message.getExtension(defaultSfixed32ExtensionLite));
+    assertEqualsExactType(-50L   , message.getExtension(defaultSfixed64ExtensionLite));
+    assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite   ));
+    assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite  ));
+    assertEqualsExactType(true   , message.getExtension(defaultBoolExtensionLite    ));
+    assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite  ));
+    assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite));
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(defaultNestedEnumExtensionLite ));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(defaultForeignEnumExtensionLite));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(defaultImportEnumExtensionLite));
+
+    assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite));
+    assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite));
+
+    Assert.assertFalse(message.hasExtension(oneofUint32ExtensionLite));
+    Assert.assertFalse(message.hasExtension(oneofNestedMessageExtensionLite));
+    Assert.assertFalse(message.hasExtension(oneofStringExtensionLite));
+    Assert.assertFalse(message.hasExtension(oneofBytesExtensionLite));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Assert (using {@code junit.framework.Assert}} that all extensions of
+   * {@code message} are set to the values assigned by {@code setAllExtensions}
+   * followed by {@code modifyRepeatedExtensions}.
+   */
+  public static void assertRepeatedExtensionsModified(
+      TestAllExtensionsLiteOrBuilder message) {
+    // ModifyRepeatedFields only sets the second repeated element of each
+    // field.  In addition to verifying this, we also verify that the first
+    // element and size were *not* modified.
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite   ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite         ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
+
+    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+    assertEqualsExactType(201  , message.getExtension(repeatedInt32ExtensionLite   , 0));
+    assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite   , 0));
+    assertEqualsExactType(203  , message.getExtension(repeatedUint32ExtensionLite  , 0));
+    assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite  , 0));
+    assertEqualsExactType(205  , message.getExtension(repeatedSint32ExtensionLite  , 0));
+    assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite  , 0));
+    assertEqualsExactType(207  , message.getExtension(repeatedFixed32ExtensionLite , 0));
+    assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite   , 0));
+    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 0));
+    assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite  , 0));
+    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+    assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite         ,0).getA());
+    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite   ,0).getBb());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+      message.getExtension(repeatedNestedEnumExtensionLite, 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+      message.getExtension(repeatedForeignEnumExtensionLite, 0));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+      message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+    assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+    // Actually verify the second (modified) elements now.
+    assertEqualsExactType(501  , message.getExtension(repeatedInt32ExtensionLite   , 1));
+    assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite   , 1));
+    assertEqualsExactType(503  , message.getExtension(repeatedUint32ExtensionLite  , 1));
+    assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite  , 1));
+    assertEqualsExactType(505  , message.getExtension(repeatedSint32ExtensionLite  , 1));
+    assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite  , 1));
+    assertEqualsExactType(507  , message.getExtension(repeatedFixed32ExtensionLite , 1));
+    assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+    assertEqualsExactType(509  , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite   , 1));
+    assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite  , 1));
+    assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite    , 1));
+    assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite  , 1));
+    assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+    assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite         ,1).getA());
+    assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+    assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+    assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+    assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite   ,1).getBb());
+
+    assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+      message.getExtension(repeatedNestedEnumExtensionLite, 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+      message.getExtension(repeatedForeignEnumExtensionLite, 1));
+    assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+      message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+    assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1));
+    assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
+  }
+
+  public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
+    Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite));
+    Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite   ));
+    Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite  ));
+    Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite    ));
+    Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite));
+    assertEqualsExactType(601  , message.getExtension(packedInt32ExtensionLite   , 0));
+    assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite   , 0));
+    assertEqualsExactType(603  , message.getExtension(packedUint32ExtensionLite  , 0));
+    assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite  , 0));
+    assertEqualsExactType(605  , message.getExtension(packedSint32ExtensionLite  , 0));
+    assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite  , 0));
+    assertEqualsExactType(607  , message.getExtension(packedFixed32ExtensionLite , 0));
+    assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0));
+    assertEqualsExactType(609  , message.getExtension(packedSfixed32ExtensionLite, 0));
+    assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0));
+    assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite   , 0));
+    assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite  , 0));
+    assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite    , 0));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+                          message.getExtension(packedEnumExtensionLite, 0));
+    assertEqualsExactType(701  , message.getExtension(packedInt32ExtensionLite   , 1));
+    assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite   , 1));
+    assertEqualsExactType(703  , message.getExtension(packedUint32ExtensionLite  , 1));
+    assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite  , 1));
+    assertEqualsExactType(705  , message.getExtension(packedSint32ExtensionLite  , 1));
+    assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite  , 1));
+    assertEqualsExactType(707  , message.getExtension(packedFixed32ExtensionLite , 1));
+    assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1));
+    assertEqualsExactType(709  , message.getExtension(packedSfixed32ExtensionLite, 1));
+    assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1));
+    assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite   , 1));
+    assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite  , 1));
+    assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite    , 1));
+    assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+                          message.getExtension(packedEnumExtensionLite, 1));
+  }
+
+  // ===================================================================
+  // oneof
+  public static void setOneof(TestOneof2.Builder message) {
+    message.setFooLazyMessage(
+        TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build());
+    message.setBarString("101");
+    message.setBazInt(102);
+    message.setBazString("103");
+  }
+
+  public static void assertOneofSet(TestOneof2 message) {
+    Assert.assertTrue(message.hasFooLazyMessage            ());
+    Assert.assertTrue(message.getFooLazyMessage().hasQuxInt());
+
+    Assert.assertTrue(message.hasBarString());
+    Assert.assertTrue(message.hasBazInt   ());
+    Assert.assertTrue(message.hasBazString());
+
+    Assert.assertEquals(100  , message.getFooLazyMessage().getQuxInt());
+    Assert.assertEquals("101", message.getBarString                 ());
+    Assert.assertEquals(102  , message.getBazInt                    ());
+    Assert.assertEquals("103", message.getBazString                 ());
+  }
+
+  public static void assertAtMostOneFieldSetOneof(TestOneof2 message) {
+    int count = 0;
+    if (message.hasFooInt()) { ++count; }
+    if (message.hasFooString()) { ++count; }
+    if (message.hasFooCord()) { ++count; }
+    if (message.hasFooStringPiece()) { ++count; }
+    if (message.hasFooBytes()) { ++count; }
+    if (message.hasFooEnum()) { ++count; }
+    if (message.hasFooMessage()) { ++count; }
+    if (message.hasFooGroup()) { ++count; }
+    if (message.hasFooLazyMessage()) { ++count; }
+    Assert.assertTrue(count <= 1);
+
+    count = 0;
+    if (message.hasBarInt()) { ++count; }
+    if (message.hasBarString()) { ++count; }
+    if (message.hasBarCord()) { ++count; }
+    if (message.hasBarStringPiece()) { ++count; }
+    if (message.hasBarBytes()) { ++count; }
+    if (message.hasBarEnum()) { ++count; }
+    Assert.assertTrue(count <= 1);
+
+    switch (message.getFooCase()) {
+      case FOO_INT:
+        Assert.assertTrue(message.hasFooInt());
+        break;
+      case FOO_STRING:
+        Assert.assertTrue(message.hasFooString());
+        break;
+      case FOO_CORD:
+        Assert.assertTrue(message.hasFooCord());
+        break;
+      case FOO_BYTES:
+        Assert.assertTrue(message.hasFooBytes());
+        break;
+      case FOO_ENUM:
+        Assert.assertTrue(message.hasFooEnum());
+        break;
+      case FOO_MESSAGE:
+        Assert.assertTrue(message.hasFooMessage());
+        break;
+      case FOOGROUP:
+        Assert.assertTrue(message.hasFooGroup());
+        break;
+      case FOO_LAZY_MESSAGE:
+        Assert.assertTrue(message.hasFooLazyMessage());
+        break;
+      case FOO_NOT_SET:
+        break;
+    }
+  }
+
+  // =================================================================
+
+  /**
+   * Performs the same things that the methods of {@code TestUtil} do, but
+   * via the reflection interface.  This is its own class because it needs
+   * to know what descriptor to use.
+   */
+  public static class ReflectionTester {
+    private final Descriptors.Descriptor baseDescriptor;
+    private final ExtensionRegistry extensionRegistry;
+
+    private final Descriptors.FileDescriptor file;
+    private final Descriptors.FileDescriptor importFile;
+    private final Descriptors.FileDescriptor publicImportFile;
+
+    private final Descriptors.Descriptor optionalGroup;
+    private final Descriptors.Descriptor repeatedGroup;
+    private final Descriptors.Descriptor nestedMessage;
+    private final Descriptors.Descriptor foreignMessage;
+    private final Descriptors.Descriptor importMessage;
+    private final Descriptors.Descriptor publicImportMessage;
+
+    private final Descriptors.FieldDescriptor groupA;
+    private final Descriptors.FieldDescriptor repeatedGroupA;
+    private final Descriptors.FieldDescriptor nestedB;
+    private final Descriptors.FieldDescriptor foreignC;
+    private final Descriptors.FieldDescriptor importD;
+    private final Descriptors.FieldDescriptor importE;
+
+    private final Descriptors.EnumDescriptor nestedEnum;
+    private final Descriptors.EnumDescriptor foreignEnum;
+    private final Descriptors.EnumDescriptor importEnum;
+
+    private final Descriptors.EnumValueDescriptor nestedFoo;
+    private final Descriptors.EnumValueDescriptor nestedBar;
+    private final Descriptors.EnumValueDescriptor nestedBaz;
+    private final Descriptors.EnumValueDescriptor foreignFoo;
+    private final Descriptors.EnumValueDescriptor foreignBar;
+    private final Descriptors.EnumValueDescriptor foreignBaz;
+    private final Descriptors.EnumValueDescriptor importFoo;
+    private final Descriptors.EnumValueDescriptor importBar;
+    private final Descriptors.EnumValueDescriptor importBaz;
+
+    /**
+     * Construct a {@code ReflectionTester} that will expect messages using
+     * the given descriptor.
+     *
+     * Normally {@code baseDescriptor} should be a descriptor for the type
+     * {@code TestAllTypes}, defined in
+     * {@code google/protobuf/unittest.proto}.  However, if
+     * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should
+     * be for {@code TestAllExtensions} instead, and instead of reading and
+     * writing normal fields, the tester will read and write extensions.
+     * All of {@code TestAllExtensions}' extensions must be registered in the
+     * registry.
+     */
+    public ReflectionTester(Descriptors.Descriptor baseDescriptor,
+                            ExtensionRegistry extensionRegistry) {
+      this.baseDescriptor = baseDescriptor;
+      this.extensionRegistry = extensionRegistry;
+
+      this.file = baseDescriptor.getFile();
+      Assert.assertEquals(1, file.getDependencies().size());
+      this.importFile = file.getDependencies().get(0);
+      this.publicImportFile = importFile.getDependencies().get(0);
+
+      Descriptors.Descriptor testAllTypes;
+      if (baseDescriptor.getName() == "TestAllTypes") {
+        testAllTypes = baseDescriptor;
+      } else {
+        testAllTypes = file.findMessageTypeByName("TestAllTypes");
+        Assert.assertNotNull(testAllTypes);
+      }
+
+      if (extensionRegistry == null) {
+        // Use testAllTypes, rather than baseDescriptor, to allow
+        // initialization using TestPackedTypes descriptors. These objects
+        // won't be used by the methods for packed fields.
+        this.optionalGroup =
+          testAllTypes.findNestedTypeByName("OptionalGroup");
+        this.repeatedGroup =
+          testAllTypes.findNestedTypeByName("RepeatedGroup");
+      } else {
+        this.optionalGroup =
+          file.findMessageTypeByName("OptionalGroup_extension");
+        this.repeatedGroup =
+          file.findMessageTypeByName("RepeatedGroup_extension");
+      }
+      this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
+      this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
+      this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+      this.publicImportMessage = publicImportFile.findMessageTypeByName(
+          "PublicImportMessage");
+
+      this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
+      this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
+      this.importEnum = importFile.findEnumTypeByName("ImportEnum");
+
+      Assert.assertNotNull(optionalGroup );
+      Assert.assertNotNull(repeatedGroup );
+      Assert.assertNotNull(nestedMessage );
+      Assert.assertNotNull(foreignMessage);
+      Assert.assertNotNull(importMessage );
+      Assert.assertNotNull(nestedEnum    );
+      Assert.assertNotNull(foreignEnum   );
+      Assert.assertNotNull(importEnum    );
+
+      this.nestedB  = nestedMessage .findFieldByName("bb");
+      this.foreignC = foreignMessage.findFieldByName("c");
+      this.importD  = importMessage .findFieldByName("d");
+      this.importE  = publicImportMessage.findFieldByName("e");
+      this.nestedFoo = nestedEnum.findValueByName("FOO");
+      this.nestedBar = nestedEnum.findValueByName("BAR");
+      this.nestedBaz = nestedEnum.findValueByName("BAZ");
+      this.foreignFoo = foreignEnum.findValueByName("FOREIGN_FOO");
+      this.foreignBar = foreignEnum.findValueByName("FOREIGN_BAR");
+      this.foreignBaz = foreignEnum.findValueByName("FOREIGN_BAZ");
+      this.importFoo = importEnum.findValueByName("IMPORT_FOO");
+      this.importBar = importEnum.findValueByName("IMPORT_BAR");
+      this.importBaz = importEnum.findValueByName("IMPORT_BAZ");
+
+      this.groupA = optionalGroup.findFieldByName("a");
+      this.repeatedGroupA = repeatedGroup.findFieldByName("a");
+
+      Assert.assertNotNull(groupA        );
+      Assert.assertNotNull(repeatedGroupA);
+      Assert.assertNotNull(nestedB       );
+      Assert.assertNotNull(foreignC      );
+      Assert.assertNotNull(importD       );
+      Assert.assertNotNull(importE       );
+      Assert.assertNotNull(nestedFoo     );
+      Assert.assertNotNull(nestedBar     );
+      Assert.assertNotNull(nestedBaz     );
+      Assert.assertNotNull(foreignFoo    );
+      Assert.assertNotNull(foreignBar    );
+      Assert.assertNotNull(foreignBaz    );
+      Assert.assertNotNull(importFoo     );
+      Assert.assertNotNull(importBar     );
+      Assert.assertNotNull(importBaz     );
+    }
+
+    /**
+     * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+     */
+    private Descriptors.FieldDescriptor f(String name) {
+      Descriptors.FieldDescriptor result;
+      if (extensionRegistry == null) {
+        result = baseDescriptor.findFieldByName(name);
+      } else {
+        result = file.findExtensionByName(name + "_extension");
+      }
+      Assert.assertNotNull(result);
+      return result;
+    }
+
+    /**
+     * Calls {@code parent.newBuilderForField()} or uses the
+     * {@code ExtensionRegistry} to find an appropriate builder, depending
+     * on what type is being tested.
+     */
+    private Message.Builder newBuilderForField(
+        Message.Builder parent, Descriptors.FieldDescriptor field) {
+      if (extensionRegistry == null) {
+        return parent.newBuilderForField(field);
+      } else {
+        ExtensionRegistry.ExtensionInfo extension =
+          extensionRegistry.findImmutableExtensionByNumber(
+              field.getContainingType(), field.getNumber());
+        Assert.assertNotNull(extension);
+        Assert.assertNotNull(extension.defaultInstance);
+        return extension.defaultInstance.newBuilderForType();
+      }
+    }
+
+    // -------------------------------------------------------------------
+
+    /**
+     * Set every field of {@code message} to the values expected by
+     * {@code assertAllFieldsSet()}, using the {@link Message.Builder}
+     * reflection interface.
+     */
+    void setAllFieldsViaReflection(Message.Builder message) {
+      message.setField(f("optional_int32"   ), 101 );
+      message.setField(f("optional_int64"   ), 102L);
+      message.setField(f("optional_uint32"  ), 103 );
+      message.setField(f("optional_uint64"  ), 104L);
+      message.setField(f("optional_sint32"  ), 105 );
+      message.setField(f("optional_sint64"  ), 106L);
+      message.setField(f("optional_fixed32" ), 107 );
+      message.setField(f("optional_fixed64" ), 108L);
+      message.setField(f("optional_sfixed32"), 109 );
+      message.setField(f("optional_sfixed64"), 110L);
+      message.setField(f("optional_float"   ), 111F);
+      message.setField(f("optional_double"  ), 112D);
+      message.setField(f("optional_bool"    ), true);
+      message.setField(f("optional_string"  ), "115");
+      message.setField(f("optional_bytes"   ), toBytes("116"));
+
+      message.setField(f("optionalgroup"),
+        newBuilderForField(message, f("optionalgroup"))
+               .setField(groupA, 117).build());
+      message.setField(f("optional_nested_message"),
+        newBuilderForField(message, f("optional_nested_message"))
+               .setField(nestedB, 118).build());
+      message.setField(f("optional_foreign_message"),
+        newBuilderForField(message, f("optional_foreign_message"))
+               .setField(foreignC, 119).build());
+      message.setField(f("optional_import_message"),
+        newBuilderForField(message, f("optional_import_message"))
+               .setField(importD, 120).build());
+      message.setField(f("optional_public_import_message"),
+        newBuilderForField(message, f("optional_public_import_message"))
+               .setField(importE, 126).build());
+      message.setField(f("optional_lazy_message"),
+        newBuilderForField(message, f("optional_lazy_message"))
+               .setField(nestedB, 127).build());
+
+      message.setField(f("optional_nested_enum" ),  nestedBaz);
+      message.setField(f("optional_foreign_enum"), foreignBaz);
+      message.setField(f("optional_import_enum" ),  importBaz);
+
+      message.setField(f("optional_string_piece" ), "124");
+      message.setField(f("optional_cord" ), "125");
+
+      // -----------------------------------------------------------------
+
+      message.addRepeatedField(f("repeated_int32"   ), 201 );
+      message.addRepeatedField(f("repeated_int64"   ), 202L);
+      message.addRepeatedField(f("repeated_uint32"  ), 203 );
+      message.addRepeatedField(f("repeated_uint64"  ), 204L);
+      message.addRepeatedField(f("repeated_sint32"  ), 205 );
+      message.addRepeatedField(f("repeated_sint64"  ), 206L);
+      message.addRepeatedField(f("repeated_fixed32" ), 207 );
+      message.addRepeatedField(f("repeated_fixed64" ), 208L);
+      message.addRepeatedField(f("repeated_sfixed32"), 209 );
+      message.addRepeatedField(f("repeated_sfixed64"), 210L);
+      message.addRepeatedField(f("repeated_float"   ), 211F);
+      message.addRepeatedField(f("repeated_double"  ), 212D);
+      message.addRepeatedField(f("repeated_bool"    ), true);
+      message.addRepeatedField(f("repeated_string"  ), "215");
+      message.addRepeatedField(f("repeated_bytes"   ), toBytes("216"));
+
+      message.addRepeatedField(f("repeatedgroup"),
+        newBuilderForField(message, f("repeatedgroup"))
+               .setField(repeatedGroupA, 217).build());
+      message.addRepeatedField(f("repeated_nested_message"),
+        newBuilderForField(message, f("repeated_nested_message"))
+               .setField(nestedB, 218).build());
+      message.addRepeatedField(f("repeated_foreign_message"),
+        newBuilderForField(message, f("repeated_foreign_message"))
+               .setField(foreignC, 219).build());
+      message.addRepeatedField(f("repeated_import_message"),
+        newBuilderForField(message, f("repeated_import_message"))
+               .setField(importD, 220).build());
+      message.addRepeatedField(f("repeated_lazy_message"),
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 227).build());
+
+      message.addRepeatedField(f("repeated_nested_enum" ),  nestedBar);
+      message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
+      message.addRepeatedField(f("repeated_import_enum" ),  importBar);
+
+      message.addRepeatedField(f("repeated_string_piece" ), "224");
+      message.addRepeatedField(f("repeated_cord" ), "225");
+
+      // Add a second one of each field.
+      message.addRepeatedField(f("repeated_int32"   ), 301 );
+      message.addRepeatedField(f("repeated_int64"   ), 302L);
+      message.addRepeatedField(f("repeated_uint32"  ), 303 );
+      message.addRepeatedField(f("repeated_uint64"  ), 304L);
+      message.addRepeatedField(f("repeated_sint32"  ), 305 );
+      message.addRepeatedField(f("repeated_sint64"  ), 306L);
+      message.addRepeatedField(f("repeated_fixed32" ), 307 );
+      message.addRepeatedField(f("repeated_fixed64" ), 308L);
+      message.addRepeatedField(f("repeated_sfixed32"), 309 );
+      message.addRepeatedField(f("repeated_sfixed64"), 310L);
+      message.addRepeatedField(f("repeated_float"   ), 311F);
+      message.addRepeatedField(f("repeated_double"  ), 312D);
+      message.addRepeatedField(f("repeated_bool"    ), false);
+      message.addRepeatedField(f("repeated_string"  ), "315");
+      message.addRepeatedField(f("repeated_bytes"   ), toBytes("316"));
+
+      message.addRepeatedField(f("repeatedgroup"),
+        newBuilderForField(message, f("repeatedgroup"))
+               .setField(repeatedGroupA, 317).build());
+      message.addRepeatedField(f("repeated_nested_message"),
+        newBuilderForField(message, f("repeated_nested_message"))
+               .setField(nestedB, 318).build());
+      message.addRepeatedField(f("repeated_foreign_message"),
+        newBuilderForField(message, f("repeated_foreign_message"))
+               .setField(foreignC, 319).build());
+      message.addRepeatedField(f("repeated_import_message"),
+        newBuilderForField(message, f("repeated_import_message"))
+               .setField(importD, 320).build());
+      message.addRepeatedField(f("repeated_lazy_message"),
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 327).build());
+
+      message.addRepeatedField(f("repeated_nested_enum" ),  nestedBaz);
+      message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
+      message.addRepeatedField(f("repeated_import_enum" ),  importBaz);
+
+      message.addRepeatedField(f("repeated_string_piece" ), "324");
+      message.addRepeatedField(f("repeated_cord" ), "325");
+
+      // -----------------------------------------------------------------
+
+      message.setField(f("default_int32"   ), 401 );
+      message.setField(f("default_int64"   ), 402L);
+      message.setField(f("default_uint32"  ), 403 );
+      message.setField(f("default_uint64"  ), 404L);
+      message.setField(f("default_sint32"  ), 405 );
+      message.setField(f("default_sint64"  ), 406L);
+      message.setField(f("default_fixed32" ), 407 );
+      message.setField(f("default_fixed64" ), 408L);
+      message.setField(f("default_sfixed32"), 409 );
+      message.setField(f("default_sfixed64"), 410L);
+      message.setField(f("default_float"   ), 411F);
+      message.setField(f("default_double"  ), 412D);
+      message.setField(f("default_bool"    ), false);
+      message.setField(f("default_string"  ), "415");
+      message.setField(f("default_bytes"   ), toBytes("416"));
+
+      message.setField(f("default_nested_enum" ),  nestedFoo);
+      message.setField(f("default_foreign_enum"), foreignFoo);
+      message.setField(f("default_import_enum" ),  importFoo);
+
+      message.setField(f("default_string_piece" ), "424");
+      message.setField(f("default_cord" ), "425");
+
+      message.setField(f("oneof_uint32" ), 601);
+      message.setField(f("oneof_nested_message"),
+        newBuilderForField(message, f("oneof_nested_message"))
+          .setField(nestedB, 602).build());
+      message.setField(f("oneof_string" ), "603");
+      message.setField(f("oneof_bytes" ), toBytes("604"));
+    }
+
+    // -------------------------------------------------------------------
+
+    /**
+     * Modify the repeated fields of {@code message} to contain the values
+     * expected by {@code assertRepeatedFieldsModified()}, using the
+     * {@link Message.Builder} reflection interface.
+     */
+    void modifyRepeatedFieldsViaReflection(Message.Builder message) {
+      message.setRepeatedField(f("repeated_int32"   ), 1, 501 );
+      message.setRepeatedField(f("repeated_int64"   ), 1, 502L);
+      message.setRepeatedField(f("repeated_uint32"  ), 1, 503 );
+      message.setRepeatedField(f("repeated_uint64"  ), 1, 504L);
+      message.setRepeatedField(f("repeated_sint32"  ), 1, 505 );
+      message.setRepeatedField(f("repeated_sint64"  ), 1, 506L);
+      message.setRepeatedField(f("repeated_fixed32" ), 1, 507 );
+      message.setRepeatedField(f("repeated_fixed64" ), 1, 508L);
+      message.setRepeatedField(f("repeated_sfixed32"), 1, 509 );
+      message.setRepeatedField(f("repeated_sfixed64"), 1, 510L);
+      message.setRepeatedField(f("repeated_float"   ), 1, 511F);
+      message.setRepeatedField(f("repeated_double"  ), 1, 512D);
+      message.setRepeatedField(f("repeated_bool"    ), 1, true);
+      message.setRepeatedField(f("repeated_string"  ), 1, "515");
+      message.setRepeatedField(f("repeated_bytes"   ), 1, toBytes("516"));
+
+      message.setRepeatedField(f("repeatedgroup"), 1,
+        newBuilderForField(message, f("repeatedgroup"))
+               .setField(repeatedGroupA, 517).build());
+      message.setRepeatedField(f("repeated_nested_message"), 1,
+        newBuilderForField(message, f("repeated_nested_message"))
+               .setField(nestedB, 518).build());
+      message.setRepeatedField(f("repeated_foreign_message"), 1,
+        newBuilderForField(message, f("repeated_foreign_message"))
+               .setField(foreignC, 519).build());
+      message.setRepeatedField(f("repeated_import_message"), 1,
+        newBuilderForField(message, f("repeated_import_message"))
+               .setField(importD, 520).build());
+      message.setRepeatedField(f("repeated_lazy_message"), 1,
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 527).build());
+
+      message.setRepeatedField(f("repeated_nested_enum" ), 1,  nestedFoo);
+      message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
+      message.setRepeatedField(f("repeated_import_enum" ), 1,  importFoo);
+
+      message.setRepeatedField(f("repeated_string_piece"), 1, "524");
+      message.setRepeatedField(f("repeated_cord"), 1, "525");
+    }
+
+    // -------------------------------------------------------------------
+
+    /**
+     * Assert (using {@code junit.framework.Assert}} that all fields of
+     * {@code message} are set to the values assigned by {@code setAllFields},
+     * using the {@link Message} reflection interface.
+     */
+    public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
+      Assert.assertTrue(message.hasField(f("optional_int32"   )));
+      Assert.assertTrue(message.hasField(f("optional_int64"   )));
+      Assert.assertTrue(message.hasField(f("optional_uint32"  )));
+      Assert.assertTrue(message.hasField(f("optional_uint64"  )));
+      Assert.assertTrue(message.hasField(f("optional_sint32"  )));
+      Assert.assertTrue(message.hasField(f("optional_sint64"  )));
+      Assert.assertTrue(message.hasField(f("optional_fixed32" )));
+      Assert.assertTrue(message.hasField(f("optional_fixed64" )));
+      Assert.assertTrue(message.hasField(f("optional_sfixed32")));
+      Assert.assertTrue(message.hasField(f("optional_sfixed64")));
+      Assert.assertTrue(message.hasField(f("optional_float"   )));
+      Assert.assertTrue(message.hasField(f("optional_double"  )));
+      Assert.assertTrue(message.hasField(f("optional_bool"    )));
+      Assert.assertTrue(message.hasField(f("optional_string"  )));
+      Assert.assertTrue(message.hasField(f("optional_bytes"   )));
+
+      Assert.assertTrue(message.hasField(f("optionalgroup"           )));
+      Assert.assertTrue(message.hasField(f("optional_nested_message" )));
+      Assert.assertTrue(message.hasField(f("optional_foreign_message")));
+      Assert.assertTrue(message.hasField(f("optional_import_message" )));
+
+      Assert.assertTrue(
+        ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+      Assert.assertTrue(
+        ((Message)message.getField(f("optional_nested_message")))
+                         .hasField(nestedB));
+      Assert.assertTrue(
+        ((Message)message.getField(f("optional_foreign_message")))
+                         .hasField(foreignC));
+      Assert.assertTrue(
+        ((Message)message.getField(f("optional_import_message")))
+                         .hasField(importD));
+
+      Assert.assertTrue(message.hasField(f("optional_nested_enum" )));
+      Assert.assertTrue(message.hasField(f("optional_foreign_enum")));
+      Assert.assertTrue(message.hasField(f("optional_import_enum" )));
+
+      Assert.assertTrue(message.hasField(f("optional_string_piece")));
+      Assert.assertTrue(message.hasField(f("optional_cord")));
+
+      Assert.assertEquals(101  , message.getField(f("optional_int32"   )));
+      Assert.assertEquals(102L , message.getField(f("optional_int64"   )));
+      Assert.assertEquals(103  , message.getField(f("optional_uint32"  )));
+      Assert.assertEquals(104L , message.getField(f("optional_uint64"  )));
+      Assert.assertEquals(105  , message.getField(f("optional_sint32"  )));
+      Assert.assertEquals(106L , message.getField(f("optional_sint64"  )));
+      Assert.assertEquals(107  , message.getField(f("optional_fixed32" )));
+      Assert.assertEquals(108L , message.getField(f("optional_fixed64" )));
+      Assert.assertEquals(109  , message.getField(f("optional_sfixed32")));
+      Assert.assertEquals(110L , message.getField(f("optional_sfixed64")));
+      Assert.assertEquals(111F , message.getField(f("optional_float"   )));
+      Assert.assertEquals(112D , message.getField(f("optional_double"  )));
+      Assert.assertEquals(true , message.getField(f("optional_bool"    )));
+      Assert.assertEquals("115", message.getField(f("optional_string"  )));
+      Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes")));
+
+      Assert.assertEquals(117,
+        ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+      Assert.assertEquals(118,
+        ((Message)message.getField(f("optional_nested_message")))
+                         .getField(nestedB));
+      Assert.assertEquals(119,
+        ((Message)message.getField(f("optional_foreign_message")))
+                         .getField(foreignC));
+      Assert.assertEquals(120,
+        ((Message)message.getField(f("optional_import_message")))
+                         .getField(importD));
+      Assert.assertEquals(126,
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .getField(importE));
+      Assert.assertEquals(127,
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .getField(nestedB));
+
+      Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
+      Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
+      Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" )));
+
+      Assert.assertEquals("124", message.getField(f("optional_string_piece")));
+      Assert.assertEquals("125", message.getField(f("optional_cord")));
+
+      // -----------------------------------------------------------------
+
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"    )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"   )));
+
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"           )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
+
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+      Assert.assertEquals(201  , message.getRepeatedField(f("repeated_int32"   ), 0));
+      Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64"   ), 0));
+      Assert.assertEquals(203  , message.getRepeatedField(f("repeated_uint32"  ), 0));
+      Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64"  ), 0));
+      Assert.assertEquals(205  , message.getRepeatedField(f("repeated_sint32"  ), 0));
+      Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64"  ), 0));
+      Assert.assertEquals(207  , message.getRepeatedField(f("repeated_fixed32" ), 0));
+      Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+      Assert.assertEquals(209  , message.getRepeatedField(f("repeated_sfixed32"), 0));
+      Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+      Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float"   ), 0));
+      Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double"  ), 0));
+      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 0));
+      Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"  ), 0));
+      Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+      Assert.assertEquals(217,
+        ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+                         .getField(repeatedGroupA));
+      Assert.assertEquals(218,
+        ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+                         .getField(nestedB));
+      Assert.assertEquals(219,
+        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+                         .getField(foreignC));
+      Assert.assertEquals(220,
+        ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+                         .getField(importD));
+      Assert.assertEquals(227,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+                         .getField(nestedB));
+
+      Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+      Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+      Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+      Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+      Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+      Assert.assertEquals(301  , message.getRepeatedField(f("repeated_int32"   ), 1));
+      Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64"   ), 1));
+      Assert.assertEquals(303  , message.getRepeatedField(f("repeated_uint32"  ), 1));
+      Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64"  ), 1));
+      Assert.assertEquals(305  , message.getRepeatedField(f("repeated_sint32"  ), 1));
+      Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64"  ), 1));
+      Assert.assertEquals(307  , message.getRepeatedField(f("repeated_fixed32" ), 1));
+      Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+      Assert.assertEquals(309  , message.getRepeatedField(f("repeated_sfixed32"), 1));
+      Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+      Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float"   ), 1));
+      Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double"  ), 1));
+      Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool"    ), 1));
+      Assert.assertEquals("315", message.getRepeatedField(f("repeated_string"  ), 1));
+      Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+      Assert.assertEquals(317,
+        ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+                         .getField(repeatedGroupA));
+      Assert.assertEquals(318,
+        ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+                         .getField(nestedB));
+      Assert.assertEquals(319,
+        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+                         .getField(foreignC));
+      Assert.assertEquals(320,
+        ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+                         .getField(importD));
+      Assert.assertEquals(327,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+                         .getField(nestedB));
+
+      Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
+      Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
+      Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+      Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1));
+      Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1));
+
+      // -----------------------------------------------------------------
+
+      Assert.assertTrue(message.hasField(f("default_int32"   )));
+      Assert.assertTrue(message.hasField(f("default_int64"   )));
+      Assert.assertTrue(message.hasField(f("default_uint32"  )));
+      Assert.assertTrue(message.hasField(f("default_uint64"  )));
+      Assert.assertTrue(message.hasField(f("default_sint32"  )));
+      Assert.assertTrue(message.hasField(f("default_sint64"  )));
+      Assert.assertTrue(message.hasField(f("default_fixed32" )));
+      Assert.assertTrue(message.hasField(f("default_fixed64" )));
+      Assert.assertTrue(message.hasField(f("default_sfixed32")));
+      Assert.assertTrue(message.hasField(f("default_sfixed64")));
+      Assert.assertTrue(message.hasField(f("default_float"   )));
+      Assert.assertTrue(message.hasField(f("default_double"  )));
+      Assert.assertTrue(message.hasField(f("default_bool"    )));
+      Assert.assertTrue(message.hasField(f("default_string"  )));
+      Assert.assertTrue(message.hasField(f("default_bytes"   )));
+
+      Assert.assertTrue(message.hasField(f("default_nested_enum" )));
+      Assert.assertTrue(message.hasField(f("default_foreign_enum")));
+      Assert.assertTrue(message.hasField(f("default_import_enum" )));
+
+      Assert.assertTrue(message.hasField(f("default_string_piece")));
+      Assert.assertTrue(message.hasField(f("default_cord")));
+
+      Assert.assertEquals(401  , message.getField(f("default_int32"   )));
+      Assert.assertEquals(402L , message.getField(f("default_int64"   )));
+      Assert.assertEquals(403  , message.getField(f("default_uint32"  )));
+      Assert.assertEquals(404L , message.getField(f("default_uint64"  )));
+      Assert.assertEquals(405  , message.getField(f("default_sint32"  )));
+      Assert.assertEquals(406L , message.getField(f("default_sint64"  )));
+      Assert.assertEquals(407  , message.getField(f("default_fixed32" )));
+      Assert.assertEquals(408L , message.getField(f("default_fixed64" )));
+      Assert.assertEquals(409  , message.getField(f("default_sfixed32")));
+      Assert.assertEquals(410L , message.getField(f("default_sfixed64")));
+      Assert.assertEquals(411F , message.getField(f("default_float"   )));
+      Assert.assertEquals(412D , message.getField(f("default_double"  )));
+      Assert.assertEquals(false, message.getField(f("default_bool"    )));
+      Assert.assertEquals("415", message.getField(f("default_string"  )));
+      Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes")));
+
+      Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" )));
+      Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum")));
+      Assert.assertEquals( importFoo, message.getField(f("default_import_enum" )));
+
+      Assert.assertEquals("424", message.getField(f("default_string_piece")));
+      Assert.assertEquals("425", message.getField(f("default_cord")));
+
+      Assert.assertTrue(message.hasField(f("oneof_bytes")));
+      Assert.assertEquals(toBytes("604"), message.getField(f("oneof_bytes")));
+
+      if (extensionRegistry == null) {
+        Assert.assertFalse(message.hasField(f("oneof_uint32")));
+        Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+        Assert.assertFalse(message.hasField(f("oneof_string")));
+      } else {
+        Assert.assertTrue(message.hasField(f("oneof_uint32")));
+        Assert.assertTrue(message.hasField(f("oneof_nested_message")));
+        Assert.assertTrue(message.hasField(f("oneof_string")));
+        Assert.assertEquals(601, message.getField(f("oneof_uint32")));
+        Assert.assertEquals(602,
+            ((MessageOrBuilder) message.getField(f("oneof_nested_message")))
+            .getField(nestedB));
+        Assert.assertEquals("603", message.getField(f("oneof_string")));
+      }
+    }
+
+    // -------------------------------------------------------------------
+
+    /**
+     * Assert (using {@code junit.framework.Assert}} that all fields of
+     * {@code message} are cleared, and that getting the fields returns their
+     * default values, using the {@link Message} reflection interface.
+     */
+    public void assertClearViaReflection(MessageOrBuilder message) {
+      // has_blah() should initially be false for all optional fields.
+      Assert.assertFalse(message.hasField(f("optional_int32"   )));
+      Assert.assertFalse(message.hasField(f("optional_int64"   )));
+      Assert.assertFalse(message.hasField(f("optional_uint32"  )));
+      Assert.assertFalse(message.hasField(f("optional_uint64"  )));
+      Assert.assertFalse(message.hasField(f("optional_sint32"  )));
+      Assert.assertFalse(message.hasField(f("optional_sint64"  )));
+      Assert.assertFalse(message.hasField(f("optional_fixed32" )));
+      Assert.assertFalse(message.hasField(f("optional_fixed64" )));
+      Assert.assertFalse(message.hasField(f("optional_sfixed32")));
+      Assert.assertFalse(message.hasField(f("optional_sfixed64")));
+      Assert.assertFalse(message.hasField(f("optional_float"   )));
+      Assert.assertFalse(message.hasField(f("optional_double"  )));
+      Assert.assertFalse(message.hasField(f("optional_bool"    )));
+      Assert.assertFalse(message.hasField(f("optional_string"  )));
+      Assert.assertFalse(message.hasField(f("optional_bytes"   )));
+
+      Assert.assertFalse(message.hasField(f("optionalgroup"           )));
+      Assert.assertFalse(message.hasField(f("optional_nested_message" )));
+      Assert.assertFalse(message.hasField(f("optional_foreign_message")));
+      Assert.assertFalse(message.hasField(f("optional_import_message" )));
+
+      Assert.assertFalse(message.hasField(f("optional_nested_enum" )));
+      Assert.assertFalse(message.hasField(f("optional_foreign_enum")));
+      Assert.assertFalse(message.hasField(f("optional_import_enum" )));
+
+      Assert.assertFalse(message.hasField(f("optional_string_piece")));
+      Assert.assertFalse(message.hasField(f("optional_cord")));
+
+      // Optional fields without defaults are set to zero or something like it.
+      Assert.assertEquals(0    , message.getField(f("optional_int32"   )));
+      Assert.assertEquals(0L   , message.getField(f("optional_int64"   )));
+      Assert.assertEquals(0    , message.getField(f("optional_uint32"  )));
+      Assert.assertEquals(0L   , message.getField(f("optional_uint64"  )));
+      Assert.assertEquals(0    , message.getField(f("optional_sint32"  )));
+      Assert.assertEquals(0L   , message.getField(f("optional_sint64"  )));
+      Assert.assertEquals(0    , message.getField(f("optional_fixed32" )));
+      Assert.assertEquals(0L   , message.getField(f("optional_fixed64" )));
+      Assert.assertEquals(0    , message.getField(f("optional_sfixed32")));
+      Assert.assertEquals(0L   , message.getField(f("optional_sfixed64")));
+      Assert.assertEquals(0F   , message.getField(f("optional_float"   )));
+      Assert.assertEquals(0D   , message.getField(f("optional_double"  )));
+      Assert.assertEquals(false, message.getField(f("optional_bool"    )));
+      Assert.assertEquals(""   , message.getField(f("optional_string"  )));
+      Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes")));
+
+      // Embedded messages should also be clear.
+      Assert.assertFalse(
+        ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_nested_message")))
+                         .hasField(nestedB));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_foreign_message")))
+                         .hasField(foreignC));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_import_message")))
+                         .hasField(importD));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .hasField(importE));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .hasField(nestedB));
+
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_nested_message")))
+                         .getField(nestedB));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_foreign_message")))
+                         .getField(foreignC));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_import_message")))
+                         .getField(importD));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .getField(importE));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .getField(nestedB));
+
+      // Enums without defaults are set to the first value in the enum.
+      Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
+      Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum")));
+      Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" )));
+
+      Assert.assertEquals("", message.getField(f("optional_string_piece")));
+      Assert.assertEquals("", message.getField(f("optional_cord")));
+
+      // Repeated fields are empty.
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32"   )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64"   )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float"   )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool"    )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string"  )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes"   )));
+
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup"           )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
+
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece")));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord")));
+
+      // has_blah() should also be false for all default fields.
+      Assert.assertFalse(message.hasField(f("default_int32"   )));
+      Assert.assertFalse(message.hasField(f("default_int64"   )));
+      Assert.assertFalse(message.hasField(f("default_uint32"  )));
+      Assert.assertFalse(message.hasField(f("default_uint64"  )));
+      Assert.assertFalse(message.hasField(f("default_sint32"  )));
+      Assert.assertFalse(message.hasField(f("default_sint64"  )));
+      Assert.assertFalse(message.hasField(f("default_fixed32" )));
+      Assert.assertFalse(message.hasField(f("default_fixed64" )));
+      Assert.assertFalse(message.hasField(f("default_sfixed32")));
+      Assert.assertFalse(message.hasField(f("default_sfixed64")));
+      Assert.assertFalse(message.hasField(f("default_float"   )));
+      Assert.assertFalse(message.hasField(f("default_double"  )));
+      Assert.assertFalse(message.hasField(f("default_bool"    )));
+      Assert.assertFalse(message.hasField(f("default_string"  )));
+      Assert.assertFalse(message.hasField(f("default_bytes"   )));
+
+      Assert.assertFalse(message.hasField(f("default_nested_enum" )));
+      Assert.assertFalse(message.hasField(f("default_foreign_enum")));
+      Assert.assertFalse(message.hasField(f("default_import_enum" )));
+
+      Assert.assertFalse(message.hasField(f("default_string_piece" )));
+      Assert.assertFalse(message.hasField(f("default_cord" )));
+
+      // Fields with defaults have their default values (duh).
+      Assert.assertEquals( 41    , message.getField(f("default_int32"   )));
+      Assert.assertEquals( 42L   , message.getField(f("default_int64"   )));
+      Assert.assertEquals( 43    , message.getField(f("default_uint32"  )));
+      Assert.assertEquals( 44L   , message.getField(f("default_uint64"  )));
+      Assert.assertEquals(-45    , message.getField(f("default_sint32"  )));
+      Assert.assertEquals( 46L   , message.getField(f("default_sint64"  )));
+      Assert.assertEquals( 47    , message.getField(f("default_fixed32" )));
+      Assert.assertEquals( 48L   , message.getField(f("default_fixed64" )));
+      Assert.assertEquals( 49    , message.getField(f("default_sfixed32")));
+      Assert.assertEquals(-50L   , message.getField(f("default_sfixed64")));
+      Assert.assertEquals( 51.5F , message.getField(f("default_float"   )));
+      Assert.assertEquals( 52e3D , message.getField(f("default_double"  )));
+      Assert.assertEquals(true   , message.getField(f("default_bool"    )));
+      Assert.assertEquals("hello", message.getField(f("default_string"  )));
+      Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes")));
+
+      Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" )));
+      Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum")));
+      Assert.assertEquals( importBar, message.getField(f("default_import_enum" )));
+
+      Assert.assertEquals("abc", message.getField(f("default_string_piece")));
+      Assert.assertEquals("123", message.getField(f("default_cord")));
+
+      Assert.assertFalse(message.hasField(f("oneof_uint32")));
+      Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+      Assert.assertFalse(message.hasField(f("oneof_string")));
+      Assert.assertFalse(message.hasField(f("oneof_bytes")));
+
+      Assert.assertEquals(0, message.getField(f("oneof_uint32")));
+      Assert.assertEquals("", message.getField(f("oneof_string")));
+      Assert.assertEquals(toBytes(""), message.getField(f("oneof_bytes")));
+    }
+
+
+    // ---------------------------------------------------------------
+
+    public void assertRepeatedFieldsModifiedViaReflection(
+        MessageOrBuilder message) {
+      // ModifyRepeatedFields only sets the second repeated element of each
+      // field.  In addition to verifying this, we also verify that the first
+      // element and size were *not* modified.
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"    )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"   )));
+
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"           )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
+
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+      Assert.assertEquals(201  , message.getRepeatedField(f("repeated_int32"   ), 0));
+      Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64"   ), 0));
+      Assert.assertEquals(203  , message.getRepeatedField(f("repeated_uint32"  ), 0));
+      Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64"  ), 0));
+      Assert.assertEquals(205  , message.getRepeatedField(f("repeated_sint32"  ), 0));
+      Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64"  ), 0));
+      Assert.assertEquals(207  , message.getRepeatedField(f("repeated_fixed32" ), 0));
+      Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+      Assert.assertEquals(209  , message.getRepeatedField(f("repeated_sfixed32"), 0));
+      Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+      Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float"   ), 0));
+      Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double"  ), 0));
+      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 0));
+      Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"  ), 0));
+      Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+      Assert.assertEquals(217,
+        ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+                         .getField(repeatedGroupA));
+      Assert.assertEquals(218,
+        ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+                         .getField(nestedB));
+      Assert.assertEquals(219,
+        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+                         .getField(foreignC));
+      Assert.assertEquals(220,
+        ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+                         .getField(importD));
+      Assert.assertEquals(227,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+                         .getField(nestedB));
+
+      Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+      Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+      Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+      Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+      Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+      Assert.assertEquals(501  , message.getRepeatedField(f("repeated_int32"   ), 1));
+      Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64"   ), 1));
+      Assert.assertEquals(503  , message.getRepeatedField(f("repeated_uint32"  ), 1));
+      Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64"  ), 1));
+      Assert.assertEquals(505  , message.getRepeatedField(f("repeated_sint32"  ), 1));
+      Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64"  ), 1));
+      Assert.assertEquals(507  , message.getRepeatedField(f("repeated_fixed32" ), 1));
+      Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+      Assert.assertEquals(509  , message.getRepeatedField(f("repeated_sfixed32"), 1));
+      Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+      Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float"   ), 1));
+      Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double"  ), 1));
+      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 1));
+      Assert.assertEquals("515", message.getRepeatedField(f("repeated_string"  ), 1));
+      Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+      Assert.assertEquals(517,
+        ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+                         .getField(repeatedGroupA));
+      Assert.assertEquals(518,
+        ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+                         .getField(nestedB));
+      Assert.assertEquals(519,
+        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+                         .getField(foreignC));
+      Assert.assertEquals(520,
+        ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+                         .getField(importD));
+      Assert.assertEquals(527,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+                         .getField(nestedB));
+
+      Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
+      Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
+      Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+      Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
+      Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
+    }
+
+    public void setPackedFieldsViaReflection(Message.Builder message) {
+      message.addRepeatedField(f("packed_int32"   ), 601 );
+      message.addRepeatedField(f("packed_int64"   ), 602L);
+      message.addRepeatedField(f("packed_uint32"  ), 603 );
+      message.addRepeatedField(f("packed_uint64"  ), 604L);
+      message.addRepeatedField(f("packed_sint32"  ), 605 );
+      message.addRepeatedField(f("packed_sint64"  ), 606L);
+      message.addRepeatedField(f("packed_fixed32" ), 607 );
+      message.addRepeatedField(f("packed_fixed64" ), 608L);
+      message.addRepeatedField(f("packed_sfixed32"), 609 );
+      message.addRepeatedField(f("packed_sfixed64"), 610L);
+      message.addRepeatedField(f("packed_float"   ), 611F);
+      message.addRepeatedField(f("packed_double"  ), 612D);
+      message.addRepeatedField(f("packed_bool"    ), true);
+      message.addRepeatedField(f("packed_enum" ),  foreignBar);
+      // Add a second one of each field.
+      message.addRepeatedField(f("packed_int32"   ), 701 );
+      message.addRepeatedField(f("packed_int64"   ), 702L);
+      message.addRepeatedField(f("packed_uint32"  ), 703 );
+      message.addRepeatedField(f("packed_uint64"  ), 704L);
+      message.addRepeatedField(f("packed_sint32"  ), 705 );
+      message.addRepeatedField(f("packed_sint64"  ), 706L);
+      message.addRepeatedField(f("packed_fixed32" ), 707 );
+      message.addRepeatedField(f("packed_fixed64" ), 708L);
+      message.addRepeatedField(f("packed_sfixed32"), 709 );
+      message.addRepeatedField(f("packed_sfixed64"), 710L);
+      message.addRepeatedField(f("packed_float"   ), 711F);
+      message.addRepeatedField(f("packed_double"  ), 712D);
+      message.addRepeatedField(f("packed_bool"    ), false);
+      message.addRepeatedField(f("packed_enum" ),  foreignBaz);
+    }
+
+    public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float"   )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double"  )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool"    )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum"   )));
+      Assert.assertEquals(601  , message.getRepeatedField(f("packed_int32"   ), 0));
+      Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64"   ), 0));
+      Assert.assertEquals(603  , message.getRepeatedField(f("packed_uint32"  ), 0));
+      Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64"  ), 0));
+      Assert.assertEquals(605  , message.getRepeatedField(f("packed_sint32"  ), 0));
+      Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64"  ), 0));
+      Assert.assertEquals(607  , message.getRepeatedField(f("packed_fixed32" ), 0));
+      Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
+      Assert.assertEquals(609  , message.getRepeatedField(f("packed_sfixed32"), 0));
+      Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
+      Assert.assertEquals(611F , message.getRepeatedField(f("packed_float"   ), 0));
+      Assert.assertEquals(612D , message.getRepeatedField(f("packed_double"  ), 0));
+      Assert.assertEquals(true , message.getRepeatedField(f("packed_bool"    ), 0));
+      Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
+      Assert.assertEquals(701  , message.getRepeatedField(f("packed_int32"   ), 1));
+      Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64"   ), 1));
+      Assert.assertEquals(703  , message.getRepeatedField(f("packed_uint32"  ), 1));
+      Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64"  ), 1));
+      Assert.assertEquals(705  , message.getRepeatedField(f("packed_sint32"  ), 1));
+      Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64"  ), 1));
+      Assert.assertEquals(707  , message.getRepeatedField(f("packed_fixed32" ), 1));
+      Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
+      Assert.assertEquals(709  , message.getRepeatedField(f("packed_sfixed32"), 1));
+      Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
+      Assert.assertEquals(711F , message.getRepeatedField(f("packed_float"   ), 1));
+      Assert.assertEquals(712D , message.getRepeatedField(f("packed_double"  ), 1));
+      Assert.assertEquals(false, message.getRepeatedField(f("packed_bool"    ), 1));
+      Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
+    }
+
+    /**
+     * Verifies that the reflection setters for the given.Builder object throw a
+     * NullPointerException if they are passed a null value.  Uses Assert to throw an
+     * appropriate assertion failure, if the condition is not verified.
+     */
+    public void assertReflectionSettersRejectNull(Message.Builder builder)
+        throws Exception {
+      try {
+        builder.setField(f("optional_string"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.setField(f("optional_bytes"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.setField(f("optional_nested_enum"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.setField(f("optional_nested_message"),
+                         (TestAllTypes.NestedMessage) null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.setField(f("optional_nested_message"),
+                         (TestAllTypes.NestedMessage.Builder) null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+
+      try {
+        builder.addRepeatedField(f("repeated_string"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.addRepeatedField(f("repeated_bytes"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.addRepeatedField(f("repeated_nested_enum"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+      try {
+        builder.addRepeatedField(f("repeated_nested_message"), null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+    }
+
+    /**
+     * Verifies that the reflection repeated setters for the given Builder object throw a
+     * NullPointerException if they are passed a null value.  Uses Assert to throw an appropriate
+     * assertion failure, if the condition is not verified.
+     */
+    public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
+        throws Exception {
+      builder.addRepeatedField(f("repeated_string"), "one");
+      try {
+        builder.setRepeatedField(f("repeated_string"), 0, null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+
+      builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
+      try {
+        builder.setRepeatedField(f("repeated_bytes"), 0, null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+
+      builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
+      try {
+        builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+
+      builder.addRepeatedField(
+          f("repeated_nested_message"),
+          TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+      try {
+        builder.setRepeatedField(f("repeated_nested_message"), 0, null);
+        Assert.fail("Exception was not thrown");
+      } catch (NullPointerException e) {
+        // We expect this exception.
+      }
+    }
+  }
+
+  /**
+   * @param filePath The path relative to
+   * {@link #getTestDataDir}.
+   */
+  public static String readTextFromFile(String filePath) {
+    return readBytesFromFile(filePath).toStringUtf8();
+  }
+
+  private static File getTestDataDir() {
+    // Search each parent directory looking for "src/google/protobuf".
+    File ancestor = new File(".");
+    try {
+      ancestor = ancestor.getCanonicalFile();
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Couldn't get canonical name of working directory.", e);
+    }
+    while (ancestor != null && ancestor.exists()) {
+      if (new File(ancestor, "src/google/protobuf").exists()) {
+        return new File(ancestor, "src/google/protobuf/testdata");
+      }
+      ancestor = ancestor.getParentFile();
+    }
+
+    throw new RuntimeException(
+      "Could not find golden files.  This test must be run from within the " +
+      "protobuf source package so that it can read test data files from the " +
+      "C++ source tree.");
+  }
+
+  /**
+   * @param filename The path relative to
+   * {@link #getTestDataDir}.
+   */
+  public static ByteString readBytesFromFile(String filename) {
+    File fullPath = new File(getTestDataDir(), filename);
+    try {
+      RandomAccessFile file = new RandomAccessFile(fullPath, "r");
+      byte[] content = new byte[(int) file.length()];
+      file.readFully(content);
+      return ByteString.copyFrom(content);
+    } catch (IOException e) {
+      // Throw a RuntimeException here so that we can call this function from
+      // static initializers.
+      throw new IllegalArgumentException(
+        "Couldn't read file: " + fullPath.getPath(), e);
+    }
+  }
+
+  /**
+   * Get the bytes of the "golden message".  This is a serialized TestAllTypes
+   * with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
+   * on disk rather than generated dynamically.  The file is actually generated
+   * by C++ code, so testing against it verifies compatibility with C++.
+   */
+  public static ByteString getGoldenMessage() {
+    if (goldenMessage == null) {
+      goldenMessage = readBytesFromFile("golden_message_oneof_implemented");
+    }
+    return goldenMessage;
+  }
+  private static ByteString goldenMessage = null;
+
+  /**
+   * Get the bytes of the "golden packed fields message".  This is a serialized
+   * TestPackedTypes with all fields set as they would be by
+   * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+   * file on disk rather than generated dynamically.  The file is actually
+   * generated by C++ code, so testing against it verifies compatibility with
+   * C++.
+   */
+  public static ByteString getGoldenPackedFieldsMessage() {
+    if (goldenPackedFieldsMessage == null) {
+      goldenPackedFieldsMessage =
+          readBytesFromFile("golden_packed_fields_message");
+    }
+    return goldenPackedFieldsMessage;
+  }
+  private static ByteString goldenPackedFieldsMessage = null;
+
+  /**
+   * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
+   *
+   * @author jonp@google.com (Jon Perlow)
+   */
+  public static class MockBuilderParent
+      implements GeneratedMessage.BuilderParent {
+
+    private int invalidations;
+
+    @Override
+    public void markDirty() {
+      invalidations++;
+    }
+
+    public int getInvalidationCount() {
+      return invalidations;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtilLite.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
new file mode 100644
index 0000000..8f33fa1
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
@@ -0,0 +1,559 @@
+// 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.
+
+package com.google.protobuf;
+
+import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+
+/**
+ * Contains methods for setting fields of {@code TestAllTypesLite}, {@code TestAllExtensionsLite},
+ * and {@code TestPackedExtensionsLite}. This is analogous to the functionality in TestUtil.java but
+ * does not depend on the presence of any non-lite protos.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ */
+public final class TestUtilLite {
+  private TestUtilLite() {}
+
+  /** Helper to convert a String to ByteString. */
+  static ByteString toBytes(String str) {
+    return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+  }
+
+  /**
+   * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypesLite.Builder)}.
+   */
+  public static TestAllTypesLite.Builder getAllLiteSetBuilder() {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+    setAllFields(builder);
+    return builder;
+  }
+
+  /**
+   * Get a {@code TestAllExtensionsLite} with all fields set as they would be by
+   * {@link #setAllExtensions(TestAllExtensionsLite.Builder)}.
+   */
+  public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    setAllExtensions(builder);
+    return builder.build();
+  }
+
+  public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+    TestPackedExtensionsLite.Builder builder = TestPackedExtensionsLite.newBuilder();
+    setPackedExtensions(builder);
+    return builder.build();
+  }
+  
+  /**
+   * Set every field of {@code builder} to the values expected by
+   * {@code assertAllFieldsSet()}.
+   */
+  public static void setAllFields(TestAllTypesLite.Builder builder) {
+    builder.setOptionalInt32   (101);
+    builder.setOptionalInt64   (102);
+    builder.setOptionalUint32  (103);
+    builder.setOptionalUint64  (104);
+    builder.setOptionalSint32  (105);
+    builder.setOptionalSint64  (106);
+    builder.setOptionalFixed32 (107);
+    builder.setOptionalFixed64 (108);
+    builder.setOptionalSfixed32(109);
+    builder.setOptionalSfixed64(110);
+    builder.setOptionalFloat   (111);
+    builder.setOptionalDouble  (112);
+    builder.setOptionalBool    (true);
+    builder.setOptionalString  ("115");
+    builder.setOptionalBytes   (toBytes("116"));
+
+    builder.setOptionalGroup(
+        TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build());
+    builder.setOptionalNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+    builder.setOptionalForeignMessage(
+        ForeignMessageLite.newBuilder().setC(119).build());
+    builder.setOptionalImportMessage(
+        ImportMessageLite.newBuilder().setD(120).build());
+    builder.setOptionalPublicImportMessage(
+        PublicImportMessageLite.newBuilder().setE(126).build());
+    builder.setOptionalLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+    builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+    builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+    builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+    builder.setOptionalStringPiece("124");
+    builder.setOptionalCord("125");
+
+    // -----------------------------------------------------------------
+
+    builder.addRepeatedInt32   (201);
+    builder.addRepeatedInt64   (202);
+    builder.addRepeatedUint32  (203);
+    builder.addRepeatedUint64  (204);
+    builder.addRepeatedSint32  (205);
+    builder.addRepeatedSint64  (206);
+    builder.addRepeatedFixed32 (207);
+    builder.addRepeatedFixed64 (208);
+    builder.addRepeatedSfixed32(209);
+    builder.addRepeatedSfixed64(210);
+    builder.addRepeatedFloat   (211);
+    builder.addRepeatedDouble  (212);
+    builder.addRepeatedBool    (true);
+    builder.addRepeatedString  ("215");
+    builder.addRepeatedBytes   (toBytes("216"));
+
+    builder.addRepeatedGroup(
+        TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build());
+    builder.addRepeatedNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+    builder.addRepeatedForeignMessage(
+        ForeignMessageLite.newBuilder().setC(219).build());
+    builder.addRepeatedImportMessage(
+        ImportMessageLite.newBuilder().setD(220).build());
+    builder.addRepeatedLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR);
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR);
+
+    builder.addRepeatedStringPiece("224");
+    builder.addRepeatedCord("225");
+
+    // Add a second one of each field.
+    builder.addRepeatedInt32   (301);
+    builder.addRepeatedInt64   (302);
+    builder.addRepeatedUint32  (303);
+    builder.addRepeatedUint64  (304);
+    builder.addRepeatedSint32  (305);
+    builder.addRepeatedSint64  (306);
+    builder.addRepeatedFixed32 (307);
+    builder.addRepeatedFixed64 (308);
+    builder.addRepeatedSfixed32(309);
+    builder.addRepeatedSfixed64(310);
+    builder.addRepeatedFloat   (311);
+    builder.addRepeatedDouble  (312);
+    builder.addRepeatedBool    (false);
+    builder.addRepeatedString  ("315");
+    builder.addRepeatedBytes   (toBytes("316"));
+
+    builder.addRepeatedGroup(
+        TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build());
+    builder.addRepeatedNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+    builder.addRepeatedForeignMessage(
+        ForeignMessageLite.newBuilder().setC(319).build());
+    builder.addRepeatedImportMessage(
+        ImportMessageLite.newBuilder().setD(320).build());
+    builder.addRepeatedLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+    builder.addRepeatedStringPiece("324");
+    builder.addRepeatedCord("325");
+
+    // -----------------------------------------------------------------
+
+    builder.setDefaultInt32   (401);
+    builder.setDefaultInt64   (402);
+    builder.setDefaultUint32  (403);
+    builder.setDefaultUint64  (404);
+    builder.setDefaultSint32  (405);
+    builder.setDefaultSint64  (406);
+    builder.setDefaultFixed32 (407);
+    builder.setDefaultFixed64 (408);
+    builder.setDefaultSfixed32(409);
+    builder.setDefaultSfixed64(410);
+    builder.setDefaultFloat   (411);
+    builder.setDefaultDouble  (412);
+    builder.setDefaultBool    (false);
+    builder.setDefaultString  ("415");
+    builder.setDefaultBytes   (toBytes("416"));
+
+    builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO);
+    builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO);
+    builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO);
+
+    builder.setDefaultStringPiece("424");
+    builder.setDefaultCord("425");
+
+    builder.setOneofUint32(601);
+    builder.setOneofNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+    builder.setOneofString("603");
+    builder.setOneofBytes(toBytes("604"));
+  }
+
+  /**
+   * Get an unmodifiable {@link ExtensionRegistryLite} containing all the
+   * extensions of {@code TestAllExtensionsLite}.
+   */
+  public static ExtensionRegistryLite getExtensionRegistryLite() {
+    ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+    registerAllExtensionsLite(registry);
+    return registry.getUnmodifiable();
+  }
+
+  /**
+   * Register all of {@code TestAllExtensionsLite}'s extensions with the
+   * given {@link ExtensionRegistryLite}.
+   */
+  public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+    UnittestLite.registerAllExtensions(registry);
+  }
+
+  // ===================================================================
+  // Lite extensions
+
+  /**
+   * Set every field of {@code message} to the values expected by
+   * {@code assertAllExtensionsSet()}.
+   */
+  public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+    message.setExtension(optionalInt32ExtensionLite   , 101);
+    message.setExtension(optionalInt64ExtensionLite   , 102L);
+    message.setExtension(optionalUint32ExtensionLite  , 103);
+    message.setExtension(optionalUint64ExtensionLite  , 104L);
+    message.setExtension(optionalSint32ExtensionLite  , 105);
+    message.setExtension(optionalSint64ExtensionLite  , 106L);
+    message.setExtension(optionalFixed32ExtensionLite , 107);
+    message.setExtension(optionalFixed64ExtensionLite , 108L);
+    message.setExtension(optionalSfixed32ExtensionLite, 109);
+    message.setExtension(optionalSfixed64ExtensionLite, 110L);
+    message.setExtension(optionalFloatExtensionLite   , 111F);
+    message.setExtension(optionalDoubleExtensionLite  , 112D);
+    message.setExtension(optionalBoolExtensionLite    , true);
+    message.setExtension(optionalStringExtensionLite  , "115");
+    message.setExtension(optionalBytesExtensionLite   , toBytes("116"));
+
+    message.setExtension(optionalGroupExtensionLite,
+      OptionalGroup_extension_lite.newBuilder().setA(117).build());
+    message.setExtension(optionalNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+    message.setExtension(optionalForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(119).build());
+    message.setExtension(optionalImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(120).build());
+    message.setExtension(optionalPublicImportMessageExtensionLite,
+      PublicImportMessageLite.newBuilder().setE(126).build());
+    message.setExtension(optionalLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+    message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.setExtension(optionalStringPieceExtensionLite, "124");
+    message.setExtension(optionalCordExtensionLite, "125");
+
+    // -----------------------------------------------------------------
+
+    message.addExtension(repeatedInt32ExtensionLite   , 201);
+    message.addExtension(repeatedInt64ExtensionLite   , 202L);
+    message.addExtension(repeatedUint32ExtensionLite  , 203);
+    message.addExtension(repeatedUint64ExtensionLite  , 204L);
+    message.addExtension(repeatedSint32ExtensionLite  , 205);
+    message.addExtension(repeatedSint64ExtensionLite  , 206L);
+    message.addExtension(repeatedFixed32ExtensionLite , 207);
+    message.addExtension(repeatedFixed64ExtensionLite , 208L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 209);
+    message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+    message.addExtension(repeatedFloatExtensionLite   , 211F);
+    message.addExtension(repeatedDoubleExtensionLite  , 212D);
+    message.addExtension(repeatedBoolExtensionLite    , true);
+    message.addExtension(repeatedStringExtensionLite  , "215");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("216"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(219).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(220).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "224");
+    message.addExtension(repeatedCordExtensionLite, "225");
+
+    // Add a second one of each field.
+    message.addExtension(repeatedInt32ExtensionLite   , 301);
+    message.addExtension(repeatedInt64ExtensionLite   , 302L);
+    message.addExtension(repeatedUint32ExtensionLite  , 303);
+    message.addExtension(repeatedUint64ExtensionLite  , 304L);
+    message.addExtension(repeatedSint32ExtensionLite  , 305);
+    message.addExtension(repeatedSint64ExtensionLite  , 306L);
+    message.addExtension(repeatedFixed32ExtensionLite , 307);
+    message.addExtension(repeatedFixed64ExtensionLite , 308L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 309);
+    message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+    message.addExtension(repeatedFloatExtensionLite   , 311F);
+    message.addExtension(repeatedDoubleExtensionLite  , 312D);
+    message.addExtension(repeatedBoolExtensionLite    , false);
+    message.addExtension(repeatedStringExtensionLite  , "315");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("316"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(319).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(320).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "324");
+    message.addExtension(repeatedCordExtensionLite, "325");
+
+    // -----------------------------------------------------------------
+
+    message.setExtension(defaultInt32ExtensionLite   , 401);
+    message.setExtension(defaultInt64ExtensionLite   , 402L);
+    message.setExtension(defaultUint32ExtensionLite  , 403);
+    message.setExtension(defaultUint64ExtensionLite  , 404L);
+    message.setExtension(defaultSint32ExtensionLite  , 405);
+    message.setExtension(defaultSint64ExtensionLite  , 406L);
+    message.setExtension(defaultFixed32ExtensionLite , 407);
+    message.setExtension(defaultFixed64ExtensionLite , 408L);
+    message.setExtension(defaultSfixed32ExtensionLite, 409);
+    message.setExtension(defaultSfixed64ExtensionLite, 410L);
+    message.setExtension(defaultFloatExtensionLite   , 411F);
+    message.setExtension(defaultDoubleExtensionLite  , 412D);
+    message.setExtension(defaultBoolExtensionLite    , false);
+    message.setExtension(defaultStringExtensionLite  , "415");
+    message.setExtension(defaultBytesExtensionLite   , toBytes("416"));
+
+    message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(defaultStringPieceExtensionLite, "424");
+    message.setExtension(defaultCordExtensionLite, "425");
+
+    message.setExtension(oneofUint32ExtensionLite, 601);
+    message.setExtension(oneofNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+    message.setExtension(oneofStringExtensionLite, "603");
+    message.setExtension(oneofBytesExtensionLite, toBytes("604"));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Modify the repeated extensions of {@code message} to contain the values
+   * expected by {@code assertRepeatedExtensionsModified()}.
+   */
+  public static void modifyRepeatedExtensions(
+      TestAllExtensionsLite.Builder message) {
+    message.setExtension(repeatedInt32ExtensionLite   , 1, 501);
+    message.setExtension(repeatedInt64ExtensionLite   , 1, 502L);
+    message.setExtension(repeatedUint32ExtensionLite  , 1, 503);
+    message.setExtension(repeatedUint64ExtensionLite  , 1, 504L);
+    message.setExtension(repeatedSint32ExtensionLite  , 1, 505);
+    message.setExtension(repeatedSint64ExtensionLite  , 1, 506L);
+    message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+    message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+    message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+    message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+    message.setExtension(repeatedFloatExtensionLite   , 1, 511F);
+    message.setExtension(repeatedDoubleExtensionLite  , 1, 512D);
+    message.setExtension(repeatedBoolExtensionLite    , 1, true);
+    message.setExtension(repeatedStringExtensionLite  , 1, "515");
+    message.setExtension(repeatedBytesExtensionLite   , 1, toBytes("516"));
+
+    message.setExtension(repeatedGroupExtensionLite, 1,
+      RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+    message.setExtension(repeatedNestedMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+    message.setExtension(repeatedForeignMessageExtensionLite, 1,
+      ForeignMessageLite.newBuilder().setC(519).build());
+    message.setExtension(repeatedImportMessageExtensionLite, 1,
+      ImportMessageLite.newBuilder().setD(520).build());
+    message.setExtension(repeatedLazyMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
+
+    message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+    message.setExtension(repeatedCordExtensionLite, 1, "525");
+  }
+
+  public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+    message.addExtension(packedInt32ExtensionLite   , 601);
+    message.addExtension(packedInt64ExtensionLite   , 602L);
+    message.addExtension(packedUint32ExtensionLite  , 603);
+    message.addExtension(packedUint64ExtensionLite  , 604L);
+    message.addExtension(packedSint32ExtensionLite  , 605);
+    message.addExtension(packedSint64ExtensionLite  , 606L);
+    message.addExtension(packedFixed32ExtensionLite , 607);
+    message.addExtension(packedFixed64ExtensionLite , 608L);
+    message.addExtension(packedSfixed32ExtensionLite, 609);
+    message.addExtension(packedSfixed64ExtensionLite, 610L);
+    message.addExtension(packedFloatExtensionLite   , 611F);
+    message.addExtension(packedDoubleExtensionLite  , 612D);
+    message.addExtension(packedBoolExtensionLite    , true);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    // Add a second one of each field.
+    message.addExtension(packedInt32ExtensionLite   , 701);
+    message.addExtension(packedInt64ExtensionLite   , 702L);
+    message.addExtension(packedUint32ExtensionLite  , 703);
+    message.addExtension(packedUint64ExtensionLite  , 704L);
+    message.addExtension(packedSint32ExtensionLite  , 705);
+    message.addExtension(packedSint64ExtensionLite  , 706L);
+    message.addExtension(packedFixed32ExtensionLite , 707);
+    message.addExtension(packedFixed64ExtensionLite , 708L);
+    message.addExtension(packedSfixed32ExtensionLite, 709);
+    message.addExtension(packedSfixed64ExtensionLite, 710L);
+    message.addExtension(packedFloatExtensionLite   , 711F);
+    message.addExtension(packedDoubleExtensionLite  , 712D);
+    message.addExtension(packedBoolExtensionLite    , false);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java
new file mode 100644
index 0000000..e338af2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java
@@ -0,0 +1,182 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Test @{link TextFormatParseInfoTree}.
+ */
+public class TextFormatParseInfoTreeTest extends TestCase {
+
+  private static final Descriptor DESCRIPTOR = TestAllTypes.getDescriptor();
+  private static final FieldDescriptor OPTIONAL_INT32 =
+      DESCRIPTOR.findFieldByName("optional_int32");
+  private static final FieldDescriptor OPTIONAL_BOOLEAN =
+      DESCRIPTOR.findFieldByName("optional_boolean");
+  private static final FieldDescriptor REPEATED_INT32 =
+      DESCRIPTOR.findFieldByName("repeated_int32");
+  private static final FieldDescriptor OPTIONAL_NESTED_MESSAGE =
+      DESCRIPTOR.findFieldByName("optional_nested_message");
+  private static final FieldDescriptor REPEATED_NESTED_MESSAGE =
+      DESCRIPTOR.findFieldByName("repeated_nested_message");
+  private static final FieldDescriptor FIELD_BB =
+      TestAllTypes.NestedMessage.getDescriptor().findFieldByName("bb");
+
+  private static final TextFormatParseLocation LOC0 = TextFormatParseLocation.create(1, 2);
+  private static final TextFormatParseLocation LOC1 = TextFormatParseLocation.create(2, 3);
+
+  private TextFormatParseInfoTree.Builder rootBuilder;
+
+  @Override
+  public void setUp() {
+    rootBuilder = TextFormatParseInfoTree.builder();
+  }
+
+  public void testBuildEmptyParseTree() {
+    TextFormatParseInfoTree tree = rootBuilder.build();
+    assertTrue(tree.getLocations(null).isEmpty());
+  }
+
+  public void testGetLocationReturnsSingleLocation() {
+    rootBuilder.setLocation(OPTIONAL_INT32, LOC0);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertEquals(LOC0, root.getLocation(OPTIONAL_INT32, 0));
+    assertEquals(1, root.getLocations(OPTIONAL_INT32).size());
+    }
+
+  public void testGetLocationsReturnsNoParseLocationsForUnknownField() {
+    assertTrue(rootBuilder.build().getLocations(OPTIONAL_INT32).isEmpty());
+    rootBuilder.setLocation(OPTIONAL_BOOLEAN, LOC0);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertTrue(root.getLocations(OPTIONAL_INT32).isEmpty());
+    assertEquals(LOC0, root.getLocations(OPTIONAL_BOOLEAN).get(0));
+  }
+
+  public void testGetLocationThrowsIllegalArgumentExceptionForUnknownField() {
+    rootBuilder.setLocation(REPEATED_INT32, LOC0);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    try {
+      root.getNestedTree(OPTIONAL_INT32, 0);
+      fail("Did not detect unknown field");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+  }
+
+  public void testGetLocationThrowsIllegalArgumentExceptionForInvalidIndex() {
+    TextFormatParseInfoTree root = rootBuilder.setLocation(OPTIONAL_INT32, LOC0).build();
+    try {
+      root.getLocation(OPTIONAL_INT32, 1);
+      fail("Invalid index not detected");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+    try {
+      root.getLocation(OPTIONAL_INT32, -1);
+      fail("Negative index not detected");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+  }
+
+  public void testGetLocationsReturnsMultipleLocations() {
+    rootBuilder.setLocation(REPEATED_INT32, LOC0);
+    rootBuilder.setLocation(REPEATED_INT32, LOC1);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertEquals(LOC0, root.getLocation(REPEATED_INT32, 0));
+    assertEquals(LOC1, root.getLocation(REPEATED_INT32, 1));
+    assertEquals(2, root.getLocations(REPEATED_INT32).size());
+  }
+
+  public void testGetNestedTreeThrowsIllegalArgumentExceptionForUnknownField() {
+    rootBuilder.setLocation(REPEATED_INT32, LOC0);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    try {
+      root.getNestedTree(OPTIONAL_NESTED_MESSAGE, 0);
+      fail("Did not detect unknown field");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+  }
+
+  public void testGetNestedTreesReturnsNoParseInfoTreesForUnknownField() {
+    rootBuilder.setLocation(REPEATED_INT32, LOC0);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertTrue(root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).isEmpty());
+  }
+
+  public void testGetNestedTreeThrowsIllegalArgumentExceptionForInvalidIndex() {
+    rootBuilder.setLocation(REPEATED_INT32, LOC0);
+    rootBuilder.getBuilderForSubMessageField(OPTIONAL_NESTED_MESSAGE);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    try {
+      root.getNestedTree(OPTIONAL_NESTED_MESSAGE, 1);
+      fail("Submessage index that is too large not detected");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+    try {
+      rootBuilder.build().getNestedTree(OPTIONAL_NESTED_MESSAGE, -1);
+      fail("Invalid submessage index (-1) not detected");
+    } catch (IllegalArgumentException expected) {
+      // pass
+    }
+  }
+
+  public void testGetNestedTreesReturnsSingleTree() {
+    rootBuilder.getBuilderForSubMessageField(OPTIONAL_NESTED_MESSAGE);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertEquals(1, root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).size());
+    TextFormatParseInfoTree subtree = root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).get(0);
+    assertNotNull(subtree);
+  }
+
+  public void testGetNestedTreesReturnsMultipleTrees() {
+    TextFormatParseInfoTree.Builder subtree1Builder =
+        rootBuilder.getBuilderForSubMessageField(REPEATED_NESTED_MESSAGE);
+    subtree1Builder.getBuilderForSubMessageField(FIELD_BB);
+    subtree1Builder.getBuilderForSubMessageField(FIELD_BB);
+    TextFormatParseInfoTree.Builder subtree2Builder =
+        rootBuilder.getBuilderForSubMessageField(REPEATED_NESTED_MESSAGE);
+    subtree2Builder.getBuilderForSubMessageField(FIELD_BB);
+    TextFormatParseInfoTree root = rootBuilder.build();
+    assertEquals(2, root.getNestedTrees(REPEATED_NESTED_MESSAGE).size());
+    assertEquals(
+        2, root.getNestedTrees(REPEATED_NESTED_MESSAGE).get(0).getNestedTrees(FIELD_BB).size());
+    assertEquals(
+        1, root.getNestedTrees(REPEATED_NESTED_MESSAGE).get(1).getNestedTrees(FIELD_BB).size());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java
new file mode 100644
index 0000000..c42bfa6
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java
@@ -0,0 +1,86 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+/**
+ * Test @{link TextFormatParseLocation}.
+ */
+public class TextFormatParseLocationTest extends TestCase {
+
+  public void testCreateEmpty() {
+    TextFormatParseLocation location = TextFormatParseLocation.create(-1, -1);
+    assertEquals(TextFormatParseLocation.EMPTY, location);
+  }
+
+  public void testCreate() {
+    TextFormatParseLocation location = TextFormatParseLocation.create(2, 1);
+    assertEquals(2, location.getLine());
+    assertEquals(1, location.getColumn());
+  }
+
+  public void testCreateThrowsIllegalArgumentExceptionForInvalidIndex() {
+    try {
+      TextFormatParseLocation.create(-1, 0);
+      fail("Should throw IllegalArgumentException if line is less than 0");
+    } catch (IllegalArgumentException unused) {
+      // pass
+    }
+    try {
+      TextFormatParseLocation.create(0, -1);
+      fail("Should throw, column < 0");
+    } catch (IllegalArgumentException unused) {
+      // pass
+    }
+  }
+
+  public void testHashCode() {
+    TextFormatParseLocation loc0 = TextFormatParseLocation.create(2, 1);
+    TextFormatParseLocation loc1 = TextFormatParseLocation.create(2, 1);
+
+    assertEquals(loc0.hashCode(), loc1.hashCode());
+    assertEquals(
+        TextFormatParseLocation.EMPTY.hashCode(), TextFormatParseLocation.EMPTY.hashCode());
+  }
+
+  public void testEquals() {
+    TextFormatParseLocation loc0 = TextFormatParseLocation.create(2, 1);
+    TextFormatParseLocation loc1 = TextFormatParseLocation.create(1, 2);
+    TextFormatParseLocation loc2 = TextFormatParseLocation.create(2, 2);
+    TextFormatParseLocation loc3 = TextFormatParseLocation.create(2, 1);
+
+    assertEquals(loc0, loc3);
+    assertNotSame(loc0, loc1);
+    assertNotSame(loc0, loc2);
+    assertNotSame(loc1, loc2);
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
new file mode 100644
index 0000000..63c17cd
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -0,0 +1,1129 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto.OneString;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+import java.util.List;
+
+/**
+ * Test case for {@link TextFormat}.
+ *
+ * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
+ *
+ * @author wenboz@google.com (Wenbo Zhu)
+ */
+public class TextFormatTest extends TestCase {
+
+  // A basic string with different escapable characters for testing.
+  private final static String kEscapeTestString =
+      "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+          + "slashes \\";
+
+  // A representation of the above string with all the characters escaped.
+  private final static String kEscapeTestStringEscaped =
+      "\\\"A string with \\' characters \\n and \\r newlines "
+          + "and \\t tabs and \\001 slashes \\\\";
+
+  private static String allFieldsSetText = TestUtil.readTextFromFile(
+    "text_format_unittest_data_oneof_implemented.txt");
+  private static String allExtensionsSetText = TestUtil.readTextFromFile(
+    "text_format_unittest_extensions_data.txt");
+
+  private static String exoticText =
+    "repeated_int32: -1\n" +
+    "repeated_int32: -2147483648\n" +
+    "repeated_int64: -1,\n" +
+    "repeated_int64: -9223372036854775808\n" +
+    "repeated_uint32: 4294967295\n" +
+    "repeated_uint32: 2147483648\n" +
+    "repeated_uint64: 18446744073709551615\n" +
+    "repeated_uint64: 9223372036854775808\n" +
+    "repeated_double: 123.0\n" +
+    "repeated_double: 123.5\n" +
+    "repeated_double: 0.125\n" +
+    "repeated_double: .125\n" +
+    "repeated_double: -.125\n" +
+    "repeated_double: 1.23E17\n" +
+    "repeated_double: 1.23E+17\n" +
+    "repeated_double: -1.23e-17\n" +
+    "repeated_double: .23e+17\n" +
+    "repeated_double: -.23E17\n" +
+    "repeated_double: 1.235E22\n" +
+    "repeated_double: 1.235E-18\n" +
+    "repeated_double: 123.456789\n" +
+    "repeated_double: Infinity\n" +
+    "repeated_double: -Infinity\n" +
+    "repeated_double: NaN\n" +
+    "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
+      "\\341\\210\\264\"\n" +
+    "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+
+  private static String canonicalExoticText =
+      exoticText.replace(": .", ": 0.").replace(": -.", ": -0.")   // short-form double
+      .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16").replace(",", "");
+
+  private String messageSetText =
+    "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+    "  i: 123\n" +
+    "}\n" +
+    "[protobuf_unittest.TestMessageSetExtension2] {\n" +
+    "  str: \"foo\"\n" +
+    "}\n";
+
+  private String messageSetTextWithRepeatedExtension =
+      "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+      "  i: 123\n" +
+      "}\n" +
+      "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+      "  i: 456\n" +
+      "}\n";
+
+
+  private final TextFormat.Parser parserWithOverwriteForbidden =
+      TextFormat.Parser.newBuilder()
+          .setSingularOverwritePolicy(
+              SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+          .build();
+
+  private final TextFormat.Parser defaultParser =
+      TextFormat.Parser.newBuilder().build();
+
+  /** Print TestAllTypes and compare with golden file. */
+  public void testPrintMessage() throws Exception {
+    String javaText = TextFormat.printToString(TestUtil.getAllSet());
+
+    // Java likes to add a trailing ".0" to floats and doubles.  C printf
+    // (with %g format) does not.  Our golden files are used for both
+    // C++ and Java TextFormat classes, so we need to conform.
+    javaText = javaText.replace(".0\n", "\n");
+
+    assertEquals(allFieldsSetText, javaText);
+  }
+
+  /** Print TestAllTypes as Builder and compare with golden file. */
+  public void testPrintMessageBuilder() throws Exception {
+    String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+    // Java likes to add a trailing ".0" to floats and doubles.  C printf
+    // (with %g format) does not.  Our golden files are used for both
+    // C++ and Java TextFormat classes, so we need to conform.
+    javaText = javaText.replace(".0\n", "\n");
+
+    assertEquals(allFieldsSetText, javaText);
+  }
+
+  /** Print TestAllExtensions and compare with golden file. */
+  public void testPrintExtensions() throws Exception {
+    String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
+
+    // Java likes to add a trailing ".0" to floats and doubles.  C printf
+    // (with %g format) does not.  Our golden files are used for both
+    // C++ and Java TextFormat classes, so we need to conform.
+    javaText = javaText.replace(".0\n", "\n");
+
+    assertEquals(allExtensionsSetText, javaText);
+  }
+
+  // Creates an example unknown field set.
+  private UnknownFieldSet makeUnknownFieldSet() {
+    return UnknownFieldSet.newBuilder()
+        .addField(5,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(1)
+            .addFixed32(2)
+            .addFixed64(3)
+            .addLengthDelimited(ByteString.copyFromUtf8("4"))
+            .addGroup(
+                UnknownFieldSet.newBuilder()
+                .addField(10,
+                    UnknownFieldSet.Field.newBuilder()
+                    .addVarint(5)
+                    .build())
+                .build())
+            .build())
+        .addField(8,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(1)
+            .addVarint(2)
+            .addVarint(3)
+            .build())
+        .addField(15,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(0xABCDEF1234567890L)
+            .addFixed32(0xABCD1234)
+            .addFixed64(0xABCDEF1234567890L)
+            .build())
+        .build();
+  }
+
+  public void testPrintUnknownFields() throws Exception {
+    // Test printing of unknown fields in a message.
+
+    TestEmptyMessage message =
+      TestEmptyMessage.newBuilder()
+        .setUnknownFields(makeUnknownFieldSet())
+        .build();
+
+    assertEquals(
+      "5: 1\n" +
+      "5: 0x00000002\n" +
+      "5: 0x0000000000000003\n" +
+      "5: \"4\"\n" +
+      "5 {\n" +
+      "  10: 5\n" +
+      "}\n" +
+      "8: 1\n" +
+      "8: 2\n" +
+      "8: 3\n" +
+      "15: 12379813812177893520\n" +
+      "15: 0xabcd1234\n" +
+      "15: 0xabcdef1234567890\n",
+      TextFormat.printToString(message));
+  }
+
+  public void testPrintField() throws Exception {
+    final FieldDescriptor dataField =
+      OneString.getDescriptor().findFieldByName("data");
+    assertEquals(
+      "data: \"test data\"\n",
+      TextFormat.printFieldToString(dataField, "test data"));
+
+    final FieldDescriptor optionalField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+    final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+    assertEquals(
+      "optional_nested_message {\n  bb: 42\n}\n",
+      TextFormat.printFieldToString(optionalField, value));
+  }
+
+  /**
+   * Helper to construct a ByteString from a String containing only 8-bit
+   * characters.  The characters are converted directly to bytes, *not*
+   * encoded using UTF-8.
+   */
+  private ByteString bytes(String str) {
+    return ByteString.copyFrom(str.getBytes(Internal.ISO_8859_1));
+  }
+
+  /**
+   * Helper to construct a ByteString from a bunch of bytes.  The inputs are
+   * actually ints so that I can use hex notation and not get stupid errors
+   * about precision.
+   */
+  private ByteString bytes(int... bytesAsInts) {
+    byte[] bytes = new byte[bytesAsInts.length];
+    for (int i = 0; i < bytesAsInts.length; i++) {
+      bytes[i] = (byte) bytesAsInts[i];
+    }
+    return ByteString.copyFrom(bytes);
+  }
+
+  public void testPrintExotic() throws Exception {
+    Message message = TestAllTypes.newBuilder()
+      // Signed vs. unsigned numbers.
+      .addRepeatedInt32 (-1)
+      .addRepeatedUint32(-1)
+      .addRepeatedInt64 (-1)
+      .addRepeatedUint64(-1)
+
+      .addRepeatedInt32 (1  << 31)
+      .addRepeatedUint32(1  << 31)
+      .addRepeatedInt64 (1L << 63)
+      .addRepeatedUint64(1L << 63)
+
+      // Floats of various precisions and exponents.
+      .addRepeatedDouble(123)
+      .addRepeatedDouble(123.5)
+      .addRepeatedDouble(0.125)
+      .addRepeatedDouble(.125)
+      .addRepeatedDouble(-.125)
+      .addRepeatedDouble(123e15)
+      .addRepeatedDouble(123e15)
+      .addRepeatedDouble(-1.23e-17)
+      .addRepeatedDouble(.23e17)
+      .addRepeatedDouble(-23e15)
+      .addRepeatedDouble(123.5e20)
+      .addRepeatedDouble(123.5e-20)
+      .addRepeatedDouble(123.456789)
+      .addRepeatedDouble(Double.POSITIVE_INFINITY)
+      .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+      .addRepeatedDouble(Double.NaN)
+
+      // Strings and bytes that needing escaping.
+      .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
+      .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
+      .build();
+
+    assertEquals(canonicalExoticText, message.toString());
+  }
+
+  public void testPrintMessageSet() throws Exception {
+    TestMessageSet messageSet =
+      TestMessageSet.newBuilder()
+        .setExtension(
+          TestMessageSetExtension1.messageSetExtension,
+          TestMessageSetExtension1.newBuilder().setI(123).build())
+        .setExtension(
+          TestMessageSetExtension2.messageSetExtension,
+          TestMessageSetExtension2.newBuilder().setStr("foo").build())
+        .build();
+
+    assertEquals(messageSetText, messageSet.toString());
+  }
+
+  // =================================================================
+
+  public void testParse() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(allFieldsSetText, builder);
+    TestUtil.assertAllFieldsSet(builder.build());
+  }
+
+  public void testParseReader() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(new StringReader(allFieldsSetText), builder);
+    TestUtil.assertAllFieldsSet(builder.build());
+  }
+
+  public void testParseExtensions() throws Exception {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    TextFormat.merge(allExtensionsSetText,
+                     TestUtil.getExtensionRegistry(),
+                     builder);
+    TestUtil.assertAllExtensionsSet(builder.build());
+  }
+
+  public void testParseCompatibility() throws Exception {
+    String original = "repeated_float: inf\n" +
+                      "repeated_float: -inf\n" +
+                      "repeated_float: nan\n" +
+                      "repeated_float: inff\n" +
+                      "repeated_float: -inff\n" +
+                      "repeated_float: nanf\n" +
+                      "repeated_float: 1.0f\n" +
+                      "repeated_float: infinityf\n" +
+                      "repeated_float: -Infinityf\n" +
+                      "repeated_double: infinity\n" +
+                      "repeated_double: -infinity\n" +
+                      "repeated_double: nan\n";
+    String canonical =  "repeated_float: Infinity\n" +
+                        "repeated_float: -Infinity\n" +
+                        "repeated_float: NaN\n" +
+                        "repeated_float: Infinity\n" +
+                        "repeated_float: -Infinity\n" +
+                        "repeated_float: NaN\n" +
+                        "repeated_float: 1.0\n" +
+                        "repeated_float: Infinity\n" +
+                        "repeated_float: -Infinity\n" +
+                        "repeated_double: Infinity\n" +
+                        "repeated_double: -Infinity\n" +
+                        "repeated_double: NaN\n";
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(original, builder);
+    assertEquals(canonical, builder.build().toString());
+  }
+
+  public void testParseExotic() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(exoticText, builder);
+
+    // Too lazy to check things individually.  Don't try to debug this
+    // if testPrintExotic() is failing.
+    assertEquals(canonicalExoticText, builder.build().toString());
+  }
+
+  public void testParseMessageSet() throws Exception {
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+    extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+    TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+    TextFormat.merge(messageSetText, extensionRegistry, builder);
+    TestMessageSet messageSet = builder.build();
+
+    assertTrue(messageSet.hasExtension(
+      TestMessageSetExtension1.messageSetExtension));
+    assertEquals(123, messageSet.getExtension(
+      TestMessageSetExtension1.messageSetExtension).getI());
+    assertTrue(messageSet.hasExtension(
+      TestMessageSetExtension2.messageSetExtension));
+    assertEquals("foo", messageSet.getExtension(
+      TestMessageSetExtension2.messageSetExtension).getStr());
+
+    builder = TestMessageSet.newBuilder();
+    TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry,
+        builder);
+    messageSet = builder.build();
+    assertEquals(456, messageSet.getExtension(
+      TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  public void testParseMessageSetWithOverwriteForbidden() throws Exception {
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+    extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+    TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+    parserWithOverwriteForbidden.merge(
+        messageSetText, extensionRegistry, builder);
+    TestMessageSet messageSet = builder.build();
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+    assertEquals("foo", messageSet.getExtension(
+      TestMessageSetExtension2.messageSetExtension).getStr());
+
+    builder = TestMessageSet.newBuilder();
+    try {
+      parserWithOverwriteForbidden.merge(
+          messageSetTextWithRepeatedExtension, extensionRegistry, builder);
+      fail("expected parse exception");
+    } catch (TextFormat.ParseException e) {
+      assertEquals("6:1: Non-repeated field "
+          + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\""
+          + " cannot be overwritten.",
+          e.getMessage());
+    }
+  }
+
+  public void testParseNumericEnum() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("optional_nested_enum: 2", builder);
+    assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
+  }
+
+  public void testParseAngleBrackets() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("OptionalGroup: < a: 1 >", builder);
+    assertTrue(builder.hasOptionalGroup());
+    assertEquals(1, builder.getOptionalGroup().getA());
+  }
+
+  public void testParseComment() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(
+      "# this is a comment\n" +
+      "optional_int32: 1  # another comment\n" +
+      "optional_int64: 2\n" +
+      "# EOF comment", builder);
+    assertEquals(1, builder.getOptionalInt32());
+    assertEquals(2, builder.getOptionalInt64());
+  }
+
+  private void assertParseError(String error, String text) {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
+      fail("Expected parse exception.");
+    } catch (TextFormat.ParseException e) {
+      assertEquals(error, e.getMessage());
+    }
+  }
+
+
+  private void assertParseErrorWithOverwriteForbidden(String error,
+      String text) {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      parserWithOverwriteForbidden.merge(
+          text, TestUtil.getExtensionRegistry(), builder);
+      fail("Expected parse exception.");
+    } catch (TextFormat.ParseException e) {
+      assertEquals(error, e.getMessage());
+    }
+  }
+
+  private TestAllTypes assertParseSuccessWithOverwriteForbidden(
+      String text) throws TextFormat.ParseException {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    parserWithOverwriteForbidden.merge(
+        text, TestUtil.getExtensionRegistry(), builder);
+    return builder.build();
+  }
+
+  public void testParseErrors() throws Exception {
+    assertParseError(
+      "1:16: Expected \":\".",
+      "optional_int32 123");
+    assertParseError(
+      "1:23: Expected identifier. Found '?'",
+      "optional_nested_enum: ?");
+    assertParseError(
+      "1:18: Couldn't parse integer: Number must be positive: -1",
+      "optional_uint32: -1");
+    assertParseError(
+      "1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
+        "integer: 82301481290849012385230157",
+      "optional_int32: 82301481290849012385230157");
+    assertParseError(
+      "1:16: Expected \"true\" or \"false\".",
+      "optional_bool: maybe");
+    assertParseError(
+      "1:16: Expected \"true\" or \"false\".",
+      "optional_bool: 2");
+    assertParseError(
+      "1:18: Expected string.",
+      "optional_string: 123");
+    assertParseError(
+      "1:18: String missing ending quote.",
+      "optional_string: \"ueoauaoe");
+    assertParseError(
+      "1:18: String missing ending quote.",
+      "optional_string: \"ueoauaoe\n" +
+      "optional_int32: 123");
+    assertParseError(
+      "1:18: Invalid escape sequence: '\\z'",
+      "optional_string: \"\\z\"");
+    assertParseError(
+      "1:18: String missing ending quote.",
+      "optional_string: \"ueoauaoe\n" +
+      "optional_int32: 123");
+    assertParseError(
+      "1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.",
+      "[nosuchext]: 123");
+    assertParseError(
+      "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " +
+        "not extend message type \"protobuf_unittest.TestAllTypes\".",
+      "[protobuf_unittest.optional_int32_extension]: 123");
+    assertParseError(
+      "1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " +
+        "named \"nosuchfield\".",
+      "nosuchfield: 123");
+    assertParseError(
+      "1:21: Expected \">\".",
+      "OptionalGroup < a: 1");
+    assertParseError(
+      "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+        "value named \"NO_SUCH_VALUE\".",
+      "optional_nested_enum: NO_SUCH_VALUE");
+    assertParseError(
+      "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+        "value with number 123.",
+      "optional_nested_enum: 123");
+
+    // Delimiters must match.
+    assertParseError(
+      "1:22: Expected identifier. Found '}'",
+      "OptionalGroup < a: 1 }");
+    assertParseError(
+      "1:22: Expected identifier. Found '>'",
+      "OptionalGroup { a: 1 >");
+  }
+
+  // =================================================================
+
+  public void testEscape() throws Exception {
+    // Escape sequences.
+    assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+      TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177")));
+    assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+      TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177"));
+    assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""),
+      TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+    assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
+      TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+    assertEquals(kEscapeTestStringEscaped,
+      TextFormat.escapeText(kEscapeTestString));
+    assertEquals(kEscapeTestString,
+      TextFormat.unescapeText(kEscapeTestStringEscaped));
+
+    // Invariant
+    assertEquals("hello",
+        TextFormat.escapeBytes(bytes("hello")));
+    assertEquals("hello",
+        TextFormat.escapeText("hello"));
+    assertEquals(bytes("hello"),
+        TextFormat.unescapeBytes("hello"));
+    assertEquals("hello",
+        TextFormat.unescapeText("hello"));
+
+    // Unicode handling.
+    assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234"));
+    assertEquals("\\341\\210\\264",
+                 TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4)));
+    assertEquals("\u1234", TextFormat.unescapeText("\\341\\210\\264"));
+    assertEquals(bytes(0xe1, 0x88, 0xb4),
+                 TextFormat.unescapeBytes("\\341\\210\\264"));
+    assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4"));
+    assertEquals(bytes(0xe1, 0x88, 0xb4),
+                 TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
+
+    // Handling of strings with unescaped Unicode characters > 255.
+    final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+    ByteString zhByteString = ByteString.copyFromUtf8(zh);
+    assertEquals(zhByteString, TextFormat.unescapeBytes(zh));
+
+    // Errors.
+    try {
+      TextFormat.unescapeText("\\x");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      // success
+    }
+
+    try {
+      TextFormat.unescapeText("\\z");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      // success
+    }
+
+    try {
+      TextFormat.unescapeText("\\");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      // success
+    }
+  }
+
+  public void testParseInteger() throws Exception {
+    assertEquals(          0, TextFormat.parseInt32(          "0"));
+    assertEquals(          1, TextFormat.parseInt32(          "1"));
+    assertEquals(         -1, TextFormat.parseInt32(         "-1"));
+    assertEquals(      12345, TextFormat.parseInt32(      "12345"));
+    assertEquals(     -12345, TextFormat.parseInt32(     "-12345"));
+    assertEquals( 2147483647, TextFormat.parseInt32( "2147483647"));
+    assertEquals(-2147483648, TextFormat.parseInt32("-2147483648"));
+
+    assertEquals(                0, TextFormat.parseUInt32(         "0"));
+    assertEquals(                1, TextFormat.parseUInt32(         "1"));
+    assertEquals(            12345, TextFormat.parseUInt32(     "12345"));
+    assertEquals(       2147483647, TextFormat.parseUInt32("2147483647"));
+    assertEquals((int) 2147483648L, TextFormat.parseUInt32("2147483648"));
+    assertEquals((int) 4294967295L, TextFormat.parseUInt32("4294967295"));
+
+    assertEquals(          0L, TextFormat.parseInt64(          "0"));
+    assertEquals(          1L, TextFormat.parseInt64(          "1"));
+    assertEquals(         -1L, TextFormat.parseInt64(         "-1"));
+    assertEquals(      12345L, TextFormat.parseInt64(      "12345"));
+    assertEquals(     -12345L, TextFormat.parseInt64(     "-12345"));
+    assertEquals( 2147483647L, TextFormat.parseInt64( "2147483647"));
+    assertEquals(-2147483648L, TextFormat.parseInt64("-2147483648"));
+    assertEquals( 4294967295L, TextFormat.parseInt64( "4294967295"));
+    assertEquals( 4294967296L, TextFormat.parseInt64( "4294967296"));
+    assertEquals(9223372036854775807L,
+                 TextFormat.parseInt64("9223372036854775807"));
+    assertEquals(-9223372036854775808L,
+                 TextFormat.parseInt64("-9223372036854775808"));
+
+    assertEquals(          0L, TextFormat.parseUInt64(          "0"));
+    assertEquals(          1L, TextFormat.parseUInt64(          "1"));
+    assertEquals(      12345L, TextFormat.parseUInt64(      "12345"));
+    assertEquals( 2147483647L, TextFormat.parseUInt64( "2147483647"));
+    assertEquals( 4294967295L, TextFormat.parseUInt64( "4294967295"));
+    assertEquals( 4294967296L, TextFormat.parseUInt64( "4294967296"));
+    assertEquals(9223372036854775807L,
+                 TextFormat.parseUInt64("9223372036854775807"));
+    assertEquals(-9223372036854775808L,
+                 TextFormat.parseUInt64("9223372036854775808"));
+    assertEquals(-1L, TextFormat.parseUInt64("18446744073709551615"));
+
+    // Hex
+    assertEquals(0x1234abcd, TextFormat.parseInt32("0x1234abcd"));
+    assertEquals(-0x1234abcd, TextFormat.parseInt32("-0x1234abcd"));
+    assertEquals(-1, TextFormat.parseUInt64("0xffffffffffffffff"));
+    assertEquals(0x7fffffffffffffffL,
+                 TextFormat.parseInt64("0x7fffffffffffffff"));
+
+    // Octal
+    assertEquals(01234567, TextFormat.parseInt32("01234567"));
+
+    // Out-of-range
+    try {
+      TextFormat.parseInt32("2147483648");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseInt32("-2147483649");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseUInt32("4294967296");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseUInt32("-1");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseInt64("9223372036854775808");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseInt64("-9223372036854775809");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseUInt64("18446744073709551616");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    try {
+      TextFormat.parseUInt64("-1");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+
+    // Not a number.
+    try {
+      TextFormat.parseInt32("abcd");
+      fail("Should have thrown an exception.");
+    } catch (NumberFormatException e) {
+      // success
+    }
+  }
+
+  public void testParseString() throws Exception {
+    final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("optional_string: \"" + zh + "\"", builder);
+    assertEquals(zh, builder.getOptionalString());
+  }
+
+  public void testParseLongString() throws Exception {
+    String longText =
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890" +
+      "123456789012345678901234567890123456789012345678901234567890";
+
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("optional_string: \"" + longText + "\"", builder);
+    assertEquals(longText, builder.getOptionalString());
+  }
+
+  public void testParseBoolean() throws Exception {
+    String goodText =
+        "repeated_bool: t  repeated_bool : 0\n" +
+        "repeated_bool :f repeated_bool:1\n" +
+        "repeated_bool: False repeated_bool: True";
+    String goodTextCanonical =
+        "repeated_bool: true\n" +
+        "repeated_bool: false\n" +
+        "repeated_bool: false\n" +
+        "repeated_bool: true\n" +
+        "repeated_bool: false\n" +
+        "repeated_bool: true\n";
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(goodText, builder);
+    assertEquals(goodTextCanonical, builder.build().toString());
+
+    try {
+      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+      TextFormat.merge("optional_bool:2", badBuilder);
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.ParseException e) {
+      // success
+    }
+    try {
+      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+      TextFormat.merge("optional_bool: foo", badBuilder);
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.ParseException e) {
+      // success
+    }
+  }
+
+  public void testParseAdjacentStringLiterals() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
+    assertEquals("foocorgegrault", builder.getOptionalString());
+  }
+
+  public void testPrintFieldValue() throws Exception {
+    assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
+    assertPrintFieldValue("123.0",  123f, "repeated_float");
+    assertPrintFieldValue("123.0",  123d, "repeated_double");
+    assertPrintFieldValue("123",  123, "repeated_int32");
+    assertPrintFieldValue("123",  123L, "repeated_int64");
+    assertPrintFieldValue("true",  true, "repeated_bool");
+    assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
+    assertPrintFieldValue("18446744073709551615",  0xFFFFFFFFFFFFFFFFL,
+        "repeated_uint64");
+    assertPrintFieldValue("\"\\001\\002\\003\"",
+        ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
+  }
+
+  private void assertPrintFieldValue(String expect, Object value,
+      String fieldName) throws Exception {
+    StringBuilder sb = new StringBuilder();
+    TextFormat.printFieldValue(
+        TestAllTypes.getDescriptor().findFieldByName(fieldName),
+        value, sb);
+    assertEquals(expect, sb.toString());
+  }
+
+  public void testShortDebugString() {
+    assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
+        + " repeated_uint32: 2",
+        TextFormat.shortDebugString(TestAllTypes.newBuilder()
+            .addRepeatedInt32(1)
+            .addRepeatedUint32(2)
+            .setOptionalNestedMessage(
+                NestedMessage.newBuilder().setBb(42).build())
+            .build()));
+  }
+
+  public void testShortDebugString_field() {
+    final FieldDescriptor dataField =
+      OneString.getDescriptor().findFieldByName("data");
+    assertEquals(
+      "data: \"test data\"",
+      TextFormat.shortDebugString(dataField, "test data"));
+
+    final FieldDescriptor optionalField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+    final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+    assertEquals(
+      "optional_nested_message { bb: 42 }",
+      TextFormat.shortDebugString(optionalField, value));
+  }
+
+  public void testShortDebugString_unknown() {
+    assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+        + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+        + " 0xabcdef1234567890",
+        TextFormat.shortDebugString(makeUnknownFieldSet()));
+  }
+
+  public void testPrintToUnicodeString() throws Exception {
+    assertEquals(
+        "optional_string: \"abc\u3042efg\"\n" +
+        "optional_bytes: \"\\343\\201\\202\"\n" +
+        "repeated_string: \"\u3093XYZ\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("abc\u3042efg")
+            .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+            .addRepeatedString("\u3093XYZ")
+            .build()));
+
+    // Double quotes and backslashes should be escaped
+    assertEquals(
+        "optional_string: \"a\\\\bc\\\"ef\\\"g\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("a\\bc\"ef\"g")
+            .build()));
+
+    // Test escaping roundtrip
+    TestAllTypes message = TestAllTypes.newBuilder()
+        .setOptionalString("a\\bc\\\"ef\"g")
+        .build();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+    assertEquals(message.getOptionalString(), builder.getOptionalString());
+  }
+
+  public void testPrintToUnicodeStringWithNewlines() throws Exception {
+    // No newlines at start and end
+    assertEquals("optional_string: \"test newlines\\n\\nin\\nstring\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("test newlines\n\nin\nstring")
+            .build()));
+
+    // Newlines at start and end
+    assertEquals("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+            .build()));
+
+    // Strings with 0, 1 and 2 newlines.
+    assertEquals("optional_string: \"\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("")
+            .build()));
+    assertEquals("optional_string: \"\\n\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("\n")
+            .build()));
+    assertEquals("optional_string: \"\\n\\n\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("\n\n")
+            .build()));
+
+    // Test escaping roundtrip
+    TestAllTypes message = TestAllTypes.newBuilder()
+        .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+        .build();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+    assertEquals(message.getOptionalString(), builder.getOptionalString());
+  }
+
+  public void testPrintToUnicodeString_unknown() {
+    assertEquals(
+        "1: \"\\343\\201\\202\"\n",
+        TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+            .addField(1,
+                UnknownFieldSet.Field.newBuilder()
+                .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+            .build()));
+  }
+
+
+  public void testParseNonRepeatedFields() throws Exception {
+    assertParseSuccessWithOverwriteForbidden(
+        "repeated_int32: 1\n" +
+        "repeated_int32: 2\n");
+    assertParseSuccessWithOverwriteForbidden(
+        "RepeatedGroup { a: 1 }\n" +
+        "RepeatedGroup { a: 2 }\n");
+    assertParseSuccessWithOverwriteForbidden(
+        "repeated_nested_message { bb: 1 }\n" +
+        "repeated_nested_message { bb: 2 }\n");
+    assertParseErrorWithOverwriteForbidden(
+        "3:17: Non-repeated field " +
+        "\"protobuf_unittest.TestAllTypes.optional_int32\" " +
+        "cannot be overwritten.",
+        "optional_int32: 1\n" +
+        "optional_bool: true\n" +
+        "optional_int32: 1\n");
+    assertParseErrorWithOverwriteForbidden(
+        "2:17: Non-repeated field " +
+        "\"protobuf_unittest.TestAllTypes.optionalgroup\" " +
+        "cannot be overwritten.",
+        "OptionalGroup { a: 1 }\n" +
+        "OptionalGroup { }\n");
+    assertParseErrorWithOverwriteForbidden(
+        "2:33: Non-repeated field " +
+        "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " +
+        "cannot be overwritten.",
+        "optional_nested_message { }\n" +
+        "optional_nested_message { bb: 3 }\n");
+    assertParseErrorWithOverwriteForbidden(
+        "2:16: Non-repeated field " +
+        "\"protobuf_unittest.TestAllTypes.default_int32\" " +
+        "cannot be overwritten.",
+        "default_int32: 41\n" +  // the default value
+        "default_int32: 41\n");
+    assertParseErrorWithOverwriteForbidden(
+        "2:17: Non-repeated field " +
+        "\"protobuf_unittest.TestAllTypes.default_string\" " +
+        "cannot be overwritten.",
+        "default_string: \"zxcv\"\n" +
+        "default_string: \"asdf\"\n");
+  }
+
+  public void testParseShortRepeatedFormOfRepeatedFields() throws Exception {
+    assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR]");
+    assertParseSuccessWithOverwriteForbidden("repeated_int32: [ 1, 2 ]\n");
+    assertParseSuccessWithOverwriteForbidden("RepeatedGroup [{ a: 1 },{ a: 2 }]\n");
+    assertParseSuccessWithOverwriteForbidden("repeated_nested_message [{ bb: 1 }, { bb: 2 }]\n");
+  }
+
+  public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception {
+    assertParseErrorWithOverwriteForbidden(
+        "1:17: Couldn't parse integer: For input string: \"[\"",
+        "optional_int32: [1]\n");
+  }
+
+  // =======================================================================
+  // test oneof
+
+  public void testOneofTextFormat() throws Exception {
+    TestOneof2.Builder builder = TestOneof2.newBuilder();
+    TestUtil.setOneof(builder);
+    TestOneof2 message = builder.build();
+    TestOneof2.Builder dest = TestOneof2.newBuilder();
+    TextFormat.merge(TextFormat.printToUnicodeString(message), dest);
+    TestUtil.assertOneofSet(dest.build());
+  }
+
+  public void testOneofOverwriteForbidden() throws Exception {
+    String input = "foo_string: \"stringvalue\" foo_int: 123";
+    TestOneof2.Builder builder = TestOneof2.newBuilder();
+    try {
+      parserWithOverwriteForbidden.merge(
+          input, TestUtil.getExtensionRegistry(), builder);
+      fail("Expected parse exception.");
+    } catch (TextFormat.ParseException e) {
+      assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\""
+                   + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\","
+                   + " another member of oneof \"foo\".", e.getMessage());
+    }
+  }
+
+  public void testOneofOverwriteAllowed() throws Exception {
+    String input = "foo_string: \"stringvalue\" foo_int: 123";
+    TestOneof2.Builder builder = TestOneof2.newBuilder();
+    defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder);
+    // Only the last value sticks.
+    TestOneof2 oneof = builder.build();
+    assertFalse(oneof.hasFooString());
+    assertTrue(oneof.hasFooInt());
+  }
+
+  // =======================================================================
+  // test location information
+
+  public void testParseInfoTreeBuilding() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    TextFormatParseInfoTree.Builder treeBuilder = TextFormatParseInfoTree.builder();
+    // Set to allow unknown fields
+    TextFormat.Parser parser =
+        TextFormat.Parser.newBuilder()
+            .setParseInfoTreeBuilder(treeBuilder)
+            .build();
+
+    final String stringData =
+        "optional_int32: 1\n"
+        + "optional_int64: 2\n"
+        + "  optional_double: 2.4\n"
+        + "repeated_int32: 5\n"
+        + "repeated_int32: 10\n"
+        + "optional_nested_message <\n"
+        + "  bb: 78\n"
+        + ">\n"
+        + "repeated_nested_message <\n"
+        + "  bb: 79\n"
+        + ">\n"
+        + "repeated_nested_message <\n"
+        + "  bb: 80\n"
+        + ">";
+
+    parser.merge(stringData, builder);
+    TextFormatParseInfoTree tree = treeBuilder.build();
+
+    // Verify that the tree has the correct positions.
+    assertLocation(tree, descriptor, "optional_int32", 0, 0, 0);
+    assertLocation(tree, descriptor, "optional_int64", 0, 1, 0);
+    assertLocation(tree, descriptor, "optional_double", 0, 2, 2);
+
+    assertLocation(tree, descriptor, "repeated_int32", 0, 3, 0);
+    assertLocation(tree, descriptor, "repeated_int32", 1, 4, 0);
+
+    assertLocation(tree, descriptor, "optional_nested_message", 0, 5, 0);
+    assertLocation(tree, descriptor, "repeated_nested_message", 0, 8, 0);
+    assertLocation(tree, descriptor, "repeated_nested_message", 1, 11, 0);
+
+    // Check for fields not set. For an invalid field, the location returned should be -1, -1.
+    assertLocation(tree, descriptor, "repeated_int64", 0, -1, -1);
+    assertLocation(tree, descriptor, "repeated_int32", 6, -1, -1);
+
+    // Verify inside the nested message.
+    FieldDescriptor nestedField = descriptor.findFieldByName("optional_nested_message");
+
+    TextFormatParseInfoTree nestedTree = tree.getNestedTrees(nestedField).get(0);
+    assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 6, 2);
+
+    // Verify inside another nested message.
+    nestedField = descriptor.findFieldByName("repeated_nested_message");
+    nestedTree = tree.getNestedTrees(nestedField).get(0);
+    assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 9, 2);
+
+    nestedTree = tree.getNestedTrees(nestedField).get(1);
+    assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 12, 2);
+
+    // Verify a NULL tree for an unknown nested field.
+    try {
+      tree.getNestedTree(nestedField, 2);
+      fail("unknown nested field should throw");
+    } catch (IllegalArgumentException unused) {
+      // pass
+    }
+  }
+
+  private void assertLocation(
+      TextFormatParseInfoTree tree,
+      final Descriptor descriptor,
+      final String fieldName,
+      int index,
+      int line,
+      int column) {
+    List<TextFormatParseLocation> locs = tree.getLocations(descriptor.findFieldByName(fieldName));
+    if (index < locs.size()) {
+      TextFormatParseLocation location = locs.get(index);
+      TextFormatParseLocation expected = TextFormatParseLocation.create(line, column);
+      assertEquals(expected, location);
+    } else if (line != -1 && column != -1) {
+      fail(
+          String.format(
+              "Tree/descriptor/fieldname did not contain index %d, line %d column %d expected",
+              index,
+              line,
+              column));
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
new file mode 100644
index 0000000..8f45976
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
@@ -0,0 +1,255 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.TextFormat.ParseException;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that keep unknown enum values rather than discard
+ * them as unknown fields.
+ */
+public class UnknownEnumValueTest extends TestCase {
+  public void testUnknownEnumValues() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalNestedEnumValue(4321);
+    builder.addRepeatedNestedEnumValue(5432);
+    builder.addPackedNestedEnumValue(6543);
+    TestAllTypes message = builder.build();
+    assertEquals(4321, message.getOptionalNestedEnumValue());
+    assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+    assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+    assertEquals(6543, message.getPackedNestedEnumValue(0));
+    // Returns UNRECOGNIZED if an enum type is requested.
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+    
+    // Test serialization and parsing.
+    ByteString data = message.toByteString();
+    message = TestAllTypes.parseFrom(data);
+    assertEquals(4321, message.getOptionalNestedEnumValue());
+    assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+    assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+    assertEquals(6543, message.getPackedNestedEnumValue(0));
+    // Returns UNRECOGNIZED if an enum type is requested.
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+    
+    // Test toBuilder().
+    builder = message.toBuilder();
+    assertEquals(4321, builder.getOptionalNestedEnumValue());
+    assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+    assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+    assertEquals(6543, builder.getPackedNestedEnumValue(0));    
+    // Returns UNRECOGNIZED if an enum type is requested.
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+    
+    // Test mergeFrom().
+    builder = TestAllTypes.newBuilder().mergeFrom(message);
+    assertEquals(4321, builder.getOptionalNestedEnumValue());
+    assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+    assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+    assertEquals(6543, builder.getPackedNestedEnumValue(0));
+    // Returns UNRECOGNIZED if an enum type is requested.
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+    assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+    
+    // Test equals() and hashCode()
+    TestAllTypes sameMessage = builder.build();
+    assertEquals(message, sameMessage);
+    assertEquals(message.hashCode(), sameMessage.hashCode());
+
+    // Getting the numeric value of UNRECOGNIZED will throw an exception.
+    try {
+      TestAllTypes.NestedEnum.UNRECOGNIZED.getNumber();
+      fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    // Setting an enum field to an UNRECOGNIZED value will throw an exception.
+    try {
+      builder.setOptionalNestedEnum(builder.getOptionalNestedEnum());
+      fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+    try {
+      builder.addRepeatedNestedEnum(builder.getOptionalNestedEnum());
+      fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+  }
+  
+  public void testUnknownEnumValueInReflectionApi() throws Exception {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+    FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+    FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+    EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setField(optionalNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(4321));
+    builder.addRepeatedField(repeatedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(5432));
+    builder.addRepeatedField(packedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(6543));
+    TestAllTypes message = builder.build();
+    
+    // Getters will return unknown enum values as EnumValueDescriptor.
+    EnumValueDescriptor unknown4321 =
+        (EnumValueDescriptor) message.getField(optionalNestedEnumField);
+    EnumValueDescriptor unknown5432 =
+        (EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0);
+    EnumValueDescriptor unknown6543 =
+        (EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0);
+    assertEquals(4321, unknown4321.getNumber());
+    assertEquals(5432, unknown5432.getNumber());
+    assertEquals(6543, unknown6543.getNumber());
+    
+    // Unknown EnumValueDescriptor will map to UNRECOGNIZED.
+    assertEquals(
+        TestAllTypes.NestedEnum.valueOf(unknown4321),
+        TestAllTypes.NestedEnum.UNRECOGNIZED);
+    assertEquals(
+        TestAllTypes.NestedEnum.valueOf(unknown5432),
+        TestAllTypes.NestedEnum.UNRECOGNIZED);
+    assertEquals(
+        TestAllTypes.NestedEnum.valueOf(unknown6543),
+        TestAllTypes.NestedEnum.UNRECOGNIZED);
+    
+    // Setters also accept unknown EnumValueDescriptor.
+    builder.setField(optionalNestedEnumField, unknown6543);
+    builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);
+    builder.setRepeatedField(packedNestedEnumField, 0, unknown5432);
+    message = builder.build();
+    // Like other descriptors, unknown EnumValueDescriptor can be compared by
+    // object identity.
+    assertTrue(unknown6543 == message.getField(optionalNestedEnumField));
+    assertTrue(unknown4321 == message.getRepeatedField(repeatedNestedEnumField, 0));
+    assertTrue(unknown5432 == message.getRepeatedField(packedNestedEnumField, 0));
+  }
+  
+  public void testUnknownEnumValueWithDynamicMessage() throws Exception {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+    FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+    FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+    EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+    
+    Message dynamicMessageDefaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+
+    Message.Builder builder = dynamicMessageDefaultInstance.newBuilderForType();
+    builder.setField(optionalNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(4321));
+    builder.addRepeatedField(repeatedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(5432));
+    builder.addRepeatedField(packedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(6543));
+    Message message = builder.build();
+    assertEquals(4321,
+        ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+    assertEquals(5432,
+        ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+    assertEquals(6543,
+        ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+    
+    // Test reflection based serialization/parsing implementation.
+    ByteString data = message.toByteString();
+    message = dynamicMessageDefaultInstance
+        .newBuilderForType()
+        .mergeFrom(data)
+        .build();
+    assertEquals(4321,
+        ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+    assertEquals(5432,
+        ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+    assertEquals(6543,
+        ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+    
+    // Test reflection based equals()/hashCode().
+    builder = dynamicMessageDefaultInstance.newBuilderForType();
+    builder.setField(optionalNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(4321));
+    builder.addRepeatedField(repeatedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(5432));
+    builder.addRepeatedField(packedNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(6543));
+    Message sameMessage = builder.build();
+    assertEquals(message, sameMessage);
+    assertEquals(message.hashCode(), sameMessage.hashCode());
+    builder.setField(optionalNestedEnumField,
+        enumType.findValueByNumberCreatingIfUnknown(0));
+    Message differentMessage = builder.build();
+    assertFalse(message.equals(differentMessage));
+  }
+  
+  public void testUnknownEnumValuesInTextFormat() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.setOptionalNestedEnumValue(4321);
+    builder.addRepeatedNestedEnumValue(5432);
+    builder.addPackedNestedEnumValue(6543);
+    TestAllTypes message = builder.build();
+    
+    // We can print a message with unknown enum values.
+    String textData = TextFormat.printToString(message);
+    assertEquals(
+        "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n"
+        + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n"
+        + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", textData);
+    
+    // Parsing unknown enum values will fail just like parsing other kinds of
+    // unknown fields.
+    try {
+      TextFormat.merge(textData, builder);
+      fail();
+    } catch (ParseException e) {
+      // expected.
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
new file mode 100644
index 0000000..573cd66
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
@@ -0,0 +1,328 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Tests for {@link UnknownFieldSetLite}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class UnknownFieldSetLiteTest extends TestCase {
+  
+  public void testDefaultInstance() {
+    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+
+    assertEquals(0, unknownFields.getSerializedSize());
+    assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+  }
+
+  public void testMergeFieldFrom() throws IOException {
+    Foo foo = Foo.newBuilder()
+      .setValue(2)
+      .build();
+
+    CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+    UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+    instance.mergeFieldFrom(input.readTag(), input);
+
+    assertEquals(foo.toByteString(), toByteString(instance));
+  }
+
+  public void testSerializedSize() throws IOException {
+    Foo foo = Foo.newBuilder()
+      .setValue(2)
+      .build();
+
+    CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+    UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+    instance.mergeFieldFrom(input.readTag(), input);
+
+    assertEquals(foo.toByteString().size(), instance.getSerializedSize());
+  }
+
+  public void testMergeVarintField() throws IOException {
+    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+    unknownFields.mergeVarintField(10, 2);
+
+    CodedInputStream input =
+        CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+    int tag = input.readTag();
+    assertEquals(10, WireFormat.getTagFieldNumber(tag));
+    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+    assertEquals(2, input.readUInt64());
+    assertTrue(input.isAtEnd());
+  }
+
+  public void testMergeVarintField_negative() throws IOException {
+    UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance();
+    builder.mergeVarintField(10, -6);
+
+    CodedInputStream input =
+        CodedInputStream.newInstance(toByteString(builder).toByteArray());
+
+    int tag = input.readTag();
+    assertEquals(10, WireFormat.getTagFieldNumber(tag));
+    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+    assertEquals(-6, input.readUInt64());
+    assertTrue(input.isAtEnd());
+  }
+
+  public void testEqualsAndHashCode() {
+    UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance();
+    unknownFields1.mergeVarintField(10, 2);
+
+    UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance();
+    unknownFields2.mergeVarintField(10, 2);
+
+    assertEquals(unknownFields1, unknownFields2);
+    assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
+    assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance()));
+    assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
+  }
+
+  public void testMutableCopyOf() throws IOException {
+    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+    unknownFields.mergeVarintField(10, 2);
+    unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields);
+    unknownFields.checkMutable();
+
+    CodedInputStream input =
+        CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+    int tag = input.readTag();
+    assertEquals(10, WireFormat.getTagFieldNumber(tag));
+    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+    assertEquals(2, input.readUInt64());
+    assertFalse(input.isAtEnd());
+    input.readTag();
+    assertEquals(10, WireFormat.getTagFieldNumber(tag));
+    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+    assertEquals(2, input.readUInt64());
+    assertTrue(input.isAtEnd());
+  }
+
+  public void testMutableCopyOf_empty() {
+    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf(
+        UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
+    unknownFields.checkMutable();
+
+    assertEquals(0, unknownFields.getSerializedSize());
+    assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+  }
+
+  public void testRoundTrips() throws InvalidProtocolBufferException {
+    Foo foo = Foo.newBuilder()
+        .setValue(1)
+        .setExtension(Bar.fooExt, Bar.newBuilder()
+            .setName("name")
+            .build())
+        .setExtension(LiteEqualsAndHash.varint, 22)
+        .setExtension(LiteEqualsAndHash.fixed32, 44)
+        .setExtension(LiteEqualsAndHash.fixed64, 66L)
+        .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+            .setGroupValue("value")
+            .build())
+        .build();
+
+    Foo copy = Foo.parseFrom(foo.toByteArray());
+
+    assertEquals(foo.getSerializedSize(), copy.getSerializedSize());
+    assertFalse(foo.equals(copy));
+
+    Foo secondCopy = Foo.parseFrom(foo.toByteArray());
+    assertEquals(copy, secondCopy);
+
+    ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+    LiteEqualsAndHash.registerAllExtensions(extensionRegistry);
+    Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry);
+
+    assertEquals(foo, copyOfCopy);
+  }
+
+  public void testMalformedBytes() throws Exception {
+    try {
+      Foo.parseFrom("this is a malformed protocol buffer".getBytes(Internal.UTF_8));
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+
+  public void testMissingStartGroupTag() throws IOException {
+    ByteString.Output byteStringOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+    output.writeTag(100, WireFormat.WIRETYPE_END_GROUP);
+    output.flush();
+
+    try {
+      Foo.parseFrom(byteStringOutput.toByteString());
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+
+  public void testMissingEndGroupTag() throws IOException {
+    ByteString.Output byteStringOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+    output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+    output.flush();
+
+    try {
+      Foo.parseFrom(byteStringOutput.toByteString());
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+
+  public void testMismatchingGroupTags() throws IOException {
+    ByteString.Output byteStringOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+    output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+    output.writeTag(101, WireFormat.WIRETYPE_END_GROUP);
+    output.flush();
+
+    try {
+      Foo.parseFrom(byteStringOutput.toByteString());
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+
+  public void testTruncatedInput() {
+    Foo foo = Foo.newBuilder()
+        .setValue(1)
+        .setExtension(Bar.fooExt, Bar.newBuilder()
+            .setName("name")
+            .build())
+        .setExtension(LiteEqualsAndHash.varint, 22)
+        .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+            .setGroupValue("value")
+            .build())
+        .build();
+
+    try {
+      Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10));
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+  
+  public void testMakeImmutable() throws Exception {
+    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+    unknownFields.makeImmutable();
+    
+    try {
+      unknownFields.mergeVarintField(1, 1);
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    try {
+      unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello"));
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    try {
+      unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0]));
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+  }
+  
+  public void testEndToEnd() throws Exception {
+    TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance();
+    try {
+      testAllTypes.unknownFields.checkMutable();
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    testAllTypes = TestAllTypesLite.parseFrom(new byte[0]);
+    try {
+      testAllTypes.unknownFields.checkMutable();
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    testAllTypes = TestAllTypesLite.newBuilder().build();
+    try {
+      testAllTypes.unknownFields.checkMutable();
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    testAllTypes = TestAllTypesLite.newBuilder()
+        .setDefaultBool(true)
+        .build();
+    try {
+      testAllTypes.unknownFields.checkMutable();
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+    
+    TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder()
+        .mergeFrom(TestAllExtensionsLite.newBuilder()
+            .setExtension(UnittestLite.optionalInt32ExtensionLite, 2)
+            .build().toByteArray())
+        .build();
+    try {
+      testAllExtensions.unknownFields.checkMutable();
+      fail();
+    } catch (UnsupportedOperationException expected) {}
+  }
+
+  private ByteString toByteString(UnknownFieldSetLite unknownFields) {
+    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+    try {
+      unknownFields.writeTo(output);
+      output.flush();
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    return ByteString.copyFrom(byteArrayOutputStream.toByteArray());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
new file mode 100644
index 0000000..32380f7
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -0,0 +1,654 @@
+// 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.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Tests related to unknown field handling.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class UnknownFieldSetTest extends TestCase {
+  @Override
+  public void setUp() throws Exception {
+    descriptor = TestAllTypes.getDescriptor();
+    allFields = TestUtil.getAllSet();
+    allFieldsData = allFields.toByteString();
+    emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
+    unknownFields = emptyMessage.getUnknownFields();
+  }
+
+  UnknownFieldSet.Field getField(String name) {
+    Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
+    assertNotNull(field);
+    return unknownFields.getField(field.getNumber());
+  }
+
+  // Constructs a protocol buffer which contains fields with all the same
+  // numbers as allFieldsData except that each field is some other wire
+  // type.
+  ByteString getBizarroData() throws Exception {
+    UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();
+
+    UnknownFieldSet.Field varintField =
+      UnknownFieldSet.Field.newBuilder().addVarint(1).build();
+    UnknownFieldSet.Field fixed32Field =
+      UnknownFieldSet.Field.newBuilder().addFixed32(1).build();
+
+    for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+         unknownFields.asMap().entrySet()) {
+      if (entry.getValue().getVarintList().isEmpty()) {
+        // Original field is not a varint, so use a varint.
+        bizarroFields.addField(entry.getKey(), varintField);
+      } else {
+        // Original field *is* a varint, so use something else.
+        bizarroFields.addField(entry.getKey(), fixed32Field);
+      }
+    }
+
+    return bizarroFields.build().toByteString();
+  }
+
+  Descriptors.Descriptor descriptor;
+  TestAllTypes allFields;
+  ByteString allFieldsData;
+
+  // An empty message that has been parsed from allFieldsData.  So, it has
+  // unknown fields of every type.
+  TestEmptyMessage emptyMessage;
+  UnknownFieldSet unknownFields;
+
+  // =================================================================
+
+  public void testVarint() throws Exception {
+    UnknownFieldSet.Field field = getField("optional_int32");
+    assertEquals(1, field.getVarintList().size());
+    assertEquals(allFields.getOptionalInt32(),
+                 (long) field.getVarintList().get(0));
+  }
+
+  public void testFixed32() throws Exception {
+    UnknownFieldSet.Field field = getField("optional_fixed32");
+    assertEquals(1, field.getFixed32List().size());
+    assertEquals(allFields.getOptionalFixed32(),
+                 (int) field.getFixed32List().get(0));
+  }
+
+  public void testFixed64() throws Exception {
+    UnknownFieldSet.Field field = getField("optional_fixed64");
+    assertEquals(1, field.getFixed64List().size());
+    assertEquals(allFields.getOptionalFixed64(),
+                 (long) field.getFixed64List().get(0));
+  }
+
+  public void testLengthDelimited() throws Exception {
+    UnknownFieldSet.Field field = getField("optional_bytes");
+    assertEquals(1, field.getLengthDelimitedList().size());
+    assertEquals(allFields.getOptionalBytes(),
+                 field.getLengthDelimitedList().get(0));
+  }
+
+  public void testGroup() throws Exception {
+    Descriptors.FieldDescriptor nestedFieldDescriptor =
+      TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
+    assertNotNull(nestedFieldDescriptor);
+
+    UnknownFieldSet.Field field = getField("optionalgroup");
+    assertEquals(1, field.getGroupList().size());
+
+    UnknownFieldSet group = field.getGroupList().get(0);
+    assertEquals(1, group.asMap().size());
+    assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));
+
+    UnknownFieldSet.Field nestedField =
+      group.getField(nestedFieldDescriptor.getNumber());
+    assertEquals(1, nestedField.getVarintList().size());
+    assertEquals(allFields.getOptionalGroup().getA(),
+                 (long) nestedField.getVarintList().get(0));
+  }
+
+  public void testSerialize() throws Exception {
+    // Check that serializing the UnknownFieldSet produces the original data
+    // again.
+    ByteString data = emptyMessage.toByteString();
+    assertEquals(allFieldsData, data);
+  }
+
+  public void testCopyFrom() throws Exception {
+    TestEmptyMessage message =
+      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();
+
+    assertEquals(emptyMessage.toString(), message.toString());
+  }
+
+  public void testMergeFrom() throws Exception {
+    TestEmptyMessage source =
+      TestEmptyMessage.newBuilder()
+        .setUnknownFields(
+          UnknownFieldSet.newBuilder()
+            .addField(2,
+              UnknownFieldSet.Field.newBuilder()
+                .addVarint(2).build())
+            .addField(3,
+              UnknownFieldSet.Field.newBuilder()
+                .addVarint(4).build())
+            .build())
+        .build();
+    TestEmptyMessage destination =
+      TestEmptyMessage.newBuilder()
+        .setUnknownFields(
+          UnknownFieldSet.newBuilder()
+            .addField(1,
+              UnknownFieldSet.Field.newBuilder()
+                .addVarint(1).build())
+            .addField(3,
+              UnknownFieldSet.Field.newBuilder()
+                .addVarint(3).build())
+            .build())
+        .mergeFrom(source)
+        .build();
+
+    assertEquals(
+      "1: 1\n" +
+      "2: 2\n" +
+      "3: 3\n" +
+      "3: 4\n",
+      destination.toString());
+  }
+
+  public void testClear() throws Exception {
+    UnknownFieldSet fields =
+      UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
+    assertTrue(fields.asMap().isEmpty());
+  }
+
+  public void testClearMessage() throws Exception {
+    TestEmptyMessage message =
+      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
+    assertEquals(0, message.getSerializedSize());
+  }
+  
+  public void testClearField() throws Exception {
+    int fieldNumber = unknownFields.asMap().keySet().iterator().next();
+    UnknownFieldSet fields =
+        UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clearField(fieldNumber).build();
+    assertFalse(fields.hasField(fieldNumber));
+  }
+
+  public void testParseKnownAndUnknown() throws Exception {
+    // Test mixing known and unknown fields when parsing.
+
+    UnknownFieldSet fields =
+      UnknownFieldSet.newBuilder(unknownFields)
+        .addField(123456,
+          UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
+        .build();
+
+    ByteString data = fields.toByteString();
+    TestAllTypes destination = TestAllTypes.parseFrom(data);
+
+    TestUtil.assertAllFieldsSet(destination);
+    assertEquals(1, destination.getUnknownFields().asMap().size());
+
+    UnknownFieldSet.Field field =
+      destination.getUnknownFields().getField(123456);
+    assertEquals(1, field.getVarintList().size());
+    assertEquals(654321, (long) field.getVarintList().get(0));
+  }
+
+  public void testWrongTypeTreatedAsUnknown() throws Exception {
+    // Test that fields of the wrong wire type are treated like unknown fields
+    // when parsing.
+
+    ByteString bizarroData = getBizarroData();
+    TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+    // All fields should have been interpreted as unknown, so the debug strings
+    // should be the same.
+    assertEquals(emptyMessage.toString(), allTypesMessage.toString());
+  }
+
+  public void testUnknownExtensions() throws Exception {
+    // Make sure fields are properly parsed to the UnknownFieldSet even when
+    // they are declared as extension numbers.
+
+    TestEmptyMessageWithExtensions message =
+      TestEmptyMessageWithExtensions.parseFrom(allFieldsData);
+
+    assertEquals(unknownFields.asMap().size(),
+                 message.getUnknownFields().asMap().size());
+    assertEquals(allFieldsData, message.toByteString());
+  }
+
+  public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
+    // Test that fields of the wrong wire type are treated like unknown fields
+    // when parsing extensions.
+
+    ByteString bizarroData = getBizarroData();
+    TestAllExtensions allExtensionsMessage =
+      TestAllExtensions.parseFrom(bizarroData);
+    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+    // All fields should have been interpreted as unknown, so the debug strings
+    // should be the same.
+    assertEquals(emptyMessage.toString(),
+                 allExtensionsMessage.toString());
+  }
+
+  public void testParseUnknownEnumValue() throws Exception {
+    Descriptors.FieldDescriptor singularField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+    Descriptors.FieldDescriptor repeatedField =
+      TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+    assertNotNull(singularField);
+    assertNotNull(repeatedField);
+
+    ByteString data =
+      UnknownFieldSet.newBuilder()
+        .addField(singularField.getNumber(),
+          UnknownFieldSet.Field.newBuilder()
+            .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+            .addVarint(5)   // not valid
+            .build())
+        .addField(repeatedField.getNumber(),
+          UnknownFieldSet.Field.newBuilder()
+            .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+            .addVarint(4)   // not valid
+            .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+            .addVarint(6)   // not valid
+            .build())
+        .build()
+        .toByteString();
+
+    {
+      TestAllTypes message = TestAllTypes.parseFrom(data);
+      assertEquals(TestAllTypes.NestedEnum.BAR,
+                   message.getOptionalNestedEnum());
+      assertEquals(
+        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+        message.getRepeatedNestedEnumList());
+      assertEquals(Arrays.asList(5L),
+                   message.getUnknownFields()
+                          .getField(singularField.getNumber())
+                          .getVarintList());
+      assertEquals(Arrays.asList(4L, 6L),
+                   message.getUnknownFields()
+                          .getField(repeatedField.getNumber())
+                          .getVarintList());
+    }
+
+    {
+      TestAllExtensions message =
+        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+      assertEquals(TestAllTypes.NestedEnum.BAR,
+        message.getExtension(UnittestProto.optionalNestedEnumExtension));
+      assertEquals(
+        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+        message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+      assertEquals(Arrays.asList(5L),
+                   message.getUnknownFields()
+                          .getField(singularField.getNumber())
+                          .getVarintList());
+      assertEquals(Arrays.asList(4L, 6L),
+                   message.getUnknownFields()
+                          .getField(repeatedField.getNumber())
+                          .getVarintList());
+    }
+  }
+
+  public void testLargeVarint() throws Exception {
+    ByteString data =
+      UnknownFieldSet.newBuilder()
+        .addField(1,
+          UnknownFieldSet.Field.newBuilder()
+            .addVarint(0x7FFFFFFFFFFFFFFFL)
+            .build())
+        .build()
+        .toByteString();
+    UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
+    UnknownFieldSet.Field field = parsed.getField(1);
+    assertEquals(1, field.getVarintList().size());
+    assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
+  }
+
+  public void testEqualsAndHashCode() {
+    UnknownFieldSet.Field fixed32Field =
+        UnknownFieldSet.Field.newBuilder()
+            .addFixed32(1)
+            .build();
+    UnknownFieldSet.Field fixed64Field =
+        UnknownFieldSet.Field.newBuilder()
+            .addFixed64(1)
+            .build();
+    UnknownFieldSet.Field varIntField =
+        UnknownFieldSet.Field.newBuilder()
+            .addVarint(1)
+            .build();
+    UnknownFieldSet.Field lengthDelimitedField =
+        UnknownFieldSet.Field.newBuilder()
+            .addLengthDelimited(ByteString.EMPTY)
+            .build();
+    UnknownFieldSet.Field groupField =
+        UnknownFieldSet.Field.newBuilder()
+            .addGroup(unknownFields)
+            .build();
+
+    UnknownFieldSet a =
+        UnknownFieldSet.newBuilder()
+            .addField(1, fixed32Field)
+            .build();
+    UnknownFieldSet b =
+        UnknownFieldSet.newBuilder()
+            .addField(1, fixed64Field)
+            .build();
+    UnknownFieldSet c =
+        UnknownFieldSet.newBuilder()
+            .addField(1, varIntField)
+            .build();
+    UnknownFieldSet d =
+        UnknownFieldSet.newBuilder()
+            .addField(1, lengthDelimitedField)
+            .build();
+    UnknownFieldSet e =
+        UnknownFieldSet.newBuilder()
+            .addField(1, groupField)
+            .build();
+
+    checkEqualsIsConsistent(a);
+    checkEqualsIsConsistent(b);
+    checkEqualsIsConsistent(c);
+    checkEqualsIsConsistent(d);
+    checkEqualsIsConsistent(e);
+
+    checkNotEqual(a, b);
+    checkNotEqual(a, c);
+    checkNotEqual(a, d);
+    checkNotEqual(a, e);
+    checkNotEqual(b, c);
+    checkNotEqual(b, d);
+    checkNotEqual(b, e);
+    checkNotEqual(c, d);
+    checkNotEqual(c, e);
+    checkNotEqual(d, e);
+  }
+
+  /**
+   * Asserts that the given field sets are not equal and have different
+   * hash codes.
+   *
+   * @warning It's valid for non-equal objects to have the same hash code, so
+   *   this test is stricter than it needs to be. However, this should happen
+   *   relatively rarely.
+   */
+  private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
+    String equalsError = String.format("%s should not be equal to %s", s1, s2);
+    assertFalse(equalsError, s1.equals(s2));
+    assertFalse(equalsError, s2.equals(s1));
+
+    assertFalse(
+        String.format("%s should have a different hash code from %s", s1, s2),
+        s1.hashCode() == s2.hashCode());
+  }
+
+  /**
+   * Asserts that the given field sets are equal and have identical hash codes.
+   */
+  private void checkEqualsIsConsistent(UnknownFieldSet set) {
+    // Object should be equal to itself.
+    assertEquals(set, set);
+
+    // Object should be equal to a copy of itself.
+    UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
+    assertEquals(set, copy);
+    assertEquals(copy, set);
+    assertEquals(set.hashCode(), copy.hashCode());
+  }
+
+  // =================================================================
+
+  public void testSerializeLite() throws Exception {
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+    assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize());
+    ByteString data = emptyMessageLite.toByteString();
+    TestAllTypes message = TestAllTypes.parseFrom(data);
+    TestUtil.assertAllFieldsSet(message);
+    assertEquals(allFieldsData, data);
+  }
+
+  public void testAllExtensionsLite() throws Exception {
+    TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
+    ByteString allExtensionsData = allExtensions.toByteString();
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
+    ByteString data = emptyMessageLite.toByteString();
+    TestAllExtensions message =
+        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+    TestUtil.assertAllExtensionsSet(message);
+    assertEquals(allExtensionsData, data);
+  }
+
+  public void testAllPackedFieldsLite() throws Exception {
+    TestPackedTypes allPackedFields = TestUtil.getPackedSet();
+    ByteString allPackedData = allPackedFields.toByteString();
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData);
+    ByteString data = emptyMessageLite.toByteString();
+    TestPackedTypes message =
+        TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry());
+    TestUtil.assertPackedFieldsSet(message);
+    assertEquals(allPackedData, data);
+  }
+
+  public void testAllPackedExtensionsLite() throws Exception {
+    TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet();
+    ByteString allPackedExtensionsData = allPackedExtensions.toByteString();
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData);
+    ByteString data = emptyMessageLite.toByteString();
+    TestPackedExtensions message =
+        TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+    TestUtil.assertPackedExtensionsSet(message);
+    assertEquals(allPackedExtensionsData, data);
+  }
+
+  public void testCopyFromLite() throws Exception {
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+        UnittestLite.TestEmptyMessageLite.newBuilder()
+        .mergeFrom(emptyMessageLite).build();
+    assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString());
+  }
+
+  public void testMergeFromLite() throws Exception {
+    TestAllTypes message1 = TestAllTypes.newBuilder()
+        .setOptionalInt32(1)
+        .setOptionalString("foo")
+        .addRepeatedString("bar")
+        .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ)
+        .build();
+
+    TestAllTypes message2 = TestAllTypes.newBuilder()
+        .setOptionalInt64(2)
+        .setOptionalString("baz")
+        .addRepeatedString("qux")
+        .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ)
+        .build();
+
+    ByteString data1 = message1.toByteString();
+    UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+        UnittestLite.TestEmptyMessageLite.parseFrom(data1);
+    ByteString data2 = message2.toByteString();
+    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+        UnittestLite.TestEmptyMessageLite.parseFrom(data2);
+
+    message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build();
+    emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1)
+                        .mergeFrom(emptyMessageLite2).build();
+
+    data1 = emptyMessageLite1.toByteString();
+    message2 = TestAllTypes.parseFrom(data1);
+
+    assertEquals(message1, message2);
+  }
+
+  public void testWrongTypeTreatedAsUnknownLite() throws Exception {
+    // Test that fields of the wrong wire type are treated like unknown fields
+    // when parsing.
+
+    ByteString bizarroData = getBizarroData();
+    TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+    ByteString data = emptyMessageLite.toByteString();
+    TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data);
+
+    assertEquals(allTypesMessage.toString(), allTypesMessage2.toString());
+  }
+
+  public void testUnknownExtensionsLite() throws Exception {
+    // Make sure fields are properly parsed to the UnknownFieldSet even when
+    // they are declared as extension numbers.
+
+    UnittestLite.TestEmptyMessageWithExtensionsLite message =
+      UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData);
+
+    assertEquals(allFieldsData, message.toByteString());
+  }
+
+  public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception {
+    // Test that fields of the wrong wire type are treated like unknown fields
+    // when parsing extensions.
+
+    ByteString bizarroData = getBizarroData();
+    TestAllExtensions allExtensionsMessage =
+      TestAllExtensions.parseFrom(bizarroData);
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+
+    // All fields should have been interpreted as unknown, so the byte strings
+    // should be the same.
+    assertEquals(emptyMessageLite.toByteString(),
+                 allExtensionsMessage.toByteString());
+  }
+
+  public void testParseUnknownEnumValueLite() throws Exception {
+    Descriptors.FieldDescriptor singularField =
+      TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+    Descriptors.FieldDescriptor repeatedField =
+      TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+    assertNotNull(singularField);
+    assertNotNull(repeatedField);
+
+    ByteString data =
+      UnknownFieldSet.newBuilder()
+        .addField(singularField.getNumber(),
+          UnknownFieldSet.Field.newBuilder()
+            .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+            .addVarint(5)   // not valid
+            .build())
+        .addField(repeatedField.getNumber(),
+          UnknownFieldSet.Field.newBuilder()
+            .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+            .addVarint(4)   // not valid
+            .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+            .addVarint(6)   // not valid
+            .build())
+        .build()
+        .toByteString();
+
+    UnittestLite.TestEmptyMessageLite emptyMessageLite =
+        UnittestLite.TestEmptyMessageLite.parseFrom(data);
+    data = emptyMessageLite.toByteString();
+
+    {
+      TestAllTypes message = TestAllTypes.parseFrom(data);
+      assertEquals(TestAllTypes.NestedEnum.BAR,
+                   message.getOptionalNestedEnum());
+      assertEquals(
+        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+        message.getRepeatedNestedEnumList());
+      assertEquals(Arrays.asList(5L),
+                   message.getUnknownFields()
+                          .getField(singularField.getNumber())
+                          .getVarintList());
+      assertEquals(Arrays.asList(4L, 6L),
+                   message.getUnknownFields()
+                          .getField(repeatedField.getNumber())
+                          .getVarintList());
+    }
+
+    {
+      TestAllExtensions message =
+        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+      assertEquals(TestAllTypes.NestedEnum.BAR,
+        message.getExtension(UnittestProto.optionalNestedEnumExtension));
+      assertEquals(
+        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+        message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+      assertEquals(Arrays.asList(5L),
+                   message.getUnknownFields()
+                          .getField(singularField.getNumber())
+                          .getVarintList());
+      assertEquals(Arrays.asList(4L, 6L),
+                   message.getUnknownFields()
+                          .getField(repeatedField.getNumber())
+                          .getVarintList());
+    }
+  }
+
+  public void testClearLite() throws Exception {
+    UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+        UnittestLite.TestEmptyMessageLite.newBuilder()
+        .mergeFrom(emptyMessageLite1).clear().build();
+    assertEquals(0, emptyMessageLite2.getSerializedSize());
+    ByteString data = emptyMessageLite2.toByteString();
+    assertEquals(0, data.size());
+  }
+
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
new file mode 100644
index 0000000..b1c75fc
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
@@ -0,0 +1,227 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Tests for {@link UnmodifiableLazyStringList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringListTest extends TestCase {
+
+  private static String STRING_A = "A";
+  private static String STRING_B = "B";
+  private static String STRING_C = "C";
+
+  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+  public void testReadOnlyMethods() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+    assertEquals(3, list.size());
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_B, list.get(1));
+    assertSame(STRING_C, list.get(2));
+    assertEquals(BYTE_STRING_A, list.getByteString(0));
+    assertEquals(BYTE_STRING_B, list.getByteString(1));
+    assertEquals(BYTE_STRING_C, list.getByteString(2));
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    assertSame(list.getByteString(0), byteStringList.get(0));
+    assertSame(list.getByteString(1), byteStringList.get(1));
+    assertSame(list.getByteString(2), byteStringList.get(2));
+  }
+
+  public void testModifyMethods() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    try {
+      list.remove(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+
+    try {
+      list.add(STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+
+    try {
+      list.set(1, STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    try {
+      byteStringList.remove(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+    assertEquals(3, byteStringList.size());
+
+    try {
+      byteStringList.add(BYTE_STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+    assertEquals(3, byteStringList.size());
+
+    try {
+      byteStringList.set(1, BYTE_STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+    assertEquals(3, byteStringList.size());
+  }
+
+  public void testIterator() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    Iterator<String> iter = list.iterator();
+    int count = 0;
+    while (iter.hasNext()) {
+      iter.next();
+      count++;
+      try {
+        iter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    Iterator<ByteString> byteIter = byteStringList.iterator();
+    count = 0;
+    while (byteIter.hasNext()) {
+      byteIter.next();
+      count++;
+      try {
+        byteIter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+  }
+
+  public void testListIterator() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    ListIterator<String> iter = list.listIterator();
+    int count = 0;
+    while (iter.hasNext()) {
+      iter.next();
+      count++;
+      try {
+        iter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        iter.set("bar");
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        iter.add("bar");
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+
+    List<ByteString> byteStringList = list.asByteStringList();
+    ListIterator<ByteString> byteIter = byteStringList.listIterator();
+    count = 0;
+    while (byteIter.hasNext()) {
+      byteIter.next();
+      count++;
+      try {
+        byteIter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        byteIter.set(BYTE_STRING_A);
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        byteIter.add(BYTE_STRING_A);
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+  }
+
+  private LazyStringArrayList createSampleList() {
+    LazyStringArrayList rawList = new LazyStringArrayList();
+    rawList.add(STRING_A);
+    rawList.add(STRING_B);
+    rawList.add(STRING_C);
+    return rawList;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
new file mode 100644
index 0000000..982e200
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
@@ -0,0 +1,65 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.test.TestWellKnownTypes;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test ensures that well-known types are included in protobuf Java
+ * runtime library.
+ */
+public class WellKnownTypesTest extends TestCase {
+  public void testWellKnownTypes() {
+    // The test passes if it compiles.
+    TestWellKnownTypes message = TestWellKnownTypes.newBuilder().build();
+    assertEquals(0, message.getAnyField().getSerializedSize());
+    assertEquals(0, message.getApiField().getSerializedSize());
+    assertEquals(0, message.getDurationField().getSerializedSize());
+    assertEquals(0, message.getEmptyField().getSerializedSize());
+    assertEquals(0, message.getFieldMaskField().getSerializedSize());
+    assertEquals(0, message.getSourceContextField().getSerializedSize());
+    assertEquals(0, message.getStructField().getSerializedSize());
+    assertEquals(0, message.getTimestampField().getSerializedSize());
+    assertEquals(0, message.getTypeField().getSerializedSize());
+    assertEquals(0, message.getInt32Field().getSerializedSize());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WireFormatTest.java b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
new file mode 100644
index 0000000..e66b371
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -0,0 +1,606 @@
+// 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import protobuf_unittest.UnittestMset.RawMessageSet;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestFieldOrderings;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+/**
+ * Tests related to parsing and serialization.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class WireFormatTest extends TestCase {
+  public void testSerialization() throws Exception {
+    TestAllTypes message = TestUtil.getAllSet();
+
+    ByteString rawBytes = message.toByteString();
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+    TestUtil.assertAllFieldsSet(message2);
+  }
+
+  public void testSerializationPacked() throws Exception {
+    TestPackedTypes message = TestUtil.getPackedSet();
+
+    ByteString rawBytes = message.toByteString();
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+    TestUtil.assertPackedFieldsSet(message2);
+  }
+
+  public void testSerializeExtensions() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+    // it should work.
+
+    TestAllExtensions message = TestUtil.getAllExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+    TestUtil.assertAllFieldsSet(message2);
+  }
+
+  public void testSerializePackedExtensions() throws Exception {
+    // TestPackedTypes and TestPackedExtensions should have compatible wire
+    // formats; check that they serialize to the same string.
+    TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    TestPackedTypes message2 = TestUtil.getPackedSet();
+    ByteString rawBytes2 = message2.toByteString();
+
+    assertEquals(rawBytes, rawBytes2);
+  }
+
+  public void testSerializationPackedWithoutGetSerializedSize()
+      throws Exception {
+    // Write directly to an OutputStream, without invoking getSerializedSize()
+    // This used to be a bug where the size of a packed field was incorrect,
+    // since getSerializedSize() was never invoked.
+    TestPackedTypes message = TestUtil.getPackedSet();
+
+    // Directly construct a CodedOutputStream around the actual OutputStream,
+    // in case writeTo(OutputStream output) invokes getSerializedSize();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
+
+    message.writeTo(codedOutput);
+
+    codedOutput.flush();
+
+    TestPackedTypes message2 = TestPackedTypes.parseFrom(
+        outputStream.toByteArray());
+
+    TestUtil.assertPackedFieldsSet(message2);
+  }
+
+  public void testSerializeExtensionsLite() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+    // it should work.
+
+    TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+    TestUtil.assertAllFieldsSet(message2);
+  }
+
+  public void testSerializePackedExtensionsLite() throws Exception {
+    // TestPackedTypes and TestPackedExtensions should have compatible wire
+    // formats; check that they serialize to the same string.
+    TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    TestPackedTypes message2 = TestUtil.getPackedSet();
+    ByteString rawBytes2 = message2.toByteString();
+
+    assertEquals(rawBytes, rawBytes2);
+  }
+
+  public void testParseExtensions() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+    // it should work.
+
+    TestAllTypes message = TestUtil.getAllSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+    TestAllExtensions message2 =
+      TestAllExtensions.parseFrom(rawBytes, registry);
+
+    TestUtil.assertAllExtensionsSet(message2);
+  }
+
+  public void testParsePackedExtensions() throws Exception {
+    // Ensure that packed extensions can be properly parsed.
+    TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+    TestPackedExtensions message2 =
+        TestPackedExtensions.parseFrom(rawBytes, registry);
+
+    TestUtil.assertPackedExtensionsSet(message2);
+  }
+
+  public void testParseExtensionsLite() throws Exception {
+    // TestAllTypes and TestAllExtensions should have compatible wire formats,
+    // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+    // it should work.
+
+    TestAllTypes message = TestUtil.getAllSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistryLite registry_lite = TestUtilLite.getExtensionRegistryLite();
+
+    TestAllExtensionsLite message2 =
+      TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
+
+    TestUtil.assertAllExtensionsSet(message2);
+
+    // Try again using a full extension registry.
+    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+    TestAllExtensionsLite message3 =
+      TestAllExtensionsLite.parseFrom(rawBytes, registry);
+
+    TestUtil.assertAllExtensionsSet(message3);
+  }
+
+  public void testParsePackedExtensionsLite() throws Exception {
+    // Ensure that packed extensions can be properly parsed.
+    TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
+    ByteString rawBytes = message.toByteString();
+
+    ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite();
+
+    TestPackedExtensionsLite message2 =
+        TestPackedExtensionsLite.parseFrom(rawBytes, registry);
+
+    TestUtil.assertPackedExtensionsSet(message2);
+  }
+
+  public void testExtensionsSerializedSize() throws Exception {
+    assertNotSame(TestUtil.getAllSet().getSerializedSize(),
+                  TestUtil.getAllExtensionsSet().getSerializedSize());
+  }
+
+  public void testSerializeDelimited() throws Exception {
+    ByteArrayOutputStream output = new ByteArrayOutputStream();
+    TestUtil.getAllSet().writeDelimitedTo(output);
+    output.write(12);
+    TestUtil.getPackedSet().writeDelimitedTo(output);
+    output.write(34);
+
+    ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+
+    TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
+    assertEquals(12, input.read());
+    TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
+    assertEquals(34, input.read());
+    assertEquals(-1, input.read());
+
+    // We're at EOF, so parsing again should return null.
+    assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
+  }
+
+  private void assertFieldsInOrder(ByteString data) throws Exception {
+    CodedInputStream input = data.newCodedInput();
+    int previousTag = 0;
+
+    while (true) {
+      int tag = input.readTag();
+      if (tag == 0) {
+        break;
+      }
+
+      assertTrue(tag > previousTag);
+      previousTag = tag;
+      input.skipField(tag);
+    }
+  }
+
+  public void testInterleavedFieldsAndExtensions() throws Exception {
+    // Tests that fields are written in order even when extension ranges
+    // are interleaved with field numbers.
+    ByteString data =
+      TestFieldOrderings.newBuilder()
+        .setMyInt(1)
+        .setMyString("foo")
+        .setMyFloat(1.0F)
+        .setExtension(UnittestProto.myExtensionInt, 23)
+        .setExtension(UnittestProto.myExtensionString, "bar")
+        .build().toByteString();
+    assertFieldsInOrder(data);
+
+    Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+    ByteString dynamic_data =
+      DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+        .setField(descriptor.findFieldByName("my_int"), 1L)
+        .setField(descriptor.findFieldByName("my_string"), "foo")
+        .setField(descriptor.findFieldByName("my_float"), 1.0F)
+        .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+        .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+        .build().toByteString();
+    assertFieldsInOrder(dynamic_data);
+  }
+
+  private ExtensionRegistry getTestFieldOrderingsRegistry() {
+    ExtensionRegistry result = ExtensionRegistry.newInstance();
+    result.add(UnittestProto.myExtensionInt);
+    result.add(UnittestProto.myExtensionString);
+    return result;
+  }
+
+  public void testParseMultipleExtensionRanges() throws Exception {
+    // Make sure we can parse a message that contains multiple extensions
+    // ranges.
+    TestFieldOrderings source =
+      TestFieldOrderings.newBuilder()
+        .setMyInt(1)
+        .setMyString("foo")
+        .setMyFloat(1.0F)
+        .setExtension(UnittestProto.myExtensionInt, 23)
+        .setExtension(UnittestProto.myExtensionString, "bar")
+        .build();
+    TestFieldOrderings dest =
+      TestFieldOrderings.parseFrom(source.toByteString(),
+                                   getTestFieldOrderingsRegistry());
+    assertEquals(source, dest);
+  }
+
+  public void testParseMultipleExtensionRangesDynamic() throws Exception {
+    // Same as above except with DynamicMessage.
+    Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+    DynamicMessage source =
+      DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+        .setField(descriptor.findFieldByName("my_int"), 1L)
+        .setField(descriptor.findFieldByName("my_string"), "foo")
+        .setField(descriptor.findFieldByName("my_float"), 1.0F)
+        .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+        .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+        .build();
+    DynamicMessage dest =
+      DynamicMessage.parseFrom(descriptor, source.toByteString(),
+                               getTestFieldOrderingsRegistry());
+    assertEquals(source, dest);
+  }
+
+  private static final int UNKNOWN_TYPE_ID = 1550055;
+  private static final int TYPE_ID_1 =
+    TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
+  private static final int TYPE_ID_2 =
+    TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
+
+  public void testSerializeMessageSetEagerly() throws Exception {
+    testSerializeMessageSetWithFlag(true);
+  }
+
+  public void testSerializeMessageSetNotEagerly() throws Exception {
+    testSerializeMessageSetWithFlag(false);
+  }
+
+  private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    // Set up a TestMessageSet with two known messages and an unknown one.
+    TestMessageSet messageSet =
+      TestMessageSet.newBuilder()
+        .setExtension(
+          TestMessageSetExtension1.messageSetExtension,
+          TestMessageSetExtension1.newBuilder().setI(123).build())
+        .setExtension(
+          TestMessageSetExtension2.messageSetExtension,
+          TestMessageSetExtension2.newBuilder().setStr("foo").build())
+        .setUnknownFields(
+          UnknownFieldSet.newBuilder()
+            .addField(UNKNOWN_TYPE_ID,
+              UnknownFieldSet.Field.newBuilder()
+                .addLengthDelimited(ByteString.copyFromUtf8("bar"))
+                .build())
+            .build())
+        .build();
+
+    ByteString data = messageSet.toByteString();
+
+    // Parse back using RawMessageSet and check the contents.
+    RawMessageSet raw = RawMessageSet.parseFrom(data);
+
+    assertTrue(raw.getUnknownFields().asMap().isEmpty());
+
+    assertEquals(3, raw.getItemCount());
+    assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
+    assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
+    assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
+
+    TestMessageSetExtension1 message1 =
+      TestMessageSetExtension1.parseFrom(
+        raw.getItem(0).getMessage().toByteArray());
+    assertEquals(123, message1.getI());
+
+    TestMessageSetExtension2 message2 =
+      TestMessageSetExtension2.parseFrom(
+        raw.getItem(1).getMessage().toByteArray());
+    assertEquals("foo", message2.getStr());
+
+    assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
+  }
+
+  public void testParseMessageSetEagerly() throws Exception {
+    testParseMessageSetWithFlag(true);
+  }
+
+  public void testParseMessageSetNotEagerly()throws Exception {
+    testParseMessageSetWithFlag(false);
+  }
+
+  private void testParseMessageSetWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+    extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+    // Set up a RawMessageSet with two known messages and an unknown one.
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_2)
+            .setMessage(
+              TestMessageSetExtension2.newBuilder()
+                .setStr("foo")
+                .build().toByteString())
+            .build())
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(UNKNOWN_TYPE_ID)
+            .setMessage(ByteString.copyFromUtf8("bar"))
+            .build())
+        .build();
+
+    ByteString data = raw.toByteString();
+
+    // Parse as a TestMessageSet and check the contents.
+    TestMessageSet messageSet =
+      TestMessageSet.parseFrom(data, extensionRegistry);
+
+    assertEquals(123, messageSet.getExtension(
+      TestMessageSetExtension1.messageSetExtension).getI());
+    assertEquals("foo", messageSet.getExtension(
+      TestMessageSetExtension2.messageSetExtension).getStr());
+
+    // Check for unknown field with type LENGTH_DELIMITED,
+    //   number UNKNOWN_TYPE_ID, and contents "bar".
+    UnknownFieldSet unknownFields = messageSet.getUnknownFields();
+    assertEquals(1, unknownFields.asMap().size());
+    assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
+
+    UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
+    assertEquals(1, field.getLengthDelimitedList().size());
+    assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
+  }
+
+  public void testParseMessageSetExtensionEagerly() throws Exception {
+    testParseMessageSetExtensionWithFlag(true);
+  }
+
+  public void testParseMessageSetExtensionNotEagerly() throws Exception {
+    testParseMessageSetExtensionWithFlag(false);
+  }
+
+  private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    ByteString data = raw.toByteString();
+
+    // Parse as a TestMessageSet and check the contents.
+    TestMessageSet messageSet =
+        TestMessageSet.parseFrom(data, extensionRegistry);
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+    testMergeLazyMessageSetExtensionWithFlag(true);
+  }
+
+  public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+    testMergeLazyMessageSetExtensionWithFlag(false);
+  }
+
+  private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    ByteString data = raw.toByteString();
+
+    // Parse as a TestMessageSet and store value into lazy field
+    TestMessageSet messageSet =
+        TestMessageSet.parseFrom(data, extensionRegistry);
+    // Merge lazy field check the contents.
+    messageSet =
+        messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  public void testMergeMessageSetExtensionEagerly() throws Exception {
+    testMergeMessageSetExtensionWithFlag(true);
+  }
+
+  public void testMergeMessageSetExtensionNotEagerly() throws Exception {
+    testMergeMessageSetExtensionWithFlag(false);
+  }
+
+  private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    // Serialize RawMessageSet unnormally (message value before type id)
+    ByteString.CodedBuilder out = ByteString.newCodedBuilder(
+        raw.getSerializedSize());
+    CodedOutputStream output = out.getCodedOutput();
+    List<RawMessageSet.Item> items = raw.getItemList();
+    for (int i = 0; i < items.size(); i++) {
+      RawMessageSet.Item item = items.get(i);
+      output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
+      output.writeBytes(3, item.getMessage());
+      output.writeInt32(2, item.getTypeId());
+      output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
+    }
+    ByteString data = out.build();
+
+    // Merge bytes into TestMessageSet and check the contents.
+    TestMessageSet messageSet =
+        TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  // ================================================================
+  // oneof
+  public void testOneofWireFormat() throws Exception {
+    TestOneof2.Builder builder = TestOneof2.newBuilder();
+    TestUtil.setOneof(builder);
+    TestOneof2 message = builder.build();
+    ByteString rawBytes = message.toByteString();
+
+    assertEquals(rawBytes.size(), message.getSerializedSize());
+
+    TestOneof2 message2 = TestOneof2.parseFrom(rawBytes);
+    TestUtil.assertOneofSet(message2);
+  }
+
+  public void testOneofOnlyLastSet() throws Exception {
+    TestOneofBackwardsCompatible source = TestOneofBackwardsCompatible
+        .newBuilder().setFooInt(100).setFooString("101").build();
+
+    ByteString rawBytes = source.toByteString();
+    TestOneof2 message = TestOneof2.parseFrom(rawBytes);
+    assertFalse(message.hasFooInt());
+    assertTrue(message.hasFooString());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/any_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/any_test.proto
new file mode 100644
index 0000000..80173d8
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/any_test.proto
@@ -0,0 +1,42 @@
+// 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.
+
+syntax = "proto3";
+
+package any_test;
+
+option java_package = "any_test";
+option java_outer_classname = "AnyTestProto";
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+  google.protobuf.Any value = 1;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto
new file mode 100644
index 0000000..8f3ca8c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto
@@ -0,0 +1,93 @@
+// 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.
+
+syntax = "proto3";
+
+package field_presence_test;
+
+import "google/protobuf/unittest.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldPresenceTestProto";
+option java_generate_equals_and_hash = true;
+
+message TestAllTypes {
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+  }
+  message NestedMessage {
+    int32 value = 1;
+  }
+
+  int32 optional_int32 = 1;
+  string optional_string = 2;
+  bytes optional_bytes = 3;
+  NestedEnum optional_nested_enum = 4;
+  NestedMessage optional_nested_message = 5;
+  protobuf_unittest.TestRequired optional_proto2_message = 6;
+
+  oneof oneof_field {
+    int32 oneof_int32 = 11;
+    uint32 oneof_uint32 = 12;
+    string oneof_string = 13;
+    bytes oneof_bytes = 14;
+    NestedEnum oneof_nested_enum = 15;
+    NestedMessage oneof_nested_message = 16;
+    protobuf_unittest.TestRequired oneof_proto2_message = 17;
+  }
+
+  repeated int32 repeated_int32 = 21;
+  repeated string repeated_string = 22;
+  repeated bytes repeated_bytes = 23;
+  repeated NestedEnum repeated_nested_enum = 24;
+  repeated NestedMessage repeated_nested_message = 25;
+  repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+  repeated NestedEnum packed_nested_enum = 27 [packed = true];
+}
+
+message TestOptionalFieldsOnly {
+  int32 optional_int32 = 1;
+  string optional_string = 2;
+  bytes optional_bytes = 3;
+  TestAllTypes.NestedEnum optional_nested_enum = 4;
+  TestAllTypes.NestedMessage optional_nested_message = 5;
+  protobuf_unittest.TestRequired optional_proto2_message = 6;
+}
+
+message TestRepeatedFieldsOnly {
+  repeated int32 repeated_int32 = 21;
+  repeated string repeated_string = 22;
+  repeated bytes repeated_bytes = 23;
+  repeated TestAllTypes.NestedEnum repeated_nested_enum = 24;
+  repeated TestAllTypes.NestedMessage repeated_nested_message = 25;
+  repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
new file mode 100644
index 0000000..5580f72
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
@@ -0,0 +1,71 @@
+// 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.
+
+// Author: Naoki Iwasaki (niwasaki@google.com)
+//
+// A proto file with lazy fields
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message LazyMessageLite {
+  optional int32 num = 1;
+  optional int32 num_with_default = 2 [default = 421];
+  optional LazyInnerMessageLite inner = 3 [lazy = true];
+  repeated LazyInnerMessageLite repeated_inner = 4 [lazy = true];
+
+  oneof oneof_field {
+    int32 oneof_num = 5;
+    LazyInnerMessageLite oneof_inner = 6 [lazy = true];
+  }
+}
+
+message LazyInnerMessageLite {
+  optional int32 num = 1;
+  optional int32 num_with_default = 2 [default = 42];
+  optional LazyNestedInnerMessageLite nested = 3 [lazy = true];
+
+  extensions 1000 to max;
+}
+
+message LazyExtension {
+  extend LazyInnerMessageLite {
+    optional LazyExtension extension = 1000;
+  }
+  optional string name = 1;
+}
+
+message LazyNestedInnerMessageLite {
+  optional int32 num = 1;
+  optional int32 num_with_default = 2 [default = 4];
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
new file mode 100644
index 0000000..6eef42c
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
@@ -0,0 +1,81 @@
+// 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.
+
+// Author: pbogle@google.com (Phil Bogle)
+
+syntax = "proto2";
+
+package protobuf_unittest.lite_equals_and_hash;
+
+option optimize_for = LITE_RUNTIME;
+
+message TestOneofEquals {
+  oneof oneof_field {
+    string name = 1;
+    int32 value = 2;
+  }
+}
+
+message Foo {
+  optional int32 value = 1;
+  repeated Bar bar = 2;
+
+  extensions 100 to max;
+}
+
+message Bar {
+  extend Foo {
+    optional Bar foo_ext = 100;
+  }
+
+  optional string name = 1;
+}
+
+message BarPrime {
+  optional string name = 1;
+}
+
+message Empty {
+}
+
+extend Foo {
+  optional int32 varint = 101;
+  optional fixed32 fixed32 = 102;
+  optional fixed64 fixed64 = 103;
+  optional group MyGroup = 104 {
+    optional string group_value = 1;
+  }
+}
+
+message TestRecursiveOneof {
+  oneof Foo {
+    TestRecursiveOneof r = 1;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
new file mode 100644
index 0000000..d5418f2
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -0,0 +1,75 @@
+// 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.
+
+syntax = "proto2";
+
+
+option java_outer_classname = "MapForProto2TestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+  message MessageValue {
+    optional int32 value = 1;
+  }
+  enum EnumValue {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+
+  map<int32, int32>         int32_to_int32_field = 1;
+  map<int32, string>        int32_to_string_field = 2;
+  map<int32, bytes>         int32_to_bytes_field = 3;
+  map<int32, EnumValue>     int32_to_enum_field = 4;
+  map<int32, MessageValue>  int32_to_message_field = 5;
+  map<string, int32>        string_to_int32_field = 6;
+
+  message MessageWithRequiredFields {
+    required int32 value = 1;
+  }
+  map<int32, MessageWithRequiredFields> required_message_map = 11;
+}
+
+message TestUnknownEnumValue {
+  // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+  // parsing behavior of TestMap regarding unknown enum values.
+  map<int32, int32> int32_to_int32_field = 4;
+}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+  optional int32 value = 1;
+  map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
+package map_for_proto2_lite_test;
+option java_package = "map_lite_test";
+option optimize_for = LITE_RUNTIME;
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto
new file mode 100644
index 0000000..a9be516
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto
@@ -0,0 +1,74 @@
+// 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.
+
+syntax = "proto2";
+
+package map_for_proto2_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapForProto2TestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+  message MessageValue {
+    optional int32 value = 1;
+  }
+  enum EnumValue {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+
+  map<int32, int32>         int32_to_int32_field = 1;
+  map<int32, string>        int32_to_string_field = 2;
+  map<int32, bytes>         int32_to_bytes_field = 3;
+  map<int32, EnumValue>     int32_to_enum_field = 4;
+  map<int32, MessageValue>  int32_to_message_field = 5;
+  map<string, int32>        string_to_int32_field = 6;
+
+  message MessageWithRequiredFields {
+    required int32 value = 1;
+  }
+  map<int32, MessageWithRequiredFields> required_message_map = 11;
+}
+
+message TestUnknownEnumValue {
+  // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+  // parsing behavior of TestMap regarding unknown enum values.
+  map<int32, int32> int32_to_int32_field = 4;
+}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+  optional int32 value = 1;
+  map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto
new file mode 100644
index 0000000..b02ac59
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto
@@ -0,0 +1,61 @@
+// 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.
+
+// Regression test for a map initilaization order bug. The bug only manifests
+// when:
+//   1. A message contains map fields and is also extendable.
+//   2. There is a file-level extension defined in the same file referencing
+//      the above message as the extension type.
+//   3. The program executes in the following order:
+//        a. getDescriptor() is called on another message in the same file.
+//        b. use protobuf reflection to access the map field.
+// The symptom is a NullPointerException being thrown.
+syntax = "proto2";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapInitializationOrderTest";
+option java_multiple_files = true;
+
+// Mirrors the structure of
+// javatests/com/google/cloud/common/logging/logging_test.proto.
+
+message Message1 {
+  map<string, bool> map_field = 1;
+  extensions 1000 to max;
+}
+
+extend Message1 {
+  optional Message1 recursive_extension = 1001;
+}
+
+message RedactAllTypes {
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_test.proto
new file mode 100644
index 0000000..2280ac0
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/map_test.proto
@@ -0,0 +1,63 @@
+// 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.
+
+syntax = "proto3";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapTestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+  message MessageValue {
+    int32 value = 1;
+  }
+  enum EnumValue {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+
+  map<int32, int32>        int32_to_int32_field = 1;
+  map<int32, string>       int32_to_string_field = 2;
+  map<int32, bytes>        int32_to_bytes_field = 3;
+  map<int32, EnumValue>    int32_to_enum_field = 4;
+  map<int32, MessageValue> int32_to_message_field = 5;
+  map<string, int32>       string_to_int32_field = 6;
+}
+
+// Used to test that a nested bulider containing map fields will properly
+// propagate the onChange event and mark its parent dirty when a change
+// is made to a map field.
+message TestOnChangeEventPropagation {
+  TestMap optional_message = 1;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
new file mode 100644
index 0000000..9279050
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
@@ -0,0 +1,78 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// A proto file which tests the java_multiple_files option.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option java_generic_services = true;   // auto-added
+
+import "google/protobuf/unittest.proto";
+import "google/protobuf/descriptor.proto";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "MultipleFilesTestProto";
+
+
+message MessageWithNoOuter {
+  message NestedMessage {
+    optional int32 i = 1;
+  }
+  enum NestedEnum {
+    BAZ = 3;
+  }
+  optional NestedMessage nested = 1;
+  repeated TestAllTypes foreign = 2;
+  optional NestedEnum nested_enum = 3;
+  optional EnumWithNoOuter foreign_enum = 4;
+}
+
+extend google.protobuf.EnumValueOptions {
+  optional int32 enum_value_option = 7654321;
+}
+
+enum EnumWithNoOuter {
+  FOO = 1 [(enum_value_option) = 12345];
+  BAR = 2;
+}
+
+service ServiceWithNoOuter {
+  rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
+}
+
+extend TestAllExtensions {
+  optional int32 extension_with_outer = 1234567;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto
new file mode 100644
index 0000000..a5dd66d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto
@@ -0,0 +1,54 @@
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+//
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "NestedBuilders";
+
+
+message Vehicle {
+  optional Engine engine = 1;
+  repeated Wheel wheel = 2;
+}
+
+message Engine {
+  optional int32 cylinder = 1;
+  optional int32 liters = 2;
+}
+
+message Wheel {
+  optional int32 radius = 1;
+  optional int32 width = 2;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
new file mode 100644
index 0000000..704e649
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
@@ -0,0 +1,47 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions. Note that this must be defined in
+// a separate file to properly test the initialization of the outer class.
+
+syntax = "proto2";
+
+import "com/google/protobuf/non_nested_extension.proto";
+
+package protobuf_unittest;
+
+
+message MyNestedExtension {
+  extend MessageToBeExtended {
+    optional MessageToBeExtended recursiveExtension = 2;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
new file mode 100644
index 0000000..a95c38b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
@@ -0,0 +1,49 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions for a MessageLite messages. Note that
+// this must be defined in a separate file to properly test the initialization
+// of the outer class.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+import "com/google/protobuf/non_nested_extension_lite.proto";
+
+message MyNestedExtensionLite {
+  extend MessageLiteToBeExtended {
+    optional MessageLiteToBeExtended recursiveExtensionLite = 3;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto
new file mode 100644
index 0000000..31fac55
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto
@@ -0,0 +1,50 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message MessageToBeExtended {
+  extensions 1 to max;
+}
+
+message MyNonNestedExtension {
+}
+
+extend MessageToBeExtended {
+  optional MyNonNestedExtension nonNestedExtension = 1;
+}
+
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
new file mode 100644
index 0000000..37c369e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions for a MessageLite messages.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message MessageLiteToBeExtended {
+  extensions 1 to max;
+}
+
+message MyNonNestedExtensionLite {
+}
+
+extend MessageLiteToBeExtended {
+  optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
+}
+
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto
new file mode 100644
index 0000000..4208368
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto
@@ -0,0 +1,40 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+// This message's name is the same with the default outer class name of this
+// proto file. It's used to test if the compiler can avoid this conflict
+// correctly.
+message OuterClassNameTest {
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto
new file mode 100644
index 0000000..3e5956b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto
@@ -0,0 +1,44 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message TestMessage2 {
+  message NestedMessage {
+    // This message's name is the same with the default outer class name of this
+    // proto file. It's used to test if the compiler can avoid this conflict
+    // correctly.
+    message OuterClassNameTest2 {
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto
new file mode 100644
index 0000000..74a8ba3
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto
@@ -0,0 +1,45 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message TestMessage3 {
+  message NestedMessage {
+    // This enum's name is the same with the default outer class name of this
+    // proto file. It's used to test if the compiler can avoid this conflict
+    // correctly.
+    enum OuterClassNameTest3 {
+      DUMMY_VALUE = 1;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
new file mode 100644
index 0000000..2b1f65e
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
@@ -0,0 +1,169 @@
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the java code generator.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option java_generic_services = true;   // auto-added
+
+package io_protocol_tests;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TestBadIdentifiersProto";
+option java_generate_equals_and_hash = true;
+
+message TestMessage {
+  optional string cached_size = 1;
+  optional string serialized_size = 2;
+  optional string class = 3;
+}
+
+message Descriptor {
+  option no_standard_descriptor_accessor = true;
+  optional string descriptor = 1;
+  message NestedDescriptor {
+    option no_standard_descriptor_accessor = true;
+    optional string descriptor = 1;
+  }
+  optional NestedDescriptor nested_descriptor = 2;
+  enum NestedEnum {
+    UNKNOWN = 0;
+    FOO = 1;
+  }
+}
+
+message Parser {
+  enum ParserEnum {
+    UNKNOWN = 0;
+    PARSER = 1;
+  }
+  optional ParserEnum parser = 1;
+}
+
+message Deprecated {
+  enum TestEnum {
+    UNKNOWN = 0;
+    FOO = 1;
+
+    // Test if @Deprecated annotation conflicts with Deprecated message name.
+    BAR = 2 [ deprecated = true ];
+  }
+
+  optional int32 field1 = 1 [deprecated=true];
+  optional TestEnum field2 = 2 [deprecated=true];
+  optional TestMessage field3 = 3 [deprecated=true];
+}
+
+message Override {
+  optional int32 override = 1;
+}
+
+message Object {
+  optional int32 object = 1;
+  optional string string_object = 2;
+}
+
+message String {
+  optional string string = 1;
+}
+
+message Integer {
+  optional int32 integer = 1;
+}
+
+message Long {
+  optional int32 long = 1;
+}
+
+message Float {
+  optional float float = 1;
+}
+
+message Double {
+  optional double double = 1;
+}
+
+service TestConflictingMethodNames {
+  rpc Override(TestMessage) returns (TestMessage);
+}
+
+message TestConflictingFieldNames {
+  enum TestEnum {
+    UNKNOWN = 0;
+    FOO = 1;
+  }
+  message TestMessage {
+  }
+  repeated int32 int32_field = 1;
+  repeated TestEnum enum_field = 2;
+  repeated string string_field = 3;
+  repeated bytes bytes_field = 4;
+  repeated TestMessage message_field = 5;
+
+  optional int32 int32_field_count = 11;
+  optional TestEnum enum_field_count = 12;
+  optional string string_field_count = 13;
+  optional bytes bytes_field_count = 14;
+  optional TestMessage message_field_count = 15;
+
+  repeated int32 Int32Field = 21;  // NO_PROTO3
+  repeated TestEnum EnumField = 22;  // NO_PROTO3
+  repeated string StringField = 23;  // NO_PROTO3
+  repeated bytes BytesField = 24;  // NO_PROTO3
+  repeated TestMessage MessageField = 25;  // NO_PROTO3
+
+  // This field conflicts with "int32_field" as they both generate
+  // the method getInt32FieldList().
+  required int32 int32_field_list = 31;  // NO_PROTO3
+
+  extensions 1000 to max;  // NO_PROTO3
+
+  repeated int64 int64_field = 41;
+  extend TestConflictingFieldNames {  // NO_PROTO3
+    // We don't generate accessors for extensions so the following extension
+    // fields don't conflict with the repeated field "int64_field".
+    optional int64 int64_field_count = 1001;  // NO_PROTO3
+    optional int64 int64_field_list = 1002;  // NO_PROTO3
+  }  // NO_PROTO3
+}
+
+message TestMapField {
+  message MapField {}
+  message Pair {}
+  message Message {}
+
+  map<int32, int32> map_field = 1;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto
new file mode 100644
index 0000000..119c1dc
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: Jacob Butcher (jbaum@google.com)
+//
+// Test file option java_string_check_utf8.
+syntax = "proto2";
+
+package proto2_test_check_utf8;
+
+option java_outer_classname = "TestCheckUtf8";
+option java_string_check_utf8 = true;
+
+message StringWrapper {
+  required string req = 1;
+  optional string opt = 2;
+  repeated string rep = 3;
+}
+
+message BytesWrapper {
+  required bytes req = 1;
+  optional bytes opt = 2;
+  repeated bytes rep = 3;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto
new file mode 100644
index 0000000..f06d76d
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// Author: Jacob Butcher (jbaum@google.com)
+//
+// Test file option java_string_check_utf8.
+syntax = "proto2";
+
+package proto2_test_check_utf8_size;
+
+option java_outer_classname = "TestCheckUtf8Size";
+option java_string_check_utf8 = true;
+option optimize_for = CODE_SIZE;
+
+message StringWrapperSize {
+  required string req = 1;
+  optional string opt = 2;
+  repeated string rep = 3;
+}
+
+message BytesWrapperSize {
+  required bytes req = 1;
+  optional bytes opt = 2;
+  repeated bytes rep = 3;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto
new file mode 100644
index 0000000..f8efd45
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto
@@ -0,0 +1,44 @@
+// 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.
+
+// Author: Feng Xiao (xiaofeng@google.com)
+//
+// Test that custom options defined in a proto file's dependencies are properly
+// initialized.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+import "google/protobuf/unittest_custom_options.proto";
+
+message TestMessageWithCustomOptionsContainer {
+  optional TestMessageWithCustomOptions field = 1;
+}
diff --git a/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
new file mode 100644
index 0000000..645f57b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
@@ -0,0 +1,61 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message Proto1 {
+  option experimental_java_message_interface =
+      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
+
+  option experimental_java_interface_extends =
+      "com.google.protobuf.ExtraInterfaces.HasByteValue";
+
+  option experimental_java_message_interface =
+      "com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
+
+  option experimental_java_builder_interface =
+      "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder"
+      "<Proto1, Builder>";
+
+  optional string string_value = 1;
+  optional bool bool_value = 2;
+  optional bytes byte_value = 3;
+  optional int32 int_value = 4;
+}
+
+message Proto2 {
+  option experimental_java_message_interface =
+      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
+
+  optional bool bool_value = 1;
+}
diff --git a/src/third_party/protobuf-3/java/lite/generate-sources-build.xml b/src/third_party/protobuf-3/java/lite/generate-sources-build.xml
new file mode 100644
index 0000000..89c21c1
--- /dev/null
+++ b/src/third_party/protobuf-3/java/lite/generate-sources-build.xml
@@ -0,0 +1,20 @@
+<project name="generate-sources">
+    <echo message="Running protoc ..."/>
+    <mkdir dir="${generated.sources.lite.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=lite:${generated.sources.lite.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+    </exec>
+</project>
diff --git a/src/third_party/protobuf-3/java/lite/generate-test-sources-build.xml b/src/third_party/protobuf-3/java/lite/generate-test-sources-build.xml
new file mode 100644
index 0000000..cdd1ee8
--- /dev/null
+++ b/src/third_party/protobuf-3/java/lite/generate-test-sources-build.xml
@@ -0,0 +1,43 @@
+<project name="generate-test-sources">
+    <mkdir dir="${generated.testsources.lite.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=lite:${generated.testsources.lite.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="--proto_path=${test.proto.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
+    </exec>
+</project>
diff --git a/src/third_party/protobuf-3/java/lite/pom.xml b/src/third_party/protobuf-3/java/lite/pom.xml
new file mode 100644
index 0000000..c403dc0
--- /dev/null
+++ b/src/third_party/protobuf-3/java/lite/pom.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>3.0.0-beta-3</version>
+  </parent>
+
+  <artifactId>protobuf-lite</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Protocol Buffers [Lite]</name>
+  <description>A trimmed-down version of the Protocol Buffers library.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <core.root>../core</core.root>
+    <test.proto.dir>${core.root}/src/test/proto</test.proto.dir>
+  </properties>
+
+  <build>
+    <sourceDirectory>${core.root}/src/main/java</sourceDirectory>
+    <testSourceDirectory>${core.root}/src/test/java</testSourceDirectory>
+
+    <plugins>
+      <!-- Use Antrun plugin to generate sources with protoc -->
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <!-- Generate core protos -->
+          <execution>
+            <id>generate-sources</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+
+          <!-- Generate the test protos -->
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-test-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Only compile a subset of the files -->
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <generatedSourcesDirectory>${generated.sources.lite.dir}</generatedSourcesDirectory>
+          <generatedTestSourcesDirectory>${generated.testsources.lite.dir}</generatedTestSourcesDirectory>
+          <includes>
+            <include>**/AbstractMessageLite.java</include>
+            <include>**/AbstractParser.java</include>
+            <include>**/AbstractProtobufList.java</include>
+            <include>**/BooleanArrayList.java</include>
+            <include>**/ByteString.java</include>
+            <include>**/CodedInputStream.java</include>
+            <include>**/CodedOutputStream.java</include>
+            <include>**/DoubleArrayList.java</include>
+            <include>**/ExtensionLite.java</include>
+            <include>**/ExtensionRegistryLite.java</include>
+            <include>**/FieldSet.java</include>
+            <include>**/FloatArrayList.java</include>
+            <include>**/GeneratedMessageLite.java</include>
+            <include>**/IntArrayList.java</include>
+            <include>**/Internal.java</include>
+            <include>**/InvalidProtocolBufferException.java</include>
+            <include>**/LazyFieldLite.java</include>
+            <include>**/LazyStringArrayList.java</include>
+            <include>**/LazyStringList.java</include>
+            <include>**/LongArrayList.java</include>
+            <include>**/MapEntryLite.java</include>
+            <include>**/MapFieldLite.java</include>
+            <include>**/MessageLite.java</include>
+            <include>**/MessageLiteOrBuilder.java</include>
+            <include>**/MessageLiteToString.java</include>
+            <include>**/MutabilityOracle.java</include>
+            <include>**/NioByteString.java</include>
+            <include>**/Parser.java</include>
+            <include>**/ProtobufArrayList.java</include>
+            <include>**/ProtocolStringList.java</include>
+            <include>**/RopeByteString.java</include>
+            <include>**/SmallSortedMap.java</include>
+            <include>**/TextFormatEscaper.java</include>
+            <include>**/UninitializedMessageException.java</include>
+            <include>**/UnknownFieldSetLite.java</include>
+            <include>**/UnmodifiableLazyStringList.java</include>
+            <include>**/UnsafeByteOperations.java</include>
+            <include>**/Utf8.java</include>
+            <include>**/WireFormat.java</include>
+          </includes>
+          <testIncludes>
+            <testInclude>**/*Lite.java</testInclude>
+            <testInclude>**/BooleanArrayListTest.java</testInclude>
+            <testInclude>**/DoubleArrayListTest.java</testInclude>
+            <testInclude>**/FloatArrayListTest.java</testInclude>
+            <testInclude>**/IntArrayListTest.java</testInclude>
+            <testInclude>**/LazyMessageLiteTest.java</testInclude>
+            <testInclude>**/LiteTest.java</testInclude>
+            <testInclude>**/LongArrayListTest.java</testInclude>
+            <testInclude>**/NioByteStringTest.java</testInclude>
+            <testInclude>**/ProtobufArrayListTest.java</testInclude>
+            <testInclude>**/UnknownFieldSetLiteTest.java</testInclude>
+          </testIncludes>
+        </configuration>
+      </plugin>
+
+      <!-- OSGI bundle configuration -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+            <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
+            <Export-Package>com.google.${project.artifactId};version=${project.version}</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/src/third_party/protobuf-3/java/pom.xml b/src/third_party/protobuf-3/java/pom.xml
new file mode 100644
index 0000000..7a1a91f
--- /dev/null
+++ b/src/third_party/protobuf-3/java/pom.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google</groupId>
+    <artifactId>google</artifactId>
+    <version>1</version>
+  </parent>
+
+  <groupId>com.google.protobuf</groupId>
+  <artifactId>protobuf-parent</artifactId>
+  <version>3.0.0-beta-3</version>
+  <packaging>pom</packaging>
+
+  <name>Protocol Buffers [Parent]</name>
+  <inceptionYear>2008</inceptionYear>
+  <url>https://developers.google.com/protocol-buffers/</url>
+  <description>
+    Protocol Buffers are a way of encoding structured data in an efficient yet
+    extensible format.
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+    <!-- These are relative to the submodules -->
+    <protobuf.basedir>${project.basedir}/../..</protobuf.basedir>
+    <protobuf.source.dir>${protobuf.basedir}/src</protobuf.source.dir>
+    <protoc>${protobuf.source.dir}/protoc</protoc>
+    <test.proto.dir>src/test/proto</test.proto.dir>
+    <generated.sources.dir>${project.build.directory}/generated-sources</generated.sources.dir>
+    <generated.testsources.dir>${project.build.directory}/generated-test-sources</generated.testsources.dir>
+    <generated.sources.lite.dir>${project.build.directory}/generated-sources-lite</generated.sources.lite.dir>
+    <generated.testsources.lite.dir>${project.build.directory}/generated-test-sources-lite</generated.testsources.lite.dir>
+  </properties>
+
+  <licenses>
+    <license>
+      <name>New BSD license</name>
+      <url>http://www.opensource.org/licenses/bsd-license.php</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+
+  <scm>
+    <url>https://github.com/google/protobuf</url>
+    <connection>scm:git:https://github.com/google/protobuf.git</connection>
+  </scm>
+
+  <distributionManagement>
+    <snapshotRepository>
+      <id>sonatype-nexus-staging</id>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+    </snapshotRepository>
+    <repository>
+      <id>sonatype-nexus-staging</id>
+      <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+    </repository>
+  </distributionManagement>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>4.12</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.easymock</groupId>
+        <artifactId>easymock</artifactId>
+        <version>2.2</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.easymock</groupId>
+        <artifactId>easymockclassextension</artifactId>
+        <version>2.2.1</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava</artifactId>
+        <version>18.0</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.3</version>
+          <configuration>
+            <source>1.6</source>
+            <target>1.6</target>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-source-plugin</artifactId>
+          <version>2.4</version>
+          <executions>
+            <execution>
+              <id>attach-sources</id>
+              <goals>
+                <goal>jar-no-fork</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>2.10.3</version>
+          <executions>
+            <execution>
+              <id>attach-javadocs</id>
+              <goals>
+                <goal>jar</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.6</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>build-helper-maven-plugin</artifactId>
+          <version>1.10</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.felix</groupId>
+          <artifactId>maven-bundle-plugin</artifactId>
+          <version>3.0.1</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-antrun-plugin</artifactId>
+          <version>1.8</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.6</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>nexus-staging-maven-plugin</artifactId>
+            <version>1.6.6</version>
+            <extensions>true</extensions>
+            <configuration>
+              <serverId>sonatype-nexus-staging</serverId>
+              <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+              <autoReleaseAfterClose>false</autoReleaseAfterClose>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <modules>
+    <module>core</module>
+    <module>lite</module>
+    <module>util</module>
+  </modules>
+
+</project>
diff --git a/src/third_party/protobuf-3/java/util/pom.xml b/src/third_party/protobuf-3/java/util/pom.xml
new file mode 100644
index 0000000..9236f90
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>3.0.0-beta-3</version>
+  </parent>
+
+  <artifactId>protobuf-java-util</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Protocol Buffers [Util]</name>
+  <description>Utilities for Protocol Buffers</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>protobuf-java</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+      <version>2.3</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <!-- Use the core proto dir so that we can call the core generation script -->
+    <test.proto.dir>../core/src/test/proto</test.proto.dir>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <!-- Generate the test protos -->
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <!-- Generate all of the test protos from the core module -->
+                <ant antfile="../core/generate-test-sources-build.xml"/>
+
+                <!-- Generate additional test protos for this module -->
+                <exec executable="${protoc}">
+                  <arg value="--java_out=${generated.testsources.dir}" />
+                  <arg value="--proto_path=${protobuf.source.dir}" />
+                  <arg value="--proto_path=src/test/proto" />
+                  <arg value="src/test/proto/com/google/protobuf/util/json_test.proto" />
+                </exec>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <!-- Add the generated test sources to the build -->
+          <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory>
+        </configuration>
+      </plugin>
+
+      <!-- Configure the OSGI bundle -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+            <Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
+            <Export-Package>com.google.protobuf.util;version=${project.version}</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+
+      <!-- Configure the fat jar to include all dependencies -->
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptorRefs>
+            <descriptorRef>jar-with-dependencies</descriptorRef>
+          </descriptorRefs>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
new file mode 100644
index 0000000..668d65a
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -0,0 +1,276 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Message;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.logging.Logger;
+
+/**
+ * A tree representation of a FieldMask. Each leaf node in this tree represent
+ * a field path in the FieldMask.
+ *
+ * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be:
+ * <pre>
+ *   [root] -+- foo -+- bar
+ *           |       |
+ *           |       +- baz
+ *           |
+ *           +- bar --- baz
+ * </pre>
+ *
+ * <p>By representing FieldMasks with this tree structure we can easily convert
+ * a FieldMask to a canonical form, merge two FieldMasks, calculate the
+ * intersection to two FieldMasks and traverse all fields specified by the
+ * FieldMask in a message tree.
+ */
+class FieldMaskTree {
+  private static final Logger logger = Logger.getLogger(FieldMaskTree.class.getName());
+
+  private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
+
+  private static class Node {
+    public TreeMap<String, Node> children = new TreeMap<String, Node>();
+  }
+
+  private final Node root = new Node();
+
+  /** Creates an empty FieldMaskTree. */
+  public FieldMaskTree() {}
+
+  /** Creates a FieldMaskTree for a given FieldMask. */
+  public FieldMaskTree(FieldMask mask) {
+    mergeFromFieldMask(mask);
+  }
+
+  @Override
+  public String toString() {
+    return FieldMaskUtil.toString(toFieldMask());
+  }
+
+  /**
+   * Adds a field path to the tree. In a FieldMask, every field path matches the
+   * specified field as well as all its sub-fields. For example, a field path
+   * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
+   * a field path to the tree, redundant sub-paths will be removed. That is,
+   * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
+   * exists, which will turn the tree node for "foo.bar" to a leaf node.
+   * Likewise, if the field path to add is a sub-path of an existing leaf node,
+   * nothing will be changed in the tree.
+   */
+  public FieldMaskTree addFieldPath(String path) {
+    String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+    if (parts.length == 0) {
+      return this;
+    }
+    Node node = root;
+    boolean createNewBranch = false;
+    // Find the matching node in the tree.
+    for (String part : parts) {
+      // Check whether the path matches an existing leaf node.
+      if (!createNewBranch && node != root && node.children.isEmpty()) {
+        // The path to add is a sub-path of an existing leaf node.
+        return this;
+      }
+      if (node.children.containsKey(part)) {
+        node = node.children.get(part);
+      } else {
+        createNewBranch = true;
+        Node tmp = new Node();
+        node.children.put(part, tmp);
+        node = tmp;
+      }
+    }
+    // Turn the matching node into a leaf node (i.e., remove sub-paths).
+    node.children.clear();
+    return this;
+  }
+
+  /**
+   * Merges all field paths in a FieldMask into this tree.
+   */
+  public FieldMaskTree mergeFromFieldMask(FieldMask mask) {
+    for (String path : mask.getPathsList()) {
+      addFieldPath(path);
+    }
+    return this;
+  }
+
+  /** Converts this tree to a FieldMask. */
+  public FieldMask toFieldMask() {
+    if (root.children.isEmpty()) {
+      return FieldMask.getDefaultInstance();
+    }
+    List<String> paths = new ArrayList<String>();
+    getFieldPaths(root, "", paths);
+    return FieldMask.newBuilder().addAllPaths(paths).build();
+  }
+
+  /** Gathers all field paths in a sub-tree. */
+  private void getFieldPaths(Node node, String path, List<String> paths) {
+    if (node.children.isEmpty()) {
+      paths.add(path);
+      return;
+    }
+    for (Entry<String, Node> entry : node.children.entrySet()) {
+      String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
+      getFieldPaths(entry.getValue(), childPath, paths);
+    }
+  }
+
+  /**
+   * Adds the intersection of this tree with the given {@code path} to
+   * {@code output}.
+   */
+  public void intersectFieldPath(String path, FieldMaskTree output) {
+    if (root.children.isEmpty()) {
+      return;
+    }
+    String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+    if (parts.length == 0) {
+      return;
+    }
+    Node node = root;
+    for (String part : parts) {
+      if (node != root && node.children.isEmpty()) {
+        // The given path is a sub-path of an existing leaf node in the tree.
+        output.addFieldPath(path);
+        return;
+      }
+      if (node.children.containsKey(part)) {
+        node = node.children.get(part);
+      } else {
+        return;
+      }
+    }
+    // We found a matching node for the path. All leaf children of this matching
+    // node is in the intersection.
+    List<String> paths = new ArrayList<String>();
+    getFieldPaths(node, path, paths);
+    for (String value : paths) {
+      output.addFieldPath(value);
+    }
+  }
+
+  /**
+   * Merges all fields specified by this FieldMaskTree from {@code source} to
+   * {@code destination}.
+   */
+  public void merge(
+      Message source, Message.Builder destination, FieldMaskUtil.MergeOptions options) {
+    if (source.getDescriptorForType() != destination.getDescriptorForType()) {
+      throw new IllegalArgumentException("Cannot merge messages of different types.");
+    }
+    if (root.children.isEmpty()) {
+      return;
+    }
+    merge(root, "", source, destination, options);
+  }
+
+  /** Merges all fields specified by a sub-tree from {@code source} to
+   * {@code destination}.
+   */
+  private void merge(
+      Node node,
+      String path,
+      Message source,
+      Message.Builder destination,
+      FieldMaskUtil.MergeOptions options) {
+    assert source.getDescriptorForType() == destination.getDescriptorForType();
+
+    Descriptor descriptor = source.getDescriptorForType();
+    for (Entry<String, Node> entry : node.children.entrySet()) {
+      FieldDescriptor field = descriptor.findFieldByName(entry.getKey());
+      if (field == null) {
+        logger.warning(
+            "Cannot find field \""
+                + entry.getKey()
+                + "\" in message type "
+                + descriptor.getFullName());
+        continue;
+      }
+      if (!entry.getValue().children.isEmpty()) {
+        if (field.isRepeated() || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+          logger.warning(
+              "Field \""
+                  + field.getFullName()
+                  + "\" is not a "
+                  + "singluar message field and cannot have sub-fields.");
+          continue;
+        }
+        String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
+        merge(
+            entry.getValue(),
+            childPath,
+            (Message) source.getField(field),
+            destination.getFieldBuilder(field),
+            options);
+        continue;
+      }
+      if (field.isRepeated()) {
+        if (options.replaceRepeatedFields()) {
+          destination.setField(field, source.getField(field));
+        } else {
+          for (Object element : (List) source.getField(field)) {
+            destination.addRepeatedField(field, element);
+          }
+        }
+      } else {
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          if (options.replaceMessageFields()) {
+            if (!source.hasField(field)) {
+              destination.clearField(field);
+            } else {
+              destination.setField(field, source.getField(field));
+            }
+          } else {
+            if (source.hasField(field)) {
+              destination.getFieldBuilder(field).mergeFrom((Message) source.getField(field));
+            }
+          }
+        } else {
+          if (source.hasField(field) || !options.replacePrimitiveFields()) {
+            destination.setField(field, source.getField(field));
+          } else {
+            destination.clearField(field);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
new file mode 100644
index 0000000..9696152
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -0,0 +1,314 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.primitives.Ints;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Internal;
+import com.google.protobuf.Message;
+
+import java.util.Arrays;
+
+/**
+ * Utility helper functions to work with {@link com.google.protobuf.FieldMask}.
+ */
+public class FieldMaskUtil {
+  private static final String FIELD_PATH_SEPARATOR = ",";
+  private static final String FIELD_PATH_SEPARATOR_REGEX = ",";
+  private static final String FIELD_SEPARATOR_REGEX = "\\.";
+  
+  private FieldMaskUtil() {}
+
+  /**
+   * Converts a FieldMask to a string.
+   */
+  public static String toString(FieldMask fieldMask) {
+    // TODO(xiaofeng): Consider using com.google.common.base.Joiner here instead.
+    StringBuilder result = new StringBuilder();
+    boolean first = true;
+    for (String value : fieldMask.getPathsList()) {
+      if (value.isEmpty()) {
+        // Ignore empty paths.
+        continue;
+      }
+      if (first) {
+        first = false;
+      } else {
+        result.append(FIELD_PATH_SEPARATOR);
+      }
+      result.append(value);
+    }
+    return result.toString();
+  }
+
+  /**
+   * Parses from a string to a FieldMask.
+   */
+  public static FieldMask fromString(String value) {
+    // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
+    return fromStringList(
+        null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+  }
+
+  /**
+   * Parses from a string to a FieldMask and validates all field paths.
+   * 
+   * @throws IllegalArgumentException if any of the field path is invalid.
+   */
+  public static FieldMask fromString(Class<? extends Message> type, String value) {
+    // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
+    return fromStringList(
+        type, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+  }
+
+  /**
+   * Constructs a FieldMask for a list of field paths in a certain type.
+   *
+   * @throws IllegalArgumentException if any of the field path is not valid.
+   */
+  // TODO(xiaofeng): Consider renaming fromStrings()
+  public static FieldMask fromStringList(
+      Class<? extends Message> type, Iterable<String> paths) {
+    FieldMask.Builder builder = FieldMask.newBuilder();
+    for (String path : paths) {
+      if (path.isEmpty()) {
+        // Ignore empty field paths.
+        continue;
+      }
+      if (type != null && !isValid(type, path)) {
+        throw new IllegalArgumentException(
+            path + " is not a valid path for " + type);
+      }
+      builder.addPaths(path);
+    }
+    return builder.build();
+  }
+
+  /**
+   * Constructs a FieldMask from the passed field numbers.
+   *
+   * @throws IllegalArgumentException if any of the fields are invalid for the message.
+   */
+  public static FieldMask fromFieldNumbers(Class<? extends Message> type, int... fieldNumbers) {
+    return fromFieldNumbers(type, Ints.asList(fieldNumbers));
+  }
+
+  /**
+   * Constructs a FieldMask from the passed field numbers.
+   *
+   * @throws IllegalArgumentException if any of the fields are invalid for the message.
+   */
+  public static FieldMask fromFieldNumbers(
+      Class<? extends Message> type, Iterable<Integer> fieldNumbers) {
+    Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
+
+    FieldMask.Builder builder = FieldMask.newBuilder();
+    for (Integer fieldNumber : fieldNumbers) {
+      FieldDescriptor field = descriptor.findFieldByNumber(fieldNumber);
+      checkArgument(
+          field != null,
+          String.format("%s is not a valid field number for %s.", fieldNumber, type));
+      builder.addPaths(field.getName());
+    }
+    return builder.build();
+  }
+
+  /**
+   * Checks whether paths in a given fields mask are valid.
+   */
+  public static boolean isValid(Class<? extends Message> type, FieldMask fieldMask) {
+    Descriptor descriptor =
+        Internal.getDefaultInstance(type).getDescriptorForType();
+    
+    return isValid(descriptor, fieldMask);
+  }
+  
+  /**
+   * Checks whether paths in a given fields mask are valid.
+   */
+  public static boolean isValid(Descriptor descriptor, FieldMask fieldMask) {
+    for (String path : fieldMask.getPathsList()) {
+      if (!isValid(descriptor, path)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Checks whether a given field path is valid.
+   */
+  public static boolean isValid(Class<? extends Message> type, String path) {
+    Descriptor descriptor =
+        Internal.getDefaultInstance(type).getDescriptorForType();
+    
+    return isValid(descriptor, path);
+  }
+
+  /**
+   * Checks whether paths in a given fields mask are valid.
+   */
+  public static boolean isValid(Descriptor descriptor, String path) {
+    String[] parts = path.split(FIELD_SEPARATOR_REGEX);
+    if (parts.length == 0) {
+      return false;
+    }
+    for (String name : parts) {
+      if (descriptor == null) {
+        return false;
+      }
+      FieldDescriptor field = descriptor.findFieldByName(name);
+      if (field == null) {
+        return false;
+      }
+      if (!field.isRepeated()
+          && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        descriptor = field.getMessageType();
+      } else {
+        descriptor = null;
+      }
+    }
+    return true;
+  }
+  
+  /**
+   * Converts a FieldMask to its canonical form. In the canonical form of a
+   * FieldMask, all field paths are sorted alphabetically and redundant field
+   * paths are moved.
+   */
+  public static FieldMask normalize(FieldMask mask) {
+    return new FieldMaskTree(mask).toFieldMask();
+  }
+
+  /**
+   * Creates a union of two or more FieldMasks.
+   */
+  public static FieldMask union(
+      FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
+    FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask);
+    for (FieldMask mask : otherMasks) {
+      maskTree.mergeFromFieldMask(mask);
+    }
+    return maskTree.toFieldMask();
+  }
+
+  /**
+   * Calculates the intersection of two FieldMasks.
+   */
+  public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
+    FieldMaskTree tree = new FieldMaskTree(mask1);
+    FieldMaskTree result = new FieldMaskTree();
+    for (String path : mask2.getPathsList()) {
+      tree.intersectFieldPath(path, result);
+    }
+    return result.toFieldMask();
+  }
+
+  /**
+   * Options to customize merging behavior.
+   */
+  public static final class MergeOptions {
+    private boolean replaceMessageFields = false;
+    private boolean replaceRepeatedFields = false;
+    // TODO(b/28277137): change the default behavior to always replace primitive fields after
+    // fixing all failing TAP tests.
+    private boolean replacePrimitiveFields = false;
+
+    /**
+     * Whether to replace message fields (i.e., discard existing content in
+     * destination message fields) when merging.
+     * Default behavior is to merge the source message field into the
+     * destination message field.
+     */ 
+    public boolean replaceMessageFields() {
+      return replaceMessageFields;
+    }
+
+    /**
+     * Whether to replace repeated fields (i.e., discard existing content in
+     * destination repeated fields) when merging.
+     * Default behavior is to append elements from source repeated field to the
+     * destination repeated field.
+     */
+    public boolean replaceRepeatedFields() {
+      return replaceRepeatedFields;
+    }
+
+    /**
+     * Whether to replace primitive (non-repeated and non-message) fields in
+     * destination message fields with the source primitive fields (i.e., if the
+     * field is set in the source, the value is copied to the
+     * destination; if the field is unset in the source, the field is cleared
+     * from the destination) when merging.
+     *
+     * <p>Default behavior is to always set the value of the source primitive
+     * field to the destination primitive field, and if the source field is
+     * unset, the default value of the source field is copied to the
+     * destination.
+     */
+    public boolean replacePrimitiveFields() {
+      return replacePrimitiveFields;
+    }
+
+    public void setReplaceMessageFields(boolean value) {
+      replaceMessageFields = value;
+    }
+
+    public void setReplaceRepeatedFields(boolean value) {
+      replaceRepeatedFields = value;
+    }
+
+    public void setReplacePrimitiveFields(boolean value) {
+      replacePrimitiveFields = value;
+    }
+  }
+
+  /**
+   * Merges fields specified by a FieldMask from one message to another with the
+   * specified merge options.
+   */
+  public static void merge(FieldMask mask, Message source,
+      Message.Builder destination, MergeOptions options) {
+    new FieldMaskTree(mask).merge(source, destination, options);
+  }
+
+  /**
+   * Merges fields specified by a FieldMask from one message to another.
+   */
+  public static void merge(FieldMask mask, Message source,
+      Message.Builder destination) {
+    merge(mask, source, destination, new MergeOptions());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
new file mode 100644
index 0000000..76f3437
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -0,0 +1,1678 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.common.io.BaseEncoding;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.stream.JsonReader;
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.Duration;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Timestamp;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.logging.Logger;
+
+/**
+ * Utility classes to convert protobuf messages to/from JSON format. The JSON
+ * format follows Proto3 JSON specification and only proto3 features are
+ * supported. Proto2 only features (e.g., extensions and unknown fields) will
+ * be discarded in the conversion. That is, when converting proto2 messages
+ * to JSON format, extensions and unknown fields will be treated as if they
+ * do not exist. This applies to proto2 messages embedded in proto3 messages
+ * as well.
+ */
+public class JsonFormat {
+  private static final Logger logger =
+      Logger.getLogger(JsonFormat.class.getName());
+
+  private JsonFormat() {}
+  
+  /**
+   * Creates a {@link Printer} with default configurations.
+   */
+  public static Printer printer() {
+    return new Printer(TypeRegistry.getEmptyTypeRegistry(), false, false);
+  }
+  
+  /**
+   * A Printer converts protobuf message to JSON format.
+   */
+  public static class Printer {
+    private final TypeRegistry registry;
+    private final boolean includingDefaultValueFields;
+    private final boolean preservingProtoFieldNames;
+
+    private Printer(
+        TypeRegistry registry,
+        boolean includingDefaultValueFields,
+        boolean preservingProtoFieldNames) {
+      this.registry = registry;
+      this.includingDefaultValueFields = includingDefaultValueFields;
+      this.preservingProtoFieldNames = preservingProtoFieldNames;
+    }
+    
+    /**
+     * Creates a new {@link Printer} using the given registry. The new Printer
+     * clones all other configurations from the current {@link Printer}.
+     * 
+     * @throws IllegalArgumentException if a registry is already set.
+     */
+    public Printer usingTypeRegistry(TypeRegistry registry) {
+      if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+        throw new IllegalArgumentException("Only one registry is allowed.");
+      }
+      return new Printer(registry, includingDefaultValueFields, preservingProtoFieldNames);
+    }
+
+    /**
+     * Creates a new {@link Printer} that will also print fields set to their
+     * defaults. Empty repeated fields and map fields will be printed as well.
+     * The new Printer clones all other configurations from the current
+     * {@link Printer}.
+     */
+    public Printer includingDefaultValueFields() {
+      return new Printer(registry, true, preservingProtoFieldNames);
+    }
+
+    /**
+     * Creates a new {@link Printer} that is configured to use the original proto
+     * field names as defined in the .proto file rather than converting them to
+     * lowerCamelCase. The new Printer clones all other configurations from the
+     * current {@link Printer}.
+     */
+    public Printer preservingProtoFieldNames() {
+      return new Printer(registry, includingDefaultValueFields, true);
+    }
+    
+    /**
+     * Converts a protobuf message to JSON format.
+     * 
+     * @throws InvalidProtocolBufferException if the message contains Any types
+     *         that can't be resolved.
+     * @throws IOException if writing to the output fails.
+     */
+    public void appendTo(MessageOrBuilder message, Appendable output)
+        throws IOException {
+      // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+      // mobile.
+      new PrinterImpl(registry, includingDefaultValueFields, preservingProtoFieldNames, output)
+          .print(message);
+    }
+
+    /**
+     * Converts a protobuf message to JSON format. Throws exceptions if there
+     * are unknown Any types in the message. 
+     */
+    public String print(MessageOrBuilder message)
+        throws InvalidProtocolBufferException {
+      try {
+        StringBuilder builder = new StringBuilder();
+        appendTo(message, builder);
+        return builder.toString();
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        // Unexpected IOException.
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+  /**
+   * Creates a {@link Parser} with default configuration.
+   */
+  public static Parser parser() {
+    return new Parser(TypeRegistry.getEmptyTypeRegistry());
+  }
+  
+  /**
+   * A Parser parses JSON to protobuf message.
+   */
+  public static class Parser {
+    private final TypeRegistry registry;
+    
+    private Parser(TypeRegistry registry) {
+      this.registry = registry; 
+    }
+    
+    /**
+     * Creates a new {@link Parser} using the given registry. The new Parser
+     * clones all other configurations from this Parser.
+     * 
+     * @throws IllegalArgumentException if a registry is already set.
+     */
+    public Parser usingTypeRegistry(TypeRegistry registry) {
+      if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+        throw new IllegalArgumentException("Only one registry is allowed.");
+      }
+      return new Parser(registry);
+    }
+    
+    /**
+     * Parses from JSON into a protobuf message.
+     * 
+     * @throws InvalidProtocolBufferException if the input is not valid JSON
+     *         format or there are unknown fields in the input.
+     */
+    public void merge(String json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+      // mobile.
+      new ParserImpl(registry).merge(json, builder);
+    }
+    
+    /**
+     * Parses from JSON into a protobuf message.
+     * 
+     * @throws InvalidProtocolBufferException if the input is not valid JSON
+     *         format or there are unknown fields in the input.
+     * @throws IOException if reading from the input throws.
+     */
+    public void merge(Reader json, Message.Builder builder)
+        throws IOException {
+      // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+      // mobile.
+      new ParserImpl(registry).merge(json, builder);
+    }
+  }
+
+  /**
+   * A TypeRegistry is used to resolve Any messages in the JSON conversion.
+   * You must provide a TypeRegistry containing all message types used in
+   * Any message fields, or the JSON conversion will fail because data
+   * in Any message fields is unrecognizable. You don't need to supply a
+   * TypeRegistry if you don't use Any message fields.
+   */
+  public static class TypeRegistry {
+    private static class EmptyTypeRegistryHolder {
+      private static final TypeRegistry EMPTY = new TypeRegistry(
+          Collections.<String, Descriptor>emptyMap());
+    }
+
+    public static TypeRegistry getEmptyTypeRegistry() {
+      return EmptyTypeRegistryHolder.EMPTY;
+    }
+
+    public static Builder newBuilder() {
+      return new Builder();
+    }
+
+    /**
+     * Find a type by its full name. Returns null if it cannot be found in
+     * this {@link TypeRegistry}.
+     */
+    public Descriptor find(String name) {
+      return types.get(name);
+    }
+
+    private final Map<String, Descriptor> types;
+
+    private TypeRegistry(Map<String, Descriptor> types) {
+      this.types = types;
+    }
+
+    /**
+     * A Builder is used to build {@link TypeRegistry}.
+     */
+    public static class Builder {
+      private Builder() {}
+
+      /**
+       * Adds a message type and all types defined in the same .proto file as
+       * well as all transitively imported .proto files to this {@link Builder}.
+       */
+      public Builder add(Descriptor messageType) {
+        if (types == null) {
+          throw new IllegalStateException(
+              "A TypeRegistry.Builer can only be used once.");
+        }
+        addFile(messageType.getFile());
+        return this;
+      }
+
+      /**
+       * Adds message types and all types defined in the same .proto file as
+       * well as all transitively imported .proto files to this {@link Builder}.
+       */
+      public Builder add(Iterable<Descriptor> messageTypes) {
+        if (types == null) {
+          throw new IllegalStateException(
+              "A TypeRegistry.Builer can only be used once.");
+        }
+        for (Descriptor type : messageTypes) {
+          addFile(type.getFile());
+        }
+        return this;
+      }
+
+      /**
+       * Builds a {@link TypeRegistry}. This method can only be called once for
+       * one Builder.
+       */
+      public TypeRegistry build() {
+        TypeRegistry result = new TypeRegistry(types);
+        // Make sure the built {@link TypeRegistry} is immutable.
+        types = null;
+        return result;
+      }
+
+      private void addFile(FileDescriptor file) {
+        // Skip the file if it's already added.
+        if (!files.add(file.getFullName())) {
+          return;
+        }
+        for (FileDescriptor dependency : file.getDependencies()) {
+          addFile(dependency);
+        }
+        for (Descriptor message : file.getMessageTypes()) {
+          addMessage(message);
+        }
+      }
+
+      private void addMessage(Descriptor message) {
+        for (Descriptor nestedType : message.getNestedTypes()) {
+          addMessage(nestedType);
+        }
+
+        if (types.containsKey(message.getFullName())) {
+          logger.warning("Type " + message.getFullName()
+              + " is added multiple times.");
+          return;
+        }
+
+        types.put(message.getFullName(), message);
+      }
+
+      private final Set<String> files = new HashSet<String>();
+      private Map<String, Descriptor> types =
+          new HashMap<String, Descriptor>();
+    }
+  }
+
+  /**
+   * A TextGenerator adds indentation when writing formatted text.
+   */
+  private static final class TextGenerator {
+    private final Appendable output;
+    private final StringBuilder indent = new StringBuilder();
+    private boolean atStartOfLine = true;
+
+    private TextGenerator(final Appendable output) {
+      this.output = output;
+    }
+
+    /**
+     * Indent text by two spaces.  After calling Indent(), two spaces will be
+     * inserted at the beginning of each line of text.  Indent() may be called
+     * multiple times to produce deeper indents.
+     */
+    public void indent() {
+      indent.append("  ");
+    }
+
+    /**
+     * Reduces the current indent level by two spaces, or crashes if the indent
+     * level is zero.
+     */
+    public void outdent() {
+      final int length = indent.length();
+      if (length < 2) {
+        throw new IllegalArgumentException(
+            " Outdent() without matching Indent().");
+      }
+      indent.delete(length - 2, length);
+    }
+
+    /**
+     * Print text to the output stream.
+     */
+    public void print(final CharSequence text) throws IOException {
+      final int size = text.length();
+      int pos = 0;
+
+      for (int i = 0; i < size; i++) {
+        if (text.charAt(i) == '\n') {
+          write(text.subSequence(pos, i + 1));
+          pos = i + 1;
+          atStartOfLine = true;
+        }
+      }
+      write(text.subSequence(pos, size));
+    }
+
+    private void write(final CharSequence data) throws IOException {
+      if (data.length() == 0) {
+        return;
+      }
+      if (atStartOfLine) {
+        atStartOfLine = false;
+        output.append(indent);
+      }
+      output.append(data);
+    }
+  }
+
+  /**
+   * A Printer converts protobuf messages to JSON format.
+   */
+  private static final class PrinterImpl {
+    private final TypeRegistry registry;
+    private final boolean includingDefaultValueFields;
+    private final boolean preservingProtoFieldNames;
+    private final TextGenerator generator;
+    // We use Gson to help handle string escapes.
+    private final Gson gson;
+
+    private static class GsonHolder {
+      private static final Gson DEFAULT_GSON = new GsonBuilder().disableHtmlEscaping().create();
+    }
+
+    PrinterImpl(
+        TypeRegistry registry,
+        boolean includingDefaultValueFields,
+        boolean preservingProtoFieldNames,
+        Appendable jsonOutput) {
+      this.registry = registry;
+      this.includingDefaultValueFields = includingDefaultValueFields;
+      this.preservingProtoFieldNames = preservingProtoFieldNames;
+      this.generator = new TextGenerator(jsonOutput);
+      this.gson = GsonHolder.DEFAULT_GSON;
+    }
+
+    void print(MessageOrBuilder message) throws IOException {
+      WellKnownTypePrinter specialPrinter = wellKnownTypePrinters.get(
+          message.getDescriptorForType().getFullName());
+      if (specialPrinter != null) {
+        specialPrinter.print(this, message);
+        return;
+      }
+      print(message, null);
+    }
+    
+    private interface WellKnownTypePrinter {
+      void print(PrinterImpl printer, MessageOrBuilder message)
+          throws IOException;
+    }
+    
+    private static final Map<String, WellKnownTypePrinter>
+    wellKnownTypePrinters = buildWellKnownTypePrinters();
+    
+    private static Map<String, WellKnownTypePrinter>
+    buildWellKnownTypePrinters() {
+      Map<String, WellKnownTypePrinter> printers =
+          new HashMap<String, WellKnownTypePrinter>();
+      // Special-case Any.
+      printers.put(Any.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printAny(message);
+        }
+      });
+      // Special-case wrapper types.
+      WellKnownTypePrinter wrappersPrinter = new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printWrapper(message);
+          
+        }
+      };
+      printers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+      printers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+      // Special-case Timestamp.
+      printers.put(Timestamp.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printTimestamp(message);
+        }
+      });
+      // Special-case Duration.
+      printers.put(Duration.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printDuration(message);
+        }
+      });
+      // Special-case FieldMask.
+      printers.put(FieldMask.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printFieldMask(message);
+        }
+      });
+      // Special-case Struct.
+      printers.put(Struct.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printStruct(message);
+        }
+      });
+      // Special-case Value.
+      printers.put(Value.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printValue(message);
+        }
+      });
+      // Special-case ListValue.
+      printers.put(ListValue.getDescriptor().getFullName(),
+          new WellKnownTypePrinter() {
+        @Override
+        public void print(PrinterImpl printer, MessageOrBuilder message)
+            throws IOException {
+          printer.printListValue(message);
+        }
+      });
+      return printers;
+    }
+    
+    /** Prints google.protobuf.Any */
+    private void printAny(MessageOrBuilder message) throws IOException {
+      Descriptor descriptor = message.getDescriptorForType();
+      FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+      FieldDescriptor valueField = descriptor.findFieldByName("value");
+      // Validates type of the message. Note that we can't just cast the message
+      // to com.google.protobuf.Any because it might be a DynamicMessage. 
+      if (typeUrlField == null || valueField == null
+          || typeUrlField.getType() != FieldDescriptor.Type.STRING
+          || valueField.getType() != FieldDescriptor.Type.BYTES) {
+        throw new InvalidProtocolBufferException("Invalid Any type.");
+      }
+      String typeUrl = (String) message.getField(typeUrlField);
+      String typeName = getTypeName(typeUrl);
+      Descriptor type = registry.find(typeName);
+      if (type == null) {
+        throw new InvalidProtocolBufferException(
+            "Cannot find type for url: " + typeUrl);
+      }
+      ByteString content = (ByteString) message.getField(valueField);
+      Message contentMessage = DynamicMessage.getDefaultInstance(type)
+          .getParserForType().parseFrom(content);
+      WellKnownTypePrinter printer = wellKnownTypePrinters.get(typeName);
+      if (printer != null) {
+        // If the type is one of the well-known types, we use a special
+        // formatting.
+        generator.print("{\n");
+        generator.indent();
+        generator.print("\"@type\": " + gson.toJson(typeUrl) + ",\n");
+        generator.print("\"value\": ");
+        printer.print(this, contentMessage);
+        generator.print("\n");
+        generator.outdent();
+        generator.print("}");
+      } else {
+        // Print the content message instead (with a "@type" field added).
+        print(contentMessage, typeUrl);
+      }
+    }
+    
+    /** Prints wrapper types (e.g., google.protobuf.Int32Value) */
+    private void printWrapper(MessageOrBuilder message) throws IOException {
+      Descriptor descriptor = message.getDescriptorForType();
+      FieldDescriptor valueField = descriptor.findFieldByName("value");
+      if (valueField == null) {
+        throw new InvalidProtocolBufferException("Invalid Wrapper type.");
+      }
+      // When formatting wrapper types, we just print its value field instead of
+      // the whole message.
+      printSingleFieldValue(valueField, message.getField(valueField));
+    }
+    
+    private ByteString toByteString(MessageOrBuilder message) {
+      if (message instanceof Message) {
+        return ((Message) message).toByteString();
+      } else {
+        return ((Message.Builder) message).build().toByteString();
+      }
+    }
+    
+    /** Prints google.protobuf.Timestamp */
+    private void printTimestamp(MessageOrBuilder message) throws IOException {
+      Timestamp value = Timestamp.parseFrom(toByteString(message));
+      generator.print("\"" + TimeUtil.toString(value) + "\"");
+    }
+    
+    /** Prints google.protobuf.Duration */
+    private void printDuration(MessageOrBuilder message) throws IOException {
+      Duration value = Duration.parseFrom(toByteString(message));
+      generator.print("\"" + TimeUtil.toString(value) + "\"");
+      
+    }
+    
+    /** Prints google.protobuf.FieldMask */
+    private void printFieldMask(MessageOrBuilder message) throws IOException {
+      FieldMask value = FieldMask.parseFrom(toByteString(message));
+      generator.print("\"" + FieldMaskUtil.toString(value) + "\"");
+    }
+    
+    /** Prints google.protobuf.Struct */
+    private void printStruct(MessageOrBuilder message) throws IOException {
+      Descriptor descriptor = message.getDescriptorForType();
+      FieldDescriptor field = descriptor.findFieldByName("fields");
+      if (field == null) {
+        throw new InvalidProtocolBufferException("Invalid Struct type.");
+      }
+      // Struct is formatted as a map object.
+      printMapFieldValue(field, message.getField(field));
+    }
+    
+    /** Prints google.protobuf.Value */
+    private void printValue(MessageOrBuilder message) throws IOException {
+      // For a Value message, only the value of the field is formatted.
+      Map<FieldDescriptor, Object> fields = message.getAllFields();
+      if (fields.isEmpty()) {
+        // No value set.
+        generator.print("null");
+        return;
+      }
+      // A Value message can only have at most one field set (it only contains
+      // an oneof).
+      if (fields.size() != 1) {
+        throw new InvalidProtocolBufferException("Invalid Value type.");
+      }
+      for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
+        printSingleFieldValue(entry.getKey(), entry.getValue());
+      }
+    }
+    
+    /** Prints google.protobuf.ListValue */
+    private void printListValue(MessageOrBuilder message) throws IOException {
+      Descriptor descriptor = message.getDescriptorForType();
+      FieldDescriptor field = descriptor.findFieldByName("values");
+      if (field == null) {
+        throw new InvalidProtocolBufferException("Invalid ListValue type.");
+      }
+      printRepeatedFieldValue(field, message.getField(field));
+    }
+
+    /** Prints a regular message with an optional type URL. */
+    private void print(MessageOrBuilder message, String typeUrl)
+        throws IOException {
+      generator.print("{\n");
+      generator.indent();
+
+      boolean printedField = false;
+      if (typeUrl != null) {
+        generator.print("\"@type\": " + gson.toJson(typeUrl));
+        printedField = true;
+      }
+      Map<FieldDescriptor, Object> fieldsToPrint = null;
+      if (includingDefaultValueFields) {
+        fieldsToPrint = new TreeMap<FieldDescriptor, Object>();
+        for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
+          if (field.isOptional()
+              && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+              && !message.hasField(field)) {
+            // Always skip empty optional message fields. If not we will recurse indefinitely if
+            // a message has itself as a sub-field.
+            continue;
+          }
+          fieldsToPrint.put(field, message.getField(field));
+        }
+      } else {
+        fieldsToPrint = message.getAllFields();
+      }
+      for (Map.Entry<FieldDescriptor, Object> field : fieldsToPrint.entrySet()) {
+        if (printedField) {
+          // Add line-endings for the previous field.
+          generator.print(",\n");
+        } else {
+          printedField = true;
+        }
+        printField(field.getKey(), field.getValue());
+      }
+      
+      // Add line-endings for the last field.
+      if (printedField) {
+        generator.print("\n");
+      }
+      generator.outdent();
+      generator.print("}");
+    }
+
+    private void printField(FieldDescriptor field, Object value)
+        throws IOException {
+      if (preservingProtoFieldNames) {
+        generator.print("\"" + field.getName() + "\": ");
+      } else {
+        generator.print("\"" + field.getJsonName() + "\": ");
+      }
+      if (field.isMapField()) {
+        printMapFieldValue(field, value);
+      } else if (field.isRepeated()) {
+        printRepeatedFieldValue(field, value);
+      } else {
+        printSingleFieldValue(field, value);
+      }
+    }
+    
+    @SuppressWarnings("rawtypes")
+    private void printRepeatedFieldValue(FieldDescriptor field, Object value)
+        throws IOException {
+      generator.print("[");
+      boolean printedElement = false;
+      for (Object element : (List) value) {
+        if (printedElement) {
+          generator.print(", ");
+        } else {
+          printedElement = true;
+        }
+        printSingleFieldValue(field, element);
+      }
+      generator.print("]");
+    }
+    
+    @SuppressWarnings("rawtypes")
+    private void printMapFieldValue(FieldDescriptor field, Object value)
+        throws IOException {
+      Descriptor type = field.getMessageType();
+      FieldDescriptor keyField = type.findFieldByName("key");
+      FieldDescriptor valueField = type.findFieldByName("value");
+      if (keyField == null || valueField == null) {
+        throw new InvalidProtocolBufferException("Invalid map field.");
+      }
+      generator.print("{\n");
+      generator.indent();
+      boolean printedElement = false;
+      for (Object element : (List) value) {
+        Message entry = (Message) element;
+        Object entryKey = entry.getField(keyField);
+        Object entryValue = entry.getField(valueField);
+        if (printedElement) {
+          generator.print(",\n");
+        } else {
+          printedElement = true;
+        }
+        // Key fields are always double-quoted.
+        printSingleFieldValue(keyField, entryKey, true);
+        generator.print(": ");
+        printSingleFieldValue(valueField, entryValue);
+      }
+      if (printedElement) {
+        generator.print("\n");
+      }
+      generator.outdent();
+      generator.print("}");
+    }
+    
+    private void printSingleFieldValue(FieldDescriptor field, Object value)
+        throws IOException {
+      printSingleFieldValue(field, value, false);
+    }
+
+    /**
+     * Prints a field's value in JSON format.
+     * 
+     * @param alwaysWithQuotes whether to always add double-quotes to primitive
+     *        types.
+     */
+    private void printSingleFieldValue(
+        final FieldDescriptor field, final Object value,
+        boolean alwaysWithQuotes) throws IOException {
+      switch (field.getType()) {
+        case INT32:
+        case SINT32:
+        case SFIXED32:
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          generator.print(((Integer) value).toString());
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          break;
+
+        case INT64:
+        case SINT64:
+        case SFIXED64:
+          generator.print("\"" + ((Long) value).toString() + "\"");
+          break;
+
+        case BOOL:
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          if (((Boolean) value).booleanValue()) {
+            generator.print("true");
+          } else {
+            generator.print("false");
+          }
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          break;
+
+        case FLOAT:
+          Float floatValue = (Float) value;
+          if (floatValue.isNaN()) {
+            generator.print("\"NaN\"");
+          } else if (floatValue.isInfinite()) {
+            if (floatValue < 0) {
+              generator.print("\"-Infinity\"");
+            } else {
+              generator.print("\"Infinity\"");
+            }
+          } else {
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+            generator.print(floatValue.toString());
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+          }
+          break;
+          
+        case DOUBLE:
+          Double doubleValue = (Double) value;
+          if (doubleValue.isNaN()) {
+            generator.print("\"NaN\"");
+          } else if (doubleValue.isInfinite()) {
+            if (doubleValue < 0) {
+              generator.print("\"-Infinity\"");
+            } else {
+              generator.print("\"Infinity\"");
+            }
+          } else {
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+            generator.print(doubleValue.toString());
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+          }
+          break;
+
+        case UINT32:
+        case FIXED32:
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          generator.print(unsignedToString((Integer) value));
+          if (alwaysWithQuotes) {
+            generator.print("\"");
+          }
+          break;
+
+        case UINT64:
+        case FIXED64:
+          generator.print("\"" + unsignedToString((Long) value) + "\"");
+          break;
+
+        case STRING:
+          generator.print(gson.toJson(value));
+          break;
+
+        case BYTES:
+          generator.print("\"");
+          generator.print(
+              BaseEncoding.base64().encode(((ByteString) value).toByteArray()));
+          generator.print("\"");
+          break;
+
+        case ENUM:
+          // Special-case google.protobuf.NullValue (it's an Enum).
+          if (field.getEnumType().getFullName().equals(
+                  "google.protobuf.NullValue")) {
+            // No matter what value it contains, we always print it as "null".
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+            generator.print("null");
+            if (alwaysWithQuotes) {
+              generator.print("\"");
+            }
+          } else {
+            if (((EnumValueDescriptor) value).getIndex() == -1) {
+              generator.print(
+                  String.valueOf(((EnumValueDescriptor) value).getNumber()));
+            } else {
+              generator.print(
+                  "\"" + ((EnumValueDescriptor) value).getName() + "\"");
+            }
+          }
+          break;
+
+        case MESSAGE:
+        case GROUP:
+          print((Message) value);
+          break;
+      }
+    }
+  }
+
+  /** Convert an unsigned 32-bit integer to a string. */
+  private static String unsignedToString(final int value) {
+    if (value >= 0) {
+      return Integer.toString(value);
+    } else {
+      return Long.toString(value & 0x00000000FFFFFFFFL);
+    }
+  }
+
+  /** Convert an unsigned 64-bit integer to a string. */
+  private static String unsignedToString(final long value) {
+    if (value >= 0) {
+      return Long.toString(value);
+    } else {
+      // Pull off the most-significant bit so that BigInteger doesn't think
+      // the number is negative, then set it again using setBit().
+      return BigInteger.valueOf(value & Long.MAX_VALUE)
+                       .setBit(Long.SIZE - 1).toString();
+    }
+  }
+  
+
+  private static String getTypeName(String typeUrl)
+      throws InvalidProtocolBufferException {
+    String[] parts = typeUrl.split("/");
+    if (parts.length == 1) {
+      throw new InvalidProtocolBufferException(
+          "Invalid type url found: " + typeUrl);
+    }
+    return parts[parts.length - 1];
+  }
+  
+  private static class ParserImpl {
+    private final TypeRegistry registry;
+    private final JsonParser jsonParser;
+    
+    ParserImpl(TypeRegistry registry) {
+      this.registry = registry;
+      this.jsonParser = new JsonParser();
+    }
+    
+    void merge(Reader json, Message.Builder builder)
+        throws IOException {
+      JsonReader reader = new JsonReader(json);
+      reader.setLenient(false);
+      merge(jsonParser.parse(reader), builder);
+    }
+    
+    void merge(String json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      try {
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.setLenient(false);
+        merge(jsonParser.parse(reader), builder);
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        // We convert all exceptions from JSON parsing to our own exceptions.
+        throw new InvalidProtocolBufferException(e.getMessage());
+      }
+    }
+    
+    private interface WellKnownTypeParser {
+      void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+          throws InvalidProtocolBufferException;
+    }
+    
+    private static final Map<String, WellKnownTypeParser> wellKnownTypeParsers =
+        buildWellKnownTypeParsers();
+    
+    private static Map<String, WellKnownTypeParser>
+    buildWellKnownTypeParsers() {
+      Map<String, WellKnownTypeParser> parsers =
+          new HashMap<String, WellKnownTypeParser>();
+      // Special-case Any.
+      parsers.put(Any.getDescriptor().getFullName(), new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeAny(json, builder);
+        }
+      });
+      // Special-case wrapper types.
+      WellKnownTypeParser wrappersPrinter = new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeWrapper(json, builder);
+        }
+      };
+      parsers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+      parsers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+      // Special-case Timestamp.
+      parsers.put(Timestamp.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeTimestamp(json, builder);
+        }
+      });
+      // Special-case Duration.
+      parsers.put(Duration.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeDuration(json, builder);
+        }
+      });
+      // Special-case FieldMask.
+      parsers.put(FieldMask.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeFieldMask(json, builder);
+        }
+      });
+      // Special-case Struct.
+      parsers.put(Struct.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeStruct(json, builder);
+        }
+      });
+      // Special-case ListValue.
+      parsers.put(ListValue.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeListValue(json, builder);
+        }
+      });
+      // Special-case Value.
+      parsers.put(Value.getDescriptor().getFullName(),
+          new WellKnownTypeParser() {
+        @Override
+        public void merge(ParserImpl parser, JsonElement json,
+            Message.Builder builder) throws InvalidProtocolBufferException {
+          parser.mergeValue(json, builder);
+        }
+      });
+      return parsers;
+    }
+    
+    private void merge(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      WellKnownTypeParser specialParser = wellKnownTypeParsers.get(
+          builder.getDescriptorForType().getFullName());
+      if (specialParser != null) {
+        specialParser.merge(this, json, builder);
+        return;
+      }
+      mergeMessage(json, builder, false);
+    }
+    
+    // Maps from camel-case field names to FieldDescriptor.
+    private final Map<Descriptor, Map<String, FieldDescriptor>> fieldNameMaps =
+        new HashMap<Descriptor, Map<String, FieldDescriptor>>();
+    
+    private Map<String, FieldDescriptor> getFieldNameMap(
+        Descriptor descriptor) {
+      if (!fieldNameMaps.containsKey(descriptor)) {
+        Map<String, FieldDescriptor> fieldNameMap =
+            new HashMap<String, FieldDescriptor>();
+        for (FieldDescriptor field : descriptor.getFields()) {
+          fieldNameMap.put(field.getName(), field);
+          fieldNameMap.put(field.getJsonName(), field);
+        }
+        fieldNameMaps.put(descriptor, fieldNameMap);
+        return fieldNameMap;
+      }
+      return fieldNameMaps.get(descriptor);
+    }
+    
+    private void mergeMessage(JsonElement json, Message.Builder builder,
+        boolean skipTypeUrl) throws InvalidProtocolBufferException {
+      if (!(json instanceof JsonObject)) {
+        throw new InvalidProtocolBufferException(
+            "Expect message object but got: " + json);
+      }
+      JsonObject object = (JsonObject) json;
+      Map<String, FieldDescriptor> fieldNameMap =
+          getFieldNameMap(builder.getDescriptorForType());
+      for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+        if (skipTypeUrl && entry.getKey().equals("@type")) {
+          continue;
+        }
+        FieldDescriptor field = fieldNameMap.get(entry.getKey());
+        if (field == null) {
+          throw new InvalidProtocolBufferException(
+              "Cannot find field: " + entry.getKey() + " in message "
+              + builder.getDescriptorForType().getFullName());
+        }
+        mergeField(field, entry.getValue(), builder);
+      }
+    }
+    
+    private void mergeAny(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      Descriptor descriptor = builder.getDescriptorForType();
+      FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+      FieldDescriptor valueField = descriptor.findFieldByName("value");
+      // Validates type of the message. Note that we can't just cast the message
+      // to com.google.protobuf.Any because it might be a DynamicMessage. 
+      if (typeUrlField == null || valueField == null
+          || typeUrlField.getType() != FieldDescriptor.Type.STRING
+          || valueField.getType() != FieldDescriptor.Type.BYTES) {
+        throw new InvalidProtocolBufferException("Invalid Any type.");
+      }
+      
+      if (!(json instanceof JsonObject)) {
+        throw new InvalidProtocolBufferException(
+            "Expect message object but got: " + json);
+      }
+      JsonObject object = (JsonObject) json;
+      JsonElement typeUrlElement = object.get("@type");
+      if (typeUrlElement == null) {
+        throw new InvalidProtocolBufferException(
+            "Missing type url when parsing: " + json);
+      }
+      String typeUrl = typeUrlElement.getAsString();
+      Descriptor contentType = registry.find(getTypeName(typeUrl));
+      if (contentType == null) {
+        throw new InvalidProtocolBufferException(
+            "Cannot resolve type: " + typeUrl);
+      }
+      builder.setField(typeUrlField, typeUrl);
+      Message.Builder contentBuilder =
+          DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
+      WellKnownTypeParser specialParser =
+          wellKnownTypeParsers.get(contentType.getFullName());
+      if (specialParser != null) {
+        JsonElement value = object.get("value");
+        if (value != null) {
+          specialParser.merge(this, value, contentBuilder);
+        }
+      } else {
+        mergeMessage(json, contentBuilder, true);
+      }
+      builder.setField(valueField, contentBuilder.build().toByteString());
+    }
+    
+    private void mergeFieldMask(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      FieldMask value = FieldMaskUtil.fromString(json.getAsString());
+      builder.mergeFrom(value.toByteString());
+    }
+    
+    private void mergeTimestamp(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      try {
+        Timestamp value = TimeUtil.parseTimestamp(json.getAsString());
+        builder.mergeFrom(value.toByteString());
+      } catch (ParseException e) {
+        throw new InvalidProtocolBufferException(
+            "Failed to parse timestamp: " + json);
+      }
+    }
+    
+    private void mergeDuration(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      try {
+        Duration value = TimeUtil.parseDuration(json.getAsString());
+        builder.mergeFrom(value.toByteString());
+      } catch (ParseException e) {
+        throw new InvalidProtocolBufferException(
+            "Failed to parse duration: " + json);
+      }
+    }
+    
+    private void mergeStruct(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      Descriptor descriptor = builder.getDescriptorForType();
+      FieldDescriptor field = descriptor.findFieldByName("fields");
+      if (field == null) {
+        throw new InvalidProtocolBufferException("Invalid Struct type.");
+      }
+      mergeMapField(field, json, builder);
+    }
+
+    private void mergeListValue(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      Descriptor descriptor = builder.getDescriptorForType();
+      FieldDescriptor field = descriptor.findFieldByName("values");
+      if (field == null) {
+        throw new InvalidProtocolBufferException("Invalid ListValue type.");
+      }
+      mergeRepeatedField(field, json, builder);
+    }
+    
+    private void mergeValue(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      Descriptor type = builder.getDescriptorForType();
+      if (json instanceof JsonPrimitive) {
+        JsonPrimitive primitive = (JsonPrimitive) json;
+        if (primitive.isBoolean()) {
+          builder.setField(type.findFieldByName("bool_value"),
+              primitive.getAsBoolean());
+        } else if (primitive.isNumber()) {
+          builder.setField(type.findFieldByName("number_value"),
+              primitive.getAsDouble());
+        } else {
+          builder.setField(type.findFieldByName("string_value"),
+              primitive.getAsString());
+        }
+      } else if (json instanceof JsonObject) {
+        FieldDescriptor field = type.findFieldByName("struct_value");
+        Message.Builder structBuilder = builder.newBuilderForField(field);
+        merge(json, structBuilder);
+        builder.setField(field, structBuilder.build());
+      } else if (json instanceof JsonArray) {
+        FieldDescriptor field = type.findFieldByName("list_value");
+        Message.Builder listBuilder = builder.newBuilderForField(field);
+        merge(json, listBuilder);
+        builder.setField(field, listBuilder.build());
+      } else {
+        throw new IllegalStateException("Unexpected json data: " + json);
+      }
+    }
+    
+    private void mergeWrapper(JsonElement json, Message.Builder builder)
+        throws InvalidProtocolBufferException {
+      Descriptor type = builder.getDescriptorForType();
+      FieldDescriptor field = type.findFieldByName("value");
+      if (field == null) {
+        throw new InvalidProtocolBufferException(
+            "Invalid wrapper type: " + type.getFullName());
+      }
+      builder.setField(field, parseFieldValue(field, json, builder));
+    }
+    
+    private void mergeField(FieldDescriptor field, JsonElement json,
+        Message.Builder builder) throws InvalidProtocolBufferException {
+      if (field.isRepeated()) {
+        if (builder.getRepeatedFieldCount(field) > 0) {
+          throw new InvalidProtocolBufferException(
+              "Field " + field.getFullName() + " has already been set.");
+        }
+      } else {
+        if (builder.hasField(field)) {
+          throw new InvalidProtocolBufferException(
+              "Field " + field.getFullName() + " has already been set.");
+        }
+        if (field.getContainingOneof() != null
+            && builder.getOneofFieldDescriptor(field.getContainingOneof()) != null) {
+          FieldDescriptor other = builder.getOneofFieldDescriptor(field.getContainingOneof());
+          throw new InvalidProtocolBufferException(
+              "Cannot set field " + field.getFullName() + " because another field "
+              + other.getFullName() + " belonging to the same oneof has already been set ");
+        }
+      }
+      if (field.isRepeated() && json instanceof JsonNull) {
+        // We allow "null" as value for all field types and treat it as if the
+        // field is not present.
+        return;
+      }
+      if (field.isMapField()) {
+        mergeMapField(field, json, builder);
+      } else if (field.isRepeated()) {
+        mergeRepeatedField(field, json, builder);
+      } else {
+        Object value = parseFieldValue(field, json, builder);
+        if (value != null) {
+          builder.setField(field, value);
+        }
+      }
+    }
+    
+    private void mergeMapField(FieldDescriptor field, JsonElement json,
+        Message.Builder builder) throws InvalidProtocolBufferException {
+      if (!(json instanceof JsonObject)) {
+        throw new InvalidProtocolBufferException(
+            "Expect a map object but found: " + json);
+      }
+      Descriptor type = field.getMessageType();
+      FieldDescriptor keyField = type.findFieldByName("key");
+      FieldDescriptor valueField = type.findFieldByName("value");
+      if (keyField == null || valueField == null) {
+        throw new InvalidProtocolBufferException(
+            "Invalid map field: " + field.getFullName());
+      }
+      JsonObject object = (JsonObject) json;
+      for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+        Message.Builder entryBuilder = builder.newBuilderForField(field);
+        Object key = parseFieldValue(
+            keyField, new JsonPrimitive(entry.getKey()), entryBuilder);
+        Object value = parseFieldValue(
+            valueField, entry.getValue(), entryBuilder);
+        if (value == null) {
+          throw new InvalidProtocolBufferException(
+              "Map value cannot be null.");
+        }
+        entryBuilder.setField(keyField, key);
+        entryBuilder.setField(valueField, value);
+        builder.addRepeatedField(field, entryBuilder.build());
+      }
+    }
+    
+    /**
+     * Gets the default value for a field type. Note that we use proto3
+     * language defaults and ignore any default values set through the
+     * proto "default" option. 
+     */
+    private Object getDefaultValue(FieldDescriptor field,
+        Message.Builder builder) {
+      switch (field.getType()) {
+        case INT32:
+        case SINT32:
+        case SFIXED32:
+        case UINT32:
+        case FIXED32:
+          return 0;
+        case INT64:
+        case SINT64:
+        case SFIXED64:
+        case UINT64:
+        case FIXED64:
+          return 0L;
+        case FLOAT:
+          return 0.0f;
+        case DOUBLE:
+          return 0.0;
+        case BOOL:
+          return false;
+        case STRING:
+          return "";
+        case BYTES:
+          return ByteString.EMPTY;
+        case ENUM:
+          return field.getEnumType().getValues().get(0);
+        case MESSAGE:
+        case GROUP:
+          return builder.newBuilderForField(field).getDefaultInstanceForType();
+        default:
+          throw new IllegalStateException(
+              "Invalid field type: " + field.getType());
+      }
+    }
+    
+    private void mergeRepeatedField(FieldDescriptor field, JsonElement json,
+        Message.Builder builder) throws InvalidProtocolBufferException {
+      if (!(json instanceof JsonArray)) {
+        throw new InvalidProtocolBufferException(
+            "Expect an array but found: " + json);
+      }
+      JsonArray array = (JsonArray) json;
+      for (int i = 0; i < array.size(); ++i) {
+        Object value = parseFieldValue(field, array.get(i), builder);
+        if (value == null) {
+          throw new InvalidProtocolBufferException(
+              "Repeated field elements cannot be null");
+        }
+        builder.addRepeatedField(field, value);
+      }
+    }
+    
+    private int parseInt32(JsonElement json)
+        throws InvalidProtocolBufferException {
+      try {
+        return Integer.parseInt(json.getAsString());
+      } catch (Exception e) {
+        // Fall through.
+      }
+      // JSON doesn't distinguish between integer values and floating point values so "1" and
+      // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+      // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+      try {
+        BigDecimal value = new BigDecimal(json.getAsString());
+        return value.intValueExact();
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException("Not an int32 value: " + json);
+      }
+    }
+    
+    private long parseInt64(JsonElement json)
+        throws InvalidProtocolBufferException {
+      try {
+        return Long.parseLong(json.getAsString());
+      } catch (Exception e) {
+        // Fall through.
+      }
+      // JSON doesn't distinguish between integer values and floating point values so "1" and
+      // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+      // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+      try {
+        BigDecimal value = new BigDecimal(json.getAsString());
+        return value.longValueExact();
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException("Not an int32 value: " + json);
+      }
+    }
+    
+    private int parseUint32(JsonElement json)
+        throws InvalidProtocolBufferException {
+      try {
+        long result = Long.parseLong(json.getAsString());
+        if (result < 0 || result > 0xFFFFFFFFL) {
+          throw new InvalidProtocolBufferException(
+              "Out of range uint32 value: " + json);
+        }
+        return (int) result;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        // Fall through.
+      }
+      // JSON doesn't distinguish between integer values and floating point values so "1" and
+      // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+      // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+      try {
+        BigDecimal decimalValue = new BigDecimal(json.getAsString());
+        BigInteger value = decimalValue.toBigIntegerExact();
+        if (value.signum() < 0 || value.compareTo(new BigInteger("FFFFFFFF", 16)) > 0) {
+          throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
+        }
+        return value.intValue();
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException(
+            "Not an uint32 value: " + json);
+      }
+    }
+    
+    private static final BigInteger MAX_UINT64 =
+        new BigInteger("FFFFFFFFFFFFFFFF", 16);
+    
+    private long parseUint64(JsonElement json)
+        throws InvalidProtocolBufferException {
+      try {
+        BigDecimal decimalValue = new BigDecimal(json.getAsString());
+        BigInteger value = decimalValue.toBigIntegerExact();
+        if (value.compareTo(BigInteger.ZERO) < 0
+            || value.compareTo(MAX_UINT64) > 0) {
+          throw new InvalidProtocolBufferException(
+              "Out of range uint64 value: " + json);
+        }
+        return value.longValue();
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException(
+            "Not an uint64 value: " + json);
+      }
+    }
+    
+    private boolean parseBool(JsonElement json)
+        throws InvalidProtocolBufferException {
+      if (json.getAsString().equals("true")) {
+        return true;
+      }
+      if (json.getAsString().equals("false")) {
+        return false;
+      }
+      throw new InvalidProtocolBufferException("Invalid bool value: " + json);
+    }
+    
+    private static final double EPSILON = 1e-6;
+    
+    private float parseFloat(JsonElement json)
+        throws InvalidProtocolBufferException {
+      if (json.getAsString().equals("NaN")) {
+        return Float.NaN;
+      } else if (json.getAsString().equals("Infinity")) {
+        return Float.POSITIVE_INFINITY;
+      } else if (json.getAsString().equals("-Infinity")) {
+        return Float.NEGATIVE_INFINITY;
+      }
+      try {
+        // We don't use Float.parseFloat() here because that function simply
+        // accepts all double values. Here we parse the value into a Double
+        // and do explicit range check on it.
+        double value = Double.parseDouble(json.getAsString());
+        // When a float value is printed, the printed value might be a little
+        // larger or smaller due to precision loss. Here we need to add a bit
+        // of tolerance when checking whether the float value is in range.
+        if (value > Float.MAX_VALUE * (1.0 + EPSILON)
+            || value < -Float.MAX_VALUE * (1.0 + EPSILON)) {
+          throw new InvalidProtocolBufferException(
+              "Out of range float value: " + json);
+        }
+        return (float) value;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException("Not a float value: " + json);
+      }
+    }
+    
+    private static final BigDecimal MORE_THAN_ONE = new BigDecimal(
+        String.valueOf(1.0 + EPSILON));
+    // When a float value is printed, the printed value might be a little
+    // larger or smaller due to precision loss. Here we need to add a bit
+    // of tolerance when checking whether the float value is in range.
+    private static final BigDecimal MAX_DOUBLE = new BigDecimal(
+        String.valueOf(Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+    private static final BigDecimal MIN_DOUBLE = new BigDecimal(
+        String.valueOf(-Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+    
+    private double parseDouble(JsonElement json)
+        throws InvalidProtocolBufferException {
+      if (json.getAsString().equals("NaN")) {
+        return Double.NaN;
+      } else if (json.getAsString().equals("Infinity")) {
+        return Double.POSITIVE_INFINITY;
+      } else if (json.getAsString().equals("-Infinity")) {
+        return Double.NEGATIVE_INFINITY;
+      }
+      try {
+        // We don't use Double.parseDouble() here because that function simply
+        // accepts all values. Here we parse the value into a BigDecimal and do
+        // explicit range check on it.
+        BigDecimal value = new BigDecimal(json.getAsString());
+        if (value.compareTo(MAX_DOUBLE) > 0
+            || value.compareTo(MIN_DOUBLE) < 0) {
+          throw new InvalidProtocolBufferException(
+              "Out of range double value: " + json);
+        }
+        return value.doubleValue();
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (Exception e) {
+        throw new InvalidProtocolBufferException(
+            "Not an double value: " + json);
+      }
+    }
+    
+    private String parseString(JsonElement json) {
+      return json.getAsString();
+    }
+    
+    private ByteString parseBytes(JsonElement json) throws InvalidProtocolBufferException {
+      String encoded = json.getAsString();
+      if (encoded.length() % 4 != 0) {
+        throw new InvalidProtocolBufferException(
+            "Bytes field is not encoded in standard BASE64 with paddings: " + encoded);
+      }
+      return ByteString.copyFrom(
+          BaseEncoding.base64().decode(json.getAsString()));
+    }
+    
+    private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor,
+        JsonElement json) throws InvalidProtocolBufferException {
+      String value = json.getAsString();
+      EnumValueDescriptor result = enumDescriptor.findValueByName(value);
+      if (result == null) {
+        // Try to interpret the value as a number.
+        try {
+          int numericValue = parseInt32(json);
+          if (enumDescriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3) {
+            result = enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue);
+          } else {
+            result = enumDescriptor.findValueByNumber(numericValue);
+          }
+        } catch (InvalidProtocolBufferException e) {
+          // Fall through. This exception is about invalid int32 value we get from parseInt32() but
+          // that's not the exception we want the user to see. Since result == null, we will throw
+          // an exception later.
+        }
+        
+        if (result == null) {
+          throw new InvalidProtocolBufferException(
+              "Invalid enum value: " + value + " for enum type: "
+              + enumDescriptor.getFullName());
+        }
+      }
+      return result;
+    }
+    
+    private Object parseFieldValue(FieldDescriptor field, JsonElement json,
+        Message.Builder builder) throws InvalidProtocolBufferException {
+      if (json instanceof JsonNull) {
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+            && field.getMessageType().getFullName().equals(
+                   Value.getDescriptor().getFullName())) {
+          // For every other type, "null" means absence, but for the special
+          // Value message, it means the "null_value" field has been set.
+          Value value = Value.newBuilder().setNullValueValue(0).build();
+          return builder.newBuilderForField(field).mergeFrom(
+              value.toByteString()).build();
+        }
+        return null;
+      }
+      switch (field.getType()) {
+        case INT32:
+        case SINT32:
+        case SFIXED32:
+          return parseInt32(json);
+
+        case INT64:
+        case SINT64:
+        case SFIXED64:
+          return parseInt64(json);
+
+        case BOOL:
+          return parseBool(json);
+
+        case FLOAT:
+          return parseFloat(json);
+          
+        case DOUBLE:
+          return parseDouble(json);
+
+        case UINT32:
+        case FIXED32:
+          return parseUint32(json);
+
+        case UINT64:
+        case FIXED64:
+          return parseUint64(json);
+
+        case STRING:
+          return parseString(json);
+
+        case BYTES:
+          return parseBytes(json);
+
+        case ENUM:
+          return parseEnum(field.getEnumType(), json);
+
+        case MESSAGE:
+        case GROUP:
+          Message.Builder subBuilder = builder.newBuilderForField(field);
+          merge(json, subBuilder);
+          return subBuilder.build();
+          
+        default:
+          throw new InvalidProtocolBufferException(
+              "Invalid field type: " + field.getType());
+      } 
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
new file mode 100644
index 0000000..3033182
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
@@ -0,0 +1,549 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * Utilities to help create/manipulate Timestamp/Duration
+ */
+public class TimeUtil {
+  // Timestamp for "0001-01-01T00:00:00Z"
+  public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
+
+  // Timestamp for "9999-12-31T23:59:59Z"
+  public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
+  public static final long DURATION_SECONDS_MIN = -315576000000L;
+  public static final long DURATION_SECONDS_MAX = 315576000000L;
+
+  private static final long NANOS_PER_SECOND = 1000000000;
+  private static final long NANOS_PER_MILLISECOND = 1000000;
+  private static final long NANOS_PER_MICROSECOND = 1000;
+  private static final long MILLIS_PER_SECOND = 1000;
+  private static final long MICROS_PER_SECOND = 1000000;
+
+  private static final ThreadLocal<SimpleDateFormat> timestampFormat =
+      new ThreadLocal<SimpleDateFormat>() {
+        protected SimpleDateFormat initialValue() {
+          return createTimestampFormat();
+        }
+      };
+
+  private static SimpleDateFormat createTimestampFormat() {
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    GregorianCalendar calendar =
+      new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+    // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
+    // backwards to year one) for timestamp formating.
+    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
+    sdf.setCalendar(calendar);
+    return sdf;
+  }
+
+  private TimeUtil() {}
+
+  /**
+   * Convert Timestamp to RFC 3339 date string format. The output will always
+   * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
+   * represent the exact value. Note that Timestamp can only represent time
+   * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
+   * https://www.ietf.org/rfc/rfc3339.txt
+   *
+   * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
+   *
+   * @return The string representation of the given timestamp.
+   * @throws IllegalArgumentException if the given timestamp is not in the
+   *         valid range.
+   */
+  public static String toString(Timestamp timestamp)
+    throws IllegalArgumentException {
+    StringBuilder result = new StringBuilder();
+    // Format the seconds part.
+    if (timestamp.getSeconds() < TIMESTAMP_SECONDS_MIN
+        || timestamp.getSeconds() > TIMESTAMP_SECONDS_MAX) {
+      throw new IllegalArgumentException("Timestamp is out of range.");
+    }
+    Date date = new Date(timestamp.getSeconds() * MILLIS_PER_SECOND);
+    result.append(timestampFormat.get().format(date));
+    // Format the nanos part.
+    if (timestamp.getNanos() < 0 || timestamp.getNanos() >= NANOS_PER_SECOND) {
+      throw new IllegalArgumentException("Timestamp has invalid nanos value.");
+    }
+    if (timestamp.getNanos() != 0) {
+      result.append(".");
+      result.append(formatNanos(timestamp.getNanos()));
+    }
+    result.append("Z");
+    return result.toString();
+  }
+
+  /**
+   * Parse from RFC 3339 date string to Timestamp. This method accepts all
+   * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
+   * digits (or none) and any offset as long as they fit into nano-seconds
+   * precision.
+   *
+   * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
+   *
+   * @return A Timestamp parsed from the string.
+   * @throws ParseException if parsing fails.
+   */
+
+  public static Timestamp parseTimestamp(String value) throws ParseException {
+    int dayOffset = value.indexOf('T');
+    if (dayOffset == -1) {
+      throw new ParseException(
+        "Failed to parse timestamp: invalid timestamp \"" + value + "\"", 0);
+    }
+    int timezoneOffsetPosition = value.indexOf('Z', dayOffset);
+    if (timezoneOffsetPosition == -1) {
+      timezoneOffsetPosition = value.indexOf('+', dayOffset);
+    }
+    if (timezoneOffsetPosition == -1) {
+      timezoneOffsetPosition = value.indexOf('-', dayOffset);
+    }
+    if (timezoneOffsetPosition == -1) {
+      throw new ParseException(
+        "Failed to parse timestamp: missing valid timezone offset.", 0);
+    }
+    // Parse seconds and nanos.
+    String timeValue = value.substring(0, timezoneOffsetPosition);
+    String secondValue = timeValue;
+    String nanoValue = "";
+    int pointPosition = timeValue.indexOf('.');
+    if (pointPosition != -1) {
+      secondValue = timeValue.substring(0, pointPosition);
+      nanoValue = timeValue.substring(pointPosition + 1);
+    }
+    Date date = timestampFormat.get().parse(secondValue);
+    long seconds = date.getTime() / MILLIS_PER_SECOND;
+    int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
+    // Parse timezone offsets.
+    if (value.charAt(timezoneOffsetPosition) == 'Z') {
+      if (value.length() != timezoneOffsetPosition + 1) {
+        throw new ParseException(
+          "Failed to parse timestamp: invalid trailing data \""
+          + value.substring(timezoneOffsetPosition) + "\"", 0);
+      }
+    } else {
+      String offsetValue = value.substring(timezoneOffsetPosition + 1);
+      long offset = parseTimezoneOffset(offsetValue);
+      if (value.charAt(timezoneOffsetPosition) == '+') {
+        seconds -= offset;
+      } else {
+        seconds += offset;
+      }
+    }
+    try {
+      return normalizedTimestamp(seconds, nanos);
+    } catch (IllegalArgumentException e) {
+      throw new ParseException(
+        "Failed to parse timestmap: timestamp is out of range.", 0);
+    }
+  }
+
+  /**
+   * Convert Duration to string format. The string format will contains 3, 6,
+   * or 9 fractional digits depending on the precision required to represent
+   * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
+   * "-3.100s" The range that can be represented by Duration is from
+   * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
+   *
+   * @return The string representation of the given duration.
+   * @throws IllegalArgumentException if the given duration is not in the valid
+   *         range.
+   */
+  public static String toString(Duration duration)
+    throws IllegalArgumentException {
+    if (duration.getSeconds() < DURATION_SECONDS_MIN
+      || duration.getSeconds() > DURATION_SECONDS_MAX) {
+      throw new IllegalArgumentException("Duration is out of valid range.");
+    }
+    StringBuilder result = new StringBuilder();
+    long seconds = duration.getSeconds();
+    int nanos = duration.getNanos();
+    if (seconds < 0 || nanos < 0) {
+      if (seconds > 0 || nanos > 0) {
+        throw new IllegalArgumentException(
+            "Invalid duration: seconds value and nanos value must have the same"
+            + "sign.");
+      }
+      result.append("-");
+      seconds = -seconds;
+      nanos = -nanos;
+    }
+    result.append(seconds);
+    if (nanos != 0) {
+      result.append(".");
+      result.append(formatNanos(nanos));
+    }
+    result.append("s");
+    return result.toString();
+  }
+
+  /**
+   * Parse from a string to produce a duration.
+   *
+   * @return A Duration parsed from the string.
+   * @throws ParseException if parsing fails.
+   */
+  public static Duration parseDuration(String value) throws ParseException {
+    // Must ended with "s".
+    if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
+      throw new ParseException("Invalid duration string: " + value, 0);
+    }
+    boolean negative = false;
+    if (value.charAt(0) == '-') {
+      negative = true;
+      value = value.substring(1);
+    }
+    String secondValue = value.substring(0, value.length() - 1);
+    String nanoValue = "";
+    int pointPosition = secondValue.indexOf('.');
+    if (pointPosition != -1) {
+      nanoValue = secondValue.substring(pointPosition + 1);
+      secondValue = secondValue.substring(0, pointPosition);
+    }
+    long seconds = Long.parseLong(secondValue);
+    int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
+    if (seconds < 0) {
+      throw new ParseException("Invalid duration string: " + value, 0);
+    }
+    if (negative) {
+      seconds = -seconds;
+      nanos = -nanos;
+    }
+    try {
+      return normalizedDuration(seconds, nanos);
+    } catch (IllegalArgumentException e) {
+      throw new ParseException("Duration value is out of range.", 0);
+    }
+  }
+
+  /**
+   * Create a Timestamp from the number of milliseconds elapsed from the epoch.
+   */
+  public static Timestamp createTimestampFromMillis(long milliseconds) {
+    return normalizedTimestamp(milliseconds / MILLIS_PER_SECOND,
+      (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+  }
+
+  /**
+   * Create a Duration from the number of milliseconds.
+   */
+  public static Duration createDurationFromMillis(long milliseconds) {
+    return normalizedDuration(milliseconds / MILLIS_PER_SECOND,
+      (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+  }
+
+  /**
+   * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
+   *
+   * <p>The result will be rounded down to the nearest millisecond. E.g., if the
+   * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+   * to -1 millisecond.
+   */
+  public static long toMillis(Timestamp timestamp) {
+    return timestamp.getSeconds() * MILLIS_PER_SECOND + timestamp.getNanos()
+      / NANOS_PER_MILLISECOND;
+  }
+
+  /**
+   * Convert a Duration to the number of milliseconds.The result will be
+   * rounded towards 0 to the nearest millisecond. E.g., if the duration
+   * represents -1 nanosecond, it will be rounded to 0.
+   */
+  public static long toMillis(Duration duration) {
+    return duration.getSeconds() * MILLIS_PER_SECOND + duration.getNanos()
+      / NANOS_PER_MILLISECOND;
+  }
+
+  /**
+   * Create a Timestamp from the number of microseconds elapsed from the epoch.
+   */
+  public static Timestamp createTimestampFromMicros(long microseconds) {
+    return normalizedTimestamp(microseconds / MICROS_PER_SECOND,
+      (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+  }
+
+  /**
+   * Create a Duration from the number of microseconds.
+   */
+  public static Duration createDurationFromMicros(long microseconds) {
+    return normalizedDuration(microseconds / MICROS_PER_SECOND,
+      (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+  }
+
+  /**
+   * Convert a Timestamp to the number of microseconds elapsed from the epoch.
+   *
+   * <p>The result will be rounded down to the nearest microsecond. E.g., if the
+   * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+   * to -1 millisecond.
+   */
+  public static long toMicros(Timestamp timestamp) {
+    return timestamp.getSeconds() * MICROS_PER_SECOND + timestamp.getNanos()
+      / NANOS_PER_MICROSECOND;
+  }
+
+  /**
+   * Convert a Duration to the number of microseconds.The result will be
+   * rounded towards 0 to the nearest microseconds. E.g., if the duration
+   * represents -1 nanosecond, it will be rounded to 0.
+   */
+  public static long toMicros(Duration duration) {
+    return duration.getSeconds() * MICROS_PER_SECOND + duration.getNanos()
+      / NANOS_PER_MICROSECOND;
+  }
+
+  /**
+   * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
+   */
+  public static Timestamp createTimestampFromNanos(long nanoseconds) {
+    return normalizedTimestamp(nanoseconds / NANOS_PER_SECOND,
+      (int) (nanoseconds % NANOS_PER_SECOND));
+  }
+
+  /**
+   * Create a Duration from the number of nanoseconds.
+   */
+  public static Duration createDurationFromNanos(long nanoseconds) {
+    return normalizedDuration(nanoseconds / NANOS_PER_SECOND,
+      (int) (nanoseconds % NANOS_PER_SECOND));
+  }
+
+  /**
+   * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
+   */
+  public static long toNanos(Timestamp timestamp) {
+    return timestamp.getSeconds() * NANOS_PER_SECOND + timestamp.getNanos();
+  }
+
+  /**
+   * Convert a Duration to the number of nanoseconds.
+   */
+  public static long toNanos(Duration duration) {
+    return duration.getSeconds() * NANOS_PER_SECOND + duration.getNanos();
+  }
+
+  /**
+   * Get the current time.
+   */
+  public static Timestamp getCurrentTime() {
+    return createTimestampFromMillis(System.currentTimeMillis());
+  }
+
+  /**
+   * Get the epoch.
+   */
+  public static Timestamp getEpoch() {
+    return Timestamp.getDefaultInstance();
+  }
+
+  /**
+   * Calculate the difference between two timestamps.
+   */
+  public static Duration distance(Timestamp from, Timestamp to) {
+    return normalizedDuration(to.getSeconds() - from.getSeconds(),
+      to.getNanos() - from.getNanos());
+  }
+
+  /**
+   * Add a duration to a timestamp.
+   */
+  public static Timestamp add(Timestamp start, Duration length) {
+    return normalizedTimestamp(start.getSeconds() + length.getSeconds(),
+      start.getNanos() + length.getNanos());
+  }
+
+  /**
+   * Subtract a duration from a timestamp.
+   */
+  public static Timestamp subtract(Timestamp start, Duration length) {
+    return normalizedTimestamp(start.getSeconds() - length.getSeconds(),
+      start.getNanos() - length.getNanos());
+  }
+
+  /**
+   * Add two durations.
+   */
+  public static Duration add(Duration d1, Duration d2) {
+    return normalizedDuration(d1.getSeconds() + d2.getSeconds(),
+      d1.getNanos() + d2.getNanos());
+  }
+
+  /**
+   * Subtract a duration from another.
+   */
+  public static Duration subtract(Duration d1, Duration d2) {
+    return normalizedDuration(d1.getSeconds() - d2.getSeconds(),
+      d1.getNanos() - d2.getNanos());
+  }
+
+  // Multiplications and divisions.
+
+  public static Duration multiply(Duration duration, double times) {
+    double result = duration.getSeconds() * times + duration.getNanos() * times
+      / 1000000000.0;
+    if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
+      throw new IllegalArgumentException("Result is out of valid range.");
+    }
+    long seconds = (long) result;
+    int nanos = (int) ((result - seconds) * 1000000000);
+    return normalizedDuration(seconds, nanos);
+  }
+  
+  public static Duration divide(Duration duration, double value) {
+    return multiply(duration, 1.0 / value);
+  }
+  
+  public static Duration multiply(Duration duration, long times) {
+    return createDurationFromBigInteger(
+      toBigInteger(duration).multiply(toBigInteger(times)));
+  }
+  
+  public static Duration divide(Duration duration, long times) {
+    return createDurationFromBigInteger(
+      toBigInteger(duration).divide(toBigInteger(times)));
+  }
+  
+  public static long divide(Duration d1, Duration d2) {
+    return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
+  }
+  
+  public static Duration remainder(Duration d1, Duration d2) {
+    return createDurationFromBigInteger(
+      toBigInteger(d1).remainder(toBigInteger(d2)));
+  }
+  
+  private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
+      new BigInteger(String.valueOf(NANOS_PER_SECOND));
+  
+  private static BigInteger toBigInteger(Duration duration) {
+    return toBigInteger(duration.getSeconds())
+      .multiply(NANOS_PER_SECOND_BIG_INTEGER)
+      .add(toBigInteger(duration.getNanos()));
+  }
+  
+  private static BigInteger toBigInteger(long value) {
+    return new BigInteger(String.valueOf(value));
+  }
+  
+  private static Duration createDurationFromBigInteger(BigInteger value) {
+    long seconds = value.divide(
+      new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
+    int nanos = value.remainder(
+      new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
+    return normalizedDuration(seconds, nanos);
+    
+  }
+
+  private static Duration normalizedDuration(long seconds, int nanos) {
+    if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+      seconds += nanos / NANOS_PER_SECOND;
+      nanos %= NANOS_PER_SECOND;
+    }
+    if (seconds > 0 && nanos < 0) {
+      nanos += NANOS_PER_SECOND;
+      seconds -= 1;
+    }
+    if (seconds < 0 && nanos > 0) {
+      nanos -= NANOS_PER_SECOND;
+      seconds += 1;
+    }
+    if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
+      throw new IllegalArgumentException("Duration is out of valid range.");
+    }
+    return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+  }
+
+  private static Timestamp normalizedTimestamp(long seconds, int nanos) {
+    if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+      seconds += nanos / NANOS_PER_SECOND;
+      nanos %= NANOS_PER_SECOND;
+    }
+    if (nanos < 0) {
+      nanos += NANOS_PER_SECOND;
+      seconds -= 1;
+    }
+    if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
+      throw new IllegalArgumentException("Timestamp is out of valid range.");
+    }
+    return Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+  }
+
+  /**
+   * Format the nano part of a timestamp or a duration.
+   */
+  private static String formatNanos(int nanos) {
+    assert nanos >= 1 && nanos <= 999999999;
+    // Determine whether to use 3, 6, or 9 digits for the nano part.
+    if (nanos % NANOS_PER_MILLISECOND == 0) {
+      return String.format("%1$03d", nanos / NANOS_PER_MILLISECOND);
+    } else if (nanos % NANOS_PER_MICROSECOND == 0) {
+      return String.format("%1$06d", nanos / NANOS_PER_MICROSECOND);
+    } else {
+      return String.format("%1$09d", nanos);
+    }
+  }
+
+  private static int parseNanos(String value) throws ParseException {
+    int result = 0;
+    for (int i = 0; i < 9; ++i) {
+      result = result * 10;
+      if (i < value.length()) {
+        if (value.charAt(i) < '0' || value.charAt(i) > '9') {
+          throw new ParseException("Invalid nanosecnds.", 0);
+        }
+        result += value.charAt(i) - '0';
+      }
+    }
+    return result;
+  }
+
+  private static long parseTimezoneOffset(String value) throws ParseException {
+    int pos = value.indexOf(':');
+    if (pos == -1) {
+      throw new ParseException("Invalid offset value: " + value, 0);
+    }
+    String hours = value.substring(0, pos);
+    String minutes = value.substring(pos + 1);
+    return (Long.parseLong(hours) * 60 + Long.parseLong(minutes)) * 60;
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
new file mode 100644
index 0000000..3ee0fc6
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -0,0 +1,261 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+
+import junit.framework.TestCase;
+
+public class FieldMaskTreeTest extends TestCase {
+  public void testAddFieldPath() throws Exception {
+    FieldMaskTree tree = new FieldMaskTree();
+    assertEquals("", tree.toString());
+    tree.addFieldPath("");
+    assertEquals("", tree.toString());
+    // New branch.
+    tree.addFieldPath("foo");
+    assertEquals("foo", tree.toString());
+    // Redundant path.
+    tree.addFieldPath("foo");
+    assertEquals("foo", tree.toString());
+    // New branch.
+    tree.addFieldPath("bar.baz");
+    assertEquals("bar.baz,foo", tree.toString());
+    // Redundant sub-path.
+    tree.addFieldPath("foo.bar");
+    assertEquals("bar.baz,foo", tree.toString());
+    // New branch from a non-root node.
+    tree.addFieldPath("bar.quz");
+    assertEquals("bar.baz,bar.quz,foo", tree.toString());
+    // A path that matches several existing sub-paths.
+    tree.addFieldPath("bar");
+    assertEquals("bar,foo", tree.toString());
+  }
+
+  public void testMergeFromFieldMask() throws Exception {
+    FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+    assertEquals("bar.baz,bar.quz,foo", tree.toString());
+    tree.mergeFromFieldMask(FieldMaskUtil.fromString("foo.bar,bar"));
+    assertEquals("bar,foo", tree.toString());
+  }
+
+  public void testIntersectFieldPath() throws Exception {
+    FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+    FieldMaskTree result = new FieldMaskTree();
+    // Empty path.
+    tree.intersectFieldPath("", result);
+    assertEquals("", result.toString());
+    // Non-exist path.
+    tree.intersectFieldPath("quz", result);
+    assertEquals("", result.toString());
+    // Sub-path of an existing leaf.
+    tree.intersectFieldPath("foo.bar", result);
+    assertEquals("foo.bar", result.toString());
+    // Match an existing leaf node.
+    tree.intersectFieldPath("foo", result);
+    assertEquals("foo", result.toString());
+    // Non-exist path.
+    tree.intersectFieldPath("bar.foo", result);
+    assertEquals("foo", result.toString());
+    // Match a non-leaf node.
+    tree.intersectFieldPath("bar", result);
+    assertEquals("bar.baz,bar.quz,foo", result.toString());
+  }
+
+  public void testMerge() throws Exception {
+    TestAllTypes value =
+        TestAllTypes.newBuilder()
+            .setOptionalInt32(1234)
+            .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678))
+            .addRepeatedInt32(4321)
+            .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765))
+            .build();
+    NestedTestAllTypes source =
+        NestedTestAllTypes.newBuilder()
+            .setPayload(value)
+            .setChild(NestedTestAllTypes.newBuilder().setPayload(value))
+            .build();
+    // Now we have a message source with the following structure:
+    //   [root] -+- payload -+- optional_int32
+    //           |           +- optional_nested_message
+    //           |           +- repeated_int32
+    //           |           +- repeated_nested_message
+    //           |
+    //           +- child --- payload -+- optional_int32
+    //                                 +- optional_nested_message
+    //                                 +- repeated_int32
+    //                                 +- repeated_nested_message
+
+    FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
+
+    // Test merging each individual field.
+    NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree().addFieldPath("payload.optional_int32").merge(source, builder, options);
+    NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().setOptionalInt32(1234);
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.optional_nested_message")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().addRepeatedInt32(4321);
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.repeated_nested_message")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("child.payload.optional_int32")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234);
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("child.payload.optional_nested_message")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected
+        .getChildBuilder()
+        .getPayloadBuilder()
+        .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("child.payload.repeated_int32")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321);
+    assertEquals(expected.build(), builder.build());
+
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("child.payload.repeated_nested_message")
+        .merge(source, builder, options);
+    expected = NestedTestAllTypes.newBuilder();
+    expected
+        .getChildBuilder()
+        .getPayloadBuilder()
+        .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
+    assertEquals(expected.build(), builder.build());
+
+    // Test merging all fields.
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree()
+        .addFieldPath("child")
+        .addFieldPath("payload")
+        .merge(source, builder, options);
+    assertEquals(source, builder.build());
+
+    // Test repeated options.
+    builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().addRepeatedInt32(1000);
+    new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+    // Default behavior is to append repeated fields.
+    assertEquals(2, builder.getPayload().getRepeatedInt32Count());
+    assertEquals(1000, builder.getPayload().getRepeatedInt32(0));
+    assertEquals(4321, builder.getPayload().getRepeatedInt32(1));
+    // Change to replace repeated fields.
+    options.setReplaceRepeatedFields(true);
+    new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+    assertEquals(1, builder.getPayload().getRepeatedInt32Count());
+    assertEquals(4321, builder.getPayload().getRepeatedInt32(0));
+
+    // Test message options.
+    builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().setOptionalInt32(1000);
+    builder.getPayloadBuilder().setOptionalUint32(2000);
+    new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+    // Default behavior is to merge message fields.
+    assertEquals(1234, builder.getPayload().getOptionalInt32());
+    assertEquals(2000, builder.getPayload().getOptionalUint32());
+
+    // Test merging unset message fields.
+    NestedTestAllTypes clearedSource = source.toBuilder().clearPayload().build();
+    builder = NestedTestAllTypes.newBuilder();
+    new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+    assertEquals(false, builder.hasPayload());
+
+    // Change to replace message fields.
+    options.setReplaceMessageFields(true);
+    builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().setOptionalInt32(1000);
+    builder.getPayloadBuilder().setOptionalUint32(2000);
+    new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+    assertEquals(1234, builder.getPayload().getOptionalInt32());
+    assertEquals(0, builder.getPayload().getOptionalUint32());
+
+    // Test merging unset message fields.
+    builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().setOptionalInt32(1000);
+    builder.getPayloadBuilder().setOptionalUint32(2000);
+    new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+    assertEquals(false, builder.hasPayload());
+
+    // Test merging unset primitive fields.
+    builder = source.toBuilder();
+    builder.getPayloadBuilder().clearOptionalInt32();
+    NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build();
+    builder = source.toBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.optional_int32")
+        .merge(sourceWithPayloadInt32Unset, builder, options);
+    assertEquals(true, builder.getPayload().hasOptionalInt32());
+    assertEquals(0, builder.getPayload().getOptionalInt32());
+
+    // Change to clear unset primitive fields.
+    options.setReplacePrimitiveFields(true);
+    builder = source.toBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.optional_int32")
+        .merge(sourceWithPayloadInt32Unset, builder, options);
+    assertEquals(true, builder.hasPayload());
+    assertEquals(false, builder.getPayload().hasOptionalInt32());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
new file mode 100644
index 0000000..194f7b9
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
@@ -0,0 +1,184 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.FieldMask;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/** Unit tests for {@link FieldMaskUtil}. */
+public class FieldMaskUtilTest extends TestCase {
+  public void testIsValid() throws Exception {
+    assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload"));
+    assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "nonexist"));
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.optional_int32"));
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.repeated_int32"));
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.optional_nested_message"));
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.repeated_nested_message"));
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.nonexist"));
+    
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, FieldMaskUtil.fromString("payload")));
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, FieldMaskUtil.fromString("nonexist")));
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, FieldMaskUtil.fromString("payload,nonexist")));
+    
+    assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "payload"));
+    assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "nonexist"));
+    
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("payload")));
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("nonexist")));
+    
+    assertTrue(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.optional_nested_message.bb"));
+    // Repeated fields cannot have sub-paths.
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.repeated_nested_message.bb"));
+    // Non-message fields cannot have sub-paths.
+    assertFalse(FieldMaskUtil.isValid(
+        NestedTestAllTypes.class, "payload.optional_int32.bb"));
+  }
+  
+  public void testToString() throws Exception {
+    assertEquals("", FieldMaskUtil.toString(FieldMask.getDefaultInstance()));
+    FieldMask mask = FieldMask.newBuilder().addPaths("foo").build();
+    assertEquals("foo", FieldMaskUtil.toString(mask));
+    mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
+    assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+    
+    // Empty field paths are ignored.
+    mask = FieldMask.newBuilder().addPaths("").addPaths("foo").addPaths("").
+      addPaths("bar").addPaths("").build();
+    assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+  }
+
+  public void testFromString() throws Exception {
+    FieldMask mask = FieldMaskUtil.fromString("");
+    assertEquals(0, mask.getPathsCount());
+    mask = FieldMaskUtil.fromString("foo");
+    assertEquals(1, mask.getPathsCount());
+    assertEquals("foo", mask.getPaths(0));
+    mask = FieldMaskUtil.fromString("foo,bar.baz");
+    assertEquals(2, mask.getPathsCount());
+    assertEquals("foo", mask.getPaths(0));
+    assertEquals("bar.baz", mask.getPaths(1));
+
+    // Empty field paths are ignore.
+    mask = FieldMaskUtil.fromString(",foo,,bar,");
+    assertEquals(2, mask.getPathsCount());
+    assertEquals("foo", mask.getPaths(0));
+    assertEquals("bar", mask.getPaths(1));
+
+    // Check whether the field paths are valid if a class parameter is provided.
+    mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, ",payload");
+
+    try {
+      mask = FieldMaskUtil.fromString(
+          NestedTestAllTypes.class, "payload,nonexist");
+      fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+  }
+
+  public void testFromFieldNumbers() throws Exception {
+    FieldMask mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class);
+    assertEquals(0, mask.getPathsCount());
+    mask =
+        FieldMaskUtil.fromFieldNumbers(
+            TestAllTypes.class, TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER);
+    assertEquals(1, mask.getPathsCount());
+    assertEquals("optional_int32", mask.getPaths(0));
+    mask =
+        FieldMaskUtil.fromFieldNumbers(
+            TestAllTypes.class,
+            TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER,
+            TestAllTypes.OPTIONAL_INT64_FIELD_NUMBER);
+    assertEquals(2, mask.getPathsCount());
+    assertEquals("optional_int32", mask.getPaths(0));
+    assertEquals("optional_int64", mask.getPaths(1));
+
+    try {
+      int invalidFieldNumber = 1000;
+      mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class, invalidFieldNumber);
+      fail("Exception is expected.");
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+  
+  public void testUnion() throws Exception {
+    // Only test a simple case here and expect
+    // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios.
+    FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+    FieldMask result = FieldMaskUtil.union(mask1, mask2);
+    assertEquals("bar,foo", FieldMaskUtil.toString(result));
+  }
+
+  public void testUnion_usingVarArgs() throws Exception {
+    FieldMask mask1 = FieldMaskUtil.fromString("foo");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz");
+    FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
+    FieldMask mask4 = FieldMaskUtil.fromString("bar");
+    FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4);
+    assertEquals("bar,foo", FieldMaskUtil.toString(result));
+  }
+  
+  public void testIntersection() throws Exception {
+    // Only test a simple case here and expect
+    // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
+    FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+    FieldMask result = FieldMaskUtil.intersection(mask1, mask2);
+    assertEquals("bar.baz,bar.quz,foo.bar", FieldMaskUtil.toString(result));
+  }
+  
+  public void testMerge() throws Exception {
+    // Only test a simple case here and expect
+    // {@link FieldMaskTreeTest#testMerge} to cover all scenarios.
+    NestedTestAllTypes source = NestedTestAllTypes.newBuilder()
+        .setPayload(TestAllTypes.newBuilder().setOptionalInt32(1234))
+        .build();
+    NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+    FieldMaskUtil.merge(FieldMaskUtil.fromString("payload"), source, builder);
+    assertEquals(1234, builder.getPayload().getOptionalInt32());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
new file mode 100644
index 0000000..d95b626
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -0,0 +1,1174 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+import com.google.protobuf.util.JsonFormat.TypeRegistry;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
+import com.google.protobuf.util.JsonTestProto.TestAny;
+import com.google.protobuf.util.JsonTestProto.TestCustomJsonName;
+import com.google.protobuf.util.JsonTestProto.TestDuration;
+import com.google.protobuf.util.JsonTestProto.TestFieldMask;
+import com.google.protobuf.util.JsonTestProto.TestMap;
+import com.google.protobuf.util.JsonTestProto.TestOneof;
+import com.google.protobuf.util.JsonTestProto.TestStruct;
+import com.google.protobuf.util.JsonTestProto.TestTimestamp;
+import com.google.protobuf.util.JsonTestProto.TestWrappers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonFormatTest extends TestCase {
+  private void setAllFields(TestAllTypes.Builder builder) {
+    builder.setOptionalInt32(1234);
+    builder.setOptionalInt64(1234567890123456789L);
+    builder.setOptionalUint32(5678);
+    builder.setOptionalUint64(2345678901234567890L);
+    builder.setOptionalSint32(9012);
+    builder.setOptionalSint64(3456789012345678901L);
+    builder.setOptionalFixed32(3456);
+    builder.setOptionalFixed64(4567890123456789012L);
+    builder.setOptionalSfixed32(7890);
+    builder.setOptionalSfixed64(5678901234567890123L);
+    builder.setOptionalFloat(1.5f);
+    builder.setOptionalDouble(1.25);
+    builder.setOptionalBool(true);
+    builder.setOptionalString("Hello world!");
+    builder.setOptionalBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
+    builder.setOptionalNestedEnum(NestedEnum.BAR);
+    builder.getOptionalNestedMessageBuilder().setValue(100);
+
+    builder.addRepeatedInt32(1234);
+    builder.addRepeatedInt64(1234567890123456789L);
+    builder.addRepeatedUint32(5678);
+    builder.addRepeatedUint64(2345678901234567890L);
+    builder.addRepeatedSint32(9012);
+    builder.addRepeatedSint64(3456789012345678901L);
+    builder.addRepeatedFixed32(3456);
+    builder.addRepeatedFixed64(4567890123456789012L);
+    builder.addRepeatedSfixed32(7890);
+    builder.addRepeatedSfixed64(5678901234567890123L);
+    builder.addRepeatedFloat(1.5f);
+    builder.addRepeatedDouble(1.25);
+    builder.addRepeatedBool(true);
+    builder.addRepeatedString("Hello world!");
+    builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
+    builder.addRepeatedNestedEnum(NestedEnum.BAR);
+    builder.addRepeatedNestedMessageBuilder().setValue(100);
+
+    builder.addRepeatedInt32(234);
+    builder.addRepeatedInt64(234567890123456789L);
+    builder.addRepeatedUint32(678);
+    builder.addRepeatedUint64(345678901234567890L);
+    builder.addRepeatedSint32(012);
+    builder.addRepeatedSint64(456789012345678901L);
+    builder.addRepeatedFixed32(456);
+    builder.addRepeatedFixed64(567890123456789012L);
+    builder.addRepeatedSfixed32(890);
+    builder.addRepeatedSfixed64(678901234567890123L);
+    builder.addRepeatedFloat(11.5f);
+    builder.addRepeatedDouble(11.25);
+    builder.addRepeatedBool(true);
+    builder.addRepeatedString("ello world!");
+    builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{1, 2}));
+    builder.addRepeatedNestedEnum(NestedEnum.BAZ);
+    builder.addRepeatedNestedMessageBuilder().setValue(200);
+  }
+
+  private void assertRoundTripEquals(Message message) throws Exception {
+    assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
+  }
+
+  private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
+    JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+    JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
+    Message.Builder builder = message.newBuilderForType();
+    parser.merge(printer.print(message), builder);
+    Message parsedMessage = builder.build();
+    assertEquals(message.toString(), parsedMessage.toString());
+  }
+
+  private String toJsonString(Message message) throws IOException {
+    return JsonFormat.printer().print(message);
+  }
+
+  private void mergeFromJson(String json, Message.Builder builder) throws IOException {
+    JsonFormat.parser().merge(json, builder);
+  }
+
+  public void testAllFields() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    assertEquals(
+        "{\n"
+            + "  \"optionalInt32\": 1234,\n"
+            + "  \"optionalInt64\": \"1234567890123456789\",\n"
+            + "  \"optionalUint32\": 5678,\n"
+            + "  \"optionalUint64\": \"2345678901234567890\",\n"
+            + "  \"optionalSint32\": 9012,\n"
+            + "  \"optionalSint64\": \"3456789012345678901\",\n"
+            + "  \"optionalFixed32\": 3456,\n"
+            + "  \"optionalFixed64\": \"4567890123456789012\",\n"
+            + "  \"optionalSfixed32\": 7890,\n"
+            + "  \"optionalSfixed64\": \"5678901234567890123\",\n"
+            + "  \"optionalFloat\": 1.5,\n"
+            + "  \"optionalDouble\": 1.25,\n"
+            + "  \"optionalBool\": true,\n"
+            + "  \"optionalString\": \"Hello world!\",\n"
+            + "  \"optionalBytes\": \"AAEC\",\n"
+            + "  \"optionalNestedMessage\": {\n"
+            + "    \"value\": 100\n"
+            + "  },\n"
+            + "  \"optionalNestedEnum\": \"BAR\",\n"
+            + "  \"repeatedInt32\": [1234, 234],\n"
+            + "  \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
+            + "  \"repeatedUint32\": [5678, 678],\n"
+            + "  \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
+            + "  \"repeatedSint32\": [9012, 10],\n"
+            + "  \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
+            + "  \"repeatedFixed32\": [3456, 456],\n"
+            + "  \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
+            + "  \"repeatedSfixed32\": [7890, 890],\n"
+            + "  \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
+            + "  \"repeatedFloat\": [1.5, 11.5],\n"
+            + "  \"repeatedDouble\": [1.25, 11.25],\n"
+            + "  \"repeatedBool\": [true, true],\n"
+            + "  \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
+            + "  \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
+            + "  \"repeatedNestedMessage\": [{\n"
+            + "    \"value\": 100\n"
+            + "  }, {\n"
+            + "    \"value\": 200\n"
+            + "  }],\n"
+            + "  \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
+            + "}",
+        toJsonString(message));
+
+    assertRoundTripEquals(message);
+  }
+
+  public void testUnknownEnumValues() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder()
+        .setOptionalNestedEnumValue(12345)
+        .addRepeatedNestedEnumValue(12345)
+        .addRepeatedNestedEnumValue(0)
+        .build();
+    assertEquals(
+        "{\n"
+        + "  \"optionalNestedEnum\": 12345,\n"
+        + "  \"repeatedNestedEnum\": [12345, \"FOO\"]\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+
+    TestMap.Builder mapBuilder = TestMap.newBuilder();
+    mapBuilder.getMutableInt32ToEnumMapValue().put(1, 0);
+    mapBuilder.getMutableInt32ToEnumMapValue().put(2, 12345);
+    TestMap mapMessage = mapBuilder.build();
+    assertEquals(
+        "{\n"
+            + "  \"int32ToEnumMap\": {\n"
+            + "    \"1\": \"FOO\",\n"
+            + "    \"2\": 12345\n"
+            + "  }\n"
+            + "}",
+        toJsonString(mapMessage));
+    assertRoundTripEquals(mapMessage);
+  }
+
+  public void testSpecialFloatValues() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder()
+        .addRepeatedFloat(Float.NaN)
+        .addRepeatedFloat(Float.POSITIVE_INFINITY)
+        .addRepeatedFloat(Float.NEGATIVE_INFINITY)
+        .addRepeatedDouble(Double.NaN)
+        .addRepeatedDouble(Double.POSITIVE_INFINITY)
+        .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+        .build();
+    assertEquals(
+        "{\n"
+        + "  \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
+        + "  \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
+        + "}", toJsonString(message));
+
+    assertRoundTripEquals(message);
+  }
+
+  public void testParserAcceptStringForNumbericField() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    mergeFromJson(
+        "{\n"
+        + "  \"optionalInt32\": \"1234\",\n"
+        + "  \"optionalUint32\": \"5678\",\n"
+        + "  \"optionalSint32\": \"9012\",\n"
+        + "  \"optionalFixed32\": \"3456\",\n"
+        + "  \"optionalSfixed32\": \"7890\",\n"
+        + "  \"optionalFloat\": \"1.5\",\n"
+        + "  \"optionalDouble\": \"1.25\",\n"
+        + "  \"optionalBool\": \"true\"\n"
+        + "}", builder);
+    TestAllTypes message = builder.build();
+    assertEquals(1234, message.getOptionalInt32());
+    assertEquals(5678, message.getOptionalUint32());
+    assertEquals(9012, message.getOptionalSint32());
+    assertEquals(3456, message.getOptionalFixed32());
+    assertEquals(7890, message.getOptionalSfixed32());
+    assertEquals(1.5f, message.getOptionalFloat());
+    assertEquals(1.25, message.getOptionalDouble());
+    assertEquals(true, message.getOptionalBool());
+  }
+
+  public void testParserAcceptFloatingPointValueForIntegerField() throws Exception {
+    // Test that numeric values like "1.000", "1e5" will also be accepted.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    mergeFromJson(
+        "{\n"
+            + "  \"repeatedInt32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+            + "  \"repeatedUint32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+            + "  \"repeatedInt64\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+            + "  \"repeatedUint64\": [1.000, 1e5, \"1.000\", \"1e5\"]\n"
+            + "}", builder);
+    int[] expectedValues = new int[]{1, 100000, 1, 100000};
+    assertEquals(4, builder.getRepeatedInt32Count());
+    assertEquals(4, builder.getRepeatedUint32Count());
+    assertEquals(4, builder.getRepeatedInt64Count());
+    assertEquals(4, builder.getRepeatedUint64Count());
+    for (int i = 0; i < 4; ++i) {
+      assertEquals(expectedValues[i], builder.getRepeatedInt32(i));
+      assertEquals(expectedValues[i], builder.getRepeatedUint32(i));
+      assertEquals(expectedValues[i], builder.getRepeatedInt64(i));
+      assertEquals(expectedValues[i], builder.getRepeatedUint64(i));
+    }
+
+    // Non-integers will still be rejected.
+    assertRejects("optionalInt32", "1.5");
+    assertRejects("optionalUint32", "1.5");
+    assertRejects("optionalInt64", "1.5");
+    assertRejects("optionalUint64", "1.5");
+  }
+
+  private void assertRejects(String name, String value) {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      // Numeric form is rejected.
+      mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+    try {
+      // String form is also rejected.
+      mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+  }
+
+  private void assertAccepts(String name, String value) throws IOException {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    // Both numeric form and string form are accepted.
+    mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+    builder.clear();
+    mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+  }
+
+  public void testParserRejectOutOfRangeNumericValues() throws Exception {
+    assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
+    assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
+    assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
+    assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
+
+    assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
+    assertRejects("optionalUint32", "123456789012345");
+    assertRejects("optionalUint32", "-1");
+
+    BigInteger one = new BigInteger("1");
+    BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
+    BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
+    assertAccepts("optionalInt64", maxLong.toString());
+    assertAccepts("optionalInt64", minLong.toString());
+    assertRejects("optionalInt64", maxLong.add(one).toString());
+    assertRejects("optionalInt64", minLong.subtract(one).toString());
+
+    assertAccepts("optionalUint64", maxLong.add(one).toString());
+    assertRejects("optionalUint64", "1234567890123456789012345");
+    assertRejects("optionalUint64", "-1");
+
+    assertAccepts("optionalBool", "true");
+    assertRejects("optionalBool", "1");
+    assertRejects("optionalBool", "0");
+
+    assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
+    assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
+    assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
+    assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
+
+    BigDecimal moreThanOne = new BigDecimal("1.000001");
+    BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
+    BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
+    assertAccepts("optionalDouble", maxDouble.toString());
+    assertAccepts("optionalDouble", minDouble.toString());
+    assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
+    assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
+  }
+
+  public void testParserAcceptNull() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    mergeFromJson(
+        "{\n"
+        + "  \"optionalInt32\": null,\n"
+        + "  \"optionalInt64\": null,\n"
+        + "  \"optionalUint32\": null,\n"
+        + "  \"optionalUint64\": null,\n"
+        + "  \"optionalSint32\": null,\n"
+        + "  \"optionalSint64\": null,\n"
+        + "  \"optionalFixed32\": null,\n"
+        + "  \"optionalFixed64\": null,\n"
+        + "  \"optionalSfixed32\": null,\n"
+        + "  \"optionalSfixed64\": null,\n"
+        + "  \"optionalFloat\": null,\n"
+        + "  \"optionalDouble\": null,\n"
+        + "  \"optionalBool\": null,\n"
+        + "  \"optionalString\": null,\n"
+        + "  \"optionalBytes\": null,\n"
+        + "  \"optionalNestedMessage\": null,\n"
+        + "  \"optionalNestedEnum\": null,\n"
+        + "  \"repeatedInt32\": null,\n"
+        + "  \"repeatedInt64\": null,\n"
+        + "  \"repeatedUint32\": null,\n"
+        + "  \"repeatedUint64\": null,\n"
+        + "  \"repeatedSint32\": null,\n"
+        + "  \"repeatedSint64\": null,\n"
+        + "  \"repeatedFixed32\": null,\n"
+        + "  \"repeatedFixed64\": null,\n"
+        + "  \"repeatedSfixed32\": null,\n"
+        + "  \"repeatedSfixed64\": null,\n"
+        + "  \"repeatedFloat\": null,\n"
+        + "  \"repeatedDouble\": null,\n"
+        + "  \"repeatedBool\": null,\n"
+        + "  \"repeatedString\": null,\n"
+        + "  \"repeatedBytes\": null,\n"
+        + "  \"repeatedNestedMessage\": null,\n"
+        + "  \"repeatedNestedEnum\": null\n"
+        + "}", builder);
+    TestAllTypes message = builder.build();
+    assertEquals(TestAllTypes.getDefaultInstance(), message);
+
+    // Repeated field elements cannot be null.
+    try {
+      builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"repeatedInt32\": [null, null],\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+
+    try {
+      builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"repeatedNestedMessage\": [null, null],\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+  }
+
+  public void testParserRejectDuplicatedFields() throws Exception {
+    // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last
+    // one if multiple entries have the same name. This is not the desired behavior but it can
+    // only be fixed by using our own parser. Here we only test the cases where the names are
+    // different but still referring to the same field.
+
+    // Duplicated optional fields.
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+              + "  \"optionalNestedMessage\": {},\n"
+              + "  \"optional_nested_message\": {}\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+
+    // Duplicated repeated fields.
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"repeatedNestedMessage\": [null, null],\n"
+          + "  \"repeated_nested_message\": [null, null]\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+
+    // Duplicated oneof fields.
+    try {
+      TestOneof.Builder builder = TestOneof.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"oneofInt32\": 1,\n"
+          + "  \"oneof_int32\": 2\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+  }
+
+  public void testMapFields() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    builder.getMutableInt32ToInt32Map().put(1, 10);
+    builder.getMutableInt64ToInt32Map().put(1234567890123456789L, 10);
+    builder.getMutableUint32ToInt32Map().put(2, 20);
+    builder.getMutableUint64ToInt32Map().put(2234567890123456789L, 20);
+    builder.getMutableSint32ToInt32Map().put(3, 30);
+    builder.getMutableSint64ToInt32Map().put(3234567890123456789L, 30);
+    builder.getMutableFixed32ToInt32Map().put(4, 40);
+    builder.getMutableFixed64ToInt32Map().put(4234567890123456789L, 40);
+    builder.getMutableSfixed32ToInt32Map().put(5, 50);
+    builder.getMutableSfixed64ToInt32Map().put(5234567890123456789L, 50);
+    builder.getMutableBoolToInt32Map().put(false, 6);
+    builder.getMutableStringToInt32Map().put("Hello", 10);
+
+    builder.getMutableInt32ToInt64Map().put(1, 1234567890123456789L);
+    builder.getMutableInt32ToUint32Map().put(2, 20);
+    builder.getMutableInt32ToUint64Map().put(2, 2234567890123456789L);
+    builder.getMutableInt32ToSint32Map().put(3, 30);
+    builder.getMutableInt32ToSint64Map().put(3, 3234567890123456789L);
+    builder.getMutableInt32ToFixed32Map().put(4, 40);
+    builder.getMutableInt32ToFixed64Map().put(4, 4234567890123456789L);
+    builder.getMutableInt32ToSfixed32Map().put(5, 50);
+    builder.getMutableInt32ToSfixed64Map().put(5, 5234567890123456789L);
+    builder.getMutableInt32ToFloatMap().put(6, 1.5f);
+    builder.getMutableInt32ToDoubleMap().put(6, 1.25);
+    builder.getMutableInt32ToBoolMap().put(7, false);
+    builder.getMutableInt32ToStringMap().put(7, "World");
+    builder.getMutableInt32ToBytesMap().put(
+        8, ByteString.copyFrom(new byte[]{1, 2, 3}));
+    builder.getMutableInt32ToMessageMap().put(
+        8, NestedMessage.newBuilder().setValue(1234).build());
+    builder.getMutableInt32ToEnumMap().put(9, NestedEnum.BAR);
+    TestMap message = builder.build();
+
+    assertEquals(
+        "{\n"
+        + "  \"int32ToInt32Map\": {\n"
+        + "    \"1\": 10\n"
+        + "  },\n"
+        + "  \"int64ToInt32Map\": {\n"
+        + "    \"1234567890123456789\": 10\n"
+        + "  },\n"
+        + "  \"uint32ToInt32Map\": {\n"
+        + "    \"2\": 20\n"
+        + "  },\n"
+        + "  \"uint64ToInt32Map\": {\n"
+        + "    \"2234567890123456789\": 20\n"
+        + "  },\n"
+        + "  \"sint32ToInt32Map\": {\n"
+        + "    \"3\": 30\n"
+        + "  },\n"
+        + "  \"sint64ToInt32Map\": {\n"
+        + "    \"3234567890123456789\": 30\n"
+        + "  },\n"
+        + "  \"fixed32ToInt32Map\": {\n"
+        + "    \"4\": 40\n"
+        + "  },\n"
+        + "  \"fixed64ToInt32Map\": {\n"
+        + "    \"4234567890123456789\": 40\n"
+        + "  },\n"
+        + "  \"sfixed32ToInt32Map\": {\n"
+        + "    \"5\": 50\n"
+        + "  },\n"
+        + "  \"sfixed64ToInt32Map\": {\n"
+        + "    \"5234567890123456789\": 50\n"
+        + "  },\n"
+        + "  \"boolToInt32Map\": {\n"
+        + "    \"false\": 6\n"
+        + "  },\n"
+        + "  \"stringToInt32Map\": {\n"
+        + "    \"Hello\": 10\n"
+        + "  },\n"
+        + "  \"int32ToInt64Map\": {\n"
+        + "    \"1\": \"1234567890123456789\"\n"
+        + "  },\n"
+        + "  \"int32ToUint32Map\": {\n"
+        + "    \"2\": 20\n"
+        + "  },\n"
+        + "  \"int32ToUint64Map\": {\n"
+        + "    \"2\": \"2234567890123456789\"\n"
+        + "  },\n"
+        + "  \"int32ToSint32Map\": {\n"
+        + "    \"3\": 30\n"
+        + "  },\n"
+        + "  \"int32ToSint64Map\": {\n"
+        + "    \"3\": \"3234567890123456789\"\n"
+        + "  },\n"
+        + "  \"int32ToFixed32Map\": {\n"
+        + "    \"4\": 40\n"
+        + "  },\n"
+        + "  \"int32ToFixed64Map\": {\n"
+        + "    \"4\": \"4234567890123456789\"\n"
+        + "  },\n"
+        + "  \"int32ToSfixed32Map\": {\n"
+        + "    \"5\": 50\n"
+        + "  },\n"
+        + "  \"int32ToSfixed64Map\": {\n"
+        + "    \"5\": \"5234567890123456789\"\n"
+        + "  },\n"
+        + "  \"int32ToFloatMap\": {\n"
+        + "    \"6\": 1.5\n"
+        + "  },\n"
+        + "  \"int32ToDoubleMap\": {\n"
+        + "    \"6\": 1.25\n"
+        + "  },\n"
+        + "  \"int32ToBoolMap\": {\n"
+        + "    \"7\": false\n"
+        + "  },\n"
+        + "  \"int32ToStringMap\": {\n"
+        + "    \"7\": \"World\"\n"
+        + "  },\n"
+        + "  \"int32ToBytesMap\": {\n"
+        + "    \"8\": \"AQID\"\n"
+        + "  },\n"
+        + "  \"int32ToMessageMap\": {\n"
+        + "    \"8\": {\n"
+        + "      \"value\": 1234\n"
+        + "    }\n"
+        + "  },\n"
+        + "  \"int32ToEnumMap\": {\n"
+        + "    \"9\": \"BAR\"\n"
+        + "  }\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+
+    // Test multiple entries.
+    builder = TestMap.newBuilder();
+    builder.getMutableInt32ToInt32Map().put(1, 2);
+    builder.getMutableInt32ToInt32Map().put(3, 4);
+    message = builder.build();
+
+    assertEquals(
+        "{\n"
+        + "  \"int32ToInt32Map\": {\n"
+        + "    \"1\": 2,\n"
+        + "    \"3\": 4\n"
+        + "  }\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testMapNullValueIsRejected() throws Exception {
+    try {
+      TestMap.Builder builder = TestMap.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"int32ToInt32Map\": {null: 1},\n"
+          + "  \"int32ToMessageMap\": {null: 2}\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+
+    try {
+      TestMap.Builder builder = TestMap.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"int32ToInt32Map\": {\"1\": null},\n"
+          + "  \"int32ToMessageMap\": {\"2\": null}\n"
+          + "}", builder);
+      fail();
+    } catch (InvalidProtocolBufferException e) {
+      // Exception expected.
+    }
+  }
+
+  public void testParserAcceptNonQuotedObjectKey() throws Exception {
+    TestMap.Builder builder = TestMap.newBuilder();
+    mergeFromJson(
+        "{\n"
+        + "  int32ToInt32Map: {1: 2},\n"
+        + "  stringToInt32Map: {hello: 3}\n"
+        + "}", builder);
+    TestMap message = builder.build();
+    assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
+    assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
+  }
+
+  public void testWrappers() throws Exception {
+    TestWrappers.Builder builder = TestWrappers.newBuilder();
+    builder.getBoolValueBuilder().setValue(false);
+    builder.getInt32ValueBuilder().setValue(0);
+    builder.getInt64ValueBuilder().setValue(0);
+    builder.getUint32ValueBuilder().setValue(0);
+    builder.getUint64ValueBuilder().setValue(0);
+    builder.getFloatValueBuilder().setValue(0.0f);
+    builder.getDoubleValueBuilder().setValue(0.0);
+    builder.getStringValueBuilder().setValue("");
+    builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
+    TestWrappers message = builder.build();
+
+    assertEquals(
+        "{\n"
+        + "  \"int32Value\": 0,\n"
+        + "  \"uint32Value\": 0,\n"
+        + "  \"int64Value\": \"0\",\n"
+        + "  \"uint64Value\": \"0\",\n"
+        + "  \"floatValue\": 0.0,\n"
+        + "  \"doubleValue\": 0.0,\n"
+        + "  \"boolValue\": false,\n"
+        + "  \"stringValue\": \"\",\n"
+        + "  \"bytesValue\": \"\"\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+
+    builder = TestWrappers.newBuilder();
+    builder.getBoolValueBuilder().setValue(true);
+    builder.getInt32ValueBuilder().setValue(1);
+    builder.getInt64ValueBuilder().setValue(2);
+    builder.getUint32ValueBuilder().setValue(3);
+    builder.getUint64ValueBuilder().setValue(4);
+    builder.getFloatValueBuilder().setValue(5.0f);
+    builder.getDoubleValueBuilder().setValue(6.0);
+    builder.getStringValueBuilder().setValue("7");
+    builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[]{8}));
+    message = builder.build();
+
+    assertEquals(
+        "{\n"
+        + "  \"int32Value\": 1,\n"
+        + "  \"uint32Value\": 3,\n"
+        + "  \"int64Value\": \"2\",\n"
+        + "  \"uint64Value\": \"4\",\n"
+        + "  \"floatValue\": 5.0,\n"
+        + "  \"doubleValue\": 6.0,\n"
+        + "  \"boolValue\": true,\n"
+        + "  \"stringValue\": \"7\",\n"
+        + "  \"bytesValue\": \"CA==\"\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testTimestamp() throws Exception {
+    TestTimestamp message = TestTimestamp.newBuilder()
+        .setTimestampValue(TimeUtil.parseTimestamp("1970-01-01T00:00:00Z"))
+        .build();
+
+    assertEquals(
+        "{\n"
+        + "  \"timestampValue\": \"1970-01-01T00:00:00Z\"\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testDuration() throws Exception {
+    TestDuration message = TestDuration.newBuilder()
+        .setDurationValue(TimeUtil.parseDuration("12345s"))
+        .build();
+
+    assertEquals(
+        "{\n"
+        + "  \"durationValue\": \"12345s\"\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testFieldMask() throws Exception {
+    TestFieldMask message = TestFieldMask.newBuilder()
+        .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz"))
+        .build();
+
+    assertEquals(
+        "{\n"
+        + "  \"fieldMaskValue\": \"foo.bar,baz\"\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testStruct() throws Exception {
+    // Build a struct with all possible values.
+    TestStruct.Builder builder = TestStruct.newBuilder();
+    Struct.Builder structBuilder = builder.getStructValueBuilder();
+    structBuilder.getMutableFields().put(
+        "null_value", Value.newBuilder().setNullValueValue(0).build());
+    structBuilder.getMutableFields().put(
+        "number_value", Value.newBuilder().setNumberValue(1.25).build());
+    structBuilder.getMutableFields().put(
+        "string_value", Value.newBuilder().setStringValue("hello").build());
+    Struct.Builder subStructBuilder = Struct.newBuilder();
+    subStructBuilder.getMutableFields().put(
+        "number_value", Value.newBuilder().setNumberValue(1234).build());
+    structBuilder.getMutableFields().put(
+        "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
+    ListValue.Builder listBuilder = ListValue.newBuilder();
+    listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
+    listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
+    structBuilder.getMutableFields().put(
+        "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
+    TestStruct message = builder.build();
+
+    assertEquals(
+        "{\n"
+        + "  \"structValue\": {\n"
+        + "    \"null_value\": null,\n"
+        + "    \"number_value\": 1.25,\n"
+        + "    \"string_value\": \"hello\",\n"
+        + "    \"struct_value\": {\n"
+        + "      \"number_value\": 1234.0\n"
+        + "    },\n"
+        + "    \"list_value\": [1.125, null]\n"
+        + "  }\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+
+    builder = TestStruct.newBuilder();
+    builder.setValue(Value.newBuilder().setNullValueValue(0).build());
+    message = builder.build();
+    assertEquals(
+        "{\n"
+        + "  \"value\": null\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+
+    builder = TestStruct.newBuilder();
+    listBuilder = builder.getListValueBuilder();
+    listBuilder.addValues(Value.newBuilder().setNumberValue(31831.125).build());
+    listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
+    message = builder.build();
+    assertEquals(
+        "{\n"
+        + "  \"listValue\": [31831.125, null]\n"
+        + "}", toJsonString(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testAnyFields() throws Exception {
+    TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
+    TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
+
+    // A TypeRegistry must be provided in order to convert Any types.
+    try {
+      toJsonString(message);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+
+    JsonFormat.TypeRegistry registry = JsonFormat.TypeRegistry.newBuilder()
+        .add(TestAllTypes.getDescriptor()).build();
+    JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+
+    assertEquals(
+        "{\n"
+        + "  \"anyValue\": {\n"
+        + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+        + "    \"optionalInt32\": 1234\n"
+        + "  }\n"
+        + "}" , printer.print(message));
+    assertRoundTripEquals(message, registry);
+
+
+    // Well-known types have a special formatting when embedded in Any.
+    //
+    // 1. Any in Any.
+    Any anyMessage = Any.pack(Any.pack(content));
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+        + "  \"value\": {\n"
+        + "    \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+        + "    \"optionalInt32\": 1234\n"
+        + "  }\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+
+    // 2. Wrappers in Any.
+    anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
+        + "  \"value\": 12345\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
+        + "  \"value\": 12345\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
+        + "  \"value\": \"12345\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
+        + "  \"value\": \"12345\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
+        + "  \"value\": 12345.0\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
+        + "  \"value\": 12345.0\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
+        + "  \"value\": true\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
+        + "  \"value\": \"Hello\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    anyMessage = Any.pack(BytesValue.newBuilder().setValue(
+        ByteString.copyFrom(new byte[]{1, 2})).build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
+        + "  \"value\": \"AQI=\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+
+    // 3. Timestamp in Any.
+    anyMessage = Any.pack(TimeUtil.parseTimestamp("1969-12-31T23:59:59Z"));
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
+        + "  \"value\": \"1969-12-31T23:59:59Z\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+
+    // 4. Duration in Any
+    anyMessage = Any.pack(TimeUtil.parseDuration("12345.10s"));
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
+        + "  \"value\": \"12345.100s\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+
+    // 5. FieldMask in Any
+    anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
+        + "  \"value\": \"foo.bar,baz\"\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+
+    // 6. Struct in Any
+    Struct.Builder structBuilder = Struct.newBuilder();
+    structBuilder.getMutableFields().put(
+        "number", Value.newBuilder().setNumberValue(1.125).build());
+    anyMessage = Any.pack(structBuilder.build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
+        + "  \"value\": {\n"
+        + "    \"number\": 1.125\n"
+        + "  }\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+    Value.Builder valueBuilder = Value.newBuilder();
+    valueBuilder.setNumberValue(1);
+    anyMessage = Any.pack(valueBuilder.build());
+    assertEquals(
+        "{\n"
+        + "  \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
+        + "  \"value\": 1.0\n"
+        + "}", printer.print(anyMessage));
+    assertRoundTripEquals(anyMessage, registry);
+  }
+
+  public void testParserMissingTypeUrl() throws Exception {
+    try {
+      Any.Builder builder = Any.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"optionalInt32\": 1234\n"
+          + "}", builder);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+  }
+
+  public void testParserUnexpectedTypeUrl() throws Exception {
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+          + "  \"optionalInt32\": 12345\n"
+          + "}", builder);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+  }
+
+  public void testParserRejectTrailingComma() throws Exception {
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"optionalInt32\": 12345,\n"
+          + "}", builder);
+      fail("Exception is expected.");
+    } catch (IOException e) {
+      // Expected.
+    }
+
+    // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
+    // the JsonReader to non-lenient mode. If we want to enforce strict JSON
+    // compliance, we might want to switch to a different JSON parser or
+    // implement one by ourselves.
+    // try {
+    //   TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    //   JsonFormat.merge(
+    //       "{\n"
+    //       + "  \"repeatedInt32\": [12345,]\n"
+    //       + "}", builder);
+    //   fail("Exception is expected.");
+    // } catch (IOException e) {
+    //   // Expected.
+    // }
+  }
+
+  public void testParserRejectInvalidBase64() throws Exception {
+    assertRejects("optionalBytes", "!@#$");
+    // We use standard BASE64 with paddings.
+    assertRejects("optionalBytes", "AQI");
+  }
+
+  public void testParserRejectInvalidEnumValue() throws Exception {
+    try {
+      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+      mergeFromJson(
+          "{\n"
+          + "  \"optionalNestedEnum\": \"XXX\"\n"
+          + "}", builder);
+      fail("Exception is expected.");
+    } catch (InvalidProtocolBufferException e) {
+      // Expected.
+    }
+  }
+
+  public void testCustomJsonName() throws Exception {
+    TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
+    assertEquals("{\n" + "  \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
+    assertRoundTripEquals(message);
+  }
+
+  public void testDefaultGsonDoesNotHtmlEscape() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("=").build();
+    assertEquals(
+        "{\n" + "  \"optionalString\": \"=\"" + "\n}", JsonFormat.printer().print(message));
+  }
+
+  public void testIncludingDefaultValueFields() throws Exception {
+    TestAllTypes message = TestAllTypes.getDefaultInstance();
+    assertEquals("{\n}", JsonFormat.printer().print(message));
+    assertEquals(
+        "{\n"
+            + "  \"optionalInt32\": 0,\n"
+            + "  \"optionalInt64\": \"0\",\n"
+            + "  \"optionalUint32\": 0,\n"
+            + "  \"optionalUint64\": \"0\",\n"
+            + "  \"optionalSint32\": 0,\n"
+            + "  \"optionalSint64\": \"0\",\n"
+            + "  \"optionalFixed32\": 0,\n"
+            + "  \"optionalFixed64\": \"0\",\n"
+            + "  \"optionalSfixed32\": 0,\n"
+            + "  \"optionalSfixed64\": \"0\",\n"
+            + "  \"optionalFloat\": 0.0,\n"
+            + "  \"optionalDouble\": 0.0,\n"
+            + "  \"optionalBool\": false,\n"
+            + "  \"optionalString\": \"\",\n"
+            + "  \"optionalBytes\": \"\",\n"
+            + "  \"optionalNestedEnum\": \"FOO\",\n"
+            + "  \"repeatedInt32\": [],\n"
+            + "  \"repeatedInt64\": [],\n"
+            + "  \"repeatedUint32\": [],\n"
+            + "  \"repeatedUint64\": [],\n"
+            + "  \"repeatedSint32\": [],\n"
+            + "  \"repeatedSint64\": [],\n"
+            + "  \"repeatedFixed32\": [],\n"
+            + "  \"repeatedFixed64\": [],\n"
+            + "  \"repeatedSfixed32\": [],\n"
+            + "  \"repeatedSfixed64\": [],\n"
+            + "  \"repeatedFloat\": [],\n"
+            + "  \"repeatedDouble\": [],\n"
+            + "  \"repeatedBool\": [],\n"
+            + "  \"repeatedString\": [],\n"
+            + "  \"repeatedBytes\": [],\n"
+            + "  \"repeatedNestedMessage\": [],\n"
+            + "  \"repeatedNestedEnum\": []\n"
+            + "}",
+        JsonFormat.printer().includingDefaultValueFields().print(message));
+
+    TestMap mapMessage = TestMap.getDefaultInstance();
+    assertEquals("{\n}", JsonFormat.printer().print(mapMessage));
+    assertEquals(
+        "{\n"
+            + "  \"int32ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"int64ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"uint32ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"uint64ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"sint32ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"sint64ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"fixed32ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"fixed64ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"sfixed32ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"sfixed64ToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"boolToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"stringToInt32Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToInt64Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToUint32Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToUint64Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToSint32Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToSint64Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToFixed32Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToFixed64Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToSfixed32Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToSfixed64Map\": {\n"
+            + "  },\n"
+            + "  \"int32ToFloatMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToDoubleMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToBoolMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToStringMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToBytesMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToMessageMap\": {\n"
+            + "  },\n"
+            + "  \"int32ToEnumMap\": {\n"
+            + "  }\n"
+            + "}",
+        JsonFormat.printer().includingDefaultValueFields().print(mapMessage));
+  }
+
+  public void testPreservingProtoFieldNames() throws Exception {
+    TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
+    assertEquals("{\n" + "  \"optionalInt32\": 12345\n" + "}", JsonFormat.printer().print(message));
+    assertEquals(
+        "{\n" + "  \"optional_int32\": 12345\n" + "}",
+        JsonFormat.printer().preservingProtoFieldNames().print(message));
+
+    // The json_name field option is ignored when configured to use original proto field names.
+    TestCustomJsonName messageWithCustomJsonName =
+        TestCustomJsonName.newBuilder().setValue(12345).build();
+    assertEquals(
+        "{\n" + "  \"value\": 12345\n" + "}",
+        JsonFormat.printer().preservingProtoFieldNames().print(messageWithCustomJsonName));
+
+    // Parsers accept both original proto field names and lowerCamelCase names.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    JsonFormat.parser().merge("{\"optionalInt32\": 12345}", builder);
+    assertEquals(12345, builder.getOptionalInt32());
+    builder.clear();
+    JsonFormat.parser().merge("{\"optional_int32\": 54321}", builder);
+    assertEquals(54321, builder.getOptionalInt32());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
new file mode 100644
index 0000000..4c31b2b
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
@@ -0,0 +1,506 @@
+// 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.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Unit tests for {@link TimeUtil}. */
+public class TimeUtilTest extends TestCase {
+  public void testTimestampStringFormat() throws Exception {
+    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+    assertEquals(TimeUtil.TIMESTAMP_SECONDS_MIN, start.getSeconds());
+    assertEquals(0, start.getNanos());
+    assertEquals(TimeUtil.TIMESTAMP_SECONDS_MAX, end.getSeconds());
+    assertEquals(999999999, end.getNanos());
+    assertEquals("0001-01-01T00:00:00Z", TimeUtil.toString(start));
+    assertEquals("9999-12-31T23:59:59.999999999Z", TimeUtil.toString(end));
+
+    Timestamp value = TimeUtil.parseTimestamp("1970-01-01T00:00:00Z");
+    assertEquals(0, value.getSeconds());
+    assertEquals(0, value.getNanos());
+
+    // Test negative timestamps.
+    value = TimeUtil.parseTimestamp("1969-12-31T23:59:59.999Z");
+    assertEquals(-1, value.getSeconds());
+    // Nano part is in the range of [0, 999999999] for Timestamp.
+    assertEquals(999000000, value.getNanos());
+
+    // Test that 3, 6, or 9 digits are used for the fractional part.
+    value = Timestamp.newBuilder().setNanos(10).build();
+    assertEquals("1970-01-01T00:00:00.000000010Z", TimeUtil.toString(value));
+    value = Timestamp.newBuilder().setNanos(10000).build();
+    assertEquals("1970-01-01T00:00:00.000010Z", TimeUtil.toString(value));
+    value = Timestamp.newBuilder().setNanos(10000000).build();
+    assertEquals("1970-01-01T00:00:00.010Z", TimeUtil.toString(value));
+
+    // Test that parsing accepts timezone offsets.
+    value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010+08:00");
+    assertEquals("1969-12-31T16:00:00.010Z", TimeUtil.toString(value));
+    value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010-08:00");
+    assertEquals("1970-01-01T08:00:00.010Z", TimeUtil.toString(value));
+  }
+
+  private volatile boolean stopParsingThreads = false;
+  private volatile String errorMessage = "";
+
+  private class ParseTimestampThread extends Thread {
+    private final String[] strings;
+    private final Timestamp[] values;
+    public ParseTimestampThread(String[] strings, Timestamp[] values) {
+      this.strings = strings;
+      this.values = values;
+    }
+
+    @Override
+    public void run() {
+      int index = 0;
+      while (!stopParsingThreads) {
+        Timestamp result;
+        try {
+          result = TimeUtil.parseTimestamp(strings[index]);
+        } catch (ParseException e) {
+          errorMessage = "Failed to parse timestamp: " + strings[index];
+          break;
+        }
+        if (result.getSeconds() != values[index].getSeconds()
+            || result.getNanos() != values[index].getNanos()) {
+          errorMessage = "Actual result: " + result.toString() + ", expected: "
+              + values[index].toString();
+          break;
+        }
+        index = (index + 1) % strings.length;
+      }
+    }
+  }
+
+  public void testTimestampConcurrentParsing() throws Exception {
+    String[] timestampStrings = new String[]{
+      "0001-01-01T00:00:00Z",
+      "9999-12-31T23:59:59.999999999Z",
+      "1970-01-01T00:00:00Z",
+      "1969-12-31T23:59:59.999Z",
+    };
+    Timestamp[] timestampValues = new Timestamp[timestampStrings.length];
+    for (int i = 0; i < timestampStrings.length; i++) {
+      timestampValues[i] = TimeUtil.parseTimestamp(timestampStrings[i]);
+    }
+
+    final int THREAD_COUNT = 16;
+    final int RUNNING_TIME = 5000;  // in milliseconds.
+    final List<Thread> threads = new ArrayList<Thread>();
+
+    stopParsingThreads = false;
+    errorMessage = "";
+    for (int i = 0; i < THREAD_COUNT; i++) {
+      Thread thread = new ParseTimestampThread(
+          timestampStrings, timestampValues);
+      thread.start();
+      threads.add(thread);
+    }
+    Thread.sleep(RUNNING_TIME);
+    stopParsingThreads = true;
+    for (Thread thread : threads) {
+      thread.join();
+    }
+    Assert.assertEquals("", errorMessage);
+  }
+
+  public void testTimetampInvalidFormat() throws Exception {
+    try {
+      // Value too small.
+      Timestamp value = Timestamp.newBuilder()
+        .setSeconds(TimeUtil.TIMESTAMP_SECONDS_MIN - 1).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Value too large.
+      Timestamp value = Timestamp.newBuilder()
+        .setSeconds(TimeUtil.TIMESTAMP_SECONDS_MAX + 1).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+    
+    try {
+      // Invalid nanos value.
+      Timestamp value = Timestamp.newBuilder().setNanos(-1).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid nanos value.
+      Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Value to small.
+      TimeUtil.parseTimestamp("0000-01-01T00:00:00Z");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Value to large.
+      TimeUtil.parseTimestamp("10000-01-01T00:00:00Z");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Missing 'T'.
+      TimeUtil.parseTimestamp("1970-01-01 00:00:00Z");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Missing 'Z'.
+      TimeUtil.parseTimestamp("1970-01-01T00:00:00");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid offset.
+      TimeUtil.parseTimestamp("1970-01-01T00:00:00+0000");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Trailing text.
+      TimeUtil.parseTimestamp("1970-01-01T00:00:00Z0");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid nanosecond value.
+      TimeUtil.parseTimestamp("1970-01-01T00:00:00.ABCZ");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+  }
+
+  public void testDurationStringFormat() throws Exception {
+    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+    Duration duration = TimeUtil.distance(start, end);
+    assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+    duration = TimeUtil.distance(end, start);
+    assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+
+    // Generated output should contain 3, 6, or 9 fractional digits.
+    duration = Duration.newBuilder().setSeconds(1).build();
+    assertEquals("1s", TimeUtil.toString(duration));
+    duration = Duration.newBuilder().setNanos(10000000).build();
+    assertEquals("0.010s", TimeUtil.toString(duration));
+    duration = Duration.newBuilder().setNanos(10000).build();
+    assertEquals("0.000010s", TimeUtil.toString(duration));
+    duration = Duration.newBuilder().setNanos(10).build();
+    assertEquals("0.000000010s", TimeUtil.toString(duration));
+
+    // Parsing accepts an fractional digits as long as they fit into nano
+    // precision.
+    duration = TimeUtil.parseDuration("0.1s");
+    assertEquals(100000000, duration.getNanos());
+    duration = TimeUtil.parseDuration("0.0001s");
+    assertEquals(100000, duration.getNanos());
+    duration = TimeUtil.parseDuration("0.0000001s");
+    assertEquals(100, duration.getNanos());
+
+    // Duration must support range from -315,576,000,000s to +315576000000s
+    // which includes negative values.
+    duration = TimeUtil.parseDuration("315576000000.999999999s");
+    assertEquals(315576000000L, duration.getSeconds());
+    assertEquals(999999999, duration.getNanos());
+    duration = TimeUtil.parseDuration("-315576000000.999999999s");
+    assertEquals(-315576000000L, duration.getSeconds());
+    assertEquals(-999999999, duration.getNanos());
+  }
+
+  public void testDurationInvalidFormat() throws Exception {
+    try {
+      // Value too small.
+      Duration value = Duration.newBuilder()
+        .setSeconds(TimeUtil.DURATION_SECONDS_MIN - 1).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Value too large.
+      Duration value = Duration.newBuilder()
+        .setSeconds(TimeUtil.DURATION_SECONDS_MAX + 1).build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+    
+    try {
+      // Invalid nanos value.
+      Duration value = Duration.newBuilder().setSeconds(1).setNanos(-1)
+          .build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid nanos value.
+      Duration value = Duration.newBuilder().setSeconds(-1).setNanos(1)
+          .build();
+      TimeUtil.toString(value);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    try {
+      // Value too small.
+      TimeUtil.parseDuration("-315576000001s");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Value too large.
+      TimeUtil.parseDuration("315576000001s");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Empty.
+      TimeUtil.parseDuration("");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Missing "s".
+      TimeUtil.parseDuration("0");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid trailing data.
+      TimeUtil.parseDuration("0s0");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+
+    try {
+      // Invalid prefix.
+      TimeUtil.parseDuration("--1s");
+      Assert.fail("Exception is expected.");
+    } catch (ParseException e) {
+      // Expected.
+    }
+  }
+
+  public void testTimestampConversion() throws Exception {
+    Timestamp timestamp =
+      TimeUtil.parseTimestamp("1970-01-01T00:00:01.111111111Z");
+    assertEquals(1111111111, TimeUtil.toNanos(timestamp));
+    assertEquals(1111111, TimeUtil.toMicros(timestamp));
+    assertEquals(1111, TimeUtil.toMillis(timestamp));
+    timestamp = TimeUtil.createTimestampFromNanos(1111111111);
+    assertEquals("1970-01-01T00:00:01.111111111Z", TimeUtil.toString(timestamp));
+    timestamp = TimeUtil.createTimestampFromMicros(1111111);
+    assertEquals("1970-01-01T00:00:01.111111Z", TimeUtil.toString(timestamp));
+    timestamp = TimeUtil.createTimestampFromMillis(1111);
+    assertEquals("1970-01-01T00:00:01.111Z", TimeUtil.toString(timestamp));
+    
+    timestamp = TimeUtil.parseTimestamp("1969-12-31T23:59:59.111111111Z");
+    assertEquals(-888888889, TimeUtil.toNanos(timestamp));
+    assertEquals(-888889, TimeUtil.toMicros(timestamp));
+    assertEquals(-889, TimeUtil.toMillis(timestamp));
+    timestamp = TimeUtil.createTimestampFromNanos(-888888889);
+    assertEquals("1969-12-31T23:59:59.111111111Z", TimeUtil.toString(timestamp));
+    timestamp = TimeUtil.createTimestampFromMicros(-888889);
+    assertEquals("1969-12-31T23:59:59.111111Z", TimeUtil.toString(timestamp));
+    timestamp = TimeUtil.createTimestampFromMillis(-889);
+    assertEquals("1969-12-31T23:59:59.111Z", TimeUtil.toString(timestamp));
+  }
+
+  public void testDurationConversion() throws Exception {
+    Duration duration = TimeUtil.parseDuration("1.111111111s");
+    assertEquals(1111111111, TimeUtil.toNanos(duration));
+    assertEquals(1111111, TimeUtil.toMicros(duration));
+    assertEquals(1111, TimeUtil.toMillis(duration));
+    duration = TimeUtil.createDurationFromNanos(1111111111);
+    assertEquals("1.111111111s", TimeUtil.toString(duration));
+    duration = TimeUtil.createDurationFromMicros(1111111);
+    assertEquals("1.111111s", TimeUtil.toString(duration));
+    duration = TimeUtil.createDurationFromMillis(1111);
+    assertEquals("1.111s", TimeUtil.toString(duration));
+    
+    duration = TimeUtil.parseDuration("-1.111111111s");
+    assertEquals(-1111111111, TimeUtil.toNanos(duration));
+    assertEquals(-1111111, TimeUtil.toMicros(duration));
+    assertEquals(-1111, TimeUtil.toMillis(duration));
+    duration = TimeUtil.createDurationFromNanos(-1111111111);
+    assertEquals("-1.111111111s", TimeUtil.toString(duration));
+    duration = TimeUtil.createDurationFromMicros(-1111111);
+    assertEquals("-1.111111s", TimeUtil.toString(duration));
+    duration = TimeUtil.createDurationFromMillis(-1111);
+    assertEquals("-1.111s", TimeUtil.toString(duration));
+  }
+
+  public void testTimeOperations() throws Exception {
+    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+
+    Duration duration = TimeUtil.distance(start, end);
+    assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+    Timestamp value = TimeUtil.add(start, duration);
+    assertEquals(end, value);
+    value = TimeUtil.subtract(end, duration);
+    assertEquals(start, value);
+
+    duration = TimeUtil.distance(end, start);
+    assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+    value = TimeUtil.add(end, duration);
+    assertEquals(start, value);
+    value = TimeUtil.subtract(start, duration);
+    assertEquals(end, value);
+
+    // Result is larger than Long.MAX_VALUE.
+    try {
+      duration = TimeUtil.parseDuration("315537897599.999999999s");
+      duration = TimeUtil.multiply(duration, 315537897599.999999999);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    // Result is lesser than Long.MIN_VALUE.
+    try {
+      duration = TimeUtil.parseDuration("315537897599.999999999s");
+      duration = TimeUtil.multiply(duration, -315537897599.999999999);
+      Assert.fail("Exception is expected.");
+    } catch (IllegalArgumentException e) {
+      // Expected.
+    }
+
+    duration = TimeUtil.parseDuration("-1.125s");
+    duration = TimeUtil.divide(duration, 2.0);
+    assertEquals("-0.562500s", TimeUtil.toString(duration));
+    duration = TimeUtil.multiply(duration, 2.0);
+    assertEquals("-1.125s", TimeUtil.toString(duration));
+
+    duration = TimeUtil.add(duration, duration);
+    assertEquals("-2.250s", TimeUtil.toString(duration));
+    
+    duration = TimeUtil.subtract(duration, TimeUtil.parseDuration("-1s"));
+    assertEquals("-1.250s", TimeUtil.toString(duration));
+    
+    // Multiplications (with results larger than Long.MAX_VALUE in nanoseconds).
+    duration = TimeUtil.parseDuration("0.999999999s");
+    assertEquals("315575999684.424s",
+      TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+    duration = TimeUtil.parseDuration("-0.999999999s");
+    assertEquals("-315575999684.424s",
+      TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+    assertEquals("315575999684.424s",
+      TimeUtil.toString(TimeUtil.multiply(duration, -315576000000L)));
+    
+    // Divisions (with values larger than Long.MAX_VALUE in nanoseconds).
+    Duration d1 = TimeUtil.parseDuration("315576000000s");
+    Duration d2 = TimeUtil.subtract(d1, TimeUtil.createDurationFromNanos(1));
+    assertEquals(1, TimeUtil.divide(d1, d2));
+    assertEquals(0, TimeUtil.divide(d2, d1));
+    assertEquals("0.000000001s", TimeUtil.toString(TimeUtil.remainder(d1, d2)));
+    assertEquals("315575999999.999999999s",
+      TimeUtil.toString(TimeUtil.remainder(d2, d1)));
+    
+    // Divisions involving negative values.
+    //
+    // (-5) / 2 = -2, remainder = -1
+    d1 = TimeUtil.parseDuration("-5s");
+    d2 = TimeUtil.parseDuration("2s");
+    assertEquals(-2, TimeUtil.divide(d1, d2));
+    assertEquals(-2, TimeUtil.divide(d1, 2).getSeconds());
+    assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+    // (-5) / (-2) = 2, remainder = -1
+    d1 = TimeUtil.parseDuration("-5s");
+    d2 = TimeUtil.parseDuration("-2s");
+    assertEquals(2, TimeUtil.divide(d1, d2));
+    assertEquals(2, TimeUtil.divide(d1, -2).getSeconds());
+    assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+    // 5 / (-2) = -2, remainder = 1
+    d1 = TimeUtil.parseDuration("5s");
+    d2 = TimeUtil.parseDuration("-2s");
+    assertEquals(-2, TimeUtil.divide(d1, d2));
+    assertEquals(-2, TimeUtil.divide(d1, -2).getSeconds());
+    assertEquals(1, TimeUtil.remainder(d1, d2).getSeconds());
+  }
+}
diff --git a/src/third_party/protobuf-3/java/util/src/test/proto/com/google/protobuf/util/json_test.proto b/src/third_party/protobuf-3/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
new file mode 100644
index 0000000..686edc4
--- /dev/null
+++ b/src/third_party/protobuf-3/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
@@ -0,0 +1,201 @@
+// 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.
+
+// 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.
+
+syntax = "proto3";
+
+package json_test;
+
+option java_package = "com.google.protobuf.util";
+option java_outer_classname = "JsonTestProto";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
+
+message TestAllTypes {
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+  }
+  message NestedMessage {
+    int32 value = 1;
+  }
+
+  int32 optional_int32 = 1;
+  int64 optional_int64 = 2;
+  uint32 optional_uint32 = 3;
+  uint64 optional_uint64 = 4;
+  sint32 optional_sint32 = 5;
+  sint64 optional_sint64 = 6;
+  fixed32 optional_fixed32 = 7;
+  fixed64 optional_fixed64 = 8;
+  sfixed32 optional_sfixed32 = 9;
+  sfixed64 optional_sfixed64 = 10;
+  float optional_float = 11;
+  double optional_double = 12;
+  bool optional_bool = 13;
+  string optional_string = 14;
+  bytes optional_bytes = 15;
+  NestedMessage optional_nested_message = 18;
+  NestedEnum optional_nested_enum = 21;
+
+  // Repeated
+  repeated int32 repeated_int32 = 31;
+  repeated int64 repeated_int64 = 32;
+  repeated uint32 repeated_uint32 = 33;
+  repeated uint64 repeated_uint64 = 34;
+  repeated sint32 repeated_sint32 = 35;
+  repeated sint64 repeated_sint64 = 36;
+  repeated fixed32 repeated_fixed32 = 37;
+  repeated fixed64 repeated_fixed64 = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated float repeated_float = 41;
+  repeated double repeated_double = 42;
+  repeated bool repeated_bool = 43;
+  repeated string repeated_string = 44;
+  repeated bytes repeated_bytes = 45;
+  repeated NestedMessage repeated_nested_message = 48;
+  repeated NestedEnum repeated_nested_enum = 51;
+}
+
+message TestOneof {
+  oneof oneof_field {
+    int32 oneof_int32 = 1;
+    TestAllTypes.NestedMessage oneof_nested_message = 2;
+  }
+}
+
+message TestMap {
+  // Instead of testing all combinations (too many), we only make sure all
+  // valid types have been used at least in one field as key and in one
+  // field as value.
+  map<int32, int32> int32_to_int32_map = 1;
+  map<int64, int32> int64_to_int32_map = 2;
+  map<uint32, int32> uint32_to_int32_map = 3;
+  map<uint64, int32> uint64_to_int32_map = 4;
+  map<sint32, int32> sint32_to_int32_map = 5;
+  map<sint64, int32> sint64_to_int32_map = 6;
+  map<fixed32, int32> fixed32_to_int32_map = 7;
+  map<fixed64, int32> fixed64_to_int32_map = 8;
+  map<sfixed32, int32> sfixed32_to_int32_map = 9;
+  map<sfixed64, int32> sfixed64_to_int32_map = 10;
+  map<bool, int32> bool_to_int32_map = 11;
+  map<string, int32> string_to_int32_map = 12;
+
+  map<int32, int64> int32_to_int64_map = 101;
+  map<int32, uint32> int32_to_uint32_map = 102;
+  map<int32, uint64> int32_to_uint64_map = 103;
+  map<int32, sint32> int32_to_sint32_map = 104;
+  map<int32, sint64> int32_to_sint64_map = 105;
+  map<int32, fixed32> int32_to_fixed32_map = 106;
+  map<int32, fixed64> int32_to_fixed64_map = 107;
+  map<int32, sfixed32> int32_to_sfixed32_map = 108;
+  map<int32, sfixed64> int32_to_sfixed64_map = 109;
+  map<int32, float> int32_to_float_map = 110;
+  map<int32, double> int32_to_double_map = 111;
+  map<int32, bool> int32_to_bool_map = 112;
+  map<int32, string> int32_to_string_map = 113;
+  map<int32, bytes> int32_to_bytes_map = 114;
+  map<int32, TestAllTypes.NestedMessage> int32_to_message_map = 115;
+  map<int32, TestAllTypes.NestedEnum> int32_to_enum_map = 116;
+}
+
+message TestWrappers {
+  google.protobuf.Int32Value int32_value = 1;
+  google.protobuf.UInt32Value uint32_value = 2;
+  google.protobuf.Int64Value int64_value = 3;
+  google.protobuf.UInt64Value uint64_value = 4;
+  google.protobuf.FloatValue float_value = 5;
+  google.protobuf.DoubleValue double_value = 6;
+  google.protobuf.BoolValue bool_value = 7;
+  google.protobuf.StringValue string_value = 8;
+  google.protobuf.BytesValue bytes_value = 9;
+}
+
+message TestTimestamp {
+  google.protobuf.Timestamp timestamp_value = 1;
+}
+
+message TestDuration {
+  google.protobuf.Duration duration_value = 1;
+}
+
+message TestFieldMask {
+  google.protobuf.FieldMask field_mask_value = 1;
+}
+
+message TestStruct {
+  google.protobuf.Struct struct_value = 1;
+  google.protobuf.Value value = 2;
+  google.protobuf.ListValue list_value = 3;
+}
+
+message TestAny {
+  google.protobuf.Any any_value = 1;
+}
+
+message TestCustomJsonName {
+  int32 value = 1 [json_name = "@value"];
+}
diff --git a/src/third_party/protobuf-3/javanano/README.md b/src/third_party/protobuf-3/javanano/README.md
new file mode 100644
index 0000000..e19b90b
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/README.md
@@ -0,0 +1,398 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the Java Protocol Buffers Nano runtime library.
+
+Installation - With Maven
+-------------------------
+
+The Protocol Buffers build is managed using Maven.  If you would
+rather build without Maven, see below.
+
+1) Install Apache Maven if you don't have it:
+
+     http://maven.apache.org/
+
+2) Build the C++ code, or obtain a binary distribution of protoc.  If
+   you install a binary distribution, make sure that it is the same
+   version as this package.  If in doubt, run:
+
+     $ protoc --version
+
+   You will need to place the protoc executable in ../src.  (If you
+   built it yourself, it should already be there.)
+
+3) Run the tests:
+
+     $ mvn test
+
+   If some tests fail, this library may not work correctly on your
+   system.  Continue at your own risk.
+
+4) Install the library into your Maven repository:
+
+     $ mvn install
+
+5) If you do not use Maven to manage your own build, you can build a
+   .jar file to use:
+
+     $ mvn package
+
+   The .jar will be placed in the "target" directory.
+
+Installation - Without Maven
+----------------------------
+
+If you would rather not install Maven to build the library, you may
+follow these instructions instead.  Note that these instructions skip
+running unit tests.
+
+1) Build the C++ code, or obtain a binary distribution of protoc.  If
+   you install a binary distribution, make sure that it is the same
+   version as this package.  If in doubt, run:
+
+     $ protoc --version
+
+   If you built the C++ code without installing, the compiler binary
+   should be located in ../src.
+
+2) Invoke protoc to build DescriptorProtos.java:
+
+     $ protoc --java_out=src/main/java -I../src \
+         ../src/google/protobuf/descriptor.proto
+
+3) Compile the code in src/main/java using whatever means you prefer.
+
+4) Install the classes wherever you prefer.
+
+Nano version
+------------
+
+JavaNano is a special code generator and runtime library designed specially for
+resource-restricted systems, like Android. It is very resource-friendly in both
+the amount of code and the runtime overhead. Here is an overview of JavaNano
+features compared with the official Java protobuf:
+
+- No descriptors or message builders.
+- All messages are mutable; fields are public Java fields.
+- For optional fields only, encapsulation behind setter/getter/hazzer/
+  clearer functions is opt-in, which provide proper 'has' state support.
+- For proto2, if not opted in, has state (field presence) is not available.
+  Serialization outputs all fields not equal to their defaults
+  (see important implications below).
+  The behavior is consistent with proto3 semantics.
+- Required fields (proto2 only) are always serialized.
+- Enum constants are integers; protection against invalid values only
+  when parsing from the wire.
+- Enum constants can be generated into container interfaces bearing
+  the enum's name (so the referencing code is in Java style).
+- CodedInputByteBufferNano can only take byte[] (not InputStream).
+- Similarly CodedOutputByteBufferNano can only write to byte[].
+- Repeated fields are in arrays, not ArrayList or Vector. Null array
+  elements are allowed and silently ignored.
+- Full support for serializing/deserializing repeated packed fields.
+- Support  extensions (in proto2).
+- Unset messages/groups are null, not an immutable empty default
+  instance.
+- toByteArray(...) and mergeFrom(...) are now static functions of
+  MessageNano.
+- The 'bytes' type translates to the Java type byte[].
+
+The generated messages are not thread-safe for writes, but may be
+used simultaneously from multiple threads in a read-only manner.
+In other words, an appropriate synchronization mechanism (such as
+a ReadWriteLock) must be used to ensure that a message, its
+ancestors, and descendants are not accessed by any other threads
+while the message is being modified. Field reads, getter methods
+(but not getExtension(...)), toByteArray(...), writeTo(...),
+getCachedSize(), and getSerializedSize() are all considered read-only
+operations.
+
+IMPORTANT: If you have fields with defaults and opt out of accessors
+
+How fields with defaults are serialized has changed. Because we don't
+keep "has" state, any field equal to its default is assumed to be not
+set and therefore is not serialized. Consider the situation where we
+change the default value of a field. Senders compiled against an older
+version of the proto continue to match against the old default, and
+don't send values to the receiver even though the receiver assumes the
+new default value. Therefore, think carefully about the implications
+of changing the default value. Alternatively, turn on accessors and
+enjoy the benefit of the explicit has() checks.
+
+IMPORTANT: If you have "bytes" fields with non-empty defaults
+
+Because the byte buffer is now of mutable type byte[], the default
+static final cannot be exposed through a public field. Each time a
+message's constructor or clear() function is called, the default value
+(kept in a private byte[]) is cloned. This causes a small memory
+penalty. This is not a problem if the field has no default or is an
+empty default.
+
+Nano Generator options
+----------------------
+
+```
+java_package           -> <file-name>|<package-name>
+java_outer_classname   -> <file-name>|<package-name>
+java_multiple_files    -> true or false
+java_nano_generate_has -> true or false [DEPRECATED]
+optional_field_style   -> default or accessors
+enum_style             -> c or java
+ignore_services        -> true or false
+parcelable_messages    -> true or false
+generate_intdefs       -> true or false
+```
+
+**java_package=\<file-name\>|\<package-name\>** (no default)
+
+  This allows overriding the 'java_package' option value
+  for the given file from the command line. Use multiple
+  java_package options to override the option for multiple
+  files. The final Java package for each file is the value
+  of this command line option if present, or the value of
+  the same option defined in the file if present, or the
+  proto package if present, or the default Java package.
+
+**java_outer_classname=\<file-name\>|\<outer-classname\>** (no default)
+
+  This allows overriding the 'java_outer_classname' option
+  for the given file from the command line. Use multiple
+  java_outer_classname options to override the option for
+  multiple files. The final Java outer class name for each
+  file is the value of this command line option if present,
+  or the value of the same option defined in the file if
+  present, or the file name converted to CamelCase. This
+  outer class will nest all classes and integer constants
+  generated from file-scope messages and enums.
+
+**java_multiple_files={true,false}** (no default)
+
+  This allows overriding the 'java_multiple_files' option
+  in all source files and their imported files from the
+  command line. The final value of this option for each
+  file is the value defined in this command line option, or
+  the value of the same option defined in the file if
+  present, or false. This specifies whether to generate
+  package-level classes for the file-scope messages in the
+  same Java package as the outer class (instead of nested
+  classes in the outer class). File-scope enum constants
+  are still generated as integer constants in the outer
+  class. This affects the fully qualified references in the
+  Java code. NOTE: because the command line option
+  overrides the value for all files and their imported
+  files, using this option inconsistently may result in
+  incorrect references to the imported messages and enum
+  constants.
+
+**java_nano_generate_has={true,false}** (default: false)
+
+  DEPRECATED. Use optional_field_style=accessors.
+
+  If true, generates a public boolean variable has\<fieldname\>
+  accompanying each optional or required field (not present for
+  repeated fields, groups or messages). It is set to false initially
+  and upon clear(). If parseFrom(...) reads the field from the wire,
+  it is set to true. This is a way for clients to inspect the "has"
+  value upon parse. If it is set to true, writeTo(...) will ALWAYS
+  output that field (even if field value is equal to its
+  default).
+
+  IMPORTANT: This option costs an extra 4 bytes per primitive field in
+  the message. Think carefully about whether you really need this. In
+  many cases reading the default works and determining whether the
+  field was received over the wire is irrelevant.
+
+**optional_field_style={default,accessors,reftypes}** (default: default)
+
+  Defines the style of the generated code for fields.
+
+  * default
+
+  In the default style, optional fields translate into public mutable
+  Java fields, and the serialization process is as discussed in the
+  "IMPORTANT" section above.
+
+  * accessors
+
+  When set to 'accessors', each optional field is encapsulated behind
+  4 accessors, namely get\<fieldname\>(), set\<fieldname\>(), has\<fieldname\>()
+  and clear\<fieldname\>() methods, with the standard semantics. The hazzer's
+  return value determines whether a field is serialized, so this style is
+  useful when you need to serialize a field with the default value, or check
+  if a field has been explicitly set to its default value from the wire.
+
+  In the 'accessors' style, required and nested message fields are still
+  translated to one public mutable Java field each, repeated fields are still
+  translated to arrays. No accessors are generated for them.
+
+  IMPORTANT: When using the 'accessors' style, ProGuard should always
+  be enabled with optimization (don't use -dontoptimize) and allowing
+  access modification (use -allowaccessmodification). This removes the
+  unused accessors and maybe inline the rest at the call sites,
+  reducing the final code size.
+  TODO(maxtroy): find ProGuard config that would work the best.
+
+  * reftypes
+
+  When set to 'reftypes', each proto field is generated as a public Java
+  field. For primitive types, these fields use the Java reference types
+  such as java.lang.Integer instead of primitive types such as int.
+
+  In the 'reftypes' style, fields are initialized to null (or empty
+  arrays for repeated fields), and their default values are not available.
+  They are serialized over the wire based on equality to null.
+
+  The 'reftypes' mode has some additional cost due to autoboxing and usage
+  of reference types. In practice, many boxed types are cached, and so don't
+  result in object creation. However, references do take slightly more memory
+  than primitives.
+
+  The 'reftypes' mode is useful when you want to be able to serialize fields
+  with default values, or check if a field has been explicitly set to the
+  default over the wire without paying the extra method cost of the
+  'accessors' mode.
+
+  Note that if you attempt to write null to a required field in the reftypes
+  mode, serialization of the proto will cause a NullPointerException. This is
+  an intentional indicator that you must set required fields.
+
+  NOTE
+  optional_field_style=accessors or reftypes cannot be used together with
+  java_nano_generate_has=true. If you need the 'has' flag for any
+  required field (you have no reason to), you can only use
+  java_nano_generate_has=true.
+
+**enum_style={c,java}** (default: c)
+
+  Defines where to put the int constants generated from enum members.
+
+  * c
+
+  Use C-style, so the enum constants are available at the scope where
+  the enum is defined. A file-scope enum's members are referenced like
+  'FileOuterClass.ENUM_VALUE'; a message-scope enum's members are
+  referenced as 'Message.ENUM_VALUE'. The enum name is unavailable.
+  This complies with the Micro code generator's behavior.
+
+  * java
+
+  Use Java-style, so the enum constants are available under the enum
+  name and referenced like 'EnumName.ENUM_VALUE' (they are still int
+  constants). The enum name becomes the name of a public interface, at
+  the scope where the enum is defined. If the enum is file-scope and
+  the java_multiple_files option is on, the interface will be defined
+  in its own file. To reduce code size, this interface should not be
+  implemented and ProGuard shrinking should be used, so after the Java
+  compiler inlines all referenced enum constants into the call sites,
+  the interface remains unused and can be removed by ProGuard.
+
+**ignore_services={true,false}** (default: false)
+
+  Skips services definitions.
+
+  Nano doesn't support services. By default, if a service is defined
+  it will generate a compilation error. If this flag is set to true,
+  services will be silently ignored, instead.
+
+**parcelable_messages={true,false}** (default: false)
+
+  Android-specific option to generate Parcelable messages.
+
+**generate_intdefs={true,false}** (default: false)
+  Android-specific option to generate @IntDef annotations for enums.
+
+  If turned on, an '@IntDef' annotation (a public @interface) will be
+  generated for each enum, and every integer parameter and return
+  value in the generated code meant for this enum will be annotated
+  with it. This interface is generated with the same name and at the
+  same place as the enum members' container interfaces described
+  above under 'enum_style=java', regardless of the enum_style option
+  used. When this is combined with enum_style=java, the interface
+  will be both the '@IntDef' annotation and the container of the enum
+  members; otherwise the interface has an empty body.
+
+  Your app must declare a compile-time dependency on the
+  android-support-annotations library.
+
+  For more information on how these @IntDef annotations help with
+  compile-time type safety, see:
+  https://sites.google.com/a/android.com/tools/tech-docs/support-annotations
+  and
+  https://developer.android.com/reference/android/support/annotation/IntDef.html
+
+
+To use nano protobufs within the Android repo:
+----------------------------------------------
+
+- Set 'LOCAL_PROTOC_OPTIMIZE_TYPE := nano' in your local .mk file.
+  When building a Java library or an app (package) target, the build
+  system will add the Java nano runtime library to the
+  LOCAL_STATIC_JAVA_LIBRARIES variable, so you don't need to.
+- Set 'LOCAL_PROTO_JAVA_OUTPUT_PARAMS := ...' in your local .mk file
+  for any command-line options you need. Use commas to join multiple
+  options. In the nano flavor only, whitespace surrounding the option
+  names and values are ignored, so you can use backslash-newline or
+  '+=' to structure your make files nicely.
+- The options will be applied to *all* proto files in LOCAL_SRC_FILES
+  when you build a Java library or package. In case different options
+  are needed for different proto files, build separate Java libraries
+  and reference them in your main target. Note: you should make sure
+  that, for each separate target, all proto files imported from any
+  proto file in LOCAL_SRC_FILES are included in LOCAL_SRC_FILES. This
+  is because the generator has to assume that the imported files are
+  built using the same options, and will generate code that reference
+  the fields and enums from the imported files using the same code
+  style.
+- Hint: 'include $(CLEAR_VARS)' resets all LOCAL_ variables, including
+  the two above.
+
+To use nano protobufs outside of Android repo:
+----------------------------------------------
+
+- Link with the generated jar file
+  \<protobuf-root\>java/target/protobuf-java-2.3.0-nano.jar.
+- Invoke with --javanano_out, e.g.:
+```
+./protoc '--javanano_out=\
+    java_package=src/proto/simple-data.proto|my_package,\
+    java_outer_classname=src/proto/simple-data.proto|OuterName\
+  :.' src/proto/simple-data.proto
+```
+
+Contributing to nano:
+---------------------
+
+Please add/edit tests in NanoTest.java.
+
+Please run the following steps to test:
+
+- cd external/protobuf
+- ./configure
+- Run "make -j12 check" and verify all tests pass.
+- cd java
+- Run "mvn test" and verify all tests pass.
+- cd ../../..
+- . build/envsetup.sh
+- lunch 1
+- "make -j12 aprotoc libprotobuf-java-2.3.0-nano aprotoc-test-nano-params NanoAndroidTest" and
+  check for build errors.
+- Plug in an Android device or start an emulator.
+- adb install -r out/target/product/generic/data/app/NanoAndroidTest.apk
+- Run:
+  "adb shell am instrument -w com.google.protobuf.nano.test/android.test.InstrumentationTestRunner"
+  and verify all tests pass.
+- repo sync -c -j256
+- "make -j12" and check for build errors
+
+Usage
+-----
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+    https://developers.google.com/protocol-buffers/
diff --git a/src/third_party/protobuf-3/javanano/pom.xml b/src/third_party/protobuf-3/javanano/pom.xml
new file mode 100644
index 0000000..a2eca09
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/pom.xml
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google</groupId>
+    <artifactId>google</artifactId>
+    <version>1</version>
+  </parent>
+  <groupId>com.google.protobuf.nano</groupId>
+  <artifactId>protobuf-javanano</artifactId>
+  <version>3.0.0-alpha-6</version>
+  <packaging>bundle</packaging>
+  <name>Protocol Buffer JavaNano API</name>
+  <description>
+    Protocol Buffers are a way of encoding structured data in an efficient yet
+    extensible format.
+  </description>
+  <inceptionYear>2008</inceptionYear>
+  <url>https://developers.google.com/protocol-buffers/</url>
+  <licenses>
+    <license>
+      <name>New BSD license</name>
+      <url>http://www.opensource.org/licenses/bsd-license.php</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <url>https://github.com/google/protobuf</url>
+    <connection>
+      scm:git:https://github.com/google/protobuf.git
+    </connection>
+  </scm>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.4</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>2.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+      <version>2.2.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>**/*Test.java</include>
+          </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <tasks>
+                <mkdir dir="target/generated-test-sources" />
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=generate_equals=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_import_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_single_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/map_test.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=store_unknown_fields=true,generate_equals=true,generate_clone=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=store_unknown_fields=true,generate_clone=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true,generate_clone=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_has_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=optional_field_style=accessors,generate_equals=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=enum_style=java:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=
+                                  optional_field_style=accessors,
+                                  java_outer_classname=google/protobuf/nano/unittest_enum_validity_nano.proto|EnumValidityAccessors
+                                :target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=optional_field_style=reftypes,generate_equals=true:target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
+                </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=
+                                  optional_field_style=reftypes_compat_mode,
+                                  generate_equals=true,
+                                  java_outer_classname=google/protobuf/nano/unittest_reference_types_nano.proto|NanoReferenceTypesCompat
+                                  :target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
+                </exec>
+              </tasks>
+              <testSourceRoot>target/generated-test-sources</testSourceRoot>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+            <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
+            <Export-Package>com.google.protobuf;version=3.0.0-alpha-5</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>release</id>
+      <distributionManagement>
+        <snapshotRepository>
+          <id>sonatype-nexus-staging</id>
+          <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+        <repository>
+          <id>sonatype-nexus-staging</id>
+          <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+        </repository>
+      </distributionManagement>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <version>2.2.1</version>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar-no-fork</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.9.1</version>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.5</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>nexus-staging-maven-plugin</artifactId>
+            <version>1.6.3</version>
+            <extensions>true</extensions>
+            <configuration>
+               <serverId>sonatype-nexus-staging</serverId>
+               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+               <autoReleaseAfterClose>false</autoReleaseAfterClose>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
new file mode 100644
index 0000000..f399315
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
@@ -0,0 +1,683 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+
+/**
+ * Reads and decodes protocol message fields.
+ *
+ * This class contains two kinds of methods:  methods that read specific
+ * protocol message constructs and field types (e.g. {@link #readTag()} and
+ * {@link #readInt32()}) and methods that read low-level values (e.g.
+ * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
+ * encoded protocol messages, you should use the former methods, but if you are
+ * reading some other format of your own design, use the latter.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class CodedInputByteBufferNano {
+  /**
+   * Create a new CodedInputStream wrapping the given byte array.
+   */
+  public static CodedInputByteBufferNano newInstance(final byte[] buf) {
+    return newInstance(buf, 0, buf.length);
+  }
+
+  /**
+   * Create a new CodedInputStream wrapping the given byte array slice.
+   */
+  public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off,
+                                             final int len) {
+    return new CodedInputByteBufferNano(buf, off, len);
+  }
+
+  // -----------------------------------------------------------------
+
+  /**
+   * Attempt to read a field tag, returning zero if we have reached EOF.
+   * Protocol message parsers use this to read tags, since a protocol message
+   * may legally end wherever a tag occurs, and zero is not a valid tag number.
+   */
+  public int readTag() throws IOException {
+    if (isAtEnd()) {
+      lastTag = 0;
+      return 0;
+    }
+
+    lastTag = readRawVarint32();
+    if (lastTag == 0) {
+      // If we actually read zero, that's not a valid tag.
+      throw InvalidProtocolBufferNanoException.invalidTag();
+    }
+    return lastTag;
+  }
+
+  /**
+   * Verifies that the last call to readTag() returned the given tag value.
+   * This is used to verify that a nested group ended with the correct
+   * end tag.
+   *
+   * @throws InvalidProtocolBufferNanoException {@code value} does not match the
+   *                                        last tag.
+   */
+  public void checkLastTagWas(final int value)
+                              throws InvalidProtocolBufferNanoException {
+    if (lastTag != value) {
+      throw InvalidProtocolBufferNanoException.invalidEndTag();
+    }
+  }
+
+  /**
+   * Reads and discards a single field, given its tag value.
+   *
+   * @return {@code false} if the tag is an endgroup tag, in which case
+   *         nothing is skipped.  Otherwise, returns {@code true}.
+   */
+  public boolean skipField(final int tag) throws IOException {
+    switch (WireFormatNano.getTagWireType(tag)) {
+      case WireFormatNano.WIRETYPE_VARINT:
+        readInt32();
+        return true;
+      case WireFormatNano.WIRETYPE_FIXED64:
+        readRawLittleEndian64();
+        return true;
+      case WireFormatNano.WIRETYPE_LENGTH_DELIMITED:
+        skipRawBytes(readRawVarint32());
+        return true;
+      case WireFormatNano.WIRETYPE_START_GROUP:
+        skipMessage();
+        checkLastTagWas(
+          WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag),
+                             WireFormatNano.WIRETYPE_END_GROUP));
+        return true;
+      case WireFormatNano.WIRETYPE_END_GROUP:
+        return false;
+      case WireFormatNano.WIRETYPE_FIXED32:
+        readRawLittleEndian32();
+        return true;
+      default:
+        throw InvalidProtocolBufferNanoException.invalidWireType();
+    }
+  }
+
+  /**
+   * Reads and discards an entire message.  This will read either until EOF
+   * or until an endgroup tag, whichever comes first.
+   */
+  public void skipMessage() throws IOException {
+    while (true) {
+      final int tag = readTag();
+      if (tag == 0 || !skipField(tag)) {
+        return;
+      }
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  /** Read a {@code double} field value from the stream. */
+  public double readDouble() throws IOException {
+    return Double.longBitsToDouble(readRawLittleEndian64());
+  }
+
+  /** Read a {@code float} field value from the stream. */
+  public float readFloat() throws IOException {
+    return Float.intBitsToFloat(readRawLittleEndian32());
+  }
+
+  /** Read a {@code uint64} field value from the stream. */
+  public long readUInt64() throws IOException {
+    return readRawVarint64();
+  }
+
+  /** Read an {@code int64} field value from the stream. */
+  public long readInt64() throws IOException {
+    return readRawVarint64();
+  }
+
+  /** Read an {@code int32} field value from the stream. */
+  public int readInt32() throws IOException {
+    return readRawVarint32();
+  }
+
+  /** Read a {@code fixed64} field value from the stream. */
+  public long readFixed64() throws IOException {
+    return readRawLittleEndian64();
+  }
+
+  /** Read a {@code fixed32} field value from the stream. */
+  public int readFixed32() throws IOException {
+    return readRawLittleEndian32();
+  }
+
+  /** Read a {@code bool} field value from the stream. */
+  public boolean readBool() throws IOException {
+    return readRawVarint32() != 0;
+  }
+
+  /** Read a {@code string} field value from the stream. */
+  public String readString() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path:  We already have the bytes in a contiguous buffer, so
+      //   just copy directly from it.
+      final String result = new String(buffer, bufferPos, size, InternalNano.UTF_8);
+      bufferPos += size;
+      return result;
+    } else {
+      // Slow path:  Build a byte array first then copy it.
+      return new String(readRawBytes(size), InternalNano.UTF_8);
+    }
+  }
+
+  /** Read a {@code group} field value from the stream. */
+  public void readGroup(final MessageNano msg, final int fieldNumber)
+      throws IOException {
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
+    }
+    ++recursionDepth;
+    msg.mergeFrom(this);
+    checkLastTagWas(
+      WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP));
+    --recursionDepth;
+  }
+
+  public void readMessage(final MessageNano msg)
+      throws IOException {
+    final int length = readRawVarint32();
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
+    }
+    final int oldLimit = pushLimit(length);
+    ++recursionDepth;
+    msg.mergeFrom(this);
+    checkLastTagWas(0);
+    --recursionDepth;
+    popLimit(oldLimit);
+  }
+
+  /** Read a {@code bytes} field value from the stream. */
+  public byte[] readBytes() throws IOException {
+    final int size = readRawVarint32();
+    if (size <= (bufferSize - bufferPos) && size > 0) {
+      // Fast path:  We already have the bytes in a contiguous buffer, so
+      //   just copy directly from it.
+      final byte[] result = new byte[size];
+      System.arraycopy(buffer, bufferPos, result, 0, size);
+      bufferPos += size;
+      return result;
+    } else if (size == 0) {
+      return WireFormatNano.EMPTY_BYTES;
+    } else {
+      // Slow path:  Build a byte array first then copy it.
+      return readRawBytes(size);
+    }
+  }
+
+  /** Read a {@code uint32} field value from the stream. */
+  public int readUInt32() throws IOException {
+    return readRawVarint32();
+  }
+
+  /**
+   * Read an enum field value from the stream.  Caller is responsible
+   * for converting the numeric value to an actual enum.
+   */
+  public int readEnum() throws IOException {
+    return readRawVarint32();
+  }
+
+  /** Read an {@code sfixed32} field value from the stream. */
+  public int readSFixed32() throws IOException {
+    return readRawLittleEndian32();
+  }
+
+  /** Read an {@code sfixed64} field value from the stream. */
+  public long readSFixed64() throws IOException {
+    return readRawLittleEndian64();
+  }
+
+  /** Read an {@code sint32} field value from the stream. */
+  public int readSInt32() throws IOException {
+    return decodeZigZag32(readRawVarint32());
+  }
+
+  /** Read an {@code sint64} field value from the stream. */
+  public long readSInt64() throws IOException {
+    return decodeZigZag64(readRawVarint64());
+  }
+
+  // =================================================================
+
+  /**
+   * Read a raw Varint from the stream.  If larger than 32 bits, discard the
+   * upper bits.
+   */
+  public int readRawVarint32() throws IOException {
+    byte tmp = readRawByte();
+    if (tmp >= 0) {
+      return tmp;
+    }
+    int result = tmp & 0x7f;
+    if ((tmp = readRawByte()) >= 0) {
+      result |= tmp << 7;
+    } else {
+      result |= (tmp & 0x7f) << 7;
+      if ((tmp = readRawByte()) >= 0) {
+        result |= tmp << 14;
+      } else {
+        result |= (tmp & 0x7f) << 14;
+        if ((tmp = readRawByte()) >= 0) {
+          result |= tmp << 21;
+        } else {
+          result |= (tmp & 0x7f) << 21;
+          result |= (tmp = readRawByte()) << 28;
+          if (tmp < 0) {
+            // Discard upper 32 bits.
+            for (int i = 0; i < 5; i++) {
+              if (readRawByte() >= 0) {
+                return result;
+              }
+            }
+            throw InvalidProtocolBufferNanoException.malformedVarint();
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /** Read a raw Varint from the stream. */
+  public long readRawVarint64() throws IOException {
+    int shift = 0;
+    long result = 0;
+    while (shift < 64) {
+      final byte b = readRawByte();
+      result |= (long)(b & 0x7F) << shift;
+      if ((b & 0x80) == 0) {
+        return result;
+      }
+      shift += 7;
+    }
+    throw InvalidProtocolBufferNanoException.malformedVarint();
+  }
+
+  /** Read a 32-bit little-endian integer from the stream. */
+  public int readRawLittleEndian32() throws IOException {
+    final byte b1 = readRawByte();
+    final byte b2 = readRawByte();
+    final byte b3 = readRawByte();
+    final byte b4 = readRawByte();
+    return ((b1 & 0xff)      ) |
+           ((b2 & 0xff) <<  8) |
+           ((b3 & 0xff) << 16) |
+           ((b4 & 0xff) << 24);
+  }
+
+  /** Read a 64-bit little-endian integer from the stream. */
+  public long readRawLittleEndian64() throws IOException {
+    final byte b1 = readRawByte();
+    final byte b2 = readRawByte();
+    final byte b3 = readRawByte();
+    final byte b4 = readRawByte();
+    final byte b5 = readRawByte();
+    final byte b6 = readRawByte();
+    final byte b7 = readRawByte();
+    final byte b8 = readRawByte();
+    return (((long)b1 & 0xff)      ) |
+           (((long)b2 & 0xff) <<  8) |
+           (((long)b3 & 0xff) << 16) |
+           (((long)b4 & 0xff) << 24) |
+           (((long)b5 & 0xff) << 32) |
+           (((long)b6 & 0xff) << 40) |
+           (((long)b7 & 0xff) << 48) |
+           (((long)b8 & 0xff) << 56);
+  }
+
+  /**
+   * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n An unsigned 32-bit integer, stored in a signed int because
+   *          Java has no explicit unsigned support.
+   * @return A signed 32-bit integer.
+   */
+  public static int decodeZigZag32(final int n) {
+    return (n >>> 1) ^ -(n & 1);
+  }
+
+  /**
+   * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n An unsigned 64-bit integer, stored in a signed int because
+   *          Java has no explicit unsigned support.
+   * @return A signed 64-bit integer.
+   */
+  public static long decodeZigZag64(final long n) {
+    return (n >>> 1) ^ -(n & 1);
+  }
+
+  // -----------------------------------------------------------------
+
+  private final byte[] buffer;
+  private int bufferStart;
+  private int bufferSize;
+  private int bufferSizeAfterLimit;
+  private int bufferPos;
+  private int lastTag;
+
+  /** The absolute position of the end of the current message. */
+  private int currentLimit = Integer.MAX_VALUE;
+
+  /** See setRecursionLimit() */
+  private int recursionDepth;
+  private int recursionLimit = DEFAULT_RECURSION_LIMIT;
+
+  /** See setSizeLimit() */
+  private int sizeLimit = DEFAULT_SIZE_LIMIT;
+
+  private static final int DEFAULT_RECURSION_LIMIT = 64;
+  private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
+
+  private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) {
+    this.buffer = buffer;
+    bufferStart = off;
+    bufferSize = off + len;
+    bufferPos = off;
+  }
+
+  /**
+   * Set the maximum message recursion depth.  In order to prevent malicious
+   * messages from causing stack overflows, {@code CodedInputStream} limits
+   * how deeply messages may be nested.  The default limit is 64.
+   *
+   * @return the old limit.
+   */
+  public int setRecursionLimit(final int limit) {
+    if (limit < 0) {
+      throw new IllegalArgumentException(
+        "Recursion limit cannot be negative: " + limit);
+    }
+    final int oldLimit = recursionLimit;
+    recursionLimit = limit;
+    return oldLimit;
+  }
+
+  /**
+   * Set the maximum message size.  In order to prevent malicious
+   * messages from exhausting memory or causing integer overflows,
+   * {@code CodedInputStream} limits how large a message may be.
+   * The default limit is 64MB.  You should set this limit as small
+   * as you can without harming your app's functionality.  Note that
+   * size limits only apply when reading from an {@code InputStream}, not
+   * when constructed around a raw byte array.
+   * <p>
+   * If you want to read several messages from a single CodedInputStream, you
+   * could call {@link #resetSizeCounter()} after each one to avoid hitting the
+   * size limit.
+   *
+   * @return the old limit.
+   */
+  public int setSizeLimit(final int limit) {
+    if (limit < 0) {
+      throw new IllegalArgumentException(
+        "Size limit cannot be negative: " + limit);
+    }
+    final int oldLimit = sizeLimit;
+    sizeLimit = limit;
+    return oldLimit;
+  }
+
+  /**
+   * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
+   */
+  public void resetSizeCounter() {
+  }
+
+  /**
+   * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
+   * is called when descending into a length-delimited embedded message.
+   *
+   * @return the old limit.
+   */
+  public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException {
+    if (byteLimit < 0) {
+      throw InvalidProtocolBufferNanoException.negativeSize();
+    }
+    byteLimit += bufferPos;
+    final int oldLimit = currentLimit;
+    if (byteLimit > oldLimit) {
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+    currentLimit = byteLimit;
+
+    recomputeBufferSizeAfterLimit();
+
+    return oldLimit;
+  }
+
+  private void recomputeBufferSizeAfterLimit() {
+    bufferSize += bufferSizeAfterLimit;
+    final int bufferEnd = bufferSize;
+    if (bufferEnd > currentLimit) {
+      // Limit is in current buffer.
+      bufferSizeAfterLimit = bufferEnd - currentLimit;
+      bufferSize -= bufferSizeAfterLimit;
+    } else {
+      bufferSizeAfterLimit = 0;
+    }
+  }
+
+  /**
+   * Discards the current limit, returning to the previous limit.
+   *
+   * @param oldLimit The old limit, as returned by {@code pushLimit}.
+   */
+  public void popLimit(final int oldLimit) {
+    currentLimit = oldLimit;
+    recomputeBufferSizeAfterLimit();
+  }
+
+  /**
+   * Returns the number of bytes to be read before the current limit.
+   * If no limit is set, returns -1.
+   */
+  public int getBytesUntilLimit() {
+    if (currentLimit == Integer.MAX_VALUE) {
+      return -1;
+    }
+
+    final int currentAbsolutePosition = bufferPos;
+    return currentLimit - currentAbsolutePosition;
+  }
+
+  /**
+   * Returns true if the stream has reached the end of the input.  This is the
+   * case if either the end of the underlying input source has been reached or
+   * if the stream has reached a limit created using {@link #pushLimit(int)}.
+   */
+  public boolean isAtEnd() {
+    return bufferPos == bufferSize;
+  }
+
+  /**
+   * Get current position in buffer relative to beginning offset.
+   */
+  public int getPosition() {
+    return bufferPos - bufferStart;
+  }
+
+  /**
+   * Retrieves a subset of data in the buffer. The returned array is not backed by the original
+   * buffer array.
+   *
+   * @param offset the position (relative to the buffer start position) to start at.
+   * @param length the number of bytes to retrieve.
+   */
+  public byte[] getData(int offset, int length) {
+    if (length == 0) {
+      return WireFormatNano.EMPTY_BYTES;
+    }
+    byte[] copy = new byte[length];
+    int start = bufferStart + offset;
+    System.arraycopy(buffer, start, copy, 0, length);
+    return copy;
+  }
+
+  /**
+   * Rewind to previous position. Cannot go forward.
+   */
+  public void rewindToPosition(int position) {
+    if (position > bufferPos - bufferStart) {
+      throw new IllegalArgumentException(
+              "Position " + position + " is beyond current " + (bufferPos - bufferStart));
+    }
+    if (position < 0) {
+      throw new IllegalArgumentException("Bad position " + position);
+    }
+    bufferPos = bufferStart + position;
+  }
+
+  /**
+   * Read one byte from the input.
+   *
+   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public byte readRawByte() throws IOException {
+    if (bufferPos == bufferSize) {
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+    return buffer[bufferPos++];
+  }
+
+  /**
+   * Read a fixed size of bytes from the input.
+   *
+   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public byte[] readRawBytes(final int size) throws IOException {
+    if (size < 0) {
+      throw InvalidProtocolBufferNanoException.negativeSize();
+    }
+
+    if (bufferPos + size > currentLimit) {
+      // Read to the end of the stream anyway.
+      skipRawBytes(currentLimit - bufferPos);
+      // Then fail.
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+
+    if (size <= bufferSize - bufferPos) {
+      // We have all the bytes we need already.
+      final byte[] bytes = new byte[size];
+      System.arraycopy(buffer, bufferPos, bytes, 0, size);
+      bufferPos += size;
+      return bytes;
+    } else {
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+  }
+
+  /**
+   * Reads and discards {@code size} bytes.
+   *
+   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+   *                                        limit was reached.
+   */
+  public void skipRawBytes(final int size) throws IOException {
+    if (size < 0) {
+      throw InvalidProtocolBufferNanoException.negativeSize();
+    }
+
+    if (bufferPos + size > currentLimit) {
+      // Read to the end of the stream anyway.
+      skipRawBytes(currentLimit - bufferPos);
+      // Then fail.
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+
+    if (size <= bufferSize - bufferPos) {
+      // We have all the bytes we need already.
+      bufferPos += size;
+    } else {
+      throw InvalidProtocolBufferNanoException.truncatedMessage();
+    }
+  }
+
+  // Read a primitive type.
+  Object readPrimitiveField(int type) throws IOException {
+    switch (type) {
+      case InternalNano.TYPE_DOUBLE:
+          return readDouble();
+      case InternalNano.TYPE_FLOAT:
+          return readFloat();
+      case InternalNano.TYPE_INT64:
+          return readInt64();
+      case InternalNano.TYPE_UINT64:
+          return readUInt64();
+      case InternalNano.TYPE_INT32:
+          return readInt32();
+      case InternalNano.TYPE_FIXED64:
+          return readFixed64();
+      case InternalNano.TYPE_FIXED32:
+          return readFixed32();
+      case InternalNano.TYPE_BOOL:
+          return readBool();
+      case InternalNano.TYPE_STRING:
+          return readString();
+      case InternalNano.TYPE_BYTES:
+          return readBytes();
+      case InternalNano.TYPE_UINT32:
+          return readUInt32();
+      case InternalNano.TYPE_ENUM:
+          return readEnum();
+      case InternalNano.TYPE_SFIXED32:
+          return readSFixed32();
+      case InternalNano.TYPE_SFIXED64:
+          return readSFixed64();
+      case InternalNano.TYPE_SINT32:
+          return readSInt32();
+      case InternalNano.TYPE_SINT64:
+          return readSInt64();
+      default:
+          throw new IllegalArgumentException("Unknown type " + type);
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
new file mode 100644
index 0000000..322ada8
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -0,0 +1,1214 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.ReadOnlyBufferException;
+
+/**
+ * Encodes and writes protocol message fields.
+ *
+ * <p>This class contains two kinds of methods:  methods that write specific
+ * protocol message constructs and field types (e.g. {@link #writeTag} and
+ * {@link #writeInt32}) and methods that write low-level values (e.g.
+ * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
+ * writing encoded protocol messages, you should use the former methods, but if
+ * you are writing some other format of your own design, use the latter.
+ *
+ * <p>This class is totally unsynchronized.
+ *
+ * @author kneton@google.com Kenton Varda
+ */
+public final class CodedOutputByteBufferNano {
+  /* max bytes per java UTF-16 char in UTF-8 */
+  private static final int MAX_UTF8_EXPANSION = 3;
+  private final ByteBuffer buffer;
+
+  private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
+                            final int length) {
+    this(ByteBuffer.wrap(buffer, offset, length));
+  }
+
+  private CodedOutputByteBufferNano(final ByteBuffer buffer) {
+    this.buffer = buffer;
+    this.buffer.order(ByteOrder.LITTLE_ENDIAN);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes directly to the given
+   * byte array.  If more bytes are written than fit in the array,
+   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
+   * array is faster than writing to an {@code OutputStream}.
+   */
+  public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) {
+    return newInstance(flatArray, 0, flatArray.length);
+  }
+
+  /**
+   * Create a new {@code CodedOutputStream} that writes directly to the given
+   * byte array slice.  If more bytes are written than fit in the slice,
+   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
+   * array is faster than writing to an {@code OutputStream}.
+   */
+  public static CodedOutputByteBufferNano newInstance(final byte[] flatArray,
+                                              final int offset,
+                                              final int length) {
+    return new CodedOutputByteBufferNano(flatArray, offset, length);
+  }
+
+  // -----------------------------------------------------------------
+
+  /** Write a {@code double} field, including tag, to the stream. */
+  public void writeDouble(final int fieldNumber, final double value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+    writeDoubleNoTag(value);
+  }
+
+  /** Write a {@code float} field, including tag, to the stream. */
+  public void writeFloat(final int fieldNumber, final float value)
+                         throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+    writeFloatNoTag(value);
+  }
+
+  /** Write a {@code uint64} field, including tag, to the stream. */
+  public void writeUInt64(final int fieldNumber, final long value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeUInt64NoTag(value);
+  }
+
+  /** Write an {@code int64} field, including tag, to the stream. */
+  public void writeInt64(final int fieldNumber, final long value)
+                         throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeInt64NoTag(value);
+  }
+
+  /** Write an {@code int32} field, including tag, to the stream. */
+  public void writeInt32(final int fieldNumber, final int value)
+                         throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeInt32NoTag(value);
+  }
+
+  /** Write a {@code fixed64} field, including tag, to the stream. */
+  public void writeFixed64(final int fieldNumber, final long value)
+                           throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+    writeFixed64NoTag(value);
+  }
+
+  /** Write a {@code fixed32} field, including tag, to the stream. */
+  public void writeFixed32(final int fieldNumber, final int value)
+                           throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+    writeFixed32NoTag(value);
+  }
+
+  /** Write a {@code bool} field, including tag, to the stream. */
+  public void writeBool(final int fieldNumber, final boolean value)
+                        throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeBoolNoTag(value);
+  }
+
+  /** Write a {@code string} field, including tag, to the stream. */
+  public void writeString(final int fieldNumber, final String value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    writeStringNoTag(value);
+  }
+
+  /** Write a {@code group} field, including tag, to the stream. */
+  public void writeGroup(final int fieldNumber, final MessageNano value)
+                         throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP);
+    writeGroupNoTag(value);
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
+  }
+
+  /** Write an embedded message field, including tag, to the stream. */
+  public void writeMessage(final int fieldNumber, final MessageNano value)
+                           throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    writeMessageNoTag(value);
+  }
+
+  /** Write a {@code bytes} field, including tag, to the stream. */
+  public void writeBytes(final int fieldNumber, final byte[] value)
+                         throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    writeBytesNoTag(value);
+  }
+
+  /** Write a {@code uint32} field, including tag, to the stream. */
+  public void writeUInt32(final int fieldNumber, final int value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeUInt32NoTag(value);
+  }
+
+  /**
+   * Write an enum field, including tag, to the stream.  Caller is responsible
+   * for converting the enum value to its numeric value.
+   */
+  public void writeEnum(final int fieldNumber, final int value)
+                        throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeEnumNoTag(value);
+  }
+
+  /** Write an {@code sfixed32} field, including tag, to the stream. */
+  public void writeSFixed32(final int fieldNumber, final int value)
+                            throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+    writeSFixed32NoTag(value);
+  }
+
+  /** Write an {@code sfixed64} field, including tag, to the stream. */
+  public void writeSFixed64(final int fieldNumber, final long value)
+                            throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+    writeSFixed64NoTag(value);
+  }
+
+  /** Write an {@code sint32} field, including tag, to the stream. */
+  public void writeSInt32(final int fieldNumber, final int value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeSInt32NoTag(value);
+  }
+
+  /** Write an {@code sint64} field, including tag, to the stream. */
+  public void writeSInt64(final int fieldNumber, final long value)
+                          throws IOException {
+    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+    writeSInt64NoTag(value);
+  }
+
+  /**
+   * Write a MessageSet extension field to the stream.  For historical reasons,
+   * the wire format differs from normal fields.
+   */
+//  public void writeMessageSetExtension(final int fieldNumber,
+//                                       final MessageMicro value)
+//                                       throws IOException {
+//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
+//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
+//    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
+//  }
+
+  /**
+   * Write an unparsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+//  public void writeRawMessageSetExtension(final int fieldNumber,
+//                                          final ByteStringMicro value)
+//                                          throws IOException {
+//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
+//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
+//    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
+//  }
+
+  // -----------------------------------------------------------------
+
+  /** Write a {@code double} field to the stream. */
+  public void writeDoubleNoTag(final double value) throws IOException {
+    writeRawLittleEndian64(Double.doubleToLongBits(value));
+  }
+
+  /** Write a {@code float} field to the stream. */
+  public void writeFloatNoTag(final float value) throws IOException {
+    writeRawLittleEndian32(Float.floatToIntBits(value));
+  }
+
+  /** Write a {@code uint64} field to the stream. */
+  public void writeUInt64NoTag(final long value) throws IOException {
+    writeRawVarint64(value);
+  }
+
+  /** Write an {@code int64} field to the stream. */
+  public void writeInt64NoTag(final long value) throws IOException {
+    writeRawVarint64(value);
+  }
+
+  /** Write an {@code int32} field to the stream. */
+  public void writeInt32NoTag(final int value) throws IOException {
+    if (value >= 0) {
+      writeRawVarint32(value);
+    } else {
+      // Must sign-extend.
+      writeRawVarint64(value);
+    }
+  }
+
+  /** Write a {@code fixed64} field to the stream. */
+  public void writeFixed64NoTag(final long value) throws IOException {
+    writeRawLittleEndian64(value);
+  }
+
+  /** Write a {@code fixed32} field to the stream. */
+  public void writeFixed32NoTag(final int value) throws IOException {
+    writeRawLittleEndian32(value);
+  }
+
+  /** Write a {@code bool} field to the stream. */
+  public void writeBoolNoTag(final boolean value) throws IOException {
+    writeRawByte(value ? 1 : 0);
+  }
+
+  /** Write a {@code string} field to the stream. */
+  public void writeStringNoTag(final String value) throws IOException {
+    // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+    // and at most 3 times of it. Optimize for the case where we know this length results in a
+    // constant varint length - saves measuring length of the string.
+    try {
+      final int minLengthVarIntSize = computeRawVarint32Size(value.length());
+      final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION);
+      if (minLengthVarIntSize == maxLengthVarIntSize) {
+        int oldPosition = buffer.position();
+        // Buffer.position, when passed a position that is past its limit, throws
+        // IllegalArgumentException, and this class is documented to throw
+        // OutOfSpaceException instead.
+        if (buffer.remaining() < minLengthVarIntSize) {
+          throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit());
+        }
+        buffer.position(oldPosition + minLengthVarIntSize);
+        encode(value, buffer);
+        int newPosition = buffer.position();
+        buffer.position(oldPosition);
+        writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize);
+        buffer.position(newPosition);
+      } else {
+        writeRawVarint32(encodedLength(value));
+        encode(value, buffer);
+      }
+    } catch (BufferOverflowException e) {
+      final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(),
+          buffer.limit());
+      outOfSpaceException.initCause(e);
+      throw outOfSpaceException;
+    }
+  }
+
+  // These UTF-8 handling methods are copied from Guava's Utf8 class.
+  /**
+   * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+   * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+   * both time and space.
+   *
+   * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+   *     surrogates)
+   */
+  private static int encodedLength(CharSequence sequence) {
+    // Warning to maintainers: this implementation is highly optimized.
+    int utf16Length = sequence.length();
+    int utf8Length = utf16Length;
+    int i = 0;
+
+    // This loop optimizes for pure ASCII.
+    while (i < utf16Length && sequence.charAt(i) < 0x80) {
+      i++;
+    }
+
+    // This loop optimizes for chars less than 0x800.
+    for (; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += ((0x7f - c) >>> 31);  // branch free!
+      } else {
+        utf8Length += encodedLengthGeneral(sequence, i);
+        break;
+      }
+    }
+
+    if (utf8Length < utf16Length) {
+      // Necessary and sufficient condition for overflow because of maximum 3x expansion
+      throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+              + (utf8Length + (1L << 32)));
+    }
+    return utf8Length;
+  }
+
+  private static int encodedLengthGeneral(CharSequence sequence, int start) {
+    int utf16Length = sequence.length();
+    int utf8Length = 0;
+    for (int i = start; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += (0x7f - c) >>> 31; // branch free!
+      } else {
+        utf8Length += 2;
+        // jdk7+: if (Character.isSurrogate(c)) {
+        if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+          // Check that we have a well-formed surrogate pair.
+          int cp = Character.codePointAt(sequence, i);
+          if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            throw new IllegalArgumentException("Unpaired surrogate at index " + i);
+          }
+          i++;
+        }
+      }
+    }
+    return utf8Length;
+  }
+
+  /**
+   * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is
+   * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time
+   * and space. Bytes are written starting at the current position. This method requires paired
+   * surrogates, and therefore does not support chunking.
+   *
+   * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+   * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the
+   * largest possible number of bytes that any input can be encoded to.
+   *
+   * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+   *     surrogates)
+   * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in
+   *     {@code byteBuffer}'s remaining space.
+   * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer.
+   */
+  private static void encode(CharSequence sequence, ByteBuffer byteBuffer) {
+    if (byteBuffer.isReadOnly()) {
+      throw new ReadOnlyBufferException();
+    } else if (byteBuffer.hasArray()) {
+      try {
+        int encoded = encode(sequence,
+                byteBuffer.array(),
+                byteBuffer.arrayOffset() + byteBuffer.position(),
+                byteBuffer.remaining());
+        byteBuffer.position(encoded - byteBuffer.arrayOffset());
+      } catch (ArrayIndexOutOfBoundsException e) {
+        BufferOverflowException boe = new BufferOverflowException();
+        boe.initCause(e);
+        throw boe;
+      }
+    } else {
+      encodeDirect(sequence, byteBuffer);
+    }
+  }
+
+  private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) {
+    int utf16Length = sequence.length();
+    for (int i = 0; i < utf16Length; i++) {
+      final char c = sequence.charAt(i);
+      if (c < 0x80) { // ASCII
+        byteBuffer.put((byte) c);
+      } else if (c < 0x800) { // 11 bits, two UTF-8 bytes
+        byteBuffer.put((byte) ((0xF << 6) | (c >>> 6)));
+        byteBuffer.put((byte) (0x80 | (0x3F & c)));
+      } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) {
+        // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+        byteBuffer.put((byte) ((0xF << 5) | (c >>> 12)));
+        byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6))));
+        byteBuffer.put((byte) (0x80 | (0x3F & c)));
+      } else {
+        final char low;
+        if (i + 1 == sequence.length()
+                || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+          throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
+        }
+        int codePoint = Character.toCodePoint(c, low);
+        byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18)));
+        byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12))));
+        byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6))));
+        byteBuffer.put((byte) (0x80 | (0x3F & codePoint)));
+      }
+    }
+  }
+
+  private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
+    int utf16Length = sequence.length();
+    int j = offset;
+    int i = 0;
+    int limit = offset + length;
+    // Designed to take advantage of
+    // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+    for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
+      bytes[j + i] = (byte) c;
+    }
+    if (i == utf16Length) {
+      return j + utf16Length;
+    }
+    j += i;
+    for (char c; i < utf16Length; i++) {
+      c = sequence.charAt(i);
+      if (c < 0x80 && j < limit) {
+        bytes[j++] = (byte) c;
+      } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+        bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
+        bytes[j++] = (byte) (0x80 | (0x3F & c));
+      } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+        // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+        bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
+        bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+        bytes[j++] = (byte) (0x80 | (0x3F & c));
+      } else if (j <= limit - 4) {
+        // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
+        final char low;
+        if (i + 1 == sequence.length()
+                || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+          throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
+        }
+        int codePoint = Character.toCodePoint(c, low);
+        bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+        bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+        bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+        bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
+      } else {
+        throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+      }
+    }
+    return j;
+  }
+
+  // End guava UTF-8 methods
+
+
+  /** Write a {@code group} field to the stream. */
+  public void writeGroupNoTag(final MessageNano value) throws IOException {
+    value.writeTo(this);
+  }
+
+  /** Write an embedded message field to the stream. */
+  public void writeMessageNoTag(final MessageNano value) throws IOException {
+    writeRawVarint32(value.getCachedSize());
+    value.writeTo(this);
+  }
+
+  /** Write a {@code bytes} field to the stream. */
+  public void writeBytesNoTag(final byte[] value) throws IOException {
+    writeRawVarint32(value.length);
+    writeRawBytes(value);
+  }
+
+  /** Write a {@code uint32} field to the stream. */
+  public void writeUInt32NoTag(final int value) throws IOException {
+    writeRawVarint32(value);
+  }
+
+  /**
+   * Write an enum field to the stream.  Caller is responsible
+   * for converting the enum value to its numeric value.
+   */
+  public void writeEnumNoTag(final int value) throws IOException {
+    writeRawVarint32(value);
+  }
+
+  /** Write an {@code sfixed32} field to the stream. */
+  public void writeSFixed32NoTag(final int value) throws IOException {
+    writeRawLittleEndian32(value);
+  }
+
+  /** Write an {@code sfixed64} field to the stream. */
+  public void writeSFixed64NoTag(final long value) throws IOException {
+    writeRawLittleEndian64(value);
+  }
+
+  /** Write an {@code sint32} field to the stream. */
+  public void writeSInt32NoTag(final int value) throws IOException {
+    writeRawVarint32(encodeZigZag32(value));
+  }
+
+  /** Write an {@code sint64} field to the stream. */
+  public void writeSInt64NoTag(final long value) throws IOException {
+    writeRawVarint64(encodeZigZag64(value));
+  }
+
+  // =================================================================
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code double} field, including tag.
+   */
+  public static int computeDoubleSize(final int fieldNumber,
+                                      final double value) {
+    return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code float} field, including tag.
+   */
+  public static int computeFloatSize(final int fieldNumber, final float value) {
+    return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint64} field, including tag.
+   */
+  public static int computeUInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int64} field, including tag.
+   */
+  public static int computeInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int32} field, including tag.
+   */
+  public static int computeInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed64} field, including tag.
+   */
+  public static int computeFixed64Size(final int fieldNumber,
+                                       final long value) {
+    return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed32} field, including tag.
+   */
+  public static int computeFixed32Size(final int fieldNumber,
+                                       final int value) {
+    return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bool} field, including tag.
+   */
+  public static int computeBoolSize(final int fieldNumber,
+                                    final boolean value) {
+    return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code string} field, including tag.
+   */
+  public static int computeStringSize(final int fieldNumber,
+                                      final String value) {
+    return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code group} field, including tag.
+   */
+  public static int computeGroupSize(final int fieldNumber,
+                                     final MessageNano value) {
+    return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * embedded message field, including tag.
+   */
+  public static int computeMessageSize(final int fieldNumber,
+                                       final MessageNano value) {
+    return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field, including tag.
+   */
+  public static int computeBytesSize(final int fieldNumber,
+                                     final byte[] value) {
+    return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint32} field, including tag.
+   */
+  public static int computeUInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * enum field, including tag.  Caller is responsible for converting the
+   * enum value to its numeric value.
+   */
+  public static int computeEnumSize(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed32} field, including tag.
+   */
+  public static int computeSFixed32Size(final int fieldNumber,
+                                        final int value) {
+    return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed64} field, including tag.
+   */
+  public static int computeSFixed64Size(final int fieldNumber,
+                                        final long value) {
+    return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint32} field, including tag.
+   */
+  public static int computeSInt32Size(final int fieldNumber, final int value) {
+    return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint64} field, including tag.
+   */
+  public static int computeSInt64Size(final int fieldNumber, final long value) {
+    return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * MessageSet extension to the stream.  For historical reasons,
+   * the wire format differs from normal fields.
+   */
+//  public static int computeMessageSetExtensionSize(
+//      final int fieldNumber, final MessageMicro value) {
+//    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
+//           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
+//           computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+//  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * unparsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+//  public static int computeRawMessageSetExtensionSize(
+//      final int fieldNumber, final ByteStringMicro value) {
+//    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
+//           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
+//           computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+//  }
+
+  // -----------------------------------------------------------------
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code double} field, including tag.
+   */
+  public static int computeDoubleSizeNoTag(final double value) {
+    return LITTLE_ENDIAN_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code float} field, including tag.
+   */
+  public static int computeFloatSizeNoTag(final float value) {
+    return LITTLE_ENDIAN_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint64} field, including tag.
+   */
+  public static int computeUInt64SizeNoTag(final long value) {
+    return computeRawVarint64Size(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int64} field, including tag.
+   */
+  public static int computeInt64SizeNoTag(final long value) {
+    return computeRawVarint64Size(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code int32} field, including tag.
+   */
+  public static int computeInt32SizeNoTag(final int value) {
+    if (value >= 0) {
+      return computeRawVarint32Size(value);
+    } else {
+      // Must sign-extend.
+      return 10;
+    }
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed64} field.
+   */
+  public static int computeFixed64SizeNoTag(final long value) {
+    return LITTLE_ENDIAN_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code fixed32} field.
+   */
+  public static int computeFixed32SizeNoTag(final int value) {
+    return LITTLE_ENDIAN_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bool} field.
+   */
+  public static int computeBoolSizeNoTag(final boolean value) {
+    return 1;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code string} field.
+   */
+  public static int computeStringSizeNoTag(final String value) {
+    final int length = encodedLength(value);
+    return computeRawVarint32Size(length) + length;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code group} field.
+   */
+  public static int computeGroupSizeNoTag(final MessageNano value) {
+    return value.getSerializedSize();
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an embedded
+   * message field.
+   */
+  public static int computeMessageSizeNoTag(final MessageNano value) {
+    final int size = value.getSerializedSize();
+    return computeRawVarint32Size(size) + size;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code bytes} field.
+   */
+  public static int computeBytesSizeNoTag(final byte[] value) {
+    return computeRawVarint32Size(value.length) + value.length;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a
+   * {@code uint32} field.
+   */
+  public static int computeUInt32SizeNoTag(final int value) {
+    return computeRawVarint32Size(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an enum field.
+   * Caller is responsible for converting the enum value to its numeric value.
+   */
+  public static int computeEnumSizeNoTag(final int value) {
+    return computeRawVarint32Size(value);
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed32} field.
+   */
+  public static int computeSFixed32SizeNoTag(final int value) {
+    return LITTLE_ENDIAN_32_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sfixed64} field.
+   */
+  public static int computeSFixed64SizeNoTag(final long value) {
+    return LITTLE_ENDIAN_64_SIZE;
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint32} field.
+   */
+  public static int computeSInt32SizeNoTag(final int value) {
+    return computeRawVarint32Size(encodeZigZag32(value));
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * {@code sint64} field.
+   */
+  public static int computeSInt64SizeNoTag(final long value) {
+    return computeRawVarint64Size(encodeZigZag64(value));
+  }
+
+  // =================================================================
+
+  /**
+   * If writing to a flat array, return the space left in the array.
+   * Otherwise, throws {@code UnsupportedOperationException}.
+   */
+  public int spaceLeft() {
+    return buffer.remaining();
+  }
+
+  /**
+   * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
+   * a byte array that is exactly big enough to hold a message, then write to
+   * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
+   * after writing verifies that the message was actually as big as expected,
+   * which can help catch bugs.
+   */
+  public void checkNoSpaceLeft() {
+    if (spaceLeft() != 0) {
+      throw new IllegalStateException(
+        "Did not write as much data as expected.");
+    }
+  }
+
+  /**
+   * Returns the position within the internal buffer.
+   */
+  public int position() {
+    return buffer.position();
+  }
+
+  /**
+   * Resets the position within the internal buffer to zero.
+   *
+   * @see #position
+   * @see #spaceLeft
+   */
+  public void reset() {
+    buffer.clear();
+  }
+
+  /**
+   * If you create a CodedOutputStream around a simple flat array, you must
+   * not attempt to write more bytes than the array has space.  Otherwise,
+   * this exception will be thrown.
+   */
+  public static class OutOfSpaceException extends IOException {
+    private static final long serialVersionUID = -6947486886997889499L;
+
+    OutOfSpaceException(int position, int limit) {
+      super("CodedOutputStream was writing to a flat byte array and ran " +
+            "out of space (pos " + position + " limit " + limit + ").");
+    }
+  }
+
+  /** Write a single byte. */
+  public void writeRawByte(final byte value) throws IOException {
+    if (!buffer.hasRemaining()) {
+      // We're writing to a single buffer.
+      throw new OutOfSpaceException(buffer.position(), buffer.limit());
+    }
+
+    buffer.put(value);
+  }
+
+  /** Write a single byte, represented by an integer value. */
+  public void writeRawByte(final int value) throws IOException {
+    writeRawByte((byte) value);
+  }
+
+  /** Write an array of bytes. */
+  public void writeRawBytes(final byte[] value) throws IOException {
+    writeRawBytes(value, 0, value.length);
+  }
+
+  /** Write part of an array of bytes. */
+  public void writeRawBytes(final byte[] value, int offset, int length)
+                            throws IOException {
+    if (buffer.remaining() >= length) {
+      buffer.put(value, offset, length);
+    } else {
+      // We're writing to a single buffer.
+      throw new OutOfSpaceException(buffer.position(), buffer.limit());
+    }
+  }
+
+  /** Encode and write a tag. */
+  public void writeTag(final int fieldNumber, final int wireType)
+                       throws IOException {
+    writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
+  }
+
+  /** Compute the number of bytes that would be needed to encode a tag. */
+  public static int computeTagSize(final int fieldNumber) {
+    return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
+  }
+
+  /**
+   * Encode and write a varint.  {@code value} is treated as
+   * unsigned, so it won't be sign-extended if negative.
+   */
+  public void writeRawVarint32(int value) throws IOException {
+    while (true) {
+      if ((value & ~0x7F) == 0) {
+        writeRawByte(value);
+        return;
+      } else {
+        writeRawByte((value & 0x7F) | 0x80);
+        value >>>= 7;
+      }
+    }
+  }
+
+  /**
+   * Compute the number of bytes that would be needed to encode a varint.
+   * {@code value} is treated as unsigned, so it won't be sign-extended if
+   * negative.
+   */
+  public static int computeRawVarint32Size(final int value) {
+    if ((value & (0xffffffff <<  7)) == 0) return 1;
+    if ((value & (0xffffffff << 14)) == 0) return 2;
+    if ((value & (0xffffffff << 21)) == 0) return 3;
+    if ((value & (0xffffffff << 28)) == 0) return 4;
+    return 5;
+  }
+
+  /** Encode and write a varint. */
+  public void writeRawVarint64(long value) throws IOException {
+    while (true) {
+      if ((value & ~0x7FL) == 0) {
+        writeRawByte((int)value);
+        return;
+      } else {
+        writeRawByte(((int)value & 0x7F) | 0x80);
+        value >>>= 7;
+      }
+    }
+  }
+
+  /** Compute the number of bytes that would be needed to encode a varint. */
+  public static int computeRawVarint64Size(final long value) {
+    if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
+    if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
+    if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
+    if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
+    if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
+    if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
+    if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
+    if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
+    if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
+    return 10;
+  }
+
+  /** Write a little-endian 32-bit integer. */
+  public void writeRawLittleEndian32(final int value) throws IOException {
+    if (buffer.remaining() < 4) {
+      throw new OutOfSpaceException(buffer.position(), buffer.limit());
+    }
+    buffer.putInt(value);
+  }
+
+  public static final int LITTLE_ENDIAN_32_SIZE = 4;
+
+  /** Write a little-endian 64-bit integer. */
+  public void writeRawLittleEndian64(final long value) throws IOException {
+    if (buffer.remaining() < 8) {
+      throw new OutOfSpaceException(buffer.position(), buffer.limit());
+    }
+    buffer.putLong(value);
+  }
+
+  public static final int LITTLE_ENDIAN_64_SIZE = 8;
+
+  /**
+   * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n A signed 32-bit integer.
+   * @return An unsigned 32-bit integer, stored in a signed int because
+   *         Java has no explicit unsigned support.
+   */
+  public static int encodeZigZag32(final int n) {
+    // Note:  the right-shift must be arithmetic
+    return (n << 1) ^ (n >> 31);
+  }
+
+  /**
+   * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+   * into values that can be efficiently encoded with varint.  (Otherwise,
+   * negative values must be sign-extended to 64 bits to be varint encoded,
+   * thus always taking 10 bytes on the wire.)
+   *
+   * @param n A signed 64-bit integer.
+   * @return An unsigned 64-bit integer, stored in a signed int because
+   *         Java has no explicit unsigned support.
+   */
+  public static long encodeZigZag64(final long n) {
+    // Note:  the right-shift must be arithmetic
+    return (n << 1) ^ (n >> 63);
+  }
+
+  static int computeFieldSize(int number, int type, Object object) {
+    switch (type) {
+      case InternalNano.TYPE_BOOL:
+        return computeBoolSize(number, (Boolean) object);
+      case InternalNano.TYPE_BYTES:
+        return computeBytesSize(number, (byte[]) object);
+      case InternalNano.TYPE_STRING:
+        return computeStringSize(number, (String) object);
+      case InternalNano.TYPE_FLOAT:
+        return computeFloatSize(number, (Float) object);
+      case InternalNano.TYPE_DOUBLE:
+        return computeDoubleSize(number, (Double) object);
+      case InternalNano.TYPE_ENUM:
+        return computeEnumSize(number, (Integer) object);
+      case InternalNano.TYPE_FIXED32:
+        return computeFixed32Size(number, (Integer) object);
+      case InternalNano.TYPE_INT32:
+        return computeInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_UINT32:
+        return computeUInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_SINT32:
+        return computeSInt32Size(number, (Integer) object);
+      case InternalNano.TYPE_SFIXED32:
+        return computeSFixed32Size(number, (Integer) object);
+      case InternalNano.TYPE_INT64:
+        return computeInt64Size(number, (Long) object);
+      case InternalNano.TYPE_UINT64:
+        return computeUInt64Size(number, (Long) object);
+      case InternalNano.TYPE_SINT64:
+        return computeSInt64Size(number, (Long) object);
+      case InternalNano.TYPE_FIXED64:
+        return computeFixed64Size(number, (Long) object);
+      case InternalNano.TYPE_SFIXED64:
+        return computeSFixed64Size(number, (Long) object);
+      case InternalNano.TYPE_MESSAGE:
+        return computeMessageSize(number, (MessageNano) object);
+      case InternalNano.TYPE_GROUP:
+        return computeGroupSize(number, (MessageNano) object);
+      default:
+        throw new IllegalArgumentException("Unknown type: " + type);
+    }
+  }
+
+  void writeField(int number, int type, Object value)
+      throws IOException {
+    switch (type) {
+      case InternalNano.TYPE_DOUBLE:
+        Double doubleValue = (Double) value;
+        writeDouble(number, doubleValue);
+        break;
+      case InternalNano.TYPE_FLOAT:
+        Float floatValue = (Float) value;
+        writeFloat(number, floatValue);
+        break;
+      case InternalNano.TYPE_INT64:
+        Long int64Value = (Long) value;
+        writeInt64(number, int64Value);
+        break;
+      case InternalNano.TYPE_UINT64:
+        Long uint64Value = (Long) value;
+        writeUInt64(number, uint64Value);
+        break;
+      case InternalNano.TYPE_INT32:
+        Integer int32Value = (Integer) value;
+        writeInt32(number, int32Value);
+        break;
+      case InternalNano.TYPE_FIXED64:
+        Long fixed64Value = (Long) value;
+        writeFixed64(number, fixed64Value);
+        break;
+      case InternalNano.TYPE_FIXED32:
+        Integer fixed32Value = (Integer) value;
+        writeFixed32(number, fixed32Value);
+        break;
+      case InternalNano.TYPE_BOOL:
+        Boolean boolValue = (Boolean) value;
+        writeBool(number, boolValue);
+        break;
+      case InternalNano.TYPE_STRING:
+        String stringValue = (String) value;
+        writeString(number, stringValue);
+        break;
+      case InternalNano.TYPE_BYTES:
+        byte[] bytesValue = (byte[]) value;
+        writeBytes(number, bytesValue);
+        break;
+      case InternalNano.TYPE_UINT32:
+        Integer uint32Value = (Integer) value;
+        writeUInt32(number, uint32Value);
+        break;
+      case InternalNano.TYPE_ENUM:
+        Integer enumValue = (Integer) value;
+        writeEnum(number, enumValue);
+        break;
+      case InternalNano.TYPE_SFIXED32:
+        Integer sfixed32Value = (Integer) value;
+        writeSFixed32(number, sfixed32Value);
+        break;
+      case InternalNano.TYPE_SFIXED64:
+        Long sfixed64Value = (Long) value;
+        writeSFixed64(number, sfixed64Value);
+        break;
+      case InternalNano.TYPE_SINT32:
+        Integer sint32Value = (Integer) value;
+        writeSInt32(number, sint32Value);
+        break;
+      case InternalNano.TYPE_SINT64:
+        Long sint64Value = (Long) value;
+        writeSInt64(number, sint64Value);
+        break;
+      case InternalNano.TYPE_MESSAGE:
+        MessageNano messageValue = (MessageNano) value;
+        writeMessage(number, messageValue);
+        break;
+      case InternalNano.TYPE_GROUP:
+        MessageNano groupValue = (MessageNano) value;
+        writeGroup(number, groupValue);
+        break;
+      default:
+        throw new IOException("Unknown type: " + type);
+    }
+  }
+
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
new file mode 100644
index 0000000..87973d7
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
@@ -0,0 +1,169 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+
+/**
+ * Base class of those Protocol Buffer messages that need to store unknown fields,
+ * such as extensions.
+ */
+public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
+        extends MessageNano {
+    /**
+     * A container for fields unknown to the message, including extensions. Extension fields can
+     * can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
+     */
+    protected FieldArray unknownFieldData;
+
+    @Override
+    protected int computeSerializedSize() {
+        int size = 0;
+        if (unknownFieldData != null) {
+            for (int i = 0; i < unknownFieldData.size(); i++) {
+                FieldData field = unknownFieldData.dataAt(i);
+                size += field.computeSerializedSize();
+            }
+        }
+        return size;
+    }
+
+    @Override
+    public void writeTo(CodedOutputByteBufferNano output) throws IOException {
+        if (unknownFieldData == null) {
+            return;
+        }
+        for (int i = 0; i < unknownFieldData.size(); i++) {
+            FieldData field = unknownFieldData.dataAt(i);
+            field.writeTo(output);
+        }
+    }
+
+    /**
+     * Checks if there is a value stored for the specified extension in this
+     * message.
+     */
+    public final boolean hasExtension(Extension<M, ?> extension) {
+        if (unknownFieldData == null) {
+            return false;
+        }
+        FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
+        return field != null;
+    }
+
+    /**
+     * Gets the value stored in the specified extension of this message.
+     */
+    public final <T> T getExtension(Extension<M, T> extension) {
+        if (unknownFieldData == null) {
+            return null;
+        }
+        FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
+        return field == null ? null : field.getValue(extension);
+    }
+
+    /**
+     * Sets the value of the specified extension of this message.
+     */
+    public final <T> M setExtension(Extension<M, T> extension, T value) {
+        int fieldNumber = WireFormatNano.getTagFieldNumber(extension.tag);
+        if (value == null) {
+            if (unknownFieldData != null) {
+                unknownFieldData.remove(fieldNumber);
+                if (unknownFieldData.isEmpty()) {
+                    unknownFieldData = null;
+                }
+            }
+        } else {
+            FieldData field = null;
+            if (unknownFieldData == null) {
+                unknownFieldData = new FieldArray();
+            } else {
+                field = unknownFieldData.get(fieldNumber);
+            }
+            if (field == null) {
+                unknownFieldData.put(fieldNumber, new FieldData(extension, value));
+            } else {
+                field.setValue(extension, value);
+            }
+        }
+
+        @SuppressWarnings("unchecked") // Generated code should guarantee type safety
+        M typedThis = (M) this;
+        return typedThis;
+    }
+
+    /**
+     * Stores the binary data of an unknown field.
+     *
+     * <p>Generated messages will call this for unknown fields if the store_unknown_fields
+     * option is on.
+     *
+     * <p>Note that the tag might be a end-group tag (rather than the start of an unknown field) in
+     * which case we do not want to add an unknown field entry.
+     *
+     * @param input the input buffer.
+     * @param tag the tag of the field.
+
+     * @return {@literal true} unless the tag is an end-group tag.
+     */
+    protected final boolean storeUnknownField(CodedInputByteBufferNano input, int tag)
+            throws IOException {
+        int startPos = input.getPosition();
+        if (!input.skipField(tag)) {
+            return false;  // This wasn't an unknown field, it's an end-group tag.
+        }
+        int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
+        int endPos = input.getPosition();
+        byte[] bytes = input.getData(startPos, endPos - startPos);
+        UnknownFieldData unknownField = new UnknownFieldData(tag, bytes);
+
+        FieldData field = null;
+        if (unknownFieldData == null) {
+            unknownFieldData = new FieldArray();
+        } else {
+            field = unknownFieldData.get(fieldNumber);
+        }
+        if (field == null) {
+            field = new FieldData();
+            unknownFieldData.put(fieldNumber, field);
+        }
+        field.addUnknownField(unknownField);
+        return true;
+    }
+
+    @Override
+    public M clone() throws CloneNotSupportedException {
+        M cloned = (M) super.clone();
+        InternalNano.cloneUnknownFieldData(this, cloned);
+        return cloned;
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/Extension.java
new file mode 100644
index 0000000..c458f9b
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/Extension.java
@@ -0,0 +1,706 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents an extension.
+ *
+ * @author bduff@google.com (Brian Duff)
+ * @author maxtroy@google.com (Max Cai)
+ * @param <M> the type of the extendable message this extension is for.
+ * @param <T> the Java type of the extension; see {@link #clazz}.
+ */
+public class Extension<M extends ExtendableMessageNano<M>, T> {
+
+    /*
+     * Because we typically only define message-typed extensions, the Extension class hierarchy is
+     * designed as follows, to allow a big amount of code in this file to be removed by ProGuard:
+     *
+     *            Extension          // ready to use for message/group typed extensions
+     *                Δ
+     *                |
+     *       PrimitiveExtension      // for primitive/enum typed extensions
+     */
+
+    public static final int TYPE_DOUBLE   = InternalNano.TYPE_DOUBLE;
+    public static final int TYPE_FLOAT    = InternalNano.TYPE_FLOAT;
+    public static final int TYPE_INT64    = InternalNano.TYPE_INT64;
+    public static final int TYPE_UINT64   = InternalNano.TYPE_UINT64;
+    public static final int TYPE_INT32    = InternalNano.TYPE_INT32;
+    public static final int TYPE_FIXED64  = InternalNano.TYPE_FIXED64;
+    public static final int TYPE_FIXED32  = InternalNano.TYPE_FIXED32;
+    public static final int TYPE_BOOL     = InternalNano.TYPE_BOOL;
+    public static final int TYPE_STRING   = InternalNano.TYPE_STRING;
+    public static final int TYPE_GROUP    = InternalNano.TYPE_GROUP;
+    public static final int TYPE_MESSAGE  = InternalNano.TYPE_MESSAGE;
+    public static final int TYPE_BYTES    = InternalNano.TYPE_BYTES;
+    public static final int TYPE_UINT32   = InternalNano.TYPE_UINT32;
+    public static final int TYPE_ENUM     = InternalNano.TYPE_ENUM;
+    public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32;
+    public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64;
+    public static final int TYPE_SINT32   = InternalNano.TYPE_SINT32;
+    public static final int TYPE_SINT64   = InternalNano.TYPE_SINT64;
+
+    /**
+     * Creates an {@code Extension} of the given message type and tag number.
+     * Should be used by the generated code only.
+     *
+     * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
+     * @deprecated use {@link #createMessageTyped(int, Class, long)} instead.
+     */
+    @Deprecated
+    public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
+            Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) {
+        return new Extension<M, T>(type, clazz, tag, false);
+    }
+
+    // Note: these create...() methods take a long for the tag parameter,
+    // because tags are represented as unsigned ints, and these values exist
+    // in generated code as long values. However, they can fit in 32-bits, so
+    // it's safe to cast them to int without loss of precision.
+
+    /**
+     * Creates an {@code Extension} of the given message type and tag number.
+     * Should be used by the generated code only.
+     *
+     * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
+     */
+    public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
+            Extension<M, T> createMessageTyped(int type, Class<T> clazz, long tag) {
+        return new Extension<M, T>(type, clazz, (int) tag, false);
+    }
+
+    /**
+     * Creates a repeated {@code Extension} of the given message type and tag number.
+     * Should be used by the generated code only.
+     *
+     * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
+     */
+    public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
+            Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag) {
+        return new Extension<M, T[]>(type, clazz, (int) tag, true);
+    }
+
+    /**
+     * Creates an {@code Extension} of the given primitive type and tag number.
+     * Should be used by the generated code only.
+     *
+     * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
+     * @param clazz the boxed Java type of this extension
+     */
+    public static <M extends ExtendableMessageNano<M>, T>
+            Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, long tag) {
+        return new PrimitiveExtension<M, T>(type, clazz, (int) tag, false, 0, 0);
+    }
+
+    /**
+     * Creates a repeated {@code Extension} of the given primitive type and tag number.
+     * Should be used by the generated code only.
+     *
+     * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
+     * @param clazz the Java array type of this extension, with an unboxed component type
+     */
+    public static <M extends ExtendableMessageNano<M>, T>
+            Extension<M, T> createRepeatedPrimitiveTyped(
+                    int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag) {
+        return new PrimitiveExtension<M, T>(type, clazz, (int) tag, true,
+            (int) nonPackedTag, (int) packedTag);
+    }
+
+    /**
+     * Protocol Buffer type of this extension; one of the {@code TYPE_} constants.
+     */
+    protected final int type;
+
+    /**
+     * Java type of this extension. For a singular extension, this is the boxed Java type for the
+     * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose
+     * component type is the unboxed Java type for {@link #type}. For example, for a singular
+     * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a
+     * repeated {@code int32} extension, this equals {@code int[].class}.
+     */
+    protected final Class<T> clazz;
+
+    /**
+     * Tag number of this extension. The data should be viewed as an unsigned 32-bit value.
+     */
+    public final int tag;
+
+    /**
+     * Whether this extension is repeated.
+     */
+    protected final boolean repeated;
+
+    private Extension(int type, Class<T> clazz, int tag, boolean repeated) {
+        this.type = type;
+        this.clazz = clazz;
+        this.tag = tag;
+        this.repeated = repeated;
+    }
+
+    /**
+     * Returns the value of this extension stored in the given list of unknown fields, or
+     * {@code null} if no unknown fields matches this extension.
+     *
+     * @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag
+     *                      that matches this Extension's tag.
+     *
+     */
+    final T getValueFrom(List<UnknownFieldData> unknownFields) {
+        if (unknownFields == null) {
+            return null;
+        }
+        return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields);
+    }
+
+    private T getRepeatedValueFrom(List<UnknownFieldData> unknownFields) {
+        // For repeated extensions, read all matching unknown fields in their original order.
+        List<Object> resultList = new ArrayList<Object>();
+        for (int i = 0; i < unknownFields.size(); i++) {
+            UnknownFieldData data = unknownFields.get(i);
+            if (data.bytes.length != 0) {
+                readDataInto(data, resultList);
+            }
+        }
+
+        int resultSize = resultList.size();
+        if (resultSize == 0) {
+            return null;
+        } else {
+            T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize));
+            for (int i = 0; i < resultSize; i++) {
+                Array.set(result, i, resultList.get(i));
+            }
+            return result;
+        }
+    }
+
+    private T getSingularValueFrom(List<UnknownFieldData> unknownFields) {
+        // For singular extensions, get the last piece of data stored under this extension.
+        if (unknownFields.isEmpty()) {
+            return null;
+        }
+        UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1);
+        return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes)));
+    }
+
+    protected Object readData(CodedInputByteBufferNano input) {
+        // This implementation is for message/group extensions.
+        Class<?> messageType = repeated ? clazz.getComponentType() : clazz;
+        try {
+            switch (type) {
+                case TYPE_GROUP:
+                    MessageNano group = (MessageNano) messageType.newInstance();
+                    input.readGroup(group, WireFormatNano.getTagFieldNumber(tag));
+                    return group;
+                case TYPE_MESSAGE:
+                    MessageNano message = (MessageNano) messageType.newInstance();
+                    input.readMessage(message);
+                    return message;
+                default:
+                    throw new IllegalArgumentException("Unknown type " + type);
+            }
+        } catch (InstantiationException e) {
+            throw new IllegalArgumentException(
+                    "Error creating instance of class " + messageType, e);
+        } catch (IllegalAccessException e) {
+            throw new IllegalArgumentException(
+                    "Error creating instance of class " + messageType, e);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Error reading extension field", e);
+        }
+    }
+
+    protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
+        // This implementation is for message/group extensions.
+        resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
+    }
+
+    void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException {
+        if (repeated) {
+            writeRepeatedData(value, output);
+        } else {
+            writeSingularData(value, output);
+        }
+    }
+
+    protected void writeSingularData(Object value, CodedOutputByteBufferNano out) {
+        // This implementation is for message/group extensions.
+        try {
+            out.writeRawVarint32(tag);
+            switch (type) {
+                case TYPE_GROUP:
+                    MessageNano groupValue = (MessageNano) value;
+                    int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
+                    out.writeGroupNoTag(groupValue);
+                    // The endgroup tag must be included in the data payload.
+                    out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
+                    break;
+                case TYPE_MESSAGE:
+                    MessageNano messageValue = (MessageNano) value;
+                    out.writeMessageNoTag(messageValue);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown type " + type);
+            }
+        } catch (IOException e) {
+            // Should not happen
+            throw new IllegalStateException(e);
+        }
+    }
+
+    protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) {
+        // This implementation is for non-packed extensions.
+        int arrayLength = Array.getLength(array);
+        for (int i = 0; i < arrayLength; i++) {
+            Object element = Array.get(array, i);
+            if (element != null) {
+                writeSingularData(element, output);
+            }
+        }
+    }
+
+    int computeSerializedSize(Object value) {
+        if (repeated) {
+            return computeRepeatedSerializedSize(value);
+        } else {
+            return computeSingularSerializedSize(value);
+        }
+    }
+
+    protected int computeRepeatedSerializedSize(Object array) {
+        // This implementation is for non-packed extensions.
+        int size = 0;
+        int arrayLength = Array.getLength(array);
+        for (int i = 0; i < arrayLength; i++) {
+            Object element = Array.get(array, i);
+            if (element != null) {
+                size += computeSingularSerializedSize(Array.get(array, i));
+            }
+        }
+        return size;
+    }
+
+    protected int computeSingularSerializedSize(Object value) {
+        // This implementation is for message/group extensions.
+        int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
+        switch (type) {
+            case TYPE_GROUP:
+                MessageNano groupValue = (MessageNano) value;
+                return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue);
+            case TYPE_MESSAGE:
+                MessageNano messageValue = (MessageNano) value;
+                return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue);
+            default:
+                throw new IllegalArgumentException("Unknown type " + type);
+        }
+    }
+
+    /**
+     * Represents an extension of a primitive (including enum) type. If there is no primitive
+     * extensions, this subclass will be removable by ProGuard.
+     */
+    private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T>
+            extends Extension<M, T> {
+
+        /**
+         * Tag of a piece of non-packed data from the wire compatible with this extension.
+         */
+        private final int nonPackedTag;
+
+        /**
+         * Tag of a piece of packed data from the wire compatible with this extension.
+         * 0 if the type of this extension is not packable.
+         */
+        private final int packedTag;
+
+        public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated,
+                int nonPackedTag, int packedTag) {
+            super(type, clazz, tag, repeated);
+            this.nonPackedTag = nonPackedTag;
+            this.packedTag = packedTag;
+        }
+
+        @Override
+        protected Object readData(CodedInputByteBufferNano input) {
+            try {
+              return input.readPrimitiveField(type);
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Error reading extension field", e);
+            }
+        }
+
+        @Override
+        protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
+            // This implementation is for primitive typed extensions,
+            // which can read both packed and non-packed data.
+            if (data.tag == nonPackedTag) {
+                resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
+            } else {
+                CodedInputByteBufferNano buffer =
+                        CodedInputByteBufferNano.newInstance(data.bytes);
+                try {
+                    buffer.pushLimit(buffer.readRawVarint32()); // length limit
+                } catch (IOException e) {
+                    throw new IllegalArgumentException("Error reading extension field", e);
+                }
+                while (!buffer.isAtEnd()) {
+                    resultList.add(readData(buffer));
+                }
+            }
+        }
+
+        @Override
+        protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) {
+            try {
+                output.writeRawVarint32(tag);
+                switch (type) {
+                    case TYPE_DOUBLE:
+                        Double doubleValue = (Double) value;
+                        output.writeDoubleNoTag(doubleValue);
+                        break;
+                    case TYPE_FLOAT:
+                        Float floatValue = (Float) value;
+                        output.writeFloatNoTag(floatValue);
+                        break;
+                    case TYPE_INT64:
+                        Long int64Value = (Long) value;
+                        output.writeInt64NoTag(int64Value);
+                        break;
+                    case TYPE_UINT64:
+                        Long uint64Value = (Long) value;
+                        output.writeUInt64NoTag(uint64Value);
+                        break;
+                    case TYPE_INT32:
+                        Integer int32Value = (Integer) value;
+                        output.writeInt32NoTag(int32Value);
+                        break;
+                    case TYPE_FIXED64:
+                        Long fixed64Value = (Long) value;
+                        output.writeFixed64NoTag(fixed64Value);
+                        break;
+                    case TYPE_FIXED32:
+                        Integer fixed32Value = (Integer) value;
+                        output.writeFixed32NoTag(fixed32Value);
+                        break;
+                    case TYPE_BOOL:
+                        Boolean boolValue = (Boolean) value;
+                        output.writeBoolNoTag(boolValue);
+                        break;
+                    case TYPE_STRING:
+                        String stringValue = (String) value;
+                        output.writeStringNoTag(stringValue);
+                        break;
+                    case TYPE_BYTES:
+                        byte[] bytesValue = (byte[]) value;
+                        output.writeBytesNoTag(bytesValue);
+                        break;
+                    case TYPE_UINT32:
+                        Integer uint32Value = (Integer) value;
+                        output.writeUInt32NoTag(uint32Value);
+                        break;
+                    case TYPE_ENUM:
+                        Integer enumValue = (Integer) value;
+                        output.writeEnumNoTag(enumValue);
+                        break;
+                    case TYPE_SFIXED32:
+                        Integer sfixed32Value = (Integer) value;
+                        output.writeSFixed32NoTag(sfixed32Value);
+                        break;
+                    case TYPE_SFIXED64:
+                        Long sfixed64Value = (Long) value;
+                        output.writeSFixed64NoTag(sfixed64Value);
+                        break;
+                    case TYPE_SINT32:
+                        Integer sint32Value = (Integer) value;
+                        output.writeSInt32NoTag(sint32Value);
+                        break;
+                    case TYPE_SINT64:
+                        Long sint64Value = (Long) value;
+                        output.writeSInt64NoTag(sint64Value);
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Unknown type " + type);
+                }
+            } catch (IOException e) {
+                // Should not happen
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) {
+            if (tag == nonPackedTag) {
+                // Use base implementation for non-packed data
+                super.writeRepeatedData(array, output);
+            } else if (tag == packedTag) {
+                // Packed. Note that the array element type is guaranteed to be primitive, so there
+                // won't be any null elements, so no null check in this block.
+                int arrayLength = Array.getLength(array);
+                int dataSize = computePackedDataSize(array);
+
+                try {
+                    output.writeRawVarint32(tag);
+                    output.writeRawVarint32(dataSize);
+                    switch (type) {
+                        case TYPE_BOOL:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeBoolNoTag(Array.getBoolean(array, i));
+                            }
+                            break;
+                        case TYPE_FIXED32:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeFixed32NoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        case TYPE_SFIXED32:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeSFixed32NoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        case TYPE_FLOAT:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeFloatNoTag(Array.getFloat(array, i));
+                            }
+                            break;
+                        case TYPE_FIXED64:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeFixed64NoTag(Array.getLong(array, i));
+                            }
+                            break;
+                        case TYPE_SFIXED64:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeSFixed64NoTag(Array.getLong(array, i));
+                            }
+                            break;
+                        case TYPE_DOUBLE:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeDoubleNoTag(Array.getDouble(array, i));
+                            }
+                            break;
+                        case TYPE_INT32:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeInt32NoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        case TYPE_SINT32:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeSInt32NoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        case TYPE_UINT32:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeUInt32NoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        case TYPE_INT64:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeInt64NoTag(Array.getLong(array, i));
+                            }
+                            break;
+                        case TYPE_SINT64:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeSInt64NoTag(Array.getLong(array, i));
+                            }
+                            break;
+                        case TYPE_UINT64:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeUInt64NoTag(Array.getLong(array, i));
+                            }
+                            break;
+                        case TYPE_ENUM:
+                            for (int i = 0; i < arrayLength; i++) {
+                                output.writeEnumNoTag(Array.getInt(array, i));
+                            }
+                            break;
+                        default:
+                            throw new IllegalArgumentException("Unpackable type " + type);
+                    }
+                } catch (IOException e) {
+                    // Should not happen.
+                    throw new IllegalStateException(e);
+                }
+            } else {
+                throw new IllegalArgumentException("Unexpected repeated extension tag " + tag
+                        + ", unequal to both non-packed variant " + nonPackedTag
+                        + " and packed variant " + packedTag);
+            }
+        }
+
+        private int computePackedDataSize(Object array) {
+            int dataSize = 0;
+            int arrayLength = Array.getLength(array);
+            switch (type) {
+                case TYPE_BOOL:
+                    // Bools are stored as int32 but just as 0 or 1, so 1 byte each.
+                    dataSize = arrayLength;
+                    break;
+                case TYPE_FIXED32:
+                case TYPE_SFIXED32:
+                case TYPE_FLOAT:
+                    dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE;
+                    break;
+                case TYPE_FIXED64:
+                case TYPE_SFIXED64:
+                case TYPE_DOUBLE:
+                    dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE;
+                    break;
+                case TYPE_INT32:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag(
+                                Array.getInt(array, i));
+                    }
+                    break;
+                case TYPE_SINT32:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag(
+                                Array.getInt(array, i));
+                    }
+                    break;
+                case TYPE_UINT32:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag(
+                                Array.getInt(array, i));
+                    }
+                    break;
+                case TYPE_INT64:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag(
+                                Array.getLong(array, i));
+                    }
+                    break;
+                case TYPE_SINT64:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag(
+                                Array.getLong(array, i));
+                    }
+                    break;
+                case TYPE_UINT64:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag(
+                                Array.getLong(array, i));
+                    }
+                    break;
+                case TYPE_ENUM:
+                    for (int i = 0; i < arrayLength; i++) {
+                        dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag(
+                                Array.getInt(array, i));
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unexpected non-packable type " + type);
+            }
+            return dataSize;
+        }
+
+        @Override
+        protected int computeRepeatedSerializedSize(Object array) {
+            if (tag == nonPackedTag) {
+                // Use base implementation for non-packed data
+                return super.computeRepeatedSerializedSize(array);
+            } else if (tag == packedTag) {
+                // Packed.
+                int dataSize = computePackedDataSize(array);
+                int payloadSize =
+                        dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize);
+                return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag);
+            } else {
+                throw new IllegalArgumentException("Unexpected repeated extension tag " + tag
+                        + ", unequal to both non-packed variant " + nonPackedTag
+                        + " and packed variant " + packedTag);
+            }
+        }
+
+        @Override
+        protected final int computeSingularSerializedSize(Object value) {
+            int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
+            switch (type) {
+                case TYPE_DOUBLE:
+                    Double doubleValue = (Double) value;
+                    return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue);
+                case TYPE_FLOAT:
+                    Float floatValue = (Float) value;
+                    return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue);
+                case TYPE_INT64:
+                    Long int64Value = (Long) value;
+                    return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value);
+                case TYPE_UINT64:
+                    Long uint64Value = (Long) value;
+                    return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value);
+                case TYPE_INT32:
+                    Integer int32Value = (Integer) value;
+                    return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value);
+                case TYPE_FIXED64:
+                    Long fixed64Value = (Long) value;
+                    return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value);
+                case TYPE_FIXED32:
+                    Integer fixed32Value = (Integer) value;
+                    return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value);
+                case TYPE_BOOL:
+                    Boolean boolValue = (Boolean) value;
+                    return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue);
+                case TYPE_STRING:
+                    String stringValue = (String) value;
+                    return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue);
+                case TYPE_BYTES:
+                    byte[] bytesValue = (byte[]) value;
+                    return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue);
+                case TYPE_UINT32:
+                    Integer uint32Value = (Integer) value;
+                    return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value);
+                case TYPE_ENUM:
+                    Integer enumValue = (Integer) value;
+                    return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue);
+                case TYPE_SFIXED32:
+                    Integer sfixed32Value = (Integer) value;
+                    return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber,
+                            sfixed32Value);
+                case TYPE_SFIXED64:
+                    Long sfixed64Value = (Long) value;
+                    return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber,
+                            sfixed64Value);
+                case TYPE_SINT32:
+                    Integer sint32Value = (Integer) value;
+                    return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value);
+                case TYPE_SINT64:
+                    Long sint64Value = (Long) value;
+                    return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value);
+                default:
+                    throw new IllegalArgumentException("Unknown type " + type);
+            }
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java
new file mode 100644
index 0000000..b49a97f
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java
@@ -0,0 +1,291 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+package com.google.protobuf.nano;
+
+
+/**
+ * A custom version of {@code android.util.SparseArray} with the minimal API
+ * for storing {@link FieldData} objects.
+ *
+ * <p>This class is an internal implementation detail of nano and should not
+ * be called directly by clients.
+ *
+ * Based on {@code android.support.v4.util.SpareArrayCompat}.
+ */
+public final class FieldArray implements Cloneable {
+    private static final FieldData DELETED = new FieldData();
+    private boolean mGarbage = false;
+
+    private int[] mFieldNumbers;
+    private FieldData[] mData;
+    private int mSize;
+
+    /**
+     * Creates a new FieldArray containing no fields.
+     */
+    FieldArray() {
+        this(10);
+    }
+
+    /**
+     * Creates a new FieldArray containing no mappings that will not
+     * require any additional memory allocation to store the specified
+     * number of mappings.
+     */
+    FieldArray(int initialCapacity) {
+        initialCapacity = idealIntArraySize(initialCapacity);
+        mFieldNumbers = new int[initialCapacity];
+        mData = new FieldData[initialCapacity];
+        mSize = 0;
+    }
+
+    /**
+     * Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
+     * if no such mapping has been made.
+     */
+    FieldData get(int fieldNumber) {
+        int i = binarySearch(fieldNumber);
+
+        if (i < 0 || mData[i] == DELETED) {
+            return null;
+        } else {
+            return mData[i];
+        }
+    }
+
+    /**
+     * Removes the data from the specified fieldNumber, if there was any.
+     */
+    void remove(int fieldNumber) {
+        int i = binarySearch(fieldNumber);
+
+        if (i >= 0 && mData[i] != DELETED) {
+            mData[i] = DELETED;
+            mGarbage = true;
+        }
+    }
+
+    private void gc() {
+        int n = mSize;
+        int o = 0;
+        int[] keys = mFieldNumbers;
+        FieldData[] values = mData;
+
+        for (int i = 0; i < n; i++) {
+            FieldData val = values[i];
+
+            if (val != DELETED) {
+                if (i != o) {
+                    keys[o] = keys[i];
+                    values[o] = val;
+                    values[i] = null;
+                }
+
+                o++;
+            }
+        }
+
+        mGarbage = false;
+        mSize = o;
+    }
+
+    /**
+     * Adds a mapping from the specified fieldNumber to the specified data,
+     * replacing the previous mapping if there was one.
+     */
+    void put(int fieldNumber, FieldData data) {
+        int i = binarySearch(fieldNumber);
+
+        if (i >= 0) {
+            mData[i] = data;
+        } else {
+            i = ~i;
+
+            if (i < mSize && mData[i] == DELETED) {
+                mFieldNumbers[i] = fieldNumber;
+                mData[i] = data;
+                return;
+            }
+
+            if (mGarbage && mSize >= mFieldNumbers.length) {
+                gc();
+
+                // Search again because indices may have changed.
+                i = ~ binarySearch(fieldNumber);
+            }
+
+            if (mSize >= mFieldNumbers.length) {
+                int n = idealIntArraySize(mSize + 1);
+
+                int[] nkeys = new int[n];
+                FieldData[] nvalues = new FieldData[n];
+
+                System.arraycopy(mFieldNumbers, 0, nkeys, 0, mFieldNumbers.length);
+                System.arraycopy(mData, 0, nvalues, 0, mData.length);
+
+                mFieldNumbers = nkeys;
+                mData = nvalues;
+            }
+
+            if (mSize - i != 0) {
+                System.arraycopy(mFieldNumbers, i, mFieldNumbers, i + 1, mSize - i);
+                System.arraycopy(mData, i, mData, i + 1, mSize - i);
+            }
+
+            mFieldNumbers[i] = fieldNumber;
+            mData[i] = data;
+            mSize++;
+        }
+    }
+
+    /**
+     * Returns the number of key-value mappings that this FieldArray
+     * currently stores.
+     */
+    int size() {
+        if (mGarbage) {
+            gc();
+        }
+
+        return mSize;
+    }
+
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the value from the <code>index</code>th key-value mapping that this
+     * FieldArray stores.
+     */
+    FieldData dataAt(int index) {
+        if (mGarbage) {
+            gc();
+        }
+
+        return mData[index];
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof FieldArray)) {
+            return false;
+        }
+
+        FieldArray other = (FieldArray) o;
+        if (size() != other.size()) {  // size() will call gc() if necessary.
+            return false;
+        }
+        return arrayEquals(mFieldNumbers, other.mFieldNumbers, mSize) &&
+                arrayEquals(mData, other.mData, mSize);
+    }
+
+    @Override
+    public int hashCode() {
+        if (mGarbage) {
+            gc();
+        }
+        int result = 17;
+        for (int i = 0; i < mSize; i++) {
+            result = 31 * result + mFieldNumbers[i];
+            result = 31 * result + mData[i].hashCode();
+        }
+        return result;
+    }
+
+    private int idealIntArraySize(int need) {
+        return idealByteArraySize(need * 4) / 4;
+    }
+
+    private int idealByteArraySize(int need) {
+        for (int i = 4; i < 32; i++)
+            if (need <= (1 << i) - 12)
+                return (1 << i) - 12;
+
+        return need;
+    }
+
+    private int binarySearch(int value) {
+        int lo = 0;
+        int hi = mSize - 1;
+
+        while (lo <= hi) {
+            int mid = (lo + hi) >>> 1;
+            int midVal = mFieldNumbers[mid];
+
+            if (midVal < value) {
+                lo = mid + 1;
+            } else if (midVal > value) {
+                hi = mid - 1;
+            } else {
+                return mid; // value found
+            }
+        }
+        return ~lo; // value not present
+    }
+
+    private boolean arrayEquals(int[] a, int[] b, int size) {
+        for (int i = 0; i < size; i++) {
+            if (a[i] != b[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean arrayEquals(FieldData[] a, FieldData[] b, int size) {
+        for (int i = 0; i < size; i++) {
+            if (!a[i].equals(b[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public final FieldArray clone() {
+        // Trigger GC so we compact and don't copy DELETED elements.
+        int size = size();
+        FieldArray clone = new FieldArray(size);
+        System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size);
+        for (int i = 0; i < size; i++) {
+            if (mData[i] != null) {
+                clone.mData[i] = mData[i].clone();
+            }
+        }
+        clone.mSize = size;
+        return clone;
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldData.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldData.java
new file mode 100644
index 0000000..ebebabc
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/FieldData.java
@@ -0,0 +1,240 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Stores unknown fields. These might be extensions or fields that the generated API doesn't
+ * know about yet.
+ */
+class FieldData implements Cloneable {
+    private Extension<?, ?> cachedExtension;
+    private Object value;
+    /** The serialised values for this object. Will be cleared if getValue is called */
+    private List<UnknownFieldData> unknownFieldData;
+
+    <T> FieldData(Extension<?, T> extension, T newValue) {
+        cachedExtension = extension;
+        value = newValue;
+    }
+
+    FieldData() {
+        unknownFieldData = new ArrayList<UnknownFieldData>();
+    }
+
+    void addUnknownField(UnknownFieldData unknownField) {
+        unknownFieldData.add(unknownField);
+    }
+
+    UnknownFieldData getUnknownField(int index) {
+        if (unknownFieldData == null) {
+            return null;
+        }
+        if (index < unknownFieldData.size()) {
+            return unknownFieldData.get(index);
+        }
+        return null;
+    }
+
+    int getUnknownFieldSize() {
+        if (unknownFieldData == null) {
+            return 0;
+        }
+        return unknownFieldData.size();
+    }
+
+    <T> T getValue(Extension<?, T> extension) {
+        if (value != null){
+            if (cachedExtension != extension) {  // Extension objects are singletons.
+                throw new IllegalStateException(
+                        "Tried to getExtension with a differernt Extension.");
+            }
+        } else {
+            cachedExtension = extension;
+            value = extension.getValueFrom(unknownFieldData);
+            unknownFieldData = null;
+        }
+        return (T) value;
+    }
+
+    <T> void setValue(Extension<?, T> extension, T newValue) {
+        cachedExtension = extension;
+        value = newValue;
+        unknownFieldData = null;
+    }
+
+    int computeSerializedSize() {
+        int size = 0;
+        if (value != null) {
+            size = cachedExtension.computeSerializedSize(value);
+        } else {
+            for (UnknownFieldData unknownField : unknownFieldData) {
+                size += unknownField.computeSerializedSize();
+            }
+        }
+        return size;
+    }
+
+    void writeTo(CodedOutputByteBufferNano output) throws IOException {
+        if (value != null) {
+            cachedExtension.writeTo(value, output);
+        } else {
+            for (UnknownFieldData unknownField : unknownFieldData) {
+                unknownField.writeTo(output);
+            }
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof FieldData)) {
+            return false;
+        }
+
+        FieldData other = (FieldData) o;
+        if (value != null && other.value != null) {
+            // If both objects have deserialized values, compare those.
+            // Since unknown fields are only compared if messages have generated equals methods
+            // we know this will be a meaningful comparison (not identity) for all values.
+            if (cachedExtension != other.cachedExtension) {  // Extension objects are singletons.
+                return false;
+            }
+            if (!cachedExtension.clazz.isArray()) {
+                // Can't test (!cachedExtension.repeated) due to 'bytes' -> 'byte[]'
+                return value.equals(other.value);
+            }
+            if (value instanceof byte[]) {
+                return Arrays.equals((byte[]) value, (byte[]) other.value);
+            } else if (value instanceof int[]) {
+                return Arrays.equals((int[]) value, (int[]) other.value);
+            } else if (value instanceof long[]) {
+                return Arrays.equals((long[]) value, (long[]) other.value);
+            } else if (value instanceof float[]) {
+                return Arrays.equals((float[]) value, (float[]) other.value);
+            } else if (value instanceof double[]) {
+                return Arrays.equals((double[]) value, (double[]) other.value);
+            } else if (value instanceof boolean[]) {
+                return Arrays.equals((boolean[]) value, (boolean[]) other.value);
+            } else {
+                return Arrays.deepEquals((Object[]) value, (Object[]) other.value);
+            }
+        }
+        if (unknownFieldData != null && other.unknownFieldData != null) {
+            // If both objects have byte arrays compare those directly.
+            return unknownFieldData.equals(other.unknownFieldData);
+        }
+        try {
+            // As a last resort, serialize and compare the resulting byte arrays.
+            return Arrays.equals(toByteArray(), other.toByteArray());
+        } catch (IOException e) {
+            // Should not happen.
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        try {
+            // The only way to generate a consistent hash is to use the serialized form.
+            result = 31 * result + Arrays.hashCode(toByteArray());
+        } catch (IOException e) {
+            // Should not happen.
+            throw new IllegalStateException(e);
+        }
+        return result;
+    }
+
+    private byte[] toByteArray() throws IOException {
+        byte[] result = new byte[computeSerializedSize()];
+        CodedOutputByteBufferNano output = CodedOutputByteBufferNano.newInstance(result);
+        writeTo(output);
+        return result;
+    }
+
+    @Override
+    public final FieldData clone() {
+        FieldData clone = new FieldData();
+        try {
+            clone.cachedExtension = cachedExtension;
+            if (unknownFieldData == null) {
+                clone.unknownFieldData = null;
+            } else {
+                clone.unknownFieldData.addAll(unknownFieldData);
+            }
+
+            // Whether we need to deep clone value depends on its type. Primitive reference types
+            // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays
+            // and messages.
+            if (value == null) {
+                // No cloning required.
+            } else if (value instanceof MessageNano) {
+                clone.value = ((MessageNano) value).clone();
+            } else if (value instanceof byte[]) {
+                clone.value = ((byte[]) value).clone();
+            } else if (value instanceof byte[][]) {
+                byte[][] valueArray = (byte[][]) value;
+                byte[][] cloneArray = new byte[valueArray.length][];
+                clone.value = cloneArray;
+                for (int i = 0; i < valueArray.length; i++) {
+                    cloneArray[i] = valueArray[i].clone();
+                }
+            } else if (value instanceof boolean[]) {
+                clone.value = ((boolean[]) value).clone();
+            } else if (value instanceof int[]) {
+                clone.value = ((int[]) value).clone();
+            } else if (value instanceof long[]) {
+                clone.value = ((long[]) value).clone();
+            } else if (value instanceof float[]) {
+                clone.value = ((float[]) value).clone();
+            } else if (value instanceof double[]) {
+                clone.value = ((double[]) value).clone();
+            } else if (value instanceof MessageNano[]) {
+                MessageNano[] valueArray = (MessageNano[]) value;
+                MessageNano[] cloneArray = new MessageNano[valueArray.length];
+                clone.value = cloneArray;
+                for (int i = 0; i < valueArray.length; i++) {
+                    cloneArray[i] = valueArray[i].clone();
+                }
+            }
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
new file mode 100644
index 0000000..f1263df
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -0,0 +1,547 @@
+// 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.
+
+package com.google.protobuf.nano;
+
+import com.google.protobuf.nano.MapFactories.MapFactory;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public final class InternalNano {
+
+  public static final int TYPE_DOUBLE   = 1;
+  public static final int TYPE_FLOAT    = 2;
+  public static final int TYPE_INT64    = 3;
+  public static final int TYPE_UINT64   = 4;
+  public static final int TYPE_INT32    = 5;
+  public static final int TYPE_FIXED64  = 6;
+  public static final int TYPE_FIXED32  = 7;
+  public static final int TYPE_BOOL     = 8;
+  public static final int TYPE_STRING   = 9;
+  public static final int TYPE_GROUP    = 10;
+  public static final int TYPE_MESSAGE  = 11;
+  public static final int TYPE_BYTES    = 12;
+  public static final int TYPE_UINT32   = 13;
+  public static final int TYPE_ENUM     = 14;
+  public static final int TYPE_SFIXED32 = 15;
+  public static final int TYPE_SFIXED64 = 16;
+  public static final int TYPE_SINT32   = 17;
+  public static final int TYPE_SINT64   = 18;
+
+  protected static final Charset UTF_8 = Charset.forName("UTF-8");
+  protected static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+  private InternalNano() {}
+
+  /**
+   * An object to provide synchronization when lazily initializing static fields
+   * of {@link MessageNano} subclasses.
+   * <p>
+   * To enable earlier versions of ProGuard to inline short methods from a
+   * generated MessageNano subclass to the call sites, that class must not have
+   * a class initializer, which will be created if there is any static variable
+   * initializers. To lazily initialize the static variables in a thread-safe
+   * manner, the initialization code will synchronize on this object.
+   */
+  public static final Object LAZY_INIT_LOCK = new Object();
+
+  /**
+   * Helper called by generated code to construct default values for string
+   * fields.
+   * <p>
+   * The protocol compiler does not actually contain a UTF-8 decoder -- it
+   * just pushes UTF-8-encoded text around without touching it.  The one place
+   * where this presents a problem is when generating Java string literals.
+   * Unicode characters in the string literal would normally need to be encoded
+   * using a Unicode escape sequence, which would require decoding them.
+   * To get around this, protoc instead embeds the UTF-8 bytes into the
+   * generated code and leaves it to the runtime library to decode them.
+   * <p>
+   * It gets worse, though.  If protoc just generated a byte array, like:
+   *   new byte[] {0x12, 0x34, 0x56, 0x78}
+   * Java actually generates *code* which allocates an array and then fills
+   * in each value.  This is much less efficient than just embedding the bytes
+   * directly into the bytecode.  To get around this, we need another
+   * work-around.  String literals are embedded directly, so protoc actually
+   * generates a string literal corresponding to the bytes.  The easiest way
+   * to do this is to use the ISO-8859-1 character set, which corresponds to
+   * the first 256 characters of the Unicode range.  Protoc can then use
+   * good old CEscape to generate the string.
+   * <p>
+   * So we have a string literal which represents a set of bytes which
+   * represents another string.  This function -- stringDefaultValue --
+   * converts from the generated string to the string we actually want.  The
+   * generated code calls this automatically.
+   */
+  public static String stringDefaultValue(String bytes) {
+    return new String(bytes.getBytes(ISO_8859_1), InternalNano.UTF_8);
+  }
+
+  /**
+   * Helper called by generated code to construct default values for bytes
+   * fields.
+   * <p>
+   * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+   * In this case we only need the second of the two hacks -- allowing us to
+   * embed raw bytes as a string literal with ISO-8859-1 encoding.
+   */
+  public static byte[] bytesDefaultValue(String bytes) {
+    return bytes.getBytes(ISO_8859_1);
+  }
+
+  /**
+   * Helper function to convert a string into UTF-8 while turning the
+   * UnsupportedEncodingException to a RuntimeException.
+   */
+  public static byte[] copyFromUtf8(final String text) {
+    return text.getBytes(InternalNano.UTF_8);
+  }
+
+  /**
+   * Checks repeated int field equality; null-value and 0-length fields are
+   * considered equal.
+   */
+  public static boolean equals(int[] field1, int[] field2) {
+    if (field1 == null || field1.length == 0) {
+      return field2 == null || field2.length == 0;
+    } else {
+      return Arrays.equals(field1, field2);
+    }
+  }
+
+  /**
+   * Checks repeated long field equality; null-value and 0-length fields are
+   * considered equal.
+   */
+  public static boolean equals(long[] field1, long[] field2) {
+    if (field1 == null || field1.length == 0) {
+      return field2 == null || field2.length == 0;
+    } else {
+      return Arrays.equals(field1, field2);
+    }
+  }
+
+  /**
+   * Checks repeated float field equality; null-value and 0-length fields are
+   * considered equal.
+   */
+  public static boolean equals(float[] field1, float[] field2) {
+    if (field1 == null || field1.length == 0) {
+      return field2 == null || field2.length == 0;
+    } else {
+      return Arrays.equals(field1, field2);
+    }
+  }
+
+  /**
+   * Checks repeated double field equality; null-value and 0-length fields are
+   * considered equal.
+   */
+  public static boolean equals(double[] field1, double[] field2) {
+    if (field1 == null || field1.length == 0) {
+      return field2 == null || field2.length == 0;
+    } else {
+      return Arrays.equals(field1, field2);
+    }
+  }
+
+  /**
+   * Checks repeated boolean field equality; null-value and 0-length fields are
+   * considered equal.
+   */
+  public static boolean equals(boolean[] field1, boolean[] field2) {
+    if (field1 == null || field1.length == 0) {
+      return field2 == null || field2.length == 0;
+    } else {
+      return Arrays.equals(field1, field2);
+    }
+  }
+
+  /**
+   * Checks repeated bytes field equality. Only non-null elements are tested.
+   * Returns true if the two fields have the same sequence of non-null
+   * elements. Null-value fields and fields of any length with only null
+   * elements are considered equal.
+   */
+  public static boolean equals(byte[][] field1, byte[][] field2) {
+    int index1 = 0;
+    int length1 = field1 == null ? 0 : field1.length;
+    int index2 = 0;
+    int length2 = field2 == null ? 0 : field2.length;
+    while (true) {
+      while (index1 < length1 && field1[index1] == null) {
+        index1++;
+      }
+      while (index2 < length2 && field2[index2] == null) {
+        index2++;
+      }
+      boolean atEndOf1 = index1 >= length1;
+      boolean atEndOf2 = index2 >= length2;
+      if (atEndOf1 && atEndOf2) {
+        // no more non-null elements to test in both arrays
+        return true;
+      } else if (atEndOf1 != atEndOf2) {
+        // one of the arrays have extra non-null elements
+        return false;
+      } else if (!Arrays.equals(field1[index1], field2[index2])) {
+        // element mismatch
+        return false;
+      }
+      index1++;
+      index2++;
+    }
+  }
+
+  /**
+   * Checks repeated string/message field equality. Only non-null elements are
+   * tested. Returns true if the two fields have the same sequence of non-null
+   * elements. Null-value fields and fields of any length with only null
+   * elements are considered equal.
+   */
+  public static boolean equals(Object[] field1, Object[] field2) {
+    int index1 = 0;
+    int length1 = field1 == null ? 0 : field1.length;
+    int index2 = 0;
+    int length2 = field2 == null ? 0 : field2.length;
+    while (true) {
+      while (index1 < length1 && field1[index1] == null) {
+        index1++;
+      }
+      while (index2 < length2 && field2[index2] == null) {
+        index2++;
+      }
+      boolean atEndOf1 = index1 >= length1;
+      boolean atEndOf2 = index2 >= length2;
+      if (atEndOf1 && atEndOf2) {
+        // no more non-null elements to test in both arrays
+        return true;
+      } else if (atEndOf1 != atEndOf2) {
+        // one of the arrays have extra non-null elements
+        return false;
+      } else if (!field1[index1].equals(field2[index2])) {
+        // element mismatch
+        return false;
+      }
+      index1++;
+      index2++;
+    }
+  }
+
+  /**
+   * Computes the hash code of a repeated int field. Null-value and 0-length
+   * fields have the same hash code.
+   */
+  public static int hashCode(int[] field) {
+    return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
+  }
+
+  /**
+   * Computes the hash code of a repeated long field. Null-value and 0-length
+   * fields have the same hash code.
+   */
+  public static int hashCode(long[] field) {
+    return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
+  }
+
+  /**
+   * Computes the hash code of a repeated float field. Null-value and 0-length
+   * fields have the same hash code.
+   */
+  public static int hashCode(float[] field) {
+    return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
+  }
+
+  /**
+   * Computes the hash code of a repeated double field. Null-value and 0-length
+   * fields have the same hash code.
+   */
+  public static int hashCode(double[] field) {
+    return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
+  }
+
+  /**
+   * Computes the hash code of a repeated boolean field. Null-value and 0-length
+   * fields have the same hash code.
+   */
+  public static int hashCode(boolean[] field) {
+    return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
+  }
+
+  /**
+   * Computes the hash code of a repeated bytes field. Only the sequence of all
+   * non-null elements are used in the computation. Null-value fields and fields
+   * of any length with only null elements have the same hash code.
+   */
+  public static int hashCode(byte[][] field) {
+    int result = 0;
+    for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) {
+      byte[] element = field[i];
+      if (element != null) {
+        result = 31 * result + Arrays.hashCode(element);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Computes the hash code of a repeated string/message field. Only the
+   * sequence of all non-null elements are used in the computation. Null-value
+   * fields and fields of any length with only null elements have the same hash
+   * code.
+   */
+  public static int hashCode(Object[] field) {
+    int result = 0;
+    for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) {
+      Object element = field[i];
+      if (element != null) {
+        result = 31 * result + element.hashCode();
+      }
+    }
+    return result;
+  }
+  private static Object primitiveDefaultValue(int type) {
+    switch (type) {
+      case TYPE_BOOL:
+        return Boolean.FALSE;
+      case TYPE_BYTES:
+        return WireFormatNano.EMPTY_BYTES;
+      case TYPE_STRING:
+        return "";
+      case TYPE_FLOAT:
+        return Float.valueOf(0);
+      case TYPE_DOUBLE:
+        return Double.valueOf(0);
+      case TYPE_ENUM:
+      case TYPE_FIXED32:
+      case TYPE_INT32:
+      case TYPE_UINT32:
+      case TYPE_SINT32:
+      case TYPE_SFIXED32:
+        return Integer.valueOf(0);
+      case TYPE_INT64:
+      case TYPE_UINT64:
+      case TYPE_SINT64:
+      case TYPE_FIXED64:
+      case TYPE_SFIXED64:
+        return Long.valueOf(0L);
+      case TYPE_MESSAGE:
+      case TYPE_GROUP:
+      default:
+        throw new IllegalArgumentException(
+            "Type: " + type + " is not a primitive type.");
+    }
+  }
+
+  /**
+   * Merges the map entry into the map field. Note this is only supposed to
+   * be called by generated messages.
+   *
+   * @param map the map field; may be null, in which case a map will be
+   *        instantiated using the {@link MapFactories.MapFactory}
+   * @param input the input byte buffer
+   * @param keyType key type, as defined in InternalNano.TYPE_*
+   * @param valueType value type, as defined in InternalNano.TYPE_*
+   * @param value an new instance of the value, if the value is a TYPE_MESSAGE;
+   *        otherwise this parameter can be null and will be ignored.
+   * @param keyTag wire tag for the key
+   * @param valueTag wire tag for the value
+   * @return the map field
+   * @throws IOException
+   */
+  @SuppressWarnings("unchecked")
+  public static final <K, V> Map<K, V> mergeMapEntry(
+      CodedInputByteBufferNano input,
+      Map<K, V> map,
+      MapFactory mapFactory,
+      int keyType,
+      int valueType,
+      V value,
+      int keyTag,
+      int valueTag) throws IOException {
+    map = mapFactory.forMap(map);
+    final int length = input.readRawVarint32();
+    final int oldLimit = input.pushLimit(length);
+    K key = null;
+    while (true) {
+      int tag = input.readTag();
+      if (tag == 0) {
+        break;
+      }
+      if (tag == keyTag) {
+        key = (K) input.readPrimitiveField(keyType);
+      } else if (tag == valueTag) {
+        if (valueType == TYPE_MESSAGE) {
+          input.readMessage((MessageNano) value);
+        } else {
+          value = (V) input.readPrimitiveField(valueType);
+        }
+      } else {
+        if (!input.skipField(tag)) {
+          break;
+        }
+      }
+    }
+    input.checkLastTagWas(0);
+    input.popLimit(oldLimit);
+
+    if (key == null) {
+      // key can only be primitive types.
+      key = (K) primitiveDefaultValue(keyType);
+    }
+
+    if (value == null) {
+      // message type value will be initialized by code-gen.
+      value = (V) primitiveDefaultValue(valueType);
+    }
+
+    map.put(key, value);
+    return map;
+  }
+
+  public static <K, V> void serializeMapField(
+      CodedOutputByteBufferNano output,
+      Map<K, V> map, int number, int keyType, int valueType)
+          throws IOException {
+    for (Entry<K, V> entry: map.entrySet()) {
+      K key = entry.getKey();
+      V value = entry.getValue();
+      if (key == null || value == null) {
+        throw new IllegalStateException(
+            "keys and values in maps cannot be null");
+      }
+      int entrySize =
+          CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+          CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+      output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+      output.writeRawVarint32(entrySize);
+      output.writeField(1, keyType, key);
+      output.writeField(2, valueType, value);
+    }
+  }
+
+  public static <K, V> int computeMapFieldSize(
+      Map<K, V> map, int number, int keyType, int valueType) {
+    int size = 0;
+    int tagSize = CodedOutputByteBufferNano.computeTagSize(number);
+    for (Entry<K, V> entry: map.entrySet()) {
+      K key = entry.getKey();
+      V value = entry.getValue();
+      if (key == null || value == null) {
+        throw new IllegalStateException(
+            "keys and values in maps cannot be null");
+      }
+      int entrySize =
+          CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+          CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+      size += tagSize + entrySize
+          + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize);
+    }
+    return size;
+  }
+
+  /**
+   * Checks whether two {@link Map} are equal. We don't use the default equals
+   * method of {@link Map} because it compares by identity not by content for
+   * byte arrays.
+   */
+  public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+    if (a == b) {
+      return true;
+    }
+    if (a == null) {
+      return b.size() == 0;
+    }
+    if (b == null) {
+      return a.size() == 0;
+    }
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (Entry<K, V> entry : a.entrySet()) {
+      if (!b.containsKey(entry.getKey())) {
+        return false;
+      }
+      if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static boolean equalsMapValue(Object a, Object b) {
+    if (a == null || b == null) {
+      throw new IllegalStateException(
+          "keys and values in maps cannot be null");
+    }
+    if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[]) a, (byte[]) b);
+    }
+    return a.equals(b);
+  }
+
+  public static <K, V> int hashCode(Map<K, V> map) {
+    if (map == null) {
+      return 0;
+    }
+    int result = 0;
+    for (Entry<K, V> entry : map.entrySet()) {
+      result += hashCodeForMap(entry.getKey())
+          ^ hashCodeForMap(entry.getValue());
+    }
+    return result;
+  }
+
+  private static int hashCodeForMap(Object o) {
+    if (o instanceof byte[]) {
+      return Arrays.hashCode((byte[]) o);
+    }
+    return o.hashCode();
+  }
+
+  // This avoids having to make FieldArray public.
+  public static void cloneUnknownFieldData(ExtendableMessageNano original,
+      ExtendableMessageNano cloned) {
+    if (original.unknownFieldData != null) {
+      cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone();
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
new file mode 100644
index 0000000..3864d38
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a protocol message being parsed is invalid in some way,
+ * e.g. it contains a malformed varint or a negative byte length.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class InvalidProtocolBufferNanoException extends IOException {
+  private static final long serialVersionUID = -1616151763072450476L;
+
+  public InvalidProtocolBufferNanoException(final String description) {
+    super(description);
+  }
+
+  static InvalidProtocolBufferNanoException truncatedMessage() {
+    return new InvalidProtocolBufferNanoException(
+      "While parsing a protocol message, the input ended unexpectedly " +
+      "in the middle of a field.  This could mean either than the " +
+      "input has been truncated or that an embedded message " +
+      "misreported its own length.");
+  }
+
+  static InvalidProtocolBufferNanoException negativeSize() {
+    return new InvalidProtocolBufferNanoException(
+      "CodedInputStream encountered an embedded string or message " +
+      "which claimed to have negative size.");
+  }
+
+  static InvalidProtocolBufferNanoException malformedVarint() {
+    return new InvalidProtocolBufferNanoException(
+      "CodedInputStream encountered a malformed varint.");
+  }
+
+  static InvalidProtocolBufferNanoException invalidTag() {
+    return new InvalidProtocolBufferNanoException(
+      "Protocol message contained an invalid tag (zero).");
+  }
+
+  static InvalidProtocolBufferNanoException invalidEndTag() {
+    return new InvalidProtocolBufferNanoException(
+      "Protocol message end-group tag did not match expected tag.");
+  }
+
+  static InvalidProtocolBufferNanoException invalidWireType() {
+    return new InvalidProtocolBufferNanoException(
+      "Protocol message tag had invalid wire type.");
+  }
+
+  static InvalidProtocolBufferNanoException recursionLimitExceeded() {
+    return new InvalidProtocolBufferNanoException(
+      "Protocol message had too many levels of nesting.  May be malicious.  " +
+      "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+  }
+
+  static InvalidProtocolBufferNanoException sizeLimitExceeded() {
+    return new InvalidProtocolBufferNanoException(
+      "Protocol message was too large.  May be malicious.  " +
+      "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
new file mode 100644
index 0000000..98fa487
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for maps support.
+ */
+public final class MapFactories {
+  public static interface MapFactory {
+    <K, V> Map<K, V> forMap(Map<K, V> oldMap);
+  }
+
+  // NOTE(liujisi): The factory setter is temporarily marked as package private.
+  // The way to provide customized implementations of maps for different
+  // platforms are still under discussion.  Mark it as private to avoid exposing
+  // the API in proto3 alpha release.
+  /* public */ static void setMapFactory(MapFactory newMapFactory) {
+    mapFactory = newMapFactory;
+  }
+
+  public static MapFactory getMapFactory() {
+    return mapFactory;
+  }
+
+  private static class DefaultMapFactory implements MapFactory {
+    public <K, V> Map<K, V> forMap(Map<K, V> oldMap) {
+      if (oldMap == null) {
+        return new HashMap<K, V>();
+      }
+      return oldMap;
+    }
+  }
+  private static volatile MapFactory mapFactory = new DefaultMapFactory();
+
+  private MapFactories() {}
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java
new file mode 100644
index 0000000..2347502
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java
@@ -0,0 +1,198 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * @author wink@google.com Wink Saville
+ */
+public abstract class MessageNano {
+    protected volatile int cachedSize = -1;
+
+    /**
+     * Get the number of bytes required to encode this message.
+     * Returns the cached size or calls getSerializedSize which
+     * sets the cached size. This is used internally when serializing
+     * so the size is only computed once. If a member is modified
+     * then this could be stale call getSerializedSize if in doubt.
+     */
+    public int getCachedSize() {
+        if (cachedSize < 0) {
+            // getSerializedSize sets cachedSize
+            getSerializedSize();
+        }
+        return cachedSize;
+    }
+
+    /**
+     * Computes the number of bytes required to encode this message.
+     * The size is cached and the cached result can be retrieved
+     * using getCachedSize().
+     */
+    public int getSerializedSize() {
+        int size = computeSerializedSize();
+        cachedSize = size;
+        return size;
+    }
+
+    /**
+     * Computes the number of bytes required to encode this message. This does not update the
+     * cached size.
+     */
+    protected int computeSerializedSize() {
+      // This is overridden if the generated message has serialized fields.
+      return 0;
+    }
+
+    /**
+     * Serializes the message and writes it to {@code output}.
+     *
+     * @param output the output to receive the serialized form.
+     * @throws IOException if an error occurred writing to {@code output}.
+     */
+    public void writeTo(CodedOutputByteBufferNano output) throws IOException {
+        // Does nothing by default. Overridden by subclasses which have data to write.
+    }
+
+    /**
+     * Parse {@code input} as a message of this type and merge it with the
+     * message being built.
+     */
+    public abstract MessageNano mergeFrom(CodedInputByteBufferNano input) throws IOException;
+
+    /**
+     * Serialize to a byte array.
+     * @return byte array with the serialized data.
+     */
+    public static final byte[] toByteArray(MessageNano msg) {
+        final byte[] result = new byte[msg.getSerializedSize()];
+        toByteArray(msg, result, 0, result.length);
+        return result;
+    }
+
+    /**
+     * Serialize to a byte array starting at offset through length. The
+     * method getSerializedSize must have been called prior to calling
+     * this method so the proper length is know.  If an attempt to
+     * write more than length bytes OutOfSpaceException will be thrown
+     * and if length bytes are not written then IllegalStateException
+     * is thrown.
+     */
+    public static final void toByteArray(MessageNano msg, byte[] data, int offset, int length) {
+        try {
+            final CodedOutputByteBufferNano output =
+                CodedOutputByteBufferNano.newInstance(data, offset, length);
+            msg.writeTo(output);
+            output.checkNoSpaceLeft();
+        } catch (IOException e) {
+            throw new RuntimeException("Serializing to a byte array threw an IOException "
+                    + "(should never happen).", e);
+        }
+    }
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.
+     */
+    public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data)
+        throws InvalidProtocolBufferNanoException {
+        return mergeFrom(msg, data, 0, data.length);
+    }
+
+    /**
+     * Parse {@code data} as a message of this type and merge it with the
+     * message being built.
+     */
+    public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data,
+            final int off, final int len) throws InvalidProtocolBufferNanoException {
+        try {
+            final CodedInputByteBufferNano input =
+                CodedInputByteBufferNano.newInstance(data, off, len);
+            msg.mergeFrom(input);
+            input.checkLastTagWas(0);
+            return msg;
+        } catch (InvalidProtocolBufferNanoException e) {
+            throw e;
+        } catch (IOException e) {
+            throw new RuntimeException("Reading from a byte array threw an IOException (should "
+                    + "never happen).");
+        }
+    }
+
+    /**
+     * Compares two {@code MessageNano}s and returns true if the message's are the same class and
+     * have serialized form equality (i.e. all of the field values are the same).
+     */
+    public static final boolean messageNanoEquals(MessageNano a, MessageNano b) {
+        if (a == b) {
+            return true;
+        }
+        if (a == null || b == null) {
+            return false;
+        }
+        if (a.getClass() != b.getClass()) {
+          return false;
+        }
+        final int serializedSize = a.getSerializedSize();
+        if (b.getSerializedSize() != serializedSize) {
+            return false;
+        }
+        final byte[] aByteArray = new byte[serializedSize];
+        final byte[] bByteArray = new byte[serializedSize];
+        toByteArray(a, aByteArray, 0, serializedSize);
+        toByteArray(b, bByteArray, 0, serializedSize);
+        return Arrays.equals(aByteArray, bByteArray);
+    }
+
+    /**
+     * Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups
+     * (which are deprecated) are not serialized with the correct field name.
+     *
+     * <p>This is implemented using reflection, so it is not especially fast nor is it guaranteed
+     * to find all fields if you have method removal turned on for proguard.
+     */
+    @Override
+    public String toString() {
+        return MessageNanoPrinter.print(this);
+    }
+
+    /**
+     * Provides support for cloning. This only works if you specify the generate_clone method.
+     */
+    @Override
+    public MessageNano clone() throws CloneNotSupportedException {
+        return (MessageNano) super.clone();
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
new file mode 100644
index 0000000..d9500bb
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -0,0 +1,275 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+/**
+ * Static helper methods for printing nano protos.
+ *
+ * @author flynn@google.com Andrew Flynn
+ */
+public final class MessageNanoPrinter {
+    // Do not allow instantiation
+    private MessageNanoPrinter() {}
+
+    private static final String INDENT = "  ";
+    private static final int MAX_STRING_LEN = 200;
+
+    /**
+     * Returns an text representation of a MessageNano suitable for debugging. The returned string
+     * is mostly compatible with Protocol Buffer's TextFormat (as provided by non-nano protocol
+     * buffers) -- groups (which are deprecated) are output with an underscore name (e.g. foo_bar
+     * instead of FooBar) and will thus not parse.
+     *
+     * <p>Employs Java reflection on the given object and recursively prints primitive fields,
+     * groups, and messages.</p>
+     */
+    public static <T extends MessageNano> String print(T message) {
+        if (message == null) {
+            return "";
+        }
+
+        StringBuffer buf = new StringBuffer();
+        try {
+            print(null, message, new StringBuffer(), buf);
+        } catch (IllegalAccessException e) {
+            return "Error printing proto: " + e.getMessage();
+        } catch (InvocationTargetException e) {
+            return "Error printing proto: " + e.getMessage();
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Function that will print the given message/field into the StringBuffer.
+     * Meant to be called recursively.
+     *
+     * @param identifier the identifier to use, or {@code null} if this is the root message to
+     *        print.
+     * @param object the value to print. May in fact be a primitive value or byte array and not a
+     *        message.
+     * @param indentBuf the indentation each line should begin with.
+     * @param buf the output buffer.
+     */
+    private static void print(String identifier, Object object,
+            StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException,
+            InvocationTargetException {
+        if (object == null) {
+            // This can happen if...
+            //   - we're about to print a message, String, or byte[], but it not present;
+            //   - we're about to print a primitive, but "reftype" optional style is enabled, and
+            //     the field is unset.
+            // In both cases the appropriate behavior is to output nothing.
+        } else if (object instanceof MessageNano) {  // Nano proto message
+            int origIndentBufLength = indentBuf.length();
+            if (identifier != null) {
+                buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
+                indentBuf.append(INDENT);
+            }
+            Class<?> clazz = object.getClass();
+
+            // Proto fields follow one of two formats:
+            //
+            // 1) Public, non-static variables that do not begin or end with '_'
+            // Find and print these using declared public fields
+            for (Field field : clazz.getFields()) {
+                int modifiers = field.getModifiers();
+                String fieldName = field.getName();
+                if ("cachedSize".equals(fieldName)) {
+                    // TODO(bduff): perhaps cachedSize should have a more obscure name.
+                    continue;
+                }
+
+                if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC
+                        && (modifiers & Modifier.STATIC) != Modifier.STATIC
+                        && !fieldName.startsWith("_")
+                        && !fieldName.endsWith("_")) {
+                    Class<?> fieldType = field.getType();
+                    Object value = field.get(object);
+
+                    if (fieldType.isArray()) {
+                        Class<?> arrayType = fieldType.getComponentType();
+
+                        // bytes is special since it's not repeated, but is represented by an array
+                        if (arrayType == byte.class) {
+                            print(fieldName, value, indentBuf, buf);
+                        } else {
+                            int len = value == null ? 0 : Array.getLength(value);
+                            for (int i = 0; i < len; i++) {
+                                Object elem = Array.get(value, i);
+                                print(fieldName, elem, indentBuf, buf);
+                            }
+                        }
+                    } else {
+                        print(fieldName, value, indentBuf, buf);
+                    }
+                }
+            }
+
+            // 2) Fields that are accessed via getter methods (when accessors
+            //    mode is turned on)
+            // Find and print these using getter methods.
+            for (Method method : clazz.getMethods()) {
+                String name = method.getName();
+                // Check for the setter accessor method since getters and hazzers both have
+                // non-proto-field name collisions (hashCode() and getSerializedSize())
+                if (name.startsWith("set")) {
+                    String subfieldName = name.substring(3);
+
+                    Method hazzer = null;
+                    try {
+                        hazzer = clazz.getMethod("has" + subfieldName);
+                    } catch (NoSuchMethodException e) {
+                        continue;
+                    }
+                    // If hazzer does't exist or returns false, no need to continue
+                    if (!(Boolean) hazzer.invoke(object)) {
+                        continue;
+                    }
+
+                    Method getter = null;
+                    try {
+                        getter = clazz.getMethod("get" + subfieldName);
+                    } catch (NoSuchMethodException e) {
+                        continue;
+                    }
+
+                    print(subfieldName, getter.invoke(object), indentBuf, buf);
+                }
+            }
+            if (identifier != null) {
+                indentBuf.setLength(origIndentBufLength);
+                buf.append(indentBuf).append(">\n");
+            }
+        } else if (object instanceof Map) {
+          Map<?,?> map = (Map<?,?>) object;
+          identifier = deCamelCaseify(identifier);
+
+          for (Map.Entry<?,?> entry : map.entrySet()) {
+            buf.append(indentBuf).append(identifier).append(" <\n");
+            int origIndentBufLength = indentBuf.length();
+            indentBuf.append(INDENT);
+            print("key", entry.getKey(), indentBuf, buf);
+            print("value", entry.getValue(), indentBuf, buf);
+            indentBuf.setLength(origIndentBufLength);
+            buf.append(indentBuf).append(">\n");
+          }
+        } else {
+            // Non-null primitive value
+            identifier = deCamelCaseify(identifier);
+            buf.append(indentBuf).append(identifier).append(": ");
+            if (object instanceof String) {
+                String stringMessage = sanitizeString((String) object);
+                buf.append("\"").append(stringMessage).append("\"");
+            } else if (object instanceof byte[]) {
+                appendQuotedBytes((byte[]) object, buf);
+            } else {
+                buf.append(object);
+            }
+            buf.append("\n");
+        }
+    }
+
+    /**
+     * Converts an identifier of the format "FieldName" into "field_name".
+     */
+    private static String deCamelCaseify(String identifier) {
+        StringBuffer out = new StringBuffer();
+        for (int i = 0; i < identifier.length(); i++) {
+            char currentChar = identifier.charAt(i);
+            if (i == 0) {
+                out.append(Character.toLowerCase(currentChar));
+            } else if (Character.isUpperCase(currentChar)) {
+                out.append('_').append(Character.toLowerCase(currentChar));
+            } else {
+                out.append(currentChar);
+            }
+        }
+        return out.toString();
+    }
+
+    /**
+     * Shortens and escapes the given string.
+     */
+    private static String sanitizeString(String str) {
+        if (!str.startsWith("http") && str.length() > MAX_STRING_LEN) {
+            // Trim non-URL strings.
+            str = str.substring(0, MAX_STRING_LEN) + "[...]";
+        }
+        return escapeString(str);
+    }
+
+    /**
+     * Escape everything except for low ASCII code points.
+     */
+    private static String escapeString(String str) {
+        int strLen = str.length();
+        StringBuilder b = new StringBuilder(strLen);
+        for (int i = 0; i < strLen; i++) {
+            char original = str.charAt(i);
+            if (original >= ' ' && original <= '~' && original != '"' && original != '\'') {
+                b.append(original);
+            } else {
+                b.append(String.format("\\u%04x", (int) original));
+            }
+        }
+        return b.toString();
+    }
+
+    /**
+     * Appends a quoted byte array to the provided {@code StringBuffer}.
+     */
+    private static void appendQuotedBytes(byte[] bytes, StringBuffer builder) {
+        if (bytes == null) {
+            builder.append("\"\"");
+            return;
+        }
+
+        builder.append('"');
+        for (int i = 0; i < bytes.length; ++i) {
+            int ch = bytes[i] & 0xff;
+            if (ch == '\\' || ch == '"') {
+                builder.append('\\').append((char) ch);
+            } else if (ch >= 32 && ch < 127) {
+                builder.append((char) ch);
+            } else {
+                builder.append(String.format("\\%03o", ch));
+            }
+        }
+        builder.append('"');
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
new file mode 100644
index 0000000..b1678d1
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
@@ -0,0 +1,88 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Stores unknown fields. These might be extensions or fields that the generated
+ * API doesn't know about yet.
+ *
+ * @author bduff@google.com (Brian Duff)
+ */
+final class UnknownFieldData {
+
+    final int tag;
+    /**
+     * Important: this should be treated as immutable, even though it's possible
+     * to change the array values.
+     */
+    final byte[] bytes;
+
+    UnknownFieldData(int tag, byte[] bytes) {
+        this.tag = tag;
+        this.bytes = bytes;
+    }
+
+    int computeSerializedSize() {
+        int size = 0;
+        size += CodedOutputByteBufferNano.computeRawVarint32Size(tag);
+        size += bytes.length;
+        return size;
+    }
+
+    void writeTo(CodedOutputByteBufferNano output) throws IOException {
+        output.writeRawVarint32(tag);
+        output.writeRawBytes(bytes);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof UnknownFieldData)) {
+            return false;
+        }
+
+        UnknownFieldData other = (UnknownFieldData) o;
+        return tag == other.tag && Arrays.equals(bytes, other.bytes);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + tag;
+        result = 31 * result + Arrays.hashCode(bytes);
+        return result;
+    }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java
new file mode 100644
index 0000000..bbb6370
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java
@@ -0,0 +1,124 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import java.io.IOException;
+
+/**
+ * This class is used internally by the Protocol Buffer library and generated
+ * message implementations.  It is public only because those generated messages
+ * do not reside in the {@code protobuf} package.  Others should not use this
+ * class directly.
+ *
+ * This class contains constants and helper functions useful for dealing with
+ * the Protocol Buffer wire format.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class WireFormatNano {
+  // Do not allow instantiation.
+  private WireFormatNano() {}
+
+  static final int WIRETYPE_VARINT           = 0;
+  static final int WIRETYPE_FIXED64          = 1;
+  static final int WIRETYPE_LENGTH_DELIMITED = 2;
+  static final int WIRETYPE_START_GROUP      = 3;
+  static final int WIRETYPE_END_GROUP        = 4;
+  static final int WIRETYPE_FIXED32          = 5;
+
+  static final int TAG_TYPE_BITS = 3;
+  static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
+
+  /** Given a tag value, determines the wire type (the lower 3 bits). */
+  static int getTagWireType(final int tag) {
+    return tag & TAG_TYPE_MASK;
+  }
+
+  /** Given a tag value, determines the field number (the upper 29 bits). */
+  public static int getTagFieldNumber(final int tag) {
+    return tag >>> TAG_TYPE_BITS;
+  }
+
+  /** Makes a tag value given a field number and wire type. */
+  static int makeTag(final int fieldNumber, final int wireType) {
+    return (fieldNumber << TAG_TYPE_BITS) | wireType;
+  }
+
+  public static final int EMPTY_INT_ARRAY[] = {};
+  public static final long EMPTY_LONG_ARRAY[] = {};
+  public static final float EMPTY_FLOAT_ARRAY[] = {};
+  public static final double EMPTY_DOUBLE_ARRAY[] = {};
+  public static final boolean EMPTY_BOOLEAN_ARRAY[] = {};
+  public static final String EMPTY_STRING_ARRAY[] = {};
+  public static final byte[] EMPTY_BYTES_ARRAY[] = {};
+  public static final byte[] EMPTY_BYTES = {};
+
+  /**
+   * Parses an unknown field. This implementation skips the field.
+   *
+   * <p>Generated messages will call this for unknown fields if the store_unknown_fields
+   * option is off.
+   *
+   * @return {@literal true} unless the tag is an end-group tag.
+   */
+  public static boolean parseUnknownField(
+      final CodedInputByteBufferNano input,
+      final int tag) throws IOException {
+    return input.skipField(tag);
+  }
+
+  /**
+   * Computes the array length of a repeated field. We assume that in the common case repeated
+   * fields are contiguously serialized but we still correctly handle interspersed values of a
+   * repeated field (but with extra allocations).
+   *
+   * Rewinds to current input position before returning.
+   *
+   * @param input stream input, pointing to the byte after the first tag
+   * @param tag repeated field tag just read
+   * @return length of array
+   * @throws IOException
+   */
+  public static final int getRepeatedFieldArrayLength(
+      final CodedInputByteBufferNano input,
+      final int tag) throws IOException {
+    int arrayLength = 1;
+    int startPos = input.getPosition();
+    input.skipField(tag);
+    while (input.readTag() == tag) {
+      input.skipField(tag);
+      arrayLength++;
+    }
+    input.rewindToPosition(startPos);
+    return arrayLength;
+  }
+
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
new file mode 100644
index 0000000..debf7c0
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
@@ -0,0 +1,4468 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+package com.google.protobuf.nano;
+
+import com.google.protobuf.nano.MapTestProto.TestMap;
+import com.google.protobuf.nano.CodedOutputByteBufferNano;
+import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue;
+import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors;
+import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
+import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
+import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano;
+import com.google.protobuf.nano.NanoReferenceTypesCompat;
+import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano;
+import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano;
+import com.google.protobuf.nano.testext.nano.Extensions;
+import com.google.protobuf.nano.testext.nano.Extensions.AnotherMessage;
+import com.google.protobuf.nano.testext.nano.Extensions.MessageWithGroup;
+import com.google.protobuf.nano.testimport.nano.UnittestImportNano;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Test nano runtime.
+ *
+ * @author ulas@google.com Ulas Kirazci
+ */
+public class NanoTest extends TestCase {
+  @Override
+  public void setUp() throws Exception {
+  }
+
+  public void testSimpleMessageNano() throws Exception {
+    SimpleMessageNano msg = new SimpleMessageNano();
+    assertEquals(123, msg.d);
+    assertEquals(null, msg.nestedMsg);
+    assertEquals(SimpleMessageNano.BAZ, msg.defaultNestedEnum);
+
+    msg.d = 456;
+    assertEquals(456, msg.d);
+
+    SimpleMessageNano.NestedMessage nestedMsg = new SimpleMessageNano.NestedMessage();
+    nestedMsg.bb = 2;
+    assertEquals(2, nestedMsg.bb);
+    msg.nestedMsg = nestedMsg;
+    assertEquals(2, msg.nestedMsg.bb);
+
+    msg.defaultNestedEnum = SimpleMessageNano.BAR;
+    assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    SimpleMessageNano newMsg = SimpleMessageNano.parseFrom(result);
+    assertEquals(456, newMsg.d);
+    assertEquals(2, msg.nestedMsg.bb);
+    assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+
+    msg.nestedMsg = null;
+    assertTrue(msgSerializedSize != msg.getSerializedSize());
+
+    msg.clear();
+    assertEquals(0, msg.getSerializedSize());
+  }
+
+  public void testRecursiveMessageNano() throws Exception {
+    RecursiveMessageNano msg = new RecursiveMessageNano();
+    assertTrue(msg.repeatedRecursiveMessageNano.length == 0);
+
+    RecursiveMessageNano msg1 = new RecursiveMessageNano();
+    msg1.id = 1;
+    assertEquals(1, msg1.id);
+    RecursiveMessageNano msg2 = new RecursiveMessageNano();
+    msg2.id = 2;
+    RecursiveMessageNano msg3 = new RecursiveMessageNano();
+    msg3.id = 3;
+
+    RecursiveMessageNano.NestedMessage nestedMsg = new RecursiveMessageNano.NestedMessage();
+    nestedMsg.a = msg1;
+    assertEquals(1, nestedMsg.a.id);
+
+    msg.id = 0;
+    msg.nestedMessage = nestedMsg;
+    msg.optionalRecursiveMessageNano = msg2;
+    msg.repeatedRecursiveMessageNano = new RecursiveMessageNano[] { msg3 };
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 16);
+    assertEquals(result.length, msgSerializedSize);
+
+    RecursiveMessageNano newMsg = RecursiveMessageNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedRecursiveMessageNano.length);
+
+    assertEquals(0, newMsg.id);
+    assertEquals(1, newMsg.nestedMessage.a.id);
+    assertEquals(2, newMsg.optionalRecursiveMessageNano.id);
+    assertEquals(3, newMsg.repeatedRecursiveMessageNano[0].id);
+  }
+
+  public void testMessageNoFields() {
+    SingleMessageNano msg = new SingleMessageNano();
+    assertEquals(0, msg.getSerializedSize());
+    assertEquals(0, MessageNano.toByteArray(msg).length);
+  }
+
+  public void testNanoRequiredInt32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.id = 123;
+    assertEquals(123, msg.id);
+    msg.clear().id = 456;
+    assertEquals(456, msg.id);
+    msg.clear();
+
+    msg.id = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 3);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.id);
+  }
+
+  public void testNanoOptionalInt32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalInt32 = 123;
+    assertEquals(123, msg.optionalInt32);
+    msg.clear()
+       .optionalInt32 = 456;
+    assertEquals(456, msg.optionalInt32);
+    msg.clear();
+
+    msg.optionalInt32 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 5);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalInt32);
+  }
+
+  public void testNanoOptionalInt64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalInt64 = 123;
+    assertEquals(123, msg.optionalInt64);
+    msg.clear()
+       .optionalInt64 = 456;
+    assertEquals(456, msg.optionalInt64);
+    msg.clear();
+    assertEquals(0, msg.optionalInt64);
+
+    msg.optionalInt64 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 5);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalInt64);
+  }
+
+  public void testNanoOptionalUint32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalUint32 = 123;
+    assertEquals(123, msg.optionalUint32);
+    msg.clear()
+       .optionalUint32 = 456;
+    assertEquals(456, msg.optionalUint32);
+    msg.clear();
+    assertEquals(0, msg.optionalUint32);
+
+    msg.optionalUint32 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 5);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalUint32);
+  }
+
+  public void testNanoOptionalUint64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalUint64 = 123;
+    assertEquals(123, msg.optionalUint64);
+    msg.clear()
+       .optionalUint64 = 456;
+    assertEquals(456, msg.optionalUint64);
+    msg.clear();
+    assertEquals(0, msg.optionalUint64);
+
+    msg.optionalUint64 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 5);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalUint64);
+  }
+
+  public void testNanoOptionalSint32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalSint32 = 123;
+    assertEquals(123, msg.optionalSint32);
+    msg.clear()
+       .optionalSint32 = 456;
+    assertEquals(456, msg.optionalSint32);
+    msg.clear();
+    assertEquals(0, msg.optionalSint32);
+
+    msg.optionalSint32 = -123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(-123, newMsg.optionalSint32);
+  }
+
+  public void testNanoOptionalSint64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalSint64 = 123;
+    assertEquals(123, msg.optionalSint64);
+    msg.clear()
+       .optionalSint64 = 456;
+    assertEquals(456, msg.optionalSint64);
+    msg.clear();
+    assertEquals(0, msg.optionalSint64);
+
+    msg.optionalSint64 = -123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(-123, newMsg.optionalSint64);
+  }
+
+  public void testNanoOptionalFixed32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalFixed32 = 123;
+    assertEquals(123, msg.optionalFixed32);
+    msg.clear()
+       .optionalFixed32 = 456;
+    assertEquals(456, msg.optionalFixed32);
+    msg.clear();
+    assertEquals(0, msg.optionalFixed32);
+
+    msg.optionalFixed32 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalFixed32);
+  }
+
+  public void testNanoOptionalFixed64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalFixed64 = 123;
+    assertEquals(123, msg.optionalFixed64);
+    msg.clear()
+       .optionalFixed64 = 456;
+    assertEquals(456, msg.optionalFixed64);
+    msg.clear();
+    assertEquals(0, msg.optionalFixed64);
+
+    msg.optionalFixed64 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 12);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalFixed64);
+  }
+
+  public void testNanoOptionalSfixed32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalSfixed32 = 123;
+    assertEquals(123, msg.optionalSfixed32);
+    msg.clear()
+       .optionalSfixed32 = 456;
+    assertEquals(456, msg.optionalSfixed32);
+    msg.clear();
+    assertEquals(0, msg.optionalSfixed32);
+
+    msg.optionalSfixed32 = 123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(123, newMsg.optionalSfixed32);
+  }
+
+  public void testNanoOptionalSfixed64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalSfixed64 = 123;
+    assertEquals(123, msg.optionalSfixed64);
+    msg.clear()
+       .optionalSfixed64 = 456;
+    assertEquals(456, msg.optionalSfixed64);
+    msg.clear();
+    assertEquals(0, msg.optionalSfixed64);
+
+    msg.optionalSfixed64 = -123;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 12);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(-123, newMsg.optionalSfixed64);
+  }
+
+  public void testNanoOptionalFloat() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalFloat = 123f;
+    assertTrue(123.0f == msg.optionalFloat);
+    msg.clear()
+       .optionalFloat = 456.0f;
+    assertTrue(456.0f == msg.optionalFloat);
+    msg.clear();
+    assertTrue(0.0f == msg.optionalFloat);
+
+    msg.optionalFloat = -123.456f;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(-123.456f == newMsg.optionalFloat);
+  }
+
+  public void testNanoOptionalDouble() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalDouble = 123;
+    assertTrue(123.0 == msg.optionalDouble);
+    msg.clear()
+       .optionalDouble = 456.0;
+    assertTrue(456.0 == msg.optionalDouble);
+    msg.clear();
+    assertTrue(0.0 == msg.optionalDouble);
+
+    msg.optionalDouble = -123.456;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 12);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(-123.456 == newMsg.optionalDouble);
+  }
+
+  public void testNanoOptionalBool() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalBool = true;
+    assertTrue(msg.optionalBool);
+    msg.clear()
+       .optionalBool = true;
+    assertTrue(msg.optionalBool);
+    msg.clear();
+    assertFalse(msg.optionalBool);
+
+    msg.optionalBool = true;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 5);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalBool);
+  }
+
+  public void testNanoOptionalString() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalString = "hello";
+    assertEquals("hello", msg.optionalString);
+    msg.clear();
+    assertTrue(msg.optionalString.isEmpty());
+    msg.clear()
+       .optionalString = "hello2";
+    assertEquals("hello2", msg.optionalString);
+    msg.clear();
+    assertTrue(msg.optionalString.isEmpty());
+
+    msg.optionalString = "bye";
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalString != null);
+    assertEquals("bye", newMsg.optionalString);
+  }
+
+  public void testNanoOptionalBytes() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertFalse(msg.optionalBytes.length > 0);
+    msg.optionalBytes = InternalNano.copyFromUtf8("hello");
+    assertTrue(msg.optionalBytes.length > 0);
+    assertEquals("hello", new String(msg.optionalBytes, InternalNano.UTF_8));
+    msg.clear();
+    assertFalse(msg.optionalBytes.length > 0);
+    msg.clear()
+       .optionalBytes = InternalNano.copyFromUtf8("hello");
+    assertTrue(msg.optionalBytes.length > 0);
+    msg.clear();
+    assertFalse(msg.optionalBytes.length > 0);
+
+    msg.optionalBytes = InternalNano.copyFromUtf8("bye");
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalBytes.length > 0);
+    assertEquals("bye", new String(newMsg.optionalBytes, InternalNano.UTF_8));
+  }
+
+  public void testNanoOptionalGroup() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    TestAllTypesNano.OptionalGroup grp = new TestAllTypesNano.OptionalGroup();
+    grp.a = 1;
+    assertFalse(msg.optionalGroup != null);
+    msg.optionalGroup = grp;
+    assertTrue(msg.optionalGroup != null);
+    assertEquals(1, msg.optionalGroup.a);
+    msg.clear();
+    assertFalse(msg.optionalGroup != null);
+    msg.clear()
+       .optionalGroup = new TestAllTypesNano.OptionalGroup();
+    msg.optionalGroup.a = 2;
+    assertTrue(msg.optionalGroup != null);
+    msg.clear();
+    assertFalse(msg.optionalGroup != null);
+
+    msg.optionalGroup = grp;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalGroup != null);
+    assertEquals(1, newMsg.optionalGroup.a);
+  }
+
+  public void testNanoOptionalGroupWithUnknownFieldsEnabled() throws Exception {
+    MessageWithGroup msg = new MessageWithGroup();
+    MessageWithGroup.Group grp = new MessageWithGroup.Group();
+    grp.a = 1;
+    msg.group = grp;
+    byte [] serialized = MessageNano.toByteArray(msg);
+
+    MessageWithGroup parsed = MessageWithGroup.parseFrom(serialized);
+    assertEquals(1, parsed.group.a);
+
+    byte [] serialized2 = MessageNano.toByteArray(parsed);
+    assertEquals(serialized.length, serialized2.length);
+    MessageWithGroup parsed2 = MessageWithGroup.parseFrom(serialized2);
+    assertEquals(1, parsed2.group.a);
+  }
+
+  public void testNanoOptionalNestedMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    TestAllTypesNano.NestedMessage nestedMsg = new TestAllTypesNano.NestedMessage();
+    nestedMsg.bb = 1;
+    assertFalse(msg.optionalNestedMessage != null);
+    msg.optionalNestedMessage = nestedMsg;
+    assertTrue(msg.optionalNestedMessage != null);
+    assertEquals(1, msg.optionalNestedMessage.bb);
+    msg.clear();
+    assertFalse(msg.optionalNestedMessage != null);
+    msg.clear()
+       .optionalNestedMessage = new TestAllTypesNano.NestedMessage();
+    msg.optionalNestedMessage.bb = 2;
+    assertTrue(msg.optionalNestedMessage != null);
+    msg.clear();
+    assertFalse(msg.optionalNestedMessage != null);
+
+    msg.optionalNestedMessage = nestedMsg;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalNestedMessage != null);
+    assertEquals(1, newMsg.optionalNestedMessage.bb);
+  }
+
+  public void testNanoOptionalForeignMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    NanoOuterClass.ForeignMessageNano nestedMsg = new NanoOuterClass.ForeignMessageNano();
+    nestedMsg.c = 1;
+    assertFalse(msg.optionalForeignMessage != null);
+    msg.optionalForeignMessage = nestedMsg;
+    assertTrue(msg.optionalForeignMessage != null);
+    assertEquals(1, msg.optionalForeignMessage.c);
+    msg.clear();
+    assertFalse(msg.optionalForeignMessage != null);
+    msg.clear()
+       .optionalForeignMessage = new NanoOuterClass.ForeignMessageNano();
+    msg.optionalForeignMessage.c = 2;
+    assertTrue(msg.optionalForeignMessage != null);
+    msg.clear();
+    assertFalse(msg.optionalForeignMessage != null);
+
+    msg.optionalForeignMessage = nestedMsg;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalForeignMessage != null);
+    assertEquals(1, newMsg.optionalForeignMessage.c);
+  }
+
+  public void testNanoOptionalImportMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    UnittestImportNano.ImportMessageNano nestedMsg = new UnittestImportNano.ImportMessageNano();
+    nestedMsg.d = 1;
+    assertFalse(msg.optionalImportMessage != null);
+    msg.optionalImportMessage = nestedMsg;
+    assertTrue(msg.optionalImportMessage != null);
+    assertEquals(1, msg.optionalImportMessage.d);
+    msg.clear();
+    assertFalse(msg.optionalImportMessage != null);
+    msg.clear()
+       .optionalImportMessage = new UnittestImportNano.ImportMessageNano();
+    msg.optionalImportMessage.d = 2;
+    assertTrue(msg.optionalImportMessage != null);
+    msg.clear();
+    assertFalse(msg.optionalImportMessage != null);
+
+    msg.optionalImportMessage = nestedMsg;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalImportMessage != null);
+    assertEquals(1, newMsg.optionalImportMessage.d);
+  }
+
+  public void testNanoOptionalNestedEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalNestedEnum = TestAllTypesNano.BAR;
+    assertEquals(TestAllTypesNano.BAR, msg.optionalNestedEnum);
+    msg.clear()
+       .optionalNestedEnum = TestAllTypesNano.BAZ;
+    assertEquals(TestAllTypesNano.BAZ, msg.optionalNestedEnum);
+    msg.clear();
+    assertEquals(TestAllTypesNano.FOO, msg.optionalNestedEnum);
+
+    msg.optionalNestedEnum = TestAllTypesNano.BAR;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(TestAllTypesNano.BAR, newMsg.optionalNestedEnum);
+  }
+
+  public void testNanoOptionalForeignEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR;
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.optionalForeignEnum);
+    msg.clear()
+       .optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAZ;
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.optionalForeignEnum);
+    msg.clear();
+    assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.optionalForeignEnum);
+
+    msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, newMsg.optionalForeignEnum);
+  }
+
+  public void testNanoOptionalImportEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR;
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.optionalImportEnum);
+    msg.clear()
+       .optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAZ;
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.optionalImportEnum);
+    msg.clear();
+    assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.optionalImportEnum);
+
+    msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR;
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAR, newMsg.optionalImportEnum);
+  }
+
+  public void testNanoOptionalStringPiece() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalStringPiece = "hello";
+    assertEquals("hello", msg.optionalStringPiece);
+    msg.clear();
+    assertTrue(msg.optionalStringPiece.isEmpty());
+    msg.clear()
+       .optionalStringPiece = "hello2";
+    assertEquals("hello2", msg.optionalStringPiece);
+    msg.clear();
+    assertTrue(msg.optionalStringPiece.isEmpty());
+
+    msg.optionalStringPiece = "bye";
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalStringPiece != null);
+    assertEquals("bye", newMsg.optionalStringPiece);
+  }
+
+  public void testNanoOptionalCord() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalCord = "hello";
+    assertEquals("hello", msg.optionalCord);
+    msg.clear();
+    assertTrue(msg.optionalCord.isEmpty());
+    msg.clear()
+       .optionalCord = "hello2";
+    assertEquals("hello2", msg.optionalCord);
+    msg.clear();
+    assertTrue(msg.optionalCord.isEmpty());
+
+    msg.optionalCord = "bye";
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertTrue(newMsg.optionalCord != null);
+    assertEquals("bye", newMsg.optionalCord);
+  }
+
+  public void testNanoRepeatedInt32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedInt32.length);
+    msg.repeatedInt32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedInt32[1]);
+    assertEquals(456, msg.repeatedInt32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedInt32.length);
+    msg.clear()
+       .repeatedInt32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedInt32.length);
+    assertEquals(456, msg.repeatedInt32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedInt32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedInt32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedInt32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedInt32.length);
+    assertEquals(123, newMsg.repeatedInt32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedInt32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedInt32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedInt32.length);
+    assertEquals(123, newMsg.repeatedInt32[0]);
+    assertEquals(456, newMsg.repeatedInt32[1]);
+  }
+
+  public void testNanoRepeatedInt64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedInt64.length);
+    msg.repeatedInt64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedInt64[1]);
+    assertEquals(456, msg.repeatedInt64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedInt64.length);
+    msg.clear()
+       .repeatedInt64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedInt64.length);
+    assertEquals(456, msg.repeatedInt64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedInt64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedInt64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedInt64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedInt64.length);
+    assertEquals(123, newMsg.repeatedInt64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedInt64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedInt64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedInt64.length);
+    assertEquals(123, newMsg.repeatedInt64[0]);
+    assertEquals(456, newMsg.repeatedInt64[1]);
+  }
+
+  public void testNanoRepeatedUint32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedUint32.length);
+    msg.repeatedUint32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedUint32[1]);
+    assertEquals(456, msg.repeatedUint32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedUint32.length);
+    msg.clear()
+       .repeatedUint32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedUint32.length);
+    assertEquals(456, msg.repeatedUint32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedUint32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedUint32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedUint32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedUint32.length);
+    assertEquals(123, newMsg.repeatedUint32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedUint32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedUint32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedUint32.length);
+    assertEquals(123, newMsg.repeatedUint32[0]);
+    assertEquals(456, newMsg.repeatedUint32[1]);
+  }
+
+  public void testNanoRepeatedUint64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedUint64.length);
+    msg.repeatedUint64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedUint64[1]);
+    assertEquals(456, msg.repeatedUint64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedUint64.length);
+    msg.clear()
+       .repeatedUint64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedUint64.length);
+    assertEquals(456, msg.repeatedUint64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedUint64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedUint64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedUint64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedUint64.length);
+    assertEquals(123, newMsg.repeatedUint64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedUint64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedUint64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedUint64.length);
+    assertEquals(123, newMsg.repeatedUint64[0]);
+    assertEquals(456, newMsg.repeatedUint64[1]);
+  }
+
+  public void testNanoRepeatedSint32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedSint32.length);
+    msg.repeatedSint32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedSint32[1]);
+    assertEquals(456, msg.repeatedSint32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSint32.length);
+    msg.clear()
+       .repeatedSint32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedSint32.length);
+    assertEquals(456, msg.repeatedSint32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSint32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedSint32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedSint32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 7);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedSint32.length);
+    assertEquals(123, newMsg.repeatedSint32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedSint32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedSint32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedSint32.length);
+    assertEquals(123, newMsg.repeatedSint32[0]);
+    assertEquals(456, newMsg.repeatedSint32[1]);
+  }
+
+  public void testNanoRepeatedSint64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedSint64.length);
+    msg.repeatedSint64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedSint64[1]);
+    assertEquals(456, msg.repeatedSint64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSint64.length);
+    msg.clear()
+       .repeatedSint64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedSint64.length);
+    assertEquals(456, msg.repeatedSint64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSint64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedSint64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedSint64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 7);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedSint64.length);
+    assertEquals(123, newMsg.repeatedSint64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedSint64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedSint64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedSint64.length);
+    assertEquals(123, newMsg.repeatedSint64[0]);
+    assertEquals(456, newMsg.repeatedSint64[1]);
+  }
+
+  public void testNanoRepeatedFixed32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedFixed32.length);
+    msg.repeatedFixed32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedFixed32[1]);
+    assertEquals(456, msg.repeatedFixed32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFixed32.length);
+    msg.clear()
+       .repeatedFixed32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedFixed32.length);
+    assertEquals(456, msg.repeatedFixed32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFixed32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedFixed32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedFixed32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedFixed32.length);
+    assertEquals(123, newMsg.repeatedFixed32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedFixed32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedFixed32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 15);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedFixed32.length);
+    assertEquals(123, newMsg.repeatedFixed32[0]);
+    assertEquals(456, newMsg.repeatedFixed32[1]);
+  }
+
+  public void testNanoRepeatedFixed64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedFixed64.length);
+    msg.repeatedFixed64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedFixed64[1]);
+    assertEquals(456, msg.repeatedFixed64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFixed64.length);
+    msg.clear()
+       .repeatedFixed64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedFixed64.length);
+    assertEquals(456, msg.repeatedFixed64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFixed64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedFixed64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedFixed64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 13);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedFixed64.length);
+    assertEquals(123, newMsg.repeatedFixed64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedFixed64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedFixed64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 23);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedFixed64.length);
+    assertEquals(123, newMsg.repeatedFixed64[0]);
+    assertEquals(456, newMsg.repeatedFixed64[1]);
+  }
+
+  public void testNanoRepeatedSfixed32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedSfixed32.length);
+    msg.repeatedSfixed32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedSfixed32[1]);
+    assertEquals(456, msg.repeatedSfixed32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSfixed32.length);
+    msg.clear()
+       .repeatedSfixed32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedSfixed32.length);
+    assertEquals(456, msg.repeatedSfixed32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSfixed32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedSfixed32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedSfixed32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedSfixed32.length);
+    assertEquals(123, newMsg.repeatedSfixed32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedSfixed32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedSfixed32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 15);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedSfixed32.length);
+    assertEquals(123, newMsg.repeatedSfixed32[0]);
+    assertEquals(456, newMsg.repeatedSfixed32[1]);
+  }
+
+  public void testNanoRepeatedSfixed64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedSfixed64.length);
+    msg.repeatedSfixed64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedSfixed64[1]);
+    assertEquals(456, msg.repeatedSfixed64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSfixed64.length);
+    msg.clear()
+       .repeatedSfixed64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedSfixed64.length);
+    assertEquals(456, msg.repeatedSfixed64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedSfixed64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedSfixed64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedSfixed64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 13);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedSfixed64.length);
+    assertEquals(123, newMsg.repeatedSfixed64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedSfixed64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedSfixed64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 23);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedSfixed64.length);
+    assertEquals(123, newMsg.repeatedSfixed64[0]);
+    assertEquals(456, newMsg.repeatedSfixed64[1]);
+  }
+
+  public void testNanoRepeatedFloat() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedFloat.length);
+    msg.repeatedFloat = new float[] { 123f, 789f, 456f };
+    assertEquals(789f, msg.repeatedFloat[1]);
+    assertEquals(456f, msg.repeatedFloat[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFloat.length);
+    msg.clear()
+       .repeatedFloat = new float[] { 456f };
+    assertEquals(1, msg.repeatedFloat.length);
+    assertEquals(456f, msg.repeatedFloat[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedFloat.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedFloat = new float[] { 123f };
+    assertEquals(1, msg.repeatedFloat.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedFloat.length);
+    assertEquals(123f, newMsg.repeatedFloat[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedFloat = new float[] { 123f, 456f };
+    assertEquals(2, msg.repeatedFloat.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 15);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedFloat.length);
+    assertEquals(123f, newMsg.repeatedFloat[0]);
+    assertEquals(456f, newMsg.repeatedFloat[1]);
+  }
+
+  public void testNanoRepeatedDouble() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedDouble.length);
+    msg.repeatedDouble = new double[] { 123.0, 789.0, 456.0 };
+    assertEquals(789.0, msg.repeatedDouble[1]);
+    assertEquals(456.0, msg.repeatedDouble[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedDouble.length);
+    msg.clear()
+       .repeatedDouble = new double[] { 456.0 };
+    assertEquals(1, msg.repeatedDouble.length);
+    assertEquals(456.0, msg.repeatedDouble[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedDouble.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedDouble = new double[] { 123.0 };
+    assertEquals(1, msg.repeatedDouble.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 13);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedDouble.length);
+    assertEquals(123.0, newMsg.repeatedDouble[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedDouble = new double[] { 123.0, 456.0 };
+    assertEquals(2, msg.repeatedDouble.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 23);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedDouble.length);
+    assertEquals(123.0, newMsg.repeatedDouble[0]);
+    assertEquals(456.0, newMsg.repeatedDouble[1]);
+  }
+
+  public void testNanoRepeatedBool() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedBool.length);
+    msg.repeatedBool = new boolean[] { false, true, false };
+    assertTrue(msg.repeatedBool[1]);
+    assertFalse(msg.repeatedBool[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedBool.length);
+    msg.clear()
+       .repeatedBool = new boolean[] { true };
+    assertEquals(1, msg.repeatedBool.length);
+    assertTrue(msg.repeatedBool[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedBool.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedBool = new boolean[] { false };
+    assertEquals(1, msg.repeatedBool.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedBool.length);
+    assertFalse(newMsg.repeatedBool[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedBool = new boolean[] { true, false };
+    assertEquals(2, msg.repeatedBool.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedBool.length);
+    assertTrue(newMsg.repeatedBool[0]);
+    assertFalse(newMsg.repeatedBool[1]);
+  }
+
+  public void testNanoRepeatedString() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedString.length);
+    msg.repeatedString = new String[] { "hello", "bye", "boo" };
+    assertEquals("bye", msg.repeatedString[1]);
+    assertEquals("boo", msg.repeatedString[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedString.length);
+    msg.clear()
+       .repeatedString = new String[] { "boo" };
+    assertEquals(1, msg.repeatedString.length);
+    assertEquals("boo", msg.repeatedString[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedString.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedString = new String[] { "" };
+    assertEquals(1, msg.repeatedString.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedString.length);
+    assertTrue(newMsg.repeatedString[0].isEmpty());
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedString = new String[] { "hello", "world" };
+    assertEquals(2, msg.repeatedString.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 19);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedString.length);
+    assertEquals("hello", newMsg.repeatedString[0]);
+    assertEquals("world", newMsg.repeatedString[1]);
+  }
+
+  public void testNanoRepeatedBytes() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedBytes.length);
+    msg.repeatedBytes = new byte[][] {
+        InternalNano.copyFromUtf8("hello"),
+        InternalNano.copyFromUtf8("bye"),
+        InternalNano.copyFromUtf8("boo")
+    };
+    assertEquals("bye", new String(msg.repeatedBytes[1], InternalNano.UTF_8));
+    assertEquals("boo", new String(msg.repeatedBytes[2], InternalNano.UTF_8));
+    msg.clear();
+    assertEquals(0, msg.repeatedBytes.length);
+    msg.clear()
+       .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("boo") };
+    assertEquals(1, msg.repeatedBytes.length);
+    assertEquals("boo", new String(msg.repeatedBytes[0], InternalNano.UTF_8));
+    msg.clear();
+    assertEquals(0, msg.repeatedBytes.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("") };
+    assertEquals(1, msg.repeatedBytes.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedBytes.length);
+    assertTrue(newMsg.repeatedBytes[0].length == 0);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedBytes = new byte[][] {
+      InternalNano.copyFromUtf8("hello"),
+      InternalNano.copyFromUtf8("world")
+    };
+    assertEquals(2, msg.repeatedBytes.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 19);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedBytes.length);
+    assertEquals("hello", new String(newMsg.repeatedBytes[0], InternalNano.UTF_8));
+    assertEquals("world", new String(newMsg.repeatedBytes[1], InternalNano.UTF_8));
+  }
+
+  public void testNanoRepeatedGroup() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    TestAllTypesNano.RepeatedGroup group0 =
+      new TestAllTypesNano.RepeatedGroup();
+    group0.a = 0;
+    TestAllTypesNano.RepeatedGroup group1 =
+      new TestAllTypesNano.RepeatedGroup();
+    group1.a = 1;
+    TestAllTypesNano.RepeatedGroup group2 =
+      new TestAllTypesNano.RepeatedGroup();
+    group2.a = 2;
+
+    msg.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1, group2 };
+    assertEquals(3, msg.repeatedGroup.length);
+    assertEquals(0, msg.repeatedGroup[0].a);
+    assertEquals(1, msg.repeatedGroup[1].a);
+    assertEquals(2, msg.repeatedGroup[2].a);
+    msg.clear();
+    assertEquals(0, msg.repeatedGroup.length);
+    msg.clear()
+       .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group1 };
+    assertEquals(1, msg.repeatedGroup.length);
+    assertEquals(1, msg.repeatedGroup[0].a);
+    msg.clear();
+    assertEquals(0, msg.repeatedGroup.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0 };
+    assertEquals(1, msg.repeatedGroup.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 7);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedGroup.length);
+    assertEquals(0, newMsg.repeatedGroup[0].a);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1 };
+    assertEquals(2, msg.repeatedGroup.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 14);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedGroup.length);
+    assertEquals(0, newMsg.repeatedGroup[0].a);
+    assertEquals(1, newMsg.repeatedGroup[1].a);
+  }
+
+  public void testNanoRepeatedNestedMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    TestAllTypesNano.NestedMessage nestedMsg0 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg0.bb = 0;
+    TestAllTypesNano.NestedMessage nestedMsg1 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg1.bb = 1;
+    TestAllTypesNano.NestedMessage nestedMsg2 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg2.bb = 2;
+
+    msg.repeatedNestedMessage =
+        new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1, nestedMsg2 };
+    assertEquals(3, msg.repeatedNestedMessage.length);
+    assertEquals(0, msg.repeatedNestedMessage[0].bb);
+    assertEquals(1, msg.repeatedNestedMessage[1].bb);
+    assertEquals(2, msg.repeatedNestedMessage[2].bb);
+    msg.clear();
+    assertEquals(0, msg.repeatedNestedMessage.length);
+    msg.clear()
+       .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg1 };
+    assertEquals(1, msg.repeatedNestedMessage.length);
+    assertEquals(1, msg.repeatedNestedMessage[0].bb);
+    msg.clear();
+    assertEquals(0, msg.repeatedNestedMessage.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 };
+    assertEquals(1, msg.repeatedNestedMessage.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedNestedMessage.length);
+    assertEquals(0, newMsg.repeatedNestedMessage[0].bb);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1 };
+    assertEquals(2, msg.repeatedNestedMessage.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedNestedMessage.length);
+    assertEquals(0, newMsg.repeatedNestedMessage[0].bb);
+    assertEquals(1, newMsg.repeatedNestedMessage[1].bb);
+  }
+
+  public void testNanoRepeatedForeignMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    NanoOuterClass.ForeignMessageNano foreignMsg0 =
+      new NanoOuterClass.ForeignMessageNano();
+    foreignMsg0.c = 0;
+    NanoOuterClass.ForeignMessageNano foreignMsg1 =
+      new NanoOuterClass.ForeignMessageNano();
+    foreignMsg1.c = 1;
+    NanoOuterClass.ForeignMessageNano foreignMsg2 =
+      new NanoOuterClass.ForeignMessageNano();
+    foreignMsg2.c = 2;
+
+    msg.repeatedForeignMessage =
+        new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 };
+    assertEquals(3, msg.repeatedForeignMessage.length);
+    assertEquals(0, msg.repeatedForeignMessage[0].c);
+    assertEquals(1, msg.repeatedForeignMessage[1].c);
+    assertEquals(2, msg.repeatedForeignMessage[2].c);
+    msg.clear();
+    assertEquals(0, msg.repeatedForeignMessage.length);
+    msg.clear()
+       .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg1 };
+    assertEquals(1, msg.repeatedForeignMessage.length);
+    assertEquals(1, msg.repeatedForeignMessage[0].c);
+    msg.clear();
+    assertEquals(0, msg.repeatedForeignMessage.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0 };
+    assertEquals(1, msg.repeatedForeignMessage.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedForeignMessage.length);
+    assertEquals(0, newMsg.repeatedForeignMessage[0].c);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1 };
+    assertEquals(2, msg.repeatedForeignMessage.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedForeignMessage.length);
+    assertEquals(0, newMsg.repeatedForeignMessage[0].c);
+    assertEquals(1, newMsg.repeatedForeignMessage[1].c);
+  }
+
+  public void testNanoRepeatedImportMessage() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    UnittestImportNano.ImportMessageNano foreignMsg0 =
+      new UnittestImportNano.ImportMessageNano();
+    foreignMsg0.d = 0;
+    UnittestImportNano.ImportMessageNano foreignMsg1 =
+      new UnittestImportNano.ImportMessageNano();
+    foreignMsg1.d = 1;
+    UnittestImportNano.ImportMessageNano foreignMsg2 =
+      new UnittestImportNano.ImportMessageNano();
+    foreignMsg2.d = 2;
+
+    msg.repeatedImportMessage =
+        new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 };
+    assertEquals(3, msg.repeatedImportMessage.length);
+    assertEquals(0, msg.repeatedImportMessage[0].d);
+    assertEquals(1, msg.repeatedImportMessage[1].d);
+    assertEquals(2, msg.repeatedImportMessage[2].d);
+    msg.clear();
+    assertEquals(0, msg.repeatedImportMessage.length);
+    msg.clear()
+       .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg1 };
+    assertEquals(1, msg.repeatedImportMessage.length);
+    assertEquals(1, msg.repeatedImportMessage[0].d);
+    msg.clear();
+    assertEquals(0, msg.repeatedImportMessage.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0 };
+    assertEquals(1, msg.repeatedImportMessage.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedImportMessage.length);
+    assertEquals(0, newMsg.repeatedImportMessage[0].d);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1 };
+    assertEquals(2, msg.repeatedImportMessage.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedImportMessage.length);
+    assertEquals(0, newMsg.repeatedImportMessage[0].d);
+    assertEquals(1, newMsg.repeatedImportMessage[1].d);
+  }
+
+  public void testNanoRepeatedNestedEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedNestedEnum = new int[] {
+        TestAllTypesNano.FOO,
+        TestAllTypesNano.BAR,
+        TestAllTypesNano.BAZ
+    };
+    assertEquals(3, msg.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]);
+    assertEquals(TestAllTypesNano.BAZ, msg.repeatedNestedEnum[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedNestedEnum.length);
+    msg.clear()
+       .repeatedNestedEnum = new int[] { TestAllTypesNano.BAR };
+    assertEquals(1, msg.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedNestedEnum.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO };
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR };
+    assertEquals(2, msg.repeatedNestedEnum.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]);
+  }
+
+  public void testNanoRepeatedForeignEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedForeignEnum = new int[] {
+        NanoOuterClass.FOREIGN_NANO_FOO,
+        NanoOuterClass.FOREIGN_NANO_BAR,
+        NanoOuterClass.FOREIGN_NANO_BAZ
+    };
+    assertEquals(3, msg.repeatedForeignEnum.length);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.repeatedForeignEnum[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedForeignEnum.length);
+    msg.clear()
+       .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_BAR };
+    assertEquals(1, msg.repeatedForeignEnum.length);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedForeignEnum.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_FOO };
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedForeignEnum.length);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedForeignEnum = new int[] {
+      NanoOuterClass.FOREIGN_NANO_FOO,
+      NanoOuterClass.FOREIGN_NANO_BAR
+    };
+    assertEquals(2, msg.repeatedForeignEnum.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedForeignEnum.length);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+    assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]);
+  }
+
+  public void testNanoRepeatedImportEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedImportEnum = new int[] {
+        UnittestImportNano.IMPORT_NANO_FOO,
+        UnittestImportNano.IMPORT_NANO_BAR,
+        UnittestImportNano.IMPORT_NANO_BAZ
+    };
+    assertEquals(3, msg.repeatedImportEnum.length);
+    assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]);
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.repeatedImportEnum[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedImportEnum.length);
+    msg.clear()
+       .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_BAR };
+    assertEquals(1, msg.repeatedImportEnum.length);
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedImportEnum.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_FOO };
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedImportEnum.length);
+    assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedImportEnum = new int[] {
+      UnittestImportNano.IMPORT_NANO_FOO,
+      UnittestImportNano.IMPORT_NANO_BAR
+    };
+    assertEquals(2, msg.repeatedImportEnum.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedImportEnum.length);
+    assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+    assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]);
+  }
+
+  public void testNanoRepeatedStringPiece() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedStringPiece.length);
+    msg.repeatedStringPiece = new String[] { "hello", "bye", "boo" };
+    assertEquals("bye", msg.repeatedStringPiece[1]);
+    assertEquals("boo", msg.repeatedStringPiece[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedStringPiece.length);
+    msg.clear()
+       .repeatedStringPiece = new String[] { "boo" };
+    assertEquals(1, msg.repeatedStringPiece.length);
+    assertEquals("boo", msg.repeatedStringPiece[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedStringPiece.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedStringPiece = new String[] { "" };
+    assertEquals(1, msg.repeatedStringPiece.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedStringPiece.length);
+    assertTrue(newMsg.repeatedStringPiece[0].isEmpty());
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedStringPiece = new String[] { "hello", "world" };
+    assertEquals(2, msg.repeatedStringPiece.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 19);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedStringPiece.length);
+    assertEquals("hello", newMsg.repeatedStringPiece[0]);
+    assertEquals("world", newMsg.repeatedStringPiece[1]);
+  }
+
+  public void testNanoRepeatedCord() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedCord.length);
+    msg.repeatedCord = new String[] { "hello", "bye", "boo" };
+    assertEquals("bye", msg.repeatedCord[1]);
+    assertEquals("boo", msg.repeatedCord[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedCord.length);
+    msg.clear()
+       .repeatedCord = new String[] { "boo" };
+    assertEquals(1, msg.repeatedCord.length);
+    assertEquals("boo", msg.repeatedCord[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedCord.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedCord = new String[] { "" };
+    assertEquals(1, msg.repeatedCord.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 6);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedCord.length);
+    assertTrue(newMsg.repeatedCord[0].isEmpty());
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedCord = new String[] { "hello", "world" };
+    assertEquals(2, msg.repeatedCord.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 19);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedCord.length);
+    assertEquals("hello", newMsg.repeatedCord[0]);
+    assertEquals("world", newMsg.repeatedCord[1]);
+  }
+
+  public void testNanoRepeatedPackedInt32() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedPackedInt32.length);
+    msg.repeatedPackedInt32 = new int[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedPackedInt32[1]);
+    assertEquals(456, msg.repeatedPackedInt32[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedInt32.length);
+    msg.clear()
+       .repeatedPackedInt32 = new int[] { 456 };
+    assertEquals(1, msg.repeatedPackedInt32.length);
+    assertEquals(456, msg.repeatedPackedInt32[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedInt32.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedPackedInt32 = new int[] { 123 };
+    assertEquals(1, msg.repeatedPackedInt32.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 7);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedPackedInt32.length);
+    assertEquals(123, newMsg.repeatedPackedInt32[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedPackedInt32 = new int[] { 123, 456 };
+    assertEquals(2, msg.repeatedPackedInt32.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 9);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedPackedInt32.length);
+    assertEquals(123, newMsg.repeatedPackedInt32[0]);
+    assertEquals(456, newMsg.repeatedPackedInt32[1]);
+  }
+
+  public void testNanoRepeatedPackedSfixed64() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    assertEquals(0, msg.repeatedPackedSfixed64.length);
+    msg.repeatedPackedSfixed64 = new long[] { 123, 789, 456 };
+    assertEquals(789, msg.repeatedPackedSfixed64[1]);
+    assertEquals(456, msg.repeatedPackedSfixed64[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedSfixed64.length);
+    msg.clear()
+       .repeatedPackedSfixed64 = new long[] { 456 };
+    assertEquals(1, msg.repeatedPackedSfixed64.length);
+    assertEquals(456, msg.repeatedPackedSfixed64[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedSfixed64.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedPackedSfixed64 = new long[] { 123 };
+    assertEquals(1, msg.repeatedPackedSfixed64.length);
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 14);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedPackedSfixed64.length);
+    assertEquals(123, newMsg.repeatedPackedSfixed64[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedPackedSfixed64 = new long[] { 123, 456 };
+    assertEquals(2, msg.repeatedPackedSfixed64.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 22);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedPackedSfixed64.length);
+    assertEquals(123, newMsg.repeatedPackedSfixed64[0]);
+    assertEquals(456, newMsg.repeatedPackedSfixed64[1]);
+  }
+
+  public void testNanoRepeatedPackedNestedEnum() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedPackedNestedEnum = new int[] {
+        TestAllTypesNano.FOO,
+        TestAllTypesNano.BAR,
+        TestAllTypesNano.BAZ
+    };
+    assertEquals(3, msg.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]);
+    assertEquals(TestAllTypesNano.BAZ, msg.repeatedPackedNestedEnum[2]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedNestedEnum.length);
+    msg.clear()
+       .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.BAR };
+    assertEquals(1, msg.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[0]);
+    msg.clear();
+    assertEquals(0, msg.repeatedPackedNestedEnum.length);
+
+    // Test 1 entry
+    msg.clear()
+       .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO };
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 7);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(1, newMsg.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+
+    // Test 2 entries
+    msg.clear()
+       .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR };
+    assertEquals(2, msg.repeatedPackedNestedEnum.length);
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 8);
+    assertEquals(result.length, msgSerializedSize);
+
+    newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(2, newMsg.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]);
+  }
+
+  public void testNanoRepeatedPackedSerializedSize() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedPackedInt32 = new int[] { 123, 789, 456 };
+    int msgSerializedSize = msg.getSerializedSize();
+    byte [] result = MessageNano.toByteArray(msg);
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 11);
+    assertEquals(result.length, msgSerializedSize);
+    TestAllTypesNano msg2 = new TestAllTypesNano();
+    msg2.repeatedPackedInt32 = new int[] { 123, 789, 456 };
+    byte [] result2 = new byte[msgSerializedSize];
+    MessageNano.toByteArray(msg2, result2, 0, msgSerializedSize);
+
+    // Check equal size and content.
+    assertEquals(msgSerializedSize, msg2.getSerializedSize());
+    assertTrue(Arrays.equals(result, result2));
+  }
+
+  public void testNanoRepeatedInt32ReMerge() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedInt32 = new int[] { 234 };
+    byte [] result1 = MessageNano.toByteArray(msg);
+
+    msg.clear().optionalInt32 = 789;
+    byte [] result2 = MessageNano.toByteArray(msg);
+
+    msg.clear().repeatedInt32 = new int[] { 123, 456 };
+    byte [] result3 = MessageNano.toByteArray(msg);
+
+    // Concatenate the three serializations and read as one message.
+    byte [] result = new byte[result1.length + result2.length + result3.length];
+    System.arraycopy(result1, 0, result, 0, result1.length);
+    System.arraycopy(result2, 0, result, result1.length, result2.length);
+    System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(789, newMsg.optionalInt32);
+    assertEquals(3, newMsg.repeatedInt32.length);
+    assertEquals(234, newMsg.repeatedInt32[0]);
+    assertEquals(123, newMsg.repeatedInt32[1]);
+    assertEquals(456, newMsg.repeatedInt32[2]);
+  }
+
+  public void testNanoRepeatedNestedEnumReMerge() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.repeatedNestedEnum = new int[] { TestAllTypesNano.FOO };
+    byte [] result1 = MessageNano.toByteArray(msg);
+
+    msg.clear().optionalInt32 = 789;
+    byte [] result2 = MessageNano.toByteArray(msg);
+
+    msg.clear().repeatedNestedEnum = new int[] { TestAllTypesNano.BAR, TestAllTypesNano.FOO };
+    byte [] result3 = MessageNano.toByteArray(msg);
+
+    // Concatenate the three serializations and read as one message.
+    byte [] result = new byte[result1.length + result2.length + result3.length];
+    System.arraycopy(result1, 0, result, 0, result1.length);
+    System.arraycopy(result2, 0, result, result1.length, result2.length);
+    System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(789, newMsg.optionalInt32);
+    assertEquals(3, newMsg.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.BAR, newMsg.repeatedNestedEnum[1]);
+    assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[2]);
+  }
+
+  public void testNanoRepeatedNestedMessageReMerge() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    TestAllTypesNano.NestedMessage nestedMsg0 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg0.bb = 0;
+    TestAllTypesNano.NestedMessage nestedMsg1 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg1.bb = 1;
+    TestAllTypesNano.NestedMessage nestedMsg2 =
+      new TestAllTypesNano.NestedMessage();
+    nestedMsg2.bb = 2;
+
+    msg.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 };
+    byte [] result1 = MessageNano.toByteArray(msg);
+
+    msg.clear().optionalInt32 = 789;
+    byte [] result2 = MessageNano.toByteArray(msg);
+
+    msg.clear().repeatedNestedMessage =
+        new TestAllTypesNano.NestedMessage[] { nestedMsg1, nestedMsg2 };
+    byte [] result3 = MessageNano.toByteArray(msg);
+
+    // Concatenate the three serializations and read as one message.
+    byte [] result = new byte[result1.length + result2.length + result3.length];
+    System.arraycopy(result1, 0, result, 0, result1.length);
+    System.arraycopy(result2, 0, result, result1.length, result2.length);
+    System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+    TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+    assertEquals(789, newMsg.optionalInt32);
+    assertEquals(3, newMsg.repeatedNestedMessage.length);
+    assertEquals(nestedMsg0.bb, newMsg.repeatedNestedMessage[0].bb);
+    assertEquals(nestedMsg1.bb, newMsg.repeatedNestedMessage[1].bb);
+    assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb);
+  }
+
+  /**
+   * Tests that invalid enum values from the wire are not accepted.
+   */
+  public void testNanoEnumValidity() throws Exception {
+    final int invalid = 120;
+    final int alsoInvalid = 121;
+
+    EnumValidity.M m = new EnumValidity.M();
+    // Sanity check & baseline of the assertions for the first case below.
+    assertEquals(EnumValidity.E.default_, m.optionalE);
+    assertEquals(EnumValidity.E.BAZ, m.defaultE);
+
+    m.optionalE = invalid;
+    m.defaultE = invalid;
+    // E contains all valid values
+    m.repeatedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR};
+    m.packedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ};
+    // E2 contains some invalid values
+    m.repeatedE2 = new int[] {invalid, EnumValidity.E.BAR, alsoInvalid};
+    m.packedE2 = new int[] {EnumValidity.E.FOO, invalid, alsoInvalid};
+    // E3 contains all invalid values
+    m.repeatedE3 = new int[] {invalid, invalid};
+    m.packedE3 = new int[] {alsoInvalid, alsoInvalid};
+    byte[] serialized = MessageNano.toByteArray(m);
+    // Sanity check that we do have all data in the byte array.
+    assertEquals(31, serialized.length);
+
+    // Test 1: tests that invalid values aren't included in the deserialized message.
+    EnumValidity.M deserialized = MessageNano.mergeFrom(new EnumValidity.M(), serialized);
+    assertEquals(EnumValidity.E.default_, deserialized.optionalE);
+    assertEquals(EnumValidity.E.BAZ, deserialized.defaultE);
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}, deserialized.repeatedE));
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}, deserialized.packedE));
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.BAR}, deserialized.repeatedE2));
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.FOO}, deserialized.packedE2));
+    assertEquals(0, deserialized.repeatedE3.length);
+    assertEquals(0, deserialized.packedE3.length);
+
+    // Test 2: tests that invalid values do not override previous values in the field, including
+    // arrays, including pre-existing invalid values.
+    deserialized.optionalE = EnumValidity.E.BAR;
+    deserialized.defaultE = alsoInvalid;
+    deserialized.repeatedE = new int[] {EnumValidity.E.BAZ};
+    deserialized.packedE = new int[] {EnumValidity.E.BAZ, alsoInvalid};
+    deserialized.repeatedE2 = new int[] {invalid, alsoInvalid};
+    deserialized.packedE2 = null;
+    deserialized.repeatedE3 = null;
+    deserialized.packedE3 = new int[0];
+    MessageNano.mergeFrom(deserialized, serialized);
+    assertEquals(EnumValidity.E.BAR, deserialized.optionalE);
+    assertEquals(alsoInvalid, deserialized.defaultE);
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.BAZ, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAR},
+        deserialized.repeatedE));
+    assertTrue(Arrays.equals(
+        new int[] {EnumValidity.E.BAZ, alsoInvalid, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAZ},
+        deserialized.packedE));
+    assertTrue(Arrays.equals(
+        new int[] {invalid, alsoInvalid, /* + */ EnumValidity.E.BAR},
+        deserialized.repeatedE2));
+    assertTrue(Arrays.equals(
+        new int[] {/* <null> + */ EnumValidity.E.FOO},
+        deserialized.packedE2));
+    assertNull(deserialized.repeatedE3); // null + all invalid == null
+    assertEquals(0, deserialized.packedE3.length); // empty + all invalid == empty
+
+    // Test 3: reading by alternative forms
+    EnumValidity.Alt alt = MessageNano.mergeFrom(new EnumValidity.Alt(), serialized);
+    assertEquals(EnumValidity.E.BAR, // last valid value in m.repeatedE2
+        alt.repeatedE2AsOptional);
+    assertTrue(Arrays.equals(new int[] {EnumValidity.E.FOO}, alt.packedE2AsNonPacked));
+    assertEquals(0, alt.nonPackedE3AsPacked.length);
+  }
+
+  /**
+   * Tests the same as {@link #testNanoEnumValidity()} with accessor style. Repeated fields are
+   * not re-tested here because they are not affected by the accessor style.
+   */
+  public void testNanoEnumValidityAccessors() throws Exception {
+    final int invalid = 120;
+    final int alsoInvalid = 121;
+
+    EnumValidityAccessors.M m = new EnumValidityAccessors.M();
+    // Sanity check & baseline of the assertions for the first case below.
+    assertEquals(EnumValidityAccessors.default_, m.getOptionalE());
+    assertEquals(EnumValidityAccessors.BAZ, m.getDefaultE());
+
+    m.setOptionalE(invalid);
+    m.setDefaultE(invalid);
+    // Set repeatedE2 for Alt.repeatedE2AsOptional
+    m.repeatedE2 = new int[] {invalid, EnumValidityAccessors.BAR, alsoInvalid};
+    byte[] serialized = MessageNano.toByteArray(m);
+    // Sanity check that we do have all data in the byte array.
+    assertEquals(10, serialized.length);
+
+    // Test 1: tests that invalid values aren't included in the deserialized message.
+    EnumValidityAccessors.M deserialized =
+        MessageNano.mergeFrom(new EnumValidityAccessors.M(), serialized);
+    assertEquals(EnumValidityAccessors.default_, deserialized.getOptionalE());
+    assertEquals(EnumValidityAccessors.BAZ, deserialized.getDefaultE());
+
+    // Test 2: tests that invalid values do not override previous values in the field, including
+    // pre-existing invalid values.
+    deserialized.setOptionalE(EnumValidityAccessors.BAR);
+    deserialized.setDefaultE(alsoInvalid);
+    MessageNano.mergeFrom(deserialized, serialized);
+    assertEquals(EnumValidityAccessors.BAR, deserialized.getOptionalE());
+    assertEquals(alsoInvalid, deserialized.getDefaultE());
+
+    // Test 3: reading by alternative forms
+    EnumValidityAccessors.Alt alt =
+        MessageNano.mergeFrom(new EnumValidityAccessors.Alt(), serialized);
+    assertEquals(EnumValidityAccessors.BAR, // last valid value in m.repeatedE2
+        alt.getRepeatedE2AsOptional());
+  }
+
+  /**
+   * Tests that code generation correctly wraps a single message into its outer
+   * class. The class {@code SingleMessageNano} is imported from the outer
+   * class {@code UnittestSingleNano}, whose name is implicit. Any error would
+   * cause this method to fail compilation.
+   */
+  public void testNanoSingle() throws Exception {
+    SingleMessageNano msg = new SingleMessageNano();
+    assertNotNull(msg);
+  }
+
+  /**
+   * Tests that code generation correctly skips generating the outer class if
+   * unnecessary, letting a file-scope entity have the same name. The class
+   * {@code MultipleNameClashNano} shares the same name with the file's outer
+   * class defined explicitly, but the file contains no other entities and has
+   * java_multiple_files set. Any error would cause this method to fail
+   * compilation.
+   */
+  public void testNanoMultipleNameClash() throws Exception {
+    MultipleNameClashNano msg = new MultipleNameClashNano();
+    msg.field = 0;
+  }
+
+  /**
+   * Tests that code generation correctly handles enums in different scopes in
+   * a source file with the option java_multiple_files set to true. Any error
+   * would cause this method to fail compilation.
+   */
+  public void testNanoMultipleEnumScoping() throws Exception {
+    FileScopeEnumRefNano msg1 = new FileScopeEnumRefNano();
+    msg1.enumField = UnittestMultipleNano.ONE;
+    MessageScopeEnumRefNano msg2 = new MessageScopeEnumRefNano();
+    msg2.enumField = MessageScopeEnumRefNano.TWO;
+  }
+
+  /**
+   * Tests that code generation with mixed values of the java_multiple_files
+   * options between the main source file and the imported source files would
+   * generate correct references. Any error would cause this method to fail
+   * compilation.
+   */
+  public void testNanoMultipleImportingNonMultiple() throws Exception {
+    UnittestImportNano.ImportMessageNano importMsg = new UnittestImportNano.ImportMessageNano();
+    MultipleImportingNonMultipleNano1 nano1 = new MultipleImportingNonMultipleNano1();
+    nano1.field = importMsg;
+    MultipleImportingNonMultipleNano2 nano2 = new MultipleImportingNonMultipleNano2();
+    nano2.nano1 = nano1;
+  }
+
+  public void testNanoDefaults() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    for (int i = 0; i < 2; i++) {
+      assertEquals(41, msg.defaultInt32);
+      assertEquals(42, msg.defaultInt64);
+      assertEquals(43, msg.defaultUint32);
+      assertEquals(44, msg.defaultUint64);
+      assertEquals(-45, msg.defaultSint32);
+      assertEquals(46, msg.defaultSint64);
+      assertEquals(47, msg.defaultFixed32);
+      assertEquals(48, msg.defaultFixed64);
+      assertEquals(49, msg.defaultSfixed32);
+      assertEquals(-50, msg.defaultSfixed64);
+      assertTrue(51.5f == msg.defaultFloat);
+      assertTrue(52.0e3 == msg.defaultDouble);
+      assertEquals(true, msg.defaultBool);
+      assertEquals("hello", msg.defaultString);
+      assertEquals("world", new String(msg.defaultBytes, InternalNano.UTF_8));
+      assertEquals("dünya", msg.defaultStringNonascii);
+      assertEquals("dünyab", new String(msg.defaultBytesNonascii, InternalNano.UTF_8));
+      assertEquals(TestAllTypesNano.BAR, msg.defaultNestedEnum);
+      assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.defaultForeignEnum);
+      assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.defaultImportEnum);
+      assertEquals(Float.POSITIVE_INFINITY, msg.defaultFloatInf);
+      assertEquals(Float.NEGATIVE_INFINITY, msg.defaultFloatNegInf);
+      assertEquals(Float.NaN, msg.defaultFloatNan);
+      assertEquals(Double.POSITIVE_INFINITY, msg.defaultDoubleInf);
+      assertEquals(Double.NEGATIVE_INFINITY, msg.defaultDoubleNegInf);
+      assertEquals(Double.NaN, msg.defaultDoubleNan);
+
+      // Default values are not output, except for required fields.
+      byte [] result = MessageNano.toByteArray(msg);
+      int msgSerializedSize = msg.getSerializedSize();
+      //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+      assertTrue(msgSerializedSize == 3);
+      assertEquals(result.length, msgSerializedSize);
+      msg.clear();
+    }
+  }
+
+  public void testDifferentStringLengthsNano() throws Exception {
+    // Test string serialization roundtrip using strings of the following lengths,
+    // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+    // char, hence causing the length delimiter varint to sometimes require more
+    // bytes for the Unicode strings than the ASCII string of the same length.
+    int[] lengths = new int[] {
+            0,
+            1,
+            (1 << 4) - 1,  // 1 byte for ASCII and Unicode
+            (1 << 7) - 1,  // 1 byte for ASCII, 2 bytes for Unicode
+            (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+            (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+            (1 << 17) - 1, // 3 bytes for ASCII and Unicode
+    };
+    for (int i : lengths) {
+      testEncodingOfString('q', i);      // 1 byte per char
+      testEncodingOfString('\u07FF', i); // 2 bytes per char
+      testEncodingOfString('\u0981', i); // 3 bytes per char
+    }
+  }
+
+  /** Regression test for https://github.com/google/protobuf/issues/292 */
+  public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+    String testCase = "Foooooooo";
+    assertEquals(CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length()),
+            CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length() * 3));
+    assertEquals(11, CodedOutputByteBufferNano.computeStringSize(1, testCase));
+    // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+    // An array of size 1 will cause a failure when trying to write the varint.
+    for (int i = 0; i < 11; i++) {
+      CodedOutputByteBufferNano bufferNano = CodedOutputByteBufferNano.newInstance(new byte[i]);
+      try {
+        bufferNano.writeString(1, testCase);
+        fail("Should have thrown an out of space exception");
+      } catch (CodedOutputByteBufferNano.OutOfSpaceException expected) {}
+    }
+  }
+
+  private void testEncodingOfString(char c, int length) throws InvalidProtocolBufferNanoException {
+    TestAllTypesNano testAllTypesNano = new TestAllTypesNano();
+    final String fullString = fullString(c, length);
+    testAllTypesNano.optionalString = fullString;
+    final TestAllTypesNano resultNano = new TestAllTypesNano();
+    MessageNano.mergeFrom(resultNano, MessageNano.toByteArray(testAllTypesNano));
+    assertEquals(fullString, resultNano.optionalString);
+  }
+
+  private String fullString(char c, int length) {
+    char[] result = new char[length];
+    Arrays.fill(result, c);
+    return new String(result);
+  }
+
+  public void testNanoWithHasParseFrom() throws Exception {
+    TestAllTypesNanoHas msg = null;
+    // Test false on creation, after clear and upon empty parse.
+    for (int i = 0; i < 3; i++) {
+      if (i == 0) {
+        msg = new TestAllTypesNanoHas();
+      } else if (i == 1) {
+        msg.clear();
+      } else if (i == 2) {
+        msg = TestAllTypesNanoHas.parseFrom(new byte[0]);
+      }
+      assertFalse(msg.hasOptionalInt32);
+      assertFalse(msg.hasOptionalString);
+      assertFalse(msg.hasOptionalBytes);
+      assertFalse(msg.hasOptionalNestedEnum);
+      assertFalse(msg.hasDefaultInt32);
+      assertFalse(msg.hasDefaultString);
+      assertFalse(msg.hasDefaultBytes);
+      assertFalse(msg.hasDefaultFloatNan);
+      assertFalse(msg.hasDefaultNestedEnum);
+      assertFalse(msg.hasId);
+      assertFalse(msg.hasRequiredEnum);
+      msg.optionalInt32 = 123;
+      msg.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage();
+      msg.optionalNestedMessage.bb = 2;
+      msg.optionalNestedEnum = TestAllTypesNano.BAZ;
+    }
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 10);
+    assertEquals(result.length, msgSerializedSize);
+
+    // Has fields true upon parse.
+    TestAllTypesNanoHas newMsg = TestAllTypesNanoHas.parseFrom(result);
+    assertEquals(123, newMsg.optionalInt32);
+    assertTrue(newMsg.hasOptionalInt32);
+    assertEquals(2, newMsg.optionalNestedMessage.bb);
+    assertTrue(newMsg.optionalNestedMessage.hasBb);
+    assertEquals(TestAllTypesNanoHas.BAZ, newMsg.optionalNestedEnum);
+    assertTrue(newMsg.hasOptionalNestedEnum);
+  }
+
+  public void testNanoWithHasSerialize() throws Exception {
+    TestAllTypesNanoHas msg = new TestAllTypesNanoHas();
+    msg.hasOptionalInt32 = true;
+    msg.hasOptionalString = true;
+    msg.hasOptionalBytes = true;
+    msg.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage();
+    msg.optionalNestedMessage.hasBb = true;
+    msg.hasOptionalNestedEnum = true;
+    msg.hasDefaultInt32 = true;
+    msg.hasDefaultString = true;
+    msg.hasDefaultBytes = true;
+    msg.hasDefaultFloatNan = true;
+    msg.hasDefaultNestedEnum = true;
+    msg.hasId = true;
+    msg.hasRequiredEnum = true;
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    assertEquals(result.length, msgSerializedSize);
+
+    // Now deserialize and find that all fields are set and equal to their defaults.
+    TestAllTypesNanoHas newMsg = TestAllTypesNanoHas.parseFrom(result);
+    assertTrue(newMsg.hasOptionalInt32);
+    assertTrue(newMsg.hasOptionalString);
+    assertTrue(newMsg.hasOptionalBytes);
+    assertTrue(newMsg.optionalNestedMessage.hasBb);
+    assertTrue(newMsg.hasOptionalNestedEnum);
+    assertTrue(newMsg.hasDefaultInt32);
+    assertTrue(newMsg.hasDefaultString);
+    assertTrue(newMsg.hasDefaultBytes);
+    assertTrue(newMsg.hasDefaultFloatNan);
+    assertTrue(newMsg.hasDefaultNestedEnum);
+    assertTrue(newMsg.hasId);
+    assertTrue(newMsg.hasRequiredEnum);
+    assertEquals(0, newMsg.optionalInt32);
+    assertEquals(0, newMsg.optionalString.length());
+    assertEquals(0, newMsg.optionalBytes.length);
+    assertEquals(0, newMsg.optionalNestedMessage.bb);
+    assertEquals(TestAllTypesNanoHas.FOO, newMsg.optionalNestedEnum);
+    assertEquals(41, newMsg.defaultInt32);
+    assertEquals("hello", newMsg.defaultString);
+    assertEquals("world", new String(newMsg.defaultBytes, InternalNano.UTF_8));
+    assertEquals(TestAllTypesNanoHas.BAR, newMsg.defaultNestedEnum);
+    assertEquals(Float.NaN, newMsg.defaultFloatNan);
+    assertEquals(0, newMsg.id);
+    assertEquals(TestAllTypesNanoHas.FOO, newMsg.requiredEnum);
+  }
+
+  public void testNanoWithAccessorsBasic() throws Exception {
+    TestNanoAccessors msg = new TestNanoAccessors();
+
+    // Makes sure required, repeated, and message fields are still public
+    msg.id = 3;
+    msg.repeatedBytes = new byte[2][3];
+    msg.optionalNestedMessage = null;
+
+    // Test accessors
+    assertEquals(0, msg.getOptionalInt32());
+    assertFalse(msg.hasOptionalInt32());
+    msg.setOptionalInt32(135);
+    assertEquals(135, msg.getOptionalInt32());
+    assertTrue(msg.hasOptionalInt32());
+    msg.clearOptionalInt32();
+    assertFalse(msg.hasOptionalInt32());
+    msg.setOptionalInt32(0); // default value
+    assertTrue(msg.hasOptionalInt32());
+
+    // Test NPE
+    try {
+      msg.setOptionalBytes(null);
+      fail();
+    } catch (NullPointerException expected) {}
+    try {
+      msg.setOptionalString(null);
+      fail();
+    } catch (NullPointerException expected) {}
+
+    // Test has bit on bytes field with defaults and clear() re-clones the default array
+    assertFalse(msg.hasDefaultBytes());
+    byte[] defaultBytes = msg.getDefaultBytes();
+    msg.setDefaultBytes(defaultBytes);
+    assertTrue(msg.hasDefaultBytes());
+    msg.clearDefaultBytes();
+    assertFalse(msg.hasDefaultBytes());
+    defaultBytes[0]++; // modify original array
+    assertFalse(Arrays.equals(defaultBytes, msg.getDefaultBytes()));
+
+    // Test has bits that require additional bit fields
+    assertFalse(msg.hasBitFieldCheck());
+    msg.setBitFieldCheck(0);
+    assertTrue(msg.hasBitFieldCheck());
+    assertFalse(msg.hasBeforeBitFieldCheck()); // checks bit field does not leak
+    assertFalse(msg.hasAfterBitFieldCheck());
+
+    // Test clear() clears has bits
+    msg.setOptionalString("hi");
+    msg.setDefaultString("there");
+    msg.clear();
+    assertFalse(msg.hasOptionalString());
+    assertFalse(msg.hasDefaultString());
+    assertFalse(msg.hasBitFieldCheck());
+
+    // Test set() and clear() returns itself (compiles = success)
+    msg.clear()
+        .setOptionalInt32(3)
+        .clearDefaultBytes()
+        .setOptionalString("4");
+  }
+
+  public void testNanoWithAccessorsParseFrom() throws Exception {
+    TestNanoAccessors msg = null;
+    // Test false on creation, after clear and upon empty parse.
+    for (int i = 0; i < 3; i++) {
+      if (i == 0) {
+        msg = new TestNanoAccessors();
+      } else if (i == 1) {
+        msg.clear();
+      } else if (i == 2) {
+        msg = TestNanoAccessors.parseFrom(new byte[0]);
+      }
+      assertFalse(msg.hasOptionalInt32());
+      assertFalse(msg.hasOptionalString());
+      assertFalse(msg.hasOptionalBytes());
+      assertFalse(msg.hasOptionalNestedEnum());
+      assertFalse(msg.hasDefaultInt32());
+      assertFalse(msg.hasDefaultString());
+      assertFalse(msg.hasDefaultBytes());
+      assertFalse(msg.hasDefaultFloatNan());
+      assertFalse(msg.hasDefaultNestedEnum());
+      msg.optionalNestedMessage = new TestNanoAccessors.NestedMessage();
+      msg.optionalNestedMessage.setBb(2);
+      msg.setOptionalNestedEnum(TestNanoAccessors.BAZ);
+      msg.setDefaultInt32(msg.getDefaultInt32());
+    }
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+    assertTrue(msgSerializedSize == 14);
+    assertEquals(result.length, msgSerializedSize);
+
+    // Has fields true upon parse.
+    TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(result);
+    assertEquals(2, newMsg.optionalNestedMessage.getBb());
+    assertTrue(newMsg.optionalNestedMessage.hasBb());
+    assertEquals(TestNanoAccessors.BAZ, newMsg.getOptionalNestedEnum());
+    assertTrue(newMsg.hasOptionalNestedEnum());
+
+    // Has field true on fields with explicit default values from wire.
+    assertTrue(newMsg.hasDefaultInt32());
+    assertEquals(41, newMsg.getDefaultInt32());
+  }
+
+  public void testNanoWithAccessorsPublicFieldTypes() throws Exception {
+    TestNanoAccessors msg = new TestNanoAccessors();
+    assertNull(msg.optionalNestedMessage);
+    assertEquals(0, msg.id);
+    assertEquals(0, msg.repeatedNestedEnum.length);
+
+    TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(MessageNano.toByteArray(msg));
+    assertNull(newMsg.optionalNestedMessage);
+    assertEquals(0, newMsg.id);
+    assertEquals(0, newMsg.repeatedNestedEnum.length);
+
+    TestNanoAccessors.NestedMessage nestedMessage = new TestNanoAccessors.NestedMessage();
+    nestedMessage.setBb(5);
+    newMsg.optionalNestedMessage = nestedMessage;
+    newMsg.id = -1;
+    newMsg.repeatedNestedEnum = new int[] { TestAllTypesNano.FOO };
+
+    TestNanoAccessors newMsg2 = TestNanoAccessors.parseFrom(MessageNano.toByteArray(newMsg));
+    assertEquals(nestedMessage.getBb(), newMsg2.optionalNestedMessage.getBb());
+    assertEquals(-1, newMsg2.id);
+    assertEquals(TestAllTypesNano.FOO, newMsg2.repeatedNestedEnum[0]);
+
+    newMsg2.optionalNestedMessage = null;
+    newMsg2.id = 0;
+    newMsg2.repeatedNestedEnum = null;
+
+    TestNanoAccessors newMsg3 = TestNanoAccessors.parseFrom(MessageNano.toByteArray(newMsg2));
+    assertNull(newMsg3.optionalNestedMessage);
+    assertEquals(0, newMsg3.id);
+    assertEquals(0, newMsg3.repeatedNestedEnum.length);
+  }
+
+  public void testNanoWithAccessorsSerialize() throws Exception {
+    TestNanoAccessors msg = new TestNanoAccessors();
+    msg.setOptionalInt32(msg.getOptionalInt32());
+    msg.setOptionalString(msg.getOptionalString());
+    msg.setOptionalBytes(msg.getOptionalBytes());
+    TestNanoAccessors.NestedMessage nestedMessage = new TestNanoAccessors.NestedMessage();
+    nestedMessage.setBb(nestedMessage.getBb());
+    msg.optionalNestedMessage = nestedMessage;
+    msg.setOptionalNestedEnum(msg.getOptionalNestedEnum());
+    msg.setDefaultInt32(msg.getDefaultInt32());
+    msg.setDefaultString(msg.getDefaultString());
+    msg.setDefaultBytes(msg.getDefaultBytes());
+    msg.setDefaultFloatNan(msg.getDefaultFloatNan());
+    msg.setDefaultNestedEnum(msg.getDefaultNestedEnum());
+
+    byte [] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    assertEquals(result.length, msgSerializedSize);
+
+    // Now deserialize and find that all fields are set and equal to their defaults.
+    TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(result);
+    assertTrue(newMsg.hasOptionalInt32());
+    assertTrue(newMsg.hasOptionalString());
+    assertTrue(newMsg.hasOptionalBytes());
+    assertTrue(newMsg.optionalNestedMessage.hasBb());
+    assertTrue(newMsg.hasOptionalNestedEnum());
+    assertTrue(newMsg.hasDefaultInt32());
+    assertTrue(newMsg.hasDefaultString());
+    assertTrue(newMsg.hasDefaultBytes());
+    assertTrue(newMsg.hasDefaultFloatNan());
+    assertTrue(newMsg.hasDefaultNestedEnum());
+    assertEquals(0, newMsg.getOptionalInt32());
+    assertEquals(0, newMsg.getOptionalString().length());
+    assertEquals(0, newMsg.getOptionalBytes().length);
+    assertEquals(0, newMsg.optionalNestedMessage.getBb());
+    assertEquals(TestNanoAccessors.FOO, newMsg.getOptionalNestedEnum());
+    assertEquals(41, newMsg.getDefaultInt32());
+    assertEquals("hello", newMsg.getDefaultString());
+    assertEquals("world", new String(newMsg.getDefaultBytes(), InternalNano.UTF_8));
+    assertEquals(TestNanoAccessors.BAR, newMsg.getDefaultNestedEnum());
+    assertEquals(Float.NaN, newMsg.getDefaultFloatNan());
+    assertEquals(0, newMsg.id);
+  }
+
+  public void testNanoJavaEnumStyle() throws Exception {
+    EnumClassNanos.EnumClassNano msg = new EnumClassNanos.EnumClassNano();
+    assertEquals(EnumClassNanos.FileScopeEnum.ONE, msg.one);
+    assertEquals(EnumClassNanos.EnumClassNano.MessageScopeEnum.TWO, msg.two);
+
+    EnumClassNanoMultiple msg2 = new EnumClassNanoMultiple();
+    assertEquals(FileScopeEnumMultiple.THREE, msg2.three);
+    assertEquals(EnumClassNanoMultiple.MessageScopeEnumMultiple.FOUR, msg2.four);
+  }
+
+  /**
+   * Tests that fields with a default value of NaN are not serialized when
+   * set to NaN. This is a special case as NaN != NaN, so normal equality
+   * checks don't work.
+   */
+  public void testNanoNotANumberDefaults() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.defaultDoubleNan = 0;
+    msg.defaultFloatNan = 0;
+    byte[] result = MessageNano.toByteArray(msg);
+    int msgSerializedSize = msg.getSerializedSize();
+    assertTrue(result.length == msgSerializedSize);
+    assertTrue(msgSerializedSize > 3);
+
+    msg.defaultDoubleNan = Double.NaN;
+    msg.defaultFloatNan = Float.NaN;
+    result = MessageNano.toByteArray(msg);
+    msgSerializedSize = msg.getSerializedSize();
+    assertEquals(3, result.length);
+    assertEquals(3, msgSerializedSize);
+  }
+
+  /**
+   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
+   * exactly up to a limit, this should not break things.
+   */
+  public void testSkipRawBytesBug() throws Exception {
+    byte[] rawBytes = new byte[] { 1, 2 };
+    CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes);
+
+    int limit = input.pushLimit(1);
+    input.skipRawBytes(1);
+    input.popLimit(limit);
+    assertEquals(2, input.readRawByte());
+  }
+
+  /**
+   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
+   * past the end of a buffer with a limit that has been set past the end of
+   * that buffer, this should not break things.
+   */
+  public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+    byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+    CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes);
+
+    int limit = input.pushLimit(4);
+    // In order to expose the bug we need to read at least one byte to prime the
+    // buffer inside the CodedInputStream.
+    assertEquals(1, input.readRawByte());
+    // Skip to the end of the limit.
+    input.skipRawBytes(3);
+    assertTrue(input.isAtEnd());
+    input.popLimit(limit);
+    assertEquals(5, input.readRawByte());
+  }
+
+  // Test a smattering of various proto types for printing
+  public void testMessageNanoPrinter() {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.optionalInt32 = 14;
+    msg.optionalFloat = 42.3f;
+    msg.optionalString = "String \"with' both quotes";
+    msg.optionalBytes = new byte[] {'"', '\0', 1, 8};
+    msg.optionalGroup = new TestAllTypesNano.OptionalGroup();
+    msg.optionalGroup.a = 15;
+    msg.repeatedInt64 = new long[2];
+    msg.repeatedInt64[0] = 1L;
+    msg.repeatedInt64[1] = -1L;
+    msg.repeatedBytes = new byte[2][];
+    msg.repeatedBytes[1] = new byte[] {'h', 'e', 'l', 'l', 'o'};
+    msg.repeatedGroup = new TestAllTypesNano.RepeatedGroup[2];
+    msg.repeatedGroup[0] = new TestAllTypesNano.RepeatedGroup();
+    msg.repeatedGroup[0].a = -27;
+    msg.repeatedGroup[1] = new TestAllTypesNano.RepeatedGroup();
+    msg.repeatedGroup[1].a = -72;
+    msg.optionalNestedMessage = new TestAllTypesNano.NestedMessage();
+    msg.optionalNestedMessage.bb = 7;
+    msg.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[2];
+    msg.repeatedNestedMessage[0] = new TestAllTypesNano.NestedMessage();
+    msg.repeatedNestedMessage[0].bb = 77;
+    msg.repeatedNestedMessage[1] = new TestAllTypesNano.NestedMessage();
+    msg.repeatedNestedMessage[1].bb = 88;
+    msg.optionalNestedEnum = TestAllTypesNano.BAZ;
+    msg.repeatedNestedEnum = new int[2];
+    msg.repeatedNestedEnum[0] = TestAllTypesNano.BAR;
+    msg.repeatedNestedEnum[1] = TestAllTypesNano.FOO;
+    msg.repeatedStringPiece = new String[] {null, "world"};
+    msg.setOneofString("hello");
+
+    String protoPrint = msg.toString();
+    assertTrue(protoPrint.contains("optional_int32: 14"));
+    assertTrue(protoPrint.contains("optional_float: 42.3"));
+    assertTrue(protoPrint.contains("optional_double: 0.0"));
+    assertTrue(protoPrint.contains("optional_string: \"String \\u0022with\\u0027 both quotes\""));
+    assertTrue(protoPrint.contains("optional_bytes: \"\\\"\\000\\001\\010\""));
+    assertTrue(protoPrint.contains("optional_group <\n  a: 15\n>"));
+
+    assertTrue(protoPrint.contains("repeated_int64: 1\nrepeated_int64: -1"));
+    assertFalse(protoPrint.contains("repeated_bytes: \"\"")); // null should be dropped
+    assertTrue(protoPrint.contains("repeated_bytes: \"hello\""));
+    assertTrue(protoPrint.contains("repeated_group <\n  a: -27\n>\n"
+            + "repeated_group <\n  a: -72\n>"));
+    assertTrue(protoPrint.contains("optional_nested_message <\n  bb: 7\n>"));
+    assertTrue(protoPrint.contains("repeated_nested_message <\n  bb: 77\n>\n"
+            + "repeated_nested_message <\n  bb: 88\n>"));
+    assertTrue(protoPrint.contains("optional_nested_enum: 3"));
+    assertTrue(protoPrint.contains("repeated_nested_enum: 2\nrepeated_nested_enum: 1"));
+    assertTrue(protoPrint.contains("default_int32: 41"));
+    assertTrue(protoPrint.contains("default_string: \"hello\""));
+    assertFalse(protoPrint.contains("repeated_string_piece: \"\""));  // null should be dropped
+    assertTrue(protoPrint.contains("repeated_string_piece: \"world\""));
+    assertTrue(protoPrint.contains("oneof_string: \"hello\""));
+  }
+
+  public void testMessageNanoPrinterAccessors() throws Exception {
+    TestNanoAccessors msg = new TestNanoAccessors();
+    msg.setOptionalInt32(13);
+    msg.setOptionalString("foo");
+    msg.setOptionalBytes(new byte[] {'"', '\0', 1, 8});
+    msg.optionalNestedMessage = new TestNanoAccessors.NestedMessage();
+    msg.optionalNestedMessage.setBb(7);
+    msg.setOptionalNestedEnum(TestNanoAccessors.BAZ);
+    msg.repeatedInt32 = new int[] { 1, -1 };
+    msg.repeatedString = new String[] { "Hello", "world" };
+    msg.repeatedBytes = new byte[2][];
+    msg.repeatedBytes[1] = new byte[] {'h', 'e', 'l', 'l', 'o'};
+    msg.repeatedNestedMessage = new TestNanoAccessors.NestedMessage[2];
+    msg.repeatedNestedMessage[0] = new TestNanoAccessors.NestedMessage();
+    msg.repeatedNestedMessage[0].setBb(5);
+    msg.repeatedNestedMessage[1] = new TestNanoAccessors.NestedMessage();
+    msg.repeatedNestedMessage[1].setBb(6);
+    msg.repeatedNestedEnum = new int[] { TestNanoAccessors.FOO, TestNanoAccessors.BAR };
+    msg.id = 33;
+
+    String protoPrint = msg.toString();
+    assertTrue(protoPrint.contains("optional_int32: 13"));
+    assertTrue(protoPrint.contains("optional_string: \"foo\""));
+    assertTrue(protoPrint.contains("optional_bytes: \"\\\"\\000\\001\\010\""));
+    assertTrue(protoPrint.contains("optional_nested_message <\n  bb: 7\n>"));
+    assertTrue(protoPrint.contains("optional_nested_enum: 3"));
+    assertTrue(protoPrint.contains("repeated_int32: 1\nrepeated_int32: -1"));
+    assertTrue(protoPrint.contains("repeated_string: \"Hello\"\nrepeated_string: \"world\""));
+    assertFalse(protoPrint.contains("repeated_bytes: \"\"")); // null should be dropped
+    assertTrue(protoPrint.contains("repeated_bytes: \"hello\""));
+    assertTrue(protoPrint.contains("repeated_nested_message <\n  bb: 5\n>\n"
+            + "repeated_nested_message <\n  bb: 6\n>"));
+    assertTrue(protoPrint.contains("repeated_nested_enum: 1\nrepeated_nested_enum: 2"));
+    assertTrue(protoPrint.contains("id: 33"));
+  }
+
+  public void testMessageNanoPrinterForMaps() throws Exception {
+    TestMap msg = new TestMap();
+    MessageValue msgValues[] = new MessageValue[] {
+      new MessageValue(), new MessageValue()
+    };
+    msgValues[0].value = 1;
+    msgValues[1].value = 2;
+    msg.int32ToBytesField = new HashMap<Integer, byte[]>();
+    msg.int32ToBytesField.put(1, new byte[] {'"', '\0'});
+    msg.int32ToBytesField.put(2, new byte[] {1, 8});
+    msg.stringToInt32Field = new HashMap<String, Integer>();
+    msg.stringToInt32Field.put("hello", 1);
+    msg.stringToInt32Field.put("world", 2);
+    msg.int32ToMessageField = new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    msg.int32ToMessageField.put(0, msgValues[0]);
+    msg.int32ToMessageField.put(1, msgValues[1]);
+    msg.int32ToEnumField = new HashMap<Integer, Integer>();
+    msg.int32ToEnumField.put(1, 2);
+    msg.int32ToEnumField.put(2, 3);
+    String protoPrint = msg.toString();
+
+    assertTrue(protoPrint.contains(
+        "int32_to_bytes_field <\n  key: 1\n  value: \"\\\"\\000\"\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_bytes_field <\n  key: 2\n  value: \"\\001\\010\"\n>"));
+    assertTrue(protoPrint.contains(
+        "string_to_int32_field <\n  key: \"hello\"\n  value: 1\n>"));
+    assertTrue(protoPrint.contains(
+        "string_to_int32_field <\n  key: \"world\"\n  value: 2\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_message_field <\n  key: 0\n  value <\n    value: 1\n"));
+    assertTrue(protoPrint.contains(
+        "int32_to_message_field <\n  key: 1\n  value <\n    value: 2\n"));
+    assertTrue(protoPrint.contains(
+        "int32_to_enum_field <\n  key: 1\n  value: 2\n>"));
+    assertTrue(protoPrint.contains(
+        "int32_to_enum_field <\n  key: 2\n  value: 3\n>"));
+  }
+
+  public void testExtensions() throws Exception {
+    Extensions.ExtendableMessage message = new Extensions.ExtendableMessage();
+    message.field = 5;
+    int[] int32s = {1, 2};
+    int[] uint32s = {3, 4};
+    int[] sint32s = {-5, -6};
+    long[] int64s = {7, 8};
+    long[] uint64s = {9, 10};
+    long[] sint64s = {-11, -12};
+    int[] fixed32s = {13, 14};
+    int[] sfixed32s = {-15, -16};
+    long[] fixed64s = {17, 18};
+    long[] sfixed64s = {-19, -20};
+    boolean[] bools = {true, false};
+    float[] floats = {2.1f, 2.2f};
+    double[] doubles = {2.3, 2.4};
+    int[] enums = {Extensions.SECOND_VALUE, Extensions.FIRST_VALUE};
+    String[] strings = {"vijfentwintig", "twenty-six"};
+    byte[][] bytess = {{2, 7}, {2, 8}};
+    AnotherMessage another1 = new AnotherMessage();
+    another1.string = "er shi jiu";
+    another1.value = false;
+    AnotherMessage another2 = new AnotherMessage();
+    another2.string = "trente";
+    another2.value = true;
+    AnotherMessage[] messages = {another1, another2};
+    RepeatedExtensions.RepeatedGroup group1 = new RepeatedExtensions.RepeatedGroup();
+    group1.a = 31;
+    RepeatedExtensions.RepeatedGroup group2 = new RepeatedExtensions.RepeatedGroup();
+    group2.a = 32;
+    RepeatedExtensions.RepeatedGroup[] groups = {group1, group2};
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedInt32));
+    message.setExtension(RepeatedExtensions.repeatedInt32, int32s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedInt32));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedUint32));
+    message.setExtension(RepeatedExtensions.repeatedUint32, uint32s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedUint32));
+    message.setExtension(RepeatedExtensions.repeatedSint32, sint32s);
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedInt64));
+    message.setExtension(RepeatedExtensions.repeatedInt64, int64s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedInt64));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedUint64));
+    message.setExtension(RepeatedExtensions.repeatedUint64, uint64s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedUint64));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedSint64));
+    message.setExtension(RepeatedExtensions.repeatedSint64, sint64s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedSint64));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedFixed32));
+    message.setExtension(RepeatedExtensions.repeatedFixed32, fixed32s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedFixed32));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedSfixed32));
+    message.setExtension(RepeatedExtensions.repeatedSfixed32, sfixed32s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedSfixed32));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedFixed64));
+    message.setExtension(RepeatedExtensions.repeatedFixed64, fixed64s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedFixed64));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedSfixed64));
+    message.setExtension(RepeatedExtensions.repeatedSfixed64, sfixed64s);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedSfixed64));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedBool));
+    message.setExtension(RepeatedExtensions.repeatedBool, bools);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedBool));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedFloat));
+    message.setExtension(RepeatedExtensions.repeatedFloat, floats);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedFloat));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedDouble));
+    message.setExtension(RepeatedExtensions.repeatedDouble, doubles);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedDouble));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedEnum));
+    message.setExtension(RepeatedExtensions.repeatedEnum, enums);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedEnum));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedString));
+    message.setExtension(RepeatedExtensions.repeatedString, strings);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedString));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedBytes));
+    message.setExtension(RepeatedExtensions.repeatedBytes, bytess);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedBytes));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedMessage));
+    message.setExtension(RepeatedExtensions.repeatedMessage, messages);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedMessage));
+    assertFalse(message.hasExtension(RepeatedExtensions.repeatedGroup));
+    message.setExtension(RepeatedExtensions.repeatedGroup, groups);
+    assertTrue(message.hasExtension(RepeatedExtensions.repeatedGroup));
+
+    byte[] data = MessageNano.toByteArray(message);
+    message = Extensions.ExtendableMessage.parseFrom(data);
+    assertEquals(5, message.field);
+
+    // Test reading back using SingularExtensions: the retrieved value should equal the last
+    // in each array.
+    assertEquals(int32s[1], (int) message.getExtension(SingularExtensions.someInt32));
+    assertEquals(uint32s[1], (int) message.getExtension(SingularExtensions.someUint32));
+    assertEquals(sint32s[1], (int) message.getExtension(SingularExtensions.someSint32));
+    assertEquals(int64s[1], (long) message.getExtension(SingularExtensions.someInt64));
+    assertEquals(uint64s[1], (long) message.getExtension(SingularExtensions.someUint64));
+    assertEquals(sint64s[1], (long) message.getExtension(SingularExtensions.someSint64));
+    assertEquals(fixed32s[1], (int) message.getExtension(SingularExtensions.someFixed32));
+    assertEquals(sfixed32s[1], (int) message.getExtension(SingularExtensions.someSfixed32));
+    assertEquals(fixed64s[1], (long) message.getExtension(SingularExtensions.someFixed64));
+    assertEquals(sfixed64s[1], (long) message.getExtension(SingularExtensions.someSfixed64));
+    assertEquals(bools[1], (boolean) message.getExtension(SingularExtensions.someBool));
+    assertEquals(floats[1], (float) message.getExtension(SingularExtensions.someFloat));
+    assertEquals(doubles[1], (double) message.getExtension(SingularExtensions.someDouble));
+    assertEquals(enums[1], (int) message.getExtension(SingularExtensions.someEnum));
+    assertEquals(strings[1], message.getExtension(SingularExtensions.someString));
+    assertTrue(Arrays.equals(bytess[1], message.getExtension(SingularExtensions.someBytes)));
+    AnotherMessage deserializedMessage = message.getExtension(SingularExtensions.someMessage);
+    assertEquals(another2.string, deserializedMessage.string);
+    assertEquals(another2.value, deserializedMessage.value);
+    assertEquals(group2.a, message.getExtension(SingularExtensions.someGroup).a);
+
+    // Test reading back using RepeatedExtensions: the arrays should be equal.
+    message = Extensions.ExtendableMessage.parseFrom(data);
+    assertEquals(5, message.field);
+    assertTrue(Arrays.equals(int32s, message.getExtension(RepeatedExtensions.repeatedInt32)));
+    assertTrue(Arrays.equals(uint32s, message.getExtension(RepeatedExtensions.repeatedUint32)));
+    assertTrue(Arrays.equals(sint32s, message.getExtension(RepeatedExtensions.repeatedSint32)));
+    assertTrue(Arrays.equals(int64s, message.getExtension(RepeatedExtensions.repeatedInt64)));
+    assertTrue(Arrays.equals(uint64s, message.getExtension(RepeatedExtensions.repeatedUint64)));
+    assertTrue(Arrays.equals(sint64s, message.getExtension(RepeatedExtensions.repeatedSint64)));
+    assertTrue(Arrays.equals(fixed32s, message.getExtension(RepeatedExtensions.repeatedFixed32)));
+    assertTrue(Arrays.equals(sfixed32s, message.getExtension(RepeatedExtensions.repeatedSfixed32)));
+    assertTrue(Arrays.equals(fixed64s, message.getExtension(RepeatedExtensions.repeatedFixed64)));
+    assertTrue(Arrays.equals(sfixed64s, message.getExtension(RepeatedExtensions.repeatedSfixed64)));
+    assertTrue(Arrays.equals(bools, message.getExtension(RepeatedExtensions.repeatedBool)));
+    assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat)));
+    assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble)));
+    assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum)));
+    assertTrue(Arrays.equals(strings, message.getExtension(RepeatedExtensions.repeatedString)));
+    byte[][] deserializedRepeatedBytes = message.getExtension(RepeatedExtensions.repeatedBytes);
+    assertEquals(2, deserializedRepeatedBytes.length);
+    assertTrue(Arrays.equals(bytess[0], deserializedRepeatedBytes[0]));
+    assertTrue(Arrays.equals(bytess[1], deserializedRepeatedBytes[1]));
+    AnotherMessage[] deserializedRepeatedMessage =
+        message.getExtension(RepeatedExtensions.repeatedMessage);
+    assertEquals(2, deserializedRepeatedMessage.length);
+    assertEquals(another1.string, deserializedRepeatedMessage[0].string);
+    assertEquals(another1.value, deserializedRepeatedMessage[0].value);
+    assertEquals(another2.string, deserializedRepeatedMessage[1].string);
+    assertEquals(another2.value, deserializedRepeatedMessage[1].value);
+    RepeatedExtensions.RepeatedGroup[] deserializedRepeatedGroup =
+        message.getExtension(RepeatedExtensions.repeatedGroup);
+    assertEquals(2, deserializedRepeatedGroup.length);
+    assertEquals(group1.a, deserializedRepeatedGroup[0].a);
+    assertEquals(group2.a, deserializedRepeatedGroup[1].a);
+
+    message = Extensions.ExtendableMessage.parseFrom(data);
+    assertEquals(5, message.field);
+    // Test hasExtension using PackedExtensions.
+    assertTrue(message.hasExtension(PackedExtensions.packedInt32));
+    assertTrue(message.hasExtension(PackedExtensions.packedUint32));
+    assertTrue(message.hasExtension(PackedExtensions.packedSint32));
+    assertTrue(message.hasExtension(PackedExtensions.packedInt64));
+    assertTrue(message.hasExtension(PackedExtensions.packedUint64));
+    assertTrue(message.hasExtension(PackedExtensions.packedSint64));
+    assertTrue(message.hasExtension(PackedExtensions.packedFixed32));
+    assertTrue(message.hasExtension(PackedExtensions.packedSfixed32));
+    assertTrue(message.hasExtension(PackedExtensions.packedFixed64));
+    assertTrue(message.hasExtension(PackedExtensions.packedSfixed64));
+    assertTrue(message.hasExtension(PackedExtensions.packedBool));
+    assertTrue(message.hasExtension(PackedExtensions.packedFloat));
+    assertTrue(message.hasExtension(PackedExtensions.packedDouble));
+    assertTrue(message.hasExtension(PackedExtensions.packedEnum));
+
+    // Test reading back using PackedExtensions: the arrays should be equal, even the fields
+    // are non-packed.
+    assertTrue(Arrays.equals(int32s, message.getExtension(PackedExtensions.packedInt32)));
+    assertTrue(Arrays.equals(uint32s, message.getExtension(PackedExtensions.packedUint32)));
+    assertTrue(Arrays.equals(sint32s, message.getExtension(PackedExtensions.packedSint32)));
+    assertTrue(Arrays.equals(int64s, message.getExtension(PackedExtensions.packedInt64)));
+    assertTrue(Arrays.equals(uint64s, message.getExtension(PackedExtensions.packedUint64)));
+    assertTrue(Arrays.equals(sint64s, message.getExtension(PackedExtensions.packedSint64)));
+    assertTrue(Arrays.equals(fixed32s, message.getExtension(PackedExtensions.packedFixed32)));
+    assertTrue(Arrays.equals(sfixed32s, message.getExtension(PackedExtensions.packedSfixed32)));
+    assertTrue(Arrays.equals(fixed64s, message.getExtension(PackedExtensions.packedFixed64)));
+    assertTrue(Arrays.equals(sfixed64s, message.getExtension(PackedExtensions.packedSfixed64)));
+    assertTrue(Arrays.equals(bools, message.getExtension(PackedExtensions.packedBool)));
+    assertTrue(Arrays.equals(floats, message.getExtension(PackedExtensions.packedFloat)));
+    assertTrue(Arrays.equals(doubles, message.getExtension(PackedExtensions.packedDouble)));
+    assertTrue(Arrays.equals(enums, message.getExtension(PackedExtensions.packedEnum)));
+
+    // Now set the packable extension values using PackedExtensions so they're serialized packed.
+    message.setExtension(PackedExtensions.packedInt32, int32s);
+    message.setExtension(PackedExtensions.packedUint32, uint32s);
+    message.setExtension(PackedExtensions.packedSint32, sint32s);
+    message.setExtension(PackedExtensions.packedInt64, int64s);
+    message.setExtension(PackedExtensions.packedUint64, uint64s);
+    message.setExtension(PackedExtensions.packedSint64, sint64s);
+    message.setExtension(PackedExtensions.packedFixed32, fixed32s);
+    message.setExtension(PackedExtensions.packedSfixed32, sfixed32s);
+    message.setExtension(PackedExtensions.packedFixed64, fixed64s);
+    message.setExtension(PackedExtensions.packedSfixed64, sfixed64s);
+    message.setExtension(PackedExtensions.packedBool, bools);
+    message.setExtension(PackedExtensions.packedFloat, floats);
+    message.setExtension(PackedExtensions.packedDouble, doubles);
+    message.setExtension(PackedExtensions.packedEnum, enums);
+
+    // And read back using non-packed RepeatedExtensions.
+    byte[] data2 = MessageNano.toByteArray(message);
+    message = MessageNano.mergeFrom(new Extensions.ExtendableMessage(), data2);
+    assertTrue(Arrays.equals(int32s, message.getExtension(RepeatedExtensions.repeatedInt32)));
+    assertTrue(Arrays.equals(uint32s, message.getExtension(RepeatedExtensions.repeatedUint32)));
+    assertTrue(Arrays.equals(sint32s, message.getExtension(RepeatedExtensions.repeatedSint32)));
+    assertTrue(Arrays.equals(int64s, message.getExtension(RepeatedExtensions.repeatedInt64)));
+    assertTrue(Arrays.equals(uint64s, message.getExtension(RepeatedExtensions.repeatedUint64)));
+    assertTrue(Arrays.equals(sint64s, message.getExtension(RepeatedExtensions.repeatedSint64)));
+    assertTrue(Arrays.equals(fixed32s, message.getExtension(RepeatedExtensions.repeatedFixed32)));
+    assertTrue(Arrays.equals(sfixed32s, message.getExtension(RepeatedExtensions.repeatedSfixed32)));
+    assertTrue(Arrays.equals(fixed64s, message.getExtension(RepeatedExtensions.repeatedFixed64)));
+    assertTrue(Arrays.equals(sfixed64s, message.getExtension(RepeatedExtensions.repeatedSfixed64)));
+    assertTrue(Arrays.equals(bools, message.getExtension(RepeatedExtensions.repeatedBool)));
+    assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat)));
+    assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble)));
+    assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum)));
+
+    // Clone the message and ensure it's still equal.
+    Extensions.ExtendableMessage clone = message.clone();
+    assertEquals(clone, message);
+  }
+
+  public void testNullExtensions() throws Exception {
+    // Check that clearing the extension on an empty message is a no-op.
+    Extensions.ExtendableMessage message = new Extensions.ExtendableMessage();
+    assertFalse(message.hasExtension(SingularExtensions.someMessage));
+    message.setExtension(SingularExtensions.someMessage, null);
+    assertFalse(message.hasExtension(SingularExtensions.someMessage));
+    assertEquals(0, MessageNano.toByteArray(message).length);
+
+    // Check that the message is empty after setting and clearing an extension.
+    AnotherMessage another = new AnotherMessage();
+    assertFalse(message.hasExtension(SingularExtensions.someMessage));
+    message.setExtension(SingularExtensions.someMessage, another);
+    assertTrue(message.hasExtension(SingularExtensions.someMessage));
+    assertTrue(MessageNano.toByteArray(message).length > 0);
+    message.setExtension(SingularExtensions.someMessage, null);
+    assertFalse(message.hasExtension(SingularExtensions.someMessage));
+    assertEquals(0, MessageNano.toByteArray(message).length);
+  }
+
+  public void testExtensionsMutation() {
+    Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage();
+    extendableMessage.setExtension(SingularExtensions.someMessage,
+        new Extensions.AnotherMessage());
+
+    extendableMessage.getExtension(SingularExtensions.someMessage).string = "not empty";
+
+    assertEquals("not empty",
+        extendableMessage.getExtension(SingularExtensions.someMessage).string);
+  }
+
+  public void testExtensionsMutation_Equals() throws InvalidProtocolBufferNanoException {
+    Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage();
+    extendableMessage.field = 5;
+    int int32 = 42;
+    int[] uint32s = {3, 4};
+    int[] sint32s = {-5, -6};
+    long[] int64s = {7, 8};
+    long[] uint64s = {9, 10};
+    long[] sint64s = {-11, -12};
+    int[] fixed32s = {13, 14};
+    int[] sfixed32s = {-15, -16};
+    long[] fixed64s = {17, 18};
+    long[] sfixed64s = {-19, -20};
+    boolean[] bools = {true, false};
+    float[] floats = {2.1f, 2.2f};
+    double[] doubles = {2.3, 2.4};
+    int[] enums = {Extensions.SECOND_VALUE, Extensions.FIRST_VALUE};
+    String[] strings = {"vijfentwintig", "twenty-six"};
+    byte[][] bytess = {{2, 7}, {2, 8}};
+    AnotherMessage another1 = new AnotherMessage();
+    another1.string = "er shi jiu";
+    another1.value = false;
+    AnotherMessage another2 = new AnotherMessage();
+    another2.string = "trente";
+    another2.value = true;
+    AnotherMessage[] messages = {another1, another2};
+    RepeatedExtensions.RepeatedGroup group1 = new RepeatedExtensions.RepeatedGroup();
+    group1.a = 31;
+    RepeatedExtensions.RepeatedGroup group2 = new RepeatedExtensions.RepeatedGroup();
+    group2.a = 32;
+    RepeatedExtensions.RepeatedGroup[] groups = {group1, group2};
+    extendableMessage.setExtension(SingularExtensions.someInt32, int32);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedUint32, uint32s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedSint32, sint32s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedInt64, int64s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedUint64, uint64s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedSint64, sint64s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedFixed32, fixed32s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedSfixed32, sfixed32s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedFixed64, fixed64s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedSfixed64, sfixed64s);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedBool, bools);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedFloat, floats);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedDouble, doubles);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedEnum, enums);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedString, strings);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedBytes, bytess);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedMessage, messages);
+    extendableMessage.setExtension(RepeatedExtensions.repeatedGroup, groups);
+
+    byte[] data = MessageNano.toByteArray(extendableMessage);
+
+    extendableMessage = Extensions.ExtendableMessage.parseFrom(data);
+    Extensions.ExtendableMessage messageCopy = Extensions.ExtendableMessage.parseFrom(data);
+
+    // Without deserialising.
+    assertEquals(extendableMessage, messageCopy);
+    assertEquals(extendableMessage.hashCode(), messageCopy.hashCode());
+
+    // Only one deserialized.
+    extendableMessage.getExtension(SingularExtensions.someInt32);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedUint32);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedSint32);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedInt64);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedUint64);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedSint64);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedFixed32);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedSfixed32);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedFixed64);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedSfixed64);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedBool);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedFloat);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedDouble);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedEnum);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedString);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedBytes);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedMessage);
+    extendableMessage.getExtension(RepeatedExtensions.repeatedGroup);
+    assertEquals(extendableMessage, messageCopy);
+    assertEquals(extendableMessage.hashCode(), messageCopy.hashCode());
+
+    // Both deserialized.
+    messageCopy.getExtension(SingularExtensions.someInt32);
+    messageCopy.getExtension(RepeatedExtensions.repeatedUint32);
+    messageCopy.getExtension(RepeatedExtensions.repeatedSint32);
+    messageCopy.getExtension(RepeatedExtensions.repeatedInt64);
+    messageCopy.getExtension(RepeatedExtensions.repeatedUint64);
+    messageCopy.getExtension(RepeatedExtensions.repeatedSint64);
+    messageCopy.getExtension(RepeatedExtensions.repeatedFixed32);
+    messageCopy.getExtension(RepeatedExtensions.repeatedSfixed32);
+    messageCopy.getExtension(RepeatedExtensions.repeatedFixed64);
+    messageCopy.getExtension(RepeatedExtensions.repeatedSfixed64);
+    messageCopy.getExtension(RepeatedExtensions.repeatedBool);
+    messageCopy.getExtension(RepeatedExtensions.repeatedFloat);
+    messageCopy.getExtension(RepeatedExtensions.repeatedDouble);
+    messageCopy.getExtension(RepeatedExtensions.repeatedEnum);
+    messageCopy.getExtension(RepeatedExtensions.repeatedString);
+    messageCopy.getExtension(RepeatedExtensions.repeatedBytes);
+    messageCopy.getExtension(RepeatedExtensions.repeatedMessage);
+    messageCopy.getExtension(RepeatedExtensions.repeatedGroup);
+    assertEquals(extendableMessage, messageCopy);
+    assertEquals(extendableMessage.hashCode(), messageCopy.hashCode());
+
+    // Change one, make sure they are still different.
+    messageCopy.getExtension(RepeatedExtensions.repeatedMessage)[0].string = "not empty";
+    assertFalse(extendableMessage.equals(messageCopy));
+
+    // Even if the extension hasn't been deserialized.
+    extendableMessage = Extensions.ExtendableMessage.parseFrom(data);
+    assertFalse(extendableMessage.equals(messageCopy));
+  }
+
+  public void testExtensionsCaching() {
+    Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage();
+    extendableMessage.setExtension(SingularExtensions.someMessage,
+        new Extensions.AnotherMessage());
+    assertSame("Consecutive calls to getExtensions should return the same object",
+        extendableMessage.getExtension(SingularExtensions.someMessage),
+        extendableMessage.getExtension(SingularExtensions.someMessage));
+  }
+
+  public void testUnknownFields() throws Exception {
+    // Check that we roundtrip (serialize and deserialize) unrecognized fields.
+    AnotherMessage message = new AnotherMessage();
+    message.string = "Hello World";
+    message.value = false;
+
+    byte[] bytes = MessageNano.toByteArray(message);
+    int extraFieldSize = CodedOutputByteBufferNano.computeStringSize(
+        1001, "This is an unknown field");
+    byte[] newBytes = new byte[bytes.length + extraFieldSize];
+    System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
+    CodedOutputByteBufferNano.newInstance(newBytes, bytes.length, extraFieldSize)
+        .writeString(1001, "This is an unknown field");
+
+    // Deserialize with an unknown field.
+    AnotherMessage deserialized = AnotherMessage.parseFrom(newBytes);
+    byte[] serialized = MessageNano.toByteArray(deserialized);
+
+    assertEquals(newBytes.length, serialized.length);
+
+    // Clear, and make sure it clears everything.
+    deserialized.clear();
+    assertEquals(0, MessageNano.toByteArray(deserialized).length);
+  }
+
+  public void testMergeFrom() throws Exception {
+    SimpleMessageNano message = new SimpleMessageNano();
+    message.d = 123;
+    byte[] bytes = MessageNano.toByteArray(message);
+
+    SimpleMessageNano newMessage = MessageNano.mergeFrom(new SimpleMessageNano(), bytes);
+    assertEquals(message.d, newMessage.d);
+  }
+
+  public void testJavaKeyword() throws Exception {
+    TestAllTypesNano msg = new TestAllTypesNano();
+    msg.synchronized_ = 123;
+    assertEquals(123, msg.synchronized_);
+  }
+
+  public void testReferenceTypesForPrimitives() throws Exception {
+    NanoReferenceTypes.TestAllTypesNano message = new NanoReferenceTypes.TestAllTypesNano();
+
+    // Base check - when nothing is set, we serialize nothing.
+    assertHasWireData(message, false);
+
+    message.defaultBool = true;
+    assertHasWireData(message, true);
+
+    message.defaultBool = false;
+    assertHasWireData(message, true);
+
+    message.defaultBool = null;
+    assertHasWireData(message, false);
+
+    message.defaultInt32 = 5;
+    assertHasWireData(message, true);
+
+    message.defaultInt32 = null;
+    assertHasWireData(message, false);
+
+    message.defaultInt64 = 123456L;
+    assertHasWireData(message, true);
+
+    message.defaultInt64 = null;
+    assertHasWireData(message, false);
+
+    message.defaultFloat = 1f;
+    assertHasWireData(message, true);
+
+    message.defaultFloat = null;
+    assertHasWireData(message, false);
+
+    message.defaultDouble = 2.1;
+    assertHasWireData(message, true);
+
+    message.defaultDouble = null;
+    assertHasWireData(message, false);
+
+    message.defaultString = "hello";
+    assertHasWireData(message, true);
+
+    message.defaultString = null;
+    assertHasWireData(message, false);
+
+    message.defaultBytes = new byte[] { 1, 2, 3 };
+    assertHasWireData(message, true);
+
+    message.defaultBytes = null;
+    assertHasWireData(message, false);
+  }
+
+  public void testHashCodeEquals() throws Exception {
+    // Complete equality:
+    TestAllTypesNano a = createMessageForHashCodeEqualsTest();
+    TestAllTypesNano aEquivalent = createMessageForHashCodeEqualsTest();
+
+    assertTrue(MessageNano.messageNanoEquals(a, aEquivalent));
+    assertFalse(MessageNano.messageNanoEquals(a, new TestAllTypesNano()));
+
+    // Null and empty array for repeated fields equality:
+    TestAllTypesNano b = createMessageForHashCodeEqualsTest();
+    b.repeatedBool = null;
+    b.repeatedFloat = new float[0];
+    TestAllTypesNano bEquivalent = createMessageForHashCodeEqualsTest();
+    bEquivalent.repeatedBool = new boolean[0];
+    bEquivalent.repeatedFloat = null;
+
+    // Ref-element-type repeated fields use non-null subsequence equality:
+    TestAllTypesNano c = createMessageForHashCodeEqualsTest();
+    c.repeatedString = null;
+    c.repeatedStringPiece = new String[] {null, "one", null, "two"};
+    c.repeatedBytes = new byte[][] {{3, 4}, null};
+    TestAllTypesNano cEquivalent = createMessageForHashCodeEqualsTest();
+    cEquivalent.repeatedString = new String[3];
+    cEquivalent.repeatedStringPiece = new String[] {"one", "two", null};
+    cEquivalent.repeatedBytes = new byte[][] {{3, 4}};
+
+    // Complete equality for messages with has fields:
+    TestAllTypesNanoHas d = createMessageWithHasForHashCodeEqualsTest();
+    TestAllTypesNanoHas dEquivalent = createMessageWithHasForHashCodeEqualsTest();
+
+    // If has-fields exist, fields with the same default values but
+    // different has-field values are different.
+    TestAllTypesNanoHas e = createMessageWithHasForHashCodeEqualsTest();
+    e.optionalInt32++; // make different from d
+    e.hasDefaultString = false;
+    TestAllTypesNanoHas eDifferent = createMessageWithHasForHashCodeEqualsTest();
+    eDifferent.optionalInt32 = e.optionalInt32;
+    eDifferent.hasDefaultString = true;
+
+    // Complete equality for messages with accessors:
+    TestNanoAccessors f = createMessageWithAccessorsForHashCodeEqualsTest();
+    TestNanoAccessors fEquivalent = createMessageWithAccessorsForHashCodeEqualsTest();
+
+    // If using accessors, explicitly setting a field to its default value
+    // should make the message different.
+    TestNanoAccessors g = createMessageWithAccessorsForHashCodeEqualsTest();
+    g.setOptionalInt32(g.getOptionalInt32() + 1); // make different from f
+    g.clearDefaultString();
+    TestNanoAccessors gDifferent = createMessageWithAccessorsForHashCodeEqualsTest();
+    gDifferent.setOptionalInt32(g.getOptionalInt32());
+    gDifferent.setDefaultString(g.getDefaultString());
+
+    // Complete equality for reference typed messages:
+    NanoReferenceTypes.TestAllTypesNano h = createRefTypedMessageForHashCodeEqualsTest();
+    NanoReferenceTypes.TestAllTypesNano hEquivalent = createRefTypedMessageForHashCodeEqualsTest();
+
+    // Inequality of null and default value for reference typed messages:
+    NanoReferenceTypes.TestAllTypesNano i = createRefTypedMessageForHashCodeEqualsTest();
+    i.optionalInt32 = 1; // make different from h
+    i.optionalFloat = null;
+    NanoReferenceTypes.TestAllTypesNano iDifferent = createRefTypedMessageForHashCodeEqualsTest();
+    iDifferent.optionalInt32 = i.optionalInt32;
+    iDifferent.optionalFloat = 0.0f;
+
+    HashMap<MessageNano, String> hashMap = new HashMap<MessageNano, String>();
+    hashMap.put(a, "a");
+    hashMap.put(b, "b");
+    hashMap.put(c, "c");
+    hashMap.put(d, "d");
+    hashMap.put(e, "e");
+    hashMap.put(f, "f");
+    hashMap.put(g, "g");
+    hashMap.put(h, "h");
+    hashMap.put(i, "i");
+
+    assertEquals(9, hashMap.size()); // a-i should be different from each other.
+
+    assertEquals("a", hashMap.get(a));
+    assertEquals("a", hashMap.get(aEquivalent));
+
+    assertEquals("b", hashMap.get(b));
+    assertEquals("b", hashMap.get(bEquivalent));
+
+    assertEquals("c", hashMap.get(c));
+    assertEquals("c", hashMap.get(cEquivalent));
+
+    assertEquals("d", hashMap.get(d));
+    assertEquals("d", hashMap.get(dEquivalent));
+
+    assertEquals("e", hashMap.get(e));
+    assertNull(hashMap.get(eDifferent));
+
+    assertEquals("f", hashMap.get(f));
+    assertEquals("f", hashMap.get(fEquivalent));
+
+    assertEquals("g", hashMap.get(g));
+    assertNull(hashMap.get(gDifferent));
+
+    assertEquals("h", hashMap.get(h));
+    assertEquals("h", hashMap.get(hEquivalent));
+
+    assertEquals("i", hashMap.get(i));
+    assertNull(hashMap.get(iDifferent));
+  }
+
+  private TestAllTypesNano createMessageForHashCodeEqualsTest() {
+    TestAllTypesNano message = new TestAllTypesNano();
+    message.optionalInt32 = 5;
+    message.optionalInt64 = 777;
+    message.optionalFloat = 1.0f;
+    message.optionalDouble = 2.0;
+    message.optionalBool = true;
+    message.optionalString = "Hello";
+    message.optionalBytes = new byte[] { 1, 2, 3 };
+    message.optionalNestedMessage = new TestAllTypesNano.NestedMessage();
+    message.optionalNestedMessage.bb = 27;
+    message.optionalNestedEnum = TestAllTypesNano.BAR;
+    message.repeatedInt32 = new int[] { 5, 6, 7, 8 };
+    message.repeatedInt64 = new long[] { 27L, 28L, 29L };
+    message.repeatedFloat = new float[] { 5.0f, 6.0f };
+    message.repeatedDouble = new double[] { 99.1, 22.5 };
+    message.repeatedBool = new boolean[] { true, false, true };
+    message.repeatedString = new String[] { "One", "Two" };
+    message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } };
+    message.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {
+      message.optionalNestedMessage,
+      message.optionalNestedMessage
+    };
+    message.repeatedNestedEnum = new int[] {
+      TestAllTypesNano.BAR,
+      TestAllTypesNano.BAZ
+    };
+    message.setOneofUint32(3);
+    return message;
+  }
+
+  private TestAllTypesNanoHas createMessageWithHasForHashCodeEqualsTest() {
+    TestAllTypesNanoHas message = new TestAllTypesNanoHas();
+    message.optionalInt32 = 5;
+    message.optionalString = "Hello";
+    message.optionalBytes = new byte[] { 1, 2, 3 };
+    message.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage();
+    message.optionalNestedMessage.bb = 27;
+    message.optionalNestedEnum = TestAllTypesNano.BAR;
+    message.repeatedInt32 = new int[] { 5, 6, 7, 8 };
+    message.repeatedString = new String[] { "One", "Two" };
+    message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } };
+    message.repeatedNestedMessage = new TestAllTypesNanoHas.NestedMessage[] {
+      message.optionalNestedMessage,
+      message.optionalNestedMessage
+    };
+    message.repeatedNestedEnum = new int[] {
+      TestAllTypesNano.BAR,
+      TestAllTypesNano.BAZ
+    };
+    return message;
+  }
+
+  private TestNanoAccessors createMessageWithAccessorsForHashCodeEqualsTest() {
+    TestNanoAccessors message = new TestNanoAccessors()
+        .setOptionalInt32(5)
+        .setOptionalString("Hello")
+        .setOptionalBytes(new byte[] {1, 2, 3})
+        .setOptionalNestedEnum(TestNanoAccessors.BAR);
+    message.optionalNestedMessage = new TestNanoAccessors.NestedMessage().setBb(27);
+    message.repeatedInt32 = new int[] { 5, 6, 7, 8 };
+    message.repeatedString = new String[] { "One", "Two" };
+    message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } };
+    message.repeatedNestedMessage = new TestNanoAccessors.NestedMessage[] {
+      message.optionalNestedMessage,
+      message.optionalNestedMessage
+    };
+    message.repeatedNestedEnum = new int[] {
+      TestAllTypesNano.BAR,
+      TestAllTypesNano.BAZ
+    };
+    return message;
+  }
+
+  private NanoReferenceTypes.TestAllTypesNano createRefTypedMessageForHashCodeEqualsTest() {
+    NanoReferenceTypes.TestAllTypesNano message = new NanoReferenceTypes.TestAllTypesNano();
+    message.optionalInt32 = 5;
+    message.optionalInt64 = 777L;
+    message.optionalFloat = 1.0f;
+    message.optionalDouble = 2.0;
+    message.optionalBool = true;
+    message.optionalString = "Hello";
+    message.optionalBytes = new byte[] { 1, 2, 3 };
+    message.optionalNestedMessage =
+        new NanoReferenceTypes.TestAllTypesNano.NestedMessage();
+    message.optionalNestedMessage.foo = 27;
+    message.optionalNestedEnum = NanoReferenceTypes.TestAllTypesNano.BAR;
+    message.repeatedInt32 = new int[] { 5, 6, 7, 8 };
+    message.repeatedInt64 = new long[] { 27L, 28L, 29L };
+    message.repeatedFloat = new float[] { 5.0f, 6.0f };
+    message.repeatedDouble = new double[] { 99.1, 22.5 };
+    message.repeatedBool = new boolean[] { true, false, true };
+    message.repeatedString = new String[] { "One", "Two" };
+    message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } };
+    message.repeatedNestedMessage =
+        new NanoReferenceTypes.TestAllTypesNano.NestedMessage[] {
+          message.optionalNestedMessage,
+          message.optionalNestedMessage
+        };
+    message.repeatedNestedEnum = new int[] {
+      NanoReferenceTypes.TestAllTypesNano.BAR,
+      NanoReferenceTypes.TestAllTypesNano.BAZ
+    };
+    return message;
+  }
+
+  public void testEqualsWithSpecialFloatingPointValues() throws Exception {
+    // Checks that the nano implementation complies with Object.equals() when treating
+    // floating point numbers, i.e. NaN == NaN and +0.0 != -0.0.
+    // This test assumes that the generated equals() implementations are symmetric, so
+    // there will only be one direction for each equality check.
+
+    TestAllTypesNano m1 = new TestAllTypesNano();
+    m1.optionalFloat = Float.NaN;
+    m1.optionalDouble = Double.NaN;
+    TestAllTypesNano m2 = new TestAllTypesNano();
+    m2.optionalFloat = Float.NaN;
+    m2.optionalDouble = Double.NaN;
+    assertTrue(m1.equals(m2));
+    assertTrue(m1.equals(
+        MessageNano.mergeFrom(new TestAllTypesNano(), MessageNano.toByteArray(m1))));
+
+    m1.optionalFloat = +0f;
+    m2.optionalFloat = -0f;
+    assertFalse(m1.equals(m2));
+
+    m1.optionalFloat = -0f;
+    m1.optionalDouble = +0d;
+    m2.optionalDouble = -0d;
+    assertFalse(m1.equals(m2));
+
+    m1.optionalDouble = -0d;
+    assertTrue(m1.equals(m2));
+    assertFalse(m1.equals(new TestAllTypesNano())); // -0 does not equals() the default +0
+    assertTrue(m1.equals(
+        MessageNano.mergeFrom(new TestAllTypesNano(), MessageNano.toByteArray(m1))));
+
+    // -------
+
+    TestAllTypesNanoHas m3 = new TestAllTypesNanoHas();
+    m3.optionalFloat = Float.NaN;
+    m3.hasOptionalFloat = true;
+    m3.optionalDouble = Double.NaN;
+    m3.hasOptionalDouble = true;
+    TestAllTypesNanoHas m4 = new TestAllTypesNanoHas();
+    m4.optionalFloat = Float.NaN;
+    m4.hasOptionalFloat = true;
+    m4.optionalDouble = Double.NaN;
+    m4.hasOptionalDouble = true;
+    assertTrue(m3.equals(m4));
+    assertTrue(m3.equals(
+        MessageNano.mergeFrom(new TestAllTypesNanoHas(), MessageNano.toByteArray(m3))));
+
+    m3.optionalFloat = +0f;
+    m4.optionalFloat = -0f;
+    assertFalse(m3.equals(m4));
+
+    m3.optionalFloat = -0f;
+    m3.optionalDouble = +0d;
+    m4.optionalDouble = -0d;
+    assertFalse(m3.equals(m4));
+
+    m3.optionalDouble = -0d;
+    m3.hasOptionalFloat = false;  // -0 does not equals() the default +0,
+    m3.hasOptionalDouble = false; // so these incorrect 'has' flags should be disregarded.
+    assertTrue(m3.equals(m4));    // note: m4 has the 'has' flags set.
+    assertFalse(m3.equals(new TestAllTypesNanoHas())); // note: the new message has +0 defaults
+    assertTrue(m3.equals(
+        MessageNano.mergeFrom(new TestAllTypesNanoHas(), MessageNano.toByteArray(m3))));
+                                  // note: the deserialized message has the 'has' flags set.
+
+    // -------
+
+    TestNanoAccessors m5 = new TestNanoAccessors();
+    m5.setOptionalFloat(Float.NaN);
+    m5.setOptionalDouble(Double.NaN);
+    TestNanoAccessors m6 = new TestNanoAccessors();
+    m6.setOptionalFloat(Float.NaN);
+    m6.setOptionalDouble(Double.NaN);
+    assertTrue(m5.equals(m6));
+    assertTrue(m5.equals(
+        MessageNano.mergeFrom(new TestNanoAccessors(), MessageNano.toByteArray(m6))));
+
+    m5.setOptionalFloat(+0f);
+    m6.setOptionalFloat(-0f);
+    assertFalse(m5.equals(m6));
+
+    m5.setOptionalFloat(-0f);
+    m5.setOptionalDouble(+0d);
+    m6.setOptionalDouble(-0d);
+    assertFalse(m5.equals(m6));
+
+    m5.setOptionalDouble(-0d);
+    assertTrue(m5.equals(m6));
+    assertFalse(m5.equals(new TestNanoAccessors()));
+    assertTrue(m5.equals(
+        MessageNano.mergeFrom(new TestNanoAccessors(), MessageNano.toByteArray(m6))));
+
+    // -------
+
+    NanoReferenceTypes.TestAllTypesNano m7 = new NanoReferenceTypes.TestAllTypesNano();
+    m7.optionalFloat = Float.NaN;
+    m7.optionalDouble = Double.NaN;
+    NanoReferenceTypes.TestAllTypesNano m8 = new NanoReferenceTypes.TestAllTypesNano();
+    m8.optionalFloat = Float.NaN;
+    m8.optionalDouble = Double.NaN;
+    assertTrue(m7.equals(m8));
+    assertTrue(m7.equals(MessageNano.mergeFrom(
+        new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7))));
+
+    m7.optionalFloat = +0f;
+    m8.optionalFloat = -0f;
+    assertFalse(m7.equals(m8));
+
+    m7.optionalFloat = -0f;
+    m7.optionalDouble = +0d;
+    m8.optionalDouble = -0d;
+    assertFalse(m7.equals(m8));
+
+    m7.optionalDouble = -0d;
+    assertTrue(m7.equals(m8));
+    assertFalse(m7.equals(new NanoReferenceTypes.TestAllTypesNano()));
+    assertTrue(m7.equals(MessageNano.mergeFrom(
+        new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7))));
+  }
+
+  private static TestAllTypesNano generateMessageForOneof(int caseNumber) {
+    TestAllTypesNano result = new TestAllTypesNano();
+    TestAllTypesNano.NestedMessage nested =
+        new TestAllTypesNano.NestedMessage();
+    nested.bb = 2;
+    switch (caseNumber) {
+      case TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER:
+        result.setOneofUint32(1);
+        break;
+      case TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER:
+        result.setOneofEnum(TestAllTypesNano.BAR);
+        break;
+      case TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER:
+        result.setOneofNestedMessage(nested);
+        break;
+      case TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER:
+        result.setOneofBytes(new byte[] {1, 2});
+        break;
+      case TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER:
+        result.setOneofString("hello");
+        break;
+      case TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER:
+        result.setOneofFixed64(-1L);
+        break;
+      default:
+        throw new RuntimeException("unexpected case number: " + caseNumber);
+    }
+    return result;
+  }
+
+  public void testOneofHashCodeEquals() throws Exception {
+    TestAllTypesNano m1 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+    assertEquals(m1, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER));
+    assertFalse(m1.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m2 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(m2, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER));
+    assertFalse(m2.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m3 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+    assertEquals(m3, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER));
+    assertFalse(m3.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m4 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertEquals(m4, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER));
+    assertFalse(m4.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m5 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+    assertEquals(m5, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER));
+    assertFalse(m5.equals(new TestAllTypesNano()));
+
+    TestAllTypesNano m6 = generateMessageForOneof(
+        TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+    assertEquals(m6, generateMessageForOneof(
+        TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER));
+    assertFalse(m6.equals(new TestAllTypesNano()));
+
+    Map<TestAllTypesNano, Integer> map =
+        new HashMap<TestAllTypesNano, Integer>();
+    map.put(m1, 1);
+    map.put(m2, 2);
+    map.put(m3, 3);
+    map.put(m4, 4);
+    map.put(m5, 5);
+    map.put(m6, 6);
+
+    assertEquals(6, map.size());
+  }
+
+  private void checkOneofCase(TestAllTypesNano nano, int field)
+      throws Exception {
+    assertEquals(field, nano.getOneofFieldCase());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER,
+        nano.hasOneofBytes());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER,
+        nano.hasOneofEnum());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER,
+        nano.hasOneofFixed64());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER,
+        nano.hasOneofNestedMessage());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER,
+        nano.hasOneofString());
+    assertEquals(
+        field == TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER,
+        nano.hasOneofUint32());
+
+  }
+
+  public void testOneofDefault() throws Exception {
+    TestAllTypesNano m1 = new TestAllTypesNano();
+    checkOneofCase(m1, 0);
+    assertEquals(WireFormatNano.EMPTY_BYTES, m1.getOneofBytes());
+    assertEquals(TestAllTypesNano.FOO, m1.getOneofEnum());
+    assertEquals(0L, m1.getOneofFixed64());
+    assertEquals(null, m1.getOneofNestedMessage());
+    assertEquals("", m1.getOneofString());
+    assertEquals(0, m1.getOneofUint32());
+  }
+
+  public void testOneofExclusiveness() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    checkOneofCase(m, 0);
+
+    m.setOneofBytes(new byte[]{0, 1});
+    checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertTrue(Arrays.equals(new byte[]{0,  1}, m.getOneofBytes()));
+
+    m.setOneofEnum(TestAllTypesNano.BAZ);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    assertEquals(WireFormatNano.EMPTY_BYTES, m.getOneofBytes());
+
+    m.setOneofFixed64(-1L);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+    assertEquals(-1L, m.getOneofFixed64());
+    assertEquals(TestAllTypesNano.FOO, m.getOneofEnum());
+
+    m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+    checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+    assertEquals(
+        new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+    assertEquals(0L, m.getOneofFixed64());
+
+    m.setOneofString("hello");
+    checkOneofCase(m, TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+    assertEquals("hello", m.getOneofString());
+    assertNull(m.getOneofNestedMessage());
+
+    m.setOneofUint32(10);
+    checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+    assertEquals(10, m.getOneofUint32());
+    assertEquals("", m.getOneofString());
+
+    m.setOneofBytes(new byte[]{0, 1});
+    checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+    assertTrue(Arrays.equals(new byte[]{0,  1}, m.getOneofBytes()));
+    assertEquals(0, m.getOneofUint32());
+  }
+
+  public void testOneofClear() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    m.setOneofBytes(new byte[]{0, 1});
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofEnum(TestAllTypesNano.BAZ);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofFixed64(-1L);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofString("hello");
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+
+    m.setOneofUint32(10);
+    m.clearOneofField();
+    checkOneofCase(m, 0);
+  }
+
+  public void testOneofMarshaling() throws Exception {
+    TestAllTypesNano m = new TestAllTypesNano();
+    TestAllTypesNano parsed = new TestAllTypesNano();
+    {
+      m.setOneofBytes(new byte[]{0, 1});
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(parsed, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+      assertTrue(Arrays.equals(new byte[]{0, 1}, parsed.getOneofBytes()));
+    }
+    {
+      m.setOneofEnum(TestAllTypesNano.BAZ);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+      assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    }
+    {
+      m.setOneofEnum(TestAllTypesNano.BAZ);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+      assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+    }
+    {
+      m.setOneofFixed64(-1L);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+      assertEquals(-1L, m.getOneofFixed64());
+    }
+    {
+      m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+      assertEquals(
+          new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+    }
+    {
+      m.setOneofString("hello");
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      assertEquals("hello", m.getOneofString());
+      assertNull(m.getOneofNestedMessage());
+    }
+    {
+      m.setOneofUint32(10);
+      byte[] serialized = MessageNano.toByteArray(m);
+      MessageNano.mergeFrom(parsed, serialized);
+      checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+      assertEquals(10, m.getOneofUint32());
+    }
+  }
+
+  public void testOneofSerializedConcat() throws Exception {
+    TestAllTypesNano m1 = new TestAllTypesNano();
+    m1.setOneofBytes(new byte[] {0, 1});
+    byte[] b1 = MessageNano.toByteArray(m1);
+    TestAllTypesNano m2 = new TestAllTypesNano();
+    m2.setOneofEnum(TestAllTypesNano.BAZ);
+    byte[] b2 = MessageNano.toByteArray(m2);
+    byte[] b3 = new byte[b1.length + b2.length];
+    System.arraycopy(b1, 0, b3, 0, b1.length);
+    System.arraycopy(b2, 0, b3, b1.length, b2.length);
+    TestAllTypesNano parsed = new TestAllTypesNano();
+    MessageNano.mergeFrom(parsed, b3);
+    // the last on the wire wins.
+    checkOneofCase(parsed, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+    assertEquals(TestAllTypesNano.BAZ, parsed.getOneofEnum());
+  }
+
+  public void testNullRepeatedFields() throws Exception {
+    // Check that serialization after explicitly setting a repeated field
+    // to null doesn't NPE.
+    TestAllTypesNano message = new TestAllTypesNano();
+    message.repeatedInt32 = null;
+    MessageNano.toByteArray(message);  // should not NPE
+    message.toString(); // should not NPE
+
+    message.repeatedNestedEnum = null;
+    MessageNano.toByteArray(message);  // should not NPE
+    message.toString(); // should not NPE
+
+    message.repeatedBytes = null;
+    MessageNano.toByteArray(message); // should not NPE
+    message.toString(); // should not NPE
+
+    message.repeatedNestedMessage = null;
+    MessageNano.toByteArray(message); // should not NPE
+    message.toString(); // should not NPE
+
+    message.repeatedPackedInt32 = null;
+    MessageNano.toByteArray(message); // should not NPE
+    message.toString(); // should not NPE
+
+    message.repeatedPackedNestedEnum = null;
+    MessageNano.toByteArray(message); // should not NPE
+    message.toString(); // should not NPE
+
+    // Create a second message to merge into message.
+    TestAllTypesNano secondMessage = new TestAllTypesNano();
+    secondMessage.repeatedInt32 = new int[] {1, 2, 3};
+    secondMessage.repeatedNestedEnum = new int[] {
+      TestAllTypesNano.FOO, TestAllTypesNano.BAR
+    };
+    secondMessage.repeatedBytes = new byte[][] {{1, 2}, {3, 4}};
+    TestAllTypesNano.NestedMessage nested =
+        new TestAllTypesNano.NestedMessage();
+    nested.bb = 55;
+    secondMessage.repeatedNestedMessage =
+        new TestAllTypesNano.NestedMessage[] {nested};
+    secondMessage.repeatedPackedInt32 = new int[] {1, 2, 3};
+    secondMessage.repeatedPackedNestedEnum = new int[] {
+        TestAllTypesNano.FOO, TestAllTypesNano.BAR
+      };
+
+    // Should not NPE
+    message.mergeFrom(CodedInputByteBufferNano.newInstance(
+        MessageNano.toByteArray(secondMessage)));
+    assertEquals(3, message.repeatedInt32.length);
+    assertEquals(3, message.repeatedInt32[2]);
+    assertEquals(2, message.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.FOO, message.repeatedNestedEnum[0]);
+    assertEquals(2, message.repeatedBytes.length);
+    assertEquals(4, message.repeatedBytes[1][1]);
+    assertEquals(1, message.repeatedNestedMessage.length);
+    assertEquals(55, message.repeatedNestedMessage[0].bb);
+    assertEquals(3, message.repeatedPackedInt32.length);
+    assertEquals(2, message.repeatedPackedInt32[1]);
+    assertEquals(2, message.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.BAR, message.repeatedPackedNestedEnum[1]);
+  }
+
+  public void testNullRepeatedFieldElements() throws Exception {
+    // Check that serialization with null array elements doesn't NPE.
+    String string1 = "1";
+    String string2 = "2";
+    byte[] bytes1 = {3, 4};
+    byte[] bytes2 = {5, 6};
+    TestAllTypesNano.NestedMessage msg1 = new TestAllTypesNano.NestedMessage();
+    msg1.bb = 7;
+    TestAllTypesNano.NestedMessage msg2 = new TestAllTypesNano.NestedMessage();
+    msg2.bb = 8;
+
+    TestAllTypesNano message = new TestAllTypesNano();
+    message.repeatedString = new String[] {null, string1, string2};
+    message.repeatedBytes = new byte[][] {bytes1, null, bytes2};
+    message.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {msg1, msg2, null};
+    message.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] {null, null, null};
+
+    byte[] serialized = MessageNano.toByteArray(message); // should not NPE
+    TestAllTypesNano deserialized = MessageNano.mergeFrom(new TestAllTypesNano(), serialized);
+    assertEquals(2, deserialized.repeatedString.length);
+    assertEquals(string1, deserialized.repeatedString[0]);
+    assertEquals(string2, deserialized.repeatedString[1]);
+    assertEquals(2, deserialized.repeatedBytes.length);
+    assertTrue(Arrays.equals(bytes1, deserialized.repeatedBytes[0]));
+    assertTrue(Arrays.equals(bytes2, deserialized.repeatedBytes[1]));
+    assertEquals(2, deserialized.repeatedNestedMessage.length);
+    assertEquals(msg1.bb, deserialized.repeatedNestedMessage[0].bb);
+    assertEquals(msg2.bb, deserialized.repeatedNestedMessage[1].bb);
+    assertEquals(0, deserialized.repeatedGroup.length);
+  }
+
+  public void testRepeatedMerge() throws Exception {
+    // Check that merging repeated fields cause the arrays to expand with
+    // new data.
+    TestAllTypesNano first = new TestAllTypesNano();
+    first.repeatedInt32 = new int[] {1, 2, 3};
+    TestAllTypesNano second = new TestAllTypesNano();
+    second.repeatedInt32 = new int[] {4, 5};
+    MessageNano.mergeFrom(first, MessageNano.toByteArray(second));
+    assertEquals(5, first.repeatedInt32.length);
+    assertEquals(1, first.repeatedInt32[0]);
+    assertEquals(4, first.repeatedInt32[3]);
+
+    first = new TestAllTypesNano();
+    first.repeatedNestedEnum = new int[] {TestAllTypesNano.BAR};
+    second = new TestAllTypesNano();
+    second.repeatedNestedEnum = new int[] {TestAllTypesNano.FOO};
+    MessageNano.mergeFrom(first, MessageNano.toByteArray(second));
+    assertEquals(2, first.repeatedNestedEnum.length);
+    assertEquals(TestAllTypesNano.BAR, first.repeatedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.FOO, first.repeatedNestedEnum[1]);
+
+    first = new TestAllTypesNano();
+    first.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {
+      new TestAllTypesNano.NestedMessage()
+    };
+    first.repeatedNestedMessage[0].bb = 3;
+    second = new TestAllTypesNano();
+    second.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {
+      new TestAllTypesNano.NestedMessage()
+    };
+    second.repeatedNestedMessage[0].bb = 5;
+    MessageNano.mergeFrom(first, MessageNano.toByteArray(second));
+    assertEquals(2, first.repeatedNestedMessage.length);
+    assertEquals(3, first.repeatedNestedMessage[0].bb);
+    assertEquals(5, first.repeatedNestedMessage[1].bb);
+
+    first = new TestAllTypesNano();
+    first.repeatedPackedSfixed64 = new long[] {-1, -2, -3};
+    second = new TestAllTypesNano();
+    second.repeatedPackedSfixed64 = new long[] {-4, -5};
+    MessageNano.mergeFrom(first, MessageNano.toByteArray(second));
+    assertEquals(5, first.repeatedPackedSfixed64.length);
+    assertEquals(-1, first.repeatedPackedSfixed64[0]);
+    assertEquals(-4, first.repeatedPackedSfixed64[3]);
+
+    first = new TestAllTypesNano();
+    first.repeatedPackedNestedEnum = new int[] {TestAllTypesNano.BAR};
+    second = new TestAllTypesNano();
+    second.repeatedPackedNestedEnum = new int[] {TestAllTypesNano.FOO};
+    MessageNano.mergeFrom(first, MessageNano.toByteArray(second));
+    assertEquals(2, first.repeatedPackedNestedEnum.length);
+    assertEquals(TestAllTypesNano.BAR, first.repeatedPackedNestedEnum[0]);
+    assertEquals(TestAllTypesNano.FOO, first.repeatedPackedNestedEnum[1]);
+
+    // Now test repeated merging in a nested scope
+    TestRepeatedMergeNano firstContainer = new TestRepeatedMergeNano();
+    firstContainer.contained = new TestAllTypesNano();
+    firstContainer.contained.repeatedInt32 = new int[] {10, 20};
+    TestRepeatedMergeNano secondContainer = new TestRepeatedMergeNano();
+    secondContainer.contained = new TestAllTypesNano();
+    secondContainer.contained.repeatedInt32 = new int[] {30};
+    MessageNano.mergeFrom(firstContainer, MessageNano.toByteArray(secondContainer));
+    assertEquals(3, firstContainer.contained.repeatedInt32.length);
+    assertEquals(20, firstContainer.contained.repeatedInt32[1]);
+    assertEquals(30, firstContainer.contained.repeatedInt32[2]);
+  }
+
+  public void testRepeatedPackables() throws Exception {
+    // Check that repeated fields with packable types can accept both packed and unpacked
+    // serialized forms.
+    NanoRepeatedPackables.NonPacked nonPacked = new NanoRepeatedPackables.NonPacked();
+    // Exaggerates the first values of varint-typed arrays. This is to test that the parsing code
+    // of packed fields handles non-packed data correctly. If the code incorrectly thinks it is
+    // reading from a packed tag, it will read the first value as the byte length of the field,
+    // and the large number will cause the input to go out of bounds, thus capturing the error.
+    nonPacked.int32S = new int[] {1000, 2, 3};
+    nonPacked.int64S = new long[] {4000, 5, 6};
+    nonPacked.uint32S = new int[] {7000, 8, 9};
+    nonPacked.uint64S = new long[] {10000, 11, 12};
+    nonPacked.sint32S = new int[] {13000, 14, 15};
+    nonPacked.sint64S = new long[] {16000, 17, 18};
+    nonPacked.fixed32S = new int[] {19, 20, 21};
+    nonPacked.fixed64S = new long[] {22, 23, 24};
+    nonPacked.sfixed32S = new int[] {25, 26, 27};
+    nonPacked.sfixed64S = new long[] {28, 29, 30};
+    nonPacked.floats = new float[] {31, 32, 33};
+    nonPacked.doubles = new double[] {34, 35, 36};
+    nonPacked.bools = new boolean[] {false, true};
+    nonPacked.enums = new int[] {
+      NanoRepeatedPackables.Enum.OPTION_ONE,
+      NanoRepeatedPackables.Enum.OPTION_TWO,
+    };
+    nonPacked.noise = 13579;
+
+    byte[] nonPackedSerialized = MessageNano.toByteArray(nonPacked);
+
+    NanoRepeatedPackables.Packed packed =
+        MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), nonPackedSerialized);
+    assertRepeatedPackablesEqual(nonPacked, packed);
+
+    byte[] packedSerialized = MessageNano.toByteArray(packed);
+    // Just a cautious check that the two serialized forms are different,
+    // to make sure the remaining of this test is useful:
+    assertFalse(Arrays.equals(nonPackedSerialized, packedSerialized));
+
+    nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), packedSerialized);
+    assertRepeatedPackablesEqual(nonPacked, packed);
+
+    // Test mixed serialized form.
+    byte[] mixedSerialized = new byte[nonPackedSerialized.length + packedSerialized.length];
+    System.arraycopy(nonPackedSerialized, 0, mixedSerialized, 0, nonPackedSerialized.length);
+    System.arraycopy(packedSerialized, 0,
+        mixedSerialized, nonPackedSerialized.length, packedSerialized.length);
+
+    nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), mixedSerialized);
+    packed = MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), mixedSerialized);
+    assertRepeatedPackablesEqual(nonPacked, packed);
+    assertTrue(Arrays.equals(new int[] {1000, 2, 3, 1000, 2, 3}, nonPacked.int32S));
+    assertTrue(Arrays.equals(new int[] {13000, 14, 15, 13000, 14, 15}, nonPacked.sint32S));
+    assertTrue(Arrays.equals(new int[] {25, 26, 27, 25, 26, 27}, nonPacked.sfixed32S));
+    assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools));
+  }
+
+  public void testMapsSerializeAndParse() throws Exception {
+    TestMap origin = new TestMap();
+    setMapMessage(origin);
+    assertMapMessageSet(origin);
+
+    byte[] output = MessageNano.toByteArray(origin);
+    TestMap parsed = new TestMap();
+    MessageNano.mergeFrom(parsed, output);
+  }
+
+  public void testMapSerializeRejectNull() throws Exception {
+    TestMap primitiveMap = new TestMap();
+    primitiveMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+    primitiveMap.int32ToInt32Field.put(null, 1);
+    try {
+      MessageNano.toByteArray(primitiveMap);
+      fail("should reject null keys");
+    } catch (IllegalStateException e) {
+      // pass.
+    }
+
+    TestMap messageMap = new TestMap();
+    messageMap.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    messageMap.int32ToMessageField.put(0, null);
+    try {
+      MessageNano.toByteArray(messageMap);
+      fail("should reject null values");
+    } catch (IllegalStateException e) {
+      // pass.
+    }
+  }
+
+  /**
+   * Tests that merging bytes containing conflicting keys with override the
+   * message value instead of merging the message value into the existing entry.
+   */
+  public void testMapMergeOverrideMessageValues() throws Exception {
+    TestMap.MessageValue origValue = new TestMap.MessageValue();
+    origValue.value = 1;
+    origValue.value2 = 2;
+    TestMap.MessageValue newValue = new TestMap.MessageValue();
+    newValue.value = 3;
+
+    TestMap origMessage = new TestMap();
+    origMessage.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    origMessage.int32ToMessageField.put(1, origValue);
+
+    TestMap newMessage = new TestMap();
+    newMessage.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    newMessage.int32ToMessageField.put(1, newValue);
+    MessageNano.mergeFrom(origMessage,
+        MessageNano.toByteArray(newMessage));
+    TestMap.MessageValue mergedValue = origMessage.int32ToMessageField.get(1);
+    assertEquals(3, mergedValue.value);
+    assertEquals(0, mergedValue.value2);
+  }
+
+  /**
+   * Tests that when merging with empty entries,
+   * we will use default for the key and value, instead of null.
+   */
+  public void testMapMergeEmptyEntry() throws Exception {
+    TestMap testMap = new TestMap();
+    byte[] buffer = new byte[1024];
+    CodedOutputByteBufferNano output =
+        CodedOutputByteBufferNano.newInstance(buffer);
+    // An empty entry for int32_to_int32 map.
+    output.writeTag(1, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(0);
+    // An empty entry for int32_to_message map.
+    output.writeTag(5, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(0);
+
+    CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(
+        buffer, 0, buffer.length - output.spaceLeft());
+    testMap.mergeFrom(input);
+    assertNotNull(testMap.int32ToInt32Field);;
+    assertEquals(1, testMap.int32ToInt32Field.size());
+    assertEquals(Integer.valueOf(0), testMap.int32ToInt32Field.get(0));
+    assertNotNull(testMap.int32ToMessageField);
+    assertEquals(1, testMap.int32ToMessageField.size());
+    TestMap.MessageValue messageValue = testMap.int32ToMessageField.get(0);
+    assertNotNull(messageValue);
+    assertEquals(0, messageValue.value);
+    assertEquals(0, messageValue.value2);
+  }
+
+  public void testMapEquals() throws Exception {
+    TestMap a = new TestMap();
+    TestMap b = new TestMap();
+
+    // empty and null map fields are equal.
+    assertTestMapEqual(a, b);
+    a.int32ToBytesField = new HashMap<Integer, byte[]>();
+    assertTestMapEqual(a, b);
+
+    a.int32ToInt32Field = new HashMap<Integer, Integer>();
+    b.int32ToInt32Field = new HashMap<Integer, Integer>();
+    setMap(a.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+    setMap(b.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+    assertTestMapEqual(a, b);
+
+    a.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    b.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    setMap(a.int32ToMessageField,
+        deepCopy(int32Values), deepCopy(messageValues));
+    setMap(b.int32ToMessageField,
+        deepCopy(int32Values), deepCopy(messageValues));
+    assertTestMapEqual(a, b);
+
+    a.stringToInt32Field = new HashMap<String, Integer>();
+    b.stringToInt32Field = new HashMap<String, Integer>();
+    setMap(a.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+    setMap(b.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+    assertTestMapEqual(a, b);
+
+    a.int32ToBytesField = new HashMap<Integer, byte[]>();
+    b.int32ToBytesField = new HashMap<Integer, byte[]>();
+    setMap(a.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+    setMap(b.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+    assertTestMapEqual(a, b);
+
+    // Make sure the map implementation does not matter.
+    a.int32ToStringField = new TreeMap<Integer, String>();
+    b.int32ToStringField = new HashMap<Integer, String>();
+    setMap(a.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+    setMap(b.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+    assertTestMapEqual(a, b);
+
+    a.clear();
+    b.clear();
+
+    // unequal cases: different value
+    a.int32ToInt32Field = new HashMap<Integer, Integer>();
+    b.int32ToInt32Field = new HashMap<Integer, Integer>();
+    a.int32ToInt32Field.put(1, 1);
+    b.int32ToInt32Field.put(1, 2);
+    assertTestMapUnequal(a, b);
+    // unequal case: additional entry
+    b.int32ToInt32Field.put(1, 1);
+    b.int32ToInt32Field.put(2, 1);
+    assertTestMapUnequal(a, b);
+    a.int32ToInt32Field.put(2, 1);
+    assertTestMapEqual(a, b);
+
+    // unequal case: different message value.
+    a.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    b.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    MessageValue va = new MessageValue();
+    va.value = 1;
+    MessageValue vb = new MessageValue();
+    vb.value = 1;
+    a.int32ToMessageField.put(1, va);
+    b.int32ToMessageField.put(1, vb);
+    assertTestMapEqual(a, b);
+    vb.value = 2;
+    assertTestMapUnequal(a, b);
+  }
+
+  private static void assertTestMapEqual(TestMap a, TestMap b)
+      throws Exception {
+    assertEquals(a.hashCode(), b.hashCode());
+    assertTrue(a.equals(b));
+    assertTrue(b.equals(a));
+  }
+
+  private static void assertTestMapUnequal(TestMap a, TestMap b)
+      throws Exception {
+    assertFalse(a.equals(b));
+    assertFalse(b.equals(a));
+  }
+
+  private static final Integer[] int32Values = new Integer[] {
+    0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE,
+  };
+
+  private static final Long[] int64Values = new Long[] {
+    0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE,
+  };
+
+  private static final String[] stringValues = new String[] {
+    "", "hello", "world", "foo", "bar",
+  };
+
+  private static final byte[][] bytesValues = new byte[][] {
+    new byte[] {},
+    new byte[] {0},
+    new byte[] {1, -1},
+    new byte[] {127, -128},
+    new byte[] {'a', 'b', '0', '1'},
+  };
+
+  private static final Boolean[] boolValues = new Boolean[] {
+    false, true,
+  };
+
+  private static final Integer[] enumValues = new Integer[] {
+    TestMap.FOO, TestMap.BAR, TestMap.BAZ, TestMap.QUX,
+    Integer.MAX_VALUE /* unknown */,
+  };
+
+  private static final TestMap.MessageValue[] messageValues =
+      new TestMap.MessageValue[] {
+    newMapValueMessage(0),
+    newMapValueMessage(1),
+    newMapValueMessage(-1),
+    newMapValueMessage(Integer.MAX_VALUE),
+    newMapValueMessage(Integer.MIN_VALUE),
+  };
+
+  private static TestMap.MessageValue newMapValueMessage(int value) {
+    TestMap.MessageValue result = new TestMap.MessageValue();
+    result.value = value;
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static <T> T[] deepCopy(T[] orig) throws Exception {
+    if (orig instanceof MessageValue[]) {
+      MessageValue[] result = new MessageValue[orig.length];
+      for (int i = 0; i < orig.length; i++) {
+        result[i] = new MessageValue();
+        MessageNano.mergeFrom(
+            result[i], MessageNano.toByteArray((MessageValue) orig[i]));
+      }
+      return (T[]) result;
+    }
+    if (orig instanceof byte[][]) {
+      byte[][] result = new byte[orig.length][];
+      for (int i = 0; i < orig.length; i++) {
+        byte[] origBytes = (byte[]) orig[i];
+        result[i] = Arrays.copyOf(origBytes, origBytes.length);
+      }
+    }
+    return Arrays.copyOf(orig, orig.length);
+  }
+
+  private <K, V> void setMap(Map<K, V> map, K[] keys, V[] values) {
+    assert(keys.length == values.length);
+    for (int i = 0; i < keys.length; i++) {
+      map.put(keys[i], values[i]);
+    }
+  }
+
+  private <K, V> void assertMapSet(
+      Map<K, V> map, K[] keys, V[] values) throws Exception {
+    assert(keys.length == values.length);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals(values[i], map.get(keys[i]));
+    }
+    assertEquals(keys.length, map.size());
+  }
+
+  private void setMapMessage(TestMap testMap) {
+    testMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+    testMap.int32ToBytesField = new HashMap<Integer, byte[]>();
+    testMap.int32ToEnumField = new HashMap<Integer, Integer>();
+    testMap.int32ToMessageField =
+        new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+    testMap.int32ToStringField = new HashMap<Integer, String>();
+    testMap.stringToInt32Field = new HashMap<String, Integer>();
+    testMap.boolToBoolField = new HashMap<Boolean, Boolean>();
+    testMap.uint32ToUint32Field = new HashMap<Integer, Integer>();
+    testMap.sint32ToSint32Field = new HashMap<Integer, Integer>();
+    testMap.fixed32ToFixed32Field = new HashMap<Integer, Integer>();
+    testMap.sfixed32ToSfixed32Field = new HashMap<Integer, Integer>();
+    testMap.int64ToInt64Field = new HashMap<Long, Long>();
+    testMap.uint64ToUint64Field = new HashMap<Long, Long>();
+    testMap.sint64ToSint64Field = new HashMap<Long, Long>();
+    testMap.fixed64ToFixed64Field = new HashMap<Long, Long>();
+    testMap.sfixed64ToSfixed64Field = new HashMap<Long, Long>();
+    setMap(testMap.int32ToInt32Field, int32Values, int32Values);
+    setMap(testMap.int32ToBytesField, int32Values, bytesValues);
+    setMap(testMap.int32ToEnumField, int32Values, enumValues);
+    setMap(testMap.int32ToMessageField, int32Values, messageValues);
+    setMap(testMap.int32ToStringField, int32Values, stringValues);
+    setMap(testMap.stringToInt32Field, stringValues, int32Values);
+    setMap(testMap.boolToBoolField, boolValues, boolValues);
+    setMap(testMap.uint32ToUint32Field, int32Values, int32Values);
+    setMap(testMap.sint32ToSint32Field, int32Values, int32Values);
+    setMap(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+    setMap(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+    setMap(testMap.int64ToInt64Field, int64Values, int64Values);
+    setMap(testMap.uint64ToUint64Field, int64Values, int64Values);
+    setMap(testMap.sint64ToSint64Field, int64Values, int64Values);
+    setMap(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+    setMap(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+  }
+  private void assertMapMessageSet(TestMap testMap) throws Exception {
+    assertMapSet(testMap.int32ToInt32Field, int32Values, int32Values);
+    assertMapSet(testMap.int32ToBytesField, int32Values, bytesValues);
+    assertMapSet(testMap.int32ToEnumField, int32Values, enumValues);
+    assertMapSet(testMap.int32ToMessageField, int32Values, messageValues);
+    assertMapSet(testMap.int32ToStringField, int32Values, stringValues);
+    assertMapSet(testMap.stringToInt32Field, stringValues, int32Values);
+    assertMapSet(testMap.boolToBoolField, boolValues, boolValues);
+    assertMapSet(testMap.uint32ToUint32Field, int32Values, int32Values);
+    assertMapSet(testMap.sint32ToSint32Field, int32Values, int32Values);
+    assertMapSet(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+    assertMapSet(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+    assertMapSet(testMap.int64ToInt64Field, int64Values, int64Values);
+    assertMapSet(testMap.uint64ToUint64Field, int64Values, int64Values);
+    assertMapSet(testMap.sint64ToSint64Field, int64Values, int64Values);
+    assertMapSet(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+    assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+  }
+
+  public void testRepeatedFieldInitializedInReftypesCompatMode() {
+    NanoReferenceTypesCompat.TestAllTypesNano proto = new NanoReferenceTypesCompat.TestAllTypesNano();
+    assertNotNull(proto.repeatedString);
+  }
+
+  private void assertRepeatedPackablesEqual(
+      NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
+    // Not using MessageNano.equals() -- that belongs to a separate test.
+    assertTrue(Arrays.equals(nonPacked.int32S, packed.int32S));
+    assertTrue(Arrays.equals(nonPacked.int64S, packed.int64S));
+    assertTrue(Arrays.equals(nonPacked.uint32S, packed.uint32S));
+    assertTrue(Arrays.equals(nonPacked.uint64S, packed.uint64S));
+    assertTrue(Arrays.equals(nonPacked.sint32S, packed.sint32S));
+    assertTrue(Arrays.equals(nonPacked.sint64S, packed.sint64S));
+    assertTrue(Arrays.equals(nonPacked.fixed32S, packed.fixed32S));
+    assertTrue(Arrays.equals(nonPacked.fixed64S, packed.fixed64S));
+    assertTrue(Arrays.equals(nonPacked.sfixed32S, packed.sfixed32S));
+    assertTrue(Arrays.equals(nonPacked.sfixed64S, packed.sfixed64S));
+    assertTrue(Arrays.equals(nonPacked.floats, packed.floats));
+    assertTrue(Arrays.equals(nonPacked.doubles, packed.doubles));
+    assertTrue(Arrays.equals(nonPacked.bools, packed.bools));
+    assertTrue(Arrays.equals(nonPacked.enums, packed.enums));
+  }
+
+  public void testClone() throws Exception {
+    // A simple message.
+    AnotherMessage anotherMessage = new AnotherMessage();
+    anotherMessage.string = "Hello";
+    anotherMessage.value = true;
+    anotherMessage.integers = new int[] { 1, 2, 3 };
+
+    AnotherMessage clone = anotherMessage.clone();
+    assertEquals(clone, anotherMessage);
+
+    // Verify it was a deep clone - changes to the clone shouldn't affect the
+    // original.
+    clone.integers[1] = 100;
+    assertFalse(clone.equals(anotherMessage));
+  }
+
+  private void assertHasWireData(MessageNano message, boolean expected) {
+    byte[] bytes = MessageNano.toByteArray(message);
+    int wireLength = bytes.length;
+    if (expected) {
+      assertFalse(wireLength == 0);
+    } else {
+      if (wireLength != 0) {
+        fail("Expected no wire data for message \n" + message
+            + "\nBut got:\n"
+            + hexDump(bytes));
+      }
+    }
+  }
+
+  private static String hexDump(byte[] bytes) {
+    StringBuilder sb = new StringBuilder();
+    for (byte b : bytes) {
+      sb.append(String.format("%02x ", b));
+    }
+    return sb.toString();
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/map_test.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
new file mode 100644
index 0000000..51498a4
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
@@ -0,0 +1,70 @@
+// 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.
+
+syntax = "proto3";
+
+package map_test;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "MapTestProto";
+
+message TestMap {
+  message MessageValue {
+    int32 value = 1;
+    int32 value2 = 2;
+  }
+  enum EnumValue {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+
+  map<int32, int32>        int32_to_int32_field = 1;
+  map<int32, string>       int32_to_string_field = 2;
+  map<int32, bytes>        int32_to_bytes_field = 3;
+  map<int32, EnumValue>    int32_to_enum_field = 4;
+  map<int32, MessageValue> int32_to_message_field = 5;
+  map<string, int32>       string_to_int32_field = 6;
+  map<bool, bool>          bool_to_bool_field = 7;
+
+  // Test all the other primitive types. As the key and value are not coupled in
+  // the implementation, we do not test all the combinations of key/value pairs,
+  // so that we can keep the number of test cases manageable
+  map<uint32, uint32>      uint32_to_uint32_field = 11;
+  map<sint32, sint32>      sint32_to_sint32_field = 12;
+  map<fixed32, fixed32>    fixed32_to_fixed32_field = 13;
+  map<sfixed32, sfixed32>  sfixed32_to_sfixed32_field = 14;
+  map<int64, int64>        int64_to_int64_field = 15;
+  map<uint64, uint64>      uint64_to_uint64_field = 16;
+  map<sint64, sint64>      sint64_to_sint64_field = 17;
+  map<fixed64, fixed64>    fixed64_to_fixed64_field = 18;
+  map<sfixed64, sfixed64>  sfixed64_to_sfixed64_field = 19;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto
new file mode 100644
index 0000000..6511e47
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto
@@ -0,0 +1,118 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "NanoAccessorsOuterClass";
+
+message TestNanoAccessors {
+
+  message NestedMessage {
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  // Singular
+  optional int32  optional_int32    =  1;
+  optional float  optional_float    = 11;
+  optional double optional_double   = 12;
+  optional string optional_string   = 14;
+  optional bytes  optional_bytes    = 15;
+
+  optional NestedMessage optional_nested_message = 18;
+
+  optional NestedEnum optional_nested_enum = 21;
+
+  // Repeated
+  repeated int32  repeated_int32    = 31;
+  repeated string repeated_string   = 44;
+  repeated bytes  repeated_bytes    = 45;
+
+  repeated NestedMessage repeated_nested_message  = 48;
+
+  repeated NestedEnum repeated_nested_enum  = 51;
+
+  // Singular with defaults
+  optional int32  default_int32    = 61 [default =  41    ];
+  optional string default_string   = 74 [default = "hello"];
+  optional bytes  default_bytes    = 75 [default = "world"];
+
+  optional float default_float_nan = 99  [default =  nan];
+
+  optional NestedEnum default_nested_enum = 81 [default = BAR];
+
+  // Required
+  required int32 id = 86;
+
+  // Add enough optional fields to make 2 bit fields in total
+  optional int32 filler100 = 100;
+  optional int32 filler101 = 101;
+  optional int32 filler102 = 102;
+  optional int32 filler103 = 103;
+  optional int32 filler104 = 104;
+  optional int32 filler105 = 105;
+  optional int32 filler106 = 106;
+  optional int32 filler107 = 107;
+  optional int32 filler108 = 108;
+  optional int32 filler109 = 109;
+  optional int32 filler110 = 110;
+  optional int32 filler111 = 111;
+  optional int32 filler112 = 112;
+  optional int32 filler113 = 113;
+  optional int32 filler114 = 114;
+  optional int32 filler115 = 115;
+  optional int32 filler116 = 116;
+  optional int32 filler117 = 117;
+  optional int32 filler118 = 118;
+  optional int32 filler119 = 119;
+  optional int32 filler120 = 120;
+  optional int32 filler121 = 121;
+  optional int32 filler122 = 122;
+  optional int32 filler123 = 123;
+  optional int32 filler124 = 124;
+  optional int32 filler125 = 125;
+  optional int32 filler126 = 126;
+  optional int32 filler127 = 127;
+  optional int32 filler128 = 128;
+  optional int32 filler129 = 129;
+  optional int32 filler130 = 130;
+
+  optional int32 before_bit_field_check = 139;
+  optional int32 bit_field_check = 140;
+  optional int32 after_bit_field_check = 141;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto
new file mode 100644
index 0000000..958e1f1
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto
@@ -0,0 +1,48 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_multiple_files = true;
+
+enum FileScopeEnumMultiple {
+  THREE = 3;
+}
+
+message EnumClassNanoMultiple {
+  enum MessageScopeEnumMultiple {
+    FOUR = 4;
+  }
+  optional FileScopeEnumMultiple three = 3 [ default = THREE ];
+  optional MessageScopeEnumMultiple four = 4 [ default = FOUR ];
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto
new file mode 100644
index 0000000..3a1e07f
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto
@@ -0,0 +1,48 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "EnumClassNanos";
+
+enum FileScopeEnum {
+  ONE = 1;
+}
+
+message EnumClassNano {
+  enum MessageScopeEnum {
+    TWO = 2;
+  }
+  optional FileScopeEnum one = 1 [ default = ONE ];
+  optional MessageScopeEnum two = 2 [ default = TWO ];
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto
new file mode 100644
index 0000000..c0da8b4
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto
@@ -0,0 +1,28 @@
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "EnumValidity";
+
+enum E {
+  default = 1; // test java keyword renaming
+  FOO = 2;
+  BAR = 3;
+  BAZ = 4;
+}
+
+message M {
+  optional E optional_e = 1;
+  optional E default_e = 2 [ default = BAZ ];
+  repeated E repeated_e = 3;
+  repeated E packed_e = 4 [ packed = true ];
+  repeated E repeated_e2 = 5;
+  repeated E packed_e2 = 6 [ packed = true ];
+  repeated E repeated_e3 = 7;
+  repeated E packed_e3 = 8 [ packed = true ];
+}
+
+message Alt {
+  optional E repeated_e2_as_optional = 5;
+  repeated E packed_e2_as_non_packed = 6;
+  repeated E non_packed_e3_as_packed = 7 [ packed = true ];
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto
new file mode 100644
index 0000000..ca56b3d
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto
@@ -0,0 +1,37 @@
+syntax = "proto2";
+
+option java_outer_classname = "Extensions";
+option java_package = "com.google.protobuf.nano.testext";
+
+message ExtendableMessage {
+  optional int32 field = 1;
+  extensions 10 to max;
+}
+
+enum AnEnum {
+  FIRST_VALUE = 1;
+  SECOND_VALUE = 2;
+}
+
+message AnotherMessage {
+  optional string string = 1;
+  optional bool value = 2;
+  repeated int32 integers = 3;
+}
+
+message ContainerMessage {
+  extend ExtendableMessage {
+    optional bool another_thing = 100;
+    // The largest permitted field number, per
+    // https://developers.google.com/protocol-buffers/docs/proto#simple
+    optional bool large_field_number = 536870911;
+  }
+}
+
+// For testNanoOptionalGroupWithUnknownFieldsEnabled;
+// not part of the extensions tests.
+message MessageWithGroup {
+  optional group Group = 1 {
+    optional int32 a = 2;
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto
new file mode 100644
index 0000000..3b7a004
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto
@@ -0,0 +1,29 @@
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "com.google.protobuf";
+
+import "google/protobuf/nano/unittest_extension_nano.proto";
+
+// Must be compiled separately due to extension number reuse.
+// The reuse is deliberate, for testing wire compatibility.
+
+message PackedExtensions {
+  extend ExtendableMessage {
+    repeated int32    packed_int32    = 10 [ packed = true ];
+    repeated uint32   packed_uint32   = 11 [ packed = true ];
+    repeated sint32   packed_sint32   = 12 [ packed = true ];
+    repeated int64    packed_int64    = 13 [ packed = true ];
+    repeated uint64   packed_uint64   = 14 [ packed = true ];
+    repeated sint64   packed_sint64   = 15 [ packed = true ];
+    repeated fixed32  packed_fixed32  = 16 [ packed = true ];
+    repeated sfixed32 packed_sfixed32 = 17 [ packed = true ];
+    repeated fixed64  packed_fixed64  = 18 [ packed = true ];
+    repeated sfixed64 packed_sfixed64 = 19 [ packed = true ];
+    repeated bool     packed_bool     = 20 [ packed = true ];
+    repeated float    packed_float    = 21 [ packed = true ];
+    repeated double   packed_double   = 22 [ packed = true ];
+    repeated AnEnum   packed_enum     = 23 [ packed = true ];
+    // Non-packable types omitted.
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto
new file mode 100644
index 0000000..e533c65
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto
@@ -0,0 +1,34 @@
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "com.google.protobuf";
+
+import "google/protobuf/nano/unittest_extension_nano.proto";
+
+// Must be compiled separately due to extension number reuse.
+// The reuse is deliberate, for testing wire compatibility.
+
+message RepeatedExtensions {
+  extend ExtendableMessage {
+    repeated int32          repeated_int32    = 10;
+    repeated uint32         repeated_uint32   = 11;
+    repeated sint32         repeated_sint32   = 12;
+    repeated int64          repeated_int64    = 13;
+    repeated uint64         repeated_uint64   = 14;
+    repeated sint64         repeated_sint64   = 15;
+    repeated fixed32        repeated_fixed32  = 16;
+    repeated sfixed32       repeated_sfixed32 = 17;
+    repeated fixed64        repeated_fixed64  = 18;
+    repeated sfixed64       repeated_sfixed64 = 19;
+    repeated bool           repeated_bool     = 20;
+    repeated float          repeated_float    = 21;
+    repeated double         repeated_double   = 22;
+    repeated AnEnum         repeated_enum     = 23;
+    repeated string         repeated_string   = 24;
+    repeated bytes          repeated_bytes    = 25;
+    repeated AnotherMessage repeated_message  = 26;
+    repeated group          RepeatedGroup     = 27 {
+      optional int32 a = 1;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto
new file mode 100644
index 0000000..8b2d965
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto
@@ -0,0 +1,34 @@
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "com.google.protobuf";
+
+import "google/protobuf/nano/unittest_extension_nano.proto";
+
+// Must be compiled separately due to extension number reuse.
+// The reuse is deliberate, for testing wire compatibility.
+
+message SingularExtensions {
+  extend ExtendableMessage {
+    optional int32          some_int32    = 10;
+    optional uint32         some_uint32   = 11;
+    optional sint32         some_sint32   = 12;
+    optional int64          some_int64    = 13;
+    optional uint64         some_uint64   = 14;
+    optional sint64         some_sint64   = 15;
+    optional fixed32        some_fixed32  = 16;
+    optional sfixed32       some_sfixed32 = 17;
+    optional fixed64        some_fixed64  = 18;
+    optional sfixed64       some_sfixed64 = 19;
+    optional bool           some_bool     = 20;
+    optional float          some_float    = 21;
+    optional double         some_double   = 22;
+    optional AnEnum         some_enum     = 23;
+    optional string         some_string   = 24;
+    optional bytes          some_bytes    = 25;
+    optional AnotherMessage some_message  = 26;
+    optional group          SomeGroup     = 27 {
+      optional int32 a = 1;
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto
new file mode 100644
index 0000000..fe7d179
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto
@@ -0,0 +1,82 @@
+// 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.
+
+// Author: ulas@google.com (Ulas Kirazci)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "NanoHasOuterClass";
+
+message TestAllTypesNanoHas {
+
+  message NestedMessage {
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  // Singular
+  optional int32  optional_int32    =  1;
+  optional float  optional_float    = 11;
+  optional double optional_double   = 12;
+  optional string optional_string   = 14;
+  optional bytes  optional_bytes    = 15;
+
+  optional NestedMessage optional_nested_message = 18;
+
+  optional NestedEnum optional_nested_enum = 21;
+
+  // Repeated
+  repeated int32  repeated_int32    = 31;
+  repeated string repeated_string   = 44;
+  repeated bytes  repeated_bytes    = 45;
+
+  repeated NestedMessage repeated_nested_message  = 48;
+
+  repeated NestedEnum repeated_nested_enum  = 51;
+
+  // Singular with defaults
+  optional int32  default_int32    = 61 [default =  41    ];
+  optional string default_string   = 74 [default = "hello"];
+  optional bytes  default_bytes    = 75 [default = "world"];
+
+  optional float default_float_nan = 99  [default =  nan];
+
+  optional NestedEnum default_nested_enum = 81 [default = BAR];
+
+  required int32 id = 86;
+  required NestedEnum required_enum = 87;
+
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto
new file mode 100644
index 0000000..1a3ddc5
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto
@@ -0,0 +1,48 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = NANO_RUNTIME.
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.nano.testimport";
+option java_outer_classname = "UnittestImportNano";
+
+message ImportMessageNano {
+  optional int32 d = 1;
+}
+
+enum ImportEnumNano {
+  IMPORT_NANO_FOO = 7;
+  IMPORT_NANO_BAR = 8;
+  IMPORT_NANO_BAZ = 9;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto
new file mode 100644
index 0000000..b31c439
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto
@@ -0,0 +1,41 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "MultipleNameClashNano";
+option java_multiple_files = true;
+
+message MultipleNameClashNano {
+  optional int32 field = 1;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto
new file mode 100644
index 0000000..406ab77
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto
@@ -0,0 +1,63 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest_import;
+
+import "google/protobuf/nano/unittest_import_nano.proto";
+
+option java_package = "com.google.protobuf";
+option java_multiple_files = true;
+
+enum FileScopeEnum {
+  ONE = 1;
+  TWO = 2;
+}
+
+message FileScopeEnumRefNano {
+  optional FileScopeEnum enum_field = 1;
+}
+
+message MessageScopeEnumRefNano {
+  enum MessageScopeEnum {
+    ONE = 1;
+    TWO = 2;
+  }
+  optional MessageScopeEnum enum_field = 1;
+}
+
+message MultipleImportingNonMultipleNano1 {
+  optional ImportMessageNano field = 1;
+}
+
+message MultipleImportingNonMultipleNano2 {
+  optional MultipleImportingNonMultipleNano1 nano1 = 1;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
new file mode 100644
index 0000000..3fff24c
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
@@ -0,0 +1,195 @@
+// 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.
+
+// Author: wink@google.com (Wink Saville)
+
+package protobuf_unittest;
+
+import "google/protobuf/nano/unittest_import_nano.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "NanoOuterClass";
+
+// Same as TestAllTypes but with the nano runtime.
+message TestAllTypesNano {
+
+  message NestedMessage {
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage      optional_nested_message  = 18;
+  optional ForeignMessageNano optional_foreign_message = 19;
+  optional protobuf_unittest_import.ImportMessageNano
+    optional_import_message = 20;
+
+  optional NestedEnum      optional_nested_enum     = 21;
+  optional ForeignEnumNano optional_foreign_enum    = 22;
+  optional protobuf_unittest_import.ImportEnumNano optional_import_enum = 23;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage      repeated_nested_message  = 48;
+  repeated ForeignMessageNano repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessageNano
+    repeated_import_message = 50;
+
+  repeated NestedEnum      repeated_nested_enum  = 51;
+  repeated ForeignEnumNano repeated_foreign_enum = 52;
+  repeated protobuf_unittest_import.ImportEnumNano repeated_import_enum = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Repeated packed
+  repeated    int32 repeated_packed_int32    = 87 [packed=true];
+  repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
+
+  repeated NestedEnum repeated_packed_nested_enum  = 89 [packed=true];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+  optional string default_string_nonascii = 76 [default = "dünya"];
+  optional  bytes default_bytes_nonascii  = 77 [default = "dünyab"];
+
+  optional  float default_float_inf      = 97  [default =  inf];
+  optional  float default_float_neg_inf  = 98  [default = -inf];
+  optional  float default_float_nan      = 99  [default =  nan];
+  optional double default_double_inf     = 100 [default =  inf];
+  optional double default_double_neg_inf = 101 [default = -inf];
+  optional double default_double_nan     = 102 [default =  nan];
+
+  optional NestedEnum default_nested_enum = 81 [default = BAR];
+  optional ForeignEnumNano default_foreign_enum = 82
+      [default = FOREIGN_NANO_BAR];
+  optional protobuf_unittest_import.ImportEnumNano
+      default_import_enum = 83 [default = IMPORT_NANO_BAR];
+
+  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+  optional string default_cord = 85 [ctype=CORD,default="123"];
+
+  required int32 id = 86;
+
+  // Try to cause conflicts.
+  optional int32 tag = 93;
+  optional int32 get_serialized_size = 94;
+  optional int32 write_to = 95;
+
+  // Try to fail with java reserved keywords
+  optional int32 synchronized = 96;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 123;
+    bytes oneof_bytes = 124;
+    fixed64 oneof_fixed64 = 115;
+    NestedEnum oneof_enum = 116;
+  }
+}
+
+message ForeignMessageNano {
+  optional int32 c = 1;
+}
+
+enum ForeignEnumNano {
+  FOREIGN_NANO_FOO = 4;
+  FOREIGN_NANO_BAR = 5;
+  FOREIGN_NANO_BAZ = 6;
+}
+
+// Test that deprecated fields work.  We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedNano {
+  optional int32 deprecated_field = 1 [deprecated = true];
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto
new file mode 100644
index 0000000..29b944f
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto
@@ -0,0 +1,49 @@
+// 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestRecursiveNano";
+
+message RecursiveMessageNano {
+  message NestedMessage {
+    optional RecursiveMessageNano a = 1;
+  }
+
+  required int32 id = 1;
+  optional NestedMessage nested_message = 2;
+  optional RecursiveMessageNano optional_recursive_message_nano = 3;
+  repeated RecursiveMessageNano repeated_recursive_message_nano = 4;
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto
new file mode 100644
index 0000000..82eb8d1
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto
@@ -0,0 +1,116 @@
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "NanoReferenceTypes";
+
+message TestAllTypesNano {
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  message NestedMessage {
+    optional int32 foo = 1;
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage      optional_nested_message  = 18;
+
+  optional NestedEnum      optional_nested_enum     = 21;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage      repeated_nested_message  = 48;
+
+  repeated NestedEnum      repeated_nested_enum  = 51;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Repeated packed
+  repeated    int32 repeated_packed_int32    = 87 [packed=true];
+  repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
+
+  repeated NestedEnum repeated_packed_nested_enum  = 89 [packed=true];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+
+  optional  float default_float_inf      = 97  [default =  inf];
+  optional  float default_float_neg_inf  = 98  [default = -inf];
+  optional  float default_float_nan      = 99  [default =  nan];
+  optional double default_double_inf     = 100 [default =  inf];
+  optional double default_double_neg_inf = 101 [default = -inf];
+  optional double default_double_nan     = 102 [default =  nan];
+
+}
+
+message ForeignMessageNano {
+  optional int32 c = 1;
+}
+
+enum ForeignEnumNano {
+  FOREIGN_NANO_FOO = 4;
+  FOREIGN_NANO_BAR = 5;
+  FOREIGN_NANO_BAZ = 6;
+}
+
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto
new file mode 100644
index 0000000..ef4e2d2
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto
@@ -0,0 +1,47 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+import "google/protobuf/nano/unittest_nano.proto";
+
+option java_package = "com.google.protobuf";
+option java_multiple_files = true;
+
+// A container message for testing the merging of repeated fields at a
+// nested level. Other tests will be done using the repeated fields in
+// TestAllTypesNano.
+message TestRepeatedMergeNano {
+
+  optional TestAllTypesNano contained = 1;
+
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto
new file mode 100644
index 0000000..96af885
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto
@@ -0,0 +1,95 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "NanoRepeatedPackables";
+
+enum Enum {
+  OPTION_ONE = 1;
+  OPTION_TWO = 2;
+}
+
+// Two almost identical messages with all packable repeated field types.
+// One with none marked as packed and the other all packed. For
+// compatibility, they should be able to parse each other's serialized
+// forms.
+
+message NonPacked {
+
+  // All packable types, none marked as packed.
+
+  repeated    int32 int32s    = 1;
+  repeated    int64 int64s    = 2;
+  repeated   uint32 uint32s   = 3;
+  repeated   uint64 uint64s   = 4;
+  repeated   sint32 sint32s   = 5;
+  repeated   sint64 sint64s   = 6;
+  repeated  fixed32 fixed32s  = 7;
+  repeated  fixed64 fixed64s  = 8;
+  repeated sfixed32 sfixed32s = 9;
+  repeated sfixed64 sfixed64s = 10;
+  repeated    float floats    = 11;
+  repeated   double doubles   = 12;
+  repeated     bool bools     = 13;
+  repeated     Enum enums     = 14;
+
+  // Noise for testing merged deserialization.
+  optional int32 noise = 15;
+
+}
+
+message Packed {
+
+  // All packable types, all matching the field numbers in NonPacked,
+  // all marked as packed.
+
+  repeated    int32 int32s    = 1  [ packed = true ];
+  repeated    int64 int64s    = 2  [ packed = true ];
+  repeated   uint32 uint32s   = 3  [ packed = true ];
+  repeated   uint64 uint64s   = 4  [ packed = true ];
+  repeated   sint32 sint32s   = 5  [ packed = true ];
+  repeated   sint64 sint64s   = 6  [ packed = true ];
+  repeated  fixed32 fixed32s  = 7  [ packed = true ];
+  repeated  fixed64 fixed64s  = 8  [ packed = true ];
+  repeated sfixed32 sfixed32s = 9  [ packed = true ];
+  repeated sfixed64 sfixed64s = 10 [ packed = true ];
+  repeated    float floats    = 11 [ packed = true ];
+  repeated   double doubles   = 12 [ packed = true ];
+  repeated     bool bools     = 13 [ packed = true ];
+  repeated     Enum enums     = 14 [ packed = true ];
+
+  // Noise for testing merged deserialization.
+  optional int32 noise = 15;
+
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto
new file mode 100644
index 0000000..25786cc
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto
@@ -0,0 +1,54 @@
+// 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestSimpleNano";
+
+message SimpleMessageNano {
+  message NestedMessage {
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  optional int32 d = 1 [default = 123];
+  optional NestedMessage nested_msg = 2;
+  optional NestedEnum default_nested_enum = 3 [default = BAZ];
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto
new file mode 100644
index 0000000..7de30c8
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto
@@ -0,0 +1,38 @@
+// 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.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf";
+
+message SingleMessageNano {
+}
diff --git a/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto
new file mode 100644
index 0000000..bbd677c
--- /dev/null
+++ b/src/third_party/protobuf-3/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto
@@ -0,0 +1,43 @@
+// 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestStringutf8Nano";
+
+message StringUtf8 {
+  optional string id = 1;
+  repeated string rs = 2;
+}
diff --git a/src/third_party/protobuf-3/jenkins/README.md b/src/third_party/protobuf-3/jenkins/README.md
new file mode 100644
index 0000000..29f664f
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/README.md
@@ -0,0 +1,6 @@
+
+Jenkins Infrastructure
+----------------------
+
+The scripts in this directory serve as plumbing for running the protobuf
+tests under Jenkins.
diff --git a/src/third_party/protobuf-3/jenkins/build_and_run_docker.sh b/src/third_party/protobuf-3/jenkins/build_and_run_docker.sh
new file mode 100755
index 0000000..abc6f05
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/build_and_run_docker.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# Builds docker image and runs a command under it.
+# This is a generic script that is configured with the following variables:
+#
+# DOCKERFILE_DIR - Directory in which Dockerfile file is located.
+# DOCKER_RUN_SCRIPT - Script to run under docker (relative to protobuf repo root)
+# OUTPUT_DIR - Directory that will be copied from inside docker after finishing.
+# $@ - Extra args to pass to docker run
+
+
+set -ex
+
+cd $(dirname $0)/..
+git_root=$(pwd)
+cd -
+
+# Use image name based on Dockerfile location checksum
+DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
+
+# Make sure docker image has been built. Should be instantaneous if so.
+docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR
+
+# Ensure existence of ccache directory
+CCACHE_DIR=/tmp/protobuf-ccache
+mkdir -p $CCACHE_DIR
+
+# Choose random name for docker container
+CONTAINER_NAME="build_and_run_docker_$(uuidgen)"
+
+# Run command inside docker
+docker run \
+  "$@" \
+  -e CCACHE_DIR=$CCACHE_DIR \
+  -e EXTERNAL_GIT_ROOT="/var/local/jenkins/protobuf" \
+  -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
+  -v "$git_root:/var/local/jenkins/protobuf:ro" \
+  -v $CCACHE_DIR:$CCACHE_DIR \
+  -w /var/local/git/protobuf \
+  --name=$CONTAINER_NAME \
+  $DOCKER_IMAGE_NAME \
+  bash -l "/var/local/jenkins/protobuf/$DOCKER_RUN_SCRIPT" || FAILED="true"
+
+# Copy output artifacts
+if [ "$OUTPUT_DIR" != "" ]
+then
+  docker cp "$CONTAINER_NAME:/var/local/git/protobuf/$OUTPUT_DIR" "$git_root" || FAILED="true"
+fi
+
+# remove the container, possibly killing it first
+docker rm -f $CONTAINER_NAME || true
+
+if [ "$FAILED" != "" ]
+then
+  exit 1
+fi
diff --git a/src/third_party/protobuf-3/jenkins/buildcmds/README.md b/src/third_party/protobuf-3/jenkins/buildcmds/README.md
new file mode 100644
index 0000000..7a48f2d
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/buildcmds/README.md
@@ -0,0 +1,6 @@
+
+Jenkins Build Commands
+----------------------
+
+The scripts in this directory are designed to be top-level entry points for
+Jenkins projects.
diff --git a/src/third_party/protobuf-3/jenkins/buildcmds/pull_request.sh b/src/third_party/protobuf-3/jenkins/buildcmds/pull_request.sh
new file mode 100755
index 0000000..01fda79
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/buildcmds/pull_request.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Jenkins as the entry point for
+# running the "pull request" project:
+#
+#   https://grpc-testing.appspot.com/view/Protocol%20Buffers/job/protobuf_pull_request/
+#
+# This script selects a specific Dockerfile (for building a Docker image) and
+# a script to run inside that image.  Then we delegate to the general
+# build_and_run_docker.sh script.
+
+export DOCKERFILE_DIR=jenkins/docker
+export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh
+export OUTPUT_DIR=testoutput
+./jenkins/build_and_run_docker.sh
diff --git a/src/third_party/protobuf-3/jenkins/docker/Dockerfile b/src/third_party/protobuf-3/jenkins/docker/Dockerfile
new file mode 100644
index 0000000..8467aef
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/docker/Dockerfile
@@ -0,0 +1,130 @@
+# This Dockerfile specifies the recipe for creating an image for the tests
+# to run in.
+#
+# We install as many test dependencies here as we can, because these setup
+# steps can be cached.  They do *not* run every time we run the build.
+# The Docker image is only rebuilt when the Dockerfile (ie. this file)
+# changes.
+
+# Base Dockerfile for gRPC dev images
+FROM debian:latest
+
+# Apt source for old Python versions.
+RUN echo 'deb http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu trusty main' > /etc/apt/sources.list.d/deadsnakes.list && \
+  apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DB82666C
+
+# Apt source for Oracle Java.
+run echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \
+  apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886 && \
+  echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections
+
+# Apt source for Mono
+run echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \
+  echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list && \
+  apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+
+# Install dependencies.  We start with the basic ones require to build protoc
+# and the C++ build
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  git \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  parallel \
+  time \
+  wget \
+  # -- For csharp --
+  mono-devel \
+  referenceassemblies-pcl \
+  nunit \
+  # -- For all Java builds -- \
+  maven \
+  # -- For java_jdk6 -- \
+  #   oops! not in jessie. too old? openjdk-6-jdk \
+  # -- For java_jdk7 -- \
+  openjdk-7-jdk \
+  # -- For java_oracle7 -- \
+  oracle-java7-installer \
+  # -- For python / python_cpp -- \
+  python-setuptools \
+  python-pip \
+  python-dev \
+  python2.6-dev \
+  python3.3-dev \
+  python3.4-dev \
+  # -- For Ruby --
+  ruby \
+  && apt-get clean
+
+##################
+# C# dependencies
+
+RUN wget www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe
+
+##################
+# Python dependencies
+
+# These packages exist in apt-get, but their versions are too old, so we have
+# to get updates from pip.
+
+RUN pip install pip --upgrade
+RUN pip install virtualenv tox yattag
+
+
+##################
+# Ruby dependencies
+
+# Install rvm
+RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+RUN \curl -sSL https://get.rvm.io | bash -s stable
+
+# Install Ruby 2.1
+RUN /bin/bash -l -c "rvm install ruby-2.1"
+RUN /bin/bash -l -c "rvm use --default ruby-2.1"
+RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
+RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
+RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
+
+##################
+# Java dependencies
+
+# This step requires compiling protoc. :(
+
+ENV MAVEN_REPO /var/maven_local_repository
+ENV MVN mvn --batch-mode
+
+RUN cd /tmp && \
+  git clone https://github.com/google/protobuf.git && \
+  cd protobuf && \
+  ./autogen.sh && \
+  ./configure && \
+  make -j6 && \
+  cd java && \
+  $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO -P lite && \
+  $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO && \
+  cd ../javanano && \
+  $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO
+
+##################
+# Prepare ccache
+
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+# Define the default command.
+CMD ["bash"]
diff --git a/src/third_party/protobuf-3/jenkins/make_test_output.py b/src/third_party/protobuf-3/jenkins/make_test_output.py
new file mode 100644
index 0000000..b1f2e2c
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/make_test_output.py
@@ -0,0 +1,91 @@
+"""Gathers output from test runs and create an XML file in JUnit format.
+
+The output files from the individual tests have been written in a directory
+structure like:
+
+  $DIR/joblog  (output from "parallel --joblog joblog")
+  $DIR/logs/1/cpp/stdout
+  $DIR/logs/1/cpp/stderr
+  $DIR/logs/1/csharp/stdout
+  $DIR/logs/1/csharp/stderr
+  $DIR/logs/1/java_jdk7/stdout
+  $DIR/logs/1/java_jdk7/stderr
+  etc.
+
+This script bundles them into a single output XML file so Jenkins can show
+detailed test results.  It runs as the last step before the Jenkins build
+finishes.
+"""
+
+import os;
+import sys;
+from yattag import Doc
+from collections import defaultdict
+
+def readtests(basedir):
+  tests = defaultdict(dict)
+
+  # Sample input (note: separators are tabs).
+  #
+  # Seq	Host	Starttime	Runtime	Send	Receive	Exitval	Signal	Command
+  # 1	:	1456263838.313	0.005	0	0	0	0	echo A
+  with open(basedir + "/joblog") as jobs:
+    firstline = next(jobs)
+    for line in jobs:
+      values = line.split("\t")
+
+      name = values[8].split()[-1]
+      test = tests[name]
+      test["name"] = name
+      test["time"] = values[3]
+
+      exitval = values[6]
+      if int(exitval):
+        # We don't have a more specific message.  User should look at stderr.
+        test["failure"] = "TEST FAILURE"
+      else:
+        test["failure"] = False
+
+  for testname in os.listdir(basedir + "/logs/1"):
+    test = tests[testname]
+
+    with open(basedir + "/logs/1/" + testname + "/stdout") as f:
+      test["stdout"] = f.read()
+
+    with open(basedir + "/logs/1/" + testname + "/stderr") as f:
+      test["stderr"] = f.read()
+
+  # The cpp test is special since it doesn't run under parallel so doesn't show
+  # up in the job log.
+  tests["cpp"]["name"] = "cpp"
+
+  with open(basedir + '/logs/1/cpp/build_time', 'r') as f:
+    tests["cpp"]["time"] = f.read().strip()
+  tests["cpp"]["failure"] = False
+
+  ret = tests.values()
+  ret.sort(key=lambda x: x["name"])
+
+  return ret
+
+def genxml(tests):
+  doc, tag, text = Doc().tagtext()
+
+  with tag("testsuites"):
+    with tag("testsuite", name="Protobuf Tests"):
+      for test in tests:
+        with tag("testcase", name=test["name"], classname=test["name"],
+                             time=test["time"]):
+          with tag("system-out"):
+            text(test["stdout"])
+          with tag("system-err"):
+            text(test["stderr"])
+          if test["failure"]:
+            with tag("failure"):
+              text(test["failure"])
+
+  return doc.getvalue()
+
+sys.stderr.write("make_test_output.py: writing XML from directory: " +
+                 sys.argv[1] + "\n");
+print genxml(readtests(sys.argv[1]))
diff --git a/src/third_party/protobuf-3/jenkins/pull_request_in_docker.sh b/src/third_party/protobuf-3/jenkins/pull_request_in_docker.sh
new file mode 100755
index 0000000..887f97c
--- /dev/null
+++ b/src/third_party/protobuf-3/jenkins/pull_request_in_docker.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# This is the script that runs inside Docker, once the image has been built,
+# to execute all tests for the "pull request" project.
+
+WORKSPACE_BASE=`pwd`
+MY_DIR="$(dirname "$0")"
+TEST_SCRIPT=$MY_DIR/../tests.sh
+BUILD_DIR=/tmp/protobuf
+
+set -e  # exit immediately on error
+set -x  # display all commands
+
+# The protobuf repository is mounted into our Docker image, but read-only.
+# We clone into a directory inside Docker (this is faster than cp).
+rm -rf $BUILD_DIR
+mkdir -p $BUILD_DIR
+cd $BUILD_DIR
+git clone /var/local/jenkins/protobuf
+cd protobuf
+
+# Set up the directory where our test output is going to go.
+OUTPUT_DIR=`mktemp -d`
+LOG_OUTPUT_DIR=$OUTPUT_DIR/logs
+mkdir -p $LOG_OUTPUT_DIR/1/cpp
+
+################################################################################
+# cpp build needs to run first, non-parallelized, so that protoc is available
+# for other builds.
+
+# Output filenames to follow the overall scheme used by parallel, ie:
+#  $DIR/logs/1/cpp/stdout
+#  $DIR/logs/1/cpp/stderr
+#  $DIR/logs/1/csharp/stdout
+#  $DIR/logs/1/csharp/stderr
+#  $DIR/logs/1/java_jdk7/stdout
+#  $DIR/logs/1/java_jdk7/stderr
+CPP_STDOUT=$LOG_OUTPUT_DIR/1/cpp/stdout
+CPP_STDERR=$LOG_OUTPUT_DIR/1/cpp/stderr
+
+# Time the C++ build, so we can put this info in the test output.
+# It's important that we get /usr/bin/time (which supports -f and -o) and not
+# the bash builtin "time" which doesn't.
+TIME_CMD="/usr/bin/time -f %e -o $LOG_OUTPUT_DIR/1/cpp/build_time"
+
+$TIME_CMD $TEST_SCRIPT cpp > >(tee $CPP_STDOUT) 2> >(tee $CPP_STDERR >&2)
+
+# Other tests are run in parallel.
+
+parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \
+  csharp \
+  java_jdk7 \
+  javanano_jdk7 \
+  java_oracle7 \
+  javanano_oracle7 \
+  python \
+  python_cpp \
+  ruby21 \
+  || true  # Process test results even if tests fail.
+
+cat $OUTPUT_DIR/joblog
+
+# The directory that is copied from Docker back into the Jenkins workspace.
+COPY_FROM_DOCKER=/var/local/git/protobuf/testoutput
+mkdir -p $COPY_FROM_DOCKER
+TESTOUTPUT_XML_FILE=$COPY_FROM_DOCKER/testresults.xml
+
+# Process all the output files from "parallel" and package them into a single
+# .xml file with detailed, broken-down test output.
+python $MY_DIR/make_test_output.py $OUTPUT_DIR > $TESTOUTPUT_XML_FILE
+
+ls -l $TESTOUTPUT_XML_FILE
diff --git a/src/third_party/protobuf-3/js/README.md b/src/third_party/protobuf-3/js/README.md
new file mode 100644
index 0000000..15d48c8
--- /dev/null
+++ b/src/third_party/protobuf-3/js/README.md
@@ -0,0 +1,159 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the JavaScript Protocol Buffers runtime library.
+
+The library is currently compatible with:
+
+1. CommonJS-style imports (eg. `var protos = require('my-protos');`)
+2. Closure-style imports (eg. `goog.require('my.package.MyProto');`)
+
+Support for ES6-style imports is not implemented yet.  Browsers can
+be supported by using Browserify, webpack, Closure Compiler, etc. to
+resolve imports at compile time.
+
+To use Protocol Buffers with JavaScript, you need two main components:
+
+1. The protobuf runtime library.  You can install this with
+   `npm install google-protobuf`, or use the files in this directory.
+2. The Protocol Compiler `protoc`.  This translates `.proto` files
+   into `.js` files.  The compiler is not currently available via
+   npm, but you can download a pre-built binary
+   [on GitHub](https://github.com/google/protobuf/releases)
+   (look for the `protoc-*.zip` files under **Downloads**).
+
+
+Setup
+=====
+
+First, obtain the Protocol Compiler.  The easiest way is to download
+a pre-built binary from [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases).
+
+If you want, you can compile `protoc` from source instead.  To do this
+follow the instructions in [the top-level
+README](https://github.com/google/protobuf/blob/master/src/README.md).
+
+Once you have `protoc` compiled, you can run the tests by typing:
+
+    $ cd js
+    $ npm install
+    $ npm test
+
+    # If your protoc is somewhere else than ../src/protoc, instead do this.
+    # But make sure your protoc is the same version as this (or compatible)!
+    $ PROTOC=/usr/local/bin/protoc npm test
+
+This will run two separate copies of the tests: one that uses
+Closure Compiler style imports and one that uses CommonJS imports.
+You can see all the CommonJS files in `commonjs_out/`.
+If all of these tests pass, you know you have a working setup.
+
+
+Using Protocol Buffers in your own project
+==========================================
+
+To use Protocol Buffers in your own project, you need to integrate
+the Protocol Compiler into your build system.  The details are a
+little different depending on whether you are using Closure imports
+or CommonJS imports:
+
+Closure Imports
+---------------
+
+If you want to use Closure imports, your build should run a command
+like this:
+
+    $ protoc --js_out=library=myproto_libs,binary:. messages.proto base.proto
+
+For Closure imports, `protoc` will generate a single output file
+(`myproto_libs.js` in this example).  The generated file will `goog.provide()`
+all of the types defined in your .proto files.  For example, for the unit
+tests the generated files contain many `goog.provide` statements like:
+
+    goog.provide('proto.google.protobuf.DescriptorProto');
+    goog.provide('proto.google.protobuf.DescriptorProto.ExtensionRange');
+    goog.provide('proto.google.protobuf.DescriptorProto.ReservedRange');
+    goog.provide('proto.google.protobuf.EnumDescriptorProto');
+    goog.provide('proto.google.protobuf.EnumOptions');
+
+The generated code will also `goog.require()` many types in the core library,
+and they will require many types in the Google Closure library.  So make sure
+that your `goog.provide()` / `goog.require()` setup can find all of your
+generated code, the core library `.js` files in this directory, and the
+Google Closure library itself.
+
+Once you've done this, you should be able to import your types with
+statements like:
+
+    goog.require('proto.my.package.MyMessage');
+
+    var message = proto.my.package.MyMessage();
+
+CommonJS imports
+----------------
+
+If you want to use CommonJS imports, your build should run a command
+like this:
+
+    $ protoc --js_out=import_style=commonjs,binary:. messages.proto base.proto
+
+For CommonJS imports, `protoc` will spit out one file per input file
+(so `messages_pb.js` and `base_pb.js` in this example).  The generated
+code will depend on the core runtime, which should be in a file called
+`google-protobuf.js`.  If you are installing from `npm`, this file should
+already be built and available.  If you are running from GitHub, you need
+to build it first by running:
+
+    $ gulp dist
+
+Once you've done this, you should be able to import your types with
+statements like:
+
+    var messages = require('./messages_pb');
+
+    var message = new messages.MyMessage();
+
+The `--js_out` flag
+-------------------
+
+The syntax of the `--js_out` flag is:
+
+    --js_out=[OPTIONS:]output_dir
+
+Where `OPTIONS` are separated by commas.  Options are either `opt=val` or
+just `opt` (for options that don't take a value).  The available options
+are specified and documented in the `GeneratorOptions` struct in
+[src/google/protobuf/compiler/js/js_generator.h](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/js/js_generator.h#L53).
+
+Some examples:
+
+- `--js_out=library=myprotos_lib.js,binary:.`: this contains the options
+  `library=myprotos.lib.js` and `binary` and outputs to the current directory.
+  The `import_style` option is left to the default, which is `closure`.
+- `--js_out=import_style=commonjs,binary:protos`: this contains the options
+  `import_style=commonjs` and `binary` and outputs to the directory `protos`.
+
+API
+===
+
+The API is not well-documented yet.  Here is a quick example to give you an
+idea of how the library generally works:
+
+    var message = new MyMessage();
+
+    message.setName("John Doe");
+    message.setAge(25);
+    message.setPhoneNumbers(["800-555-1212", "800-555-0000"]);
+
+    // Serializes to a UInt8Array.
+    bytes = message.serializeBinary();
+
+    var message2 = new MyMessage();
+    message2.deserializeBinary(bytes);
+
+For more examples, see the tests.  You can also look at the generated code
+to see what methods are defined for your generated messages.
diff --git a/src/third_party/protobuf-3/js/binary/arith.js b/src/third_party/protobuf-3/js/binary/arith.js
new file mode 100644
index 0000000..70257de
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/arith.js
@@ -0,0 +1,413 @@
+// 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.
+
+/**
+ * @fileoverview This file contains helper code used by jspb.utils to
+ * handle 64-bit integer conversion to/from strings.
+ *
+ * @author cfallin@google.com (Chris Fallin)
+ *
+ * TODO(haberman): move this to javascript/closure/math?
+ */
+
+goog.provide('jspb.arith.Int64');
+goog.provide('jspb.arith.UInt64');
+
+/**
+ * UInt64 implements some 64-bit arithmetic routines necessary for properly
+ * handling 64-bit integer fields. It implements lossless integer arithmetic on
+ * top of JavaScript's number type, which has only 53 bits of precision, by
+ * representing 64-bit integers as two 32-bit halves.
+ *
+ * @param {number} lo The low 32 bits.
+ * @param {number} hi The high 32 bits.
+ * @constructor
+ */
+jspb.arith.UInt64 = function(lo, hi) {
+  /**
+   * The low 32 bits.
+   * @public {number}
+   */
+  this.lo = lo;
+  /**
+   * The high 32 bits.
+   * @public {number}
+   */
+  this.hi = hi;
+};
+
+
+/**
+ * Compare two 64-bit numbers. Returns -1 if the first is
+ * less, +1 if the first is greater, or 0 if both are equal.
+ * @param {!jspb.arith.UInt64} other
+ * @return {number}
+ */
+jspb.arith.UInt64.prototype.cmp = function(other) {
+  if (this.hi < other.hi || (this.hi == other.hi && this.lo < other.lo)) {
+    return -1;
+  } else if (this.hi == other.hi && this.lo == other.lo) {
+    return 0;
+  } else {
+    return 1;
+  }
+};
+
+
+/**
+ * Right-shift this number by one bit.
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.rightShift = function() {
+  var hi = this.hi >>> 1;
+  var lo = (this.lo >>> 1) | ((this.hi & 1) << 31);
+  return new jspb.arith.UInt64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Left-shift this number by one bit.
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.leftShift = function() {
+  var lo = this.lo << 1;
+  var hi = (this.hi << 1) | (this.lo >>> 31);
+  return new jspb.arith.UInt64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Test the MSB.
+ * @return {boolean}
+ */
+jspb.arith.UInt64.prototype.msb = function() {
+  return !!(this.hi & 0x80000000);
+};
+
+
+/**
+ * Test the LSB.
+ * @return {boolean}
+ */
+jspb.arith.UInt64.prototype.lsb = function() {
+  return !!(this.lo & 1);
+};
+
+
+/**
+ * Test whether this number is zero.
+ * @return {boolean}
+ */
+jspb.arith.UInt64.prototype.zero = function() {
+  return this.lo == 0 && this.hi == 0;
+};
+
+
+/**
+ * Add two 64-bit numbers to produce a 64-bit number.
+ * @param {!jspb.arith.UInt64} other
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.add = function(other) {
+  var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0;
+  var hi =
+      (((this.hi + other.hi) & 0xffffffff) >>> 0) +
+      (((this.lo + other.lo) >= 0x100000000) ? 1 : 0);
+  return new jspb.arith.UInt64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Subtract two 64-bit numbers to produce a 64-bit number.
+ * @param {!jspb.arith.UInt64} other
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.sub = function(other) {
+  var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0;
+  var hi =
+      (((this.hi - other.hi) & 0xffffffff) >>> 0) -
+      (((this.lo - other.lo) < 0) ? 1 : 0);
+  return new jspb.arith.UInt64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Multiply two 32-bit numbers to produce a 64-bit number.
+ * @param {number} a The first integer:  must be in [0, 2^32-1).
+ * @param {number} b The second integer: must be in [0, 2^32-1).
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.mul32x32 = function(a, b) {
+  // Directly multiplying two 32-bit numbers may produce up to 64 bits of
+  // precision, thus losing precision because of the 53-bit mantissa of
+  // JavaScript numbers. So we multiply with 16-bit digits (radix 65536)
+  // instead.
+  var aLow = (a & 0xffff);
+  var aHigh = (a >>> 16);
+  var bLow = (b & 0xffff);
+  var bHigh = (b >>> 16);
+  var productLow =
+      // 32-bit result, result bits 0-31, take all 32 bits
+      (aLow * bLow) +
+      // 32-bit result, result bits 16-47, take bottom 16 as our top 16
+      ((aLow * bHigh) & 0xffff) * 0x10000 +
+      // 32-bit result, result bits 16-47, take bottom 16 as our top 16
+      ((aHigh * bLow) & 0xffff) * 0x10000;
+  var productHigh =
+      // 32-bit result, result bits 32-63, take all 32 bits
+      (aHigh * bHigh) +
+      // 32-bit result, result bits 16-47, take top 16 as our bottom 16
+      ((aLow * bHigh) >>> 16) +
+      // 32-bit result, result bits 16-47, take top 16 as our bottom 16
+      ((aHigh * bLow) >>> 16);
+
+  // Carry. Note that we actually have up to *two* carries due to addition of
+  // three terms.
+  while (productLow >= 0x100000000) {
+    productLow -= 0x100000000;
+    productHigh += 1;
+  }
+
+  return new jspb.arith.UInt64(productLow >>> 0, productHigh >>> 0);
+};
+
+
+/**
+ * Multiply this number by a 32-bit number, producing a 96-bit number, then
+ * truncate the top 32 bits.
+ * @param {number} a The multiplier.
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.mul = function(a) {
+  // Produce two parts: at bits 0-63, and 32-95.
+  var lo = jspb.arith.UInt64.mul32x32(this.lo, a);
+  var hi = jspb.arith.UInt64.mul32x32(this.hi, a);
+  // Left-shift hi by 32 bits, truncating its top bits. The parts will then be
+  // aligned for addition.
+  hi.hi = hi.lo;
+  hi.lo = 0;
+  return lo.add(hi);
+};
+
+
+/**
+ * Divide a 64-bit number by a 32-bit number to produce a
+ * 64-bit quotient and a 32-bit remainder.
+ * @param {number} _divisor
+ * @return {Array.<jspb.arith.UInt64>} array of [quotient, remainder],
+ * unless divisor is 0, in which case an empty array is returned.
+ */
+jspb.arith.UInt64.prototype.div = function(_divisor) {
+  if (_divisor == 0) {
+    return [];
+  }
+
+  // We perform long division using a radix-2 algorithm, for simplicity (i.e.,
+  // one bit at a time). TODO: optimize to a radix-2^32 algorithm, taking care
+  // to get the variable shifts right.
+  var quotient = new jspb.arith.UInt64(0, 0);
+  var remainder = new jspb.arith.UInt64(this.lo, this.hi);
+  var divisor = new jspb.arith.UInt64(_divisor, 0);
+  var unit = new jspb.arith.UInt64(1, 0);
+
+  // Left-shift the divisor and unit until the high bit of divisor is set.
+  while (!divisor.msb()) {
+    divisor = divisor.leftShift();
+    unit = unit.leftShift();
+  }
+
+  // Perform long division one bit at a time.
+  while (!unit.zero()) {
+    // If divisor < remainder, add unit to quotient and subtract divisor from
+    // remainder.
+    if (divisor.cmp(remainder) <= 0) {
+      quotient = quotient.add(unit);
+      remainder = remainder.sub(divisor);
+    }
+    // Right-shift the divisor and unit.
+    divisor = divisor.rightShift();
+    unit = unit.rightShift();
+  }
+
+  return [quotient, remainder];
+};
+
+
+/**
+ * Convert a 64-bit number to a string.
+ * @return {string}
+ * @override
+ */
+jspb.arith.UInt64.prototype.toString = function() {
+  var result = '';
+  var num = this;
+  while (!num.zero()) {
+    var divResult = num.div(10);
+    var quotient = divResult[0], remainder = divResult[1];
+    result = remainder.lo + result;
+    num = quotient;
+  }
+  if (result == '') {
+    result = '0';
+  }
+  return result;
+};
+
+
+/**
+ * Parse a string into a 64-bit number. Returns `null` on a parse error.
+ * @param {string} s
+ * @return {?jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.fromString = function(s) {
+  var result = new jspb.arith.UInt64(0, 0);
+  // optimization: reuse this instance for each digit.
+  var digit64 = new jspb.arith.UInt64(0, 0);
+  for (var i = 0; i < s.length; i++) {
+    if (s[i] < '0' || s[i] > '9') {
+      return null;
+    }
+    var digit = parseInt(s[i], 10);
+    digit64.lo = digit;
+    result = result.mul(10).add(digit64);
+  }
+  return result;
+};
+
+
+/**
+ * Make a copy of the uint64.
+ * @return {!jspb.arith.UInt64}
+ */
+jspb.arith.UInt64.prototype.clone = function() {
+  return new jspb.arith.UInt64(this.lo, this.hi);
+};
+
+
+/**
+ * Int64 is like UInt64, but modifies string conversions to interpret the stored
+ * 64-bit value as a twos-complement-signed integer. It does *not* support the
+ * full range of operations that UInt64 does: only add, subtract, and string
+ * conversions.
+ *
+ * N.B. that multiply and divide routines are *NOT* supported. They will throw
+ * exceptions. (They are not necessary to implement string conversions, which
+ * are the only operations we really need in jspb.)
+ *
+ * @param {number} lo The low 32 bits.
+ * @param {number} hi The high 32 bits.
+ * @constructor
+ */
+jspb.arith.Int64 = function(lo, hi) {
+  /**
+   * The low 32 bits.
+   * @public {number}
+   */
+  this.lo = lo;
+  /**
+   * The high 32 bits.
+   * @public {number}
+   */
+  this.hi = hi;
+};
+
+
+/**
+ * Add two 64-bit numbers to produce a 64-bit number.
+ * @param {!jspb.arith.Int64} other
+ * @return {!jspb.arith.Int64}
+ */
+jspb.arith.Int64.prototype.add = function(other) {
+  var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0;
+  var hi =
+      (((this.hi + other.hi) & 0xffffffff) >>> 0) +
+      (((this.lo + other.lo) >= 0x100000000) ? 1 : 0);
+  return new jspb.arith.Int64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Subtract two 64-bit numbers to produce a 64-bit number.
+ * @param {!jspb.arith.Int64} other
+ * @return {!jspb.arith.Int64}
+ */
+jspb.arith.Int64.prototype.sub = function(other) {
+  var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0;
+  var hi =
+      (((this.hi - other.hi) & 0xffffffff) >>> 0) -
+      (((this.lo - other.lo) < 0) ? 1 : 0);
+  return new jspb.arith.Int64(lo >>> 0, hi >>> 0);
+};
+
+
+/**
+ * Make a copy of the int64.
+ * @return {!jspb.arith.Int64}
+ */
+jspb.arith.Int64.prototype.clone = function() {
+  return new jspb.arith.Int64(this.lo, this.hi);
+};
+
+
+/**
+ * Convert a 64-bit number to a string.
+ * @return {string}
+ * @override
+ */
+jspb.arith.Int64.prototype.toString = function() {
+  // If the number is negative, find its twos-complement inverse.
+  var sign = (this.hi & 0x80000000) != 0;
+  var num = new jspb.arith.UInt64(this.lo, this.hi);
+  if (sign) {
+    num = new jspb.arith.UInt64(0, 0).sub(num);
+  }
+  return (sign ? '-' : '') + num.toString();
+};
+
+
+/**
+ * Parse a string into a 64-bit number. Returns `null` on a parse error.
+ * @param {string} s
+ * @return {?jspb.arith.Int64}
+ */
+jspb.arith.Int64.fromString = function(s) {
+  var hasNegative = (s.length > 0 && s[0] == '-');
+  if (hasNegative) {
+    s = s.substring(1);
+  }
+  var num = jspb.arith.UInt64.fromString(s);
+  if (num === null) {
+    return null;
+  }
+  if (hasNegative) {
+    num = new jspb.arith.UInt64(0, 0).sub(num);
+  }
+  return new jspb.arith.Int64(num.lo, num.hi);
+};
diff --git a/src/third_party/protobuf-3/js/binary/arith_test.js b/src/third_party/protobuf-3/js/binary/arith_test.js
new file mode 100644
index 0000000..89796bf
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/arith_test.js
@@ -0,0 +1,355 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for Int64-manipulation functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author cfallin@google.com (Chris Fallin)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.arith.Int64');
+goog.require('jspb.arith.UInt64');
+
+
+describe('binaryArithTest', function() {
+  /**
+   * Tests comparison operations.
+   */
+  it('testCompare', function() {
+    var a = new jspb.arith.UInt64(1234, 5678);
+    var b = new jspb.arith.UInt64(1234, 5678);
+    assertEquals(a.cmp(b), 0);
+    assertEquals(b.cmp(a), 0);
+    b.lo -= 1;
+    assertEquals(a.cmp(b), 1);
+    assertEquals(b.cmp(a), -1);
+    b.lo += 2;
+    assertEquals(a.cmp(b), -1);
+    assertEquals(b.cmp(a), 1);
+    b.lo = a.lo;
+    b.hi = a.hi - 1;
+    assertEquals(a.cmp(b), 1);
+    assertEquals(b.cmp(a), -1);
+
+    assertEquals(a.zero(), false);
+    assertEquals(a.msb(), false);
+    assertEquals(a.lsb(), false);
+    a.hi = 0;
+    a.lo = 0;
+    assertEquals(a.zero(), true);
+    a.hi = 0x80000000;
+    assertEquals(a.zero(), false);
+    assertEquals(a.msb(), true);
+    a.lo = 0x00000001;
+    assertEquals(a.lsb(), true);
+  });
+
+
+  /**
+   * Tests shifts.
+   */
+  it('testShifts', function() {
+    var a = new jspb.arith.UInt64(1, 0);
+    assertEquals(a.lo, 1);
+    assertEquals(a.hi, 0);
+    var orig = a;
+    a = a.leftShift();
+    assertEquals(orig.lo, 1);  // original unmodified.
+    assertEquals(orig.hi, 0);
+    assertEquals(a.lo, 2);
+    assertEquals(a.hi, 0);
+    a = a.leftShift();
+    assertEquals(a.lo, 4);
+    assertEquals(a.hi, 0);
+    for (var i = 0; i < 29; i++) {
+      a = a.leftShift();
+    }
+    assertEquals(a.lo, 0x80000000);
+    assertEquals(a.hi, 0);
+    a = a.leftShift();
+    assertEquals(a.lo, 0);
+    assertEquals(a.hi, 1);
+    a = a.leftShift();
+    assertEquals(a.lo, 0);
+    assertEquals(a.hi, 2);
+    a = a.rightShift();
+    a = a.rightShift();
+    assertEquals(a.lo, 0x80000000);
+    assertEquals(a.hi, 0);
+    a = a.rightShift();
+    assertEquals(a.lo, 0x40000000);
+    assertEquals(a.hi, 0);
+  });
+
+
+  /**
+   * Tests additions.
+   */
+  it('testAdd', function() {
+    var a = new jspb.arith.UInt64(/* lo = */ 0x89abcdef,
+                                         /* hi = */ 0x01234567);
+    var b = new jspb.arith.UInt64(/* lo = */ 0xff52ab91,
+                                         /* hi = */ 0x92fa2123);
+    // Addition with carry.
+    var c = a.add(b);
+    assertEquals(a.lo, 0x89abcdef);  // originals unmodified.
+    assertEquals(a.hi, 0x01234567);
+    assertEquals(b.lo, 0xff52ab91);
+    assertEquals(b.hi, 0x92fa2123);
+    assertEquals(c.lo, 0x88fe7980);
+    assertEquals(c.hi, 0x941d668b);
+
+    // Simple addition without carry.
+    a.lo = 2;
+    a.hi = 0;
+    b.lo = 3;
+    b.hi = 0;
+    c = a.add(b);
+    assertEquals(c.lo, 5);
+    assertEquals(c.hi, 0);
+  });
+
+
+  /**
+   * Test subtractions.
+   */
+  it('testSub', function() {
+    var kLength = 10;
+    var hiValues = [0x1682ef32,
+                    0x583902f7,
+                    0xb62f5955,
+                    0x6ea99bbf,
+                    0x25a39c20,
+                    0x0700a08b,
+                    0x00f7304d,
+                    0x91a5b5af,
+                    0x89077fd2,
+                    0xe09e347c];
+    var loValues = [0xe1538b18,
+                    0xbeacd556,
+                    0x74100758,
+                    0x96e3cb26,
+                    0x56c37c3f,
+                    0xe00b3f7d,
+                    0x859f25d7,
+                    0xc2ee614a,
+                    0xe1d21cd7,
+                    0x30aae6a4];
+    for (var i = 0; i < kLength; i++) {
+      for (var j = 0; j < kLength; j++) {
+        var a = new jspb.arith.UInt64(loValues[i], hiValues[j]);
+        var b = new jspb.arith.UInt64(loValues[j], hiValues[i]);
+        var c = a.add(b).sub(b);
+        assertEquals(c.hi, a.hi);
+        assertEquals(c.lo, a.lo);
+      }
+    }
+  });
+
+
+  /**
+   * Tests 32-by-32 multiplication.
+   */
+  it('testMul32x32', function() {
+    var testData = [
+      // a        b          low(a*b)   high(a*b)
+      [0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8],
+      [0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc],
+      [0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c],
+      [0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c],
+      [0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa],
+      [0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad],
+      [0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8],
+      [0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7],
+      [0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412],
+      [0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = testData[i][0] >>> 0;
+      var b = testData[i][1] >>> 0;
+      var cLow = testData[i][2] >>> 0;
+      var cHigh = testData[i][3] >>> 0;
+      var c = jspb.arith.UInt64.mul32x32(a, b);
+      assertEquals(c.lo, cLow);
+      assertEquals(c.hi, cHigh);
+    }
+  });
+
+
+  /**
+   * Tests 64-by-32 multiplication.
+   */
+  it('testMul', function() {
+    // 64x32 bits produces 96 bits of product. The multiplication function under
+    // test truncates the top 32 bits, so we compare against a 64-bit expected
+    // product.
+    var testData = [
+      // low(a)   high(a)               low(a*b)   high(a*b)
+      [0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f],
+      [0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b],
+      [0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df],
+      [0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a],
+      [0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe],
+      [0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1],
+      [0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d],
+      [0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d],
+      [0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8],
+      [0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var prod = a.mul(testData[i][2]);
+      assertEquals(prod.lo, testData[i][3]);
+      assertEquals(prod.hi, testData[i][4]);
+    }
+  });
+
+
+  /**
+   * Tests 64-div-by-32 division.
+   */
+  it('testDiv', function() {
+    // Compute a/b, yielding quot = a/b and rem = a%b.
+    var testData = [
+      // --- divisors in (0, 2^32-1) to test full divisor range
+      // low(a)   high(a)    b          low(quot)  high(quot) rem
+      [0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882],
+      [0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd],
+      [0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6],
+      [0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2],
+      [0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751],
+      [0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce],
+      [0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4],
+      [0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7],
+      [0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095],
+      [0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6],
+      // --- divisors in (0, 2^16-1) to test larger quotient high-words
+      // low(a)   high(a)    b          low(quot)  high(quot) rem
+      [0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99],
+      [0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6],
+      [0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af],
+      [0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981],
+      [0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9],
+      [0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2],
+      [0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a],
+      [0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69],
+      [0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d],
+      [0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var result = a.div(testData[i][2]);
+      var quotient = result[0];
+      var remainder = result[1];
+      assertEquals(quotient.lo, testData[i][3]);
+      assertEquals(quotient.hi, testData[i][4]);
+      assertEquals(remainder.lo, testData[i][5]);
+    }
+  });
+
+
+  /**
+   * Tests .toString() and .fromString().
+   */
+  it('testStrings', function() {
+    var testData = [
+        [0x5e84c935, 0xcae33d0e, '14619595947299359029'],
+        [0x62b3b8b8, 0x93480544, '10612738313170434232'],
+        [0x319bfb13, 0xc01c4172, '13843011313344445203'],
+        [0x5b8a65fb, 0xa5885b31, '11927883880638080507'],
+        [0x6bdb80f1, 0xb0d1b16b, '12741159895737008369'],
+        [0x4b82b442, 0x2e0d8c97, '3318463081876730946'],
+        [0x780d5208, 0x7d76752c, '9040542135845999112'],
+        [0x2e46800f, 0x0993778d, '690026616168284175'],
+        [0xf00a7e32, 0xcd8e3931, '14811839111111540274'],
+        [0x1baeccd6, 0x923048c4, '10533999535534820566'],
+        [0x03669d29, 0xbff3ab72, '13831587386756603177'],
+        [0x2526073e, 0x01affc81, '121593346566522686'],
+        [0xc24244e0, 0xd7f40d0e, '15561076969511732448'],
+        [0xc56a341e, 0xa68b66a7, '12000798502816461854'],
+        [0x8738d64d, 0xbfe78604, '13828168534871037517'],
+        [0x5baff03b, 0xd7572aea, '15516918227177304123'],
+        [0x4a843d8a, 0x864e132b, '9677693725920476554'],
+        [0x25b4e94d, 0x22b54dc6, '2500990681505655117'],
+        [0x6bbe664b, 0x55a5cc0e, '6171563226690381387'],
+        [0xee916c81, 0xb00aabb3, '12685140089732426881']
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var roundtrip = jspb.arith.UInt64.fromString(a.toString());
+      assertEquals(roundtrip.lo, a.lo);
+      assertEquals(roundtrip.hi, a.hi);
+      assertEquals(a.toString(), testData[i][2]);
+    }
+  });
+
+
+  /**
+   * Tests signed Int64s. These are built on UInt64s, so we only need to test
+   * the explicit overrides: .toString() and .fromString().
+   */
+  it('testSignedInt64', function() {
+    var testStrings = [
+        '-7847499644178593666',
+        '3771946501229139523',
+        '2872856549054995060',
+        '-5780049594274350904',
+        '3383785956695105201',
+        '2973055184857072610',
+        '-3879428459215627206',
+        '4589812431064156631',
+        '8484075557333689940',
+        '1075325817098092407',
+        '-4346697501012292314',
+        '2488620459718316637',
+        '6112655187423520672',
+        '-3655278273928612104',
+        '3439154019435803196',
+        '1004112478843763757',
+        '-6587790776614368413',
+        '664320065099714586',
+        '4760412909973292912',
+        '-7911903989602274672'
+    ];
+
+    for (var i = 0; i < testStrings.length; i++) {
+      var roundtrip =
+          jspb.arith.Int64.fromString(testStrings[i]).toString();
+      assertEquals(roundtrip, testStrings[i]);
+    }
+  });
+});
diff --git a/src/third_party/protobuf-3/js/binary/constants.js b/src/third_party/protobuf-3/js/binary/constants.js
new file mode 100644
index 0000000..836216b
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/constants.js
@@ -0,0 +1,360 @@
+// 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.
+
+/**
+ * @fileoverview This file contains constants and typedefs used by
+ * jspb.BinaryReader and BinaryWriter.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.AnyFieldType');
+goog.provide('jspb.BinaryConstants');
+goog.provide('jspb.BinaryMessage');
+goog.provide('jspb.BuilderFunction');
+goog.provide('jspb.ByteSource');
+goog.provide('jspb.ClonerFunction');
+goog.provide('jspb.ComparerFunction');
+goog.provide('jspb.ConstBinaryMessage');
+goog.provide('jspb.PrunerFunction');
+goog.provide('jspb.ReaderFunction');
+goog.provide('jspb.RecyclerFunction');
+goog.provide('jspb.RepeatedFieldType');
+goog.provide('jspb.ScalarFieldType');
+goog.provide('jspb.WriterFunction');
+
+
+goog.forwardDeclare('jspb.Message');
+goog.forwardDeclare('jsproto.BinaryExtension');
+
+
+
+/**
+ * Base interface class for all const messages. Does __not__ define any
+ * methods, as doing so on a widely-used interface defeats dead-code
+ * elimination.
+ * @interface
+ */
+jspb.ConstBinaryMessage = function() {};
+
+
+
+/**
+ * Base interface class for all messages. Does __not__ define any methods, as
+ * doing so on a widely-used interface defeats dead-code elimination.
+ * @interface
+ * @extends {jspb.ConstBinaryMessage}
+ */
+jspb.BinaryMessage = function() {};
+
+
+/**
+ * The types convertible to Uint8Arrays. Strings are assumed to be
+ * base64-encoded.
+ * @typedef {ArrayBuffer|Uint8Array|Array<number>|string}
+ */
+jspb.ByteSource;
+
+
+/**
+ * A scalar field in jspb can be a boolean, number, or string.
+ * @typedef {boolean|number|string}
+ */
+jspb.ScalarFieldType;
+
+
+/**
+ * A repeated field in jspb is an array of scalars, blobs, or messages.
+ * @typedef {!Array<jspb.ScalarFieldType>|
+             !Array<!Uint8Array>|
+             !Array<!jspb.BinaryMessage>}
+ */
+jspb.RepeatedFieldType;
+
+
+/**
+ * A field in jspb can be a scalar, a block of bytes, another proto, or an
+ * array of any of the above.
+ * @typedef {jspb.ScalarFieldType|
+             jspb.RepeatedFieldType|
+             !Uint8Array|
+             !jspb.BinaryMessage|
+             !jsproto.BinaryExtension}
+ */
+jspb.AnyFieldType;
+
+
+/**
+ * A builder function creates an instance of a message object.
+ * @typedef {function():!jspb.BinaryMessage}
+ */
+jspb.BuilderFunction;
+
+
+/**
+ * A cloner function creates a deep copy of a message object.
+ * @typedef {function(jspb.ConstBinaryMessage):jspb.BinaryMessage}
+ */
+jspb.ClonerFunction;
+
+
+/**
+ * A recycler function destroys an instance of a message object.
+ * @typedef {function(!jspb.BinaryMessage):void}
+ */
+jspb.RecyclerFunction;
+
+
+/**
+ * A reader function initializes a message using data from a BinaryReader.
+ * @typedef {function(!jspb.BinaryMessage, !jspb.BinaryReader):void}
+ */
+jspb.ReaderFunction;
+
+
+/**
+ * A writer function serializes a message to a BinaryWriter.
+ * @typedef {!function(!jspb.Message, !jspb.BinaryWriter):void |
+ *           !function(!jspb.ConstBinaryMessage, !jspb.BinaryWriter):void}
+ */
+jspb.WriterFunction;
+
+
+/**
+ * A pruner function removes default-valued fields and empty submessages from a
+ * message and returns either the pruned message or null if the entire message
+ * was pruned away.
+ * @typedef {function(?jspb.BinaryMessage):?jspb.BinaryMessage}
+ */
+jspb.PrunerFunction;
+
+
+/**
+ * A comparer function returns true if two protos are equal.
+ * @typedef {!function(?jspb.ConstBinaryMessage,
+ *                     ?jspb.ConstBinaryMessage):boolean}
+ */
+jspb.ComparerFunction;
+
+
+/**
+ * Field type codes, taken from proto2/public/wire_format_lite.h.
+ * @enum {number}
+ */
+jspb.BinaryConstants.FieldType = {
+  INVALID: -1,
+  DOUBLE: 1,
+  FLOAT: 2,
+  INT64: 3,
+  UINT64: 4,
+  INT32: 5,
+  FIXED64: 6,
+  FIXED32: 7,
+  BOOL: 8,
+  STRING: 9,
+  GROUP: 10,
+  MESSAGE: 11,
+  BYTES: 12,
+  UINT32: 13,
+  ENUM: 14,
+  SFIXED32: 15,
+  SFIXED64: 16,
+  SINT32: 17,
+  SINT64: 18,
+
+  // Extended types for Javascript
+
+  FHASH64: 30, // 64-bit hash string, fixed-length encoding.
+  VHASH64: 31  // 64-bit hash string, varint encoding.
+};
+
+
+/**
+ * Wire-format type codes, taken from proto2/public/wire_format_lite.h.
+ * @enum {number}
+ */
+jspb.BinaryConstants.WireType = {
+  INVALID: -1,
+  VARINT: 0,
+  FIXED64: 1,
+  DELIMITED: 2,
+  START_GROUP: 3,
+  END_GROUP: 4,
+  FIXED32: 5
+};
+
+
+/**
+ * Translates field type to wire type.
+ * @param {jspb.BinaryConstants.FieldType} fieldType
+ * @return {jspb.BinaryConstants.WireType}
+ */
+jspb.BinaryConstants.FieldTypeToWireType = function(fieldType) {
+  var fieldTypes = jspb.BinaryConstants.FieldType;
+  var wireTypes = jspb.BinaryConstants.WireType;
+  switch (fieldType) {
+    case fieldTypes.INT32:
+    case fieldTypes.INT64:
+    case fieldTypes.UINT32:
+    case fieldTypes.UINT64:
+    case fieldTypes.SINT32:
+    case fieldTypes.SINT64:
+    case fieldTypes.BOOL:
+    case fieldTypes.ENUM:
+    case fieldTypes.VHASH64:
+      return wireTypes.VARINT;
+
+    case fieldTypes.DOUBLE:
+    case fieldTypes.FIXED64:
+    case fieldTypes.SFIXED64:
+    case fieldTypes.FHASH64:
+      return wireTypes.FIXED64;
+
+    case fieldTypes.STRING:
+    case fieldTypes.MESSAGE:
+    case fieldTypes.BYTES:
+      return wireTypes.DELIMITED;
+
+    case fieldTypes.FLOAT:
+    case fieldTypes.FIXED32:
+    case fieldTypes.SFIXED32:
+      return wireTypes.FIXED32;
+
+    case fieldTypes.INVALID:
+    case fieldTypes.GROUP:
+    default:
+      return wireTypes.INVALID;
+  }
+};
+
+
+/**
+ * Flag to indicate a missing field.
+ * @const {number}
+ */
+jspb.BinaryConstants.INVALID_FIELD_NUMBER = -1;
+
+
+/**
+ * The smallest denormal float32 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT32_EPS = 1.401298464324817e-45;
+
+
+/**
+ * The smallest normal float64 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT32_MIN = 1.1754943508222875e-38;
+
+
+/**
+ * The largest finite float32 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT32_MAX = 3.4028234663852886e+38;
+
+
+/**
+ * The smallest denormal float64 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT64_EPS = 5e-324;
+
+
+/**
+ * The smallest normal float64 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT64_MIN = 2.2250738585072014e-308;
+
+
+/**
+ * The largest finite float64 value.
+ * @const {number}
+ */
+jspb.BinaryConstants.FLOAT64_MAX = 1.7976931348623157e+308;
+
+
+/**
+ * Convenience constant equal to 2^20.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_20 = 1048576;
+
+
+/**
+ * Convenience constant equal to 2^23.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_23 = 8388608;
+
+
+/**
+ * Convenience constant equal to 2^31.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_31 = 2147483648;
+
+
+/**
+ * Convenience constant equal to 2^32.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_32 = 4294967296;
+
+
+/**
+ * Convenience constant equal to 2^52.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_52 = 4503599627370496;
+
+
+/**
+ * Convenience constant equal to 2^63.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_63 = 9223372036854775808;
+
+
+/**
+ * Convenience constant equal to 2^64.
+ * @const {number}
+ */
+jspb.BinaryConstants.TWO_TO_64 = 18446744073709551616;
+
+
+/**
+ * Eight-character string of zeros, used as the default 64-bit hash value.
+ * @const {string}
+ */
+jspb.BinaryConstants.ZERO_HASH = '\0\0\0\0\0\0\0\0';
diff --git a/src/third_party/protobuf-3/js/binary/decoder.js b/src/third_party/protobuf-3/js/binary/decoder.js
new file mode 100644
index 0000000..41094a3
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/decoder.js
@@ -0,0 +1,1007 @@
+// 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.
+
+/**
+ * @fileoverview This file contains utilities for decoding primitive values
+ * (signed and unsigned integers, varints, booleans, enums, hashes, strings,
+ * and raw bytes) embedded in Uint8Arrays into their corresponding Javascript
+ * types.
+ *
+ * Major caveat - Javascript is unable to accurately represent integers larger
+ * than 2^53 due to its use of a double-precision floating point format or all
+ * numbers. If you need to guarantee that 64-bit values survive with all bits
+ * intact, you _must_ read them using one of the Hash64 methods, which return
+ * an 8-character string.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.BinaryDecoder');
+goog.provide('jspb.BinaryIterator');
+
+goog.require('goog.asserts');
+goog.require('jspb.utils');
+
+
+
+/**
+ * Simple helper class for traversing the contents of repeated scalar fields.
+ * that may or may not have been packed into a wire-format blob.
+ * @param {?jspb.BinaryDecoder=} opt_decoder
+ * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
+ *     opt_next The decoder method to use for next().
+ * @param {?Array.<number|boolean|string>=} opt_elements
+ * @constructor
+ * @struct
+ */
+jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
+  /** @private {jspb.BinaryDecoder} */
+  this.decoder_ = null;
+
+  /**
+   * The BinaryDecoder member function used when iterating over packed data.
+   * @private {?function(this:jspb.BinaryDecoder):(number|boolean|string)}
+   */
+  this.nextMethod_ = null;
+
+  /** @private {Array.<number>} */
+  this.elements_ = null;
+
+  /** @private {number} */
+  this.cursor_ = 0;
+
+  /** @private {number|boolean|string|null} */
+  this.nextValue_ = null;
+
+  /** @private {boolean} */
+  this.atEnd_ = true;
+
+  this.init_(opt_decoder, opt_next, opt_elements);
+};
+
+
+/**
+ * @param {?jspb.BinaryDecoder=} opt_decoder
+ * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
+ *     opt_next The decoder method to use for next().
+ * @param {?Array.<number|boolean|string>=} opt_elements
+ * @private
+ */
+jspb.BinaryIterator.prototype.init_ =
+    function(opt_decoder, opt_next, opt_elements) {
+  if (opt_decoder && opt_next) {
+    this.decoder_ = opt_decoder;
+    this.nextMethod_ = opt_next;
+  }
+  this.elements_ = opt_elements ? opt_elements : null;
+  this.cursor_ = 0;
+  this.nextValue_ = null;
+  this.atEnd_ = !this.decoder_ && !this.elements_;
+
+  this.next();
+};
+
+
+/**
+ * Global pool of BinaryIterator instances.
+ * @private {!Array.<!jspb.BinaryIterator>}
+ */
+jspb.BinaryIterator.instanceCache_ = [];
+
+
+/**
+ * Allocates a BinaryIterator from the cache, creating a new one if the cache
+ * is empty.
+ * @param {?jspb.BinaryDecoder=} opt_decoder
+ * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
+ *     opt_next The decoder method to use for next().
+ * @param {?Array.<number|boolean|string>=} opt_elements
+ * @return {!jspb.BinaryIterator}
+ */
+jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) {
+  if (jspb.BinaryIterator.instanceCache_.length) {
+    var iterator = jspb.BinaryIterator.instanceCache_.pop();
+    iterator.init_(opt_decoder, opt_next, opt_elements);
+    return iterator;
+  } else {
+    return new jspb.BinaryIterator(opt_decoder, opt_next, opt_elements);
+  }
+};
+
+
+/**
+ * Puts this instance back in the instance cache.
+ */
+jspb.BinaryIterator.prototype.free = function() {
+  this.clear();
+  if (jspb.BinaryIterator.instanceCache_.length < 100) {
+    jspb.BinaryIterator.instanceCache_.push(this);
+  }
+};
+
+
+/**
+ * Clears the iterator.
+ */
+jspb.BinaryIterator.prototype.clear = function() {
+  if (this.decoder_) {
+    this.decoder_.free();
+  }
+  this.decoder_ = null;
+  this.nextMethod_ = null;
+  this.elements_ = null;
+  this.cursor_ = 0;
+  this.nextValue_ = null;
+  this.atEnd_ = true;
+};
+
+
+/**
+ * Returns the element at the iterator, or null if the iterator is invalid or
+ * past the end of the decoder/array.
+ * @return {number|boolean|string|null}
+ */
+jspb.BinaryIterator.prototype.get = function() {
+  return this.nextValue_;
+};
+
+
+/**
+ * Returns true if the iterator is at the end of the decoder/array.
+ * @return {boolean}
+ */
+jspb.BinaryIterator.prototype.atEnd = function() {
+  return this.atEnd_;
+};
+
+
+/**
+ * Returns the element at the iterator and steps to the next element,
+ * equivalent to '*pointer++' in C.
+ * @return {number|boolean|string|null}
+ */
+jspb.BinaryIterator.prototype.next = function() {
+  var lastValue = this.nextValue_;
+  if (this.decoder_) {
+    if (this.decoder_.atEnd()) {
+      this.nextValue_ = null;
+      this.atEnd_ = true;
+    } else {
+      this.nextValue_ = this.nextMethod_.call(this.decoder_);
+    }
+  } else if (this.elements_) {
+    if (this.cursor_ == this.elements_.length) {
+      this.nextValue_ = null;
+      this.atEnd_ = true;
+    } else {
+      this.nextValue_ = this.elements_[this.cursor_++];
+    }
+  }
+  return lastValue;
+};
+
+
+
+/**
+ * BinaryDecoder implements the decoders for all the wire types specified in
+ * https://developers.google.com/protocol-buffers/docs/encoding.
+ *
+ * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ * @constructor
+ * @struct
+ */
+jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) {
+  /**
+   * Typed byte-wise view of the source buffer.
+   * @private {?Uint8Array}
+   */
+  this.bytes_ = null;
+
+  /**
+   * Start point of the block to read.
+   * @private {number}
+   */
+  this.start_ = 0;
+
+  /**
+   * End point of the block to read.
+   * @private {number}
+   */
+  this.end_ = 0;
+
+  /**
+   * Current read location in bytes_.
+   * @private {number}
+   */
+  this.cursor_ = 0;
+
+  /**
+   * Temporary storage for the low 32 bits of 64-bit data types that we're
+   * decoding.
+   * @private {number}
+   */
+  this.tempLow_ = 0;
+
+  /**
+   * Temporary storage for the high 32 bits of 64-bit data types that we're
+   * decoding.
+   * @private {number}
+   */
+  this.tempHigh_ = 0;
+
+  /**
+   * Set to true if this decoder encountered an error due to corrupt data.
+   * @private {boolean}
+   */
+  this.error_ = false;
+
+  if (opt_bytes) {
+    this.setBlock(opt_bytes, opt_start, opt_length);
+  }
+};
+
+
+/**
+ * Global pool of BinaryDecoder instances.
+ * @private {!Array.<!jspb.BinaryDecoder>}
+ */
+jspb.BinaryDecoder.instanceCache_ = [];
+
+
+/**
+ * Pops an instance off the instance cache, or creates one if the cache is
+ * empty.
+ * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ * @return {!jspb.BinaryDecoder}
+ */
+jspb.BinaryDecoder.alloc = function(opt_bytes, opt_start, opt_length) {
+  if (jspb.BinaryDecoder.instanceCache_.length) {
+    var newDecoder = jspb.BinaryDecoder.instanceCache_.pop();
+    if (opt_bytes) {
+      newDecoder.setBlock(opt_bytes, opt_start, opt_length);
+    }
+    return newDecoder;
+  } else {
+    return new jspb.BinaryDecoder(opt_bytes, opt_start, opt_length);
+  }
+};
+
+
+/**
+ * Puts this instance back in the instance cache.
+ */
+jspb.BinaryDecoder.prototype.free = function() {
+  this.clear();
+  if (jspb.BinaryDecoder.instanceCache_.length < 100) {
+    jspb.BinaryDecoder.instanceCache_.push(this);
+  }
+};
+
+
+/**
+ * Makes a copy of this decoder.
+ * @return {!jspb.BinaryDecoder}
+ */
+jspb.BinaryDecoder.prototype.clone = function() {
+  return jspb.BinaryDecoder.alloc(this.bytes_,
+      this.start_, this.end_ - this.start_);
+};
+
+
+/**
+ * Clears the decoder.
+ */
+jspb.BinaryDecoder.prototype.clear = function() {
+  this.bytes_ = null;
+  this.start_ = 0;
+  this.end_ = 0;
+  this.cursor_ = 0;
+  this.error_ = false;
+};
+
+
+/**
+ * Returns the raw buffer.
+ * @return {?Uint8Array} The raw buffer.
+ */
+jspb.BinaryDecoder.prototype.getBuffer = function() {
+  return this.bytes_;
+};
+
+
+/**
+ * Changes the block of bytes we're decoding.
+ * @param {!jspb.ByteSource} data The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ */
+jspb.BinaryDecoder.prototype.setBlock =
+    function(data, opt_start, opt_length) {
+  this.bytes_ = jspb.utils.byteSourceToUint8Array(data);
+  this.start_ = goog.isDef(opt_start) ? opt_start : 0;
+  this.end_ =
+      goog.isDef(opt_length) ? this.start_ + opt_length : this.bytes_.length;
+  this.cursor_ = this.start_;
+};
+
+
+/**
+ * @return {number}
+ */
+jspb.BinaryDecoder.prototype.getEnd = function() {
+  return this.end_;
+};
+
+
+/**
+ * @param {number} end
+ */
+jspb.BinaryDecoder.prototype.setEnd = function(end) {
+  this.end_ = end;
+};
+
+
+/**
+ * Moves the read cursor back to the start of the block.
+ */
+jspb.BinaryDecoder.prototype.reset = function() {
+  this.cursor_ = this.start_;
+};
+
+
+/**
+ * Returns the internal read cursor.
+ * @return {number} The internal read cursor.
+ */
+jspb.BinaryDecoder.prototype.getCursor = function() {
+  return this.cursor_;
+};
+
+
+/**
+ * Returns the internal read cursor.
+ * @param {number} cursor The new cursor.
+ */
+jspb.BinaryDecoder.prototype.setCursor = function(cursor) {
+  this.cursor_ = cursor;
+};
+
+
+/**
+ * Advances the stream cursor by the given number of bytes.
+ * @param {number} count The number of bytes to advance by.
+ */
+jspb.BinaryDecoder.prototype.advance = function(count) {
+  this.cursor_ += count;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+};
+
+
+/**
+ * Returns true if this decoder is at the end of the block.
+ * @return {boolean}
+ */
+jspb.BinaryDecoder.prototype.atEnd = function() {
+  return this.cursor_ == this.end_;
+};
+
+
+/**
+ * Returns true if this decoder is at the end of the block.
+ * @return {boolean}
+ */
+jspb.BinaryDecoder.prototype.pastEnd = function() {
+  return this.cursor_ > this.end_;
+};
+
+
+/**
+ * Returns true if this decoder encountered an error due to corrupt data.
+ * @return {boolean}
+ */
+jspb.BinaryDecoder.prototype.getError = function() {
+  return this.error_ ||
+         (this.cursor_ < 0) ||
+         (this.cursor_ > this.end_);
+};
+
+
+/**
+ * Reads an unsigned varint from the binary stream and stores it as a split
+ * 64-bit integer. Since this does not convert the value to a number, no
+ * precision is lost.
+ *
+ * It's possible for an unsigned varint to be incorrectly encoded - more than
+ * 64 bits' worth of data could be present. If this happens, this method will
+ * throw an error.
+ *
+ * Decoding varints requires doing some funny base-128 math - for more
+ * details on the format, see
+ * https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @private
+ */
+jspb.BinaryDecoder.prototype.readSplitVarint64_ = function() {
+  var temp;
+  var lowBits = 0;
+  var highBits = 0;
+
+  // Read the first four bytes of the varint, stopping at the terminator if we
+  // see it.
+  for (var i = 0; i < 4; i++) {
+    temp = this.bytes_[this.cursor_++];
+    lowBits |= (temp & 0x7F) << (i * 7);
+    if (temp < 128) {
+      this.tempLow_ = lowBits >>> 0;
+      this.tempHigh_ = 0;
+      return;
+    }
+  }
+
+  // Read the fifth byte, which straddles the low and high dwords.
+  temp = this.bytes_[this.cursor_++];
+  lowBits |= (temp & 0x7F) << 28;
+  highBits |= (temp & 0x7F) >> 4;
+  if (temp < 128) {
+    this.tempLow_ = lowBits >>> 0;
+    this.tempHigh_ = highBits >>> 0;
+    return;
+  }
+
+  // Read the sixth through tenth byte.
+  for (var i = 0; i < 5; i++) {
+    temp = this.bytes_[this.cursor_++];
+    highBits |= (temp & 0x7F) << (i * 7 + 3);
+    if (temp < 128) {
+      this.tempLow_ = lowBits >>> 0;
+      this.tempHigh_ = highBits >>> 0;
+      return;
+    }
+  }
+
+  // If we did not see the terminator, the encoding was invalid.
+  goog.asserts.fail('Failed to read varint, encoding is invalid.');
+  this.error_ = true;
+};
+
+
+/**
+ * Skips over a varint in the block without decoding it.
+ */
+jspb.BinaryDecoder.prototype.skipVarint = function() {
+  while (this.bytes_[this.cursor_] & 0x80) {
+    this.cursor_++;
+  }
+  this.cursor_++;
+};
+
+
+/**
+ * Skips backwards over a varint in the block - to do this correctly, we have
+ * to know the value we're skipping backwards over or things are ambiguous.
+ * @param {number} value The varint value to unskip.
+ */
+jspb.BinaryDecoder.prototype.unskipVarint = function(value) {
+  while (value > 128) {
+    this.cursor_--;
+    value = value >>> 7;
+  }
+  this.cursor_--;
+};
+
+
+/**
+ * Reads a 32-bit varint from the binary stream. Due to a quirk of the encoding
+ * format and Javascript's handling of bitwise math, this actually works
+ * correctly for both signed and unsigned 32-bit varints.
+ *
+ * This function is called vastly more frequently than any other in
+ * BinaryDecoder, so it has been unrolled and tweaked for performance.
+ *
+ * If there are more than 32 bits of data in the varint, it _must_ be due to
+ * sign-extension. If we're in debug mode and the high 32 bits don't match the
+ * expected sign extension, this method will throw an error.
+ *
+ * Decoding varints requires doing some funny base-128 math - for more
+ * details on the format, see
+ * https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @return {number} The decoded unsigned 32-bit varint.
+ */
+jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() {
+  var temp;
+  var bytes = this.bytes_;
+
+  temp = bytes[this.cursor_ + 0];
+  var x = (temp & 0x7F);
+  if (temp < 128) {
+    this.cursor_ += 1;
+    goog.asserts.assert(this.cursor_ <= this.end_);
+    return x;
+  }
+
+  temp = bytes[this.cursor_ + 1];
+  x |= (temp & 0x7F) << 7;
+  if (temp < 128) {
+    this.cursor_ += 2;
+    goog.asserts.assert(this.cursor_ <= this.end_);
+    return x;
+  }
+
+  temp = bytes[this.cursor_ + 2];
+  x |= (temp & 0x7F) << 14;
+  if (temp < 128) {
+    this.cursor_ += 3;
+    goog.asserts.assert(this.cursor_ <= this.end_);
+    return x;
+  }
+
+  temp = bytes[this.cursor_ + 3];
+  x |= (temp & 0x7F) << 21;
+  if (temp < 128) {
+    this.cursor_ += 4;
+    goog.asserts.assert(this.cursor_ <= this.end_);
+    return x;
+  }
+
+  temp = bytes[this.cursor_ + 4];
+  x |= (temp & 0x0F) << 28;
+  if (temp < 128) {
+    // We're reading the high bits of an unsigned varint. The byte we just read
+    // also contains bits 33 through 35, which we're going to discard. Those
+    // bits _must_ be zero, or the encoding is invalid.
+    goog.asserts.assert((temp & 0xF0) == 0);
+    this.cursor_ += 5;
+    goog.asserts.assert(this.cursor_ <= this.end_);
+    return x >>> 0;
+  }
+
+  // If we get here, we're reading the sign extension of a negative 32-bit int.
+  // We can skip these bytes, as we know in advance that they have to be all
+  // 1's if the varint is correctly encoded. Since we also know the value is
+  // negative, we don't have to coerce it to unsigned before we return it.
+
+  goog.asserts.assert((temp & 0xF0) == 0xF0);
+  goog.asserts.assert(bytes[this.cursor_ + 5] == 0xFF);
+  goog.asserts.assert(bytes[this.cursor_ + 6] == 0xFF);
+  goog.asserts.assert(bytes[this.cursor_ + 7] == 0xFF);
+  goog.asserts.assert(bytes[this.cursor_ + 8] == 0xFF);
+  goog.asserts.assert(bytes[this.cursor_ + 9] == 0x01);
+
+  this.cursor_ += 10;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return x;
+};
+
+
+/**
+ * The readUnsignedVarint32 above deals with signed 32-bit varints correctly,
+ * so this is just an alias.
+ *
+ * @return {number} The decoded signed 32-bit varint.
+ */
+jspb.BinaryDecoder.prototype.readSignedVarint32 =
+    jspb.BinaryDecoder.prototype.readUnsignedVarint32;
+
+
+/**
+ * Reads a 32-bit unsigned variant and returns its value as a string.
+ *
+ * @return {string} The decoded unsigned 32-bit varint as a string.
+ */
+jspb.BinaryDecoder.prototype.readUnsignedVarint32String = function() {
+  // 32-bit integers fit in JavaScript numbers without loss of precision, so
+  // string variants of 32-bit varint readers can simply delegate then convert
+  // to string.
+  var value = this.readUnsignedVarint32();
+  return value.toString();
+};
+
+
+/**
+ * Reads a 32-bit signed variant and returns its value as a string.
+ *
+ * @return {string} The decoded signed 32-bit varint as a string.
+ */
+jspb.BinaryDecoder.prototype.readSignedVarint32String = function() {
+  // 32-bit integers fit in JavaScript numbers without loss of precision, so
+  // string variants of 32-bit varint readers can simply delegate then convert
+  // to string.
+  var value = this.readSignedVarint32();
+  return value.toString();
+};
+
+
+/**
+ * Reads a signed, zigzag-encoded 32-bit varint from the binary stream.
+ *
+ * Zigzag encoding is a modification of varint encoding that reduces the
+ * storage overhead for small negative integers - for more details on the
+ * format, see https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @return {number} The decoded signed, zigzag-encoded 32-bit varint.
+ */
+jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() {
+  var result = this.readUnsignedVarint32();
+  return (result >>> 1) ^ - (result & 1);
+};
+
+
+/**
+ * Reads an unsigned 64-bit varint from the binary stream. Note that since
+ * Javascript represents all numbers as double-precision floats, there will be
+ * precision lost if the absolute value of the varint is larger than 2^53.
+ *
+ * @return {number} The decoded unsigned varint. Precision will be lost if the
+ *     integer exceeds 2^53.
+ */
+jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinUint64(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads an unsigned 64-bit varint from the binary stream and returns the value
+ * as a decimal string.
+ *
+ * @return {string} The decoded unsigned varint as a decimal string.
+ */
+jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinUnsignedDecimalString(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads a signed 64-bit varint from the binary stream. Note that since
+ * Javascript represents all numbers as double-precision floats, there will be
+ * precision lost if the absolute value of the varint is larger than 2^53.
+ *
+ * @return {number} The decoded signed varint. Precision will be lost if the
+ *     integer exceeds 2^53.
+ */
+jspb.BinaryDecoder.prototype.readSignedVarint64 = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinInt64(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads an signed 64-bit varint from the binary stream and returns the value
+ * as a decimal string.
+ *
+ * @return {string} The decoded signed varint as a decimal string.
+ */
+jspb.BinaryDecoder.prototype.readSignedVarint64String = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinSignedDecimalString(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads a signed, zigzag-encoded 64-bit varint from the binary stream. Note
+ * that since Javascript represents all numbers as double-precision floats,
+ * there will be precision lost if the absolute value of the varint is larger
+ * than 2^53.
+ *
+ * Zigzag encoding is a modification of varint encoding that reduces the
+ * storage overhead for small negative integers - for more details on the
+ * format, see https://developers.google.com/protocol-buffers/docs/encoding
+ *
+ * @return {number} The decoded zigzag varint. Precision will be lost if the
+ *     integer exceeds 2^53.
+ */
+jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinZigzag64(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads a raw unsigned 8-bit integer from the binary stream.
+ *
+ * @return {number} The unsigned 8-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readUint8 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  this.cursor_ += 1;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return a;
+};
+
+
+/**
+ * Reads a raw unsigned 16-bit integer from the binary stream.
+ *
+ * @return {number} The unsigned 16-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readUint16 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  var b = this.bytes_[this.cursor_ + 1];
+  this.cursor_ += 2;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return (a << 0) | (b << 8);
+};
+
+
+/**
+ * Reads a raw unsigned 32-bit integer from the binary stream.
+ *
+ * @return {number} The unsigned 32-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readUint32 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  var b = this.bytes_[this.cursor_ + 1];
+  var c = this.bytes_[this.cursor_ + 2];
+  var d = this.bytes_[this.cursor_ + 3];
+  this.cursor_ += 4;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0;
+};
+
+
+/**
+ * Reads a raw unsigned 64-bit integer from the binary stream. Note that since
+ * Javascript represents all numbers as double-precision floats, there will be
+ * precision lost if the absolute value of the integer is larger than 2^53.
+ *
+ * @return {number} The unsigned 64-bit integer read from the binary stream.
+ *     Precision will be lost if the integer exceeds 2^53.
+ */
+jspb.BinaryDecoder.prototype.readUint64 = function() {
+  var bitsLow = this.readUint32();
+  var bitsHigh = this.readUint32();
+  return jspb.utils.joinUint64(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Reads a raw signed 8-bit integer from the binary stream.
+ *
+ * @return {number} The signed 8-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readInt8 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  this.cursor_ += 1;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return (a << 24) >> 24;
+};
+
+
+/**
+ * Reads a raw signed 16-bit integer from the binary stream.
+ *
+ * @return {number} The signed 16-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readInt16 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  var b = this.bytes_[this.cursor_ + 1];
+  this.cursor_ += 2;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return (((a << 0) | (b << 8)) << 16) >> 16;
+};
+
+
+/**
+ * Reads a raw signed 32-bit integer from the binary stream.
+ *
+ * @return {number} The signed 32-bit integer read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readInt32 = function() {
+  var a = this.bytes_[this.cursor_ + 0];
+  var b = this.bytes_[this.cursor_ + 1];
+  var c = this.bytes_[this.cursor_ + 2];
+  var d = this.bytes_[this.cursor_ + 3];
+  this.cursor_ += 4;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return (a << 0) | (b << 8) | (c << 16) | (d << 24);
+};
+
+
+/**
+ * Reads a raw signed 64-bit integer from the binary stream. Note that since
+ * Javascript represents all numbers as double-precision floats, there will be
+ * precision lost if the absolute vlaue of the integer is larger than 2^53.
+ *
+ * @return {number} The signed 64-bit integer read from the binary stream.
+ *     Precision will be lost if the integer exceeds 2^53.
+ */
+jspb.BinaryDecoder.prototype.readInt64 = function() {
+  var bitsLow = this.readUint32();
+  var bitsHigh = this.readUint32();
+  return jspb.utils.joinInt64(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Reads a 32-bit floating-point number from the binary stream, using the
+ * temporary buffer to realign the data.
+ *
+ * @return {number} The float read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readFloat = function() {
+  var bitsLow = this.readUint32();
+  var bitsHigh = 0;
+  return jspb.utils.joinFloat32(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Reads a 64-bit floating-point number from the binary stream, using the
+ * temporary buffer to realign the data.
+ *
+ * @return {number} The double read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readDouble = function() {
+  var bitsLow = this.readUint32();
+  var bitsHigh = this.readUint32();
+  return jspb.utils.joinFloat64(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Reads a boolean value from the binary stream.
+ * @return {boolean} The boolean read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readBool = function() {
+  return !!this.bytes_[this.cursor_++];
+};
+
+
+/**
+ * Reads an enum value from the binary stream, which are always encoded as
+ * signed varints.
+ * @return {number} The enum value read from the binary stream.
+ */
+jspb.BinaryDecoder.prototype.readEnum = function() {
+  return this.readSignedVarint32();
+};
+
+
+/**
+ * Reads and parses a UTF-8 encoded unicode string from the stream.
+ * The code is inspired by maps.vectortown.parse.StreamedDataViewReader, with
+ * the exception that the implementation here does not get confused if it
+ * encounters characters longer than three bytes. These characters are ignored
+ * though, as they are extremely rare: three UTF-8 bytes cover virtually all
+ * characters in common use (http://en.wikipedia.org/wiki/UTF-8).
+ * @param {number} length The length of the string to read.
+ * @return {string} The decoded string.
+ */
+jspb.BinaryDecoder.prototype.readString = function(length) {
+  var bytes = this.bytes_;
+  var cursor = this.cursor_;
+  var end = cursor + length;
+  var chars = [];
+
+  while (cursor < end) {
+    var c = bytes[cursor++];
+    if (c < 128) { // Regular 7-bit ASCII.
+      chars.push(c);
+    } else if (c < 192) {
+      // UTF-8 continuation mark. We are out of sync. This
+      // might happen if we attempted to read a character
+      // with more than three bytes.
+      continue;
+    } else if (c < 224) { // UTF-8 with two bytes.
+      var c2 = bytes[cursor++];
+      chars.push(((c & 31) << 6) | (c2 & 63));
+    } else if (c < 240) { // UTF-8 with three bytes.
+      var c2 = bytes[cursor++];
+      var c3 = bytes[cursor++];
+      chars.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+    }
+  }
+
+  // String.fromCharCode.apply is faster than manually appending characters on
+  // Chrome 25+, and generates no additional cons string garbage.
+  var result = String.fromCharCode.apply(null, chars);
+  this.cursor_ = cursor;
+  return result;
+};
+
+
+/**
+ * Reads and parses a UTF-8 encoded unicode string (with length prefix) from
+ * the stream.
+ * @return {string} The decoded string.
+ */
+jspb.BinaryDecoder.prototype.readStringWithLength = function() {
+  var length = this.readUnsignedVarint32();
+  return this.readString(length);
+};
+
+
+/**
+ * Reads a block of raw bytes from the binary stream.
+ *
+ * @param {number} length The number of bytes to read.
+ * @return {!Uint8Array} The decoded block of bytes, or an empty block if the
+ *     length was invalid.
+ */
+jspb.BinaryDecoder.prototype.readBytes = function(length) {
+  if (length < 0 ||
+      this.cursor_ + length > this.bytes_.length) {
+    this.error_ = true;
+    goog.asserts.fail('Invalid byte length!');
+    return new Uint8Array(0);
+  }
+
+  var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length);
+
+  this.cursor_ += length;
+  goog.asserts.assert(this.cursor_ <= this.end_);
+  return result;
+};
+
+
+/**
+ * Reads a 64-bit varint from the stream and returns it as an 8-character
+ * Unicode string for use as a hash table key.
+ *
+ * @return {string} The hash value.
+ */
+jspb.BinaryDecoder.prototype.readVarintHash64 = function() {
+  this.readSplitVarint64_();
+  return jspb.utils.joinHash64(this.tempLow_, this.tempHigh_);
+};
+
+
+/**
+ * Reads a 64-bit fixed-width value from the stream and returns it as an
+ * 8-character Unicode string for use as a hash table key.
+ *
+ * @return {string} The hash value.
+ */
+jspb.BinaryDecoder.prototype.readFixedHash64 = function() {
+  var bytes = this.bytes_;
+  var cursor = this.cursor_;
+
+  var a = bytes[cursor + 0];
+  var b = bytes[cursor + 1];
+  var c = bytes[cursor + 2];
+  var d = bytes[cursor + 3];
+  var e = bytes[cursor + 4];
+  var f = bytes[cursor + 5];
+  var g = bytes[cursor + 6];
+  var h = bytes[cursor + 7];
+
+  this.cursor_ += 8;
+
+  return String.fromCharCode(a, b, c, d, e, f, g, h);
+};
diff --git a/src/third_party/protobuf-3/js/binary/decoder_test.js b/src/third_party/protobuf-3/js/binary/decoder_test.js
new file mode 100644
index 0000000..d045e91
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/decoder_test.js
@@ -0,0 +1,335 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer decoder.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryEncoder');
+
+
+/**
+ * Tests encoding and decoding of unsigned types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties|visibility}
+ */
+function doTestUnsignedValue(readValue,
+    writeValue, epsilon, upperLimit, filter) {
+  var encoder = new jspb.BinaryEncoder();
+
+  // Encode zero and limits.
+  writeValue.call(encoder, filter(0));
+  writeValue.call(encoder, filter(epsilon));
+  writeValue.call(encoder, filter(upperLimit));
+
+  // Encode positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    writeValue.call(encoder, filter(cursor));
+  }
+
+  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+  // Check zero and limits.
+  assertEquals(filter(0), readValue.call(decoder));
+  assertEquals(filter(epsilon), readValue.call(decoder));
+  assertEquals(filter(upperLimit), readValue.call(decoder));
+
+  // Check positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
+  }
+
+  // Encoding values outside the valid range should assert.
+  assertThrows(function() {writeValue.call(encoder, -1);});
+  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+
+/**
+ * Tests encoding and decoding of signed types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} lowerLimit
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties}
+ */
+function doTestSignedValue(readValue,
+    writeValue, epsilon, lowerLimit, upperLimit, filter) {
+  var encoder = new jspb.BinaryEncoder();
+
+  // Encode zero and limits.
+  writeValue.call(encoder, filter(lowerLimit));
+  writeValue.call(encoder, filter(-epsilon));
+  writeValue.call(encoder, filter(0));
+  writeValue.call(encoder, filter(epsilon));
+  writeValue.call(encoder, filter(upperLimit));
+
+  var inputValues = [];
+
+  // Encode negative values.
+  for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+    var val = filter(cursor);
+    writeValue.call(encoder, val);
+    inputValues.push(val);
+  }
+
+  // Encode positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    var val = filter(cursor);
+    writeValue.call(encoder, val);
+    inputValues.push(val);
+  }
+
+  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+  // Check zero and limits.
+  assertEquals(filter(lowerLimit), readValue.call(decoder));
+  assertEquals(filter(-epsilon), readValue.call(decoder));
+  assertEquals(filter(0), readValue.call(decoder));
+  assertEquals(filter(epsilon), readValue.call(decoder));
+  assertEquals(filter(upperLimit), readValue.call(decoder));
+
+  // Verify decoded values.
+  for (var i = 0; i < inputValues.length; i++) {
+    assertEquals(inputValues[i], readValue.call(decoder));
+  }
+
+  // Encoding values outside the valid range should assert.
+  assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);});
+  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+describe('binaryDecoderTest', function() {
+  /**
+   * Tests the decoder instance cache.
+   * @suppress {visibility}
+   */
+  it('testInstanceCache', function() {
+    // Empty the instance caches.
+    jspb.BinaryDecoder.instanceCache_ = [];
+
+    // Allocating and then freeing a decoder should put it in the instance
+    // cache.
+    jspb.BinaryDecoder.alloc().free();
+
+    assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);
+
+    // Allocating and then freeing three decoders should leave us with three in
+    // the cache.
+
+    var decoder1 = jspb.BinaryDecoder.alloc();
+    var decoder2 = jspb.BinaryDecoder.alloc();
+    var decoder3 = jspb.BinaryDecoder.alloc();
+    decoder1.free();
+    decoder2.free();
+    decoder3.free();
+
+    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+  });
+
+
+  /**
+   * Tests reading 64-bit integers as hash strings.
+   */
+  it('testHashStrings', function() {
+    var encoder = new jspb.BinaryEncoder();
+
+    var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
+                                    0x00, 0x00, 0x00, 0x00);
+    var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
+                                    0x00, 0x00, 0x00, 0x00);
+    var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
+                                    0x87, 0x65, 0x43, 0x21);
+    var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
+                                    0xFF, 0xFF, 0xFF, 0xFF);
+
+    encoder.writeVarintHash64(hashA);
+    encoder.writeVarintHash64(hashB);
+    encoder.writeVarintHash64(hashC);
+    encoder.writeVarintHash64(hashD);
+
+    encoder.writeFixedHash64(hashA);
+    encoder.writeFixedHash64(hashB);
+    encoder.writeFixedHash64(hashC);
+    encoder.writeFixedHash64(hashD);
+
+    var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+    assertEquals(hashA, decoder.readVarintHash64());
+    assertEquals(hashB, decoder.readVarintHash64());
+    assertEquals(hashC, decoder.readVarintHash64());
+    assertEquals(hashD, decoder.readVarintHash64());
+
+    assertEquals(hashA, decoder.readFixedHash64());
+    assertEquals(hashB, decoder.readFixedHash64());
+    assertEquals(hashC, decoder.readFixedHash64());
+    assertEquals(hashD, decoder.readFixedHash64());
+  });
+
+
+  /**
+   * Verifies that misuse of the decoder class triggers assertions.
+   * @suppress {checkTypes|visibility}
+   */
+  it('testDecodeErrors', function() {
+    // Reading a value past the end of the stream should trigger an assertion.
+    var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
+    assertThrows(function() {decoder.readUint64()});
+
+    // Overlong varints should trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 255, 255,
+                      255, 255, 255, 255, 255, 0]);
+    assertThrows(function() {decoder.readUnsignedVarint64()});
+    decoder.reset();
+    assertThrows(function() {decoder.readSignedVarint64()});
+    decoder.reset();
+    assertThrows(function() {decoder.readZigzagVarint64()});
+
+    // Positive 32-bit varints encoded with 1 bits in positions 33 through 35
+    // should trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 0x1F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 0x2F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 0x4F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    // Negative 32-bit varints encoded with non-1 bits in the high dword should
+    // trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+  });
+
+
+  /**
+   * Tests encoding and decoding of unsigned integers.
+   */
+  it('testUnsignedIntegers', function() {
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint8,
+        jspb.BinaryEncoder.prototype.writeUint8,
+        1, 0xFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint16,
+        jspb.BinaryEncoder.prototype.writeUint16,
+        1, 0xFFFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint32,
+        jspb.BinaryEncoder.prototype.writeUint32,
+        1, 0xFFFFFFFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint64,
+        jspb.BinaryEncoder.prototype.writeUint64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+  });
+
+
+  /**
+   * Tests encoding and decoding of signed integers.
+   */
+  it('testSignedIntegers', function() {
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt8,
+        jspb.BinaryEncoder.prototype.writeInt8,
+        1, -0x80, 0x7F, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt16,
+        jspb.BinaryEncoder.prototype.writeInt16,
+        1, -0x8000, 0x7FFF, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt32,
+        jspb.BinaryEncoder.prototype.writeInt32,
+        1, -0x80000000, 0x7FFFFFFF, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt64,
+        jspb.BinaryEncoder.prototype.writeInt64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests encoding and decoding of floats.
+   */
+  it('testFloats', function() {
+    /**
+     * @param {number} x
+     * @return {number}
+     */
+    function truncate(x) {
+      var temp = new Float32Array(1);
+      temp[0] = x;
+      return temp[0];
+    }
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readFloat,
+        jspb.BinaryEncoder.prototype.writeFloat,
+        jspb.BinaryConstants.FLOAT32_EPS,
+        -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX,
+        truncate);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readDouble,
+        jspb.BinaryEncoder.prototype.writeDouble,
+        jspb.BinaryConstants.FLOAT64_EPS * 10,
+        -jspb.BinaryConstants.FLOAT64_MAX,
+        jspb.BinaryConstants.FLOAT64_MAX,
+        function(x) { return x; });
+  });
+});
diff --git a/src/third_party/protobuf-3/js/binary/encoder.js b/src/third_party/protobuf-3/js/binary/encoder.js
new file mode 100644
index 0000000..c9b0c2a
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/encoder.js
@@ -0,0 +1,430 @@
+// 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.
+
+/**
+ * @fileoverview BinaryEncode defines methods for encoding Javascript values
+ * into arrays of bytes compatible with the Protocol Buffer wire format.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.BinaryEncoder');
+
+goog.require('goog.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.utils');
+
+
+
+/**
+ * BinaryEncoder implements encoders for all the wire types specified in
+ * https://developers.google.com/protocol-buffers/docs/encoding.
+ *
+ * @constructor
+ * @struct
+ */
+jspb.BinaryEncoder = function() {
+  /** @private {!Array.<number>} */
+  this.buffer_ = [];
+};
+
+
+/**
+ * @return {number}
+ */
+jspb.BinaryEncoder.prototype.length = function() {
+  return this.buffer_.length;
+};
+
+
+/**
+ * @return {!Array.<number>}
+ */
+jspb.BinaryEncoder.prototype.end = function() {
+  var buffer = this.buffer_;
+  this.buffer_ = [];
+  return buffer;
+};
+
+
+/**
+ * Encodes a 64-bit integer in 32:32 split representation into its wire-format
+ * varint representation and stores it in the buffer.
+ * @param {number} lowBits The low 32 bits of the int.
+ * @param {number} highBits The high 32 bits of the int.
+ */
+jspb.BinaryEncoder.prototype.writeSplitVarint64 = function(lowBits, highBits) {
+  goog.asserts.assert(lowBits == Math.floor(lowBits));
+  goog.asserts.assert(highBits == Math.floor(highBits));
+  goog.asserts.assert((lowBits >= 0) &&
+                      (lowBits < jspb.BinaryConstants.TWO_TO_32));
+  goog.asserts.assert((highBits >= 0) &&
+                      (highBits < jspb.BinaryConstants.TWO_TO_32));
+
+  // Break the binary representation into chunks of 7 bits, set the 8th bit
+  // in each chunk if it's not the final chunk, and append to the result.
+  while (highBits > 0 || lowBits > 127) {
+    this.buffer_.push((lowBits & 0x7f) | 0x80);
+    lowBits = ((lowBits >>> 7) | (highBits << 25)) >>> 0;
+    highBits = highBits >>> 7;
+  }
+  this.buffer_.push(lowBits);
+};
+
+
+/**
+ * Encodes a 32-bit unsigned integer into its wire-format varint representation
+ * and stores it in the buffer.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeUnsignedVarint32 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_32));
+
+  while (value > 127) {
+    this.buffer_.push((value & 0x7f) | 0x80);
+    value = value >>> 7;
+  }
+
+  this.buffer_.push(value);
+};
+
+
+/**
+ * Encodes a 32-bit signed integer into its wire-format varint representation
+ * and stores it in the buffer.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeSignedVarint32 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+
+  // Use the unsigned version if the value is not negative.
+  if (value >= 0) {
+    this.writeUnsignedVarint32(value);
+    return;
+  }
+
+  // Write nine bytes with a _signed_ right shift so we preserve the sign bit.
+  for (var i = 0; i < 9; i++) {
+    this.buffer_.push((value & 0x7f) | 0x80);
+    value = value >> 7;
+  }
+
+  // The above loop writes out 63 bits, so the last byte is always the sign bit
+  // which is always set for negative numbers.
+  this.buffer_.push(1);
+};
+
+
+/**
+ * Encodes a 64-bit unsigned integer into its wire-format varint representation
+ * and stores it in the buffer. Integers that are not representable in 64 bits
+ * will be truncated.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeUnsignedVarint64 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_64));
+  jspb.utils.splitInt64(value);
+  this.writeSplitVarint64(jspb.utils.split64Low,
+                          jspb.utils.split64High);
+};
+
+
+/**
+ * Encodes a 64-bit signed integer into its wire-format varint representation
+ * and stores it in the buffer. Integers that are not representable in 64 bits
+ * will be truncated.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeSignedVarint64 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  jspb.utils.splitInt64(value);
+  this.writeSplitVarint64(jspb.utils.split64Low,
+                          jspb.utils.split64High);
+};
+
+
+/**
+ * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint
+ * representation and stores it in the buffer.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeZigzagVarint32 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeUnsignedVarint32(((value << 1) ^ (value >> 31)) >>> 0);
+};
+
+
+/**
+ * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint
+ * representation and stores it in the buffer. Integers not representable in 64
+ * bits will be truncated.
+ * @param {number} value The integer to convert.
+ */
+jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  jspb.utils.splitZigzag64(value);
+  this.writeSplitVarint64(jspb.utils.split64Low,
+                          jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a 8-bit unsigned integer to the buffer. Numbers outside the range
+ * [0,2^8) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeUint8 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) && (value < 256));
+  this.buffer_.push((value >>> 0) & 0xFF);
+};
+
+
+/**
+ * Writes a 16-bit unsigned integer to the buffer. Numbers outside the
+ * range [0,2^16) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeUint16 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) && (value < 65536));
+  this.buffer_.push((value >>> 0) & 0xFF);
+  this.buffer_.push((value >>> 8) & 0xFF);
+};
+
+
+/**
+ * Writes a 32-bit unsigned integer to the buffer. Numbers outside the
+ * range [0,2^32) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeUint32 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_32));
+  this.buffer_.push((value >>> 0) & 0xFF);
+  this.buffer_.push((value >>> 8) & 0xFF);
+  this.buffer_.push((value >>> 16) & 0xFF);
+  this.buffer_.push((value >>> 24) & 0xFF);
+};
+
+
+/**
+ * Writes a 64-bit unsigned integer to the buffer. Numbers outside the
+ * range [0,2^64) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeUint64 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_64));
+  jspb.utils.splitUint64(value);
+  this.writeUint32(jspb.utils.split64Low);
+  this.writeUint32(jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a 8-bit integer to the buffer. Numbers outside the range
+ * [-2^7,2^7) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeInt8 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -128) && (value < 128));
+  this.buffer_.push((value >>> 0) & 0xFF);
+};
+
+
+/**
+ * Writes a 16-bit integer to the buffer. Numbers outside the range
+ * [-2^15,2^15) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeInt16 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -32768) && (value < 32768));
+  this.buffer_.push((value >>> 0) & 0xFF);
+  this.buffer_.push((value >>> 8) & 0xFF);
+};
+
+
+/**
+ * Writes a 32-bit integer to the buffer. Numbers outside the range
+ * [-2^31,2^31) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeInt32 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.buffer_.push((value >>> 0) & 0xFF);
+  this.buffer_.push((value >>> 8) & 0xFF);
+  this.buffer_.push((value >>> 16) & 0xFF);
+  this.buffer_.push((value >>> 24) & 0xFF);
+};
+
+
+/**
+ * Writes a 64-bit integer to the buffer. Numbers outside the range
+ * [-2^63,2^63) will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeInt64 = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  jspb.utils.splitInt64(value);
+  this.writeUint32(jspb.utils.split64Low);
+  this.writeUint32(jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a single-precision floating point value to the buffer. Numbers
+ * requiring more than 32 bits of precision will be truncated.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeFloat = function(value) {
+  goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT32_MAX) &&
+                      (value <= jspb.BinaryConstants.FLOAT32_MAX));
+  jspb.utils.splitFloat32(value);
+  this.writeUint32(jspb.utils.split64Low);
+};
+
+
+/**
+ * Writes a double-precision floating point value to the buffer. As this is
+ * the native format used by JavaScript, no precision will be lost.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeDouble = function(value) {
+  goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT64_MAX) &&
+                      (value <= jspb.BinaryConstants.FLOAT64_MAX));
+  jspb.utils.splitFloat64(value);
+  this.writeUint32(jspb.utils.split64Low);
+  this.writeUint32(jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a boolean value to the buffer as a varint.
+ * @param {boolean} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeBool = function(value) {
+  goog.asserts.assert(goog.isBoolean(value));
+  this.buffer_.push(value ? 1 : 0);
+};
+
+
+/**
+ * Writes an enum value to the buffer as a varint.
+ * @param {number} value The value to write.
+ */
+jspb.BinaryEncoder.prototype.writeEnum = function(value) {
+  goog.asserts.assert(value == Math.floor(value));
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeSignedVarint32(value);
+};
+
+
+/**
+ * Writes an arbitrary byte array to the buffer.
+ * @param {!Uint8Array} bytes The array of bytes to write.
+ */
+jspb.BinaryEncoder.prototype.writeBytes = function(bytes) {
+  this.buffer_.push.apply(this.buffer_, bytes);
+};
+
+
+/**
+ * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the
+ * buffer as a varint.
+ * @param {string} hash The hash to write.
+ */
+jspb.BinaryEncoder.prototype.writeVarintHash64 = function(hash) {
+  jspb.utils.splitHash64(hash);
+  this.writeSplitVarint64(jspb.utils.split64Low,
+                          jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the
+ * buffer as a fixed64.
+ * @param {string} hash The hash to write.
+ */
+jspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) {
+  jspb.utils.splitHash64(hash);
+  this.writeUint32(jspb.utils.split64Low);
+  this.writeUint32(jspb.utils.split64High);
+};
+
+
+/**
+ * Writes a UTF16 Javascript string to the buffer encoded as UTF8.
+ * TODO(aappleby): Add support for surrogate pairs, reject unpaired surrogates.
+ * @param {string} value The string to write.
+ * @return {number} The number of bytes used to encode the string.
+ */
+jspb.BinaryEncoder.prototype.writeString = function(value) {
+  var oldLength = this.buffer_.length;
+
+  // UTF16 to UTF8 conversion loop swiped from goog.crypt.stringToUtf8ByteArray.
+  for (var i = 0; i < value.length; i++) {
+    var c = value.charCodeAt(i);
+    if (c < 128) {
+      this.buffer_.push(c);
+    } else if (c < 2048) {
+      this.buffer_.push((c >> 6) | 192);
+      this.buffer_.push((c & 63) | 128);
+    } else {
+      this.buffer_.push((c >> 12) | 224);
+      this.buffer_.push(((c >> 6) & 63) | 128);
+      this.buffer_.push((c & 63) | 128);
+    }
+  }
+
+  var length = this.buffer_.length - oldLength;
+  return length;
+};
diff --git a/src/third_party/protobuf-3/js/binary/proto_test.js b/src/third_party/protobuf-3/js/binary/proto_test.js
new file mode 100644
index 0000000..14d0f42
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/proto_test.js
@@ -0,0 +1,628 @@
+// 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.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: ../testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtendsWithMessage');
+goog.require('proto.jspb.test.ForeignEnum');
+goog.require('proto.jspb.test.ForeignMessage');
+goog.require('proto.jspb.test.TestAllTypes');
+goog.require('proto.jspb.test.TestExtendable');
+goog.require('proto.jspb.test.extendOptionalBool');
+goog.require('proto.jspb.test.extendOptionalBytes');
+goog.require('proto.jspb.test.extendOptionalDouble');
+goog.require('proto.jspb.test.extendOptionalFixed32');
+goog.require('proto.jspb.test.extendOptionalFixed64');
+goog.require('proto.jspb.test.extendOptionalFloat');
+goog.require('proto.jspb.test.extendOptionalForeignEnum');
+goog.require('proto.jspb.test.extendOptionalInt32');
+goog.require('proto.jspb.test.extendOptionalInt64');
+goog.require('proto.jspb.test.extendOptionalSfixed32');
+goog.require('proto.jspb.test.extendOptionalSfixed64');
+goog.require('proto.jspb.test.extendOptionalSint32');
+goog.require('proto.jspb.test.extendOptionalSint64');
+goog.require('proto.jspb.test.extendOptionalString');
+goog.require('proto.jspb.test.extendOptionalUint32');
+goog.require('proto.jspb.test.extendOptionalUint64');
+goog.require('proto.jspb.test.extendPackedRepeatedBoolList');
+goog.require('proto.jspb.test.extendPackedRepeatedDoubleList');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedFloatList');
+goog.require('proto.jspb.test.extendPackedRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendPackedRepeatedInt32List');
+goog.require('proto.jspb.test.extendPackedRepeatedInt64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint64List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint64List');
+goog.require('proto.jspb.test.extendRepeatedBoolList');
+goog.require('proto.jspb.test.extendRepeatedBytesList');
+goog.require('proto.jspb.test.extendRepeatedDoubleList');
+goog.require('proto.jspb.test.extendRepeatedFixed32List');
+goog.require('proto.jspb.test.extendRepeatedFixed64List');
+goog.require('proto.jspb.test.extendRepeatedFloatList');
+goog.require('proto.jspb.test.extendRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendRepeatedInt32List');
+goog.require('proto.jspb.test.extendRepeatedInt64List');
+goog.require('proto.jspb.test.extendRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendRepeatedSint32List');
+goog.require('proto.jspb.test.extendRepeatedSint64List');
+goog.require('proto.jspb.test.extendRepeatedStringList');
+goog.require('proto.jspb.test.extendRepeatedUint32List');
+goog.require('proto.jspb.test.extendRepeatedUint64List');
+
+
+var suite = {};
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: fill all fields on a TestAllTypes message.
+ * @param {proto.jspb.test.TestAllTypes} msg
+ */
+function fillAllFields(msg) {
+  msg.setOptionalInt32(-42);
+  // can be exactly represented by JS number (64-bit double, i.e., 52-bit
+  // mantissa).
+  msg.setOptionalInt64(-0x7fffffff00000000);
+  msg.setOptionalUint32(0x80000000);
+  msg.setOptionalUint64(0xf000000000000000);
+  msg.setOptionalSint32(-100);
+  msg.setOptionalSint64(-0x8000000000000000);
+  msg.setOptionalFixed32(1234);
+  msg.setOptionalFixed64(0x1234567800000000);
+  msg.setOptionalSfixed32(-1234);
+  msg.setOptionalSfixed64(-0x1234567800000000);
+  msg.setOptionalFloat(1.5);
+  msg.setOptionalDouble(-1.5);
+  msg.setOptionalBool(true);
+  msg.setOptionalString('hello world');
+  msg.setOptionalBytes(BYTES);
+  msg.setOptionalGroup(new proto.jspb.test.TestAllTypes.OptionalGroup());
+  msg.getOptionalGroup().setA(100);
+  var submsg = new proto.jspb.test.ForeignMessage();
+  submsg.setC(16);
+  msg.setOptionalForeignMessage(submsg);
+  msg.setOptionalForeignEnum(proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+  msg.setOneofString('oneof');
+
+
+  msg.setRepeatedInt32List([-42]);
+  msg.setRepeatedInt64List([-0x7fffffff00000000]);
+  msg.setRepeatedUint32List([0x80000000]);
+  msg.setRepeatedUint64List([0xf000000000000000]);
+  msg.setRepeatedSint32List([-100]);
+  msg.setRepeatedSint64List([-0x8000000000000000]);
+  msg.setRepeatedFixed32List([1234]);
+  msg.setRepeatedFixed64List([0x1234567800000000]);
+  msg.setRepeatedSfixed32List([-1234]);
+  msg.setRepeatedSfixed64List([-0x1234567800000000]);
+  msg.setRepeatedFloatList([1.5]);
+  msg.setRepeatedDoubleList([-1.5]);
+  msg.setRepeatedBoolList([true]);
+  msg.setRepeatedStringList(['hello world']);
+  msg.setRepeatedBytesList([BYTES, BYTES]);
+  msg.setRepeatedGroupList([new proto.jspb.test.TestAllTypes.RepeatedGroup()]);
+  msg.getRepeatedGroupList()[0].setA(100);
+  submsg = new proto.jspb.test.ForeignMessage();
+  submsg.setC(1000);
+  msg.setRepeatedForeignMessageList([submsg]);
+  msg.setRepeatedForeignEnumList([proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  msg.setPackedRepeatedInt32List([-42]);
+  msg.setPackedRepeatedInt64List([-0x7fffffff00000000]);
+  msg.setPackedRepeatedUint32List([0x80000000]);
+  msg.setPackedRepeatedUint64List([0xf000000000000000]);
+  msg.setPackedRepeatedSint32List([-100]);
+  msg.setPackedRepeatedSint64List([-0x8000000000000000]);
+  msg.setPackedRepeatedFixed32List([1234]);
+  msg.setPackedRepeatedFixed64List([0x1234567800000000]);
+  msg.setPackedRepeatedSfixed32List([-1234]);
+  msg.setPackedRepeatedSfixed64List([-0x1234567800000000]);
+  msg.setPackedRepeatedFloatList([1.5]);
+  msg.setPackedRepeatedDoubleList([-1.5]);
+  msg.setPackedRepeatedBoolList([true]);
+
+}
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+  if (goog.isString(arr)) {
+    arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+  }
+  if (arr.length != expected.length) {
+    return false;
+  }
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] != expected[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+/**
+ * Helper: verify contents of given TestAllTypes message as set by
+ * fillAllFields().
+ * @param {proto.jspb.test.TestAllTypes} original
+ * @param {proto.jspb.test.TestAllTypes} copy
+ */
+function checkAllFields(original, copy) {
+  assertTrue(jspb.Message.equals(original, copy));
+
+  assertEquals(copy.getOptionalInt32(), -42);
+  assertEquals(copy.getOptionalInt64(), -0x7fffffff00000000);
+  assertEquals(copy.getOptionalUint32(), 0x80000000);
+  assertEquals(copy.getOptionalUint64(), 0xf000000000000000);
+  assertEquals(copy.getOptionalSint32(), -100);
+  assertEquals(copy.getOptionalSint64(), -0x8000000000000000);
+  assertEquals(copy.getOptionalFixed32(), 1234);
+  assertEquals(copy.getOptionalFixed64(), 0x1234567800000000);
+  assertEquals(copy.getOptionalSfixed32(), -1234);
+  assertEquals(copy.getOptionalSfixed64(), -0x1234567800000000);
+  assertEquals(copy.getOptionalFloat(), 1.5);
+  assertEquals(copy.getOptionalDouble(), -1.5);
+  assertEquals(copy.getOptionalBool(), true);
+  assertEquals(copy.getOptionalString(), 'hello world');
+  assertEquals(true, bytesCompare(copy.getOptionalBytes(), BYTES));
+  assertEquals(true, bytesCompare(copy.getOptionalBytes_asU8(), BYTES));
+  assertEquals(
+      copy.getOptionalBytes_asB64(), goog.crypt.base64.encodeByteArray(BYTES));
+
+  assertEquals(copy.getOptionalGroup().getA(), 100);
+  assertEquals(copy.getOptionalForeignMessage().getC(), 16);
+  assertEquals(copy.getOptionalForeignEnum(),
+      proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+  assertEquals(copy.getOneofString(), 'oneof');
+  assertEquals(copy.getOneofFieldCase(),
+      proto.jspb.test.TestAllTypes.OneofFieldCase.ONEOF_STRING);
+
+  assertElementsEquals(copy.getRepeatedInt32List(), [-42]);
+  assertElementsEquals(copy.getRepeatedInt64List(), [-0x7fffffff00000000]);
+  assertElementsEquals(copy.getRepeatedUint32List(), [0x80000000]);
+  assertElementsEquals(copy.getRepeatedUint64List(), [0xf000000000000000]);
+  assertElementsEquals(copy.getRepeatedSint32List(), [-100]);
+  assertElementsEquals(copy.getRepeatedSint64List(), [-0x8000000000000000]);
+  assertElementsEquals(copy.getRepeatedFixed32List(), [1234]);
+  assertElementsEquals(copy.getRepeatedFixed64List(), [0x1234567800000000]);
+  assertElementsEquals(copy.getRepeatedSfixed32List(), [-1234]);
+  assertElementsEquals(copy.getRepeatedSfixed64List(), [-0x1234567800000000]);
+  assertElementsEquals(copy.getRepeatedFloatList(), [1.5]);
+  assertElementsEquals(copy.getRepeatedDoubleList(), [-1.5]);
+  assertElementsEquals(copy.getRepeatedBoolList(), [true]);
+  assertElementsEquals(copy.getRepeatedStringList(), ['hello world']);
+  assertEquals(copy.getRepeatedBytesList().length, 2);
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES));
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList()[0], BYTES));
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES));
+  assertEquals(copy.getRepeatedBytesList_asB64()[0], BYTES_B64);
+  assertEquals(copy.getRepeatedBytesList_asB64()[1], BYTES_B64);
+  assertEquals(copy.getRepeatedGroupList().length, 1);
+  assertEquals(copy.getRepeatedGroupList()[0].getA(), 100);
+  assertEquals(copy.getRepeatedForeignMessageList().length, 1);
+  assertEquals(copy.getRepeatedForeignMessageList()[0].getC(), 1000);
+  assertElementsEquals(copy.getRepeatedForeignEnumList(),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  assertElementsEquals(copy.getPackedRepeatedInt32List(), [-42]);
+  assertElementsEquals(copy.getPackedRepeatedInt64List(),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(copy.getPackedRepeatedUint32List(), [0x80000000]);
+  assertElementsEquals(copy.getPackedRepeatedUint64List(),
+      [0xf000000000000000]);
+  assertElementsEquals(copy.getPackedRepeatedSint32List(), [-100]);
+  assertElementsEquals(copy.getPackedRepeatedSint64List(),
+      [-0x8000000000000000]);
+  assertElementsEquals(copy.getPackedRepeatedFixed32List(), [1234]);
+  assertElementsEquals(copy.getPackedRepeatedFixed64List(),
+      [0x1234567800000000]);
+  assertElementsEquals(copy.getPackedRepeatedSfixed32List(), [-1234]);
+  assertElementsEquals(copy.getPackedRepeatedSfixed64List(),
+      [-0x1234567800000000]);
+  assertElementsEquals(copy.getPackedRepeatedFloatList(), [1.5]);
+  assertElementsEquals(copy.getPackedRepeatedDoubleList(), [-1.5]);
+
+}
+
+
+/**
+ * Helper: verify that all expected extensions are present.
+ * @param {!proto.jspb.test.TestExtendable} msg
+ */
+function checkExtensions(msg) {
+  assertEquals(-42,
+      msg.getExtension(proto.jspb.test.extendOptionalInt32));
+  assertEquals(-0x7fffffff00000000,
+      msg.getExtension(proto.jspb.test.extendOptionalInt64));
+  assertEquals(0x80000000,
+      msg.getExtension(proto.jspb.test.extendOptionalUint32));
+  assertEquals(0xf000000000000000,
+      msg.getExtension(proto.jspb.test.extendOptionalUint64));
+  assertEquals(-100,
+      msg.getExtension(proto.jspb.test.extendOptionalSint32));
+  assertEquals(-0x8000000000000000,
+      msg.getExtension(proto.jspb.test.extendOptionalSint64));
+  assertEquals(1234,
+      msg.getExtension(proto.jspb.test.extendOptionalFixed32));
+  assertEquals(0x1234567800000000,
+      msg.getExtension(proto.jspb.test.extendOptionalFixed64));
+  assertEquals(-1234,
+      msg.getExtension(proto.jspb.test.extendOptionalSfixed32));
+  assertEquals(-0x1234567800000000,
+      msg.getExtension(proto.jspb.test.extendOptionalSfixed64));
+  assertEquals(1.5,
+      msg.getExtension(proto.jspb.test.extendOptionalFloat));
+  assertEquals(-1.5,
+      msg.getExtension(proto.jspb.test.extendOptionalDouble));
+  assertEquals(true,
+      msg.getExtension(proto.jspb.test.extendOptionalBool));
+  assertEquals('hello world',
+      msg.getExtension(proto.jspb.test.extendOptionalString));
+  assertEquals(
+      true, bytesCompare(
+                msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES));
+  assertEquals(16,
+      msg.getExtension(
+          proto.jspb.test.ExtendsWithMessage.optionalExtension).getFoo());
+
+
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedInt32List),
+      [-42]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedInt64List),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedUint32List),
+      [0x80000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedUint64List),
+      [0xf000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSint32List),
+      [-100]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSint64List),
+      [-0x8000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFixed32List),
+      [1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFixed64List),
+      [0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSfixed32List),
+      [-1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List),
+      [-0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFloatList),
+      [1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedDoubleList),
+      [-1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedBoolList),
+      [true]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedStringList),
+      ['hello world']);
+  assertEquals(
+      true,
+      bytesCompare(
+          msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES));
+  assertEquals(1000,
+      msg.getExtension(
+          proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0]
+      .getFoo());
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedForeignEnumList),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedInt32List),
+      [-42]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedInt64List),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedUint32List),
+      [0x80000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedUint64List),
+      [0xf000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSint32List),
+      [-100]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSint64List),
+      [-0x8000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed32List),
+      [1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed64List),
+      [0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed32List),
+      [-1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed64List),
+      [-0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFloatList),
+      [1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedDoubleList),
+      [-1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedBoolList),
+      [true]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+}
+
+
+describe('protoBinaryTest', function() {
+  /**
+   * Tests a basic serialization-deserializaton round-trip with all supported
+   * field types (on the TestAllTypes message type).
+   */
+  it('testRoundTrip', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    fillAllFields(msg);
+    var encoded = msg.serializeBinary();
+    var decoded = proto.jspb.test.TestAllTypes.deserializeBinary(encoded);
+    checkAllFields(msg, decoded);
+  });
+
+  /**
+   * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+   */
+  it('testBytesFieldsGettersInterop', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    // Set from a base64 string and check all the getters work.
+    msg.setOptionalBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    // Test binary serialize round trip doesn't break it.
+    msg = proto.jspb.test.TestAllTypes.deserializeBinary(msg.serializeBinary());
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg = new proto.jspb.test.TestAllTypes();
+    // Set from a Uint8Array and check all the getters work.
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+  });
+
+  /**
+   * Test that bytes setters will receive result of any of the getters.
+   */
+  it('testBytesFieldsSettersInterop', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg.setOptionalBytes(msg.getOptionalBytes());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    msg.setOptionalBytes(msg.getOptionalBytes_asB64());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    msg.setOptionalBytes(msg.getOptionalBytes_asU8());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+  });
+
+  /**
+   * Test that bytes setters will receive result of any of the getters.
+   */
+  it('testRepeatedBytesGetters', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+
+    function assertGetters() {
+      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
+      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
+      assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
+      assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
+
+      assertTrue(bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList()[1], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[1], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[1], BYTES));
+    }
+
+    msg.setRepeatedBytesList([BYTES, BYTES]);
+    assertGetters();
+
+    msg.setRepeatedBytesList([BYTES_B64, BYTES_B64]);
+    assertGetters();
+
+    msg.setRepeatedBytesList(null);
+    assertEquals(0, msg.getRepeatedBytesList().length);
+    assertEquals(0, msg.getRepeatedBytesList_asB64().length);
+    assertEquals(0, msg.getRepeatedBytesList_asU8().length);
+  });
+
+  /**
+   * Helper: fill all extension values.
+   * @param {proto.jspb.test.TestExtendable} msg
+   */
+  function fillExtensions(msg) {
+    msg.setExtension(
+        proto.jspb.test.extendOptionalInt32, -42);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalUint32, 0x80000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalUint64, 0xf000000000000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSint32, -100);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSint64, -0x8000000000000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFixed32, 1234);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFixed64, 0x1234567800000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSfixed32, -1234);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSfixed64, -0x1234567800000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFloat, 1.5);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalDouble, -1.5);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalBool, true);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalString, 'hello world');
+    msg.setExtension(proto.jspb.test.extendOptionalBytes, BYTES);
+    var submsg = new proto.jspb.test.ExtendsWithMessage();
+    submsg.setFoo(16);
+    msg.setExtension(
+        proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalForeignEnum,
+        proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedInt32List, [-42]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedInt64List, [-0x7fffffff00000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedUint32List, [0x80000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedUint64List, [0xf000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSint32List, [-100]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSint64List, [-0x8000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFixed32List, [1234]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFixed64List, [0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSfixed32List, [-1234]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSfixed64List, [-0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFloatList, [1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedDoubleList, [-1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedBoolList, [true]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedStringList, ['hello world']);
+    msg.setExtension(proto.jspb.test.extendRepeatedBytesList, [BYTES]);
+    submsg = new proto.jspb.test.ExtendsWithMessage();
+    submsg.setFoo(1000);
+    msg.setExtension(
+        proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]);
+    msg.setExtension(proto.jspb.test.extendRepeatedForeignEnumList,
+        [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedInt32List, [-42]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedInt64List, [-0x7fffffff00000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedUint64List, [0xf000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSint32List, [-100]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSint64List, [-0x8000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFixed32List, [1234]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFixed64List, [0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSfixed32List, [-1234]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSfixed64List,
+        [-0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFloatList, [1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedDoubleList, [-1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedBoolList, [true]);
+    msg.setExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList,
+        [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  }
+
+
+  /**
+   * Tests extension serialization and deserialization.
+   */
+  it('testExtensions', function() {
+    var msg = new proto.jspb.test.TestExtendable();
+    fillExtensions(msg);
+    var encoded = msg.serializeBinary();
+    var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
+    checkExtensions(decoded);
+  });
+});
diff --git a/src/third_party/protobuf-3/js/binary/reader.js b/src/third_party/protobuf-3/js/binary/reader.js
new file mode 100644
index 0000000..15f9043
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/reader.js
@@ -0,0 +1,1127 @@
+// 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.
+
+/**
+ * @fileoverview This file contains utilities for converting binary,
+ * wire-format protocol buffers into Javascript data structures.
+ *
+ * jspb's BinaryReader class wraps the BinaryDecoder class to add methods
+ * that understand the protocol buffer syntax and can do the type checking and
+ * bookkeeping necessary to parse trees of nested messages.
+ *
+ * Major caveat - Users of this library _must_ keep their Javascript proto
+ * parsing code in sync with the original .proto file - presumably you'll be
+ * using the typed jspb code generator, but if you bypass that you'll need
+ * to keep things in sync by hand.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.BinaryReader');
+
+goog.require('goog.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+
+
+
+/**
+ * BinaryReader implements the decoders for all the wire types specified in
+ * https://developers.google.com/protocol-buffers/docs/encoding.
+ *
+ * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ * @constructor
+ * @struct
+ */
+jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) {
+  /**
+   * Wire-format decoder.
+   * @private {!jspb.BinaryDecoder}
+   */
+  this.decoder_ = jspb.BinaryDecoder.alloc(opt_bytes, opt_start, opt_length);
+
+  /**
+   * Cursor immediately before the field tag.
+   * @private {number}
+   */
+  this.fieldCursor_ = this.decoder_.getCursor();
+
+  /**
+   * Field number of the next field in the buffer, filled in by nextField().
+   * @private {number}
+   */
+  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
+
+  /**
+   * Wire type of the next proto field in the buffer, filled in by
+   * nextField().
+   * @private {jspb.BinaryConstants.WireType}
+   */
+  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
+
+  /**
+   * Set to true if this reader encountered an error due to corrupt data.
+   * @private {boolean}
+   */
+  this.error_ = false;
+
+  /**
+   * User-defined reader callbacks.
+   * @private {Object.<string, function(!jspb.BinaryReader):*>}
+   */
+  this.readCallbacks_ = null;
+};
+
+
+/**
+ * Global pool of BinaryReader instances.
+ * @private {!Array.<!jspb.BinaryReader>}
+ */
+jspb.BinaryReader.instanceCache_ = [];
+
+
+/**
+ * Pops an instance off the instance cache, or creates one if the cache is
+ * empty.
+ * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ * @return {!jspb.BinaryReader}
+ */
+jspb.BinaryReader.alloc =
+    function(opt_bytes, opt_start, opt_length) {
+  if (jspb.BinaryReader.instanceCache_.length) {
+    var newReader = jspb.BinaryReader.instanceCache_.pop();
+    if (opt_bytes) {
+      newReader.decoder_.setBlock(opt_bytes, opt_start, opt_length);
+    }
+    return newReader;
+  } else {
+    return new jspb.BinaryReader(opt_bytes, opt_start, opt_length);
+  }
+};
+
+
+/**
+ * Alias for the above method.
+ * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
+ * @param {number=} opt_start The optional offset to start reading at.
+ * @param {number=} opt_length The optional length of the block to read -
+ *     we'll throw an assertion if we go off the end of the block.
+ * @return {!jspb.BinaryReader}
+ */
+jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc;
+
+
+/**
+ * Puts this instance back in the instance cache.
+ */
+jspb.BinaryReader.prototype.free = function() {
+  this.decoder_.clear();
+  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
+  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
+  this.error_ = false;
+  this.readCallbacks_ = null;
+
+  if (jspb.BinaryReader.instanceCache_.length < 100) {
+    jspb.BinaryReader.instanceCache_.push(this);
+  }
+};
+
+
+/**
+ * Returns the cursor immediately before the current field's tag.
+ * @return {number} The internal read cursor.
+ */
+jspb.BinaryReader.prototype.getFieldCursor = function() {
+  return this.fieldCursor_;
+};
+
+
+/**
+ * Returns the internal read cursor.
+ * @return {number} The internal read cursor.
+ */
+jspb.BinaryReader.prototype.getCursor = function() {
+  return this.decoder_.getCursor();
+};
+
+
+/**
+ * Returns the raw buffer.
+ * @return {?Uint8Array} The raw buffer.
+ */
+jspb.BinaryReader.prototype.getBuffer = function() {
+  return this.decoder_.getBuffer();
+};
+
+
+/**
+ * @return {number} The field number of the next field in the buffer, or
+ *     INVALID_FIELD_NUMBER if there is no next field.
+ */
+jspb.BinaryReader.prototype.getFieldNumber = function() {
+  return this.nextField_;
+};
+
+
+/**
+ * @return {jspb.BinaryConstants.WireType} The wire type of the next field
+ *     in the stream, or WireType.INVALID if there is no next field.
+ */
+jspb.BinaryReader.prototype.getWireType = function() {
+  return this.nextWireType_;
+};
+
+
+/**
+ * @return {boolean} Whether the current wire type is an end-group tag. Used as
+ * an exit condition in decoder loops in generated code.
+ */
+jspb.BinaryReader.prototype.isEndGroup = function() {
+  return this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP;
+};
+
+
+/**
+ * Returns true if this reader hit an error due to corrupt data.
+ * @return {boolean}
+ */
+jspb.BinaryReader.prototype.getError = function() {
+  return this.error_ || this.decoder_.getError();
+};
+
+
+/**
+ * Points this reader at a new block of bytes.
+ * @param {!Uint8Array} bytes The block of bytes we're reading from.
+ * @param {number} start The offset to start reading at.
+ * @param {number} length The length of the block to read.
+ */
+jspb.BinaryReader.prototype.setBlock = function(bytes, start, length) {
+  this.decoder_.setBlock(bytes, start, length);
+  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
+  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
+};
+
+
+/**
+ * Rewinds the stream cursor to the beginning of the buffer and resets all
+ * internal state.
+ */
+jspb.BinaryReader.prototype.reset = function() {
+  this.decoder_.reset();
+  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
+  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
+};
+
+
+/**
+ * Advances the stream cursor by the given number of bytes.
+ * @param {number} count The number of bytes to advance by.
+ */
+jspb.BinaryReader.prototype.advance = function(count) {
+  this.decoder_.advance(count);
+};
+
+
+/**
+ * Reads the next field header in the stream if there is one, returns true if
+ * we saw a valid field header or false if we've read the whole stream.
+ * Throws an error if we encountered a deprecated START_GROUP/END_GROUP field.
+ * @return {boolean} True if the stream contains more fields.
+ */
+jspb.BinaryReader.prototype.nextField = function() {
+  // If we're at the end of the block, there are no more fields.
+  if (this.decoder_.atEnd()) {
+    return false;
+  }
+
+  // If we hit an error decoding the previous field, stop now before we
+  // try to decode anything else
+  if (this.getError()) {
+    goog.asserts.fail('Decoder hit an error');
+    return false;
+  }
+
+  // Otherwise just read the header of the next field.
+  this.fieldCursor_ = this.decoder_.getCursor();
+  var header = this.decoder_.readUnsignedVarint32();
+
+  var nextField = header >>> 3;
+  var nextWireType = /** @type {jspb.BinaryConstants.WireType} */
+      (header & 0x7);
+
+  // If the wire type isn't one of the valid ones, something's broken.
+  if (nextWireType != jspb.BinaryConstants.WireType.VARINT &&
+      nextWireType != jspb.BinaryConstants.WireType.FIXED32 &&
+      nextWireType != jspb.BinaryConstants.WireType.FIXED64 &&
+      nextWireType != jspb.BinaryConstants.WireType.DELIMITED &&
+      nextWireType != jspb.BinaryConstants.WireType.START_GROUP &&
+      nextWireType != jspb.BinaryConstants.WireType.END_GROUP) {
+    goog.asserts.fail('Invalid wire type');
+    this.error_ = true;
+    return false;
+  }
+
+  this.nextField_ = nextField;
+  this.nextWireType_ = nextWireType;
+
+  return true;
+};
+
+
+/**
+ * Winds the reader back to just before this field's header.
+ */
+jspb.BinaryReader.prototype.unskipHeader = function() {
+  this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_);
+};
+
+
+/**
+ * Skips all contiguous fields whose header matches the one we just read.
+ */
+jspb.BinaryReader.prototype.skipMatchingFields = function() {
+  var field = this.nextField_;
+  this.unskipHeader();
+
+  while (this.nextField() && (this.getFieldNumber() == field)) {
+    this.skipField();
+  }
+
+  if (!this.decoder_.atEnd()) {
+    this.unskipHeader();
+  }
+};
+
+
+/**
+ * Skips over the next varint field in the binary stream.
+ */
+jspb.BinaryReader.prototype.skipVarintField = function() {
+  if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) {
+    goog.asserts.fail('Invalid wire type for skipVarintField');
+    this.skipField();
+    return;
+  }
+
+  this.decoder_.skipVarint();
+};
+
+
+/**
+ * Skips over the next delimited field in the binary stream.
+ */
+jspb.BinaryReader.prototype.skipDelimitedField = function() {
+  if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) {
+    goog.asserts.fail('Invalid wire type for skipDelimitedField');
+    this.skipField();
+    return;
+  }
+
+  var length = this.decoder_.readUnsignedVarint32();
+  this.decoder_.advance(length);
+};
+
+
+/**
+ * Skips over the next fixed32 field in the binary stream.
+ */
+jspb.BinaryReader.prototype.skipFixed32Field = function() {
+  if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) {
+    goog.asserts.fail('Invalid wire type for skipFixed32Field');
+    this.skipField();
+    return;
+  }
+
+  this.decoder_.advance(4);
+};
+
+
+/**
+ * Skips over the next fixed64 field in the binary stream.
+ */
+jspb.BinaryReader.prototype.skipFixed64Field = function() {
+  if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) {
+    goog.asserts.fail('Invalid wire type for skipFixed64Field');
+    this.skipField();
+    return;
+  }
+
+  this.decoder_.advance(8);
+};
+
+
+/**
+ * Skips over the next group field in the binary stream.
+ */
+jspb.BinaryReader.prototype.skipGroup = function() {
+  // Keep a stack of start-group tags that must be matched by end-group tags.
+  var nestedGroups = [this.nextField_];
+  do {
+    if (!this.nextField()) {
+      goog.asserts.fail('Unmatched start-group tag: stream EOF');
+      this.error_ = true;
+      return;
+    }
+    if (this.nextWireType_ ==
+        jspb.BinaryConstants.WireType.START_GROUP) {
+      // Nested group start.
+      nestedGroups.push(this.nextField_);
+    } else if (this.nextWireType_ ==
+               jspb.BinaryConstants.WireType.END_GROUP) {
+      // Group end: check that it matches top-of-stack.
+      if (this.nextField_ != nestedGroups.pop()) {
+        goog.asserts.fail('Unmatched end-group tag');
+        this.error_ = true;
+        return;
+      }
+    }
+  } while (nestedGroups.length > 0);
+};
+
+
+/**
+ * Skips over the next field in the binary stream - this is useful if we're
+ * decoding a message that contain unknown fields.
+ */
+jspb.BinaryReader.prototype.skipField = function() {
+  switch (this.nextWireType_) {
+    case jspb.BinaryConstants.WireType.VARINT:
+      this.skipVarintField();
+      break;
+    case jspb.BinaryConstants.WireType.FIXED64:
+      this.skipFixed64Field();
+      break;
+    case jspb.BinaryConstants.WireType.DELIMITED:
+      this.skipDelimitedField();
+      break;
+    case jspb.BinaryConstants.WireType.FIXED32:
+      this.skipFixed32Field();
+      break;
+    case jspb.BinaryConstants.WireType.START_GROUP:
+      this.skipGroup();
+      break;
+    default:
+      goog.asserts.fail('Invalid wire encoding for field.');
+  }
+};
+
+
+/**
+ * Registers a user-defined read callback.
+ * @param {string} callbackName
+ * @param {function(!jspb.BinaryReader):*} callback
+ */
+jspb.BinaryReader.prototype.registerReadCallback =
+    function(callbackName, callback) {
+  if (goog.isNull(this.readCallbacks_)) {
+    this.readCallbacks_ = {};
+  }
+  goog.asserts.assert(!this.readCallbacks_[callbackName]);
+  this.readCallbacks_[callbackName] = callback;
+};
+
+
+/**
+ * Runs a registered read callback.
+ * @param {string} callbackName The name the callback is registered under.
+ * @return {*} The value returned by the callback.
+ */
+jspb.BinaryReader.prototype.runReadCallback = function(callbackName) {
+  goog.asserts.assert(!goog.isNull(this.readCallbacks_));
+  var callback = this.readCallbacks_[callbackName];
+  goog.asserts.assert(callback);
+  return callback(this);
+};
+
+
+/**
+ * Reads a field of any valid non-message type from the binary stream.
+ * @param {jspb.BinaryConstants.FieldType} fieldType
+ * @return {jspb.AnyFieldType}
+ */
+jspb.BinaryReader.prototype.readAny = function(fieldType) {
+  this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType);
+  var fieldTypes = jspb.BinaryConstants.FieldType;
+  switch (fieldType) {
+    case fieldTypes.DOUBLE:
+      return this.readDouble();
+    case fieldTypes.FLOAT:
+      return this.readFloat();
+    case fieldTypes.INT64:
+      return this.readInt64();
+    case fieldTypes.UINT64:
+      return this.readUint64();
+    case fieldTypes.INT32:
+      return this.readInt32();
+    case fieldTypes.FIXED64:
+      return this.readFixed64();
+    case fieldTypes.FIXED32:
+      return this.readFixed32();
+    case fieldTypes.BOOL:
+      return this.readBool();
+    case fieldTypes.STRING:
+      return this.readString();
+    case fieldTypes.GROUP:
+      goog.asserts.fail('Group field type not supported in readAny()');
+    case fieldTypes.MESSAGE:
+      goog.asserts.fail('Message field type not supported in readAny()');
+    case fieldTypes.BYTES:
+      return this.readBytes();
+    case fieldTypes.UINT32:
+      return this.readUint32();
+    case fieldTypes.ENUM:
+      return this.readEnum();
+    case fieldTypes.SFIXED32:
+      return this.readSfixed32();
+    case fieldTypes.SFIXED64:
+      return this.readSfixed64();
+    case fieldTypes.SINT32:
+      return this.readSint32();
+    case fieldTypes.SINT64:
+      return this.readSint64();
+    case fieldTypes.FHASH64:
+      return this.readFixedHash64();
+    case fieldTypes.VHASH64:
+      return this.readVarintHash64();
+    default:
+      goog.asserts.fail('Invalid field type in readAny()');
+  }
+  return 0;
+};
+
+
+/**
+ * Deserialize a proto into the provided message object using the provided
+ * reader function. This function is templated as we currently have one client
+ * who is using manual deserialization instead of the code-generated versions.
+ * @template T
+ * @param {T} message
+ * @param {function(T, !jspb.BinaryReader)} reader
+ */
+jspb.BinaryReader.prototype.readMessage = function(message, reader) {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
+
+  // Save the current endpoint of the decoder and move it to the end of the
+  // embedded message.
+  var oldEnd = this.decoder_.getEnd();
+  var length = this.decoder_.readUnsignedVarint32();
+  var newEnd = this.decoder_.getCursor() + length;
+  this.decoder_.setEnd(newEnd);
+
+  // Deserialize the embedded message.
+  reader(message, this);
+
+  // Advance the decoder past the embedded message and restore the endpoint.
+  this.decoder_.setCursor(newEnd);
+  this.decoder_.setEnd(oldEnd);
+};
+
+
+/**
+ * Deserialize a proto into the provided message object using the provided
+ * reader function, assuming that the message is serialized as a group
+ * with the given tag.
+ * @template T
+ * @param {number} field
+ * @param {T} message
+ * @param {function(T, !jspb.BinaryReader)} reader
+ */
+jspb.BinaryReader.prototype.readGroup =
+    function(field, message, reader) {
+  // Ensure that the wire type is correct.
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP);
+  // Ensure that the field number is correct.
+  goog.asserts.assert(this.nextField_ == field);
+
+  // Deserialize the message. The deserialization will stop at an END_GROUP tag.
+  reader(message, this);
+
+  if (!this.error_ &&
+      this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) {
+    goog.asserts.fail('Group submessage did not end with an END_GROUP tag');
+    this.error_ = true;
+  }
+};
+
+
+/**
+ * Return a decoder that wraps the current delimited field.
+ * @return {!jspb.BinaryDecoder}
+ */
+jspb.BinaryReader.prototype.getFieldDecoder = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
+
+  var length = this.decoder_.readUnsignedVarint32();
+  var start = this.decoder_.getCursor();
+  var end = start + length;
+
+  var innerDecoder =
+      jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length);
+  this.decoder_.setCursor(end);
+  return innerDecoder;
+};
+
+
+/**
+ * Reads a signed 32-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the signed 32-bit integer field.
+ */
+jspb.BinaryReader.prototype.readInt32 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSignedVarint32();
+};
+
+
+/**
+ * Reads a signed 32-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * Returns the value as a string.
+ *
+ * @return {string} The value of the signed 32-bit integer field as a decimal
+ * string.
+ */
+jspb.BinaryReader.prototype.readInt32String = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSignedVarint32String();
+};
+
+
+/**
+ * Reads a signed 64-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the signed 64-bit integer field.
+ */
+jspb.BinaryReader.prototype.readInt64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSignedVarint64();
+};
+
+
+/**
+ * Reads a signed 64-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * Returns the value as a string.
+ *
+ * @return {string} The value of the signed 64-bit integer field as a decimal
+ * string.
+ */
+jspb.BinaryReader.prototype.readInt64String = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSignedVarint64String();
+};
+
+
+/**
+ * Reads an unsigned 32-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the unsigned 32-bit integer field.
+ */
+jspb.BinaryReader.prototype.readUint32 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readUnsignedVarint32();
+};
+
+
+/**
+ * Reads an unsigned 32-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * Returns the value as a string.
+ *
+ * @return {string} The value of the unsigned 32-bit integer field as a decimal
+ * string.
+ */
+jspb.BinaryReader.prototype.readUint32String = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readUnsignedVarint32String();
+};
+
+
+/**
+ * Reads an unsigned 64-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the unsigned 64-bit integer field.
+ */
+jspb.BinaryReader.prototype.readUint64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readUnsignedVarint64();
+};
+
+
+/**
+ * Reads an unsigned 64-bit integer field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * Returns the value as a string.
+ *
+ * @return {string} The value of the unsigned 64-bit integer field as a decimal
+ * string.
+ */
+jspb.BinaryReader.prototype.readUint64String = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readUnsignedVarint64String();
+};
+
+
+/**
+ * Reads a signed zigzag-encoded 32-bit integer field from the binary stream,
+ * or throws an error if the next field in the stream is not of the correct
+ * wire type.
+ *
+ * @return {number} The value of the signed 32-bit integer field.
+ */
+jspb.BinaryReader.prototype.readSint32 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readZigzagVarint32();
+};
+
+
+/**
+ * Reads a signed zigzag-encoded 64-bit integer field from the binary stream,
+ * or throws an error if the next field in the stream is not of the correct
+ * wire type.
+ *
+ * @return {number} The value of the signed 64-bit integer field.
+ */
+jspb.BinaryReader.prototype.readSint64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readZigzagVarint64();
+};
+
+
+/**
+ * Reads an unsigned 32-bit fixed-length integer fiield from the binary stream,
+ * or throws an error if the next field in the stream is not of the correct
+ * wire type.
+ *
+ * @return {number} The value of the double field.
+ */
+jspb.BinaryReader.prototype.readFixed32 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
+  return this.decoder_.readUint32();
+};
+
+
+/**
+ * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream,
+ * or throws an error if the next field in the stream is not of the correct
+ * wire type.
+ *
+ * @return {number} The value of the float field.
+ */
+jspb.BinaryReader.prototype.readFixed64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
+  return this.decoder_.readUint64();
+};
+
+
+/**
+ * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
+ * throws an error if the next field in the stream is not of the correct wire
+ * type.
+ *
+ * @return {number} The value of the double field.
+ */
+jspb.BinaryReader.prototype.readSfixed32 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
+  return this.decoder_.readInt32();
+};
+
+
+/**
+ * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
+ * throws an error if the next field in the stream is not of the correct wire
+ * type.
+ *
+ * @return {number} The value of the float field.
+ */
+jspb.BinaryReader.prototype.readSfixed64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
+  return this.decoder_.readInt64();
+};
+
+
+/**
+ * Reads a 32-bit floating-point field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the float field.
+ */
+jspb.BinaryReader.prototype.readFloat = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
+  return this.decoder_.readFloat();
+};
+
+
+/**
+ * Reads a 64-bit floating-point field from the binary stream, or throws an
+ * error if the next field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the double field.
+ */
+jspb.BinaryReader.prototype.readDouble = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
+  return this.decoder_.readDouble();
+};
+
+
+/**
+ * Reads a boolean field from the binary stream, or throws an error if the next
+ * field in the stream is not of the correct wire type.
+ *
+ * @return {boolean} The value of the boolean field.
+ */
+jspb.BinaryReader.prototype.readBool = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return !!this.decoder_.readUnsignedVarint32();
+};
+
+
+/**
+ * Reads an enum field from the binary stream, or throws an error if the next
+ * field in the stream is not of the correct wire type.
+ *
+ * @return {number} The value of the enum field.
+ */
+jspb.BinaryReader.prototype.readEnum = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readSignedVarint64();
+};
+
+
+/**
+ * Reads a string field from the binary stream, or throws an error if the next
+ * field in the stream is not of the correct wire type.
+ *
+ * @return {string} The value of the string field.
+ */
+jspb.BinaryReader.prototype.readString = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
+  var length = this.decoder_.readUnsignedVarint32();
+  return this.decoder_.readString(length);
+};
+
+
+/**
+ * Reads a length-prefixed block of bytes from the binary stream, or returns
+ * null if the next field in the stream has an invalid length value.
+ *
+ * @return {!Uint8Array} The block of bytes.
+ */
+jspb.BinaryReader.prototype.readBytes = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
+  var length = this.decoder_.readUnsignedVarint32();
+  return this.decoder_.readBytes(length);
+};
+
+
+/**
+ * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
+ * 8-character Unicode string for use as a hash table key, or throws an error
+ * if the next field in the stream is not of the correct wire type.
+ *
+ * @return {string} The hash value.
+ */
+jspb.BinaryReader.prototype.readVarintHash64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
+  return this.decoder_.readVarintHash64();
+};
+
+
+/**
+ * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
+ * 8-character Unicode string for use as a hash table key, or throws an error
+ * if the next field in the stream is not of the correct wire type.
+ *
+ * @return {string} The hash value.
+ */
+jspb.BinaryReader.prototype.readFixedHash64 = function() {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
+  return this.decoder_.readFixedHash64();
+};
+
+
+/**
+ * Reads a packed scalar field using the supplied raw reader function.
+ * @param {function()} decodeMethod
+ * @return {!Array}
+ * @private
+ */
+jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) {
+  goog.asserts.assert(
+      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
+  var length = this.decoder_.readUnsignedVarint32();
+  var end = this.decoder_.getCursor() + length;
+  var result = [];
+  while (this.decoder_.getCursor() < end) {
+    // TODO(aappleby): .call is slow
+    result.push(decodeMethod.call(this.decoder_));
+  }
+  return result;
+};
+
+
+/**
+ * Reads a packed int32 field, which consists of a length header and a list of
+ * signed varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedInt32 = function() {
+  return this.readPackedField_(this.decoder_.readSignedVarint32);
+};
+
+
+/**
+ * Reads a packed int32 field, which consists of a length header and a list of
+ * signed varints. Returns a list of strings.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedInt32String = function() {
+  return this.readPackedField_(this.decoder_.readSignedVarint32String);
+};
+
+
+/**
+ * Reads a packed int64 field, which consists of a length header and a list of
+ * signed varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedInt64 = function() {
+  return this.readPackedField_(this.decoder_.readSignedVarint64);
+};
+
+
+/**
+ * Reads a packed int64 field, which consists of a length header and a list of
+ * signed varints. Returns a list of strings.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedInt64String = function() {
+  return this.readPackedField_(this.decoder_.readSignedVarint64String);
+};
+
+
+/**
+ * Reads a packed uint32 field, which consists of a length header and a list of
+ * unsigned varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedUint32 = function() {
+  return this.readPackedField_(this.decoder_.readUnsignedVarint32);
+};
+
+
+/**
+ * Reads a packed uint32 field, which consists of a length header and a list of
+ * unsigned varints. Returns a list of strings.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedUint32String = function() {
+  return this.readPackedField_(this.decoder_.readUnsignedVarint32String);
+};
+
+
+/**
+ * Reads a packed uint64 field, which consists of a length header and a list of
+ * unsigned varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedUint64 = function() {
+  return this.readPackedField_(this.decoder_.readUnsignedVarint64);
+};
+
+
+/**
+ * Reads a packed uint64 field, which consists of a length header and a list of
+ * unsigned varints. Returns a list of strings.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedUint64String = function() {
+  return this.readPackedField_(this.decoder_.readUnsignedVarint64String);
+};
+
+
+/**
+ * Reads a packed sint32 field, which consists of a length header and a list of
+ * zigzag varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedSint32 = function() {
+  return this.readPackedField_(this.decoder_.readZigzagVarint32);
+};
+
+
+/**
+ * Reads a packed sint64 field, which consists of a length header and a list of
+ * zigzag varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedSint64 = function() {
+  return this.readPackedField_(this.decoder_.readZigzagVarint64);
+};
+
+
+/**
+ * Reads a packed fixed32 field, which consists of a length header and a list
+ * of unsigned 32-bit ints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedFixed32 = function() {
+  return this.readPackedField_(this.decoder_.readUint32);
+};
+
+
+/**
+ * Reads a packed fixed64 field, which consists of a length header and a list
+ * of unsigned 64-bit ints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedFixed64 = function() {
+  return this.readPackedField_(this.decoder_.readUint64);
+};
+
+
+/**
+ * Reads a packed sfixed32 field, which consists of a length header and a list
+ * of 32-bit ints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedSfixed32 = function() {
+  return this.readPackedField_(this.decoder_.readInt32);
+};
+
+
+/**
+ * Reads a packed sfixed64 field, which consists of a length header and a list
+ * of 64-bit ints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedSfixed64 = function() {
+  return this.readPackedField_(this.decoder_.readInt64);
+};
+
+
+/**
+ * Reads a packed float field, which consists of a length header and a list of
+ * floats.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedFloat = function() {
+  return this.readPackedField_(this.decoder_.readFloat);
+};
+
+
+/**
+ * Reads a packed double field, which consists of a length header and a list of
+ * doubles.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedDouble = function() {
+  return this.readPackedField_(this.decoder_.readDouble);
+};
+
+
+/**
+ * Reads a packed bool field, which consists of a length header and a list of
+ * unsigned varints.
+ * @return {!Array.<boolean>}
+ */
+jspb.BinaryReader.prototype.readPackedBool = function() {
+  return this.readPackedField_(this.decoder_.readBool);
+};
+
+
+/**
+ * Reads a packed enum field, which consists of a length header and a list of
+ * unsigned varints.
+ * @return {!Array.<number>}
+ */
+jspb.BinaryReader.prototype.readPackedEnum = function() {
+  return this.readPackedField_(this.decoder_.readEnum);
+};
+
+
+/**
+ * Reads a packed varint hash64 field, which consists of a length header and a
+ * list of varint hash64s.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {
+  return this.readPackedField_(this.decoder_.readVarintHash64);
+};
+
+
+/**
+ * Reads a packed fixed hash64 field, which consists of a length header and a
+ * list of fixed hash64s.
+ * @return {!Array.<string>}
+ */
+jspb.BinaryReader.prototype.readPackedFixedHash64 = function() {
+  return this.readPackedField_(this.decoder_.readFixedHash64);
+};
diff --git a/src/third_party/protobuf-3/js/binary/reader_test.js b/src/third_party/protobuf-3/js/binary/reader_test.js
new file mode 100644
index 0000000..6f7e5d4
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/reader_test.js
@@ -0,0 +1,873 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer reader.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryReader');
+goog.require('jspb.BinaryWriter');
+
+
+
+describe('binaryReaderTest', function() {
+  /**
+   * Tests the reader instance cache.
+   * @suppress {visibility}
+   */
+  it('testInstanceCaches', function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    writer.writeMessage(1, dummyMessage, goog.nullFunction);
+    writer.writeMessage(2, dummyMessage, goog.nullFunction);
+
+    var buffer = writer.getResultBuffer();
+
+    // Empty the instance caches.
+    jspb.BinaryReader.instanceCache_ = [];
+
+    // Allocating and then freeing three decoders should leave us with three in
+    // the cache.
+
+    var decoder1 = jspb.BinaryDecoder.alloc();
+    var decoder2 = jspb.BinaryDecoder.alloc();
+    var decoder3 = jspb.BinaryDecoder.alloc();
+    decoder1.free();
+    decoder2.free();
+    decoder3.free();
+
+    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Allocating and then freeing a reader should remove one decoder from its
+    // cache, but it should stay stuck to the reader afterwards since we can't
+    // have a reader without a decoder.
+    jspb.BinaryReader.alloc().free();
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+
+    // Allocating a reader should remove a reader from the cache.
+    var reader = jspb.BinaryReader.alloc(buffer);
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Processing the message reuses the current reader.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+    });
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+    });
+
+    assertEquals(false, reader.nextField());
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Freeing the reader should put it back into the cache.
+    reader.free();
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+  });
+
+
+  /**
+   * @param {number} x
+   * @return {number}
+   */
+  function truncate(x) {
+    var temp = new Float32Array(1);
+    temp[0] = x;
+    return temp[0];
+  }
+
+
+  /**
+   * Verifies that misuse of the reader class triggers assertions.
+   * @suppress {checkTypes|visibility}
+   */
+  it('testReadErrors', function() {
+    // Calling readMessage on a non-delimited field should trigger an
+    // assertion.
+    var reader = jspb.BinaryReader.alloc([8, 1]);
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    reader.nextField();
+    assertThrows(function() {
+      reader.readMessage(dummyMessage, goog.nullFunction);
+    });
+
+    // Reading past the end of the stream should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([9, 1]);
+    reader.nextField();
+    assertThrows(function() {reader.readFixed64()});
+
+    // Reading past the end of a submessage should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
+    reader.nextField();
+    reader.readMessage(dummyMessage, function() {
+      reader.nextField();
+      assertThrows(function() {reader.readFixed32()});
+    });
+
+    // Skipping an invalid field should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([12, 1]);
+    reader.nextWireType_ = 1000;
+    assertThrows(function() {reader.skipField()});
+
+    // Reading fields with the wrong wire type should assert.
+    reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
+    reader.nextField();
+    assertThrows(function() {reader.readInt32()});
+    assertThrows(function() {reader.readInt32String()});
+    assertThrows(function() {reader.readInt64()});
+    assertThrows(function() {reader.readInt64String()});
+    assertThrows(function() {reader.readUint32()});
+    assertThrows(function() {reader.readUint32String()});
+    assertThrows(function() {reader.readUint64()});
+    assertThrows(function() {reader.readUint64String()});
+    assertThrows(function() {reader.readSint32()});
+    assertThrows(function() {reader.readBool()});
+    assertThrows(function() {reader.readEnum()});
+
+    reader = jspb.BinaryReader.alloc([8, 1]);
+    reader.nextField();
+    assertThrows(function() {reader.readFixed32()});
+    assertThrows(function() {reader.readFixed64()});
+    assertThrows(function() {reader.readSfixed32()});
+    assertThrows(function() {reader.readSfixed64()});
+    assertThrows(function() {reader.readFloat()});
+    assertThrows(function() {reader.readDouble()});
+
+    assertThrows(function() {reader.readString()});
+    assertThrows(function() {reader.readBytes()});
+  });
+
+
+  /**
+   * Tests encoding and decoding of unsigned field types.
+   * @param {Function} readField
+   * @param {Function} writeField
+   * @param {number} epsilon
+   * @param {number} upperLimit
+   * @param {Function} filter
+   * @private
+   * @suppress {missingProperties}
+   */
+  function doTestUnsignedField_(readField,
+      writeField, epsilon, upperLimit, filter) {
+    assertNotNull(readField);
+    assertNotNull(writeField);
+
+    var writer = new jspb.BinaryWriter();
+
+    // Encode zero and limits.
+    writeField.call(writer, 1, filter(0));
+    writeField.call(writer, 2, filter(epsilon));
+    writeField.call(writer, 3, filter(upperLimit));
+
+    // Encode positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      writeField.call(writer, 4, filter(cursor));
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Check zero and limits.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(filter(0), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(filter(epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(filter(upperLimit), readField.call(reader));
+
+    // Check positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      reader.nextField();
+      if (4 != reader.getFieldNumber()) throw 'fail!';
+      if (filter(cursor) != readField.call(reader)) throw 'fail!';
+    }
+  };
+
+
+  /**
+   * Tests encoding and decoding of signed field types.
+   * @param {Function} readField
+   * @param {Function} writeField
+   * @param {number} epsilon
+   * @param {number} lowerLimit
+   * @param {number} upperLimit
+   * @param {Function} filter
+   * @private
+   * @suppress {missingProperties}
+   */
+  function doTestSignedField_(readField,
+      writeField, epsilon, lowerLimit, upperLimit, filter) {
+    var writer = new jspb.BinaryWriter();
+
+    // Encode zero and limits.
+    writeField.call(writer, 1, filter(lowerLimit));
+    writeField.call(writer, 2, filter(-epsilon));
+    writeField.call(writer, 3, filter(0));
+    writeField.call(writer, 4, filter(epsilon));
+    writeField.call(writer, 5, filter(upperLimit));
+
+    var inputValues = [];
+
+    // Encode negative values.
+    for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+      var val = filter(cursor);
+      writeField.call(writer, 6, val);
+      inputValues.push({
+        fieldNumber: 6,
+        value: val
+      });
+    }
+
+    // Encode positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      var val = filter(cursor);
+      writeField.call(writer, 7, val);
+      inputValues.push({
+        fieldNumber: 7,
+        value: val
+      });
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Check zero and limits.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(filter(lowerLimit), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(filter(-epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(filter(0), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(4, reader.getFieldNumber());
+    assertEquals(filter(epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(5, reader.getFieldNumber());
+    assertEquals(filter(upperLimit), readField.call(reader));
+
+    for (var i = 0; i < inputValues.length; i++) {
+      var expected = inputValues[i];
+      reader.nextField();
+      assertEquals(expected.fieldNumber, reader.getFieldNumber());
+      assertEquals(expected.value, readField.call(reader));
+    }
+  };
+
+
+  /**
+   * Tests fields that use varint encoding.
+   */
+  it('testVarintFields', function() {
+    assertNotNull(jspb.BinaryReader.prototype.readUint32);
+    assertNotNull(jspb.BinaryReader.prototype.writeUint32);
+    assertNotNull(jspb.BinaryReader.prototype.readUint64);
+    assertNotNull(jspb.BinaryReader.prototype.writeUint64);
+    assertNotNull(jspb.BinaryReader.prototype.readBool);
+    assertNotNull(jspb.BinaryReader.prototype.writeBool);
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readUint32,
+        jspb.BinaryWriter.prototype.writeUint32,
+        1, Math.pow(2, 32) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readUint64,
+        jspb.BinaryWriter.prototype.writeUint64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readInt32,
+        jspb.BinaryWriter.prototype.writeInt32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readInt64,
+        jspb.BinaryWriter.prototype.writeInt64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readEnum,
+        jspb.BinaryWriter.prototype.writeEnum,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readBool,
+        jspb.BinaryWriter.prototype.writeBool,
+        1, 1, function(x) { return !!x; });
+  });
+
+
+  /**
+   * Tests 64-bit fields that are handled as strings.
+   */
+  it('testStringInt64Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var testSignedData = [
+      '2730538252207801776',
+      '-2688470994844604560',
+      '3398529779486536359',
+      '3568577411627971000',
+      '272477188847484900',
+      '-6649058714086158188',
+      '-7695254765712060806',
+      '-4525541438037104029',
+      '-4993706538836508568',
+      '4990160321893729138'
+    ];
+    var testUnsignedData = [
+      '7822732630241694882',
+      '6753602971916687352',
+      '2399935075244442116',
+      '8724292567325338867',
+      '16948784802625696584',
+      '4136275908516066934',
+      '3575388346793700364',
+      '5167142028379259461',
+      '1557573948689737699',
+      '17100725280812548567'
+    ];
+
+    for (var i = 0; i < testSignedData.length; i++) {
+      writer.writeInt64String(2 * i + 1, testSignedData[i]);
+      writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    for (var i = 0; i < testSignedData.length; i++) {
+      reader.nextField();
+      assertEquals(2 * i + 1, reader.getFieldNumber());
+      assertEquals(testSignedData[i], reader.readInt64String());
+      reader.nextField();
+      assertEquals(2 * i + 2, reader.getFieldNumber());
+      assertEquals(testUnsignedData[i], reader.readUint64String());
+    }
+  });
+
+
+  /**
+   * Tests fields that use zigzag encoding.
+   */
+  it('testZigzagFields', function() {
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSint32,
+        jspb.BinaryWriter.prototype.writeSint32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSint64,
+        jspb.BinaryWriter.prototype.writeSint64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests fields that use fixed-length encoding.
+   */
+  it('testFixedFields', function() {
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readFixed32,
+        jspb.BinaryWriter.prototype.writeFixed32,
+        1, Math.pow(2, 32) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readFixed64,
+        jspb.BinaryWriter.prototype.writeFixed64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSfixed32,
+        jspb.BinaryWriter.prototype.writeSfixed32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSfixed64,
+        jspb.BinaryWriter.prototype.writeSfixed64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests floating point fields.
+   */
+  it('testFloatFields', function() {
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readFloat,
+        jspb.BinaryWriter.prototype.writeFloat,
+        jspb.BinaryConstants.FLOAT32_MIN,
+        -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX,
+        truncate);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readDouble,
+        jspb.BinaryWriter.prototype.writeDouble,
+        jspb.BinaryConstants.FLOAT64_EPS * 10,
+        -jspb.BinaryConstants.FLOAT64_MIN,
+        jspb.BinaryConstants.FLOAT64_MIN,
+        function(x) { return x; });
+  });
+
+
+  /**
+   * Tests length-delimited string fields.
+   */
+  it('testStringFields', function() {
+    var s1 = 'The quick brown fox jumps over the lazy dog.';
+    var s2 = '人人生而自由,在尊嚴和權利上一律平等。';
+
+    var writer = new jspb.BinaryWriter();
+
+    writer.writeString(1, s1);
+    writer.writeString(2, s2);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(s1, reader.readString());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(s2, reader.readString());
+  });
+
+
+  /**
+   * Tests length-delimited byte fields.
+   */
+  it('testByteFields', function() {
+    var message = [];
+    var lowerLimit = 1;
+    var upperLimit = 256;
+    var scale = 1.1;
+
+    var writer = new jspb.BinaryWriter();
+
+    for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
+      var len = Math.round(cursor);
+      var bytes = [];
+      for (var i = 0; i < len; i++) bytes.push(i % 256);
+
+      writer.writeBytes(len, bytes);
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
+      var len = Math.round(cursor);
+      if (len != reader.getFieldNumber()) throw 'fail!';
+
+      var bytes = reader.readBytes();
+      if (len != bytes.length) throw 'fail!';
+      for (var i = 0; i < bytes.length; i++) {
+        if (i % 256 != bytes[i]) throw 'fail!';
+      }
+    }
+  });
+
+
+  /**
+   * Tests nested messages.
+   */
+  it('testNesting', function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    writer.writeInt32(1, 100);
+
+    // Add one message with 3 int fields.
+    writer.writeMessage(2, dummyMessage, function() {
+      writer.writeInt32(3, 300);
+      writer.writeInt32(4, 400);
+      writer.writeInt32(5, 500);
+    });
+
+    // Add one empty message.
+    writer.writeMessage(6, dummyMessage, goog.nullFunction);
+
+    writer.writeInt32(7, 700);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Validate outermost message.
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(100, reader.readInt32());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Validate embedded message 1.
+      reader.nextField();
+      assertEquals(3, reader.getFieldNumber());
+      assertEquals(300, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(4, reader.getFieldNumber());
+      assertEquals(400, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(5, reader.getFieldNumber());
+      assertEquals(500, reader.readInt32());
+
+      assertEquals(false, reader.nextField());
+    });
+
+    reader.nextField();
+    assertEquals(6, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Validate embedded message 2.
+
+      assertEquals(false, reader.nextField());
+    });
+
+    reader.nextField();
+    assertEquals(7, reader.getFieldNumber());
+    assertEquals(700, reader.readInt32());
+
+    assertEquals(false, reader.nextField());
+  });
+
+  /**
+   * Tests skipping fields of each type by interleaving them with sentinel
+   * values and skipping everything that's not a sentinel.
+   */
+  it('testSkipField', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var sentinel = 123456789;
+
+    // Write varint fields of different sizes.
+    writer.writeInt32(1, sentinel);
+    writer.writeInt32(1, 1);
+    writer.writeInt32(1, 1000);
+    writer.writeInt32(1, 1000000);
+    writer.writeInt32(1, 1000000000);
+
+    // Write fixed 64-bit encoded fields.
+    writer.writeInt32(2, sentinel);
+    writer.writeDouble(2, 1);
+    writer.writeFixed64(2, 1);
+    writer.writeSfixed64(2, 1);
+
+    // Write fixed 32-bit encoded fields.
+    writer.writeInt32(3, sentinel);
+    writer.writeFloat(3, 1);
+    writer.writeFixed32(3, 1);
+    writer.writeSfixed32(3, 1);
+
+    // Write delimited fields.
+    writer.writeInt32(4, sentinel);
+    writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    writer.writeString(4, 'The quick brown fox jumps over the lazy dog');
+
+    // Write a group with a nested group inside.
+    writer.writeInt32(5, sentinel);
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    writer.writeGroup(5, dummyMessage, function() {
+      writer.writeInt64(42, 42);
+      writer.writeGroup(6, dummyMessage, function() {
+        writer.writeInt64(84, 42);
+      });
+    });
+
+    // Write final sentinel.
+    writer.writeInt32(6, sentinel);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    function skip(field, count) {
+      for (var i = 0; i < count; i++) {
+        reader.nextField();
+        if (field != reader.getFieldNumber()) throw 'fail!';
+        reader.skipField();
+      }
+    }
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(1, 4);
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(2, 3);
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(3, 3);
+
+    reader.nextField();
+    assertEquals(4, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(4, 2);
+
+    reader.nextField();
+    assertEquals(5, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(5, 1);
+
+    reader.nextField();
+    assertEquals(6, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+  });
+
+
+  /**
+   * Tests packed fields.
+   */
+  it('testPackedFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var sentinel = 123456789;
+
+    var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
+    var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+    var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+    var boolData = [true, false, true, true, false, false, true, false];
+
+    for (var i = 0; i < floatData.length; i++) {
+      floatData[i] = truncate(floatData[i]);
+    }
+
+    writer.writeInt32(1, sentinel);
+
+    writer.writePackedInt32(2, signedData);
+    writer.writePackedInt64(2, signedData);
+    writer.writePackedUint32(2, unsignedData);
+    writer.writePackedUint64(2, unsignedData);
+    writer.writePackedSint32(2, signedData);
+    writer.writePackedSint64(2, signedData);
+    writer.writePackedFixed32(2, unsignedData);
+    writer.writePackedFixed64(2, unsignedData);
+    writer.writePackedSfixed32(2, signedData);
+    writer.writePackedSfixed64(2, signedData);
+    writer.writePackedFloat(2, floatData);
+    writer.writePackedDouble(2, doubleData);
+    writer.writePackedBool(2, boolData);
+    writer.writePackedEnum(2, unsignedData);
+
+    writer.writeInt32(3, sentinel);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    reader.nextField();
+    assertEquals(sentinel, reader.readInt32());
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedInt32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedInt64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedUint32(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedUint64(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSint32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSint64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFixed32(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFixed64(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSfixed32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSfixed64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFloat(), floatData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedDouble(), doubleData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedBool(), boolData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedEnum(), unsignedData);
+
+    reader.nextField();
+    assertEquals(sentinel, reader.readInt32());
+  });
+
+
+  /**
+   * Byte blobs inside nested messages should always have their byte offset set
+   * relative to the start of the outermost blob, not the start of their parent
+   * blob.
+   */
+  it('testNestedBlobs', function() {
+    // Create a proto consisting of two nested messages, with the inner one
+    // containing a blob of bytes.
+
+    var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
+    var blob = [1, 2, 3, 4, 5];
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    writer.writeMessage(1, dummyMessage, function() {
+      writer.writeMessage(1, dummyMessage, function() {
+        writer.writeBytes(1, blob);
+      });
+    });
+
+    // Peel off the outer two message layers. Each layer should have two bytes
+    // of overhead, one for the field tag and one for the length of the inner
+    // blob.
+
+    var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
+    assertEquals(fieldTag, decoder1.readUnsignedVarint32());
+    assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());
+
+    var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
+    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+    assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());
+
+    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+    assertEquals(blob.length, decoder2.readUnsignedVarint32());
+    var bytes = decoder2.readBytes(blob.length);
+
+    assertElementsEquals(bytes, blob);
+  });
+
+
+  /**
+   * Tests read callbacks.
+   */
+  it('testReadCallbacks', function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    // Add an int, a submessage, and another int.
+    writer.writeInt32(1, 100);
+
+    writer.writeMessage(2, dummyMessage, function() {
+      writer.writeInt32(3, 300);
+      writer.writeInt32(4, 400);
+      writer.writeInt32(5, 500);
+    });
+
+    writer.writeInt32(7, 700);
+
+    // Create the reader and register a custom read callback.
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    /**
+     * @param {!jspb.BinaryReader} reader
+     * @return {*}
+     */
+    function readCallback(reader) {
+      reader.nextField();
+      assertEquals(3, reader.getFieldNumber());
+      assertEquals(300, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(4, reader.getFieldNumber());
+      assertEquals(400, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(5, reader.getFieldNumber());
+      assertEquals(500, reader.readInt32());
+
+      assertEquals(false, reader.nextField());
+    };
+
+    reader.registerReadCallback('readCallback', readCallback);
+
+    // Read the container message.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(100, reader.readInt32());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Decode the embedded message using the registered callback.
+      reader.runReadCallback('readCallback');
+    });
+
+    reader.nextField();
+    assertEquals(7, reader.getFieldNumber());
+    assertEquals(700, reader.readInt32());
+
+    assertEquals(false, reader.nextField());
+  });
+});
diff --git a/src/third_party/protobuf-3/js/binary/utils.js b/src/third_party/protobuf-3/js/binary/utils.js
new file mode 100644
index 0000000..5140555
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/utils.js
@@ -0,0 +1,975 @@
+// 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.
+
+/**
+ * @fileoverview This file contains helper code used by jspb.BinaryReader
+ * and BinaryWriter.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.utils');
+
+goog.require('goog.asserts');
+goog.require('goog.crypt.base64');
+goog.require('goog.string');
+goog.require('jspb.BinaryConstants');
+
+
+/**
+ * Javascript can't natively handle 64-bit data types, so to manipulate them we
+ * have to split them into two 32-bit halves and do the math manually.
+ *
+ * Instead of instantiating and passing small structures around to do this, we
+ * instead just use two global temporary values. This one stores the low 32
+ * bits of a split value - for example, if the original value was a 64-bit
+ * integer, this temporary value will contain the low 32 bits of that integer.
+ * If the original value was a double, this temporary value will contain the
+ * low 32 bits of the binary representation of that double, etcetera.
+ * @type {number}
+ */
+jspb.utils.split64Low = 0;
+
+
+/**
+ * And correspondingly, this temporary variable will contain the high 32 bits
+ * of whatever value was split.
+ * @type {number}
+ */
+jspb.utils.split64High = 0;
+
+
+/**
+ * Splits an unsigned Javascript integer into two 32-bit halves and stores it
+ * in the temp values above.
+ * @param {number} value The number to split.
+ */
+jspb.utils.splitUint64 = function(value) {
+  // Extract low 32 bits and high 32 bits as unsigned integers.
+  var lowBits = value >>> 0;
+  var highBits = Math.floor((value - lowBits) /
+                            jspb.BinaryConstants.TWO_TO_32) >>> 0;
+
+  jspb.utils.split64Low = lowBits;
+  jspb.utils.split64High = highBits;
+};
+
+
+/**
+ * Splits a signed Javascript integer into two 32-bit halves and stores it in
+ * the temp values above.
+ * @param {number} value The number to split.
+ */
+jspb.utils.splitInt64 = function(value) {
+  // Convert to sign-magnitude representation.
+  var sign = (value < 0);
+  value = Math.abs(value);
+
+  // Extract low 32 bits and high 32 bits as unsigned integers.
+  var lowBits = value >>> 0;
+  var highBits = Math.floor((value - lowBits) /
+                            jspb.BinaryConstants.TWO_TO_32);
+  highBits = highBits >>> 0;
+
+  // Perform two's complement conversion if the sign bit was set.
+  if (sign) {
+    highBits = ~highBits >>> 0;
+    lowBits = ~lowBits >>> 0;
+    lowBits += 1;
+    if (lowBits > 0xFFFFFFFF) {
+      lowBits = 0;
+      highBits++;
+      if (highBits > 0xFFFFFFFF) highBits = 0;
+    }
+  }
+
+  jspb.utils.split64Low = lowBits;
+  jspb.utils.split64High = highBits;
+};
+
+
+/**
+ * Convers a signed Javascript integer into zigzag format, splits it into two
+ * 32-bit halves, and stores it in the temp values above.
+ * @param {number} value The number to split.
+ */
+jspb.utils.splitZigzag64 = function(value) {
+  // Convert to sign-magnitude and scale by 2 before we split the value.
+  var sign = (value < 0);
+  value = Math.abs(value) * 2;
+
+  jspb.utils.splitUint64(value);
+  var lowBits = jspb.utils.split64Low;
+  var highBits = jspb.utils.split64High;
+
+  // If the value is negative, subtract 1 from the split representation so we
+  // don't lose the sign bit due to precision issues.
+  if (sign) {
+    if (lowBits == 0) {
+      if (highBits == 0) {
+        lowBits = 0xFFFFFFFF;
+        highBits = 0xFFFFFFFF;
+      } else {
+        highBits--;
+        lowBits = 0xFFFFFFFF;
+      }
+    } else {
+      lowBits--;
+    }
+  }
+
+  jspb.utils.split64Low = lowBits;
+  jspb.utils.split64High = highBits;
+};
+
+
+/**
+ * Converts a floating-point number into 32-bit IEEE representation and stores
+ * it in the temp values above.
+ * @param {number} value
+ */
+jspb.utils.splitFloat32 = function(value) {
+  var sign = (value < 0) ? 1 : 0;
+  value = sign ? -value : value;
+  var exp;
+  var mant;
+
+  // Handle zeros.
+  if (value === 0) {
+    if ((1 / value) > 0) {
+      // Positive zero.
+      jspb.utils.split64High = 0;
+      jspb.utils.split64Low = 0x00000000;
+    } else {
+      // Negative zero.
+      jspb.utils.split64High = 0;
+      jspb.utils.split64Low = 0x80000000;
+    }
+    return;
+  }
+
+  // Handle nans.
+  if (isNaN(value)) {
+    jspb.utils.split64High = 0;
+    jspb.utils.split64Low = 0x7FFFFFFF;
+    return;
+  }
+
+  // Handle infinities.
+  if (value > jspb.BinaryConstants.FLOAT32_MAX) {
+    jspb.utils.split64High = 0;
+    jspb.utils.split64Low = ((sign << 31) | (0x7F800000)) >>> 0;
+    return;
+  }
+
+  // Handle denormals.
+  if (value < jspb.BinaryConstants.FLOAT32_MIN) {
+    // Number is a denormal.
+    mant = Math.round(value / Math.pow(2, -149));
+    jspb.utils.split64High = 0;
+    jspb.utils.split64Low = ((sign << 31) | mant) >>> 0;
+    return;
+  }
+
+  exp = Math.floor(Math.log(value) / Math.LN2);
+  mant = value * Math.pow(2, -exp);
+  mant = Math.round(mant * jspb.BinaryConstants.TWO_TO_23) & 0x7FFFFF;
+
+  jspb.utils.split64High = 0;
+  jspb.utils.split64Low = ((sign << 31) | ((exp + 127) << 23) | mant) >>> 0;
+};
+
+
+/**
+ * Converts a floating-point number into 64-bit IEEE representation and stores
+ * it in the temp values above.
+ * @param {number} value
+ */
+jspb.utils.splitFloat64 = function(value) {
+  var sign = (value < 0) ? 1 : 0;
+  value = sign ? -value : value;
+
+  // Handle zeros.
+  if (value === 0) {
+    if ((1 / value) > 0) {
+      // Positive zero.
+      jspb.utils.split64High = 0x00000000;
+      jspb.utils.split64Low = 0x00000000;
+    } else {
+      // Negative zero.
+      jspb.utils.split64High = 0x80000000;
+      jspb.utils.split64Low = 0x00000000;
+    }
+    return;
+  }
+
+  // Handle nans.
+  if (isNaN(value)) {
+    jspb.utils.split64High = 0x7FFFFFFF;
+    jspb.utils.split64Low = 0xFFFFFFFF;
+    return;
+  }
+
+  // Handle infinities.
+  if (value > jspb.BinaryConstants.FLOAT64_MAX) {
+    jspb.utils.split64High = ((sign << 31) | (0x7FF00000)) >>> 0;
+    jspb.utils.split64Low = 0;
+    return;
+  }
+
+  // Handle denormals.
+  if (value < jspb.BinaryConstants.FLOAT64_MIN) {
+    // Number is a denormal.
+    var mant = value / Math.pow(2, -1074);
+    var mantHigh = (mant / jspb.BinaryConstants.TWO_TO_32);
+    jspb.utils.split64High = ((sign << 31) | mantHigh) >>> 0;
+    jspb.utils.split64Low = (mant >>> 0);
+    return;
+  }
+
+  var exp = Math.floor(Math.log(value) / Math.LN2);
+  if (exp == 1024) exp = 1023;
+  var mant = value * Math.pow(2, -exp);
+
+  var mantHigh = (mant * jspb.BinaryConstants.TWO_TO_20) & 0xFFFFF;
+  var mantLow = (mant * jspb.BinaryConstants.TWO_TO_52) >>> 0;
+
+  jspb.utils.split64High =
+      ((sign << 31) | ((exp + 1023) << 20) | mantHigh) >>> 0;
+  jspb.utils.split64Low = mantLow;
+};
+
+
+/**
+ * Converts an 8-character hash string into two 32-bit numbers and stores them
+ * in the temp values above.
+ * @param {string} hash
+ */
+jspb.utils.splitHash64 = function(hash) {
+  var a = hash.charCodeAt(0);
+  var b = hash.charCodeAt(1);
+  var c = hash.charCodeAt(2);
+  var d = hash.charCodeAt(3);
+  var e = hash.charCodeAt(4);
+  var f = hash.charCodeAt(5);
+  var g = hash.charCodeAt(6);
+  var h = hash.charCodeAt(7);
+
+  jspb.utils.split64Low = (a + (b << 8) + (c << 16) + (d << 24)) >>> 0;
+  jspb.utils.split64High = (e + (f << 8) + (g << 16) + (h << 24)) >>> 0;
+};
+
+
+/**
+ * Joins two 32-bit values into a 64-bit unsigned integer. Precision will be
+ * lost if the result is greater than 2^52.
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @return {number}
+ */
+jspb.utils.joinUint64 = function(bitsLow, bitsHigh) {
+  return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + bitsLow;
+};
+
+
+/**
+ * Joins two 32-bit values into a 64-bit signed integer. Precision will be lost
+ * if the result is greater than 2^52.
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @return {number}
+ */
+jspb.utils.joinInt64 = function(bitsLow, bitsHigh) {
+  // If the high bit is set, do a manual two's complement conversion.
+  var sign = (bitsHigh & 0x80000000);
+  if (sign) {
+    bitsLow = (~bitsLow + 1) >>> 0;
+    bitsHigh = ~bitsHigh >>> 0;
+    if (bitsLow == 0) {
+      bitsHigh = (bitsHigh + 1) >>> 0;
+    }
+  }
+
+  var result = jspb.utils.joinUint64(bitsLow, bitsHigh);
+  return sign ? -result : result;
+};
+
+
+/**
+ * Joins two 32-bit values into a 64-bit unsigned integer and applies zigzag
+ * decoding. Precision will be lost if the result is greater than 2^52.
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @return {number}
+ */
+jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) {
+  // Extract the sign bit and shift right by one.
+  var sign = bitsLow & 1;
+  bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) >>> 0;
+  bitsHigh = bitsHigh >>> 1;
+
+  // Increment the split value if the sign bit was set.
+  if (sign) {
+    bitsLow = (bitsLow + 1) >>> 0;
+    if (bitsLow == 0) {
+      bitsHigh = (bitsHigh + 1) >>> 0;
+    }
+  }
+
+  var result = jspb.utils.joinUint64(bitsLow, bitsHigh);
+  return sign ? -result : result;
+};
+
+
+/**
+ * Joins two 32-bit values into a 32-bit IEEE floating point number and
+ * converts it back into a Javascript number.
+ * @param {number} bitsLow The low 32 bits of the binary number;
+ * @param {number} bitsHigh The high 32 bits of the binary number.
+ * @return {number}
+ */
+jspb.utils.joinFloat32 = function(bitsLow, bitsHigh) {
+  var sign = ((bitsLow >> 31) * 2 + 1);
+  var exp = (bitsLow >>> 23) & 0xFF;
+  var mant = bitsLow & 0x7FFFFF;
+
+  if (exp == 0xFF) {
+    if (mant) {
+      return NaN;
+    } else {
+      return sign * Infinity;
+    }
+  }
+
+  if (exp == 0) {
+    // Denormal.
+    return sign * Math.pow(2, -149) * mant;
+  } else {
+    return sign * Math.pow(2, exp - 150) *
+           (mant + Math.pow(2, 23));
+  }
+};
+
+
+/**
+ * Joins two 32-bit values into a 64-bit IEEE floating point number and
+ * converts it back into a Javascript number.
+ * @param {number} bitsLow The low 32 bits of the binary number;
+ * @param {number} bitsHigh The high 32 bits of the binary number.
+ * @return {number}
+ */
+jspb.utils.joinFloat64 = function(bitsLow, bitsHigh) {
+  var sign = ((bitsHigh >> 31) * 2 + 1);
+  var exp = (bitsHigh >>> 20) & 0x7FF;
+  var mant = jspb.BinaryConstants.TWO_TO_32 * (bitsHigh & 0xFFFFF) + bitsLow;
+
+  if (exp == 0x7FF) {
+    if (mant) {
+      return NaN;
+    } else {
+      return sign * Infinity;
+    }
+  }
+
+  if (exp == 0) {
+    // Denormal.
+    return sign * Math.pow(2, -1074) * mant;
+  } else {
+    return sign * Math.pow(2, exp - 1075) *
+           (mant + jspb.BinaryConstants.TWO_TO_52);
+  }
+};
+
+
+/**
+ * Joins two 32-bit values into an 8-character hash string.
+ * @param {number} bitsLow
+ * @param {number} bitsHigh
+ * @return {string}
+ */
+jspb.utils.joinHash64 = function(bitsLow, bitsHigh) {
+  var a = (bitsLow >>> 0) & 0xFF;
+  var b = (bitsLow >>> 8) & 0xFF;
+  var c = (bitsLow >>> 16) & 0xFF;
+  var d = (bitsLow >>> 24) & 0xFF;
+  var e = (bitsHigh >>> 0) & 0xFF;
+  var f = (bitsHigh >>> 8) & 0xFF;
+  var g = (bitsHigh >>> 16) & 0xFF;
+  var h = (bitsHigh >>> 24) & 0xFF;
+
+  return String.fromCharCode(a, b, c, d, e, f, g, h);
+};
+
+
+/**
+ * Individual digits for number->string conversion.
+ * @const {!Array.<number>}
+ */
+jspb.utils.DIGITS = [
+  '0', '1', '2', '3', '4', '5', '6', '7',
+  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+];
+
+
+/**
+ * Losslessly converts a 64-bit unsigned integer in 32:32 split representation
+ * into a decimal string.
+ * @param {number} bitsLow The low 32 bits of the binary number;
+ * @param {number} bitsHigh The high 32 bits of the binary number.
+ * @return {string} The binary number represented as a string.
+ */
+jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) {
+  // Skip the expensive conversion if the number is small enough to use the
+  // built-in conversions.
+  if (bitsHigh <= 0x1FFFFF) {
+    return '' + (jspb.BinaryConstants.TWO_TO_32 * bitsHigh + bitsLow);
+  }
+
+  // What this code is doing is essentially converting the input number from
+  // base-2 to base-1e7, which allows us to represent the 64-bit range with
+  // only 3 (very large) digits. Those digits are then trivial to convert to
+  // a base-10 string.
+
+  // The magic numbers used here are -
+  // 2^24 = 16777216 = (1,6777216) in base-1e7.
+  // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7.
+
+  // Split 32:32 representation into 16:24:24 representation so our
+  // intermediate digits don't overflow.
+  var low = bitsLow & 0xFFFFFF;
+  var mid = (((bitsLow >>> 24) | (bitsHigh << 8)) >>> 0) & 0xFFFFFF;
+  var high = (bitsHigh >> 16) & 0xFFFF;
+
+  // Assemble our three base-1e7 digits, ignoring carries. The maximum
+  // value in a digit at this step is representable as a 48-bit integer, which
+  // can be stored in a 64-bit floating point number.
+  var digitA = low + (mid * 6777216) + (high * 6710656);
+  var digitB = mid + (high * 8147497);
+  var digitC = (high * 2);
+
+  // Apply carries from A to B and from B to C.
+  var base = 10000000;
+  if (digitA >= base) {
+    digitB += Math.floor(digitA / base);
+    digitA %= base;
+  }
+
+  if (digitB >= base) {
+    digitC += Math.floor(digitB / base);
+    digitB %= base;
+  }
+
+  // Convert base-1e7 digits to base-10, omitting leading zeroes.
+  var table = jspb.utils.DIGITS;
+  var start = false;
+  var result = '';
+
+  function emit(digit) {
+    var temp = base;
+    for (var i = 0; i < 7; i++) {
+      temp /= 10;
+      var decimalDigit = ((digit / temp) % 10) >>> 0;
+      if ((decimalDigit == 0) && !start) continue;
+      start = true;
+      result += table[decimalDigit];
+    }
+  }
+
+  if (digitC || start) emit(digitC);
+  if (digitB || start) emit(digitB);
+  if (digitA || start) emit(digitA);
+
+  return result;
+};
+
+
+/**
+ * Losslessly converts a 64-bit signed integer in 32:32 split representation
+ * into a decimal string.
+ * @param {number} bitsLow The low 32 bits of the binary number;
+ * @param {number} bitsHigh The high 32 bits of the binary number.
+ * @return {string} The binary number represented as a string.
+ */
+jspb.utils.joinSignedDecimalString = function(bitsLow, bitsHigh) {
+  // If we're treating the input as a signed value and the high bit is set, do
+  // a manual two's complement conversion before the decimal conversion.
+  var negative = (bitsHigh & 0x80000000);
+  if (negative) {
+    bitsLow = (~bitsLow + 1) >>> 0;
+    var carry = (bitsLow == 0) ? 1 : 0;
+    bitsHigh = (~bitsHigh + carry) >>> 0;
+  }
+
+  var result = jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh);
+  return negative ? '-' + result : result;
+};
+
+
+/**
+ * Convert an 8-character hash string representing either a signed or unsigned
+ * 64-bit integer into its decimal representation without losing accuracy.
+ * @param {string} hash The hash string to convert.
+ * @param {boolean} signed True if we should treat the hash string as encoding
+ *     a signed integer.
+ * @return {string}
+ */
+jspb.utils.hash64ToDecimalString = function(hash, signed) {
+  jspb.utils.splitHash64(hash);
+  var bitsLow = jspb.utils.split64Low;
+  var bitsHigh = jspb.utils.split64High;
+  return signed ?
+      jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh) :
+      jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Converts an array of 8-character hash strings into their decimal
+ * representations.
+ * @param {!Array.<string>} hashes The array of hash strings to convert.
+ * @param {boolean} signed True if we should treat the hash string as encoding
+ *     a signed integer.
+ * @return {!Array.<string>}
+ */
+jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) {
+  var result = new Array(hashes.length);
+  for (var i = 0; i < hashes.length; i++) {
+    result[i] = jspb.utils.hash64ToDecimalString(hashes[i], signed);
+  }
+  return result;
+};
+
+
+/**
+ * Converts a signed or unsigned decimal string into its hash string
+ * representation.
+ * @param {string} dec
+ * @return {string}
+ */
+jspb.utils.decimalStringToHash64 = function(dec) {
+  goog.asserts.assert(dec.length > 0);
+
+  // Check for minus sign.
+  var minus = false;
+  if (dec[0] === '-') {
+    minus = true;
+    dec = dec.slice(1);
+  }
+
+  // Store result as a byte array.
+  var resultBytes = [0, 0, 0, 0, 0, 0, 0, 0];
+
+  // Set result to m*result + c.
+  function muladd(m, c) {
+    for (var i = 0; i < 8 && (m !== 1 || c > 0); i++) {
+      var r = m * resultBytes[i] + c;
+      resultBytes[i] = r & 0xFF;
+      c = r >>> 8;
+    }
+  }
+
+  // Negate the result bits.
+  function neg() {
+    for (var i = 0; i < 8; i++) {
+      resultBytes[i] = (~resultBytes[i]) & 0xFF;
+    }
+  }
+
+  // For each decimal digit, set result to 10*result + digit.
+  for (var i = 0; i < dec.length; i++) {
+    muladd(10, jspb.utils.DIGITS.indexOf(dec[i]));
+  }
+
+  // If there's a minus sign, convert into two's complement.
+  if (minus) {
+    neg();
+    muladd(1, 1);
+  }
+
+  return String.fromCharCode.apply(null, resultBytes);
+};
+
+
+/**
+ * Converts an 8-character hash string into its hexadecimal representation.
+ * @param {string} hash
+ * @return {string}
+ */
+jspb.utils.hash64ToHexString = function(hash) {
+  var temp = new Array(18);
+  temp[0] = '0';
+  temp[1] = 'x';
+
+  for (var i = 0; i < 8; i++) {
+    var c = hash.charCodeAt(7 - i);
+    temp[i * 2 + 2] = jspb.utils.DIGITS[c >> 4];
+    temp[i * 2 + 3] = jspb.utils.DIGITS[c & 0xF];
+  }
+
+  var result = temp.join('');
+  return result;
+};
+
+
+/**
+ * Converts a '0x<16 digits>' hex string into its hash string representation.
+ * @param {string} hex
+ * @return {string}
+ */
+jspb.utils.hexStringToHash64 = function(hex) {
+  hex = hex.toLowerCase();
+  goog.asserts.assert(hex.length == 18);
+  goog.asserts.assert(hex[0] == '0');
+  goog.asserts.assert(hex[1] == 'x');
+
+  var result = '';
+  for (var i = 0; i < 8; i++) {
+    var hi = jspb.utils.DIGITS.indexOf(hex[i * 2 + 2]);
+    var lo = jspb.utils.DIGITS.indexOf(hex[i * 2 + 3]);
+    result = String.fromCharCode(hi * 16 + lo) + result;
+  }
+
+  return result;
+};
+
+
+/**
+ * Convert an 8-character hash string representing either a signed or unsigned
+ * 64-bit integer into a Javascript number. Will lose accuracy if the result is
+ * larger than 2^52.
+ * @param {string} hash The hash string to convert.
+ * @param {boolean} signed True if the has should be interpreted as a signed
+ *     number.
+ * @return {number}
+ */
+jspb.utils.hash64ToNumber = function(hash, signed) {
+  jspb.utils.splitHash64(hash);
+  var bitsLow = jspb.utils.split64Low;
+  var bitsHigh = jspb.utils.split64High;
+  return signed ? jspb.utils.joinInt64(bitsLow, bitsHigh) :
+                  jspb.utils.joinUint64(bitsLow, bitsHigh);
+};
+
+
+/**
+ * Convert a Javascript number into an 8-character hash string. Will lose
+ * precision if the value is non-integral or greater than 2^64.
+ * @param {number} value The integer to convert.
+ * @return {string}
+ */
+jspb.utils.numberToHash64 = function(value) {
+  jspb.utils.splitInt64(value);
+  return jspb.utils.joinHash64(jspb.utils.split64Low,
+                                  jspb.utils.split64High);
+};
+
+
+/**
+ * Counts the number of contiguous varints in a buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @return {number} The number of varints in the buffer.
+ */
+jspb.utils.countVarints = function(buffer, start, end) {
+  // Count how many high bits of each byte were set in the buffer.
+  var count = 0;
+  for (var i = start; i < end; i++) {
+    count += buffer[i] >> 7;
+  }
+
+  // The number of varints in the buffer equals the size of the buffer minus
+  // the number of non-terminal bytes in the buffer (those with the high bit
+  // set).
+  return (end - start) - count;
+};
+
+
+/**
+ * Counts the number of contiguous varint fields with the given field number in
+ * the buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @param {number} field The field number to count.
+ * @return {number} The number of matching fields in the buffer.
+ */
+jspb.utils.countVarintFields = function(buffer, start, end, field) {
+  var count = 0;
+  var cursor = start;
+  var tag = field * 8 + jspb.BinaryConstants.WireType.VARINT;
+
+  if (tag < 128) {
+    // Single-byte field tag, we can use a slightly quicker count.
+    while (cursor < end) {
+      // Skip the field tag, or exit if we find a non-matching tag.
+      if (buffer[cursor++] != tag) return count;
+
+      // Field tag matches, we've found a valid field.
+      count++;
+
+      // Skip the varint.
+      while (1) {
+        var x = buffer[cursor++];
+        if ((x & 0x80) == 0) break;
+      }
+    }
+  } else {
+    while (cursor < end) {
+      // Skip the field tag, or exit if we find a non-matching tag.
+      var temp = tag;
+      while (temp > 128) {
+        if (buffer[cursor] != ((temp & 0x7F) | 0x80)) return count;
+        cursor++;
+        temp >>= 7;
+      }
+      if (buffer[cursor++] != temp) return count;
+
+      // Field tag matches, we've found a valid field.
+      count++;
+
+      // Skip the varint.
+      while (1) {
+        var x = buffer[cursor++];
+        if ((x & 0x80) == 0) break;
+      }
+    }
+  }
+  return count;
+};
+
+
+/**
+ * Counts the number of contiguous fixed32 fields with the given tag in the
+ * buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @param {number} tag The tag value to count.
+ * @param {number} stride The number of bytes to skip per field.
+ * @return {number} The number of fields with a matching tag in the buffer.
+ * @private
+ */
+jspb.utils.countFixedFields_ =
+    function(buffer, start, end, tag, stride) {
+  var count = 0;
+  var cursor = start;
+
+  if (tag < 128) {
+    // Single-byte field tag, we can use a slightly quicker count.
+    while (cursor < end) {
+      // Skip the field tag, or exit if we find a non-matching tag.
+      if (buffer[cursor++] != tag) return count;
+
+      // Field tag matches, we've found a valid field.
+      count++;
+
+      // Skip the value.
+      cursor += stride;
+    }
+  } else {
+    while (cursor < end) {
+      // Skip the field tag, or exit if we find a non-matching tag.
+      var temp = tag;
+      while (temp > 128) {
+        if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count;
+        temp >>= 7;
+      }
+      if (buffer[cursor++] != temp) return count;
+
+      // Field tag matches, we've found a valid field.
+      count++;
+
+      // Skip the value.
+      cursor += stride;
+    }
+  }
+  return count;
+};
+
+
+/**
+ * Counts the number of contiguous fixed32 fields with the given field number
+ * in the buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @param {number} field The field number to count.
+ * @return {number} The number of matching fields in the buffer.
+ */
+jspb.utils.countFixed32Fields = function(buffer, start, end, field) {
+  var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED32;
+  return jspb.utils.countFixedFields_(buffer, start, end, tag, 4);
+};
+
+
+/**
+ * Counts the number of contiguous fixed64 fields with the given field number
+ * in the buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @param {number} field The field number to count
+ * @return {number} The number of matching fields in the buffer.
+ */
+jspb.utils.countFixed64Fields = function(buffer, start, end, field) {
+  var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED64;
+  return jspb.utils.countFixedFields_(buffer, start, end, tag, 8);
+};
+
+
+/**
+ * Counts the number of contiguous delimited fields with the given field number
+ * in the buffer.
+ * @param {!Uint8Array} buffer The buffer to scan.
+ * @param {number} start The starting point in the buffer to scan.
+ * @param {number} end The end point in the buffer to scan.
+ * @param {number} field The field number to count.
+ * @return {number} The number of matching fields in the buffer.
+ */
+jspb.utils.countDelimitedFields = function(buffer, start, end, field) {
+  var count = 0;
+  var cursor = start;
+  var tag = field * 8 + jspb.BinaryConstants.WireType.DELIMITED;
+
+  while (cursor < end) {
+    // Skip the field tag, or exit if we find a non-matching tag.
+    var temp = tag;
+    while (temp > 128) {
+      if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count;
+      temp >>= 7;
+    }
+    if (buffer[cursor++] != temp) return count;
+
+    // Field tag matches, we've found a valid field.
+    count++;
+
+    // Decode the length prefix.
+    var length = 0;
+    var shift = 1;
+    while (1) {
+      temp = buffer[cursor++];
+      length += (temp & 0x7f) * shift;
+      shift *= 128;
+      if ((temp & 0x80) == 0) break;
+    }
+
+    // Advance the cursor past the blob.
+    cursor += length;
+  }
+  return count;
+};
+
+
+/**
+ * String-ify bytes for text format. Should be optimized away in non-debug.
+ * The returned string uses \xXX escapes for all values and is itself quoted.
+ * [1, 31] serializes to '"\x01\x1f"'.
+ * @param {jspb.ByteSource} byteSource The bytes to serialize.
+ * @return {string} Stringified bytes for text format.
+ */
+jspb.utils.debugBytesToTextFormat = function(byteSource) {
+  var s = '"';
+  if (byteSource) {
+    var bytes = jspb.utils.byteSourceToUint8Array(byteSource);
+    for (var i = 0; i < bytes.length; i++) {
+      s += '\\x';
+      if (bytes[i] < 16) s += '0';
+      s += bytes[i].toString(16);
+    }
+  }
+  return s + '"';
+};
+
+
+/**
+ * String-ify a scalar for text format. Should be optimized away in non-debug.
+ * @param {string|number|boolean} scalar The scalar to stringify.
+ * @return {string} Stringified scalar for text format.
+ */
+jspb.utils.debugScalarToTextFormat = function(scalar) {
+  if (goog.isString(scalar)) {
+    return goog.string.quote(scalar);
+  } else {
+    return scalar.toString();
+  }
+};
+
+
+/**
+ * Utility function: convert a string with codepoints 0--255 inclusive to a
+ * Uint8Array. If any codepoints greater than 255 exist in the string, throws an
+ * exception.
+ * @param {string} str
+ * @return {!Uint8Array}
+ */
+jspb.utils.stringToByteArray = function(str) {
+  var arr = new Uint8Array(str.length);
+  for (var i = 0; i < str.length; i++) {
+    var codepoint = str.charCodeAt(i);
+    if (codepoint > 255) {
+      throw new Error('Conversion error: string contains codepoint ' +
+                      'outside of byte range');
+    }
+    arr[i] = codepoint;
+  }
+  return arr;
+};
+
+
+/**
+ * Converts any type defined in jspb.ByteSource into a Uint8Array.
+ * @param {!jspb.ByteSource} data
+ * @return {!Uint8Array}
+ * @suppress {invalidCasts}
+ */
+jspb.utils.byteSourceToUint8Array = function(data) {
+  if (data.constructor === Uint8Array) {
+    return /** @type {!Uint8Array} */(data);
+  }
+
+  if (data.constructor === ArrayBuffer) {
+    data = /** @type {!ArrayBuffer} */(data);
+    return /** @type {!Uint8Array} */(new Uint8Array(data));
+  }
+
+  if (data.constructor === Array) {
+    data = /** @type {!Array.<number>} */(data);
+    return /** @type {!Uint8Array} */(new Uint8Array(data));
+  }
+
+  if (data.constructor === String) {
+    data = /** @type {string} */(data);
+    return goog.crypt.base64.decodeStringToUint8Array(data);
+  }
+
+  goog.asserts.fail('Type not convertible to Uint8Array.');
+  return /** @type {!Uint8Array} */(new Uint8Array(0));
+};
diff --git a/src/third_party/protobuf-3/js/binary/utils_test.js b/src/third_party/protobuf-3/js/binary/utils_test.js
new file mode 100644
index 0000000..d27e5ea
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/utils_test.js
@@ -0,0 +1,668 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's helper functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryWriter');
+goog.require('jspb.utils');
+
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+function truncate(x) {
+  var temp = new Float32Array(1);
+  temp[0] = x;
+  return temp[0];
+}
+
+
+/**
+ * Converts an 64-bit integer in split representation to a 64-bit hash string
+ * (8 bits encoded per character).
+ * @param {number} bitsLow The low 32 bits of the split 64-bit integer.
+ * @param {number} bitsHigh The high 32 bits of the split 64-bit integer.
+ * @return {string} The encoded hash string, 8 bits per character.
+ */
+function toHashString(bitsLow, bitsHigh) {
+  return String.fromCharCode((bitsLow >>> 0) & 0xFF,
+                             (bitsLow >>> 8) & 0xFF,
+                             (bitsLow >>> 16) & 0xFF,
+                             (bitsLow >>> 24) & 0xFF,
+                             (bitsHigh >>> 0) & 0xFF,
+                             (bitsHigh >>> 8) & 0xFF,
+                             (bitsHigh >>> 16) & 0xFF,
+                             (bitsHigh >>> 24) & 0xFF);
+}
+
+
+describe('binaryUtilsTest', function() {
+  /**
+   * Tests lossless binary-to-decimal conversion.
+   */
+  it('testDecimalConversion', function() {
+    // Check some magic numbers.
+    var result =
+        jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304);
+    assertEquals('10000000000000000001', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b);
+    assertEquals('123456789123456789', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c);
+    assertEquals('12345678901234567890', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8);
+    assertEquals('9876543210987654321', result);
+
+    // Check limits.
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000);
+    assertEquals('0', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF);
+    assertEquals('18446744073709551615', result);
+
+    // Check each bit of the low dword.
+    for (var i = 0; i < 32; i++) {
+      var low = (1 << i) >>> 0;
+      result = jspb.utils.joinUnsignedDecimalString(low, 0);
+      assertEquals('' + Math.pow(2, i), result);
+    }
+
+    // Check the first 20 bits of the high dword.
+    for (var i = 0; i < 20; i++) {
+      var high = (1 << i) >>> 0;
+      result = jspb.utils.joinUnsignedDecimalString(0, high);
+      assertEquals('' + Math.pow(2, 32 + i), result);
+    }
+
+    // V8's internal double-to-string conversion is inaccurate for values above
+    // 2^52, even if they're representable integers - check the rest of the bits
+    // manually against the correct string representations of 2^N.
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000);
+    assertEquals('4503599627370496', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000);
+    assertEquals('9007199254740992', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000);
+    assertEquals('18014398509481984', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000);
+    assertEquals('36028797018963968', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000);
+    assertEquals('72057594037927936', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000);
+    assertEquals('144115188075855872', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000);
+    assertEquals('288230376151711744', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000);
+    assertEquals('576460752303423488', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000);
+    assertEquals('1152921504606846976', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000);
+    assertEquals('2305843009213693952', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000);
+    assertEquals('4611686018427387904', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000);
+    assertEquals('9223372036854775808', result);
+  });
+
+
+  /**
+   * Going from hash strings to decimal strings should also be lossless.
+   */
+  it('testHashToDecimalConversion', function() {
+    var result;
+    var convert = jspb.utils.hash64ToDecimalString;
+
+    result = convert(toHashString(0x00000000, 0x00000000), false);
+    assertEquals('0', result);
+
+    result = convert(toHashString(0x00000000, 0x00000000), true);
+    assertEquals('0', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false);
+    assertEquals('18446744073709551615', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true);
+    assertEquals('-1', result);
+
+    result = convert(toHashString(0x00000000, 0x80000000), false);
+    assertEquals('9223372036854775808', result);
+
+    result = convert(toHashString(0x00000000, 0x80000000), true);
+    assertEquals('-9223372036854775808', result);
+
+    result = convert(toHashString(0xacd05f15, 0x01b69b4b), false);
+    assertEquals('123456789123456789', result);
+
+    result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true);
+    assertEquals('-123456789123456789', result);
+
+    // And converting arrays of hashes should work the same way.
+    result = jspb.utils.hash64ArrayToDecimalStrings([
+      toHashString(0xFFFFFFFF, 0xFFFFFFFF),
+      toHashString(0x00000000, 0x80000000),
+      toHashString(0xacd05f15, 0x01b69b4b)], false);
+    assertEquals(3, result.length);
+    assertEquals('18446744073709551615', result[0]);
+    assertEquals('9223372036854775808', result[1]);
+    assertEquals('123456789123456789', result[2]);
+  });
+
+  /*
+   * Going from decimal strings to hash strings should be lossless.
+   */
+  it('testDecimalToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.decimalStringToHash64;
+
+    result = convert('0');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+    result = convert('-1');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('18446744073709551615');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('-9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
+
+    result = convert('-123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
+  });
+
+  /**
+   * Going from hash strings to hex strings should be lossless.
+   */
+  it('testHashToHexConversion', function() {
+    var result;
+    var convert = jspb.utils.hash64ToHexString;
+
+    result = convert(toHashString(0x00000000, 0x00000000));
+    assertEquals('0x0000000000000000', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF));
+    assertEquals('0xffffffffffffffff', result);
+
+    result = convert(toHashString(0x12345678, 0x9ABCDEF0));
+    assertEquals('0x9abcdef012345678', result);
+  });
+
+
+  /**
+   * Going from hex strings to hash strings should be lossless.
+   */
+  it('testHexToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.hexStringToHash64;
+
+    result = convert('0x0000000000000000');
+    assertEquals(String.fromCharCode.apply(null,
+        [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+    result = convert('0xffffffffffffffff');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    // Hex string is big-endian, hash string is little-endian.
+    result = convert('0x123456789ABCDEF0');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result);
+
+    // Capitalization should not matter.
+    result = convert('0x0000abcdefABCDEF');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result);
+  });
+
+
+  /**
+   * Going from numbers to hash strings should be lossless for up to 53 bits of
+   * precision.
+   */
+  it('testNumberToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.numberToHash64;
+
+    result = convert(0x0000000000000);
+    assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0xFFFFFFFFFFFFF);
+    assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0x123456789ABCD);
+    assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0xDCBA987654321);
+    assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result));
+
+    // 53 bits of precision should not be truncated.
+    result = convert(0x10000000000001);
+    assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result));
+
+    // 54 bits of precision should be truncated.
+    result = convert(0x20000000000001);
+    assertNotEquals(
+        '0x0020000000000001', jspb.utils.hash64ToHexString(result));
+  });
+
+
+  /**
+   * Sanity check the behavior of Javascript's strings when doing funny things
+   * with unicode characters.
+   */
+  it('sanityCheckUnicodeStrings', function() {
+    var strings = new Array(65536);
+
+    // All possible unsigned 16-bit values should be storable in a string, they
+    // shouldn't do weird things with the length of the string, and they should
+    // come back out of the string unchanged.
+    for (var i = 0; i < 65536; i++) {
+      strings[i] = 'a' + String.fromCharCode(i) + 'a';
+      if (3 != strings[i].length) throw 'fail!';
+      if (i != strings[i].charCodeAt(1)) throw 'fail!';
+    }
+
+    // Each unicode character should compare equal to itself and not equal to a
+    // different unicode character.
+    for (var i = 0; i < 65536; i++) {
+      if (strings[i] != strings[i]) throw 'fail!';
+      if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!';
+    }
+  });
+
+
+  /**
+   * Tests conversion from 32-bit floating point numbers to split64 numbers.
+   */
+  it('testFloat32ToSplit64', function() {
+    var f32_eps = jspb.BinaryConstants.FLOAT32_EPS;
+    var f32_min = jspb.BinaryConstants.FLOAT32_MIN;
+    var f32_max = jspb.BinaryConstants.FLOAT32_MAX;
+
+    // NaN.
+    jspb.utils.splitFloat32(NaN);
+    if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low,
+                                      jspb.utils.split64High))) {
+      throw 'fail!';
+    }
+
+    /**
+     * @param {number} x
+     * @param {number=} opt_bits
+     */
+    function test(x, opt_bits) {
+      jspb.utils.splitFloat32(x);
+      if (goog.isDef(opt_bits)) {
+        if (opt_bits != jspb.utils.split64Low) throw 'fail!';
+      }
+      if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
+          jspb.utils.split64High)) {
+        throw 'fail!';
+      }
+    }
+
+    // Positive and negative infinity.
+    test(Infinity, 0x7f800000);
+    test(-Infinity, 0xff800000);
+
+    // Positive and negative zero.
+    test(0, 0x00000000);
+    test(-0, 0x80000000);
+
+    // Positive and negative epsilon.
+    test(f32_eps, 0x00000001);
+    test(-f32_eps, 0x80000001);
+
+    // Positive and negative min.
+    test(f32_min, 0x00800000);
+    test(-f32_min, 0x80800000);
+
+    // Positive and negative max.
+    test(f32_max, 0x7F7FFFFF);
+    test(-f32_max, 0xFF7FFFFF);
+
+    // Various positive values.
+    var cursor = f32_eps * 10;
+    while (cursor != Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+
+    // Various negative values.
+    cursor = -f32_eps * 10;
+    while (cursor != -Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+  });
+
+
+  /**
+   * Tests conversion from 64-bit floating point numbers to split64 numbers.
+   */
+  it('testFloat64ToSplit64', function() {
+    var f64_eps = jspb.BinaryConstants.FLOAT64_EPS;
+    var f64_min = jspb.BinaryConstants.FLOAT64_MIN;
+    var f64_max = jspb.BinaryConstants.FLOAT64_MAX;
+
+    // NaN.
+    jspb.utils.splitFloat64(NaN);
+    if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low,
+        jspb.utils.split64High))) {
+      throw 'fail!';
+    }
+
+    /**
+     * @param {number} x
+     * @param {number=} opt_highBits
+     * @param {number=} opt_lowBits
+     */
+    function test(x, opt_highBits, opt_lowBits) {
+      jspb.utils.splitFloat64(x);
+      if (goog.isDef(opt_highBits)) {
+        if (opt_highBits != jspb.utils.split64High) throw 'fail!';
+      }
+      if (goog.isDef(opt_lowBits)) {
+        if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
+      }
+      if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,
+          jspb.utils.split64High)) {
+        throw 'fail!';
+      }
+    }
+
+    // Positive and negative infinity.
+    test(Infinity, 0x7ff00000, 0x00000000);
+    test(-Infinity, 0xfff00000, 0x00000000);
+
+    // Positive and negative zero.
+    test(0, 0x00000000, 0x00000000);
+    test(-0, 0x80000000, 0x00000000);
+
+    // Positive and negative epsilon.
+    test(f64_eps, 0x00000000, 0x00000001);
+    test(-f64_eps, 0x80000000, 0x00000001);
+
+    // Positive and negative min.
+    test(f64_min, 0x00100000, 0x00000000);
+    test(-f64_min, 0x80100000, 0x00000000);
+
+    // Positive and negative max.
+    test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF);
+    test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF);
+
+    // Various positive values.
+    var cursor = f64_eps * 10;
+    while (cursor != Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+
+    // Various negative values.
+    cursor = -f64_eps * 10;
+    while (cursor != -Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+  });
+
+
+  /**
+   * Tests counting packed varints.
+   */
+  it('testCountVarints', function() {
+    var values = [];
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      values.push(Math.floor(i));
+    }
+
+    var writer = new jspb.BinaryWriter();
+    writer.writePackedUint64(1, values);
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+
+    // We should have two more varints than we started with - one for the field
+    // tag, one for the packed length.
+    assertEquals(values.length + 2,
+                 jspb.utils.countVarints(buffer, 0, buffer.length));
+  });
+
+
+  /**
+   * Tests counting matching varint fields.
+   */
+  it('testCountVarintFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeUint64(1, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countVarintFields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeUint64(123456789, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching fixed32 fields.
+   */
+  it('testCountFixed32Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeFixed32(1, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeFixed32(123456789, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching fixed64 fields.
+   */
+  it('testCountFixed64Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeDouble(1, i);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeDouble(123456789, i);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching delimited fields.
+   */
+  it('testCountDelimitedFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000; i *= 1.1) {
+      writer.writeBytes(1, [Math.floor(i)]);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000; i *= 1.1) {
+      writer.writeBytes(123456789, [Math.floor(i)]);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests byte format for debug strings.
+   */
+  it('testDebugBytesToTextFormat', function() {
+    assertEquals('""', jspb.utils.debugBytesToTextFormat(null));
+    assertEquals('"\\x00\\x10\\xff"',
+        jspb.utils.debugBytesToTextFormat([0, 16, 255]));
+  });
+
+
+  /**
+   * Tests converting byte blob sources into byte blobs.
+   */
+  it('testByteSourceToUint8Array', function() {
+    var convert = jspb.utils.byteSourceToUint8Array;
+
+    var sourceData = [];
+    for (var i = 0; i < 256; i++) {
+      sourceData.push(i);
+    }
+
+    var sourceBytes = new Uint8Array(sourceData);
+    var sourceBuffer = sourceBytes.buffer;
+    var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData);
+    var sourceString = String.fromCharCode.apply(null, sourceData);
+
+    function check(result) {
+      assertEquals(Uint8Array, result.constructor);
+      assertEquals(sourceData.length, result.length);
+      for (var i = 0; i < result.length; i++) {
+        assertEquals(sourceData[i], result[i]);
+      }
+    }
+
+    // Converting Uint8Arrays into Uint8Arrays should be a no-op.
+    assertEquals(sourceBytes, convert(sourceBytes));
+
+    // Converting Array.<numbers> into Uint8Arrays should work.
+    check(convert(sourceData));
+
+    // Converting ArrayBuffers into Uint8Arrays should work.
+    check(convert(sourceBuffer));
+
+    // Converting base64-encoded strings into Uint8Arrays should work.
+    check(convert(sourceBase64));
+  });
+});
diff --git a/src/third_party/protobuf-3/js/binary/writer.js b/src/third_party/protobuf-3/js/binary/writer.js
new file mode 100644
index 0000000..be4478e
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/writer.js
@@ -0,0 +1,1561 @@
+// 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.
+
+/**
+ * @fileoverview This file contains utilities for encoding Javascript objects
+ * into binary, wire-format protocol buffers (in the form of Uint8Arrays) that
+ * a server can consume directly.
+ *
+ * jspb's BinaryWriter class defines methods for efficiently encoding
+ * Javascript objects into binary, wire-format protocol buffers and supports
+ * all the fundamental field types used in protocol buffers.
+ *
+ * Major caveat 1 - Users of this library _must_ keep their Javascript proto
+ * parsing code in sync with the original .proto file - presumably you'll be
+ * using the typed jspb code generator, but if you bypass that you'll need
+ * to keep things in sync by hand.
+ *
+ * Major caveat 2 - Javascript is unable to accurately represent integers
+ * larger than 2^53 due to its use of a double-precision floating point format
+ * for all numbers. BinaryWriter does not make any special effort to preserve
+ * precision for values above this limit - if you need to pass 64-bit integers
+ * (hash codes, for example) between the client and server without precision
+ * loss, do _not_ use this library.
+ *
+ * Major caveat 3 - This class uses typed arrays and must not be used on older
+ * browsers that do not support them.
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.provide('jspb.BinaryWriter');
+
+goog.require('goog.asserts');
+goog.require('goog.crypt.base64');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryEncoder');
+goog.require('jspb.arith.Int64');
+goog.require('jspb.arith.UInt64');
+goog.require('jspb.utils');
+
+
+
+/**
+ * BinaryWriter implements encoders for all the wire types specified in
+ * https://developers.google.com/protocol-buffers/docs/encoding.
+ *
+ * @constructor
+ * @struct
+ */
+jspb.BinaryWriter = function() {
+  /**
+   * Blocks of serialized data that will be concatenated once all messages have
+   * been written.
+   * @private {!Array<!Uint8Array|!Array<number>>}
+   */
+  this.blocks_ = [];
+
+  /**
+   * Total number of bytes in the blocks_ array. Does _not_ include bytes in
+   * the encoder below.
+   * @private {number}
+   */
+  this.totalLength_ = 0;
+
+  /**
+   * Binary encoder holding pieces of a message that we're still serializing.
+   * When we get to a stopping point (either the start of a new submessage, or
+   * when we need to append a raw Uint8Array), the encoder's buffer will be
+   * added to the block array above and the encoder will be reset.
+   * @private {!jspb.BinaryEncoder}
+   */
+  this.encoder_ = new jspb.BinaryEncoder();
+
+  /**
+   * A stack of bookmarks containing the parent blocks for each message started
+   * via beginSubMessage(), needed as bookkeeping for endSubMessage().
+   * TODO(aappleby): Deprecated, users should be calling writeMessage().
+   * @private {!Array.<!Array.<number>>}
+   */
+  this.bookmarks_ = [];
+};
+
+
+/**
+ * Append a typed array of bytes onto the buffer.
+ *
+ * @param {!Uint8Array} arr The byte array to append.
+ * @private
+ */
+jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) {
+  var temp = this.encoder_.end();
+  this.blocks_.push(temp);
+  this.blocks_.push(arr);
+  this.totalLength_ += temp.length + arr.length;
+};
+
+
+/**
+ * Begins a new message by writing the field header and returning a bookmark
+ * which we will use to patch in the message length to in endDelimited_ below.
+ * @param {number} field
+ * @return {!Array.<number>}
+ * @private
+ */
+jspb.BinaryWriter.prototype.beginDelimited_ = function(field) {
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  var bookmark = this.encoder_.end();
+  this.blocks_.push(bookmark);
+  this.totalLength_ += bookmark.length;
+  bookmark.push(this.totalLength_);
+  return bookmark;
+};
+
+
+/**
+ * Ends a message by encoding the _change_ in length of the buffer to the
+ * parent block and adds the number of bytes needed to encode that length to
+ * the total byte length.
+ * @param {!Array.<number>} bookmark
+ * @private
+ */
+jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) {
+  var oldLength = bookmark.pop();
+  var messageLength = this.totalLength_ + this.encoder_.length() - oldLength;
+  goog.asserts.assert(messageLength >= 0);
+
+  while (messageLength > 127) {
+    bookmark.push((messageLength & 0x7f) | 0x80);
+    messageLength = messageLength >>> 7;
+    this.totalLength_++;
+  }
+
+  bookmark.push(messageLength);
+  this.totalLength_++;
+};
+
+
+/**
+ * Writes a pre-serialized message to the buffer.
+ * @param {!Uint8Array} bytes The array of bytes to write.
+ * @param {number} start The start of the range to write.
+ * @param {number} end The end of the range to write.
+ */
+jspb.BinaryWriter.prototype.writeSerializedMessage = function(
+    bytes, start, end) {
+  this.appendUint8Array_(bytes.subarray(start, end));
+};
+
+
+/**
+ * Writes a pre-serialized message to the buffer if the message and endpoints
+ * are non-null.
+ * @param {?Uint8Array} bytes The array of bytes to write.
+ * @param {?number} start The start of the range to write.
+ * @param {?number} end The end of the range to write.
+ */
+jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function(
+    bytes, start, end) {
+  if (bytes != null && start != null && end != null) {
+    this.writeSerializedMessage(bytes, start, end);
+  }
+};
+
+
+/**
+ * Resets the writer, throwing away any accumulated buffers.
+ */
+jspb.BinaryWriter.prototype.reset = function() {
+  this.blocks_ = [];
+  this.encoder_.end();
+  this.totalLength_ = 0;
+  this.bookmarks_ = [];
+};
+
+
+/**
+ * Converts the encoded data into a Uint8Array.
+ * @return {!Uint8Array}
+ */
+jspb.BinaryWriter.prototype.getResultBuffer = function() {
+  goog.asserts.assert(this.bookmarks_.length == 0);
+
+  var flat = new Uint8Array(this.totalLength_ + this.encoder_.length());
+
+  var blocks = this.blocks_;
+  var blockCount = blocks.length;
+  var offset = 0;
+
+  for (var i = 0; i < blockCount; i++) {
+    var block = blocks[i];
+    flat.set(block, offset);
+    offset += block.length;
+  }
+
+  var tail = this.encoder_.end();
+  flat.set(tail, offset);
+  offset += tail.length;
+
+  // Post condition: `flattened` must have had every byte written.
+  goog.asserts.assert(offset == flat.length);
+
+  // Replace our block list with the flattened block, which lets GC reclaim
+  // the temp blocks sooner.
+  this.blocks_ = [flat];
+
+  return flat;
+};
+
+
+/**
+ * Converts the encoded data into a bas64-encoded string.
+ * @return {string}
+ */
+jspb.BinaryWriter.prototype.getResultBase64String = function() {
+  return goog.crypt.base64.encodeByteArray(this.getResultBuffer());
+};
+
+
+/**
+ * Begins a new sub-message. The client must call endSubMessage() when they're
+ * done.
+ * TODO(aappleby): Deprecated. Move callers to writeMessage().
+ * @param {number} field The field number of the sub-message.
+ */
+jspb.BinaryWriter.prototype.beginSubMessage = function(field) {
+  this.bookmarks_.push(this.beginDelimited_(field));
+};
+
+
+/**
+ * Finishes a sub-message and packs it into the parent messages' buffer.
+ * TODO(aappleby): Deprecated. Move callers to writeMessage().
+ */
+jspb.BinaryWriter.prototype.endSubMessage = function() {
+  goog.asserts.assert(this.bookmarks_.length >= 0);
+  this.endDelimited_(this.bookmarks_.pop());
+};
+
+
+/**
+ * Encodes a (field number, wire type) tuple into a wire-format field header
+ * and stores it in the buffer as a varint.
+ * @param {number} field The field number.
+ * @param {number} wireType The wire-type of the field, as specified in the
+ *     protocol buffer documentation.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeFieldHeader_ =
+    function(field, wireType) {
+  goog.asserts.assert(field >= 1 && field == Math.floor(field));
+  var x = field * 8 + wireType;
+  this.encoder_.writeUnsignedVarint32(x);
+};
+
+
+/**
+ * Writes a field of any valid scalar type to the binary stream.
+ * @param {jspb.BinaryConstants.FieldType} fieldType
+ * @param {number} field
+ * @param {jspb.AnyFieldType} value
+ */
+jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) {
+  var fieldTypes = jspb.BinaryConstants.FieldType;
+  switch (fieldType) {
+    case fieldTypes.DOUBLE:
+      this.writeDouble(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.FLOAT:
+      this.writeFloat(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.INT64:
+      this.writeInt64(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.UINT64:
+      this.writeUint64(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.INT32:
+      this.writeInt32(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.FIXED64:
+      this.writeFixed64(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.FIXED32:
+      this.writeFixed32(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.BOOL:
+      this.writeBool(field, /** @type {boolean} */(value));
+      return;
+    case fieldTypes.STRING:
+      this.writeString(field, /** @type {string} */(value));
+      return;
+    case fieldTypes.GROUP:
+      goog.asserts.fail('Group field type not supported in writeAny()');
+      return;
+    case fieldTypes.MESSAGE:
+      goog.asserts.fail('Message field type not supported in writeAny()');
+      return;
+    case fieldTypes.BYTES:
+      this.writeBytes(field, /** @type {?Uint8Array} */(value));
+      return;
+    case fieldTypes.UINT32:
+      this.writeUint32(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.ENUM:
+      this.writeEnum(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.SFIXED32:
+      this.writeSfixed32(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.SFIXED64:
+      this.writeSfixed64(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.SINT32:
+      this.writeSint32(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.SINT64:
+      this.writeSint64(field, /** @type {number} */(value));
+      return;
+    case fieldTypes.FHASH64:
+      this.writeFixedHash64(field, /** @type {string} */(value));
+      return;
+    case fieldTypes.VHASH64:
+      this.writeVarintHash64(field, /** @type {string} */(value));
+      return;
+    default:
+      goog.asserts.fail('Invalid field type in writeAny()');
+      return;
+  }
+};
+
+
+/**
+ * Writes a varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeUnsignedVarint32(value);
+};
+
+
+/**
+ * Writes a varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeSignedVarint32(value);
+};
+
+
+/**
+ * Writes a varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeUnsignedVarint64(value);
+};
+
+
+/**
+ * Writes a varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeSignedVarint64(value);
+};
+
+
+/**
+ * Writes a zigzag varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeZigzagVarint32(value);
+};
+
+
+/**
+ * Writes a zigzag varint field to the buffer without range checking.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeZigzagVarint64(value);
+};
+
+
+/**
+ * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeInt32 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeSignedVarint32_(field, value);
+};
+
+
+/**
+ * Writes an int32 field represented as a string to the buffer. Numbers outside
+ * the range [-2^31,2^31) will be truncated.
+ * @param {number} field The field number.
+ * @param {string?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeInt32String = function(field, value) {
+  if (value == null) return;
+  var intValue = /** {number} */ parseInt(value, 10);
+  goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (intValue < jspb.BinaryConstants.TWO_TO_31));
+  this.writeSignedVarint32_(field, intValue);
+};
+
+
+/**
+ * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeInt64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  this.writeSignedVarint64_(field, value);
+};
+
+
+/**
+ * Writes a int64 field (with value as a string) to the buffer.
+ * @param {number} field The field number.
+ * @param {string?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeInt64String = function(field, value) {
+  if (value == null) return;
+  var num = jspb.arith.Int64.fromString(value);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeSplitVarint64(num.lo, num.hi);
+};
+
+
+/**
+ * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeUint32 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_32));
+  this.writeUnsignedVarint32_(field, value);
+};
+
+
+/**
+ * Writes a uint32 field represented as a string to the buffer. Numbers outside
+ * the range [0,2^32) will be truncated.
+ * @param {number} field The field number.
+ * @param {string?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeUint32String = function(field, value) {
+  if (value == null) return;
+  var intValue = /** {number} */ parseInt(value, 10);
+  goog.asserts.assert((intValue >= 0) &&
+                      (intValue < jspb.BinaryConstants.TWO_TO_32));
+  this.writeUnsignedVarint32_(field, intValue);
+};
+
+
+/**
+ * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeUint64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_64));
+  this.writeUnsignedVarint64_(field, value);
+};
+
+
+/**
+ * Writes a uint64 field (with value as a string) to the buffer.
+ * @param {number} field The field number.
+ * @param {string?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeUint64String = function(field, value) {
+  if (value == null) return;
+  var num = jspb.arith.UInt64.fromString(value);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeSplitVarint64(num.lo, num.hi);
+};
+
+
+/**
+ * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeSint32 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeZigzagVarint32_(field, value);
+};
+
+
+/**
+ * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeSint64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  this.writeZigzagVarint64_(field, value);
+};
+
+
+/**
+ * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_32));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
+  this.encoder_.writeUint32(value);
+};
+
+
+/**
+ * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64)
+ * will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= 0) &&
+                      (value < jspb.BinaryConstants.TWO_TO_64));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
+  this.encoder_.writeUint64(value);
+};
+
+
+/**
+ * Writes a sfixed32 field to the buffer. Numbers outside the range
+ * [-2^31,2^31) will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
+  this.encoder_.writeInt32(value);
+};
+
+
+/**
+ * Writes a sfixed64 field to the buffer. Numbers outside the range
+ * [-2^63,2^63) will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
+                      (value < jspb.BinaryConstants.TWO_TO_63));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
+  this.encoder_.writeInt64(value);
+};
+
+
+/**
+ * Writes a single-precision floating point field to the buffer. Numbers
+ * requiring more than 32 bits of precision will be truncated.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeFloat = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
+  this.encoder_.writeFloat(value);
+};
+
+
+/**
+ * Writes a double-precision floating point field to the buffer. As this is the
+ * native format used by JavaScript, no precision will be lost.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeDouble = function(field, value) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
+  this.encoder_.writeDouble(value);
+};
+
+
+/**
+ * Writes a boolean field to the buffer.
+ * @param {number} field The field number.
+ * @param {boolean?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeBool = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert(goog.isBoolean(value));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeBool(value);
+};
+
+
+/**
+ * Writes an enum field to the buffer.
+ * @param {number} field The field number.
+ * @param {number?} value The value to write.
+ */
+jspb.BinaryWriter.prototype.writeEnum = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
+                      (value < jspb.BinaryConstants.TWO_TO_31));
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeSignedVarint32(value);
+};
+
+
+/**
+ * Writes a string field to the buffer.
+ * @param {number} field The field number.
+ * @param {string?} value The string to write.
+ */
+jspb.BinaryWriter.prototype.writeString = function(field, value) {
+  if (value == null) return;
+  var bookmark = this.beginDelimited_(field);
+  this.encoder_.writeString(value);
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an arbitrary byte field to the buffer. Note - to match the behavior
+ * of the C++ implementation, empty byte arrays _are_ serialized.
+ * @param {number} field The field number.
+ * @param {?jspb.ByteSource} value The array of bytes to write.
+ */
+jspb.BinaryWriter.prototype.writeBytes = function(field, value) {
+  if (value == null) return;
+  var bytes = jspb.utils.byteSourceToUint8Array(value);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(bytes.length);
+  this.appendUint8Array_(bytes);
+};
+
+
+/**
+ * Writes a message to the buffer.
+ * @template MessageType
+ * @param {number} field The field number.
+ * @param {?MessageType} value The message to write.
+ * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
+ *     to write and the writer to write it with.
+ */
+jspb.BinaryWriter.prototype.writeMessage = function(
+    field, value, writerCallback) {
+  if (value == null) return;
+  var bookmark = this.beginDelimited_(field);
+  writerCallback(value, this);
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes a group message to the buffer.
+ *
+ * @template MessageType
+ * @param {number} field The field number.
+ * @param {?MessageType} value The message to write, wrapped with START_GROUP /
+ *     END_GROUP tags. Will be a no-op if 'value' is null.
+ * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
+ *     to write and the writer to write it with.
+ */
+jspb.BinaryWriter.prototype.writeGroup = function(
+    field, value, writerCallback) {
+  if (value == null) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP);
+  writerCallback(value, this);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP);
+};
+
+
+/**
+ * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
+ * the buffer.
+ * @param {number} field The field number.
+ * @param {string?} value The hash string.
+ */
+jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert(value.length == 8);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
+  this.encoder_.writeFixedHash64(value);
+};
+
+
+/**
+ * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
+ * the buffer.
+ * @param {number} field The field number.
+ * @param {string?} value The hash string.
+ */
+jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) {
+  if (value == null) return;
+  goog.asserts.assert(value.length == 8);
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
+  this.encoder_.writeVarintHash64(value);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_ =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeUnsignedVarint32_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_ =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeSignedVarint32_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_ =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeUnsignedVarint64_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_ =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeSignedVarint64_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated zigzag field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedZigzag32_ = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeZigzagVarint32_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated zigzag field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writeRepeatedZigzag_ = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeZigzagVarint64_(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedInt32 =
+    jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_;
+
+
+/**
+ * Writes an array of numbers formatted as strings to the buffer as a repeated
+ * 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedInt32String =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeInt32String(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedInt64 =
+    jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_;
+
+
+/**
+ * Writes an array of numbers formatted as strings to the buffer as a repeated
+ * 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedInt64String =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeInt64String(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a repeated unsigned 32-bit int
+ *     field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUint32 =
+    jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_;
+
+
+/**
+ * Writes an array of numbers formatted as strings to the buffer as a repeated
+ * unsigned 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUint32String =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeUint32String(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a repeated unsigned 64-bit int
+ *     field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUint64 =
+    jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_;
+
+
+/**
+ * Writes an array of numbers formatted as strings to the buffer as a repeated
+ * unsigned 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedUint64String =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeUint64String(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a repeated signed 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSint32 =
+    jspb.BinaryWriter.prototype.writeRepeatedZigzag32_;
+
+
+/**
+ * Writes an array numbers to the buffer as a repeated signed 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSint64 =
+    jspb.BinaryWriter.prototype.writeRepeatedZigzag_;
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated fixed32 field. This
+ * works for both signed and unsigned fixed32s.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeFixed32(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated fixed64 field. This
+ * works for both signed and unsigned fixed64s.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeFixed64(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated sfixed32 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeSfixed32(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated sfixed64 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeSfixed64(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated float field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeFloat(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a repeated double field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeDouble(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of booleans to the buffer as a repeated bool field.
+ * @param {number} field The field number.
+ * @param {?Array.<boolean>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeBool(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of enums to the buffer as a repeated enum field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeEnum(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of strings to the buffer as a repeated string field.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of strings to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeString(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of arbitrary byte fields to the buffer.
+ * @param {number} field The field number.
+ * @param {?Array.<!jspb.ByteSource>} value The arrays of arrays of bytes to
+ *     write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeBytes(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of messages to the buffer.
+ * @template MessageType
+ * @param {number} field The field number.
+ * @param {?Array.<MessageType>} value The array of messages to
+ *    write.
+ * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
+ *     to write and the writer to write it with.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedMessage = function(
+    field, value, writerCallback) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    var bookmark = this.beginDelimited_(field);
+    writerCallback(value[i], this);
+    this.endDelimited_(bookmark);
+  }
+};
+
+
+/**
+ * Writes an array of group messages to the buffer.
+ * @template MessageType
+ * @param {number} field The field number.
+ * @param {?Array.<MessageType>} value The array of messages to
+ *    write.
+ * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
+ *     to write and the writer to write it with.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedGroup = function(
+    field, value, writerCallback) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP);
+    writerCallback(value[i], this);
+    this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP);
+  }
+};
+
+
+/**
+ * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
+ * the buffer.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of hashes to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeFixedHash64(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data
+ * each) to the buffer.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of hashes to write.
+ */
+jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 =
+    function(field, value) {
+  if (value == null) return;
+  for (var i = 0; i < value.length; i++) {
+    this.writeVarintHash64(field, value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_ = function(
+    field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeUnsignedVarint32(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedSignedVarint32_ = function(
+    field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeSignedVarint32(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_ = function(
+    field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeUnsignedVarint64(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed varint field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedSignedVarint64_ = function(
+    field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeSignedVarint64(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed zigzag field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedZigzag32_ = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeZigzagVarint32(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed zigzag field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ * @private
+ */
+jspb.BinaryWriter.prototype.writePackedZigzag64_ = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeZigzagVarint64(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedInt32 =
+    jspb.BinaryWriter.prototype.writePackedSignedVarint32_;
+
+
+/**
+ * Writes an array of numbers represented as strings to the buffer as a packed
+ * 32-bit int field.
+ * @param {number} field
+ * @param {?Array.<string>} value
+ */
+jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeSignedVarint32(parseInt(value[i], 10));
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedInt64 =
+    jspb.BinaryWriter.prototype.writePackedSignedVarint64_;
+
+
+/**
+ * Writes an array of numbers represented as strings to the buffer as a packed
+ * 64-bit int field.
+ * @param {number} field
+ * @param {?Array.<string>} value
+ */
+jspb.BinaryWriter.prototype.writePackedInt64String =
+    function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    var num = jspb.arith.Int64.fromString(value[i]);
+    this.encoder_.writeSplitVarint64(num.lo, num.hi);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a packed unsigned 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedUint32 =
+    jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_;
+
+
+/**
+ * Writes an array of numbers represented as strings to the buffer as a packed
+ * unsigned 32-bit int field.
+ * @param {number} field
+ * @param {?Array.<string>} value
+ */
+jspb.BinaryWriter.prototype.writePackedUint32String =
+    function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10));
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a packed unsigned 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedUint64 =
+    jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_;
+
+
+/**
+ * Writes an array of numbers represented as strings to the buffer as a packed
+ * unsigned 64-bit int field.
+ * @param {number} field
+ * @param {?Array.<string>} value
+ */
+jspb.BinaryWriter.prototype.writePackedUint64String =
+    function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    var num = jspb.arith.UInt64.fromString(value[i]);
+    this.encoder_.writeSplitVarint64(num.lo, num.hi);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes an array numbers to the buffer as a packed signed 32-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedSint32 =
+    jspb.BinaryWriter.prototype.writePackedZigzag32_;
+
+
+/**
+ * Writes an array numbers to the buffer as a packed signed 64-bit int field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedSint64 =
+    jspb.BinaryWriter.prototype.writePackedZigzag64_;
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed fixed32 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 4);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeUint32(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed fixed64 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 8);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeUint64(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed sfixed32 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 4);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeInt32(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed sfixed64 field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 8);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeInt64(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed float field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 4);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeFloat(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of numbers to the buffer as a packed double field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 8);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeDouble(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of booleans to the buffer as a packed bool field.
+ * @param {number} field The field number.
+ * @param {?Array.<boolean>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedBool = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeBool(value[i]);
+  }
+};
+
+
+/**
+ * Writes an array of enums to the buffer as a packed enum field.
+ * @param {number} field The field number.
+ * @param {?Array.<number>} value The array of ints to write.
+ */
+jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeEnum(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
+
+
+/**
+ * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
+ * the buffer.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of hashes to write.
+ */
+jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) {
+  if (value == null || !value.length) return;
+  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
+  this.encoder_.writeUnsignedVarint32(value.length * 8);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeFixedHash64(value[i]);
+  }
+};
+
+
+/**
+ * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
+ * the buffer.
+ * @param {number} field The field number.
+ * @param {?Array.<string>} value The array of hashes to write.
+ */
+jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) {
+  if (value == null || !value.length) return;
+  var bookmark = this.beginDelimited_(field);
+  for (var i = 0; i < value.length; i++) {
+    this.encoder_.writeVarintHash64(value[i]);
+  }
+  this.endDelimited_(bookmark);
+};
diff --git a/src/third_party/protobuf-3/js/binary/writer_test.js b/src/third_party/protobuf-3/js/binary/writer_test.js
new file mode 100644
index 0000000..54d37a2
--- /dev/null
+++ b/src/third_party/protobuf-3/js/binary/writer_test.js
@@ -0,0 +1,123 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer writer. In
+ * practice BinaryWriter is used to drive the Decoder and Reader test cases,
+ * so only writer-specific tests are here.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.crypt');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryWriter');
+
+
+/**
+ * @param {function()} func This function should throw an error when run.
+ */
+function assertFails(func) {
+  var e = assertThrows(func);
+  console.log(e);
+  //assertNotNull(e.toString().match(/Error/));
+}
+
+
+describe('binaryWriterTest', function() {
+  /**
+   * Verifies that misuse of the writer class triggers assertions.
+   */
+  it('testWriteErrors', function() {
+    // Submessages with invalid field indices should assert.
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    assertFails(function() {
+      writer.writeMessage(-1, dummyMessage, goog.nullFunction);
+    });
+
+    // Writing invalid field indices should assert.
+    writer = new jspb.BinaryWriter();
+    assertFails(function() {writer.writeUint64(-1, 1);});
+
+    // Writing out-of-range field values should assert.
+    writer = new jspb.BinaryWriter();
+
+    assertFails(function() {writer.writeInt32(1, -Infinity);});
+    assertFails(function() {writer.writeInt32(1, Infinity);});
+
+    assertFails(function() {writer.writeInt64(1, -Infinity);});
+    assertFails(function() {writer.writeInt64(1, Infinity);});
+
+    assertFails(function() {writer.writeUint32(1, -1);});
+    assertFails(function() {writer.writeUint32(1, Infinity);});
+
+    assertFails(function() {writer.writeUint64(1, -1);});
+    assertFails(function() {writer.writeUint64(1, Infinity);});
+
+    assertFails(function() {writer.writeSint32(1, -Infinity);});
+    assertFails(function() {writer.writeSint32(1, Infinity);});
+
+    assertFails(function() {writer.writeSint64(1, -Infinity);});
+    assertFails(function() {writer.writeSint64(1, Infinity);});
+
+    assertFails(function() {writer.writeFixed32(1, -1);});
+    assertFails(function() {writer.writeFixed32(1, Infinity);});
+
+    assertFails(function() {writer.writeFixed64(1, -1);});
+    assertFails(function() {writer.writeFixed64(1, Infinity);});
+
+    assertFails(function() {writer.writeSfixed32(1, -Infinity);});
+    assertFails(function() {writer.writeSfixed32(1, Infinity);});
+
+    assertFails(function() {writer.writeSfixed64(1, -Infinity);});
+    assertFails(function() {writer.writeSfixed64(1, Infinity);});
+  });
+
+
+  /**
+   * Basic test of retrieving the result as a Uint8Array buffer
+   */
+  it('testGetResultBuffer', function() {
+    var expected = '0864120b48656c6c6f20776f726c641a0301020320c801';
+
+    var writer = new jspb.BinaryWriter();
+    writer.writeUint32(1, 100);
+    writer.writeString(2, 'Hello world');
+    writer.writeBytes(3, new Uint8Array([1, 2, 3]));
+    writer.writeUint32(4, 200);
+
+    var buffer = writer.getResultBuffer();
+    assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
+  });
+});
diff --git a/src/third_party/protobuf-3/js/commonjs/export.js b/src/third_party/protobuf-3/js/commonjs/export.js
new file mode 100644
index 0000000..a3cfbd6
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/export.js
@@ -0,0 +1,22 @@
+/**
+ * @fileoverview Export symbols needed by generated code in CommonJS style.
+ *
+ * This effectively is our canonical list of what we publicly export from
+ * the google-protobuf.js file that we build at distribution time.
+ */
+
+goog.require('goog.object');
+goog.require('jspb.BinaryReader');
+goog.require('jspb.BinaryWriter');
+goog.require('jspb.ExtensionFieldInfo');
+goog.require('jspb.Message');
+
+exports.Message = jspb.Message;
+exports.BinaryReader = jspb.BinaryReader;
+exports.BinaryWriter = jspb.BinaryWriter;
+exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo;
+
+// These are used by generated code but should not be used directly by clients.
+exports.exportSymbol = goog.exportSymbol;
+exports.inherits = goog.inherits;
+exports.object = {extend: goog.object.extend};
diff --git a/src/third_party/protobuf-3/js/commonjs/export_asserts.js b/src/third_party/protobuf-3/js/commonjs/export_asserts.js
new file mode 100644
index 0000000..5219d12
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/export_asserts.js
@@ -0,0 +1,37 @@
+/**
+ * @fileoverview Exports symbols needed only by tests.
+ *
+ * This file exports several Closure Library symbols that are only
+ * used by tests.  It is used to generate a file
+ * closure_asserts_commonjs.js that is only used at testing time.
+ */
+
+goog.require('goog.testing.asserts');
+
+var global = Function('return this')();
+
+// All of the closure "assert" functions are exported at the global level.
+//
+// The Google Closure assert functions start with assert, eg.
+//   assertThrows
+//   assertNotThrows
+//   assertTrue
+//   ...
+//
+// The one exception is the "fail" function.
+function shouldExport(str) {
+  return str.lastIndexOf('assert') === 0 || str == 'fail';
+}
+
+for (var key in global) {
+  if ((typeof key == "string") && global.hasOwnProperty(key) &&
+      shouldExport(key)) {
+    exports[key] = global[key];
+  }
+}
+
+// The COMPILED variable is set by Closure compiler to "true" when it compiles
+// JavaScript, so in practice this is equivalent to "exports.COMPILED = true".
+// This will disable some debugging functionality in debug.js.  We could
+// investigate whether this can/should be enabled in CommonJS builds.
+exports.COMPILED = COMPILED
diff --git a/src/third_party/protobuf-3/js/commonjs/export_testdeps.js b/src/third_party/protobuf-3/js/commonjs/export_testdeps.js
new file mode 100644
index 0000000..59c77ca
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/export_testdeps.js
@@ -0,0 +1,18 @@
+/**
+ * @fileoverview Export symbols needed by tests in CommonJS style.
+ *
+ * This file is like export.js, but for symbols that are only used by tests.
+ * However we exclude assert functions here, because they are exported into
+ * the global namespace, so those are handled as a special case in
+ * export_asserts.js.
+ */
+
+goog.require('goog.crypt.base64');
+goog.require('jspb.arith.Int64');
+goog.require('jspb.arith.UInt64');
+goog.require('jspb.BinaryEncoder');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.utils');
+
+exports.goog = goog;
+exports.jspb = jspb;
diff --git a/src/third_party/protobuf-3/js/commonjs/import_test.js b/src/third_party/protobuf-3/js/commonjs/import_test.js
new file mode 100644
index 0000000..ffa34fe
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/import_test.js
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+
+
+var googleProtobuf = require('google-protobuf');
+var asserts = require('closure_asserts_commonjs');
+var global = Function('return this')();
+
+// Bring asserts into the global namespace.
+googleProtobuf.object.extend(global, asserts);
+googleProtobuf.exportSymbol('jspb.Message', googleProtobuf.Message, global);
+
+var test7_pb = require('./test7/test7_pb');
+googleProtobuf.exportSymbol('proto.jspb.test.framing.FramingMessage', test7_pb.FramingMessage, global);
+
+describe('Import test suite', function() {
+  it('testImportedMessage', function() {
+    var framing1 = new proto.jspb.test.framing.FramingMessage([]);
+    var framing2 = new proto.jspb.test.framing.FramingMessage([]);
+    assertObjectEquals(framing1.toObject(), framing2.toObject());
+  });
+});
diff --git a/src/third_party/protobuf-3/js/commonjs/jasmine.json b/src/third_party/protobuf-3/js/commonjs/jasmine.json
new file mode 100644
index 0000000..666b8ed
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/jasmine.json
@@ -0,0 +1,9 @@
+{
+    "spec_dir": "",
+    "spec_files": [
+        "*_test.js",
+        "binary/proto_test.js"
+    ],
+    "helpers": [
+    ]
+}
diff --git a/src/third_party/protobuf-3/js/commonjs/rewrite_tests_for_commonjs.js b/src/third_party/protobuf-3/js/commonjs/rewrite_tests_for_commonjs.js
new file mode 100644
index 0000000..b6d90d2
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/rewrite_tests_for_commonjs.js
@@ -0,0 +1,97 @@
+/**
+ * @fileoverview Utility to translate test files to CommonJS imports.
+ *
+ * This is a somewhat hacky tool designed to do one very specific thing.
+ * All of the test files in *_test.js are written with Closure-style
+ * imports (goog.require()).  This works great for running the tests
+ * against Closure-style generated code, but we also want to run the
+ * tests against CommonJS-style generated code without having to fork
+ * the tests.
+ *
+ * Closure-style imports import each individual type by name.  This is
+ * very different than CommonJS imports which are by file.  So we put
+ * special comments in these tests like:
+ *
+ * // CommonJS-LoadFromFile: test_pb
+ * goog.require('proto.jspb.test.CloneExtension');
+ * goog.require('proto.jspb.test.Complex');
+ * goog.require('proto.jspb.test.DefaultValues');
+ *
+ * This script parses that special comment and uses it to generate proper
+ * CommonJS require() statements so that the tests can run and pass using
+ * CommonJS imports.  The script will change the above statements into:
+ *
+ *   var test_pb = require('test_pb');
+ *   googleProtobuf.exportSymbol('proto.jspb.test.CloneExtension', test_pb.CloneExtension, global);
+ *   googleProtobuf.exportSymbol('proto.jspb.test.Complex', test_pb.Complex, global);
+ *   googleProtobuf.exportSymbol('proto.jspb.test.DefaultValues', test_pb.DefaultValues, global);
+ *
+ * (The "exportSymbol" function will define the given names in the global
+ * namespace, taking care not to overwrite any previous value for
+ * "proto.jspb.test").
+ */
+
+var lineReader = require('readline').createInterface({
+  input: process.stdin,
+  output: process.stdout
+});
+
+function tryStripPrefix(str, prefix) {
+  if (str.lastIndexOf(prefix) !== 0) {
+    throw "String: " + str + " didn't start with: " + prefix;
+  }
+  return str.substr(prefix.length);
+}
+
+function camelCase(str) {
+  var ret = '';
+  var ucaseNext = false;
+  for (var i = 0; i < str.length; i++) {
+    if (str[i] == '-') {
+      ucaseNext = true;
+    } else if (ucaseNext) {
+      ret += str[i].toUpperCase();
+      ucaseNext = false;
+    } else {
+      ret += str[i];
+    }
+  }
+  return ret;
+}
+
+var module = null;
+var pkg = null;
+
+// Header: goes in every file at the top.
+console.log("var global = Function('return this')();");
+console.log("var googleProtobuf = require('google-protobuf');");
+console.log("var testdeps = require('testdeps_commonjs');");
+console.log("global.goog = testdeps.goog;");
+console.log("global.jspb = testdeps.jspb;");
+console.log("var asserts = require('closure_asserts_commonjs');");
+console.log("");
+console.log("// Bring asserts into the global namespace.");
+console.log("googleProtobuf.object.extend(global, asserts);");
+
+lineReader.on('line', function(line) {
+  var isRequire = line.match(/goog\.require\('([^']*)'\)/);
+  var isLoadFromFile = line.match(/CommonJS-LoadFromFile: (\S*) (.*)/);
+  var isSetTestOnly = line.match(/goog.setTestOnly()/);
+  if (isRequire) {
+    if (module) {  // Skip goog.require() lines before the first directive.
+      var fullSym = isRequire[1];
+      var sym = tryStripPrefix(fullSym, pkg);
+      console.log("googleProtobuf.exportSymbol('" + fullSym + "', " + module + sym + ', global);');
+    }
+  } else if (isLoadFromFile) {
+    var module_path = isLoadFromFile[1].split('/');
+    module = camelCase(module_path[module_path.length - 1]);
+    pkg = isLoadFromFile[2];
+
+    if (module != "googleProtobuf") {  // We unconditionally require this in the header.
+      console.log("var " + module + " = require('./" + isLoadFromFile[1] + "');");
+    }
+  } else if (!isSetTestOnly) {  // Remove goog.setTestOnly() lines.
+    console.log(line);
+  }
+});
diff --git a/src/third_party/protobuf-3/js/commonjs/test6/test6.proto b/src/third_party/protobuf-3/js/commonjs/test6/test6.proto
new file mode 100644
index 0000000..a060925
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/test6/test6.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+
+syntax = "proto3";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.importing;
+
+message ImportedMessage {
+  string string_value = 1;
+}
diff --git a/src/third_party/protobuf-3/js/commonjs/test7/test7.proto b/src/third_party/protobuf-3/js/commonjs/test7/test7.proto
new file mode 100644
index 0000000..f5574a3
--- /dev/null
+++ b/src/third_party/protobuf-3/js/commonjs/test7/test7.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+
+syntax = "proto3";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.framing;
+
+import "test6/test6.proto";
+
+message FramingMessage {
+  jspb.test.importing.ImportedMessage imported_message = 1;
+}
diff --git a/src/third_party/protobuf-3/js/data.proto b/src/third_party/protobuf-3/js/data.proto
new file mode 100644
index 0000000..74a8a99
--- /dev/null
+++ b/src/third_party/protobuf-3/js/data.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: mwr@google.com (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+// legacy data, must be nested
+message data {
+  message NestedData {
+    required string str = 1;
+  }
+}
+
+// new data, does not require nesting
+message UnnestedData {
+  required string str = 1;
+}
+
diff --git a/src/third_party/protobuf-3/js/debug.js b/src/third_party/protobuf-3/js/debug.js
new file mode 100644
index 0000000..3701a09
--- /dev/null
+++ b/src/third_party/protobuf-3/js/debug.js
@@ -0,0 +1,140 @@
+// 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.
+
+/**
+ * @fileoverview Utilities to debug JSPB based proto objects.
+ */
+
+goog.provide('jspb.debug');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.object');
+goog.require('jspb.Message');
+
+
+/**
+ * Turns a proto into a human readable object that can i.e. be written to the
+ * console: {@code console.log(jspb.debug.dump(myProto))}.
+ * This function makes a best effort and may not work in all cases. It will not
+ * work in obfuscated and or optimized code.
+ * Use this in environments where {@see jspb.Message.prototype.toObject} is
+ * not available for code size reasons.
+ * @param {jspb.Message} message A jspb.Message.
+ * @return {Object}
+ */
+jspb.debug.dump = function(message) {
+  if (!goog.DEBUG) {
+    return null;
+  }
+  goog.asserts.assert(message instanceof jspb.Message,
+      'jspb.Message instance expected');
+  /** @type {Object} */
+  var object = message;
+  goog.asserts.assert(object['getExtension'],
+      'Only unobfuscated and unoptimized compilation modes supported.');
+  return /** @type {Object} */ (jspb.debug.dump_(message));
+};
+
+
+/**
+ * Recursively introspects a message and the values its getters return to
+ * make a best effort in creating a human readable representation of the
+ * message.
+ * @param {?} thing A jspb.Message, Array or primitive type to dump.
+ * @return {*}
+ * @private
+ */
+jspb.debug.dump_ = function(thing) {
+  var type = goog.typeOf(thing);
+  if (type == 'number' || type == 'string' || type == 'boolean' ||
+      type == 'null' || type == 'undefined') {
+    return thing;
+  }
+  if (type == 'array') {
+    goog.asserts.assertArray(thing);
+    return goog.array.map(thing, jspb.debug.dump_);
+  }
+  var message = thing;  // Copy because we don't want type inference on thing.
+  goog.asserts.assert(message instanceof jspb.Message,
+      'Only messages expected: ' + thing);
+  var ctor = message.constructor;
+  var messageName = ctor.name || ctor.displayName;
+  var object = {
+    '$name': messageName
+  };
+  for (var name in ctor.prototype) {
+    var match = /^get([A-Z]\w*)/.exec(name);
+    if (match && name != 'getExtension' &&
+        name != 'getJsPbMessageId') {
+      var val = thing[name]();
+      if (val != null) {
+        object[jspb.debug.formatFieldName_(match[1])] = jspb.debug.dump_(val);
+      }
+    }
+  }
+  if (COMPILED && thing['extensionObject_']) {
+    object['$extensions'] = 'Recursive dumping of extensions not supported ' +
+        'in compiled code. Switch to uncompiled or dump extension object ' +
+        'directly';
+    return object;
+  }
+  var extensionsObject;
+  for (var id in ctor['extensions']) {
+    if (/^\d+$/.test(id)) {
+      var ext = ctor['extensions'][id];
+      var extVal = thing.getExtension(ext);
+      var fieldName = goog.object.getKeys(ext.fieldName)[0];
+      if (extVal != null) {
+        if (!extensionsObject) {
+          extensionsObject = object['$extensions'] = {};
+        }
+        extensionsObject[jspb.debug.formatFieldName_(fieldName)] =
+            jspb.debug.dump_(extVal);
+      }
+    }
+  }
+  return object;
+};
+
+
+/**
+ * Formats a field name for output as camelCase.
+ *
+ * @param {string} name Name of the field.
+ * @return {string}
+ * @private
+ */
+jspb.debug.formatFieldName_ = function(name) {
+  // Name may be in TitleCase.
+  return name.replace(/^[A-Z]/, function(c) {
+    return c.toLowerCase();
+  });
+};
diff --git a/src/third_party/protobuf-3/js/debug_test.js b/src/third_party/protobuf-3/js/debug_test.js
new file mode 100644
index 0000000..01cbf89
--- /dev/null
+++ b/src/third_party/protobuf-3/js/debug_test.js
@@ -0,0 +1,105 @@
+// 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.
+
+goog.setTestOnly();
+
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: google-protobuf
+goog.require('jspb.debug');
+
+// CommonJS-LoadFromFile: test_pb
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.Simple1');
+
+
+
+describe('debugTest', function() {
+  it('testSimple1', function() {
+    if (COMPILED) {
+      return;
+    }
+    var message = new proto.jspb.test.Simple1();
+    message.setAString('foo');
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aString': 'foo',
+      'aRepeatedStringList': []
+    }, jspb.debug.dump(message));
+
+    message.setABoolean(true);
+    message.setARepeatedStringList(['1', '2']);
+
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aString': 'foo',
+      'aRepeatedStringList': ['1', '2'],
+      'aBoolean': true
+    }, jspb.debug.dump(message));
+
+    message.setAString(undefined);
+
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aRepeatedStringList': ['1', '2'],
+      'aBoolean': true
+    }, jspb.debug.dump(message));
+  });
+
+
+  it('testExtensions', function() {
+    if (COMPILED) {
+      return;
+    }
+    var extension = new proto.jspb.test.IsExtension();
+    extension.setExt1('ext1field');
+    var extendable = new proto.jspb.test.HasExtensions();
+    extendable.setStr1('v1');
+    extendable.setStr2('v2');
+    extendable.setStr3('v3');
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension);
+
+    assertObjectEquals({
+      '$name': 'proto.jspb.test.HasExtensions',
+      'str1': 'v1',
+      'str2': 'v2',
+      'str3': 'v3',
+      '$extensions': {
+        'extField': {
+          '$name': 'proto.jspb.test.IsExtension',
+          'ext1': 'ext1field'
+        },
+        'repeatedSimpleList': []
+      }
+    }, jspb.debug.dump(extendable));
+  });
+
+});
diff --git a/src/third_party/protobuf-3/js/gulpfile.js b/src/third_party/protobuf-3/js/gulpfile.js
new file mode 100644
index 0000000..c522015
--- /dev/null
+++ b/src/third_party/protobuf-3/js/gulpfile.js
@@ -0,0 +1,110 @@
+var gulp = require('gulp');
+var execFile = require('child_process').execFile;
+var glob = require('glob');
+
+function exec(command, cb) {
+  execFile('sh', ['-c', command], cb);
+}
+
+var protoc = process.env.PROTOC || '../src/protoc';
+
+gulp.task('genproto_closure', function (cb) {
+  exec(protoc + ' --js_out=library=testproto_libs,binary:.  -I ../src -I . *.proto ../src/google/protobuf/descriptor.proto',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('genproto_commonjs', function (cb) {
+  exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . *.proto commonjs/test*/*.proto ../src/google/protobuf/descriptor.proto',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('dist', function (cb) {
+  // TODO(haberman): minify this more aggressively.
+  // Will require proper externs/exports.
+  exec('./node_modules/google-closure-library/closure/bin/calcdeps.py -i message.js -i binary/reader.js -i binary/writer.js -i commonjs/export.js -p . -p node_modules/google-closure-library/closure -o compiled --compiler_jar node_modules/google-closure-compiler/compiler.jar > google-protobuf.js',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('commonjs_asserts', function (cb) {
+  exec('mkdir -p commonjs_out/test_node_modules && ./node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_asserts.js -p . -p node_modules/google-closure-library/closure -o compiled --compiler_jar node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/closure_asserts_commonjs.js',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('commonjs_testdeps', function (cb) {
+  exec('mkdir -p commonjs_out/test_node_modules && ./node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_testdeps.js -p . -p node_modules/google-closure-library/closure -o compiled --compiler_jar node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/testdeps_commonjs.js',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('make_commonjs_out', ['dist', 'genproto_commonjs', 'commonjs_asserts', 'commonjs_testdeps'], function (cb) {
+  // TODO(haberman): minify this more aggressively.
+  // Will require proper externs/exports.
+  var cmd = "mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && ";
+  function addTestFile(file) {
+    cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file +
+           ' > commonjs_out/' + file + '&& ';
+  }
+
+  glob.sync('*_test.js').forEach(addTestFile);
+  glob.sync('binary/*_test.js').forEach(addTestFile);
+
+  exec(cmd +
+       'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' +
+       'cp google-protobuf.js commonjs_out/test_node_modules && ' +
+       'cp commonjs/import_test.js commonjs_out/import_test.js',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('deps', ['genproto_closure'], function (cb) {
+  exec('./node_modules/google-closure-library/closure/bin/build/depswriter.py *.js binary/*.js > deps.js',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('test_closure', ['genproto_closure', 'deps'], function (cb) {
+  exec('JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('test_commonjs', ['make_commonjs_out'], function (cb) {
+  exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine',
+       function (err, stdout, stderr) {
+    console.log(stdout);
+    console.log(stderr);
+    cb(err);
+  });
+});
+
+gulp.task('test', ['test_closure', 'test_commonjs'], function(cb) {
+  cb();
+});
diff --git a/src/third_party/protobuf-3/js/jasmine.json b/src/third_party/protobuf-3/js/jasmine.json
new file mode 100644
index 0000000..f83c54c
--- /dev/null
+++ b/src/third_party/protobuf-3/js/jasmine.json
@@ -0,0 +1,12 @@
+{
+    "spec_dir": "",
+    "spec_files": [
+        "*_test.js",
+        "binary/*_test.js"
+    ],
+    "helpers": [
+        "node_modules/google-closure-library/closure/goog/bootstrap/nodejs.js",
+        "node_loader.js",
+        "deps.js"
+    ]
+}
diff --git a/src/third_party/protobuf-3/js/message.js b/src/third_party/protobuf-3/js/message.js
new file mode 100644
index 0000000..813e6b8
--- /dev/null
+++ b/src/third_party/protobuf-3/js/message.js
@@ -0,0 +1,1337 @@
+// 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.
+
+/**
+ * @fileoverview Definition of jspb.Message.
+ *
+ * @author mwr@google.com (Mark Rawling)
+ */
+
+goog.provide('jspb.ExtensionFieldInfo');
+goog.provide('jspb.Message');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.crypt.base64');
+goog.require('goog.json');
+
+// Not needed in compilation units that have no protos with xids.
+goog.forwardDeclare('xid.String');
+
+
+
+/**
+ * Stores information for a single extension field.
+ *
+ * For example, an extension field defined like so:
+ *
+ *     extend BaseMessage {
+ *       optional MyMessage my_field = 123;
+ *     }
+ *
+ * will result in an ExtensionFieldInfo object with these properties:
+ *
+ *     {
+ *       fieldIndex: 123,
+ *       fieldName: {my_field_renamed: 0},
+ *       ctor: proto.example.MyMessage,
+ *       toObjectFn: proto.example.MyMessage.toObject,
+ *       isRepeated: 0
+ *     }
+ *
+ * We include `toObjectFn` to allow the JSCompiler to perform dead-code removal
+ * on unused toObject() methods.
+ *
+ * If an extension field is primitive, ctor and toObjectFn will be null.
+ * isRepeated should be 0 or 1.
+ *
+ * binary{Reader,Writer}Fn and (if message type) binaryMessageSerializeFn are
+ * always provided. binaryReaderFn and binaryWriterFn are references to the
+ * appropriate methods on BinaryReader/BinaryWriter to read/write the value of
+ * this extension, and binaryMessageSerializeFn is a reference to the message
+ * class's .serializeBinary method, if available.
+ *
+ * @param {number} fieldNumber
+ * @param {Object} fieldName This has the extension field name as a property.
+ * @param {?function(new: jspb.Message, Array=)} ctor
+ * @param {?function((boolean|undefined),!jspb.Message):!Object} toObjectFn
+ * @param {number} isRepeated
+ * @param {?function(number,?)=} opt_binaryReaderFn
+ * @param {?function(number,?)|function(number,?,?,?,?,?)=} opt_binaryWriterFn
+ * @param {?function(?,?)=} opt_binaryMessageSerializeFn
+ * @param {?function(?,?)=} opt_binaryMessageDeserializeFn
+ * @param {?boolean=} opt_isPacked
+ * @constructor
+ * @struct
+ * @template T
+ */
+jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
+    isRepeated, opt_binaryReaderFn, opt_binaryWriterFn,
+    opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn,
+    opt_isPacked) {
+  /** @const */
+  this.fieldIndex = fieldNumber;
+  /** @const */
+  this.fieldName = fieldName;
+  /** @const */
+  this.ctor = ctor;
+  /** @const */
+  this.toObjectFn = toObjectFn;
+  /** @const */
+  this.binaryReaderFn = opt_binaryReaderFn;
+  /** @const */
+  this.binaryWriterFn = opt_binaryWriterFn;
+  /** @const */
+  this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn;
+  /** @const */
+  this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn;
+  /** @const */
+  this.isRepeated = isRepeated;
+  /** @const */
+  this.isPacked = opt_isPacked;
+};
+
+
+/**
+ * @return {boolean} Does this field represent a sub Message?
+ */
+jspb.ExtensionFieldInfo.prototype.isMessageType = function() {
+  return !!this.ctor;
+};
+
+
+/**
+ * Base class for all JsPb messages.
+ * @constructor
+ * @struct
+ */
+jspb.Message = function() {
+};
+
+
+/**
+ * @define {boolean} Whether to generate toObject methods for objects. Turn
+ *     this off, if you do not want toObject to be ever used in your project.
+ *     When turning off this flag, consider adding a conformance test that bans
+ *     calling toObject. Enabling this will disable the JSCompiler's ability to
+ *     dead code eliminate fields used in protocol buffers that are never used
+ *     in an application.
+ */
+goog.define('jspb.Message.GENERATE_TO_OBJECT', true);
+
+
+/**
+ * @define {boolean} Whether to generate fromObject methods for objects. Turn
+ *     this off, if you do not want fromObject to be ever used in your project.
+ *     When turning off this flag, consider adding a conformance test that bans
+ *     calling fromObject. Enabling this might disable the JSCompiler's ability
+ *     to dead code eliminate fields used in protocol buffers that are never
+ *     used in an application.
+ *     NOTE: By default no protos actually have a fromObject method. You need to
+ *     add the jspb.generate_from_object options to the proto definition to
+ *     activate the feature.
+ *     By default this is enabled for test code only.
+ */
+goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE);
+
+
+/**
+ * @define {boolean} Turning on this flag does NOT change the behavior of JSPB
+ *     and only affects private internal state. It may, however, break some
+ *     tests that use naive deeply-equals algorithms, because using a proto
+ *     mutates its internal state.
+ *     Projects are advised to turn this flag always on.
+ */
+goog.define('jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS', COMPILED);
+// TODO(b/19419436) Turn this on by default.
+
+
+/**
+ * Does this browser support Uint8Aray typed arrays?
+ * @type {boolean}
+ * @private
+ */
+jspb.Message.SUPPORTS_UINT8ARRAY_ = (typeof Uint8Array == 'function');
+
+
+/**
+ * The internal data array.
+ * @type {!Array}
+ * @protected
+ */
+jspb.Message.prototype.array;
+
+
+/**
+ * Wrappers are the constructed instances of message-type fields. They are built
+ * on demand from the raw array data. Includes message fields, repeated message
+ * fields and extension message fields. Indexed by field number.
+ * @type {Object}
+ * @private
+ */
+jspb.Message.prototype.wrappers_;
+
+
+/**
+ * The object that contains extension fields, if any. This is an object that
+ * maps from a proto field number to the field's value.
+ * @type {Object}
+ * @private
+ */
+jspb.Message.prototype.extensionObject_;
+
+
+/**
+ * Non-extension fields with a field number at or above the pivot are
+ * stored in the extension object (in addition to all extension fields).
+ * @type {number}
+ * @private
+ */
+jspb.Message.prototype.pivot_;
+
+
+/**
+ * The JsPb message_id of this proto.
+ * @type {string|undefined} the message id or undefined if this message
+ *     has no id.
+ * @private
+ */
+jspb.Message.prototype.messageId_;
+
+
+/**
+ * Repeated float or double fields which have been converted to include only
+ * numbers and not strings holding "NaN", "Infinity" and "-Infinity".
+ * @private {!Object<number,boolean>|undefined}
+ */
+jspb.Message.prototype.convertedFloatingPointFields_;
+
+
+/**
+ * The xid of this proto type (The same for all instances of a proto). Provides
+ * a way to identify a proto by stable obfuscated name.
+ * @see {xid}.
+ * Available if {@link jspb.generate_xid} is added as a Message option to
+ * a protocol buffer.
+ * @const {!xid.String|undefined} The xid or undefined if message is
+ *     annotated to generate the xid.
+ */
+jspb.Message.prototype.messageXid;
+
+
+
+/**
+ * Returns the JsPb message_id of this proto.
+ * @return {string|undefined} the message id or undefined if this message
+ *     has no id.
+ */
+jspb.Message.prototype.getJsPbMessageId = function() {
+  return this.messageId_;
+};
+
+
+/**
+ * An offset applied to lookups into this.array to account for the presence or
+ * absence of a messageId at position 0. For response messages, this will be 0.
+ * Otherwise, it will be -1 so that the first array position is not wasted.
+ * @type {number}
+ * @private
+ */
+jspb.Message.prototype.arrayIndexOffset_;
+
+
+/**
+ * Returns the index into msg.array at which the proto field with tag number
+ * fieldNumber will be located.
+ * @param {!jspb.Message} msg Message for which we're calculating an index.
+ * @param {number} fieldNumber The field number.
+ * @return {number} The index.
+ * @private
+ */
+jspb.Message.getIndex_ = function(msg, fieldNumber) {
+  return fieldNumber + msg.arrayIndexOffset_;
+};
+
+
+/**
+ * Initializes a JsPb Message.
+ * @param {!jspb.Message} msg The JsPb proto to modify.
+ * @param {Array|undefined} data An initial data array.
+ * @param {string|number} messageId For response messages, the message id or ''
+ *     if no message id is specified. For non-response messages, 0.
+ * @param {number} suggestedPivot The field number at which to start putting
+ *     fields into the extension object. This is only used if data does not
+ *     contain an extension object already. -1 if no extension object is
+ *     required for this message type.
+ * @param {Array<number>} repeatedFields The message's repeated fields.
+ * @param {Array<!Array<number>>=} opt_oneofFields The fields belonging to
+ *     each of the message's oneof unions.
+ * @protected
+ */
+jspb.Message.initialize = function(
+    msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) {
+  msg.wrappers_ = jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? null : {};
+  if (!data) {
+    data = messageId ? [messageId] : [];
+  }
+  msg.messageId_ = messageId ? String(messageId) : undefined;
+  // If the messageId is 0, this message is not a response message, so we shift
+  // array indices down by 1 so as not to waste the first position in the array,
+  // which would otherwise go unused.
+  msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0;
+  msg.array = data;
+  jspb.Message.materializeExtensionObject_(msg, suggestedPivot);
+  msg.convertedFloatingPointFields_ = {};
+
+  if (repeatedFields) {
+    for (var i = 0; i < repeatedFields.length; i++) {
+      var fieldNumber = repeatedFields[i];
+      if (fieldNumber < msg.pivot_) {
+        var index = jspb.Message.getIndex_(msg, fieldNumber);
+        msg.array[index] = msg.array[index] ||
+            (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
+                jspb.Message.EMPTY_LIST_SENTINEL_ :
+                []);
+      } else {
+        msg.extensionObject_[fieldNumber] =
+            msg.extensionObject_[fieldNumber] ||
+            (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
+                jspb.Message.EMPTY_LIST_SENTINEL_ :
+                []);
+      }
+    }
+  }
+
+  if (opt_oneofFields && opt_oneofFields.length) {
+    // Compute the oneof case for each union. This ensures only one value is
+    // set in the union.
+    goog.array.forEach(
+        opt_oneofFields, goog.partial(jspb.Message.computeOneofCase, msg));
+  }
+};
+
+
+/**
+ * Used to mark empty repeated fields. Serializes to null when serialized
+ * to JSON.
+ * When reading a repeated field readers must check the return value against
+ * this value and return and replace it with a new empty array if it is
+ * present.
+ * @private @const {!Object}
+ */
+jspb.Message.EMPTY_LIST_SENTINEL_ = goog.DEBUG && Object.freeze ?
+    Object.freeze([]) :
+    [];
+
+
+/**
+ * Ensures that the array contains an extension object if necessary.
+ * If the array contains an extension object in its last position, then the
+ * object is kept in place and its position is used as the pivot.  If not, then
+ * create an extension object using suggestedPivot.  If suggestedPivot is -1,
+ * we don't have an extension object at all, in which case all fields are stored
+ * in the array.
+ * @param {!jspb.Message} msg The JsPb proto to modify.
+ * @param {number} suggestedPivot See description for initialize().
+ * @private
+ */
+jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
+  if (msg.array.length) {
+    var foundIndex = msg.array.length - 1;
+    var obj = msg.array[foundIndex];
+    // Normal fields are never objects, so we can be sure that if we find an
+    // object here, then it's the extension object. However, we must ensure that
+    // the object is not an array, since arrays are valid field values.
+    // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug
+    // in Safari on iOS 8. See the description of CL/86511464 for details.
+    if (obj && typeof obj == 'object' && !goog.isArray(obj)) {
+      msg.pivot_ = foundIndex - msg.arrayIndexOffset_;
+      msg.extensionObject_ = obj;
+      return;
+    }
+  }
+  // This complexity exists because we keep all extension fields in the
+  // extensionObject_ regardless of proto field number. Changing this would
+  // simplify the code here, but it would require changing the serialization
+  // format from the server, which is not backwards compatible.
+  // TODO(jshneier): Should we just treat extension fields the same as
+  // non-extension fields, and select whether they appear in the object or in
+  // the array purely based on tag number? This would allow simplifying all the
+  // get/setExtension logic, but it would require the breaking change described
+  // above.
+  if (suggestedPivot > -1) {
+    msg.pivot_ = suggestedPivot;
+    var pivotIndex = jspb.Message.getIndex_(msg, suggestedPivot);
+    if (!jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
+      msg.extensionObject_ = msg.array[pivotIndex] = {};
+    } else {
+      // Initialize to null to avoid changing the shape of the proto when it
+      // gets eventually set.
+      msg.extensionObject_ = null;
+    }
+  } else {
+    msg.pivot_ = Number.MAX_VALUE;
+  }
+};
+
+
+/**
+ * Creates an empty extensionObject_ if non exists.
+ * @param {!jspb.Message} msg The JsPb proto to modify.
+ * @private
+ */
+jspb.Message.maybeInitEmptyExtensionObject_ = function(msg) {
+  var pivotIndex = jspb.Message.getIndex_(msg, msg.pivot_);
+  if (!msg.array[pivotIndex]) {
+    msg.extensionObject_ = msg.array[pivotIndex] = {};
+  }
+};
+
+
+/**
+ * Converts a JsPb repeated message field into an object list.
+ * @param {!Array<T>} field The repeated message field to be
+ *     converted.
+ * @param {?function(boolean=): Object|
+ *     function((boolean|undefined),T): Object} toObjectFn The toObject
+ *     function for this field.  We need to pass this for effective dead code
+ *     removal.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Array<Object>} An array of converted message objects.
+ * @template T
+ */
+jspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) {
+  // Not using goog.array.map in the generated code to keep it small.
+  // And not using it here to avoid a function call.
+  var result = [];
+  for (var i = 0; i < field.length; i++) {
+    result[i] = toObjectFn.call(field[i], opt_includeInstance,
+      /** @type {!jspb.Message} */ (field[i]));
+  }
+  return result;
+};
+
+
+/**
+ * Adds a proto's extension data to a Soy rendering object.
+ * @param {!jspb.Message} proto The proto whose extensions to convert.
+ * @param {!Object} obj The Soy object to add converted extension data to.
+ * @param {!Object} extensions The proto class' registered extensions.
+ * @param {function(this:?, jspb.ExtensionFieldInfo) : *} getExtensionFn
+ *     The proto class' getExtension function. Passed for effective dead code
+ *     removal.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ */
+jspb.Message.toObjectExtension = function(proto, obj, extensions,
+    getExtensionFn, opt_includeInstance) {
+  for (var fieldNumber in extensions) {
+    var fieldInfo = extensions[fieldNumber];
+    var value = getExtensionFn.call(proto, fieldInfo);
+    if (value) {
+      for (var name in fieldInfo.fieldName) {
+        if (fieldInfo.fieldName.hasOwnProperty(name)) {
+          break; // the compiled field name
+        }
+      }
+      if (!fieldInfo.toObjectFn) {
+        obj[name] = value;
+      } else {
+        if (fieldInfo.isRepeated) {
+          obj[name] = jspb.Message.toObjectList(
+              /** @type {!Array<jspb.Message>} */ (value),
+              fieldInfo.toObjectFn, opt_includeInstance);
+        } else {
+          obj[name] = fieldInfo.toObjectFn(opt_includeInstance, value);
+        }
+      }
+    }
+  }
+};
+
+
+/**
+ * Writes a proto's extension data to a binary-format output stream.
+ * @param {!jspb.Message} proto The proto whose extensions to convert.
+ * @param {*} writer The binary-format writer to write to.
+ * @param {!Object} extensions The proto class' registered extensions.
+ * @param {function(jspb.ExtensionFieldInfo) : *} getExtensionFn The proto
+ *     class' getExtension function. Passed for effective dead code removal.
+ */
+jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
+    getExtensionFn) {
+  for (var fieldNumber in extensions) {
+    var fieldInfo = extensions[fieldNumber];
+    // The old codegen doesn't add the extra fields to ExtensionFieldInfo, so we
+    // need to gracefully error-out here rather than produce a null dereference
+    // below.
+    if (!fieldInfo.binaryWriterFn) {
+      throw new Error('Message extension present that was generated ' +
+                      'without binary serialization support');
+    }
+    var value = getExtensionFn.call(proto, fieldInfo);
+    if (value) {
+      if (fieldInfo.isMessageType()) {
+        // If the message type of the extension was generated without binary
+        // support, there may not be a binary message serializer function, and
+        // we can't know when we codegen the extending message that the extended
+        // message may require binary support, so we can *only* catch this error
+        // here, at runtime (and this decoupled codegen is the whole point of
+        // extensions!).
+        if (fieldInfo.binaryMessageSerializeFn) {
+          fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex,
+              value, fieldInfo.binaryMessageSerializeFn);
+        } else {
+          throw new Error('Message extension present holding submessage ' +
+                          'without binary support enabled, and message is ' +
+                          'being serialized to binary format');
+        }
+      } else {
+        fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex, value);
+      }
+    }
+  }
+};
+
+
+/**
+ * Reads an extension field from the given reader and, if a valid extension,
+ * sets the extension value.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {{skipField:function(),getFieldNumber:function():number}} reader
+ * @param {!Object} extensions The extensions object.
+ * @param {function(jspb.ExtensionFieldInfo)} getExtensionFn
+ * @param {function(jspb.ExtensionFieldInfo, ?)} setExtensionFn
+ */
+jspb.Message.readBinaryExtension = function(msg, reader, extensions,
+    getExtensionFn, setExtensionFn) {
+  var fieldInfo = extensions[reader.getFieldNumber()];
+  if (!fieldInfo) {
+    reader.skipField();
+    return;
+  }
+  if (!fieldInfo.binaryReaderFn) {
+    throw new Error('Deserializing extension whose generated code does not ' +
+                    'support binary format');
+  }
+
+  var value;
+  if (fieldInfo.isMessageType()) {
+    value = new fieldInfo.ctor();
+    fieldInfo.binaryReaderFn.call(
+        reader, value, fieldInfo.binaryMessageDeserializeFn);
+  } else {
+    // All other types.
+    value = fieldInfo.binaryReaderFn.call(reader);
+  }
+
+  if (fieldInfo.isRepeated && !fieldInfo.isPacked) {
+    var currentList = getExtensionFn.call(msg, fieldInfo);
+    if (!currentList) {
+      setExtensionFn.call(msg, fieldInfo, [value]);
+    } else {
+      currentList.push(value);
+    }
+  } else {
+    setExtensionFn.call(msg, fieldInfo, value);
+  }
+};
+
+
+/**
+ * Gets the value of a non-extension field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {string|number|boolean|Uint8Array|Array|null|undefined}
+ * The field's value.
+ * @protected
+ */
+jspb.Message.getField = function(msg, fieldNumber) {
+  if (fieldNumber < msg.pivot_) {
+    var index = jspb.Message.getIndex_(msg, fieldNumber);
+    var val = msg.array[index];
+    if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+      return msg.array[index] = [];
+    }
+    return val;
+  } else {
+    var val = msg.extensionObject_[fieldNumber];
+    if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+      return msg.extensionObject_[fieldNumber] = [];
+    }
+    return val;
+  }
+};
+
+
+/**
+ * Gets the value of an optional float or double field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {?number|undefined} The field's value.
+ * @protected
+ */
+jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) {
+  var value = jspb.Message.getField(msg, fieldNumber);
+  // Converts "NaN", "Infinity" and "-Infinity" to their corresponding numbers.
+  return value == null ? value : +value;
+};
+
+
+/**
+ * Gets the value of a repeated float or double field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {!Array<number>} The field's value.
+ * @protected
+ */
+jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) {
+  var values = jspb.Message.getField(msg, fieldNumber);
+  if (!msg.convertedFloatingPointFields_) {
+    msg.convertedFloatingPointFields_ = {};
+  }
+  if (!msg.convertedFloatingPointFields_[fieldNumber]) {
+    for (var i = 0; i < values.length; i++) {
+      // Converts "NaN", "Infinity" and "-Infinity" to their corresponding
+      // numbers.
+      values[i] = +values[i];
+    }
+    msg.convertedFloatingPointFields_[fieldNumber] = true;
+  }
+  return /** @type {!Array<number>} */ (values);
+};
+
+
+/**
+ * Coerce a 'bytes' field to a base 64 string.
+ * @param {string|Uint8Array|null} value
+ * @return {?string} The field's coerced value.
+ */
+jspb.Message.bytesAsB64 = function(value) {
+  if (value == null || goog.isString(value)) {
+    return value;
+  }
+  if (jspb.Message.SUPPORTS_UINT8ARRAY_ && value instanceof Uint8Array) {
+    return goog.crypt.base64.encodeByteArray(value);
+  }
+  goog.asserts.fail('Cannot coerce to b64 string: ' + goog.typeOf(value));
+  return null;
+};
+
+
+/**
+ * Coerce a 'bytes' field to a Uint8Array byte buffer.
+ * Note that Uint8Array is not supported on IE versions before 10 nor on Opera
+ * Mini. @see http://caniuse.com/Uint8Array
+ * @param {string|Uint8Array|null} value
+ * @return {?Uint8Array} The field's coerced value.
+ */
+jspb.Message.bytesAsU8 = function(value) {
+  if (value == null || value instanceof Uint8Array) {
+    return value;
+  }
+  if (goog.isString(value)) {
+    return goog.crypt.base64.decodeStringToUint8Array(value);
+  }
+  goog.asserts.fail('Cannot coerce to Uint8Array: ' + goog.typeOf(value));
+  return null;
+};
+
+
+/**
+ * Coerce a repeated 'bytes' field to an array of base 64 strings.
+ * Note: the returned array should be treated as immutable.
+ * @param {!Array<string>|!Array<!Uint8Array>} value
+ * @return {!Array<string?>} The field's coerced value.
+ */
+jspb.Message.bytesListAsB64 = function(value) {
+  jspb.Message.assertConsistentTypes_(value);
+  if (!value.length || goog.isString(value[0])) {
+    return /** @type {!Array<string>} */ (value);
+  }
+  return goog.array.map(value, jspb.Message.bytesAsB64);
+};
+
+
+/**
+ * Coerce a repeated 'bytes' field to an array of Uint8Array byte buffers.
+ * Note: the returned array should be treated as immutable.
+ * Note that Uint8Array is not supported on IE versions before 10 nor on Opera
+ * Mini. @see http://caniuse.com/Uint8Array
+ * @param {!Array<string>|!Array<!Uint8Array>} value
+ * @return {!Array<Uint8Array?>} The field's coerced value.
+ */
+jspb.Message.bytesListAsU8 = function(value) {
+  jspb.Message.assertConsistentTypes_(value);
+  if (!value.length || value[0] instanceof Uint8Array) {
+    return /** @type {!Array<!Uint8Array>} */ (value);
+  }
+  return goog.array.map(value, jspb.Message.bytesAsU8);
+};
+
+
+/**
+ * Asserts that all elements of an array are of the same type.
+ * @param {Array?} array The array to test.
+ * @private
+ */
+jspb.Message.assertConsistentTypes_ = function(array) {
+  if (goog.DEBUG && array && array.length > 1) {
+    var expected = goog.typeOf(array[0]);
+    goog.array.forEach(array, function(e) {
+      if (goog.typeOf(e) != expected) {
+        goog.asserts.fail('Inconsistent type in JSPB repeated field array. ' +
+            'Got ' + goog.typeOf(e) + ' expected ' + expected);
+      }
+    });
+  }
+};
+
+
+/**
+ * Gets the value of a non-extension primitive field, with proto3 (non-nullable
+ * primitives) semantics. Returns `defaultValue` if the field is not otherwise
+ * set.
+ * @template T
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {T} defaultValue The default value.
+ * @return {T} The field's value.
+ * @protected
+ */
+jspb.Message.getFieldProto3 = function(msg, fieldNumber, defaultValue) {
+  var value = jspb.Message.getField(msg, fieldNumber);
+  if (value == null) {
+    return defaultValue;
+  } else {
+    return value;
+  }
+};
+
+
+/**
+ * Sets the value of a non-extension field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {string|number|boolean|Uint8Array|Array|undefined} value New value
+ * @protected
+ */
+jspb.Message.setField = function(msg, fieldNumber, value) {
+  if (fieldNumber < msg.pivot_) {
+    msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
+  } else {
+    msg.extensionObject_[fieldNumber] = value;
+  }
+};
+
+
+/**
+ * Sets the value of a field in a oneof union and clears all other fields in
+ * the union.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {!Array<number>} oneof The fields belonging to the union.
+ * @param {string|number|boolean|Uint8Array|Array|undefined} value New value
+ * @protected
+ */
+jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) {
+  var currentCase = jspb.Message.computeOneofCase(msg, oneof);
+  if (currentCase && currentCase !== fieldNumber && value !== undefined) {
+    if (msg.wrappers_ && currentCase in msg.wrappers_) {
+      msg.wrappers_[currentCase] = undefined;
+    }
+    jspb.Message.setField(msg, currentCase, undefined);
+  }
+  jspb.Message.setField(msg, fieldNumber, value);
+};
+
+
+/**
+ * Computes the selection in a oneof group for the given message, ensuring
+ * only one field is set in the process.
+ *
+ * According to the protobuf language guide (
+ * https://developers.google.com/protocol-buffers/docs/proto#oneof), "if the
+ * parser encounters multiple members of the same oneof on the wire, only the
+ * last member seen is used in the parsed message." Since JSPB serializes
+ * messages to a JSON array, the "last member seen" will always be the field
+ * with the greatest field number (directly corresponding to the greatest
+ * array index).
+ *
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {!Array<number>} oneof The field numbers belonging to the union.
+ * @return {number} The field number currently set in the union, or 0 if none.
+ * @protected
+ */
+jspb.Message.computeOneofCase = function(msg, oneof) {
+  var oneofField;
+  var oneofValue;
+
+  goog.array.forEach(oneof, function(fieldNumber) {
+    var value = jspb.Message.getField(msg, fieldNumber);
+    if (goog.isDefAndNotNull(value)) {
+      oneofField = fieldNumber;
+      oneofValue = value;
+      jspb.Message.setField(msg, fieldNumber, undefined);
+    }
+  });
+
+  if (oneofField) {
+    // NB: We know the value is unique, so we can call jspb.Message.setField
+    // directly instead of jpsb.Message.setOneofField. Also, setOneofField
+    // calls this function.
+    jspb.Message.setField(msg, oneofField, oneofValue);
+    return oneofField;
+  }
+
+  return 0;
+};
+
+
+/**
+ * Gets and wraps a proto field on access.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {function(new:jspb.Message, Array)} ctor Constructor for the field.
+ * @param {number} fieldNumber The field number.
+ * @param {number=} opt_required True (1) if this is a required field.
+ * @return {jspb.Message} The field as a jspb proto.
+ * @protected
+ */
+jspb.Message.getWrapperField = function(msg, ctor, fieldNumber, opt_required) {
+  // TODO(mwr): Consider copying data and/or arrays.
+  if (!msg.wrappers_) {
+    msg.wrappers_ = {};
+  }
+  if (!msg.wrappers_[fieldNumber]) {
+    var data = /** @type {Array} */ (jspb.Message.getField(msg, fieldNumber));
+    if (opt_required || data) {
+      // TODO(mwr): Remove existence test for always valid default protos.
+      msg.wrappers_[fieldNumber] = new ctor(data);
+    }
+  }
+  return /** @type {jspb.Message} */ (msg.wrappers_[fieldNumber]);
+};
+
+
+/**
+ * Gets and wraps a repeated proto field on access.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {function(new:jspb.Message, Array)} ctor Constructor for the field.
+ * @param {number} fieldNumber The field number.
+ * @return {Array<!jspb.Message>} The repeated field as an array of protos.
+ * @protected
+ */
+jspb.Message.getRepeatedWrapperField = function(msg, ctor, fieldNumber) {
+  if (!msg.wrappers_) {
+    msg.wrappers_ = {};
+  }
+  if (!msg.wrappers_[fieldNumber]) {
+    var data = jspb.Message.getField(msg, fieldNumber);
+    for (var wrappers = [], i = 0; i < data.length; i++) {
+      wrappers[i] = new ctor(data[i]);
+    }
+    msg.wrappers_[fieldNumber] = wrappers;
+  }
+  var val = msg.wrappers_[fieldNumber];
+  if (val == jspb.Message.EMPTY_LIST_SENTINEL_) {
+    val = msg.wrappers_[fieldNumber] = [];
+  }
+  return /** @type {Array<!jspb.Message>} */ (val);
+};
+
+
+/**
+ * Sets a proto field and syncs it to the backing array.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {jspb.Message|undefined} value A new value for this proto field.
+ * @protected
+ */
+jspb.Message.setWrapperField = function(msg, fieldNumber, value) {
+  if (!msg.wrappers_) {
+    msg.wrappers_ = {};
+  }
+  var data = value ? value.toArray() : value;
+  msg.wrappers_[fieldNumber] = value;
+  jspb.Message.setField(msg, fieldNumber, data);
+};
+
+
+/**
+ * Sets a proto field in a oneof union and syncs it to the backing array.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {!Array<number>} oneof The fields belonging to the union.
+ * @param {jspb.Message|undefined} value A new value for this proto field.
+ * @protected
+ */
+jspb.Message.setOneofWrapperField = function(msg, fieldNumber, oneof, value) {
+  if (!msg.wrappers_) {
+    msg.wrappers_ = {};
+  }
+  var data = value ? value.toArray() : value;
+  msg.wrappers_[fieldNumber] = value;
+  jspb.Message.setOneofField(msg, fieldNumber, oneof, data);
+};
+
+
+/**
+ * Sets a repeated proto field and syncs it to the backing array.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {Array<!jspb.Message>|undefined} value An array of protos.
+ * @protected
+ */
+jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) {
+  if (!msg.wrappers_) {
+    msg.wrappers_ = {};
+  }
+  value = value || [];
+  for (var data = [], i = 0; i < value.length; i++) {
+    data[i] = value[i].toArray();
+  }
+  msg.wrappers_[fieldNumber] = value;
+  jspb.Message.setField(msg, fieldNumber, data);
+};
+
+
+/**
+ * Converts a JsPb repeated message field into a map. The map will contain
+ * protos unless an optional toObject function is given, in which case it will
+ * contain objects suitable for Soy rendering.
+ * @param {!Array<T>} field The repeated message field to be
+ *     converted.
+ * @param {function() : string?} mapKeyGetterFn The function to get the key of
+ *     the map.
+ * @param {?function(boolean=): Object|
+ *     function((boolean|undefined),T): Object} opt_toObjectFn The
+ *     toObject function for this field. We need to pass this for effective
+ *     dead code removal.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ *     for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object.<string, Object>} A map of proto or Soy objects.
+ * @template T
+ */
+jspb.Message.toMap = function(
+    field, mapKeyGetterFn, opt_toObjectFn, opt_includeInstance) {
+  var result = {};
+  for (var i = 0; i < field.length; i++) {
+    result[mapKeyGetterFn.call(field[i])] = opt_toObjectFn ?
+        opt_toObjectFn.call(field[i], opt_includeInstance,
+            /** @type {!jspb.Message} */ (field[i])) : field[i];
+  }
+  return result;
+};
+
+
+/**
+ * Returns the internal array of this proto.
+ * <p>Note: If you use this array to construct a second proto, the content
+ * would then be partially shared between the two protos.
+ * @return {!Array} The proto represented as an array.
+ */
+jspb.Message.prototype.toArray = function() {
+  return this.array;
+};
+
+
+
+
+/**
+ * Creates a string representation of the internal data array of this proto.
+ * <p>NOTE: This string is *not* suitable for use in server requests.
+ * @return {string} A string representation of this proto.
+ * @override
+ */
+jspb.Message.prototype.toString = function() {
+  return this.array.toString();
+};
+
+
+/**
+ * Gets the value of the extension field from the extended object.
+ * @param {jspb.ExtensionFieldInfo.<T>} fieldInfo Specifies the field to get.
+ * @return {T} The value of the field.
+ * @template T
+ */
+jspb.Message.prototype.getExtension = function(fieldInfo) {
+  if (!this.extensionObject_) {
+    return undefined;
+  }
+  if (!this.wrappers_) {
+    this.wrappers_ = {};
+  }
+  var fieldNumber = fieldInfo.fieldIndex;
+  if (fieldInfo.isRepeated) {
+    if (fieldInfo.isMessageType()) {
+      if (!this.wrappers_[fieldNumber]) {
+        this.wrappers_[fieldNumber] =
+            goog.array.map(this.extensionObject_[fieldNumber] || [],
+                function(arr) {
+                  return new fieldInfo.ctor(arr);
+                });
+      }
+      return this.wrappers_[fieldNumber];
+    } else {
+      return this.extensionObject_[fieldNumber];
+    }
+  } else {
+    if (fieldInfo.isMessageType()) {
+      if (!this.wrappers_[fieldNumber] && this.extensionObject_[fieldNumber]) {
+        this.wrappers_[fieldNumber] = new fieldInfo.ctor(
+            /** @type {Array|undefined} */ (
+                this.extensionObject_[fieldNumber]));
+      }
+      return this.wrappers_[fieldNumber];
+    } else {
+      return this.extensionObject_[fieldNumber];
+    }
+  }
+};
+
+
+/**
+ * Sets the value of the extension field in the extended object.
+ * @param {jspb.ExtensionFieldInfo} fieldInfo Specifies the field to set.
+ * @param {jspb.Message|string|Uint8Array|number|boolean|Array?} value The value
+ *     to set.
+ */
+jspb.Message.prototype.setExtension = function(fieldInfo, value) {
+  if (!this.wrappers_) {
+    this.wrappers_ = {};
+  }
+  jspb.Message.maybeInitEmptyExtensionObject_(this);
+  var fieldNumber = fieldInfo.fieldIndex;
+  if (fieldInfo.isRepeated) {
+    value = value || [];
+    if (fieldInfo.isMessageType()) {
+      this.wrappers_[fieldNumber] = value;
+      this.extensionObject_[fieldNumber] = goog.array.map(
+          /** @type {Array<jspb.Message>} */ (value), function(msg) {
+        return msg.toArray();
+      });
+    } else {
+      this.extensionObject_[fieldNumber] = value;
+    }
+  } else {
+    if (fieldInfo.isMessageType()) {
+      this.wrappers_[fieldNumber] = value;
+      this.extensionObject_[fieldNumber] = value ? value.toArray() : value;
+    } else {
+      this.extensionObject_[fieldNumber] = value;
+    }
+  }
+};
+
+
+/**
+ * Creates a difference object between two messages.
+ *
+ * The result will contain the top-level fields of m2 that differ from those of
+ * m1 at any level of nesting. No data is cloned, the result object will
+ * share its top-level elements with m2 (but not with m1).
+ *
+ * Note that repeated fields should not have null/undefined elements, but if
+ * they do, this operation will treat repeated fields of different length as
+ * the same if the only difference between them is due to trailing
+ * null/undefined values.
+ *
+ * @param {!jspb.Message} m1 The first message object.
+ * @param {!jspb.Message} m2 The second message object.
+ * @return {!jspb.Message} The difference returned as a proto message.
+ *     Note that the returned message may be missing required fields. This is
+ *     currently tolerated in Js, but would cause an error if you tried to
+ *     send such a proto to the server. You can access the raw difference
+ *     array with result.toArray().
+ * @throws {Error} If the messages are responses with different types.
+ */
+jspb.Message.difference = function(m1, m2) {
+  if (!(m1 instanceof m2.constructor)) {
+    throw new Error('Messages have different types.');
+  }
+  var arr1 = m1.toArray();
+  var arr2 = m2.toArray();
+  var res = [];
+  var start = 0;
+  var length = arr1.length > arr2.length ? arr1.length : arr2.length;
+  if (m1.getJsPbMessageId()) {
+    res[0] = m1.getJsPbMessageId();
+    start = 1;
+  }
+  for (var i = start; i < length; i++) {
+    if (!jspb.Message.compareFields(arr1[i], arr2[i])) {
+      res[i] = arr2[i];
+    }
+  }
+  return new m1.constructor(res);
+};
+
+
+/**
+ * Tests whether two messages are equal.
+ * @param {jspb.Message|undefined} m1 The first message object.
+ * @param {jspb.Message|undefined} m2 The second message object.
+ * @return {boolean} true if both messages are null/undefined, or if both are
+ *     of the same type and have the same field values.
+ */
+jspb.Message.equals = function(m1, m2) {
+  return m1 == m2 || (!!(m1 && m2) && (m1 instanceof m2.constructor) &&
+      jspb.Message.compareFields(m1.toArray(), m2.toArray()));
+};
+
+
+/**
+ * Compares two message extension fields recursively.
+ * @param {!Object} extension1 The first field.
+ * @param {!Object} extension2 The second field.
+ * @return {boolean} true if the extensions are null/undefined, or otherwise
+ *     equal.
+ */
+jspb.Message.compareExtensions = function(extension1, extension2) {
+  extension1 = extension1 || {};
+  extension2 = extension2 || {};
+
+  var keys = {};
+  for (var name in extension1) {
+    keys[name] = 0;
+  }
+  for (var name in extension2) {
+    keys[name] = 0;
+  }
+  for (name in keys) {
+    if (!jspb.Message.compareFields(extension1[name], extension2[name])) {
+      return false;
+    }
+  }
+  return true;
+};
+
+
+/**
+ * Compares two message fields recursively.
+ * @param {*} field1 The first field.
+ * @param {*} field2 The second field.
+ * @return {boolean} true if the fields are null/undefined, or otherwise equal.
+ */
+jspb.Message.compareFields = function(field1, field2) {
+  // If the fields are trivially equal, they're equal.
+  if (field1 == field2) return true;
+
+  // If the fields aren't trivially equal and one of them isn't an object,
+  // they can't possibly be equal.
+  if (!goog.isObject(field1) || !goog.isObject(field2)) {
+    return false;
+  }
+
+  // We have two objects. If they're different types, they're not equal.
+  field1 = /** @type {!Object} */(field1);
+  field2 = /** @type {!Object} */(field2);
+  if (field1.constructor != field2.constructor) return false;
+
+  // If both are Uint8Arrays, compare them element-by-element.
+  if (jspb.Message.SUPPORTS_UINT8ARRAY_ && field1.constructor === Uint8Array) {
+    var bytes1 = /** @type {!Uint8Array} */(field1);
+    var bytes2 = /** @type {!Uint8Array} */(field2);
+    if (bytes1.length != bytes2.length) return false;
+    for (var i = 0; i < bytes1.length; i++) {
+      if (bytes1[i] != bytes2[i]) return false;
+    }
+    return true;
+  }
+
+  // If they're both Arrays, compare them element by element except for the
+  // optional extension objects at the end, which we compare separately.
+  if (field1.constructor === Array) {
+    var extension1 = undefined;
+    var extension2 = undefined;
+
+    var length = Math.max(field1.length, field2.length);
+    for (var i = 0; i < length; i++) {
+      var val1 = field1[i];
+      var val2 = field2[i];
+
+      if (val1 && (val1.constructor == Object)) {
+        goog.asserts.assert(extension1 === undefined);
+        goog.asserts.assert(i === field1.length - 1);
+        extension1 = val1;
+        val1 = undefined;
+      }
+
+      if (val2 && (val2.constructor == Object)) {
+        goog.asserts.assert(extension2 === undefined);
+        goog.asserts.assert(i === field2.length - 1);
+        extension2 = val2;
+        val2 = undefined;
+      }
+
+      if (!jspb.Message.compareFields(val1, val2)) {
+        return false;
+      }
+    }
+
+    if (extension1 || extension2) {
+      extension1 = extension1 || {};
+      extension2 = extension2 || {};
+      return jspb.Message.compareExtensions(extension1, extension2);
+    }
+
+    return true;
+  }
+
+  // If they're both plain Objects (i.e. extensions), compare them as
+  // extensions.
+  if (field1.constructor === Object) {
+    return jspb.Message.compareExtensions(field1, field2);
+  }
+
+  throw new Error('Invalid type in JSPB array');
+};
+
+
+/**
+ * Static clone function. NOTE: A type-safe method called "cloneMessage" exists
+ * on each generated JsPb class. Do not call this function directly.
+ * @param {!jspb.Message} msg A message to clone.
+ * @return {!jspb.Message} A deep clone of the given message.
+ */
+jspb.Message.clone = function(msg) {
+  // Although we could include the wrappers, we leave them out here.
+  return jspb.Message.cloneMessage(msg);
+};
+
+
+/**
+ * @param {!jspb.Message} msg A message to clone.
+ * @return {!jspb.Message} A deep clone of the given message.
+ * @protected
+ */
+jspb.Message.cloneMessage = function(msg) {
+  // Although we could include the wrappers, we leave them out here.
+  return new msg.constructor(jspb.Message.clone_(msg.toArray()));
+};
+
+
+/**
+ * Takes 2 messages of the same type and copies the contents of the first
+ * message into the second. After this the 2 messages will equals in terms of
+ * value semantics but share no state. All data in the destination message will
+ * be overridden.
+ *
+ * @param {MESSAGE} fromMessage Message that will be copied into toMessage.
+ * @param {MESSAGE} toMessage Message which will receive a copy of fromMessage
+ *     as its contents.
+ * @template MESSAGE
+ */
+jspb.Message.copyInto = function(fromMessage, toMessage) {
+  goog.asserts.assertInstanceof(fromMessage, jspb.Message);
+  goog.asserts.assertInstanceof(toMessage, jspb.Message);
+  goog.asserts.assert(fromMessage.constructor == toMessage.constructor,
+      'Copy source and target message should have the same type.');
+  var copyOfFrom = jspb.Message.clone(fromMessage);
+
+  var to = toMessage.toArray();
+  var from = copyOfFrom.toArray();
+
+  // Empty destination in case it has more values at the end of the array.
+  to.length = 0;
+  // and then copy everything from the new to the existing message.
+  for (var i = 0; i < from.length; i++) {
+    to[i] = from[i];
+  }
+
+  // This is either null or empty for a fresh copy.
+  toMessage.wrappers_ = copyOfFrom.wrappers_;
+  // Just a reference into the shared array.
+  toMessage.extensionObject_ = copyOfFrom.extensionObject_;
+};
+
+
+/**
+ * Helper for cloning an internal JsPb object.
+ * @param {!Object} obj A JsPb object, eg, a field, to be cloned.
+ * @return {!Object} A clone of the input object.
+ * @private
+ */
+jspb.Message.clone_ = function(obj) {
+  var o;
+  if (goog.isArray(obj)) {
+    // Allocate array of correct size.
+    var clonedArray = new Array(obj.length);
+    // Use array iteration where possible because it is faster than for-in.
+    for (var i = 0; i < obj.length; i++) {
+      if ((o = obj[i]) != null) {
+        clonedArray[i] = typeof o == 'object' ? jspb.Message.clone_(o) : o;
+      }
+    }
+    return clonedArray;
+  }
+  var clone = {};
+  for (var key in obj) {
+    if ((o = obj[key]) != null) {
+      clone[key] = typeof o == 'object' ? jspb.Message.clone_(o) : o;
+    }
+  }
+  return clone;
+};
+
+
+/**
+ * Registers a JsPb message type id with its constructor.
+ * @param {string} id The id for this type of message.
+ * @param {Function} constructor The message constructor.
+ */
+jspb.Message.registerMessageType = function(id, constructor) {
+  jspb.Message.registry_[id] = constructor;
+  // This is needed so we can later access messageId directly on the contructor,
+  // otherwise it is not available due to 'property collapsing' by the compiler.
+  constructor.messageId = id;
+};
+
+
+/**
+ * The registry of message ids to message constructors.
+ * @private
+ */
+jspb.Message.registry_ = {};
+
+
+/**
+ * The extensions registered on MessageSet. This is a map of extension
+ * field number to field info object. This should be considered as a
+ * private API.
+ *
+ * This is similar to [jspb class name].extensions object for
+ * non-MessageSet. We special case MessageSet so that we do not need
+ * to goog.require MessageSet from classes that extends MessageSet.
+ *
+ * @type {!Object.<number, jspb.ExtensionFieldInfo>}
+ */
+jspb.Message.messageSetExtensions = {};
diff --git a/src/third_party/protobuf-3/js/message_test.js b/src/third_party/protobuf-3/js/message_test.js
new file mode 100644
index 0000000..01add5f
--- /dev/null
+++ b/src/third_party/protobuf-3/js/message_test.js
@@ -0,0 +1,1010 @@
+// 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.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.setTestOnly();
+
+goog.require('goog.json');
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: google-protobuf jspb
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: test5_pb proto.jspb.exttest.beta
+goog.require('proto.jspb.exttest.beta.floatingStrField');
+
+// CommonJS-LoadFromFile: test3_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgField');
+
+// CommonJS-LoadFromFile: test4_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgFieldTwo');
+
+// CommonJS-LoadFromFile: test_pb proto.jspb.test
+goog.require('proto.jspb.test.CloneExtension');
+goog.require('proto.jspb.test.Complex');
+goog.require('proto.jspb.test.DefaultValues');
+goog.require('proto.jspb.test.Empty');
+goog.require('proto.jspb.test.EnumContainer');
+goog.require('proto.jspb.test.floatingMsgField');
+goog.require('proto.jspb.test.FloatingPointFields');
+goog.require('proto.jspb.test.floatingStrField');
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IndirectExtension');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.OptionalFields');
+goog.require('proto.jspb.test.OuterEnum');
+goog.require('proto.jspb.test.OuterMessage.Complex');
+goog.require('proto.jspb.test.Simple1');
+goog.require('proto.jspb.test.Simple2');
+goog.require('proto.jspb.test.SpecialCases');
+goog.require('proto.jspb.test.TestClone');
+goog.require('proto.jspb.test.TestGroup');
+goog.require('proto.jspb.test.TestGroup1');
+goog.require('proto.jspb.test.TestMessageWithOneof');
+goog.require('proto.jspb.test.TestReservedNames');
+goog.require('proto.jspb.test.TestReservedNamesExtension');
+
+// CommonJS-LoadFromFile: test2_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtensionMessage');
+goog.require('proto.jspb.test.TestExtensionsMessage');
+
+
+
+
+describe('Message test suite', function() {
+  it('testEmptyProto', function() {
+    var empty1 = new proto.jspb.test.Empty([]);
+    var empty2 = new proto.jspb.test.Empty([]);
+    assertObjectEquals({}, empty1.toObject());
+    assertObjectEquals('Message should not be corrupted:', empty2, empty1);
+  });
+
+  it('testTopLevelEnum', function() {
+    var response = new proto.jspb.test.EnumContainer([]);
+    response.setOuterEnum(proto.jspb.test.OuterEnum.FOO);
+    assertEquals(proto.jspb.test.OuterEnum.FOO, response.getOuterEnum());
+  });
+
+  it('testByteStrings', function() {
+    var data = new proto.jspb.test.DefaultValues([]);
+    data.setBytesField('some_bytes');
+    assertEquals('some_bytes', data.getBytesField());
+  });
+
+  it('testComplexConversion', function() {
+    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var foo = new proto.jspb.test.Complex(data1);
+    var bar = new proto.jspb.test.Complex(data2);
+    var result = foo.toObject();
+    assertObjectEquals({
+      aString: 'a',
+      anOutOfOrderBool: 1,
+      aNestedMessage: {
+        anInt: 11
+      },
+      aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
+      aRepeatedStringList: ['s1', 's2']
+    }, result);
+
+    // Now test with the jspb instances included.
+    result = foo.toObject(true /* opt_includeInstance */);
+    assertObjectEquals({
+      aString: 'a',
+      anOutOfOrderBool: 1,
+      aNestedMessage: {
+        anInt: 11,
+        $jspbMessageInstance: foo.getANestedMessage()
+      },
+      aRepeatedMessageList: [
+        {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
+        {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
+      ],
+      aRepeatedStringList: ['s1', 's2'],
+      $jspbMessageInstance: foo
+    }, result);
+
+  });
+
+  it('testMissingFields', function() {
+    var foo = new proto.jspb.test.Complex([
+        undefined, undefined, undefined, [],
+        undefined, undefined, undefined, undefined]);
+    var bar = new proto.jspb.test.Complex([
+        undefined, undefined, undefined, [],
+        undefined, undefined, undefined, undefined]);
+    var result = foo.toObject();
+    assertObjectEquals({
+      aString: undefined,
+      anOutOfOrderBool: undefined,
+      aNestedMessage: {
+        anInt: undefined
+      },
+      // Note: JsPb converts undefined repeated fields to empty arrays.
+      aRepeatedMessageList: [],
+      aRepeatedStringList: []
+    }, result);
+
+  });
+
+  it('testNestedComplexMessage', function() {
+    // Instantiate the message and set a unique field, just to ensure that we
+    // are not getting jspb.test.Complex instead.
+    var msg = new proto.jspb.test.OuterMessage.Complex();
+    msg.setInnerComplexField(5);
+  });
+
+  it('testSpecialCases', function() {
+    // Note: Some property names are reserved in JavaScript.
+    // These names are converted to the Js property named pb_<reserved_name>.
+    var special =
+        new proto.jspb.test.SpecialCases(['normal', 'default', 'function',
+        'var']);
+    var result = special.toObject();
+    assertObjectEquals({
+      normal: 'normal',
+      pb_default: 'default',
+      pb_function: 'function',
+      pb_var: 'var'
+    }, result);
+  });
+
+  it('testDefaultValues', function() {
+    var defaultString = "default<>\'\"abc";
+    var response = new proto.jspb.test.DefaultValues();
+
+    // Test toObject
+    var expectedObject = {
+      stringField: defaultString,
+      boolField: true,
+      intField: 11,
+      enumField: 13,
+      emptyField: '',
+      bytesField: 'bW9v'
+    };
+    assertObjectEquals(expectedObject, response.toObject());
+
+
+    // Test getters
+    response = new proto.jspb.test.DefaultValues();
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertEquals('', response.getEmptyField());
+    assertEquals('bW9v', response.getBytesField());
+
+    function makeDefault(values) {
+      return new proto.jspb.test.DefaultValues(values);
+    }
+
+    // Test with undefined values,
+    // Use push to workaround IE treating undefined array elements as holes.
+    response = makeDefault([undefined, undefined, undefined, undefined]);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+
+    // Test with null values, as would be returned by a JSON serializer.
+    response = makeDefault([null, null, null, null]);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+
+    // Test with false-like values.
+    response = makeDefault(['', false, 0, 0]);
+    assertEquals('', response.getStringField());
+    assertEquals(false, response.getBoolField());
+    assertEquals(true, response.getIntField() == 0);
+    assertEquals(true, response.getEnumField() == 0);
+
+    // Test that clearing the values reverts them to the default state.
+    response = makeDefault(['blah', false, 111, 77]);
+    response.clearStringField(); response.clearBoolField();
+    response.clearIntField(); response.clearEnumField();
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+
+    // Test that setFoo(null) clears the values.
+    response = makeDefault(['blah', false, 111, 77]);
+    response.setStringField(null); response.setBoolField(null);
+    response.setIntField(undefined); response.setEnumField(undefined);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+  });
+
+  it('testMessageRegistration', function() {
+    // goog.require(SomeResponse) will include its library, which will in
+    // turn add SomeResponse to the message registry.
+    assertEquals(jspb.Message.registry_['res'], proto.jspb.test.SomeResponse);
+  });
+
+  it('testClearFields', function() {
+    // We don't set 'proper' defaults, rather, bools, strings,
+    // etc, are cleared to undefined or null and take on the Javascript
+    // meaning for that value. Repeated fields are set to [] when cleared.
+    var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
+    var foo = new proto.jspb.test.OptionalFields(data);
+    foo.clearAString();
+    foo.clearABool();
+    foo.clearANestedMessage();
+    foo.clearARepeatedMessageList();
+    foo.clearARepeatedStringList();
+    assertUndefined(foo.getAString());
+    assertUndefined(foo.getABool());
+    assertUndefined(foo.getANestedMessage());
+    assertObjectEquals([], foo.getARepeatedMessageList());
+    assertObjectEquals([], foo.getARepeatedStringList());
+    // NOTE: We want the missing fields in 'expected' to be undefined,
+    // but we actually get a sparse array instead. We could use something
+    // like [1,undefined,2] to avoid this, except that this is still
+    // sparse on IE. No comment...
+    var expected = [,,, [], []];
+    expected[0] = expected[1] = expected[2] = undefined;
+    assertObjectEquals(expected, foo.toArray());
+
+    // Test set(null). We could deprecated this in favor of clear(), but
+    // it's also convenient to have.
+    data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
+    foo = new proto.jspb.test.OptionalFields(data);
+    foo.setAString(null);
+    foo.setABool(null);
+    foo.setANestedMessage(null);
+    foo.setARepeatedMessageList(null);
+    foo.setARepeatedStringList(null);
+    assertNull(foo.getAString());
+    assertNull(foo.getABool());
+    assertNull(foo.getANestedMessage());
+    assertObjectEquals([], foo.getARepeatedMessageList());
+    assertObjectEquals([], foo.getARepeatedStringList());
+    assertObjectEquals([null, null, null, [], []], foo.toArray());
+
+    // Test set(undefined). Again, not something we really need, and not
+    // supported directly by our typing, but it should 'do the right thing'.
+    data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
+    foo = new proto.jspb.test.OptionalFields(data);
+    foo.setAString(undefined);
+    foo.setABool(undefined);
+    foo.setANestedMessage(undefined);
+    foo.setARepeatedMessageList(undefined);
+    foo.setARepeatedStringList(undefined);
+    assertUndefined(foo.getAString());
+    assertUndefined(foo.getABool());
+    assertUndefined(foo.getANestedMessage());
+    assertObjectEquals([], foo.getARepeatedMessageList());
+    assertObjectEquals([], foo.getARepeatedStringList());
+    expected = [,,, [], []];
+    expected[0] = expected[1] = expected[2] = undefined;
+    assertObjectEquals(expected, foo.toArray());
+  });
+
+  it('testDifferenceRawObject', function() {
+    var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
+    var p2 = new proto.jspb.test.HasExtensions(['hi', 'what',
+                                               {1000: 'unique'}]);
+    var diff = /** @type {proto.jspb.test.HasExtensions} */
+        (jspb.Message.difference(p1, p2));
+    assertUndefined(diff.getStr1());
+    assertEquals('what', diff.getStr2());
+    assertUndefined(diff.getStr3());
+    assertEquals('unique', diff.extensionObject_[1000]);
+  });
+
+  it('testEqualsSimple', function() {
+    var s1 = new proto.jspb.test.Simple1(['hi']);
+    assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
+    assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
+    var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', ['hello']])));
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', ['hello', undefined,
+                                            undefined, undefined]])));
+    assertFalse(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['no', ['hello']])));
+    // Test with messages of different types
+    var s2 = new proto.jspb.test.Simple2(['hi']);
+    assertFalse(jspb.Message.equals(s1, s2));
+  });
+
+  it('testEquals_softComparison', function() {
+    var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
+    assertTrue(jspb.Message.equals(s1,
+        new proto.jspb.test.Simple1(['hi', []])));
+
+    var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', [], 1])));
+  });
+
+  it('testEqualsComplex', function() {
+    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1];
+    var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1];
+    var data4 = ['hi'];
+    var c1a = new proto.jspb.test.Complex(data1);
+    var c1b = new proto.jspb.test.Complex(data1);
+    var c2 = new proto.jspb.test.Complex(data2);
+    var c3 = new proto.jspb.test.Complex(data3);
+    var s1 = new proto.jspb.test.Simple1(data4);
+
+    assertTrue(jspb.Message.equals(c1a, c1b));
+    assertFalse(jspb.Message.equals(c1a, c2));
+    assertFalse(jspb.Message.equals(c2, c3));
+    assertFalse(jspb.Message.equals(c1a, s1));
+  });
+
+  it('testEqualsExtensionsConstructed', function() {
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([]),
+        new proto.jspb.test.HasExtensions([{}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+    ));
+    assertFalse(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+    ));
+  });
+
+  it('testEqualsExtensionsUnconstructed', function() {
+    assertTrue(jspb.Message.compareFields([], [{}]));
+    assertTrue(jspb.Message.compareFields([,,, {}], []));
+    assertTrue(jspb.Message.compareFields([,,, {}], [,, {}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+    assertFalse(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'b'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+  });
+
+  it('testToMap', function() {
+    var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
+    var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
+    var soymap = jspb.Message.toMap([p1, p2],
+        proto.jspb.test.Simple1.prototype.getAString,
+        proto.jspb.test.Simple1.prototype.toObject);
+    assertEquals('k', soymap['k'].aString);
+    assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
+    var protomap = jspb.Message.toMap([p1, p2],
+        proto.jspb.test.Simple1.prototype.getAString);
+    assertEquals('k', protomap['k'].getAString());
+    assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
+  });
+
+  it('testClone', function() {
+    var original = new proto.jspb.test.TestClone();
+    original.setStr('v1');
+    var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+    var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+    var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+    original.setSimple1(simple1);
+    original.setSimple2List([simple2, simple3]);
+    var extension = new proto.jspb.test.CloneExtension();
+    extension.setExt('e1');
+    original.setExtension(proto.jspb.test.IsExtension.extField, extension);
+    var clone = original.cloneMessage();
+    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]],,, { 100: [, 'e1'] }],
+        clone.toArray());
+    clone.setStr('v2');
+    var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
+    var simple5 = new proto.jspb.test.Simple1(['a2', ['b2', 'c2']]);
+    var simple6 = new proto.jspb.test.Simple1(['a3', ['b3', 'c3']]);
+    clone.setSimple1(simple4);
+    clone.setSimple2List([simple5, simple6]);
+    var newExtension = new proto.jspb.test.CloneExtension();
+    newExtension.setExt('e2');
+    clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
+    assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],,
+      [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]],,, { 100: [, 'e2'] }],
+        clone.toArray());
+    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]],,, { 100: [, 'e1'] }],
+        original.toArray());
+  });
+
+  it('testCopyInto', function() {
+    var original = new proto.jspb.test.TestClone();
+    original.setStr('v1');
+    var dest = new proto.jspb.test.TestClone();
+    dest.setStr('override');
+    var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+    var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+    var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+    var destSimple1 = new proto.jspb.test.Simple1(['ox1', ['oy1', 'oz1']]);
+    var destSimple2 = new proto.jspb.test.Simple1(['ox2', ['oy2', 'oz2']]);
+    var destSimple3 = new proto.jspb.test.Simple1(['ox3', ['oy3', 'oz3']]);
+    original.setSimple1(simple1);
+    original.setSimple2List([simple2, simple3]);
+    dest.setSimple1(destSimple1);
+    dest.setSimple2List([destSimple2, destSimple3]);
+    var extension = new proto.jspb.test.CloneExtension();
+    extension.setExt('e1');
+    original.setExtension(proto.jspb.test.CloneExtension.extField, extension);
+
+    jspb.Message.copyInto(original, dest);
+    assertArrayEquals(original.toArray(), dest.toArray());
+    assertEquals('x1', dest.getSimple1().getAString());
+    assertEquals('e1',
+        dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
+    dest.getSimple1().setAString('new value');
+    assertNotEquals(dest.getSimple1().getAString(),
+        original.getSimple1().getAString());
+    dest.getExtension(proto.jspb.test.CloneExtension.extField).
+        setExt('new value');
+    assertNotEquals(
+        dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
+        original.getExtension(
+            proto.jspb.test.CloneExtension.extField).getExt());
+  });
+
+  it('testCopyInto_notSameType', function() {
+    var a = new proto.jspb.test.TestClone();
+    var b = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+
+    var e = assertThrows(function() {
+      jspb.Message.copyInto(a, b);
+    });
+    assertContains('should have the same type', e.message);
+  });
+
+  it('testExtensions', function() {
+    var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+    var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+                            extension2);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+        ['a', 'b']);
+    var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+    var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList,
+        [s1, s2]);
+    assertObjectEquals(extension1,
+        extendable.getExtension(proto.jspb.test.IsExtension.extField));
+    assertObjectEquals(extension2,
+        extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+    assertObjectEquals('xyzzy',
+        extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+    assertObjectEquals(['a', 'b'], extendable.getExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList));
+    assertObjectEquals([s1, s2], extendable.getExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList));
+    // Not supported yet, but it should work...
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
+    assertNull(
+        extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, null);
+    assertNull(extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+
+
+    // Extension fields with jspb.ignore = true are ignored.
+    assertUndefined(proto.jspb.test.IndirectExtension['ignored']);
+    assertUndefined(proto.jspb.test.HasExtensions['ignoredFloating']);
+  });
+
+  it('testFloatingExtensions', function() {
+    // From an autogenerated container.
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+    extendable.setExtension(proto.jspb.test.simple1, extension);
+    assertObjectEquals(extension,
+        extendable.getExtension(proto.jspb.test.simple1));
+
+    // From _lib mode.
+    extension = new proto.jspb.test.ExtensionMessage(['s1']);
+    extendable = new proto.jspb.test.TestExtensionsMessage([16]);
+    extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
+    extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
+    assertObjectEquals(extension,
+        extendable.getExtension(proto.jspb.test.floatingMsgField));
+    assertObjectEquals('s2',
+        extendable.getExtension(proto.jspb.test.floatingStrField));
+    assertNotUndefined(proto.jspb.exttest.floatingMsgField);
+    assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
+    assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
+  });
+
+  it('testToObject_extendedObject', function() {
+    var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+    var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+                            extension2);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+        ['a', 'b']);
+    var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
+    var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList,
+        [s1, s2]);
+    assertObjectEquals({
+      str1: 'v1', str2: 'v2', str3: 'v3',
+      extField: { ext1: 'ext1field' },
+      simple: {
+        aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true
+      },
+      str: 'xyzzy',
+      repeatedStrList: ['a', 'b'],
+      repeatedSimpleList: [
+        { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
+        { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
+      ]
+    }, extendable.toObject());
+
+    // Now, with instances included.
+    assertObjectEquals({
+      str1: 'v1', str2: 'v2', str3: 'v3',
+      extField: {
+        ext1: 'ext1field',
+        $jspbMessageInstance:
+            extendable.getExtension(proto.jspb.test.IsExtension.extField)
+      },
+      simple: {
+        aString: 'str',
+        aRepeatedStringList: ['s1', 's2'],
+        aBoolean: true,
+        $jspbMessageInstance:
+            extendable.getExtension(proto.jspb.test.IndirectExtension.simple)
+      },
+      str: 'xyzzy',
+      repeatedStrList: ['a', 'b'],
+      repeatedSimpleList: [{
+        aString: 'foo',
+        aRepeatedStringList: ['s1', 's2'],
+        aBoolean: true,
+        $jspbMessageInstance: s1
+      }, {
+        aString: 'bar',
+        aRepeatedStringList: ['t1', 't2'],
+        aBoolean: false,
+        $jspbMessageInstance: s2
+      }],
+      $jspbMessageInstance: extendable
+    }, extendable.toObject(true /* opt_includeInstance */));
+  });
+
+  it('testInitialization_emptyArray', function() {
+    var msg = new proto.jspb.test.HasExtensions([]);
+    if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
+      assertArrayEquals([], msg.toArray());
+    } else {
+      // Extension object is created past all regular fields.
+      assertArrayEquals([,,, {}], msg.toArray());
+    }
+  });
+
+  it('testInitialization_justExtensionObject', function() {
+    var msg = new proto.jspb.test.Empty([{1: 'hi'}]);
+    // The extensionObject is not moved from its original location.
+    assertArrayEquals([{1: 'hi'}], msg.toArray());
+  });
+
+  it('testInitialization_incompleteList', function() {
+    var msg = new proto.jspb.test.Empty([1, {4: 'hi'}]);
+    // The extensionObject is not moved from its original location.
+    assertArrayEquals([1, {4: 'hi'}], msg.toArray());
+  });
+
+  it('testInitialization_forwardCompatible', function() {
+    var msg = new proto.jspb.test.Empty([1, 2, 3, {1: 'hi'}]);
+    assertArrayEquals([1, 2, 3, {1: 'hi'}], msg.toArray());
+  });
+
+  it('testExtendedMessageEnsureObject', function() {
+    var data = new proto.jspb.test.HasExtensions(['str1',
+        {'a_key': 'an_object'}]);
+    assertEquals('an_object', data.extensionObject_['a_key']);
+  });
+
+  it('testToObject_hasExtensionField', function() {
+    var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+    var obj = data.toObject();
+    assertEquals('str1', obj.str1);
+    assertEquals('ext1', obj.extField.ext1);
+  });
+
+  it('testGetExtension', function() {
+    var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+    assertEquals('str1', data.getStr1());
+    var extension = data.getExtension(proto.jspb.test.IsExtension.extField);
+    assertNotNull(extension);
+    assertEquals('ext1', extension.getExt1());
+  });
+
+  it('testSetExtension', function() {
+    var data = new proto.jspb.test.HasExtensions();
+    var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
+    data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
+    var obj = data.toObject();
+    assertNotNull(
+        data.getExtension(proto.jspb.test.IsExtension.extField));
+    assertEquals('is_extension', obj.extField.ext1);
+  });
+
+  /**
+   * Note that group is long deprecated, we only support it because JsPb has
+   * a goal of being able to generate JS classes for all proto descriptors.
+   */
+  it('testGroups', function() {
+    var group = new proto.jspb.test.TestGroup();
+    var someGroup = new proto.jspb.test.TestGroup.RepeatedGroup();
+    someGroup.setId('g1');
+    someGroup.setSomeBoolList([true, false]);
+    group.setRepeatedGroupList([someGroup]);
+    var groups = group.getRepeatedGroupList();
+    assertEquals('g1', groups[0].getId());
+    assertObjectEquals([true, false], groups[0].getSomeBoolList());
+    assertObjectEquals({id: 'g1', someBoolList: [true, false]},
+        groups[0].toObject());
+    assertObjectEquals({
+      repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
+      requiredGroup: {id: undefined},
+      optionalGroup: undefined,
+      requiredSimple: {aRepeatedStringList: [], aString: undefined},
+      optionalSimple: undefined,
+      id: undefined
+    }, group.toObject());
+    var group1 = new proto.jspb.test.TestGroup1();
+    group1.setGroup(someGroup);
+    assertEquals(someGroup, group1.getGroup());
+  });
+
+  it('testNonExtensionFieldsAfterExtensionRange', function() {
+    var data = [{'1': 'a_string'}];
+    var message = new proto.jspb.test.Complex(data);
+    assertArrayEquals([], message.getARepeatedStringList());
+  });
+
+  it('testReservedGetterNames', function() {
+    var message = new proto.jspb.test.TestReservedNames();
+    message.setExtension$(11);
+    message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
+    assertEquals(11, message.getExtension$());
+    assertEquals(12, message.getExtension(
+        proto.jspb.test.TestReservedNamesExtension.foo));
+    assertObjectEquals({extension: 11, foo: 12}, message.toObject());
+  });
+
+  it('testInitializeMessageWithUnsetOneof', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([]);
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+            RECURSIVE_ONEOF_NOT_SET,
+        message.getRecursiveOneofCase());
+  });
+
+  it('testInitializeMessageWithSingleValueSetInOneof', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
+
+    assertEquals('x', message.getPone());
+    assertUndefined(message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+  });
+
+  it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
+
+    assertUndefined('x', message.getPone());
+    assertEquals('y', message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+        message.getPartialOneofCase());
+  });
+
+  it('testSettingOneofFieldClearsOthers', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertUndefined(message.getPone());
+    assertUndefined(message.getPthree());
+
+    message.setPone('hi');
+    assertEquals('hi', message.getPone());
+    assertUndefined(message.getPthree());
+
+    message.setPthree('bye');
+    assertUndefined(message.getPone());
+    assertEquals('bye', message.getPthree());
+  });
+
+  it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
+    var other = new proto.jspb.test.TestMessageWithOneof;
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertUndefined(message.getPone());
+    assertUndefined(message.getPthree());
+    assertUndefined(message.getRone());
+
+    message.setPone('hi');
+    message.setRone(other);
+    assertEquals('hi', message.getPone());
+    assertUndefined(message.getPthree());
+    assertEquals(other, message.getRone());
+
+    message.setPthree('bye');
+    assertUndefined(message.getPone());
+    assertEquals('bye', message.getPthree());
+    assertEquals(other, message.getRone());
+  });
+
+  it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+
+    message.setPone('hi');
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+
+    message.clearPone();
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+  });
+
+  it('testMessageWithDefaultOneofValues', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(1234, message.getAone());
+    assertUndefined(message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+            .DEFAULT_ONEOF_A_NOT_SET,
+        message.getDefaultOneofACase());
+
+    message.setAone(567);
+    assertEquals(567, message.getAone());
+    assertUndefined(message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+        message.getDefaultOneofACase());
+
+    message.setAtwo(890);
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+
+    message.clearAtwo();
+    assertEquals(1234, message.getAone());
+    assertUndefined(message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+            .DEFAULT_ONEOF_A_NOT_SET,
+        message.getDefaultOneofACase());
+  });
+
+  it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertUndefined(message.getBone());
+    assertEquals(1234, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+            .DEFAULT_ONEOF_B_NOT_SET,
+        message.getDefaultOneofBCase());
+
+    message.setBone(2);
+    assertEquals(2, message.getBone());
+    assertEquals(1234, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+        message.getDefaultOneofBCase());
+
+    message.setBtwo(3);
+    assertUndefined(message.getBone());
+    assertEquals(3, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+        message.getDefaultOneofBCase());
+
+    message.clearBtwo();
+    assertUndefined(message.getBone());
+    assertEquals(1234, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+            .DEFAULT_ONEOF_B_NOT_SET,
+        message.getDefaultOneofBCase());
+  });
+
+  it('testInitializeMessageWithOneofDefaults', function() {
+    var message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
+    assertEquals(567, message.getAone());
+    assertUndefined(message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+        message.getDefaultOneofACase());
+
+    message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890));
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+
+    message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890));
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+  });
+
+  it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField',
+      function() {
+        var message;
+
+        message =
+            new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
+        assertEquals(567, message.getBone());
+        assertEquals(1234, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+            message.getDefaultOneofBCase());
+
+        message =
+            new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
+        assertUndefined(message.getBone());
+        assertEquals(890, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+            message.getDefaultOneofBCase());
+
+        message = new proto.jspb.test.TestMessageWithOneof(
+            new Array(11).concat(567, 890));
+        assertUndefined(message.getBone());
+        assertEquals(890, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+            message.getDefaultOneofBCase());
+      });
+
+  it('testOneofContainingAnotherMessage', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+            RECURSIVE_ONEOF_NOT_SET,
+        message.getRecursiveOneofCase());
+
+    var other = new proto.jspb.test.TestMessageWithOneof;
+    message.setRone(other);
+    assertEquals(other, message.getRone());
+    assertUndefined(message.getRtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
+        message.getRecursiveOneofCase());
+
+    message.setRtwo('hi');
+    assertUndefined(message.getRone());
+    assertEquals('hi', message.getRtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO,
+        message.getRecursiveOneofCase());
+  });
+
+  it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray',
+     function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    message.setPone('x');
+    assertEquals('x', message.getPone());
+    assertUndefined(message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+
+    var array = message.toArray();
+    assertEquals('x', array[2]);
+    assertUndefined(array[4]);
+    array[4] = 'y';
+
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+        message.getPartialOneofCase());
+    assertUndefined(array[2]);
+    assertEquals('y', array[4]);
+  });
+
+  it('testFloatingPointFieldsSupportNan', function() {
+    var assertNan = function(x) {
+      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+          goog.isNumber(x) && isNaN(x));
+    };
+
+    var message = new proto.jspb.test.FloatingPointFields([
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+    ]);
+    assertNan(message.getOptionalFloatField());
+    assertNan(message.getRequiredFloatField());
+    assertNan(message.getRepeatedFloatFieldList()[0]);
+    assertNan(message.getRepeatedFloatFieldList()[1]);
+    assertNan(message.getDefaultFloatField());
+    assertNan(message.getOptionalDoubleField());
+    assertNan(message.getRequiredDoubleField());
+    assertNan(message.getRepeatedDoubleFieldList()[0]);
+    assertNan(message.getRepeatedDoubleFieldList()[1]);
+    assertNan(message.getDefaultDoubleField());
+  });
+
+});
diff --git a/src/third_party/protobuf-3/js/node_loader.js b/src/third_party/protobuf-3/js/node_loader.js
new file mode 100644
index 0000000..79211ad
--- /dev/null
+++ b/src/third_party/protobuf-3/js/node_loader.js
@@ -0,0 +1,49 @@
+// 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.
+
+/**
+ * @fileoverview Loader that handles goog.require() for Node.JS.
+ */
+
+var oldLoader = goog.global.CLOSURE_IMPORT_SCRIPT;
+
+goog.global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) {
+  if (opt_sourceText === undefined) {
+    try {
+      // Load from the current directory.
+      require("./" + src);
+      return true;
+    } catch (e) {
+      // Fall back to the Closure loader.
+    }
+  }
+
+  return oldLoader(src, opt_sourceText);
+};
diff --git a/src/third_party/protobuf-3/js/package.json b/src/third_party/protobuf-3/js/package.json
new file mode 100644
index 0000000..ae05722
--- /dev/null
+++ b/src/third_party/protobuf-3/js/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "google-protobuf",
+  "version": "3.0.0-alpha.6",
+  "description": "Protocol Buffers for JavaScript",
+  "main": "google-protobuf.js",
+  "dependencies": {
+    "google-closure-library": "~20160125.0.0",
+    "gulp": "~3.9.0",
+    "jasmine": "~2.4.1"
+  },
+  "devDependencies": {
+    "google-closure-compiler": "~20151216.2.0",
+    "glob": "~6.0.4"
+  },
+  "scripts": {
+    "test": "node ./node_modules/gulp/bin/gulp.js test"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/google/protobuf/tree/master/js"
+  },
+  "author": "",
+  "license": "Apache-2.0"
+}
diff --git a/src/third_party/protobuf-3/js/proto3_test.js b/src/third_party/protobuf-3/js/proto3_test.js
new file mode 100644
index 0000000..4dd7790
--- /dev/null
+++ b/src/third_party/protobuf-3/js/proto3_test.js
@@ -0,0 +1,314 @@
+// 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.
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ForeignMessage');
+
+// CommonJS-LoadFromFile: proto3_test_pb proto.jspb.test
+goog.require('proto.jspb.test.Proto3Enum');
+goog.require('proto.jspb.test.TestProto3');
+
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+  if (goog.isString(arr)) {
+    arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+  }
+  if (arr.length != expected.length) {
+    return false;
+  }
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] != expected[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+describe('proto3Test', function() {
+  /**
+   * Test defaults for proto3 message fields.
+   */
+  it('testProto3FieldDefaults', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    assertEquals(msg.getOptionalInt32(), 0);
+    assertEquals(msg.getOptionalInt64(), 0);
+    assertEquals(msg.getOptionalUint32(), 0);
+    assertEquals(msg.getOptionalUint64(), 0);
+    assertEquals(msg.getOptionalSint32(), 0);
+    assertEquals(msg.getOptionalSint64(), 0);
+    assertEquals(msg.getOptionalFixed32(), 0);
+    assertEquals(msg.getOptionalFixed64(), 0);
+    assertEquals(msg.getOptionalSfixed32(), 0);
+    assertEquals(msg.getOptionalSfixed64(), 0);
+    assertEquals(msg.getOptionalFloat(), 0);
+    assertEquals(msg.getOptionalDouble(), 0);
+    assertEquals(msg.getOptionalString(), '');
+
+    // TODO(b/26173701): when we change bytes fields default getter to return
+    // Uint8Array, we'll want to switch this assertion to match the u8 case.
+    assertEquals(typeof msg.getOptionalBytes(), 'string');
+    assertEquals(msg.getOptionalBytes_asU8() instanceof Uint8Array, true);
+    assertEquals(typeof msg.getOptionalBytes_asB64(), 'string');
+    assertEquals(msg.getOptionalBytes().length, 0);
+    assertEquals(msg.getOptionalBytes_asU8().length, 0);
+    assertEquals(msg.getOptionalBytes_asB64(), '');
+
+    assertEquals(msg.getOptionalForeignEnum(),
+                 proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    assertEquals(msg.getOptionalForeignMessage(), undefined);
+    assertEquals(msg.getOptionalForeignMessage(), undefined);
+
+    assertEquals(msg.getRepeatedInt32List().length, 0);
+    assertEquals(msg.getRepeatedInt64List().length, 0);
+    assertEquals(msg.getRepeatedUint32List().length, 0);
+    assertEquals(msg.getRepeatedUint64List().length, 0);
+    assertEquals(msg.getRepeatedSint32List().length, 0);
+    assertEquals(msg.getRepeatedSint64List().length, 0);
+    assertEquals(msg.getRepeatedFixed32List().length, 0);
+    assertEquals(msg.getRepeatedFixed64List().length, 0);
+    assertEquals(msg.getRepeatedSfixed32List().length, 0);
+    assertEquals(msg.getRepeatedSfixed64List().length, 0);
+    assertEquals(msg.getRepeatedFloatList().length, 0);
+    assertEquals(msg.getRepeatedDoubleList().length, 0);
+    assertEquals(msg.getRepeatedStringList().length, 0);
+    assertEquals(msg.getRepeatedBytesList().length, 0);
+    assertEquals(msg.getRepeatedForeignEnumList().length, 0);
+    assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+
+  });
+
+
+  /**
+   * Test that all fields can be set and read via a serialization roundtrip.
+   */
+  it('testProto3FieldSetGet', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    msg.setOptionalInt32(-42);
+    msg.setOptionalInt64(-0x7fffffff00000000);
+    msg.setOptionalUint32(0x80000000);
+    msg.setOptionalUint64(0xf000000000000000);
+    msg.setOptionalSint32(-100);
+    msg.setOptionalSint64(-0x8000000000000000);
+    msg.setOptionalFixed32(1234);
+    msg.setOptionalFixed64(0x1234567800000000);
+    msg.setOptionalSfixed32(-1234);
+    msg.setOptionalSfixed64(-0x1234567800000000);
+    msg.setOptionalFloat(1.5);
+    msg.setOptionalDouble(-1.5);
+    msg.setOptionalBool(true);
+    msg.setOptionalString('hello world');
+    msg.setOptionalBytes(BYTES);
+    var submsg = new proto.jspb.test.ForeignMessage();
+    submsg.setC(16);
+    msg.setOptionalForeignMessage(submsg);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+    msg.setRepeatedInt32List([-42]);
+    msg.setRepeatedInt64List([-0x7fffffff00000000]);
+    msg.setRepeatedUint32List([0x80000000]);
+    msg.setRepeatedUint64List([0xf000000000000000]);
+    msg.setRepeatedSint32List([-100]);
+    msg.setRepeatedSint64List([-0x8000000000000000]);
+    msg.setRepeatedFixed32List([1234]);
+    msg.setRepeatedFixed64List([0x1234567800000000]);
+    msg.setRepeatedSfixed32List([-1234]);
+    msg.setRepeatedSfixed64List([-0x1234567800000000]);
+    msg.setRepeatedFloatList([1.5]);
+    msg.setRepeatedDoubleList([-1.5]);
+    msg.setRepeatedBoolList([true]);
+    msg.setRepeatedStringList(['hello world']);
+    msg.setRepeatedBytesList([BYTES]);
+    submsg = new proto.jspb.test.ForeignMessage();
+    submsg.setC(1000);
+    msg.setRepeatedForeignMessageList([submsg]);
+    msg.setRepeatedForeignEnumList([proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+    msg.setOneofString('asdf');
+
+    var serialized = msg.serializeBinary();
+    msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
+
+    assertEquals(msg.getOptionalInt32(), -42);
+    assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
+    assertEquals(msg.getOptionalUint32(), 0x80000000);
+    assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
+    assertEquals(msg.getOptionalSint32(), -100);
+    assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
+    assertEquals(msg.getOptionalFixed32(), 1234);
+    assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
+    assertEquals(msg.getOptionalSfixed32(), -1234);
+    assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
+    assertEquals(msg.getOptionalFloat(), 1.5);
+    assertEquals(msg.getOptionalDouble(), -1.5);
+    assertEquals(msg.getOptionalBool(), true);
+    assertEquals(msg.getOptionalString(), 'hello world');
+    assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
+    assertEquals(msg.getOptionalForeignMessage().getC(), 16);
+    assertEquals(msg.getOptionalForeignEnum(),
+        proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+    assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
+    assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
+    assertElementsEquals(msg.getRepeatedUint32List(), [0x80000000]);
+    assertElementsEquals(msg.getRepeatedUint64List(), [0xf000000000000000]);
+    assertElementsEquals(msg.getRepeatedSint32List(), [-100]);
+    assertElementsEquals(msg.getRepeatedSint64List(), [-0x8000000000000000]);
+    assertElementsEquals(msg.getRepeatedFixed32List(), [1234]);
+    assertElementsEquals(msg.getRepeatedFixed64List(), [0x1234567800000000]);
+    assertElementsEquals(msg.getRepeatedSfixed32List(), [-1234]);
+    assertElementsEquals(msg.getRepeatedSfixed64List(), [-0x1234567800000000]);
+    assertElementsEquals(msg.getRepeatedFloatList(), [1.5]);
+    assertElementsEquals(msg.getRepeatedDoubleList(), [-1.5]);
+    assertElementsEquals(msg.getRepeatedBoolList(), [true]);
+    assertElementsEquals(msg.getRepeatedStringList(), ['hello world']);
+    assertEquals(msg.getRepeatedBytesList().length, 1);
+    assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+    assertEquals(msg.getRepeatedForeignMessageList().length, 1);
+    assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
+    assertElementsEquals(msg.getRepeatedForeignEnumList(),
+        [proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+    assertEquals(msg.getOneofString(), 'asdf');
+  });
+
+
+  /**
+   * Test that oneofs continue to have a notion of field presence.
+   */
+  it('testOneofs', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    assertEquals(msg.getOneofUint32(), undefined);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), undefined);
+    assertEquals(msg.getOneofBytes(), undefined);
+
+    msg.setOneofUint32(42);
+    assertEquals(msg.getOneofUint32(), 42);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), undefined);
+    assertEquals(msg.getOneofBytes(), undefined);
+
+
+    var submsg = new proto.jspb.test.ForeignMessage();
+    msg.setOneofForeignMessage(submsg);
+    assertEquals(msg.getOneofUint32(), undefined);
+    assertEquals(msg.getOneofForeignMessage(), submsg);
+    assertEquals(msg.getOneofString(), undefined);
+    assertEquals(msg.getOneofBytes(), undefined);
+
+    msg.setOneofString('hello');
+    assertEquals(msg.getOneofUint32(), undefined);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), 'hello');
+    assertEquals(msg.getOneofBytes(), undefined);
+
+    msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    assertEquals(msg.getOneofUint32(), undefined);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), undefined);
+    assertEquals(msg.getOneofBytes_asB64(),
+        goog.crypt.base64.encodeString('\u00FF\u00FF'));
+  });
+
+
+  /**
+   * Test that "default"-valued primitive fields are not emitted on the wire.
+   */
+  it('testNoSerializeDefaults', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    // Set each primitive to a non-default value, then back to its default, to
+    // ensure that the serialization is actually checking the value and not just
+    // whether it has ever been set.
+    msg.setOptionalInt32(42);
+    msg.setOptionalInt32(0);
+    msg.setOptionalDouble(3.14);
+    msg.setOptionalDouble(0.0);
+    msg.setOptionalBool(true);
+    msg.setOptionalBool(false);
+    msg.setOptionalString('hello world');
+    msg.setOptionalString('');
+    msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    msg.setOptionalBytes('');
+    msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
+    msg.setOptionalForeignMessage(null);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    msg.setOneofUint32(32);
+    msg.setOneofUint32(null);
+
+
+    var serialized = msg.serializeBinary();
+    assertEquals(0, serialized.length);
+  });
+
+  /**
+   * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+   */
+  it('testBytesFieldsInterop', function() {
+    var msg = new proto.jspb.test.TestProto3();
+    // Set as a base64 string and check all the getters work.
+    msg.setOptionalBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    // Test binary serialize round trip doesn't break it.
+    msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg = new proto.jspb.test.TestProto3();
+    // Set as a Uint8Array and check all the getters work.
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+  });
+});
diff --git a/src/third_party/protobuf-3/js/proto3_test.proto b/src/third_party/protobuf-3/js/proto3_test.proto
new file mode 100644
index 0000000..acb6716
--- /dev/null
+++ b/src/third_party/protobuf-3/js/proto3_test.proto
@@ -0,0 +1,89 @@
+// 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.
+
+syntax = "proto3";
+
+import "testbinary.proto";
+
+package jspb.test;
+
+message TestProto3 {
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  ForeignMessage optional_foreign_message = 19;
+  Proto3Enum     optional_foreign_enum    = 22;
+
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated ForeignMessage repeated_foreign_message = 49;
+  repeated Proto3Enum     repeated_foreign_enum    = 52;
+
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    ForeignMessage oneof_foreign_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+enum Proto3Enum {
+  PROTO3_FOO = 0;
+  PROTO3_BAR = 1;
+  PROTO3_BAZ = 2;
+}
diff --git a/src/third_party/protobuf-3/js/test.proto b/src/third_party/protobuf-3/js/test.proto
new file mode 100644
index 0000000..6b9dc89
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test.proto
@@ -0,0 +1,230 @@
+// 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.
+
+// Author: mwr@google.com (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+import "google/protobuf/descriptor.proto";
+
+package jspb.test;
+
+message Empty {
+}
+
+enum OuterEnum {
+  FOO = 1;
+  BAR = 2;
+}
+
+message EnumContainer {
+  optional OuterEnum outer_enum = 1;
+}
+
+message Simple1 {
+  required string a_string = 1;
+  repeated string a_repeated_string = 2;
+  optional bool a_boolean = 3;
+}
+
+// A message that differs from Simple1 only by name
+message Simple2 {
+  required string a_string = 1;
+  repeated string a_repeated_string = 2;
+}
+
+message SpecialCases {
+  required string normal = 1;
+  // Examples of Js reserved names that are converted to pb_<name>.
+  required string default = 2;
+  required string function = 3;
+  required string var = 4;
+}
+
+message OptionalFields {
+  message Nested {
+    optional int32 an_int = 1;
+  }
+  optional string a_string = 1;
+  required bool a_bool = 2;
+  optional Nested a_nested_message = 3;
+  repeated Nested a_repeated_message = 4;
+  repeated string a_repeated_string = 5;
+}
+
+message HasExtensions {
+  optional string str1 = 1;
+  optional string str2 = 2;
+  optional string str3 = 3;
+  extensions 10 to max;
+}
+
+message Complex {
+  message Nested {
+    required int32 an_int = 2;
+  }
+  required string a_string = 1;
+  required bool an_out_of_order_bool = 9;
+  optional Nested a_nested_message = 4;
+  repeated Nested a_repeated_message = 5;
+  repeated string a_repeated_string = 7;
+}
+
+message OuterMessage {
+  // Make sure this doesn't conflict with the other Complex message.
+  message Complex {
+    optional int32 inner_complex_field = 1;
+  }
+}
+
+message IsExtension {
+  extend HasExtensions {
+    optional IsExtension ext_field = 100;
+  }
+  optional string ext1 = 1;
+
+  // Extensions of proto2 Descriptor messages will be ignored.
+  extend google.protobuf.EnumOptions {
+    optional string simple_option = 42113038;
+  }
+}
+
+message IndirectExtension {
+  extend HasExtensions {
+    optional Simple1 simple = 101;
+    optional string str = 102;
+    repeated string repeated_str = 103;
+    repeated Simple1 repeated_simple = 104;
+  }
+}
+
+extend HasExtensions {
+  optional Simple1 simple1 = 105;
+}
+
+message DefaultValues {
+  enum Enum {
+    E1 = 13;
+    E2 = 77;
+  }
+  optional string string_field = 1 [default="default<>\'\"abc"];
+  optional bool bool_field = 2 [default=true];
+  optional int64 int_field = 3 [default=11];
+  optional Enum enum_field = 4 [default=E1];
+  optional string empty_field = 6 [default=""];
+  optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v"
+}
+
+message FloatingPointFields {
+  optional float optional_float_field = 1;
+  required float required_float_field = 2;
+  repeated float repeated_float_field = 3;
+  optional float default_float_field = 4 [default = 2.0];
+  optional double optional_double_field = 5;
+  required double required_double_field = 6;
+  repeated double repeated_double_field = 7;
+  optional double default_double_field = 8 [default = 2.0];
+}
+
+message TestClone {
+  optional string str = 1;
+  optional Simple1 simple1 = 3;
+  repeated Simple1 simple2 = 5;
+  optional string unused = 7;
+  extensions 10 to max;
+}
+
+message CloneExtension {
+  extend TestClone {
+    optional CloneExtension ext_field = 100;
+  }
+  optional string ext = 2;
+}
+
+message TestGroup {
+  repeated group RepeatedGroup = 1 {
+    required string id = 1;
+    repeated bool some_bool = 2;
+  }
+  required group RequiredGroup = 2 {
+    required string id = 1;
+  }
+  optional group OptionalGroup = 3 {
+    required string id = 1;
+  }
+  optional string id = 4;
+  required Simple2 required_simple = 5;
+  optional Simple2 optional_simple = 6;
+}
+
+message TestGroup1 {
+  optional TestGroup.RepeatedGroup group = 1;
+}
+
+message TestReservedNames {
+  optional int32 extension = 1;
+  extensions 10 to max;
+}
+
+message TestReservedNamesExtension {
+  extend TestReservedNames {
+    optional int32 foo = 10;
+  }
+}
+
+message TestMessageWithOneof {
+
+  oneof partial_oneof {
+    string pone = 3;
+    string pthree = 5;
+  }
+
+  oneof recursive_oneof {
+    TestMessageWithOneof rone = 6;
+    string rtwo = 7;
+  }
+
+  optional bool normal_field = 8;
+  repeated string repeated_field = 9;
+
+  oneof default_oneof_a {
+    int32 aone = 10 [default = 1234];
+    int32 atwo = 11;
+  }
+
+  oneof default_oneof_b {
+    int32 bone = 12;
+    int32 btwo = 13 [default = 1234];
+  }
+}
+
diff --git a/src/third_party/protobuf-3/js/test2.proto b/src/third_party/protobuf-3/js/test2.proto
new file mode 100644
index 0000000..44e55ef
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test2.proto
@@ -0,0 +1,54 @@
+// 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.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+message TestExtensionsMessage {
+  optional int32 intfield = 1;
+  extensions 100 to max;
+}
+
+message ExtensionMessage {
+  extend TestExtensionsMessage {
+    optional ExtensionMessage ext_field = 100;
+  }
+  optional string ext1 = 1;
+}
+
+// Floating extensions are only supported when generating a _lib.js library.
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field = 101;
+  optional string floating_str_field = 102;
+}
diff --git a/src/third_party/protobuf-3/js/test3.proto b/src/third_party/protobuf-3/js/test3.proto
new file mode 100644
index 0000000..940a552
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test3.proto
@@ -0,0 +1,53 @@
+// 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.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+message TestExtensionsMessage {
+  optional int32 intfield = 1;
+  extensions 100 to max;
+}
+
+message ExtensionMessage {
+  extend TestExtensionsMessage {
+    optional ExtensionMessage ext_field = 100;
+  }
+  optional string ext1 = 1;
+}
+
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field = 101;
+  optional string floating_str_field = 102;
+}
diff --git a/src/third_party/protobuf-3/js/test4.proto b/src/third_party/protobuf-3/js/test4.proto
new file mode 100644
index 0000000..cf2451e
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test4.proto
@@ -0,0 +1,42 @@
+// 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.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+import "test3.proto";
+
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field_two = 103;
+}
diff --git a/src/third_party/protobuf-3/js/test5.proto b/src/third_party/protobuf-3/js/test5.proto
new file mode 100644
index 0000000..3497951
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test5.proto
@@ -0,0 +1,44 @@
+// 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.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest.beta;
+
+message TestBetaExtensionsMessage {
+  extensions 100 to max;
+}
+
+extend TestBetaExtensionsMessage {
+  optional string floating_str_field = 101;
+}
diff --git a/src/third_party/protobuf-3/js/test_bootstrap.js b/src/third_party/protobuf-3/js/test_bootstrap.js
new file mode 100644
index 0000000..9d00a1c
--- /dev/null
+++ b/src/third_party/protobuf-3/js/test_bootstrap.js
@@ -0,0 +1,41 @@
+// 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.
+
+/**
+ * @fileoverview Sets flags for uncompiled JSUnit tests.
+ */
+
+/**
+ * Set uncompiled flags.
+ */
+var CLOSURE_DEFINES = {
+    // Enable the fromObject method on the message class.
+    'jspb.Message.GENERATE_FROM_OBJECT': true
+};
diff --git a/src/third_party/protobuf-3/js/testbinary.proto b/src/third_party/protobuf-3/js/testbinary.proto
new file mode 100644
index 0000000..60c7019
--- /dev/null
+++ b/src/third_party/protobuf-3/js/testbinary.proto
@@ -0,0 +1,185 @@
+// 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.
+
+// LINT: ALLOW_GROUPS
+
+syntax = "proto2";
+
+
+package jspb.test;
+
+// These types are borrowed from `unittest.proto` in the protobuf tree. We want
+// to ensure that the binary-format support will handle all field types
+// properly.
+message TestAllTypes {
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional ForeignMessage                       optional_foreign_message = 19;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  // Packed repeated
+  repeated    int32 packed_repeated_int32    = 61 [packed=true];
+  repeated    int64 packed_repeated_int64    = 62 [packed=true];
+  repeated   uint32 packed_repeated_uint32   = 63 [packed=true];
+  repeated   uint64 packed_repeated_uint64   = 64 [packed=true];
+  repeated   sint32 packed_repeated_sint32   = 65 [packed=true];
+  repeated   sint64 packed_repeated_sint64   = 66 [packed=true];
+  repeated  fixed32 packed_repeated_fixed32  = 67 [packed=true];
+  repeated  fixed64 packed_repeated_fixed64  = 68 [packed=true];
+  repeated sfixed32 packed_repeated_sfixed32 = 69 [packed=true];
+  repeated sfixed64 packed_repeated_sfixed64 = 70 [packed=true];
+  repeated    float packed_repeated_float    = 71 [packed=true];
+  repeated   double packed_repeated_double   = 72 [packed=true];
+  repeated     bool packed_repeated_bool     = 73 [packed=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    ForeignMessage oneof_foreign_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+
+}
+
+message ForeignMessage {
+  optional int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestExtendable {
+  extensions 1 to max;
+}
+
+message ExtendsWithMessage {
+  extend TestExtendable {
+    optional ExtendsWithMessage optional_extension = 19;
+    repeated ExtendsWithMessage repeated_extension = 49;
+  }
+  optional int32 foo = 1;
+}
+
+extend TestExtendable {
+  optional    int32 extend_optional_int32    =  1;
+  optional    int64 extend_optional_int64    =  2;
+  optional   uint32 extend_optional_uint32   =  3;
+  optional   uint64 extend_optional_uint64   =  4;
+  optional   sint32 extend_optional_sint32   =  5;
+  optional   sint64 extend_optional_sint64   =  6;
+  optional  fixed32 extend_optional_fixed32  =  7;
+  optional  fixed64 extend_optional_fixed64  =  8;
+  optional sfixed32 extend_optional_sfixed32 =  9;
+  optional sfixed64 extend_optional_sfixed64 = 10;
+  optional    float extend_optional_float    = 11;
+  optional   double extend_optional_double   = 12;
+  optional     bool extend_optional_bool     = 13;
+  optional   string extend_optional_string   = 14;
+  optional    bytes extend_optional_bytes    = 15;
+  optional ForeignEnum extend_optional_foreign_enum    = 22;
+
+  repeated    int32 extend_repeated_int32    = 31;
+  repeated    int64 extend_repeated_int64    = 32;
+  repeated   uint32 extend_repeated_uint32   = 33;
+  repeated   uint64 extend_repeated_uint64   = 34;
+  repeated   sint32 extend_repeated_sint32   = 35;
+  repeated   sint64 extend_repeated_sint64   = 36;
+  repeated  fixed32 extend_repeated_fixed32  = 37;
+  repeated  fixed64 extend_repeated_fixed64  = 38;
+  repeated sfixed32 extend_repeated_sfixed32 = 39;
+  repeated sfixed64 extend_repeated_sfixed64 = 40;
+  repeated    float extend_repeated_float    = 41;
+  repeated   double extend_repeated_double   = 42;
+  repeated     bool extend_repeated_bool     = 43;
+  repeated   string extend_repeated_string   = 44;
+  repeated    bytes extend_repeated_bytes    = 45;
+  repeated ForeignEnum extend_repeated_foreign_enum    = 52;
+
+  repeated    int32 extend_packed_repeated_int32    = 61 [packed=true];
+  repeated    int64 extend_packed_repeated_int64    = 62 [packed=true];
+  repeated   uint32 extend_packed_repeated_uint32   = 63 [packed=true];
+  repeated   uint64 extend_packed_repeated_uint64   = 64 [packed=true];
+  repeated   sint32 extend_packed_repeated_sint32   = 65 [packed=true];
+  repeated   sint64 extend_packed_repeated_sint64   = 66 [packed=true];
+  repeated  fixed32 extend_packed_repeated_fixed32  = 67 [packed=true];
+  repeated  fixed64 extend_packed_repeated_fixed64  = 68 [packed=true];
+  repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed=true];
+  repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed=true];
+  repeated    float extend_packed_repeated_float    = 71 [packed=true];
+  repeated   double extend_packed_repeated_double   = 72 [packed=true];
+  repeated     bool extend_packed_repeated_bool     = 73 [packed=true];
+  repeated ForeignEnum extend_packed_repeated_foreign_enum    = 82
+      [packed=true];
+
+}
diff --git a/src/third_party/protobuf-3/js/testempty.proto b/src/third_party/protobuf-3/js/testempty.proto
new file mode 100644
index 0000000..960bce4
--- /dev/null
+++ b/src/third_party/protobuf-3/js/testempty.proto
@@ -0,0 +1,34 @@
+// 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.
+
+syntax = "proto2";
+
+package javatests.com.google.apps.jspb;
+
diff --git a/src/third_party/protobuf-3/m4/ac_system_extensions.m4 b/src/third_party/protobuf-3/m4/ac_system_extensions.m4
new file mode 100644
index 0000000..1ca2eeb
--- /dev/null
+++ b/src/third_party/protobuf-3/m4/ac_system_extensions.m4
@@ -0,0 +1,37 @@
+dnl Provide AC_USE_SYSTEM_EXTENSIONS for old autoconf machines.
+AC_DEFUN([ACX_USE_SYSTEM_EXTENSIONS],[
+  ifdef([AC_USE_SYSTEM_EXTENSIONS],[
+    AC_USE_SYSTEM_EXTENSIONS
+  ],[
+    AC_BEFORE([$0], [AC_COMPILE_IFELSE])
+    AC_BEFORE([$0], [AC_RUN_IFELSE])
+
+    AC_REQUIRE([AC_GNU_SOURCE])
+    AC_REQUIRE([AC_AIX])
+    AC_REQUIRE([AC_MINIX])
+
+    AH_VERBATIM([__EXTENSIONS__],
+[/* Enable extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif])
+    AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
+      [ac_cv_safe_to_define___extensions__],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM([
+#           define __EXTENSIONS__ 1
+            AC_INCLUDES_DEFAULT])],
+         [ac_cv_safe_to_define___extensions__=yes],
+         [ac_cv_safe_to_define___extensions__=no])])
+    test $ac_cv_safe_to_define___extensions__ = yes &&
+      AC_DEFINE([__EXTENSIONS__])
+    AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
+    AC_DEFINE([_TANDEM_SOURCE])
+  ])
+])
diff --git a/src/third_party/protobuf-3/m4/acx_check_suncc.m4 b/src/third_party/protobuf-3/m4/acx_check_suncc.m4
new file mode 100644
index 0000000..8bc0a89
--- /dev/null
+++ b/src/third_party/protobuf-3/m4/acx_check_suncc.m4
@@ -0,0 +1,70 @@
+dnl Check for the presence of the Sun Studio compiler.
+dnl If Sun Studio compiler is found, set appropriate flags.
+dnl Additionally, Sun Studio doesn't default to 64-bit by itself,
+dnl nor does it automatically look in standard Solaris places for
+dnl 64-bit libs, so we must add those options and paths to the search
+dnl paths.
+
+dnl TODO(kenton):  This is pretty hacky.  It sets CXXFLAGS, which the autoconf
+dnl docs say should never be overridden except by the user.  It also isn't
+dnl cross-compile safe.  We should fix these problems, but since I don't have
+dnl Sun CC at my disposal for testing, someone else will have to do it.
+
+AC_DEFUN([ACX_CHECK_SUNCC],[
+
+  AC_LANG_PUSH([C++])
+  AC_CHECK_DECL([__SUNPRO_CC], [SUNCC="yes"], [SUNCC="no"])
+  AC_LANG_POP()
+
+
+  AC_ARG_ENABLE([64bit-solaris],
+    [AS_HELP_STRING([--disable-64bit-solaris],
+      [Build 64 bit binary on Solaris @<:@default=on@:>@])],
+             [ac_enable_64bit="$enableval"],
+             [ac_enable_64bit="yes"])
+
+  AS_IF([test "$SUNCC" = "yes" -a "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
+    dnl Sun Studio has a crashing bug with -xO4 in some cases. Keep this
+    dnl at -xO3 until a proper test to detect those crashes can be done.
+    CXXFLAGS="-g0 -xO3 -xlibmil -xdepend -xbuiltin -mt -compat=5 -library=stlport4 -library=Crun -template=no%extdef ${CXXFLAGS}"
+  ])
+
+  case $host_os in
+    *solaris*)
+      AC_CHECK_PROGS(ISAINFO, [isainfo], [no])
+      AS_IF([test "x$ISAINFO" != "xno"],
+            [isainfo_b=`${ISAINFO} -b`],
+            [isainfo_b="x"])
+
+      AS_IF([test "$isainfo_b" != "x"],[
+
+        isainfo_k=`${ISAINFO} -k`
+
+        AS_IF([test "x$ac_enable_64bit" = "xyes"],[
+
+          AS_IF([test "x$libdir" = "x\${exec_prefix}/lib"],[
+           dnl The user hasn't overridden the default libdir, so we'll
+           dnl the dir suffix to match solaris 32/64-bit policy
+           libdir="${libdir}/${isainfo_k}"
+          ])
+
+          dnl This should just be set in CPPFLAGS and in LDFLAGS, but libtool
+          dnl does the wrong thing if you don't put it into CXXFLAGS. sigh.
+          dnl (It also needs it in CFLAGS, or it does a different wrong thing!)
+          CXXFLAGS="${CXXFLAGS} -m64"
+          ac_cv_env_CXXFLAGS_set=set
+          ac_cv_env_CXXFLAGS_value='-m64'
+
+          CFLAGS="${CFLAGS} -m64"
+          ac_cv_env_CFLAGS_set=set
+          ac_cv_env_CFLAGS_value='-m64'
+
+          AS_IF([test "$target_cpu" = "sparc" -a "x$SUNCC" = "xyes" ],[
+            CXXFLAGS="-xmemalign=8s ${CXXFLAGS}"
+          ])
+        ])
+      ])
+    ;;
+  esac
+
+])
diff --git a/src/third_party/protobuf-3/m4/acx_pthread.m4 b/src/third_party/protobuf-3/m4/acx_pthread.m4
new file mode 100644
index 0000000..89d42c7
--- /dev/null
+++ b/src/third_party/protobuf-3/m4/acx_pthread.m4
@@ -0,0 +1,397 @@
+# This was retrieved from
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
+# See also (perhaps for new versions?)
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
+#
+# We've rewritten the inconsistency check code (from avahi), to work
+# more broadly.  In particular, it no longer assumes ld accepts -zdefs.
+# This caused a restructing of the code, but the functionality has only
+# changed a little.
+
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl @summary figure out how to build C programs using POSIX threads
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2006-05-29
+dnl @license GPLWithACException
+dnl 
+dnl Checks for GCC shared/pthread inconsistency based on work by
+dnl Marcin Owsiany <marcin@owsiany.pl>
+
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+	AC_MSG_CHECKING([for joinable pthread attribute])
+	attr_name=unknown
+	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+                        [attr_name=$attr; break])
+	done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+        # More AIX lossage: must compile with xlc_r or cc_r
+	if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+	fi
+
+	# The next part tries to detect GCC inconsistency with -shared on some
+	# architectures and systems. The problem is that in certain
+	# configurations, when -shared is specified, GCC "forgets" to
+	# internally use various flags which are still necessary.
+	
+	#
+	# Prepare the flags
+	#
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	save_CC="$CC"
+	
+	# Try with the flags determined by the earlier checks.
+	#
+	# -Wl,-z,defs forces link-time symbol resolution, so that the
+	# linking checks with -shared actually have any value
+	#
+	# FIXME: -fPIC is required for -shared on many architectures,
+	# so we specify it here, but the right way would probably be to
+	# properly detect whether it is actually required.
+	CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+	LIBS="$PTHREAD_LIBS $LIBS"
+	CC="$PTHREAD_CC"
+	
+	# In order not to create several levels of indentation, we test
+	# the value of "$done" until we find the cure or run out of ideas.
+	done="no"
+	
+	# First, make sure the CFLAGS we added are actually accepted by our
+	# compiler.  If not (and OS X's ld, for instance, does not accept -z),
+	# then we can't do this test.
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
+	   AC_TRY_LINK(,, , [done=yes])
+	
+	   if test "x$done" = xyes ; then
+	      AC_MSG_RESULT([no])
+	   else
+	      AC_MSG_RESULT([yes])
+	   fi
+	fi
+	
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
+	   AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes])
+	   
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	
+	#
+	# Linux gcc on some architectures such as mips/mipsel forgets
+	# about -lpthread
+	#
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -lpthread fixes that])
+	   LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+	   AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes])
+	
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	      PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	#
+	# FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+	#
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -lc_r fixes that])
+	   LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+	   AC_TRY_LINK([#include <pthread.h>],
+	       [pthread_t th; pthread_join(th, 0);
+	        pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	        pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	       [done=yes])
+	
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	      PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	if test x"$done" = xno; then
+	   # OK, we have run out of ideas
+	   AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
+	
+	   # so it's not safe to assume that we may use pthreads
+	   acx_pthread_ok=no
+	fi
+	
+	AC_MSG_CHECKING([whether what we have so far is sufficient with -nostdlib])
+	CFLAGS="-nostdlib $CFLAGS"
+	# we need c with nostdlib
+	LIBS="$LIBS -lc"
+	AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	       pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	       pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes],[done=no])
+
+	if test "x$done" = xyes; then
+	   AC_MSG_RESULT([yes])
+	else
+	   AC_MSG_RESULT([no])
+	fi
+	
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -lpthread saves the day])
+	   LIBS="-lpthread $LIBS"
+	   AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	       pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	       pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes],[done=no])
+
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	      PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+	   else
+	      AC_MSG_RESULT([no])
+	      AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries and -nostdlib])
+	   fi
+	fi
+
+	CFLAGS="$save_CFLAGS"
+	LIBS="$save_LIBS"
+	CC="$save_CC"
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/src/third_party/protobuf-3/m4/stl_hash.m4 b/src/third_party/protobuf-3/m4/stl_hash.m4
new file mode 100644
index 0000000..d7def1a
--- /dev/null
+++ b/src/third_party/protobuf-3/m4/stl_hash.m4
@@ -0,0 +1,71 @@
+# We check two things: where the include file is for
+# unordered_map/hash_map (we prefer the first form), and what
+# namespace unordered/hash_map lives in within that include file.  We
+# include AC_TRY_COMPILE for all the combinations we've seen in the
+# wild.  We define HASH_MAP_H to the location of the header file, and
+# HASH_NAMESPACE to the namespace the class (unordered_map or
+# hash_map) is in.
+
+# This also checks if unordered map exists.
+AC_DEFUN([AC_CXX_STL_HASH],
+  [
+   AC_MSG_CHECKING(the location of hash_map)
+   AC_LANG_SAVE
+   AC_LANG_CPLUSPLUS
+   ac_cv_cxx_hash_map=""
+   # First try unordered_map, but not on gcc's before 4.2 -- I've
+   # seen unexplainable unordered_map bugs with -O2 on older gcc's.
+   AC_TRY_COMPILE([#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
+                   # error GCC too old for unordered_map
+                   #endif
+                   ],
+                   [/* no program body necessary */],
+                   [stl_hash_old_gcc=no],
+                   [stl_hash_old_gcc=yes])
+   for location in unordered_map tr1/unordered_map; do
+     for namespace in std std::tr1; do
+       if test -z "$ac_cv_cxx_hash_map" -a "$stl_hash_old_gcc" != yes; then
+         # Some older gcc's have a buggy tr1, so test a bit of code.
+         AC_TRY_COMPILE([#include <$location>],
+                        [const ${namespace}::unordered_map<int, int> t;
+                         return t.find(5) == t.end();],
+                        [ac_cv_cxx_hash_map="<$location>";
+                         ac_cv_cxx_hash_namespace="$namespace";
+                         ac_cv_cxx_hash_map_class="unordered_map";])
+       fi
+     done
+   done
+   # Now try hash_map
+   for location in ext/hash_map hash_map; do
+     for namespace in __gnu_cxx "" std stdext; do
+       if test -z "$ac_cv_cxx_hash_map"; then
+         AC_TRY_COMPILE([#include <$location>],
+                        [${namespace}::hash_map<int, int> t],
+                        [ac_cv_cxx_hash_map="<$location>";
+                         ac_cv_cxx_hash_namespace="$namespace";
+                         ac_cv_cxx_hash_map_class="hash_map";])
+       fi
+     done
+   done
+   ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`;
+   ac_cv_cxx_hash_set_class=`echo "$ac_cv_cxx_hash_map_class" | sed s/map/set/`;
+   if test -n "$ac_cv_cxx_hash_map"; then
+      AC_DEFINE(HAVE_HASH_MAP, 1, [define if the compiler has hash_map])
+      AC_DEFINE(HAVE_HASH_SET, 1, [define if the compiler has hash_set])
+      AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map,
+                         [the location of <unordered_map> or <hash_map>])
+      AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set,
+                         [the location of <unordered_set> or <hash_set>])
+      AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace,
+                         [the namespace of hash_map/hash_set])
+      AC_DEFINE_UNQUOTED(HASH_MAP_CLASS,$ac_cv_cxx_hash_map_class,
+                         [the name of <hash_map>])
+      AC_DEFINE_UNQUOTED(HASH_SET_CLASS,$ac_cv_cxx_hash_set_class,
+                         [the name of <hash_set>])
+      AC_MSG_RESULT([$ac_cv_cxx_hash_map])
+   else
+      AC_MSG_RESULT()
+      AC_MSG_WARN([could not find an STL hash_map])
+   fi
+])
+
diff --git a/src/third_party/protobuf-3/objectivec/DevTools/check_version_stamps.sh b/src/third_party/protobuf-3/objectivec/DevTools/check_version_stamps.sh
new file mode 100755
index 0000000..325b71d
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/DevTools/check_version_stamps.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+# This script checks that the runtime version number constant in the compiler
+# source and in the runtime source is the same.
+#
+# A distro can be made of the protobuf sources with only a subset of the
+# languages, so if the compiler depended on the Objective C runtime, those
+# builds would break. At the same time, we don't want the runtime source
+# depending on the compiler sources; so two copies of the constant are needed.
+
+set -eu
+
+readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
+readonly ProtoRootDir="${ScriptDir}/../.."
+
+die() {
+    echo "Error: $1"
+    exit 1
+}
+
+readonly ConstantName=GOOGLE_PROTOBUF_OBJC_GEN_VERSION
+
+# Collect version from plugin sources.
+
+readonly PluginSrc="${ProtoRootDir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc"
+readonly PluginVersion=$( \
+    cat "${PluginSrc}" \
+        | sed -n -e "s:const int32 ${ConstantName} = \([0-9]*\);:\1:p"
+)
+
+if [[ -z "${PluginVersion}" ]] ; then
+    die "Failed to find ${ConstantName} in the plugin source (${PluginSrc})."
+fi
+
+# Collect version from runtime sources.
+
+readonly RuntimeSrc="${ProtoRootDir}/objectivec/GPBBootstrap.h"
+readonly RuntimeVersion=$( \
+    cat "${RuntimeSrc}" \
+        | sed -n -e "s:#define ${ConstantName} \([0-9]*\):\1:p"
+)
+
+if [[ -z "${RuntimeVersion}" ]] ; then
+    die "Failed to find ${ConstantName} in the runtime source (${RuntimeSrc})."
+fi
+
+# Compare them.
+
+if [[ "${PluginVersion}" != "${RuntimeVersion}" ]] ; then
+    die "Versions don't match!
+   Plugin: ${PluginVersion} from ${PluginSrc}
+  Runtime: ${RuntimeVersion} from ${RuntimeSrc}
+"
+fi
+
+# Success
diff --git a/src/third_party/protobuf-3/objectivec/DevTools/compile_testing_protos.sh b/src/third_party/protobuf-3/objectivec/DevTools/compile_testing_protos.sh
new file mode 100755
index 0000000..8295313
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/DevTools/compile_testing_protos.sh
@@ -0,0 +1,124 @@
+#!/bin/bash
+
+# Invoked by the Xcode projects to build the protos needed for the unittests.
+
+set -eu
+
+readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos"
+
+# Helper for bailing.
+die() {
+  echo "Error: $1"
+  exit 2
+}
+
+# What to do.
+case "${ACTION}" in
+  "")
+    # Build, fall thru
+    ;;
+  "clean")
+    rm -rf "${OUTPUT_DIR}"
+    exit 0
+    ;;
+  *)
+    die "Unknown action requested: ${ACTION}"
+    ;;
+esac
+
+# Move to the top of the protobuf directories.
+cd "${SRCROOT}/.."
+
+[[ -x src/protoc ]] || \
+  die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)."
+
+RUN_PROTOC=no
+if [[ ! -d "${OUTPUT_DIR}" ]] ; then
+  RUN_PROTOC=yes
+else
+  # Find the newest input file (protos, compiler, and this script).
+  # (these patterns catch some extra stuff, but better to over sample than
+  # under)
+  readonly NewestInput=$(find \
+     src/google/protobuf/*.proto \
+     objectivec/Tests/*.proto \
+     src/.libs src/*.la src/protoc \
+     objectivec/DevTools/compile_testing_protos.sh \
+        -type f -print0 \
+        | xargs -0 stat -f "%m %N" \
+        | sort -n | tail -n1 | cut -f2- -d" ")
+  # Find the oldest output file.
+  readonly OldestOutput=$(find \
+        "${OUTPUT_DIR}" \
+        -type f -print0 \
+        | xargs -0 stat -f "%m %N" \
+        | sort -n -r | tail -n1 | cut -f2- -d" ")
+  # If the newest input is newer than the oldest output, regenerate.
+  if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then
+    RUN_PROTOC=yes
+  fi
+fi
+
+if [[ "${RUN_PROTOC}" != "yes" ]] ; then
+  # Up to date.
+  exit 0
+fi
+
+# Ensure the output dir exists
+mkdir -p "${OUTPUT_DIR}/google/protobuf"
+
+CORE_PROTO_FILES=(
+  src/google/protobuf/unittest_arena.proto
+  src/google/protobuf/unittest_custom_options.proto
+  src/google/protobuf/unittest_enormous_descriptor.proto
+  src/google/protobuf/unittest_embed_optimize_for.proto
+  src/google/protobuf/unittest_empty.proto
+  src/google/protobuf/unittest_import.proto
+  src/google/protobuf/unittest_import_lite.proto
+  src/google/protobuf/unittest_lite.proto
+  src/google/protobuf/unittest_mset.proto
+  src/google/protobuf/unittest_mset_wire_format.proto
+  src/google/protobuf/unittest_no_arena.proto
+  src/google/protobuf/unittest_no_arena_import.proto
+  src/google/protobuf/unittest_no_generic_services.proto
+  src/google/protobuf/unittest_optimize_for.proto
+  src/google/protobuf/unittest.proto
+  src/google/protobuf/unittest_import_public.proto
+  src/google/protobuf/unittest_import_public_lite.proto
+  src/google/protobuf/unittest_drop_unknown_fields.proto
+  src/google/protobuf/unittest_preserve_unknown_enum.proto
+  src/google/protobuf/map_lite_unittest.proto
+  src/google/protobuf/map_proto2_unittest.proto
+  src/google/protobuf/map_unittest.proto
+)
+
+# The unittest_custom_options.proto extends the messages in descriptor.proto
+# so we build it in to test extending in general. The library doesn't provide
+# a descriptor as it doesn't use the classes/enums.
+CORE_PROTO_FILES+=(
+  src/google/protobuf/descriptor.proto
+)
+
+compile_proto() {
+  src/protoc                                   \
+    --objc_out="${OUTPUT_DIR}/google/protobuf" \
+    --proto_path=src/google/protobuf/          \
+    --proto_path=src                           \
+    $*
+}
+
+for a_proto in "${CORE_PROTO_FILES[@]}" ; do
+  compile_proto "${a_proto}"
+done
+
+OBJC_PROTO_FILES=(
+  objectivec/Tests/unittest_cycle.proto
+  objectivec/Tests/unittest_runtime_proto2.proto
+  objectivec/Tests/unittest_runtime_proto3.proto
+  objectivec/Tests/unittest_objc.proto
+  objectivec/Tests/unittest_objc_startup.proto
+)
+
+for a_proto in "${OBJC_PROTO_FILES[@]}" ; do
+  compile_proto --proto_path="objectivec/Tests" "${a_proto}"
+done
diff --git a/src/third_party/protobuf-3/objectivec/DevTools/full_mac_build.sh b/src/third_party/protobuf-3/objectivec/DevTools/full_mac_build.sh
new file mode 100755
index 0000000..ff51d9f
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/DevTools/full_mac_build.sh
@@ -0,0 +1,271 @@
+#!/bin/bash
+#
+# Helper to do build so you don't have to remember all the steps/args.
+
+
+set -eu
+
+# Some base locations.
+readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
+readonly ProtoRootDir="${ScriptDir}/../.."
+
+printUsage() {
+  NAME=$(basename "${0}")
+  cat << EOF
+usage: ${NAME} [OPTIONS]
+
+This script does the common build steps needed.
+
+OPTIONS:
+
+ General:
+
+   -h, --help
+         Show this message
+   -c, --clean
+         Issue a clean before the normal build.
+   -a, --autogen
+         Start by rerunning autogen & configure.
+   -r, --regenerate-descriptors
+         Run generate_descriptor_proto.sh to regenerate all the checked in
+         proto sources.
+   -j #, --jobs #
+         Force the number of parallel jobs (useful for debugging build issues).
+   --core-only
+         Skip some of the core protobuf build/checks to shorten the build time.
+   --skip-xcode
+         Skip the invoke of Xcode to test the runtime on both iOS and OS X.
+   --skip-xcode-ios
+         Skip the invoke of Xcode to test the runtime on iOS.
+   --skip-xcode-osx
+         Skip the invoke of Xcode to test the runtime on OS X.
+   --skip-objc-conformance
+         Skip the Objective C conformance tests (run on OS X).
+
+EOF
+}
+
+header() {
+  echo ""
+  echo "========================================================================"
+  echo "    ${@}"
+  echo "========================================================================"
+}
+
+# Thanks to libtool, builds can fail in odd ways and since it eats some output
+# it can be hard to spot, so force error output if make exits with a non zero.
+wrapped_make() {
+  set +e  # Don't stop if the command fails.
+  make $*
+  MAKE_EXIT_STATUS=$?
+  if [ ${MAKE_EXIT_STATUS} -ne 0 ]; then
+    echo "Error: 'make $*' exited with status ${MAKE_EXIT_STATUS}"
+    exit ${MAKE_EXIT_STATUS}
+  fi
+  set -e
+}
+
+NUM_MAKE_JOBS=$(/usr/sbin/sysctl -n hw.ncpu)
+if [[ "${NUM_MAKE_JOBS}" -lt 4 ]] ; then
+  NUM_MAKE_JOBS=4
+fi
+
+DO_AUTOGEN=no
+DO_CLEAN=no
+REGEN_DESCRIPTORS=no
+CORE_ONLY=no
+DO_XCODE_IOS_TESTS=yes
+DO_XCODE_OSX_TESTS=yes
+DO_OBJC_CONFORMANCE_TESTS=yes
+while [[ $# != 0 ]]; do
+  case "${1}" in
+    -h | --help )
+      printUsage
+      exit 0
+      ;;
+    -c | --clean )
+      DO_CLEAN=yes
+      ;;
+    -a | --autogen )
+      DO_AUTOGEN=yes
+      ;;
+    -r | --regenerate-descriptors )
+      REGEN_DESCRIPTORS=yes
+      ;;
+    -j | --jobs )
+      shift
+      NUM_MAKE_JOBS="${1}"
+      ;;
+    --core-only )
+      CORE_ONLY=yes
+      ;;
+    --skip-xcode )
+      DO_XCODE_IOS_TESTS=no
+      DO_XCODE_OSX_TESTS=no
+      ;;
+    --skip-xcode-ios )
+      DO_XCODE_IOS_TESTS=no
+      ;;
+    --skip-xcode-osx )
+      DO_XCODE_OSX_TESTS=no
+      ;;
+    --skip-objc-conformance )
+      DO_OBJC_CONFORMANCE_TESTS=no
+      ;;
+    -*)
+      echo "ERROR: Unknown option: ${1}" 1>&2
+      printUsage
+      exit 1
+      ;;
+    *)
+      echo "ERROR: Unknown argument: ${1}" 1>&2
+      printUsage
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+# Into the proto dir.
+cd "${ProtoRootDir}"
+
+# if no Makefile, force the autogen.
+if [[ ! -f Makefile ]] ; then
+  DO_AUTOGEN=yes
+fi
+
+if [[ "${DO_AUTOGEN}" == "yes" ]] ; then
+  header "Running autogen & configure"
+  ./autogen.sh
+  ./configure \
+    CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function" \
+    CXXFLAGS="-Wnon-virtual-dtor -Woverloaded-virtual"
+fi
+
+if [[ "${DO_CLEAN}" == "yes" ]] ; then
+  header "Cleaning"
+  wrapped_make clean
+  if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
+    XCODEBUILD_CLEAN_BASE_IOS=(
+      xcodebuild
+        -project objectivec/ProtocolBuffers_iOS.xcodeproj
+        -scheme ProtocolBuffers
+    )
+  "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Debug clean
+  "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Release clean
+  fi
+  if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then
+    XCODEBUILD_CLEAN_BASE_OSX=(
+      xcodebuild
+        -project objectivec/ProtocolBuffers_OSX.xcodeproj
+        -scheme ProtocolBuffers
+    )
+  "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Debug clean
+  "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Release clean
+  fi
+fi
+
+if [[ "${REGEN_DESCRIPTORS}" == "yes" ]] ; then
+  header "Regenerating the descriptor sources."
+  ./generate_descriptor_proto.sh -j "${NUM_MAKE_JOBS}"
+fi
+
+if [[ "${CORE_ONLY}" == "yes" ]] ; then
+  header "Building core Only"
+  wrapped_make -j "${NUM_MAKE_JOBS}"
+else
+  header "Building"
+  # Can't issue these together, when fully parallel, something sometimes chokes
+  # at random.
+  wrapped_make -j "${NUM_MAKE_JOBS}" all
+  wrapped_make -j "${NUM_MAKE_JOBS}" check
+  # Fire off the conformance tests also.
+  cd conformance
+  wrapped_make -j "${NUM_MAKE_JOBS}" test_cpp
+  cd ..
+fi
+
+# Ensure the WKT sources checked in are current.
+objectivec/generate_well_known_types.sh --check-only -j "${NUM_MAKE_JOBS}"
+
+header "Checking on the ObjC Runtime Code"
+objectivec/DevTools/pddm_tests.py
+if ! objectivec/DevTools/pddm.py --dry-run objectivec/*.[hm] objectivec/Tests/*.[hm] ; then
+  echo ""
+  echo "Update by running:"
+  echo "   objectivec/DevTools/pddm.py objectivec/*.[hm] objectivec/Tests/*.[hm]"
+  exit 1
+fi
+
+if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
+  XCODEBUILD_TEST_BASE_IOS=(
+    xcodebuild
+      -project objectivec/ProtocolBuffers_iOS.xcodeproj
+      -scheme ProtocolBuffers
+  )
+  # Don't need to worry about form factors or retina/non retina;
+  # just pick a mix of OS Versions and 32/64 bit.
+  # NOTE: Different Xcode have different simulated hardware/os support.
+  readonly XCODE_VERSION_LINE="$(xcodebuild -version | grep Xcode\  )"
+  readonly XCODE_VERSION="${XCODE_VERSION_LINE/Xcode /}"  # drop the prefix.
+  IOS_SIMULATOR_NAME="Simulator"
+  case "${XCODE_VERSION}" in
+    6.* )
+      echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 7.0 or higher." 1>&2
+      exit 10
+      ;;
+    7.1* )
+      XCODEBUILD_TEST_BASE_IOS+=(
+          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPhone 6,OS=9.0" # 64bit
+          -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPad Air,OS=9.0" # 64bit
+      )
+      ;;
+    7.3* )
+      XCODEBUILD_TEST_BASE_IOS+=(
+          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPhone 6,OS=9.3" # 64bit
+          -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPad Air,OS=9.3" # 64bit
+      )
+      ;;
+    7.* )
+      XCODEBUILD_TEST_BASE_IOS+=(
+          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPhone 6,OS=9.2" # 64bit
+          -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPad Air,OS=9.2" # 64bit
+      )
+      ;;
+    * )
+      echo "Time to update the simulator targets for Xcode ${XCODE_VERSION}"
+      exit 2
+      ;;
+  esac
+  header "Doing Xcode iOS build/tests - Debug"
+  "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Debug test
+  header "Doing Xcode iOS build/tests - Release"
+  "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Release test
+  # Don't leave the simulator in the developer's face.
+  killall "${IOS_SIMULATOR_NAME}"
+fi
+if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then
+  XCODEBUILD_TEST_BASE_OSX=(
+    xcodebuild
+      -project objectivec/ProtocolBuffers_OSX.xcodeproj
+      -scheme ProtocolBuffers
+      # Since the ObjC 2.0 Runtime is required, 32bit OS X isn't supported.
+      -destination "platform=OS X,arch=x86_64" # 64bit
+  )
+  header "Doing Xcode OS X build/tests - Debug"
+  "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Debug test
+  header "Doing Xcode OS X build/tests - Release"
+  "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Release test
+fi
+
+if [[ "${DO_OBJC_CONFORMANCE_TESTS}" == "yes" ]] ; then
+  cd conformance
+  wrapped_make -j "${NUM_MAKE_JOBS}" test_objc
+  cd ..
+fi
diff --git a/src/third_party/protobuf-3/objectivec/DevTools/pddm.py b/src/third_party/protobuf-3/objectivec/DevTools/pddm.py
new file mode 100755
index 0000000..9a11fec
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/DevTools/pddm.py
@@ -0,0 +1,686 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2015 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.
+
+"""PDDM - Poor Developers' Debug-able Macros
+
+A simple markup that can be added in comments of source so they can then be
+expanded out into code. Most of this could be done with CPP macros, but then
+developers can't really step through them in the debugger, this way they are
+expanded to the same code, but you can debug them.
+
+Any file can be processed, but the syntax is designed around a C based compiler.
+Processed lines start with "//%".  There are three types of sections you can
+create: Text (left alone), Macro Definitions, and Macro Expansions.  There is
+no order required between definitions and expansions, all definitions are read
+before any expansions are processed (thus, if desired, definitions can be put
+at the end of the file to keep them out of the way of the code).
+
+Macro Definitions are started with "//%PDDM-DEFINE Name(args)" and all lines
+afterwards that start with "//%" are included in the definition.  Multiple
+macros can be defined in one block by just using a another "//%PDDM-DEFINE"
+line to start the next macro.  Optionally, a macro can be ended with
+"//%PDDM-DEFINE-END", this can be useful when you want to make it clear that
+trailing blank lines are included in the macro.  You can also end a definition
+with an expansion.
+
+Macro Expansions are started by single lines containing
+"//%PDDM-EXPAND Name(args)" and then with "//%PDDM-EXPAND-END" or another
+expansions.  All lines in-between are replaced by the result of the expansion.
+The first line of the expansion is always a blank like just for readability.
+
+Expansion itself is pretty simple, one macro can invoke another macro, but
+you cannot nest the invoke of a macro in another macro (i.e. - can't do
+"foo(bar(a))", but you can define foo(a) and bar(b) where bar invokes foo()
+within its expansion.
+
+When macros are expanded, the arg references can also add "$O" suffix to the
+name (i.e. - "NAME$O") to specify an option to be applied. The options are:
+
+    $S - Replace each character in the value with a space.
+    $l - Lowercase the first letter of the value.
+    $L - Lowercase the whole value.
+    $u - Uppercase the first letter of the value.
+    $U - Uppercase the whole value.
+
+Within a macro you can use ## to cause things to get joined together after
+expansion (i.e. - "a##b" within a macro will become "ab").
+
+Example:
+
+    int foo(MyEnum x) {
+    switch (x) {
+    //%PDDM-EXPAND case(Enum_Left, 1)
+    //%PDDM-EXPAND case(Enum_Center, 2)
+    //%PDDM-EXPAND case(Enum_Right, 3)
+    //%PDDM-EXPAND-END
+    }
+
+    //%PDDM-DEFINE case(_A, _B)
+    //%  case _A:
+    //%    return _B;
+
+  A macro ends at the start of the next one, or an optional %PDDM-DEFINE-END
+  can be used to avoid adding extra blank lines/returns (or make it clear when
+  it is desired).
+
+  One macro can invoke another by simply using its name NAME(ARGS). You cannot
+  nest an invoke inside another (i.e. - NAME1(NAME2(ARGS)) isn't supported).
+
+  Within a macro you can use ## to cause things to get joined together after
+  processing (i.e. - "a##b" within a macro will become "ab").
+
+
+"""
+
+import optparse
+import os
+import re
+import sys
+
+
+# Regex for macro definition.
+_MACRO_RE = re.compile(r'(?P<name>\w+)\((?P<args>.*?)\)')
+# Regex for macro's argument definition.
+_MACRO_ARG_NAME_RE = re.compile(r'^\w+$')
+
+# Line inserted after each EXPAND.
+_GENERATED_CODE_LINE = (
+  '// This block of code is generated, do not edit it directly.'
+)
+
+
+def _MacroRefRe(macro_names):
+  # Takes in a list of macro names and makes a regex that will match invokes
+  # of those macros.
+  return re.compile(r'\b(?P<macro_ref>(?P<name>(%s))\((?P<args>.*?)\))' %
+                    '|'.join(macro_names))
+
+def _MacroArgRefRe(macro_arg_names):
+  # Takes in a list of macro arg names and makes a regex that will match
+  # uses of those args.
+  return re.compile(r'\b(?P<name>(%s))(\$(?P<option>.))?\b' %
+                    '|'.join(macro_arg_names))
+
+
+class PDDMError(Exception):
+  """Error thrown by pddm."""
+  pass
+
+
+class MacroCollection(object):
+  """Hold a set of macros and can resolve/expand them."""
+
+  def __init__(self, a_file=None):
+    """Initializes the collection.
+
+    Args:
+      a_file: The file like stream to parse.
+
+    Raises:
+      PDDMError if there are any issues.
+    """
+    self._macros = dict()
+    if a_file:
+      self.ParseInput(a_file)
+
+  class MacroDefinition(object):
+    """Holds a macro definition."""
+
+    def __init__(self, name, arg_names):
+      self._name = name
+      self._args = tuple(arg_names)
+      self._body = ''
+      self._needNewLine = False
+
+    def AppendLine(self, line):
+      if self._needNewLine:
+        self._body += '\n'
+      self._body += line
+      self._needNewLine = not line.endswith('\n')
+
+    @property
+    def name(self):
+      return self._name
+
+    @property
+    def args(self):
+      return self._args
+
+    @property
+    def body(self):
+      return self._body
+
+  def ParseInput(self, a_file):
+    """Consumes input extracting definitions.
+
+    Args:
+      a_file: The file like stream to parse.
+
+    Raises:
+      PDDMError if there are any issues.
+    """
+    input_lines = a_file.read().splitlines()
+    self.ParseLines(input_lines)
+
+  def ParseLines(self, input_lines):
+    """Parses list of lines.
+
+    Args:
+      input_lines: A list of strings of input to parse (no newlines on the
+                   strings).
+
+    Raises:
+      PDDMError if there are any issues.
+    """
+    current_macro = None
+    for line in input_lines:
+      if line.startswith('PDDM-'):
+        directive = line.split(' ', 1)[0]
+        if directive == 'PDDM-DEFINE':
+          name, args = self._ParseDefineLine(line)
+          if self._macros.get(name):
+            raise PDDMError('Attempt to redefine macro: "%s"' % line)
+          current_macro = self.MacroDefinition(name, args)
+          self._macros[name] = current_macro
+          continue
+        if directive == 'PDDM-DEFINE-END':
+          if not current_macro:
+            raise PDDMError('Got DEFINE-END directive without an active macro:'
+                            ' "%s"' % line)
+          current_macro = None
+          continue
+        raise PDDMError('Hit a line with an unknown directive: "%s"' % line)
+
+      if current_macro:
+        current_macro.AppendLine(line)
+        continue
+
+      # Allow blank lines between macro definitions.
+      if line.strip() == '':
+        continue
+
+      raise PDDMError('Hit a line that wasn\'t a directive and no open macro'
+                      ' definition: "%s"' % line)
+
+  def _ParseDefineLine(self, input_line):
+    assert input_line.startswith('PDDM-DEFINE')
+    line = input_line[12:].strip()
+    match = _MACRO_RE.match(line)
+    # Must match full line
+    if match is None or match.group(0) != line:
+      raise PDDMError('Failed to parse macro definition: "%s"' % input_line)
+    name = match.group('name')
+    args_str = match.group('args').strip()
+    args = []
+    if args_str:
+      for part in args_str.split(','):
+        arg = part.strip()
+        if arg == '':
+          raise PDDMError('Empty arg name in macro definition: "%s"'
+                          % input_line)
+        if not _MACRO_ARG_NAME_RE.match(arg):
+          raise PDDMError('Invalid arg name "%s" in macro definition: "%s"'
+                          % (arg, input_line))
+        if arg in args:
+          raise PDDMError('Arg name "%s" used more than once in macro'
+                          ' definition: "%s"' % (arg, input_line))
+        args.append(arg)
+    return (name, tuple(args))
+
+  def Expand(self, macro_ref_str):
+    """Expands the macro reference.
+
+    Args:
+      macro_ref_str: String of a macro reference (i.e. foo(a, b)).
+
+    Returns:
+      The text from the expansion.
+
+    Raises:
+      PDDMError if there are any issues.
+    """
+    match = _MACRO_RE.match(macro_ref_str)
+    if match is None or match.group(0) != macro_ref_str:
+      raise PDDMError('Failed to parse macro reference: "%s"' % macro_ref_str)
+    if match.group('name') not in self._macros:
+      raise PDDMError('No macro named "%s".' % match.group('name'))
+    return self._Expand(match, [], macro_ref_str)
+
+  def _FormatStack(self, macro_ref_stack):
+    result = ''
+    for _, macro_ref in reversed(macro_ref_stack):
+      result += '\n...while expanding "%s".' % macro_ref
+    return result
+
+  def _Expand(self, macro_ref_match, macro_stack, macro_ref_str=None):
+    if macro_ref_str is None:
+      macro_ref_str = macro_ref_match.group('macro_ref')
+    name = macro_ref_match.group('name')
+    for prev_name, prev_macro_ref in macro_stack:
+      if name == prev_name:
+        raise PDDMError('Found macro recusion, invoking "%s":%s' %
+                        (macro_ref_str, self._FormatStack(macro_stack)))
+    macro = self._macros[name]
+    args_str = macro_ref_match.group('args').strip()
+    args = []
+    if args_str or len(macro.args):
+      args = [x.strip() for x in args_str.split(',')]
+    if len(args) != len(macro.args):
+      raise PDDMError('Expected %d args, got: "%s".%s' %
+                      (len(macro.args), macro_ref_str,
+                       self._FormatStack(macro_stack)))
+    # Replace args usages.
+    result = self._ReplaceArgValues(macro, args, macro_ref_str, macro_stack)
+    # Expand any macro invokes.
+    new_macro_stack = macro_stack + [(name, macro_ref_str)]
+    while True:
+      eval_result = self._EvalMacrosRefs(result, new_macro_stack)
+      # Consume all ## directives to glue things together.
+      eval_result = eval_result.replace('##', '')
+      if eval_result == result:
+        break
+      result = eval_result
+    return result
+
+  def _ReplaceArgValues(self,
+                        macro, arg_values, macro_ref_to_report, macro_stack):
+    if len(arg_values) == 0:
+      # Nothing to do
+      return macro.body
+    assert len(arg_values) == len(macro.args)
+    args = dict(zip(macro.args, arg_values))
+    def _lookupArg(match):
+      val = args[match.group('name')]
+      opt = match.group('option')
+      if opt:
+        if opt == 'S': # Spaces for the length
+          return ' ' * len(val)
+        elif opt == 'l': # Lowercase first character
+          if val:
+            return val[0].lower() + val[1:]
+          else:
+            return val
+        elif opt == 'L': # All Lowercase
+          return val.lower()
+        elif opt == 'u': # Uppercase first character
+          if val:
+            return val[0].upper() + val[1:]
+          else:
+            return val
+        elif opt == 'U': # All Uppercase
+          return val.upper()
+        else:
+          raise PDDMError('Unknown arg option "%s$%s" while expanding "%s".%s'
+                          % (match.group('name'), match.group('option'),
+                             macro_ref_to_report,
+                             self._FormatStack(macro_stack)))
+      return val
+    # Let the regex do the work!
+    macro_arg_ref_re = _MacroArgRefRe(macro.args)
+    return macro_arg_ref_re.sub(_lookupArg, macro.body)
+
+  def _EvalMacrosRefs(self, text, macro_stack):
+    macro_ref_re = _MacroRefRe(self._macros.keys())
+    def _resolveMacro(match):
+      return self._Expand(match, macro_stack)
+    return macro_ref_re.sub(_resolveMacro, text)
+
+
+class SourceFile(object):
+  """Represents a source file with PDDM directives in it."""
+
+  def __init__(self, a_file, import_resolver=None):
+    """Initializes the file reading in the file.
+
+    Args:
+      a_file: The file to read in.
+      import_resolver: a function that given a path will return a stream for
+        the contents.
+
+    Raises:
+      PDDMError if there are any issues.
+    """
+    self._sections = []
+    self._original_content = a_file.read()
+    self._import_resolver = import_resolver
+    self._processed_content = None
+
+  class SectionBase(object):
+
+    def __init__(self, first_line_num):
+      self._lines = []
+      self._first_line_num = first_line_num
+
+    def TryAppend(self, line, line_num):
+      """Try appending a line.
+
+      Args:
+        line: The line to append.
+        line_num: The number of the line.
+
+      Returns:
+        A tuple of (SUCCESS, CAN_ADD_MORE).  If SUCCESS if False, the line
+        wasn't append.  If SUCCESS is True, then CAN_ADD_MORE is True/False to
+        indicate if more lines can be added after this one.
+      """
+      assert False, "sublcass should have overridden"
+      return (False, False)
+
+    def HitEOF(self):
+      """Called when the EOF was reached for for a given section."""
+      pass
+
+    def BindMacroCollection(self, macro_collection):
+      """Binds the chunk to a macro collection.
+
+      Args:
+        macro_collection: The collection to bind too.
+      """
+      pass
+
+    def Append(self, line):
+      self._lines.append(line)
+
+    @property
+    def lines(self):
+      return self._lines
+
+    @property
+    def num_lines_captured(self):
+      return len(self._lines)
+
+    @property
+    def first_line_num(self):
+      return self._first_line_num
+
+    @property
+    def first_line(self):
+      if not self._lines:
+        return ''
+      return self._lines[0]
+
+    @property
+    def text(self):
+      return '\n'.join(self.lines) + '\n'
+
+  class TextSection(SectionBase):
+    """Text section that is echoed out as is."""
+
+    def TryAppend(self, line, line_num):
+      if line.startswith('//%PDDM'):
+        return (False, False)
+      self.Append(line)
+      return (True, True)
+
+  class ExpansionSection(SectionBase):
+    """Section that is the result of an macro expansion."""
+
+    def __init__(self, first_line_num):
+      SourceFile.SectionBase.__init__(self, first_line_num)
+      self._macro_collection = None
+
+    def TryAppend(self, line, line_num):
+      if line.startswith('//%PDDM'):
+        directive = line.split(' ', 1)[0]
+        if directive == '//%PDDM-EXPAND':
+          self.Append(line)
+          return (True, True)
+        if directive == '//%PDDM-EXPAND-END':
+          assert self.num_lines_captured > 0
+          return (True, False)
+        raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' %
+                        (directive, line_num, self.first_line))
+      # Eat other lines.
+      return (True, True)
+
+    def HitEOF(self):
+      raise PDDMError('Hit the end of the file while in "%s".' %
+                      self.first_line)
+
+    def BindMacroCollection(self, macro_collection):
+      self._macro_collection = macro_collection
+
+    @property
+    def lines(self):
+      captured_lines = SourceFile.SectionBase.lines.fget(self)
+      directive_len = len('//%PDDM-EXPAND')
+      result = []
+      for line in captured_lines:
+        result.append(line)
+        if self._macro_collection:
+          # Always add a blank line, seems to read better. (If need be, add an
+          # option to the EXPAND to indicate if this should be done.)
+          result.extend([_GENERATED_CODE_LINE, ''])
+          macro = line[directive_len:].strip()
+          try:
+            expand_result = self._macro_collection.Expand(macro)
+            # Since expansions are line oriented, strip trailing whitespace
+            # from the lines.
+            lines = [x.rstrip() for x in expand_result.split('\n')]
+            result.append('\n'.join(lines))
+          except PDDMError as e:
+            raise PDDMError('%s\n...while expanding "%s" from the section'
+                            ' that started:\n   Line %d: %s' %
+                            (e.message, macro,
+                             self.first_line_num, self.first_line))
+
+      # Add the ending marker.
+      if len(captured_lines) == 1:
+        result.append('//%%PDDM-EXPAND-END %s' %
+                       captured_lines[0][directive_len:].strip())
+      else:
+        result.append('//%%PDDM-EXPAND-END (%s expansions)' % len(captured_lines))
+
+      return result
+
+  class DefinitionSection(SectionBase):
+    """Section containing macro definitions"""
+
+    def TryAppend(self, line, line_num):
+      if not line.startswith('//%'):
+        return (False, False)
+      if line.startswith('//%PDDM'):
+        directive = line.split(' ', 1)[0]
+        if directive == "//%PDDM-EXPAND":
+          return False, False
+        if directive not in ('//%PDDM-DEFINE', '//%PDDM-DEFINE-END'):
+          raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' %
+                          (directive, line_num, self.first_line))
+      self.Append(line)
+      return (True, True)
+
+    def BindMacroCollection(self, macro_collection):
+      if macro_collection:
+        try:
+          # Parse the lines after stripping the prefix.
+          macro_collection.ParseLines([x[3:] for x in self.lines])
+        except PDDMError as e:
+          raise PDDMError('%s\n...while parsing section that started:\n'
+                          '  Line %d: %s' %
+                          (e.message, self.first_line_num, self.first_line))
+
+  class ImportDefinesSection(SectionBase):
+    """Section containing an import of PDDM-DEFINES from an external file."""
+
+    def __init__(self, first_line_num, import_resolver):
+      SourceFile.SectionBase.__init__(self, first_line_num)
+      self._import_resolver = import_resolver
+
+    def TryAppend(self, line, line_num):
+      if not line.startswith('//%PDDM-IMPORT-DEFINES '):
+        return (False, False)
+      assert self.num_lines_captured == 0
+      self.Append(line)
+      return (True, False)
+
+    def BindMacroCollection(self, macro_colletion):
+      if not macro_colletion:
+        return
+      if self._import_resolver is None:
+        raise PDDMError('Got an IMPORT-DEFINES without a resolver (line %d):'
+                        ' "%s".' % (self.first_line_num, self.first_line))
+      import_name = self.first_line.split(' ', 1)[1].strip()
+      imported_file = self._import_resolver(import_name)
+      if imported_file is None:
+        raise PDDMError('Resolver failed to find "%s" (line %d):'
+                        ' "%s".' %
+                        (import_name, self.first_line_num, self.first_line))
+      try:
+        imported_src_file = SourceFile(imported_file, self._import_resolver)
+        imported_src_file._ParseFile()
+        for section in imported_src_file._sections:
+          section.BindMacroCollection(macro_colletion)
+      except PDDMError as e:
+        raise PDDMError('%s\n...while importing defines:\n'
+                        '  Line %d: %s' %
+                        (e.message, self.first_line_num, self.first_line))
+
+  def _ParseFile(self):
+    self._sections = []
+    lines = self._original_content.splitlines()
+    cur_section = None
+    for line_num, line in enumerate(lines, 1):
+      if not cur_section:
+        cur_section = self._MakeSection(line, line_num)
+      was_added, accept_more = cur_section.TryAppend(line, line_num)
+      if not was_added:
+        cur_section = self._MakeSection(line, line_num)
+        was_added, accept_more = cur_section.TryAppend(line, line_num)
+        assert was_added
+      if not accept_more:
+        cur_section = None
+
+    if cur_section:
+      cur_section.HitEOF()
+
+  def _MakeSection(self, line, line_num):
+    if not line.startswith('//%PDDM'):
+      section = self.TextSection(line_num)
+    else:
+      directive = line.split(' ', 1)[0]
+      if directive == '//%PDDM-EXPAND':
+        section = self.ExpansionSection(line_num)
+      elif directive == '//%PDDM-DEFINE':
+        section = self.DefinitionSection(line_num)
+      elif directive == '//%PDDM-IMPORT-DEFINES':
+        section = self.ImportDefinesSection(line_num, self._import_resolver)
+      else:
+        raise PDDMError('Unexpected line %d: "%s".' % (line_num, line))
+    self._sections.append(section)
+    return section
+
+  def ProcessContent(self, strip_expansion=False):
+    """Processes the file contents."""
+    self._ParseFile()
+    if strip_expansion:
+      # Without a collection the expansions become blank, removing them.
+      collection = None
+    else:
+      collection = MacroCollection()
+    for section in self._sections:
+      section.BindMacroCollection(collection)
+    result = ''
+    for section in self._sections:
+      result += section.text
+    self._processed_content = result
+
+  @property
+  def original_content(self):
+    return self._original_content
+
+  @property
+  def processed_content(self):
+    return self._processed_content
+
+
+def main(args):
+  usage = '%prog [OPTIONS] PATH ...'
+  description = (
+      'Processes PDDM directives in the given paths and write them back out.'
+  )
+  parser = optparse.OptionParser(usage=usage, description=description)
+  parser.add_option('--dry-run',
+                    default=False, action='store_true',
+                    help='Don\'t write back to the file(s), just report if the'
+                    ' contents needs an update and exit with a value of 1.')
+  parser.add_option('--verbose',
+                    default=False, action='store_true',
+                    help='Reports is a file is already current.')
+  parser.add_option('--collapse',
+                    default=False, action='store_true',
+                    help='Removes all the generated code.')
+  opts, extra_args = parser.parse_args(args)
+
+  if not extra_args:
+    parser.error('Need atleast one file to process')
+
+  result = 0
+  for a_path in extra_args:
+    if not os.path.exists(a_path):
+      sys.stderr.write('ERROR: File not found: %s\n' % a_path)
+      return 100
+
+    def _ImportResolver(name):
+      # resolve based on the file being read.
+      a_dir = os.path.dirname(a_path)
+      import_path = os.path.join(a_dir, name)
+      if not os.path.exists(import_path):
+        return None
+      return open(import_path, 'r')
+
+    with open(a_path, 'r') as f:
+      src_file = SourceFile(f, _ImportResolver)
+
+    try:
+      src_file.ProcessContent(strip_expansion=opts.collapse)
+    except PDDMError as e:
+      sys.stderr.write('ERROR: %s\n...While processing "%s"\n' %
+                       (e.message, a_path))
+      return 101
+
+    if src_file.processed_content != src_file.original_content:
+      if not opts.dry_run:
+        print 'Updating for "%s".' % a_path
+        with open(a_path, 'w') as f:
+          f.write(src_file.processed_content)
+      else:
+        # Special result to indicate things need updating.
+        print 'Update needed for "%s".' % a_path
+        result = 1
+    elif opts.verbose:
+      print 'No update for "%s".' % a_path
+
+  return result
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/src/third_party/protobuf-3/objectivec/DevTools/pddm_tests.py b/src/third_party/protobuf-3/objectivec/DevTools/pddm_tests.py
new file mode 100755
index 0000000..8a73b84
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/DevTools/pddm_tests.py
@@ -0,0 +1,515 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2015 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.
+
+"""Tests for pddm.py."""
+
+import io
+import unittest
+
+import pddm
+
+
+class TestParsingMacros(unittest.TestCase):
+
+  def testParseEmpty(self):
+    f = io.StringIO(u'')
+    result = pddm.MacroCollection(f)
+    self.assertEqual(len(result._macros), 0)
+
+  def testParseOne(self):
+    f = io.StringIO(u"""PDDM-DEFINE foo( )
+body""")
+    result = pddm.MacroCollection(f)
+    self.assertEqual(len(result._macros), 1)
+    macro = result._macros.get('foo')
+    self.assertIsNotNone(macro)
+    self.assertEquals(macro.name, 'foo')
+    self.assertEquals(macro.args, tuple())
+    self.assertEquals(macro.body, 'body')
+
+  def testParseGeneral(self):
+    # Tests multiple defines, spaces in all places, etc.
+    f = io.StringIO(u"""
+PDDM-DEFINE noArgs( )
+body1
+body2
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE oneArg(foo)
+body3
+PDDM-DEFINE  twoArgs( bar_ , baz )
+body4
+body5""")
+    result = pddm.MacroCollection(f)
+    self.assertEqual(len(result._macros), 3)
+    macro = result._macros.get('noArgs')
+    self.assertIsNotNone(macro)
+    self.assertEquals(macro.name, 'noArgs')
+    self.assertEquals(macro.args, tuple())
+    self.assertEquals(macro.body, 'body1\nbody2\n')
+    macro = result._macros.get('oneArg')
+    self.assertIsNotNone(macro)
+    self.assertEquals(macro.name, 'oneArg')
+    self.assertEquals(macro.args, ('foo',))
+    self.assertEquals(macro.body, 'body3')
+    macro = result._macros.get('twoArgs')
+    self.assertIsNotNone(macro)
+    self.assertEquals(macro.name, 'twoArgs')
+    self.assertEquals(macro.args, ('bar_', 'baz'))
+    self.assertEquals(macro.body, 'body4\nbody5')
+    # Add into existing collection
+    f = io.StringIO(u"""
+PDDM-DEFINE another(a,b,c)
+body1
+body2""")
+    result.ParseInput(f)
+    self.assertEqual(len(result._macros), 4)
+    macro = result._macros.get('another')
+    self.assertIsNotNone(macro)
+    self.assertEquals(macro.name, 'another')
+    self.assertEquals(macro.args, ('a', 'b', 'c'))
+    self.assertEquals(macro.body, 'body1\nbody2')
+
+  def testParseDirectiveIssues(self):
+    test_list = [
+      # Unknown directive
+      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz',
+       'Hit a line with an unknown directive: '),
+      # End without begin
+      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n',
+       'Got DEFINE-END directive without an active macro: '),
+      # Line not in macro block
+      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n',
+       'Hit a line that wasn\'t a directive and no open macro definition: '),
+      # Redefine macro
+      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n',
+       'Attempt to redefine macro: '),
+    ]
+    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
+      f = io.StringIO(input_str)
+      try:
+        result = pddm.MacroCollection(f)
+        self.fail('Should throw exception, entry %d' % idx)
+      except pddm.PDDMError as e:
+        self.assertTrue(e.message.startswith(expected_prefix),
+                        'Entry %d failed: %r' % (idx, e))
+
+  def testParseBeginIssues(self):
+    test_list = [
+      # 1. No name
+      (u'PDDM-DEFINE\nmumble',
+       'Failed to parse macro definition: '),
+      # 2. No name (with spaces)
+      (u'PDDM-DEFINE  \nmumble',
+       'Failed to parse macro definition: '),
+      # 3. No open paren
+      (u'PDDM-DEFINE  foo\nmumble',
+       'Failed to parse macro definition: '),
+      # 4. No close paren
+      (u'PDDM-DEFINE foo(\nmumble',
+       'Failed to parse macro definition: '),
+      # 5. No close paren (with args)
+      (u'PDDM-DEFINE foo(a, b\nmumble',
+       'Failed to parse macro definition: '),
+      # 6. No name before args
+      (u'PDDM-DEFINE  (a, b)\nmumble',
+       'Failed to parse macro definition: '),
+      # 7. No name before args
+      (u'PDDM-DEFINE foo bar(a, b)\nmumble',
+       'Failed to parse macro definition: '),
+      # 8. Empty arg name
+      (u'PDDM-DEFINE foo(a, ,b)\nmumble',
+       'Empty arg name in macro definition: '),
+      (u'PDDM-DEFINE foo(a,,b)\nmumble',
+       'Empty arg name in macro definition: '),
+      # 10. Duplicate name
+      (u'PDDM-DEFINE foo(a,b,a,c)\nmumble',
+       'Arg name "a" used more than once in macro definition: '),
+      # 11. Invalid arg name
+      (u'PDDM-DEFINE foo(a b,c)\nmumble',
+       'Invalid arg name "a b" in macro definition: '),
+      (u'PDDM-DEFINE foo(a.b,c)\nmumble',
+       'Invalid arg name "a.b" in macro definition: '),
+      (u'PDDM-DEFINE foo(a-b,c)\nmumble',
+       'Invalid arg name "a-b" in macro definition: '),
+      (u'PDDM-DEFINE foo(a,b,c.)\nmumble',
+       'Invalid arg name "c." in macro definition: '),
+      # 15. Extra stuff after the name
+      (u'PDDM-DEFINE foo(a,c) foo\nmumble',
+       'Failed to parse macro definition: '),
+      (u'PDDM-DEFINE foo(a,c) foo)\nmumble',
+       'Failed to parse macro definition: '),
+    ]
+    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
+      f = io.StringIO(input_str)
+      try:
+        result = pddm.MacroCollection(f)
+        self.fail('Should throw exception, entry %d' % idx)
+      except pddm.PDDMError as e:
+        self.assertTrue(e.message.startswith(expected_prefix),
+                        'Entry %d failed: %r' % (idx, e))
+
+
+class TestExpandingMacros(unittest.TestCase):
+
+  def testExpandBasics(self):
+    f = io.StringIO(u"""
+PDDM-DEFINE noArgs( )
+body1
+body2
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE oneArg(a)
+body3 a
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE twoArgs(b,c)
+body4 b c
+body5
+PDDM-DEFINE-END
+
+""")
+    mc = pddm.MacroCollection(f)
+    test_list = [
+      (u'noArgs()',
+       'body1\nbody2\n'),
+      (u'oneArg(wee)',
+       'body3 wee\n'),
+      (u'twoArgs(having some, fun)',
+       'body4 having some fun\nbody5'),
+      # One arg, pass empty.
+      (u'oneArg()',
+       'body3 \n'),
+      # Two args, gets empty in each slot.
+      (u'twoArgs(, empty)',
+       'body4  empty\nbody5'),
+      (u'twoArgs(empty, )',
+       'body4 empty \nbody5'),
+      (u'twoArgs(, )',
+       'body4  \nbody5'),
+    ]
+    for idx, (input_str, expected) in enumerate(test_list, 1):
+      result = mc.Expand(input_str)
+      self.assertEqual(result, expected,
+                       'Entry %d --\n       Result: %r\n     Expected: %r' %
+                       (idx, result, expected))
+
+  def testExpandArgOptions(self):
+    f = io.StringIO(u"""
+PDDM-DEFINE bar(a)
+a-a$S-a$l-a$L-a$u-a$U
+PDDM-DEFINE-END
+""")
+    mc = pddm.MacroCollection(f)
+
+    self.assertEqual(mc.Expand('bar(xYz)'), 'xYz-   -xYz-xyz-XYz-XYZ')
+    self.assertEqual(mc.Expand('bar(MnoP)'), 'MnoP-    -mnoP-mnop-MnoP-MNOP')
+    # Test empty
+    self.assertEqual(mc.Expand('bar()'), '-----')
+
+  def testExpandSimpleMacroErrors(self):
+    f = io.StringIO(u"""
+PDDM-DEFINE foo(a, b)
+<a-z>
+PDDM-DEFINE baz(a)
+a - a$z
+""")
+    mc = pddm.MacroCollection(f)
+    test_list = [
+      # 1. Unknown macro
+      (u'bar()',
+       'No macro named "bar".'),
+      (u'bar(a)',
+       'No macro named "bar".'),
+      # 3. Arg mismatch
+      (u'foo()',
+       'Expected 2 args, got: "foo()".'),
+      (u'foo(a b)',
+       'Expected 2 args, got: "foo(a b)".'),
+      (u'foo(a,b,c)',
+       'Expected 2 args, got: "foo(a,b,c)".'),
+      # 6. Unknown option in expansion
+      (u'baz(mumble)',
+       'Unknown arg option "a$z" while expanding "baz(mumble)".'),
+    ]
+    for idx, (input_str, expected_err) in enumerate(test_list, 1):
+      try:
+        result = mc.Expand(input_str)
+        self.fail('Should throw exception, entry %d' % idx)
+      except pddm.PDDMError as e:
+        self.assertEqual(e.message, expected_err,
+                        'Entry %d failed: %r' % (idx, e))
+
+  def testExpandReferences(self):
+    f = io.StringIO(u"""
+PDDM-DEFINE StartIt()
+foo(abc, def)
+foo(ghi, jkl)
+PDDM-DEFINE foo(a, b)
+bar(a, int)
+bar(b, NSString *)
+PDDM-DEFINE bar(n, t)
+- (t)n;
+- (void)set##n$u##:(t)value;
+
+""")
+    mc = pddm.MacroCollection(f)
+    expected = """- (int)abc;
+- (void)setAbc:(int)value;
+
+- (NSString *)def;
+- (void)setDef:(NSString *)value;
+
+- (int)ghi;
+- (void)setGhi:(int)value;
+
+- (NSString *)jkl;
+- (void)setJkl:(NSString *)value;
+"""
+    self.assertEqual(mc.Expand('StartIt()'), expected)
+
+  def testCatchRecursion(self):
+    f = io.StringIO(u"""
+PDDM-DEFINE foo(a, b)
+bar(1, a)
+bar(2, b)
+PDDM-DEFINE bar(x, y)
+foo(x, y)
+""")
+    mc = pddm.MacroCollection(f)
+    try:
+      result = mc.Expand('foo(A,B)')
+      self.fail('Should throw exception, entry %d' % idx)
+    except pddm.PDDMError as e:
+      self.assertEqual(e.message,
+                       'Found macro recusion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".')
+
+
+class TestParsingSource(unittest.TestCase):
+
+  def testBasicParse(self):
+    test_list = [
+      # 1. no directives
+      (u'a\nb\nc',
+       (3,) ),
+      # 2. One define
+      (u'a\n//%PDDM-DEFINE foo()\n//%body\nc',
+       (1, 2, 1) ),
+      # 3. Two defines
+      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc',
+       (1, 4, 1) ),
+      # 4. Two defines with ends
+      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE-END\n'
+       u'//%PDDM-DEFINE bar()\n//%body2\n//%PDDM-DEFINE-END\nc',
+       (1, 6, 1) ),
+      # 5. One expand, one define (that runs to end of file)
+      (u'a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n'
+       u'//%PDDM-DEFINE bar()\n//%body2\n',
+       (1, 1, 2) ),
+      # 6. One define ended with an expand.
+      (u'a\nb\n//%PDDM-DEFINE bar()\n//%body2\n'
+       u'//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n',
+       (2, 2, 1) ),
+      # 7. Two expands (one end), one define.
+      (u'a\n//%PDDM-EXPAND foo(1)\nbody\n//%PDDM-EXPAND foo(2)\nbody2\n//%PDDM-EXPAND-END\n'
+       u'//%PDDM-DEFINE foo()\n//%body2\n',
+       (1, 2, 2) ),
+    ]
+    for idx, (input_str, line_counts) in enumerate(test_list, 1):
+      f = io.StringIO(input_str)
+      sf = pddm.SourceFile(f)
+      sf._ParseFile()
+      self.assertEqual(len(sf._sections), len(line_counts),
+                       'Entry %d -- %d != %d' %
+                       (idx, len(sf._sections), len(line_counts)))
+      for idx2, (sec, expected) in enumerate(zip(sf._sections, line_counts), 1):
+        self.assertEqual(sec.num_lines_captured, expected,
+                         'Entry %d, section %d -- %d != %d' %
+                         (idx, idx2, sec.num_lines_captured, expected))
+
+  def testErrors(self):
+    test_list = [
+      # 1. Directive within expansion
+      (u'//%PDDM-EXPAND a()\n//%PDDM-BOGUS',
+       'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'),
+      (u'//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n',
+       'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'),
+      # 3. Expansion ran off end of file
+      (u'//%PDDM-EXPAND a()\na\nb\n',
+       'Hit the end of the file while in "//%PDDM-EXPAND a()".'),
+      # 4. Directive within define
+      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS',
+       'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'),
+      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()',
+       'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'),
+      # 6. Directives that shouldn't start sections
+      (u'a\n//%PDDM-DEFINE-END a()\n//a\n',
+       'Unexpected line 2: "//%PDDM-DEFINE-END a()".'),
+      (u'a\n//%PDDM-EXPAND-END a()\n//a\n',
+       'Unexpected line 2: "//%PDDM-EXPAND-END a()".'),
+      (u'//%PDDM-BOGUS\n//a\n',
+       'Unexpected line 1: "//%PDDM-BOGUS".'),
+    ]
+    for idx, (input_str, expected_err) in enumerate(test_list, 1):
+      f = io.StringIO(input_str)
+      try:
+        pddm.SourceFile(f)._ParseFile()
+        self.fail('Should throw exception, entry %d' % idx)
+      except pddm.PDDMError as e:
+        self.assertEqual(e.message, expected_err,
+                        'Entry %d failed: %r' % (idx, e))
+
+class TestProcessingSource(unittest.TestCase):
+
+  def testBasics(self):
+    input_str = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+//%PDDM-EXPAND-END
+bar
+//%PDDM-EXPAND mumble(def)
+//%PDDM-EXPAND mumble(ghi)
+//%PDDM-EXPAND-END
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+    input_str2 = u"""
+//%PDDM-DEFINE getName(x_)
+//%do##x_$u##(int x_);
+
+"""
+    expected = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+// This block of code is generated, do not edit it directly.
+
+abc: doAbc(int abc);
+//%PDDM-EXPAND-END mumble(abc)
+bar
+//%PDDM-EXPAND mumble(def)
+// This block of code is generated, do not edit it directly.
+
+def: doDef(int def);
+//%PDDM-EXPAND mumble(ghi)
+// This block of code is generated, do not edit it directly.
+
+ghi: doGhi(int ghi);
+//%PDDM-EXPAND-END (2 expansions)
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+    expected_stripped = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+//%PDDM-EXPAND-END mumble(abc)
+bar
+//%PDDM-EXPAND mumble(def)
+//%PDDM-EXPAND mumble(ghi)
+//%PDDM-EXPAND-END (2 expansions)
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+    def _Resolver(name):
+      self.assertEqual(name, 'ImportFile')
+      return io.StringIO(input_str2)
+    f = io.StringIO(input_str)
+    sf = pddm.SourceFile(f, _Resolver)
+    sf.ProcessContent()
+    self.assertEqual(sf.processed_content, expected)
+    # Feed it through and nothing should change.
+    f2 = io.StringIO(sf.processed_content)
+    sf2 = pddm.SourceFile(f2, _Resolver)
+    sf2.ProcessContent()
+    self.assertEqual(sf2.processed_content, expected)
+    self.assertEqual(sf2.processed_content, sf.processed_content)
+    # Test stripping (with the original input and expanded version).
+    f2 = io.StringIO(input_str)
+    sf2 = pddm.SourceFile(f2)
+    sf2.ProcessContent(strip_expansion=True)
+    self.assertEqual(sf2.processed_content, expected_stripped)
+    f2 = io.StringIO(sf.processed_content)
+    sf2 = pddm.SourceFile(f2, _Resolver)
+    sf2.ProcessContent(strip_expansion=True)
+    self.assertEqual(sf2.processed_content, expected_stripped)
+
+  def testProcessFileWithMacroParseError(self):
+    input_str = u"""
+foo
+//%PDDM-DEFINE mumble(a_)
+//%body
+//%PDDM-DEFINE mumble(x_)
+//%body2
+
+"""
+    f = io.StringIO(input_str)
+    sf = pddm.SourceFile(f)
+    try:
+      sf.ProcessContent()
+      self.fail('Should throw exception, entry %d' % idx)
+    except pddm.PDDMError as e:
+      self.assertEqual(e.message,
+                       'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n'
+                       '...while parsing section that started:\n'
+                       '  Line 3: //%PDDM-DEFINE mumble(a_)')
+
+  def testProcessFileWithExpandError(self):
+    input_str = u"""
+foo
+//%PDDM-DEFINE mumble(a_)
+//%body
+//%PDDM-EXPAND foobar(x_)
+//%PDDM-EXPAND-END
+
+"""
+    f = io.StringIO(input_str)
+    sf = pddm.SourceFile(f)
+    try:
+      sf.ProcessContent()
+      self.fail('Should throw exception, entry %d' % idx)
+    except pddm.PDDMError as e:
+      self.assertEqual(e.message,
+                       'No macro named "foobar".\n'
+                       '...while expanding "foobar(x_)" from the section that'
+                       ' started:\n   Line 5: //%PDDM-EXPAND foobar(x_)')
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/objectivec/GPBArray.h b/src/third_party/protobuf-3/objectivec/GPBArray.h
new file mode 100644
index 0000000..afda57f
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBArray.h
@@ -0,0 +1,549 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBRuntimeTypes.h"
+
+// These classes are used for repeated fields of basic data types. They are used because
+// they perform better than boxing into NSNumbers in NSArrays.
+
+// Note: These are not meant to be subclassed.
+
+NS_ASSUME_NONNULL_BEGIN
+
+//%PDDM-EXPAND DECLARE_ARRAYS()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(int32_t)value;
++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const int32_t [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBInt32Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (int32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(int32_t)value;
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBInt32Array *)array;
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - UInt32
+
+@interface GPBUInt32Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(uint32_t)value;
++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const uint32_t [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBUInt32Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (uint32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(uint32_t)value;
+- (void)addValues:(const uint32_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBUInt32Array *)array;
+
+- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Int64
+
+@interface GPBInt64Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(int64_t)value;
++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const int64_t [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBInt64Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (int64_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(int64_t)value;
+- (void)addValues:(const int64_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBInt64Array *)array;
+
+- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - UInt64
+
+@interface GPBUInt64Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(uint64_t)value;
++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const uint64_t [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBUInt64Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (uint64_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(uint64_t)value;
+- (void)addValues:(const uint64_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBUInt64Array *)array;
+
+- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Float
+
+@interface GPBFloatArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(float)value;
++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const float [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBFloatArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (float)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(float)value;
+- (void)addValues:(const float [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBFloatArray *)array;
+
+- (void)insertValue:(float)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Double
+
+@interface GPBDoubleArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(double)value;
++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const double [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBDoubleArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (double)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(double)value;
+- (void)addValues:(const double [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBDoubleArray *)array;
+
+- (void)insertValue:(double)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Bool
+
+@interface GPBBoolArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(BOOL)value;
++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const BOOL [])values
+                         count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBBoolArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (BOOL)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(BOOL)value;
+- (void)addValues:(const BOOL [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBBoolArray *)array;
+
+- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Enum
+
+@interface GPBEnumArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)array;
++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                   rawValue:(int32_t)value;
++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array;
++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                   capacity:(NSUInteger)count;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+    NS_DESIGNATED_INITIALIZER;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                     count:(NSUInteger)count;
+- (instancetype)initWithValueArray:(GPBEnumArray *)array;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)count;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a
+// valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (int32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (int32_t)rawValueAtIndex:(NSUInteger)index;
+
+- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+                           usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)addValue:(int32_t)value;
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
+
+// These methods bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+
+- (void)addRawValue:(int32_t)value;
+- (void)addRawValuesFromArray:(GPBEnumArray *)array;
+- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count;
+
+- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value;
+
+// No validation applies to these methods.
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+//%PDDM-EXPAND-END DECLARE_ARRAYS()
+
+NS_ASSUME_NONNULL_END
+
+//%PDDM-DEFINE DECLARE_ARRAYS()
+//%ARRAY_INTERFACE_SIMPLE(Int32, int32_t)
+//%ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t)
+//%ARRAY_INTERFACE_SIMPLE(Int64, int64_t)
+//%ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t)
+//%ARRAY_INTERFACE_SIMPLE(Float, float)
+//%ARRAY_INTERFACE_SIMPLE(Double, double)
+//%ARRAY_INTERFACE_SIMPLE(Bool, BOOL)
+//%ARRAY_INTERFACE_ENUM(Enum, int32_t)
+
+//
+// The common case (everything but Enum)
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%
+//%+ (instancetype)array;
+//%+ (instancetype)arrayWithValue:(TYPE)value;
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+//%
+//%- (instancetype)init NS_DESIGNATED_INITIALIZER;
+//%// Initializes the array, copying the values.
+//%- (instancetype)initWithValues:(const TYPE [])values
+//%                         count:(NSUInteger)count;
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%- (instancetype)initWithCapacity:(NSUInteger)count;
+//%
+//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, Basic)
+//%
+//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, Basic)
+//%
+//%@end
+//%
+
+//
+// Macros specific to Enums (to tweak their interface).
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_ENUM(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+//%
+//%+ (instancetype)array;
+//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                   rawValue:(TYPE)value;
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                   capacity:(NSUInteger)count;
+//%
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%    NS_DESIGNATED_INITIALIZER;
+//%
+//%// Initializes the array, copying the values.
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                 rawValues:(const TYPE [])values
+//%                                     count:(NSUInteger)count;
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                  capacity:(NSUInteger)count;
+//%
+//%// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a
+//%// valid enumerator as defined by validationFunc. If the actual value is
+//%// desired, use "raw" version of the method.
+//%
+//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, NAME)
+//%
+//%// These methods bypass the validationFunc to provide access to values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (TYPE)rawValueAtIndex:(NSUInteger)index;
+//%
+//%- (void)enumerateRawValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+//%                           usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%
+//%// If value is not a valid enumerator as defined by validationFunc, these
+//%// methods will assert in debug, and will log in release and assign the value
+//%// to the default value. Use the rawValue methods below to assign non enumerator
+//%// values.
+//%
+//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, NAME)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%- (TYPE)valueAtIndex:(NSUInteger)index;
+//%
+//%- (void)enumerateValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+//%                        usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+
+//%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%- (void)addValue:(TYPE)value;
+//%- (void)addValues:(const TYPE [])values count:(NSUInteger)count;
+//%ARRAY_EXTRA_MUTABLE_METHODS1_##HELPER_NAME(NAME, TYPE)
+//%- (void)insertValue:(TYPE)value atIndex:(NSUInteger)index;
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index withValue:(TYPE)value;
+//%ARRAY_EXTRA_MUTABLE_METHODS2_##HELPER_NAME(NAME, TYPE)
+//%- (void)removeValueAtIndex:(NSUInteger)index;
+//%- (void)removeAll;
+//%
+//%- (void)exchangeValueAtIndex:(NSUInteger)idx1
+//%            withValueAtIndex:(NSUInteger)idx2;
+
+//
+// These are hooks invoked by the above to do insert as needed.
+//
+
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Basic(NAME, TYPE)
+//%- (void)addValuesFromArray:(GPB##NAME##Array *)array;
+//%
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Basic(NAME, TYPE)
+// Empty
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Enum(NAME, TYPE)
+// Empty
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Enum(NAME, TYPE)
+//%
+//%// These methods bypass the validationFunc to provide setting of values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (void)addRawValue:(TYPE)value;
+//%- (void)addRawValuesFromArray:(GPB##NAME##Array *)array;
+//%- (void)addRawValues:(const TYPE [])values count:(NSUInteger)count;
+//%
+//%- (void)insertRawValue:(TYPE)value atIndex:(NSUInteger)index;
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(TYPE)value;
+//%
+//%// No validation applies to these methods.
+//%
diff --git a/src/third_party/protobuf-3/objectivec/GPBArray.m b/src/third_party/protobuf-3/objectivec/GPBArray.m
new file mode 100644
index 0000000..426c7cb
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBArray.m
@@ -0,0 +1,2534 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBArray_PackagePrivate.h"
+
+#import "GPBMessage_PackagePrivate.h"
+
+// Mutable arrays use an internal buffer that can always hold a multiple of this elements.
+#define kChunkSize 16
+#define CapacityFromCount(x) (((x / kChunkSize) + 1) * kChunkSize)
+
+static BOOL ArrayDefault_IsValidValue(int32_t value) {
+  // Anything but the bad value marker is allowed.
+  return (value != kGPBUnrecognizedEnumeratorValue);
+}
+
+//%PDDM-DEFINE VALIDATE_RANGE(INDEX, COUNT)
+//%  if (INDEX >= COUNT) {
+//%    [NSException raise:NSRangeException
+//%                format:@"Index (%lu) beyond bounds (%lu)",
+//%                       (unsigned long)INDEX, (unsigned long)COUNT];
+//%  }
+//%PDDM-DEFINE MAYBE_GROW_TO_SET_COUNT(NEW_COUNT)
+//%  if (NEW_COUNT > _capacity) {
+//%    [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)];
+//%  }
+//%  _count = NEW_COUNT;
+//%PDDM-DEFINE SET_COUNT_AND_MAYBE_SHRINK(NEW_COUNT)
+//%  _count = NEW_COUNT;
+//%  if ((NEW_COUNT + (2 * kChunkSize)) < _capacity) {
+//%    [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)];
+//%  }
+
+//
+// Macros for the common basic cases.
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE, FORMAT)
+//%#pragma mark - NAME
+//%
+//%@implementation GPB##NAME##Array {
+//% @package
+//%  TYPE *_values;
+//%  NSUInteger _count;
+//%  NSUInteger _capacity;
+//%}
+//%
+//%@synthesize count = _count;
+//%
+//%+ (instancetype)array {
+//%  return [[[self alloc] init] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithValue:(TYPE)value {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+//%  // the type correct.
+//%  return [[(GPB##NAME##Array*)[self alloc] initWithValues:&value count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array {
+//%  return [[(GPB##NAME##Array*)[self alloc] initWithValueArray:array] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithCapacity:(NSUInteger)count {
+//%  return [[[self alloc] initWithCapacity:count] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//%  self = [super init];
+//%  // No work needed;
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array {
+//%  return [self initWithValues:array->_values count:array->_count];
+//%}
+//%
+//%- (instancetype)initWithValues:(const TYPE [])values count:(NSUInteger)count {
+//%  self = [self init];
+//%  if (self) {
+//%    if (count && values) {
+//%      _values = reallocf(_values, count * sizeof(TYPE));
+//%      if (_values != NULL) {
+//%        _capacity = count;
+//%        memcpy(_values, values, count * sizeof(TYPE));
+//%        _count = count;
+//%      } else {
+//%        [self release];
+//%        [NSException raise:NSMallocException
+//%                    format:@"Failed to allocate %lu bytes",
+//%                           (unsigned long)(count * sizeof(TYPE))];
+//%      }
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)count {
+//%  self = [self initWithValues:NULL count:0];
+//%  if (self && count) {
+//%    [self internalResizeToCapacity:count];
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)copyWithZone:(NSZone *)zone {
+//%  return [[GPB##NAME##Array allocWithZone:zone] initWithValues:_values count:_count];
+//%}
+//%
+//%ARRAY_IMMUTABLE_CORE(NAME, TYPE, , FORMAT)
+//%
+//%- (TYPE)valueAtIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count)
+//%  return _values[index];
+//%}
+//%
+//%ARRAY_MUTABLE_CORE(NAME, TYPE, , FORMAT)
+//%@end
+//%
+
+//
+// Some core macros used for both the simple types and Enums.
+//
+
+//%PDDM-DEFINE ARRAY_IMMUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT)
+//%- (void)dealloc {
+//%  NSAssert(!_autocreator,
+//%           @"%@: Autocreator must be cleared before release, autocreator: %@",
+//%           [self class], _autocreator);
+//%  free(_values);
+//%  [super dealloc];
+//%}
+//%
+//%- (BOOL)isEqual:(GPB##NAME##Array *)other {
+//%  if (self == other) {
+//%    return YES;
+//%  }
+//%  if (![other isKindOfClass:[GPB##NAME##Array class]]) {
+//%    return NO;
+//%  }
+//%  return (_count == other->_count
+//%          && memcmp(_values, other->_values, (_count * sizeof(TYPE))) == 0);
+//%}
+//%
+//%- (NSUInteger)hash {
+//%  // Follow NSArray's lead, and use the count as the hash.
+//%  return _count;
+//%}
+//%
+//%- (NSString *)description {
+//%  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+//%  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+//%    if (i == 0) {
+//%      [result appendFormat:@"##FORMAT##", _values[i]];
+//%    } else {
+//%      [result appendFormat:@", ##FORMAT##", _values[i]];
+//%    }
+//%  }
+//%  [result appendFormat:@" }"];
+//%  return result;
+//%}
+//%
+//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//%  [self enumerate##ACCESSOR_NAME##ValuesWithOptions:0 usingBlock:block];
+//%}
+//%
+//%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts
+//%                  ACCESSOR_NAME$S      usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//%  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+//%  BOOL stop = NO;
+//%  if ((opts & NSEnumerationReverse) == 0) {
+//%    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+//%      block(_values[i], i, &stop);
+//%      if (stop) break;
+//%    }
+//%  } else if (_count > 0) {
+//%    for (NSUInteger i = _count; i > 0; --i) {
+//%      block(_values[i - 1], (i - 1), &stop);
+//%      if (stop) break;
+//%    }
+//%  }
+//%}
+
+//%PDDM-DEFINE MUTATION_HOOK_None()
+//%PDDM-DEFINE MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, HOOK_1, HOOK_2)
+//%- (void)add##ACCESSOR_NAME##Value:(TYPE)value {
+//%  [self add##ACCESSOR_NAME##Values:&value count:1];
+//%}
+//%
+//%- (void)add##ACCESSOR_NAME##Values:(const TYPE [])values count:(NSUInteger)count {
+//%  if (values == NULL || count == 0) return;
+//%MUTATION_HOOK_##HOOK_1()  NSUInteger initialCount = _count;
+//%  NSUInteger newCount = initialCount + count;
+//%MAYBE_GROW_TO_SET_COUNT(newCount)
+//%  memcpy(&_values[initialCount], values, count * sizeof(TYPE));
+//%  if (_autocreator) {
+//%    GPBAutocreatedArrayModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%- (void)insert##ACCESSOR_NAME##Value:(TYPE)value atIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count + 1)
+//%MUTATION_HOOK_##HOOK_2()  NSUInteger initialCount = _count;
+//%  NSUInteger newCount = initialCount + 1;
+//%MAYBE_GROW_TO_SET_COUNT(newCount)
+//%  if (index != initialCount) {
+//%    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(TYPE));
+//%  }
+//%  _values[index] = value;
+//%  if (_autocreator) {
+//%    GPBAutocreatedArrayModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index with##ACCESSOR_NAME##Value:(TYPE)value {
+//%VALIDATE_RANGE(index, _count)
+//%MUTATION_HOOK_##HOOK_2()  _values[index] = value;
+//%}
+
+//%PDDM-DEFINE ARRAY_MUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT)
+//%- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+//%  _values = reallocf(_values, newCapacity * sizeof(TYPE));
+//%  if (_values == NULL) {
+//%    _capacity = 0;
+//%    _count = 0;
+//%    [NSException raise:NSMallocException
+//%                format:@"Failed to allocate %lu bytes",
+//%                       (unsigned long)(newCapacity * sizeof(TYPE))];
+//%  }
+//%  _capacity = newCapacity;
+//%}
+//%
+//%MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, None, None)
+//%
+//%- (void)add##ACCESSOR_NAME##ValuesFromArray:(GPB##NAME##Array *)array {
+//%  [self add##ACCESSOR_NAME##Values:array->_values count:array->_count];
+//%}
+//%
+//%- (void)removeValueAtIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count)
+//%  NSUInteger newCount = _count - 1;
+//%  if (index != newCount) {
+//%    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(TYPE));
+//%  }
+//%SET_COUNT_AND_MAYBE_SHRINK(newCount)
+//%}
+//%
+//%- (void)removeAll {
+//%SET_COUNT_AND_MAYBE_SHRINK(0)
+//%}
+//%
+//%- (void)exchangeValueAtIndex:(NSUInteger)idx1
+//%            withValueAtIndex:(NSUInteger)idx2 {
+//%VALIDATE_RANGE(idx1, _count)
+//%VALIDATE_RANGE(idx2, _count)
+//%  TYPE temp = _values[idx1];
+//%  _values[idx1] = _values[idx2];
+//%  _values[idx2] = temp;
+//%}
+//%
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@implementation GPBInt32Array {
+ @package
+  int32_t *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(int32_t)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBInt32Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array {
+  return [[(GPBInt32Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBInt32Array *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(int32_t));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(int32_t));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(int32_t))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBInt32Array *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32Array class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(int32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%d", _values[i]];
+    } else {
+      [result appendFormat:@", %d", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (int32_t)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(int32_t));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(int32_t))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(int32_t)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBInt32Array *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  int32_t temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32
+
+@implementation GPBUInt32Array {
+ @package
+  uint32_t *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(uint32_t)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBUInt32Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array {
+  return [[(GPBUInt32Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBUInt32Array *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(uint32_t));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(uint32_t));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(uint32_t))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBUInt32Array *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32Array class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(uint32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%u", _values[i]];
+    } else {
+      [result appendFormat:@", %u", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (uint32_t)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(uint32_t));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(uint32_t))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(uint32_t)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const uint32_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(uint32_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint32_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBUInt32Array *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint32_t));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  uint32_t temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64
+
+@implementation GPBInt64Array {
+ @package
+  int64_t *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(int64_t)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBInt64Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array {
+  return [[(GPBInt64Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBInt64Array *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(int64_t));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(int64_t));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(int64_t))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBInt64Array *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64Array class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(int64_t))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%lld", _values[i]];
+    } else {
+      [result appendFormat:@", %lld", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (int64_t)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(int64_t));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(int64_t))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(int64_t)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int64_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(int64_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int64_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBInt64Array *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int64_t));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  int64_t temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64
+
+@implementation GPBUInt64Array {
+ @package
+  uint64_t *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(uint64_t)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBUInt64Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array {
+  return [[(GPBUInt64Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBUInt64Array *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(uint64_t));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(uint64_t));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(uint64_t))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBUInt64Array *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64Array class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(uint64_t))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%llu", _values[i]];
+    } else {
+      [result appendFormat:@", %llu", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (uint64_t)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(uint64_t));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(uint64_t))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(uint64_t)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const uint64_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(uint64_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint64_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBUInt64Array *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint64_t));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  uint64_t temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Float
+
+@implementation GPBFloatArray {
+ @package
+  float *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(float)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBFloatArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array {
+  return [[(GPBFloatArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBFloatArray *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const float [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(float));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(float));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(float))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBFloatArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBFloatArray *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBFloatArray class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(float))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%f", _values[i]];
+    } else {
+      [result appendFormat:@", %f", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (float)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(float));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(float))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(float)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const float [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(float));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(float)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(float));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBFloatArray *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(float));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  float temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Double
+
+@implementation GPBDoubleArray {
+ @package
+  double *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(double)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBDoubleArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array {
+  return [[(GPBDoubleArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBDoubleArray *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const double [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(double));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(double));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(double))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBDoubleArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBDoubleArray *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBDoubleArray class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(double))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%lf", _values[i]];
+    } else {
+      [result appendFormat:@", %lf", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (double)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(double));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(double))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(double)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const double [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(double));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(double)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(double));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBDoubleArray *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(double));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  double temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool
+
+@implementation GPBBoolArray {
+ @package
+  BOOL *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+  return [[[self alloc] init] autorelease];
+}
+
++ (instancetype)arrayWithValue:(BOOL)value {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+  // the type correct.
+  return [[(GPBBoolArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array {
+  return [[(GPBBoolArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+  return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+  self = [super init];
+  // No work needed;
+  return self;
+}
+
+- (instancetype)initWithValueArray:(GPBBoolArray *)array {
+  return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values count:(NSUInteger)count {
+  self = [self init];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(BOOL));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(BOOL));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(BOOL))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+  self = [self initWithValues:NULL count:0];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBBoolArray *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolArray class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(BOOL))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%d", _values[i]];
+    } else {
+      [result appendFormat:@", %d", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+
+- (BOOL)valueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(BOOL));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(BOOL))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addValue:(BOOL)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const BOOL [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(BOOL));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(BOOL));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBBoolArray *)array {
+  [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(BOOL));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  BOOL temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND-END (7 expansions)
+
+#pragma mark - Enum
+
+@implementation GPBEnumArray {
+ @package
+  GPBEnumValidationFunc _validationFunc;
+  int32_t *_values;
+  NSUInteger _count;
+  NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)array {
+  return [[[self alloc] initWithValidationFunction:NULL] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+                                   rawValue:(int32_t)value {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:&value
+                                             count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array {
+  return [[(GPBEnumArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+                                   capacity:(NSUInteger)count {
+  return [[[self alloc] initWithValidationFunction:func capacity:count] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL];
+}
+
+- (instancetype)initWithValueArray:(GPBEnumArray *)array {
+  return [self initWithValidationFunction:array->_validationFunc
+                                rawValues:array->_values
+                                    count:array->_count];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  self = [super init];
+  if (self) {
+    _validationFunc = (func != NULL ? func : ArrayDefault_IsValidValue);
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                     count:(NSUInteger)count {
+  self = [self initWithValidationFunction:func];
+  if (self) {
+    if (count && values) {
+      _values = reallocf(_values, count * sizeof(int32_t));
+      if (_values != NULL) {
+        _capacity = count;
+        memcpy(_values, values, count * sizeof(int32_t));
+        _count = count;
+      } else {
+        [self release];
+        [NSException raise:NSMallocException
+                    format:@"Failed to allocate %lu bytes",
+                           (unsigned long)(count * sizeof(int32_t))];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)count {
+  self = [self initWithValidationFunction:func];
+  if (self && count) {
+    [self internalResizeToCapacity:count];
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBEnumArray allocWithZone:zone]
+             initWithValidationFunction:_validationFunc
+                              rawValues:_values
+                                  count:_count];
+}
+
+//%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
+// This block of code is generated, do not edit it directly.
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  free(_values);
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBEnumArray *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBEnumArray class]]) {
+    return NO;
+  }
+  return (_count == other->_count
+          && memcmp(_values, other->_values, (_count * sizeof(int32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+  // Follow NSArray's lead, and use the count as the hash.
+  return _count;
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+  for (NSUInteger i = 0, count = _count; i < count; ++i) {
+    if (i == 0) {
+      [result appendFormat:@"%d", _values[i]];
+    } else {
+      [result appendFormat:@", %d", _values[i]];
+    }
+  }
+  [result appendFormat:@" }"];
+  return result;
+}
+
+- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateRawValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+                           usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  if ((opts & NSEnumerationReverse) == 0) {
+    for (NSUInteger i = 0, count = _count; i < count; ++i) {
+      block(_values[i], i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    for (NSUInteger i = _count; i > 0; --i) {
+      block(_values[i - 1], (i - 1), &stop);
+      if (stop) break;
+    }
+  }
+}
+//%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
+
+- (int32_t)valueAtIndex:(NSUInteger)index {
+//%PDDM-EXPAND VALIDATE_RANGE(index, _count)
+// This block of code is generated, do not edit it directly.
+
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+  int32_t result = _values[index];
+  if (!_validationFunc(result)) {
+    result = kGPBUnrecognizedEnumeratorValue;
+  }
+  return result;
+}
+
+- (int32_t)rawValueAtIndex:(NSUInteger)index {
+//%PDDM-EXPAND VALIDATE_RANGE(index, _count)
+// This block of code is generated, do not edit it directly.
+
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+  return _values[index];
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+                        usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+  BOOL stop = NO;
+  GPBEnumValidationFunc func = _validationFunc;
+  if ((opts & NSEnumerationReverse) == 0) {
+    int32_t *scan = _values;
+    int32_t *end = scan + _count;
+    for (NSUInteger i = 0; scan < end; ++i, ++scan) {
+      int32_t value = *scan;
+      if (!func(value)) {
+        value = kGPBUnrecognizedEnumeratorValue;
+      }
+      block(value, i, &stop);
+      if (stop) break;
+    }
+  } else if (_count > 0) {
+    int32_t *end = _values;
+    int32_t *scan = end + (_count - 1);
+    for (NSUInteger i = (_count - 1); scan >= end; --i, --scan) {
+      int32_t value = *scan;
+      if (!func(value)) {
+        value = kGPBUnrecognizedEnumeratorValue;
+      }
+      block(value, i, &stop);
+      if (stop) break;
+    }
+  }
+}
+
+//%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d)
+// This block of code is generated, do not edit it directly.
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+  _values = reallocf(_values, newCapacity * sizeof(int32_t));
+  if (_values == NULL) {
+    _capacity = 0;
+    _count = 0;
+    [NSException raise:NSMallocException
+                format:@"Failed to allocate %lu bytes",
+                       (unsigned long)(newCapacity * sizeof(int32_t))];
+  }
+  _capacity = newCapacity;
+}
+
+- (void)addRawValue:(int32_t)value {
+  [self addRawValues:&value count:1];
+}
+
+- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  _values[index] = value;
+}
+
+- (void)addRawValuesFromArray:(GPBEnumArray *)array {
+  [self addRawValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  NSUInteger newCount = _count - 1;
+  if (index != newCount) {
+    memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t));
+  }
+  _count = newCount;
+  if ((newCount + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+}
+
+- (void)removeAll {
+  _count = 0;
+  if ((0 + (2 * kChunkSize)) < _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(0)];
+  }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+            withValueAtIndex:(NSUInteger)idx2 {
+  if (idx1 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx1, (unsigned long)_count];
+  }
+  if (idx2 >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)idx2, (unsigned long)_count];
+  }
+  int32_t temp = _values[idx1];
+  _values[idx1] = _values[idx2];
+  _values[idx2] = temp;
+}
+
+//%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne)
+// This block of code is generated, do not edit it directly.
+
+- (void)addValue:(int32_t)value {
+  [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count {
+  if (values == NULL || count == 0) return;
+  GPBEnumValidationFunc func = _validationFunc;
+  for (NSUInteger i = 0; i < count; ++i) {
+    if (!func(values[i])) {
+      [NSException raise:NSInvalidArgumentException
+                  format:@"%@: Attempt to set an unknown enum value (%d)",
+                         [self class], values[i]];
+    }
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + count;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index {
+  if (index >= _count + 1) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count + 1];
+  }
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@: Attempt to set an unknown enum value (%d)",
+                       [self class], value];
+  }
+  NSUInteger initialCount = _count;
+  NSUInteger newCount = initialCount + 1;
+  if (newCount > _capacity) {
+    [self internalResizeToCapacity:CapacityFromCount(newCount)];
+  }
+  _count = newCount;
+  if (index != initialCount) {
+    memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+  }
+  _values[index] = value;
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value {
+  if (index >= _count) {
+    [NSException raise:NSRangeException
+                format:@"Index (%lu) beyond bounds (%lu)",
+                       (unsigned long)index, (unsigned long)_count];
+  }
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@: Attempt to set an unknown enum value (%d)",
+                       [self class], value];
+  }
+  _values[index] = value;
+}
+//%PDDM-EXPAND-END (2 expansions)
+
+//%PDDM-DEFINE MUTATION_HOOK_EnumValidationList()
+//%  GPBEnumValidationFunc func = _validationFunc;
+//%  for (NSUInteger i = 0; i < count; ++i) {
+//%    if (!func(values[i])) {
+//%      [NSException raise:NSInvalidArgumentException
+//%                  format:@"%@: Attempt to set an unknown enum value (%d)",
+//%                         [self class], values[i]];
+//%    }
+//%  }
+//%
+//%PDDM-DEFINE MUTATION_HOOK_EnumValidationOne()
+//%  if (!_validationFunc(value)) {
+//%    [NSException raise:NSInvalidArgumentException
+//%                format:@"%@: Attempt to set an unknown enum value (%d)",
+//%                       [self class], value];
+//%  }
+//%
+
+@end
+
+#pragma mark - NSArray Subclass
+
+@implementation GPBAutocreatedArray {
+  NSMutableArray *_array;
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_array release];
+  [super dealloc];
+}
+
+#pragma mark Required NSArray overrides
+
+- (NSUInteger)count {
+  return [_array count];
+}
+
+- (id)objectAtIndex:(NSUInteger)idx {
+  return [_array objectAtIndex:idx];
+}
+
+#pragma mark Required NSMutableArray overrides
+
+// Only need to call GPBAutocreatedArrayModified() when adding things since
+// we only autocreate empty arrays.
+
+- (void)insertObject:(id)anObject atIndex:(NSUInteger)idx {
+  if (_array == nil) {
+    _array = [[NSMutableArray alloc] init];
+  }
+  [_array insertObject:anObject atIndex:idx];
+
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)removeObject:(id)anObject {
+  [_array removeObject:anObject];
+}
+
+- (void)removeObjectAtIndex:(NSUInteger)idx {
+  [_array removeObjectAtIndex:idx];
+}
+
+- (void)addObject:(id)anObject {
+  if (_array == nil) {
+    _array = [[NSMutableArray alloc] init];
+  }
+  [_array addObject:anObject];
+
+  if (_autocreator) {
+    GPBAutocreatedArrayModified(_autocreator, self);
+  }
+}
+
+- (void)removeLastObject {
+  [_array removeLastObject];
+}
+
+- (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)anObject {
+  [_array replaceObjectAtIndex:idx withObject:anObject];
+}
+
+#pragma mark Extra things hooked
+
+- (id)copyWithZone:(NSZone *)zone {
+  if (_array == nil) {
+    _array = [[NSMutableArray alloc] init];
+  }
+  return [_array copyWithZone:zone];
+}
+
+- (id)mutableCopyWithZone:(NSZone *)zone {
+  if (_array == nil) {
+    _array = [[NSMutableArray alloc] init];
+  }
+  return [_array mutableCopyWithZone:zone];
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
+                                  objects:(id __unsafe_unretained [])buffer
+                                    count:(NSUInteger)len {
+  return [_array countByEnumeratingWithState:state objects:buffer count:len];
+}
+
+- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
+  [_array enumerateObjectsUsingBlock:block];
+}
+
+- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts
+                         usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
+  [_array enumerateObjectsWithOptions:opts usingBlock:block];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBArray_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBArray_PackagePrivate.h
new file mode 100644
index 0000000..35a453813
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBArray_PackagePrivate.h
@@ -0,0 +1,130 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBArray.h"
+
+@class GPBMessage;
+
+//%PDDM-DEFINE DECLARE_ARRAY_EXTRAS()
+//%ARRAY_INTERFACE_EXTRAS(Int32, int32_t)
+//%ARRAY_INTERFACE_EXTRAS(UInt32, uint32_t)
+//%ARRAY_INTERFACE_EXTRAS(Int64, int64_t)
+//%ARRAY_INTERFACE_EXTRAS(UInt64, uint64_t)
+//%ARRAY_INTERFACE_EXTRAS(Float, float)
+//%ARRAY_INTERFACE_EXTRAS(Double, double)
+//%ARRAY_INTERFACE_EXTRAS(Bool, BOOL)
+//%ARRAY_INTERFACE_EXTRAS(Enum, int32_t)
+
+//%PDDM-DEFINE ARRAY_INTERFACE_EXTRAS(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array () {
+//% @package
+//%  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+//%}
+//%@end
+//%
+
+//%PDDM-EXPAND DECLARE_ARRAY_EXTRAS()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32Array () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - UInt32
+
+@interface GPBUInt32Array () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Int64
+
+@interface GPBInt64Array () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - UInt64
+
+@interface GPBUInt64Array () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Float
+
+@interface GPBFloatArray () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Double
+
+@interface GPBDoubleArray () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Bool
+
+@interface GPBBoolArray () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Enum
+
+@interface GPBEnumArray () {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+//%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS()
+
+#pragma mark - NSArray Subclass
+
+@interface GPBAutocreatedArray : NSMutableArray {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBBootstrap.h b/src/third_party/protobuf-3/objectivec/GPBBootstrap.h
new file mode 100644
index 0000000..ffefa77
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBBootstrap.h
@@ -0,0 +1,85 @@
+// 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.
+
+// The Objective C runtime has complete enough info that most protos don’t end
+// up using this, so leaving it on is no cost or very little cost.  If you
+// happen to see it causing bloat, this is the way to disable it. If you do
+// need to disable it, try only disabling it for Release builds as having
+// full TextFormat can be useful for debugging.
+#ifndef GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+#define GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS 0
+#endif
+
+// Used in the generated code to give sizes to enums. int32_t was chosen based
+// on the fact that Protocol Buffers enums are limited to this range.
+#if !__has_feature(objc_fixed_enum)
+ #error All supported Xcode versions should support objc_fixed_enum.
+#endif
+// If the headers are imported into Objective-C++, we can run into an issue
+// where the defintion of NS_ENUM (really CF_ENUM) changes based on the C++
+// standard that is in effect.  If it isn't C++11 or higher, the definition
+// doesn't allow us to forward declare. We work around this one case by
+// providing a local definition. The default case has to use NS_ENUM for the
+// magic that is Swift bridging of enums.
+#if (__cplusplus && __cplusplus < 201103L)
+ #define GPB_ENUM(X) enum X : int32_t X; enum X : int32_t
+#else
+ #define GPB_ENUM(X) NS_ENUM(int32_t, X)
+#endif
+// GPB_ENUM_FWD_DECLARE is used for forward declaring enums, ex:
+//   GPB_ENUM_FWD_DECLARE(Foo_Enum)
+//   @property (nonatomic) Foo_Enum value;
+#define GPB_ENUM_FWD_DECLARE(X) enum X : int32_t
+
+// Based upon CF_INLINE. Forces inlining in release.
+#if !defined(DEBUG)
+#define GPB_INLINE static __inline__ __attribute__((always_inline))
+#else
+#define GPB_INLINE static __inline__
+#endif
+
+// For use in public headers that might need to deal with ARC.
+#ifndef GPB_UNSAFE_UNRETAINED
+#if __has_feature(objc_arc)
+#define GPB_UNSAFE_UNRETAINED __unsafe_unretained
+#else
+#define GPB_UNSAFE_UNRETAINED
+#endif
+#endif
+
+// If property name starts with init we need to annotate it to get past ARC.
+// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+#define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
+
+// The protoc-gen-objc version which works with the current version of the
+// generated Objective C sources.  In general we don't want to change the
+// runtime interfaces (or this version) as it means everything has to be
+// regenerated.
+#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.h b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.h
new file mode 100644
index 0000000..d64b64e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.h
@@ -0,0 +1,130 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+@class GPBMessage;
+@class GPBExtensionRegistry;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Reads and decodes protocol message fields.
+///
+/// The common uses of protocol buffers shouldn't need to use this class.
+/// @c GPBMessage's provide a @c +parseFromData:error: and @c
+/// +parseFromData:extensionRegistry:error: method that will decode a
+/// message for you.
+///
+/// @note Subclassing of GPBCodedInputStream is NOT supported.
+@interface GPBCodedInputStream : NSObject
+
+/// Creates a new stream wrapping some data.
++ (instancetype)streamWithData:(NSData *)data;
+
+/// Initializes a stream wrapping some data.
+- (instancetype)initWithData:(NSData *)data;
+
+/// Attempt to read a field tag, returning zero if we have reached EOF.
+/// Protocol message parsers use this to read tags, since a protocol message
+/// may legally end wherever a tag occurs, and zero is not a valid tag number.
+- (int32_t)readTag;
+
+/// Read and return a double.
+- (double)readDouble;
+/// Read and return a float.
+- (float)readFloat;
+/// Read and return a uint64.
+- (uint64_t)readUInt64;
+/// Read and return a uint32.
+- (uint32_t)readUInt32;
+/// Read and return an int64.
+- (int64_t)readInt64;
+/// Read and return an int32.
+- (int32_t)readInt32;
+/// Read and return a fixed64.
+- (uint64_t)readFixed64;
+/// Read and return a fixed32.
+- (uint32_t)readFixed32;
+/// Read and return an enum (int).
+- (int32_t)readEnum;
+/// Read and return a sfixed32.
+- (int32_t)readSFixed32;
+/// Read and return a sfixed64.
+- (int64_t)readSFixed64;
+/// Read and return a sint32.
+- (int32_t)readSInt32;
+/// Read and return a sint64.
+- (int64_t)readSInt64;
+/// Read and return a boolean.
+- (BOOL)readBool;
+/// Read and return a string.
+- (NSString *)readString;
+/// Read and return length delimited data.
+- (NSData *)readBytes;
+
+/// Read an embedded message field value from the stream.
+///
+/// @param message           The message to set fields on as they are read.
+/// @param extensionRegistry An optional extension registry to use to lookup
+///                          extensions for @message.
+- (void)readMessage:(GPBMessage *)message
+  extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
+
+/// Reads and discards a single field, given its tag value.
+///
+/// @param tag The tag number of the field to skip.
+///
+/// @return NO if the tag is an endgroup tag (in which case nothing is skipped),
+///         YES in all other cases.
+- (BOOL)skipField:(int32_t)tag;
+
+/// Reads and discards an entire message.  This will read either until EOF
+/// or until an endgroup tag, whichever comes first.
+- (void)skipMessage;
+
+/// Check to see if the logical end of the stream has been reached.
+///
+/// This can return NO when there is no more data, but the current parsing
+/// expected more data.
+- (BOOL)isAtEnd;
+
+/// The offset into the stream.
+- (size_t)position;
+
+/// Verifies that the last call to @c -readTag returned the given tag value.
+/// This is used to verify that a nested group ended with the correct end tag.
+/// Throws @c NSParseErrorException if value does not match the last tag.
+///
+/// @param expected The tag that was expected.
+- (void)checkLastTagWas:(int32_t)expected;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.m b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.m
new file mode 100644
index 0000000..319ec15
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream.m
@@ -0,0 +1,499 @@
+// 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.
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "GPBWireFormat.h"
+
+static const NSUInteger kDefaultRecursionLimit = 64;
+
+static void CheckSize(GPBCodedInputStreamState *state, size_t size) {
+  size_t newSize = state->bufferPos + size;
+  if (newSize > state->bufferSize) {
+    [NSException raise:NSParseErrorException format:@""];
+  }
+  if (newSize > state->currentLimit) {
+    // Fast forward to end of currentLimit;
+    state->bufferPos = state->currentLimit;
+    [NSException raise:NSParseErrorException format:@""];
+  }
+}
+
+static int8_t ReadRawByte(GPBCodedInputStreamState *state) {
+  CheckSize(state, sizeof(int8_t));
+  return ((int8_t *)state->bytes)[state->bufferPos++];
+}
+
+static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) {
+  CheckSize(state, sizeof(int32_t));
+  int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos);
+  state->bufferPos += sizeof(int32_t);
+  return value;
+}
+
+static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
+  CheckSize(state, sizeof(int64_t));
+  int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos);
+  state->bufferPos += sizeof(int64_t);
+  return value;
+}
+
+static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
+  int8_t tmp = ReadRawByte(state);
+  if (tmp >= 0) {
+    return tmp;
+  }
+  int32_t result = tmp & 0x7f;
+  if ((tmp = ReadRawByte(state)) >= 0) {
+    result |= tmp << 7;
+  } else {
+    result |= (tmp & 0x7f) << 7;
+    if ((tmp = ReadRawByte(state)) >= 0) {
+      result |= tmp << 14;
+    } else {
+      result |= (tmp & 0x7f) << 14;
+      if ((tmp = ReadRawByte(state)) >= 0) {
+        result |= tmp << 21;
+      } else {
+        result |= (tmp & 0x7f) << 21;
+        result |= (tmp = ReadRawByte(state)) << 28;
+        if (tmp < 0) {
+          // Discard upper 32 bits.
+          for (int i = 0; i < 5; i++) {
+            if (ReadRawByte(state) >= 0) {
+              return result;
+            }
+          }
+          [NSException raise:NSParseErrorException
+                      format:@"Unable to read varint32"];
+        }
+      }
+    }
+  }
+  return result;
+}
+
+static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
+  int32_t shift = 0;
+  int64_t result = 0;
+  while (shift < 64) {
+    int8_t b = ReadRawByte(state);
+    result |= (int64_t)(b & 0x7F) << shift;
+    if ((b & 0x80) == 0) {
+      return result;
+    }
+    shift += 7;
+  }
+  [NSException raise:NSParseErrorException format:@"Unable to read varint64"];
+  return 0;
+}
+
+static void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
+  CheckSize(state, size);
+  state->bufferPos += size;
+}
+
+double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) {
+  int64_t value = ReadRawLittleEndian64(state);
+  return GPBConvertInt64ToDouble(value);
+}
+
+float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) {
+  int32_t value = ReadRawLittleEndian32(state);
+  return GPBConvertInt32ToFloat(value);
+}
+
+uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) {
+  uint64_t value = ReadRawVarint64(state);
+  return value;
+}
+
+uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) {
+  uint32_t value = ReadRawVarint32(state);
+  return value;
+}
+
+int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) {
+  int64_t value = ReadRawVarint64(state);
+  return value;
+}
+
+int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) {
+  int32_t value = ReadRawVarint32(state);
+  return value;
+}
+
+uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) {
+  uint64_t value = ReadRawLittleEndian64(state);
+  return value;
+}
+
+uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) {
+  uint32_t value = ReadRawLittleEndian32(state);
+  return value;
+}
+
+int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) {
+  int32_t value = ReadRawVarint32(state);
+  return value;
+}
+
+int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) {
+  int32_t value = ReadRawLittleEndian32(state);
+  return value;
+}
+
+int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) {
+  int64_t value = ReadRawLittleEndian64(state);
+  return value;
+}
+
+int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) {
+  int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state));
+  return value;
+}
+
+int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) {
+  int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state));
+  return value;
+}
+
+BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) {
+  return ReadRawVarint32(state) != 0;
+}
+
+int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
+  if (GPBCodedInputStreamIsAtEnd(state)) {
+    state->lastTag = 0;
+    return 0;
+  }
+
+  state->lastTag = ReadRawVarint32(state);
+  if (state->lastTag == 0) {
+    // If we actually read zero, that's not a valid tag.
+    [NSException raise:NSParseErrorException
+                format:@"Invalid last tag %d", state->lastTag];
+  }
+  return state->lastTag;
+}
+
+NSString *GPBCodedInputStreamReadRetainedString(
+    GPBCodedInputStreamState *state) {
+  int32_t size = ReadRawVarint32(state);
+  NSString *result;
+  if (size == 0) {
+    result = @"";
+  } else {
+    CheckSize(state, size);
+    result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos]
+                                      length:size
+                                    encoding:NSUTF8StringEncoding];
+    state->bufferPos += size;
+    if (!result) {
+#ifdef DEBUG
+      // https://developers.google.com/protocol-buffers/docs/proto#scalar
+      NSLog(@"UTF-8 failure, is some field type 'string' when it should be "
+            @"'bytes'?");
+#endif
+      [NSException raise:NSParseErrorException
+                  format:@"Invalid UTF-8 for a 'string'"];
+    }
+  }
+  return result;
+}
+
+NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) {
+  int32_t size = ReadRawVarint32(state);
+  if (size < 0) return nil;
+  CheckSize(state, size);
+  NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos
+                                          length:size];
+  state->bufferPos += size;
+  return result;
+}
+
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
+    GPBCodedInputStreamState *state) {
+  int32_t size = ReadRawVarint32(state);
+  if (size < 0) return nil;
+  CheckSize(state, size);
+  // Cast is safe because freeWhenDone is NO.
+  NSData *result = [[NSData alloc]
+      initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos)
+                   length:size
+             freeWhenDone:NO];
+  state->bufferPos += size;
+  return result;
+}
+
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
+                                    size_t byteLimit) {
+  byteLimit += state->bufferPos;
+  size_t oldLimit = state->currentLimit;
+  if (byteLimit > oldLimit) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"byteLimit > oldLimit: %tu > %tu", byteLimit, oldLimit];
+  }
+  state->currentLimit = byteLimit;
+  return oldLimit;
+}
+
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
+                                 size_t oldLimit) {
+  state->currentLimit = oldLimit;
+}
+
+size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) {
+  return state->currentLimit - state->bufferPos;
+}
+
+BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
+  return (state->bufferPos == state->bufferSize) ||
+         (state->bufferPos == state->currentLimit);
+}
+
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
+                                        int32_t value) {
+  if (state->lastTag != value) {
+    [NSException raise:NSParseErrorException
+                format:@"Last tag: %d should be %d", state->lastTag, value];
+  }
+}
+
+@implementation GPBCodedInputStream
+
++ (instancetype)streamWithData:(NSData *)data {
+  return [[[self alloc] initWithData:data] autorelease];
+}
+
+- (instancetype)initWithData:(NSData *)data {
+  if ((self = [super init])) {
+#ifdef DEBUG
+    NSCAssert([self class] == [GPBCodedInputStream class],
+              @"Subclassing of GPBCodedInputStream is not allowed.");
+#endif
+    buffer_ = [data retain];
+    state_.bytes = (const uint8_t *)[data bytes];
+    state_.bufferSize = [data length];
+    state_.currentLimit = state_.bufferSize;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [buffer_ release];
+  [super dealloc];
+}
+
+- (int32_t)readTag {
+  return GPBCodedInputStreamReadTag(&state_);
+}
+
+- (void)checkLastTagWas:(int32_t)value {
+  GPBCodedInputStreamCheckLastTagWas(&state_, value);
+}
+
+- (BOOL)skipField:(int32_t)tag {
+  switch (GPBWireFormatGetTagWireType(tag)) {
+    case GPBWireFormatVarint:
+      GPBCodedInputStreamReadInt32(&state_);
+      return YES;
+    case GPBWireFormatFixed64:
+      SkipRawData(&state_, sizeof(int64_t));
+      return YES;
+    case GPBWireFormatLengthDelimited:
+      SkipRawData(&state_, ReadRawVarint32(&state_));
+      return YES;
+    case GPBWireFormatStartGroup:
+      [self skipMessage];
+      GPBCodedInputStreamCheckLastTagWas(
+          &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
+                                        GPBWireFormatEndGroup));
+      return YES;
+    case GPBWireFormatEndGroup:
+      return NO;
+    case GPBWireFormatFixed32:
+      SkipRawData(&state_, sizeof(int32_t));
+      return YES;
+  }
+  [NSException raise:NSParseErrorException format:@"Invalid tag %d", tag];
+  return NO;
+}
+
+- (void)skipMessage {
+  while (YES) {
+    int32_t tag = GPBCodedInputStreamReadTag(&state_);
+    if (tag == 0 || ![self skipField:tag]) {
+      return;
+    }
+  }
+}
+
+- (BOOL)isAtEnd {
+  return GPBCodedInputStreamIsAtEnd(&state_);
+}
+
+- (size_t)position {
+  return state_.bufferPos;
+}
+
+- (double)readDouble {
+  return GPBCodedInputStreamReadDouble(&state_);
+}
+
+- (float)readFloat {
+  return GPBCodedInputStreamReadFloat(&state_);
+}
+
+- (uint64_t)readUInt64 {
+  return GPBCodedInputStreamReadUInt64(&state_);
+}
+
+- (int64_t)readInt64 {
+  return GPBCodedInputStreamReadInt64(&state_);
+}
+
+- (int32_t)readInt32 {
+  return GPBCodedInputStreamReadInt32(&state_);
+}
+
+- (uint64_t)readFixed64 {
+  return GPBCodedInputStreamReadFixed64(&state_);
+}
+
+- (uint32_t)readFixed32 {
+  return GPBCodedInputStreamReadFixed32(&state_);
+}
+
+- (BOOL)readBool {
+  return GPBCodedInputStreamReadBool(&state_);
+}
+
+- (NSString *)readString {
+  return [GPBCodedInputStreamReadRetainedString(&state_) autorelease];
+}
+
+- (void)readGroup:(int32_t)fieldNumber
+              message:(GPBMessage *)message
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  if (state_.recursionDepth >= kDefaultRecursionLimit) {
+    [NSException raise:NSParseErrorException
+                format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+                       kDefaultRecursionLimit];
+  }
+  ++state_.recursionDepth;
+  [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
+  GPBCodedInputStreamCheckLastTagWas(
+      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+  --state_.recursionDepth;
+}
+
+- (void)readUnknownGroup:(int32_t)fieldNumber
+                 message:(GPBUnknownFieldSet *)message {
+  if (state_.recursionDepth >= kDefaultRecursionLimit) {
+    [NSException raise:NSParseErrorException
+                format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+                       kDefaultRecursionLimit];
+  }
+  ++state_.recursionDepth;
+  [message mergeFromCodedInputStream:self];
+  GPBCodedInputStreamCheckLastTagWas(
+      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+  --state_.recursionDepth;
+}
+
+- (void)readMessage:(GPBMessage *)message
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  int32_t length = ReadRawVarint32(&state_);
+  if (state_.recursionDepth >= kDefaultRecursionLimit) {
+    [NSException raise:NSParseErrorException
+                format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+                       kDefaultRecursionLimit];
+  }
+  size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
+  ++state_.recursionDepth;
+  [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
+  GPBCodedInputStreamCheckLastTagWas(&state_, 0);
+  --state_.recursionDepth;
+  GPBCodedInputStreamPopLimit(&state_, oldLimit);
+}
+
+- (void)readMapEntry:(id)mapDictionary
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                field:(GPBFieldDescriptor *)field
+        parentMessage:(GPBMessage *)parentMessage {
+  int32_t length = ReadRawVarint32(&state_);
+  if (state_.recursionDepth >= kDefaultRecursionLimit) {
+    [NSException raise:NSParseErrorException
+                format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+                       kDefaultRecursionLimit];
+  }
+  size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
+  ++state_.recursionDepth;
+  GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field,
+                         parentMessage);
+  GPBCodedInputStreamCheckLastTagWas(&state_, 0);
+  --state_.recursionDepth;
+  GPBCodedInputStreamPopLimit(&state_, oldLimit);
+}
+
+- (NSData *)readBytes {
+  return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease];
+}
+
+- (uint32_t)readUInt32 {
+  return GPBCodedInputStreamReadUInt32(&state_);
+}
+
+- (int32_t)readEnum {
+  return GPBCodedInputStreamReadEnum(&state_);
+}
+
+- (int32_t)readSFixed32 {
+  return GPBCodedInputStreamReadSFixed32(&state_);
+}
+
+- (int64_t)readSFixed64 {
+  return GPBCodedInputStreamReadSFixed64(&state_);
+}
+
+- (int32_t)readSInt32 {
+  return GPBCodedInputStreamReadSInt32(&state_);
+}
+
+- (int64_t)readSInt64 {
+  return GPBCodedInputStreamReadSInt64(&state_);
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedInputStream_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream_PackagePrivate.h
new file mode 100644
index 0000000..90bd0c9
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedInputStream_PackagePrivate.h
@@ -0,0 +1,114 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBCodedInputStream.h"
+
+#import <libkern/OSAtomic.h>
+
+@class GPBUnknownFieldSet;
+@class GPBFieldDescriptor;
+
+typedef struct GPBCodedInputStreamState {
+  const uint8_t *bytes;
+  size_t bufferSize;
+  size_t bufferPos;
+
+  // For parsing subsections of an input stream you can put a hard limit on
+  // how much should be read. Normally the limit is the end of the stream,
+  // but you can adjust it to anywhere, and if you hit it you will be at the
+  // end of the stream, until you adjust the limit.
+  size_t currentLimit;
+  int32_t lastTag;
+  NSUInteger recursionDepth;
+} GPBCodedInputStreamState;
+
+@interface GPBCodedInputStream () {
+ @package
+  struct GPBCodedInputStreamState state_;
+  NSData *buffer_;
+}
+
+// Group support is deprecated, so we hide this interface from users, but
+// support for older data.
+- (void)readGroup:(int32_t)fieldNumber
+              message:(GPBMessage *)message
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Reads a group field value from the stream and merges it into the given
+// UnknownFieldSet.
+- (void)readUnknownGroup:(int32_t)fieldNumber
+                 message:(GPBUnknownFieldSet *)message;
+
+// Reads a map entry.
+- (void)readMapEntry:(id)mapDictionary
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                field:(GPBFieldDescriptor *)field
+        parentMessage:(GPBMessage *)parentMessage;
+@end
+
+CF_EXTERN_C_BEGIN
+
+int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state);
+
+double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state);
+float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state);
+uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state);
+uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state);
+uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state);
+uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state);
+BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state);
+NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state)
+    __attribute((ns_returns_retained));
+NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
+    __attribute((ns_returns_retained));
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
+    GPBCodedInputStreamState *state) __attribute((ns_returns_retained));
+
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
+                                    size_t byteLimit);
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
+                                 size_t oldLimit);
+size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state);
+BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state);
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
+                                        int32_t value);
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.h b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.h
new file mode 100644
index 0000000..8272880
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.h
@@ -0,0 +1,344 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBRuntimeTypes.h"
+#import "GPBWireFormat.h"
+
+@class GPBBoolArray;
+@class GPBDoubleArray;
+@class GPBEnumArray;
+@class GPBFloatArray;
+@class GPBMessage;
+@class GPBInt32Array;
+@class GPBInt64Array;
+@class GPBUInt32Array;
+@class GPBUInt64Array;
+@class GPBUnknownFieldSet;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Writes out protocol message fields.
+///
+/// The common uses of protocol buffers shouldn't need to use this class.
+/// @c GPBMessage's provide a @c -data method that will serialize the message
+/// for you.
+///
+/// @note Subclassing of GPBCodedOutputStream is NOT supported.
+@interface GPBCodedOutputStream : NSObject
+
+/// Creates a stream to fill in the given data. Data must be sized to fit or
+/// an error will be raised when out of space.
++ (instancetype)streamWithData:(NSMutableData *)data;
+
+/// Creates a stream to write into the given @c NSOutputStream.
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output;
+
+/// Initializes a stream to fill in the given data. Data must be sized to fit
+/// or an error will be raised when out of space.
+- (instancetype)initWithData:(NSMutableData *)data;
+
+/// Initializes a stream to write into the given @c NSOutputStream.
+- (instancetype)initWithOutputStream:(NSOutputStream *)output;
+
+/// Flush any buffered data out.
+- (void)flush;
+
+/// Write the raw byte out.
+- (void)writeRawByte:(uint8_t)value;
+
+/// Write the tag for the given field number and wire format.
+///
+/// @param fieldNumber The field number.
+/// @param format      The wire format the data for the field will be in.
+- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format;
+
+/// Write a 32bit value out in little endian format.
+- (void)writeRawLittleEndian32:(int32_t)value;
+/// Write a 64bit value out in little endian format.
+- (void)writeRawLittleEndian64:(int64_t)value;
+
+/// Write a 32bit value out in varint format.
+- (void)writeRawVarint32:(int32_t)value;
+/// Write a 64bit value out in varint format.
+- (void)writeRawVarint64:(int64_t)value;
+
+/// Write a size_t out as a 32bit varint value.
+///
+/// @note This will truncate 64 bit values to 32.
+- (void)writeRawVarintSizeTAs32:(size_t)value;
+
+/// Writes the contents of an @c NSData out.
+- (void)writeRawData:(NSData *)data;
+/// Writes out the given data.
+///
+/// @param data   The data blob to write out.
+/// @param offset The offset into the blob to start writing out.
+/// @param length The number of bytes from the blob to write out.
+- (void)writeRawPtr:(const void *)data
+             offset:(size_t)offset
+             length:(size_t)length;
+
+//%PDDM-EXPAND _WRITE_DECLS()
+// This block of code is generated, do not edit it directly.
+
+/// Write a double for the given field number.
+- (void)writeDouble:(int32_t)fieldNumber value:(double)value;
+/// Write a packed array of double for the given field number.
+- (void)writeDoubleArray:(int32_t)fieldNumber
+                  values:(GPBDoubleArray *)values
+                     tag:(uint32_t)tag;
+/// Write a double without any tag.
+- (void)writeDoubleNoTag:(double)value;
+
+/// Write a float for the given field number.
+- (void)writeFloat:(int32_t)fieldNumber value:(float)value;
+/// Write a packed array of float for the given field number.
+- (void)writeFloatArray:(int32_t)fieldNumber
+                 values:(GPBFloatArray *)values
+                    tag:(uint32_t)tag;
+/// Write a float without any tag.
+- (void)writeFloatNoTag:(float)value;
+
+/// Write a uint64_t for the given field number.
+- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value;
+/// Write a packed array of uint64_t for the given field number.
+- (void)writeUInt64Array:(int32_t)fieldNumber
+                  values:(GPBUInt64Array *)values
+                     tag:(uint32_t)tag;
+/// Write a uint64_t without any tag.
+- (void)writeUInt64NoTag:(uint64_t)value;
+
+/// Write a int64_t for the given field number.
+- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value;
+/// Write a packed array of int64_t for the given field number.
+- (void)writeInt64Array:(int32_t)fieldNumber
+                 values:(GPBInt64Array *)values
+                    tag:(uint32_t)tag;
+/// Write a int64_t without any tag.
+- (void)writeInt64NoTag:(int64_t)value;
+
+/// Write a int32_t for the given field number.
+- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value;
+/// Write a packed array of int32_t for the given field number.
+- (void)writeInt32Array:(int32_t)fieldNumber
+                 values:(GPBInt32Array *)values
+                    tag:(uint32_t)tag;
+/// Write a int32_t without any tag.
+- (void)writeInt32NoTag:(int32_t)value;
+
+/// Write a uint32_t for the given field number.
+- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value;
+/// Write a packed array of uint32_t for the given field number.
+- (void)writeUInt32Array:(int32_t)fieldNumber
+                  values:(GPBUInt32Array *)values
+                     tag:(uint32_t)tag;
+/// Write a uint32_t without any tag.
+- (void)writeUInt32NoTag:(uint32_t)value;
+
+/// Write a uint64_t for the given field number.
+- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value;
+/// Write a packed array of uint64_t for the given field number.
+- (void)writeFixed64Array:(int32_t)fieldNumber
+                   values:(GPBUInt64Array *)values
+                      tag:(uint32_t)tag;
+/// Write a uint64_t without any tag.
+- (void)writeFixed64NoTag:(uint64_t)value;
+
+/// Write a uint32_t for the given field number.
+- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value;
+/// Write a packed array of uint32_t for the given field number.
+- (void)writeFixed32Array:(int32_t)fieldNumber
+                   values:(GPBUInt32Array *)values
+                      tag:(uint32_t)tag;
+/// Write a uint32_t without any tag.
+- (void)writeFixed32NoTag:(uint32_t)value;
+
+/// Write a int32_t for the given field number.
+- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value;
+/// Write a packed array of int32_t for the given field number.
+- (void)writeSInt32Array:(int32_t)fieldNumber
+                  values:(GPBInt32Array *)values
+                     tag:(uint32_t)tag;
+/// Write a int32_t without any tag.
+- (void)writeSInt32NoTag:(int32_t)value;
+
+/// Write a int64_t for the given field number.
+- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value;
+/// Write a packed array of int64_t for the given field number.
+- (void)writeSInt64Array:(int32_t)fieldNumber
+                  values:(GPBInt64Array *)values
+                     tag:(uint32_t)tag;
+/// Write a int64_t without any tag.
+- (void)writeSInt64NoTag:(int64_t)value;
+
+/// Write a int64_t for the given field number.
+- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value;
+/// Write a packed array of int64_t for the given field number.
+- (void)writeSFixed64Array:(int32_t)fieldNumber
+                    values:(GPBInt64Array *)values
+                       tag:(uint32_t)tag;
+/// Write a int64_t without any tag.
+- (void)writeSFixed64NoTag:(int64_t)value;
+
+/// Write a int32_t for the given field number.
+- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value;
+/// Write a packed array of int32_t for the given field number.
+- (void)writeSFixed32Array:(int32_t)fieldNumber
+                    values:(GPBInt32Array *)values
+                       tag:(uint32_t)tag;
+/// Write a int32_t without any tag.
+- (void)writeSFixed32NoTag:(int32_t)value;
+
+/// Write a BOOL for the given field number.
+- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value;
+/// Write a packed array of BOOL for the given field number.
+- (void)writeBoolArray:(int32_t)fieldNumber
+                values:(GPBBoolArray *)values
+                   tag:(uint32_t)tag;
+/// Write a BOOL without any tag.
+- (void)writeBoolNoTag:(BOOL)value;
+
+/// Write a int32_t for the given field number.
+- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value;
+/// Write a packed array of int32_t for the given field number.
+- (void)writeEnumArray:(int32_t)fieldNumber
+                values:(GPBEnumArray *)values
+                   tag:(uint32_t)tag;
+/// Write a int32_t without any tag.
+- (void)writeEnumNoTag:(int32_t)value;
+
+/// Write a NSString for the given field number.
+- (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
+/// Write an array of NSString for the given field number.
+- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray<NSString*> *)values;
+/// Write a NSString without any tag.
+- (void)writeStringNoTag:(NSString *)value;
+
+/// Write a GPBMessage for the given field number.
+- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
+/// Write an array of GPBMessage for the given field number.
+- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
+/// Write a GPBMessage without any tag.
+- (void)writeMessageNoTag:(GPBMessage *)value;
+
+/// Write a NSData for the given field number.
+- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value;
+/// Write an array of NSData for the given field number.
+- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray<NSData*> *)values;
+/// Write a NSData without any tag.
+- (void)writeBytesNoTag:(NSData *)value;
+
+/// Write a GPBMessage for the given field number.
+- (void)writeGroup:(int32_t)fieldNumber
+             value:(GPBMessage *)value;
+/// Write an array of GPBMessage for the given field number.
+- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
+/// Write a GPBMessage without any tag (but does write the endGroup tag).
+- (void)writeGroupNoTag:(int32_t)fieldNumber
+                  value:(GPBMessage *)value;
+
+/// Write a GPBUnknownFieldSet for the given field number.
+- (void)writeUnknownGroup:(int32_t)fieldNumber
+                    value:(GPBUnknownFieldSet *)value;
+/// Write an array of GPBUnknownFieldSet for the given field number.
+- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray<GPBUnknownFieldSet*> *)values;
+/// Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag).
+- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
+                         value:(GPBUnknownFieldSet *)value;
+
+//%PDDM-EXPAND-END _WRITE_DECLS()
+
+/// Write a MessageSet extension field to the stream. For historical reasons,
+/// the wire format differs from normal fields.
+- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value;
+
+/// Write an unparsed MessageSet extension field to the stream. For
+/// historical reasons, the wire format differs from normal fields.
+- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+// Write methods for types that can be in packed arrays.
+//%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE)
+//%/// Write a TYPE for the given field number.
+//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
+//%/// Write a packed array of TYPE for the given field number.
+//%- (void)write##NAME##Array:(int32_t)fieldNumber
+//%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
+//%       NAME$S        tag:(uint32_t)tag;
+//%/// Write a TYPE without any tag.
+//%- (void)write##NAME##NoTag:(TYPE)value;
+//%
+// Write methods for types that aren't in packed arrays.
+//%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
+//%/// Write a TYPE for the given field number.
+//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE *)value;
+//%/// Write an array of TYPE for the given field number.
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
+//%/// Write a TYPE without any tag.
+//%- (void)write##NAME##NoTag:(TYPE *)value;
+//%
+// Special write methods for Groups.
+//%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
+//%/// Write a TYPE for the given field number.
+//%- (void)write##NAME:(int32_t)fieldNumber
+//%       NAME$S value:(TYPE *)value;
+//%/// Write an array of TYPE for the given field number.
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
+//%/// Write a TYPE without any tag (but does write the endGroup tag).
+//%- (void)write##NAME##NoTag:(int32_t)fieldNumber
+//%            NAME$S value:(TYPE *)value;
+//%
+
+// One macro to hide it all up above.
+//%PDDM-DEFINE _WRITE_DECLS()
+//%_WRITE_PACKABLE_DECLS(Double, Double, double)
+//%_WRITE_PACKABLE_DECLS(Float, Float, float)
+//%_WRITE_PACKABLE_DECLS(UInt64, UInt64, uint64_t)
+//%_WRITE_PACKABLE_DECLS(Int64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(Int32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(UInt32, UInt32, uint32_t)
+//%_WRITE_PACKABLE_DECLS(Fixed64, UInt64, uint64_t)
+//%_WRITE_PACKABLE_DECLS(Fixed32, UInt32, uint32_t)
+//%_WRITE_PACKABLE_DECLS(SInt32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(SInt64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(SFixed64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL)
+//%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t)
+//%_WRITE_UNPACKABLE_DECLS(String, NSString)
+//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage)
+//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData)
+//%_WRITE_GROUP_DECLS(Group, GPBMessage)
+//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet)
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.m b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.m
new file mode 100644
index 0000000..fd9ed66
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream.m
@@ -0,0 +1,1221 @@
+// 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.
+
+#import "GPBCodedOutputStream_PackagePrivate.h"
+
+#import <mach/vm_param.h>
+
+#import "GPBArray.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+// Structure for containing state of a GPBCodedInputStream. Brought out into
+// a struct so that we can inline several common functions instead of dealing
+// with overhead of ObjC dispatch.
+typedef struct GPBOutputBufferState {
+  uint8_t *bytes;
+  size_t size;
+  size_t position;
+  NSOutputStream *output;
+} GPBOutputBufferState;
+
+@implementation GPBCodedOutputStream {
+  GPBOutputBufferState state_;
+  NSMutableData *buffer_;
+}
+
+static const int32_t LITTLE_ENDIAN_32_SIZE = sizeof(uint32_t);
+static const int32_t LITTLE_ENDIAN_64_SIZE = sizeof(uint64_t);
+
+// Internal helper that writes the current buffer to the output. The
+// buffer position is reset to its initial value when this returns.
+static void GPBRefreshBuffer(GPBOutputBufferState *state) {
+  if (state->output == nil) {
+    // We're writing to a single buffer.
+    [NSException raise:@"OutOfSpace" format:@""];
+  }
+  if (state->position != 0) {
+    NSInteger written =
+        [state->output write:state->bytes maxLength:state->position];
+    if (written != (NSInteger)state->position) {
+      [NSException raise:@"WriteFailed" format:@""];
+    }
+    state->position = 0;
+  }
+}
+
+static void GPBWriteRawByte(GPBOutputBufferState *state, uint8_t value) {
+  if (state->position == state->size) {
+    GPBRefreshBuffer(state);
+  }
+  state->bytes[state->position++] = value;
+}
+
+static void GPBWriteRawVarint32(GPBOutputBufferState *state, int32_t value) {
+  while (YES) {
+    if ((value & ~0x7F) == 0) {
+      uint8_t val = (uint8_t)value;
+      GPBWriteRawByte(state, val);
+      return;
+    } else {
+      GPBWriteRawByte(state, (value & 0x7F) | 0x80);
+      value = GPBLogicalRightShift32(value, 7);
+    }
+  }
+}
+
+static void GPBWriteRawVarint64(GPBOutputBufferState *state, int64_t value) {
+  while (YES) {
+    if ((value & ~0x7FL) == 0) {
+      uint8_t val = (uint8_t)value;
+      GPBWriteRawByte(state, val);
+      return;
+    } else {
+      GPBWriteRawByte(state, ((int32_t)value & 0x7F) | 0x80);
+      value = GPBLogicalRightShift64(value, 7);
+    }
+  }
+}
+
+static void GPBWriteInt32NoTag(GPBOutputBufferState *state, int32_t value) {
+  if (value >= 0) {
+    GPBWriteRawVarint32(state, value);
+  } else {
+    // Must sign-extend
+    GPBWriteRawVarint64(state, value);
+  }
+}
+
+static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber,
+                           uint32_t value) {
+  GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint32(state, value);
+}
+
+static void GPBWriteTagWithFormat(GPBOutputBufferState *state,
+                                  uint32_t fieldNumber, GPBWireFormat format) {
+  GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format));
+}
+
+static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state,
+                                      int32_t value) {
+  GPBWriteRawByte(state, (value)&0xFF);
+  GPBWriteRawByte(state, (value >> 8) & 0xFF);
+  GPBWriteRawByte(state, (value >> 16) & 0xFF);
+  GPBWriteRawByte(state, (value >> 24) & 0xFF);
+}
+
+static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
+                                      int64_t value) {
+  GPBWriteRawByte(state, (int32_t)(value)&0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 24) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 32) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 40) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 48) & 0xFF);
+  GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF);
+}
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
++ (void)load {
+  // This test exists to verify that CFStrings with embedded NULLs will work
+  // for us. If this Assert fails, all code below that depends on
+  // CFStringGetCStringPtr will NOT work properly on strings that contain
+  // embedded NULLs, and we do get that in some protobufs.
+  // Note that this will not be compiled in release.
+  // We didn't feel that just keeping it in a unit test was sufficient because
+  // the Protobuf unit tests are only run when somebody is actually working
+  // on protobufs.
+  CFStringRef zeroTest = CFSTR("Test\0String");
+  const char *cString = CFStringGetCStringPtr(zeroTest, kCFStringEncodingUTF8);
+  NSAssert(cString == NULL, @"Serious Error");
+}
+#endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+
+- (void)dealloc {
+  [self flush];
+  [state_.output close];
+  [state_.output release];
+  [buffer_ release];
+
+  [super dealloc];
+}
+
+- (instancetype)initWithOutputStream:(NSOutputStream *)output {
+  NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
+  return [self initWithOutputStream:output data:data];
+}
+
+- (instancetype)initWithData:(NSMutableData *)data {
+  return [self initWithOutputStream:nil data:data];
+}
+
+// This initializer isn't exposed, but it is the designated initializer.
+// Setting OutputStream and NSData is to control the buffering behavior/size
+// of the work, but that is more obvious via the bufferSize: version.
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+                                data:(NSMutableData *)data {
+  if ((self = [super init])) {
+    buffer_ = [data retain];
+    [output open];
+    state_.bytes = [data mutableBytes];
+    state_.size = [data length];
+    state_.output = [output retain];
+  }
+  return self;
+}
+
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output {
+  NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
+  return [[[self alloc] initWithOutputStream:output
+                                        data:data] autorelease];
+}
+
++ (instancetype)streamWithData:(NSMutableData *)data {
+  return [[[self alloc] initWithData:data] autorelease];
+}
+
+- (void)writeDoubleNoTag:(double)value {
+  GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
+}
+
+- (void)writeDouble:(int32_t)fieldNumber value:(double)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+  GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
+}
+
+- (void)writeFloatNoTag:(float)value {
+  GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
+}
+
+- (void)writeFloat:(int32_t)fieldNumber value:(float)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+  GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
+}
+
+- (void)writeUInt64NoTag:(uint64_t)value {
+  GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt64NoTag:(int64_t)value {
+  GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt32NoTag:(int32_t)value {
+  GPBWriteInt32NoTag(&state_, value);
+}
+
+- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteInt32NoTag(&state_, value);
+}
+
+- (void)writeFixed64NoTag:(uint64_t)value {
+  GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+  GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeFixed32NoTag:(uint32_t)value {
+  GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+  GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeBoolNoTag:(BOOL)value {
+  GPBWriteRawByte(&state_, (value ? 1 : 0));
+}
+
+- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawByte(&state_, (value ? 1 : 0));
+}
+
+- (void)writeStringNoTag:(const NSString *)value {
+  // If you are concerned about embedded NULLs see the test in
+  // +load above.
+  const char *quickString =
+      CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+  size_t length = (quickString != NULL)
+                      ? strlen(quickString)
+                      : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+  GPBWriteRawVarint32(&state_, (int32_t)length);
+
+  if (length == 0) {
+    return;
+  }
+
+  // Fast path: Most strings are short, if the buffer already has space,
+  // add to it directly.
+  NSUInteger bufferBytesLeft = state_.size - state_.position;
+  if (bufferBytesLeft >= length) {
+    NSUInteger usedBufferLength = 0;
+    BOOL result;
+    if (quickString != NULL) {
+      memcpy(state_.bytes + state_.position, quickString, length);
+      usedBufferLength = length;
+      result = YES;
+    } else {
+      result = [value getBytes:state_.bytes + state_.position
+                     maxLength:bufferBytesLeft
+                    usedLength:&usedBufferLength
+                      encoding:NSUTF8StringEncoding
+                       options:0
+                         range:NSMakeRange(0, [value length])
+                remainingRange:NULL];
+    }
+    if (result) {
+      NSAssert2((usedBufferLength == length),
+                @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength,
+                length);
+      state_.position += usedBufferLength;
+      return;
+    }
+  } else if (quickString != NULL) {
+    [self writeRawPtr:quickString offset:0 length:length];
+  } else {
+    // Slow path: just get it as data and write it out.
+    NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding];
+    NSAssert2(([utf8Data length] == length),
+              @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length],
+              length);
+    [self writeRawData:utf8Data];
+  }
+}
+
+- (void)writeString:(int32_t)fieldNumber value:(NSString *)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+  [self writeStringNoTag:value];
+}
+
+- (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value {
+  [value writeToCodedOutputStream:self];
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
+}
+
+- (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
+  [self writeGroupNoTag:fieldNumber value:value];
+}
+
+- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
+                         value:(const GPBUnknownFieldSet *)value {
+  [value writeToCodedOutputStream:self];
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
+}
+
+- (void)writeUnknownGroup:(int32_t)fieldNumber
+                    value:(GPBUnknownFieldSet *)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
+  [self writeUnknownGroupNoTag:fieldNumber value:value];
+}
+
+- (void)writeMessageNoTag:(GPBMessage *)value {
+  GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]);
+  [value writeToCodedOutputStream:self];
+}
+
+- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+  [self writeMessageNoTag:value];
+}
+
+- (void)writeBytesNoTag:(NSData *)value {
+  GPBWriteRawVarint32(&state_, (int32_t)[value length]);
+  [self writeRawData:value];
+}
+
+- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+  [self writeBytesNoTag:value];
+}
+
+- (void)writeUInt32NoTag:(uint32_t)value {
+  GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value {
+  GPBWriteUInt32(&state_, fieldNumber, value);
+}
+
+- (void)writeEnumNoTag:(int32_t)value {
+  GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeSFixed32NoTag:(int32_t)value {
+  GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+  GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeSFixed64NoTag:(int64_t)value {
+  GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+  GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeSInt32NoTag:(int32_t)value {
+  GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
+}
+
+- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
+}
+
+- (void)writeSInt64NoTag:(int64_t)value {
+  GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
+}
+
+- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value {
+  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+  GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
+}
+
+//%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME)
+//%- (void)write##NAME##Array:(int32_t)fieldNumber
+//%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
+//%       NAME$S        tag:(uint32_t)tag {
+//%  if (tag != 0) {
+//%    if (values.count == 0) return;
+//%    __block size_t dataSize = 0;
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//%      dataSize += GPBCompute##NAME##SizeNoTag(value);
+//%    }];
+//%    GPBWriteRawVarint32(&state_, tag);
+//%    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//%      [self write##NAME##NoTag:value];
+//%    }];
+//%  } else {
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//%      [self write##NAME:fieldNumber value:value];
+//%    }];
+//%  }
+//%}
+//%
+//%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE)
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values {
+//%  for (TYPE *value in values) {
+//%    [self write##NAME:fieldNumber value:value];
+//%  }
+//%}
+//%
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeDoubleArray:(int32_t)fieldNumber
+                  values:(GPBDoubleArray *)values
+                     tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeDoubleSizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeDoubleNoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeDouble:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFloatArray:(int32_t)fieldNumber
+                 values:(GPBFloatArray *)values
+                    tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeFloatSizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFloatNoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFloat:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUInt64Array:(int32_t)fieldNumber
+                  values:(GPBUInt64Array *)values
+                     tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeUInt64SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeUInt64NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeUInt64:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeInt64Array:(int32_t)fieldNumber
+                 values:(GPBInt64Array *)values
+                    tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeInt64SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeInt64NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeInt64:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeInt32Array:(int32_t)fieldNumber
+                 values:(GPBInt32Array *)values
+                    tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeInt32SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeInt32NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeInt32:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUInt32Array:(int32_t)fieldNumber
+                  values:(GPBUInt32Array *)values
+                     tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeUInt32SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeUInt32NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeUInt32:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFixed64Array:(int32_t)fieldNumber
+                   values:(GPBUInt64Array *)values
+                      tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeFixed64SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFixed64NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFixed64:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFixed32Array:(int32_t)fieldNumber
+                   values:(GPBUInt32Array *)values
+                      tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeFixed32SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFixed32NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeFixed32:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSInt32Array:(int32_t)fieldNumber
+                  values:(GPBInt32Array *)values
+                     tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeSInt32SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSInt32NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSInt32:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSInt64Array:(int32_t)fieldNumber
+                  values:(GPBInt64Array *)values
+                     tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeSInt64SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSInt64NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSInt64:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSFixed64Array:(int32_t)fieldNumber
+                    values:(GPBInt64Array *)values
+                       tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeSFixed64SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSFixed64NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSFixed64:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSFixed32Array:(int32_t)fieldNumber
+                    values:(GPBInt32Array *)values
+                       tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeSFixed32SizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSFixed32NoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeSFixed32:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeBoolArray:(int32_t)fieldNumber
+                values:(GPBBoolArray *)values
+                   tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeBoolSizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeBoolNoTag:value];
+    }];
+  } else {
+    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeBool:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeEnumArray:(int32_t)fieldNumber
+                values:(GPBEnumArray *)values
+                   tag:(uint32_t)tag {
+  if (tag != 0) {
+    if (values.count == 0) return;
+    __block size_t dataSize = 0;
+    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      dataSize += GPBComputeEnumSizeNoTag(value);
+    }];
+    GPBWriteRawVarint32(&state_, tag);
+    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeEnumNoTag:value];
+    }];
+  } else {
+    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+      [self writeEnum:fieldNumber value:value];
+    }];
+  }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values {
+  for (NSString *value in values) {
+    [self writeString:fieldNumber value:value];
+  }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values {
+  for (GPBMessage *value in values) {
+    [self writeMessage:fieldNumber value:value];
+  }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values {
+  for (NSData *value in values) {
+    [self writeBytes:fieldNumber value:value];
+  }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
+  for (GPBMessage *value in values) {
+    [self writeGroup:fieldNumber value:value];
+  }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
+  for (GPBUnknownFieldSet *value in values) {
+    [self writeUnknownGroup:fieldNumber value:value];
+  }
+}
+
+//%PDDM-EXPAND-END (19 expansions)
+
+- (void)writeMessageSetExtension:(int32_t)fieldNumber
+                           value:(GPBMessage *)value {
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+                        GPBWireFormatStartGroup);
+  GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
+  [self writeMessage:GPBWireFormatMessageSetMessage value:value];
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+                        GPBWireFormatEndGroup);
+}
+
+- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value {
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+                        GPBWireFormatStartGroup);
+  GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
+  [self writeBytes:GPBWireFormatMessageSetMessage value:value];
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+                        GPBWireFormatEndGroup);
+}
+
+- (void)flush {
+  if (state_.output != nil) {
+    GPBRefreshBuffer(&state_);
+  }
+}
+
+- (void)writeRawByte:(uint8_t)value {
+  GPBWriteRawByte(&state_, value);
+}
+
+- (void)writeRawData:(const NSData *)data {
+  [self writeRawPtr:[data bytes] offset:0 length:[data length]];
+}
+
+- (void)writeRawPtr:(const void *)value
+             offset:(size_t)offset
+             length:(size_t)length {
+  if (value == nil || length == 0) {
+    return;
+  }
+
+  NSUInteger bufferLength = state_.size;
+  NSUInteger bufferBytesLeft = bufferLength - state_.position;
+  if (bufferBytesLeft >= length) {
+    // We have room in the current buffer.
+    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, length);
+    state_.position += length;
+  } else {
+    // Write extends past current buffer.  Fill the rest of this buffer and
+    // flush.
+    size_t bytesWritten = bufferBytesLeft;
+    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset,
+           bytesWritten);
+    offset += bytesWritten;
+    length -= bytesWritten;
+    state_.position = bufferLength;
+    GPBRefreshBuffer(&state_);
+    bufferLength = state_.size;
+
+    // Now deal with the rest.
+    // Since we have an output stream, this is our buffer
+    // and buffer offset == 0
+    if (length <= bufferLength) {
+      // Fits in new buffer.
+      memcpy(state_.bytes, ((uint8_t *)value) + offset, length);
+      state_.position = length;
+    } else {
+      // Write is very big.  Let's do it all at once.
+      [state_.output write:((uint8_t *)value) + offset maxLength:length];
+    }
+  }
+}
+
+- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format {
+  GPBWriteTagWithFormat(&state_, fieldNumber, format);
+}
+
+- (void)writeRawVarint32:(int32_t)value {
+  GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeRawVarintSizeTAs32:(size_t)value {
+  // Note the truncation.
+  GPBWriteRawVarint32(&state_, (int32_t)value);
+}
+
+- (void)writeRawVarint64:(int64_t)value {
+  GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeRawLittleEndian32:(int32_t)value {
+  GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeRawLittleEndian64:(int64_t)value {
+  GPBWriteRawLittleEndian64(&state_, value);
+}
+
+@end
+
+size_t GPBComputeDoubleSizeNoTag(Float64 value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeFloatSizeNoTag(Float32 value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeUInt64SizeNoTag(uint64_t value) {
+  return GPBComputeRawVarint64Size(value);
+}
+
+size_t GPBComputeInt64SizeNoTag(int64_t value) {
+  return GPBComputeRawVarint64Size(value);
+}
+
+size_t GPBComputeInt32SizeNoTag(int32_t value) {
+  if (value >= 0) {
+    return GPBComputeRawVarint32Size(value);
+  } else {
+    // Must sign-extend.
+    return 10;
+  }
+}
+
+size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) {
+  return GPBComputeInt32SizeNoTag((int32_t)value);
+}
+
+size_t GPBComputeFixed64SizeNoTag(uint64_t value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeFixed32SizeNoTag(uint32_t value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeBoolSizeNoTag(BOOL value) {
+#pragma unused(value)
+  return 1;
+}
+
+size_t GPBComputeStringSizeNoTag(NSString *value) {
+  // If you are concerned about embedded NULLs see the test in
+  // +load above.
+  const char *quickString =
+      CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+  NSUInteger length =
+      (quickString != NULL)
+          ? strlen(quickString)
+          : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+  return GPBComputeRawVarint32SizeForInteger(length) + length;
+}
+
+size_t GPBComputeGroupSizeNoTag(GPBMessage *value) {
+  return [value serializedSize];
+}
+
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) {
+  return value.serializedSize;
+}
+
+size_t GPBComputeMessageSizeNoTag(GPBMessage *value) {
+  size_t size = [value serializedSize];
+  return GPBComputeRawVarint32SizeForInteger(size) + size;
+}
+
+size_t GPBComputeBytesSizeNoTag(NSData *value) {
+  NSUInteger valueLength = [value length];
+  return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength;
+}
+
+size_t GPBComputeUInt32SizeNoTag(int32_t value) {
+  return GPBComputeRawVarint32Size(value);
+}
+
+size_t GPBComputeEnumSizeNoTag(int32_t value) {
+  return GPBComputeRawVarint32Size(value);
+}
+
+size_t GPBComputeSFixed32SizeNoTag(int32_t value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeSFixed64SizeNoTag(int64_t value) {
+#pragma unused(value)
+  return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeSInt32SizeNoTag(int32_t value) {
+  return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value));
+}
+
+size_t GPBComputeSInt64SizeNoTag(int64_t value) {
+  return GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
+}
+
+size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeDoubleSizeNoTag(value);
+}
+
+size_t GPBComputeFloatSize(int32_t fieldNumber, float value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeFloatSizeNoTag(value);
+}
+
+size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeUInt64SizeNoTag(value);
+}
+
+size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeInt64SizeNoTag(value);
+}
+
+size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeInt32SizeNoTag(value);
+}
+
+size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeFixed64SizeNoTag(value);
+}
+
+size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeFixed32SizeNoTag(value);
+}
+
+size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeBoolSizeNoTag(value);
+}
+
+size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeStringSizeNoTag(value);
+}
+
+size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) {
+  return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value);
+}
+
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
+                                  GPBUnknownFieldSet *value) {
+  return GPBComputeTagSize(fieldNumber) * 2 +
+         GPBComputeUnknownGroupSizeNoTag(value);
+}
+
+size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value);
+}
+
+size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value);
+}
+
+size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeUInt32SizeNoTag(value);
+}
+
+size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeEnumSizeNoTag(value);
+}
+
+size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed32SizeNoTag(value);
+}
+
+size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed64SizeNoTag(value);
+}
+
+size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) {
+  return GPBComputeTagSize(fieldNumber) + GPBComputeSInt32SizeNoTag(value);
+}
+
+size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) {
+  return GPBComputeTagSize(fieldNumber) +
+         GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
+}
+
+size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber,
+                                         GPBMessage *value) {
+  return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
+         GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
+         GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value);
+}
+
+size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber,
+                                            NSData *value) {
+  return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
+         GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
+         GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value);
+}
+
+size_t GPBComputeTagSize(int32_t fieldNumber) {
+  return GPBComputeRawVarint32Size(
+      GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
+}
+
+size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) {
+  size_t result = GPBComputeTagSize(field_number);
+  if (dataType == GPBDataTypeGroup) {
+    // Groups have both a start and an end tag.
+    return result * 2;
+  } else {
+    return result;
+  }
+}
+
+size_t GPBComputeRawVarint32Size(int32_t value) {
+  // value is treated as unsigned, so it won't be sign-extended if negative.
+  if ((value & (0xffffffff << 7)) == 0) return 1;
+  if ((value & (0xffffffff << 14)) == 0) return 2;
+  if ((value & (0xffffffff << 21)) == 0) return 3;
+  if ((value & (0xffffffff << 28)) == 0) return 4;
+  return 5;
+}
+
+size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) {
+  // Note the truncation.
+  return GPBComputeRawVarint32Size((int32_t)value);
+}
+
+size_t GPBComputeRawVarint64Size(int64_t value) {
+  if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
+  if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
+  if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
+  if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
+  if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
+  if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
+  if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
+  if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
+  if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
+  return 10;
+}
diff --git a/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream_PackagePrivate.h
new file mode 100644
index 0000000..2e7bb4c
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBCodedOutputStream_PackagePrivate.h
@@ -0,0 +1,126 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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.
+
+#import "GPBCodedOutputStream.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+CF_EXTERN_C_BEGIN
+
+size_t GPBComputeDoubleSize(int32_t fieldNumber, double value)
+    __attribute__((const));
+size_t GPBComputeFloatSize(int32_t fieldNumber, float value)
+    __attribute__((const));
+size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value)
+    __attribute__((const));
+size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value)
+    __attribute__((const));
+size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value)
+    __attribute__((const));
+size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value)
+    __attribute__((const));
+size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value)
+    __attribute__((const));
+size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value)
+    __attribute__((const));
+size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value)
+    __attribute__((const));
+size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value)
+    __attribute__((const));
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
+                                  GPBUnknownFieldSet *value)
+    __attribute__((const));
+size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value)
+    __attribute__((const));
+size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value)
+    __attribute__((const));
+size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value)
+    __attribute__((const));
+size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value)
+    __attribute__((const));
+size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value)
+    __attribute__((const));
+size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value)
+    __attribute__((const));
+size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value)
+    __attribute__((const));
+size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const));
+size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType)
+    __attribute__((const));
+
+size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const));
+size_t GPBComputeFloatSizeNoTag(float value) __attribute__((const));
+size_t GPBComputeUInt64SizeNoTag(uint64_t value) __attribute__((const));
+size_t GPBComputeInt64SizeNoTag(int64_t value) __attribute__((const));
+size_t GPBComputeInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeFixed64SizeNoTag(uint64_t value) __attribute__((const));
+size_t GPBComputeFixed32SizeNoTag(uint32_t value) __attribute__((const));
+size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const));
+size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const));
+size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const));
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value)
+    __attribute__((const));
+size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const));
+size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const));
+size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSFixed64SizeNoTag(int64_t value) __attribute__((const));
+size_t GPBComputeSInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSInt64SizeNoTag(int64_t value) __attribute__((const));
+
+// Note that this will calculate the size of 64 bit values truncated to 32.
+size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) __attribute__((const));
+
+size_t GPBComputeRawVarint32Size(int32_t value) __attribute__((const));
+size_t GPBComputeRawVarint64Size(int64_t value) __attribute__((const));
+
+// Note that this will calculate the size of 64 bit values truncated to 32.
+size_t GPBComputeRawVarint32SizeForInteger(NSInteger value)
+    __attribute__((const));
+
+// Compute the number of bytes that would be needed to encode a
+// MessageSet extension to the stream.  For historical reasons,
+// the wire format differs from normal fields.
+size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, GPBMessage *value)
+    __attribute__((const));
+
+// Compute the number of bytes that would be needed to encode an
+// unparsed MessageSet extension field to the stream.  For
+// historical reasons, the wire format differs from normal fields.
+size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value)
+    __attribute__((const));
+
+size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value)
+    __attribute__((const));
+
+CF_EXTERN_C_END
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBDescriptor.h b/src/third_party/protobuf-3/objectivec/GPBDescriptor.h
new file mode 100644
index 0000000..a6eff0f
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDescriptor.h
@@ -0,0 +1,141 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBRuntimeTypes.h"
+
+@class GPBEnumDescriptor;
+@class GPBFieldDescriptor;
+@class GPBFileDescriptor;
+@class GPBOneofDescriptor;
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(uint8_t, GPBFileSyntax) {
+  GPBFileSyntaxUnknown = 0,
+  GPBFileSyntaxProto2 = 2,
+  GPBFileSyntaxProto3 = 3,
+};
+
+typedef NS_ENUM(uint8_t, GPBFieldType) {
+  GPBFieldTypeSingle,    // optional/required
+  GPBFieldTypeRepeated,  // repeated
+  GPBFieldTypeMap,       // map<K,V>
+};
+
+@interface GPBDescriptor : NSObject<NSCopying>
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBFieldDescriptor*> *fields;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBOneofDescriptor*> *oneofs;
+@property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges;
+@property(nonatomic, readonly) uint32_t extensionRangesCount;
+@property(nonatomic, readonly, assign) GPBFileDescriptor *file;
+
+@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat;
+@property(nonatomic, readonly) Class messageClass;
+
+- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+- (nullable GPBOneofDescriptor *)oneofWithName:(NSString *)name;
+
+@end
+
+@interface GPBFileDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *package;
+@property(nonatomic, readonly) GPBFileSyntax syntax;
+
+@end
+
+@interface GPBOneofDescriptor : NSObject
+@property(nonatomic, readonly) NSString *name;
+@property(nonatomic, readonly) NSArray<GPBFieldDescriptor*> *fields;
+
+- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+@end
+
+@interface GPBFieldDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly) uint32_t number;
+@property(nonatomic, readonly) GPBDataType dataType;
+@property(nonatomic, readonly) BOOL hasDefaultValue;
+@property(nonatomic, readonly) GPBGenericValue defaultValue;
+@property(nonatomic, readonly, getter=isRequired) BOOL required;
+@property(nonatomic, readonly, getter=isOptional) BOOL optional;
+@property(nonatomic, readonly) GPBFieldType fieldType;
+// If it is a map, the value type is in -type.
+@property(nonatomic, readonly) GPBDataType mapKeyDataType;
+@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+
+@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof;
+
+// Message properties
+@property(nonatomic, readonly, assign, nullable) Class msgClass;
+
+// Enum properties
+@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor;
+
+- (BOOL)isValidEnumValue:(int32_t)value;
+
+// For now, this will return nil if it doesn't know the name to use for
+// TextFormat.
+- (nullable NSString *)textFormatName;
+
+@end
+
+@interface GPBEnumDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier;
+
+- (nullable NSString *)enumNameForValue:(int32_t)number;
+- (BOOL)getValue:(nullable int32_t *)outValue forEnumName:(NSString *)name;
+
+- (nullable NSString *)textFormatNameForValue:(int32_t)number;
+
+@end
+
+@interface GPBExtensionDescriptor : NSObject<NSCopying>
+@property(nonatomic, readonly) uint32_t fieldNumber;
+@property(nonatomic, readonly) Class containingMessageClass;
+@property(nonatomic, readonly) GPBDataType dataType;
+@property(nonatomic, readonly, getter=isRepeated) BOOL repeated;
+@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+@property(nonatomic, readonly, assign) Class msgClass;
+@property(nonatomic, readonly) NSString *singletonName;
+@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor;
+@property(nonatomic, readonly) id defaultValue;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBDescriptor.m b/src/third_party/protobuf-3/objectivec/GPBDescriptor.m
new file mode 100644
index 0000000..2709737
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDescriptor.m
@@ -0,0 +1,963 @@
+// 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.
+
+#import "GPBDescriptor_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBUtilities_PackagePrivate.h"
+#import "GPBWireFormat.h"
+#import "GPBMessage_PackagePrivate.h"
+
+// The address of this variable is used as a key for obj_getAssociatedObject.
+static const char kTextFormatExtraValueKey = 0;
+
+// Utility function to generate selectors on the fly.
+static SEL SelFromStrings(const char *prefix, const char *middle,
+                          const char *suffix, BOOL takesArg) {
+  if (prefix == NULL && suffix == NULL && !takesArg) {
+    return sel_getUid(middle);
+  }
+  const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0;
+  const size_t middleLen = strlen(middle);
+  const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0;
+  size_t totalLen =
+      prefixLen + middleLen + suffixLen + 1;  // include space for null on end.
+  if (takesArg) {
+    totalLen += 1;
+  }
+  char buffer[totalLen];
+  if (prefix != NULL) {
+    memcpy(buffer, prefix, prefixLen);
+    memcpy(buffer + prefixLen, middle, middleLen);
+    buffer[prefixLen] = (char)toupper(buffer[prefixLen]);
+  } else {
+    memcpy(buffer, middle, middleLen);
+  }
+  if (suffix != NULL) {
+    memcpy(buffer + prefixLen + middleLen, suffix, suffixLen);
+  }
+  if (takesArg) {
+    buffer[totalLen - 2] = ':';
+  }
+  // Always null terminate it.
+  buffer[totalLen - 1] = 0;
+
+  SEL result = sel_getUid(buffer);
+  return result;
+}
+
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
+                                          NSArray *allMessageFields)
+    __attribute__((ns_returns_retained));
+
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
+                                          NSArray *allMessageFields) {
+  NSMutableArray *result = [[NSMutableArray alloc] init];
+  for (GPBFieldDescriptor *fieldDesc in allMessageFields) {
+    if (fieldDesc->description_->hasIndex == hasIndex) {
+      [result addObject:fieldDesc];
+    }
+  }
+  return result;
+}
+
+@implementation GPBDescriptor {
+  Class messageClass_;
+  GPBFileDescriptor *file_;
+  BOOL wireFormat_;
+}
+
+@synthesize messageClass = messageClass_;
+@synthesize fields = fields_;
+@synthesize oneofs = oneofs_;
+@synthesize extensionRanges = extensionRanges_;
+@synthesize extensionRangesCount = extensionRangesCount_;
+@synthesize file = file_;
+@synthesize wireFormat = wireFormat_;
+
++ (instancetype)
+    allocDescriptorForClass:(Class)messageClass
+                  rootClass:(Class)rootClass
+                       file:(GPBFileDescriptor *)file
+                     fields:(void *)fieldDescriptions
+                 fieldCount:(uint32_t)fieldCount
+                storageSize:(uint32_t)storageSize
+                      flags:(GPBDescriptorInitializationFlags)flags {
+  // The rootClass is no longer used, but it is passed in to ensure it
+  // was started up during initialization also.
+  (void)rootClass;
+  NSMutableArray *fields = nil;
+  GPBFileSyntax syntax = file.syntax;
+  BOOL fieldsIncludeDefault =
+      (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
+
+  void *desc;
+  for (uint32_t i = 0; i < fieldCount; ++i) {
+    if (fields == nil) {
+      fields = [[NSMutableArray alloc] initWithCapacity:fieldCount];
+    }
+    // Need correctly typed pointer for array indexing below to work.
+    if (fieldsIncludeDefault) {
+      GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions;
+      desc = &(fieldDescWithDefault[i]);
+    } else {
+      GPBMessageFieldDescription *fieldDesc = fieldDescriptions;
+      desc = &(fieldDesc[i]);
+    }
+    GPBFieldDescriptor *fieldDescriptor =
+        [[GPBFieldDescriptor alloc] initWithFieldDescription:desc
+                                             includesDefault:fieldsIncludeDefault
+                                                      syntax:syntax];
+    [fields addObject:fieldDescriptor];
+    [fieldDescriptor release];
+  }
+
+  BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0;
+  GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass
+                                                     file:file
+                                                   fields:fields
+                                              storageSize:storageSize
+                                               wireFormat:wireFormat];
+  [fields release];
+  return descriptor;
+}
+
+- (instancetype)initWithClass:(Class)messageClass
+                         file:(GPBFileDescriptor *)file
+                       fields:(NSArray *)fields
+                  storageSize:(uint32_t)storageSize
+                   wireFormat:(BOOL)wireFormat {
+  if ((self = [super init])) {
+    messageClass_ = messageClass;
+    file_ = file;
+    fields_ = [fields retain];
+    storageSize_ = storageSize;
+    wireFormat_ = wireFormat;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [fields_ release];
+  [oneofs_ release];
+  [super dealloc];
+}
+
+- (void)setupOneofs:(const char **)oneofNames
+              count:(uint32_t)count
+      firstHasIndex:(int32_t)firstHasIndex {
+  NSCAssert(firstHasIndex < 0, @"Should always be <0");
+  NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) {
+    const char *name = oneofNames[i];
+    NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_);
+    NSCAssert(fieldsForOneof.count > 0,
+              @"No fields for this oneof? (%s:%d)", name, hasIndex);
+    GPBOneofDescriptor *oneofDescriptor =
+        [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof];
+    [oneofs addObject:oneofDescriptor];
+    [oneofDescriptor release];
+    [fieldsForOneof release];
+  }
+  oneofs_ = oneofs;
+}
+
+- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo {
+  // Extra info is a compile time option, so skip the work if not needed.
+  if (extraTextFormatInfo) {
+    NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo];
+    for (GPBFieldDescriptor *fieldDescriptor in fields_) {
+      if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) {
+        objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey,
+                                 extraInfoValue,
+                                 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+      }
+    }
+  }
+}
+
+- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count {
+  extensionRanges_ = ranges;
+  extensionRangesCount_ = count;
+}
+
+- (NSString *)name {
+  return NSStringFromClass(messageClass_);
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+#pragma unused(zone)
+  return [self retain];
+}
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
+  for (GPBFieldDescriptor *descriptor in fields_) {
+    if (GPBFieldNumber(descriptor) == fieldNumber) {
+      return descriptor;
+    }
+  }
+  return nil;
+}
+
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
+  for (GPBFieldDescriptor *descriptor in fields_) {
+    if ([descriptor.name isEqual:name]) {
+      return descriptor;
+    }
+  }
+  return nil;
+}
+
+- (GPBOneofDescriptor *)oneofWithName:(NSString *)name {
+  for (GPBOneofDescriptor *descriptor in oneofs_) {
+    if ([descriptor.name isEqual:name]) {
+      return descriptor;
+    }
+  }
+  return nil;
+}
+
+@end
+
+@implementation GPBFileDescriptor {
+  NSString *package_;
+  GPBFileSyntax syntax_;
+}
+
+@synthesize package = package_;
+@synthesize syntax = syntax_;
+
+- (instancetype)initWithPackage:(NSString *)package
+                         syntax:(GPBFileSyntax)syntax {
+  self = [super init];
+  if (self) {
+    package_ = [package copy];
+    syntax_ = syntax;
+  }
+  return self;
+}
+
+@end
+
+@implementation GPBOneofDescriptor
+
+@synthesize fields = fields_;
+
+- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields {
+  self = [super init];
+  if (self) {
+    name_ = name;
+    fields_ = [fields retain];
+    for (GPBFieldDescriptor *fieldDesc in fields) {
+      fieldDesc->containingOneof_ = self;
+    }
+
+    caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [fields_ release];
+  [super dealloc];
+}
+
+- (NSString *)name {
+  return @(name_);
+}
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
+  for (GPBFieldDescriptor *descriptor in fields_) {
+    if (GPBFieldNumber(descriptor) == fieldNumber) {
+      return descriptor;
+    }
+  }
+  return nil;
+}
+
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
+  for (GPBFieldDescriptor *descriptor in fields_) {
+    if ([descriptor.name isEqual:name]) {
+      return descriptor;
+    }
+  }
+  return nil;
+}
+
+@end
+
+uint32_t GPBFieldTag(GPBFieldDescriptor *self) {
+  GPBMessageFieldDescription *description = self->description_;
+  GPBWireFormat format;
+  if ((description->flags & GPBFieldMapKeyMask) != 0) {
+    // Maps are repeated messages on the wire.
+    format = GPBWireFormatForType(GPBDataTypeMessage, NO);
+  } else {
+    format = GPBWireFormatForType(description->dataType,
+                                  ((description->flags & GPBFieldPacked) != 0));
+  }
+  return GPBWireFormatMakeTag(description->number, format);
+}
+
+uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
+  GPBMessageFieldDescription *description = self->description_;
+  NSCAssert((description->flags & GPBFieldRepeated) != 0,
+            @"Only valid on repeated fields");
+  GPBWireFormat format =
+      GPBWireFormatForType(description->dataType,
+                           ((description->flags & GPBFieldPacked) == 0));
+  return GPBWireFormatMakeTag(description->number, format);
+}
+
+@implementation GPBFieldDescriptor {
+  GPBGenericValue defaultValue_;
+
+  // Message ivars
+  Class msgClass_;
+
+  // Enum ivars.
+  // If protos are generated with GenerateEnumDescriptors on then it will
+  // be a enumDescriptor, otherwise it will be a enumVerifier.
+  union {
+    GPBEnumDescriptor *enumDescriptor_;
+    GPBEnumValidationFunc enumVerifier_;
+  } enumHandling_;
+}
+
+@synthesize msgClass = msgClass_;
+@synthesize containingOneof = containingOneof_;
+
+- (instancetype)init {
+  // Throw an exception if people attempt to not use the designated initializer.
+  self = [super init];
+  if (self != nil) {
+    [self doesNotRecognizeSelector:_cmd];
+    self = nil;
+  }
+  return self;
+}
+
+- (instancetype)initWithFieldDescription:(void *)description
+                         includesDefault:(BOOL)includesDefault
+                                  syntax:(GPBFileSyntax)syntax {
+  if ((self = [super init])) {
+    GPBMessageFieldDescription *coreDesc;
+    if (includesDefault) {
+      coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core);
+    } else {
+      coreDesc = description;
+    }
+    description_ = coreDesc;
+    getSel_ = sel_getUid(coreDesc->name);
+    setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES);
+
+    GPBDataType dataType = coreDesc->dataType;
+    BOOL isMessage = GPBDataTypeIsMessage(dataType);
+    BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
+
+    if (isMapOrArray) {
+      // map<>/repeated fields get a *Count property (inplace of a has*) to
+      // support checking if there are any entries without triggering
+      // autocreation.
+      hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO);
+    } else {
+      // If there is a positive hasIndex, then:
+      //   - All fields types for proto2 messages get has* selectors.
+      //   - Only message fields for proto3 messages get has* selectors.
+      // Note: the positive check is to handle oneOfs, we can't check
+      // containingOneof_ because it isn't set until after initialization.
+      if ((coreDesc->hasIndex >= 0) &&
+          (coreDesc->hasIndex != GPBNoHasBit) &&
+          ((syntax != GPBFileSyntaxProto3) || isMessage)) {
+        hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO);
+        setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES);
+      }
+    }
+
+    // Extra type specific data.
+    if (isMessage) {
+      const char *className = coreDesc->dataTypeSpecific.className;
+      msgClass_ = objc_getClass(className);
+      NSAssert(msgClass_, @"Class %s not defined", className);
+    } else if (dataType == GPBDataTypeEnum) {
+      if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) {
+        enumHandling_.enumDescriptor_ =
+            coreDesc->dataTypeSpecific.enumDescFunc();
+      } else {
+        enumHandling_.enumVerifier_ =
+            coreDesc->dataTypeSpecific.enumVerifier;
+      }
+    }
+
+    // Non map<>/repeated fields can have defaults in proto2 syntax.
+    if (!isMapOrArray && includesDefault) {
+      defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue;
+      if (dataType == GPBDataTypeBytes) {
+        // Data stored as a length prefixed (network byte order) c-string in
+        // descriptor structure.
+        const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData;
+        if (bytes) {
+          uint32_t length = *((uint32_t *)bytes);
+          length = ntohl(length);
+          bytes += sizeof(length);
+          defaultValue_.valueData =
+              [[NSData alloc] initWithBytes:bytes length:length];
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if (description_->dataType == GPBDataTypeBytes &&
+      !(description_->flags & GPBFieldRepeated)) {
+    [defaultValue_.valueData release];
+  }
+  [super dealloc];
+}
+
+- (GPBDataType)dataType {
+  return description_->dataType;
+}
+
+- (BOOL)hasDefaultValue {
+  return (description_->flags & GPBFieldHasDefaultValue) != 0;
+}
+
+- (uint32_t)number {
+  return description_->number;
+}
+
+- (NSString *)name {
+  return @(description_->name);
+}
+
+- (BOOL)isRequired {
+  return (description_->flags & GPBFieldRequired) != 0;
+}
+
+- (BOOL)isOptional {
+  return (description_->flags & GPBFieldOptional) != 0;
+}
+
+- (GPBFieldType)fieldType {
+  GPBFieldFlags flags = description_->flags;
+  if ((flags & GPBFieldRepeated) != 0) {
+    return GPBFieldTypeRepeated;
+  } else if ((flags & GPBFieldMapKeyMask) != 0) {
+    return GPBFieldTypeMap;
+  } else {
+    return GPBFieldTypeSingle;
+  }
+}
+
+- (GPBDataType)mapKeyDataType {
+  switch (description_->flags & GPBFieldMapKeyMask) {
+    case GPBFieldMapKeyInt32:
+      return GPBDataTypeInt32;
+    case GPBFieldMapKeyInt64:
+      return GPBDataTypeInt64;
+    case GPBFieldMapKeyUInt32:
+      return GPBDataTypeUInt32;
+    case GPBFieldMapKeyUInt64:
+      return GPBDataTypeUInt64;
+    case GPBFieldMapKeySInt32:
+      return GPBDataTypeSInt32;
+    case GPBFieldMapKeySInt64:
+      return GPBDataTypeSInt64;
+    case GPBFieldMapKeyFixed32:
+      return GPBDataTypeFixed32;
+    case GPBFieldMapKeyFixed64:
+      return GPBDataTypeFixed64;
+    case GPBFieldMapKeySFixed32:
+      return GPBDataTypeSFixed32;
+    case GPBFieldMapKeySFixed64:
+      return GPBDataTypeSFixed64;
+    case GPBFieldMapKeyBool:
+      return GPBDataTypeBool;
+    case GPBFieldMapKeyString:
+      return GPBDataTypeString;
+
+    default:
+      NSAssert(0, @"Not a map type");
+      return GPBDataTypeInt32;  // For lack of anything better.
+  }
+}
+
+- (BOOL)isPackable {
+  return (description_->flags & GPBFieldPacked) != 0;
+}
+
+- (BOOL)isValidEnumValue:(int32_t)value {
+  NSAssert(description_->dataType == GPBDataTypeEnum,
+           @"Field Must be of type GPBDataTypeEnum");
+  if (description_->flags & GPBFieldHasEnumDescriptor) {
+    return enumHandling_.enumDescriptor_.enumVerifier(value);
+  } else {
+    return enumHandling_.enumVerifier_(value);
+  }
+}
+
+- (GPBEnumDescriptor *)enumDescriptor {
+  if (description_->flags & GPBFieldHasEnumDescriptor) {
+    return enumHandling_.enumDescriptor_;
+  } else {
+    return nil;
+  }
+}
+
+- (GPBGenericValue)defaultValue {
+  // Depends on the fact that defaultValue_ is initialized either to "0/nil" or
+  // to an actual defaultValue in our initializer.
+  GPBGenericValue value = defaultValue_;
+
+  if (!(description_->flags & GPBFieldRepeated)) {
+    // We special handle data and strings. If they are nil, we replace them
+    // with empty string/empty data.
+    GPBDataType type = description_->dataType;
+    if (type == GPBDataTypeBytes && value.valueData == nil) {
+      value.valueData = GPBEmptyNSData();
+    } else if (type == GPBDataTypeString && value.valueString == nil) {
+      value.valueString = @"";
+    }
+  }
+  return value;
+}
+
+- (NSString *)textFormatName {
+  if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) {
+    NSValue *extraInfoValue =
+        objc_getAssociatedObject(self, &kTextFormatExtraValueKey);
+    // Support can be left out at generation time.
+    if (!extraInfoValue) {
+      return nil;
+    }
+    const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue];
+    return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self),
+                                   self.name);
+  }
+
+  // The logic here has to match SetCommonFieldVariables() from
+  // objectivec_field.cc in the proto compiler.
+  NSString *name = self.name;
+  NSUInteger len = [name length];
+
+  // Remove the "_p" added to reserved names.
+  if ([name hasSuffix:@"_p"]) {
+    name = [name substringToIndex:(len - 2)];
+    len = [name length];
+  }
+
+  // Remove "Array" from the end for repeated fields.
+  if (((description_->flags & GPBFieldRepeated) != 0) &&
+      [name hasSuffix:@"Array"]) {
+    name = [name substringToIndex:(len - 5)];
+    len = [name length];
+  }
+
+  // Groups vs. other fields.
+  if (description_->dataType == GPBDataTypeGroup) {
+    // Just capitalize the first letter.
+    unichar firstChar = [name characterAtIndex:0];
+    if (firstChar >= 'a' && firstChar <= 'z') {
+      NSString *firstCharString =
+          [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')];
+      NSString *result =
+          [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
+                                        withString:firstCharString];
+      return result;
+    }
+    return name;
+
+  } else {
+    // Undo the CamelCase.
+    NSMutableString *result = [NSMutableString stringWithCapacity:len];
+    for (uint32_t i = 0; i < len; i++) {
+      unichar c = [name characterAtIndex:i];
+      if (c >= 'A' && c <= 'Z') {
+        if (i > 0) {
+          [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')];
+        } else {
+          [result appendFormat:@"%C", c];
+        }
+      } else {
+        [result appendFormat:@"%C", c];
+      }
+    }
+    return result;
+  }
+}
+
+@end
+
+@implementation GPBEnumDescriptor {
+  NSString *name_;
+  // valueNames_ is a single c string with all of the value names appended
+  // together, each null terminated.  -calcValueNameOffsets fills in
+  // nameOffsets_ with the offsets to allow quicker access to the individual
+  // names.
+  const char *valueNames_;
+  const int32_t *values_;
+  GPBEnumValidationFunc enumVerifier_;
+  const uint8_t *extraTextFormatInfo_;
+  uint32_t *nameOffsets_;
+  uint32_t valueCount_;
+}
+
+@synthesize name = name_;
+@synthesize enumVerifier = enumVerifier_;
+
++ (instancetype)
+    allocDescriptorForName:(NSString *)name
+                valueNames:(const char *)valueNames
+                    values:(const int32_t *)values
+                     count:(uint32_t)valueCount
+              enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+  GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name
+                                                  valueNames:valueNames
+                                                      values:values
+                                                       count:valueCount
+                                                enumVerifier:enumVerifier];
+  return descriptor;
+}
+
++ (instancetype)
+    allocDescriptorForName:(NSString *)name
+                valueNames:(const char *)valueNames
+                    values:(const int32_t *)values
+                     count:(uint32_t)valueCount
+              enumVerifier:(GPBEnumValidationFunc)enumVerifier
+       extraTextFormatInfo:(const char *)extraTextFormatInfo {
+  // Call the common case.
+  GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name
+                                                    valueNames:valueNames
+                                                        values:values
+                                                         count:valueCount
+                                                  enumVerifier:enumVerifier];
+  // Set the extra info.
+  descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo;
+  return descriptor;
+}
+
+- (instancetype)initWithName:(NSString *)name
+                  valueNames:(const char *)valueNames
+                      values:(const int32_t *)values
+                       count:(uint32_t)valueCount
+                enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+  if ((self = [super init])) {
+    name_ = [name copy];
+    valueNames_ = valueNames;
+    values_ = values;
+    valueCount_ = valueCount;
+    enumVerifier_ = enumVerifier;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [name_ release];
+  if (nameOffsets_) free(nameOffsets_);
+  [super dealloc];
+}
+
+- (void)calcValueNameOffsets {
+  @synchronized(self) {
+    if (nameOffsets_ != NULL) {
+      return;
+    }
+    uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t));
+    const char *scan = valueNames_;
+    for (uint32_t i = 0; i < valueCount_; ++i) {
+      offsets[i] = (uint32_t)(scan - valueNames_);
+      while (*scan != '\0') ++scan;
+      ++scan;  // Step over the null.
+    }
+    nameOffsets_ = offsets;
+  }
+}
+
+- (NSString *)enumNameForValue:(int32_t)number {
+  if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+
+  for (uint32_t i = 0; i < valueCount_; ++i) {
+    if (values_[i] == number) {
+      const char *valueName = valueNames_ + nameOffsets_[i];
+      NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName];
+      return fullName;
+    }
+  }
+  return nil;
+}
+
+- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name {
+  // Must have the prefix.
+  NSUInteger prefixLen = name_.length + 1;
+  if ((name.length <= prefixLen) || ![name hasPrefix:name_] ||
+      ([name characterAtIndex:prefixLen - 1] != '_')) {
+    return NO;
+  }
+
+  // Skip over the prefix.
+  const char *nameAsCStr = [name UTF8String];
+  nameAsCStr += prefixLen;
+
+  if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+
+  // Find it.
+  for (uint32_t i = 0; i < valueCount_; ++i) {
+    const char *valueName = valueNames_ + nameOffsets_[i];
+    if (strcmp(nameAsCStr, valueName) == 0) {
+      if (outValue) {
+        *outValue = values_[i];
+      }
+      return YES;
+    }
+  }
+  return NO;
+}
+
+- (NSString *)textFormatNameForValue:(int32_t)number {
+  if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+
+  // Find the EnumValue descriptor and its index.
+  BOOL foundIt = NO;
+  uint32_t valueDescriptorIndex;
+  for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_;
+       ++valueDescriptorIndex) {
+    if (values_[valueDescriptorIndex] == number) {
+      foundIt = YES;
+      break;
+    }
+  }
+
+  if (!foundIt) {
+    return nil;
+  }
+
+  NSString *result = nil;
+  // Naming adds an underscore between enum name and value name, skip that also.
+  const char *valueName = valueNames_ + nameOffsets_[valueDescriptorIndex];
+  NSString *shortName = @(valueName);
+
+  // See if it is in the map of special format handling.
+  if (extraTextFormatInfo_) {
+    result = GPBDecodeTextFormatName(extraTextFormatInfo_,
+                                     (int32_t)valueDescriptorIndex, shortName);
+  }
+  // Logic here needs to match what objectivec_enum.cc does in the proto
+  // compiler.
+  if (result == nil) {
+    NSUInteger len = [shortName length];
+    NSMutableString *worker = [NSMutableString stringWithCapacity:len];
+    for (NSUInteger i = 0; i < len; i++) {
+      unichar c = [shortName characterAtIndex:i];
+      if (i > 0 && c >= 'A' && c <= 'Z') {
+        [worker appendString:@"_"];
+      }
+      [worker appendFormat:@"%c", toupper((char)c)];
+    }
+    result = worker;
+  }
+  return result;
+}
+
+@end
+
+@implementation GPBExtensionDescriptor {
+  GPBGenericValue defaultValue_;
+}
+
+@synthesize containingMessageClass = containingMessageClass_;
+
+- (instancetype)initWithExtensionDescription:
+        (GPBExtensionDescription *)description {
+  if ((self = [super init])) {
+    description_ = description;
+
+#if DEBUG
+    const char *className = description->messageOrGroupClassName;
+    if (className) {
+      NSAssert(objc_lookUpClass(className) != Nil,
+               @"Class %s not defined", className);
+    }
+#endif
+
+    if (description->extendedClass) {
+      Class containingClass = objc_lookUpClass(description->extendedClass);
+      NSAssert(containingClass, @"Class %s not defined",
+               description->extendedClass);
+      containingMessageClass_ = containingClass;
+    }
+
+    GPBDataType type = description_->dataType;
+    if (type == GPBDataTypeBytes) {
+      // Data stored as a length prefixed c-string in descriptor records.
+      const uint8_t *bytes =
+          (const uint8_t *)description->defaultValue.valueData;
+      if (bytes) {
+        uint32_t length = *((uint32_t *)bytes);
+        // The length is stored in network byte order.
+        length = ntohl(length);
+        bytes += sizeof(length);
+        defaultValue_.valueData =
+            [[NSData alloc] initWithBytes:bytes length:length];
+      }
+    } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) {
+      // The default is looked up in -defaultValue instead since extensions
+      // aren't common, we avoid the hit startup hit and it avoid initialization
+      // order issues.
+    } else {
+      defaultValue_ = description->defaultValue;
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if ((description_->dataType == GPBDataTypeBytes) &&
+      !GPBExtensionIsRepeated(description_)) {
+    [defaultValue_.valueData release];
+  }
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+#pragma unused(zone)
+  // Immutable.
+  return [self retain];
+}
+
+- (NSString *)singletonName {
+  return @(description_->singletonName);
+}
+
+- (const char *)singletonNameC {
+  return description_->singletonName;
+}
+
+- (uint32_t)fieldNumber {
+  return description_->fieldNumber;
+}
+
+- (GPBDataType)dataType {
+  return description_->dataType;
+}
+
+- (GPBWireFormat)wireType {
+  return GPBWireFormatForType(description_->dataType,
+                              GPBExtensionIsPacked(description_));
+}
+
+- (GPBWireFormat)alternateWireType {
+  NSAssert(GPBExtensionIsRepeated(description_),
+           @"Only valid on repeated extensions");
+  return GPBWireFormatForType(description_->dataType,
+                              !GPBExtensionIsPacked(description_));
+}
+
+- (BOOL)isRepeated {
+  return GPBExtensionIsRepeated(description_);
+}
+
+- (BOOL)isMap {
+  return (description_->options & GPBFieldMapKeyMask) != 0;
+}
+
+- (BOOL)isPackable {
+  return GPBExtensionIsPacked(description_);
+}
+
+- (Class)msgClass {
+  return objc_getClass(description_->messageOrGroupClassName);
+}
+
+- (GPBEnumDescriptor *)enumDescriptor {
+  if (description_->dataType == GPBDataTypeEnum) {
+    GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc();
+    return enumDescriptor;
+  }
+  return nil;
+}
+
+- (id)defaultValue {
+  if (GPBExtensionIsRepeated(description_)) {
+    return nil;
+  }
+
+  switch (description_->dataType) {
+    case GPBDataTypeBool:
+      return @(defaultValue_.valueBool);
+    case GPBDataTypeFloat:
+      return @(defaultValue_.valueFloat);
+    case GPBDataTypeDouble:
+      return @(defaultValue_.valueDouble);
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+    case GPBDataTypeEnum:
+    case GPBDataTypeSFixed32:
+      return @(defaultValue_.valueInt32);
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+    case GPBDataTypeSFixed64:
+      return @(defaultValue_.valueInt64);
+    case GPBDataTypeUInt32:
+    case GPBDataTypeFixed32:
+      return @(defaultValue_.valueUInt32);
+    case GPBDataTypeUInt64:
+    case GPBDataTypeFixed64:
+      return @(defaultValue_.valueUInt64);
+    case GPBDataTypeBytes:
+      // Like message fields, the default is zero length data.
+      return (defaultValue_.valueData ? defaultValue_.valueData
+                                      : GPBEmptyNSData());
+    case GPBDataTypeString:
+      // Like message fields, the default is zero length string.
+      return (defaultValue_.valueString ? defaultValue_.valueString : @"");
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
+      return nil;
+  }
+}
+
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other {
+  int32_t selfNumber = description_->fieldNumber;
+  int32_t otherNumber = other->description_->fieldNumber;
+  if (selfNumber < otherNumber) {
+    return NSOrderedAscending;
+  } else if (selfNumber == otherNumber) {
+    return NSOrderedSame;
+  } else {
+    return NSOrderedDescending;
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBDescriptor_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBDescriptor_PackagePrivate.h
new file mode 100644
index 0000000..e3d0a80
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDescriptor_PackagePrivate.h
@@ -0,0 +1,313 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBDescriptor.h"
+#import "GPBWireFormat.h"
+
+// Describes attributes of the field.
+typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
+  // These map to standard protobuf concepts.
+  GPBFieldRequired        = 1 << 0,
+  GPBFieldRepeated        = 1 << 1,
+  GPBFieldPacked          = 1 << 2,
+  GPBFieldOptional        = 1 << 3,
+  GPBFieldHasDefaultValue = 1 << 4,
+
+  // Indicates the field needs custom handling for the TextFormat name, if not
+  // set, the name can be derived from the ObjC name.
+  GPBFieldTextFormatNameCustom = 1 << 6,
+  // Indicates the field has an enum descriptor.
+  GPBFieldHasEnumDescriptor = 1 << 7,
+
+  // These are not standard protobuf concepts, they are specific to the
+  // Objective C runtime.
+
+  // These bits are used to mark the field as a map and what the key
+  // type is.
+  GPBFieldMapKeyMask     = 0xF << 8,
+  GPBFieldMapKeyInt32    =  1 << 8,
+  GPBFieldMapKeyInt64    =  2 << 8,
+  GPBFieldMapKeyUInt32   =  3 << 8,
+  GPBFieldMapKeyUInt64   =  4 << 8,
+  GPBFieldMapKeySInt32   =  5 << 8,
+  GPBFieldMapKeySInt64   =  6 << 8,
+  GPBFieldMapKeyFixed32  =  7 << 8,
+  GPBFieldMapKeyFixed64  =  8 << 8,
+  GPBFieldMapKeySFixed32 =  9 << 8,
+  GPBFieldMapKeySFixed64 = 10 << 8,
+  GPBFieldMapKeyBool     = 11 << 8,
+  GPBFieldMapKeyString   = 12 << 8,
+};
+
+// NOTE: The structures defined here have their members ordered to minimize
+// their size. This directly impacts the size of apps since these exist per
+// field/extension.
+
+// Describes a single field in a protobuf as it is represented as an ivar.
+typedef struct GPBMessageFieldDescription {
+  // Name of ivar.
+  const char *name;
+  union {
+    const char *className;  // Name for message class.
+    // For enums only: If EnumDescriptors are compiled in, it will be that,
+    // otherwise it will be the verifier.
+    GPBEnumDescriptorFunc enumDescFunc;
+    GPBEnumValidationFunc enumVerifier;
+  } dataTypeSpecific;
+  // The field number for the ivar.
+  uint32_t number;
+  // The index (in bits) into _has_storage_.
+  //   >= 0: the bit to use for a value being set.
+  //   = GPBNoHasBit(INT32_MAX): no storage used.
+  //   < 0: in a oneOf, use a full int32 to record the field active.
+  int32_t hasIndex;
+  // Offset of the variable into it's structure struct.
+  uint32_t offset;
+  // Field flags. Use accessor functions below.
+  GPBFieldFlags flags;
+  // Data type of the ivar.
+  GPBDataType dataType;
+} GPBMessageFieldDescription;
+
+// Fields in messages defined in a 'proto2' syntax file can provide a default
+// value. This struct provides the default along with the field info.
+typedef struct GPBMessageFieldDescriptionWithDefault {
+  // Default value for the ivar.
+  GPBGenericValue defaultValue;
+
+  GPBMessageFieldDescription core;
+} GPBMessageFieldDescriptionWithDefault;
+
+// Describes attributes of the extension.
+typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
+  // These map to standard protobuf concepts.
+  GPBExtensionRepeated      = 1 << 0,
+  GPBExtensionPacked        = 1 << 1,
+  GPBExtensionSetWireFormat = 1 << 2,
+};
+
+// An extension
+typedef struct GPBExtensionDescription {
+  GPBGenericValue defaultValue;
+  const char *singletonName;
+  const char *extendedClass;
+  const char *messageOrGroupClassName;
+  GPBEnumDescriptorFunc enumDescriptorFunc;
+  int32_t fieldNumber;
+  GPBDataType dataType;
+  GPBExtensionOptions options;
+} GPBExtensionDescription;
+
+typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
+  GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
+  GPBDescriptorInitializationFlag_WireFormat        = 1 << 1,
+};
+
+@interface GPBDescriptor () {
+ @package
+  NSArray *fields_;
+  NSArray *oneofs_;
+  uint32_t storageSize_;
+}
+
+// fieldDescriptions have to be long lived, they are held as raw pointers.
++ (instancetype)
+    allocDescriptorForClass:(Class)messageClass
+                  rootClass:(Class)rootClass
+                       file:(GPBFileDescriptor *)file
+                     fields:(void *)fieldDescriptions
+                 fieldCount:(uint32_t)fieldCount
+                storageSize:(uint32_t)storageSize
+                      flags:(GPBDescriptorInitializationFlags)flags;
+
+- (instancetype)initWithClass:(Class)messageClass
+                         file:(GPBFileDescriptor *)file
+                       fields:(NSArray *)fields
+                  storageSize:(uint32_t)storage
+                   wireFormat:(BOOL)wireFormat;
+
+// Called right after init to provide extra information to avoid init having
+// an explosion of args. These pointers are recorded, so they are expected
+// to live for the lifetime of the app.
+- (void)setupOneofs:(const char **)oneofNames
+              count:(uint32_t)count
+      firstHasIndex:(int32_t)firstHasIndex;
+- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
+- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
+
+@end
+
+@interface GPBFileDescriptor ()
+- (instancetype)initWithPackage:(NSString *)package
+                         syntax:(GPBFileSyntax)syntax;
+@end
+
+@interface GPBOneofDescriptor () {
+ @package
+  const char *name_;
+  NSArray *fields_;
+  SEL caseSel_;
+}
+// name must be long lived.
+- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields;
+@end
+
+@interface GPBFieldDescriptor () {
+ @package
+  GPBMessageFieldDescription *description_;
+  GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
+
+  SEL getSel_;
+  SEL setSel_;
+  SEL hasOrCountSel_;  // *Count for map<>/repeated fields, has* otherwise.
+  SEL setHasSel_;
+}
+
+// Single initializer
+// description has to be long lived, it is held as a raw pointer.
+- (instancetype)initWithFieldDescription:(void *)description
+                         includesDefault:(BOOL)includesDefault
+                                  syntax:(GPBFileSyntax)syntax;
+@end
+
+@interface GPBEnumDescriptor ()
+// valueNames, values and extraTextFormatInfo have to be long lived, they are
+// held as raw pointers.
++ (instancetype)
+    allocDescriptorForName:(NSString *)name
+                valueNames:(const char *)valueNames
+                    values:(const int32_t *)values
+                     count:(uint32_t)valueCount
+              enumVerifier:(GPBEnumValidationFunc)enumVerifier;
++ (instancetype)
+    allocDescriptorForName:(NSString *)name
+                valueNames:(const char *)valueNames
+                    values:(const int32_t *)values
+                     count:(uint32_t)valueCount
+              enumVerifier:(GPBEnumValidationFunc)enumVerifier
+       extraTextFormatInfo:(const char *)extraTextFormatInfo;
+
+- (instancetype)initWithName:(NSString *)name
+                  valueNames:(const char *)valueNames
+                      values:(const int32_t *)values
+                       count:(uint32_t)valueCount
+                enumVerifier:(GPBEnumValidationFunc)enumVerifier;
+@end
+
+@interface GPBExtensionDescriptor () {
+ @package
+  GPBExtensionDescription *description_;
+}
+@property(nonatomic, readonly) GPBWireFormat wireType;
+
+// For repeated extensions, alternateWireType is the wireType with the opposite
+// value for the packable property.  i.e. - if the extension was marked packed
+// it would be the wire type for unpacked; if the extension was marked unpacked,
+// it would be the wire type for packed.
+@property(nonatomic, readonly) GPBWireFormat alternateWireType;
+
+// description has to be long lived, it is held as a raw pointer.
+- (instancetype)initWithExtensionDescription:
+    (GPBExtensionDescription *)description;
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
+@end
+
+CF_EXTERN_C_BEGIN
+
+GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
+  return (field->description_->flags &
+          (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
+}
+
+GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
+  return field->description_->dataType;
+}
+
+GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
+  return field->description_->hasIndex;
+}
+
+GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) {
+  return field->description_->number;
+}
+
+uint32_t GPBFieldTag(GPBFieldDescriptor *self);
+
+// For repeated fields, alternateWireType is the wireType with the opposite
+// value for the packable property.  i.e. - if the field was marked packed it
+// would be the wire type for unpacked; if the field was marked unpacked, it
+// would be the wire type for packed.
+uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
+
+GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) {
+  return syntax != GPBFileSyntaxProto3;
+}
+
+GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
+  return syntax == GPBFileSyntaxProto3;
+}
+
+GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionRepeated) != 0;
+}
+
+GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionPacked) != 0;
+}
+
+GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) {
+  return (description->options & GPBExtensionSetWireFormat) != 0;
+}
+
+// Helper for compile time assets.
+#ifndef _GPBCompileAssert
+  #if __has_feature(c_static_assert) || __has_extension(c_static_assert)
+    #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg)
+  #else
+    // Pre-Xcode 7 support.
+    #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg
+    #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg)
+    #define _GPBCompileAssert(test, msg) \
+        typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
+  #endif  // __has_feature(c_static_assert) || __has_extension(c_static_assert)
+#endif // _GPBCompileAssert
+
+// Sanity check that there isn't padding between the field description
+// structures with and without a default.
+_GPBCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) ==
+                  (sizeof(GPBGenericValue) +
+                   sizeof(GPBMessageFieldDescription)),
+                  DescriptionsWithDefault_different_size_than_expected);
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBDictionary.h b/src/third_party/protobuf-3/objectivec/GPBDictionary.h
new file mode 100644
index 0000000..3120814
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDictionary.h
@@ -0,0 +1,2243 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBRuntimeTypes.h"
+
+// These classes are used for map fields of basic data types. They are used because
+// they perform better than boxing into NSNumbers in NSDictionaries.
+
+// Note: These are not meant to be subclassed.
+
+NS_ASSUME_NONNULL_BEGIN
+
+//%PDDM-EXPAND DECLARE_DICTIONARIES()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32 -> UInt32
+
+@interface GPBUInt32UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@interface GPBUInt32Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@interface GPBUInt32UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@interface GPBUInt32Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@interface GPBUInt32BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@interface GPBUInt32FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@interface GPBUInt32DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@interface GPBUInt32EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const uint32_t [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const uint32_t [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(uint32_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(uint32_t)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(uint32_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithObject:(ObjectType)object
+                              forKey:(uint32_t)key;
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                              forKeys:(const uint32_t [])keys
+                                count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                        forKeys:(const uint32_t [])keys
+                          count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (ObjectType)objectForKey:(uint32_t)key;
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(uint32_t key, ObjectType object, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary;
+
+- (void)setObject:(ObjectType)object forKey:(uint32_t)key;
+
+- (void)removeObjectForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> UInt32
+
+@interface GPBInt32UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@interface GPBInt32Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@interface GPBInt32UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@interface GPBInt32Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@interface GPBInt32BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@interface GPBInt32FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@interface GPBInt32DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@interface GPBInt32EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(int32_t)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const int32_t [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const int32_t [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(int32_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(int32_t)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(int32_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(int32_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithObject:(ObjectType)object
+                              forKey:(int32_t)key;
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                              forKeys:(const int32_t [])keys
+                                count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                        forKeys:(const int32_t [])keys
+                          count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (ObjectType)objectForKey:(int32_t)key;
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(int32_t key, ObjectType object, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary;
+
+- (void)setObject:(ObjectType)object forKey:(int32_t)key;
+
+- (void)removeObjectForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> UInt32
+
+@interface GPBUInt64UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@interface GPBUInt64Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@interface GPBUInt64UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@interface GPBUInt64Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@interface GPBUInt64BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@interface GPBUInt64FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@interface GPBUInt64DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@interface GPBUInt64EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const uint64_t [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const uint64_t [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(uint64_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(uint64_t)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(uint64_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithObject:(ObjectType)object
+                              forKey:(uint64_t)key;
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                              forKeys:(const uint64_t [])keys
+                                count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                        forKeys:(const uint64_t [])keys
+                          count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (ObjectType)objectForKey:(uint64_t)key;
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(uint64_t key, ObjectType object, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary;
+
+- (void)setObject:(ObjectType)object forKey:(uint64_t)key;
+
+- (void)removeObjectForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> UInt32
+
+@interface GPBInt64UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@interface GPBInt64Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@interface GPBInt64UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@interface GPBInt64Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@interface GPBInt64BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@interface GPBInt64FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@interface GPBInt64DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@interface GPBInt64EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(int64_t)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const int64_t [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const int64_t [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(int64_t)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(int64_t)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(int64_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(int64_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithObject:(ObjectType)object
+                              forKey:(int64_t)key;
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                              forKeys:(const int64_t [])keys
+                                count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                        forKeys:(const int64_t [])keys
+                          count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (ObjectType)objectForKey:(int64_t)key;
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(int64_t key, ObjectType object, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary;
+
+- (void)setObject:(ObjectType)object forKey:(int64_t)key;
+
+- (void)removeObjectForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> UInt32
+
+@interface GPBBoolUInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Int32
+
+@interface GPBBoolInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> UInt64
+
+@interface GPBBoolUInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Int64
+
+@interface GPBBoolInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Bool
+
+@interface GPBBoolBoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Float
+
+@interface GPBBoolFloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Double
+
+@interface GPBBoolDoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Enum
+
+@interface GPBBoolEnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(BOOL)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const BOOL [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const BOOL [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(BOOL)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(BOOL)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Object
+
+@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithObject:(ObjectType)object
+                              forKey:(BOOL)key;
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                              forKeys:(const BOOL [])keys
+                                count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
+                        forKeys:(const BOOL [])keys
+                          count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (ObjectType)objectForKey:(BOOL)key;
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(BOOL key, ObjectType object, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary;
+
+- (void)setObject:(ObjectType)object forKey:(BOOL)key;
+
+- (void)removeObjectForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> UInt32
+
+@interface GPBStringUInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Int32
+
+@interface GPBStringInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> UInt64
+
+@interface GPBStringUInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Int64
+
+@interface GPBStringInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Bool
+
+@interface GPBStringBoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Float
+
+@interface GPBStringFloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Double
+
+@interface GPBStringDoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                               count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                         count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Enum
+
+@interface GPBStringEnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(NSString *)key;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                                           count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])values
+                                   forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(NSString *)key value:(nullable int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(NSString *)key rawValue:(nullable int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(NSString *key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(NSString *)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+//%PDDM-EXPAND-END DECLARE_DICTIONARIES()
+
+NS_ASSUME_NONNULL_END
+
+//%PDDM-DEFINE DECLARE_DICTIONARIES()
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt32, uint32_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int32, int32_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt64, uint64_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int64, int64_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Bool, BOOL)
+//%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT)
+//%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
+//%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
+//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, ObjectType)
+//%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt64, uint64_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int64, int64_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Bool, BOOL)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Float, float)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Double, double)
+//%DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Enum, int32_t)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, POD, value)
+//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, , POD, VALUE_NAME, VALUE_TYPE, OBJECT, object)
+//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE)
+//%- (BOOL)valueForKey:(KEY_TYPE)key value:(nullable VALUE_TYPE *)value;
+//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_TYPE)
+//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key;
+//%PDDM-DEFINE VALUE_FOR_KEY_Enum(KEY_TYPE, VALUE_TYPE)
+//%VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE)
+//%PDDM-DEFINE ARRAY_ARG_MODIFIERPOD()
+// Nothing
+//%PDDM-DEFINE ARRAY_ARG_MODIFIEREnum()
+// Nothing
+//%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT()
+//%GPB_UNSAFE_UNRETAINED ##
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary<__covariant VALUE_TYPE>
+//%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%
+//%+ (instancetype)dictionary;
+//%+ (instancetype)dictionaryWith##VNAME$u##:(VALUE_TYPE)##VNAME
+//%                       ##VNAME$S## forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%+ (instancetype)dictionaryWith##VNAME$u##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])##VNAME##s
+//%                      ##VNAME$S##  forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//%                      ##VNAME$S##    count:(NSUInteger)count;
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+//%
+//%- (instancetype)initWith##VNAME$u##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])##VNAME##s
+//%                ##VNAME$S##  forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//%                ##VNAME$S##    count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems;
+//%
+//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
+//%
+//%- (void)addEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
+//%
+//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, Enum)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+//%
+//%+ (instancetype)dictionary;
+//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                        rawValue:(VALUE_TYPE)rawValue
+//%                                          forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                       rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//%                                         forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//%                                           count:(NSUInteger)count;
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                        capacity:(NSUInteger)numItems;
+//%
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                 rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//%                                   forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//%                                     count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
+//%                                  capacity:(NSUInteger)numItems;
+//%
+//%// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+//%// is not a valid enumerator as defined by validationFunc. If the actual value is
+//%// desired, use "raw" version of the method.
+//%
+//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, value)
+//%
+//%// These methods bypass the validationFunc to provide access to values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key rawValue:(nullable VALUE_TYPE *)rawValue;
+//%
+//%- (void)enumerateKeysAndRawValuesUsingBlock:
+//%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block;
+//%
+//%- (void)addRawEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
+//%
+//%// If value is not a valid enumerator as defined by validationFunc, these
+//%// methods will assert in debug, and will log in release and assign the value
+//%// to the default value. Use the rawValue methods below to assign non enumerator
+//%// values.
+//%
+//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, value)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
+//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_TYPE)
+//%
+//%- (void)enumerateKeysAnd##VNAME$u##sUsingBlock:
+//%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME, BOOL *stop))block;
+
+//%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
+//%- (void)set##VNAME$u##:(VALUE_TYPE)##VNAME forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%DICTIONARY_EXTRA_MUTABLE_METHODS_##VHELPER(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+//%- (void)remove##VNAME$u##ForKey:(KEY_TYPE##KisP$S##KisP)aKey;
+//%- (void)removeAll;
+
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_POD(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+// Empty
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_OBJECT(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+// Empty
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_Enum(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+//%
+//%// This method bypass the validationFunc to provide setting of values that were not
+//%// known at the time the binary was compiled.
+//%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%
+//%// No validation applies to these methods.
+//%
diff --git a/src/third_party/protobuf-3/objectivec/GPBDictionary.m b/src/third_party/protobuf-3/objectivec/GPBDictionary.m
new file mode 100644
index 0000000..3bd146e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDictionary.m
@@ -0,0 +1,13555 @@
+// 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.
+
+#import "GPBDictionary_PackagePrivate.h"
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+// ------------------------------ NOTE ------------------------------
+// At the moment, this is all using NSNumbers in NSDictionaries under
+// the hood, but it is all hidden so we can come back and optimize
+// with direct CFDictionary usage later.  The reason that wasn't
+// done yet is needing to support 32bit iOS builds.  Otherwise
+// it would be pretty simple to store all this data in CFDictionaries
+// directly.
+// ------------------------------------------------------------------
+
+// Used to include code only visible to specific versions of the static
+// analyzer. Useful for wrapping code that only exists to silence the analyzer.
+// Determine the values you want to use for BEGIN_APPLE_BUILD_VERSION,
+// END_APPLE_BUILD_VERSION using:
+//   xcrun clang -dM -E -x c /dev/null | grep __apple_build_version__
+// Example usage:
+//  #if GPB_STATIC_ANALYZER_ONLY(5621, 5623) ... #endif
+#define GPB_STATIC_ANALYZER_ONLY(BEGIN_APPLE_BUILD_VERSION, END_APPLE_BUILD_VERSION) \
+    (defined(__clang_analyzer__) && \
+     (__apple_build_version__ >= BEGIN_APPLE_BUILD_VERSION && \
+      __apple_build_version__ <= END_APPLE_BUILD_VERSION))
+
+enum {
+  kMapKeyFieldNumber = 1,
+  kMapValueFieldNumber = 2,
+};
+
+static BOOL DictDefault_IsValidValue(int32_t value) {
+  // Anything but the bad value marker is allowed.
+  return (value != kGPBUnrecognizedEnumeratorValue);
+}
+
+//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2)
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value);
+//%  } else {
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
+//%    return 0;
+//%  }
+//%}
+//%
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    [stream write##GPBDATATYPE_NAME1##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    [stream write##GPBDATATYPE_NAME2##:fieldNum value:value];
+//%  } else {
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
+//%  }
+//%}
+//%
+//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3)
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value);
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) {
+//%    return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value);
+//%  } else {
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
+//%    return 0;
+//%  }
+//%}
+//%
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
+//%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
+//%    [stream write##GPBDATATYPE_NAME1##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) {
+//%    [stream write##GPBDATATYPE_NAME2##:fieldNum value:value];
+//%  } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) {
+//%    [stream write##GPBDATATYPE_NAME3##:fieldNum value:value];
+//%  } else {
+//%    NSCAssert(NO, @"Unexpected type %d", dataType);
+//%  }
+//%}
+//%
+//%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP)
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
+//%  #pragma unused(dataType)  // For when asserts are off in release.
+//%  return GPBCompute##VALUE_NAME##Size(fieldNum, value);
+//%}
+//%
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
+//%  #pragma unused(dataType)  // For when asserts are off in release.
+//%  [stream write##VALUE_NAME##:fieldNum value:value];
+//%}
+//%
+//%PDDM-DEFINE SERIALIZE_SUPPORT_HELPERS()
+//%SERIALIZE_SUPPORT_3_TYPE(Int32, int32_t, Int32, SInt32, SFixed32)
+//%SERIALIZE_SUPPORT_2_TYPE(UInt32, uint32_t, UInt32, Fixed32)
+//%SERIALIZE_SUPPORT_3_TYPE(Int64, int64_t, Int64, SInt64, SFixed64)
+//%SERIALIZE_SUPPORT_2_TYPE(UInt64, uint64_t, UInt64, Fixed64)
+//%SIMPLE_SERIALIZE_SUPPORT(Bool, BOOL, )
+//%SIMPLE_SERIALIZE_SUPPORT(Enum, int32_t, )
+//%SIMPLE_SERIALIZE_SUPPORT(Float, float, )
+//%SIMPLE_SERIALIZE_SUPPORT(Double, double, )
+//%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *)
+//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes)
+//%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS()
+// This block of code is generated, do not edit it directly.
+
+static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt32) {
+    return GPBComputeInt32Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeSInt32) {
+    return GPBComputeSInt32Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeSFixed32) {
+    return GPBComputeSFixed32Size(fieldNum, value);
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+    return 0;
+  }
+}
+
+static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt32) {
+    [stream writeInt32:fieldNum value:value];
+  } else if (dataType == GPBDataTypeSInt32) {
+    [stream writeSInt32:fieldNum value:value];
+  } else if (dataType == GPBDataTypeSFixed32) {
+    [stream writeSFixed32:fieldNum value:value];
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+  }
+}
+
+static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt32) {
+    return GPBComputeUInt32Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeFixed32) {
+    return GPBComputeFixed32Size(fieldNum, value);
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+    return 0;
+  }
+}
+
+static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt32) {
+    [stream writeUInt32:fieldNum value:value];
+  } else if (dataType == GPBDataTypeFixed32) {
+    [stream writeFixed32:fieldNum value:value];
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+  }
+}
+
+static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt64) {
+    return GPBComputeInt64Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeSInt64) {
+    return GPBComputeSInt64Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeSFixed64) {
+    return GPBComputeSFixed64Size(fieldNum, value);
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+    return 0;
+  }
+}
+
+static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeInt64) {
+    [stream writeInt64:fieldNum value:value];
+  } else if (dataType == GPBDataTypeSInt64) {
+    [stream writeSInt64:fieldNum value:value];
+  } else if (dataType == GPBDataTypeSFixed64) {
+    [stream writeSFixed64:fieldNum value:value];
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+  }
+}
+
+static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt64) {
+    return GPBComputeUInt64Size(fieldNum, value);
+  } else if (dataType == GPBDataTypeFixed64) {
+    return GPBComputeFixed64Size(fieldNum, value);
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+    return 0;
+  }
+}
+
+static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeUInt64) {
+    [stream writeUInt64:fieldNum value:value];
+  } else if (dataType == GPBDataTypeFixed64) {
+    [stream writeFixed64:fieldNum value:value];
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+  }
+}
+
+static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  return GPBComputeBoolSize(fieldNum, value);
+}
+
+static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  [stream writeBool:fieldNum value:value];
+}
+
+static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  return GPBComputeEnumSize(fieldNum, value);
+}
+
+static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  [stream writeEnum:fieldNum value:value];
+}
+
+static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  return GPBComputeFloatSize(fieldNum, value);
+}
+
+static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  [stream writeFloat:fieldNum value:value];
+}
+
+static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  return GPBComputeDoubleSize(fieldNum, value);
+}
+
+static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  [stream writeDouble:fieldNum value:value];
+}
+
+static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  return GPBComputeStringSize(fieldNum, value);
+}
+
+static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+  NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
+  #pragma unused(dataType)  // For when asserts are off in release.
+  [stream writeString:fieldNum value:value];
+}
+
+static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeMessage) {
+    return GPBComputeMessageSize(fieldNum, value);
+  } else if (dataType == GPBDataTypeString) {
+    return GPBComputeStringSize(fieldNum, value);
+  } else if (dataType == GPBDataTypeBytes) {
+    return GPBComputeBytesSize(fieldNum, value);
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+    return 0;
+  }
+}
+
+static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) {
+  if (dataType == GPBDataTypeMessage) {
+    [stream writeMessage:fieldNum value:value];
+  } else if (dataType == GPBDataTypeString) {
+    [stream writeString:fieldNum value:value];
+  } else if (dataType == GPBDataTypeBytes) {
+    [stream writeBytes:fieldNum value:value];
+  } else {
+    NSCAssert(NO, @"Unexpected type %d", dataType);
+  }
+}
+
+//%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS()
+
+size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
+  GPBDataType mapValueType = GPBGetFieldDataType(field);
+  __block size_t result = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key);
+    msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * dict.count;
+  return result;
+}
+
+void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream,
+                                              NSDictionary *dict,
+                                              GPBFieldDescriptor *field) {
+  NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
+  GPBDataType mapValueType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key);
+    msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
+
+    // Write the size and fields.
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    [outputStream writeString:kMapKeyFieldNumber value:key];
+    WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType);
+  }];
+}
+
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
+  NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
+  NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type");
+  #pragma unused(field)  // For when asserts are off in release.
+  for (GPBMessage *msg in [dict objectEnumerator]) {
+    if (!msg.initialized) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+// Note: if the type is an object, it the retain pass back to the caller.
+static void ReadValue(GPBCodedInputStream *stream,
+                      GPBGenericValue *valueToFill,
+                      GPBDataType type,
+                      GPBExtensionRegistry *registry,
+                      GPBFieldDescriptor *field) {
+  switch (type) {
+    case GPBDataTypeBool:
+      valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_);
+      break;
+    case GPBDataTypeFixed32:
+      valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_);
+      break;
+    case GPBDataTypeSFixed32:
+      valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_);
+      break;
+    case GPBDataTypeFloat:
+      valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_);
+      break;
+    case GPBDataTypeFixed64:
+      valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_);
+      break;
+    case GPBDataTypeSFixed64:
+      valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_);
+      break;
+    case GPBDataTypeDouble:
+      valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_);
+      break;
+    case GPBDataTypeInt32:
+      valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_);
+      break;
+    case GPBDataTypeInt64:
+      valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_);
+      break;
+    case GPBDataTypeSInt32:
+      valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_);
+      break;
+    case GPBDataTypeSInt64:
+      valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_);
+      break;
+    case GPBDataTypeUInt32:
+      valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_);
+      break;
+    case GPBDataTypeUInt64:
+      valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_);
+      break;
+    case GPBDataTypeBytes:
+      [valueToFill->valueData release];
+      valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_);
+      break;
+    case GPBDataTypeString:
+      [valueToFill->valueString release];
+      valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_);
+      break;
+    case GPBDataTypeMessage: {
+      GPBMessage *message = [[field.msgClass alloc] init];
+      [stream readMessage:message extensionRegistry:registry];
+      [valueToFill->valueMessage release];
+      valueToFill->valueMessage = message;
+      break;
+    }
+    case GPBDataTypeGroup:
+      NSCAssert(NO, @"Can't happen");
+      break;
+    case GPBDataTypeEnum:
+      valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_);
+      break;
+  }
+}
+
+void GPBDictionaryReadEntry(id mapDictionary,
+                            GPBCodedInputStream *stream,
+                            GPBExtensionRegistry *registry,
+                            GPBFieldDescriptor *field,
+                            GPBMessage *parentMessage) {
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+
+  GPBGenericValue key;
+  GPBGenericValue value;
+  // Zero them (but pick up any enum default for proto2).
+  key.valueString = value.valueString = nil;
+  if (valueDataType == GPBDataTypeEnum) {
+    value = field.defaultValue;
+  }
+
+  GPBCodedInputStreamState *state = &stream->state_;
+  uint32_t keyTag =
+      GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO));
+  uint32_t valueTag =
+      GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO));
+
+  BOOL hitError = NO;
+  while (YES) {
+    uint32_t tag = GPBCodedInputStreamReadTag(state);
+    if (tag == keyTag) {
+      ReadValue(stream, &key, keyDataType, registry, field);
+    } else if (tag == valueTag) {
+      ReadValue(stream, &value, valueDataType, registry, field);
+    } else if (tag == 0) {
+      // zero signals EOF / limit reached
+      break;
+    } else {  // Unknown
+      if (![stream skipField:tag]){
+        hitError = YES;
+        break;
+      }
+    }
+  }
+
+  if (!hitError) {
+    // Handle the special defaults and/or missing key/value.
+    if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) {
+      key.valueString = [@"" retain];
+    }
+    if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) {
+      switch (valueDataType) {
+        case GPBDataTypeString:
+          value.valueString = [@"" retain];
+          break;
+        case GPBDataTypeBytes:
+          value.valueData = [GPBEmptyNSData() retain];
+          break;
+#if defined(__clang_analyzer__)
+        case GPBDataTypeGroup:
+          // Maps can't really have Groups as the value type, but this case is needed
+          // so the analyzer won't report the posibility of send nil in for the value
+          // in the NSMutableDictionary case below.
+#endif
+        case GPBDataTypeMessage: {
+          value.valueMessage = [[field.msgClass alloc] init];
+          break;
+        }
+        default:
+          // Nothing
+          break;
+      }
+    }
+
+    if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
+#if GPB_STATIC_ANALYZER_ONLY(6020053, 7000181)
+     // Limited to Xcode 6.4 - 7.2, are known to fail here. The upper end can
+     // be raised as needed for new Xcodes.
+     //
+     // This is only needed on a "shallow" analyze; on a "deep" analyze, the
+     // existing code path gets this correct. In shallow, the analyzer decides
+     // GPBDataTypeIsObject(valueDataType) is both false and true on a single
+     // path through this function, allowing nil to be used for the
+     // setObject:forKey:.
+     if (value.valueString == nil) {
+       value.valueString = [@"" retain];
+     }
+#endif
+      // mapDictionary is an NSMutableDictionary
+      [(NSMutableDictionary *)mapDictionary setObject:value.valueString
+                                               forKey:key.valueString];
+    } else {
+      if (valueDataType == GPBDataTypeEnum) {
+        if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) ||
+            [field isValidEnumValue:value.valueEnum]) {
+          [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key];
+        } else {
+          NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum
+                                                               forKey:&key
+                                                          keyDataType:keyDataType];
+          [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data];
+        }
+      } else {
+        [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key];
+      }
+    }
+  }
+
+  if (GPBDataTypeIsObject(keyDataType)) {
+    [key.valueString release];
+  }
+  if (GPBDataTypeIsObject(valueDataType)) {
+    [value.valueString release];
+  }
+}
+
+//
+// Macros for the common basic cases.
+//
+
+//%PDDM-DEFINE DICTIONARY_IMPL_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
+//%DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
+//%DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, Object, id)
+
+//%PDDM-DEFINE DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt32, uint32_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int32, int32_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt64, uint64_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int64, int64_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Bool, BOOL, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Float, float, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Double, double, KHELPER)
+//%DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, Enum, int32_t, KHELPER)
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD, value)
+
+//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, , VALUE_NAME, VALUE_TYPE, POD, OBJECT, object)
+
+//%PDDM-DEFINE DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary {
+//% @package
+//%  NSMutableDictionary *_dictionary;
+//%}
+//%
+//%+ (instancetype)dictionary {
+//%  return [[[self alloc] initWith##VNAME$u##s:NULL forKeys:NULL count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWith##VNAME$u##:(VALUE_TYPE)##VNAME
+//%                      ##VNAME$S##  forKey:(KEY_TYPE##KisP$S##KisP)key {
+//%  // Cast is needed so the compiler knows what class we are invoking initWith##VNAME$u##s:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME$u##s:&##VNAME
+//%               KEY_NAME$S VALUE_NAME$S                        ##VNAME$S##  forKeys:&key
+//%               KEY_NAME$S VALUE_NAME$S                        ##VNAME$S##    count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWith##VNAME$u##s:(const VALUE_TYPE [])##VNAME##s
+//%                      ##VNAME$S##  forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                      ##VNAME$S##    count:(NSUInteger)count {
+//%  // Cast is needed so the compiler knows what class we are invoking initWith##VNAME$u##s:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME$u##s:##VNAME##s
+//%               KEY_NAME$S VALUE_NAME$S                               forKeys:keys
+//%               KEY_NAME$S VALUE_NAME$S                                 count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+//%  return [[[self alloc] initWithCapacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//%  return [self initWith##VNAME$u##s:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWith##VNAME$u##s:(const VALUE_TYPE [])##VNAME##s
+//%                ##VNAME$S##  forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                ##VNAME$S##    count:(NSUInteger)count {
+//%  self = [super init];
+//%  if (self) {
+//%    _dictionary = [[NSMutableDictionary alloc] init];
+//%    if (count && VNAME##s && keys) {
+//%      for (NSUInteger i = 0; i < count; ++i) {
+//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME##s[i], ______)##DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______)        [_dictionary setObject:WRAPPED##VHELPER(VNAME##s[i]) forKey:WRAPPED##KHELPER(keys[i])];
+//%      }
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//%  self = [self initWith##VNAME$u##s:NULL forKeys:NULL count:0];
+//%  if (self) {
+//%    if (dictionary) {
+//%      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
+//%  #pragma unused(numItems)
+//%  return [self initWith##VNAME$u##s:NULL forKeys:NULL count:0];
+//%}
+//%
+//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, )
+//%
+//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%
+//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, )
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary {
+//% @package
+//%  NSMutableDictionary *_dictionary;
+//%  GPBEnumValidationFunc _validationFunc;
+//%}
+//%
+//%@synthesize validationFunc = _validationFunc;
+//%
+//%+ (instancetype)dictionary {
+//%  return [[[self alloc] initWithValidationFunction:NULL
+//%                                         rawValues:NULL
+//%                                           forKeys:NULL
+//%                                             count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+//%  return [[[self alloc] initWithValidationFunction:func
+//%                                         rawValues:NULL
+//%                                           forKeys:NULL
+//%                                             count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//%                                        rawValue:(VALUE_TYPE)rawValue
+//%                                          forKey:(KEY_TYPE##KisP$S##KisP)key {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func
+//%               KEY_NAME$S VALUE_NAME$S                                         rawValues:&rawValue
+//%               KEY_NAME$S VALUE_NAME$S                                           forKeys:&key
+//%               KEY_NAME$S VALUE_NAME$S                                             count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//%                                       rawValues:(const VALUE_TYPE [])rawValues
+//%                                         forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                                           count:(NSUInteger)count {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func
+//%               KEY_NAME$S VALUE_NAME$S                                         rawValues:rawValues
+//%               KEY_NAME$S VALUE_NAME$S                                           forKeys:keys
+//%               KEY_NAME$S VALUE_NAME$S                                             count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//%                                        capacity:(NSUInteger)numItems {
+//%  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//%  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+//%  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//%                                 rawValues:(const VALUE_TYPE [])rawValues
+//%                                   forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                                     count:(NSUInteger)count {
+//%  self = [super init];
+//%  if (self) {
+//%    _dictionary = [[NSMutableDictionary alloc] init];
+//%    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+//%    if (count && rawValues && keys) {
+//%      for (NSUInteger i = 0; i < count; ++i) {
+//%DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______)        [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])];
+//%      }
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//%  self = [self initWithValidationFunction:dictionary.validationFunc
+//%                                rawValues:NULL
+//%                                  forKeys:NULL
+//%                                    count:0];
+//%  if (self) {
+//%    if (dictionary) {
+//%      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//%                                  capacity:(NSUInteger)numItems {
+//%  #pragma unused(numItems)
+//%  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, value, Raw)
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key value:(VALUE_TYPE *)value {
+//%  NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//%  if (wrapped && value) {
+//%    VALUE_TYPE result = UNWRAP##VALUE_NAME(wrapped);
+//%    if (!_validationFunc(result)) {
+//%      result = kGPBUnrecognizedEnumeratorValue;
+//%    }
+//%    *value = result;
+//%  }
+//%  return (wrapped != NULL);
+//%}
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key rawValue:(VALUE_TYPE *)rawValue {
+//%  NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//%  if (wrapped && rawValue) {
+//%    *rawValue = UNWRAP##VALUE_NAME(wrapped);
+//%  }
+//%  return (wrapped != NULL);
+//%}
+//%
+//%- (void)enumerateKeysAndValuesUsingBlock:
+//%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block {
+//%  GPBEnumValidationFunc func = _validationFunc;
+//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
+//%                                                   BOOL *stop) {
+//%      VALUE_TYPE unwrapped = UNWRAP##VALUE_NAME(aValue);
+//%      if (!func(unwrapped)) {
+//%        unwrapped = kGPBUnrecognizedEnumeratorValue;
+//%      }
+//%      block(UNWRAP##KEY_NAME(aKey), unwrapped, stop);
+//%  }];
+//%}
+//%
+//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, value, Raw)
+//%
+//%- (void)setValue:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//%DICTIONARY_VALIDATE_KEY_##KHELPER(key, )  if (!_validationFunc(value)) {
+//%    [NSException raise:NSInvalidArgumentException
+//%                format:@"GPB##KEY_NAME##VALUE_NAME##Dictionary: Attempt to set an unknown enum value (%d)",
+//%                       value];
+//%  }
+//%
+//%  [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)];
+//%  if (_autocreator) {
+//%    GPBAutocreatedDictionaryModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, ACCESSOR_NAME)
+//%- (void)dealloc {
+//%  NSAssert(!_autocreator,
+//%           @"%@: Autocreator must be cleared before release, autocreator: %@",
+//%           [self class], _autocreator);
+//%  [_dictionary release];
+//%  [super dealloc];
+//%}
+//%
+//%- (instancetype)copyWithZone:(NSZone *)zone {
+//%  return [[GPB##KEY_NAME##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self];
+//%}
+//%
+//%- (BOOL)isEqual:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)other {
+//%  if (self == other) {
+//%    return YES;
+//%  }
+//%  if (![other isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]) {
+//%    return NO;
+//%  }
+//%  return [_dictionary isEqual:other->_dictionary];
+//%}
+//%
+//%- (NSUInteger)hash {
+//%  return _dictionary.count;
+//%}
+//%
+//%- (NSString *)description {
+//%  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+//%}
+//%
+//%- (NSUInteger)count {
+//%  return _dictionary.count;
+//%}
+//%
+//%- (void)enumerateKeysAnd##ACCESSOR_NAME##VNAME$u##sUsingBlock:
+//%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME, BOOL *stop))block {
+//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME$u,
+//%                                                   BOOL *stop) {
+//%      block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(a##VNAME$u), stop);
+//%  }];
+//%}
+//%
+//%EXTRA_METHODS_##VHELPER(KEY_NAME, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+//%  NSUInteger count = _dictionary.count;
+//%  if (count == 0) {
+//%    return 0;
+//%  }
+//%
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  GPBDataType keyDataType = field.mapKeyDataType;
+//%  __block size_t result = 0;
+//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME$u##,
+//%                                                   BOOL *stop) {
+//%    #pragma unused(stop)
+//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME$u), kMapValueFieldNumber, valueDataType);
+//%    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+//%  }];
+//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+//%  result += tagSize * count;
+//%  return result;
+//%}
+//%
+//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+//%                         asField:(GPBFieldDescriptor *)field {
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  GPBDataType keyDataType = field.mapKeyDataType;
+//%  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME$u,
+//%                                                   BOOL *stop) {
+//%    #pragma unused(stop)
+//%    // Write the tag.
+//%    [outputStream writeInt32NoTag:tag];
+//%    // Write the size of the message.
+//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME$u), kMapValueFieldNumber, valueDataType);
+//%    [outputStream writeInt32NoTag:(int32_t)msgSize];
+//%    // Write the fields.
+//%    WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
+//%    WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(a##VNAME$u), kMapValueFieldNumber, valueDataType);
+//%  }];
+//%}
+//%
+//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
+//%  [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)];
+//%}
+//%
+//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+//%  [self enumerateKeysAnd##ACCESSOR_NAME##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME, BOOL *stop) {
+//%      #pragma unused(stop)
+//%      block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(VNAME));
+//%  }];
+//%}
+//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, VNAME, ACCESSOR_NAME)
+//%- (void)add##ACCESSOR_NAME##EntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary {
+//%  if (otherDictionary) {
+//%    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+//%    if (_autocreator) {
+//%      GPBAutocreatedDictionaryModified(_autocreator, self);
+//%    }
+//%  }
+//%}
+//%
+//%- (void)set##ACCESSOR_NAME##VNAME$u##:(VALUE_TYPE)VNAME forKey:(KEY_TYPE##KisP$S##KisP)key {
+//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME, )##DICTIONARY_VALIDATE_KEY_##KHELPER(key, )  [_dictionary setObject:WRAPPED##VHELPER(VNAME) forKey:WRAPPED##KHELPER(key)];
+//%  if (_autocreator) {
+//%    GPBAutocreatedDictionaryModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%- (void)remove##VNAME$u##ForKey:(KEY_TYPE##KisP$S##KisP)aKey {
+//%  [_dictionary removeObjectForKey:WRAPPED##KHELPER(aKey)];
+//%}
+//%
+//%- (void)removeAll {
+//%  [_dictionary removeAllObjects];
+//%}
+
+//
+// Custom Generation for Bool keys
+//
+
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_POD_IMPL(VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, POD, value)
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, OBJECT, object)
+
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, HELPER, VNAME)
+//%#pragma mark - Bool -> VALUE_NAME
+//%
+//%@implementation GPBBool##VALUE_NAME##Dictionary {
+//% @package
+//%  VALUE_TYPE _values[2];
+//%BOOL_DICT_HAS_STORAGE_##HELPER()}
+//%
+//%+ (instancetype)dictionary {
+//%  return [[[self alloc] initWith##VNAME$u##s:NULL forKeys:NULL count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWith##VNAME$u##:(VALUE_TYPE)VNAME
+//%                      ##VNAME$S##  forKey:(BOOL)key {
+//%  // Cast is needed so the compiler knows what class we are invoking initWith##VNAME$u##s:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME$u##s:&##VNAME
+//%                    VALUE_NAME$S                        ##VNAME$S##  forKeys:&key
+//%                    VALUE_NAME$S                        ##VNAME$S##    count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWith##VNAME$u##s:(const VALUE_TYPE [])##VNAME##s
+//%                      ##VNAME$S##  forKeys:(const BOOL [])keys
+//%                      ##VNAME$S##    count:(NSUInteger)count {
+//%  // Cast is needed so the compiler knows what class we are invoking initWith##VNAME$u##s:forKeys:count:
+//%  // on to get the type correct.
+//%  return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME$u##s:##VNAME##s
+//%                    VALUE_NAME$S                        ##VNAME$S##  forKeys:keys
+//%                    VALUE_NAME$S                        ##VNAME$S##    count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//%  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+//%  // on to get the type correct.
+//%  return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+//%  return [[[self alloc] initWithCapacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//%  return [self initWith##VNAME$u##s:NULL forKeys:NULL count:0];
+//%}
+//%
+//%BOOL_DICT_INITS_##HELPER(VALUE_NAME, VALUE_TYPE)
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
+//%  #pragma unused(numItems)
+//%  return [self initWith##VNAME$u##s:NULL forKeys:NULL count:0];
+//%}
+//%
+//%BOOL_DICT_DEALLOC##HELPER()
+//%
+//%- (instancetype)copyWithZone:(NSZone *)zone {
+//%  return [[GPBBool##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self];
+//%}
+//%
+//%- (BOOL)isEqual:(GPBBool##VALUE_NAME##Dictionary *)other {
+//%  if (self == other) {
+//%    return YES;
+//%  }
+//%  if (![other isKindOfClass:[GPBBool##VALUE_NAME##Dictionary class]]) {
+//%    return NO;
+//%  }
+//%  if ((BOOL_DICT_W_HAS##HELPER(0, ) != BOOL_DICT_W_HAS##HELPER(0, other->)) ||
+//%      (BOOL_DICT_W_HAS##HELPER(1, ) != BOOL_DICT_W_HAS##HELPER(1, other->))) {
+//%    return NO;
+//%  }
+//%  if ((BOOL_DICT_W_HAS##HELPER(0, ) && (NEQ_##HELPER(_values[0], other->_values[0]))) ||
+//%      (BOOL_DICT_W_HAS##HELPER(1, ) && (NEQ_##HELPER(_values[1], other->_values[1])))) {
+//%    return NO;
+//%  }
+//%  return YES;
+//%}
+//%
+//%- (NSUInteger)hash {
+//%  return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0);
+//%}
+//%
+//%- (NSString *)description {
+//%  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+//%  if (BOOL_DICT_W_HAS##HELPER(0, )) {
+//%    [result appendFormat:@"NO: STR_FORMAT_##HELPER(VALUE_NAME)", _values[0]];
+//%  }
+//%  if (BOOL_DICT_W_HAS##HELPER(1, )) {
+//%    [result appendFormat:@"YES: STR_FORMAT_##HELPER(VALUE_NAME)", _values[1]];
+//%  }
+//%  [result appendString:@" }"];
+//%  return result;
+//%}
+//%
+//%- (NSUInteger)count {
+//%  return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0);
+//%}
+//%
+//%BOOL_VALUE_FOR_KEY_##HELPER(VALUE_TYPE)
+//%
+//%BOOL_SET_GPBVALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE, VisP)
+//%
+//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+//%  if (BOOL_DICT_HAS##HELPER(0, )) {
+//%    block(@"false", TEXT_FORMAT_OBJ##VALUE_NAME(_values[0]));
+//%  }
+//%  if (BOOL_DICT_W_HAS##HELPER(1, )) {
+//%    block(@"true", TEXT_FORMAT_OBJ##VALUE_NAME(_values[1]));
+//%  }
+//%}
+//%
+//%- (void)enumerateKeysAnd##VNAME$u##sUsingBlock:
+//%    (void (^)(BOOL key, VALUE_TYPE VNAME, BOOL *stop))block {
+//%  BOOL stop = NO;
+//%  if (BOOL_DICT_HAS##HELPER(0, )) {
+//%    block(NO, _values[0], &stop);
+//%  }
+//%  if (!stop && BOOL_DICT_W_HAS##HELPER(1, )) {
+//%    block(YES, _values[1], &stop);
+//%  }
+//%}
+//%
+//%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  NSUInteger count = 0;
+//%  size_t result = 0;
+//%  for (int i = 0; i < 2; ++i) {
+//%    if (BOOL_DICT_HAS##HELPER(i, )) {
+//%      ++count;
+//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+//%      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+//%    }
+//%  }
+//%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+//%  result += tagSize * count;
+//%  return result;
+//%}
+//%
+//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+//%                         asField:(GPBFieldDescriptor *)field {
+//%  GPBDataType valueDataType = GPBGetFieldDataType(field);
+//%  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+//%  for (int i = 0; i < 2; ++i) {
+//%    if (BOOL_DICT_HAS##HELPER(i, )) {
+//%      // Write the tag.
+//%      [outputStream writeInt32NoTag:tag];
+//%      // Write the size of the message.
+//%      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+//%      [outputStream writeInt32NoTag:(int32_t)msgSize];
+//%      // Write the fields.
+//%      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+//%      WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+//%    }
+//%  }
+//%}
+//%
+//%BOOL_DICT_MUTATIONS_##HELPER(VALUE_NAME, VALUE_TYPE)
+//%
+//%@end
+//%
+
+
+//
+// Helpers for PODs
+//
+
+//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%- (BOOL)valueForKey:(KEY_TYPE)key value:(VALUE_TYPE *)value {
+//%  NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//%  if (wrapped && value) {
+//%    *value = UNWRAP##VALUE_NAME(wrapped);
+//%  }
+//%  return (wrapped != NULL);
+//%}
+//%PDDM-DEFINE WRAPPEDPOD(VALUE)
+//%@(VALUE)
+//%PDDM-DEFINE UNWRAPUInt32(VALUE)
+//%[VALUE unsignedIntValue]
+//%PDDM-DEFINE UNWRAPInt32(VALUE)
+//%[VALUE intValue]
+//%PDDM-DEFINE UNWRAPUInt64(VALUE)
+//%[VALUE unsignedLongLongValue]
+//%PDDM-DEFINE UNWRAPInt64(VALUE)
+//%[VALUE longLongValue]
+//%PDDM-DEFINE UNWRAPBool(VALUE)
+//%[VALUE boolValue]
+//%PDDM-DEFINE UNWRAPFloat(VALUE)
+//%[VALUE floatValue]
+//%PDDM-DEFINE UNWRAPDouble(VALUE)
+//%[VALUE doubleValue]
+//%PDDM-DEFINE UNWRAPEnum(VALUE)
+//%[VALUE intValue]
+//%PDDM-DEFINE TEXT_FORMAT_OBJUInt32(VALUE)
+//%[NSString stringWithFormat:@"%u", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJInt32(VALUE)
+//%[NSString stringWithFormat:@"%d", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJUInt64(VALUE)
+//%[NSString stringWithFormat:@"%llu", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJInt64(VALUE)
+//%[NSString stringWithFormat:@"%lld", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJBool(VALUE)
+//%(VALUE ? @"true" : @"false")
+//%PDDM-DEFINE TEXT_FORMAT_OBJFloat(VALUE)
+//%[NSString stringWithFormat:@"%.*g", FLT_DIG, VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJDouble(VALUE)
+//%[NSString stringWithFormat:@"%.*lg", DBL_DIG, VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJEnum(VALUE)
+//%@(VALUE)
+//%PDDM-DEFINE ENUM_TYPEPOD(TYPE)
+//%NSNumber *
+//%PDDM-DEFINE NEQ_POD(VAL1, VAL2)
+//%VAL1 != VAL2
+//%PDDM-DEFINE EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE BOOL_EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD(KEY_NAME, VALUE_NAME)
+//%SERIAL_DATA_FOR_ENTRY_POD_##VALUE_NAME(KEY_NAME)
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt32(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int32(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt64(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int64(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Bool(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Float(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Double(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME)
+//%- (NSData *)serializedDataForUnknownValue:(int32_t)value
+//%                                   forKey:(GPBGenericValue *)key
+//%                              keyDataType:(GPBDataType)keyDataType {
+//%  size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType);
+//%  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+//%  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+//%  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+//%  WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType);
+//%  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+//%  [outputStream release];
+//%  return data;
+//%}
+//%
+//%PDDM-DEFINE GPBVALUE_POD(VALUE_NAME)
+//%value##VALUE_NAME
+//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_POD(VALUE_NAME, EXTRA_INDENT)
+// Empty
+//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_POD(KEY_NAME, EXTRA_INDENT)
+// Empty
+
+//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_POD()
+//%  BOOL _valueSet[2];
+//%
+//%PDDM-DEFINE BOOL_DICT_INITS_POD(VALUE_NAME, VALUE_TYPE)
+//%- (instancetype)initWithValues:(const VALUE_TYPE [])values
+//%                       forKeys:(const BOOL [])keys
+//%                         count:(NSUInteger)count {
+//%  self = [super init];
+//%  if (self) {
+//%    for (NSUInteger i = 0; i < count; ++i) {
+//%      int idx = keys[i] ? 1 : 0;
+//%      _values[idx] = values[i];
+//%      _valueSet[idx] = YES;
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//%  self = [self initWithValues:NULL forKeys:NULL count:0];
+//%  if (self) {
+//%    if (dictionary) {
+//%      for (int i = 0; i < 2; ++i) {
+//%        if (dictionary->_valueSet[i]) {
+//%          _values[i] = dictionary->_values[i];
+//%          _valueSet[i] = YES;
+//%        }
+//%      }
+//%    }
+//%  }
+//%  return self;
+//%}
+//%PDDM-DEFINE BOOL_DICT_DEALLOCPOD()
+//%#if !defined(NS_BLOCK_ASSERTIONS)
+//%- (void)dealloc {
+//%  NSAssert(!_autocreator,
+//%           @"%@: Autocreator must be cleared before release, autocreator: %@",
+//%           [self class], _autocreator);
+//%  [super dealloc];
+//%}
+//%#endif  // !defined(NS_BLOCK_ASSERTIONS)
+//%PDDM-DEFINE BOOL_DICT_W_HASPOD(IDX, REF)
+//%BOOL_DICT_HASPOD(IDX, REF)
+//%PDDM-DEFINE BOOL_DICT_HASPOD(IDX, REF)
+//%REF##_valueSet[IDX]
+//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_POD(VALUE_TYPE)
+//%- (BOOL)valueForKey:(BOOL)key value:(VALUE_TYPE *)value {
+//%  int idx = (key ? 1 : 0);
+//%  if (_valueSet[idx]) {
+//%    if (value) {
+//%      *value = _values[idx];
+//%    }
+//%    return YES;
+//%  }
+//%  return NO;
+//%}
+//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP)
+//%- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
+//%  int idx = (key->valueBool ? 1 : 0);
+//%  _values[idx] = value->value##VALUE_NAME;
+//%  _valueSet[idx] = YES;
+//%}
+//%PDDM-DEFINE BOOL_DICT_MUTATIONS_POD(VALUE_NAME, VALUE_TYPE)
+//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary {
+//%  if (otherDictionary) {
+//%    for (int i = 0; i < 2; ++i) {
+//%      if (otherDictionary->_valueSet[i]) {
+//%        _valueSet[i] = YES;
+//%        _values[i] = otherDictionary->_values[i];
+//%      }
+//%    }
+//%    if (_autocreator) {
+//%      GPBAutocreatedDictionaryModified(_autocreator, self);
+//%    }
+//%  }
+//%}
+//%
+//%- (void)setValue:(VALUE_TYPE)value forKey:(BOOL)key {
+//%  int idx = (key ? 1 : 0);
+//%  _values[idx] = value;
+//%  _valueSet[idx] = YES;
+//%  if (_autocreator) {
+//%    GPBAutocreatedDictionaryModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%- (void)removeValueForKey:(BOOL)aKey {
+//%  _valueSet[aKey ? 1 : 0] = NO;
+//%}
+//%
+//%- (void)removeAll {
+//%  _valueSet[0] = NO;
+//%  _valueSet[1] = NO;
+//%}
+//%PDDM-DEFINE STR_FORMAT_POD(VALUE_NAME)
+//%STR_FORMAT_##VALUE_NAME()
+//%PDDM-DEFINE STR_FORMAT_UInt32()
+//%%u
+//%PDDM-DEFINE STR_FORMAT_Int32()
+//%%d
+//%PDDM-DEFINE STR_FORMAT_UInt64()
+//%%llu
+//%PDDM-DEFINE STR_FORMAT_Int64()
+//%%lld
+//%PDDM-DEFINE STR_FORMAT_Bool()
+//%%d
+//%PDDM-DEFINE STR_FORMAT_Float()
+//%%f
+//%PDDM-DEFINE STR_FORMAT_Double()
+//%%lf
+
+//
+// Helpers for Objects
+//
+
+//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key {
+//%  VALUE_TYPE result = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//%  return result;
+//%}
+//%PDDM-DEFINE WRAPPEDOBJECT(VALUE)
+//%VALUE
+//%PDDM-DEFINE UNWRAPString(VALUE)
+//%VALUE
+//%PDDM-DEFINE UNWRAPObject(VALUE)
+//%VALUE
+//%PDDM-DEFINE TEXT_FORMAT_OBJString(VALUE)
+//%VALUE
+//%PDDM-DEFINE TEXT_FORMAT_OBJObject(VALUE)
+//%VALUE
+//%PDDM-DEFINE ENUM_TYPEOBJECT(TYPE)
+//%ENUM_TYPEOBJECT_##TYPE()
+//%PDDM-DEFINE ENUM_TYPEOBJECT_NSString()
+//%NSString *
+//%PDDM-DEFINE ENUM_TYPEOBJECT_id()
+//%id ##
+//%PDDM-DEFINE NEQ_OBJECT(VAL1, VAL2)
+//%![VAL1 isEqual:VAL2]
+//%PDDM-DEFINE EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME)
+//%- (BOOL)isInitialized {
+//%  for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+//%    if (!msg.initialized) {
+//%      return NO;
+//%    }
+//%  }
+//%  return YES;
+//%}
+//%
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone {
+//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+//%                                                   GPBMessage *msg,
+//%                                                   BOOL *stop) {
+//%    #pragma unused(stop)
+//%    GPBMessage *copiedMsg = [msg copyWithZone:zone];
+//%    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+//%    [copiedMsg release];
+//%  }];
+//%  return newDict;
+//%}
+//%
+//%
+//%PDDM-DEFINE BOOL_EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME)
+//%- (BOOL)isInitialized {
+//%  if (_values[0] && ![_values[0] isInitialized]) {
+//%    return NO;
+//%  }
+//%  if (_values[1] && ![_values[1] isInitialized]) {
+//%    return NO;
+//%  }
+//%  return YES;
+//%}
+//%
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone {
+//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  for (int i = 0; i < 2; ++i) {
+//%    if (_values[i] != nil) {
+//%      newDict->_values[i] = [_values[i] copyWithZone:zone];
+//%    }
+//%  }
+//%  return newDict;
+//%}
+//%
+//%
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_OBJECT(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE GPBVALUE_OBJECT(VALUE_NAME)
+//%valueString
+//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_OBJECT(VALUE_NAME, EXTRA_INDENT)
+//%##EXTRA_INDENT$S##  if (!##VALUE_NAME) {
+//%##EXTRA_INDENT$S##    [NSException raise:NSInvalidArgumentException
+//%##EXTRA_INDENT$S##                format:@"Attempting to add nil object to a Dictionary"];
+//%##EXTRA_INDENT$S##  }
+//%
+//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_OBJECT(KEY_NAME, EXTRA_INDENT)
+//%##EXTRA_INDENT$S##  if (!##KEY_NAME) {
+//%##EXTRA_INDENT$S##    [NSException raise:NSInvalidArgumentException
+//%##EXTRA_INDENT$S##                format:@"Attempting to add nil key to a Dictionary"];
+//%##EXTRA_INDENT$S##  }
+//%
+
+//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_OBJECT()
+// Empty
+//%PDDM-DEFINE BOOL_DICT_INITS_OBJECT(VALUE_NAME, VALUE_TYPE)
+//%- (instancetype)initWithObjects:(const VALUE_TYPE [])objects
+//%                        forKeys:(const BOOL [])keys
+//%                          count:(NSUInteger)count {
+//%  self = [super init];
+//%  if (self) {
+//%    for (NSUInteger i = 0; i < count; ++i) {
+//%      if (!objects[i]) {
+//%        [NSException raise:NSInvalidArgumentException
+//%                    format:@"Attempting to add nil object to a Dictionary"];
+//%      }
+//%      int idx = keys[i] ? 1 : 0;
+//%      [_values[idx] release];
+//%      _values[idx] = (VALUE_TYPE)[objects[i] retain];
+//%    }
+//%  }
+//%  return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//%  self = [self initWithObjects:NULL forKeys:NULL count:0];
+//%  if (self) {
+//%    if (dictionary) {
+//%      _values[0] = [dictionary->_values[0] retain];
+//%      _values[1] = [dictionary->_values[1] retain];
+//%    }
+//%  }
+//%  return self;
+//%}
+//%PDDM-DEFINE BOOL_DICT_DEALLOCOBJECT()
+//%- (void)dealloc {
+//%  NSAssert(!_autocreator,
+//%           @"%@: Autocreator must be cleared before release, autocreator: %@",
+//%           [self class], _autocreator);
+//%  [_values[0] release];
+//%  [_values[1] release];
+//%  [super dealloc];
+//%}
+//%PDDM-DEFINE BOOL_DICT_W_HASOBJECT(IDX, REF)
+//%(BOOL_DICT_HASOBJECT(IDX, REF))
+//%PDDM-DEFINE BOOL_DICT_HASOBJECT(IDX, REF)
+//%REF##_values[IDX] != nil
+//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_OBJECT(VALUE_TYPE)
+//%- (VALUE_TYPE)objectForKey:(BOOL)key {
+//%  return _values[key ? 1 : 0];
+//%}
+//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP)
+//%- (void)setGPBGenericValue:(GPBGenericValue *)value
+//%     forGPBGenericValueKey:(GPBGenericValue *)key {
+//%  int idx = (key->valueBool ? 1 : 0);
+//%  [_values[idx] release];
+//%  _values[idx] = [value->valueString retain];
+//%}
+
+//%PDDM-DEFINE BOOL_DICT_MUTATIONS_OBJECT(VALUE_NAME, VALUE_TYPE)
+//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary {
+//%  if (otherDictionary) {
+//%    for (int i = 0; i < 2; ++i) {
+//%      if (otherDictionary->_values[i] != nil) {
+//%        [_values[i] release];
+//%        _values[i] = [otherDictionary->_values[i] retain];
+//%      }
+//%    }
+//%    if (_autocreator) {
+//%      GPBAutocreatedDictionaryModified(_autocreator, self);
+//%    }
+//%  }
+//%}
+//%
+//%- (void)setObject:(VALUE_TYPE)object forKey:(BOOL)key {
+//%  if (!object) {
+//%    [NSException raise:NSInvalidArgumentException
+//%                format:@"Attempting to add nil object to a Dictionary"];
+//%  }
+//%  int idx = (key ? 1 : 0);
+//%  [_values[idx] release];
+//%  _values[idx] = [object retain];
+//%  if (_autocreator) {
+//%    GPBAutocreatedDictionaryModified(_autocreator, self);
+//%  }
+//%}
+//%
+//%- (void)removeObjectForKey:(BOOL)aKey {
+//%  int idx = (aKey ? 1 : 0);
+//%  [_values[idx] release];
+//%  _values[idx] = nil;
+//%}
+//%
+//%- (void)removeAll {
+//%  for (int i = 0; i < 2; ++i) {
+//%    [_values[i] release];
+//%    _values[i] = nil;
+//%  }
+//%}
+//%PDDM-DEFINE STR_FORMAT_OBJECT(VALUE_NAME)
+//%%@
+
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32 -> UInt32
+
+@implementation GPBUInt32UInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32UInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32UInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, uint32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue unsignedIntValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedIntValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@implementation GPBUInt32Int32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32Int32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32Int32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@implementation GPBUInt32UInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32UInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32UInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, uint64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue unsignedLongLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedLongLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@implementation GPBUInt32Int64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32Int64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32Int64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue longLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped longLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@implementation GPBUInt32BoolDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32BoolDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32BoolDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32BoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32BoolDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, BOOL value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue boolValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false"));
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(BOOL *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped boolValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@implementation GPBUInt32FloatDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32FloatDictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32FloatDictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32FloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32FloatDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, float value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue floatValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, float value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(float *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped floatValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@implementation GPBUInt32DoubleDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const uint32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32DoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32DoubleDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, double value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue doubleValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, double value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(double *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped doubleValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@implementation GPBUInt32EnumDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+  GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:&rawValue
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])rawValues
+                                         forKeys:(const uint32_t [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:rawValues
+                                                                     forKeys:keys
+                                                                       count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])rawValues
+                                   forKeys:(const uint32_t [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    if (count && rawValues && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32EnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32EnumDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], @(value));
+  }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    int32_t result = [wrapped intValue];
+    if (!_validationFunc(result)) {
+      result = kGPBUnrecognizedEnumeratorValue;
+    }
+    *value = result;
+  }
+  return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(uint32_t)key rawValue:(int32_t *)rawValue {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && rawValue) {
+    *rawValue = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+  GPBEnumValidationFunc func = _validationFunc;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      int32_t unwrapped = [aValue intValue];
+      if (!func(unwrapped)) {
+        unwrapped = kGPBUnrecognizedEnumeratorValue;
+      }
+      block([aKey unsignedIntValue], unwrapped, stop);
+  }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(uint32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key {
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBUInt32EnumDictionary: Attempt to set an unknown enum value (%d)",
+                       value];
+  }
+
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@implementation GPBUInt32ObjectDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithObject:(id)object
+                              forKey:(uint32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithObjects:&object
+                                                            forKeys:&key
+                                                              count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithObjects:(const id [])objects
+                              forKeys:(const uint32_t [])keys
+                                count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithObjects:objects
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const uint32_t [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && objects && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!objects[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil object to a Dictionary"];
+        }
+        [_dictionary setObject:objects[i] forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary {
+  self = [self initWithObjects:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32ObjectDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt32ObjectDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(uint32_t key, id object, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+      block([aKey unsignedIntValue], aObject, stop);
+  }];
+}
+
+- (BOOL)isInitialized {
+  for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+    if (!msg.initialized) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+  GPBUInt32ObjectDictionary *newDict =
+      [[GPBUInt32ObjectDictionary alloc] init];
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+                                                   GPBMessage *msg,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    GPBMessage *copiedMsg = [msg copyWithZone:zone];
+    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [copiedMsg release];
+  }];
+  return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%u", key], object);
+  }];
+}
+
+- (id)objectForKey:(uint32_t)key {
+  id result = [_dictionary objectForKey:@(key)];
+  return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setObject:(id)object forKey:(uint32_t)key {
+  if (!object) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil object to a Dictionary"];
+  }
+  [_dictionary setObject:object forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(uint32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32 -> UInt32
+
+@implementation GPBInt32UInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32UInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32UInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, uint32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue unsignedIntValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(uint32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedIntValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@implementation GPBInt32Int32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32Int32Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32Int32Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32Int32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32Int32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@implementation GPBInt32UInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32UInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32UInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, uint64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue unsignedLongLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(uint64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedLongLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@implementation GPBInt32Int64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32Int64Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32Int64Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32Int64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32Int64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue longLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, int64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped longLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@implementation GPBInt32BoolDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32BoolDictionary*)[self alloc] initWithValues:&value
+                                                        forKeys:&key
+                                                          count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32BoolDictionary*)[self alloc] initWithValues:values
+                                                        forKeys:keys
+                                                          count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32BoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32BoolDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, BOOL value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue boolValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, BOOL value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false"));
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(BOOL *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped boolValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@implementation GPBInt32FloatDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32FloatDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32FloatDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32FloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32FloatDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, float value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue floatValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, float value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(float *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped floatValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@implementation GPBInt32DoubleDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32DoubleDictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const int32_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32DoubleDictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32DoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32DoubleDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, double value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue doubleValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int32_t key, double value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(double *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped doubleValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@implementation GPBInt32EnumDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+  GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                  rawValues:&rawValue
+                                                                    forKeys:&key
+                                                                      count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])rawValues
+                                         forKeys:(const int32_t [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                  rawValues:rawValues
+                                                                    forKeys:keys
+                                                                      count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])rawValues
+                                   forKeys:(const int32_t [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    if (count && rawValues && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32EnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32EnumDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey intValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], @(value));
+  }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    int32_t result = [wrapped intValue];
+    if (!_validationFunc(result)) {
+      result = kGPBUnrecognizedEnumeratorValue;
+    }
+    *value = result;
+  }
+  return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(int32_t)key rawValue:(int32_t *)rawValue {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && rawValue) {
+    *rawValue = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+  GPBEnumValidationFunc func = _validationFunc;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      int32_t unwrapped = [aValue intValue];
+      if (!func(unwrapped)) {
+        unwrapped = kGPBUnrecognizedEnumeratorValue;
+      }
+      block([aKey intValue], unwrapped, stop);
+  }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(int32_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key {
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBInt32EnumDictionary: Attempt to set an unknown enum value (%d)",
+                       value];
+  }
+
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@implementation GPBInt32ObjectDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithObject:(id)object
+                              forKey:(int32_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32ObjectDictionary*)[self alloc] initWithObjects:&object
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithObjects:(const id [])objects
+                              forKeys:(const int32_t [])keys
+                                count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt32ObjectDictionary*)[self alloc] initWithObjects:objects
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const int32_t [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && objects && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!objects[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil object to a Dictionary"];
+        }
+        [_dictionary setObject:objects[i] forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary {
+  self = [self initWithObjects:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32ObjectDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt32ObjectDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(int32_t key, id object, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+      block([aKey intValue], aObject, stop);
+  }];
+}
+
+- (BOOL)isInitialized {
+  for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+    if (!msg.initialized) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+  GPBInt32ObjectDictionary *newDict =
+      [[GPBInt32ObjectDictionary alloc] init];
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+                                                   GPBMessage *msg,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    GPBMessage *copiedMsg = [msg copyWithZone:zone];
+    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [copiedMsg release];
+  }];
+  return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:value->valueString forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%d", key], object);
+  }];
+}
+
+- (id)objectForKey:(int32_t)key {
+  id result = [_dictionary objectForKey:@(key)];
+  return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setObject:(id)object forKey:(int32_t)key {
+  if (!object) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil object to a Dictionary"];
+  }
+  [_dictionary setObject:object forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(int32_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64 -> UInt32
+
+@implementation GPBUInt64UInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64UInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64UInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, uint32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue unsignedIntValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedIntValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@implementation GPBUInt64Int32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64Int32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64Int32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@implementation GPBUInt64UInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64UInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64UInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, uint64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedLongLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@implementation GPBUInt64Int64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64Int64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64Int64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue longLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped longLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@implementation GPBUInt64BoolDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64BoolDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64BoolDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64BoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64BoolDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, BOOL value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue boolValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false"));
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(BOOL *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped boolValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@implementation GPBUInt64FloatDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64FloatDictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64FloatDictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64FloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64FloatDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, float value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue floatValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, float value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(float *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped floatValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@implementation GPBUInt64DoubleDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const uint64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64DoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64DoubleDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, double value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue doubleValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, double value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(double *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped doubleValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@implementation GPBUInt64EnumDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+  GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:&rawValue
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])rawValues
+                                         forKeys:(const uint64_t [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:rawValues
+                                                                     forKeys:keys
+                                                                       count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])rawValues
+                                   forKeys:(const uint64_t [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    if (count && rawValues && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64EnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64EnumDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], @(value));
+  }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    int32_t result = [wrapped intValue];
+    if (!_validationFunc(result)) {
+      result = kGPBUnrecognizedEnumeratorValue;
+    }
+    *value = result;
+  }
+  return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(uint64_t)key rawValue:(int32_t *)rawValue {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && rawValue) {
+    *rawValue = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+  GPBEnumValidationFunc func = _validationFunc;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      int32_t unwrapped = [aValue intValue];
+      if (!func(unwrapped)) {
+        unwrapped = kGPBUnrecognizedEnumeratorValue;
+      }
+      block([aKey unsignedLongLongValue], unwrapped, stop);
+  }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(uint64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key {
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBUInt64EnumDictionary: Attempt to set an unknown enum value (%d)",
+                       value];
+  }
+
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@implementation GPBUInt64ObjectDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithObject:(id)object
+                              forKey:(uint64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithObjects:&object
+                                                            forKeys:&key
+                                                              count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithObjects:(const id [])objects
+                              forKeys:(const uint64_t [])keys
+                                count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithObjects:objects
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const uint64_t [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && objects && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!objects[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil object to a Dictionary"];
+        }
+        [_dictionary setObject:objects[i] forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary {
+  self = [self initWithObjects:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBUInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64ObjectDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBUInt64ObjectDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(uint64_t key, id object, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+      block([aKey unsignedLongLongValue], aObject, stop);
+  }];
+}
+
+- (BOOL)isInitialized {
+  for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+    if (!msg.initialized) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+  GPBUInt64ObjectDictionary *newDict =
+      [[GPBUInt64ObjectDictionary alloc] init];
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+                                                   GPBMessage *msg,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    GPBMessage *copiedMsg = [msg copyWithZone:zone];
+    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [copiedMsg release];
+  }];
+  return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%llu", key], object);
+  }];
+}
+
+- (id)objectForKey:(uint64_t)key {
+  id result = [_dictionary objectForKey:@(key)];
+  return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setObject:(id)object forKey:(uint64_t)key {
+  if (!object) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil object to a Dictionary"];
+  }
+  [_dictionary setObject:object forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(uint64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64 -> UInt32
+
+@implementation GPBInt64UInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64UInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64UInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, uint32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue unsignedIntValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(uint32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedIntValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@implementation GPBInt64Int32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64Int32Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64Int32Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64Int32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64Int32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@implementation GPBInt64UInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64UInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64UInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, uint64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue unsignedLongLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(uint64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped unsignedLongLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@implementation GPBInt64Int64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64Int64Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64Int64Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64Int64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64Int64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue longLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, int64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped longLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@implementation GPBInt64BoolDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64BoolDictionary*)[self alloc] initWithValues:&value
+                                                        forKeys:&key
+                                                          count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64BoolDictionary*)[self alloc] initWithValues:values
+                                                        forKeys:keys
+                                                          count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64BoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64BoolDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, BOOL value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue boolValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, BOOL value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false"));
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(BOOL *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped boolValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@implementation GPBInt64FloatDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64FloatDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64FloatDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64FloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64FloatDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, float value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue floatValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, float value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(float *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped floatValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@implementation GPBInt64DoubleDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64DoubleDictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const int64_t [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64DoubleDictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64DoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64DoubleDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, double value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue doubleValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(int64_t key, double value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(double *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    *value = [wrapped doubleValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@implementation GPBInt64EnumDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+  GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                  rawValues:&rawValue
+                                                                    forKeys:&key
+                                                                      count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])rawValues
+                                         forKeys:(const int64_t [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                  rawValues:rawValues
+                                                                    forKeys:keys
+                                                                      count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])rawValues
+                                   forKeys:(const int64_t [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    if (count && rawValues && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64EnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64EnumDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], @(value));
+  }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && value) {
+    int32_t result = [wrapped intValue];
+    if (!_validationFunc(result)) {
+      result = kGPBUnrecognizedEnumeratorValue;
+    }
+    *value = result;
+  }
+  return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(int64_t)key rawValue:(int32_t *)rawValue {
+  NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+  if (wrapped && rawValue) {
+    *rawValue = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+  GPBEnumValidationFunc func = _validationFunc;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      int32_t unwrapped = [aValue intValue];
+      if (!func(unwrapped)) {
+        unwrapped = kGPBUnrecognizedEnumeratorValue;
+      }
+      block([aKey longLongValue], unwrapped, stop);
+  }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(int64_t)key {
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key {
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBInt64EnumDictionary: Attempt to set an unknown enum value (%d)",
+                       value];
+  }
+
+  [_dictionary setObject:@(value) forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@implementation GPBInt64ObjectDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithObject:(id)object
+                              forKey:(int64_t)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64ObjectDictionary*)[self alloc] initWithObjects:&object
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithObjects:(const id [])objects
+                              forKeys:(const int64_t [])keys
+                                count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBInt64ObjectDictionary*)[self alloc] initWithObjects:objects
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const int64_t [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && objects && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!objects[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil object to a Dictionary"];
+        }
+        [_dictionary setObject:objects[i] forKey:@(keys[i])];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary {
+  self = [self initWithObjects:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64ObjectDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBInt64ObjectDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(int64_t key, id object, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+      block([aKey longLongValue], aObject, stop);
+  }];
+}
+
+- (BOOL)isInitialized {
+  for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+    if (!msg.initialized) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+  GPBInt64ObjectDictionary *newDict =
+      [[GPBInt64ObjectDictionary alloc] init];
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+                                                   GPBMessage *msg,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    GPBMessage *copiedMsg = [msg copyWithZone:zone];
+    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [copiedMsg release];
+  }];
+  return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+                                                   id aObject,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:value->valueString forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, BOOL *stop) {
+      #pragma unused(stop)
+      block([NSString stringWithFormat:@"%lld", key], object);
+  }];
+}
+
+- (id)objectForKey:(int64_t)key {
+  id result = [_dictionary objectForKey:@(key)];
+  return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setObject:(id)object forKey:(int64_t)key {
+  if (!object) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil object to a Dictionary"];
+  }
+  [_dictionary setObject:object forKey:@(key)];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(int64_t)aKey {
+  [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - String -> UInt32
+
+@implementation GPBStringUInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringUInt32Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringUInt32Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringUInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringUInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringUInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, uint32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue unsignedIntValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%u", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(uint32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped unsignedIntValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Int32
+
+@implementation GPBStringInt32Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringInt32Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringInt32Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringInt32Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt32) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%d", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> UInt64
+
+@implementation GPBStringUInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringUInt64Dictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringUInt64Dictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringUInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringUInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringUInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, uint64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue unsignedLongLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%llu", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(uint64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped unsignedLongLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Int64
+
+@implementation GPBStringInt64Dictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringInt64Dictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringInt64Dictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringInt64Dictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int64_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue longLongValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueInt64) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, int64_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%lld", value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int64_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped longLongValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Bool
+
+@implementation GPBStringBoolDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringBoolDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringBoolDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringBoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringBoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringBoolDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, BOOL value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue boolValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueBool) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, BOOL value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, (value ? @"true" : @"false"));
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(BOOL *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped boolValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Float
+
+@implementation GPBStringFloatDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringFloatDictionary*)[self alloc] initWithValues:&value
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringFloatDictionary*)[self alloc] initWithValues:values
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringFloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringFloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringFloatDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, float value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue floatValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueFloat) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, float value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(float *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped floatValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Double
+
+@implementation GPBStringDoubleDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringDoubleDictionary*)[self alloc] initWithValues:&value
+                                                           forKeys:&key
+                                                             count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const NSString * [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringDoubleDictionary*)[self alloc] initWithValues:values
+                                                           forKeys:keys
+                                                             count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBStringDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    if (count && values && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(values[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringDoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringDoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringDoubleDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, double value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue doubleValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueDouble) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndValuesUsingBlock:^(NSString *key, double value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(double *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    *value = [wrapped doubleValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Enum
+
+@implementation GPBStringEnumDictionary {
+ @package
+  NSMutableDictionary *_dictionary;
+  GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        rawValue:(int32_t)rawValue
+                                          forKey:(NSString *)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:&rawValue
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])rawValues
+                                         forKeys:(const NSString * [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                   rawValues:rawValues
+                                                                     forKeys:keys
+                                                                       count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBStringEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                 rawValues:(const int32_t [])rawValues
+                                   forKeys:(const NSString * [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    if (count && rawValues && keys) {
+      for (NSUInteger i = 0; i < count; ++i) {
+        if (!keys[i]) {
+          [NSException raise:NSInvalidArgumentException
+                      format:@"Attempting to add nil key to a Dictionary"];
+        }
+        [_dictionary setObject:@(rawValues[i]) forKey:keys[i]];
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBStringEnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringEnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBStringEnumDictionary class]]) {
+    return NO;
+  }
+  return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+  return _dictionary.count;
+}
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+  return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      block(aKey, [aValue intValue], stop);
+  }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  NSUInteger count = _dictionary.count;
+  if (count == 0) {
+    return 0;
+  }
+
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  __block size_t result = 0;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+  }];
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  GPBDataType keyDataType = field.mapKeyDataType;
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+    #pragma unused(stop)
+    // Write the tag.
+    [outputStream writeInt32NoTag:tag];
+    // Write the size of the message.
+    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    [outputStream writeInt32NoTag:(int32_t)msgSize];
+    // Write the fields.
+    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
+  }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  [_dictionary setObject:@(value->valueEnum) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
+      #pragma unused(stop)
+      block(key, @(value));
+  }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && value) {
+    int32_t result = [wrapped intValue];
+    if (!_validationFunc(result)) {
+      result = kGPBUnrecognizedEnumeratorValue;
+    }
+    *value = result;
+  }
+  return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(NSString *)key rawValue:(int32_t *)rawValue {
+  NSNumber *wrapped = [_dictionary objectForKey:key];
+  if (wrapped && rawValue) {
+    *rawValue = [wrapped intValue];
+  }
+  return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+  GPBEnumValidationFunc func = _validationFunc;
+  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+                                                   NSNumber *aValue,
+                                                   BOOL *stop) {
+      int32_t unwrapped = [aValue intValue];
+      if (!func(unwrapped)) {
+        unwrapped = kGPBUnrecognizedEnumeratorValue;
+      }
+      block(aKey, unwrapped, stop);
+  }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+  [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key {
+  if (!key) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil key to a Dictionary"];
+  }
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBStringEnumDictionary: Attempt to set an unknown enum value (%d)",
+                       value];
+  }
+
+  [_dictionary setObject:@(value) forKey:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+@end
+
+//%PDDM-EXPAND-END (5 expansions)
+
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt32
+
+@implementation GPBBoolUInt32Dictionary {
+ @package
+  uint32_t _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolUInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolUInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolUInt32Dictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %u", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %u", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(uint32_t *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueUInt32;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%u", _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%u", _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, uint32_t value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint32_t)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int32
+
+@implementation GPBBoolInt32Dictionary {
+ @package
+  int32_t _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolInt32Dictionary*)[self alloc] initWithValues:&value
+                                                        forKeys:&key
+                                                          count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolInt32Dictionary*)[self alloc] initWithValues:values
+                                                        forKeys:keys
+                                                          count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolInt32Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolInt32Dictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %d", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %d", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueInt32;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%d", _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%d", _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int32_t value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt64
+
+@implementation GPBBoolUInt64Dictionary {
+ @package
+  uint64_t _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolUInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolUInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolUInt64Dictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %llu", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %llu", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(uint64_t *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueUInt64;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%llu", _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%llu", _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, uint64_t value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(uint64_t)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int64
+
+@implementation GPBBoolInt64Dictionary {
+ @package
+  int64_t _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolInt64Dictionary*)[self alloc] initWithValues:&value
+                                                        forKeys:&key
+                                                          count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolInt64Dictionary*)[self alloc] initWithValues:values
+                                                        forKeys:keys
+                                                          count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolInt64Dictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolInt64Dictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %lld", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %lld", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int64_t *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueInt64;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%lld", _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%lld", _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int64_t value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int64_t)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Bool
+
+@implementation GPBBoolBoolDictionary {
+ @package
+  BOOL _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolBoolDictionary*)[self alloc] initWithValues:&value
+                                                       forKeys:&key
+                                                         count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolBoolDictionary*)[self alloc] initWithValues:values
+                                                       forKeys:keys
+                                                         count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolBoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolBoolDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolBoolDictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %d", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %d", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(BOOL *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueBool;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", (_values[0] ? @"true" : @"false"));
+  }
+  if (_valueSet[1]) {
+    block(@"true", (_values[1] ? @"true" : @"false"));
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, BOOL value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(BOOL)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Float
+
+@implementation GPBBoolFloatDictionary {
+ @package
+  float _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolFloatDictionary*)[self alloc] initWithValues:&value
+                                                        forKeys:&key
+                                                          count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolFloatDictionary*)[self alloc] initWithValues:values
+                                                        forKeys:keys
+                                                          count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolFloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolFloatDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolFloatDictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %f", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %f", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(float *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueFloat;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, float value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(float)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Double
+
+@implementation GPBBoolDoubleDictionary {
+ @package
+  double _values[2];
+  BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+                             forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolDoubleDictionary*)[self alloc] initWithValues:&value
+                                                         forKeys:&key
+                                                           count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+                             forKeys:(const BOOL [])keys
+                               count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolDoubleDictionary*)[self alloc] initWithValues:values
+                                                         forKeys:keys
+                                                           count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+                       forKeys:(const BOOL [])keys
+                         count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = values[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary {
+  self = [self initWithValues:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolDoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolDoubleDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolDoubleDictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %lf", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %lf", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(double *)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      *value = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueDouble;
+  _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[0]]);
+  }
+  if (_valueSet[1]) {
+    block(@"true", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[1]]);
+  }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, double value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(double)value forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Object
+
+@implementation GPBBoolObjectDictionary {
+ @package
+  id _values[2];
+}
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithObject:(id)object
+                              forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolObjectDictionary*)[self alloc] initWithObjects:&object
+                                                          forKeys:&key
+                                                            count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithObjects:(const id [])objects
+                              forKeys:(const BOOL [])keys
+                                count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolObjectDictionary*)[self alloc] initWithObjects:objects
+                                                          forKeys:keys
+                                                            count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithDictionary:
+  // on to get the type correct.
+  return [[(GPBBoolObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const BOOL [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    for (NSUInteger i = 0; i < count; ++i) {
+      if (!objects[i]) {
+        [NSException raise:NSInvalidArgumentException
+                    format:@"Attempting to add nil object to a Dictionary"];
+      }
+      int idx = keys[i] ? 1 : 0;
+      [_values[idx] release];
+      _values[idx] = (id)[objects[i] retain];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary {
+  self = [self initWithObjects:NULL forKeys:NULL count:0];
+  if (self) {
+    if (dictionary) {
+      _values[0] = [dictionary->_values[0] retain];
+      _values[1] = [dictionary->_values[1] retain];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+  #pragma unused(numItems)
+  return [self initWithObjects:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_values[0] release];
+  [_values[1] release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolObjectDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolObjectDictionary class]]) {
+    return NO;
+  }
+  if (((_values[0] != nil) != (other->_values[0] != nil)) ||
+      ((_values[1] != nil) != (other->_values[1] != nil))) {
+    return NO;
+  }
+  if (((_values[0] != nil) && (![_values[0] isEqual:other->_values[0]])) ||
+      ((_values[1] != nil) && (![_values[1] isEqual:other->_values[1]]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if ((_values[0] != nil)) {
+    [result appendFormat:@"NO: %@", _values[0]];
+  }
+  if ((_values[1] != nil)) {
+    [result appendFormat:@"YES: %@", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0);
+}
+
+- (id)objectForKey:(BOOL)key {
+  return _values[key ? 1 : 0];
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  [_values[idx] release];
+  _values[idx] = [value->valueString retain];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_values[0] != nil) {
+    block(@"false", _values[0]);
+  }
+  if ((_values[1] != nil)) {
+    block(@"true", _values[1]);
+  }
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:
+    (void (^)(BOOL key, id object, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_values[0] != nil) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && (_values[1] != nil)) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (BOOL)isInitialized {
+  if (_values[0] && ![_values[0] isInitialized]) {
+    return NO;
+  }
+  if (_values[1] && ![_values[1] isInitialized]) {
+    return NO;
+  }
+  return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+  GPBBoolObjectDictionary *newDict =
+      [[GPBBoolObjectDictionary alloc] init];
+  for (int i = 0; i < 2; ++i) {
+    if (_values[i] != nil) {
+      newDict->_values[i] = [_values[i] copyWithZone:zone];
+    }
+  }
+  return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_values[i] != nil) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_values[i] != nil) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_values[i] != nil) {
+        [_values[i] release];
+        _values[i] = [otherDictionary->_values[i] retain];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setObject:(id)object forKey:(BOOL)key {
+  if (!object) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Attempting to add nil object to a Dictionary"];
+  }
+  int idx = (key ? 1 : 0);
+  [_values[idx] release];
+  _values[idx] = [object retain];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(BOOL)aKey {
+  int idx = (aKey ? 1 : 0);
+  [_values[idx] release];
+  _values[idx] = nil;
+}
+
+- (void)removeAll {
+  for (int i = 0; i < 2; ++i) {
+    [_values[i] release];
+    _values[i] = nil;
+  }
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+#pragma mark - Bool -> Enum
+
+@implementation GPBBoolEnumDictionary {
+ @package
+  GPBEnumValidationFunc _validationFunc;
+  int32_t _values[2];
+  BOOL _valueSet[2];
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+  return [[[self alloc] initWithValidationFunction:NULL
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [[[self alloc] initWithValidationFunction:func
+                                         rawValues:NULL
+                                           forKeys:NULL
+                                             count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValue:(int32_t)rawValue
+                                          forKey:(BOOL)key {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                 rawValues:&rawValue
+                                                                   forKeys:&key
+                                                                     count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                       rawValues:(const int32_t [])values
+                                         forKeys:(const BOOL [])keys
+                                           count:(NSUInteger)count {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func
+                                                                 rawValues:values
+                                                                   forKeys:keys
+                                                                     count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary {
+  // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+  // on to get the type correct.
+  return [[(GPBBoolEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+                                        capacity:(NSUInteger)numItems {
+  return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+  return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                rawValues:(const int32_t [])rawValues
+                                   forKeys:(const BOOL [])keys
+                                     count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+    for (NSUInteger i = 0; i < count; ++i) {
+      int idx = keys[i] ? 1 : 0;
+      _values[idx] = rawValues[i];
+      _valueSet[idx] = YES;
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary {
+  self = [self initWithValidationFunction:dictionary.validationFunc
+                                rawValues:NULL
+                                  forKeys:NULL
+                                    count:0];
+  if (self) {
+    if (dictionary) {
+      for (int i = 0; i < 2; ++i) {
+        if (dictionary->_valueSet[i]) {
+          _values[i] = dictionary->_values[i];
+          _valueSet[i] = YES;
+        }
+      }
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+                                  capacity:(NSUInteger)numItems {
+#pragma unused(numItems)
+  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+#if !defined(NS_BLOCK_ASSERTIONS)
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [super dealloc];
+}
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  return [[GPBBoolEnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolEnumDictionary *)other {
+  if (self == other) {
+    return YES;
+  }
+  if (![other isKindOfClass:[GPBBoolEnumDictionary class]]) {
+    return NO;
+  }
+  if ((_valueSet[0] != other->_valueSet[0]) ||
+      (_valueSet[1] != other->_valueSet[1])) {
+    return NO;
+  }
+  if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+      (_valueSet[1] && (_values[1] != other->_values[1]))) {
+    return NO;
+  }
+  return YES;
+}
+
+- (NSUInteger)hash {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+  NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+  if (_valueSet[0]) {
+    [result appendFormat:@"NO: %d", _values[0]];
+  }
+  if (_valueSet[1]) {
+    [result appendFormat:@"YES: %d", _values[1]];
+  }
+  [result appendString:@" }"];
+  return result;
+}
+
+- (NSUInteger)count {
+  return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t*)value {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (value) {
+      int32_t result = _values[idx];
+      if (!_validationFunc(result)) {
+        result = kGPBUnrecognizedEnumeratorValue;
+      }
+      *value = result;
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (BOOL)valueForKey:(BOOL)key rawValue:(int32_t*)rawValue {
+  int idx = (key ? 1 : 0);
+  if (_valueSet[idx]) {
+    if (rawValue) {
+      *rawValue = _values[idx];
+    }
+    return YES;
+  }
+  return NO;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+    (void (^)(BOOL key, int32_t value, BOOL *stop))block {
+  BOOL stop = NO;
+  if (_valueSet[0]) {
+    block(NO, _values[0], &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    block(YES, _values[1], &stop);
+  }
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+    (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block {
+  BOOL stop = NO;
+  GPBEnumValidationFunc func = _validationFunc;
+  int32_t validatedValue;
+  if (_valueSet[0]) {
+    validatedValue = _values[0];
+    if (!func(validatedValue)) {
+      validatedValue = kGPBUnrecognizedEnumeratorValue;
+    }
+    block(NO, validatedValue, &stop);
+  }
+  if (!stop && _valueSet[1]) {
+    validatedValue = _values[1];
+    if (!func(validatedValue)) {
+      validatedValue = kGPBUnrecognizedEnumeratorValue;
+    }
+    block(YES, validatedValue, &stop);
+  }
+}
+
+//%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
+// This block of code is generated, do not edit it directly.
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType {
+  size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType);
+  msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum);
+  NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+  GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+  WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType);
+  WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
+  [outputStream release];
+  return data;
+}
+
+//%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  NSUInteger count = 0;
+  size_t result = 0;
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      ++count;
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+    }
+  }
+  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
+  result += tagSize * count;
+  return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field {
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+  for (int i = 0; i < 2; ++i) {
+    if (_valueSet[i]) {
+      // Write the tag.
+      [outputStream writeInt32NoTag:tag];
+      // Write the size of the message.
+      size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType);
+      [outputStream writeInt32NoTag:(int32_t)msgSize];
+      // Write the fields.
+      WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool);
+      WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType);
+    }
+  }
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+  if (_valueSet[0]) {
+    block(@"false", @(_values[0]));
+  }
+  if (_valueSet[1]) {
+    block(@"true", @(_values[1]));
+  }
+}
+
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key {
+  int idx = (key->valueBool ? 1 : 0);
+  _values[idx] = value->valueInt32;
+  _valueSet[idx] = YES;
+}
+
+- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary {
+  if (otherDictionary) {
+    for (int i = 0; i < 2; ++i) {
+      if (otherDictionary->_valueSet[i]) {
+        _valueSet[i] = YES;
+        _values[i] = otherDictionary->_values[i];
+      }
+    }
+    if (_autocreator) {
+      GPBAutocreatedDictionaryModified(_autocreator, self);
+    }
+  }
+}
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key {
+  if (!_validationFunc(value)) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)",
+     value];
+  }
+  int idx = (key ? 1 : 0);
+  _values[idx] = value;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key {
+  int idx = (key ? 1 : 0);
+  _values[idx] = rawValue;
+  _valueSet[idx] = YES;
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+  _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+  _valueSet[0] = NO;
+  _valueSet[1] = NO;
+}
+
+@end
+
+#pragma mark - NSDictionary Subclass
+
+@implementation GPBAutocreatedDictionary {
+  NSMutableDictionary *_dictionary;
+}
+
+- (void)dealloc {
+  NSAssert(!_autocreator,
+           @"%@: Autocreator must be cleared before release, autocreator: %@",
+           [self class], _autocreator);
+  [_dictionary release];
+  [super dealloc];
+}
+
+#pragma mark Required NSDictionary overrides
+
+- (instancetype)initWithObjects:(const id [])objects
+                        forKeys:(const id<NSCopying> [])keys
+                          count:(NSUInteger)count {
+  self = [super init];
+  if (self) {
+    _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects
+                                                       forKeys:keys
+                                                         count:count];
+  }
+  return self;
+}
+
+- (NSUInteger)count {
+  return [_dictionary count];
+}
+
+- (id)objectForKey:(id)aKey {
+  return [_dictionary objectForKey:aKey];
+}
+
+- (NSEnumerator *)keyEnumerator {
+  if (_dictionary == nil) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+  }
+  return [_dictionary keyEnumerator];
+}
+
+#pragma mark Required NSMutableDictionary overrides
+
+// Only need to call GPBAutocreatedDictionaryModified() when adding things
+// since we only autocreate empty dictionaries.
+
+- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
+  if (_dictionary == nil) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+  }
+  [_dictionary setObject:anObject forKey:aKey];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)removeObjectForKey:(id)aKey {
+  [_dictionary removeObjectForKey:aKey];
+}
+
+#pragma mark Extra things hooked
+
+- (id)copyWithZone:(NSZone *)zone {
+  if (_dictionary == nil) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+  }
+  return [_dictionary copyWithZone:zone];
+}
+
+- (id)mutableCopyWithZone:(NSZone *)zone {
+  if (_dictionary == nil) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+  }
+  return [_dictionary mutableCopyWithZone:zone];
+}
+
+- (id)objectForKeyedSubscript:(id)key {
+  return [_dictionary objectForKeyedSubscript:key];
+}
+
+- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
+  if (_dictionary == nil) {
+    _dictionary = [[NSMutableDictionary alloc] init];
+  }
+  [_dictionary setObject:obj forKeyedSubscript:key];
+  if (_autocreator) {
+    GPBAutocreatedDictionaryModified(_autocreator, self);
+  }
+}
+
+- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key,
+                                                    id obj,
+                                                    BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsUsingBlock:block];
+}
+
+- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts
+                                usingBlock:(void (^)(id key,
+                                                     id obj,
+                                                     BOOL *stop))block {
+  [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBDictionary_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBDictionary_PackagePrivate.h
new file mode 100644
index 0000000..7b921e8
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBDictionary_PackagePrivate.h
@@ -0,0 +1,488 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBDictionary.h"
+
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionRegistry;
+@class GPBFieldDescriptor;
+
+@protocol GPBDictionaryInternalsProtocol
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+                         asField:(GPBFieldDescriptor *)field;
+- (void)setGPBGenericValue:(GPBGenericValue *)value
+     forGPBGenericValueKey:(GPBGenericValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+//%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME)
+//%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object)
+//%PDDM-DEFINE DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt32, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int32, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt64, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int64, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Bool, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Float, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Double, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Enum, Enum)
+
+//%PDDM-DEFINE DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, VALUE_NAME, HELPER)
+//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary () <GPBDictionaryInternalsProtocol> {
+//% @package
+//%  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+//%}
+//%EXTRA_DICTIONARY_PRIVATE_INTERFACES_##HELPER()@end
+//%
+
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Basic()
+// Empty
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Object()
+//%- (BOOL)isInitialized;
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone
+//%    __attribute__((ns_returns_retained));
+//%
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum()
+//%- (NSData *)serializedDataForUnknownValue:(int32_t)value
+//%                                   forKey:(GPBGenericValue *)key
+//%                              keyDataType:(GPBDataType)keyDataType;
+//%
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBUInt32UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32Int32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32UInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32Int64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32BoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32FloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32DoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt32EnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+@interface GPBUInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+    __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBInt32UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32Int32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32UInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32Int64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32BoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32FloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32DoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt32EnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+@interface GPBInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+    __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBUInt64UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64Int32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64UInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64Int64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64BoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64FloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64DoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBUInt64EnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+@interface GPBUInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+    __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBInt64UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64Int32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64UInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64Int64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64BoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64FloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64DoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBInt64EnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+@interface GPBInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+    __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBBoolUInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolUInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolBoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolFloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolDoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBBoolEnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+@interface GPBBoolObjectDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+    __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBStringUInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringInt32Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringUInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringInt64Dictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringBoolDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringFloatDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringDoubleDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+@interface GPBStringEnumDictionary () <GPBDictionaryInternalsProtocol> {
+ @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+                                   forKey:(GPBGenericValue *)key
+                              keyDataType:(GPBDataType)keyDataType;
+@end
+
+//%PDDM-EXPAND-END (6 expansions)
+
+#pragma mark - NSDictionary Subclass
+
+@interface GPBAutocreatedDictionary : NSMutableDictionary {
+  @package
+  GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Helpers
+
+CF_EXTERN_C_BEGIN
+
+// Helper to compute size when an NSDictionary is used for the map instead
+// of a custom type.
+size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict,
+                                              GPBFieldDescriptor *field);
+
+// Helper to write out when an NSDictionary is used for the map instead
+// of a custom type.
+void GPBDictionaryWriteToStreamInternalHelper(
+    GPBCodedOutputStream *outputStream, NSDictionary *dict,
+    GPBFieldDescriptor *field);
+
+// Helper to check message initialization when an NSDictionary is used for
+// the map instead of a custom type.
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict,
+                                              GPBFieldDescriptor *field);
+
+// Helper to read a map instead.
+void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
+                            GPBExtensionRegistry *registry,
+                            GPBFieldDescriptor *field,
+                            GPBMessage *parentMessage);
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.h b/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.h
new file mode 100644
index 0000000..2b980ae
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.h
@@ -0,0 +1,50 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBDescriptor.h"
+
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionRegistry;
+
+void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
+                                      BOOL isPackedOnStream,
+                                      GPBCodedInputStream *input,
+                                      GPBExtensionRegistry *extensionRegistry,
+                                      GPBMessage *message);
+
+size_t GPBComputeExtensionSerializedSizeIncludingTag(
+    GPBExtensionDescriptor *extension, id value);
+
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
+                                          id value,
+                                          GPBCodedOutputStream *output);
diff --git a/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.m b/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.m
new file mode 100644
index 0000000..7d0dcb2
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBExtensionInternals.m
@@ -0,0 +1,380 @@
+// 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.
+
+#import "GPBExtensionInternals.h"
+
+#import <objc/runtime.h>
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBCodedInputStream *input,
+                                        GPBExtensionRegistry *extensionRegistry,
+                                        GPBMessage *existingValue)
+    __attribute__((ns_returns_retained));
+
+GPB_INLINE size_t DataTypeSize(GPBDataType dataType) {
+  switch (dataType) {
+    case GPBDataTypeBool:
+      return 1;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeFloat:
+      return 4;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeDouble:
+      return 8;
+    default:
+      return 0;
+  }
+}
+
+static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR)                                     \
+  case GPBDataType##TYPE:                                              \
+    return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE)                                              \
+  case GPBDataType##TYPE:                                              \
+    return GPBCompute##TYPE##SizeNoTag(object);
+  switch (dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Message)
+    FIELD_CASE2(Group)
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfObject(
+    GPBExtensionDescription *description, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR)                                   \
+  case GPBDataType##TYPE:                                            \
+    return GPBCompute##TYPE##Size(description->fieldNumber,          \
+                                  [(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE)                                            \
+  case GPBDataType##TYPE:                                            \
+    return GPBCompute##TYPE##Size(description->fieldNumber, object);
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Group)
+    case GPBDataTypeMessage:
+      if (GPBExtensionIsWireFormat(description)) {
+        return GPBComputeMessageSetExtensionSize(description->fieldNumber,
+                                                 object);
+      } else {
+        return GPBComputeMessageSize(description->fieldNumber, object);
+      }
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfArray(
+    GPBExtensionDescription *description, NSArray *values) {
+  if (GPBExtensionIsPacked(description)) {
+    size_t size = 0;
+    size_t typeSize = DataTypeSize(description->dataType);
+    if (typeSize != 0) {
+      size = values.count * typeSize;
+    } else {
+      for (id value in values) {
+        size +=
+            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+      }
+    }
+    return size + GPBComputeTagSize(description->fieldNumber) +
+           GPBComputeRawVarint32SizeForInteger(size);
+  } else {
+    size_t size = 0;
+    for (id value in values) {
+      size += ComputeSerializedSizeIncludingTagOfObject(description, value);
+    }
+    return size;
+  }
+}
+
+static void WriteObjectIncludingTagToCodedOutputStream(
+    id object, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR)                      \
+  case GPBDataType##TYPE:                               \
+    [output write##TYPE:description->fieldNumber        \
+                  value:[(NSNumber *)object ACCESSOR]]; \
+    return;
+#define FIELD_CASE2(TYPE)                                       \
+  case GPBDataType##TYPE:                                       \
+    [output write##TYPE:description->fieldNumber value:object]; \
+    return;
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Group)
+    case GPBDataTypeMessage:
+      if (GPBExtensionIsWireFormat(description)) {
+        [output writeMessageSetExtension:description->fieldNumber value:object];
+      } else {
+        [output writeMessage:description->fieldNumber value:object];
+      }
+      return;
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteObjectNoTagToCodedOutputStream(
+    id object, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR)                             \
+  case GPBDataType##TYPE:                                      \
+    [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
+    return;
+#define FIELD_CASE2(TYPE)               \
+  case GPBDataType##TYPE:               \
+    [output write##TYPE##NoTag:object]; \
+    return;
+  switch (description->dataType) {
+    FIELD_CASE(Bool, boolValue)
+    FIELD_CASE(Float, floatValue)
+    FIELD_CASE(Double, doubleValue)
+    FIELD_CASE(Int32, intValue)
+    FIELD_CASE(SFixed32, intValue)
+    FIELD_CASE(SInt32, intValue)
+    FIELD_CASE(Enum, intValue)
+    FIELD_CASE(Int64, longLongValue)
+    FIELD_CASE(SInt64, longLongValue)
+    FIELD_CASE(SFixed64, longLongValue)
+    FIELD_CASE(UInt32, unsignedIntValue)
+    FIELD_CASE(Fixed32, unsignedIntValue)
+    FIELD_CASE(UInt64, unsignedLongLongValue)
+    FIELD_CASE(Fixed64, unsignedLongLongValue)
+    FIELD_CASE2(Bytes)
+    FIELD_CASE2(String)
+    FIELD_CASE2(Message)
+    case GPBDataTypeGroup:
+      [output writeGroupNoTag:description->fieldNumber value:object];
+      return;
+  }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteArrayIncludingTagsToCodedOutputStream(
+    NSArray *values, GPBExtensionDescription *description,
+    GPBCodedOutputStream *output) {
+  if (GPBExtensionIsPacked(description)) {
+    [output writeTag:description->fieldNumber
+              format:GPBWireFormatLengthDelimited];
+    size_t dataSize = 0;
+    size_t typeSize = DataTypeSize(description->dataType);
+    if (typeSize != 0) {
+      dataSize = values.count * typeSize;
+    } else {
+      for (id value in values) {
+        dataSize +=
+            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+      }
+    }
+    [output writeRawVarintSizeTAs32:dataSize];
+    for (id value in values) {
+      WriteObjectNoTagToCodedOutputStream(value, description, output);
+    }
+  } else {
+    for (id value in values) {
+      WriteObjectIncludingTagToCodedOutputStream(value, description, output);
+    }
+  }
+}
+
+void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
+                                      BOOL isPackedOnStream,
+                                      GPBCodedInputStream *input,
+                                      GPBExtensionRegistry *extensionRegistry,
+                                      GPBMessage *message) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  if (isPackedOnStream) {
+    NSCAssert(GPBExtensionIsRepeated(description),
+              @"How was it packed if it isn't repeated?");
+    int32_t length = GPBCodedInputStreamReadInt32(state);
+    size_t limit = GPBCodedInputStreamPushLimit(state, length);
+    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+      id value = NewSingleValueFromInputStream(extension,
+                                               input,
+                                               extensionRegistry,
+                                               nil);
+      [message addExtension:extension value:value];
+      [value release];
+    }
+    GPBCodedInputStreamPopLimit(state, limit);
+  } else {
+    id existingValue = nil;
+    BOOL isRepeated = GPBExtensionIsRepeated(description);
+    if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) {
+      existingValue = [message getExistingExtension:extension];
+    }
+    id value = NewSingleValueFromInputStream(extension,
+                                             input,
+                                             extensionRegistry,
+                                             existingValue);
+    if (isRepeated) {
+      [message addExtension:extension value:value];
+    } else {
+      [message setExtension:extension value:value];
+    }
+    [value release];
+  }
+}
+
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
+                                          id value,
+                                          GPBCodedOutputStream *output) {
+  GPBExtensionDescription *description = extension->description_;
+  if (GPBExtensionIsRepeated(description)) {
+    WriteArrayIncludingTagsToCodedOutputStream(value, description, output);
+  } else {
+    WriteObjectIncludingTagToCodedOutputStream(value, description, output);
+  }
+}
+
+size_t GPBComputeExtensionSerializedSizeIncludingTag(
+    GPBExtensionDescriptor *extension, id value) {
+  GPBExtensionDescription *description = extension->description_;
+  if (GPBExtensionIsRepeated(description)) {
+    return ComputeSerializedSizeIncludingTagOfArray(description, value);
+  } else {
+    return ComputeSerializedSizeIncludingTagOfObject(description, value);
+  }
+}
+
+// Note that this returns a retained value intentionally.
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBCodedInputStream *input,
+                                        GPBExtensionRegistry *extensionRegistry,
+                                        GPBMessage *existingValue) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  switch (description->dataType) {
+    case GPBDataTypeBool:     return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
+    case GPBDataTypeFixed32:  return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
+    case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
+    case GPBDataTypeFloat:    return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
+    case GPBDataTypeFixed64:  return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
+    case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
+    case GPBDataTypeDouble:   return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
+    case GPBDataTypeInt32:    return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
+    case GPBDataTypeInt64:    return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
+    case GPBDataTypeSInt32:   return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
+    case GPBDataTypeSInt64:   return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
+    case GPBDataTypeUInt32:   return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
+    case GPBDataTypeUInt64:   return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
+    case GPBDataTypeBytes:    return GPBCodedInputStreamReadRetainedBytes(state);
+    case GPBDataTypeString:   return GPBCodedInputStreamReadRetainedString(state);
+    case GPBDataTypeEnum:     return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage: {
+      GPBMessage *message;
+      if (existingValue) {
+        message = [existingValue retain];
+      } else {
+        GPBDescriptor *decriptor = [extension.msgClass descriptor];
+        message = [[decriptor.messageClass alloc] init];
+      }
+
+      if (description->dataType == GPBDataTypeGroup) {
+        [input readGroup:description->fieldNumber
+                 message:message
+            extensionRegistry:extensionRegistry];
+      } else {
+        // description->dataType == GPBDataTypeMessage
+        if (GPBExtensionIsWireFormat(description)) {
+          // For MessageSet fields the message length will have already been
+          // read.
+          [message mergeFromCodedInputStream:input
+                           extensionRegistry:extensionRegistry];
+        } else {
+          [input readMessage:message extensionRegistry:extensionRegistry];
+        }
+      }
+
+      return message;
+    }
+  }
+
+  return nil;
+}
diff --git a/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.h b/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.h
new file mode 100644
index 0000000..08a6472
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.h
@@ -0,0 +1,82 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+@class GPBDescriptor;
+@class GPBExtensionDescriptor;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A table of known extensions, searchable by name or field number.  When
+/// parsing a protocol message that might have extensions, you must provide a
+/// @c GPBExtensionRegistry in which you have registered any extensions that you
+/// want to be able to parse. Otherwise, those extensions will just be treated
+/// like unknown fields.
+///
+/// The @c *Root classes provide @c +extensionRegistry for the extensions defined
+/// in a given file *and* all files it imports. You can also create a
+/// @c GPBExtensionRegistry, and merge those registries to handle parsing
+/// extensions defined from non overlapping files.
+///
+/// @code
+/// GPBExtensionRegistry *registry =
+///     [[[MyProtoFileRoot extensionRegistry] copy] autorelease];
+/// [registry addExtension:[OtherMessage neededExtension];  // Not in MyProtoFile
+/// NSError *parseError = nil;
+/// MyMessage *msg = [MyMessage parseData:data
+///                     extensionRegistry:registry
+///                                 error:&parseError];
+/// @endcode
+@interface GPBExtensionRegistry : NSObject<NSCopying>
+
+/// Add the given @c GPBExtensionDescriptor to this registry.
+///
+/// @param extension The extension description to add.
+- (void)addExtension:(GPBExtensionDescriptor *)extension;
+
+/// Adds all the extensions from another registry to this registry.
+///
+/// @param registry The registry to merge into this registry.
+- (void)addExtensions:(GPBExtensionRegistry *)registry;
+
+/// Looks for the extension registered for the given field number on a given
+/// @c GPBDescriptor.
+///
+/// @param descriptor  The descriptor to look for a registered extension on.
+/// @param fieldNumber The field number of an extension to look for.
+///
+/// @return The registered @c GPBExtensionDescripto or nil if none was found.
+- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
+                                                fieldNumber:(NSInteger)fieldNumber;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.m b/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.m
new file mode 100644
index 0000000..df61a17
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBExtensionRegistry.m
@@ -0,0 +1,108 @@
+// 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.
+
+#import "GPBExtensionRegistry.h"
+
+#import "GPBBootstrap.h"
+#import "GPBDescriptor.h"
+
+@implementation GPBExtensionRegistry {
+  // TODO(dmaclach): Reimplement with CFDictionaries that don't use
+  // objects as keys.
+  NSMutableDictionary *mutableClassMap_;
+}
+
+- (instancetype)init {
+  if ((self = [super init])) {
+    mutableClassMap_ = [[NSMutableDictionary alloc] init];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [mutableClassMap_ release];
+  [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init];
+  if (result && mutableClassMap_.count) {
+    [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_];
+  }
+  return result;
+}
+
+- (NSMutableDictionary *)extensionMapForContainingMessageClass:
+        (Class)containingMessageClass {
+  NSMutableDictionary *extensionMap =
+      [mutableClassMap_ objectForKey:containingMessageClass];
+  if (extensionMap == nil) {
+    extensionMap = [NSMutableDictionary dictionary];
+    [mutableClassMap_ setObject:extensionMap
+                         forKey:(id<NSCopying>)containingMessageClass];
+  }
+  return extensionMap;
+}
+
+- (void)addExtension:(GPBExtensionDescriptor *)extension {
+  if (extension == nil) {
+    return;
+  }
+
+  Class containingMessageClass = extension.containingMessageClass;
+  NSMutableDictionary *extensionMap =
+      [self extensionMapForContainingMessageClass:containingMessageClass];
+  [extensionMap setObject:extension forKey:@(extension.fieldNumber)];
+}
+
+- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
+                                       fieldNumber:(NSInteger)fieldNumber {
+  Class messageClass = descriptor.messageClass;
+  NSDictionary *extensionMap =
+      [mutableClassMap_ objectForKey:messageClass];
+  return [extensionMap objectForKey:@(fieldNumber)];
+}
+
+- (void)addExtensions:(GPBExtensionRegistry *)registry {
+  if (registry == nil) {
+    // In the case where there are no extensions just ignore.
+    return;
+  }
+  NSMutableDictionary *otherClassMap = registry->mutableClassMap_;
+  for (Class containingMessageClass in otherClassMap) {
+    NSMutableDictionary *extensionMap =
+        [self extensionMapForContainingMessageClass:containingMessageClass];
+    NSMutableDictionary *otherExtensionMap =
+        [registry extensionMapForContainingMessageClass:containingMessageClass];
+    [extensionMap addEntriesFromDictionary:otherExtensionMap];
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBMessage.h b/src/third_party/protobuf-3/objectivec/GPBMessage.h
new file mode 100644
index 0000000..58c42d0
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBMessage.h
@@ -0,0 +1,308 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBBootstrap.h"
+
+@class GPBDescriptor;
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionDescriptor;
+@class GPBExtensionRegistry;
+@class GPBFieldDescriptor;
+@class GPBUnknownFieldSet;
+
+NS_ASSUME_NONNULL_BEGIN
+
+CF_EXTERN_C_BEGIN
+
+/// NSError domain used for errors.
+extern NSString *const GPBMessageErrorDomain;
+
+/// Error code for NSError with GPBMessageErrorDomain.
+typedef NS_ENUM(NSInteger, GPBMessageErrorCode) {
+  /// The data being parsed is bad and a message can not be created from it.
+  GPBMessageErrorCodeMalformedData = -100,
+  /// A message can't be serialized because it is missing required fields.
+  GPBMessageErrorCodeMissingRequiredField = -101,
+};
+
+#ifdef DEBUG
+/// In DEBUG ONLY, an NSException is thrown when a parsed message doesn't
+/// contain required fields. This key allows you to retrieve the parsed message
+/// from the exception's @c userInfo dictionary.
+extern NSString *const GPBExceptionMessageKey;
+#endif  // DEBUG
+
+CF_EXTERN_C_END
+
+/// Base class for all of the generated message classes.
+@interface GPBMessage : NSObject<NSSecureCoding, NSCopying>
+
+// NOTE: If you add a instance method/property to this class that may conflict
+// with methods declared in protos, you need to update objective_helpers.cc.
+// The main cases are methods that take no arguments, or setFoo:/hasFoo: type
+// methods.
+
+/// The unknown fields for this message.
+///
+/// Only messages from proto files declared with "proto2" syntax support unknown
+/// fields. For "proto3" syntax, any unknown fields found while parsing are
+/// dropped.
+@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields;
+
+/// Are all required fields set in the message and all embedded messages.
+@property(nonatomic, readonly, getter=isInitialized) BOOL initialized;
+
+/// Returns an autoreleased instance.
++ (instancetype)message;
+
+/// Creates a new instance by parsing the data. This method should be sent to
+/// the generated message class that the data should be interpreted as. If
+/// there is an error the method returns nil and the error is returned in
+/// errorPtr (when provided).
+///
+/// @note In DEBUG builds, the parsed message is checked to be sure all required
+///       fields were provided, and the parse will fail if some are missing.
+///
+/// @param data     The data to parse.
+/// @param errorPtr An optional error pointer to fill in with a failure reason if
+///                 the data can not be parsed.
+///
+/// @return A new instance of the class messaged.
++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr;
+
+/// Creates a new instance by parsing the data. This method should be sent to
+/// the generated message class that the data should be interpreted as. If
+/// there is an error the method returns nil and the error is returned in
+/// errorPtr (when provided).
+///
+/// @note In DEBUG builds, the parsed message is checked to be sure all required
+///       fields were provided, and the parse will fail if some are missing.
+///
+/// @param data              The data to parse.
+/// @param extensionRegistry The extension registry to use to look up extensions.
+/// @param errorPtr          An optional error pointer to fill in with a failure
+///                          reason if the data can not be parsed.
+///
+/// @return A new instance of the class messaged.
++ (instancetype)parseFromData:(NSData *)data
+            extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
+                        error:(NSError **)errorPtr;
+
+/// Creates a new instance by parsing the data from the given input stream. This
+/// method should be sent to the generated message class that the data should
+/// be interpreted as. If there is an error the method returns nil and the error
+/// is returned in errorPtr (when provided).
+///
+/// @note In DEBUG builds, the parsed message is checked to be sure all required
+///       fields were provided, and the parse will fail if some are missing.
+///
+/// @param input             The stream to read data from.
+/// @param extensionRegistry The extension registry to use to look up extensions.
+/// @param errorPtr          An optional error pointer to fill in with a failure
+///                          reason if the data can not be parsed.
+///
+/// @return A new instance of the class messaged.
++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
+                        extensionRegistry:
+                            (nullable GPBExtensionRegistry *)extensionRegistry
+                                    error:(NSError **)errorPtr;
+
+/// Creates a new instance by parsing the data from the given input stream. This
+/// method should be sent to the generated message class that the data should
+/// be interpreted as. If there is an error the method returns nil and the error
+/// is returned in errorPtr (when provided).
+///
+/// @note Unlike the parseFrom... methods, this never checks to see if all of
+///       the required fields are set. So this method can be used to reload
+///       messages that may not be complete.
+///
+/// @param input             The stream to read data from.
+/// @param extensionRegistry The extension registry to use to look up extensions.
+/// @param errorPtr          An optional error pointer to fill in with a failure
+///                          reason if the data can not be parsed.
+///
+/// @return A new instance of the class messaged.
++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+                                 extensionRegistry:
+                                     (nullable GPBExtensionRegistry *)extensionRegistry
+                                             error:(NSError **)errorPtr;
+
+/// Initializes an instance by parsing the data. This method should be sent to
+/// the generated message class that the data should be interpreted as. If
+/// there is an error the method returns nil and the error is returned in
+/// errorPtr (when provided).
+///
+/// @note In DEBUG builds, the parsed message is checked to be sure all required
+///       fields were provided, and the parse will fail if some are missing.
+///
+/// @param data     The data to parse.
+/// @param errorPtr An optional error pointer to fill in with a failure reason if
+///                 the data can not be parsed.
+- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr;
+
+/// Initializes an instance by parsing the data. This method should be sent to
+/// the generated message class that the data should be interpreted as. If
+/// there is an error the method returns nil and the error is returned in
+/// errorPtr (when provided).
+///
+/// @note In DEBUG builds, the parsed message is checked to be sure all required
+///       fields were provided, and the parse will fail if some are missing.
+///
+/// @param data              The data to parse.
+/// @param extensionRegistry The extension registry to use to look up extensions.
+/// @param errorPtr          An optional error pointer to fill in with a failure
+///                          reason if the data can not be parsed.
+- (instancetype)initWithData:(NSData *)data
+           extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
+                       error:(NSError **)errorPtr;
+
+/// Initializes an instance by parsing the data from the given input stream. This
+/// method should be sent to the generated message class that the data should
+/// be interpreted as. If there is an error the method returns nil and the error
+/// is returned in errorPtr (when provided).
+///
+/// @note Unlike the parseFrom... methods, this never checks to see if all of
+///       the required fields are set. So this method can be used to reload
+///       messages that may not be complete.
+///
+/// @param input             The stream to read data from.
+/// @param extensionRegistry The extension registry to use to look up extensions.
+/// @param errorPtr          An optional error pointer to fill in with a failure
+///                          reason if the data can not be parsed.
+- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
+                       extensionRegistry:
+                           (nullable GPBExtensionRegistry *)extensionRegistry
+                                   error:(NSError **)errorPtr;
+
+/// Writes out the message to the given output stream.
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
+/// Writes out the message to the given output stream.
+- (void)writeToOutputStream:(NSOutputStream *)output;
+
+/// Writes out a varint for the message size followed by the the message to
+/// the given output stream.
+- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output;
+/// Writes out a varint for the message size followed by the the message to
+/// the given output stream.
+- (void)writeDelimitedToOutputStream:(NSOutputStream *)output;
+
+/// Serializes the message to a @c NSData.
+///
+/// If there is an error while generating the data, nil is returned.
+///
+/// @note This value is not cached, so if you are using it repeatedly, cache
+///       it yourself.
+///
+/// @note In DEBUG ONLY, the message is also checked for all required field,
+///       if one is missing, nil will be returned.
+- (nullable NSData *)data;
+
+/// Serializes a varint with the message size followed by the message data,
+/// returning that as a @c NSData.
+///
+/// @note This value is not cached, so if you are using it repeatedly, cache
+///       it yourself.
+- (NSData *)delimitedData;
+
+/// Calculates the size of the object if it were serialized.
+///
+/// This is not a cached value. If you are following a pattern like this:
+/// @code
+///   size_t size = [aMsg serializedSize];
+///   NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+///   [foo writeSize:size];
+///   [foo appendData:[aMsg data]];
+/// @endcode
+/// you would be better doing:
+/// @code
+///   NSData *data = [aMsg data];
+///   NSUInteger size = [aMsg length];
+///   NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+///   [foo writeSize:size];
+///   [foo appendData:data];
+/// @endcode
+- (size_t)serializedSize;
+
+/// Return the descriptor for the message class.
++ (GPBDescriptor *)descriptor;
+/// Return the descriptor for the message.
+- (GPBDescriptor *)descriptor;
+
+/// Test to see if the given extension is set on the message.
+- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension;
+
+/// Fetches the given extension's value for this message.
+///
+/// Extensions use boxed values (NSNumbers) for PODs and NSMutableArrays for
+/// repeated fields. If the extension is a Message one will be auto created for you
+/// and returned similar to fields.
+- (nullable id)getExtension:(GPBExtensionDescriptor *)extension;
+
+/// Sets the given extension's value for this message. This is only for single
+/// field extensions (i.e. - not repeated fields).
+///
+/// Extensions use boxed values (@c NSNumbers).
+- (void)setExtension:(GPBExtensionDescriptor *)extension value:(nullable id)value;
+
+/// Adds the given value to the extension for this message. This is only for
+/// repeated field extensions. If the field is a repeated POD type the @c value
+/// is a @c NSNumber.
+- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value;
+
+/// Replaces the given value at an index for the extension on this message. This
+/// is only for repeated field extensions. If the field is a repeated POD type
+/// the @c value is a @c NSNumber.
+- (void)setExtension:(GPBExtensionDescriptor *)extension
+               index:(NSUInteger)index
+               value:(id)value;
+
+/// Clears the given extension for this message.
+- (void)clearExtension:(GPBExtensionDescriptor *)extension;
+
+/// Resets all of the fields of this message to their default values.
+- (void)clear;
+
+/// Parses a message of this type from the input and merges it with this
+/// message.
+///
+/// @note This will throw if there is an error parsing the data.
+- (void)mergeFromData:(NSData *)data
+    extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
+
+/// Merges the fields from another message (of the same type) into this
+/// message.
+- (void)mergeFrom:(GPBMessage *)other;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBMessage.m b/src/third_party/protobuf-3/objectivec/GPBMessage.m
new file mode 100644
index 0000000..8134e25
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBMessage.m
@@ -0,0 +1,3184 @@
+// 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.
+
+#import "GPBMessage_PackagePrivate.h"
+
+#import <objc/runtime.h>
+#import <objc/message.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBExtensionInternals.h"
+#import "GPBExtensionRegistry.h"
+#import "GPBRootObject_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+NSString *const GPBMessageErrorDomain =
+    GPBNSStringifySymbol(GPBMessageErrorDomain);
+
+#ifdef DEBUG
+NSString *const GPBExceptionMessageKey =
+    GPBNSStringifySymbol(GPBExceptionMessage);
+#endif  // DEBUG
+
+static NSString *const kGPBDataCoderKey = @"GPBData";
+
+//
+// PLEASE REMEMBER:
+//
+// This is the base class for *all* messages generated, so any selector defined,
+// *public* or *private* could end up colliding with a proto message field. So
+// avoid using selectors that could match a property, use C functions to hide
+// them, etc.
+//
+
+@interface GPBMessage () {
+ @package
+  GPBUnknownFieldSet *unknownFields_;
+  NSMutableDictionary *extensionMap_;
+  NSMutableDictionary *autocreatedExtensionMap_;
+
+  // If the object was autocreated, we remember the creator so that if we get
+  // mutated, we can inform the creator to make our field visible.
+  GPBMessage *autocreator_;
+  GPBFieldDescriptor *autocreatorField_;
+  GPBExtensionDescriptor *autocreatorExtension_;
+}
+@end
+
+static id CreateArrayForField(GPBFieldDescriptor *field,
+                              GPBMessage *autocreator)
+    __attribute__((ns_returns_retained));
+static id GetOrCreateArrayIvarWithField(GPBMessage *self,
+                                        GPBFieldDescriptor *field,
+                                        GPBFileSyntax syntax);
+static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
+static id CreateMapForField(GPBFieldDescriptor *field,
+                            GPBMessage *autocreator)
+    __attribute__((ns_returns_retained));
+static id GetOrCreateMapIvarWithField(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      GPBFileSyntax syntax);
+static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
+                                              NSZone *zone)
+    __attribute__((ns_returns_retained));
+
+static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
+  return [NSError errorWithDomain:GPBMessageErrorDomain
+                             code:code
+                         userInfo:userInfo];
+}
+
+static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) {
+  NSDictionary *userInfo = nil;
+  if ([reason length]) {
+    userInfo = @{ @"Reason" : reason };
+  }
+  return MessageError(code, userInfo);
+}
+
+
+static void CheckExtension(GPBMessage *self,
+                           GPBExtensionDescriptor *extension) {
+  if ([self class] != extension.containingMessageClass) {
+    [NSException
+         raise:NSInvalidArgumentException
+        format:@"Extension %@ used on wrong class (%@ instead of %@)",
+               extension.singletonName,
+               [self class], extension.containingMessageClass];
+  }
+}
+
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
+                                              NSZone *zone) {
+  if (extensionMap.count == 0) {
+    return nil;
+  }
+  NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
+      initWithCapacity:extensionMap.count];
+
+  for (GPBExtensionDescriptor *extension in extensionMap) {
+    id value = [extensionMap objectForKey:extension];
+    BOOL isMessageExtension = GPBExtensionIsMessage(extension);
+
+    if (extension.repeated) {
+      if (isMessageExtension) {
+        NSMutableArray *list =
+            [[NSMutableArray alloc] initWithCapacity:[value count]];
+        for (GPBMessage *listValue in value) {
+          GPBMessage *copiedValue = [listValue copyWithZone:zone];
+          [list addObject:copiedValue];
+          [copiedValue release];
+        }
+        [result setObject:list forKey:extension];
+        [list release];
+      } else {
+        NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
+        [result setObject:copiedValue forKey:extension];
+        [copiedValue release];
+      }
+    } else {
+      if (isMessageExtension) {
+        GPBMessage *copiedValue = [value copyWithZone:zone];
+        [result setObject:copiedValue forKey:extension];
+        [copiedValue release];
+      } else {
+        [result setObject:value forKey:extension];
+      }
+    }
+  }
+
+  return result;
+}
+
+static id CreateArrayForField(GPBFieldDescriptor *field,
+                              GPBMessage *autocreator) {
+  id result;
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+    case GPBDataTypeBool:
+      result = [[GPBBoolArray alloc] init];
+      break;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      result = [[GPBUInt32Array alloc] init];
+      break;
+    case GPBDataTypeInt32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeSInt32:
+      result = [[GPBInt32Array alloc] init];
+      break;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      result = [[GPBUInt64Array alloc] init];
+      break;
+    case GPBDataTypeInt64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeSInt64:
+      result = [[GPBInt64Array alloc] init];
+      break;
+    case GPBDataTypeFloat:
+      result = [[GPBFloatArray alloc] init];
+      break;
+    case GPBDataTypeDouble:
+      result = [[GPBDoubleArray alloc] init];
+      break;
+
+    case GPBDataTypeEnum:
+      result = [[GPBEnumArray alloc]
+                  initWithValidationFunction:field.enumDescriptor.enumVerifier];
+      break;
+
+    case GPBDataTypeBytes:
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
+    case GPBDataTypeString:
+      if (autocreator) {
+        result = [[GPBAutocreatedArray alloc] init];
+      } else {
+        result = [[NSMutableArray alloc] init];
+      }
+      break;
+  }
+
+  if (autocreator) {
+    if (GPBDataTypeIsObject(fieldDataType)) {
+      GPBAutocreatedArray *autoArray = result;
+      autoArray->_autocreator =  autocreator;
+    } else {
+      GPBInt32Array *gpbArray = result;
+      gpbArray->_autocreator = autocreator;
+    }
+  }
+
+  return result;
+}
+
+static id CreateMapForField(GPBFieldDescriptor *field,
+                            GPBMessage *autocreator) {
+  id result;
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  switch (keyDataType) {
+    case GPBDataTypeBool:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBBoolBoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBBoolUInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBBoolInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBBoolUInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBBoolInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBBoolFloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBBoolDoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBBoolEnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          result = [[GPBBoolObjectDictionary alloc] init];
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBUInt32BoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBUInt32UInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBUInt32Int32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBUInt32UInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBUInt32Int64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBUInt32FloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBUInt32DoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBUInt32EnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          result = [[GPBUInt32ObjectDictionary alloc] init];
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+    case GPBDataTypeInt32:
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeSInt32:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBInt32BoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBInt32UInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBInt32Int32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBInt32UInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBInt32Int64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBInt32FloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBInt32DoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBInt32EnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          result = [[GPBInt32ObjectDictionary alloc] init];
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBUInt64BoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBUInt64UInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBUInt64Int32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBUInt64UInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBUInt64Int64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBUInt64FloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBUInt64DoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBUInt64EnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          result = [[GPBUInt64ObjectDictionary alloc] init];
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+    case GPBDataTypeInt64:
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeSInt64:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBInt64BoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBInt64UInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBInt64Int32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBInt64UInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBInt64Int64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBInt64FloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBInt64DoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBInt64EnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          result = [[GPBInt64ObjectDictionary alloc] init];
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+    case GPBDataTypeString:
+      switch (valueDataType) {
+        case GPBDataTypeBool:
+          result = [[GPBStringBoolDictionary alloc] init];
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          result = [[GPBStringUInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt32:
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeSInt32:
+          result = [[GPBStringInt32Dictionary alloc] init];
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          result = [[GPBStringUInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeInt64:
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeSInt64:
+          result = [[GPBStringInt64Dictionary alloc] init];
+          break;
+        case GPBDataTypeFloat:
+          result = [[GPBStringFloatDictionary alloc] init];
+          break;
+        case GPBDataTypeDouble:
+          result = [[GPBStringDoubleDictionary alloc] init];
+          break;
+        case GPBDataTypeEnum:
+          result = [[GPBStringEnumDictionary alloc]
+              initWithValidationFunction:field.enumDescriptor.enumVerifier];
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeMessage:
+        case GPBDataTypeString:
+          if (autocreator) {
+            result = [[GPBAutocreatedDictionary alloc] init];
+          } else {
+            result = [[NSMutableDictionary alloc] init];
+          }
+          break;
+        case GPBDataTypeGroup:
+          NSCAssert(NO, @"shouldn't happen");
+          return nil;
+      }
+      break;
+
+    case GPBDataTypeFloat:
+    case GPBDataTypeDouble:
+    case GPBDataTypeEnum:
+    case GPBDataTypeBytes:
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage:
+      NSCAssert(NO, @"shouldn't happen");
+      return nil;
+  }
+
+  if (autocreator) {
+    if ((keyDataType == GPBDataTypeString) &&
+        GPBDataTypeIsObject(valueDataType)) {
+      GPBAutocreatedDictionary *autoDict = result;
+      autoDict->_autocreator =  autocreator;
+    } else {
+      GPBInt32Int32Dictionary *gpbDict = result;
+      gpbDict->_autocreator = autocreator;
+    }
+  }
+
+  return result;
+}
+
+#if !defined(__clang_analyzer__)
+// These functions are blocked from the analyzer because the analyzer sees the
+// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
+// so use of the array/map after the call returns is flagged as a use after
+// free.
+// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
+// count be holding onto the object (it is transfering it), the object is
+// still valid after returning from the call.  The other way to avoid this
+// would be to add a -retain/-autorelease, but that would force every
+// repeated/map field parsed into the autorelease pool which is both a memory
+// and performance hit.
+
+static id GetOrCreateArrayIvarWithField(GPBMessage *self,
+                                        GPBFieldDescriptor *field,
+                                        GPBFileSyntax syntax) {
+  id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+  if (!array) {
+    // No lock needed, this is called from places expecting to mutate
+    // so no threading protection is needed.
+    array = CreateArrayForField(field, nil);
+    GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
+  }
+  return array;
+}
+
+// This is like GPBGetObjectIvarWithField(), but for arrays, it should
+// only be used to wire the method into the class.
+static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+  id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+  if (!array) {
+    // Check again after getting the lock.
+    GPBPrepareReadOnlySemaphore(self);
+    dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
+    array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+    if (!array) {
+      array = CreateArrayForField(field, self);
+      GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
+    }
+    dispatch_semaphore_signal(self->readOnlySemaphore_);
+  }
+  return array;
+}
+
+static id GetOrCreateMapIvarWithField(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      GPBFileSyntax syntax) {
+  id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+  if (!dict) {
+    // No lock needed, this is called from places expecting to mutate
+    // so no threading protection is needed.
+    dict = CreateMapForField(field, nil);
+    GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
+  }
+  return dict;
+}
+
+// This is like GPBGetObjectIvarWithField(), but for maps, it should
+// only be used to wire the method into the class.
+static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+  id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+  if (!dict) {
+    // Check again after getting the lock.
+    GPBPrepareReadOnlySemaphore(self);
+    dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
+    dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+    if (!dict) {
+      dict = CreateMapForField(field, self);
+      GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
+    }
+    dispatch_semaphore_signal(self->readOnlySemaphore_);
+  }
+  return dict;
+}
+
+#endif  // !defined(__clang_analyzer__)
+
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
+                                            GPBMessage *autocreator,
+                                            GPBFieldDescriptor *field) {
+  GPBMessage *message = [[msgClass alloc] init];
+  message->autocreator_ = autocreator;
+  message->autocreatorField_ = [field retain];
+  return message;
+}
+
+static GPBMessage *CreateMessageWithAutocreatorForExtension(
+    Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension)
+    __attribute__((ns_returns_retained));
+
+static GPBMessage *CreateMessageWithAutocreatorForExtension(
+    Class msgClass, GPBMessage *autocreator,
+    GPBExtensionDescriptor *extension) {
+  GPBMessage *message = [[msgClass alloc] init];
+  message->autocreator_ = autocreator;
+  message->autocreatorExtension_ = [extension retain];
+  return message;
+}
+
+BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) {
+  return (message->autocreator_ == parent);
+}
+
+void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
+  // Message objects that are implicitly created by accessing a message field
+  // are initially not visible via the hasX selector. This method makes them
+  // visible.
+  if (self->autocreator_) {
+    // This will recursively make all parent messages visible until it reaches a
+    // super-creator that's visible.
+    if (self->autocreatorField_) {
+      GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
+      GPBSetObjectIvarWithFieldInternal(self->autocreator_,
+                                        self->autocreatorField_, self, syntax);
+    } else {
+      [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
+    }
+  }
+}
+
+void GPBAutocreatedArrayModified(GPBMessage *self, id array) {
+  // When one of our autocreated arrays adds elements, make it visible.
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (field.fieldType == GPBFieldTypeRepeated) {
+      id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      if (curArray == array) {
+        if (GPBFieldDataTypeIsObject(field)) {
+          GPBAutocreatedArray *autoArray = array;
+          autoArray->_autocreator = nil;
+        } else {
+          GPBInt32Array *gpbArray = array;
+          gpbArray->_autocreator = nil;
+        }
+        GPBBecomeVisibleToAutocreator(self);
+        return;
+      }
+    }
+  }
+  NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self);
+}
+
+void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) {
+  // When one of our autocreated dicts adds elements, make it visible.
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (field.fieldType == GPBFieldTypeMap) {
+      id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      if (curDict == dictionary) {
+        if ((field.mapKeyDataType == GPBDataTypeString) &&
+            GPBFieldDataTypeIsObject(field)) {
+          GPBAutocreatedDictionary *autoDict = dictionary;
+          autoDict->_autocreator = nil;
+        } else {
+          GPBInt32Int32Dictionary *gpbDict = dictionary;
+          gpbDict->_autocreator = nil;
+        }
+        GPBBecomeVisibleToAutocreator(self);
+        return;
+      }
+    }
+  }
+  NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self);
+}
+
+void GPBClearMessageAutocreator(GPBMessage *self) {
+  if ((self == nil) || !self->autocreator_) {
+    return;
+  }
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+  // Either the autocreator must have its "has" flag set to YES, or it must be
+  // NO and not equal to ourselves.
+  BOOL autocreatorHas =
+      (self->autocreatorField_
+           ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
+           : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
+  GPBMessage *autocreatorFieldValue =
+      (self->autocreatorField_
+           ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_,
+                                                   self->autocreatorField_)
+           : [self->autocreator_->autocreatedExtensionMap_
+                 objectForKey:self->autocreatorExtension_]);
+  NSCAssert(autocreatorHas || autocreatorFieldValue != self,
+            @"Cannot clear autocreator because it still refers to self, self: %@.",
+            self);
+
+#endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+
+  self->autocreator_ = nil;
+  [self->autocreatorField_ release];
+  self->autocreatorField_ = nil;
+  [self->autocreatorExtension_ release];
+  self->autocreatorExtension_ = nil;
+}
+
+static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
+  if (!self->unknownFields_) {
+    self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
+    GPBBecomeVisibleToAutocreator(self);
+  }
+  return self->unknownFields_;
+}
+
+@implementation GPBMessage
+
++ (void)initialize {
+  Class pbMessageClass = [GPBMessage class];
+  if ([self class] == pbMessageClass) {
+    // This is here to start up the "base" class descriptor.
+    [self descriptor];
+    // Message shares extension method resolving with GPBRootObject so insure
+    // it is started up at the same time.
+    (void)[GPBRootObject class];
+  } else if ([self superclass] == pbMessageClass) {
+    // This is here to start up all the "message" subclasses. Just needs to be
+    // done for the messages, not any of the subclasses.
+    // This must be done in initialize to enforce thread safety of start up of
+    // the protocol buffer library.
+    // Note: The generated code for -descriptor calls
+    // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject
+    // subclass for the file.  That call chain is what ensures that *Root class
+    // is started up to support extension resolution off the message class
+    // (+resolveClassMethod: below) in a thread safe manner.
+    [self descriptor];
+  }
+}
+
++ (instancetype)allocWithZone:(NSZone *)zone {
+  // Override alloc to allocate our classes with the additional storage
+  // required for the instance variables.
+  GPBDescriptor *descriptor = [self descriptor];
+  return NSAllocateObject(self, descriptor->storageSize_, zone);
+}
+
++ (instancetype)alloc {
+  return [self allocWithZone:nil];
+}
+
++ (GPBDescriptor *)descriptor {
+  // This is thread safe because it is called from +initialize.
+  static GPBDescriptor *descriptor = NULL;
+  static GPBFileDescriptor *fileDescriptor = NULL;
+  if (!descriptor) {
+    // Use a dummy file that marks it as proto2 syntax so when used generically
+    // it supports unknowns/etc.
+    fileDescriptor =
+        [[GPBFileDescriptor alloc] initWithPackage:@"internal"
+                                            syntax:GPBFileSyntaxProto2];
+
+    descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class]
+                                              rootClass:Nil
+                                                   file:fileDescriptor
+                                                 fields:NULL
+                                             fieldCount:0
+                                            storageSize:0
+                                                  flags:0];
+  }
+  return descriptor;
+}
+
++ (instancetype)message {
+  return [[[self alloc] init] autorelease];
+}
+
+- (instancetype)init {
+  if ((self = [super init])) {
+    messageStorage_ = (GPBMessage_StoragePtr)(
+        ((uint8_t *)self) + class_getInstanceSize([self class]));
+  }
+
+  return self;
+}
+
+- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr {
+  return [self initWithData:data extensionRegistry:nil error:errorPtr];
+}
+
+- (instancetype)initWithData:(NSData *)data
+           extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                       error:(NSError **)errorPtr {
+  if ((self = [self init])) {
+    @try {
+      [self mergeFromData:data extensionRegistry:extensionRegistry];
+      if (errorPtr) {
+        *errorPtr = nil;
+      }
+    }
+    @catch (NSException *exception) {
+      [self release];
+      self = nil;
+      if (errorPtr) {
+        *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
+                                           exception.reason);
+      }
+    }
+#ifdef DEBUG
+    if (self && !self.initialized) {
+      [self release];
+      self = nil;
+      if (errorPtr) {
+        *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
+      }
+    }
+#endif
+  }
+  return self;
+}
+
+- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
+                       extensionRegistry:
+                           (GPBExtensionRegistry *)extensionRegistry
+                                   error:(NSError **)errorPtr {
+  if ((self = [self init])) {
+    @try {
+      [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+      if (errorPtr) {
+        *errorPtr = nil;
+      }
+    }
+    @catch (NSException *exception) {
+      [self release];
+      self = nil;
+      if (errorPtr) {
+        *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
+                                           exception.reason);
+      }
+    }
+#ifdef DEBUG
+    if (self && !self.initialized) {
+      [self release];
+      self = nil;
+      if (errorPtr) {
+        *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
+      }
+    }
+#endif
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self internalClear:NO];
+  NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
+  if (readOnlySemaphore_) {
+    dispatch_release(readOnlySemaphore_);
+  }
+  [super dealloc];
+}
+
+- (void)copyFieldsInto:(GPBMessage *)message
+                  zone:(NSZone *)zone
+            descriptor:(GPBDescriptor *)descriptor {
+  // Copy all the storage...
+  memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
+
+  GPBFileSyntax syntax = descriptor.file.syntax;
+
+  // Loop over the fields doing fixup...
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (GPBFieldIsMapOrArray(field)) {
+      id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      if (value) {
+        // We need to copy the array/map, but the catch is for message fields,
+        // we also need to ensure all the messages as those need copying also.
+        id newValue;
+        if (GPBFieldDataTypeIsMessage(field)) {
+          if (field.fieldType == GPBFieldTypeRepeated) {
+            NSArray *existingArray = (NSArray *)value;
+            NSMutableArray *newArray =
+                [[NSMutableArray alloc] initWithCapacity:existingArray.count];
+            newValue = newArray;
+            for (GPBMessage *msg in existingArray) {
+              GPBMessage *copiedMsg = [msg copyWithZone:zone];
+              [newArray addObject:copiedMsg];
+              [copiedMsg release];
+            }
+          } else {
+            if (field.mapKeyDataType == GPBDataTypeString) {
+              // Map is an NSDictionary.
+              NSDictionary *existingDict = value;
+              NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
+                  initWithCapacity:existingDict.count];
+              newValue = newDict;
+              [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key,
+                                                                GPBMessage *msg,
+                                                                BOOL *stop) {
+#pragma unused(stop)
+                GPBMessage *copiedMsg = [msg copyWithZone:zone];
+                [newDict setObject:copiedMsg forKey:key];
+                [copiedMsg release];
+              }];
+            } else {
+              // Is one of the GPB*ObjectDictionary classes.  Type doesn't
+              // matter, just need one to invoke the selector.
+              GPBInt32ObjectDictionary *existingDict = value;
+              newValue = [existingDict deepCopyWithZone:zone];
+            }
+          }
+        } else {
+          // Not messages (but is a map/array)...
+          if (field.fieldType == GPBFieldTypeRepeated) {
+            if (GPBFieldDataTypeIsObject(field)) {
+              // NSArray
+              newValue = [value mutableCopyWithZone:zone];
+            } else {
+              // GPB*Array
+              newValue = [value copyWithZone:zone];
+            }
+          } else {
+            if (field.mapKeyDataType == GPBDataTypeString) {
+              // NSDictionary
+              newValue = [value mutableCopyWithZone:zone];
+            } else {
+              // Is one of the GPB*Dictionary classes.  Type doesn't matter,
+              // just need one to invoke the selector.
+              GPBInt32Int32Dictionary *existingDict = value;
+              newValue = [existingDict copyWithZone:zone];
+            }
+          }
+        }
+        // We retain here because the memcpy picked up the pointer value and
+        // the next call to SetRetainedObject... will release the current value.
+        [value retain];
+        GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+                                                  syntax);
+      }
+    } else if (GPBFieldDataTypeIsMessage(field)) {
+      // For object types, if we have a value, copy it.  If we don't,
+      // zero it to remove the pointer to something that was autocreated
+      // (and the ptr just got memcpyed).
+      if (GPBGetHasIvarField(self, field)) {
+        GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        GPBMessage *newValue = [value copyWithZone:zone];
+        // We retain here because the memcpy picked up the pointer value and
+        // the next call to SetRetainedObject... will release the current value.
+        [value retain];
+        GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+                                                  syntax);
+      } else {
+        uint8_t *storage = (uint8_t *)message->messageStorage_;
+        id *typePtr = (id *)&storage[field->description_->offset];
+        *typePtr = NULL;
+      }
+    } else if (GPBFieldDataTypeIsObject(field) &&
+               GPBGetHasIvarField(self, field)) {
+      // A set string/data value (message picked off above), copy it.
+      id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      id newValue = [value copyWithZone:zone];
+      // We retain here because the memcpy picked up the pointer value and
+      // the next call to SetRetainedObject... will release the current value.
+      [value retain];
+      GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+                                                syntax);
+    } else {
+      // memcpy took care of the rest of the primitive fields if they were set.
+    }
+  }  // for (field in descriptor->fields_)
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  GPBDescriptor *descriptor = [self descriptor];
+  GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
+
+  [self copyFieldsInto:result zone:zone descriptor:descriptor];
+  // Make immutable copies of the extra bits.
+  result->unknownFields_ = [unknownFields_ copyWithZone:zone];
+  result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
+  return result;
+}
+
+- (void)clear {
+  [self internalClear:YES];
+}
+
+- (void)internalClear:(BOOL)zeroStorage {
+  GPBDescriptor *descriptor = [self descriptor];
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (GPBFieldIsMapOrArray(field)) {
+      id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      if (arrayOrMap) {
+        if (field.fieldType == GPBFieldTypeRepeated) {
+          if (GPBFieldDataTypeIsObject(field)) {
+            GPBAutocreatedArray *autoArray = arrayOrMap;
+            if (autoArray->_autocreator == self) {
+              autoArray->_autocreator = nil;
+            }
+          } else {
+            // Type doesn't matter, it is a GPB*Array.
+            GPBInt32Array *gpbArray = arrayOrMap;
+            if (gpbArray->_autocreator == self) {
+              gpbArray->_autocreator = nil;
+            }
+          }
+        } else {
+          if ((field.mapKeyDataType == GPBDataTypeString) &&
+              GPBFieldDataTypeIsObject(field)) {
+            GPBAutocreatedDictionary *autoDict = arrayOrMap;
+            if (autoDict->_autocreator == self) {
+              autoDict->_autocreator = nil;
+            }
+          } else {
+            // Type doesn't matter, it is a GPB*Dictionary.
+            GPBInt32Int32Dictionary *gpbDict = arrayOrMap;
+            if (gpbDict->_autocreator == self) {
+              gpbDict->_autocreator = nil;
+            }
+          }
+        }
+        [arrayOrMap release];
+      }
+    } else if (GPBFieldDataTypeIsMessage(field)) {
+      GPBClearAutocreatedMessageIvarWithField(self, field);
+      GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      [value release];
+    } else if (GPBFieldDataTypeIsObject(field) &&
+               GPBGetHasIvarField(self, field)) {
+      id value = GPBGetObjectIvarWithField(self, field);
+      [value release];
+    }
+  }
+
+  // GPBClearMessageAutocreator() expects that its caller has already been
+  // removed from autocreatedExtensionMap_ so we set to nil first.
+  NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues];
+  [autocreatedExtensionMap_ release];
+  autocreatedExtensionMap_ = nil;
+
+  // Since we're clearing all of our extensions, make sure that we clear the
+  // autocreator on any that we've created so they no longer refer to us.
+  for (GPBMessage *value in autocreatedValues) {
+    NSCAssert(GPBWasMessageAutocreatedBy(value, self),
+              @"Autocreated extension does not refer back to self.");
+    GPBClearMessageAutocreator(value);
+  }
+
+  [extensionMap_ release];
+  extensionMap_ = nil;
+  [unknownFields_ release];
+  unknownFields_ = nil;
+
+  // Note that clearing does not affect autocreator_. If we are being cleared
+  // because of a dealloc, then autocreator_ should be nil anyway. If we are
+  // being cleared because someone explicitly clears us, we don't want to
+  // sever our relationship with our autocreator.
+
+  if (zeroStorage) {
+    memset(messageStorage_, 0, descriptor->storageSize_);
+  }
+}
+
+- (BOOL)isInitialized {
+  GPBDescriptor *descriptor = [self descriptor];
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (field.isRequired) {
+      if (!GPBGetHasIvarField(self, field)) {
+        return NO;
+      }
+    }
+    if (GPBFieldDataTypeIsMessage(field)) {
+      GPBFieldType fieldType = field.fieldType;
+      if (fieldType == GPBFieldTypeSingle) {
+        if (field.isRequired) {
+          GPBMessage *message = GPBGetMessageMessageField(self, field);
+          if (!message.initialized) {
+            return NO;
+          }
+        } else {
+          NSAssert(field.isOptional,
+                   @"%@: Single message field %@ not required or optional?",
+                   [self class], field.name);
+          if (GPBGetHasIvarField(self, field)) {
+            GPBMessage *message = GPBGetMessageMessageField(self, field);
+            if (!message.initialized) {
+              return NO;
+            }
+          }
+        }
+      } else if (fieldType == GPBFieldTypeRepeated) {
+        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        for (GPBMessage *message in array) {
+          if (!message.initialized) {
+            return NO;
+          }
+        }
+      } else {  // fieldType == GPBFieldTypeMap
+        if (field.mapKeyDataType == GPBDataTypeString) {
+          NSDictionary *map =
+              GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+          if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
+            return NO;
+          }
+        } else {
+          // Real type is GPB*ObjectDictionary, exact type doesn't matter.
+          GPBInt32ObjectDictionary *map =
+              GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+          if (map && ![map isInitialized]) {
+            return NO;
+          }
+        }
+      }
+    }
+  }
+
+  __block BOOL result = YES;
+  [extensionMap_
+      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension,
+                                          id obj,
+                                          BOOL *stop) {
+        if (GPBExtensionIsMessage(extension)) {
+          if (extension.isRepeated) {
+            for (GPBMessage *msg in obj) {
+              if (!msg.initialized) {
+                result = NO;
+                *stop = YES;
+                break;
+              }
+            }
+          } else {
+            GPBMessage *asMsg = obj;
+            if (!asMsg.initialized) {
+              result = NO;
+              *stop = YES;
+            }
+          }
+        }
+      }];
+  return result;
+}
+
+- (GPBDescriptor *)descriptor {
+  return [[self class] descriptor];
+}
+
+- (NSData *)data {
+#ifdef DEBUG
+  if (!self.initialized) {
+    return nil;
+  }
+#endif
+  NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]];
+  GPBCodedOutputStream *stream =
+      [[GPBCodedOutputStream alloc] initWithData:data];
+  @try {
+    [self writeToCodedOutputStream:stream];
+  }
+  @catch (NSException *exception) {
+    // This really shouldn't happen. The only way writeToCodedOutputStream:
+    // could throw is if something in the library has a bug and the
+    // serializedSize was wrong.
+#ifdef DEBUG
+    NSLog(@"%@: Internal exception while building message data: %@",
+          [self class], exception);
+#endif
+    data = nil;
+  }
+  [stream release];
+  return data;
+}
+
+- (NSData *)delimitedData {
+  size_t serializedSize = [self serializedSize];
+  size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
+  NSMutableData *data =
+      [NSMutableData dataWithLength:(serializedSize + varintSize)];
+  GPBCodedOutputStream *stream =
+      [[GPBCodedOutputStream alloc] initWithData:data];
+  @try {
+    [self writeDelimitedToCodedOutputStream:stream];
+  }
+  @catch (NSException *exception) {
+    // This really shouldn't happen.  The only way writeToCodedOutputStream:
+    // could throw is if something in the library has a bug and the
+    // serializedSize was wrong.
+#ifdef DEBUG
+    NSLog(@"%@: Internal exception while building message delimitedData: %@",
+          [self class], exception);
+#endif
+    // If it happens, truncate.
+    data.length = 0;
+  }
+  [stream release];
+  return data;
+}
+
+- (void)writeToOutputStream:(NSOutputStream *)output {
+  GPBCodedOutputStream *stream =
+      [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+  [self writeToCodedOutputStream:stream];
+  [stream release];
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
+  GPBDescriptor *descriptor = [self descriptor];
+  NSArray *fieldsArray = descriptor->fields_;
+  NSUInteger fieldCount = fieldsArray.count;
+  const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
+  NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
+  for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
+    if (i == fieldCount) {
+      [self writeExtensionsToCodedOutputStream:output
+                                         range:extensionRanges[j++]];
+    } else if (j == extensionRangesCount ||
+               GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
+      [self writeField:fieldsArray[i++] toCodedOutputStream:output];
+    } else {
+      [self writeExtensionsToCodedOutputStream:output
+                                         range:extensionRanges[j++]];
+    }
+  }
+  if (descriptor.isWireFormat) {
+    [unknownFields_ writeAsMessageSetTo:output];
+  } else {
+    [unknownFields_ writeToCodedOutputStream:output];
+  }
+}
+
+- (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
+  GPBCodedOutputStream *codedOutput =
+      [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+  [self writeDelimitedToCodedOutputStream:codedOutput];
+  [codedOutput release];
+}
+
+- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output {
+  [output writeRawVarintSizeTAs32:[self serializedSize]];
+  [self writeToCodedOutputStream:output];
+}
+
+- (void)writeField:(GPBFieldDescriptor *)field
+    toCodedOutputStream:(GPBCodedOutputStream *)output {
+  GPBFieldType fieldType = field.fieldType;
+  if (fieldType == GPBFieldTypeSingle) {
+    BOOL has = GPBGetHasIvarField(self, field);
+    if (!has) {
+      return;
+    }
+  }
+  uint32_t fieldNumber = GPBFieldNumber(field);
+
+//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
+//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
+//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
+//%    case GPBDataType##TYPE:
+//%      if (fieldType == GPBFieldTypeRepeated) {
+//%        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+//%        GPB##ARRAY_TYPE##Array *array =
+//%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//%        [output write##TYPE##Array:fieldNumber values:array tag:tag];
+//%      } else if (fieldType == GPBFieldTypeSingle) {
+//%        [output write##TYPE:fieldNumber
+//%              TYPE$S  value:GPBGetMessage##REAL_TYPE##Field(self, field)];
+//%      } else {  // fieldType == GPBFieldTypeMap
+//%        // Exact type here doesn't matter.
+//%        GPBInt32##ARRAY_TYPE##Dictionary *dict =
+//%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//%        [dict writeToCodedOutputStream:output asField:field];
+//%      }
+//%      break;
+//%
+//%PDDM-DEFINE FIELD_CASE2(TYPE)
+//%    case GPBDataType##TYPE:
+//%      if (fieldType == GPBFieldTypeRepeated) {
+//%        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//%        [output write##TYPE##Array:fieldNumber values:array];
+//%      } else if (fieldType == GPBFieldTypeSingle) {
+//%        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+//%        // again.
+//%        [output write##TYPE:fieldNumber
+//%              TYPE$S  value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+//%      } else {  // fieldType == GPBFieldTypeMap
+//%        // Exact type here doesn't matter.
+//%        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//%        GPBDataType mapKeyDataType = field.mapKeyDataType;
+//%        if (mapKeyDataType == GPBDataTypeString) {
+//%          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+//%        } else {
+//%          [dict writeToCodedOutputStream:output asField:field];
+//%        }
+//%      }
+//%      break;
+//%
+
+  switch (GPBGetFieldDataType(field)) {
+
+//%PDDM-EXPAND FIELD_CASE(Bool, Bool)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeBool:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBBoolArray *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeBoolArray:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeBool:fieldNumber
+                    value:GPBGetMessageBoolField(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32BoolDictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeFixed32:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBUInt32Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeFixed32Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeFixed32:fieldNumber
+                       value:GPBGetMessageUInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32UInt32Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeSFixed32:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt32Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeSFixed32Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeSFixed32:fieldNumber
+                        value:GPBGetMessageInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int32Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Float, Float)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeFloat:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBFloatArray *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeFloatArray:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeFloat:fieldNumber
+                     value:GPBGetMessageFloatField(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32FloatDictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeFixed64:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBUInt64Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeFixed64Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeFixed64:fieldNumber
+                       value:GPBGetMessageUInt64Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32UInt64Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeSFixed64:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt64Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeSFixed64Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeSFixed64:fieldNumber
+                        value:GPBGetMessageInt64Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int64Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Double, Double)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeDouble:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBDoubleArray *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeDoubleArray:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeDouble:fieldNumber
+                      value:GPBGetMessageDoubleField(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32DoubleDictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Int32, Int32)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeInt32:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt32Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeInt32Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeInt32:fieldNumber
+                     value:GPBGetMessageInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int32Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(Int64, Int64)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeInt64:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt64Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeInt64Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeInt64:fieldNumber
+                     value:GPBGetMessageInt64Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int64Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeSInt32:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt32Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeSInt32Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeSInt32:fieldNumber
+                      value:GPBGetMessageInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int32Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeSInt64:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBInt64Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeSInt64Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeSInt64:fieldNumber
+                      value:GPBGetMessageInt64Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32Int64Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeUInt32:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBUInt32Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeUInt32Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeUInt32:fieldNumber
+                      value:GPBGetMessageUInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32UInt32Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeUInt64:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBUInt64Array *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeUInt64Array:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeUInt64:fieldNumber
+                      value:GPBGetMessageUInt64Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32UInt64Dictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeEnum:
+      if (fieldType == GPBFieldTypeRepeated) {
+        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+        GPBEnumArray *array =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeEnumArray:fieldNumber values:array tag:tag];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        [output writeEnum:fieldNumber
+                    value:GPBGetMessageInt32Field(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        GPBInt32EnumDictionary *dict =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [dict writeToCodedOutputStream:output asField:field];
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE2(Bytes)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeBytes:
+      if (fieldType == GPBFieldTypeRepeated) {
+        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeBytesArray:fieldNumber values:array];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+        // again.
+        [output writeBytes:fieldNumber
+                     value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
+          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+        } else {
+          [dict writeToCodedOutputStream:output asField:field];
+        }
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE2(String)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeString:
+      if (fieldType == GPBFieldTypeRepeated) {
+        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeStringArray:fieldNumber values:array];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+        // again.
+        [output writeString:fieldNumber
+                      value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
+          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+        } else {
+          [dict writeToCodedOutputStream:output asField:field];
+        }
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE2(Message)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeMessage:
+      if (fieldType == GPBFieldTypeRepeated) {
+        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeMessageArray:fieldNumber values:array];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+        // again.
+        [output writeMessage:fieldNumber
+                       value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
+          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+        } else {
+          [dict writeToCodedOutputStream:output asField:field];
+        }
+      }
+      break;
+
+//%PDDM-EXPAND FIELD_CASE2(Group)
+// This block of code is generated, do not edit it directly.
+
+    case GPBDataTypeGroup:
+      if (fieldType == GPBFieldTypeRepeated) {
+        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [output writeGroupArray:fieldNumber values:array];
+      } else if (fieldType == GPBFieldTypeSingle) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+        // again.
+        [output writeGroup:fieldNumber
+                     value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+      } else {  // fieldType == GPBFieldTypeMap
+        // Exact type here doesn't matter.
+        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        GPBDataType mapKeyDataType = field.mapKeyDataType;
+        if (mapKeyDataType == GPBDataTypeString) {
+          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+        } else {
+          [dict writeToCodedOutputStream:output asField:field];
+        }
+      }
+      break;
+
+//%PDDM-EXPAND-END (18 expansions)
+  }
+}
+
+#pragma mark - Extensions
+
+- (id)getExtension:(GPBExtensionDescriptor *)extension {
+  CheckExtension(self, extension);
+  id value = [extensionMap_ objectForKey:extension];
+  if (value != nil) {
+    return value;
+  }
+
+  // No default for repeated.
+  if (extension.isRepeated) {
+    return nil;
+  }
+  // Non messages get their default.
+  if (!GPBExtensionIsMessage(extension)) {
+    return extension.defaultValue;
+  }
+
+  // Check for an autocreated value.
+  GPBPrepareReadOnlySemaphore(self);
+  dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER);
+  value = [autocreatedExtensionMap_ objectForKey:extension];
+  if (!value) {
+    // Auto create the message extensions to match normal fields.
+    value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self,
+                                                     extension);
+
+    if (autocreatedExtensionMap_ == nil) {
+      autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init];
+    }
+
+    // We can't simply call setExtension here because that would clear the new
+    // value's autocreator.
+    [autocreatedExtensionMap_ setObject:value forKey:extension];
+    [value release];
+  }
+
+  dispatch_semaphore_signal(readOnlySemaphore_);
+  return value;
+}
+
+- (id)getExistingExtension:(GPBExtensionDescriptor *)extension {
+  // This is an internal method so we don't need to call CheckExtension().
+  return [extensionMap_ objectForKey:extension];
+}
+
+- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension {
+#if DEBUG
+  CheckExtension(self, extension);
+#endif  // DEBUG
+  return nil != [extensionMap_ objectForKey:extension];
+}
+
+- (NSArray *)extensionsCurrentlySet {
+  return [extensionMap_ allKeys];
+}
+
+- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output
+                                     range:(GPBExtensionRange)range {
+  NSArray *sortedExtensions = [[extensionMap_ allKeys]
+      sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
+  uint32_t start = range.start;
+  uint32_t end = range.end;
+  for (GPBExtensionDescriptor *extension in sortedExtensions) {
+    uint32_t fieldNumber = extension.fieldNumber;
+    if (fieldNumber >= start && fieldNumber < end) {
+      id value = [extensionMap_ objectForKey:extension];
+      GPBWriteExtensionValueToOutputStream(extension, value, output);
+    }
+  }
+}
+
+- (NSArray *)sortedExtensionsInUse {
+  return [[extensionMap_ allKeys]
+      sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
+}
+
+- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
+  if (!value) {
+    [self clearExtension:extension];
+    return;
+  }
+
+  CheckExtension(self, extension);
+
+  if (extension.repeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Must call addExtension() for repeated types."];
+  }
+
+  if (extensionMap_ == nil) {
+    extensionMap_ = [[NSMutableDictionary alloc] init];
+  }
+
+  // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION.
+  // Without it, the compiler complains we're passing an id nullable when
+  // setObject:forKey: requires a id nonnull for the value. The check for
+  // !value at the start of the method ensures it isn't nil, but the check
+  // isn't smart enough to realize that.
+  [extensionMap_ setObject:(id)value forKey:extension];
+
+  GPBExtensionDescriptor *descriptor = extension;
+
+  if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
+    GPBMessage *autocreatedValue =
+        [[autocreatedExtensionMap_ objectForKey:extension] retain];
+    // Must remove from the map before calling GPBClearMessageAutocreator() so
+    // that GPBClearMessageAutocreator() knows its safe to clear.
+    [autocreatedExtensionMap_ removeObjectForKey:extension];
+    GPBClearMessageAutocreator(autocreatedValue);
+    [autocreatedValue release];
+  }
+
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value {
+  CheckExtension(self, extension);
+
+  if (!extension.repeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Must call setExtension() for singular types."];
+  }
+
+  if (extensionMap_ == nil) {
+    extensionMap_ = [[NSMutableDictionary alloc] init];
+  }
+  NSMutableArray *list = [extensionMap_ objectForKey:extension];
+  if (list == nil) {
+    list = [NSMutableArray array];
+    [extensionMap_ setObject:list forKey:extension];
+  }
+
+  [list addObject:value];
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)setExtension:(GPBExtensionDescriptor *)extension
+               index:(NSUInteger)idx
+               value:(id)value {
+  CheckExtension(self, extension);
+
+  if (!extension.repeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Must call setExtension() for singular types."];
+  }
+
+  if (extensionMap_ == nil) {
+    extensionMap_ = [[NSMutableDictionary alloc] init];
+  }
+
+  NSMutableArray *list = [extensionMap_ objectForKey:extension];
+
+  [list replaceObjectAtIndex:idx withObject:value];
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)clearExtension:(GPBExtensionDescriptor *)extension {
+  CheckExtension(self, extension);
+
+  // Only become visible if there was actually a value to clear.
+  if ([extensionMap_ objectForKey:extension]) {
+    [extensionMap_ removeObjectForKey:extension];
+    GPBBecomeVisibleToAutocreator(self);
+  }
+}
+
+#pragma mark - mergeFrom
+
+- (void)mergeFromData:(NSData *)data
+    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
+  [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+  [input checkLastTagWas:0];
+  [input release];
+}
+
+#pragma mark - mergeDelimitedFrom
+
+- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+                         extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  GPBCodedInputStreamState *state = &input->state_;
+  if (GPBCodedInputStreamIsAtEnd(state)) {
+    return;
+  }
+  NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state);
+  if (data == nil) {
+    return;
+  }
+  [self mergeFromData:data extensionRegistry:extensionRegistry];
+  [data release];
+}
+
+#pragma mark - Parse From Data Support
+
++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr {
+  return [self parseFromData:data extensionRegistry:nil error:errorPtr];
+}
+
++ (instancetype)parseFromData:(NSData *)data
+            extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                        error:(NSError **)errorPtr {
+  return [[[self alloc] initWithData:data
+                   extensionRegistry:extensionRegistry
+                               error:errorPtr] autorelease];
+}
+
++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
+                        extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                                    error:(NSError **)errorPtr {
+  return
+      [[[self alloc] initWithCodedInputStream:input
+                            extensionRegistry:extensionRegistry
+                                        error:errorPtr] autorelease];
+}
+
+#pragma mark - Parse Delimited From Data Support
+
++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+                                 extensionRegistry:
+                                     (GPBExtensionRegistry *)extensionRegistry
+                                             error:(NSError **)errorPtr {
+  GPBMessage *message = [[[self alloc] init] autorelease];
+  @try {
+    [message mergeDelimitedFromCodedInputStream:input
+                              extensionRegistry:extensionRegistry];
+    if (errorPtr) {
+      *errorPtr = nil;
+    }
+  }
+  @catch (NSException *exception) {
+    message = nil;
+    if (errorPtr) {
+      *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
+                                         exception.reason);
+    }
+  }
+#ifdef DEBUG
+  if (message && !message.initialized) {
+    message = nil;
+    if (errorPtr) {
+      *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
+    }
+  }
+#endif
+  return message;
+}
+
+#pragma mark - Unknown Field Support
+
+- (GPBUnknownFieldSet *)unknownFields {
+  return unknownFields_;
+}
+
+- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
+  if (unknownFields != unknownFields_) {
+    [unknownFields_ release];
+    unknownFields_ = [unknownFields copy];
+    GPBBecomeVisibleToAutocreator(self);
+  }
+}
+
+- (void)parseMessageSet:(GPBCodedInputStream *)input
+      extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  uint32_t typeId = 0;
+  NSData *rawBytes = nil;
+  GPBExtensionDescriptor *extension = nil;
+  GPBCodedInputStreamState *state = &input->state_;
+  while (true) {
+    uint32_t tag = GPBCodedInputStreamReadTag(state);
+    if (tag == 0) {
+      break;
+    }
+
+    if (tag == GPBWireFormatMessageSetTypeIdTag) {
+      typeId = GPBCodedInputStreamReadUInt32(state);
+      if (typeId != 0) {
+        extension = [extensionRegistry extensionForDescriptor:[self descriptor]
+                                                  fieldNumber:typeId];
+      }
+    } else if (tag == GPBWireFormatMessageSetMessageTag) {
+      rawBytes =
+          [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
+    } else {
+      if (![input skipField:tag]) {
+        break;
+      }
+    }
+  }
+
+  [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag];
+
+  if (rawBytes != nil && typeId != 0) {
+    if (extension != nil) {
+      GPBCodedInputStream *newInput =
+          [[GPBCodedInputStream alloc] initWithData:rawBytes];
+      GPBExtensionMergeFromInputStream(extension,
+                                       extension.packable,
+                                       newInput,
+                                       extensionRegistry,
+                                       self);
+      [newInput release];
+    } else {
+      GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+      [unknownFields mergeMessageSetMessage:typeId data:rawBytes];
+    }
+  }
+}
+
+- (BOOL)parseUnknownField:(GPBCodedInputStream *)input
+        extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                      tag:(uint32_t)tag {
+  GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
+  int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
+
+  GPBDescriptor *descriptor = [self descriptor];
+  GPBExtensionDescriptor *extension =
+      [extensionRegistry extensionForDescriptor:descriptor
+                                    fieldNumber:fieldNumber];
+  if (extension == nil) {
+    if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
+      [self parseMessageSet:input extensionRegistry:extensionRegistry];
+      return YES;
+    }
+  } else {
+    if (extension.wireType == wireType) {
+      GPBExtensionMergeFromInputStream(extension,
+                                       extension.packable,
+                                       input,
+                                       extensionRegistry,
+                                       self);
+      return YES;
+    }
+    // Primitive, repeated types can be packed on unpacked on the wire, and are
+    // parsed either way.
+    if ([extension isRepeated] &&
+        !GPBDataTypeIsObject(extension->description_->dataType) &&
+        (extension.alternateWireType == wireType)) {
+      GPBExtensionMergeFromInputStream(extension,
+                                       !extension.packable,
+                                       input,
+                                       extensionRegistry,
+                                       self);
+      return YES;
+    }
+  }
+  if ([GPBUnknownFieldSet isFieldTag:tag]) {
+    GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+    return [unknownFields mergeFieldFrom:tag input:input];
+  } else {
+    return NO;
+  }
+}
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
+  GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+  [unknownFields addUnknownMapEntry:fieldNum value:data];
+}
+
+#pragma mark - MergeFromCodedInputStream Support
+
+static void MergeSingleFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                             \
+    case GPBDataType##NAME: {                                              \
+      TYPE val = GPBCodedInputStreamRead##NAME(&input->state_);            \
+      GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax);  \
+      break;                                                               \
+            }
+#define CASE_SINGLE_OBJECT(NAME)                                           \
+    case GPBDataType##NAME: {                                              \
+      id val = GPBCodedInputStreamReadRetained##NAME(&input->state_);      \
+      GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
+      break;                                                               \
+    }
+      CASE_SINGLE_POD(Bool, BOOL, Bool)
+      CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
+      CASE_SINGLE_POD(SFixed32, int32_t, Int32)
+      CASE_SINGLE_POD(Float, float, Float)
+      CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
+      CASE_SINGLE_POD(SFixed64, int64_t, Int64)
+      CASE_SINGLE_POD(Double, double, Double)
+      CASE_SINGLE_POD(Int32, int32_t, Int32)
+      CASE_SINGLE_POD(Int64, int64_t, Int64)
+      CASE_SINGLE_POD(SInt32, int32_t, Int32)
+      CASE_SINGLE_POD(SInt64, int64_t, Int64)
+      CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
+      CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
+      CASE_SINGLE_OBJECT(Bytes)
+      CASE_SINGLE_OBJECT(String)
+#undef CASE_SINGLE_POD
+#undef CASE_SINGLE_OBJECT
+
+    case GPBDataTypeMessage: {
+      if (GPBGetHasIvarField(self, field)) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
+        // check again.
+        GPBMessage *message =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [input readMessage:message extensionRegistry:extensionRegistry];
+      } else {
+        GPBMessage *message = [[field.msgClass alloc] init];
+        [input readMessage:message extensionRegistry:extensionRegistry];
+        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+      }
+      break;
+    }
+
+    case GPBDataTypeGroup: {
+      if (GPBGetHasIvarField(self, field)) {
+        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
+        // check again.
+        GPBMessage *message =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+        [input readGroup:GPBFieldNumber(field)
+                      message:message
+            extensionRegistry:extensionRegistry];
+      } else {
+        GPBMessage *message = [[field.msgClass alloc] init];
+        [input readGroup:GPBFieldNumber(field)
+                      message:message
+            extensionRegistry:extensionRegistry];
+        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+      }
+      break;
+    }
+
+    case GPBDataTypeEnum: {
+      int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
+      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+          [field isValidEnumValue:val]) {
+        GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
+      } else {
+        GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+        [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
+      }
+    }
+  }  // switch
+}
+
+static void MergeRepeatedPackedFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  GPBCodedInputStreamState *state = &input->state_;
+  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  int32_t length = GPBCodedInputStreamReadInt32(state);
+  size_t limit = GPBCodedInputStreamPushLimit(state, length);
+  while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+    switch (fieldDataType) {
+#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE)      \
+     case GPBDataType##NAME: {                                \
+       TYPE val = GPBCodedInputStreamRead##NAME(state);       \
+       [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
+       break;                                                 \
+     }
+        CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool)
+        CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32)
+        CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(Float, float, Float)
+        CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64)
+        CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(Double, double, Double)
+        CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32)
+        CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64)
+        CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32)
+        CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64)
+#undef CASE_REPEATED_PACKED_POD
+
+      case GPBDataTypeBytes:
+      case GPBDataTypeString:
+      case GPBDataTypeMessage:
+      case GPBDataTypeGroup:
+        NSCAssert(NO, @"Non primitive types can't be packed");
+        break;
+
+      case GPBDataTypeEnum: {
+        int32_t val = GPBCodedInputStreamReadEnum(state);
+        if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+            [field isValidEnumValue:val]) {
+          [(GPBEnumArray*)genericArray addRawValue:val];
+        } else {
+          GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+          [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
+        }
+        break;
+      }
+    }  // switch
+  }  // while(BytesUntilLimit() > 0)
+  GPBCodedInputStreamPopLimit(state, limit);
+}
+
+static void MergeRepeatedNotPackedFieldFromCodedInputStream(
+    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+  GPBCodedInputStreamState *state = &input->state_;
+  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  switch (GPBGetFieldDataType(field)) {
+#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
+   case GPBDataType##NAME: {                                 \
+     TYPE val = GPBCodedInputStreamRead##NAME(state);        \
+     [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val];  \
+     break;                                                  \
+   }
+#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME)                \
+   case GPBDataType##NAME: {                                 \
+     id val = GPBCodedInputStreamReadRetained##NAME(state);  \
+     [(NSMutableArray*)genericArray addObject:val];          \
+     [val release];                                          \
+     break;                                                  \
+   }
+      CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool)
+      CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32)
+      CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(Float, float, Float)
+      CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64)
+      CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(Double, double, Double)
+      CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32)
+      CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64)
+      CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32)
+      CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64)
+      CASE_REPEATED_NOT_PACKED_OBJECT(Bytes)
+      CASE_REPEATED_NOT_PACKED_OBJECT(String)
+#undef CASE_REPEATED_NOT_PACKED_POD
+#undef CASE_NOT_PACKED_OBJECT
+    case GPBDataTypeMessage: {
+      GPBMessage *message = [[field.msgClass alloc] init];
+      [input readMessage:message extensionRegistry:extensionRegistry];
+      [(NSMutableArray*)genericArray addObject:message];
+      [message release];
+      break;
+    }
+    case GPBDataTypeGroup: {
+      GPBMessage *message = [[field.msgClass alloc] init];
+      [input readGroup:GPBFieldNumber(field)
+                    message:message
+          extensionRegistry:extensionRegistry];
+      [(NSMutableArray*)genericArray addObject:message];
+      [message release];
+      break;
+    }
+    case GPBDataTypeEnum: {
+      int32_t val = GPBCodedInputStreamReadEnum(state);
+      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
+          [field isValidEnumValue:val]) {
+        [(GPBEnumArray*)genericArray addRawValue:val];
+      } else {
+        GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+        [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
+      }
+      break;
+    }
+  }  // switch
+}
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+  GPBDescriptor *descriptor = [self descriptor];
+  GPBFileSyntax syntax = descriptor.file.syntax;
+  GPBCodedInputStreamState *state = &input->state_;
+  uint32_t tag = 0;
+  NSUInteger startingIndex = 0;
+  NSArray *fields = descriptor->fields_;
+  NSUInteger numFields = fields.count;
+  while (YES) {
+    BOOL merged = NO;
+    tag = GPBCodedInputStreamReadTag(state);
+    for (NSUInteger i = 0; i < numFields; ++i) {
+      if (startingIndex >= numFields) startingIndex = 0;
+      GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
+      if (GPBFieldTag(fieldDescriptor) == tag) {
+        GPBFieldType fieldType = fieldDescriptor.fieldType;
+        if (fieldType == GPBFieldTypeSingle) {
+          MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax,
+                                               input, extensionRegistry);
+          // Well formed protos will only have a single field once, advance
+          // the starting index to the next field.
+          startingIndex += 1;
+        } else if (fieldType == GPBFieldTypeRepeated) {
+          if (fieldDescriptor.isPackable) {
+            MergeRepeatedPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input);
+            // Well formed protos will only have a repeated field that is
+            // packed once, advance the starting index to the next field.
+            startingIndex += 1;
+          } else {
+            MergeRepeatedNotPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input, extensionRegistry);
+          }
+        } else {  // fieldType == GPBFieldTypeMap
+          // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
+          // point.
+          id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
+          [input readMapEntry:map
+            extensionRegistry:extensionRegistry
+                        field:fieldDescriptor
+                parentMessage:self];
+        }
+        merged = YES;
+        break;
+      } else {
+        startingIndex += 1;
+      }
+    }  // for(i < numFields)
+
+    if (!merged) {
+      // Primitive, repeated types can be packed on unpacked on the wire, and
+      // are parsed either way.  The above loop covered tag in the preferred
+      // for, so this need to check the alternate form.
+      for (NSUInteger i = 0; i < numFields; ++i) {
+        if (startingIndex >= numFields) startingIndex = 0;
+        GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
+        if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
+            !GPBFieldDataTypeIsObject(fieldDescriptor) &&
+            (GPBFieldAlternateTag(fieldDescriptor) == tag)) {
+          BOOL alternateIsPacked = !fieldDescriptor.isPackable;
+          if (alternateIsPacked) {
+            MergeRepeatedPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input);
+            // Well formed protos will only have a repeated field that is
+            // packed once, advance the starting index to the next field.
+            startingIndex += 1;
+          } else {
+            MergeRepeatedNotPackedFieldFromCodedInputStream(
+                self, fieldDescriptor, syntax, input, extensionRegistry);
+          }
+          merged = YES;
+          break;
+        } else {
+          startingIndex += 1;
+        }
+      }
+    }
+
+    if (!merged) {
+      if (tag == 0) {
+        // zero signals EOF / limit reached
+        return;
+      } else {
+        if (GPBPreserveUnknownFields(syntax)) {
+          if (![self parseUnknownField:input
+                     extensionRegistry:extensionRegistry
+                                   tag:tag]) {
+            // it's an endgroup tag
+            return;
+          }
+        } else {
+          if (![input skipField:tag]) {
+            return;
+          }
+        }
+      }
+    }  // if(!merged)
+
+  }  // while(YES)
+}
+
+#pragma mark - MergeFrom Support
+
+- (void)mergeFrom:(GPBMessage *)other {
+  Class selfClass = [self class];
+  Class otherClass = [other class];
+  if (!([selfClass isSubclassOfClass:otherClass] ||
+        [otherClass isSubclassOfClass:selfClass])) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Classes must match %@ != %@", selfClass, otherClass];
+  }
+
+  // We assume something will be done and become visible.
+  GPBBecomeVisibleToAutocreator(self);
+
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  GPBFileSyntax syntax = descriptor.file.syntax;
+
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    GPBFieldType fieldType = field.fieldType;
+    if (fieldType == GPBFieldTypeSingle) {
+      int32_t hasIndex = GPBFieldHasIndex(field);
+      uint32_t fieldNumber = GPBFieldNumber(field);
+      if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) {
+        // Other doesn't have the field set, on to the next.
+        continue;
+      }
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      switch (fieldDataType) {
+        case GPBDataTypeBool:
+          GPBSetBoolIvarWithFieldInternal(
+              self, field, GPBGetMessageBoolField(other, field), syntax);
+          break;
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+          GPBSetInt32IvarWithFieldInternal(
+              self, field, GPBGetMessageInt32Field(other, field), syntax);
+          break;
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+          GPBSetUInt32IvarWithFieldInternal(
+              self, field, GPBGetMessageUInt32Field(other, field), syntax);
+          break;
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+          GPBSetInt64IvarWithFieldInternal(
+              self, field, GPBGetMessageInt64Field(other, field), syntax);
+          break;
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+          GPBSetUInt64IvarWithFieldInternal(
+              self, field, GPBGetMessageUInt64Field(other, field), syntax);
+          break;
+        case GPBDataTypeFloat:
+          GPBSetFloatIvarWithFieldInternal(
+              self, field, GPBGetMessageFloatField(other, field), syntax);
+          break;
+        case GPBDataTypeDouble:
+          GPBSetDoubleIvarWithFieldInternal(
+              self, field, GPBGetMessageDoubleField(other, field), syntax);
+          break;
+        case GPBDataTypeBytes:
+        case GPBDataTypeString: {
+          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+          GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
+          break;
+        }
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+          if (GPBGetHasIvar(self, hasIndex, fieldNumber)) {
+            GPBMessage *message =
+                GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+            [message mergeFrom:otherVal];
+          } else {
+            GPBMessage *message = [otherVal copy];
+            GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
+                                                      syntax);
+          }
+          break;
+        }
+      } // switch()
+    } else if (fieldType == GPBFieldTypeRepeated) {
+      // In the case of a list, they need to be appended, and there is no
+      // _hasIvar to worry about setting.
+      id otherArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      if (otherArray) {
+        GPBDataType fieldDataType = field->description_->dataType;
+        if (GPBDataTypeIsObject(fieldDataType)) {
+          NSMutableArray *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addObjectsFromArray:otherArray];
+        } else if (fieldDataType == GPBDataTypeEnum) {
+          GPBEnumArray *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addRawValuesFromArray:otherArray];
+        } else {
+          // The array type doesn't matter, that all implment
+          // -addValuesFromArray:.
+          GPBInt32Array *resultArray =
+              GetOrCreateArrayIvarWithField(self, field, syntax);
+          [resultArray addValuesFromArray:otherArray];
+        }
+      }
+    } else {  // fieldType = GPBFieldTypeMap
+      // In the case of a map, they need to be merged, and there is no
+      // _hasIvar to worry about setting.
+      id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      if (otherDict) {
+        GPBDataType keyDataType = field.mapKeyDataType;
+        GPBDataType valueDataType = field->description_->dataType;
+        if (GPBDataTypeIsObject(keyDataType) &&
+            GPBDataTypeIsObject(valueDataType)) {
+          NSMutableDictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addEntriesFromDictionary:otherDict];
+        } else if (valueDataType == GPBDataTypeEnum) {
+          // The exact type doesn't matter, just need to know it is a
+          // GPB*EnumDictionary.
+          GPBInt32EnumDictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addRawEntriesFromDictionary:otherDict];
+        } else {
+          // The exact type doesn't matter, they all implement
+          // -addEntriesFromDictionary:.
+          GPBInt32Int32Dictionary *resultDict =
+              GetOrCreateMapIvarWithField(self, field, syntax);
+          [resultDict addEntriesFromDictionary:otherDict];
+        }
+      }
+    }  // if (fieldType)..else if...else
+  }  // for(fields)
+
+  // Unknown fields.
+  if (!unknownFields_) {
+    [self setUnknownFields:other.unknownFields];
+  } else {
+    [unknownFields_ mergeUnknownFields:other.unknownFields];
+  }
+
+  // Extensions
+
+  if (other->extensionMap_.count == 0) {
+    return;
+  }
+
+  if (extensionMap_ == nil) {
+    extensionMap_ =
+        CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
+  } else {
+    for (GPBExtensionDescriptor *extension in other->extensionMap_) {
+      id otherValue = [other->extensionMap_ objectForKey:extension];
+      id value = [extensionMap_ objectForKey:extension];
+      BOOL isMessageExtension = GPBExtensionIsMessage(extension);
+
+      if (extension.repeated) {
+        NSMutableArray *list = value;
+        if (list == nil) {
+          list = [[NSMutableArray alloc] init];
+          [extensionMap_ setObject:list forKey:extension];
+          [list release];
+        }
+        if (isMessageExtension) {
+          for (GPBMessage *otherListValue in otherValue) {
+            GPBMessage *copiedValue = [otherListValue copy];
+            [list addObject:copiedValue];
+            [copiedValue release];
+          }
+        } else {
+          [list addObjectsFromArray:otherValue];
+        }
+      } else {
+        if (isMessageExtension) {
+          if (value) {
+            [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
+          } else {
+            GPBMessage *copiedValue = [otherValue copy];
+            [extensionMap_ setObject:copiedValue forKey:extension];
+            [copiedValue release];
+          }
+        } else {
+          [extensionMap_ setObject:otherValue forKey:extension];
+        }
+      }
+
+      if (isMessageExtension && !extension.isRepeated) {
+        GPBMessage *autocreatedValue =
+            [[autocreatedExtensionMap_ objectForKey:extension] retain];
+        // Must remove from the map before calling GPBClearMessageAutocreator()
+        // so that GPBClearMessageAutocreator() knows its safe to clear.
+        [autocreatedExtensionMap_ removeObjectForKey:extension];
+        GPBClearMessageAutocreator(autocreatedValue);
+        [autocreatedValue release];
+      }
+    }
+  }
+}
+
+#pragma mark - isEqual: & hash Support
+
+- (BOOL)isEqual:(GPBMessage *)other {
+  if (other == self) {
+    return YES;
+  }
+  if (![other isKindOfClass:[self class]] &&
+      ![self isKindOfClass:[other class]]) {
+    return NO;
+  }
+
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  uint8_t *selfStorage = (uint8_t *)messageStorage_;
+  uint8_t *otherStorage = (uint8_t *)other->messageStorage_;
+
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (GPBFieldIsMapOrArray(field)) {
+      // In the case of a list or map, there is no _hasIvar to worry about.
+      // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but
+      // the type doesn't really matter as the objects all support -count and
+      // -isEqual:.
+      NSArray *resultMapOrArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      NSArray *otherMapOrArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(other, field);
+      // nil and empty are equal
+      if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) {
+        if (![resultMapOrArray isEqual:otherMapOrArray]) {
+          return NO;
+        }
+      }
+    } else {  // Single field
+      int32_t hasIndex = GPBFieldHasIndex(field);
+      uint32_t fieldNum = GPBFieldNumber(field);
+      BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum);
+      BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum);
+      if (selfHas != otherHas) {
+        return NO;  // Differing has values, not equal.
+      }
+      if (!selfHas) {
+        // Same has values, was no, nothing else to check for this field.
+        continue;
+      }
+      // Now compare the values.
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      size_t fieldOffset = field->description_->offset;
+      switch (fieldDataType) {
+        case GPBDataTypeBool: {
+          // Bools are stored in has_bits to avoid needing explicit space in
+          // the storage structure.
+          // (the field number passed to the HasIvar helper doesn't really
+          // matter since the offset is never negative)
+          BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
+          BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0);
+          if (selfValue != otherValue) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+        case GPBDataTypeFloat: {
+          _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
+          // These are all 32bit, signed/unsigned doesn't matter for equality.
+          uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset];
+          uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset];
+          if (*selfValPtr != *otherValPtr) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+        case GPBDataTypeDouble: {
+          _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
+          // These are all 64bit, signed/unsigned doesn't matter for equality.
+          uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset];
+          uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset];
+          if (*selfValPtr != *otherValPtr) {
+            return NO;
+          }
+          break;
+        }
+        case GPBDataTypeBytes:
+        case GPBDataTypeString:
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          // Type doesn't matter here, they all implement -isEqual:.
+          id *selfValPtr = (id *)&selfStorage[fieldOffset];
+          id *otherValPtr = (id *)&otherStorage[fieldOffset];
+          if (![*selfValPtr isEqual:*otherValPtr]) {
+            return NO;
+          }
+          break;
+        }
+      } // switch()
+    }   // if(mapOrArray)...else
+  }  // for(fields)
+
+  // nil and empty are equal
+  if (extensionMap_.count != 0 || other->extensionMap_.count != 0) {
+    if (![extensionMap_ isEqual:other->extensionMap_]) {
+      return NO;
+    }
+  }
+
+  // nil and empty are equal
+  GPBUnknownFieldSet *otherUnknowns = other->unknownFields_;
+  if ([unknownFields_ countOfFields] != 0 ||
+      [otherUnknowns countOfFields] != 0) {
+    if (![unknownFields_ isEqual:otherUnknowns]) {
+      return NO;
+    }
+  }
+
+  return YES;
+}
+
+// It is very difficult to implement a generic hash for ProtoBuf messages that
+// will perform well. If you need hashing on your ProtoBufs (eg you are using
+// them as dictionary keys) you will probably want to implement a ProtoBuf
+// message specific hash as a category on your protobuf class. Do not make it a
+// category on GPBMessage as you will conflict with this hash, and will possibly
+// override hash for all generated protobufs. A good implementation of hash will
+// be really fast, so we would recommend only hashing protobufs that have an
+// identifier field of some kind that you can easily hash. If you implement
+// hash, we would strongly recommend overriding isEqual: in your category as
+// well, as the default implementation of isEqual: is extremely slow, and may
+// drastically affect performance in large sets.
+- (NSUInteger)hash {
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  const NSUInteger prime = 19;
+  uint8_t *storage = (uint8_t *)messageStorage_;
+
+  // Start with the descriptor and then mix it with some instance info.
+  // Hopefully that will give a spread based on classes and what fields are set.
+  NSUInteger result = (NSUInteger)descriptor;
+
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    if (GPBFieldIsMapOrArray(field)) {
+      // Exact type doesn't matter, just check if there are any elements.
+      NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+      NSUInteger count = mapOrArray.count;
+      if (count) {
+        // NSArray/NSDictionary use count, use the field number and the count.
+        result = prime * result + GPBFieldNumber(field);
+        result = prime * result + count;
+      }
+    } else if (GPBGetHasIvarField(self, field)) {
+      // Just using the field number seemed simple/fast, but then a small
+      // message class where all the same fields are always set (to different
+      // things would end up all with the same hash, so pull in some data).
+      GPBDataType fieldDataType = GPBGetFieldDataType(field);
+      size_t fieldOffset = field->description_->offset;
+      switch (fieldDataType) {
+        case GPBDataTypeBool: {
+          // Bools are stored in has_bits to avoid needing explicit space in
+          // the storage structure.
+          // (the field number passed to the HasIvar helper doesn't really
+          // matter since the offset is never negative)
+          BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
+          result = prime * result + value;
+          break;
+        }
+        case GPBDataTypeSFixed32:
+        case GPBDataTypeInt32:
+        case GPBDataTypeSInt32:
+        case GPBDataTypeEnum:
+        case GPBDataTypeFixed32:
+        case GPBDataTypeUInt32:
+        case GPBDataTypeFloat: {
+          _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
+          // These are all 32bit, just mix it in.
+          uint32_t *valPtr = (uint32_t *)&storage[fieldOffset];
+          result = prime * result + *valPtr;
+          break;
+        }
+        case GPBDataTypeSFixed64:
+        case GPBDataTypeInt64:
+        case GPBDataTypeSInt64:
+        case GPBDataTypeFixed64:
+        case GPBDataTypeUInt64:
+        case GPBDataTypeDouble: {
+          _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
+          // These are all 64bit, just mix what fits into an NSUInteger in.
+          uint64_t *valPtr = (uint64_t *)&storage[fieldOffset];
+          result = prime * result + (NSUInteger)(*valPtr);
+          break;
+        }
+        case GPBDataTypeBytes:
+        case GPBDataTypeString: {
+          // Type doesn't matter here, they both implement -hash:.
+          id *valPtr = (id *)&storage[fieldOffset];
+          result = prime * result + [*valPtr hash];
+          break;
+        }
+
+        case GPBDataTypeMessage:
+        case GPBDataTypeGroup: {
+          GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset];
+          // Could call -hash on the sub message, but that could recurse pretty
+          // deep; follow the lead of NSArray/NSDictionary and don't really
+          // recurse for hash, instead use the field number and the descriptor
+          // of the sub message.  Yes, this could suck for a bunch of messages
+          // where they all only differ in the sub messages, but if you are
+          // using a message with sub messages for something that needs -hash,
+          // odds are you are also copying them as keys, and that deep copy
+          // will also suck.
+          result = prime * result + GPBFieldNumber(field);
+          result = prime * result + (NSUInteger)[[*valPtr class] descriptor];
+          break;
+        }
+      } // switch()
+    }
+  }
+
+  // Unknowns and extensions are not included.
+
+  return result;
+}
+
+#pragma mark - Description Support
+
+- (NSString *)description {
+  NSString *textFormat = GPBTextFormatForMessage(self, @"    ");
+  NSString *description = [NSString
+      stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat];
+  return description;
+}
+
+#if DEBUG
+
+// Xcode 5.1 added support for custom quick look info.
+// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1
+- (id)debugQuickLookObject {
+  return GPBTextFormatForMessage(self, nil);
+}
+
+#endif  // DEBUG
+
+#pragma mark - SerializedSize
+
+- (size_t)serializedSize {
+  GPBDescriptor *descriptor = [[self class] descriptor];
+  size_t result = 0;
+
+  // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate()
+  // avoids doing the has check again.
+
+  // Fields.
+  for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
+    GPBFieldType fieldType = fieldDescriptor.fieldType;
+    GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor);
+
+    // Single Fields
+    if (fieldType == GPBFieldTypeSingle) {
+      BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor);
+      if (!selfHas) {
+        continue;  // Nothing to do.
+      }
+
+      uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor);
+
+      switch (fieldDataType) {
+#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                                \
+        case GPBDataType##NAME: {                                             \
+          TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \
+          result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
+          break;                                                              \
+        }
+#define CASE_SINGLE_OBJECT(NAME)                                              \
+        case GPBDataType##NAME: {                                             \
+          id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \
+          result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
+          break;                                                              \
+        }
+          CASE_SINGLE_POD(Bool, BOOL, Bool)
+          CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
+          CASE_SINGLE_POD(SFixed32, int32_t, Int32)
+          CASE_SINGLE_POD(Float, float, Float)
+          CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
+          CASE_SINGLE_POD(SFixed64, int64_t, Int64)
+          CASE_SINGLE_POD(Double, double, Double)
+          CASE_SINGLE_POD(Int32, int32_t, Int32)
+          CASE_SINGLE_POD(Int64, int64_t, Int64)
+          CASE_SINGLE_POD(SInt32, int32_t, Int32)
+          CASE_SINGLE_POD(SInt64, int64_t, Int64)
+          CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
+          CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
+          CASE_SINGLE_OBJECT(Bytes)
+          CASE_SINGLE_OBJECT(String)
+          CASE_SINGLE_OBJECT(Message)
+          CASE_SINGLE_OBJECT(Group)
+          CASE_SINGLE_POD(Enum, int32_t, Int32)
+#undef CASE_SINGLE_POD
+#undef CASE_SINGLE_OBJECT
+      }
+
+    // Repeated Fields
+    } else if (fieldType == GPBFieldTypeRepeated) {
+      id genericArray =
+          GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+      NSUInteger count = [genericArray count];
+      if (count == 0) {
+        continue;  // Nothing to add.
+      }
+      __block size_t dataSize = 0;
+
+      switch (fieldDataType) {
+#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE)                             \
+    CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, )
+#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)  \
+        case GPBDataType##NAME: {                                             \
+          GPB##ARRAY_TYPE##Array *array = genericArray;                       \
+          [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \
+            _Pragma("unused(idx, stop)");                                     \
+            dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
+          }];                                                                 \
+          break;                                                              \
+        }
+#define CASE_REPEATED_OBJECT(NAME)                                            \
+        case GPBDataType##NAME: {                                             \
+          for (id value in genericArray) {                                    \
+            dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
+          }                                                                   \
+          break;                                                              \
+        }
+          CASE_REPEATED_POD(Bool, BOOL, Bool)
+          CASE_REPEATED_POD(Fixed32, uint32_t, UInt32)
+          CASE_REPEATED_POD(SFixed32, int32_t, Int32)
+          CASE_REPEATED_POD(Float, float, Float)
+          CASE_REPEATED_POD(Fixed64, uint64_t, UInt64)
+          CASE_REPEATED_POD(SFixed64, int64_t, Int64)
+          CASE_REPEATED_POD(Double, double, Double)
+          CASE_REPEATED_POD(Int32, int32_t, Int32)
+          CASE_REPEATED_POD(Int64, int64_t, Int64)
+          CASE_REPEATED_POD(SInt32, int32_t, Int32)
+          CASE_REPEATED_POD(SInt64, int64_t, Int64)
+          CASE_REPEATED_POD(UInt32, uint32_t, UInt32)
+          CASE_REPEATED_POD(UInt64, uint64_t, UInt64)
+          CASE_REPEATED_OBJECT(Bytes)
+          CASE_REPEATED_OBJECT(String)
+          CASE_REPEATED_OBJECT(Message)
+          CASE_REPEATED_OBJECT(Group)
+          CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw)
+#undef CASE_REPEATED_POD
+#undef CASE_REPEATED_POD_EXTRA
+#undef CASE_REPEATED_OBJECT
+      }  // switch
+      result += dataSize;
+      size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor));
+      if (fieldDataType == GPBDataTypeGroup) {
+        // Groups have both a start and an end tag.
+        tagSize *= 2;
+      }
+      if (fieldDescriptor.isPackable) {
+        result += tagSize;
+        result += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+      } else {
+        result += count * tagSize;
+      }
+
+    // Map<> Fields
+    } else {  // fieldType == GPBFieldTypeMap
+      if (GPBDataTypeIsObject(fieldDataType) &&
+          (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) {
+        // If key type was string, then the map is an NSDictionary.
+        NSDictionary *map =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+        if (map) {
+          result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor);
+        }
+      } else {
+        // Type will be GPB*GroupDictionary, exact type doesn't matter.
+        GPBInt32Int32Dictionary *map =
+            GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
+        result += [map computeSerializedSizeAsField:fieldDescriptor];
+      }
+    }
+  }  // for(fields)
+
+  // Add any unknown fields.
+  if (descriptor.wireFormat) {
+    result += [unknownFields_ serializedSizeAsMessageSet];
+  } else {
+    result += [unknownFields_ serializedSize];
+  }
+
+  // Add any extensions.
+  for (GPBExtensionDescriptor *extension in extensionMap_) {
+    id value = [extensionMap_ objectForKey:extension];
+    result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value);
+  }
+
+  return result;
+}
+
+#pragma mark - Resolve Methods Support
+
+typedef struct ResolveIvarAccessorMethodResult {
+  IMP impToAdd;
+  SEL encodingSelector;
+} ResolveIvarAccessorMethodResult;
+
+static void ResolveIvarGet(GPBFieldDescriptor *field,
+                           ResolveIvarAccessorMethodResult *result) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_GET(NAME, TYPE, TRUE_NAME)                          \
+    case GPBDataType##NAME: {                                    \
+      result->impToAdd = imp_implementationWithBlock(^(id obj) { \
+        return GPBGetMessage##TRUE_NAME##Field(obj, field);      \
+       });                                                       \
+      result->encodingSelector = @selector(get##NAME);           \
+      break;                                                     \
+    }
+#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME)                   \
+    case GPBDataType##NAME: {                                    \
+      result->impToAdd = imp_implementationWithBlock(^(id obj) { \
+        return GPBGetObjectIvarWithField(obj, field);            \
+       });                                                       \
+      result->encodingSelector = @selector(get##NAME);           \
+      break;                                                     \
+    }
+      CASE_GET(Bool, BOOL, Bool)
+      CASE_GET(Fixed32, uint32_t, UInt32)
+      CASE_GET(SFixed32, int32_t, Int32)
+      CASE_GET(Float, float, Float)
+      CASE_GET(Fixed64, uint64_t, UInt64)
+      CASE_GET(SFixed64, int64_t, Int64)
+      CASE_GET(Double, double, Double)
+      CASE_GET(Int32, int32_t, Int32)
+      CASE_GET(Int64, int64_t, Int64)
+      CASE_GET(SInt32, int32_t, Int32)
+      CASE_GET(SInt64, int64_t, Int64)
+      CASE_GET(UInt32, uint32_t, UInt32)
+      CASE_GET(UInt64, uint64_t, UInt64)
+      CASE_GET_OBJECT(Bytes, id, Object)
+      CASE_GET_OBJECT(String, id, Object)
+      CASE_GET_OBJECT(Message, id, Object)
+      CASE_GET_OBJECT(Group, id, Object)
+      CASE_GET(Enum, int32_t, Enum)
+#undef CASE_GET
+  }
+}
+
+static void ResolveIvarSet(GPBFieldDescriptor *field,
+                           GPBFileSyntax syntax,
+                           ResolveIvarAccessorMethodResult *result) {
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  switch (fieldDataType) {
+#define CASE_SET(NAME, TYPE, TRUE_NAME)                                       \
+    case GPBDataType##NAME: {                                                 \
+      result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {  \
+        return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
+      });                                                                     \
+      result->encodingSelector = @selector(set##NAME:);                       \
+      break;                                                                  \
+    }
+      CASE_SET(Bool, BOOL, Bool)
+      CASE_SET(Fixed32, uint32_t, UInt32)
+      CASE_SET(SFixed32, int32_t, Int32)
+      CASE_SET(Float, float, Float)
+      CASE_SET(Fixed64, uint64_t, UInt64)
+      CASE_SET(SFixed64, int64_t, Int64)
+      CASE_SET(Double, double, Double)
+      CASE_SET(Int32, int32_t, Int32)
+      CASE_SET(Int64, int64_t, Int64)
+      CASE_SET(SInt32, int32_t, Int32)
+      CASE_SET(SInt64, int64_t, Int64)
+      CASE_SET(UInt32, uint32_t, UInt32)
+      CASE_SET(UInt64, uint64_t, UInt64)
+      CASE_SET(Bytes, id, Object)
+      CASE_SET(String, id, Object)
+      CASE_SET(Message, id, Object)
+      CASE_SET(Group, id, Object)
+      CASE_SET(Enum, int32_t, Enum)
+#undef CASE_SET
+  }
+}
+
++ (BOOL)resolveInstanceMethod:(SEL)sel {
+  const GPBDescriptor *descriptor = [self descriptor];
+  if (!descriptor) {
+    return NO;
+  }
+
+  // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given
+  // message should not have has support (done in GPBDescriptor.m), so there is
+  // no need for checks here to see if has*/setHas* are allowed.
+
+  ResolveIvarAccessorMethodResult result = {NULL, NULL};
+  for (GPBFieldDescriptor *field in descriptor->fields_) {
+    BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
+    if (!isMapOrArray) {
+      // Single fields.
+      if (sel == field->getSel_) {
+        ResolveIvarGet(field, &result);
+        break;
+      } else if (sel == field->setSel_) {
+        ResolveIvarSet(field, descriptor.file.syntax, &result);
+        break;
+      } else if (sel == field->hasOrCountSel_) {
+        int32_t index = GPBFieldHasIndex(field);
+        uint32_t fieldNum = GPBFieldNumber(field);
+        result.impToAdd = imp_implementationWithBlock(^(id obj) {
+          return GPBGetHasIvar(obj, index, fieldNum);
+        });
+        result.encodingSelector = @selector(getBool);
+        break;
+      } else if (sel == field->setHasSel_) {
+        result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
+          if (value) {
+            [NSException raise:NSInvalidArgumentException
+                        format:@"%@: %@ can only be set to NO (to clear field).",
+                               [obj class],
+                               NSStringFromSelector(field->setHasSel_)];
+          }
+          GPBClearMessageField(obj, field);
+        });
+        result.encodingSelector = @selector(setBool:);
+        break;
+      } else {
+        GPBOneofDescriptor *oneof = field->containingOneof_;
+        if (oneof && (sel == oneof->caseSel_)) {
+          int32_t index = GPBFieldHasIndex(field);
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
+            return GPBGetHasOneof(obj, index);
+          });
+          result.encodingSelector = @selector(getEnum);
+          break;
+        }
+      }
+    } else {
+      // map<>/repeated fields.
+      if (sel == field->getSel_) {
+        if (field.fieldType == GPBFieldTypeRepeated) {
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
+            return GetArrayIvarWithField(obj, field);
+          });
+        } else {
+          result.impToAdd = imp_implementationWithBlock(^(id obj) {
+            return GetMapIvarWithField(obj, field);
+          });
+        }
+        result.encodingSelector = @selector(getArray);
+        break;
+      } else if (sel == field->setSel_) {
+        // Local for syntax so the block can directly capture it and not the
+        // full lookup.
+        const GPBFileSyntax syntax = descriptor.file.syntax;
+        result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+          return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+        });
+        result.encodingSelector = @selector(setArray:);
+        break;
+      } else if (sel == field->hasOrCountSel_) {
+        result.impToAdd = imp_implementationWithBlock(^(id obj) {
+          // Type doesn't matter, all *Array and *Dictionary types support
+          // -count.
+          NSArray *arrayOrMap =
+              GPBGetObjectIvarWithFieldNoAutocreate(obj, field);
+          return [arrayOrMap count];
+        });
+        result.encodingSelector = @selector(getArrayCount);
+        break;
+      }
+    }
+  }
+  if (result.impToAdd) {
+    const char *encoding =
+        GPBMessageEncodingForSelector(result.encodingSelector, YES);
+    BOOL methodAdded = class_addMethod(descriptor.messageClass, sel,
+                                       result.impToAdd, encoding);
+    return methodAdded;
+  }
+  return [super resolveInstanceMethod:sel];
+}
+
++ (BOOL)resolveClassMethod:(SEL)sel {
+  // Extensions scoped to a Message and looked up via class methods.
+  if (GPBResolveExtensionClassMethod(self, sel)) {
+    return YES;
+  }
+  return [super resolveClassMethod:sel];
+}
+
+#pragma mark - NSCoding Support
+
++ (BOOL)supportsSecureCoding {
+  return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [self init];
+  if (self) {
+    NSData *data =
+        [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey];
+    if (data.length) {
+      [self mergeFromData:data extensionRegistry:nil];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  NSData *data = [self data];
+  if (data.length) {
+    [aCoder encodeObject:data forKey:kGPBDataCoderKey];
+  }
+}
+
+#pragma mark - KVC Support
+
++ (BOOL)accessInstanceVariablesDirectly {
+  // Make sure KVC doesn't use instance variables.
+  return NO;
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBMessage_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBMessage_PackagePrivate.h
new file mode 100644
index 0000000..478db2c
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBMessage_PackagePrivate.h
@@ -0,0 +1,143 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBMessage.h"
+
+#import <libkern/OSAtomic.h>
+
+#import "GPBBootstrap.h"
+
+typedef struct GPBMessage_Storage {
+  uint32_t _has_storage_[0];
+} GPBMessage_Storage;
+
+typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
+
+@interface GPBMessage () {
+ @package
+  // NOTE: Because of the +allocWithZone code using NSAllocateObject(),
+  // this structure should ideally always be kept pointer aligned where the
+  // real storage starts is also pointer aligned. The compiler/runtime already
+  // do this, but it may not be documented.
+
+  // A pointer to the actual fields of the subclasses. The actual structure
+  // pointed to by this pointer will depend on the subclass.
+  // All of the actual structures will start the same as
+  // GPBMessage_Storage with _has_storage__ as the first field.
+  // Kept public because static functions need to access it.
+  GPBMessage_StoragePtr messageStorage_;
+
+  // A lock to provide mutual exclusion from internal data that can be modified
+  // by *read* operations such as getters (autocreation of message fields and
+  // message extensions, not setting of values). Used to guarantee thread safety
+  // for concurrent reads on the message.
+  // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
+  // pointed out that they are vulnerable to live locking on iOS in cases of
+  // priority inversion:
+  //   http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
+  //   https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
+  // Use of readOnlySemaphore_ must be prefaced by a call to
+  // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows
+  // readOnlySemaphore_ to be only created when actually needed.
+  dispatch_once_t readOnlySemaphoreCreationOnce_;
+  dispatch_semaphore_t readOnlySemaphore_;
+}
+
+// Gets an extension value without autocreating the result if not found. (i.e.
+// returns nil if the extension is not set)
+- (id)getExistingExtension:(GPBExtensionDescriptor *)extension;
+
+// Returns an array of GPBExtensionDescriptor* for all the extensions currently
+// in use on the message.  They are sorted by field number.
+- (NSArray *)sortedExtensionsInUse;
+
+// Parses a message of this type from the input and merges it with this
+// message.
+//
+// Warning:  This does not verify that all required fields are present in
+// the input message.
+// Note:  The caller should call
+// -[CodedInputStream checkLastTagWas:] after calling this to
+// verify that the last tag seen was the appropriate end-group tag,
+// or zero for EOF.
+// NOTE: This will throw if there is an error while parsing.
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Parses the next delimited message of this type from the input and merges it
+// with this message.
+- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+                         extensionRegistry:
+                             (GPBExtensionRegistry *)extensionRegistry;
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
+
+@end
+
+CF_EXTERN_C_BEGIN
+
+
+// Call this before using the readOnlySemaphore_. This ensures it is created only once.
+NS_INLINE void GPBPrepareReadOnlySemaphore(GPBMessage *self) {
+  dispatch_once(&self->readOnlySemaphoreCreationOnce_, ^{
+    self->readOnlySemaphore_ = dispatch_semaphore_create(1);
+  });
+}
+
+// Returns a new instance that was automatically created by |autocreator| for
+// its field |field|.
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
+                                            GPBMessage *autocreator,
+                                            GPBFieldDescriptor *field)
+    __attribute__((ns_returns_retained));
+
+// Returns whether |message| autocreated this message. This is NO if the message
+// was not autocreated by |message| or if it has been mutated since
+// autocreation.
+BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent);
+
+// Call this when you mutate a message. It will cause the message to become
+// visible to its autocreator.
+void GPBBecomeVisibleToAutocreator(GPBMessage *self);
+
+// Call this when an array/dictionary is mutated so the parent message that
+// autocreated it can react.
+void GPBAutocreatedArrayModified(GPBMessage *self, id array);
+void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary);
+
+// Clear the autocreator, if any. Asserts if the autocreator still has an
+// autocreated reference to this message.
+void GPBClearMessageAutocreator(GPBMessage *self);
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.h b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.h
new file mode 100644
index 0000000..677903e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.h
@@ -0,0 +1,57 @@
+// 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.
+
+#import "GPBBootstrap.h"
+
+#import "GPBArray.h"
+#import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor.h"
+#import "GPBDictionary.h"
+#import "GPBExtensionRegistry.h"
+#import "GPBMessage.h"
+#import "GPBRootObject.h"
+#import "GPBUnknownField.h"
+#import "GPBUnknownFieldSet.h"
+#import "GPBUtilities.h"
+#import "GPBWellKnownTypes.h"
+#import "GPBWireFormat.h"
+
+// Well-known proto types
+#import "google/protobuf/Any.pbobjc.h"
+#import "google/protobuf/Api.pbobjc.h"
+#import "google/protobuf/Duration.pbobjc.h"
+#import "google/protobuf/Empty.pbobjc.h"
+#import "google/protobuf/FieldMask.pbobjc.h"
+#import "google/protobuf/SourceContext.pbobjc.h"
+#import "google/protobuf/Struct.pbobjc.h"
+#import "google/protobuf/Timestamp.pbobjc.h"
+#import "google/protobuf/Type.pbobjc.h"
+#import "google/protobuf/Wrappers.pbobjc.h"
diff --git a/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.m b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.m
new file mode 100644
index 0000000..8512af7
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers.m
@@ -0,0 +1,60 @@
+// 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.
+
+// If you want to build protocol buffers in your own project without adding the
+// project dependency, you can just add this file.
+
+#import "GPBArray.m"
+#import "GPBCodedInputStream.m"
+#import "GPBCodedOutputStream.m"
+#import "GPBDescriptor.m"
+#import "GPBDictionary.m"
+#import "GPBExtensionInternals.m"
+#import "GPBExtensionRegistry.m"
+#import "GPBMessage.m"
+#import "GPBRootObject.m"
+#import "GPBUnknownField.m"
+#import "GPBUnknownFieldSet.m"
+#import "GPBUtilities.m"
+#import "GPBWellKnownTypes.m"
+#import "GPBWireFormat.m"
+
+// Duration and Timestamp are #imported into GPBWellKnownTypes.m to the
+// Objective C categories added will always be linked in with the classes.
+#import "google/protobuf/Any.pbobjc.m"
+#import "google/protobuf/Api.pbobjc.m"
+// #import "google/protobuf/Duration.pbobjc.m"
+#import "google/protobuf/Empty.pbobjc.m"
+#import "google/protobuf/FieldMask.pbobjc.m"
+#import "google/protobuf/SourceContext.pbobjc.m"
+#import "google/protobuf/Struct.pbobjc.m"
+// #import "google/protobuf/Timestamp.pbobjc.m"
+#import "google/protobuf/Type.pbobjc.m"
+#import "google/protobuf/Wrappers.pbobjc.m"
diff --git a/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers_RuntimeSupport.h
new file mode 100644
index 0000000..fea75b9
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBProtocolBuffers_RuntimeSupport.h
@@ -0,0 +1,40 @@
+// 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.
+
+// This header is meant to only be used by the generated source, it should not
+// be included in code using protocol buffers.
+
+#import "GPBProtocolBuffers.h"
+
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBExtensionInternals.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBRootObject_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
diff --git a/src/third_party/protobuf-3/objectivec/GPBRootObject.h b/src/third_party/protobuf-3/objectivec/GPBRootObject.h
new file mode 100644
index 0000000..c05b5c6
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBRootObject.h
@@ -0,0 +1,47 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+@class GPBExtensionRegistry;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Every generated proto file defines a local "Root" class that exposes a
+/// @c GPBExtensionRegistry for all the extensions defined by that file and
+/// the files it depends on.
+@interface GPBRootObject : NSObject
+
+/// An extension registry for the given file and all the files it depends on.
++ (GPBExtensionRegistry *)extensionRegistry;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBRootObject.m b/src/third_party/protobuf-3/objectivec/GPBRootObject.m
new file mode 100644
index 0000000..4570716
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBRootObject.m
@@ -0,0 +1,230 @@
+// 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.
+
+#import "GPBRootObject_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+
+#import "GPBDescriptor.h"
+#import "GPBExtensionRegistry.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+@interface GPBExtensionDescriptor (GPBRootObject)
+// Get singletonName as a c string.
+- (const char *)singletonNameC;
+@end
+
+@implementation GPBRootObject
+
+// Taken from http://www.burtleburtle.net/bob/hash/doobs.html
+// Public Domain
+static uint32_t jenkins_one_at_a_time_hash(const char *key) {
+  uint32_t hash = 0;
+  for (uint32_t i = 0; key[i] != '\0'; ++i) {
+    hash += key[i];
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+  }
+  hash += (hash << 3);
+  hash ^= (hash >> 11);
+  hash += (hash << 15);
+  return hash;
+}
+
+// Key methods for our custom CFDictionary.
+// Note that the dictionary lasts for the lifetime of our app, so no need
+// to worry about deallocation. All of the items are added to it at
+// startup, and so the keys don't need to be retained/released.
+// Keys are NULL terminated char *.
+static const void *GPBRootExtensionKeyRetain(CFAllocatorRef allocator,
+                                             const void *value) {
+#pragma unused(allocator)
+  return value;
+}
+
+static void GPBRootExtensionKeyRelease(CFAllocatorRef allocator,
+                                       const void *value) {
+#pragma unused(allocator)
+#pragma unused(value)
+}
+
+static CFStringRef GPBRootExtensionCopyKeyDescription(const void *value) {
+  const char *key = (const char *)value;
+  return CFStringCreateWithCString(kCFAllocatorDefault, key,
+                                   kCFStringEncodingUTF8);
+}
+
+static Boolean GPBRootExtensionKeyEqual(const void *value1,
+                                        const void *value2) {
+  const char *key1 = (const char *)value1;
+  const char *key2 = (const char *)value2;
+  return strcmp(key1, key2) == 0;
+}
+
+static CFHashCode GPBRootExtensionKeyHash(const void *value) {
+  const char *key = (const char *)value;
+  return jenkins_one_at_a_time_hash(key);
+}
+
+// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
+// pointed out that they are vulnerable to live locking on iOS in cases of
+// priority inversion:
+//   http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
+//   https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
+static dispatch_semaphore_t gExtensionSingletonDictionarySemaphore;
+static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL;
+static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL;
+
++ (void)initialize {
+  // Ensure the global is started up.
+  if (!gExtensionSingletonDictionary) {
+    gExtensionSingletonDictionarySemaphore = dispatch_semaphore_create(1);
+    CFDictionaryKeyCallBacks keyCallBacks = {
+      // See description above for reason for using custom dictionary.
+      0,
+      GPBRootExtensionKeyRetain,
+      GPBRootExtensionKeyRelease,
+      GPBRootExtensionCopyKeyDescription,
+      GPBRootExtensionKeyEqual,
+      GPBRootExtensionKeyHash,
+    };
+    gExtensionSingletonDictionary =
+        CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
+                                  &kCFTypeDictionaryValueCallBacks);
+    gDefaultExtensionRegistry = [[GPBExtensionRegistry alloc] init];
+  }
+
+  if ([self superclass] == [GPBRootObject class]) {
+    // This is here to start up all the per file "Root" subclasses.
+    // This must be done in initialize to enforce thread safety of start up of
+    // the protocol buffer library.
+    [self extensionRegistry];
+  }
+}
+
++ (GPBExtensionRegistry *)extensionRegistry {
+  // Is overridden in all the subclasses that provide extensions to provide the
+  // per class one.
+  return gDefaultExtensionRegistry;
+}
+
++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field {
+  const char *key = [field singletonNameC];
+  dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
+                          DISPATCH_TIME_FOREVER);
+  CFDictionarySetValue(gExtensionSingletonDictionary, key, field);
+  dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
+}
+
+static id ExtensionForName(id self, SEL _cmd) {
+  // Really fast way of doing "classname_selName".
+  // This came up as a hotspot (creation of NSString *) when accessing a
+  // lot of extensions.
+  const char *selName = sel_getName(_cmd);
+  if (selName[0] == '_') {
+    return nil;  // Apple internal selector.
+  }
+  size_t selNameLen = 0;
+  while (1) {
+    char c = selName[selNameLen];
+    if (c == '\0') {  // String end.
+      break;
+    }
+    if (c == ':') {
+      return nil;  // Selector took an arg, not one of the runtime methods.
+    }
+    ++selNameLen;
+  }
+
+  const char *className = class_getName(self);
+  size_t classNameLen = strlen(className);
+  char key[classNameLen + selNameLen + 2];
+  memcpy(key, className, classNameLen);
+  key[classNameLen] = '_';
+  memcpy(&key[classNameLen + 1], selName, selNameLen);
+  key[classNameLen + 1 + selNameLen] = '\0';
+
+  // NOTE: Even though this method is called from another C function,
+  // gExtensionSingletonDictionarySemaphore and gExtensionSingletonDictionary
+  // will always be initialized. This is because this call flow is just to
+  // lookup the Extension, meaning the code is calling an Extension class
+  // message on a Message or Root class. This guarantees that the class was
+  // initialized and Message classes ensure their Root was also initialized.
+  NSAssert(gExtensionSingletonDictionary, @"Startup order broken!");
+
+  dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
+                          DISPATCH_TIME_FOREVER);
+  id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key);
+  if (extension) {
+    // The method is getting wired in to the class, so no need to keep it in
+    // the dictionary.
+    CFDictionaryRemoveValue(gExtensionSingletonDictionary, key);
+  }
+  dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
+  return extension;
+}
+
+BOOL GPBResolveExtensionClassMethod(Class self, SEL sel) {
+  // Another option would be to register the extensions with the class at
+  // globallyRegisterExtension:
+  // Timing the two solutions, this solution turned out to be much faster
+  // and reduced startup time, and runtime memory.
+  // The advantage to globallyRegisterExtension is that it would reduce the
+  // size of the protos somewhat because the singletonNameC wouldn't need
+  // to include the class name. For a class with a lot of extensions it
+  // can add up. You could also significantly reduce the code complexity of this
+  // file.
+  id extension = ExtensionForName(self, sel);
+  if (extension != nil) {
+    const char *encoding =
+        GPBMessageEncodingForSelector(@selector(getClassValue), NO);
+    Class metaClass = objc_getMetaClass(class_getName(self));
+    IMP imp = imp_implementationWithBlock(^(id obj) {
+#pragma unused(obj)
+      return extension;
+    });
+    if (class_addMethod(metaClass, sel, imp, encoding)) {
+      return YES;
+    }
+  }
+  return NO;
+}
+
+
++ (BOOL)resolveClassMethod:(SEL)sel {
+  if (GPBResolveExtensionClassMethod(self, sel)) {
+    return YES;
+  }
+  return [super resolveClassMethod:sel];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBRootObject_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBRootObject_PackagePrivate.h
new file mode 100644
index 0000000..3c8f09c
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBRootObject_PackagePrivate.h
@@ -0,0 +1,46 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBRootObject.h"
+
+@class GPBExtensionDescriptor;
+
+@interface GPBRootObject ()
+
+// Globally register.
++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field;
+
+@end
+
+// Returns YES if the selector was resolved and added to the class,
+// NO otherwise.
+BOOL GPBResolveExtensionClassMethod(Class self, SEL sel);
diff --git a/src/third_party/protobuf-3/objectivec/GPBRuntimeTypes.h b/src/third_party/protobuf-3/objectivec/GPBRuntimeTypes.h
new file mode 100644
index 0000000..0a38b11
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBRuntimeTypes.h
@@ -0,0 +1,102 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBBootstrap.h"
+
+@class GPBEnumDescriptor;
+@class GPBMessage;
+@class GPBInt32Array;
+
+// Function used to verify that a given value can be represented by an
+// enum type.
+typedef BOOL (*GPBEnumValidationFunc)(int32_t);
+
+// Function used to fetch an EnumDescriptor.
+typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void);
+
+// Magic values used for when an the at runtime to indicate an enum value
+// that wasn't know at compile time.
+enum {
+  kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF,
+};
+
+// A union for storing all possible Protobuf values.
+// Note that owner is responsible for memory management of object types.
+typedef union {
+  BOOL valueBool;
+  int32_t valueInt32;
+  int64_t valueInt64;
+  uint32_t valueUInt32;
+  uint64_t valueUInt64;
+  float valueFloat;
+  double valueDouble;
+  GPB_UNSAFE_UNRETAINED NSData *valueData;
+  GPB_UNSAFE_UNRETAINED NSString *valueString;
+  GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage;
+  int32_t valueEnum;
+} GPBGenericValue;
+
+// Do not change the order of this enum (or add things to it) without thinking
+// about it very carefully. There are several things that depend on the order.
+typedef NS_ENUM(uint8_t, GPBDataType) {
+  GPBDataTypeBool = 0,
+  GPBDataTypeFixed32,
+  GPBDataTypeSFixed32,
+  GPBDataTypeFloat,
+  GPBDataTypeFixed64,
+  GPBDataTypeSFixed64,
+  GPBDataTypeDouble,
+  GPBDataTypeInt32,
+  GPBDataTypeInt64,
+  GPBDataTypeSInt32,
+  GPBDataTypeSInt64,
+  GPBDataTypeUInt32,
+  GPBDataTypeUInt64,
+  GPBDataTypeBytes,
+  GPBDataTypeString,
+  GPBDataTypeMessage,
+  GPBDataTypeGroup,
+  GPBDataTypeEnum,
+};
+
+enum {
+  // A count of the number of types in GPBDataType. Separated out from the
+  // GPBDataType enum to avoid warnings regarding not handling
+  // GPBDataType_Count in switch statements.
+  GPBDataType_Count = GPBDataTypeEnum + 1
+};
+
+// An extension range.
+typedef struct GPBExtensionRange {
+  uint32_t start;  // inclusive
+  uint32_t end;    // exclusive
+} GPBExtensionRange;
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownField.h b/src/third_party/protobuf-3/objectivec/GPBUnknownField.h
new file mode 100644
index 0000000..0f301e4
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownField.h
@@ -0,0 +1,89 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+@class GPBCodedOutputStream;
+@class GPBUInt32Array;
+@class GPBUInt64Array;
+@class GPBUnknownFieldSet;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Store an unknown field. These are used in conjunction with @c GPBUnknownFieldSet
+@interface GPBUnknownField : NSObject<NSCopying>
+
+/// The field number the data is stored under.
+@property(nonatomic, readonly, assign) int32_t number;
+
+/// An array of varint values for this field.
+@property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
+
+/// An array of fixed32 values for this field.
+@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
+
+/// An array of fixed64 values for this field.
+@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
+
+/// An array of data values for this field.
+@property(nonatomic, readonly, strong) NSArray<NSData*> *lengthDelimitedList;
+
+/// An array of groups of values for this field.
+@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet*> *groupList;
+
+
+/// Add a value to the varintList.
+///
+/// @param value The value to add.
+- (void)addVarint:(uint64_t)value;
+
+/// Add a value to the fixed32List.
+///
+/// @param value The value to add.
+- (void)addFixed32:(uint32_t)value;
+
+/// Add a value to the fixed64List.
+///
+/// @param value The value to add.
+- (void)addFixed64:(uint64_t)value;
+
+/// Add a value to the lengthDelimitedList.
+///
+/// @param value The value to add.
+- (void)addLengthDelimited:(NSData *)value;
+
+/// Add a value to the groupList.
+///
+/// @param value The value to add.
+- (void)addGroup:(GPBUnknownFieldSet *)value;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownField.m b/src/third_party/protobuf-3/objectivec/GPBUnknownField.m
new file mode 100644
index 0000000..0e29bde
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownField.m
@@ -0,0 +1,326 @@
+// 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.
+
+#import "GPBUnknownField_PackagePrivate.h"
+
+#import "GPBArray.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
+
+@implementation GPBUnknownField {
+ @protected
+  int32_t number_;
+  GPBUInt64Array *mutableVarintList_;
+  GPBUInt32Array *mutableFixed32List_;
+  GPBUInt64Array *mutableFixed64List_;
+  NSMutableArray<NSData*> *mutableLengthDelimitedList_;
+  NSMutableArray<GPBUnknownFieldSet*> *mutableGroupList_;
+}
+
+@synthesize number = number_;
+@synthesize varintList = mutableVarintList_;
+@synthesize fixed32List = mutableFixed32List_;
+@synthesize fixed64List = mutableFixed64List_;
+@synthesize lengthDelimitedList = mutableLengthDelimitedList_;
+@synthesize groupList = mutableGroupList_;
+
+- (instancetype)initWithNumber:(int32_t)number {
+  if ((self = [super init])) {
+    number_ = number;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [mutableVarintList_ release];
+  [mutableFixed32List_ release];
+  [mutableFixed64List_ release];
+  [mutableLengthDelimitedList_ release];
+  [mutableGroupList_ release];
+
+  [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  GPBUnknownField *result =
+      [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
+  result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
+  result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
+  result->mutableLengthDelimitedList_ =
+      [mutableLengthDelimitedList_ copyWithZone:zone];
+  result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone];
+  if (mutableGroupList_.count) {
+    result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone]
+        initWithCapacity:mutableGroupList_.count];
+    for (GPBUnknownFieldSet *group in mutableGroupList_) {
+      GPBUnknownFieldSet *copied = [group copyWithZone:zone];
+      [result->mutableGroupList_ addObject:copied];
+      [copied release];
+    }
+  }
+  return result;
+}
+
+- (BOOL)isEqual:(id)object {
+  if (self == object) return YES;
+  if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
+  GPBUnknownField *field = (GPBUnknownField *)object;
+  BOOL equalVarint =
+      (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
+      [mutableVarintList_ isEqual:field->mutableVarintList_];
+  if (!equalVarint) return NO;
+  BOOL equalFixed32 = (mutableFixed32List_.count == 0 &&
+                       field->mutableFixed32List_.count == 0) ||
+                      [mutableFixed32List_ isEqual:field->mutableFixed32List_];
+  if (!equalFixed32) return NO;
+  BOOL equalFixed64 = (mutableFixed64List_.count == 0 &&
+                       field->mutableFixed64List_.count == 0) ||
+                      [mutableFixed64List_ isEqual:field->mutableFixed64List_];
+  if (!equalFixed64) return NO;
+  BOOL equalLDList =
+      (mutableLengthDelimitedList_.count == 0 &&
+       field->mutableLengthDelimitedList_.count == 0) ||
+      [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_];
+  if (!equalLDList) return NO;
+  BOOL equalGroupList =
+      (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
+      [mutableGroupList_ isEqual:field->mutableGroupList_];
+  if (!equalGroupList) return NO;
+  return YES;
+}
+
+- (NSUInteger)hash {
+  // Just mix the hashes of the possible sub arrays.
+  const int prime = 31;
+  NSUInteger result = prime + [mutableVarintList_ hash];
+  result = prime * result + [mutableFixed32List_ hash];
+  result = prime * result + [mutableFixed64List_ hash];
+  result = prime * result + [mutableLengthDelimitedList_ hash];
+  result = prime * result + [mutableGroupList_ hash];
+  return result;
+}
+
+- (void)writeToOutput:(GPBCodedOutputStream *)output {
+  NSUInteger count = mutableVarintList_.count;
+  if (count > 0) {
+    [output writeUInt64Array:number_ values:mutableVarintList_ tag:0];
+  }
+  count = mutableFixed32List_.count;
+  if (count > 0) {
+    [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0];
+  }
+  count = mutableFixed64List_.count;
+  if (count > 0) {
+    [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0];
+  }
+  count = mutableLengthDelimitedList_.count;
+  if (count > 0) {
+    [output writeBytesArray:number_ values:mutableLengthDelimitedList_];
+  }
+  count = mutableGroupList_.count;
+  if (count > 0) {
+    [output writeUnknownGroupArray:number_ values:mutableGroupList_];
+  }
+}
+
+- (size_t)serializedSize {
+  __block size_t result = 0;
+  int32_t number = number_;
+  [mutableVarintList_
+      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        result += GPBComputeUInt64Size(number, value);
+      }];
+
+  [mutableFixed32List_
+      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        result += GPBComputeFixed32Size(number, value);
+      }];
+
+  [mutableFixed64List_
+      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        result += GPBComputeFixed64Size(number, value);
+      }];
+
+  for (NSData *data in mutableLengthDelimitedList_) {
+    result += GPBComputeBytesSize(number, data);
+  }
+
+  for (GPBUnknownFieldSet *set in mutableGroupList_) {
+    result += GPBComputeUnknownGroupSize(number, set);
+  }
+
+  return result;
+}
+
+- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
+  for (NSData *data in mutableLengthDelimitedList_) {
+    [output writeRawMessageSetExtension:number_ value:data];
+  }
+}
+
+- (size_t)serializedSizeAsMessageSetExtension {
+  size_t result = 0;
+  for (NSData *data in mutableLengthDelimitedList_) {
+    result += GPBComputeRawMessageSetExtensionSize(number_, data);
+  }
+  return result;
+}
+
+- (NSString *)description {
+  NSMutableString *description = [NSMutableString
+      stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_];
+  [mutableVarintList_
+      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        [description appendFormat:@"\t%llu\n", value];
+      }];
+
+  [mutableFixed32List_
+      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        [description appendFormat:@"\t%u\n", value];
+      }];
+
+  [mutableFixed64List_
+      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+        [description appendFormat:@"\t%llu\n", value];
+      }];
+
+  for (NSData *data in mutableLengthDelimitedList_) {
+    [description appendFormat:@"\t%@\n", data];
+  }
+
+  for (GPBUnknownFieldSet *set in mutableGroupList_) {
+    [description appendFormat:@"\t%@\n", set];
+  }
+  [description appendString:@"}"];
+  return description;
+}
+
+- (void)mergeFromField:(GPBUnknownField *)other {
+  GPBUInt64Array *otherVarintList = other.varintList;
+  if (otherVarintList.count > 0) {
+    if (mutableVarintList_ == nil) {
+      mutableVarintList_ = [otherVarintList copy];
+    } else {
+      [mutableVarintList_ addValuesFromArray:otherVarintList];
+    }
+  }
+
+  GPBUInt32Array *otherFixed32List = other.fixed32List;
+  if (otherFixed32List.count > 0) {
+    if (mutableFixed32List_ == nil) {
+      mutableFixed32List_ = [otherFixed32List copy];
+    } else {
+      [mutableFixed32List_ addValuesFromArray:otherFixed32List];
+    }
+  }
+
+  GPBUInt64Array *otherFixed64List = other.fixed64List;
+  if (otherFixed64List.count > 0) {
+    if (mutableFixed64List_ == nil) {
+      mutableFixed64List_ = [otherFixed64List copy];
+    } else {
+      [mutableFixed64List_ addValuesFromArray:otherFixed64List];
+    }
+  }
+
+  NSArray *otherLengthDelimitedList = other.lengthDelimitedList;
+  if (otherLengthDelimitedList.count > 0) {
+    if (mutableLengthDelimitedList_ == nil) {
+      mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy];
+    } else {
+      [mutableLengthDelimitedList_
+          addObjectsFromArray:otherLengthDelimitedList];
+    }
+  }
+
+  NSArray *otherGroupList = other.groupList;
+  if (otherGroupList.count > 0) {
+    if (mutableGroupList_ == nil) {
+      mutableGroupList_ =
+          [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
+    }
+    // Make our own mutable copies.
+    for (GPBUnknownFieldSet *group in otherGroupList) {
+      GPBUnknownFieldSet *copied = [group copy];
+      [mutableGroupList_ addObject:copied];
+      [copied release];
+    }
+  }
+}
+
+- (void)addVarint:(uint64_t)value {
+  if (mutableVarintList_ == nil) {
+    mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
+  } else {
+    [mutableVarintList_ addValue:value];
+  }
+}
+
+- (void)addFixed32:(uint32_t)value {
+  if (mutableFixed32List_ == nil) {
+    mutableFixed32List_ =
+        [[GPBUInt32Array alloc] initWithValues:&value count:1];
+  } else {
+    [mutableFixed32List_ addValue:value];
+  }
+}
+
+- (void)addFixed64:(uint64_t)value {
+  if (mutableFixed64List_ == nil) {
+    mutableFixed64List_ =
+        [[GPBUInt64Array alloc] initWithValues:&value count:1];
+  } else {
+    [mutableFixed64List_ addValue:value];
+  }
+}
+
+- (void)addLengthDelimited:(NSData *)value {
+  if (mutableLengthDelimitedList_ == nil) {
+    mutableLengthDelimitedList_ =
+        [[NSMutableArray alloc] initWithObjects:&value count:1];
+  } else {
+    [mutableLengthDelimitedList_ addObject:value];
+  }
+}
+
+- (void)addGroup:(GPBUnknownFieldSet *)value {
+  if (mutableGroupList_ == nil) {
+    mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
+  } else {
+    [mutableGroupList_ addObject:value];
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.h b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.h
new file mode 100644
index 0000000..cf61299
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.h
@@ -0,0 +1,65 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+@class GPBUnknownField;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A collection of unknown fields.
+@interface GPBUnknownFieldSet : NSObject<NSCopying>
+
+/// Tests to see if the given field number has a value.
+///
+/// @param number The field number to check.
+///
+/// @return YES if there is an unknown field for the given field number.
+- (BOOL)hasField:(int32_t)number;
+
+/// Fetches the @c GPBUnknownField for the given field number.
+///
+/// @param number The field number to look up.
+///
+/// @return The @c GPBUnknownField or nil.
+- (nullable GPBUnknownField *)getField:(int32_t)number;
+
+/// Returns the number of fields in this set.
+- (NSUInteger)countOfFields;
+
+/// Adds the given field to the set.
+- (void)addField:(GPBUnknownField *)field;
+
+/// Returns an NSArray of the @c GPBUnknownFields sorted by the field numbers.
+- (NSArray<GPBUnknownField*> *)sortedFields;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.m b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.m
new file mode 100644
index 0000000..4ddc0d2
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet.m
@@ -0,0 +1,423 @@
+// 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.
+
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBUnknownField_PackagePrivate.h"
+#import "GPBUtilities.h"
+#import "GPBWireFormat.h"
+
+#pragma mark CFDictionaryKeyCallBacks
+
+// We use a custom dictionary here because our keys are numbers and
+// conversion back and forth from NSNumber was costing us performance.
+// If/when we move to C++ this could be done using a std::map and some
+// careful retain/release calls.
+
+static const void *GPBUnknownFieldSetKeyRetain(CFAllocatorRef allocator,
+                                               const void *value) {
+#pragma unused(allocator)
+  return value;
+}
+
+static void GPBUnknownFieldSetKeyRelease(CFAllocatorRef allocator,
+                                         const void *value) {
+#pragma unused(allocator)
+#pragma unused(value)
+}
+
+static CFStringRef GPBUnknownFieldSetCopyKeyDescription(const void *value) {
+  return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"),
+                                  (int)value);
+}
+
+static Boolean GPBUnknownFieldSetKeyEqual(const void *value1,
+                                          const void *value2) {
+  return value1 == value2;
+}
+
+static CFHashCode GPBUnknownFieldSetKeyHash(const void *value) {
+  return (CFHashCode)value;
+}
+
+#pragma mark Helpers
+
+static void checkNumber(int32_t number) {
+  if (number == 0) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Zero is not a valid field number."];
+  }
+}
+
+@implementation GPBUnknownFieldSet {
+ @package
+  CFMutableDictionaryRef fields_;
+}
+
+static void CopyWorker(const void *key, const void *value, void *context) {
+#pragma unused(key)
+  GPBUnknownField *field = value;
+  GPBUnknownFieldSet *result = context;
+
+  GPBUnknownField *copied = [field copy];
+  [result addField:copied];
+  [copied release];
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init];
+  if (fields_) {
+    CFDictionaryApplyFunction(fields_, CopyWorker, result);
+  }
+  return result;
+}
+
+- (void)dealloc {
+  if (fields_) {
+    CFRelease(fields_);
+  }
+  [super dealloc];
+}
+
+- (BOOL)isEqual:(id)object {
+  BOOL equal = NO;
+  if ([object isKindOfClass:[GPBUnknownFieldSet class]]) {
+    GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object;
+    if ((fields_ == NULL) && (set->fields_ == NULL)) {
+      equal = YES;
+    } else if ((fields_ != NULL) && (set->fields_ != NULL)) {
+      equal = CFEqual(fields_, set->fields_);
+    }
+  }
+  return equal;
+}
+
+- (NSUInteger)hash {
+  // Return the hash of the fields dictionary (or just some value).
+  if (fields_) {
+    return CFHash(fields_);
+  }
+  return (NSUInteger)[GPBUnknownFieldSet class];
+}
+
+#pragma mark - Public Methods
+
+- (BOOL)hasField:(int32_t)number {
+  ssize_t key = number;
+  return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO;
+}
+
+- (GPBUnknownField *)getField:(int32_t)number {
+  ssize_t key = number;
+  GPBUnknownField *result =
+      fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
+  return result;
+}
+
+- (NSUInteger)countOfFields {
+  return fields_ ? CFDictionaryGetCount(fields_) : 0;
+}
+
+- (NSArray *)sortedFields {
+  if (!fields_) return nil;
+  size_t count = CFDictionaryGetCount(fields_);
+  ssize_t keys[count];
+  GPBUnknownField *values[count];
+  CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
+                               (const void **)values);
+  struct GPBFieldPair {
+    ssize_t key;
+    GPBUnknownField *value;
+  } pairs[count];
+  for (size_t i = 0; i < count; ++i) {
+    pairs[i].key = keys[i];
+    pairs[i].value = values[i];
+  };
+  qsort_b(pairs, count, sizeof(struct GPBFieldPair),
+          ^(const void *first, const void *second) {
+            const struct GPBFieldPair *a = first;
+            const struct GPBFieldPair *b = second;
+            return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+          });
+  for (size_t i = 0; i < count; ++i) {
+    values[i] = pairs[i].value;
+  };
+  return [NSArray arrayWithObjects:values count:count];
+}
+
+#pragma mark - Internal Methods
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
+  if (!fields_) return;
+  size_t count = CFDictionaryGetCount(fields_);
+  ssize_t keys[count];
+  GPBUnknownField *values[count];
+  CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
+                               (const void **)values);
+  if (count > 1) {
+    struct GPBFieldPair {
+      ssize_t key;
+      GPBUnknownField *value;
+    } pairs[count];
+
+    for (size_t i = 0; i < count; ++i) {
+      pairs[i].key = keys[i];
+      pairs[i].value = values[i];
+    };
+    qsort_b(pairs, count, sizeof(struct GPBFieldPair),
+            ^(const void *first, const void *second) {
+              const struct GPBFieldPair *a = first;
+              const struct GPBFieldPair *b = second;
+              return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+            });
+    for (size_t i = 0; i < count; ++i) {
+      GPBUnknownField *value = pairs[i].value;
+      [value writeToOutput:output];
+    }
+  } else {
+    [values[0] writeToOutput:output];
+  }
+}
+
+- (NSString *)description {
+  NSMutableString *description = [NSMutableString
+      stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
+  NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @"  ");
+  [description appendString:textFormat];
+  [description appendString:@"}"];
+  return description;
+}
+
+static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value,
+                                             void *context) {
+#pragma unused(key)
+  GPBUnknownField *field = value;
+  size_t *result = context;
+  *result += [field serializedSize];
+}
+
+- (size_t)serializedSize {
+  size_t result = 0;
+  if (fields_) {
+    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize,
+                              &result);
+  }
+  return result;
+}
+
+static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key,
+                                                  const void *value,
+                                                  void *context) {
+#pragma unused(key)
+  GPBUnknownField *field = value;
+  GPBCodedOutputStream *output = context;
+  [field writeAsMessageSetExtensionToOutput:output];
+}
+
+- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output {
+  if (fields_) {
+    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo,
+                              output);
+  }
+}
+
+static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key,
+                                                         const void *value,
+                                                         void *context) {
+#pragma unused(key)
+  GPBUnknownField *field = value;
+  size_t *result = context;
+  *result += [field serializedSizeAsMessageSetExtension];
+}
+
+- (size_t)serializedSizeAsMessageSet {
+  size_t result = 0;
+  if (fields_) {
+    CFDictionaryApplyFunction(
+        fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result);
+  }
+  return result;
+}
+
+- (NSData *)data {
+  NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize];
+  GPBCodedOutputStream *output =
+      [[GPBCodedOutputStream alloc] initWithData:data];
+  [self writeToCodedOutputStream:output];
+  [output release];
+  return data;
+}
+
++ (BOOL)isFieldTag:(int32_t)tag {
+  return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup;
+}
+
+- (void)addField:(GPBUnknownField *)field {
+  int32_t number = [field number];
+  checkNumber(number);
+  if (!fields_) {
+    CFDictionaryKeyCallBacks keyCallBacks = {
+        // See description above for reason for using custom dictionary.
+        0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease,
+        GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual,
+        GPBUnknownFieldSetKeyHash,
+    };
+    fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+  }
+  ssize_t key = number;
+  CFDictionarySetValue(fields_, (const void *)key, field);
+}
+
+- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create {
+  ssize_t key = number;
+  GPBUnknownField *existing =
+      fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil;
+  if (!existing && create) {
+    existing = [[GPBUnknownField alloc] initWithNumber:number];
+    // This retains existing.
+    [self addField:existing];
+    [existing release];
+  }
+  return existing;
+}
+
+static void GPBUnknownFieldSetMergeUnknownFields(const void *key,
+                                                 const void *value,
+                                                 void *context) {
+#pragma unused(key)
+  GPBUnknownField *field = value;
+  GPBUnknownFieldSet *self = context;
+
+  int32_t number = [field number];
+  checkNumber(number);
+  GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO];
+  if (oldField) {
+    [oldField mergeFromField:field];
+  } else {
+    // Merge only comes from GPBMessage's mergeFrom:, so it means we are on
+    // mutable message and are an mutable instance, so make sure we need
+    // mutable fields.
+    GPBUnknownField *fieldCopy = [field copy];
+    [self addField:fieldCopy];
+    [fieldCopy release];
+  }
+}
+
+- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other {
+  if (other && other->fields_) {
+    CFDictionaryApplyFunction(other->fields_,
+                              GPBUnknownFieldSetMergeUnknownFields, self);
+  }
+}
+
+- (void)mergeFromData:(NSData *)data {
+  GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
+  [self mergeFromCodedInputStream:input];
+  [input checkLastTagWas:0];
+  [input release];
+}
+
+- (void)mergeVarintField:(int32_t)number value:(int32_t)value {
+  checkNumber(number);
+  [[self mutableFieldForNumber:number create:YES] addVarint:value];
+}
+
+- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input {
+  int32_t number = GPBWireFormatGetTagFieldNumber(tag);
+  GPBCodedInputStreamState *state = &input->state_;
+  switch (GPBWireFormatGetTagWireType(tag)) {
+    case GPBWireFormatVarint: {
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
+      [field addVarint:GPBCodedInputStreamReadInt64(state)];
+      return YES;
+    }
+    case GPBWireFormatFixed64: {
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
+      [field addFixed64:GPBCodedInputStreamReadFixed64(state)];
+      return YES;
+    }
+    case GPBWireFormatLengthDelimited: {
+      NSData *data = GPBCodedInputStreamReadRetainedBytes(state);
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
+      [field addLengthDelimited:data];
+      [data release];
+      return YES;
+    }
+    case GPBWireFormatStartGroup: {
+      GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init];
+      [input readUnknownGroup:number message:unknownFieldSet];
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
+      [field addGroup:unknownFieldSet];
+      [unknownFieldSet release];
+      return YES;
+    }
+    case GPBWireFormatEndGroup:
+      return NO;
+    case GPBWireFormatFixed32: {
+      GPBUnknownField *field = [self mutableFieldForNumber:number create:YES];
+      [field addFixed32:GPBCodedInputStreamReadFixed32(state)];
+      return YES;
+    }
+  }
+}
+
+- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData {
+  [[self mutableFieldForNumber:number create:YES]
+      addLengthDelimited:messageData];
+}
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
+  GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES];
+  [field addLengthDelimited:data];
+}
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input {
+  while (YES) {
+    int32_t tag = GPBCodedInputStreamReadTag(&input->state_);
+    if (tag == 0 || ![self mergeFieldFrom:tag input:input]) {
+      break;
+    }
+  }
+}
+
+- (void)getTags:(int32_t *)tags {
+  if (!fields_) return;
+  size_t count = CFDictionaryGetCount(fields_);
+  ssize_t keys[count];
+  CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL);
+  for (size_t i = 0; i < count; ++i) {
+    tags[i] = (int32_t)keys[i];
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet_PackagePrivate.h
new file mode 100644
index 0000000..e27127a
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownFieldSet_PackagePrivate.h
@@ -0,0 +1,61 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBUnknownFieldSet.h"
+
+@class GPBCodedOutputStream;
+@class GPBCodedInputStream;
+
+@interface GPBUnknownFieldSet ()
+
++ (BOOL)isFieldTag:(int32_t)tag;
+
+- (NSData *)data;
+
+- (size_t)serializedSize;
+- (size_t)serializedSizeAsMessageSet;
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
+- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output;
+
+- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other;
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input;
+- (void)mergeFromData:(NSData *)data;
+
+- (void)mergeVarintField:(int32_t)number value:(int32_t)value;
+- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input;
+- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData;
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBUnknownField_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBUnknownField_PackagePrivate.h
new file mode 100644
index 0000000..1fbce0f
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUnknownField_PackagePrivate.h
@@ -0,0 +1,49 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBUnknownField.h"
+
+@class GPBCodedOutputStream;
+
+@interface GPBUnknownField ()
+
+- (instancetype)initWithNumber:(int32_t)number;
+
+- (void)writeToOutput:(GPBCodedOutputStream *)output;
+- (size_t)serializedSize;
+
+- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output;
+- (size_t)serializedSizeAsMessageSetExtension;
+
+- (void)mergeFromField:(GPBUnknownField *)other;
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBUtilities.h b/src/third_party/protobuf-3/objectivec/GPBUtilities.h
new file mode 100644
index 0000000..b720932
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUtilities.h
@@ -0,0 +1,257 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBArray.h"
+#import "GPBMessage.h"
+#import "GPBRuntimeTypes.h"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Generates a string that should be a valid "Text Format" for the C++ version
+/// of Protocol Buffers.
+///
+///  @param message    The message to generate from.
+///  @param lineIndent A string to use as the prefix for all lines generated. Can
+///                    be nil if no extra indent is needed.
+///
+/// @return A @c NSString with the Text Format of the message.
+NSString *GPBTextFormatForMessage(GPBMessage *message,
+                                  NSString * __nullable lineIndent);
+
+/// Generates a string that should be a valid "Text Format" for the C++ version
+/// of Protocol Buffers.
+///
+///  @param unknownSet The unknown field set to generate from.
+///  @param lineIndent A string to use as the prefix for all lines generated. Can
+///                    be nil if no extra indent is needed.
+///
+/// @return A @c NSString with the Text Format of the unknown field set.
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet,
+                                          NSString * __nullable lineIndent);
+
+/// Test if the given field is set on a message.
+BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber);
+/// Test if the given field is set on a message.
+BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
+
+/// Clear the given field of a message.
+void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
+
+//%PDDM-EXPAND GPB_ACCESSORS()
+// This block of code is generated, do not edit it directly.
+
+
+//
+// Get/Set the given field of a message.
+//
+
+// Single Fields
+
+/// Gets the value of a bytes field.
+NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a bytes field.
+void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value);
+
+/// Gets the value of a string field.
+NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a string field.
+void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value);
+
+/// Gets the value of a message field.
+GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a message field.
+void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
+
+/// Gets the value of a group field.
+GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a group field.
+void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
+
+/// Gets the value of a bool field.
+BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a bool field.
+void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value);
+
+/// Gets the value of an int32 field.
+int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of an int32 field.
+void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+
+/// Gets the value of an uint32 field.
+uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of an uint32 field.
+void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value);
+
+/// Gets the value of an int64 field.
+int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of an int64 field.
+void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value);
+
+/// Gets the value of an uint64 field.
+uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of an uint64 field.
+void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value);
+
+/// Gets the value of a float field.
+float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a float field.
+void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value);
+
+/// Gets the value of a double field.
+double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a double field.
+void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value);
+
+/// Get the given enum field of a message. For proto3, if the value isn't a
+/// member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
+/// GPBGetMessageRawEnumField will bypass the check and return whatever value
+/// was set.
+int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Set the given enum field of a message. You can only set values that are
+/// members of the enum.
+void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+/// Get the given enum field of a message. No check is done to ensure the value
+/// was defined in the enum.
+int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Set the given enum field of a message. You can set the value to anything,
+/// even a value that is not a member of the enum.
+void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+
+// Repeated Fields
+
+/// Gets the value of a repeated field.
+///
+/// The result will be @c GPB*Array or @c NSMutableArray based on the
+/// field's type.
+id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a repeated field.
+///
+/// The value should be @c GPB*Array or @c NSMutableArray based on the
+/// field's type.
+void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+
+// Map Fields
+
+/// Gets the value of a map<> field.
+///
+/// The result will be @c GPB*Dictionary or @c NSMutableDictionary based on
+/// the field's type.
+id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
+/// Sets the value of a map<> field.
+///
+/// The object should be @c GPB*Dictionary or @c NSMutableDictionary based
+/// on the field's type.
+void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+
+//%PDDM-EXPAND-END GPB_ACCESSORS()
+
+// Returns an empty NSData to assign to byte fields when you wish
+// to assign them to empty. Prevents allocating a lot of little [NSData data]
+// objects.
+NSData *GPBEmptyNSData(void) __attribute__((pure));
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+
+//%PDDM-DEFINE GPB_ACCESSORS()
+//%
+//%//
+//%// Get/Set the given field of a message.
+//%//
+//%
+//%// Single Fields
+//%
+//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, , *)
+//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, , *)
+//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, , *)
+//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, , *)
+//%GPB_ACCESSOR_SINGLE(Bool, BOOL, )
+//%GPB_ACCESSOR_SINGLE(Int32, int32_t, n)
+//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t, n)
+//%GPB_ACCESSOR_SINGLE(Int64, int64_t, n)
+//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t, n)
+//%GPB_ACCESSOR_SINGLE(Float, float, )
+//%GPB_ACCESSOR_SINGLE(Double, double, )
+//%/// Get the given enum field of a message. For proto3, if the value isn't a
+//%/// member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
+//%/// GPBGetMessageRawEnumField will bypass the check and return whatever value
+//%/// was set.
+//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+//%/// Set the given enum field of a message. You can only set values that are
+//%/// members of the enum.
+//%void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+//%/// Get the given enum field of a message. No check is done to ensure the value
+//%/// was defined in the enum.
+//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
+//%/// Set the given enum field of a message. You can set the value to anything,
+//%/// even a value that is not a member of the enum.
+//%void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+//%
+//%// Repeated Fields
+//%
+//%/// Gets the value of a repeated field.
+//%///
+//%/// The result will be @c GPB*Array or @c NSMutableArray based on the
+//%/// field's type.
+//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
+//%/// Sets the value of a repeated field.
+//%///
+//%/// The value should be @c GPB*Array or @c NSMutableArray based on the
+//%/// field's type.
+//%void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+//%
+//%// Map Fields
+//%
+//%/// Gets the value of a map<> field.
+//%///
+//%/// The result will be @c GPB*Dictionary or @c NSMutableDictionary based on
+//%/// the field's type.
+//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
+//%/// Sets the value of a map<> field.
+//%///
+//%/// The object should be @c GPB*Dictionary or @c NSMutableDictionary based
+//%/// on the field's type.
+//%void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+//%
+
+//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE, AN)
+//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, )
+//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, TisP)
+//%/// Gets the value of a##AN NAME$L field.
+//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field);
+//%/// Sets the value of a##AN NAME$L field.
+//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value);
+//%
diff --git a/src/third_party/protobuf-3/objectivec/GPBUtilities.m b/src/third_party/protobuf-3/objectivec/GPBUtilities.m
new file mode 100644
index 0000000..447c749
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUtilities.m
@@ -0,0 +1,1717 @@
+// 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.
+
+#import "GPBUtilities_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownField.h"
+#import "GPBUnknownFieldSet.h"
+
+static void AppendTextFormatForMessage(GPBMessage *message,
+                                       NSMutableString *toStr,
+                                       NSString *lineIndent);
+
+NSData *GPBEmptyNSData(void) {
+  static dispatch_once_t onceToken;
+  static NSData *defaultNSData = nil;
+  dispatch_once(&onceToken, ^{
+    defaultNSData = [[NSData alloc] init];
+  });
+  return defaultNSData;
+}
+
+void GPBCheckRuntimeVersionInternal(int32_t version) {
+  if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) {
+    [NSException raise:NSInternalInconsistencyException
+                format:@"Linked to ProtocolBuffer runtime version %d,"
+                       @" but code compiled with version %d!",
+                       GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
+  }
+}
+
+BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
+  GPBDescriptor *descriptor = [self descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
+  return GPBMessageHasFieldSet(self, field);
+}
+
+BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
+  if (self == nil || field == nil) return NO;
+
+  // Repeated/Map don't use the bit, they check the count.
+  if (GPBFieldIsMapOrArray(field)) {
+    // Array/map type doesn't matter, since GPB*Array/NSArray and
+    // GPB*Dictionary/NSDictionary all support -count;
+    NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+    return (arrayOrMap.count > 0);
+  } else {
+    return GPBGetHasIvarField(self, field);
+  }
+}
+
+void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
+  // If not set, nothing to do.
+  if (!GPBGetHasIvarField(self, field)) {
+    return;
+  }
+
+  if (GPBFieldStoresObject(field)) {
+    // Object types are handled slightly differently, they need to be released.
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    id *typePtr = (id *)&storage[field->description_->offset];
+    [*typePtr release];
+    *typePtr = nil;
+  } else {
+    // POD types just need to clear the has bit as the Get* method will
+    // fetch the default when needed.
+  }
+  GPBSetHasIvarField(self, field, NO);
+}
+
+BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+  if (idx < 0) {
+    NSCAssert(fieldNumber != 0, @"Invalid field number.");
+    BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
+    return hasIvar;
+  } else {
+    NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
+    uint32_t byteIndex = idx / 32;
+    uint32_t bitMask = (1 << (idx % 32));
+    BOOL hasIvar =
+        (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
+    return hasIvar;
+  }
+}
+
+uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
+  NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.",
+            [self class], idx);
+  uint32_t result = self->messageStorage_->_has_storage_[-idx];
+  return result;
+}
+
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
+                   BOOL value) {
+  if (idx < 0) {
+    NSCAssert(fieldNumber != 0, @"Invalid field number.");
+    uint32_t *has_storage = self->messageStorage_->_has_storage_;
+    has_storage[-idx] = (value ? fieldNumber : 0);
+  } else {
+    NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
+    uint32_t *has_storage = self->messageStorage_->_has_storage_;
+    uint32_t byte = idx / 32;
+    uint32_t bitMask = (1 << (idx % 32));
+    if (value) {
+      has_storage[byte] |= bitMask;
+    } else {
+      has_storage[byte] &= ~bitMask;
+    }
+  }
+}
+
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
+  uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
+  if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
+    // Do nothing/nothing set in the oneof.
+    return;
+  }
+
+  // Like GPBClearMessageField(), free the memory if an objecttype is set,
+  // pod types don't need to do anything.
+  GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
+  NSCAssert(fieldSet,
+            @"%@: oneof set to something (%u) not in the oneof?",
+            [self class], fieldNumberSet);
+  if (fieldSet && GPBFieldStoresObject(fieldSet)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    id *typePtr = (id *)&storage[fieldSet->description_->offset];
+    [*typePtr release];
+    *typePtr = nil;
+  }
+
+  // Set to nothing stored in the oneof.
+  // (field number doesn't matter since setting to nothing).
+  GPBSetHasIvar(self, oneofHasIndex, 1, NO);
+}
+
+#pragma mark - IVar accessors
+
+//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
+//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
+//% TYPE$S            NAME$S       GPBFieldDescriptor *field) {
+//%  if (GPBGetHasIvarField(self, field)) {
+//%    uint8_t *storage = (uint8_t *)self->messageStorage_;
+//%    TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
+//%    return *typePtr;
+//%  } else {
+//%    return field.defaultValue.value##NAME;
+//%  }
+//%}
+//%
+//%// Only exists for public api, no core code should use this.
+//%void GPBSetMessage##NAME##Field(GPBMessage *self,
+//%                   NAME$S     GPBFieldDescriptor *field,
+//%                   NAME$S     TYPE value) {
+//%  if (self == nil || field == nil) return;
+//%  GPBFileSyntax syntax = [self descriptor].file.syntax;
+//%  GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
+//%}
+//%
+//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
+//%            NAME$S                     GPBFieldDescriptor *field,
+//%            NAME$S                     TYPE value,
+//%            NAME$S                     GPBFileSyntax syntax) {
+//%  GPBOneofDescriptor *oneof = field->containingOneof_;
+//%  if (oneof) {
+//%    GPBMessageFieldDescription *fieldDesc = field->description_;
+//%    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+//%  }
+//%  NSCAssert(self->messageStorage_ != NULL,
+//%            @"%@: All messages should have storage (from init)",
+//%            [self class]);
+//%#if defined(__clang_analyzer__)
+//%  if (self->messageStorage_ == NULL) return;
+//%#endif
+//%  uint8_t *storage = (uint8_t *)self->messageStorage_;
+//%  TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
+//%  *typePtr = value;
+//%  // proto2: any value counts as having been set; proto3, it
+//%  // has to be a non zero value.
+//%  BOOL hasValue =
+//%    (syntax == GPBFileSyntaxProto2) || (value != (TYPE)0);
+//%  GPBSetHasIvarField(self, field, hasValue);
+//%  GPBBecomeVisibleToAutocreator(self);
+//%}
+//%
+//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
+//%// Only exists for public api, no core code should use this.
+//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
+//% TYPE$S             NAME$S       GPBFieldDescriptor *field) {
+//%  return (TYPE *)GPBGetObjectIvarWithField(self, field);
+//%}
+//%
+//%// Only exists for public api, no core code should use this.
+//%void GPBSetMessage##NAME##Field(GPBMessage *self,
+//%                   NAME$S     GPBFieldDescriptor *field,
+//%                   NAME$S     TYPE *value) {
+//%  GPBSetObjectIvarWithField(self, field, (id)value);
+//%}
+//%
+
+// Object types are handled slightly differently, they need to be released
+// and retained.
+
+void GPBSetAutocreatedRetainedObjectIvarWithField(
+    GPBMessage *self, GPBFieldDescriptor *field,
+    id __attribute__((ns_consumed)) value) {
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  id *typePtr = (id *)&storage[field->description_->offset];
+  NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
+  *typePtr = value;
+}
+
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
+                                             GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    return;
+  }
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  id *typePtr = (id *)&storage[field->description_->offset];
+  GPBMessage *oldValue = *typePtr;
+  *typePtr = NULL;
+  GPBClearMessageAutocreator(oldValue);
+  [oldValue release];
+}
+
+// This exists only for briging some aliased types, nothing else should use it.
+static void GPBSetObjectIvarWithField(GPBMessage *self,
+                                      GPBFieldDescriptor *field, id value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
+                                            syntax);
+}
+
+void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field, id value,
+                                       GPBFileSyntax syntax) {
+  GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
+                                            syntax);
+}
+
+void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
+                                               GPBFieldDescriptor *field,
+                                               id value, GPBFileSyntax syntax) {
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  GPBDataType fieldType = GPBGetFieldDataType(field);
+  BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
+  BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
+#ifdef DEBUG
+  if (value == nil && !isMapOrArray && !fieldIsMessage &&
+      field.hasDefaultValue) {
+    // Setting a message to nil is an obvious way to "clear" the value
+    // as there is no way to set a non-empty default value for messages.
+    //
+    // For Strings and Bytes that have default values set it is not clear what
+    // should be done when their value is set to nil. Is the intention just to
+    // clear the set value and reset to default, or is the intention to set the
+    // value to the empty string/data? Arguments can be made for both cases.
+    // 'nil' has been abused as a replacement for an empty string/data in ObjC.
+    // We decided to be consistent with all "object" types and clear the has
+    // field, and fall back on the default value. The warning below will only
+    // appear in debug, but the could should be changed so the intention is
+    // clear.
+    NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_);
+    NSString *propName = field.name;
+    NSString *className = self.descriptor.name;
+    NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
+          @"default values. Please use '%@.%@ = %@' if you want to set it to "
+          @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
+          @"'%@'. Defaulting to resetting default value.",
+          className, propName, className, propName,
+          (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
+          className, hasSel, field.defaultValue.valueString);
+    // Note: valueString, depending on the type, it could easily be
+    // valueData/valueMessage.
+  }
+#endif  // DEBUG
+  if (!isMapOrArray) {
+    // Non repeated/map can be in an oneof, clear any existing value from the
+    // oneof.
+    GPBOneofDescriptor *oneof = field->containingOneof_;
+    if (oneof) {
+      GPBMessageFieldDescription *fieldDesc = field->description_;
+      GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    }
+    // Clear "has" if they are being set to nil.
+    BOOL setHasValue = (value != nil);
+    // Under proto3, Bytes & String fields get cleared by resetting them to
+    // their default (empty) values, so if they are set to something of length
+    // zero, they are being cleared.
+    if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
+        ([value length] == 0)) {
+      setHasValue = NO;
+      value = nil;
+    }
+    GPBSetHasIvarField(self, field, setHasValue);
+  }
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  id *typePtr = (id *)&storage[field->description_->offset];
+
+  id oldValue = *typePtr;
+
+  *typePtr = value;
+
+  if (oldValue) {
+    if (isMapOrArray) {
+      if (field.fieldType == GPBFieldTypeRepeated) {
+        // If the old array was autocreated by us, then clear it.
+        if (GPBDataTypeIsObject(fieldType)) {
+          GPBAutocreatedArray *autoArray = oldValue;
+          if (autoArray->_autocreator == self) {
+            autoArray->_autocreator = nil;
+          }
+        } else {
+          // Type doesn't matter, it is a GPB*Array.
+          GPBInt32Array *gpbArray = oldValue;
+          if (gpbArray->_autocreator == self) {
+            gpbArray->_autocreator = nil;
+          }
+        }
+      } else { // GPBFieldTypeMap
+        // If the old map was autocreated by us, then clear it.
+        if ((field.mapKeyDataType == GPBDataTypeString) &&
+            GPBDataTypeIsObject(fieldType)) {
+          GPBAutocreatedDictionary *autoDict = oldValue;
+          if (autoDict->_autocreator == self) {
+            autoDict->_autocreator = nil;
+          }
+        } else {
+          // Type doesn't matter, it is a GPB*Dictionary.
+          GPBInt32Int32Dictionary *gpbDict = oldValue;
+          if (gpbDict->_autocreator == self) {
+            gpbDict->_autocreator = nil;
+          }
+        }
+      }
+    } else if (fieldIsMessage) {
+      // If the old message value was autocreated by us, then clear it.
+      GPBMessage *oldMessageValue = oldValue;
+      if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
+        GPBClearMessageAutocreator(oldMessageValue);
+      }
+    }
+    [oldValue release];
+  }
+
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
+                                         GPBFieldDescriptor *field) {
+  if (self->messageStorage_ == nil) {
+    return nil;
+  }
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  id *typePtr = (id *)&storage[field->description_->offset];
+  return *typePtr;
+}
+
+id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+  NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    id *typePtr = (id *)&storage[field->description_->offset];
+    return *typePtr;
+  }
+  // Not set...
+
+  // Non messages (string/data), get their default.
+  if (!GPBFieldDataTypeIsMessage(field)) {
+    return field.defaultValue.valueMessage;
+  }
+
+  GPBPrepareReadOnlySemaphore(self);
+  dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
+  GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+  if (!result) {
+    // For non repeated messages, create the object, set it and return it.
+    // This object will not initially be visible via GPBGetHasIvar, so
+    // we save its creator so it can become visible if it's mutated later.
+    result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
+    GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
+  }
+  dispatch_semaphore_signal(self->readOnlySemaphore_);
+  return result;
+}
+
+// Only exists for public api, no core code should use this.
+int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
+}
+
+int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
+                                        GPBFieldDescriptor *field,
+                                        GPBFileSyntax syntax) {
+  int32_t result = GPBGetMessageInt32Field(self, field);
+  // If this is presevering unknown enums, make sure the value is valid before
+  // returning it.
+  if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
+      ![field isValidEnumValue:result]) {
+    result = kGPBUnrecognizedEnumeratorValue;
+  }
+  return result;
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
+                            int32_t value) {
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
+                                     GPBFieldDescriptor *field, int32_t value,
+                                     GPBFileSyntax syntax) {
+  // Don't allow in unknown values.  Proto3 can use the Raw method.
+  if (![field isValidEnumValue:value]) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@: Attempt to set an unknown enum value (%d)",
+                       [self class], field.name, value];
+  }
+  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+// Only exists for public api, no core code should use this.
+int32_t GPBGetMessageRawEnumField(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
+  int32_t result = GPBGetMessageInt32Field(self, field);
+  return result;
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
+                               int32_t value) {
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+BOOL GPBGetMessageBoolField(GPBMessage *self,
+                            GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    // Bools are stored in the has bits to avoid needing explicit space in the
+    // storage structure.
+    // (the field number passed to the HasIvar helper doesn't really matter
+    // since the offset is never negative)
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number);
+  } else {
+    return field.defaultValue.valueBool;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageBoolField(GPBMessage *self,
+                            GPBFieldDescriptor *field,
+                            BOOL value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     BOOL value,
+                                     GPBFileSyntax syntax) {
+  GPBMessageFieldDescription *fieldDesc = field->description_;
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+
+  // Bools are stored in the has bits to avoid needing explicit space in the
+  // storage structure.
+  // (the field number passed to the HasIvar helper doesn't really matter since
+  // the offset is never negative)
+  GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
+
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (BOOL)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+int32_t GPBGetMessageInt32Field(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueInt32;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageInt32Field(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             int32_t value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int32_t value,
+                                      GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (int32_t)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueUInt32;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageUInt32Field(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              uint32_t value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       uint32_t value,
+                                       GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+int64_t GPBGetMessageInt64Field(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueInt64;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageInt64Field(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             int64_t value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int64_t value,
+                                      GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (int64_t)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
+                                  GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueUInt64;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageUInt64Field(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              uint64_t value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       uint64_t value,
+                                       GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
+// This block of code is generated, do not edit it directly.
+
+float GPBGetMessageFloatField(GPBMessage *self,
+                              GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    float *typePtr = (float *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueFloat;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageFloatField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             float value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      float value,
+                                      GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  float *typePtr = (float *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (float)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
+// This block of code is generated, do not edit it directly.
+
+double GPBGetMessageDoubleField(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
+  if (GPBGetHasIvarField(self, field)) {
+    uint8_t *storage = (uint8_t *)self->messageStorage_;
+    double *typePtr = (double *)&storage[field->description_->offset];
+    return *typePtr;
+  } else {
+    return field.defaultValue.valueDouble;
+  }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageDoubleField(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              double value) {
+  if (self == nil || field == nil) return;
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
+  GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       double value,
+                                       GPBFileSyntax syntax) {
+  GPBOneofDescriptor *oneof = field->containingOneof_;
+  if (oneof) {
+    GPBMessageFieldDescription *fieldDesc = field->description_;
+    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+  }
+  NSCAssert(self->messageStorage_ != NULL,
+            @"%@: All messages should have storage (from init)",
+            [self class]);
+#if defined(__clang_analyzer__)
+  if (self->messageStorage_ == NULL) return;
+#endif
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  double *typePtr = (double *)&storage[field->description_->offset];
+  *typePtr = value;
+  // proto2: any value counts as having been set; proto3, it
+  // has to be a non zero value.
+  BOOL hasValue =
+    (syntax == GPBFileSyntaxProto2) || (value != (double)0);
+  GPBSetHasIvarField(self, field, hasValue);
+  GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND-END (6 expansions)
+
+// Aliases are function calls that are virtually the same.
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+NSString *GPBGetMessageStringField(GPBMessage *self,
+                                   GPBFieldDescriptor *field) {
+  return (NSString *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageStringField(GPBMessage *self,
+                              GPBFieldDescriptor *field,
+                              NSString *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+NSData *GPBGetMessageBytesField(GPBMessage *self,
+                                GPBFieldDescriptor *field) {
+  return (NSData *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageBytesField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             NSData *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
+                                      GPBFieldDescriptor *field) {
+  return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageMessageField(GPBMessage *self,
+                               GPBFieldDescriptor *field,
+                               GPBMessage *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
+                                    GPBFieldDescriptor *field) {
+  return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageGroupField(GPBMessage *self,
+                             GPBFieldDescriptor *field,
+                             GPBMessage *value) {
+  GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND-END (4 expansions)
+
+// Only exists for public api, no core code should use this.
+id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeRepeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a repeated field.",
+                       [self class], field.name];
+  }
+#endif
+  return GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeRepeated) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a repeated field.",
+                       [self class], field.name];
+  }
+  Class expectedClass = Nil;
+  switch (GPBGetFieldDataType(field)) {
+    case GPBDataTypeBool:
+      expectedClass = [GPBBoolArray class];
+      break;
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+      expectedClass = [GPBInt32Array class];
+      break;
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      expectedClass = [GPBUInt32Array class];
+      break;
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+      expectedClass = [GPBInt64Array class];
+      break;
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      expectedClass = [GPBUInt64Array class];
+      break;
+    case GPBDataTypeFloat:
+      expectedClass = [GPBFloatArray class];
+      break;
+    case GPBDataTypeDouble:
+      expectedClass = [GPBDoubleArray class];
+      break;
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      expectedClass = [NSMutableDictionary class];
+      break;
+    case GPBDataTypeEnum:
+      expectedClass = [GPBBoolArray class];
+      break;
+  }
+  if (array && ![array isKindOfClass:expectedClass]) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@: Expected %@ object, got %@.",
+                       [self class], field.name, expectedClass, [array class]];
+  }
+#endif
+  GPBSetObjectIvarWithField(self, field, array);
+}
+
+#if DEBUG
+static NSString *TypeToStr(GPBDataType dataType) {
+  switch (dataType) {
+    case GPBDataTypeBool:
+      return @"Bool";
+    case GPBDataTypeSFixed32:
+    case GPBDataTypeInt32:
+    case GPBDataTypeSInt32:
+      return @"Int32";
+    case GPBDataTypeFixed32:
+    case GPBDataTypeUInt32:
+      return @"UInt32";
+    case GPBDataTypeSFixed64:
+    case GPBDataTypeInt64:
+    case GPBDataTypeSInt64:
+      return @"Int64";
+    case GPBDataTypeFixed64:
+    case GPBDataTypeUInt64:
+      return @"UInt64";
+    case GPBDataTypeFloat:
+      return @"Float";
+    case GPBDataTypeDouble:
+      return @"Double";
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      return @"Object";
+    case GPBDataTypeEnum:
+      return @"Bool";
+  }
+}
+#endif
+
+// Only exists for public api, no core code should use this.
+id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeMap) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a map<> field.",
+                       [self class], field.name];
+  }
+#endif
+  return GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
+                           id dictionary) {
+#if DEBUG
+  if (field.fieldType != GPBFieldTypeMap) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"%@.%@ is not a map<> field.",
+                       [self class], field.name];
+  }
+  if (dictionary) {
+    GPBDataType keyDataType = field.mapKeyDataType;
+    GPBDataType valueDataType = GPBGetFieldDataType(field);
+    NSString *keyStr = TypeToStr(keyDataType);
+    NSString *valueStr = TypeToStr(valueDataType);
+    if (keyDataType == GPBDataTypeString) {
+      keyStr = @"String";
+    }
+    Class expectedClass = Nil;
+    if ((keyDataType == GPBDataTypeString) &&
+        GPBDataTypeIsObject(valueDataType)) {
+      expectedClass = [NSMutableDictionary class];
+    } else {
+      NSString *className =
+          [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
+      expectedClass = NSClassFromString(className);
+      NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
+    }
+    if (![dictionary isKindOfClass:expectedClass]) {
+      [NSException raise:NSInvalidArgumentException
+                  format:@"%@.%@: Expected %@ object, got %@.",
+                         [self class], field.name, expectedClass,
+                         [dictionary class]];
+    }
+  }
+#endif
+  GPBSetObjectIvarWithField(self, field, dictionary);
+}
+
+#pragma mark - Misc Dynamic Runtime Utils
+
+const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
+  Protocol *protocol =
+      objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
+  struct objc_method_description description =
+      protocol_getMethodDescription(protocol, selector, NO, instanceSel);
+  return description.types;
+}
+
+#pragma mark - Text Format Support
+
+static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
+  [destStr appendString:@"\""];
+  NSUInteger len = [toPrint length];
+  for (NSUInteger i = 0; i < len; ++i) {
+    unichar aChar = [toPrint characterAtIndex:i];
+    switch (aChar) {
+      case '\n': [destStr appendString:@"\\n"];  break;
+      case '\r': [destStr appendString:@"\\r"];  break;
+      case '\t': [destStr appendString:@"\\t"];  break;
+      case '\"': [destStr appendString:@"\\\""]; break;
+      case '\'': [destStr appendString:@"\\\'"]; break;
+      case '\\': [destStr appendString:@"\\\\"]; break;
+      default:
+        [destStr appendFormat:@"%C", aChar];
+        break;
+    }
+  }
+  [destStr appendString:@"\""];
+}
+
+static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
+  const char *src = (const char *)[buffer bytes];
+  size_t srcLen = [buffer length];
+  [destStr appendString:@"\""];
+  for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
+    switch (*src) {
+      case '\n': [destStr appendString:@"\\n"];  break;
+      case '\r': [destStr appendString:@"\\r"];  break;
+      case '\t': [destStr appendString:@"\\t"];  break;
+      case '\"': [destStr appendString:@"\\\""]; break;
+      case '\'': [destStr appendString:@"\\\'"]; break;
+      case '\\': [destStr appendString:@"\\\\"]; break;
+      default:
+        if (isprint(*src)) {
+          [destStr appendFormat:@"%c", *src];
+        } else {
+          // NOTE: doing hex means you have to worry about the letter after
+          // the hex being another hex char and forcing that to be escaped, so
+          // use octal to keep it simple.
+          [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
+        }
+        break;
+    }
+  }
+  [destStr appendString:@"\""];
+}
+
+static void AppendTextFormatForMapMessageField(
+    id map, GPBFieldDescriptor *field, NSMutableString *toStr,
+    NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
+  GPBDataType keyDataType = field.mapKeyDataType;
+  GPBDataType valueDataType = GPBGetFieldDataType(field);
+  BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
+
+  NSString *msgStartFirst =
+      [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
+  NSString *msgStart =
+      [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
+  NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
+
+  NSString *keyLine = [NSString stringWithFormat:@"%@  key: ", lineIndent];
+  NSString *valueLine = [NSString stringWithFormat:@"%@  value%s ", lineIndent,
+                                                   (isMessageValue ? "" : ":")];
+
+  __block BOOL isFirst = YES;
+
+  if ((keyDataType == GPBDataTypeString) &&
+      GPBDataTypeIsObject(valueDataType)) {
+    // map is an NSDictionary.
+    NSDictionary *dict = map;
+    [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
+      #pragma unused(stop)
+      [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
+      isFirst = NO;
+
+      [toStr appendString:keyLine];
+      AppendStringEscaped(key, toStr);
+      [toStr appendString:@"\n"];
+
+      [toStr appendString:valueLine];
+      switch (valueDataType) {
+        case GPBDataTypeString:
+          AppendStringEscaped(value, toStr);
+          break;
+
+        case GPBDataTypeBytes:
+          AppendBufferAsString(value, toStr);
+          break;
+
+        case GPBDataTypeMessage:
+          [toStr appendString:@"{\n"];
+          NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
+          AppendTextFormatForMessage(value, toStr, subIndent);
+          [toStr appendFormat:@"%@  }", lineIndent];
+          break;
+
+        default:
+          NSCAssert(NO, @"Can't happen");
+          break;
+      }
+      [toStr appendString:@"\n"];
+
+      [toStr appendString:msgEnd];
+    }];
+  } else {
+    // map is one of the GPB*Dictionary classes, type doesn't matter.
+    GPBInt32Int32Dictionary *dict = map;
+    [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
+      [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
+      isFirst = NO;
+
+      // Key always is a NSString.
+      if (keyDataType == GPBDataTypeString) {
+        [toStr appendString:keyLine];
+        AppendStringEscaped(keyObj, toStr);
+        [toStr appendString:@"\n"];
+      } else {
+        [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
+      }
+
+      [toStr appendString:valueLine];
+      switch (valueDataType) {
+        case GPBDataTypeString:
+          AppendStringEscaped(valueObj, toStr);
+          break;
+
+        case GPBDataTypeBytes:
+          AppendBufferAsString(valueObj, toStr);
+          break;
+
+        case GPBDataTypeMessage:
+          [toStr appendString:@"{\n"];
+          NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
+          AppendTextFormatForMessage(valueObj, toStr, subIndent);
+          [toStr appendFormat:@"%@  }", lineIndent];
+          break;
+
+        case GPBDataTypeEnum: {
+          int32_t enumValue = [valueObj intValue];
+          NSString *valueStr = nil;
+          GPBEnumDescriptor *descriptor = field.enumDescriptor;
+          if (descriptor) {
+            valueStr = [descriptor textFormatNameForValue:enumValue];
+          }
+          if (valueStr) {
+            [toStr appendString:valueStr];
+          } else {
+            [toStr appendFormat:@"%d", enumValue];
+          }
+          break;
+        }
+
+        default:
+          NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
+          // Everything else is a NSString.
+          [toStr appendString:valueObj];
+          break;
+      }
+      [toStr appendString:@"\n"];
+
+      [toStr appendString:msgEnd];
+    }];
+  }
+}
+
+static void AppendTextFormatForMessageField(GPBMessage *message,
+                                            GPBFieldDescriptor *field,
+                                            NSMutableString *toStr,
+                                            NSString *lineIndent) {
+  id arrayOrMap;
+  NSUInteger count;
+  GPBFieldType fieldType = field.fieldType;
+  switch (fieldType) {
+    case GPBFieldTypeSingle:
+      arrayOrMap = nil;
+      count = (GPBGetHasIvarField(message, field) ? 1 : 0);
+      break;
+
+    case GPBFieldTypeRepeated:
+      // Will be NSArray or GPB*Array, type doesn't matter, they both
+      // implement count.
+      arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
+      count = [(NSArray *)arrayOrMap count];
+      break;
+
+    case GPBFieldTypeMap: {
+      // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter,
+      // they both implement count.
+      arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
+      count = [(NSDictionary *)arrayOrMap count];
+      break;
+    }
+  }
+
+  if (count == 0) {
+    // Nothing to print, out of here.
+    return;
+  }
+
+  NSString *lineEnding = @"";
+
+  // If the name can't be reversed or support for extra info was turned off,
+  // this can return nil.
+  NSString *fieldName = [field textFormatName];
+  if ([fieldName length] == 0) {
+    fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
+    // If there is only one entry, put the objc name as a comment, other wise
+    // add it before the repeated values.
+    if (count > 1) {
+      [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
+    } else {
+      lineEnding = [NSString stringWithFormat:@"  # %@", field.name];
+    }
+  }
+
+  if (fieldType == GPBFieldTypeMap) {
+    AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent,
+                                       fieldName, lineEnding);
+    return;
+  }
+
+  id array = arrayOrMap;
+  const BOOL isRepeated = (array != nil);
+
+  GPBDataType fieldDataType = GPBGetFieldDataType(field);
+  BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
+  for (NSUInteger j = 0; j < count; ++j) {
+    // Start the line.
+    [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
+                        (isMessageField ? "" : ":")];
+
+    // The value.
+    switch (fieldDataType) {
+#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...)                        \
+  case GPBDataType##GPBDATATYPE: {                                            \
+    CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j]   \
+                          : GPBGetMessage##REAL_TYPE##Field(message, field)); \
+    [toStr appendFormat:__VA_ARGS__, v];                                      \
+    break;                                                                    \
+  }
+
+      FIELD_CASE(Int32, int32_t, Int32, @"%d")
+      FIELD_CASE(SInt32, int32_t, Int32, @"%d")
+      FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
+      FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
+      FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
+      FIELD_CASE(Int64, int64_t, Int64, @"%lld")
+      FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
+      FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
+      FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
+      FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
+      FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
+      FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
+
+#undef FIELD_CASE
+
+      case GPBDataTypeEnum: {
+        int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
+                                : GPBGetMessageInt32Field(message, field));
+        NSString *valueStr = nil;
+        GPBEnumDescriptor *descriptor = field.enumDescriptor;
+        if (descriptor) {
+          valueStr = [descriptor textFormatNameForValue:v];
+        }
+        if (valueStr) {
+          [toStr appendString:valueStr];
+        } else {
+          [toStr appendFormat:@"%d", v];
+        }
+        break;
+      }
+
+      case GPBDataTypeBool: {
+        BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
+                             : GPBGetMessageBoolField(message, field));
+        [toStr appendString:(v ? @"true" : @"false")];
+        break;
+      }
+
+      case GPBDataTypeString: {
+        NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
+                                  : GPBGetMessageStringField(message, field));
+        AppendStringEscaped(v, toStr);
+        break;
+      }
+
+      case GPBDataTypeBytes: {
+        NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
+                                : GPBGetMessageBytesField(message, field));
+        AppendBufferAsString(v, toStr);
+        break;
+      }
+
+      case GPBDataTypeGroup:
+      case GPBDataTypeMessage: {
+        GPBMessage *v =
+            (isRepeated ? [(NSArray *)array objectAtIndex:j]
+                        : GPBGetObjectIvarWithField(message, field));
+        [toStr appendFormat:@"{%@\n", lineEnding];
+        NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
+        AppendTextFormatForMessage(v, toStr, subIndent);
+        [toStr appendFormat:@"%@}", lineIndent];
+        lineEnding = @"";
+        break;
+      }
+
+    }  // switch(fieldDataType)
+
+    // End the line.
+    [toStr appendFormat:@"%@\n", lineEnding];
+
+  }  // for(count)
+}
+
+static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
+                                                     NSArray *activeExtensions,
+                                                     GPBExtensionRange range,
+                                                     NSMutableString *toStr,
+                                                     NSString *lineIndent) {
+  uint32_t start = range.start;
+  uint32_t end = range.end;
+  for (GPBExtensionDescriptor *extension in activeExtensions) {
+    uint32_t fieldNumber = extension.fieldNumber;
+    if (fieldNumber < start) {
+      // Not there yet.
+      continue;
+    }
+    if (fieldNumber > end) {
+      // Done.
+      break;
+    }
+
+    id rawExtValue = [message getExtension:extension];
+    BOOL isRepeated = extension.isRepeated;
+
+    NSUInteger numValues = 1;
+    NSString *lineEnding = @"";
+    if (isRepeated) {
+      numValues = [(NSArray *)rawExtValue count];
+    }
+
+    NSString *singletonName = extension.singletonName;
+    if (numValues == 1) {
+      lineEnding = [NSString stringWithFormat:@"  # [%@]", singletonName];
+    } else {
+      [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
+    }
+
+    GPBDataType extDataType = extension.dataType;
+    for (NSUInteger j = 0; j < numValues; ++j) {
+      id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
+
+      // Start the line.
+      [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
+                          (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
+
+      // The value.
+      switch (extDataType) {
+#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
+  case GPBDataType##GPBDATATYPE: {                       \
+    CTYPE v = [(NSNumber *)curValue NUMSELECTOR];        \
+    [toStr appendFormat:__VA_ARGS__, v];                 \
+    break;                                               \
+  }
+
+        FIELD_CASE(Int32, int32_t, intValue, @"%d")
+        FIELD_CASE(SInt32, int32_t, intValue, @"%d")
+        FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
+        FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
+        FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
+        FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
+        FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
+        FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
+        FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
+        FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
+        FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
+        FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
+        // TODO: Add a comment with the enum name from enum descriptors
+        // (might not be real value, so leave it as a comment, ObjC compiler
+        // name mangles differently).  Doesn't look like we actually generate
+        // an enum descriptor reference like we do for normal fields, so this
+        // will take a compiler change.
+        FIELD_CASE(Enum, int32_t, intValue, @"%d")
+
+#undef FIELD_CASE
+
+        case GPBDataTypeBool:
+          [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
+                                                                : @"false")];
+          break;
+
+        case GPBDataTypeString:
+          AppendStringEscaped(curValue, toStr);
+          break;
+
+        case GPBDataTypeBytes:
+          AppendBufferAsString((NSData *)curValue, toStr);
+          break;
+
+        case GPBDataTypeGroup:
+        case GPBDataTypeMessage: {
+          [toStr appendFormat:@"{%@\n", lineEnding];
+          NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
+          AppendTextFormatForMessage(curValue, toStr, subIndent);
+          [toStr appendFormat:@"%@}", lineIndent];
+          lineEnding = @"";
+          break;
+        }
+
+      }  // switch(extDataType)
+
+    }  //  for(numValues)
+
+    // End the line.
+    [toStr appendFormat:@"%@\n", lineEnding];
+
+  }  // for..in(activeExtensions)
+}
+
+static void AppendTextFormatForMessage(GPBMessage *message,
+                                       NSMutableString *toStr,
+                                       NSString *lineIndent) {
+  GPBDescriptor *descriptor = [message descriptor];
+  NSArray *fieldsArray = descriptor->fields_;
+  NSUInteger fieldCount = fieldsArray.count;
+  const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
+  NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
+  NSArray *activeExtensions = [message sortedExtensionsInUse];
+  for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
+    if (i == fieldCount) {
+      AppendTextFormatForMessageExtensionRange(
+          message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+    } else if (j == extensionRangesCount ||
+               GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
+      AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
+                                      lineIndent);
+    } else {
+      AppendTextFormatForMessageExtensionRange(
+          message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+    }
+  }
+
+  NSString *unknownFieldsStr =
+      GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
+  if ([unknownFieldsStr length] > 0) {
+    [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
+    [toStr appendString:unknownFieldsStr];
+  }
+}
+
+NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
+  if (message == nil) return @"";
+  if (lineIndent == nil) lineIndent = @"";
+
+  NSMutableString *buildString = [NSMutableString string];
+  AppendTextFormatForMessage(message, buildString, lineIndent);
+  return buildString;
+}
+
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
+                                          NSString *lineIndent) {
+  if (unknownSet == nil) return @"";
+  if (lineIndent == nil) lineIndent = @"";
+
+  NSMutableString *result = [NSMutableString string];
+  for (GPBUnknownField *field in [unknownSet sortedFields]) {
+    int32_t fieldNumber = [field number];
+
+#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT)                                   \
+  [field.PROPNAME                                                             \
+      enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) {  \
+    _Pragma("unused(idx, stop)");                                             \
+    [result                                                                   \
+        appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
+      }];
+
+    PRINT_LOOP(varintList, uint64_t, %llu);
+    PRINT_LOOP(fixed32List, uint32_t, 0x%X);
+    PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
+
+#undef PRINT_LOOP
+
+    // NOTE: C++ version of TextFormat tries to parse this as a message
+    // and print that if it succeeds.
+    for (NSData *data in field.lengthDelimitedList) {
+      [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
+      AppendBufferAsString(data, result);
+      [result appendString:@"\n"];
+    }
+
+    for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
+      [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
+      NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
+      NSString *subUnknwonSetStr =
+          GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
+      [result appendString:subUnknwonSetStr];
+      [result appendFormat:@"%@}\n", lineIndent];
+    }
+  }
+  return result;
+}
+
+// Helpers to decode a varint. Not using GPBCodedInputStream version because
+// that needs a state object, and we don't want to create an input stream out
+// of the data.
+GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
+  int8_t result = *((int8_t *)(*data));
+  ++(*data);
+  return result;
+}
+
+static int32_t ReadRawVarint32FromData(const uint8_t **data) {
+  int8_t tmp = ReadRawByteFromData(data);
+  if (tmp >= 0) {
+    return tmp;
+  }
+  int32_t result = tmp & 0x7f;
+  if ((tmp = ReadRawByteFromData(data)) >= 0) {
+    result |= tmp << 7;
+  } else {
+    result |= (tmp & 0x7f) << 7;
+    if ((tmp = ReadRawByteFromData(data)) >= 0) {
+      result |= tmp << 14;
+    } else {
+      result |= (tmp & 0x7f) << 14;
+      if ((tmp = ReadRawByteFromData(data)) >= 0) {
+        result |= tmp << 21;
+      } else {
+        result |= (tmp & 0x7f) << 21;
+        result |= (tmp = ReadRawByteFromData(data)) << 28;
+        if (tmp < 0) {
+          // Discard upper 32 bits.
+          for (int i = 0; i < 5; i++) {
+            if (ReadRawByteFromData(data) >= 0) {
+              return result;
+            }
+          }
+          [NSException raise:NSParseErrorException
+                      format:@"Unable to read varint32"];
+        }
+      }
+    }
+  }
+  return result;
+}
+
+NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
+                                  NSString *inputStr) {
+  // decodData form:
+  //  varint32: num entries
+  //  for each entry:
+  //    varint32: key
+  //    bytes*: decode data
+  //
+  // decode data one of two forms:
+  //  1: a \0 followed by the string followed by an \0
+  //  2: bytecodes to transform an input into the right thing, ending with \0
+  //
+  // the bytes codes are of the form:
+  //  0xabbccccc
+  //  0x0 (all zeros), end.
+  //  a - if set, add an underscore
+  //  bb - 00 ccccc bytes as is
+  //  bb - 10 ccccc upper first, as is on rest, ccccc byte total
+  //  bb - 01 ccccc lower first, as is on rest, ccccc byte total
+  //  bb - 11 ccccc all upper, ccccc byte total
+
+  if (!decodeData || !inputStr) {
+    return nil;
+  }
+
+  // Find key
+  const uint8_t *scan = decodeData;
+  int32_t numEntries = ReadRawVarint32FromData(&scan);
+  BOOL foundKey = NO;
+  while (!foundKey && (numEntries > 0)) {
+    --numEntries;
+    int32_t dataKey = ReadRawVarint32FromData(&scan);
+    if (dataKey == key) {
+      foundKey = YES;
+    } else {
+      // If it is a inlined string, it will start with \0; if it is bytecode it
+      // will start with a code. So advance one (skipping the inline string
+      // marker), and then loop until reaching the end marker (\0).
+      ++scan;
+      while (*scan != 0) ++scan;
+      // Now move past the end marker.
+      ++scan;
+    }
+  }
+
+  if (!foundKey) {
+    return nil;
+  }
+
+  // Decode
+
+  if (*scan == 0) {
+    // Inline string. Move over the marker, and NSString can take it as
+    // UTF8.
+    ++scan;
+    NSString *result = [NSString stringWithUTF8String:(const char *)scan];
+    return result;
+  }
+
+  NSMutableString *result =
+      [NSMutableString stringWithCapacity:[inputStr length]];
+
+  const uint8_t kAddUnderscore  = 0b10000000;
+  const uint8_t kOpMask         = 0b01100000;
+  // const uint8_t kOpAsIs        = 0b00000000;
+  const uint8_t kOpFirstUpper     = 0b01000000;
+  const uint8_t kOpFirstLower     = 0b00100000;
+  const uint8_t kOpAllUpper       = 0b01100000;
+  const uint8_t kSegmentLenMask = 0b00011111;
+
+  NSInteger i = 0;
+  for (; *scan != 0; ++scan) {
+    if (*scan & kAddUnderscore) {
+      [result appendString:@"_"];
+    }
+    int segmentLen = *scan & kSegmentLenMask;
+    uint8_t decodeOp = *scan & kOpMask;
+
+    // Do op specific handling of the first character.
+    if (decodeOp == kOpFirstUpper) {
+      unichar c = [inputStr characterAtIndex:i];
+      [result appendFormat:@"%c", toupper((char)c)];
+      ++i;
+      --segmentLen;
+    } else if (decodeOp == kOpFirstLower) {
+      unichar c = [inputStr characterAtIndex:i];
+      [result appendFormat:@"%c", tolower((char)c)];
+      ++i;
+      --segmentLen;
+    }
+    // else op == kOpAsIs || op == kOpAllUpper
+
+    // Now pull over the rest of the length for this segment.
+    for (int x = 0; x < segmentLen; ++x) {
+      unichar c = [inputStr characterAtIndex:(i + x)];
+      if (decodeOp == kOpAllUpper) {
+        [result appendFormat:@"%c", toupper((char)c)];
+      } else {
+        [result appendFormat:@"%C", c];
+      }
+    }
+    i += segmentLen;
+  }
+
+  return result;
+}
+
+#pragma mark - GPBMessageSignatureProtocol
+
+// A series of selectors that are used solely to get @encoding values
+// for them by the dynamic protobuf runtime code. An object using the protocol
+// needs to be declared for the protocol to be valid at runtime.
+@interface GPBMessageSignatureProtocol : NSObject<GPBMessageSignatureProtocol>
+@end
+@implementation GPBMessageSignatureProtocol
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBUtilities_PackagePrivate.h b/src/third_party/protobuf-3/objectivec/GPBUtilities_PackagePrivate.h
new file mode 100644
index 0000000..a6b6c84
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBUtilities_PackagePrivate.h
@@ -0,0 +1,331 @@
+// 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.
+
+#import <Foundation/Foundation.h>
+
+#import "GPBUtilities.h"
+
+#import "GPBDescriptor_PackagePrivate.h"
+
+// Macros for stringifying library symbols. These are used in the generated
+// PB descriptor classes wherever a library symbol name is represented as a
+// string. See README.google for more information.
+#define GPBStringify(S) #S
+#define GPBStringifySymbol(S) GPBStringify(S)
+
+#define GPBNSStringify(S) @#S
+#define GPBNSStringifySymbol(S) GPBNSStringify(S)
+
+// Constant to internally mark when there is no has bit.
+#define GPBNoHasBit INT32_MAX
+
+CF_EXTERN_C_BEGIN
+
+// These two are used to inject a runtime check for version mismatch into the
+// generated sources to make sure they are linked with a supporting runtime.
+void GPBCheckRuntimeVersionInternal(int32_t version);
+GPB_INLINE void GPBDebugCheckRuntimeVersion() {
+#if DEBUG
+  GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION);
+#endif
+}
+
+// Conversion functions for de/serializing floating point types.
+
+GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) {
+  union { double f; int64_t i; } u;
+  u.f = v;
+  return u.i;
+}
+
+GPB_INLINE int32_t GPBConvertFloatToInt32(float v) {
+  union { float f; int32_t i; } u;
+  u.f = v;
+  return u.i;
+}
+
+GPB_INLINE double GPBConvertInt64ToDouble(int64_t v) {
+  union { double f; int64_t i; } u;
+  u.i = v;
+  return u.f;
+}
+
+GPB_INLINE float GPBConvertInt32ToFloat(int32_t v) {
+  union { float f; int32_t i; } u;
+  u.i = v;
+  return u.f;
+}
+
+GPB_INLINE int32_t GPBLogicalRightShift32(int32_t value, int32_t spaces) {
+  return (int32_t)((uint32_t)(value) >> spaces);
+}
+
+GPB_INLINE int64_t GPBLogicalRightShift64(int64_t value, int32_t spaces) {
+  return (int64_t)((uint64_t)(value) >> spaces);
+}
+
+// Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint.  (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) {
+  return GPBLogicalRightShift32(n, 1) ^ -(n & 1);
+}
+
+// Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint.  (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) {
+  return GPBLogicalRightShift64(n, 1) ^ -(n & 1);
+}
+
+// Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint.  (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) {
+  // Note:  the right-shift must be arithmetic
+  return (n << 1) ^ (n >> 31);
+}
+
+// Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint.  (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) {
+  // Note:  the right-shift must be arithmetic
+  return (n << 1) ^ (n >> 63);
+}
+
+GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) {
+  switch (type) {
+    case GPBDataTypeBytes:
+    case GPBDataTypeString:
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) {
+  switch (type) {
+    case GPBDataTypeMessage:
+    case GPBDataTypeGroup:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+GPB_INLINE BOOL GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) {
+  return GPBDataTypeIsMessage(field->description_->dataType);
+}
+
+GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) {
+  return GPBDataTypeIsObject(field->description_->dataType);
+}
+
+GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) {
+  return GPBDataTypeIsMessage(ext->description_->dataType);
+}
+
+// The field is an array/map or it has an object value.
+GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) {
+  GPBMessageFieldDescription *desc = field->description_;
+  if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) {
+    return YES;
+  }
+  return GPBDataTypeIsObject(desc->dataType);
+}
+
+BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber);
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
+                   BOOL value);
+uint32_t GPBGetHasOneof(GPBMessage *self, int32_t index);
+
+GPB_INLINE BOOL
+GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) {
+  GPBMessageFieldDescription *fieldDesc = field->description_;
+  return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number);
+}
+GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field,
+                                   BOOL value) {
+  GPBMessageFieldDescription *fieldDesc = field->description_;
+  GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value);
+}
+
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
+
+//%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE)
+//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
+//%            NAME$S                     GPBFieldDescriptor *field,
+//%            NAME$S                     TYPE value,
+//%            NAME$S                     GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     BOOL value,
+                                     GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int32_t value,
+                                      GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       uint32_t value,
+                                       GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int64_t value,
+                                      GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       uint64_t value,
+                                       GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      float value,
+                                      GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field,
+                                       double value,
+                                       GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     int32_t value,
+                                     GPBFileSyntax syntax);
+//%PDDM-EXPAND-END (8 expansions)
+
+int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
+                                        GPBFieldDescriptor *field,
+                                        GPBFileSyntax syntax);
+
+id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
+
+void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
+                                       GPBFieldDescriptor *field, id value,
+                                       GPBFileSyntax syntax);
+void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
+                                               GPBFieldDescriptor *field,
+                                               id __attribute__((ns_consumed))
+                                               value,
+                                               GPBFileSyntax syntax);
+
+// GPBGetObjectIvarWithField will automatically create the field (message) if
+// it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil.
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
+                                         GPBFieldDescriptor *field);
+
+void GPBSetAutocreatedRetainedObjectIvarWithField(
+    GPBMessage *self, GPBFieldDescriptor *field,
+    id __attribute__((ns_consumed)) value);
+
+// Clears and releases the autocreated message ivar, if it's autocreated. If
+// it's not set as autocreated, this method does nothing.
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
+                                             GPBFieldDescriptor *field);
+
+// Returns an Objective C encoding for |selector|. |instanceSel| should be
+// YES if it's an instance selector (as opposed to a class selector).
+// |selector| must be a selector from MessageSignatureProtocol.
+const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel);
+
+// Helper for text format name encoding.
+// decodeData is the data describing the sepecial decodes.
+// key and inputString are the input that needs decoding.
+NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
+                                  NSString *inputString);
+
+// A series of selectors that are used solely to get @encoding values
+// for them by the dynamic protobuf runtime code. See
+// GPBMessageEncodingForSelector for details.
+@protocol GPBMessageSignatureProtocol
+@optional
+
+#define GPB_MESSAGE_SIGNATURE_ENTRY(TYPE, NAME) \
+  -(TYPE)get##NAME;                             \
+  -(void)set##NAME : (TYPE)value;               \
+  -(TYPE)get##NAME##AtIndex : (NSUInteger)index;
+
+GPB_MESSAGE_SIGNATURE_ENTRY(BOOL, Bool)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, Fixed32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SFixed32)
+GPB_MESSAGE_SIGNATURE_ENTRY(float, Float)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, Fixed64)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SFixed64)
+GPB_MESSAGE_SIGNATURE_ENTRY(double, Double)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Int32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, Int64)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SInt32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64)
+GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Bytes)
+GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String)
+GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message)
+GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum)
+
+#undef GPB_MESSAGE_SIGNATURE_ENTRY
+
+- (id)getArray;
+- (NSUInteger)getArrayCount;
+- (void)setArray:(NSArray *)array;
++ (id)getClassValue;
+@end
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.h b/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.h
new file mode 100644
index 0000000..28442fb
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.h
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+
+#import "google/protobuf/Duration.pbobjc.h"
+#import "google/protobuf/Timestamp.pbobjc.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+// Extension to GPBTimestamp to work with standard Foundation time/date types.
+@interface GPBTimestamp (GBPWellKnownTypes)
+@property(nonatomic, readwrite, strong) NSDate *date;
+@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+- (instancetype)initWithDate:(NSDate *)date;
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+@end
+
+// Extension to GPBDuration to work with standard Foundation time type.
+@interface GPBDuration (GBPWellKnownTypes)
+@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.m b/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.m
new file mode 100644
index 0000000..fe02f5d
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBWellKnownTypes.m
@@ -0,0 +1,117 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+// Importing sources here to force the linker to include our category methods in
+// the static library. If these were compiled separately, the category methods
+// below would be stripped by the linker.
+
+#import "google/protobuf/Timestamp.pbobjc.m"
+#import "google/protobuf/Duration.pbobjc.m"
+#import "GPBWellKnownTypes.h"
+
+static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds,
+                                                               int32_t nanos) {
+  return seconds + (NSTimeInterval)nanos / 1e9;
+}
+
+static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
+                                                        int64_t *outSeconds) {
+  NSTimeInterval seconds;
+  NSTimeInterval nanos = modf(time, &seconds);
+  nanos *= 1e9;
+  *outSeconds = (int64_t)seconds;
+  return (int32_t)nanos;
+}
+
+@implementation GPBTimestamp (GBPWellKnownTypes)
+
+- (instancetype)initWithDate:(NSDate *)date {
+  return [self initWithTimeIntervalSince1970:date.timeIntervalSince1970];
+}
+
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+  if ((self = [super init])) {
+    int64_t seconds;
+    int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970(
+        timeIntervalSince1970, &seconds);
+    self.seconds = seconds;
+    self.nanos = nanos;
+  }
+  return self;
+}
+
+- (NSDate *)date {
+  return [NSDate dateWithTimeIntervalSince1970:self.timeIntervalSince1970];
+}
+
+- (void)setDate:(NSDate *)date {
+  self.timeIntervalSince1970 = date.timeIntervalSince1970;
+}
+
+- (NSTimeInterval)timeIntervalSince1970 {
+  return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos);
+}
+
+- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+  int64_t seconds;
+  int32_t nanos =
+      SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds);
+  self.seconds = seconds;
+  self.nanos = nanos;
+}
+
+@end
+
+@implementation GPBDuration (GBPWellKnownTypes)
+
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+  if ((self = [super init])) {
+    int64_t seconds;
+    int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970(
+        timeIntervalSince1970, &seconds);
+    self.seconds = seconds;
+    self.nanos = nanos;
+  }
+  return self;
+}
+
+- (NSTimeInterval)timeIntervalSince1970 {
+  return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos);
+}
+
+- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+  int64_t seconds;
+  int32_t nanos =
+      SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds);
+  self.seconds = seconds;
+  self.nanos = nanos;
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/GPBWireFormat.h b/src/third_party/protobuf-3/objectivec/GPBWireFormat.h
new file mode 100644
index 0000000..29cf2f0
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBWireFormat.h
@@ -0,0 +1,72 @@
+// 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.
+
+#import "GPBRuntimeTypes.h"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef enum {
+  GPBWireFormatVarint = 0,
+  GPBWireFormatFixed64 = 1,
+  GPBWireFormatLengthDelimited = 2,
+  GPBWireFormatStartGroup = 3,
+  GPBWireFormatEndGroup = 4,
+  GPBWireFormatFixed32 = 5,
+} GPBWireFormat;
+
+enum {
+  GPBWireFormatMessageSetItem = 1,
+  GPBWireFormatMessageSetTypeId = 2,
+  GPBWireFormatMessageSetMessage = 3
+};
+
+uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType)
+    __attribute__((const));
+GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const));
+uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const));
+
+GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked)
+    __attribute__((const));
+
+#define GPBWireFormatMessageSetItemTag \
+  (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatStartGroup))
+#define GPBWireFormatMessageSetItemEndTag \
+  (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatEndGroup))
+#define GPBWireFormatMessageSetTypeIdTag \
+  (GPBWireFormatMakeTag(GPBWireFormatMessageSetTypeId, GPBWireFormatVarint))
+#define GPBWireFormatMessageSetMessageTag               \
+  (GPBWireFormatMakeTag(GPBWireFormatMessageSetMessage, \
+                        GPBWireFormatLengthDelimited))
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
diff --git a/src/third_party/protobuf-3/objectivec/GPBWireFormat.m b/src/third_party/protobuf-3/objectivec/GPBWireFormat.m
new file mode 100644
index 0000000..193235d
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/GPBWireFormat.m
@@ -0,0 +1,78 @@
+// 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.
+
+#import "GPBWireFormat.h"
+
+#import "GPBUtilities_PackagePrivate.h"
+
+enum {
+  GPBWireFormatTagTypeBits = 3,
+  GPBWireFormatTagTypeMask = 7 /* = (1 << GPBWireFormatTagTypeBits) - 1 */,
+};
+
+uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) {
+  return (fieldNumber << GPBWireFormatTagTypeBits) | wireType;
+}
+
+GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) {
+  return (GPBWireFormat)(tag & GPBWireFormatTagTypeMask);
+}
+
+uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) {
+  return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits);
+}
+
+GPBWireFormat GPBWireFormatForType(GPBDataType type, BOOL isPacked) {
+  if (isPacked) {
+    return GPBWireFormatLengthDelimited;
+  }
+
+  static const GPBWireFormat format[GPBDataType_Count] = {
+      GPBWireFormatVarint,           // GPBDataTypeBool
+      GPBWireFormatFixed32,          // GPBDataTypeFixed32
+      GPBWireFormatFixed32,          // GPBDataTypeSFixed32
+      GPBWireFormatFixed32,          // GPBDataTypeFloat
+      GPBWireFormatFixed64,          // GPBDataTypeFixed64
+      GPBWireFormatFixed64,          // GPBDataTypeSFixed64
+      GPBWireFormatFixed64,          // GPBDataTypeDouble
+      GPBWireFormatVarint,           // GPBDataTypeInt32
+      GPBWireFormatVarint,           // GPBDataTypeInt64
+      GPBWireFormatVarint,           // GPBDataTypeSInt32
+      GPBWireFormatVarint,           // GPBDataTypeSInt64
+      GPBWireFormatVarint,           // GPBDataTypeUInt32
+      GPBWireFormatVarint,           // GPBDataTypeUInt64
+      GPBWireFormatLengthDelimited,  // GPBDataTypeBytes
+      GPBWireFormatLengthDelimited,  // GPBDataTypeString
+      GPBWireFormatLengthDelimited,  // GPBDataTypeMessage
+      GPBWireFormatStartGroup,       // GPBDataTypeGroup
+      GPBWireFormatVarint            // GPBDataTypeEnum
+  };
+  return format[type];
+}
diff --git a/src/third_party/protobuf-3/objectivec/README.md b/src/third_party/protobuf-3/objectivec/README.md
new file mode 100644
index 0000000..c7313e4
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/README.md
@@ -0,0 +1,152 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the Objective C Protocol Buffers runtime library.
+
+Requirements
+------------
+
+The Objective C implementation requires:
+
+- Objective C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X).
+- Xcode 7.0 (or later).
+- The library code does *not* use ARC (for performance reasons), but it all can
+  be called from ARC code.
+
+Installation
+------------
+
+The full distribution pulled from github includes the sources for both the
+compiler (protoc) and the runtime (this directory). To build the compiler
+and run the runtime tests, you can use:
+
+     $ objectivec/DevTools/full_mac_build.sh
+
+This will generate the `src/protoc` binary.
+
+Building
+--------
+
+There are two ways to include the Runtime sources in your project:
+
+Add `objectivec/\*.h` & `objectivec/GPBProtocolBuffers.m` to your project.
+
+*or*
+
+Add `objectivec/\*.h` & `objectivec/\*.m` except for
+`objectivec/GPBProtocolBuffers.m` to your project.
+
+
+If the target is using ARC, remember to turn off ARC (`-fno-objc-arc`) for the
+`.m` files.
+
+The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h' and
+`\*.pbobjc.m`) are then also added to the target.
+
+Usage
+-----
+
+The objects generated for messages should work like any other Objective C
+object. They are mutable objects, but if you don't change them, they are safe
+to share between threads (similar to passing an NSMutableDictionary between
+threads/queues; as long as no one mutates it, things are fine).
+
+There are a few behaviors worth calling out:
+
+A property that is type NSString\* will never return nil. If the value is
+unset, it will return an empty string (@""). This is inpart to align things
+with the Protocol Buffers spec which says the default for strings is an empty
+string, but also so you can always safely pass them to isEqual:/compare:, etc.
+and have deterministic results.
+
+A property that is type NSData\* also won't return nil, it will return an empty
+data ([NSData data]). The reasoning is the same as for NSString not returning
+nil.
+
+A property that is another GPBMessage class also will not return nil. If the
+field wasn't already set, you will get a instance of the correct class. This
+instance will be a temporary instance unless you mutate it, at which point it
+will be attached to its parent object. We call this pattern *autocreators*.
+Similar to NSString and NSData properties it makes things a little safer when
+using them with isEqual:/etc.; but more importantly, this allows you to write
+code that uses Objective C's property dot notation to walk into nested objects
+and access and/or assign things without having to check that they are not nil
+and create them each step along the way. You can write this:
+
+```
+- (void)updateRecord:(MyMessage *)msg {
+  ...
+  // Note: You don't have to check subMessage and otherMessage for nil and
+  // alloc/init/assign them back along the way.
+  msg.subMessage.otherMessage.lastName = @"Smith";
+  ...
+}
+```
+
+If you want to check if a GPBMessage property is present, there is always as
+`has\[NAME\]` property to go with the main property to check if it is set.
+
+A property that is of an Array or Dictionary type also provides *autocreator*
+behavior and will never return nil. This provides all the same benefits you
+see for the message properties. Again, you can write:
+
+```
+- (void)updateRecord:(MyMessage *)msg {
+  ...
+  // Note: Just like above, you don't have to check subMessage and otherMessage
+  // for nil and alloc/init/assign them back along the way. You also don't have
+  // to create the siblingsArray, you can safely just append to it.
+  [msg.subMessage.otherMessage.siblingsArray addObject:@"Pat"];
+  ...
+}
+```
+
+If you are inspecting a message you got from some other place (server, disk,
+etc), you may want to check if the Array or Dictionary has entries without
+causing it to be created for you. For this, there is always a `\[NAME\]_Count`
+property also provided that can return zero or the real count, but won't trigger
+the creation.
+
+For primitive type fields (ints, floats, bools, enum) in messages defined in a
+`.proto` file that use *proto2* syntax there are conceptual differences between
+having an *explicit* and *default* value. You can always get the value of the
+property. In the case that it hasn't been set you will get the default. In
+cases where you need to know whether it was set explicitly or you are just
+getting the default, you can use the `has\[NAME\]` property. If the value has
+been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`.
+*proto3* syntax messages do away with this concept, thus the default values are
+never included when the message is encoded.
+
+The Objective C classes/enums can be used from Swift code.
+
+Objective C Generator Options
+-----------------------------
+
+**objc_class_prefix=\<prefix\>** (no default)
+
+Since Objective C uses a global namespace for all of its classes, there can
+be collisions. This option provides a prefix that will be added to the Enums
+and Objects (for messages) generated from the proto. Convention is to base
+the prefix on the package the proto is in.
+
+Contributing
+------------
+
+Please make updates to the tests along with changes. If just changing the
+runtime, the Xcode projects can be used to build and run tests. If your change
+also requires changes to the generated code,
+`objectivec/DevTools/full_mac_build.sh` can be used to easily rebuild and test
+changes. Passing `-h` to the script will show the addition options that could
+be useful.
+
+Documentation
+-------------
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+    https://developers.google.com/protocol-buffers/
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBARCUnittestProtos.m b/src/third_party/protobuf-3/objectivec/Tests/GPBARCUnittestProtos.m
new file mode 100644
index 0000000..28d2396
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBARCUnittestProtos.m
@@ -0,0 +1,61 @@
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// 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.
+
+// Makes sure all the generated headers compile with ARC on.
+
+// The unittest_custom_options.proto extends the messages in descriptor.proto
+// so we build it in to test extending in general. The library doesn't provide
+// a descriptor as it doesn't use the classes/enums.
+#import "google/protobuf/Descriptor.pbobjc.h"
+
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
+#import "google/protobuf/UnittestCycle.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestEmpty.pbobjc.h"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "google/protobuf/UnittestImportLite.pbobjc.h"
+#import "google/protobuf/UnittestImportPublic.pbobjc.h"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.h"
+#import "google/protobuf/UnittestLite.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBArrayTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBArrayTests.m
new file mode 100644
index 0000000..0fb15e4
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBArrayTests.m
@@ -0,0 +1,3438 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBArray.h"
+
+#import "GPBTestUtilities.h"
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value;
+- (instancetype)initWithValues:(const int32_t [])values
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+static BOOL TestingEnum_IsValidValue2(int32_t value) {
+  switch (value) {
+    case 71:
+    case 72:
+    case 73:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value {
+  return [[[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                         rawValues:&value
+                                             count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                    count:count];
+}
+@end
+
+#pragma mark - PDDM Macros
+
+//%PDDM-DEFINE ARRAY_TESTS(NAME, TYPE, VAL1, VAL2, VAL3, VAL4)
+//%ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, )
+//%PDDM-DEFINE ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, HELPER)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##ArrayTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##NAME##ArrayTests
+//%
+//%- (void)testEmpty {
+//%  GPB##NAME##Array *array = [[GPB##NAME##Array alloc] init];
+//%  XCTAssertNotNil(array);
+//%  XCTAssertEqual(array.count, 0U);
+//%  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+//%  [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    #pragma unused(value, idx, stop)
+//%    XCTFail(@"Shouldn't get here!");
+//%  }];
+//%  [array enumerateValuesWithOptions:NSEnumerationReverse
+//%                         usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    #pragma unused(value, idx, stop)
+//%    XCTFail(@"Shouldn't get here!");
+//%  }];
+//%  [array release];
+//%}
+//%
+//%- (void)testOne {
+//%  GPB##NAME##Array *array = [GPB##NAME##Array arrayWithValue:VAL1];
+//%  XCTAssertNotNil(array);
+//%  XCTAssertEqual(array.count, 1U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+//%  [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, 0U);
+//%    XCTAssertEqual(value, VAL1);
+//%    XCTAssertNotEqual(stop, NULL);
+//%  }];
+//%  [array enumerateValuesWithOptions:NSEnumerationReverse
+//%                         usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, 0U);
+//%    XCTAssertEqual(value, VAL1);
+//%    XCTAssertNotEqual(stop, NULL);
+//%  }];
+//%}
+//%
+//%- (void)testBasics {
+//%  static const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%  XCTAssertEqual(array.count, 4U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL2);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL4);
+//%  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+//%  __block NSUInteger idx2 = 0;
+//%  [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, idx2);
+//%    XCTAssertEqual(value, kValues[idx]);
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx2;
+//%  }];
+//%  idx2 = 0;
+//%  [array enumerateValuesWithOptions:NSEnumerationReverse
+//%                         usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, (3 - idx2));
+//%    XCTAssertEqual(value, kValues[idx]);
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx2;
+//%  }];
+//%  // Stopping the enumeration.
+//%  idx2 = 0;
+//%  [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, idx2);
+//%    XCTAssertEqual(value, kValues[idx]);
+//%    XCTAssertNotEqual(stop, NULL);
+//%    if (idx2 == 1) *stop = YES;
+//%    XCTAssertNotEqual(idx, 2U);
+//%    XCTAssertNotEqual(idx, 3U);
+//%    ++idx2;
+//%  }];
+//%  idx2 = 0;
+//%  [array enumerateValuesWithOptions:NSEnumerationReverse
+//%                         usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%    XCTAssertEqual(idx, (3 - idx2));
+//%    XCTAssertEqual(value, kValues[idx]);
+//%    XCTAssertNotEqual(stop, NULL);
+//%    if (idx2 == 1) *stop = YES;
+//%    XCTAssertNotEqual(idx, 1U);
+//%    XCTAssertNotEqual(idx, 0U);
+//%    ++idx2;
+//%  }];
+//%  [array release];
+//%}
+//%
+//%- (void)testEquality {
+//%  const TYPE kValues1[] = { VAL1, VAL2, VAL3 };
+//%  const TYPE kValues2[] = { VAL1, VAL4, VAL3 };
+//%  const TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  GPB##NAME##Array *array1 =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues1
+//%            NAME$S                     count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertNotNil(array1);
+//%  GPB##NAME##Array *array1prime =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues1
+//%            NAME$S                     count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertNotNil(array1prime);
+//%  GPB##NAME##Array *array2 =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues2
+//%            NAME$S                     count:GPBARRAYSIZE(kValues2)];
+//%  XCTAssertNotNil(array2);
+//%  GPB##NAME##Array *array3 =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues3
+//%            NAME$S                     count:GPBARRAYSIZE(kValues3)];
+//%  XCTAssertNotNil(array3);
+//%
+//%  // 1/1Prime should be different objects, but equal.
+//%  XCTAssertNotEqual(array1, array1prime);
+//%  XCTAssertEqualObjects(array1, array1prime);
+//%  // Equal, so they must have same hash.
+//%  XCTAssertEqual([array1 hash], [array1prime hash]);
+//%
+//%  // 1/2/3 shouldn't be equal.
+//%  XCTAssertNotEqualObjects(array1, array2);
+//%  XCTAssertNotEqualObjects(array1, array3);
+//%  XCTAssertNotEqualObjects(array2, array3);
+//%
+//%  [array1 release];
+//%  [array1prime release];
+//%  [array2 release];
+//%  [array3 release];
+//%}
+//%
+//%- (void)testCopy {
+//%  const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%
+//%  GPB##NAME##Array *array2 = [array copy];
+//%  XCTAssertNotNil(array2);
+//%
+//%  // Should be new object but equal.
+//%  XCTAssertNotEqual(array, array2);
+//%  XCTAssertEqualObjects(array, array2);
+//%  [array2 release];
+//%  [array release];
+//%}
+//%
+//%- (void)testArrayFromArray {
+//%  const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%
+//%  GPB##NAME##Array *array2 = [GPB##NAME##Array arrayWithValueArray:array];
+//%  XCTAssertNotNil(array2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(array, array2);
+//%  XCTAssertEqualObjects(array, array2);
+//%  [array release];
+//%}
+//%
+//%- (void)testAdds {
+//%  GPB##NAME##Array *array = [GPB##NAME##Array array];
+//%  XCTAssertNotNil(array);
+//%
+//%  XCTAssertEqual(array.count, 0U);
+//%  [array addValue:VAL1];
+//%  XCTAssertEqual(array.count, 1U);
+//%
+//%  const TYPE kValues1[] = { VAL2, VAL3 };
+//%  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertEqual(array.count, 3U);
+//%
+//%  const TYPE kValues2[] = { VAL4, VAL1 };
+//%  GPB##NAME##Array *array2 =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues2
+//%            NAME$S                     count:GPBARRAYSIZE(kValues2)];
+//%  XCTAssertNotNil(array2);
+//%  [array add##HELPER##ValuesFromArray:array2];
+//%  XCTAssertEqual(array.count, 5U);
+//%
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL2);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL4);
+//%  XCTAssertEqual([array valueAtIndex:4], VAL1);
+//%  [array2 release];
+//%}
+//%
+//%- (void)testInsert {
+//%  const TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%  XCTAssertEqual(array.count, 3U);
+//%
+//%  // First
+//%  [array insertValue:VAL4 atIndex:0];
+//%  XCTAssertEqual(array.count, 4U);
+//%
+//%  // Middle
+//%  [array insertValue:VAL4 atIndex:2];
+//%  XCTAssertEqual(array.count, 5U);
+//%
+//%  // End
+//%  [array insertValue:VAL4 atIndex:5];
+//%  XCTAssertEqual(array.count, 6U);
+//%
+//%  // Too far.
+//%  XCTAssertThrowsSpecificNamed([array insertValue:VAL4 atIndex:7],
+//%                               NSException, NSRangeException);
+//%
+//%  XCTAssertEqual([array valueAtIndex:0], VAL4);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL4);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%  XCTAssertEqual([array valueAtIndex:4], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:5], VAL4);
+//%  [array release];
+//%}
+//%
+//%- (void)testRemove {
+//%  const TYPE kValues[] = { VAL4, VAL1, VAL2, VAL4, VAL3, VAL4 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%  XCTAssertEqual(array.count, 6U);
+//%
+//%  // First
+//%  [array removeValueAtIndex:0];
+//%  XCTAssertEqual(array.count, 5U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%
+//%  // Middle
+//%  [array removeValueAtIndex:2];
+//%  XCTAssertEqual(array.count, 4U);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//%  // End
+//%  [array removeValueAtIndex:3];
+//%  XCTAssertEqual(array.count, 3U);
+//%
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL2);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//%  // Too far.
+//%  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+//%                               NSException, NSRangeException);
+//%
+//%  [array removeAll];
+//%  XCTAssertEqual(array.count, 0U);
+//%  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+//%                               NSException, NSRangeException);
+//%  [array release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//%  const TYPE kValues[] = { VAL1, VAL1, VAL3, VAL3 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%
+//%  [array replaceValueAtIndex:1 withValue:VAL2];
+//%  [array replaceValueAtIndex:3 withValue:VAL4];
+//%  XCTAssertEqual(array.count, 4U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL2);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL4);
+//%
+//%  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:VAL4],
+//%                               NSException, NSRangeException);
+//%
+//%  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+//%  XCTAssertEqual(array.count, 4U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL4);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//%  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+//%  XCTAssertEqual(array.count, 4U);
+//%  XCTAssertEqual([array valueAtIndex:0], VAL3);
+//%  XCTAssertEqual([array valueAtIndex:1], VAL4);
+//%  XCTAssertEqual([array valueAtIndex:2], VAL1);
+//%  XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//%  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+//%                               NSException, NSRangeException);
+//%  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+//%                               NSException, NSRangeException);
+//%  [array release];
+//%}
+//%
+//%- (void)testInternalResizing {
+//%  const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  GPB##NAME##Array *array =
+//%      [[GPB##NAME##Array alloc] initWithValues:kValues
+//%            NAME$S                     count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(array);
+//%
+//%  // Add/remove to trigger the intneral buffer to grow/shrink.
+//%  for (int i = 0; i < 100; ++i) {
+//%    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+//%  }
+//%  XCTAssertEqual(array.count, 404U);
+//%  for (int i = 0; i < 100; ++i) {
+//%    [array removeValueAtIndex:(i * 2)];
+//%  }
+//%  XCTAssertEqual(array.count, 304U);
+//%  for (int i = 0; i < 100; ++i) {
+//%    [array insertValue:VAL4 atIndex:(i * 3)];
+//%  }
+//%  XCTAssertEqual(array.count, 404U);
+//%  [array removeAll];
+//%  XCTAssertEqual(array.count, 0U);
+//%  [array release];
+//%}
+//%
+//%@end
+//%
+//%PDDM-EXPAND ARRAY_TESTS(Int32, int32_t, 1, 2, 3, 4)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt32ArrayTests
+
+- (void)testEmpty {
+  GPBInt32Array *array = [[GPBInt32Array alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBInt32Array *array = [GPBInt32Array arrayWithValue:1];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 1);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 1);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const int32_t kValues[] = { 1, 2, 3, 4 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertEqual([array valueAtIndex:1], 2);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+  XCTAssertEqual([array valueAtIndex:3], 4);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const int32_t kValues1[] = { 1, 2, 3 };
+  const int32_t kValues2[] = { 1, 4, 3 };
+  const int32_t kValues3[] = { 1, 2, 3, 4 };
+  GPBInt32Array *array1 =
+      [[GPBInt32Array alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBInt32Array *array1prime =
+      [[GPBInt32Array alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBInt32Array *array2 =
+      [[GPBInt32Array alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBInt32Array *array3 =
+      [[GPBInt32Array alloc] initWithValues:kValues3
+                                      count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const int32_t kValues[] = { 1, 2, 3, 4 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBInt32Array *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const int32_t kValues[] = { 1, 2, 3, 4 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBInt32Array *array2 = [GPBInt32Array arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBInt32Array *array = [GPBInt32Array array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:1];
+  XCTAssertEqual(array.count, 1U);
+
+  const int32_t kValues1[] = { 2, 3 };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const int32_t kValues2[] = { 4, 1 };
+  GPBInt32Array *array2 =
+      [[GPBInt32Array alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertEqual([array valueAtIndex:1], 2);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+  XCTAssertEqual([array valueAtIndex:3], 4);
+  XCTAssertEqual([array valueAtIndex:4], 1);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const int32_t kValues[] = { 1, 2, 3 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:4 atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:4 atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:4 atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:4 atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 4);
+  XCTAssertEqual([array valueAtIndex:1], 1);
+  XCTAssertEqual([array valueAtIndex:2], 4);
+  XCTAssertEqual([array valueAtIndex:3], 2);
+  XCTAssertEqual([array valueAtIndex:4], 3);
+  XCTAssertEqual([array valueAtIndex:5], 4);
+  [array release];
+}
+
+- (void)testRemove {
+  const int32_t kValues[] = { 4, 1, 2, 4, 3, 4 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 1);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertEqual([array valueAtIndex:1], 2);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kValues[] = { 1, 1, 3, 3 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:2];
+  [array replaceValueAtIndex:3 withValue:4];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertEqual([array valueAtIndex:1], 2);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+  XCTAssertEqual([array valueAtIndex:3], 4);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:4],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 1);
+  XCTAssertEqual([array valueAtIndex:1], 4);
+  XCTAssertEqual([array valueAtIndex:2], 3);
+  XCTAssertEqual([array valueAtIndex:3], 2);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 3);
+  XCTAssertEqual([array valueAtIndex:1], 4);
+  XCTAssertEqual([array valueAtIndex:2], 1);
+  XCTAssertEqual([array valueAtIndex:3], 2);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const int32_t kValues[] = { 1, 2, 3, 4 };
+  GPBInt32Array *array =
+      [[GPBInt32Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:4 atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt32, uint32_t, 11U, 12U, 13U, 14U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32
+
+@interface GPBUInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt32ArrayTests
+
+- (void)testEmpty {
+  GPBUInt32Array *array = [[GPBUInt32Array alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBUInt32Array *array = [GPBUInt32Array arrayWithValue:11U];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 11U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 11U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertEqual([array valueAtIndex:1], 12U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+  XCTAssertEqual([array valueAtIndex:3], 14U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const uint32_t kValues1[] = { 11U, 12U, 13U };
+  const uint32_t kValues2[] = { 11U, 14U, 13U };
+  const uint32_t kValues3[] = { 11U, 12U, 13U, 14U };
+  GPBUInt32Array *array1 =
+      [[GPBUInt32Array alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBUInt32Array *array1prime =
+      [[GPBUInt32Array alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBUInt32Array *array2 =
+      [[GPBUInt32Array alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBUInt32Array *array3 =
+      [[GPBUInt32Array alloc] initWithValues:kValues3
+                                       count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBUInt32Array *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBUInt32Array *array2 = [GPBUInt32Array arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBUInt32Array *array = [GPBUInt32Array array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:11U];
+  XCTAssertEqual(array.count, 1U);
+
+  const uint32_t kValues1[] = { 12U, 13U };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const uint32_t kValues2[] = { 14U, 11U };
+  GPBUInt32Array *array2 =
+      [[GPBUInt32Array alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertEqual([array valueAtIndex:1], 12U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+  XCTAssertEqual([array valueAtIndex:3], 14U);
+  XCTAssertEqual([array valueAtIndex:4], 11U);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const uint32_t kValues[] = { 11U, 12U, 13U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:14U atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:14U atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:14U atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:14U atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 14U);
+  XCTAssertEqual([array valueAtIndex:1], 11U);
+  XCTAssertEqual([array valueAtIndex:2], 14U);
+  XCTAssertEqual([array valueAtIndex:3], 12U);
+  XCTAssertEqual([array valueAtIndex:4], 13U);
+  XCTAssertEqual([array valueAtIndex:5], 14U);
+  [array release];
+}
+
+- (void)testRemove {
+  const uint32_t kValues[] = { 14U, 11U, 12U, 14U, 13U, 14U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertEqual([array valueAtIndex:1], 12U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kValues[] = { 11U, 11U, 13U, 13U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:12U];
+  [array replaceValueAtIndex:3 withValue:14U];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertEqual([array valueAtIndex:1], 12U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+  XCTAssertEqual([array valueAtIndex:3], 14U);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:14U],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 11U);
+  XCTAssertEqual([array valueAtIndex:1], 14U);
+  XCTAssertEqual([array valueAtIndex:2], 13U);
+  XCTAssertEqual([array valueAtIndex:3], 12U);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 13U);
+  XCTAssertEqual([array valueAtIndex:1], 14U);
+  XCTAssertEqual([array valueAtIndex:2], 11U);
+  XCTAssertEqual([array valueAtIndex:3], 12U);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+  GPBUInt32Array *array =
+      [[GPBUInt32Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:14U atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Int64, int64_t, 31LL, 32LL, 33LL, 34LL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64
+
+@interface GPBInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt64ArrayTests
+
+- (void)testEmpty {
+  GPBInt64Array *array = [[GPBInt64Array alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBInt64Array *array = [GPBInt64Array arrayWithValue:31LL];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 31LL);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 31LL);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertEqual([array valueAtIndex:1], 32LL);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+  XCTAssertEqual([array valueAtIndex:3], 34LL);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const int64_t kValues1[] = { 31LL, 32LL, 33LL };
+  const int64_t kValues2[] = { 31LL, 34LL, 33LL };
+  const int64_t kValues3[] = { 31LL, 32LL, 33LL, 34LL };
+  GPBInt64Array *array1 =
+      [[GPBInt64Array alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBInt64Array *array1prime =
+      [[GPBInt64Array alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBInt64Array *array2 =
+      [[GPBInt64Array alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBInt64Array *array3 =
+      [[GPBInt64Array alloc] initWithValues:kValues3
+                                      count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBInt64Array *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBInt64Array *array2 = [GPBInt64Array arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBInt64Array *array = [GPBInt64Array array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:31LL];
+  XCTAssertEqual(array.count, 1U);
+
+  const int64_t kValues1[] = { 32LL, 33LL };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const int64_t kValues2[] = { 34LL, 31LL };
+  GPBInt64Array *array2 =
+      [[GPBInt64Array alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertEqual([array valueAtIndex:1], 32LL);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+  XCTAssertEqual([array valueAtIndex:3], 34LL);
+  XCTAssertEqual([array valueAtIndex:4], 31LL);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const int64_t kValues[] = { 31LL, 32LL, 33LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:34LL atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:34LL atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:34LL atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:34LL atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 34LL);
+  XCTAssertEqual([array valueAtIndex:1], 31LL);
+  XCTAssertEqual([array valueAtIndex:2], 34LL);
+  XCTAssertEqual([array valueAtIndex:3], 32LL);
+  XCTAssertEqual([array valueAtIndex:4], 33LL);
+  XCTAssertEqual([array valueAtIndex:5], 34LL);
+  [array release];
+}
+
+- (void)testRemove {
+  const int64_t kValues[] = { 34LL, 31LL, 32LL, 34LL, 33LL, 34LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertEqual([array valueAtIndex:1], 32LL);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kValues[] = { 31LL, 31LL, 33LL, 33LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:32LL];
+  [array replaceValueAtIndex:3 withValue:34LL];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertEqual([array valueAtIndex:1], 32LL);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+  XCTAssertEqual([array valueAtIndex:3], 34LL);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:34LL],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 31LL);
+  XCTAssertEqual([array valueAtIndex:1], 34LL);
+  XCTAssertEqual([array valueAtIndex:2], 33LL);
+  XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 33LL);
+  XCTAssertEqual([array valueAtIndex:1], 34LL);
+  XCTAssertEqual([array valueAtIndex:2], 31LL);
+  XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+  GPBInt64Array *array =
+      [[GPBInt64Array alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:34LL atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt64, uint64_t, 41ULL, 42ULL, 43ULL, 44ULL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64
+
+@interface GPBUInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt64ArrayTests
+
+- (void)testEmpty {
+  GPBUInt64Array *array = [[GPBUInt64Array alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBUInt64Array *array = [GPBUInt64Array arrayWithValue:41ULL];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 41ULL);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 41ULL);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertEqual([array valueAtIndex:1], 42ULL);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+  XCTAssertEqual([array valueAtIndex:3], 44ULL);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const uint64_t kValues1[] = { 41ULL, 42ULL, 43ULL };
+  const uint64_t kValues2[] = { 41ULL, 44ULL, 43ULL };
+  const uint64_t kValues3[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array1 =
+      [[GPBUInt64Array alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBUInt64Array *array1prime =
+      [[GPBUInt64Array alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBUInt64Array *array2 =
+      [[GPBUInt64Array alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBUInt64Array *array3 =
+      [[GPBUInt64Array alloc] initWithValues:kValues3
+                                       count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBUInt64Array *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBUInt64Array *array2 = [GPBUInt64Array arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBUInt64Array *array = [GPBUInt64Array array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:41ULL];
+  XCTAssertEqual(array.count, 1U);
+
+  const uint64_t kValues1[] = { 42ULL, 43ULL };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const uint64_t kValues2[] = { 44ULL, 41ULL };
+  GPBUInt64Array *array2 =
+      [[GPBUInt64Array alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertEqual([array valueAtIndex:1], 42ULL);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+  XCTAssertEqual([array valueAtIndex:3], 44ULL);
+  XCTAssertEqual([array valueAtIndex:4], 41ULL);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:44ULL atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:44ULL atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:44ULL atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:44ULL atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 44ULL);
+  XCTAssertEqual([array valueAtIndex:1], 41ULL);
+  XCTAssertEqual([array valueAtIndex:2], 44ULL);
+  XCTAssertEqual([array valueAtIndex:3], 42ULL);
+  XCTAssertEqual([array valueAtIndex:4], 43ULL);
+  XCTAssertEqual([array valueAtIndex:5], 44ULL);
+  [array release];
+}
+
+- (void)testRemove {
+  const uint64_t kValues[] = { 44ULL, 41ULL, 42ULL, 44ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertEqual([array valueAtIndex:1], 42ULL);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kValues[] = { 41ULL, 41ULL, 43ULL, 43ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:42ULL];
+  [array replaceValueAtIndex:3 withValue:44ULL];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertEqual([array valueAtIndex:1], 42ULL);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+  XCTAssertEqual([array valueAtIndex:3], 44ULL);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:44ULL],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 41ULL);
+  XCTAssertEqual([array valueAtIndex:1], 44ULL);
+  XCTAssertEqual([array valueAtIndex:2], 43ULL);
+  XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 43ULL);
+  XCTAssertEqual([array valueAtIndex:1], 44ULL);
+  XCTAssertEqual([array valueAtIndex:2], 41ULL);
+  XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+  GPBUInt64Array *array =
+      [[GPBUInt64Array alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:44ULL atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Float, float, 51.f, 52.f, 53.f, 54.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Float
+
+@interface GPBFloatArrayTests : XCTestCase
+@end
+
+@implementation GPBFloatArrayTests
+
+- (void)testEmpty {
+  GPBFloatArray *array = [[GPBFloatArray alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBFloatArray *array = [GPBFloatArray arrayWithValue:51.f];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 51.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 51.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertEqual([array valueAtIndex:1], 52.f);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+  XCTAssertEqual([array valueAtIndex:3], 54.f);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const float kValues1[] = { 51.f, 52.f, 53.f };
+  const float kValues2[] = { 51.f, 54.f, 53.f };
+  const float kValues3[] = { 51.f, 52.f, 53.f, 54.f };
+  GPBFloatArray *array1 =
+      [[GPBFloatArray alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBFloatArray *array1prime =
+      [[GPBFloatArray alloc] initWithValues:kValues1
+                                      count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBFloatArray *array2 =
+      [[GPBFloatArray alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBFloatArray *array3 =
+      [[GPBFloatArray alloc] initWithValues:kValues3
+                                      count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBFloatArray *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBFloatArray *array2 = [GPBFloatArray arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBFloatArray *array = [GPBFloatArray array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:51.f];
+  XCTAssertEqual(array.count, 1U);
+
+  const float kValues1[] = { 52.f, 53.f };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const float kValues2[] = { 54.f, 51.f };
+  GPBFloatArray *array2 =
+      [[GPBFloatArray alloc] initWithValues:kValues2
+                                      count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertEqual([array valueAtIndex:1], 52.f);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+  XCTAssertEqual([array valueAtIndex:3], 54.f);
+  XCTAssertEqual([array valueAtIndex:4], 51.f);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const float kValues[] = { 51.f, 52.f, 53.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:54.f atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:54.f atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:54.f atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:54.f atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 54.f);
+  XCTAssertEqual([array valueAtIndex:1], 51.f);
+  XCTAssertEqual([array valueAtIndex:2], 54.f);
+  XCTAssertEqual([array valueAtIndex:3], 52.f);
+  XCTAssertEqual([array valueAtIndex:4], 53.f);
+  XCTAssertEqual([array valueAtIndex:5], 54.f);
+  [array release];
+}
+
+- (void)testRemove {
+  const float kValues[] = { 54.f, 51.f, 52.f, 54.f, 53.f, 54.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertEqual([array valueAtIndex:1], 52.f);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const float kValues[] = { 51.f, 51.f, 53.f, 53.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:52.f];
+  [array replaceValueAtIndex:3 withValue:54.f];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertEqual([array valueAtIndex:1], 52.f);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+  XCTAssertEqual([array valueAtIndex:3], 54.f);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:54.f],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 51.f);
+  XCTAssertEqual([array valueAtIndex:1], 54.f);
+  XCTAssertEqual([array valueAtIndex:2], 53.f);
+  XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 53.f);
+  XCTAssertEqual([array valueAtIndex:1], 54.f);
+  XCTAssertEqual([array valueAtIndex:2], 51.f);
+  XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+  GPBFloatArray *array =
+      [[GPBFloatArray alloc] initWithValues:kValues
+                                      count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:54.f atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Double, double, 61., 62., 63., 64.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Double
+
+@interface GPBDoubleArrayTests : XCTestCase
+@end
+
+@implementation GPBDoubleArrayTests
+
+- (void)testEmpty {
+  GPBDoubleArray *array = [[GPBDoubleArray alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBDoubleArray *array = [GPBDoubleArray arrayWithValue:61.];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 61.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 61.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const double kValues[] = { 61., 62., 63., 64. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertEqual([array valueAtIndex:1], 62.);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+  XCTAssertEqual([array valueAtIndex:3], 64.);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const double kValues1[] = { 61., 62., 63. };
+  const double kValues2[] = { 61., 64., 63. };
+  const double kValues3[] = { 61., 62., 63., 64. };
+  GPBDoubleArray *array1 =
+      [[GPBDoubleArray alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBDoubleArray *array1prime =
+      [[GPBDoubleArray alloc] initWithValues:kValues1
+                                       count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBDoubleArray *array2 =
+      [[GPBDoubleArray alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBDoubleArray *array3 =
+      [[GPBDoubleArray alloc] initWithValues:kValues3
+                                       count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const double kValues[] = { 61., 62., 63., 64. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBDoubleArray *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const double kValues[] = { 61., 62., 63., 64. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBDoubleArray *array2 = [GPBDoubleArray arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBDoubleArray *array = [GPBDoubleArray array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:61.];
+  XCTAssertEqual(array.count, 1U);
+
+  const double kValues1[] = { 62., 63. };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const double kValues2[] = { 64., 61. };
+  GPBDoubleArray *array2 =
+      [[GPBDoubleArray alloc] initWithValues:kValues2
+                                       count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertEqual([array valueAtIndex:1], 62.);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+  XCTAssertEqual([array valueAtIndex:3], 64.);
+  XCTAssertEqual([array valueAtIndex:4], 61.);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const double kValues[] = { 61., 62., 63. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:64. atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:64. atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:64. atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:64. atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 64.);
+  XCTAssertEqual([array valueAtIndex:1], 61.);
+  XCTAssertEqual([array valueAtIndex:2], 64.);
+  XCTAssertEqual([array valueAtIndex:3], 62.);
+  XCTAssertEqual([array valueAtIndex:4], 63.);
+  XCTAssertEqual([array valueAtIndex:5], 64.);
+  [array release];
+}
+
+- (void)testRemove {
+  const double kValues[] = { 64., 61., 62., 64., 63., 64. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertEqual([array valueAtIndex:1], 62.);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const double kValues[] = { 61., 61., 63., 63. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:62.];
+  [array replaceValueAtIndex:3 withValue:64.];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertEqual([array valueAtIndex:1], 62.);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+  XCTAssertEqual([array valueAtIndex:3], 64.);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:64.],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 61.);
+  XCTAssertEqual([array valueAtIndex:1], 64.);
+  XCTAssertEqual([array valueAtIndex:2], 63.);
+  XCTAssertEqual([array valueAtIndex:3], 62.);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 63.);
+  XCTAssertEqual([array valueAtIndex:1], 64.);
+  XCTAssertEqual([array valueAtIndex:2], 61.);
+  XCTAssertEqual([array valueAtIndex:3], 62.);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const double kValues[] = { 61., 62., 63., 64. };
+  GPBDoubleArray *array =
+      [[GPBDoubleArray alloc] initWithValues:kValues
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:64. atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Bool, BOOL, TRUE, TRUE, FALSE, FALSE)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool
+
+@interface GPBBoolArrayTests : XCTestCase
+@end
+
+@implementation GPBBoolArrayTests
+
+- (void)testEmpty {
+  GPBBoolArray *array = [[GPBBoolArray alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBBoolArray *array = [GPBBoolArray arrayWithValue:TRUE];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, TRUE);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, TRUE);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertEqual([array valueAtIndex:1], TRUE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+  XCTAssertEqual([array valueAtIndex:3], FALSE);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const BOOL kValues1[] = { TRUE, TRUE, FALSE };
+  const BOOL kValues2[] = { TRUE, FALSE, FALSE };
+  const BOOL kValues3[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array1 =
+      [[GPBBoolArray alloc] initWithValues:kValues1
+                                     count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBBoolArray *array1prime =
+      [[GPBBoolArray alloc] initWithValues:kValues1
+                                     count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBBoolArray *array2 =
+      [[GPBBoolArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBBoolArray *array3 =
+      [[GPBBoolArray alloc] initWithValues:kValues3
+                                     count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBBoolArray *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBBoolArray *array2 = [GPBBoolArray arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBBoolArray *array = [GPBBoolArray array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:TRUE];
+  XCTAssertEqual(array.count, 1U);
+
+  const BOOL kValues1[] = { TRUE, FALSE };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const BOOL kValues2[] = { FALSE, TRUE };
+  GPBBoolArray *array2 =
+      [[GPBBoolArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertEqual([array valueAtIndex:1], TRUE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+  XCTAssertEqual([array valueAtIndex:3], FALSE);
+  XCTAssertEqual([array valueAtIndex:4], TRUE);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const BOOL kValues[] = { TRUE, TRUE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:FALSE atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:FALSE atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:FALSE atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:FALSE atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], FALSE);
+  XCTAssertEqual([array valueAtIndex:1], TRUE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+  XCTAssertEqual([array valueAtIndex:3], TRUE);
+  XCTAssertEqual([array valueAtIndex:4], FALSE);
+  XCTAssertEqual([array valueAtIndex:5], FALSE);
+  [array release];
+}
+
+- (void)testRemove {
+  const BOOL kValues[] = { FALSE, TRUE, TRUE, FALSE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertEqual([array valueAtIndex:1], TRUE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:TRUE];
+  [array replaceValueAtIndex:3 withValue:FALSE];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertEqual([array valueAtIndex:1], TRUE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+  XCTAssertEqual([array valueAtIndex:3], FALSE);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:FALSE],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], TRUE);
+  XCTAssertEqual([array valueAtIndex:1], FALSE);
+  XCTAssertEqual([array valueAtIndex:2], FALSE);
+  XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], FALSE);
+  XCTAssertEqual([array valueAtIndex:1], FALSE);
+  XCTAssertEqual([array valueAtIndex:2], TRUE);
+  XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+  GPBBoolArray *array =
+      [[GPBBoolArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:FALSE atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS2(Enum, int32_t, 71, 72, 73, 74, Raw)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Enum
+
+@interface GPBEnumArrayTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayTests
+
+- (void)testEmpty {
+  GPBEnumArray *array = [[GPBEnumArray alloc] init];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    #pragma unused(value, idx, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [array release];
+}
+
+- (void)testOne {
+  GPBEnumArray *array = [GPBEnumArray arrayWithValue:71];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 1U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 71);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, 0U);
+    XCTAssertEqual(value, 71);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  static const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 72);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+  XCTAssertEqual([array valueAtIndex:3], 74);
+  XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const int32_t kValues1[] = { 71, 72, 73 };
+  const int32_t kValues2[] = { 71, 74, 73 };
+  const int32_t kValues3[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array1 =
+      [[GPBEnumArray alloc] initWithValues:kValues1
+                                     count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBEnumArray *array1prime =
+      [[GPBEnumArray alloc] initWithValues:kValues1
+                                     count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBEnumArray *array2 =
+      [[GPBEnumArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBEnumArray *array3 =
+      [[GPBEnumArray alloc] initWithValues:kValues3
+                                     count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBEnumArray *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  [array release];
+}
+
+- (void)testAdds {
+  GPBEnumArray *array = [GPBEnumArray array];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addValue:71];
+  XCTAssertEqual(array.count, 1U);
+
+  const int32_t kValues1[] = { 72, 73 };
+  [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const int32_t kValues2[] = { 74, 71 };
+  GPBEnumArray *array2 =
+      [[GPBEnumArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addRawValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 72);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+  XCTAssertEqual([array valueAtIndex:3], 74);
+  XCTAssertEqual([array valueAtIndex:4], 71);
+  [array2 release];
+}
+
+- (void)testInsert {
+  const int32_t kValues[] = { 71, 72, 73 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertValue:74 atIndex:0];
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertValue:74 atIndex:2];
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertValue:74 atIndex:5];
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertValue:74 atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array valueAtIndex:0], 74);
+  XCTAssertEqual([array valueAtIndex:1], 71);
+  XCTAssertEqual([array valueAtIndex:2], 74);
+  XCTAssertEqual([array valueAtIndex:3], 72);
+  XCTAssertEqual([array valueAtIndex:4], 73);
+  XCTAssertEqual([array valueAtIndex:5], 74);
+  [array release];
+}
+
+- (void)testRemove {
+  const int32_t kValues[] = { 74, 71, 72, 74, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 6U);
+
+  // First
+  [array removeValueAtIndex:0];
+  XCTAssertEqual(array.count, 5U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+
+  // Middle
+  [array removeValueAtIndex:2];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+
+  // End
+  [array removeValueAtIndex:3];
+  XCTAssertEqual(array.count, 3U);
+
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 72);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+                               NSException, NSRangeException);
+
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kValues[] = { 71, 71, 73, 73 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withValue:72];
+  [array replaceValueAtIndex:3 withValue:74];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 72);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+  XCTAssertEqual([array valueAtIndex:3], 74);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:74],
+                               NSException, NSRangeException);
+
+  [array exchangeValueAtIndex:1 withValueAtIndex:3];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 74);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+  XCTAssertEqual([array valueAtIndex:3], 72);
+
+  [array exchangeValueAtIndex:2 withValueAtIndex:0];
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 73);
+  XCTAssertEqual([array valueAtIndex:1], 74);
+  XCTAssertEqual([array valueAtIndex:2], 71);
+  XCTAssertEqual([array valueAtIndex:3], 72);
+
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testInternalResizing {
+  const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertValue:74 atIndex:(i * 3)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+#pragma mark - Non macro-based Enum tests
+
+// These are hand written tests to cover the verification and raw methods.
+
+@interface GPBEnumArrayCustomTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayCustomTests
+
+- (void)testRawBasics {
+  static const int32_t kValues[] = { 71, 272, 73, 374 };
+  static const int32_t kValuesFiltered[] = {
+      71, kGPBUnrecognizedEnumeratorValue, 73, kGPBUnrecognizedEnumeratorValue
+  };
+  XCTAssertEqual(GPBARRAYSIZE(kValues), GPBARRAYSIZE(kValuesFiltered));
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 4U);
+  GPBEnumValidationFunc func = TestingEnum_IsValidValue;
+  XCTAssertEqual(array.validationFunc, func);
+  XCTAssertEqual([array rawValueAtIndex:0], 71);
+  XCTAssertEqual([array rawValueAtIndex:1], 272);
+  XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:2], 73);
+  XCTAssertEqual([array rawValueAtIndex:3], 374);
+  XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertThrowsSpecificNamed([array rawValueAtIndex:4], NSException, NSRangeException);
+  __block NSUInteger idx2 = 0;
+  [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValuesFiltered[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateRawValuesWithOptions:NSEnumerationReverse
+                            usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateValuesWithOptions:NSEnumerationReverse
+                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValuesFiltered[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    ++idx2;
+  }];
+  // Stopping the enumeration.
+  idx2 = 0;
+  [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, idx2);
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    XCTAssertNotEqual(idx, 3U);
+    ++idx2;
+  }];
+  idx2 = 0;
+  [array enumerateRawValuesWithOptions:NSEnumerationReverse
+                            usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+    XCTAssertEqual(idx, (3 - idx2));
+    XCTAssertEqual(value, kValues[idx]);
+    XCTAssertNotEqual(stop, NULL);
+    if (idx2 == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 1U);
+    XCTAssertNotEqual(idx, 0U);
+    ++idx2;
+  }];
+  [array release];
+}
+
+- (void)testEquality {
+  const int32_t kValues1[] = { 71, 72, 173 };  // With unknown value
+  const int32_t kValues2[] = { 71, 74, 173 };  // With unknown value
+  const int32_t kValues3[] = { 71, 72, 173, 74 };  // With unknown value
+  GPBEnumArray *array1 =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1);
+  GPBEnumArray *array1prime =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue2
+                                             rawValues:kValues1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(array1prime);
+  GPBEnumArray *array2 =
+      [[GPBEnumArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  GPBEnumArray *array3 =
+      [[GPBEnumArray alloc] initWithValues:kValues3
+                                     count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(array3);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(array1, array1prime);
+  XCTAssertEqualObjects(array1, array1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([array1 hash], [array1prime hash]);
+  // But different validation functions.
+  XCTAssertNotEqual(array1.validationFunc, array1prime.validationFunc);
+
+  // 1/2/3 shouldn't be equal.
+  XCTAssertNotEqualObjects(array1, array2);
+  XCTAssertNotEqualObjects(array1, array3);
+  XCTAssertNotEqualObjects(array2, array3);
+
+  [array1 release];
+  [array1prime release];
+  [array2 release];
+  [array3 release];
+}
+
+- (void)testCopy {
+  const int32_t kValues[] = { 71, 72 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array addRawValue:1000]; // Unknown
+  XCTAssertEqual(array.count, 3U);
+  XCTAssertEqual([array rawValueAtIndex:0], 71);
+  XCTAssertEqual([array rawValueAtIndex:1], 72);
+  XCTAssertEqual([array rawValueAtIndex:2], 1000);
+  XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+
+  GPBEnumArray *array2 = [array copy];
+  XCTAssertNotNil(array2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  XCTAssertEqual(array.validationFunc, array2.validationFunc);
+  XCTAssertTrue([array2 isKindOfClass:[GPBEnumArray class]]);
+  XCTAssertEqual(array2.count, 3U);
+  XCTAssertEqual([array2 rawValueAtIndex:0], 71);
+  XCTAssertEqual([array2 rawValueAtIndex:1], 72);
+  XCTAssertEqual([array2 rawValueAtIndex:2], 1000);
+  XCTAssertEqual([array2 valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+  [array2 release];
+  [array release];
+}
+
+- (void)testArrayFromArray {
+  const int32_t kValues[] = { 71, 172, 173, 74 };  // Unknowns
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+  XCTAssertNotNil(array2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(array, array2);
+  XCTAssertEqualObjects(array, array2);
+  XCTAssertEqual(array.validationFunc, array2.validationFunc);
+  [array release];
+}
+
+- (void)testUnknownAdds {
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(array);
+
+  XCTAssertThrowsSpecificNamed([array addValue:172],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 0U);
+
+  const int32_t kValues1[] = { 172, 173 };  // Unknown
+  XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+- (void)testRawAdds {
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(array);
+
+  XCTAssertEqual(array.count, 0U);
+  [array addRawValue:71];  // Valid
+  XCTAssertEqual(array.count, 1U);
+
+  const int32_t kValues1[] = { 172, 173 };  // Unknown
+  [array addRawValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertEqual(array.count, 3U);
+
+  const int32_t kValues2[] = { 74, 71 };
+  GPBEnumArray *array2 =
+      [[GPBEnumArray alloc] initWithValues:kValues2
+                                     count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(array2);
+  [array addRawValuesFromArray:array2];
+  XCTAssertEqual(array.count, 5U);
+
+  XCTAssertEqual([array rawValueAtIndex:0], 71);
+  XCTAssertEqual([array rawValueAtIndex:1], 172);
+  XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:2], 173);
+  XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:3], 74);
+  XCTAssertEqual([array rawValueAtIndex:4], 71);
+  [array release];
+}
+
+- (void)testUnknownInserts {
+  const int32_t kValues[] = { 71, 72, 73 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  XCTAssertThrowsSpecificNamed([array insertValue:174 atIndex:0],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 3U);
+
+  // Middle
+  XCTAssertThrowsSpecificNamed([array insertValue:274 atIndex:1],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 3U);
+
+  // End
+  XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 3U);
+  [array release];
+}
+
+- (void)testRawInsert {
+  const int32_t kValues[] = { 71, 72, 73 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+  XCTAssertEqual(array.count, 3U);
+
+  // First
+  [array insertRawValue:174 atIndex:0];  // Unknown
+  XCTAssertEqual(array.count, 4U);
+
+  // Middle
+  [array insertRawValue:274 atIndex:2];  // Unknown
+  XCTAssertEqual(array.count, 5U);
+
+  // End
+  [array insertRawValue:374 atIndex:5];  // Unknown
+  XCTAssertEqual(array.count, 6U);
+
+  // Too far.
+  XCTAssertThrowsSpecificNamed([array insertRawValue:74 atIndex:7],
+                               NSException, NSRangeException);
+
+  XCTAssertEqual([array rawValueAtIndex:0], 174);
+  XCTAssertEqual([array valueAtIndex:0], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:1], 71);
+  XCTAssertEqual([array rawValueAtIndex:2], 274);
+  XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:3], 72);
+  XCTAssertEqual([array rawValueAtIndex:4], 73);
+  XCTAssertEqual([array rawValueAtIndex:5], 374);
+  XCTAssertEqual([array valueAtIndex:5], kGPBUnrecognizedEnumeratorValue);
+  [array release];
+}
+
+- (void)testUnknownInplaceMutation {
+  const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:1 withValue:172],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:3 withValue:274],
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array valueAtIndex:0], 71);
+  XCTAssertEqual([array valueAtIndex:1], 72);
+  XCTAssertEqual([array valueAtIndex:2], 73);
+  XCTAssertEqual([array valueAtIndex:3], 74);
+  [array release];
+}
+
+
+- (void)testRawInplaceMutation {
+  const int32_t kValues[] = { 71, 72, 73, 74 };
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                             rawValues:kValues
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  [array replaceValueAtIndex:1 withRawValue:172];  // Unknown
+  [array replaceValueAtIndex:3 withRawValue:274];  // Unknown
+  XCTAssertEqual(array.count, 4U);
+  XCTAssertEqual([array rawValueAtIndex:0], 71);
+  XCTAssertEqual([array rawValueAtIndex:1], 172);
+  XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([array rawValueAtIndex:2], 73);
+  XCTAssertEqual([array rawValueAtIndex:3], 274);
+  XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74],
+                               NSException, NSRangeException);
+  [array release];
+}
+
+- (void)testRawInternalResizing {
+  const int32_t kValues[] = { 71, 172, 173, 74 };  // Unknown
+  GPBEnumArray *array =
+      [[GPBEnumArray alloc] initWithValues:kValues
+                                     count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(array);
+
+  // Add/remove to trigger the intneral buffer to grow/shrink.
+  for (int i = 0; i < 100; ++i) {
+    [array addRawValues:kValues count:GPBARRAYSIZE(kValues)];
+  }
+  XCTAssertEqual(array.count, 404U);
+  for (int i = 0; i < 100; ++i) {
+    [array removeValueAtIndex:(i * 2)];
+  }
+  XCTAssertEqual(array.count, 304U);
+  for (int i = 0; i < 100; ++i) {
+    [array insertRawValue:274 atIndex:(i * 3)];  // Unknown
+  }
+  XCTAssertEqual(array.count, 404U);
+  [array removeAll];
+  XCTAssertEqual(array.count, 0U);
+  [array release];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBCodedInputStreamTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBCodedInputStreamTests.m
new file mode 100644
index 0000000..cc40215
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -0,0 +1,335 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface CodedInputStreamTests : GPBTestCase
+@end
+
+@implementation CodedInputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+  va_list list;
+  va_start(list, unused);
+
+  NSMutableData* values = [NSMutableData dataWithCapacity:0];
+  int32_t i;
+
+  while ((i = va_arg(list, int32_t)) != 256) {
+    NSAssert(i >= 0 && i < 256, @"");
+    uint8_t u = (uint8_t)i;
+    [values appendBytes:&u length:1];
+  }
+
+  va_end(list);
+
+  return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)testDecodeZigZag {
+  XCTAssertEqual(0, GPBDecodeZigZag32(0));
+  XCTAssertEqual(-1, GPBDecodeZigZag32(1));
+  XCTAssertEqual(1, GPBDecodeZigZag32(2));
+  XCTAssertEqual(-2, GPBDecodeZigZag32(3));
+  XCTAssertEqual((int32_t)0x3FFFFFFF, GPBDecodeZigZag32(0x7FFFFFFE));
+  XCTAssertEqual((int32_t)0xC0000000, GPBDecodeZigZag32(0x7FFFFFFF));
+  XCTAssertEqual((int32_t)0x7FFFFFFF, GPBDecodeZigZag32(0xFFFFFFFE));
+  XCTAssertEqual((int32_t)0x80000000, GPBDecodeZigZag32(0xFFFFFFFF));
+
+  XCTAssertEqual((int64_t)0, GPBDecodeZigZag64(0));
+  XCTAssertEqual((int64_t)-1, GPBDecodeZigZag64(1));
+  XCTAssertEqual((int64_t)1, GPBDecodeZigZag64(2));
+  XCTAssertEqual((int64_t)-2, GPBDecodeZigZag64(3));
+  XCTAssertEqual((int64_t)0x000000003FFFFFFFL,
+                 GPBDecodeZigZag64(0x000000007FFFFFFEL));
+  XCTAssertEqual((int64_t)0xFFFFFFFFC0000000L,
+                 GPBDecodeZigZag64(0x000000007FFFFFFFL));
+  XCTAssertEqual((int64_t)0x000000007FFFFFFFL,
+                 GPBDecodeZigZag64(0x00000000FFFFFFFEL));
+  XCTAssertEqual((int64_t)0xFFFFFFFF80000000L,
+                 GPBDecodeZigZag64(0x00000000FFFFFFFFL));
+  XCTAssertEqual((int64_t)0x7FFFFFFFFFFFFFFFL,
+                 GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+  XCTAssertEqual((int64_t)0x8000000000000000L,
+                 GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+}
+
+- (void)assertReadVarint:(NSData*)data value:(int64_t)value {
+  {
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    XCTAssertEqual((int32_t)value, [input readInt32]);
+  }
+  {
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    XCTAssertEqual(value, [input readInt64]);
+  }
+}
+
+- (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value {
+  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+  XCTAssertEqual(value, [input readSFixed32]);
+}
+
+- (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value {
+  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+  XCTAssertEqual(value, [input readSFixed64]);
+}
+
+- (void)assertReadVarintFailure:(NSData*)data {
+  {
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    XCTAssertThrows([input readInt32]);
+  }
+  {
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    XCTAssertThrows([input readInt64]);
+  }
+}
+
+- (void)testBytes {
+  NSData* data = bytes(0xa2, 0x74);
+  XCTAssertEqual(data.length, (NSUInteger)2);
+  XCTAssertEqual(((uint8_t*)data.bytes)[0], (uint8_t)0xa2);
+  XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74);
+}
+
+- (void)testReadVarint {
+  [self assertReadVarint:bytes(0x00) value:0];
+  [self assertReadVarint:bytes(0x01) value:1];
+  [self assertReadVarint:bytes(0x7f) value:127];
+  // 14882
+  [self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+  // 2961488830
+  [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+                         (0x04 << 21) | (0x0bLL << 28)];
+
+  // 64-bit
+  // 7256456126
+  [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+                         (0x04 << 21) | (0x1bLL << 28)];
+  // 41256202580718336
+  [self assertReadVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+                   value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+                         (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+                         (0x24LL << 42) | (0x49LL << 49)];
+  // 11964378330978735131
+  [self
+      assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+                             0xa6, 0x01)
+                 value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+                       (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) |
+                       (0x05LL << 49) | (0x26LL << 56) | (0x01LL << 63)];
+
+  // Failures
+  [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+                                      0x80, 0x80, 0x80, 0x00)];
+  [self assertReadVarintFailure:bytes(0x80)];
+}
+
+- (void)testReadLittleEndian {
+  [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+                           value:0x12345678];
+  [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+                           value:0x9abcdef0];
+
+  [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34,
+                                       0x12)
+                           value:0x123456789abcdef0LL];
+  [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc,
+                                       0x9a)
+                           value:0x9abcdef012345678LL];
+}
+
+- (void)testReadWholeMessage {
+  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+  NSData* rawBytes = message.data;
+  XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+  TestAllTypes* message2 =
+      [TestAllTypes parseFromData:rawBytes extensionRegistry:nil error:NULL];
+  [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSkipWholeMessage {
+  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes = message.data;
+
+  // Create two parallel inputs.  Parse one as unknown fields while using
+  // skipField() to skip each field on the other.  Expect the same tags.
+  GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
+  GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
+  GPBUnknownFieldSet* unknownFields =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+
+  while (YES) {
+    int32_t tag = [input1 readTag];
+    XCTAssertEqual(tag, [input2 readTag]);
+    if (tag == 0) {
+      break;
+    }
+    [unknownFields mergeFieldFrom:tag input:input1];
+    [input2 skipField:tag];
+  }
+}
+
+- (void)testReadHugeBlob {
+  // Allocate and initialize a 1MB blob.
+  NSMutableData* blob = [NSMutableData dataWithLength:1 << 20];
+  for (NSUInteger i = 0; i < blob.length; i++) {
+    ((uint8_t*)blob.mutableBytes)[i] = (uint8_t)i;
+  }
+
+  // Make a message containing it.
+  TestAllTypes* message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [message setOptionalBytes:blob];
+
+  // Serialize and parse it.  Make sure to parse from an InputStream, not
+  // directly from a ByteString, so that CodedInputStream uses buffered
+  // reading.
+  NSData *messageData = message.data;
+  XCTAssertNotNil(messageData);
+  GPBCodedInputStream* stream =
+      [GPBCodedInputStream streamWithData:messageData];
+  TestAllTypes* message2 = [TestAllTypes parseFromCodedInputStream:stream
+                                                 extensionRegistry:nil
+                                                             error:NULL];
+
+  XCTAssertEqualObjects(message.optionalBytes, message2.optionalBytes);
+
+  // Make sure all the other fields were parsed correctly.
+  TestAllTypes* message3 = [[message2 copy] autorelease];
+  TestAllTypes* types = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* data = [types optionalBytes];
+  [message3 setOptionalBytes:data];
+
+  [self assertAllFieldsSet:message3 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testReadMaliciouslyLargeBlob {
+  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+  GPBCodedOutputStream* output =
+      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+  int32_t tag = GPBWireFormatMakeTag(1, GPBWireFormatLengthDelimited);
+  [output writeRawVarint32:tag];
+  [output writeRawVarint32:0x7FFFFFFF];
+  uint8_t bytes[32] = {0};
+  [output writeRawData:[NSData dataWithBytes:bytes length:32]];
+  [output flush];
+
+  NSData* data =
+      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  GPBCodedInputStream* input =
+      [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
+  XCTAssertEqual(tag, [input readTag]);
+
+  XCTAssertThrows([input readBytes]);
+}
+
+// Verifies fix for b/10315336.
+// Note: Now that there isn't a custom string class under the hood, this test
+// isn't as critical, but it does cover bad input and if a custom class is added
+// again, it will help validate that class' handing of bad utf8.
+- (void)testReadMalformedString {
+  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+  GPBCodedOutputStream* output =
+      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+  int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
+                                     GPBWireFormatLengthDelimited);
+  [output writeRawVarint32:tag];
+  [output writeRawVarint32:5];
+  // Create an invalid utf-8 byte array.
+  uint8_t bytes[] = {0xc2, 0xf2, 0x0, 0x0, 0x0};
+  [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
+  [output flush];
+
+  NSData *data =
+      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+  NSError *error = nil;
+  TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
+                                                extensionRegistry:nil
+                                                            error:&error];
+  XCTAssertNotNil(error);
+  XCTAssertNil(message);
+}
+
+- (void)testBOMWithinStrings {
+  // We've seen servers that end up with BOMs within strings (not always at the
+  // start, and sometimes in multiple places), make sure they always parse
+  // correctly. (Again, this is inpart incase a custom string class is ever
+  // used again.)
+  const char* strs[] = {
+    "\xEF\xBB\xBF String with BOM",
+    "String with \xEF\xBB\xBF in middle",
+    "String with end bom \xEF\xBB\xBF",
+    "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart
+    "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
+  };
+  for (size_t i = 0; i < GPBARRAYSIZE(strs); ++i) {
+    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+    GPBCodedOutputStream* output =
+        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+    int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
+                                       GPBWireFormatLengthDelimited);
+    [output writeRawVarint32:tag];
+    size_t length = strlen(strs[i]);
+    [output writeRawVarint32:(int32_t)length];
+    [output writeRawData:[NSData dataWithBytes:strs[i] length:length]];
+    [output flush];
+
+    NSData* data =
+        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
+                                                  extensionRegistry:nil
+                                                              error:NULL];
+    XCTAssertNotNil(message, @"Loop %zd", i);
+    // Ensure the string is there. NSString can consume the BOM in some
+    // cases, so don't actually check the string for exact equality.
+    XCTAssertTrue(message.defaultString.length > 0, @"Loop %zd", i);
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBCodedOuputStreamTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBCodedOuputStreamTests.m
new file mode 100644
index 0000000..0723b64
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBCodedOuputStreamTests.m
@@ -0,0 +1,340 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedOutputStream_PackagePrivate.h"
+#import "GPBCodedInputStream.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface GPBCodedOutputStream (InternalMethods)
+// Declared in the .m file, expose for testing.
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+                                data:(NSMutableData *)data;
+@end
+
+@interface GPBCodedOutputStream (Helper)
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output
+                            bufferSize:(size_t)bufferSize;
+@end
+
+@implementation GPBCodedOutputStream (Helper)
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output
+                            bufferSize:(size_t)bufferSize {
+  NSMutableData *data = [NSMutableData dataWithLength:bufferSize];
+  return [[[self alloc] initWithOutputStream:output data:data] autorelease];
+}
+@end
+
+@interface CodedOutputStreamTests : GPBTestCase
+@end
+
+@implementation CodedOutputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+  va_list list;
+  va_start(list, unused);
+
+  NSMutableData* values = [NSMutableData dataWithCapacity:0];
+  int32_t i;
+
+  while ((i = va_arg(list, int32_t)) != 256) {
+    NSAssert(i >= 0 && i < 256, @"");
+    uint8_t u = (uint8_t)i;
+    [values appendBytes:&u length:1];
+  }
+
+  va_end(list);
+
+  return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value {
+  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+  GPBCodedOutputStream* output =
+      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  [output writeRawLittleEndian32:(int32_t)value];
+  [output flush];
+
+  NSData* actual =
+      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  XCTAssertEqualObjects(data, actual);
+
+  // Try different block sizes.
+  for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+    rawOutput = [NSOutputStream outputStreamToMemory];
+    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                               bufferSize:blockSize];
+    [output writeRawLittleEndian32:(int32_t)value];
+    [output flush];
+
+    actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    XCTAssertEqualObjects(data, actual);
+  }
+}
+
+- (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value {
+  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+  GPBCodedOutputStream* output =
+      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  [output writeRawLittleEndian64:value];
+  [output flush];
+
+  NSData* actual =
+      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  XCTAssertEqualObjects(data, actual);
+
+  // Try different block sizes.
+  for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+    rawOutput = [NSOutputStream outputStreamToMemory];
+    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                               bufferSize:blockSize];
+    [output writeRawLittleEndian64:value];
+    [output flush];
+
+    actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    XCTAssertEqualObjects(data, actual);
+  }
+}
+
+- (void)assertWriteVarint:(NSData*)data value:(int64_t)value {
+  // Only do 32-bit write if the value fits in 32 bits.
+  if (GPBLogicalRightShift64(value, 32) == 0) {
+    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+    GPBCodedOutputStream* output =
+        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+    [output writeRawVarint32:(int32_t)value];
+    [output flush];
+
+    NSData* actual =
+        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    XCTAssertEqualObjects(data, actual);
+
+    // Also try computing size.
+    XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value),
+                   (size_t)data.length);
+  }
+
+  {
+    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+    GPBCodedOutputStream* output =
+        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+    [output writeRawVarint64:value];
+    [output flush];
+
+    NSData* actual =
+        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    XCTAssertEqualObjects(data, actual);
+
+    // Also try computing size.
+    XCTAssertEqual(GPBComputeRawVarint64Size(value), (size_t)data.length);
+  }
+
+  // Try different block sizes.
+  for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+    // Only do 32-bit write if the value fits in 32 bits.
+    if (GPBLogicalRightShift64(value, 32) == 0) {
+      NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+      GPBCodedOutputStream* output =
+          [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                            bufferSize:blockSize];
+
+      [output writeRawVarint32:(int32_t)value];
+      [output flush];
+
+      NSData* actual =
+          [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+      XCTAssertEqualObjects(data, actual);
+    }
+
+    {
+      NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+      GPBCodedOutputStream* output =
+          [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                            bufferSize:blockSize];
+
+      [output writeRawVarint64:value];
+      [output flush];
+
+      NSData* actual =
+          [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+      XCTAssertEqualObjects(data, actual);
+    }
+  }
+}
+
+- (void)testWriteVarint1 {
+  [self assertWriteVarint:bytes(0x00) value:0];
+}
+
+- (void)testWriteVarint2 {
+  [self assertWriteVarint:bytes(0x01) value:1];
+}
+
+- (void)testWriteVarint3 {
+  [self assertWriteVarint:bytes(0x7f) value:127];
+}
+
+- (void)testWriteVarint4 {
+  // 14882
+  [self assertWriteVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+}
+
+- (void)testWriteVarint5 {
+  // 2961488830
+  [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+                          (0x04 << 21) | (0x0bLL << 28)];
+}
+
+- (void)testWriteVarint6 {
+  // 64-bit
+  // 7256456126
+  [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+                          (0x04 << 21) | (0x1bLL << 28)];
+}
+
+- (void)testWriteVarint7 {
+  // 41256202580718336
+  [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+                    value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+                          (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+                          (0x24LL << 42) | (0x49LL << 49)];
+}
+
+- (void)testWriteVarint8 {
+  // 11964378330978735131
+  [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+                                0xa6, 0x01)
+                    value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) |
+                          (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) |
+                          (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
+                          (0x01LL << 63)];
+}
+
+- (void)testWriteLittleEndian {
+  [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+                            value:0x12345678];
+  [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+                            value:0x9abcdef0];
+
+  [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
+                                        0x34, 0x12)
+                            value:0x123456789abcdef0LL];
+  [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde,
+                                        0xbc, 0x9a)
+                            value:0x9abcdef012345678LL];
+}
+
+- (void)testEncodeZigZag {
+  XCTAssertEqual(0U, GPBEncodeZigZag32(0));
+  XCTAssertEqual(1U, GPBEncodeZigZag32(-1));
+  XCTAssertEqual(2U, GPBEncodeZigZag32(1));
+  XCTAssertEqual(3U, GPBEncodeZigZag32(-2));
+  XCTAssertEqual(0x7FFFFFFEU, GPBEncodeZigZag32(0x3FFFFFFF));
+  XCTAssertEqual(0x7FFFFFFFU, GPBEncodeZigZag32(0xC0000000));
+  XCTAssertEqual(0xFFFFFFFEU, GPBEncodeZigZag32(0x7FFFFFFF));
+  XCTAssertEqual(0xFFFFFFFFU, GPBEncodeZigZag32(0x80000000));
+
+  XCTAssertEqual(0ULL, GPBEncodeZigZag64(0));
+  XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1));
+  XCTAssertEqual(2ULL, GPBEncodeZigZag64(1));
+  XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2));
+  XCTAssertEqual(0x000000007FFFFFFEULL,
+                 GPBEncodeZigZag64(0x000000003FFFFFFFLL));
+  XCTAssertEqual(0x000000007FFFFFFFULL,
+                 GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
+  XCTAssertEqual(0x00000000FFFFFFFEULL,
+                 GPBEncodeZigZag64(0x000000007FFFFFFFLL));
+  XCTAssertEqual(0x00000000FFFFFFFFULL,
+                 GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
+  XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL,
+                 GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
+  XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL,
+                 GPBEncodeZigZag64(0x8000000000000000LL));
+
+  // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
+  // were chosen semi-randomly via keyboard bashing.
+  XCTAssertEqual(0U, GPBEncodeZigZag32(GPBDecodeZigZag32(0)));
+  XCTAssertEqual(1U, GPBEncodeZigZag32(GPBDecodeZigZag32(1)));
+  XCTAssertEqual(-1U, GPBEncodeZigZag32(GPBDecodeZigZag32(-1)));
+  XCTAssertEqual(14927U, GPBEncodeZigZag32(GPBDecodeZigZag32(14927)));
+  XCTAssertEqual(-3612U, GPBEncodeZigZag32(GPBDecodeZigZag32(-3612)));
+
+  XCTAssertEqual(0ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(0)));
+  XCTAssertEqual(1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(1)));
+  XCTAssertEqual(-1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-1)));
+  XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927)));
+  XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612)));
+
+  XCTAssertEqual(856912304801416ULL,
+                 GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
+  XCTAssertEqual(-75123905439571256ULL,
+                 GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
+}
+
+- (void)testWriteWholeMessage {
+  // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+  // that was generated with 2.
+  TestAllTypes* message = [self allSetRepeatedCount:2];
+
+  NSData* rawBytes = message.data;
+  NSData* goldenData =
+      [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
+  XCTAssertEqualObjects(rawBytes, goldenData);
+
+  // Try different block sizes.
+  for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+    GPBCodedOutputStream* output =
+        [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                          bufferSize:blockSize];
+    [message writeToCodedOutputStream:output];
+    [output flush];
+
+    NSData* actual =
+        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    XCTAssertEqualObjects(rawBytes, actual);
+  }
+
+  // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+  // that was generated with 2.
+  TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2];
+  rawBytes = extensions.data;
+  goldenData = [self getDataFileNamed:@"golden_packed_fields_message"
+                          dataToWrite:rawBytes];
+  XCTAssertEqualObjects(rawBytes, goldenData);
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBConcurrencyTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBConcurrencyTests.m
new file mode 100644
index 0000000..daf75e7
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBConcurrencyTests.m
@@ -0,0 +1,206 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#import "GPBTestUtilities.h"
+
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+static const int kNumThreads = 100;
+static const int kNumMessages = 100;
+
+// NOTE: Most of these tests don't "fail" in the sense that the XCTAsserts
+// trip.  Rather, the asserts simply exercise the apis, and if there is
+// a concurancy issue, the NSAsserts in the runtime code fire and/or the
+// code just crashes outright.
+
+@interface ConcurrencyTests : GPBTestCase
+@end
+
+@implementation ConcurrencyTests
+
+- (NSArray *)createThreadsWithSelector:(SEL)selector object:(id)object {
+  NSMutableArray *array = [NSMutableArray array];
+  for (NSUInteger i = 0; i < kNumThreads; i++) {
+    NSThread *thread =
+        [[NSThread alloc] initWithTarget:self selector:selector object:object];
+    [array addObject:thread];
+    [thread release];
+  }
+  return array;
+}
+
+- (NSArray *)createMessagesWithType:(Class)msgType {
+  NSMutableArray *array = [NSMutableArray array];
+  for (NSUInteger i = 0; i < kNumMessages; i++) {
+    [array addObject:[msgType message]];
+  }
+  return array;
+}
+
+- (void)startThreads:(NSArray *)threads {
+  for (NSThread *thread in threads) {
+    [thread start];
+  }
+}
+
+- (void)joinThreads:(NSArray *)threads {
+  for (NSThread *thread in threads) {
+    while (![thread isFinished])
+      ;
+  }
+}
+
+- (void)readForeignMessage:(NSArray *)messages {
+  for (NSUInteger i = 0; i < 10; i++) {
+    for (TestAllTypes *message in messages) {
+      XCTAssertEqual(message.optionalForeignMessage.c, 0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetMessageField {
+  NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+  NSArray *threads =
+      [self createThreadsWithSelector:@selector(readForeignMessage:)
+                               object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  for (TestAllTypes *message in messages) {
+    XCTAssertFalse(message.hasOptionalForeignMessage);
+  }
+}
+
+- (void)readRepeatedInt32:(NSArray *)messages {
+  for (int i = 0; i < 10; i++) {
+    for (TestAllTypes *message in messages) {
+      XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedIntField {
+  NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+  NSArray *threads =
+      [self createThreadsWithSelector:@selector(readRepeatedInt32:)
+                               object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  for (TestAllTypes *message in messages) {
+    XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+  }
+}
+
+- (void)readRepeatedString:(NSArray *)messages {
+  for (int i = 0; i < 10; i++) {
+    for (TestAllTypes *message in messages) {
+      XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedStringField {
+  NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+  NSArray *threads =
+      [self createThreadsWithSelector:@selector(readRepeatedString:)
+                               object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  for (TestAllTypes *message in messages) {
+    XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+  }
+}
+
+- (void)readInt32Int32Map:(NSArray *)messages {
+  for (int i = 0; i < 10; i++) {
+    for (TestRecursiveMessageWithRepeatedField *message in messages) {
+      XCTAssertEqual([message.iToI count], (NSUInteger)0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetInt32Int32MapField {
+  NSArray *messages =
+      [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
+  NSArray *threads =
+      [self createThreadsWithSelector:@selector(readInt32Int32Map:)
+                               object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  for (TestRecursiveMessageWithRepeatedField *message in messages) {
+    XCTAssertEqual([message.iToI count], (NSUInteger)0);
+  }
+}
+
+- (void)readStringStringMap:(NSArray *)messages {
+  for (int i = 0; i < 10; i++) {
+    for (TestRecursiveMessageWithRepeatedField *message in messages) {
+      XCTAssertEqual([message.strToStr count], (NSUInteger)0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetStringStringMapField {
+  NSArray *messages =
+      [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
+  NSArray *threads =
+      [self createThreadsWithSelector:@selector(readStringStringMap:)
+                               object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  for (TestRecursiveMessageWithRepeatedField *message in messages) {
+    XCTAssertEqual([message.strToStr count], (NSUInteger)0);
+  }
+}
+
+- (void)readOptionalForeignMessageExtension:(NSArray *)messages {
+  for (int i = 0; i < 10; i++) {
+    for (TestAllExtensions *message in messages) {
+      ForeignMessage *foreign =
+          [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+      XCTAssertEqual(foreign.c, 0);
+    }
+  }
+}
+
+- (void)testConcurrentReadOfUnsetExtensionField {
+  NSArray *messages = [self createMessagesWithType:[TestAllExtensions class]];
+  SEL sel = @selector(readOptionalForeignMessageExtension:);
+  NSArray *threads = [self createThreadsWithSelector:sel object:messages];
+  [self startThreads:threads];
+  [self joinThreads:threads];
+  GPBExtensionDescriptor *extension =
+      [UnittestRoot optionalForeignMessageExtension];
+  for (TestAllExtensions *message in messages) {
+    XCTAssertFalse([message hasExtension:extension]);
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDescriptorTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDescriptorTests.m
new file mode 100644
index 0000000..a1923c9
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDescriptorTests.m
@@ -0,0 +1,219 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBDescriptor.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface DescriptorTests : GPBTestCase
+@end
+
+@implementation DescriptorTests
+
+- (void)testFieldDescriptor {
+  GPBDescriptor *descriptor = [TestAllTypes descriptor];
+
+  // Nested Enum
+  GPBFieldDescriptor *fieldDescriptorWithName =
+      [descriptor fieldWithName:@"optionalNestedEnum"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  GPBFieldDescriptor *fieldDescriptorWithNumber =
+      [descriptor fieldWithNumber:21];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+                        @"TestAllTypes_NestedEnum");
+
+  // Foreign Enum
+  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  fieldDescriptorWithNumber = [descriptor fieldWithNumber:22];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+                        @"ForeignEnum");
+
+  // Import Enum
+  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  fieldDescriptorWithNumber = [descriptor fieldWithNumber:23];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+                        @"ImportEnum");
+
+  // Nested Message
+  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  fieldDescriptorWithNumber = [descriptor fieldWithNumber:18];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+  // Foreign Message
+  fieldDescriptorWithName =
+      [descriptor fieldWithName:@"optionalForeignMessage"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+  // Import Message
+  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"];
+  XCTAssertNotNil(fieldDescriptorWithName);
+  fieldDescriptorWithNumber = [descriptor fieldWithNumber:20];
+  XCTAssertNotNil(fieldDescriptorWithNumber);
+  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+}
+
+- (void)testEnumDescriptor {
+  GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
+
+  NSString *enumName = [descriptor enumNameForValue:1];
+  XCTAssertNotNil(enumName);
+  int32_t value;
+  XCTAssertTrue(
+      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+  XCTAssertTrue(
+      [descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+  XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
+
+  enumName = [descriptor enumNameForValue:2];
+  XCTAssertNotNil(enumName);
+  XCTAssertTrue(
+      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
+  XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
+
+  enumName = [descriptor enumNameForValue:3];
+  XCTAssertNotNil(enumName);
+  XCTAssertTrue(
+      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
+  XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
+
+  // Bad values
+  enumName = [descriptor enumNameForValue:0];
+  XCTAssertNil(enumName);
+  XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
+  XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
+  XCTAssertFalse([descriptor getValue:&value
+                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+  XCTAssertFalse([descriptor getValue:NULL
+                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+}
+
+- (void)testEnumValueValidator {
+  GPBDescriptor *descriptor = [TestAllTypes descriptor];
+  GPBFieldDescriptor *fieldDescriptor =
+      [descriptor fieldWithName:@"optionalNestedEnum"];
+
+  // Valid values
+  XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
+  XCTAssertTrue([fieldDescriptor isValidEnumValue:2]);
+  XCTAssertTrue([fieldDescriptor isValidEnumValue:3]);
+  XCTAssertTrue([fieldDescriptor isValidEnumValue:-1]);
+
+  // Invalid values
+  XCTAssertFalse([fieldDescriptor isValidEnumValue:4]);
+  XCTAssertFalse([fieldDescriptor isValidEnumValue:0]);
+  XCTAssertFalse([fieldDescriptor isValidEnumValue:-2]);
+}
+
+- (void)testOneofDescriptor {
+  GPBDescriptor *descriptor = [TestOneof2 descriptor];
+
+  // All fields should be listed.
+  XCTAssertEqual(descriptor.fields.count, 17U);
+
+  // There are two oneofs in there.
+  XCTAssertEqual(descriptor.oneofs.count, 2U);
+
+  GPBFieldDescriptor *fooStringField =
+      [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
+  XCTAssertNotNil(fooStringField);
+  GPBFieldDescriptor *barStringField =
+      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
+  XCTAssertNotNil(barStringField);
+
+  // Check the oneofs to have what is expected.
+
+  GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
+  XCTAssertNotNil(oneofFoo);
+  XCTAssertEqual(oneofFoo.fields.count, 9U);
+
+  // Pointer comparisons.
+  XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
+                 fooStringField);
+  XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
+
+  GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
+  XCTAssertNotNil(oneofBar);
+  XCTAssertEqual(oneofBar.fields.count, 6U);
+
+  // Pointer comparisons.
+  XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
+                 barStringField);
+  XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
+
+  // Unknown oneof not found.
+
+  XCTAssertNil([descriptor oneofWithName:@"mumble"]);
+  XCTAssertNil([descriptor oneofWithName:@"Foo"]);
+
+  // Unknown oneof item.
+
+  XCTAssertNil([oneofFoo fieldWithName:@"mumble"]);
+  XCTAssertNil([oneofFoo fieldWithNumber:666]);
+
+  // Field exists, but not in this oneof.
+
+  XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
+  XCTAssertNil([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_BarString]);
+  XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
+  XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]);
+
+  // Check pointers back to the enclosing oneofs.
+  // (pointer comparisions)
+  XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
+  XCTAssertEqual(barStringField.containingOneof, oneofBar);
+  GPBFieldDescriptor *bazString =
+      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
+  XCTAssertNotNil(bazString);
+  XCTAssertNil(bazString.containingOneof);
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Bool.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Bool.m
new file mode 100644
index 0000000..afa3d11
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Bool.m
@@ -0,0 +1,2418 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt32, uint32_t, 100U, 101U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt32
+
+@interface GPBBoolUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBBoolUInt32Dictionary *dict = [[GPBBoolUInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionaryWithValue:100U forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const uint32_t kValues[] = { 100U, 101U };
+  GPBBoolUInt32Dictionary *dict =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  uint32_t *seenValues = malloc(2 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const uint32_t kValues1[] = { 100U, 101U };
+  const uint32_t kValues2[] = { 101U, 100U };
+  const uint32_t kValues3[] = { 101U };
+  GPBBoolUInt32Dictionary *dict1 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolUInt32Dictionary *dict1prime =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolUInt32Dictionary *dict2 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolUInt32Dictionary *dict3 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolUInt32Dictionary *dict4 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const uint32_t kValues[] = { 100U, 101U };
+  GPBBoolUInt32Dictionary *dict =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolUInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const uint32_t kValues[] = { 100U, 101U };
+  GPBBoolUInt32Dictionary *dict =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolUInt32Dictionary *dict2 =
+      [GPBBoolUInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const uint32_t kValues[] = { 101U };
+  GPBBoolUInt32Dictionary *dict2 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 101U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const uint32_t kValues[] = { 100U, 101U };
+  GPBBoolUInt32Dictionary *dict =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const uint32_t kValues[] = { 100U, 101U };
+  GPBBoolUInt32Dictionary *dict =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict setValue:101U forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict setValue:100U forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 100U);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const uint32_t kValues2[] = { 101U, 100U };
+  GPBBoolUInt32Dictionary *dict2 =
+      [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int32, int32_t, 200, 201)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int32
+
+@interface GPBBoolInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBBoolInt32Dictionary *dict = [[GPBBoolInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionaryWithValue:200 forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const int32_t kValues[] = { 200, 201 };
+  GPBBoolInt32Dictionary *dict =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 201);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  int32_t *seenValues = malloc(2 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const int32_t kValues1[] = { 200, 201 };
+  const int32_t kValues2[] = { 201, 200 };
+  const int32_t kValues3[] = { 201 };
+  GPBBoolInt32Dictionary *dict1 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolInt32Dictionary *dict1prime =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolInt32Dictionary *dict2 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolInt32Dictionary *dict3 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolInt32Dictionary *dict4 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const int32_t kValues[] = { 200, 201 };
+  GPBBoolInt32Dictionary *dict =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const int32_t kValues[] = { 200, 201 };
+  GPBBoolInt32Dictionary *dict =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolInt32Dictionary *dict2 =
+      [GPBBoolInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const int32_t kValues[] = { 201 };
+  GPBBoolInt32Dictionary *dict2 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 201);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const int32_t kValues[] = { 200, 201 };
+  GPBBoolInt32Dictionary *dict =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const int32_t kValues[] = { 200, 201 };
+  GPBBoolInt32Dictionary *dict =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict setValue:201 forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict setValue:200 forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 200);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const int32_t kValues2[] = { 201, 200 };
+  GPBBoolInt32Dictionary *dict2 =
+      [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt64, uint64_t, 300U, 301U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt64
+
+@interface GPBBoolUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBBoolUInt64Dictionary *dict = [[GPBBoolUInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionaryWithValue:300U forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const uint64_t kValues[] = { 300U, 301U };
+  GPBBoolUInt64Dictionary *dict =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  uint64_t *seenValues = malloc(2 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const uint64_t kValues1[] = { 300U, 301U };
+  const uint64_t kValues2[] = { 301U, 300U };
+  const uint64_t kValues3[] = { 301U };
+  GPBBoolUInt64Dictionary *dict1 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolUInt64Dictionary *dict1prime =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolUInt64Dictionary *dict2 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolUInt64Dictionary *dict3 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolUInt64Dictionary *dict4 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const uint64_t kValues[] = { 300U, 301U };
+  GPBBoolUInt64Dictionary *dict =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolUInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const uint64_t kValues[] = { 300U, 301U };
+  GPBBoolUInt64Dictionary *dict =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolUInt64Dictionary *dict2 =
+      [GPBBoolUInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const uint64_t kValues[] = { 301U };
+  GPBBoolUInt64Dictionary *dict2 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 301U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const uint64_t kValues[] = { 300U, 301U };
+  GPBBoolUInt64Dictionary *dict =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const uint64_t kValues[] = { 300U, 301U };
+  GPBBoolUInt64Dictionary *dict =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict setValue:301U forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict setValue:300U forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 300U);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const uint64_t kValues2[] = { 301U, 300U };
+  GPBBoolUInt64Dictionary *dict2 =
+      [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int64, int64_t, 400, 401)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int64
+
+@interface GPBBoolInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBBoolInt64Dictionary *dict = [[GPBBoolInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionaryWithValue:400 forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const int64_t kValues[] = { 400, 401 };
+  GPBBoolInt64Dictionary *dict =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 401);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  int64_t *seenValues = malloc(2 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const int64_t kValues1[] = { 400, 401 };
+  const int64_t kValues2[] = { 401, 400 };
+  const int64_t kValues3[] = { 401 };
+  GPBBoolInt64Dictionary *dict1 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolInt64Dictionary *dict1prime =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolInt64Dictionary *dict2 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolInt64Dictionary *dict3 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolInt64Dictionary *dict4 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const int64_t kValues[] = { 400, 401 };
+  GPBBoolInt64Dictionary *dict =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const int64_t kValues[] = { 400, 401 };
+  GPBBoolInt64Dictionary *dict =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolInt64Dictionary *dict2 =
+      [GPBBoolInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const int64_t kValues[] = { 401 };
+  GPBBoolInt64Dictionary *dict2 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 401);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const int64_t kValues[] = { 400, 401 };
+  GPBBoolInt64Dictionary *dict =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const int64_t kValues[] = { 400, 401 };
+  GPBBoolInt64Dictionary *dict =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict setValue:401 forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict setValue:400 forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 400);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const int64_t kValues2[] = { 401, 400 };
+  GPBBoolInt64Dictionary *dict2 =
+      [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Bool, BOOL, NO, YES)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Bool
+
+@interface GPBBoolBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolBoolDictionaryTests
+
+- (void)testEmpty {
+  GPBBoolBoolDictionary *dict = [[GPBBoolBoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionaryWithValue:NO forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, NO);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const BOOL kValues[] = { NO, YES };
+  GPBBoolBoolDictionary *dict =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                            forKeys:kKeys
+                                              count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, YES);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  BOOL *seenValues = malloc(2 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const BOOL kValues1[] = { NO, YES };
+  const BOOL kValues2[] = { YES, NO };
+  const BOOL kValues3[] = { YES };
+  GPBBoolBoolDictionary *dict1 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+                                            forKeys:kKeys1
+                                              count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolBoolDictionary *dict1prime =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+                                            forKeys:kKeys1
+                                              count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolBoolDictionary *dict2 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+                                            forKeys:kKeys1
+                                              count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolBoolDictionary *dict3 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+                                            forKeys:kKeys2
+                                              count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolBoolDictionary *dict4 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues3
+                                            forKeys:kKeys1
+                                              count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const BOOL kValues[] = { NO, YES };
+  GPBBoolBoolDictionary *dict =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                            forKeys:kKeys
+                                              count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolBoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolBoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const BOOL kValues[] = { NO, YES };
+  GPBBoolBoolDictionary *dict =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                            forKeys:kKeys
+                                              count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolBoolDictionary *dict2 =
+      [GPBBoolBoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:NO forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const BOOL kValues[] = { YES };
+  GPBBoolBoolDictionary *dict2 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                            forKeys:kKeys
+                                              count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, YES);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const BOOL kValues[] = { NO, YES };
+  GPBBoolBoolDictionary *dict =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                     forKeys:kKeys
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const BOOL kValues[] = { NO, YES };
+  GPBBoolBoolDictionary *dict =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+                                     forKeys:kKeys
+                                       count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict setValue:YES forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict setValue:NO forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, NO);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const BOOL kValues2[] = { YES, NO };
+  GPBBoolBoolDictionary *dict2 =
+      [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+                                            forKeys:kKeys2
+                                              count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Float, float, 500.f, 501.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Float
+
+@interface GPBBoolFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolFloatDictionaryTests
+
+- (void)testEmpty {
+  GPBBoolFloatDictionary *dict = [[GPBBoolFloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionaryWithValue:500.f forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const float kValues[] = { 500.f, 501.f };
+  GPBBoolFloatDictionary *dict =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  float value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  float *seenValues = malloc(2 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const float kValues1[] = { 500.f, 501.f };
+  const float kValues2[] = { 501.f, 500.f };
+  const float kValues3[] = { 501.f };
+  GPBBoolFloatDictionary *dict1 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolFloatDictionary *dict1prime =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolFloatDictionary *dict2 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolFloatDictionary *dict3 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolFloatDictionary *dict4 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const float kValues[] = { 500.f, 501.f };
+  GPBBoolFloatDictionary *dict =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolFloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolFloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const float kValues[] = { 500.f, 501.f };
+  GPBBoolFloatDictionary *dict =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolFloatDictionary *dict2 =
+      [GPBBoolFloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const float kValues[] = { 501.f };
+  GPBBoolFloatDictionary *dict2 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 501.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const float kValues[] = { 500.f, 501.f };
+  GPBBoolFloatDictionary *dict =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const float kValues[] = { 500.f, 501.f };
+  GPBBoolFloatDictionary *dict =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  float value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict setValue:501.f forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict setValue:500.f forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 500.f);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const float kValues2[] = { 501.f, 500.f };
+  GPBBoolFloatDictionary *dict2 =
+      [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Double, double, 600., 601.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Double
+
+@interface GPBBoolDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolDoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBBoolDoubleDictionary *dict = [[GPBBoolDoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionaryWithValue:600. forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const double kValues[] = { 600., 601. };
+  GPBBoolDoubleDictionary *dict =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  double value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  double *seenValues = malloc(2 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const double kValues1[] = { 600., 601. };
+  const double kValues2[] = { 601., 600. };
+  const double kValues3[] = { 601. };
+  GPBBoolDoubleDictionary *dict1 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolDoubleDictionary *dict1prime =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolDoubleDictionary *dict2 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolDoubleDictionary *dict3 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolDoubleDictionary *dict4 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const double kValues[] = { 600., 601. };
+  GPBBoolDoubleDictionary *dict =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolDoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolDoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const double kValues[] = { 600., 601. };
+  GPBBoolDoubleDictionary *dict =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolDoubleDictionary *dict2 =
+      [GPBBoolDoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const double kValues[] = { 601. };
+  GPBBoolDoubleDictionary *dict2 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 601.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const double kValues[] = { 600., 601. };
+  GPBBoolDoubleDictionary *dict =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:YES value:NULL]);
+  XCTAssertFalse([dict valueForKey:NO value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const double kValues[] = { 600., 601. };
+  GPBBoolDoubleDictionary *dict =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  double value;
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict setValue:601. forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict setValue:600. forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 600.);
+
+  const BOOL kKeys2[] = { NO, YES };
+  const double kValues2[] = { 601., 600. };
+  GPBBoolDoubleDictionary *dict2 =
+      [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:YES value:NULL]);
+  XCTAssertTrue([dict valueForKey:YES value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:NO value:NULL]);
+  XCTAssertTrue([dict valueForKey:NO value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, NSString*, @"abc", @"def")
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Object
+
+@interface GPBBoolObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolObjectDictionaryTests
+
+- (void)testEmpty {
+  GPBBoolObjectDictionary<NSString*> *dict = [[GPBBoolObjectDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:YES]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBBoolObjectDictionary<NSString*> *dict = [GPBBoolObjectDictionary dictionaryWithObject:@"abc" forKey:YES];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertNil([dict objectForKey:NO]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertEqual(aKey, YES);
+    XCTAssertEqualObjects(aObject, @"abc");
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const BOOL kKeys[] = { YES, NO };
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"def");
+
+  __block NSUInteger idx = 0;
+  BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+  NSString* *seenObjects = malloc(2 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertLessThan(idx, 2U);
+    seenKeys[idx] = aKey;
+    seenObjects[idx] = aObject;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 2; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 2) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenObjects);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject)
+    if (idx == 0) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const BOOL kKeys1[] = { YES, NO };
+  const BOOL kKeys2[] = { NO, YES };
+  const NSString* kObjects1[] = { @"abc", @"def" };
+  const NSString* kObjects2[] = { @"def", @"abc" };
+  const NSString* kObjects3[] = { @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict1 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1);
+  GPBBoolObjectDictionary<NSString*> *dict1prime =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1prime);
+  GPBBoolObjectDictionary<NSString*> *dict2 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  GPBBoolObjectDictionary<NSString*> *dict3 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict3);
+  GPBBoolObjectDictionary<NSString*> *dict4 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kObjects3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 Fewer pairs; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const BOOL kKeys[] = { YES, NO };
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolObjectDictionary<NSString*> *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBBoolObjectDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const BOOL kKeys[] = { YES, NO };
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBBoolObjectDictionary<NSString*> *dict2 =
+      [GPBBoolObjectDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBBoolObjectDictionary<NSString*> *dict = [GPBBoolObjectDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setObject:@"abc" forKey:YES];
+  XCTAssertEqual(dict.count, 1U);
+
+  const BOOL kKeys[] = { NO };
+  const NSString* kObjects[] = { @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict2 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"def");
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const BOOL kKeys[] = { YES, NO};
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+
+  [dict removeObjectForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertNil([dict objectForKey:NO]);
+
+  // Remove again does nothing.
+  [dict removeObjectForKey:NO];
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertNil([dict objectForKey:NO]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:YES]);
+  XCTAssertNil([dict objectForKey:NO]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const BOOL kKeys[] = { YES, NO };
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"def");
+
+  [dict setObject:@"def" forKey:YES];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"def");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"def");
+
+  [dict setObject:@"abc" forKey:NO];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"def");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"abc");
+
+  const BOOL kKeys2[] = { NO, YES };
+  const NSString* kObjects2[] = { @"def", @"abc" };
+  GPBBoolObjectDictionary<NSString*> *dict2 =
+      [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:NO], @"def");
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int32.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int32.m
new file mode 100644
index 0000000..54dd2ed
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int32.m
@@ -0,0 +1,3647 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+// This block of code is generated, do not edit it directly.
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 700:
+    case 701:
+    case 702:
+    case 703:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key {
+  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+  // type correct.
+  return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                  rawValues:&value
+                                                                    forKeys:&key
+                                                                      count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int32_t [])keys
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                  forKeys:keys
+                                    count:count];
+}
+@end
+
+
+#pragma mark - Int32 -> UInt32
+
+@interface GPBInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBInt32UInt32Dictionary *dict = [[GPBInt32UInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionaryWithValue:100U forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const uint32_t kValues[] = { 100U, 101U, 102U };
+  GPBInt32UInt32Dictionary *dict =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const uint32_t kValues1[] = { 100U, 101U, 102U };
+  const uint32_t kValues2[] = { 100U, 103U, 102U };
+  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict1 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32UInt32Dictionary *dict1prime =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32UInt32Dictionary *dict2 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32UInt32Dictionary *dict3 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32UInt32Dictionary *dict4 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32UInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32UInt32Dictionary *dict2 =
+      [GPBInt32UInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const uint32_t kValues[] = { 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict2 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 103U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt32UInt32Dictionary *dict =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:103U forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:101U forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const uint32_t kValues2[] = { 102U, 100U };
+  GPBInt32UInt32Dictionary *dict2 =
+      [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@interface GPBInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int32DictionaryTests
+
+- (void)testEmpty {
+  GPBInt32Int32Dictionary *dict = [[GPBInt32Int32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionaryWithValue:200 forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const int32_t kValues[] = { 200, 201, 202 };
+  GPBInt32Int32Dictionary *dict =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const int32_t kValues1[] = { 200, 201, 202 };
+  const int32_t kValues2[] = { 200, 203, 202 };
+  const int32_t kValues3[] = { 200, 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict1 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32Int32Dictionary *dict1prime =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32Int32Dictionary *dict2 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32Int32Dictionary *dict3 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32Int32Dictionary *dict4 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32Int32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32Int32Dictionary *dict2 =
+      [GPBInt32Int32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const int32_t kValues[] = { 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict2 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 203);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 203);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt32Int32Dictionary *dict =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:203 forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:201 forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 201);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const int32_t kValues2[] = { 202, 200 };
+  GPBInt32Int32Dictionary *dict2 =
+      [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@interface GPBInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBInt32UInt64Dictionary *dict = [[GPBInt32UInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionaryWithValue:300U forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const uint64_t kValues[] = { 300U, 301U, 302U };
+  GPBInt32UInt64Dictionary *dict =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const uint64_t kValues1[] = { 300U, 301U, 302U };
+  const uint64_t kValues2[] = { 300U, 303U, 302U };
+  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict1 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32UInt64Dictionary *dict1prime =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32UInt64Dictionary *dict2 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32UInt64Dictionary *dict3 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32UInt64Dictionary *dict4 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32UInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32UInt64Dictionary *dict2 =
+      [GPBInt32UInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const uint64_t kValues[] = { 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict2 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 303U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt32UInt64Dictionary *dict =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:303U forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:301U forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const uint64_t kValues2[] = { 302U, 300U };
+  GPBInt32UInt64Dictionary *dict2 =
+      [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@interface GPBInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int64DictionaryTests
+
+- (void)testEmpty {
+  GPBInt32Int64Dictionary *dict = [[GPBInt32Int64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionaryWithValue:400 forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const int64_t kValues[] = { 400, 401, 402 };
+  GPBInt32Int64Dictionary *dict =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  int64_t *seenValues = malloc(3 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const int64_t kValues1[] = { 400, 401, 402 };
+  const int64_t kValues2[] = { 400, 403, 402 };
+  const int64_t kValues3[] = { 400, 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict1 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32Int64Dictionary *dict1prime =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32Int64Dictionary *dict2 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32Int64Dictionary *dict3 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32Int64Dictionary *dict4 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32Int64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32Int64Dictionary *dict2 =
+      [GPBInt32Int64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const int64_t kValues[] = { 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict2 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 403);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 403);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt32Int64Dictionary *dict =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:403 forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:401 forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 401);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const int64_t kValues2[] = { 402, 400 };
+  GPBInt32Int64Dictionary *dict2 =
+      [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@interface GPBInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32BoolDictionaryTests
+
+- (void)testEmpty {
+  GPBInt32BoolDictionary *dict = [[GPBInt32BoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionaryWithValue:YES forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, YES);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const BOOL kValues[] = { YES, YES, NO };
+  GPBInt32BoolDictionary *dict =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  BOOL *seenValues = malloc(3 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const BOOL kValues1[] = { YES, YES, NO };
+  const BOOL kValues2[] = { YES, NO, NO };
+  const BOOL kValues3[] = { YES, YES, NO, NO };
+  GPBInt32BoolDictionary *dict1 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32BoolDictionary *dict1prime =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32BoolDictionary *dict2 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32BoolDictionary *dict3 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32BoolDictionary *dict4 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt32BoolDictionary *dict =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32BoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32BoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt32BoolDictionary *dict =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32BoolDictionary *dict2 =
+      [GPBInt32BoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:YES forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const BOOL kValues[] = { YES, NO, NO };
+  GPBInt32BoolDictionary *dict2 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, NO);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt32BoolDictionary *dict =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, NO);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt32BoolDictionary *dict =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:NO forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:YES forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, YES);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const BOOL kValues2[] = { NO, YES };
+  GPBInt32BoolDictionary *dict2 =
+      [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@interface GPBInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32FloatDictionaryTests
+
+- (void)testEmpty {
+  GPBInt32FloatDictionary *dict = [[GPBInt32FloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionaryWithValue:500.f forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const float kValues[] = { 500.f, 501.f, 502.f };
+  GPBInt32FloatDictionary *dict =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  float *seenValues = malloc(3 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const float kValues1[] = { 500.f, 501.f, 502.f };
+  const float kValues2[] = { 500.f, 503.f, 502.f };
+  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict1 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32FloatDictionary *dict1prime =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32FloatDictionary *dict2 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32FloatDictionary *dict3 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32FloatDictionary *dict4 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32FloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32FloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32FloatDictionary *dict2 =
+      [GPBInt32FloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const float kValues[] = { 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict2 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 503.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt32FloatDictionary *dict =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  float value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:503.f forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:501.f forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const float kValues2[] = { 502.f, 500.f };
+  GPBInt32FloatDictionary *dict2 =
+      [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@interface GPBInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBInt32DoubleDictionary *dict = [[GPBInt32DoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionaryWithValue:600. forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const double kValues[] = { 600., 601., 602. };
+  GPBInt32DoubleDictionary *dict =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  double *seenValues = malloc(3 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const double kValues1[] = { 600., 601., 602. };
+  const double kValues2[] = { 600., 603., 602. };
+  const double kValues3[] = { 600., 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict1 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32DoubleDictionary *dict1prime =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32DoubleDictionary *dict2 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32DoubleDictionary *dict3 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32DoubleDictionary *dict4 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32DoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32DoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32DoubleDictionary *dict2 =
+      [GPBInt32DoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const double kValues[] = { 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict2 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 603.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt32DoubleDictionary *dict =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  double value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:603. forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:601. forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const double kValues2[] = { 602., 600. };
+  GPBInt32DoubleDictionary *dict2 =
+      [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@interface GPBInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryTests
+
+- (void)testEmpty {
+  GPBInt32EnumDictionary *dict = [[GPBInt32EnumDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionaryWithValue:700 forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqual(aValue, 700);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const int32_t kValues[] = { 700, 701, 702 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const int32_t kValues1[] = { 700, 701, 702 };
+  const int32_t kValues2[] = { 700, 703, 702 };
+  const int32_t kValues3[] = { 700, 701, 702, 703 };
+  GPBInt32EnumDictionary *dict1 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32EnumDictionary *dict1prime =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32EnumDictionary *dict3 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32EnumDictionary *dict4 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32EnumDictionary *dict2 =
+      [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:700 forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const int32_t kValues[] = { 701, 702, 703 };
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 703);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 703);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:703 forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:701 forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 701);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const int32_t kValues2[] = { 702, 700 };
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 701);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum (Unknown Enums)
+
+@interface GPBInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const int32_t kValues[] = { 700, 801, 702 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:14 rawValue:NULL]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        if (i == 1) {
+          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+        } else {
+          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+        }
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
+  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
+  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt32EnumDictionary *dict1 =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32EnumDictionary *dict1prime =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues2
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32EnumDictionary *dict3 =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys2
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32EnumDictionary *dict4 =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues3
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertEqualObjects(dict, dict2);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32EnumDictionary *dict2 =
+      [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  [dict release];
+}
+
+- (void)testUnknownAdds {
+  GPBInt32EnumDictionary *dict =
+    [GPBInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:12],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 0U);
+  [dict setRawValue:801 forKey:12];  // Unknown
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 11, 13, 14 };
+  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  [dict2 release];
+}
+
+- (void)testUnknownRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict removeValueForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:11 value:NULL]);
+  XCTAssertFalse([dict valueForKey:12 value:NULL]);
+  XCTAssertFalse([dict valueForKey:13 value:NULL]);
+  XCTAssertFalse([dict valueForKey:14 value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:11],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 value:NULL]);
+  XCTAssertTrue([dict valueForKey:11 value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:803 forKey:11];  // Unknown
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:700 forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:13 value:NULL]);
+  XCTAssertTrue([dict valueForKey:13 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 700);
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const int32_t kValues2[] = { 702, 801 };  // Unknown
+  GPBInt32EnumDictionary *dict2 =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues2
+                                                         forKeys:kKeys2
+                                                           count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:12 value:NULL]);
+  XCTAssertTrue([dict valueForKey:12 value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:14 value:NULL]);
+  XCTAssertTrue([dict valueForKey:14 value:&value]);
+  XCTAssertEqual(value, 700);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testCopyUnknowns {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const int32_t kValues[] = { 700, 801, 702, 803 };
+  GPBInt32EnumDictionary *dict =
+      [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@interface GPBInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+  GPBInt32ObjectDictionary<NSString*> *dict = [[GPBInt32ObjectDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:11]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt32ObjectDictionary<NSString*> *dict = [GPBInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:11];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertNil([dict objectForKey:12]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertEqual(aKey, 11);
+    XCTAssertEqualObjects(aObject, @"abc");
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int32_t kKeys[] = { 11, 12, 13 };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:12], @"def");
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertNil([dict objectForKey:14]);
+
+  __block NSUInteger idx = 0;
+  int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenObjects[idx] = aObject;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenObjects);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int32_t kKeys1[] = { 11, 12, 13, 14 };
+  const int32_t kKeys2[] = { 12, 11, 14 };
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict1 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1);
+  GPBInt32ObjectDictionary<NSString*> *dict1prime =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  GPBInt32ObjectDictionary<NSString*> *dict3 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict3);
+  GPBInt32ObjectDictionary<NSString*> *dict4 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32ObjectDictionary<NSString*> *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt32ObjectDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
+      [GPBInt32ObjectDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt32ObjectDictionary<NSString*> *dict = [GPBInt32ObjectDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setObject:@"abc" forKey:11];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int32_t kKeys[] = { 12, 13, 14 };
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:12], @"def");
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"jkl");
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeObjectForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertNil([dict objectForKey:12]);
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"jkl");
+
+  // Remove again does nothing.
+  [dict removeObjectForKey:12];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertNil([dict objectForKey:12]);
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"jkl");
+
+  [dict removeObjectForKey:14];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertNil([dict objectForKey:12]);
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertNil([dict objectForKey:14]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:11]);
+  XCTAssertNil([dict objectForKey:12]);
+  XCTAssertNil([dict objectForKey:13]);
+  XCTAssertNil([dict objectForKey:14]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int32_t kKeys[] = { 11, 12, 13, 14 };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:12], @"def");
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"jkl");
+
+  [dict setObject:@"jkl" forKey:11];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:12], @"def");
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"jkl");
+
+  [dict setObject:@"def" forKey:14];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:12], @"def");
+  XCTAssertEqualObjects([dict objectForKey:13], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:14], @"def");
+
+  const int32_t kKeys2[] = { 12, 13 };
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:11], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:12], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:13], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:14], @"def");
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int64.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int64.m
new file mode 100644
index 0000000..66bc648
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+Int64.m
@@ -0,0 +1,3647 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+// This block of code is generated, do not edit it directly.
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 700:
+    case 701:
+    case 702:
+    case 703:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key {
+  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+  // type correct.
+  return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                  rawValues:&value
+                                                                    forKeys:&key
+                                                                      count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const int64_t [])keys
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                  forKeys:keys
+                                    count:count];
+}
+@end
+
+
+#pragma mark - Int64 -> UInt32
+
+@interface GPBInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBInt64UInt32Dictionary *dict = [[GPBInt64UInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionaryWithValue:100U forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const uint32_t kValues[] = { 100U, 101U, 102U };
+  GPBInt64UInt32Dictionary *dict =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const uint32_t kValues1[] = { 100U, 101U, 102U };
+  const uint32_t kValues2[] = { 100U, 103U, 102U };
+  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict1 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64UInt32Dictionary *dict1prime =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64UInt32Dictionary *dict2 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64UInt32Dictionary *dict3 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64UInt32Dictionary *dict4 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64UInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64UInt32Dictionary *dict2 =
+      [GPBInt64UInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const uint32_t kValues[] = { 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict2 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 103U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBInt64UInt32Dictionary *dict =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:103U forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:101U forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const uint32_t kValues2[] = { 102U, 100U };
+  GPBInt64UInt32Dictionary *dict2 =
+      [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@interface GPBInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int32DictionaryTests
+
+- (void)testEmpty {
+  GPBInt64Int32Dictionary *dict = [[GPBInt64Int32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionaryWithValue:200 forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const int32_t kValues[] = { 200, 201, 202 };
+  GPBInt64Int32Dictionary *dict =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const int32_t kValues1[] = { 200, 201, 202 };
+  const int32_t kValues2[] = { 200, 203, 202 };
+  const int32_t kValues3[] = { 200, 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict1 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64Int32Dictionary *dict1prime =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64Int32Dictionary *dict2 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64Int32Dictionary *dict3 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64Int32Dictionary *dict4 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64Int32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64Int32Dictionary *dict2 =
+      [GPBInt64Int32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict2 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 203);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBInt64Int32Dictionary *dict =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:203 forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:201 forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 201);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const int32_t kValues2[] = { 202, 200 };
+  GPBInt64Int32Dictionary *dict2 =
+      [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@interface GPBInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBInt64UInt64Dictionary *dict = [[GPBInt64UInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionaryWithValue:300U forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const uint64_t kValues[] = { 300U, 301U, 302U };
+  GPBInt64UInt64Dictionary *dict =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const uint64_t kValues1[] = { 300U, 301U, 302U };
+  const uint64_t kValues2[] = { 300U, 303U, 302U };
+  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict1 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64UInt64Dictionary *dict1prime =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64UInt64Dictionary *dict2 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64UInt64Dictionary *dict3 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64UInt64Dictionary *dict4 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64UInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64UInt64Dictionary *dict2 =
+      [GPBInt64UInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const uint64_t kValues[] = { 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict2 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 303U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBInt64UInt64Dictionary *dict =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:303U forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:301U forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const uint64_t kValues2[] = { 302U, 300U };
+  GPBInt64UInt64Dictionary *dict2 =
+      [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@interface GPBInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int64DictionaryTests
+
+- (void)testEmpty {
+  GPBInt64Int64Dictionary *dict = [[GPBInt64Int64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionaryWithValue:400 forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const int64_t kValues[] = { 400, 401, 402 };
+  GPBInt64Int64Dictionary *dict =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  int64_t *seenValues = malloc(3 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const int64_t kValues1[] = { 400, 401, 402 };
+  const int64_t kValues2[] = { 400, 403, 402 };
+  const int64_t kValues3[] = { 400, 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict1 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64Int64Dictionary *dict1prime =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64Int64Dictionary *dict2 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64Int64Dictionary *dict3 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64Int64Dictionary *dict4 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64Int64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64Int64Dictionary *dict2 =
+      [GPBInt64Int64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const int64_t kValues[] = { 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict2 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 403);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBInt64Int64Dictionary *dict =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:403 forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:401 forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 401);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const int64_t kValues2[] = { 402, 400 };
+  GPBInt64Int64Dictionary *dict2 =
+      [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@interface GPBInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64BoolDictionaryTests
+
+- (void)testEmpty {
+  GPBInt64BoolDictionary *dict = [[GPBInt64BoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionaryWithValue:YES forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, YES);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const BOOL kValues[] = { YES, YES, NO };
+  GPBInt64BoolDictionary *dict =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  BOOL *seenValues = malloc(3 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const BOOL kValues1[] = { YES, YES, NO };
+  const BOOL kValues2[] = { YES, NO, NO };
+  const BOOL kValues3[] = { YES, YES, NO, NO };
+  GPBInt64BoolDictionary *dict1 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64BoolDictionary *dict1prime =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64BoolDictionary *dict2 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64BoolDictionary *dict3 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64BoolDictionary *dict4 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt64BoolDictionary *dict =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64BoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64BoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt64BoolDictionary *dict =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64BoolDictionary *dict2 =
+      [GPBInt64BoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:YES forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const BOOL kValues[] = { YES, NO, NO };
+  GPBInt64BoolDictionary *dict2 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, NO);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt64BoolDictionary *dict =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBInt64BoolDictionary *dict =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:NO forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:YES forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, YES);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const BOOL kValues2[] = { NO, YES };
+  GPBInt64BoolDictionary *dict2 =
+      [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@interface GPBInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64FloatDictionaryTests
+
+- (void)testEmpty {
+  GPBInt64FloatDictionary *dict = [[GPBInt64FloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionaryWithValue:500.f forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const float kValues[] = { 500.f, 501.f, 502.f };
+  GPBInt64FloatDictionary *dict =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  float *seenValues = malloc(3 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const float kValues1[] = { 500.f, 501.f, 502.f };
+  const float kValues2[] = { 500.f, 503.f, 502.f };
+  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict1 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64FloatDictionary *dict1prime =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64FloatDictionary *dict2 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64FloatDictionary *dict3 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64FloatDictionary *dict4 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64FloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64FloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64FloatDictionary *dict2 =
+      [GPBInt64FloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const float kValues[] = { 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict2 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBInt64FloatDictionary *dict =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  float value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:503.f forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:501.f forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const float kValues2[] = { 502.f, 500.f };
+  GPBInt64FloatDictionary *dict2 =
+      [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@interface GPBInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBInt64DoubleDictionary *dict = [[GPBInt64DoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionaryWithValue:600. forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const double kValues[] = { 600., 601., 602. };
+  GPBInt64DoubleDictionary *dict =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  double *seenValues = malloc(3 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const double kValues1[] = { 600., 601., 602. };
+  const double kValues2[] = { 600., 603., 602. };
+  const double kValues3[] = { 600., 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict1 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64DoubleDictionary *dict1prime =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64DoubleDictionary *dict2 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64DoubleDictionary *dict3 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64DoubleDictionary *dict4 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64DoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64DoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64DoubleDictionary *dict2 =
+      [GPBInt64DoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const double kValues[] = { 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict2 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 603.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBInt64DoubleDictionary *dict =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  double value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:603. forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:601. forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const double kValues2[] = { 602., 600. };
+  GPBInt64DoubleDictionary *dict2 =
+      [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@interface GPBInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryTests
+
+- (void)testEmpty {
+  GPBInt64EnumDictionary *dict = [[GPBInt64EnumDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionaryWithValue:700 forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqual(aValue, 700);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const int32_t kValues[] = { 700, 701, 702 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const int32_t kValues1[] = { 700, 701, 702 };
+  const int32_t kValues2[] = { 700, 703, 702 };
+  const int32_t kValues3[] = { 700, 701, 702, 703 };
+  GPBInt64EnumDictionary *dict1 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64EnumDictionary *dict1prime =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64EnumDictionary *dict3 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64EnumDictionary *dict4 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues3
+                                             forKeys:kKeys1
+                                               count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64EnumDictionary *dict2 =
+      [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:700 forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 701, 702, 703 };
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 703);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                      forKeys:kKeys
+                                        count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:703 forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:701 forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 701);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const int32_t kValues2[] = { 702, 700 };
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+                                             forKeys:kKeys2
+                                               count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 701);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum (Unknown Enums)
+
+@interface GPBInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const int32_t kValues[] = { 700, 801, 702 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:24LL rawValue:NULL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        if (i == 1) {
+          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+        } else {
+          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+        }
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
+  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
+  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt64EnumDictionary *dict1 =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64EnumDictionary *dict1prime =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues2
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64EnumDictionary *dict3 =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues1
+                                                         forKeys:kKeys2
+                                                           count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64EnumDictionary *dict4 =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues3
+                                                         forKeys:kKeys1
+                                                           count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertEqualObjects(dict, dict2);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64EnumDictionary *dict2 =
+      [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  [dict release];
+}
+
+- (void)testUnknownAdds {
+  GPBInt64EnumDictionary *dict =
+    [GPBInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:22LL],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 0U);
+  [dict setRawValue:801 forKey:22LL];  // Unknown
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 21LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+                                             forKeys:kKeys
+                                               count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  [dict2 release];
+}
+
+- (void)testUnknownRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict removeValueForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+  XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:21LL],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:803 forKey:21LL];  // Unknown
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:700 forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 700);
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const int32_t kValues2[] = { 702, 801 };  // Unknown
+  GPBInt64EnumDictionary *dict2 =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues2
+                                                         forKeys:kKeys2
+                                                           count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:22LL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+  XCTAssertTrue([dict valueForKey:24LL value:&value]);
+  XCTAssertEqual(value, 700);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testCopyUnknowns {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };
+  GPBInt64EnumDictionary *dict =
+      [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                       rawValues:kValues
+                                                         forKeys:kKeys
+                                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@interface GPBInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+  GPBInt64ObjectDictionary<NSString*> *dict = [[GPBInt64ObjectDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:21LL]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBInt64ObjectDictionary<NSString*> *dict = [GPBInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:21LL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertNil([dict objectForKey:22LL]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertEqual(aKey, 21LL);
+    XCTAssertEqualObjects(aObject, @"abc");
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertNil([dict objectForKey:24LL]);
+
+  __block NSUInteger idx = 0;
+  int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenObjects[idx] = aObject;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenObjects);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+  const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict1 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1);
+  GPBInt64ObjectDictionary<NSString*> *dict1prime =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1prime);
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  GPBInt64ObjectDictionary<NSString*> *dict3 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict3);
+  GPBInt64ObjectDictionary<NSString*> *dict4 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kObjects3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64ObjectDictionary<NSString*> *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBInt64ObjectDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
+      [GPBInt64ObjectDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBInt64ObjectDictionary<NSString*> *dict = [GPBInt64ObjectDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setObject:@"abc" forKey:21LL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl");
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeObjectForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertNil([dict objectForKey:22LL]);
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl");
+
+  // Remove again does nothing.
+  [dict removeObjectForKey:22LL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertNil([dict objectForKey:22LL]);
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl");
+
+  [dict removeObjectForKey:24LL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertNil([dict objectForKey:22LL]);
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertNil([dict objectForKey:24LL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:21LL]);
+  XCTAssertNil([dict objectForKey:22LL]);
+  XCTAssertNil([dict objectForKey:23LL]);
+  XCTAssertNil([dict objectForKey:24LL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl");
+
+  [dict setObject:@"jkl" forKey:21LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl");
+
+  [dict setObject:@"def" forKey:24LL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"def");
+
+  const int64_t kKeys2[] = { 22LL, 23LL };
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:21LL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:22LL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:23LL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:24LL], @"def");
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+String.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+String.m
new file mode 100644
index 0000000..bfa10b1
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+String.m
@@ -0,0 +1,3359 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+// This block of code is generated, do not edit it directly.
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key;
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 700:
+    case 701:
+    case 702:
+    case 703:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key {
+  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+  // type correct.
+  return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                   rawValues:&value
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const NSString * [])keys
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                  forKeys:keys
+                                    count:count];
+}
+@end
+
+
+#pragma mark - String -> UInt32
+
+@interface GPBStringUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionaryWithValue:100U forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const uint32_t kValues[] = { 100U, 101U, 102U };
+  GPBStringUInt32Dictionary *dict =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const uint32_t kValues1[] = { 100U, 101U, 102U };
+  const uint32_t kValues2[] = { 100U, 103U, 102U };
+  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict1 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringUInt32Dictionary *dict1prime =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringUInt32Dictionary *dict2 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringUInt32Dictionary *dict3 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringUInt32Dictionary *dict4 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringUInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringUInt32Dictionary *dict2 =
+      [GPBStringUInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const uint32_t kValues[] = { 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict2 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 103U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBStringUInt32Dictionary *dict =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:103U forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:101U forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const uint32_t kValues2[] = { 102U, 100U };
+  GPBStringUInt32Dictionary *dict2 =
+      [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int32
+
+@interface GPBStringInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionaryWithValue:200 forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const int32_t kValues[] = { 200, 201, 202 };
+  GPBStringInt32Dictionary *dict =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const int32_t kValues1[] = { 200, 201, 202 };
+  const int32_t kValues2[] = { 200, 203, 202 };
+  const int32_t kValues3[] = { 200, 201, 202, 203 };
+  GPBStringInt32Dictionary *dict1 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringInt32Dictionary *dict1prime =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringInt32Dictionary *dict2 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringInt32Dictionary *dict3 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringInt32Dictionary *dict4 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBStringInt32Dictionary *dict =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBStringInt32Dictionary *dict =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringInt32Dictionary *dict2 =
+      [GPBStringInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 201, 202, 203 };
+  GPBStringInt32Dictionary *dict2 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 203);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBStringInt32Dictionary *dict =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 203);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBStringInt32Dictionary *dict =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:203 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:201 forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 201);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const int32_t kValues2[] = { 202, 200 };
+  GPBStringInt32Dictionary *dict2 =
+      [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> UInt64
+
+@interface GPBStringUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionaryWithValue:300U forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const uint64_t kValues[] = { 300U, 301U, 302U };
+  GPBStringUInt64Dictionary *dict =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const uint64_t kValues1[] = { 300U, 301U, 302U };
+  const uint64_t kValues2[] = { 300U, 303U, 302U };
+  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict1 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringUInt64Dictionary *dict1prime =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringUInt64Dictionary *dict2 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringUInt64Dictionary *dict3 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringUInt64Dictionary *dict4 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringUInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringUInt64Dictionary *dict2 =
+      [GPBStringUInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const uint64_t kValues[] = { 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict2 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 303U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBStringUInt64Dictionary *dict =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:303U forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:301U forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const uint64_t kValues2[] = { 302U, 300U };
+  GPBStringUInt64Dictionary *dict2 =
+      [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int64
+
+@interface GPBStringInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionaryWithValue:400 forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const int64_t kValues[] = { 400, 401, 402 };
+  GPBStringInt64Dictionary *dict =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  int64_t *seenValues = malloc(3 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const int64_t kValues1[] = { 400, 401, 402 };
+  const int64_t kValues2[] = { 400, 403, 402 };
+  const int64_t kValues3[] = { 400, 401, 402, 403 };
+  GPBStringInt64Dictionary *dict1 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringInt64Dictionary *dict1prime =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringInt64Dictionary *dict2 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringInt64Dictionary *dict3 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringInt64Dictionary *dict4 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBStringInt64Dictionary *dict =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBStringInt64Dictionary *dict =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringInt64Dictionary *dict2 =
+      [GPBStringInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const int64_t kValues[] = { 401, 402, 403 };
+  GPBStringInt64Dictionary *dict2 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 403);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBStringInt64Dictionary *dict =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 403);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBStringInt64Dictionary *dict =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:403 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:401 forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 401);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const int64_t kValues2[] = { 402, 400 };
+  GPBStringInt64Dictionary *dict2 =
+      [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Bool
+
+@interface GPBStringBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringBoolDictionaryTests
+
+- (void)testEmpty {
+  GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionaryWithValue:YES forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, YES);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const BOOL kValues[] = { YES, YES, NO };
+  GPBStringBoolDictionary *dict =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  BOOL *seenValues = malloc(3 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const BOOL kValues1[] = { YES, YES, NO };
+  const BOOL kValues2[] = { YES, NO, NO };
+  const BOOL kValues3[] = { YES, YES, NO, NO };
+  GPBStringBoolDictionary *dict1 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringBoolDictionary *dict1prime =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringBoolDictionary *dict2 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringBoolDictionary *dict3 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringBoolDictionary *dict4 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBStringBoolDictionary *dict =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringBoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringBoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBStringBoolDictionary *dict =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringBoolDictionary *dict2 =
+      [GPBStringBoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:YES forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const BOOL kValues[] = { YES, NO, NO };
+  GPBStringBoolDictionary *dict2 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, NO);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBStringBoolDictionary *dict =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, NO);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBStringBoolDictionary *dict =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:NO forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:YES forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, YES);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const BOOL kValues2[] = { NO, YES };
+  GPBStringBoolDictionary *dict2 =
+      [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Float
+
+@interface GPBStringFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringFloatDictionaryTests
+
+- (void)testEmpty {
+  GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionaryWithValue:500.f forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const float kValues[] = { 500.f, 501.f, 502.f };
+  GPBStringFloatDictionary *dict =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  float *seenValues = malloc(3 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const float kValues1[] = { 500.f, 501.f, 502.f };
+  const float kValues2[] = { 500.f, 503.f, 502.f };
+  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict1 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringFloatDictionary *dict1prime =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringFloatDictionary *dict2 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringFloatDictionary *dict3 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringFloatDictionary *dict4 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringFloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringFloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringFloatDictionary *dict2 =
+      [GPBStringFloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const float kValues[] = { 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict2 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 503.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBStringFloatDictionary *dict =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  float value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:503.f forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:501.f forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const float kValues2[] = { 502.f, 500.f };
+  GPBStringFloatDictionary *dict2 =
+      [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Double
+
+@interface GPBStringDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringDoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionaryWithValue:600. forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const double kValues[] = { 600., 601., 602. };
+  GPBStringDoubleDictionary *dict =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  double *seenValues = malloc(3 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const double kValues1[] = { 600., 601., 602. };
+  const double kValues2[] = { 600., 603., 602. };
+  const double kValues3[] = { 600., 601., 602., 603. };
+  GPBStringDoubleDictionary *dict1 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringDoubleDictionary *dict1prime =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringDoubleDictionary *dict2 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringDoubleDictionary *dict3 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringDoubleDictionary *dict4 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBStringDoubleDictionary *dict =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringDoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringDoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBStringDoubleDictionary *dict =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringDoubleDictionary *dict2 =
+      [GPBStringDoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const double kValues[] = { 601., 602., 603. };
+  GPBStringDoubleDictionary *dict2 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 603.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBStringDoubleDictionary *dict =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBStringDoubleDictionary *dict =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  double value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:603. forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:601. forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const double kValues2[] = { 602., 600. };
+  GPBStringDoubleDictionary *dict2 =
+      [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum
+
+@interface GPBStringEnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryTests
+
+- (void)testEmpty {
+  GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionaryWithValue:700 forKey:@"foo"];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqualObjects(aKey, @"foo");
+    XCTAssertEqual(aValue, 700);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const int32_t kValues[] = { 700, 701, 702 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const int32_t kValues1[] = { 700, 701, 702 };
+  const int32_t kValues2[] = { 700, 703, 702 };
+  const int32_t kValues3[] = { 700, 701, 702, 703 };
+  GPBStringEnumDictionary *dict1 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringEnumDictionary *dict1prime =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringEnumDictionary *dict3 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringEnumDictionary *dict4 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringEnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringEnumDictionary *dict2 =
+      [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:700 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 701, 702, 703 };
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 703);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 703);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:703 forKey:@"foo"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:701 forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 701);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const int32_t kValues2[] = { 702, 700 };
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 701);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum (Unknown Enums)
+
+@interface GPBStringEnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+  const int32_t kValues[] = { 700, 801, 702 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:@"mumble" rawValue:NULL]);
+
+  __block NSUInteger idx = 0;
+  NSString **seenKeys = malloc(3 * sizeof(NSString*));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        if (i == 1) {
+          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+        } else {
+          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+        }
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if ([kKeys[i] isEqual:seenKeys[j]]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+  const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
+  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
+  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBStringEnumDictionary *dict1 =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBStringEnumDictionary *dict1prime =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBStringEnumDictionary *dict3 =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBStringEnumDictionary *dict4 =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues3
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringEnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertEqualObjects(dict, dict2);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringEnumDictionary *dict2 =
+      [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  [dict release];
+}
+
+- (void)testUnknownAdds {
+  GPBStringEnumDictionary *dict =
+    [GPBStringEnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:@"bar"],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 0U);
+  [dict setRawValue:801 forKey:@"bar"];  // Unknown
+  XCTAssertEqual(dict.count, 1U);
+
+  const NSString *kKeys[] = { @"foo", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  [dict2 release];
+}
+
+- (void)testUnknownRemove {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:@"bar"];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict removeValueForKey:@"mumble"];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:@"foo"],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:803 forKey:@"foo"];  // Unknown
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:700 forKey:@"mumble"];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 700);
+
+  const NSString *kKeys2[] = { @"bar", @"baz" };
+  const int32_t kValues2[] = { 702, 801 };  // Unknown
+  GPBStringEnumDictionary *dict2 =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+  XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+  XCTAssertEqual(value, 700);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testCopyUnknowns {
+  const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+  const int32_t kValues[] = { 700, 801, 702, 803 };
+  GPBStringEnumDictionary *dict =
+      [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBStringEnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt32.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt32.m
new file mode 100644
index 0000000..499f2ad
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt32.m
@@ -0,0 +1,3647 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+// This block of code is generated, do not edit it directly.
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 700:
+    case 701:
+    case 702:
+    case 703:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key {
+  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+  // type correct.
+  return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                   rawValues:&value
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint32_t [])keys
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                  forKeys:keys
+                                    count:count];
+}
+@end
+
+
+#pragma mark - UInt32 -> UInt32
+
+@interface GPBUInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionaryWithValue:100U forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const uint32_t kValues[] = { 100U, 101U, 102U };
+  GPBUInt32UInt32Dictionary *dict =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const uint32_t kValues1[] = { 100U, 101U, 102U };
+  const uint32_t kValues2[] = { 100U, 103U, 102U };
+  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict1 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32UInt32Dictionary *dict1prime =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32UInt32Dictionary *dict2 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32UInt32Dictionary *dict3 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32UInt32Dictionary *dict4 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32UInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32UInt32Dictionary *dict2 =
+      [GPBUInt32UInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const uint32_t kValues[] = { 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict2 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 103U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt32UInt32Dictionary *dict =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:103U forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:101U forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const uint32_t kValues2[] = { 102U, 100U };
+  GPBUInt32UInt32Dictionary *dict2 =
+      [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@interface GPBUInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int32DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionaryWithValue:200 forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const int32_t kValues[] = { 200, 201, 202 };
+  GPBUInt32Int32Dictionary *dict =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const int32_t kValues1[] = { 200, 201, 202 };
+  const int32_t kValues2[] = { 200, 203, 202 };
+  const int32_t kValues3[] = { 200, 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict1 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32Int32Dictionary *dict1prime =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32Int32Dictionary *dict2 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32Int32Dictionary *dict3 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32Int32Dictionary *dict4 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32Int32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32Int32Dictionary *dict2 =
+      [GPBUInt32Int32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const int32_t kValues[] = { 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict2 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 203);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 203);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt32Int32Dictionary *dict =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:203 forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:201 forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 201);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const int32_t kValues2[] = { 202, 200 };
+  GPBUInt32Int32Dictionary *dict2 =
+      [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@interface GPBUInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionaryWithValue:300U forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const uint64_t kValues[] = { 300U, 301U, 302U };
+  GPBUInt32UInt64Dictionary *dict =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const uint64_t kValues1[] = { 300U, 301U, 302U };
+  const uint64_t kValues2[] = { 300U, 303U, 302U };
+  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict1 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32UInt64Dictionary *dict1prime =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32UInt64Dictionary *dict2 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32UInt64Dictionary *dict3 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32UInt64Dictionary *dict4 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32UInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32UInt64Dictionary *dict2 =
+      [GPBUInt32UInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const uint64_t kValues[] = { 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict2 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 303U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt32UInt64Dictionary *dict =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:303U forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:301U forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const uint64_t kValues2[] = { 302U, 300U };
+  GPBUInt32UInt64Dictionary *dict2 =
+      [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@interface GPBUInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int64DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionaryWithValue:400 forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const int64_t kValues[] = { 400, 401, 402 };
+  GPBUInt32Int64Dictionary *dict =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  int64_t *seenValues = malloc(3 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const int64_t kValues1[] = { 400, 401, 402 };
+  const int64_t kValues2[] = { 400, 403, 402 };
+  const int64_t kValues3[] = { 400, 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict1 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32Int64Dictionary *dict1prime =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32Int64Dictionary *dict2 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32Int64Dictionary *dict3 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32Int64Dictionary *dict4 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32Int64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32Int64Dictionary *dict2 =
+      [GPBUInt32Int64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const int64_t kValues[] = { 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict2 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 403);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 403);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt32Int64Dictionary *dict =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:403 forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:401 forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 401);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const int64_t kValues2[] = { 402, 400 };
+  GPBUInt32Int64Dictionary *dict2 =
+      [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@interface GPBUInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32BoolDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionaryWithValue:YES forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, YES);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const BOOL kValues[] = { YES, YES, NO };
+  GPBUInt32BoolDictionary *dict =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  BOOL *seenValues = malloc(3 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const BOOL kValues1[] = { YES, YES, NO };
+  const BOOL kValues2[] = { YES, NO, NO };
+  const BOOL kValues3[] = { YES, YES, NO, NO };
+  GPBUInt32BoolDictionary *dict1 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32BoolDictionary *dict1prime =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32BoolDictionary *dict2 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32BoolDictionary *dict3 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32BoolDictionary *dict4 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt32BoolDictionary *dict =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32BoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32BoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt32BoolDictionary *dict =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32BoolDictionary *dict2 =
+      [GPBUInt32BoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:YES forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const BOOL kValues[] = { YES, NO, NO };
+  GPBUInt32BoolDictionary *dict2 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, NO);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt32BoolDictionary *dict =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, NO);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt32BoolDictionary *dict =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:NO forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:YES forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, YES);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const BOOL kValues2[] = { NO, YES };
+  GPBUInt32BoolDictionary *dict2 =
+      [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@interface GPBUInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32FloatDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionaryWithValue:500.f forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const float kValues[] = { 500.f, 501.f, 502.f };
+  GPBUInt32FloatDictionary *dict =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  float *seenValues = malloc(3 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const float kValues1[] = { 500.f, 501.f, 502.f };
+  const float kValues2[] = { 500.f, 503.f, 502.f };
+  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict1 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32FloatDictionary *dict1prime =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32FloatDictionary *dict2 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32FloatDictionary *dict3 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32FloatDictionary *dict4 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32FloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32FloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32FloatDictionary *dict2 =
+      [GPBUInt32FloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const float kValues[] = { 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict2 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 503.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt32FloatDictionary *dict =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  float value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:503.f forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:501.f forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const float kValues2[] = { 502.f, 500.f };
+  GPBUInt32FloatDictionary *dict2 =
+      [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@interface GPBUInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionaryWithValue:600. forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const double kValues[] = { 600., 601., 602. };
+  GPBUInt32DoubleDictionary *dict =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  double *seenValues = malloc(3 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const double kValues1[] = { 600., 601., 602. };
+  const double kValues2[] = { 600., 603., 602. };
+  const double kValues3[] = { 600., 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict1 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32DoubleDictionary *dict1prime =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32DoubleDictionary *dict2 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32DoubleDictionary *dict3 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32DoubleDictionary *dict4 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32DoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32DoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32DoubleDictionary *dict2 =
+      [GPBUInt32DoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const double kValues[] = { 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict2 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 603.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt32DoubleDictionary *dict =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  double value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:603. forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:601. forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const double kValues2[] = { 602., 600. };
+  GPBUInt32DoubleDictionary *dict2 =
+      [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@interface GPBUInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionaryWithValue:700 forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqual(aValue, 700);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const int32_t kValues[] = { 700, 701, 702 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const int32_t kValues1[] = { 700, 701, 702 };
+  const int32_t kValues2[] = { 700, 703, 702 };
+  const int32_t kValues3[] = { 700, 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict1 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32EnumDictionary *dict1prime =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32EnumDictionary *dict3 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32EnumDictionary *dict4 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32EnumDictionary *dict2 =
+      [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:700 forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const int32_t kValues[] = { 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 703);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 703);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:703 forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:701 forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 701);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const int32_t kValues2[] = { 702, 700 };
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 701);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum (Unknown Enums)
+
+@interface GPBUInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const int32_t kValues[] = { 700, 801, 702 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:4U rawValue:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        if (i == 1) {
+          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+        } else {
+          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+        }
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
+  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
+  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt32EnumDictionary *dict1 =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32EnumDictionary *dict1prime =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32EnumDictionary *dict3 =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32EnumDictionary *dict4 =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues3
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertEqualObjects(dict, dict2);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32EnumDictionary *dict2 =
+      [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  [dict release];
+}
+
+- (void)testUnknownAdds {
+  GPBUInt32EnumDictionary *dict =
+    [GPBUInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:2U],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 0U);
+  [dict setRawValue:801 forKey:2U];  // Unknown
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 1U, 3U, 4U };
+  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  [dict2 release];
+}
+
+- (void)testUnknownRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict removeValueForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:1U value:NULL]);
+  XCTAssertFalse([dict valueForKey:2U value:NULL]);
+  XCTAssertFalse([dict valueForKey:3U value:NULL]);
+  XCTAssertFalse([dict valueForKey:4U value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:1U],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U value:NULL]);
+  XCTAssertTrue([dict valueForKey:1U value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:803 forKey:1U];  // Unknown
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:700 forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:3U value:NULL]);
+  XCTAssertTrue([dict valueForKey:3U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 700);
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const int32_t kValues2[] = { 702, 801 };  // Unknown
+  GPBUInt32EnumDictionary *dict2 =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:2U value:NULL]);
+  XCTAssertTrue([dict valueForKey:2U value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:4U value:NULL]);
+  XCTAssertTrue([dict valueForKey:4U value:&value]);
+  XCTAssertEqual(value, 700);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testCopyUnknowns {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const int32_t kValues[] = { 700, 801, 702, 803 };
+  GPBUInt32EnumDictionary *dict =
+      [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@interface GPBUInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt32ObjectDictionary<NSString*> *dict = [[GPBUInt32ObjectDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:1U]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:1U];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertNil([dict objectForKey:2U]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertEqual(aKey, 1U);
+    XCTAssertEqualObjects(aObject, @"abc");
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint32_t kKeys[] = { 1U, 2U, 3U };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertNil([dict objectForKey:4U]);
+
+  __block NSUInteger idx = 0;
+  uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenObjects[idx] = aObject;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenObjects);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+  const uint32_t kKeys2[] = { 2U, 1U, 4U };
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict1 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt32ObjectDictionary<NSString*> *dict1prime =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt32ObjectDictionary<NSString*> *dict3 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys2
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt32ObjectDictionary<NSString*> *dict4 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects3
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32ObjectDictionary<NSString*> *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32ObjectDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
+      [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setObject:@"abc" forKey:1U];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint32_t kKeys[] = { 2U, 3U, 4U };
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                          forKeys:kKeys
+                                            count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeObjectForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertNil([dict objectForKey:2U]);
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
+
+  // Remove again does nothing.
+  [dict removeObjectForKey:2U];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertNil([dict objectForKey:2U]);
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
+
+  [dict removeObjectForKey:4U];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertNil([dict objectForKey:2U]);
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertNil([dict objectForKey:4U]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:1U]);
+  XCTAssertNil([dict objectForKey:2U]);
+  XCTAssertNil([dict objectForKey:3U]);
+  XCTAssertNil([dict objectForKey:4U]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
+                                          forKeys:kKeys
+                                            count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
+
+  [dict setObject:@"jkl" forKey:1U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"jkl");
+
+  [dict setObject:@"def" forKey:4U];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"def");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"def");
+
+  const uint32_t kKeys2[] = { 2U, 3U };
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
+                                                 forKeys:kKeys2
+                                                   count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:1U], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:2U], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:3U], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:4U], @"def");
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt64.m b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt64.m
new file mode 100644
index 0000000..327e154
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests+UInt64.m
@@ -0,0 +1,3646 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
+// This block of code is generated, do not edit it directly.
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+  switch (value) {
+    case 700:
+    case 701:
+    case 702:
+    case 703:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+@implementation GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key {
+  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+  // type correct.
+  return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                   rawValues:&value
+                                                                     forKeys:&key
+                                                                       count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+                       forKeys:(const uint64_t [])keys
+                         count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue
+                                rawValues:values
+                                  forKeys:keys
+                                    count:count];
+}
+@end
+
+
+#pragma mark - UInt64 -> UInt32
+
+@interface GPBUInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64UInt32Dictionary *dict = [[GPBUInt64UInt32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionaryWithValue:100U forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 100U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const uint32_t kValues[] = { 100U, 101U, 102U };
+  GPBUInt64UInt32Dictionary *dict =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const uint32_t kValues1[] = { 100U, 101U, 102U };
+  const uint32_t kValues2[] = { 100U, 103U, 102U };
+  const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict1 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64UInt32Dictionary *dict1prime =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64UInt32Dictionary *dict2 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64UInt32Dictionary *dict3 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64UInt32Dictionary *dict4 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64UInt32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64UInt32Dictionary *dict2 =
+      [GPBUInt64UInt32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:100U forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const uint32_t kValues[] = { 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict2 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+  GPBUInt64UInt32Dictionary *dict =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:103U forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+
+  [dict setValue:101U forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const uint32_t kValues2[] = { 102U, 100U };
+  GPBUInt64UInt32Dictionary *dict2 =
+      [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 103U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 102U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 100U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 101U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@interface GPBUInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int32DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64Int32Dictionary *dict = [[GPBUInt64Int32Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionaryWithValue:200 forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 200);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const int32_t kValues[] = { 200, 201, 202 };
+  GPBUInt64Int32Dictionary *dict =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const int32_t kValues1[] = { 200, 201, 202 };
+  const int32_t kValues2[] = { 200, 203, 202 };
+  const int32_t kValues3[] = { 200, 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict1 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64Int32Dictionary *dict1prime =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64Int32Dictionary *dict2 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64Int32Dictionary *dict3 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64Int32Dictionary *dict4 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64Int32Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int32Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64Int32Dictionary *dict2 =
+      [GPBUInt64Int32Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:200 forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict2 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 203);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 200, 201, 202, 203 };
+  GPBUInt64Int32Dictionary *dict =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:203 forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 203);
+
+  [dict setValue:201 forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 201);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 201);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const int32_t kValues2[] = { 202, 200 };
+  GPBUInt64Int32Dictionary *dict2 =
+      [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 203);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 202);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 200);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 201);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@interface GPBUInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64UInt64Dictionary *dict = [[GPBUInt64UInt64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionaryWithValue:300U forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 300U);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const uint64_t kValues[] = { 300U, 301U, 302U };
+  GPBUInt64UInt64Dictionary *dict =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const uint64_t kValues1[] = { 300U, 301U, 302U };
+  const uint64_t kValues2[] = { 300U, 303U, 302U };
+  const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict1 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64UInt64Dictionary *dict1prime =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64UInt64Dictionary *dict2 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64UInt64Dictionary *dict3 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64UInt64Dictionary *dict4 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64UInt64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64UInt64Dictionary *dict2 =
+      [GPBUInt64UInt64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:300U forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const uint64_t kValues[] = { 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict2 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+  GPBUInt64UInt64Dictionary *dict =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  uint64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:303U forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+
+  [dict setValue:301U forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const uint64_t kValues2[] = { 302U, 300U };
+  GPBUInt64UInt64Dictionary *dict2 =
+      [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 303U);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 302U);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 300U);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 301U);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@interface GPBUInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int64DictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64Int64Dictionary *dict = [[GPBUInt64Int64Dictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionaryWithValue:400 forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 400);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const int64_t kValues[] = { 400, 401, 402 };
+  GPBUInt64Int64Dictionary *dict =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  int64_t *seenValues = malloc(3 * sizeof(int64_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const int64_t kValues1[] = { 400, 401, 402 };
+  const int64_t kValues2[] = { 400, 403, 402 };
+  const int64_t kValues3[] = { 400, 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict1 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64Int64Dictionary *dict1prime =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64Int64Dictionary *dict2 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64Int64Dictionary *dict3 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64Int64Dictionary *dict4 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64Int64Dictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int64Dictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64Int64Dictionary *dict2 =
+      [GPBUInt64Int64Dictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:400 forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const int64_t kValues[] = { 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict2 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 403);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int64_t kValues[] = { 400, 401, 402, 403 };
+  GPBUInt64Int64Dictionary *dict =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int64_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:403 forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 403);
+
+  [dict setValue:401 forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 401);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 401);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const int64_t kValues2[] = { 402, 400 };
+  GPBUInt64Int64Dictionary *dict2 =
+      [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 403);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 402);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 400);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 401);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@interface GPBUInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64BoolDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64BoolDictionary *dict = [[GPBUInt64BoolDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionaryWithValue:YES forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, YES);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const BOOL kValues[] = { YES, YES, NO };
+  GPBUInt64BoolDictionary *dict =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  BOOL *seenValues = malloc(3 * sizeof(BOOL));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const BOOL kValues1[] = { YES, YES, NO };
+  const BOOL kValues2[] = { YES, NO, NO };
+  const BOOL kValues3[] = { YES, YES, NO, NO };
+  GPBUInt64BoolDictionary *dict1 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64BoolDictionary *dict1prime =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64BoolDictionary *dict2 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64BoolDictionary *dict3 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64BoolDictionary *dict4 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt64BoolDictionary *dict =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64BoolDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64BoolDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt64BoolDictionary *dict =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64BoolDictionary *dict2 =
+      [GPBUInt64BoolDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:YES forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const BOOL kValues[] = { YES, NO, NO };
+  GPBUInt64BoolDictionary *dict2 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt64BoolDictionary *dict =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const BOOL kValues[] = { YES, YES, NO, NO };
+  GPBUInt64BoolDictionary *dict =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  BOOL value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:NO forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, NO);
+
+  [dict setValue:YES forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, YES);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const BOOL kValues2[] = { NO, YES };
+  GPBUInt64BoolDictionary *dict2 =
+      [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, NO);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, YES);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, YES);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@interface GPBUInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64FloatDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64FloatDictionary *dict = [[GPBUInt64FloatDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionaryWithValue:500.f forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  float value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 500.f);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const float kValues[] = { 500.f, 501.f, 502.f };
+  GPBUInt64FloatDictionary *dict =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  float *seenValues = malloc(3 * sizeof(float));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const float kValues1[] = { 500.f, 501.f, 502.f };
+  const float kValues2[] = { 500.f, 503.f, 502.f };
+  const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict1 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64FloatDictionary *dict1prime =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64FloatDictionary *dict2 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64FloatDictionary *dict3 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64FloatDictionary *dict4 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues3
+                                               forKeys:kKeys1
+                                                 count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64FloatDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64FloatDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64FloatDictionary *dict2 =
+      [GPBUInt64FloatDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:500.f forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const float kValues[] = { 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict2 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                               forKeys:kKeys
+                                                 count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  float value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  float value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+  GPBUInt64FloatDictionary *dict =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+                                        forKeys:kKeys
+                                          count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  float value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:503.f forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+
+  [dict setValue:501.f forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const float kValues2[] = { 502.f, 500.f };
+  GPBUInt64FloatDictionary *dict2 =
+      [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+                                               forKeys:kKeys2
+                                                 count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 503.f);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 502.f);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 500.f);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 501.f);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@interface GPBUInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64DoubleDictionary *dict = [[GPBUInt64DoubleDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionaryWithValue:600. forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  double value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 600.);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const double kValues[] = { 600., 601., 602. };
+  GPBUInt64DoubleDictionary *dict =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  double *seenValues = malloc(3 * sizeof(double));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const double kValues1[] = { 600., 601., 602. };
+  const double kValues2[] = { 600., 603., 602. };
+  const double kValues3[] = { 600., 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict1 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64DoubleDictionary *dict1prime =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64DoubleDictionary *dict2 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64DoubleDictionary *dict3 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64DoubleDictionary *dict4 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues3
+                                                forKeys:kKeys1
+                                                  count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64DoubleDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64DoubleDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64DoubleDictionary *dict2 =
+      [GPBUInt64DoubleDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:600. forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const double kValues[] = { 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict2 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                                forKeys:kKeys
+                                                  count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  double value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  double value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const double kValues[] = { 600., 601., 602., 603. };
+  GPBUInt64DoubleDictionary *dict =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+                                         forKeys:kKeys
+                                           count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  double value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:603. forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+
+  [dict setValue:601. forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const double kValues2[] = { 602., 600. };
+  GPBUInt64DoubleDictionary *dict2 =
+      [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+                                                forKeys:kKeys2
+                                                  count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 603.);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 602.);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 600.);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 601.);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@interface GPBUInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64EnumDictionary *dict = [[GPBUInt64EnumDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionaryWithValue:700 forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqual(aValue, 700);
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const int32_t kValues[] = { 700, 701, 702 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const int32_t kValues1[] = { 700, 701, 702 };
+  const int32_t kValues2[] = { 700, 703, 702 };
+  const int32_t kValues3[] = { 700, 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict1 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64EnumDictionary *dict1prime =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64EnumDictionary *dict3 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64EnumDictionary *dict4 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues3
+                                              forKeys:kKeys1
+                                                count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64EnumDictionary *dict2 =
+      [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setValue:700 forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 703);
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 701, 702, 703 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                       forKeys:kKeys
+                                         count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:703 forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 703);
+
+  [dict setValue:701 forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 701);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 701);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const int32_t kValues2[] = { 702, 700 };
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+                                              forKeys:kKeys2
+                                                count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 703);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 701);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum (Unknown Enums)
+
+@interface GPBUInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const int32_t kValues[] = { 700, 801, 702 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:34ULL rawValue:NULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  int32_t *seenValues = malloc(3 * sizeof(int32_t));
+  [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        if (i == 1) {
+          XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+        } else {
+          XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+        }
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenValues[idx] = aValue;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenValues);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+    #pragma unused(aKey, aValue)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const int32_t kValues1[] = { 700, 801, 702 };  // Unknown
+  const int32_t kValues2[] = { 700, 803, 702 };  // Unknown
+  const int32_t kValues3[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt64EnumDictionary *dict1 =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64EnumDictionary *dict1prime =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64EnumDictionary *dict3 =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues1
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64EnumDictionary *dict4 =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues3
+                                                          forKeys:kKeys1
+                                                            count:GPBARRAYSIZE(kValues3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same values; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknown
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertEqualObjects(dict, dict2);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64EnumDictionary *dict2 =
+      [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  [dict release];
+}
+
+- (void)testUnknownAdds {
+  GPBUInt64EnumDictionary *dict =
+    [GPBUInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:32ULL],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 0U);
+  [dict setRawValue:801 forKey:32ULL];  // Unknown
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 31ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 702, 803 };  // Unknown
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+                                              forKeys:kKeys
+                                                count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  [dict2 release];
+}
+
+- (void)testUnknownRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  // Remove again does nothing.
+  [dict removeValueForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict removeValueForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+  XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };  // Unknowns
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  int32_t value;
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:31ULL],  // Unknown
+                               NSException, NSInvalidArgumentException);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+  XCTAssertEqual(value, 700);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:803 forKey:31ULL];  // Unknown
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+
+  [dict setRawValue:700 forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 700);
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const int32_t kValues2[] = { 702, 801 };  // Unknown
+  GPBUInt64EnumDictionary *dict2 =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues2
+                                                          forKeys:kKeys2
+                                                            count:GPBARRAYSIZE(kValues2)];
+  XCTAssertNotNil(dict2);
+  [dict addRawEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+  XCTAssertEqual(value, 803);
+  XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+  XCTAssertEqual(value, 702);
+  XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+  XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+  XCTAssertEqual(value, 801);
+  XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+  XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+  XCTAssertEqual(value, 700);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testCopyUnknowns {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const int32_t kValues[] = { 700, 801, 702, 803 };
+  GPBUInt64EnumDictionary *dict =
+      [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                        rawValues:kValues
+                                                          forKeys:kKeys
+                                                            count:GPBARRAYSIZE(kValues)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64EnumDictionary *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@interface GPBUInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+  GPBUInt64ObjectDictionary<NSString*> *dict = [[GPBUInt64ObjectDictionary alloc] init];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:31ULL]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject, stop)
+    XCTFail(@"Shouldn't get here!");
+  }];
+  [dict release];
+}
+
+- (void)testOne {
+  GPBUInt64ObjectDictionary<NSString*> *dict = [GPBUInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:31ULL];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 1U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertNil([dict objectForKey:32ULL]);
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertEqual(aKey, 31ULL);
+    XCTAssertEqualObjects(aObject, @"abc");
+    XCTAssertNotEqual(stop, NULL);
+  }];
+}
+
+- (void)testBasics {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertNil([dict objectForKey:34ULL]);
+
+  __block NSUInteger idx = 0;
+  uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
+    XCTAssertLessThan(idx, 3U);
+    seenKeys[idx] = aKey;
+    seenObjects[idx] = aObject;
+    XCTAssertNotEqual(stop, NULL);
+    ++idx;
+  }];
+  for (int i = 0; i < 3; ++i) {
+    BOOL foundKey = NO;
+    for (int j = 0; (j < 3) && !foundKey; ++j) {
+      if (kKeys[i] == seenKeys[j]) {
+        foundKey = YES;
+        XCTAssertEqualObjects(kObjects[i], seenObjects[j], @"i = %d, j = %d", i, j);
+      }
+    }
+    XCTAssertTrue(foundKey, @"i = %d", i);
+  }
+  free(seenKeys);
+  free(seenObjects);
+
+  // Stopping the enumeration.
+  idx = 0;
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
+    #pragma unused(aKey, aObject)
+    if (idx == 1) *stop = YES;
+    XCTAssertNotEqual(idx, 2U);
+    ++idx;
+  }];
+  [dict release];
+}
+
+- (void)testEquality {
+  const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict1 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1);
+  GPBUInt64ObjectDictionary<NSString*> *dict1prime =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict1prime);
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  GPBUInt64ObjectDictionary<NSString*> *dict3 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
+                                                 forKeys:kKeys2
+                                                   count:GPBARRAYSIZE(kObjects1)];
+  XCTAssertNotNil(dict3);
+  GPBUInt64ObjectDictionary<NSString*> *dict4 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects3
+                                                 forKeys:kKeys1
+                                                   count:GPBARRAYSIZE(kObjects3)];
+  XCTAssertNotNil(dict4);
+
+  // 1/1Prime should be different objects, but equal.
+  XCTAssertNotEqual(dict1, dict1prime);
+  XCTAssertEqualObjects(dict1, dict1prime);
+  // Equal, so they must have same hash.
+  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+  // 2 is same keys, different objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict2);
+
+  // 3 is different keys, same objects; not equal.
+  XCTAssertNotEqualObjects(dict1, dict3);
+
+  // 4 extra pair; not equal
+  XCTAssertNotEqualObjects(dict1, dict4);
+
+  [dict1 release];
+  [dict1prime release];
+  [dict2 release];
+  [dict3 release];
+  [dict4 release];
+}
+
+- (void)testCopy {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64ObjectDictionary<NSString*> *dict2 = [dict copy];
+  XCTAssertNotNil(dict2);
+
+  // Should be new object but equal.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64ObjectDictionary class]]);
+
+  [dict2 release];
+  [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
+      [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict];
+  XCTAssertNotNil(dict2);
+
+  // Should be new pointer, but equal objects.
+  XCTAssertNotEqual(dict, dict2);
+  XCTAssertEqualObjects(dict, dict2);
+  [dict release];
+}
+
+- (void)testAdds {
+  GPBUInt64ObjectDictionary<NSString*> *dict = [GPBUInt64ObjectDictionary dictionary];
+  XCTAssertNotNil(dict);
+
+  XCTAssertEqual(dict.count, 0U);
+  [dict setObject:@"abc" forKey:31ULL];
+  XCTAssertEqual(dict.count, 1U);
+
+  const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                                 forKeys:kKeys
+                                                   count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl");
+  [dict2 release];
+}
+
+- (void)testRemove {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                          forKeys:kKeys
+                                            count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+
+  [dict removeObjectForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertNil([dict objectForKey:32ULL]);
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl");
+
+  // Remove again does nothing.
+  [dict removeObjectForKey:32ULL];
+  XCTAssertEqual(dict.count, 3U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertNil([dict objectForKey:32ULL]);
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl");
+
+  [dict removeObjectForKey:34ULL];
+  XCTAssertEqual(dict.count, 2U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertNil([dict objectForKey:32ULL]);
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertNil([dict objectForKey:34ULL]);
+
+  [dict removeAll];
+  XCTAssertEqual(dict.count, 0U);
+  XCTAssertNil([dict objectForKey:31ULL]);
+  XCTAssertNil([dict objectForKey:32ULL]);
+  XCTAssertNil([dict objectForKey:33ULL]);
+  XCTAssertNil([dict objectForKey:34ULL]);
+  [dict release];
+}
+
+- (void)testInplaceMutation {
+  const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
+                                          forKeys:kKeys
+                                            count:GPBARRAYSIZE(kObjects)];
+  XCTAssertNotNil(dict);
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl");
+
+  [dict setObject:@"jkl" forKey:31ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl");
+
+  [dict setObject:@"def" forKey:34ULL];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"def");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"def");
+
+  const uint64_t kKeys2[] = { 32ULL, 33ULL };
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
+      [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
+                                                 forKeys:kKeys2
+                                                   count:GPBARRAYSIZE(kObjects2)];
+  XCTAssertNotNil(dict2);
+  [dict addEntriesFromDictionary:dict2];
+  XCTAssertEqual(dict.count, 4U);
+  XCTAssertEqualObjects([dict objectForKey:31ULL], @"jkl");
+  XCTAssertEqualObjects([dict objectForKey:32ULL], @"ghi");
+  XCTAssertEqualObjects([dict objectForKey:33ULL], @"abc");
+  XCTAssertEqualObjects([dict objectForKey:34ULL], @"def");
+
+  [dict2 release];
+  [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests.pddm b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests.pddm
new file mode 100644
index 0000000..0951294
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBDictionaryTests.pddm
@@ -0,0 +1,1047 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+//%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, NSString*, @"abc", @"def", @"ghi", @"jkl")
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt32, uint32_t, , 100U, 101U, 102U, 103U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int32, int32_t, , 200, 201, 202, 203)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt64, uint64_t, , 300U, 301U, 302U, 303U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int64, int64_t, , 400, 401, 402, 403)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Bool, BOOL, , YES, YES, NO, NO)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Float, float, , 500.f, 501.f, 502.f, 503.f)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Double, double, , 600., 601., 602., 603.)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, Raw, 700, 701, 702, 703)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, , value, POD, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, , VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary<VALUE_TYPE>
+
+//%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
+//%    #pragma unused(aKey, a##VNAME$u, stop)
+//%    XCTFail(@"Shouldn't get here!");
+//%  }];
+//%  [dict release];
+//%}
+//%
+//%- (void)testOne {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
+//%    XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//%    XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
+//%    XCTAssertNotEqual(stop, NULL);
+//%  }];
+//%}
+//%
+//%- (void)testBasics {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//%  __block NSUInteger idx = 0;
+//%  KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//%  VALUE_TYPE *seen##VNAME$u##s = malloc(3 * sizeof(VALUE_TYPE));
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
+//%    XCTAssertLessThan(idx, 3U);
+//%    seenKeys[idx] = aKey;
+//%    seen##VNAME$u##s[idx] = a##VNAME$u##;
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx;
+//%  }];
+//%  for (int i = 0; i < 3; ++i) {
+//%    BOOL foundKey = NO;
+//%    for (int j = 0; (j < 3) && !foundKey; ++j) {
+//%      if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//%        foundKey = YES;
+//%        XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
+//%      }
+//%    }
+//%    XCTAssertTrue(foundKey, @"i = %d", i);
+//%  }
+//%  free(seenKeys);
+//%  free(seen##VNAME$u##s);
+//%
+//%  // Stopping the enumeration.
+//%  idx = 0;
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
+//%    #pragma unused(aKey, a##VNAME$u)
+//%    if (idx == 1) *stop = YES;
+//%    XCTAssertNotEqual(idx, 2U);
+//%    ++idx;
+//%  }];
+//%  [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//%  const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
+//%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
+//%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict1);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict1prime);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
+//%  XCTAssertNotNil(dict2);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict3);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
+//%  XCTAssertNotNil(dict4);
+//%
+//%  // 1/1Prime should be different objects, but equal.
+//%  XCTAssertNotEqual(dict1, dict1prime);
+//%  XCTAssertEqualObjects(dict1, dict1prime);
+//%  // Equal, so they must have same hash.
+//%  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//%  // 2 is same keys, different ##VNAME##s; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//%  // 3 is different keys, same ##VNAME##s; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//%  // 4 extra pair; not equal
+//%  XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//%  [dict1 release];
+//%  [dict1prime release];
+//%  [dict2 release];
+//%  [dict3 release];
+//%  [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new object but equal.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//%  XCTAssertNotNil(dict);
+//%
+//%  XCTAssertEqual(dict.count, 0U);
+//%  [dict set##VNAME$u##:VAL1 forKey:KEY1];
+//%  XCTAssertEqual(dict.count, 1U);
+//%
+//%  const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
+//%  [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 4U);
+//%
+//%  [dict remove##VNAME$u##ForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
+//%
+//%  // Remove again does nothing.
+//%  [dict remove##VNAME$u##ForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
+//%
+//%  [dict remove##VNAME$u##ForKey:KEY4];
+//%  XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//%  [dict removeAll];
+//%  XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%  [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
+//%
+//%  [dict set##VNAME$u##:VAL4 forKey:KEY1];
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL4)
+//%
+//%  [dict set##VNAME$u##:VAL2 forKey:KEY4];
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL2)
+//%
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL3)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY3, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY4, VAL2)
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
+//%
+//%- (void)testRawBasics {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 3U);
+//%  XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue);  // Pointer comparison
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%RAW_VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//%  __block NSUInteger idx = 0;
+//%  KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//%  VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
+//%  [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//%    XCTAssertLessThan(idx, 3U);
+//%    seenKeys[idx] = aKey;
+//%    seenValues[idx] = aValue;
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx;
+//%  }];
+//%  for (int i = 0; i < 3; ++i) {
+//%    BOOL foundKey = NO;
+//%    for (int j = 0; (j < 3) && !foundKey; ++j) {
+//%      if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//%        foundKey = YES;
+//%        if (i == 1) {
+//%          XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+//%        } else {
+//%          XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//%        }
+//%      }
+//%    }
+//%    XCTAssertTrue(foundKey, @"i = %d", i);
+//%  }
+//%  idx = 0;
+//%  [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//%    XCTAssertLessThan(idx, 3U);
+//%    seenKeys[idx] = aKey;
+//%    seenValues[idx] = aValue;
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx;
+//%  }];
+//%  for (int i = 0; i < 3; ++i) {
+//%    BOOL foundKey = NO;
+//%    for (int j = 0; (j < 3) && !foundKey; ++j) {
+//%      if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//%        foundKey = YES;
+//%        XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//%      }
+//%    }
+//%    XCTAssertTrue(foundKey, @"i = %d", i);
+//%  }
+//%  free(seenKeys);
+//%  free(seenValues);
+//%
+//%  // Stopping the enumeration.
+//%  idx = 0;
+//%  [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//%    #pragma unused(aKey, aValue)
+//%    if (idx == 1) *stop = YES;
+//%    XCTAssertNotEqual(idx, 2U);
+//%    ++idx;
+//%  }];
+//%  [dict release];
+//%}
+//%
+//%- (void)testEqualityWithUnknowns {
+//%  const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//%  const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 };  // Unknown
+//%  const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 };  // Unknown
+//%  const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertNotNil(dict1);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertNotNil(dict1prime);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues2)];
+//%  XCTAssertNotNil(dict2);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
+//%  XCTAssertNotNil(dict3);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues3
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues3)];
+//%  XCTAssertNotNil(dict4);
+//%
+//%  // 1/1Prime should be different objects, but equal.
+//%  XCTAssertNotEqual(dict1, dict1prime);
+//%  XCTAssertEqualObjects(dict1, dict1prime);
+//%  // Equal, so they must have same hash.
+//%  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//%  // 2 is same keys, different values; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//%  // 3 is different keys, same values; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//%  // 4 extra pair; not equal
+//%  XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//%  [dict1 release];
+//%  [dict1prime release];
+//%  [dict2 release];
+//%  [dict3 release];
+//%  [dict4 release];
+//%}
+//%
+//%- (void)testCopyWithUnknowns {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknown
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+//%  XCTAssertEqualObjects(dict, dict2);
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+//%  [dict release];
+//%}
+//%
+//%- (void)testUnknownAdds {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%    [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+//%  XCTAssertNotNil(dict);
+//%
+//%  XCTAssertEqual(dict.count, 0U);
+//%  XCTAssertThrowsSpecificNamed([dict setValue:VAL2 forKey:KEY2],  // Unknown
+//%                               NSException, NSInvalidArgumentException);
+//%  XCTAssertEqual(dict.count, 0U);
+//%  [dict setRawValue:VAL2 forKey:KEY2];  // Unknown
+//%  XCTAssertEqual(dict.count, 1U);
+//%
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 };  // Unknown
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                        forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                          count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict addRawEntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%  [dict2 release];
+//%}
+//%
+//%- (void)testUnknownRemove {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 4U);
+//%
+//%  [dict removeValueForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//%  // Remove again does nothing.
+//%  [dict removeValueForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//%  [dict removeValueForKey:KEY4];
+//%  XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//%  [dict removeAll];
+//%  XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%  [dict release];
+//%}
+//%
+//%- (void)testInplaceMutationUnknowns {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//%  XCTAssertThrowsSpecificNamed([dict setValue:VAL4 forKey:KEY1],  // Unknown
+//%                               NSException, NSInvalidArgumentException);
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//%  [dict setRawValue:VAL4 forKey:KEY1];  // Unknown
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//%  [dict setRawValue:VAL1 forKey:KEY4];
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//%  const VALUE_TYPE kValues2[] = { VAL3, VAL2 };  // Unknown
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues2)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict addRawEntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%- (void)testCopyUnknowns {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
+//%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  XCTAssertEqual(dict.validationFunc, dict2.validationFunc);  // Pointer comparison
+//%  XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%@end
+//%
+
+//
+// Helpers for PODs
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
+//%  VALUE_TYPE NAME;
+//%
+//%PDDM-DEFINE VALUE_NOT_FOUNDPOD(DICT, KEY)
+//%  XCTAssertFalse([DICT valueForKey:KEY value:NULL]);
+//%PDDM-DEFINE TEST_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//%  XCTAssertTrue([DICT valueForKey:KEY value:NULL]);
+//%  XCTAssertTrue([DICT valueForKey:KEY value:&STORAGE]);
+//%  XCTAssertEqual(STORAGE, VALUE);
+//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
+//%KEY1 == KEY2
+//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(DICT, KEY)
+//%  XCTAssertFalse([DICT valueForKey:KEY rawValue:NULL]);
+//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//%  XCTAssertTrue([DICT valueForKey:KEY rawValue:NULL]);
+//%  XCTAssertTrue([DICT valueForKey:KEY rawValue:&STORAGE]);
+//%  XCTAssertEqual(STORAGE, VALUE);
+
+//
+// Helpers for Objects
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
+// Empty
+//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(DICT, KEY)
+//%  XCTAssertNil([DICT objectForKey:KEY]);
+//%PDDM-DEFINE TEST_VALUEOBJECT(DICT, STORAGE, KEY, VALUE)
+//%  XCTAssertEqualObjects([DICT objectForKey:KEY], VALUE);
+//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
+//%[KEY1 isEqual:KEY2]
+
+//
+// Helpers for tests.
+//
+
+//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%// To let the testing macros work, add some extra methods to simplify things.
+//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%- (instancetype)initWithValues:(const int32_t [])values
+//%                       forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                         count:(NSUInteger)count;
+//%@end
+//%
+//%static BOOL TestingEnum_IsValidValue(int32_t value) {
+//%  switch (value) {
+//%    case 700:
+//%    case 701:
+//%    case 702:
+//%    case 703:
+//%      return YES;
+//%    default:
+//%      return NO;
+//%  }
+//%}
+//%
+//%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//%  // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+//%  // type correct.
+//%  return [[(GPB##KEY_NAME##EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//%                KEY_NAME$S                                             rawValues:&value
+//%                KEY_NAME$S                                               forKeys:&key
+//%                KEY_NAME$S                                                 count:1] autorelease];
+//%}
+//%- (instancetype)initWithValues:(const int32_t [])values
+//%                       forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//%                         count:(NSUInteger)count {
+//%  return [self initWithValidationFunction:TestingEnum_IsValidValue
+//%                                rawValues:values
+//%                                  forKeys:keys
+//%                                    count:count];
+//%}
+//%@end
+//%
+//%
+
+
+//
+// BOOL test macros
+//
+//TODO(thomasvl): enum tests
+
+//%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , value, POD, VAL1, VAL2)
+
+//%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, VAL1, VAL2)
+
+//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VAL1, VAL2)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
+//%    #pragma unused(aKey, a##VNAME$u##, stop)
+//%    XCTFail(@"Shouldn't get here!");
+//%  }];
+//%  [dict release];
+//%}
+//%
+//%- (void)testOne {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
+//%    XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//%    XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1);
+//%    XCTAssertNotEqual(stop, NULL);
+//%  }];
+//%}
+//%
+//%- (void)testBasics {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%
+//%  __block NSUInteger idx = 0;
+//%  KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
+//%  VALUE_TYPE *seen##VNAME$u##s = malloc(2 * sizeof(VALUE_TYPE));
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
+//%    XCTAssertLessThan(idx, 2U);
+//%    seenKeys[idx] = aKey;
+//%    seen##VNAME$u##s[idx] = a##VNAME$u;
+//%    XCTAssertNotEqual(stop, NULL);
+//%    ++idx;
+//%  }];
+//%  for (int i = 0; i < 2; ++i) {
+//%    BOOL foundKey = NO;
+//%    for (int j = 0; (j < 2) && !foundKey; ++j) {
+//%      if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//%        foundKey = YES;
+//%        XCTAssertEqual##VSUFFIX(k##VNAME$u##s[i], seen##VNAME$u##s[j], @"i = %d, j = %d", i, j);
+//%      }
+//%    }
+//%    XCTAssertTrue(foundKey, @"i = %d", i);
+//%  }
+//%  free(seenKeys);
+//%  free(seen##VNAME$u##s);
+//%
+//%  // Stopping the enumeration.
+//%  idx = 0;
+//%  [dict enumerateKeysAnd##VNAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
+//%    #pragma unused(aKey, a##VNAME$u)
+//%    if (idx == 0) *stop = YES;
+//%    XCTAssertNotEqual(idx, 2U);
+//%    ++idx;
+//%  }];
+//%  [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//%  const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
+//%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
+//%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict1);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict1prime);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
+//%  XCTAssertNotNil(dict2);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
+//%  XCTAssertNotNil(dict3);
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
+//%  XCTAssertNotNil(dict4);
+//%
+//%  // 1/1Prime should be different objects, but equal.
+//%  XCTAssertNotEqual(dict1, dict1prime);
+//%  XCTAssertEqualObjects(dict1, dict1prime);
+//%  // Equal, so they must have same hash.
+//%  XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//%  // 2 is same keys, different ##VNAME##s; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//%  // 3 is different keys, same ##VNAME##s; not equal.
+//%  XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//%  // 4 Fewer pairs; not equal
+//%  XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//%  [dict1 release];
+//%  [dict1prime release];
+//%  [dict2 release];
+//%  [dict3 release];
+//%  [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new object but equal.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//%  XCTAssertNotNil(dict2);
+//%
+//%  // Should be new pointer, but equal objects.
+//%  XCTAssertNotEqual(dict, dict2);
+//%  XCTAssertEqualObjects(dict, dict2);
+//%  [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//%  XCTAssertNotNil(dict);
+//%
+//%  XCTAssertEqual(dict.count, 0U);
+//%  [dict set##VNAME$u:VAL1 forKey:KEY1];
+//%  XCTAssertEqual(dict.count, 1U);
+//%
+//%  const KEY_TYPE KisP##kKeys[] = { KEY2 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict addEntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 2U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%  [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 2U);
+//%
+//%  [dict remove##VNAME$u##ForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//%  // Remove again does nothing.
+//%  [dict remove##VNAME$u##ForKey:KEY2];
+//%  XCTAssertEqual(dict.count, 1U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//%  [dict removeAll];
+//%  XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%  [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
+//%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
+//%  XCTAssertNotNil(dict);
+//%  XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%
+//%  [dict set##VNAME$u##:VAL2 forKey:KEY1];
+//%  XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%
+//%  [dict set##VNAME$u##:VAL1 forKey:KEY2];
+//%  XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL1)
+//%
+//%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
+//%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
+//%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
+//%  XCTAssertNotNil(dict2);
+//%  [dict addEntriesFromDictionary:dict2];
+//%  XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, VNAME, KEY2, VAL2)
+//%
+//%  [dict2 release];
+//%  [dict release];
+//%}
+//%
+//%@end
+//%
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Merge.m b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Merge.m
new file mode 100644
index 0000000..c0bd589
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Merge.m
@@ -0,0 +1,700 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageMergeTests : GPBTestCase
+@end
+
+@implementation MessageMergeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are merge specific.
+
+- (void)testProto3MergingAndZeroValues {
+  // Proto2 covered in other tests.
+
+  Message3 *src = [[Message3 alloc] init];
+  Message3 *dst = [[Message3 alloc] init];
+  NSData *testData1 = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
+  NSData *testData2 = [@"def" dataUsingEncoding:NSUTF8StringEncoding];
+
+  dst.optionalInt32 = 1;
+  dst.optionalInt64 = 1;
+  dst.optionalUint32 = 1;
+  dst.optionalUint64 = 1;
+  dst.optionalSint32 = 1;
+  dst.optionalSint64 = 1;
+  dst.optionalFixed32 = 1;
+  dst.optionalFixed64 = 1;
+  dst.optionalSfixed32 = 1;
+  dst.optionalSfixed64 = 1;
+  dst.optionalFloat = 1.0f;
+  dst.optionalDouble = 1.0;
+  dst.optionalBool = YES;
+  dst.optionalString = @"bar";
+  dst.optionalBytes = testData1;
+  dst.optionalEnum = Message3_Enum_Bar;
+
+  // All zeros, nothing should overright.
+
+  src.optionalInt32 = 0;
+  src.optionalInt64 = 0;
+  src.optionalUint32 = 0;
+  src.optionalUint64 = 0;
+  src.optionalSint32 = 0;
+  src.optionalSint64 = 0;
+  src.optionalFixed32 = 0;
+  src.optionalFixed64 = 0;
+  src.optionalSfixed32 = 0;
+  src.optionalSfixed64 = 0;
+  src.optionalFloat = 0.0f;
+  src.optionalDouble = 0.0;
+  src.optionalBool = NO;
+  src.optionalString = @"";
+  src.optionalBytes = [NSData data];
+  src.optionalEnum = Message3_Enum_Foo;  // first value
+
+  [dst mergeFrom:src];
+
+  XCTAssertEqual(dst.optionalInt32, 1);
+  XCTAssertEqual(dst.optionalInt64, 1);
+  XCTAssertEqual(dst.optionalUint32, 1U);
+  XCTAssertEqual(dst.optionalUint64, 1U);
+  XCTAssertEqual(dst.optionalSint32, 1);
+  XCTAssertEqual(dst.optionalSint64, 1);
+  XCTAssertEqual(dst.optionalFixed32, 1U);
+  XCTAssertEqual(dst.optionalFixed64, 1U);
+  XCTAssertEqual(dst.optionalSfixed32, 1);
+  XCTAssertEqual(dst.optionalSfixed64, 1);
+  XCTAssertEqual(dst.optionalFloat, 1.0f);
+  XCTAssertEqual(dst.optionalDouble, 1.0);
+  XCTAssertEqual(dst.optionalBool, YES);
+  XCTAssertEqualObjects(dst.optionalString, @"bar");
+  XCTAssertEqualObjects(dst.optionalBytes, testData1);
+  XCTAssertEqual(dst.optionalEnum, Message3_Enum_Bar);
+
+  // Half the values that will replace.
+
+  src.optionalInt32 = 0;
+  src.optionalInt64 = 2;
+  src.optionalUint32 = 0;
+  src.optionalUint64 = 2;
+  src.optionalSint32 = 0;
+  src.optionalSint64 = 2;
+  src.optionalFixed32 = 0;
+  src.optionalFixed64 = 2;
+  src.optionalSfixed32 = 0;
+  src.optionalSfixed64 = 2;
+  src.optionalFloat = 0.0f;
+  src.optionalDouble = 2.0;
+  src.optionalBool = YES;  // No other value to use.  :(
+  src.optionalString = @"baz";
+  src.optionalBytes = nil;
+  src.optionalEnum = Message3_Enum_Baz;
+
+  [dst mergeFrom:src];
+
+  XCTAssertEqual(dst.optionalInt32, 1);
+  XCTAssertEqual(dst.optionalInt64, 2);
+  XCTAssertEqual(dst.optionalUint32, 1U);
+  XCTAssertEqual(dst.optionalUint64, 2U);
+  XCTAssertEqual(dst.optionalSint32, 1);
+  XCTAssertEqual(dst.optionalSint64, 2);
+  XCTAssertEqual(dst.optionalFixed32, 1U);
+  XCTAssertEqual(dst.optionalFixed64, 2U);
+  XCTAssertEqual(dst.optionalSfixed32, 1);
+  XCTAssertEqual(dst.optionalSfixed64, 2);
+  XCTAssertEqual(dst.optionalFloat, 1.0f);
+  XCTAssertEqual(dst.optionalDouble, 2.0);
+  XCTAssertEqual(dst.optionalBool, YES);
+  XCTAssertEqualObjects(dst.optionalString, @"baz");
+  XCTAssertEqualObjects(dst.optionalBytes, testData1);
+  XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+  // Other half the values that will replace.
+
+  src.optionalInt32 = 3;
+  src.optionalInt64 = 0;
+  src.optionalUint32 = 3;
+  src.optionalUint64 = 0;
+  src.optionalSint32 = 3;
+  src.optionalSint64 = 0;
+  src.optionalFixed32 = 3;
+  src.optionalFixed64 = 0;
+  src.optionalSfixed32 = 3;
+  src.optionalSfixed64 = 0;
+  src.optionalFloat = 3.0f;
+  src.optionalDouble = 0.0;
+  src.optionalBool = YES;  // No other value to use.  :(
+  src.optionalString = nil;
+  src.optionalBytes = testData2;
+  src.optionalEnum = Message3_Enum_Foo;
+
+  [dst mergeFrom:src];
+
+  XCTAssertEqual(dst.optionalInt32, 3);
+  XCTAssertEqual(dst.optionalInt64, 2);
+  XCTAssertEqual(dst.optionalUint32, 3U);
+  XCTAssertEqual(dst.optionalUint64, 2U);
+  XCTAssertEqual(dst.optionalSint32, 3);
+  XCTAssertEqual(dst.optionalSint64, 2);
+  XCTAssertEqual(dst.optionalFixed32, 3U);
+  XCTAssertEqual(dst.optionalFixed64, 2U);
+  XCTAssertEqual(dst.optionalSfixed32, 3);
+  XCTAssertEqual(dst.optionalSfixed64, 2);
+  XCTAssertEqual(dst.optionalFloat, 3.0f);
+  XCTAssertEqual(dst.optionalDouble, 2.0);
+  XCTAssertEqual(dst.optionalBool, YES);
+  XCTAssertEqualObjects(dst.optionalString, @"baz");
+  XCTAssertEqualObjects(dst.optionalBytes, testData2);
+  XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+  [src release];
+  [dst release];
+}
+
+- (void)testProto3MergingEnums {
+  UnknownEnumsMyMessage *src = [UnknownEnumsMyMessage message];
+  UnknownEnumsMyMessage *dst = [UnknownEnumsMyMessage message];
+
+  // Known value.
+
+  src.e = UnknownEnumsMyEnum_Bar;
+  src.repeatedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                       rawValue:UnknownEnumsMyEnum_Bar];
+  src.repeatedPackedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                       rawValue:UnknownEnumsMyEnum_Bar];
+  src.oneofE1 = UnknownEnumsMyEnum_Bar;
+
+  [dst mergeFrom:src];
+
+  XCTAssertEqual(dst.e, UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual(dst.repeatedEArray.count, 1U);
+  XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual(dst.repeatedPackedEArray.count, 1U);
+  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual(dst.oneofE1, UnknownEnumsMyEnum_Bar);
+
+  // Unknown value.
+
+  const int32_t kUnknownValue = 666;
+
+  SetUnknownEnumsMyMessage_E_RawValue(src, kUnknownValue);
+  src.repeatedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                       rawValue:kUnknownValue];
+  src.repeatedPackedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                       rawValue:kUnknownValue];
+  SetUnknownEnumsMyMessage_OneofE1_RawValue(src, kUnknownValue);
+
+  [dst mergeFrom:src];
+
+  XCTAssertEqual(dst.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(dst), kUnknownValue);
+  XCTAssertEqual(dst.repeatedEArray.count, 2U);
+  XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual([dst.repeatedEArray valueAtIndex:1],
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([dst.repeatedEArray rawValueAtIndex:1], kUnknownValue);
+  XCTAssertEqual(dst.repeatedPackedEArray.count, 2U);
+  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:1],
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([dst.repeatedPackedEArray rawValueAtIndex:1], kUnknownValue);
+  XCTAssertEqual(dst.oneofE1,
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(dst), kUnknownValue);
+}
+
+- (void)testProto2MergeOneof {
+  Message2 *src = [Message2 message];
+  Message2 *dst = [Message2 message];
+
+  //
+  // Make sure whatever is in dst gets cleared out be merging in something else.
+  //
+
+  dst.oneofEnum = Message2_Enum_Bar;
+
+//%PDDM-DEFINE MERGE2_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//%  src.oneof##SET_NAME = SET_VALUE;
+//%  [dst mergeFrom:src];
+//%  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_Oneof##SET_NAME);
+//%  XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//%  XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE2_TEST(Int32, 10, Enum, Message2_Enum_Baz)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofInt32 = 10;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+  XCTAssertEqual(dst.oneofInt32, 10);
+  XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+//%PDDM-EXPAND MERGE2_TEST(Int64, 11, Int32, 100)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofInt64 = 11;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+  XCTAssertEqual(dst.oneofInt64, 11);
+  XCTAssertEqual(dst.oneofInt32, 100);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint32, 12U, Int64, 101)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofUint32 = 12U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+  XCTAssertEqual(dst.oneofUint32, 12U);
+  XCTAssertEqual(dst.oneofInt64, 101);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint64, 13U, Uint32, 102U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofUint64 = 13U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+  XCTAssertEqual(dst.oneofUint64, 13U);
+  XCTAssertEqual(dst.oneofUint32, 102U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint32, 14, Uint64, 103U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSint32 = 14;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+  XCTAssertEqual(dst.oneofSint32, 14);
+  XCTAssertEqual(dst.oneofUint64, 103U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint64, 15, Sint32, 104)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSint64 = 15;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+  XCTAssertEqual(dst.oneofSint64, 15);
+  XCTAssertEqual(dst.oneofSint32, 104);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed32, 16U, Sint64, 105)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFixed32 = 16U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+  XCTAssertEqual(dst.oneofFixed32, 16U);
+  XCTAssertEqual(dst.oneofSint64, 105);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed64, 17U, Fixed32, 106U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFixed64 = 17U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+  XCTAssertEqual(dst.oneofFixed64, 17U);
+  XCTAssertEqual(dst.oneofFixed32, 106U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed32, 18, Fixed64, 107U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSfixed32 = 18;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+  XCTAssertEqual(dst.oneofSfixed32, 18);
+  XCTAssertEqual(dst.oneofFixed64, 107U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed64, 19, Sfixed32, 108)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSfixed64 = 19;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+  XCTAssertEqual(dst.oneofSfixed64, 19);
+  XCTAssertEqual(dst.oneofSfixed32, 108);
+
+//%PDDM-EXPAND MERGE2_TEST(Float, 20.0f, Sfixed64, 109)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFloat = 20.0f;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+  XCTAssertEqual(dst.oneofFloat, 20.0f);
+  XCTAssertEqual(dst.oneofSfixed64, 109);
+
+//%PDDM-EXPAND MERGE2_TEST(Double, 21.0, Float, 110.0f)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofDouble = 21.0;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+  XCTAssertEqual(dst.oneofDouble, 21.0);
+  XCTAssertEqual(dst.oneofFloat, 110.0f);
+
+//%PDDM-EXPAND MERGE2_TEST(Bool, NO, Double, 111.0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofBool = NO;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+  XCTAssertEqual(dst.oneofBool, NO);
+  XCTAssertEqual(dst.oneofDouble, 111.0);
+
+//%PDDM-EXPAND MERGE2_TEST(Enum, Message2_Enum_Bar, Bool, YES)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofEnum = Message2_Enum_Bar;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+  XCTAssertEqual(dst.oneofEnum, Message2_Enum_Bar);
+  XCTAssertEqual(dst.oneofBool, YES);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+  NSString *oneofStringDefault = @"string";
+  NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+  src.oneofString = @"foo";
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofString);
+  XCTAssertEqualObjects(dst.oneofString, @"foo");
+  XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+  src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+  XCTAssertEqualObjects(dst.oneofBytes,
+                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+  Message2_OneofGroup *group = [Message2_OneofGroup message];
+  group.a = 666;
+  src.oneofGroup = group;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+  Message2_OneofGroup *mergedGroup = [[dst.oneofGroup retain] autorelease];
+  XCTAssertNotNil(mergedGroup);
+  XCTAssertNotEqual(mergedGroup, group);  // Pointer comparision.
+  XCTAssertEqualObjects(mergedGroup, group);
+  XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+  Message2 *subMessage = [Message2 message];
+  subMessage.optionalInt32 = 777;
+  src.oneofMessage = subMessage;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+  Message2 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+  XCTAssertNotNil(mergedSubMessage);
+  XCTAssertNotEqual(mergedSubMessage, subMessage);  // Pointer comparision.
+  XCTAssertEqualObjects(mergedSubMessage, subMessage);
+  XCTAssertNotNil(dst.oneofGroup);
+  XCTAssertNotEqual(dst.oneofGroup, mergedGroup);  // Pointer comparision.
+
+  // Back to something else to make sure message clears out ok.
+
+  src.oneofInt32 = 10;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+  XCTAssertNotNil(dst.oneofMessage);
+  XCTAssertNotEqual(dst.oneofMessage,
+                    mergedSubMessage);  // Pointer comparision.
+
+  //
+  // Test merging in to message/group when they already had something.
+  //
+
+  src.oneofGroup = group;
+  mergedGroup = [Message2_OneofGroup message];
+  mergedGroup.b = 888;
+  dst.oneofGroup = mergedGroup;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+  // Shouldn't have been a new object.
+  XCTAssertEqual(dst.oneofGroup, mergedGroup);  // Pointer comparision.
+  XCTAssertEqual(dst.oneofGroup.a, 666);        // Pointer comparision.
+  XCTAssertEqual(dst.oneofGroup.b, 888);        // Pointer comparision.
+
+  src.oneofMessage = subMessage;
+  mergedSubMessage = [Message2 message];
+  mergedSubMessage.optionalInt64 = 999;
+  dst.oneofMessage = mergedSubMessage;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+  // Shouldn't have been a new object.
+  XCTAssertEqual(dst.oneofMessage, mergedSubMessage);   // Pointer comparision.
+  XCTAssertEqual(dst.oneofMessage.optionalInt32, 777);  // Pointer comparision.
+  XCTAssertEqual(dst.oneofMessage.optionalInt64, 999);  // Pointer comparision.
+}
+
+- (void)testProto3MergeOneof {
+  Message3 *src = [Message3 message];
+  Message3 *dst = [Message3 message];
+
+  //
+  // Make sure whatever is in dst gets cleared out be merging in something else.
+  //
+
+  dst.oneofEnum = Message3_Enum_Bar;
+
+//%PDDM-DEFINE MERGE3_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//%  src.oneof##SET_NAME = SET_VALUE;
+//%  [dst mergeFrom:src];
+//%  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_Oneof##SET_NAME);
+//%  XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//%  XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE3_TEST(Int32, 10, Enum, Message3_Enum_Foo)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofInt32 = 10;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+  XCTAssertEqual(dst.oneofInt32, 10);
+  XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+//%PDDM-EXPAND MERGE3_TEST(Int64, 11, Int32, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofInt64 = 11;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+  XCTAssertEqual(dst.oneofInt64, 11);
+  XCTAssertEqual(dst.oneofInt32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint32, 12U, Int64, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofUint32 = 12U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+  XCTAssertEqual(dst.oneofUint32, 12U);
+  XCTAssertEqual(dst.oneofInt64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint64, 13U, Uint32, 0U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofUint64 = 13U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+  XCTAssertEqual(dst.oneofUint64, 13U);
+  XCTAssertEqual(dst.oneofUint32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint32, 14, Uint64, 0U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSint32 = 14;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+  XCTAssertEqual(dst.oneofSint32, 14);
+  XCTAssertEqual(dst.oneofUint64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint64, 15, Sint32, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSint64 = 15;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+  XCTAssertEqual(dst.oneofSint64, 15);
+  XCTAssertEqual(dst.oneofSint32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed32, 16U, Sint64, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFixed32 = 16U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+  XCTAssertEqual(dst.oneofFixed32, 16U);
+  XCTAssertEqual(dst.oneofSint64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed64, 17U, Fixed32, 0U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFixed64 = 17U;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+  XCTAssertEqual(dst.oneofFixed64, 17U);
+  XCTAssertEqual(dst.oneofFixed32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed32, 18, Fixed64, 0U)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSfixed32 = 18;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+  XCTAssertEqual(dst.oneofSfixed32, 18);
+  XCTAssertEqual(dst.oneofFixed64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed64, 19, Sfixed32, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofSfixed64 = 19;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+  XCTAssertEqual(dst.oneofSfixed64, 19);
+  XCTAssertEqual(dst.oneofSfixed32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Float, 20.0f, Sfixed64, 0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofFloat = 20.0f;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+  XCTAssertEqual(dst.oneofFloat, 20.0f);
+  XCTAssertEqual(dst.oneofSfixed64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Double, 21.0, Float, 0.0f)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofDouble = 21.0;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+  XCTAssertEqual(dst.oneofDouble, 21.0);
+  XCTAssertEqual(dst.oneofFloat, 0.0f);
+
+//%PDDM-EXPAND MERGE3_TEST(Bool, YES, Double, 0.0)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofBool = YES;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+  XCTAssertEqual(dst.oneofBool, YES);
+  XCTAssertEqual(dst.oneofDouble, 0.0);
+
+//%PDDM-EXPAND MERGE3_TEST(Enum, Message3_Enum_Bar, Bool, NO)
+// This block of code is generated, do not edit it directly.
+
+  src.oneofEnum = Message3_Enum_Bar;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+  XCTAssertEqual(dst.oneofEnum, Message3_Enum_Bar);
+  XCTAssertEqual(dst.oneofBool, NO);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+  NSString *oneofStringDefault = @"";
+  NSData *oneofBytesDefault = [NSData data];
+
+  src.oneofString = @"foo";
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofString);
+  XCTAssertEqualObjects(dst.oneofString, @"foo");
+  XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+  src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+  XCTAssertEqualObjects(dst.oneofBytes,
+                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+
+  Message3 *subMessage = [Message3 message];
+  subMessage.optionalInt32 = 777;
+  src.oneofMessage = subMessage;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+  Message3 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+  XCTAssertNotNil(mergedSubMessage);
+  XCTAssertNotEqual(mergedSubMessage, subMessage);  // Pointer comparision.
+  XCTAssertEqualObjects(mergedSubMessage, subMessage);
+  XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+  // Back to something else to make sure message clears out ok.
+
+  src.oneofInt32 = 10;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+  XCTAssertNotNil(dst.oneofMessage);
+  XCTAssertNotEqual(dst.oneofMessage,
+                    mergedSubMessage);  // Pointer comparision.
+
+  //
+  // Test merging in to message when they already had something.
+  //
+
+  src.oneofMessage = subMessage;
+  mergedSubMessage = [Message3 message];
+  mergedSubMessage.optionalInt64 = 999;
+  dst.oneofMessage = mergedSubMessage;
+  [dst mergeFrom:src];
+  XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+  // Shouldn't have been a new object.
+  XCTAssertEqual(dst.oneofMessage, mergedSubMessage);   // Pointer comparision.
+  XCTAssertEqual(dst.oneofMessage.optionalInt32, 777);  // Pointer comparision.
+  XCTAssertEqual(dst.oneofMessage.optionalInt64, 999);  // Pointer comparision.
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, CopyFromMessageMap)
+- (void)testMap_CopyFromMessageMap {
+  TestMessageMap *msg1 = [[TestMessageMap alloc] init];
+  TestMessageMap *msg2 = [[TestMessageMap alloc] init];
+
+  TestAllTypes *subMsg = [TestAllTypes message];
+  subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:100];
+  [msg1.mapInt32Message setObject:subMsg forKey:0];
+  subMsg = nil;
+
+  subMsg = [TestAllTypes message];
+  subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:101];
+
+  [msg2.mapInt32Message setObject:subMsg forKey:0];
+  subMsg = nil;
+
+  [msg1 mergeFrom:msg2];
+
+  // Checks repeated field is overwritten.
+  XCTAssertEqual(msg1.mapInt32Message.count, 1U);
+  subMsg = [msg1.mapInt32Message objectForKey:0];
+  XCTAssertNotNil(subMsg);
+  XCTAssertEqual(subMsg.repeatedInt32Array.count, 1U);
+  XCTAssertEqual([subMsg.repeatedInt32Array valueAtIndex:0], 101);
+
+  [msg2 release];
+  [msg1 release];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Runtime.m b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Runtime.m
new file mode 100644
index 0000000..5e19771
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -0,0 +1,2090 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageRuntimeTests : GPBTestCase
+@end
+
+@implementation MessageRuntimeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime
+// specific.
+
+- (void)testStartupOrdering {
+  // Just have to create a message.  Nothing else uses the classes from
+  // this file, so the first selector invoked on the class will initialize
+  // it, which also initializes the root.
+  TestObjCStartupMessage *message = [TestObjCStartupMessage message];
+  XCTAssertNotNil(message);
+}
+
+- (void)testProto2HasMethodSupport {
+  NSArray *names = @[
+    @"Int32",
+    @"Int64",
+    @"Uint32",
+    @"Uint64",
+    @"Sint32",
+    @"Sint64",
+    @"Fixed32",
+    @"Fixed64",
+    @"Sfixed32",
+    @"Sfixed64",
+    @"Float",
+    @"Double",
+    @"Bool",
+    @"String",
+    @"Bytes",
+    @"Group",
+    @"Message",
+    @"Enum",
+  ];
+
+  // Proto2 gets:
+
+  // Single fields - has*/setHas* is valid.
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasOptional%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasOptional%@:", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                  name);
+    XCTAssertTrue([Message2 instancesRespondToSelector:setHasSel], @"field: %@",
+                  name);
+  }
+
+  // Repeated fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - repeatedInt32Array_Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
+  }
+
+  // OneOf fields - no has*/setHas*
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+    SEL hasSel =
+        NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasOneof%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+  }
+
+  // map<> fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  NSArray *mapNames = @[
+    @"Int32Int32",
+    @"Int64Int64",
+    @"Uint32Uint32",
+    @"Uint64Uint64",
+    @"Sint32Sint32",
+    @"Sint64Sint64",
+    @"Fixed32Fixed32",
+    @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32",
+    @"Sfixed64Sfixed64",
+    @"Int32Float",
+    @"Int32Double",
+    @"BoolBool",
+    @"StringString",
+    @"StringBytes",
+    @"StringMessage",
+    @"Int32Bytes",
+    @"Int32Enum",
+    @"Int32Message",
+  ];
+
+  for (NSString *name in mapNames) {
+    // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - mapInt32Int32Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
+  }
+
+}
+
+- (void)testProto3HasMethodSupport {
+  NSArray *names = @[
+    @"Int32",
+    @"Int64",
+    @"Uint32",
+    @"Uint64",
+    @"Sint32",
+    @"Sint64",
+    @"Fixed32",
+    @"Fixed64",
+    @"Sfixed32",
+    @"Sfixed64",
+    @"Float",
+    @"Double",
+    @"Bool",
+    @"String",
+    @"Bytes",
+    @"Message",
+    @"Enum",
+  ];
+
+  // Proto3 gets:
+
+  // Single fields
+  //  - has*/setHas* invalid for primative types.
+  //  - has*/setHas* valid for Message.
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasOptional%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasOptional%@:", name]);
+    if ([name isEqual:@"Message"]) {
+      // Sub messages/groups are the exception.
+      XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+                    name);
+      XCTAssertTrue([Message3 instancesRespondToSelector:setHasSel],
+                    @"field: %@", name);
+    } else {
+      XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+                     name);
+      XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+                     @"field: %@", name);
+    }
+  }
+
+  // Repeated fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
+    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - repeatedInt32Array_Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                  name);
+  }
+
+  // OneOf fields - no has*/setHas*
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+    SEL hasSel =
+        NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasOneof%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+  }
+
+  // map<> fields
+  //  - no has*/setHas*
+  //  - *Count
+
+  NSArray *mapNames = @[
+    @"Int32Int32",
+    @"Int64Int64",
+    @"Uint32Uint32",
+    @"Uint64Uint64",
+    @"Sint32Sint32",
+    @"Sint64Sint64",
+    @"Fixed32Fixed32",
+    @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32",
+    @"Sfixed64Sfixed64",
+    @"Int32Float",
+    @"Int32Double",
+    @"BoolBool",
+    @"StringString",
+    @"StringBytes",
+    @"StringMessage",
+    @"Int32Bytes",
+    @"Int32Enum",
+    @"Int32Message",
+  ];
+
+  for (NSString *name in mapNames) {
+    // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+                   name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+                   @"field: %@", name);
+    // build the selector, i.e. - mapInt32Int32Count
+    SEL countSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
+                   name);
+  }
+}
+
+- (void)testProto2SingleFieldHasBehavior {
+  //
+  // Setting to any value including the default value (0) should result has*
+  // being true.
+  //
+
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//%  {  // optional##FIELD :: NON_ZERO_VALUE
+//%    Message2 *msg = [[Message2 alloc] init];
+//%    XCTAssertFalse(msg.hasOptional##FIELD);
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = NON_ZERO_VALUE;
+//%    XCTAssertTrue(msg.hasOptional##FIELD);
+//%    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//%    [msg release];
+//%  }
+//%  {  // optional##FIELD :: ZERO_VALUE
+//%    Message2 *msg = [[Message2 alloc] init];
+//%    XCTAssertFalse(msg.hasOptional##FIELD);
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = ZERO_VALUE;
+//%    XCTAssertTrue(msg.hasOptional##FIELD);
+//%    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//%    [msg release];
+//%  }
+//%
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELDS()
+//%PROTO2_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO2_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO2_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO2_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO2_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//%  //
+//%  // Test doesn't apply to optionalGroup/optionalMessage.
+//%  //
+//%
+//%PROTO2_TEST_HAS_FIELD(Enum, Message2_Enum_Bar, Message2_Enum_Foo)
+//%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+  {  // optionalInt32 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalInt32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 1;
+    XCTAssertTrue(msg.hasOptionalInt32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+    [msg release];
+  }
+  {  // optionalInt32 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalInt32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 0;
+    XCTAssertTrue(msg.hasOptionalInt32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+    [msg release];
+  }
+
+  {  // optionalInt64 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalInt64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 1;
+    XCTAssertTrue(msg.hasOptionalInt64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+    [msg release];
+  }
+  {  // optionalInt64 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalInt64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 0;
+    XCTAssertTrue(msg.hasOptionalInt64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+    [msg release];
+  }
+
+  {  // optionalUint32 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalUint32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 1;
+    XCTAssertTrue(msg.hasOptionalUint32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+    [msg release];
+  }
+  {  // optionalUint32 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalUint32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 0;
+    XCTAssertTrue(msg.hasOptionalUint32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+    [msg release];
+  }
+
+  {  // optionalUint64 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalUint64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 1;
+    XCTAssertTrue(msg.hasOptionalUint64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+    [msg release];
+  }
+  {  // optionalUint64 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalUint64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 0;
+    XCTAssertTrue(msg.hasOptionalUint64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+    [msg release];
+  }
+
+  {  // optionalSint32 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSint32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 1;
+    XCTAssertTrue(msg.hasOptionalSint32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+    [msg release];
+  }
+  {  // optionalSint32 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSint32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 0;
+    XCTAssertTrue(msg.hasOptionalSint32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+    [msg release];
+  }
+
+  {  // optionalSint64 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSint64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 1;
+    XCTAssertTrue(msg.hasOptionalSint64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+    [msg release];
+  }
+  {  // optionalSint64 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSint64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 0;
+    XCTAssertTrue(msg.hasOptionalSint64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+    [msg release];
+  }
+
+  {  // optionalFixed32 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFixed32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 1;
+    XCTAssertTrue(msg.hasOptionalFixed32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+    [msg release];
+  }
+  {  // optionalFixed32 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFixed32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 0;
+    XCTAssertTrue(msg.hasOptionalFixed32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+    [msg release];
+  }
+
+  {  // optionalFixed64 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFixed64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 1;
+    XCTAssertTrue(msg.hasOptionalFixed64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+    [msg release];
+  }
+  {  // optionalFixed64 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFixed64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 0;
+    XCTAssertTrue(msg.hasOptionalFixed64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+    [msg release];
+  }
+
+  {  // optionalSfixed32 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSfixed32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 1;
+    XCTAssertTrue(msg.hasOptionalSfixed32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+    [msg release];
+  }
+  {  // optionalSfixed32 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSfixed32);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 0;
+    XCTAssertTrue(msg.hasOptionalSfixed32);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+    [msg release];
+  }
+
+  {  // optionalSfixed64 :: 1
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSfixed64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 1;
+    XCTAssertTrue(msg.hasOptionalSfixed64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+    [msg release];
+  }
+  {  // optionalSfixed64 :: 0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalSfixed64);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 0;
+    XCTAssertTrue(msg.hasOptionalSfixed64);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+    [msg release];
+  }
+
+  {  // optionalFloat :: 1.0f
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFloat);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 1.0f;
+    XCTAssertTrue(msg.hasOptionalFloat);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+    [msg release];
+  }
+  {  // optionalFloat :: 0.0f
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalFloat);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 0.0f;
+    XCTAssertTrue(msg.hasOptionalFloat);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+    [msg release];
+  }
+
+  {  // optionalDouble :: 1.0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalDouble);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 1.0;
+    XCTAssertTrue(msg.hasOptionalDouble);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+    [msg release];
+  }
+  {  // optionalDouble :: 0.0
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalDouble);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 0.0;
+    XCTAssertTrue(msg.hasOptionalDouble);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+    [msg release];
+  }
+
+  {  // optionalBool :: YES
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalBool);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+    msg.optionalBool = YES;
+    XCTAssertTrue(msg.hasOptionalBool);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+    [msg release];
+  }
+  {  // optionalBool :: NO
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalBool);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+    msg.optionalBool = NO;
+    XCTAssertTrue(msg.hasOptionalBool);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+    [msg release];
+  }
+
+  {  // optionalString :: @"foo"
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalString);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+    msg.optionalString = @"foo";
+    XCTAssertTrue(msg.hasOptionalString);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+    [msg release];
+  }
+  {  // optionalString :: @""
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalString);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+    msg.optionalString = @"";
+    XCTAssertTrue(msg.hasOptionalString);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+    [msg release];
+  }
+
+  {  // optionalBytes :: [@"foo" dataUsingEncoding:NSUTF8StringEncoding]
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalBytes);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+    XCTAssertTrue(msg.hasOptionalBytes);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+    [msg release];
+  }
+  {  // optionalBytes :: [NSData data]
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalBytes);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [NSData data];
+    XCTAssertTrue(msg.hasOptionalBytes);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+    [msg release];
+  }
+
+  //
+  // Test doesn't apply to optionalGroup/optionalMessage.
+  //
+
+  {  // optionalEnum :: Message2_Enum_Bar
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalEnum);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message2_Enum_Bar;
+    XCTAssertTrue(msg.hasOptionalEnum);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+    [msg release];
+  }
+  {  // optionalEnum :: Message2_Enum_Foo
+    Message2 *msg = [[Message2 alloc] init];
+    XCTAssertFalse(msg.hasOptionalEnum);
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message2_Enum_Foo;
+    XCTAssertTrue(msg.hasOptionalEnum);
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+    [msg release];
+  }
+
+//%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS()
+}
+
+- (void)testProto3SingleFieldHasBehavior {
+  //
+  // Setting to any value including the default value (0) should result has*
+  // being true.
+  //
+
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//%  {  // optional##FIELD
+//%    Message3 *msg = [[Message3 alloc] init];
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = NON_ZERO_VALUE;
+//%    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = ZERO_VALUE;
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//%    [msg release];
+//%  }
+//%
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELDS()
+//%PROTO3_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO3_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO3_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO3_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO3_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//%  //
+//%  // Test doesn't apply to optionalGroup/optionalMessage.
+//%  //
+//%
+//%PROTO3_TEST_HAS_FIELD(Enum, Message3_Enum_Bar, Message3_Enum_Foo)
+//%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+  {  // optionalInt32
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+    [msg release];
+  }
+
+  {  // optionalInt64
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+    [msg release];
+  }
+
+  {  // optionalUint32
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+    [msg release];
+  }
+
+  {  // optionalUint64
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+    [msg release];
+  }
+
+  {  // optionalSint32
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+    [msg release];
+  }
+
+  {  // optionalSint64
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+    [msg release];
+  }
+
+  {  // optionalFixed32
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+    [msg release];
+  }
+
+  {  // optionalFixed64
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+    [msg release];
+  }
+
+  {  // optionalSfixed32
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+    [msg release];
+  }
+
+  {  // optionalSfixed64
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+    [msg release];
+  }
+
+  {  // optionalFloat
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 1.0f;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 0.0f;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+    [msg release];
+  }
+
+  {  // optionalDouble
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 1.0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 0.0;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+    [msg release];
+  }
+
+  {  // optionalBool
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+    msg.optionalBool = YES;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+    msg.optionalBool = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+    [msg release];
+  }
+
+  {  // optionalString
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+    msg.optionalString = @"foo";
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+    msg.optionalString = @"";
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+    [msg release];
+  }
+
+  {  // optionalBytes
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [NSData data];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+    [msg release];
+  }
+
+  //
+  // Test doesn't apply to optionalGroup/optionalMessage.
+  //
+
+  {  // optionalEnum
+    Message3 *msg = [[Message3 alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message3_Enum_Bar;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message3_Enum_Foo;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+    [msg release];
+  }
+
+//%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
+}
+
+- (void)testAccessingProto2UnknownEnumValues {
+  Message2 *msg = [[Message2 alloc] init];
+
+  // Set it to something non zero, try and confirm it doesn't change.
+
+  msg.optionalEnum = Message2_Enum_Bar;
+  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+                               NSInvalidArgumentException);
+  XCTAssertEqual(msg.optionalEnum, Message2_Enum_Bar);
+
+  msg.oneofEnum = Message2_Enum_Bar;
+  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+                               NSInvalidArgumentException);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+
+  [msg release];
+}
+
+- (void)testAccessingProto3UnknownEnumValues {
+  Message3 *msg = [[Message3 alloc] init];
+
+  // Set it to something non zero, try and confirm it doesn't change.
+
+  msg.optionalEnum = Message3_Enum_Bar;
+  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+                               NSInvalidArgumentException);
+  XCTAssertEqual(msg.optionalEnum, Message3_Enum_Bar);
+
+  msg.oneofEnum = Message3_Enum_Bar;
+  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+                               NSInvalidArgumentException);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+
+  // Set via raw api to confirm it works.
+
+  SetMessage3_OptionalEnum_RawValue(msg, 666);
+  XCTAssertEqual(msg.optionalEnum,
+                 Message3_Enum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(Message3_OptionalEnum_RawValue(msg), 666);
+
+  SetMessage3_OneofEnum_RawValue(msg, 666);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(Message3_OneofEnum_RawValue(msg), 666);
+
+  [msg release];
+}
+
+- (void)testProto2OneofBasicBehaviors {
+  Message2 *msg = [[Message2 alloc] init];
+
+  NSString *oneofStringDefault = @"string";
+  NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+  // Nothing set.
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+
+  // Set, check the case, check everyone has default but the one, confirm case
+  // didn't change.
+
+  msg.oneofInt32 = 1;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+  XCTAssertEqual(msg.oneofInt32, 1);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+
+  msg.oneofInt64 = 2;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 2);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+
+  msg.oneofUint32 = 3;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 3U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+
+  msg.oneofUint64 = 4;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 4U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+
+  msg.oneofSint32 = 5;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 5);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+
+  msg.oneofSint64 = 6;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 6);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+
+  msg.oneofFixed32 = 7;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 7U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+
+  msg.oneofFixed64 = 8;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 8U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+
+  msg.oneofSfixed32 = 9;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 9);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+
+  msg.oneofSfixed64 = 10;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 10);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+
+  msg.oneofFloat = 11.0f;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 11.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+
+  msg.oneofDouble = 12.0;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 12.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+
+  msg.oneofBool = NO;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+
+  msg.oneofString = @"foo";
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, @"foo");
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+
+  msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes,
+                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+
+  Message2_OneofGroup *group = [Message2_OneofGroup message];
+  msg.oneofGroup = group;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertEqual(msg.oneofGroup, group);  // Pointer compare.
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+
+  Message2 *subMessage = [Message2 message];
+  msg.oneofMessage = subMessage;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotEqual(msg.oneofGroup, group);      // Pointer compare.
+  XCTAssertEqual(msg.oneofMessage, subMessage);  // Pointer compare.
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+
+  msg.oneofEnum = Message2_Enum_Bar;
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+  XCTAssertEqual(msg.oneofInt32, 100);
+  XCTAssertEqual(msg.oneofInt64, 101);
+  XCTAssertEqual(msg.oneofUint32, 102U);
+  XCTAssertEqual(msg.oneofUint64, 103U);
+  XCTAssertEqual(msg.oneofSint32, 104);
+  XCTAssertEqual(msg.oneofSint64, 105);
+  XCTAssertEqual(msg.oneofFixed32, 106U);
+  XCTAssertEqual(msg.oneofFixed64, 107U);
+  XCTAssertEqual(msg.oneofSfixed32, 108);
+  XCTAssertEqual(msg.oneofSfixed64, 109);
+  XCTAssertEqual(msg.oneofFloat, 110.0f);
+  XCTAssertEqual(msg.oneofDouble, 111.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofGroup);
+  XCTAssertNotEqual(msg.oneofGroup, group);  // Pointer compare.
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertNotEqual(msg.oneofMessage, subMessage);  // Pointer compare.
+  XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+  XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+
+  // Test setting/calling clear clearing.
+
+  [msg release];
+  msg = [[Message2 alloc] init];
+
+  uint32_t values[] = {
+    Message2_O_OneOfCase_OneofInt32,
+    Message2_O_OneOfCase_OneofInt64,
+    Message2_O_OneOfCase_OneofUint32,
+    Message2_O_OneOfCase_OneofUint64,
+    Message2_O_OneOfCase_OneofSint32,
+    Message2_O_OneOfCase_OneofSint64,
+    Message2_O_OneOfCase_OneofFixed32,
+    Message2_O_OneOfCase_OneofFixed64,
+    Message2_O_OneOfCase_OneofSfixed32,
+    Message2_O_OneOfCase_OneofSfixed64,
+    Message2_O_OneOfCase_OneofFloat,
+    Message2_O_OneOfCase_OneofDouble,
+    Message2_O_OneOfCase_OneofBool,
+    Message2_O_OneOfCase_OneofString,
+    Message2_O_OneOfCase_OneofBytes,
+    Message2_O_OneOfCase_OneofGroup,
+    Message2_O_OneOfCase_OneofMessage,
+    Message2_O_OneOfCase_OneofEnum,
+  };
+
+  for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
+    switch (values[i]) {
+      case Message2_O_OneOfCase_OneofInt32:
+        msg.oneofInt32 = 1;
+        break;
+      case Message2_O_OneOfCase_OneofInt64:
+        msg.oneofInt64 = 2;
+        break;
+      case Message2_O_OneOfCase_OneofUint32:
+        msg.oneofUint32 = 3;
+        break;
+      case Message2_O_OneOfCase_OneofUint64:
+        msg.oneofUint64 = 4;
+        break;
+      case Message2_O_OneOfCase_OneofSint32:
+        msg.oneofSint32 = 5;
+        break;
+      case Message2_O_OneOfCase_OneofSint64:
+        msg.oneofSint64 = 6;
+        break;
+      case Message2_O_OneOfCase_OneofFixed32:
+        msg.oneofFixed32 = 7;
+        break;
+      case Message2_O_OneOfCase_OneofFixed64:
+        msg.oneofFixed64 = 8;
+        break;
+      case Message2_O_OneOfCase_OneofSfixed32:
+        msg.oneofSfixed32 = 9;
+        break;
+      case Message2_O_OneOfCase_OneofSfixed64:
+        msg.oneofSfixed64 = 10;
+        break;
+      case Message2_O_OneOfCase_OneofFloat:
+        msg.oneofFloat = 11.0f;
+        break;
+      case Message2_O_OneOfCase_OneofDouble:
+        msg.oneofDouble = 12.0;
+        break;
+      case Message2_O_OneOfCase_OneofBool:
+        msg.oneofBool = YES;
+        break;
+      case Message2_O_OneOfCase_OneofString:
+        msg.oneofString = @"foo";
+        break;
+      case Message2_O_OneOfCase_OneofBytes:
+        msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+        break;
+      case Message2_O_OneOfCase_OneofGroup:
+        msg.oneofGroup = group;
+        break;
+      case Message2_O_OneOfCase_OneofMessage:
+        msg.oneofMessage = subMessage;
+        break;
+      case Message2_O_OneOfCase_OneofEnum:
+        msg.oneofEnum = Message2_Enum_Bar;
+        break;
+      default:
+        XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]);
+        break;
+    }
+
+    XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+    // No need to check the value was set, the above tests did that.
+    Message2_ClearOOneOfCase(msg);
+    // Nothing in the case.
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase,
+                   "Loop: %zd", i);
+    // Confirm everything is back to defaults after a clear.
+    XCTAssertEqual(msg.oneofInt32, 100, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofInt64, 101, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofUint32, 102U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofUint64, 103U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSint32, 104, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSint64, 105, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFixed32, 106U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFixed64, 107U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSfixed32, 108, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSfixed64, 109, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFloat, 110.0f, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofDouble, 111.0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofBool, YES, "Loop: %zd", i);
+    XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+    XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+    XCTAssertNotNil(msg.oneofGroup, "Loop: %zd", i);
+    XCTAssertNotEqual(msg.oneofGroup, group, "Loop: %zd",
+                      i);  // Pointer compare.
+    XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+    XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+                      i);  // Pointer compare.
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz, "Loop: %zd", i);
+  }
+
+  [msg release];
+}
+
+- (void)testProto3OneofBasicBehaviors {
+  Message3 *msg = [[Message3 alloc] init];
+
+  NSString *oneofStringDefault = @"";
+  NSData *oneofBytesDefault = [NSData data];
+
+  // Nothing set.
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+
+  // Set, check the case, check everyone has default but the one, confirm case
+  // didn't change.
+
+  msg.oneofInt32 = 1;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+  XCTAssertEqual(msg.oneofInt32, 1);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+
+  msg.oneofInt64 = 2;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 2);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+
+  msg.oneofUint32 = 3;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 3U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+
+  msg.oneofUint64 = 4;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 4U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+
+  msg.oneofSint32 = 5;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 5);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+
+  msg.oneofSint64 = 6;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 6);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+
+  msg.oneofFixed32 = 7;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 7U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+
+  msg.oneofFixed64 = 8;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 8U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+
+  msg.oneofSfixed32 = 9;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 9);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+
+  msg.oneofSfixed64 = 10;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 10);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+
+  msg.oneofFloat = 11.0f;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 11.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+
+  msg.oneofDouble = 12.0;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 12.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+
+  msg.oneofBool = YES;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, YES);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+
+  msg.oneofString = @"foo";
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, @"foo");
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+
+  msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes,
+                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+
+  Message3 *subMessage = [Message3 message];
+  msg.oneofMessage = subMessage;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertEqual(msg.oneofMessage, subMessage);  // Pointer compare.
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+
+  msg.oneofEnum = Message3_Enum_Bar;
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+  XCTAssertEqual(msg.oneofInt32, 0);
+  XCTAssertEqual(msg.oneofInt64, 0);
+  XCTAssertEqual(msg.oneofUint32, 0U);
+  XCTAssertEqual(msg.oneofUint64, 0U);
+  XCTAssertEqual(msg.oneofSint32, 0);
+  XCTAssertEqual(msg.oneofSint64, 0);
+  XCTAssertEqual(msg.oneofFixed32, 0U);
+  XCTAssertEqual(msg.oneofFixed64, 0U);
+  XCTAssertEqual(msg.oneofSfixed32, 0);
+  XCTAssertEqual(msg.oneofSfixed64, 0);
+  XCTAssertEqual(msg.oneofFloat, 0.0f);
+  XCTAssertEqual(msg.oneofDouble, 0.0);
+  XCTAssertEqual(msg.oneofBool, NO);
+  XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+  XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+  XCTAssertNotNil(msg.oneofMessage);
+  XCTAssertNotEqual(msg.oneofMessage, subMessage);  // Pointer compare.
+  XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+
+  // Test setting/calling clear clearing.
+
+  [msg release];
+  msg = [[Message3 alloc] init];
+
+  uint32_t values[] = {
+    Message3_O_OneOfCase_OneofInt32,
+    Message3_O_OneOfCase_OneofInt64,
+    Message3_O_OneOfCase_OneofUint32,
+    Message3_O_OneOfCase_OneofUint64,
+    Message3_O_OneOfCase_OneofSint32,
+    Message3_O_OneOfCase_OneofSint64,
+    Message3_O_OneOfCase_OneofFixed32,
+    Message3_O_OneOfCase_OneofFixed64,
+    Message3_O_OneOfCase_OneofSfixed32,
+    Message3_O_OneOfCase_OneofSfixed64,
+    Message3_O_OneOfCase_OneofFloat,
+    Message3_O_OneOfCase_OneofDouble,
+    Message3_O_OneOfCase_OneofBool,
+    Message3_O_OneOfCase_OneofString,
+    Message3_O_OneOfCase_OneofBytes,
+    Message3_O_OneOfCase_OneofMessage,
+    Message3_O_OneOfCase_OneofEnum,
+  };
+
+  for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
+    switch (values[i]) {
+      case Message3_O_OneOfCase_OneofInt32:
+        msg.oneofInt32 = 1;
+        break;
+      case Message3_O_OneOfCase_OneofInt64:
+        msg.oneofInt64 = 2;
+        break;
+      case Message3_O_OneOfCase_OneofUint32:
+        msg.oneofUint32 = 3;
+        break;
+      case Message3_O_OneOfCase_OneofUint64:
+        msg.oneofUint64 = 4;
+        break;
+      case Message3_O_OneOfCase_OneofSint32:
+        msg.oneofSint32 = 5;
+        break;
+      case Message3_O_OneOfCase_OneofSint64:
+        msg.oneofSint64 = 6;
+        break;
+      case Message3_O_OneOfCase_OneofFixed32:
+        msg.oneofFixed32 = 7;
+        break;
+      case Message3_O_OneOfCase_OneofFixed64:
+        msg.oneofFixed64 = 8;
+        break;
+      case Message3_O_OneOfCase_OneofSfixed32:
+        msg.oneofSfixed32 = 9;
+        break;
+      case Message3_O_OneOfCase_OneofSfixed64:
+        msg.oneofSfixed64 = 10;
+        break;
+      case Message3_O_OneOfCase_OneofFloat:
+        msg.oneofFloat = 11.0f;
+        break;
+      case Message3_O_OneOfCase_OneofDouble:
+        msg.oneofDouble = 12.0;
+        break;
+      case Message3_O_OneOfCase_OneofBool:
+        msg.oneofBool = YES;
+        break;
+      case Message3_O_OneOfCase_OneofString:
+        msg.oneofString = @"foo";
+        break;
+      case Message3_O_OneOfCase_OneofBytes:
+        msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+        break;
+      case Message3_O_OneOfCase_OneofMessage:
+        msg.oneofMessage = subMessage;
+        break;
+      case Message3_O_OneOfCase_OneofEnum:
+        msg.oneofEnum = Message3_Enum_Baz;
+        break;
+      default:
+        XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]);
+        break;
+    }
+
+    XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+    // No need to check the value was set, the above tests did that.
+    Message3_ClearOOneOfCase(msg);
+    // Nothing in the case.
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase,
+                   "Loop: %zd", i);
+    // Confirm everything is back to defaults after a clear.
+    XCTAssertEqual(msg.oneofInt32, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofInt64, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofUint32, 0U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofUint64, 0U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSint32, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSint64, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFixed32, 0U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFixed64, 0U, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSfixed32, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofSfixed64, 0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofFloat, 0.0f, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofDouble, 0.0, "Loop: %zd", i);
+    XCTAssertEqual(msg.oneofBool, NO, "Loop: %zd", i);
+    XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+    XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+    XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+    XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+                      i);  // Pointer compare.
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo, "Loop: %zd", i);
+  }
+
+  [msg release];
+}
+
+- (void)testCopyingMakesUniqueObjects {
+  const int repeatCount = 5;
+  TestAllTypes *msg1 = [TestAllTypes message];
+  [self setAllFields:msg1 repeatedCount:repeatCount];
+
+  TestAllTypes *msg2 = [[msg1 copy] autorelease];
+
+  XCTAssertNotEqual(msg1, msg2);      // Ptr compare, new object.
+  XCTAssertEqualObjects(msg1, msg2);  // Equal values.
+
+  // Pointer comparisions, different objects.
+
+  XCTAssertNotEqual(msg1.optionalGroup, msg2.optionalGroup);
+  XCTAssertNotEqual(msg1.optionalNestedMessage, msg2.optionalNestedMessage);
+  XCTAssertNotEqual(msg1.optionalForeignMessage, msg2.optionalForeignMessage);
+  XCTAssertNotEqual(msg1.optionalImportMessage, msg2.optionalImportMessage);
+
+  XCTAssertNotEqual(msg1.repeatedInt32Array, msg2.repeatedInt32Array);
+  XCTAssertNotEqual(msg1.repeatedInt64Array, msg2.repeatedInt64Array);
+  XCTAssertNotEqual(msg1.repeatedUint32Array, msg2.repeatedUint32Array);
+  XCTAssertNotEqual(msg1.repeatedUint64Array, msg2.repeatedUint64Array);
+  XCTAssertNotEqual(msg1.repeatedSint32Array, msg2.repeatedSint32Array);
+  XCTAssertNotEqual(msg1.repeatedSint64Array, msg2.repeatedSint64Array);
+  XCTAssertNotEqual(msg1.repeatedFixed32Array, msg2.repeatedFixed32Array);
+  XCTAssertNotEqual(msg1.repeatedFixed64Array, msg2.repeatedFixed64Array);
+  XCTAssertNotEqual(msg1.repeatedSfixed32Array, msg2.repeatedSfixed32Array);
+  XCTAssertNotEqual(msg1.repeatedSfixed64Array, msg2.repeatedSfixed64Array);
+  XCTAssertNotEqual(msg1.repeatedFloatArray, msg2.repeatedFloatArray);
+  XCTAssertNotEqual(msg1.repeatedDoubleArray, msg2.repeatedDoubleArray);
+  XCTAssertNotEqual(msg1.repeatedBoolArray, msg2.repeatedBoolArray);
+  XCTAssertNotEqual(msg1.repeatedStringArray, msg2.repeatedStringArray);
+  XCTAssertNotEqual(msg1.repeatedBytesArray, msg2.repeatedBytesArray);
+  XCTAssertNotEqual(msg1.repeatedGroupArray, msg2.repeatedGroupArray);
+  XCTAssertNotEqual(msg1.repeatedNestedMessageArray,
+                    msg2.repeatedNestedMessageArray);
+  XCTAssertNotEqual(msg1.repeatedForeignMessageArray,
+                    msg2.repeatedForeignMessageArray);
+  XCTAssertNotEqual(msg1.repeatedImportMessageArray,
+                    msg2.repeatedImportMessageArray);
+  XCTAssertNotEqual(msg1.repeatedNestedEnumArray, msg2.repeatedNestedEnumArray);
+  XCTAssertNotEqual(msg1.repeatedForeignEnumArray,
+                    msg2.repeatedForeignEnumArray);
+  XCTAssertNotEqual(msg1.repeatedImportEnumArray, msg2.repeatedImportEnumArray);
+  XCTAssertNotEqual(msg1.repeatedStringPieceArray,
+                    msg2.repeatedStringPieceArray);
+  XCTAssertNotEqual(msg1.repeatedCordArray, msg2.repeatedCordArray);
+
+  for (int i = 0; i < repeatCount; i++) {
+    XCTAssertNotEqual(msg1.repeatedNestedMessageArray[i],
+                      msg2.repeatedNestedMessageArray[i]);
+    XCTAssertNotEqual(msg1.repeatedForeignMessageArray[i],
+                      msg2.repeatedForeignMessageArray[i]);
+    XCTAssertNotEqual(msg1.repeatedImportMessageArray[i],
+                      msg2.repeatedImportMessageArray[i]);
+  }
+}
+
+- (void)testCopyingMapsMakesUniqueObjects {
+  TestMap *msg1 = [TestMap message];
+  [self setAllMapFields:msg1 numEntries:5];
+
+  TestMap *msg2 = [[msg1 copy] autorelease];
+
+  XCTAssertNotEqual(msg1, msg2);      // Ptr compare, new object.
+  XCTAssertEqualObjects(msg1, msg2);  // Equal values.
+
+  // Pointer comparisions, different objects.
+  XCTAssertNotEqual(msg1.mapInt32Int32, msg2.mapInt32Int32);
+  XCTAssertNotEqual(msg1.mapInt64Int64, msg2.mapInt64Int64);
+  XCTAssertNotEqual(msg1.mapUint32Uint32, msg2.mapUint32Uint32);
+  XCTAssertNotEqual(msg1.mapUint64Uint64, msg2.mapUint64Uint64);
+  XCTAssertNotEqual(msg1.mapSint32Sint32, msg2.mapSint32Sint32);
+  XCTAssertNotEqual(msg1.mapSint64Sint64, msg2.mapSint64Sint64);
+  XCTAssertNotEqual(msg1.mapFixed32Fixed32, msg2.mapFixed32Fixed32);
+  XCTAssertNotEqual(msg1.mapFixed64Fixed64, msg2.mapFixed64Fixed64);
+  XCTAssertNotEqual(msg1.mapSfixed32Sfixed32, msg2.mapSfixed32Sfixed32);
+  XCTAssertNotEqual(msg1.mapSfixed64Sfixed64, msg2.mapSfixed64Sfixed64);
+  XCTAssertNotEqual(msg1.mapInt32Float, msg2.mapInt32Float);
+  XCTAssertNotEqual(msg1.mapInt32Double, msg2.mapInt32Double);
+  XCTAssertNotEqual(msg1.mapBoolBool, msg2.mapBoolBool);
+  XCTAssertNotEqual(msg1.mapStringString, msg2.mapStringString);
+  XCTAssertNotEqual(msg1.mapInt32Bytes, msg2.mapInt32Bytes);
+  XCTAssertNotEqual(msg1.mapInt32Enum, msg2.mapInt32Enum);
+  XCTAssertNotEqual(msg1.mapInt32ForeignMessage, msg2.mapInt32ForeignMessage);
+
+  // Ensure the messages are unique per map.
+  [msg1.mapInt32ForeignMessage
+      enumerateKeysAndObjectsUsingBlock:^(int32_t key, id value, BOOL *stop) {
+#pragma unused(stop)
+        ForeignMessage *subMsg2 = [msg2.mapInt32ForeignMessage objectForKey:key];
+        XCTAssertNotEqual(value, subMsg2);  // Ptr compare, new object.
+      }];
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, IsInitialized)
+- (void)testMap_IsInitialized {
+  TestRequiredMessageMap *msg = [[TestRequiredMessageMap alloc] init];
+
+  // Add an uninitialized message.
+  TestRequired *subMsg = [[TestRequired alloc] init];
+  [msg.mapField setObject:subMsg forKey:0];
+  XCTAssertFalse(msg.initialized);
+
+  // Initialize uninitialized message
+  subMsg.a = 0;
+  subMsg.b = 0;
+  subMsg.c = 0;
+  XCTAssertTrue(msg.initialized);
+
+  [subMsg release];
+  [msg release];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Serialization.m b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Serialization.m
new file mode 100644
index 0000000..0d811a9
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -0,0 +1,1105 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.h"
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+static NSData *DataFromCStr(const char *str) {
+  return [NSData dataWithBytes:str length:strlen(str)];
+}
+
+@interface MessageSerializationTests : GPBTestCase
+@end
+
+@implementation MessageSerializationTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are serialization
+// specific.
+
+- (void)testProto3SerializationHandlingDefaults {
+  // Proto2 covered in other tests.
+
+  Message3 *msg = [[Message3 alloc] init];
+
+  // Add defaults, no output.
+
+  NSData *data = [msg data];
+  XCTAssertEqual([data length], 0U);
+
+  // All zeros, still nothing.
+
+  msg.optionalInt32 = 0;
+  msg.optionalInt64 = 0;
+  msg.optionalUint32 = 0;
+  msg.optionalUint64 = 0;
+  msg.optionalSint32 = 0;
+  msg.optionalSint64 = 0;
+  msg.optionalFixed32 = 0;
+  msg.optionalFixed64 = 0;
+  msg.optionalSfixed32 = 0;
+  msg.optionalSfixed64 = 0;
+  msg.optionalFloat = 0.0f;
+  msg.optionalDouble = 0.0;
+  msg.optionalBool = NO;
+  msg.optionalString = @"";
+  msg.optionalBytes = [NSData data];
+  msg.optionalEnum = Message3_Enum_Foo;  // first value
+
+  data = [msg data];
+  XCTAssertEqual([data length], 0U);
+
+  // The two that also take nil as nothing.
+
+  msg.optionalString = nil;
+  msg.optionalBytes = nil;
+
+  data = [msg data];
+  XCTAssertEqual([data length], 0U);
+
+  // Set one field...
+
+  msg.optionalInt32 = 1;
+
+  data = [msg data];
+  const uint8_t expectedBytes[] = {0x08, 0x01};
+  NSData *expected = [NSData dataWithBytes:expectedBytes length:2];
+  XCTAssertEqualObjects(data, expected);
+
+  // Back to zero...
+
+  msg.optionalInt32 = 0;
+
+  data = [msg data];
+  XCTAssertEqual([data length], 0U);
+
+  [msg release];
+}
+
+- (void)testProto3DroppingUnknownFields {
+  DropUnknownsFooWithExtraFields *fooWithExtras =
+      [[DropUnknownsFooWithExtraFields alloc] init];
+
+  fooWithExtras.int32Value = 1;
+  fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz;
+  fooWithExtras.extraInt32Value = 2;
+
+  NSData *data = [fooWithExtras data];
+  XCTAssertNotNil(data);
+  DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:data error:NULL];
+
+  XCTAssertEqual(foo.int32Value, 1);
+  XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz);
+  // Nothing should end up in the unknowns.
+  XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+
+  [fooWithExtras release];
+  data = [foo data];
+  fooWithExtras =
+      [DropUnknownsFooWithExtraFields parseFromData:data error:NULL];
+  XCTAssertEqual(fooWithExtras.int32Value, 1);
+  XCTAssertEqual(fooWithExtras.enumValue,
+                 DropUnknownsFooWithExtraFields_NestedEnum_Baz);
+  // And the extra value is gone (back to the default).
+  XCTAssertEqual(fooWithExtras.extraInt32Value, 0);
+  XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+}
+
+- (void)testProto2UnknownEnumToUnknownField {
+  Message3 *orig = [[Message3 alloc] init];
+
+  orig.optionalEnum = Message3_Enum_Extra3;
+  orig.repeatedEnumArray =
+      [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+                                       rawValue:Message3_Enum_Extra3];
+  orig.oneofEnum = Message3_Enum_Extra3;
+
+  NSData *data = [orig data];
+  XCTAssertNotNil(data);
+  Message2 *msg = [[Message2 alloc] initWithData:data error:NULL];
+
+  // None of the fields should be set.
+
+  XCTAssertFalse(msg.hasOptionalEnum);
+  XCTAssertEqual(msg.repeatedEnumArray.count, 0U);
+  XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+
+  // All the values should be in unknown fields.
+
+  GPBUnknownFieldSet *unknownFields = msg.unknownFields;
+
+  XCTAssertEqual([unknownFields countOfFields], 3U);
+  XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OptionalEnum]);
+  XCTAssertTrue(
+      [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
+  XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]);
+
+  GPBUnknownField *field =
+      [unknownFields getField:Message2_FieldNumber_OptionalEnum];
+  XCTAssertEqual(field.varintList.count, 1U);
+  XCTAssertEqual([field.varintList valueAtIndex:0],
+                 (uint64_t)Message3_Enum_Extra3);
+
+  field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray];
+  XCTAssertEqual(field.varintList.count, 1U);
+  XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3);
+
+  field = [unknownFields getField:Message2_FieldNumber_OneofEnum];
+  XCTAssertEqual(field.varintList.count, 1U);
+  XCTAssertEqual([field.varintList valueAtIndex:0],
+                 (uint64_t)Message3_Enum_Extra3);
+
+  [msg release];
+  [orig release];
+}
+
+- (void)testProto3UnknownEnumPreserving {
+  UnknownEnumsMyMessagePlusExtra *orig =
+      [UnknownEnumsMyMessagePlusExtra message];
+
+  orig.e = UnknownEnumsMyEnumPlusExtra_EExtra;
+  orig.repeatedEArray = [GPBEnumArray
+      arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+                         rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+  orig.repeatedPackedEArray = [GPBEnumArray
+      arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+                         rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+  orig.oneofE1 = UnknownEnumsMyEnumPlusExtra_EExtra;
+
+  // Everything should be there via raw values.
+
+  NSData *data = [orig data];
+  XCTAssertNotNil(data);
+  UnknownEnumsMyMessage *msg =
+      [UnknownEnumsMyMessage parseFromData:data error:NULL];
+
+  XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg),
+                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(msg.repeatedEArray.count, 1U);
+  XCTAssertEqual([msg.repeatedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([msg.repeatedEArray rawValueAtIndex:0],
+                 (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(msg.repeatedPackedEArray.count, 1U);
+  XCTAssertEqual([msg.repeatedPackedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual([msg.repeatedPackedEArray rawValueAtIndex:0],
+                 (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(msg.oneofE1,
+                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(msg),
+                 UnknownEnumsMyEnumPlusExtra_EExtra);
+
+  // Everything should go out and come back.
+
+  data = [msg data];
+  orig = [UnknownEnumsMyMessagePlusExtra parseFromData:data error:NULL];
+
+  XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(orig.repeatedEArray.count, 1U);
+  XCTAssertEqual([orig.repeatedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(orig.repeatedPackedEArray.count, 1U);
+  XCTAssertEqual([orig.repeatedPackedEArray valueAtIndex:0],
+                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(orig.oneofE1, UnknownEnumsMyEnumPlusExtra_EExtra);
+}
+
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF(MESSAGE, FIELD, VALUE)
+//%TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, )
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, EQ_SUFFIX)
+//%  {  // oneof##FIELD
+//%    MESSAGE *orig = [[MESSAGE alloc] init];
+//%    orig.oneof##FIELD = VALUE;
+//%    XCTAssertEqual(orig.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//%    NSData *data = [orig data];
+//%    XCTAssertNotNil(data);
+//%    MESSAGE *msg = [MESSAGE parseFromData:data error:NULL];
+//%    XCTAssertEqual(msg.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//%    XCTAssertEqual##EQ_SUFFIX(msg.oneof##FIELD, VALUE);
+//%    [orig release];
+//%  }
+//%
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOFS(SYNTAX, BOOL_NON_DEFAULT)
+//%- (void)testProto##SYNTAX##RoundTripOneof {
+//%
+//%GROUP_INIT##SYNTAX()  Message##SYNTAX *subMessage = [[Message##SYNTAX alloc] init];
+//%  XCTAssertNotNil(subMessage);
+//%  subMessage.optionalInt32 = 666;
+//%
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int32, 1)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int64, 2)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint32, 3U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint64, 4U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint32, 5)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint64, 6)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed32, 7U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed64, 8U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed32, 9)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed64, 10)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Float, 11.0f)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Double, 12.0)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Bool, BOOL_NON_DEFAULT)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, String, @"foo", Objects)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Bytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding], Objects)
+//%GROUP_TEST##SYNTAX()TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Message, subMessage, Objects)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Enum, Message2_Enum_Bar)
+//%GROUP_CLEANUP##SYNTAX()  [subMessage release];
+//%}
+//%
+//%PDDM-DEFINE GROUP_INIT2()
+//%  Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+//%  XCTAssertNotNil(group);
+//%  group.a = 777;
+//%
+//%PDDM-DEFINE GROUP_CLEANUP2()
+//%  [group release];
+//%
+//%PDDM-DEFINE GROUP_TEST2()
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message2, Group, group, Objects)
+//%
+//%PDDM-DEFINE GROUP_INIT3()
+// Empty
+//%PDDM-DEFINE GROUP_CLEANUP3()
+// Empty
+//%PDDM-DEFINE GROUP_TEST3()
+//%  // Not "group" in proto3.
+//%
+//%
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(2, NO)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto2RoundTripOneof {
+
+  Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+  XCTAssertNotNil(group);
+  group.a = 777;
+  Message2 *subMessage = [[Message2 alloc] init];
+  XCTAssertNotNil(subMessage);
+  subMessage.optionalInt32 = 666;
+
+  {  // oneofInt32
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofInt32 = 1;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+    XCTAssertEqual(msg.oneofInt32, 1);
+    [orig release];
+  }
+
+  {  // oneofInt64
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofInt64 = 2;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+    XCTAssertEqual(msg.oneofInt64, 2);
+    [orig release];
+  }
+
+  {  // oneofUint32
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofUint32 = 3U;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+    XCTAssertEqual(msg.oneofUint32, 3U);
+    [orig release];
+  }
+
+  {  // oneofUint64
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofUint64 = 4U;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+    XCTAssertEqual(msg.oneofUint64, 4U);
+    [orig release];
+  }
+
+  {  // oneofSint32
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofSint32 = 5;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+    XCTAssertEqual(msg.oneofSint32, 5);
+    [orig release];
+  }
+
+  {  // oneofSint64
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofSint64 = 6;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+    XCTAssertEqual(msg.oneofSint64, 6);
+    [orig release];
+  }
+
+  {  // oneofFixed32
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofFixed32 = 7U;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+    XCTAssertEqual(msg.oneofFixed32, 7U);
+    [orig release];
+  }
+
+  {  // oneofFixed64
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofFixed64 = 8U;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+    XCTAssertEqual(msg.oneofFixed64, 8U);
+    [orig release];
+  }
+
+  {  // oneofSfixed32
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofSfixed32 = 9;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+    XCTAssertEqual(msg.oneofSfixed32, 9);
+    [orig release];
+  }
+
+  {  // oneofSfixed64
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofSfixed64 = 10;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+    XCTAssertEqual(msg.oneofSfixed64, 10);
+    [orig release];
+  }
+
+  {  // oneofFloat
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofFloat = 11.0f;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+    XCTAssertEqual(msg.oneofFloat, 11.0f);
+    [orig release];
+  }
+
+  {  // oneofDouble
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofDouble = 12.0;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+    XCTAssertEqual(msg.oneofDouble, 12.0);
+    [orig release];
+  }
+
+  {  // oneofBool
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofBool = NO;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+    XCTAssertEqual(msg.oneofBool, NO);
+    [orig release];
+  }
+
+  {  // oneofString
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofString = @"foo";
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofString);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+    XCTAssertEqualObjects(msg.oneofString, @"foo");
+    [orig release];
+  }
+
+  {  // oneofBytes
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+    XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+    [orig release];
+  }
+
+  {  // oneofGroup
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofGroup = group;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+    XCTAssertEqualObjects(msg.oneofGroup, group);
+    [orig release];
+  }
+
+  {  // oneofMessage
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofMessage = subMessage;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+    XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+    [orig release];
+  }
+
+  {  // oneofEnum
+    Message2 *orig = [[Message2 alloc] init];
+    orig.oneofEnum = Message2_Enum_Bar;
+    XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message2 *msg = [Message2 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+    [orig release];
+  }
+
+  [group release];
+  [subMessage release];
+}
+
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(3, YES)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto3RoundTripOneof {
+
+  Message3 *subMessage = [[Message3 alloc] init];
+  XCTAssertNotNil(subMessage);
+  subMessage.optionalInt32 = 666;
+
+  {  // oneofInt32
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofInt32 = 1;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+    XCTAssertEqual(msg.oneofInt32, 1);
+    [orig release];
+  }
+
+  {  // oneofInt64
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofInt64 = 2;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+    XCTAssertEqual(msg.oneofInt64, 2);
+    [orig release];
+  }
+
+  {  // oneofUint32
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofUint32 = 3U;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+    XCTAssertEqual(msg.oneofUint32, 3U);
+    [orig release];
+  }
+
+  {  // oneofUint64
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofUint64 = 4U;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+    XCTAssertEqual(msg.oneofUint64, 4U);
+    [orig release];
+  }
+
+  {  // oneofSint32
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofSint32 = 5;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+    XCTAssertEqual(msg.oneofSint32, 5);
+    [orig release];
+  }
+
+  {  // oneofSint64
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofSint64 = 6;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+    XCTAssertEqual(msg.oneofSint64, 6);
+    [orig release];
+  }
+
+  {  // oneofFixed32
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofFixed32 = 7U;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+    XCTAssertEqual(msg.oneofFixed32, 7U);
+    [orig release];
+  }
+
+  {  // oneofFixed64
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofFixed64 = 8U;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+    XCTAssertEqual(msg.oneofFixed64, 8U);
+    [orig release];
+  }
+
+  {  // oneofSfixed32
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofSfixed32 = 9;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+    XCTAssertEqual(msg.oneofSfixed32, 9);
+    [orig release];
+  }
+
+  {  // oneofSfixed64
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofSfixed64 = 10;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+    XCTAssertEqual(msg.oneofSfixed64, 10);
+    [orig release];
+  }
+
+  {  // oneofFloat
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofFloat = 11.0f;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+    XCTAssertEqual(msg.oneofFloat, 11.0f);
+    [orig release];
+  }
+
+  {  // oneofDouble
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofDouble = 12.0;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+    XCTAssertEqual(msg.oneofDouble, 12.0);
+    [orig release];
+  }
+
+  {  // oneofBool
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofBool = YES;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+    XCTAssertEqual(msg.oneofBool, YES);
+    [orig release];
+  }
+
+  {  // oneofString
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofString = @"foo";
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofString);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+    XCTAssertEqualObjects(msg.oneofString, @"foo");
+    [orig release];
+  }
+
+  {  // oneofBytes
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+    XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+    [orig release];
+  }
+
+  // Not "group" in proto3.
+
+  {  // oneofMessage
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofMessage = subMessage;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+    XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+    [orig release];
+  }
+
+  {  // oneofEnum
+    Message3 *orig = [[Message3 alloc] init];
+    orig.oneofEnum = Message2_Enum_Bar;
+    XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+    NSData *data = [orig data];
+    XCTAssertNotNil(data);
+    Message3 *msg = [Message3 parseFromData:data error:NULL];
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+    [orig release];
+  }
+
+  [subMessage release];
+}
+
+//%PDDM-EXPAND-END (2 expansions)
+
+- (void)testPackedUnpackedMessageParsing {
+  // packed is optional, a repeated field should parse when packed or unpacked.
+
+  TestPackedTypes *packedOrig = [TestPackedTypes message];
+  TestUnpackedTypes *unpackedOrig = [TestUnpackedTypes message];
+  [self setPackedFields:packedOrig repeatedCount:4];
+  [self setUnpackedFields:unpackedOrig repeatedCount:4];
+
+  NSData *packedData = [packedOrig data];
+  NSData *unpackedData = [unpackedOrig data];
+  XCTAssertNotNil(packedData);
+  XCTAssertNotNil(unpackedData);
+  XCTAssertNotEqualObjects(packedData, unpackedData,
+                           @"Data should differ (packed vs unpacked) use");
+
+  NSError *error = nil;
+  TestPackedTypes *packedParse =
+      [TestPackedTypes parseFromData:unpackedData error:&error];
+  XCTAssertNotNil(packedParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(packedParse, packedOrig);
+
+  error = nil;
+  TestUnpackedTypes *unpackedParsed =
+      [TestUnpackedTypes parseFromData:packedData error:&error];
+  XCTAssertNotNil(unpackedParsed);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(unpackedParsed, unpackedOrig);
+}
+
+- (void)testPackedUnpackedExtensionParsing {
+  // packed is optional, a repeated extension should parse when packed or
+  // unpacked.
+
+  TestPackedExtensions *packedOrig = [TestPackedExtensions message];
+  TestUnpackedExtensions *unpackedOrig = [TestUnpackedExtensions message];
+  [self setPackedExtensions:packedOrig repeatedCount:kGPBDefaultRepeatCount];
+  [self setUnpackedExtensions:unpackedOrig repeatedCount:kGPBDefaultRepeatCount];
+
+  NSData *packedData = [packedOrig data];
+  NSData *unpackedData = [unpackedOrig data];
+  XCTAssertNotNil(packedData);
+  XCTAssertNotNil(unpackedData);
+  XCTAssertNotEqualObjects(packedData, unpackedData,
+                           @"Data should differ (packed vs unpacked) use");
+
+  NSError *error = nil;
+  TestPackedExtensions *packedParse =
+      [TestPackedExtensions parseFromData:unpackedData
+                        extensionRegistry:[UnittestRoot extensionRegistry]
+                                    error:&error];
+  XCTAssertNotNil(packedParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(packedParse, packedOrig);
+
+  error = nil;
+  TestUnpackedExtensions *unpackedParsed =
+      [TestUnpackedExtensions parseFromData:packedData
+                          extensionRegistry:[UnittestRoot extensionRegistry]
+                                      error:&error];
+  XCTAssertNotNil(unpackedParsed);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(unpackedParsed, unpackedOrig);
+}
+
+- (void)testPackedExtensionVsFieldParsing {
+  // Extensions and fields end up on the wire the same way, so they can parse
+  // each other.
+
+  TestPackedTypes *fieldsOrig = [TestPackedTypes message];
+  TestPackedExtensions *extsOrig = [TestPackedExtensions message];
+  [self setPackedFields:fieldsOrig repeatedCount:kGPBDefaultRepeatCount];
+  [self setPackedExtensions:extsOrig repeatedCount:kGPBDefaultRepeatCount];
+
+  NSData *fieldsData = [fieldsOrig data];
+  NSData *extsData = [extsOrig data];
+  XCTAssertNotNil(fieldsData);
+  XCTAssertNotNil(extsData);
+  XCTAssertEqualObjects(fieldsData, extsData);
+
+  NSError *error = nil;
+  TestPackedTypes *fieldsParse =
+      [TestPackedTypes parseFromData:extsData error:&error];
+  XCTAssertNotNil(fieldsParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(fieldsParse, fieldsOrig);
+
+  error = nil;
+  TestPackedExtensions *extsParse =
+      [TestPackedExtensions parseFromData:fieldsData
+                        extensionRegistry:[UnittestRoot extensionRegistry]
+                                    error:&error];
+  XCTAssertNotNil(extsParse);
+  XCTAssertNil(error);
+  XCTAssertEqualObjects(extsParse, extsOrig);
+}
+
+- (void)testUnpackedExtensionVsFieldParsing {
+  // Extensions and fields end up on the wire the same way, so they can parse
+  // each other.
+
+  TestUnpackedTypes *fieldsOrig = [TestUnpackedTypes message];
+  TestUnpackedExtensions *extsOrig = [TestUnpackedExtensions message];
+  [self setUnpackedFields:fieldsOrig repeatedCount:3];
+  [self setUnpackedExtensions:extsOrig repeatedCount:3];
+
+  NSData *fieldsData = [fieldsOrig data];
+  NSData *extsData = [extsOrig data];
+  XCTAssertNotNil(fieldsData);
+  XCTAssertNotNil(extsData);
+  XCTAssertEqualObjects(fieldsData, extsData);
+
+  TestUnpackedTypes *fieldsParse =
+      [TestUnpackedTypes parseFromData:extsData error:NULL];
+  XCTAssertNotNil(fieldsParse);
+  XCTAssertEqualObjects(fieldsParse, fieldsOrig);
+
+  TestUnpackedExtensions *extsParse =
+      [TestUnpackedExtensions parseFromData:fieldsData
+                          extensionRegistry:[UnittestRoot extensionRegistry]
+                                      error:NULL];
+  XCTAssertNotNil(extsParse);
+  XCTAssertEqualObjects(extsParse, extsOrig);
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, StandardWireFormat)
+- (void)testMap_StandardWireFormat {
+  NSData *data = DataFromCStr("\x0A\x04\x08\x01\x10\x01");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+  XCTAssertEqual(val, 1);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnorderedWireFormat)
+- (void)testMap_UnorderedWireFormat {
+  // put value before key in wire format
+  NSData *data = DataFromCStr("\x0A\x04\x10\x01\x08\x02");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+  XCTAssertEqual(val, 1);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat)
+- (void)testMap_DuplicatedKeyWireFormat {
+  // Two key fields in wire format
+  NSData *data = DataFromCStr("\x0A\x06\x08\x01\x08\x02\x10\x01");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+  XCTAssertEqual(val, 1);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat)
+- (void)testMap_DuplicatedValueWireFormat {
+  // Two value fields in wire format
+  NSData *data = DataFromCStr("\x0A\x06\x08\x01\x10\x01\x10\x02");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+  XCTAssertEqual(val, 2);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedKeyWireFormat)
+- (void)testMap_MissedKeyWireFormat {
+  // No key field in wire format
+  NSData *data = DataFromCStr("\x0A\x02\x10\x01");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:0 value:&val]);
+  XCTAssertEqual(val, 1);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedValueWireFormat)
+- (void)testMap_MissedValueWireFormat {
+  // No value field in wire format
+  NSData *data = DataFromCStr("\x0A\x02\x08\x01");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+  XCTAssertEqual(val, 0);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnknownFieldWireFormat)
+- (void)testMap_UnknownFieldWireFormat {
+  // Unknown field in wire format
+  NSData *data = DataFromCStr("\x0A\x06\x08\x02\x10\x03\x18\x01");
+
+  TestMap *msg = [[TestMap alloc] initWithData:data error:NULL];
+  XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+  int32_t val = 666;
+  XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+  XCTAssertEqual(val, 3);
+
+  [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, CorruptedWireFormat)
+- (void)testMap_CorruptedWireFormat {
+  // corrupted data in wire format
+  NSData *data = DataFromCStr("\x0A\x06\x08\x02\x11\x03");
+
+  NSError *error = nil;
+  TestMap *msg = [TestMap parseFromData:data error:&error];
+  XCTAssertNil(msg);
+  XCTAssertNotNil(error);
+  XCTAssertEqualObjects(error.domain, GPBMessageErrorDomain);
+  XCTAssertEqual(error.code, GPBMessageErrorCodeMalformedData);
+}
+
+// TEST(GeneratedMapFieldTest, Proto2UnknownEnum)
+- (void)testMap_Proto2UnknownEnum {
+  TestEnumMapPlusExtra *orig = [[TestEnumMapPlusExtra alloc] init];
+
+  orig.knownMapField = [GPBInt32EnumDictionary
+      dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+  orig.unknownMapField = [GPBInt32EnumDictionary
+      dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+  [orig.knownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumFoo
+                        forKey:0];
+  [orig.unknownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumExtra
+                          forKey:0];
+
+  NSData *data = [orig data];
+  XCTAssertNotNil(data);
+  TestEnumMap *msg1 = [TestEnumMap parseFromData:data error:NULL];
+  XCTAssertEqual(msg1.knownMapField.count, 1U);
+  int32_t val = -1;
+  XCTAssertTrue([msg1.knownMapField valueForKey:0 value:&val]);
+  XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo);
+  XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
+
+  data = [msg1 data];
+  TestEnumMapPlusExtra *msg2 =
+      [TestEnumMapPlusExtra parseFromData:data error:NULL];
+  val = -1;
+  XCTAssertEqual(msg2.knownMapField.count, 1U);
+  XCTAssertTrue([msg2.knownMapField valueForKey:0 value:&val]);
+  XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumFoo);
+  val = -1;
+  XCTAssertEqual(msg2.unknownMapField.count, 1U);
+  XCTAssertTrue([msg2.unknownMapField valueForKey:0 value:&val]);
+  XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra);
+  XCTAssertEqual(msg2.unknownFields.countOfFields, 0U);
+
+  XCTAssertEqualObjects(orig, msg2);
+
+  [orig release];
+}
+
+#pragma mark - Map Round Tripping
+
+- (void)testProto2MapRoundTripping {
+  Message2 *msg = [[Message2 alloc] init];
+
+  // Key/Value data should result in different byte lengths on wire to ensure
+  // everything is right.
+  [msg.mapInt32Int32 setValue:1000 forKey:200];
+  [msg.mapInt32Int32 setValue:101 forKey:2001];
+  [msg.mapInt64Int64 setValue:1002 forKey:202];
+  [msg.mapInt64Int64 setValue:103 forKey:2003];
+  [msg.mapUint32Uint32 setValue:1004 forKey:204];
+  [msg.mapUint32Uint32 setValue:105 forKey:2005];
+  [msg.mapUint64Uint64 setValue:1006 forKey:206];
+  [msg.mapUint64Uint64 setValue:107 forKey:2007];
+  [msg.mapSint32Sint32 setValue:1008 forKey:208];
+  [msg.mapSint32Sint32 setValue:109 forKey:2009];
+  [msg.mapSint64Sint64 setValue:1010 forKey:210];
+  [msg.mapSint64Sint64 setValue:111 forKey:2011];
+  [msg.mapFixed32Fixed32 setValue:1012 forKey:212];
+  [msg.mapFixed32Fixed32 setValue:113 forKey:2013];
+  [msg.mapFixed64Fixed64 setValue:1014 forKey:214];
+  [msg.mapFixed64Fixed64 setValue:115 forKey:2015];
+  [msg.mapSfixed32Sfixed32 setValue:1016 forKey:216];
+  [msg.mapSfixed32Sfixed32 setValue:117 forKey:2017];
+  [msg.mapSfixed64Sfixed64 setValue:1018 forKey:218];
+  [msg.mapSfixed64Sfixed64 setValue:119 forKey:2019];
+  [msg.mapInt32Float setValue:1020.f forKey:220];
+  [msg.mapInt32Float setValue:121.f forKey:2021];
+  [msg.mapInt32Double setValue:1022. forKey:222];
+  [msg.mapInt32Double setValue:123. forKey:2023];
+  [msg.mapBoolBool setValue:false forKey:true];
+  [msg.mapBoolBool setValue:true forKey:false];
+  msg.mapStringString[@"224"] = @"1024";
+  msg.mapStringString[@"2025"] = @"125";
+  msg.mapStringBytes[@"226"] = DataFromCStr("1026");
+  msg.mapStringBytes[@"2027"] = DataFromCStr("127");
+  Message2 *val1 = [[Message2 alloc] init];
+  val1.optionalInt32 = 1028;
+  Message2 *val2 = [[Message2 alloc] init];
+  val2.optionalInt32 = 129;
+  [msg.mapStringMessage setValue:val1 forKey:@"228"];
+  [msg.mapStringMessage setValue:val2 forKey:@"2029"];
+  [msg.mapInt32Bytes setObject:DataFromCStr("1030 bytes") forKey:230];
+  [msg.mapInt32Bytes setObject:DataFromCStr("131") forKey:2031];
+  [msg.mapInt32Enum setValue:Message2_Enum_Bar forKey:232];
+  [msg.mapInt32Enum setValue:Message2_Enum_Baz forKey:2033];
+  Message2 *val3 = [[Message2 alloc] init];
+  val3.optionalInt32 = 1034;
+  Message2 *val4 = [[Message2 alloc] init];
+  val4.optionalInt32 = 135;
+  [msg.mapInt32Message setObject:val3 forKey:234];
+  [msg.mapInt32Message setObject:val4 forKey:2035];
+
+  NSData *data = [msg data];
+  XCTAssertNotNil(data);
+  Message2 *msg2 = [[Message2 alloc] initWithData:data error:NULL];
+
+  XCTAssertNotEqual(msg2, msg);  // Pointer comparison
+  XCTAssertEqualObjects(msg2, msg);
+
+  [val4 release];
+  [val3 release];
+  [val2 release];
+  [val1 release];
+  [msg2 release];
+  [msg release];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests.m
new file mode 100644
index 0000000..89d1fce
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBMessageTests.m
@@ -0,0 +1,2022 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBDescriptor.h"
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+@interface MessageTests : GPBTestCase
+@end
+
+@implementation MessageTests
+
+// TODO(thomasvl): this should get split into a few files of logic junks, it is
+// a jumble of things at the moment (and the testutils have a bunch of the real
+// assertions).
+
+- (TestAllTypes *)mergeSource {
+  TestAllTypes *message = [TestAllTypes message];
+  [message setOptionalInt32:1];
+  [message setOptionalString:@"foo"];
+  [message setOptionalForeignMessage:[ForeignMessage message]];
+  [message.repeatedStringArray addObject:@"bar"];
+  return message;
+}
+
+- (TestAllTypes *)mergeDestination {
+  TestAllTypes *message = [TestAllTypes message];
+  [message setOptionalInt64:2];
+  [message setOptionalString:@"baz"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setC:3];
+  [message setOptionalForeignMessage:foreignMessage];
+  [message.repeatedStringArray addObject:@"qux"];
+  return message;
+}
+
+- (TestAllTypes *)mergeDestinationWithoutForeignMessageIvar {
+  TestAllTypes *message = [TestAllTypes message];
+  [message setOptionalInt64:2];
+  [message setOptionalString:@"baz"];
+  [message.repeatedStringArray addObject:@"qux"];
+  return message;
+}
+
+- (TestAllTypes *)mergeResult {
+  TestAllTypes *message = [TestAllTypes message];
+  [message setOptionalInt32:1];
+  [message setOptionalInt64:2];
+  [message setOptionalString:@"foo"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setC:3];
+  [message setOptionalForeignMessage:foreignMessage];
+  [message.repeatedStringArray addObject:@"qux"];
+  [message.repeatedStringArray addObject:@"bar"];
+  return message;
+}
+
+- (TestAllTypes *)mergeResultForDestinationWithoutForeignMessageIvar {
+  TestAllTypes *message = [TestAllTypes message];
+  [message setOptionalInt32:1];
+  [message setOptionalInt64:2];
+  [message setOptionalString:@"foo"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [message setOptionalForeignMessage:foreignMessage];
+  [message.repeatedStringArray addObject:@"qux"];
+  [message.repeatedStringArray addObject:@"bar"];
+  return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsDestination {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+  [message setExtension:[UnittestRoot optionalStringExtension] value:@"foo"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  foreignMessage.c = 4;
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+                  value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+                  value:nestedMessage];
+  return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsSource {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+  [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+                  value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  nestedMessage.bb = 7;
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+                  value:nestedMessage];
+  return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsResult {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+  [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+  [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  foreignMessage.c = 4;
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+                  value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  nestedMessage.bb = 7;
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+                  value:nestedMessage];
+  return message;
+}
+
+- (void)testMergeFrom {
+  TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+  [result mergeFrom:self.mergeSource];
+  NSData *resultData = [result data];
+  NSData *mergeResultData = [self.mergeResult data];
+  XCTAssertEqualObjects(resultData, mergeResultData);
+  XCTAssertEqualObjects(result, self.mergeResult);
+
+  // Test when destination does not have an Ivar (type is an object) but source
+  // has such Ivar.
+  // The result must has the Ivar which is same as the one in source.
+  result = [[self.mergeDestinationWithoutForeignMessageIvar copy] autorelease];
+  [result mergeFrom:self.mergeSource];
+  resultData = [result data];
+  mergeResultData =
+      [self.mergeResultForDestinationWithoutForeignMessageIvar data];
+  XCTAssertEqualObjects(resultData, mergeResultData);
+  XCTAssertEqualObjects(
+      result, self.mergeResultForDestinationWithoutForeignMessageIvar);
+
+  // Test when destination is empty.
+  // The result must is same as the source.
+  result = [TestAllTypes message];
+  [result mergeFrom:self.mergeSource];
+  resultData = [result data];
+  mergeResultData = [self.mergeSource data];
+  XCTAssertEqualObjects(resultData, mergeResultData);
+  XCTAssertEqualObjects(result, self.mergeSource);
+}
+
+- (void)testMergeFromWithExtensions {
+  TestAllExtensions *result = [self mergeExtensionsDestination];
+  [result mergeFrom:[self mergeExtensionsSource]];
+  NSData *resultData = [result data];
+  NSData *mergeResultData = [[self mergeExtensionsResult] data];
+  XCTAssertEqualObjects(resultData, mergeResultData);
+  XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+
+  // Test merging from data.
+  result = [self mergeExtensionsDestination];
+  NSData *data = [[self mergeExtensionsSource] data];
+  XCTAssertNotNil(data);
+  [result mergeFromData:data
+      extensionRegistry:[UnittestRoot extensionRegistry]];
+  resultData = [result data];
+  XCTAssertEqualObjects(resultData, mergeResultData);
+  XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+}
+
+- (void)testIsEquals {
+  TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+  [result mergeFrom:self.mergeSource];
+  XCTAssertEqualObjects(result.data, self.mergeResult.data);
+  XCTAssertEqualObjects(result, self.mergeResult);
+  TestAllTypes *result2 = [[self.mergeDestination copy] autorelease];
+  XCTAssertNotEqualObjects(result2.data, self.mergeResult.data);
+  XCTAssertNotEqualObjects(result2, self.mergeResult);
+}
+
+// =================================================================
+// Required-field-related tests.
+
+- (TestRequired *)testRequiredInitialized {
+  TestRequired *message = [TestRequired message];
+  [message setA:1];
+  [message setB:2];
+  [message setC:3];
+  return message;
+}
+
+- (void)testRequired {
+  TestRequired *message = [TestRequired message];
+
+  XCTAssertFalse(message.initialized);
+  [message setA:1];
+  XCTAssertFalse(message.initialized);
+  [message setB:1];
+  XCTAssertFalse(message.initialized);
+  [message setC:1];
+  XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredForeign {
+  TestRequiredForeign *message = [TestRequiredForeign message];
+
+  XCTAssertTrue(message.initialized);
+
+  [message setOptionalMessage:[TestRequired message]];
+  XCTAssertFalse(message.initialized);
+
+  [message setOptionalMessage:self.testRequiredInitialized];
+  XCTAssertTrue(message.initialized);
+
+  [message.repeatedMessageArray addObject:[TestRequired message]];
+  XCTAssertFalse(message.initialized);
+
+  [message.repeatedMessageArray removeAllObjects];
+  [message.repeatedMessageArray addObject:self.testRequiredInitialized];
+  XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredExtension {
+  TestAllExtensions *message = [TestAllExtensions message];
+
+  XCTAssertTrue(message.initialized);
+
+  [message setExtension:[TestRequired single] value:[TestRequired message]];
+  XCTAssertFalse(message.initialized);
+
+  [message setExtension:[TestRequired single]
+                  value:self.testRequiredInitialized];
+  XCTAssertTrue(message.initialized);
+
+  [message addExtension:[TestRequired multi] value:[TestRequired message]];
+  XCTAssertFalse(message.initialized);
+
+  [message setExtension:[TestRequired multi]
+                  index:0
+                  value:self.testRequiredInitialized];
+  XCTAssertTrue(message.initialized);
+}
+
+- (void)testDataFromUninitialized {
+  TestRequired *message = [TestRequired message];
+  NSData *data = [message data];
+  // In DEBUG, the data generation will fail, but in non DEBUG, it passes
+  // because the check isn't done (for speed).
+#ifdef DEBUG
+  XCTAssertNil(data);
+#else
+  XCTAssertNotNil(data);
+  XCTAssertFalse(message.initialized);
+#endif  // DEBUG
+}
+
+- (void)testInitialized {
+  // We're mostly testing that no exception is thrown.
+  TestRequired *message = [TestRequired message];
+  XCTAssertFalse(message.initialized);
+}
+
+- (void)testDataFromNestedUninitialized {
+  TestRequiredForeign *message = [TestRequiredForeign message];
+  [message setOptionalMessage:[TestRequired message]];
+  [message.repeatedMessageArray addObject:[TestRequired message]];
+  [message.repeatedMessageArray addObject:[TestRequired message]];
+  NSData *data = [message data];
+  // In DEBUG, the data generation will fail, but in non DEBUG, it passes
+  // because the check isn't done (for speed).
+#ifdef DEBUG
+  XCTAssertNil(data);
+#else
+  XCTAssertNotNil(data);
+  XCTAssertFalse(message.initialized);
+#endif  // DEBUG
+}
+
+- (void)testNestedInitialized {
+  // We're mostly testing that no exception is thrown.
+
+  TestRequiredForeign *message = [TestRequiredForeign message];
+  [message setOptionalMessage:[TestRequired message]];
+  [message.repeatedMessageArray addObject:[TestRequired message]];
+  [message.repeatedMessageArray addObject:[TestRequired message]];
+
+  XCTAssertFalse(message.initialized);
+}
+
+- (void)testParseUninitialized {
+  NSError *error = nil;
+  TestRequired *msg =
+      [TestRequired parseFromData:GPBEmptyNSData() error:&error];
+  // In DEBUG, the parse will fail, but in non DEBUG, it passes because
+  // the check isn't done (for speed).
+#ifdef DEBUG
+  XCTAssertNil(msg);
+  XCTAssertNotNil(error);
+  XCTAssertEqualObjects(error.domain, GPBMessageErrorDomain);
+  XCTAssertEqual(error.code, GPBMessageErrorCodeMissingRequiredField);
+#else
+  XCTAssertNotNil(msg);
+  XCTAssertNil(error);
+  XCTAssertFalse(msg.initialized);
+#endif  // DEBUG
+}
+
+- (void)testCoding {
+  NSData *data =
+      [NSKeyedArchiver archivedDataWithRootObject:[self mergeResult]];
+  id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+
+  XCTAssertEqualObjects(unarchivedObject, [self mergeResult]);
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(unarchivedObject, [self mergeResult]);
+}
+
+- (void)testObjectReset {
+  // Tests a failure where clearing out defaults values caused an over release.
+  TestAllTypes *message = [TestAllTypes message];
+  message.hasOptionalNestedMessage = NO;
+  [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+  message.hasOptionalNestedMessage = NO;
+  [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+  [message setOptionalNestedMessage:nil];
+  message.hasOptionalNestedMessage = NO;
+}
+
+- (void)testSettingHasToYes {
+  TestAllTypes *message = [TestAllTypes message];
+  XCTAssertThrows([message setHasOptionalNestedMessage:YES]);
+}
+
+- (void)testRoot {
+  XCTAssertNotNil([UnittestRoot extensionRegistry]);
+}
+
+- (void)testGPBMessageSize {
+  // See the note in GPBMessage_PackagePrivate.h about why we want to keep the
+  // base instance size pointer size aligned.
+  size_t messageSize = class_getInstanceSize([GPBMessage class]);
+  XCTAssertEqual((messageSize % sizeof(void *)), (size_t)0,
+                 @"Base size isn't pointer size aligned");
+
+  // Since we add storage ourselves (see +allocWithZone: in GPBMessage), confirm
+  // that the size of some generated classes is still the same as the base for
+  // that logic to work as desired.
+  size_t testMessageSize = class_getInstanceSize([TestAllTypes class]);
+  XCTAssertEqual(testMessageSize, messageSize);
+}
+
+- (void)testInit {
+  TestAllTypes *message = [TestAllTypes message];
+  [self assertClear:message];
+}
+
+- (void)testAccessors {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testKVC_ValueForKey {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testKVC_SetValue_ForKey {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFieldsViaKVC:message repeatedCount:kGPBDefaultRepeatCount];
+  [self assertAllFieldsKVCMatch:message];
+  [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+  [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testDescription {
+  // No real test, just exercise code
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+
+  GPBUnknownFieldSet *unknownFields =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownField *field =
+      [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
+  [field addVarint:2];
+  [unknownFields addField:field];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
+  [field addVarint:4];
+  [unknownFields addField:field];
+
+  [message setUnknownFields:unknownFields];
+
+  NSString *description = [message description];
+  XCTAssertGreaterThan([description length], 0U);
+
+  GPBMessage *message2 = [TestAllExtensions message];
+  [message2 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+  [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@2];
+
+  description = [message2 description];
+  XCTAssertGreaterThan([description length], 0U);
+}
+
+- (void)testSetter {
+  // Test to make sure that if we set a value that has a default value
+  // with the default, that the has is set, and the value gets put into the
+  // message correctly.
+  TestAllTypes *message = [TestAllTypes message];
+  GPBDescriptor *descriptor = [[message class] descriptor];
+  XCTAssertNotNil(descriptor);
+  GPBFieldDescriptor *fieldDescriptor =
+      [descriptor fieldWithName:@"defaultInt32"];
+  XCTAssertNotNil(fieldDescriptor);
+  GPBGenericValue defaultValue = [fieldDescriptor defaultValue];
+  [message setDefaultInt32:defaultValue.valueInt32];
+  XCTAssertTrue(message.hasDefaultInt32);
+  XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32);
+
+  // Do the same thing with an object type.
+  message = [TestAllTypes message];
+  fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+  XCTAssertNotNil(fieldDescriptor);
+  defaultValue = [fieldDescriptor defaultValue];
+  [message setDefaultString:defaultValue.valueString];
+  XCTAssertTrue(message.hasDefaultString);
+  XCTAssertEqualObjects(message.defaultString, defaultValue.valueString);
+
+  // Test default string type.
+  message = [TestAllTypes message];
+  XCTAssertEqualObjects(message.defaultString, @"hello");
+  XCTAssertFalse(message.hasDefaultString);
+  fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+  XCTAssertNotNil(fieldDescriptor);
+  defaultValue = [fieldDescriptor defaultValue];
+  [message setDefaultString:defaultValue.valueString];
+  XCTAssertEqualObjects(message.defaultString, @"hello");
+  XCTAssertTrue(message.hasDefaultString);
+  [message setDefaultString:nil];
+  XCTAssertEqualObjects(message.defaultString, @"hello");
+  XCTAssertFalse(message.hasDefaultString);
+  message.hasDefaultString = NO;
+  XCTAssertFalse(message.hasDefaultString);
+  XCTAssertEqualObjects(message.defaultString, @"hello");
+
+  // Test default bytes type.
+  NSData *defaultBytes = [@"world" dataUsingEncoding:NSUTF8StringEncoding];
+  XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+  XCTAssertFalse(message.hasDefaultString);
+  fieldDescriptor = [descriptor fieldWithName:@"defaultBytes"];
+  XCTAssertNotNil(fieldDescriptor);
+  defaultValue = [fieldDescriptor defaultValue];
+  [message setDefaultBytes:defaultValue.valueData];
+  XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+  XCTAssertTrue(message.hasDefaultBytes);
+  [message setDefaultBytes:nil];
+  XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+  XCTAssertFalse(message.hasDefaultBytes);
+  message.hasDefaultBytes = NO;
+  XCTAssertFalse(message.hasDefaultBytes);
+  XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+
+  // Test optional string.
+  XCTAssertFalse(message.hasOptionalString);
+  XCTAssertEqualObjects(message.optionalString, @"");
+  XCTAssertFalse(message.hasOptionalString);
+  message.optionalString = nil;
+  XCTAssertFalse(message.hasOptionalString);
+  XCTAssertEqualObjects(message.optionalString, @"");
+  NSString *string = @"string";
+  message.optionalString = string;
+  XCTAssertEqualObjects(message.optionalString, string);
+  XCTAssertTrue(message.hasOptionalString);
+  message.optionalString = nil;
+  XCTAssertFalse(message.hasOptionalString);
+  XCTAssertEqualObjects(message.optionalString, @"");
+
+  // Test optional data.
+  XCTAssertFalse(message.hasOptionalBytes);
+  XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+  XCTAssertFalse(message.hasOptionalBytes);
+  message.optionalBytes = nil;
+  XCTAssertFalse(message.hasOptionalBytes);
+  XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+  NSData *data = [@"bytes" dataUsingEncoding:NSUTF8StringEncoding];
+  message.optionalBytes = data;
+  XCTAssertEqualObjects(message.optionalBytes, data);
+  XCTAssertTrue(message.hasOptionalBytes);
+  message.optionalBytes = nil;
+  XCTAssertFalse(message.hasOptionalBytes);
+  XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+  // Test lazy message setting
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  XCTAssertNotNil(message.optionalLazyMessage);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  message.hasOptionalLazyMessage = NO;
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  XCTAssertNotNil(message.optionalLazyMessage);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  message.optionalLazyMessage = nil;
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+
+  // Test nested messages
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  message.optionalLazyMessage.bb = 1;
+  XCTAssertTrue(message.hasOptionalLazyMessage);
+  XCTAssertEqual(message.optionalLazyMessage.bb, 1);
+  XCTAssertNotNil(message.optionalLazyMessage);
+  message.optionalLazyMessage = nil;
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  XCTAssertEqual(message.optionalLazyMessage.bb, 0);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+  XCTAssertNotNil(message.optionalLazyMessage);
+
+  // -testDefaultSubMessages tests the "defaulting" handling of fields
+  // containing messages.
+}
+
+- (void)testRepeatedSetters {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [self modifyRepeatedFields:message];
+  [self assertRepeatedFieldsModified:message
+                       repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testClear {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [self clearAllFields:message];
+  [self assertClear:message];
+  TestAllTypes *message2 = [TestAllTypes message];
+  XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testClearKVC {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+  [self clearAllFields:message];
+  [self assertClear:message];
+  [self assertClearKVC:message];
+}
+
+- (void)testClearExtension {
+  // clearExtension() is not actually used in TestUtil, so try it manually.
+  GPBMessage *message1 = [TestAllExtensions message];
+  [message1 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+  XCTAssertTrue([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+  [message1 clearExtension:[UnittestRoot optionalInt32Extension]];
+  XCTAssertFalse([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+
+  GPBMessage *message2 = [TestAllExtensions message];
+  [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@1];
+
+  XCTAssertEqual(
+      [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+      (NSUInteger)1);
+  [message2 clearExtension:[UnittestRoot repeatedInt32Extension]];
+  XCTAssertEqual(
+      [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+      (NSUInteger)0);
+
+  // Clearing an unset extension field shouldn't make the target message
+  // visible.
+  GPBMessage *message3 = [TestAllExtensions message];
+  GPBMessage *extension_msg =
+      [message3 getExtension:[UnittestObjcRoot recursiveExtension]];
+  XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+  [extension_msg clearExtension:[UnittestRoot optionalInt32Extension]];
+  XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+}
+
+- (void)testDefaultingSubMessages {
+  TestAllTypes *message = [TestAllTypes message];
+
+  // Initially they should all not have values.
+
+  XCTAssertFalse(message.hasOptionalGroup);
+  XCTAssertFalse(message.hasOptionalNestedMessage);
+  XCTAssertFalse(message.hasOptionalForeignMessage);
+  XCTAssertFalse(message.hasOptionalImportMessage);
+  XCTAssertFalse(message.hasOptionalPublicImportMessage);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+
+  // They should auto create something when fetched.
+
+  TestAllTypes_OptionalGroup *optionalGroup = [message.optionalGroup retain];
+  TestAllTypes_NestedMessage *optionalNestedMessage =
+      [message.optionalNestedMessage retain];
+  ForeignMessage *optionalForeignMessage =
+      [message.optionalForeignMessage retain];
+  ImportMessage *optionalImportMessage = [message.optionalImportMessage retain];
+  PublicImportMessage *optionalPublicImportMessage =
+      [message.optionalPublicImportMessage retain];
+  TestAllTypes_NestedMessage *optionalLazyMessage =
+      [message.optionalLazyMessage retain];
+
+  XCTAssertNotNil(optionalGroup);
+  XCTAssertNotNil(optionalNestedMessage);
+  XCTAssertNotNil(optionalForeignMessage);
+  XCTAssertNotNil(optionalImportMessage);
+  XCTAssertNotNil(optionalPublicImportMessage);
+  XCTAssertNotNil(optionalLazyMessage);
+
+  // Although they were created, they should not respond to hasValue until that
+  // submessage is mutated.
+
+  XCTAssertFalse(message.hasOptionalGroup);
+  XCTAssertFalse(message.hasOptionalNestedMessage);
+  XCTAssertFalse(message.hasOptionalForeignMessage);
+  XCTAssertFalse(message.hasOptionalImportMessage);
+  XCTAssertFalse(message.hasOptionalPublicImportMessage);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+
+  // And they set that value back in to the message since the value created was
+  // mutable (so a second fetch should give the same object).
+
+  XCTAssertEqual(message.optionalGroup, optionalGroup);
+  XCTAssertEqual(message.optionalNestedMessage, optionalNestedMessage);
+  XCTAssertEqual(message.optionalForeignMessage, optionalForeignMessage);
+  XCTAssertEqual(message.optionalImportMessage, optionalImportMessage);
+  XCTAssertEqual(message.optionalPublicImportMessage,
+                 optionalPublicImportMessage);
+  XCTAssertEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+  // And the default objects for a second message should be distinct (again,
+  // since they are mutable, each needs their own copy).
+
+  TestAllTypes *message2 = [TestAllTypes message];
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(message2.optionalGroup, optionalGroup);
+  XCTAssertNotEqual(message2.optionalNestedMessage, optionalNestedMessage);
+  XCTAssertNotEqual(message2.optionalForeignMessage, optionalForeignMessage);
+  XCTAssertNotEqual(message2.optionalImportMessage, optionalImportMessage);
+  XCTAssertNotEqual(message2.optionalPublicImportMessage,
+                    optionalPublicImportMessage);
+  XCTAssertNotEqual(message2.optionalLazyMessage, optionalLazyMessage);
+
+  // Setting the values to nil will clear the has flag, and on next access you
+  // get back new submessages.
+
+  message.optionalGroup = nil;
+  message.optionalNestedMessage = nil;
+  message.optionalForeignMessage = nil;
+  message.optionalImportMessage = nil;
+  message.optionalPublicImportMessage = nil;
+  message.optionalLazyMessage = nil;
+
+  XCTAssertFalse(message.hasOptionalGroup);
+  XCTAssertFalse(message.hasOptionalNestedMessage);
+  XCTAssertFalse(message.hasOptionalForeignMessage);
+  XCTAssertFalse(message.hasOptionalImportMessage);
+  XCTAssertFalse(message.hasOptionalPublicImportMessage);
+  XCTAssertFalse(message.hasOptionalLazyMessage);
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(message.optionalGroup, optionalGroup);
+  XCTAssertNotEqual(message.optionalNestedMessage, optionalNestedMessage);
+  XCTAssertNotEqual(message.optionalForeignMessage, optionalForeignMessage);
+  XCTAssertNotEqual(message.optionalImportMessage, optionalImportMessage);
+  XCTAssertNotEqual(message.optionalPublicImportMessage,
+                    optionalPublicImportMessage);
+  XCTAssertNotEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+  [optionalGroup release];
+  [optionalNestedMessage release];
+  [optionalForeignMessage release];
+  [optionalImportMessage release];
+  [optionalPublicImportMessage release];
+  [optionalLazyMessage release];
+}
+
+- (void)testMultiplePointersToAutocreatedMessage {
+  // Multiple objects pointing to the same autocreated message.
+  TestAllTypes *message = [TestAllTypes message];
+  TestAllTypes *message2 = [TestAllTypes message];
+  message2.optionalGroup = message.optionalGroup;
+  XCTAssertTrue([message2 hasOptionalGroup]);
+  XCTAssertFalse([message hasOptionalGroup]);
+  message2.optionalGroup.a = 42;
+  XCTAssertTrue([message hasOptionalGroup]);
+  XCTAssertTrue([message2 hasOptionalGroup]);
+}
+
+- (void)testCopyWithAutocreatedMessage {
+  // Mutable copy should not copy autocreated messages.
+  TestAllTypes *message = [TestAllTypes message];
+  message.optionalGroup.a = 42;
+  XCTAssertNotNil(message.optionalNestedMessage);
+  TestAllTypes *message2 = [[message copy] autorelease];
+  XCTAssertTrue([message2 hasOptionalGroup]);
+  XCTAssertFalse([message2 hasOptionalNestedMessage]);
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(message.optionalNestedMessage,
+                    message2.optionalNestedMessage);
+}
+
+- (void)testClearAutocreatedSubmessage {
+  // Call clear on an intermediate submessage should cause it to get recreated
+  // on the next call.
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  TestRecursiveMessage *message_inner = [message.a.a.a retain];
+  XCTAssertNotNil(message_inner);
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+  [message.a.a clear];
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(message.a.a.a, message_inner);
+  [message_inner release];
+}
+
+- (void)testRetainAutocreatedSubmessage {
+  // Should be able to retain autocreated submessage while the creator is
+  // dealloced.
+  TestAllTypes *message = [TestAllTypes message];
+
+  ForeignMessage *subMessage;
+  @autoreleasepool {
+    TestAllTypes *message2 = [TestAllTypes message];
+    subMessage = message2.optionalForeignMessage; // Autocreated
+    message.optionalForeignMessage = subMessage;
+    XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage,
+                                             message2));
+  }
+
+  // Should be the same object, and should still be live.
+  XCTAssertEqual(message.optionalForeignMessage, subMessage);
+  XCTAssertNotNil([subMessage description]);
+}
+
+- (void)testSetNilAutocreatedSubmessage {
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  TestRecursiveMessage *message_inner = [message.a.a retain];
+  XCTAssertFalse([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+  message.a.a = nil;
+
+  // |message.a| has to be made visible, but |message.a.a| was set to nil so
+  // shouldn't be.
+  XCTAssertTrue([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+
+  // Setting submessage to nil should cause it to lose its creator.
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a));
+
+  // After setting to nil, getting it again should create a new autocreated
+  // message.
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(message.a.a, message_inner);
+
+  [message_inner release];
+}
+
+- (void)testSetDoesntHaveAutocreatedSubmessage {
+  // Clearing submessage (set has == NO) should NOT cause it to lose its
+  // creator.
+  TestAllTypes *message = [TestAllTypes message];
+  TestAllTypes_NestedMessage *nestedMessage = message.optionalNestedMessage;
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+  [message setHasOptionalNestedMessage:NO];
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+  XCTAssertEqual(message.optionalNestedMessage, nestedMessage);
+}
+
+- (void)testSetAutocreatedMessageBecomesVisible {
+  // Setting a value should cause the submessage to appear to its creator.
+  // Test this several levels deep.
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  message.a.a.a.a.i = 42;
+  XCTAssertTrue([message hasA]);
+  XCTAssertTrue([message.a hasA]);
+  XCTAssertTrue([message.a.a hasA]);
+  XCTAssertTrue([message.a.a.a hasA]);
+  XCTAssertFalse([message.a.a.a.a hasA]);
+  XCTAssertEqual(message.a.a.a.a.i, 42);
+}
+
+- (void)testClearUnsetFieldOfAutocreatedMessage {
+  // Clearing an unset field should not cause the submessage to appear to its
+  // creator.
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  message.a.a.a.a.hasI = NO;
+  XCTAssertFalse([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+  XCTAssertFalse([message.a.a hasA]);
+  XCTAssertFalse([message.a.a.a hasA]);
+}
+
+- (void)testAutocreatedSubmessageAssignSkip {
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  TestRecursiveMessage *messageLevel1 = [message.a retain];
+  TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+  TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+  TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+  // Test skipping over an autocreated submessage and ensure it gets unset.
+  message.a = message.a.a;
+  XCTAssertEqual(message.a, messageLevel2);
+  XCTAssertTrue([message hasA]);
+  XCTAssertEqual(message.a.a, messageLevel3);
+  XCTAssertFalse([message.a hasA]);
+  XCTAssertEqual(message.a.a.a, messageLevel4);
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+                                            message));  // Because it was orphaned.
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+
+  [messageLevel1 release];
+  [messageLevel2 release];
+  [messageLevel3 release];
+  [messageLevel4 release];
+}
+
+- (void)testAutocreatedSubmessageAssignLoop {
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  TestRecursiveMessage *messageLevel1 = [message.a retain];
+  TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+  TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+  TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+  XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+  // Test a property with a loop. You'd never do this but at least ensure the
+  // autocreated submessages behave sanely.
+  message.a.a = message.a;
+  XCTAssertTrue([message hasA]);
+  XCTAssertEqual(message.a, messageLevel1);
+  XCTAssertTrue([message.a hasA]);
+  XCTAssertEqual(message.a.a, messageLevel1);
+  XCTAssertTrue([message.a.a hasA]);
+  XCTAssertEqual(message.a.a.a, messageLevel1);
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+                                            message));  // Because it was assigned.
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel2,
+                                            messageLevel1));  // Because it was orphaned.
+  XCTAssertFalse([messageLevel2 hasA]);
+
+  // Break the retain loop.
+  message.a.a = nil;
+  XCTAssertTrue([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+
+  [messageLevel1 release];
+  [messageLevel2 release];
+  [messageLevel3 release];
+  [messageLevel4 release];
+}
+
+- (void)testSetAutocreatedSubmessage {
+  // Setting autocreated submessage to another value should cause the old one to
+  // lose its creator.
+  TestAllTypes *message = [TestAllTypes message];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [message.optionalNestedMessage retain];
+
+  message.optionalNestedMessage = [TestAllTypes_NestedMessage message];
+  XCTAssertTrue([message hasOptionalNestedMessage]);
+  XCTAssertTrue(message.optionalNestedMessage != nestedMessage);
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(nestedMessage, message));
+
+  [nestedMessage release];
+}
+
+- (void)testAutocreatedUnknownFields {
+  // Doing anything with (except reading) unknown fields should cause the
+  // submessage to become visible.
+  TestAllTypes *message = [TestAllTypes message];
+  XCTAssertNotNil(message.optionalNestedMessage);
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+  XCTAssertNil(message.optionalNestedMessage.unknownFields);
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+
+  GPBUnknownFieldSet *unknownFields =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  message.optionalNestedMessage.unknownFields = unknownFields;
+  XCTAssertTrue([message hasOptionalNestedMessage]);
+
+  message.optionalNestedMessage = nil;
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+  [message.optionalNestedMessage setUnknownFields:unknownFields];
+  XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testSetAutocreatedSubmessageToSelf {
+  // Setting submessage to itself should cause it to become visible.
+  TestAllTypes *message = [TestAllTypes message];
+  XCTAssertNotNil(message.optionalNestedMessage);
+  XCTAssertFalse([message hasOptionalNestedMessage]);
+  message.optionalNestedMessage = message.optionalNestedMessage;
+  XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testAutocreatedSubmessageMemoryLeaks {
+  // Test for memory leaks with autocreated submessages.
+  TestRecursiveMessage *message;
+  TestRecursiveMessage *messageLevel1;
+  TestRecursiveMessage *messageLevel2;
+  TestRecursiveMessage *messageLevel3;
+  TestRecursiveMessage *messageLevel4;
+  @autoreleasepool {
+    message = [[TestRecursiveMessage alloc] init];
+    messageLevel1 = [message.a retain];
+    messageLevel2 = [message.a.a retain];
+    messageLevel3 = [message.a.a.a retain];
+    messageLevel4 = [message.a.a.a.a retain];
+    message.a.i = 1;
+  }
+
+  XCTAssertEqual(message.retainCount, (NSUInteger)1);
+  [message release];
+  XCTAssertEqual(messageLevel1.retainCount, (NSUInteger)1);
+  [messageLevel1 release];
+  XCTAssertEqual(messageLevel2.retainCount, (NSUInteger)1);
+  [messageLevel2 release];
+  XCTAssertEqual(messageLevel3.retainCount, (NSUInteger)1);
+  [messageLevel3 release];
+  XCTAssertEqual(messageLevel4.retainCount, (NSUInteger)1);
+  [messageLevel4 release];
+}
+
+- (void)testDefaultingArrays {
+  // Basic tests for default creation of arrays in a message.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2 =
+      [TestRecursiveMessageWithRepeatedField message];
+
+  // Simply accessing the array should not make any fields visible.
+  XCTAssertNotNil(message.a.a.iArray);
+  XCTAssertFalse([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+  XCTAssertNotNil(message2.a.a.strArray);
+  XCTAssertFalse([message2 hasA]);
+  XCTAssertFalse([message2.a hasA]);
+
+  // But adding an element to the array should.
+  [message.a.a.iArray addValue:42];
+  XCTAssertTrue([message hasA]);
+  XCTAssertTrue([message.a hasA]);
+  XCTAssertEqual([message.a.a.iArray count], (NSUInteger)1);
+  [message2.a.a.strArray addObject:@"foo"];
+  XCTAssertTrue([message2 hasA]);
+  XCTAssertTrue([message2.a hasA]);
+  XCTAssertEqual([message2.a.a.strArray count], (NSUInteger)1);
+}
+
+- (void)testAutocreatedArrayShared {
+  // Multiple objects pointing to the same array.
+  TestRecursiveMessageWithRepeatedField *message1a =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message1b =
+      [TestRecursiveMessageWithRepeatedField message];
+  message1a.a.iArray = message1b.a.iArray;
+  XCTAssertTrue([message1a hasA]);
+  XCTAssertFalse([message1b hasA]);
+  [message1a.a.iArray addValue:1];
+  XCTAssertTrue([message1a hasA]);
+  XCTAssertTrue([message1b hasA]);
+  XCTAssertEqual(message1a.a.iArray, message1b.a.iArray);
+
+  TestRecursiveMessageWithRepeatedField *message2a =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2b =
+      [TestRecursiveMessageWithRepeatedField message];
+  message2a.a.strArray = message2b.a.strArray;
+  XCTAssertTrue([message2a hasA]);
+  XCTAssertFalse([message2b hasA]);
+  [message2a.a.strArray addObject:@"bar"];
+  XCTAssertTrue([message2a hasA]);
+  XCTAssertTrue([message2b hasA]);
+  XCTAssertEqual(message2a.a.strArray, message2b.a.strArray);
+}
+
+- (void)testAutocreatedArrayCopy {
+  // Copy should not copy autocreated arrays.
+  TestAllTypes *message = [TestAllTypes message];
+  XCTAssertNotNil(message.repeatedStringArray);
+  XCTAssertNotNil(message.repeatedInt32Array);
+  TestAllTypes *message2 = [[message copy] autorelease];
+  // Pointer conparisions.
+  XCTAssertNotEqual(message.repeatedStringArray, message2.repeatedStringArray);
+  XCTAssertNotEqual(message.repeatedInt32Array, message2.repeatedInt32Array);
+
+  // Mutable copy should copy empty arrays that were explicitly set (end up
+  // with different objects that are equal).
+  TestAllTypes *message3 = [TestAllTypes message];
+  message3.repeatedInt32Array = [GPBInt32Array arrayWithValue:42];
+  message3.repeatedStringArray = [NSMutableArray arrayWithObject:@"wee"];
+  XCTAssertNotNil(message.repeatedInt32Array);
+  XCTAssertNotNil(message.repeatedStringArray);
+  TestAllTypes *message4 = [[message3 copy] autorelease];
+  XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array);
+  XCTAssertEqualObjects(message3.repeatedInt32Array,
+                        message4.repeatedInt32Array);
+  XCTAssertNotEqual(message3.repeatedStringArray, message4.repeatedStringArray);
+  XCTAssertEqualObjects(message3.repeatedStringArray,
+                        message4.repeatedStringArray);
+}
+
+- (void)testAutocreatedArrayRetain {
+  // Should be able to retain autocreated array while the creator is dealloced.
+  TestAllTypes *message = [TestAllTypes message];
+
+  @autoreleasepool {
+    TestAllTypes *message2 = [TestAllTypes message];
+    message.repeatedInt32Array = message2.repeatedInt32Array;
+    message.repeatedStringArray = message2.repeatedStringArray;
+    // Pointer conparision
+    XCTAssertEqual(message.repeatedInt32Array->_autocreator, message2);
+    XCTAssertTrue([message.repeatedStringArray
+        isKindOfClass:[GPBAutocreatedArray class]]);
+    XCTAssertEqual(
+        ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator,
+        message2);
+  }
+
+  XCTAssertNil(message.repeatedInt32Array->_autocreator);
+  XCTAssertTrue(
+      [message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+  XCTAssertNil(
+      ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator);
+}
+
+- (void)testSetNilAutocreatedArray {
+  // Setting array to nil should cause it to lose its delegate.
+  TestAllTypes *message = [TestAllTypes message];
+  GPBInt32Array *repeatedInt32Array = [message.repeatedInt32Array retain];
+  GPBAutocreatedArray *repeatedStringArray =
+      (GPBAutocreatedArray *)[message.repeatedStringArray retain];
+  XCTAssertTrue([repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+  XCTAssertEqual(repeatedInt32Array->_autocreator, message);
+  XCTAssertEqual(repeatedStringArray->_autocreator, message);
+  message.repeatedInt32Array = nil;
+  message.repeatedStringArray = nil;
+  XCTAssertNil(repeatedInt32Array->_autocreator);
+  XCTAssertNil(repeatedStringArray->_autocreator);
+  [repeatedInt32Array release];
+  [repeatedStringArray release];
+}
+
+- (void)testReplaceAutocreatedArray {
+  // Replacing array should orphan the old one and cause its creator to become
+  // visible.
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.iArray);
+    XCTAssertFalse([message hasA]);
+    GPBInt32Array *iArray = [message.a.iArray retain];
+    XCTAssertEqual(iArray->_autocreator, message.a);  // Pointer comparision
+    message.a.iArray = [GPBInt32Array arrayWithValue:1];
+    XCTAssertTrue([message hasA]);
+    XCTAssertNotEqual(message.a.iArray, iArray);  // Pointer comparision
+    XCTAssertNil(iArray->_autocreator);
+    [iArray release];
+  }
+
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.strArray);
+    XCTAssertFalse([message hasA]);
+    GPBAutocreatedArray *strArray =
+        (GPBAutocreatedArray *)[message.a.strArray retain];
+    XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]);
+    XCTAssertEqual(strArray->_autocreator, message.a);  // Pointer comparision
+    message.a.strArray = [NSMutableArray arrayWithObject:@"foo"];
+    XCTAssertTrue([message hasA]);
+    XCTAssertNotEqual(message.a.strArray, strArray);  // Pointer comparision
+    XCTAssertNil(strArray->_autocreator);
+    [strArray release];
+  }
+}
+
+- (void)testSetAutocreatedArrayToSelf {
+  // Setting array to itself should cause it to become visible.
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.iArray);
+    XCTAssertFalse([message hasA]);
+    message.a.iArray = message.a.iArray;
+    XCTAssertTrue([message hasA]);
+    XCTAssertNil(message.a.iArray->_autocreator);
+  }
+
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.strArray);
+    XCTAssertFalse([message hasA]);
+    message.a.strArray = message.a.strArray;
+    XCTAssertTrue([message hasA]);
+    XCTAssertTrue([message.a.strArray isKindOfClass:[GPBAutocreatedArray class]]);
+    XCTAssertNil(((GPBAutocreatedArray *)message.a.strArray)->_autocreator);
+  }
+}
+
+- (void)testAutocreatedArrayRemoveAllValues {
+  // Calling removeAllValues on autocreated array should not cause it to be
+  // visible.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  [message.a.iArray removeAll];
+  XCTAssertFalse([message hasA]);
+  [message.a.strArray removeAllObjects];
+  XCTAssertFalse([message hasA]);
+}
+
+- (void)testDefaultingMaps {
+  // Basic tests for default creation of maps in a message.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2 =
+      [TestRecursiveMessageWithRepeatedField message];
+
+  // Simply accessing the map should not make any fields visible.
+  XCTAssertNotNil(message.a.a.iToI);
+  XCTAssertFalse([message hasA]);
+  XCTAssertFalse([message.a hasA]);
+  XCTAssertNotNil(message2.a.a.strToStr);
+  XCTAssertFalse([message2 hasA]);
+  XCTAssertFalse([message2.a hasA]);
+
+  // But adding an element to the map should.
+  [message.a.a.iToI setValue:100 forKey:200];
+  XCTAssertTrue([message hasA]);
+  XCTAssertTrue([message.a hasA]);
+  XCTAssertEqual([message.a.a.iToI count], (NSUInteger)1);
+  [message2.a.a.strToStr setObject:@"foo" forKey:@"bar"];
+  XCTAssertTrue([message2 hasA]);
+  XCTAssertTrue([message2.a hasA]);
+  XCTAssertEqual([message2.a.a.strToStr count], (NSUInteger)1);
+}
+
+- (void)testAutocreatedMapShared {
+  // Multiple objects pointing to the same map.
+  TestRecursiveMessageWithRepeatedField *message1a =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message1b =
+      [TestRecursiveMessageWithRepeatedField message];
+  message1a.a.iToI = message1b.a.iToI;
+  XCTAssertTrue([message1a hasA]);
+  XCTAssertFalse([message1b hasA]);
+  [message1a.a.iToI setValue:1 forKey:2];
+  XCTAssertTrue([message1a hasA]);
+  XCTAssertTrue([message1b hasA]);
+  XCTAssertEqual(message1a.a.iToI, message1b.a.iToI);
+
+  TestRecursiveMessageWithRepeatedField *message2a =
+      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2b =
+      [TestRecursiveMessageWithRepeatedField message];
+  message2a.a.strToStr = message2b.a.strToStr;
+  XCTAssertTrue([message2a hasA]);
+  XCTAssertFalse([message2b hasA]);
+  [message2a.a.strToStr setObject:@"bar" forKey:@"foo"];
+  XCTAssertTrue([message2a hasA]);
+  XCTAssertTrue([message2b hasA]);
+  XCTAssertEqual(message2a.a.strToStr, message2b.a.strToStr);
+}
+
+- (void)testAutocreatedMapCopy {
+  // Copy should not copy autocreated maps.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  XCTAssertNotNil(message.strToStr);
+  XCTAssertNotNil(message.iToI);
+  TestRecursiveMessageWithRepeatedField *message2 =
+      [[message copy] autorelease];
+  // Pointer conparisions.
+  XCTAssertNotEqual(message.strToStr, message2.strToStr);
+  XCTAssertNotEqual(message.iToI, message2.iToI);
+
+  // Mutable copy should copy empty arrays that were explicitly set (end up
+  // with different objects that are equal).
+  TestRecursiveMessageWithRepeatedField *message3 =
+      [TestRecursiveMessageWithRepeatedField message];
+  message3.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:10 forKey:20];
+  message3.strToStr =
+      [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"];
+  XCTAssertNotNil(message.iToI);
+  XCTAssertNotNil(message.iToI);
+  TestRecursiveMessageWithRepeatedField *message4 =
+      [[message3 copy] autorelease];
+  XCTAssertNotEqual(message3.iToI, message4.iToI);
+  XCTAssertEqualObjects(message3.iToI, message4.iToI);
+  XCTAssertNotEqual(message3.strToStr, message4.strToStr);
+  XCTAssertEqualObjects(message3.strToStr, message4.strToStr);
+}
+
+- (void)testAutocreatedMapRetain {
+  // Should be able to retain autocreated map while the creator is dealloced.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+
+  @autoreleasepool {
+    TestRecursiveMessageWithRepeatedField *message2 =
+        [TestRecursiveMessageWithRepeatedField message];
+    message.iToI = message2.iToI;
+    message.strToStr = message2.strToStr;
+    // Pointer conparision
+    XCTAssertEqual(message.iToI->_autocreator, message2);
+    XCTAssertTrue([message.strToStr
+        isKindOfClass:[GPBAutocreatedDictionary class]]);
+    XCTAssertEqual(
+        ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator,
+        message2);
+  }
+
+  XCTAssertNil(message.iToI->_autocreator);
+  XCTAssertTrue(
+      [message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+  XCTAssertNil(
+      ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator);
+}
+
+- (void)testSetNilAutocreatedMap {
+  // Setting map to nil should cause it to lose its delegate.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  GPBInt32Int32Dictionary *iToI = [message.iToI retain];
+  GPBAutocreatedDictionary *strToStr =
+      (GPBAutocreatedDictionary *)[message.strToStr retain];
+  XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+  XCTAssertEqual(iToI->_autocreator, message);
+  XCTAssertEqual(strToStr->_autocreator, message);
+  message.iToI = nil;
+  message.strToStr = nil;
+  XCTAssertNil(iToI->_autocreator);
+  XCTAssertNil(strToStr->_autocreator);
+  [iToI release];
+  [strToStr release];
+}
+
+- (void)testReplaceAutocreatedMap {
+  // Replacing map should orphan the old one and cause its creator to become
+  // visible.
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.iToI);
+    XCTAssertFalse([message hasA]);
+    GPBInt32Int32Dictionary *iToI = [message.a.iToI retain];
+    XCTAssertEqual(iToI->_autocreator, message.a);  // Pointer comparision
+    message.a.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:6 forKey:7];
+    XCTAssertTrue([message hasA]);
+    XCTAssertNotEqual(message.a.iToI, iToI);  // Pointer comparision
+    XCTAssertNil(iToI->_autocreator);
+    [iToI release];
+  }
+
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.strToStr);
+    XCTAssertFalse([message hasA]);
+    GPBAutocreatedDictionary *strToStr =
+        (GPBAutocreatedDictionary *)[message.a.strToStr retain];
+    XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+    XCTAssertEqual(strToStr->_autocreator, message.a);  // Pointer comparision
+    message.a.strToStr =
+        [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"];
+    XCTAssertTrue([message hasA]);
+    XCTAssertNotEqual(message.a.strToStr, strToStr);  // Pointer comparision
+    XCTAssertNil(strToStr->_autocreator);
+    [strToStr release];
+  }
+}
+
+- (void)testSetAutocreatedMapToSelf {
+  // Setting map to itself should cause it to become visible.
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.iToI);
+    XCTAssertFalse([message hasA]);
+    message.a.iToI = message.a.iToI;
+    XCTAssertTrue([message hasA]);
+    XCTAssertNil(message.a.iToI->_autocreator);
+  }
+
+  {
+    TestRecursiveMessageWithRepeatedField *message =
+        [TestRecursiveMessageWithRepeatedField message];
+    XCTAssertNotNil(message.a);
+    XCTAssertNotNil(message.a.strToStr);
+    XCTAssertFalse([message hasA]);
+    message.a.strToStr = message.a.strToStr;
+    XCTAssertTrue([message hasA]);
+    XCTAssertTrue([message.a.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+    XCTAssertNil(((GPBAutocreatedDictionary *)message.a.strToStr)->_autocreator);
+  }
+}
+
+- (void)testAutocreatedMapRemoveAllValues {
+  // Calling removeAll on autocreated map should not cause it to be visible.
+  TestRecursiveMessageWithRepeatedField *message =
+      [TestRecursiveMessageWithRepeatedField message];
+  [message.a.iToI removeAll];
+  XCTAssertFalse([message hasA]);
+  [message.a.strToStr removeAllObjects];
+  XCTAssertFalse([message hasA]);
+}
+
+- (void)testExtensionAccessors {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+  [self assertAllExtensionsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionRepeatedSetters {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+  [self modifyRepeatedExtensions:message];
+  [self assertRepeatedExtensionsModified:message
+                           repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionDefaults {
+  [self assertExtensionsClear:[TestAllExtensions message]];
+}
+
+- (void)testExtensionIsEquals {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+  [self modifyRepeatedExtensions:message];
+  TestAllExtensions *message2 = [TestAllExtensions message];
+  [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+  XCTAssertFalse([message isEqual:message2]);
+  message2 = [TestAllExtensions message];
+  [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+  [self modifyRepeatedExtensions:message2];
+  XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testExtensionsMergeFrom {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+  [self modifyRepeatedExtensions:message];
+
+  message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+  TestAllExtensions *message2 = [TestAllExtensions message];
+  [self modifyRepeatedExtensions:message2];
+  [message2 mergeFrom:message];
+
+  XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDefaultingExtensionMessages {
+  TestAllExtensions *message = [TestAllExtensions message];
+
+  // Initially they should all not have values.
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+  XCTAssertFalse([message
+      hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+  // They should auto create something when fetched.
+
+  TestAllTypes_OptionalGroup *optionalGroup =
+      [message getExtension:[UnittestRoot optionalGroupExtension]];
+  TestAllTypes_NestedMessage *optionalNestedMessage =
+      [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
+  ForeignMessage *optionalForeignMessage =
+      [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+  ImportMessage *optionalImportMessage =
+      [message getExtension:[UnittestRoot optionalImportMessageExtension]];
+  PublicImportMessage *optionalPublicImportMessage = [message
+      getExtension:[UnittestRoot optionalPublicImportMessageExtension]];
+  TestAllTypes_NestedMessage *optionalLazyMessage =
+      [message getExtension:[UnittestRoot optionalLazyMessageExtension]];
+
+  XCTAssertNotNil(optionalGroup);
+  XCTAssertNotNil(optionalNestedMessage);
+  XCTAssertNotNil(optionalForeignMessage);
+  XCTAssertNotNil(optionalImportMessage);
+  XCTAssertNotNil(optionalPublicImportMessage);
+  XCTAssertNotNil(optionalLazyMessage);
+
+  // Although it auto-created empty messages, it should not show that it has
+  // them.
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+  // And they set that value back in to the message since the value created was
+  // mutable (so a second fetch should give the same object).
+
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+                 optionalGroup);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+      optionalNestedMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+      optionalForeignMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+      optionalImportMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+      optionalPublicImportMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+      optionalLazyMessage);
+
+  // And the default objects for a second message should be distinct (again,
+  // since they are mutable, each needs their own copy).
+
+  TestAllExtensions *message2 = [TestAllExtensions message];
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalGroupExtension]],
+      optionalGroup);
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalNestedMessageExtension]],
+      optionalNestedMessage);
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalForeignMessageExtension]],
+      optionalForeignMessage);
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalImportMessageExtension]],
+      optionalImportMessage);
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+      optionalPublicImportMessage);
+  XCTAssertNotEqual(
+      [message2 getExtension:[UnittestRoot optionalLazyMessageExtension]],
+      optionalLazyMessage);
+
+  // Clear values, and on next access you get back new submessages.
+
+  [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+  [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+                  value:nil];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+                  value:nil];
+  [message setExtension:[UnittestRoot optionalImportMessageExtension]
+                  value:nil];
+  [message setExtension:[UnittestRoot optionalPublicImportMessageExtension]
+                  value:nil];
+  [message setExtension:[UnittestRoot optionalLazyMessageExtension] value:nil];
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+  XCTAssertFalse([message
+      hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+  XCTAssertFalse(
+      [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+                 optionalGroup);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+      optionalNestedMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+      optionalForeignMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+      optionalImportMessage);
+  XCTAssertEqual(
+      [message
+          getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+      optionalPublicImportMessage);
+  XCTAssertEqual(
+      [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+      optionalLazyMessage);
+}
+
+- (void)testMultiplePointersToAutocreatedExtension {
+  // 2 objects point to the same auto-created extension. One should "has" it.
+  // The other should not.
+  TestAllExtensions *message = [TestAllExtensions message];
+  TestAllExtensions *message2 = [TestAllExtensions message];
+  GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension];
+  [message setExtension:extension value:[message2 getExtension:extension]];
+  XCTAssertEqual([message getExtension:extension],
+                 [message2 getExtension:extension]);
+  XCTAssertFalse([message2 hasExtension:extension]);
+  XCTAssertTrue([message hasExtension:extension]);
+
+  TestAllTypes_OptionalGroup *extensionValue =
+      [message2 getExtension:extension];
+  extensionValue.a = 1;
+  XCTAssertTrue([message2 hasExtension:extension]);
+  XCTAssertTrue([message hasExtension:extension]);
+}
+
+- (void)testCopyWithAutocreatedExtension {
+  // Mutable copy shouldn't copy autocreated extensions.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *optionalGroupExtension =
+      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalNestedMessageExtesion =
+      [UnittestRoot optionalNestedMessageExtension];
+  TestAllTypes_OptionalGroup *optionalGroup =
+      [message getExtension:optionalGroupExtension];
+  optionalGroup.a = 42;
+  XCTAssertNotNil(optionalGroup);
+  XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]);
+  XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+  XCTAssertFalse([message hasExtension:optionalNestedMessageExtesion]);
+
+  TestAllExtensions *message2 = [[message copy] autorelease];
+
+  // message2 should end up with its own copy of the optional group.
+  XCTAssertTrue([message2 hasExtension:optionalGroupExtension]);
+  XCTAssertEqualObjects([message getExtension:optionalGroupExtension],
+                        [message2 getExtension:optionalGroupExtension]);
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual([message getExtension:optionalGroupExtension],
+                    [message2 getExtension:optionalGroupExtension]);
+
+  XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtesion]);
+  // Intentionally doing a pointer comparison (auto creation should be
+  // different)
+  XCTAssertNotEqual([message getExtension:optionalNestedMessageExtesion],
+                    [message2 getExtension:optionalNestedMessageExtesion]);
+}
+
+- (void)testClearMessageAutocreatedExtension {
+  // Call clear should cause it to recreate its autocreated extensions.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *optionalGroupExtension =
+      [UnittestRoot optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroup =
+      [[message getExtension:optionalGroupExtension] retain];
+  [message clear];
+  TestAllTypes_OptionalGroup *optionalGroupNew =
+      [message getExtension:optionalGroupExtension];
+
+  // Intentionally doing a pointer comparison.
+  XCTAssertNotEqual(optionalGroup, optionalGroupNew);
+  [optionalGroup release];
+}
+
+- (void)testRetainAutocreatedExtension {
+  // Should be able to retain autocreated extension while the creator is
+  // dealloced.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *optionalGroupExtension =
+      [UnittestRoot optionalGroupExtension];
+
+  @autoreleasepool {
+    TestAllExtensions *message2 = [TestAllExtensions message];
+    [message setExtension:optionalGroupExtension
+                    value:[message2 getExtension:optionalGroupExtension]];
+    XCTAssertTrue(GPBWasMessageAutocreatedBy(
+        [message getExtension:optionalGroupExtension], message2));
+  }
+
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(
+      [message getExtension:optionalGroupExtension], message));
+}
+
+- (void)testClearAutocreatedExtension {
+  // Clearing autocreated extension should NOT cause it to lose its creator.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *optionalGroupExtension =
+      [UnittestRoot optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroup =
+      [[message getExtension:optionalGroupExtension] retain];
+  [message clearExtension:optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroupNew =
+      [message getExtension:optionalGroupExtension];
+  XCTAssertEqual(optionalGroup, optionalGroupNew);
+  XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+  [optionalGroup release];
+
+  // Clearing autocreated extension should not cause its creator to become
+  // visible
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
+  TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl3 =
+      [message_lvl2 getExtension:recursiveExtension];
+  [message_lvl3 clearExtension:recursiveExtension];
+  XCTAssertFalse([message hasExtension:recursiveExtension]);
+}
+
+- (void)testSetAutocreatedExtensionBecomesVisible {
+  // Setting an extension should cause the extension to appear to its creator.
+  // Test this several levels deep.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
+  TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl3 =
+      [message_lvl2 getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl4 =
+      [message_lvl3 getExtension:recursiveExtension];
+  XCTAssertFalse([message hasExtension:recursiveExtension]);
+  XCTAssertFalse([message_lvl2 hasExtension:recursiveExtension]);
+  XCTAssertFalse([message_lvl3 hasExtension:recursiveExtension]);
+  XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+  [message_lvl4 setExtension:[UnittestRoot optionalInt32Extension] value:@(1)];
+  XCTAssertTrue([message hasExtension:recursiveExtension]);
+  XCTAssertTrue([message_lvl2 hasExtension:recursiveExtension]);
+  XCTAssertTrue([message_lvl3 hasExtension:recursiveExtension]);
+  XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl4, message_lvl3));
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl3, message_lvl2));
+  XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl2, message));
+}
+
+- (void)testSetAutocreatedExtensionToSelf {
+  // Setting extension to itself should cause it to become visible.
+  TestAllExtensions *message = [TestAllExtensions message];
+  GPBExtensionDescriptor *optionalGroupExtension =
+      [UnittestRoot optionalGroupExtension];
+  XCTAssertNotNil([message getExtension:optionalGroupExtension]);
+  XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+  [message setExtension:optionalGroupExtension
+                  value:[message getExtension:optionalGroupExtension]];
+  XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+}
+
+- (void)testAutocreatedExtensionMemoryLeaks {
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
+
+  // Test for memory leaks with autocreated extensions.
+  TestAllExtensions *message;
+  TestAllExtensions *message_lvl2;
+  TestAllExtensions *message_lvl3;
+  TestAllExtensions *message_lvl4;
+  @autoreleasepool {
+    message = [[TestAllExtensions alloc] init];
+    message_lvl2 = [[message getExtension:recursiveExtension] retain];
+    message_lvl3 = [[message_lvl2 getExtension:recursiveExtension] retain];
+    message_lvl4 = [[message_lvl3 getExtension:recursiveExtension] retain];
+    [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension]
+                         value:@(1)];
+  }
+
+  XCTAssertEqual(message.retainCount, (NSUInteger)1);
+  @autoreleasepool {
+    [message release];
+  }
+  XCTAssertEqual(message_lvl2.retainCount, (NSUInteger)1);
+  @autoreleasepool {
+    [message_lvl2 release];
+  }
+  XCTAssertEqual(message_lvl3.retainCount, (NSUInteger)1);
+  @autoreleasepool {
+    [message_lvl3 release];
+  }
+  XCTAssertEqual(message_lvl4.retainCount, (NSUInteger)1);
+  [message_lvl4 release];
+}
+
+- (void)testSetExtensionWithAutocreatedValue {
+  GPBExtensionDescriptor *recursiveExtension =
+      [UnittestObjcRoot recursiveExtension];
+
+  TestAllExtensions *message;
+  @autoreleasepool {
+    message = [[TestAllExtensions alloc] init];
+    [message getExtension:recursiveExtension];
+  }
+
+  // This statements checks that the extension value isn't accidentally
+  // dealloced when removing it from the autocreated map.
+  [message setExtension:recursiveExtension
+                  value:[message getExtension:recursiveExtension]];
+  XCTAssertTrue([message hasExtension:recursiveExtension]);
+  [message release];
+}
+
+- (void)testRecursion {
+  TestRecursiveMessage *message = [TestRecursiveMessage message];
+  XCTAssertNotNil(message.a);
+  XCTAssertNotNil(message.a.a);
+  XCTAssertEqual(message.a.a.i, 0);
+}
+
+- (void)testGenerateAndParseUnknownMessage {
+  GPBUnknownFieldSet *unknowns =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  [unknowns mergeVarintField:123 value:456];
+  GPBMessage *message = [GPBMessage message];
+  [message setUnknownFields:unknowns];
+  NSData *data = [message data];
+  GPBMessage *message2 =
+      [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
+  XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDelimitedWriteAndParseMultipleMessages {
+  GPBUnknownFieldSet *unknowns1 =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  [unknowns1 mergeVarintField:123 value:456];
+  GPBMessage *message1 = [GPBMessage message];
+  [message1 setUnknownFields:unknowns1];
+
+  GPBUnknownFieldSet *unknowns2 =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  [unknowns2 mergeVarintField:789 value:987];
+  [unknowns2 mergeVarintField:654 value:321];
+  GPBMessage *message2 = [GPBMessage message];
+  [message2 setUnknownFields:unknowns2];
+
+  NSMutableData *delimitedData = [NSMutableData data];
+  [delimitedData appendData:[message1 delimitedData]];
+  [delimitedData appendData:[message2 delimitedData]];
+  GPBCodedInputStream *input =
+      [GPBCodedInputStream streamWithData:delimitedData];
+  GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input
+                                                      extensionRegistry:nil
+                                                                  error:NULL];
+  GPBMessage *message4 = [GPBMessage parseDelimitedFromCodedInputStream:input
+                                                      extensionRegistry:nil
+                                                                  error:NULL];
+  XCTAssertEqualObjects(message1, message3);
+  XCTAssertEqualObjects(message2, message4);
+}
+
+- (void)testDuplicateEnums {
+  XCTAssertEqual(TestEnumWithDupValue_Foo1, TestEnumWithDupValue_Foo2);
+}
+
+- (void)testWeirdDefaults {
+  ObjcWeirdDefaults *message = [ObjcWeirdDefaults message];
+  GPBDescriptor *descriptor = [[message class] descriptor];
+  GPBFieldDescriptor *fieldDesc = [descriptor fieldWithName:@"foo"];
+  XCTAssertNotNil(fieldDesc);
+  XCTAssertTrue(fieldDesc.hasDefaultValue);
+  XCTAssertFalse(message.hasFoo);
+  XCTAssertEqualObjects(message.foo, @"");
+
+  fieldDesc = [descriptor fieldWithName:@"bar"];
+  XCTAssertNotNil(fieldDesc);
+  XCTAssertTrue(fieldDesc.hasDefaultValue);
+  XCTAssertFalse(message.hasBar);
+  XCTAssertEqualObjects(message.bar, GPBEmptyNSData());
+}
+
+- (void)testEnumDescriptorFromExtensionDescriptor {
+  GPBExtensionDescriptor *extDescriptor =
+      [UnittestRoot optionalForeignEnumExtension];
+  XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum);
+  GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor;
+  GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor();
+  XCTAssertEqualObjects(enumDescriptor, expectedDescriptor);
+}
+
+- (void)testPropertyNaming {
+  // objectivec_helpers.cc has some special handing to get proper all caps
+  // for a few cases to meet objc developer expectations.
+  //
+  // This "test" confirms that the expected names are generated, otherwise the
+  // test itself will fail to compile.
+  ObjCPropertyNaming *msg = [ObjCPropertyNaming message];
+  // On their own, at the end, in the middle.
+  msg.URL = @"good";
+  msg.thumbnailURL = @"good";
+  msg.URLFoo = @"good";
+  msg.someURLBlah = @"good";
+  msg.HTTP = @"good";
+  msg.HTTPS = @"good";
+  // No caps since it was "urls".
+  [msg.urlsArray addObject:@"good"];
+}
+
+- (void)testEnumNaming {
+  // objectivec_helpers.cc has some interesting cases to deal with in
+  // EnumValueName/EnumValueShortName.  Confirm that things generated as
+  // expected.
+
+  // This block just has to compile to confirm we got the expected types/names.
+  // The *_IsValidValue() calls are just there to keep the projects warnings
+  // flags happy by providing use of the variables/values.
+
+  Foo aFoo = Foo_SerializedSize;
+  Foo_IsValidValue(aFoo);
+  aFoo = Foo_Size;
+  Foo_IsValidValue(aFoo);
+
+  Category_Enum aCat = Category_Enum_Red;
+  Category_Enum_IsValidValue(aCat);
+
+  Time aTime = Time_Base;
+  Time_IsValidValue(aTime);
+  aTime = Time_SomethingElse;
+  Time_IsValidValue(aTime);
+
+  // This block confirms the names in the decriptors is what we wanted.
+
+  GPBEnumDescriptor *descriptor;
+  NSString *valueName;
+
+  descriptor = Foo_EnumDescriptor();
+  XCTAssertNotNil(descriptor);
+  XCTAssertEqualObjects(@"Foo", descriptor.name);
+  valueName = [descriptor enumNameForValue:Foo_SerializedSize];
+  XCTAssertEqualObjects(@"Foo_SerializedSize", valueName);
+  valueName = [descriptor enumNameForValue:Foo_Size];
+  XCTAssertEqualObjects(@"Foo_Size", valueName);
+
+  descriptor = Category_Enum_EnumDescriptor();
+  XCTAssertNotNil(descriptor);
+  XCTAssertEqualObjects(@"Category_Enum", descriptor.name);
+  valueName = [descriptor enumNameForValue:Category_Enum_Red];
+  XCTAssertEqualObjects(@"Category_Enum_Red", valueName);
+
+  descriptor = Time_EnumDescriptor();
+  XCTAssertNotNil(descriptor);
+  XCTAssertEqualObjects(@"Time", descriptor.name);
+  valueName = [descriptor enumNameForValue:Time_Base];
+  XCTAssertEqualObjects(@"Time_Base", valueName);
+  valueName = [descriptor enumNameForValue:Time_SomethingElse];
+  XCTAssertEqualObjects(@"Time_SomethingElse", valueName);
+}
+
+- (void)testNegativeEnums {
+  EnumTestMsg *msg = [EnumTestMsg message];
+
+  // Defaults
+  XCTAssertEqual(msg.foo, EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One);
+  XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne);
+  // Bounce to wire and back.
+  NSData *data = [msg data];
+  XCTAssertNotNil(data);
+  EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:data error:NULL];
+  XCTAssertEqualObjects(msgPrime, msg);
+  XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One);
+  XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegOne);
+
+  // Other values
+  msg.bar = EnumTestMsg_MyEnum_Two;
+  msg.baz = EnumTestMsg_MyEnum_NegTwo;
+  XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two);
+  XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo);
+  // Bounce to wire and back.
+  data = [msg data];
+  XCTAssertNotNil(data);
+  msgPrime = [EnumTestMsg parseFromData:data error:NULL];
+  XCTAssertEqualObjects(msgPrime, msg);
+  XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two);
+  XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegTwo);
+
+  // Repeated field (shouldn't ever be an issue since developer has to use the
+  // right GPBArray methods themselves).
+  msg.mumbleArray = [GPBEnumArray
+      arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue];
+  [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Zero];
+  [msg.mumbleArray addValue:EnumTestMsg_MyEnum_One];
+  [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
+  [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegOne];
+  [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo];
+  XCTAssertEqual([msg.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual([msg.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+  XCTAssertEqual([msg.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+  XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne);
+  XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
+  // Bounce to wire and back.
+  data = [msg data];
+  XCTAssertNotNil(data);
+  msgPrime = [EnumTestMsg parseFromData:data error:NULL];
+  XCTAssertEqualObjects(msgPrime, msg);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0],
+                 EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3],
+                 EnumTestMsg_MyEnum_NegOne);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4],
+                 EnumTestMsg_MyEnum_NegTwo);
+}
+
+- (void)testOneBasedEnumHolder {
+  // Test case for https://github.com/google/protobuf/issues/1453
+  // Message with no explicit defaults, but a non zero default for an enum.
+  MessageWithOneBasedEnum *enumMsg = [MessageWithOneBasedEnum message];
+  XCTAssertEqual(enumMsg.enumField, MessageWithOneBasedEnum_OneBasedEnum_One);
+}
+
+- (void)testBoolOffsetUsage {
+  // Bools use storage within has_bits; this test ensures that this is honored
+  // in all places where things should crash or fail based on reading out of
+  // field storage instead.
+  BoolOnlyMessage *msg1 = [BoolOnlyMessage message];
+  BoolOnlyMessage *msg2 = [BoolOnlyMessage message];
+
+  msg1.boolField1 = YES;
+  msg2.boolField1 = YES;
+  msg1.boolField3 = YES;
+  msg2.boolField3 = YES;
+  msg1.boolField5 = YES;
+  msg2.boolField5 = YES;
+  msg1.boolField7 = YES;
+  msg2.boolField7 = YES;
+  msg1.boolField9 = YES;
+  msg2.boolField9 = YES;
+  msg1.boolField11 = YES;
+  msg2.boolField11 = YES;
+  msg1.boolField13 = YES;
+  msg2.boolField13 = YES;
+  msg1.boolField15 = YES;
+  msg2.boolField15 = YES;
+  msg1.boolField17 = YES;
+  msg2.boolField17 = YES;
+  msg1.boolField19 = YES;
+  msg2.boolField19 = YES;
+  msg1.boolField21 = YES;
+  msg2.boolField21 = YES;
+  msg1.boolField23 = YES;
+  msg2.boolField23 = YES;
+  msg1.boolField25 = YES;
+  msg2.boolField25 = YES;
+  msg1.boolField27 = YES;
+  msg2.boolField27 = YES;
+  msg1.boolField29 = YES;
+  msg2.boolField29 = YES;
+  msg1.boolField31 = YES;
+  msg2.boolField31 = YES;
+
+  msg1.boolField32 = YES;
+  msg2.boolField32 = YES;
+
+  XCTAssertTrue(msg1 != msg2); // Different pointers.
+  XCTAssertEqual([msg1 hash], [msg2 hash]);
+  XCTAssertEqualObjects(msg1, msg2);
+
+  BoolOnlyMessage *msg1Prime = [[msg1 copy] autorelease];
+  XCTAssertTrue(msg1Prime != msg1); // Different pointers.
+  XCTAssertEqual([msg1 hash], [msg1Prime hash]);
+  XCTAssertEqualObjects(msg1, msg1Prime);
+
+  // Field set in one, but not the other means they don't match (even if
+  // set to default value).
+  msg1Prime.boolField2 = NO;
+  XCTAssertNotEqualObjects(msg1Prime, msg1);
+  // And when set to different values.
+  msg1.boolField2 = YES;
+  XCTAssertNotEqualObjects(msg1Prime, msg1);
+  // And then they match again.
+  msg1.boolField2 = NO;
+  XCTAssertEqualObjects(msg1Prime, msg1);
+  XCTAssertEqual([msg1 hash], [msg1Prime hash]);
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm b/src/third_party/protobuf-3/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
new file mode 100644
index 0000000..9ba8fd0
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
@@ -0,0 +1,69 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+
+#import "GPBTestUtilities.h"
+
+
+//
+// This is just a compile test (here to make sure things never regress).
+//
+// Objective C++ can run into issues with how the NS_ENUM/CF_ENUM declartion
+// works because of the C++ spec being used for that compilation unit. So
+// the fact that these imports all work without errors/warning means things
+// are still good.
+//
+// The "well know types" should have cross file enums needing imports.
+#import "GPBProtocolBuffers.h"
+// Some of the tests explicitly use cross file enums also.
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+
+// Sanity check the conditions of the test within the Xcode project.
+#if !__cplusplus
+  #error This isn't compiled as Objective C++?
+#elif __cplusplus >= 201103L
+  // If this trips, it means the Xcode default might have change (or someone
+  // edited the testing project) and it might be time to revisit the GPB_ENUM
+  // define in GPBBootstrap.h.
+  #warning Did the Xcode default for C++ spec change?
+#endif
+
+
+// Dummy XCTest.
+@interface GPBObjectiveCPlusPlusTests : GPBTestCase
+@end
+
+@implementation GPBObjectiveCPlusPlusTests
+- (void)testCPlusPlus {
+  // Nothing, This was a compile test.
+  XCTAssertTrue(YES);
+}
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBPerfTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBPerfTests.m
new file mode 100644
index 0000000..1259d14
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBPerfTests.m
@@ -0,0 +1,307 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+#import "GPBTestUtilities.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+//
+// This file really just uses the unittests framework as a testbed to
+// run some simple performance tests. The data can then be used to help
+// evaluate changes to the runtime.
+//
+
+static const uint32_t kRepeatedCount = 100;
+
+@interface PerfTests : GPBTestCase
+@end
+
+@implementation PerfTests
+
+- (void)setUp {
+  // A convenient place to put a break point if you want to connect instruments.
+  [super setUp];
+}
+
+- (void)testMessagePerformance {
+  [self measureBlock:^{
+    for (int i = 0; i < 200; ++i) {
+      TestAllTypes* message = [[TestAllTypes alloc] init];
+      [self setAllFields:message repeatedCount:kRepeatedCount];
+      NSData* rawBytes = [message data];
+      [message release];
+      message = [[TestAllTypes alloc] initWithData:rawBytes error:NULL];
+      [message release];
+    }
+  }];
+}
+
+- (void)testExtensionsPerformance {
+  [self measureBlock:^{
+    for (int i = 0; i < 200; ++i) {
+      TestAllExtensions* message = [[TestAllExtensions alloc] init];
+      [self setAllExtensions:message repeatedCount:kRepeatedCount];
+      NSData* rawBytes = [message data];
+      [message release];
+      TestAllExtensions* message2 =
+          [[TestAllExtensions alloc] initWithData:rawBytes error:NULL];
+      [message2 release];
+    }
+  }];
+}
+
+- (void)testPackedTypesPerformance {
+  [self measureBlock:^{
+    for (int i = 0; i < 1000; ++i) {
+      TestPackedTypes* message = [[TestPackedTypes alloc] init];
+      [self setPackedFields:message repeatedCount:kRepeatedCount];
+      NSData* rawBytes = [message data];
+      [message release];
+      message = [[TestPackedTypes alloc] initWithData:rawBytes error:NULL];
+      [message release];
+    }
+  }];
+}
+
+- (void)testPackedExtensionsPerformance {
+  [self measureBlock:^{
+    for (int i = 0; i < 1000; ++i) {
+      TestPackedExtensions* message = [[TestPackedExtensions alloc] init];
+      [self setPackedExtensions:message repeatedCount:kRepeatedCount];
+      NSData* rawBytes = [message data];
+      [message release];
+      TestPackedExtensions* message2 =
+          [[TestPackedExtensions alloc] initWithData:rawBytes error:NULL];
+      [message2 release];
+    }
+  }];
+}
+
+- (void)testHas {
+  TestAllTypes* message = [self allSetRepeatedCount:1];
+  [self measureBlock:^{
+    for (int i = 0; i < 10000; ++i) {
+      [message hasOptionalInt32];
+      message.hasOptionalInt32 = NO;
+      [message hasOptionalInt32];
+
+      [message hasOptionalInt64];
+      message.hasOptionalInt64 = NO;
+      [message hasOptionalInt64];
+
+      [message hasOptionalUint32];
+      message.hasOptionalUint32 = NO;
+      [message hasOptionalUint32];
+
+      [message hasOptionalUint64];
+      message.hasOptionalUint64 = NO;
+      [message hasOptionalUint64];
+
+      [message hasOptionalSint32];
+      message.hasOptionalSint32 = NO;
+      [message hasOptionalSint32];
+
+      [message hasOptionalSint64];
+      message.hasOptionalSint64 = NO;
+      [message hasOptionalSint64];
+
+      [message hasOptionalFixed32];
+      message.hasOptionalFixed32 = NO;
+      [message hasOptionalFixed32];
+
+      [message hasOptionalFixed64];
+      message.hasOptionalFixed64 = NO;
+      [message hasOptionalFixed64];
+
+      [message hasOptionalSfixed32];
+      message.hasOptionalSfixed32 = NO;
+      [message hasOptionalSfixed32];
+
+      [message hasOptionalSfixed64];
+      message.hasOptionalSfixed64 = NO;
+      [message hasOptionalSfixed64];
+
+      [message hasOptionalFloat];
+      message.hasOptionalFloat = NO;
+      [message hasOptionalFloat];
+
+      [message hasOptionalDouble];
+      message.hasOptionalDouble = NO;
+      [message hasOptionalDouble];
+
+      [message hasOptionalBool];
+      message.hasOptionalBool = NO;
+      [message hasOptionalBool];
+
+      [message hasOptionalString];
+      message.hasOptionalString = NO;
+      [message hasOptionalString];
+
+      [message hasOptionalBytes];
+      message.hasOptionalBytes = NO;
+      [message hasOptionalBytes];
+
+      [message hasOptionalGroup];
+      message.hasOptionalGroup = NO;
+      [message hasOptionalGroup];
+
+      [message hasOptionalNestedMessage];
+      message.hasOptionalNestedMessage = NO;
+      [message hasOptionalNestedMessage];
+
+      [message hasOptionalForeignMessage];
+      message.hasOptionalForeignMessage = NO;
+      [message hasOptionalForeignMessage];
+
+      [message hasOptionalImportMessage];
+      message.hasOptionalImportMessage = NO;
+      [message hasOptionalImportMessage];
+
+      [message.optionalGroup hasA];
+      message.optionalGroup.hasA = NO;
+      [message.optionalGroup hasA];
+
+      [message.optionalNestedMessage hasBb];
+      message.optionalNestedMessage.hasBb = NO;
+      [message.optionalNestedMessage hasBb];
+
+      [message.optionalForeignMessage hasC];
+      message.optionalForeignMessage.hasC = NO;
+      [message.optionalForeignMessage hasC];
+
+      [message.optionalImportMessage hasD];
+      message.optionalImportMessage.hasD = NO;
+      [message.optionalImportMessage hasD];
+
+      [message hasOptionalNestedEnum];
+      message.hasOptionalNestedEnum = NO;
+      [message hasOptionalNestedEnum];
+
+      [message hasOptionalForeignEnum];
+      message.hasOptionalForeignEnum = NO;
+      [message hasOptionalForeignEnum];
+
+      [message hasOptionalImportEnum];
+      message.hasOptionalImportEnum = NO;
+      [message hasOptionalImportEnum];
+
+      [message hasOptionalStringPiece];
+      message.hasOptionalStringPiece = NO;
+      [message hasOptionalStringPiece];
+
+      [message hasOptionalCord];
+      message.hasOptionalCord = NO;
+      [message hasOptionalCord];
+
+      [message hasDefaultInt32];
+      message.hasDefaultInt32 = NO;
+      [message hasDefaultInt32];
+
+      [message hasDefaultInt64];
+      message.hasDefaultInt64 = NO;
+      [message hasDefaultInt64];
+
+      [message hasDefaultUint32];
+      message.hasDefaultUint32 = NO;
+      [message hasDefaultUint32];
+
+      [message hasDefaultUint64];
+      message.hasDefaultUint64 = NO;
+      [message hasDefaultUint64];
+
+      [message hasDefaultSint32];
+      message.hasDefaultSint32 = NO;
+      [message hasDefaultSint32];
+
+      [message hasDefaultSint64];
+      message.hasDefaultSint64 = NO;
+      [message hasDefaultSint64];
+
+      [message hasDefaultFixed32];
+      message.hasDefaultFixed32 = NO;
+      [message hasDefaultFixed32];
+
+      [message hasDefaultFixed64];
+      message.hasDefaultFixed64 = NO;
+      [message hasDefaultFixed64];
+
+      [message hasDefaultSfixed32];
+      message.hasDefaultSfixed32 = NO;
+      [message hasDefaultSfixed32];
+
+      [message hasDefaultSfixed64];
+      message.hasDefaultSfixed64 = NO;
+      [message hasDefaultSfixed64];
+
+      [message hasDefaultFloat];
+      message.hasDefaultFloat = NO;
+      [message hasDefaultFloat];
+
+      [message hasDefaultDouble];
+      message.hasDefaultDouble = NO;
+      [message hasDefaultDouble];
+
+      [message hasDefaultBool];
+      message.hasDefaultBool = NO;
+      [message hasDefaultBool];
+
+      [message hasDefaultString];
+      message.hasDefaultString = NO;
+      [message hasDefaultString];
+
+      [message hasDefaultBytes];
+      message.hasDefaultBytes = NO;
+      [message hasDefaultBytes];
+
+      [message hasDefaultNestedEnum];
+      message.hasDefaultNestedEnum = NO;
+      [message hasDefaultNestedEnum];
+
+      [message hasDefaultForeignEnum];
+      message.hasDefaultForeignEnum = NO;
+      [message hasDefaultForeignEnum];
+
+      [message hasDefaultImportEnum];
+      message.hasDefaultImportEnum = NO;
+      [message hasDefaultImportEnum];
+
+      [message hasDefaultStringPiece];
+      message.hasDefaultStringPiece = NO;
+      [message hasDefaultStringPiece];
+
+      [message hasDefaultCord];
+      message.hasDefaultCord = NO;
+      [message hasDefaultCord];
+    }
+  }];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBSwiftTests.swift b/src/third_party/protobuf-3/objectivec/Tests/GPBSwiftTests.swift
new file mode 100644
index 0000000..36ed2a6
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBSwiftTests.swift
@@ -0,0 +1,460 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+import Foundation
+import XCTest
+
+// Test some usage of the ObjC library from Swift.
+
+class GPBBridgeTests: XCTestCase {
+
+  func testProto2Basics() {
+    let msg = Message2()
+    let msg2 = Message2()
+    let msg3 = Message2_OptionalGroup()
+
+    msg.optionalInt32 = 100
+    msg.optionalString = "abc"
+    msg.optionalEnum = .Bar
+    msg2.optionalString = "other"
+    msg.optionalMessage = msg2
+    msg3.a = 200
+    msg.optionalGroup = msg3
+    msg.repeatedInt32Array.addValue(300)
+    msg.repeatedInt32Array.addValue(301)
+    msg.repeatedStringArray.addObject("mno")
+    msg.repeatedStringArray.addObject("pqr")
+    msg.repeatedEnumArray.addValue(Message2_Enum.Bar.rawValue)
+    msg.repeatedEnumArray.addValue(Message2_Enum.Baz.rawValue)
+    msg.mapInt32Int32.setValue(400, forKey:500)
+    msg.mapInt32Int32.setValue(401, forKey:501)
+    msg.mapStringString.setObject("foo", forKey:"bar")
+    msg.mapStringString.setObject("abc", forKey:"xyz")
+    msg.mapInt32Enum.setValue(Message2_Enum.Bar.rawValue, forKey:600)
+    msg.mapInt32Enum.setValue(Message2_Enum.Baz.rawValue, forKey:601)
+
+    // Check has*.
+    XCTAssertTrue(msg.hasOptionalInt32)
+    XCTAssertTrue(msg.hasOptionalString)
+    XCTAssertTrue(msg.hasOptionalEnum)
+    XCTAssertTrue(msg2.hasOptionalString)
+    XCTAssertTrue(msg.hasOptionalMessage)
+    XCTAssertTrue(msg3.hasA)
+    XCTAssertTrue(msg.hasOptionalGroup)
+    XCTAssertFalse(msg.hasOptionalInt64)
+    XCTAssertFalse(msg.hasOptionalFloat)
+
+    // Check values.
+    XCTAssertEqual(msg.optionalInt32, Int32(100))
+    XCTAssertEqual(msg.optionalString, "abc")
+    XCTAssertEqual(msg2.optionalString, "other")
+    XCTAssertTrue(msg.optionalMessage === msg2)
+    XCTAssertEqual(msg.optionalEnum, Message2_Enum.Bar)
+    XCTAssertEqual(msg3.a, Int32(200))
+    XCTAssertTrue(msg.optionalGroup === msg3)
+    XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+    XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+    XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+    XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+    XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno")
+    XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr")
+    XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+    XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue)
+    XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue)
+    XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+    XCTAssertEqual(msg.mapInt32Int32.count, UInt(2))
+    var intValue: Int32 = 0;
+    XCTAssertTrue(msg.mapInt32Int32.valueForKey(500, value:&intValue))
+    XCTAssertEqual(intValue, Int32(400))
+    XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue))
+    XCTAssertEqual(intValue, Int32(401))
+    XCTAssertEqual(msg.mapStringString.count, Int(2))
+    XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo")
+    XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc")
+    XCTAssertEqual(msg.mapInt32Enum.count, UInt(2))
+    XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue))
+    XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue)
+    XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, value:&intValue))
+    XCTAssertEqual(intValue, Message2_Enum.Baz.rawValue)
+
+    // Clearing a string with nil.
+    msg2.optionalString = nil
+    XCTAssertFalse(msg2.hasOptionalString)
+    XCTAssertEqual(msg2.optionalString, "")
+
+    // Clearing a message with nil.
+    msg.optionalGroup = nil
+    XCTAssertFalse(msg.hasOptionalGroup)
+    XCTAssertTrue(msg.optionalGroup !== msg3)  // New instance
+
+    // Clear.
+    msg.clear()
+    XCTAssertFalse(msg.hasOptionalInt32)
+    XCTAssertFalse(msg.hasOptionalString)
+    XCTAssertFalse(msg.hasOptionalEnum)
+    XCTAssertFalse(msg.hasOptionalMessage)
+    XCTAssertFalse(msg.hasOptionalInt64)
+    XCTAssertFalse(msg.hasOptionalFloat)
+    XCTAssertEqual(msg.optionalInt32, Int32(0))
+    XCTAssertEqual(msg.optionalString, "")
+    XCTAssertTrue(msg.optionalMessage !== msg2)  // New instance
+    XCTAssertEqual(msg.optionalEnum, Message2_Enum.Foo)  // Default
+    XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+    XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+    XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+    XCTAssertEqual(msg.mapInt32Int32.count, UInt(0))
+    XCTAssertEqual(msg.mapStringString.count, Int(0))
+    XCTAssertEqual(msg.mapInt32Enum.count, UInt(0))
+  }
+
+  func testProto3Basics() {
+    let msg = Message3()
+    let msg2 = Message3()
+
+    msg.optionalInt32 = 100
+    msg.optionalString = "abc"
+    msg.optionalEnum = .Bar
+    msg2.optionalString = "other"
+    msg.optionalMessage = msg2
+    msg.repeatedInt32Array.addValue(300)
+    msg.repeatedInt32Array.addValue(301)
+    msg.repeatedStringArray.addObject("mno")
+    msg.repeatedStringArray.addObject("pqr")
+    // "proto3" syntax lets enum get unknown values.
+    msg.repeatedEnumArray.addValue(Message3_Enum.Bar.rawValue)
+    msg.repeatedEnumArray.addRawValue(666)
+    SetMessage3_OptionalEnum_RawValue(msg2, 666)
+    msg.mapInt32Int32.setValue(400, forKey:500)
+    msg.mapInt32Int32.setValue(401, forKey:501)
+    msg.mapStringString.setObject("foo", forKey:"bar")
+    msg.mapStringString.setObject("abc", forKey:"xyz")
+    msg.mapInt32Enum.setValue(Message2_Enum.Bar.rawValue, forKey:600)
+    // "proto3" syntax lets enum get unknown values.
+    msg.mapInt32Enum.setRawValue(666, forKey:601)
+
+    // Has only exists on for message fields.
+    XCTAssertTrue(msg.hasOptionalMessage)
+    XCTAssertFalse(msg2.hasOptionalMessage)
+
+    // Check values.
+    XCTAssertEqual(msg.optionalInt32, Int32(100))
+    XCTAssertEqual(msg.optionalString, "abc")
+    XCTAssertEqual(msg2.optionalString, "other")
+    XCTAssertTrue(msg.optionalMessage === msg2)
+    XCTAssertEqual(msg.optionalEnum, Message3_Enum.Bar)
+    XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+    XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+    XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+    XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+    XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno")
+    XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr")
+    XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+    XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+    XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message3_Enum.Bar.rawValue)
+    XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue)
+    XCTAssertEqual(msg.repeatedEnumArray.rawValueAtIndex(1), 666)
+    XCTAssertEqual(msg2.optionalEnum, Message3_Enum.GPBUnrecognizedEnumeratorValue)
+    XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666))
+    XCTAssertEqual(msg.mapInt32Int32.count, UInt(2))
+    var intValue: Int32 = 0;
+    XCTAssertTrue(msg.mapInt32Int32.valueForKey(500, value:&intValue))
+    XCTAssertEqual(intValue, Int32(400))
+    XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue))
+    XCTAssertEqual(intValue, Int32(401))
+    XCTAssertEqual(msg.mapStringString.count, Int(2))
+    XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo")
+    XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc")
+    XCTAssertEqual(msg.mapInt32Enum.count, UInt(2))
+    XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue))
+    XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue)
+    XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, value:&intValue))
+    XCTAssertEqual(intValue, Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue)
+    XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, rawValue:&intValue))
+    XCTAssertEqual(intValue, 666)
+
+    // Clearing a string with nil.
+    msg2.optionalString = nil
+    XCTAssertEqual(msg2.optionalString, "")
+
+    // Clearing a message with nil.
+    msg.optionalMessage = nil
+    XCTAssertFalse(msg.hasOptionalMessage)
+    XCTAssertTrue(msg.optionalMessage !== msg2)  // New instance
+
+    // Clear.
+    msg.clear()
+    XCTAssertFalse(msg.hasOptionalMessage)
+    XCTAssertEqual(msg.optionalInt32, Int32(0))
+    XCTAssertEqual(msg.optionalString, "")
+    XCTAssertTrue(msg.optionalMessage !== msg2)  // New instance
+    XCTAssertEqual(msg.optionalEnum, Message3_Enum.Foo)  // Default
+    XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+    XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+    XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+    msg2.clear()
+    XCTAssertEqual(msg2.optionalEnum, Message3_Enum.Foo)  // Default
+    XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.Foo.rawValue)
+    XCTAssertEqual(msg.mapInt32Int32.count, UInt(0))
+    XCTAssertEqual(msg.mapStringString.count, Int(0))
+    XCTAssertEqual(msg.mapInt32Enum.count, UInt(0))
+  }
+
+  func testAutoCreation() {
+    let msg = Message2()
+
+    XCTAssertFalse(msg.hasOptionalGroup)
+    XCTAssertFalse(msg.hasOptionalMessage)
+
+    // Access shouldn't result in has* but should return objects.
+    let msg2 = msg.optionalGroup
+    let msg3 = msg.optionalMessage.optionalMessage
+    let msg4 = msg.optionalMessage
+    XCTAssertNotNil(msg2)
+    XCTAssertNotNil(msg3)
+    XCTAssertFalse(msg.hasOptionalGroup)
+    XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+    XCTAssertFalse(msg.hasOptionalMessage)
+
+    // Setting things should trigger has* getting set.
+    msg.optionalGroup.a = 10
+    msg.optionalMessage.optionalMessage.optionalInt32 = 100
+    XCTAssertTrue(msg.hasOptionalGroup)
+    XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+    XCTAssertTrue(msg.hasOptionalMessage)
+
+    // And they should be the same pointer as before.
+    XCTAssertTrue(msg2 === msg.optionalGroup)
+    XCTAssertTrue(msg3 === msg.optionalMessage.optionalMessage)
+    XCTAssertTrue(msg4 === msg.optionalMessage)
+
+    // Clear gets us new objects next time around.
+    msg.clear()
+    XCTAssertFalse(msg.hasOptionalGroup)
+    XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+    XCTAssertFalse(msg.hasOptionalMessage)
+    msg.optionalGroup.a = 20
+    msg.optionalMessage.optionalMessage.optionalInt32 = 200
+    XCTAssertTrue(msg.hasOptionalGroup)
+    XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+    XCTAssertTrue(msg.hasOptionalMessage)
+    XCTAssertTrue(msg2 !== msg.optionalGroup)
+    XCTAssertTrue(msg3 !== msg.optionalMessage.optionalMessage)
+    XCTAssertTrue(msg4 !== msg.optionalMessage)
+
+    // Explicit set of a message, means autocreated object doesn't bind.
+    msg.clear()
+    let autoCreated = msg.optionalMessage
+    XCTAssertFalse(msg.hasOptionalMessage)
+    let msg5 = Message2()
+    msg5.optionalInt32 = 123
+    msg.optionalMessage = msg5
+    XCTAssertTrue(msg.hasOptionalMessage)
+    // Modifing the autocreated doesn't replaced the explicit set one.
+    autoCreated.optionalInt32 = 456
+    XCTAssertTrue(msg.hasOptionalMessage)
+    XCTAssertTrue(msg.optionalMessage === msg5)
+    XCTAssertEqual(msg.optionalMessage.optionalInt32, Int32(123))
+  }
+
+  func testProto2OneOfSupport() {
+    let msg = Message2()
+
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(110.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz)  // Default
+    let autoCreated = msg.oneofMessage  // Default create one.
+    XCTAssertNotNil(autoCreated)
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+    msg.oneofInt32 = 10
+    XCTAssertEqual(msg.oneofInt32, Int32(10))
+    XCTAssertEqual(msg.oneofFloat, Float(110.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+    msg.oneofFloat = 20.0
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(20.0))
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofFloat)
+
+    msg.oneofEnum = .Bar
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(110.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Bar)
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofEnum)
+
+    // Sets via the autocreated instance.
+    msg.oneofMessage.optionalInt32 = 200
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(110.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+    // Clear the oneof.
+    Message2_ClearOOneOfCase(msg)
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(110.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz)  // Default
+    let autoCreated2 = msg.oneofMessage  // Default create one
+    XCTAssertNotNil(autoCreated2)
+    XCTAssertTrue(autoCreated2 !== autoCreated)  // New instance
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+    msg.oneofInt32 = 10
+    XCTAssertEqual(msg.oneofInt32, Int32(10))
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+    // Confirm Message.clear() handles the oneof correctly.
+    msg.clear()
+    XCTAssertEqual(msg.oneofInt32, Int32(100))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+    // Sets via the autocreated instance.
+    msg.oneofMessage.optionalInt32 = 300
+    XCTAssertTrue(msg.oneofMessage !== autoCreated)  // New instance
+    XCTAssertTrue(msg.oneofMessage !== autoCreated2)  // New instance
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+    // Set message to nil clears the oneof.
+    msg.oneofMessage = nil
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+}
+
+  func testProto3OneOfSupport() {
+    let msg = Message3()
+
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(0.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo)  // Default
+    let autoCreated = msg.oneofMessage  // Default create one.
+    XCTAssertNotNil(autoCreated)
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+    msg.oneofInt32 = 10
+    XCTAssertEqual(msg.oneofInt32, Int32(10))
+    XCTAssertEqual(msg.oneofFloat, Float(0.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+    msg.oneofFloat = 20.0
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(20.0))
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofFloat)
+
+    msg.oneofEnum = .Bar
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(0.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Bar)
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofEnum)
+
+    // Sets via the autocreated instance.
+    msg.oneofMessage.optionalInt32 = 200
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(0.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo)  // Default
+    XCTAssertTrue(msg.oneofMessage === autoCreated)  // Still the same
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+    // Clear the oneof.
+    Message3_ClearOOneOfCase(msg)
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oneofFloat, Float(0.0))  // Default
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo)  // Default
+    let autoCreated2 = msg.oneofMessage  // Default create one
+    XCTAssertNotNil(autoCreated2)
+    XCTAssertTrue(autoCreated2 !== autoCreated)  // New instance
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+    msg.oneofInt32 = 10
+    XCTAssertEqual(msg.oneofInt32, Int32(10))
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+    // Confirm Message.clear() handles the oneof correctly.
+    msg.clear()
+    XCTAssertEqual(msg.oneofInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+    // Sets via the autocreated instance.
+    msg.oneofMessage.optionalInt32 = 300
+    XCTAssertTrue(msg.oneofMessage !== autoCreated)  // New instance
+    XCTAssertTrue(msg.oneofMessage !== autoCreated2)  // New instance
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+    // Set message to nil clears the oneof.
+    msg.oneofMessage = nil
+    XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0))  // Default
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+  }
+
+  func testSerialization() {
+    let msg = Message2()
+
+    msg.optionalInt32 = 100
+    msg.optionalInt64 = 101
+    msg.optionalGroup.a = 102
+    msg.repeatedStringArray.addObject("abc")
+    msg.repeatedStringArray.addObject("def")
+    msg.mapInt32Int32.setValue(200, forKey:300)
+    msg.mapInt32Int32.setValue(201, forKey:201)
+    msg.mapStringString.setObject("foo", forKey:"bar")
+    msg.mapStringString.setObject("abc", forKey:"xyz")
+
+    let data = msg.data()
+
+    let msg2 = Message2(data: data!, error:nil)
+    XCTAssertTrue(msg2 !== msg)  // New instance
+    XCTAssertEqual(msg.optionalInt32, Int32(100))
+    XCTAssertEqual(msg.optionalInt64, Int64(101))
+    XCTAssertEqual(msg.optionalGroup.a, Int32(102))
+    XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+    XCTAssertEqual(msg.mapInt32Int32.count, UInt(2))
+    XCTAssertEqual(msg.mapStringString.count, Int(2))
+    XCTAssertEqual(msg2, msg)
+  }
+
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.h b/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.h
new file mode 100644
index 0000000..44c8084
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.h
@@ -0,0 +1,100 @@
+// 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.
+
+#import <XCTest/XCTest.h>
+
+@class TestAllExtensions;
+@class TestAllTypes;
+@class TestMap;
+@class TestPackedTypes;
+@class TestPackedExtensions;
+@class TestUnpackedTypes;
+@class TestUnpackedExtensions;
+@class GPBExtensionRegistry;
+
+
+// Helper for uses of C arrays in tests cases.
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif  // GPBARRAYSIZE
+
+
+// The number of repetitions of any repeated objects inside of test messages.
+extern const uint32_t kGPBDefaultRepeatCount;
+
+@interface GPBTestCase : XCTestCase
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count;
+- (void)clearAllFields:(TestAllTypes *)message;
+- (void)setAllExtensions:(TestAllExtensions *)message
+           repeatedCount:(uint32_t)count;
+- (void)setPackedFields:(TestPackedTypes *)message
+          repeatedCount:(uint32_t)count;
+- (void)setUnpackedFields:(TestUnpackedTypes *)message
+            repeatedCount:(uint32_t)count;
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+              repeatedCount:(uint32_t)count;
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
+              repeatedCount:(uint32_t)count;
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count;
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count;
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count;
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count;
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count;
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+             repeatedCount:(uint32_t)count;
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+                 repeatedCount:(uint32_t)count;
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+                       repeatedCount:(uint32_t)count;
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+                           repeatedCount:(uint32_t)count;
+- (void)assertExtensionsClear:(TestAllExtensions *)message;
+- (void)assertClear:(TestAllTypes *)message;
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+                repeatedCount:(uint32_t)count;
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+                    repeatedCount:(uint32_t)count;
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message;
+- (void)modifyRepeatedFields:(TestAllTypes *)message;
+
+- (GPBExtensionRegistry *)extensionRegistry;
+
+- (NSData *)getDataFileNamed:(NSString *)name dataToWrite:(NSData *)dataToWrite;
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message;
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+             repeatedCount:(uint32_t)count;
+- (void)assertClearKVC:(TestAllTypes *)message;
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.m b/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.m
new file mode 100644
index 0000000..726761a
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBTestUtilities.m
@@ -0,0 +1,2546 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+
+const uint32_t kGPBDefaultRepeatCount = 2;
+
+// Small category to easily turn a CString into an NSData.
+@interface NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer;
++ (instancetype)gpbtu_dataWithEmbeddedNulls;
+@end
+
+@implementation NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer {
+  return [NSData dataWithBytes:buffer length:strlen(buffer)];
+}
+
++ (instancetype)gpbtu_dataWithUint32:(uint32_t)value {
+  return [[[self alloc] initWithUint32_gpbtu:value] autorelease];
+}
+
+- (instancetype)initWithUint32_gpbtu:(uint32_t)value {
+  value = CFSwapInt32HostToLittle(value);
+  return [self initWithBytes:&value length:sizeof(value)];
+}
+
++ (instancetype)gpbtu_dataWithEmbeddedNulls {
+  char bytes[6] = "\1\0\2\3\0\5";
+  return [self dataWithBytes:bytes length:sizeof(bytes)];
+}
+@end
+
+@implementation GPBTestCase
+
+// Return data for name. Optionally (based on #if setting) write out dataToWrite
+// to replace that data. Useful for setting golden masters.
+- (NSData *)getDataFileNamed:(NSString *)name
+                 dataToWrite:(NSData *)dataToWrite {
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *path = [bundle pathForResource:[name stringByDeletingPathExtension]
+                                    ofType:[name pathExtension]];
+  XCTAssertNotNil(path, @"Unable to find %@", name);
+  NSData *data = [NSData dataWithContentsOfFile:path];
+  XCTAssertNotNil(data, @"Unable to load from %@", path);
+#if 0
+  // Enable to write out golden master files.
+  if (!path) {
+    path = [[bundle resourcePath] stringByAppendingPathComponent:name];
+  }
+  NSError *error = nil;
+  BOOL wrote = [dataToWrite writeToFile:path options:NSDataWritingAtomic error:&error];
+  XCTAssertTrue(wrote, @"Unable to write %@ (%@)", path, error);
+  NSLog(@"Wrote data file to %@", path);
+#else
+  // Kill off the unused variable warning.
+  dataToWrite = dataToWrite;
+#endif
+  return data;
+}
+
+// -------------------------------------------------------------------
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message {
+  [message setExtension:[UnittestRoot repeatedInt32Extension]
+                  index:1
+                  value:@501];
+  [message setExtension:[UnittestRoot repeatedInt64Extension]
+                  index:1
+                  value:@502];
+  [message setExtension:[UnittestRoot repeatedUint32Extension]
+                  index:1
+                  value:@503];
+  [message setExtension:[UnittestRoot repeatedUint64Extension]
+                  index:1
+                  value:@504];
+  [message setExtension:[UnittestRoot repeatedSint32Extension]
+                  index:1
+                  value:@505];
+  [message setExtension:[UnittestRoot repeatedSint64Extension]
+                  index:1
+                  value:@506];
+  [message setExtension:[UnittestRoot repeatedFixed32Extension]
+                  index:1
+                  value:@507];
+  [message setExtension:[UnittestRoot repeatedFixed64Extension]
+                  index:1
+                  value:@508];
+  [message setExtension:[UnittestRoot repeatedSfixed32Extension]
+                  index:1
+                  value:@509];
+  [message setExtension:[UnittestRoot repeatedSfixed64Extension]
+                  index:1
+                  value:@510];
+  [message setExtension:[UnittestRoot repeatedFloatExtension]
+                  index:1
+                  value:@511.0f];
+  [message setExtension:[UnittestRoot repeatedDoubleExtension]
+                  index:1
+                  value:@512.0];
+  [message setExtension:[UnittestRoot repeatedBoolExtension]
+                  index:1
+                  value:@YES];
+  [message setExtension:[UnittestRoot repeatedStringExtension]
+                  index:1
+                  value:@"515"];
+  [message setExtension:[UnittestRoot repeatedBytesExtension]
+                  index:1
+                  value:[NSData gpbtu_dataWithUint32:516]];
+
+  RepeatedGroup_extension *repeatedGroup = [RepeatedGroup_extension message];
+  [repeatedGroup setA:517];
+  [message setExtension:[UnittestRoot repeatedGroupExtension]
+                  index:1
+                  value:repeatedGroup];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  [nestedMessage setBb:518];
+  [message setExtension:[UnittestRoot repeatedNestedMessageExtension]
+                  index:1
+                  value:nestedMessage];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setC:519];
+  [message setExtension:[UnittestRoot repeatedForeignMessageExtension]
+                  index:1
+                  value:foreignMessage];
+  ImportMessage *importMessage = [ImportMessage message];
+  [importMessage setD:520];
+  [message setExtension:[UnittestRoot repeatedImportMessageExtension]
+                  index:1
+                  value:importMessage];
+
+  [message setExtension:[UnittestRoot repeatedNestedEnumExtension]
+                  index:1
+                  value:@(TestAllTypes_NestedEnum_Foo)];
+  [message setExtension:[UnittestRoot repeatedForeignEnumExtension]
+                  index:1
+                  value:@(ForeignEnum_ForeignFoo)];
+  [message setExtension:[UnittestRoot repeatedImportEnumExtension]
+                  index:1
+                  value:@(ImportEnum_ImportFoo)];
+
+  [message setExtension:[UnittestRoot repeatedStringPieceExtension]
+                  index:1
+                  value:@"524"];
+  [message setExtension:[UnittestRoot repeatedCordExtension]
+                  index:1
+                  value:@"525"];
+}
+
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+                 repeatedCount:(uint32_t)count {
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+  XCTAssertTrue([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+  XCTAssertTrue([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+  XCTAssertTrue([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+  XCTAssertTrue([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+  XCTAssertEqual(101, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+  XCTAssertEqual(102LL, [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+  XCTAssertEqual(103U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(104ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(105, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+  XCTAssertEqual(106LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+  XCTAssertEqual(107U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(108ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(109, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+  XCTAssertEqual(110LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(111.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(112.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+  XCTAssertTrue([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+  XCTAssertEqualObjects(@"115", [message getExtension:[UnittestRoot optionalStringExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls], [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+  XCTAssertEqual(117, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+  XCTAssertEqual(118, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+  XCTAssertEqual(119, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+  XCTAssertEqual(120, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignBaz, [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportBaz, [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+  XCTAssertEqualObjects(@"124", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+  XCTAssertEqualObjects(@"125", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+  // -----------------------------------------------------------------
+
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+  for (uint32_t i = 0; i < count; ++i) {
+    id extension = [message getExtension:[UnittestRoot repeatedInt32Extension]];
+    XCTAssertEqual((int)(201 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot repeatedInt64Extension]];
+    XCTAssertEqual(202 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot repeatedUint32Extension]];
+    XCTAssertEqual(203 + i * 100, [extension[i] unsignedIntValue]);
+    extension = [message getExtension:[UnittestRoot repeatedUint64Extension]];
+    XCTAssertEqual(204 + i * 100, [extension[i] unsignedLongLongValue]);
+    extension = [message getExtension:[UnittestRoot repeatedSint32Extension]];
+    XCTAssertEqual((int)(205 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot repeatedSint64Extension]];
+    XCTAssertEqual(206 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot repeatedFixed32Extension]];
+    XCTAssertEqual(207 + i * 100, [extension[i] unsignedIntValue]);
+    extension = [message getExtension:[UnittestRoot repeatedFixed64Extension]];
+    XCTAssertEqual(208 + i * 100, [extension[i] unsignedLongLongValue]);
+    extension = [message getExtension:[UnittestRoot repeatedSfixed32Extension]];
+    XCTAssertEqual((int)(209 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot repeatedSfixed64Extension]];
+    XCTAssertEqual(210 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot repeatedFloatExtension]];
+    XCTAssertEqualWithAccuracy(211 + i * 100, [extension[i] floatValue], 0.01);
+    extension = [message getExtension:[UnittestRoot repeatedDoubleExtension]];
+    XCTAssertEqualWithAccuracy(212 + i * 100, [extension[i] doubleValue], 0.01);
+    extension = [message getExtension:[UnittestRoot repeatedBoolExtension]];
+    XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+    extension = [message getExtension:[UnittestRoot repeatedStringExtension]];
+    XCTAssertEqualObjects(string, extension[i]);
+    [string release];
+
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+    extension = [message getExtension:[UnittestRoot repeatedBytesExtension]];
+    XCTAssertEqualObjects(data, extension[i]);
+    [data release];
+
+    extension = [message getExtension:[UnittestRoot repeatedGroupExtension]];
+    XCTAssertEqual((int)(217 + i * 100), [(TestAllTypes_OptionalGroup*)extension[i] a]);
+    extension = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
+    XCTAssertEqual((int)(218 + i * 100), [(TestAllTypes_NestedMessage*)extension[i] bb]);
+    extension = [message getExtension:[UnittestRoot repeatedForeignMessageExtension]];
+    XCTAssertEqual((int)(219 + i * 100), [extension[i] c]);
+    extension = [message getExtension:[UnittestRoot repeatedImportMessageExtension]];
+    XCTAssertEqual((int)(220 + i * 100), [extension[i] d]);
+
+    extension = [message getExtension:[UnittestRoot repeatedNestedEnumExtension]];
+    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot repeatedForeignEnumExtension]];
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot repeatedImportEnumExtension]];
+    XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [extension[i] intValue]);
+
+    string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+    extension = [message getExtension:[UnittestRoot repeatedStringPieceExtension]];
+    XCTAssertEqualObjects(string, extension[i]);
+    [string release];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+    extension = [message getExtension:[UnittestRoot repeatedCordExtension]];
+    XCTAssertEqualObjects(string, extension[i]);
+    [string release];
+  }
+
+  // -----------------------------------------------------------------
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+  XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+  XCTAssertEqual(401, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+  XCTAssertEqual(402LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+  XCTAssertEqual(403U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(404ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(405, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+  XCTAssertEqual(406LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+  XCTAssertEqual(407U, [[message getExtension:[UnittestRoot defaultFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(408ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(409, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+  XCTAssertEqual(410LL,[[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(411.0f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(412.0, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+  XCTAssertFalse([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+  XCTAssertEqualObjects(@"415", [message getExtension:[UnittestRoot defaultStringExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignFoo, [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportFoo, [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+  XCTAssertEqualObjects(@"424", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+  XCTAssertEqualObjects(@"425", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+                           repeatedCount:(uint32_t)count {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+  XCTAssertEqual(201,[[message getExtension:[UnittestRoot repeatedInt32Extension]][0] intValue]);
+  XCTAssertEqual(202LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][0] longLongValue]);
+  XCTAssertEqual(203U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][0] unsignedIntValue]);
+  XCTAssertEqual(204ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][0] unsignedLongLongValue]);
+  XCTAssertEqual(205, [[message getExtension:[UnittestRoot repeatedSint32Extension]][0] intValue]);
+  XCTAssertEqual(206LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][0] longLongValue]);
+  XCTAssertEqual(207U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][0] unsignedIntValue]);
+  XCTAssertEqual(208ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][0] unsignedLongLongValue]);
+  XCTAssertEqual(209, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][0] intValue]);
+  XCTAssertEqual(210LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][0] longLongValue]);
+  XCTAssertEqualWithAccuracy(211.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][0] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(212.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][0] doubleValue], 0.01);
+  XCTAssertFalse([[message getExtension:[UnittestRoot repeatedBoolExtension]][0] boolValue]);
+  XCTAssertEqualObjects(@"215", [message getExtension:[UnittestRoot repeatedStringExtension]][0]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216], [message getExtension:[UnittestRoot repeatedBytesExtension]][0]);
+
+  XCTAssertEqual(217, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][0] a]);
+  XCTAssertEqual(218, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][0] bb]);
+  XCTAssertEqual(219, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][0] c]);
+  XCTAssertEqual(220, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][0] d]);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Baz,
+                 [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][0] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignBaz,
+                 [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][0] intValue]);
+  XCTAssertEqual(ImportEnum_ImportBaz,
+                 [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][0] intValue]);
+
+  XCTAssertEqualObjects(@"224", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][0]);
+  XCTAssertEqualObjects(@"225", [message getExtension:[UnittestRoot repeatedCordExtension]][0]);
+
+  // Actually verify the second (modified) elements now.
+  XCTAssertEqual(501, [[message getExtension:[UnittestRoot repeatedInt32Extension]][1] intValue]);
+  XCTAssertEqual(502LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][1] longLongValue]);
+  XCTAssertEqual(503U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][1] unsignedIntValue]);
+  XCTAssertEqual(504ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][1] unsignedLongLongValue]);
+  XCTAssertEqual(505, [[message getExtension:[UnittestRoot repeatedSint32Extension]][1] intValue]);
+  XCTAssertEqual(506LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][1] longLongValue]);
+  XCTAssertEqual(507U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][1] unsignedIntValue]);
+  XCTAssertEqual(508ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][1] unsignedLongLongValue]);
+  XCTAssertEqual(509, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][1] intValue]);
+  XCTAssertEqual(510LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][1] longLongValue]);
+  XCTAssertEqualWithAccuracy(511.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][1] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(512.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][1] doubleValue], 0.01);
+  XCTAssertTrue([[message getExtension:[UnittestRoot repeatedBoolExtension]][1] boolValue]);
+  XCTAssertEqualObjects(@"515", [message getExtension:[UnittestRoot repeatedStringExtension]][1]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516], [message getExtension:[UnittestRoot repeatedBytesExtension]][1]);
+
+  XCTAssertEqual(517, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][1] a]);
+  XCTAssertEqual(518, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][1] bb]);
+  XCTAssertEqual(519, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][1] c]);
+  XCTAssertEqual(520, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][1] d]);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+                 [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][1] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignFoo,
+                 [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][1] intValue]);
+  XCTAssertEqual(ImportEnum_ImportFoo,
+                 [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][1] intValue]);
+
+  XCTAssertEqualObjects(@"524", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][1]);
+  XCTAssertEqualObjects(@"525", [message getExtension:[UnittestRoot repeatedCordExtension]][1]);
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+             repeatedCount:(uint32_t)count {
+  XCTAssertTrue(message.hasOptionalInt32);
+  XCTAssertTrue(message.hasOptionalInt64);
+  XCTAssertTrue(message.hasOptionalUint32);
+  XCTAssertTrue(message.hasOptionalUint64);
+  XCTAssertTrue(message.hasOptionalSint32);
+  XCTAssertTrue(message.hasOptionalSint64);
+  XCTAssertTrue(message.hasOptionalFixed32);
+  XCTAssertTrue(message.hasOptionalFixed64);
+  XCTAssertTrue(message.hasOptionalSfixed32);
+  XCTAssertTrue(message.hasOptionalSfixed64);
+  XCTAssertTrue(message.hasOptionalFloat);
+  XCTAssertTrue(message.hasOptionalDouble);
+  XCTAssertTrue(message.hasOptionalBool);
+  XCTAssertTrue(message.hasOptionalString);
+  XCTAssertTrue(message.hasOptionalBytes);
+
+  XCTAssertTrue(message.hasOptionalGroup);
+  XCTAssertTrue(message.hasOptionalNestedMessage);
+  XCTAssertTrue(message.hasOptionalForeignMessage);
+  XCTAssertTrue(message.hasOptionalImportMessage);
+
+  XCTAssertTrue(message.optionalGroup.hasA);
+  XCTAssertTrue(message.optionalNestedMessage.hasBb);
+  XCTAssertTrue(message.optionalForeignMessage.hasC);
+  XCTAssertTrue(message.optionalImportMessage.hasD);
+
+  XCTAssertTrue(message.hasOptionalNestedEnum);
+  XCTAssertTrue(message.hasOptionalForeignEnum);
+  XCTAssertTrue(message.hasOptionalImportEnum);
+
+  XCTAssertTrue(message.hasOptionalStringPiece);
+  XCTAssertTrue(message.hasOptionalCord);
+
+  XCTAssertEqual(101, message.optionalInt32);
+  XCTAssertEqual(102LL, message.optionalInt64);
+  XCTAssertEqual(103U, message.optionalUint32);
+  XCTAssertEqual(104ULL, message.optionalUint64);
+  XCTAssertEqual(105, message.optionalSint32);
+  XCTAssertEqual(106LL, message.optionalSint64);
+  XCTAssertEqual(107U, message.optionalFixed32);
+  XCTAssertEqual(108ULL, message.optionalFixed64);
+  XCTAssertEqual(109, message.optionalSfixed32);
+  XCTAssertEqual(110LL, message.optionalSfixed64);
+  XCTAssertEqualWithAccuracy(111.0f, message.optionalFloat, 0.1);
+  XCTAssertEqualWithAccuracy(112.0, message.optionalDouble, 0.1);
+  XCTAssertTrue(message.optionalBool);
+  XCTAssertEqualObjects(@"115", message.optionalString);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls],
+                        message.optionalBytes);
+
+  XCTAssertEqual(117, message.optionalGroup.a);
+  XCTAssertEqual(118, message.optionalNestedMessage.bb);
+  XCTAssertEqual(119, message.optionalForeignMessage.c);
+  XCTAssertEqual(120, message.optionalImportMessage.d);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Baz, message.optionalNestedEnum);
+  XCTAssertEqual(ForeignEnum_ForeignBaz, message.optionalForeignEnum);
+  XCTAssertEqual(ImportEnum_ImportBaz, message.optionalImportEnum);
+
+  XCTAssertEqualObjects(@"124", message.optionalStringPiece);
+  XCTAssertEqualObjects(@"125", message.optionalCord);
+
+  // -----------------------------------------------------------------
+
+  XCTAssertEqual(count, message.repeatedInt32Array.count);
+  XCTAssertEqual(count, message.repeatedInt64Array.count);
+  XCTAssertEqual(count, message.repeatedUint32Array.count);
+  XCTAssertEqual(count, message.repeatedUint64Array.count);
+  XCTAssertEqual(count, message.repeatedSint32Array.count);
+  XCTAssertEqual(count, message.repeatedSint64Array.count);
+  XCTAssertEqual(count, message.repeatedFixed32Array.count);
+  XCTAssertEqual(count, message.repeatedFixed64Array.count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+  XCTAssertEqual(count, message.repeatedFloatArray.count);
+  XCTAssertEqual(count, message.repeatedDoubleArray.count);
+  XCTAssertEqual(count, message.repeatedBoolArray.count);
+  XCTAssertEqual(count, message.repeatedStringArray.count);
+  XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray.count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+  XCTAssertEqual(count, message.repeatedCordArray.count);
+
+  XCTAssertEqual(count, message.repeatedInt32Array_Count);
+  XCTAssertEqual(count, message.repeatedInt64Array_Count);
+  XCTAssertEqual(count, message.repeatedUint32Array_Count);
+  XCTAssertEqual(count, message.repeatedUint64Array_Count);
+  XCTAssertEqual(count, message.repeatedSint32Array_Count);
+  XCTAssertEqual(count, message.repeatedSint64Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedFloatArray_Count);
+  XCTAssertEqual(count, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(count, message.repeatedBoolArray_Count);
+  XCTAssertEqual(count, message.repeatedStringArray_Count);
+  XCTAssertEqual(count, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(count, message.repeatedCordArray_Count);
+
+  for (uint32_t i = 0; i < count; ++i) {
+    XCTAssertEqual((int)(201 + i * 100),
+                   [message.repeatedInt32Array valueAtIndex:i]);
+    XCTAssertEqual(202 + i * 100, [message.repeatedInt64Array valueAtIndex:i]);
+    XCTAssertEqual(203 + i * 100, [message.repeatedUint32Array valueAtIndex:i]);
+    XCTAssertEqual(204 + i * 100, [message.repeatedUint64Array valueAtIndex:i]);
+    XCTAssertEqual((int)(205 + i * 100),
+                   [message.repeatedSint32Array valueAtIndex:i]);
+    XCTAssertEqual(206 + i * 100, [message.repeatedSint64Array valueAtIndex:i]);
+    XCTAssertEqual(207 + i * 100,
+                   [message.repeatedFixed32Array valueAtIndex:i]);
+    XCTAssertEqual(208 + i * 100,
+                   [message.repeatedFixed64Array valueAtIndex:i]);
+    XCTAssertEqual((int)(209 + i * 100),
+                   [message.repeatedSfixed32Array valueAtIndex:i]);
+    XCTAssertEqual(210 + i * 100,
+                   [message.repeatedSfixed64Array valueAtIndex:i]);
+    XCTAssertEqualWithAccuracy(
+        211 + i * 100, [message.repeatedFloatArray valueAtIndex:i], 0.1);
+    XCTAssertEqualWithAccuracy(
+        212 + i * 100, [message.repeatedDoubleArray valueAtIndex:i], 0.1);
+    XCTAssertEqual((i % 2) ? YES : NO,
+                   [message.repeatedBoolArray valueAtIndex:i]);
+
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+    XCTAssertEqualObjects(string, message.repeatedStringArray[i]);
+    [string release];
+
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+    XCTAssertEqualObjects(data, message.repeatedBytesArray[i]);
+    [data release];
+
+    XCTAssertEqual((int)(217 + i * 100), ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[i]).a);
+    XCTAssertEqual((int)(218 + i * 100), ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[i]).bb);
+    XCTAssertEqual((int)(219 + i * 100), ((ForeignMessage*)message.repeatedForeignMessageArray[i]).c);
+    XCTAssertEqual((int)(220 + i * 100), ((ImportMessage*)message.repeatedImportMessageArray[i]).d);
+
+    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:i]);
+
+    string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+    XCTAssertEqualObjects(string, message.repeatedStringPieceArray[i]);
+    [string release];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+    XCTAssertEqualObjects(string, message.repeatedCordArray[i]);
+    [string release];
+  }
+
+  // -----------------------------------------------------------------
+
+  XCTAssertTrue(message.hasDefaultInt32);
+  XCTAssertTrue(message.hasDefaultInt64);
+  XCTAssertTrue(message.hasDefaultUint32);
+  XCTAssertTrue(message.hasDefaultUint64);
+  XCTAssertTrue(message.hasDefaultSint32);
+  XCTAssertTrue(message.hasDefaultSint64);
+  XCTAssertTrue(message.hasDefaultFixed32);
+  XCTAssertTrue(message.hasDefaultFixed64);
+  XCTAssertTrue(message.hasDefaultSfixed32);
+  XCTAssertTrue(message.hasDefaultSfixed64);
+  XCTAssertTrue(message.hasDefaultFloat);
+  XCTAssertTrue(message.hasDefaultDouble);
+  XCTAssertTrue(message.hasDefaultBool);
+  XCTAssertTrue(message.hasDefaultString);
+  XCTAssertTrue(message.hasDefaultBytes);
+
+  XCTAssertTrue(message.hasDefaultNestedEnum);
+  XCTAssertTrue(message.hasDefaultForeignEnum);
+  XCTAssertTrue(message.hasDefaultImportEnum);
+
+  XCTAssertTrue(message.hasDefaultStringPiece);
+  XCTAssertTrue(message.hasDefaultCord);
+
+  XCTAssertEqual(401, message.defaultInt32);
+  XCTAssertEqual(402LL, message.defaultInt64);
+  XCTAssertEqual(403U, message.defaultUint32);
+  XCTAssertEqual(404ULL, message.defaultUint64);
+  XCTAssertEqual(405, message.defaultSint32);
+  XCTAssertEqual(406LL, message.defaultSint64);
+  XCTAssertEqual(407U, message.defaultFixed32);
+  XCTAssertEqual(408ULL, message.defaultFixed64);
+  XCTAssertEqual(409, message.defaultSfixed32);
+  XCTAssertEqual(410LL, message.defaultSfixed64);
+  XCTAssertEqualWithAccuracy(411.0f, message.defaultFloat, 0.1);
+  XCTAssertEqualWithAccuracy(412.0, message.defaultDouble, 0.1);
+  XCTAssertFalse(message.defaultBool);
+  XCTAssertEqualObjects(@"415", message.defaultString);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416],
+                        message.defaultBytes);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.defaultNestedEnum);
+  XCTAssertEqual(ForeignEnum_ForeignFoo, message.defaultForeignEnum);
+  XCTAssertEqual(ImportEnum_ImportFoo, message.defaultImportEnum);
+
+  XCTAssertEqualObjects(@"424", message.defaultStringPiece);
+  XCTAssertEqualObjects(@"425", message.defaultCord);
+}
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count {
+  [message setOptionalInt32:101];
+  [message setOptionalInt64:102];
+  [message setOptionalUint32:103];
+  [message setOptionalUint64:104];
+  [message setOptionalSint32:105];
+  [message setOptionalSint64:106];
+  [message setOptionalFixed32:107];
+  [message setOptionalFixed64:108];
+  [message setOptionalSfixed32:109];
+  [message setOptionalSfixed64:110];
+  [message setOptionalFloat:111];
+  [message setOptionalDouble:112];
+  [message setOptionalBool:YES];
+  [message setOptionalString:@"115"];
+  [message setOptionalBytes:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+  TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+  [allTypes setA:117];
+  [message setOptionalGroup:allTypes];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  [nestedMessage setBb:118];
+  [message setOptionalNestedMessage:nestedMessage];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setC:119];
+  [message setOptionalForeignMessage:foreignMessage];
+  ImportMessage *importMessage = [ImportMessage message];
+  [importMessage setD:120];
+  [message setOptionalImportMessage:importMessage];
+
+  [message setOptionalNestedEnum:TestAllTypes_NestedEnum_Baz];
+  [message setOptionalForeignEnum:ForeignEnum_ForeignBaz];
+  [message setOptionalImportEnum:ImportEnum_ImportBaz];
+
+  [message setOptionalStringPiece:@"124"];
+  [message setOptionalCord:@"125"];
+
+  // -----------------------------------------------------------------
+
+  for (uint32_t i = 0; i < count; i++) {
+    [message.repeatedInt32Array addValue:201 + i * 100];
+    [message.repeatedInt64Array addValue:202 + i * 100];
+    [message.repeatedUint32Array addValue:203 + i * 100];
+    [message.repeatedUint64Array addValue:204 + i * 100];
+    [message.repeatedSint32Array addValue:205 + i * 100];
+    [message.repeatedSint64Array addValue:206 + i * 100];
+    [message.repeatedFixed32Array addValue:207 + i * 100];
+    [message.repeatedFixed64Array addValue:208 + i * 100];
+    [message.repeatedSfixed32Array addValue:209 + i * 100];
+    [message.repeatedSfixed64Array addValue:210 + i * 100];
+    [message.repeatedFloatArray addValue:211 + i * 100];
+    [message.repeatedDoubleArray addValue:212 + i * 100];
+    [message.repeatedBoolArray addValue:(i % 2)];
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+    [message.repeatedStringArray addObject:string];
+    [string release];
+
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+    [message.repeatedBytesArray addObject:data];
+    [data release];
+
+    TestAllTypes_RepeatedGroup *testAll =
+        [[TestAllTypes_RepeatedGroup alloc] init];
+    [testAll setA:217 + i * 100];
+    [message.repeatedGroupArray addObject:testAll];
+    [testAll release];
+
+    nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+    [nestedMessage setBb:218 + i * 100];
+    [message.repeatedNestedMessageArray addObject:nestedMessage];
+    [nestedMessage release];
+
+    foreignMessage = [[ForeignMessage alloc] init];
+    [foreignMessage setC:219 + i * 100];
+    [message.repeatedForeignMessageArray addObject:foreignMessage];
+    [foreignMessage release];
+
+    importMessage = [[ImportMessage alloc] init];
+    [importMessage setD:220 + i * 100];
+    [message.repeatedImportMessageArray addObject:importMessage];
+    [importMessage release];
+
+    [message.repeatedNestedEnumArray addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
+
+    [message.repeatedForeignEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+    [message.repeatedImportEnumArray addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+    [message.repeatedStringPieceArray addObject:string];
+    [string release];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+    [message.repeatedCordArray addObject:string];
+    [string release];
+  }
+  // -----------------------------------------------------------------
+
+  message.defaultInt32 = 401;
+  message.defaultInt64 = 402;
+  message.defaultUint32 = 403;
+  message.defaultUint64 = 404;
+  message.defaultSint32 = 405;
+  message.defaultSint64 = 406;
+  message.defaultFixed32 = 407;
+  message.defaultFixed64 = 408;
+  message.defaultSfixed32 = 409;
+  message.defaultSfixed64 = 410;
+  message.defaultFloat = 411;
+  message.defaultDouble = 412;
+  message.defaultBool = NO;
+  message.defaultString = @"415";
+  message.defaultBytes = [NSData gpbtu_dataWithUint32:416];
+
+  message.defaultNestedEnum = TestAllTypes_NestedEnum_Foo;
+  message.defaultForeignEnum = ForeignEnum_ForeignFoo;
+  message.defaultImportEnum = ImportEnum_ImportFoo;
+
+  message.defaultStringPiece = @"424";
+  message.defaultCord = @"425";
+}
+
+- (void)clearAllFields:(TestAllTypes *)message {
+  message.hasOptionalInt32 = NO;
+  message.hasOptionalInt64 = NO;
+  message.hasOptionalUint32 = NO;
+  message.hasOptionalUint64 = NO;
+  message.hasOptionalSint32 = NO;
+  message.hasOptionalSint64 = NO;
+  message.hasOptionalFixed32 = NO;
+  message.hasOptionalFixed64 = NO;
+  message.hasOptionalSfixed32 = NO;
+  message.hasOptionalSfixed64 = NO;
+  message.hasOptionalFloat = NO;
+  message.hasOptionalDouble = NO;
+  message.hasOptionalBool = NO;
+  message.hasOptionalString = NO;
+  message.hasOptionalBytes = NO;
+
+  message.hasOptionalGroup = NO;
+  message.hasOptionalNestedMessage = NO;
+  message.hasOptionalForeignMessage = NO;
+  message.hasOptionalImportMessage = NO;
+
+  message.hasOptionalNestedEnum = NO;
+  message.hasOptionalForeignEnum = NO;
+  message.hasOptionalImportEnum = NO;
+
+  message.hasOptionalStringPiece = NO;
+  message.hasOptionalCord = NO;
+
+  // -----------------------------------------------------------------
+
+  [message.repeatedInt32Array removeAll];
+  [message.repeatedInt64Array removeAll];
+  [message.repeatedUint32Array removeAll];
+  [message.repeatedUint64Array removeAll];
+  [message.repeatedSint32Array removeAll];
+  [message.repeatedSint64Array removeAll];
+  [message.repeatedFixed32Array removeAll];
+  [message.repeatedFixed64Array removeAll];
+  [message.repeatedSfixed32Array removeAll];
+  [message.repeatedSfixed64Array removeAll];
+  [message.repeatedFloatArray removeAll];
+  [message.repeatedDoubleArray removeAll];
+  [message.repeatedBoolArray removeAll];
+  [message.repeatedStringArray removeAllObjects];
+  [message.repeatedBytesArray removeAllObjects];
+
+  [message.repeatedGroupArray removeAllObjects];
+  [message.repeatedNestedMessageArray removeAllObjects];
+  [message.repeatedForeignMessageArray removeAllObjects];
+  [message.repeatedImportMessageArray removeAllObjects];
+
+  [message.repeatedNestedEnumArray removeAll];
+  [message.repeatedForeignEnumArray removeAll];
+  [message.repeatedImportEnumArray removeAll];
+
+  [message.repeatedStringPieceArray removeAllObjects];
+  [message.repeatedCordArray removeAllObjects];
+
+  // -----------------------------------------------------------------
+
+  message.hasDefaultInt32 = NO;
+  message.hasDefaultInt64 = NO;
+  message.hasDefaultUint32 = NO;
+  message.hasDefaultUint64 = NO;
+  message.hasDefaultSint32 = NO;
+  message.hasDefaultSint64 = NO;
+  message.hasDefaultFixed32 = NO;
+  message.hasDefaultFixed64 = NO;
+  message.hasDefaultSfixed32 = NO;
+  message.hasDefaultSfixed64 = NO;
+  message.hasDefaultFloat = NO;
+  message.hasDefaultDouble = NO;
+  message.hasDefaultBool = NO;
+  message.hasDefaultString = NO;
+  message.hasDefaultBytes = NO;
+
+  message.hasDefaultNestedEnum = NO;
+  message.hasDefaultForeignEnum = NO;
+  message.hasDefaultImportEnum = NO;
+
+  message.hasDefaultStringPiece = NO;
+  message.hasDefaultCord = NO;
+}
+
+- (void)setAllExtensions:(TestAllExtensions *)message
+           repeatedCount:(uint32_t)count {
+  [message setExtension:[UnittestRoot optionalInt32Extension] value:@101];
+  [message setExtension:[UnittestRoot optionalInt64Extension] value:@102L];
+  [message setExtension:[UnittestRoot optionalUint32Extension] value:@103];
+  [message setExtension:[UnittestRoot optionalUint64Extension] value:@104L];
+  [message setExtension:[UnittestRoot optionalSint32Extension] value:@105];
+  [message setExtension:[UnittestRoot optionalSint64Extension] value:@106L];
+  [message setExtension:[UnittestRoot optionalFixed32Extension] value:@107];
+  [message setExtension:[UnittestRoot optionalFixed64Extension] value:@108L];
+  [message setExtension:[UnittestRoot optionalSfixed32Extension] value:@109];
+  [message setExtension:[UnittestRoot optionalSfixed64Extension] value:@110L];
+  [message setExtension:[UnittestRoot optionalFloatExtension] value:@111.0f];
+  [message setExtension:[UnittestRoot optionalDoubleExtension] value:@112.0];
+  [message setExtension:[UnittestRoot optionalBoolExtension] value:@YES];
+  [message setExtension:[UnittestRoot optionalStringExtension] value:@"115"];
+  [message setExtension:[UnittestRoot optionalBytesExtension]
+                  value:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+  OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
+  [optionalGroup setA:117];
+  [message setExtension:[UnittestRoot optionalGroupExtension]
+                  value:optionalGroup];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  [nestedMessage setBb:118];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+                  value:nestedMessage];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setC:119];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+                  value:foreignMessage];
+  ImportMessage *importMessage = [ImportMessage message];
+  [importMessage setD:120];
+  [message setExtension:[UnittestRoot optionalImportMessageExtension]
+                  value:importMessage];
+
+  [message setExtension:[UnittestRoot optionalNestedEnumExtension]
+                  value:@(TestAllTypes_NestedEnum_Baz)];
+  [message setExtension:[UnittestRoot optionalForeignEnumExtension]
+                  value:@(ForeignEnum_ForeignBaz)];
+  [message setExtension:[UnittestRoot optionalImportEnumExtension]
+                  value:@(ImportEnum_ImportBaz)];
+
+  [message setExtension:[UnittestRoot optionalStringPieceExtension]
+                  value:@"124"];
+  [message setExtension:[UnittestRoot optionalCordExtension] value:@"125"];
+
+  for (uint32_t i = 0; i < count; ++i) {
+    [message addExtension:[UnittestRoot repeatedInt32Extension]
+                    value:@(201 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedInt64Extension]
+                    value:@(202 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedUint32Extension]
+                    value:@(203 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedUint64Extension]
+                    value:@(204 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSint32Extension]
+                    value:@(205 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSint64Extension]
+                    value:@(206 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFixed32Extension]
+                    value:@(207 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFixed64Extension]
+                    value:@(208 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSfixed32Extension]
+                    value:@(209 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSfixed64Extension]
+                    value:@(210 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFloatExtension]
+                    value:@(211 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedDoubleExtension]
+                    value:@(212 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedBoolExtension]
+                    value:@((i % 2) ? YES : NO)];
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+    [message addExtension:[UnittestRoot repeatedStringExtension] value:string];
+    [string release];
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+    [message addExtension:[UnittestRoot repeatedBytesExtension] value:data];
+    [data release];
+
+    RepeatedGroup_extension *repeatedGroup =
+        [[RepeatedGroup_extension alloc] init];
+    [repeatedGroup setA:217 + i * 100];
+    [message addExtension:[UnittestRoot repeatedGroupExtension]
+                    value:repeatedGroup];
+    [repeatedGroup release];
+    nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+    [nestedMessage setBb:218 + i * 100];
+    [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
+                    value:nestedMessage];
+    [nestedMessage release];
+    foreignMessage = [[ForeignMessage alloc] init];
+    [foreignMessage setC:219 + i * 100];
+    [message addExtension:[UnittestRoot repeatedForeignMessageExtension]
+                    value:foreignMessage];
+    [foreignMessage release];
+    importMessage = [[ImportMessage alloc] init];
+    [importMessage setD:220 + i * 100];
+    [message addExtension:[UnittestRoot repeatedImportMessageExtension]
+                    value:importMessage];
+    [importMessage release];
+    [message addExtension:[UnittestRoot repeatedNestedEnumExtension]
+                    value:@((i % 2) ? TestAllTypes_NestedEnum_Bar
+                                    : TestAllTypes_NestedEnum_Baz)];
+    [message addExtension:[UnittestRoot repeatedForeignEnumExtension]
+                    value:@((i % 2) ? ForeignEnum_ForeignBar
+                                    : ForeignEnum_ForeignBaz)];
+    [message
+        addExtension:[UnittestRoot repeatedImportEnumExtension]
+               value:@((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz)];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+    [message addExtension:[UnittestRoot repeatedStringPieceExtension]
+                    value:string];
+    [string release];
+
+    string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+    [message addExtension:[UnittestRoot repeatedCordExtension] value:string];
+    [string release];
+  }
+
+  // -----------------------------------------------------------------
+
+  [message setExtension:[UnittestRoot defaultInt32Extension] value:@401];
+  [message setExtension:[UnittestRoot defaultInt64Extension] value:@402L];
+  [message setExtension:[UnittestRoot defaultUint32Extension] value:@403];
+  [message setExtension:[UnittestRoot defaultUint64Extension] value:@404L];
+  [message setExtension:[UnittestRoot defaultSint32Extension] value:@405];
+  [message setExtension:[UnittestRoot defaultSint64Extension] value:@406L];
+  [message setExtension:[UnittestRoot defaultFixed32Extension] value:@407];
+  [message setExtension:[UnittestRoot defaultFixed64Extension] value:@408L];
+  [message setExtension:[UnittestRoot defaultSfixed32Extension] value:@409];
+  [message setExtension:[UnittestRoot defaultSfixed64Extension] value:@410L];
+  [message setExtension:[UnittestRoot defaultFloatExtension] value:@411.0f];
+  [message setExtension:[UnittestRoot defaultDoubleExtension] value:@412.0];
+  [message setExtension:[UnittestRoot defaultBoolExtension] value:@NO];
+  [message setExtension:[UnittestRoot defaultStringExtension] value:@"415"];
+  [message setExtension:[UnittestRoot defaultBytesExtension]
+                  value:[NSData gpbtu_dataWithUint32:416]];
+
+  [message setExtension:[UnittestRoot defaultNestedEnumExtension]
+                  value:@(TestAllTypes_NestedEnum_Foo)];
+  [message setExtension:[UnittestRoot defaultForeignEnumExtension]
+                  value:@(ForeignEnum_ForeignFoo)];
+  [message setExtension:[UnittestRoot defaultImportEnumExtension]
+                  value:@(ImportEnum_ImportFoo)];
+
+  [message setExtension:[UnittestRoot defaultStringPieceExtension]
+                  value:@"424"];
+  [message setExtension:[UnittestRoot defaultCordExtension] value:@"425"];
+}
+
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count {
+  for (uint32_t i = 0; i < count; i++) {
+    [message.mapInt32Int32 setValue:(i + 1) forKey:100 + i * 100];
+    [message.mapInt64Int64 setValue:(i + 1) forKey:101 + i * 100];
+    [message.mapUint32Uint32 setValue:(i + 1) forKey:102 + i * 100];
+    [message.mapUint64Uint64 setValue:(i + 1) forKey:103 + i * 100];
+    [message.mapSint32Sint32 setValue:(i + 1) forKey:104 + i * 100];
+    [message.mapSint64Sint64 setValue:(i + 1) forKey:105 + i * 100];
+    [message.mapFixed32Fixed32 setValue:(i + 1) forKey:106 + i * 100];
+    [message.mapFixed64Fixed64 setValue:(i + 1) forKey:107 + i * 100];
+    [message.mapSfixed32Sfixed32 setValue:(i + 1) forKey:108 + i * 100];
+    [message.mapSfixed64Sfixed64 setValue:(i + 1) forKey:109 + i * 100];
+    [message.mapInt32Float setValue:(i + 1) forKey:110 + i * 100];
+    [message.mapInt32Double setValue:(i + 1) forKey:111 + i * 100];
+    [message.mapBoolBool setValue:((i % 2) == 1) forKey:((i % 2) == 0)];
+
+    NSString *keyStr = [[NSString alloc] initWithFormat:@"%d", 112 + i * 100];
+    NSString *dataStr = [[NSString alloc] initWithFormat:@"%d", i + 1];
+    [message.mapStringString setObject:dataStr forKey:keyStr];
+    [keyStr release];
+    [dataStr release];
+
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:i + 1];
+    [message.mapInt32Bytes setObject:data forKey:113 + i * 100];
+    [data release];
+
+    [message.mapInt32Enum
+        setValue:(i % 2) ? MapEnum_MapEnumBar : MapEnum_MapEnumBaz
+          forKey:114 + i * 100];
+
+    ForeignMessage *subMsg = [[ForeignMessage alloc] init];
+    subMsg.c = i + 1;
+    [message.mapInt32ForeignMessage setObject:subMsg forKey:115 + i * 100];
+    [subMsg release];
+  }
+}
+
+- (void)setAllTestPackedFields:(TestPackedTypes *)message {
+  // Must match -setAllTestUnpackedFields:
+  [message.packedInt32Array addValue:101];
+  [message.packedInt64Array addValue:102];
+  [message.packedUint32Array addValue:103];
+  [message.packedUint64Array addValue:104];
+  [message.packedSint32Array addValue:105];
+  [message.packedSint64Array addValue:106];
+  [message.packedFixed32Array addValue:107];
+  [message.packedFixed64Array addValue:108];
+  [message.packedSfixed32Array addValue:109];
+  [message.packedSfixed64Array addValue:110];
+  [message.packedFloatArray addValue:111.f];
+  [message.packedDoubleArray addValue:112.];
+  [message.packedBoolArray addValue:YES];
+  [message.packedEnumArray addValue:ForeignEnum_ForeignBar];
+
+  [message.packedInt32Array addValue:201];
+  [message.packedInt64Array addValue:302];
+  [message.packedUint32Array addValue:203];
+  [message.packedUint64Array addValue:204];
+  [message.packedSint32Array addValue:205];
+  [message.packedSint64Array addValue:206];
+  [message.packedFixed32Array addValue:207];
+  [message.packedFixed64Array addValue:208];
+  [message.packedSfixed32Array addValue:209];
+  [message.packedSfixed64Array addValue:210];
+  [message.packedFloatArray addValue:211.f];
+  [message.packedDoubleArray addValue:212.];
+  [message.packedBoolArray addValue:NO];
+  [message.packedEnumArray addValue:ForeignEnum_ForeignBaz];
+}
+
+- (void)setAllTestUnpackedFields:(TestUnpackedTypes *)message {
+  // Must match -setAllTestPackedFields:
+  [message.unpackedInt32Array addValue:101];
+  [message.unpackedInt64Array addValue:102];
+  [message.unpackedUint32Array addValue:103];
+  [message.unpackedUint64Array addValue:104];
+  [message.unpackedSint32Array addValue:105];
+  [message.unpackedSint64Array addValue:106];
+  [message.unpackedFixed32Array addValue:107];
+  [message.unpackedFixed64Array addValue:108];
+  [message.unpackedSfixed32Array addValue:109];
+  [message.unpackedSfixed64Array addValue:110];
+  [message.unpackedFloatArray addValue:111.f];
+  [message.unpackedDoubleArray addValue:112.];
+  [message.unpackedBoolArray addValue:YES];
+  [message.unpackedEnumArray addValue:ForeignEnum_ForeignBar];
+
+  [message.unpackedInt32Array addValue:201];
+  [message.unpackedInt64Array addValue:302];
+  [message.unpackedUint32Array addValue:203];
+  [message.unpackedUint64Array addValue:204];
+  [message.unpackedSint32Array addValue:205];
+  [message.unpackedSint64Array addValue:206];
+  [message.unpackedFixed32Array addValue:207];
+  [message.unpackedFixed64Array addValue:208];
+  [message.unpackedSfixed32Array addValue:209];
+  [message.unpackedSfixed64Array addValue:210];
+  [message.unpackedFloatArray addValue:211.f];
+  [message.unpackedDoubleArray addValue:212.];
+  [message.unpackedBoolArray addValue:NO];
+  [message.unpackedEnumArray addValue:ForeignEnum_ForeignBaz];
+}
+
+- (GPBExtensionRegistry *)extensionRegistry {
+  return [UnittestRoot extensionRegistry];
+}
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count {
+  TestAllTypes *message = [TestAllTypes message];
+  [self setAllFields:message repeatedCount:count];
+  return message;
+}
+
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count {
+  TestAllExtensions *message = [TestAllExtensions message];
+  [self setAllExtensions:message repeatedCount:count];
+  return message;
+}
+
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count {
+  TestPackedTypes *message = [TestPackedTypes message];
+  [self setPackedFields:message repeatedCount:count];
+  return message;
+}
+
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count {
+  TestPackedExtensions *message = [TestPackedExtensions message];
+  [self setPackedExtensions:message repeatedCount:count];
+  return message;
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertClear:(TestAllTypes *)message {
+  // hasBlah() should initially be NO for all optional fields.
+  XCTAssertFalse(message.hasOptionalInt32);
+  XCTAssertFalse(message.hasOptionalInt64);
+  XCTAssertFalse(message.hasOptionalUint32);
+  XCTAssertFalse(message.hasOptionalUint64);
+  XCTAssertFalse(message.hasOptionalSint32);
+  XCTAssertFalse(message.hasOptionalSint64);
+  XCTAssertFalse(message.hasOptionalFixed32);
+  XCTAssertFalse(message.hasOptionalFixed64);
+  XCTAssertFalse(message.hasOptionalSfixed32);
+  XCTAssertFalse(message.hasOptionalSfixed64);
+  XCTAssertFalse(message.hasOptionalFloat);
+  XCTAssertFalse(message.hasOptionalDouble);
+  XCTAssertFalse(message.hasOptionalBool);
+  XCTAssertFalse(message.hasOptionalString);
+  XCTAssertFalse(message.hasOptionalBytes);
+
+  XCTAssertFalse(message.hasOptionalGroup);
+  XCTAssertFalse(message.hasOptionalNestedMessage);
+  XCTAssertFalse(message.hasOptionalForeignMessage);
+  XCTAssertFalse(message.hasOptionalImportMessage);
+
+  XCTAssertFalse(message.hasOptionalNestedEnum);
+  XCTAssertFalse(message.hasOptionalForeignEnum);
+  XCTAssertFalse(message.hasOptionalImportEnum);
+
+  XCTAssertFalse(message.hasOptionalStringPiece);
+  XCTAssertFalse(message.hasOptionalCord);
+
+  // Optional fields without defaults are set to zero or something like it.
+  XCTAssertEqual(0, message.optionalInt32);
+  XCTAssertEqual(0LL, message.optionalInt64);
+  XCTAssertEqual(0U, message.optionalUint32);
+  XCTAssertEqual(0ULL, message.optionalUint64);
+  XCTAssertEqual(0, message.optionalSint32);
+  XCTAssertEqual(0LL, message.optionalSint64);
+  XCTAssertEqual(0U, message.optionalFixed32);
+  XCTAssertEqual(0ULL, message.optionalFixed64);
+  XCTAssertEqual(0, message.optionalSfixed32);
+  XCTAssertEqual(0LL, message.optionalSfixed64);
+  XCTAssertEqual(0.0f, message.optionalFloat);
+  XCTAssertEqual(0.0, message.optionalDouble);
+  XCTAssertFalse(message.optionalBool);
+  XCTAssertEqualObjects(message.optionalString, @"");
+  XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+  // Embedded messages should also be clear.
+  XCTAssertFalse(message.hasOptionalGroup);
+  XCTAssertFalse(message.hasOptionalNestedMessage);
+  XCTAssertFalse(message.hasOptionalForeignMessage);
+  XCTAssertFalse(message.hasOptionalImportMessage);
+
+  // Enums without defaults are set to the first value in the enum.
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.optionalNestedEnum);
+  XCTAssertEqual(ForeignEnum_ForeignFoo, message.optionalForeignEnum);
+  XCTAssertEqual(ImportEnum_ImportFoo, message.optionalImportEnum);
+
+  XCTAssertEqualObjects(message.optionalStringPiece, @"");
+  XCTAssertEqualObjects(message.optionalCord, @"");
+
+  // Repeated fields are empty.
+
+  XCTAssertEqual(0U, message.repeatedInt32Array.count);
+  XCTAssertEqual(0U, message.repeatedInt64Array.count);
+  XCTAssertEqual(0U, message.repeatedUint32Array.count);
+  XCTAssertEqual(0U, message.repeatedUint64Array.count);
+  XCTAssertEqual(0U, message.repeatedSint32Array.count);
+  XCTAssertEqual(0U, message.repeatedSint64Array.count);
+  XCTAssertEqual(0U, message.repeatedFixed32Array.count);
+  XCTAssertEqual(0U, message.repeatedFixed64Array.count);
+  XCTAssertEqual(0U, message.repeatedSfixed32Array.count);
+  XCTAssertEqual(0U, message.repeatedSfixed64Array.count);
+  XCTAssertEqual(0U, message.repeatedFloatArray.count);
+  XCTAssertEqual(0U, message.repeatedDoubleArray.count);
+  XCTAssertEqual(0U, message.repeatedBoolArray.count);
+  XCTAssertEqual(0U, message.repeatedStringArray.count);
+  XCTAssertEqual(0U, message.repeatedBytesArray.count);
+
+  XCTAssertEqual(0U, message.repeatedGroupArray.count);
+  XCTAssertEqual(0U, message.repeatedNestedMessageArray.count);
+  XCTAssertEqual(0U, message.repeatedForeignMessageArray.count);
+  XCTAssertEqual(0U, message.repeatedImportMessageArray.count);
+  XCTAssertEqual(0U, message.repeatedNestedEnumArray.count);
+  XCTAssertEqual(0U, message.repeatedForeignEnumArray.count);
+  XCTAssertEqual(0U, message.repeatedImportEnumArray.count);
+
+  XCTAssertEqual(0U, message.repeatedStringPieceArray.count);
+  XCTAssertEqual(0U, message.repeatedCordArray.count);
+
+  XCTAssertEqual(0U, message.repeatedInt32Array_Count);
+  XCTAssertEqual(0U, message.repeatedInt64Array_Count);
+  XCTAssertEqual(0U, message.repeatedUint32Array_Count);
+  XCTAssertEqual(0U, message.repeatedUint64Array_Count);
+  XCTAssertEqual(0U, message.repeatedSint32Array_Count);
+  XCTAssertEqual(0U, message.repeatedSint64Array_Count);
+  XCTAssertEqual(0U, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(0U, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(0U, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(0U, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(0U, message.repeatedFloatArray_Count);
+  XCTAssertEqual(0U, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(0U, message.repeatedBoolArray_Count);
+  XCTAssertEqual(0U, message.repeatedStringArray_Count);
+  XCTAssertEqual(0U, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(0U, message.repeatedGroupArray_Count);
+  XCTAssertEqual(0U, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(0U, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(0U, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(0U, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(0U, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(0U, message.repeatedCordArray_Count);
+
+  // hasBlah() should also be NO for all default fields.
+  XCTAssertFalse(message.hasDefaultInt32);
+  XCTAssertFalse(message.hasDefaultInt64);
+  XCTAssertFalse(message.hasDefaultUint32);
+  XCTAssertFalse(message.hasDefaultUint64);
+  XCTAssertFalse(message.hasDefaultSint32);
+  XCTAssertFalse(message.hasDefaultSint64);
+  XCTAssertFalse(message.hasDefaultFixed32);
+  XCTAssertFalse(message.hasDefaultFixed64);
+  XCTAssertFalse(message.hasDefaultSfixed32);
+  XCTAssertFalse(message.hasDefaultSfixed64);
+  XCTAssertFalse(message.hasDefaultFloat);
+  XCTAssertFalse(message.hasDefaultDouble);
+  XCTAssertFalse(message.hasDefaultBool);
+  XCTAssertFalse(message.hasDefaultString);
+  XCTAssertFalse(message.hasDefaultBytes);
+
+  XCTAssertFalse(message.hasDefaultNestedEnum);
+  XCTAssertFalse(message.hasDefaultForeignEnum);
+  XCTAssertFalse(message.hasDefaultImportEnum);
+
+  XCTAssertFalse(message.hasDefaultStringPiece);
+  XCTAssertFalse(message.hasDefaultCord);
+
+  // Fields with defaults have their default values (duh).
+  XCTAssertEqual(41, message.defaultInt32);
+  XCTAssertEqual(42LL, message.defaultInt64);
+  XCTAssertEqual(43U, message.defaultUint32);
+  XCTAssertEqual(44ULL, message.defaultUint64);
+  XCTAssertEqual(-45, message.defaultSint32);
+  XCTAssertEqual(46LL, message.defaultSint64);
+  XCTAssertEqual(47U, message.defaultFixed32);
+  XCTAssertEqual(48ULL, message.defaultFixed64);
+  XCTAssertEqual(49, message.defaultSfixed32);
+  XCTAssertEqual(-50LL, message.defaultSfixed64);
+  XCTAssertEqualWithAccuracy(51.5f, message.defaultFloat, 0.1);
+  XCTAssertEqualWithAccuracy(52e3, message.defaultDouble, 0.1);
+  XCTAssertTrue(message.defaultBool);
+  XCTAssertEqualObjects(@"hello", message.defaultString);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"],
+                        message.defaultBytes);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Bar, message.defaultNestedEnum);
+  XCTAssertEqual(ForeignEnum_ForeignBar, message.defaultForeignEnum);
+  XCTAssertEqual(ImportEnum_ImportBar, message.defaultImportEnum);
+
+  XCTAssertEqualObjects(@"abc", message.defaultStringPiece);
+  XCTAssertEqualObjects(@"123", message.defaultCord);
+}
+
+- (void)assertExtensionsClear:(TestAllExtensions *)message {
+  // hasBlah() should initially be NO for all optional fields.
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+  // Optional fields without defaults are set to zero or something like it.
+  XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+  XCTAssertEqual(0LL,[[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+  XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+  XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(0.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(0.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+  XCTAssertFalse([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+  XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringExtension]]);
+  XCTAssertEqualObjects(GPBEmptyNSData(), [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+  // Embedded messages should also be clear.
+
+  XCTAssertFalse([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+  XCTAssertFalse([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+  XCTAssertFalse([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+  XCTAssertFalse([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+  XCTAssertEqual(0, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+  XCTAssertEqual(0, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+  XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+  XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+  // Enums without defaults are set to the first value in the enum.
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+               [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignFoo,
+               [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportFoo,
+               [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+  XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+  XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+  // Repeated fields are empty.
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+  // hasBlah() should also be NO for all default fields.
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+  // Fields with defaults have their default values (duh).
+  XCTAssertEqual( 41, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+  XCTAssertEqual( 42LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+  XCTAssertEqual( 43U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual( 44ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(-45, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+  XCTAssertEqual( 46LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+  XCTAssertEqual( 47, [[message getExtension:[UnittestRoot defaultFixed32Extension]] intValue]);
+  XCTAssertEqual( 48ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual( 49, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+  XCTAssertEqual(-50LL, [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy( 51.5f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy( 52e3, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+  XCTAssertTrue([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+  XCTAssertEqualObjects(@"hello", [message getExtension:[UnittestRoot defaultStringExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Bar,
+               [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignBar,
+               [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportBar,
+               [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+  XCTAssertEqualObjects(@"abc", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+  XCTAssertEqualObjects(@"123", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)modifyRepeatedFields:(TestAllTypes *)message {
+  [message.repeatedInt32Array replaceValueAtIndex:1 withValue:501];
+  [message.repeatedInt64Array replaceValueAtIndex:1 withValue:502];
+  [message.repeatedUint32Array replaceValueAtIndex:1 withValue:503];
+  [message.repeatedUint64Array replaceValueAtIndex:1 withValue:504];
+  [message.repeatedSint32Array replaceValueAtIndex:1 withValue:505];
+  [message.repeatedSint64Array replaceValueAtIndex:1 withValue:506];
+  [message.repeatedFixed32Array replaceValueAtIndex:1 withValue:507];
+  [message.repeatedFixed64Array replaceValueAtIndex:1 withValue:508];
+  [message.repeatedSfixed32Array replaceValueAtIndex:1 withValue:509];
+  [message.repeatedSfixed64Array replaceValueAtIndex:1 withValue:510];
+  [message.repeatedFloatArray replaceValueAtIndex:1 withValue:511];
+  [message.repeatedDoubleArray replaceValueAtIndex:1 withValue:512];
+  [message.repeatedBoolArray replaceValueAtIndex:1 withValue:YES];
+  [message.repeatedStringArray replaceObjectAtIndex:1 withObject:@"515"];
+
+  NSData *data = [[NSData alloc] initWithUint32_gpbtu:516];
+  [message.repeatedBytesArray replaceObjectAtIndex:1 withObject:data];
+  [data release];
+
+  TestAllTypes_RepeatedGroup *testAll =
+      [[TestAllTypes_RepeatedGroup alloc] init];
+  [testAll setA:517];
+  [message.repeatedGroupArray replaceObjectAtIndex:1 withObject:testAll];
+  [testAll release];
+
+  TestAllTypes_NestedMessage *nestedMessage =
+      [[TestAllTypes_NestedMessage alloc] init];
+  [nestedMessage setBb:518];
+  [message.repeatedNestedMessageArray replaceObjectAtIndex:1
+                                                withObject:nestedMessage];
+  [nestedMessage release];
+
+  ForeignMessage *foreignMessage = [[ForeignMessage alloc] init];
+  [foreignMessage setC:519];
+  [message.repeatedForeignMessageArray replaceObjectAtIndex:1
+                                                 withObject:foreignMessage];
+  [foreignMessage release];
+
+  ImportMessage *importMessage = [[ImportMessage alloc] init];
+  [importMessage setD:520];
+  [message.repeatedImportMessageArray replaceObjectAtIndex:1
+                                                withObject:importMessage];
+  [importMessage release];
+
+  [message.repeatedNestedEnumArray replaceValueAtIndex:1 withValue:TestAllTypes_NestedEnum_Foo];
+  [message.repeatedForeignEnumArray replaceValueAtIndex:1 withValue:ForeignEnum_ForeignFoo];
+  [message.repeatedImportEnumArray replaceValueAtIndex:1 withValue:ImportEnum_ImportFoo];
+
+  [message.repeatedStringPieceArray replaceObjectAtIndex:1 withObject:@"524"];
+  [message.repeatedCordArray replaceObjectAtIndex:1 withObject:@"525"];
+}
+
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+                       repeatedCount:(uint32_t)count {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+
+  XCTAssertEqual(count, message.repeatedInt32Array.count);
+  XCTAssertEqual(count, message.repeatedInt64Array.count);
+  XCTAssertEqual(count, message.repeatedUint32Array.count);
+  XCTAssertEqual(count, message.repeatedUint64Array.count);
+  XCTAssertEqual(count, message.repeatedSint32Array.count);
+  XCTAssertEqual(count, message.repeatedSint64Array.count);
+  XCTAssertEqual(count, message.repeatedFixed32Array.count);
+  XCTAssertEqual(count, message.repeatedFixed64Array.count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+  XCTAssertEqual(count, message.repeatedFloatArray.count);
+  XCTAssertEqual(count, message.repeatedDoubleArray.count);
+  XCTAssertEqual(count, message.repeatedBoolArray.count);
+  XCTAssertEqual(count, message.repeatedStringArray.count);
+  XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray.count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+  XCTAssertEqual(count, message.repeatedCordArray.count);
+
+  XCTAssertEqual(count, message.repeatedInt32Array_Count);
+  XCTAssertEqual(count, message.repeatedInt64Array_Count);
+  XCTAssertEqual(count, message.repeatedUint32Array_Count);
+  XCTAssertEqual(count, message.repeatedUint64Array_Count);
+  XCTAssertEqual(count, message.repeatedSint32Array_Count);
+  XCTAssertEqual(count, message.repeatedSint64Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedFixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed32Array_Count);
+  XCTAssertEqual(count, message.repeatedSfixed64Array_Count);
+  XCTAssertEqual(count, message.repeatedFloatArray_Count);
+  XCTAssertEqual(count, message.repeatedDoubleArray_Count);
+  XCTAssertEqual(count, message.repeatedBoolArray_Count);
+  XCTAssertEqual(count, message.repeatedStringArray_Count);
+  XCTAssertEqual(count, message.repeatedBytesArray_Count);
+
+  XCTAssertEqual(count, message.repeatedGroupArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedImportMessageArray_Count);
+  XCTAssertEqual(count, message.repeatedNestedEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedForeignEnumArray_Count);
+  XCTAssertEqual(count, message.repeatedImportEnumArray_Count);
+
+  XCTAssertEqual(count, message.repeatedStringPieceArray_Count);
+  XCTAssertEqual(count, message.repeatedCordArray_Count);
+
+  XCTAssertEqual(201, [message.repeatedInt32Array valueAtIndex:0]);
+  XCTAssertEqual(202LL, [message.repeatedInt64Array valueAtIndex:0]);
+  XCTAssertEqual(203U, [message.repeatedUint32Array valueAtIndex:0]);
+  XCTAssertEqual(204ULL, [message.repeatedUint64Array valueAtIndex:0]);
+  XCTAssertEqual(205, [message.repeatedSint32Array valueAtIndex:0]);
+  XCTAssertEqual(206LL, [message.repeatedSint64Array valueAtIndex:0]);
+  XCTAssertEqual(207U, [message.repeatedFixed32Array valueAtIndex:0]);
+  XCTAssertEqual(208ULL, [message.repeatedFixed64Array valueAtIndex:0]);
+  XCTAssertEqual(209, [message.repeatedSfixed32Array valueAtIndex:0]);
+  XCTAssertEqual(210LL, [message.repeatedSfixed64Array valueAtIndex:0]);
+  XCTAssertEqualWithAccuracy(211.0f, [message.repeatedFloatArray valueAtIndex:0], 0.01);
+  XCTAssertEqualWithAccuracy(212.0, [message.repeatedDoubleArray valueAtIndex:0], 0.01);
+  XCTAssertFalse([message.repeatedBoolArray valueAtIndex:0]);
+  XCTAssertEqualObjects(@"215", message.repeatedStringArray[0]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216],
+                        message.repeatedBytesArray[0]);
+
+  XCTAssertEqual(217, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[0]).a);
+  XCTAssertEqual(218, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[0]).bb);
+  XCTAssertEqual(219, ((ForeignMessage*)message.repeatedForeignMessageArray[0]).c);
+  XCTAssertEqual(220, ((ImportMessage*)message.repeatedImportMessageArray[0]).d);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:0]);
+  XCTAssertEqual(ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:0]);
+  XCTAssertEqual(ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:0]);
+
+  XCTAssertEqualObjects(@"224", message.repeatedStringPieceArray[0]);
+  XCTAssertEqualObjects(@"225", message.repeatedCordArray[0]);
+
+  // Actually verify the second (modified) elements now.
+  XCTAssertEqual(501, [message.repeatedInt32Array valueAtIndex:1]);
+  XCTAssertEqual(502LL, [message.repeatedInt64Array valueAtIndex:1]);
+  XCTAssertEqual(503U, [message.repeatedUint32Array valueAtIndex:1]);
+  XCTAssertEqual(504ULL, [message.repeatedUint64Array valueAtIndex:1]);
+  XCTAssertEqual(505, [message.repeatedSint32Array valueAtIndex:1]);
+  XCTAssertEqual(506LL, [message.repeatedSint64Array valueAtIndex:1]);
+  XCTAssertEqual(507U, [message.repeatedFixed32Array valueAtIndex:1]);
+  XCTAssertEqual(508ULL, [message.repeatedFixed64Array valueAtIndex:1]);
+  XCTAssertEqual(509, [message.repeatedSfixed32Array valueAtIndex:1]);
+  XCTAssertEqual(510LL, [message.repeatedSfixed64Array valueAtIndex:1]);
+  XCTAssertEqualWithAccuracy(511.0f, [message.repeatedFloatArray valueAtIndex:1], 0.01);
+  XCTAssertEqualWithAccuracy(512.0, [message.repeatedDoubleArray valueAtIndex:1], 0.01);
+  XCTAssertTrue([message.repeatedBoolArray valueAtIndex:1]);
+  XCTAssertEqualObjects(@"515", message.repeatedStringArray[1]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516],
+                        message.repeatedBytesArray[1]);
+
+  XCTAssertEqual(517, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[1]).a);
+  XCTAssertEqual(518, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[1]).bb);
+  XCTAssertEqual(519, ((ForeignMessage*)message.repeatedForeignMessageArray[1]).c);
+  XCTAssertEqual(520, ((ImportMessage*)message.repeatedImportMessageArray[1]).d);
+
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [message.repeatedNestedEnumArray valueAtIndex:1]);
+  XCTAssertEqual(ForeignEnum_ForeignFoo, [message.repeatedForeignEnumArray valueAtIndex:1]);
+  XCTAssertEqual(ImportEnum_ImportFoo, [message.repeatedImportEnumArray valueAtIndex:1]);
+
+  XCTAssertEqualObjects(@"524", message.repeatedStringPieceArray[1]);
+  XCTAssertEqualObjects(@"525", message.repeatedCordArray[1]);
+}
+
+- (void)setPackedFields:(TestPackedTypes *)message
+          repeatedCount:(uint32_t)count {
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedInt32Array addValue:601 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedInt64Array addValue:602 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedUint32Array addValue:603 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedUint64Array addValue:604 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSint32Array addValue:605 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSint64Array addValue:606 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFixed32Array addValue:607 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFixed64Array addValue:608 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSfixed32Array addValue:609 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedSfixed64Array addValue:610 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedFloatArray addValue:611 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedDoubleArray addValue:612 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedBoolArray addValue:(i % 2) ? YES : NO];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.packedEnumArray
+        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+  }
+}
+
+- (void)setUnpackedFields:(TestUnpackedTypes *)message
+            repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedInt32Array addValue:601 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedInt64Array addValue:602 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedUint32Array addValue:603 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedUint64Array addValue:604 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSint32Array addValue:605 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSint64Array addValue:606 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFixed32Array addValue:607 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFixed64Array addValue:608 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSfixed32Array addValue:609 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedSfixed64Array addValue:610 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedFloatArray addValue:611 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedDoubleArray addValue:612 + i * 100];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedBoolArray addValue:(i % 2) ? YES : NO];
+  }
+  for (uint32_t i = 0; i < count; ++i) {
+    [message.unpackedEnumArray
+        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+  }
+}
+
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+                repeatedCount:(uint32_t)count {
+  XCTAssertEqual(count, message.packedInt32Array.count);
+  XCTAssertEqual(count, message.packedInt64Array.count);
+  XCTAssertEqual(count, message.packedUint32Array.count);
+  XCTAssertEqual(count, message.packedUint64Array.count);
+  XCTAssertEqual(count, message.packedSint32Array.count);
+  XCTAssertEqual(count, message.packedSint64Array.count);
+  XCTAssertEqual(count, message.packedFixed32Array.count);
+  XCTAssertEqual(count, message.packedFixed64Array.count);
+  XCTAssertEqual(count, message.packedSfixed32Array.count);
+  XCTAssertEqual(count, message.packedSfixed64Array.count);
+  XCTAssertEqual(count, message.packedFloatArray.count);
+  XCTAssertEqual(count, message.packedDoubleArray.count);
+  XCTAssertEqual(count, message.packedBoolArray.count);
+  XCTAssertEqual(count, message.packedEnumArray.count);
+  for (uint32_t i = 0; i < count; ++i) {
+    XCTAssertEqual((int)(601 + i * 100),
+                   [message.packedInt32Array valueAtIndex:i]);
+    XCTAssertEqual(602 + i * 100, [message.packedInt64Array valueAtIndex:i]);
+    XCTAssertEqual(603 + i * 100, [message.packedUint32Array valueAtIndex:i]);
+    XCTAssertEqual(604 + i * 100, [message.packedUint64Array valueAtIndex:i]);
+    XCTAssertEqual((int)(605 + i * 100),
+                   [message.packedSint32Array valueAtIndex:i]);
+    XCTAssertEqual(606 + i * 100, [message.packedSint64Array valueAtIndex:i]);
+    XCTAssertEqual(607 + i * 100, [message.packedFixed32Array valueAtIndex:i]);
+    XCTAssertEqual(608 + i * 100, [message.packedFixed64Array valueAtIndex:i]);
+    XCTAssertEqual((int)(609 + i * 100),
+                   [message.packedSfixed32Array valueAtIndex:i]);
+    XCTAssertEqual(610 + i * 100, [message.packedSfixed64Array valueAtIndex:i]);
+    XCTAssertEqualWithAccuracy(611 + i * 100,
+                               [message.packedFloatArray valueAtIndex:i], 0.01);
+    XCTAssertEqualWithAccuracy(
+        612 + i * 100, [message.packedDoubleArray valueAtIndex:i], 0.01);
+    XCTAssertEqual((i % 2) ? YES : NO,
+                   [message.packedBoolArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+                   [message.packedEnumArray valueAtIndex:i]);
+  }
+}
+
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+              repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setUnpackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; i++) {
+    [message addExtension:[UnittestRoot packedInt32Extension]
+                    value:@(601 + i * 100)];
+    [message addExtension:[UnittestRoot packedInt64Extension]
+                    value:@(602 + i * 100)];
+    [message addExtension:[UnittestRoot packedUint32Extension]
+                    value:@(603 + i * 100)];
+    [message addExtension:[UnittestRoot packedUint64Extension]
+                    value:@(604 + i * 100)];
+    [message addExtension:[UnittestRoot packedSint32Extension]
+                    value:@(605 + i * 100)];
+    [message addExtension:[UnittestRoot packedSint64Extension]
+                    value:@(606 + i * 100)];
+    [message addExtension:[UnittestRoot packedFixed32Extension]
+                    value:@(607 + i * 100)];
+    [message addExtension:[UnittestRoot packedFixed64Extension]
+                    value:@(608 + i * 100)];
+    [message addExtension:[UnittestRoot packedSfixed32Extension]
+                    value:@(609 + i * 100)];
+    [message addExtension:[UnittestRoot packedSfixed64Extension]
+                    value:@(610 + i * 100)];
+    [message addExtension:[UnittestRoot packedFloatExtension]
+                    value:@(611 + i * 100)];
+    [message addExtension:[UnittestRoot packedDoubleExtension]
+                    value:@(612 + i * 100)];
+    [message addExtension:[UnittestRoot packedBoolExtension]
+                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot packedEnumExtension]
+                    value:@((i % 2) ? ForeignEnum_ForeignBar
+                                    : ForeignEnum_ForeignBaz)];
+  }
+}
+
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
+                repeatedCount:(uint32_t)count {
+  // Must match -setPackedFields:repeatedCount:
+  // Must match -setUnpackedFields:repeatedCount:
+  // Must match -setPackedExtensions:repeatedCount:
+  for (uint32_t i = 0; i < count; i++) {
+    [message addExtension:[UnittestRoot unpackedInt32Extension]
+                    value:@(601 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedInt64Extension]
+                    value:@(602 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint32Extension]
+                    value:@(603 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint64Extension]
+                    value:@(604 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint32Extension]
+                    value:@(605 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint64Extension]
+                    value:@(606 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed32Extension]
+                    value:@(607 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed64Extension]
+                    value:@(608 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed32Extension]
+                    value:@(609 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed64Extension]
+                    value:@(610 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFloatExtension]
+                    value:@(611 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedDoubleExtension]
+                    value:@(612 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedBoolExtension]
+                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot unpackedEnumExtension]
+                    value:@((i % 2) ? ForeignEnum_ForeignBar
+                         : ForeignEnum_ForeignBaz)];
+  }
+}
+
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+                    repeatedCount:(uint32_t)count{
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed32Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed64Extension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFloatExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedDoubleExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedBoolExtension]] count]);
+  XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedEnumExtension]] count]);
+
+  for (uint32_t i = 0; i < count; ++i) {
+    id extension = [message getExtension:[UnittestRoot packedInt32Extension]];
+    XCTAssertEqual((int)(601 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot packedInt64Extension]];
+    XCTAssertEqual(602 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot packedUint32Extension]];
+    XCTAssertEqual(603 + i * 100, [extension[i] unsignedIntValue]);
+    extension = [message getExtension:[UnittestRoot packedUint64Extension]];
+    XCTAssertEqual(604 + i * 100, [extension[i] unsignedLongLongValue]);
+    extension = [message getExtension:[UnittestRoot packedSint32Extension]];
+    XCTAssertEqual((int)(605 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot packedSint64Extension]];
+    XCTAssertEqual(606 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot packedFixed32Extension]];
+    XCTAssertEqual(607 + i * 100, [extension[i] unsignedIntValue]);
+    extension = [message getExtension:[UnittestRoot packedFixed64Extension]];
+    XCTAssertEqual(608 + i * 100, [extension[i] unsignedLongLongValue]);
+    extension = [message getExtension:[UnittestRoot packedSfixed32Extension]];
+    XCTAssertEqual((int)(609 + i * 100), [extension[i] intValue]);
+    extension = [message getExtension:[UnittestRoot packedSfixed64Extension]];
+    XCTAssertEqual(610 + i * 100, [extension[i] longLongValue]);
+    extension = [message getExtension:[UnittestRoot packedFloatExtension]];
+    XCTAssertEqualWithAccuracy(611 + i * 100, [extension[i] floatValue], 0.01);
+    extension = [message getExtension:[UnittestRoot packedDoubleExtension]];
+    XCTAssertEqualWithAccuracy(612 + i * 100, [extension[i] doubleValue], 0.01);
+    extension = [message getExtension:[UnittestRoot packedBoolExtension]];
+    XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+    extension = [message getExtension:[UnittestRoot packedEnumExtension]];
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+                   [extension[i] intValue]);
+  }
+}
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message {
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @YES);
+  XCTAssertEqualObjects(@(message.optionalInt32), [message valueForKey:@"optionalInt32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @YES);
+  XCTAssertEqualObjects(@(message.optionalInt64), [message valueForKey:@"optionalInt64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @YES);
+  XCTAssertEqualObjects(@(message.optionalUint32), [message valueForKey:@"optionalUint32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @YES);
+  XCTAssertEqualObjects(@(message.optionalUint64), [message valueForKey:@"optionalUint64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @YES);
+  XCTAssertEqualObjects(@(message.optionalSint32), [message valueForKey:@"optionalSint32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @YES);
+  XCTAssertEqualObjects(@(message.optionalSint64), [message valueForKey:@"optionalSint64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @YES);
+  XCTAssertEqualObjects(@(message.optionalFixed32), [message valueForKey:@"optionalFixed32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @YES);
+  XCTAssertEqualObjects(@(message.optionalFixed64), [message valueForKey:@"optionalFixed64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @YES);
+  XCTAssertEqualObjects(@(message.optionalSfixed32), [message valueForKey:@"optionalSfixed32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @YES);
+  XCTAssertEqualObjects(@(message.optionalSfixed64), [message valueForKey:@"optionalSfixed64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @YES);
+  XCTAssertEqualObjects(@(message.optionalFloat), [message valueForKey:@"optionalFloat"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @YES);
+  XCTAssertEqualObjects(@(message.optionalDouble), [message valueForKey:@"optionalDouble"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @YES);
+  XCTAssertEqualObjects(@(message.optionalBool), [message valueForKey:@"optionalBool"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @YES);
+  XCTAssertEqualObjects(message.optionalString, [message valueForKey:@"optionalString"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @YES);
+  XCTAssertEqualObjects(message.optionalBytes, [message valueForKey:@"optionalBytes"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @YES);
+  XCTAssertNotNil(message.optionalGroup);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @YES);
+  XCTAssertEqualObjects(@(message.optionalGroup.a), [message valueForKeyPath:@"optionalGroup.a"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @YES);
+  XCTAssertNotNil(message.optionalNestedMessage);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.hasBb"], @YES);
+  XCTAssertEqualObjects(@(message.optionalNestedMessage.bb), [message valueForKeyPath:@"optionalNestedMessage.bb"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"], @YES);
+  XCTAssertNotNil(message.optionalForeignMessage);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.hasC"], @YES);
+  XCTAssertEqualObjects(@(message.optionalForeignMessage.c), [message valueForKeyPath:@"optionalForeignMessage.c"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @YES);
+  XCTAssertNotNil(message.optionalForeignMessage);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"], @YES);
+  XCTAssertEqualObjects(@(message.optionalImportMessage.d), [message valueForKeyPath:@"optionalImportMessage.d"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @YES);
+  XCTAssertEqualObjects(@(message.optionalNestedEnum), [message valueForKey:@"optionalNestedEnum"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @YES);
+  XCTAssertEqualObjects(@(message.optionalForeignEnum), [message valueForKey:@"optionalForeignEnum"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @YES);
+  XCTAssertEqualObjects(@(message.optionalImportEnum), [message valueForKey:@"optionalImportEnum"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @YES);
+  XCTAssertEqualObjects(message.optionalStringPiece, [message valueForKey:@"optionalStringPiece"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @YES);
+  XCTAssertEqualObjects(message.optionalCord, [message valueForKey:@"optionalCord"]);
+
+  // -----------------------------------------------------------------
+
+  // GPBArray interface for repeated
+
+  XCTAssertEqualObjects(message.repeatedInt32Array, [message valueForKey:@"repeatedInt32Array"]);
+  XCTAssertEqualObjects(message.repeatedInt64Array, [message valueForKey:@"repeatedInt64Array"]);
+  XCTAssertEqualObjects(message.repeatedUint32Array, [message valueForKey:@"repeatedUint32Array"]);
+  XCTAssertEqualObjects(message.repeatedUint64Array, [message valueForKey:@"repeatedUint64Array"]);
+  XCTAssertEqualObjects(message.repeatedSint32Array, [message valueForKey:@"repeatedSint32Array"]);
+  XCTAssertEqualObjects(message.repeatedSint64Array, [message valueForKey:@"repeatedSint64Array"]);
+  XCTAssertEqualObjects(message.repeatedFixed32Array, [message valueForKey:@"repeatedFixed32Array"]);
+  XCTAssertEqualObjects(message.repeatedFixed64Array, [message valueForKey:@"repeatedFixed64Array"]);
+  XCTAssertEqualObjects(message.repeatedSfixed32Array, [message valueForKey:@"repeatedSfixed32Array"]);
+  XCTAssertEqualObjects(message.repeatedSfixed64Array, [message valueForKey:@"repeatedSfixed64Array"]);
+  XCTAssertEqualObjects(message.repeatedFloatArray, [message valueForKey:@"repeatedFloatArray"]);
+  XCTAssertEqualObjects(message.repeatedDoubleArray, [message valueForKey:@"repeatedDoubleArray"]);
+  XCTAssertEqualObjects(message.repeatedBoolArray, [message valueForKey:@"repeatedBoolArray"]);
+  XCTAssertEqualObjects(message.repeatedStringArray, [message valueForKey:@"repeatedStringArray"]);
+  XCTAssertEqualObjects(message.repeatedBytesArray, [message valueForKey:@"repeatedBytesArray"]);
+
+  XCTAssertEqualObjects(message.repeatedGroupArray, [message valueForKey:@"repeatedGroupArray"]);
+  XCTAssertEqualObjects(message.repeatedNestedMessageArray, [message valueForKey:@"repeatedNestedMessageArray"]);
+  XCTAssertEqualObjects(message.repeatedForeignMessageArray, [message valueForKey:@"repeatedForeignMessageArray"]);
+  XCTAssertEqualObjects(message.repeatedImportMessageArray, [message valueForKey:@"repeatedImportMessageArray"]);
+
+  XCTAssertEqualObjects(message.repeatedNestedEnumArray, [message valueForKey:@"repeatedNestedEnumArray"]);
+  XCTAssertEqualObjects(message.repeatedForeignEnumArray, [message valueForKey:@"repeatedForeignEnumArray"]);
+  XCTAssertEqualObjects(message.repeatedImportEnumArray, [message valueForKey:@"repeatedImportEnumArray"]);
+
+  XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]);
+  XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]);
+
+  XCTAssertEqualObjects(@(message.repeatedInt32Array_Count), [message valueForKey:@"repeatedInt32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedInt64Array_Count), [message valueForKey:@"repeatedInt64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint32Array_Count), [message valueForKey:@"repeatedUint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint64Array_Count), [message valueForKey:@"repeatedUint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint32Array_Count), [message valueForKey:@"repeatedSint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint64Array_Count), [message valueForKey:@"repeatedSint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count), [message valueForKey:@"repeatedFixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count), [message valueForKey:@"repeatedFixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count), [message valueForKey:@"repeatedSfixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count), [message valueForKey:@"repeatedSfixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFloatArray_Count), [message valueForKey:@"repeatedFloatArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count), [message valueForKey:@"repeatedDoubleArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBoolArray_Count), [message valueForKey:@"repeatedBoolArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedStringArray_Count), [message valueForKey:@"repeatedStringArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBytesArray_Count), [message valueForKey:@"repeatedBytesArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedGroupArray_Count), [message valueForKey:@"repeatedGroupArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count), [message valueForKey:@"repeatedNestedMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count), [message valueForKey:@"repeatedForeignMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count), [message valueForKey:@"repeatedImportMessageArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count), [message valueForKey:@"repeatedNestedEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count), [message valueForKey:@"repeatedForeignEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count), [message valueForKey:@"repeatedImportEnumArray_Count"]);
+
+  XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count), [message valueForKey:@"repeatedStringPieceArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedCordArray_Count), [message valueForKey:@"repeatedCordArray_Count"]);
+
+  // -----------------------------------------------------------------
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES);
+  XCTAssertEqualObjects(@(message.defaultInt32), [message valueForKey:@"defaultInt32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @YES);
+  XCTAssertEqualObjects(@(message.defaultInt64), [message valueForKey:@"defaultInt64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @YES);
+  XCTAssertEqualObjects(@(message.defaultUint32), [message valueForKey:@"defaultUint32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @YES);
+  XCTAssertEqualObjects(@(message.defaultUint64), [message valueForKey:@"defaultUint64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @YES);
+  XCTAssertEqualObjects(@(message.defaultSint32), [message valueForKey:@"defaultSint32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @YES);
+  XCTAssertEqualObjects(@(message.defaultSint64), [message valueForKey:@"defaultSint64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @YES);
+  XCTAssertEqualObjects(@(message.defaultFixed32), [message valueForKey:@"defaultFixed32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @YES);
+  XCTAssertEqualObjects(@(message.defaultFixed64), [message valueForKey:@"defaultFixed64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @YES);
+  XCTAssertEqualObjects(@(message.defaultSfixed32), [message valueForKey:@"defaultSfixed32"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @YES);
+  XCTAssertEqualObjects(@(message.defaultSfixed64), [message valueForKey:@"defaultSfixed64"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @YES);
+  XCTAssertEqualObjects(@(message.defaultFloat), [message valueForKey:@"defaultFloat"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @YES);
+  XCTAssertEqualObjects(@(message.defaultDouble), [message valueForKey:@"defaultDouble"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @YES);
+  XCTAssertEqualObjects(@(message.defaultBool), [message valueForKey:@"defaultBool"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @YES);
+  XCTAssertEqualObjects(message.defaultString, [message valueForKey:@"defaultString"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @YES);
+  XCTAssertEqualObjects(message.defaultBytes, [message valueForKey:@"defaultBytes"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @YES);
+  XCTAssertEqualObjects(@(message.defaultNestedEnum), [message valueForKey:@"defaultNestedEnum"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @YES);
+  XCTAssertEqualObjects(@(message.defaultForeignEnum), [message valueForKey:@"defaultForeignEnum"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @YES);
+  XCTAssertEqualObjects(@(message.defaultImportEnum), [message valueForKey:@"defaultImportEnum"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @YES);
+  XCTAssertEqualObjects(message.defaultStringPiece, [message valueForKey:@"defaultStringPiece"]);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @YES);
+  XCTAssertEqualObjects(message.defaultCord, [message valueForKey:@"defaultCord"]);
+}
+
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+             repeatedCount:(uint32_t)count {
+  [message setValue:@101 forKey:@"optionalInt32"];
+  [message setValue:@102 forKey:@"optionalInt64"];
+  [message setValue:@103 forKey:@"optionalUint32"];
+  [message setValue:@104 forKey:@"optionalUint64"];
+  [message setValue:@105 forKey:@"optionalSint32"];
+  [message setValue:@106 forKey:@"optionalSint64"];
+  [message setValue:@107 forKey:@"optionalFixed32"];
+  [message setValue:@108 forKey:@"optionalFixed64"];
+  [message setValue:@109 forKey:@"optionalSfixed32"];
+  [message setValue:@110 forKey:@"optionalSfixed64"];
+  [message setValue:@111 forKey:@"optionalFloat"];
+  [message setValue:@112 forKey:@"optionalDouble"];
+  [message setValue:@YES forKey:@"optionalBool"];
+  [message setValue:@"115" forKey:@"optionalString"];
+  [message setValue:[NSData gpbtu_dataWithEmbeddedNulls]
+             forKey:@"optionalBytes"];
+
+  TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+  [allTypes setValue:@117 forKey:@"a"];
+  [message setValue:allTypes forKey:@"optionalGroup"];
+  TestAllTypes_NestedMessage *nestedMessage =
+      [TestAllTypes_NestedMessage message];
+  [nestedMessage setValue:@118 forKey:@"bb"];
+  [message setValue:nestedMessage forKey:@"optionalNestedMessage"];
+  ForeignMessage *foreignMessage = [ForeignMessage message];
+  [foreignMessage setValue:@119 forKey:@"c"];
+  [message setValue:foreignMessage forKey:@"optionalForeignMessage"];
+  ImportMessage *importMessage = [ImportMessage message];
+  [importMessage setValue:@120 forKey:@"d"];
+  [message setValue:importMessage forKey:@"optionalImportMessage"];
+
+  [message setValue:@(TestAllTypes_NestedEnum_Baz)
+             forKey:@"optionalNestedEnum"];
+  [message setValue:@(ForeignEnum_ForeignBaz) forKey:@"optionalForeignEnum"];
+  [message setValue:@(ImportEnum_ImportBaz) forKey:@"optionalImportEnum"];
+
+  [message setValue:@"124" forKey:@"optionalStringPiece"];
+  [message setValue:@"125" forKey:@"optionalCord"];
+
+  // -----------------------------------------------------------------
+
+  {
+    GPBInt32Array *scratch = [GPBInt32Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:201 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedInt32Array"];
+  }
+  {
+    GPBInt64Array *scratch = [GPBInt64Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:202 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedInt64Array"];
+  }
+  {
+    GPBUInt32Array *scratch = [GPBUInt32Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:203 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedUint32Array"];
+  }
+  {
+    GPBUInt64Array *scratch = [GPBUInt64Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:204 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedUint64Array"];
+  }
+  {
+    GPBInt32Array *scratch = [GPBInt32Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:205 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedSint32Array"];
+  }
+  {
+    GPBInt64Array *scratch = [GPBInt64Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:206 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedSint64Array"];
+  }
+  {
+    GPBUInt32Array *scratch = [GPBUInt32Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:207 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedFixed32Array"];
+  }
+  {
+    GPBUInt64Array *scratch = [GPBUInt64Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:208 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedFixed64Array"];
+  }
+  {
+    GPBInt32Array *scratch = [GPBInt32Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:209 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedSfixed32Array"];
+  }
+  {
+    GPBInt64Array *scratch = [GPBInt64Array array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:210 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedSfixed64Array"];
+  }
+  {
+    GPBFloatArray *scratch = [GPBFloatArray array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:211 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedFloatArray"];
+  }
+  {
+    GPBDoubleArray *scratch = [GPBDoubleArray array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:212 + i * 100];
+    }
+    [message setValue:scratch forKey:@"repeatedDoubleArray"];
+  }
+  {
+    GPBBoolArray *scratch = [GPBBoolArray array];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:(i % 2) ? YES : NO];
+    }
+    [message setValue:scratch forKey:@"repeatedBoolArray"];
+  }
+
+  NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+    [array addObject:string];
+    [string release];
+  }
+  [message setValue:array forKey:@"repeatedStringArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+    [array addObject:data];
+    [data release];
+  }
+  [message setValue:array forKey:@"repeatedBytesArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    TestAllTypes_RepeatedGroup *testAll =
+        [[TestAllTypes_RepeatedGroup alloc] init];
+    [testAll setA:217 + i * 100];
+    [array addObject:testAll];
+    [testAll release];
+  }
+  [message setValue:array forKey:@"repeatedGroupArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+    [nestedMessage setBb:218 + i * 100];
+    [array addObject:nestedMessage];
+    [nestedMessage release];
+  }
+  [message setValue:array forKey:@"repeatedNestedMessageArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    foreignMessage = [[ForeignMessage alloc] init];
+    [foreignMessage setC:219 + i * 100];
+    [array addObject:foreignMessage];
+    [foreignMessage release];
+  }
+  [message setValue:array forKey:@"repeatedForeignMessageArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    importMessage = [[ImportMessage alloc] init];
+    [importMessage setD:220 + i * 100];
+    [array addObject:importMessage];
+    [importMessage release];
+  }
+  [message setValue:array forKey:@"repeatedImportMessageArray"];
+  [array release];
+
+  {
+    GPBEnumArray *scratch = [GPBEnumArray
+        arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar
+                                : TestAllTypes_NestedEnum_Baz];
+    }
+    [message setValue:scratch forKey:@"repeatedNestedEnumArray"];
+  }
+  {
+    GPBEnumArray *scratch =
+        [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch
+          addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+    }
+    [message setValue:scratch forKey:@"repeatedForeignEnumArray"];
+  }
+  {
+    GPBEnumArray *scratch =
+        [GPBEnumArray arrayWithValidationFunction:ImportEnum_IsValidValue];
+    for (uint32_t i = 0; i < count; ++i) {
+      [scratch addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+    }
+    [message setValue:scratch forKey:@"repeatedImportEnumArray"];
+  }
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+    [array addObject:string];
+    [string release];
+  }
+  [message setValue:array forKey:@"repeatedStringPieceArray"];
+  [array release];
+
+  array = [[NSMutableArray alloc] initWithCapacity:count];
+  for (uint32_t i = 0; i < count; ++i) {
+    NSString *string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+    [array addObject:string];
+    [string release];
+  }
+  [message setValue:array forKey:@"repeatedCordArray"];
+  [array release];
+
+  // -----------------------------------------------------------------
+
+  [message setValue:@401 forKey:@"defaultInt32"];
+  [message setValue:@402 forKey:@"defaultInt64"];
+  [message setValue:@403 forKey:@"defaultUint32"];
+  [message setValue:@404 forKey:@"defaultUint64"];
+  [message setValue:@405 forKey:@"defaultSint32"];
+  [message setValue:@406 forKey:@"defaultSint64"];
+  [message setValue:@407 forKey:@"defaultFixed32"];
+  [message setValue:@408 forKey:@"defaultFixed64"];
+  [message setValue:@409 forKey:@"defaultSfixed32"];
+  [message setValue:@410 forKey:@"defaultSfixed64"];
+  [message setValue:@411 forKey:@"defaultFloat"];
+  [message setValue:@412 forKey:@"defaultDouble"];
+  [message setValue:@NO forKey:@"defaultBool"];
+  [message setValue:@"415" forKey:@"defaultString"];
+  [message setValue:[NSData gpbtu_dataWithUint32:416] forKey:@"defaultBytes"];
+
+  [message setValue:@(TestAllTypes_NestedEnum_Foo) forKey:@"defaultNestedEnum"];
+  [message setValue:@(ForeignEnum_ForeignFoo) forKey:@"defaultForeignEnum"];
+  [message setValue:@(ImportEnum_ImportFoo) forKey:@"defaultImportEnum"];
+
+  [message setValue:@"424" forKey:@"defaultStringPiece"];
+  [message setValue:@"425" forKey:@"defaultCord"];
+}
+
+- (void)assertClearKVC:(TestAllTypes *)message {
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @NO);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"],
+                        @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @NO);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @NO);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @NO);
+
+  // Optional fields without defaults are set to zero or something like it.
+  XCTAssertEqualObjects([message valueForKey:@"optionalInt32"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalInt64"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalUint32"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalUint64"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalSint32"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalSint64"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalFixed32"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalFixed64"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalSfixed32"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalSfixed64"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalFloat"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalDouble"], @0);
+  XCTAssertEqualObjects([message valueForKey:@"optionalBool"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"optionalString"], @"");
+  XCTAssertEqualObjects([message valueForKey:@"optionalBytes"],
+                        GPBEmptyNSData());
+
+  // Embedded messages should also be exist, but be clear.
+  XCTAssertNotNil([message valueForKeyPath:@"optionalGroup"]);
+  XCTAssertNotNil([message valueForKeyPath:@"optionalNestedMessage"]);
+  XCTAssertNotNil([message valueForKeyPath:@"optionalForeignMessage"]);
+  XCTAssertNotNil([message valueForKeyPath:@"optionalImportMessage"]);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @NO);
+  XCTAssertEqualObjects(
+      [message valueForKeyPath:@"optionalNestedMessage.hasBb"], @NO);
+  XCTAssertEqualObjects(
+      [message valueForKeyPath:@"optionalForeignMessage.hasC"], @NO);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"],
+                        @NO);
+
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.a"], @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.bb"],
+                        @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.c"],
+                        @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.d"],
+                        @0);
+
+  // Enums without defaults are set to the first value in the enum.
+  XCTAssertEqualObjects([message valueForKey:@"optionalNestedEnum"],
+                        @(TestAllTypes_NestedEnum_Foo));
+  XCTAssertEqualObjects([message valueForKey:@"optionalForeignEnum"],
+                        @(ForeignEnum_ForeignFoo));
+  XCTAssertEqualObjects([message valueForKey:@"optionalImportEnum"],
+                        @(ImportEnum_ImportFoo));
+
+  XCTAssertEqualObjects([message valueForKey:@"optionalStringPiece"], @"");
+  XCTAssertEqualObjects([message valueForKey:@"optionalCord"], @"");
+
+  // NSArray interface for repeated doesn't have has*, nil means no value.
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @NO);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @NO);
+
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @NO);
+
+  // Fields with defaults have their default values (duh).
+  XCTAssertEqualObjects([message valueForKey:@"defaultInt32"], @41);
+  XCTAssertEqualObjects([message valueForKey:@"defaultInt64"], @42);
+  XCTAssertEqualObjects([message valueForKey:@"defaultUint32"], @43);
+  XCTAssertEqualObjects([message valueForKey:@"defaultUint64"], @44);
+  XCTAssertEqualObjects([message valueForKey:@"defaultSint32"], @-45);
+  XCTAssertEqualObjects([message valueForKey:@"defaultSint64"], @46);
+  XCTAssertEqualObjects([message valueForKey:@"defaultFixed32"], @47);
+  XCTAssertEqualObjects([message valueForKey:@"defaultFixed64"], @48);
+  XCTAssertEqualObjects([message valueForKey:@"defaultSfixed32"], @49);
+  XCTAssertEqualObjects([message valueForKey:@"defaultSfixed64"], @-50);
+  XCTAssertEqualObjects([message valueForKey:@"defaultFloat"], @51.5);
+  XCTAssertEqualObjects([message valueForKey:@"defaultDouble"], @52e3);
+  XCTAssertEqualObjects([message valueForKey:@"defaultBool"], @YES);
+  XCTAssertEqualObjects([message valueForKey:@"defaultString"], @"hello");
+  XCTAssertEqualObjects([message valueForKey:@"defaultBytes"],
+                        [NSData gpbtu_dataWithCString:"world"]);
+
+  XCTAssertEqualObjects([message valueForKey:@"defaultNestedEnum"],
+                        @(TestAllTypes_NestedEnum_Bar));
+  XCTAssertEqualObjects([message valueForKey:@"defaultForeignEnum"],
+                        @(ForeignEnum_ForeignBar));
+  XCTAssertEqualObjects([message valueForKey:@"defaultImportEnum"],
+                        @(ImportEnum_ImportBar));
+
+  XCTAssertEqualObjects([message valueForKey:@"defaultStringPiece"], @"abc");
+  XCTAssertEqualObjects([message valueForKey:@"defaultCord"], @"123");
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBUnittestProtos.m b/src/third_party/protobuf-3/objectivec/Tests/GPBUnittestProtos.m
new file mode 100644
index 0000000..d19beee
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBUnittestProtos.m
@@ -0,0 +1,64 @@
+// 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.
+
+// Collects all the compiled protos into one file and compiles them to make sure
+// the compiler is generating valid code.
+
+// The unittest_custom_options.proto extends the messages in descriptor.proto
+// so we build it in to test extending in general. The library doesn't provide
+// a descriptor as it doesn't use the classes/enums.
+#import "google/protobuf/Descriptor.pbobjc.m"
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.m"
+#import "google/protobuf/MapUnittest.pbobjc.m"
+#import "google/protobuf/Unittest.pbobjc.m"
+#import "google/protobuf/UnittestArena.pbobjc.m"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.m"
+#import "google/protobuf/UnittestCycle.pbobjc.m"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.m"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestEmpty.pbobjc.m"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m"
+#import "google/protobuf/UnittestImport.pbobjc.m"
+#import "google/protobuf/UnittestImportLite.pbobjc.m"
+#import "google/protobuf/UnittestImportPublic.pbobjc.m"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
+#import "google/protobuf/UnittestLite.pbobjc.m"
+#import "google/protobuf/UnittestMset.pbobjc.m"
+#import "google/protobuf/UnittestMsetWireFormat.pbobjc.m"
+#import "google/protobuf/UnittestNoArena.pbobjc.m"
+#import "google/protobuf/UnittestNoArenaImport.pbobjc.m"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
+#import "google/protobuf/UnittestObjc.pbobjc.m"
+#import "google/protobuf/UnittestObjcStartup.pbobjc.m"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.m"
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBUnknownFieldSetTest.m b/src/third_party/protobuf-3/objectivec/Tests/GPBUnknownFieldSetTest.m
new file mode 100644
index 0000000..01217ca
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -0,0 +1,259 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBUnknownField_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
+- (void)getTags:(int32_t*)tags;
+@end
+
+@interface UnknownFieldSetTest : GPBTestCase {
+ @private
+  TestAllTypes* allFields_;
+  NSData* allFieldsData_;
+
+  // An empty message that has been parsed from allFieldsData.  So, it has
+  // unknown fields of every type.
+  TestEmptyMessage* emptyMessage_;
+  GPBUnknownFieldSet* unknownFields_;
+}
+
+@end
+
+@implementation UnknownFieldSetTest
+
+- (void)setUp {
+  allFields_ = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+  allFieldsData_ = [allFields_ data];
+  emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_ error:NULL];
+  unknownFields_ = emptyMessage_.unknownFields;
+}
+
+- (GPBUnknownField *)getField:(int32_t)number {
+  return [unknownFields_ getField:number];
+}
+
+// Constructs a protocol buffer which contains fields with all the same
+// numbers as allFieldsData except that each field is some other wire
+// type.
+- (NSData*)getBizarroData {
+  GPBUnknownFieldSet* bizarroFields =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  NSUInteger count = [unknownFields_ countOfFields];
+  int32_t tags[count];
+  [unknownFields_ getTags:tags];
+  for (NSUInteger i = 0; i < count; ++i) {
+    int32_t tag = tags[i];
+    GPBUnknownField* field = [unknownFields_ getField:tag];
+    if (field.varintList.count == 0) {
+      // Original field is not a varint, so use a varint.
+      GPBUnknownField* varintField =
+          [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
+      [varintField addVarint:1];
+      [bizarroFields addField:varintField];
+    } else {
+      // Original field *is* a varint, so use something else.
+      GPBUnknownField* fixed32Field =
+          [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
+      [fixed32Field addFixed32:1];
+      [bizarroFields addField:fixed32Field];
+    }
+  }
+
+  return [bizarroFields data];
+}
+
+- (void)testSerialize {
+  // Check that serializing the UnknownFieldSet produces the original data
+  // again.
+  NSData* data = [emptyMessage_ data];
+  XCTAssertEqualObjects(allFieldsData_, data);
+}
+
+- (void)testCopyFrom {
+  TestEmptyMessage* message = [TestEmptyMessage message];
+  [message mergeFrom:emptyMessage_];
+
+  XCTAssertEqualObjects(emptyMessage_.data, message.data);
+}
+
+- (void)testMergeFrom {
+  GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
+  [field addVarint:2];
+  [set1 addField:field];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
+  [field addVarint:4];
+  [set1 addField:field];
+
+  GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
+  [field addVarint:1];
+  [set2 addField:field];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
+  [field addVarint:3];
+  [set2 addField:field];
+
+  GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
+  [field addVarint:1];
+  [set3 addField:field];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
+  [field addVarint:4];
+  [set3 addField:field];
+
+  GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
+  [field addVarint:2];
+  [set4 addField:field];
+  field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
+  [field addVarint:3];
+  [set4 addField:field];
+
+  TestEmptyMessage* source1 = [TestEmptyMessage message];
+  [source1 setUnknownFields:set1];
+  TestEmptyMessage* source2 = [TestEmptyMessage message];
+  [source2 setUnknownFields:set2];
+  TestEmptyMessage* source3 = [TestEmptyMessage message];
+  [source3 setUnknownFields:set3];
+  TestEmptyMessage* source4 = [TestEmptyMessage message];
+  [source4 setUnknownFields:set4];
+
+  TestEmptyMessage* destination1 = [TestEmptyMessage message];
+  [destination1 mergeFrom:source1];
+  [destination1 mergeFrom:source2];
+
+  TestEmptyMessage* destination2 = [TestEmptyMessage message];
+  [destination2 mergeFrom:source3];
+  [destination2 mergeFrom:source4];
+
+  XCTAssertEqualObjects(destination1.data, destination2.data);
+}
+
+- (void)testClearMessage {
+  TestEmptyMessage *message = [TestEmptyMessage message];
+  [message mergeFrom:emptyMessage_];
+  [message clear];
+  XCTAssertEqual(message.serializedSize, (size_t)0);
+}
+
+- (void)testParseKnownAndUnknown {
+  // Test mixing known and unknown fields when parsing.
+  GPBUnknownFieldSet *fields = [[unknownFields_ copy] autorelease];
+  GPBUnknownField *field =
+    [[[GPBUnknownField alloc] initWithNumber:123456] autorelease];
+  [field addVarint:654321];
+  [fields addField:field];
+
+  NSData* data = fields.data;
+  TestAllTypes* destination = [TestAllTypes parseFromData:data error:NULL];
+
+  [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount];
+  XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1);
+
+  GPBUnknownField* field2 = [destination.unknownFields getField:123456];
+  XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+  XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testWrongTypeTreatedAsUnknown {
+  // Test that fields of the wrong wire type are treated like unknown fields
+  // when parsing.
+
+  NSData* bizarroData = [self getBizarroData];
+  TestAllTypes* allTypesMessage =
+      [TestAllTypes parseFromData:bizarroData error:NULL];
+  TestEmptyMessage* emptyMessage =
+      [TestEmptyMessage parseFromData:bizarroData error:NULL];
+
+  // All fields should have been interpreted as unknown, so the debug strings
+  // should be the same.
+  XCTAssertEqualObjects(emptyMessage.data, allTypesMessage.data);
+}
+
+- (void)testUnknownExtensions {
+  // Make sure fields are properly parsed to the UnknownFieldSet even when
+  // they are declared as extension numbers.
+
+  TestEmptyMessageWithExtensions* message =
+      [TestEmptyMessageWithExtensions parseFromData:allFieldsData_ error:NULL];
+
+  XCTAssertEqual(unknownFields_.countOfFields,
+                 message.unknownFields.countOfFields);
+  XCTAssertEqualObjects(allFieldsData_, message.data);
+}
+
+- (void)testWrongExtensionTypeTreatedAsUnknown {
+  // Test that fields of the wrong wire type are treated like unknown fields
+  // when parsing extensions.
+
+  NSData* bizarroData = [self getBizarroData];
+  TestAllExtensions* allExtensionsMessage =
+      [TestAllExtensions parseFromData:bizarroData error:NULL];
+  TestEmptyMessage* emptyMessage =
+      [TestEmptyMessage parseFromData:bizarroData error:NULL];
+
+  // All fields should have been interpreted as unknown, so the debug strings
+  // should be the same.
+  XCTAssertEqualObjects(emptyMessage.data, allExtensionsMessage.data);
+}
+
+- (void)testLargeVarint {
+  GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+  GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
+  [field addVarint:0x7FFFFFFFFFFFFFFFL];
+  [fields addField:field];
+
+  NSData* data = [fields data];
+
+  GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  [parsed mergeFromData:data];
+  GPBUnknownField* field2 = [parsed getField:1];
+  XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+  XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testMergingFields {
+  GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease];
+  [field1 addVarint:1];
+  [field1 addFixed32:2];
+  [field1 addFixed64:3];
+  [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]];
+  [field1 addGroup:[[unknownFields_ copy] autorelease]];
+  GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
+  [field2 mergeFromField:field1];
+  XCTAssertEqualObjects(field1, field2);
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBUtilitiesTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBUtilitiesTests.m
new file mode 100644
index 0000000..ba1fc27
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBUtilitiesTests.m
@@ -0,0 +1,173 @@
+// 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.
+
+#import <XCTest/XCTest.h>
+
+#import "GPBUtilities_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBTestUtilities.h"
+
+#import "GPBDescriptor.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+@interface UtilitiesTests : GPBTestCase
+@end
+
+@implementation UtilitiesTests
+
+- (void)testRightShiftFunctions {
+  XCTAssertEqual((1UL << 31) >> 31, 1UL);
+  XCTAssertEqual((1 << 31) >> 31, -1);
+  XCTAssertEqual((1ULL << 63) >> 63, 1ULL);
+  XCTAssertEqual((1LL << 63) >> 63, -1LL);
+
+  XCTAssertEqual(GPBLogicalRightShift32((1 << 31), 31), 1);
+  XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL);
+}
+
+- (void)testGPBDecodeTextFormatName {
+  uint8_t decodeData[] = {
+    0x6,
+    // An inlined string (first to make sure the leading null is handled
+    // correctly, and with a key of zero to check that).
+    0x0, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+    // All as is (00 op)
+    0x1, 0x0A, 0x0,
+    // Underscore, upper + 9 (10 op)
+    0x3, 0xCA, 0x0,
+    //  Upper + 3 (10 op), underscore, upper + 5 (10 op)
+    0x2, 0x44, 0xC6, 0x0,
+    // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+    // underscore, lower + 0 (01 op)
+    0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+    // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+    //   underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+    //   underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op),
+    //   underscore, as is + 3 (00 op)
+    0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+  };
+  NSString *inputStr = @"abcdefghIJ";
+
+  // Empty inputs
+
+  XCTAssertNil(GPBDecodeTextFormatName(nil, 1, NULL));
+  XCTAssertNil(GPBDecodeTextFormatName(decodeData, 1, NULL));
+  XCTAssertNil(GPBDecodeTextFormatName(nil, 1, inputStr));
+
+  // Keys not found.
+
+  XCTAssertNil(GPBDecodeTextFormatName(decodeData, 5, inputStr));
+  XCTAssertNil(GPBDecodeTextFormatName(decodeData, -1, inputStr));
+
+  // Some name decodes.
+
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1, inputStr), @"abcdefghIJ");
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 2, inputStr), @"Abcd_EfghIJ");
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 3, inputStr), @"_AbcdefghIJ");
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 4, inputStr), @"ABCD__EfghI_j");
+
+  // An inlined string (and key of zero).
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ");
+
+  // Long name so multiple decode ops are needed.
+  inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+  XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr),
+                        @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+}
+
+- (void)testTextFormat {
+  TestAllTypes *message = [TestAllTypes message];
+
+  // Not kGPBDefaultRepeatCount because we are comparing to golden master file
+  // which was generated with 2.
+  [self setAllFields:message repeatedCount:2];
+
+  NSString *result = GPBTextFormatForMessage(message, nil);
+
+  NSString *fileName = @"text_format_unittest_data.txt";
+  NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+  NSData *expectedData =
+      [self getDataFileNamed:fileName dataToWrite:resultData];
+  NSString *expected = [[NSString alloc] initWithData:expectedData
+                                             encoding:NSUTF8StringEncoding];
+  XCTAssertEqualObjects(expected, result);
+  [expected release];
+}
+
+- (void)testTextFormatExtra {
+  // -testTextFormat uses all protos with fields that don't require special
+  // handing for figuring out the names.  The ObjC proto has a bunch of oddball
+  // field and enum names that require the decode info to get right, so this
+  // confirms they generated and decoded correctly.
+
+  self_Class *message = [self_Class message];
+  message.cmd = YES;
+  message.isProxy_p = YES;
+  message.subEnum = self_autorelease_RetainCount;
+  message.new_p.copy_p = @"foo";
+
+  NSString *expected = @"_cmd: true\n"
+                       @"isProxy: true\n"
+                       @"SubEnum: retainCount\n"
+                       @"New {\n"
+                       @"  copy: \"foo\"\n"
+                       @"}\n";
+  NSString *result = GPBTextFormatForMessage(message, nil);
+  XCTAssertEqualObjects(expected, result);
+}
+
+- (void)testTextFormatMaps {
+  TestMap *message = [TestMap message];
+
+  // Map iteration order doesn't have to be stable, so use only one entry.
+  [self setAllMapFields:message numEntries:1];
+
+  NSString *result = GPBTextFormatForMessage(message, nil);
+
+  NSString *fileName = @"text_format_map_unittest_data.txt";
+  NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+  NSData *expectedData =
+      [self getDataFileNamed:fileName dataToWrite:resultData];
+  NSString *expected = [[NSString alloc] initWithData:expectedData
+                                             encoding:NSUTF8StringEncoding];
+  XCTAssertEqualObjects(expected, result);
+  [expected release];
+}
+
+// TODO(thomasvl): add test with extensions once those format with correct names.
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBWellKnownTypesTest.m b/src/third_party/protobuf-3/objectivec/Tests/GPBWellKnownTypesTest.m
new file mode 100644
index 0000000..78f4e63
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBWellKnownTypesTest.m
@@ -0,0 +1,102 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#import "GPBWellKnownTypes.h"
+
+#import <XCTest/XCTest.h>
+
+// A basically random interval into the future for testing with.
+static const NSTimeInterval kFutureOffsetInterval = 15000;
+
+// Nanosecond time accuracy
+static const NSTimeInterval kTimeAccuracy = 1e-9;
+
+@interface WellKnownTypesTest : XCTestCase
+@end
+
+@implementation WellKnownTypesTest
+
+- (void)testTimeStamp {
+  // Test Creation.
+  NSDate *date = [NSDate date];
+  GPBTimestamp *timeStamp = [[GPBTimestamp alloc] initWithDate:date];
+  NSDate *timeStampDate = timeStamp.date;
+
+  // Comparing timeIntervals instead of directly comparing dates because date
+  // equality requires the time intervals to be exactly the same, and the
+  // timeintervals go through a bit of floating point error as they are
+  // converted back and forth from the internal representation.
+  XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+                             timeStampDate.timeIntervalSince1970,
+                             kTimeAccuracy);
+
+  NSTimeInterval time = [date timeIntervalSince1970];
+  GPBTimestamp *timeStamp2 =
+      [[GPBTimestamp alloc] initWithTimeIntervalSince1970:time];
+  NSTimeInterval durationTime = timeStamp2.timeIntervalSince1970;
+  XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+  [timeStamp release];
+
+  // Test Mutation.
+  date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+  timeStamp2.date = date;
+  timeStampDate = timeStamp2.date;
+  XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+                             timeStampDate.timeIntervalSince1970,
+                             kTimeAccuracy);
+
+  time = date.timeIntervalSince1970;
+  timeStamp2.timeIntervalSince1970 = time;
+  durationTime = timeStamp2.timeIntervalSince1970;
+  XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+  [timeStamp2 release];
+}
+
+- (void)testDuration {
+  // Test Creation.
+  NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
+  GPBDuration *duration =
+      [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+  NSTimeInterval durationTime = duration.timeIntervalSince1970;
+  XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+  [duration release];
+
+  // Test Mutation.
+  GPBDuration *duration2 =
+      [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+  time = date.timeIntervalSince1970;
+  duration2.timeIntervalSince1970 = time;
+  durationTime = duration2.timeIntervalSince1970;
+  XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+  [duration2 release];
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/GPBWireFormatTests.m b/src/third_party/protobuf-3/objectivec/Tests/GPBWireFormatTests.m
new file mode 100644
index 0000000..2a406f1
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/GPBWireFormatTests.m
@@ -0,0 +1,252 @@
+// 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.
+
+#import "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownField_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+#import "google/protobuf/UnittestMsetWireFormat.pbobjc.h"
+
+@interface WireFormatTests : GPBTestCase
+@end
+
+@implementation WireFormatTests
+
+- (void)testSerialization {
+  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+  NSData* rawBytes = message.data;
+  XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+  TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL];
+
+  [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializationPacked {
+  TestPackedTypes* message =
+      [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+
+  NSData* rawBytes = message.data;
+  XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+  TestPackedTypes* message2 =
+      [TestPackedTypes parseFromData:rawBytes error:NULL];
+
+  [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializeExtensions {
+  // TestAllTypes and TestAllExtensions should have compatible wire formats,
+  // so if we serealize a TestAllExtensions then parse it as TestAllTypes
+  // it should work.
+
+  TestAllExtensions* message =
+      [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes = message.data;
+  XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+  TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL];
+
+  [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializePackedExtensions {
+  // TestPackedTypes and TestPackedExtensions should have compatible wire
+  // formats; check that they serialize to the same string.
+  TestPackedExtensions* message =
+      [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes = message.data;
+
+  TestPackedTypes* message2 =
+      [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes2 = message2.data;
+
+  XCTAssertEqualObjects(rawBytes, rawBytes2);
+}
+
+- (void)testParseExtensions {
+  // TestAllTypes and TestAllExtensions should have compatible wire formats,
+  // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+  // it should work.
+
+  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes = message.data;
+
+  GPBExtensionRegistry* registry = [self extensionRegistry];
+
+  TestAllExtensions* message2 = [TestAllExtensions parseFromData:rawBytes
+                                               extensionRegistry:registry
+                                                           error:NULL];
+
+  [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+
+- (void) testExtensionsSerializedSize {
+  size_t allSet = [self allSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+  size_t extensionSet = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+  XCTAssertEqual(allSet, extensionSet);
+}
+
+- (void)testParsePackedExtensions {
+  // Ensure that packed extensions can be properly parsed.
+  TestPackedExtensions* message =
+      [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  NSData* rawBytes = message.data;
+
+  GPBExtensionRegistry* registry = [self extensionRegistry];
+
+  TestPackedExtensions* message2 = [TestPackedExtensions parseFromData:rawBytes
+                                                     extensionRegistry:registry
+                                                                 error:NULL];
+
+  [self assertPackedExtensionsSet:message2
+                    repeatedCount:kGPBDefaultRepeatCount];
+}
+
+const int kUnknownTypeId = 1550055;
+
+- (void)testSerializeMessageSet {
+  // Set up a TestMessageSet with two known messages and an unknown one.
+  TestMessageSet* message_set = [TestMessageSet message];
+  [[message_set getExtension:[TestMessageSetExtension1 messageSetExtension]]
+      setI:123];
+  [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]]
+      setStr:@"foo"];
+  GPBUnknownField* unknownField =
+      [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease];
+  [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
+  GPBUnknownFieldSet* unknownFieldSet =
+      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  [unknownFieldSet addField:unknownField];
+  [message_set setUnknownFields:unknownFieldSet];
+
+  NSData* data = [message_set data];
+
+  // Parse back using RawMessageSet and check the contents.
+  RawMessageSet* raw = [RawMessageSet parseFromData:data error:NULL];
+
+  XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
+
+  XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
+  XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId],
+                 [TestMessageSetExtension1 messageSetExtension].fieldNumber);
+  XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId],
+                 [TestMessageSetExtension2 messageSetExtension].fieldNumber);
+  XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
+
+  TestMessageSetExtension1* message1 =
+      [TestMessageSetExtension1 parseFromData:[((RawMessageSet_Item*)raw.itemArray[0]) message]
+                                        error:NULL];
+  XCTAssertEqual(message1.i, 123);
+
+  TestMessageSetExtension2* message2 =
+      [TestMessageSetExtension2 parseFromData:[((RawMessageSet_Item*)raw.itemArray[1]) message]
+                                        error:NULL];
+  XCTAssertEqualObjects(message2.str, @"foo");
+
+  XCTAssertEqualObjects([raw.itemArray[2] message],
+                        [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)testParseMessageSet {
+  // Set up a RawMessageSet with two known messages and an unknown one.
+  RawMessageSet* raw = [RawMessageSet message];
+
+  {
+    RawMessageSet_Item* item = [RawMessageSet_Item message];
+    item.typeId = [TestMessageSetExtension1 messageSetExtension].fieldNumber;
+    TestMessageSetExtension1* message = [TestMessageSetExtension1 message];
+    message.i = 123;
+    item.message = [message data];
+    [raw.itemArray addObject:item];
+  }
+
+  {
+    RawMessageSet_Item* item = [RawMessageSet_Item message];
+    item.typeId = [TestMessageSetExtension2 messageSetExtension].fieldNumber;
+    TestMessageSetExtension2* message = [TestMessageSetExtension2 message];
+    message.str = @"foo";
+    item.message = [message data];
+    [raw.itemArray addObject:item];
+  }
+
+  {
+    RawMessageSet_Item* item = [RawMessageSet_Item message];
+    item.typeId = kUnknownTypeId;
+    item.message = [NSData dataWithBytes:"bar" length:3];
+    [raw.itemArray addObject:item];
+  }
+
+  NSData* data = [raw data];
+
+  // Parse as a TestMessageSet and check the contents.
+  TestMessageSet* messageSet =
+      [TestMessageSet parseFromData:data
+                  extensionRegistry:[UnittestMsetRoot extensionRegistry]
+                              error:NULL];
+
+  XCTAssertEqual(
+      [[messageSet
+          getExtension:[TestMessageSetExtension1 messageSetExtension]] i],
+      123);
+  XCTAssertEqualObjects(
+      [[messageSet
+          getExtension:[TestMessageSetExtension2 messageSetExtension]] str],
+      @"foo");
+
+  XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
+  GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
+  XCTAssertNotNil(unknownField);
+  XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
+  XCTAssertEqualObjects(unknownField.lengthDelimitedList[0],
+                        [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)assertFieldsInOrder:(NSData*)data {
+  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+  int32_t previousTag = 0;
+
+  while (YES) {
+    int32_t tag = [input readTag];
+    if (tag == 0) {
+      break;
+    }
+
+    XCTAssertGreaterThan(tag, previousTag);
+    [input skipField:tag];
+  }
+}
+
+@end
diff --git a/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Bridging-Header.h b/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Bridging-Header.h
new file mode 100644
index 0000000..46292fc
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Bridging-Header.h
@@ -0,0 +1,6 @@
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Info.plist b/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Info.plist
new file mode 100644
index 0000000..460a7d9
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/UnitTests-Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+</dict>
+</plist>
diff --git a/src/third_party/protobuf-3/objectivec/Tests/golden_message b/src/third_party/protobuf-3/objectivec/Tests/golden_message
new file mode 100644
index 0000000..7bceab4
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/golden_message
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/golden_packed_fields_message b/src/third_party/protobuf-3/objectivec/Tests/golden_packed_fields_message
new file mode 100644
index 0000000..7bceab4
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/golden_packed_fields_message
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/AppDelegate.m b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/AppDelegate.m
new file mode 100644
index 0000000..8c4a586
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/AppDelegate.m
@@ -0,0 +1,35 @@
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (strong, nonatomic) UIWindow *window;
+@end
+
+@implementation AppDelegate
+
+@synthesize window;
+
+- (BOOL)application:(UIApplication *)application
+    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+  #pragma unused (application, launchOptions)
+
+  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+  self.window.backgroundColor = [UIColor whiteColor];
+  [self.window makeKeyAndVisible];
+  self.window.rootViewController = [[UIViewController alloc] init];
+
+  UILabel *label =
+      [[UILabel alloc] initWithFrame:CGRectMake(0, 200, CGRectGetWidth(self.window.frame), 40)];
+  label.text = @"Protocol Buffer Test Harness";
+  label.textAlignment = NSTextAlignmentCenter;
+  [self.window addSubview:label];
+
+  return YES;
+}
+
+@end
+
+int main(int argc, char * argv[]) {
+  @autoreleasepool {
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+  }
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..0cbf9ac
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "iPhone6.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "iPhone6_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "iPhone7_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "iPhone7_3x.png",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "50x50",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "50x50",
+      "scale" : "2x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "iPad6.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "iPad6_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "iPad7.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "iPad7_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "car",
+      "size" : "120x120",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
new file mode 100644
index 0000000..43da2ee
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png
new file mode 100644
index 0000000..2ec9370
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
new file mode 100644
index 0000000..aec8bc1
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png
new file mode 100644
index 0000000..e39cc3e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
new file mode 100644
index 0000000..5572d79
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png
new file mode 100644
index 0000000..2424997
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png
new file mode 100644
index 0000000..10bfc3c
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png
new file mode 100644
index 0000000..8d16f14
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png
Binary files differ
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000..5a29666
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,49 @@
+{
+  "images" : [
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "minimum-system-version" : "7.0",
+      "extent" : "full-screen",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "minimum-system-version" : "7.0",
+      "extent" : "full-screen",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "minimum-system-version" : "7.0",
+      "extent" : "full-screen",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "minimum-system-version" : "7.0",
+      "subtype" : "retina4",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "minimum-system-version" : "7.0",
+      "extent" : "full-screen",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Info.plist b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Info.plist
new file mode 100644
index 0000000..24bd333
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/Info.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+</dict>
+</plist>
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/LaunchScreen.xib b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
new file mode 100644
index 0000000..22204bf
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB">
+            <rect key="frame" x="0.0" y="0.0" width="630" height="503"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Protocol Buffer Test Harness" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+                    <rect key="frame" x="20" y="147" width="591" height="43"/>
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+            <constraints>
+                <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="Kid-kn-2rF"/>
+                <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+                <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+            </constraints>
+            <nil key="simulatedStatusBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="479" y="456.5"/>
+        </view>
+    </objects>
+</document>
diff --git a/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
new file mode 100644
index 0000000..477b28f
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/src/third_party/protobuf-3/objectivec/Tests/text_format_map_unittest_data.txt b/src/third_party/protobuf-3/objectivec/Tests/text_format_map_unittest_data.txt
new file mode 100644
index 0000000..ad1195e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/text_format_map_unittest_data.txt
@@ -0,0 +1,70 @@
+map_int32_int32 {
+  key: 100
+  value: 1
+}
+map_int64_int64 {
+  key: 101
+  value: 1
+}
+map_uint32_uint32 {
+  key: 102
+  value: 1
+}
+map_uint64_uint64 {
+  key: 103
+  value: 1
+}
+map_sint32_sint32 {
+  key: 104
+  value: 1
+}
+map_sint64_sint64 {
+  key: 105
+  value: 1
+}
+map_fixed32_fixed32 {
+  key: 106
+  value: 1
+}
+map_fixed64_fixed64 {
+  key: 107
+  value: 1
+}
+map_sfixed32_sfixed32 {
+  key: 108
+  value: 1
+}
+map_sfixed64_sfixed64 {
+  key: 109
+  value: 1
+}
+map_int32_float {
+  key: 110
+  value: 1
+}
+map_int32_double {
+  key: 111
+  value: 1
+}
+map_bool_bool {
+  key: true
+  value: false
+}
+map_string_string {
+  key: "112"
+  value: "1"
+}
+map_int32_bytes {
+  key: 113
+  value: "\001\000\000\000"
+}
+map_int32_enum {
+  key: 114
+  value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+  key: 115
+  value {
+    c: 1
+  }
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/text_format_unittest_data.txt b/src/third_party/protobuf-3/objectivec/Tests/text_format_unittest_data.txt
new file mode 100644
index 0000000..d10f100
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/text_format_unittest_data.txt
@@ -0,0 +1,116 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "\001\000\002\003\000\005"
+OptionalGroup {
+  a: 117
+}
+optional_nested_message {
+  bb: 118
+}
+optional_foreign_message {
+  c: 119
+}
+optional_import_message {
+  d: 120
+}
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: false
+repeated_bool: true
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "\330\000\000\000"
+repeated_bytes: "<\001\000\000"
+RepeatedGroup {
+  a: 217
+}
+RepeatedGroup {
+  a: 317
+}
+repeated_nested_message {
+  bb: 218
+}
+repeated_nested_message {
+  bb: 318
+}
+repeated_foreign_message {
+  c: 219
+}
+repeated_foreign_message {
+  c: 319
+}
+repeated_import_message {
+  d: 220
+}
+repeated_import_message {
+  d: 320
+}
+repeated_nested_enum: BAZ
+repeated_nested_enum: BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "\240\001\000\000"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
diff --git a/src/third_party/protobuf-3/objectivec/Tests/unittest_cycle.proto b/src/third_party/protobuf-3/objectivec/Tests/unittest_cycle.proto
new file mode 100644
index 0000000..5f6f56a
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/unittest_cycle.proto
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+// Cycles in the Message graph can cause problems for the mutable classes
+// since the properties on the mutable class change types. This file just
+// needs to generate source, and that source must compile, to ensure the
+// generated source works for this sort of case.
+
+// You can't make a object graph that spans files, so this can only be done
+// within a single proto file.
+
+message CycleFoo {
+  optional CycleFoo a_foo = 1;
+  optional CycleBar a_bar = 2;
+  optional CycleBaz a_baz = 3;
+}
+
+message CycleBar {
+  optional CycleBar a_bar = 1;
+  optional CycleBaz a_baz = 2;
+  optional CycleFoo a_foo = 3;
+}
+
+message CycleBaz {
+  optional CycleBaz a_baz = 1;
+  optional CycleFoo a_foo = 2;
+  optional CycleBar a_bar = 3;
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/unittest_objc.proto b/src/third_party/protobuf-3/objectivec/Tests/unittest_objc.proto
new file mode 100644
index 0000000..f6ab6a2
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/unittest_objc.proto
@@ -0,0 +1,449 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2011 Google Inc.  All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+// Using the messages in unittest.proto, setup for recursive cases for testing
+// extensions at various depths.
+extend TestAllExtensions {
+  optional TestAllExtensions recursive_extension = 86;
+}
+
+// Recursive message to for testing autocreators at different depths.
+message TestRecursiveMessageWithRepeatedField {
+  optional TestRecursiveMessageWithRepeatedField a = 1;
+  repeated int32 i = 2;
+  repeated string str = 3;
+  map<int32, int32> i_to_i = 4;
+  map<string, string> str_to_str = 5;
+}
+
+// Recursive message and extension to for testing autocreators at different
+// depths.
+message TestRecursiveExtension {
+  optional TestRecursiveExtension recursive_sub_message = 1;
+  repeated int32 repeated_value = 2;
+  extensions 1000 to max;
+}
+
+extend TestRecursiveExtension {
+  optional TestRecursiveExtension recursive_message_extension = 1000;
+}
+
+message self {
+  message super {
+    optional int32 description = 1;
+  }
+
+  enum autorelease {
+    retain      = 1;
+    release     = 2;
+    retainCount = 3;
+  }
+
+  // Singular
+  optional   bool id                =  1;
+  optional   bool _cmd              =  2;
+  optional   bool in                =  3;
+  optional   bool out               =  4;
+  optional   bool inout             =  5;
+  optional   bool bycopy            =  6;
+  optional   bool byref             =  7;
+  optional   bool oneway            =  8;
+  optional   bool dealloc           =  9;
+  optional   bool zone              = 10;
+  optional   bool isProxy           = 11;
+  optional   bool copy              = 12;
+  optional   bool readonly          = 13;
+  optional   bool default           = 14;
+  optional   bool assign            = 15;
+  optional   bool getter            = 16;
+  optional   bool setter            = 17;
+  optional   bool weak              = 18;
+  optional   bool public            = 19;
+  optional   bool case              = 20;
+
+  optional   autorelease SubEnum    = 25;
+
+ optional group New = 50 {
+   optional string copy = 51;
+ }
+  optional group MutableCopy = 60 {
+    optional int32 extensionRegistry = 61;
+  }
+
+  extensions 90 to 94;
+
+}
+
+enum retain {
+  count          = 4;
+  initialized    = 5;
+  serializedSize = 6;
+}
+
+message ObjCPropertyNaming {
+  // Test that the properties properly get things all caps.
+  optional string url           = 1;
+  optional string thumbnail_url = 2;
+  optional string url_foo       = 3;
+  optional string some_url_blah = 4;
+  optional string http          = 5;
+  optional string https         = 6;
+  // This one doesn't.
+  repeated string urls          = 7;
+}
+
+// EnumValueShortName: The short names shouldn't get suffixes/prefixes.
+enum Foo {
+  SERIALIZED_SIZE = 1;
+  SIZE            = 2;
+  OTHER           = 3;
+}
+
+// EnumValueShortName: The enum name gets a prefix.
+enum Category {
+  RED  = 1;
+  BLUE = 2;
+}
+
+// EnumValueShortName: Twist case, full name gets PB, but the short names
+// should still end up correct.
+enum Time {
+  BASE            = 1;
+  RECORD          = 2;
+  SOMETHING_ELSE  = 3;
+}
+
+extend self {
+  repeated    int32 debugDescription    =  90 [packed = true];
+  repeated    int64 finalize            =  91 [packed = true];
+  repeated   uint32 hash                =  92 [packed = true];
+  repeated   uint64 classForCoder       =  93 [packed = true];
+  repeated   sint32 byref               =  94 [packed = true];
+}
+
+// Test handing of fields that start with init* since Xcode 5's ARC support
+// doesn't like messages that look like initializers but aren't.
+message ObjCInitFoo {
+  optional string init_val = 11;
+  optional int32 init_size = 12;
+  optional self init_self = 13;
+
+  repeated string init_vals = 21;
+  repeated int32 init_sizes = 22;
+  repeated self init_selfs = 23;
+}
+
+// Test handling of fields that start with retained names.
+message ObjCRetainedFoo {
+  optional string new_val_lower_complex = 11;
+  optional string new_Val_upper_complex = 12;
+  optional string newvalue_lower_no_underscore_complex = 13;
+  optional string newValue_upper_no_underscore_complex = 14;
+
+  optional int32 new_val_lower_primitive = 15;
+  optional int32 new_Val_upper_primitive = 16;
+  optional int32 newvalue_lower_no_underscore_primitive = 17;
+  optional int32 newValue_upper_no_underscore_primitive = 18;
+
+  optional self new_val_lower_message = 19;
+  optional self new_Val_upper_message = 20;
+  optional self newvalue_lower_no_underscore_message = 21;
+  optional self newValue_upper_no_underscore_message = 22;
+
+  optional Foo new_val_lower_enum = 23;
+  optional Foo new_Val_upper_enum = 24;
+  optional Foo newvalue_lower_no_underscore_enum = 25;
+  optional Foo newValue_upper_no_underscore_enum = 26;
+
+  repeated string new_val_lower_complex_repeated = 111;
+  repeated string new_Val_upper_complex_repeated = 112;
+  repeated string newvalue_lower_no_underscore_complex_repeated = 113;
+  repeated string newValue_upper_no_underscore_complex_repeated = 114;
+
+  repeated int32 new_val_lower_primitive_repeated = 115;
+  repeated int32 new_Val_upper_primitive_repeated = 116;
+  repeated int32 newvalue_lower_no_underscore_primitive_repeated = 117;
+  repeated int32 newValue_upper_no_underscore_primitive_repeated = 118;
+
+  repeated self new_val_lower_message_repeated = 119;
+  repeated self new_Val_upper_message_repeated = 120;
+  repeated self newvalue_lower_no_underscore_message_repeated = 121;
+  repeated self newValue_upper_no_underscore_message_repeated = 122;
+
+  repeated Foo new_val_lower_enum_repeated = 123;
+  repeated Foo new_Val_upper_enum_repeated = 124;
+  repeated Foo newvalue_lower_no_underscore_enum_repeated = 125;
+  repeated Foo newValue_upper_no_underscore_enum_repeated = 126;
+
+  optional string alloc_val_lower_complex = 211;
+  optional string alloc_Val_upper_complex = 212;
+  optional string allocvalue_lower_no_underscore_complex = 213;
+  optional string allocValue_upper_no_underscore_complex = 214;
+
+  optional int32 alloc_val_lower_primitive = 215;
+  optional int32 alloc_Val_upper_primitive = 216;
+  optional int32 allocvalue_lower_no_underscore_primitive = 217;
+  optional int32 allocValue_upper_no_underscore_primitive = 218;
+
+  optional self alloc_val_lower_message = 219;
+  optional self alloc_Val_upper_message = 220;
+  optional self allocvalue_lower_no_underscore_message = 221;
+  optional self allocValue_upper_no_underscore_message = 222;
+
+  optional Foo alloc_val_lower_enum = 223;
+  optional Foo alloc_Val_upper_enum = 224;
+  optional Foo allocvalue_lower_no_underscore_enum = 225;
+  optional Foo allocValue_upper_no_underscore_enum = 226;
+
+  repeated string alloc_val_lower_complex_repeated = 311;
+  repeated string alloc_Val_upper_complex_repeated = 312;
+  repeated string allocvalue_lower_no_underscore_complex_repeated = 313;
+  repeated string allocValue_upper_no_underscore_complex_repeated = 314;
+
+  repeated int32 alloc_val_lower_primitive_repeated = 315;
+  repeated int32 alloc_Val_upper_primitive_repeated = 316;
+  repeated int32 allocvalue_lower_no_underscore_primitive_repeated = 317;
+  repeated int32 allocValue_upper_no_underscore_primitive_repeated = 318;
+
+  repeated self alloc_val_lower_message_repeated = 319;
+  repeated self alloc_Val_upper_message_repeated = 320;
+  repeated self allocvalue_lower_no_underscore_message_repeated = 321;
+  repeated self allocValue_upper_no_underscore_message_repeated = 322;
+
+  repeated Foo alloc_val_lower_enum_repeated = 323;
+  repeated Foo alloc_Val_upper_enum_repeated = 324;
+  repeated Foo allocvalue_lower_no_underscore_enum_repeated = 325;
+  repeated Foo allocValue_upper_no_underscore_enum_repeated = 326;
+
+  optional string copy_val_lower_complex = 411;
+  optional string copy_Val_upper_complex = 412;
+  optional string copyvalue_lower_no_underscore_complex = 413;
+  optional string copyValue_upper_no_underscore_complex = 414;
+
+  optional int32 copy_val_lower_primitive = 415;
+  optional int32 copy_Val_upper_primitive = 416;
+  optional int32 copyvalue_lower_no_underscore_primitive = 417;
+  optional int32 copyValue_upper_no_underscore_primitive = 418;
+
+  optional self copy_val_lower_message = 419;
+  optional self copy_Val_upper_message = 420;
+  optional self copyvalue_lower_no_underscore_message = 421;
+  optional self copyValue_upper_no_underscore_message = 422;
+
+  optional Foo copy_val_lower_enum = 423;
+  optional Foo copy_Val_upper_enum = 424;
+  optional Foo copyvalue_lower_no_underscore_enum = 425;
+  optional Foo copyValue_upper_no_underscore_enum = 426;
+
+  repeated string copy_val_lower_complex_repeated = 511;
+  repeated string copy_Val_upper_complex_repeated = 512;
+  repeated string copyvalue_lower_no_underscore_complex_repeated = 513;
+  repeated string copyValue_upper_no_underscore_complex_repeated = 514;
+
+  repeated int32 copy_val_lower_primitive_repeated = 515;
+  repeated int32 copy_Val_upper_primitive_repeated = 516;
+  repeated int32 copyvalue_lower_no_underscore_primitive_repeated = 517;
+  repeated int32 copyValue_upper_no_underscore_primitive_repeated = 518;
+
+  repeated self copy_val_lower_message_repeated = 519;
+  repeated self copy_Val_upper_message_repeated = 520;
+  repeated self copyvalue_lower_no_underscore_message_repeated = 521;
+  repeated self copyValue_upper_no_underscore_message_repeated = 522;
+
+  repeated Foo copy_val_lower_enum_repeated = 523;
+  repeated Foo copy_Val_upper_enum_repeated = 524;
+  repeated Foo copyvalue_lower_no_underscore_enum_repeated = 525;
+  repeated Foo copyValue_upper_no_underscore_enum_repeated = 526;
+
+  optional string mutableCopy_val_lower_complex = 611;
+  optional string mutableCopy_Val_upper_complex = 612;
+  optional string mutableCopyvalue_lower_no_underscore_complex = 613;
+  optional string mutableCopyValue_upper_no_underscore_complex = 614;
+
+  optional int32 mutableCopy_val_lower_primitive = 615;
+  optional int32 mutableCopy_Val_upper_primitive = 616;
+  optional int32 mutableCopyvalue_lower_no_underscore_primitive = 617;
+  optional int32 mutableCopyValue_upper_no_underscore_primitive = 618;
+
+  optional self mutableCopy_val_lower_message = 619;
+  optional self mutableCopy_Val_upper_message = 620;
+  optional self mutableCopyvalue_lower_no_underscore_message = 621;
+  optional self mutableCopyValue_upper_no_underscore_message = 622;
+
+  optional Foo mutableCopy_val_lower_enum = 623;
+  optional Foo mutableCopy_Val_upper_enum = 624;
+  optional Foo mutableCopyvalue_lower_no_underscore_enum = 625;
+  optional Foo mutableCopyValue_upper_no_underscore_enum = 626;
+
+  repeated string mutableCopy_val_lower_complex_repeated = 711;
+  repeated string mutableCopy_Val_upper_complex_repeated = 712;
+  repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 713;
+  repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 714;
+
+  repeated int32 mutableCopy_val_lower_primitive_repeated = 715;
+  repeated int32 mutableCopy_Val_upper_primitive_repeated = 716;
+  repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 717;
+  repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 718;
+
+  repeated self mutableCopy_val_lower_message_repeated = 719;
+  repeated self mutableCopy_Val_upper_message_repeated = 720;
+  repeated self mutableCopyvalue_lower_no_underscore_message_repeated = 721;
+  repeated self mutableCopyValue_upper_no_underscore_message_repeated = 722;
+
+  repeated Foo mutableCopy_val_lower_enum_repeated = 723;
+  repeated Foo mutableCopy_Val_upper_enum_repeated = 724;
+  repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 725;
+  repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 726;
+}
+
+// Test handling of fields that are the retained names.
+message ObjCRetainedComplex {
+  optional string new = 1;
+  optional string alloc = 2;
+  optional string copy = 3;
+  optional string mutableCopy = 4;
+}
+
+message ObjCRetainedComplexRepeated {
+  repeated string new = 1;
+  repeated string alloc = 2;
+  repeated string copy = 3;
+  repeated string mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitive {
+  optional int32 new = 1;
+  optional int32 alloc = 2;
+  optional int32 copy = 3;
+  optional int32 mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitiveRepeated {
+  repeated int32 new = 1;
+  repeated int32 alloc = 2;
+  repeated int32 copy = 3;
+  repeated int32 mutableCopy = 4;
+}
+
+message ObjCRetainedMessage {
+  optional self new = 1;
+  optional self alloc = 2;
+  optional self copy = 3;
+  optional self mutableCopy = 4;
+}
+
+message ObjCRetainedMessageRepeated {
+  repeated self new = 1;
+  repeated self alloc = 2;
+  repeated self copy = 3;
+  repeated self mutableCopy = 4;
+}
+
+// Test Handling some MacTypes
+message Point {
+  message Rect {
+    optional int32 TimeValue = 1;
+  }
+}
+
+// Test some weird defaults that we see in protos.
+message ObjcWeirdDefaults {
+  // Set default values that match the protocol buffer defined defaults to
+  // confirm hasDefault and the default values are set correctly.
+  optional string foo = 1 [default = ""];
+  optional bytes bar = 2 [default = ""];
+}
+
+// Used to confirm negative enum values work as expected.
+message EnumTestMsg {
+  enum MyEnum {
+    ZERO    = 0;
+    ONE     = 1;
+    TWO     = 2;
+    NEG_ONE = -1;
+    NEG_TWO = -2;
+  }
+  optional MyEnum foo = 1;
+  optional MyEnum bar = 2 [default = ONE];
+  optional MyEnum baz = 3 [default = NEG_ONE];
+
+  repeated MyEnum mumble = 4;
+}
+
+// Test case for https://github.com/google/protobuf/issues/1453
+// Message with no explicit defaults, but a non zero default for an enum.
+message MessageWithOneBasedEnum {
+  enum OneBasedEnum {
+    ONE = 1;
+    TWO = 2;
+  }
+  optional OneBasedEnum enum_field = 1;
+}
+
+// Message with all bools for testing things related to bool storage.
+message BoolOnlyMessage {
+  optional bool bool_field_1 = 1;
+  optional bool bool_field_2 = 2;
+  optional bool bool_field_3 = 3;
+  optional bool bool_field_4 = 4;
+  optional bool bool_field_5 = 5;
+  optional bool bool_field_6 = 6;
+  optional bool bool_field_7 = 7;
+  optional bool bool_field_8 = 8;
+  optional bool bool_field_9 = 9;
+  optional bool bool_field_10 = 10;
+  optional bool bool_field_11 = 11;
+  optional bool bool_field_12 = 12;
+  optional bool bool_field_13 = 13;
+  optional bool bool_field_14 = 14;
+  optional bool bool_field_15 = 15;
+  optional bool bool_field_16 = 16;
+  optional bool bool_field_17 = 17;
+  optional bool bool_field_18 = 18;
+  optional bool bool_field_19 = 19;
+  optional bool bool_field_20 = 20;
+  optional bool bool_field_21 = 21;
+  optional bool bool_field_22 = 22;
+  optional bool bool_field_23 = 23;
+  optional bool bool_field_24 = 24;
+  optional bool bool_field_25 = 25;
+  optional bool bool_field_26 = 26;
+  optional bool bool_field_27 = 27;
+  optional bool bool_field_28 = 28;
+  optional bool bool_field_29 = 29;
+  optional bool bool_field_30 = 30;
+  optional bool bool_field_31 = 31;
+  optional bool bool_field_32 = 32;
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/unittest_objc_startup.proto b/src/third_party/protobuf-3/objectivec/Tests/unittest_objc_startup.proto
new file mode 100644
index 0000000..aee7bd5
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/unittest_objc_startup.proto
@@ -0,0 +1,49 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_objc_unittest;
+
+message TestObjCStartupMessage {
+  extensions 1 to max;
+}
+
+extend TestObjCStartupMessage {
+  // Singular
+  optional    int32 optional_int32_extension    = 1;
+  repeated    int32 repeated_int32_extension    = 2;
+}
+
+message TestObjCStartupNested {
+  extend TestObjCStartupMessage {
+    optional string nested_string_extension = 3;
+  }
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto2.proto b/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto2.proto
new file mode 100644
index 0000000..ed83502
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto2.proto
@@ -0,0 +1,128 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message Message2 {
+  enum Enum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    EXTRA_2 = 20;
+  }
+
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+  optional Message2  optional_message = 18;
+  optional Enum         optional_enum = 19;
+
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+  repeated Message2 repeated_message  = 48;
+  repeated Enum     repeated_enum     = 49;
+
+  oneof o {
+       int32 oneof_int32    = 51 [default = 100];
+       int64 oneof_int64    = 52 [default = 101];
+      uint32 oneof_uint32   = 53 [default = 102];
+      uint64 oneof_uint64   = 54 [default = 103];
+      sint32 oneof_sint32   = 55 [default = 104];
+      sint64 oneof_sint64   = 56 [default = 105];
+     fixed32 oneof_fixed32  = 57 [default = 106];
+     fixed64 oneof_fixed64  = 58 [default = 107];
+    sfixed32 oneof_sfixed32 = 59 [default = 108];
+    sfixed64 oneof_sfixed64 = 60 [default = 109];
+       float oneof_float    = 61 [default = 110];
+      double oneof_double   = 62 [default = 111];
+        bool oneof_bool     = 63 [default = true];
+      string oneof_string   = 64 [default = "string"];
+       bytes oneof_bytes    = 65 [default = "data"];
+       group OneofGroup     = 66 {
+         optional int32 a = 67;
+         optional int32 b = 167;
+       }
+     Message2 oneof_message = 68;
+     Enum        oneof_enum = 69 [default = BAZ];
+  }
+
+  // Some token map cases, too many combinations to list them all.
+  map<int32   , int32   > map_int32_int32       = 70;
+  map<int64   , int64   > map_int64_int64       = 71;
+  map<uint32  , uint32  > map_uint32_uint32     = 72;
+  map<uint64  , uint64  > map_uint64_uint64     = 73;
+  map<sint32  , sint32  > map_sint32_sint32     = 74;
+  map<sint64  , sint64  > map_sint64_sint64     = 75;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 76;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 77;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 78;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 79;
+  map<int32   , float   > map_int32_float       = 80;
+  map<int32   , double  > map_int32_double      = 81;
+  map<bool    , bool    > map_bool_bool         = 82;
+  map<string  , string  > map_string_string     = 83;
+  map<string  , bytes   > map_string_bytes      = 84;
+  map<string  , Message2> map_string_message    = 85;
+  map<int32   , bytes   > map_int32_bytes       = 86;
+  map<int32   , Enum    > map_int32_enum        = 87;
+  map<int32   , Message2> map_int32_message     = 88;
+}
diff --git a/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto3.proto b/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto3.proto
new file mode 100644
index 0000000..ad2e3620
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/Tests/unittest_runtime_proto3.proto
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+//
+// 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.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+message Message3 {
+  enum Enum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    EXTRA_3 = 30;
+  }
+
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+  // No 'group' in proto3.
+  Message3 optional_message  = 18;
+      Enum optional_enum     = 19;
+
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+  // No 'group' in proto3.
+  repeated Message3 repeated_message  = 48;
+  repeated     Enum repeated_enum     = 49;
+
+  oneof o {
+       int32 oneof_int32    = 51;
+       int64 oneof_int64    = 52;
+      uint32 oneof_uint32   = 53;
+      uint64 oneof_uint64   = 54;
+      sint32 oneof_sint32   = 55;
+      sint64 oneof_sint64   = 56;
+     fixed32 oneof_fixed32  = 57;
+     fixed64 oneof_fixed64  = 58;
+    sfixed32 oneof_sfixed32 = 59;
+    sfixed64 oneof_sfixed64 = 60;
+       float oneof_float    = 61;
+      double oneof_double   = 62;
+        bool oneof_bool     = 63;
+      string oneof_string   = 64;
+       bytes oneof_bytes    = 65;
+    // No 'group' in proto3.
+    Message3 oneof_message  = 68;
+        Enum oneof_enum     = 69;
+  }
+
+  // Some token map cases, too many combinations to list them all.
+  map<int32   , int32   > map_int32_int32       = 70;
+  map<int64   , int64   > map_int64_int64       = 71;
+  map<uint32  , uint32  > map_uint32_uint32     = 72;
+  map<uint64  , uint64  > map_uint64_uint64     = 73;
+  map<sint32  , sint32  > map_sint32_sint32     = 74;
+  map<sint64  , sint64  > map_sint64_sint64     = 75;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 76;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 77;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 78;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 79;
+  map<int32   , float   > map_int32_float       = 80;
+  map<int32   , double  > map_int32_double      = 81;
+  map<bool    , bool    > map_bool_bool         = 82;
+  map<string  , string  > map_string_string     = 83;
+  map<string  , bytes   > map_string_bytes      = 84;
+  map<string  , Message3> map_string_message    = 85;
+  map<int32   , bytes   > map_int32_bytes       = 86;
+  map<int32   , Enum    > map_int32_enum        = 87;
+  map<int32   , Message3> map_int32_message     = 88;
+}
diff --git a/src/third_party/protobuf-3/objectivec/generate_well_known_types.sh b/src/third_party/protobuf-3/objectivec/generate_well_known_types.sh
new file mode 100755
index 0000000..36c3460
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/generate_well_known_types.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Run this script to regenerate *.pbobjc.{h,m} for the well known types after
+# the protocol compiler changes.
+
+# HINT:  Flags passed to generate_well_known_types.sh will be passed directly
+#   to make when building protoc.  This is particularly useful for passing
+#   -j4 to run 4 jobs simultaneously.
+
+set -eu
+
+readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
+readonly ProtoRootDir="${ScriptDir}/.."
+
+# Flag for continuous integration to check that everything is current.
+CHECK_ONLY=0
+if [[ $# -ge 1 && ( "$1" == "--check-only" ) ]] ; then
+  CHECK_ONLY=1
+  shift
+fi
+
+pushd "${ProtoRootDir}" > /dev/null
+
+if test ! -e src/google/protobuf/stubs/common.h; then
+  cat >&2 << __EOF__
+Could not find source code.  Make sure you are running this script from the
+root of the distribution tree.
+__EOF__
+  exit 1
+fi
+
+if test ! -e src/Makefile; then
+  cat >&2 << __EOF__
+Could not find src/Makefile.  You must run ./configure (and perhaps
+./autogen.sh) first.
+__EOF__
+  exit 1
+fi
+
+# Make sure the compiler is current.
+cd src
+make $@ protoc
+
+declare -a RUNTIME_PROTO_FILES=( \
+  google/protobuf/any.proto \
+  google/protobuf/api.proto \
+  google/protobuf/duration.proto \
+  google/protobuf/empty.proto \
+  google/protobuf/field_mask.proto \
+  google/protobuf/source_context.proto \
+  google/protobuf/struct.proto \
+  google/protobuf/timestamp.proto \
+  google/protobuf/type.proto \
+  google/protobuf/wrappers.proto)
+
+# Generate to a temp directory to see if they match.
+TMP_DIR=$(mktemp -d)
+trap "rm -rf ${TMP_DIR}" EXIT
+./protoc --objc_out="${TMP_DIR}" ${RUNTIME_PROTO_FILES[@]}
+set +e
+diff -r "${TMP_DIR}/google" "${ProtoRootDir}/objectivec/google" > /dev/null
+if [[ $? -eq 0 ]] ; then
+  echo "Generated source for WellKnownTypes is current."
+  exit 0
+fi
+set -e
+
+# If check only mode, error out.
+if [[ "${CHECK_ONLY}" == 1 ]] ; then
+  echo "ERROR: The WKTs need to be regenerated! Run $0"
+  exit 1
+fi
+
+# Copy them over.
+echo "Copying over updated WellKnownType sources."
+cp -r "${TMP_DIR}/google/." "${ProtoRootDir}/objectivec/google/"
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.h
new file mode 100644
index 0000000..4002a98
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.h
@@ -0,0 +1,134 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBAnyRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBAnyRoot : GPBRootObject
+@end
+
+#pragma mark - GPBAny
+
+typedef GPB_ENUM(GPBAny_FieldNumber) {
+  GPBAny_FieldNumber_TypeURL = 1,
+  GPBAny_FieldNumber_Value = 2,
+};
+
+/// `Any` contains an arbitrary serialized protocol buffer message along with a
+/// URL that describes the type of the serialized message.
+///
+/// Protobuf library provides support to pack/unpack Any values in the form
+/// of utility functions or additional generated methods of the Any type.
+///
+/// Example 1: Pack and unpack a message in C++.
+///
+///     Foo foo = ...;
+///     Any any;
+///     any.PackFrom(foo);
+///     ...
+///     if (any.UnpackTo(&foo)) {
+///       ...
+///     }
+///
+/// Example 2: Pack and unpack a message in Java.
+///
+///     Foo foo = ...;
+///     Any any = Any.pack(foo);
+///     ...
+///     if (any.is(Foo.class)) {
+///       foo = any.unpack(Foo.class);
+///     }
+///
+/// The pack methods provided by protobuf library will by default use
+/// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+/// methods only use the fully qualified type name after the last '/'
+/// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+/// name "y.z".
+///
+///
+/// JSON
+/// ====
+/// The JSON representation of an `Any` value uses the regular
+/// representation of the deserialized, embedded message, with an
+/// additional field `\@type` which contains the type URL. Example:
+///
+///     package google.profile;
+///     message Person {
+///       string first_name = 1;
+///       string last_name = 2;
+///     }
+///
+///     {
+///       "\@type": "type.googleapis.com/google.profile.Person",
+///       "firstName": <string>,
+///       "lastName": <string>
+///     }
+///
+/// If the embedded message type is well-known and has a custom JSON
+/// representation, that representation will be embedded adding a field
+/// `value` which holds the custom JSON in addition to the `\@type`
+/// field. Example (for message [google.protobuf.Duration][]):
+///
+///     {
+///       "\@type": "type.googleapis.com/google.protobuf.Duration",
+///       "value": "1.212s"
+///     }
+@interface GPBAny : GPBMessage
+
+/// A URL/resource name whose content describes the type of the
+/// serialized protocol buffer message.
+///
+/// For URLs which use the schema `http`, `https`, or no schema, the
+/// following restrictions and interpretations apply:
+///
+/// * If no schema is provided, `https` is assumed.
+/// * The last segment of the URL's path must represent the fully
+///   qualified name of the type (as in `path/google.protobuf.Duration`).
+///   The name should be in a canonical form (e.g., leading "." is
+///   not accepted).
+/// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+///   value in binary format, or produce an error.
+/// * Applications are allowed to cache lookup results based on the
+///   URL, or have them precompiled into a binary to avoid any
+///   lookup. Therefore, binary compatibility needs to be preserved
+///   on changes to types. (Use versioned type names to manage
+///   breaking changes.)
+///
+/// Schemas other than `http`, `https` (or the empty schema) might be
+/// used with implementation specific semantics.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
+
+/// Must be a valid serialized protocol buffer of the above specified type.
+@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.m
new file mode 100644
index 0000000..6a1bf89
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Any.pbobjc.m
@@ -0,0 +1,93 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Any.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBAnyRoot
+
+@implementation GPBAnyRoot
+
+@end
+
+#pragma mark - GPBAnyRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBAny
+
+@implementation GPBAny
+
+@dynamic typeURL;
+@dynamic value;
+
+typedef struct GPBAny__storage_ {
+  uint32_t _has_storage_[1];
+  NSString *typeURL;
+  NSData *value;
+} GPBAny__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "typeURL",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBAny_FieldNumber_TypeURL,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL),
+        .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBAny_FieldNumber_Value,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBAny__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBytes,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBAny class]
+                                     rootClass:[GPBAnyRoot class]
+                                          file:GPBAnyRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBAny__storage_)
+                                         flags:0];
+#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    static const char *extraTextFormatInfo =
+        "\001\001\004\241!!\000";
+    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];
+#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.h
new file mode 100644
index 0000000..d66df62
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.h
@@ -0,0 +1,262 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+@class GPBMethod;
+@class GPBMixin;
+@class GPBOption;
+@class GPBSourceContext;
+GPB_ENUM_FWD_DECLARE(GPBSyntax);
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBApiRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBApiRoot : GPBRootObject
+@end
+
+#pragma mark - GPBApi
+
+typedef GPB_ENUM(GPBApi_FieldNumber) {
+  GPBApi_FieldNumber_Name = 1,
+  GPBApi_FieldNumber_MethodsArray = 2,
+  GPBApi_FieldNumber_OptionsArray = 3,
+  GPBApi_FieldNumber_Version = 4,
+  GPBApi_FieldNumber_SourceContext = 5,
+  GPBApi_FieldNumber_MixinsArray = 6,
+  GPBApi_FieldNumber_Syntax = 7,
+};
+
+/// Api is a light-weight descriptor for a protocol buffer service.
+@interface GPBApi : GPBMessage
+
+/// The fully qualified name of this api, including package name
+/// followed by the api's simple name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// The methods of this api, in unspecified order.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethod*> *methodsArray;
+/// The number of items in @c methodsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger methodsArray_Count;
+
+/// Any metadata attached to the API.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+/// A version string for this api. If specified, must have the form
+/// `major-version.minor-version`, as in `1.10`. If the minor version
+/// is omitted, it defaults to zero. If the entire version field is
+/// empty, the major version is derived from the package name, as
+/// outlined below. If the field is not empty, the version in the
+/// package name will be verified to be consistent with what is
+/// provided here.
+///
+/// The versioning schema uses [semantic
+/// versioning](http://semver.org) where the major version number
+/// indicates a breaking change and the minor version an additive,
+/// non-breaking change. Both version numbers are signals to users
+/// what to expect from different versions, and should be carefully
+/// chosen based on the product plan.
+///
+/// The major version is also reflected in the package name of the
+/// API, which must end in `v<major-version>`, as in
+/// `google.feature.v1`. For major versions 0 and 1, the suffix can
+/// be omitted. Zero major versions must only be used for
+/// experimental, none-GA apis.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *version;
+
+/// Source context for the protocol buffer service represented by this
+/// message.
+@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+/// Test to see if @c sourceContext has been set.
+@property(nonatomic, readwrite) BOOL hasSourceContext;
+
+/// Included APIs. See [Mixin][].
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMixin*> *mixinsArray;
+/// The number of items in @c mixinsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger mixinsArray_Count;
+
+/// The source syntax of the service.
+@property(nonatomic, readwrite) enum GPBSyntax syntax;
+
+@end
+
+/// Fetches the raw value of a @c GPBApi's @c syntax property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBApi_Syntax_RawValue(GPBApi *message);
+/// Sets the raw value of an @c GPBApi's @c syntax property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value);
+
+#pragma mark - GPBMethod
+
+typedef GPB_ENUM(GPBMethod_FieldNumber) {
+  GPBMethod_FieldNumber_Name = 1,
+  GPBMethod_FieldNumber_RequestTypeURL = 2,
+  GPBMethod_FieldNumber_RequestStreaming = 3,
+  GPBMethod_FieldNumber_ResponseTypeURL = 4,
+  GPBMethod_FieldNumber_ResponseStreaming = 5,
+  GPBMethod_FieldNumber_OptionsArray = 6,
+  GPBMethod_FieldNumber_Syntax = 7,
+};
+
+/// Method represents a method of an api.
+@interface GPBMethod : GPBMessage
+
+/// The simple name of this method.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// A URL of the input message type.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL;
+
+/// If true, the request is streamed.
+@property(nonatomic, readwrite) BOOL requestStreaming;
+
+/// The URL of the output message type.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL;
+
+/// If true, the response is streamed.
+@property(nonatomic, readwrite) BOOL responseStreaming;
+
+/// Any metadata attached to the method.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+/// The source syntax of this method.
+@property(nonatomic, readwrite) enum GPBSyntax syntax;
+
+@end
+
+/// Fetches the raw value of a @c GPBMethod's @c syntax property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBMethod_Syntax_RawValue(GPBMethod *message);
+/// Sets the raw value of an @c GPBMethod's @c syntax property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value);
+
+#pragma mark - GPBMixin
+
+typedef GPB_ENUM(GPBMixin_FieldNumber) {
+  GPBMixin_FieldNumber_Name = 1,
+  GPBMixin_FieldNumber_Root = 2,
+};
+
+/// Declares an API to be included in this API. The including API must
+/// redeclare all the methods from the included API, but documentation
+/// and options are inherited as follows:
+///
+/// - If after comment and whitespace stripping, the documentation
+///   string of the redeclared method is empty, it will be inherited
+///   from the original method.
+///
+/// - Each annotation belonging to the service config (http,
+///   visibility) which is not set in the redeclared method will be
+///   inherited.
+///
+/// - If an http annotation is inherited, the path pattern will be
+///   modified as follows. Any version prefix will be replaced by the
+///   version of the including API plus the [root][] path if specified.
+///
+/// Example of a simple mixin:
+///
+///     package google.acl.v1;
+///     service AccessControl {
+///       // Get the underlying ACL object.
+///       rpc GetAcl(GetAclRequest) returns (Acl) {
+///         option (google.api.http).get = "/v1/{resource=**}:getAcl";
+///       }
+///     }
+///
+///     package google.storage.v2;
+///     service Storage {
+///       rpc GetAcl(GetAclRequest) returns (Acl);
+///
+///       // Get a data record.
+///       rpc GetData(GetDataRequest) returns (Data) {
+///         option (google.api.http).get = "/v2/{resource=**}";
+///       }
+///     }
+///
+/// Example of a mixin configuration:
+///
+///     apis:
+///     - name: google.storage.v2.Storage
+///       mixins:
+///       - name: google.acl.v1.AccessControl
+///
+/// The mixin construct implies that all methods in `AccessControl` are
+/// also declared with same name and request/response types in
+/// `Storage`. A documentation generator or annotation processor will
+/// see the effective `Storage.GetAcl` method after inherting
+/// documentation and annotations as follows:
+///
+///     service Storage {
+///       // Get the underlying ACL object.
+///       rpc GetAcl(GetAclRequest) returns (Acl) {
+///         option (google.api.http).get = "/v2/{resource=**}:getAcl";
+///       }
+///       ...
+///     }
+///
+/// Note how the version in the path pattern changed from `v1` to `v2`.
+///
+/// If the `root` field in the mixin is specified, it should be a
+/// relative path under which inherited HTTP paths are placed. Example:
+///
+///     apis:
+///     - name: google.storage.v2.Storage
+///       mixins:
+///       - name: google.acl.v1.AccessControl
+///         root: acls
+///
+/// This implies the following inherited HTTP annotation:
+///
+///     service Storage {
+///       // Get the underlying ACL object.
+///       rpc GetAcl(GetAclRequest) returns (Acl) {
+///         option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+///       }
+///       ...
+///     }
+@interface GPBMixin : GPBMessage
+
+/// The fully qualified name of the API which is included.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// If non-empty specifies a path under which inherited HTTP paths
+/// are rooted.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *root;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.m
new file mode 100644
index 0000000..45a06e6
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Api.pbobjc.m
@@ -0,0 +1,348 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Api.pbobjc.h"
+#import "google/protobuf/SourceContext.pbobjc.h"
+#import "google/protobuf/Type.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBApiRoot
+
+@implementation GPBApiRoot
+
++ (GPBExtensionRegistry*)extensionRegistry {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety and initialization of registry.
+  static GPBExtensionRegistry* registry = nil;
+  if (!registry) {
+    GPBDebugCheckRuntimeVersion();
+    registry = [[GPBExtensionRegistry alloc] init];
+    [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
+    [registry addExtensions:[GPBTypeRoot extensionRegistry]];
+  }
+  return registry;
+}
+
+@end
+
+#pragma mark - GPBApiRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBApi
+
+@implementation GPBApi
+
+@dynamic name;
+@dynamic methodsArray, methodsArray_Count;
+@dynamic optionsArray, optionsArray_Count;
+@dynamic version;
+@dynamic hasSourceContext, sourceContext;
+@dynamic mixinsArray, mixinsArray_Count;
+@dynamic syntax;
+
+typedef struct GPBApi__storage_ {
+  uint32_t _has_storage_[1];
+  GPBSyntax syntax;
+  NSString *name;
+  NSMutableArray *methodsArray;
+  NSMutableArray *optionsArray;
+  NSString *version;
+  GPBSourceContext *sourceContext;
+  NSMutableArray *mixinsArray;
+} GPBApi__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBApi_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "methodsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod),
+        .number = GPBApi_FieldNumber_MethodsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBApi_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "version",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBApi_FieldNumber_Version,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, version),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "sourceContext",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .number = GPBApi_FieldNumber_SourceContext,
+        .hasIndex = 2,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "mixinsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin),
+        .number = GPBApi_FieldNumber_MixinsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "syntax",
+        .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+        .number = GPBApi_FieldNumber_Syntax,
+        .hasIndex = 3,
+        .offset = (uint32_t)offsetof(GPBApi__storage_, syntax),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBApi class]
+                                     rootClass:[GPBApiRoot class]
+                                          file:GPBApiRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBApi__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBApi_Syntax_RawValue(GPBApi *message) {
+  GPBDescriptor *descriptor = [GPBApi descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBApi descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - GPBMethod
+
+@implementation GPBMethod
+
+@dynamic name;
+@dynamic requestTypeURL;
+@dynamic requestStreaming;
+@dynamic responseTypeURL;
+@dynamic responseStreaming;
+@dynamic optionsArray, optionsArray_Count;
+@dynamic syntax;
+
+typedef struct GPBMethod__storage_ {
+  uint32_t _has_storage_[1];
+  GPBSyntax syntax;
+  NSString *name;
+  NSString *requestTypeURL;
+  NSString *responseTypeURL;
+  NSMutableArray *optionsArray;
+} GPBMethod__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMethod_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBMethod__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "requestTypeURL",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMethod_FieldNumber_RequestTypeURL,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL),
+        .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "requestStreaming",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMethod_FieldNumber_RequestStreaming,
+        .hasIndex = 2,
+        .offset = 3,  // Stored in _has_storage_ to save space.
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBool,
+      },
+      {
+        .name = "responseTypeURL",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMethod_FieldNumber_ResponseTypeURL,
+        .hasIndex = 4,
+        .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL),
+        .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "responseStreaming",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMethod_FieldNumber_ResponseStreaming,
+        .hasIndex = 5,
+        .offset = 6,  // Stored in _has_storage_ to save space.
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBool,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBMethod_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "syntax",
+        .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+        .number = GPBMethod_FieldNumber_Syntax,
+        .hasIndex = 7,
+        .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMethod class]
+                                     rootClass:[GPBApiRoot class]
+                                          file:GPBApiRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBMethod__storage_)
+                                         flags:0];
+#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    static const char *extraTextFormatInfo =
+        "\002\002\007\244\241!!\000\004\010\244\241!!\000";
+    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];
+#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) {
+  GPBDescriptor *descriptor = [GPBMethod descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBMethod descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - GPBMixin
+
+@implementation GPBMixin
+
+@dynamic name;
+@dynamic root;
+
+typedef struct GPBMixin__storage_ {
+  uint32_t _has_storage_[1];
+  NSString *name;
+  NSString *root;
+} GPBMixin__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMixin_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBMixin__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "root",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBMixin_FieldNumber_Root,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBMixin__storage_, root),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBMixin class]
+                                     rootClass:[GPBApiRoot class]
+                                          file:GPBApiRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBMixin__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.h
new file mode 100644
index 0000000..29888d6
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.h
@@ -0,0 +1,101 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBDurationRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBDurationRoot : GPBRootObject
+@end
+
+#pragma mark - GPBDuration
+
+typedef GPB_ENUM(GPBDuration_FieldNumber) {
+  GPBDuration_FieldNumber_Seconds = 1,
+  GPBDuration_FieldNumber_Nanos = 2,
+};
+
+/// A Duration represents a signed, fixed-length span of time represented
+/// as a count of seconds and fractions of seconds at nanosecond
+/// resolution. It is independent of any calendar and concepts like "day"
+/// or "month". It is related to Timestamp in that the difference between
+/// two Timestamp values is a Duration and it can be added or subtracted
+/// from a Timestamp. Range is approximately +-10,000 years.
+///
+/// Example 1: Compute Duration from two Timestamps in pseudo code.
+///
+///     Timestamp start = ...;
+///     Timestamp end = ...;
+///     Duration duration = ...;
+///
+///     duration.seconds = end.seconds - start.seconds;
+///     duration.nanos = end.nanos - start.nanos;
+///
+///     if (duration.seconds < 0 && duration.nanos > 0) {
+///       duration.seconds += 1;
+///       duration.nanos -= 1000000000;
+///     } else if (durations.seconds > 0 && duration.nanos < 0) {
+///       duration.seconds -= 1;
+///       duration.nanos += 1000000000;
+///     }
+///
+/// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+///
+///     Timestamp start = ...;
+///     Duration duration = ...;
+///     Timestamp end = ...;
+///
+///     end.seconds = start.seconds + duration.seconds;
+///     end.nanos = start.nanos + duration.nanos;
+///
+///     if (end.nanos < 0) {
+///       end.seconds -= 1;
+///       end.nanos += 1000000000;
+///     } else if (end.nanos >= 1000000000) {
+///       end.seconds += 1;
+///       end.nanos -= 1000000000;
+///     }
+@interface GPBDuration : GPBMessage
+
+/// Signed seconds of the span of time. Must be from -315,576,000,000
+/// to +315,576,000,000 inclusive.
+@property(nonatomic, readwrite) int64_t seconds;
+
+/// Signed fractions of a second at nanosecond resolution of the span
+/// of time. Durations less than one second are represented with a 0
+/// `seconds` field and a positive or negative `nanos` field. For durations
+/// of one second or more, a non-zero value for the `nanos` field must be
+/// of the same sign as the `seconds` field. Must be from -999,999,999
+/// to +999,999,999 inclusive.
+@property(nonatomic, readwrite) int32_t nanos;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.m
new file mode 100644
index 0000000..7dd6b64
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Duration.pbobjc.m
@@ -0,0 +1,88 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Duration.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBDurationRoot
+
+@implementation GPBDurationRoot
+
+@end
+
+#pragma mark - GPBDurationRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBDuration
+
+@implementation GPBDuration
+
+@dynamic seconds;
+@dynamic nanos;
+
+typedef struct GPBDuration__storage_ {
+  uint32_t _has_storage_[1];
+  int32_t nanos;
+  int64_t seconds;
+} GPBDuration__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "seconds",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBDuration_FieldNumber_Seconds,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt64,
+      },
+      {
+        .name = "nanos",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBDuration_FieldNumber_Nanos,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDuration class]
+                                     rootClass:[GPBDurationRoot class]
+                                          file:GPBDurationRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBDuration__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.h
new file mode 100644
index 0000000..f33db01
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.h
@@ -0,0 +1,53 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBEmptyRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBEmptyRoot : GPBRootObject
+@end
+
+#pragma mark - GPBEmpty
+
+/// A generic empty message that you can re-use to avoid defining duplicated
+/// empty messages in your APIs. A typical example is to use it as the request
+/// or the response type of an API method. For instance:
+///
+///     service Foo {
+///       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+///     }
+///
+/// The JSON representation for `Empty` is empty JSON object `{}`.
+@interface GPBEmpty : GPBMessage
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.m
new file mode 100644
index 0000000..88753aa
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Empty.pbobjc.m
@@ -0,0 +1,64 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Empty.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBEmptyRoot
+
+@implementation GPBEmptyRoot
+
+@end
+
+#pragma mark - GPBEmptyRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBEmpty
+
+@implementation GPBEmpty
+
+
+typedef struct GPBEmpty__storage_ {
+  uint32_t _has_storage_[1];
+} GPBEmpty__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEmpty class]
+                                     rootClass:[GPBEmptyRoot class]
+                                          file:GPBEmptyRoot_FileDescriptor()
+                                        fields:NULL
+                                    fieldCount:0
+                                   storageSize:sizeof(GPBEmpty__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.h
new file mode 100644
index 0000000..73cbd8a
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.h
@@ -0,0 +1,202 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBFieldMaskRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBFieldMaskRoot : GPBRootObject
+@end
+
+#pragma mark - GPBFieldMask
+
+typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
+  GPBFieldMask_FieldNumber_PathsArray = 1,
+};
+
+/// `FieldMask` represents a set of symbolic field paths, for example:
+///
+///     paths: "f.a"
+///     paths: "f.b.d"
+///
+/// Here `f` represents a field in some root message, `a` and `b`
+/// fields in the message found in `f`, and `d` a field found in the
+/// message in `f.b`.
+///
+/// Field masks are used to specify a subset of fields that should be
+/// returned by a get operation or modified by an update operation.
+/// Field masks also have a custom JSON encoding (see below).
+///
+/// # Field Masks in Projections
+///
+/// When used in the context of a projection, a response message or
+/// sub-message is filtered by the API to only contain those fields as
+/// specified in the mask. For example, if the mask in the previous
+/// example is applied to a response message as follows:
+///
+///     f {
+///       a : 22
+///       b {
+///         d : 1
+///         x : 2
+///       }
+///       y : 13
+///     }
+///     z: 8
+///
+/// The result will not contain specific values for fields x,y and z
+/// (their value will be set to the default, and omitted in proto text
+/// output):
+///
+///
+///     f {
+///       a : 22
+///       b {
+///         d : 1
+///       }
+///     }
+///
+/// A repeated field is not allowed except at the last position of a
+/// field mask.
+///
+/// If a FieldMask object is not present in a get operation, the
+/// operation applies to all fields (as if a FieldMask of all fields
+/// had been specified).
+///
+/// Note that a field mask does not necessarily apply to the
+/// top-level response message. In case of a REST get operation, the
+/// field mask applies directly to the response, but in case of a REST
+/// list operation, the mask instead applies to each individual message
+/// in the returned resource list. In case of a REST custom method,
+/// other definitions may be used. Where the mask applies will be
+/// clearly documented together with its declaration in the API.  In
+/// any case, the effect on the returned resource/resources is required
+/// behavior for APIs.
+///
+/// # Field Masks in Update Operations
+///
+/// A field mask in update operations specifies which fields of the
+/// targeted resource are going to be updated. The API is required
+/// to only change the values of the fields as specified in the mask
+/// and leave the others untouched. If a resource is passed in to
+/// describe the updated values, the API ignores the values of all
+/// fields not covered by the mask.
+///
+/// In order to reset a field's value to the default, the field must
+/// be in the mask and set to the default value in the provided resource.
+/// Hence, in order to reset all fields of a resource, provide a default
+/// instance of the resource and set all fields in the mask, or do
+/// not provide a mask as described below.
+///
+/// If a field mask is not present on update, the operation applies to
+/// all fields (as if a field mask of all fields has been specified).
+/// Note that in the presence of schema evolution, this may mean that
+/// fields the client does not know and has therefore not filled into
+/// the request will be reset to their default. If this is unwanted
+/// behavior, a specific service may require a client to always specify
+/// a field mask, producing an error if not.
+///
+/// As with get operations, the location of the resource which
+/// describes the updated values in the request message depends on the
+/// operation kind. In any case, the effect of the field mask is
+/// required to be honored by the API.
+///
+/// ## Considerations for HTTP REST
+///
+/// The HTTP kind of an update operation which uses a field mask must
+/// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+/// (PUT must only be used for full updates).
+///
+/// # JSON Encoding of Field Masks
+///
+/// In JSON, a field mask is encoded as a single string where paths are
+/// separated by a comma. Fields name in each path are converted
+/// to/from lower-camel naming conventions.
+///
+/// As an example, consider the following message declarations:
+///
+///     message Profile {
+///       User user = 1;
+///       Photo photo = 2;
+///     }
+///     message User {
+///       string display_name = 1;
+///       string address = 2;
+///     }
+///
+/// In proto a field mask for `Profile` may look as such:
+///
+///     mask {
+///       paths: "user.display_name"
+///       paths: "photo"
+///     }
+///
+/// In JSON, the same mask is represented as below:
+///
+///     {
+///       mask: "user.displayName,photo"
+///     }
+///
+/// # Field Masks and Oneof Fields
+///
+/// Field masks treat fields in oneofs just as regular fields. Consider the
+/// following message:
+///
+///     message SampleMessage {
+///       oneof test_oneof {
+///         string name = 4;
+///         SubMessage sub_message = 9;
+///       }
+///     }
+///
+/// The field mask can be:
+///
+///     mask {
+///       paths: "name"
+///     }
+///
+/// Or:
+///
+///     mask {
+///       paths: "sub_message"
+///     }
+///
+/// Note that oneof type names ("test_oneof" in this case) cannot be used in
+/// paths.
+@interface GPBFieldMask : GPBMessage
+
+/// The set of field mask paths.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *pathsArray;
+/// The number of items in @c pathsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger pathsArray_Count;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.m
new file mode 100644
index 0000000..8c241af
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/FieldMask.pbobjc.m
@@ -0,0 +1,77 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/FieldMask.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBFieldMaskRoot
+
+@implementation GPBFieldMaskRoot
+
+@end
+
+#pragma mark - GPBFieldMaskRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBFieldMask
+
+@implementation GPBFieldMask
+
+@dynamic pathsArray, pathsArray_Count;
+
+typedef struct GPBFieldMask__storage_ {
+  uint32_t _has_storage_[1];
+  NSMutableArray *pathsArray;
+} GPBFieldMask__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "pathsArray",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBFieldMask_FieldNumber_PathsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeString,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class]
+                                     rootClass:[GPBFieldMaskRoot class]
+                                          file:GPBFieldMaskRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBFieldMask__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.h
new file mode 100644
index 0000000..8775348
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.h
@@ -0,0 +1,54 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBSourceContextRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBSourceContextRoot : GPBRootObject
+@end
+
+#pragma mark - GPBSourceContext
+
+typedef GPB_ENUM(GPBSourceContext_FieldNumber) {
+  GPBSourceContext_FieldNumber_FileName = 1,
+};
+
+/// `SourceContext` represents information about the source of a
+/// protobuf element, like the file in which it is defined.
+@interface GPBSourceContext : GPBMessage
+
+/// The path-qualified name of the .proto file that contained the associated
+/// protobuf element.  For example: `"google/protobuf/source.proto"`.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.m
new file mode 100644
index 0000000..9500712
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/SourceContext.pbobjc.m
@@ -0,0 +1,77 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/SourceContext.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBSourceContextRoot
+
+@implementation GPBSourceContextRoot
+
+@end
+
+#pragma mark - GPBSourceContextRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBSourceContext
+
+@implementation GPBSourceContext
+
+@dynamic fileName;
+
+typedef struct GPBSourceContext__storage_ {
+  uint32_t _has_storage_[1];
+  NSString *fileName;
+} GPBSourceContext__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "fileName",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBSourceContext_FieldNumber_FileName,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class]
+                                     rootClass:[GPBSourceContextRoot class]
+                                          file:GPBSourceContextRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBSourceContext__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.h
new file mode 100644
index 0000000..3924b4b
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.h
@@ -0,0 +1,167 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+@class GPBListValue;
+@class GPBStruct;
+@class GPBValue;
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - Enum GPBNullValue
+
+/// `NullValue` is a singleton enumeration to represent the null value for the
+/// `Value` type union.
+///
+///  The JSON representation for `NullValue` is JSON `null`.
+typedef GPB_ENUM(GPBNullValue) {
+  /// Value used if any message's field encounters a value that is not defined
+  /// by this enum. The message will also have C functions to get/set the rawValue
+  /// of the field.
+  GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
+  /// Null value.
+  GPBNullValue_NullValue = 0,
+};
+
+GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void);
+
+/// Checks to see if the given value is defined by the enum or was not known at
+/// the time this source was generated.
+BOOL GPBNullValue_IsValidValue(int32_t value);
+
+#pragma mark - GPBStructRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBStructRoot : GPBRootObject
+@end
+
+#pragma mark - GPBStruct
+
+typedef GPB_ENUM(GPBStruct_FieldNumber) {
+  GPBStruct_FieldNumber_Fields = 1,
+};
+
+/// `Struct` represents a structured data value, consisting of fields
+/// which map to dynamically typed values. In some languages, `Struct`
+/// might be supported by a native representation. For example, in
+/// scripting languages like JS a struct is represented as an
+/// object. The details of that representation are described together
+/// with the proto support for the language.
+///
+/// The JSON representation for `Struct` is JSON object.
+@interface GPBStruct : GPBMessage
+
+/// Unordered map of dynamically typed values.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields;
+/// The number of items in @c fields without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger fields_Count;
+
+@end
+
+#pragma mark - GPBValue
+
+typedef GPB_ENUM(GPBValue_FieldNumber) {
+  GPBValue_FieldNumber_NullValue = 1,
+  GPBValue_FieldNumber_NumberValue = 2,
+  GPBValue_FieldNumber_StringValue = 3,
+  GPBValue_FieldNumber_BoolValue = 4,
+  GPBValue_FieldNumber_StructValue = 5,
+  GPBValue_FieldNumber_ListValue = 6,
+};
+
+typedef GPB_ENUM(GPBValue_Kind_OneOfCase) {
+  GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0,
+  GPBValue_Kind_OneOfCase_NullValue = 1,
+  GPBValue_Kind_OneOfCase_NumberValue = 2,
+  GPBValue_Kind_OneOfCase_StringValue = 3,
+  GPBValue_Kind_OneOfCase_BoolValue = 4,
+  GPBValue_Kind_OneOfCase_StructValue = 5,
+  GPBValue_Kind_OneOfCase_ListValue = 6,
+};
+
+/// `Value` represents a dynamically typed value which can be either
+/// null, a number, a string, a boolean, a recursive struct value, or a
+/// list of values. A producer of value is expected to set one of that
+/// variants, absence of any variant indicates an error.
+///
+/// The JSON representation for `Value` is JSON value.
+@interface GPBValue : GPBMessage
+
+/// The kind of value.
+@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase;
+
+/// Represents a null value.
+@property(nonatomic, readwrite) GPBNullValue nullValue;
+
+/// Represents a double value.
+@property(nonatomic, readwrite) double numberValue;
+
+/// Represents a string value.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue;
+
+/// Represents a boolean value.
+@property(nonatomic, readwrite) BOOL boolValue;
+
+/// Represents a structured value.
+@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue;
+
+/// Represents a repeated `Value`.
+@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue;
+
+@end
+
+/// Fetches the raw value of a @c GPBValue's @c nullValue property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBValue_NullValue_RawValue(GPBValue *message);
+/// Sets the raw value of an @c GPBValue's @c nullValue property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value);
+
+/// Clears whatever value was set for the oneof 'kind'.
+void GPBValue_ClearKindOneOfCase(GPBValue *message);
+
+#pragma mark - GPBListValue
+
+typedef GPB_ENUM(GPBListValue_FieldNumber) {
+  GPBListValue_FieldNumber_ValuesArray = 1,
+};
+
+/// `ListValue` is a wrapper around a repeated field of values.
+///
+/// The JSON representation for `ListValue` is JSON array.
+@interface GPBListValue : GPBMessage
+
+/// Repeated field of dynamically typed values.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBValue*> *valuesArray;
+/// The number of items in @c valuesArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger valuesArray_Count;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.m
new file mode 100644
index 0000000..6094002
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Struct.pbobjc.m
@@ -0,0 +1,273 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Struct.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBStructRoot
+
+@implementation GPBStructRoot
+
+@end
+
+#pragma mark - GPBStructRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - Enum GPBNullValue
+
+GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) {
+  static GPBEnumDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    static const char *valueNames =
+        "NullValue\000";
+    static const int32_t values[] = {
+        GPBNullValue_NullValue,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBNullValue_IsValidValue];
+    if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBNullValue_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBNullValue_NullValue:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+#pragma mark - GPBStruct
+
+@implementation GPBStruct
+
+@dynamic fields, fields_Count;
+
+typedef struct GPBStruct__storage_ {
+  uint32_t _has_storage_[1];
+  NSMutableDictionary *fields;
+} GPBStruct__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "fields",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
+        .number = GPBStruct_FieldNumber_Fields,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBStruct__storage_, fields),
+        .flags = GPBFieldMapKeyString,
+        .dataType = GPBDataTypeMessage,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBStruct class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBStruct__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBValue
+
+@implementation GPBValue
+
+@dynamic kindOneOfCase;
+@dynamic nullValue;
+@dynamic numberValue;
+@dynamic stringValue;
+@dynamic boolValue;
+@dynamic structValue;
+@dynamic listValue;
+
+typedef struct GPBValue__storage_ {
+  uint32_t _has_storage_[2];
+  GPBNullValue nullValue;
+  NSString *stringValue;
+  GPBStruct *structValue;
+  GPBListValue *listValue;
+  double numberValue;
+} GPBValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "nullValue",
+        .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor,
+        .number = GPBValue_FieldNumber_NullValue,
+        .hasIndex = -1,
+        .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+      {
+        .name = "numberValue",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBValue_FieldNumber_NumberValue,
+        .hasIndex = -1,
+        .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeDouble,
+      },
+      {
+        .name = "stringValue",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBValue_FieldNumber_StringValue,
+        .hasIndex = -1,
+        .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "boolValue",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBValue_FieldNumber_BoolValue,
+        .hasIndex = -1,
+        .offset = 0,  // Stored in _has_storage_ to save space.
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBool,
+      },
+      {
+        .name = "structValue",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct),
+        .number = GPBValue_FieldNumber_StructValue,
+        .hasIndex = -1,
+        .offset = (uint32_t)offsetof(GPBValue__storage_, structValue),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "listValue",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue),
+        .number = GPBValue_FieldNumber_ListValue,
+        .hasIndex = -1,
+        .offset = (uint32_t)offsetof(GPBValue__storage_, listValue),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBValue class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBValue__storage_)
+                                         flags:0];
+    static const char *oneofs[] = {
+      "kind",
+    };
+    [localDescriptor setupOneofs:oneofs
+                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))
+                   firstHasIndex:-1];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBValue_NullValue_RawValue(GPBValue *message) {
+  GPBDescriptor *descriptor = [GPBValue descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBValue descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+void GPBValue_ClearKindOneOfCase(GPBValue *message) {
+  GPBDescriptor *descriptor = [message descriptor];
+  GPBOneofDescriptor *oneof = descriptor->oneofs_[0];
+  GPBMaybeClearOneof(message, oneof, -1, 0);
+}
+#pragma mark - GPBListValue
+
+@implementation GPBListValue
+
+@dynamic valuesArray, valuesArray_Count;
+
+typedef struct GPBListValue__storage_ {
+  uint32_t _has_storage_[1];
+  NSMutableArray *valuesArray;
+} GPBListValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "valuesArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
+        .number = GPBListValue_FieldNumber_ValuesArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBListValue class]
+                                     rootClass:[GPBStructRoot class]
+                                          file:GPBStructRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBListValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.h
new file mode 100644
index 0000000..925dca8
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.h
@@ -0,0 +1,113 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBTimestampRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBTimestampRoot : GPBRootObject
+@end
+
+#pragma mark - GPBTimestamp
+
+typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
+  GPBTimestamp_FieldNumber_Seconds = 1,
+  GPBTimestamp_FieldNumber_Nanos = 2,
+};
+
+/// A Timestamp represents a point in time independent of any time zone
+/// or calendar, represented as seconds and fractions of seconds at
+/// nanosecond resolution in UTC Epoch time. It is encoded using the
+/// Proleptic Gregorian Calendar which extends the Gregorian calendar
+/// backwards to year one. It is encoded assuming all minutes are 60
+/// seconds long, i.e. leap seconds are "smeared" so that no leap second
+/// table is needed for interpretation. Range is from
+/// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+/// By restricting to that range, we ensure that we can convert to
+/// and from  RFC 3339 date strings.
+/// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+///
+/// Example 1: Compute Timestamp from POSIX `time()`.
+///
+///     Timestamp timestamp;
+///     timestamp.set_seconds(time(NULL));
+///     timestamp.set_nanos(0);
+///
+/// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+///
+///     struct timeval tv;
+///     gettimeofday(&tv, NULL);
+///
+///     Timestamp timestamp;
+///     timestamp.set_seconds(tv.tv_sec);
+///     timestamp.set_nanos(tv.tv_usec * 1000);
+///
+/// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+///
+///     FILETIME ft;
+///     GetSystemTimeAsFileTime(&ft);
+///     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+///
+///     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+///     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+///     Timestamp timestamp;
+///     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+///     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+///
+/// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+///
+///     long millis = System.currentTimeMillis();
+///
+///     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+///         .setNanos((int) ((millis % 1000) * 1000000)).build();
+///
+///
+/// Example 5: Compute Timestamp from current time in Python.
+///
+///     now = time.time()
+///     seconds = int(now)
+///     nanos = int((now - seconds) * 10**9)
+///     timestamp = Timestamp(seconds=seconds, nanos=nanos)
+@interface GPBTimestamp : GPBMessage
+
+/// Represents seconds of UTC time since Unix epoch
+/// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+/// 9999-12-31T23:59:59Z inclusive.
+@property(nonatomic, readwrite) int64_t seconds;
+
+/// Non-negative fractions of a second at nanosecond resolution. Negative
+/// second values with fractions must still have non-negative nanos values
+/// that count forward in time. Must be from 0 to 999,999,999
+/// inclusive.
+@property(nonatomic, readwrite) int32_t nanos;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.m
new file mode 100644
index 0000000..f35e435
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Timestamp.pbobjc.m
@@ -0,0 +1,88 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Timestamp.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBTimestampRoot
+
+@implementation GPBTimestampRoot
+
+@end
+
+#pragma mark - GPBTimestampRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBTimestamp
+
+@implementation GPBTimestamp
+
+@dynamic seconds;
+@dynamic nanos;
+
+typedef struct GPBTimestamp__storage_ {
+  uint32_t _has_storage_[1];
+  int32_t nanos;
+  int64_t seconds;
+} GPBTimestamp__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "seconds",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBTimestamp_FieldNumber_Seconds,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt64,
+      },
+      {
+        .name = "nanos",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBTimestamp_FieldNumber_Nanos,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class]
+                                     rootClass:[GPBTimestampRoot class]
+                                          file:GPBTimestampRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBTimestamp__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.h
new file mode 100644
index 0000000..590d970
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.h
@@ -0,0 +1,373 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+@class GPBAny;
+@class GPBEnumValue;
+@class GPBField;
+@class GPBOption;
+@class GPBSourceContext;
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - Enum GPBSyntax
+
+/// The syntax in which a protocol buffer element is defined.
+typedef GPB_ENUM(GPBSyntax) {
+  /// Value used if any message's field encounters a value that is not defined
+  /// by this enum. The message will also have C functions to get/set the rawValue
+  /// of the field.
+  GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
+  /// Syntax `proto2`.
+  GPBSyntax_SyntaxProto2 = 0,
+
+  /// Syntax `proto3`.
+  GPBSyntax_SyntaxProto3 = 1,
+};
+
+GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void);
+
+/// Checks to see if the given value is defined by the enum or was not known at
+/// the time this source was generated.
+BOOL GPBSyntax_IsValidValue(int32_t value);
+
+#pragma mark - Enum GPBField_Kind
+
+/// Basic field types.
+typedef GPB_ENUM(GPBField_Kind) {
+  /// Value used if any message's field encounters a value that is not defined
+  /// by this enum. The message will also have C functions to get/set the rawValue
+  /// of the field.
+  GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
+  /// Field type unknown.
+  GPBField_Kind_TypeUnknown = 0,
+
+  /// Field type double.
+  GPBField_Kind_TypeDouble = 1,
+
+  /// Field type float.
+  GPBField_Kind_TypeFloat = 2,
+
+  /// Field type int64.
+  GPBField_Kind_TypeInt64 = 3,
+
+  /// Field type uint64.
+  GPBField_Kind_TypeUint64 = 4,
+
+  /// Field type int32.
+  GPBField_Kind_TypeInt32 = 5,
+
+  /// Field type fixed64.
+  GPBField_Kind_TypeFixed64 = 6,
+
+  /// Field type fixed32.
+  GPBField_Kind_TypeFixed32 = 7,
+
+  /// Field type bool.
+  GPBField_Kind_TypeBool = 8,
+
+  /// Field type string.
+  GPBField_Kind_TypeString = 9,
+
+  /// Field type group. Proto2 syntax only, and deprecated.
+  GPBField_Kind_TypeGroup = 10,
+
+  /// Field type message.
+  GPBField_Kind_TypeMessage = 11,
+
+  /// Field type bytes.
+  GPBField_Kind_TypeBytes = 12,
+
+  /// Field type uint32.
+  GPBField_Kind_TypeUint32 = 13,
+
+  /// Field type enum.
+  GPBField_Kind_TypeEnum = 14,
+
+  /// Field type sfixed32.
+  GPBField_Kind_TypeSfixed32 = 15,
+
+  /// Field type sfixed64.
+  GPBField_Kind_TypeSfixed64 = 16,
+
+  /// Field type sint32.
+  GPBField_Kind_TypeSint32 = 17,
+
+  /// Field type sint64.
+  GPBField_Kind_TypeSint64 = 18,
+};
+
+GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void);
+
+/// Checks to see if the given value is defined by the enum or was not known at
+/// the time this source was generated.
+BOOL GPBField_Kind_IsValidValue(int32_t value);
+
+#pragma mark - Enum GPBField_Cardinality
+
+/// Whether a field is optional, required, or repeated.
+typedef GPB_ENUM(GPBField_Cardinality) {
+  /// Value used if any message's field encounters a value that is not defined
+  /// by this enum. The message will also have C functions to get/set the rawValue
+  /// of the field.
+  GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
+  /// For fields with unknown cardinality.
+  GPBField_Cardinality_CardinalityUnknown = 0,
+
+  /// For optional fields.
+  GPBField_Cardinality_CardinalityOptional = 1,
+
+  /// For required fields. Proto2 syntax only.
+  GPBField_Cardinality_CardinalityRequired = 2,
+
+  /// For repeated fields.
+  GPBField_Cardinality_CardinalityRepeated = 3,
+};
+
+GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void);
+
+/// Checks to see if the given value is defined by the enum or was not known at
+/// the time this source was generated.
+BOOL GPBField_Cardinality_IsValidValue(int32_t value);
+
+#pragma mark - GPBTypeRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBTypeRoot : GPBRootObject
+@end
+
+#pragma mark - GPBType
+
+typedef GPB_ENUM(GPBType_FieldNumber) {
+  GPBType_FieldNumber_Name = 1,
+  GPBType_FieldNumber_FieldsArray = 2,
+  GPBType_FieldNumber_OneofsArray = 3,
+  GPBType_FieldNumber_OptionsArray = 4,
+  GPBType_FieldNumber_SourceContext = 5,
+  GPBType_FieldNumber_Syntax = 6,
+};
+
+/// A protocol buffer message type.
+@interface GPBType : GPBMessage
+
+/// The fully qualified message name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// The list of fields.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBField*> *fieldsArray;
+/// The number of items in @c fieldsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger fieldsArray_Count;
+
+/// The list of types appearing in `oneof` definitions in this type.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *oneofsArray;
+/// The number of items in @c oneofsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger oneofsArray_Count;
+
+/// The protocol buffer options.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+/// The source context.
+@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+/// Test to see if @c sourceContext has been set.
+@property(nonatomic, readwrite) BOOL hasSourceContext;
+
+/// The source syntax.
+@property(nonatomic, readwrite) GPBSyntax syntax;
+
+@end
+
+/// Fetches the raw value of a @c GPBType's @c syntax property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBType_Syntax_RawValue(GPBType *message);
+/// Sets the raw value of an @c GPBType's @c syntax property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value);
+
+#pragma mark - GPBField
+
+typedef GPB_ENUM(GPBField_FieldNumber) {
+  GPBField_FieldNumber_Kind = 1,
+  GPBField_FieldNumber_Cardinality = 2,
+  GPBField_FieldNumber_Number = 3,
+  GPBField_FieldNumber_Name = 4,
+  GPBField_FieldNumber_TypeURL = 6,
+  GPBField_FieldNumber_OneofIndex = 7,
+  GPBField_FieldNumber_Packed = 8,
+  GPBField_FieldNumber_OptionsArray = 9,
+  GPBField_FieldNumber_JsonName = 10,
+  GPBField_FieldNumber_DefaultValue = 11,
+};
+
+/// A single field of a message type.
+@interface GPBField : GPBMessage
+
+/// The field type.
+@property(nonatomic, readwrite) GPBField_Kind kind;
+
+/// The field cardinality.
+@property(nonatomic, readwrite) GPBField_Cardinality cardinality;
+
+/// The field number.
+@property(nonatomic, readwrite) int32_t number;
+
+/// The field name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// The field type URL, without the scheme, for message or enumeration
+/// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
+
+/// The index of the field type in `Type.oneofs`, for message or enumeration
+/// types. The first type has index 1; zero means the type is not in the list.
+@property(nonatomic, readwrite) int32_t oneofIndex;
+
+/// Whether to use alternative packed wire representation.
+@property(nonatomic, readwrite) BOOL packed;
+
+/// The protocol buffer options.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+/// The field JSON name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName;
+
+/// The string value of the default value of this field. Proto2 syntax only.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue;
+
+@end
+
+/// Fetches the raw value of a @c GPBField's @c kind property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBField_Kind_RawValue(GPBField *message);
+/// Sets the raw value of an @c GPBField's @c kind property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBField_Kind_RawValue(GPBField *message, int32_t value);
+
+/// Fetches the raw value of a @c GPBField's @c cardinality property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBField_Cardinality_RawValue(GPBField *message);
+/// Sets the raw value of an @c GPBField's @c cardinality property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value);
+
+#pragma mark - GPBEnum
+
+typedef GPB_ENUM(GPBEnum_FieldNumber) {
+  GPBEnum_FieldNumber_Name = 1,
+  GPBEnum_FieldNumber_EnumvalueArray = 2,
+  GPBEnum_FieldNumber_OptionsArray = 3,
+  GPBEnum_FieldNumber_SourceContext = 4,
+  GPBEnum_FieldNumber_Syntax = 5,
+};
+
+/// Enum type definition.
+@interface GPBEnum : GPBMessage
+
+/// Enum type name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// Enum value definitions.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumValue*> *enumvalueArray;
+/// The number of items in @c enumvalueArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
+
+/// Protocol buffer options.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+/// The source context.
+@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+/// Test to see if @c sourceContext has been set.
+@property(nonatomic, readwrite) BOOL hasSourceContext;
+
+/// The source syntax.
+@property(nonatomic, readwrite) GPBSyntax syntax;
+
+@end
+
+/// Fetches the raw value of a @c GPBEnum's @c syntax property, even
+/// if the value was not defined by the enum at the time the code was generated.
+int32_t GPBEnum_Syntax_RawValue(GPBEnum *message);
+/// Sets the raw value of an @c GPBEnum's @c syntax property, allowing
+/// it to be set to a value that was not defined by the enum at the time the code
+/// was generated.
+void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value);
+
+#pragma mark - GPBEnumValue
+
+typedef GPB_ENUM(GPBEnumValue_FieldNumber) {
+  GPBEnumValue_FieldNumber_Name = 1,
+  GPBEnumValue_FieldNumber_Number = 2,
+  GPBEnumValue_FieldNumber_OptionsArray = 3,
+};
+
+/// Enum value definition.
+@interface GPBEnumValue : GPBMessage
+
+/// Enum value name.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// Enum value number.
+@property(nonatomic, readwrite) int32_t number;
+
+/// Protocol buffer options.
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
+/// The number of items in @c optionsArray without causing the array to be created.
+@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+
+@end
+
+#pragma mark - GPBOption
+
+typedef GPB_ENUM(GPBOption_FieldNumber) {
+  GPBOption_FieldNumber_Name = 1,
+  GPBOption_FieldNumber_Value = 2,
+};
+
+/// A protocol buffer option, which can be attached to a message, field,
+/// enumeration, etc.
+@interface GPBOption : GPBMessage
+
+/// The option's name. For example, `"java_package"`.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+/// The option's value. For example, `"com.google.protobuf"`.
+@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value;
+/// Test to see if @c value has been set.
+@property(nonatomic, readwrite) BOOL hasValue;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.m
new file mode 100644
index 0000000..5554a22
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Type.pbobjc.m
@@ -0,0 +1,693 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Type.pbobjc.h"
+#import "google/protobuf/Any.pbobjc.h"
+#import "google/protobuf/SourceContext.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBTypeRoot
+
+@implementation GPBTypeRoot
+
++ (GPBExtensionRegistry*)extensionRegistry {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety and initialization of registry.
+  static GPBExtensionRegistry* registry = nil;
+  if (!registry) {
+    GPBDebugCheckRuntimeVersion();
+    registry = [[GPBExtensionRegistry alloc] init];
+    [registry addExtensions:[GPBAnyRoot extensionRegistry]];
+    [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
+  }
+  return registry;
+}
+
+@end
+
+#pragma mark - GPBTypeRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - Enum GPBSyntax
+
+GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) {
+  static GPBEnumDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    static const char *valueNames =
+        "SyntaxProto2\000SyntaxProto3\000";
+    static const int32_t values[] = {
+        GPBSyntax_SyntaxProto2,
+        GPBSyntax_SyntaxProto3,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBSyntax_IsValidValue];
+    if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBSyntax_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBSyntax_SyntaxProto2:
+    case GPBSyntax_SyntaxProto3:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+#pragma mark - GPBType
+
+@implementation GPBType
+
+@dynamic name;
+@dynamic fieldsArray, fieldsArray_Count;
+@dynamic oneofsArray, oneofsArray_Count;
+@dynamic optionsArray, optionsArray_Count;
+@dynamic hasSourceContext, sourceContext;
+@dynamic syntax;
+
+typedef struct GPBType__storage_ {
+  uint32_t _has_storage_[1];
+  GPBSyntax syntax;
+  NSString *name;
+  NSMutableArray *fieldsArray;
+  NSMutableArray *oneofsArray;
+  NSMutableArray *optionsArray;
+  GPBSourceContext *sourceContext;
+} GPBType__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBType_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBType__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "fieldsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBField),
+        .number = GPBType_FieldNumber_FieldsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "oneofsArray",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBType_FieldNumber_OneofsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBType_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "sourceContext",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .number = GPBType_FieldNumber_SourceContext,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "syntax",
+        .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+        .number = GPBType_FieldNumber_Syntax,
+        .hasIndex = 2,
+        .offset = (uint32_t)offsetof(GPBType__storage_, syntax),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBType class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBType__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBType_Syntax_RawValue(GPBType *message) {
+  GPBDescriptor *descriptor = [GPBType descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBType descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - GPBField
+
+@implementation GPBField
+
+@dynamic kind;
+@dynamic cardinality;
+@dynamic number;
+@dynamic name;
+@dynamic typeURL;
+@dynamic oneofIndex;
+@dynamic packed;
+@dynamic optionsArray, optionsArray_Count;
+@dynamic jsonName;
+@dynamic defaultValue;
+
+typedef struct GPBField__storage_ {
+  uint32_t _has_storage_[1];
+  GPBField_Kind kind;
+  GPBField_Cardinality cardinality;
+  int32_t number;
+  int32_t oneofIndex;
+  NSString *name;
+  NSString *typeURL;
+  NSMutableArray *optionsArray;
+  NSString *jsonName;
+  NSString *defaultValue;
+} GPBField__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "kind",
+        .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor,
+        .number = GPBField_FieldNumber_Kind,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBField__storage_, kind),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+      {
+        .name = "cardinality",
+        .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor,
+        .number = GPBField_FieldNumber_Cardinality,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBField__storage_, cardinality),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+      {
+        .name = "number",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_Number,
+        .hasIndex = 2,
+        .offset = (uint32_t)offsetof(GPBField__storage_, number),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_Name,
+        .hasIndex = 3,
+        .offset = (uint32_t)offsetof(GPBField__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "typeURL",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_TypeURL,
+        .hasIndex = 4,
+        .offset = (uint32_t)offsetof(GPBField__storage_, typeURL),
+        .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "oneofIndex",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_OneofIndex,
+        .hasIndex = 5,
+        .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+      {
+        .name = "packed",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_Packed,
+        .hasIndex = 6,
+        .offset = 7,  // Stored in _has_storage_ to save space.
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBool,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBField_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "jsonName",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_JsonName,
+        .hasIndex = 8,
+        .offset = (uint32_t)offsetof(GPBField__storage_, jsonName),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "defaultValue",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBField_FieldNumber_DefaultValue,
+        .hasIndex = 9,
+        .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBField class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBField__storage_)
+                                         flags:0];
+#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    static const char *extraTextFormatInfo =
+        "\001\006\004\241!!\000";
+    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];
+#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBField_Kind_RawValue(GPBField *message) {
+  GPBDescriptor *descriptor = [GPBField descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBField descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+int32_t GPBField_Cardinality_RawValue(GPBField *message) {
+  GPBDescriptor *descriptor = [GPBField descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBField descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - Enum GPBField_Kind
+
+GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) {
+  static GPBEnumDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    static const char *valueNames =
+        "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt"
+        "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type"
+        "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty"
+        "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000"
+        "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ"
+        "eSint64\000";
+    static const int32_t values[] = {
+        GPBField_Kind_TypeUnknown,
+        GPBField_Kind_TypeDouble,
+        GPBField_Kind_TypeFloat,
+        GPBField_Kind_TypeInt64,
+        GPBField_Kind_TypeUint64,
+        GPBField_Kind_TypeInt32,
+        GPBField_Kind_TypeFixed64,
+        GPBField_Kind_TypeFixed32,
+        GPBField_Kind_TypeBool,
+        GPBField_Kind_TypeString,
+        GPBField_Kind_TypeGroup,
+        GPBField_Kind_TypeMessage,
+        GPBField_Kind_TypeBytes,
+        GPBField_Kind_TypeUint32,
+        GPBField_Kind_TypeEnum,
+        GPBField_Kind_TypeSfixed32,
+        GPBField_Kind_TypeSfixed64,
+        GPBField_Kind_TypeSint32,
+        GPBField_Kind_TypeSint64,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBField_Kind_IsValidValue];
+    if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBField_Kind_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBField_Kind_TypeUnknown:
+    case GPBField_Kind_TypeDouble:
+    case GPBField_Kind_TypeFloat:
+    case GPBField_Kind_TypeInt64:
+    case GPBField_Kind_TypeUint64:
+    case GPBField_Kind_TypeInt32:
+    case GPBField_Kind_TypeFixed64:
+    case GPBField_Kind_TypeFixed32:
+    case GPBField_Kind_TypeBool:
+    case GPBField_Kind_TypeString:
+    case GPBField_Kind_TypeGroup:
+    case GPBField_Kind_TypeMessage:
+    case GPBField_Kind_TypeBytes:
+    case GPBField_Kind_TypeUint32:
+    case GPBField_Kind_TypeEnum:
+    case GPBField_Kind_TypeSfixed32:
+    case GPBField_Kind_TypeSfixed64:
+    case GPBField_Kind_TypeSint32:
+    case GPBField_Kind_TypeSint64:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+#pragma mark - Enum GPBField_Cardinality
+
+GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) {
+  static GPBEnumDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    static const char *valueNames =
+        "CardinalityUnknown\000CardinalityOptional\000C"
+        "ardinalityRequired\000CardinalityRepeated\000";
+    static const int32_t values[] = {
+        GPBField_Cardinality_CardinalityUnknown,
+        GPBField_Cardinality_CardinalityOptional,
+        GPBField_Cardinality_CardinalityRequired,
+        GPBField_Cardinality_CardinalityRepeated,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBField_Cardinality_IsValidValue];
+    if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBField_Cardinality_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBField_Cardinality_CardinalityUnknown:
+    case GPBField_Cardinality_CardinalityOptional:
+    case GPBField_Cardinality_CardinalityRequired:
+    case GPBField_Cardinality_CardinalityRepeated:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+#pragma mark - GPBEnum
+
+@implementation GPBEnum
+
+@dynamic name;
+@dynamic enumvalueArray, enumvalueArray_Count;
+@dynamic optionsArray, optionsArray_Count;
+@dynamic hasSourceContext, sourceContext;
+@dynamic syntax;
+
+typedef struct GPBEnum__storage_ {
+  uint32_t _has_storage_[1];
+  GPBSyntax syntax;
+  NSString *name;
+  NSMutableArray *enumvalueArray;
+  NSMutableArray *optionsArray;
+  GPBSourceContext *sourceContext;
+} GPBEnum__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBEnum_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBEnum__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "enumvalueArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue),
+        .number = GPBEnum_FieldNumber_EnumvalueArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBEnum_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "sourceContext",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
+        .number = GPBEnum_FieldNumber_SourceContext,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+      {
+        .name = "syntax",
+        .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+        .number = GPBEnum_FieldNumber_Syntax,
+        .hasIndex = 2,
+        .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax),
+        .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+        .dataType = GPBDataTypeEnum,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnum class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBEnum__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) {
+  GPBDescriptor *descriptor = [GPBEnum descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
+  return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) {
+  GPBDescriptor *descriptor = [GPBEnum descriptor];
+  GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
+  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - GPBEnumValue
+
+@implementation GPBEnumValue
+
+@dynamic name;
+@dynamic number;
+@dynamic optionsArray, optionsArray_Count;
+
+typedef struct GPBEnumValue__storage_ {
+  uint32_t _has_storage_[1];
+  int32_t number;
+  NSString *name;
+  NSMutableArray *optionsArray;
+} GPBEnumValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBEnumValue_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "number",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBEnumValue_FieldNumber_Number,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+      {
+        .name = "optionsArray",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
+        .number = GPBEnumValue_FieldNumber_OptionsArray,
+        .hasIndex = GPBNoHasBit,
+        .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray),
+        .flags = GPBFieldRepeated,
+        .dataType = GPBDataTypeMessage,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBEnumValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBOption
+
+@implementation GPBOption
+
+@dynamic name;
+@dynamic hasValue, value;
+
+typedef struct GPBOption__storage_ {
+  uint32_t _has_storage_[1];
+  NSString *name;
+  GPBAny *value;
+} GPBOption__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "name",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBOption_FieldNumber_Name,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBOption__storage_, name),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+      {
+        .name = "value",
+        .dataTypeSpecific.className = GPBStringifySymbol(GPBAny),
+        .number = GPBOption_FieldNumber_Value,
+        .hasIndex = 1,
+        .offset = (uint32_t)offsetof(GPBOption__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeMessage,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBOption class]
+                                     rootClass:[GPBTypeRoot class]
+                                          file:GPBTypeRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBOption__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.h b/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.h
new file mode 100644
index 0000000..4651050
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.h
@@ -0,0 +1,182 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
+#endif
+
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+CF_EXTERN_C_BEGIN
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - GPBWrappersRoot
+
+/// Exposes the extension registry for this file.
+///
+/// The base class provides:
+/// @code
+///   + (GPBExtensionRegistry *)extensionRegistry;
+/// @endcode
+/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
+/// this file and all files that it depends on.
+@interface GPBWrappersRoot : GPBRootObject
+@end
+
+#pragma mark - GPBDoubleValue
+
+typedef GPB_ENUM(GPBDoubleValue_FieldNumber) {
+  GPBDoubleValue_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `double`.
+///
+/// The JSON representation for `DoubleValue` is JSON number.
+@interface GPBDoubleValue : GPBMessage
+
+/// The double value.
+@property(nonatomic, readwrite) double value;
+
+@end
+
+#pragma mark - GPBFloatValue
+
+typedef GPB_ENUM(GPBFloatValue_FieldNumber) {
+  GPBFloatValue_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `float`.
+///
+/// The JSON representation for `FloatValue` is JSON number.
+@interface GPBFloatValue : GPBMessage
+
+/// The float value.
+@property(nonatomic, readwrite) float value;
+
+@end
+
+#pragma mark - GPBInt64Value
+
+typedef GPB_ENUM(GPBInt64Value_FieldNumber) {
+  GPBInt64Value_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `int64`.
+///
+/// The JSON representation for `Int64Value` is JSON string.
+@interface GPBInt64Value : GPBMessage
+
+/// The int64 value.
+@property(nonatomic, readwrite) int64_t value;
+
+@end
+
+#pragma mark - GPBUInt64Value
+
+typedef GPB_ENUM(GPBUInt64Value_FieldNumber) {
+  GPBUInt64Value_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `uint64`.
+///
+/// The JSON representation for `UInt64Value` is JSON string.
+@interface GPBUInt64Value : GPBMessage
+
+/// The uint64 value.
+@property(nonatomic, readwrite) uint64_t value;
+
+@end
+
+#pragma mark - GPBInt32Value
+
+typedef GPB_ENUM(GPBInt32Value_FieldNumber) {
+  GPBInt32Value_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `int32`.
+///
+/// The JSON representation for `Int32Value` is JSON number.
+@interface GPBInt32Value : GPBMessage
+
+/// The int32 value.
+@property(nonatomic, readwrite) int32_t value;
+
+@end
+
+#pragma mark - GPBUInt32Value
+
+typedef GPB_ENUM(GPBUInt32Value_FieldNumber) {
+  GPBUInt32Value_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `uint32`.
+///
+/// The JSON representation for `UInt32Value` is JSON number.
+@interface GPBUInt32Value : GPBMessage
+
+/// The uint32 value.
+@property(nonatomic, readwrite) uint32_t value;
+
+@end
+
+#pragma mark - GPBBoolValue
+
+typedef GPB_ENUM(GPBBoolValue_FieldNumber) {
+  GPBBoolValue_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `bool`.
+///
+/// The JSON representation for `BoolValue` is JSON `true` and `false`.
+@interface GPBBoolValue : GPBMessage
+
+/// The bool value.
+@property(nonatomic, readwrite) BOOL value;
+
+@end
+
+#pragma mark - GPBStringValue
+
+typedef GPB_ENUM(GPBStringValue_FieldNumber) {
+  GPBStringValue_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `string`.
+///
+/// The JSON representation for `StringValue` is JSON string.
+@interface GPBStringValue : GPBMessage
+
+/// The string value.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *value;
+
+@end
+
+#pragma mark - GPBBytesValue
+
+typedef GPB_ENUM(GPBBytesValue_FieldNumber) {
+  GPBBytesValue_FieldNumber_Value = 1,
+};
+
+/// Wrapper message for `bytes`.
+///
+/// The JSON representation for `BytesValue` is JSON string.
+@interface GPBBytesValue : GPBMessage
+
+/// The bytes value.
+@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+CF_EXTERN_C_END
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.m b/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.m
new file mode 100644
index 0000000..5cc6c2e
--- /dev/null
+++ b/src/third_party/protobuf-3/objectivec/google/protobuf/Wrappers.pbobjc.m
@@ -0,0 +1,420 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+#import "google/protobuf/Wrappers.pbobjc.h"
+// @@protoc_insertion_point(imports)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#pragma mark - GPBWrappersRoot
+
+@implementation GPBWrappersRoot
+
+@end
+
+#pragma mark - GPBWrappersRoot_FileDescriptor
+
+static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) {
+  // This is called by +initialize so there is no need to worry
+  // about thread safety of the singleton.
+  static GPBFileDescriptor *descriptor = NULL;
+  if (!descriptor) {
+    GPBDebugCheckRuntimeVersion();
+    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+                                                     syntax:GPBFileSyntaxProto3];
+  }
+  return descriptor;
+}
+
+#pragma mark - GPBDoubleValue
+
+@implementation GPBDoubleValue
+
+@dynamic value;
+
+typedef struct GPBDoubleValue__storage_ {
+  uint32_t _has_storage_[1];
+  double value;
+} GPBDoubleValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBDoubleValue_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeDouble,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBDoubleValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBFloatValue
+
+@implementation GPBFloatValue
+
+@dynamic value;
+
+typedef struct GPBFloatValue__storage_ {
+  uint32_t _has_storage_[1];
+  float value;
+} GPBFloatValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBFloatValue_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeFloat,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBFloatValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBInt64Value
+
+@implementation GPBInt64Value
+
+@dynamic value;
+
+typedef struct GPBInt64Value__storage_ {
+  uint32_t _has_storage_[1];
+  int64_t value;
+} GPBInt64Value__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBInt64Value_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt64,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBInt64Value__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBUInt64Value
+
+@implementation GPBUInt64Value
+
+@dynamic value;
+
+typedef struct GPBUInt64Value__storage_ {
+  uint32_t _has_storage_[1];
+  uint64_t value;
+} GPBUInt64Value__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBUInt64Value_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeUInt64,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBUInt64Value__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBInt32Value
+
+@implementation GPBInt32Value
+
+@dynamic value;
+
+typedef struct GPBInt32Value__storage_ {
+  uint32_t _has_storage_[1];
+  int32_t value;
+} GPBInt32Value__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBInt32Value_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeInt32,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBInt32Value__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBUInt32Value
+
+@implementation GPBUInt32Value
+
+@dynamic value;
+
+typedef struct GPBUInt32Value__storage_ {
+  uint32_t _has_storage_[1];
+  uint32_t value;
+} GPBUInt32Value__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBUInt32Value_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeUInt32,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBUInt32Value__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBBoolValue
+
+@implementation GPBBoolValue
+
+@dynamic value;
+
+typedef struct GPBBoolValue__storage_ {
+  uint32_t _has_storage_[1];
+} GPBBoolValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBBoolValue_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = 1,  // Stored in _has_storage_ to save space.
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBool,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBBoolValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBStringValue
+
+@implementation GPBStringValue
+
+@dynamic value;
+
+typedef struct GPBStringValue__storage_ {
+  uint32_t _has_storage_[1];
+  NSString *value;
+} GPBStringValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBStringValue_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBStringValue__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeString,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBStringValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBStringValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+#pragma mark - GPBBytesValue
+
+@implementation GPBBytesValue
+
+@dynamic value;
+
+typedef struct GPBBytesValue__storage_ {
+  uint32_t _has_storage_[1];
+  NSData *value;
+} GPBBytesValue__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+  static GPBDescriptor *descriptor = nil;
+  if (!descriptor) {
+    static GPBMessageFieldDescription fields[] = {
+      {
+        .name = "value",
+        .dataTypeSpecific.className = NULL,
+        .number = GPBBytesValue_FieldNumber_Value,
+        .hasIndex = 0,
+        .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value),
+        .flags = GPBFieldOptional,
+        .dataType = GPBDataTypeBytes,
+      },
+    };
+    GPBDescriptor *localDescriptor =
+        [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class]
+                                     rootClass:[GPBWrappersRoot class]
+                                          file:GPBWrappersRoot_FileDescriptor()
+                                        fields:fields
+                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                                   storageSize:sizeof(GPBBytesValue__storage_)
+                                         flags:0];
+    NSAssert(descriptor == nil, @"Startup recursed!");
+    descriptor = localDescriptor;
+  }
+  return descriptor;
+}
+
+@end
+
+
+#pragma clang diagnostic pop
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/patches/0003-remove-static-initializers.patch b/src/third_party/protobuf-3/patches/0003-remove-static-initializers.patch
new file mode 100644
index 0000000..d5b6bae
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0003-remove-static-initializers.patch
@@ -0,0 +1,60 @@
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/stubs/status.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/stubs/status.cc	2016-03-31 13:25:40.888006485 -0700
+@@ -82,9 +82,9 @@
+ }
+ }  // namespace error.
+ 
+-const Status Status::OK = Status();
+-const Status Status::CANCELLED = Status(error::CANCELLED, "");
+-const Status Status::UNKNOWN = Status(error::UNKNOWN, "");
++const StatusPod Status::OK = { error::OK };
++const StatusPod Status::CANCELLED = { error::CANCELLED };
++const StatusPod Status::UNKNOWN = { error::UNKNOWN };
+ 
+ Status::Status() : error_code_(error::OK) {
+ }
+@@ -100,6 +100,9 @@
+     : error_code_(other.error_code_), error_message_(other.error_message_) {
+ }
+ 
++Status::Status(const StatusPod& status_pod) : error_code_(status_pod.code) {
++}
++
+ Status& Status::operator=(const Status& other) {
+   error_code_ = other.error_code_;
+   error_message_ = other.error_message_;
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/stubs/status.h	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/stubs/status.h	2016-03-31 13:25:40.888006485 -0700
+@@ -62,6 +62,10 @@
+ };
+ }  // namespace error
+ 
++struct StatusPod {
++  error::Code code;
++};
++
+ class LIBPROTOBUF_EXPORT Status {
+  public:
+   // Creates a "successful" status.
+@@ -73,13 +77,14 @@
+   // constructed.
+   Status(error::Code error_code, StringPiece error_message);
+   Status(const Status&);
++  Status(const StatusPod&);
+   Status& operator=(const Status& x);
+   ~Status() {}
+ 
+   // Some pre-defined Status objects
+-  static const Status OK;             // Identical to 0-arg constructor
+-  static const Status CANCELLED;
+-  static const Status UNKNOWN;
++  static const StatusPod OK;
++  static const StatusPod CANCELLED;
++  static const StatusPod UNKNOWN;
+ 
+   // Accessor
+   bool ok() const {
+only in patch2:
+unchanged:
diff --git a/src/third_party/protobuf-3/patches/0004-fix-integer-types-and-shared-library-exports.patch b/src/third_party/protobuf-3/patches/0004-fix-integer-types-and-shared-library-exports.patch
new file mode 100644
index 0000000..0845553
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0004-fix-integer-types-and-shared-library-exports.patch
@@ -0,0 +1,84 @@
+--- protobuf-cleaned/src/google/protobuf/stubs/port.h	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/stubs/port.h	2016-03-31 13:25:26.840024811 -0700
+@@ -66,18 +66,34 @@
+     #define PROTOBUF_LITTLE_ENDIAN 1
+   #endif
+ #endif
+-#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS)
+-  #ifdef LIBPROTOBUF_EXPORTS
+-    #define LIBPROTOBUF_EXPORT __declspec(dllexport)
+-  #else
+-    #define LIBPROTOBUF_EXPORT __declspec(dllimport)
+-  #endif
+-  #ifdef LIBPROTOC_EXPORTS
+-    #define LIBPROTOC_EXPORT   __declspec(dllexport)
+-  #else
+-    #define LIBPROTOC_EXPORT   __declspec(dllimport)
++
++// The macros defined below are required in order to make protobuf_lite a
++// component on all platforms. See http://crbug.com/172800.
++#if defined(COMPONENT_BUILD) && defined(PROTOBUF_USE_DLLS)
++  #if defined(_MSC_VER)
++    #ifdef LIBPROTOBUF_EXPORTS
++      #define LIBPROTOBUF_EXPORT __declspec(dllexport)
++    #else
++      #define LIBPROTOBUF_EXPORT __declspec(dllimport)
++    #endif
++    #ifdef LIBPROTOC_EXPORTS
++      #define LIBPROTOC_EXPORT   __declspec(dllexport)
++    #else
++      #define LIBPROTOC_EXPORT   __declspec(dllimport)
++    #endif
++  #else  // defined(_MSC_VER)
++    #ifdef LIBPROTOBUF_EXPORTS
++      #define LIBPROTOBUF_EXPORT __attribute__((visibility("default")))
++    #else
++      #define LIBPROTOBUF_EXPORT
++    #endif
++    #ifdef LIBPROTOC_EXPORTS
++      #define LIBPROTOC_EXPORT   __attribute__((visibility("default")))
++    #else
++      #define LIBPROTOC_EXPORT
++    #endif
+   #endif
+-#else
++#else  // defined(COMPONENT_BUILD) && defined(PROTOBUF_USE_DLLS)
+   #define LIBPROTOBUF_EXPORT
+   #define LIBPROTOC_EXPORT
+ #endif
+@@ -109,15 +125,15 @@
+ typedef unsigned __int32 uint32;
+ typedef unsigned __int64 uint64;
+ #else
+-typedef signed char  int8;
+-typedef short int16;
+-typedef int int32;
+-typedef long long int64;
+-
+-typedef unsigned char  uint8;
+-typedef unsigned short uint16;
+-typedef unsigned int uint32;
+-typedef unsigned long long uint64;
++typedef int8_t  int8;
++typedef int16_t int16;
++typedef int32_t int32;
++typedef int64_t int64;
++
++typedef uint8_t  uint8;
++typedef uint16_t uint16;
++typedef uint32_t uint32;
++typedef uint64_t uint64;
+ #endif
+ 
+ // long long macros to be used because gcc and vc++ use different suffixes,
+@@ -131,8 +147,8 @@
+ #define GOOGLE_ULONGLONG(x) x##UI64
+ #define GOOGLE_LL_FORMAT "I64"  // As in printf("%I64d", ...)
+ #else
+-#define GOOGLE_LONGLONG(x) x##LL
+-#define GOOGLE_ULONGLONG(x) x##ULL
++#define GOOGLE_LONGLONG(x) INT64_C(x)
++#define GOOGLE_ULONGLONG(x) UINT64_C(x)
+ #define GOOGLE_LL_FORMAT "ll"  // As in "%lld". Note that "q" is poor form also.
+ #endif
+ 
diff --git a/src/third_party/protobuf-3/patches/0005-fix-include-js-generator.patch b/src/third_party/protobuf-3/patches/0005-fix-include-js-generator.patch
new file mode 100644
index 0000000..b6b6672
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0005-fix-include-js-generator.patch
@@ -0,0 +1,11 @@
+--- protobuf-3.0.0-beta-3/src/google/protobuf/compiler/js/js_generator.cc       2016-05-16 11:34:04.000000000 -0700
++++ /usr/local/google/home/xyzzyz/chromium/src/third_party/protobuf/src/google/protobuf/compiler/js/js_generator.cc   2016-05-17 12:46:08.746078982 -0700
+@@ -28,7 +28,7 @@
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+-#include "google/protobuf/compiler/js/js_generator.h"
++#include <google/protobuf/compiler/js/js_generator.h>
+ 
+ #include <assert.h>
+ #include <algorithm>
diff --git a/src/third_party/protobuf-3/patches/0007-uninline_googleonce.patch b/src/third_party/protobuf-3/patches/0007-uninline_googleonce.patch
new file mode 100644
index 0000000..85362e8
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0007-uninline_googleonce.patch
@@ -0,0 +1,36 @@
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/stubs/once.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/stubs/once.cc	2016-03-31 13:25:32.180017848 -0700
+@@ -62,6 +62,13 @@
+ 
+ }  // namespace
+ 
++void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
++  if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
++    internal::FunctionClosure0 func(init_func, false);
++    GoogleOnceInitImpl(once, &func);
++  }
++}
++
+ void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) {
+   internal::AtomicWord state = internal::Acquire_Load(once);
+   // Fast path. The provided closure was already executed.
+only in patch2:
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/stubs/once.h	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/stubs/once.h	2016-03-31 13:25:35.520013490 -0700
+@@ -122,12 +122,8 @@
+ LIBPROTOBUF_EXPORT
+ void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure);
+ 
+-inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
+-  if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
+-    internal::FunctionClosure0 func(init_func, false);
+-    GoogleOnceInitImpl(once, &func);
+-  }
+-}
++LIBPROTOBUF_EXPORT
++void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)());
+ 
+ template <typename Arg>
+ inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
diff --git a/src/third_party/protobuf-3/patches/0008-uninline_get_empty_string.patch b/src/third_party/protobuf-3/patches/0008-uninline_get_empty_string.patch
new file mode 100644
index 0000000..8faf518
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0008-uninline_get_empty_string.patch
@@ -0,0 +1,33 @@
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/generated_message_util.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/generated_message_util.cc	2016-03-31 13:25:32.180017848 -0700
+@@ -60,6 +60,12 @@
+   OnShutdown(&DeleteEmptyString);
+ }
+ 
++const ::std::string& GetEmptyString() {
++  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
++  return GetEmptyStringAlreadyInited();
++}
++
++
+ int StringSpaceUsedExcludingSelf(const string& str) {
+   const void* start = &str;
+   const void* end = &str + 1;
+only in patch2:
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/generated_message_util.h	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/generated_message_util.h	2016-03-31 13:25:40.252007316 -0700
+@@ -84,10 +84,8 @@
+   assert(empty_string_ != NULL);
+   return *empty_string_;
+ }
+-LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
+-  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
+-  return GetEmptyStringAlreadyInited();
+-}
++
++LIBPROTOBUF_EXPORT const ::std::string& GetEmptyString();
+ 
+ LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
+ 
diff --git a/src/third_party/protobuf-3/patches/0009-uninline-arenastring.patch b/src/third_party/protobuf-3/patches/0009-uninline-arenastring.patch
new file mode 100644
index 0000000..6ba6360
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0009-uninline-arenastring.patch
@@ -0,0 +1,59 @@
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/arenastring.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/arenastring.cc	2016-03-31 13:25:40.888006485 -0700
+@@ -48,6 +48,23 @@
+   }
+ }
+ 
++::std::string* ArenaStringPtr::MutableNoArena(
++     const ::std::string* default_value) {
++  if (ptr_ == default_value) {
++    CreateInstanceNoArena(default_value);
++  }
++  return ptr_;
++}
++
++
++void ArenaStringPtr::DestroyNoArena(const ::std::string* default_value) {
++  if (ptr_ != default_value) {
++    delete ptr_;
++  }
++  ptr_ = NULL;
++}
++
++
+ }  // namespace internal
+ }  // namespace protobuf
+ }  // namespace google
+only in patch2:
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/arenastring.h	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/arenastring.h	2016-03-31 13:25:40.888006485 -0700
+@@ -219,12 +219,7 @@
+     return *ptr_;
+   }
+ 
+-  inline ::std::string* MutableNoArena(const ::std::string* default_value) {
+-    if (ptr_ == default_value) {
+-      CreateInstanceNoArena(default_value);
+-    }
+-    return ptr_;
+-  }
++  ::std::string* MutableNoArena(const ::std::string* default_value);
+ 
+   inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
+     if (ptr_ == default_value) {
+@@ -248,12 +243,7 @@
+     }
+   }
+ 
+-  inline void DestroyNoArena(const ::std::string* default_value) {
+-    if (ptr_ != default_value) {
+-      delete ptr_;
+-    }
+-    ptr_ = NULL;
+-  }
++  void DestroyNoArena(const ::std::string* default_value);
+ 
+   inline void ClearToEmptyNoArena(const ::std::string* default_value) {
+     if (ptr_ == default_value) {
diff --git a/src/third_party/protobuf-3/patches/0010-uninline-generated-code.patch b/src/third_party/protobuf-3/patches/0010-uninline-generated-code.patch
new file mode 100644
index 0000000..85274de
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0010-uninline-generated-code.patch
@@ -0,0 +1,34 @@
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/compiler/cpp/cpp_file.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/compiler/cpp/cpp_file.cc	2016-03-31 13:25:40.252007316 -0700
+@@ -337,7 +337,7 @@
+           "namespace {\n"
+           "\n"
+           "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
+-          "static void MergeFromFail(int line) {\n"
++          "GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {\n"
+           "  GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
+           "}\n"
+           "\n"
+only in patch2:
+unchanged:
+--- protobuf-cleaned/src/google/protobuf/compiler/cpp/cpp_message.cc	2015-12-30 13:21:46.000000000 -0800
++++ protobuf-patched/src/google/protobuf/compiler/cpp/cpp_message.cc	2016-03-31 13:25:40.888006485 -0700
+@@ -1035,7 +1035,7 @@
+   }
+ 
+   printer->Print(vars,
+-    "void Swap($classname$* other);\n"
++    "GOOGLE_ATTRIBUTE_NOINLINE void Swap($classname$* other);\n"
+     "\n"
+     "// implements Message ----------------------------------------------\n"
+     "\n"
+@@ -2586,7 +2586,7 @@
+     // ownership situation: swapping across arenas or between an arena and a
+     // heap requires copying.
+     printer->Print(
+-        "void $classname$::Swap($classname$* other) {\n"
++        "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\n"
+         "  if (other == this) return;\n"
+         "  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
+         "    InternalSwap(other);\n"
diff --git a/src/third_party/protobuf-3/patches/0011-libprotobuf_export.patch b/src/third_party/protobuf-3/patches/0011-libprotobuf_export.patch
new file mode 100644
index 0000000..2919ff5
--- /dev/null
+++ b/src/third_party/protobuf-3/patches/0011-libprotobuf_export.patch
@@ -0,0 +1,11 @@
+--- protobuf-3.0.0-beta-3/src/google/protobuf/arena.h   2016-05-16 11:34:04.000000000 -0700
++++ /usr/local/google/home/xyzzyz/chromium/src/third_party/protobuf/src/google/protobuf/arena.h 2016-05-17 14:38:50.109603998 -0700
+@@ -213,7 +213,7 @@
+ // well as RepeatedPtrField.
+ 
+ #if __cplusplus >= 201103L
+-class Arena final {
++class LIBPROTOBUF_EXPORT Arena final {
+ #else
+ class LIBPROTOBUF_EXPORT Arena {
+ #endif
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/config.m4 b/src/third_party/protobuf-3/php/ext/google/protobuf/config.m4
new file mode 100644
index 0000000..b5946f7
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/config.m4
@@ -0,0 +1,10 @@
+dnl lines starting with "dnl" are comments
+
+PHP_ARG_ENABLE(protobuf, whether to enable Protobuf extension, [  --enable-protobuf   Enable Protobuf extension])
+
+if test "$PHP_PROTOBUF" != "no"; then
+
+  dnl this defines the extension
+  PHP_NEW_EXTENSION(protobuf, upb.c protobuf.c def.c message.c storage.c, $ext_shared)
+
+fi
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/def.c b/src/third_party/protobuf-3/php/ext/google/protobuf/def.c
new file mode 100644
index 0000000..fc18806
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/def.c
@@ -0,0 +1,381 @@
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Common Utilities
+// -----------------------------------------------------------------------------
+
+void check_upb_status(const upb_status* status, const char* msg) {
+  if (!upb_ok(status)) {
+    zend_error("%s: %s\n", msg, upb_status_errmsg(status));
+  }
+}
+
+
+static upb_def *check_notfrozen(const upb_def *def) {
+  if (upb_def_isfrozen(def)) {
+    zend_error(E_ERROR,
+               "Attempt to modify a frozen descriptor. Once descriptors are "
+               "added to the descriptor pool, they may not be modified.");
+  }
+  return (upb_def *)def;
+}
+
+static upb_msgdef *check_msgdef_notfrozen(const upb_msgdef *def) {
+  return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def *)def));
+}
+
+static upb_fielddef *check_fielddef_notfrozen(const upb_fielddef *def) {
+  return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def *)def));
+}
+
+#define PROTOBUF_WRAP_INTERN(wrapper, intern, intern_dtor)            \
+  Z_TYPE_P(wrapper) = IS_OBJECT;                                      \
+  Z_OBJVAL_P(wrapper)                                                 \
+      .handle = zend_objects_store_put(                               \
+      intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
+      intern_dtor, NULL TSRMLS_CC);                                   \
+  Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
+
+#define PROTOBUF_SETUP_ZEND_WRAPPER(class_name, class_name_lower, wrapper,    \
+                                    intern)                                   \
+  Z_TYPE_P(wrapper) = IS_OBJECT;                                              \
+  class_name *intern = ALLOC(class_name);                                     \
+  memset(intern, 0, sizeof(class_name));                                      \
+  class_name_lower##_init_c_instance(intern TSRMLS_CC);                       \
+  Z_OBJVAL_P(wrapper)                                                         \
+      .handle = zend_objects_store_put(intern, NULL, class_name_lower##_free, \
+                                       NULL TSRMLS_CC);                       \
+  Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
+
+#define PROTOBUF_CREATE_ZEND_WRAPPER(class_name, class_name_lower, wrapper, \
+                                     intern)                                \
+  MAKE_STD_ZVAL(wrapper);                                                   \
+  PROTOBUF_SETUP_ZEND_WRAPPER(class_name, class_name_lower, wrapper, intern);
+
+#define DEFINE_CLASS(name, name_lower, string_name)                          \
+  zend_class_entry *name_lower##_type;                                       \
+  void name_lower##_init(TSRMLS_D) {                                         \
+    zend_class_entry class_type;                                             \
+    INIT_CLASS_ENTRY(class_type, string_name, name_lower##_methods);         \
+    name_lower##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
+    name_lower##_type->create_object = name_lower##_create;                  \
+  }                                                                          \
+  name *php_to_##name_lower(zval *val TSRMLS_DC) {                           \
+    return (name *)zend_object_store_get_object(val TSRMLS_CC);              \
+  }                                                                          \
+  void name_lower##_free(void *object TSRMLS_DC) {                           \
+    name *intern = (name *)object;                                           \
+    name_lower##_free_c(intern TSRMLS_CC);                                   \
+    efree(object);                                                           \
+  }                                                                          \
+  zend_object_value name_lower##_create(zend_class_entry *ce TSRMLS_DC) {    \
+    zend_object_value return_value;                                          \
+    name *intern = (name *)emalloc(sizeof(name));                            \
+    memset(intern, 0, sizeof(name));                                         \
+    name_lower##_init_c_instance(intern TSRMLS_CC);                          \
+    return_value.handle = zend_objects_store_put(                            \
+        intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,      \
+        name_lower##_free, NULL TSRMLS_CC);                                  \
+    return_value.handlers = zend_get_std_object_handlers();                  \
+    return return_value;                                                     \
+  }
+
+// -----------------------------------------------------------------------------
+// DescriptorPool
+// -----------------------------------------------------------------------------
+
+static zend_function_entry descriptor_pool_methods[] = {
+  PHP_ME(DescriptorPool, addMessage, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, finalize, NULL, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+DEFINE_CLASS(DescriptorPool, descriptor_pool,
+             "Google\\Protobuf\\DescriptorPool");
+
+DescriptorPool *generated_pool;  // The actual generated pool
+
+ZEND_FUNCTION(get_generated_pool) {
+  if (PROTOBUF_G(generated_pool) == NULL) {
+    MAKE_STD_ZVAL(PROTOBUF_G(generated_pool));
+    Z_TYPE_P(PROTOBUF_G(generated_pool)) = IS_OBJECT;
+    generated_pool = ALLOC(DescriptorPool);
+    descriptor_pool_init_c_instance(generated_pool TSRMLS_CC);
+    Z_OBJ_HANDLE_P(PROTOBUF_G(generated_pool)) = zend_objects_store_put(
+        generated_pool, NULL,
+        (zend_objects_free_object_storage_t)descriptor_pool_free, NULL TSRMLS_CC);
+    Z_OBJ_HT_P(PROTOBUF_G(generated_pool)) = zend_get_std_object_handlers();
+  }
+  RETURN_ZVAL(PROTOBUF_G(generated_pool), 1, 0);
+}
+
+void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC) {
+  zend_object_std_init(&pool->std, descriptor_pool_type TSRMLS_CC);
+  pool->symtab = upb_symtab_new(&pool->symtab);
+
+  ALLOC_HASHTABLE(pool->pending_list);
+  zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
+}
+
+void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
+  upb_symtab_unref(pool->symtab, &pool->symtab);
+  zend_hash_destroy(pool->pending_list);
+  FREE_HASHTABLE(pool->pending_list);
+}
+
+PHP_METHOD(DescriptorPool, addMessage) {
+  char *name = NULL;
+  int str_len;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &str_len) ==
+      FAILURE) {
+    return;
+  }
+
+  zval* retval = NULL;
+  PROTOBUF_CREATE_ZEND_WRAPPER(MessageBuilderContext, message_builder_context,
+                               retval, context);
+
+  MAKE_STD_ZVAL(context->pool);
+  ZVAL_ZVAL(context->pool, getThis(), 1, 0);
+
+  Descriptor *desc = php_to_descriptor(context->descriptor TSRMLS_CC);
+  Descriptor_name_set(desc, name);
+
+  RETURN_ZVAL(retval, 0, 1);
+}
+
+static void validate_msgdef(const upb_msgdef* msgdef) {
+  // Verify that no required fields exist. proto3 does not support these.
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
+      zend_error(E_ERROR, "Required fields are unsupported in proto3.");
+    }
+  }
+}
+
+PHP_METHOD(DescriptorPool, finalize) {
+  DescriptorPool *self = php_to_descriptor_pool(getThis() TSRMLS_CC);
+  Bucket *temp;
+  int i, num;
+
+  num = zend_hash_num_elements(self->pending_list);
+  upb_def **defs = emalloc(sizeof(upb_def *) * num);
+
+  for (i = 0, temp = self->pending_list->pListHead; temp != NULL;
+       temp = temp->pListNext) {
+    zval *def_php = *(zval **)temp->pData;
+    Descriptor* desc = php_to_descriptor(def_php TSRMLS_CC);
+    defs[i] = (upb_def *)desc->msgdef;
+    validate_msgdef((const upb_msgdef *)defs[i++]);
+  }
+
+  CHECK_UPB(upb_symtab_add(self->symtab, (upb_def **)defs, num, NULL, &status),
+            "Unable to add defs to DescriptorPool");
+
+  for (temp = self->pending_list->pListHead; temp != NULL;
+       temp = temp->pListNext) {
+    // zval *def_php = *(zval **)temp->pData;
+    // Descriptor* desc = php_to_descriptor(def_php TSRMLS_CC);
+    build_class_from_descriptor((zval *)temp->pDataPtr TSRMLS_CC);
+  }
+
+  FREE(defs);
+  zend_hash_destroy(self->pending_list);
+  zend_hash_init(self->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
+}
+
+// -----------------------------------------------------------------------------
+// Descriptor
+// -----------------------------------------------------------------------------
+
+static zend_function_entry descriptor_methods[] = {
+  ZEND_FE_END
+};
+
+DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
+
+void descriptor_free_c(Descriptor *self TSRMLS_DC) {
+  upb_msg_field_iter iter;
+  upb_msg_field_begin(&iter, self->msgdef);
+  while (!upb_msg_field_done(&iter)) {
+    upb_fielddef *fielddef = upb_msg_iter_field(&iter);
+    upb_fielddef_unref(fielddef, &fielddef);
+    upb_msg_field_next(&iter);
+  }
+  upb_msgdef_unref(self->msgdef, &self->msgdef);
+  if (self->layout) {
+    free_layout(self->layout);
+  }
+}
+
+static void descriptor_add_field(Descriptor *desc,
+                                 const upb_fielddef *fielddef) {
+  upb_msgdef *mut_def = check_msgdef_notfrozen(desc->msgdef);
+  upb_fielddef *mut_field_def = check_fielddef_notfrozen(fielddef);
+  CHECK_UPB(upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
+            "Adding field to Descriptor failed");
+  // add_def_obj(fielddef, obj);
+}
+
+void descriptor_init_c_instance(Descriptor* desc TSRMLS_DC) {
+  zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
+  desc->msgdef = upb_msgdef_new(&desc->msgdef);
+  desc->layout = NULL;
+  // MAKE_STD_ZVAL(intern->klass);
+  // ZVAL_NULL(intern->klass);
+  desc->pb_serialize_handlers = NULL;
+}
+
+void Descriptor_name_set(Descriptor *desc, const char *name) {
+  upb_msgdef *mut_def = check_msgdef_notfrozen(desc->msgdef);
+  CHECK_UPB(upb_msgdef_setfullname(mut_def, name, &status),
+            "Error setting Descriptor name");
+}
+
+// -----------------------------------------------------------------------------
+// FieldDescriptor
+// -----------------------------------------------------------------------------
+
+static void field_descriptor_name_set(const upb_fielddef* fielddef,
+                                      const char *name) {
+  upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
+  CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
+            "Error setting FieldDescriptor name");
+}
+
+static void field_descriptor_label_set(const upb_fielddef* fielddef,
+                                       upb_label_t upb_label) {
+  upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
+  upb_fielddef_setlabel(mut_def, upb_label);
+}
+
+upb_fieldtype_t string_to_descriptortype(const char *type) {
+#define CONVERT(upb, str)   \
+  if (!strcmp(type, str)) { \
+    return UPB_DESCRIPTOR_TYPE_##upb;  \
+  }
+
+  CONVERT(FLOAT, "float");
+  CONVERT(DOUBLE, "double");
+  CONVERT(BOOL, "bool");
+  CONVERT(STRING, "string");
+  CONVERT(BYTES, "bytes");
+  CONVERT(MESSAGE, "message");
+  CONVERT(GROUP, "group");
+  CONVERT(ENUM, "enum");
+  CONVERT(INT32, "int32");
+  CONVERT(INT64, "int64");
+  CONVERT(UINT32, "uint32");
+  CONVERT(UINT64, "uint64");
+  CONVERT(SINT32, "sint32");
+  CONVERT(SINT64, "sint64");
+  CONVERT(FIXED32, "fixed32");
+  CONVERT(FIXED64, "fixed64");
+  CONVERT(SFIXED32, "sfixed32");
+  CONVERT(SFIXED64, "sfixed64");
+
+#undef CONVERT
+
+  zend_error(E_ERROR, "Unknown field type.");
+  return 0;
+}
+
+static void field_descriptor_type_set(const upb_fielddef* fielddef,
+                                      const char *type) {
+  upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
+  upb_fielddef_setdescriptortype(mut_def, string_to_descriptortype(type));
+}
+
+static void field_descriptor_number_set(const upb_fielddef* fielddef,
+                                        int number) {
+  upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
+  CHECK_UPB(upb_fielddef_setnumber(mut_def, number, &status),
+            "Error setting field number");
+}
+
+// -----------------------------------------------------------------------------
+// MessageBuilderContext
+// -----------------------------------------------------------------------------
+
+static zend_function_entry message_builder_context_methods[] = {
+    PHP_ME(MessageBuilderContext, finalizeToPool, NULL, ZEND_ACC_PUBLIC)
+    PHP_ME(MessageBuilderContext, optional, NULL, ZEND_ACC_PUBLIC)
+    {NULL, NULL, NULL}
+};
+
+DEFINE_CLASS(MessageBuilderContext, message_builder_context,
+             "Google\\Protobuf\\Internal\\MessageBuilderContext");
+
+void message_builder_context_free_c(MessageBuilderContext *context TSRMLS_DC) {
+  zval_ptr_dtor(&context->descriptor);
+  zval_ptr_dtor(&context->pool);
+}
+
+void message_builder_context_init_c_instance(
+    MessageBuilderContext *context TSRMLS_DC) {
+  zend_object_std_init(&context->std, message_builder_context_type TSRMLS_CC);
+  PROTOBUF_CREATE_ZEND_WRAPPER(Descriptor, descriptor, context->descriptor,
+                               desc);
+}
+
+static void msgdef_add_field(Descriptor *desc, upb_label_t upb_label,
+                             const char *name, const char *type, int number,
+                             const char *type_class) {
+  upb_fielddef *fielddef = upb_fielddef_new(&fielddef);
+  upb_fielddef_setpacked(fielddef, false);
+
+  field_descriptor_label_set(fielddef, upb_label);
+  field_descriptor_name_set(fielddef, name);
+  field_descriptor_type_set(fielddef, type);
+  field_descriptor_number_set(fielddef, number);
+
+// //   if (type_class != Qnil) {
+// //     if (TYPE(type_class) != T_STRING) {
+// //       rb_raise(rb_eArgError, "Expected string for type class");
+// //     }
+// //     // Make it an absolute type name by prepending a dot.
+// //     type_class = rb_str_append(rb_str_new2("."), type_class);
+// //     rb_funcall(fielddef, rb_intern("submsg_name="), 1, type_class);
+// //   }
+  descriptor_add_field(desc, fielddef);
+}
+
+PHP_METHOD(MessageBuilderContext, optional) {
+  MessageBuilderContext *self = php_to_message_builder_context(getThis() TSRMLS_CC);
+  Descriptor *desc = php_to_descriptor(self->descriptor TSRMLS_CC);
+  // VALUE name, type, number, type_class;
+  const char *name, *type, *type_class;
+  int number, name_str_len, type_str_len, type_class_str_len;
+  if (ZEND_NUM_ARGS() == 3) {
+    if (zend_parse_parameters(3 TSRMLS_CC, "ssl", &name,
+                              &name_str_len, &type, &type_str_len, &number) == FAILURE) {
+      return;
+    }
+  } else {
+    if (zend_parse_parameters(4 TSRMLS_CC, "ssls", &name,
+                              &name_str_len, &type, &type_str_len, &number, &type_class,
+                              &type_class_str_len) == FAILURE) {
+      return;
+    }
+  }
+
+  msgdef_add_field(desc, UPB_LABEL_OPTIONAL, name, type, number, type_class);
+
+  zval_copy_ctor(getThis());
+  RETURN_ZVAL(getThis(), 1, 0);
+}
+
+PHP_METHOD(MessageBuilderContext, finalizeToPool) {
+  MessageBuilderContext *self = php_to_message_builder_context(getThis() TSRMLS_CC);
+  DescriptorPool *pool = php_to_descriptor_pool(self->pool TSRMLS_CC);
+  Descriptor* desc = php_to_descriptor(self->descriptor TSRMLS_CC);
+
+  Z_ADDREF_P(self->descriptor);
+  zend_hash_next_index_insert(pool->pending_list, &self->descriptor,
+                              sizeof(zval *), NULL);
+  RETURN_ZVAL(self->pool, 1, 0);
+}
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/message.c b/src/third_party/protobuf-3/php/ext/google/protobuf/message.c
new file mode 100644
index 0000000..c062d66
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/message.c
@@ -0,0 +1,273 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include <php.h>
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Class/module creation from msgdefs and enumdefs, respectively.
+// -----------------------------------------------------------------------------
+
+void* message_data(void* msg) {
+  return ((uint8_t *)msg) + sizeof(MessageHeader);
+}
+
+void message_set_property(zval* object, zval* field_name, zval* value,
+                          const zend_literal* key TSRMLS_DC) {
+  const upb_fielddef* field;
+
+  MessageHeader* self = zend_object_store_get_object(object TSRMLS_CC);
+
+  CHECK_TYPE(field_name, IS_STRING);
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(field_name));
+  if (field == NULL) {
+    zend_error(E_ERROR, "Unknown field: %s", Z_STRVAL_P(field_name));
+  }
+  layout_set(self->descriptor->layout, message_data(self), field, value);
+}
+
+zval* message_get_property(zval* object, zval* member, int type,
+                             const zend_literal* key TSRMLS_DC) {
+  MessageHeader* self =
+      (MessageHeader*)zend_object_store_get_object(object TSRMLS_CC);
+  CHECK_TYPE(member, IS_STRING);
+
+  const upb_fielddef* field;
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
+  if (field == NULL) {
+    return EG(uninitialized_zval_ptr);
+  }
+  zval* retval = layout_get(self->descriptor->layout, message_data(self), field TSRMLS_CC);
+  return retval;
+}
+
+static  zend_function_entry message_methods[] = {
+  PHP_ME(Message, encode, NULL, ZEND_ACC_PUBLIC)
+  {NULL, NULL, NULL}
+};
+
+/* stringsink *****************************************************************/
+
+// This should probably be factored into a common upb component.
+
+typedef struct {
+  upb_byteshandler handler;
+  upb_bytessink sink;
+  char *ptr;
+  size_t len, size;
+} stringsink;
+
+static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
+  stringsink *sink = _sink;
+  sink->len = 0;
+  return sink;
+}
+
+static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
+                                size_t len, const upb_bufhandle *handle) {
+  stringsink *sink = _sink;
+  size_t new_size = sink->size;
+
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  while (sink->len + len > new_size) {
+    new_size *= 2;
+  }
+
+  if (new_size != sink->size) {
+    sink->ptr = realloc(sink->ptr, new_size);
+    sink->size = new_size;
+  }
+
+  memcpy(sink->ptr + sink->len, ptr, len);
+  sink->len += len;
+
+  return len;
+}
+
+void stringsink_init(stringsink *sink) {
+  upb_byteshandler_init(&sink->handler);
+  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
+  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
+
+  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
+
+  sink->size = 32;
+  sink->ptr = malloc(sink->size);
+  sink->len = 0;
+}
+
+void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
+
+// Stack-allocated context during an encode/decode operation. Contains the upb
+// environment and its stack-based allocator, an initial buffer for allocations
+// to avoid malloc() when possible, and a template for PHP exception messages
+// if any error occurs.
+#define STACK_ENV_STACKBYTES 4096
+typedef struct {
+  upb_env env;
+  upb_seededalloc alloc;
+  const char *php_error_template;
+  char allocbuf[STACK_ENV_STACKBYTES];
+} stackenv;
+
+static void stackenv_init(stackenv* se, const char* errmsg);
+static void stackenv_uninit(stackenv* se);
+
+// Callback invoked by upb if any error occurs during parsing or serialization.
+static bool env_error_func(void* ud, const upb_status* status) {
+    stackenv* se = ud;
+    // Free the env -- rb_raise will longjmp up the stack past the encode/decode
+    // function so it would not otherwise have been freed.
+    stackenv_uninit(se);
+
+    // TODO(teboring): have a way to verify that this is actually a parse error,
+    // instead of just throwing "parse error" unconditionally.
+    zend_error(E_ERROR, se->php_error_template);
+    // Never reached.
+    return false;
+}
+
+static void stackenv_init(stackenv* se, const char* errmsg) {
+  se->php_error_template = errmsg;
+  upb_env_init(&se->env);
+  upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES);
+  upb_env_setallocfunc(&se->env, upb_seededalloc_getallocfunc(&se->alloc),
+                       &se->alloc);
+  upb_env_seterrorfunc(&se->env, env_error_func, se);
+}
+
+static void stackenv_uninit(stackenv* se) {
+  upb_env_uninit(&se->env);
+  upb_seededalloc_uninit(&se->alloc);
+}
+
+// -----------------------------------------------------------------------------
+// Message
+// -----------------------------------------------------------------------------
+
+static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
+  if (desc->pb_serialize_handlers == NULL) {
+    desc->pb_serialize_handlers =
+        upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
+  }
+  return desc->pb_serialize_handlers;
+}
+
+PHP_METHOD(Message, encode) {
+  Descriptor* desc = (Descriptor*)zend_object_store_get_object(
+      CE_STATIC_MEMBERS(Z_OBJCE_P(getThis()))[0] TSRMLS_CC);
+
+  stringsink sink;
+  stringsink_init(&sink);
+
+  {
+    const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
+
+    stackenv se;
+    upb_pb_encoder* encoder;
+
+    stackenv_init(&se, "Error occurred during encoding: %s");
+    encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
+
+    putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0);
+
+    RETVAL_STRINGL(sink.ptr, sink.len, 1);
+
+    stackenv_uninit(&se);
+    stringsink_uninit(&sink);
+  }
+}
+
+void message_free(void * object TSRMLS_DC) {
+  FREE(object);
+}
+
+zend_object_value message_create(zend_class_entry* ce TSRMLS_DC) {
+  zend_object_value return_value;
+
+  zval* php_descriptor = get_def_obj(ce);
+
+  Descriptor* desc = zend_object_store_get_object(php_descriptor TSRMLS_CC);
+  MessageHeader* msg = (MessageHeader*)ALLOC_N(
+      uint8_t, sizeof(MessageHeader) + desc->layout->size);
+  memset(message_data(msg), 0, desc->layout->size);
+
+  // We wrap first so that everything in the message object is GC-rooted in case
+  // a collection happens during object creation in layout_init().
+  msg->descriptor = desc;
+
+  layout_init(desc->layout, message_data(msg));
+  zend_object_std_init(&msg->std, ce TSRMLS_CC);
+
+  return_value.handle = zend_objects_store_put(
+      msg, (zend_objects_store_dtor_t)zend_objects_destroy_object,
+      message_free, NULL TSRMLS_CC);
+
+  return_value.handlers = PROTOBUF_G(message_handlers);
+  return return_value;
+}
+
+const zend_class_entry* build_class_from_descriptor(
+    zval* php_descriptor TSRMLS_DC) {
+  Descriptor* desc = php_to_descriptor(php_descriptor);
+  if (desc->layout == NULL) {
+    MessageLayout* layout = create_layout(desc->msgdef);
+    desc->layout = layout;
+  }
+  // TODO(teboring): Add it back.
+  // if (desc->fill_method == NULL) {
+  //   desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
+  // }
+
+  const char* name = upb_msgdef_fullname(desc->msgdef);
+  if (name == NULL) {
+    zend_error(E_ERROR, "Descriptor does not have assigned name.");
+  }
+
+  zend_class_entry class_entry;
+  INIT_CLASS_ENTRY_EX(class_entry, name, strlen(name), message_methods);
+  zend_class_entry* registered_ce =
+      zend_register_internal_class(&class_entry TSRMLS_CC);
+
+  add_def_obj(registered_ce, php_descriptor);
+
+  if (PROTOBUF_G(message_handlers) == NULL) {
+    PROTOBUF_G(message_handlers) = ALLOC(zend_object_handlers);
+    memcpy(PROTOBUF_G(message_handlers), zend_get_std_object_handlers(),
+           sizeof(zend_object_handlers));
+    PROTOBUF_G(message_handlers)->write_property = message_set_property;
+    PROTOBUF_G(message_handlers)->read_property = message_get_property;
+  }
+
+  registered_ce->create_object = message_create;
+}
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.c b/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.c
new file mode 100644
index 0000000..b1ace8b
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.c
@@ -0,0 +1,89 @@
+#include "protobuf.h"
+
+#include <zend_hash.h>
+
+ZEND_DECLARE_MODULE_GLOBALS(protobuf)
+static PHP_GINIT_FUNCTION(protobuf);
+static PHP_GSHUTDOWN_FUNCTION(protobuf);
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+
+void add_def_obj(const void* def, zval* value) {
+  uint nIndex = (ulong)def & PROTOBUF_G(upb_def_to_php_obj_map).nTableMask;
+
+  zval* pDest = NULL;
+  Z_ADDREF_P(value);
+  zend_hash_index_update(&PROTOBUF_G(upb_def_to_php_obj_map), (zend_ulong)def,
+                         &value, sizeof(zval*), &pDest);
+}
+
+zval* get_def_obj(const void* def) {
+  zval** value;
+  if (zend_hash_index_find(&PROTOBUF_G(upb_def_to_php_obj_map), (zend_ulong)def,
+                           &value) == FAILURE) {
+    zend_error(E_ERROR, "PHP object not found for given definition.\n");
+    return NULL;
+  }
+  return *value;
+}
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+// define the function(s) we want to add
+zend_function_entry protobuf_functions[] = {
+  ZEND_FE(get_generated_pool, NULL)
+  ZEND_FE_END
+};
+
+// "protobuf_functions" refers to the struct defined above
+// we'll be filling in more of this later: you can use this to specify
+// globals, php.ini info, startup and teardown functions, etc.
+zend_module_entry protobuf_module_entry = {
+  STANDARD_MODULE_HEADER,
+  PHP_PROTOBUF_EXTNAME, // extension name
+  protobuf_functions,   // function list
+  PHP_MINIT(protobuf),  // process startup
+  NULL,  // process shutdown
+  NULL,  // request startup
+  NULL,  // request shutdown
+  NULL,  // extension info
+  PHP_PROTOBUF_VERSION, // extension version
+  PHP_MODULE_GLOBALS(protobuf),  // globals descriptor
+  PHP_GINIT(protobuf), // globals ctor
+  PHP_GSHUTDOWN(protobuf),  // globals dtor
+  NULL,  // post deactivate
+  STANDARD_MODULE_PROPERTIES_EX
+};
+
+// install module
+ZEND_GET_MODULE(protobuf)
+
+// global variables
+static PHP_GINIT_FUNCTION(protobuf) {
+  protobuf_globals->generated_pool = NULL;
+  generated_pool = NULL;
+  protobuf_globals->message_handlers = NULL;
+  zend_hash_init(&protobuf_globals->upb_def_to_php_obj_map, 16, NULL,
+                 ZVAL_PTR_DTOR, 0);
+}
+
+static PHP_GSHUTDOWN_FUNCTION(protobuf) {
+  if (protobuf_globals->generated_pool != NULL) {
+    FREE_ZVAL(protobuf_globals->generated_pool);
+  }
+  if (protobuf_globals->message_handlers != NULL) {
+    FREE(protobuf_globals->message_handlers);
+  }
+  zend_hash_destroy(&protobuf_globals->upb_def_to_php_obj_map);
+}
+
+PHP_MINIT_FUNCTION(protobuf) {
+  descriptor_pool_init(TSRMLS_C);
+  descriptor_init(TSRMLS_C);
+  message_builder_context_init(TSRMLS_C);
+}
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.h b/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.h
new file mode 100644
index 0000000..f903855
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/protobuf.h
@@ -0,0 +1,281 @@
+#ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+#define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+
+#include <php.h>
+
+#include "upb.h"
+
+#define PHP_PROTOBUF_EXTNAME "protobuf"
+#define PHP_PROTOBUF_VERSION "0.01"
+
+// Forward decls.
+struct DescriptorPool;
+struct Descriptor;
+struct FieldDescriptor;
+struct EnumDescriptor;
+struct MessageLayout;
+struct MessageField;
+struct MessageHeader;
+struct MessageBuilderContext;
+struct EnumBuilderContext;
+
+typedef struct DescriptorPool DescriptorPool;
+typedef struct Descriptor Descriptor;
+typedef struct FieldDescriptor FieldDescriptor;
+typedef struct OneofDescriptor OneofDescriptor;
+typedef struct EnumDescriptor EnumDescriptor;
+typedef struct MessageLayout MessageLayout;
+typedef struct MessageField MessageField;
+typedef struct MessageHeader MessageHeader;
+typedef struct MessageBuilderContext MessageBuilderContext;
+typedef struct OneofBuilderContext OneofBuilderContext;
+typedef struct EnumBuilderContext EnumBuilderContext;
+
+extern zend_class_entry* builder_type;
+extern zend_class_entry* descriptor_type;
+extern zend_class_entry* message_builder_context_type;
+
+extern DescriptorPool* generated_pool;  // The actual generated pool
+
+ZEND_BEGIN_MODULE_GLOBALS(protobuf)
+  zval* generated_pool;
+  zend_object_handlers* message_handlers;
+  HashTable upb_def_to_php_obj_map;
+ZEND_END_MODULE_GLOBALS(protobuf)
+
+ZEND_DECLARE_MODULE_GLOBALS(protobuf)
+
+#ifdef ZTS
+#define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals*, v)
+#else
+#define PROTOBUF_G(v) (protobuf_globals.v)
+#endif
+
+// -----------------------------------------------------------------------------
+// PHP functions and global variables.
+// -----------------------------------------------------------------------------
+
+PHP_MINIT_FUNCTION(protobuf);
+
+// -----------------------------------------------------------------------------
+// PHP class structure.
+// -----------------------------------------------------------------------------
+
+struct DescriptorPool {
+  zend_object std;
+  upb_symtab* symtab;
+  HashTable* pending_list;
+};
+
+struct Descriptor {
+  zend_object std;
+  const upb_msgdef* msgdef;
+  MessageLayout* layout;
+  // zval* klass;  // begins as NULL
+  // const upb_handlers* fill_handlers;
+  // const upb_pbdecodermethod* fill_method;
+  const upb_handlers* pb_serialize_handlers;
+  // const upb_handlers* json_serialize_handlers;
+  // Handlers hold type class references for sub-message fields directly in some
+  // cases. We need to keep these rooted because they might otherwise be
+  // collected.
+  // zval_array typeclass_references;
+};
+
+struct FieldDescriptor {
+  zend_object std;
+  const upb_fielddef* fielddef;
+};
+
+struct OneofDescriptor {
+  zend_object std;
+  const upb_oneofdef* oneofdef;
+};
+
+struct EnumDescriptor {
+  zend_object std;
+  const upb_enumdef* enumdef;
+  // zval* module;  // begins as NULL
+};
+
+// -----------------------------------------------------------------------------
+// Native slot storage abstraction.
+// -----------------------------------------------------------------------------
+
+#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
+
+size_t native_slot_size(upb_fieldtype_t type);
+
+#define MAP_KEY_FIELD 1
+#define MAP_VALUE_FIELD 2
+
+// Oneof case slot value to indicate that no oneof case is set. The value `0` is
+// safe because field numbers are used as case identifiers, and no field can
+// have a number of 0.
+#define ONEOF_CASE_NONE 0
+
+// These operate on a map field (i.e., a repeated field of submessages whose
+// submessage type is a map-entry msgdef).
+bool is_map_field(const upb_fielddef* field);
+const upb_fielddef* map_field_key(const upb_fielddef* field);
+const upb_fielddef* map_field_value(const upb_fielddef* field);
+
+// These operate on a map-entry msgdef.
+const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
+const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
+
+// -----------------------------------------------------------------------------
+// Message layout / storage.
+// -----------------------------------------------------------------------------
+
+#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
+
+struct MessageField {
+  size_t offset;
+  size_t case_offset;  // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
+};
+
+struct MessageLayout {
+  const upb_msgdef* msgdef;
+  MessageField* fields;
+  size_t size;
+};
+
+void layout_init(MessageLayout* layout, void* storage);
+zval* layout_get(MessageLayout* layout, const void* storage,
+                 const upb_fielddef* field TSRMLS_DC);
+MessageLayout* create_layout(const upb_msgdef* msgdef);
+void free_layout(MessageLayout* layout);
+zval* native_slot_get(upb_fieldtype_t type, /*VALUE type_class,*/
+                      const void* memory TSRMLS_DC);
+
+// -----------------------------------------------------------------------------
+// Message class creation.
+// -----------------------------------------------------------------------------
+
+struct MessageHeader {
+  zend_object std;
+  Descriptor* descriptor;  // kept alive by self.class.descriptor reference.
+                           // Data comes after this.
+};
+
+struct MessageBuilderContext {
+  zend_object std;
+  zval* descriptor;
+  zval* pool;
+};
+
+struct OneofBuilderContext {
+  zend_object std;
+  // VALUE descriptor;
+  // VALUE builder;
+};
+
+struct EnumBuilderContext {
+  zend_object std;
+  // VALUE enumdesc;
+};
+
+// Forward-declare all of the PHP method implementations.
+
+DescriptorPool* php_to_descriptor_pool(zval* value TSRMLS_DC);
+zend_object_value descriptor_pool_create(zend_class_entry *ce TSRMLS_DC);
+void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
+void descriptor_pool_free(void* object TSRMLS_DC);
+void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
+PHP_METHOD(DescriptorPool, addMessage);
+PHP_METHOD(DescriptorPool, finalize);
+
+Descriptor* php_to_descriptor(zval* value TSRMLS_DC);
+zend_object_value descriptor_create(zend_class_entry *ce TSRMLS_DC);
+void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
+void descriptor_free_c(Descriptor* object TSRMLS_DC);
+void descriptor_free(void* object TSRMLS_DC);
+void descriptor_name_set(Descriptor *desc, const char *name);
+
+MessageBuilderContext* php_to_message_builder_context(zval* value TSRMLS_DC);
+zend_object_value message_builder_context_create(
+    zend_class_entry* ce TSRMLS_DC);
+void message_builder_context_init_c_instance(
+    MessageBuilderContext* intern TSRMLS_DC);
+void message_builder_context_free_c(MessageBuilderContext* object TSRMLS_DC);
+void message_builder_context_free(void* object TSRMLS_DC);
+PHP_METHOD(MessageBuilderContext, optional);
+PHP_METHOD(MessageBuilderContext, finalizeToPool);
+
+PHP_METHOD(Message, encode);
+const zend_class_entry* build_class_from_descriptor(
+    zval* php_descriptor TSRMLS_DC);
+
+PHP_FUNCTION(get_generated_pool);
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// ----------------------------------------------------------------------------
+
+void add_def_obj(const void* def, zval* value);
+zval* get_def_obj(const void* def);
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+// PHP Array utils.
+#define Z_ARRVAL_SIZE_P(zval_p) zend_hash_num_elements(Z_ARRVAL_P(zval_p))
+#define Z_ARRVAL_BEGIN_P(zval_p) Z_ARRVAL_P(zval_p)->pListHead
+#define Z_BUCKET_NEXT_PP(bucket_pp) *bucket_pp = (*bucket_pp)->pListNext
+
+#define DEFINE_PHP_OBJECT(class_name, class_name_lower, name) \
+  do {                                                        \
+    zval* name;                                               \
+    MAKE_STD_ZVAL(name);                                      \
+    object_init_ex(name, class_name_lower##_type);            \
+  } while (0)
+
+#define DEFINE_PHP_WRAPPER(class_name, class_name_lower, name, intern) \
+  zval* name;                                                          \
+  MAKE_STD_ZVAL(name);                                                 \
+  object_init_ex(name, class_name_lower##_type);                       \
+  Z_OBJVAL_P(name)                                                     \
+      .handle = zend_objects_store_put(                                \
+      intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,  \
+      class_name_lower##_free, NULL TSRMLS_CC);
+
+#define DEFINE_PHP_ZVAL(name) \
+  do {                        \
+    zval* name;               \
+    MAKE_STD_ZVAL(name);      \
+  } while (0)
+
+#define DEFINE_PHP_STRING(name, value) \
+  do {                                 \
+    zval* name;                        \
+    MAKE_STD_ZVAL(name);               \
+    ZVAL_STRING(name, value, 1);       \
+  } while (0)
+
+// Upb Utilities
+
+void check_upb_status(const upb_status* status, const char* msg);
+
+#define CHECK_UPB(code, msg)             \
+  do {                                   \
+    upb_status status = UPB_STATUS_INIT; \
+    code;                                \
+    check_upb_status(&status, msg);      \
+  } while (0)
+
+// Memory management
+
+#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
+#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
+#define FREE(object) efree(object)
+
+// Type Checking
+#define CHECK_TYPE(field, type)             \
+  if (Z_TYPE_P(field) != type) {            \
+    zend_error(E_ERROR, "Unexpected type"); \
+  }
+
+#endif  // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/storage.c b/src/third_party/protobuf-3/php/ext/google/protobuf/storage.c
new file mode 100644
index 0000000..e5a09c1
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/storage.c
@@ -0,0 +1,539 @@
+#include <stdint.h>
+#include <protobuf.h>
+
+// -----------------------------------------------------------------------------
+// PHP <-> native slot management.
+// -----------------------------------------------------------------------------
+
+static zval* int32_to_zval(int32_t value) {
+  zval* tmp;
+  MAKE_STD_ZVAL(tmp);
+  ZVAL_LONG(tmp, value);
+  php_printf("int32 to zval\n");
+  // ZVAL_LONG(tmp, 1);
+  return tmp;
+}
+
+#define DEREF(memory, type) *(type*)(memory)
+
+size_t native_slot_size(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_FLOAT: return 4;
+    case UPB_TYPE_DOUBLE: return 8;
+    case UPB_TYPE_BOOL: return 1;
+    case UPB_TYPE_STRING: return sizeof(zval*);
+    case UPB_TYPE_BYTES: return sizeof(zval*);
+    case UPB_TYPE_MESSAGE: return sizeof(zval*);
+    case UPB_TYPE_ENUM: return 4;
+    case UPB_TYPE_INT32: return 4;
+    case UPB_TYPE_INT64: return 8;
+    case UPB_TYPE_UINT32: return 4;
+    case UPB_TYPE_UINT64: return 8;
+    default: return 0;
+  }
+}
+
+static bool is_php_num(zval* value) {
+  // Is numerial string also valid?
+  return (Z_TYPE_P(value) == IS_LONG ||
+          Z_TYPE_P(value) == IS_DOUBLE);
+}
+
+void native_slot_check_int_range_precision(upb_fieldtype_t type, zval* val) {
+  // TODO(teboring): Add it back.
+  // if (!is_php_num(val)) {
+  //   zend_error(E_ERROR, "Expected number type for integral field.");
+  // }
+
+  // if (Z_TYPE_P(val) == IS_DOUBLE) {
+  //   double dbl_val = NUM2DBL(val);
+  //   if (floor(dbl_val) != dbl_val) {
+  //     zend_error(E_ERROR,
+  //              "Non-integral floating point value assigned to integer field.");
+  //   }
+  // }
+  // if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
+  //   if (NUM2DBL(val) < 0) {
+  //     zend_error(E_ERROR,
+  //              "Assigning negative value to unsigned integer field.");
+  //   }
+  // }
+}
+
+zval* native_slot_get(upb_fieldtype_t type, /*VALUE type_class,*/
+                      const void* memory TSRMLS_DC) {
+  zval* retval = NULL;
+  switch (type) {
+    // TODO(teboring): Add it back.
+    // case UPB_TYPE_FLOAT:
+    //   return DBL2NUM(DEREF(memory, float));
+    // case UPB_TYPE_DOUBLE:
+    //   return DBL2NUM(DEREF(memory, double));
+    // case UPB_TYPE_BOOL:
+    //   return DEREF(memory, int8_t) ? Qtrue : Qfalse;
+    // case UPB_TYPE_STRING:
+    // case UPB_TYPE_BYTES:
+    // case UPB_TYPE_MESSAGE:
+    //   return DEREF(memory, VALUE);
+    // case UPB_TYPE_ENUM: {
+    //   int32_t val = DEREF(memory, int32_t);
+    //   VALUE symbol = enum_lookup(type_class, INT2NUM(val));
+    //   if (symbol == Qnil) {
+    //     return INT2NUM(val);
+    //   } else {
+    //     return symbol;
+    //   }
+    // }
+    case UPB_TYPE_INT32:
+      return int32_to_zval(DEREF(memory, int32_t));
+    // TODO(teboring): Add it back.
+    // case UPB_TYPE_INT64:
+    //   return LL2NUM(DEREF(memory, int64_t));
+    // case UPB_TYPE_UINT32:
+    //   return UINT2NUM(DEREF(memory, uint32_t));
+    // case UPB_TYPE_UINT64:
+    //   return ULL2NUM(DEREF(memory, uint64_t));
+    default:
+      return EG(uninitialized_zval_ptr);
+  }
+}
+
+void native_slot_init(upb_fieldtype_t type, void* memory) {
+  switch (type) {
+    case UPB_TYPE_FLOAT:
+      DEREF(memory, float) = 0.0;
+      break;
+    case UPB_TYPE_DOUBLE:
+      DEREF(memory, double) = 0.0;
+      break;
+    case UPB_TYPE_BOOL:
+      DEREF(memory, int8_t) = 0;
+      break;
+    // TODO(teboring): Add it back.
+    // case UPB_TYPE_STRING:
+    // case UPB_TYPE_BYTES:
+    //   DEREF(memory, VALUE) = php_str_new2("");
+    //   php_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES)
+    //                                              ? kRubyString8bitEncoding
+    //                                              : kRubyStringUtf8Encoding);
+    //   break;
+    // case UPB_TYPE_MESSAGE:
+    //   DEREF(memory, VALUE) = Qnil;
+    //   break;
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32:
+      DEREF(memory, int32_t) = 0;
+      break;
+    case UPB_TYPE_INT64:
+      DEREF(memory, int64_t) = 0;
+      break;
+    case UPB_TYPE_UINT32:
+      DEREF(memory, uint32_t) = 0;
+      break;
+    case UPB_TYPE_UINT64:
+      DEREF(memory, uint64_t) = 0;
+      break;
+    default:
+      break;
+  }
+}
+
+void native_slot_set(upb_fieldtype_t type, /*VALUE type_class,*/ void* memory,
+                     zval* value) {
+  native_slot_set_value_and_case(type, /*type_class,*/ memory, value, NULL, 0);
+}
+
+void native_slot_set_value_and_case(upb_fieldtype_t type, /*VALUE type_class,*/
+                                    void* memory, zval* value,
+                                    uint32_t* case_memory,
+                                    uint32_t case_number) {
+  switch (type) {
+    case UPB_TYPE_FLOAT:
+      if (!Z_TYPE_P(value) == IS_LONG) {
+        zend_error(E_ERROR, "Expected number type for float field.");
+      }
+      DEREF(memory, float) = Z_DVAL_P(value);
+      break;
+    case UPB_TYPE_DOUBLE:
+      // TODO(teboring): Add it back.
+      // if (!is_php_num(value)) {
+      //   zend_error(E_ERROR, "Expected number type for double field.");
+      // }
+      // DEREF(memory, double) = Z_DVAL_P(value);
+      break;
+    case UPB_TYPE_BOOL: {
+      int8_t val = -1;
+      if (zval_is_true(value)) {
+        val = 1;
+      } else {
+        val = 0;
+      }
+      // TODO(teboring): Add it back.
+      // else if (value == Qfalse) {
+      //   val = 0;
+      // }
+      // else {
+      //   php_raise(php_eTypeError, "Invalid argument for boolean field.");
+      // }
+      DEREF(memory, int8_t) = val;
+      break;
+    }
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      // TODO(teboring): Add it back.
+      // if (Z_TYPE_P(value) != IS_STRING) {
+      //   zend_error(E_ERROR, "Invalid argument for string field.");
+      // }
+      // native_slot_validate_string_encoding(type, value);
+      // DEREF(memory, zval*) = value;
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      // TODO(teboring): Add it back.
+      // if (CLASS_OF(value) == CLASS_OF(Qnil)) {
+      //   value = Qnil;
+      // } else if (CLASS_OF(value) != type_class) {
+      //   php_raise(php_eTypeError,
+      //            "Invalid type %s to assign to submessage field.",
+      //            php_class2name(CLASS_OF(value)));
+      // }
+      // DEREF(memory, VALUE) = value;
+      break;
+    }
+    case UPB_TYPE_ENUM: {
+      // TODO(teboring): Add it back.
+      // int32_t int_val = 0;
+      // if (!is_php_num(value) && TYPE(value) != T_SYMBOL) {
+      //   php_raise(php_eTypeError,
+      //            "Expected number or symbol type for enum field.");
+      // }
+      // if (TYPE(value) == T_SYMBOL) {
+      //   // Ensure that the given symbol exists in the enum module.
+      //   VALUE lookup = php_funcall(type_class, php_intern("resolve"), 1, value);
+      //   if (lookup == Qnil) {
+      //     php_raise(php_eRangeError, "Unknown symbol value for enum field.");
+      //   } else {
+      //     int_val = NUM2INT(lookup);
+      //   }
+      // } else {
+      //   native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
+      //   int_val = NUM2INT(value);
+      // }
+      // DEREF(memory, int32_t) = int_val;
+      // break;
+    }
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      native_slot_check_int_range_precision(type, value);
+      switch (type) {
+        case UPB_TYPE_INT32:
+          php_printf("Setting INT32 field\n");
+          DEREF(memory, int32_t) = Z_LVAL_P(value);
+          break;
+        case UPB_TYPE_INT64:
+          // TODO(teboring): Add it back.
+          // DEREF(memory, int64_t) = NUM2LL(value);
+          break;
+        case UPB_TYPE_UINT32:
+          // TODO(teboring): Add it back.
+          // DEREF(memory, uint32_t) = NUM2UINT(value);
+          break;
+        case UPB_TYPE_UINT64:
+          // TODO(teboring): Add it back.
+          // DEREF(memory, uint64_t) = NUM2ULL(value);
+          break;
+        default:
+          break;
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (case_memory != NULL) {
+    *case_memory = case_number;
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Map field utilities.
+// ----------------------------------------------------------------------------
+
+const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
+  const upb_msgdef* subdef;
+  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
+      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
+    return NULL;
+  }
+  subdef = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
+}
+
+const upb_msgdef* map_entry_msgdef(const upb_fielddef* field) {
+  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
+  assert(subdef);
+  return subdef;
+}
+
+bool is_map_field(const upb_fielddef* field) {
+  return tryget_map_entry_msgdef(field) != NULL;
+}
+
+// -----------------------------------------------------------------------------
+// Memory layout management.
+// -----------------------------------------------------------------------------
+
+static size_t align_up_to(size_t offset, size_t granularity) {
+  // Granularity must be a power of two.
+  return (offset + granularity - 1) & ~(granularity - 1);
+}
+
+MessageLayout* create_layout(const upb_msgdef* msgdef) {
+  MessageLayout* layout = ALLOC(MessageLayout);
+  int nfields = upb_msgdef_numfields(msgdef);
+  upb_msg_field_iter it;
+  upb_msg_oneof_iter oit;
+  size_t off = 0;
+
+  layout->fields = ALLOC_N(MessageField, nfields);
+
+  for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    size_t field_size;
+
+    if (upb_fielddef_containingoneof(field)) {
+      // Oneofs are handled separately below.
+      continue;
+    }
+
+    // Allocate |field_size| bytes for this field in the layout.
+    field_size = 0;
+    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      field_size = sizeof(zval*);
+    } else {
+      field_size = native_slot_size(upb_fielddef_type(field));
+    }
+
+    // Align current offset up to | size | granularity.
+    off = align_up_to(off, field_size);
+    layout->fields[upb_fielddef_index(field)].offset = off;
+    layout->fields[upb_fielddef_index(field)].case_offset =
+        MESSAGE_FIELD_NO_CASE;
+    off += field_size;
+  }
+
+  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
+  // one slot per oneof.
+  //
+  // We assign all value slots first, then pack the 'case' fields at the end,
+  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
+  // bytes respectively and we want to avoid alignment overhead.
+  //
+  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
+  // space for oneof cases is conceptually as wide as field tag numbers.  In
+  // practice, it's unlikely that a oneof would have more than e.g.  256 or 64K
+  // members (8 or 16 bits respectively), so conceivably we could assign
+  // consecutive case numbers and then pick a smaller oneof case slot size, but
+  // the complexity to implement this indirection is probably not worthwhile.
+  for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
+    // all fields.
+    size_t field_size = NATIVE_SLOT_MAX_SIZE;
+    // Align the offset .
+    off = align_up_to( off, field_size);
+    // Assign all fields in the oneof this same offset.
+    for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].offset = off;
+    }
+    off += field_size;
+  }
+
+  // Now the case fields.
+  for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    size_t field_size = sizeof(uint32_t);
+    // Align the offset .
+    off = (off + field_size - 1) & ~(field_size - 1);
+    // Assign all fields in the oneof this same offset.
+    for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].case_offset = off;
+    }
+    off += field_size;
+  }
+
+  layout->size = off;
+
+  layout->msgdef = msgdef;
+  upb_msgdef_ref(layout->msgdef, &layout->msgdef);
+
+  return layout;
+}
+
+void free_layout(MessageLayout* layout) {
+  FREE(layout->fields);
+  upb_msgdef_unref(layout->msgdef, &layout->msgdef);
+  FREE(layout);
+}
+
+// TODO(teboring): Add it back.
+// VALUE field_type_class(const upb_fielddef* field) {
+//   VALUE type_class = Qnil;
+//   if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+//     VALUE submsgdesc = get_def_obj(upb_fielddef_subdef(field));
+//     type_class = Descriptor_msgclass(submsgdesc);
+//   } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
+//     VALUE subenumdesc = get_def_obj(upb_fielddef_subdef(field));
+//     type_class = EnumDescriptor_enummodule(subenumdesc);
+//   }
+//   return type_class;
+// }
+
+static void* slot_memory(MessageLayout* layout, const void* storage,
+                         const upb_fielddef* field) {
+  return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
+}
+
+static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
+                                 const upb_fielddef* field) {
+  return (uint32_t*)(((uint8_t*)storage) +
+                     layout->fields[upb_fielddef_index(field)].case_offset);
+}
+
+void layout_set(MessageLayout* layout, void* storage, const upb_fielddef* field,
+                zval* val) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (Z_TYPE_P(val) == IS_NULL) {
+      // Assigning nil to a oneof field clears the oneof completely.
+      *oneof_case = ONEOF_CASE_NONE;
+      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+    } else {
+      // The transition between field types for a single oneof (union) slot is
+      // somewhat complex because we need to ensure that a GC triggered at any
+      // point by a call into the Ruby VM sees a valid state for this field and
+      // does not either go off into the weeds (following what it thinks is a
+      // VALUE but is actually a different field type) or miss an object (seeing
+      // what it thinks is a primitive field but is actually a VALUE for the new
+      // field type).
+      //
+      // In order for the transition to be safe, the oneof case slot must be in
+      // sync with the value slot whenever the Ruby VM has been called. Thus, we
+      // use native_slot_set_value_and_case(), which ensures that both the value
+      // and case number are altered atomically (w.r.t. the Ruby VM).
+      native_slot_set_value_and_case(upb_fielddef_type(field),
+                                     /*field_type_class(field),*/ memory, val,
+                                     oneof_case, upb_fielddef_number(field));
+    }
+  } else if (is_map_field(field)) {
+    // TODO(teboring): Add it back.
+    // check_map_field_type(val, field);
+    // DEREF(memory, zval*) = val;
+  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+    // TODO(teboring): Add it back.
+    // check_repeated_field_type(val, field);
+    // DEREF(memory, zval*) = val;
+  } else {
+    native_slot_set(upb_fielddef_type(field), /*field_type_class(field),*/ memory,
+                    val);
+  }
+}
+
+void layout_init(MessageLayout* layout, void* storage) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef); !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    void* memory = slot_memory(layout, storage, field);
+    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      // TODO(teboring): Add it back.
+      // memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+      // *oneof_case = ONEOF_CASE_NONE;
+    } else if (is_map_field(field)) {
+      // TODO(teboring): Add it back.
+      // VALUE map = Qnil;
+
+      // const upb_fielddef* key_field = map_field_key(field);
+      // const upb_fielddef* value_field = map_field_value(field);
+      // VALUE type_class = field_type_class(value_field);
+
+      // if (type_class != Qnil) {
+      //   VALUE args[3] = {
+      //       fieldtype_to_php(upb_fielddef_type(key_field)),
+      //       fieldtype_to_php(upb_fielddef_type(value_field)), type_class,
+      //   };
+      //   map = php_class_new_instance(3, args, cMap);
+      // } else {
+      //   VALUE args[2] = {
+      //       fieldtype_to_php(upb_fielddef_type(key_field)),
+      //       fieldtype_to_php(upb_fielddef_type(value_field)),
+      //   };
+      //   map = php_class_new_instance(2, args, cMap);
+      // }
+
+      // DEREF(memory, VALUE) = map;
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      // TODO(teboring): Add it back.
+      // VALUE ary = Qnil;
+
+      // VALUE type_class = field_type_class(field);
+
+      // if (type_class != Qnil) {
+      //   VALUE args[2] = {
+      //       fieldtype_to_php(upb_fielddef_type(field)), type_class,
+      //   };
+      //   ary = php_class_new_instance(2, args, cRepeatedField);
+      // } else {
+      //   VALUE args[1] = {fieldtype_to_php(upb_fielddef_type(field))};
+      //   ary = php_class_new_instance(1, args, cRepeatedField);
+      // }
+
+      // DEREF(memory, VALUE) = ary;
+    } else {
+      native_slot_init(upb_fielddef_type(field), memory);
+    }
+  }
+}
+
+zval* layout_get(MessageLayout* layout, const void* storage,
+                 const upb_fielddef* field TSRMLS_DC) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (*oneof_case != upb_fielddef_number(field)) {
+      return NULL;
+      // TODO(teboring): Add it back.
+      // return Qnil;
+    }
+      return NULL;
+    // TODO(teboring): Add it back.
+    // return native_slot_get(upb_fielddef_type(field), field_type_class(field),
+    //                        memory);
+  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      return NULL;
+    // TODO(teboring): Add it back.
+    // return *((VALUE*)memory);
+  } else {
+    return native_slot_get(
+        upb_fielddef_type(field), /*field_type_class(field), */
+        memory TSRMLS_CC);
+  }
+}
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/test.php b/src/third_party/protobuf-3/php/ext/google/protobuf/test.php
new file mode 100644
index 0000000..6bbadd4
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/test.php
@@ -0,0 +1,15 @@
+<?php
+
+
+namespace Google\Protobuf;
+
+$pool = get_generated_pool();
+$pool->addMessage("TestMessage")
+    ->optional("optional_int32_a", "int32", 1)
+    ->optional("optional_int32_b", "int32", 2)
+    ->finalizeToPool()
+    ->finalize();
+
+$test_message = new \TestMessage();
+
+?>
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/upb.c b/src/third_party/protobuf-3/php/ext/google/protobuf/upb.c
new file mode 100644
index 0000000..048a163
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/upb.c
@@ -0,0 +1,11990 @@
+// Amalgamated source file
+#include "upb.h"
+
+
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+  size_t len;
+  char str[1];  /* Null-terminated string data follows. */
+} str_t;
+
+static str_t *newstr(const char *data, size_t len) {
+  str_t *ret = malloc(sizeof(*ret) + len);
+  if (!ret) return NULL;
+  ret->len = len;
+  memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static void freestr(str_t *s) { free(s); }
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+  return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
+  bool start = true;
+  size_t i;
+  for (i = 0; i < len; i++) {
+    char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
+        return false;
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        upb_status_seterrf(
+            s, "invalid name: path components must start with a letter (%s)",
+            str);
+        return false;
+      }
+      start = false;
+    } else {
+      if (!upb_isalphanum(c)) {
+        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
+                           str);
+        return false;
+      }
+    }
+  }
+  return !start;
+}
+
+
+/* upb_def ********************************************************************/
+
+upb_deftype_t upb_def_type(const upb_def *d) { return d->type; }
+
+const char *upb_def_fullname(const upb_def *d) { return d->fullname; }
+
+bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
+  assert(!upb_def_isfrozen(def));
+  if (!upb_isident(fullname, strlen(fullname), true, s)) return false;
+  free((void*)def->fullname);
+  def->fullname = upb_strdup(fullname);
+  return true;
+}
+
+upb_def *upb_def_dup(const upb_def *def, const void *o) {
+  switch (def->type) {
+    case UPB_DEF_MSG:
+      return upb_msgdef_upcast_mutable(
+          upb_msgdef_dup(upb_downcast_msgdef(def), o));
+    case UPB_DEF_FIELD:
+      return upb_fielddef_upcast_mutable(
+          upb_fielddef_dup(upb_downcast_fielddef(def), o));
+    case UPB_DEF_ENUM:
+      return upb_enumdef_upcast_mutable(
+          upb_enumdef_dup(upb_downcast_enumdef(def), o));
+    default: assert(false); return NULL;
+  }
+}
+
+static bool upb_def_init(upb_def *def, upb_deftype_t type,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner) {
+  if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false;
+  def->type = type;
+  def->fullname = NULL;
+  def->came_from_user = false;
+  return true;
+}
+
+static void upb_def_uninit(upb_def *def) {
+  free((void*)def->fullname);
+}
+
+static const char *msgdef_name(const upb_msgdef *m) {
+  const char *name = upb_def_fullname(upb_msgdef_upcast(m));
+  return name ? name : "(anonymous)";
+}
+
+static bool upb_validate_field(upb_fielddef *f, upb_status *s) {
+  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "fielddef must have name and number set");
+    return false;
+  }
+
+  if (!f->type_is_set_) {
+    upb_status_seterrmsg(s, "fielddef type was not initialized");
+    return false;
+  }
+
+  if (upb_fielddef_lazy(f) &&
+      upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) {
+    upb_status_seterrmsg(s,
+                         "only length-delimited submessage fields may be lazy");
+    return false;
+  }
+
+  if (upb_fielddef_hassubdef(f)) {
+    const upb_def *subdef;
+
+    if (f->subdef_is_symbolic) {
+      upb_status_seterrf(s, "field '%s.%s' has not been resolved",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+
+    subdef = upb_fielddef_subdef(f);
+    if (subdef == NULL) {
+      upb_status_seterrf(s, "field %s.%s is missing required subdef",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+
+    if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) {
+      upb_status_seterrf(s,
+                         "subdef of field %s.%s is not frozen or being frozen",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    bool has_default_name = upb_fielddef_enumhasdefaultstr(f);
+    bool has_default_number = upb_fielddef_enumhasdefaultint32(f);
+
+    /* Previously verified by upb_validate_enumdef(). */
+    assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
+
+    /* We've already validated that we have an associated enumdef and that it
+     * has at least one member, so at least one of these should be true.
+     * Because if the user didn't set anything, we'll pick up the enum's
+     * default, but if the user *did* set something we should at least pick up
+     * the one they set (int32 or string). */
+    assert(has_default_name || has_default_number);
+
+    if (!has_default_name) {
+      upb_status_seterrf(s,
+                         "enum default for field %s.%s (%d) is not in the enum",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f),
+                         upb_fielddef_defaultint32(f));
+      return false;
+    }
+
+    if (!has_default_number) {
+      upb_status_seterrf(s,
+                         "enum default for field %s.%s (%s) is not in the enum",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f),
+                         upb_fielddef_defaultstr(f, NULL));
+      return false;
+    }
+
+    /* Lift the effective numeric default into the field's default slot, in case
+     * we were only getting it "by reference" from the enumdef. */
+    upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f));
+  }
+
+  /* Ensure that MapEntry submessages only appear as repeated fields, not
+   * optional/required (singular) fields. */
+  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+      upb_fielddef_msgsubdef(f) != NULL) {
+    const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
+    if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) {
+      upb_status_seterrf(s,
+                         "Field %s refers to mapentry message but is not "
+                         "a repeated field",
+                         upb_fielddef_name(f) ? upb_fielddef_name(f) :
+                         "(unnamed)");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) {
+  if (upb_enumdef_numvals(e) == 0) {
+    upb_status_seterrf(s, "enum %s has no members (must have at least one)",
+                       upb_enumdef_fullname(e));
+    return false;
+  }
+
+  return true;
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+  uint32_t ret = upb_fielddef_number(f);
+  const uint32_t high_bit = 1 << 30;
+  assert(ret < high_bit);
+  if (!upb_fielddef_issubmsg(f))
+    ret |= high_bit;
+  return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+  return field_rank(f1) - field_rank(f2);
+}
+
+static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
+  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
+   * lowest indexes, but we do not publicly guarantee this. */
+  upb_msg_field_iter j;
+  int i;
+  uint32_t selector;
+  int n = upb_msgdef_numfields(m);
+  upb_fielddef **fields = malloc(n * sizeof(*fields));
+  if (!fields) return false;
+
+  m->submsg_field_count = 0;
+  for(i = 0, upb_msg_field_begin(&j, m);
+      !upb_msg_field_done(&j);
+      upb_msg_field_next(&j), i++) {
+    upb_fielddef *f = upb_msg_iter_field(&j);
+    assert(f->msg.def == m);
+    if (!upb_validate_field(f, s)) {
+      free(fields);
+      return false;
+    }
+    if (upb_fielddef_issubmsg(f)) {
+      m->submsg_field_count++;
+    }
+    fields[i] = f;
+  }
+
+  qsort(fields, n, sizeof(*fields), cmp_fields);
+
+  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = fields[i];
+    f->index_ = i;
+    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
+    selector += upb_handlers_selectorcount(f);
+  }
+  m->selector_count = selector;
+
+#ifndef NDEBUG
+  {
+    /* Verify that all selectors for the message are distinct. */
+#define TRY(type) \
+    if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v);
+
+    upb_inttable t;
+    upb_value v;
+    upb_selector_t sel;
+
+    upb_inttable_init(&t, UPB_CTYPE_BOOL);
+    v = upb_value_bool(true);
+    upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
+    upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
+    for(upb_msg_field_begin(&j, m);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+      upb_fielddef *f = upb_msg_iter_field(&j);
+      /* These calls will assert-fail in upb_table if the value already
+       * exists. */
+      TRY(UPB_HANDLER_INT32);
+      TRY(UPB_HANDLER_INT64)
+      TRY(UPB_HANDLER_UINT32)
+      TRY(UPB_HANDLER_UINT64)
+      TRY(UPB_HANDLER_FLOAT)
+      TRY(UPB_HANDLER_DOUBLE)
+      TRY(UPB_HANDLER_BOOL)
+      TRY(UPB_HANDLER_STARTSTR)
+      TRY(UPB_HANDLER_STRING)
+      TRY(UPB_HANDLER_ENDSTR)
+      TRY(UPB_HANDLER_STARTSUBMSG)
+      TRY(UPB_HANDLER_ENDSUBMSG)
+      TRY(UPB_HANDLER_STARTSEQ)
+      TRY(UPB_HANDLER_ENDSEQ)
+    }
+    upb_inttable_uninit(&t);
+  }
+#undef TRY
+#endif
+
+  free(fields);
+  return true;
+}
+
+bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
+  int i;
+  int maxdepth;
+  bool ret;
+  upb_status_clear(s);
+
+  /* First perform validation, in two passes so we can check that we have a
+   * transitive closure without needing to search. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    if (upb_def_isfrozen(def)) {
+      /* Could relax this requirement if it's annoying. */
+      upb_status_seterrmsg(s, "def is already frozen");
+      goto err;
+    } else if (def->type == UPB_DEF_FIELD) {
+      upb_status_seterrmsg(s, "standalone fielddefs can not be frozen");
+      goto err;
+    } else if (def->type == UPB_DEF_ENUM) {
+      if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
+        goto err;
+      }
+    } else {
+      /* Set now to detect transitive closure in the second pass. */
+      def->came_from_user = true;
+    }
+  }
+
+  /* Second pass of validation.  Also assign selector bases and indexes, and
+   * compact tables. */
+  for (i = 0; i < n; i++) {
+    upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]);
+    upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]);
+    if (m) {
+      upb_inttable_compact(&m->itof);
+      if (!assign_msg_indices(m, s)) {
+        goto err;
+      }
+    } else if (e) {
+      upb_inttable_compact(&e->iton);
+    }
+  }
+
+  /* Def graph contains FieldDefs between each MessageDef, so double the
+   * limit. */
+  maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
+
+  /* Validation all passed; freeze the defs. */
+  ret = upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth);
+  assert(!(s && ret != upb_ok(s)));
+  return ret;
+
+err:
+  for (i = 0; i < n; i++) {
+    defs[i]->came_from_user = false;
+  }
+  assert(!(s && upb_ok(s)));
+  return false;
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+static void upb_enumdef_free(upb_refcounted *r) {
+  upb_enumdef *e = (upb_enumdef*)r;
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &e->iton);
+  for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    /* To clean up the upb_strdup() from upb_enumdef_addval(). */
+    free(upb_value_getcstr(upb_inttable_iter_value(&i)));
+  }
+  upb_strtable_uninit(&e->ntoi);
+  upb_inttable_uninit(&e->iton);
+  upb_def_uninit(upb_enumdef_upcast_mutable(e));
+  free(e);
+}
+
+upb_enumdef *upb_enumdef_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free};
+  upb_enumdef *e = malloc(sizeof(*e));
+  if (!e) return NULL;
+  if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner))
+    goto err2;
+  if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
+  if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
+  return e;
+
+err1:
+  upb_strtable_uninit(&e->ntoi);
+err2:
+  free(e);
+  return NULL;
+}
+
+upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) {
+  upb_enum_iter i;
+  upb_enumdef *new_e = upb_enumdef_new(owner);
+  if (!new_e) return NULL;
+  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
+    bool success = upb_enumdef_addval(
+        new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL);
+    if (!success) {
+      upb_enumdef_unref(new_e, owner);
+      return NULL;
+    }
+  }
+  return new_e;
+}
+
+bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) {
+  upb_def *d = upb_enumdef_upcast_mutable(e);
+  return upb_def_freeze(&d, 1, status);
+}
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+  return upb_def_fullname(upb_enumdef_upcast(e));
+}
+
+bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
+                             upb_status *s) {
+  return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s);
+}
+
+bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
+                        upb_status *status) {
+  if (!upb_isident(name, strlen(name), false, status)) {
+    return false;
+  }
+  if (upb_enumdef_ntoiz(e, name, NULL)) {
+    upb_status_seterrf(status, "name '%s' is already defined", name);
+    return false;
+  }
+  if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) {
+    upb_status_seterrmsg(status, "out of memory");
+    return false;
+  }
+  if (!upb_inttable_lookup(&e->iton, num, NULL) &&
+      !upb_inttable_insert(&e->iton, num, upb_value_cstr(upb_strdup(name)))) {
+    upb_status_seterrmsg(status, "out of memory");
+    upb_strtable_remove(&e->ntoi, name, NULL);
+    return false;
+  }
+  if (upb_enumdef_numvals(e) == 1) {
+    bool ok = upb_enumdef_setdefault(e, num, NULL);
+    UPB_ASSERT_VAR(ok, ok);
+  }
+  return true;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+  assert(upb_enumdef_iton(e, e->defaultval));
+  return e->defaultval;
+}
+
+bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) {
+  assert(!upb_enumdef_isfrozen(e));
+  if (!upb_enumdef_iton(e, val)) {
+    upb_status_seterrf(s, "number '%d' is not in the enum.", val);
+    return false;
+  }
+  e->defaultval = val;
+  return true;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+  return upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+  /* We iterate over the ntoi table, to account for duplicate numbers. */
+  upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+                      size_t len, int32_t *num) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+    return false;
+  }
+  if (num) *num = upb_value_getint32(v);
+  return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup32(&def->iton, num, &v) ?
+      upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+  return upb_strtable_iter_key(iter);
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+  return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+static void upb_fielddef_init_default(upb_fielddef *f);
+
+static void upb_fielddef_uninit_default(upb_fielddef *f) {
+  if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes)
+    freestr(f->defaultval.bytes);
+}
+
+static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const upb_fielddef *f = (const upb_fielddef*)r;
+  if (upb_fielddef_containingtype(f)) {
+    visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure);
+  }
+  if (upb_fielddef_containingoneof(f)) {
+    visit(r, upb_oneofdef_upcast2(upb_fielddef_containingoneof(f)), closure);
+  }
+  if (upb_fielddef_subdef(f)) {
+    visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure);
+  }
+}
+
+static void freefield(upb_refcounted *r) {
+  upb_fielddef *f = (upb_fielddef*)r;
+  upb_fielddef_uninit_default(f);
+  if (f->subdef_is_symbolic)
+    free(f->sub.name);
+  upb_def_uninit(upb_fielddef_upcast_mutable(f));
+  free(f);
+}
+
+static const char *enumdefaultstr(const upb_fielddef *f) {
+  const upb_enumdef *e;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  e = upb_fielddef_enumsubdef(f);
+  if (f->default_is_string && f->defaultval.bytes) {
+    /* Default was explicitly set as a string. */
+    str_t *s = f->defaultval.bytes;
+    return s->str;
+  } else if (e) {
+    if (!f->default_is_string) {
+      /* Default was explicitly set as an integer; look it up in enumdef. */
+      const char *name = upb_enumdef_iton(e, f->defaultval.sint);
+      if (name) {
+        return name;
+      }
+    } else {
+      /* Default is completely unset; pull enumdef default. */
+      if (upb_enumdef_numvals(e) > 0) {
+        const char *name = upb_enumdef_iton(e, upb_enumdef_default(e));
+        assert(name);
+        return name;
+      }
+    }
+  }
+  return NULL;
+}
+
+static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
+  const upb_enumdef *e;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  e = upb_fielddef_enumsubdef(f);
+  if (!f->default_is_string) {
+    /* Default was explicitly set as an integer. */
+    *val = f->defaultval.sint;
+    return true;
+  } else if (e) {
+    if (f->defaultval.bytes) {
+      /* Default was explicitly set as a str; try to lookup corresponding int. */
+      str_t *s = f->defaultval.bytes;
+      if (upb_enumdef_ntoiz(e, s->str, val)) {
+        return true;
+      }
+    } else {
+      /* Default is unset; try to pull in enumdef default. */
+      if (upb_enumdef_numvals(e) > 0) {
+        *val = upb_enumdef_default(e);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+upb_fielddef *upb_fielddef_new(const void *o) {
+  static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield};
+  upb_fielddef *f = malloc(sizeof(*f));
+  if (!f) return NULL;
+  if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) {
+    free(f);
+    return NULL;
+  }
+  f->msg.def = NULL;
+  f->sub.def = NULL;
+  f->oneof = NULL;
+  f->subdef_is_symbolic = false;
+  f->msg_is_symbolic = false;
+  f->label_ = UPB_LABEL_OPTIONAL;
+  f->type_ = UPB_TYPE_INT32;
+  f->number_ = 0;
+  f->type_is_set_ = false;
+  f->tagdelim = false;
+  f->is_extension_ = false;
+  f->lazy_ = false;
+  f->packed_ = true;
+
+  /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work
+   * with all integer types and is in some since more "default" since the most
+   * normal-looking proto2 types int32/int64/uint32/uint64 use variable.
+   *
+   * Other options to consider:
+   * - there is no default; users must set this manually (like type).
+   * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to
+   *   be an optimal default for signed integers. */
+  f->intfmt = UPB_INTFMT_VARIABLE;
+  return f;
+}
+
+upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
+  const char *srcname;
+  upb_fielddef *newf = upb_fielddef_new(owner);
+  if (!newf) return NULL;
+  upb_fielddef_settype(newf, upb_fielddef_type(f));
+  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
+  upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
+  upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
+  if (f->default_is_string && f->defaultval.bytes) {
+    str_t *s = f->defaultval.bytes;
+    upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
+  } else {
+    newf->default_is_string = f->default_is_string;
+    newf->defaultval = f->defaultval;
+  }
+
+  if (f->subdef_is_symbolic) {
+    srcname = f->sub.name;  /* Might be NULL. */
+  } else {
+    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
+  }
+  if (srcname) {
+    char *newname = malloc(strlen(f->sub.def->fullname) + 2);
+    if (!newname) {
+      upb_fielddef_unref(newf, owner);
+      return NULL;
+    }
+    strcpy(newname, ".");
+    strcat(newname, f->sub.def->fullname);
+    upb_fielddef_setsubdefname(newf, newname, NULL);
+    free(newname);
+  }
+
+  return newf;
+}
+
+bool upb_fielddef_typeisset(const upb_fielddef *f) {
+  return f->type_is_set_;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+  assert(f->type_is_set_);
+  return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+  return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+  return f->label_;
+}
+
+upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) {
+  return f->intfmt;
+}
+
+bool upb_fielddef_istagdelim(const upb_fielddef *f) {
+  return f->tagdelim;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+  return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+  return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+  return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+  return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+  return upb_def_fullname(upb_fielddef_upcast(f));
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+  return f->msg_is_symbolic ? NULL : f->msg.def;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
+upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
+  return (upb_msgdef*)upb_fielddef_containingtype(f);
+}
+
+const char *upb_fielddef_containingtypename(upb_fielddef *f) {
+  return f->msg_is_symbolic ? f->msg.name : NULL;
+}
+
+static void release_containingtype(upb_fielddef *f) {
+  if (f->msg_is_symbolic) free(f->msg.name);
+}
+
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+                                        upb_status *s) {
+  assert(!upb_fielddef_isfrozen(f));
+  if (upb_fielddef_containingtype(f)) {
+    upb_status_seterrmsg(s, "field has already been added to a message.");
+    return false;
+  }
+  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
+   * may have a leading "."). */
+  release_containingtype(f);
+  f->msg.name = upb_strdup(name);
+  f->msg_is_symbolic = true;
+  return true;
+}
+
+bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
+  if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) {
+    upb_status_seterrmsg(s, "Already added to message or oneof");
+    return false;
+  }
+  return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s);
+}
+
+static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
+  UPB_UNUSED(f);
+  UPB_UNUSED(type);
+  assert(f->type_is_set_ && upb_fielddef_type(f) == type);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT64);
+  return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+  if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    int32_t val;
+    bool ok = enumdefaultint32(f, &val);
+    UPB_ASSERT_VAR(ok, ok);
+    return val;
+  } else {
+    chkdefaulttype(f, UPB_TYPE_INT32);
+    return f->defaultval.sint;
+  }
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT64);
+  return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT32);
+  return f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_BOOL);
+  return f->defaultval.uint;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_FLOAT);
+  return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_DOUBLE);
+  return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+  assert(f->type_is_set_);
+  assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+         upb_fielddef_type(f) == UPB_TYPE_ENUM);
+
+  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    const char *ret = enumdefaultstr(f);
+    assert(ret);
+    /* Enum defaults can't have embedded NULLs. */
+    if (len) *len = strlen(ret);
+    return ret;
+  }
+
+  if (f->default_is_string) {
+    str_t *str = f->defaultval.bytes;
+    if (len) *len = str->len;
+    return str->str;
+  }
+
+  return NULL;
+}
+
+static void upb_fielddef_init_default(upb_fielddef *f) {
+  f->default_is_string = false;
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break;
+    case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64: f->defaultval.sint = 0; break;
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_BOOL: f->defaultval.uint = 0; break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      f->defaultval.bytes = newstr("", 0);
+      f->default_is_string = true;
+      break;
+    case UPB_TYPE_MESSAGE: break;
+    case UPB_TYPE_ENUM:
+      /* This is our special sentinel that indicates "not set" for an enum. */
+      f->default_is_string = true;
+      f->defaultval.bytes = NULL;
+      break;
+  }
+}
+
+const upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
+  return f->subdef_is_symbolic ? NULL : f->sub.def;
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+  const upb_def *def = upb_fielddef_subdef(f);
+  return def ? upb_dyncast_msgdef(def) : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+  const upb_def *def = upb_fielddef_subdef(f);
+  return def ? upb_dyncast_enumdef(def) : NULL;
+}
+
+upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) {
+  return (upb_def*)upb_fielddef_subdef(f);
+}
+
+const char *upb_fielddef_subdefname(const upb_fielddef *f) {
+  if (f->subdef_is_symbolic) {
+    return f->sub.name;
+  } else if (f->sub.def) {
+    return upb_def_fullname(f->sub.def);
+  } else {
+    return NULL;
+  }
+}
+
+bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
+  if (upb_fielddef_containingtype(f)) {
+    upb_status_seterrmsg(
+        s, "cannot change field number after adding to a message");
+    return false;
+  }
+  if (number == 0 || number > UPB_MAX_FIELDNUMBER) {
+    upb_status_seterrf(s, "invalid field number (%u)", number);
+    return false;
+  }
+  f->number_ = number;
+  return true;
+}
+
+void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checktype(type));
+  upb_fielddef_uninit_default(f);
+  f->type_ = type;
+  f->type_is_set_ = true;
+  upb_fielddef_init_default(f);
+}
+
+void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
+  assert(!upb_fielddef_isfrozen(f));
+  switch (type) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      upb_fielddef_settype(f, UPB_TYPE_DOUBLE);
+      break;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      upb_fielddef_settype(f, UPB_TYPE_FLOAT);
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      upb_fielddef_settype(f, UPB_TYPE_INT64);
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      upb_fielddef_settype(f, UPB_TYPE_UINT64);
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      upb_fielddef_settype(f, UPB_TYPE_INT32);
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      upb_fielddef_settype(f, UPB_TYPE_UINT32);
+      break;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      upb_fielddef_settype(f, UPB_TYPE_BOOL);
+      break;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      upb_fielddef_settype(f, UPB_TYPE_STRING);
+      break;
+    case UPB_DESCRIPTOR_TYPE_BYTES:
+      upb_fielddef_settype(f, UPB_TYPE_BYTES);
+      break;
+    case UPB_DESCRIPTOR_TYPE_GROUP:
+    case UPB_DESCRIPTOR_TYPE_MESSAGE:
+      upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
+      break;
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      upb_fielddef_settype(f, UPB_TYPE_ENUM);
+      break;
+    default: assert(false);
+  }
+
+  if (type == UPB_DESCRIPTOR_TYPE_FIXED64 ||
+      type == UPB_DESCRIPTOR_TYPE_FIXED32 ||
+      type == UPB_DESCRIPTOR_TYPE_SFIXED64 ||
+      type == UPB_DESCRIPTOR_TYPE_SFIXED32) {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED);
+  } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 ||
+             type == UPB_DESCRIPTOR_TYPE_SINT32) {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG);
+  } else {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE);
+  }
+
+  upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP);
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_FLOAT:  return UPB_DESCRIPTOR_TYPE_FLOAT;
+    case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE;
+    case UPB_TYPE_BOOL:   return UPB_DESCRIPTOR_TYPE_BOOL;
+    case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING;
+    case UPB_TYPE_BYTES:  return UPB_DESCRIPTOR_TYPE_BYTES;
+    case UPB_TYPE_ENUM:   return UPB_DESCRIPTOR_TYPE_ENUM;
+    case UPB_TYPE_INT32:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED32;
+        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT32;
+      }
+    case UPB_TYPE_INT64:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED64;
+        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT64;
+      }
+    case UPB_TYPE_UINT32:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED32;
+        case UPB_INTFMT_ZIGZAG:   return -1;
+      }
+    case UPB_TYPE_UINT64:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED64;
+        case UPB_INTFMT_ZIGZAG:   return -1;
+      }
+    case UPB_TYPE_MESSAGE:
+      return upb_fielddef_istagdelim(f) ?
+          UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE;
+  }
+  return 0;
+}
+
+void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->is_extension_ = is_extension;
+}
+
+void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->lazy_ = lazy;
+}
+
+void upb_fielddef_setpacked(upb_fielddef *f, bool packed) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->packed_ = packed;
+}
+
+void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checklabel(label));
+  f->label_ = label;
+}
+
+void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checkintfmt(fmt));
+  f->intfmt = fmt;
+}
+
+void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->tagdelim = tag_delim;
+  f->tagdelim = tag_delim;
+}
+
+static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
+  if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
+      upb_fielddef_type(f) != type) {
+    assert(false);
+    return false;
+  }
+  if (f->default_is_string) {
+    str_t *s = f->defaultval.bytes;
+    assert(s || type == UPB_TYPE_ENUM);
+    if (s) freestr(s);
+  }
+  f->default_is_string = false;
+  return true;
+}
+
+void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) {
+  if (checksetdefault(f, UPB_TYPE_INT64))
+    f->defaultval.sint = value;
+}
+
+void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) {
+  if ((upb_fielddef_type(f) == UPB_TYPE_ENUM &&
+       checksetdefault(f, UPB_TYPE_ENUM)) ||
+      checksetdefault(f, UPB_TYPE_INT32)) {
+    f->defaultval.sint = value;
+  }
+}
+
+void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) {
+  if (checksetdefault(f, UPB_TYPE_UINT64))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) {
+  if (checksetdefault(f, UPB_TYPE_UINT32))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) {
+  if (checksetdefault(f, UPB_TYPE_BOOL))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) {
+  if (checksetdefault(f, UPB_TYPE_FLOAT))
+    f->defaultval.flt = value;
+}
+
+void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
+  if (checksetdefault(f, UPB_TYPE_DOUBLE))
+    f->defaultval.dbl = value;
+}
+
+bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
+                                upb_status *s) {
+  str_t *str2;
+  assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
+  if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
+    return false;
+
+  if (f->default_is_string) {
+    str_t *s = f->defaultval.bytes;
+    assert(s || f->type_ == UPB_TYPE_ENUM);
+    if (s) freestr(s);
+  } else {
+    assert(f->type_ == UPB_TYPE_ENUM);
+  }
+
+  str2 = newstr(str, len);
+  f->defaultval.bytes = str2;
+  f->default_is_string = true;
+  return true;
+}
+
+void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
+                                 upb_status *s) {
+  assert(f->type_is_set_);
+  upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s);
+}
+
+bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) {
+  int32_t val;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  return enumdefaultint32(f, &val);
+}
+
+bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) {
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  return enumdefaultstr(f) != NULL;
+}
+
+static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef,
+                                 upb_status *s) {
+  if (f->type_ == UPB_TYPE_MESSAGE) {
+    if (upb_dyncast_msgdef(subdef)) return true;
+    upb_status_seterrmsg(s, "invalid subdef type for this submessage field");
+    return false;
+  } else if (f->type_ == UPB_TYPE_ENUM) {
+    if (upb_dyncast_enumdef(subdef)) return true;
+    upb_status_seterrmsg(s, "invalid subdef type for this enum field");
+    return false;
+  } else {
+    upb_status_seterrmsg(s, "only message and enum fields can have a subdef");
+    return false;
+  }
+}
+
+static void release_subdef(upb_fielddef *f) {
+  if (f->subdef_is_symbolic) {
+    free(f->sub.name);
+  } else if (f->sub.def) {
+    upb_unref2(f->sub.def, f);
+  }
+}
+
+bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
+                            upb_status *s) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_hassubdef(f));
+  if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false;
+  release_subdef(f);
+  f->sub.def = subdef;
+  f->subdef_is_symbolic = false;
+  if (f->sub.def) upb_ref2(f->sub.def, f);
+  return true;
+}
+
+bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
+                               upb_status *s) {
+  return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s);
+}
+
+bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
+                                upb_status *s) {
+  return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s);
+}
+
+bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
+                                upb_status *s) {
+  assert(!upb_fielddef_isfrozen(f));
+  if (!upb_fielddef_hassubdef(f)) {
+    upb_status_seterrmsg(s, "field type does not accept a subdef");
+    return false;
+  }
+  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
+   * may have a leading "."). */
+  release_subdef(f);
+  f->sub.name = upb_strdup(name);
+  f->subdef_is_symbolic = true;
+  return true;
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+  return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+  return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
+                     void *closure) {
+  upb_msg_oneof_iter o;
+  const upb_msgdef *m = (const upb_msgdef*)r;
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    visit(r, upb_fielddef_upcast2(f), closure);
+  }
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_msg_iter_oneof(&o);
+    visit(r, upb_oneofdef_upcast2(f), closure);
+  }
+}
+
+static void freemsg(upb_refcounted *r) {
+  upb_msgdef *m = (upb_msgdef*)r;
+  upb_strtable_uninit(&m->ntoo);
+  upb_strtable_uninit(&m->ntof);
+  upb_inttable_uninit(&m->itof);
+  upb_def_uninit(upb_msgdef_upcast_mutable(m));
+  free(m);
+}
+
+upb_msgdef *upb_msgdef_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg};
+  upb_msgdef *m = malloc(sizeof(*m));
+  if (!m) return NULL;
+  if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner))
+    goto err2;
+  if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3;
+  if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1;
+  m->map_entry = false;
+  return m;
+
+err1:
+  upb_strtable_uninit(&m->ntof);
+err2:
+  upb_inttable_uninit(&m->itof);
+err3:
+  free(m);
+  return NULL;
+}
+
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
+  bool ok;
+  upb_msg_field_iter i;
+  upb_msg_oneof_iter o;
+
+  upb_msgdef *newm = upb_msgdef_new(owner);
+  if (!newm) return NULL;
+  ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm),
+                           upb_def_fullname(upb_msgdef_upcast(m)),
+                           NULL);
+  newm->map_entry = m->map_entry;
+  UPB_ASSERT_VAR(ok, ok);
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
+    /* Fields in oneofs are dup'd below. */
+    if (upb_fielddef_containingoneof(f)) continue;
+    if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
+      upb_msgdef_unref(newm, owner);
+      return NULL;
+    }
+  }
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
+    if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
+      upb_msgdef_unref(newm, owner);
+      return NULL;
+    }
+  }
+  return newm;
+}
+
+bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) {
+  upb_def *d = upb_msgdef_upcast_mutable(m);
+  return upb_def_freeze(&d, 1, status);
+}
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+  return upb_def_fullname(upb_msgdef_upcast(m));
+}
+
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
+                            upb_status *s) {
+  return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s);
+}
+
+/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
+ * on status |s| and return false if not. */
+static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
+                            upb_status *s) {
+  if (upb_fielddef_containingtype(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a message");
+    return false;
+  } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_msgdef_ntofz(m, upb_fielddef_name(f)) ||
+             upb_msgdef_itof(m, upb_fielddef_number(f))) {
+    upb_status_seterrmsg(s, "duplicate field name or number for field");
+    return false;
+  }
+  return true;
+}
+
+static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) {
+  release_containingtype(f);
+  f->msg.def = m;
+  f->msg_is_symbolic = false;
+  upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, m);
+  upb_ref2(m, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+}
+
+bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
+                         upb_status *s) {
+  /* TODO: extensions need to have a separate namespace, because proto2 allows a
+   * top-level extension (ie. one not in any package) to have the same name as a
+   * field from the message.
+   *
+   * This also implies that there needs to be a separate lookup-by-name method
+   * for extensions.  It seems desirable for iteration to return both extensions
+   * and non-extensions though.
+   *
+   * We also need to validate that the field number is in an extension range iff
+   * it is an extension.
+   *
+   * This method is idempotent. Check if |f| is already part of this msgdef and
+   * return immediately if so. */
+  if (upb_fielddef_containingtype(f) == m) {
+    return true;
+  }
+
+  /* Check constraints for all fields before performing any action. */
+  if (!check_field_add(m, f, s)) {
+    return false;
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    /* Fields in a oneof can only be added by adding the oneof to the msgdef. */
+    upb_status_seterrmsg(s, "fielddef is part of a oneof");
+    return false;
+  }
+
+  /* Constraint checks ok, perform the action. */
+  add_field(m, f, ref_donor);
+  return true;
+}
+
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s) {
+  upb_oneof_iter it;
+
+  /* Check various conditions that would prevent this oneof from being added. */
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneofdef already belongs to a message");
+    return false;
+  } else if (upb_oneofdef_name(o) == NULL) {
+    upb_status_seterrmsg(s, "oneofdef name was not set");
+    return false;
+  } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) {
+    upb_status_seterrmsg(s, "duplicate oneof name");
+    return false;
+  }
+
+  /* Check that all of the oneof's fields do not conflict with names or numbers
+   * of fields already in the message. */
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&it);
+    if (!check_field_add(m, f, s)) {
+      return false;
+    }
+  }
+
+  /* Everything checks out -- commit now. */
+
+  /* Add oneof itself first. */
+  o->parent = m;
+  upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o));
+  upb_ref2(o, m);
+  upb_ref2(m, o);
+
+  /* Add each field of the oneof directly to the msgdef. */
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    upb_fielddef *f = upb_oneof_iter_field(&it);
+    add_field(m, f, NULL);
+  }
+
+  if (ref_donor) upb_oneofdef_unref(o, ref_donor);
+
+  return true;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup32(&m->itof, i, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+  return upb_strtable_lookup2(&m->ntof, name, len, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+  return upb_strtable_lookup2(&m->ntoo, name, len, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+  return upb_strtable_count(&m->ntof);
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  return upb_strtable_count(&m->ntoo);
+}
+
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
+  assert(!upb_msgdef_isfrozen(m));
+  m->map_entry = map_entry;
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+  return m->map_entry;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+  upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntoo);
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); }
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter));
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const upb_oneofdef *o = (const upb_oneofdef*)r;
+  upb_oneof_iter i;
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&i);
+    visit(r, upb_fielddef_upcast2(f), closure);
+  }
+  if (o->parent) {
+    visit(r, upb_msgdef_upcast2(o->parent), closure);
+  }
+}
+
+static void freeoneof(upb_refcounted *r) {
+  upb_oneofdef *o = (upb_oneofdef*)r;
+  upb_strtable_uninit(&o->ntof);
+  upb_inttable_uninit(&o->itof);
+  upb_def_uninit(upb_oneofdef_upcast_mutable(o));
+  free(o);
+}
+
+upb_oneofdef *upb_oneofdef_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof};
+  upb_oneofdef *o = malloc(sizeof(*o));
+  o->parent = NULL;
+  if (!o) return NULL;
+  if (!upb_def_init(upb_oneofdef_upcast_mutable(o), UPB_DEF_ONEOF, &vtbl,
+                    owner))
+    goto err2;
+  if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
+  return o;
+
+err1:
+  upb_inttable_uninit(&o->itof);
+err2:
+  free(o);
+  return NULL;
+}
+
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
+  bool ok;
+  upb_oneof_iter i;
+  upb_oneofdef *newo = upb_oneofdef_new(owner);
+  if (!newo) return NULL;
+  ok = upb_def_setfullname(upb_oneofdef_upcast_mutable(newo),
+                           upb_def_fullname(upb_oneofdef_upcast(o)), NULL);
+  UPB_ASSERT_VAR(ok, ok);
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
+    if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
+      upb_oneofdef_unref(newo, owner);
+      return NULL;
+    }
+  }
+  return newo;
+}
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+  return upb_def_fullname(upb_oneofdef_upcast(o));
+}
+
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname,
+                             upb_status *s) {
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneof already added to a message");
+    return false;
+  }
+  return upb_def_setfullname(upb_oneofdef_upcast_mutable(o), fullname, s);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return upb_strtable_count(&o->ntof);
+}
+
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s) {
+  assert(!upb_oneofdef_isfrozen(o));
+  assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
+
+  /* This method is idempotent. Check if |f| is already part of this oneofdef
+   * and return immediately if so. */
+  if (upb_fielddef_containingoneof(f) == o) {
+    return true;
+  }
+
+  /* The field must have an OPTIONAL label. */
+  if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+    upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label");
+    return false;
+  }
+
+  /* Check that no field with this name or number exists already in the oneof.
+   * Also check that the field is not already part of a oneof. */
+  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) ||
+             upb_oneofdef_ntofz(o, upb_fielddef_name(f))) {
+    upb_status_seterrmsg(s, "duplicate field name or number");
+    return false;
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a oneof");
+    return false;
+  }
+
+  /* We allow adding a field to the oneof either if the field is not part of a
+   * msgdef, or if it is and we are also part of the same msgdef. */
+  if (o->parent == NULL) {
+    /* If we're not in a msgdef, the field cannot be either. Otherwise we would
+     * need to magically add this oneof to a msgdef to remain consistent, which
+     * is surprising behavior. */
+    if (upb_fielddef_containingtype(f) != NULL) {
+      upb_status_seterrmsg(s, "fielddef already belongs to a message, but "
+                              "oneof does not");
+      return false;
+    }
+  } else {
+    /* If we're in a msgdef, the user can add fields that either aren't in any
+     * msgdef (in which case they're added to our msgdef) or already a part of
+     * our msgdef. */
+    if (upb_fielddef_containingtype(f) != NULL &&
+        upb_fielddef_containingtype(f) != o->parent) {
+      upb_status_seterrmsg(s, "fielddef belongs to a different message "
+                              "than oneof");
+      return false;
+    }
+  }
+
+  /* Commit phase. First add the field to our parent msgdef, if any, because
+   * that may fail; then add the field to our own tables. */
+
+  if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) {
+    if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) {
+      return false;
+    }
+  }
+
+  release_containingtype(f);
+  f->oneof = o;
+  upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, o);
+  upb_ref2(o, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+
+  return true;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup32(&o->itof, num, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef struct cleanup_ent {
+  upb_cleanup_func *cleanup;
+  void *ud;
+  struct cleanup_ent *next;
+} cleanup_ent;
+
+static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size);
+
+/* Default allocator **********************************************************/
+
+/* Just use realloc, keeping all allocated blocks in a linked list to destroy at
+ * the end. */
+
+typedef struct mem_block {
+  /* List is doubly-linked, because in cases where realloc() moves an existing
+   * block, we need to be able to remove the old pointer from the list
+   * efficiently. */
+  struct mem_block *prev, *next;
+#ifndef NDEBUG
+  size_t size;  /* Doesn't include mem_block structure. */
+#endif
+} mem_block;
+
+typedef struct {
+  mem_block *head;
+} default_alloc_ud;
+
+static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) {
+  default_alloc_ud *ud = _ud;
+  mem_block *from, *block;
+  void *ret;
+  UPB_UNUSED(oldsize);
+
+  from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL;
+
+#ifndef NDEBUG
+  if (from) {
+    assert(oldsize <= from->size);
+  }
+#endif
+
+  /* TODO(haberman): we probably need to provide even better alignment here,
+   * like 16-byte alignment of the returned data pointer. */
+  block = realloc(from, size + sizeof(mem_block));
+  if (!block) return NULL;
+  ret = (char*)block + sizeof(*block);
+
+#ifndef NDEBUG
+  block->size = size;
+#endif
+
+  if (from) {
+    if (block != from) {
+      /* The block was moved, so pointers in next and prev blocks must be
+       * updated to its new location. */
+      if (block->next) block->next->prev = block;
+      if (block->prev) block->prev->next = block;
+      if (ud->head == from) ud->head = block;
+    }
+  } else {
+    /* Insert at head of linked list. */
+    block->prev = NULL;
+    block->next = ud->head;
+    if (block->next) block->next->prev = block;
+    ud->head = block;
+  }
+
+  return ret;
+}
+
+static void default_alloc_cleanup(void *_ud) {
+  default_alloc_ud *ud = _ud;
+  mem_block *block = ud->head;
+
+  while (block) {
+    void *to_free = block;
+    block = block->next;
+    free(to_free);
+  }
+}
+
+
+/* Standard error functions ***************************************************/
+
+static bool default_err(void *ud, const upb_status *status) {
+  UPB_UNUSED(ud);
+  UPB_UNUSED(status);
+  return false;
+}
+
+static bool write_err_to(void *ud, const upb_status *status) {
+  upb_status *copy_to = ud;
+  upb_status_copy(copy_to, status);
+  return false;
+}
+
+
+/* upb_env ********************************************************************/
+
+void upb_env_init(upb_env *e) {
+  default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud;
+  e->ok_ = true;
+  e->bytes_allocated = 0;
+  e->cleanup_head = NULL;
+
+  ud->head = NULL;
+
+  /* Set default functions. */
+  upb_env_setallocfunc(e, default_alloc, ud);
+  upb_env_seterrorfunc(e, default_err, NULL);
+}
+
+void upb_env_uninit(upb_env *e) {
+  cleanup_ent *ent = e->cleanup_head;
+
+  while (ent) {
+    ent->cleanup(ent->ud);
+    ent = ent->next;
+  }
+
+  /* Must do this after running cleanup functions, because this will delete
+     the memory we store our cleanup entries in! */
+  if (e->alloc == default_alloc) {
+    default_alloc_cleanup(e->alloc_ud);
+  }
+}
+
+UPB_FORCEINLINE void upb_env_setallocfunc(upb_env *e, upb_alloc_func *alloc,
+                                          void *ud) {
+  e->alloc = alloc;
+  e->alloc_ud = ud;
+}
+
+UPB_FORCEINLINE void upb_env_seterrorfunc(upb_env *e, upb_error_func *func,
+                                          void *ud) {
+  e->err = func;
+  e->err_ud = ud;
+}
+
+void upb_env_reporterrorsto(upb_env *e, upb_status *status) {
+  e->err = write_err_to;
+  e->err_ud = status;
+}
+
+bool upb_env_ok(const upb_env *e) {
+  return e->ok_;
+}
+
+bool upb_env_reporterror(upb_env *e, const upb_status *status) {
+  e->ok_ = false;
+  return e->err(e->err_ud, status);
+}
+
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
+  cleanup_ent *ent = upb_env_malloc(e, sizeof(cleanup_ent));
+  if (!ent) return false;
+
+  ent->cleanup = func;
+  ent->ud = ud;
+  ent->next = e->cleanup_head;
+  e->cleanup_head = ent;
+
+  return true;
+}
+
+void *upb_env_malloc(upb_env *e, size_t size) {
+  e->bytes_allocated += size;
+  if (e->alloc == seeded_alloc) {
+    /* This is equivalent to the next branch, but allows inlining for a
+     * measurable perf benefit. */
+    return seeded_alloc(e->alloc_ud, NULL, 0, size);
+  } else {
+    return e->alloc(e->alloc_ud, NULL, 0, size);
+  }
+}
+
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
+  char *ret;
+  assert(oldsize <= size);
+  ret = e->alloc(e->alloc_ud, ptr, oldsize, size);
+
+#ifndef NDEBUG
+  /* Overwrite non-preserved memory to ensure callers are passing the oldsize
+   * that they truly require. */
+  memset(ret + oldsize, 0xff, size - oldsize);
+#endif
+
+  return ret;
+}
+
+size_t upb_env_bytesallocated(const upb_env *e) {
+  return e->bytes_allocated;
+}
+
+
+/* upb_seededalloc ************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+static const size_t maxalign = 16;
+
+static size_t align_up(size_t size) {
+  return ((size + maxalign - 1) / maxalign) * maxalign;
+}
+
+UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize,
+                                          size_t size) {
+  upb_seededalloc *a = ud;
+
+  size = align_up(size);
+
+  assert(a->mem_limit >= a->mem_ptr);
+
+  if (oldsize == 0 && size <= (size_t)(a->mem_limit - a->mem_ptr)) {
+    /* Fast path: we can satisfy from the initial allocation. */
+    void *ret = a->mem_ptr;
+    a->mem_ptr += size;
+    return ret;
+  } else {
+    char *chptr = ptr;
+    /* Slow path: fallback to other allocator. */
+    a->need_cleanup = true;
+    /* Is `ptr` part of the user-provided initial block? Don't pass it to the
+     * default allocator if so; otherwise, it may try to realloc() the block. */
+    if (chptr >= a->mem_base && chptr < a->mem_limit) {
+      void *ret;
+      assert(chptr + oldsize <= a->mem_limit);
+      ret = a->alloc(a->alloc_ud, NULL, 0, size);
+      if (ret) memcpy(ret, ptr, oldsize);
+      return ret;
+    } else {
+      return a->alloc(a->alloc_ud, ptr, oldsize, size);
+    }
+  }
+}
+
+void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len) {
+  default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud;
+  a->mem_base = mem;
+  a->mem_ptr = mem;
+  a->mem_limit = (char*)mem + len;
+  a->need_cleanup = false;
+  a->returned_allocfunc = false;
+
+  ud->head = NULL;
+
+  upb_seededalloc_setfallbackalloc(a, default_alloc, ud);
+}
+
+void upb_seededalloc_uninit(upb_seededalloc *a) {
+  if (a->alloc == default_alloc && a->need_cleanup) {
+    default_alloc_cleanup(a->alloc_ud);
+  }
+}
+
+UPB_FORCEINLINE void upb_seededalloc_setfallbackalloc(upb_seededalloc *a,
+                                                      upb_alloc_func *alloc,
+                                                      void *ud) {
+  assert(!a->returned_allocfunc);
+  a->alloc = alloc;
+  a->alloc_ud = ud;
+}
+
+upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) {
+  a->returned_allocfunc = true;
+  return seeded_alloc;
+}
+/*
+** TODO(haberman): it's unclear whether a lot of the consistency checks should
+** assert() or return false.
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+
+
+/* Defined for the sole purpose of having a unique pointer value for
+ * UPB_NO_CLOSURE. */
+char _upb_noclosure;
+
+static void freehandlers(upb_refcounted *r) {
+  upb_handlers *h = (upb_handlers*)r;
+
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &h->cleanup_);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    void *val = (void*)upb_inttable_iter_key(&i);
+    upb_value func_val = upb_inttable_iter_value(&i);
+    upb_handlerfree *func = upb_value_getfptr(func_val);
+    func(val);
+  }
+
+  upb_inttable_uninit(&h->cleanup_);
+  upb_msgdef_unref(h->msg, h);
+  free(h->sub);
+  free(h);
+}
+
+static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
+                          void *closure) {
+  const upb_handlers *h = (const upb_handlers*)r;
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, h->msg);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_handlers *sub;
+    if (!upb_fielddef_issubmsg(f)) continue;
+    sub = upb_handlers_getsubhandlers(h, f);
+    if (sub) visit(r, upb_handlers_upcast(sub), closure);
+  }
+}
+
+static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
+
+typedef struct {
+  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
+  upb_handlers_callback *callback;
+  const void *closure;
+} dfs_state;
+
+/* TODO(haberman): discard upb_handlers* objects that do not actually have any
+ * handlers set and cannot reach any upb_handlers* object that does.  This is
+ * slightly tricky to do correctly. */
+static upb_handlers *newformsg(const upb_msgdef *m, const void *owner,
+                               dfs_state *s) {
+  upb_msg_field_iter i;
+  upb_handlers *h = upb_handlers_new(m, owner);
+  if (!h) return NULL;
+  if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
+
+  s->callback(s->closure, h);
+
+  /* For each submessage field, get or create a handlers object and set it as
+   * the subhandlers. */
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_msgdef *subdef;
+    upb_value subm_ent;
+
+    if (!upb_fielddef_issubmsg(f)) continue;
+
+    subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
+    if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
+      upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
+    } else {
+      upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s);
+      if (!sub_mh) goto oom;
+      upb_handlers_setsubhandlers(h, f, sub_mh);
+      upb_handlers_unref(sub_mh, &sub_mh);
+    }
+  }
+  return h;
+
+oom:
+  upb_handlers_unref(h, owner);
+  return NULL;
+}
+
+/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
+ * subhandlers for this submessage field. */
+#define SUBH(h, selector) (h->sub[selector])
+
+/* The selector for a submessage field is the field index. */
+#define SUBH_F(h, f) SUBH(h, f->index_)
+
+static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
+                         upb_handlertype_t type) {
+  upb_selector_t sel;
+  assert(!upb_handlers_isfrozen(h));
+  if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
+    upb_status_seterrf(
+        &h->status_, "type mismatch: field %s does not belong to message %s",
+        upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h)));
+    return -1;
+  }
+  if (!upb_handlers_getselector(f, type, &sel)) {
+    upb_status_seterrf(
+        &h->status_,
+        "type mismatch: cannot register handler type %d for field %s",
+        type, upb_fielddef_name(f));
+    return -1;
+  }
+  return sel;
+}
+
+static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
+                             upb_handlertype_t type) {
+  int32_t sel = trygetsel(h, f, type);
+  assert(sel >= 0);
+  return sel;
+}
+
+static const void **returntype(upb_handlers *h, const upb_fielddef *f,
+                               upb_handlertype_t type) {
+  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_;
+}
+
+static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
+                  upb_handlertype_t type, upb_func *func,
+                  upb_handlerattr *attr) {
+  upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER;
+  const void *closure_type;
+  const void **context_closure_type;
+
+  assert(!upb_handlers_isfrozen(h));
+
+  if (sel < 0) {
+    upb_status_seterrmsg(&h->status_,
+                         "incorrect handler type for this field.");
+    return false;
+  }
+
+  if (h->table[sel].func) {
+    upb_status_seterrmsg(&h->status_,
+                         "cannot change handler once it has been set.");
+    return false;
+  }
+
+  if (attr) {
+    set_attr = *attr;
+  }
+
+  /* Check that the given closure type matches the closure type that has been
+   * established for this context (if any). */
+  closure_type = upb_handlerattr_closuretype(&set_attr);
+
+  if (type == UPB_HANDLER_STRING) {
+    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
+  } else if (f && upb_fielddef_isseq(f) &&
+             type != UPB_HANDLER_STARTSEQ &&
+             type != UPB_HANDLER_ENDSEQ) {
+    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
+  } else {
+    context_closure_type = &h->top_closure_type;
+  }
+
+  if (closure_type && *context_closure_type &&
+      closure_type != *context_closure_type) {
+    /* TODO(haberman): better message for debugging. */
+    if (f) {
+      upb_status_seterrf(&h->status_,
+                         "closure type does not match for field %s",
+                         upb_fielddef_name(f));
+    } else {
+      upb_status_seterrmsg(
+          &h->status_, "closure type does not match for message-level handler");
+    }
+    return false;
+  }
+
+  if (closure_type)
+    *context_closure_type = closure_type;
+
+  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
+   * matches any pre-existing expectations about what type is expected. */
+  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
+    const void *return_type = upb_handlerattr_returnclosuretype(&set_attr);
+    const void *table_return_type =
+        upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+    if (return_type && table_return_type && return_type != table_return_type) {
+      upb_status_seterrmsg(&h->status_, "closure return type does not match");
+      return false;
+    }
+
+    if (table_return_type && !return_type)
+      upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type);
+  }
+
+  h->table[sel].func = (upb_func*)func;
+  h->table[sel].attr = set_attr;
+  return true;
+}
+
+/* Returns the effective closure type for this handler (which will propagate
+ * from outer frames if this frame has no START* handler).  Not implemented for
+ * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
+ * the effective closure type is unspecified (either no handler was registered
+ * to specify it or the handler that was registered did not specify the closure
+ * type). */
+const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
+                                   upb_handlertype_t type) {
+  const void *ret;
+  upb_selector_t sel;
+
+  assert(type != UPB_HANDLER_STRING);
+  ret = h->top_closure_type;
+
+  if (upb_fielddef_isseq(f) &&
+      type != UPB_HANDLER_STARTSEQ &&
+      type != UPB_HANDLER_ENDSEQ &&
+      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
+    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+  }
+
+  if (type == UPB_HANDLER_STRING &&
+      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
+    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+  }
+
+  /* The effective type of the submessage; not used yet.
+   * if (type == SUBMESSAGE &&
+   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
+   *   ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+   * } */
+
+  return ret;
+}
+
+/* Checks whether the START* handler specified by f & type is missing even
+ * though it is required to convert the established type of an outer frame
+ * ("closure_type") into the established type of an inner frame (represented in
+ * the return closure type of this handler's attr. */
+bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
+                upb_status *status) {
+  const void *closure_type;
+  const upb_handlerattr *attr;
+  const void *return_closure_type;
+
+  upb_selector_t sel = handlers_getsel(h, f, type);
+  if (h->table[sel].func) return true;
+  closure_type = effective_closure_type(h, f, type);
+  attr = &h->table[sel].attr;
+  return_closure_type = upb_handlerattr_returnclosuretype(attr);
+  if (closure_type && return_closure_type &&
+      closure_type != return_closure_type) {
+    upb_status_seterrf(status,
+                       "expected start handler to return sub type for field %f",
+                       upb_fielddef_name(f));
+    return false;
+  }
+  return true;
+}
+
+/* Public interface ***********************************************************/
+
+upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) {
+  int extra;
+  upb_handlers *h;
+
+  assert(upb_msgdef_isfrozen(md));
+
+  extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
+  h = calloc(sizeof(*h) + extra, 1);
+  if (!h) return NULL;
+
+  h->msg = md;
+  upb_msgdef_ref(h->msg, h);
+  upb_status_clear(&h->status_);
+  h->sub = calloc(md->submsg_field_count, sizeof(*h->sub));
+  if (!h->sub) goto oom;
+  if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner))
+    goto oom;
+  if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom;
+
+  /* calloc() above initialized all handlers to NULL. */
+  return h;
+
+oom:
+  freehandlers(upb_handlers_upcast_mutable(h));
+  return NULL;
+}
+
+const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
+                                           const void *owner,
+                                           upb_handlers_callback *callback,
+                                           const void *closure) {
+  dfs_state state;
+  upb_handlers *ret;
+  bool ok;
+  upb_refcounted *r;
+
+  state.callback = callback;
+  state.closure = closure;
+  if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
+
+  ret = newformsg(m, owner, &state);
+
+  upb_inttable_uninit(&state.tab);
+  if (!ret) return NULL;
+
+  r = upb_handlers_upcast_mutable(ret);
+  ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
+  UPB_ASSERT_VAR(ok, ok);
+
+  return ret;
+}
+
+const upb_status *upb_handlers_status(upb_handlers *h) {
+  assert(!upb_handlers_isfrozen(h));
+  return &h->status_;
+}
+
+void upb_handlers_clearerr(upb_handlers *h) {
+  assert(!upb_handlers_isfrozen(h));
+  upb_status_clear(&h->status_);
+}
+
+#define SETTER(name, handlerctype, handlertype) \
+  bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
+                                handlerctype func, upb_handlerattr *attr) { \
+    int32_t sel = trygetsel(h, f, handlertype); \
+    return doset(h, sel, f, handlertype, (upb_func*)func, attr); \
+  }
+
+SETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
+SETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
+SETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
+SETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
+SETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
+SETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
+SETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
+SETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
+SETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
+SETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
+SETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
+SETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
+SETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
+SETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
+
+#undef SETTER
+
+bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
+                              upb_handlerattr *attr) {
+  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+               (upb_func *)func, attr);
+}
+
+bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
+                            upb_handlerattr *attr) {
+  assert(!upb_handlers_isfrozen(h));
+  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+               (upb_func *)func, attr);
+}
+
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+                                 const upb_handlers *sub) {
+  assert(sub);
+  assert(!upb_handlers_isfrozen(h));
+  assert(upb_fielddef_issubmsg(f));
+  if (SUBH_F(h, f)) return false;  /* Can't reset. */
+  if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
+    return false;
+  }
+  SUBH_F(h, f) = sub;
+  upb_ref2(sub, h);
+  return true;
+}
+
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+                                                const upb_fielddef *f) {
+  assert(upb_fielddef_issubmsg(f));
+  return SUBH_F(h, f);
+}
+
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
+                          upb_handlerattr *attr) {
+  if (!upb_handlers_gethandler(h, sel))
+    return false;
+  *attr = h->table[sel].attr;
+  return true;
+}
+
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+                                                    upb_selector_t sel) {
+  /* STARTSUBMSG selector in sel is the field's selector base. */
+  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
+}
+
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
+
+bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
+  bool ok;
+  if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) {
+    return false;
+  }
+  ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func));
+  UPB_ASSERT_VAR(ok, ok);
+  return true;
+}
+
+
+/* "Static" methods ***********************************************************/
+
+bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
+  /* TODO: verify we have a transitive closure. */
+  int i;
+  for (i = 0; i < n; i++) {
+    upb_msg_field_iter j;
+    upb_handlers *h = handlers[i];
+
+    if (!upb_ok(&h->status_)) {
+      upb_status_seterrf(s, "handlers for message %s had error status: %s",
+                         upb_msgdef_fullname(upb_handlers_msgdef(h)),
+                         upb_status_errmsg(&h->status_));
+      return false;
+    }
+
+    /* Check that there are no closure mismatches due to missing Start* handlers
+     * or subhandlers with different type-level types. */
+    for(upb_msg_field_begin(&j, h->msg);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+
+      const upb_fielddef *f = upb_msg_iter_field(&j);
+      if (upb_fielddef_isseq(f)) {
+        if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
+          return false;
+      }
+
+      if (upb_fielddef_isstring(f)) {
+        if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
+          return false;
+      }
+
+      if (upb_fielddef_issubmsg(f)) {
+        bool hashandler = false;
+        if (upb_handlers_gethandler(
+                h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
+            upb_handlers_gethandler(
+                h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
+          hashandler = true;
+        }
+
+        if (upb_fielddef_isseq(f) &&
+            (upb_handlers_gethandler(
+                 h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
+             upb_handlers_gethandler(
+                 h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
+          hashandler = true;
+        }
+
+        if (hashandler && !upb_handlers_getsubhandlers(h, f)) {
+          /* For now we add an empty subhandlers in this case.  It makes the
+           * decoder code generator simpler, because it only has to handle two
+           * cases (submessage has handlers or not) as opposed to three
+           * (submessage has handlers in enclosing message but no subhandlers).
+           *
+           * This makes parsing less efficient in the case that we want to
+           * notice a submessage but skip its contents (like if we're testing
+           * for submessage presence or counting the number of repeated
+           * submessages).  In this case we will end up parsing the submessage
+           * field by field and throwing away the results for each, instead of
+           * skipping the whole delimited thing at once.  If this is an issue we
+           * can revisit it, but do remember that this only arises when you have
+           * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the
+           * submessage but no subhandlers.  The uses cases for this are
+           * limited. */
+          upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub);
+          upb_handlers_setsubhandlers(h, f, sub);
+          upb_handlers_unref(sub, &sub);
+        }
+
+        /* TODO(haberman): check type of submessage.
+         * This is slightly tricky; also consider whether we should check that
+         * they match at setsubhandlers time. */
+      }
+    }
+  }
+
+  if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
+                             UPB_MAX_HANDLER_DEPTH)) {
+    return false;
+  }
+
+  return true;
+}
+
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
+    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
+    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
+    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
+    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
+    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
+    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
+    default: assert(false); return -1;  /* Invalid input. */
+  }
+}
+
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+                              upb_selector_t *s) {
+  switch (type) {
+    case UPB_HANDLER_INT32:
+    case UPB_HANDLER_INT64:
+    case UPB_HANDLER_UINT32:
+    case UPB_HANDLER_UINT64:
+    case UPB_HANDLER_FLOAT:
+    case UPB_HANDLER_DOUBLE:
+    case UPB_HANDLER_BOOL:
+      if (!upb_fielddef_isprimitive(f) ||
+          upb_handlers_getprimitivehandlertype(f) != type)
+        return false;
+      *s = f->selector_base;
+      break;
+    case UPB_HANDLER_STRING:
+      if (upb_fielddef_isstring(f)) {
+        *s = f->selector_base;
+      } else if (upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 3;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_STARTSTR:
+      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 1;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_ENDSTR:
+      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 2;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_STARTSEQ:
+      if (!upb_fielddef_isseq(f)) return false;
+      *s = f->selector_base - 2;
+      break;
+    case UPB_HANDLER_ENDSEQ:
+      if (!upb_fielddef_isseq(f)) return false;
+      *s = f->selector_base - 1;
+      break;
+    case UPB_HANDLER_STARTSUBMSG:
+      if (!upb_fielddef_issubmsg(f)) return false;
+      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
+       * selector can also be used as an index into the "sub" array of
+       * subhandlers.  The indexes for the two into these two tables are the
+       * same, except that in the handler table the static selectors come first. */
+      *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
+      break;
+    case UPB_HANDLER_ENDSUBMSG:
+      if (!upb_fielddef_issubmsg(f)) return false;
+      *s = f->selector_base;
+      break;
+  }
+  assert((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
+  return true;
+}
+
+uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) ? 2 : 0;
+}
+
+uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
+  uint32_t ret = 1;
+  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
+  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
+  if (upb_fielddef_issubmsg(f)) {
+    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
+    ret += 0;
+    if (upb_fielddef_lazy(f)) {
+      /* STARTSTR/ENDSTR/STRING (for lazy) */
+      ret += 3;
+    }
+  }
+  return ret;
+}
+
+
+/* upb_handlerattr ************************************************************/
+
+void upb_handlerattr_init(upb_handlerattr *attr) {
+  upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER;
+  memcpy(attr, &from, sizeof(*attr));
+}
+
+void upb_handlerattr_uninit(upb_handlerattr *attr) {
+  UPB_UNUSED(attr);
+}
+
+bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) {
+  attr->handler_data_ = hd;
+  return true;
+}
+
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) {
+  attr->closure_type_ = type;
+  return true;
+}
+
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) {
+  return attr->closure_type_;
+}
+
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+                                          const void *type) {
+  attr->return_closure_type_ = type;
+  return true;
+}
+
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) {
+  return attr->return_closure_type_;
+}
+
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) {
+  attr->alwaysok_ = alwaysok;
+  return true;
+}
+
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) {
+  return attr->alwaysok_;
+}
+
+/* upb_bufhandle **************************************************************/
+
+size_t upb_bufhandle_objofs(const upb_bufhandle *h) {
+  return h->objofs_;
+}
+
+/* upb_byteshandler ***********************************************************/
+
+void upb_byteshandler_init(upb_byteshandler* h) {
+  memset(h, 0, sizeof(*h));
+}
+
+/* For when we support handlerfree callbacks. */
+void upb_byteshandler_uninit(upb_byteshandler* h) {
+  UPB_UNUSED(h);
+}
+
+bool upb_byteshandler_setstartstr(upb_byteshandler *h,
+                                  upb_startstr_handlerfunc *func, void *d) {
+  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+
+bool upb_byteshandler_setstring(upb_byteshandler *h,
+                                upb_string_handlerfunc *func, void *d) {
+  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+
+bool upb_byteshandler_setendstr(upb_byteshandler *h,
+                                upb_endfield_handlerfunc *func, void *d) {
+  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+/*
+** upb::RefCounted Implementation
+**
+** Our key invariants are:
+** 1. reference cycles never span groups
+** 2. for ref2(to, from), we increment to's count iff group(from) != group(to)
+**
+** The previous two are how we avoid leaking cycles.  Other important
+** invariants are:
+** 3. for mutable objects "from" and "to", if there exists a ref2(to, from)
+**    this implies group(from) == group(to).  (In practice, what we implement
+**    is even stronger; "from" and "to" will share a group if there has *ever*
+**    been a ref2(to, from), but all that is necessary for correctness is the
+**    weaker one).
+** 4. mutable and immutable objects are never in the same group.
+*/
+
+
+#include <setjmp.h>
+#include <stdlib.h>
+
+static void freeobj(upb_refcounted *o);
+
+const char untracked_val;
+const void *UPB_UNTRACKED_REF = &untracked_val;
+
+/* arch-specific atomic primitives  *******************************************/
+
+#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/
+
+static void atomic_inc(uint32_t *a) { (*a)++; }
+static bool atomic_dec(uint32_t *a) { return --(*a) == 0; }
+
+#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/
+
+static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); }
+static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; }
+
+#elif defined(WIN32) /*-------------------------------------------------------*/
+
+#include <Windows.h>
+
+static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); }
+static bool atomic_dec(upb_atomic_t *a) {
+  return InterlockedDecrement(&a->val) == 0;
+}
+
+#else
+#error Atomic primitives not defined for your platform/CPU.  \
+       Implement them or compile with UPB_THREAD_UNSAFE.
+#endif
+
+/* All static objects point to this refcount.
+ * It is special-cased in ref/unref below.  */
+uint32_t static_refcount = -1;
+
+/* We can avoid atomic ops for statically-declared objects.
+ * This is a minor optimization but nice since we can avoid degrading under
+ * contention in this case. */
+
+static void refgroup(uint32_t *group) {
+  if (group != &static_refcount)
+    atomic_inc(group);
+}
+
+static bool unrefgroup(uint32_t *group) {
+  if (group == &static_refcount) {
+    return false;
+  } else {
+    return atomic_dec(group);
+  }
+}
+
+
+/* Reference tracking (debug only) ********************************************/
+
+#ifdef UPB_DEBUG_REFS
+
+#ifdef UPB_THREAD_UNSAFE
+
+static void upb_lock() {}
+static void upb_unlock() {}
+
+#else
+
+/* User must define functions that lock/unlock a global mutex and link this
+ * file against them. */
+void upb_lock();
+void upb_unlock();
+
+#endif
+
+/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some
+ * code-paths that can normally never fail, like upb_refcounted_ref().  Since
+ * we have no way to propagage out-of-memory errors back to the user, and since
+ * these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail. */
+#define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); }
+
+typedef struct {
+  int count;  /* How many refs there are (duplicates only allowed for ref2). */
+  bool is_ref2;
+} trackedref;
+
+static trackedref *trackedref_new(bool is_ref2) {
+  trackedref *ret = malloc(sizeof(*ret));
+  CHECK_OOM(ret);
+  ret->count = 1;
+  ret->is_ref2 = is_ref2;
+  return ret;
+}
+
+static void track(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+
+  assert(owner);
+  if (owner == UPB_UNTRACKED_REF) return;
+
+  upb_lock();
+  if (upb_inttable_lookupptr(r->refs, owner, &v)) {
+    trackedref *ref = upb_value_getptr(v);
+    /* Since we allow multiple ref2's for the same to/from pair without
+     * allocating separate memory for each one, we lose the fine-grained
+     * tracking behavior we get with regular refs.  Since ref2s only happen
+     * inside upb, we'll accept this limitation until/unless there is a really
+     * difficult upb-internal bug that can't be figured out without it. */
+    assert(ref2);
+    assert(ref->is_ref2);
+    ref->count++;
+  } else {
+    trackedref *ref = trackedref_new(ref2);
+    bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref));
+    CHECK_OOM(ok);
+    if (ref2) {
+      /* We know this cast is safe when it is a ref2, because it's coming from
+       * another refcounted object. */
+      const upb_refcounted *from = owner;
+      assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
+      ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL));
+      CHECK_OOM(ok);
+    }
+  }
+  upb_unlock();
+}
+
+static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+  bool found;
+  trackedref *ref;
+
+  assert(owner);
+  if (owner == UPB_UNTRACKED_REF) return;
+
+  upb_lock();
+  found = upb_inttable_lookupptr(r->refs, owner, &v);
+  /* This assert will fail if an owner attempts to release a ref it didn't have. */
+  UPB_ASSERT_VAR(found, found);
+  ref = upb_value_getptr(v);
+  assert(ref->is_ref2 == ref2);
+  if (--ref->count == 0) {
+    free(ref);
+    upb_inttable_removeptr(r->refs, owner, NULL);
+    if (ref2) {
+      /* We know this cast is safe when it is a ref2, because it's coming from
+       * another refcounted object. */
+      const upb_refcounted *from = owner;
+      bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
+      assert(removed);
+    }
+  }
+  upb_unlock();
+}
+
+static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+  bool found;
+  trackedref *ref;
+
+  upb_lock();
+  found = upb_inttable_lookupptr(r->refs, owner, &v);
+  UPB_ASSERT_VAR(found, found);
+  ref = upb_value_getptr(v);
+  assert(ref->is_ref2 == ref2);
+  upb_unlock();
+}
+
+/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that
+ * originate from the given owner. */
+static void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
+  upb_inttable_iter i;
+
+  upb_lock();
+  upb_inttable_begin(&i, owner->ref2s);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_value v;
+    upb_value count;
+    trackedref *ref;
+    bool ok;
+    bool found;
+
+    upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
+
+    /* To get the count we need to look in the target's table. */
+    found = upb_inttable_lookupptr(to->refs, owner, &v);
+    assert(found);
+    ref = upb_value_getptr(v);
+    count = upb_value_int32(ref->count);
+
+    ok = upb_inttable_insertptr(tab, to, count);
+    CHECK_OOM(ok);
+  }
+  upb_unlock();
+}
+
+typedef struct {
+  upb_inttable ref2;
+  const upb_refcounted *obj;
+} check_state;
+
+static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj,
+                        void *closure) {
+  check_state *s = closure;
+  upb_inttable *ref2 = &s->ref2;
+  upb_value v;
+  bool removed;
+  int32_t newcount;
+
+  assert(obj == s->obj);
+  assert(subobj);
+  removed = upb_inttable_removeptr(ref2, subobj, &v);
+  /* The following assertion will fail if the visit() function visits a subobj
+   * that it did not have a ref2 on, or visits the same subobj too many times. */
+  assert(removed);
+  newcount = upb_value_getint32(v) - 1;
+  if (newcount > 0) {
+    upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount));
+  }
+}
+
+static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
+                  void *closure) {
+  bool ok;
+
+  /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know
+   * exactly the set of nodes that visit() should visit.  So we verify visit()'s
+   * correctness here. */
+  check_state state;
+  state.obj = r;
+  ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32);
+  CHECK_OOM(ok);
+  getref2s(r, &state.ref2);
+
+  /* This should visit any children in the ref2 table. */
+  if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state);
+
+  /* This assertion will fail if the visit() function missed any children. */
+  assert(upb_inttable_count(&state.ref2) == 0);
+  upb_inttable_uninit(&state.ref2);
+  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
+}
+
+static bool trackinit(upb_refcounted *r) {
+  r->refs = malloc(sizeof(*r->refs));
+  r->ref2s = malloc(sizeof(*r->ref2s));
+  if (!r->refs || !r->ref2s) goto err1;
+
+  if (!upb_inttable_init(r->refs, UPB_CTYPE_PTR)) goto err1;
+  if (!upb_inttable_init(r->ref2s, UPB_CTYPE_PTR)) goto err2;
+  return true;
+
+err2:
+  upb_inttable_uninit(r->refs);
+err1:
+  free(r->refs);
+  free(r->ref2s);
+  return false;
+}
+
+static void trackfree(const upb_refcounted *r) {
+  upb_inttable_uninit(r->refs);
+  upb_inttable_uninit(r->ref2s);
+  free(r->refs);
+  free(r->ref2s);
+}
+
+#else
+
+static void track(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static bool trackinit(upb_refcounted *r) {
+  UPB_UNUSED(r);
+  return true;
+}
+
+static void trackfree(const upb_refcounted *r) {
+  UPB_UNUSED(r);
+}
+
+static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
+                  void *closure) {
+  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
+}
+
+#endif  /* UPB_DEBUG_REFS */
+
+
+/* freeze() *******************************************************************/
+
+/* The freeze() operation is by far the most complicated part of this scheme.
+ * We compute strongly-connected components and then mutate the graph such that
+ * we preserve the invariants documented at the top of this file.  And we must
+ * handle out-of-memory errors gracefully (without leaving the graph
+ * inconsistent), which adds to the fun. */
+
+/* The state used by the freeze operation (shared across many functions). */
+typedef struct {
+  int depth;
+  int maxdepth;
+  uint64_t index;
+  /* Maps upb_refcounted* -> attributes (color, etc).  attr layout varies by
+   * color. */
+  upb_inttable objattr;
+  upb_inttable stack;   /* stack of upb_refcounted* for Tarjan's algorithm. */
+  upb_inttable groups;  /* array of uint32_t*, malloc'd refcounts for new groups */
+  upb_status *status;
+  jmp_buf err;
+} tarjan;
+
+static void release_ref2(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure);
+
+/* Node attributes -----------------------------------------------------------*/
+
+/* After our analysis phase all nodes will be either GRAY or WHITE. */
+
+typedef enum {
+  BLACK = 0,  /* Object has not been seen. */
+  GRAY,   /* Object has been found via a refgroup but may not be reachable. */
+  GREEN,  /* Object is reachable and is currently on the Tarjan stack. */
+  WHITE   /* Object is reachable and has been assigned a group (SCC). */
+} color_t;
+
+UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); }
+UPB_NORETURN static void oom(tarjan *t) {
+  upb_status_seterrmsg(t->status, "out of memory");
+  err(t);
+}
+
+static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) {
+  upb_value v;
+  return upb_inttable_lookupptr(&t->objattr, r, &v) ?
+      upb_value_getuint64(v) : 0;
+}
+
+static uint64_t getattr(const tarjan *t, const upb_refcounted *r) {
+  upb_value v;
+  bool found = upb_inttable_lookupptr(&t->objattr, r, &v);
+  UPB_ASSERT_VAR(found, found);
+  return upb_value_getuint64(v);
+}
+
+static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) {
+  upb_inttable_removeptr(&t->objattr, r, NULL);
+  upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr));
+}
+
+static color_t color(tarjan *t, const upb_refcounted *r) {
+  return trygetattr(t, r) & 0x3;  /* Color is always stored in the low 2 bits. */
+}
+
+static void set_gray(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == BLACK);
+  setattr(t, r, GRAY);
+}
+
+/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */
+static void push(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == BLACK || color(t, r) == GRAY);
+  /* This defines the attr layout for the GREEN state.  "index" and "lowlink"
+   * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */
+  setattr(t, r, GREEN | (t->index << 2) | (t->index << 33));
+  if (++t->index == 0x80000000) {
+    upb_status_seterrmsg(t->status, "too many objects to freeze");
+    err(t);
+  }
+  upb_inttable_push(&t->stack, upb_value_ptr((void*)r));
+}
+
+/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its
+ * SCC group. */
+static upb_refcounted *pop(tarjan *t) {
+  upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack));
+  assert(color(t, r) == GREEN);
+  /* This defines the attr layout for nodes in the WHITE state.
+   * Top of group stack is [group, NULL]; we point at group. */
+  setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8);
+  return r;
+}
+
+static void tarjan_newgroup(tarjan *t) {
+  uint32_t *group = malloc(sizeof(*group));
+  if (!group) oom(t);
+  /* Push group and empty group leader (we'll fill in leader later). */
+  if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) ||
+      !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) {
+    free(group);
+    oom(t);
+  }
+  *group = 0;
+}
+
+static uint32_t idx(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == GREEN);
+  return (getattr(t, r) >> 2) & 0x7FFFFFFF;
+}
+
+static uint32_t lowlink(tarjan *t, const upb_refcounted *r) {
+  if (color(t, r) == GREEN) {
+    return getattr(t, r) >> 33;
+  } else {
+    return UINT32_MAX;
+  }
+}
+
+static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) {
+  assert(color(t, r) == GREEN);
+  setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF));
+}
+
+static uint32_t *group(tarjan *t, upb_refcounted *r) {
+  uint64_t groupnum;
+  upb_value v;
+  bool found;
+
+  assert(color(t, r) == WHITE);
+  groupnum = getattr(t, r) >> 8;
+  found = upb_inttable_lookup(&t->groups, groupnum, &v);
+  UPB_ASSERT_VAR(found, found);
+  return upb_value_getptr(v);
+}
+
+/* If the group leader for this object's group has not previously been set,
+ * the given object is assigned to be its leader. */
+static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) {
+  uint64_t leader_slot;
+  upb_value v;
+  bool found;
+
+  assert(color(t, r) == WHITE);
+  leader_slot = (getattr(t, r) >> 8) + 1;
+  found = upb_inttable_lookup(&t->groups, leader_slot, &v);
+  UPB_ASSERT_VAR(found, found);
+  if (upb_value_getptr(v)) {
+    return upb_value_getptr(v);
+  } else {
+    upb_inttable_remove(&t->groups, leader_slot, NULL);
+    upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r));
+    return r;
+  }
+}
+
+
+/* Tarjan's algorithm --------------------------------------------------------*/
+
+/* See:
+ *   http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */
+static void do_tarjan(const upb_refcounted *obj, tarjan *t);
+
+static void tarjan_visit(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure) {
+  tarjan *t = closure;
+  if (++t->depth > t->maxdepth) {
+    upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth);
+    err(t);
+  } else if (subobj->is_frozen || color(t, subobj) == WHITE) {
+    /* Do nothing: we don't want to visit or color already-frozen nodes,
+     * and WHITE nodes have already been assigned a SCC. */
+  } else if (color(t, subobj) < GREEN) {
+    /* Subdef has not yet been visited; recurse on it. */
+    do_tarjan(subobj, t);
+    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj)));
+  } else if (color(t, subobj) == GREEN) {
+    /* Subdef is in the stack and hence in the current SCC. */
+    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj)));
+  }
+  --t->depth;
+}
+
+static void do_tarjan(const upb_refcounted *obj, tarjan *t) {
+  if (color(t, obj) == BLACK) {
+    /* We haven't seen this object's group; mark the whole group GRAY. */
+    const upb_refcounted *o = obj;
+    do { set_gray(t, o); } while ((o = o->next) != obj);
+  }
+
+  push(t, obj);
+  visit(obj, tarjan_visit, t);
+  if (lowlink(t, obj) == idx(t, obj)) {
+    tarjan_newgroup(t);
+    while (pop(t) != obj)
+      ;
+  }
+}
+
+
+/* freeze() ------------------------------------------------------------------*/
+
+static void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
+                     void *_t) {
+  tarjan *t = _t;
+  assert(color(t, r) > BLACK);
+  if (color(t, subobj) > BLACK && r->group != subobj->group) {
+    /* Previously this ref was not reflected in subobj->group because they
+     * were in the same group; now that they are split a ref must be taken. */
+    refgroup(subobj->group);
+  }
+}
+
+static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                   int maxdepth) {
+  volatile bool ret = false;
+  int i;
+  upb_inttable_iter iter;
+
+  /* We run in two passes so that we can allocate all memory before performing
+   * any mutation of the input -- this allows us to leave the input unchanged
+   * in the case of memory allocation failure. */
+  tarjan t;
+  t.index = 0;
+  t.depth = 0;
+  t.maxdepth = maxdepth;
+  t.status = s;
+  if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1;
+  if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3;
+  if (setjmp(t.err) != 0) goto err4;
+
+
+  for (i = 0; i < n; i++) {
+    if (color(&t, roots[i]) < GREEN) {
+      do_tarjan(roots[i], &t);
+    }
+  }
+
+  /* If we've made it this far, no further errors are possible so it's safe to
+   * mutate the objects without risk of leaving them in an inconsistent state. */
+  ret = true;
+
+  /* The transformation that follows requires care.  The preconditions are:
+   * - all objects in attr map are WHITE or GRAY, and are in mutable groups
+   *   (groups of all mutable objs)
+   * - no ref2(to, from) refs have incremented count(to) if both "to" and
+   *   "from" are in our attr map (this follows from invariants (2) and (3)) */
+
+  /* Pass 1: we remove WHITE objects from their mutable groups, and add them to
+   * new groups  according to the SCC's we computed.  These new groups will
+   * consist of only frozen objects.  None will be immediately collectible,
+   * because WHITE objects are by definition reachable from one of "roots",
+   * which the caller must own refs on. */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    /* Since removal from a singly-linked list requires access to the object's
+     * predecessor, we consider obj->next instead of obj for moving.  With the
+     * while() loop we guarantee that we will visit every node's predecessor.
+     * Proof:
+     *  1. every node's predecessor is in our attr map.
+     *  2. though the loop body may change a node's predecessor, it will only
+     *     change it to be the node we are currently operating on, so with a
+     *     while() loop we guarantee ourselves the chance to remove each node. */
+    while (color(&t, obj->next) == WHITE &&
+           group(&t, obj->next) != obj->next->group) {
+      upb_refcounted *leader;
+
+      /* Remove from old group. */
+      upb_refcounted *move = obj->next;
+      if (obj == move) {
+        /* Removing the last object from a group. */
+        assert(*obj->group == obj->individual_count);
+        free(obj->group);
+      } else {
+        obj->next = move->next;
+        /* This may decrease to zero; we'll collect GRAY objects (if any) that
+         * remain in the group in the third pass. */
+        assert(*move->group >= move->individual_count);
+        *move->group -= move->individual_count;
+      }
+
+      /* Add to new group. */
+      leader = groupleader(&t, move);
+      if (move == leader) {
+        /* First object added to new group is its leader. */
+        move->group = group(&t, move);
+        move->next = move;
+        *move->group = move->individual_count;
+      } else {
+        /* Group already has at least one object in it. */
+        assert(leader->group == group(&t, move));
+        move->group = group(&t, move);
+        move->next = leader->next;
+        leader->next = move;
+        *move->group += move->individual_count;
+      }
+
+      move->is_frozen = true;
+    }
+  }
+
+  /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must
+   * increment count(to) if group(obj) != group(to) (which could now be the
+   * case if "to" was just frozen). */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    visit(obj, crossref, &t);
+  }
+
+  /* Pass 3: GRAY objects are collected if their group's refcount dropped to
+   * zero when we removed its white nodes.  This can happen if they had only
+   * been kept alive by virtue of sharing a group with an object that was just
+   * frozen.
+   *
+   * It is important that we do this last, since the GRAY object's free()
+   * function could call unref2() on just-frozen objects, which will decrement
+   * refs that were added in pass 2. */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    if (obj->group == NULL || *obj->group == 0) {
+      if (obj->group) {
+        upb_refcounted *o;
+
+        /* We eagerly free() the group's count (since we can't easily determine
+         * the group's remaining size it's the easiest way to ensure it gets
+         * done). */
+        free(obj->group);
+
+        /* Visit to release ref2's (done in a separate pass since release_ref2
+         * depends on o->group being unmodified so it can test merged()). */
+        o = obj;
+        do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj);
+
+        /* Mark "group" fields as NULL so we know to free the objects later in
+         * this loop, but also don't try to delete the group twice. */
+        o = obj;
+        do { o->group = NULL; } while ((o = o->next) != obj);
+      }
+      freeobj(obj);
+    }
+  }
+
+err4:
+  if (!ret) {
+    upb_inttable_begin(&iter, &t.groups);
+    for(; !upb_inttable_done(&iter); upb_inttable_next(&iter))
+      free(upb_value_getptr(upb_inttable_iter_value(&iter)));
+  }
+  upb_inttable_uninit(&t.groups);
+err3:
+  upb_inttable_uninit(&t.stack);
+err2:
+  upb_inttable_uninit(&t.objattr);
+err1:
+  return ret;
+}
+
+
+/* Misc internal functions  ***************************************************/
+
+static bool merged(const upb_refcounted *r, const upb_refcounted *r2) {
+  return r->group == r2->group;
+}
+
+static void merge(upb_refcounted *r, upb_refcounted *from) {
+  upb_refcounted *base;
+  upb_refcounted *tmp;
+
+  if (merged(r, from)) return;
+  *r->group += *from->group;
+  free(from->group);
+  base = from;
+
+  /* Set all refcount pointers in the "from" chain to the merged refcount.
+   *
+   * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound
+   * if the user continuously extends a group by one object.  Prevent this by
+   * using one of the techniques in this paper:
+   *     ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */
+  do { from->group = r->group; } while ((from = from->next) != base);
+
+  /* Merge the two circularly linked lists by swapping their next pointers. */
+  tmp = r->next;
+  r->next = base->next;
+  base->next = tmp;
+}
+
+static void unref(const upb_refcounted *r);
+
+static void release_ref2(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure) {
+  UPB_UNUSED(closure);
+  untrack(subobj, obj, true);
+  if (!merged(obj, subobj)) {
+    assert(subobj->is_frozen);
+    unref(subobj);
+  }
+}
+
+static void unref(const upb_refcounted *r) {
+  if (unrefgroup(r->group)) {
+    const upb_refcounted *o;
+
+    free(r->group);
+
+    /* In two passes, since release_ref2 needs a guarantee that any subobjs
+     * are alive. */
+    o = r;
+    do { visit(o, release_ref2, NULL); } while((o = o->next) != r);
+
+    o = r;
+    do {
+      const upb_refcounted *next = o->next;
+      assert(o->is_frozen || o->individual_count == 0);
+      freeobj((upb_refcounted*)o);
+      o = next;
+    } while(o != r);
+  }
+}
+
+static void freeobj(upb_refcounted *o) {
+  trackfree(o);
+  o->vtbl->free((upb_refcounted*)o);
+}
+
+
+/* Public interface ***********************************************************/
+
+bool upb_refcounted_init(upb_refcounted *r,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner) {
+#ifndef NDEBUG
+  /* Endianness check.  This is unrelated to upb_refcounted, it's just a
+   * convenient place to put the check that we can be assured will run for
+   * basically every program using upb. */
+  const int x = 1;
+#ifdef UPB_BIG_ENDIAN
+  assert(*(char*)&x != 1);
+#else
+  assert(*(char*)&x == 1);
+#endif
+#endif
+
+  r->next = r;
+  r->vtbl = vtbl;
+  r->individual_count = 0;
+  r->is_frozen = false;
+  r->group = malloc(sizeof(*r->group));
+  if (!r->group) return false;
+  *r->group = 0;
+  if (!trackinit(r)) {
+    free(r->group);
+    return false;
+  }
+  upb_refcounted_ref(r, owner);
+  return true;
+}
+
+bool upb_refcounted_isfrozen(const upb_refcounted *r) {
+  return r->is_frozen;
+}
+
+void upb_refcounted_ref(const upb_refcounted *r, const void *owner) {
+  track(r, owner, false);
+  if (!r->is_frozen)
+    ((upb_refcounted*)r)->individual_count++;
+  refgroup(r->group);
+}
+
+void upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
+  untrack(r, owner, false);
+  if (!r->is_frozen)
+    ((upb_refcounted*)r)->individual_count--;
+  unref(r);
+}
+
+void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
+  assert(!from->is_frozen);  /* Non-const pointer implies this. */
+  track(r, from, true);
+  if (r->is_frozen) {
+    refgroup(r->group);
+  } else {
+    merge((upb_refcounted*)r, from);
+  }
+}
+
+void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
+  assert(!from->is_frozen);  /* Non-const pointer implies this. */
+  untrack(r, from, true);
+  if (r->is_frozen) {
+    unref(r);
+  } else {
+    assert(merged(r, from));
+  }
+}
+
+void upb_refcounted_donateref(
+    const upb_refcounted *r, const void *from, const void *to) {
+  assert(from != to);
+  if (to != NULL)
+    upb_refcounted_ref(r, to);
+  if (from != NULL)
+    upb_refcounted_unref(r, from);
+}
+
+void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
+  checkref(r, owner, false);
+}
+
+bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                           int maxdepth) {
+  int i;
+  for (i = 0; i < n; i++) {
+    assert(!roots[i]->is_frozen);
+  }
+  return freeze(roots, n, s, maxdepth);
+}
+
+
+#include <stdlib.h>
+
+/* Fallback implementation if the shim is not specialized by the JIT. */
+#define SHIM_WRITER(type, ctype)                                              \
+  bool upb_shim_set ## type (void *c, const void *hd, ctype val) {            \
+    uint8_t *m = c;                                                           \
+    const upb_shim_data *d = hd;                                              \
+    if (d->hasbit > 0)                                                        \
+      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
+    *(ctype*)&m[d->offset] = val;                                             \
+    return true;                                                              \
+  }                                                                           \
+
+SHIM_WRITER(double, double)
+SHIM_WRITER(float,  float)
+SHIM_WRITER(int32,  int32_t)
+SHIM_WRITER(int64,  int64_t)
+SHIM_WRITER(uint32, uint32_t)
+SHIM_WRITER(uint64, uint64_t)
+SHIM_WRITER(bool,   bool)
+#undef SHIM_WRITER
+
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+                  int32_t hasbit) {
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+  bool ok;
+
+  upb_shim_data *d = malloc(sizeof(*d));
+  if (!d) return false;
+  d->offset = offset;
+  d->hasbit = hasbit;
+
+  upb_handlerattr_sethandlerdata(&attr, d);
+  upb_handlerattr_setalwaysok(&attr, true);
+  upb_handlers_addcleanup(h, d, free);
+
+#define TYPE(u, l) \
+  case UPB_TYPE_##u: \
+    ok = upb_handlers_set##l(h, f, upb_shim_set##l, &attr); break;
+
+  ok = false;
+
+  switch (upb_fielddef_type(f)) {
+    TYPE(INT64,  int64);
+    TYPE(INT32,  int32);
+    TYPE(ENUM,   int32);
+    TYPE(UINT64, uint64);
+    TYPE(UINT32, uint32);
+    TYPE(DOUBLE, double);
+    TYPE(FLOAT,  float);
+    TYPE(BOOL,   bool);
+    default: assert(false); break;
+  }
+#undef TYPE
+
+  upb_handlerattr_uninit(&attr);
+  return ok;
+}
+
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
+                                      upb_fieldtype_t *type) {
+  upb_func *f = upb_handlers_gethandler(h, s);
+
+  if ((upb_int64_handlerfunc*)f == upb_shim_setint64) {
+    *type = UPB_TYPE_INT64;
+  } else if ((upb_int32_handlerfunc*)f == upb_shim_setint32) {
+    *type = UPB_TYPE_INT32;
+  } else if ((upb_uint64_handlerfunc*)f == upb_shim_setuint64) {
+    *type = UPB_TYPE_UINT64;
+  } else if ((upb_uint32_handlerfunc*)f == upb_shim_setuint32) {
+    *type = UPB_TYPE_UINT32;
+  } else if ((upb_double_handlerfunc*)f == upb_shim_setdouble) {
+    *type = UPB_TYPE_DOUBLE;
+  } else if ((upb_float_handlerfunc*)f == upb_shim_setfloat) {
+    *type = UPB_TYPE_FLOAT;
+  } else if ((upb_bool_handlerfunc*)f == upb_shim_setbool) {
+    *type = UPB_TYPE_BOOL;
+  } else {
+    return NULL;
+  }
+
+  return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
+}
+
+
+#include <stdlib.h>
+#include <string.h>
+
+static void upb_symtab_free(upb_refcounted *r) {
+  upb_symtab *s = (upb_symtab*)r;
+  upb_strtable_iter i;
+  upb_strtable_begin(&i, &s->symtab);
+  for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
+    upb_def_unref(def, s);
+  }
+  upb_strtable_uninit(&s->symtab);
+  free(s);
+}
+
+
+upb_symtab *upb_symtab_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
+  upb_symtab *s = malloc(sizeof(*s));
+  upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner);
+  upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
+  return s;
+}
+
+void upb_symtab_freeze(upb_symtab *s) {
+  upb_refcounted *r;
+  bool ok;
+
+  assert(!upb_symtab_isfrozen(s));
+  r = upb_symtab_upcast_mutable(s);
+  /* The symtab does not take ref2's (see refcounted.h) on the defs, because
+   * defs cannot refer back to the table and therefore cannot create cycles.  So
+   * 0 will suffice for maxdepth here. */
+  ok = upb_refcounted_freeze(&r, 1, NULL, 0);
+  UPB_ASSERT_VAR(ok, ok);
+}
+
+const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return ret;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return def ? upb_dyncast_msgdef(def) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return def ? upb_dyncast_enumdef(def) : NULL;
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static upb_def *upb_resolvename(const upb_strtable *t,
+                                const char *base, const char *sym) {
+  if(strlen(sym) == 0) return NULL;
+  if(sym[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    upb_value v;
+    return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL;
+  } else {
+    /* Remove components from base until we find an entry or run out.
+     * TODO: This branch is totally broken, but currently not used. */
+    (void)base;
+    assert(false);
+    return NULL;
+  }
+}
+
+const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
+                                  const char *sym) {
+  upb_def *ret = upb_resolvename(&s->symtab, base, sym);
+  return ret;
+}
+
+/* Starts a depth-first traversal at "def", recursing into any subdefs
+ * (ie. submessage types).  Adds duplicates of existing defs to addtab
+ * wherever necessary, so that the resulting symtab will be consistent once
+ * addtab is added.
+ *
+ * More specifically, if any def D is found in the DFS that:
+ *
+ *   1. can reach a def that is being replaced by something in addtab, AND
+ *
+ *   2. is not itself being replaced already (ie. this name doesn't already
+ *      exist in addtab)
+ *
+ * ...then a duplicate (new copy) of D will be added to addtab.
+ *
+ * Returns true if this happened for any def reachable from "def."
+ *
+ * It is slightly tricky to do this correctly in the presence of cycles.  If we
+ * detect that our DFS has hit a cycle, we might not yet know if any SCCs on
+ * our stack can reach a def in addtab or not.  Once we figure this out, that
+ * answer needs to apply to *all* defs in these SCCs, even if we visited them
+ * already.  So a straight up one-pass cycle-detecting DFS won't work.
+ *
+ * To work around this problem, we traverse each SCC (which we already
+ * computed, since these defs are frozen) as a single node.  We first compute
+ * whether the SCC as a whole can reach any def in addtab, then we dup (or not)
+ * the entire SCC.  This requires breaking the encapsulation of upb_refcounted,
+ * since that is where we get the data about what SCC we are in. */
+static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
+                            const void *new_owner, upb_inttable *seen,
+                            upb_status *s) {
+  upb_value v;
+  bool need_dup;
+  const upb_def *base;
+  const void* memoize_key;
+
+  /* Memoize results of this function for efficiency (since we're traversing a
+   * DAG this is not needed to limit the depth of the search).
+   *
+   * We memoize by SCC instead of by individual def. */
+  memoize_key = def->base.group;
+
+  if (upb_inttable_lookupptr(seen, memoize_key, &v))
+    return upb_value_getbool(v);
+
+  /* Visit submessages for all messages in the SCC. */
+  need_dup = false;
+  base = def;
+  do {
+    upb_value v;
+    const upb_msgdef *m;
+
+    assert(upb_def_isfrozen(def));
+    if (def->type == UPB_DEF_FIELD) continue;
+    if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
+      need_dup = true;
+    }
+
+    /* For messages, continue the recursion by visiting all subdefs, but only
+     * ones in different SCCs. */
+    m = upb_dyncast_msgdef(def);
+    if (m) {
+      upb_msg_field_iter i;
+      for(upb_msg_field_begin(&i, m);
+          !upb_msg_field_done(&i);
+          upb_msg_field_next(&i)) {
+        upb_fielddef *f = upb_msg_iter_field(&i);
+        const upb_def *subdef;
+
+        if (!upb_fielddef_hassubdef(f)) continue;
+        subdef = upb_fielddef_subdef(f);
+
+        /* Skip subdefs in this SCC. */
+        if (def->base.group == subdef->base.group) continue;
+
+        /* |= to avoid short-circuit; we need its side-effects. */
+        need_dup |= upb_resolve_dfs(subdef, addtab, new_owner, seen, s);
+        if (!upb_ok(s)) return false;
+      }
+    }
+  } while ((def = (upb_def*)def->base.next) != base);
+
+  if (need_dup) {
+    /* Dup all defs in this SCC that don't already have entries in addtab. */
+    def = base;
+    do {
+      const char *name;
+
+      if (def->type == UPB_DEF_FIELD) continue;
+      name = upb_def_fullname(def);
+      if (!upb_strtable_lookup(addtab, name, NULL)) {
+        upb_def *newdef = upb_def_dup(def, new_owner);
+        if (!newdef) goto oom;
+        newdef->came_from_user = false;
+        if (!upb_strtable_insert(addtab, name, upb_value_ptr(newdef)))
+          goto oom;
+      }
+    } while ((def = (upb_def*)def->base.next) != base);
+  }
+
+  upb_inttable_insertptr(seen, memoize_key, upb_value_bool(need_dup));
+  return need_dup;
+
+oom:
+  upb_status_seterrmsg(s, "out of memory");
+  return false;
+}
+
+/* TODO(haberman): we need a lot more testing of error conditions.
+ * The came_from_user stuff in particular is not tested. */
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
+                    upb_status *status) {
+  int i;
+  upb_strtable_iter iter;
+  upb_def **add_defs = NULL;
+  upb_strtable addtab;
+  upb_inttable seen;
+
+  assert(!upb_symtab_isfrozen(s));
+  if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) {
+    upb_status_seterrmsg(status, "out of memory");
+    return false;
+  }
+
+  /* Add new defs to our "add" set. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    const char *fullname;
+    upb_fielddef *f;
+
+    if (upb_def_isfrozen(def)) {
+      upb_status_seterrmsg(status, "added defs must be mutable");
+      goto err;
+    }
+    assert(!upb_def_isfrozen(def));
+    fullname = upb_def_fullname(def);
+    if (!fullname) {
+      upb_status_seterrmsg(
+          status, "Anonymous defs cannot be added to a symtab");
+      goto err;
+    }
+
+    f = upb_dyncast_fielddef_mutable(def);
+
+    if (f) {
+      if (!upb_fielddef_containingtypename(f)) {
+        upb_status_seterrmsg(status,
+                             "Standalone fielddefs must have a containing type "
+                             "(extendee) name set");
+        goto err;
+      }
+    } else {
+      if (upb_strtable_lookup(&addtab, fullname, NULL)) {
+        upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
+        goto err;
+      }
+      /* We need this to back out properly, because if there is a failure we
+       * need to donate the ref back to the caller. */
+      def->came_from_user = true;
+      upb_def_donateref(def, ref_donor, s);
+      if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
+        goto oom_err;
+    }
+  }
+
+  /* Add standalone fielddefs (ie. extensions) to the appropriate messages.
+   * If the appropriate message only exists in the existing symtab, duplicate
+   * it so we have a mutable copy we can add the fields to. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
+    const char *msgname;
+    upb_value v;
+    upb_msgdef *m;
+
+    if (!f) continue;
+    msgname = upb_fielddef_containingtypename(f);
+    /* We validated this earlier in this function. */
+    assert(msgname);
+
+    /* If the extendee name is absolutely qualified, move past the initial ".".
+     * TODO(haberman): it is not obvious what it would mean if this was not
+     * absolutely qualified. */
+    if (msgname[0] == '.') {
+      msgname++;
+    }
+
+    if (upb_strtable_lookup(&addtab, msgname, &v)) {
+      /* Extendee is in the set of defs the user asked us to add. */
+      m = upb_value_getptr(v);
+    } else {
+      /* Need to find and dup the extendee from the existing symtab. */
+      const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname);
+      if (!frozen_m) {
+        upb_status_seterrf(status,
+                           "Tried to extend message %s that does not exist "
+                           "in this SymbolTable.",
+                           msgname);
+        goto err;
+      }
+      m = upb_msgdef_dup(frozen_m, s);
+      if (!m) goto oom_err;
+      if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
+        upb_msgdef_unref(m, s);
+        goto oom_err;
+      }
+    }
+
+    if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
+      goto err;
+    }
+  }
+
+  /* Add dups of any existing def that can reach a def with the same name as
+   * anything in our "add" set. */
+  if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err;
+  upb_strtable_begin(&iter, &s->symtab);
+  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+    upb_resolve_dfs(def, &addtab, s, &seen, status);
+    if (!upb_ok(status)) goto err;
+  }
+  upb_inttable_uninit(&seen);
+
+  /* Now using the table, resolve symbolic references for subdefs. */
+  upb_strtable_begin(&iter, &addtab);
+  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    const char *base;
+    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+    upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+    upb_msg_field_iter j;
+
+    if (!m) continue;
+    /* Type names are resolved relative to the message in which they appear. */
+    base = upb_msgdef_fullname(m);
+
+    for(upb_msg_field_begin(&j, m);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+      upb_fielddef *f = upb_msg_iter_field(&j);
+      const char *name = upb_fielddef_subdefname(f);
+      if (name && !upb_fielddef_subdef(f)) {
+        /* Try the lookup in the current set of to-be-added defs first. If not
+         * there, try existing defs. */
+        upb_def *subdef = upb_resolvename(&addtab, base, name);
+        if (subdef == NULL) {
+          subdef = upb_resolvename(&s->symtab, base, name);
+        }
+        if (subdef == NULL) {
+          upb_status_seterrf(
+              status, "couldn't resolve name '%s' in message '%s'", name, base);
+          goto err;
+        } else if (!upb_fielddef_setsubdef(f, subdef, status)) {
+          goto err;
+        }
+      }
+    }
+  }
+
+  /* We need an array of the defs in addtab, for passing to upb_def_freeze. */
+  add_defs = malloc(sizeof(void*) * upb_strtable_count(&addtab));
+  if (add_defs == NULL) goto oom_err;
+  upb_strtable_begin(&iter, &addtab);
+  for (n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    add_defs[n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
+  }
+
+  if (!upb_def_freeze(add_defs, n, status)) goto err;
+
+  /* This must be delayed until all errors have been detected, since error
+   * recovery code uses this table to cleanup defs. */
+  upb_strtable_uninit(&addtab);
+
+  /* TODO(haberman) we don't properly handle errors after this point (like
+   * OOM in upb_strtable_insert() below). */
+  for (i = 0; i < n; i++) {
+    upb_def *def = add_defs[i];
+    const char *name = upb_def_fullname(def);
+    upb_value v;
+    bool success;
+
+    if (upb_strtable_remove(&s->symtab, name, &v)) {
+      const upb_def *def = upb_value_getptr(v);
+      upb_def_unref(def, s);
+    }
+    success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
+    UPB_ASSERT_VAR(success, success == true);
+  }
+  free(add_defs);
+  return true;
+
+oom_err:
+  upb_status_seterrmsg(status, "out of memory");
+err: {
+    /* For defs the user passed in, we need to donate the refs back.  For defs
+     * we dup'd, we need to just unref them. */
+    upb_strtable_begin(&iter, &addtab);
+    for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+      upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+      bool came_from_user = def->came_from_user;
+      def->came_from_user = false;
+      if (came_from_user) {
+        upb_def_donateref(def, s, ref_donor);
+      } else {
+        upb_def_unref(def, s);
+      }
+    }
+  }
+  upb_strtable_uninit(&addtab);
+  free(add_defs);
+  assert(!upb_ok(status));
+  return false;
+}
+
+/* Iteration. */
+
+static void advance_to_matching(upb_symtab_iter *iter) {
+  if (iter->type == UPB_DEF_ANY)
+    return;
+
+  while (!upb_strtable_done(&iter->iter) &&
+         iter->type != upb_symtab_iter_def(iter)->type) {
+    upb_strtable_next(&iter->iter);
+  }
+}
+
+void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
+                      upb_deftype_t type) {
+  upb_strtable_begin(&iter->iter, &s->symtab);
+  iter->type = type;
+  advance_to_matching(iter);
+}
+
+void upb_symtab_next(upb_symtab_iter *iter) {
+  upb_strtable_next(&iter->iter);
+  advance_to_matching(iter);
+}
+
+bool upb_symtab_done(const upb_symtab_iter *iter) {
+  return upb_strtable_done(&iter->iter);
+}
+
+const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
+  return upb_value_getptr(upb_strtable_iter_value(&iter->iter));
+}
+/*
+** upb_table Implementation
+**
+** Implementation is heavily inspired by Lua's ltable.c.
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#define UPB_MAXARRSIZE 16  /* 64k. */
+
+/* From Chromium. */
+#define ARRAY_SIZE(x) \
+    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+static const double MAX_LOAD = 0.85;
+
+/* The minimum utilization of the array part of a mixed hash/array table.  This
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
+ * cache effects).  The lower this is, the more memory we'll use. */
+static const double MIN_DENSITY = 0.1;
+
+bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
+
+int log2ceil(uint64_t v) {
+  int ret = 0;
+  bool pow2 = is_pow2(v);
+  while (v >>= 1) ret++;
+  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
+  return UPB_MIN(UPB_MAXARRSIZE, ret);
+}
+
+char *upb_strdup(const char *s) {
+  return upb_strdup2(s, strlen(s));
+}
+
+char *upb_strdup2(const char *s, size_t len) {
+  size_t n;
+  char *p;
+
+  /* Prevent overflow errors. */
+  if (len == SIZE_MAX) return NULL;
+  /* Always null-terminate, even if binary data; but don't rely on the input to
+   * have a null-terminating byte since it may be a raw binary buffer. */
+  n = len + 1;
+  p = malloc(n);
+  if (p) {
+    memcpy(p, s, len);
+    p[len] = 0;
+  }
+  return p;
+}
+
+/* A type to represent the lookup key of either a strtable or an inttable. */
+typedef union {
+  uintptr_t num;
+  struct {
+    const char *str;
+    size_t len;
+  } str;
+} lookupkey_t;
+
+static lookupkey_t strkey2(const char *str, size_t len) {
+  lookupkey_t k;
+  k.str.str = str;
+  k.str.len = len;
+  return k;
+}
+
+static lookupkey_t intkey(uintptr_t key) {
+  lookupkey_t k;
+  k.num = key;
+  return k;
+}
+
+typedef uint32_t hashfunc_t(upb_tabkey key);
+typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
+
+/* Base table (shared code) ***************************************************/
+
+/* For when we need to cast away const. */
+static upb_tabent *mutable_entries(upb_table *t) {
+  return (upb_tabent*)t->entries;
+}
+
+static bool isfull(upb_table *t) {
+  return (double)(t->count + 1) / upb_table_size(t) > MAX_LOAD;
+}
+
+static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) {
+  size_t bytes;
+
+  t->count = 0;
+  t->ctype = ctype;
+  t->size_lg2 = size_lg2;
+  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+  bytes = upb_table_size(t) * sizeof(upb_tabent);
+  if (bytes > 0) {
+    t->entries = malloc(bytes);
+    if (!t->entries) return false;
+    memset(mutable_entries(t), 0, bytes);
+  } else {
+    t->entries = NULL;
+  }
+  return true;
+}
+
+static void uninit(upb_table *t) { free(mutable_entries(t)); }
+
+static upb_tabent *emptyent(upb_table *t) {
+  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
+  while (1) { if (upb_tabent_isempty(--e)) return e; assert(e > t->entries); }
+}
+
+static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
+  return (upb_tabent*)upb_getentry(t, hash);
+}
+
+static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
+                                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e;
+
+  if (t->size_lg2 == 0) return NULL;
+  e = upb_getentry(t, hash);
+  if (upb_tabent_isempty(e)) return NULL;
+  while (1) {
+    if (eql(e->key, key)) return e;
+    if ((e = e->next) == NULL) return NULL;
+  }
+}
+
+static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
+                                     uint32_t hash, eqlfunc_t *eql) {
+  return (upb_tabent*)findentry(t, key, hash, eql);
+}
+
+static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
+                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e = findentry(t, key, hash, eql);
+  if (e) {
+    if (v) {
+      _upb_value_setval(v, e->val.val, t->ctype);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* The given key must not already exist in the table. */
+static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
+                   upb_value val, uint32_t hash,
+                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
+  upb_tabent *mainpos_e;
+  upb_tabent *our_e;
+
+  UPB_UNUSED(eql);
+  UPB_UNUSED(key);
+  assert(findentry(t, key, hash, eql) == NULL);
+  assert(val.ctype == t->ctype);
+
+  t->count++;
+  mainpos_e = getentry_mutable(t, hash);
+  our_e = mainpos_e;
+
+  if (upb_tabent_isempty(mainpos_e)) {
+    /* Our main position is empty; use it. */
+    our_e->next = NULL;
+  } else {
+    /* Collision. */
+    upb_tabent *new_e = emptyent(t);
+    /* Head of collider's chain. */
+    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
+    if (chain == mainpos_e) {
+      /* Existing ent is in its main posisiton (it has the same hash as us, and
+       * is the head of our chain).  Insert to new ent and append to this chain. */
+      new_e->next = mainpos_e->next;
+      mainpos_e->next = new_e;
+      our_e = new_e;
+    } else {
+      /* Existing ent is not in its main position (it is a node in some other
+       * chain).  This implies that no existing ent in the table has our hash.
+       * Evict it (updating its chain) and use its ent for head of our chain. */
+      *new_e = *mainpos_e;  /* copies next. */
+      while (chain->next != mainpos_e) {
+        chain = (upb_tabent*)chain->next;
+        assert(chain);
+      }
+      chain->next = new_e;
+      our_e = mainpos_e;
+      our_e->next = NULL;
+    }
+  }
+  our_e->key = tabkey;
+  our_e->val.val = val.val;
+  assert(findentry(t, key, hash, eql) == our_e);
+}
+
+static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
+               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
+  upb_tabent *chain = getentry_mutable(t, hash);
+  if (upb_tabent_isempty(chain)) return false;
+  if (eql(chain->key, key)) {
+    /* Element to remove is at the head of its chain. */
+    t->count--;
+    if (val) {
+      _upb_value_setval(val, chain->val.val, t->ctype);
+    }
+    if (chain->next) {
+      upb_tabent *move = (upb_tabent*)chain->next;
+      *chain = *move;
+      if (removed) *removed = move->key;
+      move->key = 0;  /* Make the slot empty. */
+    } else {
+      if (removed) *removed = chain->key;
+      chain->key = 0;  /* Make the slot empty. */
+    }
+    return true;
+  } else {
+    /* Element to remove is either in a non-head position or not in the
+     * table. */
+    while (chain->next && !eql(chain->next->key, key))
+      chain = (upb_tabent*)chain->next;
+    if (chain->next) {
+      /* Found element to remove. */
+      upb_tabent *rm;
+
+      if (val) {
+        _upb_value_setval(val, chain->next->val.val, t->ctype);
+      }
+      rm = (upb_tabent*)chain->next;
+      if (removed) *removed = rm->key;
+      rm->key = 0;
+      chain->next = rm->next;
+      t->count--;
+      return true;
+    } else {
+      return false;
+    }
+  }
+}
+
+static size_t next(const upb_table *t, size_t i) {
+  do {
+    if (++i >= upb_table_size(t))
+      return SIZE_MAX;
+  } while(upb_tabent_isempty(&t->entries[i]));
+
+  return i;
+}
+
+static size_t begin(const upb_table *t) {
+  return next(t, -1);
+}
+
+
+/* upb_strtable ***************************************************************/
+
+/* A simple "subclass" of upb_table that only adds a hash function for strings. */
+
+static upb_tabkey strcopy(lookupkey_t k2) {
+  char *str = malloc(k2.str.len + sizeof(uint32_t) + 1);
+  if (str == NULL) return 0;
+  memcpy(str, &k2.str.len, sizeof(uint32_t));
+  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1);
+  return (uintptr_t)str;
+}
+
+static uint32_t strhash(upb_tabkey key) {
+  uint32_t len;
+  char *str = upb_tabstr(key, &len);
+  return MurmurHash2(str, len, 0);
+}
+
+static bool streql(upb_tabkey k1, lookupkey_t k2) {
+  uint32_t len;
+  char *str = upb_tabstr(k1, &len);
+  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
+}
+
+bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) {
+  return init(&t->t, ctype, 2);
+}
+
+void upb_strtable_uninit(upb_strtable *t) {
+  size_t i;
+  for (i = 0; i < upb_table_size(&t->t); i++)
+    free((void*)t->t.entries[i].key);
+  uninit(&t->t);
+}
+
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) {
+  upb_strtable new_table;
+  upb_strtable_iter i;
+
+  if (!init(&new_table.t, t->t.ctype, size_lg2))
+    return false;
+  upb_strtable_begin(&i, t);
+  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    upb_strtable_insert2(
+        &new_table,
+        upb_strtable_iter_key(&i),
+        upb_strtable_iter_keylength(&i),
+        upb_strtable_iter_value(&i));
+  }
+  upb_strtable_uninit(t);
+  *t = new_table;
+  return true;
+}
+
+bool upb_strtable_insert2(upb_strtable *t, const char *k, size_t len,
+                          upb_value v) {
+  lookupkey_t key;
+  upb_tabkey tabkey;
+  uint32_t hash;
+
+  if (isfull(&t->t)) {
+    /* Need to resize.  New table of double the size, add old elements to it. */
+    if (!upb_strtable_resize(t, t->t.size_lg2 + 1)) {
+      return false;
+    }
+  }
+
+  key = strkey2(k, len);
+  tabkey = strcopy(key);
+  if (tabkey == 0) return false;
+
+  hash = MurmurHash2(key.str.str, key.str.len, 0);
+  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
+  return true;
+}
+
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v) {
+  uint32_t hash = MurmurHash2(key, len, 0);
+  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
+}
+
+bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len,
+                         upb_value *val) {
+  uint32_t hash = MurmurHash2(key, strlen(key), 0);
+  upb_tabkey tabkey;
+  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
+    free((void*)tabkey);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* Iteration */
+
+static const upb_tabent *str_tabent(const upb_strtable_iter *i) {
+  return &i->t->t.entries[i->index];
+}
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
+  i->t = t;
+  i->index = begin(&t->t);
+}
+
+void upb_strtable_next(upb_strtable_iter *i) {
+  i->index = next(&i->t->t, i->index);
+}
+
+bool upb_strtable_done(const upb_strtable_iter *i) {
+  return i->index >= upb_table_size(&i->t->t) ||
+         upb_tabent_isempty(str_tabent(i));
+}
+
+const char *upb_strtable_iter_key(upb_strtable_iter *i) {
+  assert(!upb_strtable_done(i));
+  return upb_tabstr(str_tabent(i)->key, NULL);
+}
+
+size_t upb_strtable_iter_keylength(upb_strtable_iter *i) {
+  uint32_t len;
+  assert(!upb_strtable_done(i));
+  upb_tabstr(str_tabent(i)->key, &len);
+  return len;
+}
+
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
+  assert(!upb_strtable_done(i));
+  return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
+}
+
+void upb_strtable_iter_setdone(upb_strtable_iter *i) {
+  i->index = SIZE_MAX;
+}
+
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2) {
+  if (upb_strtable_done(i1) && upb_strtable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index;
+}
+
+
+/* upb_inttable ***************************************************************/
+
+/* For inttables we use a hybrid structure where small keys are kept in an
+ * array and large keys are put in the hash table. */
+
+static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
+
+static bool inteql(upb_tabkey k1, lookupkey_t k2) {
+  return k1 == k2.num;
+}
+
+static upb_tabval *mutable_array(upb_inttable *t) {
+  return (upb_tabval*)t->array;
+}
+
+static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
+  if (key < t->array_size) {
+    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
+  } else {
+    upb_tabent *e =
+        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
+    return e ? &e->val : NULL;
+  }
+}
+
+static const upb_tabval *inttable_val_const(const upb_inttable *t,
+                                            uintptr_t key) {
+  return inttable_val((upb_inttable*)t, key);
+}
+
+size_t upb_inttable_count(const upb_inttable *t) {
+  return t->t.count + t->array_count;
+}
+
+static void check(upb_inttable *t) {
+  UPB_UNUSED(t);
+#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
+  {
+    /* This check is very expensive (makes inserts/deletes O(N)). */
+    size_t count = 0;
+    upb_inttable_iter i;
+    upb_inttable_begin(&i, t);
+    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
+      assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+    }
+    assert(count == upb_inttable_count(t));
+  }
+#endif
+}
+
+bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
+                            size_t asize, int hsize_lg2) {
+  size_t array_bytes;
+
+  if (!init(&t->t, ctype, hsize_lg2)) return false;
+  /* Always make the array part at least 1 long, so that we know key 0
+   * won't be in the hash part, which simplifies things. */
+  t->array_size = UPB_MAX(1, asize);
+  t->array_count = 0;
+  array_bytes = t->array_size * sizeof(upb_value);
+  t->array = malloc(array_bytes);
+  if (!t->array) {
+    uninit(&t->t);
+    return false;
+  }
+  memset(mutable_array(t), 0xff, array_bytes);
+  check(t);
+  return true;
+}
+
+bool upb_inttable_init(upb_inttable *t, upb_ctype_t ctype) {
+  return upb_inttable_sizedinit(t, ctype, 0, 4);
+}
+
+void upb_inttable_uninit(upb_inttable *t) {
+  uninit(&t->t);
+  free(mutable_array(t));
+}
+
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
+  /* XXX: Table can't store value (uint64_t)-1.  Need to somehow statically
+   * guarantee that this is not necessary, or fix the limitation. */
+  upb_tabval tabval;
+  tabval.val = val.val;
+  UPB_UNUSED(tabval);
+  assert(upb_arrhas(tabval));
+
+  if (key < t->array_size) {
+    assert(!upb_arrhas(t->array[key]));
+    t->array_count++;
+    mutable_array(t)[key].val = val.val;
+  } else {
+    if (isfull(&t->t)) {
+      /* Need to resize the hash part, but we re-use the array part. */
+      size_t i;
+      upb_table new_table;
+      if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1))
+        return false;
+      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
+        const upb_tabent *e = &t->t.entries[i];
+        uint32_t hash;
+        upb_value v;
+
+        _upb_value_setval(&v, e->val.val, t->t.ctype);
+        hash = upb_inthash(e->key);
+        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
+      }
+
+      assert(t->t.count == new_table.count);
+
+      uninit(&t->t);
+      t->t = new_table;
+    }
+    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
+  }
+  check(t);
+  return true;
+}
+
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
+  const upb_tabval *table_v = inttable_val_const(t, key);
+  if (!table_v) return false;
+  if (v) _upb_value_setval(v, table_v->val, t->t.ctype);
+  return true;
+}
+
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
+  upb_tabval *table_v = inttable_val(t, key);
+  if (!table_v) return false;
+  table_v->val = val.val;
+  return true;
+}
+
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
+  bool success;
+  if (key < t->array_size) {
+    if (upb_arrhas(t->array[key])) {
+      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
+      t->array_count--;
+      if (val) {
+        _upb_value_setval(val, t->array[key].val, t->t.ctype);
+      }
+      mutable_array(t)[key] = empty;
+      success = true;
+    } else {
+      success = false;
+    }
+  } else {
+    upb_tabkey removed;
+    uint32_t hash = upb_inthash(key);
+    success = rm(&t->t, intkey(key), val, &removed, hash, &inteql);
+  }
+  check(t);
+  return success;
+}
+
+bool upb_inttable_push(upb_inttable *t, upb_value val) {
+  return upb_inttable_insert(t, upb_inttable_count(t), val);
+}
+
+upb_value upb_inttable_pop(upb_inttable *t) {
+  upb_value val;
+  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
+  UPB_ASSERT_VAR(ok, ok);
+  return val;
+}
+
+bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val) {
+  return upb_inttable_insert(t, (uintptr_t)key, val);
+}
+
+bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
+                            upb_value *v) {
+  return upb_inttable_lookup(t, (uintptr_t)key, v);
+}
+
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
+  return upb_inttable_remove(t, (uintptr_t)key, val);
+}
+
+void upb_inttable_compact(upb_inttable *t) {
+  /* Create a power-of-two histogram of the table keys. */
+  int counts[UPB_MAXARRSIZE + 1] = {0};
+  uintptr_t max_key = 0;
+  upb_inttable_iter i;
+  size_t arr_size;
+  int arr_count;
+  upb_inttable new_t;
+
+  upb_inttable_begin(&i, t);
+  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    uintptr_t key = upb_inttable_iter_key(&i);
+    if (key > max_key) {
+      max_key = key;
+    }
+    counts[log2ceil(key)]++;
+  }
+
+  arr_size = 1;
+  arr_count = upb_inttable_count(t);
+
+  if (upb_inttable_count(t) >= max_key * MIN_DENSITY) {
+    /* We can put 100% of the entries in the array part. */
+    arr_size = max_key + 1;
+  } else {
+    /* Find the largest power of two that satisfies the MIN_DENSITY
+     * definition. */
+    int size_lg2;
+    for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 1; size_lg2--) {
+      arr_size = 1 << size_lg2;
+      arr_count -= counts[size_lg2];
+      if (arr_count >= arr_size * MIN_DENSITY) {
+        break;
+      }
+    }
+  }
+
+  /* Array part must always be at least 1 entry large to catch lookups of key
+   * 0.  Key 0 must always be in the array part because "0" in the hash part
+   * denotes an empty entry. */
+  arr_size = UPB_MAX(arr_size, 1);
+
+  {
+    /* Insert all elements into new, perfectly-sized table. */
+    int hash_count = upb_inttable_count(t) - arr_count;
+    int hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+    int hashsize_lg2 = log2ceil(hash_size);
+
+    assert(hash_count >= 0);
+    upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2);
+    upb_inttable_begin(&i, t);
+    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+      uintptr_t k = upb_inttable_iter_key(&i);
+      upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i));
+    }
+    assert(new_t.array_size == arr_size);
+    assert(new_t.t.size_lg2 == hashsize_lg2);
+  }
+  upb_inttable_uninit(t);
+  *t = new_t;
+}
+
+/* Iteration. */
+
+static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
+  assert(!i->array_part);
+  return &i->t->t.entries[i->index];
+}
+
+static upb_tabval int_arrent(const upb_inttable_iter *i) {
+  assert(i->array_part);
+  return i->t->array[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
+  i->t = t;
+  i->index = -1;
+  i->array_part = true;
+  upb_inttable_next(i);
+}
+
+void upb_inttable_next(upb_inttable_iter *iter) {
+  const upb_inttable *t = iter->t;
+  if (iter->array_part) {
+    while (++iter->index < t->array_size) {
+      if (upb_arrhas(int_arrent(iter))) {
+        return;
+      }
+    }
+    iter->array_part = false;
+    iter->index = begin(&t->t);
+  } else {
+    iter->index = next(&t->t, iter->index);
+  }
+}
+
+bool upb_inttable_done(const upb_inttable_iter *i) {
+  if (i->array_part) {
+    return i->index >= i->t->array_size ||
+           !upb_arrhas(int_arrent(i));
+  } else {
+    return i->index >= upb_table_size(&i->t->t) ||
+           upb_tabent_isempty(int_tabent(i));
+  }
+}
+
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
+  assert(!upb_inttable_done(i));
+  return i->array_part ? i->index : int_tabent(i)->key;
+}
+
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
+  assert(!upb_inttable_done(i));
+  return _upb_value_val(
+      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
+      i->t->t.ctype);
+}
+
+void upb_inttable_iter_setdone(upb_inttable_iter *i) {
+  i->index = SIZE_MAX;
+  i->array_part = false;
+}
+
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                                          const upb_inttable_iter *i2) {
+  if (upb_inttable_done(i1) && upb_inttable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index &&
+         i1->array_part == i2->array_part;
+}
+
+#ifdef UPB_UNALIGNED_READS_OK
+/* -----------------------------------------------------------------------------
+ * MurmurHash2, by Austin Appleby (released as public domain).
+ * Reformatted and C99-ified by Joshua Haberman.
+ * Note - This code makes a few assumptions about how your machine behaves -
+ *   1. We can read a 4-byte value from any address without crashing
+ *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
+ * And it has a few limitations -
+ *   1. It will not work incrementally.
+ *   2. It will not produce the same results on little-endian and big-endian
+ *      machines. */
+uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) {
+  /* 'm' and 'r' are mixing constants generated offline.
+   * They're not really 'magic', they just happen to work well. */
+  const uint32_t m = 0x5bd1e995;
+  const int32_t r = 24;
+
+  /* Initialize the hash to a 'random' value */
+  uint32_t h = seed ^ len;
+
+  /* Mix 4 bytes at a time into the hash */
+  const uint8_t * data = (const uint8_t *)key;
+  while(len >= 4) {
+    uint32_t k = *(uint32_t *)data;
+
+    k *= m;
+    k ^= k >> r;
+    k *= m;
+
+    h *= m;
+    h ^= k;
+
+    data += 4;
+    len -= 4;
+  }
+
+  /* Handle the last few bytes of the input array */
+  switch(len) {
+    case 3: h ^= data[2] << 16;
+    case 2: h ^= data[1] << 8;
+    case 1: h ^= data[0]; h *= m;
+  };
+
+  /* Do a few final mixes of the hash to ensure the last few
+   * bytes are well-incorporated. */
+  h ^= h >> 13;
+  h *= m;
+  h ^= h >> 15;
+
+  return h;
+}
+
+#else /* !UPB_UNALIGNED_READS_OK */
+
+/* -----------------------------------------------------------------------------
+ * MurmurHashAligned2, by Austin Appleby
+ * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
+ * on certain platforms.
+ * Performance will be lower than MurmurHash2 */
+
+#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
+
+uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) {
+  const uint32_t m = 0x5bd1e995;
+  const int32_t r = 24;
+  const uint8_t * data = (const uint8_t *)key;
+  uint32_t h = seed ^ len;
+  uint8_t align = (uintptr_t)data & 3;
+
+  if(align && (len >= 4)) {
+    /* Pre-load the temp registers */
+    uint32_t t = 0, d = 0;
+    int32_t sl;
+    int32_t sr;
+
+    switch(align) {
+      case 1: t |= data[2] << 16;
+      case 2: t |= data[1] << 8;
+      case 3: t |= data[0];
+    }
+
+    t <<= (8 * align);
+
+    data += 4-align;
+    len -= 4-align;
+
+    sl = 8 * (4-align);
+    sr = 8 * align;
+
+    /* Mix */
+
+    while(len >= 4) {
+      uint32_t k;
+
+      d = *(uint32_t *)data;
+      t = (t >> sr) | (d << sl);
+
+      k = t;
+
+      MIX(h,k,m);
+
+      t = d;
+
+      data += 4;
+      len -= 4;
+    }
+
+    /* Handle leftover data in temp registers */
+
+    d = 0;
+
+    if(len >= align) {
+      uint32_t k;
+
+      switch(align) {
+        case 3: d |= data[2] << 16;
+        case 2: d |= data[1] << 8;
+        case 1: d |= data[0];
+      }
+
+      k = (t >> sr) | (d << sl);
+      MIX(h,k,m);
+
+      data += align;
+      len -= align;
+
+      /* ----------
+       * Handle tail bytes */
+
+      switch(len) {
+        case 3: h ^= data[2] << 16;
+        case 2: h ^= data[1] << 8;
+        case 1: h ^= data[0]; h *= m;
+      };
+    } else {
+      switch(len) {
+        case 3: d |= data[2] << 16;
+        case 2: d |= data[1] << 8;
+        case 1: d |= data[0];
+        case 0: h ^= (t >> sr) | (d << sl); h *= m;
+      }
+    }
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+  } else {
+    while(len >= 4) {
+      uint32_t k = *(uint32_t *)data;
+
+      MIX(h,k,m);
+
+      data += 4;
+      len -= 4;
+    }
+
+    /* ----------
+     * Handle tail bytes */
+
+    switch(len) {
+      case 3: h ^= data[2] << 16;
+      case 2: h ^= data[1] << 8;
+      case 1: h ^= data[0]; h *= m;
+    };
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+  }
+}
+#undef MIX
+
+#endif /* UPB_UNALIGNED_READS_OK */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool upb_dumptostderr(void *closure, const upb_status* status) {
+  UPB_UNUSED(closure);
+  fprintf(stderr, "%s\n", upb_status_errmsg(status));
+  return false;
+}
+
+/* Guarantee null-termination and provide ellipsis truncation.
+ * It may be tempting to "optimize" this by initializing these final
+ * four bytes up-front and then being careful never to overwrite them,
+ * this is safer and simpler. */
+static void nullz(upb_status *status) {
+  const char *ellipsis = "...";
+  size_t len = strlen(ellipsis);
+  assert(sizeof(status->msg) > len);
+  memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
+}
+
+void upb_status_clear(upb_status *status) {
+  if (!status) return;
+  status->ok_ = true;
+  status->code_ = 0;
+  status->msg[0] = '\0';
+}
+
+bool upb_ok(const upb_status *status) { return status->ok_; }
+
+upb_errorspace *upb_status_errspace(const upb_status *status) {
+  return status->error_space_;
+}
+
+int upb_status_errcode(const upb_status *status) { return status->code_; }
+
+const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
+
+void upb_status_seterrmsg(upb_status *status, const char *msg) {
+  if (!status) return;
+  status->ok_ = false;
+  strncpy(status->msg, msg, sizeof(status->msg));
+  nullz(status);
+}
+
+void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(status, fmt, args);
+  va_end(args);
+}
+
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
+  if (!status) return;
+  status->ok_ = false;
+  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+  nullz(status);
+}
+
+void upb_status_seterrcode(upb_status *status, upb_errorspace *space,
+                           int code) {
+  if (!status) return;
+  status->ok_ = false;
+  status->error_space_ = space;
+  status->code_ = code;
+  space->set_message(status, code);
+}
+
+void upb_status_copy(upb_status *to, const upb_status *from) {
+  if (!to) return;
+  *to = *from;
+}
+/* This file was generated by upbc (the upb compiler).
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+
+static const upb_msgdef msgs[20];
+static const upb_fielddef fields[81];
+static const upb_enumdef enums[4];
+static const upb_tabent strentries[236];
+static const upb_tabent intentries[14];
+static const upb_tabval arrays[232];
+
+#ifdef UPB_DEBUG_REFS
+static upb_inttable reftables[212];
+#endif
+
+static const upb_msgdef msgs[20] = {
+  UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 27, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 8, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[0]),&reftables[0], &reftables[1]),
+  UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[8], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]),&reftables[2], &reftables[3]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[20]),&reftables[4], &reftables[5]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[15], 8, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[24]),&reftables[6], &reftables[7]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[23], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]),&reftables[8], &reftables[9]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[27], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[32]),&reftables[10], &reftables[11]),
+  UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 9, 8), UPB_STRTABLE_INIT(8, 15, UPB_CTYPE_PTR, 4, &strentries[36]),&reftables[12], &reftables[13]),
+  UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 14, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[40], 32, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[52]),&reftables[14], &reftables[15]),
+  UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 39, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[72], 12, 11), UPB_STRTABLE_INIT(11, 15, UPB_CTYPE_PTR, 4, &strentries[68]),&reftables[16], &reftables[17]),
+  UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[84], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[84]),&reftables[18], &reftables[19]),
+  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 21, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[86], 64, 9), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[88]),&reftables[20], &reftables[21]),
+  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[150], 16, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[104]),&reftables[22], &reftables[23]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 13, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[166], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[108]),&reftables[24], &reftables[25]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[10], &arrays[171], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[116]),&reftables[26], &reftables[27]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[175], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[120]),&reftables[28], &reftables[29]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[12], &arrays[179], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[124]),&reftables[30], &reftables[31]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[183], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[128]),&reftables[32], &reftables[33]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 14, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[185], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[132]),&reftables[34], &reftables[35]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[190], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[140]),&reftables[36], &reftables[37]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[199], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[156]),&reftables[38], &reftables[39]),
+};
+
+static const upb_fielddef fields[81] = {
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[3], NULL, 6, 1, {0},&reftables[42], &reftables[43]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[10], NULL, 17, 6, {0},&reftables[44], &reftables[45]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[7], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[46], &reftables[47]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[6], NULL, 16, 7, {0},&reftables[48], &reftables[49]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[8], NULL, 30, 8, {0},&reftables[50], &reftables[51]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[7], NULL, 8, 3, {0},&reftables[52], &reftables[53]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[18], NULL, 11, 4, {0},&reftables[54], &reftables[55]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[56], &reftables[57]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[2]), 16, 2, {0},&reftables[58], &reftables[59]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[8], (const upb_def*)(&msgs[2]), 13, 1, {0},&reftables[60], &reftables[61]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "experimental_map_key", 9, &msgs[7], NULL, 10, 5, {0},&reftables[62], &reftables[63]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[6], NULL, 7, 2, {0},&reftables[64], &reftables[65]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[8], (const upb_def*)(&msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[9], (const upb_def*)(&msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[10], NULL, 14, 5, {0},&reftables[76], &reftables[77]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[18], NULL, 6, 1, {0},&reftables[78], &reftables[79]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[12], NULL, 7, 2, {0},&reftables[80], &reftables[81]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[19], NULL, 5, 1, {0},&reftables[82], &reftables[83]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[10], NULL, 20, 9, {0},&reftables[84], &reftables[85]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[10], NULL, 18, 7, {0},&reftables[86], &reftables[87]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[10], NULL, 13, 4, {0},&reftables[88], &reftables[89]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[10], NULL, 9, 2, {0},&reftables[90], &reftables[91]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[10], NULL, 6, 1, {0},&reftables[92], &reftables[93]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[6], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[94], &reftables[95]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[7], NULL, 9, 4, {0},&reftables[96], &reftables[97]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[17], NULL, 8, 2, {0},&reftables[98], &reftables[99]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[16], (const upb_def*)(&msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[11], NULL, 6, 1, {0},&reftables[102], &reftables[103]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[8], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[14], (const upb_def*)(&msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[8], NULL, 22, 6, {0},&reftables[108], &reftables[109]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[14], NULL, 8, 2, {0},&reftables[110], &reftables[111]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[112], &reftables[113]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[4], NULL, 4, 1, {0},&reftables[114], &reftables[115]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 24, 6, {0},&reftables[116], &reftables[117]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[12], NULL, 4, 1, {0},&reftables[118], &reftables[119]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[2], NULL, 8, 2, {0},&reftables[120], &reftables[121]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[6], NULL, 4, 1, {0},&reftables[122], &reftables[123]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[19], NULL, 2, 0, {0},&reftables[124], &reftables[125]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[18], NULL, 10, 3, {0},&reftables[126], &reftables[127]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[11], NULL, 7, 2, {0},&reftables[130], &reftables[131]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[6], NULL, 10, 3, {0},&reftables[132], &reftables[133]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[4], NULL, 7, 2, {0},&reftables[134], &reftables[135]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[10], (const upb_def*)(&enums[3]), 12, 3, {0},&reftables[136], &reftables[137]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[11]), 23, 5, {0},&reftables[138], &reftables[139]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[2], (const upb_def*)(&msgs[3]), 7, 1, {0},&reftables[140], &reftables[141]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[6], (const upb_def*)(&msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[4], (const upb_def*)(&msgs[5]), 3, 0, {0},&reftables[144], &reftables[145]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[8], (const upb_def*)(&msgs[10]), 20, 4, {0},&reftables[146], &reftables[147]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[14], (const upb_def*)(&msgs[15]), 7, 1, {0},&reftables[148], &reftables[149]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[12], (const upb_def*)(&msgs[13]), 3, 0, {0},&reftables[150], &reftables[151]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[12], NULL, 10, 3, {0},&reftables[152], &reftables[153]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[8], NULL, 25, 7, {0},&reftables[154], &reftables[155]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[7], NULL, 7, 2, {0},&reftables[156], &reftables[157]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[17], NULL, 4, 0, {0},&reftables[158], &reftables[159]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[18], NULL, 9, 2, {0},&reftables[160], &reftables[161]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[8], NULL, 35, 9, {0},&reftables[162], &reftables[163]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[10], NULL, 19, 8, {0},&reftables[164], &reftables[165]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[8], (const upb_def*)(&msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[8], (const upb_def*)(&msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[17], NULL, 7, 1, {0},&reftables[170], &reftables[171]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[172], &reftables[173]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[18], NULL, 12, 5, {0},&reftables[174], &reftables[175]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[17], NULL, 11, 3, {0},&reftables[176], &reftables[177]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[6], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[178], &reftables[179]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[6], NULL, 13, 6, {0},&reftables[180], &reftables[181]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[5], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[15], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[3], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[13], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[10], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[7], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[2], (const upb_def*)(&msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[7], NULL, 13, 6, {0},&reftables[198], &reftables[199]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[8], NULL, 38, 10, {0},&reftables[200], &reftables[201]),
+};
+
+static const upb_enumdef enums[4] = {
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[160]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[202], 4, 3), 0, &reftables[202], &reftables[203]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[164]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[206], 19, 18), 0, &reftables[204], &reftables[205]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[196]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[225], 3, 3), 0, &reftables[206], &reftables[207]),
+  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[200]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[228], 4, 3), 0, &reftables[208], &reftables[209]),
+};
+
+static const upb_tabent strentries[236] = {
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[9]), &strentries[14]},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
+  {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[40]), &strentries[22]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[30]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[49]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[12]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[48]},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "experimental_map_key"), UPB_TABVALUE_PTR_INIT(&fields[11]), &strentries[67]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[32]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[82]},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[61]), &strentries[81]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[24]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[23]), &strentries[102]},
+  {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[25]), NULL},
+  {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[31]), &strentries[106]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
+  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[54]), &strentries[122]},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[33]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[121]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[65]), &strentries[139]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[29]), &strentries[137]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[43]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[67]), &strentries[154]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[42]), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[162]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[193]},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[194]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[191]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[190]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[197]},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[203]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\047", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo.Location"), UPB_TABVALUE_PTR_INIT(&msgs[17]), NULL},
+  {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.UninterpretedOption"), UPB_TABVALUE_PTR_INIT(&msgs[18]), NULL},
+  {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.FileDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[8]), NULL},
+  {UPB_TABKEY_STR("\045", "\000", "\000", "\000", "google.protobuf.MethodDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[12]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\040", "\000", "\000", "\000", "google.protobuf.EnumValueOptions"), UPB_TABVALUE_PTR_INIT(&msgs[5]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "google.protobuf.DescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[0]), &strentries[228]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo"), UPB_TABVALUE_PTR_INIT(&msgs[16]), NULL},
+  {UPB_TABKEY_STR("\051", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Type"), UPB_TABVALUE_PTR_INIT(&enums[1]), NULL},
+  {UPB_TABKEY_STR("\056", "\000", "\000", "\000", "google.protobuf.DescriptorProto.ExtensionRange"), UPB_TABVALUE_PTR_INIT(&msgs[1]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.EnumValueDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[4]), NULL},
+  {UPB_TABKEY_STR("\034", "\000", "\000", "\000", "google.protobuf.FieldOptions"), UPB_TABVALUE_PTR_INIT(&msgs[7]), NULL},
+  {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.FileOptions"), UPB_TABVALUE_PTR_INIT(&msgs[10]), NULL},
+  {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.EnumDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[2]), &strentries[233]},
+  {UPB_TABKEY_STR("\052", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Label"), UPB_TABVALUE_PTR_INIT(&enums[0]), NULL},
+  {UPB_TABKEY_STR("\046", "\000", "\000", "\000", "google.protobuf.ServiceDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[14]), NULL},
+  {UPB_TABKEY_STR("\042", "\000", "\000", "\000", "google.protobuf.FieldOptions.CType"), UPB_TABVALUE_PTR_INIT(&enums[2]), &strentries[229]},
+  {UPB_TABKEY_STR("\041", "\000", "\000", "\000", "google.protobuf.FileDescriptorSet"), UPB_TABVALUE_PTR_INIT(&msgs[9]), &strentries[235]},
+  {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.EnumOptions"), UPB_TABVALUE_PTR_INIT(&msgs[3]), NULL},
+  {UPB_TABKEY_STR("\044", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[6]), NULL},
+  {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.FileOptions.OptimizeMode"), UPB_TABVALUE_PTR_INIT(&enums[3]), &strentries[221]},
+  {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.ServiceOptions"), UPB_TABVALUE_PTR_INIT(&msgs[15]), NULL},
+  {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.MessageOptions"), UPB_TABVALUE_PTR_INIT(&msgs[11]), NULL},
+  {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "google.protobuf.MethodOptions"), UPB_TABVALUE_PTR_INIT(&msgs[13]), &strentries[226]},
+  {UPB_TABKEY_STR("\054", "\000", "\000", "\000", "google.protobuf.UninterpretedOption.NamePart"), UPB_TABVALUE_PTR_INIT(&msgs[19]), NULL},
+};
+
+static const upb_tabent intentries[14] = {
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL},
+};
+
+static const upb_tabval arrays[232] = {
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[38]),
+  UPB_TABVALUE_PTR_INIT(&fields[16]),
+  UPB_TABVALUE_PTR_INIT(&fields[44]),
+  UPB_TABVALUE_PTR_INIT(&fields[9]),
+  UPB_TABVALUE_PTR_INIT(&fields[15]),
+  UPB_TABVALUE_PTR_INIT(&fields[14]),
+  UPB_TABVALUE_PTR_INIT(&fields[49]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[66]),
+  UPB_TABVALUE_PTR_INIT(&fields[8]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[40]),
+  UPB_TABVALUE_PTR_INIT(&fields[78]),
+  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[1]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[37]),
+  UPB_TABVALUE_PTR_INIT(&fields[47]),
+  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[41]),
+  UPB_TABVALUE_PTR_INIT(&fields[12]),
+  UPB_TABVALUE_PTR_INIT(&fields[46]),
+  UPB_TABVALUE_PTR_INIT(&fields[27]),
+  UPB_TABVALUE_PTR_INIT(&fields[69]),
+  UPB_TABVALUE_PTR_INIT(&fields[70]),
+  UPB_TABVALUE_PTR_INIT(&fields[4]),
+  UPB_TABVALUE_PTR_INIT(&fields[51]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[3]),
+  UPB_TABVALUE_PTR_INIT(&fields[58]),
+  UPB_TABVALUE_PTR_INIT(&fields[6]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[28]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[11]),
+  UPB_TABVALUE_PTR_INIT(&fields[79]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[34]),
+  UPB_TABVALUE_PTR_INIT(&fields[57]),
+  UPB_TABVALUE_PTR_INIT(&fields[5]),
+  UPB_TABVALUE_PTR_INIT(&fields[32]),
+  UPB_TABVALUE_PTR_INIT(&fields[10]),
+  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[13]),
+  UPB_TABVALUE_PTR_INIT(&fields[53]),
+  UPB_TABVALUE_PTR_INIT(&fields[64]),
+  UPB_TABVALUE_PTR_INIT(&fields[61]),
+  UPB_TABVALUE_PTR_INIT(&fields[80]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[17]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[26]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[25]),
+  UPB_TABVALUE_PTR_INIT(&fields[48]),
+  UPB_TABVALUE_PTR_INIT(&fields[24]),
+  UPB_TABVALUE_PTR_INIT(&fields[18]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[2]),
+  UPB_TABVALUE_PTR_INIT(&fields[23]),
+  UPB_TABVALUE_PTR_INIT(&fields[62]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[22]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[31]),
+  UPB_TABVALUE_PTR_INIT(&fields[45]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[39]),
+  UPB_TABVALUE_PTR_INIT(&fields[20]),
+  UPB_TABVALUE_PTR_INIT(&fields[56]),
+  UPB_TABVALUE_PTR_INIT(&fields[55]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[35]),
+  UPB_TABVALUE_PTR_INIT(&fields[33]),
+  UPB_TABVALUE_PTR_INIT(&fields[54]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[30]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[59]),
+  UPB_TABVALUE_PTR_INIT(&fields[65]),
+  UPB_TABVALUE_PTR_INIT(&fields[29]),
+  UPB_TABVALUE_PTR_INIT(&fields[68]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[36]),
+  UPB_TABVALUE_PTR_INIT(&fields[19]),
+  UPB_TABVALUE_PTR_INIT(&fields[60]),
+  UPB_TABVALUE_PTR_INIT(&fields[43]),
+  UPB_TABVALUE_PTR_INIT(&fields[7]),
+  UPB_TABVALUE_PTR_INIT(&fields[67]),
+  UPB_TABVALUE_PTR_INIT(&fields[0]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[42]),
+  UPB_TABVALUE_PTR_INIT(&fields[21]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"),
+  UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"),
+  UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"),
+  UPB_TABVALUE_PTR_INIT("TYPE_INT64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_UINT64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_INT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_BOOL"),
+  UPB_TABVALUE_PTR_INIT("TYPE_STRING"),
+  UPB_TABVALUE_PTR_INIT("TYPE_GROUP"),
+  UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"),
+  UPB_TABVALUE_PTR_INIT("TYPE_BYTES"),
+  UPB_TABVALUE_PTR_INIT("TYPE_UINT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_ENUM"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SINT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SINT64"),
+  UPB_TABVALUE_PTR_INIT("STRING"),
+  UPB_TABVALUE_PTR_INIT("CORD"),
+  UPB_TABVALUE_PTR_INIT("STRING_PIECE"),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("SPEED"),
+  UPB_TABVALUE_PTR_INIT("CODE_SIZE"),
+  UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"),
+};
+
+static const upb_symtab symtab = UPB_SYMTAB_INIT(UPB_STRTABLE_INIT(24, 31, UPB_CTYPE_PTR, 5, &strentries[204]), &reftables[210], &reftables[211]);
+
+const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner) {
+  upb_symtab_ref(&symtab, owner);
+  return &symtab;
+}
+
+#ifdef UPB_DEBUG_REFS
+static upb_inttable reftables[212] = {
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+};
+#endif
+
+/*
+** XXX: The routines in this file that consume a string do not currently
+** support having the string span buffers.  In the future, as upb_sink and
+** its buffering/sharing functionality evolve there should be an easy and
+** idiomatic way of correctly handling this case.  For now, we accept this
+** limitation since we currently only parse descriptors from single strings.
+*/
+
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* upb_deflist is an internal-only dynamic array for storing a growing list of
+ * upb_defs. */
+typedef struct {
+  upb_def **defs;
+  size_t len;
+  size_t size;
+  bool owned;
+} upb_deflist;
+
+/* We keep a stack of all the messages scopes we are currently in, as well as
+ * the top-level file scope.  This is necessary to correctly qualify the
+ * definitions that are contained inside.  "name" tracks the name of the
+ * message or package (a bare name -- not qualified by any enclosing scopes). */
+typedef struct {
+  char *name;
+  /* Index of the first def that is under this scope.  For msgdefs, the
+   * msgdef itself is at start-1. */
+  int start;
+} upb_descreader_frame;
+
+/* The maximum number of nested declarations that are allowed, ie.
+ * message Foo {
+ *   message Bar {
+ *     message Baz {
+ *     }
+ *   }
+ * }
+ *
+ * This is a resource limit that affects how big our runtime stack can grow.
+ * TODO: make this a runtime-settable property of the Reader instance. */
+#define UPB_MAX_MESSAGE_NESTING 64
+
+struct upb_descreader {
+  upb_sink sink;
+  upb_deflist defs;
+  upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
+  int stack_len;
+
+  uint32_t number;
+  char *name;
+  bool saw_number;
+  bool saw_name;
+
+  char *default_string;
+
+  upb_fielddef *f;
+};
+
+static char *upb_strndup(const char *buf, size_t n) {
+  char *ret = malloc(n + 1);
+  if (!ret) return NULL;
+  memcpy(ret, buf, n);
+  ret[n] = '\0';
+  return ret;
+}
+
+/* Returns a newly allocated string that joins input strings together, for
+ * example:
+ *   join("Foo.Bar", "Baz") -> "Foo.Bar.Baz"
+ *   join("", "Baz") -> "Baz"
+ * Caller owns a ref on the returned string. */
+static char *upb_join(const char *base, const char *name) {
+  if (!base || strlen(base) == 0) {
+    return upb_strdup(name);
+  } else {
+    char *ret = malloc(strlen(base) + strlen(name) + 2);
+    ret[0] = '\0';
+    strcat(ret, base);
+    strcat(ret, ".");
+    strcat(ret, name);
+    return ret;
+  }
+}
+
+
+/* upb_deflist ****************************************************************/
+
+void upb_deflist_init(upb_deflist *l) {
+  l->size = 0;
+  l->defs = NULL;
+  l->len = 0;
+  l->owned = true;
+}
+
+void upb_deflist_uninit(upb_deflist *l) {
+  size_t i;
+  if (l->owned)
+    for(i = 0; i < l->len; i++)
+      upb_def_unref(l->defs[i], l);
+  free(l->defs);
+}
+
+bool upb_deflist_push(upb_deflist *l, upb_def *d) {
+  if(++l->len >= l->size) {
+    size_t new_size = UPB_MAX(l->size, 4);
+    new_size *= 2;
+    l->defs = realloc(l->defs, new_size * sizeof(void *));
+    if (!l->defs) return false;
+    l->size = new_size;
+  }
+  l->defs[l->len - 1] = d;
+  return true;
+}
+
+void upb_deflist_donaterefs(upb_deflist *l, void *owner) {
+  size_t i;
+  assert(l->owned);
+  for (i = 0; i < l->len; i++)
+    upb_def_donateref(l->defs[i], l, owner);
+  l->owned = false;
+}
+
+static upb_def *upb_deflist_last(upb_deflist *l) {
+  return l->defs[l->len-1];
+}
+
+/* Qualify the defname for all defs starting with offset "start" with "str". */
+static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
+  uint32_t i;
+  for (i = start; i < l->len; i++) {
+    upb_def *def = l->defs[i];
+    char *name = upb_join(str, upb_def_fullname(def));
+    upb_def_setfullname(def, name, NULL);
+    free(name);
+  }
+}
+
+
+/* upb_descreader  ************************************************************/
+
+static upb_msgdef *upb_descreader_top(upb_descreader *r) {
+  int index;
+  assert(r->stack_len > 1);
+  index = r->stack[r->stack_len-1].start - 1;
+  assert(index >= 0);
+  return upb_downcast_msgdef_mutable(r->defs.defs[index]);
+}
+
+static upb_def *upb_descreader_last(upb_descreader *r) {
+  return upb_deflist_last(&r->defs);
+}
+
+/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two
+ * entities that have names and can contain sub-definitions. */
+void upb_descreader_startcontainer(upb_descreader *r) {
+  upb_descreader_frame *f = &r->stack[r->stack_len++];
+  f->start = r->defs.len;
+  f->name = NULL;
+}
+
+void upb_descreader_endcontainer(upb_descreader *r) {
+  upb_descreader_frame *f = &r->stack[--r->stack_len];
+  upb_deflist_qualify(&r->defs, f->name, f->start);
+  free(f->name);
+  f->name = NULL;
+}
+
+void upb_descreader_setscopename(upb_descreader *r, char *str) {
+  upb_descreader_frame *f = &r->stack[r->stack_len-1];
+  free(f->name);
+  f->name = str;
+}
+
+/* Handlers for google.protobuf.FileDescriptorProto. */
+static bool file_startmsg(void *r, const void *hd) {
+  UPB_UNUSED(hd);
+  upb_descreader_startcontainer(r);
+  return true;
+}
+
+static bool file_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(status);
+  upb_descreader_endcontainer(r);
+  return true;
+}
+
+static size_t file_onpackage(void *closure, const void *hd, const char *buf,
+                             size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  upb_descreader_setscopename(r, upb_strndup(buf, n));
+  return n;
+}
+
+/* Handlers for google.protobuf.EnumValueDescriptorProto. */
+static bool enumval_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->saw_number = false;
+  r->saw_name = false;
+  return true;
+}
+
+static size_t enumval_onname(void *closure, const void *hd, const char *buf,
+                             size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  free(r->name);
+  r->name = upb_strndup(buf, n);
+  r->saw_name = true;
+  return n;
+}
+
+static bool enumval_onnumber(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->number = val;
+  r->saw_number = true;
+  return true;
+}
+
+static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_enumdef *e;
+  UPB_UNUSED(hd);
+
+  if(!r->saw_number || !r->saw_name) {
+    upb_status_seterrmsg(status, "Enum value missing name or number.");
+    return false;
+  }
+  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
+  upb_enumdef_addval(e, r->name, r->number, status);
+  free(r->name);
+  r->name = NULL;
+  return true;
+}
+
+
+/* Handlers for google.protobuf.EnumDescriptorProto. */
+static bool enum_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  upb_deflist_push(&r->defs,
+                   upb_enumdef_upcast_mutable(upb_enumdef_new(&r->defs)));
+  return true;
+}
+
+static bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_enumdef *e;
+  UPB_UNUSED(hd);
+
+  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
+  if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
+    upb_status_seterrmsg(status, "Enum had no name.");
+    return false;
+  }
+  if (upb_enumdef_numvals(e) == 0) {
+    upb_status_seterrmsg(status, "Enum had no values.");
+    return false;
+  }
+  return true;
+}
+
+static size_t enum_onname(void *closure, const void *hd, const char *buf,
+                          size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *fullname = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  upb_def_setfullname(upb_descreader_last(r), fullname, NULL);
+  free(fullname);
+  return n;
+}
+
+/* Handlers for google.protobuf.FieldDescriptorProto */
+static bool field_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->f = upb_fielddef_new(&r->defs);
+  free(r->default_string);
+  r->default_string = NULL;
+
+  /* fielddefs default to packed, but descriptors default to non-packed. */
+  upb_fielddef_setpacked(r->f, false);
+  return true;
+}
+
+/* Converts the default value in string "str" into "d".  Passes a ref on str.
+ * Returns true on success. */
+static bool parse_default(char *str, upb_fielddef *f) {
+  bool success = true;
+  char *end;
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32: {
+      long val = strtol(str, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultint32(f, val);
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      /* XXX: Need to write our own strtoll, since it's not available in c89. */
+      long long val = strtol(str, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultint64(f, val);
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultuint32(f, val);
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      /* XXX: Need to write our own strtoull, since it's not available in c89. */
+      unsigned long long val = strtoul(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultuint64(f, val);
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultdouble(f, val);
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      /* XXX: Need to write our own strtof, since it's not available in c89. */
+      float val = strtod(str, &end);
+      if (errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultfloat(f, val);
+      break;
+    }
+    case UPB_TYPE_BOOL: {
+      if (strcmp(str, "false") == 0)
+        upb_fielddef_setdefaultbool(f, false);
+      else if (strcmp(str, "true") == 0)
+        upb_fielddef_setdefaultbool(f, true);
+      else
+        success = false;
+      break;
+    }
+    default: abort();
+  }
+  return success;
+}
+
+static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_fielddef *f = r->f;
+  UPB_UNUSED(hd);
+
+  /* TODO: verify that all required fields were present. */
+  assert(upb_fielddef_number(f) != 0);
+  assert(upb_fielddef_name(f) != NULL);
+  assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
+
+  if (r->default_string) {
+    if (upb_fielddef_issubmsg(f)) {
+      upb_status_seterrmsg(status, "Submessages cannot have defaults.");
+      return false;
+    }
+    if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+      upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
+    } else {
+      if (r->default_string && !parse_default(r->default_string, f)) {
+        /* We don't worry too much about giving a great error message since the
+         * compiler should have ensured this was correct. */
+        upb_status_seterrmsg(status, "Error converting default value.");
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+static bool field_onlazy(void *closure, const void *hd, bool val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setlazy(r->f, val);
+  return true;
+}
+
+static bool field_onpacked(void *closure, const void *hd, bool val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setpacked(r->f, val);
+  return true;
+}
+
+static bool field_ontype(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setdescriptortype(r->f, val);
+  return true;
+}
+
+static bool field_onlabel(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setlabel(r->f, val);
+  return true;
+}
+
+static bool field_onnumber(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  bool ok = upb_fielddef_setnumber(r->f, val, NULL);
+  UPB_UNUSED(hd);
+
+  UPB_ASSERT_VAR(ok, ok);
+  return true;
+}
+
+static size_t field_onname(void *closure, const void *hd, const char *buf,
+                           size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setname(r->f, name, NULL);
+  free(name);
+  return n;
+}
+
+static size_t field_ontypename(void *closure, const void *hd, const char *buf,
+                               size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setsubdefname(r->f, name, NULL);
+  free(name);
+  return n;
+}
+
+static size_t field_onextendee(void *closure, const void *hd, const char *buf,
+                               size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setcontainingtypename(r->f, name, NULL);
+  free(name);
+  return n;
+}
+
+static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
+                                 size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* Have to convert from string to the correct type, but we might not know the
+   * type yet, so we save it as a string until the end of the field.
+   * XXX: see comment at the top of the file. */
+  free(r->default_string);
+  r->default_string = upb_strndup(buf, n);
+  return n;
+}
+
+/* Handlers for google.protobuf.DescriptorProto (representing a message). */
+static bool msg_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_deflist_push(&r->defs,
+                   upb_msgdef_upcast_mutable(upb_msgdef_new(&r->defs)));
+  upb_descreader_startcontainer(r);
+  return true;
+}
+
+static bool msg_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  UPB_UNUSED(hd);
+
+  if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) {
+    upb_status_seterrmsg(status, "Encountered message with no name.");
+    return false;
+  }
+  upb_descreader_endcontainer(r);
+  return true;
+}
+
+static size_t msg_onname(void *closure, const void *hd, const char *buf,
+                         size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  /* XXX: see comment at the top of the file. */
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL);
+  upb_descreader_setscopename(r, name);  /* Passes ownership of name. */
+  return n;
+}
+
+static bool msg_onendfield(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  UPB_UNUSED(hd);
+
+  upb_msgdef_addfield(m, r->f, &r->defs, NULL);
+  r->f = NULL;
+  return true;
+}
+
+static bool pushextension(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  assert(upb_fielddef_containingtypename(r->f));
+  upb_fielddef_setisextension(r->f, true);
+  upb_deflist_push(&r->defs, upb_fielddef_upcast_mutable(r->f));
+  r->f = NULL;
+  return true;
+}
+
+#define D(name) upbdefs_google_protobuf_ ## name(s)
+
+static void reghandlers(const void *closure, upb_handlers *h) {
+  const upb_symtab *s = closure;
+  const upb_msgdef *m = upb_handlers_msgdef(h);
+
+  if (m == D(DescriptorProto)) {
+    upb_handlers_setstartmsg(h, &msg_startmsg, NULL);
+    upb_handlers_setendmsg(h, &msg_endmsg, NULL);
+    upb_handlers_setstring(h, D(DescriptorProto_name), &msg_onname, NULL);
+    upb_handlers_setendsubmsg(h, D(DescriptorProto_field), &msg_onendfield,
+                              NULL);
+    upb_handlers_setendsubmsg(h, D(DescriptorProto_extension), &pushextension,
+                              NULL);
+  } else if (m == D(FileDescriptorProto)) {
+    upb_handlers_setstartmsg(h, &file_startmsg, NULL);
+    upb_handlers_setendmsg(h, &file_endmsg, NULL);
+    upb_handlers_setstring(h, D(FileDescriptorProto_package), &file_onpackage,
+                           NULL);
+    upb_handlers_setendsubmsg(h, D(FileDescriptorProto_extension), &pushextension,
+                              NULL);
+  } else if (m == D(EnumValueDescriptorProto)) {
+    upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
+    upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
+    upb_handlers_setstring(h, D(EnumValueDescriptorProto_name), &enumval_onname, NULL);
+    upb_handlers_setint32(h, D(EnumValueDescriptorProto_number), &enumval_onnumber,
+                          NULL);
+  } else if (m == D(EnumDescriptorProto)) {
+    upb_handlers_setstartmsg(h, &enum_startmsg, NULL);
+    upb_handlers_setendmsg(h, &enum_endmsg, NULL);
+    upb_handlers_setstring(h, D(EnumDescriptorProto_name), &enum_onname, NULL);
+  } else if (m == D(FieldDescriptorProto)) {
+    upb_handlers_setstartmsg(h, &field_startmsg, NULL);
+    upb_handlers_setendmsg(h, &field_endmsg, NULL);
+    upb_handlers_setint32(h, D(FieldDescriptorProto_type), &field_ontype,
+                          NULL);
+    upb_handlers_setint32(h, D(FieldDescriptorProto_label), &field_onlabel,
+                          NULL);
+    upb_handlers_setint32(h, D(FieldDescriptorProto_number), &field_onnumber,
+                          NULL);
+    upb_handlers_setstring(h, D(FieldDescriptorProto_name), &field_onname,
+                           NULL);
+    upb_handlers_setstring(h, D(FieldDescriptorProto_type_name),
+                           &field_ontypename, NULL);
+    upb_handlers_setstring(h, D(FieldDescriptorProto_extendee),
+                           &field_onextendee, NULL);
+    upb_handlers_setstring(h, D(FieldDescriptorProto_default_value),
+                           &field_ondefaultval, NULL);
+  } else if (m == D(FieldOptions)) {
+    upb_handlers_setbool(h, D(FieldOptions_lazy), &field_onlazy, NULL);
+    upb_handlers_setbool(h, D(FieldOptions_packed), &field_onpacked, NULL);
+  }
+}
+
+#undef D
+
+void descreader_cleanup(void *_r) {
+  upb_descreader *r = _r;
+  free(r->name);
+  upb_deflist_uninit(&r->defs);
+  free(r->default_string);
+  while (r->stack_len > 0) {
+    upb_descreader_frame *f = &r->stack[--r->stack_len];
+    free(f->name);
+  }
+}
+
+
+/* Public API  ****************************************************************/
+
+upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
+  upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader));
+  if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) {
+    return NULL;
+  }
+
+  upb_deflist_init(&r->defs);
+  upb_sink_reset(upb_descreader_input(r), h, r);
+  r->stack_len = 0;
+  r->name = NULL;
+  r->default_string = NULL;
+
+  return r;
+}
+
+upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n) {
+  *n = r->defs.len;
+  upb_deflist_donaterefs(&r->defs, owner);
+  return r->defs.defs;
+}
+
+upb_sink *upb_descreader_input(upb_descreader *r) {
+  return &r->sink;
+}
+
+const upb_handlers *upb_descreader_newhandlers(const void *owner) {
+  const upb_symtab *s = upbdefs_google_protobuf_descriptor(&s);
+  const upb_handlers *h = upb_handlers_newfrozen(
+      upbdefs_google_protobuf_FileDescriptorSet(s), owner, reghandlers, s);
+  upb_symtab_unref(s, &s);
+  return h;
+}
+/*
+** protobuf decoder bytecode compiler
+**
+** Code to compile a upb::Handlers into bytecode for decoding a protobuf
+** according to that specific schema and destination handlers.
+**
+** Compiling to bytecode is always the first step.  If we are using the
+** interpreted decoder we leave it as bytecode and interpret that.  If we are
+** using a JIT decoder we use a code generator to turn the bytecode into native
+** code, LLVM IR, etc.
+**
+** Bytecode definition is in decoder.int.h.
+*/
+
+#include <stdarg.h>
+
+#ifdef UPB_DUMP_BYTECODE
+#include <stdio.h>
+#endif
+
+#define MAXLABEL 5
+#define EMPTYLABEL -1
+
+/* mgroup *********************************************************************/
+
+static void freegroup(upb_refcounted *r) {
+  mgroup *g = (mgroup*)r;
+  upb_inttable_uninit(&g->methods);
+#ifdef UPB_USE_JIT_X64
+  upb_pbdecoder_freejit(g);
+#endif
+  free(g->bytecode);
+  free(g);
+}
+
+static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const mgroup *g = (const mgroup*)r;
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &g->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
+    visit(r, upb_pbdecodermethod_upcast(method), closure);
+  }
+}
+
+mgroup *newgroup(const void *owner) {
+  mgroup *g = malloc(sizeof(*g));
+  static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup};
+  upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner);
+  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
+  g->bytecode = NULL;
+  g->bytecode_end = NULL;
+  return g;
+}
+
+
+/* upb_pbdecodermethod ********************************************************/
+
+static void freemethod(upb_refcounted *r) {
+  upb_pbdecodermethod *method = (upb_pbdecodermethod*)r;
+
+  if (method->dest_handlers_) {
+    upb_handlers_unref(method->dest_handlers_, method);
+  }
+
+  upb_inttable_uninit(&method->dispatch);
+  free(method);
+}
+
+static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
+                        void *closure) {
+  const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r;
+  visit(r, m->group, closure);
+}
+
+static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
+                                      mgroup *group) {
+  static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod};
+  upb_pbdecodermethod *ret = malloc(sizeof(*ret));
+  upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret);
+  upb_byteshandler_init(&ret->input_handler_);
+
+  /* The method references the group and vice-versa, in a circular reference. */
+  upb_ref2(ret, group);
+  upb_ref2(group, ret);
+  upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret));
+  upb_pbdecodermethod_unref(ret, &ret);
+
+  ret->group = mgroup_upcast_mutable(group);
+  ret->dest_handlers_ = dest_handlers;
+  ret->is_native_ = false;  /* If we JIT, it will update this later. */
+  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
+
+  if (ret->dest_handlers_) {
+    upb_handlers_ref(ret->dest_handlers_, ret);
+  }
+  return ret;
+}
+
+const upb_handlers *upb_pbdecodermethod_desthandlers(
+    const upb_pbdecodermethod *m) {
+  return m->dest_handlers_;
+}
+
+const upb_byteshandler *upb_pbdecodermethod_inputhandler(
+    const upb_pbdecodermethod *m) {
+  return &m->input_handler_;
+}
+
+bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
+  return m->is_native_;
+}
+
+const upb_pbdecodermethod *upb_pbdecodermethod_new(
+    const upb_pbdecodermethodopts *opts, const void *owner) {
+  const upb_pbdecodermethod *ret;
+  upb_pbcodecache cache;
+
+  upb_pbcodecache_init(&cache);
+  ret = upb_pbcodecache_getdecodermethod(&cache, opts);
+  upb_pbdecodermethod_ref(ret, owner);
+  upb_pbcodecache_uninit(&cache);
+  return ret;
+}
+
+
+/* bytecode compiler **********************************************************/
+
+/* Data used only at compilation time. */
+typedef struct {
+  mgroup *group;
+
+  uint32_t *pc;
+  int fwd_labels[MAXLABEL];
+  int back_labels[MAXLABEL];
+
+  /* For fields marked "lazy", parse them lazily or eagerly? */
+  bool lazy;
+} compiler;
+
+static compiler *newcompiler(mgroup *group, bool lazy) {
+  compiler *ret = malloc(sizeof(*ret));
+  int i;
+
+  ret->group = group;
+  ret->lazy = lazy;
+  for (i = 0; i < MAXLABEL; i++) {
+    ret->fwd_labels[i] = EMPTYLABEL;
+    ret->back_labels[i] = EMPTYLABEL;
+  }
+  return ret;
+}
+
+static void freecompiler(compiler *c) {
+  free(c);
+}
+
+const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
+
+/* How many words an instruction is. */
+static int instruction_len(uint32_t instr) {
+  switch (getop(instr)) {
+    case OP_SETDISPATCH: return 1 + ptr_words;
+    case OP_TAGN: return 3;
+    case OP_SETBIGGROUPNUM: return 2;
+    default: return 1;
+  }
+}
+
+bool op_has_longofs(int32_t instruction) {
+  switch (getop(instruction)) {
+    case OP_CALL:
+    case OP_BRANCH:
+    case OP_CHECKDELIM:
+      return true;
+    /* The "tag" instructions only have 8 bytes available for the jump target,
+     * but that is ok because these opcodes only require short jumps. */
+    case OP_TAG1:
+    case OP_TAG2:
+    case OP_TAGN:
+      return false;
+    default:
+      assert(false);
+      return false;
+  }
+}
+
+static int32_t getofs(uint32_t instruction) {
+  if (op_has_longofs(instruction)) {
+    return (int32_t)instruction >> 8;
+  } else {
+    return (int8_t)(instruction >> 8);
+  }
+}
+
+static void setofs(uint32_t *instruction, int32_t ofs) {
+  if (op_has_longofs(*instruction)) {
+    *instruction = getop(*instruction) | ofs << 8;
+  } else {
+    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
+  }
+  assert(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
+}
+
+static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
+
+/* Defines a local label at the current PC location.  All previous forward
+ * references are updated to point to this location.  The location is noted
+ * for any future backward references. */
+static void label(compiler *c, unsigned int label) {
+  int val;
+  uint32_t *codep;
+
+  assert(label < MAXLABEL);
+  val = c->fwd_labels[label];
+  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
+  while (codep) {
+    int ofs = getofs(*codep);
+    setofs(codep, c->pc - codep - instruction_len(*codep));
+    codep = ofs ? codep + ofs : NULL;
+  }
+  c->fwd_labels[label] = EMPTYLABEL;
+  c->back_labels[label] = pcofs(c);
+}
+
+/* Creates a reference to a numbered label; either a forward reference
+ * (positive arg) or backward reference (negative arg).  For forward references
+ * the value returned now is actually a "next" pointer into a linked list of all
+ * instructions that use this label and will be patched later when the label is
+ * defined with label().
+ *
+ * The returned value is the offset that should be written into the instruction.
+ */
+static int32_t labelref(compiler *c, int label) {
+  assert(label < MAXLABEL);
+  if (label == LABEL_DISPATCH) {
+    /* No resolving required. */
+    return 0;
+  } else if (label < 0) {
+    /* Backward local label.  Relative to the next instruction. */
+    uint32_t from = (c->pc + 1) - c->group->bytecode;
+    return c->back_labels[-label] - from;
+  } else {
+    /* Forward local label: prepend to (possibly-empty) linked list. */
+    int *lptr = &c->fwd_labels[label];
+    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
+    *lptr = pcofs(c);
+    return ret;
+  }
+}
+
+static void put32(compiler *c, uint32_t v) {
+  mgroup *g = c->group;
+  if (c->pc == g->bytecode_end) {
+    int ofs = pcofs(c);
+    size_t oldsize = g->bytecode_end - g->bytecode;
+    size_t newsize = UPB_MAX(oldsize * 2, 64);
+    /* TODO(haberman): handle OOM. */
+    g->bytecode = realloc(g->bytecode, newsize * sizeof(uint32_t));
+    g->bytecode_end = g->bytecode + newsize;
+    c->pc = g->bytecode + ofs;
+  }
+  *c->pc++ = v;
+}
+
+static void putop(compiler *c, opcode op, ...) {
+  va_list ap;
+  va_start(ap, op);
+
+  switch (op) {
+    case OP_SETDISPATCH: {
+      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
+      put32(c, OP_SETDISPATCH);
+      put32(c, ptr);
+      if (sizeof(uintptr_t) > sizeof(uint32_t))
+        put32(c, (uint64_t)ptr >> 32);
+      break;
+    }
+    case OP_STARTMSG:
+    case OP_ENDMSG:
+    case OP_PUSHLENDELIM:
+    case OP_POP:
+    case OP_SETDELIM:
+    case OP_HALT:
+    case OP_RET:
+    case OP_DISPATCH:
+      put32(c, op);
+      break;
+    case OP_PARSE_DOUBLE:
+    case OP_PARSE_FLOAT:
+    case OP_PARSE_INT64:
+    case OP_PARSE_UINT64:
+    case OP_PARSE_INT32:
+    case OP_PARSE_FIXED64:
+    case OP_PARSE_FIXED32:
+    case OP_PARSE_BOOL:
+    case OP_PARSE_UINT32:
+    case OP_PARSE_SFIXED32:
+    case OP_PARSE_SFIXED64:
+    case OP_PARSE_SINT32:
+    case OP_PARSE_SINT64:
+    case OP_STARTSEQ:
+    case OP_ENDSEQ:
+    case OP_STARTSUBMSG:
+    case OP_ENDSUBMSG:
+    case OP_STARTSTR:
+    case OP_STRING:
+    case OP_ENDSTR:
+    case OP_PUSHTAGDELIM:
+      put32(c, op | va_arg(ap, upb_selector_t) << 8);
+      break;
+    case OP_SETBIGGROUPNUM:
+      put32(c, op);
+      put32(c, va_arg(ap, int));
+      break;
+    case OP_CALL: {
+      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
+      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
+      break;
+    }
+    case OP_CHECKDELIM:
+    case OP_BRANCH: {
+      uint32_t instruction = op;
+      int label = va_arg(ap, int);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      break;
+    }
+    case OP_TAG1:
+    case OP_TAG2: {
+      int label = va_arg(ap, int);
+      uint64_t tag = va_arg(ap, uint64_t);
+      uint32_t instruction = op | (tag << 16);
+      assert(tag <= 0xffff);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      break;
+    }
+    case OP_TAGN: {
+      int label = va_arg(ap, int);
+      uint64_t tag = va_arg(ap, uint64_t);
+      uint32_t instruction = op | (upb_value_size(tag) << 16);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      put32(c, tag);
+      put32(c, tag >> 32);
+      break;
+    }
+  }
+
+  va_end(ap);
+}
+
+#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE)
+
+const char *upb_pbdecoder_getopname(unsigned int op) {
+#define QUOTE(x) #x
+#define EXPAND_AND_QUOTE(x) QUOTE(x)
+#define OPNAME(x) OP_##x
+#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
+#define T(x) OP(PARSE_##x)
+  /* Keep in sync with list in decoder.int.h. */
+  switch ((opcode)op) {
+    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
+    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
+    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
+    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
+    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
+    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
+    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
+  }
+  return "<unknown op>";
+#undef OP
+#undef T
+}
+
+#endif
+
+#ifdef UPB_DUMP_BYTECODE
+
+static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
+
+  uint32_t *begin = p;
+
+  while (p < end) {
+    fprintf(f, "%p  %8tx", p, p - begin);
+    uint32_t instr = *p++;
+    uint8_t op = getop(instr);
+    fprintf(f, " %s", upb_pbdecoder_getopname(op));
+    switch ((opcode)op) {
+      case OP_SETDISPATCH: {
+        const upb_inttable *dispatch;
+        memcpy(&dispatch, p, sizeof(void*));
+        p += ptr_words;
+        const upb_pbdecodermethod *method =
+            (void *)((char *)dispatch -
+                     offsetof(upb_pbdecodermethod, dispatch));
+        fprintf(f, " %s", upb_msgdef_fullname(
+                              upb_handlers_msgdef(method->dest_handlers_)));
+        break;
+      }
+      case OP_DISPATCH:
+      case OP_STARTMSG:
+      case OP_ENDMSG:
+      case OP_PUSHLENDELIM:
+      case OP_POP:
+      case OP_SETDELIM:
+      case OP_HALT:
+      case OP_RET:
+        break;
+      case OP_PARSE_DOUBLE:
+      case OP_PARSE_FLOAT:
+      case OP_PARSE_INT64:
+      case OP_PARSE_UINT64:
+      case OP_PARSE_INT32:
+      case OP_PARSE_FIXED64:
+      case OP_PARSE_FIXED32:
+      case OP_PARSE_BOOL:
+      case OP_PARSE_UINT32:
+      case OP_PARSE_SFIXED32:
+      case OP_PARSE_SFIXED64:
+      case OP_PARSE_SINT32:
+      case OP_PARSE_SINT64:
+      case OP_STARTSEQ:
+      case OP_ENDSEQ:
+      case OP_STARTSUBMSG:
+      case OP_ENDSUBMSG:
+      case OP_STARTSTR:
+      case OP_STRING:
+      case OP_ENDSTR:
+      case OP_PUSHTAGDELIM:
+        fprintf(f, " %d", instr >> 8);
+        break;
+      case OP_SETBIGGROUPNUM:
+        fprintf(f, " %d", *p++);
+        break;
+      case OP_CHECKDELIM:
+      case OP_CALL:
+      case OP_BRANCH:
+        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        break;
+      case OP_TAG1:
+      case OP_TAG2: {
+        fprintf(f, " tag:0x%x", instr >> 16);
+        if (getofs(instr)) {
+          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        }
+        break;
+      }
+      case OP_TAGN: {
+        uint64_t tag = *p++;
+        tag |= (uint64_t)*p++ << 32;
+        fprintf(f, " tag:0x%llx", (long long)tag);
+        fprintf(f, " n:%d", instr >> 16);
+        if (getofs(instr)) {
+          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        }
+        break;
+      }
+    }
+    fputs("\n", f);
+  }
+}
+
+#endif
+
+static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
+  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
+  uint64_t encoded_tag = upb_vencode32(tag);
+  /* No tag should be greater than 5 bytes. */
+  assert(encoded_tag <= 0xffffffffff);
+  return encoded_tag;
+}
+
+static void putchecktag(compiler *c, const upb_fielddef *f,
+                        int wire_type, int dest) {
+  uint64_t tag = get_encoded_tag(f, wire_type);
+  switch (upb_value_size(tag)) {
+    case 1:
+      putop(c, OP_TAG1, dest, tag);
+      break;
+    case 2:
+      putop(c, OP_TAG2, dest, tag);
+      break;
+    default:
+      putop(c, OP_TAGN, dest, tag);
+      break;
+  }
+}
+
+static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
+  upb_selector_t selector;
+  bool ok = upb_handlers_getselector(f, type, &selector);
+  UPB_ASSERT_VAR(ok, ok);
+  return selector;
+}
+
+/* Takes an existing, primary dispatch table entry and repacks it with a
+ * different alternate wire type.  Called when we are inserting a secondary
+ * dispatch table entry for an alternate wire type. */
+static uint64_t repack(uint64_t dispatch, int new_wt2) {
+  uint64_t ofs;
+  uint8_t wt1;
+  uint8_t old_wt2;
+  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
+  assert(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
+  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
+}
+
+/* Marks the current bytecode position as the dispatch target for this message,
+ * field, and wire type. */
+static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
+                           const upb_fielddef *f, int wire_type) {
+  /* Offset is relative to msg base. */
+  uint64_t ofs = pcofs(c) - method->code_base.ofs;
+  uint32_t fn = upb_fielddef_number(f);
+  upb_inttable *d = &method->dispatch;
+  upb_value v;
+  if (upb_inttable_remove(d, fn, &v)) {
+    /* TODO: prioritize based on packed setting in .proto file. */
+    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
+    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
+    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
+  } else {
+    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
+    upb_inttable_insert(d, fn, upb_value_uint64(val));
+  }
+}
+
+static void putpush(compiler *c, const upb_fielddef *f) {
+  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
+    putop(c, OP_PUSHLENDELIM);
+  } else {
+    uint32_t fn = upb_fielddef_number(f);
+    if (fn >= 1 << 24) {
+      putop(c, OP_PUSHTAGDELIM, 0);
+      putop(c, OP_SETBIGGROUPNUM, fn);
+    } else {
+      putop(c, OP_PUSHTAGDELIM, fn);
+    }
+  }
+}
+
+static upb_pbdecodermethod *find_submethod(const compiler *c,
+                                           const upb_pbdecodermethod *method,
+                                           const upb_fielddef *f) {
+  const upb_handlers *sub =
+      upb_handlers_getsubhandlers(method->dest_handlers_, f);
+  upb_value v;
+  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
+             ? upb_value_getptr(v)
+             : NULL;
+}
+
+static void putsel(compiler *c, opcode op, upb_selector_t sel,
+                   const upb_handlers *h) {
+  if (upb_handlers_gethandler(h, sel)) {
+    putop(c, op, sel);
+  }
+}
+
+/* Puts an opcode to call a callback, but only if a callback actually exists for
+ * this field and handler type. */
+static void maybeput(compiler *c, opcode op, const upb_handlers *h,
+                     const upb_fielddef *f, upb_handlertype_t type) {
+  putsel(c, op, getsel(f, type), h);
+}
+
+static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
+  if (!upb_fielddef_lazy(f))
+    return false;
+
+  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) ||
+         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) ||
+         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+
+/* bytecode compiler code generation ******************************************/
+
+/* Symbolic names for our local labels. */
+#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
+#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
+#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
+#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
+
+/* Generates bytecode to parse a single non-lazy message field. */
+static void generate_msgfield(compiler *c, const upb_fielddef *f,
+                              upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
+  int wire_type;
+
+  if (!sub_m) {
+    /* Don't emit any code for this field at all; it will be parsed as an
+     * unknown field. */
+    return;
+  }
+
+  label(c, LABEL_FIELD);
+
+  wire_type =
+      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
+          ? UPB_WIRE_TYPE_DELIMITED
+          : UPB_WIRE_TYPE_START_GROUP;
+
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
+   label(c, LABEL_LOOPSTART);
+    putpush(c, f);
+    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
+    putop(c, OP_CALL, sub_m);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
+    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
+      putop(c, OP_SETDELIM);
+    }
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putpush(c, f);
+    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
+    putop(c, OP_CALL, sub_m);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
+    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
+      putop(c, OP_SETDELIM);
+    }
+  }
+}
+
+/* Generates bytecode to parse a single string or lazy submessage field. */
+static void generate_delimfield(compiler *c, const upb_fielddef *f,
+                                upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+
+  label(c, LABEL_FIELD);
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
+   label(c, LABEL_LOOPSTART);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
+    /* Need to emit even if no handler to skip past the string. */
+    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
+    putop(c, OP_SETDELIM);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
+    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
+    putop(c, OP_SETDELIM);
+  }
+}
+
+/* Generates bytecode to parse a single primitive field. */
+static void generate_primitivefield(compiler *c, const upb_fielddef *f,
+                                    upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
+  opcode parse_type;
+  upb_selector_t sel;
+  int wire_type;
+
+  label(c, LABEL_FIELD);
+
+  /* From a decoding perspective, ENUM is the same as INT32. */
+  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
+    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
+
+  parse_type = (opcode)descriptor_type;
+
+  /* TODO(haberman): generate packed or non-packed first depending on "packed"
+   * setting in the fielddef.  This will favor (in speed) whichever was
+   * specified. */
+
+  assert((int)parse_type >= 0 && parse_type <= OP_MAX);
+  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
+   label(c, LABEL_LOOPSTART);
+    putop(c, parse_type, sel);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
+   label(c, LABEL_LOOPSTART);
+    putop(c, parse_type, sel);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);  /* Packed and non-packed join. */
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, parse_type, sel);
+  }
+}
+
+/* Adds bytecode for parsing the given message to the given decoderplan,
+ * while adding all dispatch targets to this message's dispatch table. */
+static void compile_method(compiler *c, upb_pbdecodermethod *method) {
+  const upb_handlers *h;
+  const upb_msgdef *md;
+  uint32_t* start_pc;
+  upb_msg_field_iter i;
+  upb_value val;
+
+  assert(method);
+
+  /* Clear all entries in the dispatch table. */
+  upb_inttable_uninit(&method->dispatch);
+  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
+
+  h = upb_pbdecodermethod_desthandlers(method);
+  md = upb_handlers_msgdef(h);
+
+ method->code_base.ofs = pcofs(c);
+  putop(c, OP_SETDISPATCH, &method->dispatch);
+  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
+ label(c, LABEL_FIELD);
+  start_pc = c->pc;
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    upb_fieldtype_t type = upb_fielddef_type(f);
+
+    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
+      generate_msgfield(c, f, method);
+    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
+               type == UPB_TYPE_MESSAGE) {
+      generate_delimfield(c, f, method);
+    } else {
+      generate_primitivefield(c, f, method);
+    }
+  }
+
+  /* If there were no fields, or if no handlers were defined, we need to
+   * generate a non-empty loop body so that we can at least dispatch for unknown
+   * fields and check for the end of the message. */
+  if (c->pc == start_pc) {
+    /* Check for end-of-message. */
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    /* Unconditionally dispatch. */
+    putop(c, OP_DISPATCH, 0);
+  }
+
+  /* For now we just loop back to the last field of the message (or if none,
+   * the DISPATCH opcode for the message). */
+  putop(c, OP_BRANCH, -LABEL_FIELD);
+
+  /* Insert both a label and a dispatch table entry for this end-of-msg. */
+ label(c, LABEL_ENDMSG);
+  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
+  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
+
+  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
+  putop(c, OP_RET);
+
+  upb_inttable_compact(&method->dispatch);
+}
+
+/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
+ * Returns the method for these handlers.
+ *
+ * Generates a new method for every destination handlers reachable from "h". */
+static void find_methods(compiler *c, const upb_handlers *h) {
+  upb_value v;
+  upb_msg_field_iter i;
+  const upb_msgdef *md;
+
+  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
+    return;
+  newmethod(h, c->group);
+
+  /* Find submethods. */
+  md = upb_handlers_msgdef(h);
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_handlers *sub_h;
+    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
+      /* We only generate a decoder method for submessages with handlers.
+       * Others will be parsed as unknown fields. */
+      find_methods(c, sub_h);
+    }
+  }
+}
+
+/* (Re-)compile bytecode for all messages in "msgs."
+ * Overwrites any existing bytecode in "c". */
+static void compile_methods(compiler *c) {
+  upb_inttable_iter i;
+
+  /* Start over at the beginning of the bytecode. */
+  c->pc = c->group->bytecode;
+
+  upb_inttable_begin(&i, &c->group->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
+    compile_method(c, method);
+  }
+}
+
+static void set_bytecode_handlers(mgroup *g) {
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &g->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
+    upb_byteshandler *h = &m->input_handler_;
+
+    m->code_base.ptr = g->bytecode + m->code_base.ofs;
+
+    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
+    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
+    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
+  }
+}
+
+
+/* JIT setup. *****************************************************************/
+
+#ifdef UPB_USE_JIT_X64
+
+static void sethandlers(mgroup *g, bool allowjit) {
+  g->jit_code = NULL;
+  if (allowjit) {
+    /* Compile byte-code into machine code, create handlers. */
+    upb_pbdecoder_jit(g);
+  } else {
+    set_bytecode_handlers(g);
+  }
+}
+
+#else  /* UPB_USE_JIT_X64 */
+
+static void sethandlers(mgroup *g, bool allowjit) {
+  /* No JIT compiled in; use bytecode handlers unconditionally. */
+  UPB_UNUSED(allowjit);
+  set_bytecode_handlers(g);
+}
+
+#endif  /* UPB_USE_JIT_X64 */
+
+
+/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
+ * handlers and other mgroups (but verify we have a transitive closure). */
+const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
+                         const void *owner) {
+  mgroup *g;
+  compiler *c;
+
+  UPB_UNUSED(allowjit);
+  assert(upb_handlers_isfrozen(dest));
+
+  g = newgroup(owner);
+  c = newcompiler(g, lazy);
+  find_methods(c, dest);
+
+  /* We compile in two passes:
+   * 1. all messages are assigned relative offsets from the beginning of the
+   *    bytecode (saved in method->code_base).
+   * 2. forwards OP_CALL instructions can be correctly linked since message
+   *    offsets have been previously assigned.
+   *
+   * Could avoid the second pass by linking OP_CALL instructions somehow. */
+  compile_methods(c);
+  compile_methods(c);
+  g->bytecode_end = c->pc;
+  freecompiler(c);
+
+#ifdef UPB_DUMP_BYTECODE
+  {
+    FILE *f = fopen("/tmp/upb-bytecode", "wb");
+    assert(f);
+    dumpbc(g->bytecode, g->bytecode_end, stderr);
+    dumpbc(g->bytecode, g->bytecode_end, f);
+    fclose(f);
+  }
+#endif
+
+  sethandlers(g, allowjit);
+  return g;
+}
+
+
+/* upb_pbcodecache ************************************************************/
+
+void upb_pbcodecache_init(upb_pbcodecache *c) {
+  upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR);
+  c->allow_jit_ = true;
+}
+
+void upb_pbcodecache_uninit(upb_pbcodecache *c) {
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &c->groups);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i));
+    mgroup_unref(group, c);
+  }
+  upb_inttable_uninit(&c->groups);
+}
+
+bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) {
+  return c->allow_jit_;
+}
+
+bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) {
+  if (upb_inttable_count(&c->groups) > 0)
+    return false;
+  c->allow_jit_ = allow;
+  return true;
+}
+
+const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
+    upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) {
+  upb_value v;
+  bool ok;
+
+  /* Right now we build a new DecoderMethod every time.
+   * TODO(haberman): properly cache methods by their true key. */
+  const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c);
+  upb_inttable_push(&c->groups, upb_value_constptr(g));
+
+  ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v);
+  UPB_ASSERT_VAR(ok, ok);
+  return upb_value_getptr(v);
+}
+
+
+/* upb_pbdecodermethodopts ****************************************************/
+
+void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
+                                  const upb_handlers *h) {
+  opts->handlers = h;
+  opts->lazy = false;
+}
+
+void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) {
+  opts->lazy = lazy;
+}
+/*
+** upb::Decoder (Bytecode Decoder VM)
+**
+** Bytecode must previously have been generated using the bytecode compiler in
+** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
+** parse the input.
+**
+** Decoding is fully resumable; we just keep a pointer to the current bytecode
+** instruction and resume from there.  A fair amount of the logic here is to
+** handle the fact that values can span buffer seams and we have to be able to
+** be capable of suspending/resuming from any byte in the stream.  This
+** sometimes requires keeping a few trailing bytes from the last buffer around
+** in the "residual" buffer.
+*/
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#ifdef UPB_DUMP_BYTECODE
+#include <stdio.h>
+#endif
+
+#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
+
+/* Error messages that are shared between the bytecode and JIT decoders. */
+const char *kPbDecoderStackOverflow = "Nesting too deep.";
+const char *kPbDecoderSubmessageTooLong =
+    "Submessage end extends past enclosing submessage.";
+
+/* Error messages shared within this file. */
+static const char *kUnterminatedVarint = "Unterminated varint.";
+
+/* upb_pbdecoder **************************************************************/
+
+static opcode halt = OP_HALT;
+
+/* Whether an op consumes any of the input buffer. */
+static bool consumes_input(opcode op) {
+  switch (op) {
+    case OP_SETDISPATCH:
+    case OP_STARTMSG:
+    case OP_ENDMSG:
+    case OP_STARTSEQ:
+    case OP_ENDSEQ:
+    case OP_STARTSUBMSG:
+    case OP_ENDSUBMSG:
+    case OP_STARTSTR:
+    case OP_ENDSTR:
+    case OP_PUSHTAGDELIM:
+    case OP_POP:
+    case OP_SETDELIM:
+    case OP_SETBIGGROUPNUM:
+    case OP_CHECKDELIM:
+    case OP_CALL:
+    case OP_RET:
+    case OP_BRANCH:
+      return false;
+    default:
+      return true;
+  }
+}
+
+static size_t stacksize(upb_pbdecoder *d, size_t entries) {
+  UPB_UNUSED(d);
+  return entries * sizeof(upb_pbdecoder_frame);
+}
+
+static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
+  UPB_UNUSED(d);
+
+#ifdef UPB_USE_JIT_X64
+  if (d->method_->is_native_) {
+    /* Each native stack frame needs two pointers, plus we need a few frames for
+     * the enter/exit trampolines. */
+    size_t ret = entries * sizeof(void*) * 2;
+    ret += sizeof(void*) * 10;
+    return ret;
+  }
+#endif
+
+  return entries * sizeof(uint32_t*);
+}
+
+
+static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
+
+/* It's unfortunate that we have to micro-manage the compiler with
+ * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
+ * specific to one hardware configuration.  But empirically on a Core i7,
+ * performance increases 30-50% with these annotations.  Every instance where
+ * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
+ * benchmarks. */
+
+static void seterr(upb_pbdecoder *d, const char *msg) {
+  upb_status status = UPB_STATUS_INIT;
+  upb_status_seterrmsg(&status, msg);
+  upb_env_reporterror(d->env, &status);
+}
+
+void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
+  seterr(d, msg);
+}
+
+
+/* Buffering ******************************************************************/
+
+/* We operate on one buffer at a time, which is either the user's buffer passed
+ * to our "decode" callback or some residual bytes from the previous buffer. */
+
+/* How many bytes can be safely read from d->ptr without reading past end-of-buf
+ * or past the current delimited end. */
+static size_t curbufleft(const upb_pbdecoder *d) {
+  assert(d->data_end >= d->ptr);
+  return d->data_end - d->ptr;
+}
+
+/* How many bytes are available before end-of-buffer. */
+static size_t bufleft(const upb_pbdecoder *d) {
+  return d->end - d->ptr;
+}
+
+/* Overall stream offset of d->ptr. */
+uint64_t offset(const upb_pbdecoder *d) {
+  return d->bufstart_ofs + (d->ptr - d->buf);
+}
+
+/* How many bytes are available before the end of this delimited region. */
+size_t delim_remaining(const upb_pbdecoder *d) {
+  return d->top->end_ofs - offset(d);
+}
+
+/* Advances d->ptr. */
+static void advance(upb_pbdecoder *d, size_t len) {
+  assert(curbufleft(d) >= len);
+  d->ptr += len;
+}
+
+static bool in_buf(const char *p, const char *buf, const char *end) {
+  return p >= buf && p <= end;
+}
+
+static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
+  return in_buf(p, d->residual, d->residual_end);
+}
+
+/* Calculates the delim_end value, which is affected by both the current buffer
+ * and the parsing stack, so must be called whenever either is updated. */
+static void set_delim_end(upb_pbdecoder *d) {
+  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
+  if (delim_ofs <= (size_t)(d->end - d->buf)) {
+    d->delim_end = d->buf + delim_ofs;
+    d->data_end = d->delim_end;
+  } else {
+    d->data_end = d->end;
+    d->delim_end = NULL;
+  }
+}
+
+static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
+  d->ptr = buf;
+  d->buf = buf;
+  d->end = end;
+  set_delim_end(d);
+}
+
+static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
+  assert(curbufleft(d) == 0);
+  d->bufstart_ofs += (d->end - d->buf);
+  switchtobuf(d, buf, buf + len);
+}
+
+static void checkpoint(upb_pbdecoder *d) {
+  /* The assertion here is in the interests of efficiency, not correctness.
+   * We are trying to ensure that we don't checkpoint() more often than
+   * necessary. */
+  assert(d->checkpoint != d->ptr);
+  d->checkpoint = d->ptr;
+}
+
+/* Skips "bytes" bytes in the stream, which may be more than available.  If we
+ * skip more bytes than are available, we return a long read count to the caller
+ * indicating how many bytes can be skipped over before passing actual data
+ * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
+ * won't actually be read.
+ */
+static int32_t skip(upb_pbdecoder *d, size_t bytes) {
+  assert(!in_residual_buf(d, d->ptr) || d->size_param == 0);
+  assert(d->skip == 0);
+  if (bytes > delim_remaining(d)) {
+    seterr(d, "Skipped value extended beyond enclosing submessage.");
+    return upb_pbdecoder_suspend(d);
+  } else if (bufleft(d) > bytes) {
+    /* Skipped data is all in current buffer, and more is still available. */
+    advance(d, bytes);
+    d->skip = 0;
+    return DECODE_OK;
+  } else {
+    /* Skipped data extends beyond currently available buffers. */
+    d->pc = d->last;
+    d->skip = bytes - curbufleft(d);
+    d->bufstart_ofs += (d->end - d->buf);
+    d->residual_end = d->residual;
+    switchtobuf(d, d->residual, d->residual_end);
+    return d->size_param + d->skip;
+  }
+}
+
+
+/* Resumes the decoder from an initial state or from a previous suspend. */
+int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
+                             size_t size, const upb_bufhandle *handle) {
+  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
+
+  d->buf_param = buf;
+  d->size_param = size;
+  d->handle = handle;
+
+  if (d->residual_end > d->residual) {
+    /* We have residual bytes from the last buffer. */
+    assert(d->ptr == d->residual);
+  } else {
+    switchtobuf(d, buf, buf + size);
+  }
+
+  d->checkpoint = d->ptr;
+
+  if (d->skip) {
+    size_t skip_bytes = d->skip;
+    d->skip = 0;
+    CHECK_RETURN(skip(d, skip_bytes));
+    d->checkpoint = d->ptr;
+  }
+
+  if (!buf) {
+    /* NULL buf is ok if its entire span is covered by the "skip" above, but
+     * by this point we know that "skip" doesn't cover the buffer. */
+    seterr(d, "Passed NULL buffer over non-skippable region.");
+    return upb_pbdecoder_suspend(d);
+  }
+
+  if (d->top->groupnum < 0) {
+    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
+    d->checkpoint = d->ptr;
+  }
+
+  return DECODE_OK;
+}
+
+/* Suspends the decoder at the last checkpoint, without saving any residual
+ * bytes.  If there are any unconsumed bytes, returns a short byte count. */
+size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
+  d->pc = d->last;
+  if (d->checkpoint == d->residual) {
+    /* Checkpoint was in residual buf; no user bytes were consumed. */
+    d->ptr = d->residual;
+    return 0;
+  } else {
+    size_t consumed;
+    assert(!in_residual_buf(d, d->checkpoint));
+    assert(d->buf == d->buf_param);
+
+    consumed = d->checkpoint - d->buf;
+    d->bufstart_ofs += consumed;
+    d->residual_end = d->residual;
+    switchtobuf(d, d->residual, d->residual_end);
+    return consumed;
+  }
+}
+
+/* Suspends the decoder at the last checkpoint, and saves any unconsumed
+ * bytes in our residual buffer.  This is necessary if we need more user
+ * bytes to form a complete value, which might not be contiguous in the
+ * user's buffers.  Always consumes all user bytes. */
+static size_t suspend_save(upb_pbdecoder *d) {
+  /* We hit end-of-buffer before we could parse a full value.
+   * Save any unconsumed bytes (if any) to the residual buffer. */
+  d->pc = d->last;
+
+  if (d->checkpoint == d->residual) {
+    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
+    assert((d->residual_end - d->residual) + d->size_param <=
+           sizeof(d->residual));
+    if (!in_residual_buf(d, d->ptr)) {
+      d->bufstart_ofs -= (d->residual_end - d->residual);
+    }
+    memcpy(d->residual_end, d->buf_param, d->size_param);
+    d->residual_end += d->size_param;
+  } else {
+    /* Checkpoint was in user buf; old residual bytes not needed. */
+    size_t save;
+    assert(!in_residual_buf(d, d->checkpoint));
+
+    d->ptr = d->checkpoint;
+    save = curbufleft(d);
+    assert(save <= sizeof(d->residual));
+    memcpy(d->residual, d->ptr, save);
+    d->residual_end = d->residual + save;
+    d->bufstart_ofs = offset(d);
+  }
+
+  switchtobuf(d, d->residual, d->residual_end);
+  return d->size_param;
+}
+
+/* Copies the next "bytes" bytes into "buf" and advances the stream.
+ * Requires that this many bytes are available in the current buffer. */
+UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
+                                         size_t bytes) {
+  assert(bytes <= curbufleft(d));
+  memcpy(buf, d->ptr, bytes);
+  advance(d, bytes);
+}
+
+/* Slow path for getting the next "bytes" bytes, regardless of whether they are
+ * available in the current buffer or not.  Returns a status code as described
+ * in decoder.int.h. */
+UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
+                                          size_t bytes) {
+  const size_t avail = curbufleft(d);
+  consumebytes(d, buf, avail);
+  bytes -= avail;
+  assert(bytes > 0);
+  if (in_residual_buf(d, d->ptr)) {
+    advancetobuf(d, d->buf_param, d->size_param);
+  }
+  if (curbufleft(d) >= bytes) {
+    consumebytes(d, (char *)buf + avail, bytes);
+    return DECODE_OK;
+  } else if (d->data_end == d->delim_end) {
+    seterr(d, "Submessage ended in the middle of a value or group");
+    return upb_pbdecoder_suspend(d);
+  } else {
+    return suspend_save(d);
+  }
+}
+
+/* Gets the next "bytes" bytes, regardless of whether they are available in the
+ * current buffer or not.  Returns a status code as described in decoder.int.h.
+ */
+UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
+                                        size_t bytes) {
+  if (curbufleft(d) >= bytes) {
+    /* Buffer has enough data to satisfy. */
+    consumebytes(d, buf, bytes);
+    return DECODE_OK;
+  } else {
+    return getbytes_slow(d, buf, bytes);
+  }
+}
+
+UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
+                                          size_t bytes) {
+  size_t ret = curbufleft(d);
+  memcpy(buf, d->ptr, ret);
+  if (in_residual_buf(d, d->ptr)) {
+    size_t copy = UPB_MIN(bytes - ret, d->size_param);
+    memcpy((char *)buf + ret, d->buf_param, copy);
+    ret += copy;
+  }
+  return ret;
+}
+
+UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
+                                        size_t bytes) {
+  if (curbufleft(d) >= bytes) {
+    memcpy(buf, d->ptr, bytes);
+    return bytes;
+  } else {
+    return peekbytes_slow(d, buf, bytes);
+  }
+}
+
+
+/* Decoding of wire types *****************************************************/
+
+/* Slow path for decoding a varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
+                                                      uint64_t *u64) {
+  uint8_t byte = 0x80;
+  int bitpos;
+  *u64 = 0;
+  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
+    int32_t ret = getbytes(d, &byte, 1);
+    if (ret >= 0) return ret;
+    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
+  }
+  if(bitpos == 70 && (byte & 0x80)) {
+    seterr(d, kUnterminatedVarint);
+    return upb_pbdecoder_suspend(d);
+  }
+  return DECODE_OK;
+}
+
+/* Decodes a varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
+  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
+    *u64 = *d->ptr;
+    advance(d, 1);
+    return DECODE_OK;
+  } else if (curbufleft(d) >= 10) {
+    /* Fast case. */
+    upb_decoderet r = upb_vdecode_fast(d->ptr);
+    if (r.p == NULL) {
+      seterr(d, kUnterminatedVarint);
+      return upb_pbdecoder_suspend(d);
+    }
+    advance(d, r.p - d->ptr);
+    *u64 = r.val;
+    return DECODE_OK;
+  } else {
+    /* Slow case -- varint spans buffer seam. */
+    return upb_pbdecoder_decode_varint_slow(d, u64);
+  }
+}
+
+/* Decodes a 32-bit varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
+  uint64_t u64;
+  int32_t ret = decode_varint(d, &u64);
+  if (ret >= 0) return ret;
+  if (u64 > UINT32_MAX) {
+    seterr(d, "Unterminated 32-bit varint");
+    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
+     * so we know this path will always be treated as error by our caller.
+     * Right now the size_t -> int32_t can overflow and produce negative values.
+     */
+    *u32 = 0;
+    return upb_pbdecoder_suspend(d);
+  }
+  *u32 = u64;
+  return DECODE_OK;
+}
+
+/* Decodes a fixed32 from the current buffer position.
+ * Returns a status code as described in decoder.int.h.
+ * TODO: proper byte swapping for big-endian machines. */
+UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
+  return getbytes(d, u32, 4);
+}
+
+/* Decodes a fixed64 from the current buffer position.
+ * Returns a status code as described in decoder.int.h.
+ * TODO: proper byte swapping for big-endian machines. */
+UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
+  return getbytes(d, u64, 8);
+}
+
+/* Non-static versions of the above functions.
+ * These are called by the JIT for fallback paths. */
+int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
+  return decode_fixed32(d, u32);
+}
+
+int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
+  return decode_fixed64(d, u64);
+}
+
+static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
+static float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
+
+/* Pushes a frame onto the decoder stack. */
+static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
+  upb_pbdecoder_frame *fr = d->top;
+
+  if (end > fr->end_ofs) {
+    seterr(d, kPbDecoderSubmessageTooLong);
+    return false;
+  } else if (fr == d->limit) {
+    seterr(d, kPbDecoderStackOverflow);
+    return false;
+  }
+
+  fr++;
+  fr->end_ofs = end;
+  fr->dispatch = NULL;
+  fr->groupnum = 0;
+  d->top = fr;
+  return true;
+}
+
+static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
+  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
+   * field number) prior to hitting any enclosing submessage end, pushing our
+   * existing delim end prevents us from continuing to parse values from a
+   * corrupt proto that doesn't give us an END tag in time. */
+  if (!decoder_push(d, d->top->end_ofs))
+    return false;
+  d->top->groupnum = arg;
+  return true;
+}
+
+/* Pops a frame from the decoder stack. */
+static void decoder_pop(upb_pbdecoder *d) { d->top--; }
+
+UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
+                                                 uint64_t expected) {
+  uint64_t data = 0;
+  size_t bytes = upb_value_size(expected);
+  size_t read = peekbytes(d, &data, bytes);
+  if (read == bytes && data == expected) {
+    /* Advance past matched bytes. */
+    int32_t ok = getbytes(d, &data, read);
+    UPB_ASSERT_VAR(ok, ok < 0);
+    return DECODE_OK;
+  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
+    return suspend_save(d);
+  } else {
+    return DECODE_MISMATCH;
+  }
+}
+
+int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
+                                  uint8_t wire_type) {
+  if (fieldnum >= 0)
+    goto have_tag;
+
+  while (true) {
+    uint32_t tag;
+    CHECK_RETURN(decode_v32(d, &tag));
+    wire_type = tag & 0x7;
+    fieldnum = tag >> 3;
+
+have_tag:
+    if (fieldnum == 0) {
+      seterr(d, "Saw invalid field number (0)");
+      return upb_pbdecoder_suspend(d);
+    }
+
+    /* TODO: deliver to unknown field callback. */
+    switch (wire_type) {
+      case UPB_WIRE_TYPE_32BIT:
+        CHECK_RETURN(skip(d, 4));
+        break;
+      case UPB_WIRE_TYPE_64BIT:
+        CHECK_RETURN(skip(d, 8));
+        break;
+      case UPB_WIRE_TYPE_VARINT: {
+        uint64_t u64;
+        CHECK_RETURN(decode_varint(d, &u64));
+        break;
+      }
+      case UPB_WIRE_TYPE_DELIMITED: {
+        uint32_t len;
+        CHECK_RETURN(decode_v32(d, &len));
+        CHECK_RETURN(skip(d, len));
+        break;
+      }
+      case UPB_WIRE_TYPE_START_GROUP:
+        CHECK_SUSPEND(pushtagdelim(d, -fieldnum));
+        break;
+      case UPB_WIRE_TYPE_END_GROUP:
+        if (fieldnum == -d->top->groupnum) {
+          decoder_pop(d);
+        } else if (fieldnum == d->top->groupnum) {
+          return DECODE_ENDGROUP;
+        } else {
+          seterr(d, "Unmatched ENDGROUP tag.");
+          return upb_pbdecoder_suspend(d);
+        }
+        break;
+      default:
+        seterr(d, "Invalid wire type");
+        return upb_pbdecoder_suspend(d);
+    }
+
+    if (d->top->groupnum >= 0) {
+      return DECODE_OK;
+    }
+
+    /* Unknown group -- continue looping over unknown fields. */
+    checkpoint(d);
+  }
+}
+
+static void goto_endmsg(upb_pbdecoder *d) {
+  upb_value v;
+  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
+  UPB_ASSERT_VAR(found, found);
+  d->pc = d->top->base + upb_value_getuint64(v);
+}
+
+/* Parses a tag and jumps to the corresponding bytecode instruction for this
+ * field.
+ *
+ * If the tag is unknown (or the wire type doesn't match), parses the field as
+ * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
+ * instruction for the end of message. */
+static int32_t dispatch(upb_pbdecoder *d) {
+  upb_inttable *dispatch = d->top->dispatch;
+  uint32_t tag;
+  uint8_t wire_type;
+  uint32_t fieldnum;
+  upb_value val;
+  int32_t retval;
+
+  /* Decode tag. */
+  CHECK_RETURN(decode_v32(d, &tag));
+  wire_type = tag & 0x7;
+  fieldnum = tag >> 3;
+
+  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
+   * check the wire type against two possibilities. */
+  if (fieldnum != DISPATCH_ENDMSG &&
+      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
+    uint64_t v = upb_value_getuint64(val);
+    if (wire_type == (v & 0xff)) {
+      d->pc = d->top->base + (v >> 16);
+      return DECODE_OK;
+    } else if (wire_type == ((v >> 8) & 0xff)) {
+      bool found =
+          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
+      UPB_ASSERT_VAR(found, found);
+      d->pc = d->top->base + upb_value_getuint64(val);
+      return DECODE_OK;
+    }
+  }
+
+  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
+   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
+   * we need to back up to, so that when we're done skipping unknown data we
+   * can re-check the delimited end. */
+  d->last--;  /* Necessary if we get suspended */
+  d->pc = d->last;
+  assert(getop(*d->last) == OP_CHECKDELIM);
+
+  /* Unknown field or ENDGROUP. */
+  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
+
+  CHECK_RETURN(retval);
+
+  if (retval == DECODE_ENDGROUP) {
+    goto_endmsg(d);
+    return DECODE_OK;
+  }
+
+  return DECODE_OK;
+}
+
+/* Callers know that the stack is more than one deep because the opcodes that
+ * call this only occur after PUSH operations. */
+upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
+  assert(d->top != d->stack);
+  return d->top - 1;
+}
+
+
+/* The main decoding loop *****************************************************/
+
+/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
+ * switch() statement. */
+size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
+                      const upb_bufhandle* handle) {
+
+#define VMCASE(op, code) \
+  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
+#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
+  VMCASE(OP_PARSE_ ## type, { \
+    ctype val; \
+    CHECK_RETURN(decode_ ## wt(d, &val)); \
+    upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \
+  })
+
+  while(1) {
+    int32_t instruction;
+    opcode op;
+    uint32_t arg;
+    int32_t longofs;
+
+    d->last = d->pc;
+    instruction = *d->pc++;
+    op = getop(instruction);
+    arg = instruction >> 8;
+    longofs = arg;
+    assert(d->ptr != d->residual_end);
+    UPB_UNUSED(group);
+#ifdef UPB_DUMP_BYTECODE
+    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
+                    "%x %s (%d)\n",
+            (int)offset(d),
+            (int)(d->ptr - d->buf),
+            (int)(d->data_end - d->ptr),
+            (int)(d->end - d->ptr),
+            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
+            (int)(d->pc - 1 - group->bytecode),
+            upb_pbdecoder_getopname(op),
+            arg);
+#endif
+    switch (op) {
+      /* Technically, we are losing data if we see a 32-bit varint that is not
+       * properly sign-extended.  We could detect this and error about the data
+       * loss, but proto2 does not do this, so we pass. */
+      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
+      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
+      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
+      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
+      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
+      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
+      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
+      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
+      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
+      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
+      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
+      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
+      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
+
+      VMCASE(OP_SETDISPATCH,
+        d->top->base = d->pc - 1;
+        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
+        d->pc += sizeof(void*) / sizeof(uint32_t);
+      )
+      VMCASE(OP_STARTMSG,
+        CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink));
+      )
+      VMCASE(OP_ENDMSG,
+        CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status));
+      )
+      VMCASE(OP_STARTSEQ,
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink));
+      )
+      VMCASE(OP_ENDSEQ,
+        CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg));
+      )
+      VMCASE(OP_STARTSUBMSG,
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink));
+      )
+      VMCASE(OP_ENDSUBMSG,
+        CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg));
+      )
+      VMCASE(OP_STARTSTR,
+        uint32_t len = delim_remaining(d);
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink));
+        if (len == 0) {
+          d->pc++;  /* Skip OP_STRING. */
+        }
+      )
+      VMCASE(OP_STRING,
+        uint32_t len = curbufleft(d);
+        size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle);
+        if (n > len) {
+          if (n > delim_remaining(d)) {
+            seterr(d, "Tried to skip past end of string.");
+            return upb_pbdecoder_suspend(d);
+          } else {
+            int32_t ret = skip(d, n);
+            /* This shouldn't return DECODE_OK, because n > len. */
+            assert(ret >= 0);
+            return ret;
+          }
+        }
+        advance(d, n);
+        if (n < len || d->delim_end == NULL) {
+          /* We aren't finished with this string yet. */
+          d->pc--;  /* Repeat OP_STRING. */
+          if (n > 0) checkpoint(d);
+          return upb_pbdecoder_suspend(d);
+        }
+      )
+      VMCASE(OP_ENDSTR,
+        CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg));
+      )
+      VMCASE(OP_PUSHTAGDELIM,
+        CHECK_SUSPEND(pushtagdelim(d, arg));
+      )
+      VMCASE(OP_SETBIGGROUPNUM,
+        d->top->groupnum = *d->pc++;
+      )
+      VMCASE(OP_POP,
+        assert(d->top > d->stack);
+        decoder_pop(d);
+      )
+      VMCASE(OP_PUSHLENDELIM,
+        uint32_t len;
+        CHECK_RETURN(decode_v32(d, &len));
+        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
+        set_delim_end(d);
+      )
+      VMCASE(OP_SETDELIM,
+        set_delim_end(d);
+      )
+      VMCASE(OP_CHECKDELIM,
+        /* We are guaranteed of this assert because we never allow ourselves to
+         * consume bytes beyond data_end, which covers delim_end when non-NULL.
+         */
+        assert(!(d->delim_end && d->ptr > d->delim_end));
+        if (d->ptr == d->delim_end)
+          d->pc += longofs;
+      )
+      VMCASE(OP_CALL,
+        d->callstack[d->call_len++] = d->pc;
+        d->pc += longofs;
+      )
+      VMCASE(OP_RET,
+        assert(d->call_len > 0);
+        d->pc = d->callstack[--d->call_len];
+      )
+      VMCASE(OP_BRANCH,
+        d->pc += longofs;
+      )
+      VMCASE(OP_TAG1,
+        uint8_t expected;
+        CHECK_SUSPEND(curbufleft(d) > 0);
+        expected = (arg >> 8) & 0xff;
+        if (*d->ptr == expected) {
+          advance(d, 1);
+        } else {
+          int8_t shortofs;
+         badtag:
+          shortofs = arg;
+          if (shortofs == LABEL_DISPATCH) {
+            CHECK_RETURN(dispatch(d));
+          } else {
+            d->pc += shortofs;
+            break; /* Avoid checkpoint(). */
+          }
+        }
+      )
+      VMCASE(OP_TAG2,
+        uint16_t expected;
+        CHECK_SUSPEND(curbufleft(d) > 0);
+        expected = (arg >> 8) & 0xffff;
+        if (curbufleft(d) >= 2) {
+          uint16_t actual;
+          memcpy(&actual, d->ptr, 2);
+          if (expected == actual) {
+            advance(d, 2);
+          } else {
+            goto badtag;
+          }
+        } else {
+          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
+          if (result == DECODE_MISMATCH) goto badtag;
+          if (result >= 0) return result;
+        }
+      )
+      VMCASE(OP_TAGN, {
+        uint64_t expected;
+        int32_t result;
+        memcpy(&expected, d->pc, 8);
+        d->pc += 2;
+        result = upb_pbdecoder_checktag_slow(d, expected);
+        if (result == DECODE_MISMATCH) goto badtag;
+        if (result >= 0) return result;
+      })
+      VMCASE(OP_DISPATCH, {
+        CHECK_RETURN(dispatch(d));
+      })
+      VMCASE(OP_HALT, {
+        return d->size_param;
+      })
+    }
+  }
+}
+
+
+/* BytesHandler handlers ******************************************************/
+
+void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
+  upb_pbdecoder *d = closure;
+  UPB_UNUSED(size_hint);
+  d->top->end_ofs = UINT64_MAX;
+  d->bufstart_ofs = 0;
+  d->call_len = 1;
+  d->callstack[0] = &halt;
+  d->pc = pc;
+  d->skip = 0;
+  return d;
+}
+
+void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) {
+  upb_pbdecoder *d = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(size_hint);
+  d->top->end_ofs = UINT64_MAX;
+  d->bufstart_ofs = 0;
+  d->call_len = 0;
+  d->skip = 0;
+  return d;
+}
+
+bool upb_pbdecoder_end(void *closure, const void *handler_data) {
+  upb_pbdecoder *d = closure;
+  const upb_pbdecodermethod *method = handler_data;
+  uint64_t end;
+  char dummy;
+
+  if (d->residual_end > d->residual) {
+    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
+    return false;
+  }
+
+  if (d->skip) {
+    seterr(d, "Unexpected EOF inside skipped data");
+    return false;
+  }
+
+  if (d->top->end_ofs != UINT64_MAX) {
+    seterr(d, "Unexpected EOF inside delimited string");
+    return false;
+  }
+
+  /* The user's end() call indicates that the message ends here. */
+  end = offset(d);
+  d->top->end_ofs = end;
+
+#ifdef UPB_USE_JIT_X64
+  if (method->is_native_) {
+    const mgroup *group = (const mgroup*)method->group;
+    if (d->top != d->stack)
+      d->stack->end_ofs = 0;
+    group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL);
+  } else
+#endif
+  {
+    const uint32_t *p = d->pc;
+    d->stack->end_ofs = end;
+    /* Check the previous bytecode, but guard against beginning. */
+    if (p != method->code_base.ptr) p--;
+    if (getop(*p) == OP_CHECKDELIM) {
+      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
+      assert(getop(*d->pc) == OP_TAG1 ||
+             getop(*d->pc) == OP_TAG2 ||
+             getop(*d->pc) == OP_TAGN ||
+             getop(*d->pc) == OP_DISPATCH);
+      d->pc = p;
+    }
+    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
+  }
+
+  if (d->call_len != 0) {
+    seterr(d, "Unexpected EOF inside submessage or group");
+    return false;
+  }
+
+  return true;
+}
+
+size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
+                            size_t size, const upb_bufhandle *handle) {
+  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
+
+  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
+  CHECK_RETURN(result);
+
+  return run_decoder_vm(decoder, group, handle);
+}
+
+
+/* Public API *****************************************************************/
+
+void upb_pbdecoder_reset(upb_pbdecoder *d) {
+  d->top = d->stack;
+  d->top->groupnum = 0;
+  d->ptr = d->residual;
+  d->buf = d->residual;
+  d->end = d->residual;
+  d->residual_end = d->residual;
+}
+
+upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
+                                    upb_sink *sink) {
+  const size_t default_max_nesting = 64;
+#ifndef NDEBUG
+  size_t size_before = upb_env_bytesallocated(e);
+#endif
+
+  upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder));
+  if (!d) return NULL;
+
+  d->method_ = m;
+  d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting));
+  d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting));
+  if (!d->stack || !d->callstack) {
+    return NULL;
+  }
+
+  d->env = e;
+  d->limit = d->stack + default_max_nesting - 1;
+  d->stack_size = default_max_nesting;
+
+  upb_pbdecoder_reset(d);
+  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
+
+  assert(sink);
+  if (d->method_->dest_handlers_) {
+    if (sink->handlers != d->method_->dest_handlers_)
+      return NULL;
+  }
+  upb_sink_reset(&d->top->sink, sink->handlers, sink->closure);
+
+  /* If this fails, increase the value in decoder.h. */
+  assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE);
+  return d;
+}
+
+uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
+  return offset(d);
+}
+
+const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
+  return d->method_;
+}
+
+upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) {
+  return &d->input_;
+}
+
+size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
+  return d->stack_size;
+}
+
+bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
+  assert(d->top >= d->stack);
+
+  if (max < (size_t)(d->top - d->stack)) {
+    /* Can't set a limit smaller than what we are currently at. */
+    return false;
+  }
+
+  if (max > d->stack_size) {
+    /* Need to reallocate stack and callstack to accommodate. */
+    size_t old_size = stacksize(d, d->stack_size);
+    size_t new_size = stacksize(d, max);
+    void *p = upb_env_realloc(d->env, d->stack, old_size, new_size);
+    if (!p) {
+      return false;
+    }
+    d->stack = p;
+
+    old_size = callstacksize(d, d->stack_size);
+    new_size = callstacksize(d, max);
+    p = upb_env_realloc(d->env, d->callstack, old_size, new_size);
+    if (!p) {
+      return false;
+    }
+    d->callstack = p;
+
+    d->stack_size = max;
+  }
+
+  d->limit = d->stack + max - 1;
+  return true;
+}
+/*
+** upb::Encoder
+**
+** Since we are implementing pure handlers (ie. without any out-of-band access
+** to pre-computed lengths), we have to buffer all submessages before we can
+** emit even their first byte.
+**
+** Not knowing the size of submessages also means we can't write a perfect
+** zero-copy implementation, even with buffering.  Lengths are stored as
+** varints, which means that we don't know how many bytes to reserve for the
+** length until we know what the length is.
+**
+** This leaves us with three main choices:
+**
+** 1. buffer all submessage data in a temporary buffer, then copy it exactly
+**    once into the output buffer.
+**
+** 2. attempt to buffer data directly into the output buffer, estimating how
+**    many bytes each length will take.  When our guesses are wrong, use
+**    memmove() to grow or shrink the allotted space.
+**
+** 3. buffer directly into the output buffer, allocating a max length
+**    ahead-of-time for each submessage length.  If we overallocated, we waste
+**    space, but no memcpy() or memmove() is required.  This approach requires
+**    defining a maximum size for submessages and rejecting submessages that
+**    exceed that size.
+**
+** (2) and (3) have the potential to have better performance, but they are more
+** complicated and subtle to implement:
+**
+**   (3) requires making an arbitrary choice of the maximum message size; it
+**       wastes space when submessages are shorter than this and fails
+**       completely when they are longer.  This makes it more finicky and
+**       requires configuration based on the input.  It also makes it impossible
+**       to perfectly match the output of reference encoders that always use the
+**       optimal amount of space for each length.
+**
+**   (2) requires guessing the the size upfront, and if multiple lengths are
+**       guessed wrong the minimum required number of memmove() operations may
+**       be complicated to compute correctly.  Implemented properly, it may have
+**       a useful amortized or average cost, but more investigation is required
+**       to determine this and what the optimal algorithm is to achieve it.
+**
+**   (1) makes you always pay for exactly one copy, but its implementation is
+**       the simplest and its performance is predictable.
+**
+** So for now, we implement (1) only.  If we wish to optimize later, we should
+** be able to do it without affecting users.
+**
+** The strategy is to buffer the segments of data that do *not* depend on
+** unknown lengths in one buffer, and keep a separate buffer of segment pointers
+** and lengths.  When the top-level submessage ends, we can go beginning to end,
+** alternating the writing of lengths with memcpy() of the rest of the data.
+** At the top level though, no buffering is required.
+*/
+
+
+#include <stdlib.h>
+
+/* The output buffer is divided into segments; a segment is a string of data
+ * that is "ready to go" -- it does not need any varint lengths inserted into
+ * the middle.  The seams between segments are where varints will be inserted
+ * once they are known.
+ *
+ * We also use the concept of a "run", which is a range of encoded bytes that
+ * occur at a single submessage level.  Every segment contains one or more runs.
+ *
+ * A segment can span messages.  Consider:
+ *
+ *                  .--Submessage lengths---------.
+ *                  |       |                     |
+ *                  |       V                     V
+ *                  V      | |---------------    | |-----------------
+ * Submessages:    | |-----------------------------------------------
+ * Top-level msg: ------------------------------------------------------------
+ *
+ * Segments:          -----   -------------------   -----------------
+ * Runs:              *----   *--------------*---   *----------------
+ * (* marks the start)
+ *
+ * Note that the top-level menssage is not in any segment because it does not
+ * have any length preceding it.
+ *
+ * A segment is only interrupted when another length needs to be inserted.  So
+ * observe how the second segment spans both the inner submessage and part of
+ * the next enclosing message. */
+typedef struct {
+  uint32_t msglen;  /* The length to varint-encode before this segment. */
+  uint32_t seglen;  /* Length of the segment. */
+} upb_pb_encoder_segment;
+
+struct upb_pb_encoder {
+  upb_env *env;
+
+  /* Our input and output. */
+  upb_sink input_;
+  upb_bytessink *output_;
+
+  /* The "subclosure" -- used as the inner closure as part of the bytessink
+   * protocol. */
+  void *subc;
+
+  /* The output buffer and limit, and our current write position.  "buf"
+   * initially points to "initbuf", but is dynamically allocated if we need to
+   * grow beyond the initial size. */
+  char *buf, *ptr, *limit;
+
+  /* The beginning of the current run, or undefined if we are at the top
+   * level. */
+  char *runbegin;
+
+  /* The list of segments we are accumulating. */
+  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
+
+  /* The stack of enclosing submessages.  Each entry in the stack points to the
+   * segment where this submessage's length is being accumulated. */
+  int *stack, *top, *stacklimit;
+
+  /* Depth of startmsg/endmsg calls. */
+  int depth;
+};
+
+/* low-level buffering ********************************************************/
+
+/* Low-level functions for interacting with the output buffer. */
+
+/* TODO(haberman): handle pushback */
+static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
+  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
+  UPB_ASSERT_VAR(n, n == len);
+}
+
+static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
+  return &e->segbuf[*e->top];
+}
+
+/* Call to ensure that at least "bytes" bytes are available for writing at
+ * e->ptr.  Returns false if the bytes could not be allocated. */
+static bool reserve(upb_pb_encoder *e, size_t bytes) {
+  if ((size_t)(e->limit - e->ptr) < bytes) {
+    /* Grow buffer. */
+    char *new_buf;
+    size_t needed = bytes + (e->ptr - e->buf);
+    size_t old_size = e->limit - e->buf;
+
+    size_t new_size = old_size;
+
+    while (new_size < needed) {
+      new_size *= 2;
+    }
+
+    new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size);
+
+    if (new_buf == NULL) {
+      return false;
+    }
+
+    e->ptr = new_buf + (e->ptr - e->buf);
+    e->runbegin = new_buf + (e->runbegin - e->buf);
+    e->limit = new_buf + new_size;
+    e->buf = new_buf;
+  }
+
+  return true;
+}
+
+/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
+ * previously called reserve() with at least this many bytes. */
+static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
+  assert((size_t)(e->limit - e->ptr) >= bytes);
+  e->ptr += bytes;
+}
+
+/* Call when all of the bytes for a handler have been written.  Flushes the
+ * bytes if possible and necessary, returning false if this failed. */
+static bool commit(upb_pb_encoder *e) {
+  if (!e->top) {
+    /* We aren't inside a delimited region.  Flush our accumulated bytes to
+     * the output.
+     *
+     * TODO(haberman): in the future we may want to delay flushing for
+     * efficiency reasons. */
+    putbuf(e, e->buf, e->ptr - e->buf);
+    e->ptr = e->buf;
+  }
+
+  return true;
+}
+
+/* Writes the given bytes to the buffer, handling reserve/advance. */
+static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
+  if (!reserve(e, len)) {
+    return false;
+  }
+
+  memcpy(e->ptr, data, len);
+  encoder_advance(e, len);
+  return true;
+}
+
+/* Finish the current run by adding the run totals to the segment and message
+ * length. */
+static void accumulate(upb_pb_encoder *e) {
+  size_t run_len;
+  assert(e->ptr >= e->runbegin);
+  run_len = e->ptr - e->runbegin;
+  e->segptr->seglen += run_len;
+  top(e)->msglen += run_len;
+  e->runbegin = e->ptr;
+}
+
+/* Call to indicate the start of delimited region for which the full length is
+ * not yet known.  All data will be buffered until the length is known.
+ * Delimited regions may be nested; their lengths will all be tracked properly. */
+static bool start_delim(upb_pb_encoder *e) {
+  if (e->top) {
+    /* We are already buffering, advance to the next segment and push it on the
+     * stack. */
+    accumulate(e);
+
+    if (++e->top == e->stacklimit) {
+      /* TODO(haberman): grow stack? */
+      return false;
+    }
+
+    if (++e->segptr == e->seglimit) {
+      /* Grow segment buffer. */
+      size_t old_size =
+          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
+      size_t new_size = old_size * 2;
+      upb_pb_encoder_segment *new_buf =
+          upb_env_realloc(e->env, e->segbuf, old_size, new_size);
+
+      if (new_buf == NULL) {
+        return false;
+      }
+
+      e->segptr = new_buf + (e->segptr - e->segbuf);
+      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
+      e->segbuf = new_buf;
+    }
+  } else {
+    /* We were previously at the top level, start buffering. */
+    e->segptr = e->segbuf;
+    e->top = e->stack;
+    e->runbegin = e->ptr;
+  }
+
+  *e->top = e->segptr - e->segbuf;
+  e->segptr->seglen = 0;
+  e->segptr->msglen = 0;
+
+  return true;
+}
+
+/* Call to indicate the end of a delimited region.  We now know the length of
+ * the delimited region.  If we are not nested inside any other delimited
+ * regions, we can now emit all of the buffered data we accumulated. */
+static bool end_delim(upb_pb_encoder *e) {
+  size_t msglen;
+  accumulate(e);
+  msglen = top(e)->msglen;
+
+  if (e->top == e->stack) {
+    /* All lengths are now available, emit all buffered data. */
+    char buf[UPB_PB_VARINT_MAX_LEN];
+    upb_pb_encoder_segment *s;
+    const char *ptr = e->buf;
+    for (s = e->segbuf; s <= e->segptr; s++) {
+      size_t lenbytes = upb_vencode64(s->msglen, buf);
+      putbuf(e, buf, lenbytes);
+      putbuf(e, ptr, s->seglen);
+      ptr += s->seglen;
+    }
+
+    e->ptr = e->buf;
+    e->top = NULL;
+  } else {
+    /* Need to keep buffering; propagate length info into enclosing
+     * submessages. */
+    --e->top;
+    top(e)->msglen += msglen + upb_varint_size(msglen);
+  }
+
+  return true;
+}
+
+
+/* tag_t **********************************************************************/
+
+/* A precomputed (pre-encoded) tag and length. */
+
+typedef struct {
+  uint8_t bytes;
+  char tag[7];
+} tag_t;
+
+/* Allocates a new tag for this field, and sets it in these handlerattr. */
+static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
+                    upb_handlerattr *attr) {
+  uint32_t n = upb_fielddef_number(f);
+
+  tag_t *tag = malloc(sizeof(tag_t));
+  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
+
+  upb_handlerattr_init(attr);
+  upb_handlerattr_sethandlerdata(attr, tag);
+  upb_handlers_addcleanup(h, tag, free);
+}
+
+static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
+  return encode_bytes(e, tag->tag, tag->bytes);
+}
+
+
+/* encoding of wire types *****************************************************/
+
+static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
+  /* TODO(haberman): byte-swap for big endian. */
+  return encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
+  /* TODO(haberman): byte-swap for big endian. */
+  return encode_bytes(e, &val, sizeof(uint32_t));
+}
+
+static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
+  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
+    return false;
+  }
+
+  encoder_advance(e, upb_vencode64(val, e->ptr));
+  return true;
+}
+
+static uint64_t dbl2uint64(double d) {
+  uint64_t ret;
+  memcpy(&ret, &d, sizeof(uint64_t));
+  return ret;
+}
+
+static uint32_t flt2uint32(float d) {
+  uint32_t ret;
+  memcpy(&ret, &d, sizeof(uint32_t));
+  return ret;
+}
+
+
+/* encoding of proto types ****************************************************/
+
+static bool startmsg(void *c, const void *hd) {
+  upb_pb_encoder *e = c;
+  UPB_UNUSED(hd);
+  if (e->depth++ == 0) {
+    upb_bytessink_start(e->output_, 0, &e->subc);
+  }
+  return true;
+}
+
+static bool endmsg(void *c, const void *hd, upb_status *status) {
+  upb_pb_encoder *e = c;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(status);
+  if (--e->depth == 0) {
+    upb_bytessink_end(e->output_);
+  }
+  return true;
+}
+
+static void *encode_startdelimfield(void *c, const void *hd) {
+  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
+  return ok ? c : UPB_BREAK;
+}
+
+static bool encode_enddelimfield(void *c, const void *hd) {
+  UPB_UNUSED(hd);
+  return end_delim(c);
+}
+
+static void *encode_startgroup(void *c, const void *hd) {
+  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
+}
+
+static bool encode_endgroup(void *c, const void *hd) {
+  return encode_tag(c, hd) && commit(c);
+}
+
+static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
+  UPB_UNUSED(size_hint);
+  return encode_startdelimfield(c, hd);
+}
+
+static size_t encode_strbuf(void *c, const void *hd, const char *buf,
+                            size_t len, const upb_bufhandle *h) {
+  UPB_UNUSED(hd);
+  UPB_UNUSED(h);
+  return encode_bytes(c, buf, len) ? len : 0;
+}
+
+#define T(type, ctype, convert, encode)                                  \
+  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
+    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
+  }                                                                      \
+  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
+    UPB_UNUSED(hd);                                                      \
+    return encode(e, (convert)(val));                                    \
+  }
+
+T(double,   double,   dbl2uint64,   encode_fixed64)
+T(float,    float,    flt2uint32,   encode_fixed32)
+T(int64,    int64_t,  uint64_t,     encode_varint)
+T(int32,    int32_t,  uint32_t,     encode_varint)
+T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
+T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
+T(bool,     bool,     bool,         encode_varint)
+T(uint32,   uint32_t, uint32_t,     encode_varint)
+T(uint64,   uint64_t, uint64_t,     encode_varint)
+T(enum,     int32_t,  uint32_t,     encode_varint)
+T(sfixed32, int32_t,  uint32_t,     encode_fixed32)
+T(sfixed64, int64_t,  uint64_t,     encode_fixed64)
+T(sint32,   int32_t,  upb_zzenc_32, encode_varint)
+T(sint64,   int64_t,  upb_zzenc_64, encode_varint)
+
+#undef T
+
+
+/* code to build the handlers *************************************************/
+
+static void newhandlers_callback(const void *closure, upb_handlers *h) {
+  const upb_msgdef *m;
+  upb_msg_field_iter i;
+
+  UPB_UNUSED(closure);
+
+  upb_handlers_setstartmsg(h, startmsg, NULL);
+  upb_handlers_setendmsg(h, endmsg, NULL);
+
+  m = upb_handlers_msgdef(h);
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
+                  upb_fielddef_packed(f);
+    upb_handlerattr attr;
+    upb_wiretype_t wt =
+        packed ? UPB_WIRE_TYPE_DELIMITED
+               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
+
+    /* Pre-encode the tag for this field. */
+    new_tag(h, f, wt, &attr);
+
+    if (packed) {
+      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
+      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
+    }
+
+#define T(upper, lower, upbtype)                                     \
+  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
+    if (packed) {                                                    \
+      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
+    } else {                                                         \
+      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
+    }                                                                \
+    break;
+
+    switch (upb_fielddef_descriptortype(f)) {
+      T(DOUBLE,   double,   double);
+      T(FLOAT,    float,    float);
+      T(INT64,    int64,    int64);
+      T(INT32,    int32,    int32);
+      T(FIXED64,  fixed64,  uint64);
+      T(FIXED32,  fixed32,  uint32);
+      T(BOOL,     bool,     bool);
+      T(UINT32,   uint32,   uint32);
+      T(UINT64,   uint64,   uint64);
+      T(ENUM,     enum,     int32);
+      T(SFIXED32, sfixed32, int32);
+      T(SFIXED64, sfixed64, int64);
+      T(SINT32,   sint32,   int32);
+      T(SINT64,   sint64,   int64);
+      case UPB_DESCRIPTOR_TYPE_STRING:
+      case UPB_DESCRIPTOR_TYPE_BYTES:
+        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
+        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
+        upb_handlers_setstring(h, f, encode_strbuf, &attr);
+        break;
+      case UPB_DESCRIPTOR_TYPE_MESSAGE:
+        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
+        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
+        break;
+      case UPB_DESCRIPTOR_TYPE_GROUP: {
+        /* Endgroup takes a different tag (wire_type = END_GROUP). */
+        upb_handlerattr attr2;
+        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
+
+        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
+        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
+
+        upb_handlerattr_uninit(&attr2);
+        break;
+      }
+    }
+
+#undef T
+
+    upb_handlerattr_uninit(&attr);
+  }
+}
+
+void upb_pb_encoder_reset(upb_pb_encoder *e) {
+  e->segptr = NULL;
+  e->top = NULL;
+  e->depth = 0;
+}
+
+
+/* public API *****************************************************************/
+
+const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
+                                               const void *owner) {
+  return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL);
+}
+
+upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
+                                      upb_bytessink *output) {
+  const size_t initial_bufsize = 256;
+  const size_t initial_segbufsize = 16;
+  /* TODO(haberman): make this configurable. */
+  const size_t stack_size = 64;
+#ifndef NDEBUG
+  const size_t size_before = upb_env_bytesallocated(env);
+#endif
+
+  upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder));
+  if (!e) return NULL;
+
+  e->buf = upb_env_malloc(env, initial_bufsize);
+  e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf));
+  e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack));
+
+  if (!e->buf || !e->segbuf || !e->stack) {
+    return NULL;
+  }
+
+  e->limit = e->buf + initial_bufsize;
+  e->seglimit = e->segbuf + initial_segbufsize;
+  e->stacklimit = e->stack + stack_size;
+
+  upb_pb_encoder_reset(e);
+  upb_sink_reset(&e->input_, h, e);
+
+  e->env = env;
+  e->output_ = output;
+  e->subc = output->closure;
+  e->ptr = e->buf;
+
+  /* If this fails, increase the value in encoder.h. */
+  assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE);
+  return e;
+}
+
+upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
+                                        void *owner, upb_status *status) {
+  /* Create handlers. */
+  const upb_pbdecodermethod *decoder_m;
+  const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h);
+  upb_env env;
+  upb_pbdecodermethodopts opts;
+  upb_pbdecoder *decoder;
+  upb_descreader *reader;
+  bool ok;
+  upb_def **ret = NULL;
+  upb_def **defs;
+
+  upb_pbdecodermethodopts_init(&opts, reader_h);
+  decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m);
+
+  upb_env_init(&env);
+  upb_env_reporterrorsto(&env, status);
+
+  reader = upb_descreader_create(&env, reader_h);
+  decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader));
+
+  /* Push input data. */
+  ok = upb_bufsrc_putbuf(str, len, upb_pbdecoder_input(decoder));
+
+  if (!ok) goto cleanup;
+  defs = upb_descreader_getdefs(reader, owner, n);
+  ret = malloc(sizeof(upb_def*) * (*n));
+  memcpy(ret, defs, sizeof(upb_def*) * (*n));
+
+cleanup:
+  upb_env_uninit(&env);
+  upb_handlers_unref(reader_h, &reader_h);
+  upb_pbdecodermethod_unref(decoder_m, &decoder_m);
+  return ret;
+}
+
+bool upb_load_descriptor_into_symtab(upb_symtab *s, const char *str, size_t len,
+                                     upb_status *status) {
+  int n;
+  bool success;
+  upb_def **defs = upb_load_defs_from_descriptor(str, len, &n, &defs, status);
+  if (!defs) return false;
+  success = upb_symtab_add(s, defs, n, &defs, status);
+  free(defs);
+  return success;
+}
+
+char *upb_readfile(const char *filename, size_t *len) {
+  long size;
+  char *buf;
+  FILE *f = fopen(filename, "rb");
+  if(!f) return NULL;
+  if(fseek(f, 0, SEEK_END) != 0) goto error;
+  size = ftell(f);
+  if(size < 0) goto error;
+  if(fseek(f, 0, SEEK_SET) != 0) goto error;
+  buf = malloc(size + 1);
+  if(size && fread(buf, size, 1, f) != 1) goto error;
+  fclose(f);
+  if (len) *len = size;
+  return buf;
+
+error:
+  fclose(f);
+  return NULL;
+}
+
+bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
+                                          upb_status *status) {
+  size_t len;
+  bool success;
+  char *data = upb_readfile(fname, &len);
+  if (!data) {
+    if (status) upb_status_seterrf(status, "Couldn't read file: %s", fname);
+    return false;
+  }
+  success = upb_load_descriptor_into_symtab(symtab, data, len, status);
+  free(data);
+  return success;
+}
+/*
+ * upb::pb::TextPrinter
+ *
+ * OPT: This is not optimized at all.  It uses printf() which parses the format
+ * string every time, and it allocates memory for every put.
+ */
+
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+struct upb_textprinter {
+  upb_sink input_;
+  upb_bytessink *output_;
+  int indent_depth_;
+  bool single_line_;
+  void *subc;
+};
+
+#define CHECK(x) if ((x) < 0) goto err;
+
+static const char *shortname(const char *longname) {
+  const char *last = strrchr(longname, '.');
+  return last ? last + 1 : longname;
+}
+
+static int indent(upb_textprinter *p) {
+  int i;
+  if (!p->single_line_)
+    for (i = 0; i < p->indent_depth_; i++)
+      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
+  return 0;
+}
+
+static int endfield(upb_textprinter *p) {
+  const char ch = (p->single_line_ ? ' ' : '\n');
+  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
+  return 0;
+}
+
+static int putescaped(upb_textprinter *p, const char *buf, size_t len,
+                      bool preserve_utf8) {
+  /* Based on CEscapeInternal() from Google's protobuf release. */
+  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
+  const char *end = buf + len;
+
+  /* I think hex is prettier and more useful, but proto2 uses octal; should
+   * investigate whether it can parse hex also. */
+  const bool use_hex = false;
+  bool last_hex_escape = false; /* true if last output char was \xNN */
+
+  for (; buf < end; buf++) {
+    bool is_hex_escape;
+
+    if (dstend - dst < 4) {
+      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
+      dst = dstbuf;
+    }
+
+    is_hex_escape = false;
+    switch (*buf) {
+      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
+      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
+      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
+      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
+      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
+      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
+      default:
+        /* Note that if we emit \xNN and the buf character after that is a hex
+         * digit then that digit must be escaped too to prevent it being
+         * interpreted as part of the character code by C. */
+        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
+            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
+          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
+          is_hex_escape = use_hex;
+          dst += 4;
+        } else {
+          *(dst++) = *buf; break;
+        }
+    }
+    last_hex_escape = is_hex_escape;
+  }
+  /* Flush remaining data. */
+  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
+  return 0;
+}
+
+bool putf(upb_textprinter *p, const char *fmt, ...) {
+  va_list args;
+  va_list args_copy;
+  char *str;
+  int written;
+  int len;
+  bool ok;
+
+  va_start(args, fmt);
+
+  /* Run once to get the length of the string. */
+  _upb_va_copy(args_copy, args);
+  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
+  va_end(args_copy);
+
+  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
+  str = malloc(len + 1);
+  if (!str) return false;
+  written = vsprintf(str, fmt, args);
+  va_end(args);
+  UPB_ASSERT_VAR(written, written == len);
+
+  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
+  free(str);
+  return ok;
+}
+
+
+/* handlers *******************************************************************/
+
+static bool textprinter_startmsg(void *c, const void *hd) {
+  upb_textprinter *p = c;
+  UPB_UNUSED(hd);
+  if (p->indent_depth_ == 0) {
+    upb_bytessink_start(p->output_, 0, &p->subc);
+  }
+  return true;
+}
+
+static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
+  upb_textprinter *p = c;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(s);
+  if (p->indent_depth_ == 0) {
+    upb_bytessink_end(p->output_);
+  }
+  return true;
+}
+
+#define TYPE(name, ctype, fmt) \
+  static bool textprinter_put ## name(void *closure, const void *handler_data, \
+                                      ctype val) {                             \
+    upb_textprinter *p = closure;                                              \
+    const upb_fielddef *f = handler_data;                                      \
+    CHECK(indent(p));                                                          \
+    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
+    CHECK(endfield(p));                                                        \
+    return true;                                                               \
+  err:                                                                         \
+    return false;                                                              \
+}
+
+static bool textprinter_putbool(void *closure, const void *handler_data,
+                                bool val) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  CHECK(indent(p));
+  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
+  CHECK(endfield(p));
+  return true;
+err:
+  return false;
+}
+
+#define STRINGIFY_HELPER(x) #x
+#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
+
+TYPE(int32,  int32_t,  "%" PRId32)
+TYPE(int64,  int64_t,  "%" PRId64)
+TYPE(uint32, uint32_t, "%" PRIu32)
+TYPE(uint64, uint64_t, "%" PRIu64)
+TYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
+TYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
+
+#undef TYPE
+
+/* Output a symbolic value from the enum if found, else just print as int32. */
+static bool textprinter_putenum(void *closure, const void *handler_data,
+                                int32_t val) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
+  const char *label = upb_enumdef_iton(enum_def, val);
+  if (label) {
+    indent(p);
+    putf(p, "%s: %s", upb_fielddef_name(f), label);
+    endfield(p);
+  } else {
+    if (!textprinter_putint32(closure, handler_data, val))
+      return false;
+  }
+  return true;
+}
+
+static void *textprinter_startstr(void *closure, const void *handler_data,
+                      size_t size_hint) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  UPB_UNUSED(size_hint);
+  indent(p);
+  putf(p, "%s: \"", upb_fielddef_name(f));
+  return p;
+}
+
+static bool textprinter_endstr(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  UPB_UNUSED(handler_data);
+  putf(p, "\"");
+  endfield(p);
+  return true;
+}
+
+static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
+                                 size_t len, const upb_bufhandle *handle) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = hd;
+  UPB_UNUSED(handle);
+  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
+  return len;
+err:
+  return 0;
+}
+
+static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  const char *name = handler_data;
+  CHECK(indent(p));
+  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
+  p->indent_depth_++;
+  return p;
+err:
+  return UPB_BREAK;
+}
+
+static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  UPB_UNUSED(handler_data);
+  p->indent_depth_--;
+  CHECK(indent(p));
+  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
+  CHECK(endfield(p));
+  return true;
+err:
+  return false;
+}
+
+static void onmreg(const void *c, upb_handlers *h) {
+  const upb_msgdef *m = upb_handlers_msgdef(h);
+  upb_msg_field_iter i;
+  UPB_UNUSED(c);
+
+  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
+  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
+
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+    upb_handlerattr_sethandlerdata(&attr, f);
+    switch (upb_fielddef_type(f)) {
+      case UPB_TYPE_INT32:
+        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
+        break;
+      case UPB_TYPE_INT64:
+        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
+        break;
+      case UPB_TYPE_UINT32:
+        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
+        break;
+      case UPB_TYPE_UINT64:
+        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
+        break;
+      case UPB_TYPE_FLOAT:
+        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
+        break;
+      case UPB_TYPE_DOUBLE:
+        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
+        break;
+      case UPB_TYPE_BOOL:
+        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
+        break;
+      case UPB_TYPE_STRING:
+      case UPB_TYPE_BYTES:
+        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
+        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
+        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
+        break;
+      case UPB_TYPE_MESSAGE: {
+        const char *name =
+            upb_fielddef_istagdelim(f)
+                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
+                : upb_fielddef_name(f);
+        upb_handlerattr_sethandlerdata(&attr, name);
+        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
+        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
+        break;
+      }
+      case UPB_TYPE_ENUM:
+        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
+        break;
+    }
+  }
+}
+
+static void textprinter_reset(upb_textprinter *p, bool single_line) {
+  p->single_line_ = single_line;
+  p->indent_depth_ = 0;
+}
+
+
+/* Public API *****************************************************************/
+
+upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
+                                        upb_bytessink *output) {
+  upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter));
+  if (!p) return NULL;
+
+  p->output_ = output;
+  upb_sink_reset(&p->input_, h, p);
+  textprinter_reset(p, false);
+
+  return p;
+}
+
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+                                                const void *owner) {
+  return upb_handlers_newfrozen(m, owner, &onmreg, NULL);
+}
+
+upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
+
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
+  p->single_line_ = single_line;
+}
+
+
+/* Index is descriptor type. */
+const uint8_t upb_pb_native_wire_types[] = {
+  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
+  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
+  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
+  UPB_WIRE_TYPE_VARINT,        /* INT64 */
+  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
+  UPB_WIRE_TYPE_VARINT,        /* INT32 */
+  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
+  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
+  UPB_WIRE_TYPE_VARINT,        /* BOOL */
+  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
+  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
+  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
+  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
+  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
+  UPB_WIRE_TYPE_VARINT,        /* ENUM */
+  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
+  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
+  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
+  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
+};
+
+/* A basic branch-based decoder, uses 32-bit values to get good performance
+ * on 32-bit architectures (but performs well on 64-bits also).
+ * This scheme comes from the original Google Protobuf implementation
+ * (proto2). */
+upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
+  upb_decoderet err = {NULL, 0};
+  const char *p = r.p;
+  uint32_t low = (uint32_t)r.val;
+  uint32_t high = 0;
+  uint32_t b;
+  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
+  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
+  b = *(p++); low  |= (b & 0x7fU) << 28;
+              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
+  return err;
+
+done:
+  r.val = ((uint64_t)high << 32) | low;
+  r.p = p;
+  return r;
+}
+
+/* Like the previous, but uses 64-bit values. */
+upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
+  const char *p = r.p;
+  uint64_t val = r.val;
+  uint64_t b;
+  upb_decoderet err = {NULL, 0};
+  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
+  return err;
+
+done:
+  r.val = val;
+  r.p = p;
+  return r;
+}
+
+/* Given an encoded varint v, returns an integer with a single bit set that
+ * indicates the end of the varint.  Subtracting one from this value will
+ * yield a mask that leaves only bits that are part of the varint.  Returns
+ * 0 if the varint is unterminated. */
+static uint64_t upb_get_vstopbit(uint64_t v) {
+  uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
+  return ~cbits & (cbits+1);
+}
+
+/* A branchless decoder.  Credit to Pascal Massimino for the bit-twiddling. */
+upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
+  uint64_t b;
+  uint64_t stop_bit;
+  upb_decoderet my_r;
+  memcpy(&b, r.p, sizeof(b));
+  stop_bit = upb_get_vstopbit(b);
+  b =  (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
+  b +=       b & 0x007f007f007f007fULL;
+  b +=  3 * (b & 0x0000ffff0000ffffULL);
+  b += 15 * (b & 0x00000000ffffffffULL);
+  if (stop_bit == 0) {
+    /* Error: unterminated varint. */
+    upb_decoderet err_r = {(void*)0, 0};
+    return err_r;
+  }
+  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
+                            r.val | (b << 7));
+  return my_r;
+}
+
+/* A branchless decoder.  Credit to Daniel Wright for the bit-twiddling. */
+upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
+  uint64_t b;
+  uint64_t stop_bit;
+  upb_decoderet my_r;
+  memcpy(&b, r.p, sizeof(b));
+  stop_bit = upb_get_vstopbit(b);
+  b &= (stop_bit - 1);
+  b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
+  b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
+  b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
+  if (stop_bit == 0) {
+    /* Error: unterminated varint. */
+    upb_decoderet err_r = {(void*)0, 0};
+    return err_r;
+  }
+  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
+                            r.val | (b << 14));
+  return my_r;
+}
+
+#line 1 "upb/json/parser.rl"
+/*
+** upb::json::Parser (upb_json_parser)
+**
+** A parser that uses the Ragel State Machine Compiler to generate
+** the finite automata.
+**
+** Ragel only natively handles regular languages, but we can manually
+** program it a bit to handle context-free languages like JSON, by using
+** the "fcall" and "fret" constructs.
+**
+** This parser can handle the basics, but needs several things to be fleshed
+** out:
+**
+** - handling of unicode escape sequences (including high surrogate pairs).
+** - properly check and report errors for unknown fields, stack overflow,
+**   improper array nesting (or lack of nesting).
+** - handling of base64 sequences with padding characters.
+** - handling of push-back (non-success returns from sink functions).
+** - handling of keys/escape-sequences/etc that span input buffers.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+#define UPB_JSON_MAX_DEPTH 64
+
+typedef struct {
+  upb_sink sink;
+
+  /* The current message in which we're parsing, and the field whose value we're
+   * expecting next. */
+  const upb_msgdef *m;
+  const upb_fielddef *f;
+
+  /* We are in a repeated-field context, ready to emit mapentries as
+   * submessages. This flag alters the start-of-object (open-brace) behavior to
+   * begin a sequence of mapentry messages rather than a single submessage. */
+  bool is_map;
+
+  /* We are in a map-entry message context. This flag is set when parsing the
+   * value field of a single map entry and indicates to all value-field parsers
+   * (subobjects, strings, numbers, and bools) that the map-entry submessage
+   * should end as soon as the value is parsed. */
+  bool is_mapentry;
+
+  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
+   * message's map field that we're currently parsing. This differs from |f|
+   * because |f| is the field in the *current* message (i.e., the map-entry
+   * message itself), not the parent's field that leads to this map. */
+  const upb_fielddef *mapfield;
+} upb_jsonparser_frame;
+
+struct upb_json_parser {
+  upb_env *env;
+  upb_byteshandler input_handler_;
+  upb_bytessink input_;
+
+  /* Stack to track the JSON scopes we are in. */
+  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
+  upb_jsonparser_frame *top;
+  upb_jsonparser_frame *limit;
+
+  upb_status status;
+
+  /* Ragel's internal parsing stack for the parsing state machine. */
+  int current_state;
+  int parser_stack[UPB_JSON_MAX_DEPTH];
+  int parser_top;
+
+  /* The handle for the current buffer. */
+  const upb_bufhandle *handle;
+
+  /* Accumulate buffer.  See details in parser.rl. */
+  const char *accumulated;
+  size_t accumulated_len;
+  char *accumulate_buf;
+  size_t accumulate_buf_size;
+
+  /* Multi-part text data.  See details in parser.rl. */
+  int multipart_state;
+  upb_selector_t string_selector;
+
+  /* Input capture.  See details in parser.rl. */
+  const char *capture;
+
+  /* Intermediate result of parsing a unicode escape sequence. */
+  uint32_t digit;
+};
+
+#define PARSER_CHECK_RETURN(x) if (!(x)) return false
+
+/* Used to signal that a capture has been suspended. */
+static char suspend_capture;
+
+static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
+                                             upb_handlertype_t type) {
+  upb_selector_t sel;
+  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
+  UPB_ASSERT_VAR(ok, ok);
+  return sel;
+}
+
+static upb_selector_t parser_getsel(upb_json_parser *p) {
+  return getsel_for_handlertype(
+      p, upb_handlers_getprimitivehandlertype(p->top->f));
+}
+
+static bool check_stack(upb_json_parser *p) {
+  if ((p->top + 1) == p->limit) {
+    upb_status_seterrmsg(&p->status, "Nesting too deep");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  return true;
+}
+
+/* There are GCC/Clang built-ins for overflow checking which we could start
+ * using if there was any performance benefit to it. */
+
+static bool checked_add(size_t a, size_t b, size_t *c) {
+  if (SIZE_MAX - a < b) return false;
+  *c = a + b;
+  return true;
+}
+
+static size_t saturating_multiply(size_t a, size_t b) {
+  /* size_t is unsigned, so this is defined behavior even on overflow. */
+  size_t ret = a * b;
+  if (b != 0 && ret / b != a) {
+    ret = SIZE_MAX;
+  }
+  return ret;
+}
+
+
+/* Base64 decoding ************************************************************/
+
+/* TODO(haberman): make this streaming. */
+
+static const signed char b64table[] = {
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
+  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
+  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
+  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
+};
+
+/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
+ * bits will be 1 for unrecognized characters makes it easier to check for
+ * this error condition later (see below). */
+int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
+
+/* Returns true if the given character is not a valid base64 character or
+ * padding. */
+bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
+
+static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
+                        size_t len) {
+  const char *limit = ptr + len;
+  for (; ptr < limit; ptr += 4) {
+    uint32_t val;
+    char output[3];
+
+    if (limit - ptr < 4) {
+      upb_status_seterrf(&p->status,
+                         "Base64 input for bytes field not a multiple of 4: %s",
+                         upb_fielddef_name(p->top->f));
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12 |
+          b64lookup(ptr[2]) << 6  |
+          b64lookup(ptr[3]);
+
+    /* Test the upper bit; returns true if any of the characters returned -1. */
+    if (val & 0x80000000) {
+      goto otherchar;
+    }
+
+    output[0] = val >> 16;
+    output[1] = (val >> 8) & 0xff;
+    output[2] = val & 0xff;
+    upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
+  }
+  return true;
+
+otherchar:
+  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
+      nonbase64(ptr[3]) ) {
+    upb_status_seterrf(&p->status,
+                       "Non-base64 characters in bytes field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  } if (ptr[2] == '=') {
+    uint32_t val;
+    char output;
+
+    /* Last group contains only two input bytes, one output byte. */
+    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
+      goto badpadding;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12;
+
+    assert(!(val & 0x80000000));
+    output = val >> 16;
+    upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
+    return true;
+  } else {
+    uint32_t val;
+    char output[2];
+
+    /* Last group contains only three input bytes, two output bytes. */
+    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
+      goto badpadding;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12 |
+          b64lookup(ptr[2]) << 6;
+
+    output[0] = val >> 16;
+    output[1] = (val >> 8) & 0xff;
+    upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
+    return true;
+  }
+
+badpadding:
+  upb_status_seterrf(&p->status,
+                     "Incorrect base64 padding for field: %s (%.*s)",
+                     upb_fielddef_name(p->top->f),
+                     4, ptr);
+  upb_env_reporterror(p->env, &p->status);
+  return false;
+}
+
+
+/* Accumulate buffer **********************************************************/
+
+/* Functionality for accumulating a buffer.
+ *
+ * Some parts of the parser need an entire value as a contiguous string.  For
+ * example, to look up a member name in a hash table, or to turn a string into
+ * a number, the relevant library routines need the input string to be in
+ * contiguous memory, even if the value spanned two or more buffers in the
+ * input.  These routines handle that.
+ *
+ * In the common case we can just point to the input buffer to get this
+ * contiguous string and avoid any actual copy.  So we optimistically begin
+ * this way.  But there are a few cases where we must instead copy into a
+ * separate buffer:
+ *
+ *   1. The string was not contiguous in the input (it spanned buffers).
+ *
+ *   2. The string included escape sequences that need to be interpreted to get
+ *      the true value in a contiguous buffer. */
+
+static void assert_accumulate_empty(upb_json_parser *p) {
+  UPB_UNUSED(p);
+  assert(p->accumulated == NULL);
+  assert(p->accumulated_len == 0);
+}
+
+static void accumulate_clear(upb_json_parser *p) {
+  p->accumulated = NULL;
+  p->accumulated_len = 0;
+}
+
+/* Used internally by accumulate_append(). */
+static bool accumulate_realloc(upb_json_parser *p, size_t need) {
+  void *mem;
+  size_t old_size = p->accumulate_buf_size;
+  size_t new_size = UPB_MAX(old_size, 128);
+  while (new_size < need) {
+    new_size = saturating_multiply(new_size, 2);
+  }
+
+  mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+  if (!mem) {
+    upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  p->accumulate_buf = mem;
+  p->accumulate_buf_size = new_size;
+  return true;
+}
+
+/* Logically appends the given data to the append buffer.
+ * If "can_alias" is true, we will try to avoid actually copying, but the buffer
+ * must be valid until the next accumulate_append() call (if any). */
+static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
+                              bool can_alias) {
+  size_t need;
+
+  if (!p->accumulated && can_alias) {
+    p->accumulated = buf;
+    p->accumulated_len = len;
+    return true;
+  }
+
+  if (!checked_add(p->accumulated_len, len, &need)) {
+    upb_status_seterrmsg(&p->status, "Integer overflow.");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
+    return false;
+  }
+
+  if (p->accumulated != p->accumulate_buf) {
+    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
+    p->accumulated = p->accumulate_buf;
+  }
+
+  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
+  p->accumulated_len += len;
+  return true;
+}
+
+/* Returns a pointer to the data accumulated since the last accumulate_clear()
+ * call, and writes the length to *len.  This with point either to the input
+ * buffer or a temporary accumulate buffer. */
+static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
+  assert(p->accumulated);
+  *len = p->accumulated_len;
+  return p->accumulated;
+}
+
+
+/* Mult-part text data ********************************************************/
+
+/* When we have text data in the input, it can often come in multiple segments.
+ * For example, there may be some raw string data followed by an escape
+ * sequence.  The two segments are processed with different logic.  Also buffer
+ * seams in the input can cause multiple segments.
+ *
+ * As we see segments, there are two main cases for how we want to process them:
+ *
+ *  1. we want to push the captured input directly to string handlers.
+ *
+ *  2. we need to accumulate all the parts into a contiguous buffer for further
+ *     processing (field name lookup, string->number conversion, etc). */
+
+/* This is the set of states for p->multipart_state. */
+enum {
+  /* We are not currently processing multipart data. */
+  MULTIPART_INACTIVE = 0,
+
+  /* We are processing multipart data by accumulating it into a contiguous
+   * buffer. */
+  MULTIPART_ACCUMULATE = 1,
+
+  /* We are processing multipart data by pushing each part directly to the
+   * current string handlers. */
+  MULTIPART_PUSHEAGERLY = 2
+};
+
+/* Start a multi-part text value where we accumulate the data for processing at
+ * the end. */
+static void multipart_startaccum(upb_json_parser *p) {
+  assert_accumulate_empty(p);
+  assert(p->multipart_state == MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_ACCUMULATE;
+}
+
+/* Start a multi-part text value where we immediately push text data to a string
+ * value with the given selector. */
+static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
+  assert_accumulate_empty(p);
+  assert(p->multipart_state == MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_PUSHEAGERLY;
+  p->string_selector = sel;
+}
+
+static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
+                           bool can_alias) {
+  switch (p->multipart_state) {
+    case MULTIPART_INACTIVE:
+      upb_status_seterrmsg(
+          &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+
+    case MULTIPART_ACCUMULATE:
+      if (!accumulate_append(p, buf, len, can_alias)) {
+        return false;
+      }
+      break;
+
+    case MULTIPART_PUSHEAGERLY: {
+      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
+      upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
+      break;
+    }
+  }
+
+  return true;
+}
+
+/* Note: this invalidates the accumulate buffer!  Call only after reading its
+ * contents. */
+static void multipart_end(upb_json_parser *p) {
+  assert(p->multipart_state != MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_INACTIVE;
+  accumulate_clear(p);
+}
+
+
+/* Input capture **************************************************************/
+
+/* Functionality for capturing a region of the input as text.  Gracefully
+ * handles the case where a buffer seam occurs in the middle of the captured
+ * region. */
+
+static void capture_begin(upb_json_parser *p, const char *ptr) {
+  assert(p->multipart_state != MULTIPART_INACTIVE);
+  assert(p->capture == NULL);
+  p->capture = ptr;
+}
+
+static bool capture_end(upb_json_parser *p, const char *ptr) {
+  assert(p->capture);
+  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
+    p->capture = NULL;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* This is called at the end of each input buffer (ie. when we have hit a
+ * buffer seam).  If we are in the middle of capturing the input, this
+ * processes the unprocessed capture region. */
+static void capture_suspend(upb_json_parser *p, const char **ptr) {
+  if (!p->capture) return;
+
+  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
+    /* We use this as a signal that we were in the middle of capturing, and
+     * that capturing should resume at the beginning of the next buffer.
+     * 
+     * We can't use *ptr here, because we have no guarantee that this pointer
+     * will be valid when we resume (if the underlying memory is freed, then
+     * using the pointer at all, even to compare to NULL, is likely undefined
+     * behavior). */
+    p->capture = &suspend_capture;
+  } else {
+    /* Need to back up the pointer to the beginning of the capture, since
+     * we were not able to actually preserve it. */
+    *ptr = p->capture;
+  }
+}
+
+static void capture_resume(upb_json_parser *p, const char *ptr) {
+  if (p->capture) {
+    assert(p->capture == &suspend_capture);
+    p->capture = ptr;
+  }
+}
+
+
+/* Callbacks from the parser **************************************************/
+
+/* These are the functions called directly from the parser itself.
+ * We define these in the same order as their declarations in the parser. */
+
+static char escape_char(char in) {
+  switch (in) {
+    case 'r': return '\r';
+    case 't': return '\t';
+    case 'n': return '\n';
+    case 'f': return '\f';
+    case 'b': return '\b';
+    case '/': return '/';
+    case '"': return '"';
+    case '\\': return '\\';
+    default:
+      assert(0);
+      return 'x';
+  }
+}
+
+static bool escape(upb_json_parser *p, const char *ptr) {
+  char ch = escape_char(*ptr);
+  return multipart_text(p, &ch, 1, false);
+}
+
+static void start_hex(upb_json_parser *p) {
+  p->digit = 0;
+}
+
+static void hexdigit(upb_json_parser *p, const char *ptr) {
+  char ch = *ptr;
+
+  p->digit <<= 4;
+
+  if (ch >= '0' && ch <= '9') {
+    p->digit += (ch - '0');
+  } else if (ch >= 'a' && ch <= 'f') {
+    p->digit += ((ch - 'a') + 10);
+  } else {
+    assert(ch >= 'A' && ch <= 'F');
+    p->digit += ((ch - 'A') + 10);
+  }
+}
+
+static bool end_hex(upb_json_parser *p) {
+  uint32_t codepoint = p->digit;
+
+  /* emit the codepoint as UTF-8. */
+  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
+  int length = 0;
+  if (codepoint <= 0x7F) {
+    utf8[0] = codepoint;
+    length = 1;
+  } else if (codepoint <= 0x07FF) {
+    utf8[1] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[0] = (codepoint & 0x1F) | 0xC0;
+    length = 2;
+  } else /* codepoint <= 0xFFFF */ {
+    utf8[2] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[1] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[0] = (codepoint & 0x0F) | 0xE0;
+    length = 3;
+  }
+  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
+   * we have to wait for the next escape to get the full code point). */
+
+  return multipart_text(p, utf8, length, false);
+}
+
+static void start_text(upb_json_parser *p, const char *ptr) {
+  capture_begin(p, ptr);
+}
+
+static bool end_text(upb_json_parser *p, const char *ptr) {
+  return capture_end(p, ptr);
+}
+
+static void start_number(upb_json_parser *p, const char *ptr) {
+  multipart_startaccum(p);
+  capture_begin(p, ptr);
+}
+
+static bool parse_number(upb_json_parser *p);
+
+static bool end_number(upb_json_parser *p, const char *ptr) {
+  if (!capture_end(p, ptr)) {
+    return false;
+  }
+
+  return parse_number(p);
+}
+
+static bool parse_number(upb_json_parser *p) {
+  size_t len;
+  const char *buf;
+  const char *myend;
+  char *end;
+
+  /* strtol() and friends unfortunately do not support specifying the length of
+   * the input string, so we need to force a copy into a NULL-terminated buffer. */
+  if (!multipart_text(p, "\0", 1, false)) {
+    return false;
+  }
+
+  buf = accumulate_getptr(p, &len);
+  myend = buf + len - 1;  /* One for NULL. */
+
+  /* XXX: We are using strtol to parse integers, but this is wrong as even
+   * integers can be represented as 1e6 (for example), which strtol can't
+   * handle correctly.
+   *
+   * XXX: Also, we can't handle large integers properly because strto[u]ll
+   * isn't in C89.
+   *
+   * XXX: Also, we don't properly check floats for overflow, since strtof
+   * isn't in C89. */
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32: {
+      long val = strtol(p->accumulated, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      long long val = strtol(p->accumulated, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(p->accumulated, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      unsigned long long val = strtoul(p->accumulated, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(p->accumulated, &end);
+      if (errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      float val = strtod(p->accumulated, &end);
+      if (errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    default:
+      assert(false);
+  }
+
+  multipart_end(p);
+
+  return true;
+
+err:
+  upb_status_seterrf(&p->status, "error parsing number: %s", buf);
+  upb_env_reporterror(p->env, &p->status);
+  multipart_end(p);
+  return false;
+}
+
+static bool parser_putbool(upb_json_parser *p, bool val) {
+  bool ok;
+
+  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
+    upb_status_seterrf(&p->status,
+                       "Boolean value specified for non-bool field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+  UPB_ASSERT_VAR(ok, ok);
+
+  return true;
+}
+
+static bool start_stringval(upb_json_parser *p) {
+  assert(p->top->f);
+
+  if (upb_fielddef_isstring(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    if (!check_stack(p)) return false;
+
+    /* Start a new parser frame: parser frames correspond one-to-one with
+     * handler frames, and string events occur in a sub-frame. */
+    inner = p->top + 1;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+    upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+    inner->m = p->top->m;
+    inner->f = p->top->f;
+    inner->is_map = false;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
+      /* For STRING fields we push data directly to the handlers as it is
+       * parsed.  We don't do this yet for BYTES fields, because our base64
+       * decoder is not streaming.
+       *
+       * TODO(haberman): make base64 decoding streaming also. */
+      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
+      return true;
+    } else {
+      multipart_startaccum(p);
+      return true;
+    }
+  } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
+    /* No need to push a frame -- symbolic enum names in quotes remain in the
+     * current parser frame.
+     *
+     * Enum string values must accumulate so we can look up the value in a table
+     * once it is complete. */
+    multipart_startaccum(p);
+    return true;
+  } else {
+    upb_status_seterrf(&p->status,
+                       "String specified for non-string/non-enum field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+}
+
+static bool end_stringval(upb_json_parser *p) {
+  bool ok = true;
+
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_BYTES:
+      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
+                       p->accumulated, p->accumulated_len)) {
+        return false;
+      }
+      /* Fall through. */
+
+    case UPB_TYPE_STRING: {
+      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
+      upb_sink_endstr(&p->top->sink, sel);
+      p->top--;
+      break;
+    }
+
+    case UPB_TYPE_ENUM: {
+      /* Resolve enum symbolic name to integer value. */
+      const upb_enumdef *enumdef =
+          (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
+
+      size_t len;
+      const char *buf = accumulate_getptr(p, &len);
+
+      int32_t int_val = 0;
+      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
+
+      if (ok) {
+        upb_selector_t sel = parser_getsel(p);
+        upb_sink_putint32(&p->top->sink, sel, int_val);
+      } else {
+        upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
+        upb_env_reporterror(p->env, &p->status);
+      }
+
+      break;
+    }
+
+    default:
+      assert(false);
+      upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
+      upb_env_reporterror(p->env, &p->status);
+      ok = false;
+      break;
+  }
+
+  multipart_end(p);
+
+  return ok;
+}
+
+static void start_member(upb_json_parser *p) {
+  assert(!p->top->f);
+  multipart_startaccum(p);
+}
+
+/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
+ * field based on the current contents of the accumulate buffer. */
+static bool parse_mapentry_key(upb_json_parser *p) {
+
+  size_t len;
+  const char *buf = accumulate_getptr(p, &len);
+
+  /* Emit the key field. We do a bit of ad-hoc parsing here because the
+   * parser state machine has already decided that this is a string field
+   * name, and we are reinterpreting it as some arbitrary key type. In
+   * particular, integer and bool keys are quoted, so we need to parse the
+   * quoted string contents here. */
+
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(&p->status, "mapentry message has no key");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      /* Invoke end_number. The accum buffer has the number's text already. */
+      if (!parse_number(p)) {
+        return false;
+      }
+      break;
+    case UPB_TYPE_BOOL:
+      if (len == 4 && !strncmp(buf, "true", 4)) {
+        if (!parser_putbool(p, true)) {
+          return false;
+        }
+      } else if (len == 5 && !strncmp(buf, "false", 5)) {
+        if (!parser_putbool(p, false)) {
+          return false;
+        }
+      } else {
+        upb_status_seterrmsg(&p->status,
+                             "Map bool key not 'true' or 'false'");
+        upb_env_reporterror(p->env, &p->status);
+        return false;
+      }
+      multipart_end(p);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      upb_sink subsink;
+      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+      upb_sink_startstr(&p->top->sink, sel, len, &subsink);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
+      upb_sink_putstring(&subsink, sel, buf, len, NULL);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
+      upb_sink_endstr(&subsink, sel);
+      multipart_end(p);
+      break;
+    }
+    default:
+      upb_status_seterrmsg(&p->status, "Invalid field type for map key");
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+  }
+
+  return true;
+}
+
+/* Helper: emit one map entry (as a submessage in the map field sequence). This
+ * is invoked from end_membername(), at the end of the map entry's key string,
+ * with the map key in the accumulate buffer. It parses the key from that
+ * buffer, emits the handler calls to start the mapentry submessage (setting up
+ * its subframe in the process), and sets up state in the subframe so that the
+ * value parser (invoked next) will emit the mapentry's value field and then
+ * end the mapentry message. */
+
+static bool handle_mapentry(upb_json_parser *p) {
+  const upb_fielddef *mapfield;
+  const upb_msgdef *mapentrymsg;
+  upb_jsonparser_frame *inner;
+  upb_selector_t sel;
+
+  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
+   * for the mapentry itself, and then set |f| in that frame so that the map
+   * value field is parsed, and also set a flag to end the frame after the
+   * map-entry value is parsed. */
+  if (!check_stack(p)) return false;
+
+  mapfield = p->top->mapfield;
+  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
+
+  inner = p->top + 1;
+  p->top->f = mapfield;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+  upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+  inner->m = mapentrymsg;
+  inner->mapfield = mapfield;
+  inner->is_map = false;
+
+  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
+   * the key field value to the sink, and these handlers will pop the frame
+   * if they see is_mapentry (when invoked by the parser state machine, they
+   * would have just seen the map-entry value, not key). */
+  inner->is_mapentry = false;
+  p->top = inner;
+
+  /* send STARTMSG in submsg frame. */
+  upb_sink_startmsg(&p->top->sink);
+
+  parse_mapentry_key(p);
+
+  /* Set up the value field to receive the map-entry value. */
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
+  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
+  p->top->mapfield = mapfield;
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(&p->status, "mapentry message has no value");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  return true;
+}
+
+static bool end_membername(upb_json_parser *p) {
+  assert(!p->top->f);
+
+  if (p->top->is_map) {
+    return handle_mapentry(p);
+  } else {
+    size_t len;
+    const char *buf = accumulate_getptr(p, &len);
+    const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
+
+    if (!f) {
+      /* TODO(haberman): Ignore unknown fields if requested/configured to do
+       * so. */
+      upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+    }
+
+    p->top->f = f;
+    multipart_end(p);
+
+    return true;
+  }
+}
+
+static void end_member(upb_json_parser *p) {
+  /* If we just parsed a map-entry value, end that frame too. */
+  if (p->top->is_mapentry) {
+    upb_status s = UPB_STATUS_INIT;
+    upb_selector_t sel;
+    bool ok;
+    const upb_fielddef *mapfield;
+
+    assert(p->top > p->stack);
+    /* send ENDMSG on submsg. */
+    upb_sink_endmsg(&p->top->sink, &s);
+    mapfield = p->top->mapfield;
+
+    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
+    p->top--;
+    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
+    UPB_ASSERT_VAR(ok, ok);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
+
+  p->top->f = NULL;
+}
+
+static bool start_subobject(upb_json_parser *p) {
+  assert(p->top->f);
+
+  if (upb_fielddef_ismap(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    /* Beginning of a map. Start a new parser frame in a repeated-field
+     * context. */
+    if (!check_stack(p)) return false;
+
+    inner = p->top + 1;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+    upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    inner->mapfield = p->top->f;
+    inner->f = NULL;
+    inner->is_map = true;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else if (upb_fielddef_issubmsg(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    /* Beginning of a subobject. Start a new parser frame in the submsg
+     * context. */
+    if (!check_stack(p)) return false;
+
+    inner = p->top + 1;
+
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+    upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    inner->f = NULL;
+    inner->is_map = false;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else {
+    upb_status_seterrf(&p->status,
+                       "Object specified for non-message/group field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+}
+
+static void end_subobject(upb_json_parser *p) {
+  if (p->top->is_map) {
+    upb_selector_t sel;
+    p->top--;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+    upb_sink_endseq(&p->top->sink, sel);
+  } else {
+    upb_selector_t sel;
+    p->top--;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
+}
+
+static bool start_array(upb_json_parser *p) {
+  upb_jsonparser_frame *inner;
+  upb_selector_t sel;
+
+  assert(p->top->f);
+
+  if (!upb_fielddef_isseq(p->top->f)) {
+    upb_status_seterrf(&p->status,
+                       "Array specified for non-repeated field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  if (!check_stack(p)) return false;
+
+  inner = p->top + 1;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+  upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+  inner->m = p->top->m;
+  inner->f = p->top->f;
+  inner->is_map = false;
+  inner->is_mapentry = false;
+  p->top = inner;
+
+  return true;
+}
+
+static void end_array(upb_json_parser *p) {
+  upb_selector_t sel;
+
+  assert(p->top > p->stack);
+
+  p->top--;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+  upb_sink_endseq(&p->top->sink, sel);
+}
+
+static void start_object(upb_json_parser *p) {
+  if (!p->top->is_map) {
+    upb_sink_startmsg(&p->top->sink);
+  }
+}
+
+static void end_object(upb_json_parser *p) {
+  if (!p->top->is_map) {
+    upb_status status;
+    upb_status_clear(&status);
+    upb_sink_endmsg(&p->top->sink, &status);
+    if (!upb_ok(&status)) {
+      upb_env_reporterror(p->env, &status);
+    }
+  }
+}
+
+
+#define CHECK_RETURN_TOP(x) if (!(x)) goto error
+
+
+/* The actual parser **********************************************************/
+
+/* What follows is the Ragel parser itself.  The language is specified in Ragel
+ * and the actions call our C functions above.
+ *
+ * Ragel has an extensive set of functionality, and we use only a small part of
+ * it.  There are many action types but we only use a few:
+ *
+ *   ">" -- transition into a machine
+ *   "%" -- transition out of a machine
+ *   "@" -- transition into a final state of a machine.
+ *
+ * "@" transitions are tricky because a machine can transition into a final
+ * state repeatedly.  But in some cases we know this can't happen, for example
+ * a string which is delimited by a final '"' can only transition into its
+ * final state once, when the closing '"' is seen. */
+
+
+#line 1218 "upb/json/parser.rl"
+
+
+
+#line 1130 "upb/json/parser.c"
+static const char _json_actions[] = {
+	0, 1, 0, 1, 2, 1, 3, 1, 
+	5, 1, 6, 1, 7, 1, 8, 1, 
+	10, 1, 12, 1, 13, 1, 14, 1, 
+	15, 1, 16, 1, 17, 1, 21, 1, 
+	25, 1, 27, 2, 3, 8, 2, 4, 
+	5, 2, 6, 2, 2, 6, 8, 2, 
+	11, 9, 2, 13, 15, 2, 14, 15, 
+	2, 18, 1, 2, 19, 27, 2, 20, 
+	9, 2, 22, 27, 2, 23, 27, 2, 
+	24, 27, 2, 26, 27, 3, 14, 11, 
+	9
+};
+
+static const unsigned char _json_key_offsets[] = {
+	0, 0, 4, 9, 14, 15, 19, 24, 
+	29, 34, 38, 42, 45, 48, 50, 54, 
+	58, 60, 62, 67, 69, 71, 80, 86, 
+	92, 98, 104, 106, 115, 116, 116, 116, 
+	121, 126, 131, 132, 133, 134, 135, 135, 
+	136, 137, 138, 138, 139, 140, 141, 141, 
+	146, 151, 152, 156, 161, 166, 171, 175, 
+	175, 178, 178, 178
+};
+
+static const char _json_trans_keys[] = {
+	32, 123, 9, 13, 32, 34, 125, 9, 
+	13, 32, 34, 125, 9, 13, 34, 32, 
+	58, 9, 13, 32, 93, 125, 9, 13, 
+	32, 44, 125, 9, 13, 32, 44, 125, 
+	9, 13, 32, 34, 9, 13, 45, 48, 
+	49, 57, 48, 49, 57, 46, 69, 101, 
+	48, 57, 69, 101, 48, 57, 43, 45, 
+	48, 57, 48, 57, 48, 57, 46, 69, 
+	101, 48, 57, 34, 92, 34, 92, 34, 
+	47, 92, 98, 102, 110, 114, 116, 117, 
+	48, 57, 65, 70, 97, 102, 48, 57, 
+	65, 70, 97, 102, 48, 57, 65, 70, 
+	97, 102, 48, 57, 65, 70, 97, 102, 
+	34, 92, 34, 45, 91, 102, 110, 116, 
+	123, 48, 57, 34, 32, 93, 125, 9, 
+	13, 32, 44, 93, 9, 13, 32, 93, 
+	125, 9, 13, 97, 108, 115, 101, 117, 
+	108, 108, 114, 117, 101, 32, 34, 125, 
+	9, 13, 32, 34, 125, 9, 13, 34, 
+	32, 58, 9, 13, 32, 93, 125, 9, 
+	13, 32, 44, 125, 9, 13, 32, 44, 
+	125, 9, 13, 32, 34, 9, 13, 32, 
+	9, 13, 0
+};
+
+static const char _json_single_lengths[] = {
+	0, 2, 3, 3, 1, 2, 3, 3, 
+	3, 2, 2, 1, 3, 0, 2, 2, 
+	0, 0, 3, 2, 2, 9, 0, 0, 
+	0, 0, 2, 7, 1, 0, 0, 3, 
+	3, 3, 1, 1, 1, 1, 0, 1, 
+	1, 1, 0, 1, 1, 1, 0, 3, 
+	3, 1, 2, 3, 3, 3, 2, 0, 
+	1, 0, 0, 0
+};
+
+static const char _json_range_lengths[] = {
+	0, 1, 1, 1, 0, 1, 1, 1, 
+	1, 1, 1, 1, 0, 1, 1, 1, 
+	1, 1, 1, 0, 0, 0, 3, 3, 
+	3, 3, 0, 1, 0, 0, 0, 1, 
+	1, 1, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 1, 
+	1, 0, 1, 1, 1, 1, 1, 0, 
+	1, 0, 0, 0
+};
+
+static const short _json_index_offsets[] = {
+	0, 0, 4, 9, 14, 16, 20, 25, 
+	30, 35, 39, 43, 46, 50, 52, 56, 
+	60, 62, 64, 69, 72, 75, 85, 89, 
+	93, 97, 101, 104, 113, 115, 116, 117, 
+	122, 127, 132, 134, 136, 138, 140, 141, 
+	143, 145, 147, 148, 150, 152, 154, 155, 
+	160, 165, 167, 171, 176, 181, 186, 190, 
+	191, 194, 195, 196
+};
+
+static const char _json_indicies[] = {
+	0, 2, 0, 1, 3, 4, 5, 3, 
+	1, 6, 7, 8, 6, 1, 9, 1, 
+	10, 11, 10, 1, 11, 1, 1, 11, 
+	12, 13, 14, 15, 13, 1, 16, 17, 
+	8, 16, 1, 17, 7, 17, 1, 18, 
+	19, 20, 1, 19, 20, 1, 22, 23, 
+	23, 21, 24, 1, 23, 23, 24, 21, 
+	25, 25, 26, 1, 26, 1, 26, 21, 
+	22, 23, 23, 20, 21, 28, 29, 27, 
+	31, 32, 30, 33, 33, 33, 33, 33, 
+	33, 33, 33, 34, 1, 35, 35, 35, 
+	1, 36, 36, 36, 1, 37, 37, 37, 
+	1, 38, 38, 38, 1, 40, 41, 39, 
+	42, 43, 44, 45, 46, 47, 48, 43, 
+	1, 49, 1, 50, 51, 53, 54, 1, 
+	53, 52, 55, 56, 54, 55, 1, 56, 
+	1, 1, 56, 52, 57, 1, 58, 1, 
+	59, 1, 60, 1, 61, 62, 1, 63, 
+	1, 64, 1, 65, 66, 1, 67, 1, 
+	68, 1, 69, 70, 71, 72, 70, 1, 
+	73, 74, 75, 73, 1, 76, 1, 77, 
+	78, 77, 1, 78, 1, 1, 78, 79, 
+	80, 81, 82, 80, 1, 83, 84, 75, 
+	83, 1, 84, 74, 84, 1, 85, 86, 
+	86, 1, 1, 1, 1, 0
+};
+
+static const char _json_trans_targs[] = {
+	1, 0, 2, 3, 4, 56, 3, 4, 
+	56, 5, 5, 6, 7, 8, 9, 56, 
+	8, 9, 11, 12, 18, 57, 13, 15, 
+	14, 16, 17, 20, 58, 21, 20, 58, 
+	21, 19, 22, 23, 24, 25, 26, 20, 
+	58, 21, 28, 30, 31, 34, 39, 43, 
+	47, 29, 59, 59, 32, 31, 29, 32, 
+	33, 35, 36, 37, 38, 59, 40, 41, 
+	42, 59, 44, 45, 46, 59, 48, 49, 
+	55, 48, 49, 55, 50, 50, 51, 52, 
+	53, 54, 55, 53, 54, 59, 56
+};
+
+static const char _json_trans_actions[] = {
+	0, 0, 0, 21, 77, 53, 0, 47, 
+	23, 17, 0, 0, 15, 19, 19, 50, 
+	0, 0, 0, 0, 0, 1, 0, 0, 
+	0, 0, 0, 3, 13, 0, 0, 35, 
+	5, 11, 0, 38, 7, 7, 7, 41, 
+	44, 9, 62, 56, 25, 0, 0, 0, 
+	31, 29, 33, 59, 15, 0, 27, 0, 
+	0, 0, 0, 0, 0, 68, 0, 0, 
+	0, 71, 0, 0, 0, 65, 21, 77, 
+	53, 0, 47, 23, 17, 0, 0, 15, 
+	19, 19, 50, 0, 0, 74, 0
+};
+
+static const int json_start = 1;
+
+static const int json_en_number_machine = 10;
+static const int json_en_string_machine = 19;
+static const int json_en_value_machine = 27;
+static const int json_en_main = 1;
+
+
+#line 1221 "upb/json/parser.rl"
+
+size_t parse(void *closure, const void *hd, const char *buf, size_t size,
+             const upb_bufhandle *handle) {
+  upb_json_parser *parser = closure;
+
+  /* Variables used by Ragel's generated code. */
+  int cs = parser->current_state;
+  int *stack = parser->parser_stack;
+  int top = parser->parser_top;
+
+  const char *p = buf;
+  const char *pe = buf + size;
+
+  parser->handle = handle;
+
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  capture_resume(parser, buf);
+
+  
+#line 1301 "upb/json/parser.c"
+	{
+	int _klen;
+	unsigned int _trans;
+	const char *_acts;
+	unsigned int _nacts;
+	const char *_keys;
+
+	if ( p == pe )
+		goto _test_eof;
+	if ( cs == 0 )
+		goto _out;
+_resume:
+	_keys = _json_trans_keys + _json_key_offsets[cs];
+	_trans = _json_index_offsets[cs];
+
+	_klen = _json_single_lengths[cs];
+	if ( _klen > 0 ) {
+		const char *_lower = _keys;
+		const char *_mid;
+		const char *_upper = _keys + _klen - 1;
+		while (1) {
+			if ( _upper < _lower )
+				break;
+
+			_mid = _lower + ((_upper-_lower) >> 1);
+			if ( (*p) < *_mid )
+				_upper = _mid - 1;
+			else if ( (*p) > *_mid )
+				_lower = _mid + 1;
+			else {
+				_trans += (unsigned int)(_mid - _keys);
+				goto _match;
+			}
+		}
+		_keys += _klen;
+		_trans += _klen;
+	}
+
+	_klen = _json_range_lengths[cs];
+	if ( _klen > 0 ) {
+		const char *_lower = _keys;
+		const char *_mid;
+		const char *_upper = _keys + (_klen<<1) - 2;
+		while (1) {
+			if ( _upper < _lower )
+				break;
+
+			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
+			if ( (*p) < _mid[0] )
+				_upper = _mid - 2;
+			else if ( (*p) > _mid[1] )
+				_lower = _mid + 2;
+			else {
+				_trans += (unsigned int)((_mid - _keys)>>1);
+				goto _match;
+			}
+		}
+		_trans += _klen;
+	}
+
+_match:
+	_trans = _json_indicies[_trans];
+	cs = _json_trans_targs[_trans];
+
+	if ( _json_trans_actions[_trans] == 0 )
+		goto _again;
+
+	_acts = _json_actions + _json_trans_actions[_trans];
+	_nacts = (unsigned int) *_acts++;
+	while ( _nacts-- > 0 )
+	{
+		switch ( *_acts++ )
+		{
+	case 0:
+#line 1133 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+	case 1:
+#line 1134 "upb/json/parser.rl"
+	{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
+	break;
+	case 2:
+#line 1138 "upb/json/parser.rl"
+	{ start_text(parser, p); }
+	break;
+	case 3:
+#line 1139 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_text(parser, p)); }
+	break;
+	case 4:
+#line 1145 "upb/json/parser.rl"
+	{ start_hex(parser); }
+	break;
+	case 5:
+#line 1146 "upb/json/parser.rl"
+	{ hexdigit(parser, p); }
+	break;
+	case 6:
+#line 1147 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_hex(parser)); }
+	break;
+	case 7:
+#line 1153 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(escape(parser, p)); }
+	break;
+	case 8:
+#line 1159 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+	case 9:
+#line 1162 "upb/json/parser.rl"
+	{ {stack[top++] = cs; cs = 19; goto _again;} }
+	break;
+	case 10:
+#line 1164 "upb/json/parser.rl"
+	{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
+	break;
+	case 11:
+#line 1169 "upb/json/parser.rl"
+	{ start_member(parser); }
+	break;
+	case 12:
+#line 1170 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_membername(parser)); }
+	break;
+	case 13:
+#line 1173 "upb/json/parser.rl"
+	{ end_member(parser); }
+	break;
+	case 14:
+#line 1179 "upb/json/parser.rl"
+	{ start_object(parser); }
+	break;
+	case 15:
+#line 1182 "upb/json/parser.rl"
+	{ end_object(parser); }
+	break;
+	case 16:
+#line 1188 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_array(parser)); }
+	break;
+	case 17:
+#line 1192 "upb/json/parser.rl"
+	{ end_array(parser); }
+	break;
+	case 18:
+#line 1197 "upb/json/parser.rl"
+	{ start_number(parser, p); }
+	break;
+	case 19:
+#line 1198 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_number(parser, p)); }
+	break;
+	case 20:
+#line 1200 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_stringval(parser)); }
+	break;
+	case 21:
+#line 1201 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_stringval(parser)); }
+	break;
+	case 22:
+#line 1203 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
+	break;
+	case 23:
+#line 1205 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
+	break;
+	case 24:
+#line 1207 "upb/json/parser.rl"
+	{ /* null value */ }
+	break;
+	case 25:
+#line 1209 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_subobject(parser)); }
+	break;
+	case 26:
+#line 1210 "upb/json/parser.rl"
+	{ end_subobject(parser); }
+	break;
+	case 27:
+#line 1215 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+#line 1487 "upb/json/parser.c"
+		}
+	}
+
+_again:
+	if ( cs == 0 )
+		goto _out;
+	if ( ++p != pe )
+		goto _resume;
+	_test_eof: {}
+	_out: {}
+	}
+
+#line 1242 "upb/json/parser.rl"
+
+  if (p != pe) {
+    upb_status_seterrf(&parser->status, "Parse error at %s\n", p);
+    upb_env_reporterror(parser->env, &parser->status);
+  } else {
+    capture_suspend(parser, &p);
+  }
+
+error:
+  /* Save parsing state back to parser. */
+  parser->current_state = cs;
+  parser->parser_top = top;
+
+  return p - buf;
+}
+
+bool end(void *closure, const void *hd) {
+  UPB_UNUSED(closure);
+  UPB_UNUSED(hd);
+
+  /* Prevent compile warning on unused static constants. */
+  UPB_UNUSED(json_start);
+  UPB_UNUSED(json_en_number_machine);
+  UPB_UNUSED(json_en_string_machine);
+  UPB_UNUSED(json_en_value_machine);
+  UPB_UNUSED(json_en_main);
+  return true;
+}
+
+static void json_parser_reset(upb_json_parser *p) {
+  int cs;
+  int top;
+
+  p->top = p->stack;
+  p->top->f = NULL;
+  p->top->is_map = false;
+  p->top->is_mapentry = false;
+
+  /* Emit Ragel initialization of the parser. */
+  
+#line 1541 "upb/json/parser.c"
+	{
+	cs = json_start;
+	top = 0;
+	}
+
+#line 1282 "upb/json/parser.rl"
+  p->current_state = cs;
+  p->parser_top = top;
+  accumulate_clear(p);
+  p->multipart_state = MULTIPART_INACTIVE;
+  p->capture = NULL;
+  p->accumulated = NULL;
+  upb_status_clear(&p->status);
+}
+
+
+/* Public API *****************************************************************/
+
+upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
+#ifndef NDEBUG
+  const size_t size_before = upb_env_bytesallocated(env);
+#endif
+  upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
+  if (!p) return false;
+
+  p->env = env;
+  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
+  p->accumulate_buf = NULL;
+  p->accumulate_buf_size = 0;
+  upb_byteshandler_init(&p->input_handler_);
+  upb_byteshandler_setstring(&p->input_handler_, parse, NULL);
+  upb_byteshandler_setendstr(&p->input_handler_, end, NULL);
+  upb_bytessink_reset(&p->input_, &p->input_handler_, p);
+
+  json_parser_reset(p);
+  upb_sink_reset(&p->top->sink, output->handlers, output->closure);
+  p->top->m = upb_handlers_msgdef(output->handlers);
+
+  /* If this fails, uncomment and increase the value in parser.h. */
+  /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
+  assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
+  return p;
+}
+
+upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
+  return &p->input_;
+}
+/*
+** This currently uses snprintf() to format primitives, and could be optimized
+** further.
+*/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+struct upb_json_printer {
+  upb_sink input_;
+  /* BytesSink closure. */
+  void *subc_;
+  upb_bytessink *output_;
+
+  /* We track the depth so that we know when to emit startstr/endstr on the
+   * output. */
+  int depth_;
+
+  /* Have we emitted the first element? This state is necessary to emit commas
+   * without leaving a trailing comma in arrays/maps. We keep this state per
+   * frame depth.
+   *
+   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
+   * We count frames (contexts in which we separate elements by commas) as both
+   * repeated fields and messages (maps), and the worst case is a
+   * message->repeated field->submessage->repeated field->... nesting. */
+  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
+};
+
+/* StringPiece; a pointer plus a length. */
+typedef struct {
+  const char *ptr;
+  size_t len;
+} strpc;
+
+strpc *newstrpc(upb_handlers *h, const upb_fielddef *f) {
+  strpc *ret = malloc(sizeof(*ret));
+  ret->ptr = upb_fielddef_name(f);
+  ret->len = strlen(ret->ptr);
+  upb_handlers_addcleanup(h, ret, free);
+  return ret;
+}
+
+/* ------------ JSON string printing: values, maps, arrays ------------------ */
+
+static void print_data(
+    upb_json_printer *p, const char *buf, unsigned int len) {
+  /* TODO: Will need to change if we support pushback from the sink. */
+  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
+  UPB_ASSERT_VAR(n, n == len);
+}
+
+static void print_comma(upb_json_printer *p) {
+  if (!p->first_elem_[p->depth_]) {
+    print_data(p, ",", 1);
+  }
+  p->first_elem_[p->depth_] = false;
+}
+
+/* Helpers that print properly formatted elements to the JSON output stream. */
+
+/* Used for escaping control chars in strings. */
+static const char kControlCharLimit = 0x20;
+
+UPB_INLINE bool is_json_escaped(char c) {
+  /* See RFC 4627. */
+  unsigned char uc = (unsigned char)c;
+  return uc < kControlCharLimit || uc == '"' || uc == '\\';
+}
+
+UPB_INLINE char* json_nice_escape(char c) {
+  switch (c) {
+    case '"':  return "\\\"";
+    case '\\': return "\\\\";
+    case '\b': return "\\b";
+    case '\f': return "\\f";
+    case '\n': return "\\n";
+    case '\r': return "\\r";
+    case '\t': return "\\t";
+    default:   return NULL;
+  }
+}
+
+/* Write a properly escaped string chunk. The surrounding quotes are *not*
+ * printed; this is so that the caller has the option of emitting the string
+ * content in chunks. */
+static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
+  const char* unescaped_run = NULL;
+  unsigned int i;
+  for (i = 0; i < len; i++) {
+    char c = buf[i];
+    /* Handle escaping. */
+    if (is_json_escaped(c)) {
+      /* Use a "nice" escape, like \n, if one exists for this character. */
+      const char* escape = json_nice_escape(c);
+      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
+       * escape. */
+      char escape_buf[8];
+      if (!escape) {
+        unsigned char byte = (unsigned char)c;
+        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
+        escape = escape_buf;
+      }
+
+      /* N.B. that we assume that the input encoding is equal to the output
+       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
+       * can simply pass the bytes through. */
+
+      /* If there's a current run of unescaped chars, print that run first. */
+      if (unescaped_run) {
+        print_data(p, unescaped_run, &buf[i] - unescaped_run);
+        unescaped_run = NULL;
+      }
+      /* Then print the escape code. */
+      print_data(p, escape, strlen(escape));
+    } else {
+      /* Add to the current unescaped run of characters. */
+      if (unescaped_run == NULL) {
+        unescaped_run = &buf[i];
+      }
+    }
+  }
+
+  /* If the string ended in a run of unescaped characters, print that last run. */
+  if (unescaped_run) {
+    print_data(p, unescaped_run, &buf[len] - unescaped_run);
+  }
+}
+
+#define CHKLENGTH(x) if (!(x)) return -1;
+
+/* Helpers that format floating point values according to our custom formats.
+ * Right now we use %.8g and %.17g for float/double, respectively, to match
+ * proto2::util::JsonFormat's defaults.  May want to change this later. */
+
+static size_t fmt_double(double val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%.17g", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_float(float val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%.8g", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_bool(bool val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_int64(long val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%ld", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%llu", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+/* Print a map key given a field name. Called by scalar field handlers and by
+ * startseq for repeated fields. */
+static bool putkey(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  const strpc *key = handler_data;
+  print_comma(p);
+  print_data(p, "\"", 1);
+  putstring(p, key->ptr, key->len);
+  print_data(p, "\":", 2);
+  return true;
+}
+
+#define CHKFMT(val) if ((val) == (size_t)-1) return false;
+#define CHK(val)    if (!(val)) return false;
+
+#define TYPE_HANDLERS(type, fmt_func)                                        \
+  static bool put##type(void *closure, const void *handler_data, type val) { \
+    upb_json_printer *p = closure;                                           \
+    char data[64];                                                           \
+    size_t length = fmt_func(val, data, sizeof(data));                       \
+    UPB_UNUSED(handler_data);                                                \
+    CHKFMT(length);                                                          \
+    print_data(p, data, length);                                             \
+    return true;                                                             \
+  }                                                                          \
+  static bool scalar_##type(void *closure, const void *handler_data,         \
+                            type val) {                                      \
+    CHK(putkey(closure, handler_data));                                      \
+    CHK(put##type(closure, handler_data, val));                              \
+    return true;                                                             \
+  }                                                                          \
+  static bool repeated_##type(void *closure, const void *handler_data,       \
+                              type val) {                                    \
+    upb_json_printer *p = closure;                                           \
+    print_comma(p);                                                          \
+    CHK(put##type(closure, handler_data, val));                              \
+    return true;                                                             \
+  }
+
+#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
+  static bool putmapkey_##type(void *closure, const void *handler_data,      \
+                            type val) {                                      \
+    upb_json_printer *p = closure;                                           \
+    print_data(p, "\"", 1);                                                  \
+    CHK(put##type(closure, handler_data, val));                              \
+    print_data(p, "\":", 2);                                                 \
+    return true;                                                             \
+  }
+
+TYPE_HANDLERS(double,   fmt_double)
+TYPE_HANDLERS(float,    fmt_float)
+TYPE_HANDLERS(bool,     fmt_bool)
+TYPE_HANDLERS(int32_t,  fmt_int64)
+TYPE_HANDLERS(uint32_t, fmt_int64)
+TYPE_HANDLERS(int64_t,  fmt_int64)
+TYPE_HANDLERS(uint64_t, fmt_uint64)
+
+/* double and float are not allowed to be map keys. */
+TYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
+TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64)
+TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64)
+
+#undef TYPE_HANDLERS
+#undef TYPE_HANDLERS_MAPKEY
+
+typedef struct {
+  void *keyname;
+  const upb_enumdef *enumdef;
+} EnumHandlerData;
+
+static bool scalar_enum(void *closure, const void *handler_data,
+                        int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+  const char *symbolic_name;
+
+  CHK(putkey(closure, hd->keyname));
+
+  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
+  if (symbolic_name) {
+    print_data(p, "\"", 1);
+    putstring(p, symbolic_name, strlen(symbolic_name));
+    print_data(p, "\"", 1);
+  } else {
+    putint32_t(closure, NULL, val);
+  }
+
+  return true;
+}
+
+static void print_enum_symbolic_name(upb_json_printer *p,
+                                     const upb_enumdef *def,
+                                     int32_t val) {
+  const char *symbolic_name = upb_enumdef_iton(def, val);
+  if (symbolic_name) {
+    print_data(p, "\"", 1);
+    putstring(p, symbolic_name, strlen(symbolic_name));
+    print_data(p, "\"", 1);
+  } else {
+    putint32_t(p, NULL, val);
+  }
+}
+
+static bool repeated_enum(void *closure, const void *handler_data,
+                          int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+  print_comma(p);
+
+  print_enum_symbolic_name(p, hd->enumdef, val);
+
+  return true;
+}
+
+static bool mapvalue_enum(void *closure, const void *handler_data,
+                          int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+
+  print_enum_symbolic_name(p, hd->enumdef, val);
+
+  return true;
+}
+
+static void *scalar_startsubmsg(void *closure, const void *handler_data) {
+  return putkey(closure, handler_data) ? closure : UPB_BREAK;
+}
+
+static void *repeated_startsubmsg(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_comma(p);
+  return closure;
+}
+
+static void start_frame(upb_json_printer *p) {
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "{", 1);
+}
+
+static void end_frame(upb_json_printer *p) {
+  print_data(p, "}", 1);
+  p->depth_--;
+}
+
+static bool printer_startmsg(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  if (p->depth_ == 0) {
+    upb_bytessink_start(p->output_, 0, &p->subc_);
+  }
+  start_frame(p);
+  return true;
+}
+
+static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(s);
+  end_frame(p);
+  if (p->depth_ == 0) {
+    upb_bytessink_end(p->output_);
+  }
+  return true;
+}
+
+static void *startseq(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  CHK(putkey(closure, handler_data));
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "[", 1);
+  return closure;
+}
+
+static bool endseq(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "]", 1);
+  p->depth_--;
+  return true;
+}
+
+static void *startmap(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  CHK(putkey(closure, handler_data));
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "{", 1);
+  return closure;
+}
+
+static bool endmap(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "}", 1);
+  p->depth_--;
+  return true;
+}
+
+static size_t putstr(void *closure, const void *handler_data, const char *str,
+                     size_t len, const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(handle);
+  putstring(p, str, len);
+  return len;
+}
+
+/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
+static size_t putbytes(void *closure, const void *handler_data, const char *str,
+                       size_t len, const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+
+  /* This is the regular base64, not the "web-safe" version. */
+  static const char base64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  /* Base64-encode. */
+  char data[16000];
+  const char *limit = data + sizeof(data);
+  const unsigned char *from = (const unsigned char*)str;
+  char *to = data;
+  size_t remaining = len;
+  size_t bytes;
+
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(handle);
+
+  while (remaining > 2) {
+    /* TODO(haberman): handle encoded lengths > sizeof(data) */
+    UPB_ASSERT_VAR(limit, (limit - to) >= 4);
+
+    to[0] = base64[from[0] >> 2];
+    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
+    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
+    to[3] = base64[from[2] & 0x3f];
+
+    remaining -= 3;
+    to += 4;
+    from += 3;
+  }
+
+  switch (remaining) {
+    case 2:
+      to[0] = base64[from[0] >> 2];
+      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
+      to[2] = base64[(from[1] & 0xf) << 2];
+      to[3] = '=';
+      to += 4;
+      from += 2;
+      break;
+    case 1:
+      to[0] = base64[from[0] >> 2];
+      to[1] = base64[((from[0] & 0x3) << 4)];
+      to[2] = '=';
+      to[3] = '=';
+      to += 4;
+      from += 1;
+      break;
+  }
+
+  bytes = to - data;
+  print_data(p, "\"", 1);
+  putstring(p, data, bytes);
+  print_data(p, "\"", 1);
+  return len;
+}
+
+static void *scalar_startstr(void *closure, const void *handler_data,
+                             size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  CHK(putkey(closure, handler_data));
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t scalar_str(void *closure, const void *handler_data,
+                         const char *str, size_t len,
+                         const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool scalar_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static void *repeated_startstr(void *closure, const void *handler_data,
+                               size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  print_comma(p);
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t repeated_str(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool repeated_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static void *mapkeyval_startstr(void *closure, const void *handler_data,
+                                size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t mapkey_str(void *closure, const void *handler_data,
+                         const char *str, size_t len,
+                         const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool mapkey_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\":", 2);
+  return true;
+}
+
+static bool mapvalue_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static size_t scalar_bytes(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  CHK(putkey(closure, handler_data));
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static size_t repeated_bytes(void *closure, const void *handler_data,
+                             const char *str, size_t len,
+                             const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  print_comma(p);
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static size_t mapkey_bytes(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  print_data(p, ":", 1);
+  return len;
+}
+
+static void set_enum_hd(upb_handlers *h,
+                        const upb_fielddef *f,
+                        upb_handlerattr *attr) {
+  EnumHandlerData *hd = malloc(sizeof(EnumHandlerData));
+  hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
+  hd->keyname = newstrpc(h, f);
+  upb_handlers_addcleanup(h, hd, free);
+  upb_handlerattr_sethandlerdata(attr, hd);
+}
+
+/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
+ * in a map).
+ *
+ * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
+ * key or value cases properly. The right way to do this is to allocate a
+ * temporary structure at the start of a mapentry submessage, store key and
+ * value data in it as key and value handlers are called, and then print the
+ * key/value pair once at the end of the submessage. If we don't do this, we
+ * should at least detect the case and throw an error. However, so far all of
+ * our sources that emit mapentry messages do so canonically (with one key
+ * field, and then one value field), so this is not a pressing concern at the
+ * moment. */
+void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+
+  /* A mapentry message is printed simply as '"key": value'. Rather than
+   * special-case key and value for every type below, we just handle both
+   * fields explicitly here. */
+  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
+  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
+
+  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+
+  UPB_UNUSED(closure);
+
+  switch (upb_fielddef_type(key_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
+      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
+      break;
+    default:
+      assert(false);
+      break;
+  }
+
+  switch (upb_fielddef_type(value_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
+      break;
+    case UPB_TYPE_FLOAT:
+      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
+      break;
+    case UPB_TYPE_DOUBLE:
+      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
+      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
+      break;
+    case UPB_TYPE_ENUM: {
+      upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+      set_enum_hd(h, value_field, &enum_attr);
+      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
+      upb_handlerattr_uninit(&enum_attr);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      /* No handler necessary -- the submsg handlers will print the message
+       * as appropriate. */
+      break;
+  }
+
+  upb_handlerattr_uninit(&empty_attr);
+}
+
+void printer_sethandlers(const void *closure, upb_handlers *h) {
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+  bool is_mapentry = upb_msgdef_mapentry(md);
+  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+  upb_msg_field_iter i;
+
+  UPB_UNUSED(closure);
+
+  if (is_mapentry) {
+    /* mapentry messages are sufficiently different that we handle them
+     * separately. */
+    printer_sethandlers_mapentry(closure, h);
+    return;
+  }
+
+  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
+  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
+
+#define TYPE(type, name, ctype)                                               \
+  case type:                                                                  \
+    if (upb_fielddef_isseq(f)) {                                              \
+      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
+    } else {                                                                  \
+      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
+    }                                                                         \
+    break;
+
+  upb_msg_field_begin(&i, md);
+  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+
+    upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
+    upb_handlerattr_sethandlerdata(&name_attr, newstrpc(h, f));
+
+    if (upb_fielddef_ismap(f)) {
+      upb_handlers_setstartseq(h, f, startmap, &name_attr);
+      upb_handlers_setendseq(h, f, endmap, &name_attr);
+    } else if (upb_fielddef_isseq(f)) {
+      upb_handlers_setstartseq(h, f, startseq, &name_attr);
+      upb_handlers_setendseq(h, f, endseq, &empty_attr);
+    }
+
+    switch (upb_fielddef_type(f)) {
+      TYPE(UPB_TYPE_FLOAT,  float,  float);
+      TYPE(UPB_TYPE_DOUBLE, double, double);
+      TYPE(UPB_TYPE_BOOL,   bool,   bool);
+      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
+      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
+      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
+      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
+      case UPB_TYPE_ENUM: {
+        /* For now, we always emit symbolic names for enums. We may want an
+         * option later to control this behavior, but we will wait for a real
+         * need first. */
+        upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+        set_enum_hd(h, f, &enum_attr);
+
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
+        } else {
+          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
+        }
+
+        upb_handlerattr_uninit(&enum_attr);
+        break;
+      }
+      case UPB_TYPE_STRING:
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
+          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
+          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
+        } else {
+          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
+          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
+          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
+        }
+        break;
+      case UPB_TYPE_BYTES:
+        /* XXX: this doesn't support strings that span buffers yet. The base64
+         * encoder will need to be made resumable for this to work properly. */
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
+        } else {
+          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
+        }
+        break;
+      case UPB_TYPE_MESSAGE:
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
+        } else {
+          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
+        }
+        break;
+    }
+
+    upb_handlerattr_uninit(&name_attr);
+  }
+
+  upb_handlerattr_uninit(&empty_attr);
+#undef TYPE
+}
+
+static void json_printer_reset(upb_json_printer *p) {
+  p->depth_ = 0;
+}
+
+
+/* Public API *****************************************************************/
+
+upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
+                                          upb_bytessink *output) {
+#ifndef NDEBUG
+  size_t size_before = upb_env_bytesallocated(e);
+#endif
+
+  upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
+  if (!p) return NULL;
+
+  p->output_ = output;
+  json_printer_reset(p);
+  upb_sink_reset(&p->input_, h, p);
+
+  /* If this fails, increase the value in printer.h. */
+  assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
+  return p;
+}
+
+upb_sink *upb_json_printer_input(upb_json_printer *p) {
+  return &p->input_;
+}
+
+const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+                                                 const void *owner) {
+  return upb_handlers_newfrozen(md, owner, printer_sethandlers, NULL);
+}
diff --git a/src/third_party/protobuf-3/php/ext/google/protobuf/upb.h b/src/third_party/protobuf-3/php/ext/google/protobuf/upb.h
new file mode 100644
index 0000000..078e2a2
--- /dev/null
+++ b/src/third_party/protobuf-3/php/ext/google/protobuf/upb.h
@@ -0,0 +1,8217 @@
+// Amalgamated source file
+/*
+** Defs are upb's internal representation of the constructs that can appear
+** in a .proto file:
+**
+** - upb::MessageDef (upb_msgdef): describes a "message" construct.
+** - upb::FieldDef (upb_fielddef): describes a message field.
+** - upb::EnumDef (upb_enumdef): describes an enum.
+** - upb::OneofDef (upb_oneofdef): describes a oneof.
+** - upb::Def (upb_def): base class of all the others.
+**
+** TODO: definitions of services.
+**
+** Like upb_refcounted objects, defs are mutable only until frozen, and are
+** only thread-safe once frozen.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+/*
+** upb::RefCounted (upb_refcounted)
+**
+** A refcounting scheme that supports circular refs.  It accomplishes this by
+** partitioning the set of objects into groups such that no cycle spans groups;
+** we can then reference-count the group as a whole and ignore refs within the
+** group.  When objects are mutable, these groups are computed very
+** conservatively; we group any objects that have ever had a link between them.
+** When objects are frozen, we compute strongly-connected components which
+** allows us to be precise and only group objects that are actually cyclic.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_REFCOUNTED_H_
+#define UPB_REFCOUNTED_H_
+
+/*
+** upb_table
+**
+** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
+** This file defines very fast int->upb_value (inttable) and string->upb_value
+** (strtable) hash tables.
+**
+** The table uses chained scatter with Brent's variation (inspired by the Lua
+** implementation of hash tables).  The hash function for strings is Austin
+** Appleby's "MurmurHash."
+**
+** The inttable uses uintptr_t as its key, which guarantees it can be used to
+** store pointers or integers of at least 32 bits (upb isn't really useful on
+** systems where sizeof(void*) < 4).
+**
+** The table must be homogenous (all values of the same type).  In debug
+** mode, we check this on insert and lookup.
+*/
+
+#ifndef UPB_TABLE_H_
+#define UPB_TABLE_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+/*
+** This file contains shared definitions that are widely used across upb.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_H_
+#define UPB_H_
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
+ * doesn't provide these preprocessor symbols. */
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define UPB_BIG_ENDIAN
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#endif
+
+/* A few hacky workarounds for functions not in C89.
+ * For internal use only!
+ * TODO(haberman): fix these by including our own implementations, or finding
+ * another workaround.
+ */
+#ifdef __GNUC__
+#define _upb_snprintf __builtin_snprintf
+#define _upb_vsnprintf __builtin_vsnprintf
+#define _upb_va_copy(a, b) __va_copy(a, b)
+#elif __STDC_VERSION__ >= 199901L
+/* C99 versions. */
+#define _upb_snprintf snprintf
+#define _upb_vsnprintf vsnprintf
+#define _upb_va_copy(a, b) va_copy(a, b)
+#else
+#error Need implementations of [v]snprintf and va_copy
+#endif
+
+
+#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \
+      defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11)
+#define UPB_CXX11
+#endif
+
+/* UPB_DISALLOW_COPY_AND_ASSIGN()
+ * UPB_DISALLOW_POD_OPS()
+ *
+ * Declare these in the "private" section of a C++ class to forbid copy/assign
+ * or all POD ops (construct, destruct, copy, assign) on that class. */
+#ifdef UPB_CXX11
+#include <type_traits>
+#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
+  class_name(const class_name&) = delete; \
+  void operator=(const class_name&) = delete;
+#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \
+  class_name() = delete; \
+  ~class_name() = delete; \
+  UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
+#define UPB_ASSERT_STDLAYOUT(type) \
+  static_assert(std::is_standard_layout<type>::value, \
+                #type " must be standard layout");
+#else  /* !defined(UPB_CXX11) */
+#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
+  class_name(const class_name&); \
+  void operator=(const class_name&);
+#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \
+  class_name(); \
+  ~class_name(); \
+  UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
+#define UPB_ASSERT_STDLAYOUT(type)
+#endif
+
+/* UPB_DECLARE_TYPE()
+ * UPB_DECLARE_DERIVED_TYPE()
+ * UPB_DECLARE_DERIVED_TYPE2()
+ *
+ * Macros for declaring C and C++ types both, including inheritance.
+ * The inheritance doesn't use real C++ inheritance, to stay compatible with C.
+ *
+ * These macros also provide upcasts:
+ *  - in C: types-specific functions (ie. upb_foo_upcast(foo))
+ *  - in C++: upb::upcast(foo) along with implicit conversions
+ *
+ * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */
+
+#define UPB_C_UPCASTS(ty, base)                                      \
+  UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \
+  UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; }
+
+#define UPB_C_UPCASTS2(ty, base, base2)                                 \
+  UPB_C_UPCASTS(ty, base)                                               \
+  UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \
+  UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; }
+
+#ifdef __cplusplus
+
+#define UPB_BEGIN_EXTERN_C extern "C" {
+#define UPB_END_EXTERN_C }
+#define UPB_PRIVATE_FOR_CPP private:
+#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname;
+
+#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase)  \
+  UPB_DECLARE_TYPE(cppname, cname)                                \
+  UPB_C_UPCASTS(cname, cbase)                                     \
+  namespace upb {                                                 \
+  template <>                                                     \
+  class Pointer<cppname> : public PointerBase<cppname, cppbase> { \
+   public:                                                        \
+    explicit Pointer(cppname* ptr) : PointerBase(ptr) {}          \
+  };                                                              \
+  template <>                                                     \
+  class Pointer<const cppname>                                    \
+      : public PointerBase<const cppname, const cppbase> {        \
+   public:                                                        \
+    explicit Pointer(const cppname* ptr) : PointerBase(ptr) {}    \
+  };                                                              \
+  }
+
+#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase,  \
+                                  cbase2)                                    \
+  UPB_DECLARE_TYPE(cppname, cname)                                           \
+  UPB_C_UPCASTS2(cname, cbase, cbase2)                                       \
+  namespace upb {                                                            \
+  template <>                                                                \
+  class Pointer<cppname> : public PointerBase2<cppname, cppbase, cppbase2> { \
+   public:                                                                   \
+    explicit Pointer(cppname* ptr) : PointerBase2(ptr) {}                    \
+  };                                                                         \
+  template <>                                                                \
+  class Pointer<const cppname>                                               \
+      : public PointerBase2<const cppname, const cppbase, const cppbase2> {  \
+   public:                                                                   \
+    explicit Pointer(const cppname* ptr) : PointerBase2(ptr) {}              \
+  };                                                                         \
+  }
+
+#else  /* !defined(__cplusplus) */
+
+#define UPB_BEGIN_EXTERN_C
+#define UPB_END_EXTERN_C
+#define UPB_PRIVATE_FOR_CPP
+#define UPB_DECLARE_TYPE(cppname, cname) \
+  struct cname;                          \
+  typedef struct cname cname;
+#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \
+  UPB_DECLARE_TYPE(cppname, cname)                               \
+  UPB_C_UPCASTS(cname, cbase)
+#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2,    \
+                                  cname, cbase, cbase2)          \
+  UPB_DECLARE_TYPE(cppname, cname)                               \
+  UPB_C_UPCASTS2(cname, cbase, cbase2)
+
+#endif  /* defined(__cplusplus) */
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* For asserting something about a variable when the variable is not used for
+ * anything else.  This prevents "unused variable" warnings when compiling in
+ * debug mode. */
+#define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate)
+
+/* Generic function type. */
+typedef void upb_func();
+
+/* C++ Casts ******************************************************************/
+
+#ifdef __cplusplus
+
+namespace upb {
+
+template <class T> class Pointer;
+
+/* Casts to a subclass.  The caller must know that cast is correct; an
+ * incorrect cast will throw an assertion failure in debug mode.
+ *
+ * Example:
+ *   upb::Def* def = GetDef();
+ *   // Assert-fails if this was not actually a MessageDef.
+ *   upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def);
+ *
+ * Note that downcasts are only defined for some types (at the moment you can
+ * only downcast from a upb::Def to a specific Def type). */
+template<class To, class From> To down_cast(From* f);
+
+/* Casts to a subclass.  If the class does not actually match the given To type,
+ * returns NULL.
+ *
+ * Example:
+ *   upb::Def* def = GetDef();
+ *   // md will be NULL if this was not actually a MessageDef.
+ *   upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def);
+ *
+ * Note that dynamic casts are only defined for some types (at the moment you
+ * can only downcast from a upb::Def to a specific Def type).. */
+template<class To, class From> To dyn_cast(From* f);
+
+/* Casts to any base class, or the type itself (ie. can be a no-op).
+ *
+ * Example:
+ *   upb::MessageDef* md = GetDef();
+ *   // This will fail to compile if this wasn't actually a base class.
+ *   upb::Def* def = upb::upcast(md);
+ */
+template <class T> inline Pointer<T> upcast(T *f) { return Pointer<T>(f); }
+
+/* Attempt upcast to specific base class.
+ *
+ * Example:
+ *   upb::MessageDef* md = GetDef();
+ *   upb::upcast_to<upb::Def>(md)->MethodOnDef();
+ */
+template <class T, class F> inline T* upcast_to(F *f) {
+  return static_cast<T*>(upcast(f));
+}
+
+/* PointerBase<T>: implementation detail of upb::upcast().
+ * It is implicitly convertable to pointers to the Base class(es).
+ */
+template <class T, class Base>
+class PointerBase {
+ public:
+  explicit PointerBase(T* ptr) : ptr_(ptr) {}
+  operator T*() { return ptr_; }
+  operator Base*() { return (Base*)ptr_; }
+
+ private:
+  T* ptr_;
+};
+
+template <class T, class Base, class Base2>
+class PointerBase2 : public PointerBase<T, Base> {
+ public:
+  explicit PointerBase2(T* ptr) : PointerBase<T, Base>(ptr) {}
+  operator Base2*() { return Pointer<Base>(*this); }
+};
+
+}
+
+#endif
+
+
+/* upb::reffed_ptr ************************************************************/
+
+#ifdef __cplusplus
+
+#include <algorithm>  /* For std::swap(). */
+
+namespace upb {
+
+/* Provides RAII semantics for upb refcounted objects.  Each reffed_ptr owns a
+ * ref on whatever object it points to (if any). */
+template <class T> class reffed_ptr {
+ public:
+  reffed_ptr() : ptr_(NULL) {}
+
+  /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+  template <class U>
+  reffed_ptr(U* val, const void* ref_donor = NULL)
+      : ptr_(upb::upcast(val)) {
+    if (ref_donor) {
+      assert(ptr_);
+      ptr_->DonateRef(ref_donor, this);
+    } else if (ptr_) {
+      ptr_->Ref(this);
+    }
+  }
+
+  template <class U>
+  reffed_ptr(const reffed_ptr<U>& other)
+      : ptr_(upb::upcast(other.get())) {
+    if (ptr_) ptr_->Ref(this);
+  }
+
+  ~reffed_ptr() { if (ptr_) ptr_->Unref(this); }
+
+  template <class U>
+  reffed_ptr& operator=(const reffed_ptr<U>& other) {
+    reset(other.get());
+    return *this;
+  }
+
+  reffed_ptr& operator=(const reffed_ptr& other) {
+    reset(other.get());
+    return *this;
+  }
+
+  /* TODO(haberman): add C++11 move construction/assignment for greater
+   * efficiency. */
+
+  void swap(reffed_ptr& other) {
+    if (ptr_ == other.ptr_) {
+      return;
+    }
+
+    if (ptr_) ptr_->DonateRef(this, &other);
+    if (other.ptr_) other.ptr_->DonateRef(&other, this);
+    std::swap(ptr_, other.ptr_);
+  }
+
+  T& operator*() const {
+    assert(ptr_);
+    return *ptr_;
+  }
+
+  T* operator->() const {
+    assert(ptr_);
+    return ptr_;
+  }
+
+  T* get() const { return ptr_; }
+
+  /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+  template <class U>
+  void reset(U* ptr = NULL, const void* ref_donor = NULL) {
+    reffed_ptr(ptr, ref_donor).swap(*this);
+  }
+
+  template <class U>
+  reffed_ptr<U> down_cast() {
+    return reffed_ptr<U>(upb::down_cast<U*>(get()));
+  }
+
+  template <class U>
+  reffed_ptr<U> dyn_cast() {
+    return reffed_ptr<U>(upb::dyn_cast<U*>(get()));
+  }
+
+  /* Plain release() is unsafe; if we were the only owner, it would leak the
+   * object.  Instead we provide this: */
+  T* ReleaseTo(const void* new_owner) {
+    T* ret = NULL;
+    ptr_->DonateRef(this, new_owner);
+    std::swap(ret, ptr_);
+    return ret;
+  }
+
+ private:
+  T* ptr_;
+};
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+
+/* upb::Status ****************************************************************/
+
+#ifdef __cplusplus
+namespace upb {
+class ErrorSpace;
+class Status;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace)
+UPB_DECLARE_TYPE(upb::Status, upb_status)
+
+/* The maximum length of an error message before it will get truncated. */
+#define UPB_STATUS_MAX_MESSAGE 128
+
+/* An error callback function is used to report errors from some component.
+ * The function can return "true" to indicate that the component should try
+ * to recover and proceed, but this is not always possible. */
+typedef bool upb_errcb_t(void *closure, const upb_status* status);
+
+#ifdef __cplusplus
+class upb::ErrorSpace {
+#else
+struct upb_errorspace {
+#endif
+  const char *name;
+  /* Should the error message in the status object according to this code. */
+  void (*set_message)(upb_status* status, int code);
+};
+
+#ifdef __cplusplus
+
+/* Object representing a success or failure status.
+ * It owns no resources and allocates no memory, so it should work
+ * even in OOM situations. */
+
+class upb::Status {
+ public:
+  Status();
+
+  /* Returns true if there is no error. */
+  bool ok() const;
+
+  /* Optional error space and code, useful if the caller wants to
+   * programmatically check the specific kind of error. */
+  ErrorSpace* error_space();
+  int code() const;
+
+  const char *error_message() const;
+
+  /* The error message will be truncated if it is longer than
+   * UPB_STATUS_MAX_MESSAGE-4. */
+  void SetErrorMessage(const char* msg);
+  void SetFormattedErrorMessage(const char* fmt, ...);
+
+  /* If there is no error message already, this will use the ErrorSpace to
+   * populate the error message for this code.  The caller can still call
+   * SetErrorMessage() to give a more specific message. */
+  void SetErrorCode(ErrorSpace* space, int code);
+
+  /* Resets the status to a successful state with no message. */
+  void Clear();
+
+  void CopyFrom(const Status& other);
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Status)
+#else
+struct upb_status {
+#endif
+  bool ok_;
+
+  /* Specific status code defined by some error space (optional). */
+  int code_;
+  upb_errorspace *error_space_;
+
+  /* Error message; NULL-terminated. */
+  char msg[UPB_STATUS_MAX_MESSAGE];
+};
+
+#define UPB_STATUS_INIT {true, 0, NULL, {0}}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The returned string is invalidated by any other call into the status. */
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+upb_errorspace *upb_status_errspace(const upb_status *status);
+int upb_status_errcode(const upb_status *status);
+
+/* Any of the functions that write to a status object allow status to be NULL,
+ * to support use cases where the function's caller does not care about the
+ * status message. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
+void upb_status_seterrcode(upb_status *status, upb_errorspace *space, int code);
+void upb_status_copy(upb_status *to, const upb_status *from);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+
+namespace upb {
+
+/* C++ Wrappers */
+inline Status::Status() { Clear(); }
+inline bool Status::ok() const { return upb_ok(this); }
+inline const char* Status::error_message() const {
+  return upb_status_errmsg(this);
+}
+inline void Status::SetErrorMessage(const char* msg) {
+  upb_status_seterrmsg(this, msg);
+}
+inline void Status::SetFormattedErrorMessage(const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(this, fmt, args);
+  va_end(args);
+}
+inline void Status::SetErrorCode(ErrorSpace* space, int code) {
+  upb_status_seterrcode(this, space, code);
+}
+inline void Status::Clear() { upb_status_clear(this); }
+inline void Status::CopyFrom(const Status& other) {
+  upb_status_copy(this, &other);
+}
+
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_H_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* upb_value ******************************************************************/
+
+/* A tagged union (stored untagged inside the table) so that we can check that
+ * clients calling table accessors are correctly typed without having to have
+ * an explosion of accessors. */
+typedef enum {
+  UPB_CTYPE_INT32    = 1,
+  UPB_CTYPE_INT64    = 2,
+  UPB_CTYPE_UINT32   = 3,
+  UPB_CTYPE_UINT64   = 4,
+  UPB_CTYPE_BOOL     = 5,
+  UPB_CTYPE_CSTR     = 6,
+  UPB_CTYPE_PTR      = 7,
+  UPB_CTYPE_CONSTPTR = 8,
+  UPB_CTYPE_FPTR     = 9
+} upb_ctype_t;
+
+typedef struct {
+  uint64_t val;
+#ifndef NDEBUG
+  /* In debug mode we carry the value type around also so we can check accesses
+   * to be sure the right member is being read. */
+  upb_ctype_t ctype;
+#endif
+} upb_value;
+
+#ifdef NDEBUG
+#define SET_TYPE(dest, val)      UPB_UNUSED(val)
+#else
+#define SET_TYPE(dest, val) dest = val
+#endif
+
+/* Like strdup(), which isn't always available since it's not ANSI C. */
+char *upb_strdup(const char *s);
+/* Variant that works with a length-delimited rather than NULL-delimited string,
+ * as supported by strtable. */
+char *upb_strdup2(const char *s, size_t len);
+
+UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val,
+                                  upb_ctype_t ctype) {
+  v->val = val;
+  SET_TYPE(v->ctype, ctype);
+}
+
+UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) {
+  upb_value ret;
+  _upb_value_setval(&ret, val, ctype);
+  return ret;
+}
+
+/* For each value ctype, define the following set of functions:
+ *
+ * // Get/set an int32 from a upb_value.
+ * int32_t upb_value_getint32(upb_value val);
+ * void upb_value_setint32(upb_value *val, int32_t cval);
+ *
+ * // Construct a new upb_value from an int32.
+ * upb_value upb_value_int32(int32_t val); */
+#define FUNCS(name, membername, type_t, converter, proto_type) \
+  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
+    val->val = (converter)cval; \
+    SET_TYPE(val->ctype, proto_type); \
+  } \
+  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
+    upb_value ret; \
+    upb_value_set ## name(&ret, val); \
+    return ret; \
+  } \
+  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
+    assert(val.ctype == proto_type); \
+    return (type_t)(converter)val.val; \
+  }
+
+FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
+FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
+FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
+FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
+FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
+FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
+FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
+FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
+FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
+
+#undef FUNCS
+#undef SET_TYPE
+
+
+/* upb_tabkey *****************************************************************/
+
+/* Either:
+ *   1. an actual integer key, or
+ *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
+ *
+ * ...depending on whether this is a string table or an int table.  We would
+ * make this a union of those two types, but C89 doesn't support statically
+ * initializing a non-first union member. */
+typedef uintptr_t upb_tabkey;
+
+#define UPB_TABKEY_NUM(n) n
+#define UPB_TABKEY_NONE 0
+/* The preprocessor isn't quite powerful enough to turn the compile-time string
+ * length into a byte-wise string representation, so code generation needs to
+ * help it along.
+ *
+ * "len1" is the low byte and len4 is the high byte. */
+#ifdef UPB_BIG_ENDIAN
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+    (uintptr_t)(len4 len3 len2 len1 strval)
+#else
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+    (uintptr_t)(len1 len2 len3 len4 strval)
+#endif
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+  char* mem = (char*)key;
+  if (len) memcpy(len, mem, sizeof(*len));
+  return mem + sizeof(*len);
+}
+
+
+/* upb_tabval *****************************************************************/
+
+#ifdef __cplusplus
+
+/* Status initialization not supported.
+ *
+ * This separate definition is necessary because in C++, UINTPTR_MAX isn't
+ * reliably available. */
+typedef struct {
+  uint64_t val;
+} upb_tabval;
+
+#else
+
+/* C -- supports static initialization, but to support static initialization of
+ * both integers and points for both 32 and 64 bit targets, it takes a little
+ * bit of doing. */
+
+#if UINTPTR_MAX == 0xffffffffffffffffULL
+#define UPB_PTR_IS_64BITS
+#elif UINTPTR_MAX != 0xffffffff
+#error Could not determine how many bits pointers are.
+#endif
+
+typedef union {
+  /* For static initialization.
+   *
+   * Unfortunately this ugliness is necessary -- it is the only way that we can,
+   * with -std=c89 -pedantic, statically initialize this to either a pointer or
+   * an integer on 32-bit platforms. */
+  struct {
+#ifdef UPB_PTR_IS_64BITS
+    uintptr_t val;
+#else
+    uintptr_t val1;
+    uintptr_t val2;
+#endif
+  } staticinit;
+
+  /* The normal accessor that we use for everything at runtime. */
+  uint64_t val;
+} upb_tabval;
+
+#ifdef UPB_PTR_IS_64BITS
+#define UPB_TABVALUE_INT_INIT(v) {{v}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1}}
+#else
+
+/* 32-bit pointers */
+
+#ifdef UPB_BIG_ENDIAN
+#define UPB_TABVALUE_INT_INIT(v) {{0, v}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1, -1}}
+#else
+#define UPB_TABVALUE_INT_INIT(v) {{v, 0}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1, -1}}
+#endif
+
+#endif
+
+#define UPB_TABVALUE_PTR_INIT(v) UPB_TABVALUE_INT_INIT((uintptr_t)v)
+
+#undef UPB_PTR_IS_64BITS
+
+#endif  /* __cplusplus */
+
+
+/* upb_table ******************************************************************/
+
+typedef struct _upb_tabent {
+  upb_tabkey key;
+  upb_tabval val;
+
+  /* Internal chaining.  This is const so we can create static initializers for
+   * tables.  We cast away const sometimes, but *only* when the containing
+   * upb_table is known to be non-const.  This requires a bit of care, but
+   * the subtlety is confined to table.c. */
+  const struct _upb_tabent *next;
+} upb_tabent;
+
+typedef struct {
+  size_t count;          /* Number of entries in the hash part. */
+  size_t mask;           /* Mask to turn hash value -> bucket. */
+  upb_ctype_t ctype;     /* Type of all values. */
+  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
+
+  /* Hash table entries.
+   * Making this const isn't entirely accurate; what we really want is for it to
+   * have the same const-ness as the table it's inside.  But there's no way to
+   * declare that in C.  So we have to make it const so that we can statically
+   * initialize const hash tables.  Then we cast away const when we have to.
+   */
+  const upb_tabent *entries;
+} upb_table;
+
+typedef struct {
+  upb_table t;
+} upb_strtable;
+
+#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
+  {{count, mask, ctype, size_lg2, entries}}
+
+#define UPB_EMPTY_STRTABLE_INIT(ctype)                           \
+  UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL)
+
+typedef struct {
+  upb_table t;              /* For entries that don't fit in the array part. */
+  const upb_tabval *array;  /* Array part of the table. See const note above. */
+  size_t array_size;        /* Array part size. */
+  size_t array_count;       /* Array part number of elements. */
+} upb_inttable;
+
+#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
+  {{count, mask, ctype, size_lg2, ent}, a, asize, acount}
+
+#define UPB_EMPTY_INTTABLE_INIT(ctype) \
+  UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
+
+#define UPB_ARRAY_EMPTYENT -1
+
+UPB_INLINE size_t upb_table_size(const upb_table *t) {
+  if (t->size_lg2 == 0)
+    return 0;
+  else
+    return 1 << t->size_lg2;
+}
+
+/* Internal-only functions, in .h file only out of necessity. */
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
+  return e->key == 0;
+}
+
+/* Used by some of the unit tests for generic hashing functionality. */
+uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed);
+
+UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
+  return key;
+}
+
+UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
+  return (uint32_t)key;
+}
+
+static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
+  return t->entries + (hash & t->mask);
+}
+
+UPB_INLINE bool upb_arrhas(upb_tabval key) {
+  return key.val != (uint64_t)-1;
+}
+
+/* Initialize and uninitialize a table, respectively.  If memory allocation
+ * failed, false is returned that the table is uninitialized. */
+bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype);
+bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype);
+void upb_inttable_uninit(upb_inttable *table);
+void upb_strtable_uninit(upb_strtable *table);
+
+/* Returns the number of values in the table. */
+size_t upb_inttable_count(const upb_inttable *t);
+UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
+  return t->t.count;
+}
+
+/* Inserts the given key into the hashtable with the given value.  The key must
+ * not already exist in the hash table.  For string tables, the key must be
+ * NULL-terminated, and the table will make an internal copy of the key.
+ * Inttables must not insert a value of UINTPTR_MAX.
+ *
+ * If a table resize was required but memory allocation failed, false is
+ * returned and the table is unchanged. */
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val);
+bool upb_strtable_insert2(upb_strtable *t, const char *key, size_t len,
+                          upb_value val);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
+                                    upb_value val) {
+  return upb_strtable_insert2(t, key, strlen(key), val);
+}
+
+/* Looks up key in this table, returning "true" if the key was found.
+ * If v is non-NULL, copies the value for this key into *v. */
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+/* Removes an item from the table.  Returns true if the remove was successful,
+ * and stores the removed item in *val if non-NULL. */
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
+bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len,
+                          upb_value *val);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_remove2(t, key, strlen(key), v);
+}
+
+/* Updates an existing entry in an inttable.  If the entry does not exist,
+ * returns false and does nothing.  Unlike insert/remove, this does not
+ * invalidate iterators. */
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
+
+/* Handy routines for treating an inttable like a stack.  May not be mixed with
+ * other insert/remove calls. */
+bool upb_inttable_push(upb_inttable *t, upb_value val);
+upb_value upb_inttable_pop(upb_inttable *t);
+
+/* Convenience routines for inttables with pointer keys. */
+bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val);
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
+bool upb_inttable_lookupptr(
+    const upb_inttable *t, const void *key, upb_value *val);
+
+/* Optimizes the table for the current set of entries, for both memory use and
+ * lookup time.  Client should call this after all entries have been inserted;
+ * inserting more entries is legal, but will likely require a table resize. */
+void upb_inttable_compact(upb_inttable *t);
+
+/* A special-case inlinable version of the lookup routine for 32-bit
+ * integers. */
+UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
+                                      upb_value *v) {
+  *v = upb_value_int32(0);  /* Silence compiler warnings. */
+  if (key < t->array_size) {
+    upb_tabval arrval = t->array[key];
+    if (upb_arrhas(arrval)) {
+      _upb_value_setval(v, arrval.val, t->t.ctype);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    const upb_tabent *e;
+    if (t->t.entries == NULL) return false;
+    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
+      if ((uint32_t)e->key == key) {
+        _upb_value_setval(v, e->val.val, t->t.ctype);
+        return true;
+      }
+      if (e->next == NULL) return false;
+    }
+  }
+}
+
+/* Exposed for testing only. */
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2);
+
+/* Iterators ******************************************************************/
+
+/* Iterators for int and string tables.  We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ *  - we must be able to guarantee that we don't crash or corrupt memory even if
+ *    the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ *  - iterators must be copyable
+ *  - iterators must be comparable
+ *  - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed.  Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+
+
+/* upb_strtable_iter **********************************************************/
+
+/*   upb_strtable_iter i;
+ *   upb_strtable_begin(&i, t);
+ *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ *     const char *key = upb_strtable_iter_key(&i);
+ *     const upb_value val = upb_strtable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_strtable *t;
+  size_t index;
+} upb_strtable_iter;
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
+void upb_strtable_next(upb_strtable_iter *i);
+bool upb_strtable_done(const upb_strtable_iter *i);
+const char *upb_strtable_iter_key(upb_strtable_iter *i);
+size_t upb_strtable_iter_keylength(upb_strtable_iter *i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
+void upb_strtable_iter_setdone(upb_strtable_iter *i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2);
+
+
+/* upb_inttable_iter **********************************************************/
+
+/*   upb_inttable_iter i;
+ *   upb_inttable_begin(&i, t);
+ *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ *     uintptr_t key = upb_inttable_iter_key(&i);
+ *     upb_value val = upb_inttable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_inttable *t;
+  size_t index;
+  bool array_part;
+} upb_inttable_iter;
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
+void upb_inttable_next(upb_inttable_iter *i);
+bool upb_inttable_done(const upb_inttable_iter *i);
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
+void upb_inttable_iter_setdone(upb_inttable_iter *i);
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                               const upb_inttable_iter *i2);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_TABLE_H_ */
+
+/* Reference tracking will check ref()/unref() operations to make sure the
+ * ref ownership is correct.  Where possible it will also make tools like
+ * Valgrind attribute ref leaks to the code that took the leaked ref, not
+ * the code that originally created the object.
+ *
+ * Enabling this requires the application to define upb_lock()/upb_unlock()
+ * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE).
+ * For this reason we don't enable it by default, even in debug builds.
+ */
+
+/* #define UPB_DEBUG_REFS */
+
+#ifdef __cplusplus
+namespace upb { class RefCounted; }
+#endif
+
+UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted)
+
+struct upb_refcounted_vtbl;
+
+#ifdef __cplusplus
+
+class upb::RefCounted {
+ public:
+  /* Returns true if the given object is frozen. */
+  bool IsFrozen() const;
+
+  /* Increases the ref count, the new ref is owned by "owner" which must not
+   * already own a ref (and should not itself be a refcounted object if the ref
+   * could possibly be circular; see below).
+   * Thread-safe iff "this" is frozen. */
+  void Ref(const void *owner) const;
+
+  /* Release a ref that was acquired from upb_refcounted_ref() and collects any
+   * objects it can. */
+  void Unref(const void *owner) const;
+
+  /* Moves an existing ref from "from" to "to", without changing the overall
+   * ref count.  DonateRef(foo, NULL, owner) is the same as Ref(foo, owner),
+   * but "to" may not be NULL. */
+  void DonateRef(const void *from, const void *to) const;
+
+  /* Verifies that a ref to the given object is currently held by the given
+   * owner.  Only effective in UPB_DEBUG_REFS builds. */
+  void CheckRef(const void *owner) const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted)
+#else
+struct upb_refcounted {
+#endif
+  /* TODO(haberman): move the actual structure definition to structdefs.int.h.
+   * The only reason they are here is because inline functions need to see the
+   * definition of upb_handlers, which needs to see this definition.  But we
+   * can change the upb_handlers inline functions to deal in raw offsets
+   * instead.
+   */
+
+  /* A single reference count shared by all objects in the group. */
+  uint32_t *group;
+
+  /* A singly-linked list of all objects in the group. */
+  upb_refcounted *next;
+
+  /* Table of function pointers for this type. */
+  const struct upb_refcounted_vtbl *vtbl;
+
+  /* Maintained only when mutable, this tracks the number of refs (but not
+   * ref2's) to this object.  *group should be the sum of all individual_count
+   * in the group. */
+  uint32_t individual_count;
+
+  bool is_frozen;
+
+#ifdef UPB_DEBUG_REFS
+  upb_inttable *refs;  /* Maps owner -> trackedref for incoming refs. */
+  upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */
+#endif
+};
+
+#ifdef UPB_DEBUG_REFS
+#define UPB_REFCOUNT_INIT(refs, ref2s) \
+    {&static_refcount, NULL, NULL, 0, true, refs, ref2s}
+#else
+#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true}
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* It is better to use tracked refs when possible, for the extra debugging
+ * capability.  But if this is not possible (because you don't have easy access
+ * to a stable pointer value that is associated with the ref), you can pass
+ * UPB_UNTRACKED_REF instead.  */
+extern const void *UPB_UNTRACKED_REF;
+
+/* Native C API. */
+bool upb_refcounted_isfrozen(const upb_refcounted *r);
+void upb_refcounted_ref(const upb_refcounted *r, const void *owner);
+void upb_refcounted_unref(const upb_refcounted *r, const void *owner);
+void upb_refcounted_donateref(
+    const upb_refcounted *r, const void *from, const void *to);
+void upb_refcounted_checkref(const upb_refcounted *r, const void *owner);
+
+#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \
+  UPB_INLINE bool type ## _isfrozen(const type *v) { \
+    return upb_refcounted_isfrozen(upcastfunc(v)); \
+  } \
+  UPB_INLINE void type ## _ref(const type *v, const void *owner) { \
+    upb_refcounted_ref(upcastfunc(v), owner); \
+  } \
+  UPB_INLINE void type ## _unref(const type *v, const void *owner) { \
+    upb_refcounted_unref(upcastfunc(v), owner); \
+  } \
+  UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \
+    upb_refcounted_donateref(upcastfunc(v), from, to); \
+  } \
+  UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \
+    upb_refcounted_checkref(upcastfunc(v), owner); \
+  }
+
+#define UPB_REFCOUNTED_CPPMETHODS \
+  bool IsFrozen() const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->IsFrozen(); \
+  } \
+  void Ref(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->Ref(owner); \
+  } \
+  void Unref(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->Unref(owner); \
+  } \
+  void DonateRef(const void *from, const void *to) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->DonateRef(from, to); \
+  } \
+  void CheckRef(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->CheckRef(owner); \
+  }
+
+/* Internal-to-upb Interface **************************************************/
+
+typedef void upb_refcounted_visit(const upb_refcounted *r,
+                                  const upb_refcounted *subobj,
+                                  void *closure);
+
+struct upb_refcounted_vtbl {
+  /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2.
+   * Must be longjmp()-safe. */
+  void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c);
+
+  /* Must free the object and release all references to other objects. */
+  void (*free)(upb_refcounted *r);
+};
+
+/* Initializes the refcounted with a single ref for the given owner.  Returns
+ * false if memory could not be allocated. */
+bool upb_refcounted_init(upb_refcounted *r,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner);
+
+/* Adds a ref from one refcounted object to another ("from" must not already
+ * own a ref).  These refs may be circular; cycles will be collected correctly
+ * (if conservatively).  These refs do not need to be freed in from's free()
+ * function. */
+void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from);
+
+/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any
+ * object it can.  This is only necessary when "from" no longer points to "r",
+ * and not from from's "free" function. */
+void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from);
+
+#define upb_ref2(r, from) \
+    upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from)
+#define upb_unref2(r, from) \
+    upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from)
+
+/* Freezes all mutable object reachable by ref2() refs from the given roots.
+ * This will split refcounting groups into precise SCC groups, so that
+ * refcounting of frozen objects can be more aggressive.  If memory allocation
+ * fails, or if more than 2**31 mutable objects are reachable from "roots", or
+ * if the maximum depth of the graph exceeds "maxdepth", false is returned and
+ * the objects are unchanged.
+ *
+ * After this operation succeeds, the objects are frozen/const, and may not be
+ * used through non-const pointers.  In particular, they may not be passed as
+ * the second parameter of upb_refcounted_{ref,unref}2().  On the upside, all
+ * operations on frozen refcounteds are threadsafe, and objects will be freed
+ * at the precise moment that they become unreachable.
+ *
+ * Caller must own refs on each object in the "roots" list. */
+bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                           int maxdepth);
+
+/* Shared by all compiled-in refcounted objects. */
+extern uint32_t static_refcount;
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ Wrappers. */
+namespace upb {
+inline bool RefCounted::IsFrozen() const {
+  return upb_refcounted_isfrozen(this);
+}
+inline void RefCounted::Ref(const void *owner) const {
+  upb_refcounted_ref(this, owner);
+}
+inline void RefCounted::Unref(const void *owner) const {
+  upb_refcounted_unref(this, owner);
+}
+inline void RefCounted::DonateRef(const void *from, const void *to) const {
+  upb_refcounted_donateref(this, from, to);
+}
+inline void RefCounted::CheckRef(const void *owner) const {
+  upb_refcounted_checkref(this, owner);
+}
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_REFCOUNT_H_ */
+
+#ifdef __cplusplus
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace upb {
+class Def;
+class EnumDef;
+class FieldDef;
+class MessageDef;
+class OneofDef;
+}
+#endif
+
+UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted)
+
+/* The maximum message depth that the type graph can have.  This is a resource
+ * limit for the C stack since we sometimes need to recursively traverse the
+ * graph.  Cycles are ok; the traversal will stop when it detects a cycle, but
+ * we must hit the cycle before the maximum depth is reached.
+ *
+ * If having a single static limit is too inflexible, we can add another variant
+ * of Def::Freeze that allows specifying this as a parameter. */
+#define UPB_MAX_MESSAGE_DEPTH 64
+
+
+/* upb::Def: base class for defs  *********************************************/
+
+/* All the different kind of defs we support.  These correspond 1:1 with
+ * declarations in a .proto file. */
+typedef enum {
+  UPB_DEF_MSG,
+  UPB_DEF_FIELD,
+  UPB_DEF_ENUM,
+  UPB_DEF_ONEOF,
+  UPB_DEF_SERVICE,   /* Not yet implemented. */
+  UPB_DEF_ANY = -1   /* Wildcard for upb_symtab_get*() */
+} upb_deftype_t;
+
+#ifdef __cplusplus
+
+/* The base class of all defs.  Its base is upb::RefCounted (use upb::upcast()
+ * to convert). */
+class upb::Def {
+ public:
+  typedef upb_deftype_t Type;
+
+  Def* Dup(const void *owner) const;
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  Type def_type() const;
+
+  /* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */
+  const char *full_name() const;
+
+  /* The def must be mutable.  Caller retains ownership of fullname.  Defs are
+   * not required to have a name; if a def has no name when it is frozen, it
+   * will remain an anonymous def.  On failure, returns false and details in "s"
+   * if non-NULL. */
+  bool set_full_name(const char* fullname, upb::Status* s);
+  bool set_full_name(const std::string &fullname, upb::Status* s);
+
+  /* Freezes the given defs; this validates all constraints and marks the defs
+   * as frozen (read-only).  "defs" may not contain any fielddefs, but fields
+   * of any msgdefs will be frozen.
+   *
+   * Symbolic references to sub-types and enum defaults must have already been
+   * resolved.  Any mutable defs reachable from any of "defs" must also be in
+   * the list; more formally, "defs" must be a transitive closure of mutable
+   * defs.
+   *
+   * After this operation succeeds, the finalized defs must only be accessed
+   * through a const pointer! */
+  static bool Freeze(Def* const* defs, int n, Status* status);
+  static bool Freeze(const std::vector<Def*>& defs, Status* status);
+
+ private:
+  UPB_DISALLOW_POD_OPS(Def, upb::Def)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_def *upb_def_dup(const upb_def *def, const void *owner);
+
+/* Include upb_refcounted methods like upb_def_ref()/upb_def_unref(). */
+UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast)
+
+upb_deftype_t upb_def_type(const upb_def *d);
+const char *upb_def_fullname(const upb_def *d);
+bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s);
+bool upb_def_freeze(upb_def *const *defs, int n, upb_status *s);
+
+UPB_END_EXTERN_C
+
+
+/* upb::Def casts *************************************************************/
+
+#ifdef __cplusplus
+#define UPB_CPP_CASTS(cname, cpptype)                                          \
+  namespace upb {                                                              \
+  template <>                                                                  \
+  inline cpptype *down_cast<cpptype *, Def>(Def * def) {                       \
+    return upb_downcast_##cname##_mutable(def);                                \
+  }                                                                            \
+  template <>                                                                  \
+  inline cpptype *dyn_cast<cpptype *, Def>(Def * def) {                        \
+    return upb_dyncast_##cname##_mutable(def);                                 \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *down_cast<const cpptype *, const Def>(                 \
+      const Def *def) {                                                        \
+    return upb_downcast_##cname(def);                                          \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *dyn_cast<const cpptype *, const Def>(const Def *def) { \
+    return upb_dyncast_##cname(def);                                           \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *down_cast<const cpptype *, Def>(Def * def) {           \
+    return upb_downcast_##cname(def);                                          \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *dyn_cast<const cpptype *, Def>(Def * def) {            \
+    return upb_dyncast_##cname(def);                                           \
+  }                                                                            \
+  }  /* namespace upb */
+#else
+#define UPB_CPP_CASTS(cname, cpptype)
+#endif  /* __cplusplus */
+
+/* Dynamic casts, for determining if a def is of a particular type at runtime.
+ * Downcasts, for when some wants to assert that a def is of a particular type.
+ * These are only checked if we are building debug. */
+#define UPB_DEF_CASTS(lower, upper, cpptype)                               \
+  UPB_INLINE const upb_##lower *upb_dyncast_##lower(const upb_def *def) {  \
+    if (upb_def_type(def) != UPB_DEF_##upper) return NULL;                 \
+    return (upb_##lower *)def;                                             \
+  }                                                                        \
+  UPB_INLINE const upb_##lower *upb_downcast_##lower(const upb_def *def) { \
+    assert(upb_def_type(def) == UPB_DEF_##upper);                          \
+    return (const upb_##lower *)def;                                       \
+  }                                                                        \
+  UPB_INLINE upb_##lower *upb_dyncast_##lower##_mutable(upb_def *def) {    \
+    return (upb_##lower *)upb_dyncast_##lower(def);                        \
+  }                                                                        \
+  UPB_INLINE upb_##lower *upb_downcast_##lower##_mutable(upb_def *def) {   \
+    return (upb_##lower *)upb_downcast_##lower(def);                       \
+  }                                                                        \
+  UPB_CPP_CASTS(lower, cpptype)
+
+#define UPB_DEFINE_DEF(cppname, lower, upper, cppmethods, members)             \
+  UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, cppmethods,            \
+                   members)                                                    \
+  UPB_DEF_CASTS(lower, upper, cppname)
+
+#define UPB_DECLARE_DEF_TYPE(cppname, lower, upper) \
+  UPB_DECLARE_DERIVED_TYPE2(cppname, upb::Def, upb::RefCounted, \
+                            upb_ ## lower, upb_def, upb_refcounted) \
+  UPB_DEF_CASTS(lower, upper, cppname)
+
+UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD)
+UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG)
+UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM)
+UPB_DECLARE_DEF_TYPE(upb::OneofDef, oneofdef, ONEOF)
+
+#undef UPB_DECLARE_DEF_TYPE
+#undef UPB_DEF_CASTS
+#undef UPB_CPP_CASTS
+
+
+/* upb::FieldDef **************************************************************/
+
+/* The types a field can have.  Note that this list is not identical to the
+ * types defined in descriptor.proto, which gives INT32 and SINT32 separate
+ * types (we distinguish the two with the "integer encoding" enum below). */
+typedef enum {
+  UPB_TYPE_FLOAT    = 1,
+  UPB_TYPE_DOUBLE   = 2,
+  UPB_TYPE_BOOL     = 3,
+  UPB_TYPE_STRING   = 4,
+  UPB_TYPE_BYTES    = 5,
+  UPB_TYPE_MESSAGE  = 6,
+  UPB_TYPE_ENUM     = 7,  /* Enum values are int32. */
+  UPB_TYPE_INT32    = 8,
+  UPB_TYPE_UINT32   = 9,
+  UPB_TYPE_INT64    = 10,
+  UPB_TYPE_UINT64   = 11
+} upb_fieldtype_t;
+
+/* The repeated-ness of each field; this matches descriptor.proto. */
+typedef enum {
+  UPB_LABEL_OPTIONAL = 1,
+  UPB_LABEL_REQUIRED = 2,
+  UPB_LABEL_REPEATED = 3
+} upb_label_t;
+
+/* How integers should be encoded in serializations that offer multiple
+ * integer encoding methods. */
+typedef enum {
+  UPB_INTFMT_VARIABLE = 1,
+  UPB_INTFMT_FIXED = 2,
+  UPB_INTFMT_ZIGZAG = 3   /* Only for signed types (INT32/INT64). */
+} upb_intfmt_t;
+
+/* Descriptor types, as defined in descriptor.proto. */
+typedef enum {
+  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
+  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
+  UPB_DESCRIPTOR_TYPE_INT64    = 3,
+  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
+  UPB_DESCRIPTOR_TYPE_INT32    = 5,
+  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
+  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
+  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
+  UPB_DESCRIPTOR_TYPE_STRING   = 9,
+  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
+  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
+  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
+  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
+  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
+  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
+  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
+  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
+  UPB_DESCRIPTOR_TYPE_SINT64   = 18
+} upb_descriptortype_t;
+
+/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+#ifdef __cplusplus
+
+/* A upb_fielddef describes a single field in a message.  It is most often
+ * found as a part of a upb_msgdef, but can also stand alone to represent
+ * an extension.
+ *
+ * Its base class is upb::Def (use upb::upcast() to convert). */
+class upb::FieldDef {
+ public:
+  typedef upb_fieldtype_t Type;
+  typedef upb_label_t Label;
+  typedef upb_intfmt_t IntegerFormat;
+  typedef upb_descriptortype_t DescriptorType;
+
+  /* These return true if the given value is a valid member of the enumeration. */
+  static bool CheckType(int32_t val);
+  static bool CheckLabel(int32_t val);
+  static bool CheckDescriptorType(int32_t val);
+  static bool CheckIntegerFormat(int32_t val);
+
+  /* These convert to the given enumeration; they require that the value is
+   * valid. */
+  static Type ConvertType(int32_t val);
+  static Label ConvertLabel(int32_t val);
+  static DescriptorType ConvertDescriptorType(int32_t val);
+  static IntegerFormat ConvertIntegerFormat(int32_t val);
+
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<FieldDef> New();
+
+  /* Duplicates the given field, returning NULL if memory allocation failed.
+   * When a fielddef is duplicated, the subdef (if any) is made symbolic if it
+   * wasn't already.  If the subdef is set but has no name (which is possible
+   * since msgdefs are not required to have a name) the new fielddef's subdef
+   * will be unset. */
+  FieldDef* Dup(const void* owner) const;
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+
+  bool type_is_set() const;  /* set_[descriptor_]type() has been called? */
+  Type type() const;         /* Requires that type_is_set() == true. */
+  Label label() const;       /* Defaults to UPB_LABEL_OPTIONAL. */
+  const char* name() const;  /* NULL if uninitialized. */
+  uint32_t number() const;   /* Returns 0 if uninitialized. */
+  bool is_extension() const;
+
+  /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
+   * indicates whether this field should have lazy parsing handlers that yield
+   * the unparsed string for the submessage.
+   *
+   * TODO(haberman): I think we want to move this into a FieldOptions container
+   * when we add support for custom options (the FieldOptions struct will
+   * contain both regular FieldOptions like "lazy" *and* custom options). */
+  bool lazy() const;
+
+  /* For non-string, non-submessage fields, this indicates whether binary
+   * protobufs are encoded in packed or non-packed format.
+   *
+   * TODO(haberman): see note above about putting options like this into a
+   * FieldOptions container. */
+  bool packed() const;
+
+  /* An integer that can be used as an index into an array of fields for
+   * whatever message this field belongs to.  Guaranteed to be less than
+   * f->containing_type()->field_count().  May only be accessed once the def has
+   * been finalized. */
+  int index() const;
+
+  /* The MessageDef to which this field belongs.
+   *
+   * If this field has been added to a MessageDef, that message can be retrieved
+   * directly (this is always the case for frozen FieldDefs).
+   *
+   * If the field has not yet been added to a MessageDef, you can set the name
+   * of the containing type symbolically instead.  This is mostly useful for
+   * extensions, where the extension is declared separately from the message. */
+  const MessageDef* containing_type() const;
+  const char* containing_type_name();
+
+  /* The OneofDef to which this field belongs, or NULL if this field is not part
+   * of a oneof. */
+  const OneofDef* containing_oneof() const;
+
+  /* The field's type according to the enum in descriptor.proto.  This is not
+   * the same as UPB_TYPE_*, because it distinguishes between (for example)
+   * INT32 and SINT32, whereas our "type" enum does not.  This return of
+   * descriptor_type() is a function of type(), integer_format(), and
+   * is_tag_delimited().  Likewise set_descriptor_type() sets all three
+   * appropriately. */
+  DescriptorType descriptor_type() const;
+
+  /* Convenient field type tests. */
+  bool IsSubMessage() const;
+  bool IsString() const;
+  bool IsSequence() const;
+  bool IsPrimitive() const;
+  bool IsMap() const;
+
+  /* How integers are encoded.  Only meaningful for integer types.
+   * Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */
+  IntegerFormat integer_format() const;
+
+  /* Whether a submessage field is tag-delimited or not (if false, then
+   * length-delimited).  May only be set when type() == UPB_TYPE_MESSAGE. */
+  bool is_tag_delimited() const;
+
+  /* Returns the non-string default value for this fielddef, which may either
+   * be something the client set explicitly or the "default default" (0 for
+   * numbers, empty for strings).  The field's type indicates the type of the
+   * returned value, except for enum fields that are still mutable.
+   *
+   * Requires that the given function matches the field's current type. */
+  int64_t default_int64() const;
+  int32_t default_int32() const;
+  uint64_t default_uint64() const;
+  uint32_t default_uint32() const;
+  bool default_bool() const;
+  float default_float() const;
+  double default_double() const;
+
+  /* The resulting string is always NULL-terminated.  If non-NULL, the length
+   * will be stored in *len. */
+  const char *default_string(size_t* len) const;
+
+  /* For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either
+   * string or int32, and both of these methods will always return true.
+   *
+   * For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated.
+   * Enum defaults are unusual. They can be specified either as string or int32,
+   * but to be valid the enum must have that value as a member.  And if no
+   * default is specified, the "default default" comes from the EnumDef.
+   *
+   * We allow reading the default as either an int32 or a string, but only if
+   * we have a meaningful value to report.  We have a meaningful value if it was
+   * set explicitly, or if we could get the "default default" from the EnumDef.
+   * Also if you explicitly set the name and we find the number in the EnumDef */
+  bool EnumHasStringDefault() const;
+  bool EnumHasInt32Default() const;
+
+  /* Submessage and enum fields must reference a "subdef", which is the
+   * upb::MessageDef or upb::EnumDef that defines their type.  Note that when
+   * the FieldDef is mutable it may not have a subdef *yet*, but this function
+   * still returns true to indicate that the field's type requires a subdef. */
+  bool HasSubDef() const;
+
+  /* Returns the enum or submessage def for this field, if any.  The field's
+   * type must match (ie. you may only call enum_subdef() for fields where
+   * type() == UPB_TYPE_ENUM).  Returns NULL if the subdef has not been set or
+   * is currently set symbolically. */
+  const EnumDef* enum_subdef() const;
+  const MessageDef* message_subdef() const;
+
+  /* Returns the generic subdef for this field.  Requires that HasSubDef() (ie.
+   * only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). */
+  const Def* subdef() const;
+
+  /* Returns the symbolic name of the subdef.  If the subdef is currently set
+   * unresolved (ie. set symbolically) returns the symbolic name.  If it has
+   * been resolved to a specific subdef, returns the name from that subdef. */
+  const char* subdef_name() const;
+
+  /* Setters (non-const methods), only valid for mutable FieldDefs! ***********/
+
+  bool set_full_name(const char* fullname, upb::Status* s);
+  bool set_full_name(const std::string& fullname, upb::Status* s);
+
+  /* This may only be called if containing_type() == NULL (ie. the field has not
+   * been added to a message yet). */
+  bool set_containing_type_name(const char *name, Status* status);
+  bool set_containing_type_name(const std::string& name, Status* status);
+
+  /* Defaults to false.  When we freeze, we ensure that this can only be true
+   * for length-delimited message fields.  Prior to freezing this can be true or
+   * false with no restrictions. */
+  void set_lazy(bool lazy);
+
+  /* Defaults to true.  Sets whether this field is encoded in packed format. */
+  void set_packed(bool packed);
+
+  /* "type" or "descriptor_type" MUST be set explicitly before the fielddef is
+   * finalized.  These setters require that the enum value is valid; if the
+   * value did not come directly from an enum constant, the caller should
+   * validate it first with the functions above (CheckFieldType(), etc). */
+  void set_type(Type type);
+  void set_label(Label label);
+  void set_descriptor_type(DescriptorType type);
+  void set_is_extension(bool is_extension);
+
+  /* "number" and "name" must be set before the FieldDef is added to a
+   * MessageDef, and may not be set after that.
+   *
+   * "name" is the same as full_name()/set_full_name(), but since fielddefs
+   * most often use simple, non-qualified names, we provide this accessor
+   * also.  Generally only extensions will want to think of this name as
+   * fully-qualified. */
+  bool set_number(uint32_t number, upb::Status* s);
+  bool set_name(const char* name, upb::Status* s);
+  bool set_name(const std::string& name, upb::Status* s);
+
+  void set_integer_format(IntegerFormat format);
+  bool set_tag_delimited(bool tag_delimited, upb::Status* s);
+
+  /* Sets default value for the field.  The call must exactly match the type
+   * of the field.  Enum fields may use either setint32 or setstring to set
+   * the default numerically or symbolically, respectively, but symbolic
+   * defaults must be resolved before finalizing (see ResolveEnumDefault()).
+   *
+   * Changing the type of a field will reset its default. */
+  void set_default_int64(int64_t val);
+  void set_default_int32(int32_t val);
+  void set_default_uint64(uint64_t val);
+  void set_default_uint32(uint32_t val);
+  void set_default_bool(bool val);
+  void set_default_float(float val);
+  void set_default_double(double val);
+  bool set_default_string(const void *str, size_t len, Status *s);
+  bool set_default_string(const std::string &str, Status *s);
+  void set_default_cstr(const char *str, Status *s);
+
+  /* Before a fielddef is frozen, its subdef may be set either directly (with a
+   * upb::Def*) or symbolically.  Symbolic refs must be resolved before the
+   * containing msgdef can be frozen (see upb_resolve() above).  upb always
+   * guarantees that any def reachable from a live def will also be kept alive.
+   *
+   * Both methods require that upb_hassubdef(f) (so the type must be set prior
+   * to calling these methods).  Returns false if this is not the case, or if
+   * the given subdef is not of the correct type.  The subdef is reset if the
+   * field's type is changed.  The subdef can be set to NULL to clear it. */
+  bool set_subdef(const Def* subdef, Status* s);
+  bool set_enum_subdef(const EnumDef* subdef, Status* s);
+  bool set_message_subdef(const MessageDef* subdef, Status* s);
+  bool set_subdef_name(const char* name, Status* s);
+  bool set_subdef_name(const std::string &name, Status* s);
+
+ private:
+  UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef)
+};
+
+# endif  /* defined(__cplusplus) */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_fielddef *upb_fielddef_new(const void *owner);
+upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner);
+
+/* Include upb_refcounted methods like upb_fielddef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_fielddef, upb_fielddef_upcast2)
+
+/* Methods from upb_def. */
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+bool upb_fielddef_setfullname(upb_fielddef *f, const char *fullname,
+                              upb_status *s);
+
+bool upb_fielddef_typeisset(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
+const char *upb_fielddef_containingtypename(upb_fielddef *f);
+upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_istagdelim(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f);
+bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+const upb_def *upb_fielddef_subdef(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const char *upb_fielddef_subdefname(const upb_fielddef *f);
+
+void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type);
+void upb_fielddef_setdescriptortype(upb_fielddef *f, int type);
+void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label);
+bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s);
+bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+                                        upb_status *s);
+void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension);
+void upb_fielddef_setlazy(upb_fielddef *f, bool lazy);
+void upb_fielddef_setpacked(upb_fielddef *f, bool packed);
+void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt);
+void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim);
+void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t val);
+void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t val);
+void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t val);
+void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t val);
+void upb_fielddef_setdefaultbool(upb_fielddef *f, bool val);
+void upb_fielddef_setdefaultfloat(upb_fielddef *f, float val);
+void upb_fielddef_setdefaultdouble(upb_fielddef *f, double val);
+bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
+                                upb_status *s);
+void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
+                                 upb_status *s);
+bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
+                            upb_status *s);
+bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
+                               upb_status *s);
+bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
+                                upb_status *s);
+bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
+                                upb_status *s);
+
+bool upb_fielddef_checklabel(int32_t label);
+bool upb_fielddef_checktype(int32_t type);
+bool upb_fielddef_checkdescriptortype(int32_t type);
+bool upb_fielddef_checkintfmt(int32_t fmt);
+
+UPB_END_EXTERN_C
+
+
+/* upb::MessageDef ************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+#ifdef __cplusplus
+
+/* Structure that describes a single .proto message type.
+ *
+ * Its base class is upb::Def (use upb::upcast() to convert). */
+class upb::MessageDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<MessageDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+  bool set_full_name(const char* fullname, Status* s);
+  bool set_full_name(const std::string& fullname, Status* s);
+
+  /* Call to freeze this MessageDef.
+   * WARNING: this will fail if this message has any unfrozen submessages!
+   * Messages with cycles must be frozen as a batch using upb::Def::Freeze(). */
+  bool Freeze(Status* s);
+
+  /* The number of fields that belong to the MessageDef. */
+  int field_count() const;
+
+  /* The number of oneofs that belong to the MessageDef. */
+  int oneof_count() const;
+
+  /* Adds a field (upb_fielddef object) to a msgdef.  Requires that the msgdef
+   * and the fielddefs are mutable.  The fielddef's name and number must be
+   * set, and the message may not already contain any field with this name or
+   * number, and this fielddef may not be part of another message.  In error
+   * cases false is returned and the msgdef is unchanged.
+   *
+   * If the given field is part of a oneof, this call succeeds if and only if
+   * that oneof is already part of this msgdef. (Note that adding a oneof to a
+   * msgdef automatically adds all of its fields to the msgdef at the time that
+   * the oneof is added, so it is usually more idiomatic to add the oneof's
+   * fields first then add the oneof to the msgdef. This case is supported for
+   * convenience.)
+   *
+   * If |f| is already part of this MessageDef, this method performs no action
+   * and returns true (success). Thus, this method is idempotent. */
+  bool AddField(FieldDef* f, Status* s);
+  bool AddField(const reffed_ptr<FieldDef>& f, Status* s);
+
+  /* Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef,
+   * oneof, and any fielddefs are mutable, that the fielddefs contained in the
+   * oneof do not have any name or number conflicts with existing fields in the
+   * msgdef, and that the oneof's name is unique among all oneofs in the msgdef.
+   * If the oneof is added successfully, all of its fields will be added
+   * directly to the msgdef as well. In error cases, false is returned and the
+   * msgdef is unchanged. */
+  bool AddOneof(OneofDef* o, Status* s);
+  bool AddOneof(const reffed_ptr<OneofDef>& o, Status* s);
+
+  /* These return NULL if the field is not found. */
+  FieldDef* FindFieldByNumber(uint32_t number);
+  FieldDef* FindFieldByName(const char *name, size_t len);
+  const FieldDef* FindFieldByNumber(uint32_t number) const;
+  const FieldDef* FindFieldByName(const char* name, size_t len) const;
+
+
+  FieldDef* FindFieldByName(const char *name) {
+    return FindFieldByName(name, strlen(name));
+  }
+  const FieldDef* FindFieldByName(const char *name) const {
+    return FindFieldByName(name, strlen(name));
+  }
+
+  template <class T>
+  FieldDef* FindFieldByName(const T& str) {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+  template <class T>
+  const FieldDef* FindFieldByName(const T& str) const {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+
+  OneofDef* FindOneofByName(const char* name, size_t len);
+  const OneofDef* FindOneofByName(const char* name, size_t len) const;
+
+  OneofDef* FindOneofByName(const char* name) {
+    return FindOneofByName(name, strlen(name));
+  }
+  const OneofDef* FindOneofByName(const char* name) const {
+    return FindOneofByName(name, strlen(name));
+  }
+
+  template<class T>
+  OneofDef* FindOneofByName(const T& str) {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+  template<class T>
+  const OneofDef* FindOneofByName(const T& str) const {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+
+  /* Returns a new msgdef that is a copy of the given msgdef (and a copy of all
+   * the fields) but with any references to submessages broken and replaced
+   * with just the name of the submessage.  Returns NULL if memory allocation
+   * failed.
+   *
+   * TODO(haberman): which is more useful, keeping fields resolved or
+   * unresolving them?  If there's no obvious answer, Should this functionality
+   * just be moved into symtab.c? */
+  MessageDef* Dup(const void* owner) const;
+
+  /* Is this message a map entry? */
+  void setmapentry(bool map_entry);
+  bool mapentry() const;
+
+  /* Iteration over fields.  The order is undefined. */
+  class field_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit field_iterator(MessageDef* md);
+    static field_iterator end(MessageDef* md);
+
+    void operator++();
+    FieldDef* operator*() const;
+    bool operator!=(const field_iterator& other) const;
+    bool operator==(const field_iterator& other) const;
+
+   private:
+    upb_msg_field_iter iter_;
+  };
+
+  class const_field_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_field_iterator(const MessageDef* md);
+    static const_field_iterator end(const MessageDef* md);
+
+    void operator++();
+    const FieldDef* operator*() const;
+    bool operator!=(const const_field_iterator& other) const;
+    bool operator==(const const_field_iterator& other) const;
+
+   private:
+    upb_msg_field_iter iter_;
+  };
+
+  /* Iteration over oneofs. The order is undefined. */
+  class oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit oneof_iterator(MessageDef* md);
+    static oneof_iterator end(MessageDef* md);
+
+    void operator++();
+    OneofDef* operator*() const;
+    bool operator!=(const oneof_iterator& other) const;
+    bool operator==(const oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class const_oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_oneof_iterator(const MessageDef* md);
+    static const_oneof_iterator end(const MessageDef* md);
+
+    void operator++();
+    const OneofDef* operator*() const;
+    bool operator!=(const const_oneof_iterator& other) const;
+    bool operator==(const const_oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class FieldAccessor {
+   public:
+    explicit FieldAccessor(MessageDef* msg) : msg_(msg) {}
+    field_iterator begin() { return msg_->field_begin(); }
+    field_iterator end() { return msg_->field_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstFieldAccessor {
+   public:
+    explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_field_iterator begin() { return msg_->field_begin(); }
+    const_field_iterator end() { return msg_->field_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  class OneofAccessor {
+   public:
+    explicit OneofAccessor(MessageDef* msg) : msg_(msg) {}
+    oneof_iterator begin() { return msg_->oneof_begin(); }
+    oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstOneofAccessor {
+   public:
+    explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_oneof_iterator begin() { return msg_->oneof_begin(); }
+    const_oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  field_iterator field_begin();
+  field_iterator field_end();
+  const_field_iterator field_begin() const;
+  const_field_iterator field_end() const;
+
+  oneof_iterator oneof_begin();
+  oneof_iterator oneof_end();
+  const_oneof_iterator oneof_begin() const;
+  const_oneof_iterator oneof_end() const;
+
+  FieldAccessor fields() { return FieldAccessor(this); }
+  ConstFieldAccessor fields() const { return ConstFieldAccessor(this); }
+  OneofAccessor oneofs() { return OneofAccessor(this); }
+  ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); }
+
+ private:
+  UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Returns NULL if memory allocation failed. */
+upb_msgdef *upb_msgdef_new(const void *owner);
+
+/* Include upb_refcounted methods like upb_msgdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2)
+
+bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status);
+
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
+
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
+bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
+                         upb_status *s);
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s);
+
+/* Field lookup in a couple of different variations:
+ *   - itof = int to field
+ *   - ntof = name to field
+ *   - ntofz = name to field, null-terminated string. */
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len);
+int upb_msgdef_numfields(const upb_msgdef *m);
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+                                                const char *name) {
+  return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+UPB_INLINE upb_fielddef *upb_msgdef_itof_mutable(upb_msgdef *m, uint32_t i) {
+  return (upb_fielddef*)upb_msgdef_itof(m, i);
+}
+
+UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m,
+                                                 const char *name, size_t len) {
+  return (upb_fielddef *)upb_msgdef_ntof(m, name, len);
+}
+
+/* Oneof lookup:
+ *   - ntoo = name to oneof
+ *   - ntooz = name to oneof, null-terminated string. */
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m,
+                                                 const char *name, size_t len) {
+  return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len);
+}
+
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m,
+                                          const char *name);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+
+/* upb_msg_field_iter i;
+ * for(upb_msg_field_begin(&i, m);
+ *     !upb_msg_field_done(&i);
+ *     upb_msg_field_next(&i)) {
+ *   upb_fielddef *f = upb_msg_iter_field(&i);
+ *   // ...
+ * }
+ *
+ * For C we don't have separate iterators for const and non-const.
+ * It is the caller's responsibility to cast the upb_fielddef* to
+ * const if the upb_msgdef* is const. */
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+
+/* Similar to above, we also support iterating through the oneofs in a
+ * msgdef. */
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter);
+
+UPB_END_EXTERN_C
+
+
+/* upb::EnumDef ***************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+#ifdef __cplusplus
+
+/* Class that represents an enum.  Its base class is upb::Def (convert with
+ * upb::upcast()). */
+class upb::EnumDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<EnumDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+  bool set_full_name(const char* fullname, Status* s);
+  bool set_full_name(const std::string& fullname, Status* s);
+
+  /* Call to freeze this EnumDef. */
+  bool Freeze(Status* s);
+
+  /* The value that is used as the default when no field default is specified.
+   * If not set explicitly, the first value that was added will be used.
+   * The default value must be a member of the enum.
+   * Requires that value_count() > 0. */
+  int32_t default_value() const;
+
+  /* Sets the default value.  If this value is not valid, returns false and an
+   * error message in status. */
+  bool set_default_value(int32_t val, Status* status);
+
+  /* Returns the number of values currently defined in the enum.  Note that
+   * multiple names can refer to the same number, so this may be greater than
+   * the total number of unique numbers. */
+  int value_count() const;
+
+  /* Adds a single name/number pair to the enum.  Fails if this name has
+   * already been used by another value. */
+  bool AddValue(const char* name, int32_t num, Status* status);
+  bool AddValue(const std::string& name, int32_t num, Status* status);
+
+  /* Lookups from name to integer, returning true if found. */
+  bool FindValueByName(const char* name, int32_t* num) const;
+
+  /* Finds the name corresponding to the given number, or NULL if none was
+   * found.  If more than one name corresponds to this number, returns the
+   * first one that was added. */
+  const char* FindValueByNumber(int32_t num) const;
+
+  /* Returns a new EnumDef with all the same values.  The new EnumDef will be
+   * owned by the given owner. */
+  EnumDef* Dup(const void* owner) const;
+
+  /* Iteration over name/value pairs.  The order is undefined.
+   * Adding an enum val invalidates any iterators.
+   *
+   * TODO: make compatible with range-for, with elements as pairs? */
+  class Iterator {
+   public:
+    explicit Iterator(const EnumDef*);
+
+    int32_t number();
+    const char *name();
+    bool Done();
+    void Next();
+
+   private:
+    upb_enum_iter iter_;
+  };
+
+ private:
+  UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_enumdef *upb_enumdef_new(const void *owner);
+upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner);
+
+/* Include upb_refcounted methods like upb_enumdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_enumdef, upb_enumdef_upcast2)
+
+bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status);
+
+/* From upb_def. */
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
+                             upb_status *s);
+
+int32_t upb_enumdef_default(const upb_enumdef *e);
+bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s);
+int upb_enumdef_numvals(const upb_enumdef *e);
+bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
+                        upb_status *status);
+
+/* Enum lookups:
+ * - ntoi:  look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton:  look up an integer, returning the name as a null-terminated
+ *          string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+                      int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+                                  const char *name, int32_t *num) {
+  return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+/*  upb_enum_iter i;
+ *  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
+ *    // ...
+ *  }
+ */
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+UPB_END_EXTERN_C
+
+/* upb::OneofDef **************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+#ifdef __cplusplus
+
+/* Class that represents a oneof.  Its base class is upb::Def (convert with
+ * upb::upcast()). */
+class upb::OneofDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<OneofDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+
+  /* Returns the MessageDef that owns this OneofDef. */
+  const MessageDef* containing_type() const;
+
+  /* Returns the name of this oneof. This is the name used to look up the oneof
+   * by name once added to a message def. */
+  const char* name() const;
+  bool set_name(const char* name, Status* s);
+
+  /* Returns the number of fields currently defined in the oneof. */
+  int field_count() const;
+
+  /* Adds a field to the oneof. The field must not have been added to any other
+   * oneof or msgdef. If the oneof is not yet part of a msgdef, then when the
+   * oneof is eventually added to a msgdef, all fields added to the oneof will
+   * also be added to the msgdef at that time. If the oneof is already part of a
+   * msgdef, the field must either be a part of that msgdef already, or must not
+   * be a part of any msgdef; in the latter case, the field is added to the
+   * msgdef as a part of this operation.
+   *
+   * The field may only have an OPTIONAL label, never REQUIRED or REPEATED.
+   *
+   * If |f| is already part of this MessageDef, this method performs no action
+   * and returns true (success). Thus, this method is idempotent. */
+  bool AddField(FieldDef* field, Status* s);
+  bool AddField(const reffed_ptr<FieldDef>& field, Status* s);
+
+  /* Looks up by name. */
+  const FieldDef* FindFieldByName(const char* name, size_t len) const;
+  FieldDef* FindFieldByName(const char* name, size_t len);
+  const FieldDef* FindFieldByName(const char* name) const {
+    return FindFieldByName(name, strlen(name));
+  }
+  FieldDef* FindFieldByName(const char* name) {
+    return FindFieldByName(name, strlen(name));
+  }
+
+  template <class T>
+  FieldDef* FindFieldByName(const T& str) {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+  template <class T>
+  const FieldDef* FindFieldByName(const T& str) const {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+
+  /* Looks up by tag number. */
+  const FieldDef* FindFieldByNumber(uint32_t num) const;
+
+  /* Returns a new OneofDef with all the same fields. The OneofDef will be owned
+   * by the given owner. */
+  OneofDef* Dup(const void* owner) const;
+
+  /* Iteration over fields.  The order is undefined. */
+  class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit iterator(OneofDef* md);
+    static iterator end(OneofDef* md);
+
+    void operator++();
+    FieldDef* operator*() const;
+    bool operator!=(const iterator& other) const;
+    bool operator==(const iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  class const_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_iterator(const OneofDef* md);
+    static const_iterator end(const OneofDef* md);
+
+    void operator++();
+    const FieldDef* operator*() const;
+    bool operator!=(const const_iterator& other) const;
+    bool operator==(const const_iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_oneofdef *upb_oneofdef_new(const void *owner);
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner);
+
+/* Include upb_refcounted methods like upb_oneofdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast2)
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s);
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s);
+
+/* Oneof lookups:
+ * - ntof:  look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof:  look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/*  upb_oneof_iter i;
+ *  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+ *    // ...
+ *  }
+ */
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+UPB_INLINE const char* upb_safecstr(const std::string& str) {
+  assert(str.size() == std::strlen(str.c_str()));
+  return str.c_str();
+}
+
+/* Inline C++ wrappers. */
+namespace upb {
+
+inline Def* Def::Dup(const void* owner) const {
+  return upb_def_dup(this, owner);
+}
+inline Def::Type Def::def_type() const { return upb_def_type(this); }
+inline const char* Def::full_name() const { return upb_def_fullname(this); }
+inline bool Def::set_full_name(const char* fullname, Status* s) {
+  return upb_def_setfullname(this, fullname, s);
+}
+inline bool Def::set_full_name(const std::string& fullname, Status* s) {
+  return upb_def_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool Def::Freeze(Def* const* defs, int n, Status* status) {
+  return upb_def_freeze(defs, n, status);
+}
+inline bool Def::Freeze(const std::vector<Def*>& defs, Status* status) {
+  return upb_def_freeze((Def* const*)&defs[0], defs.size(), status);
+}
+
+inline bool FieldDef::CheckType(int32_t val) {
+  return upb_fielddef_checktype(val);
+}
+inline bool FieldDef::CheckLabel(int32_t val) {
+  return upb_fielddef_checklabel(val);
+}
+inline bool FieldDef::CheckDescriptorType(int32_t val) {
+  return upb_fielddef_checkdescriptortype(val);
+}
+inline bool FieldDef::CheckIntegerFormat(int32_t val) {
+  return upb_fielddef_checkintfmt(val);
+}
+inline FieldDef::Type FieldDef::ConvertType(int32_t val) {
+  assert(CheckType(val));
+  return static_cast<FieldDef::Type>(val);
+}
+inline FieldDef::Label FieldDef::ConvertLabel(int32_t val) {
+  assert(CheckLabel(val));
+  return static_cast<FieldDef::Label>(val);
+}
+inline FieldDef::DescriptorType FieldDef::ConvertDescriptorType(int32_t val) {
+  assert(CheckDescriptorType(val));
+  return static_cast<FieldDef::DescriptorType>(val);
+}
+inline FieldDef::IntegerFormat FieldDef::ConvertIntegerFormat(int32_t val) {
+  assert(CheckIntegerFormat(val));
+  return static_cast<FieldDef::IntegerFormat>(val);
+}
+
+inline reffed_ptr<FieldDef> FieldDef::New() {
+  upb_fielddef *f = upb_fielddef_new(&f);
+  return reffed_ptr<FieldDef>(f, &f);
+}
+inline FieldDef* FieldDef::Dup(const void* owner) const {
+  return upb_fielddef_dup(this, owner);
+}
+inline const char* FieldDef::full_name() const {
+  return upb_fielddef_fullname(this);
+}
+inline bool FieldDef::set_full_name(const char* fullname, Status* s) {
+  return upb_fielddef_setfullname(this, fullname, s);
+}
+inline bool FieldDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_fielddef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool FieldDef::type_is_set() const {
+  return upb_fielddef_typeisset(this);
+}
+inline FieldDef::Type FieldDef::type() const { return upb_fielddef_type(this); }
+inline FieldDef::DescriptorType FieldDef::descriptor_type() const {
+  return upb_fielddef_descriptortype(this);
+}
+inline FieldDef::Label FieldDef::label() const {
+  return upb_fielddef_label(this);
+}
+inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); }
+inline const char* FieldDef::name() const { return upb_fielddef_name(this); }
+inline bool FieldDef::is_extension() const {
+  return upb_fielddef_isextension(this);
+}
+inline bool FieldDef::lazy() const {
+  return upb_fielddef_lazy(this);
+}
+inline void FieldDef::set_lazy(bool lazy) {
+  upb_fielddef_setlazy(this, lazy);
+}
+inline bool FieldDef::packed() const {
+  return upb_fielddef_packed(this);
+}
+inline void FieldDef::set_packed(bool packed) {
+  upb_fielddef_setpacked(this, packed);
+}
+inline const MessageDef* FieldDef::containing_type() const {
+  return upb_fielddef_containingtype(this);
+}
+inline const OneofDef* FieldDef::containing_oneof() const {
+  return upb_fielddef_containingoneof(this);
+}
+inline const char* FieldDef::containing_type_name() {
+  return upb_fielddef_containingtypename(this);
+}
+inline bool FieldDef::set_number(uint32_t number, Status* s) {
+  return upb_fielddef_setnumber(this, number, s);
+}
+inline bool FieldDef::set_name(const char *name, Status* s) {
+  return upb_fielddef_setname(this, name, s);
+}
+inline bool FieldDef::set_name(const std::string& name, Status* s) {
+  return upb_fielddef_setname(this, upb_safecstr(name), s);
+}
+inline bool FieldDef::set_containing_type_name(const char *name, Status* s) {
+  return upb_fielddef_setcontainingtypename(this, name, s);
+}
+inline bool FieldDef::set_containing_type_name(const std::string &name,
+                                               Status *s) {
+  return upb_fielddef_setcontainingtypename(this, upb_safecstr(name), s);
+}
+inline void FieldDef::set_type(upb_fieldtype_t type) {
+  upb_fielddef_settype(this, type);
+}
+inline void FieldDef::set_is_extension(bool is_extension) {
+  upb_fielddef_setisextension(this, is_extension);
+}
+inline void FieldDef::set_descriptor_type(FieldDef::DescriptorType type) {
+  upb_fielddef_setdescriptortype(this, type);
+}
+inline void FieldDef::set_label(upb_label_t label) {
+  upb_fielddef_setlabel(this, label);
+}
+inline bool FieldDef::IsSubMessage() const {
+  return upb_fielddef_issubmsg(this);
+}
+inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); }
+inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); }
+inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); }
+inline int64_t FieldDef::default_int64() const {
+  return upb_fielddef_defaultint64(this);
+}
+inline int32_t FieldDef::default_int32() const {
+  return upb_fielddef_defaultint32(this);
+}
+inline uint64_t FieldDef::default_uint64() const {
+  return upb_fielddef_defaultuint64(this);
+}
+inline uint32_t FieldDef::default_uint32() const {
+  return upb_fielddef_defaultuint32(this);
+}
+inline bool FieldDef::default_bool() const {
+  return upb_fielddef_defaultbool(this);
+}
+inline float FieldDef::default_float() const {
+  return upb_fielddef_defaultfloat(this);
+}
+inline double FieldDef::default_double() const {
+  return upb_fielddef_defaultdouble(this);
+}
+inline const char* FieldDef::default_string(size_t* len) const {
+  return upb_fielddef_defaultstr(this, len);
+}
+inline void FieldDef::set_default_int64(int64_t value) {
+  upb_fielddef_setdefaultint64(this, value);
+}
+inline void FieldDef::set_default_int32(int32_t value) {
+  upb_fielddef_setdefaultint32(this, value);
+}
+inline void FieldDef::set_default_uint64(uint64_t value) {
+  upb_fielddef_setdefaultuint64(this, value);
+}
+inline void FieldDef::set_default_uint32(uint32_t value) {
+  upb_fielddef_setdefaultuint32(this, value);
+}
+inline void FieldDef::set_default_bool(bool value) {
+  upb_fielddef_setdefaultbool(this, value);
+}
+inline void FieldDef::set_default_float(float value) {
+  upb_fielddef_setdefaultfloat(this, value);
+}
+inline void FieldDef::set_default_double(double value) {
+  upb_fielddef_setdefaultdouble(this, value);
+}
+inline bool FieldDef::set_default_string(const void *str, size_t len,
+                                         Status *s) {
+  return upb_fielddef_setdefaultstr(this, str, len, s);
+}
+inline bool FieldDef::set_default_string(const std::string& str, Status* s) {
+  return upb_fielddef_setdefaultstr(this, str.c_str(), str.size(), s);
+}
+inline void FieldDef::set_default_cstr(const char* str, Status* s) {
+  return upb_fielddef_setdefaultcstr(this, str, s);
+}
+inline bool FieldDef::HasSubDef() const { return upb_fielddef_hassubdef(this); }
+inline const Def* FieldDef::subdef() const { return upb_fielddef_subdef(this); }
+inline const MessageDef *FieldDef::message_subdef() const {
+  return upb_fielddef_msgsubdef(this);
+}
+inline const EnumDef *FieldDef::enum_subdef() const {
+  return upb_fielddef_enumsubdef(this);
+}
+inline const char* FieldDef::subdef_name() const {
+  return upb_fielddef_subdefname(this);
+}
+inline bool FieldDef::set_subdef(const Def* subdef, Status* s) {
+  return upb_fielddef_setsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_enum_subdef(const EnumDef* subdef, Status* s) {
+  return upb_fielddef_setenumsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_message_subdef(const MessageDef* subdef, Status* s) {
+  return upb_fielddef_setmsgsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_subdef_name(const char* name, Status* s) {
+  return upb_fielddef_setsubdefname(this, name, s);
+}
+inline bool FieldDef::set_subdef_name(const std::string& name, Status* s) {
+  return upb_fielddef_setsubdefname(this, upb_safecstr(name), s);
+}
+
+inline reffed_ptr<MessageDef> MessageDef::New() {
+  upb_msgdef *m = upb_msgdef_new(&m);
+  return reffed_ptr<MessageDef>(m, &m);
+}
+inline const char *MessageDef::full_name() const {
+  return upb_msgdef_fullname(this);
+}
+inline bool MessageDef::set_full_name(const char* fullname, Status* s) {
+  return upb_msgdef_setfullname(this, fullname, s);
+}
+inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_msgdef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool MessageDef::Freeze(Status* status) {
+  return upb_msgdef_freeze(this, status);
+}
+inline int MessageDef::field_count() const {
+  return upb_msgdef_numfields(this);
+}
+inline int MessageDef::oneof_count() const {
+  return upb_msgdef_numoneofs(this);
+}
+inline bool MessageDef::AddField(upb_fielddef* f, Status* s) {
+  return upb_msgdef_addfield(this, f, NULL, s);
+}
+inline bool MessageDef::AddField(const reffed_ptr<FieldDef>& f, Status* s) {
+  return upb_msgdef_addfield(this, f.get(), NULL, s);
+}
+inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) {
+  return upb_msgdef_addoneof(this, o, NULL, s);
+}
+inline bool MessageDef::AddOneof(const reffed_ptr<OneofDef>& o, Status* s) {
+  return upb_msgdef_addoneof(this, o.get(), NULL, s);
+}
+inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) {
+  return upb_msgdef_itof_mutable(this, number);
+}
+inline FieldDef* MessageDef::FindFieldByName(const char* name, size_t len) {
+  return upb_msgdef_ntof_mutable(this, name, len);
+}
+inline const FieldDef* MessageDef::FindFieldByNumber(uint32_t number) const {
+  return upb_msgdef_itof(this, number);
+}
+inline const FieldDef *MessageDef::FindFieldByName(const char *name,
+                                                   size_t len) const {
+  return upb_msgdef_ntof(this, name, len);
+}
+inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) {
+  return upb_msgdef_ntoo_mutable(this, name, len);
+}
+inline const OneofDef* MessageDef::FindOneofByName(const char* name,
+                                                   size_t len) const {
+  return upb_msgdef_ntoo(this, name, len);
+}
+inline MessageDef* MessageDef::Dup(const void *owner) const {
+  return upb_msgdef_dup(this, owner);
+}
+inline void MessageDef::setmapentry(bool map_entry) {
+  upb_msgdef_setmapentry(this, map_entry);
+}
+inline bool MessageDef::mapentry() const {
+  return upb_msgdef_mapentry(this);
+}
+inline MessageDef::field_iterator MessageDef::field_begin() {
+  return field_iterator(this);
+}
+inline MessageDef::field_iterator MessageDef::field_end() {
+  return field_iterator::end(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_begin() const {
+  return const_field_iterator(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_end() const {
+  return const_field_iterator::end(this);
+}
+
+inline MessageDef::oneof_iterator MessageDef::oneof_begin() {
+  return oneof_iterator(this);
+}
+inline MessageDef::oneof_iterator MessageDef::oneof_end() {
+  return oneof_iterator::end(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const {
+  return const_oneof_iterator(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const {
+  return const_oneof_iterator::end(this);
+}
+
+inline MessageDef::field_iterator::field_iterator(MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
+}
+inline MessageDef::field_iterator MessageDef::field_iterator::end(
+    MessageDef* md) {
+  MessageDef::field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline FieldDef* MessageDef::field_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void MessageDef::field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
+}
+inline bool MessageDef::field_iterator::operator==(
+    const field_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::field_iterator::operator!=(
+    const field_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::const_field_iterator::const_field_iterator(
+    const MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
+}
+inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end(
+    const MessageDef *md) {
+  MessageDef::const_field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const FieldDef* MessageDef::const_field_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void MessageDef::const_field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
+}
+inline bool MessageDef::const_field_iterator::operator==(
+    const const_field_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::const_field_iterator::operator!=(
+    const const_field_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end(
+    MessageDef* md) {
+  MessageDef::oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline OneofDef* MessageDef::oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::oneof_iterator::operator==(
+    const oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::oneof_iterator::operator!=(
+    const oneof_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::const_oneof_iterator::const_oneof_iterator(
+    const MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end(
+    const MessageDef *md) {
+  MessageDef::const_oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::const_oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator==(
+    const const_oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator!=(
+    const const_oneof_iterator &other) const {
+  return !(*this == other);
+}
+
+inline reffed_ptr<EnumDef> EnumDef::New() {
+  upb_enumdef *e = upb_enumdef_new(&e);
+  return reffed_ptr<EnumDef>(e, &e);
+}
+inline const char* EnumDef::full_name() const {
+  return upb_enumdef_fullname(this);
+}
+inline bool EnumDef::set_full_name(const char* fullname, Status* s) {
+  return upb_enumdef_setfullname(this, fullname, s);
+}
+inline bool EnumDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_enumdef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool EnumDef::Freeze(Status* status) {
+  return upb_enumdef_freeze(this, status);
+}
+inline int32_t EnumDef::default_value() const {
+  return upb_enumdef_default(this);
+}
+inline bool EnumDef::set_default_value(int32_t val, Status* status) {
+  return upb_enumdef_setdefault(this, val, status);
+}
+inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); }
+inline bool EnumDef::AddValue(const char* name, int32_t num, Status* status) {
+  return upb_enumdef_addval(this, name, num, status);
+}
+inline bool EnumDef::AddValue(const std::string& name, int32_t num,
+                              Status* status) {
+  return upb_enumdef_addval(this, upb_safecstr(name), num, status);
+}
+inline bool EnumDef::FindValueByName(const char* name, int32_t *num) const {
+  return upb_enumdef_ntoiz(this, name, num);
+}
+inline const char* EnumDef::FindValueByNumber(int32_t num) const {
+  return upb_enumdef_iton(this, num);
+}
+inline EnumDef* EnumDef::Dup(const void* owner) const {
+  return upb_enumdef_dup(this, owner);
+}
+
+inline EnumDef::Iterator::Iterator(const EnumDef* e) {
+  upb_enum_begin(&iter_, e);
+}
+inline int32_t EnumDef::Iterator::number() {
+  return upb_enum_iter_number(&iter_);
+}
+inline const char* EnumDef::Iterator::name() {
+  return upb_enum_iter_name(&iter_);
+}
+inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); }
+inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); }
+
+inline reffed_ptr<OneofDef> OneofDef::New() {
+  upb_oneofdef *o = upb_oneofdef_new(&o);
+  return reffed_ptr<OneofDef>(o, &o);
+}
+inline const char* OneofDef::full_name() const {
+  return upb_oneofdef_name(this);
+}
+
+inline const MessageDef* OneofDef::containing_type() const {
+  return upb_oneofdef_containingtype(this);
+}
+inline const char* OneofDef::name() const {
+  return upb_oneofdef_name(this);
+}
+inline bool OneofDef::set_name(const char* name, Status* s) {
+  return upb_oneofdef_setname(this, name, s);
+}
+inline int OneofDef::field_count() const {
+  return upb_oneofdef_numfields(this);
+}
+inline bool OneofDef::AddField(FieldDef* field, Status* s) {
+  return upb_oneofdef_addfield(this, field, NULL, s);
+}
+inline bool OneofDef::AddField(const reffed_ptr<FieldDef>& field, Status* s) {
+  return upb_oneofdef_addfield(this, field.get(), NULL, s);
+}
+inline const FieldDef* OneofDef::FindFieldByName(const char* name,
+                                                 size_t len) const {
+  return upb_oneofdef_ntof(this, name, len);
+}
+inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const {
+  return upb_oneofdef_itof(this, num);
+}
+inline OneofDef::iterator OneofDef::begin() { return iterator(this); }
+inline OneofDef::iterator OneofDef::end() { return iterator::end(this); }
+inline OneofDef::const_iterator OneofDef::begin() const {
+  return const_iterator(this);
+}
+inline OneofDef::const_iterator OneofDef::end() const {
+  return const_iterator::end(this);
+}
+
+inline OneofDef::iterator::iterator(OneofDef* o) {
+  upb_oneof_begin(&iter_, o);
+}
+inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) {
+  OneofDef::iterator iter(o);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline FieldDef* OneofDef::iterator::operator*() const {
+  return upb_oneof_iter_field(&iter_);
+}
+inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); }
+inline bool OneofDef::iterator::operator==(const iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::iterator::operator!=(const iterator &other) const {
+  return !(*this == other);
+}
+
+inline OneofDef::const_iterator::const_iterator(const OneofDef* md) {
+  upb_oneof_begin(&iter_, md);
+}
+inline OneofDef::const_iterator OneofDef::const_iterator::end(
+    const OneofDef *md) {
+  OneofDef::const_iterator iter(md);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const FieldDef* OneofDef::const_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void OneofDef::const_iterator::operator++() {
+  return upb_oneof_next(&iter_);
+}
+inline bool OneofDef::const_iterator::operator==(
+    const const_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::const_iterator::operator!=(
+    const const_iterator &other) const {
+  return !(*this == other);
+}
+
+}  /* namespace upb */
+#endif
+
+#endif /* UPB_DEF_H_ */
+/*
+** This file contains definitions of structs that should be considered private
+** and NOT stable across versions of upb.
+**
+** The only reason they are declared here and not in .c files is to allow upb
+** and the application (if desired) to embed statically-initialized instances
+** of structures like defs.
+**
+** If you include this file, all guarantees of ABI compatibility go out the
+** window!  Any code that includes this file needs to recompile against the
+** exact same version of upb that they are linking against.
+**
+** You also need to recompile if you change the value of the UPB_DEBUG_REFS
+** flag.
+*/
+
+
+#ifndef UPB_STATICINIT_H_
+#define UPB_STATICINIT_H_
+
+#ifdef __cplusplus
+/* Because of how we do our typedefs, this header can't be included from C++. */
+#error This file cannot be included from C++
+#endif
+
+/* upb_refcounted *************************************************************/
+
+
+/* upb_def ********************************************************************/
+
+struct upb_def {
+  upb_refcounted base;
+
+  const char *fullname;
+  char type;  /* A upb_deftype_t (char to save space) */
+
+  /* Used as a flag during the def's mutable stage.  Must be false unless
+   * it is currently being used by a function on the stack.  This allows
+   * us to easily determine which defs were passed into the function's
+   * current invocation. */
+  bool came_from_user;
+};
+
+#define UPB_DEF_INIT(name, type, refs, ref2s) \
+    { UPB_REFCOUNT_INIT(refs, ref2s), name, type, false }
+
+
+/* upb_fielddef ***************************************************************/
+
+struct upb_fielddef {
+  upb_def base;
+
+  union {
+    int64_t sint;
+    uint64_t uint;
+    double dbl;
+    float flt;
+    void *bytes;
+  } defaultval;
+  union {
+    const upb_msgdef *def;  /* If !msg_is_symbolic. */
+    char *name;             /* If msg_is_symbolic. */
+  } msg;
+  union {
+    const upb_def *def;  /* If !subdef_is_symbolic. */
+    char *name;          /* If subdef_is_symbolic. */
+  } sub;  /* The msgdef or enumdef for this field, if upb_hassubdef(f). */
+  bool subdef_is_symbolic;
+  bool msg_is_symbolic;
+  const upb_oneofdef *oneof;
+  bool default_is_string;
+  bool type_is_set_;     /* False until type is explicitly set. */
+  bool is_extension_;
+  bool lazy_;
+  bool packed_;
+  upb_intfmt_t intfmt;
+  bool tagdelim;
+  upb_fieldtype_t type_;
+  upb_label_t label_;
+  uint32_t number_;
+  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
+  uint32_t index_;
+};
+
+#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy,   \
+                          packed, name, num, msgdef, subdef, selector_base,    \
+                          index, defaultval, refs, ref2s)                      \
+  {                                                                            \
+    UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef},      \
+        {subdef}, NULL, false, false,                                          \
+        type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \
+        lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \
+  }
+
+
+/* upb_msgdef *****************************************************************/
+
+struct upb_msgdef {
+  upb_def base;
+
+  size_t selector_count;
+  uint32_t submsg_field_count;
+
+  /* Tables for looking up fields by number and name. */
+  upb_inttable itof;  /* int to field */
+  upb_strtable ntof;  /* name to field */
+
+  /* Tables for looking up oneofs by name. */
+  upb_strtable ntoo;  /* name to oneof */
+
+  /* Is this a map-entry message?
+   * TODO: set this flag properly for static descriptors; regenerate
+   * descriptor.upb.c. */
+  bool map_entry;
+
+  /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+/* TODO: also support static initialization of the oneofs table. This will be
+ * needed if we compile in descriptors that contain oneofs. */
+#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \
+                        refs, ref2s)                                          \
+  {                                                                           \
+    UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count,             \
+        submsg_field_count, itof, ntof,                                       \
+        UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false                         \
+  }
+
+
+/* upb_enumdef ****************************************************************/
+
+struct upb_enumdef {
+  upb_def base;
+
+  upb_strtable ntoi;
+  upb_inttable iton;
+  int32_t defaultval;
+};
+
+#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \
+  { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntoi, iton, defaultval }
+
+
+/* upb_oneofdef ***************************************************************/
+
+struct upb_oneofdef {
+  upb_def base;
+
+  upb_strtable ntof;
+  upb_inttable itof;
+  const upb_msgdef *parent;
+};
+
+#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \
+  { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof }
+
+
+/* upb_symtab *****************************************************************/
+
+struct upb_symtab {
+  upb_refcounted base;
+
+  upb_strtable symtab;
+};
+
+#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \
+  { UPB_REFCOUNT_INIT(refs, ref2s), symtab }
+
+
+#endif  /* UPB_STATICINIT_H_ */
+/*
+** upb::Handlers (upb_handlers)
+**
+** A upb_handlers is like a virtual table for a upb_msgdef.  Each field of the
+** message can have associated functions that will be called when we are
+** parsing or visiting a stream of data.  This is similar to how handlers work
+** in SAX (the Simple API for XML).
+**
+** The handlers have no idea where the data is coming from, so a single set of
+** handlers could be used with two completely different data sources (for
+** example, a parser and a visitor over in-memory objects).  This decoupling is
+** the most important feature of upb, because it allows parsers and serializers
+** to be highly reusable.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_HANDLERS_H
+#define UPB_HANDLERS_H
+
+
+#ifdef __cplusplus
+namespace upb {
+class BufferHandle;
+class BytesHandler;
+class HandlerAttributes;
+class Handlers;
+template <class T> class Handler;
+template <class T> struct CanonicalType;
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle)
+UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler)
+UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr)
+UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted,
+                         upb_handlers, upb_refcounted)
+
+/* The maximum depth that the handler graph can have.  This is a resource limit
+ * for the C stack since we sometimes need to recursively traverse the graph.
+ * Cycles are ok; the traversal will stop when it detects a cycle, but we must
+ * hit the cycle before the maximum depth is reached.
+ *
+ * If having a single static limit is too inflexible, we can add another variant
+ * of Handlers::Freeze that allows specifying this as a parameter. */
+#define UPB_MAX_HANDLER_DEPTH 64
+
+/* All the different types of handlers that can be registered.
+ * Only needed for the advanced functions in upb::Handlers. */
+typedef enum {
+  UPB_HANDLER_INT32,
+  UPB_HANDLER_INT64,
+  UPB_HANDLER_UINT32,
+  UPB_HANDLER_UINT64,
+  UPB_HANDLER_FLOAT,
+  UPB_HANDLER_DOUBLE,
+  UPB_HANDLER_BOOL,
+  UPB_HANDLER_STARTSTR,
+  UPB_HANDLER_STRING,
+  UPB_HANDLER_ENDSTR,
+  UPB_HANDLER_STARTSUBMSG,
+  UPB_HANDLER_ENDSUBMSG,
+  UPB_HANDLER_STARTSEQ,
+  UPB_HANDLER_ENDSEQ
+} upb_handlertype_t;
+
+#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
+
+#define UPB_BREAK NULL
+
+/* A convenient definition for when no closure is needed. */
+extern char _upb_noclosure;
+#define UPB_NO_CLOSURE &_upb_noclosure
+
+/* A selector refers to a specific field handler in the Handlers object
+ * (for example: the STARTSUBMSG handler for field "field15"). */
+typedef int32_t upb_selector_t;
+
+UPB_BEGIN_EXTERN_C
+
+/* Forward-declares for C inline accessors.  We need to declare these here
+ * so we can "friend" them in the class declarations in C++. */
+UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
+                                             upb_selector_t s);
+UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr);
+UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+                                                   upb_selector_t s);
+
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h);
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+                                     const void *type);
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+                                     size_t ofs);
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h);
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h);
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h);
+
+UPB_END_EXTERN_C
+
+
+/* Static selectors for upb::Handlers. */
+#define UPB_STARTMSG_SELECTOR 0
+#define UPB_ENDMSG_SELECTOR 1
+#define UPB_STATIC_SELECTOR_COUNT 2
+
+/* Static selectors for upb::BytesHandler. */
+#define UPB_STARTSTR_SELECTOR 0
+#define UPB_STRING_SELECTOR 1
+#define UPB_ENDSTR_SELECTOR 2
+
+typedef void upb_handlerfree(void *d);
+
+#ifdef __cplusplus
+
+/* A set of attributes that accompanies a handler's function pointer. */
+class upb::HandlerAttributes {
+ public:
+  HandlerAttributes();
+  ~HandlerAttributes();
+
+  /* Sets the handler data that will be passed as the second parameter of the
+   * handler.  To free this pointer when the handlers are freed, call
+   * Handlers::AddCleanup(). */
+  bool SetHandlerData(const void *handler_data);
+  const void* handler_data() const;
+
+  /* Use this to specify the type of the closure.  This will be checked against
+   * all other closure types for handler that use the same closure.
+   * Registration will fail if this does not match all other non-NULL closure
+   * types. */
+  bool SetClosureType(const void *closure_type);
+  const void* closure_type() const;
+
+  /* Use this to specify the type of the returned closure.  Only used for
+   * Start*{String,SubMessage,Sequence} handlers.  This must match the closure
+   * type of any handlers that use it (for example, the StringBuf handler must
+   * match the closure returned from StartString). */
+  bool SetReturnClosureType(const void *return_closure_type);
+  const void* return_closure_type() const;
+
+  /* Set to indicate that the handler always returns "ok" (either "true" or a
+   * non-NULL closure).  This is a hint that can allow code generators to
+   * generate more efficient code. */
+  bool SetAlwaysOk(bool always_ok);
+  bool always_ok() const;
+
+ private:
+  friend UPB_INLINE const void * ::upb_handlerattr_handlerdata(
+      const upb_handlerattr *attr);
+#else
+struct upb_handlerattr {
+#endif
+  const void *handler_data_;
+  const void *closure_type_;
+  const void *return_closure_type_;
+  bool alwaysok_;
+};
+
+#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false}
+
+typedef struct {
+  upb_func *func;
+
+  /* It is wasteful to include the entire attributes here:
+   *
+   * * Some of the information is redundant (like storing the closure type
+   *   separately for each handler that must match).
+   * * Some of the info is only needed prior to freeze() (like closure types).
+   * * alignment padding wastes a lot of space for alwaysok_.
+   *
+   * If/when the size and locality of handlers is an issue, we can optimize this
+   * not to store the entire attr like this.  We do not expose the table's
+   * layout to allow this optimization in the future. */
+  upb_handlerattr attr;
+} upb_handlers_tabent;
+
+#ifdef __cplusplus
+
+/* Extra information about a buffer that is passed to a StringBuf handler.
+ * TODO(haberman): allow the handle to be pinned so that it will outlive
+ * the handler invocation. */
+class upb::BufferHandle {
+ public:
+  BufferHandle();
+  ~BufferHandle();
+
+  /* The beginning of the buffer.  This may be different than the pointer
+   * passed to a StringBuf handler because the handler may receive data
+   * that is from the middle or end of a larger buffer. */
+  const char* buffer() const;
+
+  /* The offset within the attached object where this buffer begins.  Only
+   * meaningful if there is an attached object. */
+  size_t object_offset() const;
+
+  /* Note that object_offset is the offset of "buf" within the attached
+   * object. */
+  void SetBuffer(const char* buf, size_t object_offset);
+
+  /* The BufferHandle can have an "attached object", which can be used to
+   * tunnel through a pointer to the buffer's underlying representation. */
+  template <class T>
+  void SetAttachedObject(const T* obj);
+
+  /* Returns NULL if the attached object is not of this type. */
+  template <class T>
+  const T* GetAttachedObject() const;
+
+ private:
+  friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h);
+  friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h,
+                                                const void *obj,
+                                                const void *type);
+  friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h,
+                                                const char *buf, size_t ofs);
+  friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h);
+  friend UPB_INLINE const void* ::upb_bufhandle_objtype(
+      const upb_bufhandle *h);
+  friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h);
+#else
+struct upb_bufhandle {
+#endif
+  const char *buf_;
+  const void *obj_;
+  const void *objtype_;
+  size_t objofs_;
+};
+
+#ifdef __cplusplus
+
+/* A upb::Handlers object represents the set of handlers associated with a
+ * message in the graph of messages.  You can think of it as a big virtual
+ * table with functions corresponding to all the events that can fire while
+ * parsing or visiting a message of a specific type.
+ *
+ * Any handlers that are not set behave as if they had successfully consumed
+ * the value.  Any unset Start* handlers will propagate their closure to the
+ * inner frame.
+ *
+ * The easiest way to create the *Handler objects needed by the Set* methods is
+ * with the UpbBind() and UpbMakeHandler() macros; see below. */
+class upb::Handlers {
+ public:
+  typedef upb_selector_t Selector;
+  typedef upb_handlertype_t Type;
+
+  typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
+  typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
+  typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
+  typedef Handler<bool (*)(void *, const void *, Status*)> EndMessageHandler;
+  typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
+  typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
+                             const BufferHandle *)> StringHandler;
+
+  template <class T> struct ValueHandler {
+    typedef Handler<bool(*)(void *, const void *, T)> H;
+  };
+
+  typedef ValueHandler<int32_t>::H     Int32Handler;
+  typedef ValueHandler<int64_t>::H     Int64Handler;
+  typedef ValueHandler<uint32_t>::H    UInt32Handler;
+  typedef ValueHandler<uint64_t>::H    UInt64Handler;
+  typedef ValueHandler<float>::H       FloatHandler;
+  typedef ValueHandler<double>::H      DoubleHandler;
+  typedef ValueHandler<bool>::H        BoolHandler;
+
+  /* Any function pointer can be converted to this and converted back to its
+   * correct type. */
+  typedef void GenericFunction();
+
+  typedef void HandlersCallback(const void *closure, upb_handlers *h);
+
+  /* Returns a new handlers object for the given frozen msgdef.
+   * Returns NULL if memory allocation failed. */
+  static reffed_ptr<Handlers> New(const MessageDef *m);
+
+  /* Convenience function for registering a graph of handlers that mirrors the
+   * graph of msgdefs for some message.  For "m" and all its children a new set
+   * of handlers will be created and the given callback will be invoked,
+   * allowing the client to register handlers for this message.  Note that any
+   * subhandlers set by the callback will be overwritten. */
+  static reffed_ptr<const Handlers> NewFrozen(const MessageDef *m,
+                                              HandlersCallback *callback,
+                                              const void *closure);
+
+  /* Functionality from upb::RefCounted. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* All handler registration functions return bool to indicate success or
+   * failure; details about failures are stored in this status object.  If a
+   * failure does occur, it must be cleared before the Handlers are frozen,
+   * otherwise the freeze() operation will fail.  The functions may *only* be
+   * used while the Handlers are mutable. */
+  const Status* status();
+  void ClearError();
+
+  /* Call to freeze these Handlers.  Requires that any SubHandlers are already
+   * frozen.  For cycles, you must use the static version below and freeze the
+   * whole graph at once. */
+  bool Freeze(Status* s);
+
+  /* Freezes the given set of handlers.  You may not freeze a handler without
+   * also freezing any handlers they point to. */
+  static bool Freeze(Handlers*const* handlers, int n, Status* s);
+  static bool Freeze(const std::vector<Handlers*>& handlers, Status* s);
+
+  /* Returns the msgdef associated with this handlers object. */
+  const MessageDef* message_def() const;
+
+  /* Adds the given pointer and function to the list of cleanup functions that
+   * will be run when these handlers are freed.  If this pointer has previously
+   * been registered, the function returns false and does nothing. */
+  bool AddCleanup(void *ptr, upb_handlerfree *cleanup);
+
+  /* Sets the startmsg handler for the message, which is defined as follows:
+   *
+   *   bool startmsg(MyType* closure) {
+   *     // Called when the message begins.  Returns true if processing should
+   *     // continue.
+   *     return true;
+   *   }
+   */
+  bool SetStartMessageHandler(const StartMessageHandler& handler);
+
+  /* Sets the endmsg handler for the message, which is defined as follows:
+   *
+   *   bool endmsg(MyType* closure, upb_status *status) {
+   *     // Called when processing of this message ends, whether in success or
+   *     // failure.  "status" indicates the final status of processing, and
+   *     // can also be modified in-place to update the final status.
+   *   }
+   */
+  bool SetEndMessageHandler(const EndMessageHandler& handler);
+
+  /* Sets the value handler for the given field, which is defined as follows
+   * (this is for an int32 field; other field types will pass their native
+   * C/C++ type for "val"):
+   *
+   *   bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
+   *     // Called when the field's value is encountered.  "d" contains
+   *     // whatever data was bound to this field when it was registered.
+   *     // Returns true if processing should continue.
+   *     return true;
+   *   }
+   *
+   *   handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
+   *
+   * The value type must exactly match f->type().
+   * For example, a handler that takes an int32_t parameter may only be used for
+   * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
+   *
+   * Returns false if the handler failed to register; in this case the cleanup
+   * handler (if any) will be called immediately.
+   */
+  bool SetInt32Handler (const FieldDef* f,  const Int32Handler& h);
+  bool SetInt64Handler (const FieldDef* f,  const Int64Handler& h);
+  bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h);
+  bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h);
+  bool SetFloatHandler (const FieldDef* f,  const FloatHandler& h);
+  bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h);
+  bool SetBoolHandler  (const FieldDef* f,   const BoolHandler& h);
+
+  /* Like the previous, but templated on the type on the value (ie. int32).
+   * This is mostly useful to call from other templates.  To call this you must
+   * specify the template parameter explicitly, ie:
+   *   h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
+  template <class T>
+  bool SetValueHandler(
+      const FieldDef *f,
+      const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler);
+
+  /* Sets handlers for a string field, which are defined as follows:
+   *
+   *   MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
+   *                          size_t size_hint) {
+   *     // Called when a string value begins.  The return value indicates the
+   *     // closure for the string.  "size_hint" indicates the size of the
+   *     // string if it is known, however if the string is length-delimited
+   *     // and the end-of-string is not available size_hint will be zero.
+   *     // This case is indistinguishable from the case where the size is
+   *     // known to be zero.
+   *     //
+   *     // TODO(haberman): is it important to distinguish these cases?
+   *     // If we had ssize_t as a type we could make -1 "unknown", but
+   *     // ssize_t is POSIX (not ANSI) and therefore less portable.
+   *     // In practice I suspect it won't be important to distinguish.
+   *     return closure;
+   *   }
+   *
+   *   size_t str(MyClosure* closure, const MyHandlerData* d,
+   *              const char *str, size_t len) {
+   *     // Called for each buffer of string data; the multiple physical buffers
+   *     // are all part of the same logical string.  The return value indicates
+   *     // how many bytes were consumed.  If this number is less than "len",
+   *     // this will also indicate that processing should be halted for now,
+   *     // like returning false or UPB_BREAK from any other callback.  If
+   *     // number is greater than "len", the excess bytes will be skipped over
+   *     // and not passed to the callback.
+   *     return len;
+   *   }
+   *
+   *   bool endstr(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a string value ends.  Return value indicates whether
+   *     // processing should continue.
+   *     return true;
+   *   }
+   */
+  bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h);
+  bool SetStringHandler(const FieldDef* f, const StringHandler& h);
+  bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h);
+
+  /* Sets the startseq handler, which is defined as follows:
+   *
+   *   MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a sequence (repeated field) begins.  The returned
+   *     // pointer indicates the closure for the sequence (or UPB_BREAK
+   *     // to interrupt processing).
+   *     return closure;
+   *   }
+   *
+   *   h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * repeated field.
+   */
+  bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h);
+
+  /* Sets the startsubmsg handler for the given field, which is defined as
+   * follows:
+   *
+   *   MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a submessage begins.  The returned pointer indicates the
+   *     // closure for the sequence (or UPB_BREAK to interrupt processing).
+   *     return closure;
+   *   }
+   *
+   *   h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
+   *                                           new MyHandlerData(...)));
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * submessage/group field.
+   */
+  bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h);
+
+  /* Sets the endsubmsg handler for the given field, which is defined as
+   * follows:
+   *
+   *   bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a submessage ends.  Returns true to continue processing.
+   *     return true;
+   *   }
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * submessage/group field.
+   */
+  bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h);
+
+  /* Starts the endsubseq handler for the given field, which is defined as
+   * follows:
+   *
+   *   bool endseq(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a sequence ends.  Returns true continue processing.
+   *     return true;
+   *   }
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * repeated field.
+   */
+  bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h);
+
+  /* Sets or gets the object that specifies handlers for the given field, which
+   * must be a submessage or group.  Returns NULL if no handlers are set. */
+  bool SetSubHandlers(const FieldDef* f, const Handlers* sub);
+  const Handlers* GetSubHandlers(const FieldDef* f) const;
+
+  /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the
+   * field. */
+  const Handlers* GetSubHandlers(Selector startsubmsg) const;
+
+  /* A selector refers to a specific field handler in the Handlers object
+   * (for example: the STARTSUBMSG handler for field "field15").
+   * On success, returns true and stores the selector in "s".
+   * If the FieldDef or Type are invalid, returns false.
+   * The returned selector is ONLY valid for Handlers whose MessageDef
+   * contains this FieldDef. */
+  static bool GetSelector(const FieldDef* f, Type type, Selector* s);
+
+  /* Given a START selector of any kind, returns the corresponding END selector. */
+  static Selector GetEndSelector(Selector start_selector);
+
+  /* Returns the function pointer for this handler.  It is the client's
+   * responsibility to cast to the correct function type before calling it. */
+  GenericFunction* GetHandler(Selector selector);
+
+  /* Sets the given attributes to the attributes for this selector. */
+  bool GetAttributes(Selector selector, HandlerAttributes* attr);
+
+  /* Returns the handler data that was registered with this handler. */
+  const void* GetHandlerData(Selector selector);
+
+  /* Could add any of the following functions as-needed, with some minor
+   * implementation changes:
+   *
+   * const FieldDef* GetFieldDef(Selector selector);
+   * static bool IsSequence(Selector selector); */
+
+ private:
+  UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers)
+
+  friend UPB_INLINE GenericFunction *::upb_handlers_gethandler(
+      const upb_handlers *h, upb_selector_t s);
+  friend UPB_INLINE const void *::upb_handlers_gethandlerdata(
+      const upb_handlers *h, upb_selector_t s);
+#else
+struct upb_handlers {
+#endif
+  upb_refcounted base;
+
+  const upb_msgdef *msg;
+  const upb_handlers **sub;
+  const void *top_closure_type;
+  upb_inttable cleanup_;
+  upb_status status_;  /* Used only when mutable. */
+  upb_handlers_tabent table[1];  /* Dynamically-sized field handler array. */
+};
+
+#ifdef __cplusplus
+
+namespace upb {
+
+/* Convenience macros for creating a Handler object that is wrapped with a
+ * type-safe wrapper function that converts the "void*" parameters/returns
+ * of the underlying C API into nice C++ function.
+ *
+ * Sample usage:
+ *   void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
+ *     // do stuff ...
+ *   }
+ *
+ *   // Handler that doesn't need any data bound to it.
+ *   void OnValue2(MyClosure* c, int32_t val) {
+ *     // do stuff ...
+ *   }
+ *
+ *   // Handler that returns bool so it can return failure if necessary.
+ *   bool OnValue3(MyClosure* c, int32_t val) {
+ *     // do stuff ...
+ *     return ok;
+ *   }
+ *
+ *   // Member function handler.
+ *   class MyClosure {
+ *    public:
+ *     void OnValue(int32_t val) {
+ *       // do stuff ...
+ *     }
+ *   };
+ *
+ *   // Takes ownership of the MyHandlerData.
+ *   handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
+ *   handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
+ *   handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
+ *   handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
+ */
+
+#ifdef UPB_CXX11
+
+/* In C++11, the "template" disambiguator can appear even outside templates,
+ * so all calls can safely use this pair of macros. */
+
+#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
+
+/* We have to be careful to only evaluate "d" once. */
+#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+
+#else
+
+/* Prior to C++11, the "template" disambiguator may only appear inside a
+ * template, so the regular macro must not use "template" */
+
+#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc<f>()
+
+#define UpbBind(f, d) upb::MatchFunc(f).GetFunc<f>((d))
+
+#endif  /* UPB_CXX11 */
+
+/* This macro must be used in C++98 for calls from inside a template.  But we
+ * define this variant in all cases; code that wants to be compatible with both
+ * C++98 and C++11 should always use this macro when calling from a template. */
+#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc<f>()
+
+/* We have to be careful to only evaluate "d" once. */
+#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+
+/* Handler: a struct that contains the (handler, data, deleter) tuple that is
+ * used to register all handlers.  Users can Make() these directly but it's
+ * more convenient to use the UpbMakeHandler/UpbBind macros above. */
+template <class T> class Handler {
+ public:
+  /* The underlying, handler function signature that upb uses internally. */
+  typedef T FuncPtr;
+
+  /* Intentionally implicit. */
+  template <class F> Handler(F func);
+  ~Handler();
+
+ private:
+  void AddCleanup(Handlers* h) const {
+    if (cleanup_func_) {
+      bool ok = h->AddCleanup(cleanup_data_, cleanup_func_);
+      UPB_ASSERT_VAR(ok, ok);
+    }
+  }
+
+  UPB_DISALLOW_COPY_AND_ASSIGN(Handler)
+  friend class Handlers;
+  FuncPtr handler_;
+  mutable HandlerAttributes attr_;
+  mutable bool registered_;
+  void *cleanup_data_;
+  upb_handlerfree *cleanup_func_;
+};
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+
+/* Handler function typedefs. */
+typedef bool upb_startmsg_handlerfunc(void *c, const void*);
+typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
+typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
+typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
+typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
+typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
+typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
+typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
+typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
+typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
+                                       size_t size_hint);
+typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
+                                      size_t n, const upb_bufhandle* handle);
+
+/* upb_bufhandle */
+size_t upb_bufhandle_objofs(const upb_bufhandle *h);
+
+/* upb_handlerattr */
+void upb_handlerattr_init(upb_handlerattr *attr);
+void upb_handlerattr_uninit(upb_handlerattr *attr);
+
+bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd);
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type);
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+                                          const void *type);
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok);
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr);
+
+UPB_INLINE const void *upb_handlerattr_handlerdata(
+    const upb_handlerattr *attr) {
+  return attr->handler_data_;
+}
+
+/* upb_handlers */
+typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
+upb_handlers *upb_handlers_new(const upb_msgdef *m,
+                               const void *owner);
+const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
+                                           const void *owner,
+                                           upb_handlers_callback *callback,
+                                           const void *closure);
+
+/* Include refcounted methods like upb_handlers_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast)
+
+const upb_status *upb_handlers_status(upb_handlers *h);
+void upb_handlers_clearerr(upb_handlers *h);
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
+bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
+
+bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
+                           upb_int32_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
+                           upb_int64_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
+                            upb_uint32_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
+                            upb_uint64_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
+                           upb_float_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
+                            upb_double_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
+                          upb_bool_handlerfunc *func,
+                          upb_handlerattr *attr);
+bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
+                              upb_startstr_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
+                            upb_string_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
+                            upb_endfield_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
+                              upb_startfield_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
+                                 upb_startfield_handlerfunc *func,
+                                 upb_handlerattr *attr);
+bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
+                               upb_endfield_handlerfunc *func,
+                               upb_handlerattr *attr);
+bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
+                            upb_endfield_handlerfunc *func,
+                            upb_handlerattr *attr);
+
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+                                 const upb_handlers *sub);
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+                                                const upb_fielddef *f);
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+                                                    upb_selector_t sel);
+
+UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
+                                             upb_selector_t s) {
+  return (upb_func *)h->table[s].func;
+}
+
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
+                          upb_handlerattr *attr);
+
+UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+                                                   upb_selector_t s) {
+  return upb_handlerattr_handlerdata(&h->table[s].attr);
+}
+
+#ifdef __cplusplus
+
+/* Handler types for single fields.
+ * Right now we only have one for TYPE_BYTES but ones for other types
+ * should follow.
+ *
+ * These follow the same handlers protocol for fields of a message. */
+class upb::BytesHandler {
+ public:
+  BytesHandler();
+  ~BytesHandler();
+#else
+struct upb_byteshandler {
+#endif
+  upb_handlers_tabent table[3];
+};
+
+void upb_byteshandler_init(upb_byteshandler *h);
+
+/* Caller must ensure that "d" outlives the handlers.
+ * TODO(haberman): should this have a "freeze" operation?  It's not necessary
+ * for memory management, but could be useful to force immutability and provide
+ * a convenient moment to verify that all registration succeeded. */
+bool upb_byteshandler_setstartstr(upb_byteshandler *h,
+                                  upb_startstr_handlerfunc *func, void *d);
+bool upb_byteshandler_setstring(upb_byteshandler *h,
+                                upb_string_handlerfunc *func, void *d);
+bool upb_byteshandler_setendstr(upb_byteshandler *h,
+                                upb_endfield_handlerfunc *func, void *d);
+
+/* "Static" methods */
+bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s);
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+                              upb_selector_t *s);
+UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
+  return start + 1;
+}
+
+/* Internal-only. */
+uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
+uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
+
+UPB_END_EXTERN_C
+
+/*
+** Inline definitions for handlers.h, which are particularly long and a bit
+** tricky.
+*/
+
+#ifndef UPB_HANDLERS_INL_H_
+#define UPB_HANDLERS_INL_H_
+
+#include <limits.h>
+
+/* C inline methods. */
+
+/* upb_bufhandle */
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) {
+  h->obj_ = NULL;
+  h->objtype_ = NULL;
+  h->buf_ = NULL;
+  h->objofs_ = 0;
+}
+UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) {
+  UPB_UNUSED(h);
+}
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+                                     const void *type) {
+  h->obj_ = obj;
+  h->objtype_ = type;
+}
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+                                     size_t ofs) {
+  h->buf_ = buf;
+  h->objofs_ = ofs;
+}
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) {
+  return h->obj_;
+}
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) {
+  return h->objtype_;
+}
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) {
+  return h->buf_;
+}
+
+
+#ifdef __cplusplus
+
+/* Type detection and typedefs for integer types.
+ * For platforms where there are multiple 32-bit or 64-bit types, we need to be
+ * able to enumerate them so we can properly create overloads for all variants.
+ *
+ * If any platform existed where there were three integer types with the same
+ * size, this would have to become more complicated.  For example, short, int,
+ * and long could all be 32-bits.  Even more diabolically, short, int, long,
+ * and long long could all be 64 bits and still be standard-compliant.
+ * However, few platforms are this strange, and it's unlikely that upb will be
+ * used on the strangest ones. */
+
+/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
+ * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
+ * of stdint.h.  We can't guarantee that someone else didn't include these first
+ * without defining __STDC_LIMIT_MACROS. */
+#define UPB_INT32_MAX 0x7fffffffLL
+#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
+#define UPB_INT64_MAX 0x7fffffffffffffffLL
+#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
+
+#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
+#define UPB_INT_IS_32BITS 1
+#endif
+
+#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
+#define UPB_LONG_IS_32BITS 1
+#endif
+
+#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
+#define UPB_LONG_IS_64BITS 1
+#endif
+
+#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
+#define UPB_LLONG_IS_64BITS 1
+#endif
+
+/* We use macros instead of typedefs so we can undefine them later and avoid
+ * leaking them outside this header file. */
+#if UPB_INT_IS_32BITS
+#define UPB_INT32_T int
+#define UPB_UINT32_T unsigned int
+
+#if UPB_LONG_IS_32BITS
+#define UPB_TWO_32BIT_TYPES 1
+#define UPB_INT32ALT_T long
+#define UPB_UINT32ALT_T unsigned long
+#endif  /* UPB_LONG_IS_32BITS */
+
+#elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
+#define UPB_INT32_T long
+#define UPB_UINT32_T unsigned long
+#endif  /* UPB_INT_IS_32BITS */
+
+
+#if UPB_LONG_IS_64BITS
+#define UPB_INT64_T long
+#define UPB_UINT64_T unsigned long
+
+#if UPB_LLONG_IS_64BITS
+#define UPB_TWO_64BIT_TYPES 1
+#define UPB_INT64ALT_T long long
+#define UPB_UINT64ALT_T unsigned long long
+#endif  /* UPB_LLONG_IS_64BITS */
+
+#elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
+#define UPB_INT64_T long long
+#define UPB_UINT64_T unsigned long long
+#endif  /* UPB_LONG_IS_64BITS */
+
+#undef UPB_INT32_MAX
+#undef UPB_INT32_MIN
+#undef UPB_INT64_MAX
+#undef UPB_INT64_MIN
+#undef UPB_INT_IS_32BITS
+#undef UPB_LONG_IS_32BITS
+#undef UPB_LONG_IS_64BITS
+#undef UPB_LLONG_IS_64BITS
+
+
+namespace upb {
+
+typedef void CleanupFunc(void *ptr);
+
+/* Template to remove "const" from "const T*" and just return "T*".
+ *
+ * We define a nonsense default because otherwise it will fail to instantiate as
+ * a function parameter type even in cases where we don't expect any caller to
+ * actually match the overload. */
+class CouldntRemoveConst {};
+template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
+template <class T> struct remove_constptr<const T *> { typedef T *type; };
+
+/* Template that we use below to remove a template specialization from
+ * consideration if it matches a specific type. */
+template <class T, class U> struct disable_if_same { typedef void Type; };
+template <class T> struct disable_if_same<T, T> {};
+
+template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
+
+template <class T1, class T2>
+struct FirstUnlessVoidOrBool {
+  typedef T1 value;
+};
+
+template <class T2>
+struct FirstUnlessVoidOrBool<void, T2> {
+  typedef T2 value;
+};
+
+template <class T2>
+struct FirstUnlessVoidOrBool<bool, T2> {
+  typedef T2 value;
+};
+
+template<class T, class U>
+struct is_same {
+  static bool value;
+};
+
+template<class T>
+struct is_same<T, T> {
+  static bool value;
+};
+
+template<class T, class U>
+bool is_same<T, U>::value = false;
+
+template<class T>
+bool is_same<T, T>::value = true;
+
+/* FuncInfo *******************************************************************/
+
+/* Info about the user's original, pre-wrapped function. */
+template <class C, class R = void>
+struct FuncInfo {
+  /* The type of the closure that the function takes (its first param). */
+  typedef C Closure;
+
+  /* The return type. */
+  typedef R Return;
+};
+
+/* Func ***********************************************************************/
+
+/* Func1, Func2, Func3: Template classes representing a function and its
+ * signature.
+ *
+ * Since the function is a template parameter, calling the function can be
+ * inlined at compile-time and does not require a function pointer at runtime.
+ * These functions are not bound to a handler data so have no data or cleanup
+ * handler. */
+struct UnboundFunc {
+  CleanupFunc *GetCleanup() { return NULL; }
+  void *GetData() { return NULL; }
+};
+
+template <class R, class P1, R F(P1), class I>
+struct Func1 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1) { return F(p1); }
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct Func2 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2) { return F(p1, p2); }
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
+struct Func3 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I>
+struct Func4 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I>
+struct Func5 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    return F(p1, p2, p3, p4, p5);
+  }
+};
+
+/* BoundFunc ******************************************************************/
+
+/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
+ * shall be bound to the function's second parameter.
+ * 
+ * Note that the second parameter is a const pointer, but our stored bound value
+ * is non-const so we can free it when the handlers are destroyed. */
+template <class T>
+struct BoundFunc {
+  typedef typename remove_constptr<T>::type MutableP2;
+  explicit BoundFunc(MutableP2 data_) : data(data_) {}
+  CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
+  MutableP2 GetData() { return data; }
+  MutableP2 data;
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct BoundFunc2 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
+struct BoundFunc3 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I>
+struct BoundFunc4 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I>
+struct BoundFunc5 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+/* FuncSig ********************************************************************/
+
+/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
+ * *signature*, but without a specific function attached.
+ *
+ * These classes contain member functions that can be invoked with a
+ * specific function to return a Func/BoundFunc class. */
+template <class R, class P1>
+struct FuncSig1 {
+  template <R F(P1)>
+  Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
+    return Func1<R, P1, F, FuncInfo<P1, R> >();
+  }
+};
+
+template <class R, class P1, class P2>
+struct FuncSig2 {
+  template <R F(P1, P2)>
+  Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
+    return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2)>
+  BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3>
+struct FuncSig3 {
+  template <R F(P1, P2, P3)>
+  Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
+    return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3)>
+  BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3, class P4>
+struct FuncSig4 {
+  template <R F(P1, P2, P3, P4)>
+  Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
+    return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3, P4)>
+  BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct FuncSig5 {
+  template <R F(P1, P2, P3, P4, P5)>
+  Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
+    return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3, P4, P5)>
+  BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+/* Overloaded template function that can construct the appropriate FuncSig*
+ * class given a function pointer by deducing the template parameters. */
+template <class R, class P1>
+inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig1<R, P1>();
+}
+
+template <class R, class P1, class P2>
+inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig2<R, P1, P2>();
+}
+
+template <class R, class P1, class P2, class P3>
+inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig3<R, P1, P2, P3>();
+}
+
+template <class R, class P1, class P2, class P3, class P4>
+inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig4<R, P1, P2, P3, P4>();
+}
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig5<R, P1, P2, P3, P4, P5>();
+}
+
+/* MethodSig ******************************************************************/
+
+/* CallMethod*: a function template that calls a given method. */
+template <class R, class C, R (C::*F)()>
+R CallMethod0(C *obj) {
+  return ((*obj).*F)();
+}
+
+template <class R, class C, class P1, R (C::*F)(P1)>
+R CallMethod1(C *obj, P1 arg1) {
+  return ((*obj).*F)(arg1);
+}
+
+template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
+R CallMethod2(C *obj, P1 arg1, P2 arg2) {
+  return ((*obj).*F)(arg1, arg2);
+}
+
+template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
+R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
+  return ((*obj).*F)(arg1, arg2, arg3);
+}
+
+template <class R, class C, class P1, class P2, class P3, class P4,
+          R (C::*F)(P1, P2, P3, P4)>
+R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
+  return ((*obj).*F)(arg1, arg2, arg3, arg4);
+}
+
+/* MethodSig: like FuncSig, but for member functions.
+ *
+ * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
+ * more logic is required to special-case methods. */
+template <class R, class C>
+struct MethodSig0 {
+  template <R (C::*F)()>
+  Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
+    return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
+  }
+};
+
+template <class R, class C, class P1>
+struct MethodSig1 {
+  template <R (C::*F)(P1)>
+  Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
+    return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1)>
+  BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
+      typename remove_constptr<P1>::type param1) {
+    return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
+        param1);
+  }
+};
+
+template <class R, class C, class P1, class P2>
+struct MethodSig2 {
+  template <R (C::*F)(P1, P2)>
+  Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+  GetFunc() {
+    return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2)>
+  BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+                      FuncInfo<C *, R> >(param1);
+  }
+};
+
+template <class R, class C, class P1, class P2, class P3>
+struct MethodSig3 {
+  template <R (C::*F)(P1, P2, P3)>
+  Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
+  GetFunc() {
+    return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2, P3)>
+  BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+             FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+                      FuncInfo<C *, R> >(param1);
+  }
+};
+
+template <class R, class C, class P1, class P2, class P3, class P4>
+struct MethodSig4 {
+  template <R (C::*F)(P1, P2, P3, P4)>
+  Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+        FuncInfo<C *, R> >
+  GetFunc() {
+    return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2, P3, P4)>
+  BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+             FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc5<R, C *, P1, P2, P3, P4,
+                      CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
+        param1);
+  }
+};
+
+template <class R, class C>
+inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig0<R, C>();
+}
+
+template <class R, class C, class P1>
+inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig1<R, C, P1>();
+}
+
+template <class R, class C, class P1, class P2>
+inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig2<R, C, P1, P2>();
+}
+
+template <class R, class C, class P1, class P2, class P3>
+inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig3<R, C, P1, P2, P3>();
+}
+
+template <class R, class C, class P1, class P2, class P3, class P4>
+inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig4<R, C, P1, P2, P3, P4>();
+}
+
+/* MaybeWrapReturn ************************************************************/
+
+/* Template class that attempts to wrap the return value of the function so it
+ * matches the expected type.  There are two main adjustments it may make:
+ *
+ *   1. If the function returns void, make it return the expected type and with
+ *      a value that always indicates success.
+ *   2. If the function returns bool, make it return the expected type with a
+ *      value that indicates success or failure.
+ *
+ * The "expected type" for return is:
+ *   1. void* for start handlers.  If the closure parameter has a different type
+ *      we will cast it to void* for the return in the success case.
+ *   2. size_t for string buffer handlers.
+ *   3. bool for everything else. */
+
+/* Template parameters are FuncN type and desired return type. */
+template <class F, class R, class Enable = void>
+struct MaybeWrapReturn;
+
+/* If the return type matches, return the given function unwrapped. */
+template <class F>
+struct MaybeWrapReturn<F, typename F::Return> {
+  typedef F Func;
+};
+
+/* Function wrapper that munges the return value from void to (bool)true. */
+template <class P1, class P2, void F(P1, P2)>
+bool ReturnTrue2(P1 p1, P2 p2) {
+  F(p1, p2);
+  return true;
+}
+
+template <class P1, class P2, class P3, void F(P1, P2, P3)>
+bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
+  F(p1, p2, p3);
+  return true;
+}
+
+/* Function wrapper that munges the return value from void to (void*)arg1  */
+template <class P1, class P2, void F(P1, P2)>
+void *ReturnClosure2(P1 p1, P2 p2) {
+  F(p1, p2);
+  return p1;
+}
+
+template <class P1, class P2, class P3, void F(P1, P2, P3)>
+void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
+  F(p1, p2, p3);
+  return p1;
+}
+
+/* Function wrapper that munges the return value from R to void*. */
+template <class R, class P1, class P2, R F(P1, P2)>
+void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
+  return F(p1, p2);
+}
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
+  return F(p1, p2, p3);
+}
+
+/* Function wrapper that munges the return value from bool to void*. */
+template <class P1, class P2, bool F(P1, P2)>
+void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
+  return F(p1, p2) ? p1 : UPB_BREAK;
+}
+
+template <class P1, class P2, class P3, bool F(P1, P2, P3)>
+void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
+  return F(p1, p2, p3) ? p1 : UPB_BREAK;
+}
+
+/* For the string callback, which takes five params, returns the size param. */
+template <class P1, class P2,
+          void F(P1, P2, const char *, size_t, const BufferHandle *)>
+size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
+                       const BufferHandle *p5) {
+  F(p1, p2, p3, p4, p5);
+  return p4;
+}
+
+/* For the string callback, which takes five params, returns the size param or
+ * zero. */
+template <class P1, class P2,
+          bool F(P1, P2, const char *, size_t, const BufferHandle *)>
+size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
+                  const BufferHandle *p5) {
+  return F(p1, p2, p3, p4, p5) ? p4 : 0;
+}
+
+/* If we have a function returning void but want a function returning bool, wrap
+ * it in a function that returns true. */
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
+  typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
+  typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
+};
+
+/* If our function returns void but we want one returning void*, wrap it in a
+ * function that returns the first argument. */
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
+  typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
+  typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
+};
+
+/* If our function returns R* but we want one returning void*, wrap it in a
+ * function that casts to void*. */
+template <class R, class P1, class P2, R *F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
+                       typename disable_if_same<R *, void *>::Type> {
+  typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
+};
+
+template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
+                       typename disable_if_same<R *, void *>::Type> {
+  typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
+      Func;
+};
+
+/* If our function returns bool but we want one returning void*, wrap it in a
+ * function that returns either the first param or UPB_BREAK. */
+template <class P1, class P2, bool F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
+  typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
+  typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
+      Func;
+};
+
+/* If our function returns void but we want one returning size_t, wrap it in a
+ * function that returns the size argument. */
+template <class P1, class P2,
+          void F(P1, P2, const char *, size_t, const BufferHandle *), class I>
+struct MaybeWrapReturn<
+    Func5<void, P1, P2, const char *, size_t, const BufferHandle *, F, I>,
+          size_t> {
+  typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *,
+                ReturnStringLen<P1, P2, F>, I> Func;
+};
+
+/* If our function returns bool but we want one returning size_t, wrap it in a
+ * function that returns either 0 or the buf size. */
+template <class P1, class P2,
+          bool F(P1, P2, const char *, size_t, const BufferHandle *), class I>
+struct MaybeWrapReturn<
+    Func5<bool, P1, P2, const char *, size_t, const BufferHandle *, F, I>,
+    size_t> {
+  typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *,
+                ReturnNOr0<P1, P2, F>, I> Func;
+};
+
+/* ConvertParams **************************************************************/
+
+/* Template class that converts the function parameters if necessary, and
+ * ignores the HandlerData parameter if appropriate.
+ *
+ * Template parameter is the are FuncN function type. */
+template <class F, class T>
+struct ConvertParams;
+
+/* Function that discards the handler data parameter. */
+template <class R, class P1, R F(P1)>
+R IgnoreHandlerData2(void *p1, const void *hd) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1));
+}
+
+template <class R, class P1, class P2Wrapper, class P2Wrapped,
+          R F(P1, P2Wrapped)>
+R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2);
+}
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2, p3);
+}
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
+R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2, p3, p4);
+}
+
+template <class R, class P1, R F(P1, const char*, size_t)>
+R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
+                                size_t p3, const BufferHandle *handle) {
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  return F(static_cast<P1>(p1), p2, p3);
+}
+
+/* Function that casts the handler data parameter. */
+template <class R, class P1, class P2, R F(P1, P2)>
+R CastHandlerData2(void *c, const void *hd) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd));
+}
+
+template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
+          R F(P1, P2, P3Wrapped)>
+R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
+}
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5)>
+R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
+}
+
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
+R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
+                              size_t p4, const BufferHandle *handle) {
+  UPB_UNUSED(handle);
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
+}
+
+/* For unbound functions, ignore the handler data. */
+template <class R, class P1, R F(P1), class I, class T>
+struct ConvertParams<Func1<R, P1, F, I>, T> {
+  typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I,
+          class R2, class P1_2, class P2_2, class P3_2>
+struct ConvertParams<Func2<R, P1, P2, F, I>,
+                     R2 (*)(P1_2, P2_2, P3_2)> {
+  typedef Func3<R, void *, const void *, P3_2,
+                IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
+};
+
+/* For StringBuffer only; this ignores both the handler data and the
+ * BufferHandle. */
+template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
+struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
+  typedef Func5<R, void *, const void *, const char *, size_t,
+                const BufferHandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
+                I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I, class T>
+struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
+  typedef Func5<R, void *, const void *, P2, P3, P4,
+                IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
+};
+
+/* For bound functions, cast the handler data. */
+template <class R, class P1, class P2, R F(P1, P2), class I, class T>
+struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
+  typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
+      Func;
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
+          class R2, class P1_2, class P2_2, class P3_2>
+struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
+                     R2 (*)(P1_2, P2_2, P3_2)> {
+  typedef Func3<R, void *, const void *, P3_2,
+                CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
+};
+
+/* For StringBuffer only; this ignores the BufferHandle. */
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
+          class I, class T>
+struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
+  typedef Func5<R, void *, const void *, const char *, size_t,
+                const BufferHandle *, CastHandlerDataIgnoreHandle<R, P1, P2, F>,
+                I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I, class T>
+struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
+  typedef Func5<R, void *, const void *, P3, P4, P5,
+                CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
+};
+
+/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
+ * variant C type. */
+#define TYPE_METHODS(utype, ltype, ctype, vtype)                               \
+  template <> struct CanonicalType<vtype> {                                    \
+    typedef ctype Type;                                                        \
+  };                                                                           \
+  template <>                                                                  \
+  inline bool Handlers::SetValueHandler<vtype>(                                \
+      const FieldDef *f,                                                       \
+      const Handlers::utype ## Handler& handler) {                             \
+    assert(!handler.registered_);                                              \
+    handler.AddCleanup(this);                                                  \
+    handler.registered_ = true;                                                \
+    return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \
+  }                                                                            \
+
+TYPE_METHODS(Double, double, double,   double)
+TYPE_METHODS(Float,  float,  float,    float)
+TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
+TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
+TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
+TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
+TYPE_METHODS(Bool,   bool,   bool,     bool)
+
+#ifdef UPB_TWO_32BIT_TYPES
+TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
+TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
+#endif
+
+#ifdef UPB_TWO_64BIT_TYPES
+TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
+TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
+#endif
+#undef TYPE_METHODS
+
+template <> struct CanonicalType<Status*> {
+  typedef Status* Type;
+};
+
+/* Type methods that are only one-per-canonical-type and not
+ * one-per-cvariant. */
+
+#define TYPE_METHODS(utype, ctype) \
+    inline bool Handlers::Set##utype##Handler(const FieldDef *f, \
+                                              const utype##Handler &h) { \
+      return SetValueHandler<ctype>(f, h); \
+    } \
+
+TYPE_METHODS(Double, double)
+TYPE_METHODS(Float,  float)
+TYPE_METHODS(UInt64, uint64_t)
+TYPE_METHODS(UInt32, uint32_t)
+TYPE_METHODS(Int64,  int64_t)
+TYPE_METHODS(Int32,  int32_t)
+TYPE_METHODS(Bool,   bool)
+#undef TYPE_METHODS
+
+template <class F> struct ReturnOf;
+
+template <class R, class P1, class P2>
+struct ReturnOf<R (*)(P1, P2)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3>
+struct ReturnOf<R (*)(P1, P2, P3)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3, class P4>
+struct ReturnOf<R (*)(P1, P2, P3, P4)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
+  typedef R Return;
+};
+
+template<class T> const void *UniquePtrForType() {
+  static const char ch = 0;
+  return &ch;
+}
+
+template <class T>
+template <class F>
+inline Handler<T>::Handler(F func)
+    : registered_(false),
+      cleanup_data_(func.GetData()),
+      cleanup_func_(func.GetCleanup()) {
+  upb_handlerattr_sethandlerdata(&attr_, func.GetData());
+  typedef typename ReturnOf<T>::Return Return;
+  typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
+  typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
+      ReturnWrappedFunc;
+  handler_ = ReturnWrappedFunc().Call;
+
+  /* Set attributes based on what templates can statically tell us about the
+   * user's function. */
+
+  /* If the original function returns void, then we know that we wrapped it to
+   * always return ok. */
+  bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
+  attr_.SetAlwaysOk(always_ok);
+
+  /* Closure parameter and return type. */
+  attr_.SetClosureType(UniquePtrForType<typename F::FuncInfo::Closure>());
+
+  /* We use the closure type (from the first parameter) if the return type is
+   * void or bool, since these are the two cases we wrap to return the closure's
+   * type anyway.
+   *
+   * This is all nonsense for non START* handlers, but it doesn't matter because
+   * in that case the value will be ignored. */
+  typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
+                                         typename F::FuncInfo::Closure>::value
+      EffectiveReturn;
+  attr_.SetReturnClosureType(UniquePtrForType<EffectiveReturn>());
+}
+
+template <class T>
+inline Handler<T>::~Handler() {
+  assert(registered_);
+}
+
+inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); }
+inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); }
+inline bool HandlerAttributes::SetHandlerData(const void *hd) {
+  return upb_handlerattr_sethandlerdata(this, hd);
+}
+inline const void* HandlerAttributes::handler_data() const {
+  return upb_handlerattr_handlerdata(this);
+}
+inline bool HandlerAttributes::SetClosureType(const void *type) {
+  return upb_handlerattr_setclosuretype(this, type);
+}
+inline const void* HandlerAttributes::closure_type() const {
+  return upb_handlerattr_closuretype(this);
+}
+inline bool HandlerAttributes::SetReturnClosureType(const void *type) {
+  return upb_handlerattr_setreturnclosuretype(this, type);
+}
+inline const void* HandlerAttributes::return_closure_type() const {
+  return upb_handlerattr_returnclosuretype(this);
+}
+inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) {
+  return upb_handlerattr_setalwaysok(this, always_ok);
+}
+inline bool HandlerAttributes::always_ok() const {
+  return upb_handlerattr_alwaysok(this);
+}
+
+inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); }
+inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); }
+inline const char* BufferHandle::buffer() const {
+  return upb_bufhandle_buf(this);
+}
+inline size_t BufferHandle::object_offset() const {
+  return upb_bufhandle_objofs(this);
+}
+inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) {
+  upb_bufhandle_setbuf(this, buf, ofs);
+}
+template <class T>
+void BufferHandle::SetAttachedObject(const T* obj) {
+  upb_bufhandle_setobj(this, obj, UniquePtrForType<T>());
+}
+template <class T>
+const T* BufferHandle::GetAttachedObject() const {
+  return upb_bufhandle_objtype(this) == UniquePtrForType<T>()
+      ? static_cast<const T *>(upb_bufhandle_obj(this))
+                               : NULL;
+}
+
+inline reffed_ptr<Handlers> Handlers::New(const MessageDef *m) {
+  upb_handlers *h = upb_handlers_new(m, &h);
+  return reffed_ptr<Handlers>(h, &h);
+}
+inline reffed_ptr<const Handlers> Handlers::NewFrozen(
+    const MessageDef *m, upb_handlers_callback *callback,
+    const void *closure) {
+  const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+inline const Status* Handlers::status() {
+  return upb_handlers_status(this);
+}
+inline void Handlers::ClearError() {
+  return upb_handlers_clearerr(this);
+}
+inline bool Handlers::Freeze(Status *s) {
+  upb::Handlers* h = this;
+  return upb_handlers_freeze(&h, 1, s);
+}
+inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) {
+  return upb_handlers_freeze(handlers, n, s);
+}
+inline bool Handlers::Freeze(const std::vector<Handlers*>& h, Status* status) {
+  return upb_handlers_freeze((Handlers* const*)&h[0], h.size(), status);
+}
+inline const MessageDef *Handlers::message_def() const {
+  return upb_handlers_msgdef(this);
+}
+inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) {
+  return upb_handlers_addcleanup(this, p, func);
+}
+inline bool Handlers::SetStartMessageHandler(
+    const Handlers::StartMessageHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndMessageHandler(
+    const Handlers::EndMessageHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartStringHandler(const FieldDef *f,
+                                            const StartStringHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndStringHandler(const FieldDef *f,
+                                          const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStringHandler(const FieldDef *f,
+                                       const StringHandler& handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartSequenceHandler(
+    const FieldDef *f, const StartFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartSubMessageHandler(
+    const FieldDef *f, const StartFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f,
+                                              const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndSequenceHandler(const FieldDef *f,
+                                            const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) {
+  return upb_handlers_setsubhandlers(this, f, sub);
+}
+inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const {
+  return upb_handlers_getsubhandlers(this, f);
+}
+inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const {
+  return upb_handlers_getsubhandlers_sel(this, sel);
+}
+inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type,
+                                  Handlers::Selector *s) {
+  return upb_handlers_getselector(f, type, s);
+}
+inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) {
+  return upb_handlers_getendselector(start);
+}
+inline Handlers::GenericFunction *Handlers::GetHandler(
+    Handlers::Selector selector) {
+  return upb_handlers_gethandler(this, selector);
+}
+inline const void *Handlers::GetHandlerData(Handlers::Selector selector) {
+  return upb_handlers_gethandlerdata(this, selector);
+}
+
+inline BytesHandler::BytesHandler() {
+  upb_byteshandler_init(this);
+}
+
+inline BytesHandler::~BytesHandler() {}
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+
+#undef UPB_TWO_32BIT_TYPES
+#undef UPB_TWO_64BIT_TYPES
+#undef UPB_INT32_T
+#undef UPB_UINT32_T
+#undef UPB_INT32ALT_T
+#undef UPB_UINT32ALT_T
+#undef UPB_INT64_T
+#undef UPB_UINT64_T
+#undef UPB_INT64ALT_T
+#undef UPB_UINT64ALT_T
+
+#endif  /* UPB_HANDLERS_INL_H_ */
+
+#endif  /* UPB_HANDLERS_H */
+/*
+** upb::Environment (upb_env)
+**
+** A upb::Environment provides a means for injecting malloc and an
+** error-reporting callback into encoders/decoders.  This allows them to be
+** independent of nearly all assumptions about their actual environment.
+**
+** It is also a container for allocating the encoders/decoders themselves that
+** insulates clients from knowing their actual size.  This provides ABI
+** compatibility even if the size of the objects change.  And this allows the
+** structure definitions to be in the .c files instead of the .h files, making
+** the .h files smaller and more readable.
+*/
+
+
+#ifndef UPB_ENV_H_
+#define UPB_ENV_H_
+
+#ifdef __cplusplus
+namespace upb {
+class Environment;
+class SeededAllocator;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::Environment, upb_env)
+UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc)
+
+typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size);
+typedef void upb_cleanup_func(void *ud);
+typedef bool upb_error_func(void *ud, const upb_status *status);
+
+#ifdef __cplusplus
+
+/* An environment is *not* thread-safe. */
+class upb::Environment {
+ public:
+  Environment();
+  ~Environment();
+
+  /* Set a custom memory allocation function for the environment.  May ONLY
+   * be called before any calls to Malloc()/Realloc()/AddCleanup() below.
+   * If this is not called, the system realloc() function will be used.
+   * The given user pointer "ud" will be passed to the allocation function.
+   *
+   * The allocation function will not receive corresponding "free" calls.  it
+   * must ensure that the memory is valid for the lifetime of the Environment,
+   * but it may be reclaimed any time thereafter.  The likely usage is that
+   * "ud" points to a stateful allocator, and that the allocator frees all
+   * memory, arena-style, when it is destroyed.  In this case the allocator must
+   * outlive the Environment.  Another possibility is that the allocation
+   * function returns GC-able memory that is guaranteed to be GC-rooted for the
+   * life of the Environment. */
+  void SetAllocationFunction(upb_alloc_func* alloc, void* ud);
+
+  template<class T>
+  void SetAllocator(T* allocator) {
+    SetAllocationFunction(allocator->GetAllocationFunction(), allocator);
+  }
+
+  /* Set a custom error reporting function. */
+  void SetErrorFunction(upb_error_func* func, void* ud);
+
+  /* Set the error reporting function to simply copy the status to the given
+   * status and abort. */
+  void ReportErrorsTo(Status* status);
+
+  /* Returns true if all allocations and AddCleanup() calls have succeeded,
+   * and no errors were reported with ReportError() (except ones that recovered
+   * successfully). */
+  bool ok() const;
+
+  /* Functions for use by encoders/decoders. **********************************/
+
+  /* Reports an error to this environment's callback, returning true if
+   * the caller should try to recover. */
+  bool ReportError(const Status* status);
+
+  /* Allocate memory.  Uses the environment's allocation function.
+   *
+   * There is no need to free(). All memory will be freed automatically, but is
+   * guaranteed to outlive the Environment. */
+  void* Malloc(size_t size);
+
+  /* Reallocate memory.  Preserves "oldsize" bytes from the existing buffer
+   * Requires: oldsize <= existing_size.
+   *
+   * TODO(haberman): should we also enforce that oldsize <= size? */
+  void* Realloc(void* ptr, size_t oldsize, size_t size);
+
+  /* Add a cleanup function to run when the environment is destroyed.
+   * Returns false on out-of-memory.
+   *
+   * The first call to AddCleanup() after SetAllocationFunction() is guaranteed
+   * to return true -- this makes it possible to robustly set a cleanup handler
+   * for a custom allocation function. */
+  bool AddCleanup(upb_cleanup_func* func, void* ud);
+
+  /* Total number of bytes that have been allocated.  It is undefined what
+   * Realloc() does to this counter. */
+  size_t BytesAllocated() const;
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Environment)
+
+#else
+struct upb_env {
+#endif  /* __cplusplus */
+
+  bool ok_;
+  size_t bytes_allocated;
+
+  /* Alloc function. */
+  upb_alloc_func *alloc;
+  void *alloc_ud;
+
+  /* Error-reporting function. */
+  upb_error_func *err;
+  void *err_ud;
+
+  /* Userdata for default alloc func. */
+  void *default_alloc_ud;
+
+  /* Cleanup entries.  Pointer to a cleanup_ent, defined in env.c */
+  void *cleanup_head;
+
+  /* For future expansion, since the size of this struct is exposed to users. */
+  void *future1;
+  void *future2;
+};
+
+UPB_BEGIN_EXTERN_C
+
+void upb_env_init(upb_env *e);
+void upb_env_uninit(upb_env *e);
+void upb_env_setallocfunc(upb_env *e, upb_alloc_func *func, void *ud);
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud);
+void upb_env_reporterrorsto(upb_env *e, upb_status *status);
+bool upb_env_ok(const upb_env *e);
+bool upb_env_reporterror(upb_env *e, const upb_status *status);
+void *upb_env_malloc(upb_env *e, size_t size);
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size);
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud);
+size_t upb_env_bytesallocated(const upb_env *e);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+/* An allocator that allocates from an initial memory region (likely the stack)
+ * before falling back to another allocator. */
+class upb::SeededAllocator {
+ public:
+  SeededAllocator(void *mem, size_t len);
+  ~SeededAllocator();
+
+  /* Set a custom fallback memory allocation function for the allocator, to use
+   * once the initial region runs out.
+   *
+   * May ONLY be called before GetAllocationFunction().  If this is not
+   * called, the system realloc() will be the fallback allocator. */
+  void SetFallbackAllocator(upb_alloc_func *alloc, void *ud);
+
+  /* Gets the allocation function for this allocator. */
+  upb_alloc_func* GetAllocationFunction();
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator)
+
+#else
+struct upb_seededalloc {
+#endif  /* __cplusplus */
+
+  /* Fallback alloc function.  */
+  upb_alloc_func *alloc;
+  upb_cleanup_func *alloc_cleanup;
+  void *alloc_ud;
+  bool need_cleanup;
+  bool returned_allocfunc;
+
+  /* Userdata for default alloc func. */
+  void *default_alloc_ud;
+
+  /* Pointers for the initial memory region. */
+  char *mem_base;
+  char *mem_ptr;
+  char *mem_limit;
+
+  /* For future expansion, since the size of this struct is exposed to users. */
+  void *future1;
+  void *future2;
+};
+
+UPB_BEGIN_EXTERN_C
+
+void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len);
+void upb_seededalloc_uninit(upb_seededalloc *a);
+void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, upb_alloc_func *func,
+                                      void *ud);
+upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+inline Environment::Environment() {
+  upb_env_init(this);
+}
+inline Environment::~Environment() {
+  upb_env_uninit(this);
+}
+inline void Environment::SetAllocationFunction(upb_alloc_func *alloc,
+                                               void *ud) {
+  upb_env_setallocfunc(this, alloc, ud);
+}
+inline void Environment::SetErrorFunction(upb_error_func *func, void *ud) {
+  upb_env_seterrorfunc(this, func, ud);
+}
+inline void Environment::ReportErrorsTo(Status* status) {
+  upb_env_reporterrorsto(this, status);
+}
+inline bool Environment::ok() const {
+  return upb_env_ok(this);
+}
+inline bool Environment::ReportError(const Status* status) {
+  return upb_env_reporterror(this, status);
+}
+inline void *Environment::Malloc(size_t size) {
+  return upb_env_malloc(this, size);
+}
+inline void *Environment::Realloc(void *ptr, size_t oldsize, size_t size) {
+  return upb_env_realloc(this, ptr, oldsize, size);
+}
+inline bool Environment::AddCleanup(upb_cleanup_func *func, void *ud) {
+  return upb_env_addcleanup(this, func, ud);
+}
+inline size_t Environment::BytesAllocated() const {
+  return upb_env_bytesallocated(this);
+}
+
+inline SeededAllocator::SeededAllocator(void *mem, size_t len) {
+  upb_seededalloc_init(this, mem, len);
+}
+inline SeededAllocator::~SeededAllocator() {
+  upb_seededalloc_uninit(this);
+}
+inline void SeededAllocator::SetFallbackAllocator(upb_alloc_func *alloc,
+                                                  void *ud) {
+  upb_seededalloc_setfallbackalloc(this, alloc, ud);
+}
+inline upb_alloc_func *SeededAllocator::GetAllocationFunction() {
+  return upb_seededalloc_getallocfunc(this);
+}
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+#endif  /* UPB_ENV_H_ */
+/*
+** upb::Sink (upb_sink)
+** upb::BytesSink (upb_bytessink)
+**
+** A upb_sink is an object that binds a upb_handlers object to some runtime
+** state.  It is the object that can actually receive data via the upb_handlers
+** interface.
+**
+** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
+** thread-safe.  You can create as many of them as you want, but each one may
+** only be used in a single thread at a time.
+**
+** If we compare with class-based OOP, a you can think of a upb_def as an
+** abstract base class, a upb_handlers as a concrete derived class, and a
+** upb_sink as an object (class instance).
+*/
+
+#ifndef UPB_SINK_H
+#define UPB_SINK_H
+
+
+#ifdef __cplusplus
+namespace upb {
+class BufferSource;
+class BytesSink;
+class Sink;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc)
+UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink)
+UPB_DECLARE_TYPE(upb::Sink, upb_sink)
+
+#ifdef __cplusplus
+
+/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
+ * state.  It represents an endpoint to which data can be sent.
+ *
+ * TODO(haberman): right now all of these functions take selectors.  Should they
+ * take selectorbase instead?
+ *
+ * ie. instead of calling:
+ *   sink->StartString(FOO_FIELD_START_STRING, ...)
+ * a selector base would let you say:
+ *   sink->StartString(FOO_FIELD, ...)
+ *
+ * This would make call sites a little nicer and require emitting fewer selector
+ * definitions in .h files.
+ *
+ * But the current scheme has the benefit that you can retrieve a function
+ * pointer for any handler with handlers->GetHandler(selector), without having
+ * to have a separate GetHandler() function for each handler type.  The JIT
+ * compiler uses this.  To accommodate we'd have to expose a separate
+ * GetHandler() for every handler type.
+ *
+ * Also to ponder: selectors right now are independent of a specific Handlers
+ * instance.  In other words, they allocate a number to every possible handler
+ * that *could* be registered, without knowing anything about what handlers
+ * *are* registered.  That means that using selectors as table offsets prohibits
+ * us from compacting the handler table at Freeze() time.  If the table is very
+ * sparse, this could be wasteful.
+ *
+ * Having another selector-like thing that is specific to a Handlers instance
+ * would allow this compacting, but then it would be impossible to write code
+ * ahead-of-time that can be bound to any Handlers instance at runtime.  For
+ * example, a .proto file parser written as straight C will not know what
+ * Handlers it will be bound to, so when it calls sink->StartString() what
+ * selector will it pass?  It needs a selector like we have today, that is
+ * independent of any particular upb::Handlers.
+ *
+ * Is there a way then to allow Handlers table compaction? */
+class upb::Sink {
+ public:
+  /* Constructor with no initialization; must be Reset() before use. */
+  Sink() {}
+
+  /* Constructs a new sink for the given frozen handlers and closure.
+   *
+   * TODO: once the Handlers know the expected closure type, verify that T
+   * matches it. */
+  template <class T> Sink(const Handlers* handlers, T* closure);
+
+  /* Resets the value of the sink. */
+  template <class T> void Reset(const Handlers* handlers, T* closure);
+
+  /* Returns the top-level object that is bound to this sink.
+   *
+   * TODO: once the Handlers know the expected closure type, verify that T
+   * matches it. */
+  template <class T> T* GetObject() const;
+
+  /* Functions for pushing data into the sink.
+   *
+   * These return false if processing should stop (either due to error or just
+   * to suspend).
+   *
+   * These may not be called from within one of the same sink's handlers (in
+   * other words, handlers are not re-entrant). */
+
+  /* Should be called at the start and end of every message; both the top-level
+   * message and submessages.  This means that submessages should use the
+   * following sequence:
+   *   sink->StartSubMessage(startsubmsg_selector);
+   *   sink->StartMessage();
+   *   // ...
+   *   sink->EndMessage(&status);
+   *   sink->EndSubMessage(endsubmsg_selector); */
+  bool StartMessage();
+  bool EndMessage(Status* status);
+
+  /* Putting of individual values.  These work for both repeated and
+   * non-repeated fields, but for repeated fields you must wrap them in
+   * calls to StartSequence()/EndSequence(). */
+  bool PutInt32(Handlers::Selector s, int32_t val);
+  bool PutInt64(Handlers::Selector s, int64_t val);
+  bool PutUInt32(Handlers::Selector s, uint32_t val);
+  bool PutUInt64(Handlers::Selector s, uint64_t val);
+  bool PutFloat(Handlers::Selector s, float val);
+  bool PutDouble(Handlers::Selector s, double val);
+  bool PutBool(Handlers::Selector s, bool val);
+
+  /* Putting of string/bytes values.  Each string can consist of zero or more
+   * non-contiguous buffers of data.
+   *
+   * For StartString(), the function will write a sink for the string to "sub."
+   * The sub-sink must be used for any/all PutStringBuffer() calls. */
+  bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub);
+  size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len,
+                         const BufferHandle *handle);
+  bool EndString(Handlers::Selector s);
+
+  /* For submessage fields.
+   *
+   * For StartSubMessage(), the function will write a sink for the string to
+   * "sub." The sub-sink must be used for any/all handlers called within the
+   * submessage. */
+  bool StartSubMessage(Handlers::Selector s, Sink* sub);
+  bool EndSubMessage(Handlers::Selector s);
+
+  /* For repeated fields of any type, the sequence of values must be wrapped in
+   * these calls.
+   *
+   * For StartSequence(), the function will write a sink for the string to
+   * "sub." The sub-sink must be used for any/all handlers called within the
+   * sequence. */
+  bool StartSequence(Handlers::Selector s, Sink* sub);
+  bool EndSequence(Handlers::Selector s);
+
+  /* Copy and assign specifically allowed.
+   * We don't even bother making these members private because so many
+   * functions need them and this is mainly just a dumb data container anyway.
+   */
+#else
+struct upb_sink {
+#endif
+  const upb_handlers *handlers;
+  void *closure;
+};
+
+#ifdef __cplusplus
+class upb::BytesSink {
+ public:
+  BytesSink() {}
+
+  /* Constructs a new sink for the given frozen handlers and closure.
+   *
+   * TODO(haberman): once the Handlers know the expected closure type, verify
+   * that T matches it. */
+  template <class T> BytesSink(const BytesHandler* handler, T* closure);
+
+  /* Resets the value of the sink. */
+  template <class T> void Reset(const BytesHandler* handler, T* closure);
+
+  bool Start(size_t size_hint, void **subc);
+  size_t PutBuffer(void *subc, const char *buf, size_t len,
+                   const BufferHandle *handle);
+  bool End();
+#else
+struct upb_bytessink {
+#endif
+  const upb_byteshandler *handler;
+  void *closure;
+};
+
+#ifdef __cplusplus
+
+/* A class for pushing a flat buffer of data to a BytesSink.
+ * You can construct an instance of this to get a resumable source,
+ * or just call the static PutBuffer() to do a non-resumable push all in one
+ * go. */
+class upb::BufferSource {
+ public:
+  BufferSource();
+  BufferSource(const char* buf, size_t len, BytesSink* sink);
+
+  /* Returns true if the entire buffer was pushed successfully.  Otherwise the
+   * next call to PutNext() will resume where the previous one left off.
+   * TODO(haberman): implement this. */
+  bool PutNext();
+
+  /* A static version; with this version is it not possible to resume in the
+   * case of failure or a partially-consumed buffer. */
+  static bool PutBuffer(const char* buf, size_t len, BytesSink* sink);
+
+  template <class T> static bool PutBuffer(const T& str, BytesSink* sink) {
+    return PutBuffer(str.c_str(), str.size(), sink);
+  }
+#else
+struct upb_bufsrc {
+  char dummy;
+#endif
+};
+
+UPB_BEGIN_EXTERN_C
+
+/* Inline definitions. */
+
+UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h,
+                                    void *closure) {
+  s->handler = h;
+  s->closure = closure;
+}
+
+UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint,
+                                    void **subc) {
+  typedef upb_startstr_handlerfunc func;
+  func *start;
+  *subc = s->closure;
+  if (!s->handler) return true;
+  start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func;
+
+  if (!start) return true;
+  *subc = start(s->closure, upb_handlerattr_handlerdata(
+                                &s->handler->table[UPB_STARTSTR_SELECTOR].attr),
+                size_hint);
+  return *subc != NULL;
+}
+
+UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc,
+                                       const char *buf, size_t size,
+                                       const upb_bufhandle* handle) {
+  typedef upb_string_handlerfunc func;
+  func *putbuf;
+  if (!s->handler) return true;
+  putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func;
+
+  if (!putbuf) return true;
+  return putbuf(subc, upb_handlerattr_handlerdata(
+                          &s->handler->table[UPB_STRING_SELECTOR].attr),
+                buf, size, handle);
+}
+
+UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) {
+  typedef upb_endfield_handlerfunc func;
+  func *end;
+  if (!s->handler) return true;
+  end = (func *)s->handler->table[UPB_ENDSTR_SELECTOR].func;
+
+  if (!end) return true;
+  return end(s->closure,
+             upb_handlerattr_handlerdata(
+                 &s->handler->table[UPB_ENDSTR_SELECTOR].attr));
+}
+
+UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len,
+                                  upb_bytessink *sink) {
+  void *subc;
+  bool ret;
+  upb_bufhandle handle;
+  upb_bufhandle_init(&handle);
+  upb_bufhandle_setbuf(&handle, buf, 0);
+  ret = upb_bytessink_start(sink, len, &subc);
+  if (ret && len != 0) {
+    ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
+  }
+  if (ret) {
+    ret = upb_bytessink_end(sink);
+  }
+  upb_bufhandle_uninit(&handle);
+  return ret;
+}
+
+#define PUTVAL(type, ctype)                                                    \
+  UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel,          \
+                                     ctype val) {                              \
+    typedef upb_##type##_handlerfunc functype;                                 \
+    functype *func;                                                            \
+    const void *hd;                                                            \
+    if (!s->handlers) return true;                                             \
+    func = (functype *)upb_handlers_gethandler(s->handlers, sel);              \
+    if (!func) return true;                                                    \
+    hd = upb_handlers_gethandlerdata(s->handlers, sel);                        \
+    return func(s->closure, hd, val);                                          \
+  }
+
+PUTVAL(int32,  int32_t)
+PUTVAL(int64,  int64_t)
+PUTVAL(uint32, uint32_t)
+PUTVAL(uint64, uint64_t)
+PUTVAL(float,  float)
+PUTVAL(double, double)
+PUTVAL(bool,   bool)
+#undef PUTVAL
+
+UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
+  s->handlers = h;
+  s->closure = c;
+}
+
+UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel,
+                                     const char *buf, size_t n,
+                                     const upb_bufhandle *handle) {
+  typedef upb_string_handlerfunc func;
+  func *handler;
+  const void *hd;
+  if (!s->handlers) return n;
+  handler = (func *)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!handler) return n;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return handler(s->closure, hd, buf, n, handle);
+}
+
+UPB_INLINE bool upb_sink_startmsg(upb_sink *s) {
+  typedef upb_startmsg_handlerfunc func;
+  func *startmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR);
+
+  if (!startmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR);
+  return startmsg(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) {
+  typedef upb_endmsg_handlerfunc func;
+  func *endmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR);
+
+  if (!endmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR);
+  return endmsg(s->closure, hd, status);
+}
+
+UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel,
+                                  upb_sink *sub) {
+  typedef upb_startfield_handlerfunc func;
+  func *startseq;
+  const void *hd;
+  sub->closure = s->closure;
+  sub->handlers = s->handlers;
+  if (!s->handlers) return true;
+  startseq = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startseq) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startseq(s->closure, hd);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endseq;
+  const void *hd;
+  if (!s->handlers) return true;
+  endseq = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endseq) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endseq(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel,
+                                  size_t size_hint, upb_sink *sub) {
+  typedef upb_startstr_handlerfunc func;
+  func *startstr;
+  const void *hd;
+  sub->closure = s->closure;
+  sub->handlers = s->handlers;
+  if (!s->handlers) return true;
+  startstr = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startstr) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startstr(s->closure, hd, size_hint);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endstr;
+  const void *hd;
+  if (!s->handlers) return true;
+  endstr = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endstr) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endstr(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel,
+                                     upb_sink *sub) {
+  typedef upb_startfield_handlerfunc func;
+  func *startsubmsg;
+  const void *hd;
+  sub->closure = s->closure;
+  if (!s->handlers) {
+    sub->handlers = NULL;
+    return true;
+  }
+  sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel);
+  startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startsubmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startsubmsg(s->closure, hd);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endsubmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endsubmsg) return s->closure;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endsubmsg(s->closure, hd);
+}
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+template <class T> Sink::Sink(const Handlers* handlers, T* closure) {
+  upb_sink_reset(this, handlers, closure);
+}
+template <class T>
+inline void Sink::Reset(const Handlers* handlers, T* closure) {
+  upb_sink_reset(this, handlers, closure);
+}
+inline bool Sink::StartMessage() {
+  return upb_sink_startmsg(this);
+}
+inline bool Sink::EndMessage(Status* status) {
+  return upb_sink_endmsg(this, status);
+}
+inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) {
+  return upb_sink_putint32(this, sel, val);
+}
+inline bool Sink::PutInt64(Handlers::Selector sel, int64_t val) {
+  return upb_sink_putint64(this, sel, val);
+}
+inline bool Sink::PutUInt32(Handlers::Selector sel, uint32_t val) {
+  return upb_sink_putuint32(this, sel, val);
+}
+inline bool Sink::PutUInt64(Handlers::Selector sel, uint64_t val) {
+  return upb_sink_putuint64(this, sel, val);
+}
+inline bool Sink::PutFloat(Handlers::Selector sel, float val) {
+  return upb_sink_putfloat(this, sel, val);
+}
+inline bool Sink::PutDouble(Handlers::Selector sel, double val) {
+  return upb_sink_putdouble(this, sel, val);
+}
+inline bool Sink::PutBool(Handlers::Selector sel, bool val) {
+  return upb_sink_putbool(this, sel, val);
+}
+inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint,
+                              Sink *sub) {
+  return upb_sink_startstr(this, sel, size_hint, sub);
+}
+inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf,
+                                    size_t len, const BufferHandle* handle) {
+  return upb_sink_putstring(this, sel, buf, len, handle);
+}
+inline bool Sink::EndString(Handlers::Selector sel) {
+  return upb_sink_endstr(this, sel);
+}
+inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) {
+  return upb_sink_startsubmsg(this, sel, sub);
+}
+inline bool Sink::EndSubMessage(Handlers::Selector sel) {
+  return upb_sink_endsubmsg(this, sel);
+}
+inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) {
+  return upb_sink_startseq(this, sel, sub);
+}
+inline bool Sink::EndSequence(Handlers::Selector sel) {
+  return upb_sink_endseq(this, sel);
+}
+
+template <class T>
+BytesSink::BytesSink(const BytesHandler* handler, T* closure) {
+  Reset(handler, closure);
+}
+
+template <class T>
+void BytesSink::Reset(const BytesHandler *handler, T *closure) {
+  upb_bytessink_reset(this, handler, closure);
+}
+inline bool BytesSink::Start(size_t size_hint, void **subc) {
+  return upb_bytessink_start(this, size_hint, subc);
+}
+inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len,
+                                   const BufferHandle *handle) {
+  return upb_bytessink_putbuf(this, subc, buf, len, handle);
+}
+inline bool BytesSink::End() {
+  return upb_bytessink_end(this);
+}
+
+inline bool BufferSource::PutBuffer(const char *buf, size_t len,
+                                    BytesSink *sink) {
+  return upb_bufsrc_putbuf(buf, len, sink);
+}
+
+}  /* namespace upb */
+#endif
+
+#endif
+/*
+** For handlers that do very tiny, very simple operations, the function call
+** overhead of calling a handler can be significant.  This file allows the
+** user to define handlers that do something very simple like store the value
+** to memory and/or set a hasbit.  JIT compilers can then special-case these
+** handlers and emit specialized code for them instead of actually calling the
+** handler.
+**
+** The functionality is very simple/limited right now but may expand to be able
+** to call another function.
+*/
+
+#ifndef UPB_SHIM_H
+#define UPB_SHIM_H
+
+
+typedef struct {
+  size_t offset;
+  int32_t hasbit;
+} upb_shim_data;
+
+#ifdef __cplusplus
+
+namespace upb {
+
+struct Shim {
+  typedef upb_shim_data Data;
+
+  /* Sets a handler for the given field that writes the value to the given
+   * offset and, if hasbit >= 0, sets a bit at the given bit offset.  Returns
+   * true if the handler was set successfully. */
+  static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit);
+
+  /* If this handler is a shim, returns the corresponding upb::Shim::Data and
+   * stores the type in "type".  Otherwise returns NULL. */
+  static const Data* GetData(const Handlers* h, Handlers::Selector s,
+                             FieldDef::Type* type);
+};
+
+}  /* namespace upb */
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+                  int32_t hasbit);
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
+                                      upb_fieldtype_t *type);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ Wrappers. */
+namespace upb {
+inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs,
+                      int32_t hasbit) {
+  return upb_shim_set(h, f, ofs, hasbit);
+}
+inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s,
+                                       FieldDef::Type* type) {
+  return upb_shim_getdata(h, s, type);
+}
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_SHIM_H */
+/*
+** upb::SymbolTable (upb_symtab)
+**
+** A symtab (symbol table) stores a name->def map of upb_defs.  Clients could
+** always create such tables themselves, but upb_symtab has logic for resolving
+** symbolic references, and in particular, for keeping a whole set of consistent
+** defs when replacing some subset of those defs.  This logic is nontrivial.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_SYMTAB_H_
+#define UPB_SYMTAB_H_
+
+
+#ifdef __cplusplus
+#include <vector>
+namespace upb { class SymbolTable; }
+#endif
+
+UPB_DECLARE_DERIVED_TYPE(upb::SymbolTable, upb::RefCounted,
+                         upb_symtab, upb_refcounted)
+
+typedef struct {
+ UPB_PRIVATE_FOR_CPP
+  upb_strtable_iter iter;
+  upb_deftype_t type;
+} upb_symtab_iter;
+
+#ifdef __cplusplus
+
+/* Non-const methods in upb::SymbolTable are NOT thread-safe. */
+class upb::SymbolTable {
+ public:
+  /* Returns a new symbol table with a single ref owned by "owner."
+   * Returns NULL if memory allocation failed. */
+  static reffed_ptr<SymbolTable> New();
+
+  /* Include RefCounted base methods. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* For all lookup functions, the returned pointer is not owned by the
+   * caller; it may be invalidated by any non-const call or unref of the
+   * SymbolTable!  To protect against this, take a ref if desired. */
+
+  /* Freezes the symbol table: prevents further modification of it.
+   * After the Freeze() operation is successful, the SymbolTable must only be
+   * accessed via a const pointer.
+   *
+   * Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not
+   * a necessary step in using a SymbolTable.  If you have no need for it to be
+   * immutable, there is no need to freeze it ever.  However sometimes it is
+   * useful, and SymbolTables that are statically compiled into the binary are
+   * always frozen by nature. */
+  void Freeze();
+
+  /* Resolves the given symbol using the rules described in descriptor.proto,
+   * namely:
+   *
+   *    If the name starts with a '.', it is fully-qualified.  Otherwise,
+   *    C++-like scoping rules are used to find the type (i.e. first the nested
+   *    types within this message are searched, then within the parent, on up
+   *    to the root namespace).
+   *
+   * If not found, returns NULL. */
+  const Def* Resolve(const char* base, const char* sym) const;
+
+  /* Finds an entry in the symbol table with this exact name.  If not found,
+   * returns NULL. */
+  const Def* Lookup(const char *sym) const;
+  const MessageDef* LookupMessage(const char *sym) const;
+  const EnumDef* LookupEnum(const char *sym) const;
+
+  /* TODO: introduce a C++ iterator, but make it nice and templated so that if
+   * you ask for an iterator of MessageDef the iterated elements are strongly
+   * typed as MessageDef*. */
+
+  /* Adds the given mutable defs to the symtab, resolving all symbols
+   * (including enum default values) and finalizing the defs.  Only one def per
+   * name may be in the list, but defs can replace existing defs in the symtab.
+   * All defs must have a name -- anonymous defs are not allowed.  Anonymous
+   * defs can still be frozen by calling upb_def_freeze() directly.
+   *
+   * Any existing defs that can reach defs that are being replaced will
+   * themselves be replaced also, so that the resulting set of defs is fully
+   * consistent.
+   *
+   * This logic implemented in this method is a convenience; ultimately it
+   * calls some combination of upb_fielddef_setsubdef(), upb_def_dup(), and
+   * upb_freeze(), any of which the client could call themself.  However, since
+   * the logic for doing so is nontrivial, we provide it here.
+   *
+   * The entire operation either succeeds or fails.  If the operation fails,
+   * the symtab is unchanged, false is returned, and status indicates the
+   * error.  The caller passes a ref on all defs to the symtab (even if the
+   * operation fails).
+   *
+   * TODO(haberman): currently failure will leave the symtab unchanged, but may
+   * leave the defs themselves partially resolved.  Does this matter?  If so we
+   * could do a prepass that ensures that all symbols are resolvable and bail
+   * if not, so we don't mutate anything until we know the operation will
+   * succeed.
+   *
+   * TODO(haberman): since the defs must be mutable, refining a frozen def
+   * requires making mutable copies of the entire tree.  This is wasteful if
+   * only a few messages are changing.  We may want to add a way of adding a
+   * tree of frozen defs to the symtab (perhaps an alternate constructor where
+   * you pass the root of the tree?) */
+  bool Add(Def*const* defs, int n, void* ref_donor, upb_status* status);
+
+  bool Add(const std::vector<Def*>& defs, void *owner, Status* status) {
+    return Add((Def*const*)&defs[0], defs.size(), owner, status);
+  }
+
+ private:
+  UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+
+/* Include refcounted methods like upb_symtab_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_symtab, upb_symtab_upcast)
+
+upb_symtab *upb_symtab_new(const void *owner);
+void upb_symtab_freeze(upb_symtab *s);
+const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
+                                  const char *sym);
+const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
+                    upb_status *status);
+
+/* upb_symtab_iter i;
+ * for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i);
+ *     upb_symtab_next(&i)) {
+ *   const upb_def *def = upb_symtab_iter_def(&i);
+ *    // ...
+ * }
+ *
+ * For C we don't have separate iterators for const and non-const.
+ * It is the caller's responsibility to cast the upb_fielddef* to
+ * const if the upb_msgdef* is const. */
+void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
+                      upb_deftype_t type);
+void upb_symtab_next(upb_symtab_iter *iter);
+bool upb_symtab_done(const upb_symtab_iter *iter);
+const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ inline wrappers. */
+namespace upb {
+inline reffed_ptr<SymbolTable> SymbolTable::New() {
+  upb_symtab *s = upb_symtab_new(&s);
+  return reffed_ptr<SymbolTable>(s, &s);
+}
+
+inline void SymbolTable::Freeze() {
+  return upb_symtab_freeze(this);
+}
+inline const Def *SymbolTable::Resolve(const char *base,
+                                       const char *sym) const {
+  return upb_symtab_resolve(this, base, sym);
+}
+inline const Def* SymbolTable::Lookup(const char *sym) const {
+  return upb_symtab_lookup(this, sym);
+}
+inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const {
+  return upb_symtab_lookupmsg(this, sym);
+}
+inline bool SymbolTable::Add(
+    Def*const* defs, int n, void* ref_donor, upb_status* status) {
+  return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status);
+}
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_SYMTAB_H_ */
+/*
+** upb::descriptor::Reader (upb_descreader)
+**
+** Provides a way of building upb::Defs from data in descriptor.proto format.
+*/
+
+#ifndef UPB_DESCRIPTOR_H
+#define UPB_DESCRIPTOR_H
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace descriptor {
+class Reader;
+}  /* namespace descriptor */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader)
+
+#ifdef __cplusplus
+
+/* Class that receives descriptor data according to the descriptor.proto schema
+ * and use it to build upb::Defs corresponding to that schema. */
+class upb::descriptor::Reader {
+ public:
+  /* These handlers must have come from NewHandlers() and must outlive the
+   * Reader.
+   *
+   * TODO: generate the handlers statically (like we do with the
+   * descriptor.proto defs) so that there is no need to pass this parameter (or
+   * to build/memory-manage the handlers at runtime at all).  Unfortunately this
+   * is a bit tricky to implement for Handlers, but necessary to simplify this
+   * interface. */
+  static Reader* Create(Environment* env, const Handlers* handlers);
+
+  /* The reader's input; this is where descriptor.proto data should be sent. */
+  Sink* input();
+
+  /* Returns an array of all defs that have been parsed, and transfers ownership
+   * of them to "owner".  The number of defs is stored in *n.  Ownership of the
+   * returned array is retained and is invalidated by any other call into
+   * Reader.
+   *
+   * These defs are not frozen or resolved; they are ready to be added to a
+   * symtab. */
+  upb::Def** GetDefs(void* owner, int* n);
+
+  /* Builds and returns handlers for the reader, owned by "owner." */
+  static Handlers* NewHandlers(const void* owner);
+
+ private:
+  UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h);
+upb_sink *upb_descreader_input(upb_descreader *r);
+upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n);
+const upb_handlers *upb_descreader_newhandlers(const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ implementation details. ************************************************/
+namespace upb {
+namespace descriptor {
+inline Reader* Reader::Create(Environment* e, const Handlers *h) {
+  return upb_descreader_create(e, h);
+}
+inline Sink* Reader::input() { return upb_descreader_input(this); }
+inline upb::Def** Reader::GetDefs(void* owner, int* n) {
+  return upb_descreader_getdefs(this, owner, n);
+}
+}  /* namespace descriptor */
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_DESCRIPTOR_H */
+/* This file contains accessors for a set of compiled-in defs.
+ * Note that unlike Google's protobuf, it does *not* define
+ * generated classes or any other kind of data structure for
+ * actually storing protobufs.  It only contains *defs* which
+ * let you reflect over a protobuf *schema*.
+ */
+/* This file was generated by upbc (the upb compiler).
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_
+#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_
+
+
+#ifdef __cplusplus
+UPB_BEGIN_EXTERN_C
+#endif
+
+/* Enums */
+
+typedef enum {
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3
+} google_protobuf_FieldDescriptorProto_Label;
+
+typedef enum {
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17,
+  GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18
+} google_protobuf_FieldDescriptorProto_Type;
+
+typedef enum {
+  GOOGLE_PROTOBUF_FIELDOPTIONS_STRING = 0,
+  GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1,
+  GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2
+} google_protobuf_FieldOptions_CType;
+
+typedef enum {
+  GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1,
+  GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2,
+  GOOGLE_PROTOBUF_FILEOPTIONS_LITE_RUNTIME = 3
+} google_protobuf_FileOptions_OptimizeMode;
+
+/* Selectors */
+
+/* google.protobuf.DescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 8
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 9
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 10
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 11
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 12
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 14
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 15
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 17
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 18
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 19
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 20
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 21
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 23
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 24
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 25
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 26
+
+/* google.protobuf.DescriptorProto.ExtensionRange */
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2
+#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3
+
+/* google.protobuf.EnumDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9
+#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10
+
+/* google.protobuf.EnumOptions */
+#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6
+
+/* google.protobuf.EnumValueDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7
+
+/* google.protobuf.EnumValueOptions */
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+
+/* google.protobuf.FieldDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17
+#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18
+
+/* google.protobuf.FieldOptions */
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 10
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 11
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 12
+#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 13
+
+/* google.protobuf.FileDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38
+
+/* google.protobuf.FileDescriptorSet */
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5
+
+/* google.protobuf.FileOptions */
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19
+#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20
+
+/* google.protobuf.MessageOptions */
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6
+#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7
+
+/* google.protobuf.MethodDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11
+#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12
+
+/* google.protobuf.MethodOptions */
+#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+
+/* google.protobuf.ServiceDescriptorProto */
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9
+#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10
+
+/* google.protobuf.ServiceOptions */
+#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
+
+/* google.protobuf.SourceCodeInfo */
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5
+
+/* google.protobuf.SourceCodeInfo.Location */
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12
+#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13
+
+/* google.protobuf.UninterpretedOption */
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17
+
+/* google.protobuf.UninterpretedOption.NamePart */
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4
+#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5
+
+const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner);
+
+/* MessageDefs */
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption");
+  assert(m);
+  return m;
+}
+UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) {
+  const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart");
+  assert(m);
+  return m;
+}
+
+
+/* EnumDefs */
+UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) {
+  const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label");
+  assert(e);
+  return e;
+}
+UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) {
+  const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type");
+  assert(e);
+  return e;
+}
+UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) {
+  const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType");
+  assert(e);
+  return e;
+}
+UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) {
+  const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode");
+  assert(e);
+  return e;
+}
+
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_experimental_map_key(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); }
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upbdefs {
+namespace google {
+namespace protobuf {
+namespace descriptor {
+inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() {
+  const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s);
+  return upb::reffed_ptr<const upb::SymbolTable>(s, &s);
+}
+}  /* namespace descriptor */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+#define RETURN_REFFED(type, func) \
+    const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \
+    return upb::reffed_ptr<const type>(obj);
+
+namespace google {
+namespace protobuf {
+namespace DescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) }
+inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) }
+inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) }
+inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) }
+}  /* namespace DescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace DescriptorProto {
+namespace ExtensionRange {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) }
+inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) }
+inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) }
+}  /* namespace ExtensionRange */
+}  /* namespace DescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace EnumDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) }
+inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) }
+}  /* namespace EnumDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace EnumOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) }
+}  /* namespace EnumOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace EnumValueDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) }
+}  /* namespace EnumValueDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace EnumValueOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) }
+}  /* namespace EnumValueOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace FieldDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) }
+inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) }
+inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) }
+inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) }
+inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) }
+inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) }
+inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) }
+}  /* namespace FieldDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace FieldOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) }
+inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) }
+inline upb::reffed_ptr<const upb::FieldDef> experimental_map_key() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_experimental_map_key) }
+inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) }
+inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) }
+inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) }
+inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) }
+}  /* namespace FieldOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace FileDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) }
+inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) }
+inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) }
+inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) }
+inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) }
+inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) }
+inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) }
+inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) }
+inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) }
+}  /* namespace FileDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace FileDescriptorSet {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) }
+inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) }
+}  /* namespace FileDescriptorSet */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace FileOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) }
+inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) }
+inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) }
+inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) }
+inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) }
+inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) }
+inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) }
+inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) }
+inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) }
+inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) }
+}  /* namespace FileOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace MessageOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) }
+inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) }
+}  /* namespace MessageOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace MethodDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) }
+inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) }
+}  /* namespace MethodDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace MethodOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) }
+}  /* namespace MethodOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace ServiceDescriptorProto {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) }
+inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) }
+inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) }
+}  /* namespace ServiceDescriptorProto */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace ServiceOptions {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) }
+inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) }
+}  /* namespace ServiceOptions */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace SourceCodeInfo {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) }
+inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) }
+}  /* namespace SourceCodeInfo */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace SourceCodeInfo {
+namespace Location {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) }
+inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) }
+inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) }
+inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) }
+inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) }
+}  /* namespace Location */
+}  /* namespace SourceCodeInfo */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace UninterpretedOption {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) }
+inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) }
+inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) }
+inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) }
+inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) }
+inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) }
+inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) }
+inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) }
+}  /* namespace UninterpretedOption */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+namespace google {
+namespace protobuf {
+namespace UninterpretedOption {
+namespace NamePart {
+inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) }
+inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) }
+inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) }
+}  /* namespace NamePart */
+}  /* namespace UninterpretedOption */
+}  /* namespace protobuf */
+}  /* namespace google */
+
+}  /* namespace upbdefs */
+
+
+#undef RETURN_REFFED
+#endif /* __cplusplus */
+
+#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */
+/*
+** Internal-only definitions for the decoder.
+*/
+
+#ifndef UPB_DECODER_INT_H_
+#define UPB_DECODER_INT_H_
+
+#include <stdlib.h>
+/*
+** upb::pb::Decoder
+**
+** A high performance, streaming, resumable decoder for the binary protobuf
+** format.
+**
+** This interface works the same regardless of what decoder backend is being
+** used.  A client of this class does not need to know whether decoding is using
+** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder.  By default,
+** it will always use the fastest available decoder.  However, you can call
+** set_allow_jit(false) to disable any JIT decoder that might be available.
+** This is primarily useful for testing purposes.
+*/
+
+#ifndef UPB_DECODER_H_
+#define UPB_DECODER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class CodeCache;
+class Decoder;
+class DecoderMethod;
+class DecoderMethodOptions;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache)
+UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder)
+UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts)
+
+UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted,
+                         upb_pbdecodermethod, upb_refcounted)
+
+#ifdef __cplusplus
+
+/* The parameters one uses to construct a DecoderMethod.
+ * TODO(haberman): move allowjit here?  Seems more convenient for users.
+ * TODO(haberman): move this to be heap allocated for ABI stability. */
+class upb::pb::DecoderMethodOptions {
+ public:
+  /* Parameter represents the destination handlers that this method will push
+   * to. */
+  explicit DecoderMethodOptions(const Handlers* dest_handlers);
+
+  /* Should the decoder push submessages to lazy handlers for fields that have
+   * them?  The caller should set this iff the lazy handlers expect data that is
+   * in protobuf binary format and the caller wishes to lazy parse it. */
+  void set_lazy(bool lazy);
+#else
+struct upb_pbdecodermethodopts {
+#endif
+  const upb_handlers *handlers;
+  bool lazy;
+};
+
+#ifdef __cplusplus
+
+/* Represents the code to parse a protobuf according to a destination
+ * Handlers. */
+class upb::pb::DecoderMethod {
+ public:
+  /* Include base methods from upb::ReferenceCounted. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* The destination handlers that are statically bound to this method.
+   * This method is only capable of outputting to a sink that uses these
+   * handlers. */
+  const Handlers* dest_handlers() const;
+
+  /* The input handlers for this decoder method. */
+  const BytesHandler* input_handler() const;
+
+  /* Whether this method is native. */
+  bool is_native() const;
+
+  /* Convenience method for generating a DecoderMethod without explicitly
+   * creating a CodeCache. */
+  static reffed_ptr<const DecoderMethod> New(const DecoderMethodOptions& opts);
+
+ private:
+  UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod)
+};
+
+#endif
+
+/* Preallocation hint: decoder won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the decoder library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_PB_DECODER_SIZE 4408
+
+#ifdef __cplusplus
+
+/* A Decoder receives binary protobuf data on its input sink and pushes the
+ * decoded data to its output sink. */
+class upb::pb::Decoder {
+ public:
+  /* Constructs a decoder instance for the given method, which must outlive this
+   * decoder.  Any errors during parsing will be set on the given status, which
+   * must also outlive this decoder.
+   *
+   * The sink must match the given method. */
+  static Decoder* Create(Environment* env, const DecoderMethod* method,
+                         Sink* output);
+
+  /* Returns the DecoderMethod this decoder is parsing from. */
+  const DecoderMethod* method() const;
+
+  /* The sink on which this decoder receives input. */
+  BytesSink* input();
+
+  /* Returns number of bytes successfully parsed.
+   *
+   * This can be useful for determining the stream position where an error
+   * occurred.
+   *
+   * This value may not be up-to-date when called from inside a parsing
+   * callback. */
+  uint64_t BytesParsed() const;
+
+  /* Gets/sets the parsing nexting limit.  If the total number of nested
+   * submessages and repeated fields hits this limit, parsing will fail.  This
+   * is a resource limit that controls the amount of memory used by the parsing
+   * stack.
+   *
+   * Setting the limit will fail if the parser is currently suspended at a depth
+   * greater than this, or if memory allocation of the stack fails. */
+  size_t max_nesting() const;
+  bool set_max_nesting(size_t max);
+
+  void Reset();
+
+  static const size_t kSize = UPB_PB_DECODER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder)
+};
+
+#endif  /* __cplusplus */
+
+#ifdef __cplusplus
+
+/* A class for caching protobuf processing code, whether bytecode for the
+ * interpreted decoder or machine code for the JIT.
+ *
+ * This class is not thread-safe.
+ *
+ * TODO(haberman): move this to be heap allocated for ABI stability. */
+class upb::pb::CodeCache {
+ public:
+  CodeCache();
+  ~CodeCache();
+
+  /* Whether the cache is allowed to generate machine code.  Defaults to true.
+   * There is no real reason to turn it off except for testing or if you are
+   * having a specific problem with the JIT.
+   *
+   * Note that allow_jit = true does not *guarantee* that the code will be JIT
+   * compiled.  If this platform is not supported or the JIT was not compiled
+   * in, the code may still be interpreted. */
+  bool allow_jit() const;
+
+  /* This may only be called when the object is first constructed, and prior to
+   * any code generation, otherwise returns false and does nothing. */
+  bool set_allow_jit(bool allow);
+
+  /* Returns a DecoderMethod that can push data to the given handlers.
+   * If a suitable method already exists, it will be returned from the cache.
+   *
+   * Specifying the destination handlers here allows the DecoderMethod to be
+   * statically bound to the destination handlers if possible, which can allow
+   * more efficient decoding.  However the returned method may or may not
+   * actually be statically bound.  But in all cases, the returned method can
+   * push data to the given handlers. */
+  const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts);
+
+  /* If/when someone needs to explicitly create a dynamically-bound
+   * DecoderMethod*, we can add a method to get it here. */
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache)
+#else
+struct upb_pbcodecache {
+#endif
+  bool allow_jit_;
+
+  /* Array of mgroups. */
+  upb_inttable groups;
+};
+
+UPB_BEGIN_EXTERN_C
+
+upb_pbdecoder *upb_pbdecoder_create(upb_env *e,
+                                    const upb_pbdecodermethod *method,
+                                    upb_sink *output);
+const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
+upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d);
+uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
+size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
+bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
+void upb_pbdecoder_reset(upb_pbdecoder *d);
+
+void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
+                                  const upb_handlers *h);
+void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy);
+
+
+/* Include refcounted methods like upb_pbdecodermethod_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast)
+
+const upb_handlers *upb_pbdecodermethod_desthandlers(
+    const upb_pbdecodermethod *m);
+const upb_byteshandler *upb_pbdecodermethod_inputhandler(
+    const upb_pbdecodermethod *m);
+bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
+const upb_pbdecodermethod *upb_pbdecodermethod_new(
+    const upb_pbdecodermethodopts *opts, const void *owner);
+
+void upb_pbcodecache_init(upb_pbcodecache *c);
+void upb_pbcodecache_uninit(upb_pbcodecache *c);
+bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
+bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
+const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
+    upb_pbcodecache *c, const upb_pbdecodermethodopts *opts);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+namespace pb {
+
+/* static */
+inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m,
+                                Sink* sink) {
+  return upb_pbdecoder_create(env, m, sink);
+}
+inline const DecoderMethod* Decoder::method() const {
+  return upb_pbdecoder_method(this);
+}
+inline BytesSink* Decoder::input() {
+  return upb_pbdecoder_input(this);
+}
+inline uint64_t Decoder::BytesParsed() const {
+  return upb_pbdecoder_bytesparsed(this);
+}
+inline size_t Decoder::max_nesting() const {
+  return upb_pbdecoder_maxnesting(this);
+}
+inline bool Decoder::set_max_nesting(size_t max) {
+  return upb_pbdecoder_setmaxnesting(this, max);
+}
+inline void Decoder::Reset() { upb_pbdecoder_reset(this); }
+
+inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) {
+  upb_pbdecodermethodopts_init(this, h);
+}
+inline void DecoderMethodOptions::set_lazy(bool lazy) {
+  upb_pbdecodermethodopts_setlazy(this, lazy);
+}
+
+inline const Handlers* DecoderMethod::dest_handlers() const {
+  return upb_pbdecodermethod_desthandlers(this);
+}
+inline const BytesHandler* DecoderMethod::input_handler() const {
+  return upb_pbdecodermethod_inputhandler(this);
+}
+inline bool DecoderMethod::is_native() const {
+  return upb_pbdecodermethod_isnative(this);
+}
+/* static */
+inline reffed_ptr<const DecoderMethod> DecoderMethod::New(
+    const DecoderMethodOptions &opts) {
+  const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m);
+  return reffed_ptr<const DecoderMethod>(m, &m);
+}
+
+inline CodeCache::CodeCache() {
+  upb_pbcodecache_init(this);
+}
+inline CodeCache::~CodeCache() {
+  upb_pbcodecache_uninit(this);
+}
+inline bool CodeCache::allow_jit() const {
+  return upb_pbcodecache_allowjit(this);
+}
+inline bool CodeCache::set_allow_jit(bool allow) {
+  return upb_pbcodecache_setallowjit(this, allow);
+}
+inline const DecoderMethod *CodeCache::GetDecoderMethod(
+    const DecoderMethodOptions& opts) {
+  return upb_pbcodecache_getdecodermethod(this, &opts);
+}
+
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+#endif  /* UPB_DECODER_H_ */
+
+/* C++ names are not actually used since this type isn't exposed to users. */
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class MessageGroup;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted,
+                         mgroup, upb_refcounted)
+
+/* Opcode definitions.  The canonical meaning of each opcode is its
+ * implementation in the interpreter (the JIT is written to match this).
+ *
+ * All instructions have the opcode in the low byte.
+ * Instruction format for most instructions is:
+ *
+ * +-------------------+--------+
+ * |     arg (24)      | op (8) |
+ * +-------------------+--------+
+ *
+ * Exceptions are indicated below.  A few opcodes are multi-word. */
+typedef enum {
+  /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
+   * Arg for all of these is the upb selector for this field. */
+#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
+  T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
+  T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
+#undef T
+  OP_STARTMSG       = 9,   /* No arg. */
+  OP_ENDMSG         = 10,  /* No arg. */
+  OP_STARTSEQ       = 11,
+  OP_ENDSEQ         = 12,
+  OP_STARTSUBMSG    = 14,
+  OP_ENDSUBMSG      = 19,
+  OP_STARTSTR       = 20,
+  OP_STRING         = 21,
+  OP_ENDSTR         = 22,
+
+  OP_PUSHTAGDELIM   = 23,  /* No arg. */
+  OP_PUSHLENDELIM   = 24,  /* No arg. */
+  OP_POP            = 25,  /* No arg. */
+  OP_SETDELIM       = 26,  /* No arg. */
+  OP_SETBIGGROUPNUM = 27,  /* two words:
+                            *   | unused (24)     | opc (8) |
+                            *   |        groupnum (32)      | */
+  OP_CHECKDELIM     = 28,
+  OP_CALL           = 29,
+  OP_RET            = 30,
+  OP_BRANCH         = 31,
+
+  /* Different opcodes depending on how many bytes expected. */
+  OP_TAG1           = 32,  /* | match tag (16) | jump target (8) | opc (8) | */
+  OP_TAG2           = 33,  /* | match tag (16) | jump target (8) | opc (8) | */
+  OP_TAGN           = 34,  /* three words: */
+                           /*   | unused (16) | jump target(8) | opc (8) | */
+                           /*   |           match tag 1 (32)             | */
+                           /*   |           match tag 2 (32)             | */
+
+  OP_SETDISPATCH    = 35,  /* N words: */
+                           /*   | unused (24)         | opc | */
+                           /*   | upb_inttable* (32 or 64)  | */
+
+  OP_DISPATCH       = 36,  /* No arg. */
+
+  OP_HALT           = 37   /* No arg. */
+} opcode;
+
+#define OP_MAX OP_HALT
+
+UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; }
+
+/* Method group; represents a set of decoder methods that had their code
+ * emitted together, and must therefore be freed together.  Immutable once
+ * created.  It is possible we may want to expose this to users at some point.
+ *
+ * Overall ownership of Decoder objects looks like this:
+ *
+ *                +----------+
+ *                |          | <---> DecoderMethod
+ *                | method   |
+ * CodeCache ---> |  group   | <---> DecoderMethod
+ *                |          |
+ *                | (mgroup) | <---> DecoderMethod
+ *                +----------+
+ */
+struct mgroup {
+  upb_refcounted base;
+
+  /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod.  We own refs on the
+   * methods. */
+  upb_inttable methods;
+
+  /* When we add the ability to link to previously existing mgroups, we'll
+   * need an array of mgroups we reference here, and own refs on them. */
+
+  /* The bytecode for our methods, if any exists.  Owned by us. */
+  uint32_t *bytecode;
+  uint32_t *bytecode_end;
+
+#ifdef UPB_USE_JIT_X64
+  /* JIT-generated machine code, if any. */
+  upb_string_handlerfunc *jit_code;
+  /* The size of the jit_code (required to munmap()). */
+  size_t jit_size;
+  char *debug_info;
+  void *dl;
+#endif
+};
+
+/* The maximum that any submessages can be nested.  Matches proto2's limit.
+ * This specifies the size of the decoder's statically-sized array and therefore
+ * setting it high will cause the upb::pb::Decoder object to be larger.
+ *
+ * If necessary we can add a runtime-settable property to Decoder that allow
+ * this to be larger than the compile-time setting, but this would add
+ * complexity, particularly since we would have to decide how/if to give users
+ * the ability to set a custom memory allocation function. */
+#define UPB_DECODER_MAX_NESTING 64
+
+/* Internal-only struct used by the decoder. */
+typedef struct {
+  /* Space optimization note: we store two pointers here that the JIT
+   * doesn't need at all; the upb_handlers* inside the sink and
+   * the dispatch table pointer.  We can optimze so that the JIT uses
+   * smaller stack frames than the interpreter.  The only thing we need
+   * to guarantee is that the fallback routines can find end_ofs. */
+  upb_sink sink;
+
+  /* The absolute stream offset of the end-of-frame delimiter.
+   * Non-delimited frames (groups and non-packed repeated fields) reuse the
+   * delimiter of their parent, even though the frame may not end there.
+   *
+   * NOTE: the JIT stores a slightly different value here for non-top frames.
+   * It stores the value relative to the end of the enclosed message.  But the
+   * top frame is still stored the same way, which is important for ensuring
+   * that calls from the JIT into C work correctly. */
+  uint64_t end_ofs;
+  const uint32_t *base;
+
+  /* 0 indicates a length-delimited field.
+   * A positive number indicates a known group.
+   * A negative number indicates an unknown group. */
+  int32_t groupnum;
+  upb_inttable *dispatch;  /* Not used by the JIT. */
+} upb_pbdecoder_frame;
+
+struct upb_pbdecodermethod {
+  upb_refcounted base;
+
+  /* While compiling, the base is relative in "ofs", after compiling it is
+   * absolute in "ptr". */
+  union {
+    uint32_t ofs;     /* PC offset of method. */
+    void *ptr;        /* Pointer to bytecode or machine code for this method. */
+  } code_base;
+
+  /* The decoder method group to which this method belongs.  We own a ref.
+   * Owning a ref on the entire group is more coarse-grained than is strictly
+   * necessary; all we truly require is that methods we directly reference
+   * outlive us, while the group could contain many other messages we don't
+   * require.  But the group represents the messages that were
+   * allocated+compiled together, so it makes the most sense to free them
+   * together also. */
+  const upb_refcounted *group;
+
+  /* Whether this method is native code or bytecode. */
+  bool is_native_;
+
+  /* The handler one calls to invoke this method. */
+  upb_byteshandler input_handler_;
+
+  /* The destination handlers this method is bound to.  We own a ref. */
+  const upb_handlers *dest_handlers_;
+
+  /* Dispatch table -- used by both bytecode decoder and JIT when encountering a
+   * field number that wasn't the one we were expecting to see.  See
+   * decoder.int.h for the layout of this table. */
+  upb_inttable dispatch;
+};
+
+struct upb_pbdecoder {
+  upb_env *env;
+
+  /* Our input sink. */
+  upb_bytessink input_;
+
+  /* The decoder method we are parsing with (owned). */
+  const upb_pbdecodermethod *method_;
+
+  size_t call_len;
+  const uint32_t *pc, *last;
+
+  /* Current input buffer and its stream offset. */
+  const char *buf, *ptr, *end, *checkpoint;
+
+  /* End of the delimited region, relative to ptr, NULL if not in this buf. */
+  const char *delim_end;
+
+  /* End of the delimited region, relative to ptr, end if not in this buf. */
+  const char *data_end;
+
+  /* Overall stream offset of "buf." */
+  uint64_t bufstart_ofs;
+
+  /* Buffer for residual bytes not parsed from the previous buffer.
+   * The maximum number of residual bytes we require is 12; a five-byte
+   * unknown tag plus an eight-byte value, less one because the value
+   * is only a partial value. */
+  char residual[12];
+  char *residual_end;
+
+  /* Bytes of data that should be discarded from the input beore we start
+   * parsing again.  We set this when we internally determine that we can
+   * safely skip the next N bytes, but this region extends past the current
+   * user buffer. */
+  size_t skip;
+
+  /* Stores the user buffer passed to our decode function. */
+  const char *buf_param;
+  size_t size_param;
+  const upb_bufhandle *handle;
+
+  /* Our internal stack. */
+  upb_pbdecoder_frame *stack, *top, *limit;
+  const uint32_t **callstack;
+  size_t stack_size;
+
+  upb_status *status;
+
+#ifdef UPB_USE_JIT_X64
+  /* Used momentarily by the generated code to store a value while a user
+   * function is called. */
+  uint32_t tmp_len;
+
+  const void *saved_rsp;
+#endif
+};
+
+/* Decoder entry points; used as handlers. */
+void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
+void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint);
+size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
+                            size_t size, const upb_bufhandle *handle);
+bool upb_pbdecoder_end(void *closure, const void *handler_data);
+
+/* Decoder-internal functions that the JIT calls to handle fallback paths. */
+int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
+                             size_t size, const upb_bufhandle *handle);
+size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
+int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
+                                  uint8_t wire_type);
+int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
+int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
+int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
+int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
+void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
+
+/* Error messages that are shared between the bytecode and JIT decoders. */
+extern const char *kPbDecoderStackOverflow;
+extern const char *kPbDecoderSubmessageTooLong;
+
+/* Access to decoderplan members needed by the decoder. */
+const char *upb_pbdecoder_getopname(unsigned int op);
+
+/* JIT codegen entry point. */
+void upb_pbdecoder_jit(mgroup *group);
+void upb_pbdecoder_freejit(mgroup *group);
+UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast)
+
+/* A special label that means "do field dispatch for this message and branch to
+ * wherever that takes you." */
+#define LABEL_DISPATCH 0
+
+/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or
+ * RET) for branching to when we find an appropriate ENDGROUP tag. */
+#define DISPATCH_ENDMSG 0
+
+/* It's important to use this invalid wire type instead of 0 (which is a valid
+ * wire type). */
+#define NO_WIRE_TYPE 0xff
+
+/* The dispatch table layout is:
+ *   [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
+ *
+ * If wt1 matches, jump to the 48-bit offset.  If wt2 matches, lookup
+ * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
+ *
+ * We need two wire types because of packed/non-packed compatibility.  A
+ * primitive repeated field can use either wire type and be valid.  While we
+ * could key the table on fieldnum+wiretype, the table would be 8x sparser.
+ *
+ * Storing two wire types in the primary value allows us to quickly rule out
+ * the second wire type without needing to do a separate lookup (this case is
+ * less common than an unknown field). */
+UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1,
+                                               uint8_t wt2) {
+  return (ofs << 16) | (wt2 << 8) | wt1;
+}
+
+UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
+                                             uint8_t *wt1, uint8_t *wt2) {
+  *wt1 = (uint8_t)dispatch;
+  *wt2 = (uint8_t)(dispatch >> 8);
+  *ofs = dispatch >> 16;
+}
+
+/* All of the functions in decoder.c that return int32_t return values according
+ * to the following scheme:
+ *   1. negative values indicate a return code from the following list.
+ *   2. positive values indicate that error or end of buffer was hit, and
+ *      that the decode function should immediately return the given value
+ *      (the decoder state has already been suspended and is ready to be
+ *      resumed). */
+#define DECODE_OK -1
+#define DECODE_MISMATCH -2  /* Used only from checktag_slow(). */
+#define DECODE_ENDGROUP -3  /* Used only from checkunknown(). */
+
+#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; }
+
+#endif  /* UPB_DECODER_INT_H_ */
+/*
+** A number of routines for varint manipulation (we keep them all around to
+** have multiple approaches available for benchmarking).
+*/
+
+#ifndef UPB_VARINT_DECODER_H_
+#define UPB_VARINT_DECODER_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A list of types as they are encoded on-the-wire. */
+typedef enum {
+  UPB_WIRE_TYPE_VARINT      = 0,
+  UPB_WIRE_TYPE_64BIT       = 1,
+  UPB_WIRE_TYPE_DELIMITED   = 2,
+  UPB_WIRE_TYPE_START_GROUP = 3,
+  UPB_WIRE_TYPE_END_GROUP   = 4,
+  UPB_WIRE_TYPE_32BIT       = 5
+} upb_wiretype_t;
+
+#define UPB_MAX_WIRE_TYPE 5
+
+/* The maximum number of bytes that it takes to encode a 64-bit varint.
+ * Note that with a better encoding this could be 9 (TODO: write up a
+ * wiki document about this). */
+#define UPB_PB_VARINT_MAX_LEN 10
+
+/* Array of the "native" (ie. non-packed-repeated) wire type for the given a
+ * descriptor type (upb_descriptortype_t). */
+extern const uint8_t upb_pb_native_wire_types[];
+
+/* Zig-zag encoding/decoding **************************************************/
+
+UPB_INLINE int32_t upb_zzdec_32(uint32_t n) {
+  return (n >> 1) ^ -(int32_t)(n & 1);
+}
+UPB_INLINE int64_t upb_zzdec_64(uint64_t n) {
+  return (n >> 1) ^ -(int64_t)(n & 1);
+}
+UPB_INLINE uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); }
+UPB_INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); }
+
+/* Decoding *******************************************************************/
+
+/* All decoding functions return this struct by value. */
+typedef struct {
+  const char *p;  /* NULL if the varint was unterminated. */
+  uint64_t val;
+} upb_decoderet;
+
+UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) {
+  upb_decoderet ret;
+  ret.p = p;
+  ret.val = val;
+  return ret;
+}
+
+/* Four functions for decoding a varint of at most eight bytes.  They are all
+ * functionally identical, but are implemented in different ways and likely have
+ * different performance profiles.  We keep them around for performance testing.
+ *
+ * Note that these functions may not read byte-by-byte, so they must not be used
+ * unless there are at least eight bytes left in the buffer! */
+upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_wright(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r);
+
+/* Template for a function that checks the first two bytes with branching
+ * and dispatches 2-10 bytes with a separate function.  Note that this may read
+ * up to 10 bytes, so it must not be used unless there are at least ten bytes
+ * left in the buffer! */
+#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function)                  \
+UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) {         \
+  uint8_t *p = (uint8_t*)_p;                                                   \
+  upb_decoderet r;                                                             \
+  if ((*p & 0x80) == 0) {                                                      \
+  /* Common case: one-byte varint. */                                          \
+    return upb_decoderet_make(_p + 1, *p & 0x7fU);                             \
+  }                                                                            \
+  r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7));    \
+  if ((*(p + 1) & 0x80) == 0) {                                                \
+    /* Two-byte varint. */                                                     \
+    return r;                                                                  \
+  }                                                                            \
+  /* Longer varint, fallback to out-of-line function. */                       \
+  return decode_max8_function(r);                                              \
+}
+
+UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
+UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
+UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright)
+UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino)
+#undef UPB_VARINT_DECODER_CHECK2
+
+/* Our canonical functions for decoding varints, based on the currently
+ * favored best-performing implementations. */
+UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
+  if (sizeof(long) == 8)
+    return upb_vdecode_check2_branch64(p);
+  else
+    return upb_vdecode_check2_branch32(p);
+}
+
+UPB_INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) {
+  return upb_vdecode_max8_massimino(r);
+}
+
+
+/* Encoding *******************************************************************/
+
+UPB_INLINE int upb_value_size(uint64_t val) {
+#ifdef __GNUC__
+  int high_bit = 63 - __builtin_clzll(val);  /* 0-based, undef if val == 0. */
+#else
+  int high_bit = 0;
+  uint64_t tmp = val;
+  while(tmp >>= 1) high_bit++;
+#endif
+  return val == 0 ? 1 : high_bit / 8 + 1;
+}
+
+/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN
+ * bytes long), returning how many bytes were used.
+ *
+ * TODO: benchmark and optimize if necessary. */
+UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) {
+  size_t i;
+  if (val == 0) { buf[0] = 0; return 1; }
+  i = 0;
+  while (val) {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  }
+  return i;
+}
+
+UPB_INLINE size_t upb_varint_size(uint64_t val) {
+  char buf[UPB_PB_VARINT_MAX_LEN];
+  return upb_vencode64(val, buf);
+}
+
+/* Encodes a 32-bit varint, *not* sign-extended. */
+UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
+  char buf[UPB_PB_VARINT_MAX_LEN];
+  size_t bytes = upb_vencode64(val, buf);
+  uint64_t ret = 0;
+  assert(bytes <= 5);
+  memcpy(&ret, buf, bytes);
+  assert(ret <= 0xffffffffffU);
+  return ret;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_VARINT_DECODER_H_ */
+/*
+** upb::pb::Encoder (upb_pb_encoder)
+**
+** Implements a set of upb_handlers that write protobuf data to the binary wire
+** format.
+**
+** This encoder implementation does not have any access to any out-of-band or
+** precomputed lengths for submessages, so it must buffer submessages internally
+** before it can emit the first byte.
+*/
+
+#ifndef UPB_ENCODER_H_
+#define UPB_ENCODER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class Encoder;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder)
+
+#define UPB_PBENCODER_MAX_NESTING 100
+
+/* upb::pb::Encoder ***********************************************************/
+
+/* Preallocation hint: decoder won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the decoder library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_PB_ENCODER_SIZE 768
+
+#ifdef __cplusplus
+
+class upb::pb::Encoder {
+ public:
+  /* Creates a new encoder in the given environment.  The Handlers must have
+   * come from NewHandlers() below. */
+  static Encoder* Create(Environment* env, const Handlers* handlers,
+                         BytesSink* output);
+
+  /* The input to the encoder. */
+  Sink* input();
+
+  /* Creates a new set of handlers for this MessageDef. */
+  static reffed_ptr<const Handlers> NewHandlers(const MessageDef* msg);
+
+  static const size_t kSize = UPB_PB_ENCODER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
+                                               const void *owner);
+upb_sink *upb_pb_encoder_input(upb_pb_encoder *p);
+upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h,
+                                      upb_bytessink* output);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace pb {
+inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers,
+                                BytesSink* output) {
+  return upb_pb_encoder_create(env, handlers, output);
+}
+inline Sink* Encoder::input() {
+  return upb_pb_encoder_input(this);
+}
+inline reffed_ptr<const Handlers> Encoder::NewHandlers(
+    const upb::MessageDef *md) {
+  const Handlers* h = upb_pb_encoder_newhandlers(md, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_ENCODER_H_ */
+/*
+** upb's core components like upb_decoder and upb_msg are carefully designed to
+** avoid depending on each other for maximum orthogonality.  In other words,
+** you can use a upb_decoder to decode into *any* kind of structure; upb_msg is
+** just one such structure.  A upb_msg can be serialized/deserialized into any
+** format, protobuf binary format is just one such format.
+**
+** However, for convenience we provide functions here for doing common
+** operations like deserializing protobuf binary format into a upb_msg.  The
+** compromise is that this file drags in almost all of upb as a dependency,
+** which could be undesirable if you're trying to use a trimmed-down build of
+** upb.
+**
+** While these routines are convenient, they do not reuse any encoding/decoding
+** state.  For example, if a decoder is JIT-based, it will be re-JITted every
+** time these functions are called.  For this reason, if you are parsing lots
+** of data and efficiency is an issue, these may not be the best functions to
+** use (though they are useful for prototyping, before optimizing).
+*/
+
+#ifndef UPB_GLUE_H
+#define UPB_GLUE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Loads all defs from the given protobuf binary descriptor, setting default
+ * accessors and a default layout on all messages.  The caller owns the
+ * returned array of defs, which will be of length *n.  On error NULL is
+ * returned and status is set (if non-NULL). */
+upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
+                                        void *owner, upb_status *status);
+
+/* Like the previous but also adds the loaded defs to the given symtab. */
+bool upb_load_descriptor_into_symtab(upb_symtab *symtab, const char *str,
+                                     size_t len, upb_status *status);
+
+/* Like the previous but also reads the descriptor from the given filename. */
+bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
+                                          upb_status *status);
+
+/* Reads the given filename into a character string, returning NULL if there
+ * was an error. */
+char *upb_readfile(const char *filename, size_t *len);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+
+namespace upb {
+
+/* All routines that load descriptors expect the descriptor to be a
+ * FileDescriptorSet. */
+inline bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname,
+                                         Status* status) {
+  return upb_load_descriptor_file_into_symtab(s, fname, status);
+}
+
+inline bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str,
+                                     size_t len, Status* status) {
+  return upb_load_descriptor_into_symtab(s, str, len, status);
+}
+
+/* Templated so it can accept both string and std::string. */
+template <typename T>
+bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) {
+  return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status);
+}
+
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_GLUE_H */
+/*
+** upb::pb::TextPrinter (upb_textprinter)
+**
+** Handlers for writing to protobuf text format.
+*/
+
+#ifndef UPB_TEXT_H_
+#define UPB_TEXT_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class TextPrinter;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter)
+
+#ifdef __cplusplus
+
+class upb::pb::TextPrinter {
+ public:
+  /* The given handlers must have come from NewHandlers().  It must outlive the
+   * TextPrinter. */
+  static TextPrinter *Create(Environment *env, const upb::Handlers *handlers,
+                             BytesSink *output);
+
+  void SetSingleLineMode(bool single_line);
+
+  Sink* input();
+
+  /* If handler caching becomes a requirement we can add a code cache as in
+   * decoder.h */
+  static reffed_ptr<const Handlers> NewHandlers(const MessageDef* md);
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
+                                        upb_bytessink *output);
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
+upb_sink *upb_textprinter_input(upb_textprinter *p);
+
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+                                                const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace pb {
+inline TextPrinter *TextPrinter::Create(Environment *env,
+                                        const upb::Handlers *handlers,
+                                        BytesSink *output) {
+  return upb_textprinter_create(env, handlers, output);
+}
+inline void TextPrinter::SetSingleLineMode(bool single_line) {
+  upb_textprinter_setsingleline(this, single_line);
+}
+inline Sink* TextPrinter::input() {
+  return upb_textprinter_input(this);
+}
+inline reffed_ptr<const Handlers> TextPrinter::NewHandlers(
+    const MessageDef *md) {
+  const Handlers* h = upb_textprinter_newhandlers(md, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_TEXT_H_ */
+/*
+** upb::json::Parser (upb_json_parser)
+**
+** Parses JSON according to a specific schema.
+** Support for parsing arbitrary JSON (schema-less) will be added later.
+*/
+
+#ifndef UPB_JSON_PARSER_H_
+#define UPB_JSON_PARSER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace json {
+class Parser;
+}  /* namespace json */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
+
+/* upb::json::Parser **********************************************************/
+
+/* Preallocation hint: parser won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the parser library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_JSON_PARSER_SIZE 3704
+
+#ifdef __cplusplus
+
+/* Parses an incoming BytesStream, pushing the results to the destination
+ * sink. */
+class upb::json::Parser {
+ public:
+  static Parser* Create(Environment* env, Sink* output);
+
+  BytesSink* input();
+
+ private:
+  UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+upb_json_parser *upb_json_parser_create(upb_env *e, upb_sink *output);
+upb_bytessink *upb_json_parser_input(upb_json_parser *p);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace json {
+inline Parser* Parser::Create(Environment* env, Sink* output) {
+  return upb_json_parser_create(env, output);
+}
+inline BytesSink* Parser::input() {
+  return upb_json_parser_input(this);
+}
+}  /* namespace json */
+}  /* namespace upb */
+
+#endif
+
+
+#endif  /* UPB_JSON_PARSER_H_ */
+/*
+** upb::json::Printer
+**
+** Handlers that emit JSON according to a specific protobuf schema.
+*/
+
+#ifndef UPB_JSON_TYPED_PRINTER_H_
+#define UPB_JSON_TYPED_PRINTER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace json {
+class Printer;
+}  /* namespace json */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer)
+
+
+/* upb::json::Printer *********************************************************/
+
+#define UPB_JSON_PRINTER_SIZE 168
+
+#ifdef __cplusplus
+
+/* Prints an incoming stream of data to a BytesSink in JSON format. */
+class upb::json::Printer {
+ public:
+  static Printer* Create(Environment* env, const upb::Handlers* handlers,
+                         BytesSink* output);
+
+  /* The input to the printer. */
+  Sink* input();
+
+  /* Returns handlers for printing according to the specified schema. */
+  static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md);
+
+  static const size_t kSize = UPB_JSON_PRINTER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
+                                          upb_bytessink *output);
+upb_sink *upb_json_printer_input(upb_json_printer *p);
+const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+                                                 const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace json {
+inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers,
+                                BytesSink* output) {
+  return upb_json_printer_create(env, handlers, output);
+}
+inline Sink* Printer::input() { return upb_json_printer_input(this); }
+inline reffed_ptr<const Handlers> Printer::NewHandlers(
+    const upb::MessageDef *md) {
+  const Handlers* h = upb_json_printer_newhandlers(md, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace json */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_JSON_TYPED_PRINTER_H_ */
diff --git a/src/third_party/protobuf-3/php/tests/autoload.php b/src/third_party/protobuf-3/php/tests/autoload.php
new file mode 100644
index 0000000..af88ba0
--- /dev/null
+++ b/src/third_party/protobuf-3/php/tests/autoload.php
@@ -0,0 +1,4 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_util.php');
diff --git a/src/third_party/protobuf-3/post_process_dist.sh b/src/third_party/protobuf-3/post_process_dist.sh
new file mode 100755
index 0000000..82736bd
--- /dev/null
+++ b/src/third_party/protobuf-3/post_process_dist.sh
@@ -0,0 +1,64 @@
+#! /bin/sh
+
+# This script takes the result of "make dist" and:
+# 1) Unpacks it.
+# 2) Ensures all contents are user-writable.  Some version control systems
+#    keep code read-only until you explicitly ask to edit it, and the normal
+#    "make dist" process does not correct for this, so the result is that
+#    the entire dist is still marked read-only when unpacked, which is
+#    annoying.  So, we fix it.
+# 3) Convert MSVC project files to MSVC 2005, so that anyone who has version
+#    2005 *or* 2008 can open them.  (In version control, we keep things in
+#    MSVC 2008 format since that's what we use in development.)
+# 4) Uses the result to create .tar.gz, .tar.bz2, and .zip versions and
+#    deposites them in the "dist" directory.  In the .zip version, all
+#    non-testdata .txt files are converted to Windows-style line endings.
+# 5) Cleans up after itself.
+
+if [ "$1" == "" ]; then
+  echo "USAGE:  $0 DISTFILE" >&2
+  exit 1
+fi
+
+if [ ! -e $1 ]; then
+  echo $1": File not found." >&2
+  exit 1
+fi
+
+set -ex
+
+LANGUAGES="cpp csharp java javanano js objectivec python ruby"
+BASENAME=`basename $1 .tar.gz`
+VERSION=${BASENAME:9}
+
+# Create a directory called "dist", copy the tarball there and unpack it.
+mkdir dist
+cp $1 dist
+cd dist
+tar zxvf $BASENAME.tar.gz
+rm $BASENAME.tar.gz
+
+# Set the entire contents to be user-writable.
+chmod -R u+w $BASENAME
+cd $BASENAME
+
+for LANG in $LANGUAGES; do
+  # Build the dist again in .tar.gz
+  ./configure DIST_LANG=$LANG
+  make dist-gzip
+  mv $BASENAME.tar.gz ../protobuf-$LANG-$VERSION.tar.gz
+done
+
+# Convert all text files to use DOS-style line endings, then build a .zip
+# distribution.
+todos *.txt */*.txt
+
+for LANG in $LANGUAGES; do
+  # Build the dist again in .zip
+  ./configure DIST_LANG=$LANG
+  make dist-zip
+  mv $BASENAME.zip ../protobuf-$LANG-$VERSION.zip
+done
+
+cd ..
+rm -rf $BASENAME
diff --git a/src/third_party/protobuf-3/proto_library.gni b/src/third_party/protobuf-3/proto_library.gni
new file mode 100644
index 0000000..84373f3
--- /dev/null
+++ b/src/third_party/protobuf-3/proto_library.gni
@@ -0,0 +1,389 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Compile a protocol buffer.
+#
+# Protobuf parameters:
+#
+#   proto_in_dir (optional)
+#       Specifies the path relative to the current BUILD.gn file where
+#       proto files are located and the directory structure of
+#       this proto library starts.
+#
+#       This option can be calculated automatically but it will raise an
+#       assertion error if any nested directories are found.
+#
+#   proto_out_dir (optional)
+#       Specifies the path suffix that output files are generated under.
+#       This path will be appended to |root_gen_dir|, but for python stubs
+#       it will be appended to |root_build_dir|/pyproto.
+#
+#   generate_python (optional, default true)
+#       Generate Python protobuf stubs.
+#
+#   generate_cc (optional, default true)
+#       Generate C++ protobuf stubs.
+#
+#   cc_generator_options (optional)
+#       List of extra flags passed to the protocol compiler.  If you need to
+#       add an EXPORT macro to a protobuf's C++ header, set the
+#       'cc_generator_options' variable with the value:
+#       'dllexport_decl=FOO_EXPORT:' (note trailing colon).
+#
+#       It is likely you also need to #include a file for the above EXPORT
+#       macro to work (see cc_include) and set
+#       component_build_force_source_set = true.
+#
+#   cc_include (optional)
+#       String listing an extra include that should be passed.
+#       Example: cc_include = "foo/bar.h"
+#
+#   generator_plugin_label (optional)
+#       GN label for plugin executable which generates custom cc stubs.
+#       Don't specify a toolchain, host toolchain is assumed.
+#
+#   generator_plugin_script (optional)
+#       Path to plugin script. Mutually exclusive with |generator_plugin_label|.
+#
+#   generator_plugin_script_deps (optional)
+#       List of additional files required for generator plugin script.
+#
+#   generator_plugin_suffix[es] (required if using a plugin)
+#       Suffix (before extension) for generated .cc and .h files
+#       or list of suffixes for all files (with extensions).
+#
+#   generator_plugin_options (optional)
+#       Extra flags passed to the plugin. See cc_generator_options.
+#
+#   deps (optional)
+#       Additional dependencies.
+#
+#   use_protobuf_full (optional)
+#       If adding protobuf library would be required, adds protobuf_full to deps
+#       instead of protobuf_lite.
+#
+#   import_dirs (optional)
+#       A list of extra import directories to be passed to protoc compiler. The
+#       default case is just proto_in_dir.
+#       WARNING: This options should not be used in Chrome code until
+#       http://crbug.com/691451 is resolved.
+#
+# Parameters for compiling the generated code:
+#
+#   component_build_force_source_set (Default=false)
+#       When set true the generated code will be compiled as a source set in
+#       the component build. This does not affect static builds.  If you are
+#       exporting symbols from a component, this is required to prevent those
+#       symbols from being stripped. If you're not using dllexports in
+#       cc_generator_options, it's usually best to leave this false.
+#
+#   defines (optional)
+#       Defines to supply to the source set that compiles the generated source
+#       code.
+#
+#   extra_configs (optional)
+#       A list of config labels that will be appended to the configs applying
+#       to the source set.
+#
+# Example:
+#  proto_library("mylib") {
+#    sources = [
+#      "foo.proto",
+#    ]
+#  }
+
+template("proto_library") {
+  assert(defined(invoker.sources), "Need sources for proto_library")
+  proto_sources = invoker.sources
+
+  # Don't apply OS-specific sources filtering to the assignments later on.
+  # Platform files should have gotten filtered out in the sources assignment
+  # when this template was invoked. If they weren't, it was on purpose and
+  # this template shouldn't re-apply the filter.
+  set_sources_assignment_filter([])
+
+  if (host_os == "win") {
+    host_executable_suffix = ".exe"
+  } else {
+    host_executable_suffix = ""
+  }
+
+  if (defined(invoker.generate_cc)) {
+    generate_cc = invoker.generate_cc
+  } else {
+    generate_cc = true
+  }
+
+  if (defined(invoker.generate_python)) {
+    generate_python = invoker.generate_python
+  } else {
+    generate_python = true
+  }
+
+  if (defined(invoker.generator_plugin_label)) {
+    # Straightforward way to get the name of executable doesn't work because
+    # |root_out_dir| and |root_build_dir| may differ in cross-compilation and
+    # also Windows executables have .exe at the end.
+
+    plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
+    plugin_path =
+        get_label_info(plugin_host_label, "root_out_dir") + "/" +
+        get_label_info(plugin_host_label, "name") + host_executable_suffix
+    generate_with_plugin = true
+  } else if (defined(invoker.generator_plugin_script)) {
+    plugin_path = invoker.generator_plugin_script
+    generate_with_plugin = true
+  } else {
+    generate_with_plugin = false
+  }
+
+  if (generate_with_plugin) {
+    if (defined(invoker.generator_plugin_suffix)) {
+      generator_plugin_suffixes = [
+        "${invoker.generator_plugin_suffix}.h",
+        "${invoker.generator_plugin_suffix}.cc",
+      ]
+    } else {
+      generator_plugin_suffixes = invoker.generator_plugin_suffixes
+    }
+  }
+
+  if (defined(invoker.proto_in_dir)) {
+    proto_in_dir = invoker.proto_in_dir
+    has_nested_dirs = false
+    foreach(proto_source, proto_sources) {
+      if (get_path_info(proto_source, "dir") != proto_in_dir) {
+        has_nested_dirs = true
+      }
+    }
+  } else {
+    proto_in_dir = get_path_info(proto_sources[0], "dir")
+    has_nested_dirs = false
+
+    # Sanity check, |proto_in_dir| should be defined to allow sub-directories.
+    foreach(proto_source, proto_sources) {
+      assert(get_path_info(proto_source, "dir") == proto_in_dir,
+             "Please define |proto_in_dir| to allow nested directories.")
+    }
+  }
+
+  # Avoid absolute path because of the assumption that |proto_in_dir| is
+  # relative to the directory of current BUILD.gn file.
+  proto_in_dir = rebase_path(proto_in_dir, ".")
+
+  if (defined(invoker.proto_out_dir)) {
+    proto_out_dir = invoker.proto_out_dir
+  } else {
+    # Absolute path to the directory of current BUILD.gn file excluding "//".
+    proto_out_dir = rebase_path(".", "//")
+    if (proto_in_dir != ".") {
+      proto_out_dir += "/$proto_in_dir"
+    }
+  }
+
+  # We need both absolute path to use in GN statements and a relative one
+  # to pass to external script.
+  if (generate_cc || generate_with_plugin) {
+    cc_out_dir = "$root_gen_dir/" + proto_out_dir
+    rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir)
+  }
+  if (generate_python) {
+    py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir
+    rel_py_out_dir = rebase_path(py_out_dir, root_build_dir)
+  }
+
+  protos = rebase_path(invoker.sources, proto_in_dir)
+  protogens = []
+
+  # List output files.
+  foreach(proto, protos) {
+    proto_dir = get_path_info(proto, "dir")
+    proto_name = get_path_info(proto, "name")
+    proto_path = proto_dir + "/" + proto_name
+
+    if (generate_cc) {
+      protogens += [
+        "$cc_out_dir/$proto_path.pb.h",
+        "$cc_out_dir/$proto_path.pb.cc",
+      ]
+    }
+    if (generate_python) {
+      protogens += [ "$py_out_dir/${proto_path}_pb2.py" ]
+    }
+    if (generate_with_plugin) {
+      foreach(suffix, generator_plugin_suffixes) {
+        protogens += [ "$cc_out_dir/${proto_path}${suffix}" ]
+      }
+    }
+  }
+
+  action_name = "${target_name}_gen"
+  source_set_name = target_name
+
+  # Generate protobuf stubs.
+  action(action_name) {
+    visibility = [ ":$source_set_name" ]
+    script = "//tools/protoc_wrapper/protoc_wrapper.py"
+    sources = proto_sources
+    outputs = get_path_info(protogens, "abspath")
+    args = protos
+
+    protoc_label = "//third_party/protobuf:protoc($host_toolchain)"
+    protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" +
+                  host_executable_suffix
+    args += [
+      # Wrapper should never pick a system protoc.
+      # Path should be rebased because |root_build_dir| for current toolchain
+      # may be different from |root_out_dir| of protoc built on host toolchain.
+      "--protoc",
+      "./" + rebase_path(protoc_path, root_build_dir),
+      "--proto-in-dir",
+      rebase_path(proto_in_dir, root_build_dir),
+    ]
+
+    if (generate_cc) {
+      args += [
+        "--cc-out-dir",
+        rel_cc_out_dir,
+      ]
+      if (defined(invoker.cc_generator_options)) {
+        args += [
+          "--cc-options",
+          invoker.cc_generator_options,
+        ]
+      }
+      if (defined(invoker.cc_include)) {
+        args += [
+          "--include",
+          invoker.cc_include,
+        ]
+      }
+    }
+
+    if (generate_python) {
+      args += [
+        "--py-out-dir",
+        rel_py_out_dir,
+      ]
+    }
+
+    if (generate_with_plugin) {
+      args += [
+        "--plugin",
+        rebase_path(plugin_path, root_build_dir),
+        "--plugin-out-dir",
+        rel_cc_out_dir,
+      ]
+      if (defined(invoker.generator_plugin_options)) {
+        args += [
+          "--plugin-options",
+          invoker.generator_plugin_options,
+        ]
+      }
+    }
+
+    if (defined(invoker.import_dirs)) {
+      foreach(path, invoker.import_dirs) {
+        args += ["--import-dir=" + rebase_path(path, root_build_dir)]
+      }
+    }
+
+    # System protoc is not used so it's necessary to build a chromium one.
+    inputs = [
+      protoc_path,
+    ]
+    deps = [
+      protoc_label,
+    ]
+
+    if (generate_with_plugin) {
+      inputs += [ plugin_path ]
+      if (defined(invoker.generator_plugin_script_deps)) {
+        # Additional scripts for plugin.
+        inputs += invoker.generator_plugin_script_deps
+      }
+      if (defined(plugin_host_label)) {
+        # Action depends on native generator plugin but for host toolchain only.
+        deps += [ plugin_host_label ]
+      }
+    }
+
+    if (defined(invoker.deps)) {
+      # The deps may have steps that have to run before running protoc.
+      deps += invoker.deps
+    }
+  }
+
+  # Option to disable building a library in component build.
+  if (defined(invoker.component_build_force_source_set) &&
+      invoker.component_build_force_source_set && is_component_build) {
+    link_target_type = "source_set"
+  } else {
+    link_target_type = "static_library"
+  }
+
+  # Generated files may include other generated headers. These includes always
+  # use relative paths starting at |cc_out_dir|.
+  # However there is no necessity to add an additional directory, if all protos
+  # are located in the same directory which is in the search path by default.
+  if (has_nested_dirs) {
+    config_name = "${target_name}_config"
+    config(config_name) {
+      include_dirs = [ cc_out_dir ]
+    }
+  }
+
+  # Build generated protobuf stubs as libary or source set.
+  target(link_target_type, target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "defines",
+                             "testonly",
+                             "visibility",
+                           ])
+
+    sources = get_target_outputs(":$action_name")
+
+    if (defined(invoker.extra_configs)) {
+      configs += invoker.extra_configs
+    }
+
+    public_configs = [ "//third_party/protobuf:using_proto" ]
+
+    if (generate_cc || generate_with_plugin) {
+      # Not necessary if all protos are located in the same directory.
+      if (has_nested_dirs) {
+        # It's not enough to set |include_dirs| for target since public imports
+        # expose corresponding includes to header files as well.
+        public_configs += [ ":$config_name" ]
+      }
+
+      # If using built-in cc generator, the resulting headers reference headers
+      # within protobuf_lite. Hence, dependencies require those headers too.
+      # If using generator plugin, extra deps should be resolved by the invoker.
+      if (generate_cc) {
+        if (defined(invoker.use_protobuf_full) &&
+            invoker.use_protobuf_full == true) {
+          public_deps = [
+            "//third_party/protobuf:protobuf_full",
+          ]
+        } else {
+          public_deps = [
+            "//third_party/protobuf:protobuf_lite",
+          ]
+        }
+      }
+    }
+
+    deps = [
+      ":$action_name",
+    ]
+
+    # This will link any libraries in the deps (the use of invoker.deps in the
+    # action won't link it).
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+  }
+}
diff --git a/src/third_party/protobuf-3/protobuf-lite.pc.in b/src/third_party/protobuf-3/protobuf-lite.pc.in
new file mode 100644
index 0000000..80f1f46
--- /dev/null
+++ b/src/third_party/protobuf-3/protobuf-lite.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Protocol Buffers
+Description: Google's Data Interchange Format
+Version: @VERSION@
+Libs: -L${libdir} -lprotobuf-lite @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Cflags: -I${includedir} @PTHREAD_CFLAGS@
+Conflicts: protobuf
diff --git a/src/third_party/protobuf-3/protobuf.bzl b/src/third_party/protobuf-3/protobuf.bzl
new file mode 100644
index 0000000..fbcae0b
--- /dev/null
+++ b/src/third_party/protobuf-3/protobuf.bzl
@@ -0,0 +1,304 @@
+# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
+
+def _GetPath(ctx, path):
+  if ctx.label.workspace_root:
+    return ctx.label.workspace_root + '/' + path
+  else:
+    return path
+
+def _GenDir(ctx):
+  if not ctx.attr.includes:
+    return ctx.label.workspace_root
+  if not ctx.attr.includes[0]:
+    return _GetPath(ctx, ctx.label.package)
+  if not ctx.label.package:
+    return _GetPath(ctx, ctx.attr.includes[0])
+  return _GetPath(ctx, ctx.label.package + '/' + ctx.attr.includes[0])
+
+def _CcOuts(srcs, use_grpc_plugin=False):
+  ret = [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
+        [s[:-len(".proto")] + ".pb.cc" for s in srcs]
+  if use_grpc_plugin:
+    ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs] + \
+           [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
+  return ret
+
+def _PyOuts(srcs):
+  return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
+
+def _RelativeOutputPath(path, include):
+  if include == None:
+    return path
+
+  if not path.startswith(include):
+    fail("Include path %s isn't part of the path %s." % (include, path))
+
+  if include and include[-1] != '/':
+    include = include + '/'
+
+  path = path[len(include):]
+
+  if not path.startswith(PACKAGE_NAME):
+    fail("The package %s is not within the path %s" % (PACKAGE_NAME, path))
+
+  if not PACKAGE_NAME:
+    return path
+
+  return path[len(PACKAGE_NAME)+1:]
+
+def _proto_gen_impl(ctx):
+  """General implementation for generating protos"""
+  srcs = ctx.files.srcs
+  deps = []
+  deps += ctx.files.srcs
+  gen_dir = _GenDir(ctx)
+  if gen_dir:
+    import_flags = ["-I" + gen_dir]
+  else:
+    import_flags = ["-I."]
+
+  for dep in ctx.attr.deps:
+    import_flags += dep.proto.import_flags
+    deps += dep.proto.deps
+
+  args = []
+  if ctx.attr.gen_cc:
+    args += ["--cpp_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+  if ctx.attr.gen_py:
+    args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+
+  if ctx.executable.grpc_cpp_plugin:
+    args += ["--plugin=protoc-gen-grpc=" + ctx.executable.grpc_cpp_plugin.path]
+    args += ["--grpc_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+
+  if args:
+    ctx.action(
+        inputs=srcs + deps,
+        outputs=ctx.outputs.outs,
+        arguments=args + import_flags + [s.path for s in srcs],
+        executable=ctx.executable.protoc,
+    )
+
+  return struct(
+      proto=struct(
+          srcs=srcs,
+          import_flags=import_flags,
+          deps=deps,
+      ),
+  )
+
+_proto_gen = rule(
+    attrs = {
+        "srcs": attr.label_list(allow_files = True),
+        "deps": attr.label_list(providers = ["proto"]),
+        "includes": attr.string_list(),
+        "protoc": attr.label(
+            cfg = HOST_CFG,
+            executable = True,
+            single_file = True,
+            mandatory = True,
+        ),
+        "grpc_cpp_plugin": attr.label(
+            cfg = HOST_CFG,
+            executable = True,
+            single_file = True,
+        ),
+        "gen_cc": attr.bool(),
+        "gen_py": attr.bool(),
+        "outs": attr.output_list(),
+    },
+    output_to_genfiles = True,
+    implementation = _proto_gen_impl,
+)
+
+def cc_proto_library(
+        name,
+        srcs=[],
+        deps=[],
+        cc_libs=[],
+        include=None,
+        protoc="//:protoc",
+        internal_bootstrap_hack=False,
+        use_grpc_plugin=False,
+        default_runtime="//:protobuf",
+        **kargs):
+  """Bazel rule to create a C++ protobuf library from proto source files
+
+  NOTE: the rule is only an internal workaround to generate protos. The
+  interface may change and the rule may be removed when bazel has introduced
+  the native rule.
+
+  Args:
+    name: the name of the cc_proto_library.
+    srcs: the .proto files of the cc_proto_library.
+    deps: a list of dependency labels; must be cc_proto_library.
+    cc_libs: a list of other cc_library targets depended by the generated
+        cc_library.
+    include: a string indicating the include path of the .proto files.
+    protoc: the label of the protocol compiler to generate the sources.
+    internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
+        for bootstraping. When it is set to True, no files will be generated.
+        The rule will simply be a provider for .proto files, so that other
+        cc_proto_library can depend on it.
+    use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
+        when processing the proto files.
+    default_runtime: the implicitly default runtime which will be depended on by
+        the generated cc_library target.
+    **kargs: other keyword arguments that are passed to cc_library.
+
+  """
+
+  includes = []
+  if include != None:
+    includes = [include]
+
+  if internal_bootstrap_hack:
+    # For pre-checked-in generated files, we add the internal_bootstrap_hack
+    # which will skip the codegen action.
+    _proto_gen(
+        name=name + "_genproto",
+        srcs=srcs,
+        deps=[s + "_genproto" for s in deps],
+        includes=includes,
+        protoc=protoc,
+        visibility=["//visibility:public"],
+    )
+    # An empty cc_library to make rule dependency consistent.
+    native.cc_library(
+        name=name,
+        **kargs)
+    return
+
+  grpc_cpp_plugin = None
+  if use_grpc_plugin:
+    grpc_cpp_plugin = "//external:grpc_cpp_plugin"
+
+  outs = _CcOuts(srcs, use_grpc_plugin)
+
+  _proto_gen(
+      name=name + "_genproto",
+      srcs=srcs,
+      deps=[s + "_genproto" for s in deps],
+      includes=includes,
+      protoc=protoc,
+      grpc_cpp_plugin=grpc_cpp_plugin,
+      gen_cc=1,
+      outs=outs,
+      visibility=["//visibility:public"],
+  )
+
+  if default_runtime and not default_runtime in cc_libs:
+    cc_libs += [default_runtime]
+  if use_grpc_plugin:
+    cc_libs += ["//external:grpc_lib"]
+
+  native.cc_library(
+      name=name,
+      srcs=outs,
+      deps=cc_libs + deps,
+      includes=includes,
+      **kargs)
+
+
+def internal_gen_well_known_protos_java(srcs):
+  """Bazel rule to generate the gen_well_known_protos_java genrule
+
+  Args:
+    srcs: the well known protos
+  """
+  root = Label("%s//protobuf_java" % (REPOSITORY_NAME)).workspace_root
+  if root == "":
+    include = " -Isrc "
+  else:
+    include = " -I%s/src " % root
+  native.genrule(
+    name = "gen_well_known_protos_java",
+    srcs = srcs,
+    outs = [
+        "wellknown.srcjar",
+    ],
+    cmd = "$(location :protoc) --java_out=$(@D)/wellknown.jar" +
+          " %s $(SRCS) " % include +
+          " && mv $(@D)/wellknown.jar $(@D)/wellknown.srcjar",
+    tools = [":protoc"],
+  )
+
+
+def py_proto_library(
+        name,
+        srcs=[],
+        deps=[],
+        py_libs=[],
+        py_extra_srcs=[],
+        include=None,
+        default_runtime="//:protobuf_python",
+        protoc="//:protoc",
+        **kargs):
+  """Bazel rule to create a Python protobuf library from proto source files
+
+  NOTE: the rule is only an internal workaround to generate protos. The
+  interface may change and the rule may be removed when bazel has introduced
+  the native rule.
+
+  Args:
+    name: the name of the py_proto_library.
+    srcs: the .proto files of the py_proto_library.
+    deps: a list of dependency labels; must be py_proto_library.
+    py_libs: a list of other py_library targets depended by the generated
+        py_library.
+    py_extra_srcs: extra source files that will be added to the output
+        py_library. This attribute is used for internal bootstrapping.
+    include: a string indicating the include path of the .proto files.
+    default_runtime: the implicitly default runtime which will be depended on by
+        the generated py_library target.
+    protoc: the label of the protocol compiler to generate the sources.
+    **kargs: other keyword arguments that are passed to cc_library.
+
+  """
+  outs = _PyOuts(srcs)
+
+  includes = []
+  if include != None:
+    includes = [include]
+
+  _proto_gen(
+      name=name + "_genproto",
+      srcs=srcs,
+      deps=[s + "_genproto" for s in deps],
+      includes=includes,
+      protoc=protoc,
+      gen_py=1,
+      outs=outs,
+      visibility=["//visibility:public"],
+  )
+
+  if default_runtime and not default_runtime in py_libs + deps:
+    py_libs += [default_runtime]
+
+  native.py_library(
+      name=name,
+      srcs=outs+py_extra_srcs,
+      deps=py_libs+deps,
+      imports=includes,
+      **kargs)
+
+def internal_protobuf_py_tests(
+    name,
+    modules=[],
+    **kargs):
+  """Bazel rules to create batch tests for protobuf internal.
+
+  Args:
+    name: the name of the rule.
+    modules: a list of modules for tests. The macro will create a py_test for
+        each of the parameter with the source "google/protobuf/%s.py"
+    kargs: extra parameters that will be passed into the py_test.
+
+  """
+  for m in modules:
+    s = "python/google/protobuf/internal/%s.py" % m
+    native.py_test(
+        name="py_%s" % m,
+        srcs=[s],
+        main=s,
+        **kargs)
diff --git a/src/third_party/protobuf-3/protobuf.gyp b/src/third_party/protobuf-3/protobuf.gyp
new file mode 100644
index 0000000..e985836
--- /dev/null
+++ b/src/third_party/protobuf-3/protobuf.gyp
@@ -0,0 +1,563 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'conditions': [
+    ['use_system_protobuf==0', {
+      'conditions': [
+        ['OS=="win"', {
+          'target_defaults': {
+            'msvs_disabled_warnings': [
+              4018,  # signed/unsigned mismatch in comparison
+              4065,  # switch statement contains 'default' but no 'case' labels
+              4146,  # unary minus operator applied to unsigned type
+              4244,  # implicit conversion, possible loss of data
+              4267,  # size_t to int truncation
+              4291,  # no matching operator delete for a placement new
+              4305,  # double to float truncation
+              4355,  # 'this' used in base member initializer list
+              4506,  # no definition for inline function (protobuf issue #240)
+              4715,  # not all control paths return a value (fixed in trunk)
+            ],
+            'defines!': [
+              'WIN32_LEAN_AND_MEAN',  # Protobuf defines this itself.
+            ],
+          },
+        }],
+      ],
+      'targets': [
+        # The "lite" lib is about 1/7th the size of the heavy lib,
+        # but it doesn't support some of the more exotic features of
+        # protobufs, like reflection.  To generate C++ code that can link
+        # against the lite version of the library, add the option line:
+        #
+        #   option optimize_for = LITE_RUNTIME;
+        #
+        # to your .proto file.
+        {
+          'target_name': 'protobuf_lite',
+          'type': '<(component)',
+          'toolsets': ['host', 'target'],
+          'includes': [
+            'protobuf_lite.gypi',
+          ],
+          'variables': {
+            'clang_warning_flags': [
+              # protobuf-3 contains a few functions that are unused.
+              '-Wno-unused-function',
+            ],
+          },
+          # Required for component builds. See http://crbug.com/172800.
+          'defines': [
+            'LIBPROTOBUF_EXPORTS',
+            'PROTOBUF_USE_DLLS',
+          ],
+          'direct_dependent_settings': {
+            'defines': [
+              'PROTOBUF_USE_DLLS',
+            ],
+          },
+        },
+        # This is the full, heavy protobuf lib that's needed for c++ .protos
+        # that don't specify the LITE_RUNTIME option.  The protocol
+        # compiler itself (protoc) falls into that category.
+        #
+        # DO NOT LINK AGAINST THIS TARGET IN CHROME CODE  --agl
+        {
+          'target_name': 'protobuf_full_do_not_use',
+          'type': 'static_library',
+          'toolsets': ['host','target'],
+          'includes': [
+            'protobuf_lite.gypi',
+          ],
+          'variables': {
+            'clang_warning_flags': [
+              # protobuf-3 contains a few functions that are unused.
+              '-Wno-unused-function',
+            ],
+          },
+          'sources': [
+            'src/google/protobuf/any.cc',
+            'src/google/protobuf/any.h',
+            'src/google/protobuf/any.pb.cc',
+            'src/google/protobuf/any.pb.h',
+            'src/google/protobuf/api.pb.cc',
+            'src/google/protobuf/api.pb.h',
+            'src/google/protobuf/compiler/importer.cc',
+            'src/google/protobuf/compiler/importer.h',
+            'src/google/protobuf/compiler/parser.cc',
+            'src/google/protobuf/compiler/parser.h',
+            'src/google/protobuf/descriptor.cc',
+            'src/google/protobuf/descriptor.h',
+            'src/google/protobuf/descriptor.pb.cc',
+            'src/google/protobuf/descriptor.pb.h',
+            'src/google/protobuf/descriptor_database.cc',
+            'src/google/protobuf/descriptor_database.h',
+            'src/google/protobuf/duration.pb.cc',
+            'src/google/protobuf/duration.pb.h',
+            'src/google/protobuf/dynamic_message.cc',
+            'src/google/protobuf/dynamic_message.h',
+            'src/google/protobuf/empty.pb.cc',
+            'src/google/protobuf/empty.pb.h',
+            'src/google/protobuf/extension_set_heavy.cc',
+            'src/google/protobuf/field_mask.pb.cc',
+            'src/google/protobuf/field_mask.pb.h',
+            'src/google/protobuf/generated_enum_reflection.h',
+            'src/google/protobuf/generated_enum_util.h',
+            'src/google/protobuf/generated_message_reflection.cc',
+            'src/google/protobuf/generated_message_reflection.h',
+
+            # gzip_stream.cc pulls in zlib, but it's not actually used by
+            # protoc, just by test code, so instead of compiling zlib for the
+            # host, let's just exclude this.
+            # 'src/google/protobuf/io/gzip_stream.cc',
+            # 'src/google/protobuf/io/gzip_stream.h',
+
+            'src/google/protobuf/io/printer.cc',
+            'src/google/protobuf/io/printer.h',
+            'src/google/protobuf/io/strtod.cc',
+            'src/google/protobuf/io/strtod.h',
+            'src/google/protobuf/io/tokenizer.cc',
+            'src/google/protobuf/io/tokenizer.h',
+            'src/google/protobuf/io/zero_copy_stream_impl.cc',
+            'src/google/protobuf/io/zero_copy_stream_impl.h',
+            'src/google/protobuf/map_entry.h',
+            'src/google/protobuf/map_field.cc',
+            'src/google/protobuf/map_field.h',
+            'src/google/protobuf/map_field_inl.h',
+            'src/google/protobuf/message.cc',
+            'src/google/protobuf/message.h',
+            'src/google/protobuf/metadata.h',
+            'src/google/protobuf/reflection.h',
+            'src/google/protobuf/reflection_internal.h',
+            'src/google/protobuf/reflection_ops.cc',
+            'src/google/protobuf/reflection_ops.h',
+            'src/google/protobuf/service.cc',
+            'src/google/protobuf/service.h',
+            'src/google/protobuf/source_context.pb.cc',
+            'src/google/protobuf/source_context.pb.h',
+            'src/google/protobuf/struct.pb.cc',
+            'src/google/protobuf/struct.pb.h',
+            'src/google/protobuf/stubs/mathutil.h',
+            'src/google/protobuf/stubs/mathlimits.cc',
+            'src/google/protobuf/stubs/mathlimits.h',
+            'src/google/protobuf/stubs/substitute.cc',
+            'src/google/protobuf/stubs/substitute.h',
+            'src/google/protobuf/stubs/singleton$.h',
+            'src/google/protobuf/text_format.cc',
+            'src/google/protobuf/text_format.h',
+            'src/google/protobuf/timestamp.pb.cc',
+            'src/google/protobuf/timestamp.pb.h',
+            'src/google/protobuf/type.pb.cc',
+            'src/google/protobuf/type.pb.h',
+            'src/google/protobuf/unknown_field_set.cc',
+            'src/google/protobuf/unknown_field_set.h',
+            'src/google/protobuf/util/field_comparator.cc',
+            'src/google/protobuf/util/field_comparator.h',
+            'src/google/protobuf/util/field_mask_util.cc',
+            'src/google/protobuf/util/field_mask_util.h',
+            'src/google/protobuf/util/internal/constants.h',
+            'src/google/protobuf/util/internal/datapiece.cc',
+            'src/google/protobuf/util/internal/datapiece.h',
+            'src/google/protobuf/util/internal/default_value_objectwriter.cc',
+            'src/google/protobuf/util/internal/default_value_objectwriter.h',
+            'src/google/protobuf/util/internal/error_listener.cc',
+            'src/google/protobuf/util/internal/error_listener.h',
+            'src/google/protobuf/util/internal/field_mask_utility.cc',
+            'src/google/protobuf/util/internal/field_mask_utility.h',
+            'src/google/protobuf/util/internal/json_escaping.cc',
+            'src/google/protobuf/util/internal/json_escaping.h',
+            'src/google/protobuf/util/internal/json_objectwriter.cc',
+            'src/google/protobuf/util/internal/json_objectwriter.h',
+            'src/google/protobuf/util/internal/json_stream_parser.cc',
+            'src/google/protobuf/util/internal/json_stream_parser.h',
+            'src/google/protobuf/util/internal/location_tracker.h',
+            'src/google/protobuf/util/internal/object_location_tracker.h',
+            'src/google/protobuf/util/internal/object_source.h',
+            'src/google/protobuf/util/internal/object_writer.cc',
+            'src/google/protobuf/util/internal/object_writer.h',
+            'src/google/protobuf/util/internal/proto_writer.cc',
+            'src/google/protobuf/util/internal/proto_writer.h',
+            'src/google/protobuf/util/internal/protostream_objectsource.cc',
+            'src/google/protobuf/util/internal/protostream_objectsource.h',
+            'src/google/protobuf/util/internal/protostream_objectwriter.cc',
+            'src/google/protobuf/util/internal/protostream_objectwriter.h',
+            'src/google/protobuf/util/internal/structured_objectwriter.h',
+            'src/google/protobuf/util/internal/type_info.cc',
+            'src/google/protobuf/util/internal/type_info.h',
+            'src/google/protobuf/util/internal/type_info_test_helper.cc',
+            'src/google/protobuf/util/internal/type_info_test_helper.h',
+            'src/google/protobuf/util/internal/utility.cc',
+            'src/google/protobuf/util/internal/utility.h',
+            'src/google/protobuf/util/json_util.cc',
+            'src/google/protobuf/util/json_util.h',
+            'src/google/protobuf/util/message_differencer.cc',
+            'src/google/protobuf/util/message_differencer.h',
+            'src/google/protobuf/util/time_util.cc',
+            'src/google/protobuf/util/time_util.h',
+            'src/google/protobuf/util/type_resolver.h',
+            'src/google/protobuf/util/type_resolver_util.cc',
+            'src/google/protobuf/util/type_resolver_util.h',
+            'src/google/protobuf/wire_format.cc',
+            'src/google/protobuf/wire_format.h',
+            'src/google/protobuf/wrappers.pb.cc',
+            'src/google/protobuf/wrappers.pb.h',
+          ],
+        },
+        {
+          'target_name': 'protoc_lib',
+          'type': 'static_library',
+          'toolsets': ['host'],
+          'sources': [
+            "src/google/protobuf/compiler/code_generator.cc",
+            "src/google/protobuf/compiler/code_generator.h",
+            "src/google/protobuf/compiler/command_line_interface.cc",
+            "src/google/protobuf/compiler/command_line_interface.h",
+            "src/google/protobuf/compiler/cpp/cpp_enum.cc",
+            "src/google/protobuf/compiler/cpp/cpp_enum.h",
+            "src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_enum_field.h",
+            "src/google/protobuf/compiler/cpp/cpp_extension.cc",
+            "src/google/protobuf/compiler/cpp/cpp_extension.h",
+            "src/google/protobuf/compiler/cpp/cpp_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_field.h",
+            "src/google/protobuf/compiler/cpp/cpp_file.cc",
+            "src/google/protobuf/compiler/cpp/cpp_file.h",
+            "src/google/protobuf/compiler/cpp/cpp_generator.cc",
+            "src/google/protobuf/compiler/cpp/cpp_generator.h",
+            "src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+            "src/google/protobuf/compiler/cpp/cpp_helpers.h",
+            "src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_map_field.h",
+            "src/google/protobuf/compiler/cpp/cpp_message.cc",
+            "src/google/protobuf/compiler/cpp/cpp_message.h",
+            "src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_message_field.h",
+            "src/google/protobuf/compiler/cpp/cpp_options.h",
+            "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_primitive_field.h",
+            "src/google/protobuf/compiler/cpp/cpp_service.cc",
+            "src/google/protobuf/compiler/cpp/cpp_service.h",
+            "src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+            "src/google/protobuf/compiler/cpp/cpp_string_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
+            "src/google/protobuf/compiler/csharp/csharp_doc_comment.h",
+            "src/google/protobuf/compiler/csharp/csharp_enum.cc",
+            "src/google/protobuf/compiler/csharp/csharp_enum.h",
+            "src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_enum_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+            "src/google/protobuf/compiler/csharp/csharp_field_base.h",
+            "src/google/protobuf/compiler/csharp/csharp_generator.cc",
+            "src/google/protobuf/compiler/csharp/csharp_generator.h",
+            "src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+            "src/google/protobuf/compiler/csharp/csharp_helpers.h",
+            "src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_map_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_message.cc",
+            "src/google/protobuf/compiler/csharp/csharp_message.h",
+            "src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_message_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_options.h",
+            "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_primitive_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
+            "src/google/protobuf/compiler/csharp/csharp_reflection_class.h",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h",
+            "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+            "src/google/protobuf/compiler/csharp/csharp_source_generator_base.h",
+            "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+            "src/google/protobuf/compiler/csharp/csharp_wrapper_field.h",
+            "src/google/protobuf/compiler/java/java_context.cc",
+            "src/google/protobuf/compiler/java/java_context.h",
+            "src/google/protobuf/compiler/java/java_doc_comment.cc",
+            "src/google/protobuf/compiler/java/java_doc_comment.h",
+            "src/google/protobuf/compiler/java/java_enum.cc",
+            "src/google/protobuf/compiler/java/java_enum.h",
+            "src/google/protobuf/compiler/java/java_enum_field.cc",
+            "src/google/protobuf/compiler/java/java_enum_field.h",
+            "src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_enum_field_lite.h",
+            "src/google/protobuf/compiler/java/java_enum_lite.cc",
+            "src/google/protobuf/compiler/java/java_enum_lite.h",
+            "src/google/protobuf/compiler/java/java_extension.cc",
+            "src/google/protobuf/compiler/java/java_extension.h",
+            "src/google/protobuf/compiler/java/java_extension_lite.cc",
+            "src/google/protobuf/compiler/java/java_extension_lite.h",
+            "src/google/protobuf/compiler/java/java_field.cc",
+            "src/google/protobuf/compiler/java/java_field.h",
+            "src/google/protobuf/compiler/java/java_file.cc",
+            "src/google/protobuf/compiler/java/java_file.h",
+            "src/google/protobuf/compiler/java/java_generator.cc",
+            "src/google/protobuf/compiler/java/java_generator.h",
+            "src/google/protobuf/compiler/java/java_generator_factory.cc",
+            "src/google/protobuf/compiler/java/java_generator_factory.h",
+            "src/google/protobuf/compiler/java/java_helpers.cc",
+            "src/google/protobuf/compiler/java/java_helpers.h",
+            "src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+            "src/google/protobuf/compiler/java/java_lazy_message_field.h",
+            "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_lazy_message_field_lite.h",
+            "src/google/protobuf/compiler/java/java_map_field.cc",
+            "src/google/protobuf/compiler/java/java_map_field.h",
+            "src/google/protobuf/compiler/java/java_map_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_map_field_lite.h",
+            "src/google/protobuf/compiler/java/java_message.cc",
+            "src/google/protobuf/compiler/java/java_message.h",
+            "src/google/protobuf/compiler/java/java_message_builder.cc",
+            "src/google/protobuf/compiler/java/java_message_builder.h",
+            "src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+            "src/google/protobuf/compiler/java/java_message_builder_lite.h",
+            "src/google/protobuf/compiler/java/java_message_field.cc",
+            "src/google/protobuf/compiler/java/java_message_field.h",
+            "src/google/protobuf/compiler/java/java_message_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_message_field_lite.h",
+            "src/google/protobuf/compiler/java/java_message_lite.cc",
+            "src/google/protobuf/compiler/java/java_message_lite.h",
+            "src/google/protobuf/compiler/java/java_name_resolver.cc",
+            "src/google/protobuf/compiler/java/java_name_resolver.h",
+            "src/google/protobuf/compiler/java/java_primitive_field.cc",
+            "src/google/protobuf/compiler/java/java_primitive_field.h",
+            "src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_primitive_field_lite.h",
+            "src/google/protobuf/compiler/java/java_service.cc",
+            "src/google/protobuf/compiler/java/java_service.h",
+            "src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+            "src/google/protobuf/compiler/java/java_shared_code_generator.h",
+            "src/google/protobuf/compiler/java/java_string_field.cc",
+            "src/google/protobuf/compiler/java/java_string_field.h",
+            "src/google/protobuf/compiler/java/java_string_field_lite.cc",
+            "src/google/protobuf/compiler/java/java_string_field_lite.h",
+            "src/google/protobuf/compiler/javanano/javanano_enum.cc",
+            "src/google/protobuf/compiler/javanano/javanano_enum.h",
+            "src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+            "src/google/protobuf/compiler/javanano/javanano_enum_field.h",
+            "src/google/protobuf/compiler/javanano/javanano_extension.cc",
+            "src/google/protobuf/compiler/javanano/javanano_extension.h",
+            "src/google/protobuf/compiler/javanano/javanano_field.cc",
+            "src/google/protobuf/compiler/javanano/javanano_field.h",
+            "src/google/protobuf/compiler/javanano/javanano_file.cc",
+            "src/google/protobuf/compiler/javanano/javanano_file.h",
+            "src/google/protobuf/compiler/javanano/javanano_generator.cc",
+            "src/google/protobuf/compiler/javanano/javanano_generator.h",
+            "src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+            "src/google/protobuf/compiler/javanano/javanano_helpers.h",
+            "src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+            "src/google/protobuf/compiler/javanano/javanano_map_field.h",
+            "src/google/protobuf/compiler/javanano/javanano_message.cc",
+            "src/google/protobuf/compiler/javanano/javanano_message.h",
+            "src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+            "src/google/protobuf/compiler/javanano/javanano_message_field.h",
+            "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+            "src/google/protobuf/compiler/javanano/javanano_primitive_field.h",
+            "src/google/protobuf/compiler/js/js_generator.cc",
+            "src/google/protobuf/compiler/js/js_generator.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_enum.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_enum_field.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_extension.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_field.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_file.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_generator.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_helpers.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_map_field.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_message.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_message_field.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_oneof.h",
+            "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+            "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h",
+            "src/google/protobuf/compiler/plugin.cc",
+            "src/google/protobuf/compiler/plugin.h",
+            "src/google/protobuf/compiler/plugin.pb.cc",
+            "src/google/protobuf/compiler/plugin.pb.h",
+            "src/google/protobuf/compiler/python/python_generator.cc",
+            "src/google/protobuf/compiler/python/python_generator.h",
+            "src/google/protobuf/compiler/ruby/ruby_generator.cc",
+            "src/google/protobuf/compiler/ruby/ruby_generator.h",
+            "src/google/protobuf/compiler/subprocess.cc",
+            "src/google/protobuf/compiler/subprocess.h",
+            "src/google/protobuf/compiler/zip_writer.cc",
+            "src/google/protobuf/compiler/zip_writer.h",
+          ],
+          'variables': {
+            'clang_warning_flags': [
+              # protobuf-3 contains a few functions that are unused.
+              '-Wno-unused-function',
+            ],
+          },
+          'dependencies': [
+            'protobuf_full_do_not_use',
+          ],
+          'include_dirs': [
+            'src',
+          ],
+        },
+        {
+          'target_name': 'protoc',
+          'type': 'executable',
+          'toolsets': ['host'],
+          'sources': [
+            "src/google/protobuf/compiler/main.cc",
+          ],
+          'dependencies': [
+            'protoc_lib',
+          ],
+          'include_dirs': [
+            'src',
+          ],
+        },
+        {
+          # Generate the python module needed by all protoc-generated Python code.
+          'target_name': 'py_proto',
+          'type': 'none',
+          'copies': [
+            {
+              'destination': '<(PRODUCT_DIR)/pyproto/google/',
+              'files': [
+                '__init__.py',
+              ],
+            },
+            {
+              'destination': '<(PRODUCT_DIR)/pyproto/google/third_party/six/',
+              'files': [
+                'third_party/six/six.py',
+              ],
+            },
+            {
+              'destination': '<(PRODUCT_DIR)/pyproto/google/protobuf',
+              'files': [
+                'python/google/protobuf/__init__.py',
+                'python/google/protobuf/descriptor.py',
+                'python/google/protobuf/descriptor_database.py',
+                'python/google/protobuf/descriptor_pool.py',
+                'python/google/protobuf/json_format.py',
+                'python/google/protobuf/message.py',
+                'python/google/protobuf/message_factory.py',
+                'python/google/protobuf/proto_builder.py',
+                'python/google/protobuf/reflection.py',
+                'python/google/protobuf/service.py',
+                'python/google/protobuf/service_reflection.py',
+                'python/google/protobuf/symbol_database.py',
+                'python/google/protobuf/text_encoding.py',
+                'python/google/protobuf/text_format.py',
+
+                # TODO(ncarter): protoc's python generator treats
+                # descriptor.proto specially, but only when the input path is
+                # exactly "google/protobuf/descriptor.proto".  I'm not sure how
+                # to execute a rule from a different directory.  For now, use a
+                # manually-generated copy of descriptor_pb2.py.
+                'python/google/protobuf/descriptor_pb2.py',
+              ],
+            },
+            {
+              'destination': '<(PRODUCT_DIR)/pyproto/google/protobuf/internal',
+              'files': [
+                'python/google/protobuf/internal/__init__.py',
+                'python/google/protobuf/internal/_parameterized.py',
+                'python/google/protobuf/internal/api_implementation.py',
+                'python/google/protobuf/internal/containers.py',
+                'python/google/protobuf/internal/decoder.py',
+                'python/google/protobuf/internal/encoder.py',
+                'python/google/protobuf/internal/enum_type_wrapper.py',
+                'python/google/protobuf/internal/message_listener.py',
+                'python/google/protobuf/internal/python_message.py',
+                'python/google/protobuf/internal/type_checkers.py',
+                'python/google/protobuf/internal/well_known_types.py',
+                'python/google/protobuf/internal/wire_format.py',
+              ],
+            },
+          ],
+      #   # We can't generate a proper descriptor_pb2.py -- see earlier comment.
+      #   'rules': [
+      #     {
+      #       'rule_name': 'genproto',
+      #       'extension': 'proto',
+      #       'inputs': [
+      #         '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+      #       ],
+      #       'variables': {
+      #         # The protoc compiler requires a proto_path argument with the
+      #           # directory containing the .proto file.
+      #           'rule_input_relpath': 'src/google/protobuf',
+      #         },
+      #         'outputs': [
+      #           '<(PRODUCT_DIR)/pyproto/google/protobuf/<(RULE_INPUT_ROOT)_pb2.py',
+      #         ],
+      #         'action': [
+      #           '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+      #           '-I./src',
+      #           '-I.',
+      #           '--python_out=<(PRODUCT_DIR)/pyproto/google/protobuf',
+      #           'google/protobuf/descriptor.proto',
+      #         ],
+      #         'message': 'Generating Python code from <(RULE_INPUT_PATH)',
+      #       },
+      #     ],
+      #     'dependencies': [
+      #       'protoc#host',
+      #     ],
+      #     'sources': [
+      #       'src/google/protobuf/descriptor.proto',
+      #     ],
+         },
+      ],
+    }, { # use_system_protobuf==1
+      'targets': [
+        {
+          'target_name': 'protobuf_lite',
+          'type': 'none',
+          'direct_dependent_settings': {
+            'cflags': [
+              # Use full protobuf, because vanilla protobuf doesn't have
+              # our custom patch to retain unknown fields in lite mode.
+              '<!@(pkg-config --cflags protobuf)',
+            ],
+            'defines': [
+              'USE_SYSTEM_PROTOBUF',
+
+              # This macro must be defined to suppress the use
+              # of dynamic_cast<>, which requires RTTI.
+              'GOOGLE_PROTOBUF_NO_RTTI',
+              'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER',
+            ],
+          },
+          'link_settings': {
+            # Use full protobuf, because vanilla protobuf doesn't have
+            # our custom patch to retain unknown fields in lite mode.
+            'ldflags': [
+              '<!@(pkg-config --libs-only-L --libs-only-other protobuf)',
+            ],
+            'libraries': [
+              '<!@(pkg-config --libs-only-l protobuf)',
+            ],
+          },
+        },
+        {
+          'target_name': 'protoc',
+          'type': 'none',
+          'toolsets': ['host', 'target'],
+        },
+        {
+          'target_name': 'py_proto',
+          'type': 'none',
+        },
+      ],
+    }],
+  ],
+}
diff --git a/src/third_party/protobuf-3/protobuf.pc.in b/src/third_party/protobuf-3/protobuf.pc.in
new file mode 100644
index 0000000..4901490
--- /dev/null
+++ b/src/third_party/protobuf-3/protobuf.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Protocol Buffers
+Description: Google's Data Interchange Format
+Version: @VERSION@
+Libs: -L${libdir} -lprotobuf @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Libs.private: @LIBS@
+Cflags: -I${includedir} @PTHREAD_CFLAGS@
+Conflicts: protobuf-lite
diff --git a/src/third_party/protobuf-3/protobuf_lite.gypi b/src/third_party/protobuf-3/protobuf_lite.gypi
new file mode 100644
index 0000000..ffe2288
--- /dev/null
+++ b/src/third_party/protobuf-3/protobuf_lite.gypi
@@ -0,0 +1,111 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'sources': [
+    'src/google/protobuf/arena.cc',
+    'src/google/protobuf/arena.h',
+    'src/google/protobuf/arenastring.cc',
+    'src/google/protobuf/arenastring.h',
+    'src/google/protobuf/extension_set.cc',
+    'src/google/protobuf/extension_set.h',
+    'src/google/protobuf/generated_message_util.cc',
+    'src/google/protobuf/generated_message_util.h',
+    'src/google/protobuf/io/coded_stream.cc',
+    'src/google/protobuf/io/coded_stream.h',
+    'src/google/protobuf/io/coded_stream_inl.h',
+    'src/google/protobuf/io/zero_copy_stream.cc',
+    'src/google/protobuf/io/zero_copy_stream.h',
+    'src/google/protobuf/io/zero_copy_stream_impl_lite.cc',
+    'src/google/protobuf/io/zero_copy_stream_impl_lite.h',
+    'src/google/protobuf/map.h',
+    'src/google/protobuf/map_entry_lite.h',
+    'src/google/protobuf/map_field_lite.h',
+    'src/google/protobuf/map_type_handler.h',
+    'src/google/protobuf/message_lite.cc',
+    'src/google/protobuf/message_lite.h',
+    'src/google/protobuf/repeated_field.cc',
+    'src/google/protobuf/repeated_field.h',
+    'src/google/protobuf/stubs/atomicops.h',
+    'src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_arm_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_arm_qnx.h',
+    'src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h',
+    'src/google/protobuf/stubs/atomicops_internals_generic_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_macosx.h',
+    'src/google/protobuf/stubs/atomicops_internals_mips_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_pnacl.h',
+    'src/google/protobuf/stubs/atomicops_internals_power.h',
+    'src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_solaris.h',
+    'src/google/protobuf/stubs/atomicops_internals_tsan.h',
+    'src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc',
+    'src/google/protobuf/stubs/atomicops_internals_x86_gcc.h',
+    'src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc',
+    'src/google/protobuf/stubs/atomicops_internals_x86_msvc.h',
+    'src/google/protobuf/stubs/atomic_sequence_num.h',
+    'src/google/protobuf/stubs/bytestream.cc',
+    'src/google/protobuf/stubs/bytestream.h',
+    'src/google/protobuf/stubs/callback.h',
+    'src/google/protobuf/stubs/casts.h',
+    'src/google/protobuf/stubs/common.cc',
+    'src/google/protobuf/stubs/common.h',
+    'src/google/protobuf/stubs/fastmem.h',
+    'src/google/protobuf/stubs/hash.h',
+    'src/google/protobuf/stubs/int128.cc',
+    'src/google/protobuf/stubs/int128.h',
+    'src/google/protobuf/stubs/logging.h',
+    'src/google/protobuf/stubs/macros.h',
+    'src/google/protobuf/stubs/map_util.h',
+    'src/google/protobuf/stubs/mutex.h',
+    'src/google/protobuf/stubs/once.cc',
+    'src/google/protobuf/stubs/once.h',
+    'src/google/protobuf/stubs/platform_macros.h',
+    'src/google/protobuf/stubs/port.h',
+    'src/google/protobuf/stubs/scoped_ptr.h',
+    'src/google/protobuf/stubs/shared_ptr.h',
+    'src/google/protobuf/stubs/status.cc',
+    'src/google/protobuf/stubs/status.h',
+    'src/google/protobuf/stubs/status_macros.h',
+    'src/google/protobuf/stubs/statusor.cc',
+    'src/google/protobuf/stubs/statusor.h',
+    'src/google/protobuf/stubs/stl_util.h',
+    'src/google/protobuf/stubs/stringpiece.cc',
+    'src/google/protobuf/stubs/stringpiece.h',
+    'src/google/protobuf/stubs/stringprintf.cc',
+    'src/google/protobuf/stubs/stringprintf.h',
+    'src/google/protobuf/stubs/structurally_valid.cc',
+    'src/google/protobuf/stubs/strutil.cc',
+    'src/google/protobuf/stubs/strutil.h',
+    'src/google/protobuf/stubs/template_util.h',
+    'src/google/protobuf/stubs/type_traits.h',
+    'src/google/protobuf/stubs/time.cc',
+    'src/google/protobuf/stubs/time.h',
+    'src/google/protobuf/wire_format_lite.cc',
+    'src/google/protobuf/wire_format_lite.h',
+    'src/google/protobuf/wire_format_lite_inl.h',
+  ],
+  'include_dirs': [
+    'src',
+  ],
+  'defines': [
+    # This macro must be defined to suppress the use of dynamic_cast<>,
+    # which requires RTTI.
+    'GOOGLE_PROTOBUF_NO_RTTI',
+
+    'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER',
+    'HAVE_PTHREAD',
+  ],
+  'direct_dependent_settings': {
+    'include_dirs': [
+      'src',
+    ],
+    'defines': [
+      'GOOGLE_PROTOBUF_NO_RTTI',
+      'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER',
+    ],
+    # TODO(jschuh): http://crbug.com/167187 size_t -> int.
+    'msvs_disabled_warnings': [ 4267 ],
+  },
+}
diff --git a/src/third_party/protobuf-3/protoc-artifacts/Dockerfile b/src/third_party/protobuf-3/protoc-artifacts/Dockerfile
new file mode 100644
index 0000000..fd35b89
--- /dev/null
+++ b/src/third_party/protobuf-3/protoc-artifacts/Dockerfile
@@ -0,0 +1,40 @@
+FROM centos:6.6
+
+RUN yum install -y git \
+                   tar \
+                   wget \
+                   make \
+                   autoconf \
+                   curl-devel \
+                   unzip \
+                   automake \
+                   libtool \
+                   glibc-static.i686 \
+                   glibc-devel \
+                   glibc-devel.i686
+
+# Install Java 8
+RUN wget -q --no-cookies --no-check-certificate \
+    --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz" \
+    -O - | tar xz -C /var/local
+ENV JAVA_HOME /var/local/jdk1.8.0_45
+ENV PATH $JAVA_HOME/bin:$PATH
+
+# Install Maven
+RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz -O - | \
+    tar xz -C /var/local
+ENV PATH /var/local/apache-maven-3.3.3/bin:$PATH
+
+# Install GCC 4.7 to support -static-libstdc++
+RUN wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -P /etc/yum.repos.d
+RUN bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-1.1.repo'
+RUN bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo"
+RUN sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo
+RUN yum install -y devtoolset-1.1 \
+                   devtoolset-1.1-libstdc++-devel \
+                   devtoolset-1.1-libstdc++-devel.i686
+
+RUN git clone --depth 1 https://github.com/google/protobuf.git
+
+# Start in devtoolset environment that uses GCC 4.7
+CMD ["scl", "enable", "devtoolset-1.1", "bash"]
diff --git a/src/third_party/protobuf-3/protoc-artifacts/README.md b/src/third_party/protobuf-3/protoc-artifacts/README.md
new file mode 100644
index 0000000..4320f65
--- /dev/null
+++ b/src/third_party/protobuf-3/protoc-artifacts/README.md
@@ -0,0 +1,143 @@
+# Build scripts that publish pre-compiled protoc artifacts
+``protoc`` is the compiler for ``.proto`` files. It generates language bindings
+for the messages and/or RPC services from ``.proto`` files.
+
+Because ``protoc`` is a native executable, the scripts under this directory
+build and publish a ``protoc`` executable (a.k.a. artifact) to Maven
+repositories. The artifact can be used by build automation tools so that users
+would not need to compile and install ``protoc`` for their systems.
+
+## Versioning
+The version of the ``protoc`` artifact must be the same as the version of the
+Protobuf project.
+
+## Artifact name
+The name of a published ``protoc`` artifact is in the following format:
+``protoc-<version>-<os>-<arch>.exe``, e.g., ``protoc-3.0.0-alpha-3-windows-x86_64.exe``.
+
+## System requirement
+Install [Apache Maven](http://maven.apache.org/) if you don't have it.
+
+The scripts only work under Unix-like environments, e.g., Linux, MacOSX, and
+Cygwin or MinGW for Windows. Please see ``README.md`` of the Protobuf project
+for how to set up the build environment.
+
+## To install artifacts locally
+The following command will install the ``protoc`` artifact to your local Maven repository.
+```
+$ mvn install
+```
+
+## Cross-compilation
+The Maven script will try to detect the OS and the architecture from Java
+system properties. It's possible to build a protoc binary for an architecture
+that is different from what Java has detected, as long as you have the proper
+compilers installed.
+
+You can override the Maven properties ``os.detected.name`` and
+``os.detected.arch`` to force the script to generate binaries for a specific OS
+and/or architecture. Valid values are defined as the return values of
+``normalizeOs()`` and ``normalizeArch()`` of ``Detector`` from
+[os-maven-plugin](https://github.com/trustin/os-maven-plugin/blob/master/src/main/java/kr/motd/maven/os/Detector.java).
+Frequently used values are:
+- ``os.detected.name``: ``linux``, ``osx``, ``windows``.
+- ``os.detected.arch``: ``x86_32``, ``x86_64``
+
+For example, MingGW32 only ships with 32-bit compilers, but you can still build
+32-bit protoc under 64-bit Windows, with the following command:
+```
+$ mvn install -Dos.detected.arch=x86_32
+```
+
+## To push artifacts to Maven Central
+Before you can upload artifacts to Maven Central repository, make sure you have
+read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to
+configure GPG and Sonatype account.
+
+You need to perform the deployment for every platform that you want to
+support. DO NOT close the staging repository until you have done the
+deployment for all platforms. Currently the following platforms are supported:
+- Linux (x86_32 and x86_64)
+- Windows (x86_32 and x86_64) with
+ - Cygwin with MinGW compilers (both x86_32 and x86_64)
+ - MSYS with MinGW32 (x86_32 only)
+- MacOSX (x86_32 and x86_64)
+
+Use the following command to deploy artifacts for the host platform to a
+staging repository.
+```
+$ mvn clean deploy -P release
+```
+It creates a new staging repository. Go to
+https://oss.sonatype.org/#stagingRepositories and find the repository, usually
+in the name like ``comgoogle-123``.
+
+You will want to run this command on a different platform. Remember, in
+subsequent deployments you will need to provide the repository name that you
+have found in the first deployment so that all artifacts go to the same
+repository:
+```
+$ mvn clean deploy -P release -Dstaging.repository=comgoogle-123
+```
+
+A 32-bit artifact can be deployed from a 64-bit host with
+``-Dos.detected.arch=x86_32``
+
+When you have done deployment for all platforms, go to
+https://oss.sonatype.org/#stagingRepositories, verify that the staging
+repository has all the binaries, close and release this repository.
+
+### Tips for deploying on Linux
+We build on Centos 6.6 to provide a good compatibility for not very new
+systems. We have provided a ``Dockerfile`` under this directory to build the
+environment. It has been tested with Docker 1.6.1.
+
+To build a image:
+```
+$ docker build -t protoc-artifacts .
+```
+
+To run the image:
+```
+$ docker run -it --rm=true protoc-artifacts
+```
+
+The Protobuf repository has been cloned into ``/protobuf``.
+
+### Tips for deploying on Windows
+Under Windows the following error may occur: ``gpg: cannot open tty `no tty':
+No such file or directory``. This can be fixed by configuring gpg through an
+active profile in ``.m2\settings.xml`` where also the Sonatype password is
+stored:
+```xml
+<settings>
+  <servers>
+    <server>
+      <id>ossrh</id>
+      <username>[username]</username>
+      <password>[password]</password>
+    </server>
+  </servers>
+  <profiles>
+    <profile>
+      <id>gpg</id>
+      <properties>
+        <gpg.executable>gpg</gpg.executable>
+        <gpg.passphrase>[password]</gpg.passphrase>
+      </properties>
+    </profile>
+  </profiles>
+  <activeProfiles>
+    <activeProfile>gpg</activeProfile>
+  </activeProfiles>
+</settings>
+```
+
+### Tested build environments
+We have successfully built artifacts on the following environments:
+- Linux x86_32 and x86_64:
+ - Centos 6.6 (within Docker 1.6.1)
+ - Ubuntu 14.04.2 64-bit
+- Windows x86_32: MSYS with ``mingw32-gcc-g++ 4.8.1-4`` on Windows 7 64-bit
+- Windows x86_64: Cygwin64 with ``mingw64-x86_64-gcc-g++ 4.8.3-1`` on Windows 7 64-bit
+- Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
diff --git a/src/third_party/protobuf-3/protoc-artifacts/build-protoc.sh b/src/third_party/protobuf-3/protoc-artifacts/build-protoc.sh
new file mode 100755
index 0000000..88e6ae5
--- /dev/null
+++ b/src/third_party/protobuf-3/protoc-artifacts/build-protoc.sh
@@ -0,0 +1,225 @@
+#!/bin/bash
+
+# Builds protoc executable into target/protoc.exe
+# To be run from Maven.
+# Usage: build-protoc.sh <OS> <ARCH>
+# <OS> and <ARCH> are ${os.detected.name} and ${os.detected.arch} from os-maven-plugin
+OS=$1
+ARCH=$2
+
+if [[ $# < 2 ]]; then
+  echo "No arguments provided. This script is intended to be run from Maven."
+  exit 1
+fi
+
+# Under Cygwin, bash doesn't have these in PATH when called from Maven which
+# runs in Windows version of Java.
+export PATH="/bin:/usr/bin:$PATH"
+
+############################################################################
+# Helper functions
+############################################################################
+E_PARAM_ERR=98
+E_ASSERT_FAILED=99
+
+# Usage:
+fail()
+{
+  echo "ERROR: $1"
+  echo
+  exit $E_ASSERT_FAILED
+}
+
+# Usage: assertEq VAL1 VAL2 $LINENO
+assertEq ()
+{
+  lineno=$3
+  if [ -z "$lineno" ]; then
+    echo "lineno not given"
+    exit $E_PARAM_ERR
+  fi
+
+  if [[ "$1" != "$2" ]]; then
+    echo "Assertion failed:  \"$1\" == \"$2\""
+    echo "File \"$0\", line $lineno"    # Give name of file and line number.
+    exit $E_ASSERT_FAILED
+  fi
+}
+
+# Checks the artifact is for the expected architecture
+# Usage: checkArch <path-to-protoc>
+checkArch ()
+{
+  echo
+  echo "Checking file format ..."
+  if [[ "$OS" == windows || "$OS" == linux ]]; then
+    format="$(objdump -f "$1" | grep -o "file format .*$" | grep -o "[^ ]*$")"
+    echo Format=$format
+    if [[ "$OS" == linux ]]; then
+      if [[ "$ARCH" == x86_32 ]]; then
+        assertEq $format "elf32-i386" $LINENO
+      elif [[ "$ARCH" == x86_64 ]]; then
+        assertEq $format "elf64-x86-64" $LINENO
+      else
+        fail "Unsupported arch: $ARCH"
+      fi
+    else
+      # $OS == windows
+      if [[ "$ARCH" == x86_32 ]]; then
+        assertEq $format "pei-i386" $LINENO
+      elif [[ "$ARCH" == x86_64 ]]; then
+        assertEq $format "pei-x86-64" $LINENO
+      else
+        fail "Unsupported arch: $ARCH"
+      fi
+    fi
+  elif [[ "$OS" == osx ]]; then
+    format="$(file -b "$1" | grep -o "[^ ]*$")"
+    echo Format=$format
+    if [[ "$ARCH" == x86_32 ]]; then
+      assertEq $format "i386" $LINENO
+    elif [[ "$ARCH" == x86_64 ]]; then
+      assertEq $format "x86_64" $LINENO
+    else
+      fail "Unsupported arch: $ARCH"
+    fi
+  else
+    fail "Unsupported system: $OS"
+  fi
+  echo
+}
+
+# Checks the dependencies of the artifact. Artifacts should only depend on
+# system libraries.
+# Usage: checkDependencies <path-to-protoc>
+checkDependencies ()
+{
+  if [[ "$OS" == windows ]]; then
+    dump_cmd='objdump -x '"$1"' | fgrep "DLL Name"'
+    white_list="KERNEL32\.dll\|msvcrt\.dll"
+  elif [[ "$OS" == linux ]]; then
+    dump_cmd='ldd '"$1"
+    if [[ "$ARCH" == x86_32 ]]; then
+      white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
+    elif [[ "$ARCH" == x86_64 ]]; then
+      white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
+    fi
+  elif [[ "$OS" == osx ]]; then
+    dump_cmd='otool -L '"$1"' | fgrep dylib'
+    white_list="libz\.1\.dylib\|libstdc++\.6\.dylib\|libSystem\.B\.dylib"
+  fi
+  if [[ -z "$white_list" || -z "$dump_cmd" ]]; then
+    fail "Unsupported platform $OS-$ARCH."
+  fi
+  echo "Checking for expected dependencies ..."
+  eval $dump_cmd | grep -i "$white_list" || fail "doesn't show any expected dependencies"
+  echo "Checking for unexpected dependencies ..."
+  eval $dump_cmd | grep -i -v "$white_list"
+  ret=$?
+  if [[ $ret == 0 ]]; then
+    fail "found unexpected dependencies (listed above)."
+  elif [[ $ret != 1 ]]; then
+    fail "Error when checking dependencies."
+  fi  # grep returns 1 when "not found", which is what we expect
+  echo "Dependencies look good."
+  echo
+}
+############################################################################
+
+echo "Building protoc, OS=$OS ARCH=$ARCH"
+
+# Nested double quotes are unintuitive, but it works.
+cd "$(dirname "$0")"
+
+WORKING_DIR=$(pwd)
+CONFIGURE_ARGS="--disable-shared"
+
+MAKE_TARGET="protoc"
+if [[ "$OS" == windows ]]; then
+  MAKE_TARGET="${MAKE_TARGET}.exe"
+fi
+
+# Override the default value set in configure.ac that has '-g' which produces
+# huge binary.
+CXXFLAGS="-DNDEBUG"
+LDFLAGS=""
+
+if [[ "$(uname)" == CYGWIN* ]]; then
+  assertEq "$OS" windows $LINENO
+  # Use mingw32 compilers because executables produced by Cygwin compiler
+  # always have dependency on Cygwin DLL.
+  if [[ "$ARCH" == x86_64 ]]; then
+    CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
+  elif [[ "$ARCH" == x86_32 ]]; then
+    CONFIGURE_ARGS="$CONFIGURE_ARGS --host=i686-pc-mingw32"
+  else
+    fail "Unsupported arch by CYGWIN: $ARCH"
+  fi
+elif [[ "$(uname)" == MINGW32* ]]; then
+  assertEq "$OS" windows $LINENO
+  assertEq "$ARCH" x86_32 $LINENO
+elif [[ "$(uname)" == MINGW64* ]]; then
+  assertEq "$OS" windows $LINENO
+  assertEq "$ARCH" x86_64 $LINENO
+elif [[ "$(uname)" == Linux* ]]; then
+  if [[ "$OS" == linux ]]; then
+    if [[ "$ARCH" == x86_64 ]]; then
+      CXXFLAGS="$CXXFLAGS -m64"
+    elif [[ "$ARCH" == x86_32 ]]; then
+      CXXFLAGS="$CXXFLAGS -m32"
+    else
+      fail "Unsupported arch: $ARCH"
+    fi
+  elif [[ "$OS" == windows ]]; then
+    # Cross-compilation for Windows
+    # TODO(zhangkun83) MinGW 64 always adds dependency on libwinpthread-1.dll,
+    # which is undesirable for repository deployment.
+    CONFIGURE_ARGS="$CONFIGURE_ARGS"
+    if [[ "$ARCH" == x86_64 ]]; then
+      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
+    elif [[ "$ARCH" == x86_32 ]]; then
+      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=i686-w64-mingw32"
+    else
+      fail "Unsupported arch: $ARCH"
+    fi
+  else
+    fail "Cannot build $OS on $(uname)"
+  fi
+elif [[ "$(uname)" == Darwin* ]]; then
+  assertEq "$OS" osx $LINENO
+  # Make the binary compatible with OSX 10.7 and later
+  CXXFLAGS="$CXXFLAGS -mmacosx-version-min=10.7"
+  if [[ "$ARCH" == x86_64 ]]; then
+    CXXFLAGS="$CXXFLAGS -m64"
+  elif [[ "$ARCH" == x86_32 ]]; then
+    CXXFLAGS="$CXXFLAGS -m32"
+  else
+    fail "Unsupported arch: $ARCH"
+  fi
+else
+  fail "Unsupported system: $(uname)"
+fi
+
+# Statically link libgcc and libstdc++.
+# -s to produce stripped binary.
+# And they don't work under Mac.
+if [[ "$OS" != osx ]]; then
+  LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -s"
+fi
+
+export CXXFLAGS LDFLAGS
+
+TARGET_FILE=target/protoc.exe
+
+cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS &&
+  cd src && make clean && make $MAKE_TARGET &&
+  cd "$WORKING_DIR" && mkdir -p target &&
+  (cp ../src/protoc $TARGET_FILE || cp ../src/protoc.exe $TARGET_FILE) ||
+  exit 1
+
+if [[ "$OS" == osx ]]; then
+  # Since Mac linker doesn't accept "-s", we need to run strip
+  strip $TARGET_FILE || exit 1
+fi
+
+checkArch $TARGET_FILE && checkDependencies $TARGET_FILE
diff --git a/src/third_party/protobuf-3/protoc-artifacts/pom.xml b/src/third_party/protobuf-3/protoc-artifacts/pom.xml
new file mode 100644
index 0000000..e9728a0
--- /dev/null
+++ b/src/third_party/protobuf-3/protoc-artifacts/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google</groupId>
+    <artifactId>google</artifactId>
+    <version>1</version>
+  </parent>
+  <groupId>com.google.protobuf</groupId>
+  <artifactId>protoc</artifactId>
+  <version>3.0.0-beta-2</version>
+  <packaging>pom</packaging>
+  <name>Protobuf Compiler</name>
+  <description>
+    Protobuf Compiler (protoc) is a compiler for .proto files. It generates
+    language-specific code for Protobuf messages and RPC interfaces.
+  </description>
+  <inceptionYear>2008</inceptionYear>
+  <url>https://developers.google.com/protocol-buffers/</url>
+  <licenses>
+    <license>
+      <name>New BSD license</name>
+      <url>http://www.opensource.org/licenses/bsd-license.php</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <url>https://github.com/google/protobuf</url>
+    <connection>
+      scm:git:https://github.com/google/protobuf.git
+    </connection>
+  </scm>
+  <build>
+    <extensions>
+      <extension>
+        <groupId>kr.motd.maven</groupId>
+        <artifactId>os-maven-plugin</artifactId>
+        <version>1.2.3.Final</version>
+      </extension>
+    </extensions>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <version>1.1.1</version>
+        <executions>
+          <execution>
+            <phase>compile</phase>
+            <goals>
+              <goal>exec</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <executable>bash</executable>
+          <arguments>
+            <argument>build-protoc.sh</argument>
+            <argument>${os.detected.name}</argument>
+            <argument>${os.detected.arch}</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.8</version>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <phase>package</phase>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${basedir}/target/protoc.exe</file>
+                  <classifier>${os.detected.name}-${os.detected.arch}</classifier>
+                  <type>exe</type>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>release</id>
+      <properties>
+        <!-- Specify the staging repository to deploy to. This can be left
+             empty for the first deployment, and Sonatype will create one. For
+             subsequent deployments it should be set to what Sonatype has
+             created, so that all deployments will go to the same repository.
+             -->
+        <staging.repository></staging.repository>
+      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.5</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>nexus-staging-maven-plugin</artifactId>
+            <version>1.6.3</version>
+            <extensions>true</extensions>
+            <configuration>
+               <serverId>sonatype-nexus-staging</serverId>
+               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+               <skipStagingRepositoryClose>true</skipStagingRepositoryClose>
+               <autoReleaseAfterClose>false</autoReleaseAfterClose>
+               <stagingRepositoryId>${staging.repository}</stagingRepositoryId>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/src/third_party/protobuf-3/python/MANIFEST.in b/src/third_party/protobuf-3/python/MANIFEST.in
new file mode 100644
index 0000000..2608882
--- /dev/null
+++ b/src/third_party/protobuf-3/python/MANIFEST.in
@@ -0,0 +1,14 @@
+prune google/protobuf/internal/import_test_package
+exclude google/protobuf/internal/*_pb2.py
+exclude google/protobuf/internal/*_test.py
+exclude google/protobuf/internal/*.proto
+exclude google/protobuf/internal/test_util.py
+
+recursive-exclude google *_test.py
+recursive-exclude google *_test.proto
+recursive-exclude google unittest*_pb2.py
+
+global-exclude *.dll
+global-exclude *.pyc
+global-exclude *.pyo
+global-exclude *.so
diff --git a/src/third_party/protobuf-3/python/README.md b/src/third_party/protobuf-3/python/README.md
new file mode 100644
index 0000000..57acfd9
--- /dev/null
+++ b/src/third_party/protobuf-3/python/README.md
@@ -0,0 +1,127 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the Python Protocol Buffers runtime library.
+
+Normally, this directory comes as part of the protobuf package, available
+from:
+
+  https://developers.google.com/protocol-buffers/
+
+The complete package includes the C++ source code, which includes the
+Protocol Compiler (protoc).  If you downloaded this package from PyPI
+or some other Python-specific source, you may have received only the
+Python part of the code.  In this case, you will need to obtain the
+Protocol Compiler from some other source before you can use this
+package.
+
+Development Warning
+===================
+
+The Python implementation of Protocol Buffers is not as mature as the C++
+and Java implementations.  It may be more buggy, and it is known to be
+pretty slow at this time.  If you would like to help fix these issues,
+join the Protocol Buffers discussion list and let us know!
+
+Installation
+============
+
+1) Make sure you have Python 2.6 or newer.  If in doubt, run:
+
+     $ python -V
+
+2) If you do not have setuptools installed, note that it will be
+   downloaded and installed automatically as soon as you run setup.py.
+   If you would rather install it manually, you may do so by following
+   the instructions on this page:
+
+     https://packaging.python.org/en/latest/installing.html#setup-for-installing-packages
+
+3) Build the C++ code, or install a binary distribution of protoc.  If
+   you install a binary distribution, make sure that it is the same
+   version as this package.  If in doubt, run:
+
+     $ protoc --version
+
+4) Build and run the tests:
+
+     $ python setup.py build
+     $ python setup.py test
+
+     To build, test, and use the C++ implementation, you must first compile
+     libprotobuf.so:
+
+     $ (cd .. && make)
+
+     On OS X:
+
+      If you are running a homebrew-provided python, you must make sure another
+      version of protobuf is not already installed, as homebrew's python will
+      search /usr/local/lib for libprotobuf.so before it searches ../src/.libs
+      You can either unlink homebrew's protobuf or install the libprotobuf you
+      built earlier:
+
+      $ brew unlink protobuf
+      or
+      $ (cd .. && make install)
+
+     On other *nix:
+
+      You must make libprotobuf.so dynamically available. You can either
+      install libprotobuf you built earlier, or set LD_LIBRARY_PATH:
+
+      $ export LD_LIBRARY_PATH=../src/.libs
+      or
+      $ (cd .. && make install)
+
+     To build the C++ implementation run:
+     $ python setup.py build --cpp_implementation
+
+     Then run the tests like so:
+     $ python setup.py test --cpp_implementation
+
+   If some tests fail, this library may not work correctly on your
+   system.  Continue at your own risk.
+
+   Please note that there is a known problem with some versions of
+   Python on Cygwin which causes the tests to fail after printing the
+   error:  "sem_init: Resource temporarily unavailable".  This appears
+   to be a bug either in Cygwin or in Python:
+     http://www.cygwin.com/ml/cygwin/2005-07/msg01378.html
+   We do not know if or when it might me fixed.  We also do not know
+   how likely it is that this bug will affect users in practice.
+
+5) Install:
+
+    $ python setup.py install
+
+  or:
+
+    $ (cd .. && make install)
+    $ python setup.py install --cpp_implementation
+
+   This step may require superuser privileges.
+   NOTE: To use C++ implementation, you need to export an environment
+   variable before running your program.  See the "C++ Implementation"
+   section below for more details.
+
+Usage
+=====
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+  https://developers.google.com/protocol-buffers/
+
+C++ Implementation
+==================
+
+The C++ implementation for Python messages is built as a Python extension to
+improve the overall protobuf Python performance.
+
+To use the C++ implementation, you need to install the C++ protobuf runtime
+library, please see instructions in the parent directory.
diff --git a/src/third_party/protobuf-3/python/google/__init__.py b/src/third_party/protobuf-3/python/google/__init__.py
new file mode 100755
index 0000000..5585614
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/__init__.py
@@ -0,0 +1,4 @@
+try:
+  __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/__init__.py b/src/third_party/protobuf-3/python/google/protobuf/__init__.py
new file mode 100755
index 0000000..2a3c677
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/__init__.py
@@ -0,0 +1,39 @@
+# 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.
+
+# Copyright 2007 Google Inc. All Rights Reserved.
+
+__version__ = '3.0.0b3'
+
+if __name__ != '__main__':
+  try:
+    __import__('pkg_resources').declare_namespace(__name__)
+  except ImportError:
+    __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/descriptor.py b/src/third_party/protobuf-3/python/google/protobuf/descriptor.py
new file mode 100755
index 0000000..3209b34
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/descriptor.py
@@ -0,0 +1,971 @@
+# 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.
+
+"""Descriptors essentially contain exactly the information found in a .proto
+file, in types that make this information accessible in Python.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+import six
+
+from google.protobuf.internal import api_implementation
+
+_USE_C_DESCRIPTORS = False
+if api_implementation.Type() == 'cpp':
+  # Used by MakeDescriptor in cpp mode
+  import os
+  import uuid
+  from google.protobuf.pyext import _message
+  _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
+
+
+class Error(Exception):
+  """Base error for this module."""
+
+
+class TypeTransformationError(Error):
+  """Error transforming between python proto type and corresponding C++ type."""
+
+
+if _USE_C_DESCRIPTORS:
+  # This metaclass allows to override the behavior of code like
+  #     isinstance(my_descriptor, FieldDescriptor)
+  # and make it return True when the descriptor is an instance of the extension
+  # type written in C++.
+  class DescriptorMetaclass(type):
+    def __instancecheck__(cls, obj):
+      if super(DescriptorMetaclass, cls).__instancecheck__(obj):
+        return True
+      if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
+        return True
+      return False
+else:
+  # The standard metaclass; nothing changes.
+  DescriptorMetaclass = type
+
+
+class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
+
+  """Descriptors base class.
+
+  This class is the base of all descriptor classes. It provides common options
+  related functionality.
+
+  Attributes:
+    has_options:  True if the descriptor has non-default options.  Usually it
+        is not necessary to read this -- just call GetOptions() which will
+        happily return the default instance.  However, it's sometimes useful
+        for efficiency, and also useful inside the protobuf implementation to
+        avoid some bootstrapping issues.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    # The class, or tuple of classes, that are considered as "virtual
+    # subclasses" of this descriptor class.
+    _C_DESCRIPTOR_CLASS = ()
+
+  def __init__(self, options, options_class_name):
+    """Initialize the descriptor given its options message and the name of the
+    class of the options message. The name of the class is required in case
+    the options message is None and has to be created.
+    """
+    self._options = options
+    self._options_class_name = options_class_name
+
+    # Does this descriptor have non-default options?
+    self.has_options = options is not None
+
+  def _SetOptions(self, options, options_class_name):
+    """Sets the descriptor's options
+
+    This function is used in generated proto2 files to update descriptor
+    options. It must not be used outside proto2.
+    """
+    self._options = options
+    self._options_class_name = options_class_name
+
+    # Does this descriptor have non-default options?
+    self.has_options = options is not None
+
+  def GetOptions(self):
+    """Retrieves descriptor options.
+
+    This method returns the options set or creates the default options for the
+    descriptor.
+    """
+    if self._options:
+      return self._options
+    from google.protobuf import descriptor_pb2
+    try:
+      options_class = getattr(descriptor_pb2, self._options_class_name)
+    except AttributeError:
+      raise RuntimeError('Unknown options class name %s!' %
+                         (self._options_class_name))
+    self._options = options_class()
+    return self._options
+
+
+class _NestedDescriptorBase(DescriptorBase):
+  """Common class for descriptors that can be nested."""
+
+  def __init__(self, options, options_class_name, name, full_name,
+               file, containing_type, serialized_start=None,
+               serialized_end=None):
+    """Constructor.
+
+    Args:
+      options: Protocol message options or None
+        to use default message options.
+      options_class_name: (str) The class name of the above options.
+
+      name: (str) Name of this protocol message type.
+      full_name: (str) Fully-qualified name of this protocol message type,
+        which will include protocol "package" name and the name of any
+        enclosing types.
+      file: (FileDescriptor) Reference to file info.
+      containing_type: if provided, this is a nested descriptor, with this
+        descriptor as parent, otherwise None.
+      serialized_start: The start index (inclusive) in block in the
+        file.serialized_pb that describes this descriptor.
+      serialized_end: The end index (exclusive) in block in the
+        file.serialized_pb that describes this descriptor.
+    """
+    super(_NestedDescriptorBase, self).__init__(
+        options, options_class_name)
+
+    self.name = name
+    # TODO(falk): Add function to calculate full_name instead of having it in
+    #             memory?
+    self.full_name = full_name
+    self.file = file
+    self.containing_type = containing_type
+
+    self._serialized_start = serialized_start
+    self._serialized_end = serialized_end
+
+  def GetTopLevelContainingType(self):
+    """Returns the root if this is a nested type, or itself if its the root."""
+    desc = self
+    while desc.containing_type is not None:
+      desc = desc.containing_type
+    return desc
+
+  def CopyToProto(self, proto):
+    """Copies this to the matching proto in descriptor_pb2.
+
+    Args:
+      proto: An empty proto instance from descriptor_pb2.
+
+    Raises:
+      Error: If self couldnt be serialized, due to to few constructor arguments.
+    """
+    if (self.file is not None and
+        self._serialized_start is not None and
+        self._serialized_end is not None):
+      proto.ParseFromString(self.file.serialized_pb[
+          self._serialized_start:self._serialized_end])
+    else:
+      raise Error('Descriptor does not contain serialization.')
+
+
+class Descriptor(_NestedDescriptorBase):
+
+  """Descriptor for a protocol message type.
+
+  A Descriptor instance has the following attributes:
+
+    name: (str) Name of this protocol message type.
+    full_name: (str) Fully-qualified name of this protocol message type,
+      which will include protocol "package" name and the name of any
+      enclosing types.
+
+    containing_type: (Descriptor) Reference to the descriptor of the
+      type containing us, or None if this is top-level.
+
+    fields: (list of FieldDescriptors) Field descriptors for all
+      fields in this type.
+    fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor
+      objects as in |fields|, but indexed by "number" attribute in each
+      FieldDescriptor.
+    fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor
+      objects as in |fields|, but indexed by "name" attribute in each
+      FieldDescriptor.
+    fields_by_camelcase_name: (dict str -> FieldDescriptor) Same
+      FieldDescriptor objects as in |fields|, but indexed by
+      "camelcase_name" attribute in each FieldDescriptor.
+
+    nested_types: (list of Descriptors) Descriptor references
+      for all protocol message types nested within this one.
+    nested_types_by_name: (dict str -> Descriptor) Same Descriptor
+      objects as in |nested_types|, but indexed by "name" attribute
+      in each Descriptor.
+
+    enum_types: (list of EnumDescriptors) EnumDescriptor references
+      for all enums contained within this type.
+    enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor
+      objects as in |enum_types|, but indexed by "name" attribute
+      in each EnumDescriptor.
+    enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping
+      from enum value name to EnumValueDescriptor for that value.
+
+    extensions: (list of FieldDescriptor) All extensions defined directly
+      within this message type (NOT within a nested type).
+    extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor
+      objects as |extensions|, but indexed by "name" attribute of each
+      FieldDescriptor.
+
+    is_extendable:  Does this type define any extension ranges?
+
+    oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields
+      in this message.
+    oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|,
+      but indexed by "name" attribute.
+
+    file: (FileDescriptor) Reference to file descriptor.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.Descriptor
+
+    def __new__(cls, name, full_name, filename, containing_type, fields,
+                nested_types, enum_types, extensions, options=None,
+                is_extendable=True, extension_ranges=None, oneofs=None,
+                file=None, serialized_start=None, serialized_end=None,
+                syntax=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.default_pool.FindMessageTypeByName(full_name)
+
+  # NOTE(tmarek): The file argument redefining a builtin is nothing we can
+  # fix right now since we don't know how many clients already rely on the
+  # name of the argument.
+  def __init__(self, name, full_name, filename, containing_type, fields,
+               nested_types, enum_types, extensions, options=None,
+               is_extendable=True, extension_ranges=None, oneofs=None,
+               file=None, serialized_start=None, serialized_end=None,
+               syntax=None):  # pylint:disable=redefined-builtin
+    """Arguments to __init__() are as described in the description
+    of Descriptor fields above.
+
+    Note that filename is an obsolete argument, that is not used anymore.
+    Please use file.name to access this as an attribute.
+    """
+    super(Descriptor, self).__init__(
+        options, 'MessageOptions', name, full_name, file,
+        containing_type, serialized_start=serialized_start,
+        serialized_end=serialized_end)
+
+    # We have fields in addition to fields_by_name and fields_by_number,
+    # so that:
+    #   1. Clients can index fields by "order in which they're listed."
+    #   2. Clients can easily iterate over all fields with the terse
+    #      syntax: for f in descriptor.fields: ...
+    self.fields = fields
+    for field in self.fields:
+      field.containing_type = self
+    self.fields_by_number = dict((f.number, f) for f in fields)
+    self.fields_by_name = dict((f.name, f) for f in fields)
+    self._fields_by_camelcase_name = None
+
+    self.nested_types = nested_types
+    for nested_type in nested_types:
+      nested_type.containing_type = self
+    self.nested_types_by_name = dict((t.name, t) for t in nested_types)
+
+    self.enum_types = enum_types
+    for enum_type in self.enum_types:
+      enum_type.containing_type = self
+    self.enum_types_by_name = dict((t.name, t) for t in enum_types)
+    self.enum_values_by_name = dict(
+        (v.name, v) for t in enum_types for v in t.values)
+
+    self.extensions = extensions
+    for extension in self.extensions:
+      extension.extension_scope = self
+    self.extensions_by_name = dict((f.name, f) for f in extensions)
+    self.is_extendable = is_extendable
+    self.extension_ranges = extension_ranges
+    self.oneofs = oneofs if oneofs is not None else []
+    self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
+    for oneof in self.oneofs:
+      oneof.containing_type = self
+    self.syntax = syntax or "proto2"
+
+  @property
+  def fields_by_camelcase_name(self):
+    if self._fields_by_camelcase_name is None:
+      self._fields_by_camelcase_name = dict(
+          (f.camelcase_name, f) for f in self.fields)
+    return self._fields_by_camelcase_name
+
+  def EnumValueName(self, enum, value):
+    """Returns the string name of an enum value.
+
+    This is just a small helper method to simplify a common operation.
+
+    Args:
+      enum: string name of the Enum.
+      value: int, value of the enum.
+
+    Returns:
+      string name of the enum value.
+
+    Raises:
+      KeyError if either the Enum doesn't exist or the value is not a valid
+        value for the enum.
+    """
+    return self.enum_types_by_name[enum].values_by_number[value].name
+
+  def CopyToProto(self, proto):
+    """Copies this to a descriptor_pb2.DescriptorProto.
+
+    Args:
+      proto: An empty descriptor_pb2.DescriptorProto.
+    """
+    # This function is overriden to give a better doc comment.
+    super(Descriptor, self).CopyToProto(proto)
+
+
+# TODO(robinson): We should have aggressive checking here,
+# for example:
+#   * If you specify a repeated field, you should not be allowed
+#     to specify a default value.
+#   * [Other examples here as needed].
+#
+# TODO(robinson): for this and other *Descriptor classes, we
+# might also want to lock things down aggressively (e.g.,
+# prevent clients from setting the attributes).  Having
+# stronger invariants here in general will reduce the number
+# of runtime checks we must do in reflection.py...
+class FieldDescriptor(DescriptorBase):
+
+  """Descriptor for a single field in a .proto file.
+
+  A FieldDescriptor instance has the following attributes:
+
+    name: (str) Name of this field, exactly as it appears in .proto.
+    full_name: (str) Name of this field, including containing scope.  This is
+      particularly relevant for extensions.
+    camelcase_name: (str) Camelcase name of this field.
+    index: (int) Dense, 0-indexed index giving the order that this
+      field textually appears within its message in the .proto file.
+    number: (int) Tag number declared for this field in the .proto file.
+
+    type: (One of the TYPE_* constants below) Declared type.
+    cpp_type: (One of the CPPTYPE_* constants below) C++ type used to
+      represent this field.
+
+    label: (One of the LABEL_* constants below) Tells whether this
+      field is optional, required, or repeated.
+    has_default_value: (bool) True if this field has a default value defined,
+      otherwise false.
+    default_value: (Varies) Default value of this field.  Only
+      meaningful for non-repeated scalar fields.  Repeated fields
+      should always set this to [], and non-repeated composite
+      fields should always set this to None.
+
+    containing_type: (Descriptor) Descriptor of the protocol message
+      type that contains this field.  Set by the Descriptor constructor
+      if we're passed into one.
+      Somewhat confusingly, for extension fields, this is the
+      descriptor of the EXTENDED message, not the descriptor
+      of the message containing this field.  (See is_extension and
+      extension_scope below).
+    message_type: (Descriptor) If a composite field, a descriptor
+      of the message type contained in this field.  Otherwise, this is None.
+    enum_type: (EnumDescriptor) If this field contains an enum, a
+      descriptor of that enum.  Otherwise, this is None.
+
+    is_extension: True iff this describes an extension field.
+    extension_scope: (Descriptor) Only meaningful if is_extension is True.
+      Gives the message that immediately contains this extension field.
+      Will be None iff we're a top-level (file-level) extension field.
+
+    options: (descriptor_pb2.FieldOptions) Protocol message field options or
+      None to use default field options.
+
+    containing_oneof: (OneofDescriptor) If the field is a member of a oneof
+      union, contains its descriptor. Otherwise, None.
+  """
+
+  # Must be consistent with C++ FieldDescriptor::Type enum in
+  # descriptor.h.
+  #
+  # TODO(robinson): Find a way to eliminate this repetition.
+  TYPE_DOUBLE         = 1
+  TYPE_FLOAT          = 2
+  TYPE_INT64          = 3
+  TYPE_UINT64         = 4
+  TYPE_INT32          = 5
+  TYPE_FIXED64        = 6
+  TYPE_FIXED32        = 7
+  TYPE_BOOL           = 8
+  TYPE_STRING         = 9
+  TYPE_GROUP          = 10
+  TYPE_MESSAGE        = 11
+  TYPE_BYTES          = 12
+  TYPE_UINT32         = 13
+  TYPE_ENUM           = 14
+  TYPE_SFIXED32       = 15
+  TYPE_SFIXED64       = 16
+  TYPE_SINT32         = 17
+  TYPE_SINT64         = 18
+  MAX_TYPE            = 18
+
+  # Must be consistent with C++ FieldDescriptor::CppType enum in
+  # descriptor.h.
+  #
+  # TODO(robinson): Find a way to eliminate this repetition.
+  CPPTYPE_INT32       = 1
+  CPPTYPE_INT64       = 2
+  CPPTYPE_UINT32      = 3
+  CPPTYPE_UINT64      = 4
+  CPPTYPE_DOUBLE      = 5
+  CPPTYPE_FLOAT       = 6
+  CPPTYPE_BOOL        = 7
+  CPPTYPE_ENUM        = 8
+  CPPTYPE_STRING      = 9
+  CPPTYPE_MESSAGE     = 10
+  MAX_CPPTYPE         = 10
+
+  _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
+      TYPE_DOUBLE: CPPTYPE_DOUBLE,
+      TYPE_FLOAT: CPPTYPE_FLOAT,
+      TYPE_ENUM: CPPTYPE_ENUM,
+      TYPE_INT64: CPPTYPE_INT64,
+      TYPE_SINT64: CPPTYPE_INT64,
+      TYPE_SFIXED64: CPPTYPE_INT64,
+      TYPE_UINT64: CPPTYPE_UINT64,
+      TYPE_FIXED64: CPPTYPE_UINT64,
+      TYPE_INT32: CPPTYPE_INT32,
+      TYPE_SFIXED32: CPPTYPE_INT32,
+      TYPE_SINT32: CPPTYPE_INT32,
+      TYPE_UINT32: CPPTYPE_UINT32,
+      TYPE_FIXED32: CPPTYPE_UINT32,
+      TYPE_BYTES: CPPTYPE_STRING,
+      TYPE_STRING: CPPTYPE_STRING,
+      TYPE_BOOL: CPPTYPE_BOOL,
+      TYPE_MESSAGE: CPPTYPE_MESSAGE,
+      TYPE_GROUP: CPPTYPE_MESSAGE
+      }
+
+  # Must be consistent with C++ FieldDescriptor::Label enum in
+  # descriptor.h.
+  #
+  # TODO(robinson): Find a way to eliminate this repetition.
+  LABEL_OPTIONAL      = 1
+  LABEL_REQUIRED      = 2
+  LABEL_REPEATED      = 3
+  MAX_LABEL           = 3
+
+  # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
+  # and kLastReservedNumber in descriptor.h
+  MAX_FIELD_NUMBER = (1 << 29) - 1
+  FIRST_RESERVED_FIELD_NUMBER = 19000
+  LAST_RESERVED_FIELD_NUMBER = 19999
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
+
+    def __new__(cls, name, full_name, index, number, type, cpp_type, label,
+                default_value, message_type, enum_type, containing_type,
+                is_extension, extension_scope, options=None,
+                has_default_value=True, containing_oneof=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      if is_extension:
+        return _message.default_pool.FindExtensionByName(full_name)
+      else:
+        return _message.default_pool.FindFieldByName(full_name)
+
+  def __init__(self, name, full_name, index, number, type, cpp_type, label,
+               default_value, message_type, enum_type, containing_type,
+               is_extension, extension_scope, options=None,
+               has_default_value=True, containing_oneof=None):
+    """The arguments are as described in the description of FieldDescriptor
+    attributes above.
+
+    Note that containing_type may be None, and may be set later if necessary
+    (to deal with circular references between message types, for example).
+    Likewise for extension_scope.
+    """
+    super(FieldDescriptor, self).__init__(options, 'FieldOptions')
+    self.name = name
+    self.full_name = full_name
+    self._camelcase_name = None
+    self.index = index
+    self.number = number
+    self.type = type
+    self.cpp_type = cpp_type
+    self.label = label
+    self.has_default_value = has_default_value
+    self.default_value = default_value
+    self.containing_type = containing_type
+    self.message_type = message_type
+    self.enum_type = enum_type
+    self.is_extension = is_extension
+    self.extension_scope = extension_scope
+    self.containing_oneof = containing_oneof
+    if api_implementation.Type() == 'cpp':
+      if is_extension:
+        self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
+      else:
+        self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
+    else:
+      self._cdescriptor = None
+
+  @property
+  def camelcase_name(self):
+    if self._camelcase_name is None:
+      self._camelcase_name = _ToCamelCase(self.name)
+    return self._camelcase_name
+
+  @staticmethod
+  def ProtoTypeToCppProtoType(proto_type):
+    """Converts from a Python proto type to a C++ Proto Type.
+
+    The Python ProtocolBuffer classes specify both the 'Python' datatype and the
+    'C++' datatype - and they're not the same. This helper method should
+    translate from one to another.
+
+    Args:
+      proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
+    Returns:
+      descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
+    Raises:
+      TypeTransformationError: when the Python proto type isn't known.
+    """
+    try:
+      return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
+    except KeyError:
+      raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
+
+
+class EnumDescriptor(_NestedDescriptorBase):
+
+  """Descriptor for an enum defined in a .proto file.
+
+  An EnumDescriptor instance has the following attributes:
+
+    name: (str) Name of the enum type.
+    full_name: (str) Full name of the type, including package name
+      and any enclosing type(s).
+
+    values: (list of EnumValueDescriptors) List of the values
+      in this enum.
+    values_by_name: (dict str -> EnumValueDescriptor) Same as |values|,
+      but indexed by the "name" field of each EnumValueDescriptor.
+    values_by_number: (dict int -> EnumValueDescriptor) Same as |values|,
+      but indexed by the "number" field of each EnumValueDescriptor.
+    containing_type: (Descriptor) Descriptor of the immediate containing
+      type of this enum, or None if this is an enum defined at the
+      top level in a .proto file.  Set by Descriptor's constructor
+      if we're passed into one.
+    file: (FileDescriptor) Reference to file descriptor.
+    options: (descriptor_pb2.EnumOptions) Enum options message or
+      None to use default enum options.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
+
+    def __new__(cls, name, full_name, filename, values,
+                containing_type=None, options=None, file=None,
+                serialized_start=None, serialized_end=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.default_pool.FindEnumTypeByName(full_name)
+
+  def __init__(self, name, full_name, filename, values,
+               containing_type=None, options=None, file=None,
+               serialized_start=None, serialized_end=None):
+    """Arguments are as described in the attribute description above.
+
+    Note that filename is an obsolete argument, that is not used anymore.
+    Please use file.name to access this as an attribute.
+    """
+    super(EnumDescriptor, self).__init__(
+        options, 'EnumOptions', name, full_name, file,
+        containing_type, serialized_start=serialized_start,
+        serialized_end=serialized_end)
+
+    self.values = values
+    for value in self.values:
+      value.type = self
+    self.values_by_name = dict((v.name, v) for v in values)
+    self.values_by_number = dict((v.number, v) for v in values)
+
+  def CopyToProto(self, proto):
+    """Copies this to a descriptor_pb2.EnumDescriptorProto.
+
+    Args:
+      proto: An empty descriptor_pb2.EnumDescriptorProto.
+    """
+    # This function is overriden to give a better doc comment.
+    super(EnumDescriptor, self).CopyToProto(proto)
+
+
+class EnumValueDescriptor(DescriptorBase):
+
+  """Descriptor for a single value within an enum.
+
+    name: (str) Name of this value.
+    index: (int) Dense, 0-indexed index giving the order that this
+      value appears textually within its enum in the .proto file.
+    number: (int) Actual number assigned to this enum value.
+    type: (EnumDescriptor) EnumDescriptor to which this value
+      belongs.  Set by EnumDescriptor's constructor if we're
+      passed into one.
+    options: (descriptor_pb2.EnumValueOptions) Enum value options message or
+      None to use default enum value options options.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
+
+    def __new__(cls, name, index, number, type=None, options=None):
+      _message.Message._CheckCalledFromGeneratedFile()
+      # There is no way we can build a complete EnumValueDescriptor with the
+      # given parameters (the name of the Enum is not known, for example).
+      # Fortunately generated files just pass it to the EnumDescriptor()
+      # constructor, which will ignore it, so returning None is good enough.
+      return None
+
+  def __init__(self, name, index, number, type=None, options=None):
+    """Arguments are as described in the attribute description above."""
+    super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
+    self.name = name
+    self.index = index
+    self.number = number
+    self.type = type
+
+
+class OneofDescriptor(object):
+  """Descriptor for a oneof field.
+
+    name: (str) Name of the oneof field.
+    full_name: (str) Full name of the oneof field, including package name.
+    index: (int) 0-based index giving the order of the oneof field inside
+      its containing type.
+    containing_type: (Descriptor) Descriptor of the protocol message
+      type that contains this field.  Set by the Descriptor constructor
+      if we're passed into one.
+    fields: (list of FieldDescriptor) The list of field descriptors this
+      oneof can contain.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
+
+    def __new__(cls, name, full_name, index, containing_type, fields):
+      _message.Message._CheckCalledFromGeneratedFile()
+      return _message.default_pool.FindOneofByName(full_name)
+
+  def __init__(self, name, full_name, index, containing_type, fields):
+    """Arguments are as described in the attribute description above."""
+    self.name = name
+    self.full_name = full_name
+    self.index = index
+    self.containing_type = containing_type
+    self.fields = fields
+
+
+class ServiceDescriptor(_NestedDescriptorBase):
+
+  """Descriptor for a service.
+
+    name: (str) Name of the service.
+    full_name: (str) Full name of the service, including package name.
+    index: (int) 0-indexed index giving the order that this services
+      definition appears withing the .proto file.
+    methods: (list of MethodDescriptor) List of methods provided by this
+      service.
+    options: (descriptor_pb2.ServiceOptions) Service options message or
+      None to use default service options.
+    file: (FileDescriptor) Reference to file info.
+  """
+
+  def __init__(self, name, full_name, index, methods, options=None, file=None,
+               serialized_start=None, serialized_end=None):
+    super(ServiceDescriptor, self).__init__(
+        options, 'ServiceOptions', name, full_name, file,
+        None, serialized_start=serialized_start,
+        serialized_end=serialized_end)
+    self.index = index
+    self.methods = methods
+    # Set the containing service for each method in this service.
+    for method in self.methods:
+      method.containing_service = self
+
+  def FindMethodByName(self, name):
+    """Searches for the specified method, and returns its descriptor."""
+    for method in self.methods:
+      if name == method.name:
+        return method
+    return None
+
+  def CopyToProto(self, proto):
+    """Copies this to a descriptor_pb2.ServiceDescriptorProto.
+
+    Args:
+      proto: An empty descriptor_pb2.ServiceDescriptorProto.
+    """
+    # This function is overriden to give a better doc comment.
+    super(ServiceDescriptor, self).CopyToProto(proto)
+
+
+class MethodDescriptor(DescriptorBase):
+
+  """Descriptor for a method in a service.
+
+  name: (str) Name of the method within the service.
+  full_name: (str) Full name of method.
+  index: (int) 0-indexed index of the method inside the service.
+  containing_service: (ServiceDescriptor) The service that contains this
+    method.
+  input_type: The descriptor of the message that this method accepts.
+  output_type: The descriptor of the message that this method returns.
+  options: (descriptor_pb2.MethodOptions) Method options message or
+    None to use default method options.
+  """
+
+  def __init__(self, name, full_name, index, containing_service,
+               input_type, output_type, options=None):
+    """The arguments are as described in the description of MethodDescriptor
+    attributes above.
+
+    Note that containing_service may be None, and may be set later if necessary.
+    """
+    super(MethodDescriptor, self).__init__(options, 'MethodOptions')
+    self.name = name
+    self.full_name = full_name
+    self.index = index
+    self.containing_service = containing_service
+    self.input_type = input_type
+    self.output_type = output_type
+
+
+class FileDescriptor(DescriptorBase):
+  """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
+
+  Note that enum_types_by_name, extensions_by_name, and dependencies
+  fields are only set by the message_factory module, and not by the
+  generated proto code.
+
+  name: name of file, relative to root of source tree.
+  package: name of the package
+  syntax: string indicating syntax of the file (can be "proto2" or "proto3")
+  serialized_pb: (str) Byte string of serialized
+    descriptor_pb2.FileDescriptorProto.
+  dependencies: List of other FileDescriptors this FileDescriptor depends on.
+  public_dependencies: A list of FileDescriptors, subset of the dependencies
+    above, which were declared as "public".
+  message_types_by_name: Dict of message names of their descriptors.
+  enum_types_by_name: Dict of enum names and their descriptors.
+  extensions_by_name: Dict of extension names and their descriptors.
+  pool: the DescriptorPool this descriptor belongs to.  When not passed to the
+    constructor, the global default pool is used.
+  """
+
+  if _USE_C_DESCRIPTORS:
+    _C_DESCRIPTOR_CLASS = _message.FileDescriptor
+
+    def __new__(cls, name, package, options=None, serialized_pb=None,
+                dependencies=None, public_dependencies=None,
+                syntax=None, pool=None):
+      # FileDescriptor() is called from various places, not only from generated
+      # files, to register dynamic proto files and messages.
+      if serialized_pb:
+        # TODO(amauryfa): use the pool passed as argument. This will work only
+        # for C++-implemented DescriptorPools.
+        return _message.default_pool.AddSerializedFile(serialized_pb)
+      else:
+        return super(FileDescriptor, cls).__new__(cls)
+
+  def __init__(self, name, package, options=None, serialized_pb=None,
+               dependencies=None, public_dependencies=None,
+               syntax=None, pool=None):
+    """Constructor."""
+    super(FileDescriptor, self).__init__(options, 'FileOptions')
+
+    if pool is None:
+      from google.protobuf import descriptor_pool
+      pool = descriptor_pool.Default()
+    self.pool = pool
+    self.message_types_by_name = {}
+    self.name = name
+    self.package = package
+    self.syntax = syntax or "proto2"
+    self.serialized_pb = serialized_pb
+
+    self.enum_types_by_name = {}
+    self.extensions_by_name = {}
+    self.dependencies = (dependencies or [])
+    self.public_dependencies = (public_dependencies or [])
+
+    if (api_implementation.Type() == 'cpp' and
+        self.serialized_pb is not None):
+      _message.default_pool.AddSerializedFile(self.serialized_pb)
+
+  def CopyToProto(self, proto):
+    """Copies this to a descriptor_pb2.FileDescriptorProto.
+
+    Args:
+      proto: An empty descriptor_pb2.FileDescriptorProto.
+    """
+    proto.ParseFromString(self.serialized_pb)
+
+
+def _ParseOptions(message, string):
+  """Parses serialized options.
+
+  This helper function is used to parse serialized options in generated
+  proto2 files. It must not be used outside proto2.
+  """
+  message.ParseFromString(string)
+  return message
+
+
+def _ToCamelCase(name):
+  """Converts name to camel-case and returns it."""
+  capitalize_next = False
+  result = []
+
+  for c in name:
+    if c == '_':
+      if result:
+        capitalize_next = True
+    elif capitalize_next:
+      result.append(c.upper())
+      capitalize_next = False
+    else:
+      result += c
+
+  # Lower-case the first letter.
+  if result and result[0].isupper():
+    result[0] = result[0].lower()
+  return ''.join(result)
+
+
+def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
+                   syntax=None):
+  """Make a protobuf Descriptor given a DescriptorProto protobuf.
+
+  Handles nested descriptors. Note that this is limited to the scope of defining
+  a message inside of another message. Composite fields can currently only be
+  resolved if the message is defined in the same scope as the field.
+
+  Args:
+    desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+    package: Optional package name for the new message Descriptor (string).
+    build_file_if_cpp: Update the C++ descriptor pool if api matches.
+                       Set to False on recursion, so no duplicates are created.
+    syntax: The syntax/semantics that should be used.  Set to "proto3" to get
+            proto3 field presence semantics.
+  Returns:
+    A Descriptor for protobuf messages.
+  """
+  if api_implementation.Type() == 'cpp' and build_file_if_cpp:
+    # The C++ implementation requires all descriptors to be backed by the same
+    # definition in the C++ descriptor pool. To do this, we build a
+    # FileDescriptorProto with the same definition as this descriptor and build
+    # it into the pool.
+    from google.protobuf import descriptor_pb2
+    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+    file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
+
+    # Generate a random name for this proto file to prevent conflicts with any
+    # imported ones. We need to specify a file name so the descriptor pool
+    # accepts our FileDescriptorProto, but it is not important what that file
+    # name is actually set to.
+    proto_name = str(uuid.uuid4())
+
+    if package:
+      file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
+                                                proto_name + '.proto')
+      file_descriptor_proto.package = package
+    else:
+      file_descriptor_proto.name = proto_name + '.proto'
+
+    _message.default_pool.Add(file_descriptor_proto)
+    result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
+
+    if _USE_C_DESCRIPTORS:
+      return result.message_types_by_name[desc_proto.name]
+
+  full_message_name = [desc_proto.name]
+  if package: full_message_name.insert(0, package)
+
+  # Create Descriptors for enum types
+  enum_types = {}
+  for enum_proto in desc_proto.enum_type:
+    full_name = '.'.join(full_message_name + [enum_proto.name])
+    enum_desc = EnumDescriptor(
+      enum_proto.name, full_name, None, [
+          EnumValueDescriptor(enum_val.name, ii, enum_val.number)
+          for ii, enum_val in enumerate(enum_proto.value)])
+    enum_types[full_name] = enum_desc
+
+  # Create Descriptors for nested types
+  nested_types = {}
+  for nested_proto in desc_proto.nested_type:
+    full_name = '.'.join(full_message_name + [nested_proto.name])
+    # Nested types are just those defined inside of the message, not all types
+    # used by fields in the message, so no loops are possible here.
+    nested_desc = MakeDescriptor(nested_proto,
+                                 package='.'.join(full_message_name),
+                                 build_file_if_cpp=False,
+                                 syntax=syntax)
+    nested_types[full_name] = nested_desc
+
+  fields = []
+  for field_proto in desc_proto.field:
+    full_name = '.'.join(full_message_name + [field_proto.name])
+    enum_desc = None
+    nested_desc = None
+    if field_proto.HasField('type_name'):
+      type_name = field_proto.type_name
+      full_type_name = '.'.join(full_message_name +
+                                [type_name[type_name.rfind('.')+1:]])
+      if full_type_name in nested_types:
+        nested_desc = nested_types[full_type_name]
+      elif full_type_name in enum_types:
+        enum_desc = enum_types[full_type_name]
+      # Else type_name references a non-local type, which isn't implemented
+    field = FieldDescriptor(
+        field_proto.name, full_name, field_proto.number - 1,
+        field_proto.number, field_proto.type,
+        FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
+        field_proto.label, None, nested_desc, enum_desc, None, False, None,
+        options=field_proto.options, has_default_value=False)
+    fields.append(field)
+
+  desc_name = '.'.join(full_message_name)
+  return Descriptor(desc_proto.name, desc_name, None, None, fields,
+                    list(nested_types.values()), list(enum_types.values()), [],
+                    options=desc_proto.options)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/descriptor_database.py b/src/third_party/protobuf-3/python/google/protobuf/descriptor_database.py
new file mode 100644
index 0000000..1333f99
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/descriptor_database.py
@@ -0,0 +1,141 @@
+# 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.
+
+"""Provides a container for DescriptorProtos."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+
+class Error(Exception):
+  pass
+
+
+class DescriptorDatabaseConflictingDefinitionError(Error):
+  """Raised when a proto is added with the same name & different descriptor."""
+
+
+class DescriptorDatabase(object):
+  """A container accepting FileDescriptorProtos and maps DescriptorProtos."""
+
+  def __init__(self):
+    self._file_desc_protos_by_file = {}
+    self._file_desc_protos_by_symbol = {}
+
+  def Add(self, file_desc_proto):
+    """Adds the FileDescriptorProto and its types to this database.
+
+    Args:
+      file_desc_proto: The FileDescriptorProto to add.
+    Raises:
+      DescriptorDatabaseException: if an attempt is made to add a proto
+        with the same name but different definition than an exisiting
+        proto in the database.
+    """
+    proto_name = file_desc_proto.name
+    if proto_name not in self._file_desc_protos_by_file:
+      self._file_desc_protos_by_file[proto_name] = file_desc_proto
+    elif self._file_desc_protos_by_file[proto_name] != file_desc_proto:
+      raise DescriptorDatabaseConflictingDefinitionError(
+          '%s already added, but with different descriptor.' % proto_name)
+
+    # Add the top-level Message, Enum and Extension descriptors to the index.
+    package = file_desc_proto.package
+    for message in file_desc_proto.message_type:
+      self._file_desc_protos_by_symbol.update(
+          (name, file_desc_proto) for name in _ExtractSymbols(message, package))
+    for enum in file_desc_proto.enum_type:
+      self._file_desc_protos_by_symbol[
+          '.'.join((package, enum.name))] = file_desc_proto
+    for extension in file_desc_proto.extension:
+      self._file_desc_protos_by_symbol[
+          '.'.join((package, extension.name))] = file_desc_proto
+
+  def FindFileByName(self, name):
+    """Finds the file descriptor proto by file name.
+
+    Typically the file name is a relative path ending to a .proto file. The
+    proto with the given name will have to have been added to this database
+    using the Add method or else an error will be raised.
+
+    Args:
+      name: The file name to find.
+
+    Returns:
+      The file descriptor proto matching the name.
+
+    Raises:
+      KeyError if no file by the given name was added.
+    """
+
+    return self._file_desc_protos_by_file[name]
+
+  def FindFileContainingSymbol(self, symbol):
+    """Finds the file descriptor proto containing the specified symbol.
+
+    The symbol should be a fully qualified name including the file descriptor's
+    package and any containing messages. Some examples:
+
+    'some.package.name.Message'
+    'some.package.name.Message.NestedEnum'
+
+    The file descriptor proto containing the specified symbol must be added to
+    this database using the Add method or else an error will be raised.
+
+    Args:
+      symbol: The fully qualified symbol name.
+
+    Returns:
+      The file descriptor proto containing the symbol.
+
+    Raises:
+      KeyError if no file contains the specified symbol.
+    """
+
+    return self._file_desc_protos_by_symbol[symbol]
+
+
+def _ExtractSymbols(desc_proto, package):
+  """Pulls out all the symbols from a descriptor proto.
+
+  Args:
+    desc_proto: The proto to extract symbols from.
+    package: The package containing the descriptor type.
+
+  Yields:
+    The fully qualified name found in the descriptor.
+  """
+
+  message_name = '.'.join((package, desc_proto.name))
+  yield message_name
+  for nested_type in desc_proto.nested_type:
+    for symbol in _ExtractSymbols(nested_type, message_name):
+      yield symbol
+  for enum_type in desc_proto.enum_type:
+    yield '.'.join((message_name, enum_type.name))
diff --git a/src/third_party/protobuf-3/python/google/protobuf/descriptor_pb2.py b/src/third_party/protobuf-3/python/google/protobuf/descriptor_pb2.py
new file mode 100644
index 0000000..ca3be5a
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/descriptor_pb2.py
@@ -0,0 +1,1797 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/descriptor.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='google/protobuf/descriptor.proto',
+  package='google.protobuf',
+  syntax='proto2',
+  serialized_pb=_b('\n google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"G\n\x11\x46ileDescriptorSet\x12\x32\n\x04\x66ile\x18\x01 \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xdb\x03\n\x13\x46ileDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07package\x18\x02 \x01(\t\x12\x12\n\ndependency\x18\x03 \x03(\t\x12\x19\n\x11public_dependency\x18\n \x03(\x05\x12\x17\n\x0fweak_dependency\x18\x0b \x03(\x05\x12\x36\n\x0cmessage_type\x18\x04 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x05 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12\x38\n\x07service\x18\x06 \x03(\x0b\x32\'.google.protobuf.ServiceDescriptorProto\x12\x38\n\textension\x18\x07 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12-\n\x07options\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x39\n\x10source_code_info\x18\t \x01(\x0b\x32\x1f.google.protobuf.SourceCodeInfo\x12\x0e\n\x06syntax\x18\x0c \x01(\t\"\xf0\x04\n\x0f\x44\x65scriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05\x66ield\x18\x02 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x38\n\textension\x18\x06 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x35\n\x0bnested_type\x18\x03 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x04 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12H\n\x0f\x65xtension_range\x18\x05 \x03(\x0b\x32/.google.protobuf.DescriptorProto.ExtensionRange\x12\x39\n\noneof_decl\x18\x08 \x03(\x0b\x32%.google.protobuf.OneofDescriptorProto\x12\x30\n\x07options\x18\x07 \x01(\x0b\x32\x1f.google.protobuf.MessageOptions\x12\x46\n\x0ereserved_range\x18\t \x03(\x0b\x32..google.protobuf.DescriptorProto.ReservedRange\x12\x15\n\rreserved_name\x18\n \x03(\t\x1a,\n\x0e\x45xtensionRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x1a+\n\rReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"\xbc\x05\n\x14\x46ieldDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12:\n\x05label\x18\x04 \x01(\x0e\x32+.google.protobuf.FieldDescriptorProto.Label\x12\x38\n\x04type\x18\x05 \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x11\n\ttype_name\x18\x06 \x01(\t\x12\x10\n\x08\x65xtendee\x18\x02 \x01(\t\x12\x15\n\rdefault_value\x18\x07 \x01(\t\x12\x13\n\x0boneof_index\x18\t \x01(\x05\x12\x11\n\tjson_name\x18\n \x01(\t\x12.\n\x07options\x18\x08 \x01(\x0b\x32\x1d.google.protobuf.FieldOptions\"\xb6\x02\n\x04Type\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"C\n\x05Label\x12\x12\n\x0eLABEL_OPTIONAL\x10\x01\x12\x12\n\x0eLABEL_REQUIRED\x10\x02\x12\x12\n\x0eLABEL_REPEATED\x10\x03\"$\n\x14OneofDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x8c\x01\n\x13\x45numDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x03(\x0b\x32).google.protobuf.EnumValueDescriptorProto\x12-\n\x07options\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.EnumOptions\"l\n\x18\x45numValueDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12\x32\n\x07options\x18\x03 \x01(\x0b\x32!.google.protobuf.EnumValueOptions\"\x90\x01\n\x16ServiceDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06method\x18\x02 \x03(\x0b\x32&.google.protobuf.MethodDescriptorProto\x12\x30\n\x07options\x18\x03 \x01(\x0b\x32\x1f.google.protobuf.ServiceOptions\"\xc1\x01\n\x15MethodDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ninput_type\x18\x02 \x01(\t\x12\x13\n\x0boutput_type\x18\x03 \x01(\t\x12/\n\x07options\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.MethodOptions\x12\x1f\n\x10\x63lient_streaming\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10server_streaming\x18\x06 \x01(\x08:\x05\x66\x61lse\"\x87\x05\n\x0b\x46ileOptions\x12\x14\n\x0cjava_package\x18\x01 \x01(\t\x12\x1c\n\x14java_outer_classname\x18\x08 \x01(\t\x12\"\n\x13java_multiple_files\x18\n \x01(\x08:\x05\x66\x61lse\x12,\n\x1djava_generate_equals_and_hash\x18\x14 \x01(\x08:\x05\x66\x61lse\x12%\n\x16java_string_check_utf8\x18\x1b \x01(\x08:\x05\x66\x61lse\x12\x46\n\x0coptimize_for\x18\t \x01(\x0e\x32).google.protobuf.FileOptions.OptimizeMode:\x05SPEED\x12\x12\n\ngo_package\x18\x0b \x01(\t\x12\"\n\x13\x63\x63_generic_services\x18\x10 \x01(\x08:\x05\x66\x61lse\x12$\n\x15java_generic_services\x18\x11 \x01(\x08:\x05\x66\x61lse\x12\"\n\x13py_generic_services\x18\x12 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10\x63\x63_enable_arenas\x18\x1f \x01(\x08:\x05\x66\x61lse\x12\x19\n\x11objc_class_prefix\x18$ \x01(\t\x12\x18\n\x10\x63sharp_namespace\x18% \x01(\t\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\":\n\x0cOptimizeMode\x12\t\n\x05SPEED\x10\x01\x12\r\n\tCODE_SIZE\x10\x02\x12\x10\n\x0cLITE_RUNTIME\x10\x03*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08&\x10\'\"\xe6\x01\n\x0eMessageOptions\x12&\n\x17message_set_wire_format\x18\x01 \x01(\x08:\x05\x66\x61lse\x12.\n\x1fno_standard_descriptor_accessor\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x11\n\tmap_entry\x18\x07 \x01(\x08\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x98\x03\n\x0c\x46ieldOptions\x12:\n\x05\x63type\x18\x01 \x01(\x0e\x32#.google.protobuf.FieldOptions.CType:\x06STRING\x12\x0e\n\x06packed\x18\x02 \x01(\x08\x12?\n\x06jstype\x18\x06 \x01(\x0e\x32$.google.protobuf.FieldOptions.JSType:\tJS_NORMAL\x12\x13\n\x04lazy\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x04weak\x18\n \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"/\n\x05\x43Type\x12\n\n\x06STRING\x10\x00\x12\x08\n\x04\x43ORD\x10\x01\x12\x10\n\x0cSTRING_PIECE\x10\x02\"5\n\x06JSType\x12\r\n\tJS_NORMAL\x10\x00\x12\r\n\tJS_STRING\x10\x01\x12\r\n\tJS_NUMBER\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x8d\x01\n\x0b\x45numOptions\x12\x13\n\x0b\x61llow_alias\x18\x02 \x01(\x08\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"}\n\x10\x45numValueOptions\x12\x19\n\ndeprecated\x18\x01 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"{\n\x0eServiceOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"z\n\rMethodOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x9e\x02\n\x13UninterpretedOption\x12;\n\x04name\x18\x02 \x03(\x0b\x32-.google.protobuf.UninterpretedOption.NamePart\x12\x18\n\x10identifier_value\x18\x03 \x01(\t\x12\x1a\n\x12positive_int_value\x18\x04 \x01(\x04\x12\x1a\n\x12negative_int_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x14\n\x0cstring_value\x18\x07 \x01(\x0c\x12\x17\n\x0f\x61ggregate_value\x18\x08 \x01(\t\x1a\x33\n\x08NamePart\x12\x11\n\tname_part\x18\x01 \x02(\t\x12\x14\n\x0cis_extension\x18\x02 \x02(\x08\"\xd5\x01\n\x0eSourceCodeInfo\x12:\n\x08location\x18\x01 \x03(\x0b\x32(.google.protobuf.SourceCodeInfo.Location\x1a\x86\x01\n\x08Location\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x10\n\x04span\x18\x02 \x03(\x05\x42\x02\x10\x01\x12\x18\n\x10leading_comments\x18\x03 \x01(\t\x12\x19\n\x11trailing_comments\x18\x04 \x01(\t\x12!\n\x19leading_detached_comments\x18\x06 \x03(\t\"\xa7\x01\n\x11GeneratedCodeInfo\x12\x41\n\nannotation\x18\x01 \x03(\x0b\x32-.google.protobuf.GeneratedCodeInfo.Annotation\x1aO\n\nAnnotation\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x13\n\x0bsource_file\x18\x02 \x01(\t\x12\r\n\x05\x62\x65gin\x18\x03 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x04 \x01(\x05\x42X\n\x13\x63om.google.protobufB\x10\x44\x65scriptorProtosH\x01Z\ndescriptor\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection')
+)
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+
+
+_FIELDDESCRIPTORPROTO_TYPE = _descriptor.EnumDescriptor(
+  name='Type',
+  full_name='google.protobuf.FieldDescriptorProto.Type',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_DOUBLE', index=0, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_FLOAT', index=1, number=2,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_INT64', index=2, number=3,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_UINT64', index=3, number=4,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_INT32', index=4, number=5,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_FIXED64', index=5, number=6,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_FIXED32', index=6, number=7,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_BOOL', index=7, number=8,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_STRING', index=8, number=9,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_GROUP', index=9, number=10,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_MESSAGE', index=10, number=11,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_BYTES', index=11, number=12,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_UINT32', index=12, number=13,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_ENUM', index=13, number=14,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_SFIXED32', index=14, number=15,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_SFIXED64', index=15, number=16,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_SINT32', index=16, number=17,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='TYPE_SINT64', index=17, number=18,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=1553,
+  serialized_end=1863,
+)
+_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_TYPE)
+
+_FIELDDESCRIPTORPROTO_LABEL = _descriptor.EnumDescriptor(
+  name='Label',
+  full_name='google.protobuf.FieldDescriptorProto.Label',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='LABEL_OPTIONAL', index=0, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='LABEL_REQUIRED', index=1, number=2,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='LABEL_REPEATED', index=2, number=3,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=1865,
+  serialized_end=1932,
+)
+_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_LABEL)
+
+_FILEOPTIONS_OPTIMIZEMODE = _descriptor.EnumDescriptor(
+  name='OptimizeMode',
+  full_name='google.protobuf.FileOptions.OptimizeMode',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='SPEED', index=0, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='CODE_SIZE', index=1, number=2,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='LITE_RUNTIME', index=2, number=3,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=3141,
+  serialized_end=3199,
+)
+_sym_db.RegisterEnumDescriptor(_FILEOPTIONS_OPTIMIZEMODE)
+
+_FIELDOPTIONS_CTYPE = _descriptor.EnumDescriptor(
+  name='CType',
+  full_name='google.protobuf.FieldOptions.CType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='STRING', index=0, number=0,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='CORD', index=1, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='STRING_PIECE', index=2, number=2,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=3747,
+  serialized_end=3794,
+)
+_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_CTYPE)
+
+_FIELDOPTIONS_JSTYPE = _descriptor.EnumDescriptor(
+  name='JSType',
+  full_name='google.protobuf.FieldOptions.JSType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='JS_NORMAL', index=0, number=0,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='JS_STRING', index=1, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='JS_NUMBER', index=2, number=2,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=3796,
+  serialized_end=3849,
+)
+_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_JSTYPE)
+
+
+_FILEDESCRIPTORSET = _descriptor.Descriptor(
+  name='FileDescriptorSet',
+  full_name='google.protobuf.FileDescriptorSet',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='file', full_name='google.protobuf.FileDescriptorSet.file', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=53,
+  serialized_end=124,
+)
+
+
+_FILEDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='FileDescriptorProto',
+  full_name='google.protobuf.FileDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.FileDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='package', full_name='google.protobuf.FileDescriptorProto.package', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='dependency', full_name='google.protobuf.FileDescriptorProto.dependency', index=2,
+      number=3, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='public_dependency', full_name='google.protobuf.FileDescriptorProto.public_dependency', index=3,
+      number=10, type=5, cpp_type=1, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='weak_dependency', full_name='google.protobuf.FileDescriptorProto.weak_dependency', index=4,
+      number=11, type=5, cpp_type=1, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='message_type', full_name='google.protobuf.FileDescriptorProto.message_type', index=5,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='enum_type', full_name='google.protobuf.FileDescriptorProto.enum_type', index=6,
+      number=5, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='service', full_name='google.protobuf.FileDescriptorProto.service', index=7,
+      number=6, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='extension', full_name='google.protobuf.FileDescriptorProto.extension', index=8,
+      number=7, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.FileDescriptorProto.options', index=9,
+      number=8, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='source_code_info', full_name='google.protobuf.FileDescriptorProto.source_code_info', index=10,
+      number=9, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='syntax', full_name='google.protobuf.FileDescriptorProto.syntax', index=11,
+      number=12, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=127,
+  serialized_end=602,
+)
+
+
+_DESCRIPTORPROTO_EXTENSIONRANGE = _descriptor.Descriptor(
+  name='ExtensionRange',
+  full_name='google.protobuf.DescriptorProto.ExtensionRange',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='start', full_name='google.protobuf.DescriptorProto.ExtensionRange.start', index=0,
+      number=1, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='end', full_name='google.protobuf.DescriptorProto.ExtensionRange.end', index=1,
+      number=2, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1140,
+  serialized_end=1184,
+)
+
+_DESCRIPTORPROTO_RESERVEDRANGE = _descriptor.Descriptor(
+  name='ReservedRange',
+  full_name='google.protobuf.DescriptorProto.ReservedRange',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='start', full_name='google.protobuf.DescriptorProto.ReservedRange.start', index=0,
+      number=1, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='end', full_name='google.protobuf.DescriptorProto.ReservedRange.end', index=1,
+      number=2, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1186,
+  serialized_end=1229,
+)
+
+_DESCRIPTORPROTO = _descriptor.Descriptor(
+  name='DescriptorProto',
+  full_name='google.protobuf.DescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.DescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='field', full_name='google.protobuf.DescriptorProto.field', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='extension', full_name='google.protobuf.DescriptorProto.extension', index=2,
+      number=6, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='nested_type', full_name='google.protobuf.DescriptorProto.nested_type', index=3,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='enum_type', full_name='google.protobuf.DescriptorProto.enum_type', index=4,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='extension_range', full_name='google.protobuf.DescriptorProto.extension_range', index=5,
+      number=5, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='oneof_decl', full_name='google.protobuf.DescriptorProto.oneof_decl', index=6,
+      number=8, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.DescriptorProto.options', index=7,
+      number=7, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='reserved_range', full_name='google.protobuf.DescriptorProto.reserved_range', index=8,
+      number=9, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='reserved_name', full_name='google.protobuf.DescriptorProto.reserved_name', index=9,
+      number=10, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[_DESCRIPTORPROTO_EXTENSIONRANGE, _DESCRIPTORPROTO_RESERVEDRANGE, ],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=605,
+  serialized_end=1229,
+)
+
+
+_FIELDDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='FieldDescriptorProto',
+  full_name='google.protobuf.FieldDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.FieldDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='number', full_name='google.protobuf.FieldDescriptorProto.number', index=1,
+      number=3, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='label', full_name='google.protobuf.FieldDescriptorProto.label', index=2,
+      number=4, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=1,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='type', full_name='google.protobuf.FieldDescriptorProto.type', index=3,
+      number=5, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=1,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='type_name', full_name='google.protobuf.FieldDescriptorProto.type_name', index=4,
+      number=6, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='extendee', full_name='google.protobuf.FieldDescriptorProto.extendee', index=5,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='default_value', full_name='google.protobuf.FieldDescriptorProto.default_value', index=6,
+      number=7, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='oneof_index', full_name='google.protobuf.FieldDescriptorProto.oneof_index', index=7,
+      number=9, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='json_name', full_name='google.protobuf.FieldDescriptorProto.json_name', index=8,
+      number=10, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.FieldDescriptorProto.options', index=9,
+      number=8, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+    _FIELDDESCRIPTORPROTO_TYPE,
+    _FIELDDESCRIPTORPROTO_LABEL,
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1232,
+  serialized_end=1932,
+)
+
+
+_ONEOFDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='OneofDescriptorProto',
+  full_name='google.protobuf.OneofDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.OneofDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1934,
+  serialized_end=1970,
+)
+
+
+_ENUMDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='EnumDescriptorProto',
+  full_name='google.protobuf.EnumDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.EnumDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='value', full_name='google.protobuf.EnumDescriptorProto.value', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.EnumDescriptorProto.options', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1973,
+  serialized_end=2113,
+)
+
+
+_ENUMVALUEDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='EnumValueDescriptorProto',
+  full_name='google.protobuf.EnumValueDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.EnumValueDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='number', full_name='google.protobuf.EnumValueDescriptorProto.number', index=1,
+      number=2, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.EnumValueDescriptorProto.options', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2115,
+  serialized_end=2223,
+)
+
+
+_SERVICEDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='ServiceDescriptorProto',
+  full_name='google.protobuf.ServiceDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.ServiceDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='method', full_name='google.protobuf.ServiceDescriptorProto.method', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.ServiceDescriptorProto.options', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2226,
+  serialized_end=2370,
+)
+
+
+_METHODDESCRIPTORPROTO = _descriptor.Descriptor(
+  name='MethodDescriptorProto',
+  full_name='google.protobuf.MethodDescriptorProto',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.MethodDescriptorProto.name', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='input_type', full_name='google.protobuf.MethodDescriptorProto.input_type', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='output_type', full_name='google.protobuf.MethodDescriptorProto.output_type', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='options', full_name='google.protobuf.MethodDescriptorProto.options', index=3,
+      number=4, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='client_streaming', full_name='google.protobuf.MethodDescriptorProto.client_streaming', index=4,
+      number=5, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='server_streaming', full_name='google.protobuf.MethodDescriptorProto.server_streaming', index=5,
+      number=6, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2373,
+  serialized_end=2566,
+)
+
+
+_FILEOPTIONS = _descriptor.Descriptor(
+  name='FileOptions',
+  full_name='google.protobuf.FileOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='java_package', full_name='google.protobuf.FileOptions.java_package', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='java_outer_classname', full_name='google.protobuf.FileOptions.java_outer_classname', index=1,
+      number=8, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='java_multiple_files', full_name='google.protobuf.FileOptions.java_multiple_files', index=2,
+      number=10, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='java_generate_equals_and_hash', full_name='google.protobuf.FileOptions.java_generate_equals_and_hash', index=3,
+      number=20, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='java_string_check_utf8', full_name='google.protobuf.FileOptions.java_string_check_utf8', index=4,
+      number=27, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='optimize_for', full_name='google.protobuf.FileOptions.optimize_for', index=5,
+      number=9, type=14, cpp_type=8, label=1,
+      has_default_value=True, default_value=1,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='go_package', full_name='google.protobuf.FileOptions.go_package', index=6,
+      number=11, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='cc_generic_services', full_name='google.protobuf.FileOptions.cc_generic_services', index=7,
+      number=16, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='java_generic_services', full_name='google.protobuf.FileOptions.java_generic_services', index=8,
+      number=17, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='py_generic_services', full_name='google.protobuf.FileOptions.py_generic_services', index=9,
+      number=18, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.FileOptions.deprecated', index=10,
+      number=23, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='cc_enable_arenas', full_name='google.protobuf.FileOptions.cc_enable_arenas', index=11,
+      number=31, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='objc_class_prefix', full_name='google.protobuf.FileOptions.objc_class_prefix', index=12,
+      number=36, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='csharp_namespace', full_name='google.protobuf.FileOptions.csharp_namespace', index=13,
+      number=37, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.FileOptions.uninterpreted_option', index=14,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+    _FILEOPTIONS_OPTIMIZEMODE,
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=2569,
+  serialized_end=3216,
+)
+
+
+_MESSAGEOPTIONS = _descriptor.Descriptor(
+  name='MessageOptions',
+  full_name='google.protobuf.MessageOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='message_set_wire_format', full_name='google.protobuf.MessageOptions.message_set_wire_format', index=0,
+      number=1, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='no_standard_descriptor_accessor', full_name='google.protobuf.MessageOptions.no_standard_descriptor_accessor', index=1,
+      number=2, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.MessageOptions.deprecated', index=2,
+      number=3, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='map_entry', full_name='google.protobuf.MessageOptions.map_entry', index=3,
+      number=7, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.MessageOptions.uninterpreted_option', index=4,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=3219,
+  serialized_end=3449,
+)
+
+
+_FIELDOPTIONS = _descriptor.Descriptor(
+  name='FieldOptions',
+  full_name='google.protobuf.FieldOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='ctype', full_name='google.protobuf.FieldOptions.ctype', index=0,
+      number=1, type=14, cpp_type=8, label=1,
+      has_default_value=True, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='packed', full_name='google.protobuf.FieldOptions.packed', index=1,
+      number=2, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='jstype', full_name='google.protobuf.FieldOptions.jstype', index=2,
+      number=6, type=14, cpp_type=8, label=1,
+      has_default_value=True, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='lazy', full_name='google.protobuf.FieldOptions.lazy', index=3,
+      number=5, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.FieldOptions.deprecated', index=4,
+      number=3, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='weak', full_name='google.protobuf.FieldOptions.weak', index=5,
+      number=10, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.FieldOptions.uninterpreted_option', index=6,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+    _FIELDOPTIONS_CTYPE,
+    _FIELDOPTIONS_JSTYPE,
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=3452,
+  serialized_end=3860,
+)
+
+
+_ENUMOPTIONS = _descriptor.Descriptor(
+  name='EnumOptions',
+  full_name='google.protobuf.EnumOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='allow_alias', full_name='google.protobuf.EnumOptions.allow_alias', index=0,
+      number=2, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.EnumOptions.deprecated', index=1,
+      number=3, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.EnumOptions.uninterpreted_option', index=2,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=3863,
+  serialized_end=4004,
+)
+
+
+_ENUMVALUEOPTIONS = _descriptor.Descriptor(
+  name='EnumValueOptions',
+  full_name='google.protobuf.EnumValueOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.EnumValueOptions.deprecated', index=0,
+      number=1, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.EnumValueOptions.uninterpreted_option', index=1,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=4006,
+  serialized_end=4131,
+)
+
+
+_SERVICEOPTIONS = _descriptor.Descriptor(
+  name='ServiceOptions',
+  full_name='google.protobuf.ServiceOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.ServiceOptions.deprecated', index=0,
+      number=33, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.ServiceOptions.uninterpreted_option', index=1,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=4133,
+  serialized_end=4256,
+)
+
+
+_METHODOPTIONS = _descriptor.Descriptor(
+  name='MethodOptions',
+  full_name='google.protobuf.MethodOptions',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='deprecated', full_name='google.protobuf.MethodOptions.deprecated', index=0,
+      number=33, type=8, cpp_type=7, label=1,
+      has_default_value=True, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='uninterpreted_option', full_name='google.protobuf.MethodOptions.uninterpreted_option', index=1,
+      number=999, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=True,
+  syntax='proto2',
+  extension_ranges=[(1000, 536870912), ],
+  oneofs=[
+  ],
+  serialized_start=4258,
+  serialized_end=4380,
+)
+
+
+_UNINTERPRETEDOPTION_NAMEPART = _descriptor.Descriptor(
+  name='NamePart',
+  full_name='google.protobuf.UninterpretedOption.NamePart',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name_part', full_name='google.protobuf.UninterpretedOption.NamePart.name_part', index=0,
+      number=1, type=9, cpp_type=9, label=2,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='is_extension', full_name='google.protobuf.UninterpretedOption.NamePart.is_extension', index=1,
+      number=2, type=8, cpp_type=7, label=2,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4618,
+  serialized_end=4669,
+)
+
+_UNINTERPRETEDOPTION = _descriptor.Descriptor(
+  name='UninterpretedOption',
+  full_name='google.protobuf.UninterpretedOption',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='name', full_name='google.protobuf.UninterpretedOption.name', index=0,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='identifier_value', full_name='google.protobuf.UninterpretedOption.identifier_value', index=1,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='positive_int_value', full_name='google.protobuf.UninterpretedOption.positive_int_value', index=2,
+      number=4, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='negative_int_value', full_name='google.protobuf.UninterpretedOption.negative_int_value', index=3,
+      number=5, type=3, cpp_type=2, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='double_value', full_name='google.protobuf.UninterpretedOption.double_value', index=4,
+      number=6, type=1, cpp_type=5, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='string_value', full_name='google.protobuf.UninterpretedOption.string_value', index=5,
+      number=7, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b(""),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='aggregate_value', full_name='google.protobuf.UninterpretedOption.aggregate_value', index=6,
+      number=8, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[_UNINTERPRETEDOPTION_NAMEPART, ],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4383,
+  serialized_end=4669,
+)
+
+
+_SOURCECODEINFO_LOCATION = _descriptor.Descriptor(
+  name='Location',
+  full_name='google.protobuf.SourceCodeInfo.Location',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='path', full_name='google.protobuf.SourceCodeInfo.Location.path', index=0,
+      number=1, type=5, cpp_type=1, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='span', full_name='google.protobuf.SourceCodeInfo.Location.span', index=1,
+      number=2, type=5, cpp_type=1, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='leading_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_comments', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='trailing_comments', full_name='google.protobuf.SourceCodeInfo.Location.trailing_comments', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='leading_detached_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_detached_comments', index=4,
+      number=6, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4751,
+  serialized_end=4885,
+)
+
+_SOURCECODEINFO = _descriptor.Descriptor(
+  name='SourceCodeInfo',
+  full_name='google.protobuf.SourceCodeInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='location', full_name='google.protobuf.SourceCodeInfo.location', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[_SOURCECODEINFO_LOCATION, ],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4672,
+  serialized_end=4885,
+)
+
+
+_GENERATEDCODEINFO_ANNOTATION = _descriptor.Descriptor(
+  name='Annotation',
+  full_name='google.protobuf.GeneratedCodeInfo.Annotation',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='path', full_name='google.protobuf.GeneratedCodeInfo.Annotation.path', index=0,
+      number=1, type=5, cpp_type=1, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='source_file', full_name='google.protobuf.GeneratedCodeInfo.Annotation.source_file', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='begin', full_name='google.protobuf.GeneratedCodeInfo.Annotation.begin', index=2,
+      number=3, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='end', full_name='google.protobuf.GeneratedCodeInfo.Annotation.end', index=3,
+      number=4, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4976,
+  serialized_end=5055,
+)
+
+_GENERATEDCODEINFO = _descriptor.Descriptor(
+  name='GeneratedCodeInfo',
+  full_name='google.protobuf.GeneratedCodeInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='annotation', full_name='google.protobuf.GeneratedCodeInfo.annotation', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[_GENERATEDCODEINFO_ANNOTATION, ],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  syntax='proto2',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=4888,
+  serialized_end=5055,
+)
+
+_FILEDESCRIPTORSET.fields_by_name['file'].message_type = _FILEDESCRIPTORPROTO
+_FILEDESCRIPTORPROTO.fields_by_name['message_type'].message_type = _DESCRIPTORPROTO
+_FILEDESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO
+_FILEDESCRIPTORPROTO.fields_by_name['service'].message_type = _SERVICEDESCRIPTORPROTO
+_FILEDESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO
+_FILEDESCRIPTORPROTO.fields_by_name['options'].message_type = _FILEOPTIONS
+_FILEDESCRIPTORPROTO.fields_by_name['source_code_info'].message_type = _SOURCECODEINFO
+_DESCRIPTORPROTO_EXTENSIONRANGE.containing_type = _DESCRIPTORPROTO
+_DESCRIPTORPROTO_RESERVEDRANGE.containing_type = _DESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['field'].message_type = _FIELDDESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['nested_type'].message_type = _DESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['extension_range'].message_type = _DESCRIPTORPROTO_EXTENSIONRANGE
+_DESCRIPTORPROTO.fields_by_name['oneof_decl'].message_type = _ONEOFDESCRIPTORPROTO
+_DESCRIPTORPROTO.fields_by_name['options'].message_type = _MESSAGEOPTIONS
+_DESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _DESCRIPTORPROTO_RESERVEDRANGE
+_FIELDDESCRIPTORPROTO.fields_by_name['label'].enum_type = _FIELDDESCRIPTORPROTO_LABEL
+_FIELDDESCRIPTORPROTO.fields_by_name['type'].enum_type = _FIELDDESCRIPTORPROTO_TYPE
+_FIELDDESCRIPTORPROTO.fields_by_name['options'].message_type = _FIELDOPTIONS
+_FIELDDESCRIPTORPROTO_TYPE.containing_type = _FIELDDESCRIPTORPROTO
+_FIELDDESCRIPTORPROTO_LABEL.containing_type = _FIELDDESCRIPTORPROTO
+_ENUMDESCRIPTORPROTO.fields_by_name['value'].message_type = _ENUMVALUEDESCRIPTORPROTO
+_ENUMDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMOPTIONS
+_ENUMVALUEDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMVALUEOPTIONS
+_SERVICEDESCRIPTORPROTO.fields_by_name['method'].message_type = _METHODDESCRIPTORPROTO
+_SERVICEDESCRIPTORPROTO.fields_by_name['options'].message_type = _SERVICEOPTIONS
+_METHODDESCRIPTORPROTO.fields_by_name['options'].message_type = _METHODOPTIONS
+_FILEOPTIONS.fields_by_name['optimize_for'].enum_type = _FILEOPTIONS_OPTIMIZEMODE
+_FILEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_FILEOPTIONS_OPTIMIZEMODE.containing_type = _FILEOPTIONS
+_MESSAGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_FIELDOPTIONS.fields_by_name['ctype'].enum_type = _FIELDOPTIONS_CTYPE
+_FIELDOPTIONS.fields_by_name['jstype'].enum_type = _FIELDOPTIONS_JSTYPE
+_FIELDOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_FIELDOPTIONS_CTYPE.containing_type = _FIELDOPTIONS
+_FIELDOPTIONS_JSTYPE.containing_type = _FIELDOPTIONS
+_ENUMOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_ENUMVALUEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_SERVICEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_METHODOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION
+_UNINTERPRETEDOPTION_NAMEPART.containing_type = _UNINTERPRETEDOPTION
+_UNINTERPRETEDOPTION.fields_by_name['name'].message_type = _UNINTERPRETEDOPTION_NAMEPART
+_SOURCECODEINFO_LOCATION.containing_type = _SOURCECODEINFO
+_SOURCECODEINFO.fields_by_name['location'].message_type = _SOURCECODEINFO_LOCATION
+_GENERATEDCODEINFO_ANNOTATION.containing_type = _GENERATEDCODEINFO
+_GENERATEDCODEINFO.fields_by_name['annotation'].message_type = _GENERATEDCODEINFO_ANNOTATION
+DESCRIPTOR.message_types_by_name['FileDescriptorSet'] = _FILEDESCRIPTORSET
+DESCRIPTOR.message_types_by_name['FileDescriptorProto'] = _FILEDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['DescriptorProto'] = _DESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['FieldDescriptorProto'] = _FIELDDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['OneofDescriptorProto'] = _ONEOFDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['EnumDescriptorProto'] = _ENUMDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['EnumValueDescriptorProto'] = _ENUMVALUEDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['ServiceDescriptorProto'] = _SERVICEDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['MethodDescriptorProto'] = _METHODDESCRIPTORPROTO
+DESCRIPTOR.message_types_by_name['FileOptions'] = _FILEOPTIONS
+DESCRIPTOR.message_types_by_name['MessageOptions'] = _MESSAGEOPTIONS
+DESCRIPTOR.message_types_by_name['FieldOptions'] = _FIELDOPTIONS
+DESCRIPTOR.message_types_by_name['EnumOptions'] = _ENUMOPTIONS
+DESCRIPTOR.message_types_by_name['EnumValueOptions'] = _ENUMVALUEOPTIONS
+DESCRIPTOR.message_types_by_name['ServiceOptions'] = _SERVICEOPTIONS
+DESCRIPTOR.message_types_by_name['MethodOptions'] = _METHODOPTIONS
+DESCRIPTOR.message_types_by_name['UninterpretedOption'] = _UNINTERPRETEDOPTION
+DESCRIPTOR.message_types_by_name['SourceCodeInfo'] = _SOURCECODEINFO
+DESCRIPTOR.message_types_by_name['GeneratedCodeInfo'] = _GENERATEDCODEINFO
+
+FileDescriptorSet = _reflection.GeneratedProtocolMessageType('FileDescriptorSet', (_message.Message,), dict(
+  DESCRIPTOR = _FILEDESCRIPTORSET,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
+  ))
+_sym_db.RegisterMessage(FileDescriptorSet)
+
+FileDescriptorProto = _reflection.GeneratedProtocolMessageType('FileDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _FILEDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
+  ))
+_sym_db.RegisterMessage(FileDescriptorProto)
+
+DescriptorProto = _reflection.GeneratedProtocolMessageType('DescriptorProto', (_message.Message,), dict(
+
+  ExtensionRange = _reflection.GeneratedProtocolMessageType('ExtensionRange', (_message.Message,), dict(
+    DESCRIPTOR = _DESCRIPTORPROTO_EXTENSIONRANGE,
+    __module__ = 'google.protobuf.descriptor_pb2'
+    # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
+    ))
+  ,
+
+  ReservedRange = _reflection.GeneratedProtocolMessageType('ReservedRange', (_message.Message,), dict(
+    DESCRIPTOR = _DESCRIPTORPROTO_RESERVEDRANGE,
+    __module__ = 'google.protobuf.descriptor_pb2'
+    # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange)
+    ))
+  ,
+  DESCRIPTOR = _DESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
+  ))
+_sym_db.RegisterMessage(DescriptorProto)
+_sym_db.RegisterMessage(DescriptorProto.ExtensionRange)
+_sym_db.RegisterMessage(DescriptorProto.ReservedRange)
+
+FieldDescriptorProto = _reflection.GeneratedProtocolMessageType('FieldDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _FIELDDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
+  ))
+_sym_db.RegisterMessage(FieldDescriptorProto)
+
+OneofDescriptorProto = _reflection.GeneratedProtocolMessageType('OneofDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _ONEOFDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto)
+  ))
+_sym_db.RegisterMessage(OneofDescriptorProto)
+
+EnumDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _ENUMDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
+  ))
+_sym_db.RegisterMessage(EnumDescriptorProto)
+
+EnumValueDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumValueDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _ENUMVALUEDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
+  ))
+_sym_db.RegisterMessage(EnumValueDescriptorProto)
+
+ServiceDescriptorProto = _reflection.GeneratedProtocolMessageType('ServiceDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _SERVICEDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
+  ))
+_sym_db.RegisterMessage(ServiceDescriptorProto)
+
+MethodDescriptorProto = _reflection.GeneratedProtocolMessageType('MethodDescriptorProto', (_message.Message,), dict(
+  DESCRIPTOR = _METHODDESCRIPTORPROTO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
+  ))
+_sym_db.RegisterMessage(MethodDescriptorProto)
+
+FileOptions = _reflection.GeneratedProtocolMessageType('FileOptions', (_message.Message,), dict(
+  DESCRIPTOR = _FILEOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
+  ))
+_sym_db.RegisterMessage(FileOptions)
+
+MessageOptions = _reflection.GeneratedProtocolMessageType('MessageOptions', (_message.Message,), dict(
+  DESCRIPTOR = _MESSAGEOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
+  ))
+_sym_db.RegisterMessage(MessageOptions)
+
+FieldOptions = _reflection.GeneratedProtocolMessageType('FieldOptions', (_message.Message,), dict(
+  DESCRIPTOR = _FIELDOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
+  ))
+_sym_db.RegisterMessage(FieldOptions)
+
+EnumOptions = _reflection.GeneratedProtocolMessageType('EnumOptions', (_message.Message,), dict(
+  DESCRIPTOR = _ENUMOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
+  ))
+_sym_db.RegisterMessage(EnumOptions)
+
+EnumValueOptions = _reflection.GeneratedProtocolMessageType('EnumValueOptions', (_message.Message,), dict(
+  DESCRIPTOR = _ENUMVALUEOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
+  ))
+_sym_db.RegisterMessage(EnumValueOptions)
+
+ServiceOptions = _reflection.GeneratedProtocolMessageType('ServiceOptions', (_message.Message,), dict(
+  DESCRIPTOR = _SERVICEOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
+  ))
+_sym_db.RegisterMessage(ServiceOptions)
+
+MethodOptions = _reflection.GeneratedProtocolMessageType('MethodOptions', (_message.Message,), dict(
+  DESCRIPTOR = _METHODOPTIONS,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
+  ))
+_sym_db.RegisterMessage(MethodOptions)
+
+UninterpretedOption = _reflection.GeneratedProtocolMessageType('UninterpretedOption', (_message.Message,), dict(
+
+  NamePart = _reflection.GeneratedProtocolMessageType('NamePart', (_message.Message,), dict(
+    DESCRIPTOR = _UNINTERPRETEDOPTION_NAMEPART,
+    __module__ = 'google.protobuf.descriptor_pb2'
+    # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
+    ))
+  ,
+  DESCRIPTOR = _UNINTERPRETEDOPTION,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
+  ))
+_sym_db.RegisterMessage(UninterpretedOption)
+_sym_db.RegisterMessage(UninterpretedOption.NamePart)
+
+SourceCodeInfo = _reflection.GeneratedProtocolMessageType('SourceCodeInfo', (_message.Message,), dict(
+
+  Location = _reflection.GeneratedProtocolMessageType('Location', (_message.Message,), dict(
+    DESCRIPTOR = _SOURCECODEINFO_LOCATION,
+    __module__ = 'google.protobuf.descriptor_pb2'
+    # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
+    ))
+  ,
+  DESCRIPTOR = _SOURCECODEINFO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
+  ))
+_sym_db.RegisterMessage(SourceCodeInfo)
+_sym_db.RegisterMessage(SourceCodeInfo.Location)
+
+GeneratedCodeInfo = _reflection.GeneratedProtocolMessageType('GeneratedCodeInfo', (_message.Message,), dict(
+
+  Annotation = _reflection.GeneratedProtocolMessageType('Annotation', (_message.Message,), dict(
+    DESCRIPTOR = _GENERATEDCODEINFO_ANNOTATION,
+    __module__ = 'google.protobuf.descriptor_pb2'
+    # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation)
+    ))
+  ,
+  DESCRIPTOR = _GENERATEDCODEINFO,
+  __module__ = 'google.protobuf.descriptor_pb2'
+  # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo)
+  ))
+_sym_db.RegisterMessage(GeneratedCodeInfo)
+_sym_db.RegisterMessage(GeneratedCodeInfo.Annotation)
+
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/descriptor_pool.py b/src/third_party/protobuf-3/python/google/protobuf/descriptor_pool.py
new file mode 100644
index 0000000..20a3370
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/descriptor_pool.py
@@ -0,0 +1,751 @@
+# 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.
+
+"""Provides DescriptorPool to use as a container for proto2 descriptors.
+
+The DescriptorPool is used in conjection with a DescriptorDatabase to maintain
+a collection of protocol buffer descriptors for use when dynamically creating
+message types at runtime.
+
+For most applications protocol buffers should be used via modules generated by
+the protocol buffer compiler tool. This should only be used when the type of
+protocol buffers used in an application or library cannot be predetermined.
+
+Below is a straightforward example on how to use this class:
+
+  pool = DescriptorPool()
+  file_descriptor_protos = [ ... ]
+  for file_descriptor_proto in file_descriptor_protos:
+    pool.Add(file_descriptor_proto)
+  my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType')
+
+The message descriptor can be used in conjunction with the message_factory
+module in order to create a protocol buffer class that can be encoded and
+decoded.
+
+If you want to get a Python class for the specified proto, use the
+helper functions inside google.protobuf.message_factory
+directly instead of this class.
+"""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+from google.protobuf import text_encoding
+
+
+_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS
+
+
+def _NormalizeFullyQualifiedName(name):
+  """Remove leading period from fully-qualified type name.
+
+  Due to b/13860351 in descriptor_database.py, types in the root namespace are
+  generated with a leading period. This function removes that prefix.
+
+  Args:
+    name: A str, the fully-qualified symbol name.
+
+  Returns:
+    A str, the normalized fully-qualified symbol name.
+  """
+  return name.lstrip('.')
+
+
+class DescriptorPool(object):
+  """A collection of protobufs dynamically constructed by descriptor protos."""
+
+  if _USE_C_DESCRIPTORS:
+
+    def __new__(cls, descriptor_db=None):
+      # pylint: disable=protected-access
+      return descriptor._message.DescriptorPool(descriptor_db)
+
+  def __init__(self, descriptor_db=None):
+    """Initializes a Pool of proto buffs.
+
+    The descriptor_db argument to the constructor is provided to allow
+    specialized file descriptor proto lookup code to be triggered on demand. An
+    example would be an implementation which will read and compile a file
+    specified in a call to FindFileByName() and not require the call to Add()
+    at all. Results from this database will be cached internally here as well.
+
+    Args:
+      descriptor_db: A secondary source of file descriptors.
+    """
+
+    self._internal_db = descriptor_database.DescriptorDatabase()
+    self._descriptor_db = descriptor_db
+    self._descriptors = {}
+    self._enum_descriptors = {}
+    self._file_descriptors = {}
+
+  def Add(self, file_desc_proto):
+    """Adds the FileDescriptorProto and its types to this pool.
+
+    Args:
+      file_desc_proto: The FileDescriptorProto to add.
+    """
+
+    self._internal_db.Add(file_desc_proto)
+
+  def AddSerializedFile(self, serialized_file_desc_proto):
+    """Adds the FileDescriptorProto and its types to this pool.
+
+    Args:
+      serialized_file_desc_proto: A bytes string, serialization of the
+        FileDescriptorProto to add.
+    """
+
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf import descriptor_pb2
+    file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
+        serialized_file_desc_proto)
+    self.Add(file_desc_proto)
+
+  def AddDescriptor(self, desc):
+    """Adds a Descriptor to the pool, non-recursively.
+
+    If the Descriptor contains nested messages or enums, the caller must
+    explicitly register them. This method also registers the FileDescriptor
+    associated with the message.
+
+    Args:
+      desc: A Descriptor.
+    """
+    if not isinstance(desc, descriptor.Descriptor):
+      raise TypeError('Expected instance of descriptor.Descriptor.')
+
+    self._descriptors[desc.full_name] = desc
+    self.AddFileDescriptor(desc.file)
+
+  def AddEnumDescriptor(self, enum_desc):
+    """Adds an EnumDescriptor to the pool.
+
+    This method also registers the FileDescriptor associated with the message.
+
+    Args:
+      enum_desc: An EnumDescriptor.
+    """
+
+    if not isinstance(enum_desc, descriptor.EnumDescriptor):
+      raise TypeError('Expected instance of descriptor.EnumDescriptor.')
+
+    self._enum_descriptors[enum_desc.full_name] = enum_desc
+    self.AddFileDescriptor(enum_desc.file)
+
+  def AddFileDescriptor(self, file_desc):
+    """Adds a FileDescriptor to the pool, non-recursively.
+
+    If the FileDescriptor contains messages or enums, the caller must explicitly
+    register them.
+
+    Args:
+      file_desc: A FileDescriptor.
+    """
+
+    if not isinstance(file_desc, descriptor.FileDescriptor):
+      raise TypeError('Expected instance of descriptor.FileDescriptor.')
+    self._file_descriptors[file_desc.name] = file_desc
+
+  def FindFileByName(self, file_name):
+    """Gets a FileDescriptor by file name.
+
+    Args:
+      file_name: The path to the file to get a descriptor for.
+
+    Returns:
+      A FileDescriptor for the named file.
+
+    Raises:
+      KeyError: if the file can not be found in the pool.
+    """
+
+    try:
+      return self._file_descriptors[file_name]
+    except KeyError:
+      pass
+
+    try:
+      file_proto = self._internal_db.FindFileByName(file_name)
+    except KeyError as error:
+      if self._descriptor_db:
+        file_proto = self._descriptor_db.FindFileByName(file_name)
+      else:
+        raise error
+    if not file_proto:
+      raise KeyError('Cannot find a file named %s' % file_name)
+    return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+  def FindFileContainingSymbol(self, symbol):
+    """Gets the FileDescriptor for the file containing the specified symbol.
+
+    Args:
+      symbol: The name of the symbol to search for.
+
+    Returns:
+      A FileDescriptor that contains the specified symbol.
+
+    Raises:
+      KeyError: if the file can not be found in the pool.
+    """
+
+    symbol = _NormalizeFullyQualifiedName(symbol)
+    try:
+      return self._descriptors[symbol].file
+    except KeyError:
+      pass
+
+    try:
+      return self._enum_descriptors[symbol].file
+    except KeyError:
+      pass
+
+    try:
+      file_proto = self._internal_db.FindFileContainingSymbol(symbol)
+    except KeyError as error:
+      if self._descriptor_db:
+        file_proto = self._descriptor_db.FindFileContainingSymbol(symbol)
+      else:
+        raise error
+    if not file_proto:
+      raise KeyError('Cannot find a file containing %s' % symbol)
+    return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+  def FindMessageTypeByName(self, full_name):
+    """Loads the named descriptor from the pool.
+
+    Args:
+      full_name: The full name of the descriptor to load.
+
+    Returns:
+      The descriptor for the named type.
+    """
+
+    full_name = _NormalizeFullyQualifiedName(full_name)
+    if full_name not in self._descriptors:
+      self.FindFileContainingSymbol(full_name)
+    return self._descriptors[full_name]
+
+  def FindEnumTypeByName(self, full_name):
+    """Loads the named enum descriptor from the pool.
+
+    Args:
+      full_name: The full name of the enum descriptor to load.
+
+    Returns:
+      The enum descriptor for the named type.
+    """
+
+    full_name = _NormalizeFullyQualifiedName(full_name)
+    if full_name not in self._enum_descriptors:
+      self.FindFileContainingSymbol(full_name)
+    return self._enum_descriptors[full_name]
+
+  def FindFieldByName(self, full_name):
+    """Loads the named field descriptor from the pool.
+
+    Args:
+      full_name: The full name of the field descriptor to load.
+
+    Returns:
+      The field descriptor for the named field.
+    """
+    full_name = _NormalizeFullyQualifiedName(full_name)
+    message_name, _, field_name = full_name.rpartition('.')
+    message_descriptor = self.FindMessageTypeByName(message_name)
+    return message_descriptor.fields_by_name[field_name]
+
+  def FindExtensionByName(self, full_name):
+    """Loads the named extension descriptor from the pool.
+
+    Args:
+      full_name: The full name of the extension descriptor to load.
+
+    Returns:
+      A FieldDescriptor, describing the named extension.
+    """
+    full_name = _NormalizeFullyQualifiedName(full_name)
+    message_name, _, extension_name = full_name.rpartition('.')
+    try:
+      # Most extensions are nested inside a message.
+      scope = self.FindMessageTypeByName(message_name)
+    except KeyError:
+      # Some extensions are defined at file scope.
+      scope = self.FindFileContainingSymbol(full_name)
+    return scope.extensions_by_name[extension_name]
+
+  def _ConvertFileProtoToFileDescriptor(self, file_proto):
+    """Creates a FileDescriptor from a proto or returns a cached copy.
+
+    This method also has the side effect of loading all the symbols found in
+    the file into the appropriate dictionaries in the pool.
+
+    Args:
+      file_proto: The proto to convert.
+
+    Returns:
+      A FileDescriptor matching the passed in proto.
+    """
+
+    if file_proto.name not in self._file_descriptors:
+      built_deps = list(self._GetDeps(file_proto.dependency))
+      direct_deps = [self.FindFileByName(n) for n in file_proto.dependency]
+      public_deps = [direct_deps[i] for i in file_proto.public_dependency]
+
+      file_descriptor = descriptor.FileDescriptor(
+          pool=self,
+          name=file_proto.name,
+          package=file_proto.package,
+          syntax=file_proto.syntax,
+          options=file_proto.options,
+          serialized_pb=file_proto.SerializeToString(),
+          dependencies=direct_deps,
+          public_dependencies=public_deps)
+      if _USE_C_DESCRIPTORS:
+        # When using C++ descriptors, all objects defined in the file were added
+        # to the C++ database when the FileDescriptor was built above.
+        # Just add them to this descriptor pool.
+        def _AddMessageDescriptor(message_desc):
+          self._descriptors[message_desc.full_name] = message_desc
+          for nested in message_desc.nested_types:
+            _AddMessageDescriptor(nested)
+          for enum_type in message_desc.enum_types:
+            _AddEnumDescriptor(enum_type)
+        def _AddEnumDescriptor(enum_desc):
+          self._enum_descriptors[enum_desc.full_name] = enum_desc
+        for message_type in file_descriptor.message_types_by_name.values():
+          _AddMessageDescriptor(message_type)
+        for enum_type in file_descriptor.enum_types_by_name.values():
+          _AddEnumDescriptor(enum_type)
+      else:
+        scope = {}
+
+        # This loop extracts all the message and enum types from all the
+        # dependencies of the file_proto. This is necessary to create the
+        # scope of available message types when defining the passed in
+        # file proto.
+        for dependency in built_deps:
+          scope.update(self._ExtractSymbols(
+              dependency.message_types_by_name.values()))
+          scope.update((_PrefixWithDot(enum.full_name), enum)
+                       for enum in dependency.enum_types_by_name.values())
+
+        for message_type in file_proto.message_type:
+          message_desc = self._ConvertMessageDescriptor(
+              message_type, file_proto.package, file_descriptor, scope,
+              file_proto.syntax)
+          file_descriptor.message_types_by_name[message_desc.name] = (
+              message_desc)
+
+        for enum_type in file_proto.enum_type:
+          file_descriptor.enum_types_by_name[enum_type.name] = (
+              self._ConvertEnumDescriptor(enum_type, file_proto.package,
+                                          file_descriptor, None, scope))
+
+        for index, extension_proto in enumerate(file_proto.extension):
+          extension_desc = self._MakeFieldDescriptor(
+              extension_proto, file_proto.package, index, is_extension=True)
+          extension_desc.containing_type = self._GetTypeFromScope(
+              file_descriptor.package, extension_proto.extendee, scope)
+          self._SetFieldType(extension_proto, extension_desc,
+                            file_descriptor.package, scope)
+          file_descriptor.extensions_by_name[extension_desc.name] = (
+              extension_desc)
+
+        for desc_proto in file_proto.message_type:
+          self._SetAllFieldTypes(file_proto.package, desc_proto, scope)
+
+        if file_proto.package:
+          desc_proto_prefix = _PrefixWithDot(file_proto.package)
+        else:
+          desc_proto_prefix = ''
+
+        for desc_proto in file_proto.message_type:
+          desc = self._GetTypeFromScope(
+              desc_proto_prefix, desc_proto.name, scope)
+          file_descriptor.message_types_by_name[desc_proto.name] = desc
+
+      self.Add(file_proto)
+      self._file_descriptors[file_proto.name] = file_descriptor
+
+    return self._file_descriptors[file_proto.name]
+
+  def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
+                                scope=None, syntax=None):
+    """Adds the proto to the pool in the specified package.
+
+    Args:
+      desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+      package: The package the proto should be located in.
+      file_desc: The file containing this message.
+      scope: Dict mapping short and full symbols to message and enum types.
+
+    Returns:
+      The added descriptor.
+    """
+
+    if package:
+      desc_name = '.'.join((package, desc_proto.name))
+    else:
+      desc_name = desc_proto.name
+
+    if file_desc is None:
+      file_name = None
+    else:
+      file_name = file_desc.name
+
+    if scope is None:
+      scope = {}
+
+    nested = [
+        self._ConvertMessageDescriptor(
+            nested, desc_name, file_desc, scope, syntax)
+        for nested in desc_proto.nested_type]
+    enums = [
+        self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
+        for enum in desc_proto.enum_type]
+    fields = [self._MakeFieldDescriptor(field, desc_name, index)
+              for index, field in enumerate(desc_proto.field)]
+    extensions = [
+        self._MakeFieldDescriptor(extension, desc_name, index,
+                                  is_extension=True)
+        for index, extension in enumerate(desc_proto.extension)]
+    oneofs = [
+        descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)),
+                                   index, None, [])
+        for index, desc in enumerate(desc_proto.oneof_decl)]
+    extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
+    if extension_ranges:
+      is_extendable = True
+    else:
+      is_extendable = False
+    desc = descriptor.Descriptor(
+        name=desc_proto.name,
+        full_name=desc_name,
+        filename=file_name,
+        containing_type=None,
+        fields=fields,
+        oneofs=oneofs,
+        nested_types=nested,
+        enum_types=enums,
+        extensions=extensions,
+        options=desc_proto.options,
+        is_extendable=is_extendable,
+        extension_ranges=extension_ranges,
+        file=file_desc,
+        serialized_start=None,
+        serialized_end=None,
+        syntax=syntax)
+    for nested in desc.nested_types:
+      nested.containing_type = desc
+    for enum in desc.enum_types:
+      enum.containing_type = desc
+    for field_index, field_desc in enumerate(desc_proto.field):
+      if field_desc.HasField('oneof_index'):
+        oneof_index = field_desc.oneof_index
+        oneofs[oneof_index].fields.append(fields[field_index])
+        fields[field_index].containing_oneof = oneofs[oneof_index]
+
+    scope[_PrefixWithDot(desc_name)] = desc
+    self._descriptors[desc_name] = desc
+    return desc
+
+  def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None,
+                             containing_type=None, scope=None):
+    """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
+
+    Args:
+      enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
+      package: Optional package name for the new message EnumDescriptor.
+      file_desc: The file containing the enum descriptor.
+      containing_type: The type containing this enum.
+      scope: Scope containing available types.
+
+    Returns:
+      The added descriptor
+    """
+
+    if package:
+      enum_name = '.'.join((package, enum_proto.name))
+    else:
+      enum_name = enum_proto.name
+
+    if file_desc is None:
+      file_name = None
+    else:
+      file_name = file_desc.name
+
+    values = [self._MakeEnumValueDescriptor(value, index)
+              for index, value in enumerate(enum_proto.value)]
+    desc = descriptor.EnumDescriptor(name=enum_proto.name,
+                                     full_name=enum_name,
+                                     filename=file_name,
+                                     file=file_desc,
+                                     values=values,
+                                     containing_type=containing_type,
+                                     options=enum_proto.options)
+    scope['.%s' % enum_name] = desc
+    self._enum_descriptors[enum_name] = desc
+    return desc
+
+  def _MakeFieldDescriptor(self, field_proto, message_name, index,
+                           is_extension=False):
+    """Creates a field descriptor from a FieldDescriptorProto.
+
+    For message and enum type fields, this method will do a look up
+    in the pool for the appropriate descriptor for that type. If it
+    is unavailable, it will fall back to the _source function to
+    create it. If this type is still unavailable, construction will
+    fail.
+
+    Args:
+      field_proto: The proto describing the field.
+      message_name: The name of the containing message.
+      index: Index of the field
+      is_extension: Indication that this field is for an extension.
+
+    Returns:
+      An initialized FieldDescriptor object
+    """
+
+    if message_name:
+      full_name = '.'.join((message_name, field_proto.name))
+    else:
+      full_name = field_proto.name
+
+    return descriptor.FieldDescriptor(
+        name=field_proto.name,
+        full_name=full_name,
+        index=index,
+        number=field_proto.number,
+        type=field_proto.type,
+        cpp_type=None,
+        message_type=None,
+        enum_type=None,
+        containing_type=None,
+        label=field_proto.label,
+        has_default_value=False,
+        default_value=None,
+        is_extension=is_extension,
+        extension_scope=None,
+        options=field_proto.options)
+
+  def _SetAllFieldTypes(self, package, desc_proto, scope):
+    """Sets all the descriptor's fields's types.
+
+    This method also sets the containing types on any extensions.
+
+    Args:
+      package: The current package of desc_proto.
+      desc_proto: The message descriptor to update.
+      scope: Enclosing scope of available types.
+    """
+
+    package = _PrefixWithDot(package)
+
+    main_desc = self._GetTypeFromScope(package, desc_proto.name, scope)
+
+    if package == '.':
+      nested_package = _PrefixWithDot(desc_proto.name)
+    else:
+      nested_package = '.'.join([package, desc_proto.name])
+
+    for field_proto, field_desc in zip(desc_proto.field, main_desc.fields):
+      self._SetFieldType(field_proto, field_desc, nested_package, scope)
+
+    for extension_proto, extension_desc in (
+        zip(desc_proto.extension, main_desc.extensions)):
+      extension_desc.containing_type = self._GetTypeFromScope(
+          nested_package, extension_proto.extendee, scope)
+      self._SetFieldType(extension_proto, extension_desc, nested_package, scope)
+
+    for nested_type in desc_proto.nested_type:
+      self._SetAllFieldTypes(nested_package, nested_type, scope)
+
+  def _SetFieldType(self, field_proto, field_desc, package, scope):
+    """Sets the field's type, cpp_type, message_type and enum_type.
+
+    Args:
+      field_proto: Data about the field in proto format.
+      field_desc: The descriptor to modiy.
+      package: The package the field's container is in.
+      scope: Enclosing scope of available types.
+    """
+    if field_proto.type_name:
+      desc = self._GetTypeFromScope(package, field_proto.type_name, scope)
+    else:
+      desc = None
+
+    if not field_proto.HasField('type'):
+      if isinstance(desc, descriptor.Descriptor):
+        field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
+      else:
+        field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
+
+    field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
+        field_proto.type)
+
+    if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
+        or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
+      field_desc.message_type = desc
+
+    if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+      field_desc.enum_type = desc
+
+    if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+      field_desc.has_default_value = False
+      field_desc.default_value = []
+    elif field_proto.HasField('default_value'):
+      field_desc.has_default_value = True
+      if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
+          field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
+        field_desc.default_value = float(field_proto.default_value)
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
+        field_desc.default_value = field_proto.default_value
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
+        field_desc.default_value = field_proto.default_value.lower() == 'true'
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+        field_desc.default_value = field_desc.enum_type.values_by_name[
+            field_proto.default_value].number
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
+        field_desc.default_value = text_encoding.CUnescape(
+            field_proto.default_value)
+      else:
+        # All other types are of the "int" type.
+        field_desc.default_value = int(field_proto.default_value)
+    else:
+      field_desc.has_default_value = False
+      if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
+          field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
+        field_desc.default_value = 0.0
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
+        field_desc.default_value = u''
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
+        field_desc.default_value = False
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+        field_desc.default_value = field_desc.enum_type.values[0].number
+      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
+        field_desc.default_value = b''
+      else:
+        # All other types are of the "int" type.
+        field_desc.default_value = 0
+
+    field_desc.type = field_proto.type
+
+  def _MakeEnumValueDescriptor(self, value_proto, index):
+    """Creates a enum value descriptor object from a enum value proto.
+
+    Args:
+      value_proto: The proto describing the enum value.
+      index: The index of the enum value.
+
+    Returns:
+      An initialized EnumValueDescriptor object.
+    """
+
+    return descriptor.EnumValueDescriptor(
+        name=value_proto.name,
+        index=index,
+        number=value_proto.number,
+        options=value_proto.options,
+        type=None)
+
+  def _ExtractSymbols(self, descriptors):
+    """Pulls out all the symbols from descriptor protos.
+
+    Args:
+      descriptors: The messages to extract descriptors from.
+    Yields:
+      A two element tuple of the type name and descriptor object.
+    """
+
+    for desc in descriptors:
+      yield (_PrefixWithDot(desc.full_name), desc)
+      for symbol in self._ExtractSymbols(desc.nested_types):
+        yield symbol
+      for enum in desc.enum_types:
+        yield (_PrefixWithDot(enum.full_name), enum)
+
+  def _GetDeps(self, dependencies):
+    """Recursively finds dependencies for file protos.
+
+    Args:
+      dependencies: The names of the files being depended on.
+
+    Yields:
+      Each direct and indirect dependency.
+    """
+
+    for dependency in dependencies:
+      dep_desc = self.FindFileByName(dependency)
+      yield dep_desc
+      for parent_dep in dep_desc.dependencies:
+        yield parent_dep
+
+  def _GetTypeFromScope(self, package, type_name, scope):
+    """Finds a given type name in the current scope.
+
+    Args:
+      package: The package the proto should be located in.
+      type_name: The name of the type to be found in the scope.
+      scope: Dict mapping short and full symbols to message and enum types.
+
+    Returns:
+      The descriptor for the requested type.
+    """
+    if type_name not in scope:
+      components = _PrefixWithDot(package).split('.')
+      while components:
+        possible_match = '.'.join(components + [type_name])
+        if possible_match in scope:
+          type_name = possible_match
+          break
+        else:
+          components.pop(-1)
+    return scope[type_name]
+
+
+def _PrefixWithDot(name):
+  return name if name.startswith('.') else '.%s' % name
+
+
+if _USE_C_DESCRIPTORS:
+  # TODO(amauryfa): This pool could be constructed from Python code, when we
+  # support a flag like 'use_cpp_generated_pool=True'.
+  # pylint: disable=protected-access
+  _DEFAULT = descriptor._message.default_pool
+else:
+  _DEFAULT = DescriptorPool()
+
+
+def Default():
+  return _DEFAULT
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/__init__.py b/src/third_party/protobuf-3/python/google/protobuf/internal/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/__init__.py
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/_parameterized.py b/src/third_party/protobuf-3/python/google/protobuf/internal/_parameterized.py
new file mode 100755
index 0000000..dea3f19
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/_parameterized.py
@@ -0,0 +1,443 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Adds support for parameterized tests to Python's unittest TestCase class.
+
+A parameterized test is a method in a test case that is invoked with different
+argument tuples.
+
+A simple example:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       (1, 2, 3),
+       (4, 5, 9),
+       (1, 1, 3))
+    def testAddition(self, op1, op2, result):
+      self.assertEqual(result, op1 + op2)
+
+
+Each invocation is a separate test case and properly isolated just
+like a normal test method, with its own setUp/tearDown cycle. In the
+example above, there are three separate testcases, one of which will
+fail due to an assertion error (1 + 1 != 3).
+
+Parameters for invididual test cases can be tuples (with positional parameters)
+or dictionaries (with named parameters):
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       {'op1': 1, 'op2': 2, 'result': 3},
+       {'op1': 4, 'op2': 5, 'result': 9},
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEqual(result, op1 + op2)
+
+If a parameterized test fails, the error message will show the
+original test name (which is modified internally) and the arguments
+for the specific invocation, which are part of the string returned by
+the shortDescription() method on test cases.
+
+The id method of the test, used internally by the unittest framework,
+is also modified to show the arguments. To make sure that test names
+stay the same across several invocations, object representations like
+
+  >>> class Foo(object):
+  ...  pass
+  >>> repr(Foo())
+  '<__main__.Foo object at 0x23d8610>'
+
+are turned into '<__main__.Foo>'. For even more descriptive names,
+especially in test logs, you can use the NamedParameters decorator. In
+this case, only tuples are supported, and the first parameters has to
+be a string (or an object that returns an apt name when converted via
+str()):
+
+  class NamedExample(parameterized.ParameterizedTestCase):
+    @parameterized.NamedParameters(
+       ('Normal', 'aa', 'aaa', True),
+       ('EmptyPrefix', '', 'abc', True),
+       ('BothEmpty', '', '', True))
+    def testStartsWith(self, prefix, string, result):
+      self.assertEqual(result, strings.startswith(prefix))
+
+Named tests also have the benefit that they can be run individually
+from the command line:
+
+  $ testmodule.py NamedExample.testStartsWithNormal
+  .
+  --------------------------------------------------------------------
+  Ran 1 test in 0.000s
+
+  OK
+
+Parameterized Classes
+=====================
+If invocation arguments are shared across test methods in a single
+ParameterizedTestCase class, instead of decorating all test methods
+individually, the class itself can be decorated:
+
+  @parameterized.Parameters(
+    (1, 2, 3)
+    (4, 5, 9))
+  class ArithmeticTest(parameterized.ParameterizedTestCase):
+    def testAdd(self, arg1, arg2, result):
+      self.assertEqual(arg1 + arg2, result)
+
+    def testSubtract(self, arg2, arg2, result):
+      self.assertEqual(result - arg1, arg2)
+
+Inputs from Iterables
+=====================
+If parameters should be shared across several test cases, or are dynamically
+created from other sources, a single non-tuple iterable can be passed into
+the decorator. This iterable will be used to obtain the test cases:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+      c.op1, c.op2, c.result for c in testcases
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEqual(result, op1 + op2)
+
+
+Single-Argument Test Methods
+============================
+If a test method takes only one argument, the single argument does not need to
+be wrapped into a tuple:
+
+  class NegativeNumberExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       -1, -3, -4, -5
+    )
+    def testIsNegative(self, arg):
+      self.assertTrue(IsNegative(arg))
+"""
+
+__author__ = 'tmarek@google.com (Torsten Marek)'
+
+import collections
+import functools
+import re
+import types
+try:
+  import unittest2 as unittest
+except ImportError:
+  import unittest
+import uuid
+
+import six
+
+ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
+_SEPARATOR = uuid.uuid1().hex
+_FIRST_ARG = object()
+_ARGUMENT_REPR = object()
+
+
+def _CleanRepr(obj):
+  return ADDR_RE.sub(r'<\1>', repr(obj))
+
+
+# Helper function formerly from the unittest module, removed from it in
+# Python 2.7.
+def _StrClass(cls):
+  return '%s.%s' % (cls.__module__, cls.__name__)
+
+
+def _NonStringIterable(obj):
+  return (isinstance(obj, collections.Iterable) and not
+          isinstance(obj, six.string_types))
+
+
+def _FormatParameterList(testcase_params):
+  if isinstance(testcase_params, collections.Mapping):
+    return ', '.join('%s=%s' % (argname, _CleanRepr(value))
+                     for argname, value in testcase_params.items())
+  elif _NonStringIterable(testcase_params):
+    return ', '.join(map(_CleanRepr, testcase_params))
+  else:
+    return _FormatParameterList((testcase_params,))
+
+
+class _ParameterizedTestIter(object):
+  """Callable and iterable class for producing new test cases."""
+
+  def __init__(self, test_method, testcases, naming_type):
+    """Returns concrete test functions for a test and a list of parameters.
+
+    The naming_type is used to determine the name of the concrete
+    functions as reported by the unittest framework. If naming_type is
+    _FIRST_ARG, the testcases must be tuples, and the first element must
+    have a string representation that is a valid Python identifier.
+
+    Args:
+      test_method: The decorated test method.
+      testcases: (list of tuple/dict) A list of parameter
+                 tuples/dicts for individual test invocations.
+      naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR.
+    """
+    self._test_method = test_method
+    self.testcases = testcases
+    self._naming_type = naming_type
+
+  def __call__(self, *args, **kwargs):
+    raise RuntimeError('You appear to be running a parameterized test case '
+                       'without having inherited from parameterized.'
+                       'ParameterizedTestCase. This is bad because none of '
+                       'your test cases are actually being run.')
+
+  def __iter__(self):
+    test_method = self._test_method
+    naming_type = self._naming_type
+
+    def MakeBoundParamTest(testcase_params):
+      @functools.wraps(test_method)
+      def BoundParamTest(self):
+        if isinstance(testcase_params, collections.Mapping):
+          test_method(self, **testcase_params)
+        elif _NonStringIterable(testcase_params):
+          test_method(self, *testcase_params)
+        else:
+          test_method(self, testcase_params)
+
+      if naming_type is _FIRST_ARG:
+        # Signal the metaclass that the name of the test function is unique
+        # and descriptive.
+        BoundParamTest.__x_use_name__ = True
+        BoundParamTest.__name__ += str(testcase_params[0])
+        testcase_params = testcase_params[1:]
+      elif naming_type is _ARGUMENT_REPR:
+        # __x_extra_id__ is used to pass naming information to the __new__
+        # method of TestGeneratorMetaclass.
+        # The metaclass will make sure to create a unique, but nondescriptive
+        # name for this test.
+        BoundParamTest.__x_extra_id__ = '(%s)' % (
+            _FormatParameterList(testcase_params),)
+      else:
+        raise RuntimeError('%s is not a valid naming type.' % (naming_type,))
+
+      BoundParamTest.__doc__ = '%s(%s)' % (
+          BoundParamTest.__name__, _FormatParameterList(testcase_params))
+      if test_method.__doc__:
+        BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,)
+      return BoundParamTest
+    return (MakeBoundParamTest(c) for c in self.testcases)
+
+
+def _IsSingletonList(testcases):
+  """True iff testcases contains only a single non-tuple element."""
+  return len(testcases) == 1 and not isinstance(testcases[0], tuple)
+
+
+def _ModifyClass(class_object, testcases, naming_type):
+  assert not getattr(class_object, '_id_suffix', None), (
+      'Cannot add parameters to %s,'
+      ' which already has parameterized methods.' % (class_object,))
+  class_object._id_suffix = id_suffix = {}
+  # We change the size of __dict__ while we iterate over it, 
+  # which Python 3.x will complain about, so use copy().
+  for name, obj in class_object.__dict__.copy().items():
+    if (name.startswith(unittest.TestLoader.testMethodPrefix)
+        and isinstance(obj, types.FunctionType)):
+      delattr(class_object, name)
+      methods = {}
+      _UpdateClassDictForParamTestCase(
+          methods, id_suffix, name,
+          _ParameterizedTestIter(obj, testcases, naming_type))
+      for name, meth in methods.items():
+        setattr(class_object, name, meth)
+
+
+def _ParameterDecorator(naming_type, testcases):
+  """Implementation of the parameterization decorators.
+
+  Args:
+    naming_type: The naming type.
+    testcases: Testcase parameters.
+
+  Returns:
+    A function for modifying the decorated object.
+  """
+  def _Apply(obj):
+    if isinstance(obj, type):
+      _ModifyClass(
+          obj,
+          list(testcases) if not isinstance(testcases, collections.Sequence)
+          else testcases,
+          naming_type)
+      return obj
+    else:
+      return _ParameterizedTestIter(obj, testcases, naming_type)
+
+  if _IsSingletonList(testcases):
+    assert _NonStringIterable(testcases[0]), (
+        'Single parameter argument must be a non-string iterable')
+    testcases = testcases[0]
+
+  return _Apply
+
+
+def Parameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example.
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples/dicts/objects (for tests
+                with only one argument).
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_ARGUMENT_REPR, testcases)
+
+
+def NamedParameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example. The first element of
+  each parameter tuple should be a string and will be appended to the
+  name of the test method.
+
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples.
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_FIRST_ARG, testcases)
+
+
+class TestGeneratorMetaclass(type):
+  """Metaclass for test cases with test generators.
+
+  A test generator is an iterable in a testcase that produces callables. These
+  callables must be single-argument methods. These methods are injected into
+  the class namespace and the original iterable is removed. If the name of the
+  iterable conforms to the test pattern, the injected methods will be picked
+  up as tests by the unittest framework.
+
+  In general, it is supposed to be used in conjuction with the
+  Parameters decorator.
+  """
+
+  def __new__(mcs, class_name, bases, dct):
+    dct['_id_suffix'] = id_suffix = {}
+    for name, obj in dct.items():
+      if (name.startswith(unittest.TestLoader.testMethodPrefix) and
+          _NonStringIterable(obj)):
+        iterator = iter(obj)
+        dct.pop(name)
+        _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)
+
+    return type.__new__(mcs, class_name, bases, dct)
+
+
+def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
+  """Adds individual test cases to a dictionary.
+
+  Args:
+    dct: The target dictionary.
+    id_suffix: The dictionary for mapping names to test IDs.
+    name: The original name of the test case.
+    iterator: The iterator generating the individual test cases.
+  """
+  for idx, func in enumerate(iterator):
+    assert callable(func), 'Test generators must yield callables, got %r' % (
+        func,)
+    if getattr(func, '__x_use_name__', False):
+      new_name = func.__name__
+    else:
+      new_name = '%s%s%d' % (name, _SEPARATOR, idx)
+    assert new_name not in dct, (
+        'Name of parameterized test case "%s" not unique' % (new_name,))
+    dct[new_name] = func
+    id_suffix[new_name] = getattr(func, '__x_extra_id__', '')
+
+
+class ParameterizedTestCase(unittest.TestCase):
+  """Base class for test cases using the Parameters decorator."""
+  __metaclass__ = TestGeneratorMetaclass
+
+  def _OriginalName(self):
+    return self._testMethodName.split(_SEPARATOR)[0]
+
+  def __str__(self):
+    return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))
+
+  def id(self):  # pylint: disable=invalid-name
+    """Returns the descriptive ID of the test.
+
+    This is used internally by the unittesting framework to get a name
+    for the test to be used in reports.
+
+    Returns:
+      The test id.
+    """
+    return '%s.%s%s' % (_StrClass(self.__class__),
+                        self._OriginalName(),
+                        self._id_suffix.get(self._testMethodName, ''))
+
+
+def CoopParameterizedTestCase(other_base_class):
+  """Returns a new base class with a cooperative metaclass base.
+
+  This enables the ParameterizedTestCase to be used in combination
+  with other base classes that have custom metaclasses, such as
+  mox.MoxTestBase.
+
+  Only works with metaclasses that do not override type.__new__.
+
+  Example:
+
+    import google3
+    import mox
+
+    from google3.testing.pybase import parameterized
+
+    class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)):
+      ...
+
+  Args:
+    other_base_class: (class) A test case base class.
+
+  Returns:
+    A new class object.
+  """
+  metaclass = type(
+      'CoopMetaclass',
+      (other_base_class.__metaclass__,
+       TestGeneratorMetaclass), {})
+  return metaclass(
+      'CoopParameterizedTestCase',
+      (other_base_class, ParameterizedTestCase), {})
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/any_test.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/any_test.proto
new file mode 100644
index 0000000..cd641ca
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/any_test.proto
@@ -0,0 +1,42 @@
+// 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.
+
+// Author: jieluo@google.com (Jie Luo)
+
+syntax = "proto3";
+
+package google.protobuf.internal;
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+  google.protobuf.Any value = 1;
+  int32 int_value = 2;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.cc b/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.cc
new file mode 100644
index 0000000..6db12e8
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.cc
@@ -0,0 +1,129 @@
+// 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.
+
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// Version constant.
+// This is either 0 for python, 1 for CPP V1, 2 for CPP V2.
+//
+// 0 is default and is equivalent to
+//   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
+//
+// 1 is set with -DPYTHON_PROTO2_CPP_IMPL_V1 and is equivalent to
+//   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+// and
+//   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=1
+//
+// 2 is set with -DPYTHON_PROTO2_CPP_IMPL_V2 and is equivalent to
+//   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+// and
+//   PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
+#ifdef PYTHON_PROTO2_CPP_IMPL_V1
+#error "PYTHON_PROTO2_CPP_IMPL_V1 is no longer supported."
+#else
+#ifdef PYTHON_PROTO2_CPP_IMPL_V2
+static int kImplVersion = 2;
+#else
+#ifdef PYTHON_PROTO2_PYTHON_IMPL
+static int kImplVersion = 0;
+#else
+
+static int kImplVersion = -1;  // -1 means "Unspecified by compiler flags".
+
+#endif  // PYTHON_PROTO2_PYTHON_IMPL
+#endif  // PYTHON_PROTO2_CPP_IMPL_V2
+#endif  // PYTHON_PROTO2_CPP_IMPL_V1
+
+static const char* kImplVersionName = "api_version";
+
+static const char* kModuleName = "_api_implementation";
+static const char kModuleDocstring[] =
+"_api_implementation is a module that exposes compile-time constants that\n"
+"determine the default API implementation to use for Python proto2.\n"
+"\n"
+"It complements api_implementation.py by setting defaults using compile-time\n"
+"constants defined in C, such that one can set defaults at compilation\n"
+"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2).";
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef _module = {
+  PyModuleDef_HEAD_INIT,
+  kModuleName,
+  kModuleDocstring,
+  -1,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+#define INITFUNC PyInit__api_implementation
+#define INITFUNC_ERRORVAL NULL
+#else
+#define INITFUNC init_api_implementation
+#define INITFUNC_ERRORVAL
+#endif
+
+extern "C" {
+  PyMODINIT_FUNC INITFUNC() {
+#if PY_MAJOR_VERSION >= 3
+    PyObject *module = PyModule_Create(&_module);
+#else
+    PyObject *module = Py_InitModule3(
+        const_cast<char*>(kModuleName),
+        NULL,
+        const_cast<char*>(kModuleDocstring));
+#endif
+    if (module == NULL) {
+      return INITFUNC_ERRORVAL;
+    }
+
+    // Adds the module variable "api_version".
+    if (PyModule_AddIntConstant(
+        module,
+        const_cast<char*>(kImplVersionName),
+        kImplVersion))
+#if PY_MAJOR_VERSION < 3
+      return;
+#else
+      { Py_DECREF(module); return NULL; }
+
+    return module;
+#endif
+  }
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.py b/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.py
new file mode 100755
index 0000000..460a4a6
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/api_implementation.py
@@ -0,0 +1,113 @@
+# 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.
+
+"""Determine which implementation of the protobuf API is used in this process.
+"""
+
+import os
+import warnings
+import sys
+
+try:
+  # pylint: disable=g-import-not-at-top
+  from google.protobuf.internal import _api_implementation
+  # The compile-time constants in the _api_implementation module can be used to
+  # switch to a certain implementation of the Python API at build time.
+  _api_version = _api_implementation.api_version
+  _proto_extension_modules_exist_in_build = True
+except ImportError:
+  _api_version = -1  # Unspecified by compiler flags.
+  _proto_extension_modules_exist_in_build = False
+
+if _api_version == 1:
+  raise ValueError('api_version=1 is no longer supported.')
+if _api_version < 0:  # Still unspecified?
+  try:
+    # The presence of this module in a build allows the proto implementation to
+    # be upgraded merely via build deps rather than a compiler flag or the
+    # runtime environment variable.
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf import _use_fast_cpp_protos
+    # Work around a known issue in the classic bootstrap .par import hook.
+    if not _use_fast_cpp_protos:
+      raise ImportError('_use_fast_cpp_protos import succeeded but was None')
+    del _use_fast_cpp_protos
+    _api_version = 2
+  except ImportError:
+    if _proto_extension_modules_exist_in_build:
+      if sys.version_info[0] >= 3:  # Python 3 defaults to C++ impl v2.
+        _api_version = 2
+      # TODO(b/17427486): Make Python 2 default to C++ impl v2.
+
+_default_implementation_type = (
+    'python' if _api_version <= 0 else 'cpp')
+
+# This environment variable can be used to switch to a certain implementation
+# of the Python API, overriding the compile-time constants in the
+# _api_implementation module. Right now only 'python' and 'cpp' are valid
+# values. Any other value will be ignored.
+_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION',
+                                 _default_implementation_type)
+
+if _implementation_type != 'python':
+  _implementation_type = 'cpp'
+
+if 'PyPy' in sys.version and _implementation_type == 'cpp':
+  warnings.warn('PyPy does not work yet with cpp protocol buffers. '
+                'Falling back to the python implementation.')
+  _implementation_type = 'python'
+
+# This environment variable can be used to switch between the two
+# 'cpp' implementations, overriding the compile-time constants in the
+# _api_implementation module. Right now only '2' is supported. Any other
+# value will cause an error to be raised.
+_implementation_version_str = os.getenv(
+    'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2')
+
+if _implementation_version_str != '2':
+  raise ValueError(
+      'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' +
+      _implementation_version_str + '" (supported versions: 2)'
+      )
+
+_implementation_version = int(_implementation_version_str)
+
+
+# Usage of this function is discouraged. Clients shouldn't care which
+# implementation of the API is in use. Note that there is no guarantee
+# that differences between APIs will be maintained.
+# Please don't use this function if possible.
+def Type():
+  return _implementation_type
+
+
+# See comment on 'Type' above.
+def Version():
+  return _implementation_version
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/containers.py b/src/third_party/protobuf-3/python/google/protobuf/internal/containers.py
new file mode 100755
index 0000000..97cdd84
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/containers.py
@@ -0,0 +1,611 @@
+# 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.
+
+"""Contains container classes to represent different protocol buffer types.
+
+This file defines container classes which represent categories of protocol
+buffer field types which need extra maintenance. Currently these categories
+are:
+  - Repeated scalar fields - These are all repeated fields which aren't
+    composite (e.g. they are of simple types like int32, string, etc).
+  - Repeated composite fields - Repeated fields which are composite. This
+    includes groups and nested messages.
+"""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+import collections
+import sys
+
+if sys.version_info[0] < 3:
+  # We would use collections.MutableMapping all the time, but in Python 2 it
+  # doesn't define __slots__.  This causes two significant problems:
+  #
+  # 1. we can't disallow arbitrary attribute assignment, even if our derived
+  #    classes *do* define __slots__.
+  #
+  # 2. we can't safely derive a C type from it without __slots__ defined (the
+  #    interpreter expects to find a dict at tp_dictoffset, which we can't
+  #    robustly provide.  And we don't want an instance dict anyway.
+  #
+  # So this is the Python 2.7 definition of Mapping/MutableMapping functions
+  # verbatim, except that:
+  # 1. We declare __slots__.
+  # 2. We don't declare this as a virtual base class.  The classes defined
+  #    in collections are the interesting base classes, not us.
+  #
+  # Note: deriving from object is critical.  It is the only thing that makes
+  # this a true type, allowing us to derive from it in C++ cleanly and making
+  # __slots__ properly disallow arbitrary element assignment.
+
+  class Mapping(object):
+    __slots__ = ()
+
+    def get(self, key, default=None):
+      try:
+        return self[key]
+      except KeyError:
+        return default
+
+    def __contains__(self, key):
+      try:
+        self[key]
+      except KeyError:
+        return False
+      else:
+        return True
+
+    def iterkeys(self):
+      return iter(self)
+
+    def itervalues(self):
+      for key in self:
+        yield self[key]
+
+    def iteritems(self):
+      for key in self:
+        yield (key, self[key])
+
+    def keys(self):
+      return list(self)
+
+    def items(self):
+      return [(key, self[key]) for key in self]
+
+    def values(self):
+      return [self[key] for key in self]
+
+    # Mappings are not hashable by default, but subclasses can change this
+    __hash__ = None
+
+    def __eq__(self, other):
+      if not isinstance(other, collections.Mapping):
+        return NotImplemented
+      return dict(self.items()) == dict(other.items())
+
+    def __ne__(self, other):
+      return not (self == other)
+
+  class MutableMapping(Mapping):
+    __slots__ = ()
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+      try:
+        value = self[key]
+      except KeyError:
+        if default is self.__marker:
+          raise
+        return default
+      else:
+        del self[key]
+        return value
+
+    def popitem(self):
+      try:
+        key = next(iter(self))
+      except StopIteration:
+        raise KeyError
+      value = self[key]
+      del self[key]
+      return key, value
+
+    def clear(self):
+      try:
+        while True:
+          self.popitem()
+      except KeyError:
+        pass
+
+    def update(*args, **kwds):
+      if len(args) > 2:
+        raise TypeError("update() takes at most 2 positional "
+                        "arguments ({} given)".format(len(args)))
+      elif not args:
+        raise TypeError("update() takes at least 1 argument (0 given)")
+      self = args[0]
+      other = args[1] if len(args) >= 2 else ()
+
+      if isinstance(other, Mapping):
+        for key in other:
+          self[key] = other[key]
+      elif hasattr(other, "keys"):
+        for key in other.keys():
+          self[key] = other[key]
+      else:
+        for key, value in other:
+          self[key] = value
+      for key, value in kwds.items():
+        self[key] = value
+
+    def setdefault(self, key, default=None):
+      try:
+        return self[key]
+      except KeyError:
+        self[key] = default
+      return default
+
+  collections.Mapping.register(Mapping)
+  collections.MutableMapping.register(MutableMapping)
+
+else:
+  # In Python 3 we can just use MutableMapping directly, because it defines
+  # __slots__.
+  MutableMapping = collections.MutableMapping
+
+
+class BaseContainer(object):
+
+  """Base container class."""
+
+  # Minimizes memory usage and disallows assignment to other attributes.
+  __slots__ = ['_message_listener', '_values']
+
+  def __init__(self, message_listener):
+    """
+    Args:
+      message_listener: A MessageListener implementation.
+        The RepeatedScalarFieldContainer will call this object's
+        Modified() method when it is modified.
+    """
+    self._message_listener = message_listener
+    self._values = []
+
+  def __getitem__(self, key):
+    """Retrieves item by the specified key."""
+    return self._values[key]
+
+  def __len__(self):
+    """Returns the number of elements in the container."""
+    return len(self._values)
+
+  def __ne__(self, other):
+    """Checks if another instance isn't equal to this one."""
+    # The concrete classes should define __eq__.
+    return not self == other
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  def __repr__(self):
+    return repr(self._values)
+
+  def sort(self, *args, **kwargs):
+    # Continue to support the old sort_function keyword argument.
+    # This is expected to be a rare occurrence, so use LBYL to avoid
+    # the overhead of actually catching KeyError.
+    if 'sort_function' in kwargs:
+      kwargs['cmp'] = kwargs.pop('sort_function')
+    self._values.sort(*args, **kwargs)
+
+
+class RepeatedScalarFieldContainer(BaseContainer):
+
+  """Simple, type-checked, list-like container for holding repeated scalars."""
+
+  # Disallows assignment to other attributes.
+  __slots__ = ['_type_checker']
+
+  def __init__(self, message_listener, type_checker):
+    """
+    Args:
+      message_listener: A MessageListener implementation.
+        The RepeatedScalarFieldContainer will call this object's
+        Modified() method when it is modified.
+      type_checker: A type_checkers.ValueChecker instance to run on elements
+        inserted into this container.
+    """
+    super(RepeatedScalarFieldContainer, self).__init__(message_listener)
+    self._type_checker = type_checker
+
+  def append(self, value):
+    """Appends an item to the list. Similar to list.append()."""
+    self._values.append(self._type_checker.CheckValue(value))
+    if not self._message_listener.dirty:
+      self._message_listener.Modified()
+
+  def insert(self, key, value):
+    """Inserts the item at the specified position. Similar to list.insert()."""
+    self._values.insert(key, self._type_checker.CheckValue(value))
+    if not self._message_listener.dirty:
+      self._message_listener.Modified()
+
+  def extend(self, elem_seq):
+    """Extends by appending the given iterable. Similar to list.extend()."""
+
+    if elem_seq is None:
+      return
+    try:
+      elem_seq_iter = iter(elem_seq)
+    except TypeError:
+      if not elem_seq:
+        # silently ignore falsy inputs :-/.
+        # TODO(ptucker): Deprecate this behavior. b/18413862
+        return
+      raise
+
+    new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter]
+    if new_values:
+      self._values.extend(new_values)
+      self._message_listener.Modified()
+
+  def MergeFrom(self, other):
+    """Appends the contents of another repeated field of the same type to this
+    one. We do not check the types of the individual fields.
+    """
+    self._values.extend(other._values)
+    self._message_listener.Modified()
+
+  def remove(self, elem):
+    """Removes an item from the list. Similar to list.remove()."""
+    self._values.remove(elem)
+    self._message_listener.Modified()
+
+  def pop(self, key=-1):
+    """Removes and returns an item at a given index. Similar to list.pop()."""
+    value = self._values[key]
+    self.__delitem__(key)
+    return value
+
+  def __setitem__(self, key, value):
+    """Sets the item on the specified position."""
+    if isinstance(key, slice):  # PY3
+      if key.step is not None:
+        raise ValueError('Extended slices not supported')
+      self.__setslice__(key.start, key.stop, value)
+    else:
+      self._values[key] = self._type_checker.CheckValue(value)
+      self._message_listener.Modified()
+
+  def __getslice__(self, start, stop):
+    """Retrieves the subset of items from between the specified indices."""
+    return self._values[start:stop]
+
+  def __setslice__(self, start, stop, values):
+    """Sets the subset of items from between the specified indices."""
+    new_values = []
+    for value in values:
+      new_values.append(self._type_checker.CheckValue(value))
+    self._values[start:stop] = new_values
+    self._message_listener.Modified()
+
+  def __delitem__(self, key):
+    """Deletes the item at the specified position."""
+    del self._values[key]
+    self._message_listener.Modified()
+
+  def __delslice__(self, start, stop):
+    """Deletes the subset of items from between the specified indices."""
+    del self._values[start:stop]
+    self._message_listener.Modified()
+
+  def __eq__(self, other):
+    """Compares the current instance with another one."""
+    if self is other:
+      return True
+    # Special case for the same type which should be common and fast.
+    if isinstance(other, self.__class__):
+      return other._values == self._values
+    # We are presumably comparing against some other sequence type.
+    return other == self._values
+
+collections.MutableSequence.register(BaseContainer)
+
+
+class RepeatedCompositeFieldContainer(BaseContainer):
+
+  """Simple, list-like container for holding repeated composite fields."""
+
+  # Disallows assignment to other attributes.
+  __slots__ = ['_message_descriptor']
+
+  def __init__(self, message_listener, message_descriptor):
+    """
+    Note that we pass in a descriptor instead of the generated directly,
+    since at the time we construct a _RepeatedCompositeFieldContainer we
+    haven't yet necessarily initialized the type that will be contained in the
+    container.
+
+    Args:
+      message_listener: A MessageListener implementation.
+        The RepeatedCompositeFieldContainer will call this object's
+        Modified() method when it is modified.
+      message_descriptor: A Descriptor instance describing the protocol type
+        that should be present in this container.  We'll use the
+        _concrete_class field of this descriptor when the client calls add().
+    """
+    super(RepeatedCompositeFieldContainer, self).__init__(message_listener)
+    self._message_descriptor = message_descriptor
+
+  def add(self, **kwargs):
+    """Adds a new element at the end of the list and returns it. Keyword
+    arguments may be used to initialize the element.
+    """
+    new_element = self._message_descriptor._concrete_class(**kwargs)
+    new_element._SetListener(self._message_listener)
+    self._values.append(new_element)
+    if not self._message_listener.dirty:
+      self._message_listener.Modified()
+    return new_element
+
+  def extend(self, elem_seq):
+    """Extends by appending the given sequence of elements of the same type
+    as this one, copying each individual message.
+    """
+    message_class = self._message_descriptor._concrete_class
+    listener = self._message_listener
+    values = self._values
+    for message in elem_seq:
+      new_element = message_class()
+      new_element._SetListener(listener)
+      new_element.MergeFrom(message)
+      values.append(new_element)
+    listener.Modified()
+
+  def MergeFrom(self, other):
+    """Appends the contents of another repeated field of the same type to this
+    one, copying each individual message.
+    """
+    self.extend(other._values)
+
+  def remove(self, elem):
+    """Removes an item from the list. Similar to list.remove()."""
+    self._values.remove(elem)
+    self._message_listener.Modified()
+
+  def pop(self, key=-1):
+    """Removes and returns an item at a given index. Similar to list.pop()."""
+    value = self._values[key]
+    self.__delitem__(key)
+    return value
+
+  def __getslice__(self, start, stop):
+    """Retrieves the subset of items from between the specified indices."""
+    return self._values[start:stop]
+
+  def __delitem__(self, key):
+    """Deletes the item at the specified position."""
+    del self._values[key]
+    self._message_listener.Modified()
+
+  def __delslice__(self, start, stop):
+    """Deletes the subset of items from between the specified indices."""
+    del self._values[start:stop]
+    self._message_listener.Modified()
+
+  def __eq__(self, other):
+    """Compares the current instance with another one."""
+    if self is other:
+      return True
+    if not isinstance(other, self.__class__):
+      raise TypeError('Can only compare repeated composite fields against '
+                      'other repeated composite fields.')
+    return self._values == other._values
+
+
+class ScalarMap(MutableMapping):
+
+  """Simple, type-checked, dict-like container for holding repeated scalars."""
+
+  # Disallows assignment to other attributes.
+  __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener']
+
+  def __init__(self, message_listener, key_checker, value_checker):
+    """
+    Args:
+      message_listener: A MessageListener implementation.
+        The ScalarMap will call this object's Modified() method when it
+        is modified.
+      key_checker: A type_checkers.ValueChecker instance to run on keys
+        inserted into this container.
+      value_checker: A type_checkers.ValueChecker instance to run on values
+        inserted into this container.
+    """
+    self._message_listener = message_listener
+    self._key_checker = key_checker
+    self._value_checker = value_checker
+    self._values = {}
+
+  def __getitem__(self, key):
+    try:
+      return self._values[key]
+    except KeyError:
+      key = self._key_checker.CheckValue(key)
+      val = self._value_checker.DefaultValue()
+      self._values[key] = val
+      return val
+
+  def __contains__(self, item):
+    # We check the key's type to match the strong-typing flavor of the API.
+    # Also this makes it easier to match the behavior of the C++ implementation.
+    self._key_checker.CheckValue(item)
+    return item in self._values
+
+  # We need to override this explicitly, because our defaultdict-like behavior
+  # will make the default implementation (from our base class) always insert
+  # the key.
+  def get(self, key, default=None):
+    if key in self:
+      return self[key]
+    else:
+      return default
+
+  def __setitem__(self, key, value):
+    checked_key = self._key_checker.CheckValue(key)
+    checked_value = self._value_checker.CheckValue(value)
+    self._values[checked_key] = checked_value
+    self._message_listener.Modified()
+
+  def __delitem__(self, key):
+    del self._values[key]
+    self._message_listener.Modified()
+
+  def __len__(self):
+    return len(self._values)
+
+  def __iter__(self):
+    return iter(self._values)
+
+  def __repr__(self):
+    return repr(self._values)
+
+  def MergeFrom(self, other):
+    self._values.update(other._values)
+    self._message_listener.Modified()
+
+  def InvalidateIterators(self):
+    # It appears that the only way to reliably invalidate iterators to
+    # self._values is to ensure that its size changes.
+    original = self._values
+    self._values = original.copy()
+    original[None] = None
+
+  # This is defined in the abstract base, but we can do it much more cheaply.
+  def clear(self):
+    self._values.clear()
+    self._message_listener.Modified()
+
+
+class MessageMap(MutableMapping):
+
+  """Simple, type-checked, dict-like container for with submessage values."""
+
+  # Disallows assignment to other attributes.
+  __slots__ = ['_key_checker', '_values', '_message_listener',
+               '_message_descriptor']
+
+  def __init__(self, message_listener, message_descriptor, key_checker):
+    """
+    Args:
+      message_listener: A MessageListener implementation.
+        The ScalarMap will call this object's Modified() method when it
+        is modified.
+      key_checker: A type_checkers.ValueChecker instance to run on keys
+        inserted into this container.
+      value_checker: A type_checkers.ValueChecker instance to run on values
+        inserted into this container.
+    """
+    self._message_listener = message_listener
+    self._message_descriptor = message_descriptor
+    self._key_checker = key_checker
+    self._values = {}
+
+  def __getitem__(self, key):
+    try:
+      return self._values[key]
+    except KeyError:
+      key = self._key_checker.CheckValue(key)
+      new_element = self._message_descriptor._concrete_class()
+      new_element._SetListener(self._message_listener)
+      self._values[key] = new_element
+      self._message_listener.Modified()
+
+      return new_element
+
+  def get_or_create(self, key):
+    """get_or_create() is an alias for getitem (ie. map[key]).
+
+    Args:
+      key: The key to get or create in the map.
+
+    This is useful in cases where you want to be explicit that the call is
+    mutating the map.  This can avoid lint errors for statements like this
+    that otherwise would appear to be pointless statements:
+
+      msg.my_map[key]
+    """
+    return self[key]
+
+  # We need to override this explicitly, because our defaultdict-like behavior
+  # will make the default implementation (from our base class) always insert
+  # the key.
+  def get(self, key, default=None):
+    if key in self:
+      return self[key]
+    else:
+      return default
+
+  def __contains__(self, item):
+    return item in self._values
+
+  def __setitem__(self, key, value):
+    raise ValueError('May not set values directly, call my_map[key].foo = 5')
+
+  def __delitem__(self, key):
+    del self._values[key]
+    self._message_listener.Modified()
+
+  def __len__(self):
+    return len(self._values)
+
+  def __iter__(self):
+    return iter(self._values)
+
+  def __repr__(self):
+    return repr(self._values)
+
+  def MergeFrom(self, other):
+    for key in other:
+      self[key].MergeFrom(other[key])
+    # self._message_listener.Modified() not required here, because
+    # mutations to submessages already propagate.
+
+  def InvalidateIterators(self):
+    # It appears that the only way to reliably invalidate iterators to
+    # self._values is to ensure that its size changes.
+    original = self._values
+    self._values = original.copy()
+    original[None] = None
+
+  # This is defined in the abstract base, but we can do it much more cheaply.
+  def clear(self):
+    self._values.clear()
+    self._message_listener.Modified()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/decoder.py b/src/third_party/protobuf-3/python/google/protobuf/internal/decoder.py
new file mode 100755
index 0000000..31869e4
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/decoder.py
@@ -0,0 +1,854 @@
+# 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.
+
+"""Code for decoding protocol buffer primitives.
+
+This code is very similar to encoder.py -- read the docs for that module first.
+
+A "decoder" is a function with the signature:
+  Decode(buffer, pos, end, message, field_dict)
+The arguments are:
+  buffer:     The string containing the encoded message.
+  pos:        The current position in the string.
+  end:        The position in the string where the current message ends.  May be
+              less than len(buffer) if we're reading a sub-message.
+  message:    The message object into which we're parsing.
+  field_dict: message._fields (avoids a hashtable lookup).
+The decoder reads the field and stores it into field_dict, returning the new
+buffer position.  A decoder for a repeated field may proactively decode all of
+the elements of that field, if they appear consecutively.
+
+Note that decoders may throw any of the following:
+  IndexError:  Indicates a truncated message.
+  struct.error:  Unpacking of a fixed-width field failed.
+  message.DecodeError:  Other errors.
+
+Decoders are expected to raise an exception if they are called with pos > end.
+This allows callers to be lax about bounds checking:  it's fineto read past
+"end" as long as you are sure that someone else will notice and throw an
+exception later on.
+
+Something up the call stack is expected to catch IndexError and struct.error
+and convert them to message.DecodeError.
+
+Decoders are constructed using decoder constructors with the signature:
+  MakeDecoder(field_number, is_repeated, is_packed, key, new_default)
+The arguments are:
+  field_number:  The field number of the field we want to decode.
+  is_repeated:   Is the field a repeated field? (bool)
+  is_packed:     Is the field a packed field? (bool)
+  key:           The key to use when looking up the field within field_dict.
+                 (This is actually the FieldDescriptor but nothing in this
+                 file should depend on that.)
+  new_default:   A function which takes a message object as a parameter and
+                 returns a new instance of the default value for this field.
+                 (This is called for repeated fields and sub-messages, when an
+                 instance does not already exist.)
+
+As with encoders, we define a decoder constructor for every type of field.
+Then, for every field of every message class we construct an actual decoder.
+That decoder goes into a dict indexed by tag, so when we decode a message
+we repeatedly read a tag, look up the corresponding decoder, and invoke it.
+"""
+
+__author__ = 'kenton@google.com (Kenton Varda)'
+
+import struct
+
+import six
+
+if six.PY3:
+  long = int
+
+from google.protobuf.internal import encoder
+from google.protobuf.internal import wire_format
+from google.protobuf import message
+
+
+# This will overflow and thus become IEEE-754 "infinity".  We would use
+# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
+_POS_INF = 1e10000
+_NEG_INF = -_POS_INF
+_NAN = _POS_INF * 0
+
+
+# This is not for optimization, but rather to avoid conflicts with local
+# variables named "message".
+_DecodeError = message.DecodeError
+
+
+def _VarintDecoder(mask, result_type):
+  """Return an encoder for a basic varint value (does not include tag).
+
+  Decoded values will be bitwise-anded with the given mask before being
+  returned, e.g. to limit them to 32 bits.  The returned decoder does not
+  take the usual "end" parameter -- the caller is expected to do bounds checking
+  after the fact (often the caller can defer such checking until later).  The
+  decoder returns a (value, new_pos) pair.
+  """
+
+  def DecodeVarint(buffer, pos):
+    result = 0
+    shift = 0
+    while 1:
+      b = six.indexbytes(buffer, pos)
+      result |= ((b & 0x7f) << shift)
+      pos += 1
+      if not (b & 0x80):
+        result &= mask
+        result = result_type(result)
+        return (result, pos)
+      shift += 7
+      if shift >= 64:
+        raise _DecodeError('Too many bytes when decoding varint.')
+  return DecodeVarint
+
+
+def _SignedVarintDecoder(mask, result_type):
+  """Like _VarintDecoder() but decodes signed values."""
+
+  def DecodeVarint(buffer, pos):
+    result = 0
+    shift = 0
+    while 1:
+      b = six.indexbytes(buffer, pos)
+      result |= ((b & 0x7f) << shift)
+      pos += 1
+      if not (b & 0x80):
+        if result > 0x7fffffffffffffff:
+          result -= (1 << 64)
+          result |= ~mask
+        else:
+          result &= mask
+        result = result_type(result)
+        return (result, pos)
+      shift += 7
+      if shift >= 64:
+        raise _DecodeError('Too many bytes when decoding varint.')
+  return DecodeVarint
+
+# We force 32-bit values to int and 64-bit values to long to make
+# alternate implementations where the distinction is more significant
+# (e.g. the C++ implementation) simpler.
+
+_DecodeVarint = _VarintDecoder((1 << 64) - 1, long)
+_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1, long)
+
+# Use these versions for values which must be limited to 32 bits.
+_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int)
+_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1, int)
+
+
+def ReadTag(buffer, pos):
+  """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple.
+
+  We return the raw bytes of the tag rather than decoding them.  The raw
+  bytes can then be used to look up the proper decoder.  This effectively allows
+  us to trade some work that would be done in pure-python (decoding a varint)
+  for work that is done in C (searching for a byte string in a hash table).
+  In a low-level language it would be much cheaper to decode the varint and
+  use that, but not in Python.
+  """
+
+  start = pos
+  while six.indexbytes(buffer, pos) & 0x80:
+    pos += 1
+  pos += 1
+  return (buffer[start:pos], pos)
+
+
+# --------------------------------------------------------------------
+
+
+def _SimpleDecoder(wire_type, decode_value):
+  """Return a constructor for a decoder for fields of a particular type.
+
+  Args:
+      wire_type:  The field's wire type.
+      decode_value:  A function which decodes an individual value, e.g.
+        _DecodeVarint()
+  """
+
+  def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default):
+    if is_packed:
+      local_DecodeVarint = _DecodeVarint
+      def DecodePackedField(buffer, pos, end, message, field_dict):
+        value = field_dict.get(key)
+        if value is None:
+          value = field_dict.setdefault(key, new_default(message))
+        (endpoint, pos) = local_DecodeVarint(buffer, pos)
+        endpoint += pos
+        if endpoint > end:
+          raise _DecodeError('Truncated message.')
+        while pos < endpoint:
+          (element, pos) = decode_value(buffer, pos)
+          value.append(element)
+        if pos > endpoint:
+          del value[-1]   # Discard corrupt value.
+          raise _DecodeError('Packed element was truncated.')
+        return pos
+      return DecodePackedField
+    elif is_repeated:
+      tag_bytes = encoder.TagBytes(field_number, wire_type)
+      tag_len = len(tag_bytes)
+      def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+        value = field_dict.get(key)
+        if value is None:
+          value = field_dict.setdefault(key, new_default(message))
+        while 1:
+          (element, new_pos) = decode_value(buffer, pos)
+          value.append(element)
+          # Predict that the next tag is another copy of the same repeated
+          # field.
+          pos = new_pos + tag_len
+          if buffer[new_pos:pos] != tag_bytes or new_pos >= end:
+            # Prediction failed.  Return.
+            if new_pos > end:
+              raise _DecodeError('Truncated message.')
+            return new_pos
+      return DecodeRepeatedField
+    else:
+      def DecodeField(buffer, pos, end, message, field_dict):
+        (field_dict[key], pos) = decode_value(buffer, pos)
+        if pos > end:
+          del field_dict[key]  # Discard corrupt value.
+          raise _DecodeError('Truncated message.')
+        return pos
+      return DecodeField
+
+  return SpecificDecoder
+
+
+def _ModifiedDecoder(wire_type, decode_value, modify_value):
+  """Like SimpleDecoder but additionally invokes modify_value on every value
+  before storing it.  Usually modify_value is ZigZagDecode.
+  """
+
+  # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
+  # not enough to make a significant difference.
+
+  def InnerDecode(buffer, pos):
+    (result, new_pos) = decode_value(buffer, pos)
+    return (modify_value(result), new_pos)
+  return _SimpleDecoder(wire_type, InnerDecode)
+
+
+def _StructPackDecoder(wire_type, format):
+  """Return a constructor for a decoder for a fixed-width field.
+
+  Args:
+      wire_type:  The field's wire type.
+      format:  The format string to pass to struct.unpack().
+  """
+
+  value_size = struct.calcsize(format)
+  local_unpack = struct.unpack
+
+  # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
+  # not enough to make a significant difference.
+
+  # Note that we expect someone up-stack to catch struct.error and convert
+  # it to _DecodeError -- this way we don't have to set up exception-
+  # handling blocks every time we parse one value.
+
+  def InnerDecode(buffer, pos):
+    new_pos = pos + value_size
+    result = local_unpack(format, buffer[pos:new_pos])[0]
+    return (result, new_pos)
+  return _SimpleDecoder(wire_type, InnerDecode)
+
+
+def _FloatDecoder():
+  """Returns a decoder for a float field.
+
+  This code works around a bug in struct.unpack for non-finite 32-bit
+  floating-point values.
+  """
+
+  local_unpack = struct.unpack
+
+  def InnerDecode(buffer, pos):
+    # We expect a 32-bit value in little-endian byte order.  Bit 1 is the sign
+    # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand.
+    new_pos = pos + 4
+    float_bytes = buffer[pos:new_pos]
+
+    # If this value has all its exponent bits set, then it's non-finite.
+    # In Python 2.4, struct.unpack will convert it to a finite 64-bit value.
+    # To avoid that, we parse it specially.
+    if (float_bytes[3:4] in b'\x7F\xFF' and float_bytes[2:3] >= b'\x80'):
+      # If at least one significand bit is set...
+      if float_bytes[0:3] != b'\x00\x00\x80':
+        return (_NAN, new_pos)
+      # If sign bit is set...
+      if float_bytes[3:4] == b'\xFF':
+        return (_NEG_INF, new_pos)
+      return (_POS_INF, new_pos)
+
+    # Note that we expect someone up-stack to catch struct.error and convert
+    # it to _DecodeError -- this way we don't have to set up exception-
+    # handling blocks every time we parse one value.
+    result = local_unpack('<f', float_bytes)[0]
+    return (result, new_pos)
+  return _SimpleDecoder(wire_format.WIRETYPE_FIXED32, InnerDecode)
+
+
+def _DoubleDecoder():
+  """Returns a decoder for a double field.
+
+  This code works around a bug in struct.unpack for not-a-number.
+  """
+
+  local_unpack = struct.unpack
+
+  def InnerDecode(buffer, pos):
+    # We expect a 64-bit value in little-endian byte order.  Bit 1 is the sign
+    # bit, bits 2-12 represent the exponent, and bits 13-64 are the significand.
+    new_pos = pos + 8
+    double_bytes = buffer[pos:new_pos]
+
+    # If this value has all its exponent bits set and at least one significand
+    # bit set, it's not a number.  In Python 2.4, struct.unpack will treat it
+    # as inf or -inf.  To avoid that, we treat it specially.
+    if ((double_bytes[7:8] in b'\x7F\xFF')
+        and (double_bytes[6:7] >= b'\xF0')
+        and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')):
+      return (_NAN, new_pos)
+
+    # Note that we expect someone up-stack to catch struct.error and convert
+    # it to _DecodeError -- this way we don't have to set up exception-
+    # handling blocks every time we parse one value.
+    result = local_unpack('<d', double_bytes)[0]
+    return (result, new_pos)
+  return _SimpleDecoder(wire_format.WIRETYPE_FIXED64, InnerDecode)
+
+
+def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
+  enum_type = key.enum_type
+  if is_packed:
+    local_DecodeVarint = _DecodeVarint
+    def DecodePackedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      (endpoint, pos) = local_DecodeVarint(buffer, pos)
+      endpoint += pos
+      if endpoint > end:
+        raise _DecodeError('Truncated message.')
+      while pos < endpoint:
+        value_start_pos = pos
+        (element, pos) = _DecodeSignedVarint32(buffer, pos)
+        if element in enum_type.values_by_number:
+          value.append(element)
+        else:
+          if not message._unknown_fields:
+            message._unknown_fields = []
+          tag_bytes = encoder.TagBytes(field_number,
+                                       wire_format.WIRETYPE_VARINT)
+          message._unknown_fields.append(
+              (tag_bytes, buffer[value_start_pos:pos]))
+      if pos > endpoint:
+        if element in enum_type.values_by_number:
+          del value[-1]   # Discard corrupt value.
+        else:
+          del message._unknown_fields[-1]
+        raise _DecodeError('Packed element was truncated.')
+      return pos
+    return DecodePackedField
+  elif is_repeated:
+    tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT)
+    tag_len = len(tag_bytes)
+    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      while 1:
+        (element, new_pos) = _DecodeSignedVarint32(buffer, pos)
+        if element in enum_type.values_by_number:
+          value.append(element)
+        else:
+          if not message._unknown_fields:
+            message._unknown_fields = []
+          message._unknown_fields.append(
+              (tag_bytes, buffer[pos:new_pos]))
+        # Predict that the next tag is another copy of the same repeated
+        # field.
+        pos = new_pos + tag_len
+        if buffer[new_pos:pos] != tag_bytes or new_pos >= end:
+          # Prediction failed.  Return.
+          if new_pos > end:
+            raise _DecodeError('Truncated message.')
+          return new_pos
+    return DecodeRepeatedField
+  else:
+    def DecodeField(buffer, pos, end, message, field_dict):
+      value_start_pos = pos
+      (enum_value, pos) = _DecodeSignedVarint32(buffer, pos)
+      if pos > end:
+        raise _DecodeError('Truncated message.')
+      if enum_value in enum_type.values_by_number:
+        field_dict[key] = enum_value
+      else:
+        if not message._unknown_fields:
+          message._unknown_fields = []
+        tag_bytes = encoder.TagBytes(field_number,
+                                     wire_format.WIRETYPE_VARINT)
+        message._unknown_fields.append(
+          (tag_bytes, buffer[value_start_pos:pos]))
+      return pos
+    return DecodeField
+
+
+# --------------------------------------------------------------------
+
+
+Int32Decoder = _SimpleDecoder(
+    wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32)
+
+Int64Decoder = _SimpleDecoder(
+    wire_format.WIRETYPE_VARINT, _DecodeSignedVarint)
+
+UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32)
+UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint)
+
+SInt32Decoder = _ModifiedDecoder(
+    wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode)
+SInt64Decoder = _ModifiedDecoder(
+    wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode)
+
+# Note that Python conveniently guarantees that when using the '<' prefix on
+# formats, they will also have the same size across all platforms (as opposed
+# to without the prefix, where their sizes depend on the C compiler's basic
+# type sizes).
+Fixed32Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<I')
+Fixed64Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<Q')
+SFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<i')
+SFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<q')
+FloatDecoder = _FloatDecoder()
+DoubleDecoder = _DoubleDecoder()
+
+BoolDecoder = _ModifiedDecoder(
+    wire_format.WIRETYPE_VARINT, _DecodeVarint, bool)
+
+
+def StringDecoder(field_number, is_repeated, is_packed, key, new_default):
+  """Returns a decoder for a string field."""
+
+  local_DecodeVarint = _DecodeVarint
+  local_unicode = six.text_type
+
+  def _ConvertToUnicode(byte_str):
+    try:
+      return local_unicode(byte_str, 'utf-8')
+    except UnicodeDecodeError as e:
+      # add more information to the error message and re-raise it.
+      e.reason = '%s in field: %s' % (e, key.full_name)
+      raise
+
+  assert not is_packed
+  if is_repeated:
+    tag_bytes = encoder.TagBytes(field_number,
+                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
+    tag_len = len(tag_bytes)
+    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      while 1:
+        (size, pos) = local_DecodeVarint(buffer, pos)
+        new_pos = pos + size
+        if new_pos > end:
+          raise _DecodeError('Truncated string.')
+        value.append(_ConvertToUnicode(buffer[pos:new_pos]))
+        # Predict that the next tag is another copy of the same repeated field.
+        pos = new_pos + tag_len
+        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+          # Prediction failed.  Return.
+          return new_pos
+    return DecodeRepeatedField
+  else:
+    def DecodeField(buffer, pos, end, message, field_dict):
+      (size, pos) = local_DecodeVarint(buffer, pos)
+      new_pos = pos + size
+      if new_pos > end:
+        raise _DecodeError('Truncated string.')
+      field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos])
+      return new_pos
+    return DecodeField
+
+
+def BytesDecoder(field_number, is_repeated, is_packed, key, new_default):
+  """Returns a decoder for a bytes field."""
+
+  local_DecodeVarint = _DecodeVarint
+
+  assert not is_packed
+  if is_repeated:
+    tag_bytes = encoder.TagBytes(field_number,
+                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
+    tag_len = len(tag_bytes)
+    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      while 1:
+        (size, pos) = local_DecodeVarint(buffer, pos)
+        new_pos = pos + size
+        if new_pos > end:
+          raise _DecodeError('Truncated string.')
+        value.append(buffer[pos:new_pos])
+        # Predict that the next tag is another copy of the same repeated field.
+        pos = new_pos + tag_len
+        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+          # Prediction failed.  Return.
+          return new_pos
+    return DecodeRepeatedField
+  else:
+    def DecodeField(buffer, pos, end, message, field_dict):
+      (size, pos) = local_DecodeVarint(buffer, pos)
+      new_pos = pos + size
+      if new_pos > end:
+        raise _DecodeError('Truncated string.')
+      field_dict[key] = buffer[pos:new_pos]
+      return new_pos
+    return DecodeField
+
+
+def GroupDecoder(field_number, is_repeated, is_packed, key, new_default):
+  """Returns a decoder for a group field."""
+
+  end_tag_bytes = encoder.TagBytes(field_number,
+                                   wire_format.WIRETYPE_END_GROUP)
+  end_tag_len = len(end_tag_bytes)
+
+  assert not is_packed
+  if is_repeated:
+    tag_bytes = encoder.TagBytes(field_number,
+                                 wire_format.WIRETYPE_START_GROUP)
+    tag_len = len(tag_bytes)
+    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      while 1:
+        value = field_dict.get(key)
+        if value is None:
+          value = field_dict.setdefault(key, new_default(message))
+        # Read sub-message.
+        pos = value.add()._InternalParse(buffer, pos, end)
+        # Read end tag.
+        new_pos = pos+end_tag_len
+        if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
+          raise _DecodeError('Missing group end tag.')
+        # Predict that the next tag is another copy of the same repeated field.
+        pos = new_pos + tag_len
+        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+          # Prediction failed.  Return.
+          return new_pos
+    return DecodeRepeatedField
+  else:
+    def DecodeField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      # Read sub-message.
+      pos = value._InternalParse(buffer, pos, end)
+      # Read end tag.
+      new_pos = pos+end_tag_len
+      if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
+        raise _DecodeError('Missing group end tag.')
+      return new_pos
+    return DecodeField
+
+
+def MessageDecoder(field_number, is_repeated, is_packed, key, new_default):
+  """Returns a decoder for a message field."""
+
+  local_DecodeVarint = _DecodeVarint
+
+  assert not is_packed
+  if is_repeated:
+    tag_bytes = encoder.TagBytes(field_number,
+                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
+    tag_len = len(tag_bytes)
+    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      while 1:
+        # Read length.
+        (size, pos) = local_DecodeVarint(buffer, pos)
+        new_pos = pos + size
+        if new_pos > end:
+          raise _DecodeError('Truncated message.')
+        # Read sub-message.
+        if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:
+          # The only reason _InternalParse would return early is if it
+          # encountered an end-group tag.
+          raise _DecodeError('Unexpected end-group tag.')
+        # Predict that the next tag is another copy of the same repeated field.
+        pos = new_pos + tag_len
+        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+          # Prediction failed.  Return.
+          return new_pos
+    return DecodeRepeatedField
+  else:
+    def DecodeField(buffer, pos, end, message, field_dict):
+      value = field_dict.get(key)
+      if value is None:
+        value = field_dict.setdefault(key, new_default(message))
+      # Read length.
+      (size, pos) = local_DecodeVarint(buffer, pos)
+      new_pos = pos + size
+      if new_pos > end:
+        raise _DecodeError('Truncated message.')
+      # Read sub-message.
+      if value._InternalParse(buffer, pos, new_pos) != new_pos:
+        # The only reason _InternalParse would return early is if it encountered
+        # an end-group tag.
+        raise _DecodeError('Unexpected end-group tag.')
+      return new_pos
+    return DecodeField
+
+
+# --------------------------------------------------------------------
+
+MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP)
+
+def MessageSetItemDecoder(extensions_by_number):
+  """Returns a decoder for a MessageSet item.
+
+  The parameter is the _extensions_by_number map for the message class.
+
+  The message set message looks like this:
+    message MessageSet {
+      repeated group Item = 1 {
+        required int32 type_id = 2;
+        required string message = 3;
+      }
+    }
+  """
+
+  type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT)
+  message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)
+  item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP)
+
+  local_ReadTag = ReadTag
+  local_DecodeVarint = _DecodeVarint
+  local_SkipField = SkipField
+
+  def DecodeItem(buffer, pos, end, message, field_dict):
+    message_set_item_start = pos
+    type_id = -1
+    message_start = -1
+    message_end = -1
+
+    # Technically, type_id and message can appear in any order, so we need
+    # a little loop here.
+    while 1:
+      (tag_bytes, pos) = local_ReadTag(buffer, pos)
+      if tag_bytes == type_id_tag_bytes:
+        (type_id, pos) = local_DecodeVarint(buffer, pos)
+      elif tag_bytes == message_tag_bytes:
+        (size, message_start) = local_DecodeVarint(buffer, pos)
+        pos = message_end = message_start + size
+      elif tag_bytes == item_end_tag_bytes:
+        break
+      else:
+        pos = SkipField(buffer, pos, end, tag_bytes)
+        if pos == -1:
+          raise _DecodeError('Missing group end tag.')
+
+    if pos > end:
+      raise _DecodeError('Truncated message.')
+
+    if type_id == -1:
+      raise _DecodeError('MessageSet item missing type_id.')
+    if message_start == -1:
+      raise _DecodeError('MessageSet item missing message.')
+
+    extension = extensions_by_number.get(type_id)
+    if extension is not None:
+      value = field_dict.get(extension)
+      if value is None:
+        value = field_dict.setdefault(
+            extension, extension.message_type._concrete_class())
+      if value._InternalParse(buffer, message_start,message_end) != message_end:
+        # The only reason _InternalParse would return early is if it encountered
+        # an end-group tag.
+        raise _DecodeError('Unexpected end-group tag.')
+    else:
+      if not message._unknown_fields:
+        message._unknown_fields = []
+      message._unknown_fields.append((MESSAGE_SET_ITEM_TAG,
+                                      buffer[message_set_item_start:pos]))
+
+    return pos
+
+  return DecodeItem
+
+# --------------------------------------------------------------------
+
+def MapDecoder(field_descriptor, new_default, is_message_map):
+  """Returns a decoder for a map field."""
+
+  key = field_descriptor
+  tag_bytes = encoder.TagBytes(field_descriptor.number,
+                               wire_format.WIRETYPE_LENGTH_DELIMITED)
+  tag_len = len(tag_bytes)
+  local_DecodeVarint = _DecodeVarint
+  # Can't read _concrete_class yet; might not be initialized.
+  message_type = field_descriptor.message_type
+
+  def DecodeMap(buffer, pos, end, message, field_dict):
+    submsg = message_type._concrete_class()
+    value = field_dict.get(key)
+    if value is None:
+      value = field_dict.setdefault(key, new_default(message))
+    while 1:
+      # Read length.
+      (size, pos) = local_DecodeVarint(buffer, pos)
+      new_pos = pos + size
+      if new_pos > end:
+        raise _DecodeError('Truncated message.')
+      # Read sub-message.
+      submsg.Clear()
+      if submsg._InternalParse(buffer, pos, new_pos) != new_pos:
+        # The only reason _InternalParse would return early is if it
+        # encountered an end-group tag.
+        raise _DecodeError('Unexpected end-group tag.')
+
+      if is_message_map:
+        value[submsg.key].MergeFrom(submsg.value)
+      else:
+        value[submsg.key] = submsg.value
+
+      # Predict that the next tag is another copy of the same repeated field.
+      pos = new_pos + tag_len
+      if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+        # Prediction failed.  Return.
+        return new_pos
+
+  return DecodeMap
+
+# --------------------------------------------------------------------
+# Optimization is not as heavy here because calls to SkipField() are rare,
+# except for handling end-group tags.
+
+def _SkipVarint(buffer, pos, end):
+  """Skip a varint value.  Returns the new position."""
+  # Previously ord(buffer[pos]) raised IndexError when pos is out of range.
+  # With this code, ord(b'') raises TypeError.  Both are handled in
+  # python_message.py to generate a 'Truncated message' error.
+  while ord(buffer[pos:pos+1]) & 0x80:
+    pos += 1
+  pos += 1
+  if pos > end:
+    raise _DecodeError('Truncated message.')
+  return pos
+
+def _SkipFixed64(buffer, pos, end):
+  """Skip a fixed64 value.  Returns the new position."""
+
+  pos += 8
+  if pos > end:
+    raise _DecodeError('Truncated message.')
+  return pos
+
+def _SkipLengthDelimited(buffer, pos, end):
+  """Skip a length-delimited value.  Returns the new position."""
+
+  (size, pos) = _DecodeVarint(buffer, pos)
+  pos += size
+  if pos > end:
+    raise _DecodeError('Truncated message.')
+  return pos
+
+def _SkipGroup(buffer, pos, end):
+  """Skip sub-group.  Returns the new position."""
+
+  while 1:
+    (tag_bytes, pos) = ReadTag(buffer, pos)
+    new_pos = SkipField(buffer, pos, end, tag_bytes)
+    if new_pos == -1:
+      return pos
+    pos = new_pos
+
+def _EndGroup(buffer, pos, end):
+  """Skipping an END_GROUP tag returns -1 to tell the parent loop to break."""
+
+  return -1
+
+def _SkipFixed32(buffer, pos, end):
+  """Skip a fixed32 value.  Returns the new position."""
+
+  pos += 4
+  if pos > end:
+    raise _DecodeError('Truncated message.')
+  return pos
+
+def _RaiseInvalidWireType(buffer, pos, end):
+  """Skip function for unknown wire types.  Raises an exception."""
+
+  raise _DecodeError('Tag had invalid wire type.')
+
+def _FieldSkipper():
+  """Constructs the SkipField function."""
+
+  WIRETYPE_TO_SKIPPER = [
+      _SkipVarint,
+      _SkipFixed64,
+      _SkipLengthDelimited,
+      _SkipGroup,
+      _EndGroup,
+      _SkipFixed32,
+      _RaiseInvalidWireType,
+      _RaiseInvalidWireType,
+      ]
+
+  wiretype_mask = wire_format.TAG_TYPE_MASK
+
+  def SkipField(buffer, pos, end, tag_bytes):
+    """Skips a field with the specified tag.
+
+    |pos| should point to the byte immediately after the tag.
+
+    Returns:
+        The new position (after the tag value), or -1 if the tag is an end-group
+        tag (in which case the calling loop should break).
+    """
+
+    # The wire type is always in the first byte since varints are little-endian.
+    wire_type = ord(tag_bytes[0:1]) & wiretype_mask
+    return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)
+
+  return SkipField
+
+SkipField = _FieldSkipper()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_database_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_database_test.py
new file mode 100644
index 0000000..5225a45
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_database_test.py
@@ -0,0 +1,69 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.descriptor_database."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+
+
+class DescriptorDatabaseTest(unittest.TestCase):
+
+  def testAdd(self):
+    db = descriptor_database.DescriptorDatabase()
+    file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+    db.Add(file_desc_proto)
+
+    self.assertEqual(file_desc_proto, db.FindFileByName(
+        'google/protobuf/internal/factory_test2.proto'))
+    self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory2Message.NestedFactory2Message'))
+    self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory2Enum'))
+    self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum'))
+    self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
+        'google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum'))
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test.py
new file mode 100644
index 0000000..6a13e0b
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test.py
@@ -0,0 +1,750 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.descriptor_pool."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import os
+import sys
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_import_public_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import descriptor_pool_test1_pb2
+from google.protobuf.internal import descriptor_pool_test2_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf.internal import more_messages_pb2
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
+from google.protobuf import symbol_database
+
+
+class DescriptorPoolTest(unittest.TestCase):
+
+  def setUp(self):
+    self.pool = descriptor_pool.DescriptorPool()
+    self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test1_pb2.DESCRIPTOR.serialized_pb)
+    self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+    self.pool.Add(self.factory_test1_fd)
+    self.pool.Add(self.factory_test2_fd)
+
+  def testFindFileByName(self):
+    name1 = 'google/protobuf/internal/factory_test1.proto'
+    file_desc1 = self.pool.FindFileByName(name1)
+    self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+    self.assertEqual(name1, file_desc1.name)
+    self.assertEqual('google.protobuf.python.internal', file_desc1.package)
+    self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+    name2 = 'google/protobuf/internal/factory_test2.proto'
+    file_desc2 = self.pool.FindFileByName(name2)
+    self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+    self.assertEqual(name2, file_desc2.name)
+    self.assertEqual('google.protobuf.python.internal', file_desc2.package)
+    self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+  def testFindFileByNameFailure(self):
+    with self.assertRaises(KeyError):
+      self.pool.FindFileByName('Does not exist')
+
+  def testFindFileContainingSymbol(self):
+    file_desc1 = self.pool.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory1Message')
+    self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+    self.assertEqual('google/protobuf/internal/factory_test1.proto',
+                     file_desc1.name)
+    self.assertEqual('google.protobuf.python.internal', file_desc1.package)
+    self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+    file_desc2 = self.pool.FindFileContainingSymbol(
+        'google.protobuf.python.internal.Factory2Message')
+    self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+    self.assertEqual('google/protobuf/internal/factory_test2.proto',
+                     file_desc2.name)
+    self.assertEqual('google.protobuf.python.internal', file_desc2.package)
+    self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+  def testFindFileContainingSymbolFailure(self):
+    with self.assertRaises(KeyError):
+      self.pool.FindFileContainingSymbol('Does not exist')
+
+  def testFindMessageTypeByName(self):
+    msg1 = self.pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory1Message')
+    self.assertIsInstance(msg1, descriptor.Descriptor)
+    self.assertEqual('Factory1Message', msg1.name)
+    self.assertEqual('google.protobuf.python.internal.Factory1Message',
+                     msg1.full_name)
+    self.assertEqual(None, msg1.containing_type)
+
+    nested_msg1 = msg1.nested_types[0]
+    self.assertEqual('NestedFactory1Message', nested_msg1.name)
+    self.assertEqual(msg1, nested_msg1.containing_type)
+
+    nested_enum1 = msg1.enum_types[0]
+    self.assertEqual('NestedFactory1Enum', nested_enum1.name)
+    self.assertEqual(msg1, nested_enum1.containing_type)
+
+    self.assertEqual(nested_msg1, msg1.fields_by_name[
+        'nested_factory_1_message'].message_type)
+    self.assertEqual(nested_enum1, msg1.fields_by_name[
+        'nested_factory_1_enum'].enum_type)
+
+    msg2 = self.pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message')
+    self.assertIsInstance(msg2, descriptor.Descriptor)
+    self.assertEqual('Factory2Message', msg2.name)
+    self.assertEqual('google.protobuf.python.internal.Factory2Message',
+                     msg2.full_name)
+    self.assertIsNone(msg2.containing_type)
+
+    nested_msg2 = msg2.nested_types[0]
+    self.assertEqual('NestedFactory2Message', nested_msg2.name)
+    self.assertEqual(msg2, nested_msg2.containing_type)
+
+    nested_enum2 = msg2.enum_types[0]
+    self.assertEqual('NestedFactory2Enum', nested_enum2.name)
+    self.assertEqual(msg2, nested_enum2.containing_type)
+
+    self.assertEqual(nested_msg2, msg2.fields_by_name[
+        'nested_factory_2_message'].message_type)
+    self.assertEqual(nested_enum2, msg2.fields_by_name[
+        'nested_factory_2_enum'].enum_type)
+
+    self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value)
+    self.assertEqual(
+        1776, msg2.fields_by_name['int_with_default'].default_value)
+
+    self.assertTrue(
+        msg2.fields_by_name['double_with_default'].has_default_value)
+    self.assertEqual(
+        9.99, msg2.fields_by_name['double_with_default'].default_value)
+
+    self.assertTrue(
+        msg2.fields_by_name['string_with_default'].has_default_value)
+    self.assertEqual(
+        'hello world', msg2.fields_by_name['string_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value)
+    self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value)
+    self.assertEqual(
+        1, msg2.fields_by_name['enum_with_default'].default_value)
+
+    msg3 = self.pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message.NestedFactory2Message')
+    self.assertEqual(nested_msg2, msg3)
+
+    self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value)
+    self.assertEqual(
+        b'a\xfb\x00c',
+        msg2.fields_by_name['bytes_with_default'].default_value)
+
+    self.assertEqual(1, len(msg2.oneofs))
+    self.assertEqual(1, len(msg2.oneofs_by_name))
+    self.assertEqual(2, len(msg2.oneofs[0].fields))
+    for name in ['oneof_int', 'oneof_string']:
+      self.assertEqual(msg2.oneofs[0],
+                       msg2.fields_by_name[name].containing_oneof)
+      self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields)
+
+  def testFindMessageTypeByNameFailure(self):
+    with self.assertRaises(KeyError):
+      self.pool.FindMessageTypeByName('Does not exist')
+
+  def testFindEnumTypeByName(self):
+    enum1 = self.pool.FindEnumTypeByName(
+        'google.protobuf.python.internal.Factory1Enum')
+    self.assertIsInstance(enum1, descriptor.EnumDescriptor)
+    self.assertEqual(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number)
+    self.assertEqual(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number)
+
+    nested_enum1 = self.pool.FindEnumTypeByName(
+        'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum')
+    self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor)
+    self.assertEqual(
+        0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number)
+    self.assertEqual(
+        1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number)
+
+    enum2 = self.pool.FindEnumTypeByName(
+        'google.protobuf.python.internal.Factory2Enum')
+    self.assertIsInstance(enum2, descriptor.EnumDescriptor)
+    self.assertEqual(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number)
+    self.assertEqual(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number)
+
+    nested_enum2 = self.pool.FindEnumTypeByName(
+        'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum')
+    self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor)
+    self.assertEqual(
+        0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number)
+    self.assertEqual(
+        1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number)
+
+  def testFindEnumTypeByNameFailure(self):
+    with self.assertRaises(KeyError):
+      self.pool.FindEnumTypeByName('Does not exist')
+
+  def testFindFieldByName(self):
+    field = self.pool.FindFieldByName(
+        'google.protobuf.python.internal.Factory1Message.list_value')
+    self.assertEqual(field.name, 'list_value')
+    self.assertEqual(field.label, field.LABEL_REPEATED)
+    with self.assertRaises(KeyError):
+      self.pool.FindFieldByName('Does not exist')
+
+  def testFindExtensionByName(self):
+    # An extension defined in a message.
+    extension = self.pool.FindExtensionByName(
+        'google.protobuf.python.internal.Factory2Message.one_more_field')
+    self.assertEqual(extension.name, 'one_more_field')
+    # An extension defined at file scope.
+    extension = self.pool.FindExtensionByName(
+        'google.protobuf.python.internal.another_field')
+    self.assertEqual(extension.name, 'another_field')
+    self.assertEqual(extension.number, 1002)
+    with self.assertRaises(KeyError):
+      self.pool.FindFieldByName('Does not exist')
+
+  def testExtensionsAreNotFields(self):
+    with self.assertRaises(KeyError):
+      self.pool.FindFieldByName('google.protobuf.python.internal.another_field')
+    with self.assertRaises(KeyError):
+      self.pool.FindFieldByName(
+          'google.protobuf.python.internal.Factory2Message.one_more_field')
+    with self.assertRaises(KeyError):
+      self.pool.FindExtensionByName(
+          'google.protobuf.python.internal.Factory1Message.list_value')
+
+  def testUserDefinedDB(self):
+    db = descriptor_database.DescriptorDatabase()
+    self.pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    self.testFindMessageTypeByName()
+
+  def testAddSerializedFile(self):
+    self.pool = descriptor_pool.DescriptorPool()
+    self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString())
+    self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString())
+    self.testFindMessageTypeByName()
+
+  def testComplexNesting(self):
+    more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString(
+        more_messages_pb2.DESCRIPTOR.serialized_pb)
+    test1_desc = descriptor_pb2.FileDescriptorProto.FromString(
+        descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb)
+    test2_desc = descriptor_pb2.FileDescriptorProto.FromString(
+        descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb)
+    self.pool.Add(more_messages_desc)
+    self.pool.Add(test1_desc)
+    self.pool.Add(test2_desc)
+    TEST1_FILE.CheckFile(self, self.pool)
+    TEST2_FILE.CheckFile(self, self.pool)
+
+
+  def testEnumDefaultValue(self):
+    """Test the default value of enums which don't start at zero."""
+    def _CheckDefaultValue(file_descriptor):
+      default_value = (file_descriptor
+                       .message_types_by_name['DescriptorPoolTest1']
+                       .fields_by_name['nested_enum']
+                       .default_value)
+      self.assertEqual(default_value,
+                       descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA)
+    # First check what the generated descriptor contains.
+    _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR)
+    # Then check the generated pool. Normally this is the same descriptor.
+    file_descriptor = symbol_database.Default().pool.FindFileByName(
+        'google/protobuf/internal/descriptor_pool_test1.proto')
+    self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR)
+    _CheckDefaultValue(file_descriptor)
+
+    # Then check the dynamic pool and its internal DescriptorDatabase.
+    descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString(
+        descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb)
+    self.pool.Add(descriptor_proto)
+    # And do the same check as above
+    file_descriptor = self.pool.FindFileByName(
+        'google/protobuf/internal/descriptor_pool_test1.proto')
+    _CheckDefaultValue(file_descriptor)
+
+  def testDefaultValueForCustomMessages(self):
+    """Check the value returned by non-existent fields."""
+    def _CheckValueAndType(value, expected_value, expected_type):
+      self.assertEqual(value, expected_value)
+      self.assertIsInstance(value, expected_type)
+
+    def _CheckDefaultValues(msg):
+      try:
+        int64 = long
+      except NameError:  # Python3
+        int64 = int
+      try:
+        unicode_type = unicode
+      except NameError:  # Python3
+        unicode_type = str
+      _CheckValueAndType(msg.optional_int32, 0, int)
+      _CheckValueAndType(msg.optional_uint64, 0, (int64, int))
+      _CheckValueAndType(msg.optional_float, 0, (float, int))
+      _CheckValueAndType(msg.optional_double, 0, (float, int))
+      _CheckValueAndType(msg.optional_bool, False, bool)
+      _CheckValueAndType(msg.optional_string, u'', unicode_type)
+      _CheckValueAndType(msg.optional_bytes, b'', bytes)
+      _CheckValueAndType(msg.optional_nested_enum, msg.FOO, int)
+    # First for the generated message
+    _CheckDefaultValues(unittest_pb2.TestAllTypes())
+    # Then for a message built with from the DescriptorPool.
+    pool = descriptor_pool.DescriptorPool()
+    pool.Add(descriptor_pb2.FileDescriptorProto.FromString(
+        unittest_import_public_pb2.DESCRIPTOR.serialized_pb))
+    pool.Add(descriptor_pb2.FileDescriptorProto.FromString(
+        unittest_import_pb2.DESCRIPTOR.serialized_pb))
+    pool.Add(descriptor_pb2.FileDescriptorProto.FromString(
+        unittest_pb2.DESCRIPTOR.serialized_pb))
+    message_class = message_factory.MessageFactory(pool).GetPrototype(
+        pool.FindMessageTypeByName(
+            unittest_pb2.TestAllTypes.DESCRIPTOR.full_name))
+    _CheckDefaultValues(message_class())
+
+
+class ProtoFile(object):
+
+  def __init__(self, name, package, messages, dependencies=None,
+               public_dependencies=None):
+    self.name = name
+    self.package = package
+    self.messages = messages
+    self.dependencies = dependencies or []
+    self.public_dependencies = public_dependencies or []
+
+  def CheckFile(self, test, pool):
+    file_desc = pool.FindFileByName(self.name)
+    test.assertEqual(self.name, file_desc.name)
+    test.assertEqual(self.package, file_desc.package)
+    dependencies_names = [f.name for f in file_desc.dependencies]
+    test.assertEqual(self.dependencies, dependencies_names)
+    public_dependencies_names = [f.name for f in file_desc.public_dependencies]
+    test.assertEqual(self.public_dependencies, public_dependencies_names)
+    for name, msg_type in self.messages.items():
+      msg_type.CheckType(test, None, name, file_desc)
+
+
+class EnumType(object):
+
+  def __init__(self, values):
+    self.values = values
+
+  def CheckType(self, test, msg_desc, name, file_desc):
+    enum_desc = msg_desc.enum_types_by_name[name]
+    test.assertEqual(name, enum_desc.name)
+    expected_enum_full_name = '.'.join([msg_desc.full_name, name])
+    test.assertEqual(expected_enum_full_name, enum_desc.full_name)
+    test.assertEqual(msg_desc, enum_desc.containing_type)
+    test.assertEqual(file_desc, enum_desc.file)
+    for index, (value, number) in enumerate(self.values):
+      value_desc = enum_desc.values_by_name[value]
+      test.assertEqual(value, value_desc.name)
+      test.assertEqual(index, value_desc.index)
+      test.assertEqual(number, value_desc.number)
+      test.assertEqual(enum_desc, value_desc.type)
+      test.assertIn(value, msg_desc.enum_values_by_name)
+
+
+class MessageType(object):
+
+  def __init__(self, type_dict, field_list, is_extendable=False,
+               extensions=None):
+    self.type_dict = type_dict
+    self.field_list = field_list
+    self.is_extendable = is_extendable
+    self.extensions = extensions or []
+
+  def CheckType(self, test, containing_type_desc, name, file_desc):
+    if containing_type_desc is None:
+      desc = file_desc.message_types_by_name[name]
+      expected_full_name = '.'.join([file_desc.package, name])
+    else:
+      desc = containing_type_desc.nested_types_by_name[name]
+      expected_full_name = '.'.join([containing_type_desc.full_name, name])
+
+    test.assertEqual(name, desc.name)
+    test.assertEqual(expected_full_name, desc.full_name)
+    test.assertEqual(containing_type_desc, desc.containing_type)
+    test.assertEqual(desc.file, file_desc)
+    test.assertEqual(self.is_extendable, desc.is_extendable)
+    for name, subtype in self.type_dict.items():
+      subtype.CheckType(test, desc, name, file_desc)
+
+    for index, (name, field) in enumerate(self.field_list):
+      field.CheckField(test, desc, name, index)
+
+    for index, (name, field) in enumerate(self.extensions):
+      field.CheckField(test, desc, name, index)
+
+
+class EnumField(object):
+
+  def __init__(self, number, type_name, default_value):
+    self.number = number
+    self.type_name = type_name
+    self.default_value = default_value
+
+  def CheckField(self, test, msg_desc, name, index):
+    field_desc = msg_desc.fields_by_name[name]
+    enum_desc = msg_desc.enum_types_by_name[self.type_name]
+    test.assertEqual(name, field_desc.name)
+    expected_field_full_name = '.'.join([msg_desc.full_name, name])
+    test.assertEqual(expected_field_full_name, field_desc.full_name)
+    test.assertEqual(index, field_desc.index)
+    test.assertEqual(self.number, field_desc.number)
+    test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type)
+    test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM,
+                     field_desc.cpp_type)
+    test.assertTrue(field_desc.has_default_value)
+    test.assertEqual(enum_desc.values_by_name[self.default_value].number,
+                     field_desc.default_value)
+    test.assertEqual(msg_desc, field_desc.containing_type)
+    test.assertEqual(enum_desc, field_desc.enum_type)
+
+
+class MessageField(object):
+
+  def __init__(self, number, type_name):
+    self.number = number
+    self.type_name = type_name
+
+  def CheckField(self, test, msg_desc, name, index):
+    field_desc = msg_desc.fields_by_name[name]
+    field_type_desc = msg_desc.nested_types_by_name[self.type_name]
+    test.assertEqual(name, field_desc.name)
+    expected_field_full_name = '.'.join([msg_desc.full_name, name])
+    test.assertEqual(expected_field_full_name, field_desc.full_name)
+    test.assertEqual(index, field_desc.index)
+    test.assertEqual(self.number, field_desc.number)
+    test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type)
+    test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE,
+                     field_desc.cpp_type)
+    test.assertFalse(field_desc.has_default_value)
+    test.assertEqual(msg_desc, field_desc.containing_type)
+    test.assertEqual(field_type_desc, field_desc.message_type)
+
+
+class StringField(object):
+
+  def __init__(self, number, default_value):
+    self.number = number
+    self.default_value = default_value
+
+  def CheckField(self, test, msg_desc, name, index):
+    field_desc = msg_desc.fields_by_name[name]
+    test.assertEqual(name, field_desc.name)
+    expected_field_full_name = '.'.join([msg_desc.full_name, name])
+    test.assertEqual(expected_field_full_name, field_desc.full_name)
+    test.assertEqual(index, field_desc.index)
+    test.assertEqual(self.number, field_desc.number)
+    test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type)
+    test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING,
+                     field_desc.cpp_type)
+    test.assertTrue(field_desc.has_default_value)
+    test.assertEqual(self.default_value, field_desc.default_value)
+
+
+class ExtensionField(object):
+
+  def __init__(self, number, extended_type):
+    self.number = number
+    self.extended_type = extended_type
+
+  def CheckField(self, test, msg_desc, name, index):
+    field_desc = msg_desc.extensions_by_name[name]
+    test.assertEqual(name, field_desc.name)
+    expected_field_full_name = '.'.join([msg_desc.full_name, name])
+    test.assertEqual(expected_field_full_name, field_desc.full_name)
+    test.assertEqual(self.number, field_desc.number)
+    test.assertEqual(index, field_desc.index)
+    test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type)
+    test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE,
+                     field_desc.cpp_type)
+    test.assertFalse(field_desc.has_default_value)
+    test.assertTrue(field_desc.is_extension)
+    test.assertEqual(msg_desc, field_desc.extension_scope)
+    test.assertEqual(msg_desc, field_desc.message_type)
+    test.assertEqual(self.extended_type, field_desc.containing_type.name)
+
+
+class AddDescriptorTest(unittest.TestCase):
+
+  def _TestMessage(self, prefix):
+    pool = descriptor_pool.DescriptorPool()
+    pool.AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes',
+        pool.FindMessageTypeByName(
+            prefix + 'protobuf_unittest.TestAllTypes').full_name)
+
+    # AddDescriptor is not recursive.
+    with self.assertRaises(KeyError):
+      pool.FindMessageTypeByName(
+          prefix + 'protobuf_unittest.TestAllTypes.NestedMessage')
+
+    pool.AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes.NestedMessage',
+        pool.FindMessageTypeByName(
+            prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name)
+
+    # Files are implicitly also indexed when messages are added.
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        pool.FindFileByName(
+            'google/protobuf/unittest.proto').name)
+
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        pool.FindFileContainingSymbol(
+            prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name)
+
+  @unittest.skipIf(api_implementation.Type() == 'cpp',
+                   'With the cpp implementation, Add() must be called first')
+  def testMessage(self):
+    self._TestMessage('')
+    self._TestMessage('.')
+
+  def _TestEnum(self, prefix):
+    pool = descriptor_pool.DescriptorPool()
+    pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
+    self.assertEqual(
+        'protobuf_unittest.ForeignEnum',
+        pool.FindEnumTypeByName(
+            prefix + 'protobuf_unittest.ForeignEnum').full_name)
+
+    # AddEnumDescriptor is not recursive.
+    with self.assertRaises(KeyError):
+      pool.FindEnumTypeByName(
+          prefix + 'protobuf_unittest.ForeignEnum.NestedEnum')
+
+    pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes.NestedEnum',
+        pool.FindEnumTypeByName(
+            prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name)
+
+    # Files are implicitly also indexed when enums are added.
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        pool.FindFileByName(
+            'google/protobuf/unittest.proto').name)
+
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        pool.FindFileContainingSymbol(
+            prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name)
+
+  @unittest.skipIf(api_implementation.Type() == 'cpp',
+                   'With the cpp implementation, Add() must be called first')
+  def testEnum(self):
+    self._TestEnum('')
+    self._TestEnum('.')
+
+  @unittest.skipIf(api_implementation.Type() == 'cpp',
+                   'With the cpp implementation, Add() must be called first')
+  def testFile(self):
+    pool = descriptor_pool.DescriptorPool()
+    pool.AddFileDescriptor(unittest_pb2.DESCRIPTOR)
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        pool.FindFileByName(
+            'google/protobuf/unittest.proto').name)
+
+    # AddFileDescriptor is not recursive; messages and enums within files must
+    # be explicitly registered.
+    with self.assertRaises(KeyError):
+      pool.FindFileContainingSymbol(
+          'protobuf_unittest.TestAllTypes')
+
+  def testEmptyDescriptorPool(self):
+    # Check that an empty DescriptorPool() contains no messages.
+    pool = descriptor_pool.DescriptorPool()
+    proto_file_name = descriptor_pb2.DESCRIPTOR.name
+    self.assertRaises(KeyError, pool.FindFileByName, proto_file_name)
+    # Add the above file to the pool
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor)
+    pool.Add(file_descriptor)
+    # Now it exists.
+    self.assertTrue(pool.FindFileByName(proto_file_name))
+
+  def testCustomDescriptorPool(self):
+    # Create a new pool, and add a file descriptor.
+    pool = descriptor_pool.DescriptorPool()
+    file_desc = descriptor_pb2.FileDescriptorProto(
+        name='some/file.proto', package='package')
+    file_desc.message_type.add(name='Message')
+    pool.Add(file_desc)
+    self.assertEqual(pool.FindFileByName('some/file.proto').name,
+                     'some/file.proto')
+    self.assertEqual(pool.FindMessageTypeByName('package.Message').name,
+                     'Message')
+
+
+@unittest.skipIf(
+    api_implementation.Type() != 'cpp',
+    'default_pool is only supported by the C++ implementation')
+class DefaultPoolTest(unittest.TestCase):
+
+  def testFindMethods(self):
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf.pyext import _message
+    pool = _message.default_pool
+    self.assertIs(
+        pool.FindFileByName('google/protobuf/unittest.proto'),
+        unittest_pb2.DESCRIPTOR)
+    self.assertIs(
+        pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'),
+        unittest_pb2.TestAllTypes.DESCRIPTOR)
+    self.assertIs(
+        pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'),
+        unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32'])
+    self.assertIs(
+        pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'),
+        unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension'])
+    self.assertIs(
+        pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'),
+        unittest_pb2.ForeignEnum.DESCRIPTOR)
+    self.assertIs(
+        pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'),
+        unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field'])
+
+  def testAddFileDescriptor(self):
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf.pyext import _message
+    pool = _message.default_pool
+    file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto')
+    pool.Add(file_desc)
+    pool.AddSerializedFile(file_desc.SerializeToString())
+
+
+TEST1_FILE = ProtoFile(
+    'google/protobuf/internal/descriptor_pool_test1.proto',
+    'google.protobuf.python.internal',
+    {
+        'DescriptorPoolTest1': MessageType({
+            'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]),
+            'NestedMessage': MessageType({
+                'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]),
+                'DeepNestedMessage': MessageType({
+                    'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]),
+                }, [
+                    ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')),
+                    ('nested_field', StringField(2, 'theta')),
+                ]),
+            }, [
+                ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')),
+                ('nested_field', StringField(2, 'beta')),
+                ('deep_nested_message', MessageField(3, 'DeepNestedMessage')),
+            ])
+        }, [
+            ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')),
+            ('nested_message', MessageField(2, 'NestedMessage')),
+        ], is_extendable=True),
+
+        'DescriptorPoolTest2': MessageType({
+            'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]),
+            'NestedMessage': MessageType({
+                'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]),
+                'DeepNestedMessage': MessageType({
+                    'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]),
+                }, [
+                    ('nested_enum', EnumField(1, 'NestedEnum', 'MU')),
+                    ('nested_field', StringField(2, 'lambda')),
+                ]),
+            }, [
+                ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')),
+                ('nested_field', StringField(2, 'delta')),
+                ('deep_nested_message', MessageField(3, 'DeepNestedMessage')),
+            ])
+        }, [
+            ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')),
+            ('nested_message', MessageField(2, 'NestedMessage')),
+        ]),
+    })
+
+
+TEST2_FILE = ProtoFile(
+    'google/protobuf/internal/descriptor_pool_test2.proto',
+    'google.protobuf.python.internal',
+    {
+        'DescriptorPoolTest3': MessageType({
+            'NestedEnum': EnumType([('NU', 13), ('XI', 14)]),
+            'NestedMessage': MessageType({
+                'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]),
+                'DeepNestedMessage': MessageType({
+                    'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]),
+                }, [
+                    ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')),
+                    ('nested_field', StringField(2, 'sigma')),
+                ]),
+            }, [
+                ('nested_enum', EnumField(1, 'NestedEnum', 'PI')),
+                ('nested_field', StringField(2, 'nu')),
+                ('deep_nested_message', MessageField(3, 'DeepNestedMessage')),
+            ])
+        }, [
+            ('nested_enum', EnumField(1, 'NestedEnum', 'XI')),
+            ('nested_message', MessageField(2, 'NestedMessage')),
+        ], extensions=[
+            ('descriptor_pool_test',
+             ExtensionField(1001, 'DescriptorPoolTest1')),
+        ]),
+    },
+    dependencies=['google/protobuf/internal/descriptor_pool_test1.proto',
+                  'google/protobuf/internal/more_messages.proto'],
+    public_dependencies=['google/protobuf/internal/more_messages.proto'])
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test1.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test1.proto
new file mode 100644
index 0000000..00816b7
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test1.proto
@@ -0,0 +1,96 @@
+// 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.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+
+message DescriptorPoolTest1 {
+  extensions 1000 to max;
+
+  enum NestedEnum {
+    ALPHA = 1;
+    BETA = 2;
+  }
+
+  optional NestedEnum nested_enum = 1 [default = BETA];
+
+  message NestedMessage {
+    enum NestedEnum {
+      EPSILON = 5;
+      ZETA = 6;
+    }
+    optional NestedEnum nested_enum = 1 [default = ZETA];
+    optional string nested_field = 2 [default = "beta"];
+    optional DeepNestedMessage deep_nested_message = 3;
+
+    message DeepNestedMessage {
+      enum NestedEnum {
+        ETA = 7;
+        THETA = 8;
+      }
+      optional NestedEnum nested_enum = 1 [default = ETA];
+      optional string nested_field = 2 [default = "theta"];
+    }
+  }
+
+  optional NestedMessage nested_message = 2;
+}
+
+message DescriptorPoolTest2 {
+  enum NestedEnum {
+    GAMMA = 3;
+    DELTA = 4;
+  }
+
+  optional NestedEnum nested_enum = 1 [default = GAMMA];
+
+  message NestedMessage {
+    enum NestedEnum {
+      IOTA = 9;
+      KAPPA = 10;
+    }
+    optional NestedEnum nested_enum = 1 [default = IOTA];
+    optional string nested_field = 2 [default = "delta"];
+    optional DeepNestedMessage deep_nested_message = 3;
+
+    message DeepNestedMessage {
+      enum NestedEnum {
+        LAMBDA = 11;
+        MU = 12;
+      }
+      optional NestedEnum nested_enum = 1 [default = MU];
+      optional string nested_field = 2 [default = "lambda"];
+    }
+  }
+
+  optional NestedMessage nested_message = 2;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test2.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test2.proto
new file mode 100644
index 0000000..a218ecc
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_pool_test2.proto
@@ -0,0 +1,73 @@
+// 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.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+import "google/protobuf/internal/descriptor_pool_test1.proto";
+import public "google/protobuf/internal/more_messages.proto";
+
+
+message DescriptorPoolTest3 {
+
+  extend DescriptorPoolTest1 {
+    optional DescriptorPoolTest3 descriptor_pool_test = 1001;
+  }
+
+  enum NestedEnum {
+    NU = 13;
+    XI = 14;
+  }
+
+  optional NestedEnum nested_enum = 1 [default = XI];
+
+  message NestedMessage {
+    enum NestedEnum {
+      OMICRON = 15;
+      PI = 16;
+    }
+    optional NestedEnum nested_enum = 1 [default = PI];
+    optional string nested_field = 2 [default = "nu"];
+    optional DeepNestedMessage deep_nested_message = 3;
+
+    message DeepNestedMessage {
+      enum NestedEnum {
+        RHO = 17;
+        SIGMA = 18;
+      }
+      optional NestedEnum nested_enum = 1 [default = RHO];
+      optional string nested_field = 2 [default = "sigma"];
+    }
+  }
+
+  optional NestedMessage nested_message = 2;
+}
+
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_test.py
new file mode 100755
index 0000000..b8e7555
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/descriptor_test.py
@@ -0,0 +1,822 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Unittest for google.protobuf.internal.descriptor."""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+import sys
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import test_util
+from google.protobuf import descriptor
+from google.protobuf import descriptor_pool
+from google.protobuf import symbol_database
+from google.protobuf import text_format
+
+
+TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
+name: 'TestEmptyMessage'
+"""
+
+
+class DescriptorTest(unittest.TestCase):
+
+  def setUp(self):
+    file_proto = descriptor_pb2.FileDescriptorProto(
+        name='some/filename/some.proto',
+        package='protobuf_unittest')
+    message_proto = file_proto.message_type.add(
+        name='NestedMessage')
+    message_proto.field.add(
+        name='bb',
+        number=1,
+        type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
+        label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL)
+    enum_proto = message_proto.enum_type.add(
+        name='ForeignEnum')
+    enum_proto.value.add(name='FOREIGN_FOO', number=4)
+    enum_proto.value.add(name='FOREIGN_BAR', number=5)
+    enum_proto.value.add(name='FOREIGN_BAZ', number=6)
+
+    self.pool = self.GetDescriptorPool()
+    self.pool.Add(file_proto)
+    self.my_file = self.pool.FindFileByName(file_proto.name)
+    self.my_message = self.my_file.message_types_by_name[message_proto.name]
+    self.my_enum = self.my_message.enum_types_by_name[enum_proto.name]
+
+    self.my_method = descriptor.MethodDescriptor(
+        name='Bar',
+        full_name='protobuf_unittest.TestService.Bar',
+        index=0,
+        containing_service=None,
+        input_type=None,
+        output_type=None)
+    self.my_service = descriptor.ServiceDescriptor(
+        name='TestServiceWithOptions',
+        full_name='protobuf_unittest.TestServiceWithOptions',
+        file=self.my_file,
+        index=0,
+        methods=[
+            self.my_method
+        ])
+
+  def GetDescriptorPool(self):
+    return symbol_database.Default().pool
+
+  def testEnumValueName(self):
+    self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4),
+                     'FOREIGN_FOO')
+
+    self.assertEqual(
+        self.my_message.enum_types_by_name[
+            'ForeignEnum'].values_by_number[4].name,
+        self.my_message.EnumValueName('ForeignEnum', 4))
+
+  def testEnumFixups(self):
+    self.assertEqual(self.my_enum, self.my_enum.values[0].type)
+
+  def testContainingTypeFixups(self):
+    self.assertEqual(self.my_message, self.my_message.fields[0].containing_type)
+    self.assertEqual(self.my_message, self.my_enum.containing_type)
+
+  def testContainingServiceFixups(self):
+    self.assertEqual(self.my_service, self.my_method.containing_service)
+
+  def testGetOptions(self):
+    self.assertEqual(self.my_enum.GetOptions(),
+                     descriptor_pb2.EnumOptions())
+    self.assertEqual(self.my_enum.values[0].GetOptions(),
+                     descriptor_pb2.EnumValueOptions())
+    self.assertEqual(self.my_message.GetOptions(),
+                     descriptor_pb2.MessageOptions())
+    self.assertEqual(self.my_message.fields[0].GetOptions(),
+                     descriptor_pb2.FieldOptions())
+    self.assertEqual(self.my_method.GetOptions(),
+                     descriptor_pb2.MethodOptions())
+    self.assertEqual(self.my_service.GetOptions(),
+                     descriptor_pb2.ServiceOptions())
+
+  def testSimpleCustomOptions(self):
+    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+    message_descriptor =\
+        unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR
+    field_descriptor = message_descriptor.fields_by_name["field1"]
+    enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"]
+    enum_value_descriptor =\
+        message_descriptor.enum_values_by_name["ANENUM_VAL2"]
+    service_descriptor =\
+        unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR
+    method_descriptor = service_descriptor.FindMethodByName("Foo")
+
+    file_options = file_descriptor.GetOptions()
+    file_opt1 = unittest_custom_options_pb2.file_opt1
+    self.assertEqual(9876543210, file_options.Extensions[file_opt1])
+    message_options = message_descriptor.GetOptions()
+    message_opt1 = unittest_custom_options_pb2.message_opt1
+    self.assertEqual(-56, message_options.Extensions[message_opt1])
+    field_options = field_descriptor.GetOptions()
+    field_opt1 = unittest_custom_options_pb2.field_opt1
+    self.assertEqual(8765432109, field_options.Extensions[field_opt1])
+    field_opt2 = unittest_custom_options_pb2.field_opt2
+    self.assertEqual(42, field_options.Extensions[field_opt2])
+    enum_options = enum_descriptor.GetOptions()
+    enum_opt1 = unittest_custom_options_pb2.enum_opt1
+    self.assertEqual(-789, enum_options.Extensions[enum_opt1])
+    enum_value_options = enum_value_descriptor.GetOptions()
+    enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1
+    self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1])
+
+    service_options = service_descriptor.GetOptions()
+    service_opt1 = unittest_custom_options_pb2.service_opt1
+    self.assertEqual(-9876543210, service_options.Extensions[service_opt1])
+    method_options = method_descriptor.GetOptions()
+    method_opt1 = unittest_custom_options_pb2.method_opt1
+    self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
+                     method_options.Extensions[method_opt1])
+
+    message_descriptor = (
+        unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR)
+    self.assertTrue(file_descriptor.has_options)
+    self.assertFalse(message_descriptor.has_options)
+
+  def testDifferentCustomOptionTypes(self):
+    kint32min = -2**31
+    kint64min = -2**63
+    kint32max = 2**31 - 1
+    kint64max = 2**63 - 1
+    kuint32max = 2**32 - 1
+    kuint64max = 2**64 - 1
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(False, message_options.Extensions[
+        unittest_custom_options_pb2.bool_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.int64_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.uint32_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.uint64_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.sint32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.sint64_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.fixed32_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.fixed64_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed64_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(True, message_options.Extensions[
+        unittest_custom_options_pb2.bool_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.int64_opt])
+    self.assertEqual(kuint32max, message_options.Extensions[
+        unittest_custom_options_pb2.uint32_opt])
+    self.assertEqual(kuint64max, message_options.Extensions[
+        unittest_custom_options_pb2.uint64_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.sint32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.sint64_opt])
+    self.assertEqual(kuint32max, message_options.Extensions[
+        unittest_custom_options_pb2.fixed32_opt])
+    self.assertEqual(kuint64max, message_options.Extensions[
+        unittest_custom_options_pb2.fixed64_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed64_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(-100, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertAlmostEqual(12.3456789, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+    self.assertEqual("Hello, \"World\"", message_options.Extensions[
+        unittest_custom_options_pb2.string_opt])
+    self.assertEqual(b"Hello\0World", message_options.Extensions[
+        unittest_custom_options_pb2.bytes_opt])
+    dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum
+    self.assertEqual(
+        dummy_enum.TEST_OPTION_ENUM_TYPE2,
+        message_options.Extensions[unittest_custom_options_pb2.enum_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertAlmostEqual(12, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(154, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertAlmostEqual(-12, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(-154, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+
+  def testComplexExtensionOptions(self):
+    descriptor =\
+        unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR
+    options = descriptor.GetOptions()
+    self.assertEqual(42, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].foo)
+    self.assertEqual(324, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].Extensions[
+            unittest_custom_options_pb2.quux])
+    self.assertEqual(876, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].Extensions[
+            unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(987, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].baz)
+    self.assertEqual(654, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.grault])
+    self.assertEqual(743, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.foo)
+    self.assertEqual(1999, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+            unittest_custom_options_pb2.quux])
+    self.assertEqual(2008, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+            unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(741, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].foo)
+    self.assertEqual(1998, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].Extensions[
+                unittest_custom_options_pb2.quux])
+    self.assertEqual(2121, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].Extensions[
+                unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(1971, options.Extensions[
+        unittest_custom_options_pb2.ComplexOptionType2
+        .ComplexOptionType4.complex_opt4].waldo)
+    self.assertEqual(321, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].fred.waldo)
+    self.assertEqual(9, options.Extensions[
+        unittest_custom_options_pb2.complex_opt3].qux)
+    self.assertEqual(22, options.Extensions[
+        unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh)
+    self.assertEqual(24, options.Extensions[
+        unittest_custom_options_pb2.complexopt6].xyzzy)
+
+  # Check that aggregate options were parsed and saved correctly in
+  # the appropriate descriptors.
+  def testAggregateOptions(self):
+    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+    message_descriptor =\
+        unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR
+    field_descriptor = message_descriptor.fields_by_name["fieldname"]
+    enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR
+    enum_value_descriptor = enum_descriptor.values_by_name["VALUE"]
+    service_descriptor =\
+        unittest_custom_options_pb2.AggregateService.DESCRIPTOR
+    method_descriptor = service_descriptor.FindMethodByName("Method")
+
+    # Tests for the different types of data embedded in fileopt
+    file_options = file_descriptor.GetOptions().Extensions[
+        unittest_custom_options_pb2.fileopt]
+    self.assertEqual(100, file_options.i)
+    self.assertEqual("FileAnnotation", file_options.s)
+    self.assertEqual("NestedFileAnnotation", file_options.sub.s)
+    self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[
+        unittest_custom_options_pb2.fileopt].s)
+    self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[
+        unittest_custom_options_pb2.AggregateMessageSetElement
+        .message_set_extension].s)
+
+    # Simple tests for all the other types of annotations
+    self.assertEqual(
+        "MessageAnnotation",
+        message_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.msgopt].s)
+    self.assertEqual(
+        "FieldAnnotation",
+        field_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.fieldopt].s)
+    self.assertEqual(
+        "EnumAnnotation",
+        enum_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.enumopt].s)
+    self.assertEqual(
+        "EnumValueAnnotation",
+        enum_value_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.enumvalopt].s)
+    self.assertEqual(
+        "ServiceAnnotation",
+        service_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.serviceopt].s)
+    self.assertEqual(
+        "MethodAnnotation",
+        method_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.methodopt].s)
+
+  def testNestedOptions(self):
+    nested_message =\
+        unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR
+    self.assertEqual(1001, nested_message.GetOptions().Extensions[
+        unittest_custom_options_pb2.message_opt1])
+    nested_field = nested_message.fields_by_name["nested_field"]
+    self.assertEqual(1002, nested_field.GetOptions().Extensions[
+        unittest_custom_options_pb2.field_opt1])
+    outer_message =\
+        unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR
+    nested_enum = outer_message.enum_types_by_name["NestedEnum"]
+    self.assertEqual(1003, nested_enum.GetOptions().Extensions[
+        unittest_custom_options_pb2.enum_opt1])
+    nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"]
+    self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[
+        unittest_custom_options_pb2.enum_value_opt1])
+    nested_extension = outer_message.extensions_by_name["nested_extension"]
+    self.assertEqual(1005, nested_extension.GetOptions().Extensions[
+        unittest_custom_options_pb2.field_opt2])
+
+  def testFileDescriptorReferences(self):
+    self.assertEqual(self.my_enum.file, self.my_file)
+    self.assertEqual(self.my_message.file, self.my_file)
+
+  def testFileDescriptor(self):
+    self.assertEqual(self.my_file.name, 'some/filename/some.proto')
+    self.assertEqual(self.my_file.package, 'protobuf_unittest')
+    self.assertEqual(self.my_file.pool, self.pool)
+    # Generated modules also belong to the default pool.
+    self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default())
+
+  @unittest.skipIf(
+      api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+      'Immutability of descriptors is only enforced in v2 implementation')
+  def testImmutableCppDescriptor(self):
+    message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    with self.assertRaises(AttributeError):
+      message_descriptor.fields_by_name = None
+    with self.assertRaises(TypeError):
+      message_descriptor.fields_by_name['Another'] = None
+    with self.assertRaises(TypeError):
+      message_descriptor.fields.append(None)
+
+
+class NewDescriptorTest(DescriptorTest):
+  """Redo the same tests as above, but with a separate DescriptorPool."""
+
+  def GetDescriptorPool(self):
+    return descriptor_pool.DescriptorPool()
+
+
+class GeneratedDescriptorTest(unittest.TestCase):
+  """Tests for the properties of descriptors in generated code."""
+
+  def CheckMessageDescriptor(self, message_descriptor):
+    # Basic properties
+    self.assertEqual(message_descriptor.name, 'TestAllTypes')
+    self.assertEqual(message_descriptor.full_name,
+                     'protobuf_unittest.TestAllTypes')
+    # Test equality and hashability
+    self.assertEqual(message_descriptor, message_descriptor)
+    self.assertEqual(message_descriptor.fields[0].containing_type,
+                     message_descriptor)
+    self.assertIn(message_descriptor, [message_descriptor])
+    self.assertIn(message_descriptor, {message_descriptor: None})
+    # Test field containers
+    self.CheckDescriptorSequence(message_descriptor.fields)
+    self.CheckDescriptorMapping(message_descriptor.fields_by_name)
+    self.CheckDescriptorMapping(message_descriptor.fields_by_number)
+    self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name)
+
+  def CheckFieldDescriptor(self, field_descriptor):
+    # Basic properties
+    self.assertEqual(field_descriptor.name, 'optional_int32')
+    self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32')
+    self.assertEqual(field_descriptor.full_name,
+                     'protobuf_unittest.TestAllTypes.optional_int32')
+    self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes')
+    # Test equality and hashability
+    self.assertEqual(field_descriptor, field_descriptor)
+    self.assertEqual(
+        field_descriptor.containing_type.fields_by_name['optional_int32'],
+        field_descriptor)
+    self.assertEqual(
+        field_descriptor.containing_type.fields_by_camelcase_name[
+            'optionalInt32'],
+        field_descriptor)
+    self.assertIn(field_descriptor, [field_descriptor])
+    self.assertIn(field_descriptor, {field_descriptor: None})
+
+  def CheckDescriptorSequence(self, sequence):
+    # Verifies that a property like 'messageDescriptor.fields' has all the
+    # properties of an immutable abc.Sequence.
+    self.assertGreater(len(sequence), 0)  # Sized
+    self.assertEqual(len(sequence), len(list(sequence)))  # Iterable
+    item = sequence[0]
+    self.assertEqual(item, sequence[0])
+    self.assertIn(item, sequence)  # Container
+    self.assertEqual(sequence.index(item), 0)
+    self.assertEqual(sequence.count(item), 1)
+    reversed_iterator = reversed(sequence)
+    self.assertEqual(list(reversed_iterator), list(sequence)[::-1])
+    self.assertRaises(StopIteration, next, reversed_iterator)
+
+  def CheckDescriptorMapping(self, mapping):
+    # Verifies that a property like 'messageDescriptor.fields' has all the
+    # properties of an immutable abc.Mapping.
+    self.assertGreater(len(mapping), 0)  # Sized
+    self.assertEqual(len(mapping), len(list(mapping)))  # Iterable
+    if sys.version_info >= (3,):
+      key, item = next(iter(mapping.items()))
+    else:
+      key, item = mapping.items()[0]
+    self.assertIn(key, mapping)  # Container
+    self.assertEqual(mapping.get(key), item)
+    # keys(), iterkeys() &co
+    item = (next(iter(mapping.keys())), next(iter(mapping.values())))
+    self.assertEqual(item, next(iter(mapping.items())))
+    if sys.version_info < (3,):
+      def CheckItems(seq, iterator):
+        self.assertEqual(next(iterator), seq[0])
+        self.assertEqual(list(iterator), seq[1:])
+      CheckItems(mapping.keys(), mapping.iterkeys())
+      CheckItems(mapping.values(), mapping.itervalues())
+      CheckItems(mapping.items(), mapping.iteritems())
+
+  def testDescriptor(self):
+    message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.CheckMessageDescriptor(message_descriptor)
+    field_descriptor = message_descriptor.fields_by_name['optional_int32']
+    self.CheckFieldDescriptor(field_descriptor)
+    field_descriptor = message_descriptor.fields_by_camelcase_name[
+        'optionalInt32']
+    self.CheckFieldDescriptor(field_descriptor)
+
+  def testCppDescriptorContainer(self):
+    # Check that the collection is still valid even if the parent disappeared.
+    enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+    values = enum.values
+    del enum
+    self.assertEqual('FOO', values[0].name)
+
+  def testCppDescriptorContainer_Iterator(self):
+    # Same test with the iterator
+    enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+    values_iter = iter(enum.values)
+    del enum
+    self.assertEqual('FOO', next(values_iter).name)
+
+
+class DescriptorCopyToProtoTest(unittest.TestCase):
+  """Tests for CopyTo functions of Descriptor."""
+
+  def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii):
+    expected_proto = expected_class()
+    text_format.Merge(expected_ascii, expected_proto)
+
+    self.assertEqual(
+        actual_proto, expected_proto,
+        'Not equal,\nActual:\n%s\nExpected:\n%s\n'
+        % (str(actual_proto), str(expected_proto)))
+
+  def _InternalTestCopyToProto(self, desc, expected_proto_class,
+                               expected_proto_ascii):
+    actual = expected_proto_class()
+    desc.CopyToProto(actual)
+    self._AssertProtoEqual(
+        actual, expected_proto_class, expected_proto_ascii)
+
+  def testCopyToProto_EmptyMessage(self):
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestEmptyMessage.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII)
+
+  def testCopyToProto_NestedMessage(self):
+    TEST_NESTED_MESSAGE_ASCII = """
+      name: 'NestedMessage'
+      field: <
+        name: 'bb'
+        number: 1
+        label: 1  # Optional
+        type: 5  # TYPE_INT32
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_NESTED_MESSAGE_ASCII)
+
+  def testCopyToProto_ForeignNestedMessage(self):
+    TEST_FOREIGN_NESTED_ASCII = """
+      name: 'TestForeignNested'
+      field: <
+        name: 'foreign_nested'
+        number: 1
+        label: 1  # Optional
+        type: 11  # TYPE_MESSAGE
+        type_name: '.protobuf_unittest.TestAllTypes.NestedMessage'
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestForeignNested.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_FOREIGN_NESTED_ASCII)
+
+  def testCopyToProto_ForeignEnum(self):
+    TEST_FOREIGN_ENUM_ASCII = """
+      name: 'ForeignEnum'
+      value: <
+        name: 'FOREIGN_FOO'
+        number: 4
+      >
+      value: <
+        name: 'FOREIGN_BAR'
+        number: 5
+      >
+      value: <
+        name: 'FOREIGN_BAZ'
+        number: 6
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.ForeignEnum.DESCRIPTOR,
+        descriptor_pb2.EnumDescriptorProto,
+        TEST_FOREIGN_ENUM_ASCII)
+
+  def testCopyToProto_Options(self):
+    TEST_DEPRECATED_FIELDS_ASCII = """
+      name: 'TestDeprecatedFields'
+      field: <
+        name: 'deprecated_int32'
+        number: 1
+        label: 1  # Optional
+        type: 5  # TYPE_INT32
+        options: <
+          deprecated: true
+        >
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestDeprecatedFields.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_DEPRECATED_FIELDS_ASCII)
+
+  def testCopyToProto_AllExtensions(self):
+    TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """
+      name: 'TestEmptyMessageWithExtensions'
+      extension_range: <
+        start: 1
+        end: 536870912
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII)
+
+  def testCopyToProto_SeveralExtensions(self):
+    TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """
+      name: 'TestMultipleExtensionRanges'
+      extension_range: <
+        start: 42
+        end: 43
+      >
+      extension_range: <
+        start: 4143
+        end: 4244
+      >
+      extension_range: <
+        start: 65536
+        end: 536870912
+      >
+      """
+
+    self._InternalTestCopyToProto(
+        unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR,
+        descriptor_pb2.DescriptorProto,
+        TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII)
+
+  # Disable this test so we can make changes to the proto file.
+  # TODO(xiaofeng): Enable this test after cl/55530659 is submitted.
+  #
+  # def testCopyToProto_FileDescriptor(self):
+  #   UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
+  #     name: 'google/protobuf/unittest_import.proto'
+  #     package: 'protobuf_unittest_import'
+  #     dependency: 'google/protobuf/unittest_import_public.proto'
+  #     message_type: <
+  #       name: 'ImportMessage'
+  #       field: <
+  #         name: 'd'
+  #         number: 1
+  #         label: 1  # Optional
+  #         type: 5  # TYPE_INT32
+  #       >
+  #     >
+  #     """ +
+  #     """enum_type: <
+  #       name: 'ImportEnum'
+  #       value: <
+  #         name: 'IMPORT_FOO'
+  #         number: 7
+  #       >
+  #       value: <
+  #         name: 'IMPORT_BAR'
+  #         number: 8
+  #       >
+  #       value: <
+  #         name: 'IMPORT_BAZ'
+  #         number: 9
+  #       >
+  #     >
+  #     options: <
+  #       java_package: 'com.google.protobuf.test'
+  #       optimize_for: 1  # SPEED
+  #     >
+  #     public_dependency: 0
+  #  """)
+  #  self._InternalTestCopyToProto(
+  #      unittest_import_pb2.DESCRIPTOR,
+  #      descriptor_pb2.FileDescriptorProto,
+  #      UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII)
+
+  def testCopyToProto_ServiceDescriptor(self):
+    TEST_SERVICE_ASCII = """
+      name: 'TestService'
+      method: <
+        name: 'Foo'
+        input_type: '.protobuf_unittest.FooRequest'
+        output_type: '.protobuf_unittest.FooResponse'
+      >
+      method: <
+        name: 'Bar'
+        input_type: '.protobuf_unittest.BarRequest'
+        output_type: '.protobuf_unittest.BarResponse'
+      >
+      """
+    # TODO(rocking): enable this test after the proto descriptor change is
+    # checked in.
+    #self._InternalTestCopyToProto(
+    #    unittest_pb2.TestService.DESCRIPTOR,
+    #    descriptor_pb2.ServiceDescriptorProto,
+    #    TEST_SERVICE_ASCII)
+
+
+class MakeDescriptorTest(unittest.TestCase):
+
+  def testMakeDescriptorWithNestedFields(self):
+    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+    file_descriptor_proto.name = 'Foo2'
+    message_type = file_descriptor_proto.message_type.add()
+    message_type.name = file_descriptor_proto.name
+    nested_type = message_type.nested_type.add()
+    nested_type.name = 'Sub'
+    enum_type = nested_type.enum_type.add()
+    enum_type.name = 'FOO'
+    enum_type_val = enum_type.value.add()
+    enum_type_val.name = 'BAR'
+    enum_type_val.number = 3
+    field = message_type.field.add()
+    field.number = 1
+    field.name = 'uint64_field'
+    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    field.type = descriptor.FieldDescriptor.TYPE_UINT64
+    field = message_type.field.add()
+    field.number = 2
+    field.name = 'nested_message_field'
+    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    field.type = descriptor.FieldDescriptor.TYPE_MESSAGE
+    field.type_name = 'Sub'
+    enum_field = nested_type.field.add()
+    enum_field.number = 2
+    enum_field.name = 'bar_field'
+    enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM
+    enum_field.type_name = 'Foo2.Sub.FOO'
+
+    result = descriptor.MakeDescriptor(message_type)
+    self.assertEqual(result.fields[0].cpp_type,
+                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
+    self.assertEqual(result.fields[1].cpp_type,
+                     descriptor.FieldDescriptor.CPPTYPE_MESSAGE)
+    self.assertEqual(result.fields[1].message_type.containing_type,
+                     result)
+    self.assertEqual(result.nested_types[0].fields[0].full_name,
+                     'Foo2.Sub.bar_field')
+    self.assertEqual(result.nested_types[0].fields[0].enum_type,
+                     result.nested_types[0].enum_types[0])
+
+  def testMakeDescriptorWithUnsignedIntField(self):
+    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+    file_descriptor_proto.name = 'Foo'
+    message_type = file_descriptor_proto.message_type.add()
+    message_type.name = file_descriptor_proto.name
+    enum_type = message_type.enum_type.add()
+    enum_type.name = 'FOO'
+    enum_type_val = enum_type.value.add()
+    enum_type_val.name = 'BAR'
+    enum_type_val.number = 3
+    field = message_type.field.add()
+    field.number = 1
+    field.name = 'uint64_field'
+    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    field.type = descriptor.FieldDescriptor.TYPE_UINT64
+    enum_field = message_type.field.add()
+    enum_field.number = 2
+    enum_field.name = 'bar_field'
+    enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM
+    enum_field.type_name = 'Foo.FOO'
+
+    result = descriptor.MakeDescriptor(message_type)
+    self.assertEqual(result.fields[0].cpp_type,
+                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
+
+
+  def testMakeDescriptorWithOptions(self):
+    descriptor_proto = descriptor_pb2.DescriptorProto()
+    aggregate_message = unittest_custom_options_pb2.AggregateMessage
+    aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto)
+    reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto)
+
+    options = reformed_descriptor.GetOptions()
+    self.assertEqual(101,
+                      options.Extensions[unittest_custom_options_pb2.msgopt].i)
+
+  def testCamelcaseName(self):
+    descriptor_proto = descriptor_pb2.DescriptorProto()
+    descriptor_proto.name = 'Bar'
+    names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar']
+    camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar']
+    for index in range(len(names)):
+      field = descriptor_proto.field.add()
+      field.number = index + 1
+      field.name = names[index]
+    result = descriptor.MakeDescriptor(descriptor_proto)
+    for index in range(len(camelcase_names)):
+      self.assertEqual(result.fields[index].camelcase_name,
+                       camelcase_names[index])
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/encoder.py b/src/third_party/protobuf-3/python/google/protobuf/internal/encoder.py
new file mode 100755
index 0000000..48ef2df
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/encoder.py
@@ -0,0 +1,823 @@
+# 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.
+
+"""Code for encoding protocol message primitives.
+
+Contains the logic for encoding every logical protocol field type
+into one of the 5 physical wire types.
+
+This code is designed to push the Python interpreter's performance to the
+limits.
+
+The basic idea is that at startup time, for every field (i.e. every
+FieldDescriptor) we construct two functions:  a "sizer" and an "encoder".  The
+sizer takes a value of this field's type and computes its byte size.  The
+encoder takes a writer function and a value.  It encodes the value into byte
+strings and invokes the writer function to write those strings.  Typically the
+writer function is the write() method of a BytesIO.
+
+We try to do as much work as possible when constructing the writer and the
+sizer rather than when calling them.  In particular:
+* We copy any needed global functions to local variables, so that we do not need
+  to do costly global table lookups at runtime.
+* Similarly, we try to do any attribute lookups at startup time if possible.
+* Every field's tag is encoded to bytes at startup, since it can't change at
+  runtime.
+* Whatever component of the field size we can compute at startup, we do.
+* We *avoid* sharing code if doing so would make the code slower and not sharing
+  does not burden us too much.  For example, encoders for repeated fields do
+  not just call the encoders for singular fields in a loop because this would
+  add an extra function call overhead for every loop iteration; instead, we
+  manually inline the single-value encoder into the loop.
+* If a Python function lacks a return statement, Python actually generates
+  instructions to pop the result of the last statement off the stack, push
+  None onto the stack, and then return that.  If we really don't care what
+  value is returned, then we can save two instructions by returning the
+  result of the last statement.  It looks funny but it helps.
+* We assume that type and bounds checking has happened at a higher level.
+"""
+
+__author__ = 'kenton@google.com (Kenton Varda)'
+
+import struct
+
+import six
+
+from google.protobuf.internal import wire_format
+
+
+# This will overflow and thus become IEEE-754 "infinity".  We would use
+# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
+_POS_INF = 1e10000
+_NEG_INF = -_POS_INF
+
+
+def _VarintSize(value):
+  """Compute the size of a varint value."""
+  if value <= 0x7f: return 1
+  if value <= 0x3fff: return 2
+  if value <= 0x1fffff: return 3
+  if value <= 0xfffffff: return 4
+  if value <= 0x7ffffffff: return 5
+  if value <= 0x3ffffffffff: return 6
+  if value <= 0x1ffffffffffff: return 7
+  if value <= 0xffffffffffffff: return 8
+  if value <= 0x7fffffffffffffff: return 9
+  return 10
+
+
+def _SignedVarintSize(value):
+  """Compute the size of a signed varint value."""
+  if value < 0: return 10
+  if value <= 0x7f: return 1
+  if value <= 0x3fff: return 2
+  if value <= 0x1fffff: return 3
+  if value <= 0xfffffff: return 4
+  if value <= 0x7ffffffff: return 5
+  if value <= 0x3ffffffffff: return 6
+  if value <= 0x1ffffffffffff: return 7
+  if value <= 0xffffffffffffff: return 8
+  if value <= 0x7fffffffffffffff: return 9
+  return 10
+
+
+def _TagSize(field_number):
+  """Returns the number of bytes required to serialize a tag with this field
+  number."""
+  # Just pass in type 0, since the type won't affect the tag+type size.
+  return _VarintSize(wire_format.PackTag(field_number, 0))
+
+
+# --------------------------------------------------------------------
+# In this section we define some generic sizers.  Each of these functions
+# takes parameters specific to a particular field type, e.g. int32 or fixed64.
+# It returns another function which in turn takes parameters specific to a
+# particular field, e.g. the field number and whether it is repeated or packed.
+# Look at the next section to see how these are used.
+
+
+def _SimpleSizer(compute_value_size):
+  """A sizer which uses the function compute_value_size to compute the size of
+  each value.  Typically compute_value_size is _VarintSize."""
+
+  def SpecificSizer(field_number, is_repeated, is_packed):
+    tag_size = _TagSize(field_number)
+    if is_packed:
+      local_VarintSize = _VarintSize
+      def PackedFieldSize(value):
+        result = 0
+        for element in value:
+          result += compute_value_size(element)
+        return result + local_VarintSize(result) + tag_size
+      return PackedFieldSize
+    elif is_repeated:
+      def RepeatedFieldSize(value):
+        result = tag_size * len(value)
+        for element in value:
+          result += compute_value_size(element)
+        return result
+      return RepeatedFieldSize
+    else:
+      def FieldSize(value):
+        return tag_size + compute_value_size(value)
+      return FieldSize
+
+  return SpecificSizer
+
+
+def _ModifiedSizer(compute_value_size, modify_value):
+  """Like SimpleSizer, but modify_value is invoked on each value before it is
+  passed to compute_value_size.  modify_value is typically ZigZagEncode."""
+
+  def SpecificSizer(field_number, is_repeated, is_packed):
+    tag_size = _TagSize(field_number)
+    if is_packed:
+      local_VarintSize = _VarintSize
+      def PackedFieldSize(value):
+        result = 0
+        for element in value:
+          result += compute_value_size(modify_value(element))
+        return result + local_VarintSize(result) + tag_size
+      return PackedFieldSize
+    elif is_repeated:
+      def RepeatedFieldSize(value):
+        result = tag_size * len(value)
+        for element in value:
+          result += compute_value_size(modify_value(element))
+        return result
+      return RepeatedFieldSize
+    else:
+      def FieldSize(value):
+        return tag_size + compute_value_size(modify_value(value))
+      return FieldSize
+
+  return SpecificSizer
+
+
+def _FixedSizer(value_size):
+  """Like _SimpleSizer except for a fixed-size field.  The input is the size
+  of one value."""
+
+  def SpecificSizer(field_number, is_repeated, is_packed):
+    tag_size = _TagSize(field_number)
+    if is_packed:
+      local_VarintSize = _VarintSize
+      def PackedFieldSize(value):
+        result = len(value) * value_size
+        return result + local_VarintSize(result) + tag_size
+      return PackedFieldSize
+    elif is_repeated:
+      element_size = value_size + tag_size
+      def RepeatedFieldSize(value):
+        return len(value) * element_size
+      return RepeatedFieldSize
+    else:
+      field_size = value_size + tag_size
+      def FieldSize(value):
+        return field_size
+      return FieldSize
+
+  return SpecificSizer
+
+
+# ====================================================================
+# Here we declare a sizer constructor for each field type.  Each "sizer
+# constructor" is a function that takes (field_number, is_repeated, is_packed)
+# as parameters and returns a sizer, which in turn takes a field value as
+# a parameter and returns its encoded size.
+
+
+Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize)
+
+UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize)
+
+SInt32Sizer = SInt64Sizer = _ModifiedSizer(
+    _SignedVarintSize, wire_format.ZigZagEncode)
+
+Fixed32Sizer = SFixed32Sizer = FloatSizer  = _FixedSizer(4)
+Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8)
+
+BoolSizer = _FixedSizer(1)
+
+
+def StringSizer(field_number, is_repeated, is_packed):
+  """Returns a sizer for a string field."""
+
+  tag_size = _TagSize(field_number)
+  local_VarintSize = _VarintSize
+  local_len = len
+  assert not is_packed
+  if is_repeated:
+    def RepeatedFieldSize(value):
+      result = tag_size * len(value)
+      for element in value:
+        l = local_len(element.encode('utf-8'))
+        result += local_VarintSize(l) + l
+      return result
+    return RepeatedFieldSize
+  else:
+    def FieldSize(value):
+      l = local_len(value.encode('utf-8'))
+      return tag_size + local_VarintSize(l) + l
+    return FieldSize
+
+
+def BytesSizer(field_number, is_repeated, is_packed):
+  """Returns a sizer for a bytes field."""
+
+  tag_size = _TagSize(field_number)
+  local_VarintSize = _VarintSize
+  local_len = len
+  assert not is_packed
+  if is_repeated:
+    def RepeatedFieldSize(value):
+      result = tag_size * len(value)
+      for element in value:
+        l = local_len(element)
+        result += local_VarintSize(l) + l
+      return result
+    return RepeatedFieldSize
+  else:
+    def FieldSize(value):
+      l = local_len(value)
+      return tag_size + local_VarintSize(l) + l
+    return FieldSize
+
+
+def GroupSizer(field_number, is_repeated, is_packed):
+  """Returns a sizer for a group field."""
+
+  tag_size = _TagSize(field_number) * 2
+  assert not is_packed
+  if is_repeated:
+    def RepeatedFieldSize(value):
+      result = tag_size * len(value)
+      for element in value:
+        result += element.ByteSize()
+      return result
+    return RepeatedFieldSize
+  else:
+    def FieldSize(value):
+      return tag_size + value.ByteSize()
+    return FieldSize
+
+
+def MessageSizer(field_number, is_repeated, is_packed):
+  """Returns a sizer for a message field."""
+
+  tag_size = _TagSize(field_number)
+  local_VarintSize = _VarintSize
+  assert not is_packed
+  if is_repeated:
+    def RepeatedFieldSize(value):
+      result = tag_size * len(value)
+      for element in value:
+        l = element.ByteSize()
+        result += local_VarintSize(l) + l
+      return result
+    return RepeatedFieldSize
+  else:
+    def FieldSize(value):
+      l = value.ByteSize()
+      return tag_size + local_VarintSize(l) + l
+    return FieldSize
+
+
+# --------------------------------------------------------------------
+# MessageSet is special: it needs custom logic to compute its size properly.
+
+
+def MessageSetItemSizer(field_number):
+  """Returns a sizer for extensions of MessageSet.
+
+  The message set message looks like this:
+    message MessageSet {
+      repeated group Item = 1 {
+        required int32 type_id = 2;
+        required string message = 3;
+      }
+    }
+  """
+  static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) +
+                 _TagSize(3))
+  local_VarintSize = _VarintSize
+
+  def FieldSize(value):
+    l = value.ByteSize()
+    return static_size + local_VarintSize(l) + l
+
+  return FieldSize
+
+
+# --------------------------------------------------------------------
+# Map is special: it needs custom logic to compute its size properly.
+
+
+def MapSizer(field_descriptor):
+  """Returns a sizer for a map field."""
+
+  # Can't look at field_descriptor.message_type._concrete_class because it may
+  # not have been initialized yet.
+  message_type = field_descriptor.message_type
+  message_sizer = MessageSizer(field_descriptor.number, False, False)
+
+  def FieldSize(map_value):
+    total = 0
+    for key in map_value:
+      value = map_value[key]
+      # It's wasteful to create the messages and throw them away one second
+      # later since we'll do the same for the actual encode.  But there's not an
+      # obvious way to avoid this within the current design without tons of code
+      # duplication.
+      entry_msg = message_type._concrete_class(key=key, value=value)
+      total += message_sizer(entry_msg)
+    return total
+
+  return FieldSize
+
+# ====================================================================
+# Encoders!
+
+
+def _VarintEncoder():
+  """Return an encoder for a basic varint value (does not include tag)."""
+
+  def EncodeVarint(write, value):
+    bits = value & 0x7f
+    value >>= 7
+    while value:
+      write(six.int2byte(0x80|bits))
+      bits = value & 0x7f
+      value >>= 7
+    return write(six.int2byte(bits))
+
+  return EncodeVarint
+
+
+def _SignedVarintEncoder():
+  """Return an encoder for a basic signed varint value (does not include
+  tag)."""
+
+  def EncodeSignedVarint(write, value):
+    if value < 0:
+      value += (1 << 64)
+    bits = value & 0x7f
+    value >>= 7
+    while value:
+      write(six.int2byte(0x80|bits))
+      bits = value & 0x7f
+      value >>= 7
+    return write(six.int2byte(bits))
+
+  return EncodeSignedVarint
+
+
+_EncodeVarint = _VarintEncoder()
+_EncodeSignedVarint = _SignedVarintEncoder()
+
+
+def _VarintBytes(value):
+  """Encode the given integer as a varint and return the bytes.  This is only
+  called at startup time so it doesn't need to be fast."""
+
+  pieces = []
+  _EncodeVarint(pieces.append, value)
+  return b"".join(pieces)
+
+
+def TagBytes(field_number, wire_type):
+  """Encode the given tag and return the bytes.  Only called at startup."""
+
+  return _VarintBytes(wire_format.PackTag(field_number, wire_type))
+
+# --------------------------------------------------------------------
+# As with sizers (see above), we have a number of common encoder
+# implementations.
+
+
+def _SimpleEncoder(wire_type, encode_value, compute_value_size):
+  """Return a constructor for an encoder for fields of a particular type.
+
+  Args:
+      wire_type:  The field's wire type, for encoding tags.
+      encode_value:  A function which encodes an individual value, e.g.
+        _EncodeVarint().
+      compute_value_size:  A function which computes the size of an individual
+        value, e.g. _VarintSize().
+  """
+
+  def SpecificEncoder(field_number, is_repeated, is_packed):
+    if is_packed:
+      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+      local_EncodeVarint = _EncodeVarint
+      def EncodePackedField(write, value):
+        write(tag_bytes)
+        size = 0
+        for element in value:
+          size += compute_value_size(element)
+        local_EncodeVarint(write, size)
+        for element in value:
+          encode_value(write, element)
+      return EncodePackedField
+    elif is_repeated:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeRepeatedField(write, value):
+        for element in value:
+          write(tag_bytes)
+          encode_value(write, element)
+      return EncodeRepeatedField
+    else:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeField(write, value):
+        write(tag_bytes)
+        return encode_value(write, value)
+      return EncodeField
+
+  return SpecificEncoder
+
+
+def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):
+  """Like SimpleEncoder but additionally invokes modify_value on every value
+  before passing it to encode_value.  Usually modify_value is ZigZagEncode."""
+
+  def SpecificEncoder(field_number, is_repeated, is_packed):
+    if is_packed:
+      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+      local_EncodeVarint = _EncodeVarint
+      def EncodePackedField(write, value):
+        write(tag_bytes)
+        size = 0
+        for element in value:
+          size += compute_value_size(modify_value(element))
+        local_EncodeVarint(write, size)
+        for element in value:
+          encode_value(write, modify_value(element))
+      return EncodePackedField
+    elif is_repeated:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeRepeatedField(write, value):
+        for element in value:
+          write(tag_bytes)
+          encode_value(write, modify_value(element))
+      return EncodeRepeatedField
+    else:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeField(write, value):
+        write(tag_bytes)
+        return encode_value(write, modify_value(value))
+      return EncodeField
+
+  return SpecificEncoder
+
+
+def _StructPackEncoder(wire_type, format):
+  """Return a constructor for an encoder for a fixed-width field.
+
+  Args:
+      wire_type:  The field's wire type, for encoding tags.
+      format:  The format string to pass to struct.pack().
+  """
+
+  value_size = struct.calcsize(format)
+
+  def SpecificEncoder(field_number, is_repeated, is_packed):
+    local_struct_pack = struct.pack
+    if is_packed:
+      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+      local_EncodeVarint = _EncodeVarint
+      def EncodePackedField(write, value):
+        write(tag_bytes)
+        local_EncodeVarint(write, len(value) * value_size)
+        for element in value:
+          write(local_struct_pack(format, element))
+      return EncodePackedField
+    elif is_repeated:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeRepeatedField(write, value):
+        for element in value:
+          write(tag_bytes)
+          write(local_struct_pack(format, element))
+      return EncodeRepeatedField
+    else:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeField(write, value):
+        write(tag_bytes)
+        return write(local_struct_pack(format, value))
+      return EncodeField
+
+  return SpecificEncoder
+
+
+def _FloatingPointEncoder(wire_type, format):
+  """Return a constructor for an encoder for float fields.
+
+  This is like StructPackEncoder, but catches errors that may be due to
+  passing non-finite floating-point values to struct.pack, and makes a
+  second attempt to encode those values.
+
+  Args:
+      wire_type:  The field's wire type, for encoding tags.
+      format:  The format string to pass to struct.pack().
+  """
+
+  value_size = struct.calcsize(format)
+  if value_size == 4:
+    def EncodeNonFiniteOrRaise(write, value):
+      # Remember that the serialized form uses little-endian byte order.
+      if value == _POS_INF:
+        write(b'\x00\x00\x80\x7F')
+      elif value == _NEG_INF:
+        write(b'\x00\x00\x80\xFF')
+      elif value != value:           # NaN
+        write(b'\x00\x00\xC0\x7F')
+      else:
+        raise
+  elif value_size == 8:
+    def EncodeNonFiniteOrRaise(write, value):
+      if value == _POS_INF:
+        write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F')
+      elif value == _NEG_INF:
+        write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF')
+      elif value != value:                         # NaN
+        write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')
+      else:
+        raise
+  else:
+    raise ValueError('Can\'t encode floating-point values that are '
+                     '%d bytes long (only 4 or 8)' % value_size)
+
+  def SpecificEncoder(field_number, is_repeated, is_packed):
+    local_struct_pack = struct.pack
+    if is_packed:
+      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+      local_EncodeVarint = _EncodeVarint
+      def EncodePackedField(write, value):
+        write(tag_bytes)
+        local_EncodeVarint(write, len(value) * value_size)
+        for element in value:
+          # This try/except block is going to be faster than any code that
+          # we could write to check whether element is finite.
+          try:
+            write(local_struct_pack(format, element))
+          except SystemError:
+            EncodeNonFiniteOrRaise(write, element)
+      return EncodePackedField
+    elif is_repeated:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeRepeatedField(write, value):
+        for element in value:
+          write(tag_bytes)
+          try:
+            write(local_struct_pack(format, element))
+          except SystemError:
+            EncodeNonFiniteOrRaise(write, element)
+      return EncodeRepeatedField
+    else:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeField(write, value):
+        write(tag_bytes)
+        try:
+          write(local_struct_pack(format, value))
+        except SystemError:
+          EncodeNonFiniteOrRaise(write, value)
+      return EncodeField
+
+  return SpecificEncoder
+
+
+# ====================================================================
+# Here we declare an encoder constructor for each field type.  These work
+# very similarly to sizer constructors, described earlier.
+
+
+Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder(
+    wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize)
+
+UInt32Encoder = UInt64Encoder = _SimpleEncoder(
+    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize)
+
+SInt32Encoder = SInt64Encoder = _ModifiedEncoder(
+    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize,
+    wire_format.ZigZagEncode)
+
+# Note that Python conveniently guarantees that when using the '<' prefix on
+# formats, they will also have the same size across all platforms (as opposed
+# to without the prefix, where their sizes depend on the C compiler's basic
+# type sizes).
+Fixed32Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
+Fixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
+SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
+SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
+FloatEncoder    = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
+DoubleEncoder   = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
+
+
+def BoolEncoder(field_number, is_repeated, is_packed):
+  """Returns an encoder for a boolean field."""
+
+  false_byte = b'\x00'
+  true_byte = b'\x01'
+  if is_packed:
+    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+    local_EncodeVarint = _EncodeVarint
+    def EncodePackedField(write, value):
+      write(tag_bytes)
+      local_EncodeVarint(write, len(value))
+      for element in value:
+        if element:
+          write(true_byte)
+        else:
+          write(false_byte)
+    return EncodePackedField
+  elif is_repeated:
+    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
+    def EncodeRepeatedField(write, value):
+      for element in value:
+        write(tag_bytes)
+        if element:
+          write(true_byte)
+        else:
+          write(false_byte)
+    return EncodeRepeatedField
+  else:
+    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
+    def EncodeField(write, value):
+      write(tag_bytes)
+      if value:
+        return write(true_byte)
+      return write(false_byte)
+    return EncodeField
+
+
+def StringEncoder(field_number, is_repeated, is_packed):
+  """Returns an encoder for a string field."""
+
+  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+  local_EncodeVarint = _EncodeVarint
+  local_len = len
+  assert not is_packed
+  if is_repeated:
+    def EncodeRepeatedField(write, value):
+      for element in value:
+        encoded = element.encode('utf-8')
+        write(tag)
+        local_EncodeVarint(write, local_len(encoded))
+        write(encoded)
+    return EncodeRepeatedField
+  else:
+    def EncodeField(write, value):
+      encoded = value.encode('utf-8')
+      write(tag)
+      local_EncodeVarint(write, local_len(encoded))
+      return write(encoded)
+    return EncodeField
+
+
+def BytesEncoder(field_number, is_repeated, is_packed):
+  """Returns an encoder for a bytes field."""
+
+  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+  local_EncodeVarint = _EncodeVarint
+  local_len = len
+  assert not is_packed
+  if is_repeated:
+    def EncodeRepeatedField(write, value):
+      for element in value:
+        write(tag)
+        local_EncodeVarint(write, local_len(element))
+        write(element)
+    return EncodeRepeatedField
+  else:
+    def EncodeField(write, value):
+      write(tag)
+      local_EncodeVarint(write, local_len(value))
+      return write(value)
+    return EncodeField
+
+
+def GroupEncoder(field_number, is_repeated, is_packed):
+  """Returns an encoder for a group field."""
+
+  start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP)
+  end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
+  assert not is_packed
+  if is_repeated:
+    def EncodeRepeatedField(write, value):
+      for element in value:
+        write(start_tag)
+        element._InternalSerialize(write)
+        write(end_tag)
+    return EncodeRepeatedField
+  else:
+    def EncodeField(write, value):
+      write(start_tag)
+      value._InternalSerialize(write)
+      return write(end_tag)
+    return EncodeField
+
+
+def MessageEncoder(field_number, is_repeated, is_packed):
+  """Returns an encoder for a message field."""
+
+  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+  local_EncodeVarint = _EncodeVarint
+  assert not is_packed
+  if is_repeated:
+    def EncodeRepeatedField(write, value):
+      for element in value:
+        write(tag)
+        local_EncodeVarint(write, element.ByteSize())
+        element._InternalSerialize(write)
+    return EncodeRepeatedField
+  else:
+    def EncodeField(write, value):
+      write(tag)
+      local_EncodeVarint(write, value.ByteSize())
+      return value._InternalSerialize(write)
+    return EncodeField
+
+
+# --------------------------------------------------------------------
+# As before, MessageSet is special.
+
+
+def MessageSetItemEncoder(field_number):
+  """Encoder for extensions of MessageSet.
+
+  The message set message looks like this:
+    message MessageSet {
+      repeated group Item = 1 {
+        required int32 type_id = 2;
+        required string message = 3;
+      }
+    }
+  """
+  start_bytes = b"".join([
+      TagBytes(1, wire_format.WIRETYPE_START_GROUP),
+      TagBytes(2, wire_format.WIRETYPE_VARINT),
+      _VarintBytes(field_number),
+      TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)])
+  end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
+  local_EncodeVarint = _EncodeVarint
+
+  def EncodeField(write, value):
+    write(start_bytes)
+    local_EncodeVarint(write, value.ByteSize())
+    value._InternalSerialize(write)
+    return write(end_bytes)
+
+  return EncodeField
+
+
+# --------------------------------------------------------------------
+# As before, Map is special.
+
+
+def MapEncoder(field_descriptor):
+  """Encoder for extensions of MessageSet.
+
+  Maps always have a wire format like this:
+    message MapEntry {
+      key_type key = 1;
+      value_type value = 2;
+    }
+    repeated MapEntry map = N;
+  """
+  # Can't look at field_descriptor.message_type._concrete_class because it may
+  # not have been initialized yet.
+  message_type = field_descriptor.message_type
+  encode_message = MessageEncoder(field_descriptor.number, False, False)
+
+  def EncodeField(write, value):
+    for key in value:
+      entry_msg = message_type._concrete_class(key=key, value=value[key])
+      encode_message(write, entry_msg)
+
+  return EncodeField
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/enum_type_wrapper.py b/src/third_party/protobuf-3/python/google/protobuf/internal/enum_type_wrapper.py
new file mode 100644
index 0000000..1cffe35
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/enum_type_wrapper.py
@@ -0,0 +1,89 @@
+# 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.
+
+"""A simple wrapper around enum types to expose utility functions.
+
+Instances are created as properties with the same name as the enum they wrap
+on proto classes.  For usage, see:
+  reflection_test.py
+"""
+
+__author__ = 'rabsatt@google.com (Kevin Rabsatt)'
+
+
+class EnumTypeWrapper(object):
+  """A utility for finding the names of enum values."""
+
+  DESCRIPTOR = None
+
+  def __init__(self, enum_type):
+    """Inits EnumTypeWrapper with an EnumDescriptor."""
+    self._enum_type = enum_type
+    self.DESCRIPTOR = enum_type;
+
+  def Name(self, number):
+    """Returns a string containing the name of an enum value."""
+    if number in self._enum_type.values_by_number:
+      return self._enum_type.values_by_number[number].name
+    raise ValueError('Enum %s has no name defined for value %d' % (
+        self._enum_type.name, number))
+
+  def Value(self, name):
+    """Returns the value coresponding to the given enum name."""
+    if name in self._enum_type.values_by_name:
+      return self._enum_type.values_by_name[name].number
+    raise ValueError('Enum %s has no value defined for name %s' % (
+        self._enum_type.name, name))
+
+  def keys(self):
+    """Return a list of the string names in the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+
+    return [value_descriptor.name
+            for value_descriptor in self._enum_type.values]
+
+  def values(self):
+    """Return a list of the integer values in the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+
+    return [value_descriptor.number
+            for value_descriptor in self._enum_type.values]
+
+  def items(self):
+    """Return a list of the (name, value) pairs of the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+    return [(value_descriptor.name, value_descriptor.number)
+            for value_descriptor in self._enum_type.values]
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test1.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test1.proto
new file mode 100644
index 0000000..d2fbbee
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test1.proto
@@ -0,0 +1,58 @@
+// 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.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+
+enum Factory1Enum {
+  FACTORY_1_VALUE_0 = 0;
+  FACTORY_1_VALUE_1 = 1;
+}
+
+message Factory1Message {
+  optional Factory1Enum factory_1_enum = 1;
+  enum NestedFactory1Enum {
+    NESTED_FACTORY_1_VALUE_0 = 0;
+    NESTED_FACTORY_1_VALUE_1 = 1;
+  }
+  optional NestedFactory1Enum nested_factory_1_enum = 2;
+  message NestedFactory1Message {
+    optional string value = 1;
+  }
+  optional NestedFactory1Message nested_factory_1_message = 3;
+  optional int32 scalar_value = 4;
+  repeated string list_value = 5;
+
+  extensions 1000 to max;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test2.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test2.proto
new file mode 100644
index 0000000..bb1b54a
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/factory_test2.proto
@@ -0,0 +1,99 @@
+// 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.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+import "google/protobuf/internal/factory_test1.proto";
+
+
+enum Factory2Enum {
+  FACTORY_2_VALUE_0 = 0;
+  FACTORY_2_VALUE_1 = 1;
+}
+
+message Factory2Message {
+  required int32 mandatory = 1;
+  optional Factory2Enum factory_2_enum = 2;
+  enum NestedFactory2Enum {
+    NESTED_FACTORY_2_VALUE_0 = 0;
+    NESTED_FACTORY_2_VALUE_1 = 1;
+  }
+  optional NestedFactory2Enum nested_factory_2_enum = 3;
+  message NestedFactory2Message {
+    optional string value = 1;
+  }
+  optional NestedFactory2Message nested_factory_2_message = 4;
+  optional Factory1Message factory_1_message = 5;
+  optional Factory1Enum factory_1_enum = 6;
+  optional Factory1Message.NestedFactory1Enum nested_factory_1_enum = 7;
+  optional Factory1Message.NestedFactory1Message nested_factory_1_message = 8;
+  optional Factory2Message circular_message = 9;
+  optional string scalar_value = 10;
+  repeated string list_value = 11;
+  repeated group Grouped = 12 {
+    optional string part_1 = 13;
+    optional string part_2 = 14;
+  }
+  optional LoopMessage loop = 15;
+  optional int32 int_with_default = 16 [default = 1776];
+  optional double double_with_default = 17 [default = 9.99];
+  optional string string_with_default = 18 [default = "hello world"];
+  optional bool bool_with_default = 19 [default = false];
+  optional Factory2Enum enum_with_default = 20 [default = FACTORY_2_VALUE_1];
+  optional bytes bytes_with_default = 21 [default = "a\373\000c"];
+
+
+  extend Factory1Message {
+    optional string one_more_field = 1001;
+  }
+
+  oneof oneof_field {
+    int32 oneof_int = 22;
+    string oneof_string = 23;
+  }
+}
+
+message LoopMessage {
+  optional Factory2Message loop = 1;
+}
+
+message MessageWithNestedEnumOnly {
+  enum NestedEnum {
+    NESTED_MESSAGE_ENUM_0 = 0;
+  }
+}
+
+extend Factory1Message {
+  optional string another_field = 1002;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/generator_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/generator_test.py
new file mode 100755
index 0000000..83ea5f5
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/generator_test.py
@@ -0,0 +1,348 @@
+#! /usr/bin/env python
+#
+# 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.
+
+# TODO(robinson): Flesh this out considerably.  We focused on reflection_test.py
+# first, since it's testing the subtler code, and since it provides decent
+# indirect testing of the protocol compiler output.
+
+"""Unittest that directly tests the output of the pure-Python protocol
+compiler.  See //google/protobuf/internal/reflection_test.py for a test which
+further ensures that we can use Python protocol message objects as we expect.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf.internal import test_bad_identifiers_pb2
+from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_import_public_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_mset_wire_format_pb2
+from google.protobuf import unittest_no_generic_services_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import service
+from google.protobuf import symbol_database
+
+MAX_EXTENSION = 536870912
+
+
+class GeneratorTest(unittest.TestCase):
+
+  def testNestedMessageDescriptor(self):
+    field_name = 'optional_nested_message'
+    proto_type = unittest_pb2.TestAllTypes
+    self.assertEqual(
+        proto_type.NestedMessage.DESCRIPTOR,
+        proto_type.DESCRIPTOR.fields_by_name[field_name].message_type)
+
+  def testEnums(self):
+    # We test only module-level enums here.
+    # TODO(robinson): Examine descriptors directly to check
+    # enum descriptor output.
+    self.assertEqual(4, unittest_pb2.FOREIGN_FOO)
+    self.assertEqual(5, unittest_pb2.FOREIGN_BAR)
+    self.assertEqual(6, unittest_pb2.FOREIGN_BAZ)
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(1, proto.FOO)
+    self.assertEqual(1, unittest_pb2.TestAllTypes.FOO)
+    self.assertEqual(2, proto.BAR)
+    self.assertEqual(2, unittest_pb2.TestAllTypes.BAR)
+    self.assertEqual(3, proto.BAZ)
+    self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
+
+  def testExtremeDefaultValues(self):
+    message = unittest_pb2.TestExtremeDefaultValues()
+
+    # Python pre-2.6 does not have isinf() or isnan() functions, so we have
+    # to provide our own.
+    def isnan(val):
+      # NaN is never equal to itself.
+      return val != val
+    def isinf(val):
+      # Infinity times zero equals NaN.
+      return not isnan(val) and isnan(val * 0)
+
+    self.assertTrue(isinf(message.inf_double))
+    self.assertTrue(message.inf_double > 0)
+    self.assertTrue(isinf(message.neg_inf_double))
+    self.assertTrue(message.neg_inf_double < 0)
+    self.assertTrue(isnan(message.nan_double))
+
+    self.assertTrue(isinf(message.inf_float))
+    self.assertTrue(message.inf_float > 0)
+    self.assertTrue(isinf(message.neg_inf_float))
+    self.assertTrue(message.neg_inf_float < 0)
+    self.assertTrue(isnan(message.nan_float))
+    self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph)
+
+  def testHasDefaultValues(self):
+    desc = unittest_pb2.TestAllTypes.DESCRIPTOR
+
+    expected_has_default_by_name = {
+        'optional_int32': False,
+        'repeated_int32': False,
+        'optional_nested_message': False,
+        'default_int32': True,
+    }
+
+    has_default_by_name = dict(
+        [(f.name, f.has_default_value)
+         for f in desc.fields
+         if f.name in expected_has_default_by_name])
+    self.assertEqual(expected_has_default_by_name, has_default_by_name)
+
+  def testContainingTypeBehaviorForExtensions(self):
+    self.assertEqual(unittest_pb2.optional_int32_extension.containing_type,
+                     unittest_pb2.TestAllExtensions.DESCRIPTOR)
+    self.assertEqual(unittest_pb2.TestRequired.single.containing_type,
+                     unittest_pb2.TestAllExtensions.DESCRIPTOR)
+
+  def testExtensionScope(self):
+    self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope,
+                     None)
+    self.assertEqual(unittest_pb2.TestRequired.single.extension_scope,
+                     unittest_pb2.TestRequired.DESCRIPTOR)
+
+  def testIsExtension(self):
+    self.assertTrue(unittest_pb2.optional_int32_extension.is_extension)
+    self.assertTrue(unittest_pb2.TestRequired.single.is_extension)
+
+    message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR
+    non_extension_descriptor = message_descriptor.fields_by_name['a']
+    self.assertTrue(not non_extension_descriptor.is_extension)
+
+  def testOptions(self):
+    proto = unittest_mset_wire_format_pb2.TestMessageSet()
+    self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
+
+  def testMessageWithCustomOptions(self):
+    proto = unittest_custom_options_pb2.TestMessageWithCustomOptions()
+    enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions()
+    self.assertTrue(enum_options is not None)
+    # TODO(gps): We really should test for the presence of the enum_opt1
+    # extension and for its value to be set to -789.
+
+  def testNestedTypes(self):
+    self.assertEqual(
+        set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),
+        set([
+            unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
+            unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR,
+            unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR,
+        ]))
+    self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, [])
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, [])
+
+  def testContainingType(self):
+    self.assertTrue(
+        unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None)
+    self.assertTrue(
+        unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None)
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
+        unittest_pb2.TestAllTypes.DESCRIPTOR)
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
+        unittest_pb2.TestAllTypes.DESCRIPTOR)
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type,
+        unittest_pb2.TestAllTypes.DESCRIPTOR)
+
+  def testContainingTypeInEnumDescriptor(self):
+    self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None)
+    self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type,
+                     unittest_pb2.TestAllTypes.DESCRIPTOR)
+
+  def testPackage(self):
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.DESCRIPTOR.file.package,
+        'protobuf_unittest')
+    desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR
+    self.assertEqual(desc.file.package, 'protobuf_unittest')
+    self.assertEqual(
+        unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package,
+        'protobuf_unittest_import')
+
+    self.assertEqual(
+        unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest')
+    self.assertEqual(
+        unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package,
+        'protobuf_unittest')
+    self.assertEqual(
+        unittest_import_pb2._IMPORTENUM.file.package,
+        'protobuf_unittest_import')
+
+  def testExtensionRange(self):
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, [])
+    self.assertEqual(
+        unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges,
+        [(1, MAX_EXTENSION)])
+    self.assertEqual(
+        unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges,
+        [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)])
+
+  def testFileDescriptor(self):
+    self.assertEqual(unittest_pb2.DESCRIPTOR.name,
+                     'google/protobuf/unittest.proto')
+    self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest')
+    self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None)
+    self.assertEqual(unittest_pb2.DESCRIPTOR.dependencies,
+                     [unittest_import_pb2.DESCRIPTOR])
+    self.assertEqual(unittest_import_pb2.DESCRIPTOR.dependencies,
+                     [unittest_import_public_pb2.DESCRIPTOR])
+
+  def testNoGenericServices(self):
+    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage"))
+    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO"))
+    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension"))
+
+    # Make sure unittest_no_generic_services_pb2 has no services subclassing
+    # Proto2 Service class.
+    if hasattr(unittest_no_generic_services_pb2, "TestService"):
+      self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService,
+                                  service.Service))
+
+  def testMessageTypesByName(self):
+    file_type = unittest_pb2.DESCRIPTOR
+    self.assertEqual(
+        unittest_pb2._TESTALLTYPES,
+        file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name])
+
+    # Nested messages shouldn't be included in the message_types_by_name
+    # dictionary (like in the C++ API).
+    self.assertFalse(
+        unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in
+        file_type.message_types_by_name)
+
+  def testEnumTypesByName(self):
+    file_type = unittest_pb2.DESCRIPTOR
+    self.assertEqual(
+        unittest_pb2._FOREIGNENUM,
+        file_type.enum_types_by_name[unittest_pb2._FOREIGNENUM.name])
+
+  def testExtensionsByName(self):
+    file_type = unittest_pb2.DESCRIPTOR
+    self.assertEqual(
+        unittest_pb2.my_extension_string,
+        file_type.extensions_by_name[unittest_pb2.my_extension_string.name])
+
+  def testPublicImports(self):
+    # Test public imports as embedded message.
+    all_type_proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, all_type_proto.optional_public_import_message.e)
+
+    # PublicImportMessage is actually defined in unittest_import_public_pb2
+    # module, and is public imported by unittest_import_pb2 module.
+    public_import_proto = unittest_import_pb2.PublicImportMessage()
+    self.assertEqual(0, public_import_proto.e)
+    self.assertTrue(unittest_import_public_pb2.PublicImportMessage is
+                    unittest_import_pb2.PublicImportMessage)
+
+  def testBadIdentifiers(self):
+    # We're just testing that the code was imported without problems.
+    message = test_bad_identifiers_pb2.TestBadIdentifiers()
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message],
+                     "foo")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor],
+                     "bar")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection],
+                     "baz")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
+                     "qux")
+
+  def testOneof(self):
+    desc = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.assertEqual(1, len(desc.oneofs))
+    self.assertEqual('oneof_field', desc.oneofs[0].name)
+    self.assertEqual(0, desc.oneofs[0].index)
+    self.assertIs(desc, desc.oneofs[0].containing_type)
+    self.assertIs(desc.oneofs[0], desc.oneofs_by_name['oneof_field'])
+    nested_names = set(['oneof_uint32', 'oneof_nested_message',
+                        'oneof_string', 'oneof_bytes'])
+    self.assertEqual(
+        nested_names,
+        set([field.name for field in desc.oneofs[0].fields]))
+    for field_name, field_desc in desc.fields_by_name.items():
+      if field_name in nested_names:
+        self.assertIs(desc.oneofs[0], field_desc.containing_oneof)
+      else:
+        self.assertIsNone(field_desc.containing_oneof)
+
+
+class SymbolDatabaseRegistrationTest(unittest.TestCase):
+  """Checks that messages, enums and files are correctly registered."""
+
+  def testGetSymbol(self):
+    self.assertEqual(
+        unittest_pb2.TestAllTypes, symbol_database.Default().GetSymbol(
+            'protobuf_unittest.TestAllTypes'))
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.NestedMessage,
+        symbol_database.Default().GetSymbol(
+            'protobuf_unittest.TestAllTypes.NestedMessage'))
+    with self.assertRaises(KeyError):
+      symbol_database.Default().GetSymbol('protobuf_unittest.NestedMessage')
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.OptionalGroup,
+        symbol_database.Default().GetSymbol(
+            'protobuf_unittest.TestAllTypes.OptionalGroup'))
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.RepeatedGroup,
+        symbol_database.Default().GetSymbol(
+            'protobuf_unittest.TestAllTypes.RepeatedGroup'))
+
+  def testEnums(self):
+    self.assertEqual(
+        'protobuf_unittest.ForeignEnum',
+        symbol_database.Default().pool.FindEnumTypeByName(
+            'protobuf_unittest.ForeignEnum').full_name)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes.NestedEnum',
+        symbol_database.Default().pool.FindEnumTypeByName(
+            'protobuf_unittest.TestAllTypes.NestedEnum').full_name)
+
+  def testFindFileByName(self):
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        symbol_database.Default().pool.FindFileByName(
+            'google/protobuf/unittest.proto').name)
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/__init__.py b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/__init__.py
new file mode 100644
index 0000000..5121dd0
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/__init__.py
@@ -0,0 +1,33 @@
+# 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.
+
+"""Sample module importing a nested proto from itself."""
+
+from google.protobuf.internal.import_test_package import outer_pb2 as myproto
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/inner.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/inner.proto
new file mode 100644
index 0000000..2887c12
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/inner.proto
@@ -0,0 +1,37 @@
+// 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.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal.import_test_package;
+
+message Inner {
+  optional int32 value = 1 [default = 57];
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/outer.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/outer.proto
new file mode 100644
index 0000000..a27fb5c
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/import_test_package/outer.proto
@@ -0,0 +1,39 @@
+// 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.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal.import_test_package;
+
+import "google/protobuf/internal/import_test_package/inner.proto";
+
+message Outer {
+  optional Inner inner = 1;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/json_format_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/json_format_test.py
new file mode 100644
index 0000000..bdc9f49
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/json_format_test.py
@@ -0,0 +1,769 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Test for google.protobuf.json_format."""
+
+__author__ = 'jieluo@google.com (Jie Luo)'
+
+import json
+import math
+import sys
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import any_pb2
+from google.protobuf import duration_pb2
+from google.protobuf import field_mask_pb2
+from google.protobuf import struct_pb2
+from google.protobuf import timestamp_pb2
+from google.protobuf import wrappers_pb2
+from google.protobuf.internal import well_known_types
+from google.protobuf import json_format
+from google.protobuf.util import json_format_proto3_pb2
+
+
+class JsonFormatBase(unittest.TestCase):
+
+  def FillAllFields(self, message):
+    message.int32_value = 20
+    message.int64_value = -20
+    message.uint32_value = 3120987654
+    message.uint64_value = 12345678900
+    message.float_value = float('-inf')
+    message.double_value = 3.1415
+    message.bool_value = True
+    message.string_value = 'foo'
+    message.bytes_value = b'bar'
+    message.message_value.value = 10
+    message.enum_value = json_format_proto3_pb2.BAR
+    # Repeated
+    message.repeated_int32_value.append(0x7FFFFFFF)
+    message.repeated_int32_value.append(-2147483648)
+    message.repeated_int64_value.append(9007199254740992)
+    message.repeated_int64_value.append(-9007199254740992)
+    message.repeated_uint32_value.append(0xFFFFFFF)
+    message.repeated_uint32_value.append(0x7FFFFFF)
+    message.repeated_uint64_value.append(9007199254740992)
+    message.repeated_uint64_value.append(9007199254740991)
+    message.repeated_float_value.append(0)
+
+    message.repeated_double_value.append(1E-15)
+    message.repeated_double_value.append(float('inf'))
+    message.repeated_bool_value.append(True)
+    message.repeated_bool_value.append(False)
+    message.repeated_string_value.append('Few symbols!#$,;')
+    message.repeated_string_value.append('bar')
+    message.repeated_bytes_value.append(b'foo')
+    message.repeated_bytes_value.append(b'bar')
+    message.repeated_message_value.add().value = 10
+    message.repeated_message_value.add().value = 11
+    message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
+    message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
+    self.message = message
+
+  def CheckParseBack(self, message, parsed_message):
+    json_format.Parse(json_format.MessageToJson(message),
+                      parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def CheckError(self, text, error_message):
+    message = json_format_proto3_pb2.TestMessage()
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        error_message,
+        json_format.Parse, text, message)
+
+
+class JsonFormatTest(JsonFormatBase):
+
+  def testEmptyMessageToJson(self):
+    message = json_format_proto3_pb2.TestMessage()
+    self.assertEqual(json_format.MessageToJson(message),
+                     '{}')
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    self.CheckParseBack(message, parsed_message)
+
+  def testPartialMessageToJson(self):
+    message = json_format_proto3_pb2.TestMessage(
+        string_value='test',
+        repeated_int32_value=[89, 4])
+    self.assertEqual(json.loads(json_format.MessageToJson(message)),
+                     json.loads('{"stringValue": "test", '
+                                '"repeatedInt32Value": [89, 4]}'))
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    self.CheckParseBack(message, parsed_message)
+
+  def testAllFieldsToJson(self):
+    message = json_format_proto3_pb2.TestMessage()
+    text = ('{"int32Value": 20, '
+            '"int64Value": "-20", '
+            '"uint32Value": 3120987654,'
+            '"uint64Value": "12345678900",'
+            '"floatValue": "-Infinity",'
+            '"doubleValue": 3.1415,'
+            '"boolValue": true,'
+            '"stringValue": "foo",'
+            '"bytesValue": "YmFy",'
+            '"messageValue": {"value": 10},'
+            '"enumValue": "BAR",'
+            '"repeatedInt32Value": [2147483647, -2147483648],'
+            '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],'
+            '"repeatedUint32Value": [268435455, 134217727],'
+            '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],'
+            '"repeatedFloatValue": [0],'
+            '"repeatedDoubleValue": [1e-15, "Infinity"],'
+            '"repeatedBoolValue": [true, false],'
+            '"repeatedStringValue": ["Few symbols!#$,;", "bar"],'
+            '"repeatedBytesValue": ["Zm9v", "YmFy"],'
+            '"repeatedMessageValue": [{"value": 10}, {"value": 11}],'
+            '"repeatedEnumValue": ["FOO", "BAR"]'
+            '}')
+    self.FillAllFields(message)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message)),
+        json.loads(text))
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    json_format.Parse(text, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testJsonEscapeString(self):
+    message = json_format_proto3_pb2.TestMessage()
+    if sys.version_info[0] < 3:
+      message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9'
+    else:
+      message.string_value = '&\n<\"\r>\b\t\f\\\001/'
+      message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8')
+    self.assertEqual(
+        json_format.MessageToJson(message),
+        '{\n  "stringValue": '
+        '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}')
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    self.CheckParseBack(message, parsed_message)
+    text = u'{"int32Value": "\u0031"}'
+    json_format.Parse(text, message)
+    self.assertEqual(message.int32_value, 1)
+
+  def testAlwaysSeriliaze(self):
+    message = json_format_proto3_pb2.TestMessage(
+        string_value='foo')
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads('{'
+                   '"repeatedStringValue": [],'
+                   '"stringValue": "foo",'
+                   '"repeatedBoolValue": [],'
+                   '"repeatedUint32Value": [],'
+                   '"repeatedInt32Value": [],'
+                   '"enumValue": "FOO",'
+                   '"int32Value": 0,'
+                   '"floatValue": 0,'
+                   '"int64Value": "0",'
+                   '"uint32Value": 0,'
+                   '"repeatedBytesValue": [],'
+                   '"repeatedUint64Value": [],'
+                   '"repeatedDoubleValue": [],'
+                   '"bytesValue": "",'
+                   '"boolValue": false,'
+                   '"repeatedEnumValue": [],'
+                   '"uint64Value": "0",'
+                   '"doubleValue": 0,'
+                   '"repeatedFloatValue": [],'
+                   '"repeatedInt64Value": [],'
+                   '"repeatedMessageValue": []}'))
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    self.CheckParseBack(message, parsed_message)
+
+  def testMapFields(self):
+    message = json_format_proto3_pb2.TestMap()
+    message.bool_map[True] = 1
+    message.bool_map[False] = 2
+    message.int32_map[1] = 2
+    message.int32_map[2] = 3
+    message.int64_map[1] = 2
+    message.int64_map[2] = 3
+    message.uint32_map[1] = 2
+    message.uint32_map[2] = 3
+    message.uint64_map[1] = 2
+    message.uint64_map[2] = 3
+    message.string_map['1'] = 2
+    message.string_map['null'] = 3
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads('{'
+                   '"boolMap": {"false": 2, "true": 1},'
+                   '"int32Map": {"1": 2, "2": 3},'
+                   '"int64Map": {"1": 2, "2": 3},'
+                   '"uint32Map": {"1": 2, "2": 3},'
+                   '"uint64Map": {"1": 2, "2": 3},'
+                   '"stringMap": {"1": 2, "null": 3}'
+                   '}'))
+    parsed_message = json_format_proto3_pb2.TestMap()
+    self.CheckParseBack(message, parsed_message)
+
+  def testOneofFields(self):
+    message = json_format_proto3_pb2.TestOneof()
+    # Always print does not affect oneof fields.
+    self.assertEqual(
+        json_format.MessageToJson(message, True),
+        '{}')
+    message.oneof_int32_value = 0
+    self.assertEqual(
+        json_format.MessageToJson(message, True),
+        '{\n'
+        '  "oneofInt32Value": 0\n'
+        '}')
+    parsed_message = json_format_proto3_pb2.TestOneof()
+    self.CheckParseBack(message, parsed_message)
+
+  def testTimestampMessage(self):
+    message = json_format_proto3_pb2.TestTimestamp()
+    message.value.seconds = 0
+    message.value.nanos = 0
+    message.repeated_value.add().seconds = 20
+    message.repeated_value[0].nanos = 1
+    message.repeated_value.add().seconds = 0
+    message.repeated_value[1].nanos = 10000
+    message.repeated_value.add().seconds = 100000000
+    message.repeated_value[2].nanos = 0
+    # Maximum time
+    message.repeated_value.add().seconds = 253402300799
+    message.repeated_value[3].nanos = 999999999
+    # Minimum time
+    message.repeated_value.add().seconds = -62135596800
+    message.repeated_value[4].nanos = 0
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads('{'
+                   '"value": "1970-01-01T00:00:00Z",'
+                   '"repeatedValue": ['
+                   '  "1970-01-01T00:00:20.000000001Z",'
+                   '  "1970-01-01T00:00:00.000010Z",'
+                   '  "1973-03-03T09:46:40Z",'
+                   '  "9999-12-31T23:59:59.999999999Z",'
+                   '  "0001-01-01T00:00:00Z"'
+                   ']'
+                   '}'))
+    parsed_message = json_format_proto3_pb2.TestTimestamp()
+    self.CheckParseBack(message, parsed_message)
+    text = (r'{"value": "1970-01-01T00:00:00.01+08:00",'
+            r'"repeatedValue":['
+            r'  "1970-01-01T00:00:00.01+08:30",'
+            r'  "1970-01-01T00:00:00.01-01:23"]}')
+    json_format.Parse(text, parsed_message)
+    self.assertEqual(parsed_message.value.seconds, -8 * 3600)
+    self.assertEqual(parsed_message.value.nanos, 10000000)
+    self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600)
+    self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60)
+
+  def testDurationMessage(self):
+    message = json_format_proto3_pb2.TestDuration()
+    message.value.seconds = 1
+    message.repeated_value.add().seconds = 0
+    message.repeated_value[0].nanos = 10
+    message.repeated_value.add().seconds = -1
+    message.repeated_value[1].nanos = -1000
+    message.repeated_value.add().seconds = 10
+    message.repeated_value[2].nanos = 11000000
+    message.repeated_value.add().seconds = -315576000000
+    message.repeated_value.add().seconds = 315576000000
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads('{'
+                   '"value": "1s",'
+                   '"repeatedValue": ['
+                   '  "0.000000010s",'
+                   '  "-1.000001s",'
+                   '  "10.011s",'
+                   '  "-315576000000s",'
+                   '  "315576000000s"'
+                   ']'
+                   '}'))
+    parsed_message = json_format_proto3_pb2.TestDuration()
+    self.CheckParseBack(message, parsed_message)
+
+  def testFieldMaskMessage(self):
+    message = json_format_proto3_pb2.TestFieldMask()
+    message.value.paths.append('foo.bar')
+    message.value.paths.append('bar')
+    self.assertEqual(
+        json_format.MessageToJson(message, True),
+        '{\n'
+        '  "value": "foo.bar,bar"\n'
+        '}')
+    parsed_message = json_format_proto3_pb2.TestFieldMask()
+    self.CheckParseBack(message, parsed_message)
+
+  def testWrapperMessage(self):
+    message = json_format_proto3_pb2.TestWrapper()
+    message.bool_value.value = False
+    message.int32_value.value = 0
+    message.string_value.value = ''
+    message.bytes_value.value = b''
+    message.repeated_bool_value.add().value = True
+    message.repeated_bool_value.add().value = False
+    message.repeated_int32_value.add()
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads('{\n'
+                   '  "int32Value": 0,'
+                   '  "boolValue": false,'
+                   '  "stringValue": "",'
+                   '  "bytesValue": "",'
+                   '  "repeatedBoolValue": [true, false],'
+                   '  "repeatedInt32Value": [0],'
+                   '  "repeatedUint32Value": [],'
+                   '  "repeatedFloatValue": [],'
+                   '  "repeatedDoubleValue": [],'
+                   '  "repeatedBytesValue": [],'
+                   '  "repeatedInt64Value": [],'
+                   '  "repeatedUint64Value": [],'
+                   '  "repeatedStringValue": []'
+                   '}'))
+    parsed_message = json_format_proto3_pb2.TestWrapper()
+    self.CheckParseBack(message, parsed_message)
+
+  def testStructMessage(self):
+    message = json_format_proto3_pb2.TestStruct()
+    message.value['name'] = 'Jim'
+    message.value['age'] = 10
+    message.value['attend'] = True
+    message.value['email'] = None
+    message.value.get_or_create_struct('address')['city'] = 'SFO'
+    message.value['address']['house_number'] = 1024
+    struct_list = message.value.get_or_create_list('list')
+    struct_list.extend([6, 'seven', True, False, None])
+    struct_list.add_struct()['subkey2'] = 9
+    message.repeated_value.add()['age'] = 11
+    message.repeated_value.add()
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, False)),
+        json.loads(
+            '{'
+            '  "value": {'
+            '    "address": {'
+            '      "city": "SFO", '
+            '      "house_number": 1024'
+            '    }, '
+            '    "age": 10, '
+            '    "name": "Jim", '
+            '    "attend": true, '
+            '    "email": null, '
+            '    "list": [6, "seven", true, false, null, {"subkey2": 9}]'
+            '  },'
+            '  "repeatedValue": [{"age": 11}, {}]'
+            '}'))
+    parsed_message = json_format_proto3_pb2.TestStruct()
+    self.CheckParseBack(message, parsed_message)
+
+  def testValueMessage(self):
+    message = json_format_proto3_pb2.TestValue()
+    message.value.string_value = 'hello'
+    message.repeated_value.add().number_value = 11.1
+    message.repeated_value.add().bool_value = False
+    message.repeated_value.add().null_value = 0
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, False)),
+        json.loads(
+            '{'
+            '  "value": "hello",'
+            '  "repeatedValue": [11.1, false, null]'
+            '}'))
+    parsed_message = json_format_proto3_pb2.TestValue()
+    self.CheckParseBack(message, parsed_message)
+    # Can't parse back if the Value message is not set.
+    message.repeated_value.add()
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, False)),
+        json.loads(
+            '{'
+            '  "value": "hello",'
+            '  "repeatedValue": [11.1, false, null, null]'
+            '}'))
+
+  def testListValueMessage(self):
+    message = json_format_proto3_pb2.TestListValue()
+    message.value.values.add().number_value = 11.1
+    message.value.values.add().null_value = 0
+    message.value.values.add().bool_value = True
+    message.value.values.add().string_value = 'hello'
+    message.value.values.add().struct_value['name'] = 'Jim'
+    message.repeated_value.add().values.add().number_value = 1
+    message.repeated_value.add()
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, False)),
+        json.loads(
+            '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,'
+            '"repeatedValue": [[1], []]}'))
+    parsed_message = json_format_proto3_pb2.TestListValue()
+    self.CheckParseBack(message, parsed_message)
+
+  def testAnyMessage(self):
+    message = json_format_proto3_pb2.TestAny()
+    value1 = json_format_proto3_pb2.MessageType()
+    value2 = json_format_proto3_pb2.MessageType()
+    value1.value = 1234
+    value2.value = 5678
+    message.value.Pack(value1)
+    message.repeated_value.add().Pack(value1)
+    message.repeated_value.add().Pack(value2)
+    message.repeated_value.add()
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "repeatedValue": [ {\n'
+            '    "@type": "type.googleapis.com/proto3.MessageType",\n'
+            '    "value": 1234\n'
+            '  }, {\n'
+            '    "@type": "type.googleapis.com/proto3.MessageType",\n'
+            '    "value": 5678\n'
+            '  },\n'
+            '  {}],\n'
+            '  "value": {\n'
+            '    "@type": "type.googleapis.com/proto3.MessageType",\n'
+            '    "value": 1234\n'
+            '  }\n'
+            '}\n'))
+    parsed_message = json_format_proto3_pb2.TestAny()
+    self.CheckParseBack(message, parsed_message)
+
+  def testWellKnownInAnyMessage(self):
+    message = any_pb2.Any()
+    int32_value = wrappers_pb2.Int32Value()
+    int32_value.value = 1234
+    message.Pack(int32_value)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n'
+            '  "value": 1234\n'
+            '}\n'))
+    parsed_message = any_pb2.Any()
+    self.CheckParseBack(message, parsed_message)
+
+    timestamp = timestamp_pb2.Timestamp()
+    message.Pack(timestamp)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": "type.googleapis.com/google.protobuf.Timestamp",\n'
+            '  "value": "1970-01-01T00:00:00Z"\n'
+            '}\n'))
+    self.CheckParseBack(message, parsed_message)
+
+    duration = duration_pb2.Duration()
+    duration.seconds = 1
+    message.Pack(duration)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": "type.googleapis.com/google.protobuf.Duration",\n'
+            '  "value": "1s"\n'
+            '}\n'))
+    self.CheckParseBack(message, parsed_message)
+
+    field_mask = field_mask_pb2.FieldMask()
+    field_mask.paths.append('foo.bar')
+    field_mask.paths.append('bar')
+    message.Pack(field_mask)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": "type.googleapis.com/google.protobuf.FieldMask",\n'
+            '  "value": "foo.bar,bar"\n'
+            '}\n'))
+    self.CheckParseBack(message, parsed_message)
+
+    struct_message = struct_pb2.Struct()
+    struct_message['name'] = 'Jim'
+    message.Pack(struct_message)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": "type.googleapis.com/google.protobuf.Struct",\n'
+            '  "value": {"name": "Jim"}\n'
+            '}\n'))
+    self.CheckParseBack(message, parsed_message)
+
+    nested_any = any_pb2.Any()
+    int32_value.value = 5678
+    nested_any.Pack(int32_value)
+    message.Pack(nested_any)
+    self.assertEqual(
+        json.loads(json_format.MessageToJson(message, True)),
+        json.loads(
+            '{\n'
+            '  "@type": "type.googleapis.com/google.protobuf.Any",\n'
+            '  "value": {\n'
+            '    "@type": "type.googleapis.com/google.protobuf.Int32Value",\n'
+            '    "value": 5678\n'
+            '  }\n'
+            '}\n'))
+    self.CheckParseBack(message, parsed_message)
+
+  def testParseNull(self):
+    message = json_format_proto3_pb2.TestMessage()
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    self.FillAllFields(parsed_message)
+    json_format.Parse('{"int32Value": null, '
+                      '"int64Value": null, '
+                      '"uint32Value": null,'
+                      '"uint64Value": null,'
+                      '"floatValue": null,'
+                      '"doubleValue": null,'
+                      '"boolValue": null,'
+                      '"stringValue": null,'
+                      '"bytesValue": null,'
+                      '"messageValue": null,'
+                      '"enumValue": null,'
+                      '"repeatedInt32Value": null,'
+                      '"repeatedInt64Value": null,'
+                      '"repeatedUint32Value": null,'
+                      '"repeatedUint64Value": null,'
+                      '"repeatedFloatValue": null,'
+                      '"repeatedDoubleValue": null,'
+                      '"repeatedBoolValue": null,'
+                      '"repeatedStringValue": null,'
+                      '"repeatedBytesValue": null,'
+                      '"repeatedMessageValue": null,'
+                      '"repeatedEnumValue": null'
+                      '}',
+                      parsed_message)
+    self.assertEqual(message, parsed_message)
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to parse repeatedInt32Value field: '
+        'null is not allowed to be used as an element in a repeated field.',
+        json_format.Parse,
+        '{"repeatedInt32Value":[1, null]}',
+        parsed_message)
+
+  def testNanFloat(self):
+    message = json_format_proto3_pb2.TestMessage()
+    message.float_value = float('nan')
+    text = '{\n  "floatValue": "NaN"\n}'
+    self.assertEqual(json_format.MessageToJson(message), text)
+    parsed_message = json_format_proto3_pb2.TestMessage()
+    json_format.Parse(text, parsed_message)
+    self.assertTrue(math.isnan(parsed_message.float_value))
+
+  def testParseEmptyText(self):
+    self.CheckError('',
+                    r'Failed to load JSON: (Expecting value)|(No JSON).')
+
+  def testParseBadEnumValue(self):
+    self.CheckError(
+        '{"enumValue": 1}',
+        'Enum value must be a string literal with double quotes. '
+        'Type "proto3.EnumType" has no value named 1.')
+    self.CheckError(
+        '{"enumValue": "baz"}',
+        'Enum value must be a string literal with double quotes. '
+        'Type "proto3.EnumType" has no value named baz.')
+
+  def testParseBadIdentifer(self):
+    self.CheckError('{int32Value: 1}',
+                    (r'Failed to load JSON: Expecting property name'
+                     r'( enclosed in double quotes)?: line 1'))
+    self.CheckError('{"unknownName": 1}',
+                    'Message type "proto3.TestMessage" has no field named '
+                    '"unknownName".')
+
+  def testDuplicateField(self):
+    # Duplicate key check is not supported for python2.6
+    if sys.version_info < (2, 7):
+      return
+    self.CheckError('{"int32Value": 1,\n"int32Value":2}',
+                    'Failed to load JSON: duplicate key int32Value.')
+
+  def testInvalidBoolValue(self):
+    self.CheckError('{"boolValue": 1}',
+                    'Failed to parse boolValue field: '
+                    'Expected true or false without quotes.')
+    self.CheckError('{"boolValue": "true"}',
+                    'Failed to parse boolValue field: '
+                    'Expected true or false without quotes.')
+
+  def testInvalidIntegerValue(self):
+    message = json_format_proto3_pb2.TestMessage()
+    text = '{"int32Value": 0x12345}'
+    self.assertRaises(json_format.ParseError,
+                      json_format.Parse, text, message)
+    self.CheckError('{"int32Value": 012345}',
+                    (r'Failed to load JSON: Expecting \'?,\'? delimiter: '
+                     r'line 1.'))
+    self.CheckError('{"int32Value": 1.0}',
+                    'Failed to parse int32Value field: '
+                    'Couldn\'t parse integer: 1.0.')
+    self.CheckError('{"int32Value": " 1 "}',
+                    'Failed to parse int32Value field: '
+                    'Couldn\'t parse integer: " 1 ".')
+    self.CheckError('{"int32Value": "1 "}',
+                    'Failed to parse int32Value field: '
+                    'Couldn\'t parse integer: "1 ".')
+    self.CheckError('{"int32Value": 12345678901234567890}',
+                    'Failed to parse int32Value field: Value out of range: '
+                    '12345678901234567890.')
+    self.CheckError('{"int32Value": 1e5}',
+                    'Failed to parse int32Value field: '
+                    'Couldn\'t parse integer: 100000.0.')
+    self.CheckError('{"uint32Value": -1}',
+                    'Failed to parse uint32Value field: '
+                    'Value out of range: -1.')
+
+  def testInvalidFloatValue(self):
+    self.CheckError('{"floatValue": "nan"}',
+                    'Failed to parse floatValue field: Couldn\'t '
+                    'parse float "nan", use "NaN" instead.')
+
+  def testInvalidBytesValue(self):
+    self.CheckError('{"bytesValue": "AQI"}',
+                    'Failed to parse bytesValue field: Incorrect padding.')
+    self.CheckError('{"bytesValue": "AQI*"}',
+                    'Failed to parse bytesValue field: Incorrect padding.')
+
+  def testInvalidMap(self):
+    message = json_format_proto3_pb2.TestMap()
+    text = '{"int32Map": {"null": 2, "2": 3}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to parse int32Map field: invalid literal',
+        json_format.Parse, text, message)
+    text = '{"int32Map": {1: 2, "2": 3}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        (r'Failed to load JSON: Expecting property name'
+         r'( enclosed in double quotes)?: line 1'),
+        json_format.Parse, text, message)
+    text = '{"boolMap": {"null": 1}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to parse boolMap field: Expected "true" or "false", not null.',
+        json_format.Parse, text, message)
+    if sys.version_info < (2, 7):
+      return
+    text = r'{"stringMap": {"a": 3, "\u0061": 2}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to load JSON: duplicate key a',
+        json_format.Parse, text, message)
+
+  def testInvalidTimestamp(self):
+    message = json_format_proto3_pb2.TestTimestamp()
+    text = '{"value": "10000-01-01T00:00:00.00Z"}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'time data \'10000-01-01T00:00:00\' does not match'
+        ' format \'%Y-%m-%dT%H:%M:%S\'.',
+        json_format.Parse, text, message)
+    text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}'
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        'nanos 0123456789012 more than 9 fractional digits.',
+        json_format.Parse, text, message)
+    text = '{"value": "1972-01-01T01:00:00.01+08"}'
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        (r'Invalid timezone offset value: \+08.'),
+        json_format.Parse, text, message)
+    # Time smaller than minimum time.
+    text = '{"value": "0000-01-01T00:00:00Z"}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to parse value field: year is out of range.',
+        json_format.Parse, text, message)
+    # Time bigger than maxinum time.
+    message.value.seconds = 253402300800
+    self.assertRaisesRegexp(
+        OverflowError,
+        'date value out of range',
+        json_format.MessageToJson, message)
+
+  def testInvalidOneof(self):
+    message = json_format_proto3_pb2.TestOneof()
+    text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Message type "proto3.TestOneof"'
+        ' should not have multiple "oneof_value" oneof fields.',
+        json_format.Parse, text, message)
+
+  def testInvalidListValue(self):
+    message = json_format_proto3_pb2.TestListValue()
+    text = '{"value": 1234}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        r'Failed to parse value field: ListValue must be in \[\] which is 1234',
+        json_format.Parse, text, message)
+
+  def testInvalidStruct(self):
+    message = json_format_proto3_pb2.TestStruct()
+    text = '{"value": 1234}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        'Failed to parse value field: Struct must be in a dict which is 1234',
+        json_format.Parse, text, message)
+
+  def testInvalidAny(self):
+    message = any_pb2.Any()
+    text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}'
+    self.assertRaisesRegexp(
+        KeyError,
+        'value',
+        json_format.Parse, text, message)
+    text = '{"value": 1234}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        '@type is missing when parsing any message.',
+        json_format.Parse, text, message)
+    text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}'
+    self.assertRaisesRegexp(
+        TypeError,
+        'Can not find message descriptor by type_url: '
+        'type.googleapis.com/MessageNotExist.',
+        json_format.Parse, text, message)
+    # Only last part is to be used: b/25630112
+    text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",'
+            r'"value": 1234}')
+    json_format.Parse(text, message)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/message_factory_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/message_factory_test.py
new file mode 100644
index 0000000..7bb7d1a
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/message_factory_test.py
@@ -0,0 +1,190 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.message_factory."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
+
+
+class MessageFactoryTest(unittest.TestCase):
+
+  def setUp(self):
+    self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test1_pb2.DESCRIPTOR.serialized_pb)
+    self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+
+  def _ExerciseDynamicClass(self, cls):
+    msg = cls()
+    msg.mandatory = 42
+    msg.nested_factory_2_enum = 0
+    msg.nested_factory_2_message.value = 'nested message value'
+    msg.factory_1_message.factory_1_enum = 1
+    msg.factory_1_message.nested_factory_1_enum = 0
+    msg.factory_1_message.nested_factory_1_message.value = (
+        'nested message value')
+    msg.factory_1_message.scalar_value = 22
+    msg.factory_1_message.list_value.extend([u'one', u'two', u'three'])
+    msg.factory_1_message.list_value.append(u'four')
+    msg.factory_1_enum = 1
+    msg.nested_factory_1_enum = 0
+    msg.nested_factory_1_message.value = 'nested message value'
+    msg.circular_message.mandatory = 1
+    msg.circular_message.circular_message.mandatory = 2
+    msg.circular_message.scalar_value = 'one deep'
+    msg.scalar_value = 'zero deep'
+    msg.list_value.extend([u'four', u'three', u'two'])
+    msg.list_value.append(u'one')
+    msg.grouped.add()
+    msg.grouped[0].part_1 = 'hello'
+    msg.grouped[0].part_2 = 'world'
+    msg.grouped.add(part_1='testing', part_2='123')
+    msg.loop.loop.mandatory = 2
+    msg.loop.loop.loop.loop.mandatory = 4
+    serialized = msg.SerializeToString()
+    converted = factory_test2_pb2.Factory2Message.FromString(serialized)
+    reserialized = converted.SerializeToString()
+    self.assertEqual(serialized, reserialized)
+    result = cls.FromString(reserialized)
+    self.assertEqual(msg, result)
+
+  def testGetPrototype(self):
+    db = descriptor_database.DescriptorDatabase()
+    pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    factory = message_factory.MessageFactory()
+    cls = factory.GetPrototype(pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertFalse(cls is factory_test2_pb2.Factory2Message)
+    self._ExerciseDynamicClass(cls)
+    cls2 = factory.GetPrototype(pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertTrue(cls is cls2)
+
+  def testGetMessages(self):
+    # performed twice because multiple calls with the same input must be allowed
+    for _ in range(2):
+      messages = message_factory.GetMessages([self.factory_test1_fd,
+                                              self.factory_test2_fd])
+      self.assertTrue(
+          set(['google.protobuf.python.internal.Factory2Message',
+               'google.protobuf.python.internal.Factory1Message'],
+             ).issubset(set(messages.keys())))
+      self._ExerciseDynamicClass(
+          messages['google.protobuf.python.internal.Factory2Message'])
+      self.assertTrue(
+          set(['google.protobuf.python.internal.Factory2Message.one_more_field',
+               'google.protobuf.python.internal.another_field'],
+             ).issubset(
+                 set(messages['google.protobuf.python.internal.Factory1Message']
+                     ._extensions_by_name.keys())))
+      factory_msg1 = messages['google.protobuf.python.internal.Factory1Message']
+      msg1 = messages['google.protobuf.python.internal.Factory1Message']()
+      ext1 = factory_msg1._extensions_by_name[
+          'google.protobuf.python.internal.Factory2Message.one_more_field']
+      ext2 = factory_msg1._extensions_by_name[
+          'google.protobuf.python.internal.another_field']
+      msg1.Extensions[ext1] = 'test1'
+      msg1.Extensions[ext2] = 'test2'
+      self.assertEqual('test1', msg1.Extensions[ext1])
+      self.assertEqual('test2', msg1.Extensions[ext2])
+
+  def testDuplicateExtensionNumber(self):
+    pool = descriptor_pool.DescriptorPool()
+    factory = message_factory.MessageFactory(pool=pool)
+
+    # Add Container message.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/container.proto'
+    f.package = 'google.protobuf.python.internal'
+    msg = f.message_type.add()
+    msg.name = 'Container'
+    rng = msg.extension_range.add()
+    rng.start = 1
+    rng.end = 10
+    pool.Add(f)
+    msgs = factory.GetMessages([f.name])
+    self.assertIn('google.protobuf.python.internal.Container', msgs)
+
+    # Extend container.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/extension.proto'
+    f.package = 'google.protobuf.python.internal'
+    f.dependency.append('google/protobuf/internal/container.proto')
+    msg = f.message_type.add()
+    msg.name = 'Extension'
+    ext = msg.extension.add()
+    ext.name = 'extension_field'
+    ext.number = 2
+    ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+    ext.type_name = 'Extension'
+    ext.extendee = 'Container'
+    pool.Add(f)
+    msgs = factory.GetMessages([f.name])
+    self.assertIn('google.protobuf.python.internal.Extension', msgs)
+
+    # Add Duplicate extending the same field number.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/duplicate.proto'
+    f.package = 'google.protobuf.python.internal'
+    f.dependency.append('google/protobuf/internal/container.proto')
+    msg = f.message_type.add()
+    msg.name = 'Duplicate'
+    ext = msg.extension.add()
+    ext.name = 'extension_field'
+    ext.number = 2
+    ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+    ext.type_name = 'Duplicate'
+    ext.extendee = 'Container'
+    pool.Add(f)
+
+    with self.assertRaises(Exception) as cm:
+      factory.GetMessages([f.name])
+
+    self.assertIsInstance(cm.exception, (AssertionError, ValueError))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/message_listener.py b/src/third_party/protobuf-3/python/google/protobuf/internal/message_listener.py
new file mode 100755
index 0000000..0fc255a
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/message_listener.py
@@ -0,0 +1,78 @@
+# 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.
+
+"""Defines a listener interface for observing certain
+state transitions on Message objects.
+
+Also defines a null implementation of this interface.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+
+class MessageListener(object):
+
+  """Listens for modifications made to a message.  Meant to be registered via
+  Message._SetListener().
+
+  Attributes:
+    dirty:  If True, then calling Modified() would be a no-op.  This can be
+            used to avoid these calls entirely in the common case.
+  """
+
+  def Modified(self):
+    """Called every time the message is modified in such a way that the parent
+    message may need to be updated.  This currently means either:
+    (a) The message was modified for the first time, so the parent message
+        should henceforth mark the message as present.
+    (b) The message's cached byte size became dirty -- i.e. the message was
+        modified for the first time after a previous call to ByteSize().
+        Therefore the parent should also mark its byte size as dirty.
+    Note that (a) implies (b), since new objects start out with a client cached
+    size (zero).  However, we document (a) explicitly because it is important.
+
+    Modified() will *only* be called in response to one of these two events --
+    not every time the sub-message is modified.
+
+    Note that if the listener's |dirty| attribute is true, then calling
+    Modified at the moment would be a no-op, so it can be skipped.  Performance-
+    sensitive callers should check this attribute directly before calling since
+    it will be true most of the time.
+    """
+
+    raise NotImplementedError
+
+
+class NullMessageListener(object):
+
+  """No-op MessageListener implementation."""
+
+  def Modified(self):
+    pass
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/message_set_extensions.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/message_set_extensions.proto
new file mode 100644
index 0000000..14e5f19
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/message_set_extensions.proto
@@ -0,0 +1,74 @@
+// 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.
+
+// This file contains messages that extend MessageSet.
+
+syntax = "proto2";
+package google.protobuf.internal;
+
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message TestMessageSetExtension1 {
+  extend TestMessageSet {
+    optional TestMessageSetExtension1 message_set_extension = 98418603;
+  }
+  optional int32 i = 15;
+}
+
+message TestMessageSetExtension2 {
+  extend TestMessageSet {
+    optional TestMessageSetExtension2 message_set_extension = 98418634;
+  }
+  optional string str = 25;
+}
+
+message TestMessageSetExtension3 {
+  optional string text = 35;
+}
+
+extend TestMessageSet {
+  optional TestMessageSetExtension3 message_set_extension3 = 98418655;
+}
+
+// This message was used to generate
+// //net/proto2/python/internal/testdata/message_set_message, but is commented
+// out since it must not actually exist in code, to simulate an "unknown"
+// extension.
+// message TestMessageSetUnknownExtension {
+//   extend TestMessageSet {
+//     optional TestMessageSetUnknownExtension message_set_extension = 56141421;
+//   }
+//   optional int64 a = 1;
+// }
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/message_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/message_test.py
new file mode 100755
index 0000000..4ee31d8
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/message_test.py
@@ -0,0 +1,1852 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests python protocol buffers against the golden message.
+
+Note that the golden messages exercise every known field type, thus this
+test ends up exercising and verifying nearly all of the parsing and
+serialization code in the whole library.
+
+TODO(kenton):  Merge with wire_format_test?  It doesn't make a whole lot of
+sense to call this a test of the "message" module, which only declares an
+abstract interface.
+"""
+
+__author__ = 'gps@google.com (Gregory P. Smith)'
+
+
+import collections
+import copy
+import math
+import operator
+import pickle
+import six
+import sys
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
+from google.protobuf import text_format
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import packed_field_test_pb2
+from google.protobuf.internal import test_util
+from google.protobuf import message
+from google.protobuf.internal import _parameterized
+
+if six.PY3:
+  long = int
+
+
+# Python pre-2.6 does not have isinf() or isnan() functions, so we have
+# to provide our own.
+def isnan(val):
+  # NaN is never equal to itself.
+  return val != val
+def isinf(val):
+  # Infinity times zero equals NaN.
+  return not isnan(val) and isnan(val * 0)
+def IsPosInf(val):
+  return isinf(val) and (val > 0)
+def IsNegInf(val):
+  return isinf(val) and (val < 0)
+
+
+@_parameterized.Parameters(
+    (unittest_pb2),
+    (unittest_proto3_arena_pb2))
+class MessageTest(unittest.TestCase):
+
+  def testBadUtf8String(self, message_module):
+    if api_implementation.Type() != 'python':
+      self.skipTest("Skipping testBadUtf8String, currently only the python "
+                    "api implementation raises UnicodeDecodeError when a "
+                    "string field contains bad utf-8.")
+    bad_utf8_data = test_util.GoldenFileData('bad_utf8_string')
+    with self.assertRaises(UnicodeDecodeError) as context:
+      message_module.TestAllTypes.FromString(bad_utf8_data)
+    self.assertIn('TestAllTypes.optional_string', str(context.exception))
+
+  def testGoldenMessage(self, message_module):
+    # Proto3 doesn't have the "default_foo" members or foreign enums,
+    # and doesn't preserve unknown fields, so for proto3 we use a golden
+    # message that doesn't have these fields set.
+    if message_module is unittest_pb2:
+      golden_data = test_util.GoldenFileData(
+          'golden_message_oneof_implemented')
+    else:
+      golden_data = test_util.GoldenFileData('golden_message_proto3')
+
+    golden_message = message_module.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    if message_module is unittest_pb2:
+      test_util.ExpectAllFieldsSet(self, golden_message)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testGoldenPackedMessage(self, message_module):
+    golden_data = test_util.GoldenFileData('golden_packed_fields_message')
+    golden_message = message_module.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    all_set = message_module.TestPackedTypes()
+    test_util.SetAllPackedFields(all_set)
+    self.assertEqual(all_set, golden_message)
+    self.assertEqual(golden_data, all_set.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testPickleSupport(self, message_module):
+    golden_data = test_util.GoldenFileData('golden_message')
+    golden_message = message_module.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    pickled_message = pickle.dumps(golden_message)
+
+    unpickled_message = pickle.loads(pickled_message)
+    self.assertEqual(unpickled_message, golden_message)
+
+  def testPositiveInfinity(self, message_module):
+    if message_module is unittest_pb2:
+      golden_data = (b'\x5D\x00\x00\x80\x7F'
+                     b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
+                     b'\xCD\x02\x00\x00\x80\x7F'
+                     b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
+    else:
+      golden_data = (b'\x5D\x00\x00\x80\x7F'
+                     b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
+                     b'\xCA\x02\x04\x00\x00\x80\x7F'
+                     b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
+
+    golden_message = message_module.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsPosInf(golden_message.optional_float))
+    self.assertTrue(IsPosInf(golden_message.optional_double))
+    self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
+    self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+
+  def testNegativeInfinity(self, message_module):
+    if message_module is unittest_pb2:
+      golden_data = (b'\x5D\x00\x00\x80\xFF'
+                     b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
+                     b'\xCD\x02\x00\x00\x80\xFF'
+                     b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
+    else:
+      golden_data = (b'\x5D\x00\x00\x80\xFF'
+                     b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
+                     b'\xCA\x02\x04\x00\x00\x80\xFF'
+                     b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
+
+    golden_message = message_module.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsNegInf(golden_message.optional_float))
+    self.assertTrue(IsNegInf(golden_message.optional_double))
+    self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
+    self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+
+  def testNotANumber(self, message_module):
+    golden_data = (b'\x5D\x00\x00\xC0\x7F'
+                   b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
+                   b'\xCD\x02\x00\x00\xC0\x7F'
+                   b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
+    golden_message = message_module.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(isnan(golden_message.optional_float))
+    self.assertTrue(isnan(golden_message.optional_double))
+    self.assertTrue(isnan(golden_message.repeated_float[0]))
+    self.assertTrue(isnan(golden_message.repeated_double[0]))
+
+    # The protocol buffer may serialize to any one of multiple different
+    # representations of a NaN.  Rather than verify a specific representation,
+    # verify the serialized string can be converted into a correctly
+    # behaving protocol buffer.
+    serialized = golden_message.SerializeToString()
+    message = message_module.TestAllTypes()
+    message.ParseFromString(serialized)
+    self.assertTrue(isnan(message.optional_float))
+    self.assertTrue(isnan(message.optional_double))
+    self.assertTrue(isnan(message.repeated_float[0]))
+    self.assertTrue(isnan(message.repeated_double[0]))
+
+  def testPositiveInfinityPacked(self, message_module):
+    golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F'
+                   b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
+    golden_message = message_module.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsPosInf(golden_message.packed_float[0]))
+    self.assertTrue(IsPosInf(golden_message.packed_double[0]))
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+
+  def testNegativeInfinityPacked(self, message_module):
+    golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF'
+                   b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
+    golden_message = message_module.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsNegInf(golden_message.packed_float[0]))
+    self.assertTrue(IsNegInf(golden_message.packed_double[0]))
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+
+  def testNotANumberPacked(self, message_module):
+    golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F'
+                   b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
+    golden_message = message_module.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(isnan(golden_message.packed_float[0]))
+    self.assertTrue(isnan(golden_message.packed_double[0]))
+
+    serialized = golden_message.SerializeToString()
+    message = message_module.TestPackedTypes()
+    message.ParseFromString(serialized)
+    self.assertTrue(isnan(message.packed_float[0]))
+    self.assertTrue(isnan(message.packed_double[0]))
+
+  def testExtremeFloatValues(self, message_module):
+    message = message_module.TestAllTypes()
+
+    # Most positive exponent, no significand bits set.
+    kMostPosExponentNoSigBits = math.pow(2, 127)
+    message.optional_float = kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostPosExponentNoSigBits)
+
+    # Most positive exponent, one significand bit set.
+    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127)
+    message.optional_float = kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostPosExponentOneSigBit)
+
+    # Repeat last two cases with values of same magnitude, but negative.
+    message.optional_float = -kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits)
+
+    message.optional_float = -kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit)
+
+    # Most negative exponent, no significand bits set.
+    kMostNegExponentNoSigBits = math.pow(2, -127)
+    message.optional_float = kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostNegExponentNoSigBits)
+
+    # Most negative exponent, one significand bit set.
+    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127)
+    message.optional_float = kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostNegExponentOneSigBit)
+
+    # Repeat last two cases with values of the same magnitude, but negative.
+    message.optional_float = -kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits)
+
+    message.optional_float = -kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
+
+  def testExtremeDoubleValues(self, message_module):
+    message = message_module.TestAllTypes()
+
+    # Most positive exponent, no significand bits set.
+    kMostPosExponentNoSigBits = math.pow(2, 1023)
+    message.optional_double = kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostPosExponentNoSigBits)
+
+    # Most positive exponent, one significand bit set.
+    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023)
+    message.optional_double = kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostPosExponentOneSigBit)
+
+    # Repeat last two cases with values of same magnitude, but negative.
+    message.optional_double = -kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits)
+
+    message.optional_double = -kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit)
+
+    # Most negative exponent, no significand bits set.
+    kMostNegExponentNoSigBits = math.pow(2, -1023)
+    message.optional_double = kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostNegExponentNoSigBits)
+
+    # Most negative exponent, one significand bit set.
+    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023)
+    message.optional_double = kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostNegExponentOneSigBit)
+
+    # Repeat last two cases with values of the same magnitude, but negative.
+    message.optional_double = -kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits)
+
+    message.optional_double = -kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
+
+  def testFloatPrinting(self, message_module):
+    message = message_module.TestAllTypes()
+    message.optional_float = 2.0
+    self.assertEqual(str(message), 'optional_float: 2.0\n')
+
+  def testHighPrecisionFloatPrinting(self, message_module):
+    message = message_module.TestAllTypes()
+    message.optional_double = 0.12345678912345678
+    if sys.version_info >= (3,):
+      self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
+    else:
+      self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
+
+  def testUnknownFieldPrinting(self, message_module):
+    populated = message_module.TestAllTypes()
+    test_util.SetAllNonLazyFields(populated)
+    empty = message_module.TestEmptyMessage()
+    empty.ParseFromString(populated.SerializeToString())
+    self.assertEqual(str(empty), '')
+
+  def testRepeatedNestedFieldIteration(self, message_module):
+    msg = message_module.TestAllTypes()
+    msg.repeated_nested_message.add(bb=1)
+    msg.repeated_nested_message.add(bb=2)
+    msg.repeated_nested_message.add(bb=3)
+    msg.repeated_nested_message.add(bb=4)
+
+    self.assertEqual([1, 2, 3, 4],
+                     [m.bb for m in msg.repeated_nested_message])
+    self.assertEqual([4, 3, 2, 1],
+                     [m.bb for m in reversed(msg.repeated_nested_message)])
+    self.assertEqual([4, 3, 2, 1],
+                     [m.bb for m in msg.repeated_nested_message[::-1]])
+
+  def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module):
+    """Check some different types with the default comparator."""
+    message = message_module.TestAllTypes()
+
+    # TODO(mattp): would testing more scalar types strengthen test?
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(3)
+    message.repeated_int32.append(2)
+    message.repeated_int32.sort()
+    self.assertEqual(message.repeated_int32[0], 1)
+    self.assertEqual(message.repeated_int32[1], 2)
+    self.assertEqual(message.repeated_int32[2], 3)
+
+    message.repeated_float.append(1.1)
+    message.repeated_float.append(1.3)
+    message.repeated_float.append(1.2)
+    message.repeated_float.sort()
+    self.assertAlmostEqual(message.repeated_float[0], 1.1)
+    self.assertAlmostEqual(message.repeated_float[1], 1.2)
+    self.assertAlmostEqual(message.repeated_float[2], 1.3)
+
+    message.repeated_string.append('a')
+    message.repeated_string.append('c')
+    message.repeated_string.append('b')
+    message.repeated_string.sort()
+    self.assertEqual(message.repeated_string[0], 'a')
+    self.assertEqual(message.repeated_string[1], 'b')
+    self.assertEqual(message.repeated_string[2], 'c')
+
+    message.repeated_bytes.append(b'a')
+    message.repeated_bytes.append(b'c')
+    message.repeated_bytes.append(b'b')
+    message.repeated_bytes.sort()
+    self.assertEqual(message.repeated_bytes[0], b'a')
+    self.assertEqual(message.repeated_bytes[1], b'b')
+    self.assertEqual(message.repeated_bytes[2], b'c')
+
+  def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
+    """Check some different types with custom comparator."""
+    message = message_module.TestAllTypes()
+
+    message.repeated_int32.append(-3)
+    message.repeated_int32.append(-2)
+    message.repeated_int32.append(-1)
+    message.repeated_int32.sort(key=abs)
+    self.assertEqual(message.repeated_int32[0], -1)
+    self.assertEqual(message.repeated_int32[1], -2)
+    self.assertEqual(message.repeated_int32[2], -3)
+
+    message.repeated_string.append('aaa')
+    message.repeated_string.append('bb')
+    message.repeated_string.append('c')
+    message.repeated_string.sort(key=len)
+    self.assertEqual(message.repeated_string[0], 'c')
+    self.assertEqual(message.repeated_string[1], 'bb')
+    self.assertEqual(message.repeated_string[2], 'aaa')
+
+  def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module):
+    """Check passing a custom comparator to sort a repeated composite field."""
+    message = message_module.TestAllTypes()
+
+    message.repeated_nested_message.add().bb = 1
+    message.repeated_nested_message.add().bb = 3
+    message.repeated_nested_message.add().bb = 2
+    message.repeated_nested_message.add().bb = 6
+    message.repeated_nested_message.add().bb = 5
+    message.repeated_nested_message.add().bb = 4
+    message.repeated_nested_message.sort(key=operator.attrgetter('bb'))
+    self.assertEqual(message.repeated_nested_message[0].bb, 1)
+    self.assertEqual(message.repeated_nested_message[1].bb, 2)
+    self.assertEqual(message.repeated_nested_message[2].bb, 3)
+    self.assertEqual(message.repeated_nested_message[3].bb, 4)
+    self.assertEqual(message.repeated_nested_message[4].bb, 5)
+    self.assertEqual(message.repeated_nested_message[5].bb, 6)
+
+  def testSortingRepeatedCompositeFieldsStable(self, message_module):
+    """Check passing a custom comparator to sort a repeated composite field."""
+    message = message_module.TestAllTypes()
+
+    message.repeated_nested_message.add().bb = 21
+    message.repeated_nested_message.add().bb = 20
+    message.repeated_nested_message.add().bb = 13
+    message.repeated_nested_message.add().bb = 33
+    message.repeated_nested_message.add().bb = 11
+    message.repeated_nested_message.add().bb = 24
+    message.repeated_nested_message.add().bb = 10
+    message.repeated_nested_message.sort(key=lambda z: z.bb // 10)
+    self.assertEqual(
+        [13, 11, 10, 21, 20, 24, 33],
+        [n.bb for n in message.repeated_nested_message])
+
+    # Make sure that for the C++ implementation, the underlying fields
+    # are actually reordered.
+    pb = message.SerializeToString()
+    message.Clear()
+    message.MergeFromString(pb)
+    self.assertEqual(
+        [13, 11, 10, 21, 20, 24, 33],
+        [n.bb for n in message.repeated_nested_message])
+
+  def testRepeatedCompositeFieldSortArguments(self, message_module):
+    """Check sorting a repeated composite field using list.sort() arguments."""
+    message = message_module.TestAllTypes()
+
+    get_bb = operator.attrgetter('bb')
+    cmp_bb = lambda a, b: cmp(a.bb, b.bb)
+    message.repeated_nested_message.add().bb = 1
+    message.repeated_nested_message.add().bb = 3
+    message.repeated_nested_message.add().bb = 2
+    message.repeated_nested_message.add().bb = 6
+    message.repeated_nested_message.add().bb = 5
+    message.repeated_nested_message.add().bb = 4
+    message.repeated_nested_message.sort(key=get_bb)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [1, 2, 3, 4, 5, 6])
+    message.repeated_nested_message.sort(key=get_bb, reverse=True)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [6, 5, 4, 3, 2, 1])
+    if sys.version_info >= (3,): return  # No cmp sorting in PY3.
+    message.repeated_nested_message.sort(sort_function=cmp_bb)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [1, 2, 3, 4, 5, 6])
+    message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [6, 5, 4, 3, 2, 1])
+
+  def testRepeatedScalarFieldSortArguments(self, message_module):
+    """Check sorting a scalar field using list.sort() arguments."""
+    message = message_module.TestAllTypes()
+
+    message.repeated_int32.append(-3)
+    message.repeated_int32.append(-2)
+    message.repeated_int32.append(-1)
+    message.repeated_int32.sort(key=abs)
+    self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+    message.repeated_int32.sort(key=abs, reverse=True)
+    self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+    if sys.version_info < (3,):  # No cmp sorting in PY3.
+      abs_cmp = lambda a, b: cmp(abs(a), abs(b))
+      message.repeated_int32.sort(sort_function=abs_cmp)
+      self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+      message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
+      self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+
+    message.repeated_string.append('aaa')
+    message.repeated_string.append('bb')
+    message.repeated_string.append('c')
+    message.repeated_string.sort(key=len)
+    self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+    message.repeated_string.sort(key=len, reverse=True)
+    self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+    if sys.version_info < (3,):  # No cmp sorting in PY3.
+      len_cmp = lambda a, b: cmp(len(a), len(b))
+      message.repeated_string.sort(sort_function=len_cmp)
+      self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+      message.repeated_string.sort(cmp=len_cmp, reverse=True)
+      self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+
+  def testRepeatedFieldsComparable(self, message_module):
+    m1 = message_module.TestAllTypes()
+    m2 = message_module.TestAllTypes()
+    m1.repeated_int32.append(0)
+    m1.repeated_int32.append(1)
+    m1.repeated_int32.append(2)
+    m2.repeated_int32.append(0)
+    m2.repeated_int32.append(1)
+    m2.repeated_int32.append(2)
+    m1.repeated_nested_message.add().bb = 1
+    m1.repeated_nested_message.add().bb = 2
+    m1.repeated_nested_message.add().bb = 3
+    m2.repeated_nested_message.add().bb = 1
+    m2.repeated_nested_message.add().bb = 2
+    m2.repeated_nested_message.add().bb = 3
+
+    if sys.version_info >= (3,): return  # No cmp() in PY3.
+
+    # These comparisons should not raise errors.
+    _ = m1 < m2
+    _ = m1.repeated_nested_message < m2.repeated_nested_message
+
+    # Make sure cmp always works. If it wasn't defined, these would be
+    # id() comparisons and would all fail.
+    self.assertEqual(cmp(m1, m2), 0)
+    self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0)
+    self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0)
+    self.assertEqual(cmp(m1.repeated_nested_message,
+                         m2.repeated_nested_message), 0)
+    with self.assertRaises(TypeError):
+      # Can't compare repeated composite containers to lists.
+      cmp(m1.repeated_nested_message, m2.repeated_nested_message[:])
+
+    # TODO(anuraag): Implement extensiondict comparison in C++ and then add test
+
+  def testRepeatedFieldsAreSequences(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIsInstance(m.repeated_int32, collections.MutableSequence)
+    self.assertIsInstance(m.repeated_nested_message,
+                          collections.MutableSequence)
+
+  def ensureNestedMessageExists(self, msg, attribute):
+    """Make sure that a nested message object exists.
+
+    As soon as a nested message attribute is accessed, it will be present in the
+    _fields dict, without being marked as actually being set.
+    """
+    getattr(msg, attribute)
+    self.assertFalse(msg.HasField(attribute))
+
+  def testOneofGetCaseNonexistingField(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
+
+  def testOneofDefaultValues(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+
+    # Oneof is set even when setting it to a default value.
+    m.oneof_uint32 = 0
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+    self.assertFalse(m.HasField('oneof_string'))
+
+    m.oneof_string = ""
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_string'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+
+  def testOneofSemantics(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+    m.oneof_uint32 = 11
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+
+    m.oneof_string = u'foo'
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertTrue(m.HasField('oneof_string'))
+
+    # Read nested message accessor without accessing submessage.
+    m.oneof_nested_message
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_string'))
+    self.assertFalse(m.HasField('oneof_nested_message'))
+
+    # Read accessor of nested message without accessing submessage.
+    m.oneof_nested_message.bb
+    self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+    self.assertTrue(m.HasField('oneof_string'))
+    self.assertFalse(m.HasField('oneof_nested_message'))
+
+    m.oneof_nested_message.bb = 11
+    self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_string'))
+    self.assertTrue(m.HasField('oneof_nested_message'))
+
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+    self.assertFalse(m.HasField('oneof_nested_message'))
+    self.assertTrue(m.HasField('oneof_bytes'))
+
+  def testOneofCompositeFieldReadAccess(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+
+    self.ensureNestedMessageExists(m, 'oneof_nested_message')
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    self.assertEqual(11, m.oneof_uint32)
+
+  def testOneofWhichOneof(self, message_module):
+    m = message_module.TestAllTypes()
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+
+    m.oneof_uint32 = 11
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertTrue(m.HasField('oneof_field'))
+
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
+    m.ClearField('oneof_bytes')
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+
+  def testOneofClearField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.ClearField('oneof_field')
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+  def testOneofClearSetField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.ClearField('oneof_uint32')
+    if message_module is unittest_pb2:
+      self.assertFalse(m.HasField('oneof_field'))
+    self.assertFalse(m.HasField('oneof_uint32'))
+    self.assertIs(None, m.WhichOneof('oneof_field'))
+
+  def testOneofClearUnsetField(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    self.ensureNestedMessageExists(m, 'oneof_nested_message')
+    m.ClearField('oneof_nested_message')
+    self.assertEqual(11, m.oneof_uint32)
+    if message_module is unittest_pb2:
+      self.assertTrue(m.HasField('oneof_field'))
+    self.assertTrue(m.HasField('oneof_uint32'))
+    self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+
+  def testOneofDeserialize(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    m2.ParseFromString(m.SerializeToString())
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+  def testOneofCopyFrom(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    m2.CopyFrom(m)
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+  def testOneofNestedMergeFrom(self, message_module):
+    m = message_module.NestedTestAllTypes()
+    m.payload.oneof_uint32 = 11
+    m2 = message_module.NestedTestAllTypes()
+    m2.payload.oneof_bytes = b'bb'
+    m2.child.payload.oneof_bytes = b'bb'
+    m2.MergeFrom(m)
+    self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
+    self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
+
+  def testOneofMessageMergeFrom(self, message_module):
+    m = message_module.NestedTestAllTypes()
+    m.payload.oneof_nested_message.bb = 11
+    m.child.payload.oneof_nested_message.bb = 12
+    m2 = message_module.NestedTestAllTypes()
+    m2.payload.oneof_uint32 = 13
+    m2.MergeFrom(m)
+    self.assertEqual('oneof_nested_message',
+                     m2.payload.WhichOneof('oneof_field'))
+    self.assertEqual('oneof_nested_message',
+                     m2.child.payload.WhichOneof('oneof_field'))
+
+  def testOneofNestedMessageInit(self, message_module):
+    m = message_module.TestAllTypes(
+        oneof_nested_message=message_module.TestAllTypes.NestedMessage())
+    self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
+
+  def testOneofClear(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m.Clear()
+    self.assertIsNone(m.WhichOneof('oneof_field'))
+    m.oneof_bytes = b'bb'
+    self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
+  def testAssignByteStringToUnicodeField(self, message_module):
+    """Assigning a byte string to a string field should result
+    in the value being converted to a Unicode string."""
+    m = message_module.TestAllTypes()
+    m.optional_string = str('')
+    self.assertIsInstance(m.optional_string, six.text_type)
+
+  def testLongValuedSlice(self, message_module):
+    """It should be possible to use long-valued indicies in slices
+
+    This didn't used to work in the v2 C++ implementation.
+    """
+    m = message_module.TestAllTypes()
+
+    # Repeated scalar
+    m.repeated_int32.append(1)
+    sl = m.repeated_int32[long(0):long(len(m.repeated_int32))]
+    self.assertEqual(len(m.repeated_int32), len(sl))
+
+    # Repeated composite
+    m.repeated_nested_message.add().bb = 3
+    sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))]
+    self.assertEqual(len(m.repeated_nested_message), len(sl))
+
+  def testExtendShouldNotSwallowExceptions(self, message_module):
+    """This didn't use to work in the v2 C++ implementation."""
+    m = message_module.TestAllTypes()
+    with self.assertRaises(NameError) as _:
+      m.repeated_int32.extend(a for i in range(10))  # pylint: disable=undefined-variable
+    with self.assertRaises(NameError) as _:
+      m.repeated_nested_enum.extend(
+          a for i in range(10))  # pylint: disable=undefined-variable
+
+  FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()]
+
+  def testExtendInt32WithNothing(self, message_module):
+    """Test no-ops extending repeated int32 fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_int32.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_int32)
+
+    m.repeated_int32.extend([])
+    self.assertSequenceEqual([], m.repeated_int32)
+
+  def testExtendFloatWithNothing(self, message_module):
+    """Test no-ops extending repeated float fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_float.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_float)
+
+    m.repeated_float.extend([])
+    self.assertSequenceEqual([], m.repeated_float)
+
+  def testExtendStringWithNothing(self, message_module):
+    """Test no-ops extending repeated string fields."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+
+    # TODO(ptucker): Deprecate this behavior. b/18413862
+    for falsy_value in MessageTest.FALSY_VALUES:
+      m.repeated_string.extend(falsy_value)
+      self.assertSequenceEqual([], m.repeated_string)
+
+    m.repeated_string.extend([])
+    self.assertSequenceEqual([], m.repeated_string)
+
+  def testExtendInt32WithPythonList(self, message_module):
+    """Test extending repeated int32 fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend([0])
+    self.assertSequenceEqual([0], m.repeated_int32)
+    m.repeated_int32.extend([1, 2])
+    self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+    m.repeated_int32.extend([3, 4])
+    self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+  def testExtendFloatWithPythonList(self, message_module):
+    """Test extending repeated float fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend([0.0])
+    self.assertSequenceEqual([0.0], m.repeated_float)
+    m.repeated_float.extend([1.0, 2.0])
+    self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+    m.repeated_float.extend([3.0, 4.0])
+    self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+  def testExtendStringWithPythonList(self, message_module):
+    """Test extending repeated string fields with python lists."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend([''])
+    self.assertSequenceEqual([''], m.repeated_string)
+    m.repeated_string.extend(['11', '22'])
+    self.assertSequenceEqual(['', '11', '22'], m.repeated_string)
+    m.repeated_string.extend(['33', '44'])
+    self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string)
+
+  def testExtendStringWithString(self, message_module):
+    """Test extending repeated string fields with characters from a string."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend('abc')
+    self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string)
+
+  class TestIterable(object):
+    """This iterable object mimics the behavior of numpy.array.
+
+    __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1.
+
+    """
+
+    def __init__(self, values=None):
+      self._list = values or []
+
+    def __nonzero__(self):
+      size = len(self._list)
+      if size == 0:
+        return False
+      if size == 1:
+        return bool(self._list[0])
+      raise ValueError('Truth value is ambiguous.')
+
+    def __len__(self):
+      return len(self._list)
+
+    def __iter__(self):
+      return self._list.__iter__()
+
+  def testExtendInt32WithIterable(self, message_module):
+    """Test extending repeated int32 fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([0]))
+    self.assertSequenceEqual([0], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([1, 2]))
+    self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+    m.repeated_int32.extend(MessageTest.TestIterable([3, 4]))
+    self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+  def testExtendFloatWithIterable(self, message_module):
+    """Test extending repeated float fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([0.0]))
+    self.assertSequenceEqual([0.0], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0]))
+    self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+    m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0]))
+    self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+  def testExtendStringWithIterable(self, message_module):
+    """Test extending repeated string fields with iterable."""
+    m = message_module.TestAllTypes()
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable([]))
+    self.assertSequenceEqual([], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['']))
+    self.assertSequenceEqual([''], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['1', '2']))
+    self.assertSequenceEqual(['', '1', '2'], m.repeated_string)
+    m.repeated_string.extend(MessageTest.TestIterable(['3', '4']))
+    self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string)
+
+  def testPickleRepeatedScalarContainer(self, message_module):
+    # TODO(tibell): The pure-Python implementation support pickling of
+    #   scalar containers in *some* cases. For now the cpp2 version
+    #   throws an exception to avoid a segfault. Investigate if we
+    #   want to support pickling of these fields.
+    #
+    # For more information see: https://b2.corp.google.com/u/0/issues/18677897
+    if (api_implementation.Type() != 'cpp' or
+        api_implementation.Version() == 2):
+      return
+    m = message_module.TestAllTypes()
+    with self.assertRaises(pickle.PickleError) as _:
+      pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL)
+
+  def testSortEmptyRepeatedCompositeContainer(self, message_module):
+    """Exercise a scenario that has led to segfaults in the past.
+    """
+    m = message_module.TestAllTypes()
+    m.repeated_nested_message.sort()
+
+  def testHasFieldOnRepeatedField(self, message_module):
+    """Using HasField on a repeated field should raise an exception.
+    """
+    m = message_module.TestAllTypes()
+    with self.assertRaises(ValueError) as _:
+      m.HasField('repeated_int32')
+
+  def testRepeatedScalarFieldPop(self, message_module):
+    m = message_module.TestAllTypes()
+    with self.assertRaises(IndexError) as _:
+      m.repeated_int32.pop()
+    m.repeated_int32.extend(range(5))
+    self.assertEqual(4, m.repeated_int32.pop())
+    self.assertEqual(0, m.repeated_int32.pop(0))
+    self.assertEqual(2, m.repeated_int32.pop(1))
+    self.assertEqual([1, 3], m.repeated_int32)
+
+  def testRepeatedCompositeFieldPop(self, message_module):
+    m = message_module.TestAllTypes()
+    with self.assertRaises(IndexError) as _:
+      m.repeated_nested_message.pop()
+    for i in range(5):
+      n = m.repeated_nested_message.add()
+      n.bb = i
+    self.assertEqual(4, m.repeated_nested_message.pop().bb)
+    self.assertEqual(0, m.repeated_nested_message.pop(0).bb)
+    self.assertEqual(2, m.repeated_nested_message.pop(1).bb)
+    self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message])
+
+
+# Class to test proto2-only features (required, extensions, etc.)
+class Proto2Test(unittest.TestCase):
+
+  def testFieldPresence(self):
+    message = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(message.HasField("optional_int32"))
+    self.assertFalse(message.HasField("optional_bool"))
+    self.assertFalse(message.HasField("optional_nested_message"))
+
+    with self.assertRaises(ValueError):
+      message.HasField("field_doesnt_exist")
+
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_int32")
+    with self.assertRaises(ValueError):
+      message.HasField("repeated_nested_message")
+
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+    # Fields are set even when setting the values to default values.
+    message.optional_int32 = 0
+    message.optional_bool = False
+    message.optional_nested_message.bb = 0
+    self.assertTrue(message.HasField("optional_int32"))
+    self.assertTrue(message.HasField("optional_bool"))
+    self.assertTrue(message.HasField("optional_nested_message"))
+
+    # Set the fields to non-default values.
+    message.optional_int32 = 5
+    message.optional_bool = True
+    message.optional_nested_message.bb = 15
+
+    self.assertTrue(message.HasField("optional_int32"))
+    self.assertTrue(message.HasField("optional_bool"))
+    self.assertTrue(message.HasField("optional_nested_message"))
+
+    # Clearing the fields unsets them and resets their value to default.
+    message.ClearField("optional_int32")
+    message.ClearField("optional_bool")
+    message.ClearField("optional_nested_message")
+
+    self.assertFalse(message.HasField("optional_int32"))
+    self.assertFalse(message.HasField("optional_bool"))
+    self.assertFalse(message.HasField("optional_nested_message"))
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+  # TODO(tibell): The C++ implementations actually allows assignment
+  # of unknown enum values to *scalar* fields (but not repeated
+  # fields). Once checked enum fields becomes the default in the
+  # Python implementation, the C++ implementation should follow suit.
+  def testAssignInvalidEnum(self):
+    """It should not be possible to assign an invalid enum number to an
+    enum field."""
+    m = unittest_pb2.TestAllTypes()
+
+    with self.assertRaises(ValueError) as _:
+      m.optional_nested_enum = 1234567
+    self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567)
+
+  def testGoldenExtensions(self):
+    golden_data = test_util.GoldenFileData('golden_message')
+    golden_message = unittest_pb2.TestAllExtensions()
+    golden_message.ParseFromString(golden_data)
+    all_set = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(all_set)
+    self.assertEqual(all_set, golden_message)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testGoldenPackedExtensions(self):
+    golden_data = test_util.GoldenFileData('golden_packed_fields_message')
+    golden_message = unittest_pb2.TestPackedExtensions()
+    golden_message.ParseFromString(golden_data)
+    all_set = unittest_pb2.TestPackedExtensions()
+    test_util.SetAllPackedExtensions(all_set)
+    self.assertEqual(all_set, golden_message)
+    self.assertEqual(golden_data, all_set.SerializeToString())
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testPickleIncompleteProto(self):
+    golden_message = unittest_pb2.TestRequired(a=1)
+    pickled_message = pickle.dumps(golden_message)
+
+    unpickled_message = pickle.loads(pickled_message)
+    self.assertEqual(unpickled_message, golden_message)
+    self.assertEqual(unpickled_message.a, 1)
+    # This is still an incomplete proto - so serializing should fail
+    self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
+
+
+  # TODO(haberman): this isn't really a proto2-specific test except that this
+  # message has a required field in it.  Should probably be factored out so
+  # that we can test the other parts with proto3.
+  def testParsingMerge(self):
+    """Check the merge behavior when a required or optional field appears
+    multiple times in the input."""
+    messages = [
+        unittest_pb2.TestAllTypes(),
+        unittest_pb2.TestAllTypes(),
+        unittest_pb2.TestAllTypes() ]
+    messages[0].optional_int32 = 1
+    messages[1].optional_int64 = 2
+    messages[2].optional_int32 = 3
+    messages[2].optional_string = 'hello'
+
+    merged_message = unittest_pb2.TestAllTypes()
+    merged_message.optional_int32 = 3
+    merged_message.optional_int64 = 2
+    merged_message.optional_string = 'hello'
+
+    generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
+    generator.field1.extend(messages)
+    generator.field2.extend(messages)
+    generator.field3.extend(messages)
+    generator.ext1.extend(messages)
+    generator.ext2.extend(messages)
+    generator.group1.add().field1.MergeFrom(messages[0])
+    generator.group1.add().field1.MergeFrom(messages[1])
+    generator.group1.add().field1.MergeFrom(messages[2])
+    generator.group2.add().field1.MergeFrom(messages[0])
+    generator.group2.add().field1.MergeFrom(messages[1])
+    generator.group2.add().field1.MergeFrom(messages[2])
+
+    data = generator.SerializeToString()
+    parsing_merge = unittest_pb2.TestParsingMerge()
+    parsing_merge.ParseFromString(data)
+
+    # Required and optional fields should be merged.
+    self.assertEqual(parsing_merge.required_all_types, merged_message)
+    self.assertEqual(parsing_merge.optional_all_types, merged_message)
+    self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
+                     merged_message)
+    self.assertEqual(parsing_merge.Extensions[
+                     unittest_pb2.TestParsingMerge.optional_ext],
+                     merged_message)
+
+    # Repeated fields should not be merged.
+    self.assertEqual(len(parsing_merge.repeated_all_types), 3)
+    self.assertEqual(len(parsing_merge.repeatedgroup), 3)
+    self.assertEqual(len(parsing_merge.Extensions[
+        unittest_pb2.TestParsingMerge.repeated_ext]), 3)
+
+  def testPythonicInit(self):
+    message = unittest_pb2.TestAllTypes(
+        optional_int32=100,
+        optional_fixed32=200,
+        optional_float=300.5,
+        optional_bytes=b'x',
+        optionalgroup={'a': 400},
+        optional_nested_message={'bb': 500},
+        optional_nested_enum='BAZ',
+        repeatedgroup=[{'a': 600},
+                       {'a': 700}],
+        repeated_nested_enum=['FOO', unittest_pb2.TestAllTypes.BAR],
+        default_int32=800,
+        oneof_string='y')
+    self.assertIsInstance(message, unittest_pb2.TestAllTypes)
+    self.assertEqual(100, message.optional_int32)
+    self.assertEqual(200, message.optional_fixed32)
+    self.assertEqual(300.5, message.optional_float)
+    self.assertEqual(b'x', message.optional_bytes)
+    self.assertEqual(400, message.optionalgroup.a)
+    self.assertIsInstance(message.optional_nested_message, unittest_pb2.TestAllTypes.NestedMessage)
+    self.assertEqual(500, message.optional_nested_message.bb)
+    self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                     message.optional_nested_enum)
+    self.assertEqual(2, len(message.repeatedgroup))
+    self.assertEqual(600, message.repeatedgroup[0].a)
+    self.assertEqual(700, message.repeatedgroup[1].a)
+    self.assertEqual(2, len(message.repeated_nested_enum))
+    self.assertEqual(unittest_pb2.TestAllTypes.FOO,
+                     message.repeated_nested_enum[0])
+    self.assertEqual(unittest_pb2.TestAllTypes.BAR,
+                     message.repeated_nested_enum[1])
+    self.assertEqual(800, message.default_int32)
+    self.assertEqual('y', message.oneof_string)
+    self.assertFalse(message.HasField('optional_int64'))
+    self.assertEqual(0, len(message.repeated_float))
+    self.assertEqual(42, message.default_int64)
+
+    message = unittest_pb2.TestAllTypes(optional_nested_enum=u'BAZ')
+    self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                     message.optional_nested_enum)
+
+    with self.assertRaises(ValueError):
+      unittest_pb2.TestAllTypes(
+          optional_nested_message={'INVALID_NESTED_FIELD': 17})
+
+    with self.assertRaises(TypeError):
+      unittest_pb2.TestAllTypes(
+          optional_nested_message={'bb': 'INVALID_VALUE_TYPE'})
+
+    with self.assertRaises(ValueError):
+      unittest_pb2.TestAllTypes(optional_nested_enum='INVALID_LABEL')
+
+    with self.assertRaises(ValueError):
+      unittest_pb2.TestAllTypes(repeated_nested_enum='FOO')
+
+
+
+# Class to test proto3-only features/behavior (updated field presence & enums)
+class Proto3Test(unittest.TestCase):
+
+  # Utility method for comparing equality with a map.
+  def assertMapIterEquals(self, map_iter, dict_value):
+    # Avoid mutating caller's copy.
+    dict_value = dict(dict_value)
+
+    for k, v in map_iter:
+      self.assertEqual(v, dict_value[k])
+      del dict_value[k]
+
+    self.assertEqual({}, dict_value)
+
+  def testFieldPresence(self):
+    message = unittest_proto3_arena_pb2.TestAllTypes()
+
+    # We can't test presence of non-repeated, non-submessage fields.
+    with self.assertRaises(ValueError):
+      message.HasField('optional_int32')
+    with self.assertRaises(ValueError):
+      message.HasField('optional_float')
+    with self.assertRaises(ValueError):
+      message.HasField('optional_string')
+    with self.assertRaises(ValueError):
+      message.HasField('optional_bool')
+
+    # But we can still test presence of submessage fields.
+    self.assertFalse(message.HasField('optional_nested_message'))
+
+    # As with proto2, we can't test presence of fields that don't exist, or
+    # repeated fields.
+    with self.assertRaises(ValueError):
+      message.HasField('field_doesnt_exist')
+
+    with self.assertRaises(ValueError):
+      message.HasField('repeated_int32')
+    with self.assertRaises(ValueError):
+      message.HasField('repeated_nested_message')
+
+    # Fields should default to their type-specific default.
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(0, message.optional_float)
+    self.assertEqual('', message.optional_string)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+    # Setting a submessage should still return proper presence information.
+    message.optional_nested_message.bb = 0
+    self.assertTrue(message.HasField('optional_nested_message'))
+
+    # Set the fields to non-default values.
+    message.optional_int32 = 5
+    message.optional_float = 1.1
+    message.optional_string = 'abc'
+    message.optional_bool = True
+    message.optional_nested_message.bb = 15
+
+    # Clearing the fields unsets them and resets their value to default.
+    message.ClearField('optional_int32')
+    message.ClearField('optional_float')
+    message.ClearField('optional_string')
+    message.ClearField('optional_bool')
+    message.ClearField('optional_nested_message')
+
+    self.assertEqual(0, message.optional_int32)
+    self.assertEqual(0, message.optional_float)
+    self.assertEqual('', message.optional_string)
+    self.assertEqual(False, message.optional_bool)
+    self.assertEqual(0, message.optional_nested_message.bb)
+
+  def testAssignUnknownEnum(self):
+    """Assigning an unknown enum value is allowed and preserves the value."""
+    m = unittest_proto3_arena_pb2.TestAllTypes()
+
+    m.optional_nested_enum = 1234567
+    self.assertEqual(1234567, m.optional_nested_enum)
+    m.repeated_nested_enum.append(22334455)
+    self.assertEqual(22334455, m.repeated_nested_enum[0])
+    # Assignment is a different code path than append for the C++ impl.
+    m.repeated_nested_enum[0] = 7654321
+    self.assertEqual(7654321, m.repeated_nested_enum[0])
+    serialized = m.SerializeToString()
+
+    m2 = unittest_proto3_arena_pb2.TestAllTypes()
+    m2.ParseFromString(serialized)
+    self.assertEqual(1234567, m2.optional_nested_enum)
+    self.assertEqual(7654321, m2.repeated_nested_enum[0])
+
+  # Map isn't really a proto3-only feature. But there is no proto2 equivalent
+  # of google/protobuf/map_unittest.proto right now, so it's not easy to
+  # test both with the same test like we do for the other proto2/proto3 tests.
+  # (google/protobuf/map_protobuf_unittest.proto is very different in the set
+  # of messages and fields it contains).
+  def testScalarMapDefaults(self):
+    msg = map_unittest_pb2.TestMap()
+
+    # Scalars start out unset.
+    self.assertFalse(-123 in msg.map_int32_int32)
+    self.assertFalse(-2**33 in msg.map_int64_int64)
+    self.assertFalse(123 in msg.map_uint32_uint32)
+    self.assertFalse(2**33 in msg.map_uint64_uint64)
+    self.assertFalse(123 in msg.map_int32_double)
+    self.assertFalse(False in msg.map_bool_bool)
+    self.assertFalse('abc' in msg.map_string_string)
+    self.assertFalse(111 in msg.map_int32_bytes)
+    self.assertFalse(888 in msg.map_int32_enum)
+
+    # Accessing an unset key returns the default.
+    self.assertEqual(0, msg.map_int32_int32[-123])
+    self.assertEqual(0, msg.map_int64_int64[-2**33])
+    self.assertEqual(0, msg.map_uint32_uint32[123])
+    self.assertEqual(0, msg.map_uint64_uint64[2**33])
+    self.assertEqual(0.0, msg.map_int32_double[123])
+    self.assertTrue(isinstance(msg.map_int32_double[123], float))
+    self.assertEqual(False, msg.map_bool_bool[False])
+    self.assertTrue(isinstance(msg.map_bool_bool[False], bool))
+    self.assertEqual('', msg.map_string_string['abc'])
+    self.assertEqual(b'', msg.map_int32_bytes[111])
+    self.assertEqual(0, msg.map_int32_enum[888])
+
+    # It also sets the value in the map
+    self.assertTrue(-123 in msg.map_int32_int32)
+    self.assertTrue(-2**33 in msg.map_int64_int64)
+    self.assertTrue(123 in msg.map_uint32_uint32)
+    self.assertTrue(2**33 in msg.map_uint64_uint64)
+    self.assertTrue(123 in msg.map_int32_double)
+    self.assertTrue(False in msg.map_bool_bool)
+    self.assertTrue('abc' in msg.map_string_string)
+    self.assertTrue(111 in msg.map_int32_bytes)
+    self.assertTrue(888 in msg.map_int32_enum)
+
+    self.assertIsInstance(msg.map_string_string['abc'], six.text_type)
+
+    # Accessing an unset key still throws TypeError if the type of the key
+    # is incorrect.
+    with self.assertRaises(TypeError):
+      msg.map_string_string[123]
+
+    with self.assertRaises(TypeError):
+      123 in msg.map_string_string
+
+  def testMapGet(self):
+    # Need to test that get() properly returns the default, even though the dict
+    # has defaultdict-like semantics.
+    msg = map_unittest_pb2.TestMap()
+
+    self.assertIsNone(msg.map_int32_int32.get(5))
+    self.assertEqual(10, msg.map_int32_int32.get(5, 10))
+    self.assertIsNone(msg.map_int32_int32.get(5))
+
+    msg.map_int32_int32[5] = 15
+    self.assertEqual(15, msg.map_int32_int32.get(5))
+
+    self.assertIsNone(msg.map_int32_foreign_message.get(5))
+    self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10))
+
+    submsg = msg.map_int32_foreign_message[5]
+    self.assertIs(submsg, msg.map_int32_foreign_message.get(5))
+
+  def testScalarMap(self):
+    msg = map_unittest_pb2.TestMap()
+
+    self.assertEqual(0, len(msg.map_int32_int32))
+    self.assertFalse(5 in msg.map_int32_int32)
+
+    msg.map_int32_int32[-123] = -456
+    msg.map_int64_int64[-2**33] = -2**34
+    msg.map_uint32_uint32[123] = 456
+    msg.map_uint64_uint64[2**33] = 2**34
+    msg.map_string_string['abc'] = '123'
+    msg.map_int32_enum[888] = 2
+
+    self.assertEqual([], msg.FindInitializationErrors())
+
+    self.assertEqual(1, len(msg.map_string_string))
+
+    # Bad key.
+    with self.assertRaises(TypeError):
+      msg.map_string_string[123] = '123'
+
+    # Verify that trying to assign a bad key doesn't actually add a member to
+    # the map.
+    self.assertEqual(1, len(msg.map_string_string))
+
+    # Bad value.
+    with self.assertRaises(TypeError):
+      msg.map_string_string['123'] = 123
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.ParseFromString(serialized)
+
+    # Bad key.
+    with self.assertRaises(TypeError):
+      msg2.map_string_string[123] = '123'
+
+    # Bad value.
+    with self.assertRaises(TypeError):
+      msg2.map_string_string['123'] = 123
+
+    self.assertEqual(-456, msg2.map_int32_int32[-123])
+    self.assertEqual(-2**34, msg2.map_int64_int64[-2**33])
+    self.assertEqual(456, msg2.map_uint32_uint32[123])
+    self.assertEqual(2**34, msg2.map_uint64_uint64[2**33])
+    self.assertEqual('123', msg2.map_string_string['abc'])
+    self.assertEqual(2, msg2.map_int32_enum[888])
+
+  def testStringUnicodeConversionInMap(self):
+    msg = map_unittest_pb2.TestMap()
+
+    unicode_obj = u'\u1234'
+    bytes_obj = unicode_obj.encode('utf8')
+
+    msg.map_string_string[bytes_obj] = bytes_obj
+
+    (key, value) = list(msg.map_string_string.items())[0]
+
+    self.assertEqual(key, unicode_obj)
+    self.assertEqual(value, unicode_obj)
+
+    self.assertIsInstance(key, six.text_type)
+    self.assertIsInstance(value, six.text_type)
+
+  def testMessageMap(self):
+    msg = map_unittest_pb2.TestMap()
+
+    self.assertEqual(0, len(msg.map_int32_foreign_message))
+    self.assertFalse(5 in msg.map_int32_foreign_message)
+
+    msg.map_int32_foreign_message[123]
+    # get_or_create() is an alias for getitem.
+    msg.map_int32_foreign_message.get_or_create(-456)
+
+    self.assertEqual(2, len(msg.map_int32_foreign_message))
+    self.assertIn(123, msg.map_int32_foreign_message)
+    self.assertIn(-456, msg.map_int32_foreign_message)
+    self.assertEqual(2, len(msg.map_int32_foreign_message))
+
+    # Bad key.
+    with self.assertRaises(TypeError):
+      msg.map_int32_foreign_message['123']
+
+    # Can't assign directly to submessage.
+    with self.assertRaises(ValueError):
+      msg.map_int32_foreign_message[999] = msg.map_int32_foreign_message[123]
+
+    # Verify that trying to assign a bad key doesn't actually add a member to
+    # the map.
+    self.assertEqual(2, len(msg.map_int32_foreign_message))
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.ParseFromString(serialized)
+
+    self.assertEqual(2, len(msg2.map_int32_foreign_message))
+    self.assertIn(123, msg2.map_int32_foreign_message)
+    self.assertIn(-456, msg2.map_int32_foreign_message)
+    self.assertEqual(2, len(msg2.map_int32_foreign_message))
+
+  def testMergeFrom(self):
+    msg = map_unittest_pb2.TestMap()
+    msg.map_int32_int32[12] = 34
+    msg.map_int32_int32[56] = 78
+    msg.map_int64_int64[22] = 33
+    msg.map_int32_foreign_message[111].c = 5
+    msg.map_int32_foreign_message[222].c = 10
+
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.map_int32_int32[12] = 55
+    msg2.map_int64_int64[88] = 99
+    msg2.map_int32_foreign_message[222].c = 15
+
+    msg2.MergeFrom(msg)
+
+    self.assertEqual(34, msg2.map_int32_int32[12])
+    self.assertEqual(78, msg2.map_int32_int32[56])
+    self.assertEqual(33, msg2.map_int64_int64[22])
+    self.assertEqual(99, msg2.map_int64_int64[88])
+    self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
+    self.assertEqual(10, msg2.map_int32_foreign_message[222].c)
+
+    # Verify that there is only one entry per key, even though the MergeFrom
+    # may have internally created multiple entries for a single key in the
+    # list representation.
+    as_dict = {}
+    for key in msg2.map_int32_foreign_message:
+      self.assertFalse(key in as_dict)
+      as_dict[key] = msg2.map_int32_foreign_message[key].c
+
+    self.assertEqual({111: 5, 222: 10}, as_dict)
+
+    # Special case: test that delete of item really removes the item, even if
+    # there might have physically been duplicate keys due to the previous merge.
+    # This is only a special case for the C++ implementation which stores the
+    # map as an array.
+    del msg2.map_int32_int32[12]
+    self.assertFalse(12 in msg2.map_int32_int32)
+
+    del msg2.map_int32_foreign_message[222]
+    self.assertFalse(222 in msg2.map_int32_foreign_message)
+
+  def testMergeFromBadType(self):
+    msg = map_unittest_pb2.TestMap()
+    with self.assertRaisesRegexp(
+        TypeError,
+        r'Parameter to MergeFrom\(\) must be instance of same class: expected '
+        r'.*TestMap got int\.'):
+      msg.MergeFrom(1)
+
+  def testCopyFromBadType(self):
+    msg = map_unittest_pb2.TestMap()
+    with self.assertRaisesRegexp(
+        TypeError,
+        r'Parameter to [A-Za-z]*From\(\) must be instance of same class: '
+        r'expected .*TestMap got int\.'):
+      msg.CopyFrom(1)
+
+  def testIntegerMapWithLongs(self):
+    msg = map_unittest_pb2.TestMap()
+    msg.map_int32_int32[long(-123)] = long(-456)
+    msg.map_int64_int64[long(-2**33)] = long(-2**34)
+    msg.map_uint32_uint32[long(123)] = long(456)
+    msg.map_uint64_uint64[long(2**33)] = long(2**34)
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.ParseFromString(serialized)
+
+    self.assertEqual(-456, msg2.map_int32_int32[-123])
+    self.assertEqual(-2**34, msg2.map_int64_int64[-2**33])
+    self.assertEqual(456, msg2.map_uint32_uint32[123])
+    self.assertEqual(2**34, msg2.map_uint64_uint64[2**33])
+
+  def testMapAssignmentCausesPresence(self):
+    msg = map_unittest_pb2.TestMapSubmessage()
+    msg.test_map.map_int32_int32[123] = 456
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMapSubmessage()
+    msg2.ParseFromString(serialized)
+
+    self.assertEqual(msg, msg2)
+
+    # Now test that various mutations of the map properly invalidate the
+    # cached size of the submessage.
+    msg.test_map.map_int32_int32[888] = 999
+    serialized = msg.SerializeToString()
+    msg2.ParseFromString(serialized)
+    self.assertEqual(msg, msg2)
+
+    msg.test_map.map_int32_int32.clear()
+    serialized = msg.SerializeToString()
+    msg2.ParseFromString(serialized)
+    self.assertEqual(msg, msg2)
+
+  def testMapAssignmentCausesPresenceForSubmessages(self):
+    msg = map_unittest_pb2.TestMapSubmessage()
+    msg.test_map.map_int32_foreign_message[123].c = 5
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMapSubmessage()
+    msg2.ParseFromString(serialized)
+
+    self.assertEqual(msg, msg2)
+
+    # Now test that various mutations of the map properly invalidate the
+    # cached size of the submessage.
+    msg.test_map.map_int32_foreign_message[888].c = 7
+    serialized = msg.SerializeToString()
+    msg2.ParseFromString(serialized)
+    self.assertEqual(msg, msg2)
+
+    msg.test_map.map_int32_foreign_message[888].MergeFrom(
+        msg.test_map.map_int32_foreign_message[123])
+    serialized = msg.SerializeToString()
+    msg2.ParseFromString(serialized)
+    self.assertEqual(msg, msg2)
+
+    msg.test_map.map_int32_foreign_message.clear()
+    serialized = msg.SerializeToString()
+    msg2.ParseFromString(serialized)
+    self.assertEqual(msg, msg2)
+
+  def testModifyMapWhileIterating(self):
+    msg = map_unittest_pb2.TestMap()
+
+    string_string_iter = iter(msg.map_string_string)
+    int32_foreign_iter = iter(msg.map_int32_foreign_message)
+
+    msg.map_string_string['abc'] = '123'
+    msg.map_int32_foreign_message[5].c = 5
+
+    with self.assertRaises(RuntimeError):
+      for key in string_string_iter:
+        pass
+
+    with self.assertRaises(RuntimeError):
+      for key in int32_foreign_iter:
+        pass
+
+  def testSubmessageMap(self):
+    msg = map_unittest_pb2.TestMap()
+
+    submsg = msg.map_int32_foreign_message[111]
+    self.assertIs(submsg, msg.map_int32_foreign_message[111])
+    self.assertIsInstance(submsg, unittest_pb2.ForeignMessage)
+
+    submsg.c = 5
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.ParseFromString(serialized)
+
+    self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
+
+    # Doesn't allow direct submessage assignment.
+    with self.assertRaises(ValueError):
+      msg.map_int32_foreign_message[88] = unittest_pb2.ForeignMessage()
+
+  def testMapIteration(self):
+    msg = map_unittest_pb2.TestMap()
+
+    for k, v in msg.map_int32_int32.items():
+      # Should not be reached.
+      self.assertTrue(False)
+
+    msg.map_int32_int32[2] = 4
+    msg.map_int32_int32[3] = 6
+    msg.map_int32_int32[4] = 8
+    self.assertEqual(3, len(msg.map_int32_int32))
+
+    matching_dict = {2: 4, 3: 6, 4: 8}
+    self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict)
+
+  def testMapItems(self):
+    # Map items used to have strange behaviors when use c extension. Because
+    # [] may reorder the map and invalidate any exsting iterators.
+    # TODO(jieluo): Check if [] reordering the map is a bug or intended
+    # behavior.
+    msg = map_unittest_pb2.TestMap()
+    msg.map_string_string['local_init_op'] = ''
+    msg.map_string_string['trainable_variables'] = ''
+    msg.map_string_string['variables'] = ''
+    msg.map_string_string['init_op'] = ''
+    msg.map_string_string['summaries'] = ''
+    items1 = msg.map_string_string.items()
+    items2 = msg.map_string_string.items()
+    self.assertEqual(items1, items2)
+
+  def testMapIterationClearMessage(self):
+    # Iterator needs to work even if message and map are deleted.
+    msg = map_unittest_pb2.TestMap()
+
+    msg.map_int32_int32[2] = 4
+    msg.map_int32_int32[3] = 6
+    msg.map_int32_int32[4] = 8
+
+    it = msg.map_int32_int32.items()
+    del msg
+
+    matching_dict = {2: 4, 3: 6, 4: 8}
+    self.assertMapIterEquals(it, matching_dict)
+
+  def testMapConstruction(self):
+    msg = map_unittest_pb2.TestMap(map_int32_int32={1: 2, 3: 4})
+    self.assertEqual(2, msg.map_int32_int32[1])
+    self.assertEqual(4, msg.map_int32_int32[3])
+
+    msg = map_unittest_pb2.TestMap(
+        map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)})
+    self.assertEqual(5, msg.map_int32_foreign_message[3].c)
+
+  def testMapValidAfterFieldCleared(self):
+    # Map needs to work even if field is cleared.
+    # For the C++ implementation this tests the correctness of
+    # ScalarMapContainer::Release()
+    msg = map_unittest_pb2.TestMap()
+    int32_map = msg.map_int32_int32
+
+    int32_map[2] = 4
+    int32_map[3] = 6
+    int32_map[4] = 8
+
+    msg.ClearField('map_int32_int32')
+    self.assertEqual(b'', msg.SerializeToString())
+    matching_dict = {2: 4, 3: 6, 4: 8}
+    self.assertMapIterEquals(int32_map.items(), matching_dict)
+
+  def testMessageMapValidAfterFieldCleared(self):
+    # Map needs to work even if field is cleared.
+    # For the C++ implementation this tests the correctness of
+    # ScalarMapContainer::Release()
+    msg = map_unittest_pb2.TestMap()
+    int32_foreign_message = msg.map_int32_foreign_message
+
+    int32_foreign_message[2].c = 5
+
+    msg.ClearField('map_int32_foreign_message')
+    self.assertEqual(b'', msg.SerializeToString())
+    self.assertTrue(2 in int32_foreign_message.keys())
+
+  def testMapIterInvalidatedByClearField(self):
+    # Map iterator is invalidated when field is cleared.
+    # But this case does need to not crash the interpreter.
+    # For the C++ implementation this tests the correctness of
+    # ScalarMapContainer::Release()
+    msg = map_unittest_pb2.TestMap()
+
+    it = iter(msg.map_int32_int32)
+
+    msg.ClearField('map_int32_int32')
+    with self.assertRaises(RuntimeError):
+      for _ in it:
+        pass
+
+    it = iter(msg.map_int32_foreign_message)
+    msg.ClearField('map_int32_foreign_message')
+    with self.assertRaises(RuntimeError):
+      for _ in it:
+        pass
+
+  def testMapDelete(self):
+    msg = map_unittest_pb2.TestMap()
+
+    self.assertEqual(0, len(msg.map_int32_int32))
+
+    msg.map_int32_int32[4] = 6
+    self.assertEqual(1, len(msg.map_int32_int32))
+
+    with self.assertRaises(KeyError):
+      del msg.map_int32_int32[88]
+
+    del msg.map_int32_int32[4]
+    self.assertEqual(0, len(msg.map_int32_int32))
+
+  def testMapsAreMapping(self):
+    msg = map_unittest_pb2.TestMap()
+    self.assertIsInstance(msg.map_int32_int32, collections.Mapping)
+    self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping)
+    self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping)
+    self.assertIsInstance(msg.map_int32_foreign_message,
+                          collections.MutableMapping)
+
+  def testMapFindInitializationErrorsSmokeTest(self):
+    msg = map_unittest_pb2.TestMap()
+    msg.map_string_string['abc'] = '123'
+    msg.map_int32_int32[35] = 64
+    msg.map_string_foreign_message['foo'].c = 5
+    self.assertEqual(0, len(msg.FindInitializationErrors()))
+
+
+
+class ValidTypeNamesTest(unittest.TestCase):
+
+  def assertImportFromName(self, msg, base_name):
+    # Parse <type 'module.class_name'> to extra 'some.name' as a string.
+    tp_name = str(type(msg)).split("'")[1]
+    valid_names = ('Repeated%sContainer' % base_name,
+                   'Repeated%sFieldContainer' % base_name)
+    self.assertTrue(any(tp_name.endswith(v) for v in valid_names),
+                    '%r does end with any of %r' % (tp_name, valid_names))
+
+    parts = tp_name.split('.')
+    class_name = parts[-1]
+    module_name = '.'.join(parts[:-1])
+    __import__(module_name, fromlist=[class_name])
+
+  def testTypeNamesCanBeImported(self):
+    # If import doesn't work, pickling won't work either.
+    pb = unittest_pb2.TestAllTypes()
+    self.assertImportFromName(pb.repeated_int32, 'Scalar')
+    self.assertImportFromName(pb.repeated_nested_message, 'Composite')
+
+class PackedFieldTest(unittest.TestCase):
+
+  def setMessage(self, message):
+    message.repeated_int32.append(1)
+    message.repeated_int64.append(1)
+    message.repeated_uint32.append(1)
+    message.repeated_uint64.append(1)
+    message.repeated_sint32.append(1)
+    message.repeated_sint64.append(1)
+    message.repeated_fixed32.append(1)
+    message.repeated_fixed64.append(1)
+    message.repeated_sfixed32.append(1)
+    message.repeated_sfixed64.append(1)
+    message.repeated_float.append(1.0)
+    message.repeated_double.append(1.0)
+    message.repeated_bool.append(True)
+    message.repeated_nested_enum.append(1)
+
+  def testPackedFields(self):
+    message = packed_field_test_pb2.TestPackedTypes()
+    self.setMessage(message)
+    golden_data = (b'\x0A\x01\x01'
+                   b'\x12\x01\x01'
+                   b'\x1A\x01\x01'
+                   b'\x22\x01\x01'
+                   b'\x2A\x01\x02'
+                   b'\x32\x01\x02'
+                   b'\x3A\x04\x01\x00\x00\x00'
+                   b'\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+                   b'\x4A\x04\x01\x00\x00\x00'
+                   b'\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+                   b'\x5A\x04\x00\x00\x80\x3f'
+                   b'\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f'
+                   b'\x6A\x01\x01'
+                   b'\x72\x01\x01')
+    self.assertEqual(golden_data, message.SerializeToString())
+
+  def testUnpackedFields(self):
+    message = packed_field_test_pb2.TestUnpackedTypes()
+    self.setMessage(message)
+    golden_data = (b'\x08\x01'
+                   b'\x10\x01'
+                   b'\x18\x01'
+                   b'\x20\x01'
+                   b'\x28\x02'
+                   b'\x30\x02'
+                   b'\x3D\x01\x00\x00\x00'
+                   b'\x41\x01\x00\x00\x00\x00\x00\x00\x00'
+                   b'\x4D\x01\x00\x00\x00'
+                   b'\x51\x01\x00\x00\x00\x00\x00\x00\x00'
+                   b'\x5D\x00\x00\x80\x3f'
+                   b'\x61\x00\x00\x00\x00\x00\x00\xf0\x3f'
+                   b'\x68\x01'
+                   b'\x70\x01')
+    self.assertEqual(golden_data, message.SerializeToString())
+
+
+@unittest.skipIf(api_implementation.Type() != 'cpp',
+                 'explicit tests of the C++ implementation')
+class OversizeProtosTest(unittest.TestCase):
+
+  def setUp(self):
+    self.file_desc = """
+      name: "f/f.msg2"
+      package: "f"
+      message_type {
+        name: "msg1"
+        field {
+          name: "payload"
+          number: 1
+          label: LABEL_OPTIONAL
+          type: TYPE_STRING
+        }
+      }
+      message_type {
+        name: "msg2"
+        field {
+          name: "field"
+          number: 1
+          label: LABEL_OPTIONAL
+          type: TYPE_MESSAGE
+          type_name: "msg1"
+        }
+      }
+    """
+    pool = descriptor_pool.DescriptorPool()
+    desc = descriptor_pb2.FileDescriptorProto()
+    text_format.Parse(self.file_desc, desc)
+    pool.Add(desc)
+    self.proto_cls = message_factory.MessageFactory(pool).GetPrototype(
+        pool.FindMessageTypeByName('f.msg2'))
+    self.p = self.proto_cls()
+    self.p.field.payload = 'c' * (1024 * 1024 * 64 + 1)
+    self.p_serialized = self.p.SerializeToString()
+
+  def testAssertOversizeProto(self):
+    from google.protobuf.pyext._message import SetAllowOversizeProtos
+    SetAllowOversizeProtos(False)
+    q = self.proto_cls()
+    try:
+      q.ParseFromString(self.p_serialized)
+    except message.DecodeError as e:
+      self.assertEqual(str(e), 'Error parsing message')
+
+  def testSucceedOversizeProto(self):
+    from google.protobuf.pyext._message import SetAllowOversizeProtos
+    SetAllowOversizeProtos(True)
+    q = self.proto_cls()
+    q.ParseFromString(self.p_serialized)
+    self.assertEqual(self.p.field.payload, q.field.payload)
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/missing_enum_values.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/missing_enum_values.proto
new file mode 100644
index 0000000..1850be5
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/missing_enum_values.proto
@@ -0,0 +1,56 @@
+// 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.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+message TestEnumValues {
+  enum NestedEnum {
+    ZERO = 0;
+    ONE = 1;
+  }
+  optional NestedEnum optional_nested_enum = 1;
+  repeated NestedEnum repeated_nested_enum = 2;
+  repeated NestedEnum packed_nested_enum = 3 [packed = true];
+}
+
+message TestMissingEnumValues {
+  enum NestedEnum {
+    TWO = 2;
+  }
+  optional NestedEnum optional_nested_enum = 1;
+  repeated NestedEnum repeated_nested_enum = 2;
+  repeated NestedEnum packed_nested_enum = 3 [packed = true];
+}
+
+message JustString {
+  required string dummy = 1;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions.proto
new file mode 100644
index 0000000..78f1467
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions.proto
@@ -0,0 +1,59 @@
+// 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.
+
+// Author: robinson@google.com (Will Robinson)
+
+syntax = "proto2";
+
+package google.protobuf.internal;
+
+
+message TopLevelMessage {
+  optional ExtendedMessage submessage = 1;
+}
+
+
+message ExtendedMessage {
+  extensions 1 to max;
+}
+
+
+message ForeignMessage {
+  optional int32 foreign_message_int = 1;
+}
+
+
+extend ExtendedMessage {
+  optional int32 optional_int_extension = 1;
+  optional ForeignMessage optional_message_extension = 2;
+
+  repeated int32 repeated_int_extension = 3;
+  repeated ForeignMessage repeated_message_extension = 4;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions_dynamic.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions_dynamic.proto
new file mode 100644
index 0000000..11f85ef
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -0,0 +1,50 @@
+// 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.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This file is used to test a corner case in the CPP implementation where the
+// generated C++ type is available for the extendee, but the extension is
+// defined in a file whose C++ type is not in the binary.
+
+syntax = "proto2";
+
+import "google/protobuf/internal/more_extensions.proto";
+
+package google.protobuf.internal;
+
+message DynamicMessageType {
+  optional int32 a = 1;
+}
+
+extend ExtendedMessage {
+  optional int32 dynamic_int32_extension = 100;
+  optional DynamicMessageType dynamic_message_extension = 101;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/more_messages.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/more_messages.proto
new file mode 100644
index 0000000..2c6ab9e
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/more_messages.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// Author: robinson@google.com (Will Robinson)
+
+syntax = "proto2";
+
+package google.protobuf.internal;
+
+// A message where tag numbers are listed out of order, to allow us to test our
+// canonicalization of serialized output, which should always be in tag order.
+// We also mix in some extensions for extra fun.
+message OutOfOrderFields {
+  optional   sint32 optional_sint32   =  5;
+  extensions 4 to 4;
+  optional   uint32 optional_uint32   =  3;
+  extensions 2 to 2;
+  optional    int32 optional_int32    =  1;
+};
+
+
+extend OutOfOrderFields {
+  optional   uint64 optional_uint64   =  4;
+  optional    int64 optional_int64    =  2;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/packed_field_test.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/packed_field_test.proto
new file mode 100644
index 0000000..0dfdc10
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/packed_field_test.proto
@@ -0,0 +1,73 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf.python.internal;
+
+message TestPackedTypes {
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+  }
+
+  repeated    int32 repeated_int32    =  1;
+  repeated    int64 repeated_int64    =  2;
+  repeated   uint32 repeated_uint32   =  3;
+  repeated   uint64 repeated_uint64   =  4;
+  repeated   sint32 repeated_sint32   =  5;
+  repeated   sint64 repeated_sint64   =  6;
+  repeated  fixed32 repeated_fixed32  =  7;
+  repeated  fixed64 repeated_fixed64  =  8;
+  repeated sfixed32 repeated_sfixed32 =  9;
+  repeated sfixed64 repeated_sfixed64 = 10;
+  repeated    float repeated_float    = 11;
+  repeated   double repeated_double   = 12;
+  repeated     bool repeated_bool     = 13;
+  repeated NestedEnum repeated_nested_enum = 14;
+}
+
+message TestUnpackedTypes {
+  repeated    int32 repeated_int32    =  1 [packed = false];
+  repeated    int64 repeated_int64    =  2 [packed = false];
+  repeated   uint32 repeated_uint32   =  3 [packed = false];
+  repeated   uint64 repeated_uint64   =  4 [packed = false];
+  repeated   sint32 repeated_sint32   =  5 [packed = false];
+  repeated   sint64 repeated_sint64   =  6 [packed = false];
+  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
+  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+  repeated    float repeated_float    = 11 [packed = false];
+  repeated   double repeated_double   = 12 [packed = false];
+  repeated     bool repeated_bool     = 13 [packed = false];
+  repeated TestPackedTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/proto_builder_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/proto_builder_test.py
new file mode 100644
index 0000000..36dfbfd
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/proto_builder_test.py
@@ -0,0 +1,96 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.proto_builder."""
+
+try:
+    from collections import OrderedDict
+except ImportError:
+    from ordereddict import OrderedDict  #PY26
+try:
+  import unittest2 as unittest
+except ImportError:
+  import unittest
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor_pool
+from google.protobuf import proto_builder
+from google.protobuf import text_format
+
+
+class ProtoBuilderTest(unittest.TestCase):
+
+  def setUp(self):
+    self.ordered_fields = OrderedDict([
+        ('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64),
+        ('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING),
+        ])
+    self._fields = dict(self.ordered_fields)
+
+  def testMakeSimpleProtoClass(self):
+    """Test that we can create a proto class."""
+    proto_cls = proto_builder.MakeSimpleProtoClass(
+        self._fields,
+        full_name='net.proto2.python.public.proto_builder_test.Test')
+    proto = proto_cls()
+    proto.foo = 12345
+    proto.bar = 'asdf'
+    self.assertMultiLineEqual(
+        'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto))
+
+  def testOrderedFields(self):
+    """Test that the field order is maintained when given an OrderedDict."""
+    proto_cls = proto_builder.MakeSimpleProtoClass(
+        self.ordered_fields,
+        full_name='net.proto2.python.public.proto_builder_test.OrderedTest')
+    proto = proto_cls()
+    proto.foo = 12345
+    proto.bar = 'asdf'
+    self.assertMultiLineEqual(
+        'foo: 12345\nbar: "asdf"\n', text_format.MessageToString(proto))
+
+  def testMakeSameProtoClassTwice(self):
+    """Test that the DescriptorPool is used."""
+    pool = descriptor_pool.DescriptorPool()
+    proto_cls1 = proto_builder.MakeSimpleProtoClass(
+        self._fields,
+        full_name='net.proto2.python.public.proto_builder_test.Test',
+        pool=pool)
+    proto_cls2 = proto_builder.MakeSimpleProtoClass(
+        self._fields,
+        full_name='net.proto2.python.public.proto_builder_test.Test',
+        pool=pool)
+    self.assertIs(proto_cls1.DESCRIPTOR, proto_cls2.DESCRIPTOR)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/python_message.py b/src/third_party/protobuf-3/python/google/protobuf/internal/python_message.py
new file mode 100755
index 0000000..f8f73dd
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/python_message.py
@@ -0,0 +1,1548 @@
+# 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.
+
+# This code is meant to work on Python 2.4 and above only.
+#
+# TODO(robinson): Helpers for verbose, common checks like seeing if a
+# descriptor's cpp_type is CPPTYPE_MESSAGE.
+
+"""Contains a metaclass and helper functions used to create
+protocol message classes from Descriptor objects at runtime.
+
+Recall that a metaclass is the "type" of a class.
+(A class is to a metaclass what an instance is to a class.)
+
+In this case, we use the GeneratedProtocolMessageType metaclass
+to inject all the useful functionality into the classes
+output by the protocol compiler at compile-time.
+
+The upshot of all this is that the real implementation
+details for ALL pure-Python protocol buffers are *here in
+this file*.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+from io import BytesIO
+import sys
+import struct
+import weakref
+
+import six
+try:
+  import six.moves.copyreg as copyreg
+except ImportError:
+  # On some platforms, for example gMac, we run native Python because there is
+  # nothing like hermetic Python. This means lesser control on the system and
+  # the six.moves package may be missing (is missing on 20150321 on gMac). Be
+  # extra conservative and try to load the old replacement if it fails.
+  import copy_reg as copyreg
+
+# We use "as" to avoid name collisions with variables.
+from google.protobuf.internal import containers
+from google.protobuf.internal import decoder
+from google.protobuf.internal import encoder
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf.internal import message_listener as message_listener_mod
+from google.protobuf.internal import type_checkers
+from google.protobuf.internal import well_known_types
+from google.protobuf.internal import wire_format
+from google.protobuf import descriptor as descriptor_mod
+from google.protobuf import message as message_mod
+from google.protobuf import symbol_database
+from google.protobuf import text_format
+
+_FieldDescriptor = descriptor_mod.FieldDescriptor
+_AnyFullTypeName = 'google.protobuf.Any'
+
+
+class GeneratedProtocolMessageType(type):
+
+  """Metaclass for protocol message classes created at runtime from Descriptors.
+
+  We add implementations for all methods described in the Message class.  We
+  also create properties to allow getting/setting all fields in the protocol
+  message.  Finally, we create slots to prevent users from accidentally
+  "setting" nonexistent fields in the protocol message, which then wouldn't get
+  serialized / deserialized properly.
+
+  The protocol compiler currently uses this metaclass to create protocol
+  message classes at runtime.  Clients can also manually create their own
+  classes at runtime, as in this example:
+
+  mydescriptor = Descriptor(.....)
+  class MyProtoClass(Message):
+    __metaclass__ = GeneratedProtocolMessageType
+    DESCRIPTOR = mydescriptor
+  myproto_instance = MyProtoClass()
+  myproto.foo_field = 23
+  ...
+
+  The above example will not work for nested types. If you wish to include them,
+  use reflection.MakeClass() instead of manually instantiating the class in
+  order to create the appropriate class structure.
+  """
+
+  # Must be consistent with the protocol-compiler code in
+  # proto2/compiler/internal/generator.*.
+  _DESCRIPTOR_KEY = 'DESCRIPTOR'
+
+  def __new__(cls, name, bases, dictionary):
+    """Custom allocation for runtime-generated class types.
+
+    We override __new__ because this is apparently the only place
+    where we can meaningfully set __slots__ on the class we're creating(?).
+    (The interplay between metaclasses and slots is not very well-documented).
+
+    Args:
+      name: Name of the class (ignored, but required by the
+        metaclass protocol).
+      bases: Base classes of the class we're constructing.
+        (Should be message.Message).  We ignore this field, but
+        it's required by the metaclass protocol
+      dictionary: The class dictionary of the class we're
+        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
+        a Descriptor object describing this protocol message
+        type.
+
+    Returns:
+      Newly-allocated class.
+    """
+    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+    if descriptor.full_name in well_known_types.WKTBASES:
+      bases += (well_known_types.WKTBASES[descriptor.full_name],)
+    _AddClassAttributesForNestedExtensions(descriptor, dictionary)
+    _AddSlots(descriptor, dictionary)
+
+    superclass = super(GeneratedProtocolMessageType, cls)
+    new_class = superclass.__new__(cls, name, bases, dictionary)
+    return new_class
+
+  def __init__(cls, name, bases, dictionary):
+    """Here we perform the majority of our work on the class.
+    We add enum getters, an __init__ method, implementations
+    of all Message methods, and properties for all fields
+    in the protocol type.
+
+    Args:
+      name: Name of the class (ignored, but required by the
+        metaclass protocol).
+      bases: Base classes of the class we're constructing.
+        (Should be message.Message).  We ignore this field, but
+        it's required by the metaclass protocol
+      dictionary: The class dictionary of the class we're
+        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
+        a Descriptor object describing this protocol message
+        type.
+    """
+    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+    cls._decoders_by_tag = {}
+    cls._extensions_by_name = {}
+    cls._extensions_by_number = {}
+    if (descriptor.has_options and
+        descriptor.GetOptions().message_set_wire_format):
+      cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
+          decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
+
+    # Attach stuff to each FieldDescriptor for quick lookup later on.
+    for field in descriptor.fields:
+      _AttachFieldHelpers(cls, field)
+
+    descriptor._concrete_class = cls  # pylint: disable=protected-access
+    _AddEnumValues(descriptor, cls)
+    _AddInitMethod(descriptor, cls)
+    _AddPropertiesForFields(descriptor, cls)
+    _AddPropertiesForExtensions(descriptor, cls)
+    _AddStaticMethods(cls)
+    _AddMessageMethods(descriptor, cls)
+    _AddPrivateHelperMethods(descriptor, cls)
+    copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
+
+    superclass = super(GeneratedProtocolMessageType, cls)
+    superclass.__init__(name, bases, dictionary)
+
+
+# Stateless helpers for GeneratedProtocolMessageType below.
+# Outside clients should not access these directly.
+#
+# I opted not to make any of these methods on the metaclass, to make it more
+# clear that I'm not really using any state there and to keep clients from
+# thinking that they have direct access to these construction helpers.
+
+
+def _PropertyName(proto_field_name):
+  """Returns the name of the public property attribute which
+  clients can use to get and (in some cases) set the value
+  of a protocol message field.
+
+  Args:
+    proto_field_name: The protocol message field name, exactly
+      as it appears (or would appear) in a .proto file.
+  """
+  # TODO(robinson): Escape Python keywords (e.g., yield), and test this support.
+  # nnorwitz makes my day by writing:
+  # """
+  # FYI.  See the keyword module in the stdlib. This could be as simple as:
+  #
+  # if keyword.iskeyword(proto_field_name):
+  #   return proto_field_name + "_"
+  # return proto_field_name
+  # """
+  # Kenton says:  The above is a BAD IDEA.  People rely on being able to use
+  #   getattr() and setattr() to reflectively manipulate field values.  If we
+  #   rename the properties, then every such user has to also make sure to apply
+  #   the same transformation.  Note that currently if you name a field "yield",
+  #   you can still access it just fine using getattr/setattr -- it's not even
+  #   that cumbersome to do so.
+  # TODO(kenton):  Remove this method entirely if/when everyone agrees with my
+  #   position.
+  return proto_field_name
+
+
+def _VerifyExtensionHandle(message, extension_handle):
+  """Verify that the given extension handle is valid."""
+
+  if not isinstance(extension_handle, _FieldDescriptor):
+    raise KeyError('HasExtension() expects an extension handle, got: %s' %
+                   extension_handle)
+
+  if not extension_handle.is_extension:
+    raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
+
+  if not extension_handle.containing_type:
+    raise KeyError('"%s" is missing a containing_type.'
+                   % extension_handle.full_name)
+
+  if extension_handle.containing_type is not message.DESCRIPTOR:
+    raise KeyError('Extension "%s" extends message type "%s", but this '
+                   'message is of type "%s".' %
+                   (extension_handle.full_name,
+                    extension_handle.containing_type.full_name,
+                    message.DESCRIPTOR.full_name))
+
+
+def _AddSlots(message_descriptor, dictionary):
+  """Adds a __slots__ entry to dictionary, containing the names of all valid
+  attributes for this message type.
+
+  Args:
+    message_descriptor: A Descriptor instance describing this message type.
+    dictionary: Class dictionary to which we'll add a '__slots__' entry.
+  """
+  dictionary['__slots__'] = ['_cached_byte_size',
+                             '_cached_byte_size_dirty',
+                             '_fields',
+                             '_unknown_fields',
+                             '_is_present_in_parent',
+                             '_listener',
+                             '_listener_for_children',
+                             '__weakref__',
+                             '_oneofs']
+
+
+def _IsMessageSetExtension(field):
+  return (field.is_extension and
+          field.containing_type.has_options and
+          field.containing_type.GetOptions().message_set_wire_format and
+          field.type == _FieldDescriptor.TYPE_MESSAGE and
+          field.label == _FieldDescriptor.LABEL_OPTIONAL)
+
+
+def _IsMapField(field):
+  return (field.type == _FieldDescriptor.TYPE_MESSAGE and
+          field.message_type.has_options and
+          field.message_type.GetOptions().map_entry)
+
+
+def _IsMessageMapField(field):
+  value_type = field.message_type.fields_by_name["value"]
+  return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
+
+
+def _AttachFieldHelpers(cls, field_descriptor):
+  is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
+  is_packable = (is_repeated and
+                 wire_format.IsTypePackable(field_descriptor.type))
+  if not is_packable:
+    is_packed = False
+  elif field_descriptor.containing_type.syntax == "proto2":
+    is_packed = (field_descriptor.has_options and
+                field_descriptor.GetOptions().packed)
+  else:
+    has_packed_false = (field_descriptor.has_options and
+                        field_descriptor.GetOptions().HasField("packed") and
+                        field_descriptor.GetOptions().packed == False)
+    is_packed = not has_packed_false
+  is_map_entry = _IsMapField(field_descriptor)
+
+  if is_map_entry:
+    field_encoder = encoder.MapEncoder(field_descriptor)
+    sizer = encoder.MapSizer(field_descriptor)
+  elif _IsMessageSetExtension(field_descriptor):
+    field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
+    sizer = encoder.MessageSetItemSizer(field_descriptor.number)
+  else:
+    field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
+        field_descriptor.number, is_repeated, is_packed)
+    sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
+        field_descriptor.number, is_repeated, is_packed)
+
+  field_descriptor._encoder = field_encoder
+  field_descriptor._sizer = sizer
+  field_descriptor._default_constructor = _DefaultValueConstructorForField(
+      field_descriptor)
+
+  def AddDecoder(wiretype, is_packed):
+    tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
+    decode_type = field_descriptor.type
+    if (decode_type == _FieldDescriptor.TYPE_ENUM and
+        type_checkers.SupportsOpenEnums(field_descriptor)):
+      decode_type = _FieldDescriptor.TYPE_INT32
+
+    oneof_descriptor = None
+    if field_descriptor.containing_oneof is not None:
+      oneof_descriptor = field_descriptor
+
+    if is_map_entry:
+      is_message_map = _IsMessageMapField(field_descriptor)
+
+      field_decoder = decoder.MapDecoder(
+          field_descriptor, _GetInitializeDefaultForMap(field_descriptor),
+          is_message_map)
+    else:
+      field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
+              field_descriptor.number, is_repeated, is_packed,
+              field_descriptor, field_descriptor._default_constructor)
+
+    cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
+
+  AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
+             False)
+
+  if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
+    # To support wire compatibility of adding packed = true, add a decoder for
+    # packed values regardless of the field's options.
+    AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
+
+
+def _AddClassAttributesForNestedExtensions(descriptor, dictionary):
+  extension_dict = descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.items():
+    assert extension_name not in dictionary
+    dictionary[extension_name] = extension_field
+
+
+def _AddEnumValues(descriptor, cls):
+  """Sets class-level attributes for all enum fields defined in this message.
+
+  Also exporting a class-level object that can name enum values.
+
+  Args:
+    descriptor: Descriptor object for this message type.
+    cls: Class we're constructing for this message type.
+  """
+  for enum_type in descriptor.enum_types:
+    setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type))
+    for enum_value in enum_type.values:
+      setattr(cls, enum_value.name, enum_value.number)
+
+
+def _GetInitializeDefaultForMap(field):
+  if field.label != _FieldDescriptor.LABEL_REPEATED:
+    raise ValueError('map_entry set on non-repeated field %s' % (
+        field.name))
+  fields_by_name = field.message_type.fields_by_name
+  key_checker = type_checkers.GetTypeChecker(fields_by_name['key'])
+
+  value_field = fields_by_name['value']
+  if _IsMessageMapField(field):
+    def MakeMessageMapDefault(message):
+      return containers.MessageMap(
+          message._listener_for_children, value_field.message_type, key_checker)
+    return MakeMessageMapDefault
+  else:
+    value_checker = type_checkers.GetTypeChecker(value_field)
+    def MakePrimitiveMapDefault(message):
+      return containers.ScalarMap(
+          message._listener_for_children, key_checker, value_checker)
+    return MakePrimitiveMapDefault
+
+def _DefaultValueConstructorForField(field):
+  """Returns a function which returns a default value for a field.
+
+  Args:
+    field: FieldDescriptor object for this field.
+
+  The returned function has one argument:
+    message: Message instance containing this field, or a weakref proxy
+      of same.
+
+  That function in turn returns a default value for this field.  The default
+    value may refer back to |message| via a weak reference.
+  """
+
+  if _IsMapField(field):
+    return _GetInitializeDefaultForMap(field)
+
+  if field.label == _FieldDescriptor.LABEL_REPEATED:
+    if field.has_default_value and field.default_value != []:
+      raise ValueError('Repeated field default value not empty list: %s' % (
+          field.default_value))
+    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      # We can't look at _concrete_class yet since it might not have
+      # been set.  (Depends on order in which we initialize the classes).
+      message_type = field.message_type
+      def MakeRepeatedMessageDefault(message):
+        return containers.RepeatedCompositeFieldContainer(
+            message._listener_for_children, field.message_type)
+      return MakeRepeatedMessageDefault
+    else:
+      type_checker = type_checkers.GetTypeChecker(field)
+      def MakeRepeatedScalarDefault(message):
+        return containers.RepeatedScalarFieldContainer(
+            message._listener_for_children, type_checker)
+      return MakeRepeatedScalarDefault
+
+  if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    # _concrete_class may not yet be initialized.
+    message_type = field.message_type
+    def MakeSubMessageDefault(message):
+      result = message_type._concrete_class()
+      result._SetListener(
+          _OneofListener(message, field)
+          if field.containing_oneof is not None
+          else message._listener_for_children)
+      return result
+    return MakeSubMessageDefault
+
+  def MakeScalarDefault(message):
+    # TODO(protobuf-team): This may be broken since there may not be
+    # default_value.  Combine with has_default_value somehow.
+    return field.default_value
+  return MakeScalarDefault
+
+
+def _ReraiseTypeErrorWithFieldName(message_name, field_name):
+  """Re-raise the currently-handled TypeError with the field name added."""
+  exc = sys.exc_info()[1]
+  if len(exc.args) == 1 and type(exc) is TypeError:
+    # simple TypeError; add field name to exception message
+    exc = TypeError('%s for field %s.%s' % (str(exc), message_name, field_name))
+
+  # re-raise possibly-amended exception with original traceback:
+  six.reraise(type(exc), exc, sys.exc_info()[2])
+
+
+def _AddInitMethod(message_descriptor, cls):
+  """Adds an __init__ method to cls."""
+
+  def _GetIntegerEnumValue(enum_type, value):
+    """Convert a string or integer enum value to an integer.
+
+    If the value is a string, it is converted to the enum value in
+    enum_type with the same name.  If the value is not a string, it's
+    returned as-is.  (No conversion or bounds-checking is done.)
+    """
+    if isinstance(value, six.string_types):
+      try:
+        return enum_type.values_by_name[value].number
+      except KeyError:
+        raise ValueError('Enum type %s: unknown label "%s"' % (
+            enum_type.full_name, value))
+    return value
+
+  def init(self, **kwargs):
+    self._cached_byte_size = 0
+    self._cached_byte_size_dirty = len(kwargs) > 0
+    self._fields = {}
+    # Contains a mapping from oneof field descriptors to the descriptor
+    # of the currently set field in that oneof field.
+    self._oneofs = {}
+
+    # _unknown_fields is () when empty for efficiency, and will be turned into
+    # a list if fields are added.
+    self._unknown_fields = ()
+    self._is_present_in_parent = False
+    self._listener = message_listener_mod.NullMessageListener()
+    self._listener_for_children = _Listener(self)
+    for field_name, field_value in kwargs.items():
+      field = _GetFieldByName(message_descriptor, field_name)
+      if field is None:
+        raise TypeError("%s() got an unexpected keyword argument '%s'" %
+                        (message_descriptor.name, field_name))
+      if field_value is None:
+        # field=None is the same as no field at all.
+        continue
+      if field.label == _FieldDescriptor.LABEL_REPEATED:
+        copy = field._default_constructor(self)
+        if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:  # Composite
+          if _IsMapField(field):
+            if _IsMessageMapField(field):
+              for key in field_value:
+                copy[key].MergeFrom(field_value[key])
+            else:
+              copy.update(field_value)
+          else:
+            for val in field_value:
+              if isinstance(val, dict):
+                copy.add(**val)
+              else:
+                copy.add().MergeFrom(val)
+        else:  # Scalar
+          if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
+            field_value = [_GetIntegerEnumValue(field.enum_type, val)
+                           for val in field_value]
+          copy.extend(field_value)
+        self._fields[field] = copy
+      elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        copy = field._default_constructor(self)
+        new_val = field_value
+        if isinstance(field_value, dict):
+          new_val = field.message_type._concrete_class(**field_value)
+        try:
+          copy.MergeFrom(new_val)
+        except TypeError:
+          _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
+        self._fields[field] = copy
+      else:
+        if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
+          field_value = _GetIntegerEnumValue(field.enum_type, field_value)
+        try:
+          setattr(self, field_name, field_value)
+        except TypeError:
+          _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
+
+  init.__module__ = None
+  init.__doc__ = None
+  cls.__init__ = init
+
+
+def _GetFieldByName(message_descriptor, field_name):
+  """Returns a field descriptor by field name.
+
+  Args:
+    message_descriptor: A Descriptor describing all fields in message.
+    field_name: The name of the field to retrieve.
+  Returns:
+    The field descriptor associated with the field name.
+  """
+  try:
+    return message_descriptor.fields_by_name[field_name]
+  except KeyError:
+    raise ValueError('Protocol message %s has no "%s" field.' %
+                     (message_descriptor.name, field_name))
+
+
+def _AddPropertiesForFields(descriptor, cls):
+  """Adds properties for all fields in this protocol message type."""
+  for field in descriptor.fields:
+    _AddPropertiesForField(field, cls)
+
+  if descriptor.is_extendable:
+    # _ExtensionDict is just an adaptor with no state so we allocate a new one
+    # every time it is accessed.
+    cls.Extensions = property(lambda self: _ExtensionDict(self))
+
+
+def _AddPropertiesForField(field, cls):
+  """Adds a public property for a protocol message field.
+  Clients can use this property to get and (in the case
+  of non-repeated scalar fields) directly set the value
+  of a protocol message field.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  # Catch it if we add other types that we should
+  # handle specially here.
+  assert _FieldDescriptor.MAX_CPPTYPE == 10
+
+  constant_name = field.name.upper() + "_FIELD_NUMBER"
+  setattr(cls, constant_name, field.number)
+
+  if field.label == _FieldDescriptor.LABEL_REPEATED:
+    _AddPropertiesForRepeatedField(field, cls)
+  elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    _AddPropertiesForNonRepeatedCompositeField(field, cls)
+  else:
+    _AddPropertiesForNonRepeatedScalarField(field, cls)
+
+
+def _AddPropertiesForRepeatedField(field, cls):
+  """Adds a public property for a "repeated" protocol message field.  Clients
+  can use this property to get the value of the field, which will be either a
+  _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
+  below).
+
+  Note that when clients add values to these containers, we perform
+  type-checking in the case of repeated scalar fields, and we also set any
+  necessary "has" bits as a side-effect.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+
+  def getter(self):
+    field_value = self._fields.get(field)
+    if field_value is None:
+      # Construct a new object to represent this field.
+      field_value = field._default_constructor(self)
+
+      # Atomically check if another thread has preempted us and, if not, swap
+      # in the new object we just created.  If someone has preempted us, we
+      # take that object and discard ours.
+      # WARNING:  We are relying on setdefault() being atomic.  This is true
+      #   in CPython but we haven't investigated others.  This warning appears
+      #   in several other locations in this file.
+      field_value = self._fields.setdefault(field, field_value)
+    return field_value
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  # We define a setter just so we can throw an exception with a more
+  # helpful error message.
+  def setter(self, new_value):
+    raise AttributeError('Assignment not allowed to repeated field '
+                         '"%s" in protocol message object.' % proto_field_name)
+
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForNonRepeatedScalarField(field, cls):
+  """Adds a public property for a nonrepeated, scalar protocol message field.
+  Clients can use this property to get and directly set the value of the field.
+  Note that when the client sets the value of a field by using this property,
+  all necessary "has" bits are set as a side-effect, and we also perform
+  type-checking.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+  type_checker = type_checkers.GetTypeChecker(field)
+  default_value = field.default_value
+  valid_values = set()
+  is_proto3 = field.containing_type.syntax == "proto3"
+
+  def getter(self):
+    # TODO(protobuf-team): This may be broken since there may not be
+    # default_value.  Combine with has_default_value somehow.
+    return self._fields.get(field, default_value)
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  clear_when_set_to_default = is_proto3 and not field.containing_oneof
+
+  def field_setter(self, new_value):
+    # pylint: disable=protected-access
+    # Testing the value for truthiness captures all of the proto3 defaults
+    # (0, 0.0, enum 0, and False).
+    new_value = type_checker.CheckValue(new_value)
+    if clear_when_set_to_default and not new_value:
+      self._fields.pop(field, None)
+    else:
+      self._fields[field] = new_value
+    # Check _cached_byte_size_dirty inline to improve performance, since scalar
+    # setters are called frequently.
+    if not self._cached_byte_size_dirty:
+      self._Modified()
+
+  if field.containing_oneof:
+    def setter(self, new_value):
+      field_setter(self, new_value)
+      self._UpdateOneofState(field)
+  else:
+    setter = field_setter
+
+  setter.__module__ = None
+  setter.__doc__ = 'Setter for %s.' % proto_field_name
+
+  # Add a property to encapsulate the getter/setter.
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForNonRepeatedCompositeField(field, cls):
+  """Adds a public property for a nonrepeated, composite protocol message field.
+  A composite field is a "group" or "message" field.
+
+  Clients can use this property to get the value of the field, but cannot
+  assign to the property directly.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  # TODO(robinson): Remove duplication with similar method
+  # for non-repeated scalars.
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+
+  def getter(self):
+    field_value = self._fields.get(field)
+    if field_value is None:
+      # Construct a new object to represent this field.
+      field_value = field._default_constructor(self)
+
+      # Atomically check if another thread has preempted us and, if not, swap
+      # in the new object we just created.  If someone has preempted us, we
+      # take that object and discard ours.
+      # WARNING:  We are relying on setdefault() being atomic.  This is true
+      #   in CPython but we haven't investigated others.  This warning appears
+      #   in several other locations in this file.
+      field_value = self._fields.setdefault(field, field_value)
+    return field_value
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  # We define a setter just so we can throw an exception with a more
+  # helpful error message.
+  def setter(self, new_value):
+    raise AttributeError('Assignment not allowed to composite field '
+                         '"%s" in protocol message object.' % proto_field_name)
+
+  # Add a property to encapsulate the getter.
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForExtensions(descriptor, cls):
+  """Adds properties for all fields in this protocol message type."""
+  extension_dict = descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.items():
+    constant_name = extension_name.upper() + "_FIELD_NUMBER"
+    setattr(cls, constant_name, extension_field.number)
+
+
+def _AddStaticMethods(cls):
+  # TODO(robinson): This probably needs to be thread-safe(?)
+  def RegisterExtension(extension_handle):
+    extension_handle.containing_type = cls.DESCRIPTOR
+    _AttachFieldHelpers(cls, extension_handle)
+
+    # Try to insert our extension, failing if an extension with the same number
+    # already exists.
+    actual_handle = cls._extensions_by_number.setdefault(
+        extension_handle.number, extension_handle)
+    if actual_handle is not extension_handle:
+      raise AssertionError(
+          'Extensions "%s" and "%s" both try to extend message type "%s" with '
+          'field number %d.' %
+          (extension_handle.full_name, actual_handle.full_name,
+           cls.DESCRIPTOR.full_name, extension_handle.number))
+
+    cls._extensions_by_name[extension_handle.full_name] = extension_handle
+
+    handle = extension_handle  # avoid line wrapping
+    if _IsMessageSetExtension(handle):
+      # MessageSet extension.  Also register under type name.
+      cls._extensions_by_name[
+          extension_handle.message_type.full_name] = extension_handle
+
+  cls.RegisterExtension = staticmethod(RegisterExtension)
+
+  def FromString(s):
+    message = cls()
+    message.MergeFromString(s)
+    return message
+  cls.FromString = staticmethod(FromString)
+
+
+def _IsPresent(item):
+  """Given a (FieldDescriptor, value) tuple from _fields, return true if the
+  value should be included in the list returned by ListFields()."""
+
+  if item[0].label == _FieldDescriptor.LABEL_REPEATED:
+    return bool(item[1])
+  elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    return item[1]._is_present_in_parent
+  else:
+    return True
+
+
+def _AddListFieldsMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def ListFields(self):
+    all_fields = [item for item in self._fields.items() if _IsPresent(item)]
+    all_fields.sort(key = lambda item: item[0].number)
+    return all_fields
+
+  cls.ListFields = ListFields
+
+_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"'
+_Proto2HasError = 'Protocol message has no non-repeated field "%s"'
+
+def _AddHasFieldMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  is_proto3 = (message_descriptor.syntax == "proto3")
+  error_msg = _Proto3HasError if is_proto3 else _Proto2HasError
+
+  hassable_fields = {}
+  for field in message_descriptor.fields:
+    if field.label == _FieldDescriptor.LABEL_REPEATED:
+      continue
+    # For proto3, only submessages and fields inside a oneof have presence.
+    if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and
+        not field.containing_oneof):
+      continue
+    hassable_fields[field.name] = field
+
+  if not is_proto3:
+    # Fields inside oneofs are never repeated (enforced by the compiler).
+    for oneof in message_descriptor.oneofs:
+      hassable_fields[oneof.name] = oneof
+
+  def HasField(self, field_name):
+    try:
+      field = hassable_fields[field_name]
+    except KeyError:
+      raise ValueError(error_msg % field_name)
+
+    if isinstance(field, descriptor_mod.OneofDescriptor):
+      try:
+        return HasField(self, self._oneofs[field].name)
+      except KeyError:
+        return False
+    else:
+      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        value = self._fields.get(field)
+        return value is not None and value._is_present_in_parent
+      else:
+        return field in self._fields
+
+  cls.HasField = HasField
+
+
+def _AddClearFieldMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def ClearField(self, field_name):
+    try:
+      field = message_descriptor.fields_by_name[field_name]
+    except KeyError:
+      try:
+        field = message_descriptor.oneofs_by_name[field_name]
+        if field in self._oneofs:
+          field = self._oneofs[field]
+        else:
+          return
+      except KeyError:
+        raise ValueError('Protocol message %s() has no "%s" field.' %
+                         (message_descriptor.name, field_name))
+
+    if field in self._fields:
+      # To match the C++ implementation, we need to invalidate iterators
+      # for map fields when ClearField() happens.
+      if hasattr(self._fields[field], 'InvalidateIterators'):
+        self._fields[field].InvalidateIterators()
+
+      # Note:  If the field is a sub-message, its listener will still point
+      #   at us.  That's fine, because the worst than can happen is that it
+      #   will call _Modified() and invalidate our byte size.  Big deal.
+      del self._fields[field]
+
+      if self._oneofs.get(field.containing_oneof, None) is field:
+        del self._oneofs[field.containing_oneof]
+
+    # Always call _Modified() -- even if nothing was changed, this is
+    # a mutating method, and thus calling it should cause the field to become
+    # present in the parent message.
+    self._Modified()
+
+  cls.ClearField = ClearField
+
+
+def _AddClearExtensionMethod(cls):
+  """Helper for _AddMessageMethods()."""
+  def ClearExtension(self, extension_handle):
+    _VerifyExtensionHandle(self, extension_handle)
+
+    # Similar to ClearField(), above.
+    if extension_handle in self._fields:
+      del self._fields[extension_handle]
+    self._Modified()
+  cls.ClearExtension = ClearExtension
+
+
+def _AddHasExtensionMethod(cls):
+  """Helper for _AddMessageMethods()."""
+  def HasExtension(self, extension_handle):
+    _VerifyExtensionHandle(self, extension_handle)
+    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+      raise KeyError('"%s" is repeated.' % extension_handle.full_name)
+
+    if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      value = self._fields.get(extension_handle)
+      return value is not None and value._is_present_in_parent
+    else:
+      return extension_handle in self._fields
+  cls.HasExtension = HasExtension
+
+def _InternalUnpackAny(msg):
+  """Unpacks Any message and returns the unpacked message.
+
+  This internal method is differnt from public Any Unpack method which takes
+  the target message as argument. _InternalUnpackAny method does not have
+  target message type and need to find the message type in descriptor pool.
+
+  Args:
+    msg: An Any message to be unpacked.
+
+  Returns:
+    The unpacked message.
+  """
+  type_url = msg.type_url
+  db = symbol_database.Default()
+
+  if not type_url:
+    return None
+
+  # TODO(haberman): For now we just strip the hostname.  Better logic will be
+  # required.
+  type_name = type_url.split("/")[-1]
+  descriptor = db.pool.FindMessageTypeByName(type_name)
+
+  if descriptor is None:
+    return None
+
+  message_class = db.GetPrototype(descriptor)
+  message = message_class()
+
+  message.ParseFromString(msg.value)
+  return message
+
+def _AddEqualsMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __eq__(self, other):
+    if (not isinstance(other, message_mod.Message) or
+        other.DESCRIPTOR != self.DESCRIPTOR):
+      return False
+
+    if self is other:
+      return True
+
+    if self.DESCRIPTOR.full_name == _AnyFullTypeName:
+      any_a = _InternalUnpackAny(self)
+      any_b = _InternalUnpackAny(other)
+      if any_a and any_b:
+        return any_a == any_b
+
+    if not self.ListFields() == other.ListFields():
+      return False
+
+    # Sort unknown fields because their order shouldn't affect equality test.
+    unknown_fields = list(self._unknown_fields)
+    unknown_fields.sort()
+    other_unknown_fields = list(other._unknown_fields)
+    other_unknown_fields.sort()
+
+    return unknown_fields == other_unknown_fields
+
+  cls.__eq__ = __eq__
+
+
+def _AddStrMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __str__(self):
+    return text_format.MessageToString(self)
+  cls.__str__ = __str__
+
+
+def _AddReprMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __repr__(self):
+    return text_format.MessageToString(self)
+  cls.__repr__ = __repr__
+
+
+def _AddUnicodeMethod(unused_message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def __unicode__(self):
+    return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
+  cls.__unicode__ = __unicode__
+
+
+def _BytesForNonRepeatedElement(value, field_number, field_type):
+  """Returns the number of bytes needed to serialize a non-repeated element.
+  The returned byte count includes space for tag information and any
+  other additional space associated with serializing value.
+
+  Args:
+    value: Value we're serializing.
+    field_number: Field number of this value.  (Since the field number
+      is stored as part of a varint-encoded tag, this has an impact
+      on the total bytes required to serialize the value).
+    field_type: The type of the field.  One of the TYPE_* constants
+      within FieldDescriptor.
+  """
+  try:
+    fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
+    return fn(field_number, value)
+  except KeyError:
+    raise message_mod.EncodeError('Unrecognized field type: %d' % field_type)
+
+
+def _AddByteSizeMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def ByteSize(self):
+    if not self._cached_byte_size_dirty:
+      return self._cached_byte_size
+
+    size = 0
+    for field_descriptor, field_value in self.ListFields():
+      size += field_descriptor._sizer(field_value)
+
+    for tag_bytes, value_bytes in self._unknown_fields:
+      size += len(tag_bytes) + len(value_bytes)
+
+    self._cached_byte_size = size
+    self._cached_byte_size_dirty = False
+    self._listener_for_children.dirty = False
+    return size
+
+  cls.ByteSize = ByteSize
+
+
+def _AddSerializeToStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def SerializeToString(self):
+    # Check if the message has all of its required fields set.
+    errors = []
+    if not self.IsInitialized():
+      raise message_mod.EncodeError(
+          'Message %s is missing required fields: %s' % (
+          self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
+    return self.SerializePartialToString()
+  cls.SerializeToString = SerializeToString
+
+
+def _AddSerializePartialToStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def SerializePartialToString(self):
+    out = BytesIO()
+    self._InternalSerialize(out.write)
+    return out.getvalue()
+  cls.SerializePartialToString = SerializePartialToString
+
+  def InternalSerialize(self, write_bytes):
+    for field_descriptor, field_value in self.ListFields():
+      field_descriptor._encoder(write_bytes, field_value)
+    for tag_bytes, value_bytes in self._unknown_fields:
+      write_bytes(tag_bytes)
+      write_bytes(value_bytes)
+  cls._InternalSerialize = InternalSerialize
+
+
+def _AddMergeFromStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def MergeFromString(self, serialized):
+    length = len(serialized)
+    try:
+      if self._InternalParse(serialized, 0, length) != length:
+        # The only reason _InternalParse would return early is if it
+        # encountered an end-group tag.
+        raise message_mod.DecodeError('Unexpected end-group tag.')
+    except (IndexError, TypeError):
+      # Now ord(buf[p:p+1]) == ord('') gets TypeError.
+      raise message_mod.DecodeError('Truncated message.')
+    except struct.error as e:
+      raise message_mod.DecodeError(e)
+    return length   # Return this for legacy reasons.
+  cls.MergeFromString = MergeFromString
+
+  local_ReadTag = decoder.ReadTag
+  local_SkipField = decoder.SkipField
+  decoders_by_tag = cls._decoders_by_tag
+  is_proto3 = message_descriptor.syntax == "proto3"
+
+  def InternalParse(self, buffer, pos, end):
+    self._Modified()
+    field_dict = self._fields
+    unknown_field_list = self._unknown_fields
+    while pos != end:
+      (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
+      field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (None, None))
+      if field_decoder is None:
+        value_start_pos = new_pos
+        new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
+        if new_pos == -1:
+          return pos
+        if not is_proto3:
+          if not unknown_field_list:
+            unknown_field_list = self._unknown_fields = []
+          unknown_field_list.append(
+              (tag_bytes, buffer[value_start_pos:new_pos]))
+        pos = new_pos
+      else:
+        pos = field_decoder(buffer, new_pos, end, self, field_dict)
+        if field_desc:
+          self._UpdateOneofState(field_desc)
+    return pos
+  cls._InternalParse = InternalParse
+
+
+def _AddIsInitializedMethod(message_descriptor, cls):
+  """Adds the IsInitialized and FindInitializationError methods to the
+  protocol message class."""
+
+  required_fields = [field for field in message_descriptor.fields
+                           if field.label == _FieldDescriptor.LABEL_REQUIRED]
+
+  def IsInitialized(self, errors=None):
+    """Checks if all required fields of a message are set.
+
+    Args:
+      errors:  A list which, if provided, will be populated with the field
+               paths of all missing required fields.
+
+    Returns:
+      True iff the specified message has all required fields set.
+    """
+
+    # Performance is critical so we avoid HasField() and ListFields().
+
+    for field in required_fields:
+      if (field not in self._fields or
+          (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
+           not self._fields[field]._is_present_in_parent)):
+        if errors is not None:
+          errors.extend(self.FindInitializationErrors())
+        return False
+
+    for field, value in list(self._fields.items()):  # dict can change size!
+      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        if field.label == _FieldDescriptor.LABEL_REPEATED:
+          if (field.message_type.has_options and
+              field.message_type.GetOptions().map_entry):
+            continue
+          for element in value:
+            if not element.IsInitialized():
+              if errors is not None:
+                errors.extend(self.FindInitializationErrors())
+              return False
+        elif value._is_present_in_parent and not value.IsInitialized():
+          if errors is not None:
+            errors.extend(self.FindInitializationErrors())
+          return False
+
+    return True
+
+  cls.IsInitialized = IsInitialized
+
+  def FindInitializationErrors(self):
+    """Finds required fields which are not initialized.
+
+    Returns:
+      A list of strings.  Each string is a path to an uninitialized field from
+      the top-level message, e.g. "foo.bar[5].baz".
+    """
+
+    errors = []  # simplify things
+
+    for field in required_fields:
+      if not self.HasField(field.name):
+        errors.append(field.name)
+
+    for field, value in self.ListFields():
+      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        if field.is_extension:
+          name = "(%s)" % field.full_name
+        else:
+          name = field.name
+
+        if _IsMapField(field):
+          if _IsMessageMapField(field):
+            for key in value:
+              element = value[key]
+              prefix = "%s[%s]." % (name, key)
+              sub_errors = element.FindInitializationErrors()
+              errors += [prefix + error for error in sub_errors]
+          else:
+            # ScalarMaps can't have any initialization errors.
+            pass
+        elif field.label == _FieldDescriptor.LABEL_REPEATED:
+          for i in range(len(value)):
+            element = value[i]
+            prefix = "%s[%d]." % (name, i)
+            sub_errors = element.FindInitializationErrors()
+            errors += [prefix + error for error in sub_errors]
+        else:
+          prefix = name + "."
+          sub_errors = value.FindInitializationErrors()
+          errors += [prefix + error for error in sub_errors]
+
+    return errors
+
+  cls.FindInitializationErrors = FindInitializationErrors
+
+
+def _AddMergeFromMethod(cls):
+  LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
+  CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
+
+  def MergeFrom(self, msg):
+    if not isinstance(msg, cls):
+      raise TypeError(
+          "Parameter to MergeFrom() must be instance of same class: "
+          "expected %s got %s." % (cls.__name__, type(msg).__name__))
+
+    assert msg is not self
+    self._Modified()
+
+    fields = self._fields
+
+    for field, value in msg._fields.items():
+      if field.label == LABEL_REPEATED:
+        field_value = fields.get(field)
+        if field_value is None:
+          # Construct a new object to represent this field.
+          field_value = field._default_constructor(self)
+          fields[field] = field_value
+        field_value.MergeFrom(value)
+      elif field.cpp_type == CPPTYPE_MESSAGE:
+        if value._is_present_in_parent:
+          field_value = fields.get(field)
+          if field_value is None:
+            # Construct a new object to represent this field.
+            field_value = field._default_constructor(self)
+            fields[field] = field_value
+          field_value.MergeFrom(value)
+      else:
+        self._fields[field] = value
+        if field.containing_oneof:
+          self._UpdateOneofState(field)
+
+    if msg._unknown_fields:
+      if not self._unknown_fields:
+        self._unknown_fields = []
+      self._unknown_fields.extend(msg._unknown_fields)
+
+  cls.MergeFrom = MergeFrom
+
+
+def _AddWhichOneofMethod(message_descriptor, cls):
+  def WhichOneof(self, oneof_name):
+    """Returns the name of the currently set field inside a oneof, or None."""
+    try:
+      field = message_descriptor.oneofs_by_name[oneof_name]
+    except KeyError:
+      raise ValueError(
+          'Protocol message has no oneof "%s" field.' % oneof_name)
+
+    nested_field = self._oneofs.get(field, None)
+    if nested_field is not None and self.HasField(nested_field.name):
+      return nested_field.name
+    else:
+      return None
+
+  cls.WhichOneof = WhichOneof
+
+
+def _Clear(self):
+  # Clear fields.
+  self._fields = {}
+  self._unknown_fields = ()
+  self._oneofs = {}
+  self._Modified()
+
+
+def _DiscardUnknownFields(self):
+  self._unknown_fields = []
+  for field, value in self.ListFields():
+    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      if field.label == _FieldDescriptor.LABEL_REPEATED:
+        for sub_message in value:
+          sub_message.DiscardUnknownFields()
+      else:
+        value.DiscardUnknownFields()
+
+
+def _SetListener(self, listener):
+  if listener is None:
+    self._listener = message_listener_mod.NullMessageListener()
+  else:
+    self._listener = listener
+
+
+def _AddMessageMethods(message_descriptor, cls):
+  """Adds implementations of all Message methods to cls."""
+  _AddListFieldsMethod(message_descriptor, cls)
+  _AddHasFieldMethod(message_descriptor, cls)
+  _AddClearFieldMethod(message_descriptor, cls)
+  if message_descriptor.is_extendable:
+    _AddClearExtensionMethod(cls)
+    _AddHasExtensionMethod(cls)
+  _AddEqualsMethod(message_descriptor, cls)
+  _AddStrMethod(message_descriptor, cls)
+  _AddReprMethod(message_descriptor, cls)
+  _AddUnicodeMethod(message_descriptor, cls)
+  _AddByteSizeMethod(message_descriptor, cls)
+  _AddSerializeToStringMethod(message_descriptor, cls)
+  _AddSerializePartialToStringMethod(message_descriptor, cls)
+  _AddMergeFromStringMethod(message_descriptor, cls)
+  _AddIsInitializedMethod(message_descriptor, cls)
+  _AddMergeFromMethod(cls)
+  _AddWhichOneofMethod(message_descriptor, cls)
+  # Adds methods which do not depend on cls.
+  cls.Clear = _Clear
+  cls.DiscardUnknownFields = _DiscardUnknownFields
+  cls._SetListener = _SetListener
+
+
+def _AddPrivateHelperMethods(message_descriptor, cls):
+  """Adds implementation of private helper methods to cls."""
+
+  def Modified(self):
+    """Sets the _cached_byte_size_dirty bit to true,
+    and propagates this to our listener iff this was a state change.
+    """
+
+    # Note:  Some callers check _cached_byte_size_dirty before calling
+    #   _Modified() as an extra optimization.  So, if this method is ever
+    #   changed such that it does stuff even when _cached_byte_size_dirty is
+    #   already true, the callers need to be updated.
+    if not self._cached_byte_size_dirty:
+      self._cached_byte_size_dirty = True
+      self._listener_for_children.dirty = True
+      self._is_present_in_parent = True
+      self._listener.Modified()
+
+  def _UpdateOneofState(self, field):
+    """Sets field as the active field in its containing oneof.
+
+    Will also delete currently active field in the oneof, if it is different
+    from the argument. Does not mark the message as modified.
+    """
+    other_field = self._oneofs.setdefault(field.containing_oneof, field)
+    if other_field is not field:
+      del self._fields[other_field]
+      self._oneofs[field.containing_oneof] = field
+
+  cls._Modified = Modified
+  cls.SetInParent = Modified
+  cls._UpdateOneofState = _UpdateOneofState
+
+
+class _Listener(object):
+
+  """MessageListener implementation that a parent message registers with its
+  child message.
+
+  In order to support semantics like:
+
+    foo.bar.baz.qux = 23
+    assert foo.HasField('bar')
+
+  ...child objects must have back references to their parents.
+  This helper class is at the heart of this support.
+  """
+
+  def __init__(self, parent_message):
+    """Args:
+      parent_message: The message whose _Modified() method we should call when
+        we receive Modified() messages.
+    """
+    # This listener establishes a back reference from a child (contained) object
+    # to its parent (containing) object.  We make this a weak reference to avoid
+    # creating cyclic garbage when the client finishes with the 'parent' object
+    # in the tree.
+    if isinstance(parent_message, weakref.ProxyType):
+      self._parent_message_weakref = parent_message
+    else:
+      self._parent_message_weakref = weakref.proxy(parent_message)
+
+    # As an optimization, we also indicate directly on the listener whether
+    # or not the parent message is dirty.  This way we can avoid traversing
+    # up the tree in the common case.
+    self.dirty = False
+
+  def Modified(self):
+    if self.dirty:
+      return
+    try:
+      # Propagate the signal to our parents iff this is the first field set.
+      self._parent_message_weakref._Modified()
+    except ReferenceError:
+      # We can get here if a client has kept a reference to a child object,
+      # and is now setting a field on it, but the child's parent has been
+      # garbage-collected.  This is not an error.
+      pass
+
+
+class _OneofListener(_Listener):
+  """Special listener implementation for setting composite oneof fields."""
+
+  def __init__(self, parent_message, field):
+    """Args:
+      parent_message: The message whose _Modified() method we should call when
+        we receive Modified() messages.
+      field: The descriptor of the field being set in the parent message.
+    """
+    super(_OneofListener, self).__init__(parent_message)
+    self._field = field
+
+  def Modified(self):
+    """Also updates the state of the containing oneof in the parent message."""
+    try:
+      self._parent_message_weakref._UpdateOneofState(self._field)
+      super(_OneofListener, self).Modified()
+    except ReferenceError:
+      pass
+
+
+# TODO(robinson): Move elsewhere?  This file is getting pretty ridiculous...
+# TODO(robinson): Unify error handling of "unknown extension" crap.
+# TODO(robinson): Support iteritems()-style iteration over all
+# extensions with the "has" bits turned on?
+class _ExtensionDict(object):
+
+  """Dict-like container for supporting an indexable "Extensions"
+  field on proto instances.
+
+  Note that in all cases we expect extension handles to be
+  FieldDescriptors.
+  """
+
+  def __init__(self, extended_message):
+    """extended_message: Message instance for which we are the Extensions dict.
+    """
+
+    self._extended_message = extended_message
+
+  def __getitem__(self, extension_handle):
+    """Returns the current value of the given extension handle."""
+
+    _VerifyExtensionHandle(self._extended_message, extension_handle)
+
+    result = self._extended_message._fields.get(extension_handle)
+    if result is not None:
+      return result
+
+    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+      result = extension_handle._default_constructor(self._extended_message)
+    elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      result = extension_handle.message_type._concrete_class()
+      try:
+        result._SetListener(self._extended_message._listener_for_children)
+      except ReferenceError:
+        pass
+    else:
+      # Singular scalar -- just return the default without inserting into the
+      # dict.
+      return extension_handle.default_value
+
+    # Atomically check if another thread has preempted us and, if not, swap
+    # in the new object we just created.  If someone has preempted us, we
+    # take that object and discard ours.
+    # WARNING:  We are relying on setdefault() being atomic.  This is true
+    #   in CPython but we haven't investigated others.  This warning appears
+    #   in several other locations in this file.
+    result = self._extended_message._fields.setdefault(
+        extension_handle, result)
+
+    return result
+
+  def __eq__(self, other):
+    if not isinstance(other, self.__class__):
+      return False
+
+    my_fields = self._extended_message.ListFields()
+    other_fields = other._extended_message.ListFields()
+
+    # Get rid of non-extension fields.
+    my_fields    = [ field for field in my_fields    if field.is_extension ]
+    other_fields = [ field for field in other_fields if field.is_extension ]
+
+    return my_fields == other_fields
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  # Note that this is only meaningful for non-repeated, scalar extension
+  # fields.  Note also that we may have to call _Modified() when we do
+  # successfully set a field this way, to set any necssary "has" bits in the
+  # ancestors of the extended message.
+  def __setitem__(self, extension_handle, value):
+    """If extension_handle specifies a non-repeated, scalar extension
+    field, sets the value of that field.
+    """
+
+    _VerifyExtensionHandle(self._extended_message, extension_handle)
+
+    if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or
+        extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
+      raise TypeError(
+          'Cannot assign to extension "%s" because it is a repeated or '
+          'composite type.' % extension_handle.full_name)
+
+    # It's slightly wasteful to lookup the type checker each time,
+    # but we expect this to be a vanishingly uncommon case anyway.
+    type_checker = type_checkers.GetTypeChecker(extension_handle)
+    # pylint: disable=protected-access
+    self._extended_message._fields[extension_handle] = (
+        type_checker.CheckValue(value))
+    self._extended_message._Modified()
+
+  def _FindExtensionByName(self, name):
+    """Tries to find a known extension with the specified name.
+
+    Args:
+      name: Extension full name.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._extended_message._extensions_by_name.get(name, None)
+
+  def _FindExtensionByNumber(self, number):
+    """Tries to find a known extension with the field number.
+
+    Args:
+      number: Extension field number.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._extended_message._extensions_by_number.get(number, None)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/reflection_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/reflection_test.py
new file mode 100755
index 0000000..6dc2fff
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/reflection_test.py
@@ -0,0 +1,2983 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# 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.
+
+"""Unittest for reflection.py, which also indirectly tests the output of the
+pure-Python protocol compiler.
+"""
+
+import copy
+import gc
+import operator
+import six
+import struct
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor
+from google.protobuf import message
+from google.protobuf import reflection
+from google.protobuf import text_format
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import more_extensions_pb2
+from google.protobuf.internal import more_messages_pb2
+from google.protobuf.internal import message_set_extensions_pb2
+from google.protobuf.internal import wire_format
+from google.protobuf.internal import test_util
+from google.protobuf.internal import decoder
+
+
+class _MiniDecoder(object):
+  """Decodes a stream of values from a string.
+
+  Once upon a time we actually had a class called decoder.Decoder.  Then we
+  got rid of it during a redesign that made decoding much, much faster overall.
+  But a couple tests in this file used it to check that the serialized form of
+  a message was correct.  So, this class implements just the methods that were
+  used by said tests, so that we don't have to rewrite the tests.
+  """
+
+  def __init__(self, bytes):
+    self._bytes = bytes
+    self._pos = 0
+
+  def ReadVarint(self):
+    result, self._pos = decoder._DecodeVarint(self._bytes, self._pos)
+    return result
+
+  ReadInt32 = ReadVarint
+  ReadInt64 = ReadVarint
+  ReadUInt32 = ReadVarint
+  ReadUInt64 = ReadVarint
+
+  def ReadSInt64(self):
+    return wire_format.ZigZagDecode(self.ReadVarint())
+
+  ReadSInt32 = ReadSInt64
+
+  def ReadFieldNumberAndWireType(self):
+    return wire_format.UnpackTag(self.ReadVarint())
+
+  def ReadFloat(self):
+    result = struct.unpack("<f", self._bytes[self._pos:self._pos+4])[0]
+    self._pos += 4
+    return result
+
+  def ReadDouble(self):
+    result = struct.unpack("<d", self._bytes[self._pos:self._pos+8])[0]
+    self._pos += 8
+    return result
+
+  def EndOfStream(self):
+    return self._pos == len(self._bytes)
+
+
+class ReflectionTest(unittest.TestCase):
+
+  def assertListsEqual(self, values, others):
+    self.assertEqual(len(values), len(others))
+    for i in range(len(values)):
+      self.assertEqual(values[i], others[i])
+
+  def testScalarConstructor(self):
+    # Constructor with only scalar types should succeed.
+    proto = unittest_pb2.TestAllTypes(
+        optional_int32=24,
+        optional_double=54.321,
+        optional_string='optional_string',
+        optional_float=None)
+
+    self.assertEqual(24, proto.optional_int32)
+    self.assertEqual(54.321, proto.optional_double)
+    self.assertEqual('optional_string', proto.optional_string)
+    self.assertFalse(proto.HasField("optional_float"))
+
+  def testRepeatedScalarConstructor(self):
+    # Constructor with only repeated scalar types should succeed.
+    proto = unittest_pb2.TestAllTypes(
+        repeated_int32=[1, 2, 3, 4],
+        repeated_double=[1.23, 54.321],
+        repeated_bool=[True, False, False],
+        repeated_string=["optional_string"],
+        repeated_float=None)
+
+    self.assertEqual([1, 2, 3, 4], list(proto.repeated_int32))
+    self.assertEqual([1.23, 54.321], list(proto.repeated_double))
+    self.assertEqual([True, False, False], list(proto.repeated_bool))
+    self.assertEqual(["optional_string"], list(proto.repeated_string))
+    self.assertEqual([], list(proto.repeated_float))
+
+  def testRepeatedCompositeConstructor(self):
+    # Constructor with only repeated composite types should succeed.
+    proto = unittest_pb2.TestAllTypes(
+        repeated_nested_message=[
+            unittest_pb2.TestAllTypes.NestedMessage(
+                bb=unittest_pb2.TestAllTypes.FOO),
+            unittest_pb2.TestAllTypes.NestedMessage(
+                bb=unittest_pb2.TestAllTypes.BAR)],
+        repeated_foreign_message=[
+            unittest_pb2.ForeignMessage(c=-43),
+            unittest_pb2.ForeignMessage(c=45324),
+            unittest_pb2.ForeignMessage(c=12)],
+        repeatedgroup=[
+            unittest_pb2.TestAllTypes.RepeatedGroup(),
+            unittest_pb2.TestAllTypes.RepeatedGroup(a=1),
+            unittest_pb2.TestAllTypes.RepeatedGroup(a=2)])
+
+    self.assertEqual(
+        [unittest_pb2.TestAllTypes.NestedMessage(
+            bb=unittest_pb2.TestAllTypes.FOO),
+         unittest_pb2.TestAllTypes.NestedMessage(
+             bb=unittest_pb2.TestAllTypes.BAR)],
+        list(proto.repeated_nested_message))
+    self.assertEqual(
+        [unittest_pb2.ForeignMessage(c=-43),
+         unittest_pb2.ForeignMessage(c=45324),
+         unittest_pb2.ForeignMessage(c=12)],
+        list(proto.repeated_foreign_message))
+    self.assertEqual(
+        [unittest_pb2.TestAllTypes.RepeatedGroup(),
+         unittest_pb2.TestAllTypes.RepeatedGroup(a=1),
+         unittest_pb2.TestAllTypes.RepeatedGroup(a=2)],
+        list(proto.repeatedgroup))
+
+  def testMixedConstructor(self):
+    # Constructor with only mixed types should succeed.
+    proto = unittest_pb2.TestAllTypes(
+        optional_int32=24,
+        optional_string='optional_string',
+        repeated_double=[1.23, 54.321],
+        repeated_bool=[True, False, False],
+        repeated_nested_message=[
+            unittest_pb2.TestAllTypes.NestedMessage(
+                bb=unittest_pb2.TestAllTypes.FOO),
+            unittest_pb2.TestAllTypes.NestedMessage(
+                bb=unittest_pb2.TestAllTypes.BAR)],
+        repeated_foreign_message=[
+            unittest_pb2.ForeignMessage(c=-43),
+            unittest_pb2.ForeignMessage(c=45324),
+            unittest_pb2.ForeignMessage(c=12)],
+        optional_nested_message=None)
+
+    self.assertEqual(24, proto.optional_int32)
+    self.assertEqual('optional_string', proto.optional_string)
+    self.assertEqual([1.23, 54.321], list(proto.repeated_double))
+    self.assertEqual([True, False, False], list(proto.repeated_bool))
+    self.assertEqual(
+        [unittest_pb2.TestAllTypes.NestedMessage(
+            bb=unittest_pb2.TestAllTypes.FOO),
+         unittest_pb2.TestAllTypes.NestedMessage(
+             bb=unittest_pb2.TestAllTypes.BAR)],
+        list(proto.repeated_nested_message))
+    self.assertEqual(
+        [unittest_pb2.ForeignMessage(c=-43),
+         unittest_pb2.ForeignMessage(c=45324),
+         unittest_pb2.ForeignMessage(c=12)],
+        list(proto.repeated_foreign_message))
+    self.assertFalse(proto.HasField("optional_nested_message"))
+
+  def testConstructorTypeError(self):
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_int32="foo")
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_string=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_nested_message=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_int32=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_int32=["foo"])
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_string=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_string=[1234])
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=[1234])
+
+  def testConstructorInvalidatesCachedByteSize(self):
+    message = unittest_pb2.TestAllTypes(optional_int32 = 12)
+    self.assertEqual(2, message.ByteSize())
+
+    message = unittest_pb2.TestAllTypes(
+        optional_nested_message = unittest_pb2.TestAllTypes.NestedMessage())
+    self.assertEqual(3, message.ByteSize())
+
+    message = unittest_pb2.TestAllTypes(repeated_int32 = [12])
+    self.assertEqual(3, message.ByteSize())
+
+    message = unittest_pb2.TestAllTypes(
+        repeated_nested_message = [unittest_pb2.TestAllTypes.NestedMessage()])
+    self.assertEqual(3, message.ByteSize())
+
+  def testSimpleHasBits(self):
+    # Test a scalar.
+    proto = unittest_pb2.TestAllTypes()
+    self.assertTrue(not proto.HasField('optional_int32'))
+    self.assertEqual(0, proto.optional_int32)
+    # HasField() shouldn't be true if all we've done is
+    # read the default value.
+    self.assertTrue(not proto.HasField('optional_int32'))
+    proto.optional_int32 = 1
+    # Setting a value however *should* set the "has" bit.
+    self.assertTrue(proto.HasField('optional_int32'))
+    proto.ClearField('optional_int32')
+    # And clearing that value should unset the "has" bit.
+    self.assertTrue(not proto.HasField('optional_int32'))
+
+  def testHasBitsWithSinglyNestedScalar(self):
+    # Helper used to test foreign messages and groups.
+    #
+    # composite_field_name should be the name of a non-repeated
+    # composite (i.e., foreign or group) field in TestAllTypes,
+    # and scalar_field_name should be the name of an integer-valued
+    # scalar field within that composite.
+    #
+    # I never thought I'd miss C++ macros and templates so much. :(
+    # This helper is semantically just:
+    #
+    #   assert proto.composite_field.scalar_field == 0
+    #   assert not proto.composite_field.HasField('scalar_field')
+    #   assert not proto.HasField('composite_field')
+    #
+    #   proto.composite_field.scalar_field = 10
+    #   old_composite_field = proto.composite_field
+    #
+    #   assert proto.composite_field.scalar_field == 10
+    #   assert proto.composite_field.HasField('scalar_field')
+    #   assert proto.HasField('composite_field')
+    #
+    #   proto.ClearField('composite_field')
+    #
+    #   assert not proto.composite_field.HasField('scalar_field')
+    #   assert not proto.HasField('composite_field')
+    #   assert proto.composite_field.scalar_field == 0
+    #
+    #   # Now ensure that ClearField('composite_field') disconnected
+    #   # the old field object from the object tree...
+    #   assert old_composite_field is not proto.composite_field
+    #   old_composite_field.scalar_field = 20
+    #   assert not proto.composite_field.HasField('scalar_field')
+    #   assert not proto.HasField('composite_field')
+    def TestCompositeHasBits(composite_field_name, scalar_field_name):
+      proto = unittest_pb2.TestAllTypes()
+      # First, check that we can get the scalar value, and see that it's the
+      # default (0), but that proto.HasField('omposite') and
+      # proto.composite.HasField('scalar') will still return False.
+      composite_field = getattr(proto, composite_field_name)
+      original_scalar_value = getattr(composite_field, scalar_field_name)
+      self.assertEqual(0, original_scalar_value)
+      # Assert that the composite object does not "have" the scalar.
+      self.assertTrue(not composite_field.HasField(scalar_field_name))
+      # Assert that proto does not "have" the composite field.
+      self.assertTrue(not proto.HasField(composite_field_name))
+
+      # Now set the scalar within the composite field.  Ensure that the setting
+      # is reflected, and that proto.HasField('composite') and
+      # proto.composite.HasField('scalar') now both return True.
+      new_val = 20
+      setattr(composite_field, scalar_field_name, new_val)
+      self.assertEqual(new_val, getattr(composite_field, scalar_field_name))
+      # Hold on to a reference to the current composite_field object.
+      old_composite_field = composite_field
+      # Assert that the has methods now return true.
+      self.assertTrue(composite_field.HasField(scalar_field_name))
+      self.assertTrue(proto.HasField(composite_field_name))
+
+      # Now call the clear method...
+      proto.ClearField(composite_field_name)
+
+      # ...and ensure that the "has" bits are all back to False...
+      composite_field = getattr(proto, composite_field_name)
+      self.assertTrue(not composite_field.HasField(scalar_field_name))
+      self.assertTrue(not proto.HasField(composite_field_name))
+      # ...and ensure that the scalar field has returned to its default.
+      self.assertEqual(0, getattr(composite_field, scalar_field_name))
+
+      self.assertTrue(old_composite_field is not composite_field)
+      setattr(old_composite_field, scalar_field_name, new_val)
+      self.assertTrue(not composite_field.HasField(scalar_field_name))
+      self.assertTrue(not proto.HasField(composite_field_name))
+      self.assertEqual(0, getattr(composite_field, scalar_field_name))
+
+    # Test simple, single-level nesting when we set a scalar.
+    TestCompositeHasBits('optionalgroup', 'a')
+    TestCompositeHasBits('optional_nested_message', 'bb')
+    TestCompositeHasBits('optional_foreign_message', 'c')
+    TestCompositeHasBits('optional_import_message', 'd')
+
+  def testReferencesToNestedMessage(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    del proto
+    # A previous version had a bug where this would raise an exception when
+    # hitting a now-dead weak reference.
+    nested.bb = 23
+
+  def testDisconnectingNestedMessageBeforeSettingField(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    proto.ClearField('optional_nested_message')  # Should disconnect from parent
+    self.assertTrue(nested is not proto.optional_nested_message)
+    nested.bb = 23
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+
+  def testGetDefaultMessageAfterDisconnectingDefaultMessage(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    proto.ClearField('optional_nested_message')
+    del proto
+    del nested
+    # Force a garbage collect so that the underlying CMessages are freed along
+    # with the Messages they point to. This is to make sure we're not deleting
+    # default message instances.
+    gc.collect()
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+
+  def testDisconnectingNestedMessageAfterSettingField(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    nested.bb = 5
+    self.assertTrue(proto.HasField('optional_nested_message'))
+    proto.ClearField('optional_nested_message')  # Should disconnect from parent
+    self.assertEqual(5, nested.bb)
+    self.assertEqual(0, proto.optional_nested_message.bb)
+    self.assertTrue(nested is not proto.optional_nested_message)
+    nested.bb = 23
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+
+  def testDisconnectingNestedMessageBeforeGettingField(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    proto.ClearField('optional_nested_message')
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+
+  def testDisconnectingNestedMessageAfterMerge(self):
+    # This test exercises the code path that does not use ReleaseMessage().
+    # The underlying fear is that if we use ReleaseMessage() incorrectly,
+    # we will have memory leaks.  It's hard to check that that doesn't happen,
+    # but at least we can exercise that code path to make sure it works.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.optional_nested_message.bb = 5
+    proto1.MergeFrom(proto2)
+    self.assertTrue(proto1.HasField('optional_nested_message'))
+    proto1.ClearField('optional_nested_message')
+    self.assertTrue(not proto1.HasField('optional_nested_message'))
+
+  def testDisconnectingLazyNestedMessage(self):
+    # This test exercises releasing a nested message that is lazy. This test
+    # only exercises real code in the C++ implementation as Python does not
+    # support lazy parsing, but the current C++ implementation results in
+    # memory corruption and a crash.
+    if api_implementation.Type() != 'python':
+      return
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_lazy_message.bb = 5
+    proto.ClearField('optional_lazy_message')
+    del proto
+    gc.collect()
+
+  def testHasBitsWhenModifyingRepeatedFields(self):
+    # Test nesting when we add an element to a repeated field in a submessage.
+    proto = unittest_pb2.TestNestedMessageHasBits()
+    proto.optional_nested_message.nestedmessage_repeated_int32.append(5)
+    self.assertEqual(
+        [5], proto.optional_nested_message.nestedmessage_repeated_int32)
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+    # Do the same test, but with a repeated composite field within the
+    # submessage.
+    proto.ClearField('optional_nested_message')
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    proto.optional_nested_message.nestedmessage_repeated_foreignmessage.add()
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+  def testHasBitsForManyLevelsOfNesting(self):
+    # Test nesting many levels deep.
+    recursive_proto = unittest_pb2.TestMutualRecursionA()
+    self.assertTrue(not recursive_proto.HasField('bb'))
+    self.assertEqual(0, recursive_proto.bb.a.bb.a.bb.optional_int32)
+    self.assertTrue(not recursive_proto.HasField('bb'))
+    recursive_proto.bb.a.bb.a.bb.optional_int32 = 5
+    self.assertEqual(5, recursive_proto.bb.a.bb.a.bb.optional_int32)
+    self.assertTrue(recursive_proto.HasField('bb'))
+    self.assertTrue(recursive_proto.bb.HasField('a'))
+    self.assertTrue(recursive_proto.bb.a.HasField('bb'))
+    self.assertTrue(recursive_proto.bb.a.bb.HasField('a'))
+    self.assertTrue(recursive_proto.bb.a.bb.a.HasField('bb'))
+    self.assertTrue(not recursive_proto.bb.a.bb.a.bb.HasField('a'))
+    self.assertTrue(recursive_proto.bb.a.bb.a.bb.HasField('optional_int32'))
+
+  def testSingularListFields(self):
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_fixed32 = 1
+    proto.optional_int32 = 5
+    proto.optional_string = 'foo'
+    # Access sub-message but don't set it yet.
+    nested_message = proto.optional_nested_message
+    self.assertEqual(
+      [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 5),
+        (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1),
+        (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo') ],
+      proto.ListFields())
+
+    proto.optional_nested_message.bb = 123
+    self.assertEqual(
+      [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 5),
+        (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1),
+        (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo'),
+        (proto.DESCRIPTOR.fields_by_name['optional_nested_message' ],
+             nested_message) ],
+      proto.ListFields())
+
+  def testRepeatedListFields(self):
+    proto = unittest_pb2.TestAllTypes()
+    proto.repeated_fixed32.append(1)
+    proto.repeated_int32.append(5)
+    proto.repeated_int32.append(11)
+    proto.repeated_string.extend(['foo', 'bar'])
+    proto.repeated_string.extend([])
+    proto.repeated_string.append('baz')
+    proto.repeated_string.extend(str(x) for x in range(2))
+    proto.optional_int32 = 21
+    proto.repeated_bool  # Access but don't set anything; should not be listed.
+    self.assertEqual(
+      [ (proto.DESCRIPTOR.fields_by_name['optional_int32'  ], 21),
+        (proto.DESCRIPTOR.fields_by_name['repeated_int32'  ], [5, 11]),
+        (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]),
+        (proto.DESCRIPTOR.fields_by_name['repeated_string' ],
+          ['foo', 'bar', 'baz', '0', '1']) ],
+      proto.ListFields())
+
+  def testSingularListExtensions(self):
+    proto = unittest_pb2.TestAllExtensions()
+    proto.Extensions[unittest_pb2.optional_fixed32_extension] = 1
+    proto.Extensions[unittest_pb2.optional_int32_extension  ] = 5
+    proto.Extensions[unittest_pb2.optional_string_extension ] = 'foo'
+    self.assertEqual(
+      [ (unittest_pb2.optional_int32_extension  , 5),
+        (unittest_pb2.optional_fixed32_extension, 1),
+        (unittest_pb2.optional_string_extension , 'foo') ],
+      proto.ListFields())
+
+  def testRepeatedListExtensions(self):
+    proto = unittest_pb2.TestAllExtensions()
+    proto.Extensions[unittest_pb2.repeated_fixed32_extension].append(1)
+    proto.Extensions[unittest_pb2.repeated_int32_extension  ].append(5)
+    proto.Extensions[unittest_pb2.repeated_int32_extension  ].append(11)
+    proto.Extensions[unittest_pb2.repeated_string_extension ].append('foo')
+    proto.Extensions[unittest_pb2.repeated_string_extension ].append('bar')
+    proto.Extensions[unittest_pb2.repeated_string_extension ].append('baz')
+    proto.Extensions[unittest_pb2.optional_int32_extension  ] = 21
+    self.assertEqual(
+      [ (unittest_pb2.optional_int32_extension  , 21),
+        (unittest_pb2.repeated_int32_extension  , [5, 11]),
+        (unittest_pb2.repeated_fixed32_extension, [1]),
+        (unittest_pb2.repeated_string_extension , ['foo', 'bar', 'baz']) ],
+      proto.ListFields())
+
+  def testListFieldsAndExtensions(self):
+    proto = unittest_pb2.TestFieldOrderings()
+    test_util.SetAllFieldsAndExtensions(proto)
+    unittest_pb2.my_extension_int
+    self.assertEqual(
+      [ (proto.DESCRIPTOR.fields_by_name['my_int'   ], 1),
+        (unittest_pb2.my_extension_int               , 23),
+        (proto.DESCRIPTOR.fields_by_name['my_string'], 'foo'),
+        (unittest_pb2.my_extension_string            , 'bar'),
+        (proto.DESCRIPTOR.fields_by_name['my_float' ], 1.0) ],
+      proto.ListFields())
+
+  def testDefaultValues(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, proto.optional_int32)
+    self.assertEqual(0, proto.optional_int64)
+    self.assertEqual(0, proto.optional_uint32)
+    self.assertEqual(0, proto.optional_uint64)
+    self.assertEqual(0, proto.optional_sint32)
+    self.assertEqual(0, proto.optional_sint64)
+    self.assertEqual(0, proto.optional_fixed32)
+    self.assertEqual(0, proto.optional_fixed64)
+    self.assertEqual(0, proto.optional_sfixed32)
+    self.assertEqual(0, proto.optional_sfixed64)
+    self.assertEqual(0.0, proto.optional_float)
+    self.assertEqual(0.0, proto.optional_double)
+    self.assertEqual(False, proto.optional_bool)
+    self.assertEqual('', proto.optional_string)
+    self.assertEqual(b'', proto.optional_bytes)
+
+    self.assertEqual(41, proto.default_int32)
+    self.assertEqual(42, proto.default_int64)
+    self.assertEqual(43, proto.default_uint32)
+    self.assertEqual(44, proto.default_uint64)
+    self.assertEqual(-45, proto.default_sint32)
+    self.assertEqual(46, proto.default_sint64)
+    self.assertEqual(47, proto.default_fixed32)
+    self.assertEqual(48, proto.default_fixed64)
+    self.assertEqual(49, proto.default_sfixed32)
+    self.assertEqual(-50, proto.default_sfixed64)
+    self.assertEqual(51.5, proto.default_float)
+    self.assertEqual(52e3, proto.default_double)
+    self.assertEqual(True, proto.default_bool)
+    self.assertEqual('hello', proto.default_string)
+    self.assertEqual(b'world', proto.default_bytes)
+    self.assertEqual(unittest_pb2.TestAllTypes.BAR, proto.default_nested_enum)
+    self.assertEqual(unittest_pb2.FOREIGN_BAR, proto.default_foreign_enum)
+    self.assertEqual(unittest_import_pb2.IMPORT_BAR,
+                     proto.default_import_enum)
+
+    proto = unittest_pb2.TestExtremeDefaultValues()
+    self.assertEqual(u'\u1234', proto.utf8_string)
+
+  def testHasFieldWithUnknownFieldName(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertRaises(ValueError, proto.HasField, 'nonexistent_field')
+
+  def testClearFieldWithUnknownFieldName(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertRaises(ValueError, proto.ClearField, 'nonexistent_field')
+
+  def testClearRemovesChildren(self):
+    # Make sure there aren't any implementation bugs that are only partially
+    # clearing the message (which can happen in the more complex C++
+    # implementation which has parallel message lists).
+    proto = unittest_pb2.TestRequiredForeign()
+    for i in range(10):
+      proto.repeated_message.add()
+    proto2 = unittest_pb2.TestRequiredForeign()
+    proto.CopyFrom(proto2)
+    self.assertRaises(IndexError, lambda: proto.repeated_message[5])
+
+  def testDisallowedAssignments(self):
+    # It's illegal to assign values directly to repeated fields
+    # or to nonrepeated composite fields.  Ensure that this fails.
+    proto = unittest_pb2.TestAllTypes()
+    # Repeated fields.
+    self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', 10)
+    # Lists shouldn't work, either.
+    self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', [10])
+    # Composite fields.
+    self.assertRaises(AttributeError, setattr, proto,
+                      'optional_nested_message', 23)
+    # Assignment to a repeated nested message field without specifying
+    # the index in the array of nested messages.
+    self.assertRaises(AttributeError, setattr, proto.repeated_nested_message,
+                      'bb', 34)
+    # Assignment to an attribute of a repeated field.
+    self.assertRaises(AttributeError, setattr, proto.repeated_float,
+                      'some_attribute', 34)
+    # proto.nonexistent_field = 23 should fail as well.
+    self.assertRaises(AttributeError, setattr, proto, 'nonexistent_field', 23)
+
+  def testSingleScalarTypeSafety(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertRaises(TypeError, setattr, proto, 'optional_int32', 1.1)
+    self.assertRaises(TypeError, setattr, proto, 'optional_int32', 'foo')
+    self.assertRaises(TypeError, setattr, proto, 'optional_string', 10)
+    self.assertRaises(TypeError, setattr, proto, 'optional_bytes', 10)
+
+  def testIntegerTypes(self):
+    def TestGetAndDeserialize(field_name, value, expected_type):
+      proto = unittest_pb2.TestAllTypes()
+      setattr(proto, field_name, value)
+      self.assertIsInstance(getattr(proto, field_name), expected_type)
+      proto2 = unittest_pb2.TestAllTypes()
+      proto2.ParseFromString(proto.SerializeToString())
+      self.assertIsInstance(getattr(proto2, field_name), expected_type)
+
+    TestGetAndDeserialize('optional_int32', 1, int)
+    TestGetAndDeserialize('optional_int32', 1 << 30, int)
+    TestGetAndDeserialize('optional_uint32', 1 << 30, int)
+    try:
+      integer_64 = long
+    except NameError: # Python3
+      integer_64 = int
+    if struct.calcsize('L') == 4:
+      # Python only has signed ints, so 32-bit python can't fit an uint32
+      # in an int.
+      TestGetAndDeserialize('optional_uint32', 1 << 31, long)
+    else:
+      # 64-bit python can fit uint32 inside an int
+      TestGetAndDeserialize('optional_uint32', 1 << 31, int)
+    TestGetAndDeserialize('optional_int64', 1 << 30, integer_64)
+    TestGetAndDeserialize('optional_int64', 1 << 60, integer_64)
+    TestGetAndDeserialize('optional_uint64', 1 << 30, integer_64)
+    TestGetAndDeserialize('optional_uint64', 1 << 60, integer_64)
+
+  def testSingleScalarBoundsChecking(self):
+    def TestMinAndMaxIntegers(field_name, expected_min, expected_max):
+      pb = unittest_pb2.TestAllTypes()
+      setattr(pb, field_name, expected_min)
+      self.assertEqual(expected_min, getattr(pb, field_name))
+      setattr(pb, field_name, expected_max)
+      self.assertEqual(expected_max, getattr(pb, field_name))
+      self.assertRaises(ValueError, setattr, pb, field_name, expected_min - 1)
+      self.assertRaises(ValueError, setattr, pb, field_name, expected_max + 1)
+
+    TestMinAndMaxIntegers('optional_int32', -(1 << 31), (1 << 31) - 1)
+    TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff)
+    TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1)
+    TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff)
+
+    pb = unittest_pb2.TestAllTypes()
+    pb.optional_nested_enum = 1
+    self.assertEqual(1, pb.optional_nested_enum)
+
+  def testRepeatedScalarTypeSafety(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertRaises(TypeError, proto.repeated_int32.append, 1.1)
+    self.assertRaises(TypeError, proto.repeated_int32.append, 'foo')
+    self.assertRaises(TypeError, proto.repeated_string, 10)
+    self.assertRaises(TypeError, proto.repeated_bytes, 10)
+
+    proto.repeated_int32.append(10)
+    proto.repeated_int32[0] = 23
+    self.assertRaises(IndexError, proto.repeated_int32.__setitem__, 500, 23)
+    self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, 'abc')
+
+    # Repeated enums tests.
+    #proto.repeated_nested_enum.append(0)
+
+  def testSingleScalarGettersAndSetters(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, proto.optional_int32)
+    proto.optional_int32 = 1
+    self.assertEqual(1, proto.optional_int32)
+
+    proto.optional_uint64 = 0xffffffffffff
+    self.assertEqual(0xffffffffffff, proto.optional_uint64)
+    proto.optional_uint64 = 0xffffffffffffffff
+    self.assertEqual(0xffffffffffffffff, proto.optional_uint64)
+    # TODO(robinson): Test all other scalar field types.
+
+  def testSingleScalarClearField(self):
+    proto = unittest_pb2.TestAllTypes()
+    # Should be allowed to clear something that's not there (a no-op).
+    proto.ClearField('optional_int32')
+    proto.optional_int32 = 1
+    self.assertTrue(proto.HasField('optional_int32'))
+    proto.ClearField('optional_int32')
+    self.assertEqual(0, proto.optional_int32)
+    self.assertTrue(not proto.HasField('optional_int32'))
+    # TODO(robinson): Test all other scalar field types.
+
+  def testEnums(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(1, proto.FOO)
+    self.assertEqual(1, unittest_pb2.TestAllTypes.FOO)
+    self.assertEqual(2, proto.BAR)
+    self.assertEqual(2, unittest_pb2.TestAllTypes.BAR)
+    self.assertEqual(3, proto.BAZ)
+    self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
+
+  def testEnum_Name(self):
+    self.assertEqual('FOREIGN_FOO',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO))
+    self.assertEqual('FOREIGN_BAR',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR))
+    self.assertEqual('FOREIGN_BAZ',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ))
+    self.assertRaises(ValueError,
+                      unittest_pb2.ForeignEnum.Name, 11312)
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual('FOO',
+                     proto.NestedEnum.Name(proto.FOO))
+    self.assertEqual('FOO',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO))
+    self.assertEqual('BAR',
+                     proto.NestedEnum.Name(proto.BAR))
+    self.assertEqual('BAR',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR))
+    self.assertEqual('BAZ',
+                     proto.NestedEnum.Name(proto.BAZ))
+    self.assertEqual('BAZ',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ))
+    self.assertRaises(ValueError,
+                      proto.NestedEnum.Name, 11312)
+    self.assertRaises(ValueError,
+                      unittest_pb2.TestAllTypes.NestedEnum.Name, 11312)
+
+  def testEnum_Value(self):
+    self.assertEqual(unittest_pb2.FOREIGN_FOO,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_FOO'))
+    self.assertEqual(unittest_pb2.FOREIGN_BAR,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_BAR'))
+    self.assertEqual(unittest_pb2.FOREIGN_BAZ,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ'))
+    self.assertRaises(ValueError,
+                      unittest_pb2.ForeignEnum.Value, 'FO')
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(proto.FOO,
+                     proto.NestedEnum.Value('FOO'))
+    self.assertEqual(proto.FOO,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('FOO'))
+    self.assertEqual(proto.BAR,
+                     proto.NestedEnum.Value('BAR'))
+    self.assertEqual(proto.BAR,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('BAR'))
+    self.assertEqual(proto.BAZ,
+                     proto.NestedEnum.Value('BAZ'))
+    self.assertEqual(proto.BAZ,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ'))
+    self.assertRaises(ValueError,
+                      proto.NestedEnum.Value, 'Foo')
+    self.assertRaises(ValueError,
+                      unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo')
+
+  def testEnum_KeysAndValues(self):
+    self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'],
+                     list(unittest_pb2.ForeignEnum.keys()))
+    self.assertEqual([4, 5, 6],
+                     list(unittest_pb2.ForeignEnum.values()))
+    self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5),
+                      ('FOREIGN_BAZ', 6)],
+                     list(unittest_pb2.ForeignEnum.items()))
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(['FOO', 'BAR', 'BAZ', 'NEG'], list(proto.NestedEnum.keys()))
+    self.assertEqual([1, 2, 3, -1], list(proto.NestedEnum.values()))
+    self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3), ('NEG', -1)],
+                     list(proto.NestedEnum.items()))
+
+  def testRepeatedScalars(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertTrue(not proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+    proto.repeated_int32.append(5)
+    proto.repeated_int32.append(10)
+    proto.repeated_int32.append(15)
+    self.assertTrue(proto.repeated_int32)
+    self.assertEqual(3, len(proto.repeated_int32))
+
+    self.assertEqual([5, 10, 15], proto.repeated_int32)
+
+    # Test single retrieval.
+    self.assertEqual(5, proto.repeated_int32[0])
+    self.assertEqual(15, proto.repeated_int32[-1])
+    # Test out-of-bounds indices.
+    self.assertRaises(IndexError, proto.repeated_int32.__getitem__, 1234)
+    self.assertRaises(IndexError, proto.repeated_int32.__getitem__, -1234)
+    # Test incorrect types passed to __getitem__.
+    self.assertRaises(TypeError, proto.repeated_int32.__getitem__, 'foo')
+    self.assertRaises(TypeError, proto.repeated_int32.__getitem__, None)
+
+    # Test single assignment.
+    proto.repeated_int32[1] = 20
+    self.assertEqual([5, 20, 15], proto.repeated_int32)
+
+    # Test insertion.
+    proto.repeated_int32.insert(1, 25)
+    self.assertEqual([5, 25, 20, 15], proto.repeated_int32)
+
+    # Test slice retrieval.
+    proto.repeated_int32.append(30)
+    self.assertEqual([25, 20, 15], proto.repeated_int32[1:4])
+    self.assertEqual([5, 25, 20, 15, 30], proto.repeated_int32[:])
+
+    # Test slice assignment with an iterator
+    proto.repeated_int32[1:4] = (i for i in range(3))
+    self.assertEqual([5, 0, 1, 2, 30], proto.repeated_int32)
+
+    # Test slice assignment.
+    proto.repeated_int32[1:4] = [35, 40, 45]
+    self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32)
+
+    # Test that we can use the field as an iterator.
+    result = []
+    for i in proto.repeated_int32:
+      result.append(i)
+    self.assertEqual([5, 35, 40, 45, 30], result)
+
+    # Test single deletion.
+    del proto.repeated_int32[2]
+    self.assertEqual([5, 35, 45, 30], proto.repeated_int32)
+
+    # Test slice deletion.
+    del proto.repeated_int32[2:]
+    self.assertEqual([5, 35], proto.repeated_int32)
+
+    # Test extending.
+    proto.repeated_int32.extend([3, 13])
+    self.assertEqual([5, 35, 3, 13], proto.repeated_int32)
+
+    # Test clearing.
+    proto.ClearField('repeated_int32')
+    self.assertTrue(not proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+
+    proto.repeated_int32.append(1)
+    self.assertEqual(1, proto.repeated_int32[-1])
+    # Test assignment to a negative index.
+    proto.repeated_int32[-1] = 2
+    self.assertEqual(2, proto.repeated_int32[-1])
+
+    # Test deletion at negative indices.
+    proto.repeated_int32[:] = [0, 1, 2, 3]
+    del proto.repeated_int32[-1]
+    self.assertEqual([0, 1, 2], proto.repeated_int32)
+
+    del proto.repeated_int32[-2]
+    self.assertEqual([0, 2], proto.repeated_int32)
+
+    self.assertRaises(IndexError, proto.repeated_int32.__delitem__, -3)
+    self.assertRaises(IndexError, proto.repeated_int32.__delitem__, 300)
+
+    del proto.repeated_int32[-2:-1]
+    self.assertEqual([2], proto.repeated_int32)
+
+    del proto.repeated_int32[100:10000]
+    self.assertEqual([2], proto.repeated_int32)
+
+  def testRepeatedScalarsRemove(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertTrue(not proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+    proto.repeated_int32.append(5)
+    proto.repeated_int32.append(10)
+    proto.repeated_int32.append(5)
+    proto.repeated_int32.append(5)
+
+    self.assertEqual(4, len(proto.repeated_int32))
+    proto.repeated_int32.remove(5)
+    self.assertEqual(3, len(proto.repeated_int32))
+    self.assertEqual(10, proto.repeated_int32[0])
+    self.assertEqual(5, proto.repeated_int32[1])
+    self.assertEqual(5, proto.repeated_int32[2])
+
+    proto.repeated_int32.remove(5)
+    self.assertEqual(2, len(proto.repeated_int32))
+    self.assertEqual(10, proto.repeated_int32[0])
+    self.assertEqual(5, proto.repeated_int32[1])
+
+    proto.repeated_int32.remove(10)
+    self.assertEqual(1, len(proto.repeated_int32))
+    self.assertEqual(5, proto.repeated_int32[0])
+
+    # Remove a non-existent element.
+    self.assertRaises(ValueError, proto.repeated_int32.remove, 123)
+
+  def testRepeatedComposites(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertTrue(not proto.repeated_nested_message)
+    self.assertEqual(0, len(proto.repeated_nested_message))
+    m0 = proto.repeated_nested_message.add()
+    m1 = proto.repeated_nested_message.add()
+    self.assertTrue(proto.repeated_nested_message)
+    self.assertEqual(2, len(proto.repeated_nested_message))
+    self.assertListsEqual([m0, m1], proto.repeated_nested_message)
+    self.assertIsInstance(m0, unittest_pb2.TestAllTypes.NestedMessage)
+
+    # Test out-of-bounds indices.
+    self.assertRaises(IndexError, proto.repeated_nested_message.__getitem__,
+                      1234)
+    self.assertRaises(IndexError, proto.repeated_nested_message.__getitem__,
+                      -1234)
+
+    # Test incorrect types passed to __getitem__.
+    self.assertRaises(TypeError, proto.repeated_nested_message.__getitem__,
+                      'foo')
+    self.assertRaises(TypeError, proto.repeated_nested_message.__getitem__,
+                      None)
+
+    # Test slice retrieval.
+    m2 = proto.repeated_nested_message.add()
+    m3 = proto.repeated_nested_message.add()
+    m4 = proto.repeated_nested_message.add()
+    self.assertListsEqual(
+        [m1, m2, m3], proto.repeated_nested_message[1:4])
+    self.assertListsEqual(
+        [m0, m1, m2, m3, m4], proto.repeated_nested_message[:])
+    self.assertListsEqual(
+        [m0, m1], proto.repeated_nested_message[:2])
+    self.assertListsEqual(
+        [m2, m3, m4], proto.repeated_nested_message[2:])
+    self.assertEqual(
+        m0, proto.repeated_nested_message[0])
+    self.assertListsEqual(
+        [m0], proto.repeated_nested_message[:1])
+
+    # Test that we can use the field as an iterator.
+    result = []
+    for i in proto.repeated_nested_message:
+      result.append(i)
+    self.assertListsEqual([m0, m1, m2, m3, m4], result)
+
+    # Test single deletion.
+    del proto.repeated_nested_message[2]
+    self.assertListsEqual([m0, m1, m3, m4], proto.repeated_nested_message)
+
+    # Test slice deletion.
+    del proto.repeated_nested_message[2:]
+    self.assertListsEqual([m0, m1], proto.repeated_nested_message)
+
+    # Test extending.
+    n1 = unittest_pb2.TestAllTypes.NestedMessage(bb=1)
+    n2 = unittest_pb2.TestAllTypes.NestedMessage(bb=2)
+    proto.repeated_nested_message.extend([n1,n2])
+    self.assertEqual(4, len(proto.repeated_nested_message))
+    self.assertEqual(n1, proto.repeated_nested_message[2])
+    self.assertEqual(n2, proto.repeated_nested_message[3])
+
+    # Test clearing.
+    proto.ClearField('repeated_nested_message')
+    self.assertTrue(not proto.repeated_nested_message)
+    self.assertEqual(0, len(proto.repeated_nested_message))
+
+    # Test constructing an element while adding it.
+    proto.repeated_nested_message.add(bb=23)
+    self.assertEqual(1, len(proto.repeated_nested_message))
+    self.assertEqual(23, proto.repeated_nested_message[0].bb)
+
+  def testRepeatedCompositeRemove(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertEqual(0, len(proto.repeated_nested_message))
+    m0 = proto.repeated_nested_message.add()
+    # Need to set some differentiating variable so m0 != m1 != m2:
+    m0.bb = len(proto.repeated_nested_message)
+    m1 = proto.repeated_nested_message.add()
+    m1.bb = len(proto.repeated_nested_message)
+    self.assertTrue(m0 != m1)
+    m2 = proto.repeated_nested_message.add()
+    m2.bb = len(proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message)
+
+    self.assertEqual(3, len(proto.repeated_nested_message))
+    proto.repeated_nested_message.remove(m0)
+    self.assertEqual(2, len(proto.repeated_nested_message))
+    self.assertEqual(m1, proto.repeated_nested_message[0])
+    self.assertEqual(m2, proto.repeated_nested_message[1])
+
+    # Removing m0 again or removing None should raise error
+    self.assertRaises(ValueError, proto.repeated_nested_message.remove, m0)
+    self.assertRaises(ValueError, proto.repeated_nested_message.remove, None)
+    self.assertEqual(2, len(proto.repeated_nested_message))
+
+    proto.repeated_nested_message.remove(m2)
+    self.assertEqual(1, len(proto.repeated_nested_message))
+    self.assertEqual(m1, proto.repeated_nested_message[0])
+
+  def testHandWrittenReflection(self):
+    # Hand written extensions are only supported by the pure-Python
+    # implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
+    FieldDescriptor = descriptor.FieldDescriptor
+    foo_field_descriptor = FieldDescriptor(
+        name='foo_field', full_name='MyProto.foo_field',
+        index=0, number=1, type=FieldDescriptor.TYPE_INT64,
+        cpp_type=FieldDescriptor.CPPTYPE_INT64,
+        label=FieldDescriptor.LABEL_OPTIONAL, default_value=0,
+        containing_type=None, message_type=None, enum_type=None,
+        is_extension=False, extension_scope=None,
+        options=descriptor_pb2.FieldOptions())
+    mydescriptor = descriptor.Descriptor(
+        name='MyProto', full_name='MyProto', filename='ignored',
+        containing_type=None, nested_types=[], enum_types=[],
+        fields=[foo_field_descriptor], extensions=[],
+        options=descriptor_pb2.MessageOptions())
+    class MyProtoClass(six.with_metaclass(reflection.GeneratedProtocolMessageType, message.Message)):
+      DESCRIPTOR = mydescriptor
+    myproto_instance = MyProtoClass()
+    self.assertEqual(0, myproto_instance.foo_field)
+    self.assertTrue(not myproto_instance.HasField('foo_field'))
+    myproto_instance.foo_field = 23
+    self.assertEqual(23, myproto_instance.foo_field)
+    self.assertTrue(myproto_instance.HasField('foo_field'))
+
+  def testDescriptorProtoSupport(self):
+    # Hand written descriptors/reflection are only supported by the pure-Python
+    # implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
+    def AddDescriptorField(proto, field_name, field_type):
+      AddDescriptorField.field_index += 1
+      new_field = proto.field.add()
+      new_field.name = field_name
+      new_field.type = field_type
+      new_field.number = AddDescriptorField.field_index
+      new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+
+    AddDescriptorField.field_index = 0
+
+    desc_proto = descriptor_pb2.DescriptorProto()
+    desc_proto.name = 'Car'
+    fdp = descriptor_pb2.FieldDescriptorProto
+    AddDescriptorField(desc_proto, 'name', fdp.TYPE_STRING)
+    AddDescriptorField(desc_proto, 'year', fdp.TYPE_INT64)
+    AddDescriptorField(desc_proto, 'automatic', fdp.TYPE_BOOL)
+    AddDescriptorField(desc_proto, 'price', fdp.TYPE_DOUBLE)
+    # Add a repeated field
+    AddDescriptorField.field_index += 1
+    new_field = desc_proto.field.add()
+    new_field.name = 'owners'
+    new_field.type = fdp.TYPE_STRING
+    new_field.number = AddDescriptorField.field_index
+    new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED
+
+    desc = descriptor.MakeDescriptor(desc_proto)
+    self.assertTrue('name' in desc.fields_by_name)
+    self.assertTrue('year' in desc.fields_by_name)
+    self.assertTrue('automatic' in desc.fields_by_name)
+    self.assertTrue('price' in desc.fields_by_name)
+    self.assertTrue('owners' in desc.fields_by_name)
+
+    class CarMessage(six.with_metaclass(reflection.GeneratedProtocolMessageType, message.Message)):
+      DESCRIPTOR = desc
+
+    prius = CarMessage()
+    prius.name = 'prius'
+    prius.year = 2010
+    prius.automatic = True
+    prius.price = 25134.75
+    prius.owners.extend(['bob', 'susan'])
+
+    serialized_prius = prius.SerializeToString()
+    new_prius = reflection.ParseMessage(desc, serialized_prius)
+    self.assertTrue(new_prius is not prius)
+    self.assertEqual(prius, new_prius)
+
+    # these are unnecessary assuming message equality works as advertised but
+    # explicitly check to be safe since we're mucking about in metaclass foo
+    self.assertEqual(prius.name, new_prius.name)
+    self.assertEqual(prius.year, new_prius.year)
+    self.assertEqual(prius.automatic, new_prius.automatic)
+    self.assertEqual(prius.price, new_prius.price)
+    self.assertEqual(prius.owners, new_prius.owners)
+
+  def testTopLevelExtensionsForOptionalScalar(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.optional_int32_extension
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    self.assertEqual(0, extendee_proto.Extensions[extension])
+    # As with normal scalar fields, just doing a read doesn't actually set the
+    # "has" bit.
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    # Actually set the thing.
+    extendee_proto.Extensions[extension] = 23
+    self.assertEqual(23, extendee_proto.Extensions[extension])
+    self.assertTrue(extendee_proto.HasExtension(extension))
+    # Ensure that clearing works as well.
+    extendee_proto.ClearExtension(extension)
+    self.assertEqual(0, extendee_proto.Extensions[extension])
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+
+  def testTopLevelExtensionsForRepeatedScalar(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.repeated_string_extension
+    self.assertEqual(0, len(extendee_proto.Extensions[extension]))
+    extendee_proto.Extensions[extension].append('foo')
+    self.assertEqual(['foo'], extendee_proto.Extensions[extension])
+    string_list = extendee_proto.Extensions[extension]
+    extendee_proto.ClearExtension(extension)
+    self.assertEqual(0, len(extendee_proto.Extensions[extension]))
+    self.assertTrue(string_list is not extendee_proto.Extensions[extension])
+    # Shouldn't be allowed to do Extensions[extension] = 'a'
+    self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions,
+                      extension, 'a')
+
+  def testTopLevelExtensionsForOptionalMessage(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.optional_foreign_message_extension
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    self.assertEqual(0, extendee_proto.Extensions[extension].c)
+    # As with normal (non-extension) fields, merely reading from the
+    # thing shouldn't set the "has" bit.
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    extendee_proto.Extensions[extension].c = 23
+    self.assertEqual(23, extendee_proto.Extensions[extension].c)
+    self.assertTrue(extendee_proto.HasExtension(extension))
+    # Save a reference here.
+    foreign_message = extendee_proto.Extensions[extension]
+    extendee_proto.ClearExtension(extension)
+    self.assertTrue(foreign_message is not extendee_proto.Extensions[extension])
+    # Setting a field on foreign_message now shouldn't set
+    # any "has" bits on extendee_proto.
+    foreign_message.c = 42
+    self.assertEqual(42, foreign_message.c)
+    self.assertTrue(foreign_message.HasField('c'))
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    # Shouldn't be allowed to do Extensions[extension] = 'a'
+    self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions,
+                      extension, 'a')
+
+  def testTopLevelExtensionsForRepeatedMessage(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.repeatedgroup_extension
+    self.assertEqual(0, len(extendee_proto.Extensions[extension]))
+    group = extendee_proto.Extensions[extension].add()
+    group.a = 23
+    self.assertEqual(23, extendee_proto.Extensions[extension][0].a)
+    group.a = 42
+    self.assertEqual(42, extendee_proto.Extensions[extension][0].a)
+    group_list = extendee_proto.Extensions[extension]
+    extendee_proto.ClearExtension(extension)
+    self.assertEqual(0, len(extendee_proto.Extensions[extension]))
+    self.assertTrue(group_list is not extendee_proto.Extensions[extension])
+    # Shouldn't be allowed to do Extensions[extension] = 'a'
+    self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions,
+                      extension, 'a')
+
+  def testNestedExtensions(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.TestRequired.single
+
+    # We just test the non-repeated case.
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    required = extendee_proto.Extensions[extension]
+    self.assertEqual(0, required.a)
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+    required.a = 23
+    self.assertEqual(23, extendee_proto.Extensions[extension].a)
+    self.assertTrue(extendee_proto.HasExtension(extension))
+    extendee_proto.ClearExtension(extension)
+    self.assertTrue(required is not extendee_proto.Extensions[extension])
+    self.assertTrue(not extendee_proto.HasExtension(extension))
+
+  def testRegisteredExtensions(self):
+    self.assertTrue('protobuf_unittest.optional_int32_extension' in
+                    unittest_pb2.TestAllExtensions._extensions_by_name)
+    self.assertTrue(1 in unittest_pb2.TestAllExtensions._extensions_by_number)
+    # Make sure extensions haven't been registered into types that shouldn't
+    # have any.
+    self.assertEqual(0, len(unittest_pb2.TestAllTypes._extensions_by_name))
+
+  # If message A directly contains message B, and
+  # a.HasField('b') is currently False, then mutating any
+  # extension in B should change a.HasField('b') to True
+  # (and so on up the object tree).
+  def testHasBitsForAncestorsOfExtendedMessage(self):
+    # Optional scalar extension.
+    toplevel = more_extensions_pb2.TopLevelMessage()
+    self.assertTrue(not toplevel.HasField('submessage'))
+    self.assertEqual(0, toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_int_extension])
+    self.assertTrue(not toplevel.HasField('submessage'))
+    toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_int_extension] = 23
+    self.assertEqual(23, toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_int_extension])
+    self.assertTrue(toplevel.HasField('submessage'))
+
+    # Repeated scalar extension.
+    toplevel = more_extensions_pb2.TopLevelMessage()
+    self.assertTrue(not toplevel.HasField('submessage'))
+    self.assertEqual([], toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_int_extension])
+    self.assertTrue(not toplevel.HasField('submessage'))
+    toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_int_extension].append(23)
+    self.assertEqual([23], toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_int_extension])
+    self.assertTrue(toplevel.HasField('submessage'))
+
+    # Optional message extension.
+    toplevel = more_extensions_pb2.TopLevelMessage()
+    self.assertTrue(not toplevel.HasField('submessage'))
+    self.assertEqual(0, toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_message_extension].foreign_message_int)
+    self.assertTrue(not toplevel.HasField('submessage'))
+    toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_message_extension].foreign_message_int = 23
+    self.assertEqual(23, toplevel.submessage.Extensions[
+        more_extensions_pb2.optional_message_extension].foreign_message_int)
+    self.assertTrue(toplevel.HasField('submessage'))
+
+    # Repeated message extension.
+    toplevel = more_extensions_pb2.TopLevelMessage()
+    self.assertTrue(not toplevel.HasField('submessage'))
+    self.assertEqual(0, len(toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_message_extension]))
+    self.assertTrue(not toplevel.HasField('submessage'))
+    foreign = toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_message_extension].add()
+    self.assertEqual(foreign, toplevel.submessage.Extensions[
+        more_extensions_pb2.repeated_message_extension][0])
+    self.assertTrue(toplevel.HasField('submessage'))
+
+  def testDisconnectionAfterClearingEmptyMessage(self):
+    toplevel = more_extensions_pb2.TopLevelMessage()
+    extendee_proto = toplevel.submessage
+    extension = more_extensions_pb2.optional_message_extension
+    extension_proto = extendee_proto.Extensions[extension]
+    extendee_proto.ClearExtension(extension)
+    extension_proto.foreign_message_int = 23
+
+    self.assertTrue(extension_proto is not extendee_proto.Extensions[extension])
+
+  def testExtensionFailureModes(self):
+    extendee_proto = unittest_pb2.TestAllExtensions()
+
+    # Try non-extension-handle arguments to HasExtension,
+    # ClearExtension(), and Extensions[]...
+    self.assertRaises(KeyError, extendee_proto.HasExtension, 1234)
+    self.assertRaises(KeyError, extendee_proto.ClearExtension, 1234)
+    self.assertRaises(KeyError, extendee_proto.Extensions.__getitem__, 1234)
+    self.assertRaises(KeyError, extendee_proto.Extensions.__setitem__, 1234, 5)
+
+    # Try something that *is* an extension handle, just not for
+    # this message...
+    for unknown_handle in (more_extensions_pb2.optional_int_extension,
+                           more_extensions_pb2.optional_message_extension,
+                           more_extensions_pb2.repeated_int_extension,
+                           more_extensions_pb2.repeated_message_extension):
+      self.assertRaises(KeyError, extendee_proto.HasExtension,
+                        unknown_handle)
+      self.assertRaises(KeyError, extendee_proto.ClearExtension,
+                        unknown_handle)
+      self.assertRaises(KeyError, extendee_proto.Extensions.__getitem__,
+                        unknown_handle)
+      self.assertRaises(KeyError, extendee_proto.Extensions.__setitem__,
+                        unknown_handle, 5)
+
+    # Try call HasExtension() with a valid handle, but for a
+    # *repeated* field.  (Just as with non-extension repeated
+    # fields, Has*() isn't supported for extension repeated fields).
+    self.assertRaises(KeyError, extendee_proto.HasExtension,
+                      unittest_pb2.repeated_string_extension)
+
+  def testStaticParseFrom(self):
+    proto1 = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(proto1)
+
+    string1 = proto1.SerializeToString()
+    proto2 = unittest_pb2.TestAllTypes.FromString(string1)
+
+    # Messages should be equal.
+    self.assertEqual(proto2, proto1)
+
+  def testMergeFromSingularField(self):
+    # Test merge with just a singular field.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.optional_int32 = 1
+
+    proto2 = unittest_pb2.TestAllTypes()
+    # This shouldn't get overwritten.
+    proto2.optional_string = 'value'
+
+    proto2.MergeFrom(proto1)
+    self.assertEqual(1, proto2.optional_int32)
+    self.assertEqual('value', proto2.optional_string)
+
+  def testMergeFromRepeatedField(self):
+    # Test merge with just a repeated field.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.repeated_int32.append(1)
+    proto1.repeated_int32.append(2)
+
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.repeated_int32.append(0)
+    proto2.MergeFrom(proto1)
+
+    self.assertEqual(0, proto2.repeated_int32[0])
+    self.assertEqual(1, proto2.repeated_int32[1])
+    self.assertEqual(2, proto2.repeated_int32[2])
+
+  def testMergeFromOptionalGroup(self):
+    # Test merge with an optional group.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.optionalgroup.a = 12
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.MergeFrom(proto1)
+    self.assertEqual(12, proto2.optionalgroup.a)
+
+  def testMergeFromRepeatedNestedMessage(self):
+    # Test merge with a repeated nested message.
+    proto1 = unittest_pb2.TestAllTypes()
+    m = proto1.repeated_nested_message.add()
+    m.bb = 123
+    m = proto1.repeated_nested_message.add()
+    m.bb = 321
+
+    proto2 = unittest_pb2.TestAllTypes()
+    m = proto2.repeated_nested_message.add()
+    m.bb = 999
+    proto2.MergeFrom(proto1)
+    self.assertEqual(999, proto2.repeated_nested_message[0].bb)
+    self.assertEqual(123, proto2.repeated_nested_message[1].bb)
+    self.assertEqual(321, proto2.repeated_nested_message[2].bb)
+
+    proto3 = unittest_pb2.TestAllTypes()
+    proto3.repeated_nested_message.MergeFrom(proto2.repeated_nested_message)
+    self.assertEqual(999, proto3.repeated_nested_message[0].bb)
+    self.assertEqual(123, proto3.repeated_nested_message[1].bb)
+    self.assertEqual(321, proto3.repeated_nested_message[2].bb)
+
+  def testMergeFromAllFields(self):
+    # With all fields set.
+    proto1 = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(proto1)
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.MergeFrom(proto1)
+
+    # Messages should be equal.
+    self.assertEqual(proto2, proto1)
+
+    # Serialized string should be equal too.
+    string1 = proto1.SerializeToString()
+    string2 = proto2.SerializeToString()
+    self.assertEqual(string1, string2)
+
+  def testMergeFromExtensionsSingular(self):
+    proto1 = unittest_pb2.TestAllExtensions()
+    proto1.Extensions[unittest_pb2.optional_int32_extension] = 1
+
+    proto2 = unittest_pb2.TestAllExtensions()
+    proto2.MergeFrom(proto1)
+    self.assertEqual(
+        1, proto2.Extensions[unittest_pb2.optional_int32_extension])
+
+  def testMergeFromExtensionsRepeated(self):
+    proto1 = unittest_pb2.TestAllExtensions()
+    proto1.Extensions[unittest_pb2.repeated_int32_extension].append(1)
+    proto1.Extensions[unittest_pb2.repeated_int32_extension].append(2)
+
+    proto2 = unittest_pb2.TestAllExtensions()
+    proto2.Extensions[unittest_pb2.repeated_int32_extension].append(0)
+    proto2.MergeFrom(proto1)
+    self.assertEqual(
+        3, len(proto2.Extensions[unittest_pb2.repeated_int32_extension]))
+    self.assertEqual(
+        0, proto2.Extensions[unittest_pb2.repeated_int32_extension][0])
+    self.assertEqual(
+        1, proto2.Extensions[unittest_pb2.repeated_int32_extension][1])
+    self.assertEqual(
+        2, proto2.Extensions[unittest_pb2.repeated_int32_extension][2])
+
+  def testMergeFromExtensionsNestedMessage(self):
+    proto1 = unittest_pb2.TestAllExtensions()
+    ext1 = proto1.Extensions[
+        unittest_pb2.repeated_nested_message_extension]
+    m = ext1.add()
+    m.bb = 222
+    m = ext1.add()
+    m.bb = 333
+
+    proto2 = unittest_pb2.TestAllExtensions()
+    ext2 = proto2.Extensions[
+        unittest_pb2.repeated_nested_message_extension]
+    m = ext2.add()
+    m.bb = 111
+
+    proto2.MergeFrom(proto1)
+    ext2 = proto2.Extensions[
+        unittest_pb2.repeated_nested_message_extension]
+    self.assertEqual(3, len(ext2))
+    self.assertEqual(111, ext2[0].bb)
+    self.assertEqual(222, ext2[1].bb)
+    self.assertEqual(333, ext2[2].bb)
+
+  def testMergeFromBug(self):
+    message1 = unittest_pb2.TestAllTypes()
+    message2 = unittest_pb2.TestAllTypes()
+
+    # Cause optional_nested_message to be instantiated within message1, even
+    # though it is not considered to be "present".
+    message1.optional_nested_message
+    self.assertFalse(message1.HasField('optional_nested_message'))
+
+    # Merge into message2.  This should not instantiate the field is message2.
+    message2.MergeFrom(message1)
+    self.assertFalse(message2.HasField('optional_nested_message'))
+
+  def testCopyFromSingularField(self):
+    # Test copy with just a singular field.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.optional_int32 = 1
+    proto1.optional_string = 'important-text'
+
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.optional_string = 'value'
+
+    proto2.CopyFrom(proto1)
+    self.assertEqual(1, proto2.optional_int32)
+    self.assertEqual('important-text', proto2.optional_string)
+
+  def testCopyFromRepeatedField(self):
+    # Test copy with a repeated field.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.repeated_int32.append(1)
+    proto1.repeated_int32.append(2)
+
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.repeated_int32.append(0)
+    proto2.CopyFrom(proto1)
+
+    self.assertEqual(1, proto2.repeated_int32[0])
+    self.assertEqual(2, proto2.repeated_int32[1])
+
+  def testCopyFromAllFields(self):
+    # With all fields set.
+    proto1 = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(proto1)
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.CopyFrom(proto1)
+
+    # Messages should be equal.
+    self.assertEqual(proto2, proto1)
+
+    # Serialized string should be equal too.
+    string1 = proto1.SerializeToString()
+    string2 = proto2.SerializeToString()
+    self.assertEqual(string1, string2)
+
+  def testCopyFromSelf(self):
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.repeated_int32.append(1)
+    proto1.optional_int32 = 2
+    proto1.optional_string = 'important-text'
+
+    proto1.CopyFrom(proto1)
+    self.assertEqual(1, proto1.repeated_int32[0])
+    self.assertEqual(2, proto1.optional_int32)
+    self.assertEqual('important-text', proto1.optional_string)
+
+  def testCopyFromBadType(self):
+    # The python implementation doesn't raise an exception in this
+    # case. In theory it should.
+    if api_implementation.Type() == 'python':
+      return
+    proto1 = unittest_pb2.TestAllTypes()
+    proto2 = unittest_pb2.TestAllExtensions()
+    self.assertRaises(TypeError, proto1.CopyFrom, proto2)
+
+  def testDeepCopy(self):
+    proto1 = unittest_pb2.TestAllTypes()
+    proto1.optional_int32 = 1
+    proto2 = copy.deepcopy(proto1)
+    self.assertEqual(1, proto2.optional_int32)
+
+    proto1.repeated_int32.append(2)
+    proto1.repeated_int32.append(3)
+    container = copy.deepcopy(proto1.repeated_int32)
+    self.assertEqual([2, 3], container)
+
+    # TODO(anuraag): Implement deepcopy for repeated composite / extension dict
+
+  def testClear(self):
+    proto = unittest_pb2.TestAllTypes()
+    # C++ implementation does not support lazy fields right now so leave it
+    # out for now.
+    if api_implementation.Type() == 'python':
+      test_util.SetAllFields(proto)
+    else:
+      test_util.SetAllNonLazyFields(proto)
+    # Clear the message.
+    proto.Clear()
+    self.assertEqual(proto.ByteSize(), 0)
+    empty_proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(proto, empty_proto)
+
+    # Test if extensions which were set are cleared.
+    proto = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(proto)
+    # Clear the message.
+    proto.Clear()
+    self.assertEqual(proto.ByteSize(), 0)
+    empty_proto = unittest_pb2.TestAllExtensions()
+    self.assertEqual(proto, empty_proto)
+
+  def testDisconnectingBeforeClear(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    proto.Clear()
+    self.assertTrue(nested is not proto.optional_nested_message)
+    nested.bb = 23
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    nested.bb = 5
+    foreign = proto.optional_foreign_message
+    foreign.c = 6
+
+    proto.Clear()
+    self.assertTrue(nested is not proto.optional_nested_message)
+    self.assertTrue(foreign is not proto.optional_foreign_message)
+    self.assertEqual(5, nested.bb)
+    self.assertEqual(6, foreign.c)
+    nested.bb = 15
+    foreign.c = 16
+    self.assertFalse(proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+    self.assertFalse(proto.HasField('optional_foreign_message'))
+    self.assertEqual(0, proto.optional_foreign_message.c)
+
+  def testOneOf(self):
+    proto = unittest_pb2.TestAllTypes()
+    proto.oneof_uint32 = 10
+    proto.oneof_nested_message.bb = 11
+    self.assertEqual(11, proto.oneof_nested_message.bb)
+    self.assertFalse(proto.HasField('oneof_uint32'))
+    nested = proto.oneof_nested_message
+    proto.oneof_string = 'abc'
+    self.assertEqual('abc', proto.oneof_string)
+    self.assertEqual(11, nested.bb)
+    self.assertFalse(proto.HasField('oneof_nested_message'))
+
+  def assertInitialized(self, proto):
+    self.assertTrue(proto.IsInitialized())
+    # Neither method should raise an exception.
+    proto.SerializeToString()
+    proto.SerializePartialToString()
+
+  def assertNotInitialized(self, proto):
+    self.assertFalse(proto.IsInitialized())
+    self.assertRaises(message.EncodeError, proto.SerializeToString)
+    # "Partial" serialization doesn't care if message is uninitialized.
+    proto.SerializePartialToString()
+
+  def testIsInitialized(self):
+    # Trivial cases - all optional fields and extensions.
+    proto = unittest_pb2.TestAllTypes()
+    self.assertInitialized(proto)
+    proto = unittest_pb2.TestAllExtensions()
+    self.assertInitialized(proto)
+
+    # The case of uninitialized required fields.
+    proto = unittest_pb2.TestRequired()
+    self.assertNotInitialized(proto)
+    proto.a = proto.b = proto.c = 2
+    self.assertInitialized(proto)
+
+    # The case of uninitialized submessage.
+    proto = unittest_pb2.TestRequiredForeign()
+    self.assertInitialized(proto)
+    proto.optional_message.a = 1
+    self.assertNotInitialized(proto)
+    proto.optional_message.b = 0
+    proto.optional_message.c = 0
+    self.assertInitialized(proto)
+
+    # Uninitialized repeated submessage.
+    message1 = proto.repeated_message.add()
+    self.assertNotInitialized(proto)
+    message1.a = message1.b = message1.c = 0
+    self.assertInitialized(proto)
+
+    # Uninitialized repeated group in an extension.
+    proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.TestRequired.multi
+    message1 = proto.Extensions[extension].add()
+    message2 = proto.Extensions[extension].add()
+    self.assertNotInitialized(proto)
+    message1.a = 1
+    message1.b = 1
+    message1.c = 1
+    self.assertNotInitialized(proto)
+    message2.a = 2
+    message2.b = 2
+    message2.c = 2
+    self.assertInitialized(proto)
+
+    # Uninitialized nonrepeated message in an extension.
+    proto = unittest_pb2.TestAllExtensions()
+    extension = unittest_pb2.TestRequired.single
+    proto.Extensions[extension].a = 1
+    self.assertNotInitialized(proto)
+    proto.Extensions[extension].b = 2
+    proto.Extensions[extension].c = 3
+    self.assertInitialized(proto)
+
+    # Try passing an errors list.
+    errors = []
+    proto = unittest_pb2.TestRequired()
+    self.assertFalse(proto.IsInitialized(errors))
+    self.assertEqual(errors, ['a', 'b', 'c'])
+
+  @unittest.skipIf(
+      api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+      'Errors are only available from the most recent C++ implementation.')
+  def testFileDescriptorErrors(self):
+    file_name = 'test_file_descriptor_errors.proto'
+    package_name = 'test_file_descriptor_errors.proto'
+    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+    file_descriptor_proto.name = file_name
+    file_descriptor_proto.package = package_name
+    m1 = file_descriptor_proto.message_type.add()
+    m1.name = 'msg1'
+    # Compiles the proto into the C++ descriptor pool
+    descriptor.FileDescriptor(
+        file_name,
+        package_name,
+        serialized_pb=file_descriptor_proto.SerializeToString())
+    # Add a FileDescriptorProto that has duplicate symbols
+    another_file_name = 'another_test_file_descriptor_errors.proto'
+    file_descriptor_proto.name = another_file_name
+    m2 = file_descriptor_proto.message_type.add()
+    m2.name = 'msg2'
+    with self.assertRaises(TypeError) as cm:
+      descriptor.FileDescriptor(
+          another_file_name,
+          package_name,
+          serialized_pb=file_descriptor_proto.SerializeToString())
+      self.assertTrue(hasattr(cm, 'exception'), '%s not raised' %
+                      getattr(cm.expected, '__name__', cm.expected))
+      self.assertIn('test_file_descriptor_errors.proto', str(cm.exception))
+      # Error message will say something about this definition being a
+      # duplicate, though we don't check the message exactly to avoid a
+      # dependency on the C++ logging code.
+      self.assertIn('test_file_descriptor_errors.msg1', str(cm.exception))
+
+  def testStringUTF8Encoding(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    # Assignment of a unicode object to a field of type 'bytes' is not allowed.
+    self.assertRaises(TypeError,
+                      setattr, proto, 'optional_bytes', u'unicode object')
+
+    # Check that the default value is of python's 'unicode' type.
+    self.assertEqual(type(proto.optional_string), six.text_type)
+
+    proto.optional_string = six.text_type('Testing')
+    self.assertEqual(proto.optional_string, str('Testing'))
+
+    # Assign a value of type 'str' which can be encoded in UTF-8.
+    proto.optional_string = str('Testing')
+    self.assertEqual(proto.optional_string, six.text_type('Testing'))
+
+    # Try to assign a 'bytes' object which contains non-UTF-8.
+    self.assertRaises(ValueError,
+                      setattr, proto, 'optional_string', b'a\x80a')
+    # No exception: Assign already encoded UTF-8 bytes to a string field.
+    utf8_bytes = u'Тест'.encode('utf-8')
+    proto.optional_string = utf8_bytes
+    # No exception: Assign the a non-ascii unicode object.
+    proto.optional_string = u'Тест'
+    # No exception thrown (normal str assignment containing ASCII).
+    proto.optional_string = 'abc'
+
+  def testStringUTF8Serialization(self):
+    proto = message_set_extensions_pb2.TestMessageSet()
+    extension_message = message_set_extensions_pb2.TestMessageSetExtension2
+    extension = extension_message.message_set_extension
+
+    test_utf8 = u'Тест'
+    test_utf8_bytes = test_utf8.encode('utf-8')
+
+    # 'Test' in another language, using UTF-8 charset.
+    proto.Extensions[extension].str = test_utf8
+
+    # Serialize using the MessageSet wire format (this is specified in the
+    # .proto file).
+    serialized = proto.SerializeToString()
+
+    # Check byte size.
+    self.assertEqual(proto.ByteSize(), len(serialized))
+
+    raw = unittest_mset_pb2.RawMessageSet()
+    bytes_read = raw.MergeFromString(serialized)
+    self.assertEqual(len(serialized), bytes_read)
+
+    message2 = message_set_extensions_pb2.TestMessageSetExtension2()
+
+    self.assertEqual(1, len(raw.item))
+    # Check that the type_id is the same as the tag ID in the .proto file.
+    self.assertEqual(raw.item[0].type_id, 98418634)
+
+    # Check the actual bytes on the wire.
+    self.assertTrue(raw.item[0].message.endswith(test_utf8_bytes))
+    bytes_read = message2.MergeFromString(raw.item[0].message)
+    self.assertEqual(len(raw.item[0].message), bytes_read)
+
+    self.assertEqual(type(message2.str), six.text_type)
+    self.assertEqual(message2.str, test_utf8)
+
+    # The pure Python API throws an exception on MergeFromString(),
+    # if any of the string fields of the message can't be UTF-8 decoded.
+    # The C++ implementation of the API has no way to check that on
+    # MergeFromString and thus has no way to throw the exception.
+    #
+    # The pure Python API always returns objects of type 'unicode' (UTF-8
+    # encoded), or 'bytes' (in 7 bit ASCII).
+    badbytes = raw.item[0].message.replace(
+        test_utf8_bytes, len(test_utf8_bytes) * b'\xff')
+
+    unicode_decode_failed = False
+    try:
+      message2.MergeFromString(badbytes)
+    except UnicodeDecodeError:
+      unicode_decode_failed = True
+    string_field = message2.str
+    self.assertTrue(unicode_decode_failed or type(string_field) is bytes)
+
+  def testBytesInTextFormat(self):
+    proto = unittest_pb2.TestAllTypes(optional_bytes=b'\x00\x7f\x80\xff')
+    self.assertEqual(u'optional_bytes: "\\000\\177\\200\\377"\n',
+                     six.text_type(proto))
+
+  def testEmptyNestedMessage(self):
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_nested_message.MergeFrom(
+        unittest_pb2.TestAllTypes.NestedMessage())
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_nested_message.CopyFrom(
+        unittest_pb2.TestAllTypes.NestedMessage())
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+    proto = unittest_pb2.TestAllTypes()
+    bytes_read = proto.optional_nested_message.MergeFromString(b'')
+    self.assertEqual(0, bytes_read)
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_nested_message.ParseFromString(b'')
+    self.assertTrue(proto.HasField('optional_nested_message'))
+
+    serialized = proto.SerializeToString()
+    proto2 = unittest_pb2.TestAllTypes()
+    self.assertEqual(
+        len(serialized),
+        proto2.MergeFromString(serialized))
+    self.assertTrue(proto2.HasField('optional_nested_message'))
+
+  def testSetInParent(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertFalse(proto.HasField('optionalgroup'))
+    proto.optionalgroup.SetInParent()
+    self.assertTrue(proto.HasField('optionalgroup'))
+
+  def testPackageInitializationImport(self):
+    """Test that we can import nested messages from their __init__.py.
+
+    Such setup is not trivial since at the time of processing of __init__.py one
+    can't refer to its submodules by name in code, so expressions like
+    google.protobuf.internal.import_test_package.inner_pb2
+    don't work. They do work in imports, so we have assign an alias at import
+    and then use that alias in generated code.
+    """
+    # We import here since it's the import that used to fail, and we want
+    # the failure to have the right context.
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf.internal import import_test_package
+    # pylint: enable=g-import-not-at-top
+    msg = import_test_package.myproto.Outer()
+    # Just check the default value.
+    self.assertEqual(57, msg.inner.value)
+
+#  Since we had so many tests for protocol buffer equality, we broke these out
+#  into separate TestCase classes.
+
+
+class TestAllTypesEqualityTest(unittest.TestCase):
+
+  def setUp(self):
+    self.first_proto = unittest_pb2.TestAllTypes()
+    self.second_proto = unittest_pb2.TestAllTypes()
+
+  def testNotHashable(self):
+    self.assertRaises(TypeError, hash, self.first_proto)
+
+  def testSelfEquality(self):
+    self.assertEqual(self.first_proto, self.first_proto)
+
+  def testEmptyProtosEqual(self):
+    self.assertEqual(self.first_proto, self.second_proto)
+
+
+class FullProtosEqualityTest(unittest.TestCase):
+
+  """Equality tests using completely-full protos as a starting point."""
+
+  def setUp(self):
+    self.first_proto = unittest_pb2.TestAllTypes()
+    self.second_proto = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(self.first_proto)
+    test_util.SetAllFields(self.second_proto)
+
+  def testNotHashable(self):
+    self.assertRaises(TypeError, hash, self.first_proto)
+
+  def testNoneNotEqual(self):
+    self.assertNotEqual(self.first_proto, None)
+    self.assertNotEqual(None, self.second_proto)
+
+  def testNotEqualToOtherMessage(self):
+    third_proto = unittest_pb2.TestRequired()
+    self.assertNotEqual(self.first_proto, third_proto)
+    self.assertNotEqual(third_proto, self.second_proto)
+
+  def testAllFieldsFilledEquality(self):
+    self.assertEqual(self.first_proto, self.second_proto)
+
+  def testNonRepeatedScalar(self):
+    # Nonrepeated scalar field change should cause inequality.
+    self.first_proto.optional_int32 += 1
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    # ...as should clearing a field.
+    self.first_proto.ClearField('optional_int32')
+    self.assertNotEqual(self.first_proto, self.second_proto)
+
+  def testNonRepeatedComposite(self):
+    # Change a nonrepeated composite field.
+    self.first_proto.optional_nested_message.bb += 1
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.first_proto.optional_nested_message.bb -= 1
+    self.assertEqual(self.first_proto, self.second_proto)
+    # Clear a field in the nested message.
+    self.first_proto.optional_nested_message.ClearField('bb')
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.first_proto.optional_nested_message.bb = (
+        self.second_proto.optional_nested_message.bb)
+    self.assertEqual(self.first_proto, self.second_proto)
+    # Remove the nested message entirely.
+    self.first_proto.ClearField('optional_nested_message')
+    self.assertNotEqual(self.first_proto, self.second_proto)
+
+  def testRepeatedScalar(self):
+    # Change a repeated scalar field.
+    self.first_proto.repeated_int32.append(5)
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.first_proto.ClearField('repeated_int32')
+    self.assertNotEqual(self.first_proto, self.second_proto)
+
+  def testRepeatedComposite(self):
+    # Change value within a repeated composite field.
+    self.first_proto.repeated_nested_message[0].bb += 1
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.first_proto.repeated_nested_message[0].bb -= 1
+    self.assertEqual(self.first_proto, self.second_proto)
+    # Add a value to a repeated composite field.
+    self.first_proto.repeated_nested_message.add()
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.second_proto.repeated_nested_message.add()
+    self.assertEqual(self.first_proto, self.second_proto)
+
+  def testNonRepeatedScalarHasBits(self):
+    # Ensure that we test "has" bits as well as value for
+    # nonrepeated scalar field.
+    self.first_proto.ClearField('optional_int32')
+    self.second_proto.optional_int32 = 0
+    self.assertNotEqual(self.first_proto, self.second_proto)
+
+  def testNonRepeatedCompositeHasBits(self):
+    # Ensure that we test "has" bits as well as value for
+    # nonrepeated composite field.
+    self.first_proto.ClearField('optional_nested_message')
+    self.second_proto.optional_nested_message.ClearField('bb')
+    self.assertNotEqual(self.first_proto, self.second_proto)
+    self.first_proto.optional_nested_message.bb = 0
+    self.first_proto.optional_nested_message.ClearField('bb')
+    self.assertEqual(self.first_proto, self.second_proto)
+
+
+class ExtensionEqualityTest(unittest.TestCase):
+
+  def testExtensionEquality(self):
+    first_proto = unittest_pb2.TestAllExtensions()
+    second_proto = unittest_pb2.TestAllExtensions()
+    self.assertEqual(first_proto, second_proto)
+    test_util.SetAllExtensions(first_proto)
+    self.assertNotEqual(first_proto, second_proto)
+    test_util.SetAllExtensions(second_proto)
+    self.assertEqual(first_proto, second_proto)
+
+    # Ensure that we check value equality.
+    first_proto.Extensions[unittest_pb2.optional_int32_extension] += 1
+    self.assertNotEqual(first_proto, second_proto)
+    first_proto.Extensions[unittest_pb2.optional_int32_extension] -= 1
+    self.assertEqual(first_proto, second_proto)
+
+    # Ensure that we also look at "has" bits.
+    first_proto.ClearExtension(unittest_pb2.optional_int32_extension)
+    second_proto.Extensions[unittest_pb2.optional_int32_extension] = 0
+    self.assertNotEqual(first_proto, second_proto)
+    first_proto.Extensions[unittest_pb2.optional_int32_extension] = 0
+    self.assertEqual(first_proto, second_proto)
+
+    # Ensure that differences in cached values
+    # don't matter if "has" bits are both false.
+    first_proto = unittest_pb2.TestAllExtensions()
+    second_proto = unittest_pb2.TestAllExtensions()
+    self.assertEqual(
+        0, first_proto.Extensions[unittest_pb2.optional_int32_extension])
+    self.assertEqual(first_proto, second_proto)
+
+
+class MutualRecursionEqualityTest(unittest.TestCase):
+
+  def testEqualityWithMutualRecursion(self):
+    first_proto = unittest_pb2.TestMutualRecursionA()
+    second_proto = unittest_pb2.TestMutualRecursionA()
+    self.assertEqual(first_proto, second_proto)
+    first_proto.bb.a.bb.optional_int32 = 23
+    self.assertNotEqual(first_proto, second_proto)
+    second_proto.bb.a.bb.optional_int32 = 23
+    self.assertEqual(first_proto, second_proto)
+
+
+class ByteSizeTest(unittest.TestCase):
+
+  def setUp(self):
+    self.proto = unittest_pb2.TestAllTypes()
+    self.extended_proto = more_extensions_pb2.ExtendedMessage()
+    self.packed_proto = unittest_pb2.TestPackedTypes()
+    self.packed_extended_proto = unittest_pb2.TestPackedExtensions()
+
+  def Size(self):
+    return self.proto.ByteSize()
+
+  def testEmptyMessage(self):
+    self.assertEqual(0, self.proto.ByteSize())
+
+  def testSizedOnKwargs(self):
+    # Use a separate message to ensure testing right after creation.
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, proto.ByteSize())
+    proto_kwargs = unittest_pb2.TestAllTypes(optional_int64 = 1)
+    # One byte for the tag, one to encode varint 1.
+    self.assertEqual(2, proto_kwargs.ByteSize())
+
+  def testVarints(self):
+    def Test(i, expected_varint_size):
+      self.proto.Clear()
+      self.proto.optional_int64 = i
+      # Add one to the varint size for the tag info
+      # for tag 1.
+      self.assertEqual(expected_varint_size + 1, self.Size())
+    Test(0, 1)
+    Test(1, 1)
+    for i, num_bytes in zip(range(7, 63, 7), range(1, 10000)):
+      Test((1 << i) - 1, num_bytes)
+    Test(-1, 10)
+    Test(-2, 10)
+    Test(-(1 << 63), 10)
+
+  def testStrings(self):
+    self.proto.optional_string = ''
+    # Need one byte for tag info (tag #14), and one byte for length.
+    self.assertEqual(2, self.Size())
+
+    self.proto.optional_string = 'abc'
+    # Need one byte for tag info (tag #14), and one byte for length.
+    self.assertEqual(2 + len(self.proto.optional_string), self.Size())
+
+    self.proto.optional_string = 'x' * 128
+    # Need one byte for tag info (tag #14), and TWO bytes for length.
+    self.assertEqual(3 + len(self.proto.optional_string), self.Size())
+
+  def testOtherNumerics(self):
+    self.proto.optional_fixed32 = 1234
+    # One byte for tag and 4 bytes for fixed32.
+    self.assertEqual(5, self.Size())
+    self.proto = unittest_pb2.TestAllTypes()
+
+    self.proto.optional_fixed64 = 1234
+    # One byte for tag and 8 bytes for fixed64.
+    self.assertEqual(9, self.Size())
+    self.proto = unittest_pb2.TestAllTypes()
+
+    self.proto.optional_float = 1.234
+    # One byte for tag and 4 bytes for float.
+    self.assertEqual(5, self.Size())
+    self.proto = unittest_pb2.TestAllTypes()
+
+    self.proto.optional_double = 1.234
+    # One byte for tag and 8 bytes for float.
+    self.assertEqual(9, self.Size())
+    self.proto = unittest_pb2.TestAllTypes()
+
+    self.proto.optional_sint32 = 64
+    # One byte for tag and 2 bytes for zig-zag-encoded 64.
+    self.assertEqual(3, self.Size())
+    self.proto = unittest_pb2.TestAllTypes()
+
+  def testComposites(self):
+    # 3 bytes.
+    self.proto.optional_nested_message.bb = (1 << 14)
+    # Plus one byte for bb tag.
+    # Plus 1 byte for optional_nested_message serialized size.
+    # Plus two bytes for optional_nested_message tag.
+    self.assertEqual(3 + 1 + 1 + 2, self.Size())
+
+  def testGroups(self):
+    # 4 bytes.
+    self.proto.optionalgroup.a = (1 << 21)
+    # Plus two bytes for |a| tag.
+    # Plus 2 * two bytes for START_GROUP and END_GROUP tags.
+    self.assertEqual(4 + 2 + 2*2, self.Size())
+
+  def testRepeatedScalars(self):
+    self.proto.repeated_int32.append(10)  # 1 byte.
+    self.proto.repeated_int32.append(128)  # 2 bytes.
+    # Also need 2 bytes for each entry for tag.
+    self.assertEqual(1 + 2 + 2*2, self.Size())
+
+  def testRepeatedScalarsExtend(self):
+    self.proto.repeated_int32.extend([10, 128])  # 3 bytes.
+    # Also need 2 bytes for each entry for tag.
+    self.assertEqual(1 + 2 + 2*2, self.Size())
+
+  def testRepeatedScalarsRemove(self):
+    self.proto.repeated_int32.append(10)  # 1 byte.
+    self.proto.repeated_int32.append(128)  # 2 bytes.
+    # Also need 2 bytes for each entry for tag.
+    self.assertEqual(1 + 2 + 2*2, self.Size())
+    self.proto.repeated_int32.remove(128)
+    self.assertEqual(1 + 2, self.Size())
+
+  def testRepeatedComposites(self):
+    # Empty message.  2 bytes tag plus 1 byte length.
+    foreign_message_0 = self.proto.repeated_nested_message.add()
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    foreign_message_1 = self.proto.repeated_nested_message.add()
+    foreign_message_1.bb = 7
+    self.assertEqual(2 + 1 + 2 + 1 + 1 + 1, self.Size())
+
+  def testRepeatedCompositesDelete(self):
+    # Empty message.  2 bytes tag plus 1 byte length.
+    foreign_message_0 = self.proto.repeated_nested_message.add()
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    foreign_message_1 = self.proto.repeated_nested_message.add()
+    foreign_message_1.bb = 9
+    self.assertEqual(2 + 1 + 2 + 1 + 1 + 1, self.Size())
+
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    del self.proto.repeated_nested_message[0]
+    self.assertEqual(2 + 1 + 1 + 1, self.Size())
+
+    # Now add a new message.
+    foreign_message_2 = self.proto.repeated_nested_message.add()
+    foreign_message_2.bb = 12
+
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    self.assertEqual(2 + 1 + 1 + 1 + 2 + 1 + 1 + 1, self.Size())
+
+    # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int.
+    del self.proto.repeated_nested_message[1]
+    self.assertEqual(2 + 1 + 1 + 1, self.Size())
+
+    del self.proto.repeated_nested_message[0]
+    self.assertEqual(0, self.Size())
+
+  def testRepeatedGroups(self):
+    # 2-byte START_GROUP plus 2-byte END_GROUP.
+    group_0 = self.proto.repeatedgroup.add()
+    # 2-byte START_GROUP plus 2-byte |a| tag + 1-byte |a|
+    # plus 2-byte END_GROUP.
+    group_1 = self.proto.repeatedgroup.add()
+    group_1.a =  7
+    self.assertEqual(2 + 2 + 2 + 2 + 1 + 2, self.Size())
+
+  def testExtensions(self):
+    proto = unittest_pb2.TestAllExtensions()
+    self.assertEqual(0, proto.ByteSize())
+    extension = unittest_pb2.optional_int32_extension  # Field #1, 1 byte.
+    proto.Extensions[extension] = 23
+    # 1 byte for tag, 1 byte for value.
+    self.assertEqual(2, proto.ByteSize())
+
+  def testCacheInvalidationForNonrepeatedScalar(self):
+    # Test non-extension.
+    self.proto.optional_int32 = 1
+    self.assertEqual(2, self.proto.ByteSize())
+    self.proto.optional_int32 = 128
+    self.assertEqual(3, self.proto.ByteSize())
+    self.proto.ClearField('optional_int32')
+    self.assertEqual(0, self.proto.ByteSize())
+
+    # Test within extension.
+    extension = more_extensions_pb2.optional_int_extension
+    self.extended_proto.Extensions[extension] = 1
+    self.assertEqual(2, self.extended_proto.ByteSize())
+    self.extended_proto.Extensions[extension] = 128
+    self.assertEqual(3, self.extended_proto.ByteSize())
+    self.extended_proto.ClearExtension(extension)
+    self.assertEqual(0, self.extended_proto.ByteSize())
+
+  def testCacheInvalidationForRepeatedScalar(self):
+    # Test non-extension.
+    self.proto.repeated_int32.append(1)
+    self.assertEqual(3, self.proto.ByteSize())
+    self.proto.repeated_int32.append(1)
+    self.assertEqual(6, self.proto.ByteSize())
+    self.proto.repeated_int32[1] = 128
+    self.assertEqual(7, self.proto.ByteSize())
+    self.proto.ClearField('repeated_int32')
+    self.assertEqual(0, self.proto.ByteSize())
+
+    # Test within extension.
+    extension = more_extensions_pb2.repeated_int_extension
+    repeated = self.extended_proto.Extensions[extension]
+    repeated.append(1)
+    self.assertEqual(2, self.extended_proto.ByteSize())
+    repeated.append(1)
+    self.assertEqual(4, self.extended_proto.ByteSize())
+    repeated[1] = 128
+    self.assertEqual(5, self.extended_proto.ByteSize())
+    self.extended_proto.ClearExtension(extension)
+    self.assertEqual(0, self.extended_proto.ByteSize())
+
+  def testCacheInvalidationForNonrepeatedMessage(self):
+    # Test non-extension.
+    self.proto.optional_foreign_message.c = 1
+    self.assertEqual(5, self.proto.ByteSize())
+    self.proto.optional_foreign_message.c = 128
+    self.assertEqual(6, self.proto.ByteSize())
+    self.proto.optional_foreign_message.ClearField('c')
+    self.assertEqual(3, self.proto.ByteSize())
+    self.proto.ClearField('optional_foreign_message')
+    self.assertEqual(0, self.proto.ByteSize())
+
+    if api_implementation.Type() == 'python':
+      # This is only possible in pure-Python implementation of the API.
+      child = self.proto.optional_foreign_message
+      self.proto.ClearField('optional_foreign_message')
+      child.c = 128
+      self.assertEqual(0, self.proto.ByteSize())
+
+    # Test within extension.
+    extension = more_extensions_pb2.optional_message_extension
+    child = self.extended_proto.Extensions[extension]
+    self.assertEqual(0, self.extended_proto.ByteSize())
+    child.foreign_message_int = 1
+    self.assertEqual(4, self.extended_proto.ByteSize())
+    child.foreign_message_int = 128
+    self.assertEqual(5, self.extended_proto.ByteSize())
+    self.extended_proto.ClearExtension(extension)
+    self.assertEqual(0, self.extended_proto.ByteSize())
+
+  def testCacheInvalidationForRepeatedMessage(self):
+    # Test non-extension.
+    child0 = self.proto.repeated_foreign_message.add()
+    self.assertEqual(3, self.proto.ByteSize())
+    self.proto.repeated_foreign_message.add()
+    self.assertEqual(6, self.proto.ByteSize())
+    child0.c = 1
+    self.assertEqual(8, self.proto.ByteSize())
+    self.proto.ClearField('repeated_foreign_message')
+    self.assertEqual(0, self.proto.ByteSize())
+
+    # Test within extension.
+    extension = more_extensions_pb2.repeated_message_extension
+    child_list = self.extended_proto.Extensions[extension]
+    child0 = child_list.add()
+    self.assertEqual(2, self.extended_proto.ByteSize())
+    child_list.add()
+    self.assertEqual(4, self.extended_proto.ByteSize())
+    child0.foreign_message_int = 1
+    self.assertEqual(6, self.extended_proto.ByteSize())
+    child0.ClearField('foreign_message_int')
+    self.assertEqual(4, self.extended_proto.ByteSize())
+    self.extended_proto.ClearExtension(extension)
+    self.assertEqual(0, self.extended_proto.ByteSize())
+
+  def testPackedRepeatedScalars(self):
+    self.assertEqual(0, self.packed_proto.ByteSize())
+
+    self.packed_proto.packed_int32.append(10)   # 1 byte.
+    self.packed_proto.packed_int32.append(128)  # 2 bytes.
+    # The tag is 2 bytes (the field number is 90), and the varint
+    # storing the length is 1 byte.
+    int_size = 1 + 2 + 3
+    self.assertEqual(int_size, self.packed_proto.ByteSize())
+
+    self.packed_proto.packed_double.append(4.2)   # 8 bytes
+    self.packed_proto.packed_double.append(3.25)  # 8 bytes
+    # 2 more tag bytes, 1 more length byte.
+    double_size = 8 + 8 + 3
+    self.assertEqual(int_size+double_size, self.packed_proto.ByteSize())
+
+    self.packed_proto.ClearField('packed_int32')
+    self.assertEqual(double_size, self.packed_proto.ByteSize())
+
+  def testPackedExtensions(self):
+    self.assertEqual(0, self.packed_extended_proto.ByteSize())
+    extension = self.packed_extended_proto.Extensions[
+        unittest_pb2.packed_fixed32_extension]
+    extension.extend([1, 2, 3, 4])   # 16 bytes
+    # Tag is 3 bytes.
+    self.assertEqual(19, self.packed_extended_proto.ByteSize())
+
+
+# Issues to be sure to cover include:
+#   * Handling of unrecognized tags ("uninterpreted_bytes").
+#   * Handling of MessageSets.
+#   * Consistent ordering of tags in the wire format,
+#     including ordering between extensions and non-extension
+#     fields.
+#   * Consistent serialization of negative numbers, especially
+#     negative int32s.
+#   * Handling of empty submessages (with and without "has"
+#     bits set).
+
+class SerializationTest(unittest.TestCase):
+
+  def testSerializeEmtpyMessage(self):
+    first_proto = unittest_pb2.TestAllTypes()
+    second_proto = unittest_pb2.TestAllTypes()
+    serialized = first_proto.SerializeToString()
+    self.assertEqual(first_proto.ByteSize(), len(serialized))
+    self.assertEqual(
+        len(serialized),
+        second_proto.MergeFromString(serialized))
+    self.assertEqual(first_proto, second_proto)
+
+  def testSerializeAllFields(self):
+    first_proto = unittest_pb2.TestAllTypes()
+    second_proto = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(first_proto)
+    serialized = first_proto.SerializeToString()
+    self.assertEqual(first_proto.ByteSize(), len(serialized))
+    self.assertEqual(
+        len(serialized),
+        second_proto.MergeFromString(serialized))
+    self.assertEqual(first_proto, second_proto)
+
+  def testSerializeAllExtensions(self):
+    first_proto = unittest_pb2.TestAllExtensions()
+    second_proto = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(first_proto)
+    serialized = first_proto.SerializeToString()
+    self.assertEqual(
+        len(serialized),
+        second_proto.MergeFromString(serialized))
+    self.assertEqual(first_proto, second_proto)
+
+  def testSerializeWithOptionalGroup(self):
+    first_proto = unittest_pb2.TestAllTypes()
+    second_proto = unittest_pb2.TestAllTypes()
+    first_proto.optionalgroup.a = 242
+    serialized = first_proto.SerializeToString()
+    self.assertEqual(
+        len(serialized),
+        second_proto.MergeFromString(serialized))
+    self.assertEqual(first_proto, second_proto)
+
+  def testSerializeNegativeValues(self):
+    first_proto = unittest_pb2.TestAllTypes()
+
+    first_proto.optional_int32 = -1
+    first_proto.optional_int64 = -(2 << 40)
+    first_proto.optional_sint32 = -3
+    first_proto.optional_sint64 = -(4 << 40)
+    first_proto.optional_sfixed32 = -5
+    first_proto.optional_sfixed64 = -(6 << 40)
+
+    second_proto = unittest_pb2.TestAllTypes.FromString(
+        first_proto.SerializeToString())
+
+    self.assertEqual(first_proto, second_proto)
+
+  def testParseTruncated(self):
+    # This test is only applicable for the Python implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
+    first_proto = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(first_proto)
+    serialized = first_proto.SerializeToString()
+
+    for truncation_point in range(len(serialized) + 1):
+      try:
+        second_proto = unittest_pb2.TestAllTypes()
+        unknown_fields = unittest_pb2.TestEmptyMessage()
+        pos = second_proto._InternalParse(serialized, 0, truncation_point)
+        # If we didn't raise an error then we read exactly the amount expected.
+        self.assertEqual(truncation_point, pos)
+
+        # Parsing to unknown fields should not throw if parsing to known fields
+        # did not.
+        try:
+          pos2 = unknown_fields._InternalParse(serialized, 0, truncation_point)
+          self.assertEqual(truncation_point, pos2)
+        except message.DecodeError:
+          self.fail('Parsing unknown fields failed when parsing known fields '
+                    'did not.')
+      except message.DecodeError:
+        # Parsing unknown fields should also fail.
+        self.assertRaises(message.DecodeError, unknown_fields._InternalParse,
+                          serialized, 0, truncation_point)
+
+  def testCanonicalSerializationOrder(self):
+    proto = more_messages_pb2.OutOfOrderFields()
+    # These are also their tag numbers.  Even though we're setting these in
+    # reverse-tag order AND they're listed in reverse tag-order in the .proto
+    # file, they should nonetheless be serialized in tag order.
+    proto.optional_sint32 = 5
+    proto.Extensions[more_messages_pb2.optional_uint64] = 4
+    proto.optional_uint32 = 3
+    proto.Extensions[more_messages_pb2.optional_int64] = 2
+    proto.optional_int32 = 1
+    serialized = proto.SerializeToString()
+    self.assertEqual(proto.ByteSize(), len(serialized))
+    d = _MiniDecoder(serialized)
+    ReadTag = d.ReadFieldNumberAndWireType
+    self.assertEqual((1, wire_format.WIRETYPE_VARINT), ReadTag())
+    self.assertEqual(1, d.ReadInt32())
+    self.assertEqual((2, wire_format.WIRETYPE_VARINT), ReadTag())
+    self.assertEqual(2, d.ReadInt64())
+    self.assertEqual((3, wire_format.WIRETYPE_VARINT), ReadTag())
+    self.assertEqual(3, d.ReadUInt32())
+    self.assertEqual((4, wire_format.WIRETYPE_VARINT), ReadTag())
+    self.assertEqual(4, d.ReadUInt64())
+    self.assertEqual((5, wire_format.WIRETYPE_VARINT), ReadTag())
+    self.assertEqual(5, d.ReadSInt32())
+
+  def testCanonicalSerializationOrderSameAsCpp(self):
+    # Copy of the same test we use for C++.
+    proto = unittest_pb2.TestFieldOrderings()
+    test_util.SetAllFieldsAndExtensions(proto)
+    serialized = proto.SerializeToString()
+    test_util.ExpectAllFieldsAndExtensionsInOrder(serialized)
+
+  def testMergeFromStringWhenFieldsAlreadySet(self):
+    first_proto = unittest_pb2.TestAllTypes()
+    first_proto.repeated_string.append('foobar')
+    first_proto.optional_int32 = 23
+    first_proto.optional_nested_message.bb = 42
+    serialized = first_proto.SerializeToString()
+
+    second_proto = unittest_pb2.TestAllTypes()
+    second_proto.repeated_string.append('baz')
+    second_proto.optional_int32 = 100
+    second_proto.optional_nested_message.bb = 999
+
+    bytes_parsed = second_proto.MergeFromString(serialized)
+    self.assertEqual(len(serialized), bytes_parsed)
+
+    # Ensure that we append to repeated fields.
+    self.assertEqual(['baz', 'foobar'], list(second_proto.repeated_string))
+    # Ensure that we overwrite nonrepeatd scalars.
+    self.assertEqual(23, second_proto.optional_int32)
+    # Ensure that we recursively call MergeFromString() on
+    # submessages.
+    self.assertEqual(42, second_proto.optional_nested_message.bb)
+
+  def testMessageSetWireFormat(self):
+    proto = message_set_extensions_pb2.TestMessageSet()
+    extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+    extension_message2 = message_set_extensions_pb2.TestMessageSetExtension2
+    extension1 = extension_message1.message_set_extension
+    extension2 = extension_message2.message_set_extension
+    extension3 = message_set_extensions_pb2.message_set_extension3
+    proto.Extensions[extension1].i = 123
+    proto.Extensions[extension2].str = 'foo'
+    proto.Extensions[extension3].text = 'bar'
+
+    # Serialize using the MessageSet wire format (this is specified in the
+    # .proto file).
+    serialized = proto.SerializeToString()
+
+    raw = unittest_mset_pb2.RawMessageSet()
+    self.assertEqual(False,
+                     raw.DESCRIPTOR.GetOptions().message_set_wire_format)
+    self.assertEqual(
+        len(serialized),
+        raw.MergeFromString(serialized))
+    self.assertEqual(3, len(raw.item))
+
+    message1 = message_set_extensions_pb2.TestMessageSetExtension1()
+    self.assertEqual(
+        len(raw.item[0].message),
+        message1.MergeFromString(raw.item[0].message))
+    self.assertEqual(123, message1.i)
+
+    message2 = message_set_extensions_pb2.TestMessageSetExtension2()
+    self.assertEqual(
+        len(raw.item[1].message),
+        message2.MergeFromString(raw.item[1].message))
+    self.assertEqual('foo', message2.str)
+
+    message3 = message_set_extensions_pb2.TestMessageSetExtension3()
+    self.assertEqual(
+        len(raw.item[2].message),
+        message3.MergeFromString(raw.item[2].message))
+    self.assertEqual('bar', message3.text)
+
+    # Deserialize using the MessageSet wire format.
+    proto2 = message_set_extensions_pb2.TestMessageSet()
+    self.assertEqual(
+        len(serialized),
+        proto2.MergeFromString(serialized))
+    self.assertEqual(123, proto2.Extensions[extension1].i)
+    self.assertEqual('foo', proto2.Extensions[extension2].str)
+    self.assertEqual('bar', proto2.Extensions[extension3].text)
+
+    # Check byte size.
+    self.assertEqual(proto2.ByteSize(), len(serialized))
+    self.assertEqual(proto.ByteSize(), len(serialized))
+
+  def testMessageSetWireFormatUnknownExtension(self):
+    # Create a message using the message set wire format with an unknown
+    # message.
+    raw = unittest_mset_pb2.RawMessageSet()
+
+    # Add an item.
+    item = raw.item.add()
+    item.type_id = 98418603
+    extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+    message1 = message_set_extensions_pb2.TestMessageSetExtension1()
+    message1.i = 12345
+    item.message = message1.SerializeToString()
+
+    # Add a second, unknown extension.
+    item = raw.item.add()
+    item.type_id = 98418604
+    extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+    message1 = message_set_extensions_pb2.TestMessageSetExtension1()
+    message1.i = 12346
+    item.message = message1.SerializeToString()
+
+    # Add another unknown extension.
+    item = raw.item.add()
+    item.type_id = 98418605
+    message1 = message_set_extensions_pb2.TestMessageSetExtension2()
+    message1.str = 'foo'
+    item.message = message1.SerializeToString()
+
+    serialized = raw.SerializeToString()
+
+    # Parse message using the message set wire format.
+    proto = message_set_extensions_pb2.TestMessageSet()
+    self.assertEqual(
+        len(serialized),
+        proto.MergeFromString(serialized))
+
+    # Check that the message parsed well.
+    extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+    extension1 = extension_message1.message_set_extension
+    self.assertEqual(12345, proto.Extensions[extension1].i)
+
+  def testUnknownFields(self):
+    proto = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(proto)
+
+    serialized = proto.SerializeToString()
+
+    # The empty message should be parsable with all of the fields
+    # unknown.
+    proto2 = unittest_pb2.TestEmptyMessage()
+
+    # Parsing this message should succeed.
+    self.assertEqual(
+        len(serialized),
+        proto2.MergeFromString(serialized))
+
+    # Now test with a int64 field set.
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_int64 = 0x0fffffffffffffff
+    serialized = proto.SerializeToString()
+    # The empty message should be parsable with all of the fields
+    # unknown.
+    proto2 = unittest_pb2.TestEmptyMessage()
+    # Parsing this message should succeed.
+    self.assertEqual(
+        len(serialized),
+        proto2.MergeFromString(serialized))
+
+  def _CheckRaises(self, exc_class, callable_obj, exception):
+    """This method checks if the excpetion type and message are as expected."""
+    try:
+      callable_obj()
+    except exc_class as ex:
+      # Check if the exception message is the right one.
+      self.assertEqual(exception, str(ex))
+      return
+    else:
+      raise self.failureException('%s not raised' % str(exc_class))
+
+  def testSerializeUninitialized(self):
+    proto = unittest_pb2.TestRequired()
+    self._CheckRaises(
+        message.EncodeError,
+        proto.SerializeToString,
+        'Message protobuf_unittest.TestRequired is missing required fields: '
+        'a,b,c')
+    # Shouldn't raise exceptions.
+    partial = proto.SerializePartialToString()
+
+    proto2 = unittest_pb2.TestRequired()
+    self.assertFalse(proto2.HasField('a'))
+    # proto2 ParseFromString does not check that required fields are set.
+    proto2.ParseFromString(partial)
+    self.assertFalse(proto2.HasField('a'))
+
+    proto.a = 1
+    self._CheckRaises(
+        message.EncodeError,
+        proto.SerializeToString,
+        'Message protobuf_unittest.TestRequired is missing required fields: b,c')
+    # Shouldn't raise exceptions.
+    partial = proto.SerializePartialToString()
+
+    proto.b = 2
+    self._CheckRaises(
+        message.EncodeError,
+        proto.SerializeToString,
+        'Message protobuf_unittest.TestRequired is missing required fields: c')
+    # Shouldn't raise exceptions.
+    partial = proto.SerializePartialToString()
+
+    proto.c = 3
+    serialized = proto.SerializeToString()
+    # Shouldn't raise exceptions.
+    partial = proto.SerializePartialToString()
+
+    proto2 = unittest_pb2.TestRequired()
+    self.assertEqual(
+        len(serialized),
+        proto2.MergeFromString(serialized))
+    self.assertEqual(1, proto2.a)
+    self.assertEqual(2, proto2.b)
+    self.assertEqual(3, proto2.c)
+    self.assertEqual(
+        len(partial),
+        proto2.MergeFromString(partial))
+    self.assertEqual(1, proto2.a)
+    self.assertEqual(2, proto2.b)
+    self.assertEqual(3, proto2.c)
+
+  def testSerializeUninitializedSubMessage(self):
+    proto = unittest_pb2.TestRequiredForeign()
+
+    # Sub-message doesn't exist yet, so this succeeds.
+    proto.SerializeToString()
+
+    proto.optional_message.a = 1
+    self._CheckRaises(
+        message.EncodeError,
+        proto.SerializeToString,
+        'Message protobuf_unittest.TestRequiredForeign '
+        'is missing required fields: '
+        'optional_message.b,optional_message.c')
+
+    proto.optional_message.b = 2
+    proto.optional_message.c = 3
+    proto.SerializeToString()
+
+    proto.repeated_message.add().a = 1
+    proto.repeated_message.add().b = 2
+    self._CheckRaises(
+        message.EncodeError,
+        proto.SerializeToString,
+        'Message protobuf_unittest.TestRequiredForeign is missing required fields: '
+        'repeated_message[0].b,repeated_message[0].c,'
+        'repeated_message[1].a,repeated_message[1].c')
+
+    proto.repeated_message[0].b = 2
+    proto.repeated_message[0].c = 3
+    proto.repeated_message[1].a = 1
+    proto.repeated_message[1].c = 3
+    proto.SerializeToString()
+
+  def testSerializeAllPackedFields(self):
+    first_proto = unittest_pb2.TestPackedTypes()
+    second_proto = unittest_pb2.TestPackedTypes()
+    test_util.SetAllPackedFields(first_proto)
+    serialized = first_proto.SerializeToString()
+    self.assertEqual(first_proto.ByteSize(), len(serialized))
+    bytes_read = second_proto.MergeFromString(serialized)
+    self.assertEqual(second_proto.ByteSize(), bytes_read)
+    self.assertEqual(first_proto, second_proto)
+
+  def testSerializeAllPackedExtensions(self):
+    first_proto = unittest_pb2.TestPackedExtensions()
+    second_proto = unittest_pb2.TestPackedExtensions()
+    test_util.SetAllPackedExtensions(first_proto)
+    serialized = first_proto.SerializeToString()
+    bytes_read = second_proto.MergeFromString(serialized)
+    self.assertEqual(second_proto.ByteSize(), bytes_read)
+    self.assertEqual(first_proto, second_proto)
+
+  def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
+    first_proto = unittest_pb2.TestPackedTypes()
+    first_proto.packed_int32.extend([1, 2])
+    first_proto.packed_double.append(3.0)
+    serialized = first_proto.SerializeToString()
+
+    second_proto = unittest_pb2.TestPackedTypes()
+    second_proto.packed_int32.append(3)
+    second_proto.packed_double.extend([1.0, 2.0])
+    second_proto.packed_sint32.append(4)
+
+    self.assertEqual(
+        len(serialized),
+        second_proto.MergeFromString(serialized))
+    self.assertEqual([3, 1, 2], second_proto.packed_int32)
+    self.assertEqual([1.0, 2.0, 3.0], second_proto.packed_double)
+    self.assertEqual([4], second_proto.packed_sint32)
+
+  def testPackedFieldsWireFormat(self):
+    proto = unittest_pb2.TestPackedTypes()
+    proto.packed_int32.extend([1, 2, 150, 3])  # 1 + 1 + 2 + 1 bytes
+    proto.packed_double.extend([1.0, 1000.0])  # 8 + 8 bytes
+    proto.packed_float.append(2.0)             # 4 bytes, will be before double
+    serialized = proto.SerializeToString()
+    self.assertEqual(proto.ByteSize(), len(serialized))
+    d = _MiniDecoder(serialized)
+    ReadTag = d.ReadFieldNumberAndWireType
+    self.assertEqual((90, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+    self.assertEqual(1+1+1+2, d.ReadInt32())
+    self.assertEqual(1, d.ReadInt32())
+    self.assertEqual(2, d.ReadInt32())
+    self.assertEqual(150, d.ReadInt32())
+    self.assertEqual(3, d.ReadInt32())
+    self.assertEqual((100, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+    self.assertEqual(4, d.ReadInt32())
+    self.assertEqual(2.0, d.ReadFloat())
+    self.assertEqual((101, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+    self.assertEqual(8+8, d.ReadInt32())
+    self.assertEqual(1.0, d.ReadDouble())
+    self.assertEqual(1000.0, d.ReadDouble())
+    self.assertTrue(d.EndOfStream())
+
+  def testParsePackedFromUnpacked(self):
+    unpacked = unittest_pb2.TestUnpackedTypes()
+    test_util.SetAllUnpackedFields(unpacked)
+    packed = unittest_pb2.TestPackedTypes()
+    serialized = unpacked.SerializeToString()
+    self.assertEqual(
+        len(serialized),
+        packed.MergeFromString(serialized))
+    expected = unittest_pb2.TestPackedTypes()
+    test_util.SetAllPackedFields(expected)
+    self.assertEqual(expected, packed)
+
+  def testParseUnpackedFromPacked(self):
+    packed = unittest_pb2.TestPackedTypes()
+    test_util.SetAllPackedFields(packed)
+    unpacked = unittest_pb2.TestUnpackedTypes()
+    serialized = packed.SerializeToString()
+    self.assertEqual(
+        len(serialized),
+        unpacked.MergeFromString(serialized))
+    expected = unittest_pb2.TestUnpackedTypes()
+    test_util.SetAllUnpackedFields(expected)
+    self.assertEqual(expected, unpacked)
+
+  def testFieldNumbers(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(unittest_pb2.TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1)
+    self.assertEqual(unittest_pb2.TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1)
+    self.assertEqual(unittest_pb2.TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16)
+    self.assertEqual(
+      unittest_pb2.TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18)
+    self.assertEqual(
+      unittest_pb2.TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21)
+    self.assertEqual(unittest_pb2.TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31)
+    self.assertEqual(unittest_pb2.TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46)
+    self.assertEqual(
+      unittest_pb2.TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48)
+    self.assertEqual(
+      unittest_pb2.TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51)
+
+  def testExtensionFieldNumbers(self):
+    self.assertEqual(unittest_pb2.TestRequired.single.number, 1000)
+    self.assertEqual(unittest_pb2.TestRequired.SINGLE_FIELD_NUMBER, 1000)
+    self.assertEqual(unittest_pb2.TestRequired.multi.number, 1001)
+    self.assertEqual(unittest_pb2.TestRequired.MULTI_FIELD_NUMBER, 1001)
+    self.assertEqual(unittest_pb2.optional_int32_extension.number, 1)
+    self.assertEqual(unittest_pb2.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1)
+    self.assertEqual(unittest_pb2.optionalgroup_extension.number, 16)
+    self.assertEqual(unittest_pb2.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16)
+    self.assertEqual(unittest_pb2.optional_nested_message_extension.number, 18)
+    self.assertEqual(
+      unittest_pb2.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18)
+    self.assertEqual(unittest_pb2.optional_nested_enum_extension.number, 21)
+    self.assertEqual(unittest_pb2.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
+      21)
+    self.assertEqual(unittest_pb2.repeated_int32_extension.number, 31)
+    self.assertEqual(unittest_pb2.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31)
+    self.assertEqual(unittest_pb2.repeatedgroup_extension.number, 46)
+    self.assertEqual(unittest_pb2.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46)
+    self.assertEqual(unittest_pb2.repeated_nested_message_extension.number, 48)
+    self.assertEqual(
+      unittest_pb2.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48)
+    self.assertEqual(unittest_pb2.repeated_nested_enum_extension.number, 51)
+    self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
+      51)
+
+  def testInitKwargs(self):
+    proto = unittest_pb2.TestAllTypes(
+        optional_int32=1,
+        optional_string='foo',
+        optional_bool=True,
+        optional_bytes=b'bar',
+        optional_nested_message=unittest_pb2.TestAllTypes.NestedMessage(bb=1),
+        optional_foreign_message=unittest_pb2.ForeignMessage(c=1),
+        optional_nested_enum=unittest_pb2.TestAllTypes.FOO,
+        optional_foreign_enum=unittest_pb2.FOREIGN_FOO,
+        repeated_int32=[1, 2, 3])
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('optional_int32'))
+    self.assertTrue(proto.HasField('optional_string'))
+    self.assertTrue(proto.HasField('optional_bool'))
+    self.assertTrue(proto.HasField('optional_bytes'))
+    self.assertTrue(proto.HasField('optional_nested_message'))
+    self.assertTrue(proto.HasField('optional_foreign_message'))
+    self.assertTrue(proto.HasField('optional_nested_enum'))
+    self.assertTrue(proto.HasField('optional_foreign_enum'))
+    self.assertEqual(1, proto.optional_int32)
+    self.assertEqual('foo', proto.optional_string)
+    self.assertEqual(True, proto.optional_bool)
+    self.assertEqual(b'bar', proto.optional_bytes)
+    self.assertEqual(1, proto.optional_nested_message.bb)
+    self.assertEqual(1, proto.optional_foreign_message.c)
+    self.assertEqual(unittest_pb2.TestAllTypes.FOO,
+                     proto.optional_nested_enum)
+    self.assertEqual(unittest_pb2.FOREIGN_FOO, proto.optional_foreign_enum)
+    self.assertEqual([1, 2, 3], proto.repeated_int32)
+
+  def testInitArgsUnknownFieldName(self):
+    def InitalizeEmptyMessageWithExtraKeywordArg():
+      unused_proto = unittest_pb2.TestEmptyMessage(unknown='unknown')
+    self._CheckRaises(
+        ValueError,
+        InitalizeEmptyMessageWithExtraKeywordArg,
+        'Protocol message TestEmptyMessage has no "unknown" field.')
+
+  def testInitRequiredKwargs(self):
+    proto = unittest_pb2.TestRequired(a=1, b=1, c=1)
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('a'))
+    self.assertTrue(proto.HasField('b'))
+    self.assertTrue(proto.HasField('c'))
+    self.assertTrue(not proto.HasField('dummy2'))
+    self.assertEqual(1, proto.a)
+    self.assertEqual(1, proto.b)
+    self.assertEqual(1, proto.c)
+
+  def testInitRequiredForeignKwargs(self):
+    proto = unittest_pb2.TestRequiredForeign(
+        optional_message=unittest_pb2.TestRequired(a=1, b=1, c=1))
+    self.assertTrue(proto.IsInitialized())
+    self.assertTrue(proto.HasField('optional_message'))
+    self.assertTrue(proto.optional_message.IsInitialized())
+    self.assertTrue(proto.optional_message.HasField('a'))
+    self.assertTrue(proto.optional_message.HasField('b'))
+    self.assertTrue(proto.optional_message.HasField('c'))
+    self.assertTrue(not proto.optional_message.HasField('dummy2'))
+    self.assertEqual(unittest_pb2.TestRequired(a=1, b=1, c=1),
+                     proto.optional_message)
+    self.assertEqual(1, proto.optional_message.a)
+    self.assertEqual(1, proto.optional_message.b)
+    self.assertEqual(1, proto.optional_message.c)
+
+  def testInitRepeatedKwargs(self):
+    proto = unittest_pb2.TestAllTypes(repeated_int32=[1, 2, 3])
+    self.assertTrue(proto.IsInitialized())
+    self.assertEqual(1, proto.repeated_int32[0])
+    self.assertEqual(2, proto.repeated_int32[1])
+    self.assertEqual(3, proto.repeated_int32[2])
+
+
+class OptionsTest(unittest.TestCase):
+
+  def testMessageOptions(self):
+    proto = message_set_extensions_pb2.TestMessageSet()
+    self.assertEqual(True,
+                     proto.DESCRIPTOR.GetOptions().message_set_wire_format)
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(False,
+                     proto.DESCRIPTOR.GetOptions().message_set_wire_format)
+
+  def testPackedOptions(self):
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_int32 = 1
+    proto.optional_double = 3.0
+    for field_descriptor, _ in proto.ListFields():
+      self.assertEqual(False, field_descriptor.GetOptions().packed)
+
+    proto = unittest_pb2.TestPackedTypes()
+    proto.packed_int32.append(1)
+    proto.packed_double.append(3.0)
+    for field_descriptor, _ in proto.ListFields():
+      self.assertEqual(True, field_descriptor.GetOptions().packed)
+      self.assertEqual(descriptor.FieldDescriptor.LABEL_REPEATED,
+                       field_descriptor.label)
+
+
+
+class ClassAPITest(unittest.TestCase):
+
+  @unittest.skipIf(
+      api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+      'C++ implementation requires a call to MakeDescriptor()')
+  def testMakeClassWithNestedDescriptor(self):
+    leaf_desc = descriptor.Descriptor('leaf', 'package.parent.child.leaf', '',
+                                      containing_type=None, fields=[],
+                                      nested_types=[], enum_types=[],
+                                      extensions=[])
+    child_desc = descriptor.Descriptor('child', 'package.parent.child', '',
+                                       containing_type=None, fields=[],
+                                       nested_types=[leaf_desc], enum_types=[],
+                                       extensions=[])
+    sibling_desc = descriptor.Descriptor('sibling', 'package.parent.sibling',
+                                         '', containing_type=None, fields=[],
+                                         nested_types=[], enum_types=[],
+                                         extensions=[])
+    parent_desc = descriptor.Descriptor('parent', 'package.parent', '',
+                                        containing_type=None, fields=[],
+                                        nested_types=[child_desc, sibling_desc],
+                                        enum_types=[], extensions=[])
+    message_class = reflection.MakeClass(parent_desc)
+    self.assertIn('child', message_class.__dict__)
+    self.assertIn('sibling', message_class.__dict__)
+    self.assertIn('leaf', message_class.child.__dict__)
+
+  def _GetSerializedFileDescriptor(self, name):
+    """Get a serialized representation of a test FileDescriptorProto.
+
+    Args:
+      name: All calls to this must use a unique message name, to avoid
+          collisions in the cpp descriptor pool.
+    Returns:
+      A string containing the serialized form of a test FileDescriptorProto.
+    """
+    file_descriptor_str = (
+        'message_type {'
+        '  name: "' + name + '"'
+        '  field {'
+        '    name: "flat"'
+        '    number: 1'
+        '    label: LABEL_REPEATED'
+        '    type: TYPE_UINT32'
+        '  }'
+        '  field {'
+        '    name: "bar"'
+        '    number: 2'
+        '    label: LABEL_OPTIONAL'
+        '    type: TYPE_MESSAGE'
+        '    type_name: "Bar"'
+        '  }'
+        '  nested_type {'
+        '    name: "Bar"'
+        '    field {'
+        '      name: "baz"'
+        '      number: 3'
+        '      label: LABEL_OPTIONAL'
+        '      type: TYPE_MESSAGE'
+        '      type_name: "Baz"'
+        '    }'
+        '    nested_type {'
+        '      name: "Baz"'
+        '      enum_type {'
+        '        name: "deep_enum"'
+        '        value {'
+        '          name: "VALUE_A"'
+        '          number: 0'
+        '        }'
+        '      }'
+        '      field {'
+        '        name: "deep"'
+        '        number: 4'
+        '        label: LABEL_OPTIONAL'
+        '        type: TYPE_UINT32'
+        '      }'
+        '    }'
+        '  }'
+        '}')
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    text_format.Merge(file_descriptor_str, file_descriptor)
+    return file_descriptor.SerializeToString()
+
+  def testParsingFlatClassWithExplicitClassDeclaration(self):
+    """Test that the generated class can parse a flat message."""
+    # TODO(xiaofeng): This test fails with cpp implemetnation in the call
+    # of six.with_metaclass(). The other two callsites of with_metaclass
+    # in this file are both excluded from cpp test, so it might be expected
+    # to fail. Need someone more familiar with the python code to take a
+    # look at this.
+    if api_implementation.Type() != 'python':
+      return
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('A'))
+    msg_descriptor = descriptor.MakeDescriptor(
+        file_descriptor.message_type[0])
+
+    class MessageClass(six.with_metaclass(reflection.GeneratedProtocolMessageType, message.Message)):
+      DESCRIPTOR = msg_descriptor
+    msg = MessageClass()
+    msg_str = (
+        'flat: 0 '
+        'flat: 1 '
+        'flat: 2 ')
+    text_format.Merge(msg_str, msg)
+    self.assertEqual(msg.flat, [0, 1, 2])
+
+  def testParsingFlatClass(self):
+    """Test that the generated class can parse a flat message."""
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('B'))
+    msg_descriptor = descriptor.MakeDescriptor(
+        file_descriptor.message_type[0])
+    msg_class = reflection.MakeClass(msg_descriptor)
+    msg = msg_class()
+    msg_str = (
+        'flat: 0 '
+        'flat: 1 '
+        'flat: 2 ')
+    text_format.Merge(msg_str, msg)
+    self.assertEqual(msg.flat, [0, 1, 2])
+
+  def testParsingNestedClass(self):
+    """Test that the generated class can parse a nested message."""
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('C'))
+    msg_descriptor = descriptor.MakeDescriptor(
+        file_descriptor.message_type[0])
+    msg_class = reflection.MakeClass(msg_descriptor)
+    msg = msg_class()
+    msg_str = (
+        'bar {'
+        '  baz {'
+        '    deep: 4'
+        '  }'
+        '}')
+    text_format.Merge(msg_str, msg)
+    self.assertEqual(msg.bar.baz.deep, 4)
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/service_reflection_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/service_reflection_test.py
new file mode 100755
index 0000000..62900b1
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/service_reflection_test.py
@@ -0,0 +1,140 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.internal.service_reflection."""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import unittest_pb2
+from google.protobuf import service_reflection
+from google.protobuf import service
+
+
+class FooUnitTest(unittest.TestCase):
+
+  def testService(self):
+    class MockRpcChannel(service.RpcChannel):
+      def CallMethod(self, method, controller, request, response, callback):
+        self.method = method
+        self.controller = controller
+        self.request = request
+        callback(response)
+
+    class MockRpcController(service.RpcController):
+      def SetFailed(self, msg):
+        self.failure_message = msg
+
+    self.callback_response = None
+
+    class MyService(unittest_pb2.TestService):
+      pass
+
+    self.callback_response = None
+
+    def MyCallback(response):
+      self.callback_response = response
+
+    rpc_controller = MockRpcController()
+    channel = MockRpcChannel()
+    srvc = MyService()
+    srvc.Foo(rpc_controller, unittest_pb2.FooRequest(), MyCallback)
+    self.assertEqual('Method Foo not implemented.',
+                     rpc_controller.failure_message)
+    self.assertEqual(None, self.callback_response)
+
+    rpc_controller.failure_message = None
+
+    service_descriptor = unittest_pb2.TestService.GetDescriptor()
+    srvc.CallMethod(service_descriptor.methods[1], rpc_controller,
+                    unittest_pb2.BarRequest(), MyCallback)
+    self.assertEqual('Method Bar not implemented.',
+                     rpc_controller.failure_message)
+    self.assertEqual(None, self.callback_response)
+
+    class MyServiceImpl(unittest_pb2.TestService):
+      def Foo(self, rpc_controller, request, done):
+        self.foo_called = True
+      def Bar(self, rpc_controller, request, done):
+        self.bar_called = True
+
+    srvc = MyServiceImpl()
+    rpc_controller.failure_message = None
+    srvc.Foo(rpc_controller, unittest_pb2.FooRequest(), MyCallback)
+    self.assertEqual(None, rpc_controller.failure_message)
+    self.assertEqual(True, srvc.foo_called)
+
+    rpc_controller.failure_message = None
+    srvc.CallMethod(service_descriptor.methods[1], rpc_controller,
+                    unittest_pb2.BarRequest(), MyCallback)
+    self.assertEqual(None, rpc_controller.failure_message)
+    self.assertEqual(True, srvc.bar_called)
+
+  def testServiceStub(self):
+    class MockRpcChannel(service.RpcChannel):
+      def CallMethod(self, method, controller, request,
+                     response_class, callback):
+        self.method = method
+        self.controller = controller
+        self.request = request
+        callback(response_class())
+
+    self.callback_response = None
+
+    def MyCallback(response):
+      self.callback_response = response
+
+    channel = MockRpcChannel()
+    stub = unittest_pb2.TestService_Stub(channel)
+    rpc_controller = 'controller'
+    request = 'request'
+
+    # GetDescriptor now static, still works as instance method for compatibility
+    self.assertEqual(unittest_pb2.TestService_Stub.GetDescriptor(),
+                     stub.GetDescriptor())
+
+    # Invoke method.
+    stub.Foo(rpc_controller, request, MyCallback)
+
+    self.assertIsInstance(self.callback_response, unittest_pb2.FooResponse)
+    self.assertEqual(request, channel.request)
+    self.assertEqual(rpc_controller, channel.controller)
+    self.assertEqual(stub.GetDescriptor().methods[0], channel.method)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/symbol_database_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/symbol_database_test.py
new file mode 100644
index 0000000..c99b426
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/symbol_database_test.py
@@ -0,0 +1,129 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.symbol_database."""
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import unittest_pb2
+from google.protobuf import descriptor
+from google.protobuf import symbol_database
+
+class SymbolDatabaseTest(unittest.TestCase):
+
+  def _Database(self):
+    # TODO(b/17734095): Remove this difference when the C++ implementation
+    # supports multiple databases.
+    if descriptor._USE_C_DESCRIPTORS:
+      return symbol_database.Default()
+    else:
+      db = symbol_database.SymbolDatabase()
+      # Register representative types from unittest_pb2.
+      db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR)
+      db.RegisterMessage(unittest_pb2.TestAllTypes)
+      db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage)
+      db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup)
+      db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup)
+      db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
+      db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
+      return db
+
+  def testGetPrototype(self):
+    instance = self._Database().GetPrototype(
+        unittest_pb2.TestAllTypes.DESCRIPTOR)
+    self.assertTrue(instance is unittest_pb2.TestAllTypes)
+
+  def testGetMessages(self):
+    messages = self._Database().GetMessages(
+        ['google/protobuf/unittest.proto'])
+    self.assertTrue(
+        unittest_pb2.TestAllTypes is
+        messages['protobuf_unittest.TestAllTypes'])
+
+  def testGetSymbol(self):
+    self.assertEqual(
+        unittest_pb2.TestAllTypes, self._Database().GetSymbol(
+            'protobuf_unittest.TestAllTypes'))
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.NestedMessage, self._Database().GetSymbol(
+            'protobuf_unittest.TestAllTypes.NestedMessage'))
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.OptionalGroup, self._Database().GetSymbol(
+            'protobuf_unittest.TestAllTypes.OptionalGroup'))
+    self.assertEqual(
+        unittest_pb2.TestAllTypes.RepeatedGroup, self._Database().GetSymbol(
+            'protobuf_unittest.TestAllTypes.RepeatedGroup'))
+
+  def testEnums(self):
+    # Check registration of types in the pool.
+    self.assertEqual(
+        'protobuf_unittest.ForeignEnum',
+        self._Database().pool.FindEnumTypeByName(
+            'protobuf_unittest.ForeignEnum').full_name)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes.NestedEnum',
+        self._Database().pool.FindEnumTypeByName(
+            'protobuf_unittest.TestAllTypes.NestedEnum').full_name)
+
+  def testFindMessageTypeByName(self):
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes',
+        self._Database().pool.FindMessageTypeByName(
+            'protobuf_unittest.TestAllTypes').full_name)
+    self.assertEqual(
+        'protobuf_unittest.TestAllTypes.NestedMessage',
+        self._Database().pool.FindMessageTypeByName(
+            'protobuf_unittest.TestAllTypes.NestedMessage').full_name)
+
+  def testFindFindContainingSymbol(self):
+    # Lookup based on either enum or message.
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        self._Database().pool.FindFileContainingSymbol(
+            'protobuf_unittest.TestAllTypes.NestedEnum').name)
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        self._Database().pool.FindFileContainingSymbol(
+            'protobuf_unittest.TestAllTypes').name)
+
+  def testFindFileByName(self):
+    self.assertEqual(
+        'google/protobuf/unittest.proto',
+        self._Database().pool.FindFileByName(
+            'google/protobuf/unittest.proto').name)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/test_bad_identifiers.proto b/src/third_party/protobuf-3/python/google/protobuf/internal/test_bad_identifiers.proto
new file mode 100644
index 0000000..c4860ea
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/test_bad_identifiers.proto
@@ -0,0 +1,53 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option py_generic_services = true;
+
+message TestBadIdentifiers {
+  extensions 100 to max;
+}
+
+// Make sure these reasonable extension names don't conflict with internal
+// variables.
+extend TestBadIdentifiers {
+  optional string message = 100 [default="foo"];
+  optional string descriptor = 101 [default="bar"];
+  optional string reflection = 102 [default="baz"];
+  optional string service = 103 [default="qux"];
+}
+
+message AnotherMessage {}
+service AnotherService {}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/test_util.py b/src/third_party/protobuf-3/python/google/protobuf/internal/test_util.py
new file mode 100755
index 0000000..2c80559
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/test_util.py
@@ -0,0 +1,696 @@
+# 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.
+
+"""Utilities for Python proto2 tests.
+
+This is intentionally modeled on C++ code in
+//google/protobuf/test_util.*.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+import os.path
+
+import sys
+
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
+
+# Tests whether the given TestAllTypes message is proto2 or not.
+# This is used to gate several fields/features that only exist
+# for the proto2 version of the message.
+def IsProto2(message):
+  return message.DESCRIPTOR.syntax == "proto2"
+
+def SetAllNonLazyFields(message):
+  """Sets every non-lazy field in the message to a unique value.
+
+  Args:
+    message: A TestAllTypes instance.
+  """
+
+  #
+  # Optional fields.
+  #
+
+  message.optional_int32    = 101
+  message.optional_int64    = 102
+  message.optional_uint32   = 103
+  message.optional_uint64   = 104
+  message.optional_sint32   = 105
+  message.optional_sint64   = 106
+  message.optional_fixed32  = 107
+  message.optional_fixed64  = 108
+  message.optional_sfixed32 = 109
+  message.optional_sfixed64 = 110
+  message.optional_float    = 111
+  message.optional_double   = 112
+  message.optional_bool     = True
+  message.optional_string   = u'115'
+  message.optional_bytes    = b'116'
+
+  if IsProto2(message):
+    message.optionalgroup.a = 117
+  message.optional_nested_message.bb = 118
+  message.optional_foreign_message.c = 119
+  message.optional_import_message.d = 120
+  message.optional_public_import_message.e = 126
+
+  message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
+  message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
+  if IsProto2(message):
+    message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
+
+  message.optional_string_piece = u'124'
+  message.optional_cord = u'125'
+
+  #
+  # Repeated fields.
+  #
+
+  message.repeated_int32.append(201)
+  message.repeated_int64.append(202)
+  message.repeated_uint32.append(203)
+  message.repeated_uint64.append(204)
+  message.repeated_sint32.append(205)
+  message.repeated_sint64.append(206)
+  message.repeated_fixed32.append(207)
+  message.repeated_fixed64.append(208)
+  message.repeated_sfixed32.append(209)
+  message.repeated_sfixed64.append(210)
+  message.repeated_float.append(211)
+  message.repeated_double.append(212)
+  message.repeated_bool.append(True)
+  message.repeated_string.append(u'215')
+  message.repeated_bytes.append(b'216')
+
+  if IsProto2(message):
+    message.repeatedgroup.add().a = 217
+  message.repeated_nested_message.add().bb = 218
+  message.repeated_foreign_message.add().c = 219
+  message.repeated_import_message.add().d = 220
+  message.repeated_lazy_message.add().bb = 227
+
+  message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
+  message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
+  if IsProto2(message):
+    message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
+
+  message.repeated_string_piece.append(u'224')
+  message.repeated_cord.append(u'225')
+
+  # Add a second one of each field.
+  message.repeated_int32.append(301)
+  message.repeated_int64.append(302)
+  message.repeated_uint32.append(303)
+  message.repeated_uint64.append(304)
+  message.repeated_sint32.append(305)
+  message.repeated_sint64.append(306)
+  message.repeated_fixed32.append(307)
+  message.repeated_fixed64.append(308)
+  message.repeated_sfixed32.append(309)
+  message.repeated_sfixed64.append(310)
+  message.repeated_float.append(311)
+  message.repeated_double.append(312)
+  message.repeated_bool.append(False)
+  message.repeated_string.append(u'315')
+  message.repeated_bytes.append(b'316')
+
+  if IsProto2(message):
+    message.repeatedgroup.add().a = 317
+  message.repeated_nested_message.add().bb = 318
+  message.repeated_foreign_message.add().c = 319
+  message.repeated_import_message.add().d = 320
+  message.repeated_lazy_message.add().bb = 327
+
+  message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
+  message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
+  if IsProto2(message):
+    message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
+
+  message.repeated_string_piece.append(u'324')
+  message.repeated_cord.append(u'325')
+
+  #
+  # Fields that have defaults.
+  #
+
+  if IsProto2(message):
+    message.default_int32 = 401
+    message.default_int64 = 402
+    message.default_uint32 = 403
+    message.default_uint64 = 404
+    message.default_sint32 = 405
+    message.default_sint64 = 406
+    message.default_fixed32 = 407
+    message.default_fixed64 = 408
+    message.default_sfixed32 = 409
+    message.default_sfixed64 = 410
+    message.default_float = 411
+    message.default_double = 412
+    message.default_bool = False
+    message.default_string = '415'
+    message.default_bytes = b'416'
+
+    message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
+    message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
+    message.default_import_enum = unittest_import_pb2.IMPORT_FOO
+
+    message.default_string_piece = '424'
+    message.default_cord = '425'
+
+  message.oneof_uint32 = 601
+  message.oneof_nested_message.bb = 602
+  message.oneof_string = '603'
+  message.oneof_bytes = b'604'
+
+
+def SetAllFields(message):
+  SetAllNonLazyFields(message)
+  message.optional_lazy_message.bb = 127
+
+
+def SetAllExtensions(message):
+  """Sets every extension in the message to a unique value.
+
+  Args:
+    message: A unittest_pb2.TestAllExtensions instance.
+  """
+
+  extensions = message.Extensions
+  pb2 = unittest_pb2
+  import_pb2 = unittest_import_pb2
+
+  #
+  # Optional fields.
+  #
+
+  extensions[pb2.optional_int32_extension] = 101
+  extensions[pb2.optional_int64_extension] = 102
+  extensions[pb2.optional_uint32_extension] = 103
+  extensions[pb2.optional_uint64_extension] = 104
+  extensions[pb2.optional_sint32_extension] = 105
+  extensions[pb2.optional_sint64_extension] = 106
+  extensions[pb2.optional_fixed32_extension] = 107
+  extensions[pb2.optional_fixed64_extension] = 108
+  extensions[pb2.optional_sfixed32_extension] = 109
+  extensions[pb2.optional_sfixed64_extension] = 110
+  extensions[pb2.optional_float_extension] = 111
+  extensions[pb2.optional_double_extension] = 112
+  extensions[pb2.optional_bool_extension] = True
+  extensions[pb2.optional_string_extension] = u'115'
+  extensions[pb2.optional_bytes_extension] = b'116'
+
+  extensions[pb2.optionalgroup_extension].a = 117
+  extensions[pb2.optional_nested_message_extension].bb = 118
+  extensions[pb2.optional_foreign_message_extension].c = 119
+  extensions[pb2.optional_import_message_extension].d = 120
+  extensions[pb2.optional_public_import_message_extension].e = 126
+  extensions[pb2.optional_lazy_message_extension].bb = 127
+
+  extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
+  extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
+  extensions[pb2.optional_foreign_enum_extension] = pb2.FOREIGN_BAZ
+  extensions[pb2.optional_import_enum_extension] = import_pb2.IMPORT_BAZ
+
+  extensions[pb2.optional_string_piece_extension] = u'124'
+  extensions[pb2.optional_cord_extension] = u'125'
+
+  #
+  # Repeated fields.
+  #
+
+  extensions[pb2.repeated_int32_extension].append(201)
+  extensions[pb2.repeated_int64_extension].append(202)
+  extensions[pb2.repeated_uint32_extension].append(203)
+  extensions[pb2.repeated_uint64_extension].append(204)
+  extensions[pb2.repeated_sint32_extension].append(205)
+  extensions[pb2.repeated_sint64_extension].append(206)
+  extensions[pb2.repeated_fixed32_extension].append(207)
+  extensions[pb2.repeated_fixed64_extension].append(208)
+  extensions[pb2.repeated_sfixed32_extension].append(209)
+  extensions[pb2.repeated_sfixed64_extension].append(210)
+  extensions[pb2.repeated_float_extension].append(211)
+  extensions[pb2.repeated_double_extension].append(212)
+  extensions[pb2.repeated_bool_extension].append(True)
+  extensions[pb2.repeated_string_extension].append(u'215')
+  extensions[pb2.repeated_bytes_extension].append(b'216')
+
+  extensions[pb2.repeatedgroup_extension].add().a = 217
+  extensions[pb2.repeated_nested_message_extension].add().bb = 218
+  extensions[pb2.repeated_foreign_message_extension].add().c = 219
+  extensions[pb2.repeated_import_message_extension].add().d = 220
+  extensions[pb2.repeated_lazy_message_extension].add().bb = 227
+
+  extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR)
+  extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR)
+  extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAR)
+
+  extensions[pb2.repeated_string_piece_extension].append(u'224')
+  extensions[pb2.repeated_cord_extension].append(u'225')
+
+  # Append a second one of each field.
+  extensions[pb2.repeated_int32_extension].append(301)
+  extensions[pb2.repeated_int64_extension].append(302)
+  extensions[pb2.repeated_uint32_extension].append(303)
+  extensions[pb2.repeated_uint64_extension].append(304)
+  extensions[pb2.repeated_sint32_extension].append(305)
+  extensions[pb2.repeated_sint64_extension].append(306)
+  extensions[pb2.repeated_fixed32_extension].append(307)
+  extensions[pb2.repeated_fixed64_extension].append(308)
+  extensions[pb2.repeated_sfixed32_extension].append(309)
+  extensions[pb2.repeated_sfixed64_extension].append(310)
+  extensions[pb2.repeated_float_extension].append(311)
+  extensions[pb2.repeated_double_extension].append(312)
+  extensions[pb2.repeated_bool_extension].append(False)
+  extensions[pb2.repeated_string_extension].append(u'315')
+  extensions[pb2.repeated_bytes_extension].append(b'316')
+
+  extensions[pb2.repeatedgroup_extension].add().a = 317
+  extensions[pb2.repeated_nested_message_extension].add().bb = 318
+  extensions[pb2.repeated_foreign_message_extension].add().c = 319
+  extensions[pb2.repeated_import_message_extension].add().d = 320
+  extensions[pb2.repeated_lazy_message_extension].add().bb = 327
+
+  extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ)
+  extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ)
+  extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAZ)
+
+  extensions[pb2.repeated_string_piece_extension].append(u'324')
+  extensions[pb2.repeated_cord_extension].append(u'325')
+
+  #
+  # Fields with defaults.
+  #
+
+  extensions[pb2.default_int32_extension] = 401
+  extensions[pb2.default_int64_extension] = 402
+  extensions[pb2.default_uint32_extension] = 403
+  extensions[pb2.default_uint64_extension] = 404
+  extensions[pb2.default_sint32_extension] = 405
+  extensions[pb2.default_sint64_extension] = 406
+  extensions[pb2.default_fixed32_extension] = 407
+  extensions[pb2.default_fixed64_extension] = 408
+  extensions[pb2.default_sfixed32_extension] = 409
+  extensions[pb2.default_sfixed64_extension] = 410
+  extensions[pb2.default_float_extension] = 411
+  extensions[pb2.default_double_extension] = 412
+  extensions[pb2.default_bool_extension] = False
+  extensions[pb2.default_string_extension] = u'415'
+  extensions[pb2.default_bytes_extension] = b'416'
+
+  extensions[pb2.default_nested_enum_extension] = pb2.TestAllTypes.FOO
+  extensions[pb2.default_foreign_enum_extension] = pb2.FOREIGN_FOO
+  extensions[pb2.default_import_enum_extension] = import_pb2.IMPORT_FOO
+
+  extensions[pb2.default_string_piece_extension] = u'424'
+  extensions[pb2.default_cord_extension] = '425'
+
+  extensions[pb2.oneof_uint32_extension] = 601
+  extensions[pb2.oneof_nested_message_extension].bb = 602
+  extensions[pb2.oneof_string_extension] = u'603'
+  extensions[pb2.oneof_bytes_extension] = b'604'
+
+
+def SetAllFieldsAndExtensions(message):
+  """Sets every field and extension in the message to a unique value.
+
+  Args:
+    message: A unittest_pb2.TestAllExtensions message.
+  """
+  message.my_int = 1
+  message.my_string = 'foo'
+  message.my_float = 1.0
+  message.Extensions[unittest_pb2.my_extension_int] = 23
+  message.Extensions[unittest_pb2.my_extension_string] = 'bar'
+
+
+def ExpectAllFieldsAndExtensionsInOrder(serialized):
+  """Ensures that serialized is the serialization we expect for a message
+  filled with SetAllFieldsAndExtensions().  (Specifically, ensures that the
+  serialization is in canonical, tag-number order).
+  """
+  my_extension_int = unittest_pb2.my_extension_int
+  my_extension_string = unittest_pb2.my_extension_string
+  expected_strings = []
+  message = unittest_pb2.TestFieldOrderings()
+  message.my_int = 1  # Field 1.
+  expected_strings.append(message.SerializeToString())
+  message.Clear()
+  message.Extensions[my_extension_int] = 23  # Field 5.
+  expected_strings.append(message.SerializeToString())
+  message.Clear()
+  message.my_string = 'foo'  # Field 11.
+  expected_strings.append(message.SerializeToString())
+  message.Clear()
+  message.Extensions[my_extension_string] = 'bar'  # Field 50.
+  expected_strings.append(message.SerializeToString())
+  message.Clear()
+  message.my_float = 1.0
+  expected_strings.append(message.SerializeToString())
+  message.Clear()
+  expected = b''.join(expected_strings)
+
+  if expected != serialized:
+    raise ValueError('Expected %r, found %r' % (expected, serialized))
+
+
+def ExpectAllFieldsSet(test_case, message):
+  """Check all fields for correct values have after Set*Fields() is called."""
+  test_case.assertTrue(message.HasField('optional_int32'))
+  test_case.assertTrue(message.HasField('optional_int64'))
+  test_case.assertTrue(message.HasField('optional_uint32'))
+  test_case.assertTrue(message.HasField('optional_uint64'))
+  test_case.assertTrue(message.HasField('optional_sint32'))
+  test_case.assertTrue(message.HasField('optional_sint64'))
+  test_case.assertTrue(message.HasField('optional_fixed32'))
+  test_case.assertTrue(message.HasField('optional_fixed64'))
+  test_case.assertTrue(message.HasField('optional_sfixed32'))
+  test_case.assertTrue(message.HasField('optional_sfixed64'))
+  test_case.assertTrue(message.HasField('optional_float'))
+  test_case.assertTrue(message.HasField('optional_double'))
+  test_case.assertTrue(message.HasField('optional_bool'))
+  test_case.assertTrue(message.HasField('optional_string'))
+  test_case.assertTrue(message.HasField('optional_bytes'))
+
+  if IsProto2(message):
+    test_case.assertTrue(message.HasField('optionalgroup'))
+  test_case.assertTrue(message.HasField('optional_nested_message'))
+  test_case.assertTrue(message.HasField('optional_foreign_message'))
+  test_case.assertTrue(message.HasField('optional_import_message'))
+
+  test_case.assertTrue(message.optionalgroup.HasField('a'))
+  test_case.assertTrue(message.optional_nested_message.HasField('bb'))
+  test_case.assertTrue(message.optional_foreign_message.HasField('c'))
+  test_case.assertTrue(message.optional_import_message.HasField('d'))
+
+  test_case.assertTrue(message.HasField('optional_nested_enum'))
+  test_case.assertTrue(message.HasField('optional_foreign_enum'))
+  if IsProto2(message):
+    test_case.assertTrue(message.HasField('optional_import_enum'))
+
+  test_case.assertTrue(message.HasField('optional_string_piece'))
+  test_case.assertTrue(message.HasField('optional_cord'))
+
+  test_case.assertEqual(101, message.optional_int32)
+  test_case.assertEqual(102, message.optional_int64)
+  test_case.assertEqual(103, message.optional_uint32)
+  test_case.assertEqual(104, message.optional_uint64)
+  test_case.assertEqual(105, message.optional_sint32)
+  test_case.assertEqual(106, message.optional_sint64)
+  test_case.assertEqual(107, message.optional_fixed32)
+  test_case.assertEqual(108, message.optional_fixed64)
+  test_case.assertEqual(109, message.optional_sfixed32)
+  test_case.assertEqual(110, message.optional_sfixed64)
+  test_case.assertEqual(111, message.optional_float)
+  test_case.assertEqual(112, message.optional_double)
+  test_case.assertEqual(True, message.optional_bool)
+  test_case.assertEqual('115', message.optional_string)
+  test_case.assertEqual(b'116', message.optional_bytes)
+
+  if IsProto2(message):
+    test_case.assertEqual(117, message.optionalgroup.a)
+  test_case.assertEqual(118, message.optional_nested_message.bb)
+  test_case.assertEqual(119, message.optional_foreign_message.c)
+  test_case.assertEqual(120, message.optional_import_message.d)
+  test_case.assertEqual(126, message.optional_public_import_message.e)
+  test_case.assertEqual(127, message.optional_lazy_message.bb)
+
+  test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                        message.optional_nested_enum)
+  test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
+                        message.optional_foreign_enum)
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                          message.optional_import_enum)
+
+  # -----------------------------------------------------------------
+
+  test_case.assertEqual(2, len(message.repeated_int32))
+  test_case.assertEqual(2, len(message.repeated_int64))
+  test_case.assertEqual(2, len(message.repeated_uint32))
+  test_case.assertEqual(2, len(message.repeated_uint64))
+  test_case.assertEqual(2, len(message.repeated_sint32))
+  test_case.assertEqual(2, len(message.repeated_sint64))
+  test_case.assertEqual(2, len(message.repeated_fixed32))
+  test_case.assertEqual(2, len(message.repeated_fixed64))
+  test_case.assertEqual(2, len(message.repeated_sfixed32))
+  test_case.assertEqual(2, len(message.repeated_sfixed64))
+  test_case.assertEqual(2, len(message.repeated_float))
+  test_case.assertEqual(2, len(message.repeated_double))
+  test_case.assertEqual(2, len(message.repeated_bool))
+  test_case.assertEqual(2, len(message.repeated_string))
+  test_case.assertEqual(2, len(message.repeated_bytes))
+
+  if IsProto2(message):
+    test_case.assertEqual(2, len(message.repeatedgroup))
+  test_case.assertEqual(2, len(message.repeated_nested_message))
+  test_case.assertEqual(2, len(message.repeated_foreign_message))
+  test_case.assertEqual(2, len(message.repeated_import_message))
+  test_case.assertEqual(2, len(message.repeated_nested_enum))
+  test_case.assertEqual(2, len(message.repeated_foreign_enum))
+  if IsProto2(message):
+    test_case.assertEqual(2, len(message.repeated_import_enum))
+
+  test_case.assertEqual(2, len(message.repeated_string_piece))
+  test_case.assertEqual(2, len(message.repeated_cord))
+
+  test_case.assertEqual(201, message.repeated_int32[0])
+  test_case.assertEqual(202, message.repeated_int64[0])
+  test_case.assertEqual(203, message.repeated_uint32[0])
+  test_case.assertEqual(204, message.repeated_uint64[0])
+  test_case.assertEqual(205, message.repeated_sint32[0])
+  test_case.assertEqual(206, message.repeated_sint64[0])
+  test_case.assertEqual(207, message.repeated_fixed32[0])
+  test_case.assertEqual(208, message.repeated_fixed64[0])
+  test_case.assertEqual(209, message.repeated_sfixed32[0])
+  test_case.assertEqual(210, message.repeated_sfixed64[0])
+  test_case.assertEqual(211, message.repeated_float[0])
+  test_case.assertEqual(212, message.repeated_double[0])
+  test_case.assertEqual(True, message.repeated_bool[0])
+  test_case.assertEqual('215', message.repeated_string[0])
+  test_case.assertEqual(b'216', message.repeated_bytes[0])
+
+  if IsProto2(message):
+    test_case.assertEqual(217, message.repeatedgroup[0].a)
+  test_case.assertEqual(218, message.repeated_nested_message[0].bb)
+  test_case.assertEqual(219, message.repeated_foreign_message[0].c)
+  test_case.assertEqual(220, message.repeated_import_message[0].d)
+  test_case.assertEqual(227, message.repeated_lazy_message[0].bb)
+
+  test_case.assertEqual(unittest_pb2.TestAllTypes.BAR,
+                        message.repeated_nested_enum[0])
+  test_case.assertEqual(unittest_pb2.FOREIGN_BAR,
+                        message.repeated_foreign_enum[0])
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
+                          message.repeated_import_enum[0])
+
+  test_case.assertEqual(301, message.repeated_int32[1])
+  test_case.assertEqual(302, message.repeated_int64[1])
+  test_case.assertEqual(303, message.repeated_uint32[1])
+  test_case.assertEqual(304, message.repeated_uint64[1])
+  test_case.assertEqual(305, message.repeated_sint32[1])
+  test_case.assertEqual(306, message.repeated_sint64[1])
+  test_case.assertEqual(307, message.repeated_fixed32[1])
+  test_case.assertEqual(308, message.repeated_fixed64[1])
+  test_case.assertEqual(309, message.repeated_sfixed32[1])
+  test_case.assertEqual(310, message.repeated_sfixed64[1])
+  test_case.assertEqual(311, message.repeated_float[1])
+  test_case.assertEqual(312, message.repeated_double[1])
+  test_case.assertEqual(False, message.repeated_bool[1])
+  test_case.assertEqual('315', message.repeated_string[1])
+  test_case.assertEqual(b'316', message.repeated_bytes[1])
+
+  if IsProto2(message):
+    test_case.assertEqual(317, message.repeatedgroup[1].a)
+  test_case.assertEqual(318, message.repeated_nested_message[1].bb)
+  test_case.assertEqual(319, message.repeated_foreign_message[1].c)
+  test_case.assertEqual(320, message.repeated_import_message[1].d)
+  test_case.assertEqual(327, message.repeated_lazy_message[1].bb)
+
+  test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+                        message.repeated_nested_enum[1])
+  test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
+                        message.repeated_foreign_enum[1])
+  if IsProto2(message):
+    test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+                          message.repeated_import_enum[1])
+
+  # -----------------------------------------------------------------
+
+  if IsProto2(message):
+    test_case.assertTrue(message.HasField('default_int32'))
+    test_case.assertTrue(message.HasField('default_int64'))
+    test_case.assertTrue(message.HasField('default_uint32'))
+    test_case.assertTrue(message.HasField('default_uint64'))
+    test_case.assertTrue(message.HasField('default_sint32'))
+    test_case.assertTrue(message.HasField('default_sint64'))
+    test_case.assertTrue(message.HasField('default_fixed32'))
+    test_case.assertTrue(message.HasField('default_fixed64'))
+    test_case.assertTrue(message.HasField('default_sfixed32'))
+    test_case.assertTrue(message.HasField('default_sfixed64'))
+    test_case.assertTrue(message.HasField('default_float'))
+    test_case.assertTrue(message.HasField('default_double'))
+    test_case.assertTrue(message.HasField('default_bool'))
+    test_case.assertTrue(message.HasField('default_string'))
+    test_case.assertTrue(message.HasField('default_bytes'))
+
+    test_case.assertTrue(message.HasField('default_nested_enum'))
+    test_case.assertTrue(message.HasField('default_foreign_enum'))
+    test_case.assertTrue(message.HasField('default_import_enum'))
+
+    test_case.assertEqual(401, message.default_int32)
+    test_case.assertEqual(402, message.default_int64)
+    test_case.assertEqual(403, message.default_uint32)
+    test_case.assertEqual(404, message.default_uint64)
+    test_case.assertEqual(405, message.default_sint32)
+    test_case.assertEqual(406, message.default_sint64)
+    test_case.assertEqual(407, message.default_fixed32)
+    test_case.assertEqual(408, message.default_fixed64)
+    test_case.assertEqual(409, message.default_sfixed32)
+    test_case.assertEqual(410, message.default_sfixed64)
+    test_case.assertEqual(411, message.default_float)
+    test_case.assertEqual(412, message.default_double)
+    test_case.assertEqual(False, message.default_bool)
+    test_case.assertEqual('415', message.default_string)
+    test_case.assertEqual(b'416', message.default_bytes)
+
+    test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
+                          message.default_nested_enum)
+    test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
+                          message.default_foreign_enum)
+    test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
+                          message.default_import_enum)
+
+
+def GoldenFile(filename):
+  """Finds the given golden file and returns a file object representing it."""
+
+  # Search up the directory tree looking for the C++ protobuf source code.
+  path = '.'
+  while os.path.exists(path):
+    if os.path.exists(os.path.join(path, 'src/google/protobuf')):
+      # Found it.  Load the golden file from the testdata directory.
+      full_path = os.path.join(path, 'src/google/protobuf/testdata', filename)
+      return open(full_path, 'rb')
+    path = os.path.join(path, '..')
+
+  # Search internally.
+  path = '.'
+  full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata',
+                           filename)
+  if os.path.exists(full_path):
+    # Found it.  Load the golden file from the testdata directory.
+    return open(full_path, 'rb')
+
+  raise RuntimeError(
+      'Could not find golden files.  This test must be run from within the '
+      'protobuf source package so that it can read test data files from the '
+      'C++ source tree.')
+
+
+def GoldenFileData(filename):
+  """Finds the given golden file and returns its contents."""
+  with GoldenFile(filename) as f:
+    return f.read()
+
+
+def SetAllPackedFields(message):
+  """Sets every field in the message to a unique value.
+
+  Args:
+    message: A TestPackedTypes instance.
+  """
+  message.packed_int32.extend([601, 701])
+  message.packed_int64.extend([602, 702])
+  message.packed_uint32.extend([603, 703])
+  message.packed_uint64.extend([604, 704])
+  message.packed_sint32.extend([605, 705])
+  message.packed_sint64.extend([606, 706])
+  message.packed_fixed32.extend([607, 707])
+  message.packed_fixed64.extend([608, 708])
+  message.packed_sfixed32.extend([609, 709])
+  message.packed_sfixed64.extend([610, 710])
+  message.packed_float.extend([611.0, 711.0])
+  message.packed_double.extend([612.0, 712.0])
+  message.packed_bool.extend([True, False])
+  message.packed_enum.extend([unittest_pb2.FOREIGN_BAR,
+                              unittest_pb2.FOREIGN_BAZ])
+
+
+def SetAllPackedExtensions(message):
+  """Sets every extension in the message to a unique value.
+
+  Args:
+    message: A unittest_pb2.TestPackedExtensions instance.
+  """
+  extensions = message.Extensions
+  pb2 = unittest_pb2
+
+  extensions[pb2.packed_int32_extension].extend([601, 701])
+  extensions[pb2.packed_int64_extension].extend([602, 702])
+  extensions[pb2.packed_uint32_extension].extend([603, 703])
+  extensions[pb2.packed_uint64_extension].extend([604, 704])
+  extensions[pb2.packed_sint32_extension].extend([605, 705])
+  extensions[pb2.packed_sint64_extension].extend([606, 706])
+  extensions[pb2.packed_fixed32_extension].extend([607, 707])
+  extensions[pb2.packed_fixed64_extension].extend([608, 708])
+  extensions[pb2.packed_sfixed32_extension].extend([609, 709])
+  extensions[pb2.packed_sfixed64_extension].extend([610, 710])
+  extensions[pb2.packed_float_extension].extend([611.0, 711.0])
+  extensions[pb2.packed_double_extension].extend([612.0, 712.0])
+  extensions[pb2.packed_bool_extension].extend([True, False])
+  extensions[pb2.packed_enum_extension].extend([unittest_pb2.FOREIGN_BAR,
+                                                unittest_pb2.FOREIGN_BAZ])
+
+
+def SetAllUnpackedFields(message):
+  """Sets every field in the message to a unique value.
+
+  Args:
+    message: A unittest_pb2.TestUnpackedTypes instance.
+  """
+  message.unpacked_int32.extend([601, 701])
+  message.unpacked_int64.extend([602, 702])
+  message.unpacked_uint32.extend([603, 703])
+  message.unpacked_uint64.extend([604, 704])
+  message.unpacked_sint32.extend([605, 705])
+  message.unpacked_sint64.extend([606, 706])
+  message.unpacked_fixed32.extend([607, 707])
+  message.unpacked_fixed64.extend([608, 708])
+  message.unpacked_sfixed32.extend([609, 709])
+  message.unpacked_sfixed64.extend([610, 710])
+  message.unpacked_float.extend([611.0, 711.0])
+  message.unpacked_double.extend([612.0, 712.0])
+  message.unpacked_bool.extend([True, False])
+  message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR,
+                                unittest_pb2.FOREIGN_BAZ])
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/text_encoding_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/text_encoding_test.py
new file mode 100755
index 0000000..c7d182c
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/text_encoding_test.py
@@ -0,0 +1,72 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Tests for google.protobuf.text_encoding."""
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import text_encoding
+
+TEST_VALUES = [
+    ("foo\\rbar\\nbaz\\t",
+     "foo\\rbar\\nbaz\\t",
+     b"foo\rbar\nbaz\t"),
+    ("\\'full of \\\"sound\\\" and \\\"fury\\\"\\'",
+     "\\'full of \\\"sound\\\" and \\\"fury\\\"\\'",
+     b"'full of \"sound\" and \"fury\"'"),
+    ("signi\\\\fying\\\\ nothing\\\\",
+     "signi\\\\fying\\\\ nothing\\\\",
+     b"signi\\fying\\ nothing\\"),
+    ("\\010\\t\\n\\013\\014\\r",
+     "\x08\\t\\n\x0b\x0c\\r",
+     b"\010\011\012\013\014\015")]
+
+
+class TextEncodingTestCase(unittest.TestCase):
+  def testCEscape(self):
+    for escaped, escaped_utf8, unescaped in TEST_VALUES:
+      self.assertEqual(escaped,
+                        text_encoding.CEscape(unescaped, as_utf8=False))
+      self.assertEqual(escaped_utf8,
+                        text_encoding.CEscape(unescaped, as_utf8=True))
+
+  def testCUnescape(self):
+    for escaped, escaped_utf8, unescaped in TEST_VALUES:
+      self.assertEqual(unescaped, text_encoding.CUnescape(escaped))
+      self.assertEqual(unescaped, text_encoding.CUnescape(escaped_utf8))
+
+
+if __name__ == "__main__":
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/text_format_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/text_format_test.py
new file mode 100755
index 0000000..ab2bf05
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/text_format_test.py
@@ -0,0 +1,1159 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Test for google.protobuf.text_format."""
+
+__author__ = 'kenton@google.com (Kenton Varda)'
+
+
+import re
+import six
+import string
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf.internal import _parameterized
+
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import test_util
+from google.protobuf.internal import message_set_extensions_pb2
+from google.protobuf import text_format
+
+
+# Low-level nuts-n-bolts tests.
+class SimpleTextFormatTests(unittest.TestCase):
+
+  # The members of _QUOTES are formatted into a regexp template that
+  # expects single characters.  Therefore it's an error (in addition to being
+  # non-sensical in the first place) to try to specify a "quote mark" that is
+  # more than one character.
+  def testQuoteMarksAreSingleChars(self):
+    for quote in text_format._QUOTES:
+      self.assertEqual(1, len(quote))
+
+
+# Base class with some common functionality.
+class TextFormatBase(unittest.TestCase):
+
+  def ReadGolden(self, golden_filename):
+    with test_util.GoldenFile(golden_filename) as f:
+      return (f.readlines() if str is bytes else  # PY3
+              [golden_line.decode('utf-8') for golden_line in f])
+
+  def CompareToGoldenFile(self, text, golden_filename):
+    golden_lines = self.ReadGolden(golden_filename)
+    self.assertMultiLineEqual(text, ''.join(golden_lines))
+
+  def CompareToGoldenText(self, text, golden_text):
+    self.assertEqual(text, golden_text)
+
+  def RemoveRedundantZeros(self, text):
+    # Some platforms print 1e+5 as 1e+005.  This is fine, but we need to remove
+    # these zeros in order to match the golden file.
+    text = text.replace('e+0','e+').replace('e+0','e+') \
+               .replace('e-0','e-').replace('e-0','e-')
+    # Floating point fields are printed with .0 suffix even if they are
+    # actualy integer numbers.
+    text = re.compile('\.0$', re.MULTILINE).sub('', text)
+    return text
+
+
+@_parameterized.Parameters(
+    (unittest_pb2),
+    (unittest_proto3_arena_pb2))
+class TextFormatTest(TextFormatBase):
+
+  def testPrintExotic(self, message_module):
+    message = message_module.TestAllTypes()
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_format.MessageToString(message)),
+        'repeated_int64: -9223372036854775808\n'
+        'repeated_uint64: 18446744073709551615\n'
+        'repeated_double: 123.456\n'
+        'repeated_double: 1.23e+22\n'
+        'repeated_double: 1.23e-18\n'
+        'repeated_string:'
+        ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
+        'repeated_string: "\\303\\274\\352\\234\\237"\n')
+
+  def testPrintExoticUnicodeSubclass(self, message_module):
+    class UnicodeSub(six.text_type):
+      pass
+    message = message_module.TestAllTypes()
+    message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f'))
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        'repeated_string: "\\303\\274\\352\\234\\237"\n')
+
+  def testPrintNestedMessageAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'repeated_nested_message { bb: 42 }')
+
+  def testPrintRepeatedFieldsAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(3)
+    message.repeated_string.append('Google')
+    message.repeated_string.append('Zurich')
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
+        'repeated_string: "Google" repeated_string: "Zurich"')
+
+  def testPrintNestedNewLineInStringAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    message.optional_string = 'a\nnew\nline'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'optional_string: "a\\nnew\\nline"')
+
+  def testPrintExoticAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(
+            text_format.MessageToString(message, as_one_line=True)),
+        'repeated_int64: -9223372036854775808'
+        ' repeated_uint64: 18446744073709551615'
+        ' repeated_double: 123.456'
+        ' repeated_double: 1.23e+22'
+        ' repeated_double: 1.23e-18'
+        ' repeated_string: '
+        '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
+        ' repeated_string: "\\303\\274\\352\\234\\237"')
+
+  def testRoundTripExoticAsOneLine(self, message_module):
+    message = message_module.TestAllTypes()
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
+
+    # Test as_utf8 = False.
+    wire_text = text_format.MessageToString(
+        message, as_one_line=True, as_utf8=False)
+    parsed_message = message_module.TestAllTypes()
+    r = text_format.Parse(wire_text, parsed_message)
+    self.assertIs(r, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+    # Test as_utf8 = True.
+    wire_text = text_format.MessageToString(
+        message, as_one_line=True, as_utf8=True)
+    parsed_message = message_module.TestAllTypes()
+    r = text_format.Parse(wire_text, parsed_message)
+    self.assertIs(r, parsed_message)
+    self.assertEqual(message, parsed_message,
+                      '\n%s != %s' % (message, parsed_message))
+
+  def testPrintRawUtf8String(self, message_module):
+    message = message_module.TestAllTypes()
+    message.repeated_string.append(u'\u00fc\ua71f')
+    text = text_format.MessageToString(message, as_utf8=True)
+    self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n')
+    parsed_message = message_module.TestAllTypes()
+    text_format.Parse(text, parsed_message)
+    self.assertEqual(message, parsed_message,
+                      '\n%s != %s' % (message, parsed_message))
+
+  def testPrintFloatFormat(self, message_module):
+    # Check that float_format argument is passed to sub-message formatting.
+    message = message_module.NestedTestAllTypes()
+    # We use 1.25 as it is a round number in binary.  The proto 32-bit float
+    # will not gain additional imprecise digits as a 64-bit Python float and
+    # show up in its str.  32-bit 1.2 is noisy when extended to 64-bit:
+    #  >>> struct.unpack('f', struct.pack('f', 1.2))[0]
+    #  1.2000000476837158
+    #  >>> struct.unpack('f', struct.pack('f', 1.25))[0]
+    #  1.25
+    message.payload.optional_float = 1.25
+    # Check rounding at 15 significant digits
+    message.payload.optional_double = -.000003456789012345678
+    # Check no decimal point.
+    message.payload.repeated_float.append(-5642)
+    # Check no trailing zeros.
+    message.payload.repeated_double.append(.000078900)
+    formatted_fields = ['optional_float: 1.25',
+                        'optional_double: -3.45678901234568e-6',
+                        'repeated_float: -5642',
+                        'repeated_double: 7.89e-5']
+    text_message = text_format.MessageToString(message, float_format='.15g')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_message),
+        'payload {{\n  {0}\n  {1}\n  {2}\n  {3}\n}}\n'.format(*formatted_fields))
+    # as_one_line=True is a separate code branch where float_format is passed.
+    text_message = text_format.MessageToString(message, as_one_line=True,
+                                               float_format='.15g')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_message),
+        'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields))
+
+  def testMessageToString(self, message_module):
+    message = message_module.ForeignMessage()
+    message.c = 123
+    self.assertEqual('c: 123\n', str(message))
+
+  def testPrintField(self, message_module):
+    message = message_module.TestAllTypes()
+    field = message.DESCRIPTOR.fields_by_name['optional_float']
+    value = message.optional_float
+    out = text_format.TextWriter(False)
+    text_format.PrintField(field, value, out)
+    self.assertEqual('optional_float: 0.0\n', out.getvalue())
+    out.close()
+    # Test Printer
+    out = text_format.TextWriter(False)
+    printer = text_format._Printer(out)
+    printer.PrintField(field, value)
+    self.assertEqual('optional_float: 0.0\n', out.getvalue())
+    out.close()
+
+  def testPrintFieldValue(self, message_module):
+    message = message_module.TestAllTypes()
+    field = message.DESCRIPTOR.fields_by_name['optional_float']
+    value = message.optional_float
+    out = text_format.TextWriter(False)
+    text_format.PrintFieldValue(field, value, out)
+    self.assertEqual('0.0', out.getvalue())
+    out.close()
+    # Test Printer
+    out = text_format.TextWriter(False)
+    printer = text_format._Printer(out)
+    printer.PrintFieldValue(field, value)
+    self.assertEqual('0.0', out.getvalue())
+    out.close()
+
+  def testParseAllFields(self, message_module):
+    message = message_module.TestAllTypes()
+    test_util.SetAllFields(message)
+    ascii_text = text_format.MessageToString(message)
+
+    parsed_message = message_module.TestAllTypes()
+    text_format.Parse(ascii_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+    if message_module is unittest_pb2:
+      test_util.ExpectAllFieldsSet(self, message)
+
+  def testParseExotic(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('repeated_int64: -9223372036854775808\n'
+            'repeated_uint64: 18446744073709551615\n'
+            'repeated_double: 123.456\n'
+            'repeated_double: 1.23e+22\n'
+            'repeated_double: 1.23e-18\n'
+            'repeated_string: \n'
+            '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
+            'repeated_string: "foo" \'corge\' "grault"\n'
+            'repeated_string: "\\303\\274\\352\\234\\237"\n'
+            'repeated_string: "\\xc3\\xbc"\n'
+            'repeated_string: "\xc3\xbc"\n')
+    text_format.Parse(text, message)
+
+    self.assertEqual(-9223372036854775808, message.repeated_int64[0])
+    self.assertEqual(18446744073709551615, message.repeated_uint64[0])
+    self.assertEqual(123.456, message.repeated_double[0])
+    self.assertEqual(1.23e22, message.repeated_double[1])
+    self.assertEqual(1.23e-18, message.repeated_double[2])
+    self.assertEqual(
+        '\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0])
+    self.assertEqual('foocorgegrault', message.repeated_string[1])
+    self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
+    self.assertEqual(u'\u00fc', message.repeated_string[3])
+
+  def testParseTrailingCommas(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('repeated_int64: 100;\n'
+            'repeated_int64: 200;\n'
+            'repeated_int64: 300,\n'
+            'repeated_string: "one",\n'
+            'repeated_string: "two";\n')
+    text_format.Parse(text, message)
+
+    self.assertEqual(100, message.repeated_int64[0])
+    self.assertEqual(200, message.repeated_int64[1])
+    self.assertEqual(300, message.repeated_int64[2])
+    self.assertEqual(u'one', message.repeated_string[0])
+    self.assertEqual(u'two', message.repeated_string[1])
+
+  def testParseRepeatedScalarShortFormat(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('repeated_int64: [100, 200];\n'
+            'repeated_int64: 300,\n'
+            'repeated_string: ["one", "two"];\n')
+    text_format.Parse(text, message)
+
+    self.assertEqual(100, message.repeated_int64[0])
+    self.assertEqual(200, message.repeated_int64[1])
+    self.assertEqual(300, message.repeated_int64[2])
+    self.assertEqual(u'one', message.repeated_string[0])
+    self.assertEqual(u'two', message.repeated_string[1])
+
+  def testParseRepeatedMessageShortFormat(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('repeated_nested_message: [{bb: 100}, {bb: 200}],\n'
+            'repeated_nested_message: {bb: 300}\n'
+            'repeated_nested_message [{bb: 400}];\n')
+    text_format.Parse(text, message)
+
+    self.assertEqual(100, message.repeated_nested_message[0].bb)
+    self.assertEqual(200, message.repeated_nested_message[1].bb)
+    self.assertEqual(300, message.repeated_nested_message[2].bb)
+    self.assertEqual(400, message.repeated_nested_message[3].bb)
+
+  def testParseEmptyText(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ''
+    text_format.Parse(text, message)
+    self.assertEqual(message_module.TestAllTypes(), message)
+
+  def testParseInvalidUtf8(self, message_module):
+    message = message_module.TestAllTypes()
+    text = 'repeated_string: "\\xc3\\xc3"'
+    self.assertRaises(text_format.ParseError, text_format.Parse, text, message)
+
+  def testParseSingleWord(self, message_module):
+    message = message_module.TestAllTypes()
+    text = 'foo'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"foo".'),
+        text_format.Parse, text, message)
+
+  def testParseUnknownField(self, message_module):
+    message = message_module.TestAllTypes()
+    text = 'unknown_field: 8\n'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"unknown_field".'),
+        text_format.Parse, text, message)
+
+  def testParseBadEnumValue(self, message_module):
+    message = message_module.TestAllTypes()
+    text = 'optional_nested_enum: BARR'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+         r'has no value named BARR.'),
+        text_format.Parse, text, message)
+
+    message = message_module.TestAllTypes()
+    text = 'optional_nested_enum: 100'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+         r'has no value with number 100.'),
+        text_format.Parse, text, message)
+
+  def testParseBadIntValue(self, message_module):
+    message = message_module.TestAllTypes()
+    text = 'optional_int32: bork'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        ('1:17 : Couldn\'t parse integer: bork'),
+        text_format.Parse, text, message)
+
+  def testParseStringFieldUnescape(self, message_module):
+    message = message_module.TestAllTypes()
+    text = r'''repeated_string: "\xf\x62"
+               repeated_string: "\\xf\\x62"
+               repeated_string: "\\\xf\\\x62"
+               repeated_string: "\\\\xf\\\\x62"
+               repeated_string: "\\\\\xf\\\\\x62"
+               repeated_string: "\x5cx20"'''
+    text_format.Parse(text, message)
+
+    SLASH = '\\'
+    self.assertEqual('\x0fb', message.repeated_string[0])
+    self.assertEqual(SLASH + 'xf' + SLASH + 'x62', message.repeated_string[1])
+    self.assertEqual(SLASH + '\x0f' + SLASH + 'b', message.repeated_string[2])
+    self.assertEqual(SLASH + SLASH + 'xf' + SLASH + SLASH + 'x62',
+                     message.repeated_string[3])
+    self.assertEqual(SLASH + SLASH + '\x0f' + SLASH + SLASH + 'b',
+                     message.repeated_string[4])
+    self.assertEqual(SLASH + 'x20', message.repeated_string[5])
+
+  def testMergeDuplicateScalars(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('optional_int32: 42 '
+            'optional_int32: 67')
+    r = text_format.Merge(text, message)
+    self.assertIs(r, message)
+    self.assertEqual(67, message.optional_int32)
+
+  def testMergeDuplicateNestedMessageScalars(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('optional_nested_message { bb: 1 } '
+            'optional_nested_message { bb: 2 }')
+    r = text_format.Merge(text, message)
+    self.assertTrue(r is message)
+    self.assertEqual(2, message.optional_nested_message.bb)
+
+  def testParseOneof(self, message_module):
+    m = message_module.TestAllTypes()
+    m.oneof_uint32 = 11
+    m2 = message_module.TestAllTypes()
+    text_format.Parse(text_format.MessageToString(m), m2)
+    self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+  def testParseMultipleOneof(self, message_module):
+    m_string = '\n'.join([
+        'oneof_uint32: 11',
+        'oneof_string: "foo"'])
+    m2 = message_module.TestAllTypes()
+    if message_module is unittest_pb2:
+      with self.assertRaisesRegexp(
+          text_format.ParseError, ' is specified along with field '):
+        text_format.Parse(m_string, m2)
+    else:
+      text_format.Parse(m_string, m2)
+      self.assertEqual('oneof_string', m2.WhichOneof('oneof_field'))
+
+
+# These are tests that aren't fundamentally specific to proto2, but are at
+# the moment because of differences between the proto2 and proto3 test schemas.
+# Ideally the schemas would be made more similar so these tests could pass.
+class OnlyWorksWithProto2RightNowTests(TextFormatBase):
+
+  def testPrintAllFieldsPointy(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(
+            text_format.MessageToString(message, pointy_brackets=True)),
+        'text_format_unittest_data_pointy_oneof.txt')
+
+  def testParseGolden(self):
+    golden_text = '\n'.join(self.ReadGolden(
+        'text_format_unittest_data_oneof_implemented.txt'))
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.Parse(golden_text, parsed_message)
+    self.assertIs(r, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEqual(message, parsed_message)
+
+  def testPrintAllFields(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(message)),
+        'text_format_unittest_data_oneof_implemented.txt')
+
+  def testPrintAllFieldsPointy(self):
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(
+            text_format.MessageToString(message, pointy_brackets=True)),
+        'text_format_unittest_data_pointy_oneof.txt')
+
+  def testPrintInIndexOrder(self):
+    message = unittest_pb2.TestFieldOrderings()
+    message.my_string = '115'
+    message.my_int = 101
+    message.my_float = 111
+    message.optional_nested_message.oo = 0
+    message.optional_nested_message.bb = 1
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message, use_index_order=True)),
+        'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
+        'optional_nested_message {\n  oo: 0\n  bb: 1\n}\n')
+    self.CompareToGoldenText(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message)),
+        'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
+        'optional_nested_message {\n  bb: 1\n  oo: 0\n}\n')
+
+  def testMergeLinesGolden(self):
+    opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt')
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.MergeLines(opened, parsed_message)
+    self.assertIs(r, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEqual(message, parsed_message)
+
+  def testParseLinesGolden(self):
+    opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt')
+    parsed_message = unittest_pb2.TestAllTypes()
+    r = text_format.ParseLines(opened, parsed_message)
+    self.assertIs(r, parsed_message)
+
+    message = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(message)
+    self.assertEqual(message, parsed_message)
+
+  def testPrintMap(self):
+    message = map_unittest_pb2.TestMap()
+
+    message.map_int32_int32[-123] = -456
+    message.map_int64_int64[-2**33] = -2**34
+    message.map_uint32_uint32[123] = 456
+    message.map_uint64_uint64[2**33] = 2**34
+    message.map_string_string["abc"] = "123"
+    message.map_int32_foreign_message[111].c = 5
+
+    # Maps are serialized to text format using their underlying repeated
+    # representation.
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        'map_int32_int32 {\n'
+        '  key: -123\n'
+        '  value: -456\n'
+        '}\n'
+        'map_int64_int64 {\n'
+        '  key: -8589934592\n'
+        '  value: -17179869184\n'
+        '}\n'
+        'map_uint32_uint32 {\n'
+        '  key: 123\n'
+        '  value: 456\n'
+        '}\n'
+        'map_uint64_uint64 {\n'
+        '  key: 8589934592\n'
+        '  value: 17179869184\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "123"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    c: 5\n'
+        '  }\n'
+        '}\n')
+
+  def testMapOrderEnforcement(self):
+    message = map_unittest_pb2.TestMap()
+    for letter in string.ascii_uppercase[13:26]:
+      message.map_string_string[letter] = 'dummy'
+    for letter in reversed(string.ascii_uppercase[0:13]):
+      message.map_string_string[letter] = 'dummy'
+    golden = ''.join((
+        'map_string_string {\n  key: "%c"\n  value: "dummy"\n}\n' % (letter,)
+        for letter in string.ascii_uppercase))
+    self.CompareToGoldenText(text_format.MessageToString(message), golden)
+
+  def testMapOrderSemantics(self):
+    golden_lines = self.ReadGolden('map_test_data.txt')
+    # The C++ implementation emits defaulted-value fields, while the Python
+    # implementation does not.  Adjusting for this is awkward, but it is
+    # valuable to test against a common golden file.
+    line_blacklist = ('  key: 0\n',
+                      '  value: 0\n',
+                      '  key: false\n',
+                      '  value: false\n')
+    golden_lines = [line for line in golden_lines if line not in line_blacklist]
+
+    message = map_unittest_pb2.TestMap()
+    text_format.ParseLines(golden_lines, message)
+    candidate = text_format.MessageToString(message)
+    # The Python implementation emits "1.0" for the double value that the C++
+    # implementation emits as "1".
+    candidate = candidate.replace('1.0', '1', 2)
+    self.assertMultiLineEqual(candidate, ''.join(golden_lines))
+
+
+# Tests of proto2-only features (MessageSet, extensions, etc.).
+class Proto2Tests(TextFormatBase):
+
+  def testPrintMessageSet(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        'message_set {\n'
+        '  [protobuf_unittest.TestMessageSetExtension1] {\n'
+        '    i: 23\n'
+        '  }\n'
+        '  [protobuf_unittest.TestMessageSetExtension2] {\n'
+        '    str: \"foo\"\n'
+        '  }\n'
+        '}\n')
+
+    message = message_set_extensions_pb2.TestMessageSet()
+    ext = message_set_extensions_pb2.message_set_extension3
+    message.Extensions[ext].text = 'bar'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        '[google.protobuf.internal.TestMessageSetExtension3] {\n'
+        '  text: \"bar\"\n'
+        '}\n')
+
+  def testPrintMessageSetByFieldNumber(self):
+    out = text_format.TextWriter(False)
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    text_format.PrintMessage(message, out, use_field_number=True)
+    self.CompareToGoldenText(
+        out.getvalue(),
+        '1 {\n'
+        '  1545008 {\n'
+        '    15: 23\n'
+        '  }\n'
+        '  1547769 {\n'
+        '    25: \"foo\"\n'
+        '  }\n'
+        '}\n')
+    out.close()
+
+  def testPrintMessageSetAsOneLine(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'message_set {'
+        ' [protobuf_unittest.TestMessageSetExtension1] {'
+        ' i: 23'
+        ' }'
+        ' [protobuf_unittest.TestMessageSetExtension2] {'
+        ' str: \"foo\"'
+        ' }'
+        ' }')
+
+  def testParseMessageSet(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('repeated_uint64: 1\n'
+            'repeated_uint64: 2\n')
+    text_format.Parse(text, message)
+    self.assertEqual(1, message.repeated_uint64[0])
+    self.assertEqual(2, message.repeated_uint64[1])
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('message_set {\n'
+            '  [protobuf_unittest.TestMessageSetExtension1] {\n'
+            '    i: 23\n'
+            '  }\n'
+            '  [protobuf_unittest.TestMessageSetExtension2] {\n'
+            '    str: \"foo\"\n'
+            '  }\n'
+            '}\n')
+    text_format.Parse(text, message)
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    self.assertEqual(23, message.message_set.Extensions[ext1].i)
+    self.assertEqual('foo', message.message_set.Extensions[ext2].str)
+
+  def testParseMessageByFieldNumber(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('34: 1\n'
+            'repeated_uint64: 2\n')
+    text_format.Parse(text, message, allow_field_number=True)
+    self.assertEqual(1, message.repeated_uint64[0])
+    self.assertEqual(2, message.repeated_uint64[1])
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('1 {\n'
+            '  1545008 {\n'
+            '    15: 23\n'
+            '  }\n'
+            '  1547769 {\n'
+            '    25: \"foo\"\n'
+            '  }\n'
+            '}\n')
+    text_format.Parse(text, message, allow_field_number=True)
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    self.assertEqual(23, message.message_set.Extensions[ext1].i)
+    self.assertEqual('foo', message.message_set.Extensions[ext2].str)
+
+    # Can't parse field number without set allow_field_number=True.
+    message = unittest_pb2.TestAllTypes()
+    text = '34:1\n'
+    six.assertRaisesRegex(
+        self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"34".'),
+        text_format.Parse, text, message)
+
+    # Can't parse if field number is not found.
+    text = '1234:1\n'
+    six.assertRaisesRegex(
+        self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"1234".'),
+        text_format.Parse, text, message, allow_field_number=True)
+
+  def testPrintAllExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(message)),
+        'text_format_unittest_extensions_data.txt')
+
+  def testPrintAllExtensionsPointy(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.CompareToGoldenFile(
+        self.RemoveRedundantZeros(text_format.MessageToString(
+            message, pointy_brackets=True)),
+        'text_format_unittest_extensions_data_pointy.txt')
+
+  def testParseGoldenExtensions(self):
+    golden_text = '\n'.join(self.ReadGolden(
+        'text_format_unittest_extensions_data.txt'))
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Parse(golden_text, parsed_message)
+
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    self.assertEqual(message, parsed_message)
+
+  def testParseAllExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    test_util.SetAllExtensions(message)
+    ascii_text = text_format.MessageToString(message)
+
+    parsed_message = unittest_pb2.TestAllExtensions()
+    text_format.Parse(ascii_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testParseAllowedUnknownExtension(self):
+    # Skip over unknown extension correctly.
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('message_set {\n'
+            '  [unknown_extension] {\n'
+            '    i: 23\n'
+            '    bin: "\xe0"'
+            '    [nested_unknown_ext]: {\n'
+            '      i: 23\n'
+            '      test: "test_string"\n'
+            '      floaty_float: -0.315\n'
+            '      num: -inf\n'
+            '      multiline_str: "abc"\n'
+            '          "def"\n'
+            '          "xyz."\n'
+            '      [nested_unknown_ext]: <\n'
+            '        i: 23\n'
+            '        i: 24\n'
+            '        pointfloat: .3\n'
+            '        test: "test_string"\n'
+            '        floaty_float: -0.315\n'
+            '        num: -inf\n'
+            '        long_string: "test" "test2" \n'
+            '      >\n'
+            '    }\n'
+            '  }\n'
+            '  [unknown_extension]: 5\n'
+            '}\n')
+    text_format.Parse(text, message, allow_unknown_extension=True)
+    golden = 'message_set {\n}\n'
+    self.CompareToGoldenText(text_format.MessageToString(message), golden)
+
+    # Catch parse errors in unknown extension.
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    malformed = ('message_set {\n'
+                 '  [unknown_extension] {\n'
+                 '    i:\n'  # Missing value.
+                 '  }\n'
+                 '}\n')
+    six.assertRaisesRegex(self,
+                          text_format.ParseError,
+                          'Invalid field value: }',
+                          text_format.Parse, malformed, message,
+                          allow_unknown_extension=True)
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    malformed = ('message_set {\n'
+                 '  [unknown_extension] {\n'
+                 '    str: "malformed string\n'  # Missing closing quote.
+                 '  }\n'
+                 '}\n')
+    six.assertRaisesRegex(self,
+                          text_format.ParseError,
+                          'Invalid field value: "',
+                          text_format.Parse, malformed, message,
+                          allow_unknown_extension=True)
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    malformed = ('message_set {\n'
+                 '  [unknown_extension] {\n'
+                 '    str: "malformed\n multiline\n string\n'
+                 '  }\n'
+                 '}\n')
+    six.assertRaisesRegex(self,
+                          text_format.ParseError,
+                          'Invalid field value: "',
+                          text_format.Parse, malformed, message,
+                          allow_unknown_extension=True)
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    malformed = ('message_set {\n'
+                 '  [malformed_extension] <\n'
+                 '    i: -5\n'
+                 '  \n'  # Missing '>' here.
+                 '}\n')
+    six.assertRaisesRegex(self,
+                          text_format.ParseError,
+                          '5:1 : Expected ">".',
+                          text_format.Parse, malformed, message,
+                          allow_unknown_extension=True)
+
+    # Don't allow unknown fields with allow_unknown_extension=True.
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    malformed = ('message_set {\n'
+                 '  unknown_field: true\n'
+                 '  \n'  # Missing '>' here.
+                 '}\n')
+    six.assertRaisesRegex(self,
+                          text_format.ParseError,
+                          ('2:3 : Message type '
+                           '"proto2_wireformat_unittest.TestMessageSet" has no'
+                           ' field named "unknown_field".'),
+                          text_format.Parse, malformed, message,
+                          allow_unknown_extension=True)
+
+    # Parse known extension correcty.
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('message_set {\n'
+            '  [protobuf_unittest.TestMessageSetExtension1] {\n'
+            '    i: 23\n'
+            '  }\n'
+            '  [protobuf_unittest.TestMessageSetExtension2] {\n'
+            '    str: \"foo\"\n'
+            '  }\n'
+            '}\n')
+    text_format.Parse(text, message, allow_unknown_extension=True)
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    self.assertEqual(23, message.message_set.Extensions[ext1].i)
+    self.assertEqual('foo', message.message_set.Extensions[ext2].str)
+
+  def testParseBadExtension(self):
+    message = unittest_pb2.TestAllExtensions()
+    text = '[unknown_extension]: 8\n'
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        '1:2 : Extension "unknown_extension" not registered.',
+        text_format.Parse, text, message)
+    message = unittest_pb2.TestAllTypes()
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
+         'extensions.'),
+        text_format.Parse, text, message)
+
+  def testMergeDuplicateExtensionScalars(self):
+    message = unittest_pb2.TestAllExtensions()
+    text = ('[protobuf_unittest.optional_int32_extension]: 42 '
+            '[protobuf_unittest.optional_int32_extension]: 67')
+    text_format.Merge(text, message)
+    self.assertEqual(
+        67,
+        message.Extensions[unittest_pb2.optional_int32_extension])
+
+  def testParseDuplicateExtensionScalars(self):
+    message = unittest_pb2.TestAllExtensions()
+    text = ('[protobuf_unittest.optional_int32_extension]: 42 '
+            '[protobuf_unittest.optional_int32_extension]: 67')
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        ('1:96 : Message type "protobuf_unittest.TestAllExtensions" '
+         'should not have multiple '
+         '"protobuf_unittest.optional_int32_extension" extensions.'),
+        text_format.Parse, text, message)
+
+  def testParseDuplicateNestedMessageScalars(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('optional_nested_message { bb: 1 } '
+            'optional_nested_message { bb: 2 }')
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
+         'should not have multiple "bb" fields.'),
+        text_format.Parse, text, message)
+
+  def testParseDuplicateScalars(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('optional_int32: 42 '
+            'optional_int32: 67')
+    six.assertRaisesRegex(self,
+        text_format.ParseError,
+        ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
+         'have multiple "optional_int32" fields.'),
+        text_format.Parse, text, message)
+
+  def testParseGroupNotClosed(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'RepeatedGroup: <'
+    six.assertRaisesRegex(self,
+        text_format.ParseError, '1:16 : Expected ">".',
+        text_format.Parse, text, message)
+    text = 'RepeatedGroup: {'
+    six.assertRaisesRegex(self,
+        text_format.ParseError, '1:16 : Expected "}".',
+        text_format.Parse, text, message)
+
+  def testParseEmptyGroup(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'OptionalGroup: {}'
+    text_format.Parse(text, message)
+    self.assertTrue(message.HasField('optionalgroup'))
+
+    message.Clear()
+
+    message = unittest_pb2.TestAllTypes()
+    text = 'OptionalGroup: <>'
+    text_format.Parse(text, message)
+    self.assertTrue(message.HasField('optionalgroup'))
+
+  # Maps aren't really proto2-only, but our test schema only has maps for
+  # proto2.
+  def testParseMap(self):
+    text = ('map_int32_int32 {\n'
+            '  key: -123\n'
+            '  value: -456\n'
+            '}\n'
+            'map_int64_int64 {\n'
+            '  key: -8589934592\n'
+            '  value: -17179869184\n'
+            '}\n'
+            'map_uint32_uint32 {\n'
+            '  key: 123\n'
+            '  value: 456\n'
+            '}\n'
+            'map_uint64_uint64 {\n'
+            '  key: 8589934592\n'
+            '  value: 17179869184\n'
+            '}\n'
+            'map_string_string {\n'
+            '  key: "abc"\n'
+            '  value: "123"\n'
+            '}\n'
+            'map_int32_foreign_message {\n'
+            '  key: 111\n'
+            '  value {\n'
+            '    c: 5\n'
+            '  }\n'
+            '}\n')
+    message = map_unittest_pb2.TestMap()
+    text_format.Parse(text, message)
+
+    self.assertEqual(-456, message.map_int32_int32[-123])
+    self.assertEqual(-2**34, message.map_int64_int64[-2**33])
+    self.assertEqual(456, message.map_uint32_uint32[123])
+    self.assertEqual(2**34, message.map_uint64_uint64[2**33])
+    self.assertEqual("123", message.map_string_string["abc"])
+    self.assertEqual(5, message.map_int32_foreign_message[111].c)
+
+
+class TokenizerTest(unittest.TestCase):
+
+  def testSimpleTokenCases(self):
+    text = ('identifier1:"string1"\n     \n\n'
+            'identifier2 : \n \n123  \n  identifier3 :\'string\'\n'
+            'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
+            'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
+            'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
+            'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f '
+            'false_bool:  0 true_BOOL:t \n true_bool1:  1 false_BOOL1:f ')
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
+               ':',
+               (tokenizer.ConsumeString, 'string1'),
+               (tokenizer.ConsumeIdentifier, 'identifier2'),
+               ':',
+               (tokenizer.ConsumeInt32, 123),
+               (tokenizer.ConsumeIdentifier, 'identifier3'),
+               ':',
+               (tokenizer.ConsumeString, 'string'),
+               (tokenizer.ConsumeIdentifier, 'identifiER_4'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.1e+2),
+               (tokenizer.ConsumeIdentifier, 'ID5'),
+               ':',
+               (tokenizer.ConsumeFloat, -0.23),
+               (tokenizer.ConsumeIdentifier, 'ID6'),
+               ':',
+               (tokenizer.ConsumeString, 'aaaa\'bbbb'),
+               (tokenizer.ConsumeIdentifier, 'ID7'),
+               ':',
+               (tokenizer.ConsumeString, 'aa\"bb'),
+               (tokenizer.ConsumeIdentifier, 'ID8'),
+               ':',
+               '{',
+               (tokenizer.ConsumeIdentifier, 'A'),
+               ':',
+               (tokenizer.ConsumeFloat, float('inf')),
+               (tokenizer.ConsumeIdentifier, 'B'),
+               ':',
+               (tokenizer.ConsumeFloat, -float('inf')),
+               (tokenizer.ConsumeIdentifier, 'C'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'D'),
+               ':',
+               (tokenizer.ConsumeBool, False),
+               '}',
+               (tokenizer.ConsumeIdentifier, 'ID9'),
+               ':',
+               (tokenizer.ConsumeUint32, 22),
+               (tokenizer.ConsumeIdentifier, 'ID10'),
+               ':',
+               (tokenizer.ConsumeInt64, -111111111111111111),
+               (tokenizer.ConsumeIdentifier, 'ID11'),
+               ':',
+               (tokenizer.ConsumeInt32, -22),
+               (tokenizer.ConsumeIdentifier, 'ID12'),
+               ':',
+               (tokenizer.ConsumeUint64, 2222222222222222222),
+               (tokenizer.ConsumeIdentifier, 'ID13'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.23456),
+               (tokenizer.ConsumeIdentifier, 'ID14'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.2e+2),
+               (tokenizer.ConsumeIdentifier, 'false_bool'),
+               ':',
+               (tokenizer.ConsumeBool, False),
+               (tokenizer.ConsumeIdentifier, 'true_BOOL'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'true_bool1'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'false_BOOL1'),
+               ':',
+               (tokenizer.ConsumeBool, False)]
+
+    i = 0
+    while not tokenizer.AtEnd():
+      m = methods[i]
+      if type(m) == str:
+        token = tokenizer.token
+        self.assertEqual(token, m)
+        tokenizer.NextToken()
+      else:
+        self.assertEqual(m[1], m[0]())
+      i += 1
+
+  def testConsumeIntegers(self):
+    # This test only tests the failures in the integer parsing methods as well
+    # as the '0' special cases.
+    int64_max = (1 << 63) - 1
+    uint32_max = (1 << 32) - 1
+    text = '-1 %d %d' % (uint32_max + 1, int64_max + 1)
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64)
+    self.assertEqual(-1, tokenizer.ConsumeInt32())
+
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32)
+    self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64())
+
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64)
+    self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64())
+    self.assertTrue(tokenizer.AtEnd())
+
+    text = '-0 -0 0 0'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertEqual(0, tokenizer.ConsumeUint32())
+    self.assertEqual(0, tokenizer.ConsumeUint64())
+    self.assertEqual(0, tokenizer.ConsumeUint32())
+    self.assertEqual(0, tokenizer.ConsumeUint64())
+    self.assertTrue(tokenizer.AtEnd())
+
+  def testConsumeByteString(self):
+    text = '"string1\''
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = 'string1"'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\xt"'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\"'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+    text = '\n"\\x"'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
+
+  def testConsumeBool(self):
+    text = 'not-a-bool'
+    tokenizer = text_format._Tokenizer(text.splitlines())
+    self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/type_checkers.py b/src/third_party/protobuf-3/python/google/protobuf/internal/type_checkers.py
new file mode 100755
index 0000000..1be3ad9
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/type_checkers.py
@@ -0,0 +1,352 @@
+# 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.
+
+"""Provides type checking routines.
+
+This module defines type checking utilities in the forms of dictionaries:
+
+VALUE_CHECKERS: A dictionary of field types and a value validation object.
+TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing
+  function.
+TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization
+  function.
+FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their
+  coresponding wire types.
+TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
+  function.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+import six
+
+if six.PY3:
+  long = int
+
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import decoder
+from google.protobuf.internal import encoder
+from google.protobuf.internal import wire_format
+from google.protobuf import descriptor
+
+_FieldDescriptor = descriptor.FieldDescriptor
+
+def SupportsOpenEnums(field_descriptor):
+  return field_descriptor.containing_type.syntax == "proto3"
+
+def GetTypeChecker(field):
+  """Returns a type checker for a message field of the specified types.
+
+  Args:
+    field: FieldDescriptor object for this field.
+
+  Returns:
+    An instance of TypeChecker which can be used to verify the types
+    of values assigned to a field of the specified type.
+  """
+  if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and
+      field.type == _FieldDescriptor.TYPE_STRING):
+    return UnicodeValueChecker()
+  if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
+    if SupportsOpenEnums(field):
+      # When open enums are supported, any int32 can be assigned.
+      return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32]
+    else:
+      return EnumValueChecker(field.enum_type)
+  return _VALUE_CHECKERS[field.cpp_type]
+
+
+# None of the typecheckers below make any attempt to guard against people
+# subclassing builtin types and doing weird things.  We're not trying to
+# protect against malicious clients here, just people accidentally shooting
+# themselves in the foot in obvious ways.
+
+class TypeChecker(object):
+
+  """Type checker used to catch type errors as early as possible
+  when the client is setting scalar fields in protocol messages.
+  """
+
+  def __init__(self, *acceptable_types):
+    self._acceptable_types = acceptable_types
+
+  def CheckValue(self, proposed_value):
+    """Type check the provided value and return it.
+
+    The returned value might have been normalized to another type.
+    """
+    if not isinstance(proposed_value, self._acceptable_types):
+      message = ('%.1024r has type %s, but expected one of: %s' %
+                 (proposed_value, type(proposed_value), self._acceptable_types))
+      raise TypeError(message)
+    return proposed_value
+
+
+class TypeCheckerWithDefault(TypeChecker):
+
+  def __init__(self, default_value, *acceptable_types):
+    TypeChecker.__init__(self, acceptable_types)
+    self._default_value = default_value
+
+  def DefaultValue(self):
+    return self._default_value
+
+
+# IntValueChecker and its subclasses perform integer type-checks
+# and bounds-checks.
+class IntValueChecker(object):
+
+  """Checker used for integer fields.  Performs type-check and range check."""
+
+  def CheckValue(self, proposed_value):
+    if not isinstance(proposed_value, six.integer_types):
+      message = ('%.1024r has type %s, but expected one of: %s' %
+                 (proposed_value, type(proposed_value), six.integer_types))
+      raise TypeError(message)
+    if not self._MIN <= proposed_value <= self._MAX:
+      raise ValueError('Value out of range: %d' % proposed_value)
+    # We force 32-bit values to int and 64-bit values to long to make
+    # alternate implementations where the distinction is more significant
+    # (e.g. the C++ implementation) simpler.
+    proposed_value = self._TYPE(proposed_value)
+    return proposed_value
+
+  def DefaultValue(self):
+    return 0
+
+
+class EnumValueChecker(object):
+
+  """Checker used for enum fields.  Performs type-check and range check."""
+
+  def __init__(self, enum_type):
+    self._enum_type = enum_type
+
+  def CheckValue(self, proposed_value):
+    if not isinstance(proposed_value, six.integer_types):
+      message = ('%.1024r has type %s, but expected one of: %s' %
+                 (proposed_value, type(proposed_value), six.integer_types))
+      raise TypeError(message)
+    if proposed_value not in self._enum_type.values_by_number:
+      raise ValueError('Unknown enum value: %d' % proposed_value)
+    return proposed_value
+
+  def DefaultValue(self):
+    return self._enum_type.values[0].number
+
+
+class UnicodeValueChecker(object):
+
+  """Checker used for string fields.
+
+  Always returns a unicode value, even if the input is of type str.
+  """
+
+  def CheckValue(self, proposed_value):
+    if not isinstance(proposed_value, (bytes, six.text_type)):
+      message = ('%.1024r has type %s, but expected one of: %s' %
+                 (proposed_value, type(proposed_value), (bytes, six.text_type)))
+      raise TypeError(message)
+
+    # If the value is of type 'bytes' make sure that it is valid UTF-8 data.
+    if isinstance(proposed_value, bytes):
+      try:
+        proposed_value = proposed_value.decode('utf-8')
+      except UnicodeDecodeError:
+        raise ValueError('%.1024r has type bytes, but isn\'t valid UTF-8 '
+                         'encoding. Non-UTF-8 strings must be converted to '
+                         'unicode objects before being added.' %
+                         (proposed_value))
+    return proposed_value
+
+  def DefaultValue(self):
+    return u""
+
+
+class Int32ValueChecker(IntValueChecker):
+  # We're sure to use ints instead of longs here since comparison may be more
+  # efficient.
+  _MIN = -2147483648
+  _MAX = 2147483647
+  _TYPE = int
+
+
+class Uint32ValueChecker(IntValueChecker):
+  _MIN = 0
+  _MAX = (1 << 32) - 1
+  _TYPE = int
+
+
+class Int64ValueChecker(IntValueChecker):
+  _MIN = -(1 << 63)
+  _MAX = (1 << 63) - 1
+  _TYPE = long
+
+
+class Uint64ValueChecker(IntValueChecker):
+  _MIN = 0
+  _MAX = (1 << 64) - 1
+  _TYPE = long
+
+
+# Type-checkers for all scalar CPPTYPEs.
+_VALUE_CHECKERS = {
+    _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(),
+    _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(),
+    _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(),
+    _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(),
+    _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault(
+        0.0, float, int, long),
+    _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault(
+        0.0, float, int, long),
+    _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault(
+        False, bool, int),
+    _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes),
+    }
+
+
+# Map from field type to a function F, such that F(field_num, value)
+# gives the total byte size for a value of the given type.  This
+# byte size includes tag information and any other additional space
+# associated with serializing "value".
+TYPE_TO_BYTE_SIZE_FN = {
+    _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize,
+    _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize,
+    _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize,
+    _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize,
+    _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize,
+    _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize,
+    _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize,
+    _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize,
+    _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize,
+    _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize,
+    _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize,
+    _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize,
+    _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize,
+    _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize,
+    _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize,
+    _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize,
+    _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize,
+    _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize
+    }
+
+
+# Maps from field types to encoder constructors.
+TYPE_TO_ENCODER = {
+    _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder,
+    _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder,
+    _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder,
+    _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder,
+    _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder,
+    _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder,
+    _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder,
+    _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder,
+    _FieldDescriptor.TYPE_STRING: encoder.StringEncoder,
+    _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder,
+    _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder,
+    _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder,
+    _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder,
+    _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder,
+    _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder,
+    _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder,
+    _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder,
+    _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder,
+    }
+
+
+# Maps from field types to sizer constructors.
+TYPE_TO_SIZER = {
+    _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer,
+    _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer,
+    _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer,
+    _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer,
+    _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer,
+    _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer,
+    _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer,
+    _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer,
+    _FieldDescriptor.TYPE_STRING: encoder.StringSizer,
+    _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer,
+    _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer,
+    _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer,
+    _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer,
+    _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer,
+    _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer,
+    _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer,
+    _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer,
+    _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer,
+    }
+
+
+# Maps from field type to a decoder constructor.
+TYPE_TO_DECODER = {
+    _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder,
+    _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder,
+    _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder,
+    _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder,
+    _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder,
+    _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder,
+    _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder,
+    _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder,
+    _FieldDescriptor.TYPE_STRING: decoder.StringDecoder,
+    _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder,
+    _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder,
+    _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder,
+    _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder,
+    _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder,
+    _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder,
+    _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder,
+    _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder,
+    _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder,
+    }
+
+# Maps from field type to expected wiretype.
+FIELD_TYPE_TO_WIRE_TYPE = {
+    _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64,
+    _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32,
+    _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64,
+    _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32,
+    _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_STRING:
+      wire_format.WIRETYPE_LENGTH_DELIMITED,
+    _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP,
+    _FieldDescriptor.TYPE_MESSAGE:
+      wire_format.WIRETYPE_LENGTH_DELIMITED,
+    _FieldDescriptor.TYPE_BYTES:
+      wire_format.WIRETYPE_LENGTH_DELIMITED,
+    _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32,
+    _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64,
+    _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT,
+    _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT,
+    }
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/unknown_fields_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/unknown_fields_test.py
new file mode 100755
index 0000000..84073f1
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/unknown_fields_test.py
@@ -0,0 +1,320 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# 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.
+
+"""Test for preservation of unknown fields in the pure Python implementation."""
+
+__author__ = 'bohdank@google.com (Bohdan Koval)'
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import encoder
+from google.protobuf.internal import message_set_extensions_pb2
+from google.protobuf.internal import missing_enum_values_pb2
+from google.protobuf.internal import test_util
+from google.protobuf.internal import type_checkers
+
+
+def SkipIfCppImplementation(func):
+  return unittest.skipIf(
+      api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+      'C++ implementation does not expose unknown fields to Python')(func)
+
+
+class UnknownFieldsTest(unittest.TestCase):
+
+  def setUp(self):
+    self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.all_fields = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(self.all_fields)
+    self.all_fields_data = self.all_fields.SerializeToString()
+    self.empty_message = unittest_pb2.TestEmptyMessage()
+    self.empty_message.ParseFromString(self.all_fields_data)
+
+  def testSerialize(self):
+    data = self.empty_message.SerializeToString()
+
+    # Don't use assertEqual because we don't want to dump raw binary data to
+    # stdout.
+    self.assertTrue(data == self.all_fields_data)
+
+  def testSerializeProto3(self):
+    # Verify that proto3 doesn't preserve unknown fields.
+    message = unittest_proto3_arena_pb2.TestEmptyMessage()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(0, len(message.SerializeToString()))
+
+  def testByteSize(self):
+    self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
+
+  def testListFields(self):
+    # Make sure ListFields doesn't return unknown fields.
+    self.assertEqual(0, len(self.empty_message.ListFields()))
+
+  def testSerializeMessageSetWireFormatUnknownExtension(self):
+    # Create a message using the message set wire format with an unknown
+    # message.
+    raw = unittest_mset_pb2.RawMessageSet()
+
+    # Add an unknown extension.
+    item = raw.item.add()
+    item.type_id = 98418603
+    message1 = message_set_extensions_pb2.TestMessageSetExtension1()
+    message1.i = 12345
+    item.message = message1.SerializeToString()
+
+    serialized = raw.SerializeToString()
+
+    # Parse message using the message set wire format.
+    proto = message_set_extensions_pb2.TestMessageSet()
+    proto.MergeFromString(serialized)
+
+    # Verify that the unknown extension is serialized unchanged
+    reserialized = proto.SerializeToString()
+    new_raw = unittest_mset_pb2.RawMessageSet()
+    new_raw.MergeFromString(reserialized)
+    self.assertEqual(raw, new_raw)
+
+  def testEquals(self):
+    message = unittest_pb2.TestEmptyMessage()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(self.empty_message, message)
+
+    self.all_fields.ClearField('optional_string')
+    message.ParseFromString(self.all_fields.SerializeToString())
+    self.assertNotEqual(self.empty_message, message)
+
+  def testDiscardUnknownFields(self):
+    self.empty_message.DiscardUnknownFields()
+    self.assertEqual(b'', self.empty_message.SerializeToString())
+    # Test message field and repeated message field.
+    message = unittest_pb2.TestAllTypes()
+    other_message = unittest_pb2.TestAllTypes()
+    other_message.optional_string = 'discard'
+    message.optional_nested_message.ParseFromString(
+        other_message.SerializeToString())
+    message.repeated_nested_message.add().ParseFromString(
+        other_message.SerializeToString())
+    self.assertNotEqual(
+        b'', message.optional_nested_message.SerializeToString())
+    self.assertNotEqual(
+        b'', message.repeated_nested_message[0].SerializeToString())
+    message.DiscardUnknownFields()
+    self.assertEqual(b'', message.optional_nested_message.SerializeToString())
+    self.assertEqual(
+        b'', message.repeated_nested_message[0].SerializeToString())
+
+
+class UnknownFieldsAccessorsTest(unittest.TestCase):
+
+  def setUp(self):
+    self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.all_fields = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(self.all_fields)
+    self.all_fields_data = self.all_fields.SerializeToString()
+    self.empty_message = unittest_pb2.TestEmptyMessage()
+    self.empty_message.ParseFromString(self.all_fields_data)
+    if api_implementation.Type() != 'cpp':
+      # _unknown_fields is an implementation detail.
+      self.unknown_fields = self.empty_message._unknown_fields
+
+  # All the tests that use GetField() check an implementation detail of the
+  # Python implementation, which stores unknown fields as serialized strings.
+  # These tests are skipped by the C++ implementation: it's enough to check that
+  # the message is correctly serialized.
+
+  def GetField(self, name):
+    field_descriptor = self.descriptor.fields_by_name[name]
+    wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type]
+    field_tag = encoder.TagBytes(field_descriptor.number, wire_type)
+    result_dict = {}
+    for tag_bytes, value in self.unknown_fields:
+      if tag_bytes == field_tag:
+        decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes][0]
+        decoder(value, 0, len(value), self.all_fields, result_dict)
+    return result_dict[field_descriptor]
+
+  @SkipIfCppImplementation
+  def testEnum(self):
+    value = self.GetField('optional_nested_enum')
+    self.assertEqual(self.all_fields.optional_nested_enum, value)
+
+  @SkipIfCppImplementation
+  def testRepeatedEnum(self):
+    value = self.GetField('repeated_nested_enum')
+    self.assertEqual(self.all_fields.repeated_nested_enum, value)
+
+  @SkipIfCppImplementation
+  def testVarint(self):
+    value = self.GetField('optional_int32')
+    self.assertEqual(self.all_fields.optional_int32, value)
+
+  @SkipIfCppImplementation
+  def testFixed32(self):
+    value = self.GetField('optional_fixed32')
+    self.assertEqual(self.all_fields.optional_fixed32, value)
+
+  @SkipIfCppImplementation
+  def testFixed64(self):
+    value = self.GetField('optional_fixed64')
+    self.assertEqual(self.all_fields.optional_fixed64, value)
+
+  @SkipIfCppImplementation
+  def testLengthDelimited(self):
+    value = self.GetField('optional_string')
+    self.assertEqual(self.all_fields.optional_string, value)
+
+  @SkipIfCppImplementation
+  def testGroup(self):
+    value = self.GetField('optionalgroup')
+    self.assertEqual(self.all_fields.optionalgroup, value)
+
+  def testCopyFrom(self):
+    message = unittest_pb2.TestEmptyMessage()
+    message.CopyFrom(self.empty_message)
+    self.assertEqual(message.SerializeToString(), self.all_fields_data)
+
+  def testMergeFrom(self):
+    message = unittest_pb2.TestAllTypes()
+    message.optional_int32 = 1
+    message.optional_uint32 = 2
+    source = unittest_pb2.TestEmptyMessage()
+    source.ParseFromString(message.SerializeToString())
+
+    message.ClearField('optional_int32')
+    message.optional_int64 = 3
+    message.optional_uint32 = 4
+    destination = unittest_pb2.TestEmptyMessage()
+    destination.ParseFromString(message.SerializeToString())
+
+    destination.MergeFrom(source)
+    # Check that the fields where correctly merged, even stored in the unknown
+    # fields set.
+    message.ParseFromString(destination.SerializeToString())
+    self.assertEqual(message.optional_int32, 1)
+    self.assertEqual(message.optional_uint32, 2)
+    self.assertEqual(message.optional_int64, 3)
+
+  def testClear(self):
+    self.empty_message.Clear()
+    # All cleared, even unknown fields.
+    self.assertEqual(self.empty_message.SerializeToString(), b'')
+
+  def testUnknownExtensions(self):
+    message = unittest_pb2.TestEmptyMessageWithExtensions()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(message.SerializeToString(), self.all_fields_data)
+
+
+class UnknownEnumValuesTest(unittest.TestCase):
+
+  def setUp(self):
+    self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR
+
+    self.message = missing_enum_values_pb2.TestEnumValues()
+    self.message.optional_nested_enum = (
+      missing_enum_values_pb2.TestEnumValues.ZERO)
+    self.message.repeated_nested_enum.extend([
+      missing_enum_values_pb2.TestEnumValues.ZERO,
+      missing_enum_values_pb2.TestEnumValues.ONE,
+      ])
+    self.message.packed_nested_enum.extend([
+      missing_enum_values_pb2.TestEnumValues.ZERO,
+      missing_enum_values_pb2.TestEnumValues.ONE,
+      ])
+    self.message_data = self.message.SerializeToString()
+    self.missing_message = missing_enum_values_pb2.TestMissingEnumValues()
+    self.missing_message.ParseFromString(self.message_data)
+    if api_implementation.Type() != 'cpp':
+      # _unknown_fields is an implementation detail.
+      self.unknown_fields = self.missing_message._unknown_fields
+
+  # All the tests that use GetField() check an implementation detail of the
+  # Python implementation, which stores unknown fields as serialized strings.
+  # These tests are skipped by the C++ implementation: it's enough to check that
+  # the message is correctly serialized.
+
+  def GetField(self, name):
+    field_descriptor = self.descriptor.fields_by_name[name]
+    wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type]
+    field_tag = encoder.TagBytes(field_descriptor.number, wire_type)
+    result_dict = {}
+    for tag_bytes, value in self.unknown_fields:
+      if tag_bytes == field_tag:
+        decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[
+          tag_bytes][0]
+        decoder(value, 0, len(value), self.message, result_dict)
+    return result_dict[field_descriptor]
+
+  def testUnknownParseMismatchEnumValue(self):
+    just_string = missing_enum_values_pb2.JustString()
+    just_string.dummy = 'blah'
+
+    missing = missing_enum_values_pb2.TestEnumValues()
+    # The parse is invalid, storing the string proto into the set of
+    # unknown fields.
+    missing.ParseFromString(just_string.SerializeToString())
+
+    # Fetching the enum field shouldn't crash, instead returning the
+    # default value.
+    self.assertEqual(missing.optional_nested_enum, 0)
+
+  @SkipIfCppImplementation
+  def testUnknownEnumValue(self):
+    self.assertFalse(self.missing_message.HasField('optional_nested_enum'))
+    value = self.GetField('optional_nested_enum')
+    self.assertEqual(self.message.optional_nested_enum, value)
+
+  @SkipIfCppImplementation
+  def testUnknownRepeatedEnumValue(self):
+    value = self.GetField('repeated_nested_enum')
+    self.assertEqual(self.message.repeated_nested_enum, value)
+
+  @SkipIfCppImplementation
+  def testUnknownPackedEnumValue(self):
+    value = self.GetField('packed_nested_enum')
+    self.assertEqual(self.message.packed_nested_enum, value)
+
+  def testRoundTrip(self):
+    new_message = missing_enum_values_pb2.TestEnumValues()
+    new_message.ParseFromString(self.missing_message.SerializeToString())
+    self.assertEqual(self.message, new_message)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types.py b/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types.py
new file mode 100644
index 0000000..7c5dffd
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types.py
@@ -0,0 +1,724 @@
+# 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.
+
+"""Contains well known classes.
+
+This files defines well known classes which need extra maintenance including:
+  - Any
+  - Duration
+  - FieldMask
+  - Struct
+  - Timestamp
+"""
+
+__author__ = 'jieluo@google.com (Jie Luo)'
+
+from datetime import datetime
+from datetime import timedelta
+import six
+
+from google.protobuf.descriptor import FieldDescriptor
+
+_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
+_NANOS_PER_SECOND = 1000000000
+_NANOS_PER_MILLISECOND = 1000000
+_NANOS_PER_MICROSECOND = 1000
+_MILLIS_PER_SECOND = 1000
+_MICROS_PER_SECOND = 1000000
+_SECONDS_PER_DAY = 24 * 3600
+
+
+class Error(Exception):
+  """Top-level module error."""
+
+
+class ParseError(Error):
+  """Thrown in case of parsing error."""
+
+
+class Any(object):
+  """Class for Any Message type."""
+
+  def Pack(self, msg, type_url_prefix='type.googleapis.com/'):
+    """Packs the specified message into current Any message."""
+    if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/':
+      self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
+    else:
+      self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
+    self.value = msg.SerializeToString()
+
+  def Unpack(self, msg):
+    """Unpacks the current Any message into specified message."""
+    descriptor = msg.DESCRIPTOR
+    if not self.Is(descriptor):
+      return False
+    msg.ParseFromString(self.value)
+    return True
+
+  def TypeName(self):
+    """Returns the protobuf type name of the inner message."""
+    # Only last part is to be used: b/25630112
+    return self.type_url.split('/')[-1]
+
+  def Is(self, descriptor):
+    """Checks if this Any represents the given protobuf type."""
+    return self.TypeName() == descriptor.full_name
+
+
+class Timestamp(object):
+  """Class for Timestamp message type."""
+
+  def ToJsonString(self):
+    """Converts Timestamp to RFC 3339 date string format.
+
+    Returns:
+      A string converted from timestamp. The string is always Z-normalized
+      and uses 3, 6 or 9 fractional digits as required to represent the
+      exact time. Example of the return format: '1972-01-01T10:00:20.021Z'
+    """
+    nanos = self.nanos % _NANOS_PER_SECOND
+    total_sec = self.seconds + (self.nanos - nanos) // _NANOS_PER_SECOND
+    seconds = total_sec % _SECONDS_PER_DAY
+    days = (total_sec - seconds) // _SECONDS_PER_DAY
+    dt = datetime(1970, 1, 1) + timedelta(days, seconds)
+
+    result = dt.isoformat()
+    if (nanos % 1e9) == 0:
+      # If there are 0 fractional digits, the fractional
+      # point '.' should be omitted when serializing.
+      return result + 'Z'
+    if (nanos % 1e6) == 0:
+      # Serialize 3 fractional digits.
+      return result + '.%03dZ' % (nanos / 1e6)
+    if (nanos % 1e3) == 0:
+      # Serialize 6 fractional digits.
+      return result + '.%06dZ' % (nanos / 1e3)
+    # Serialize 9 fractional digits.
+    return result + '.%09dZ' % nanos
+
+  def FromJsonString(self, value):
+    """Parse a RFC 3339 date string format to Timestamp.
+
+    Args:
+      value: A date string. Any fractional digits (or none) and any offset are
+          accepted as long as they fit into nano-seconds precision.
+          Example of accepted format: '1972-01-01T10:00:20.021-05:00'
+
+    Raises:
+      ParseError: On parsing problems.
+    """
+    timezone_offset = value.find('Z')
+    if timezone_offset == -1:
+      timezone_offset = value.find('+')
+    if timezone_offset == -1:
+      timezone_offset = value.rfind('-')
+    if timezone_offset == -1:
+      raise ParseError(
+          'Failed to parse timestamp: missing valid timezone offset.')
+    time_value = value[0:timezone_offset]
+    # Parse datetime and nanos.
+    point_position = time_value.find('.')
+    if point_position == -1:
+      second_value = time_value
+      nano_value = ''
+    else:
+      second_value = time_value[:point_position]
+      nano_value = time_value[point_position + 1:]
+    date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT)
+    td = date_object - datetime(1970, 1, 1)
+    seconds = td.seconds + td.days * _SECONDS_PER_DAY
+    if len(nano_value) > 9:
+      raise ParseError(
+          'Failed to parse Timestamp: nanos {0} more than '
+          '9 fractional digits.'.format(nano_value))
+    if nano_value:
+      nanos = round(float('0.' + nano_value) * 1e9)
+    else:
+      nanos = 0
+    # Parse timezone offsets.
+    if value[timezone_offset] == 'Z':
+      if len(value) != timezone_offset + 1:
+        raise ParseError('Failed to parse timestamp: invalid trailing'
+                         ' data {0}.'.format(value))
+    else:
+      timezone = value[timezone_offset:]
+      pos = timezone.find(':')
+      if pos == -1:
+        raise ParseError(
+            'Invalid timezone offset value: {0}.'.format(timezone))
+      if timezone[0] == '+':
+        seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
+      else:
+        seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
+    # Set seconds and nanos
+    self.seconds = int(seconds)
+    self.nanos = int(nanos)
+
+  def GetCurrentTime(self):
+    """Get the current UTC into Timestamp."""
+    self.FromDatetime(datetime.utcnow())
+
+  def ToNanoseconds(self):
+    """Converts Timestamp to nanoseconds since epoch."""
+    return self.seconds * _NANOS_PER_SECOND + self.nanos
+
+  def ToMicroseconds(self):
+    """Converts Timestamp to microseconds since epoch."""
+    return (self.seconds * _MICROS_PER_SECOND +
+            self.nanos // _NANOS_PER_MICROSECOND)
+
+  def ToMilliseconds(self):
+    """Converts Timestamp to milliseconds since epoch."""
+    return (self.seconds * _MILLIS_PER_SECOND +
+            self.nanos // _NANOS_PER_MILLISECOND)
+
+  def ToSeconds(self):
+    """Converts Timestamp to seconds since epoch."""
+    return self.seconds
+
+  def FromNanoseconds(self, nanos):
+    """Converts nanoseconds since epoch to Timestamp."""
+    self.seconds = nanos // _NANOS_PER_SECOND
+    self.nanos = nanos % _NANOS_PER_SECOND
+
+  def FromMicroseconds(self, micros):
+    """Converts microseconds since epoch to Timestamp."""
+    self.seconds = micros // _MICROS_PER_SECOND
+    self.nanos = (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND
+
+  def FromMilliseconds(self, millis):
+    """Converts milliseconds since epoch to Timestamp."""
+    self.seconds = millis // _MILLIS_PER_SECOND
+    self.nanos = (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND
+
+  def FromSeconds(self, seconds):
+    """Converts seconds since epoch to Timestamp."""
+    self.seconds = seconds
+    self.nanos = 0
+
+  def ToDatetime(self):
+    """Converts Timestamp to datetime."""
+    return datetime.utcfromtimestamp(
+        self.seconds + self.nanos / float(_NANOS_PER_SECOND))
+
+  def FromDatetime(self, dt):
+    """Converts datetime to Timestamp."""
+    td = dt - datetime(1970, 1, 1)
+    self.seconds = td.seconds + td.days * _SECONDS_PER_DAY
+    self.nanos = td.microseconds * _NANOS_PER_MICROSECOND
+
+
+class Duration(object):
+  """Class for Duration message type."""
+
+  def ToJsonString(self):
+    """Converts Duration to string format.
+
+    Returns:
+      A string converted from self. The string format will contains
+      3, 6, or 9 fractional digits depending on the precision required to
+      represent the exact Duration value. For example: "1s", "1.010s",
+      "1.000000100s", "-3.100s"
+    """
+    if self.seconds < 0 or self.nanos < 0:
+      result = '-'
+      seconds = - self.seconds + int((0 - self.nanos) // 1e9)
+      nanos = (0 - self.nanos) % 1e9
+    else:
+      result = ''
+      seconds = self.seconds + int(self.nanos // 1e9)
+      nanos = self.nanos % 1e9
+    result += '%d' % seconds
+    if (nanos % 1e9) == 0:
+      # If there are 0 fractional digits, the fractional
+      # point '.' should be omitted when serializing.
+      return result + 's'
+    if (nanos % 1e6) == 0:
+      # Serialize 3 fractional digits.
+      return result + '.%03ds' % (nanos / 1e6)
+    if (nanos % 1e3) == 0:
+      # Serialize 6 fractional digits.
+      return result + '.%06ds' % (nanos / 1e3)
+    # Serialize 9 fractional digits.
+    return result + '.%09ds' % nanos
+
+  def FromJsonString(self, value):
+    """Converts a string to Duration.
+
+    Args:
+      value: A string to be converted. The string must end with 's'. Any
+          fractional digits (or none) are accepted as long as they fit into
+          precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s
+
+    Raises:
+      ParseError: On parsing problems.
+    """
+    if len(value) < 1 or value[-1] != 's':
+      raise ParseError(
+          'Duration must end with letter "s": {0}.'.format(value))
+    try:
+      pos = value.find('.')
+      if pos == -1:
+        self.seconds = int(value[:-1])
+        self.nanos = 0
+      else:
+        self.seconds = int(value[:pos])
+        if value[0] == '-':
+          self.nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9))
+        else:
+          self.nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9))
+    except ValueError:
+      raise ParseError(
+          'Couldn\'t parse duration: {0}.'.format(value))
+
+  def ToNanoseconds(self):
+    """Converts a Duration to nanoseconds."""
+    return self.seconds * _NANOS_PER_SECOND + self.nanos
+
+  def ToMicroseconds(self):
+    """Converts a Duration to microseconds."""
+    micros = _RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND)
+    return self.seconds * _MICROS_PER_SECOND + micros
+
+  def ToMilliseconds(self):
+    """Converts a Duration to milliseconds."""
+    millis = _RoundTowardZero(self.nanos, _NANOS_PER_MILLISECOND)
+    return self.seconds * _MILLIS_PER_SECOND + millis
+
+  def ToSeconds(self):
+    """Converts a Duration to seconds."""
+    return self.seconds
+
+  def FromNanoseconds(self, nanos):
+    """Converts nanoseconds to Duration."""
+    self._NormalizeDuration(nanos // _NANOS_PER_SECOND,
+                            nanos % _NANOS_PER_SECOND)
+
+  def FromMicroseconds(self, micros):
+    """Converts microseconds to Duration."""
+    self._NormalizeDuration(
+        micros // _MICROS_PER_SECOND,
+        (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND)
+
+  def FromMilliseconds(self, millis):
+    """Converts milliseconds to Duration."""
+    self._NormalizeDuration(
+        millis // _MILLIS_PER_SECOND,
+        (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND)
+
+  def FromSeconds(self, seconds):
+    """Converts seconds to Duration."""
+    self.seconds = seconds
+    self.nanos = 0
+
+  def ToTimedelta(self):
+    """Converts Duration to timedelta."""
+    return timedelta(
+        seconds=self.seconds, microseconds=_RoundTowardZero(
+            self.nanos, _NANOS_PER_MICROSECOND))
+
+  def FromTimedelta(self, td):
+    """Convertd timedelta to Duration."""
+    self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY,
+                            td.microseconds * _NANOS_PER_MICROSECOND)
+
+  def _NormalizeDuration(self, seconds, nanos):
+    """Set Duration by seconds and nonas."""
+    # Force nanos to be negative if the duration is negative.
+    if seconds < 0 and nanos > 0:
+      seconds += 1
+      nanos -= _NANOS_PER_SECOND
+    self.seconds = seconds
+    self.nanos = nanos
+
+
+def _RoundTowardZero(value, divider):
+  """Truncates the remainder part after division."""
+  # For some languanges, the sign of the remainder is implementation
+  # dependent if any of the operands is negative. Here we enforce
+  # "rounded toward zero" semantics. For example, for (-5) / 2 an
+  # implementation may give -3 as the result with the remainder being
+  # 1. This function ensures we always return -2 (closer to zero).
+  result = value // divider
+  remainder = value % divider
+  if result < 0 and remainder > 0:
+    return result + 1
+  else:
+    return result
+
+
+class FieldMask(object):
+  """Class for FieldMask message type."""
+
+  def ToJsonString(self):
+    """Converts FieldMask to string according to proto3 JSON spec."""
+    return ','.join(self.paths)
+
+  def FromJsonString(self, value):
+    """Converts string to FieldMask according to proto3 JSON spec."""
+    self.Clear()
+    for path in value.split(','):
+      self.paths.append(path)
+
+  def IsValidForDescriptor(self, message_descriptor):
+    """Checks whether the FieldMask is valid for Message Descriptor."""
+    for path in self.paths:
+      if not _IsValidPath(message_descriptor, path):
+        return False
+    return True
+
+  def AllFieldsFromDescriptor(self, message_descriptor):
+    """Gets all direct fields of Message Descriptor to FieldMask."""
+    self.Clear()
+    for field in message_descriptor.fields:
+      self.paths.append(field.name)
+
+  def CanonicalFormFromMask(self, mask):
+    """Converts a FieldMask to the canonical form.
+
+    Removes paths that are covered by another path. For example,
+    "foo.bar" is covered by "foo" and will be removed if "foo"
+    is also in the FieldMask. Then sorts all paths in alphabetical order.
+
+    Args:
+      mask: The original FieldMask to be converted.
+    """
+    tree = _FieldMaskTree(mask)
+    tree.ToFieldMask(self)
+
+  def Union(self, mask1, mask2):
+    """Merges mask1 and mask2 into this FieldMask."""
+    _CheckFieldMaskMessage(mask1)
+    _CheckFieldMaskMessage(mask2)
+    tree = _FieldMaskTree(mask1)
+    tree.MergeFromFieldMask(mask2)
+    tree.ToFieldMask(self)
+
+  def Intersect(self, mask1, mask2):
+    """Intersects mask1 and mask2 into this FieldMask."""
+    _CheckFieldMaskMessage(mask1)
+    _CheckFieldMaskMessage(mask2)
+    tree = _FieldMaskTree(mask1)
+    intersection = _FieldMaskTree()
+    for path in mask2.paths:
+      tree.IntersectPath(path, intersection)
+    intersection.ToFieldMask(self)
+
+  def MergeMessage(
+      self, source, destination,
+      replace_message_field=False, replace_repeated_field=False):
+    """Merges fields specified in FieldMask from source to destination.
+
+    Args:
+      source: Source message.
+      destination: The destination message to be merged into.
+      replace_message_field: Replace message field if True. Merge message
+          field if False.
+      replace_repeated_field: Replace repeated field if True. Append
+          elements of repeated field if False.
+    """
+    tree = _FieldMaskTree(self)
+    tree.MergeMessage(
+        source, destination, replace_message_field, replace_repeated_field)
+
+
+def _IsValidPath(message_descriptor, path):
+  """Checks whether the path is valid for Message Descriptor."""
+  parts = path.split('.')
+  last = parts.pop()
+  for name in parts:
+    field = message_descriptor.fields_by_name[name]
+    if (field is None or
+        field.label == FieldDescriptor.LABEL_REPEATED or
+        field.type != FieldDescriptor.TYPE_MESSAGE):
+      return False
+    message_descriptor = field.message_type
+  return last in message_descriptor.fields_by_name
+
+
+def _CheckFieldMaskMessage(message):
+  """Raises ValueError if message is not a FieldMask."""
+  message_descriptor = message.DESCRIPTOR
+  if (message_descriptor.name != 'FieldMask' or
+      message_descriptor.file.name != 'google/protobuf/field_mask.proto'):
+    raise ValueError('Message {0} is not a FieldMask.'.format(
+        message_descriptor.full_name))
+
+
+class _FieldMaskTree(object):
+  """Represents a FieldMask in a tree structure.
+
+  For example, given a FieldMask "foo.bar,foo.baz,bar.baz",
+  the FieldMaskTree will be:
+      [_root] -+- foo -+- bar
+            |       |
+            |       +- baz
+            |
+            +- bar --- baz
+  In the tree, each leaf node represents a field path.
+  """
+
+  def __init__(self, field_mask=None):
+    """Initializes the tree by FieldMask."""
+    self._root = {}
+    if field_mask:
+      self.MergeFromFieldMask(field_mask)
+
+  def MergeFromFieldMask(self, field_mask):
+    """Merges a FieldMask to the tree."""
+    for path in field_mask.paths:
+      self.AddPath(path)
+
+  def AddPath(self, path):
+    """Adds a field path into the tree.
+
+    If the field path to add is a sub-path of an existing field path
+    in the tree (i.e., a leaf node), it means the tree already matches
+    the given path so nothing will be added to the tree. If the path
+    matches an existing non-leaf node in the tree, that non-leaf node
+    will be turned into a leaf node with all its children removed because
+    the path matches all the node's children. Otherwise, a new path will
+    be added.
+
+    Args:
+      path: The field path to add.
+    """
+    node = self._root
+    for name in path.split('.'):
+      if name not in node:
+        node[name] = {}
+      elif not node[name]:
+        # Pre-existing empty node implies we already have this entire tree.
+        return
+      node = node[name]
+    # Remove any sub-trees we might have had.
+    node.clear()
+
+  def ToFieldMask(self, field_mask):
+    """Converts the tree to a FieldMask."""
+    field_mask.Clear()
+    _AddFieldPaths(self._root, '', field_mask)
+
+  def IntersectPath(self, path, intersection):
+    """Calculates the intersection part of a field path with this tree.
+
+    Args:
+      path: The field path to calculates.
+      intersection: The out tree to record the intersection part.
+    """
+    node = self._root
+    for name in path.split('.'):
+      if name not in node:
+        return
+      elif not node[name]:
+        intersection.AddPath(path)
+        return
+      node = node[name]
+    intersection.AddLeafNodes(path, node)
+
+  def AddLeafNodes(self, prefix, node):
+    """Adds leaf nodes begin with prefix to this tree."""
+    if not node:
+      self.AddPath(prefix)
+    for name in node:
+      child_path = prefix + '.' + name
+      self.AddLeafNodes(child_path, node[name])
+
+  def MergeMessage(
+      self, source, destination,
+      replace_message, replace_repeated):
+    """Merge all fields specified by this tree from source to destination."""
+    _MergeMessage(
+        self._root, source, destination, replace_message, replace_repeated)
+
+
+def _StrConvert(value):
+  """Converts value to str if it is not."""
+  # This file is imported by c extension and some methods like ClearField
+  # requires string for the field name. py2/py3 has different text
+  # type and may use unicode.
+  if not isinstance(value, str):
+    return value.encode('utf-8')
+  return value
+
+
+def _MergeMessage(
+    node, source, destination, replace_message, replace_repeated):
+  """Merge all fields specified by a sub-tree from source to destination."""
+  source_descriptor = source.DESCRIPTOR
+  for name in node:
+    child = node[name]
+    field = source_descriptor.fields_by_name[name]
+    if field is None:
+      raise ValueError('Error: Can\'t find field {0} in message {1}.'.format(
+          name, source_descriptor.full_name))
+    if child:
+      # Sub-paths are only allowed for singular message fields.
+      if (field.label == FieldDescriptor.LABEL_REPEATED or
+          field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE):
+        raise ValueError('Error: Field {0} in message {1} is not a singular '
+                         'message field and cannot have sub-fields.'.format(
+                             name, source_descriptor.full_name))
+      _MergeMessage(
+          child, getattr(source, name), getattr(destination, name),
+          replace_message, replace_repeated)
+      continue
+    if field.label == FieldDescriptor.LABEL_REPEATED:
+      if replace_repeated:
+        destination.ClearField(_StrConvert(name))
+      repeated_source = getattr(source, name)
+      repeated_destination = getattr(destination, name)
+      if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
+        for item in repeated_source:
+          repeated_destination.add().MergeFrom(item)
+      else:
+        repeated_destination.extend(repeated_source)
+    else:
+      if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
+        if replace_message:
+          destination.ClearField(_StrConvert(name))
+        if source.HasField(name):
+          getattr(destination, name).MergeFrom(getattr(source, name))
+      else:
+        setattr(destination, name, getattr(source, name))
+
+
+def _AddFieldPaths(node, prefix, field_mask):
+  """Adds the field paths descended from node to field_mask."""
+  if not node:
+    field_mask.paths.append(prefix)
+    return
+  for name in sorted(node):
+    if prefix:
+      child_path = prefix + '.' + name
+    else:
+      child_path = name
+    _AddFieldPaths(node[name], child_path, field_mask)
+
+
+_INT_OR_FLOAT = six.integer_types + (float,)
+
+
+def _SetStructValue(struct_value, value):
+  if value is None:
+    struct_value.null_value = 0
+  elif isinstance(value, bool):
+    # Note: this check must come before the number check because in Python
+    # True and False are also considered numbers.
+    struct_value.bool_value = value
+  elif isinstance(value, six.string_types):
+    struct_value.string_value = value
+  elif isinstance(value, _INT_OR_FLOAT):
+    struct_value.number_value = value
+  else:
+    raise ValueError('Unexpected type')
+
+
+def _GetStructValue(struct_value):
+  which = struct_value.WhichOneof('kind')
+  if which == 'struct_value':
+    return struct_value.struct_value
+  elif which == 'null_value':
+    return None
+  elif which == 'number_value':
+    return struct_value.number_value
+  elif which == 'string_value':
+    return struct_value.string_value
+  elif which == 'bool_value':
+    return struct_value.bool_value
+  elif which == 'list_value':
+    return struct_value.list_value
+  elif which is None:
+    raise ValueError('Value not set')
+
+
+class Struct(object):
+  """Class for Struct message type."""
+
+  __slots__ = []
+
+  def __getitem__(self, key):
+    return _GetStructValue(self.fields[key])
+
+  def __setitem__(self, key, value):
+    _SetStructValue(self.fields[key], value)
+
+  def get_or_create_list(self, key):
+    """Returns a list for this key, creating if it didn't exist already."""
+    return self.fields[key].list_value
+
+  def get_or_create_struct(self, key):
+    """Returns a struct for this key, creating if it didn't exist already."""
+    return self.fields[key].struct_value
+
+  # TODO(haberman): allow constructing/merging from dict.
+
+
+class ListValue(object):
+  """Class for ListValue message type."""
+
+  def __len__(self):
+    return len(self.values)
+
+  def append(self, value):
+    _SetStructValue(self.values.add(), value)
+
+  def extend(self, elem_seq):
+    for value in elem_seq:
+      self.append(value)
+
+  def __getitem__(self, index):
+    """Retrieves item by the specified index."""
+    return _GetStructValue(self.values.__getitem__(index))
+
+  def __setitem__(self, index, value):
+    _SetStructValue(self.values.__getitem__(index), value)
+
+  def items(self):
+    for i in range(len(self)):
+      yield self[i]
+
+  def add_struct(self):
+    """Appends and returns a struct value as the next value in the list."""
+    return self.values.add().struct_value
+
+  def add_list(self):
+    """Appends and returns a list value as the next value in the list."""
+    return self.values.add().list_value
+
+
+WKTBASES = {
+    'google.protobuf.Any': Any,
+    'google.protobuf.Duration': Duration,
+    'google.protobuf.FieldMask': FieldMask,
+    'google.protobuf.ListValue': ListValue,
+    'google.protobuf.Struct': Struct,
+    'google.protobuf.Timestamp': Timestamp,
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types_test.py
new file mode 100644
index 0000000..2f32ac9
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/well_known_types_test.py
@@ -0,0 +1,644 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Test for google.protobuf.internal.well_known_types."""
+
+__author__ = 'jieluo@google.com (Jie Luo)'
+
+from datetime import datetime
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import any_pb2
+from google.protobuf import duration_pb2
+from google.protobuf import field_mask_pb2
+from google.protobuf import struct_pb2
+from google.protobuf import timestamp_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf.internal import any_test_pb2
+from google.protobuf.internal import test_util
+from google.protobuf.internal import well_known_types
+from google.protobuf import descriptor
+from google.protobuf import text_format
+
+
+class TimeUtilTestBase(unittest.TestCase):
+
+  def CheckTimestampConversion(self, message, text):
+    self.assertEqual(text, message.ToJsonString())
+    parsed_message = timestamp_pb2.Timestamp()
+    parsed_message.FromJsonString(text)
+    self.assertEqual(message, parsed_message)
+
+  def CheckDurationConversion(self, message, text):
+    self.assertEqual(text, message.ToJsonString())
+    parsed_message = duration_pb2.Duration()
+    parsed_message.FromJsonString(text)
+    self.assertEqual(message, parsed_message)
+
+
+class TimeUtilTest(TimeUtilTestBase):
+
+  def testTimestampSerializeAndParse(self):
+    message = timestamp_pb2.Timestamp()
+    # Generated output should contain 3, 6, or 9 fractional digits.
+    message.seconds = 0
+    message.nanos = 0
+    self.CheckTimestampConversion(message, '1970-01-01T00:00:00Z')
+    message.nanos = 10000000
+    self.CheckTimestampConversion(message, '1970-01-01T00:00:00.010Z')
+    message.nanos = 10000
+    self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000010Z')
+    message.nanos = 10
+    self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000000010Z')
+    # Test min timestamps.
+    message.seconds = -62135596800
+    message.nanos = 0
+    self.CheckTimestampConversion(message, '0001-01-01T00:00:00Z')
+    # Test max timestamps.
+    message.seconds = 253402300799
+    message.nanos = 999999999
+    self.CheckTimestampConversion(message, '9999-12-31T23:59:59.999999999Z')
+    # Test negative timestamps.
+    message.seconds = -1
+    self.CheckTimestampConversion(message, '1969-12-31T23:59:59.999999999Z')
+
+    # Parsing accepts an fractional digits as long as they fit into nano
+    # precision.
+    message.FromJsonString('1970-01-01T00:00:00.1Z')
+    self.assertEqual(0, message.seconds)
+    self.assertEqual(100000000, message.nanos)
+    # Parsing accpets offsets.
+    message.FromJsonString('1970-01-01T00:00:00-08:00')
+    self.assertEqual(8 * 3600, message.seconds)
+    self.assertEqual(0, message.nanos)
+
+  def testDurationSerializeAndParse(self):
+    message = duration_pb2.Duration()
+    # Generated output should contain 3, 6, or 9 fractional digits.
+    message.seconds = 0
+    message.nanos = 0
+    self.CheckDurationConversion(message, '0s')
+    message.nanos = 10000000
+    self.CheckDurationConversion(message, '0.010s')
+    message.nanos = 10000
+    self.CheckDurationConversion(message, '0.000010s')
+    message.nanos = 10
+    self.CheckDurationConversion(message, '0.000000010s')
+
+    # Test min and max
+    message.seconds = 315576000000
+    message.nanos = 999999999
+    self.CheckDurationConversion(message, '315576000000.999999999s')
+    message.seconds = -315576000000
+    message.nanos = -999999999
+    self.CheckDurationConversion(message, '-315576000000.999999999s')
+
+    # Parsing accepts an fractional digits as long as they fit into nano
+    # precision.
+    message.FromJsonString('0.1s')
+    self.assertEqual(100000000, message.nanos)
+    message.FromJsonString('0.0000001s')
+    self.assertEqual(100, message.nanos)
+
+  def testTimestampIntegerConversion(self):
+    message = timestamp_pb2.Timestamp()
+    message.FromNanoseconds(1)
+    self.assertEqual('1970-01-01T00:00:00.000000001Z',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToNanoseconds())
+
+    message.FromNanoseconds(-1)
+    self.assertEqual('1969-12-31T23:59:59.999999999Z',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToNanoseconds())
+
+    message.FromMicroseconds(1)
+    self.assertEqual('1970-01-01T00:00:00.000001Z',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToMicroseconds())
+
+    message.FromMicroseconds(-1)
+    self.assertEqual('1969-12-31T23:59:59.999999Z',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToMicroseconds())
+
+    message.FromMilliseconds(1)
+    self.assertEqual('1970-01-01T00:00:00.001Z',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToMilliseconds())
+
+    message.FromMilliseconds(-1)
+    self.assertEqual('1969-12-31T23:59:59.999Z',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToMilliseconds())
+
+    message.FromSeconds(1)
+    self.assertEqual('1970-01-01T00:00:01Z',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToSeconds())
+
+    message.FromSeconds(-1)
+    self.assertEqual('1969-12-31T23:59:59Z',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToSeconds())
+
+    message.FromNanoseconds(1999)
+    self.assertEqual(1, message.ToMicroseconds())
+    # For negative values, Timestamp will be rounded down.
+    # For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds
+    # will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than
+    # "1970-01-01T00:00:00Z" (i.e., 0s).
+    message.FromNanoseconds(-1999)
+    self.assertEqual(-2, message.ToMicroseconds())
+
+  def testDurationIntegerConversion(self):
+    message = duration_pb2.Duration()
+    message.FromNanoseconds(1)
+    self.assertEqual('0.000000001s',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToNanoseconds())
+
+    message.FromNanoseconds(-1)
+    self.assertEqual('-0.000000001s',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToNanoseconds())
+
+    message.FromMicroseconds(1)
+    self.assertEqual('0.000001s',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToMicroseconds())
+
+    message.FromMicroseconds(-1)
+    self.assertEqual('-0.000001s',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToMicroseconds())
+
+    message.FromMilliseconds(1)
+    self.assertEqual('0.001s',
+                     message.ToJsonString())
+    self.assertEqual(1, message.ToMilliseconds())
+
+    message.FromMilliseconds(-1)
+    self.assertEqual('-0.001s',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToMilliseconds())
+
+    message.FromSeconds(1)
+    self.assertEqual('1s', message.ToJsonString())
+    self.assertEqual(1, message.ToSeconds())
+
+    message.FromSeconds(-1)
+    self.assertEqual('-1s',
+                     message.ToJsonString())
+    self.assertEqual(-1, message.ToSeconds())
+
+    # Test truncation behavior.
+    message.FromNanoseconds(1999)
+    self.assertEqual(1, message.ToMicroseconds())
+
+    # For negative values, Duration will be rounded towards 0.
+    message.FromNanoseconds(-1999)
+    self.assertEqual(-1, message.ToMicroseconds())
+
+  def testDatetimeConverison(self):
+    message = timestamp_pb2.Timestamp()
+    dt = datetime(1970, 1, 1)
+    message.FromDatetime(dt)
+    self.assertEqual(dt, message.ToDatetime())
+
+    message.FromMilliseconds(1999)
+    self.assertEqual(datetime(1970, 1, 1, 0, 0, 1, 999000),
+                     message.ToDatetime())
+
+  def testTimedeltaConversion(self):
+    message = duration_pb2.Duration()
+    message.FromNanoseconds(1999999999)
+    td = message.ToTimedelta()
+    self.assertEqual(1, td.seconds)
+    self.assertEqual(999999, td.microseconds)
+
+    message.FromNanoseconds(-1999999999)
+    td = message.ToTimedelta()
+    self.assertEqual(-1, td.days)
+    self.assertEqual(86398, td.seconds)
+    self.assertEqual(1, td.microseconds)
+
+    message.FromMicroseconds(-1)
+    td = message.ToTimedelta()
+    self.assertEqual(-1, td.days)
+    self.assertEqual(86399, td.seconds)
+    self.assertEqual(999999, td.microseconds)
+    converted_message = duration_pb2.Duration()
+    converted_message.FromTimedelta(td)
+    self.assertEqual(message, converted_message)
+
+  def testInvalidTimestamp(self):
+    message = timestamp_pb2.Timestamp()
+    self.assertRaisesRegexp(
+        ValueError,
+        'time data \'10000-01-01T00:00:00\' does not match'
+        ' format \'%Y-%m-%dT%H:%M:%S\'',
+        message.FromJsonString, '10000-01-01T00:00:00.00Z')
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        'nanos 0123456789012 more than 9 fractional digits.',
+        message.FromJsonString,
+        '1970-01-01T00:00:00.0123456789012Z')
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        (r'Invalid timezone offset value: \+08.'),
+        message.FromJsonString,
+        '1972-01-01T01:00:00.01+08',)
+    self.assertRaisesRegexp(
+        ValueError,
+        'year is out of range',
+        message.FromJsonString,
+        '0000-01-01T00:00:00Z')
+    message.seconds = 253402300800
+    self.assertRaisesRegexp(
+        OverflowError,
+        'date value out of range',
+        message.ToJsonString)
+
+  def testInvalidDuration(self):
+    message = duration_pb2.Duration()
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        'Duration must end with letter "s": 1.',
+        message.FromJsonString, '1')
+    self.assertRaisesRegexp(
+        well_known_types.ParseError,
+        'Couldn\'t parse duration: 1...2s.',
+        message.FromJsonString, '1...2s')
+
+
+class FieldMaskTest(unittest.TestCase):
+
+  def testStringFormat(self):
+    mask = field_mask_pb2.FieldMask()
+    self.assertEqual('', mask.ToJsonString())
+    mask.paths.append('foo')
+    self.assertEqual('foo', mask.ToJsonString())
+    mask.paths.append('bar')
+    self.assertEqual('foo,bar', mask.ToJsonString())
+
+    mask.FromJsonString('')
+    self.assertEqual('', mask.ToJsonString())
+    mask.FromJsonString('foo')
+    self.assertEqual(['foo'], mask.paths)
+    mask.FromJsonString('foo,bar')
+    self.assertEqual(['foo', 'bar'], mask.paths)
+
+  def testDescriptorToFieldMask(self):
+    mask = field_mask_pb2.FieldMask()
+    msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    mask.AllFieldsFromDescriptor(msg_descriptor)
+    self.assertEqual(75, len(mask.paths))
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    for field in msg_descriptor.fields:
+      self.assertTrue(field.name in mask.paths)
+    mask.paths.append('optional_nested_message.bb')
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    mask.paths.append('repeated_nested_message.bb')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+
+  def testCanonicalFrom(self):
+    mask = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    # Paths will be sorted.
+    mask.FromJsonString('baz.quz,bar,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString())
+    # Duplicated paths will be removed.
+    mask.FromJsonString('foo,bar,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,foo', out_mask.ToJsonString())
+    # Sub-paths of other paths will be removed.
+    mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString())
+
+    # Test more deeply nested cases.
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
+                     out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
+                     out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar', out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo', out_mask.ToJsonString())
+
+  def testUnion(self):
+    mask1 = field_mask_pb2.FieldMask()
+    mask2 = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    mask1.FromJsonString('foo,baz')
+    mask2.FromJsonString('bar,quz')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString())
+    # Overlap with duplicated paths.
+    mask1.FromJsonString('foo,baz.bb')
+    mask2.FromJsonString('baz.bb,quz')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString())
+    # Overlap with paths covering some other paths.
+    mask1.FromJsonString('foo.bar.baz,quz')
+    mask2.FromJsonString('foo.bar,bar')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString())
+
+  def testIntersect(self):
+    mask1 = field_mask_pb2.FieldMask()
+    mask2 = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    # Test cases without overlapping.
+    mask1.FromJsonString('foo,baz')
+    mask2.FromJsonString('bar,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('', out_mask.ToJsonString())
+    # Overlap with duplicated paths.
+    mask1.FromJsonString('foo,baz.bb')
+    mask2.FromJsonString('baz.bb,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('baz.bb', out_mask.ToJsonString())
+    # Overlap with paths covering some other paths.
+    mask1.FromJsonString('foo.bar.baz,quz')
+    mask2.FromJsonString('foo.bar,bar')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
+    mask1.FromJsonString('foo.bar,bar')
+    mask2.FromJsonString('foo.bar.baz,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
+
+  def testMergeMessage(self):
+    # Test merge one field.
+    src = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(src)
+    for field in src.DESCRIPTOR.fields:
+      if field.containing_oneof:
+        continue
+      field_name = field.name
+      dst = unittest_pb2.TestAllTypes()
+      # Only set one path to mask.
+      mask = field_mask_pb2.FieldMask()
+      mask.paths.append(field_name)
+      mask.MergeMessage(src, dst)
+      # The expected result message.
+      msg = unittest_pb2.TestAllTypes()
+      if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        repeated_src = getattr(src, field_name)
+        repeated_msg = getattr(msg, field_name)
+        if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+          for item in repeated_src:
+            repeated_msg.add().CopyFrom(item)
+        else:
+          repeated_msg.extend(repeated_src)
+      elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+        getattr(msg, field_name).CopyFrom(getattr(src, field_name))
+      else:
+        setattr(msg, field_name, getattr(src, field_name))
+      # Only field specified in mask is merged.
+      self.assertEqual(msg, dst)
+
+    # Test merge nested fields.
+    nested_src = unittest_pb2.NestedTestAllTypes()
+    nested_dst = unittest_pb2.NestedTestAllTypes()
+    nested_src.child.payload.optional_int32 = 1234
+    nested_src.child.child.payload.optional_int32 = 5678
+    mask = field_mask_pb2.FieldMask()
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(0, nested_dst.child.child.payload.optional_int32)
+
+    mask.FromJsonString('child.child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    nested_dst.Clear()
+    mask.FromJsonString('child.child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(0, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    nested_dst.Clear()
+    mask.FromJsonString('child')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    # Test MergeOptions.
+    nested_dst.Clear()
+    nested_dst.child.payload.optional_int64 = 4321
+    # Message fields will be merged by default.
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(4321, nested_dst.child.payload.optional_int64)
+    # Change the behavior to replace message fields.
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst, True, False)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(0, nested_dst.child.payload.optional_int64)
+
+    # By default, fields missing in source are not cleared in destination.
+    nested_dst.payload.optional_int32 = 1234
+    self.assertTrue(nested_dst.HasField('payload'))
+    mask.FromJsonString('payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertTrue(nested_dst.HasField('payload'))
+    # But they are cleared when replacing message fields.
+    nested_dst.Clear()
+    nested_dst.payload.optional_int32 = 1234
+    mask.FromJsonString('payload')
+    mask.MergeMessage(nested_src, nested_dst, True, False)
+    self.assertFalse(nested_dst.HasField('payload'))
+
+    nested_src.payload.repeated_int32.append(1234)
+    nested_dst.payload.repeated_int32.append(5678)
+    # Repeated fields will be appended by default.
+    mask.FromJsonString('payload.repeated_int32')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(2, len(nested_dst.payload.repeated_int32))
+    self.assertEqual(5678, nested_dst.payload.repeated_int32[0])
+    self.assertEqual(1234, nested_dst.payload.repeated_int32[1])
+    # Change the behavior to replace repeated fields.
+    mask.FromJsonString('payload.repeated_int32')
+    mask.MergeMessage(nested_src, nested_dst, False, True)
+    self.assertEqual(1, len(nested_dst.payload.repeated_int32))
+    self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
+
+
+class StructTest(unittest.TestCase):
+
+  def testStruct(self):
+    struct = struct_pb2.Struct()
+    struct_class = struct.__class__
+
+    struct['key1'] = 5
+    struct['key2'] = 'abc'
+    struct['key3'] = True
+    struct.get_or_create_struct('key4')['subkey'] = 11.0
+    struct_list = struct.get_or_create_list('key5')
+    struct_list.extend([6, 'seven', True, False, None])
+    struct_list.add_struct()['subkey2'] = 9
+
+    self.assertTrue(isinstance(struct, well_known_types.Struct))
+    self.assertEquals(5, struct['key1'])
+    self.assertEquals('abc', struct['key2'])
+    self.assertIs(True, struct['key3'])
+    self.assertEquals(11, struct['key4']['subkey'])
+    inner_struct = struct_class()
+    inner_struct['subkey2'] = 9
+    self.assertEquals([6, 'seven', True, False, None, inner_struct],
+                      list(struct['key5'].items()))
+
+    serialized = struct.SerializeToString()
+
+    struct2 = struct_pb2.Struct()
+    struct2.ParseFromString(serialized)
+
+    self.assertEquals(struct, struct2)
+
+    self.assertTrue(isinstance(struct2, well_known_types.Struct))
+    self.assertEquals(5, struct2['key1'])
+    self.assertEquals('abc', struct2['key2'])
+    self.assertIs(True, struct2['key3'])
+    self.assertEquals(11, struct2['key4']['subkey'])
+    self.assertEquals([6, 'seven', True, False, None, inner_struct],
+                      list(struct2['key5'].items()))
+
+    struct_list = struct2['key5']
+    self.assertEquals(6, struct_list[0])
+    self.assertEquals('seven', struct_list[1])
+    self.assertEquals(True, struct_list[2])
+    self.assertEquals(False, struct_list[3])
+    self.assertEquals(None, struct_list[4])
+    self.assertEquals(inner_struct, struct_list[5])
+
+    struct_list[1] = 7
+    self.assertEquals(7, struct_list[1])
+
+    struct_list.add_list().extend([1, 'two', True, False, None])
+    self.assertEquals([1, 'two', True, False, None],
+                      list(struct_list[6].items()))
+
+    text_serialized = str(struct)
+    struct3 = struct_pb2.Struct()
+    text_format.Merge(text_serialized, struct3)
+    self.assertEquals(struct, struct3)
+
+    struct.get_or_create_struct('key3')['replace'] = 12
+    self.assertEquals(12, struct['key3']['replace'])
+
+
+class AnyTest(unittest.TestCase):
+
+  def testAnyMessage(self):
+    # Creates and sets message.
+    msg = any_test_pb2.TestAny()
+    msg_descriptor = msg.DESCRIPTOR
+    all_types = unittest_pb2.TestAllTypes()
+    all_descriptor = all_types.DESCRIPTOR
+    all_types.repeated_string.append(u'\u00fc\ua71f')
+    # Packs to Any.
+    msg.value.Pack(all_types)
+    self.assertEqual(msg.value.type_url,
+                     'type.googleapis.com/%s' % all_descriptor.full_name)
+    self.assertEqual(msg.value.value,
+                     all_types.SerializeToString())
+    # Tests Is() method.
+    self.assertTrue(msg.value.Is(all_descriptor))
+    self.assertFalse(msg.value.Is(msg_descriptor))
+    # Unpacks Any.
+    unpacked_message = unittest_pb2.TestAllTypes()
+    self.assertTrue(msg.value.Unpack(unpacked_message))
+    self.assertEqual(all_types, unpacked_message)
+    # Unpacks to different type.
+    self.assertFalse(msg.value.Unpack(msg))
+    # Only Any messages have Pack method.
+    try:
+      msg.Pack(all_types)
+    except AttributeError:
+      pass
+    else:
+      raise AttributeError('%s should not have Pack method.' %
+                           msg_descriptor.full_name)
+
+  def testMessageName(self):
+    # Creates and sets message.
+    submessage = any_test_pb2.TestAny()
+    submessage.int_value = 12345
+    msg = any_pb2.Any()
+    msg.Pack(submessage)
+    self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny')
+
+  def testPackWithCustomTypeUrl(self):
+    submessage = any_test_pb2.TestAny()
+    submessage.int_value = 12345
+    msg = any_pb2.Any()
+    # Pack with a custom type URL prefix.
+    msg.Pack(submessage, 'type.myservice.com')
+    self.assertEqual(msg.type_url,
+                     'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
+    # Pack with a custom type URL prefix ending with '/'.
+    msg.Pack(submessage, 'type.myservice.com/')
+    self.assertEqual(msg.type_url,
+                     'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
+    # Pack with an empty type URL prefix.
+    msg.Pack(submessage, '')
+    self.assertEqual(msg.type_url,
+                     '/%s' % submessage.DESCRIPTOR.full_name)
+    # Test unpacking the type.
+    unpacked_message = any_test_pb2.TestAny()
+    self.assertTrue(msg.Unpack(unpacked_message))
+    self.assertEqual(submessage, unpacked_message)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format.py b/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format.py
new file mode 100755
index 0000000..883f525
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format.py
@@ -0,0 +1,268 @@
+# 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.
+
+"""Constants and static functions to support protocol buffer wire format."""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+import struct
+from google.protobuf import descriptor
+from google.protobuf import message
+
+
+TAG_TYPE_BITS = 3  # Number of bits used to hold type info in a proto tag.
+TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1  # 0x7
+
+# These numbers identify the wire type of a protocol buffer value.
+# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded
+# tag-and-type to store one of these WIRETYPE_* constants.
+# These values must match WireType enum in google/protobuf/wire_format.h.
+WIRETYPE_VARINT = 0
+WIRETYPE_FIXED64 = 1
+WIRETYPE_LENGTH_DELIMITED = 2
+WIRETYPE_START_GROUP = 3
+WIRETYPE_END_GROUP = 4
+WIRETYPE_FIXED32 = 5
+_WIRETYPE_MAX = 5
+
+
+# Bounds for various integer types.
+INT32_MAX = int((1 << 31) - 1)
+INT32_MIN = int(-(1 << 31))
+UINT32_MAX = (1 << 32) - 1
+
+INT64_MAX = (1 << 63) - 1
+INT64_MIN = -(1 << 63)
+UINT64_MAX = (1 << 64) - 1
+
+# "struct" format strings that will encode/decode the specified formats.
+FORMAT_UINT32_LITTLE_ENDIAN = '<I'
+FORMAT_UINT64_LITTLE_ENDIAN = '<Q'
+FORMAT_FLOAT_LITTLE_ENDIAN = '<f'
+FORMAT_DOUBLE_LITTLE_ENDIAN = '<d'
+
+
+# We'll have to provide alternate implementations of AppendLittleEndian*() on
+# any architectures where these checks fail.
+if struct.calcsize(FORMAT_UINT32_LITTLE_ENDIAN) != 4:
+  raise AssertionError('Format "I" is not a 32-bit number.')
+if struct.calcsize(FORMAT_UINT64_LITTLE_ENDIAN) != 8:
+  raise AssertionError('Format "Q" is not a 64-bit number.')
+
+
+def PackTag(field_number, wire_type):
+  """Returns an unsigned 32-bit integer that encodes the field number and
+  wire type information in standard protocol message wire format.
+
+  Args:
+    field_number: Expected to be an integer in the range [1, 1 << 29)
+    wire_type: One of the WIRETYPE_* constants.
+  """
+  if not 0 <= wire_type <= _WIRETYPE_MAX:
+    raise message.EncodeError('Unknown wire type: %d' % wire_type)
+  return (field_number << TAG_TYPE_BITS) | wire_type
+
+
+def UnpackTag(tag):
+  """The inverse of PackTag().  Given an unsigned 32-bit number,
+  returns a (field_number, wire_type) tuple.
+  """
+  return (tag >> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK)
+
+
+def ZigZagEncode(value):
+  """ZigZag Transform:  Encodes signed integers so that they can be
+  effectively used with varint encoding.  See wire_format.h for
+  more details.
+  """
+  if value >= 0:
+    return value << 1
+  return (value << 1) ^ (~0)
+
+
+def ZigZagDecode(value):
+  """Inverse of ZigZagEncode()."""
+  if not value & 0x1:
+    return value >> 1
+  return (value >> 1) ^ (~0)
+
+
+
+# The *ByteSize() functions below return the number of bytes required to
+# serialize "field number + type" information and then serialize the value.
+
+
+def Int32ByteSize(field_number, int32):
+  return Int64ByteSize(field_number, int32)
+
+
+def Int32ByteSizeNoTag(int32):
+  return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32)
+
+
+def Int64ByteSize(field_number, int64):
+  # Have to convert to uint before calling UInt64ByteSize().
+  return UInt64ByteSize(field_number, 0xffffffffffffffff & int64)
+
+
+def UInt32ByteSize(field_number, uint32):
+  return UInt64ByteSize(field_number, uint32)
+
+
+def UInt64ByteSize(field_number, uint64):
+  return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64)
+
+
+def SInt32ByteSize(field_number, int32):
+  return UInt32ByteSize(field_number, ZigZagEncode(int32))
+
+
+def SInt64ByteSize(field_number, int64):
+  return UInt64ByteSize(field_number, ZigZagEncode(int64))
+
+
+def Fixed32ByteSize(field_number, fixed32):
+  return TagByteSize(field_number) + 4
+
+
+def Fixed64ByteSize(field_number, fixed64):
+  return TagByteSize(field_number) + 8
+
+
+def SFixed32ByteSize(field_number, sfixed32):
+  return TagByteSize(field_number) + 4
+
+
+def SFixed64ByteSize(field_number, sfixed64):
+  return TagByteSize(field_number) + 8
+
+
+def FloatByteSize(field_number, flt):
+  return TagByteSize(field_number) + 4
+
+
+def DoubleByteSize(field_number, double):
+  return TagByteSize(field_number) + 8
+
+
+def BoolByteSize(field_number, b):
+  return TagByteSize(field_number) + 1
+
+
+def EnumByteSize(field_number, enum):
+  return UInt32ByteSize(field_number, enum)
+
+
+def StringByteSize(field_number, string):
+  return BytesByteSize(field_number, string.encode('utf-8'))
+
+
+def BytesByteSize(field_number, b):
+  return (TagByteSize(field_number)
+          + _VarUInt64ByteSizeNoTag(len(b))
+          + len(b))
+
+
+def GroupByteSize(field_number, message):
+  return (2 * TagByteSize(field_number)  # START and END group.
+          + message.ByteSize())
+
+
+def MessageByteSize(field_number, message):
+  return (TagByteSize(field_number)
+          + _VarUInt64ByteSizeNoTag(message.ByteSize())
+          + message.ByteSize())
+
+
+def MessageSetItemByteSize(field_number, msg):
+  # First compute the sizes of the tags.
+  # There are 2 tags for the beginning and ending of the repeated group, that
+  # is field number 1, one with field number 2 (type_id) and one with field
+  # number 3 (message).
+  total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3))
+
+  # Add the number of bytes for type_id.
+  total_size += _VarUInt64ByteSizeNoTag(field_number)
+
+  message_size = msg.ByteSize()
+
+  # The number of bytes for encoding the length of the message.
+  total_size += _VarUInt64ByteSizeNoTag(message_size)
+
+  # The size of the message.
+  total_size += message_size
+  return total_size
+
+
+def TagByteSize(field_number):
+  """Returns the bytes required to serialize a tag with this field number."""
+  # Just pass in type 0, since the type won't affect the tag+type size.
+  return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0))
+
+
+# Private helper function for the *ByteSize() functions above.
+
+def _VarUInt64ByteSizeNoTag(uint64):
+  """Returns the number of bytes required to serialize a single varint
+  using boundary value comparisons. (unrolled loop optimization -WPierce)
+  uint64 must be unsigned.
+  """
+  if uint64 <= 0x7f: return 1
+  if uint64 <= 0x3fff: return 2
+  if uint64 <= 0x1fffff: return 3
+  if uint64 <= 0xfffffff: return 4
+  if uint64 <= 0x7ffffffff: return 5
+  if uint64 <= 0x3ffffffffff: return 6
+  if uint64 <= 0x1ffffffffffff: return 7
+  if uint64 <= 0xffffffffffffff: return 8
+  if uint64 <= 0x7fffffffffffffff: return 9
+  if uint64 > UINT64_MAX:
+    raise message.EncodeError('Value out of range: %d' % uint64)
+  return 10
+
+
+NON_PACKABLE_TYPES = (
+  descriptor.FieldDescriptor.TYPE_STRING,
+  descriptor.FieldDescriptor.TYPE_GROUP,
+  descriptor.FieldDescriptor.TYPE_MESSAGE,
+  descriptor.FieldDescriptor.TYPE_BYTES
+)
+
+
+def IsTypePackable(field_type):
+  """Return true iff packable = true is valid for fields of this type.
+
+  Args:
+    field_type: a FieldDescriptor::Type value.
+
+  Returns:
+    True iff fields of this type are packable.
+  """
+  return field_type not in NON_PACKABLE_TYPES
diff --git a/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format_test.py b/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format_test.py
new file mode 100755
index 0000000..da120f3
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/internal/wire_format_test.py
@@ -0,0 +1,257 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Test for google.protobuf.internal.wire_format."""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+try:
+  import unittest2 as unittest  #PY26
+except ImportError:
+  import unittest
+
+from google.protobuf import message
+from google.protobuf.internal import wire_format
+
+
+class WireFormatTest(unittest.TestCase):
+
+  def testPackTag(self):
+    field_number = 0xabc
+    tag_type = 2
+    self.assertEqual((field_number << 3) | tag_type,
+                     wire_format.PackTag(field_number, tag_type))
+    PackTag = wire_format.PackTag
+    # Number too high.
+    self.assertRaises(message.EncodeError, PackTag, field_number, 6)
+    # Number too low.
+    self.assertRaises(message.EncodeError, PackTag, field_number, -1)
+
+  def testUnpackTag(self):
+    # Test field numbers that will require various varint sizes.
+    for expected_field_number in (1, 15, 16, 2047, 2048):
+      for expected_wire_type in range(6):  # Highest-numbered wiretype is 5.
+        field_number, wire_type = wire_format.UnpackTag(
+            wire_format.PackTag(expected_field_number, expected_wire_type))
+        self.assertEqual(expected_field_number, field_number)
+        self.assertEqual(expected_wire_type, wire_type)
+
+    self.assertRaises(TypeError, wire_format.UnpackTag, None)
+    self.assertRaises(TypeError, wire_format.UnpackTag, 'abc')
+    self.assertRaises(TypeError, wire_format.UnpackTag, 0.0)
+    self.assertRaises(TypeError, wire_format.UnpackTag, object())
+
+  def testZigZagEncode(self):
+    Z = wire_format.ZigZagEncode
+    self.assertEqual(0, Z(0))
+    self.assertEqual(1, Z(-1))
+    self.assertEqual(2, Z(1))
+    self.assertEqual(3, Z(-2))
+    self.assertEqual(4, Z(2))
+    self.assertEqual(0xfffffffe, Z(0x7fffffff))
+    self.assertEqual(0xffffffff, Z(-0x80000000))
+    self.assertEqual(0xfffffffffffffffe, Z(0x7fffffffffffffff))
+    self.assertEqual(0xffffffffffffffff, Z(-0x8000000000000000))
+
+    self.assertRaises(TypeError, Z, None)
+    self.assertRaises(TypeError, Z, 'abcd')
+    self.assertRaises(TypeError, Z, 0.0)
+    self.assertRaises(TypeError, Z, object())
+
+  def testZigZagDecode(self):
+    Z = wire_format.ZigZagDecode
+    self.assertEqual(0, Z(0))
+    self.assertEqual(-1, Z(1))
+    self.assertEqual(1, Z(2))
+    self.assertEqual(-2, Z(3))
+    self.assertEqual(2, Z(4))
+    self.assertEqual(0x7fffffff, Z(0xfffffffe))
+    self.assertEqual(-0x80000000, Z(0xffffffff))
+    self.assertEqual(0x7fffffffffffffff, Z(0xfffffffffffffffe))
+    self.assertEqual(-0x8000000000000000, Z(0xffffffffffffffff))
+
+    self.assertRaises(TypeError, Z, None)
+    self.assertRaises(TypeError, Z, 'abcd')
+    self.assertRaises(TypeError, Z, 0.0)
+    self.assertRaises(TypeError, Z, object())
+
+  def NumericByteSizeTestHelper(self, byte_size_fn, value, expected_value_size):
+    # Use field numbers that cause various byte sizes for the tag information.
+    for field_number, tag_bytes in ((15, 1), (16, 2), (2047, 2), (2048, 3)):
+      expected_size = expected_value_size + tag_bytes
+      actual_size = byte_size_fn(field_number, value)
+      self.assertEqual(expected_size, actual_size,
+                       'byte_size_fn: %s, field_number: %d, value: %r\n'
+                       'Expected: %d, Actual: %d'% (
+          byte_size_fn, field_number, value, expected_size, actual_size))
+
+  def testByteSizeFunctions(self):
+    # Test all numeric *ByteSize() functions.
+    NUMERIC_ARGS = [
+        # Int32ByteSize().
+        [wire_format.Int32ByteSize, 0, 1],
+        [wire_format.Int32ByteSize, 127, 1],
+        [wire_format.Int32ByteSize, 128, 2],
+        [wire_format.Int32ByteSize, -1, 10],
+        # Int64ByteSize().
+        [wire_format.Int64ByteSize, 0, 1],
+        [wire_format.Int64ByteSize, 127, 1],
+        [wire_format.Int64ByteSize, 128, 2],
+        [wire_format.Int64ByteSize, -1, 10],
+        # UInt32ByteSize().
+        [wire_format.UInt32ByteSize, 0, 1],
+        [wire_format.UInt32ByteSize, 127, 1],
+        [wire_format.UInt32ByteSize, 128, 2],
+        [wire_format.UInt32ByteSize, wire_format.UINT32_MAX, 5],
+        # UInt64ByteSize().
+        [wire_format.UInt64ByteSize, 0, 1],
+        [wire_format.UInt64ByteSize, 127, 1],
+        [wire_format.UInt64ByteSize, 128, 2],
+        [wire_format.UInt64ByteSize, wire_format.UINT64_MAX, 10],
+        # SInt32ByteSize().
+        [wire_format.SInt32ByteSize, 0, 1],
+        [wire_format.SInt32ByteSize, -1, 1],
+        [wire_format.SInt32ByteSize, 1, 1],
+        [wire_format.SInt32ByteSize, -63, 1],
+        [wire_format.SInt32ByteSize, 63, 1],
+        [wire_format.SInt32ByteSize, -64, 1],
+        [wire_format.SInt32ByteSize, 64, 2],
+        # SInt64ByteSize().
+        [wire_format.SInt64ByteSize, 0, 1],
+        [wire_format.SInt64ByteSize, -1, 1],
+        [wire_format.SInt64ByteSize, 1, 1],
+        [wire_format.SInt64ByteSize, -63, 1],
+        [wire_format.SInt64ByteSize, 63, 1],
+        [wire_format.SInt64ByteSize, -64, 1],
+        [wire_format.SInt64ByteSize, 64, 2],
+        # Fixed32ByteSize().
+        [wire_format.Fixed32ByteSize, 0, 4],
+        [wire_format.Fixed32ByteSize, wire_format.UINT32_MAX, 4],
+        # Fixed64ByteSize().
+        [wire_format.Fixed64ByteSize, 0, 8],
+        [wire_format.Fixed64ByteSize, wire_format.UINT64_MAX, 8],
+        # SFixed32ByteSize().
+        [wire_format.SFixed32ByteSize, 0, 4],
+        [wire_format.SFixed32ByteSize, wire_format.INT32_MIN, 4],
+        [wire_format.SFixed32ByteSize, wire_format.INT32_MAX, 4],
+        # SFixed64ByteSize().
+        [wire_format.SFixed64ByteSize, 0, 8],
+        [wire_format.SFixed64ByteSize, wire_format.INT64_MIN, 8],
+        [wire_format.SFixed64ByteSize, wire_format.INT64_MAX, 8],
+        # FloatByteSize().
+        [wire_format.FloatByteSize, 0.0, 4],
+        [wire_format.FloatByteSize, 1000000000.0, 4],
+        [wire_format.FloatByteSize, -1000000000.0, 4],
+        # DoubleByteSize().
+        [wire_format.DoubleByteSize, 0.0, 8],
+        [wire_format.DoubleByteSize, 1000000000.0, 8],
+        [wire_format.DoubleByteSize, -1000000000.0, 8],
+        # BoolByteSize().
+        [wire_format.BoolByteSize, False, 1],
+        [wire_format.BoolByteSize, True, 1],
+        # EnumByteSize().
+        [wire_format.EnumByteSize, 0, 1],
+        [wire_format.EnumByteSize, 127, 1],
+        [wire_format.EnumByteSize, 128, 2],
+        [wire_format.EnumByteSize, wire_format.UINT32_MAX, 5],
+        ]
+    for args in NUMERIC_ARGS:
+      self.NumericByteSizeTestHelper(*args)
+
+    # Test strings and bytes.
+    for byte_size_fn in (wire_format.StringByteSize, wire_format.BytesByteSize):
+      # 1 byte for tag, 1 byte for length, 3 bytes for contents.
+      self.assertEqual(5, byte_size_fn(10, 'abc'))
+      # 2 bytes for tag, 1 byte for length, 3 bytes for contents.
+      self.assertEqual(6, byte_size_fn(16, 'abc'))
+      # 2 bytes for tag, 2 bytes for length, 128 bytes for contents.
+      self.assertEqual(132, byte_size_fn(16, 'a' * 128))
+
+    # Test UTF-8 string byte size calculation.
+    # 1 byte for tag, 1 byte for length, 8 bytes for content.
+    self.assertEqual(10, wire_format.StringByteSize(
+        5, b'\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'.decode('utf-8')))
+
+    class MockMessage(object):
+      def __init__(self, byte_size):
+        self.byte_size = byte_size
+      def ByteSize(self):
+        return self.byte_size
+
+    message_byte_size = 10
+    mock_message = MockMessage(byte_size=message_byte_size)
+    # Test groups.
+    # (2 * 1) bytes for begin and end tags, plus message_byte_size.
+    self.assertEqual(2 + message_byte_size,
+                     wire_format.GroupByteSize(1, mock_message))
+    # (2 * 2) bytes for begin and end tags, plus message_byte_size.
+    self.assertEqual(4 + message_byte_size,
+                     wire_format.GroupByteSize(16, mock_message))
+
+    # Test messages.
+    # 1 byte for tag, plus 1 byte for length, plus contents.
+    self.assertEqual(2 + mock_message.byte_size,
+                     wire_format.MessageByteSize(1, mock_message))
+    # 2 bytes for tag, plus 1 byte for length, plus contents.
+    self.assertEqual(3 + mock_message.byte_size,
+                     wire_format.MessageByteSize(16, mock_message))
+    # 2 bytes for tag, plus 2 bytes for length, plus contents.
+    mock_message.byte_size = 128
+    self.assertEqual(4 + mock_message.byte_size,
+                     wire_format.MessageByteSize(16, mock_message))
+
+
+    # Test message set item byte size.
+    # 4 bytes for tags, plus 1 byte for length, plus 1 byte for type_id,
+    # plus contents.
+    mock_message.byte_size = 10
+    self.assertEqual(mock_message.byte_size + 6,
+                     wire_format.MessageSetItemByteSize(1, mock_message))
+
+    # 4 bytes for tags, plus 2 bytes for length, plus 1 byte for type_id,
+    # plus contents.
+    mock_message.byte_size = 128
+    self.assertEqual(mock_message.byte_size + 7,
+                     wire_format.MessageSetItemByteSize(1, mock_message))
+
+    # 4 bytes for tags, plus 2 bytes for length, plus 2 byte for type_id,
+    # plus contents.
+    self.assertEqual(mock_message.byte_size + 8,
+                     wire_format.MessageSetItemByteSize(128, mock_message))
+
+    # Too-long varint.
+    self.assertRaises(message.EncodeError,
+                      wire_format.UInt64ByteSize, 1, 1 << 128)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/python/google/protobuf/json_format.py b/src/third_party/protobuf-3/python/google/protobuf/json_format.py
new file mode 100644
index 0000000..7921556
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/json_format.py
@@ -0,0 +1,645 @@
+# 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.
+
+"""Contains routines for printing protocol messages in JSON format.
+
+Simple usage example:
+
+  # Create a proto object and serialize it to a json format string.
+  message = my_proto_pb2.MyMessage(foo='bar')
+  json_string = json_format.MessageToJson(message)
+
+  # Parse a json format string to proto object.
+  message = json_format.Parse(json_string, my_proto_pb2.MyMessage())
+"""
+
+__author__ = 'jieluo@google.com (Jie Luo)'
+
+import base64
+import json
+import math
+import six
+import sys
+
+from google.protobuf import descriptor
+from google.protobuf import symbol_database
+
+_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
+_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32,
+                        descriptor.FieldDescriptor.CPPTYPE_UINT32,
+                        descriptor.FieldDescriptor.CPPTYPE_INT64,
+                        descriptor.FieldDescriptor.CPPTYPE_UINT64])
+_INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64,
+                          descriptor.FieldDescriptor.CPPTYPE_UINT64])
+_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT,
+                          descriptor.FieldDescriptor.CPPTYPE_DOUBLE])
+_INFINITY = 'Infinity'
+_NEG_INFINITY = '-Infinity'
+_NAN = 'NaN'
+
+
+class Error(Exception):
+  """Top-level module error for json_format."""
+
+
+class SerializeToJsonError(Error):
+  """Thrown if serialization to JSON fails."""
+
+
+class ParseError(Error):
+  """Thrown in case of parsing error."""
+
+
+def MessageToJson(message, including_default_value_fields=False):
+  """Converts protobuf message to JSON format.
+
+  Args:
+    message: The protocol buffers message instance to serialize.
+    including_default_value_fields: If True, singular primitive fields,
+        repeated fields, and map fields will always be serialized.  If
+        False, only serialize non-empty fields.  Singular message fields
+        and oneof fields are not affected by this option.
+
+  Returns:
+    A string containing the JSON formatted protocol buffer message.
+  """
+  js = _MessageToJsonObject(message, including_default_value_fields)
+  return json.dumps(js, indent=2)
+
+
+def _MessageToJsonObject(message, including_default_value_fields):
+  """Converts message to an object according to Proto3 JSON Specification."""
+  message_descriptor = message.DESCRIPTOR
+  full_name = message_descriptor.full_name
+  if _IsWrapperMessage(message_descriptor):
+    return _WrapperMessageToJsonObject(message)
+  if full_name in _WKTJSONMETHODS:
+    return _WKTJSONMETHODS[full_name][0](
+        message, including_default_value_fields)
+  js = {}
+  return _RegularMessageToJsonObject(
+      message, js, including_default_value_fields)
+
+
+def _IsMapEntry(field):
+  return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
+          field.message_type.has_options and
+          field.message_type.GetOptions().map_entry)
+
+
+def _RegularMessageToJsonObject(message, js, including_default_value_fields):
+  """Converts normal message according to Proto3 JSON Specification."""
+  fields = message.ListFields()
+  include_default = including_default_value_fields
+
+  try:
+    for field, value in fields:
+      name = field.camelcase_name
+      if _IsMapEntry(field):
+        # Convert a map field.
+        v_field = field.message_type.fields_by_name['value']
+        js_map = {}
+        for key in value:
+          if isinstance(key, bool):
+            if key:
+              recorded_key = 'true'
+            else:
+              recorded_key = 'false'
+          else:
+            recorded_key = key
+          js_map[recorded_key] = _FieldToJsonObject(
+              v_field, value[key], including_default_value_fields)
+        js[name] = js_map
+      elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        # Convert a repeated field.
+        js[name] = [_FieldToJsonObject(field, k, include_default)
+                    for k in value]
+      else:
+        js[name] = _FieldToJsonObject(field, value, include_default)
+
+    # Serialize default value if including_default_value_fields is True.
+    if including_default_value_fields:
+      message_descriptor = message.DESCRIPTOR
+      for field in message_descriptor.fields:
+        # Singular message fields and oneof fields will not be affected.
+        if ((field.label != descriptor.FieldDescriptor.LABEL_REPEATED and
+             field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE) or
+            field.containing_oneof):
+          continue
+        name = field.camelcase_name
+        if name in js:
+          # Skip the field which has been serailized already.
+          continue
+        if _IsMapEntry(field):
+          js[name] = {}
+        elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+          js[name] = []
+        else:
+          js[name] = _FieldToJsonObject(field, field.default_value)
+
+  except ValueError as e:
+    raise SerializeToJsonError(
+        'Failed to serialize {0} field: {1}.'.format(field.name, e))
+
+  return js
+
+
+def _FieldToJsonObject(
+    field, value, including_default_value_fields=False):
+  """Converts field value according to Proto3 JSON Specification."""
+  if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+    return _MessageToJsonObject(value, including_default_value_fields)
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
+    enum_value = field.enum_type.values_by_number.get(value, None)
+    if enum_value is not None:
+      return enum_value.name
+    else:
+      raise SerializeToJsonError('Enum field contains an integer value '
+                                 'which can not mapped to an enum value.')
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
+    if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
+      # Use base64 Data encoding for bytes
+      return base64.b64encode(value).decode('utf-8')
+    else:
+      return value
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
+    return bool(value)
+  elif field.cpp_type in _INT64_TYPES:
+    return str(value)
+  elif field.cpp_type in _FLOAT_TYPES:
+    if math.isinf(value):
+      if value < 0.0:
+        return _NEG_INFINITY
+      else:
+        return _INFINITY
+    if math.isnan(value):
+      return _NAN
+  return value
+
+
+def _AnyMessageToJsonObject(message, including_default):
+  """Converts Any message according to Proto3 JSON Specification."""
+  if not message.ListFields():
+    return {}
+  js = {}
+  type_url = message.type_url
+  js['@type'] = type_url
+  sub_message = _CreateMessageFromTypeUrl(type_url)
+  sub_message.ParseFromString(message.value)
+  message_descriptor = sub_message.DESCRIPTOR
+  full_name = message_descriptor.full_name
+  if _IsWrapperMessage(message_descriptor):
+    js['value'] = _WrapperMessageToJsonObject(sub_message)
+    return js
+  if full_name in _WKTJSONMETHODS:
+    js['value'] = _WKTJSONMETHODS[full_name][0](sub_message, including_default)
+    return js
+  return _RegularMessageToJsonObject(sub_message, js, including_default)
+
+
+def _CreateMessageFromTypeUrl(type_url):
+  # TODO(jieluo): Should add a way that users can register the type resolver
+  # instead of the default one.
+  db = symbol_database.Default()
+  type_name = type_url.split('/')[-1]
+  try:
+    message_descriptor = db.pool.FindMessageTypeByName(type_name)
+  except KeyError:
+    raise TypeError(
+        'Can not find message descriptor by type_url: {0}.'.format(type_url))
+  message_class = db.GetPrototype(message_descriptor)
+  return message_class()
+
+
+def _GenericMessageToJsonObject(message, unused_including_default):
+  """Converts message by ToJsonString according to Proto3 JSON Specification."""
+  # Duration, Timestamp and FieldMask have ToJsonString method to do the
+  # convert. Users can also call the method directly.
+  return message.ToJsonString()
+
+
+def _ValueMessageToJsonObject(message, unused_including_default=False):
+  """Converts Value message according to Proto3 JSON Specification."""
+  which = message.WhichOneof('kind')
+  # If the Value message is not set treat as null_value when serialize
+  # to JSON. The parse back result will be different from original message.
+  if which is None or which == 'null_value':
+    return None
+  if which == 'list_value':
+    return _ListValueMessageToJsonObject(message.list_value)
+  if which == 'struct_value':
+    value = message.struct_value
+  else:
+    value = getattr(message, which)
+  oneof_descriptor = message.DESCRIPTOR.fields_by_name[which]
+  return _FieldToJsonObject(oneof_descriptor, value)
+
+
+def _ListValueMessageToJsonObject(message, unused_including_default=False):
+  """Converts ListValue message according to Proto3 JSON Specification."""
+  return [_ValueMessageToJsonObject(value)
+          for value in message.values]
+
+
+def _StructMessageToJsonObject(message, unused_including_default=False):
+  """Converts Struct message according to Proto3 JSON Specification."""
+  fields = message.fields
+  ret = {}
+  for key in fields:
+    ret[key] = _ValueMessageToJsonObject(fields[key])
+  return ret
+
+
+def _IsWrapperMessage(message_descriptor):
+  return message_descriptor.file.name == 'google/protobuf/wrappers.proto'
+
+
+def _WrapperMessageToJsonObject(message):
+  return _FieldToJsonObject(
+      message.DESCRIPTOR.fields_by_name['value'], message.value)
+
+
+def _DuplicateChecker(js):
+  result = {}
+  for name, value in js:
+    if name in result:
+      raise ParseError('Failed to load JSON: duplicate key {0}.'.format(name))
+    result[name] = value
+  return result
+
+
+def Parse(text, message):
+  """Parses a JSON representation of a protocol message into a message.
+
+  Args:
+    text: Message JSON representation.
+    message: A protocol beffer message to merge into.
+
+  Returns:
+    The same message passed as argument.
+
+  Raises::
+    ParseError: On JSON parsing problems.
+  """
+  if not isinstance(text, six.text_type): text = text.decode('utf-8')
+  try:
+    if sys.version_info < (2, 7):
+      # object_pair_hook is not supported before python2.7
+      js = json.loads(text)
+    else:
+      js = json.loads(text, object_pairs_hook=_DuplicateChecker)
+  except ValueError as e:
+    raise ParseError('Failed to load JSON: {0}.'.format(str(e)))
+  _ConvertMessage(js, message)
+  return message
+
+
+def _ConvertFieldValuePair(js, message):
+  """Convert field value pairs into regular message.
+
+  Args:
+    js: A JSON object to convert the field value pairs.
+    message: A regular protocol message to record the data.
+
+  Raises:
+    ParseError: In case of problems converting.
+  """
+  names = []
+  message_descriptor = message.DESCRIPTOR
+  for name in js:
+    try:
+      field = message_descriptor.fields_by_camelcase_name.get(name, None)
+      if not field:
+        raise ParseError(
+            'Message type "{0}" has no field named "{1}".'.format(
+                message_descriptor.full_name, name))
+      if name in names:
+        raise ParseError(
+            'Message type "{0}" should not have multiple "{1}" fields.'.format(
+                message.DESCRIPTOR.full_name, name))
+      names.append(name)
+      # Check no other oneof field is parsed.
+      if field.containing_oneof is not None:
+        oneof_name = field.containing_oneof.name
+        if oneof_name in names:
+          raise ParseError('Message type "{0}" should not have multiple "{1}" '
+                           'oneof fields.'.format(
+                               message.DESCRIPTOR.full_name, oneof_name))
+        names.append(oneof_name)
+
+      value = js[name]
+      if value is None:
+        message.ClearField(field.name)
+        continue
+
+      # Parse field value.
+      if _IsMapEntry(field):
+        message.ClearField(field.name)
+        _ConvertMapFieldValue(value, message, field)
+      elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        message.ClearField(field.name)
+        if not isinstance(value, list):
+          raise ParseError('repeated field {0} must be in [] which is '
+                           '{1}.'.format(name, value))
+        if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+          # Repeated message field.
+          for item in value:
+            sub_message = getattr(message, field.name).add()
+            # None is a null_value in Value.
+            if (item is None and
+                sub_message.DESCRIPTOR.full_name != 'google.protobuf.Value'):
+              raise ParseError('null is not allowed to be used as an element'
+                               ' in a repeated field.')
+            _ConvertMessage(item, sub_message)
+        else:
+          # Repeated scalar field.
+          for item in value:
+            if item is None:
+              raise ParseError('null is not allowed to be used as an element'
+                               ' in a repeated field.')
+            getattr(message, field.name).append(
+                _ConvertScalarFieldValue(item, field))
+      elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+        sub_message = getattr(message, field.name)
+        _ConvertMessage(value, sub_message)
+      else:
+        setattr(message, field.name, _ConvertScalarFieldValue(value, field))
+    except ParseError as e:
+      if field and field.containing_oneof is None:
+        raise ParseError('Failed to parse {0} field: {1}'.format(name, e))
+      else:
+        raise ParseError(str(e))
+    except ValueError as e:
+      raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
+    except TypeError as e:
+      raise ParseError('Failed to parse {0} field: {1}.'.format(name, e))
+
+
+def _ConvertMessage(value, message):
+  """Convert a JSON object into a message.
+
+  Args:
+    value: A JSON object.
+    message: A WKT or regular protocol message to record the data.
+
+  Raises:
+    ParseError: In case of convert problems.
+  """
+  message_descriptor = message.DESCRIPTOR
+  full_name = message_descriptor.full_name
+  if _IsWrapperMessage(message_descriptor):
+    _ConvertWrapperMessage(value, message)
+  elif full_name in _WKTJSONMETHODS:
+    _WKTJSONMETHODS[full_name][1](value, message)
+  else:
+    _ConvertFieldValuePair(value, message)
+
+
+def _ConvertAnyMessage(value, message):
+  """Convert a JSON representation into Any message."""
+  if isinstance(value, dict) and not value:
+    return
+  try:
+    type_url = value['@type']
+  except KeyError:
+    raise ParseError('@type is missing when parsing any message.')
+
+  sub_message = _CreateMessageFromTypeUrl(type_url)
+  message_descriptor = sub_message.DESCRIPTOR
+  full_name = message_descriptor.full_name
+  if _IsWrapperMessage(message_descriptor):
+    _ConvertWrapperMessage(value['value'], sub_message)
+  elif full_name in _WKTJSONMETHODS:
+    _WKTJSONMETHODS[full_name][1](value['value'], sub_message)
+  else:
+    del value['@type']
+    _ConvertFieldValuePair(value, sub_message)
+  # Sets Any message
+  message.value = sub_message.SerializeToString()
+  message.type_url = type_url
+
+
+def _ConvertGenericMessage(value, message):
+  """Convert a JSON representation into message with FromJsonString."""
+  # Durantion, Timestamp, FieldMask have FromJsonString method to do the
+  # convert. Users can also call the method directly.
+  message.FromJsonString(value)
+
+
+_INT_OR_FLOAT = six.integer_types + (float,)
+
+
+def _ConvertValueMessage(value, message):
+  """Convert a JSON representation into Value message."""
+  if isinstance(value, dict):
+    _ConvertStructMessage(value, message.struct_value)
+  elif isinstance(value, list):
+    _ConvertListValueMessage(value, message.list_value)
+  elif value is None:
+    message.null_value = 0
+  elif isinstance(value, bool):
+    message.bool_value = value
+  elif isinstance(value, six.string_types):
+    message.string_value = value
+  elif isinstance(value, _INT_OR_FLOAT):
+    message.number_value = value
+  else:
+    raise ParseError('Unexpected type for Value message.')
+
+
+def _ConvertListValueMessage(value, message):
+  """Convert a JSON representation into ListValue message."""
+  if not isinstance(value, list):
+    raise ParseError(
+        'ListValue must be in [] which is {0}.'.format(value))
+  message.ClearField('values')
+  for item in value:
+    _ConvertValueMessage(item, message.values.add())
+
+
+def _ConvertStructMessage(value, message):
+  """Convert a JSON representation into Struct message."""
+  if not isinstance(value, dict):
+    raise ParseError(
+        'Struct must be in a dict which is {0}.'.format(value))
+  for key in value:
+    _ConvertValueMessage(value[key], message.fields[key])
+  return
+
+
+def _ConvertWrapperMessage(value, message):
+  """Convert a JSON representation into Wrapper message."""
+  field = message.DESCRIPTOR.fields_by_name['value']
+  setattr(message, 'value', _ConvertScalarFieldValue(value, field))
+
+
+def _ConvertMapFieldValue(value, message, field):
+  """Convert map field value for a message map field.
+
+  Args:
+    value: A JSON object to convert the map field value.
+    message: A protocol message to record the converted data.
+    field: The descriptor of the map field to be converted.
+
+  Raises:
+    ParseError: In case of convert problems.
+  """
+  if not isinstance(value, dict):
+    raise ParseError(
+        'Map field {0} must be in a dict which is {1}.'.format(
+            field.name, value))
+  key_field = field.message_type.fields_by_name['key']
+  value_field = field.message_type.fields_by_name['value']
+  for key in value:
+    key_value = _ConvertScalarFieldValue(key, key_field, True)
+    if value_field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+      _ConvertMessage(value[key], getattr(message, field.name)[key_value])
+    else:
+      getattr(message, field.name)[key_value] = _ConvertScalarFieldValue(
+          value[key], value_field)
+
+
+def _ConvertScalarFieldValue(value, field, require_str=False):
+  """Convert a single scalar field value.
+
+  Args:
+    value: A scalar value to convert the scalar field value.
+    field: The descriptor of the field to convert.
+    require_str: If True, the field value must be a str.
+
+  Returns:
+    The converted scalar field value
+
+  Raises:
+    ParseError: In case of convert problems.
+  """
+  if field.cpp_type in _INT_TYPES:
+    return _ConvertInteger(value)
+  elif field.cpp_type in _FLOAT_TYPES:
+    return _ConvertFloat(value)
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
+    return _ConvertBool(value, require_str)
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
+    if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
+      return base64.b64decode(value)
+    else:
+      return value
+  elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
+    # Convert an enum value.
+    enum_value = field.enum_type.values_by_name.get(value, None)
+    if enum_value is None:
+      raise ParseError(
+          'Enum value must be a string literal with double quotes. '
+          'Type "{0}" has no value named {1}.'.format(
+              field.enum_type.full_name, value))
+    return enum_value.number
+
+
+def _ConvertInteger(value):
+  """Convert an integer.
+
+  Args:
+    value: A scalar value to convert.
+
+  Returns:
+    The integer value.
+
+  Raises:
+    ParseError: If an integer couldn't be consumed.
+  """
+  if isinstance(value, float):
+    raise ParseError('Couldn\'t parse integer: {0}.'.format(value))
+
+  if isinstance(value, six.text_type) and value.find(' ') != -1:
+    raise ParseError('Couldn\'t parse integer: "{0}".'.format(value))
+
+  return int(value)
+
+
+def _ConvertFloat(value):
+  """Convert an floating point number."""
+  if value == 'nan':
+    raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.')
+  try:
+    # Assume Python compatible syntax.
+    return float(value)
+  except ValueError:
+    # Check alternative spellings.
+    if value == _NEG_INFINITY:
+      return float('-inf')
+    elif value == _INFINITY:
+      return float('inf')
+    elif value == _NAN:
+      return float('nan')
+    else:
+      raise ParseError('Couldn\'t parse float: {0}.'.format(value))
+
+
+def _ConvertBool(value, require_str):
+  """Convert a boolean value.
+
+  Args:
+    value: A scalar value to convert.
+    require_str: If True, value must be a str.
+
+  Returns:
+    The bool parsed.
+
+  Raises:
+    ParseError: If a boolean value couldn't be consumed.
+  """
+  if require_str:
+    if value == 'true':
+      return True
+    elif value == 'false':
+      return False
+    else:
+      raise ParseError('Expected "true" or "false", not {0}.'.format(value))
+
+  if not isinstance(value, bool):
+    raise ParseError('Expected true or false without quotes.')
+  return value
+
+_WKTJSONMETHODS = {
+    'google.protobuf.Any': [_AnyMessageToJsonObject,
+                            _ConvertAnyMessage],
+    'google.protobuf.Duration': [_GenericMessageToJsonObject,
+                                 _ConvertGenericMessage],
+    'google.protobuf.FieldMask': [_GenericMessageToJsonObject,
+                                  _ConvertGenericMessage],
+    'google.protobuf.ListValue': [_ListValueMessageToJsonObject,
+                                  _ConvertListValueMessage],
+    'google.protobuf.Struct': [_StructMessageToJsonObject,
+                               _ConvertStructMessage],
+    'google.protobuf.Timestamp': [_GenericMessageToJsonObject,
+                                  _ConvertGenericMessage],
+    'google.protobuf.Value': [_ValueMessageToJsonObject,
+                              _ConvertValueMessage]
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/message.py b/src/third_party/protobuf-3/python/google/protobuf/message.py
new file mode 100755
index 0000000..606f735
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/message.py
@@ -0,0 +1,295 @@
+# 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.
+
+# TODO(robinson): We should just make these methods all "pure-virtual" and move
+# all implementation out, into reflection.py for now.
+
+
+"""Contains an abstract base class for protocol messages."""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+class Error(Exception): pass
+class DecodeError(Error): pass
+class EncodeError(Error): pass
+
+
+class Message(object):
+
+  """Abstract base class for protocol messages.
+
+  Protocol message classes are almost always generated by the protocol
+  compiler.  These generated types subclass Message and implement the methods
+  shown below.
+
+  TODO(robinson): Link to an HTML document here.
+
+  TODO(robinson): Document that instances of this class will also
+  have an Extensions attribute with __getitem__ and __setitem__.
+  Again, not sure how to best convey this.
+
+  TODO(robinson): Document that the class must also have a static
+    RegisterExtension(extension_field) method.
+    Not sure how to best express at this point.
+  """
+
+  # TODO(robinson): Document these fields and methods.
+
+  __slots__ = []
+
+  DESCRIPTOR = None
+
+  def __deepcopy__(self, memo=None):
+    clone = type(self)()
+    clone.MergeFrom(self)
+    return clone
+
+  def __eq__(self, other_msg):
+    """Recursively compares two messages by value and structure."""
+    raise NotImplementedError
+
+  def __ne__(self, other_msg):
+    # Can't just say self != other_msg, since that would infinitely recurse. :)
+    return not self == other_msg
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  def __str__(self):
+    """Outputs a human-readable representation of the message."""
+    raise NotImplementedError
+
+  def __unicode__(self):
+    """Outputs a human-readable representation of the message."""
+    raise NotImplementedError
+
+  def MergeFrom(self, other_msg):
+    """Merges the contents of the specified message into current message.
+
+    This method merges the contents of the specified message into the current
+    message. Singular fields that are set in the specified message overwrite
+    the corresponding fields in the current message. Repeated fields are
+    appended. Singular sub-messages and groups are recursively merged.
+
+    Args:
+      other_msg: Message to merge into the current message.
+    """
+    raise NotImplementedError
+
+  def CopyFrom(self, other_msg):
+    """Copies the content of the specified message into the current message.
+
+    The method clears the current message and then merges the specified
+    message using MergeFrom.
+
+    Args:
+      other_msg: Message to copy into the current one.
+    """
+    if self is other_msg:
+      return
+    self.Clear()
+    self.MergeFrom(other_msg)
+
+  def Clear(self):
+    """Clears all data that was set in the message."""
+    raise NotImplementedError
+
+  def SetInParent(self):
+    """Mark this as present in the parent.
+
+    This normally happens automatically when you assign a field of a
+    sub-message, but sometimes you want to make the sub-message
+    present while keeping it empty.  If you find yourself using this,
+    you may want to reconsider your design."""
+    raise NotImplementedError
+
+  def IsInitialized(self):
+    """Checks if the message is initialized.
+
+    Returns:
+      The method returns True if the message is initialized (i.e. all of its
+      required fields are set).
+    """
+    raise NotImplementedError
+
+  # TODO(robinson): MergeFromString() should probably return None and be
+  # implemented in terms of a helper that returns the # of bytes read.  Our
+  # deserialization routines would use the helper when recursively
+  # deserializing, but the end user would almost always just want the no-return
+  # MergeFromString().
+
+  def MergeFromString(self, serialized):
+    """Merges serialized protocol buffer data into this message.
+
+    When we find a field in |serialized| that is already present
+    in this message:
+      - If it's a "repeated" field, we append to the end of our list.
+      - Else, if it's a scalar, we overwrite our field.
+      - Else, (it's a nonrepeated composite), we recursively merge
+        into the existing composite.
+
+    TODO(robinson): Document handling of unknown fields.
+
+    Args:
+      serialized: Any object that allows us to call buffer(serialized)
+        to access a string of bytes using the buffer interface.
+
+    TODO(robinson): When we switch to a helper, this will return None.
+
+    Returns:
+      The number of bytes read from |serialized|.
+      For non-group messages, this will always be len(serialized),
+      but for messages which are actually groups, this will
+      generally be less than len(serialized), since we must
+      stop when we reach an END_GROUP tag.  Note that if
+      we *do* stop because of an END_GROUP tag, the number
+      of bytes returned does not include the bytes
+      for the END_GROUP tag information.
+    """
+    raise NotImplementedError
+
+  def ParseFromString(self, serialized):
+    """Parse serialized protocol buffer data into this message.
+
+    Like MergeFromString(), except we clear the object first and
+    do not return the value that MergeFromString returns.
+    """
+    self.Clear()
+    self.MergeFromString(serialized)
+
+  def SerializeToString(self):
+    """Serializes the protocol message to a binary string.
+
+    Returns:
+      A binary string representation of the message if all of the required
+      fields in the message are set (i.e. the message is initialized).
+
+    Raises:
+      message.EncodeError if the message isn't initialized.
+    """
+    raise NotImplementedError
+
+  def SerializePartialToString(self):
+    """Serializes the protocol message to a binary string.
+
+    This method is similar to SerializeToString but doesn't check if the
+    message is initialized.
+
+    Returns:
+      A string representation of the partial message.
+    """
+    raise NotImplementedError
+
+  # TODO(robinson): Decide whether we like these better
+  # than auto-generated has_foo() and clear_foo() methods
+  # on the instances themselves.  This way is less consistent
+  # with C++, but it makes reflection-type access easier and
+  # reduces the number of magically autogenerated things.
+  #
+  # TODO(robinson): Be sure to document (and test) exactly
+  # which field names are accepted here.  Are we case-sensitive?
+  # What do we do with fields that share names with Python keywords
+  # like 'lambda' and 'yield'?
+  #
+  # nnorwitz says:
+  # """
+  # Typically (in python), an underscore is appended to names that are
+  # keywords. So they would become lambda_ or yield_.
+  # """
+  def ListFields(self):
+    """Returns a list of (FieldDescriptor, value) tuples for all
+    fields in the message which are not empty.  A singular field is non-empty
+    if HasField() would return true, and a repeated field is non-empty if
+    it contains at least one element.  The fields are ordered by field
+    number"""
+    raise NotImplementedError
+
+  def HasField(self, field_name):
+    """Checks if a certain field is set for the message, or if any field inside
+    a oneof group is set.  Note that if the field_name is not defined in the
+    message descriptor, ValueError will be raised."""
+    raise NotImplementedError
+
+  def ClearField(self, field_name):
+    """Clears the contents of a given field, or the field set inside a oneof
+    group.  If the name neither refers to a defined field or oneof group,
+    ValueError is raised."""
+    raise NotImplementedError
+
+  def WhichOneof(self, oneof_group):
+    """Returns the name of the field that is set inside a oneof group, or
+    None if no field is set.  If no group with the given name exists, ValueError
+    will be raised."""
+    raise NotImplementedError
+
+  def HasExtension(self, extension_handle):
+    raise NotImplementedError
+
+  def ClearExtension(self, extension_handle):
+    raise NotImplementedError
+
+  def DiscardUnknownFields(self):
+    raise NotImplementedError
+
+  def ByteSize(self):
+    """Returns the serialized size of this message.
+    Recursively calls ByteSize() on all contained messages.
+    """
+    raise NotImplementedError
+
+  def _SetListener(self, message_listener):
+    """Internal method used by the protocol message implementation.
+    Clients should not call this directly.
+
+    Sets a listener that this message will call on certain state transitions.
+
+    The purpose of this method is to register back-edges from children to
+    parents at runtime, for the purpose of setting "has" bits and
+    byte-size-dirty bits in the parent and ancestor objects whenever a child or
+    descendant object is modified.
+
+    If the client wants to disconnect this Message from the object tree, she
+    explicitly sets callback to None.
+
+    If message_listener is None, unregisters any existing listener.  Otherwise,
+    message_listener must implement the MessageListener interface in
+    internal/message_listener.py, and we discard any listener registered
+    via a previous _SetListener() call.
+    """
+    raise NotImplementedError
+
+  def __getstate__(self):
+    """Support the pickle protocol."""
+    return dict(serialized=self.SerializePartialToString())
+
+  def __setstate__(self, state):
+    """Support the pickle protocol."""
+    self.__init__()
+    self.ParseFromString(state['serialized'])
diff --git a/src/third_party/protobuf-3/python/google/protobuf/message_factory.py b/src/third_party/protobuf-3/python/google/protobuf/message_factory.py
new file mode 100644
index 0000000..1b059d1
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/message_factory.py
@@ -0,0 +1,147 @@
+# 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.
+
+"""Provides a factory class for generating dynamic messages.
+
+The easiest way to use this class is if you have access to the FileDescriptor
+protos containing the messages you want to create you can just do the following:
+
+message_classes = message_factory.GetMessages(iterable_of_file_descriptors)
+my_proto_instance = message_classes['some.proto.package.MessageName']()
+"""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor_pool
+from google.protobuf import message
+from google.protobuf import reflection
+
+
+class MessageFactory(object):
+  """Factory for creating Proto2 messages from descriptors in a pool."""
+
+  def __init__(self, pool=None):
+    """Initializes a new factory."""
+    self.pool = pool or descriptor_pool.DescriptorPool()
+
+    # local cache of all classes built from protobuf descriptors
+    self._classes = {}
+
+  def GetPrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Passing a descriptor with a fully qualified name matching a previous
+    invocation will cause the same class to be returned.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+    if descriptor.full_name not in self._classes:
+      descriptor_name = descriptor.name
+      if str is bytes:  # PY2
+        descriptor_name = descriptor.name.encode('ascii', 'ignore')
+      result_class = reflection.GeneratedProtocolMessageType(
+          descriptor_name,
+          (message.Message,),
+          {'DESCRIPTOR': descriptor, '__module__': None})
+          # If module not set, it wrongly points to the reflection.py module.
+      self._classes[descriptor.full_name] = result_class
+      for field in descriptor.fields:
+        if field.message_type:
+          self.GetPrototype(field.message_type)
+      for extension in result_class.DESCRIPTOR.extensions:
+        if extension.containing_type.full_name not in self._classes:
+          self.GetPrototype(extension.containing_type)
+        extended_class = self._classes[extension.containing_type.full_name]
+        extended_class.RegisterExtension(extension)
+    return self._classes[descriptor.full_name]
+
+  def GetMessages(self, files):
+    """Gets all the messages from a specified file.
+
+    This will find and resolve dependencies, failing if the descriptor
+    pool cannot satisfy them.
+
+    Args:
+      files: The file names to extract messages from.
+
+    Returns:
+      A dictionary mapping proto names to the message classes. This will include
+      any dependent messages as well as any messages defined in the same file as
+      a specified message.
+    """
+    result = {}
+    for file_name in files:
+      file_desc = self.pool.FindFileByName(file_name)
+      for name, msg in file_desc.message_types_by_name.items():
+        if file_desc.package:
+          full_name = '.'.join([file_desc.package, name])
+        else:
+          full_name = msg.name
+        result[full_name] = self.GetPrototype(
+            self.pool.FindMessageTypeByName(full_name))
+
+      # While the extension FieldDescriptors are created by the descriptor pool,
+      # the python classes created in the factory need them to be registered
+      # explicitly, which is done below.
+      #
+      # The call to RegisterExtension will specifically check if the
+      # extension was already registered on the object and either
+      # ignore the registration if the original was the same, or raise
+      # an error if they were different.
+
+      for name, extension in file_desc.extensions_by_name.items():
+        if extension.containing_type.full_name not in self._classes:
+          self.GetPrototype(extension.containing_type)
+        extended_class = self._classes[extension.containing_type.full_name]
+        extended_class.RegisterExtension(extension)
+    return result
+
+
+_FACTORY = MessageFactory()
+
+
+def GetMessages(file_protos):
+  """Builds a dictionary of all the messages available in a set of files.
+
+  Args:
+    file_protos: A sequence of file protos to build messages out of.
+
+  Returns:
+    A dictionary mapping proto names to the message classes. This will include
+    any dependent messages as well as any messages defined in the same file as
+    a specified message.
+  """
+  for file_proto in file_protos:
+    _FACTORY.pool.Add(file_proto)
+  return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos])
diff --git a/src/third_party/protobuf-3/python/google/protobuf/proto_builder.py b/src/third_party/protobuf-3/python/google/protobuf/proto_builder.py
new file mode 100644
index 0000000..736caed
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/proto_builder.py
@@ -0,0 +1,130 @@
+# 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.
+
+"""Dynamic Protobuf class creator."""
+
+try:
+    from collections import OrderedDict
+except ImportError:
+    from ordereddict import OrderedDict  #PY26
+import hashlib
+import os
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import message_factory
+
+
+def _GetMessageFromFactory(factory, full_name):
+  """Get a proto class from the MessageFactory by name.
+
+  Args:
+    factory: a MessageFactory instance.
+    full_name: str, the fully qualified name of the proto type.
+  Returns:
+    A class, for the type identified by full_name.
+  Raises:
+    KeyError, if the proto is not found in the factory's descriptor pool.
+  """
+  proto_descriptor = factory.pool.FindMessageTypeByName(full_name)
+  proto_cls = factory.GetPrototype(proto_descriptor)
+  return proto_cls
+
+
+def MakeSimpleProtoClass(fields, full_name=None, pool=None):
+  """Create a Protobuf class whose fields are basic types.
+
+  Note: this doesn't validate field names!
+
+  Args:
+    fields: dict of {name: field_type} mappings for each field in the proto. If
+        this is an OrderedDict the order will be maintained, otherwise the
+        fields will be sorted by name.
+    full_name: optional str, the fully-qualified name of the proto type.
+    pool: optional DescriptorPool instance.
+  Returns:
+    a class, the new protobuf class with a FileDescriptor.
+  """
+  factory = message_factory.MessageFactory(pool=pool)
+
+  if full_name is not None:
+    try:
+      proto_cls = _GetMessageFromFactory(factory, full_name)
+      return proto_cls
+    except KeyError:
+      # The factory's DescriptorPool doesn't know about this class yet.
+      pass
+
+  # Get a list of (name, field_type) tuples from the fields dict. If fields was
+  # an OrderedDict we keep the order, but otherwise we sort the field to ensure
+  # consistent ordering.
+  field_items = fields.items()
+  if not isinstance(fields, OrderedDict):
+    field_items = sorted(field_items)
+
+  # Use a consistent file name that is unlikely to conflict with any imported
+  # proto files.
+  fields_hash = hashlib.sha1()
+  for f_name, f_type in field_items:
+    fields_hash.update(f_name.encode('utf-8'))
+    fields_hash.update(str(f_type).encode('utf-8'))
+  proto_file_name = fields_hash.hexdigest() + '.proto'
+
+  # If the proto is anonymous, use the same hash to name it.
+  if full_name is None:
+    full_name = ('net.proto2.python.public.proto_builder.AnonymousProto_' +
+                 fields_hash.hexdigest())
+    try:
+      proto_cls = _GetMessageFromFactory(factory, full_name)
+      return proto_cls
+    except KeyError:
+      # The factory's DescriptorPool doesn't know about this class yet.
+      pass
+
+  # This is the first time we see this proto: add a new descriptor to the pool.
+  factory.pool.Add(
+      _MakeFileDescriptorProto(proto_file_name, full_name, field_items))
+  return _GetMessageFromFactory(factory, full_name)
+
+
+def _MakeFileDescriptorProto(proto_file_name, full_name, field_items):
+  """Populate FileDescriptorProto for MessageFactory's DescriptorPool."""
+  package, name = full_name.rsplit('.', 1)
+  file_proto = descriptor_pb2.FileDescriptorProto()
+  file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name)
+  file_proto.package = package
+  desc_proto = file_proto.message_type.add()
+  desc_proto.name = name
+  for f_number, (f_name, f_type) in enumerate(field_items, 1):
+    field_proto = desc_proto.field.add()
+    field_proto.name = f_name
+    field_proto.number = f_number
+    field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+    field_proto.type = f_type
+  return file_proto
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/README b/src/third_party/protobuf-3/python/google/protobuf/pyext/README
new file mode 100644
index 0000000..6d61cb4
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/README
@@ -0,0 +1,6 @@
+This is the 'v2' C++ implementation for python proto2.
+
+It is active when:
+
+PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/__init__.py b/src/third_party/protobuf-3/python/google/protobuf/pyext/__init__.py
new file mode 100644
index 0000000..5585614
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/__init__.py
@@ -0,0 +1,4 @@
+try:
+  __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/cpp_message.py b/src/third_party/protobuf-3/python/google/protobuf/pyext/cpp_message.py
new file mode 100644
index 0000000..b215211
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/cpp_message.py
@@ -0,0 +1,65 @@
+# 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.
+
+"""Protocol message implementation hooks for C++ implementation.
+
+Contains helper functions used to create protocol message classes from
+Descriptor objects at runtime backed by the protocol buffer C++ API.
+"""
+
+__author__ = 'tibell@google.com (Johan Tibell)'
+
+from google.protobuf.pyext import _message
+
+
+class GeneratedProtocolMessageType(_message.MessageMeta):
+
+  """Metaclass for protocol message classes created at runtime from Descriptors.
+
+  The protocol compiler currently uses this metaclass to create protocol
+  message classes at runtime.  Clients can also manually create their own
+  classes at runtime, as in this example:
+
+  mydescriptor = Descriptor(.....)
+  class MyProtoClass(Message):
+    __metaclass__ = GeneratedProtocolMessageType
+    DESCRIPTOR = mydescriptor
+  myproto_instance = MyProtoClass()
+  myproto.foo_field = 23
+  ...
+
+  The above example will not work for nested types. If you wish to include them,
+  use reflection.MakeClass() instead of manually instantiating the class in
+  order to create the appropriate class structure.
+  """
+
+  # Must be consistent with the protocol-compiler code in
+  # proto2/compiler/internal/generator.*.
+  _DESCRIPTOR_KEY = 'DESCRIPTOR'
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.cc
new file mode 100644
index 0000000..2355753
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.cc
@@ -0,0 +1,1584 @@
+// 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.
+
+// Author: petar@google.com (Petar Petrov)
+
+#include <Python.h>
+#include <frameobject.h>
+#include <string>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #define PyString_Check PyUnicode_Check
+  #define PyString_InternFromString PyUnicode_InternFromString
+  #define PyInt_FromLong PyLong_FromLong
+  #define PyInt_FromSize_t PyLong_FromSize_t
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// Store interned descriptors, so that the same C++ descriptor yields the same
+// Python object. Objects are not immortal: this map does not own the
+// references, and items are deleted when the last reference to the object is
+// released.
+// This is enough to support the "is" operator on live objects.
+// All descriptors are stored here.
+hash_map<const void*, PyObject*> interned_descriptors;
+
+PyObject* PyString_FromCppString(const string& str) {
+  return PyString_FromStringAndSize(str.c_str(), str.size());
+}
+
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which creates descriptors, then update some properties.
+// For example:
+//   message_descriptor = Descriptor(
+//       name='Message',
+//       fields = [FieldDescriptor(name='field')]
+//   message_descriptor.fields[0].containing_type = message_descriptor
+//
+// This code is still executed, but the descriptors now have no other storage
+// than the (const) C++ pointer, and are immutable.
+// So we let this code pass, by simply ignoring the new value.
+//
+// From user code, descriptors still look immutable.
+//
+// TODO(amauryfa): Change the proto2 compiler to remove the assignments, and
+// remove this hack.
+bool _CalledFromGeneratedFile(int stacklevel) {
+#ifndef PYPY_VERSION
+  // This check is not critical and is somewhat difficult to implement correctly
+  // in PyPy.
+  PyFrameObject* frame = PyEval_GetFrame();
+  if (frame == NULL) {
+    return false;
+  }
+  while (stacklevel-- > 0) {
+    frame = frame->f_back;
+    if (frame == NULL) {
+      return false;
+    }
+  }
+  if (frame->f_globals != frame->f_locals) {
+    // Not at global module scope
+    return false;
+  }
+
+  if (frame->f_code->co_filename == NULL) {
+    return false;
+  }
+  char* filename;
+  Py_ssize_t filename_size;
+  if (PyString_AsStringAndSize(frame->f_code->co_filename,
+                               &filename, &filename_size) < 0) {
+    // filename is not a string.
+    PyErr_Clear();
+    return false;
+  }
+  if (filename_size < 7) {
+    // filename is too short.
+    return false;
+  }
+  if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
+    // Filename is not ending with _pb2.
+    return false;
+  }
+#endif
+  return true;
+}
+
+// If the calling code is not a _pb2.py file, raise AttributeError.
+// To be used in attribute setters.
+static int CheckCalledFromGeneratedFile(const char* attr_name) {
+  if (_CalledFromGeneratedFile(0)) {
+    return 0;
+  }
+  PyErr_Format(PyExc_AttributeError,
+               "attribute is not writable: %s", attr_name);
+  return -1;
+}
+
+
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
+#endif
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+
+// Helper functions for descriptor objects.
+
+// A set of templates to retrieve the C++ FileDescriptor of any descriptor.
+template<class DescriptorClass>
+const FileDescriptor* GetFileDescriptor(const DescriptorClass* descriptor) {
+  return descriptor->file();
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const FileDescriptor* descriptor) {
+  return descriptor;
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const EnumValueDescriptor* descriptor) {
+  return descriptor->type()->file();
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) {
+  return descriptor->containing_type()->file();
+}
+
+// Converts options into a Python protobuf, and cache the result.
+//
+// This is a bit tricky because options can contain extension fields defined in
+// the same proto file. In this case the options parsed from the serialized_pb
+// have unkown fields, and we need to parse them again.
+//
+// Always returns a new reference.
+template<class DescriptorClass>
+static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
+  // Options (and their extensions) are completely resolved in the proto file
+  // containing the descriptor.
+  PyDescriptorPool* pool = GetDescriptorPool_FromPool(
+      GetFileDescriptor(descriptor)->pool());
+
+  hash_map<const void*, PyObject*>* descriptor_options =
+      pool->descriptor_options;
+  // First search in the cache.
+  if (descriptor_options->find(descriptor) != descriptor_options->end()) {
+    PyObject *value = (*descriptor_options)[descriptor];
+    Py_INCREF(value);
+    return value;
+  }
+
+  // Build the Options object: get its Python class, and make a copy of the C++
+  // read-only instance.
+  const Message& options(descriptor->options());
+  const Descriptor *message_type = options.GetDescriptor();
+  CMessageClass* message_class(
+      cdescriptor_pool::GetMessageClass(pool, message_type));
+  if (message_class == NULL) {
+    // The Options message was not found in the current DescriptorPool.
+    // In this case, there cannot be extensions to these options, and we can
+    // try to use the basic pool instead.
+    PyErr_Clear();
+    message_class = cdescriptor_pool::GetMessageClass(
+      GetDefaultDescriptorPool(), message_type);
+  }
+  if (message_class == NULL) {
+    PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
+                 message_type->full_name().c_str());
+    return NULL;
+  }
+  ScopedPyObjectPtr value(
+      PyEval_CallObject(message_class->AsPyObject(), NULL));
+  if (value == NULL) {
+    return NULL;
+  }
+  if (!PyObject_TypeCheck(value.get(), &CMessage_Type)) {
+      PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s",
+                   message_type->full_name().c_str(),
+                   Py_TYPE(value.get())->tp_name);
+      return NULL;
+  }
+  CMessage* cmsg = reinterpret_cast<CMessage*>(value.get());
+
+  const Reflection* reflection = options.GetReflection();
+  const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options));
+  if (unknown_fields.empty()) {
+    cmsg->message->CopyFrom(options);
+  } else {
+    // Reparse options string!  XXX call cmessage::MergeFromString
+    string serialized;
+    options.SerializeToString(&serialized);
+    io::CodedInputStream input(
+        reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+    input.SetExtensionRegistry(pool->pool, pool->message_factory);
+    bool success = cmsg->message->MergePartialFromCodedStream(&input);
+    if (!success) {
+      PyErr_Format(PyExc_ValueError, "Error parsing Options message");
+      return NULL;
+    }
+  }
+
+  // Cache the result.
+  Py_INCREF(value.get());
+  (*pool->descriptor_options)[descriptor] = value.get();
+
+  return value.release();
+}
+
+// Copy the C++ descriptor to a Python message.
+// The Python message is an instance of descriptor_pb2.DescriptorProto
+// or similar.
+template<class DescriptorProtoClass, class DescriptorClass>
+static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
+                                   PyObject *target) {
+  const Descriptor* self_descriptor =
+      DescriptorProtoClass::default_instance().GetDescriptor();
+  CMessage* message = reinterpret_cast<CMessage*>(target);
+  if (!PyObject_TypeCheck(target, &CMessage_Type) ||
+      message->message->GetDescriptor() != self_descriptor) {
+    PyErr_Format(PyExc_TypeError, "Not a %s message",
+                 self_descriptor->full_name().c_str());
+    return NULL;
+  }
+  cmessage::AssureWritable(message);
+  DescriptorProtoClass* descriptor_message =
+      static_cast<DescriptorProtoClass*>(message->message);
+  descriptor->CopyTo(descriptor_message);
+  Py_RETURN_NONE;
+}
+
+// All Descriptors classes share the same memory layout.
+typedef struct PyBaseDescriptor {
+  PyObject_HEAD
+
+  // Pointer to the C++ proto2 descriptor.
+  // Like all descriptors, it is owned by the global DescriptorPool.
+  const void* descriptor;
+
+  // Owned reference to the DescriptorPool, to ensure it is kept alive.
+  PyDescriptorPool* pool;
+} PyBaseDescriptor;
+
+
+// FileDescriptor structure "inherits" from the base descriptor.
+typedef struct PyFileDescriptor {
+  PyBaseDescriptor base;
+
+  // The cached version of serialized pb. Either NULL, or a Bytes string.
+  // We own the reference.
+  PyObject *serialized_pb;
+} PyFileDescriptor;
+
+
+namespace descriptor {
+
+// Creates or retrieve a Python descriptor of the specified type.
+// Objects are interned: the same descriptor will return the same object if it
+// was kept alive.
+// 'was_created' is an optional pointer to a bool, and is set to true if a new
+// object was allocated.
+// Always return a new reference.
+template<class DescriptorClass>
+PyObject* NewInternedDescriptor(PyTypeObject* type,
+                                const DescriptorClass* descriptor,
+                                bool* was_created) {
+  if (was_created) {
+    *was_created = false;
+  }
+  if (descriptor == NULL) {
+    PyErr_BadInternalCall();
+    return NULL;
+  }
+
+  // See if the object is in the map of interned descriptors
+  hash_map<const void*, PyObject*>::iterator it =
+      interned_descriptors.find(descriptor);
+  if (it != interned_descriptors.end()) {
+    GOOGLE_DCHECK(Py_TYPE(it->second) == type);
+    Py_INCREF(it->second);
+    return it->second;
+  }
+  // Create a new descriptor object
+  PyBaseDescriptor* py_descriptor = PyObject_New(
+      PyBaseDescriptor, type);
+  if (py_descriptor == NULL) {
+    return NULL;
+  }
+  py_descriptor->descriptor = descriptor;
+
+  // and cache it.
+  interned_descriptors.insert(
+      std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
+
+  // Ensures that the DescriptorPool stays alive.
+  PyDescriptorPool* pool = GetDescriptorPool_FromPool(
+      GetFileDescriptor(descriptor)->pool());
+  if (pool == NULL) {
+    // Don't DECREF, the object is not fully initialized.
+    PyObject_Del(py_descriptor);
+    return NULL;
+  }
+  Py_INCREF(pool);
+  py_descriptor->pool = pool;
+
+  if (was_created) {
+    *was_created = true;
+  }
+  return reinterpret_cast<PyObject*>(py_descriptor);
+}
+
+static void Dealloc(PyBaseDescriptor* self) {
+  // Remove from interned dictionary
+  interned_descriptors.erase(self->descriptor);
+  Py_CLEAR(self->pool);
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyGetSetDef Getters[] = {
+  {NULL}
+};
+
+PyTypeObject PyBaseDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".DescriptorBase",   // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)Dealloc,                  // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "Descriptors base class",             // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  Getters,                              // tp_getset
+};
+
+}  // namespace descriptor
+
+const void* PyDescriptor_AsVoidPtr(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor;
+}
+
+namespace message_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) {
+  return reinterpret_cast<const Descriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
+}
+
+static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
+  // Retuns the canonical class for the given descriptor.
+  // This is the class that was registered with the primary descriptor pool
+  // which contains this descriptor.
+  // This might not be the one you expect! For example the returned object does
+  // not know about extensions defined in a custom pool.
+  CMessageClass* concrete_class(cdescriptor_pool::GetMessageClass(
+      GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()),
+      _GetDescriptor(self)));
+  Py_XINCREF(concrete_class);
+  return concrete_class->AsPyObject();
+}
+
+static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsByCamelcaseName(PyBaseDescriptor* self,
+                                          void *closure) {
+  return NewMessageFieldsByCamelcaseName(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsByNumber(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageNestedTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageNestedTypesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) {
+  return NewMessageExtensionsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageEnumValuesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) {
+  return NewMessageOneofsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) {
+  return NewMessageOneofsSeq(_GetDescriptor(self));
+}
+
+static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) {
+  if (_GetDescriptor(self)->extension_range_count() > 0) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* descriptor = _GetDescriptor(self);
+  PyObject* range_list = PyList_New(descriptor->extension_range_count());
+
+  for (int i = 0; i < descriptor->extension_range_count(); i++) {
+    const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
+    PyObject* start = PyInt_FromLong(range->start);
+    PyObject* end = PyInt_FromLong(range->end);
+    PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
+  }
+
+  return range_list;
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_FromDescriptor(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const MessageOptions& options(_GetDescriptor(self)->options());
+  if (&options != &MessageOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
+  const char *enum_name;
+  int number;
+  if (!PyArg_ParseTuple(args, "si", &enum_name, &number))
+    return NULL;
+  const EnumDescriptor *enum_type =
+      _GetDescriptor(self)->FindEnumTypeByName(enum_name);
+  if (enum_type == NULL) {
+    PyErr_SetString(PyExc_KeyError, enum_name);
+    return NULL;
+  }
+  const EnumValueDescriptor *enum_value =
+      enum_type->FindValueByNumber(number);
+  if (enum_value == NULL) {
+    PyErr_Format(PyExc_KeyError, "%d", number);
+    return NULL;
+  }
+  return PyString_FromCppString(enum_value->name());
+}
+
+static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
+  return PyString_InternFromString(
+      FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
+}
+
+static PyGetSetDef Getters[] = {
+  { "name", (getter)GetName, NULL, "Last name"},
+  { "full_name", (getter)GetFullName, NULL, "Full name"},
+  { "_concrete_class", (getter)GetConcreteClass, NULL, "concrete class"},
+  { "file", (getter)GetFile, NULL, "File descriptor"},
+
+  { "fields", (getter)GetFieldsSeq, NULL, "Fields sequence"},
+  { "fields_by_name", (getter)GetFieldsByName, NULL, "Fields by name"},
+  { "fields_by_camelcase_name", (getter)GetFieldsByCamelcaseName, NULL,
+    "Fields by camelCase name"},
+  { "fields_by_number", (getter)GetFieldsByNumber, NULL, "Fields by number"},
+  { "nested_types", (getter)GetNestedTypesSeq, NULL, "Nested types sequence"},
+  { "nested_types_by_name", (getter)GetNestedTypesByName, NULL,
+    "Nested types by name"},
+  { "extensions", (getter)GetExtensions, NULL, "Extensions Sequence"},
+  { "extensions_by_name", (getter)GetExtensionsByName, NULL,
+    "Extensions by name"},
+  { "extension_ranges", (getter)GetExtensionRanges, NULL, "Extension ranges"},
+  { "enum_types", (getter)GetEnumsSeq, NULL, "Enum sequence"},
+  { "enum_types_by_name", (getter)GetEnumTypesByName, NULL,
+    "Enum types by name"},
+  { "enum_values_by_name", (getter)GetEnumValuesByName, NULL,
+    "Enum values by name"},
+  { "oneofs_by_name", (getter)GetOneofsByName, NULL, "Oneofs by name"},
+  { "oneofs", (getter)GetOneofsSeq, NULL, "Oneofs by name"},
+  { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+    "Containing type"},
+  { "is_extendable", (getter)IsExtendable, (setter)NULL},
+  { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+  { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+  { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  { "EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS, },
+  {NULL}
+};
+
+}  // namespace message_descriptor
+
+PyTypeObject PyMessageDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".MessageDescriptor",  // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A Message Descriptor",               // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  message_descriptor::Methods,          // tp_methods
+  0,                                    // tp_members
+  message_descriptor::Getters,          // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyMessageDescriptor_FromDescriptor(
+    const Descriptor* message_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyMessageDescriptor_Type, message_descriptor, NULL);
+}
+
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const Descriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace field_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const FieldDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const FieldDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->camelcase_name());
+}
+
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->type());
+}
+
+static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->cpp_type());
+}
+
+static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->label());
+}
+
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->number());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
+  return PyLong_FromVoidPtr(self);
+}
+
+static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) {
+  return PyBool_FromLong(_GetDescriptor(self)->is_extension());
+}
+
+static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
+  return PyBool_FromLong(_GetDescriptor(self)->has_default_value());
+}
+
+static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
+  PyObject *result;
+
+  switch (_GetDescriptor(self)->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = _GetDescriptor(self)->default_value_int32();
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = _GetDescriptor(self)->default_value_int64();
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = _GetDescriptor(self)->default_value_uint32();
+      result = PyInt_FromSize_t(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = _GetDescriptor(self)->default_value_uint64();
+      result = PyLong_FromUnsignedLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = _GetDescriptor(self)->default_value_float();
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = _GetDescriptor(self)->default_value_double();
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = _GetDescriptor(self)->default_value_bool();
+      result = PyBool_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string value = _GetDescriptor(self)->default_value_string();
+      result = ToStringObject(_GetDescriptor(self), value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      const EnumValueDescriptor* value =
+          _GetDescriptor(self)->default_value_enum();
+      result = PyInt_FromLong(value->number());
+      break;
+    }
+    default:
+      PyErr_Format(PyExc_NotImplementedError, "default value for %s",
+                   _GetDescriptor(self)->full_name().c_str());
+      return NULL;
+  }
+  return result;
+}
+
+static PyObject* GetCDescriptor(PyObject *self, void *closure) {
+  Py_INCREF(self);
+  return self;
+}
+
+static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
+  const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
+  if (enum_type) {
+    return PyEnumDescriptor_FromDescriptor(enum_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
+  return CheckCalledFromGeneratedFile("enum_type");
+}
+
+static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* message_type = _GetDescriptor(self)->message_type();
+  if (message_type) {
+    return PyMessageDescriptor_FromDescriptor(message_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetMessageType(PyBaseDescriptor *self, PyObject *value,
+                          void *closure) {
+  return CheckCalledFromGeneratedFile("message_type");
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_FromDescriptor(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* extension_scope =
+      _GetDescriptor(self)->extension_scope();
+  if (extension_scope) {
+    return PyMessageDescriptor_FromDescriptor(extension_scope);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
+  const OneofDescriptor* containing_oneof =
+      _GetDescriptor(self)->containing_oneof();
+  if (containing_oneof) {
+    return PyOneofDescriptor_FromDescriptor(containing_oneof);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value,
+                              void *closure) {
+  return CheckCalledFromGeneratedFile("containing_oneof");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const FieldOptions& options(_GetDescriptor(self)->options());
+  if (&options != &FieldOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+
+static PyGetSetDef Getters[] = {
+  { "full_name", (getter)GetFullName, NULL, "Full name"},
+  { "name", (getter)GetName, NULL, "Unqualified name"},
+  { "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
+  { "type", (getter)GetType, NULL, "C++ Type"},
+  { "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
+  { "label", (getter)GetLabel, NULL, "Label"},
+  { "number", (getter)GetNumber, NULL, "Number"},
+  { "index", (getter)GetIndex, NULL, "Index"},
+  { "default_value", (getter)GetDefaultValue, NULL, "Default Value"},
+  { "has_default_value", (getter)HasDefaultValue},
+  { "is_extension", (getter)IsExtension, NULL, "ID"},
+  { "id", (getter)GetID, NULL, "ID"},
+  { "_cdescriptor", (getter)GetCDescriptor, NULL, "HAACK REMOVE ME"},
+
+  { "message_type", (getter)GetMessageType, (setter)SetMessageType,
+    "Message type"},
+  { "enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"},
+  { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+    "Containing type"},
+  { "extension_scope", (getter)GetExtensionScope, (setter)NULL,
+    "Extension scope"},
+  { "containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof,
+    "Containing oneof"},
+  { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+  { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  {NULL}
+};
+
+}  // namespace field_descriptor
+
+PyTypeObject PyFieldDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".FieldDescriptor",  // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A Field Descriptor",                 // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  field_descriptor::Methods,            // tp_methods
+  0,                                    // tp_members
+  field_descriptor::Getters,            // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyFieldDescriptor_FromDescriptor(
+    const FieldDescriptor* field_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyFieldDescriptor_Type, field_descriptor, NULL);
+}
+
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const FieldDescriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace enum_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const EnumDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const EnumDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
+}
+
+static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesByNumber(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) {
+  return NewEnumValuesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_FromDescriptor(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+                             void *closure) {
+  return CheckCalledFromGeneratedFile("containing_type");
+}
+
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const EnumOptions& options(_GetDescriptor(self)->options());
+  if (&options != &EnumOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  {NULL}
+};
+
+static PyGetSetDef Getters[] = {
+  { "full_name", (getter)GetFullName, NULL, "Full name"},
+  { "name", (getter)GetName, NULL, "last name"},
+  { "file", (getter)GetFile, NULL, "File descriptor"},
+  { "values", (getter)GetEnumvaluesSeq, NULL, "values"},
+  { "values_by_name", (getter)GetEnumvaluesByName, NULL,
+    "Enum values by name"},
+  { "values_by_number", (getter)GetEnumvaluesByNumber, NULL,
+    "Enum values by number"},
+
+  { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+    "Containing type"},
+  { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+  { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+  {NULL}
+};
+
+}  // namespace enum_descriptor
+
+PyTypeObject PyEnumDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".EnumDescriptor",   // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A Enum Descriptor",                  // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  enum_descriptor::Methods,             // tp_getset
+  0,                                    // tp_members
+  enum_descriptor::Getters,             // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyEnumDescriptor_FromDescriptor(
+    const EnumDescriptor* enum_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyEnumDescriptor_Type, enum_descriptor, NULL);
+}
+
+const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyEnumDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not an EnumDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const EnumDescriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace enumvalue_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const EnumValueDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->number());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+  return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type());
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+  const EnumValueOptions& options(_GetDescriptor(self)->options());
+  if (&options != &EnumValueOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+
+static PyGetSetDef Getters[] = {
+  { "name", (getter)GetName, NULL, "name"},
+  { "number", (getter)GetNumber, NULL, "number"},
+  { "index", (getter)GetIndex, NULL, "index"},
+  { "type", (getter)GetType, NULL, "index"},
+
+  { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+  { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  {NULL}
+};
+
+}  // namespace enumvalue_descriptor
+
+PyTypeObject PyEnumValueDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".EnumValueDescriptor",  // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A EnumValue Descriptor",             // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  enumvalue_descriptor::Methods,        // tp_methods
+  0,                                    // tp_members
+  enumvalue_descriptor::Getters,        // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyEnumValueDescriptor_FromDescriptor(
+    const EnumValueDescriptor* enumvalue_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyEnumValueDescriptor_Type, enumvalue_descriptor, NULL);
+}
+
+namespace file_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) {
+  return reinterpret_cast<const FileDescriptor*>(self->base.descriptor);
+}
+
+static void Dealloc(PyFileDescriptor* self) {
+  Py_XDECREF(self->serialized_pb);
+  descriptor::Dealloc(&self->base);
+}
+
+static PyObject* GetPool(PyFileDescriptor *self, void *closure) {
+  PyObject* pool = reinterpret_cast<PyObject*>(
+      GetDescriptorPool_FromPool(_GetDescriptor(self)->pool()));
+  Py_XINCREF(pool);
+  return pool;
+}
+
+static PyObject* GetName(PyFileDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetPackage(PyFileDescriptor *self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->package());
+}
+
+static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) {
+  PyObject *serialized_pb = self->serialized_pb;
+  if (serialized_pb != NULL) {
+    Py_INCREF(serialized_pb);
+    return serialized_pb;
+  }
+  FileDescriptorProto file_proto;
+  _GetDescriptor(self)->CopyTo(&file_proto);
+  string contents;
+  file_proto.SerializePartialToString(&contents);
+  self->serialized_pb = PyBytes_FromStringAndSize(
+      contents.c_str(), contents.size());
+  if (self->serialized_pb == NULL) {
+    return NULL;
+  }
+  Py_INCREF(self->serialized_pb);
+  return self->serialized_pb;
+}
+
+static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) {
+  return NewFileMessageTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) {
+  return NewFileEnumTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
+  return NewFileExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
+  return NewFileDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) {
+  return NewFilePublicDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) {
+  const FileOptions& options(_GetDescriptor(self)->options());
+  if (&options != &FileOptions::default_instance()) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+static int SetHasOptions(PyFileDescriptor *self, PyObject *value,
+                         void *closure) {
+  return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyFileDescriptor *self) {
+  return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyFileDescriptor *self, PyObject *value,
+                      void *closure) {
+  return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
+  return PyString_InternFromString(
+      FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
+}
+
+static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
+  return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyGetSetDef Getters[] = {
+  { "pool", (getter)GetPool, NULL, "pool"},
+  { "name", (getter)GetName, NULL, "name"},
+  { "package", (getter)GetPackage, NULL, "package"},
+  { "serialized_pb", (getter)GetSerializedPb},
+  { "message_types_by_name", (getter)GetMessageTypesByName, NULL,
+    "Messages by name"},
+  { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, "Enums by name"},
+  { "extensions_by_name", (getter)GetExtensionsByName, NULL,
+    "Extensions by name"},
+  { "dependencies", (getter)GetDependencies, NULL, "Dependencies"},
+  { "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"},
+
+  { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+  { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+  { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+  { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+  {NULL}
+};
+
+}  // namespace file_descriptor
+
+PyTypeObject PyFileDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".FileDescriptor",   // tp_name
+  sizeof(PyFileDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)file_descriptor::Dealloc,  // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A File Descriptor",                  // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  file_descriptor::Methods,             // tp_methods
+  0,                                    // tp_members
+  file_descriptor::Getters,             // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  PyObject_Del,                         // tp_free
+};
+
+PyObject* PyFileDescriptor_FromDescriptor(
+    const FileDescriptor* file_descriptor) {
+  return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor,
+                                                         NULL);
+}
+
+PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
+    const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
+  bool was_created;
+  PyObject* py_descriptor = descriptor::NewInternedDescriptor(
+      &PyFileDescriptor_Type, file_descriptor, &was_created);
+  if (py_descriptor == NULL) {
+    return NULL;
+  }
+  if (was_created) {
+    PyFileDescriptor* cfile_descriptor =
+        reinterpret_cast<PyFileDescriptor*>(py_descriptor);
+    Py_XINCREF(serialized_pb);
+    cfile_descriptor->serialized_pb = serialized_pb;
+  }
+  // TODO(amauryfa): In the case of a cached object, check that serialized_pb
+  // is the same as before.
+
+  return py_descriptor;
+}
+
+const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj) {
+  if (!PyObject_TypeCheck(obj, &PyFileDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Not a FileDescriptor");
+    return NULL;
+  }
+  return reinterpret_cast<const FileDescriptor*>(
+      reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace oneof_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const OneofDescriptor* _GetDescriptor(
+    PyBaseDescriptor *self) {
+  return reinterpret_cast<const OneofDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+  return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+  return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
+  return NewOneofFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* containing_type =
+      _GetDescriptor(self)->containing_type();
+  if (containing_type) {
+    return PyMessageDescriptor_FromDescriptor(containing_type);
+  } else {
+    Py_RETURN_NONE;
+  }
+}
+
+static PyGetSetDef Getters[] = {
+  { "name", (getter)GetName, NULL, "Name"},
+  { "full_name", (getter)GetFullName, NULL, "Full name"},
+  { "index", (getter)GetIndex, NULL, "Index"},
+
+  { "containing_type", (getter)GetContainingType, NULL, "Containing type"},
+  { "fields", (getter)GetFields, NULL, "Fields"},
+  {NULL}
+};
+
+}  // namespace oneof_descriptor
+
+PyTypeObject PyOneofDescriptor_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".OneofDescriptor",  // tp_name
+  sizeof(PyBaseDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  "A Oneof Descriptor",                 // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  oneof_descriptor::Getters,            // tp_getset
+  &descriptor::PyBaseDescriptor_Type,   // tp_base
+};
+
+PyObject* PyOneofDescriptor_FromDescriptor(
+    const OneofDescriptor* oneof_descriptor) {
+  return descriptor::NewInternedDescriptor(
+      &PyOneofDescriptor_Type, oneof_descriptor, NULL);
+}
+
+// Add a enum values to a type dictionary.
+static bool AddEnumValues(PyTypeObject *type,
+                          const EnumDescriptor* enum_descriptor) {
+  for (int i = 0; i < enum_descriptor->value_count(); ++i) {
+    const EnumValueDescriptor* value = enum_descriptor->value(i);
+    ScopedPyObjectPtr obj(PyInt_FromLong(value->number()));
+    if (obj == NULL) {
+      return false;
+    }
+    if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj.get()) <
+        0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
+  ScopedPyObjectPtr obj(PyInt_FromLong(value));
+  if (PyDict_SetItemString(type->tp_dict, name, obj.get()) < 0) {
+    return false;
+  }
+  return true;
+}
+
+
+bool InitDescriptor() {
+  if (PyType_Ready(&PyMessageDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyFieldDescriptor_Type) < 0)
+    return false;
+
+  if (!AddEnumValues(&PyFieldDescriptor_Type,
+                     FieldDescriptorProto::Label_descriptor())) {
+    return false;
+  }
+  if (!AddEnumValues(&PyFieldDescriptor_Type,
+                     FieldDescriptorProto::Type_descriptor())) {
+    return false;
+  }
+#define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \
+    &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME)
+  if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) ||
+      !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) {
+    return false;
+  }
+#undef ADD_FIELDDESC_CONSTANT
+
+  if (PyType_Ready(&PyEnumDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyFileDescriptor_Type) < 0)
+    return false;
+
+  if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
+    return false;
+
+  if (!InitDescriptorMappingTypes())
+    return false;
+
+  return true;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.h
new file mode 100644
index 0000000..eb99df1
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor.h
@@ -0,0 +1,97 @@
+// 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.
+
+// Author: petar@google.com (Petar Petrov)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+extern PyTypeObject PyMessageDescriptor_Type;
+extern PyTypeObject PyFieldDescriptor_Type;
+extern PyTypeObject PyEnumDescriptor_Type;
+extern PyTypeObject PyEnumValueDescriptor_Type;
+extern PyTypeObject PyFileDescriptor_Type;
+extern PyTypeObject PyOneofDescriptor_Type;
+
+// Wraps a Descriptor in a Python object.
+// The C++ pointer is usually borrowed from the global DescriptorPool.
+// In any case, it must stay alive as long as the Python object.
+// Returns a new reference.
+PyObject* PyMessageDescriptor_FromDescriptor(const Descriptor* descriptor);
+PyObject* PyFieldDescriptor_FromDescriptor(const FieldDescriptor* descriptor);
+PyObject* PyEnumDescriptor_FromDescriptor(const EnumDescriptor* descriptor);
+PyObject* PyEnumValueDescriptor_FromDescriptor(
+    const EnumValueDescriptor* descriptor);
+PyObject* PyOneofDescriptor_FromDescriptor(const OneofDescriptor* descriptor);
+PyObject* PyFileDescriptor_FromDescriptor(
+    const FileDescriptor* file_descriptor);
+
+// Alternate constructor of PyFileDescriptor, used when we already have a
+// serialized FileDescriptorProto that can be cached.
+// Returns a new reference.
+PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
+    const FileDescriptor* file_descriptor, PyObject* serialized_pb);
+
+// Return the C++ descriptor pointer.
+// This function checks the parameter type; on error, return NULL with a Python
+// exception set.
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj);
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj);
+const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj);
+const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj);
+
+// Returns the raw C++ pointer.
+const void* PyDescriptor_AsVoidPtr(PyObject* obj);
+
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which insists on modifying descriptors after they have been
+// created.
+//
+// stacklevel indicates which Python frame should be the _pb2.py module.
+//
+// Don't use this function outside descriptor classes.
+bool _CalledFromGeneratedFile(int stacklevel);
+
+bool InitDescriptor();
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.cc
new file mode 100644
index 0000000..e505d81
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.cc
@@ -0,0 +1,1652 @@
+// 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.
+
+// Mappings and Sequences of descriptors.
+// Used by Descriptor.fields_by_name, EnumDescriptor.values...
+//
+// They avoid the allocation of a full dictionary or a full list: they simply
+// store a pointer to the parent descriptor, use the C++ Descriptor methods (see
+// google/protobuf/descriptor.h) to retrieve other descriptors, and create
+// Python objects on the fly.
+//
+// The containers fully conform to abc.Mapping and abc.Sequence, and behave just
+// like read-only dictionaries and lists.
+//
+// Because the interface of C++ Descriptors is quite regular, this file actually
+// defines only three types, the exact behavior of a container is controlled by
+// a DescriptorContainerDef structure, which contains functions that uses the
+// public Descriptor API.
+//
+// Note: This DescriptorContainerDef is similar to the "virtual methods table"
+// that a C++ compiler generates for a class. We have to make it explicit
+// because the Python API is based on C, and does not play well with C++
+// inheritance.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #define PyString_FromFormat PyUnicode_FromFormat
+  #define PyInt_FromLong PyLong_FromLong
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+struct PyContainer;
+
+typedef int (*CountMethod)(PyContainer* self);
+typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
+typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
+typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
+                                                const string& name);
+typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
+typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
+typedef const string& (*GetItemNameMethod)(const void* descriptor);
+typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor);
+typedef int (*GetItemNumberMethod)(const void* descriptor);
+typedef int (*GetItemIndexMethod)(const void* descriptor);
+
+struct DescriptorContainerDef {
+  const char* mapping_name;
+  // Returns the number of items in the container.
+  CountMethod count_fn;
+  // Retrieve item by index (usually the order of declaration in the proto file)
+  // Used by sequences, but also iterators. 0 <= index < Count().
+  GetByIndexMethod get_by_index_fn;
+  // Retrieve item by name (usually a call to some 'FindByName' method).
+  // Used by "by_name" mappings.
+  GetByNameMethod get_by_name_fn;
+  // Retrieve item by camelcase name (usually a call to some
+  // 'FindByCamelcaseName' method). Used by "by_camelcase_name" mappings.
+  GetByCamelcaseNameMethod get_by_camelcase_name_fn;
+  // Retrieve item by declared number (field tag, or enum value).
+  // Used by "by_number" mappings.
+  GetByNumberMethod get_by_number_fn;
+  // Converts a item C++ descriptor to a Python object. Returns a new reference.
+  NewObjectFromItemMethod new_object_from_item_fn;
+  // Retrieve the name of an item. Used by iterators on "by_name" mappings.
+  GetItemNameMethod get_item_name_fn;
+  // Retrieve the camelcase name of an item. Used by iterators on
+  // "by_camelcase_name" mappings.
+  GetItemCamelcaseNameMethod get_item_camelcase_name_fn;
+  // Retrieve the number of an item. Used by iterators on "by_number" mappings.
+  GetItemNumberMethod get_item_number_fn;
+  // Retrieve the index of an item for the container type.
+  // Used by "__contains__".
+  // If not set, "x in sequence" will do a linear search.
+  GetItemIndexMethod get_item_index_fn;
+};
+
+struct PyContainer {
+  PyObject_HEAD
+
+  // The proto2 descriptor this container belongs to the global DescriptorPool.
+  const void* descriptor;
+
+  // A pointer to a static structure with function pointers that control the
+  // behavior of the container. Very similar to the table of virtual functions
+  // of a C++ class.
+  const DescriptorContainerDef* container_def;
+
+  // The kind of container: list, or dict by name or value.
+  enum ContainerKind {
+    KIND_SEQUENCE,
+    KIND_BYNAME,
+    KIND_BYCAMELCASENAME,
+    KIND_BYNUMBER,
+  } kind;
+};
+
+struct PyContainerIterator {
+  PyObject_HEAD
+
+  // The container we are iterating over. Own a reference.
+  PyContainer* container;
+
+  // The current index in the iterator.
+  int index;
+
+  // The kind of container: list, or dict by name or value.
+  enum IterKind {
+    KIND_ITERKEY,
+    KIND_ITERVALUE,
+    KIND_ITERITEM,
+    KIND_ITERVALUE_REVERSED,  // For sequences
+  } kind;
+};
+
+namespace descriptor {
+
+// Returns the C++ item descriptor for a given Python key.
+// When the descriptor is found, return true and set *item.
+// When the descriptor is not found, return true, but set *item to NULL.
+// On error, returns false with an exception set.
+static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
+  switch (self->kind) {
+    case PyContainer::KIND_BYNAME:
+      {
+        char* name;
+        Py_ssize_t name_size;
+        if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
+          if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            // Not a string, cannot be in the container.
+            PyErr_Clear();
+            *item = NULL;
+            return true;
+          }
+          return false;
+        }
+        *item = self->container_def->get_by_name_fn(
+            self, string(name, name_size));
+        return true;
+      }
+    case PyContainer::KIND_BYCAMELCASENAME:
+      {
+        char* camelcase_name;
+        Py_ssize_t name_size;
+        if (PyString_AsStringAndSize(key, &camelcase_name, &name_size) < 0) {
+          if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            // Not a string, cannot be in the container.
+            PyErr_Clear();
+            *item = NULL;
+            return true;
+          }
+          return false;
+        }
+        *item = self->container_def->get_by_camelcase_name_fn(
+            self, string(camelcase_name, name_size));
+        return true;
+      }
+    case PyContainer::KIND_BYNUMBER:
+      {
+        Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
+        if (number == -1 && PyErr_Occurred()) {
+          if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+            // Not a number, cannot be in the container.
+            PyErr_Clear();
+            *item = NULL;
+            return true;
+          }
+          return false;
+        }
+        *item = self->container_def->get_by_number_fn(self, number);
+        return true;
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return false;
+  }
+}
+
+// Returns the key of the object at the given index.
+// Used when iterating over mappings.
+static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
+  const void* item = self->container_def->get_by_index_fn(self, index);
+  switch (self->kind) {
+    case PyContainer::KIND_BYNAME:
+      {
+        const string& name(self->container_def->get_item_name_fn(item));
+        return PyString_FromStringAndSize(name.c_str(), name.size());
+      }
+    case PyContainer::KIND_BYCAMELCASENAME:
+      {
+        const string& name(
+            self->container_def->get_item_camelcase_name_fn(item));
+        return PyString_FromStringAndSize(name.c_str(), name.size());
+      }
+    case PyContainer::KIND_BYNUMBER:
+      {
+        int value = self->container_def->get_item_number_fn(item);
+        return PyInt_FromLong(value);
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return NULL;
+  }
+}
+
+// Returns the object at the given index.
+// Also used when iterating over mappings.
+static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
+  return self->container_def->new_object_from_item_fn(
+      self->container_def->get_by_index_fn(self, index));
+}
+
+static Py_ssize_t Length(PyContainer* self) {
+  return self->container_def->count_fn(self);
+}
+
+// The DescriptorMapping type.
+
+static PyObject* Subscript(PyContainer* self, PyObject* key) {
+  const void* item = NULL;
+  if (!_GetItemByKey(self, key, &item)) {
+    return NULL;
+  }
+  if (!item) {
+    PyErr_SetObject(PyExc_KeyError, key);
+    return NULL;
+  }
+  return self->container_def->new_object_from_item_fn(item);
+}
+
+static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
+  if (_CalledFromGeneratedFile(0)) {
+    return 0;
+  }
+  PyErr_Format(PyExc_TypeError,
+               "'%.200s' object does not support item assignment",
+               Py_TYPE(self)->tp_name);
+  return -1;
+}
+
+static PyMappingMethods MappingMappingMethods = {
+  (lenfunc)Length,               // mp_length
+  (binaryfunc)Subscript,         // mp_subscript
+  (objobjargproc)AssSubscript,   // mp_ass_subscript
+};
+
+static int Contains(PyContainer* self, PyObject* key) {
+  const void* item = NULL;
+  if (!_GetItemByKey(self, key, &item)) {
+    return -1;
+  }
+  if (item) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+static PyObject* ContainerRepr(PyContainer* self) {
+  const char* kind = "";
+  switch (self->kind) {
+    case PyContainer::KIND_SEQUENCE:
+      kind = "sequence";
+      break;
+    case PyContainer::KIND_BYNAME:
+      kind = "mapping by name";
+      break;
+    case PyContainer::KIND_BYCAMELCASENAME:
+      kind = "mapping by camelCase name";
+      break;
+    case PyContainer::KIND_BYNUMBER:
+      kind = "mapping by number";
+      break;
+  }
+  return PyString_FromFormat(
+      "<%s %s>", self->container_def->mapping_name, kind);
+}
+
+extern PyTypeObject DescriptorMapping_Type;
+extern PyTypeObject DescriptorSequence_Type;
+
+// A sequence container can only be equal to another sequence container, or (for
+// backward compatibility) to a list containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
+  // Check the identity of C++ pointers.
+  if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
+    PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+    if (self->descriptor == other_container->descriptor &&
+        self->container_def == other_container->container_def &&
+        self->kind == other_container->kind) {
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+
+  // If other is a list
+  if (PyList_Check(other)) {
+    // return list(self) == other
+    int size = Length(self);
+    if (size != PyList_Size(other)) {
+      return false;
+    }
+    for (int index = 0; index < size; index++) {
+      ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+      if (value1 == NULL) {
+        return -1;
+      }
+      PyObject* value2 = PyList_GetItem(other, index);
+      if (value2 == NULL) {
+        return -1;
+      }
+      int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
+      if (cmp != 1)  // error or not equal
+          return cmp;
+    }
+    // All items were found and equal
+    return 1;
+  }
+
+  // Any other object is different.
+  return 0;
+}
+
+// A mapping container can only be equal to another mapping container, or (for
+// backward compatibility) to a dict containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
+  // Check the identity of C++ pointers.
+  if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
+    PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+    if (self->descriptor == other_container->descriptor &&
+        self->container_def == other_container->container_def &&
+        self->kind == other_container->kind) {
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+
+  // If other is a dict
+  if (PyDict_Check(other)) {
+    // equivalent to dict(self.items()) == other
+    int size = Length(self);
+    if (size != PyDict_Size(other)) {
+      return false;
+    }
+    for (int index = 0; index < size; index++) {
+      ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
+      if (key == NULL) {
+        return -1;
+      }
+      ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+      if (value1 == NULL) {
+        return -1;
+      }
+      PyObject* value2 = PyDict_GetItem(other, key.get());
+      if (value2 == NULL) {
+        // Not found in the other dictionary
+        return 0;
+      }
+      int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
+      if (cmp != 1)  // error or not equal
+          return cmp;
+    }
+    // All items were found and equal
+    return 1;
+  }
+
+  // Any other object is different.
+  return 0;
+}
+
+static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
+  if (opid != Py_EQ && opid != Py_NE) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+
+  int result;
+
+  if (self->kind == PyContainer::KIND_SEQUENCE) {
+    result = DescriptorSequence_Equal(self, other);
+  } else {
+    result = DescriptorMapping_Equal(self, other);
+  }
+  if (result < 0) {
+    return NULL;
+  }
+  if (result ^ (opid == Py_NE)) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+static PySequenceMethods MappingSequenceMethods = {
+    0,                      // sq_length
+    0,                      // sq_concat
+    0,                      // sq_repeat
+    0,                      // sq_item
+    0,                      // sq_slice
+    0,                      // sq_ass_item
+    0,                      // sq_ass_slice
+    (objobjproc)Contains,   // sq_contains
+};
+
+static PyObject* Get(PyContainer* self, PyObject* args) {
+  PyObject* key;
+  PyObject* default_value = Py_None;
+  if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
+    return NULL;
+  }
+
+  const void* item;
+  if (!_GetItemByKey(self, key, &item)) {
+    return NULL;
+  }
+  if (item == NULL) {
+    Py_INCREF(default_value);
+    return default_value;
+  }
+  return self->container_def->new_object_from_item_fn(item);
+}
+
+static PyObject* Keys(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    PyObject* key = _NewKey_ByIndex(self, index);
+    if (key == NULL) {
+      return NULL;
+    }
+    PyList_SET_ITEM(list.get(), index, key);
+  }
+  return list.release();
+}
+
+static PyObject* Values(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    PyObject* value = _NewObj_ByIndex(self, index);
+    if (value == NULL) {
+      return NULL;
+    }
+    PyList_SET_ITEM(list.get(), index, value);
+  }
+  return list.release();
+}
+
+static PyObject* Items(PyContainer* self, PyObject* args) {
+  Py_ssize_t count = Length(self);
+  ScopedPyObjectPtr list(PyList_New(count));
+  if (list == NULL) {
+    return NULL;
+  }
+  for (Py_ssize_t index = 0; index < count; ++index) {
+    ScopedPyObjectPtr obj(PyTuple_New(2));
+    if (obj == NULL) {
+      return NULL;
+    }
+    PyObject* key = _NewKey_ByIndex(self, index);
+    if (key == NULL) {
+      return NULL;
+    }
+    PyTuple_SET_ITEM(obj.get(), 0, key);
+    PyObject* value = _NewObj_ByIndex(self, index);
+    if (value == NULL) {
+      return NULL;
+    }
+    PyTuple_SET_ITEM(obj.get(), 1, value);
+    PyList_SET_ITEM(list.get(), index, obj.release());
+  }
+  return list.release();
+}
+
+static PyObject* NewContainerIterator(PyContainer* mapping,
+                                      PyContainerIterator::IterKind kind);
+
+static PyObject* Iter(PyContainer* self) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterKeys(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterValues(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
+}
+static PyObject* IterItems(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
+}
+
+static PyMethodDef MappingMethods[] = {
+  { "get", (PyCFunction)Get, METH_VARARGS, },
+  { "keys", (PyCFunction)Keys, METH_NOARGS, },
+  { "values", (PyCFunction)Values, METH_NOARGS, },
+  { "items", (PyCFunction)Items, METH_NOARGS, },
+  { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
+  { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
+  { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
+  {NULL}
+};
+
+PyTypeObject DescriptorMapping_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorMapping",                  // tp_name
+  sizeof(PyContainer),                  // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  (reprfunc)ContainerRepr,              // tp_repr
+  0,                                    // tp_as_number
+  &MappingSequenceMethods,              // tp_as_sequence
+  &MappingMappingMethods,               // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  (richcmpfunc)RichCompare,             // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  (getiterfunc)Iter,                    // tp_iter
+  0,                                    // tp_iternext
+  MappingMethods,                       // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+// The DescriptorSequence type.
+
+static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
+  if (index < 0) {
+    index += Length(self);
+  }
+  if (index < 0 || index >= Length(self)) {
+    PyErr_SetString(PyExc_IndexError, "index out of range");
+    return NULL;
+  }
+  return _NewObj_ByIndex(self, index);
+}
+
+// Returns the position of the item in the sequence, of -1 if not found.
+// This function never fails.
+int Find(PyContainer* self, PyObject* item) {
+  // The item can only be in one position: item.index.
+  // Check that self[item.index] == item, it's faster than a linear search.
+  //
+  // This assumes that sequences are only defined by syntax of the .proto file:
+  // a specific item belongs to only one sequence, depending on its position in
+  // the .proto file definition.
+  const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
+  if (descriptor_ptr == NULL) {
+    // Not a descriptor, it cannot be in the list.
+    return -1;
+  }
+  if (self->container_def->get_item_index_fn) {
+    int index = self->container_def->get_item_index_fn(descriptor_ptr);
+    if (index < 0 || index >= Length(self)) {
+      // This index is not from this collection.
+      return -1;
+    }
+    if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
+      // The descriptor at this index is not the same.
+      return -1;
+    }
+    // self[item.index] == item, so return the index.
+    return index;
+  } else {
+    // Fall back to linear search.
+    int length = Length(self);
+    for (int index=0; index < length; index++) {
+      if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
+        return index;
+      }
+    }
+    // Not found
+    return -1;
+  }
+}
+
+// Implements list.index(): the position of the item is in the sequence.
+static PyObject* Index(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    // Not found
+    PyErr_SetNone(PyExc_ValueError);
+    return NULL;
+  } else {
+    return PyInt_FromLong(position);
+  }
+}
+// Implements "list.__contains__()": is the object in the sequence.
+static int SeqContains(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+// Implements list.count(): number of occurrences of the item in the sequence.
+// An item can only appear once in a sequence. If it exists, return 1.
+static PyObject* Count(PyContainer* self, PyObject* item) {
+  int position = Find(self, item);
+  if (position < 0) {
+    return PyInt_FromLong(0);
+  } else {
+    return PyInt_FromLong(1);
+  }
+}
+
+static PyObject* Append(PyContainer* self, PyObject* args) {
+  if (_CalledFromGeneratedFile(0)) {
+    Py_RETURN_NONE;
+  }
+  PyErr_Format(PyExc_TypeError,
+               "'%.200s' object is not a mutable sequence",
+               Py_TYPE(self)->tp_name);
+  return NULL;
+}
+
+static PyObject* Reversed(PyContainer* self, PyObject* args) {
+  return NewContainerIterator(self,
+                              PyContainerIterator::KIND_ITERVALUE_REVERSED);
+}
+
+static PyMethodDef SeqMethods[] = {
+  { "index", (PyCFunction)Index, METH_O, },
+  { "count", (PyCFunction)Count, METH_O, },
+  { "append", (PyCFunction)Append, METH_O, },
+  { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
+  {NULL}
+};
+
+static PySequenceMethods SeqSequenceMethods = {
+    (lenfunc)Length,          // sq_length
+    0,                        // sq_concat
+    0,                        // sq_repeat
+    (ssizeargfunc)GetItem,    // sq_item
+    0,                        // sq_slice
+    0,                        // sq_ass_item
+    0,                        // sq_ass_slice
+    (objobjproc)SeqContains,  // sq_contains
+};
+
+PyTypeObject DescriptorSequence_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorSequence",                 // tp_name
+  sizeof(PyContainer),                  // tp_basicsize
+  0,                                    // tp_itemsize
+  0,                                    // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  (reprfunc)ContainerRepr,              // tp_repr
+  0,                                    // tp_as_number
+  &SeqSequenceMethods,                  // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  (richcmpfunc)RichCompare,             // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  SeqMethods,                           // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+static PyObject* NewMappingByName(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_BYNAME;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewMappingByCamelcaseName(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_BYCAMELCASENAME;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewMappingByNumber(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  if (container_def->get_by_number_fn == NULL ||
+      container_def->get_item_number_fn == NULL) {
+    PyErr_SetNone(PyExc_NotImplementedError);
+    return NULL;
+  }
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_BYNUMBER;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewSequence(
+    DescriptorContainerDef* container_def, const void* descriptor) {
+  PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->descriptor = descriptor;
+  self->container_def = container_def;
+  self->kind = PyContainer::KIND_SEQUENCE;
+  return reinterpret_cast<PyObject*>(self);
+}
+
+// Implement iterators over PyContainers.
+
+static void Iterator_Dealloc(PyContainerIterator* self) {
+  Py_CLEAR(self->container);
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* Iterator_Next(PyContainerIterator* self) {
+  int count = self->container->container_def->count_fn(self->container);
+  if (self->index >= count) {
+    // Return NULL with no exception to indicate the end.
+    return NULL;
+  }
+  int index = self->index;
+  self->index += 1;
+  switch (self->kind) {
+    case PyContainerIterator::KIND_ITERKEY:
+      return _NewKey_ByIndex(self->container, index);
+    case PyContainerIterator::KIND_ITERVALUE:
+      return _NewObj_ByIndex(self->container, index);
+    case PyContainerIterator::KIND_ITERVALUE_REVERSED:
+      return _NewObj_ByIndex(self->container, count - index - 1);
+    case PyContainerIterator::KIND_ITERITEM:
+      {
+        PyObject* obj = PyTuple_New(2);
+        if (obj == NULL) {
+          return NULL;
+        }
+        PyObject* key = _NewKey_ByIndex(self->container, index);
+        if (key == NULL) {
+          Py_DECREF(obj);
+          return NULL;
+        }
+        PyTuple_SET_ITEM(obj, 0, key);
+        PyObject* value = _NewObj_ByIndex(self->container, index);
+        if (value == NULL) {
+          Py_DECREF(obj);
+          return NULL;
+        }
+        PyTuple_SET_ITEM(obj, 1, value);
+        return obj;
+      }
+    default:
+      PyErr_SetNone(PyExc_NotImplementedError);
+      return NULL;
+  }
+}
+
+static PyTypeObject ContainerIterator_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "DescriptorContainerIterator",        // tp_name
+  sizeof(PyContainerIterator),          // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)Iterator_Dealloc,         // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  0,                                    // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  PyObject_SelfIter,                    // tp_iter
+  (iternextfunc)Iterator_Next,          // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  0,                                    // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  0,                                    // tp_alloc
+  0,                                    // tp_new
+  0,                                    // tp_free
+};
+
+static PyObject* NewContainerIterator(PyContainer* container,
+                                      PyContainerIterator::IterKind kind) {
+  PyContainerIterator* self = PyObject_New(PyContainerIterator,
+                                           &ContainerIterator_Type);
+  if (self == NULL) {
+    return NULL;
+  }
+  Py_INCREF(container);
+  self->container = container;
+  self->kind = kind;
+  self->index = 0;
+
+  return reinterpret_cast<PyObject*>(self);
+}
+
+}  // namespace descriptor
+
+// Now define the real collections!
+
+namespace message_descriptor {
+
+typedef const Descriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindFieldByName(name);
+}
+
+static ItemDescriptor GetByCamelcaseName(PyContainer* self,
+                                         const string& name) {
+  return GetDescriptor(self)->FindFieldByCamelcaseName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+  return GetDescriptor(self)->FindFieldByNumber(number);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static const string& GetItemCamelcaseName(ItemDescriptor item) {
+  return item->camelcase_name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+  return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageFields",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)GetByCamelcaseName,
+  (GetByNumberMethod)GetByNumber,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)GetItemCamelcaseName,
+  (GetItemNumberMethod)GetItemNumber,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace fields
+
+PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef,
+                                               descriptor);
+}
+
+PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+namespace nested_types {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->nested_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindNestedTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->nested_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyMessageDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageNestedTypes",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace nested_types
+
+PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageNestedEnums",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enums
+
+PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&enums::ContainerDef, descriptor);
+}
+
+namespace enumvalues {
+
+// This is the "enum_values_by_name" mapping, which collects values from all
+// enum types in a message.
+//
+// Note that the behavior of the C++ descriptor is different: it will search and
+// return the first value that matches the name, whereas the Python
+// implementation retrieves the last one.
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  int count = 0;
+  for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
+    count += GetDescriptor(self)->enum_type(i)->value_count();
+  }
+  return count;
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumValueByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  // This is not optimal, but the number of enums *types* in a given message
+  // is small.  This function is only used when iterating over the mapping.
+  const EnumDescriptor* enum_type = NULL;
+  int enum_type_count = GetDescriptor(self)->enum_type_count();
+  for (int i = 0; i < enum_type_count; ++i) {
+    enum_type = GetDescriptor(self)->enum_type(i);
+    int enum_value_count = enum_type->value_count();
+    if (index < enum_value_count) {
+      // Found it!
+      break;
+    }
+    index -= enum_value_count;
+  }
+  // The next statement cannot overflow, because this function is only called by
+  // internal iterators which ensure that 0 <= index < Count().
+  return enum_type->value(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumValueDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageEnumValues",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace enumvalues
+
+PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageExtensions",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace extensions
+
+PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
+}
+
+namespace oneofs {
+
+typedef const OneofDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->oneof_decl_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindOneofByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->oneof_decl(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyOneofDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "MessageOneofs",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace oneofs
+
+PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
+}
+
+}  // namespace message_descriptor
+
+namespace enum_descriptor {
+
+typedef const EnumDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace enumvalues {
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->value_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->value(index);
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindValueByName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+  return GetDescriptor(self)->FindValueByNumber(number);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumValueDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+  return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "EnumValues",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)GetByNumber,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)GetItemNumber,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enumvalues
+
+PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
+  return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
+}
+
+}  // namespace enum_descriptor
+
+namespace oneof_descriptor {
+
+typedef const OneofDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_FromDescriptor(item);
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index_in_oneof();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "OneofFields",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace fields
+
+PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
+  return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+}  // namespace oneof_descriptor
+
+namespace file_descriptor {
+
+typedef const FileDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+  return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace messages {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->message_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindMessageTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->message_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyMessageDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileMessages",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace messages
+
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyEnumDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileEnums",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace enums
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+  return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFieldDescriptor_FromDescriptor(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+  return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+  return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileExtensions",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)GetByName,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)GetItemName,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)GetItemIndex,
+};
+
+}  // namespace extensions
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) {
+  return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+namespace dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFileDescriptor_FromDescriptor(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FileDependencies",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace dependencies
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
+  return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
+}
+
+namespace public_dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+  return GetDescriptor(self)->public_dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+  return GetDescriptor(self)->public_dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+  return PyFileDescriptor_FromDescriptor(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+  "FilePublicDependencies",
+  (CountMethod)Count,
+  (GetByIndexMethod)GetByIndex,
+  (GetByNameMethod)NULL,
+  (GetByCamelcaseNameMethod)NULL,
+  (GetByNumberMethod)NULL,
+  (NewObjectFromItemMethod)NewObjectFromItem,
+  (GetItemNameMethod)NULL,
+  (GetItemCamelcaseNameMethod)NULL,
+  (GetItemNumberMethod)NULL,
+  (GetItemIndexMethod)NULL,
+};
+
+}  // namespace public_dependencies
+
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
+  return descriptor::NewSequence(&public_dependencies::ContainerDef,
+                                 descriptor);
+}
+
+}  // namespace file_descriptor
+
+
+// Register all implementations
+
+bool InitDescriptorMappingTypes() {
+  if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
+    return false;
+  if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
+    return false;
+  if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
+    return false;
+  return true;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.h
new file mode 100644
index 0000000..ce40747
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_containers.h
@@ -0,0 +1,101 @@
+// 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_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
+
+// Mappings and Sequences of descriptors.
+// They implement containers like fields_by_name, EnumDescriptor.values...
+// See descriptor_containers.cc for more description.
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class FileDescriptor;
+class EnumDescriptor;
+class OneofDescriptor;
+
+namespace python {
+
+// Initialize the various types and objects.
+bool InitDescriptorMappingTypes();
+
+// Each function below returns a Mapping, or a Sequence of descriptors.
+// They all return a new reference.
+
+namespace message_descriptor {
+PyObject* NewMessageFieldsByName(const Descriptor* descriptor);
+PyObject* NewMessageFieldsByCamelcaseName(const Descriptor* descriptor);
+PyObject* NewMessageFieldsByNumber(const Descriptor* descriptor);
+PyObject* NewMessageFieldsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageNestedTypesSeq(const Descriptor* descriptor);
+PyObject* NewMessageNestedTypesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageEnumsByName(const Descriptor* descriptor);
+PyObject* NewMessageEnumsSeq(const Descriptor* descriptor);
+PyObject* NewMessageEnumValuesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageExtensionsByName(const Descriptor* descriptor);
+PyObject* NewMessageExtensionsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageOneofsByName(const Descriptor* descriptor);
+PyObject* NewMessageOneofsSeq(const Descriptor* descriptor);
+}  // namespace message_descriptor
+
+namespace enum_descriptor {
+PyObject* NewEnumValuesByName(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesByNumber(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesSeq(const EnumDescriptor* descriptor);
+}  // namespace enum_descriptor
+
+namespace oneof_descriptor {
+PyObject* NewOneofFieldsSeq(const OneofDescriptor* descriptor);
+}  // namespace oneof_descriptor
+
+namespace file_descriptor {
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor);
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor);
+}  // namespace file_descriptor
+
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.cc
new file mode 100644
index 0000000..daa40cc
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.cc
@@ -0,0 +1,148 @@
+// 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.
+
+// This file defines a C++ DescriptorDatabase, which wraps a Python Database
+// and delegate all its operations to Python methods.
+
+#include <google/protobuf/pyext/descriptor_database.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+PyDescriptorDatabase::PyDescriptorDatabase(PyObject* py_database)
+    : py_database_(py_database) {
+  Py_INCREF(py_database_);
+}
+
+PyDescriptorDatabase::~PyDescriptorDatabase() { Py_DECREF(py_database_); }
+
+// Convert a Python object to a FileDescriptorProto pointer.
+// Handles all kinds of Python errors, which are simply logged.
+static bool GetFileDescriptorProto(PyObject* py_descriptor,
+                                   FileDescriptorProto* output) {
+  if (py_descriptor == NULL) {
+    if (PyErr_ExceptionMatches(PyExc_KeyError)) {
+      // Expected error: item was simply not found.
+      PyErr_Clear();
+    } else {
+      GOOGLE_LOG(ERROR) << "DescriptorDatabase method raised an error";
+      PyErr_Print();
+    }
+    return false;
+  }
+  if (py_descriptor == Py_None) {
+    return false;
+  }
+  const Descriptor* filedescriptor_descriptor =
+      FileDescriptorProto::default_instance().GetDescriptor();
+  CMessage* message = reinterpret_cast<CMessage*>(py_descriptor);
+  if (PyObject_TypeCheck(py_descriptor, &CMessage_Type) &&
+      message->message->GetDescriptor() == filedescriptor_descriptor) {
+    // Fast path: Just use the pointer.
+    FileDescriptorProto* file_proto =
+        static_cast<FileDescriptorProto*>(message->message);
+    *output = *file_proto;
+    return true;
+  } else {
+    // Slow path: serialize the message. This allows to use databases which
+    // use a different implementation of FileDescriptorProto.
+    ScopedPyObjectPtr serialized_pb(
+        PyObject_CallMethod(py_descriptor, "SerializeToString", NULL));
+    if (serialized_pb == NULL) {
+      GOOGLE_LOG(ERROR)
+          << "DescriptorDatabase method did not return a FileDescriptorProto";
+      PyErr_Print();
+      return false;
+    }
+    char* str;
+    Py_ssize_t len;
+    if (PyBytes_AsStringAndSize(serialized_pb.get(), &str, &len) < 0) {
+      GOOGLE_LOG(ERROR)
+          << "DescriptorDatabase method did not return a FileDescriptorProto";
+      PyErr_Print();
+      return false;
+    }
+    FileDescriptorProto file_proto;
+    if (!file_proto.ParseFromArray(str, len)) {
+      GOOGLE_LOG(ERROR)
+          << "DescriptorDatabase method did not return a FileDescriptorProto";
+      return false;
+    }
+    *output = file_proto;
+    return true;
+  }
+}
+
+// Find a file by file name.
+bool PyDescriptorDatabase::FindFileByName(const string& filename,
+                                          FileDescriptorProto* output) {
+  ScopedPyObjectPtr py_descriptor(PyObject_CallMethod(
+      py_database_, "FindFileByName", "s#", filename.c_str(), filename.size()));
+  return GetFileDescriptorProto(py_descriptor.get(), output);
+}
+
+// Find the file that declares the given fully-qualified symbol name.
+bool PyDescriptorDatabase::FindFileContainingSymbol(
+    const string& symbol_name, FileDescriptorProto* output) {
+  ScopedPyObjectPtr py_descriptor(
+      PyObject_CallMethod(py_database_, "FindFileContainingSymbol", "s#",
+                          symbol_name.c_str(), symbol_name.size()));
+  return GetFileDescriptorProto(py_descriptor.get(), output);
+}
+
+// Find the file which defines an extension extending the given message type
+// with the given field number.
+// Python DescriptorDatabases are not required to implement this method.
+bool PyDescriptorDatabase::FindFileContainingExtension(
+    const string& containing_type, int field_number,
+    FileDescriptorProto* output) {
+  ScopedPyObjectPtr py_method(
+      PyObject_GetAttrString(py_database_, "FindFileContainingExtension"));
+  if (py_method == NULL) {
+    // This method is not implemented, returns without error.
+    PyErr_Clear();
+    return false;
+  }
+  ScopedPyObjectPtr py_descriptor(
+      PyObject_CallFunction(py_method.get(), "s#i", containing_type.c_str(),
+                            containing_type.size(), field_number));
+  return GetFileDescriptorProto(py_descriptor.get(), output);
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.h
new file mode 100644
index 0000000..fc71c4b
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_database.h
@@ -0,0 +1,75 @@
+// 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_PYTHON_CPP_DESCRIPTOR_DATABASE_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_DATABASE_H__
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor_database.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+class PyDescriptorDatabase : public DescriptorDatabase {
+ public:
+  explicit PyDescriptorDatabase(PyObject* py_database);
+  ~PyDescriptorDatabase();
+
+  // Implement the abstract interface. All these functions fill the output
+  // with a copy of FileDescriptorProto.
+
+  // Find a file by file name.
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output);
+
+  // Find the file that declares the given fully-qualified symbol name.
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+
+  // Find the file which defines an extension extending the given message type
+  // with the given field number.
+  // Containing_type must be a fully-qualified type name.
+  // Python objects are not required to implement this method.
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+
+ private:
+  // The python object that implements the database. The reference is owned.
+  PyObject* py_database_;
+};
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_DATABASE_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.cc
new file mode 100644
index 0000000..1faff96
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.cc
@@ -0,0 +1,593 @@
+// 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.
+
+// Implements the DescriptorPool, which collects all descriptors.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_database.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #endif
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// A map to cache Python Pools per C++ pointer.
+// Pointers are not owned here, and belong to the PyDescriptorPool.
+static hash_map<const DescriptorPool*, PyDescriptorPool*> descriptor_pool_map;
+
+namespace cdescriptor_pool {
+
+// Create a Python DescriptorPool object, but does not fill the "pool"
+// attribute.
+static PyDescriptorPool* _CreateDescriptorPool() {
+  PyDescriptorPool* cpool = PyObject_New(
+      PyDescriptorPool, &PyDescriptorPool_Type);
+  if (cpool == NULL) {
+    return NULL;
+  }
+
+  cpool->underlay = NULL;
+  cpool->database = NULL;
+
+  DynamicMessageFactory* message_factory = new DynamicMessageFactory();
+  // This option might be the default some day.
+  message_factory->SetDelegateToGeneratedFactory(true);
+  cpool->message_factory = message_factory;
+
+  // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
+  // storage.
+  cpool->classes_by_descriptor =
+      new PyDescriptorPool::ClassesByMessageMap();
+  cpool->descriptor_options =
+      new hash_map<const void*, PyObject *>();
+
+  return cpool;
+}
+
+// Create a Python DescriptorPool, using the given pool as an underlay:
+// new messages will be added to a custom pool, not to the underlay.
+//
+// Ownership of the underlay is not transferred, its pointer should
+// stay alive.
+static PyDescriptorPool* PyDescriptorPool_NewWithUnderlay(
+    const DescriptorPool* underlay) {
+  PyDescriptorPool* cpool = _CreateDescriptorPool();
+  if (cpool == NULL) {
+    return NULL;
+  }
+  cpool->pool = new DescriptorPool(underlay);
+  cpool->underlay = underlay;
+
+  if (!descriptor_pool_map.insert(
+      std::make_pair(cpool->pool, cpool)).second) {
+    // Should never happen -- would indicate an internal error / bug.
+    PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered");
+    return NULL;
+  }
+
+  return cpool;
+}
+
+static PyDescriptorPool* PyDescriptorPool_NewWithDatabase(
+    DescriptorDatabase* database) {
+  PyDescriptorPool* cpool = _CreateDescriptorPool();
+  if (cpool == NULL) {
+    return NULL;
+  }
+  if (database != NULL) {
+    cpool->pool = new DescriptorPool(database);
+    cpool->database = database;
+  } else {
+    cpool->pool = new DescriptorPool();
+  }
+
+  if (!descriptor_pool_map.insert(std::make_pair(cpool->pool, cpool)).second) {
+    // Should never happen -- would indicate an internal error / bug.
+    PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered");
+    return NULL;
+  }
+
+  return cpool;
+}
+
+// The public DescriptorPool constructor.
+static PyObject* New(PyTypeObject* type,
+                     PyObject* args, PyObject* kwargs) {
+  static char* kwlist[] = {"descriptor_db", 0};
+  PyObject* py_database = NULL;
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &py_database)) {
+    return NULL;
+  }
+  DescriptorDatabase* database = NULL;
+  if (py_database && py_database != Py_None) {
+    database = new PyDescriptorDatabase(py_database);
+  }
+  return reinterpret_cast<PyObject*>(
+      PyDescriptorPool_NewWithDatabase(database));
+}
+
+static void Dealloc(PyDescriptorPool* self) {
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  descriptor_pool_map.erase(self->pool);
+  for (iterator it = self->classes_by_descriptor->begin();
+       it != self->classes_by_descriptor->end(); ++it) {
+    Py_DECREF(it->second);
+  }
+  delete self->classes_by_descriptor;
+  for (hash_map<const void*, PyObject*>::iterator it =
+           self->descriptor_options->begin();
+       it != self->descriptor_options->end(); ++it) {
+    Py_DECREF(it->second);
+  }
+  delete self->descriptor_options;
+  delete self->message_factory;
+  delete self->database;
+  delete self->pool;
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const Descriptor* message_descriptor =
+      self->pool->FindMessageTypeByName(string(name, name_size));
+
+  if (message_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name);
+    return NULL;
+  }
+
+  return PyMessageDescriptor_FromDescriptor(message_descriptor);
+}
+
+// Add a message class to our database.
+int RegisterMessageClass(PyDescriptorPool* self,
+                         const Descriptor* message_descriptor,
+                         CMessageClass* message_class) {
+  Py_INCREF(message_class);
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
+      std::make_pair(message_descriptor, message_class));
+  if (!ret.second) {
+    // Update case: DECREF the previous value.
+    Py_DECREF(ret.first->second);
+    ret.first->second = message_class;
+  }
+  return 0;
+}
+
+// Retrieve the message class added to our database.
+CMessageClass* GetMessageClass(PyDescriptorPool* self,
+                               const Descriptor* message_descriptor) {
+  typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+  iterator ret = self->classes_by_descriptor->find(message_descriptor);
+  if (ret == self->classes_by_descriptor->end()) {
+    PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
+                 message_descriptor->full_name().c_str());
+    return NULL;
+  } else {
+    return ret->second;
+  }
+}
+
+PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FileDescriptor* file_descriptor =
+      self->pool->FindFileByName(string(name, name_size));
+  if (file_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s",
+                 name);
+    return NULL;
+  }
+
+  return PyFileDescriptor_FromDescriptor(file_descriptor);
+}
+
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FieldDescriptor* field_descriptor =
+      self->pool->FindFieldByName(string(name, name_size));
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s",
+                 name);
+    return NULL;
+  }
+
+  return PyFieldDescriptor_FromDescriptor(field_descriptor);
+}
+
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FieldDescriptor* field_descriptor =
+      self->pool->FindExtensionByName(string(name, name_size));
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name);
+    return NULL;
+  }
+
+  return PyFieldDescriptor_FromDescriptor(field_descriptor);
+}
+
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const EnumDescriptor* enum_descriptor =
+      self->pool->FindEnumTypeByName(string(name, name_size));
+  if (enum_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name);
+    return NULL;
+  }
+
+  return PyEnumDescriptor_FromDescriptor(enum_descriptor);
+}
+
+PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const OneofDescriptor* oneof_descriptor =
+      self->pool->FindOneofByName(string(name, name_size));
+  if (oneof_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name);
+    return NULL;
+  }
+
+  return PyOneofDescriptor_FromDescriptor(oneof_descriptor);
+}
+
+PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char* name;
+  if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+    return NULL;
+  }
+
+  const FileDescriptor* file_descriptor =
+      self->pool->FindFileContainingSymbol(string(name, name_size));
+  if (file_descriptor == NULL) {
+    PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name);
+    return NULL;
+  }
+
+  return PyFileDescriptor_FromDescriptor(file_descriptor);
+}
+
+// These functions should not exist -- the only valid way to create
+// descriptors is to call Add() or AddSerializedFile().
+// But these AddDescriptor() functions were created in Python and some people
+// call them, so we support them for now for compatibility.
+// However we do check that the existing descriptor already exists in the pool,
+// which appears to always be true for existing calls -- but then why do people
+// call a function that will just be a no-op?
+// TODO(amauryfa): Need to investigate further.
+
+PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
+  const FileDescriptor* file_descriptor =
+      PyFileDescriptor_AsDescriptor(descriptor);
+  if (!file_descriptor) {
+    return NULL;
+  }
+  if (file_descriptor !=
+      self->pool->FindFileByName(file_descriptor->name())) {
+    PyErr_Format(PyExc_ValueError,
+                 "The file descriptor %s does not belong to this pool",
+                 file_descriptor->name().c_str());
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
+  const Descriptor* message_descriptor =
+      PyMessageDescriptor_AsDescriptor(descriptor);
+  if (!message_descriptor) {
+    return NULL;
+  }
+  if (message_descriptor !=
+      self->pool->FindMessageTypeByName(message_descriptor->full_name())) {
+    PyErr_Format(PyExc_ValueError,
+                 "The message descriptor %s does not belong to this pool",
+                 message_descriptor->full_name().c_str());
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
+  const EnumDescriptor* enum_descriptor =
+      PyEnumDescriptor_AsDescriptor(descriptor);
+  if (!enum_descriptor) {
+    return NULL;
+  }
+  if (enum_descriptor !=
+      self->pool->FindEnumTypeByName(enum_descriptor->full_name())) {
+    PyErr_Format(PyExc_ValueError,
+                 "The enum descriptor %s does not belong to this pool",
+                 enum_descriptor->full_name().c_str());
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+// The code below loads new Descriptors from a serialized FileDescriptorProto.
+
+
+// Collects errors that occur during proto file building to allow them to be
+// propagated in the python exception instead of only living in ERROR logs.
+class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  BuildFileErrorCollector() : error_message(""), had_errors(false) {}
+
+  void AddError(const string& filename, const string& element_name,
+                const Message* descriptor, ErrorLocation location,
+                const string& message) {
+    // Replicates the logging behavior that happens in the C++ implementation
+    // when an error collector is not passed in.
+    if (!had_errors) {
+      error_message +=
+          ("Invalid proto descriptor for file \"" + filename + "\":\n");
+      had_errors = true;
+    }
+    // As this only happens on failure and will result in the program not
+    // running at all, no effort is made to optimize this string manipulation.
+    error_message += ("  " + element_name + ": " + message + "\n");
+  }
+
+  string error_message;
+  bool had_errors;
+};
+
+PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) {
+  char* message_type;
+  Py_ssize_t message_len;
+
+  if (self->database != NULL) {
+    PyErr_SetString(
+        PyExc_ValueError,
+        "Cannot call Add on a DescriptorPool that uses a DescriptorDatabase. "
+        "Add your file to the underlying database.");
+    return NULL;
+  }
+
+  if (PyBytes_AsStringAndSize(serialized_pb, &message_type, &message_len) < 0) {
+    return NULL;
+  }
+
+  FileDescriptorProto file_proto;
+  if (!file_proto.ParseFromArray(message_type, message_len)) {
+    PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
+    return NULL;
+  }
+
+  // If the file was already part of a C++ library, all its descriptors are in
+  // the underlying pool.  No need to do anything else.
+  const FileDescriptor* generated_file = NULL;
+  if (self->underlay) {
+    generated_file = self->underlay->FindFileByName(file_proto.name());
+  }
+  if (generated_file != NULL) {
+    return PyFileDescriptor_FromDescriptorWithSerializedPb(
+        generated_file, serialized_pb);
+  }
+
+  BuildFileErrorCollector error_collector;
+  const FileDescriptor* descriptor =
+      self->pool->BuildFileCollectingErrors(file_proto,
+                                            &error_collector);
+  if (descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError,
+                 "Couldn't build proto file into descriptor pool!\n%s",
+                 error_collector.error_message.c_str());
+    return NULL;
+  }
+
+  return PyFileDescriptor_FromDescriptorWithSerializedPb(
+      descriptor, serialized_pb);
+}
+
+PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) {
+  ScopedPyObjectPtr serialized_pb(
+      PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL));
+  if (serialized_pb == NULL) {
+    return NULL;
+  }
+  return AddSerializedFile(self, serialized_pb.get());
+}
+
+static PyMethodDef Methods[] = {
+  { "Add", (PyCFunction)Add, METH_O,
+    "Adds the FileDescriptorProto and its types to this pool." },
+  { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O,
+    "Adds a serialized FileDescriptorProto to this pool." },
+
+  // TODO(amauryfa): Understand why the Python implementation differs from
+  // this one, ask users to use another API and deprecate these functions.
+  { "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O,
+    "No-op. Add() must have been called before." },
+  { "AddDescriptor", (PyCFunction)AddDescriptor, METH_O,
+    "No-op. Add() must have been called before." },
+  { "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O,
+    "No-op. Add() must have been called before." },
+
+  { "FindFileByName", (PyCFunction)FindFileByName, METH_O,
+    "Searches for a file descriptor by its .proto name." },
+  { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O,
+    "Searches for a message descriptor by full name." },
+  { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O,
+    "Searches for a field descriptor by full name." },
+  { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O,
+    "Searches for extension descriptor by full name." },
+  { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O,
+    "Searches for enum type descriptor by full name." },
+  { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O,
+    "Searches for oneof descriptor by full name." },
+
+  { "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O,
+    "Gets the FileDescriptor containing the specified symbol." },
+  {NULL}
+};
+
+}  // namespace cdescriptor_pool
+
+PyTypeObject PyDescriptorPool_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".DescriptorPool",  // tp_name
+  sizeof(PyDescriptorPool),            // tp_basicsize
+  0,                                   // tp_itemsize
+  (destructor)cdescriptor_pool::Dealloc,  // tp_dealloc
+  0,                                   // tp_print
+  0,                                   // tp_getattr
+  0,                                   // tp_setattr
+  0,                                   // tp_compare
+  0,                                   // tp_repr
+  0,                                   // tp_as_number
+  0,                                   // tp_as_sequence
+  0,                                   // tp_as_mapping
+  0,                                   // tp_hash
+  0,                                   // tp_call
+  0,                                   // tp_str
+  0,                                   // tp_getattro
+  0,                                   // tp_setattro
+  0,                                   // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  // tp_flags
+  "A Descriptor Pool",                 // tp_doc
+  0,                                   // tp_traverse
+  0,                                   // tp_clear
+  0,                                   // tp_richcompare
+  0,                                   // tp_weaklistoffset
+  0,                                   // tp_iter
+  0,                                   // tp_iternext
+  cdescriptor_pool::Methods,           // tp_methods
+  0,                                   // tp_members
+  0,                                   // tp_getset
+  0,                                   // tp_base
+  0,                                   // tp_dict
+  0,                                   // tp_descr_get
+  0,                                   // tp_descr_set
+  0,                                   // tp_dictoffset
+  0,                                   // tp_init
+  0,                                   // tp_alloc
+  cdescriptor_pool::New,               // tp_new
+  PyObject_Del,                        // tp_free
+};
+
+// This is the DescriptorPool which contains all the definitions from the
+// generated _pb2.py modules.
+static PyDescriptorPool* python_generated_pool = NULL;
+
+bool InitDescriptorPool() {
+  if (PyType_Ready(&PyDescriptorPool_Type) < 0)
+    return false;
+
+  // The Pool of messages declared in Python libraries.
+  // generated_pool() contains all messages already linked in C++ libraries, and
+  // is used as underlay.
+  python_generated_pool = cdescriptor_pool::PyDescriptorPool_NewWithUnderlay(
+      DescriptorPool::generated_pool());
+  if (python_generated_pool == NULL) {
+    return false;
+  }
+  // Register this pool to be found for C++-generated descriptors.
+  descriptor_pool_map.insert(
+      std::make_pair(DescriptorPool::generated_pool(),
+                     python_generated_pool));
+
+  return true;
+}
+
+// The default DescriptorPool used everywhere in this module.
+// Today it's the python_generated_pool.
+// TODO(amauryfa): Remove all usages of this function: the pool should be
+// derived from the context.
+PyDescriptorPool* GetDefaultDescriptorPool() {
+  return python_generated_pool;
+}
+
+PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool) {
+  // Fast path for standard descriptors.
+  if (pool == python_generated_pool->pool ||
+      pool == DescriptorPool::generated_pool()) {
+    return python_generated_pool;
+  }
+  hash_map<const DescriptorPool*, PyDescriptorPool*>::iterator it =
+      descriptor_pool_map.find(pool);
+  if (it == descriptor_pool_map.end()) {
+    PyErr_SetString(PyExc_KeyError, "Unknown descriptor pool");
+    return NULL;
+  }
+  return it->second;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.h
new file mode 100644
index 0000000..2a42c11
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/descriptor_pool.h
@@ -0,0 +1,167 @@
+// 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_PYTHON_CPP_DESCRIPTOR_POOL_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
+
+#include <Python.h>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+class MessageFactory;
+
+namespace python {
+
+// The (meta) type of all Messages classes.
+struct CMessageClass;
+
+// Wraps operations to the global DescriptorPool which contains information
+// about all messages and fields.
+//
+// There is normally one pool per process. We make it a Python object only
+// because it contains many Python references.
+// TODO(amauryfa): See whether such objects can appear in reference cycles, and
+// consider adding support for the cyclic GC.
+//
+// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
+// namespace.
+typedef struct PyDescriptorPool {
+  PyObject_HEAD
+
+  // The C++ pool containing Descriptors.
+  DescriptorPool* pool;
+
+  // The C++ pool acting as an underlay. Can be NULL.
+  // This pointer is not owned and must stay alive.
+  const DescriptorPool* underlay;
+
+  // The C++ descriptor database used to fetch unknown protos. Can be NULL.
+  // This pointer is owned.
+  const DescriptorDatabase* database;
+
+  // DynamicMessageFactory used to create C++ instances of messages.
+  // This object cache the descriptors that were used, so the DescriptorPool
+  // needs to get rid of it before it can delete itself.
+  //
+  // Note: A C++ MessageFactory is different from the Python MessageFactory.
+  // The C++ one creates messages, when the Python one creates classes.
+  MessageFactory* message_factory;
+
+  // Make our own mapping to retrieve Python classes from C++ descriptors.
+  //
+  // Descriptor pointers stored here are owned by the DescriptorPool above.
+  // Python references to classes are owned by this PyDescriptorPool.
+  typedef hash_map<const Descriptor*, CMessageClass*> ClassesByMessageMap;
+  ClassesByMessageMap* classes_by_descriptor;
+
+  // Cache the options for any kind of descriptor.
+  // Descriptor pointers are owned by the DescriptorPool above.
+  // Python objects are owned by the map.
+  hash_map<const void*, PyObject*>* descriptor_options;
+} PyDescriptorPool;
+
+
+extern PyTypeObject PyDescriptorPool_Type;
+
+namespace cdescriptor_pool {
+
+// Looks up a message by name.
+// Returns a message Descriptor, or NULL if not found.
+const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
+                                        const string& name);
+
+// Registers a new Python class for the given message descriptor.
+// On error, returns -1 with a Python exception set.
+int RegisterMessageClass(PyDescriptorPool* self,
+                         const Descriptor* message_descriptor,
+                         CMessageClass* message_class);
+
+// Retrieves the Python class registered with the given message descriptor.
+//
+// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// exception set.
+CMessageClass* GetMessageClass(PyDescriptorPool* self,
+                               const Descriptor* message_descriptor);
+
+// The functions below are also exposed as methods of the DescriptorPool type.
+
+// Looks up a message by name. Returns a PyMessageDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up a field by name. Returns a PyFieldDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up an extension by name. Returns a PyFieldDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up an enum type by name. Returns a PyEnumDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up a oneof by name. Returns a COneofDescriptor corresponding
+// to the oneof on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg);
+
+}  // namespace cdescriptor_pool
+
+// Retrieve the global descriptor pool owned by the _message module.
+// This is the one used by pb2.py generated modules.
+// Returns a *borrowed* reference.
+// "Default" pool used to register messages from _pb2.py modules.
+PyDescriptorPool* GetDefaultDescriptorPool();
+
+// Retrieve the python descriptor pool owning a C++ descriptor pool.
+// Returns a *borrowed* reference.
+PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool);
+
+// Initialize objects used by this module.
+bool InitDescriptorPool();
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.cc
new file mode 100644
index 0000000..21bbb8c
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.cc
@@ -0,0 +1,337 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#include <google/protobuf/pyext/extension_dict.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/repeated_composite_container.h>
+#include <google/protobuf/pyext/repeated_scalar_container.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include <google/protobuf/stubs/shared_ptr.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+namespace extension_dict {
+
+PyObject* len(ExtensionDict* self) {
+#if PY_MAJOR_VERSION >= 3
+  return PyLong_FromLong(PyDict_Size(self->values));
+#else
+  return PyInt_FromLong(PyDict_Size(self->values));
+#endif
+}
+
+// TODO(tibell): Use VisitCompositeField.
+int ReleaseExtension(ExtensionDict* self,
+                     PyObject* extension,
+                     const FieldDescriptor* descriptor) {
+  if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (repeated_composite_container::Release(
+              reinterpret_cast<RepeatedCompositeContainer*>(
+                  extension)) < 0) {
+        return -1;
+      }
+    } else {
+      if (repeated_scalar_container::Release(
+              reinterpret_cast<RepeatedScalarContainer*>(
+                  extension)) < 0) {
+        return -1;
+      }
+    }
+  } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    if (cmessage::ReleaseSubMessage(
+            self->parent, descriptor,
+            reinterpret_cast<CMessage*>(extension)) < 0) {
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+PyObject* subscript(ExtensionDict* self, PyObject* key) {
+  const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
+    return NULL;
+  }
+
+  if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
+      descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    return cmessage::InternalGetScalar(self->message, descriptor);
+  }
+
+  PyObject* value = PyDict_GetItem(self->values, key);
+  if (value != NULL) {
+    Py_INCREF(value);
+    return value;
+  }
+
+  if (self->parent == NULL) {
+    // We are in "detached" state. Don't allow further modifications.
+    // TODO(amauryfa): Support adding non-scalars to a detached extension dict.
+    // This probably requires to store the type of the main message.
+    PyErr_SetObject(PyExc_KeyError, key);
+    return NULL;
+  }
+
+  if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
+      descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    PyObject* sub_message = cmessage::InternalGetSubMessage(
+        self->parent, descriptor);
+    if (sub_message == NULL) {
+      return NULL;
+    }
+    PyDict_SetItem(self->values, key, sub_message);
+    return sub_message;
+  }
+
+  if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      CMessageClass* message_class = cdescriptor_pool::GetMessageClass(
+          cmessage::GetDescriptorPoolForMessage(self->parent),
+          descriptor->message_type());
+      if (message_class == NULL) {
+        return NULL;
+      }
+      PyObject* py_container = repeated_composite_container::NewContainer(
+          self->parent, descriptor, message_class);
+      if (py_container == NULL) {
+        return NULL;
+      }
+      PyDict_SetItem(self->values, key, py_container);
+      return py_container;
+    } else {
+      PyObject* py_container = repeated_scalar_container::NewContainer(
+          self->parent, descriptor);
+      if (py_container == NULL) {
+        return NULL;
+      }
+      PyDict_SetItem(self->values, key, py_container);
+      return py_container;
+    }
+  }
+  PyErr_SetString(PyExc_ValueError, "control reached unexpected line");
+  return NULL;
+}
+
+int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
+  const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
+  if (descriptor == NULL) {
+    return -1;
+  }
+  if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
+    return -1;
+  }
+
+  if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL ||
+      descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite "
+                    "type");
+    return -1;
+  }
+  if (self->parent) {
+    cmessage::AssureWritable(self->parent);
+    if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) {
+      return -1;
+    }
+  }
+  // TODO(tibell): We shouldn't write scalars to the cache.
+  PyDict_SetItem(self->values, key, value);
+  return 0;
+}
+
+PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
+  const FieldDescriptor* descriptor =
+      cmessage::GetExtensionDescriptor(extension);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  PyObject* value = PyDict_GetItem(self->values, extension);
+  if (self->parent) {
+    if (value != NULL) {
+      if (ReleaseExtension(self, value, descriptor) < 0) {
+        return NULL;
+      }
+    }
+    if (ScopedPyObjectPtr(cmessage::ClearFieldByDescriptor(
+            self->parent, descriptor)) == NULL) {
+      return NULL;
+    }
+  }
+  if (PyDict_DelItem(self->values, extension) < 0) {
+    PyErr_Clear();
+  }
+  Py_RETURN_NONE;
+}
+
+PyObject* HasExtension(ExtensionDict* self, PyObject* extension) {
+  const FieldDescriptor* descriptor =
+      cmessage::GetExtensionDescriptor(extension);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  if (self->parent) {
+    return cmessage::HasFieldByDescriptor(self->parent, descriptor);
+  } else {
+    int exists = PyDict_Contains(self->values, extension);
+    if (exists < 0) {
+      return NULL;
+    }
+    return PyBool_FromLong(exists);
+  }
+}
+
+PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) {
+  ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString(
+      reinterpret_cast<PyObject*>(self->parent), "_extensions_by_name"));
+  if (extensions_by_name == NULL) {
+    return NULL;
+  }
+  PyObject* result = PyDict_GetItem(extensions_by_name.get(), name);
+  if (result == NULL) {
+    Py_RETURN_NONE;
+  } else {
+    Py_INCREF(result);
+    return result;
+  }
+}
+
+PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number) {
+  ScopedPyObjectPtr extensions_by_number(PyObject_GetAttrString(
+      reinterpret_cast<PyObject*>(self->parent), "_extensions_by_number"));
+  if (extensions_by_number == NULL) {
+    return NULL;
+  }
+  PyObject* result = PyDict_GetItem(extensions_by_number.get(), number);
+  if (result == NULL) {
+    Py_RETURN_NONE;
+  } else {
+    Py_INCREF(result);
+    return result;
+  }
+}
+
+ExtensionDict* NewExtensionDict(CMessage *parent) {
+  ExtensionDict* self = reinterpret_cast<ExtensionDict*>(
+      PyType_GenericAlloc(&ExtensionDict_Type, 0));
+  if (self == NULL) {
+    return NULL;
+  }
+
+  self->parent = parent;  // Store a borrowed reference.
+  self->message = parent->message;
+  self->owner = parent->owner;
+  self->values = PyDict_New();
+  return self;
+}
+
+void dealloc(ExtensionDict* self) {
+  Py_CLEAR(self->values);
+  self->owner.reset();
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyMappingMethods MpMethods = {
+  (lenfunc)len,               /* mp_length */
+  (binaryfunc)subscript,      /* mp_subscript */
+  (objobjargproc)ass_subscript,/* mp_ass_subscript */
+};
+
+#define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc }
+static PyMethodDef Methods[] = {
+  EDMETHOD(ClearExtension, METH_O, "Clears an extension from the object."),
+  EDMETHOD(HasExtension, METH_O, "Checks if the object has an extension."),
+  EDMETHOD(_FindExtensionByName, METH_O,
+           "Finds an extension by name."),
+  EDMETHOD(_FindExtensionByNumber, METH_O,
+           "Finds an extension by field number."),
+  { NULL, NULL }
+};
+
+}  // namespace extension_dict
+
+PyTypeObject ExtensionDict_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".ExtensionDict",   // tp_name
+  sizeof(ExtensionDict),               // tp_basicsize
+  0,                                   //  tp_itemsize
+  (destructor)extension_dict::dealloc,  //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  0,                                   //  tp_repr
+  0,                                   //  tp_as_number
+  0,                                   //  tp_as_sequence
+  &extension_dict::MpMethods,          //  tp_as_mapping
+  PyObject_HashNotImplemented,         //  tp_hash
+  0,                                   //  tp_call
+  0,                                   //  tp_str
+  0,                                   //  tp_getattro
+  0,                                   //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  //  tp_flags
+  "An extension dict",                 //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  0,                                   //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  0,                                   //  tp_iter
+  0,                                   //  tp_iternext
+  extension_dict::Methods,             //  tp_methods
+  0,                                   //  tp_members
+  0,                                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  0,                                   //  tp_init
+};
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.h
new file mode 100644
index 0000000..2456eda
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/extension_dict.h
@@ -0,0 +1,137 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+namespace google {
+namespace protobuf {
+
+class Message;
+class FieldDescriptor;
+
+#ifdef _SHARED_PTR_H
+using std::shared_ptr;
+#else
+using internal::shared_ptr;
+#endif
+
+namespace python {
+
+struct CMessage;
+
+typedef struct ExtensionDict {
+  PyObject_HEAD;
+
+  // This is the top-level C++ Message object that owns the whole
+  // proto tree.  Every Python container class holds a
+  // reference to it in order to keep it alive as long as there's a
+  // Python object that references any part of the tree.
+  shared_ptr<Message> owner;
+
+  // Weak reference to parent message. Used to make sure
+  // the parent is writable when an extension field is modified.
+  CMessage* parent;
+
+  // Pointer to the C++ Message that this ExtensionDict extends.
+  // Not owned by us.
+  Message* message;
+
+  // A dict of child messages, indexed by Extension descriptors.
+  // Similar to CMessage::composite_fields.
+  PyObject* values;
+} ExtensionDict;
+
+extern PyTypeObject ExtensionDict_Type;
+
+namespace extension_dict {
+
+// Builds an Extensions dict for a specific message.
+ExtensionDict* NewExtensionDict(CMessage *parent);
+
+// Gets the number of extension values in this ExtensionDict as a python object.
+//
+// Returns a new reference.
+PyObject* len(ExtensionDict* self);
+
+// Releases extensions referenced outside this dictionary to keep outside
+// references alive.
+//
+// Returns 0 on success, -1 on failure.
+int ReleaseExtension(ExtensionDict* self,
+                     PyObject* extension,
+                     const FieldDescriptor* descriptor);
+
+// Gets an extension from the dict for the given extension descriptor.
+//
+// Returns a new reference.
+PyObject* subscript(ExtensionDict* self, PyObject* key);
+
+// Assigns a value to an extension in the dict. Can only be used for singular
+// simple types.
+//
+// Returns 0 on success, -1 on failure.
+int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value);
+
+// Clears an extension from the dict. Will release the extension if there
+// is still an external reference left to it.
+//
+// Returns None on success.
+PyObject* ClearExtension(ExtensionDict* self,
+                                       PyObject* extension);
+
+// Gets an extension from the dict given the extension name as opposed to
+// descriptor.
+//
+// Returns a new reference.
+PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name);
+
+// Gets an extension from the dict given the extension field number as
+// opposed to descriptor.
+//
+// Returns a new reference.
+PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number);
+
+}  // namespace extension_dict
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.cc
new file mode 100644
index 0000000..e022406
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.cc
@@ -0,0 +1,970 @@
+// 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.
+
+// Author: haberman@google.com (Josh Haberman)
+
+#include <google/protobuf/pyext/map_container.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyInt_FromLong PyLong_FromLong
+  #define PyInt_FromSize_t PyLong_FromSize_t
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// Functions that need access to map reflection functionality.
+// They need to be contained in this class because it is friended.
+class MapReflectionFriend {
+ public:
+  // Methods that are in common between the map types.
+  static PyObject* Contains(PyObject* _self, PyObject* key);
+  static Py_ssize_t Length(PyObject* _self);
+  static PyObject* GetIterator(PyObject *_self);
+  static PyObject* IterNext(PyObject* _self);
+
+  // Methods that differ between the map types.
+  static PyObject* ScalarMapGetItem(PyObject* _self, PyObject* key);
+  static PyObject* MessageMapGetItem(PyObject* _self, PyObject* key);
+  static int ScalarMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
+  static int MessageMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
+};
+
+struct MapIterator {
+  PyObject_HEAD;
+
+  google::protobuf::scoped_ptr< ::google::protobuf::MapIterator> iter;
+
+  // A pointer back to the container, so we can notice changes to the version.
+  // We own a ref on this.
+  MapContainer* container;
+
+  // We need to keep a ref on the Message* too, because
+  // MapIterator::~MapIterator() accesses it.  Normally this would be ok because
+  // the ref on container (above) would guarantee outlive semantics.  However in
+  // the case of ClearField(), InitializeAndCopyToParentContainer() resets the
+  // message pointer (and the owner) to a different message, a copy of the
+  // original.  But our iterator still points to the original, which could now
+  // get deleted before us.
+  //
+  // To prevent this, we ensure that the Message will always stay alive as long
+  // as this iterator does.  This is solely for the benefit of the MapIterator
+  // destructor -- we should never actually access the iterator in this state
+  // except to delete it.
+  shared_ptr<Message> owner;
+
+  // The version of the map when we took the iterator to it.
+  //
+  // We store this so that if the map is modified during iteration we can throw
+  // an error.
+  uint64 version;
+
+  // True if the container is empty.  We signal this separately to avoid calling
+  // any of the iteration methods, which are non-const.
+  bool empty;
+};
+
+Message* MapContainer::GetMutableMessage() {
+  cmessage::AssureWritable(parent);
+  return const_cast<Message*>(message);
+}
+
+// Consumes a reference on the Python string object.
+static bool PyStringToSTL(PyObject* py_string, string* stl_string) {
+  char *value;
+  Py_ssize_t value_len;
+
+  if (!py_string) {
+    return false;
+  }
+  if (PyBytes_AsStringAndSize(py_string, &value, &value_len) < 0) {
+    Py_DECREF(py_string);
+    return false;
+  } else {
+    stl_string->assign(value, value_len);
+    Py_DECREF(py_string);
+    return true;
+  }
+}
+
+static bool PythonToMapKey(PyObject* obj,
+                           const FieldDescriptor* field_descriptor,
+                           MapKey* key) {
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(obj, value, false);
+      key->SetInt32Value(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(obj, value, false);
+      key->SetInt64Value(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(obj, value, false);
+      key->SetUInt32Value(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(obj, value, false);
+      key->SetUInt64Value(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(obj, value, false);
+      key->SetBoolValue(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string str;
+      if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) {
+        return false;
+      }
+      key->SetStringValue(str);
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Type %d cannot be a map key",
+          field_descriptor->cpp_type());
+      return false;
+  }
+  return true;
+}
+
+static PyObject* MapKeyToPython(const FieldDescriptor* field_descriptor,
+                                const MapKey& key) {
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return PyInt_FromLong(key.GetInt32Value());
+    case FieldDescriptor::CPPTYPE_INT64:
+      return PyLong_FromLongLong(key.GetInt64Value());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return PyInt_FromSize_t(key.GetUInt32Value());
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return PyLong_FromUnsignedLongLong(key.GetUInt64Value());
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return PyBool_FromLong(key.GetBoolValue());
+    case FieldDescriptor::CPPTYPE_STRING:
+      return ToStringObject(field_descriptor, key.GetStringValue());
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Couldn't convert type %d to value",
+          field_descriptor->cpp_type());
+      return NULL;
+  }
+}
+
+// This is only used for ScalarMap, so we don't need to handle the
+// CPPTYPE_MESSAGE case.
+PyObject* MapValueRefToPython(const FieldDescriptor* field_descriptor,
+                              MapValueRef* value) {
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return PyInt_FromLong(value->GetInt32Value());
+    case FieldDescriptor::CPPTYPE_INT64:
+      return PyLong_FromLongLong(value->GetInt64Value());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return PyInt_FromSize_t(value->GetUInt32Value());
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return PyLong_FromUnsignedLongLong(value->GetUInt64Value());
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return PyFloat_FromDouble(value->GetFloatValue());
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return PyFloat_FromDouble(value->GetDoubleValue());
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return PyBool_FromLong(value->GetBoolValue());
+    case FieldDescriptor::CPPTYPE_STRING:
+      return ToStringObject(field_descriptor, value->GetStringValue());
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return PyInt_FromLong(value->GetEnumValue());
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Couldn't convert type %d to value",
+          field_descriptor->cpp_type());
+      return NULL;
+  }
+}
+
+// This is only used for ScalarMap, so we don't need to handle the
+// CPPTYPE_MESSAGE case.
+static bool PythonToMapValueRef(PyObject* obj,
+                                const FieldDescriptor* field_descriptor,
+                                bool allow_unknown_enum_values,
+                                MapValueRef* value_ref) {
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(obj, value, false);
+      value_ref->SetInt32Value(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(obj, value, false);
+      value_ref->SetInt64Value(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(obj, value, false);
+      value_ref->SetUInt32Value(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(obj, value, false);
+      value_ref->SetUInt64Value(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(obj, value, false);
+      value_ref->SetFloatValue(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(obj, value, false);
+      value_ref->SetDoubleValue(value);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(obj, value, false);
+      value_ref->SetBoolValue(value);
+      return true;;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string str;
+      if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) {
+        return false;
+      }
+      value_ref->SetStringValue(str);
+      return true;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(obj, value, false);
+      if (allow_unknown_enum_values) {
+        value_ref->SetEnumValue(value);
+        return true;
+      } else {
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          value_ref->SetEnumValue(value);
+          return true;
+        } else {
+          PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
+          return false;
+        }
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Setting value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+      return false;
+  }
+}
+
+// Map methods common to ScalarMap and MessageMap //////////////////////////////
+
+static MapContainer* GetMap(PyObject* obj) {
+  return reinterpret_cast<MapContainer*>(obj);
+}
+
+Py_ssize_t MapReflectionFriend::Length(PyObject* _self) {
+  MapContainer* self = GetMap(_self);
+  const google::protobuf::Message* message = self->message;
+  return message->GetReflection()->MapSize(*message,
+                                           self->parent_field_descriptor);
+}
+
+PyObject* Clear(PyObject* _self) {
+  MapContainer* self = GetMap(_self);
+  Message* message = self->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+
+  reflection->ClearField(message, self->parent_field_descriptor);
+
+  Py_RETURN_NONE;
+}
+
+PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) {
+  MapContainer* self = GetMap(_self);
+
+  const Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
+  MapKey map_key;
+
+  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+    return NULL;
+  }
+
+  if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
+                                 map_key)) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+// Initializes the underlying Message object of "to" so it becomes a new parent
+// repeated scalar, and copies all the values from "from" to it. A child scalar
+// container can be released by passing it as both from and to (e.g. making it
+// the recipient of the new parent message and copying the values from itself).
+static int InitializeAndCopyToParentContainer(MapContainer* from,
+                                              MapContainer* to) {
+  // For now we require from == to, re-evaluate if we want to support deep copy
+  // as in repeated_scalar_container.cc.
+  GOOGLE_DCHECK(from == to);
+  Message* new_message = from->message->New();
+
+  if (MapReflectionFriend::Length(reinterpret_cast<PyObject*>(from)) > 0) {
+    // A somewhat roundabout way of copying just one field from old_message to
+    // new_message.  This is the best we can do with what Reflection gives us.
+    Message* mutable_old = from->GetMutableMessage();
+    vector<const FieldDescriptor*> fields;
+    fields.push_back(from->parent_field_descriptor);
+
+    // Move the map field into the new message.
+    mutable_old->GetReflection()->SwapFields(mutable_old, new_message, fields);
+
+    // If/when we support from != to, this will be required also to copy the
+    // map field back into the existing message:
+    // mutable_old->MergeFrom(*new_message);
+  }
+
+  // If from == to this could delete old_message.
+  to->owner.reset(new_message);
+
+  to->parent = NULL;
+  to->parent_field_descriptor = from->parent_field_descriptor;
+  to->message = new_message;
+
+  // Invalidate iterators, since they point to the old copy of the field.
+  to->version++;
+
+  return 0;
+}
+
+int MapContainer::Release() {
+  return InitializeAndCopyToParentContainer(this, this);
+}
+
+
+// ScalarMap ///////////////////////////////////////////////////////////////////
+
+PyObject *NewScalarMapContainer(
+    CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
+  if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+    return NULL;
+  }
+
+#if PY_MAJOR_VERSION >= 3
+  ScopedPyObjectPtr obj(PyType_GenericAlloc(
+        reinterpret_cast<PyTypeObject *>(ScalarMapContainer_Type), 0));
+#else
+  ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0));
+#endif
+  if (obj.get() == NULL) {
+    return PyErr_Format(PyExc_RuntimeError,
+                        "Could not allocate new container.");
+  }
+
+  MapContainer* self = GetMap(obj.get());
+
+  self->message = parent->message;
+  self->parent = parent;
+  self->parent_field_descriptor = parent_field_descriptor;
+  self->owner = parent->owner;
+  self->version = 0;
+
+  self->key_field_descriptor =
+      parent_field_descriptor->message_type()->FindFieldByName("key");
+  self->value_field_descriptor =
+      parent_field_descriptor->message_type()->FindFieldByName("value");
+
+  if (self->key_field_descriptor == NULL ||
+      self->value_field_descriptor == NULL) {
+    return PyErr_Format(PyExc_KeyError,
+                        "Map entry descriptor did not have key/value fields");
+  }
+
+  return obj.release();
+}
+
+PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self,
+                                                PyObject* key) {
+  MapContainer* self = GetMap(_self);
+
+  Message* message = self->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+  MapKey map_key;
+  MapValueRef value;
+
+  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+    return NULL;
+  }
+
+  if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
+                                         map_key, &value)) {
+    self->version++;
+  }
+
+  return MapValueRefToPython(self->value_field_descriptor, &value);
+}
+
+int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key,
+                                          PyObject* v) {
+  MapContainer* self = GetMap(_self);
+
+  Message* message = self->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+  MapKey map_key;
+  MapValueRef value;
+
+  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+    return -1;
+  }
+
+  self->version++;
+
+  if (v) {
+    // Set item to v.
+    reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
+                                       map_key, &value);
+
+    return PythonToMapValueRef(v, self->value_field_descriptor,
+                               reflection->SupportsUnknownEnumValues(), &value)
+               ? 0
+               : -1;
+  } else {
+    // Delete key from map.
+    if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
+                                   map_key)) {
+      return 0;
+    } else {
+      PyErr_Format(PyExc_KeyError, "Key not present in map");
+      return -1;
+    }
+  }
+}
+
+static PyObject* ScalarMapGet(PyObject* self, PyObject* args) {
+  PyObject* key;
+  PyObject* default_value = NULL;
+  if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
+    return NULL;
+  }
+
+  ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
+  if (is_present.get() == NULL) {
+    return NULL;
+  }
+
+  if (PyObject_IsTrue(is_present.get())) {
+    return MapReflectionFriend::ScalarMapGetItem(self, key);
+  } else {
+    if (default_value != NULL) {
+      Py_INCREF(default_value);
+      return default_value;
+    } else {
+      Py_RETURN_NONE;
+    }
+  }
+}
+
+static void ScalarMapDealloc(PyObject* _self) {
+  MapContainer* self = GetMap(_self);
+  self->owner.reset();
+  Py_TYPE(_self)->tp_free(_self);
+}
+
+static PyMethodDef ScalarMapMethods[] = {
+  { "__contains__", MapReflectionFriend::Contains, METH_O,
+    "Tests whether a key is a member of the map." },
+  { "clear", (PyCFunction)Clear, METH_NOARGS,
+    "Removes all elements from the map." },
+  { "get", ScalarMapGet, METH_VARARGS,
+    "Gets the value for the given key if present, or otherwise a default" },
+  /*
+  { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+    "Makes a deep copy of the class." },
+  { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+    "Outputs picklable representation of the repeated field." },
+  */
+  {NULL, NULL},
+};
+
+#if PY_MAJOR_VERSION >= 3
+  static PyType_Slot ScalarMapContainer_Type_slots[] = {
+      {Py_tp_dealloc, (void *)ScalarMapDealloc},
+      {Py_mp_length, (void *)MapReflectionFriend::Length},
+      {Py_mp_subscript, (void *)MapReflectionFriend::ScalarMapGetItem},
+      {Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem},
+      {Py_tp_methods, (void *)ScalarMapMethods},
+      {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
+      {0, 0},
+  };
+
+  PyType_Spec ScalarMapContainer_Type_spec = {
+      FULL_MODULE_NAME ".ScalarMapContainer",
+      sizeof(MapContainer),
+      0,
+      Py_TPFLAGS_DEFAULT,
+      ScalarMapContainer_Type_slots
+  };
+  PyObject *ScalarMapContainer_Type;
+#else
+  static PyMappingMethods ScalarMapMappingMethods = {
+    MapReflectionFriend::Length,             // mp_length
+    MapReflectionFriend::ScalarMapGetItem,   // mp_subscript
+    MapReflectionFriend::ScalarMapSetItem,   // mp_ass_subscript
+  };
+
+  PyTypeObject ScalarMapContainer_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    FULL_MODULE_NAME ".ScalarMapContainer",  //  tp_name
+    sizeof(MapContainer),                //  tp_basicsize
+    0,                                   //  tp_itemsize
+    ScalarMapDealloc,                    //  tp_dealloc
+    0,                                   //  tp_print
+    0,                                   //  tp_getattr
+    0,                                   //  tp_setattr
+    0,                                   //  tp_compare
+    0,                                   //  tp_repr
+    0,                                   //  tp_as_number
+    0,                                   //  tp_as_sequence
+    &ScalarMapMappingMethods,            //  tp_as_mapping
+    0,                                   //  tp_hash
+    0,                                   //  tp_call
+    0,                                   //  tp_str
+    0,                                   //  tp_getattro
+    0,                                   //  tp_setattro
+    0,                                   //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                  //  tp_flags
+    "A scalar map container",            //  tp_doc
+    0,                                   //  tp_traverse
+    0,                                   //  tp_clear
+    0,                                   //  tp_richcompare
+    0,                                   //  tp_weaklistoffset
+    MapReflectionFriend::GetIterator,    //  tp_iter
+    0,                                   //  tp_iternext
+    ScalarMapMethods,                    //  tp_methods
+    0,                                   //  tp_members
+    0,                                   //  tp_getset
+    0,                                   //  tp_base
+    0,                                   //  tp_dict
+    0,                                   //  tp_descr_get
+    0,                                   //  tp_descr_set
+    0,                                   //  tp_dictoffset
+    0,                                   //  tp_init
+  };
+#endif
+
+
+// MessageMap //////////////////////////////////////////////////////////////////
+
+static MessageMapContainer* GetMessageMap(PyObject* obj) {
+  return reinterpret_cast<MessageMapContainer*>(obj);
+}
+
+static PyObject* GetCMessage(MessageMapContainer* self, Message* message) {
+  // Get or create the CMessage object corresponding to this message.
+  ScopedPyObjectPtr key(PyLong_FromVoidPtr(message));
+  PyObject* ret = PyDict_GetItem(self->message_dict, key.get());
+
+  if (ret == NULL) {
+    CMessage* cmsg = cmessage::NewEmptyMessage(self->message_class);
+    ret = reinterpret_cast<PyObject*>(cmsg);
+
+    if (cmsg == NULL) {
+      return NULL;
+    }
+    cmsg->owner = self->owner;
+    cmsg->message = message;
+    cmsg->parent = self->parent;
+
+    if (PyDict_SetItem(self->message_dict, key.get(), ret) < 0) {
+      Py_DECREF(ret);
+      return NULL;
+    }
+  } else {
+    Py_INCREF(ret);
+  }
+
+  return ret;
+}
+
+PyObject* NewMessageMapContainer(
+    CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor,
+    CMessageClass* message_class) {
+  if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+    return NULL;
+  }
+
+#if PY_MAJOR_VERSION >= 3
+  PyObject* obj = PyType_GenericAlloc(
+        reinterpret_cast<PyTypeObject *>(MessageMapContainer_Type), 0);
+#else
+  PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0);
+#endif
+  if (obj == NULL) {
+    return PyErr_Format(PyExc_RuntimeError,
+                        "Could not allocate new container.");
+  }
+
+  MessageMapContainer* self = GetMessageMap(obj);
+
+  self->message = parent->message;
+  self->parent = parent;
+  self->parent_field_descriptor = parent_field_descriptor;
+  self->owner = parent->owner;
+  self->version = 0;
+
+  self->key_field_descriptor =
+      parent_field_descriptor->message_type()->FindFieldByName("key");
+  self->value_field_descriptor =
+      parent_field_descriptor->message_type()->FindFieldByName("value");
+
+  self->message_dict = PyDict_New();
+  if (self->message_dict == NULL) {
+    return PyErr_Format(PyExc_RuntimeError,
+                        "Could not allocate message dict.");
+  }
+
+  Py_INCREF(message_class);
+  self->message_class = message_class;
+
+  if (self->key_field_descriptor == NULL ||
+      self->value_field_descriptor == NULL) {
+    Py_DECREF(obj);
+    return PyErr_Format(PyExc_KeyError,
+                        "Map entry descriptor did not have key/value fields");
+  }
+
+  return obj;
+}
+
+int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key,
+                                           PyObject* v) {
+  if (v) {
+    PyErr_Format(PyExc_ValueError,
+                 "Direct assignment of submessage not allowed");
+    return -1;
+  }
+
+  // Now we know that this is a delete, not a set.
+
+  MessageMapContainer* self = GetMessageMap(_self);
+  Message* message = self->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+  MapKey map_key;
+  MapValueRef value;
+
+  self->version++;
+
+  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+    return -1;
+  }
+
+  // Delete key from map.
+  if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
+                                 map_key)) {
+    return 0;
+  } else {
+    PyErr_Format(PyExc_KeyError, "Key not present in map");
+    return -1;
+  }
+}
+
+PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self,
+                                                 PyObject* key) {
+  MessageMapContainer* self = GetMessageMap(_self);
+
+  Message* message = self->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+  MapKey map_key;
+  MapValueRef value;
+
+  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+    return NULL;
+  }
+
+  if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
+                                         map_key, &value)) {
+    self->version++;
+  }
+
+  return GetCMessage(self, value.MutableMessageValue());
+}
+
+PyObject* MessageMapGet(PyObject* self, PyObject* args) {
+  PyObject* key;
+  PyObject* default_value = NULL;
+  if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
+    return NULL;
+  }
+
+  ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
+  if (is_present.get() == NULL) {
+    return NULL;
+  }
+
+  if (PyObject_IsTrue(is_present.get())) {
+    return MapReflectionFriend::MessageMapGetItem(self, key);
+  } else {
+    if (default_value != NULL) {
+      Py_INCREF(default_value);
+      return default_value;
+    } else {
+      Py_RETURN_NONE;
+    }
+  }
+}
+
+static void MessageMapDealloc(PyObject* _self) {
+  MessageMapContainer* self = GetMessageMap(_self);
+  self->owner.reset();
+  Py_DECREF(self->message_dict);
+  Py_DECREF(self->message_class);
+  Py_TYPE(_self)->tp_free(_self);
+}
+
+static PyMethodDef MessageMapMethods[] = {
+  { "__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
+    "Tests whether the map contains this element."},
+  { "clear", (PyCFunction)Clear, METH_NOARGS,
+    "Removes all elements from the map."},
+  { "get", MessageMapGet, METH_VARARGS,
+    "Gets the value for the given key if present, or otherwise a default" },
+  { "get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O,
+    "Alias for getitem, useful to make explicit that the map is mutated." },
+  /*
+  { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+    "Makes a deep copy of the class." },
+  { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+    "Outputs picklable representation of the repeated field." },
+  */
+  {NULL, NULL},
+};
+
+#if PY_MAJOR_VERSION >= 3
+  static PyType_Slot MessageMapContainer_Type_slots[] = {
+      {Py_tp_dealloc, (void *)MessageMapDealloc},
+      {Py_mp_length, (void *)MapReflectionFriend::Length},
+      {Py_mp_subscript, (void *)MapReflectionFriend::MessageMapGetItem},
+      {Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem},
+      {Py_tp_methods, (void *)MessageMapMethods},
+      {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
+      {0, 0}
+  };
+
+  PyType_Spec MessageMapContainer_Type_spec = {
+      FULL_MODULE_NAME ".MessageMapContainer",
+      sizeof(MessageMapContainer),
+      0,
+      Py_TPFLAGS_DEFAULT,
+      MessageMapContainer_Type_slots
+  };
+
+  PyObject *MessageMapContainer_Type;
+#else
+  static PyMappingMethods MessageMapMappingMethods = {
+    MapReflectionFriend::Length,              // mp_length
+    MapReflectionFriend::MessageMapGetItem,   // mp_subscript
+    MapReflectionFriend::MessageMapSetItem,   // mp_ass_subscript
+  };
+
+  PyTypeObject MessageMapContainer_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    FULL_MODULE_NAME ".MessageMapContainer",  //  tp_name
+    sizeof(MessageMapContainer),         //  tp_basicsize
+    0,                                   //  tp_itemsize
+    MessageMapDealloc,                   //  tp_dealloc
+    0,                                   //  tp_print
+    0,                                   //  tp_getattr
+    0,                                   //  tp_setattr
+    0,                                   //  tp_compare
+    0,                                   //  tp_repr
+    0,                                   //  tp_as_number
+    0,                                   //  tp_as_sequence
+    &MessageMapMappingMethods,           //  tp_as_mapping
+    0,                                   //  tp_hash
+    0,                                   //  tp_call
+    0,                                   //  tp_str
+    0,                                   //  tp_getattro
+    0,                                   //  tp_setattro
+    0,                                   //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                  //  tp_flags
+    "A map container for message",       //  tp_doc
+    0,                                   //  tp_traverse
+    0,                                   //  tp_clear
+    0,                                   //  tp_richcompare
+    0,                                   //  tp_weaklistoffset
+    MapReflectionFriend::GetIterator,    //  tp_iter
+    0,                                   //  tp_iternext
+    MessageMapMethods,                   //  tp_methods
+    0,                                   //  tp_members
+    0,                                   //  tp_getset
+    0,                                   //  tp_base
+    0,                                   //  tp_dict
+    0,                                   //  tp_descr_get
+    0,                                   //  tp_descr_set
+    0,                                   //  tp_dictoffset
+    0,                                   //  tp_init
+  };
+#endif
+
+// MapIterator /////////////////////////////////////////////////////////////////
+
+static MapIterator* GetIter(PyObject* obj) {
+  return reinterpret_cast<MapIterator*>(obj);
+}
+
+PyObject* MapReflectionFriend::GetIterator(PyObject *_self) {
+  MapContainer* self = GetMap(_self);
+
+  ScopedPyObjectPtr obj(PyType_GenericAlloc(&MapIterator_Type, 0));
+  if (obj == NULL) {
+    return PyErr_Format(PyExc_KeyError, "Could not allocate iterator");
+  }
+
+  MapIterator* iter = GetIter(obj.get());
+
+  Py_INCREF(self);
+  iter->container = self;
+  iter->version = self->version;
+  iter->owner = self->owner;
+
+  if (MapReflectionFriend::Length(_self) > 0) {
+    Message* message = self->GetMutableMessage();
+    const Reflection* reflection = message->GetReflection();
+
+    iter->iter.reset(new ::google::protobuf::MapIterator(
+        reflection->MapBegin(message, self->parent_field_descriptor)));
+  }
+
+  return obj.release();
+}
+
+PyObject* MapReflectionFriend::IterNext(PyObject* _self) {
+  MapIterator* self = GetIter(_self);
+
+  // This won't catch mutations to the map performed by MergeFrom(); no easy way
+  // to address that.
+  if (self->version != self->container->version) {
+    return PyErr_Format(PyExc_RuntimeError,
+                        "Map modified during iteration.");
+  }
+
+  if (self->iter.get() == NULL) {
+    return NULL;
+  }
+
+  Message* message = self->container->GetMutableMessage();
+  const Reflection* reflection = message->GetReflection();
+
+  if (*self->iter ==
+      reflection->MapEnd(message, self->container->parent_field_descriptor)) {
+    return NULL;
+  }
+
+  PyObject* ret = MapKeyToPython(self->container->key_field_descriptor,
+                                 self->iter->GetKey());
+
+  ++(*self->iter);
+
+  return ret;
+}
+
+static void DeallocMapIterator(PyObject* _self) {
+  MapIterator* self = GetIter(_self);
+  self->iter.reset();
+  self->owner.reset();
+  Py_XDECREF(self->container);
+  Py_TYPE(_self)->tp_free(_self);
+}
+
+PyTypeObject MapIterator_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".MapIterator",     //  tp_name
+  sizeof(MapIterator),                 //  tp_basicsize
+  0,                                   //  tp_itemsize
+  DeallocMapIterator,                  //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  0,                                   //  tp_repr
+  0,                                   //  tp_as_number
+  0,                                   //  tp_as_sequence
+  0,                                   //  tp_as_mapping
+  0,                                   //  tp_hash
+  0,                                   //  tp_call
+  0,                                   //  tp_str
+  0,                                   //  tp_getattro
+  0,                                   //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  //  tp_flags
+  "A scalar map iterator",             //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  0,                                   //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  PyObject_SelfIter,                   //  tp_iter
+  MapReflectionFriend::IterNext,       //  tp_iternext
+  0,                                   //  tp_methods
+  0,                                   //  tp_members
+  0,                                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  0,                                   //  tp_init
+};
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.h
new file mode 100644
index 0000000..fbd6713
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/map_container.h
@@ -0,0 +1,142 @@
+// 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_PYTHON_CPP_MAP_CONTAINER_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_MAP_CONTAINER_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+#ifdef _SHARED_PTR_H
+using std::shared_ptr;
+#else
+using internal::shared_ptr;
+#endif
+
+namespace python {
+
+struct CMessage;
+struct CMessageClass;
+
+// This struct is used directly for ScalarMap, and is the base class of
+// MessageMapContainer, which is used for MessageMap.
+struct MapContainer {
+  PyObject_HEAD;
+
+  // This is the top-level C++ Message object that owns the whole
+  // proto tree.  Every Python MapContainer holds a
+  // reference to it in order to keep it alive as long as there's a
+  // Python object that references any part of the tree.
+  shared_ptr<Message> owner;
+
+  // Pointer to the C++ Message that contains this container.  The
+  // MapContainer does not own this pointer.
+  const Message* message;
+
+  // Use to get a mutable message when necessary.
+  Message* GetMutableMessage();
+
+  // Weak reference to a parent CMessage object (i.e. may be NULL.)
+  //
+  // Used to make sure all ancestors are also mutable when first
+  // modifying the container.
+  CMessage* parent;
+
+  // Pointer to the parent's descriptor that describes this
+  // field.  Used together with the parent's message when making a
+  // default message instance mutable.
+  // The pointer is owned by the global DescriptorPool.
+  const FieldDescriptor* parent_field_descriptor;
+  const FieldDescriptor* key_field_descriptor;
+  const FieldDescriptor* value_field_descriptor;
+
+  // We bump this whenever we perform a mutation, to invalidate existing
+  // iterators.
+  uint64 version;
+
+  // Releases the messages in the container to a new message.
+  //
+  // Returns 0 on success, -1 on failure.
+  int Release();
+
+  // Set the owner field of self and any children of self.
+  void SetOwner(const shared_ptr<Message>& new_owner) {
+    owner = new_owner;
+  }
+};
+
+struct MessageMapContainer : public MapContainer {
+  // The type used to create new child messages.
+  CMessageClass* message_class;
+
+  // A dict mapping Message* -> CMessage.
+  PyObject* message_dict;
+};
+
+#if PY_MAJOR_VERSION >= 3
+  extern PyObject *MessageMapContainer_Type;
+  extern PyType_Spec MessageMapContainer_Type_spec;
+  extern PyObject *ScalarMapContainer_Type;
+  extern PyType_Spec ScalarMapContainer_Type_spec;
+#else
+  extern PyTypeObject MessageMapContainer_Type;
+  extern PyTypeObject ScalarMapContainer_Type;
+#endif
+
+extern PyTypeObject MapIterator_Type;  // Both map types use the same iterator.
+
+// Builds a MapContainer object, from a parent message and a
+// field descriptor.
+extern PyObject* NewScalarMapContainer(
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor);
+
+// Builds a MessageMap object, from a parent message and a
+// field descriptor.
+extern PyObject* NewMessageMapContainer(
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor,
+    CMessageClass* message_class);
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_MAP_CONTAINER_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/message.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/message.cc
new file mode 100644
index 0000000..83c151f
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/message.cc
@@ -0,0 +1,3133 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#include <google/protobuf/pyext/message.h>
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+#include <structmember.h>  // A Python header file.
+
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
+#endif
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/extension_dict.h>
+#include <google/protobuf/pyext/repeated_composite_container.h>
+#include <google/protobuf/pyext/repeated_scalar_container.h>
+#include <google/protobuf/pyext/map_container.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyInt_Check PyLong_Check
+  #define PyInt_AsLong PyLong_AsLong
+  #define PyInt_FromLong PyLong_FromLong
+  #define PyInt_FromSize_t PyLong_FromSize_t
+  #define PyString_Check PyUnicode_Check
+  #define PyString_FromString PyUnicode_FromString
+  #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #else
+  #define PyString_AsString(ob) \
+    (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
+  #define PyString_AsStringAndSize(ob, charpp, sizep) \
+    (PyUnicode_Check(ob)? \
+       ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+       PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+  #endif
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+static PyObject* kDESCRIPTOR;
+static PyObject* k_extensions_by_name;
+static PyObject* k_extensions_by_number;
+PyObject* EnumTypeWrapper_class;
+static PyObject* PythonMessage_class;
+static PyObject* kEmptyWeakref;
+static PyObject* WKT_classes = NULL;
+
+namespace message_meta {
+
+static int InsertEmptyWeakref(PyTypeObject* base);
+
+// Add the number of a field descriptor to the containing message class.
+// Equivalent to:
+//   _cls.<field>_FIELD_NUMBER = <number>
+static bool AddFieldNumberToClass(
+    PyObject* cls, const FieldDescriptor* field_descriptor) {
+  string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
+  UpperString(&constant_name);
+  ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
+      constant_name.c_str(), constant_name.size()));
+  if (attr_name == NULL) {
+    return false;
+  }
+  ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
+  if (number == NULL) {
+    return false;
+  }
+  if (PyObject_SetAttr(cls, attr_name.get(), number.get()) == -1) {
+    return false;
+  }
+  return true;
+}
+
+
+// Finalize the creation of the Message class.
+static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
+  // If there are extension_ranges, the message is "extendable", and extension
+  // classes will register themselves in this class.
+  if (descriptor->extension_range_count() > 0) {
+    ScopedPyObjectPtr by_name(PyDict_New());
+    if (PyObject_SetAttr(cls, k_extensions_by_name, by_name.get()) < 0) {
+      return -1;
+    }
+    ScopedPyObjectPtr by_number(PyDict_New());
+    if (PyObject_SetAttr(cls, k_extensions_by_number, by_number.get()) < 0) {
+      return -1;
+    }
+  }
+
+  // For each field set: cls.<field>_FIELD_NUMBER = <number>
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    if (!AddFieldNumberToClass(cls, descriptor->field(i))) {
+      return -1;
+    }
+  }
+
+  // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>).
+  for (int i = 0; i < descriptor->enum_type_count(); ++i) {
+    const EnumDescriptor* enum_descriptor = descriptor->enum_type(i);
+    ScopedPyObjectPtr enum_type(
+        PyEnumDescriptor_FromDescriptor(enum_descriptor));
+    if (enum_type == NULL) {
+      return -1;
+     }
+    // Add wrapped enum type to message class.
+    ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
+        EnumTypeWrapper_class, enum_type.get(), NULL));
+    if (wrapped == NULL) {
+      return -1;
+    }
+    if (PyObject_SetAttrString(
+            cls, enum_descriptor->name().c_str(), wrapped.get()) == -1) {
+      return -1;
+    }
+
+    // For each enum value add cls.<name> = <number>
+    for (int j = 0; j < enum_descriptor->value_count(); ++j) {
+      const EnumValueDescriptor* enum_value_descriptor =
+          enum_descriptor->value(j);
+      ScopedPyObjectPtr value_number(PyInt_FromLong(
+          enum_value_descriptor->number()));
+      if (value_number == NULL) {
+        return -1;
+      }
+      if (PyObject_SetAttrString(cls, enum_value_descriptor->name().c_str(),
+                                 value_number.get()) == -1) {
+        return -1;
+      }
+    }
+  }
+
+  // For each extension set cls.<extension name> = <extension descriptor>.
+  //
+  // Extension descriptors come from
+  // <message descriptor>.extensions_by_name[name]
+  // which was defined previously.
+  for (int i = 0; i < descriptor->extension_count(); ++i) {
+    const google::protobuf::FieldDescriptor* field = descriptor->extension(i);
+    ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
+    if (extension_field == NULL) {
+      return -1;
+    }
+
+    // Add the extension field to the message class.
+    if (PyObject_SetAttrString(
+            cls, field->name().c_str(), extension_field.get()) == -1) {
+      return -1;
+    }
+
+    // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
+    if (!AddFieldNumberToClass(cls, field)) {
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+static PyObject* New(PyTypeObject* type,
+                     PyObject* args, PyObject* kwargs) {
+  static char *kwlist[] = {"name", "bases", "dict", 0};
+  PyObject *bases, *dict;
+  const char* name;
+
+  // Check arguments: (name, bases, dict)
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
+                                   &name,
+                                   &PyTuple_Type, &bases,
+                                   &PyDict_Type, &dict)) {
+    return NULL;
+  }
+
+  // Check bases: only (), or (message.Message,) are allowed
+  if (!(PyTuple_GET_SIZE(bases) == 0 ||
+        (PyTuple_GET_SIZE(bases) == 1 &&
+         PyTuple_GET_ITEM(bases, 0) == PythonMessage_class))) {
+    PyErr_SetString(PyExc_TypeError,
+                    "A Message class can only inherit from Message");
+    return NULL;
+  }
+
+  // Check dict['DESCRIPTOR']
+  PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+  if (py_descriptor == NULL) {
+    PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
+    return NULL;
+  }
+  if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) {
+    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+                 py_descriptor->ob_type->tp_name);
+    return NULL;
+  }
+
+  // Build the arguments to the base metaclass.
+  // We change the __bases__ classes.
+  ScopedPyObjectPtr new_args;
+  const Descriptor* message_descriptor =
+      PyMessageDescriptor_AsDescriptor(py_descriptor);
+  if (message_descriptor == NULL) {
+    return NULL;
+  }
+
+  if (WKT_classes == NULL) {
+    ScopedPyObjectPtr well_known_types(PyImport_ImportModule(
+        "google.protobuf.internal.well_known_types"));
+    GOOGLE_DCHECK(well_known_types != NULL);
+
+    WKT_classes = PyObject_GetAttrString(well_known_types.get(), "WKTBASES");
+    GOOGLE_DCHECK(WKT_classes != NULL);
+  }
+
+  PyObject* well_known_class = PyDict_GetItemString(
+      WKT_classes, message_descriptor->full_name().c_str());
+  if (well_known_class == NULL) {
+    new_args.reset(Py_BuildValue("s(OO)O", name, &CMessage_Type,
+                                 PythonMessage_class, dict));
+  } else {
+    new_args.reset(Py_BuildValue("s(OOO)O", name, &CMessage_Type,
+                                 PythonMessage_class, well_known_class, dict));
+  }
+
+  if (new_args == NULL) {
+    return NULL;
+  }
+  // Call the base metaclass.
+  ScopedPyObjectPtr result(PyType_Type.tp_new(type, new_args.get(), NULL));
+  if (result == NULL) {
+    return NULL;
+  }
+  CMessageClass* newtype = reinterpret_cast<CMessageClass*>(result.get());
+
+  // Insert the empty weakref into the base classes.
+  if (InsertEmptyWeakref(
+          reinterpret_cast<PyTypeObject*>(PythonMessage_class)) < 0 ||
+      InsertEmptyWeakref(&CMessage_Type) < 0) {
+    return NULL;
+  }
+
+  // Cache the descriptor, both as Python object and as C++ pointer.
+  const Descriptor* descriptor =
+      PyMessageDescriptor_AsDescriptor(py_descriptor);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  Py_INCREF(py_descriptor);
+  newtype->py_message_descriptor = py_descriptor;
+  newtype->message_descriptor = descriptor;
+  // TODO(amauryfa): Don't always use the canonical pool of the descriptor,
+  // use the MessageFactory optionally passed in the class dict.
+  newtype->py_descriptor_pool = GetDescriptorPool_FromPool(
+      descriptor->file()->pool());
+  if (newtype->py_descriptor_pool == NULL) {
+    return NULL;
+  }
+  Py_INCREF(newtype->py_descriptor_pool);
+
+  // Add the message to the DescriptorPool.
+  if (cdescriptor_pool::RegisterMessageClass(newtype->py_descriptor_pool,
+                                             descriptor, newtype) < 0) {
+    return NULL;
+  }
+
+  // Continue with type initialization: add other descriptors, enum values...
+  if (AddDescriptors(result.get(), descriptor) < 0) {
+    return NULL;
+  }
+  return result.release();
+}
+
+static void Dealloc(CMessageClass *self) {
+  Py_DECREF(self->py_message_descriptor);
+  Py_DECREF(self->py_descriptor_pool);
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+
+// This function inserts and empty weakref at the end of the list of
+// subclasses for the main protocol buffer Message class.
+//
+// This eliminates a O(n^2) behaviour in the internal add_subclass
+// routine.
+static int InsertEmptyWeakref(PyTypeObject *base_type) {
+#if PY_MAJOR_VERSION >= 3
+  // Python 3.4 has already included the fix for the issue that this
+  // hack addresses. For further background and the fix please see
+  // https://bugs.python.org/issue17936.
+  return 0;
+#else
+  PyObject *subclasses = base_type->tp_subclasses;
+  if (subclasses && PyList_CheckExact(subclasses)) {
+    return PyList_Append(subclasses, kEmptyWeakref);
+  }
+  return 0;
+#endif  // PY_MAJOR_VERSION >= 3
+}
+
+}  // namespace message_meta
+
+PyTypeObject CMessageClass_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".MessageMeta",     // tp_name
+  sizeof(CMessageClass),               // tp_basicsize
+  0,                                   // tp_itemsize
+  (destructor)message_meta::Dealloc,   // tp_dealloc
+  0,                                   // tp_print
+  0,                                   // tp_getattr
+  0,                                   // tp_setattr
+  0,                                   // tp_compare
+  0,                                   // tp_repr
+  0,                                   // tp_as_number
+  0,                                   // tp_as_sequence
+  0,                                   // tp_as_mapping
+  0,                                   // tp_hash
+  0,                                   // tp_call
+  0,                                   // tp_str
+  0,                                   // tp_getattro
+  0,                                   // tp_setattro
+  0,                                   // tp_as_buffer
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  // tp_flags
+  "The metaclass of ProtocolMessages",  // tp_doc
+  0,                                   // tp_traverse
+  0,                                   // tp_clear
+  0,                                   // tp_richcompare
+  0,                                   // tp_weaklistoffset
+  0,                                   // tp_iter
+  0,                                   // tp_iternext
+  0,                                   // tp_methods
+  0,                                   // tp_members
+  0,                                   // tp_getset
+  0,                                   // tp_base
+  0,                                   // tp_dict
+  0,                                   // tp_descr_get
+  0,                                   // tp_descr_set
+  0,                                   // tp_dictoffset
+  0,                                   // tp_init
+  0,                                   // tp_alloc
+  message_meta::New,                   // tp_new
+};
+
+static CMessageClass* CheckMessageClass(PyTypeObject* cls) {
+  if (!PyObject_TypeCheck(cls, &CMessageClass_Type)) {
+    PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name);
+    return NULL;
+  }
+  return reinterpret_cast<CMessageClass*>(cls);
+}
+
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+  CMessageClass* type = CheckMessageClass(cls);
+  if (type == NULL) {
+    return NULL;
+  }
+  return type->message_descriptor;
+}
+
+// Forward declarations
+namespace cmessage {
+int InternalReleaseFieldByDescriptor(
+    CMessage* self,
+    const FieldDescriptor* field_descriptor,
+    PyObject* composite_field);
+}  // namespace cmessage
+
+// ---------------------------------------------------------------------
+// Visiting the composite children of a CMessage
+
+struct ChildVisitor {
+  // Returns 0 on success, -1 on failure.
+  int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
+    return 0;
+  }
+
+  // Returns 0 on success, -1 on failure.
+  int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) {
+    return 0;
+  }
+
+  // Returns 0 on success, -1 on failure.
+  int VisitCMessage(CMessage* cmessage,
+                    const FieldDescriptor* field_descriptor) {
+    return 0;
+  }
+};
+
+// Apply a function to a composite field.  Does nothing if child is of
+// non-composite type.
+template<class Visitor>
+static int VisitCompositeField(const FieldDescriptor* descriptor,
+                               PyObject* child,
+                               Visitor visitor) {
+  if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (descriptor->is_map()) {
+        MapContainer* container = reinterpret_cast<MapContainer*>(child);
+        if (visitor.VisitMapContainer(container) == -1) {
+          return -1;
+        }
+      } else {
+        RepeatedCompositeContainer* container =
+          reinterpret_cast<RepeatedCompositeContainer*>(child);
+        if (visitor.VisitRepeatedCompositeContainer(container) == -1)
+          return -1;
+      }
+    } else {
+      RepeatedScalarContainer* container =
+        reinterpret_cast<RepeatedScalarContainer*>(child);
+      if (visitor.VisitRepeatedScalarContainer(container) == -1)
+        return -1;
+    }
+  } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    CMessage* cmsg = reinterpret_cast<CMessage*>(child);
+    if (visitor.VisitCMessage(cmsg, descriptor) == -1)
+      return -1;
+  }
+  // The ExtensionDict might contain non-composite fields, which we
+  // skip here.
+  return 0;
+}
+
+// Visit each composite field and extension field of this CMessage.
+// Returns -1 on error and 0 on success.
+template<class Visitor>
+int ForEachCompositeField(CMessage* self, Visitor visitor) {
+  Py_ssize_t pos = 0;
+  PyObject* key;
+  PyObject* field;
+
+  // Visit normal fields.
+  if (self->composite_fields) {
+    // Never use self->message in this function, it may be already freed.
+    const Descriptor* message_descriptor =
+        GetMessageDescriptor(Py_TYPE(self));
+    while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
+      Py_ssize_t key_str_size;
+      char *key_str_data;
+      if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0)
+        return -1;
+      const string key_str(key_str_data, key_str_size);
+      const FieldDescriptor* descriptor =
+        message_descriptor->FindFieldByName(key_str);
+      if (descriptor != NULL) {
+        if (VisitCompositeField(descriptor, field, visitor) == -1)
+          return -1;
+      }
+    }
+  }
+
+  // Visit extension fields.
+  if (self->extensions != NULL) {
+    pos = 0;
+    while (PyDict_Next(self->extensions->values, &pos, &key, &field)) {
+      const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
+      if (descriptor == NULL)
+        return -1;
+      if (VisitCompositeField(descriptor, field, visitor) == -1)
+        return -1;
+    }
+  }
+
+  return 0;
+}
+
+// ---------------------------------------------------------------------
+
+// Constants used for integer type range checking.
+PyObject* kPythonZero;
+PyObject* kint32min_py;
+PyObject* kint32max_py;
+PyObject* kuint32max_py;
+PyObject* kint64min_py;
+PyObject* kint64max_py;
+PyObject* kuint64max_py;
+
+PyObject* EncodeError_class;
+PyObject* DecodeError_class;
+PyObject* PickleError_class;
+
+// Constant PyString values used for GetAttr/GetItem.
+static PyObject* k_cdescriptor;
+static PyObject* kfull_name;
+
+/* Is 64bit */
+void FormatTypeError(PyObject* arg, char* expected_types) {
+  PyObject* repr = PyObject_Repr(arg);
+  if (repr) {
+    PyErr_Format(PyExc_TypeError,
+                 "%.100s has type %.100s, but expected one of: %s",
+                 PyString_AsString(repr),
+                 Py_TYPE(arg)->tp_name,
+                 expected_types);
+    Py_DECREF(repr);
+  }
+}
+
+template<class T>
+bool CheckAndGetInteger(
+    PyObject* arg, T* value, PyObject* min, PyObject* max) {
+  bool is_long = PyLong_Check(arg);
+#if PY_MAJOR_VERSION < 3
+  if (!PyInt_Check(arg) && !is_long) {
+    FormatTypeError(arg, "int, long");
+    return false;
+  }
+  if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) {
+#else
+  if (!is_long) {
+    FormatTypeError(arg, "int");
+    return false;
+  }
+  if (PyObject_RichCompareBool(min, arg, Py_LE) != 1 ||
+      PyObject_RichCompareBool(max, arg, Py_GE) != 1) {
+#endif
+    if (!PyErr_Occurred()) {
+      PyObject *s = PyObject_Str(arg);
+      if (s) {
+        PyErr_Format(PyExc_ValueError,
+                     "Value out of range: %s",
+                     PyString_AsString(s));
+        Py_DECREF(s);
+      }
+    }
+    return false;
+  }
+#if PY_MAJOR_VERSION < 3
+  if (!is_long) {
+    *value = static_cast<T>(PyInt_AsLong(arg));
+  } else  // NOLINT
+#endif
+  {
+    if (min == kPythonZero) {
+      *value = static_cast<T>(PyLong_AsUnsignedLongLong(arg));
+    } else {
+      *value = static_cast<T>(PyLong_AsLongLong(arg));
+    }
+  }
+  return true;
+}
+
+// These are referenced by repeated_scalar_container, and must
+// be explicitly instantiated.
+template bool CheckAndGetInteger<int32>(
+    PyObject*, int32*, PyObject*, PyObject*);
+template bool CheckAndGetInteger<int64>(
+    PyObject*, int64*, PyObject*, PyObject*);
+template bool CheckAndGetInteger<uint32>(
+    PyObject*, uint32*, PyObject*, PyObject*);
+template bool CheckAndGetInteger<uint64>(
+    PyObject*, uint64*, PyObject*, PyObject*);
+
+bool CheckAndGetDouble(PyObject* arg, double* value) {
+  if (!PyInt_Check(arg) && !PyLong_Check(arg) &&
+      !PyFloat_Check(arg)) {
+    FormatTypeError(arg, "int, long, float");
+    return false;
+  }
+  *value = PyFloat_AsDouble(arg);
+  return true;
+}
+
+bool CheckAndGetFloat(PyObject* arg, float* value) {
+  double double_value;
+  if (!CheckAndGetDouble(arg, &double_value)) {
+    return false;
+  }
+  *value = static_cast<float>(double_value);
+  return true;
+}
+
+bool CheckAndGetBool(PyObject* arg, bool* value) {
+  if (!PyInt_Check(arg) && !PyBool_Check(arg) && !PyLong_Check(arg)) {
+    FormatTypeError(arg, "int, long, bool");
+    return false;
+  }
+  *value = static_cast<bool>(PyInt_AsLong(arg));
+  return true;
+}
+
+// Checks whether the given object (which must be "bytes" or "unicode") contains
+// valid UTF-8.
+bool IsValidUTF8(PyObject* obj) {
+  if (PyBytes_Check(obj)) {
+    PyObject* unicode = PyUnicode_FromEncodedObject(obj, "utf-8", NULL);
+
+    // Clear the error indicator; we report our own error when desired.
+    PyErr_Clear();
+
+    if (unicode) {
+      Py_DECREF(unicode);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    // Unicode object, known to be valid UTF-8.
+    return true;
+  }
+}
+
+bool AllowInvalidUTF8(const FieldDescriptor* field) { return false; }
+
+PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor) {
+  GOOGLE_DCHECK(descriptor->type() == FieldDescriptor::TYPE_STRING ||
+         descriptor->type() == FieldDescriptor::TYPE_BYTES);
+  if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
+    if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) {
+      FormatTypeError(arg, "bytes, unicode");
+      return NULL;
+    }
+
+    if (!IsValidUTF8(arg) && !AllowInvalidUTF8(descriptor)) {
+      PyObject* repr = PyObject_Repr(arg);
+      PyErr_Format(PyExc_ValueError,
+                   "%s has type str, but isn't valid UTF-8 "
+                   "encoding. Non-UTF-8 strings must be converted to "
+                   "unicode objects before being added.",
+                   PyString_AsString(repr));
+      Py_DECREF(repr);
+      return NULL;
+    }
+  } else if (!PyBytes_Check(arg)) {
+    FormatTypeError(arg, "bytes");
+    return NULL;
+  }
+
+  PyObject* encoded_string = NULL;
+  if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
+    if (PyBytes_Check(arg)) {
+      // The bytes were already validated as correctly encoded UTF-8 above.
+      encoded_string = arg;  // Already encoded.
+      Py_INCREF(encoded_string);
+    } else {
+      encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL);
+    }
+  } else {
+    // In this case field type is "bytes".
+    encoded_string = arg;
+    Py_INCREF(encoded_string);
+  }
+
+  return encoded_string;
+}
+
+bool CheckAndSetString(
+    PyObject* arg, Message* message,
+    const FieldDescriptor* descriptor,
+    const Reflection* reflection,
+    bool append,
+    int index) {
+  ScopedPyObjectPtr encoded_string(CheckString(arg, descriptor));
+
+  if (encoded_string.get() == NULL) {
+    return false;
+  }
+
+  char* value;
+  Py_ssize_t value_len;
+  if (PyBytes_AsStringAndSize(encoded_string.get(), &value, &value_len) < 0) {
+    return false;
+  }
+
+  string value_string(value, value_len);
+  if (append) {
+    reflection->AddString(message, descriptor, value_string);
+  } else if (index < 0) {
+    reflection->SetString(message, descriptor, value_string);
+  } else {
+    reflection->SetRepeatedString(message, descriptor, index, value_string);
+  }
+  return true;
+}
+
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) {
+  if (descriptor->type() != FieldDescriptor::TYPE_STRING) {
+    return PyBytes_FromStringAndSize(value.c_str(), value.length());
+  }
+
+  PyObject* result = PyUnicode_DecodeUTF8(value.c_str(), value.length(), NULL);
+  // If the string can't be decoded in UTF-8, just return a string object that
+  // contains the raw bytes. This can't happen if the value was assigned using
+  // the members of the Python message object, but can happen if the values were
+  // parsed from the wire (binary).
+  if (result == NULL) {
+    PyErr_Clear();
+    result = PyBytes_FromStringAndSize(value.c_str(), value.length());
+  }
+  return result;
+}
+
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+                                const Message* message) {
+  if (message->GetDescriptor() == field_descriptor->containing_type()) {
+    return true;
+  }
+  PyErr_Format(PyExc_KeyError, "Field '%s' does not belong to message '%s'",
+               field_descriptor->full_name().c_str(),
+               message->GetDescriptor()->full_name().c_str());
+  return false;
+}
+
+namespace cmessage {
+
+PyDescriptorPool* GetDescriptorPoolForMessage(CMessage* message) {
+  // No need to check the type: the type of instances of CMessage is always
+  // an instance of CMessageClass. Let's prove it with a debug-only check.
+  GOOGLE_DCHECK(PyObject_TypeCheck(message, &CMessage_Type));
+  return reinterpret_cast<CMessageClass*>(Py_TYPE(message))->py_descriptor_pool;
+}
+
+MessageFactory* GetFactoryForMessage(CMessage* message) {
+  return GetDescriptorPoolForMessage(message)->message_factory;
+}
+
+static int MaybeReleaseOverlappingOneofField(
+    CMessage* cmessage,
+    const FieldDescriptor* field) {
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+  Message* message = cmessage->message;
+  const Reflection* reflection = message->GetReflection();
+  if (!field->containing_oneof() ||
+      !reflection->HasOneof(*message, field->containing_oneof()) ||
+      reflection->HasField(*message, field)) {
+    // No other field in this oneof, no need to release.
+    return 0;
+  }
+
+  const OneofDescriptor* oneof = field->containing_oneof();
+  const FieldDescriptor* existing_field =
+      reflection->GetOneofFieldDescriptor(*message, oneof);
+  if (existing_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    // Non-message fields don't need to be released.
+    return 0;
+  }
+  const char* field_name = existing_field->name().c_str();
+  PyObject* child_message = cmessage->composite_fields ?
+      PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL;
+  if (child_message == NULL) {
+    // No python reference to this field so no need to release.
+    return 0;
+  }
+
+  if (InternalReleaseFieldByDescriptor(
+          cmessage, existing_field, child_message) < 0) {
+    return -1;
+  }
+  return PyDict_DelItemString(cmessage->composite_fields, field_name);
+#else
+  return 0;
+#endif
+}
+
+// ---------------------------------------------------------------------
+// Making a message writable
+
+static Message* GetMutableMessage(
+    CMessage* parent,
+    const FieldDescriptor* parent_field) {
+  Message* parent_message = parent->message;
+  const Reflection* reflection = parent_message->GetReflection();
+  if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) {
+    return NULL;
+  }
+  return reflection->MutableMessage(
+      parent_message, parent_field, GetFactoryForMessage(parent));
+}
+
+struct FixupMessageReference : public ChildVisitor {
+  // message must outlive this object.
+  explicit FixupMessageReference(Message* message) :
+      message_(message) {}
+
+  int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
+    container->message = message_;
+    return 0;
+  }
+
+  int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) {
+    container->message = message_;
+    return 0;
+  }
+
+  int VisitMapContainer(MapContainer* container) {
+    container->message = message_;
+    return 0;
+  }
+
+ private:
+  Message* message_;
+};
+
+int AssureWritable(CMessage* self) {
+  if (self == NULL || !self->read_only) {
+    return 0;
+  }
+
+  if (self->parent == NULL) {
+    // If parent is NULL but we are trying to modify a read-only message, this
+    // is a reference to a constant default instance that needs to be replaced
+    // with a mutable top-level message.
+    self->message = self->message->New();
+    self->owner.reset(self->message);
+    // Cascade the new owner to eventual children: even if this message is
+    // empty, some submessages or repeated containers might exist already.
+    SetOwner(self, self->owner);
+  } else {
+    // Otherwise, we need a mutable child message.
+    if (AssureWritable(self->parent) == -1)
+      return -1;
+
+    // Make self->message writable.
+    Message* mutable_message = GetMutableMessage(
+        self->parent,
+        self->parent_field_descriptor);
+    if (mutable_message == NULL) {
+      return -1;
+    }
+    self->message = mutable_message;
+  }
+  self->read_only = false;
+
+  // When a CMessage is made writable its Message pointer is updated
+  // to point to a new mutable Message.  When that happens we need to
+  // update any references to the old, read-only CMessage.  There are
+  // four places such references occur: RepeatedScalarContainer,
+  // RepeatedCompositeContainer, MapContainer, and ExtensionDict.
+  if (self->extensions != NULL)
+    self->extensions->message = self->message;
+  if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1)
+    return -1;
+
+  return 0;
+}
+
+// --- Globals:
+
+// Retrieve a C++ FieldDescriptor for a message attribute.
+// The C++ message must be valid.
+// TODO(amauryfa): This function should stay internal, because exception
+// handling is not consistent.
+static const FieldDescriptor* GetFieldDescriptor(
+    CMessage* self, PyObject* name) {
+  const Descriptor *message_descriptor = self->message->GetDescriptor();
+  char* field_name;
+  Py_ssize_t size;
+  if (PyString_AsStringAndSize(name, &field_name, &size) < 0) {
+    return NULL;
+  }
+  const FieldDescriptor *field_descriptor =
+      message_descriptor->FindFieldByName(string(field_name, size));
+  if (field_descriptor == NULL) {
+    // Note: No exception is set!
+    return NULL;
+  }
+  return field_descriptor;
+}
+
+// Retrieve a C++ FieldDescriptor for an extension handle.
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
+  ScopedPyObjectPtr cdescriptor;
+  if (!PyObject_TypeCheck(extension, &PyFieldDescriptor_Type)) {
+    // Most callers consider extensions as a plain dictionary.  We should
+    // allow input which is not a field descriptor, and simply pretend it does
+    // not exist.
+    PyErr_SetObject(PyExc_KeyError, extension);
+    return NULL;
+  }
+  return PyFieldDescriptor_AsDescriptor(extension);
+}
+
+// If value is a string, convert it into an enum value based on the labels in
+// descriptor, otherwise simply return value.  Always returns a new reference.
+static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor,
+                                     PyObject* value) {
+  if (PyString_Check(value) || PyUnicode_Check(value)) {
+    const EnumDescriptor* enum_descriptor = descriptor.enum_type();
+    if (enum_descriptor == NULL) {
+      PyErr_SetString(PyExc_TypeError, "not an enum field");
+      return NULL;
+    }
+    char* enum_label;
+    Py_ssize_t size;
+    if (PyString_AsStringAndSize(value, &enum_label, &size) < 0) {
+      return NULL;
+    }
+    const EnumValueDescriptor* enum_value_descriptor =
+        enum_descriptor->FindValueByName(string(enum_label, size));
+    if (enum_value_descriptor == NULL) {
+      PyErr_SetString(PyExc_ValueError, "unknown enum label");
+      return NULL;
+    }
+    return PyInt_FromLong(enum_value_descriptor->number());
+  }
+  Py_INCREF(value);
+  return value;
+}
+
+// If cmessage_list is not NULL, this function releases values into the
+// container CMessages instead of just removing. Repeated composite container
+// needs to do this to make sure CMessages stay alive if they're still
+// referenced after deletion. Repeated scalar container doesn't need to worry.
+int InternalDeleteRepeatedField(
+    CMessage* self,
+    const FieldDescriptor* field_descriptor,
+    PyObject* slice,
+    PyObject* cmessage_list) {
+  Message* message = self->message;
+  Py_ssize_t length, from, to, step, slice_length;
+  const Reflection* reflection = message->GetReflection();
+  int min, max;
+  length = reflection->FieldSize(*message, field_descriptor);
+
+  if (PyInt_Check(slice) || PyLong_Check(slice)) {
+    from = to = PyLong_AsLong(slice);
+    if (from < 0) {
+      from = to = length + from;
+    }
+    step = 1;
+    min = max = from;
+
+    // Range check.
+    if (from < 0 || from >= length) {
+      PyErr_Format(PyExc_IndexError, "list assignment index out of range");
+      return -1;
+    }
+  } else if (PySlice_Check(slice)) {
+    from = to = step = slice_length = 0;
+    PySlice_GetIndicesEx(
+#if PY_MAJOR_VERSION < 3
+        reinterpret_cast<PySliceObject*>(slice),
+#else
+        slice,
+#endif
+        length, &from, &to, &step, &slice_length);
+    if (from < to) {
+      min = from;
+      max = to - 1;
+    } else {
+      min = to + 1;
+      max = from;
+    }
+  } else {
+    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
+    return -1;
+  }
+
+  Py_ssize_t i = from;
+  std::vector<bool> to_delete(length, false);
+  while (i >= min && i <= max) {
+    to_delete[i] = true;
+    i += step;
+  }
+
+  to = 0;
+  for (i = 0; i < length; ++i) {
+    if (!to_delete[i]) {
+      if (i != to) {
+        reflection->SwapElements(message, field_descriptor, i, to);
+        if (cmessage_list != NULL) {
+          // If a list of cmessages is passed in (i.e. from a repeated
+          // composite container), swap those as well to correspond to the
+          // swaps in the underlying message so they're in the right order
+          // when we start releasing.
+          PyObject* tmp = PyList_GET_ITEM(cmessage_list, i);
+          PyList_SET_ITEM(cmessage_list, i,
+                          PyList_GET_ITEM(cmessage_list, to));
+          PyList_SET_ITEM(cmessage_list, to, tmp);
+        }
+      }
+      ++to;
+    }
+  }
+
+  while (i > to) {
+    if (cmessage_list == NULL) {
+      reflection->RemoveLast(message, field_descriptor);
+    } else {
+      CMessage* last_cmessage = reinterpret_cast<CMessage*>(
+          PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1));
+      repeated_composite_container::ReleaseLastTo(
+          self, field_descriptor, last_cmessage);
+      if (PySequence_DelItem(cmessage_list, -1) < 0) {
+        return -1;
+      }
+    }
+    --i;
+  }
+
+  return 0;
+}
+
+// Initializes fields of a message. Used in constructors.
+int InitAttributes(CMessage* self, PyObject* kwargs) {
+  if (kwargs == NULL) {
+    return 0;
+  }
+
+  Py_ssize_t pos = 0;
+  PyObject* name;
+  PyObject* value;
+  while (PyDict_Next(kwargs, &pos, &name, &value)) {
+    if (!PyString_Check(name)) {
+      PyErr_SetString(PyExc_ValueError, "Field name must be a string");
+      return -1;
+    }
+    const FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
+    if (descriptor == NULL) {
+      PyErr_Format(PyExc_ValueError, "Protocol message %s has no \"%s\" field.",
+                   self->message->GetDescriptor()->name().c_str(),
+                   PyString_AsString(name));
+      return -1;
+    }
+    if (value == Py_None) {
+      // field=None is the same as no field at all.
+      continue;
+    }
+    if (descriptor->is_map()) {
+      ScopedPyObjectPtr map(GetAttr(self, name));
+      const FieldDescriptor* value_descriptor =
+          descriptor->message_type()->FindFieldByName("value");
+      if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        Py_ssize_t map_pos = 0;
+        PyObject* map_key;
+        PyObject* map_value;
+        while (PyDict_Next(value, &map_pos, &map_key, &map_value)) {
+          ScopedPyObjectPtr function_return;
+          function_return.reset(PyObject_GetItem(map.get(), map_key));
+          if (function_return.get() == NULL) {
+            return -1;
+          }
+          ScopedPyObjectPtr ok(PyObject_CallMethod(
+              function_return.get(), "MergeFrom", "O", map_value));
+          if (ok.get() == NULL) {
+            return -1;
+          }
+        }
+      } else {
+        ScopedPyObjectPtr function_return;
+        function_return.reset(
+            PyObject_CallMethod(map.get(), "update", "O", value));
+        if (function_return.get() == NULL) {
+          return -1;
+        }
+      }
+    } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+      ScopedPyObjectPtr container(GetAttr(self, name));
+      if (container == NULL) {
+        return -1;
+      }
+      if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        RepeatedCompositeContainer* rc_container =
+            reinterpret_cast<RepeatedCompositeContainer*>(container.get());
+        ScopedPyObjectPtr iter(PyObject_GetIter(value));
+        if (iter == NULL) {
+          PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+          return -1;
+        }
+        ScopedPyObjectPtr next;
+        while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
+          PyObject* kwargs = (PyDict_Check(next.get()) ? next.get() : NULL);
+          ScopedPyObjectPtr new_msg(
+              repeated_composite_container::Add(rc_container, NULL, kwargs));
+          if (new_msg == NULL) {
+            return -1;
+          }
+          if (kwargs == NULL) {
+            // next was not a dict, it's a message we need to merge
+            ScopedPyObjectPtr merged(MergeFrom(
+                reinterpret_cast<CMessage*>(new_msg.get()), next.get()));
+            if (merged.get() == NULL) {
+              return -1;
+            }
+          }
+        }
+        if (PyErr_Occurred()) {
+          // Check to see how PyIter_Next() exited.
+          return -1;
+        }
+      } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+        RepeatedScalarContainer* rs_container =
+            reinterpret_cast<RepeatedScalarContainer*>(container.get());
+        ScopedPyObjectPtr iter(PyObject_GetIter(value));
+        if (iter == NULL) {
+          PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+          return -1;
+        }
+        ScopedPyObjectPtr next;
+        while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
+          ScopedPyObjectPtr enum_value(
+              GetIntegerEnumValue(*descriptor, next.get()));
+          if (enum_value == NULL) {
+            return -1;
+          }
+          ScopedPyObjectPtr new_msg(repeated_scalar_container::Append(
+              rs_container, enum_value.get()));
+          if (new_msg == NULL) {
+            return -1;
+          }
+        }
+        if (PyErr_Occurred()) {
+          // Check to see how PyIter_Next() exited.
+          return -1;
+        }
+      } else {
+        if (ScopedPyObjectPtr(repeated_scalar_container::Extend(
+                reinterpret_cast<RepeatedScalarContainer*>(container.get()),
+                value)) ==
+            NULL) {
+          return -1;
+        }
+      }
+    } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      ScopedPyObjectPtr message(GetAttr(self, name));
+      if (message == NULL) {
+        return -1;
+      }
+      CMessage* cmessage = reinterpret_cast<CMessage*>(message.get());
+      if (PyDict_Check(value)) {
+        if (InitAttributes(cmessage, value) < 0) {
+          return -1;
+        }
+      } else {
+        ScopedPyObjectPtr merged(MergeFrom(cmessage, value));
+        if (merged == NULL) {
+          return -1;
+        }
+      }
+    } else {
+      ScopedPyObjectPtr new_val;
+      if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+        new_val.reset(GetIntegerEnumValue(*descriptor, value));
+        if (new_val == NULL) {
+          return -1;
+        }
+      }
+      if (SetAttr(self, name, (new_val.get() == NULL) ? value : new_val.get()) <
+          0) {
+        return -1;
+      }
+    }
+  }
+  return 0;
+}
+
+// Allocates an incomplete Python Message: the caller must fill self->message,
+// self->owner and eventually self->parent.
+CMessage* NewEmptyMessage(CMessageClass* type) {
+  CMessage* self = reinterpret_cast<CMessage*>(
+      PyType_GenericAlloc(&type->super.ht_type, 0));
+  if (self == NULL) {
+    return NULL;
+  }
+
+  self->message = NULL;
+  self->parent = NULL;
+  self->parent_field_descriptor = NULL;
+  self->read_only = false;
+  self->extensions = NULL;
+
+  self->composite_fields = NULL;
+
+  return self;
+}
+
+// The __new__ method of Message classes.
+// Creates a new C++ message and takes ownership.
+static PyObject* New(PyTypeObject* cls,
+                     PyObject* unused_args, PyObject* unused_kwargs) {
+  CMessageClass* type = CheckMessageClass(cls);
+  if (type == NULL) {
+    return NULL;
+  }
+  // Retrieve the message descriptor and the default instance (=prototype).
+  const Descriptor* message_descriptor = type->message_descriptor;
+  if (message_descriptor == NULL) {
+    return NULL;
+  }
+  const Message* default_message = type->py_descriptor_pool->message_factory
+                                   ->GetPrototype(message_descriptor);
+  if (default_message == NULL) {
+    PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
+    return NULL;
+  }
+
+  CMessage* self = NewEmptyMessage(type);
+  if (self == NULL) {
+    return NULL;
+  }
+  self->message = default_message->New();
+  self->owner.reset(self->message);
+  return reinterpret_cast<PyObject*>(self);
+}
+
+// The __init__ method of Message classes.
+// It initializes fields from keywords passed to the constructor.
+static int Init(CMessage* self, PyObject* args, PyObject* kwargs) {
+  if (PyTuple_Size(args) != 0) {
+    PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
+    return -1;
+  }
+
+  return InitAttributes(self, kwargs);
+}
+
+// ---------------------------------------------------------------------
+// Deallocating a CMessage
+//
+// Deallocating a CMessage requires that we clear any weak references
+// from children to the message being deallocated.
+
+// Clear the weak reference from the child to the parent.
+struct ClearWeakReferences : public ChildVisitor {
+  int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
+    container->parent = NULL;
+    // The elements in the container have the same parent as the
+    // container itself, so NULL out that pointer as well.
+    const Py_ssize_t n = PyList_GET_SIZE(container->child_messages);
+    for (Py_ssize_t i = 0; i < n; ++i) {
+      CMessage* child_cmessage = reinterpret_cast<CMessage*>(
+          PyList_GET_ITEM(container->child_messages, i));
+      child_cmessage->parent = NULL;
+    }
+    return 0;
+  }
+
+  int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) {
+    container->parent = NULL;
+    return 0;
+  }
+
+  int VisitMapContainer(MapContainer* container) {
+    container->parent = NULL;
+    return 0;
+  }
+
+  int VisitCMessage(CMessage* cmessage,
+                    const FieldDescriptor* field_descriptor) {
+    cmessage->parent = NULL;
+    return 0;
+  }
+};
+
+static void Dealloc(CMessage* self) {
+  // Null out all weak references from children to this message.
+  GOOGLE_CHECK_EQ(0, ForEachCompositeField(self, ClearWeakReferences()));
+  if (self->extensions) {
+    self->extensions->parent = NULL;
+  }
+
+  Py_CLEAR(self->extensions);
+  Py_CLEAR(self->composite_fields);
+  self->owner.reset();
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+// ---------------------------------------------------------------------
+
+
+PyObject* IsInitialized(CMessage* self, PyObject* args) {
+  PyObject* errors = NULL;
+  if (PyArg_ParseTuple(args, "|O", &errors) < 0) {
+    return NULL;
+  }
+  if (self->message->IsInitialized()) {
+    Py_RETURN_TRUE;
+  }
+  if (errors != NULL) {
+    ScopedPyObjectPtr initialization_errors(
+        FindInitializationErrors(self));
+    if (initialization_errors == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr extend_name(PyString_FromString("extend"));
+    if (extend_name == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr result(PyObject_CallMethodObjArgs(
+        errors,
+        extend_name.get(),
+        initialization_errors.get(),
+        NULL));
+    if (result == NULL) {
+      return NULL;
+    }
+  }
+  Py_RETURN_FALSE;
+}
+
+PyObject* HasFieldByDescriptor(
+    CMessage* self, const FieldDescriptor* field_descriptor) {
+  Message* message = self->message;
+  if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
+    return NULL;
+  }
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    PyErr_SetString(PyExc_KeyError,
+                    "Field is repeated. A singular method is required.");
+    return NULL;
+  }
+  bool has_field =
+      message->GetReflection()->HasField(*message, field_descriptor);
+  return PyBool_FromLong(has_field ? 1 : 0);
+}
+
+const FieldDescriptor* FindFieldWithOneofs(
+    const Message* message, const string& field_name, bool* in_oneof) {
+  *in_oneof = false;
+  const Descriptor* descriptor = message->GetDescriptor();
+  const FieldDescriptor* field_descriptor =
+      descriptor->FindFieldByName(field_name);
+  if (field_descriptor != NULL) {
+    return field_descriptor;
+  }
+  const OneofDescriptor* oneof_desc =
+      descriptor->FindOneofByName(field_name);
+  if (oneof_desc != NULL) {
+    *in_oneof = true;
+    return message->GetReflection()->GetOneofFieldDescriptor(*message,
+                                                             oneof_desc);
+  }
+  return NULL;
+}
+
+bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    PyErr_Format(PyExc_ValueError,
+                 "Protocol message has no singular \"%s\" field.",
+                 field_descriptor->name().c_str());
+    return false;
+  }
+
+  if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    // HasField() for a oneof *itself* isn't supported.
+    if (in_oneof) {
+      PyErr_Format(PyExc_ValueError,
+                   "Can't test oneof field \"%s\" for presence in proto3, use "
+                   "WhichOneof instead.",
+                   field_descriptor->containing_oneof()->name().c_str());
+      return false;
+    }
+
+    // ...but HasField() for fields *in* a oneof is supported.
+    if (field_descriptor->containing_oneof() != NULL) {
+      return true;
+    }
+
+    if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+      PyErr_Format(
+          PyExc_ValueError,
+          "Can't test non-submessage field \"%s\" for presence in proto3.",
+          field_descriptor->name().c_str());
+      return false;
+    }
+  }
+
+  return true;
+}
+
+PyObject* HasField(CMessage* self, PyObject* arg) {
+  char* field_name;
+  Py_ssize_t size;
+#if PY_MAJOR_VERSION < 3
+  if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) {
+    return NULL;
+  }
+#else
+  field_name = PyUnicode_AsUTF8AndSize(arg, &size);
+  if (!field_name) {
+    return NULL;
+  }
+#endif
+
+  Message* message = self->message;
+  bool is_in_oneof;
+  const FieldDescriptor* field_descriptor =
+      FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
+  if (field_descriptor == NULL) {
+    if (!is_in_oneof) {
+      PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
+      return NULL;
+    } else {
+      Py_RETURN_FALSE;
+    }
+  }
+
+  if (!CheckHasPresence(field_descriptor, is_in_oneof)) {
+    return NULL;
+  }
+
+  if (message->GetReflection()->HasField(*message, field_descriptor)) {
+    Py_RETURN_TRUE;
+  }
+  if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+      field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+    // Special case: Python HasField() differs in semantics from C++
+    // slightly: we return HasField('enum_field') == true if there is
+    // an unknown enum value present. To implement this we have to
+    // look in the UnknownFieldSet.
+    const UnknownFieldSet& unknown_field_set =
+        message->GetReflection()->GetUnknownFields(*message);
+    for (int i = 0; i < unknown_field_set.field_count(); ++i) {
+      if (unknown_field_set.field(i).number() == field_descriptor->number()) {
+        Py_RETURN_TRUE;
+      }
+    }
+  }
+  Py_RETURN_FALSE;
+}
+
+PyObject* ClearExtension(CMessage* self, PyObject* extension) {
+  if (self->extensions != NULL) {
+    return extension_dict::ClearExtension(self->extensions, extension);
+  } else {
+    const FieldDescriptor* descriptor = GetExtensionDescriptor(extension);
+    if (descriptor == NULL) {
+      return NULL;
+    }
+    if (ScopedPyObjectPtr(ClearFieldByDescriptor(self, descriptor)) == NULL) {
+      return NULL;
+    }
+  }
+  Py_RETURN_NONE;
+}
+
+PyObject* HasExtension(CMessage* self, PyObject* extension) {
+  const FieldDescriptor* descriptor = GetExtensionDescriptor(extension);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  return HasFieldByDescriptor(self, descriptor);
+}
+
+// ---------------------------------------------------------------------
+// Releasing messages
+//
+// The Python API's ClearField() and Clear() methods behave
+// differently than their C++ counterparts.  While the C++ versions
+// clears the children the Python versions detaches the children,
+// without touching their content.  This impedance mismatch causes
+// some complexity in the implementation, which is captured in this
+// section.
+//
+// When a CMessage field is cleared we need to:
+//
+// * Release the Message used as the backing store for the CMessage
+//   from its parent.
+//
+// * Change the owner field of the released CMessage and all of its
+//   children to point to the newly released Message.
+//
+// * Clear the weak references from the released CMessage to the
+//   parent.
+//
+// When a RepeatedCompositeContainer field is cleared we need to:
+//
+// * Release all the Message used as the backing store for the
+//   CMessages stored in the container.
+//
+// * Change the owner field of all the released CMessage and all of
+//   their children to point to the newly released Messages.
+//
+// * Clear the weak references from the released container to the
+//   parent.
+
+struct SetOwnerVisitor : public ChildVisitor {
+  // new_owner must outlive this object.
+  explicit SetOwnerVisitor(const shared_ptr<Message>& new_owner)
+      : new_owner_(new_owner) {}
+
+  int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
+    repeated_composite_container::SetOwner(container, new_owner_);
+    return 0;
+  }
+
+  int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) {
+    repeated_scalar_container::SetOwner(container, new_owner_);
+    return 0;
+  }
+
+  int VisitMapContainer(MapContainer* container) {
+    container->SetOwner(new_owner_);
+    return 0;
+  }
+
+  int VisitCMessage(CMessage* cmessage,
+                    const FieldDescriptor* field_descriptor) {
+    return SetOwner(cmessage, new_owner_);
+  }
+
+ private:
+  const shared_ptr<Message>& new_owner_;
+};
+
+// Change the owner of this CMessage and all its children, recursively.
+int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
+  self->owner = new_owner;
+  if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1)
+    return -1;
+  return 0;
+}
+
+// Releases the message specified by 'field' and returns the
+// pointer. If the field does not exist a new message is created using
+// 'descriptor'. The caller takes ownership of the returned pointer.
+Message* ReleaseMessage(CMessage* self,
+                        const Descriptor* descriptor,
+                        const FieldDescriptor* field_descriptor) {
+  MessageFactory* message_factory = GetFactoryForMessage(self);
+  Message* released_message = self->message->GetReflection()->ReleaseMessage(
+      self->message, field_descriptor, message_factory);
+  // ReleaseMessage will return NULL which differs from
+  // child_cmessage->message, if the field does not exist.  In this case,
+  // the latter points to the default instance via a const_cast<>, so we
+  // have to reset it to a new mutable object since we are taking ownership.
+  if (released_message == NULL) {
+    const Message* prototype = message_factory->GetPrototype(descriptor);
+    GOOGLE_DCHECK(prototype != NULL);
+    released_message = prototype->New();
+  }
+
+  return released_message;
+}
+
+int ReleaseSubMessage(CMessage* self,
+                      const FieldDescriptor* field_descriptor,
+                      CMessage* child_cmessage) {
+  // Release the Message
+  shared_ptr<Message> released_message(ReleaseMessage(
+      self, child_cmessage->message->GetDescriptor(), field_descriptor));
+  child_cmessage->message = released_message.get();
+  child_cmessage->owner.swap(released_message);
+  child_cmessage->parent = NULL;
+  child_cmessage->parent_field_descriptor = NULL;
+  child_cmessage->read_only = false;
+  return ForEachCompositeField(child_cmessage,
+                               SetOwnerVisitor(child_cmessage->owner));
+}
+
+struct ReleaseChild : public ChildVisitor {
+  // message must outlive this object.
+  explicit ReleaseChild(CMessage* parent) :
+      parent_(parent) {}
+
+  int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
+    return repeated_composite_container::Release(
+        reinterpret_cast<RepeatedCompositeContainer*>(container));
+  }
+
+  int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) {
+    return repeated_scalar_container::Release(
+        reinterpret_cast<RepeatedScalarContainer*>(container));
+  }
+
+  int VisitMapContainer(MapContainer* container) {
+    return reinterpret_cast<MapContainer*>(container)->Release();
+  }
+
+  int VisitCMessage(CMessage* cmessage,
+                    const FieldDescriptor* field_descriptor) {
+    return ReleaseSubMessage(parent_, field_descriptor,
+        reinterpret_cast<CMessage*>(cmessage));
+  }
+
+  CMessage* parent_;
+};
+
+int InternalReleaseFieldByDescriptor(
+    CMessage* self,
+    const FieldDescriptor* field_descriptor,
+    PyObject* composite_field) {
+  return VisitCompositeField(
+      field_descriptor,
+      composite_field,
+      ReleaseChild(self));
+}
+
+PyObject* ClearFieldByDescriptor(
+    CMessage* self,
+    const FieldDescriptor* descriptor) {
+  if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
+    return NULL;
+  }
+  AssureWritable(self);
+  self->message->GetReflection()->ClearField(self->message, descriptor);
+  Py_RETURN_NONE;
+}
+
+PyObject* ClearField(CMessage* self, PyObject* arg) {
+  if (!PyString_Check(arg)) {
+    PyErr_SetString(PyExc_TypeError, "field name must be a string");
+    return NULL;
+  }
+#if PY_MAJOR_VERSION < 3
+  const char* field_name = PyString_AS_STRING(arg);
+  Py_ssize_t size = PyString_GET_SIZE(arg);
+#else
+  Py_ssize_t size;
+  const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size);
+#endif
+  AssureWritable(self);
+  Message* message = self->message;
+  ScopedPyObjectPtr arg_in_oneof;
+  bool is_in_oneof;
+  const FieldDescriptor* field_descriptor =
+      FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
+  if (field_descriptor == NULL) {
+    if (!is_in_oneof) {
+      PyErr_Format(PyExc_ValueError,
+                   "Protocol message has no \"%s\" field.", field_name);
+      return NULL;
+    } else {
+      Py_RETURN_NONE;
+    }
+  } else if (is_in_oneof) {
+    const string& name = field_descriptor->name();
+    arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size()));
+    arg = arg_in_oneof.get();
+  }
+
+  PyObject* composite_field = self->composite_fields ?
+      PyDict_GetItem(self->composite_fields, arg) : NULL;
+
+  // Only release the field if there's a possibility that there are
+  // references to it.
+  if (composite_field != NULL) {
+    if (InternalReleaseFieldByDescriptor(self, field_descriptor,
+                                         composite_field) < 0) {
+      return NULL;
+    }
+    PyDict_DelItem(self->composite_fields, arg);
+  }
+  message->GetReflection()->ClearField(message, field_descriptor);
+  if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+      !message->GetReflection()->SupportsUnknownEnumValues()) {
+    UnknownFieldSet* unknown_field_set =
+        message->GetReflection()->MutableUnknownFields(message);
+    unknown_field_set->DeleteByNumber(field_descriptor->number());
+  }
+
+  Py_RETURN_NONE;
+}
+
+PyObject* Clear(CMessage* self) {
+  AssureWritable(self);
+  if (ForEachCompositeField(self, ReleaseChild(self)) == -1)
+    return NULL;
+  Py_CLEAR(self->extensions);
+  if (self->composite_fields) {
+    PyDict_Clear(self->composite_fields);
+  }
+  self->message->Clear();
+  Py_RETURN_NONE;
+}
+
+// ---------------------------------------------------------------------
+
+static string GetMessageName(CMessage* self) {
+  if (self->parent_field_descriptor != NULL) {
+    return self->parent_field_descriptor->full_name();
+  } else {
+    return self->message->GetDescriptor()->full_name();
+  }
+}
+
+static PyObject* SerializeToString(CMessage* self, PyObject* args) {
+  if (!self->message->IsInitialized()) {
+    ScopedPyObjectPtr errors(FindInitializationErrors(self));
+    if (errors == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr comma(PyString_FromString(","));
+    if (comma == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr joined(
+        PyObject_CallMethod(comma.get(), "join", "O", errors.get()));
+    if (joined == NULL) {
+      return NULL;
+    }
+
+    // TODO(haberman): this is a (hopefully temporary) hack.  The unit testing
+    // infrastructure reloads all pure-Python modules for every test, but not
+    // C++ modules (because that's generally impossible:
+    // http://bugs.python.org/issue1144263).  But if we cache EncodeError, we'll
+    // return the EncodeError from a previous load of the module, which won't
+    // match a user's attempt to catch EncodeError.  So we have to look it up
+    // again every time.
+    ScopedPyObjectPtr message_module(PyImport_ImportModule(
+        "google.protobuf.message"));
+    if (message_module.get() == NULL) {
+      return NULL;
+    }
+
+    ScopedPyObjectPtr encode_error(
+        PyObject_GetAttrString(message_module.get(), "EncodeError"));
+    if (encode_error.get() == NULL) {
+      return NULL;
+    }
+    PyErr_Format(encode_error.get(),
+                 "Message %s is missing required fields: %s",
+                 GetMessageName(self).c_str(), PyString_AsString(joined.get()));
+    return NULL;
+  }
+  int size = self->message->ByteSize();
+  if (size <= 0) {
+    return PyBytes_FromString("");
+  }
+  PyObject* result = PyBytes_FromStringAndSize(NULL, size);
+  if (result == NULL) {
+    return NULL;
+  }
+  char* buffer = PyBytes_AS_STRING(result);
+  self->message->SerializeWithCachedSizesToArray(
+      reinterpret_cast<uint8*>(buffer));
+  return result;
+}
+
+static PyObject* SerializePartialToString(CMessage* self) {
+  string contents;
+  self->message->SerializePartialToString(&contents);
+  return PyBytes_FromStringAndSize(contents.c_str(), contents.size());
+}
+
+// Formats proto fields for ascii dumps using python formatting functions where
+// appropriate.
+class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
+ public:
+  // Python has some differences from C++ when printing floating point numbers.
+  //
+  // 1) Trailing .0 is always printed.
+  // 2) (Python2) Output is rounded to 12 digits.
+  // 3) (Python3) The full precision of the double is preserved (and Python uses
+  //    David M. Gay's dtoa(), when the C++ code uses SimpleDtoa. There are some
+  //    differences, but they rarely happen)
+  //
+  // We override floating point printing with the C-API function for printing
+  // Python floats to ensure consistency.
+  string PrintFloat(float value) const { return PrintDouble(value); }
+  string PrintDouble(double value) const {
+    // This implementation is not highly optimized (it allocates two temporary
+    // Python objects) but it is simple and portable.  If this is shown to be a
+    // performance bottleneck, we can optimize it, but the results will likely
+    // be more complicated to accommodate the differing behavior of double
+    // formatting between Python 2 and Python 3.
+    //
+    // (Though a valid question is: do we really want to make out output
+    // dependent on the Python version?)
+    ScopedPyObjectPtr py_value(PyFloat_FromDouble(value));
+    if (!py_value.get()) {
+      return string();
+    }
+
+    ScopedPyObjectPtr py_str(PyObject_Str(py_value.get()));
+    if (!py_str.get()) {
+      return string();
+    }
+
+    return string(PyString_AsString(py_str.get()));
+  }
+};
+
+static PyObject* ToStr(CMessage* self) {
+  TextFormat::Printer printer;
+  // Passes ownership
+  printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter());
+  printer.SetHideUnknownFields(true);
+  string output;
+  if (!printer.PrintToString(*self->message, &output)) {
+    PyErr_SetString(PyExc_ValueError, "Unable to convert message to str");
+    return NULL;
+  }
+  return PyString_FromString(output.c_str());
+}
+
+PyObject* MergeFrom(CMessage* self, PyObject* arg) {
+  CMessage* other_message;
+  if (!PyObject_TypeCheck(arg, &CMessage_Type)) {
+    PyErr_Format(PyExc_TypeError,
+                 "Parameter to MergeFrom() must be instance of same class: "
+                 "expected %s got %s.",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 Py_TYPE(arg)->tp_name);
+    return NULL;
+  }
+
+  other_message = reinterpret_cast<CMessage*>(arg);
+  if (other_message->message->GetDescriptor() !=
+      self->message->GetDescriptor()) {
+    PyErr_Format(PyExc_TypeError,
+                 "Parameter to MergeFrom() must be instance of same class: "
+                 "expected %s got %s.",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 other_message->message->GetDescriptor()->full_name().c_str());
+    return NULL;
+  }
+  AssureWritable(self);
+
+  // TODO(tibell): Message::MergeFrom might turn some child Messages
+  // into mutable messages, invalidating the message field in the
+  // corresponding CMessages.  We should run a FixupMessageReferences
+  // pass here.
+
+  self->message->MergeFrom(*other_message->message);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CopyFrom(CMessage* self, PyObject* arg) {
+  CMessage* other_message;
+  if (!PyObject_TypeCheck(arg, &CMessage_Type)) {
+    PyErr_Format(PyExc_TypeError,
+                 "Parameter to CopyFrom() must be instance of same class: "
+                 "expected %s got %s.",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 Py_TYPE(arg)->tp_name);
+    return NULL;
+  }
+
+  other_message = reinterpret_cast<CMessage*>(arg);
+
+  if (self == other_message) {
+    Py_RETURN_NONE;
+  }
+
+  if (other_message->message->GetDescriptor() !=
+      self->message->GetDescriptor()) {
+    PyErr_Format(PyExc_TypeError,
+                 "Parameter to CopyFrom() must be instance of same class: "
+                 "expected %s got %s.",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 other_message->message->GetDescriptor()->full_name().c_str());
+    return NULL;
+  }
+
+  AssureWritable(self);
+
+  // CopyFrom on the message will not clean up self->composite_fields,
+  // which can leave us in an inconsistent state, so clear it out here.
+  (void)ScopedPyObjectPtr(Clear(self));
+
+  self->message->CopyFrom(*other_message->message);
+
+  Py_RETURN_NONE;
+}
+
+// Protobuf has a 64MB limit built in, this variable will override this. Please
+// do not enable this unless you fully understand the implications: protobufs
+// must all be kept in memory at the same time, so if they grow too big you may
+// get OOM errors. The protobuf APIs do not provide any tools for processing
+// protobufs in chunks.  If you have protos this big you should break them up if
+// it is at all convenient to do so.
+static bool allow_oversize_protos = false;
+
+// Provide a method in the module to set allow_oversize_protos to a boolean
+// value. This method returns the newly value of allow_oversize_protos.
+static PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg) {
+  if (!arg || !PyBool_Check(arg)) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Argument to SetAllowOversizeProtos must be boolean");
+    return NULL;
+  }
+  allow_oversize_protos = PyObject_IsTrue(arg);
+  if (allow_oversize_protos) {
+    Py_RETURN_TRUE;
+  } else {
+    Py_RETURN_FALSE;
+  }
+}
+
+static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
+  const void* data;
+  Py_ssize_t data_length;
+  if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) {
+    return NULL;
+  }
+
+  AssureWritable(self);
+  io::CodedInputStream input(
+      reinterpret_cast<const uint8*>(data), data_length);
+  if (allow_oversize_protos) {
+    input.SetTotalBytesLimit(INT_MAX, INT_MAX);
+  }
+  PyDescriptorPool* pool = GetDescriptorPoolForMessage(self);
+  input.SetExtensionRegistry(pool->pool, pool->message_factory);
+  bool success = self->message->MergePartialFromCodedStream(&input);
+  if (success) {
+    return PyInt_FromLong(input.CurrentPosition());
+  } else {
+    PyErr_Format(DecodeError_class, "Error parsing message");
+    return NULL;
+  }
+}
+
+static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
+  if (ScopedPyObjectPtr(Clear(self)) == NULL) {
+    return NULL;
+  }
+  return MergeFromString(self, arg);
+}
+
+static PyObject* ByteSize(CMessage* self, PyObject* args) {
+  return PyLong_FromLong(self->message->ByteSize());
+}
+
+static PyObject* RegisterExtension(PyObject* cls,
+                                   PyObject* extension_handle) {
+  const FieldDescriptor* descriptor =
+      GetExtensionDescriptor(extension_handle);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+
+  ScopedPyObjectPtr extensions_by_name(
+      PyObject_GetAttr(cls, k_extensions_by_name));
+  if (extensions_by_name == NULL) {
+    PyErr_SetString(PyExc_TypeError, "no extensions_by_name on class");
+    return NULL;
+  }
+  ScopedPyObjectPtr full_name(PyObject_GetAttr(extension_handle, kfull_name));
+  if (full_name == NULL) {
+    return NULL;
+  }
+
+  // If the extension was already registered, check that it is the same.
+  PyObject* existing_extension =
+      PyDict_GetItem(extensions_by_name.get(), full_name.get());
+  if (existing_extension != NULL) {
+    const FieldDescriptor* existing_extension_descriptor =
+        GetExtensionDescriptor(existing_extension);
+    if (existing_extension_descriptor != descriptor) {
+      PyErr_SetString(PyExc_ValueError, "Double registration of Extensions");
+      return NULL;
+    }
+    // Nothing else to do.
+    Py_RETURN_NONE;
+  }
+
+  if (PyDict_SetItem(extensions_by_name.get(), full_name.get(),
+                     extension_handle) < 0) {
+    return NULL;
+  }
+
+  // Also store a mapping from extension number to implementing class.
+  ScopedPyObjectPtr extensions_by_number(
+      PyObject_GetAttr(cls, k_extensions_by_number));
+  if (extensions_by_number == NULL) {
+    PyErr_SetString(PyExc_TypeError, "no extensions_by_number on class");
+    return NULL;
+  }
+
+  ScopedPyObjectPtr number(PyObject_GetAttrString(extension_handle, "number"));
+  if (number == NULL) {
+    return NULL;
+  }
+
+  // If the extension was already registered by number, check that it is the
+  // same.
+  existing_extension = PyDict_GetItem(extensions_by_number.get(), number.get());
+  if (existing_extension != NULL) {
+    const FieldDescriptor* existing_extension_descriptor =
+        GetExtensionDescriptor(existing_extension);
+    if (existing_extension_descriptor != descriptor) {
+      const Descriptor* msg_desc = GetMessageDescriptor(
+          reinterpret_cast<PyTypeObject*>(cls));
+      PyErr_Format(
+          PyExc_ValueError,
+          "Extensions \"%s\" and \"%s\" both try to extend message type "
+          "\"%s\" with field number %ld.",
+          existing_extension_descriptor->full_name().c_str(),
+          descriptor->full_name().c_str(),
+          msg_desc->full_name().c_str(),
+          PyInt_AsLong(number.get()));
+      return NULL;
+    }
+    // Nothing else to do.
+    Py_RETURN_NONE;
+  }
+  if (PyDict_SetItem(extensions_by_number.get(), number.get(),
+                     extension_handle) < 0) {
+    return NULL;
+  }
+
+  // Check if it's a message set
+  if (descriptor->is_extension() &&
+      descriptor->containing_type()->options().message_set_wire_format() &&
+      descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+      descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) {
+    ScopedPyObjectPtr message_name(PyString_FromStringAndSize(
+        descriptor->message_type()->full_name().c_str(),
+        descriptor->message_type()->full_name().size()));
+    if (message_name == NULL) {
+      return NULL;
+    }
+    PyDict_SetItem(extensions_by_name.get(), message_name.get(),
+                   extension_handle);
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject* SetInParent(CMessage* self, PyObject* args) {
+  AssureWritable(self);
+  Py_RETURN_NONE;
+}
+
+static PyObject* WhichOneof(CMessage* self, PyObject* arg) {
+  Py_ssize_t name_size;
+  char *name_data;
+  if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0)
+    return NULL;
+  string oneof_name = string(name_data, name_size);
+  const OneofDescriptor* oneof_desc =
+      self->message->GetDescriptor()->FindOneofByName(oneof_name);
+  if (oneof_desc == NULL) {
+    PyErr_Format(PyExc_ValueError,
+                 "Protocol message has no oneof \"%s\" field.",
+                 oneof_name.c_str());
+    return NULL;
+  }
+  const FieldDescriptor* field_in_oneof =
+      self->message->GetReflection()->GetOneofFieldDescriptor(
+          *self->message, oneof_desc);
+  if (field_in_oneof == NULL) {
+    Py_RETURN_NONE;
+  } else {
+    const string& name = field_in_oneof->name();
+    return PyString_FromStringAndSize(name.c_str(), name.size());
+  }
+}
+
+static PyObject* GetExtensionDict(CMessage* self, void *closure);
+
+static PyObject* ListFields(CMessage* self) {
+  vector<const FieldDescriptor*> fields;
+  self->message->GetReflection()->ListFields(*self->message, &fields);
+
+  // Normally, the list will be exactly the size of the fields.
+  ScopedPyObjectPtr all_fields(PyList_New(fields.size()));
+  if (all_fields == NULL) {
+    return NULL;
+  }
+
+  // When there are unknown extensions, the py list will *not* contain
+  // the field information.  Thus the actual size of the py list will be
+  // smaller than the size of fields.  Set the actual size at the end.
+  Py_ssize_t actual_size = 0;
+  for (size_t i = 0; i < fields.size(); ++i) {
+    ScopedPyObjectPtr t(PyTuple_New(2));
+    if (t == NULL) {
+      return NULL;
+    }
+
+    if (fields[i]->is_extension()) {
+      ScopedPyObjectPtr extension_field(
+          PyFieldDescriptor_FromDescriptor(fields[i]));
+      if (extension_field == NULL) {
+        return NULL;
+      }
+      // With C++ descriptors, the field can always be retrieved, but for
+      // unknown extensions which have not been imported in Python code, there
+      // is no message class and we cannot retrieve the value.
+      // TODO(amauryfa): consider building the class on the fly!
+      if (fields[i]->message_type() != NULL &&
+          cdescriptor_pool::GetMessageClass(
+              GetDescriptorPoolForMessage(self),
+              fields[i]->message_type()) == NULL) {
+        PyErr_Clear();
+        continue;
+      }
+      ScopedPyObjectPtr extensions(GetExtensionDict(self, NULL));
+      if (extensions == NULL) {
+        return NULL;
+      }
+      // 'extension' reference later stolen by PyTuple_SET_ITEM.
+      PyObject* extension = PyObject_GetItem(
+          extensions.get(), extension_field.get());
+      if (extension == NULL) {
+        return NULL;
+      }
+      PyTuple_SET_ITEM(t.get(), 0, extension_field.release());
+      // Steals reference to 'extension'
+      PyTuple_SET_ITEM(t.get(), 1, extension);
+    } else {
+      // Normal field
+      const string& field_name = fields[i]->name();
+      ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize(
+          field_name.c_str(), field_name.length()));
+      if (py_field_name == NULL) {
+        PyErr_SetString(PyExc_ValueError, "bad string");
+        return NULL;
+      }
+      ScopedPyObjectPtr field_descriptor(
+          PyFieldDescriptor_FromDescriptor(fields[i]));
+      if (field_descriptor == NULL) {
+        return NULL;
+      }
+
+      PyObject* field_value = GetAttr(self, py_field_name.get());
+      if (field_value == NULL) {
+        PyErr_SetObject(PyExc_ValueError, py_field_name.get());
+        return NULL;
+      }
+      PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release());
+      PyTuple_SET_ITEM(t.get(), 1, field_value);
+    }
+    PyList_SET_ITEM(all_fields.get(), actual_size, t.release());
+    ++actual_size;
+  }
+  if (static_cast<size_t>(actual_size) != fields.size() &&
+      (PyList_SetSlice(all_fields.get(), actual_size, fields.size(), NULL) <
+       0)) {
+    return NULL;
+  }
+  return all_fields.release();
+}
+
+static PyObject* DiscardUnknownFields(CMessage* self) {
+  AssureWritable(self);
+  self->message->DiscardUnknownFields();
+  Py_RETURN_NONE;
+}
+
+PyObject* FindInitializationErrors(CMessage* self) {
+  Message* message = self->message;
+  vector<string> errors;
+  message->FindInitializationErrors(&errors);
+
+  PyObject* error_list = PyList_New(errors.size());
+  if (error_list == NULL) {
+    return NULL;
+  }
+  for (size_t i = 0; i < errors.size(); ++i) {
+    const string& error = errors[i];
+    PyObject* error_string = PyString_FromStringAndSize(
+        error.c_str(), error.length());
+    if (error_string == NULL) {
+      Py_DECREF(error_list);
+      return NULL;
+    }
+    PyList_SET_ITEM(error_list, i, error_string);
+  }
+  return error_list;
+}
+
+static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
+  // Only equality comparisons are implemented.
+  if (opid != Py_EQ && opid != Py_NE) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+  bool equals = true;
+  // If other is not a message, it cannot be equal.
+  if (!PyObject_TypeCheck(other, &CMessage_Type)) {
+    equals = false;
+  }
+  const google::protobuf::Message* other_message =
+      reinterpret_cast<CMessage*>(other)->message;
+  // If messages don't have the same descriptors, they are not equal.
+  if (equals &&
+      self->message->GetDescriptor() != other_message->GetDescriptor()) {
+    equals = false;
+  }
+  // Check the message contents.
+  if (equals && !google::protobuf::util::MessageDifferencer::Equals(
+          *self->message,
+          *reinterpret_cast<CMessage*>(other)->message)) {
+    equals = false;
+  }
+  if (equals ^ (opid == Py_EQ)) {
+    Py_RETURN_FALSE;
+  } else {
+    Py_RETURN_TRUE;
+  }
+}
+
+PyObject* InternalGetScalar(const Message* message,
+                            const FieldDescriptor* field_descriptor) {
+  const Reflection* reflection = message->GetReflection();
+
+  if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
+    return NULL;
+  }
+
+  PyObject* result = NULL;
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = reflection->GetInt32(*message, field_descriptor);
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = reflection->GetInt64(*message, field_descriptor);
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = reflection->GetUInt32(*message, field_descriptor);
+      result = PyInt_FromSize_t(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = reflection->GetUInt64(*message, field_descriptor);
+      result = PyLong_FromUnsignedLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = reflection->GetFloat(*message, field_descriptor);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = reflection->GetDouble(*message, field_descriptor);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = reflection->GetBool(*message, field_descriptor);
+      result = PyBool_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string value = reflection->GetString(*message, field_descriptor);
+      result = ToStringObject(field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+          !message->GetReflection()->HasField(*message, field_descriptor)) {
+        // Look for the value in the unknown fields.
+        const UnknownFieldSet& unknown_field_set =
+            message->GetReflection()->GetUnknownFields(*message);
+        for (int i = 0; i < unknown_field_set.field_count(); ++i) {
+          if (unknown_field_set.field(i).number() ==
+              field_descriptor->number() &&
+              unknown_field_set.field(i).type() ==
+              google::protobuf::UnknownField::TYPE_VARINT) {
+            result = PyInt_FromLong(unknown_field_set.field(i).varint());
+            break;
+          }
+        }
+      }
+
+      if (result == NULL) {
+        const EnumValueDescriptor* enum_value =
+            message->GetReflection()->GetEnum(*message, field_descriptor);
+        result = PyInt_FromLong(enum_value->number());
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Getting a value from a field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  return result;
+}
+
+PyObject* InternalGetSubMessage(
+    CMessage* self, const FieldDescriptor* field_descriptor) {
+  const Reflection* reflection = self->message->GetReflection();
+  PyDescriptorPool* pool = GetDescriptorPoolForMessage(self);
+  const Message& sub_message = reflection->GetMessage(
+      *self->message, field_descriptor, pool->message_factory);
+
+  CMessageClass* message_class = cdescriptor_pool::GetMessageClass(
+      pool, field_descriptor->message_type());
+  if (message_class == NULL) {
+    return NULL;
+  }
+
+  CMessage* cmsg = cmessage::NewEmptyMessage(message_class);
+  if (cmsg == NULL) {
+    return NULL;
+  }
+
+  cmsg->owner = self->owner;
+  cmsg->parent = self;
+  cmsg->parent_field_descriptor = field_descriptor;
+  cmsg->read_only = !reflection->HasField(*self->message, field_descriptor);
+  cmsg->message = const_cast<Message*>(&sub_message);
+
+  return reinterpret_cast<PyObject*>(cmsg);
+}
+
+int InternalSetNonOneofScalar(
+    Message* message,
+    const FieldDescriptor* field_descriptor,
+    PyObject* arg) {
+  const Reflection* reflection = message->GetReflection();
+
+  if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
+    return -1;
+  }
+
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(arg, value, -1);
+      reflection->SetInt32(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(arg, value, -1);
+      reflection->SetInt64(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(arg, value, -1);
+      reflection->SetUInt32(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(arg, value, -1);
+      reflection->SetUInt64(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
+      reflection->SetFloat(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
+      reflection->SetDouble(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(arg, value, -1);
+      reflection->SetBool(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      if (!CheckAndSetString(
+          arg, message, field_descriptor, reflection, false, -1)) {
+        return -1;
+      }
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(arg, value, -1);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->SetEnumValue(message, field_descriptor, value);
+      } else {
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->SetEnum(message, field_descriptor, enum_value);
+        } else {
+          PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
+          return -1;
+        }
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Setting value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+      return -1;
+  }
+
+  return 0;
+}
+
+int InternalSetScalar(
+    CMessage* self,
+    const FieldDescriptor* field_descriptor,
+    PyObject* arg) {
+  if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) {
+    return -1;
+  }
+
+  if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) {
+    return -1;
+  }
+
+  return InternalSetNonOneofScalar(self->message, field_descriptor, arg);
+}
+
+PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
+  PyObject* py_cmsg = PyObject_CallObject(
+      reinterpret_cast<PyObject*>(cls), NULL);
+  if (py_cmsg == NULL) {
+    return NULL;
+  }
+  CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
+
+  ScopedPyObjectPtr py_length(MergeFromString(cmsg, serialized));
+  if (py_length == NULL) {
+    Py_DECREF(py_cmsg);
+    return NULL;
+  }
+
+  return py_cmsg;
+}
+
+PyObject* DeepCopy(CMessage* self, PyObject* arg) {
+  PyObject* clone = PyObject_CallObject(
+      reinterpret_cast<PyObject*>(Py_TYPE(self)), NULL);
+  if (clone == NULL) {
+    return NULL;
+  }
+  if (!PyObject_TypeCheck(clone, &CMessage_Type)) {
+    Py_DECREF(clone);
+    return NULL;
+  }
+  if (ScopedPyObjectPtr(MergeFrom(
+          reinterpret_cast<CMessage*>(clone),
+          reinterpret_cast<PyObject*>(self))) == NULL) {
+    Py_DECREF(clone);
+    return NULL;
+  }
+  return clone;
+}
+
+PyObject* ToUnicode(CMessage* self) {
+  // Lazy import to prevent circular dependencies
+  ScopedPyObjectPtr text_format(
+      PyImport_ImportModule("google.protobuf.text_format"));
+  if (text_format == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr method_name(PyString_FromString("MessageToString"));
+  if (method_name == NULL) {
+    return NULL;
+  }
+  Py_INCREF(Py_True);
+  ScopedPyObjectPtr encoded(PyObject_CallMethodObjArgs(
+      text_format.get(), method_name.get(), self, Py_True, NULL));
+  Py_DECREF(Py_True);
+  if (encoded == NULL) {
+    return NULL;
+  }
+#if PY_MAJOR_VERSION < 3
+  PyObject* decoded = PyString_AsDecodedObject(encoded.get(), "utf-8", NULL);
+#else
+  PyObject* decoded = PyUnicode_FromEncodedObject(encoded.get(), "utf-8", NULL);
+#endif
+  if (decoded == NULL) {
+    return NULL;
+  }
+  return decoded;
+}
+
+PyObject* Reduce(CMessage* self) {
+  ScopedPyObjectPtr constructor(reinterpret_cast<PyObject*>(Py_TYPE(self)));
+  constructor.inc();
+  ScopedPyObjectPtr args(PyTuple_New(0));
+  if (args == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr state(PyDict_New());
+  if (state == NULL) {
+    return  NULL;
+  }
+  ScopedPyObjectPtr serialized(SerializePartialToString(self));
+  if (serialized == NULL) {
+    return NULL;
+  }
+  if (PyDict_SetItemString(state.get(), "serialized", serialized.get()) < 0) {
+    return NULL;
+  }
+  return Py_BuildValue("OOO", constructor.get(), args.get(), state.get());
+}
+
+PyObject* SetState(CMessage* self, PyObject* state) {
+  if (!PyDict_Check(state)) {
+    PyErr_SetString(PyExc_TypeError, "state not a dict");
+    return NULL;
+  }
+  PyObject* serialized = PyDict_GetItemString(state, "serialized");
+  if (serialized == NULL) {
+    return NULL;
+  }
+  if (ScopedPyObjectPtr(ParseFromString(self, serialized)) == NULL) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+// CMessage static methods:
+PyObject* _CheckCalledFromGeneratedFile(PyObject* unused,
+                                        PyObject* unused_arg) {
+  if (!_CalledFromGeneratedFile(1)) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Descriptors should not be created directly, "
+                    "but only retrieved from their parent.");
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* GetExtensionDict(CMessage* self, void *closure) {
+  if (self->extensions)  {
+    Py_INCREF(self->extensions);
+    return reinterpret_cast<PyObject*>(self->extensions);
+  }
+
+  // If there are extension_ranges, the message is "extendable". Allocate a
+  // dictionary to store the extension fields.
+  const Descriptor* descriptor = GetMessageDescriptor(Py_TYPE(self));
+  if (descriptor->extension_range_count() > 0) {
+    ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self);
+    if (extension_dict == NULL) {
+      return NULL;
+    }
+    self->extensions = extension_dict;
+    Py_INCREF(self->extensions);
+    return reinterpret_cast<PyObject*>(self->extensions);
+  }
+
+  PyErr_SetNone(PyExc_AttributeError);
+  return NULL;
+}
+
+static PyGetSetDef Getters[] = {
+  {"Extensions", (getter)GetExtensionDict, NULL, "Extension dict"},
+  {NULL}
+};
+
+static PyMethodDef Methods[] = {
+  { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+    "Makes a deep copy of the class." },
+  { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+    "Outputs picklable representation of the message." },
+  { "__setstate__", (PyCFunction)SetState, METH_O,
+    "Inputs picklable representation of the message." },
+  { "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS,
+    "Outputs a unicode representation of the message." },
+  { "ByteSize", (PyCFunction)ByteSize, METH_NOARGS,
+    "Returns the size of the message in bytes." },
+  { "Clear", (PyCFunction)Clear, METH_NOARGS,
+    "Clears the message." },
+  { "ClearExtension", (PyCFunction)ClearExtension, METH_O,
+    "Clears a message field." },
+  { "ClearField", (PyCFunction)ClearField, METH_O,
+    "Clears a message field." },
+  { "CopyFrom", (PyCFunction)CopyFrom, METH_O,
+    "Copies a protocol message into the current message." },
+  { "DiscardUnknownFields", (PyCFunction)DiscardUnknownFields, METH_NOARGS,
+    "Discards the unknown fields." },
+  { "FindInitializationErrors", (PyCFunction)FindInitializationErrors,
+    METH_NOARGS,
+    "Finds unset required fields." },
+  { "FromString", (PyCFunction)FromString, METH_O | METH_CLASS,
+    "Creates new method instance from given serialized data." },
+  { "HasExtension", (PyCFunction)HasExtension, METH_O,
+    "Checks if a message field is set." },
+  { "HasField", (PyCFunction)HasField, METH_O,
+    "Checks if a message field is set." },
+  { "IsInitialized", (PyCFunction)IsInitialized, METH_VARARGS,
+    "Checks if all required fields of a protocol message are set." },
+  { "ListFields", (PyCFunction)ListFields, METH_NOARGS,
+    "Lists all set fields of a message." },
+  { "MergeFrom", (PyCFunction)MergeFrom, METH_O,
+    "Merges a protocol message into the current message." },
+  { "MergeFromString", (PyCFunction)MergeFromString, METH_O,
+    "Merges a serialized message into the current message." },
+  { "ParseFromString", (PyCFunction)ParseFromString, METH_O,
+    "Parses a serialized message into the current message." },
+  { "RegisterExtension", (PyCFunction)RegisterExtension, METH_O | METH_CLASS,
+    "Registers an extension with the current message." },
+  { "SerializePartialToString", (PyCFunction)SerializePartialToString,
+    METH_NOARGS,
+    "Serializes the message to a string, even if it isn't initialized." },
+  { "SerializeToString", (PyCFunction)SerializeToString, METH_NOARGS,
+    "Serializes the message to a string, only for initialized messages." },
+  { "SetInParent", (PyCFunction)SetInParent, METH_NOARGS,
+    "Sets the has bit of the given field in its parent message." },
+  { "WhichOneof", (PyCFunction)WhichOneof, METH_O,
+    "Returns the name of the field set inside a oneof, "
+    "or None if no field is set." },
+
+  // Static Methods.
+  { "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile,
+    METH_NOARGS | METH_STATIC,
+    "Raises TypeError if the caller is not in a _pb2.py file."},
+  { NULL, NULL}
+};
+
+static bool SetCompositeField(
+    CMessage* self, PyObject* name, PyObject* value) {
+  if (self->composite_fields == NULL) {
+    self->composite_fields = PyDict_New();
+    if (self->composite_fields == NULL) {
+      return false;
+    }
+  }
+  return PyDict_SetItem(self->composite_fields, name, value) == 0;
+}
+
+PyObject* GetAttr(CMessage* self, PyObject* name) {
+  PyObject* value = self->composite_fields ?
+      PyDict_GetItem(self->composite_fields, name) : NULL;
+  if (value != NULL) {
+    Py_INCREF(value);
+    return value;
+  }
+
+  const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
+  if (field_descriptor == NULL) {
+    return CMessage_Type.tp_base->tp_getattro(
+        reinterpret_cast<PyObject*>(self), name);
+  }
+
+  if (field_descriptor->is_map()) {
+    PyObject* py_container = NULL;
+    const Descriptor* entry_type = field_descriptor->message_type();
+    const FieldDescriptor* value_type = entry_type->FindFieldByName("value");
+    if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      CMessageClass* value_class = cdescriptor_pool::GetMessageClass(
+          GetDescriptorPoolForMessage(self), value_type->message_type());
+      if (value_class == NULL) {
+        return NULL;
+      }
+      py_container =
+          NewMessageMapContainer(self, field_descriptor, value_class);
+    } else {
+      py_container = NewScalarMapContainer(self, field_descriptor);
+    }
+    if (py_container == NULL) {
+      return NULL;
+    }
+    if (!SetCompositeField(self, name, py_container)) {
+      Py_DECREF(py_container);
+      return NULL;
+    }
+    return py_container;
+  }
+
+  if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+    PyObject* py_container = NULL;
+    if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      CMessageClass* message_class = cdescriptor_pool::GetMessageClass(
+          GetDescriptorPoolForMessage(self), field_descriptor->message_type());
+      if (message_class == NULL) {
+        return NULL;
+      }
+      py_container = repeated_composite_container::NewContainer(
+          self, field_descriptor, message_class);
+    } else {
+      py_container = repeated_scalar_container::NewContainer(
+          self, field_descriptor);
+    }
+    if (py_container == NULL) {
+      return NULL;
+    }
+    if (!SetCompositeField(self, name, py_container)) {
+      Py_DECREF(py_container);
+      return NULL;
+    }
+    return py_container;
+  }
+
+  if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
+    if (sub_message == NULL) {
+      return NULL;
+    }
+    if (!SetCompositeField(self, name, sub_message)) {
+      Py_DECREF(sub_message);
+      return NULL;
+    }
+    return sub_message;
+  }
+
+  return InternalGetScalar(self->message, field_descriptor);
+}
+
+int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
+  if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) {
+    PyErr_SetString(PyExc_TypeError, "Can't set composite field");
+    return -1;
+  }
+
+  const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
+  if (field_descriptor != NULL) {
+    AssureWritable(self);
+    if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+      PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated "
+                   "field \"%s\" in protocol message object.",
+                   field_descriptor->name().c_str());
+      return -1;
+    } else {
+      if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        PyErr_Format(PyExc_AttributeError, "Assignment not allowed to "
+                     "field \"%s\" in protocol message object.",
+                     field_descriptor->name().c_str());
+        return -1;
+      } else {
+        return InternalSetScalar(self, field_descriptor, value);
+      }
+    }
+  }
+
+  PyErr_Format(PyExc_AttributeError,
+               "Assignment not allowed "
+               "(no field \"%s\" in protocol message object).",
+               PyString_AsString(name));
+  return -1;
+}
+
+}  // namespace cmessage
+
+PyTypeObject CMessage_Type = {
+  PyVarObject_HEAD_INIT(&CMessageClass_Type, 0)
+  FULL_MODULE_NAME ".CMessage",        // tp_name
+  sizeof(CMessage),                    // tp_basicsize
+  0,                                   //  tp_itemsize
+  (destructor)cmessage::Dealloc,       //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  (reprfunc)cmessage::ToStr,           //  tp_repr
+  0,                                   //  tp_as_number
+  0,                                   //  tp_as_sequence
+  0,                                   //  tp_as_mapping
+  PyObject_HashNotImplemented,         //  tp_hash
+  0,                                   //  tp_call
+  (reprfunc)cmessage::ToStr,           //  tp_str
+  (getattrofunc)cmessage::GetAttr,     //  tp_getattro
+  (setattrofunc)cmessage::SetAttr,     //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  //  tp_flags
+  "A ProtocolMessage",                 //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  (richcmpfunc)cmessage::RichCompare,  //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  0,                                   //  tp_iter
+  0,                                   //  tp_iternext
+  cmessage::Methods,                   //  tp_methods
+  0,                                   //  tp_members
+  cmessage::Getters,                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  (initproc)cmessage::Init,            //  tp_init
+  0,                                   //  tp_alloc
+  cmessage::New,                       //  tp_new
+};
+
+// --- Exposing the C proto living inside Python proto to C code:
+
+const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
+Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg);
+
+static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
+  if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
+    return NULL;
+  }
+  CMessage* cmsg = reinterpret_cast<CMessage*>(msg);
+  return cmsg->message;
+}
+
+static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
+  if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
+    return NULL;
+  }
+  CMessage* cmsg = reinterpret_cast<CMessage*>(msg);
+  if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) ||
+      (cmsg->extensions != NULL &&
+       PyDict_Size(cmsg->extensions->values) != 0)) {
+    // There is currently no way of accurately syncing arbitrary changes to
+    // the underlying C++ message back to the CMessage (e.g. removed repeated
+    // composite containers). We only allow direct mutation of the underlying
+    // C++ message if there is no child data in the CMessage.
+    return NULL;
+  }
+  cmessage::AssureWritable(cmsg);
+  return cmsg->message;
+}
+
+static const char module_docstring[] =
+"python-proto2 is a module that can be used to enhance proto2 Python API\n"
+"performance.\n"
+"\n"
+"It provides access to the protocol buffers C++ reflection API that\n"
+"implements the basic protocol buffer functions.";
+
+void InitGlobals() {
+  // TODO(gps): Check all return values in this function for NULL and propagate
+  // the error (MemoryError) on up to result in an import failure.  These should
+  // also be freed and reset to NULL during finalization.
+  kPythonZero = PyInt_FromLong(0);
+  kint32min_py = PyInt_FromLong(kint32min);
+  kint32max_py = PyInt_FromLong(kint32max);
+  kuint32max_py = PyLong_FromLongLong(kuint32max);
+  kint64min_py = PyLong_FromLongLong(kint64min);
+  kint64max_py = PyLong_FromLongLong(kint64max);
+  kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max);
+
+  kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
+  k_cdescriptor = PyString_FromString("_cdescriptor");
+  kfull_name = PyString_FromString("full_name");
+  k_extensions_by_name = PyString_FromString("_extensions_by_name");
+  k_extensions_by_number = PyString_FromString("_extensions_by_number");
+
+  PyObject *dummy_obj = PySet_New(NULL);
+  kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
+  Py_DECREF(dummy_obj);
+}
+
+bool InitProto2MessageModule(PyObject *m) {
+  // Initialize types and globals in descriptor.cc
+  if (!InitDescriptor()) {
+    return false;
+  }
+
+  // Initialize types and globals in descriptor_pool.cc
+  if (!InitDescriptorPool()) {
+    return false;
+  }
+
+  // Initialize constants defined in this file.
+  InitGlobals();
+
+  CMessageClass_Type.tp_base = &PyType_Type;
+  if (PyType_Ready(&CMessageClass_Type) < 0) {
+    return false;
+  }
+  PyModule_AddObject(m, "MessageMeta",
+                     reinterpret_cast<PyObject*>(&CMessageClass_Type));
+
+  if (PyType_Ready(&CMessage_Type) < 0) {
+    return false;
+  }
+
+  // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set
+  // it here as well to document that subclasses need to set it.
+  PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
+  // Subclasses with message extensions will override _extensions_by_name and
+  // _extensions_by_number with fresh mutable dictionaries in AddDescriptors.
+  // All other classes can share this same immutable mapping.
+  ScopedPyObjectPtr empty_dict(PyDict_New());
+  if (empty_dict == NULL) {
+    return false;
+  }
+  ScopedPyObjectPtr immutable_dict(PyDictProxy_New(empty_dict.get()));
+  if (immutable_dict == NULL) {
+    return false;
+  }
+  if (PyDict_SetItem(CMessage_Type.tp_dict,
+                     k_extensions_by_name, immutable_dict.get()) < 0) {
+    return false;
+  }
+  if (PyDict_SetItem(CMessage_Type.tp_dict,
+                     k_extensions_by_number, immutable_dict.get()) < 0) {
+    return false;
+  }
+
+  PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
+
+  // Initialize Repeated container types.
+  {
+    if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
+      return false;
+    }
+
+    PyModule_AddObject(m, "RepeatedScalarContainer",
+                       reinterpret_cast<PyObject*>(
+                           &RepeatedScalarContainer_Type));
+
+    if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
+      return false;
+    }
+
+    PyModule_AddObject(
+        m, "RepeatedCompositeContainer",
+        reinterpret_cast<PyObject*>(
+            &RepeatedCompositeContainer_Type));
+
+    // Register them as collections.Sequence
+    ScopedPyObjectPtr collections(PyImport_ImportModule("collections"));
+    if (collections == NULL) {
+      return false;
+    }
+    ScopedPyObjectPtr mutable_sequence(
+        PyObject_GetAttrString(collections.get(), "MutableSequence"));
+    if (mutable_sequence == NULL) {
+      return false;
+    }
+    if (ScopedPyObjectPtr(
+            PyObject_CallMethod(mutable_sequence.get(), "register", "O",
+                                &RepeatedScalarContainer_Type)) == NULL) {
+      return false;
+    }
+    if (ScopedPyObjectPtr(
+            PyObject_CallMethod(mutable_sequence.get(), "register", "O",
+                                &RepeatedCompositeContainer_Type)) == NULL) {
+      return false;
+    }
+  }
+
+  // Initialize Map container types.
+  {
+    // ScalarMapContainer_Type derives from our MutableMapping type.
+    ScopedPyObjectPtr containers(PyImport_ImportModule(
+        "google.protobuf.internal.containers"));
+    if (containers == NULL) {
+      return false;
+    }
+
+    ScopedPyObjectPtr mutable_mapping(
+        PyObject_GetAttrString(containers.get(), "MutableMapping"));
+    if (mutable_mapping == NULL) {
+      return false;
+    }
+
+    if (!PyObject_TypeCheck(mutable_mapping.get(), &PyType_Type)) {
+      return false;
+    }
+
+    Py_INCREF(mutable_mapping.get());
+#if PY_MAJOR_VERSION >= 3
+    PyObject* bases = PyTuple_New(1);
+    PyTuple_SET_ITEM(bases, 0, mutable_mapping.get());
+
+    ScalarMapContainer_Type = 
+        PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases);
+    PyModule_AddObject(m, "ScalarMapContainer", ScalarMapContainer_Type);
+#else
+    ScalarMapContainer_Type.tp_base =
+        reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
+
+    if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
+      return false;
+    }
+
+    PyModule_AddObject(m, "ScalarMapContainer",
+                       reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
+#endif
+
+    if (PyType_Ready(&MapIterator_Type) < 0) {
+      return false;
+    }
+
+    PyModule_AddObject(m, "MapIterator",
+                       reinterpret_cast<PyObject*>(&MapIterator_Type));
+
+
+#if PY_MAJOR_VERSION >= 3
+    MessageMapContainer_Type = 
+        PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases);
+    PyModule_AddObject(m, "MessageMapContainer", MessageMapContainer_Type);
+#else
+    Py_INCREF(mutable_mapping.get());
+    MessageMapContainer_Type.tp_base =
+        reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
+
+    if (PyType_Ready(&MessageMapContainer_Type) < 0) {
+      return false;
+    }
+
+    PyModule_AddObject(m, "MessageMapContainer",
+                       reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
+#endif
+  }
+
+  if (PyType_Ready(&ExtensionDict_Type) < 0) {
+    return false;
+  }
+  PyModule_AddObject(
+      m, "ExtensionDict",
+      reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+
+  // Expose the DescriptorPool used to hold all descriptors added from generated
+  // pb2.py files.
+  // PyModule_AddObject steals a reference.
+  Py_INCREF(GetDefaultDescriptorPool());
+  PyModule_AddObject(m, "default_pool",
+                     reinterpret_cast<PyObject*>(GetDefaultDescriptorPool()));
+
+  PyModule_AddObject(m, "DescriptorPool", reinterpret_cast<PyObject*>(
+      &PyDescriptorPool_Type));
+
+  // This implementation provides full Descriptor types, we advertise it so that
+  // descriptor.py can use them in replacement of the Python classes.
+  PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1);
+
+  PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
+      &PyMessageDescriptor_Type));
+  PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
+      &PyFieldDescriptor_Type));
+  PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
+      &PyEnumDescriptor_Type));
+  PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
+      &PyEnumValueDescriptor_Type));
+  PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
+      &PyFileDescriptor_Type));
+  PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
+      &PyOneofDescriptor_Type));
+
+  PyObject* enum_type_wrapper = PyImport_ImportModule(
+      "google.protobuf.internal.enum_type_wrapper");
+  if (enum_type_wrapper == NULL) {
+    return false;
+  }
+  EnumTypeWrapper_class =
+      PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper");
+  Py_DECREF(enum_type_wrapper);
+
+  PyObject* message_module = PyImport_ImportModule(
+      "google.protobuf.message");
+  if (message_module == NULL) {
+    return false;
+  }
+  EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
+  DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
+  PythonMessage_class = PyObject_GetAttrString(message_module, "Message");
+  Py_DECREF(message_module);
+
+  PyObject* pickle_module = PyImport_ImportModule("pickle");
+  if (pickle_module == NULL) {
+    return false;
+  }
+  PickleError_class = PyObject_GetAttrString(pickle_module, "PickleError");
+  Py_DECREF(pickle_module);
+
+  // Override {Get,Mutable}CProtoInsidePyProto.
+  GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl;
+  MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl;
+
+  return true;
+}
+
+}  // namespace python
+}  // namespace protobuf
+
+static PyMethodDef ModuleMethods[] = {
+  {"SetAllowOversizeProtos",
+    (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos,
+    METH_O, "Enable/disable oversize proto parsing."},
+  { NULL, NULL}
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef _module = {
+  PyModuleDef_HEAD_INIT,
+  "_message",
+  google::protobuf::python::module_docstring,
+  -1,
+  ModuleMethods,  /* m_methods */
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+#define INITFUNC PyInit__message
+#define INITFUNC_ERRORVAL NULL
+#else  // Python 2
+#define INITFUNC init_message
+#define INITFUNC_ERRORVAL
+#endif
+
+extern "C" {
+  PyMODINIT_FUNC INITFUNC(void) {
+    PyObject* m;
+#if PY_MAJOR_VERSION >= 3
+    m = PyModule_Create(&_module);
+#else
+    m = Py_InitModule3("_message", ModuleMethods,
+                       google::protobuf::python::module_docstring);
+#endif
+    if (m == NULL) {
+      return INITFUNC_ERRORVAL;
+    }
+
+    if (!google::protobuf::python::InitProto2MessageModule(m)) {
+      Py_DECREF(m);
+      return INITFUNC_ERRORVAL;
+    }
+
+#if PY_MAJOR_VERSION >= 3
+    return m;
+#endif
+  }
+}
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/message.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/message.h
new file mode 100644
index 0000000..3a4bec8
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/message.h
@@ -0,0 +1,361 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+class Reflection;
+class FieldDescriptor;
+class Descriptor;
+class DescriptorPool;
+class MessageFactory;
+
+#ifdef _SHARED_PTR_H
+using std::shared_ptr;
+using ::std::string;
+#else
+using internal::shared_ptr;
+#endif
+
+namespace python {
+
+struct ExtensionDict;
+struct PyDescriptorPool;
+
+typedef struct CMessage {
+  PyObject_HEAD;
+
+  // This is the top-level C++ Message object that owns the whole
+  // proto tree.  Every Python CMessage holds a reference to it in
+  // order to keep it alive as long as there's a Python object that
+  // references any part of the tree.
+  shared_ptr<Message> owner;
+
+  // Weak reference to a parent CMessage object. This is NULL for any top-level
+  // message and is set for any child message (i.e. a child submessage or a
+  // part of a repeated composite field).
+  //
+  // Used to make sure all ancestors are also mutable when first modifying
+  // a child submessage (in other words, turning a default message instance
+  // into a mutable one).
+  //
+  // If a submessage is released (becomes a new top-level message), this field
+  // MUST be set to NULL. The parent may get deallocated and further attempts
+  // to use this pointer will result in a crash.
+  struct CMessage* parent;
+
+  // Pointer to the parent's descriptor that describes this submessage.
+  // Used together with the parent's message when making a default message
+  // instance mutable.
+  // The pointer is owned by the global DescriptorPool.
+  const FieldDescriptor* parent_field_descriptor;
+
+  // Pointer to the C++ Message object for this CMessage.  The
+  // CMessage does not own this pointer.
+  Message* message;
+
+  // Indicates this submessage is pointing to a default instance of a message.
+  // Submessages are always first created as read only messages and are then
+  // made writable, at which point this field is set to false.
+  bool read_only;
+
+  // A reference to a Python dictionary containing CMessage,
+  // RepeatedCompositeContainer, and RepeatedScalarContainer
+  // objects. Used as a cache to make sure we don't have to make a
+  // Python wrapper for the C++ Message objects on every access, or
+  // deal with the synchronization nightmare that could create.
+  PyObject* composite_fields;
+
+  // A reference to the dictionary containing the message's extensions.
+  // Similar to composite_fields, acting as a cache, but also contains the
+  // required extension dict logic.
+  ExtensionDict* extensions;
+} CMessage;
+
+extern PyTypeObject CMessage_Type;
+
+
+// The (meta) type of all Messages classes.
+// It allows us to cache some C++ pointers in the class object itself, they are
+// faster to extract than from the type's dictionary.
+
+struct CMessageClass {
+  // This is how CPython subclasses C structures: the base structure must be
+  // the first member of the object.
+  PyHeapTypeObject super;
+
+  // C++ descriptor of this message.
+  const Descriptor* message_descriptor;
+
+  // Owned reference, used to keep the pointer above alive.
+  PyObject* py_message_descriptor;
+
+  // The Python DescriptorPool used to create the class. It is needed to resolve
+  // fields descriptors, including extensions fields; its C++ MessageFactory is
+  // used to instantiate submessages.
+  // This can be different from DESCRIPTOR.file.pool, in the case of a custom
+  // DescriptorPool which defines new extensions.
+  // We own the reference, because it's important to keep the descriptors and
+  // factory alive.
+  PyDescriptorPool* py_descriptor_pool;
+
+  PyObject* AsPyObject() {
+    return reinterpret_cast<PyObject*>(this);
+  }
+};
+
+
+namespace cmessage {
+
+// Internal function to create a new empty Message Python object, but with empty
+// pointers to the C++ objects.
+// The caller must fill self->message, self->owner and eventually self->parent.
+CMessage* NewEmptyMessage(CMessageClass* type);
+
+// Release a submessage from its proto tree, making it a new top-level messgae.
+// A new message will be created if this is a read-only default instance.
+//
+// Corresponds to reflection api method ReleaseMessage.
+int ReleaseSubMessage(CMessage* self,
+                      const FieldDescriptor* field_descriptor,
+                      CMessage* child_cmessage);
+
+// Retrieves the C++ descriptor of a Python Extension descriptor.
+// On error, return NULL with an exception set.
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
+
+// Initializes a new CMessage instance for a submessage. Only called once per
+// submessage as the result is cached in composite_fields.
+//
+// Corresponds to reflection api method GetMessage.
+PyObject* InternalGetSubMessage(
+    CMessage* self, const FieldDescriptor* field_descriptor);
+
+// Deletes a range of C++ submessages in a repeated field (following a
+// removal in a RepeatedCompositeContainer).
+//
+// Releases messages to the provided cmessage_list if it is not NULL rather
+// than just removing them from the underlying proto. This cmessage_list must
+// have a CMessage for each underlying submessage. The CMessages referred to
+// by slice will be removed from cmessage_list by this function.
+//
+// Corresponds to reflection api method RemoveLast.
+int InternalDeleteRepeatedField(CMessage* self,
+                                const FieldDescriptor* field_descriptor,
+                                PyObject* slice, PyObject* cmessage_list);
+
+// Sets the specified scalar value to the message.
+int InternalSetScalar(CMessage* self,
+                      const FieldDescriptor* field_descriptor,
+                      PyObject* value);
+
+// Sets the specified scalar value to the message.  Requires it is not a Oneof.
+int InternalSetNonOneofScalar(Message* message,
+                              const FieldDescriptor* field_descriptor,
+                              PyObject* arg);
+
+// Retrieves the specified scalar value from the message.
+//
+// Returns a new python reference.
+PyObject* InternalGetScalar(const Message* message,
+                            const FieldDescriptor* field_descriptor);
+
+// Clears the message, removing all contained data. Extension dictionary and
+// submessages are released first if there are remaining external references.
+//
+// Corresponds to message api method Clear.
+PyObject* Clear(CMessage* self);
+
+// Clears the data described by the given descriptor. Used to clear extensions
+// (which don't have names). Extension release is handled by ExtensionDict
+// class, not this function.
+// TODO(anuraag): Try to make this discrepancy in release semantics with
+//                ClearField less confusing.
+//
+// Corresponds to reflection api method ClearField.
+PyObject* ClearFieldByDescriptor(
+    CMessage* self, const FieldDescriptor* descriptor);
+
+// Clears the data for the given field name. The message is released if there
+// are any external references.
+//
+// Corresponds to reflection api method ClearField.
+PyObject* ClearField(CMessage* self, PyObject* arg);
+
+// Checks if the message has the field described by the descriptor. Used for
+// extensions (which have no name).
+//
+// Corresponds to reflection api method HasField
+PyObject* HasFieldByDescriptor(
+    CMessage* self, const FieldDescriptor* field_descriptor);
+
+// Checks if the message has the named field.
+//
+// Corresponds to reflection api method HasField.
+PyObject* HasField(CMessage* self, PyObject* arg);
+
+// Initializes values of fields on a newly constructed message.
+int InitAttributes(CMessage* self, PyObject* kwargs);
+
+PyObject* MergeFrom(CMessage* self, PyObject* arg);
+
+// Retrieves an attribute named 'name' from CMessage 'self'. Returns
+// the attribute value on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* GetAttr(CMessage* self, PyObject* name);
+
+// Set the value of the attribute named 'name', for CMessage 'self',
+// to the value 'value'. Returns -1 on failure.
+int SetAttr(CMessage* self, PyObject* name, PyObject* value);
+
+PyObject* FindInitializationErrors(CMessage* self);
+
+// Set the owner field of self and any children of self, recursively.
+// Used when self is being released and thus has a new owner (the
+// released Message.)
+int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
+
+int AssureWritable(CMessage* self);
+
+// Returns the "best" DescriptorPool for the given message.
+// This is often equivalent to message.DESCRIPTOR.pool, but not always, when
+// the message class was created from a MessageFactory using a custom pool which
+// uses the generated pool as an underlay.
+//
+// The returned pool is suitable for finding fields and building submessages,
+// even in the case of extensions.
+PyDescriptorPool* GetDescriptorPoolForMessage(CMessage* message);
+
+}  // namespace cmessage
+
+
+/* Is 64bit */
+#define IS_64BIT (SIZEOF_LONG == 8)
+
+#define FIELD_IS_REPEATED(field_descriptor)                 \
+    ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
+
+#define GOOGLE_CHECK_GET_INT32(arg, value, err)                        \
+    int32 value;                                            \
+    if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \
+      return err;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_INT64(arg, value, err)                        \
+    int64 value;                                            \
+    if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \
+      return err;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_UINT32(arg, value, err)                       \
+    uint32 value;                                           \
+    if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \
+      return err;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_UINT64(arg, value, err)                       \
+    uint64 value;                                           \
+    if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \
+      return err;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_FLOAT(arg, value, err)                        \
+    float value;                                            \
+    if (!CheckAndGetFloat(arg, &value)) {                   \
+      return err;                                          \
+    }                                                       \
+
+#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err)                       \
+    double value;                                           \
+    if (!CheckAndGetDouble(arg, &value)) {                  \
+      return err;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_BOOL(arg, value, err)                         \
+    bool value;                                             \
+    if (!CheckAndGetBool(arg, &value)) {                    \
+      return err;                                          \
+    }
+
+
+extern PyObject* kPythonZero;
+extern PyObject* kint32min_py;
+extern PyObject* kint32max_py;
+extern PyObject* kuint32max_py;
+extern PyObject* kint64min_py;
+extern PyObject* kint64max_py;
+extern PyObject* kuint64max_py;
+
+#define FULL_MODULE_NAME "google.protobuf.pyext._message"
+
+void FormatTypeError(PyObject* arg, char* expected_types);
+template<class T>
+bool CheckAndGetInteger(
+    PyObject* arg, T* value, PyObject* min, PyObject* max);
+bool CheckAndGetDouble(PyObject* arg, double* value);
+bool CheckAndGetFloat(PyObject* arg, float* value);
+bool CheckAndGetBool(PyObject* arg, bool* value);
+PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor);
+bool CheckAndSetString(
+    PyObject* arg, Message* message,
+    const FieldDescriptor* descriptor,
+    const Reflection* reflection,
+    bool append,
+    int index);
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value);
+
+// Check if the passed field descriptor belongs to the given message.
+// If not, return false and set a Python exception (a KeyError)
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+                                const Message* message);
+
+extern PyObject* PickleError_class;
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/proto2_api_test.proto b/src/third_party/protobuf-3/python/google/protobuf/pyext/proto2_api_test.proto
new file mode 100644
index 0000000..18aecfb
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/proto2_api_test.proto
@@ -0,0 +1,40 @@
+// 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.
+
+syntax = "proto2";
+
+import "google/protobuf/internal/cpp/proto1_api_test.proto";
+
+package google.protobuf.python.internal;
+
+message TestNestedProto1APIMessage {
+  optional int32 a = 1;
+  optional TestMessage.NestedMessage b = 2;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/python.proto b/src/third_party/protobuf-3/python/google/protobuf/pyext/python.proto
new file mode 100644
index 0000000..cce645d
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/python.proto
@@ -0,0 +1,68 @@
+// 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.
+
+// Author: tibell@google.com (Johan Tibell)
+//
+// These message definitions are used to exercises known corner cases
+// in the C++ implementation of the Python API.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+message TestAllTypes {
+  message NestedMessage {
+    optional int32 bb = 1;
+    optional ForeignMessage cc = 2;
+  }
+
+  repeated NestedMessage repeated_nested_message = 1;
+  optional NestedMessage optional_nested_message = 2;
+  optional int32 optional_int32 = 3;
+}
+
+message ForeignMessage {
+  optional int32 c = 1;
+  repeated int32 d = 2;
+}
+
+message TestAllExtensions {
+  extensions 1 to max;
+}
+
+extend TestAllExtensions {
+  optional TestAllTypes.NestedMessage optional_nested_message_extension = 1;
+  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 2;
+}
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/python_protobuf.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/python_protobuf.h
new file mode 100644
index 0000000..beb6e46
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/python_protobuf.h
@@ -0,0 +1,57 @@
+// 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.
+
+// Author: qrczak@google.com (Marcin Kowalczyk)
+//
+// This module exposes the C proto inside the given Python proto, in
+// case the Python proto is implemented with a C proto.
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace python {
+
+// Return the pointer to the C proto inside the given Python proto,
+// or NULL when this is not a Python proto implemented with a C proto.
+const Message* GetCProtoInsidePyProto(PyObject* msg);
+Message* MutableCProtoInsidePyProto(PyObject* msg);
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.cc
new file mode 100644
index 0000000..4f339e7
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -0,0 +1,612 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#include <google/protobuf/pyext/repeated_composite_container.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyInt_Check PyLong_Check
+  #define PyInt_AsLong PyLong_AsLong
+  #define PyInt_FromLong PyLong_FromLong
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+namespace repeated_composite_container {
+
+// TODO(tibell): We might also want to check:
+//   GOOGLE_CHECK_NOTNULL((self)->owner.get());
+#define GOOGLE_CHECK_ATTACHED(self)             \
+  do {                                   \
+    GOOGLE_CHECK_NOTNULL((self)->message);      \
+    GOOGLE_CHECK_NOTNULL((self)->parent_field_descriptor); \
+  } while (0);
+
+#define GOOGLE_CHECK_RELEASED(self)             \
+  do {                                   \
+    GOOGLE_CHECK((self)->owner.get() == NULL);  \
+    GOOGLE_CHECK((self)->message == NULL);      \
+    GOOGLE_CHECK((self)->parent_field_descriptor == NULL); \
+    GOOGLE_CHECK((self)->parent == NULL);       \
+  } while (0);
+
+// ---------------------------------------------------------------------
+// len()
+
+static Py_ssize_t Length(RepeatedCompositeContainer* self) {
+  Message* message = self->message;
+  if (message != NULL) {
+    return message->GetReflection()->FieldSize(*message,
+                                               self->parent_field_descriptor);
+  } else {
+    // The container has been released (i.e. by a call to Clear() or
+    // ClearField() on the parent) and thus there's no message.
+    return PyList_GET_SIZE(self->child_messages);
+  }
+}
+
+// Returns 0 if successful; returns -1 and sets an exception if
+// unsuccessful.
+static int UpdateChildMessages(RepeatedCompositeContainer* self) {
+  if (self->message == NULL)
+    return 0;
+
+  // A MergeFrom on a parent message could have caused extra messages to be
+  // added in the underlying protobuf so add them to our list. They can never
+  // be removed in such a way so there's no need to worry about that.
+  Py_ssize_t message_length = Length(self);
+  Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages);
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
+  for (Py_ssize_t i = child_length; i < message_length; ++i) {
+    const Message& sub_message = reflection->GetRepeatedMessage(
+        *(self->message), self->parent_field_descriptor, i);
+    CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class);
+    ScopedPyObjectPtr py_cmsg(reinterpret_cast<PyObject*>(cmsg));
+    if (cmsg == NULL) {
+      return -1;
+    }
+    cmsg->owner = self->owner;
+    cmsg->message = const_cast<Message*>(&sub_message);
+    cmsg->parent = self->parent;
+    if (PyList_Append(self->child_messages, py_cmsg.get()) < 0) {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+// ---------------------------------------------------------------------
+// add()
+
+static PyObject* AddToAttached(RepeatedCompositeContainer* self,
+                               PyObject* args,
+                               PyObject* kwargs) {
+  GOOGLE_CHECK_ATTACHED(self);
+
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  if (cmessage::AssureWritable(self->parent) == -1)
+    return NULL;
+  Message* message = self->message;
+  Message* sub_message =
+      message->GetReflection()->AddMessage(message,
+                                           self->parent_field_descriptor);
+  CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class);
+  if (cmsg == NULL)
+    return NULL;
+
+  cmsg->owner = self->owner;
+  cmsg->message = sub_message;
+  cmsg->parent = self->parent;
+  if (cmessage::InitAttributes(cmsg, kwargs) < 0) {
+    Py_DECREF(cmsg);
+    return NULL;
+  }
+
+  PyObject* py_cmsg = reinterpret_cast<PyObject*>(cmsg);
+  if (PyList_Append(self->child_messages, py_cmsg) < 0) {
+    Py_DECREF(py_cmsg);
+    return NULL;
+  }
+  return py_cmsg;
+}
+
+static PyObject* AddToReleased(RepeatedCompositeContainer* self,
+                               PyObject* args,
+                               PyObject* kwargs) {
+  GOOGLE_CHECK_RELEASED(self);
+
+  // Create a new Message detached from the rest.
+  PyObject* py_cmsg = PyEval_CallObjectWithKeywords(
+      self->child_message_class->AsPyObject(), NULL, kwargs);
+  if (py_cmsg == NULL)
+    return NULL;
+
+  if (PyList_Append(self->child_messages, py_cmsg) < 0) {
+    Py_DECREF(py_cmsg);
+    return NULL;
+  }
+  return py_cmsg;
+}
+
+PyObject* Add(RepeatedCompositeContainer* self,
+              PyObject* args,
+              PyObject* kwargs) {
+  if (self->message == NULL)
+    return AddToReleased(self, args, kwargs);
+  else
+    return AddToAttached(self, args, kwargs);
+}
+
+// ---------------------------------------------------------------------
+// extend()
+
+PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) {
+  cmessage::AssureWritable(self->parent);
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  ScopedPyObjectPtr iter(PyObject_GetIter(value));
+  if (iter == NULL) {
+    PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+    return NULL;
+  }
+  ScopedPyObjectPtr next;
+  while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
+    if (!PyObject_TypeCheck(next.get(), &CMessage_Type)) {
+      PyErr_SetString(PyExc_TypeError, "Not a cmessage");
+      return NULL;
+    }
+    ScopedPyObjectPtr new_message(Add(self, NULL, NULL));
+    if (new_message == NULL) {
+      return NULL;
+    }
+    CMessage* new_cmessage = reinterpret_cast<CMessage*>(new_message.get());
+    if (ScopedPyObjectPtr(cmessage::MergeFrom(new_cmessage, next.get())) ==
+        NULL) {
+      return NULL;
+    }
+  }
+  if (PyErr_Occurred()) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) {
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  return Extend(self, other);
+}
+
+PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) {
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  // Just forward the call to the subscript-handling function of the
+  // list containing the child messages.
+  return PyObject_GetItem(self->child_messages, slice);
+}
+
+int AssignSubscript(RepeatedCompositeContainer* self,
+                    PyObject* slice,
+                    PyObject* value) {
+  if (UpdateChildMessages(self) < 0) {
+    return -1;
+  }
+  if (value != NULL) {
+    PyErr_SetString(PyExc_TypeError, "does not support assignment");
+    return -1;
+  }
+
+  // Delete from the underlying Message, if any.
+  if (self->parent != NULL) {
+    if (cmessage::InternalDeleteRepeatedField(self->parent,
+                                              self->parent_field_descriptor,
+                                              slice,
+                                              self->child_messages) < 0) {
+      return -1;
+    }
+  } else {
+    Py_ssize_t from;
+    Py_ssize_t to;
+    Py_ssize_t step;
+    Py_ssize_t length = Length(self);
+    Py_ssize_t slicelength;
+    if (PySlice_Check(slice)) {
+#if PY_MAJOR_VERSION >= 3
+      if (PySlice_GetIndicesEx(slice,
+#else
+      if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
+#endif
+                               length, &from, &to, &step, &slicelength) == -1) {
+        return -1;
+      }
+      return PySequence_DelSlice(self->child_messages, from, to);
+    } else if (PyInt_Check(slice) || PyLong_Check(slice)) {
+      from = to = PyLong_AsLong(slice);
+      if (from < 0) {
+        from = to = length + from;
+      }
+      return PySequence_DelItem(self->child_messages, from);
+    }
+  }
+
+  return 0;
+}
+
+static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) {
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  Py_ssize_t index = PySequence_Index(self->child_messages, value);
+  if (index == -1) {
+    return NULL;
+  }
+  ScopedPyObjectPtr py_index(PyLong_FromLong(index));
+  if (AssignSubscript(self, py_index.get(), NULL) < 0) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* RichCompare(RepeatedCompositeContainer* self,
+                             PyObject* other,
+                             int opid) {
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  if (!PyObject_TypeCheck(other, &RepeatedCompositeContainer_Type)) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Can only compare repeated composite fields "
+                    "against other repeated composite fields.");
+    return NULL;
+  }
+  if (opid == Py_EQ || opid == Py_NE) {
+    // TODO(anuraag): Don't make new lists just for this...
+    ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+    if (full_slice == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
+    if (list == NULL) {
+      return NULL;
+    }
+    ScopedPyObjectPtr other_list(
+        Subscript(reinterpret_cast<RepeatedCompositeContainer*>(other),
+                  full_slice.get()));
+    if (other_list == NULL) {
+      return NULL;
+    }
+    return PyObject_RichCompare(list.get(), other_list.get(), opid);
+  } else {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+}
+
+// ---------------------------------------------------------------------
+// sort()
+
+static void ReorderAttached(RepeatedCompositeContainer* self) {
+  Message* message = self->message;
+  const Reflection* reflection = message->GetReflection();
+  const FieldDescriptor* descriptor = self->parent_field_descriptor;
+  const Py_ssize_t length = Length(self);
+
+  // Since Python protobuf objects are never arena-allocated, adding and
+  // removing message pointers to the underlying array is just updating
+  // pointers.
+  for (Py_ssize_t i = 0; i < length; ++i)
+    reflection->ReleaseLast(message, descriptor);
+
+  for (Py_ssize_t i = 0; i < length; ++i) {
+    CMessage* py_cmsg = reinterpret_cast<CMessage*>(
+        PyList_GET_ITEM(self->child_messages, i));
+    reflection->AddAllocatedMessage(message, descriptor, py_cmsg->message);
+  }
+}
+
+// Returns 0 if successful; returns -1 and sets an exception if
+// unsuccessful.
+static int SortPythonMessages(RepeatedCompositeContainer* self,
+                               PyObject* args,
+                               PyObject* kwds) {
+  ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort"));
+  if (m == NULL)
+    return -1;
+  if (PyObject_Call(m.get(), args, kwds) == NULL)
+    return -1;
+  if (self->message != NULL) {
+    ReorderAttached(self);
+  }
+  return 0;
+}
+
+static PyObject* Sort(RepeatedCompositeContainer* self,
+                      PyObject* args,
+                      PyObject* kwds) {
+  // Support the old sort_function argument for backwards
+  // compatibility.
+  if (kwds != NULL) {
+    PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
+    if (sort_func != NULL) {
+      // Must set before deleting as sort_func is a borrowed reference
+      // and kwds might be the only thing keeping it alive.
+      PyDict_SetItemString(kwds, "cmp", sort_func);
+      PyDict_DelItemString(kwds, "sort_function");
+    }
+  }
+
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  if (SortPythonMessages(self, args, kwds) < 0) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+// ---------------------------------------------------------------------
+
+static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) {
+  if (UpdateChildMessages(self) < 0) {
+    return NULL;
+  }
+  Py_ssize_t length = Length(self);
+  if (index < 0) {
+    index = length + index;
+  }
+  PyObject* item = PyList_GetItem(self->child_messages, index);
+  if (item == NULL) {
+    return NULL;
+  }
+  Py_INCREF(item);
+  return item;
+}
+
+static PyObject* Pop(RepeatedCompositeContainer* self,
+                     PyObject* args) {
+  Py_ssize_t index = -1;
+  if (!PyArg_ParseTuple(args, "|n", &index)) {
+    return NULL;
+  }
+  PyObject* item = Item(self, index);
+  if (item == NULL) {
+    PyErr_Format(PyExc_IndexError,
+                 "list index (%zd) out of range",
+                 index);
+    return NULL;
+  }
+  ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index));
+  if (AssignSubscript(self, py_index.get(), NULL) < 0) {
+    return NULL;
+  }
+  return item;
+}
+
+// Release field of parent message and transfer the ownership to target.
+void ReleaseLastTo(CMessage* parent,
+                   const FieldDescriptor* field,
+                   CMessage* target) {
+  GOOGLE_CHECK_NOTNULL(parent);
+  GOOGLE_CHECK_NOTNULL(field);
+  GOOGLE_CHECK_NOTNULL(target);
+
+  shared_ptr<Message> released_message(
+      parent->message->GetReflection()->ReleaseLast(parent->message, field));
+  // TODO(tibell): Deal with proto1.
+
+  target->parent = NULL;
+  target->parent_field_descriptor = NULL;
+  target->message = released_message.get();
+  target->read_only = false;
+  cmessage::SetOwner(target, released_message);
+}
+
+// Called to release a container using
+// ClearField('container_field_name') on the parent.
+int Release(RepeatedCompositeContainer* self) {
+  if (UpdateChildMessages(self) < 0) {
+    PyErr_WriteUnraisable(PyBytes_FromString("Failed to update released "
+                                             "messages"));
+    return -1;
+  }
+
+  Message* message = self->message;
+  const FieldDescriptor* field = self->parent_field_descriptor;
+
+  // The reflection API only lets us release the last message in a
+  // repeated field.  Therefore we iterate through the children
+  // starting with the last one.
+  const Py_ssize_t size = PyList_GET_SIZE(self->child_messages);
+  GOOGLE_DCHECK_EQ(size, message->GetReflection()->FieldSize(*message, field));
+  for (Py_ssize_t i = size - 1; i >= 0; --i) {
+    CMessage* child_cmessage = reinterpret_cast<CMessage*>(
+        PyList_GET_ITEM(self->child_messages, i));
+    ReleaseLastTo(self->parent, field, child_cmessage);
+  }
+
+  // Detach from containing message.
+  self->parent = NULL;
+  self->parent_field_descriptor = NULL;
+  self->message = NULL;
+  self->owner.reset();
+
+  return 0;
+}
+
+int SetOwner(RepeatedCompositeContainer* self,
+             const shared_ptr<Message>& new_owner) {
+  GOOGLE_CHECK_ATTACHED(self);
+
+  self->owner = new_owner;
+  const Py_ssize_t n = PyList_GET_SIZE(self->child_messages);
+  for (Py_ssize_t i = 0; i < n; ++i) {
+    PyObject* msg = PyList_GET_ITEM(self->child_messages, i);
+    if (cmessage::SetOwner(reinterpret_cast<CMessage*>(msg), new_owner) == -1) {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+// The private constructor of RepeatedCompositeContainer objects.
+PyObject *NewContainer(
+    CMessage* parent,
+    const FieldDescriptor* parent_field_descriptor,
+    CMessageClass* concrete_class) {
+  if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+    return NULL;
+  }
+
+  RepeatedCompositeContainer* self =
+      reinterpret_cast<RepeatedCompositeContainer*>(
+          PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0));
+  if (self == NULL) {
+    return NULL;
+  }
+
+  self->message = parent->message;
+  self->parent = parent;
+  self->parent_field_descriptor = parent_field_descriptor;
+  self->owner = parent->owner;
+  Py_INCREF(concrete_class);
+  self->child_message_class = concrete_class;
+  self->child_messages = PyList_New(0);
+
+  return reinterpret_cast<PyObject*>(self);
+}
+
+static void Dealloc(RepeatedCompositeContainer* self) {
+  Py_CLEAR(self->child_messages);
+  Py_CLEAR(self->child_message_class);
+  // TODO(tibell): Do we need to call delete on these objects to make
+  // sure their destructors are called?
+  self->owner.reset();
+
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PySequenceMethods SqMethods = {
+  (lenfunc)Length,        /* sq_length */
+  0, /* sq_concat */
+  0, /* sq_repeat */
+  (ssizeargfunc)Item /* sq_item */
+};
+
+static PyMappingMethods MpMethods = {
+  (lenfunc)Length,               /* mp_length */
+  (binaryfunc)Subscript,      /* mp_subscript */
+  (objobjargproc)AssignSubscript,/* mp_ass_subscript */
+};
+
+static PyMethodDef Methods[] = {
+  { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS,
+    "Adds an object to the repeated container." },
+  { "extend", (PyCFunction) Extend, METH_O,
+    "Adds objects to the repeated container." },
+  { "pop", (PyCFunction)Pop, METH_VARARGS,
+    "Removes an object from the repeated container and returns it." },
+  { "remove", (PyCFunction) Remove, METH_O,
+    "Removes an object from the repeated container." },
+  { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS,
+    "Sorts the repeated container." },
+  { "MergeFrom", (PyCFunction) MergeFrom, METH_O,
+    "Adds objects to the repeated container." },
+  { NULL, NULL }
+};
+
+}  // namespace repeated_composite_container
+
+PyTypeObject RepeatedCompositeContainer_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".RepeatedCompositeContainer",  // tp_name
+  sizeof(RepeatedCompositeContainer),  // tp_basicsize
+  0,                                   //  tp_itemsize
+  (destructor)repeated_composite_container::Dealloc,  //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  0,                                   //  tp_repr
+  0,                                   //  tp_as_number
+  &repeated_composite_container::SqMethods,   //  tp_as_sequence
+  &repeated_composite_container::MpMethods,   //  tp_as_mapping
+  PyObject_HashNotImplemented,         //  tp_hash
+  0,                                   //  tp_call
+  0,                                   //  tp_str
+  0,                                   //  tp_getattro
+  0,                                   //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  //  tp_flags
+  "A Repeated scalar container",       //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  (richcmpfunc)repeated_composite_container::RichCompare,  //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  0,                                   //  tp_iter
+  0,                                   //  tp_iternext
+  repeated_composite_container::Methods,   //  tp_methods
+  0,                                   //  tp_members
+  0,                                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  0,                                   //  tp_init
+};
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.h
new file mode 100644
index 0000000..a7b56b6
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_composite_container.h
@@ -0,0 +1,179 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+namespace google {
+namespace protobuf {
+
+class FieldDescriptor;
+class Message;
+
+#ifdef _SHARED_PTR_H
+using std::shared_ptr;
+#else
+using internal::shared_ptr;
+#endif
+
+namespace python {
+
+struct CMessage;
+struct CMessageClass;
+
+// A RepeatedCompositeContainer can be in one of two states: attached
+// or released.
+//
+// When in the attached state all modifications to the container are
+// done both on the 'message' and on the 'child_messages'
+// list.  In this state all Messages referred to by the children in
+// 'child_messages' are owner by the 'owner'.
+//
+// When in the released state 'message', 'owner', 'parent', and
+// 'parent_field_descriptor' are NULL.
+typedef struct RepeatedCompositeContainer {
+  PyObject_HEAD;
+
+  // This is the top-level C++ Message object that owns the whole
+  // proto tree.  Every Python RepeatedCompositeContainer holds a
+  // reference to it in order to keep it alive as long as there's a
+  // Python object that references any part of the tree.
+  shared_ptr<Message> owner;
+
+  // Weak reference to parent object. May be NULL. Used to make sure
+  // the parent is writable before modifying the
+  // RepeatedCompositeContainer.
+  CMessage* parent;
+
+  // A descriptor used to modify the underlying 'message'.
+  // The pointer is owned by the global DescriptorPool.
+  const FieldDescriptor* parent_field_descriptor;
+
+  // Pointer to the C++ Message that contains this container.  The
+  // RepeatedCompositeContainer does not own this pointer.
+  //
+  // If NULL, this message has been released from its parent (by
+  // calling Clear() or ClearField() on the parent.
+  Message* message;
+
+  // The type used to create new child messages.
+  CMessageClass* child_message_class;
+
+  // A list of child messages.
+  PyObject* child_messages;
+} RepeatedCompositeContainer;
+
+extern PyTypeObject RepeatedCompositeContainer_Type;
+
+namespace repeated_composite_container {
+
+// Builds a RepeatedCompositeContainer object, from a parent message and a
+// field descriptor.
+PyObject *NewContainer(
+    CMessage* parent,
+    const FieldDescriptor* parent_field_descriptor,
+    CMessageClass *child_message_class);
+
+// Appends a new CMessage to the container and returns it.  The
+// CMessage is initialized using the content of kwargs.
+//
+// Returns a new reference if successful; returns NULL and sets an
+// exception if unsuccessful.
+PyObject* Add(RepeatedCompositeContainer* self,
+              PyObject* args,
+              PyObject* kwargs);
+
+// Appends all the CMessages in the input iterator to the container.
+//
+// Returns None if successful; returns NULL and sets an exception if
+// unsuccessful.
+PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value);
+
+// Appends a new message to the container for each message in the
+// input iterator, merging each data element in. Equivalent to extend.
+//
+// Returns None if successful; returns NULL and sets an exception if
+// unsuccessful.
+PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other);
+
+// Accesses messages in the container.
+//
+// Returns a new reference to the message for an integer parameter.
+// Returns a new reference to a list of messages for a slice.
+PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice);
+
+// Deletes items from the container (cannot be used for assignment).
+//
+// Returns 0 on success, -1 on failure.
+int AssignSubscript(RepeatedCompositeContainer* self,
+                    PyObject* slice,
+                    PyObject* value);
+
+// Releases the messages in the container to the given message.
+//
+// Returns 0 on success, -1 on failure.
+int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message);
+
+// Releases the messages in the container to a new message.
+//
+// Returns 0 on success, -1 on failure.
+int Release(RepeatedCompositeContainer* self);
+
+// Returns 0 on success, -1 on failure.
+int SetOwner(RepeatedCompositeContainer* self,
+             const shared_ptr<Message>& new_owner);
+
+// Removes the last element of the repeated message field 'field' on
+// the Message 'parent', and transfers the ownership of the released
+// Message to 'target'.
+//
+// Corresponds to reflection api method ReleaseMessage.
+void ReleaseLastTo(CMessage* parent,
+                   const FieldDescriptor* field,
+                   CMessage* target);
+
+}  // namespace repeated_composite_container
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.cc b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.cc
new file mode 100644
index 0000000..95da85f
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -0,0 +1,812 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#include <google/protobuf/pyext/repeated_scalar_container.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyInt_FromLong PyLong_FromLong
+  #if PY_VERSION_HEX < 0x03030000
+    #error "Python 3.0 - 3.2 are not supported."
+  #else
+  #define PyString_AsString(ob) \
+    (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
+  #endif
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+namespace repeated_scalar_container {
+
+static int InternalAssignRepeatedField(
+    RepeatedScalarContainer* self, PyObject* list) {
+  self->message->GetReflection()->ClearField(self->message,
+                                             self->parent_field_descriptor);
+  for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
+    PyObject* value = PyList_GET_ITEM(list, i);
+    if (ScopedPyObjectPtr(Append(self, value)) == NULL) {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+static Py_ssize_t Len(RepeatedScalarContainer* self) {
+  Message* message = self->message;
+  return message->GetReflection()->FieldSize(*message,
+                                             self->parent_field_descriptor);
+}
+
+static int AssignItem(RepeatedScalarContainer* self,
+                      Py_ssize_t index,
+                      PyObject* arg) {
+  cmessage::AssureWritable(self->parent);
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
+
+  const Reflection* reflection = message->GetReflection();
+  int field_size = reflection->FieldSize(*message, field_descriptor);
+  if (index < 0) {
+    index = field_size + index;
+  }
+  if (index < 0 || index >= field_size) {
+    PyErr_Format(PyExc_IndexError,
+                 "list assignment index (%d) out of range",
+                 static_cast<int>(index));
+    return -1;
+  }
+
+  if (arg == NULL) {
+    ScopedPyObjectPtr py_index(PyLong_FromLong(index));
+    return cmessage::InternalDeleteRepeatedField(self->parent, field_descriptor,
+                                                 py_index.get(), NULL);
+  }
+
+  if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) {
+    PyErr_SetString(PyExc_TypeError, "Value must be scalar");
+    return -1;
+  }
+
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(arg, value, -1);
+      reflection->SetRepeatedInt32(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(arg, value, -1);
+      reflection->SetRepeatedInt64(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(arg, value, -1);
+      reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(arg, value, -1);
+      reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
+      reflection->SetRepeatedFloat(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
+      reflection->SetRepeatedDouble(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(arg, value, -1);
+      reflection->SetRepeatedBool(message, field_descriptor, index, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      if (!CheckAndSetString(
+          arg, message, field_descriptor, reflection, false, index)) {
+        return -1;
+      }
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(arg, value, -1);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->SetRepeatedEnumValue(message, field_descriptor, index,
+                                         value);
+      } else {
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->SetRepeatedEnum(message, field_descriptor, index,
+                                      enum_value);
+        } else {
+          ScopedPyObjectPtr s(PyObject_Str(arg));
+          if (s != NULL) {
+            PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+                         PyString_AsString(s.get()));
+          }
+          return -1;
+        }
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Adding value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+      return -1;
+  }
+  return 0;
+}
+
+static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
+  const Reflection* reflection = message->GetReflection();
+
+  int field_size = reflection->FieldSize(*message, field_descriptor);
+  if (index < 0) {
+    index = field_size + index;
+  }
+  if (index < 0 || index >= field_size) {
+    PyErr_Format(PyExc_IndexError,
+                 "list index (%zd) out of range",
+                 index);
+    return NULL;
+  }
+
+  PyObject* result = NULL;
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = reflection->GetRepeatedInt32(
+          *message, field_descriptor, index);
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = reflection->GetRepeatedInt64(
+          *message, field_descriptor, index);
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = reflection->GetRepeatedUInt32(
+          *message, field_descriptor, index);
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = reflection->GetRepeatedUInt64(
+          *message, field_descriptor, index);
+      result = PyLong_FromUnsignedLongLong(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = reflection->GetRepeatedFloat(
+          *message, field_descriptor, index);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = reflection->GetRepeatedDouble(
+          *message, field_descriptor, index);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = reflection->GetRepeatedBool(
+          *message, field_descriptor, index);
+      result = PyBool_FromLong(value ? 1 : 0);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      const EnumValueDescriptor* enum_value =
+          message->GetReflection()->GetRepeatedEnum(
+              *message, field_descriptor, index);
+      result = PyInt_FromLong(enum_value->number());
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string value = reflection->GetRepeatedString(
+          *message, field_descriptor, index);
+      result = ToStringObject(field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_MESSAGE: {
+      PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>(
+          &CMessage_Type), NULL);
+      if (py_cmsg == NULL) {
+        return NULL;
+      }
+      CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
+      const Message& msg = reflection->GetRepeatedMessage(
+          *message, field_descriptor, index);
+      cmsg->owner = self->owner;
+      cmsg->parent = self->parent;
+      cmsg->message = const_cast<Message*>(&msg);
+      cmsg->read_only = false;
+      result = reinterpret_cast<PyObject*>(py_cmsg);
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError,
+          "Getting value from a repeated field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  return result;
+}
+
+static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
+  Py_ssize_t from;
+  Py_ssize_t to;
+  Py_ssize_t step;
+  Py_ssize_t length;
+  Py_ssize_t slicelength;
+  bool return_list = false;
+#if PY_MAJOR_VERSION < 3
+  if (PyInt_Check(slice)) {
+    from = to = PyInt_AsLong(slice);
+  } else  // NOLINT
+#endif
+  if (PyLong_Check(slice)) {
+    from = to = PyLong_AsLong(slice);
+  } else if (PySlice_Check(slice)) {
+    length = Len(self);
+#if PY_MAJOR_VERSION >= 3
+    if (PySlice_GetIndicesEx(slice,
+#else
+    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
+#endif
+                             length, &from, &to, &step, &slicelength) == -1) {
+      return NULL;
+    }
+    return_list = true;
+  } else {
+    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
+    return NULL;
+  }
+
+  if (!return_list) {
+    return Item(self, from);
+  }
+
+  PyObject* list = PyList_New(0);
+  if (list == NULL) {
+    return NULL;
+  }
+  if (from <= to) {
+    if (step < 0) {
+      return list;
+    }
+    for (Py_ssize_t index = from; index < to; index += step) {
+      if (index < 0 || index >= length) {
+        break;
+      }
+      ScopedPyObjectPtr s(Item(self, index));
+      PyList_Append(list, s.get());
+    }
+  } else {
+    if (step > 0) {
+      return list;
+    }
+    for (Py_ssize_t index = from; index > to; index += step) {
+      if (index < 0 || index >= length) {
+        break;
+      }
+      ScopedPyObjectPtr s(Item(self, index));
+      PyList_Append(list, s.get());
+    }
+  }
+  return list;
+}
+
+PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
+  cmessage::AssureWritable(self->parent);
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
+
+  const Reflection* reflection = message->GetReflection();
+  switch (field_descriptor->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(item, value, NULL);
+      reflection->AddInt32(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(item, value, NULL);
+      reflection->AddInt64(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(item, value, NULL);
+      reflection->AddUInt32(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(item, value, NULL);
+      reflection->AddUInt64(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
+      reflection->AddFloat(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
+      reflection->AddDouble(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(item, value, NULL);
+      reflection->AddBool(message, field_descriptor, value);
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_STRING: {
+      if (!CheckAndSetString(
+          item, message, field_descriptor, reflection, true, -1)) {
+        return NULL;
+      }
+      break;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(item, value, NULL);
+      if (reflection->SupportsUnknownEnumValues()) {
+        reflection->AddEnumValue(message, field_descriptor, value);
+      } else {
+        const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+        const EnumValueDescriptor* enum_value =
+            enum_descriptor->FindValueByNumber(value);
+        if (enum_value != NULL) {
+          reflection->AddEnum(message, field_descriptor, enum_value);
+        } else {
+          ScopedPyObjectPtr s(PyObject_Str(item));
+          if (s != NULL) {
+            PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+                         PyString_AsString(s.get()));
+          }
+          return NULL;
+        }
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Adding value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+      return NULL;
+  }
+
+  Py_RETURN_NONE;
+}
+
+static int AssSubscript(RepeatedScalarContainer* self,
+                        PyObject* slice,
+                        PyObject* value) {
+  Py_ssize_t from;
+  Py_ssize_t to;
+  Py_ssize_t step;
+  Py_ssize_t length;
+  Py_ssize_t slicelength;
+  bool create_list = false;
+
+  cmessage::AssureWritable(self->parent);
+  Message* message = self->message;
+  const FieldDescriptor* field_descriptor =
+      self->parent_field_descriptor;
+
+#if PY_MAJOR_VERSION < 3
+  if (PyInt_Check(slice)) {
+    from = to = PyInt_AsLong(slice);
+  } else
+#endif
+  if (PyLong_Check(slice)) {
+    from = to = PyLong_AsLong(slice);
+  } else if (PySlice_Check(slice)) {
+    const Reflection* reflection = message->GetReflection();
+    length = reflection->FieldSize(*message, field_descriptor);
+#if PY_MAJOR_VERSION >= 3
+    if (PySlice_GetIndicesEx(slice,
+#else
+    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
+#endif
+                             length, &from, &to, &step, &slicelength) == -1) {
+      return -1;
+    }
+    create_list = true;
+  } else {
+    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
+    return -1;
+  }
+
+  if (value == NULL) {
+    return cmessage::InternalDeleteRepeatedField(
+        self->parent, field_descriptor, slice, NULL);
+  }
+
+  if (!create_list) {
+    return AssignItem(self, from, value);
+  }
+
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return -1;
+  }
+  ScopedPyObjectPtr new_list(Subscript(self, full_slice.get()));
+  if (new_list == NULL) {
+    return -1;
+  }
+  if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) {
+    return -1;
+  }
+
+  return InternalAssignRepeatedField(self, new_list.get());
+}
+
+PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
+  cmessage::AssureWritable(self->parent);
+
+  // TODO(ptucker): Deprecate this behavior. b/18413862
+  if (value == Py_None) {
+    Py_RETURN_NONE;
+  }
+  if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) {
+    Py_RETURN_NONE;
+  }
+
+  ScopedPyObjectPtr iter(PyObject_GetIter(value));
+  if (iter == NULL) {
+    PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+    return NULL;
+  }
+  ScopedPyObjectPtr next;
+  while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
+    if (ScopedPyObjectPtr(Append(self, next.get())) == NULL) {
+      return NULL;
+    }
+  }
+  if (PyErr_Occurred()) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) {
+  Py_ssize_t index;
+  PyObject* value;
+  if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
+    return NULL;
+  }
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  ScopedPyObjectPtr new_list(Subscript(self, full_slice.get()));
+  if (PyList_Insert(new_list.get(), index, value) < 0) {
+    return NULL;
+  }
+  int ret = InternalAssignRepeatedField(self, new_list.get());
+  if (ret < 0) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) {
+  Py_ssize_t match_index = -1;
+  for (Py_ssize_t i = 0; i < Len(self); ++i) {
+    ScopedPyObjectPtr elem(Item(self, i));
+    if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) {
+      match_index = i;
+      break;
+    }
+  }
+  if (match_index == -1) {
+    PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
+    return NULL;
+  }
+  if (AssignItem(self, match_index, NULL) < 0) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* RichCompare(RepeatedScalarContainer* self,
+                             PyObject* other,
+                             int opid) {
+  if (opid != Py_EQ && opid != Py_NE) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+
+  // Copy the contents of this repeated scalar container, and other if it is
+  // also a repeated scalar container, into Python lists so we can delegate
+  // to the list's compare method.
+
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return NULL;
+  }
+
+  ScopedPyObjectPtr other_list_deleter;
+  if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
+    other_list_deleter.reset(Subscript(
+        reinterpret_cast<RepeatedScalarContainer*>(other), full_slice.get()));
+    other = other_list_deleter.get();
+  }
+
+  ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
+  if (list == NULL) {
+    return NULL;
+  }
+  return PyObject_RichCompare(list.get(), other, opid);
+}
+
+PyObject* Reduce(RepeatedScalarContainer* unused_self) {
+  PyErr_Format(
+      PickleError_class,
+      "can't pickle repeated message fields, convert to list first");
+  return NULL;
+}
+
+static PyObject* Sort(RepeatedScalarContainer* self,
+                      PyObject* args,
+                      PyObject* kwds) {
+  // Support the old sort_function argument for backwards
+  // compatibility.
+  if (kwds != NULL) {
+    PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
+    if (sort_func != NULL) {
+      // Must set before deleting as sort_func is a borrowed reference
+      // and kwds might be the only thing keeping it alive.
+      if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1)
+        return NULL;
+      if (PyDict_DelItemString(kwds, "sort_function") == -1)
+        return NULL;
+    }
+  }
+
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
+  if (list == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort"));
+  if (m == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds));
+  if (res == NULL) {
+    return NULL;
+  }
+  int ret = InternalAssignRepeatedField(self, list.get());
+  if (ret < 0) {
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* Pop(RepeatedScalarContainer* self,
+                     PyObject* args) {
+  Py_ssize_t index = -1;
+  if (!PyArg_ParseTuple(args, "|n", &index)) {
+    return NULL;
+  }
+  PyObject* item = Item(self, index);
+  if (item == NULL) {
+    PyErr_Format(PyExc_IndexError,
+                 "list index (%zd) out of range",
+                 index);
+    return NULL;
+  }
+  if (AssignItem(self, index, NULL) < 0) {
+    return NULL;
+  }
+  return item;
+}
+
+// The private constructor of RepeatedScalarContainer objects.
+PyObject *NewContainer(
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
+  if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+    return NULL;
+  }
+
+  RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
+      PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
+  if (self == NULL) {
+    return NULL;
+  }
+
+  self->message = parent->message;
+  self->parent = parent;
+  self->parent_field_descriptor = parent_field_descriptor;
+  self->owner = parent->owner;
+
+  return reinterpret_cast<PyObject*>(self);
+}
+
+// Initializes the underlying Message object of "to" so it becomes a new parent
+// repeated scalar, and copies all the values from "from" to it. A child scalar
+// container can be released by passing it as both from and to (e.g. making it
+// the recipient of the new parent message and copying the values from itself).
+static int InitializeAndCopyToParentContainer(
+    RepeatedScalarContainer* from,
+    RepeatedScalarContainer* to) {
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return -1;
+  }
+  ScopedPyObjectPtr values(Subscript(from, full_slice.get()));
+  if (values == NULL) {
+    return -1;
+  }
+  Message* new_message = from->message->New();
+  to->parent = NULL;
+  to->parent_field_descriptor = from->parent_field_descriptor;
+  to->message = new_message;
+  to->owner.reset(new_message);
+  if (InternalAssignRepeatedField(to, values.get()) < 0) {
+    return -1;
+  }
+  return 0;
+}
+
+int Release(RepeatedScalarContainer* self) {
+  return InitializeAndCopyToParentContainer(self, self);
+}
+
+PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) {
+  RepeatedScalarContainer* clone = reinterpret_cast<RepeatedScalarContainer*>(
+      PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
+  if (clone == NULL) {
+    return NULL;
+  }
+
+  if (InitializeAndCopyToParentContainer(self, clone) < 0) {
+    Py_DECREF(clone);
+    return NULL;
+  }
+  return reinterpret_cast<PyObject*>(clone);
+}
+
+static void Dealloc(RepeatedScalarContainer* self) {
+  self->owner.reset();
+  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+void SetOwner(RepeatedScalarContainer* self,
+              const shared_ptr<Message>& new_owner) {
+  self->owner = new_owner;
+}
+
+static PySequenceMethods SqMethods = {
+  (lenfunc)Len,           /* sq_length */
+  0, /* sq_concat */
+  0, /* sq_repeat */
+  (ssizeargfunc)Item, /* sq_item */
+  0, /* sq_slice */
+  (ssizeobjargproc)AssignItem /* sq_ass_item */
+};
+
+static PyMappingMethods MpMethods = {
+  (lenfunc)Len,               /* mp_length */
+  (binaryfunc)Subscript,      /* mp_subscript */
+  (objobjargproc)AssSubscript, /* mp_ass_subscript */
+};
+
+static PyMethodDef Methods[] = {
+  { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+    "Makes a deep copy of the class." },
+  { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+    "Outputs picklable representation of the repeated field." },
+  { "append", (PyCFunction)Append, METH_O,
+    "Appends an object to the repeated container." },
+  { "extend", (PyCFunction)Extend, METH_O,
+    "Appends objects to the repeated container." },
+  { "insert", (PyCFunction)Insert, METH_VARARGS,
+    "Appends objects to the repeated container." },
+  { "pop", (PyCFunction)Pop, METH_VARARGS,
+    "Removes an object from the repeated container and returns it." },
+  { "remove", (PyCFunction)Remove, METH_O,
+    "Removes an object from the repeated container." },
+  { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
+    "Sorts the repeated container."},
+  { NULL, NULL }
+};
+
+}  // namespace repeated_scalar_container
+
+PyTypeObject RepeatedScalarContainer_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  FULL_MODULE_NAME ".RepeatedScalarContainer",  // tp_name
+  sizeof(RepeatedScalarContainer),     // tp_basicsize
+  0,                                   //  tp_itemsize
+  (destructor)repeated_scalar_container::Dealloc,  //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  0,                                   //  tp_repr
+  0,                                   //  tp_as_number
+  &repeated_scalar_container::SqMethods,   //  tp_as_sequence
+  &repeated_scalar_container::MpMethods,   //  tp_as_mapping
+  PyObject_HashNotImplemented,         //  tp_hash
+  0,                                   //  tp_call
+  0,                                   //  tp_str
+  0,                                   //  tp_getattro
+  0,                                   //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  //  tp_flags
+  "A Repeated scalar container",       //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  (richcmpfunc)repeated_scalar_container::RichCompare,  //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  0,                                   //  tp_iter
+  0,                                   //  tp_iternext
+  repeated_scalar_container::Methods,      //  tp_methods
+  0,                                   //  tp_members
+  0,                                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  0,                                   //  tp_init
+};
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.h
new file mode 100644
index 0000000..555e621
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/repeated_scalar_container.h
@@ -0,0 +1,122 @@
+// 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.
+
+// Author: anuraag@google.com (Anuraag Agrawal)
+// Author: tibell@google.com (Johan Tibell)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+#ifdef _SHARED_PTR_H
+using std::shared_ptr;
+#else
+using internal::shared_ptr;
+#endif
+
+namespace python {
+
+struct CMessage;
+
+typedef struct RepeatedScalarContainer {
+  PyObject_HEAD;
+
+  // This is the top-level C++ Message object that owns the whole
+  // proto tree.  Every Python RepeatedScalarContainer holds a
+  // reference to it in order to keep it alive as long as there's a
+  // Python object that references any part of the tree.
+  shared_ptr<Message> owner;
+
+  // Pointer to the C++ Message that contains this container.  The
+  // RepeatedScalarContainer does not own this pointer.
+  Message* message;
+
+  // Weak reference to a parent CMessage object (i.e. may be NULL.)
+  //
+  // Used to make sure all ancestors are also mutable when first
+  // modifying the container.
+  CMessage* parent;
+
+  // Pointer to the parent's descriptor that describes this
+  // field.  Used together with the parent's message when making a
+  // default message instance mutable.
+  // The pointer is owned by the global DescriptorPool.
+  const FieldDescriptor* parent_field_descriptor;
+} RepeatedScalarContainer;
+
+extern PyTypeObject RepeatedScalarContainer_Type;
+
+namespace repeated_scalar_container {
+
+// Builds a RepeatedScalarContainer object, from a parent message and a
+// field descriptor.
+extern PyObject *NewContainer(
+    CMessage* parent, const FieldDescriptor* parent_field_descriptor);
+
+// Appends the scalar 'item' to the end of the container 'self'.
+//
+// Returns None if successful; returns NULL and sets an exception if
+// unsuccessful.
+PyObject* Append(RepeatedScalarContainer* self, PyObject* item);
+
+// Releases the messages in the container to a new message.
+//
+// Returns 0 on success, -1 on failure.
+int Release(RepeatedScalarContainer* self);
+
+// Appends all the elements in the input iterator to the container.
+//
+// Returns None if successful; returns NULL and sets an exception if
+// unsuccessful.
+PyObject* Extend(RepeatedScalarContainer* self, PyObject* value);
+
+// Set the owner field of self and any children of self.
+void SetOwner(RepeatedScalarContainer* self,
+              const shared_ptr<Message>& new_owner);
+
+}  // namespace repeated_scalar_container
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/src/third_party/protobuf-3/python/google/protobuf/pyext/scoped_pyobject_ptr.h
new file mode 100644
index 0000000..a128cd4
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -0,0 +1,96 @@
+// 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.
+
+// Author: tibell@google.com (Johan Tibell)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
+
+#include <google/protobuf/stubs/common.h>
+
+#include <Python.h>
+
+namespace google {
+class ScopedPyObjectPtr {
+ public:
+  // Constructor.  Defaults to initializing with NULL.
+  // There is no way to create an uninitialized ScopedPyObjectPtr.
+  explicit ScopedPyObjectPtr(PyObject* p = NULL) : ptr_(p) { }
+
+  // Destructor.  If there is a PyObject object, delete it.
+  ~ScopedPyObjectPtr() {
+    Py_XDECREF(ptr_);
+  }
+
+  // Reset.  Deletes the current owned object, if any.
+  // Then takes ownership of a new object, if given.
+  // This function must be called with a reference that you own.
+  //   this->reset(this->get()) is wrong!
+  //   this->reset(this->release()) is OK.
+  PyObject* reset(PyObject* p = NULL) {
+    Py_XDECREF(ptr_);
+    ptr_ = p;
+    return ptr_;
+  }
+
+  // Releases ownership of the object.
+  // The caller now owns the returned reference.
+  PyObject* release() {
+    PyObject* p = ptr_;
+    ptr_ = NULL;
+    return p;
+  }
+
+  PyObject* operator->() const  {
+    assert(ptr_ != NULL);
+    return ptr_;
+  }
+
+  PyObject* get() const { return ptr_; }
+
+  Py_ssize_t refcnt() const { return Py_REFCNT(ptr_); }
+
+  void inc() const { Py_INCREF(ptr_); }
+
+  // Comparison operators.
+  // These return whether a ScopedPyObjectPtr and a raw pointer
+  // refer to the same object, not just to two different but equal
+  // objects.
+  bool operator==(const PyObject* p) const { return ptr_ == p; }
+  bool operator!=(const PyObject* p) const { return ptr_ != p; }
+
+ private:
+  PyObject* ptr_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPyObjectPtr);
+};
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
diff --git a/src/third_party/protobuf-3/python/google/protobuf/reflection.py b/src/third_party/protobuf-3/python/google/protobuf/reflection.py
new file mode 100755
index 0000000..0c75726
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/reflection.py
@@ -0,0 +1,120 @@
+# 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.
+
+# This code is meant to work on Python 2.4 and above only.
+
+"""Contains a metaclass and helper functions used to create
+protocol message classes from Descriptor objects at runtime.
+
+Recall that a metaclass is the "type" of a class.
+(A class is to a metaclass what an instance is to a class.)
+
+In this case, we use the GeneratedProtocolMessageType metaclass
+to inject all the useful functionality into the classes
+output by the protocol compiler at compile-time.
+
+The upshot of all this is that the real implementation
+details for ALL pure-Python protocol buffers are *here in
+this file*.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+
+from google.protobuf.internal import api_implementation
+from google.protobuf import message
+
+
+if api_implementation.Type() == 'cpp':
+  from google.protobuf.pyext import cpp_message as message_impl
+else:
+  from google.protobuf.internal import python_message as message_impl
+
+# The type of all Message classes.
+# Part of the public interface.
+#
+# Used by generated files, but clients can also use it at runtime:
+#   mydescriptor = pool.FindDescriptor(.....)
+#   class MyProtoClass(Message):
+#     __metaclass__ = GeneratedProtocolMessageType
+#     DESCRIPTOR = mydescriptor
+GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType
+
+
+def ParseMessage(descriptor, byte_str):
+  """Generate a new Message instance from this Descriptor and a byte string.
+
+  Args:
+    descriptor: Protobuf Descriptor object
+    byte_str: Serialized protocol buffer byte string
+
+  Returns:
+    Newly created protobuf Message object.
+  """
+  result_class = MakeClass(descriptor)
+  new_msg = result_class()
+  new_msg.ParseFromString(byte_str)
+  return new_msg
+
+
+def MakeClass(descriptor):
+  """Construct a class object for a protobuf described by descriptor.
+
+  Composite descriptors are handled by defining the new class as a member of the
+  parent class, recursing as deep as necessary.
+  This is the dynamic equivalent to:
+
+  class Parent(message.Message):
+    __metaclass__ = GeneratedProtocolMessageType
+    DESCRIPTOR = descriptor
+    class Child(message.Message):
+      __metaclass__ = GeneratedProtocolMessageType
+      DESCRIPTOR = descriptor.nested_types[0]
+
+  Sample usage:
+    file_descriptor = descriptor_pb2.FileDescriptorProto()
+    file_descriptor.ParseFromString(proto2_string)
+    msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0])
+    msg_class = reflection.MakeClass(msg_descriptor)
+    msg = msg_class()
+
+  Args:
+    descriptor: A descriptor.Descriptor object describing the protobuf.
+  Returns:
+    The Message class object described by the descriptor.
+  """
+  attributes = {}
+  for name, nested_type in descriptor.nested_types_by_name.items():
+    attributes[name] = MakeClass(nested_type)
+
+  attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor
+
+  return GeneratedProtocolMessageType(str(descriptor.name), (message.Message,),
+                                      attributes)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/service.py b/src/third_party/protobuf-3/python/google/protobuf/service.py
new file mode 100755
index 0000000..9e00de7
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/service.py
@@ -0,0 +1,226 @@
+# 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.
+
+"""DEPRECATED:  Declares the RPC service interfaces.
+
+This module declares the abstract interfaces underlying proto2 RPC
+services.  These are intended to be independent of any particular RPC
+implementation, so that proto2 services can be used on top of a variety
+of implementations.  Starting with version 2.3.0, RPC implementations should
+not try to build on these, but should instead provide code generator plugins
+which generate code specific to the particular RPC implementation.  This way
+the generated code can be more appropriate for the implementation in use
+and can avoid unnecessary layers of indirection.
+"""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+
+class RpcException(Exception):
+  """Exception raised on failed blocking RPC method call."""
+  pass
+
+
+class Service(object):
+
+  """Abstract base interface for protocol-buffer-based RPC services.
+
+  Services themselves are abstract classes (implemented either by servers or as
+  stubs), but they subclass this base interface. The methods of this
+  interface can be used to call the methods of the service without knowing
+  its exact type at compile time (analogous to the Message interface).
+  """
+
+  def GetDescriptor():
+    """Retrieves this service's descriptor."""
+    raise NotImplementedError
+
+  def CallMethod(self, method_descriptor, rpc_controller,
+                 request, done):
+    """Calls a method of the service specified by method_descriptor.
+
+    If "done" is None then the call is blocking and the response
+    message will be returned directly.  Otherwise the call is asynchronous
+    and "done" will later be called with the response value.
+
+    In the blocking case, RpcException will be raised on error.
+
+    Preconditions:
+    * method_descriptor.service == GetDescriptor
+    * request is of the exact same classes as returned by
+      GetRequestClass(method).
+    * After the call has started, the request must not be modified.
+    * "rpc_controller" is of the correct type for the RPC implementation being
+      used by this Service.  For stubs, the "correct type" depends on the
+      RpcChannel which the stub is using.
+
+    Postconditions:
+    * "done" will be called when the method is complete.  This may be
+      before CallMethod() returns or it may be at some point in the future.
+    * If the RPC failed, the response value passed to "done" will be None.
+      Further details about the failure can be found by querying the
+      RpcController.
+    """
+    raise NotImplementedError
+
+  def GetRequestClass(self, method_descriptor):
+    """Returns the class of the request message for the specified method.
+
+    CallMethod() requires that the request is of a particular subclass of
+    Message. GetRequestClass() gets the default instance of this required
+    type.
+
+    Example:
+      method = service.GetDescriptor().FindMethodByName("Foo")
+      request = stub.GetRequestClass(method)()
+      request.ParseFromString(input)
+      service.CallMethod(method, request, callback)
+    """
+    raise NotImplementedError
+
+  def GetResponseClass(self, method_descriptor):
+    """Returns the class of the response message for the specified method.
+
+    This method isn't really needed, as the RpcChannel's CallMethod constructs
+    the response protocol message. It's provided anyway in case it is useful
+    for the caller to know the response type in advance.
+    """
+    raise NotImplementedError
+
+
+class RpcController(object):
+
+  """An RpcController mediates a single method call.
+
+  The primary purpose of the controller is to provide a way to manipulate
+  settings specific to the RPC implementation and to find out about RPC-level
+  errors. The methods provided by the RpcController interface are intended
+  to be a "least common denominator" set of features which we expect all
+  implementations to support.  Specific implementations may provide more
+  advanced features (e.g. deadline propagation).
+  """
+
+  # Client-side methods below
+
+  def Reset(self):
+    """Resets the RpcController to its initial state.
+
+    After the RpcController has been reset, it may be reused in
+    a new call. Must not be called while an RPC is in progress.
+    """
+    raise NotImplementedError
+
+  def Failed(self):
+    """Returns true if the call failed.
+
+    After a call has finished, returns true if the call failed.  The possible
+    reasons for failure depend on the RPC implementation.  Failed() must not
+    be called before a call has finished.  If Failed() returns true, the
+    contents of the response message are undefined.
+    """
+    raise NotImplementedError
+
+  def ErrorText(self):
+    """If Failed is true, returns a human-readable description of the error."""
+    raise NotImplementedError
+
+  def StartCancel(self):
+    """Initiate cancellation.
+
+    Advises the RPC system that the caller desires that the RPC call be
+    canceled.  The RPC system may cancel it immediately, may wait awhile and
+    then cancel it, or may not even cancel the call at all.  If the call is
+    canceled, the "done" callback will still be called and the RpcController
+    will indicate that the call failed at that time.
+    """
+    raise NotImplementedError
+
+  # Server-side methods below
+
+  def SetFailed(self, reason):
+    """Sets a failure reason.
+
+    Causes Failed() to return true on the client side.  "reason" will be
+    incorporated into the message returned by ErrorText().  If you find
+    you need to return machine-readable information about failures, you
+    should incorporate it into your response protocol buffer and should
+    NOT call SetFailed().
+    """
+    raise NotImplementedError
+
+  def IsCanceled(self):
+    """Checks if the client cancelled the RPC.
+
+    If true, indicates that the client canceled the RPC, so the server may
+    as well give up on replying to it.  The server should still call the
+    final "done" callback.
+    """
+    raise NotImplementedError
+
+  def NotifyOnCancel(self, callback):
+    """Sets a callback to invoke on cancel.
+
+    Asks that the given callback be called when the RPC is canceled.  The
+    callback will always be called exactly once.  If the RPC completes without
+    being canceled, the callback will be called after completion.  If the RPC
+    has already been canceled when NotifyOnCancel() is called, the callback
+    will be called immediately.
+
+    NotifyOnCancel() must be called no more than once per request.
+    """
+    raise NotImplementedError
+
+
+class RpcChannel(object):
+
+  """Abstract interface for an RPC channel.
+
+  An RpcChannel represents a communication line to a service which can be used
+  to call that service's methods.  The service may be running on another
+  machine. Normally, you should not use an RpcChannel directly, but instead
+  construct a stub {@link Service} wrapping it.  Example:
+
+  Example:
+    RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234")
+    RpcController controller = rpcImpl.Controller()
+    MyService service = MyService_Stub(channel)
+    service.MyMethod(controller, request, callback)
+  """
+
+  def CallMethod(self, method_descriptor, rpc_controller,
+                 request, response_class, done):
+    """Calls the method identified by the descriptor.
+
+    Call the given method of the remote service.  The signature of this
+    procedure looks the same as Service.CallMethod(), but the requirements
+    are less strict in one important way:  the request object doesn't have to
+    be of any specific class as long as its descriptor is method.input_type.
+    """
+    raise NotImplementedError
diff --git a/src/third_party/protobuf-3/python/google/protobuf/service_reflection.py b/src/third_party/protobuf-3/python/google/protobuf/service_reflection.py
new file mode 100755
index 0000000..1c3636a
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/service_reflection.py
@@ -0,0 +1,284 @@
+# 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.
+
+"""Contains metaclasses used to create protocol service and service stub
+classes from ServiceDescriptor objects at runtime.
+
+The GeneratedServiceType and GeneratedServiceStubType metaclasses are used to
+inject all useful functionality into the classes output by the protocol
+compiler at compile-time.
+"""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+
+class GeneratedServiceType(type):
+
+  """Metaclass for service classes created at runtime from ServiceDescriptors.
+
+  Implementations for all methods described in the Service class are added here
+  by this class. We also create properties to allow getting/setting all fields
+  in the protocol message.
+
+  The protocol compiler currently uses this metaclass to create protocol service
+  classes at runtime. Clients can also manually create their own classes at
+  runtime, as in this example:
+
+  mydescriptor = ServiceDescriptor(.....)
+  class MyProtoService(service.Service):
+    __metaclass__ = GeneratedServiceType
+    DESCRIPTOR = mydescriptor
+  myservice_instance = MyProtoService()
+  ...
+  """
+
+  _DESCRIPTOR_KEY = 'DESCRIPTOR'
+
+  def __init__(cls, name, bases, dictionary):
+    """Creates a message service class.
+
+    Args:
+      name: Name of the class (ignored, but required by the metaclass
+        protocol).
+      bases: Base classes of the class being constructed.
+      dictionary: The class dictionary of the class being constructed.
+        dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
+        describing this protocol service type.
+    """
+    # Don't do anything if this class doesn't have a descriptor. This happens
+    # when a service class is subclassed.
+    if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary:
+      return
+    descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
+    service_builder = _ServiceBuilder(descriptor)
+    service_builder.BuildService(cls)
+
+
+class GeneratedServiceStubType(GeneratedServiceType):
+
+  """Metaclass for service stubs created at runtime from ServiceDescriptors.
+
+  This class has similar responsibilities as GeneratedServiceType, except that
+  it creates the service stub classes.
+  """
+
+  _DESCRIPTOR_KEY = 'DESCRIPTOR'
+
+  def __init__(cls, name, bases, dictionary):
+    """Creates a message service stub class.
+
+    Args:
+      name: Name of the class (ignored, here).
+      bases: Base classes of the class being constructed.
+      dictionary: The class dictionary of the class being constructed.
+        dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
+        describing this protocol service type.
+    """
+    super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
+    # Don't do anything if this class doesn't have a descriptor. This happens
+    # when a service stub is subclassed.
+    if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
+      return
+    descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
+    service_stub_builder = _ServiceStubBuilder(descriptor)
+    service_stub_builder.BuildServiceStub(cls)
+
+
+class _ServiceBuilder(object):
+
+  """This class constructs a protocol service class using a service descriptor.
+
+  Given a service descriptor, this class constructs a class that represents
+  the specified service descriptor. One service builder instance constructs
+  exactly one service class. That means all instances of that class share the
+  same builder.
+  """
+
+  def __init__(self, service_descriptor):
+    """Initializes an instance of the service class builder.
+
+    Args:
+      service_descriptor: ServiceDescriptor to use when constructing the
+        service class.
+    """
+    self.descriptor = service_descriptor
+
+  def BuildService(self, cls):
+    """Constructs the service class.
+
+    Args:
+      cls: The class that will be constructed.
+    """
+
+    # CallMethod needs to operate with an instance of the Service class. This
+    # internal wrapper function exists only to be able to pass the service
+    # instance to the method that does the real CallMethod work.
+    def _WrapCallMethod(srvc, method_descriptor,
+                        rpc_controller, request, callback):
+      return self._CallMethod(srvc, method_descriptor,
+                       rpc_controller, request, callback)
+    self.cls = cls
+    cls.CallMethod = _WrapCallMethod
+    cls.GetDescriptor = staticmethod(lambda: self.descriptor)
+    cls.GetDescriptor.__doc__ = "Returns the service descriptor."
+    cls.GetRequestClass = self._GetRequestClass
+    cls.GetResponseClass = self._GetResponseClass
+    for method in self.descriptor.methods:
+      setattr(cls, method.name, self._GenerateNonImplementedMethod(method))
+
+  def _CallMethod(self, srvc, method_descriptor,
+                  rpc_controller, request, callback):
+    """Calls the method described by a given method descriptor.
+
+    Args:
+      srvc: Instance of the service for which this method is called.
+      method_descriptor: Descriptor that represent the method to call.
+      rpc_controller: RPC controller to use for this method's execution.
+      request: Request protocol message.
+      callback: A callback to invoke after the method has completed.
+    """
+    if method_descriptor.containing_service != self.descriptor:
+      raise RuntimeError(
+          'CallMethod() given method descriptor for wrong service type.')
+    method = getattr(srvc, method_descriptor.name)
+    return method(rpc_controller, request, callback)
+
+  def _GetRequestClass(self, method_descriptor):
+    """Returns the class of the request protocol message.
+
+    Args:
+      method_descriptor: Descriptor of the method for which to return the
+        request protocol message class.
+
+    Returns:
+      A class that represents the input protocol message of the specified
+      method.
+    """
+    if method_descriptor.containing_service != self.descriptor:
+      raise RuntimeError(
+          'GetRequestClass() given method descriptor for wrong service type.')
+    return method_descriptor.input_type._concrete_class
+
+  def _GetResponseClass(self, method_descriptor):
+    """Returns the class of the response protocol message.
+
+    Args:
+      method_descriptor: Descriptor of the method for which to return the
+        response protocol message class.
+
+    Returns:
+      A class that represents the output protocol message of the specified
+      method.
+    """
+    if method_descriptor.containing_service != self.descriptor:
+      raise RuntimeError(
+          'GetResponseClass() given method descriptor for wrong service type.')
+    return method_descriptor.output_type._concrete_class
+
+  def _GenerateNonImplementedMethod(self, method):
+    """Generates and returns a method that can be set for a service methods.
+
+    Args:
+      method: Descriptor of the service method for which a method is to be
+        generated.
+
+    Returns:
+      A method that can be added to the service class.
+    """
+    return lambda inst, rpc_controller, request, callback: (
+        self._NonImplementedMethod(method.name, rpc_controller, callback))
+
+  def _NonImplementedMethod(self, method_name, rpc_controller, callback):
+    """The body of all methods in the generated service class.
+
+    Args:
+      method_name: Name of the method being executed.
+      rpc_controller: RPC controller used to execute this method.
+      callback: A callback which will be invoked when the method finishes.
+    """
+    rpc_controller.SetFailed('Method %s not implemented.' % method_name)
+    callback(None)
+
+
+class _ServiceStubBuilder(object):
+
+  """Constructs a protocol service stub class using a service descriptor.
+
+  Given a service descriptor, this class constructs a suitable stub class.
+  A stub is just a type-safe wrapper around an RpcChannel which emulates a
+  local implementation of the service.
+
+  One service stub builder instance constructs exactly one class. It means all
+  instances of that class share the same service stub builder.
+  """
+
+  def __init__(self, service_descriptor):
+    """Initializes an instance of the service stub class builder.
+
+    Args:
+      service_descriptor: ServiceDescriptor to use when constructing the
+        stub class.
+    """
+    self.descriptor = service_descriptor
+
+  def BuildServiceStub(self, cls):
+    """Constructs the stub class.
+
+    Args:
+      cls: The class that will be constructed.
+    """
+
+    def _ServiceStubInit(stub, rpc_channel):
+      stub.rpc_channel = rpc_channel
+    self.cls = cls
+    cls.__init__ = _ServiceStubInit
+    for method in self.descriptor.methods:
+      setattr(cls, method.name, self._GenerateStubMethod(method))
+
+  def _GenerateStubMethod(self, method):
+    return (lambda inst, rpc_controller, request, callback=None:
+        self._StubMethod(inst, method, rpc_controller, request, callback))
+
+  def _StubMethod(self, stub, method_descriptor,
+                  rpc_controller, request, callback):
+    """The body of all service methods in the generated stub class.
+
+    Args:
+      stub: Stub instance.
+      method_descriptor: Descriptor of the invoked method.
+      rpc_controller: Rpc controller to execute the method.
+      request: Request protocol message.
+      callback: A callback to execute when the method finishes.
+    Returns:
+      Response message (in case of blocking call).
+    """
+    return stub.rpc_channel.CallMethod(
+        method_descriptor, rpc_controller, request,
+        method_descriptor.output_type._concrete_class, callback)
diff --git a/src/third_party/protobuf-3/python/google/protobuf/symbol_database.py b/src/third_party/protobuf-3/python/google/protobuf/symbol_database.py
new file mode 100644
index 0000000..87760f2
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/symbol_database.py
@@ -0,0 +1,185 @@
+# 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.
+
+"""A database of Python protocol buffer generated symbols.
+
+SymbolDatabase makes it easy to create new instances of a registered type, given
+only the type's protocol buffer symbol name. Once all symbols are registered,
+they can be accessed using either the MessageFactory interface which
+SymbolDatabase exposes, or the DescriptorPool interface of the underlying
+pool.
+
+Example usage:
+
+  db = symbol_database.SymbolDatabase()
+
+  # Register symbols of interest, from one or multiple files.
+  db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR)
+  db.RegisterMessage(my_proto_pb2.MyMessage)
+  db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR)
+
+  # The database can be used as a MessageFactory, to generate types based on
+  # their name:
+  types = db.GetMessages(['my_proto.proto'])
+  my_message_instance = types['MyMessage']()
+
+  # The database's underlying descriptor pool can be queried, so it's not
+  # necessary to know a type's filename to be able to generate it:
+  filename = db.pool.FindFileContainingSymbol('MyMessage')
+  my_message_instance = db.GetMessages([filename])['MyMessage']()
+
+  # This functionality is also provided directly via a convenience method:
+  my_message_instance = db.GetSymbol('MyMessage')()
+"""
+
+
+from google.protobuf import descriptor_pool
+
+
+class SymbolDatabase(object):
+  """A database of Python generated symbols.
+
+  SymbolDatabase also models message_factory.MessageFactory.
+
+  The symbol database can be used to keep a global registry of all protocol
+  buffer types used within a program.
+  """
+
+  def __init__(self, pool=None):
+    """Constructor."""
+
+    self._symbols = {}
+    self._symbols_by_file = {}
+    self.pool = pool or descriptor_pool.Default()
+
+  def RegisterMessage(self, message):
+    """Registers the given message type in the local database.
+
+    Args:
+      message: a message.Message, to be registered.
+
+    Returns:
+      The provided message.
+    """
+
+    desc = message.DESCRIPTOR
+    self._symbols[desc.full_name] = message
+    if desc.file.name not in self._symbols_by_file:
+      self._symbols_by_file[desc.file.name] = {}
+    self._symbols_by_file[desc.file.name][desc.full_name] = message
+    self.pool.AddDescriptor(desc)
+    return message
+
+  def RegisterEnumDescriptor(self, enum_descriptor):
+    """Registers the given enum descriptor in the local database.
+
+    Args:
+      enum_descriptor: a descriptor.EnumDescriptor.
+
+    Returns:
+      The provided descriptor.
+    """
+    self.pool.AddEnumDescriptor(enum_descriptor)
+    return enum_descriptor
+
+  def RegisterFileDescriptor(self, file_descriptor):
+    """Registers the given file descriptor in the local database.
+
+    Args:
+      file_descriptor: a descriptor.FileDescriptor.
+
+    Returns:
+      The provided descriptor.
+    """
+    self.pool.AddFileDescriptor(file_descriptor)
+
+  def GetSymbol(self, symbol):
+    """Tries to find a symbol in the local database.
+
+    Currently, this method only returns message.Message instances, however, if
+    may be extended in future to support other symbol types.
+
+    Args:
+      symbol: A str, a protocol buffer symbol.
+
+    Returns:
+      A Python class corresponding to the symbol.
+
+    Raises:
+      KeyError: if the symbol could not be found.
+    """
+
+    return self._symbols[symbol]
+
+  def GetPrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Passing a descriptor with a fully qualified name matching a previous
+    invocation will cause the same class to be returned.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+
+    return self.GetSymbol(descriptor.full_name)
+
+  def GetMessages(self, files):
+    """Gets all the messages from a specified file.
+
+    This will find and resolve dependencies, failing if they are not registered
+    in the symbol database.
+
+
+    Args:
+      files: The file names to extract messages from.
+
+    Returns:
+      A dictionary mapping proto names to the message classes. This will include
+      any dependent messages as well as any messages defined in the same file as
+      a specified message.
+
+    Raises:
+      KeyError: if a file could not be found.
+    """
+
+    result = {}
+    for f in files:
+      result.update(self._symbols_by_file[f])
+    return result
+
+_DEFAULT = SymbolDatabase(pool=descriptor_pool.Default())
+
+
+def Default():
+  """Returns the default SymbolDatabase."""
+  return _DEFAULT
diff --git a/src/third_party/protobuf-3/python/google/protobuf/text_encoding.py b/src/third_party/protobuf-3/python/google/protobuf/text_encoding.py
new file mode 100644
index 0000000..9899563
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/text_encoding.py
@@ -0,0 +1,107 @@
+# 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.
+
+"""Encoding related utilities."""
+import re
+
+import six
+
+# Lookup table for utf8
+_cescape_utf8_to_str = [chr(i) for i in range(0, 256)]
+_cescape_utf8_to_str[9] = r'\t'  # optional escape
+_cescape_utf8_to_str[10] = r'\n'  # optional escape
+_cescape_utf8_to_str[13] = r'\r'  # optional escape
+_cescape_utf8_to_str[39] = r"\'"  # optional escape
+
+_cescape_utf8_to_str[34] = r'\"'  # necessary escape
+_cescape_utf8_to_str[92] = r'\\'  # necessary escape
+
+# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32)
+_cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] +
+                        [chr(i) for i in range(32, 127)] +
+                        [r'\%03o' % i for i in range(127, 256)])
+_cescape_byte_to_str[9] = r'\t'  # optional escape
+_cescape_byte_to_str[10] = r'\n'  # optional escape
+_cescape_byte_to_str[13] = r'\r'  # optional escape
+_cescape_byte_to_str[39] = r"\'"  # optional escape
+
+_cescape_byte_to_str[34] = r'\"'  # necessary escape
+_cescape_byte_to_str[92] = r'\\'  # necessary escape
+
+
+def CEscape(text, as_utf8):
+  """Escape a bytes string for use in an ascii protocol buffer.
+
+  text.encode('string_escape') does not seem to satisfy our needs as it
+  encodes unprintable characters using two-digit hex escapes whereas our
+  C++ unescaping function allows hex escapes to be any length.  So,
+  "\0011".encode('string_escape') ends up being "\\x011", which will be
+  decoded in C++ as a single-character string with char code 0x11.
+
+  Args:
+    text: A byte string to be escaped
+    as_utf8: Specifies if result should be returned in UTF-8 encoding
+  Returns:
+    Escaped string
+  """
+  # PY3 hack: make Ord work for str and bytes:
+  # //platforms/networking/data uses unicode here, hence basestring.
+  Ord = ord if isinstance(text, six.string_types) else lambda x: x
+  if as_utf8:
+    return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text)
+  return ''.join(_cescape_byte_to_str[Ord(c)] for c in text)
+
+
+_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])')
+_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] +
+                           [r'\%03o' % i for i in range(127, 256)])
+
+
+def CUnescape(text):
+  """Unescape a text string with C-style escape sequences to UTF-8 bytes."""
+
+  def ReplaceHex(m):
+    # Only replace the match if the number of leading back slashes is odd. i.e.
+    # the slash itself is not escaped.
+    if len(m.group(1)) & 1:
+      return m.group(1) + 'x0' + m.group(2)
+    return m.group(0)
+
+  # This is required because the 'string_escape' encoding doesn't
+  # allow single-digit hex escapes (like '\xf').
+  result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
+
+  if str is bytes:  # PY2
+    return result.decode('string_escape')
+  result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result)
+  return (result.encode('ascii')  # Make it bytes to allow decode.
+          .decode('unicode_escape')
+          # Make it bytes again to return the proper type.
+          .encode('raw_unicode_escape'))
diff --git a/src/third_party/protobuf-3/python/google/protobuf/text_format.py b/src/third_party/protobuf-3/python/google/protobuf/text_format.py
new file mode 100755
index 0000000..6f1e3c8
--- /dev/null
+++ b/src/third_party/protobuf-3/python/google/protobuf/text_format.py
@@ -0,0 +1,1219 @@
+# 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.
+
+"""Contains routines for printing protocol messages in text format.
+
+Simple usage example:
+
+  # Create a proto object and serialize it to a text proto string.
+  message = my_proto_pb2.MyMessage(foo='bar')
+  text_proto = text_format.MessageToString(message)
+
+  # Parse a text proto string.
+  message = text_format.Parse(text_proto, my_proto_pb2.MyMessage())
+"""
+
+__author__ = 'kenton@google.com (Kenton Varda)'
+
+import io
+import re
+
+import six
+
+if six.PY3:
+  long = int
+
+from google.protobuf.internal import type_checkers
+from google.protobuf import descriptor
+from google.protobuf import text_encoding
+
+__all__ = ['MessageToString', 'PrintMessage', 'PrintField',
+           'PrintFieldValue', 'Merge']
+
+
+_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(),
+                     type_checkers.Int32ValueChecker(),
+                     type_checkers.Uint64ValueChecker(),
+                     type_checkers.Int64ValueChecker())
+_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE)
+_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE)
+_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT,
+                          descriptor.FieldDescriptor.CPPTYPE_DOUBLE])
+_QUOTES = frozenset(("'", '"'))
+
+
+class Error(Exception):
+  """Top-level module error for text_format."""
+
+
+class ParseError(Error):
+  """Thrown in case of text parsing error."""
+
+
+class TextWriter(object):
+  def __init__(self, as_utf8):
+    if six.PY2:
+      self._writer = io.BytesIO()
+    else:
+      self._writer = io.StringIO()
+
+  def write(self, val):
+    if six.PY2:
+      if isinstance(val, six.text_type):
+        val = val.encode('utf-8')
+    return self._writer.write(val)
+
+  def close(self):
+    return self._writer.close()
+
+  def getvalue(self):
+    return self._writer.getvalue()
+
+
+def MessageToString(message, as_utf8=False, as_one_line=False,
+                    pointy_brackets=False, use_index_order=False,
+                    float_format=None, use_field_number=False):
+  """Convert protobuf message to text format.
+
+  Floating point values can be formatted compactly with 15 digits of
+  precision (which is the most that IEEE 754 "double" can guarantee)
+  using float_format='.15g'. To ensure that converting to text and back to a
+  proto will result in an identical value, float_format='.17g' should be used.
+
+  Args:
+    message: The protocol buffers message.
+    as_utf8: Produce text output in UTF8 format.
+    as_one_line: Don't introduce newlines between fields.
+    pointy_brackets: If True, use angle brackets instead of curly braces for
+      nesting.
+    use_index_order: If True, print fields of a proto message using the order
+      defined in source code instead of the field number. By default, use the
+      field number order.
+    float_format: If set, use this to specify floating point number formatting
+      (per the "Format Specification Mini-Language"); otherwise, str() is used.
+    use_field_number: If True, print field numbers instead of names.
+
+  Returns:
+    A string of the text formatted protocol buffer message.
+  """
+  out = TextWriter(as_utf8)
+  printer = _Printer(out, 0, as_utf8, as_one_line,
+                     pointy_brackets, use_index_order, float_format,
+                     use_field_number)
+  printer.PrintMessage(message)
+  result = out.getvalue()
+  out.close()
+  if as_one_line:
+    return result.rstrip()
+  return result
+
+
+def _IsMapEntry(field):
+  return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
+          field.message_type.has_options and
+          field.message_type.GetOptions().map_entry)
+
+
+def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
+                 pointy_brackets=False, use_index_order=False,
+                 float_format=None, use_field_number=False):
+  printer = _Printer(out, indent, as_utf8, as_one_line,
+                     pointy_brackets, use_index_order, float_format,
+                     use_field_number)
+  printer.PrintMessage(message)
+
+
+def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
+               pointy_brackets=False, use_index_order=False, float_format=None):
+  """Print a single field name/value pair."""
+  printer = _Printer(out, indent, as_utf8, as_one_line,
+                     pointy_brackets, use_index_order, float_format)
+  printer.PrintField(field, value)
+
+
+def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
+                    as_one_line=False, pointy_brackets=False,
+                    use_index_order=False,
+                    float_format=None):
+  """Print a single field value (not including name)."""
+  printer = _Printer(out, indent, as_utf8, as_one_line,
+                     pointy_brackets, use_index_order, float_format)
+  printer.PrintFieldValue(field, value)
+
+
+class _Printer(object):
+  """Text format printer for protocol message."""
+
+  def __init__(self, out, indent=0, as_utf8=False, as_one_line=False,
+               pointy_brackets=False, use_index_order=False, float_format=None,
+               use_field_number=False):
+    """Initialize the Printer.
+
+    Floating point values can be formatted compactly with 15 digits of
+    precision (which is the most that IEEE 754 "double" can guarantee)
+    using float_format='.15g'. To ensure that converting to text and back to a
+    proto will result in an identical value, float_format='.17g' should be used.
+
+    Args:
+      out: To record the text format result.
+      indent: The indent level for pretty print.
+      as_utf8: Produce text output in UTF8 format.
+      as_one_line: Don't introduce newlines between fields.
+      pointy_brackets: If True, use angle brackets instead of curly braces for
+        nesting.
+      use_index_order: If True, print fields of a proto message using the order
+        defined in source code instead of the field number. By default, use the
+        field number order.
+      float_format: If set, use this to specify floating point number formatting
+        (per the "Format Specification Mini-Language"); otherwise, str() is
+        used.
+      use_field_number: If True, print field numbers instead of names.
+    """
+    self.out = out
+    self.indent = indent
+    self.as_utf8 = as_utf8
+    self.as_one_line = as_one_line
+    self.pointy_brackets = pointy_brackets
+    self.use_index_order = use_index_order
+    self.float_format = float_format
+    self.use_field_number = use_field_number
+
+  def PrintMessage(self, message):
+    """Convert protobuf message to text format.
+
+    Args:
+      message: The protocol buffers message.
+    """
+    fields = message.ListFields()
+    if self.use_index_order:
+      fields.sort(key=lambda x: x[0].index)
+    for field, value in fields:
+      if _IsMapEntry(field):
+        for key in sorted(value):
+          # This is slow for maps with submessage entires because it copies the
+          # entire tree.  Unfortunately this would take significant refactoring
+          # of this file to work around.
+          #
+          # TODO(haberman): refactor and optimize if this becomes an issue.
+          entry_submsg = field.message_type._concrete_class(
+              key=key, value=value[key])
+          self.PrintField(field, entry_submsg)
+      elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        for element in value:
+          self.PrintField(field, element)
+      else:
+        self.PrintField(field, value)
+
+  def PrintField(self, field, value):
+    """Print a single field name/value pair."""
+    out = self.out
+    out.write(' ' * self.indent)
+    if self.use_field_number:
+      out.write(str(field.number))
+    else:
+      if field.is_extension:
+        out.write('[')
+        if (field.containing_type.GetOptions().message_set_wire_format and
+            field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
+            field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL):
+          out.write(field.message_type.full_name)
+        else:
+          out.write(field.full_name)
+        out.write(']')
+      elif field.type == descriptor.FieldDescriptor.TYPE_GROUP:
+        # For groups, use the capitalized name.
+        out.write(field.message_type.name)
+      else:
+        out.write(field.name)
+
+    if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+      # The colon is optional in this case, but our cross-language golden files
+      # don't include it.
+      out.write(': ')
+
+    self.PrintFieldValue(field, value)
+    if self.as_one_line:
+      out.write(' ')
+    else:
+      out.write('\n')
+
+  def PrintFieldValue(self, field, value):
+    """Print a single field value (not including name).
+
+    For repeated fields, the value should be a single element.
+
+    Args:
+      field: The descriptor of the field to be printed.
+      value: The value of the field.
+    """
+    out = self.out
+    if self.pointy_brackets:
+      openb = '<'
+      closeb = '>'
+    else:
+      openb = '{'
+      closeb = '}'
+
+    if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+      if self.as_one_line:
+        out.write(' %s ' % openb)
+        self.PrintMessage(value)
+        out.write(closeb)
+      else:
+        out.write(' %s\n' % openb)
+        self.indent += 2
+        self.PrintMessage(value)
+        self.indent -= 2
+        out.write(' ' * self.indent + closeb)
+    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
+      enum_value = field.enum_type.values_by_number.get(value, None)
+      if enum_value is not None:
+        out.write(enum_value.name)
+      else:
+        out.write(str(value))
+    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
+      out.write('\"')
+      if isinstance(value, six.text_type):
+        out_value = value.encode('utf-8')
+      else:
+        out_value = value
+      if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
+        # We need to escape non-UTF8 chars in TYPE_BYTES field.
+        out_as_utf8 = False
+      else:
+        out_as_utf8 = self.as_utf8
+      out.write(text_encoding.CEscape(out_value, out_as_utf8))
+      out.write('\"')
+    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
+      if value:
+        out.write('true')
+      else:
+        out.write('false')
+    elif field.cpp_type in _FLOAT_TYPES and self.float_format is not None:
+      out.write('{1:{0}}'.format(self.float_format, value))
+    else:
+      out.write(str(value))
+
+
+def Parse(text, message,
+          allow_unknown_extension=False, allow_field_number=False):
+  """Parses an text representation of a protocol message into a message.
+
+  Args:
+    text: Message text representation.
+    message: A protocol buffer message to merge into.
+    allow_unknown_extension: if True, skip over missing extensions and keep
+      parsing
+    allow_field_number: if True, both field number and field name are allowed.
+
+  Returns:
+    The same message passed as argument.
+
+  Raises:
+    ParseError: On text parsing problems.
+  """
+  if not isinstance(text, str):
+    text = text.decode('utf-8')
+  return ParseLines(text.split('\n'), message, allow_unknown_extension,
+                    allow_field_number)
+
+
+def Merge(text, message, allow_unknown_extension=False,
+          allow_field_number=False):
+  """Parses an text representation of a protocol message into a message.
+
+  Like Parse(), but allows repeated values for a non-repeated field, and uses
+  the last one.
+
+  Args:
+    text: Message text representation.
+    message: A protocol buffer message to merge into.
+    allow_unknown_extension: if True, skip over missing extensions and keep
+      parsing
+    allow_field_number: if True, both field number and field name are allowed.
+
+  Returns:
+    The same message passed as argument.
+
+  Raises:
+    ParseError: On text parsing problems.
+  """
+  return MergeLines(text.split('\n'), message, allow_unknown_extension,
+                    allow_field_number)
+
+
+def ParseLines(lines, message, allow_unknown_extension=False,
+               allow_field_number=False):
+  """Parses an text representation of a protocol message into a message.
+
+  Args:
+    lines: An iterable of lines of a message's text representation.
+    message: A protocol buffer message to merge into.
+    allow_unknown_extension: if True, skip over missing extensions and keep
+      parsing
+    allow_field_number: if True, both field number and field name are allowed.
+
+  Returns:
+    The same message passed as argument.
+
+  Raises:
+    ParseError: On text parsing problems.
+  """
+  parser = _Parser(allow_unknown_extension, allow_field_number)
+  return parser.ParseLines(lines, message)
+
+
+def MergeLines(lines, message, allow_unknown_extension=False,
+               allow_field_number=False):
+  """Parses an text representation of a protocol message into a message.
+
+  Args:
+    lines: An iterable of lines of a message's text representation.
+    message: A protocol buffer message to merge into.
+    allow_unknown_extension: if True, skip over missing extensions and keep
+      parsing
+    allow_field_number: if True, both field number and field name are allowed.
+
+  Returns:
+    The same message passed as argument.
+
+  Raises:
+    ParseError: On text parsing problems.
+  """
+  parser = _Parser(allow_unknown_extension, allow_field_number)
+  return parser.MergeLines(lines, message)
+
+
+class _Parser(object):
+  """Text format parser for protocol message."""
+
+  def __init__(self, allow_unknown_extension=False, allow_field_number=False):
+    self.allow_unknown_extension = allow_unknown_extension
+    self.allow_field_number = allow_field_number
+
+  def ParseFromString(self, text, message):
+    """Parses an text representation of a protocol message into a message."""
+    if not isinstance(text, str):
+      text = text.decode('utf-8')
+    return self.ParseLines(text.split('\n'), message)
+
+  def ParseLines(self, lines, message):
+    """Parses an text representation of a protocol message into a message."""
+    self._allow_multiple_scalars = False
+    self._ParseOrMerge(lines, message)
+    return message
+
+  def MergeFromString(self, text, message):
+    """Merges an text representation of a protocol message into a message."""
+    return self._MergeLines(text.split('\n'), message)
+
+  def MergeLines(self, lines, message):
+    """Merges an text representation of a protocol message into a message."""
+    self._allow_multiple_scalars = True
+    self._ParseOrMerge(lines, message)
+    return message
+
+  def _ParseOrMerge(self, lines, message):
+    """Converts an text representation of a protocol message into a message.
+
+    Args:
+      lines: Lines of a message's text representation.
+      message: A protocol buffer message to merge into.
+
+    Raises:
+      ParseError: On text parsing problems.
+    """
+    tokenizer = _Tokenizer(lines)
+    while not tokenizer.AtEnd():
+      self._MergeField(tokenizer, message)
+
+  def _MergeField(self, tokenizer, message):
+    """Merges a single protocol message field into a message.
+
+    Args:
+      tokenizer: A tokenizer to parse the field name and values.
+      message: A protocol message to record the data.
+
+    Raises:
+      ParseError: In case of text parsing problems.
+    """
+    message_descriptor = message.DESCRIPTOR
+    if (hasattr(message_descriptor, 'syntax') and
+        message_descriptor.syntax == 'proto3'):
+      # Proto3 doesn't represent presence so we can't test if multiple
+      # scalars have occurred.  We have to allow them.
+      self._allow_multiple_scalars = True
+    if tokenizer.TryConsume('['):
+      name = [tokenizer.ConsumeIdentifier()]
+      while tokenizer.TryConsume('.'):
+        name.append(tokenizer.ConsumeIdentifier())
+      name = '.'.join(name)
+
+      if not message_descriptor.is_extendable:
+        raise tokenizer.ParseErrorPreviousToken(
+            'Message type "%s" does not have extensions.' %
+            message_descriptor.full_name)
+      # pylint: disable=protected-access
+      field = message.Extensions._FindExtensionByName(name)
+      # pylint: enable=protected-access
+      if not field:
+        if self.allow_unknown_extension:
+          field = None
+        else:
+          raise tokenizer.ParseErrorPreviousToken(
+              'Extension "%s" not registered.' % name)
+      elif message_descriptor != field.containing_type:
+        raise tokenizer.ParseErrorPreviousToken(
+            'Extension "%s" does not extend message type "%s".' % (
+                name, message_descriptor.full_name))
+
+      tokenizer.Consume(']')
+
+    else:
+      name = tokenizer.ConsumeIdentifier()
+      if self.allow_field_number and name.isdigit():
+        number = ParseInteger(name, True, True)
+        field = message_descriptor.fields_by_number.get(number, None)
+        if not field and message_descriptor.is_extendable:
+          field = message.Extensions._FindExtensionByNumber(number)
+      else:
+        field = message_descriptor.fields_by_name.get(name, None)
+
+        # Group names are expected to be capitalized as they appear in the
+        # .proto file, which actually matches their type names, not their field
+        # names.
+        if not field:
+          field = message_descriptor.fields_by_name.get(name.lower(), None)
+          if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP:
+            field = None
+
+        if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and
+            field.message_type.name != name):
+          field = None
+
+      if not field:
+        raise tokenizer.ParseErrorPreviousToken(
+            'Message type "%s" has no field named "%s".' % (
+                message_descriptor.full_name, name))
+
+    if field:
+      if not self._allow_multiple_scalars and field.containing_oneof:
+        # Check if there's a different field set in this oneof.
+        # Note that we ignore the case if the same field was set before, and we
+        # apply _allow_multiple_scalars to non-scalar fields as well.
+        which_oneof = message.WhichOneof(field.containing_oneof.name)
+        if which_oneof is not None and which_oneof != field.name:
+          raise tokenizer.ParseErrorPreviousToken(
+              'Field "%s" is specified along with field "%s", another member '
+              'of oneof "%s" for message type "%s".' % (
+                  field.name, which_oneof, field.containing_oneof.name,
+                  message_descriptor.full_name))
+
+      if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+        tokenizer.TryConsume(':')
+        merger = self._MergeMessageField
+      else:
+        tokenizer.Consume(':')
+        merger = self._MergeScalarField
+
+      if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED
+          and tokenizer.TryConsume('[')):
+        # Short repeated format, e.g. "foo: [1, 2, 3]"
+        while True:
+          merger(tokenizer, message, field)
+          if tokenizer.TryConsume(']'): break
+          tokenizer.Consume(',')
+
+      else:
+        merger(tokenizer, message, field)
+
+    else:  # Proto field is unknown.
+      assert self.allow_unknown_extension
+      _SkipFieldContents(tokenizer)
+
+    # For historical reasons, fields may optionally be separated by commas or
+    # semicolons.
+    if not tokenizer.TryConsume(','):
+      tokenizer.TryConsume(';')
+
+  def _MergeMessageField(self, tokenizer, message, field):
+    """Merges a single scalar field into a message.
+
+    Args:
+      tokenizer: A tokenizer to parse the field value.
+      message: The message of which field is a member.
+      field: The descriptor of the field to be merged.
+
+    Raises:
+      ParseError: In case of text parsing problems.
+    """
+    is_map_entry = _IsMapEntry(field)
+
+    if tokenizer.TryConsume('<'):
+      end_token = '>'
+    else:
+      tokenizer.Consume('{')
+      end_token = '}'
+
+    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+      if field.is_extension:
+        sub_message = message.Extensions[field].add()
+      elif is_map_entry:
+        # pylint: disable=protected-access
+        sub_message = field.message_type._concrete_class()
+      else:
+        sub_message = getattr(message, field.name).add()
+    else:
+      if field.is_extension:
+        sub_message = message.Extensions[field]
+      else:
+        sub_message = getattr(message, field.name)
+      sub_message.SetInParent()
+
+    while not tokenizer.TryConsume(end_token):
+      if tokenizer.AtEnd():
+        raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,))
+      self._MergeField(tokenizer, sub_message)
+
+    if is_map_entry:
+      value_cpptype = field.message_type.fields_by_name['value'].cpp_type
+      if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+        value = getattr(message, field.name)[sub_message.key]
+        value.MergeFrom(sub_message.value)
+      else:
+        getattr(message, field.name)[sub_message.key] = sub_message.value
+
+  def _MergeScalarField(self, tokenizer, message, field):
+    """Merges a single scalar field into a message.
+
+    Args:
+      tokenizer: A tokenizer to parse the field value.
+      message: A protocol message to record the data.
+      field: The descriptor of the field to be merged.
+
+    Raises:
+      ParseError: In case of text parsing problems.
+      RuntimeError: On runtime errors.
+    """
+    _ = self.allow_unknown_extension
+    value = None
+
+    if field.type in (descriptor.FieldDescriptor.TYPE_INT32,
+                      descriptor.FieldDescriptor.TYPE_SINT32,
+                      descriptor.FieldDescriptor.TYPE_SFIXED32):
+      value = tokenizer.ConsumeInt32()
+    elif field.type in (descriptor.FieldDescriptor.TYPE_INT64,
+                        descriptor.FieldDescriptor.TYPE_SINT64,
+                        descriptor.FieldDescriptor.TYPE_SFIXED64):
+      value = tokenizer.ConsumeInt64()
+    elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32,
+                        descriptor.FieldDescriptor.TYPE_FIXED32):
+      value = tokenizer.ConsumeUint32()
+    elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64,
+                        descriptor.FieldDescriptor.TYPE_FIXED64):
+      value = tokenizer.ConsumeUint64()
+    elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT,
+                        descriptor.FieldDescriptor.TYPE_DOUBLE):
+      value = tokenizer.ConsumeFloat()
+    elif field.type == descriptor.FieldDescriptor.TYPE_BOOL:
+      value = tokenizer.ConsumeBool()
+    elif field.type == descriptor.FieldDescriptor.TYPE_STRING:
+      value = tokenizer.ConsumeString()
+    elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:
+      value = tokenizer.ConsumeByteString()
+    elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:
+      value = tokenizer.ConsumeEnum(field)
+    else:
+      raise RuntimeError('Unknown field type %d' % field.type)
+
+    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+      if field.is_extension:
+        message.Extensions[field].append(value)
+      else:
+        getattr(message, field.name).append(value)
+    else:
+      if field.is_extension:
+        if not self._allow_multiple_scalars and message.HasExtension(field):
+          raise tokenizer.ParseErrorPreviousToken(
+              'Message type "%s" should not have multiple "%s" extensions.' %
+              (message.DESCRIPTOR.full_name, field.full_name))
+        else:
+          message.Extensions[field] = value
+      else:
+        if not self._allow_multiple_scalars and message.HasField(field.name):
+          raise tokenizer.ParseErrorPreviousToken(
+              'Message type "%s" should not have multiple "%s" fields.' %
+              (message.DESCRIPTOR.full_name, field.name))
+        else:
+          setattr(message, field.name, value)
+
+
+def _SkipFieldContents(tokenizer):
+  """Skips over contents (value or message) of a field.
+
+  Args:
+    tokenizer: A tokenizer to parse the field name and values.
+  """
+  # Try to guess the type of this field.
+  # If this field is not a message, there should be a ":" between the
+  # field name and the field value and also the field value should not
+  # start with "{" or "<" which indicates the beginning of a message body.
+  # If there is no ":" or there is a "{" or "<" after ":", this field has
+  # to be a message or the input is ill-formed.
+  if tokenizer.TryConsume(':') and not tokenizer.LookingAt(
+      '{') and not tokenizer.LookingAt('<'):
+    _SkipFieldValue(tokenizer)
+  else:
+    _SkipFieldMessage(tokenizer)
+
+
+def _SkipField(tokenizer):
+  """Skips over a complete field (name and value/message).
+
+  Args:
+    tokenizer: A tokenizer to parse the field name and values.
+  """
+  if tokenizer.TryConsume('['):
+    # Consume extension name.
+    tokenizer.ConsumeIdentifier()
+    while tokenizer.TryConsume('.'):
+      tokenizer.ConsumeIdentifier()
+    tokenizer.Consume(']')
+  else:
+    tokenizer.ConsumeIdentifier()
+
+  _SkipFieldContents(tokenizer)
+
+  # For historical reasons, fields may optionally be separated by commas or
+  # semicolons.
+  if not tokenizer.TryConsume(','):
+    tokenizer.TryConsume(';')
+
+
+def _SkipFieldMessage(tokenizer):
+  """Skips over a field message.
+
+  Args:
+    tokenizer: A tokenizer to parse the field name and values.
+  """
+
+  if tokenizer.TryConsume('<'):
+    delimiter = '>'
+  else:
+    tokenizer.Consume('{')
+    delimiter = '}'
+
+  while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'):
+    _SkipField(tokenizer)
+
+  tokenizer.Consume(delimiter)
+
+
+def _SkipFieldValue(tokenizer):
+  """Skips over a field value.
+
+  Args:
+    tokenizer: A tokenizer to parse the field name and values.
+
+  Raises:
+    ParseError: In case an invalid field value is found.
+  """
+  # String/bytes tokens can come in multiple adjacent string literals.
+  # If we can consume one, consume as many as we can.
+  if tokenizer.TryConsumeByteString():
+    while tokenizer.TryConsumeByteString():
+      pass
+    return
+
+  if (not tokenizer.TryConsumeIdentifier() and
+      not tokenizer.TryConsumeInt64() and
+      not tokenizer.TryConsumeUint64() and
+      not tokenizer.TryConsumeFloat()):
+    raise ParseError('Invalid field value: ' + tokenizer.token)
+
+
+class _Tokenizer(object):
+  """Protocol buffer text representation tokenizer.
+
+  This class handles the lower level string parsing by splitting it into
+  meaningful tokens.
+
+  It was directly ported from the Java protocol buffer API.
+  """
+
+  _WHITESPACE = re.compile('(\\s|(#.*$))+', re.MULTILINE)
+  _TOKEN = re.compile('|'.join([
+      r'[a-zA-Z_][0-9a-zA-Z_+-]*',             # an identifier
+      r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*',  # a number
+  ] + [                                        # quoted str for each quote mark
+      r'{qt}([^{qt}\n\\]|\\.)*({qt}|\\?$)'.format(qt=mark) for mark in _QUOTES
+  ]))
+
+  _IDENTIFIER = re.compile(r'\w+')
+
+  def __init__(self, lines):
+    self._position = 0
+    self._line = -1
+    self._column = 0
+    self._token_start = None
+    self.token = ''
+    self._lines = iter(lines)
+    self._current_line = ''
+    self._previous_line = 0
+    self._previous_column = 0
+    self._more_lines = True
+    self._SkipWhitespace()
+    self.NextToken()
+
+  def LookingAt(self, token):
+    return self.token == token
+
+  def AtEnd(self):
+    """Checks the end of the text was reached.
+
+    Returns:
+      True iff the end was reached.
+    """
+    return not self.token
+
+  def _PopLine(self):
+    while len(self._current_line) <= self._column:
+      try:
+        self._current_line = next(self._lines)
+      except StopIteration:
+        self._current_line = ''
+        self._more_lines = False
+        return
+      else:
+        self._line += 1
+        self._column = 0
+
+  def _SkipWhitespace(self):
+    while True:
+      self._PopLine()
+      match = self._WHITESPACE.match(self._current_line, self._column)
+      if not match:
+        break
+      length = len(match.group(0))
+      self._column += length
+
+  def TryConsume(self, token):
+    """Tries to consume a given piece of text.
+
+    Args:
+      token: Text to consume.
+
+    Returns:
+      True iff the text was consumed.
+    """
+    if self.token == token:
+      self.NextToken()
+      return True
+    return False
+
+  def Consume(self, token):
+    """Consumes a piece of text.
+
+    Args:
+      token: Text to consume.
+
+    Raises:
+      ParseError: If the text couldn't be consumed.
+    """
+    if not self.TryConsume(token):
+      raise self._ParseError('Expected "%s".' % token)
+
+  def TryConsumeIdentifier(self):
+    try:
+      self.ConsumeIdentifier()
+      return True
+    except ParseError:
+      return False
+
+  def ConsumeIdentifier(self):
+    """Consumes protocol message field identifier.
+
+    Returns:
+      Identifier string.
+
+    Raises:
+      ParseError: If an identifier couldn't be consumed.
+    """
+    result = self.token
+    if not self._IDENTIFIER.match(result):
+      raise self._ParseError('Expected identifier.')
+    self.NextToken()
+    return result
+
+  def ConsumeInt32(self):
+    """Consumes a signed 32bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If a signed 32bit integer couldn't be consumed.
+    """
+    try:
+      result = ParseInteger(self.token, is_signed=True, is_long=False)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def ConsumeUint32(self):
+    """Consumes an unsigned 32bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If an unsigned 32bit integer couldn't be consumed.
+    """
+    try:
+      result = ParseInteger(self.token, is_signed=False, is_long=False)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def TryConsumeInt64(self):
+    try:
+      self.ConsumeInt64()
+      return True
+    except ParseError:
+      return False
+
+  def ConsumeInt64(self):
+    """Consumes a signed 64bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If a signed 64bit integer couldn't be consumed.
+    """
+    try:
+      result = ParseInteger(self.token, is_signed=True, is_long=True)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def TryConsumeUint64(self):
+    try:
+      self.ConsumeUint64()
+      return True
+    except ParseError:
+      return False
+
+  def ConsumeUint64(self):
+    """Consumes an unsigned 64bit integer number.
+
+    Returns:
+      The integer parsed.
+
+    Raises:
+      ParseError: If an unsigned 64bit integer couldn't be consumed.
+    """
+    try:
+      result = ParseInteger(self.token, is_signed=False, is_long=True)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def TryConsumeFloat(self):
+    try:
+      self.ConsumeFloat()
+      return True
+    except ParseError:
+      return False
+
+  def ConsumeFloat(self):
+    """Consumes an floating point number.
+
+    Returns:
+      The number parsed.
+
+    Raises:
+      ParseError: If a floating point number couldn't be consumed.
+    """
+    try:
+      result = ParseFloat(self.token)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def ConsumeBool(self):
+    """Consumes a boolean value.
+
+    Returns:
+      The bool parsed.
+
+    Raises:
+      ParseError: If a boolean value couldn't be consumed.
+    """
+    try:
+      result = ParseBool(self.token)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def TryConsumeByteString(self):
+    try:
+      self.ConsumeByteString()
+      return True
+    except ParseError:
+      return False
+
+  def ConsumeString(self):
+    """Consumes a string value.
+
+    Returns:
+      The string parsed.
+
+    Raises:
+      ParseError: If a string value couldn't be consumed.
+    """
+    the_bytes = self.ConsumeByteString()
+    try:
+      return six.text_type(the_bytes, 'utf-8')
+    except UnicodeDecodeError as e:
+      raise self._StringParseError(e)
+
+  def ConsumeByteString(self):
+    """Consumes a byte array value.
+
+    Returns:
+      The array parsed (as a string).
+
+    Raises:
+      ParseError: If a byte array value couldn't be consumed.
+    """
+    the_list = [self._ConsumeSingleByteString()]
+    while self.token and self.token[0] in _QUOTES:
+      the_list.append(self._ConsumeSingleByteString())
+    return b''.join(the_list)
+
+  def _ConsumeSingleByteString(self):
+    """Consume one token of a string literal.
+
+    String literals (whether bytes or text) can come in multiple adjacent
+    tokens which are automatically concatenated, like in C or Python.  This
+    method only consumes one token.
+
+    Returns:
+      The token parsed.
+    Raises:
+      ParseError: When the wrong format data is found.
+    """
+    text = self.token
+    if len(text) < 1 or text[0] not in _QUOTES:
+      raise self._ParseError('Expected string but found: %r' % (text,))
+
+    if len(text) < 2 or text[-1] != text[0]:
+      raise self._ParseError('String missing ending quote: %r' % (text,))
+
+    try:
+      result = text_encoding.CUnescape(text[1:-1])
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def ConsumeEnum(self, field):
+    try:
+      result = ParseEnum(field, self.token)
+    except ValueError as e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
+
+  def ParseErrorPreviousToken(self, message):
+    """Creates and *returns* a ParseError for the previously read token.
+
+    Args:
+      message: A message to set for the exception.
+
+    Returns:
+      A ParseError instance.
+    """
+    return ParseError('%d:%d : %s' % (
+        self._previous_line + 1, self._previous_column + 1, message))
+
+  def _ParseError(self, message):
+    """Creates and *returns* a ParseError for the current token."""
+    return ParseError('%d:%d : %s' % (
+        self._line + 1, self._column + 1, message))
+
+  def _StringParseError(self, e):
+    return self._ParseError('Couldn\'t parse string: ' + str(e))
+
+  def NextToken(self):
+    """Reads the next meaningful token."""
+    self._previous_line = self._line
+    self._previous_column = self._column
+
+    self._column += len(self.token)
+    self._SkipWhitespace()
+
+    if not self._more_lines:
+      self.token = ''
+      return
+
+    match = self._TOKEN.match(self._current_line, self._column)
+    if match:
+      token = match.group(0)
+      self.token = token
+    else:
+      self.token = self._current_line[self._column]
+
+
+def ParseInteger(text, is_signed=False, is_long=False):
+  """Parses an integer.
+
+  Args:
+    text: The text to parse.
+    is_signed: True if a signed integer must be parsed.
+    is_long: True if a long integer must be parsed.
+
+  Returns:
+    The integer value.
+
+  Raises:
+    ValueError: Thrown Iff the text is not a valid integer.
+  """
+  # Do the actual parsing. Exception handling is propagated to caller.
+  try:
+    # We force 32-bit values to int and 64-bit values to long to make
+    # alternate implementations where the distinction is more significant
+    # (e.g. the C++ implementation) simpler.
+    if is_long:
+      result = long(text, 0)
+    else:
+      result = int(text, 0)
+  except ValueError:
+    raise ValueError('Couldn\'t parse integer: %s' % text)
+
+  # Check if the integer is sane. Exceptions handled by callers.
+  checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
+  checker.CheckValue(result)
+  return result
+
+
+def ParseFloat(text):
+  """Parse a floating point number.
+
+  Args:
+    text: Text to parse.
+
+  Returns:
+    The number parsed.
+
+  Raises:
+    ValueError: If a floating point number couldn't be parsed.
+  """
+  try:
+    # Assume Python compatible syntax.
+    return float(text)
+  except ValueError:
+    # Check alternative spellings.
+    if _FLOAT_INFINITY.match(text):
+      if text[0] == '-':
+        return float('-inf')
+      else:
+        return float('inf')
+    elif _FLOAT_NAN.match(text):
+      return float('nan')
+    else:
+      # assume '1.0f' format
+      try:
+        return float(text.rstrip('f'))
+      except ValueError:
+        raise ValueError('Couldn\'t parse float: %s' % text)
+
+
+def ParseBool(text):
+  """Parse a boolean value.
+
+  Args:
+    text: Text to parse.
+
+  Returns:
+    Boolean values parsed
+
+  Raises:
+    ValueError: If text is not a valid boolean.
+  """
+  if text in ('true', 't', '1'):
+    return True
+  elif text in ('false', 'f', '0'):
+    return False
+  else:
+    raise ValueError('Expected "true" or "false".')
+
+
+def ParseEnum(field, value):
+  """Parse an enum value.
+
+  The value can be specified by a number (the enum value), or by
+  a string literal (the enum name).
+
+  Args:
+    field: Enum field descriptor.
+    value: String value.
+
+  Returns:
+    Enum value number.
+
+  Raises:
+    ValueError: If the enum value could not be parsed.
+  """
+  enum_descriptor = field.enum_type
+  try:
+    number = int(value, 0)
+  except ValueError:
+    # Identifier.
+    enum_value = enum_descriptor.values_by_name.get(value, None)
+    if enum_value is None:
+      raise ValueError(
+          'Enum type "%s" has no value named %s.' % (
+              enum_descriptor.full_name, value))
+  else:
+    # Numeric value.
+    enum_value = enum_descriptor.values_by_number.get(number, None)
+    if enum_value is None:
+      raise ValueError(
+          'Enum type "%s" has no value with number %d.' % (
+              enum_descriptor.full_name, number))
+  return enum_value.number
diff --git a/src/third_party/protobuf-3/python/mox.py b/src/third_party/protobuf-3/python/mox.py
new file mode 100755
index 0000000..257468e
--- /dev/null
+++ b/src/third_party/protobuf-3/python/mox.py
@@ -0,0 +1,1401 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is used for testing.  The original is at:
+#   http://code.google.com/p/pymox/
+
+"""Mox, an object-mocking framework for Python.
+
+Mox works in the record-replay-verify paradigm.  When you first create
+a mock object, it is in record mode.  You then programmatically set
+the expected behavior of the mock object (what methods are to be
+called on it, with what parameters, what they should return, and in
+what order).
+
+Once you have set up the expected mock behavior, you put it in replay
+mode.  Now the mock responds to method calls just as you told it to.
+If an unexpected method (or an expected method with unexpected
+parameters) is called, then an exception will be raised.
+
+Once you are done interacting with the mock, you need to verify that
+all the expected interactions occurred.  (Maybe your code exited
+prematurely without calling some cleanup method!)  The verify phase
+ensures that every expected method was called; otherwise, an exception
+will be raised.
+
+Suggested usage / workflow:
+
+  # Create Mox factory
+  my_mox = Mox()
+
+  # Create a mock data access object
+  mock_dao = my_mox.CreateMock(DAOClass)
+
+  # Set up expected behavior
+  mock_dao.RetrievePersonWithIdentifier('1').AndReturn(person)
+  mock_dao.DeletePerson(person)
+
+  # Put mocks in replay mode
+  my_mox.ReplayAll()
+
+  # Inject mock object and run test
+  controller.SetDao(mock_dao)
+  controller.DeletePersonById('1')
+
+  # Verify all methods were called as expected
+  my_mox.VerifyAll()
+"""
+
+from collections import deque
+import re
+import types
+import unittest
+
+import stubout
+
+class Error(AssertionError):
+  """Base exception for this module."""
+
+  pass
+
+
+class ExpectedMethodCallsError(Error):
+  """Raised when Verify() is called before all expected methods have been called
+  """
+
+  def __init__(self, expected_methods):
+    """Init exception.
+
+    Args:
+      # expected_methods: A sequence of MockMethod objects that should have been
+      #   called.
+      expected_methods: [MockMethod]
+
+    Raises:
+      ValueError: if expected_methods contains no methods.
+    """
+
+    if not expected_methods:
+      raise ValueError("There must be at least one expected method")
+    Error.__init__(self)
+    self._expected_methods = expected_methods
+
+  def __str__(self):
+    calls = "\n".join(["%3d.  %s" % (i, m)
+                       for i, m in enumerate(self._expected_methods)])
+    return "Verify: Expected methods never called:\n%s" % (calls,)
+
+
+class UnexpectedMethodCallError(Error):
+  """Raised when an unexpected method is called.
+
+  This can occur if a method is called with incorrect parameters, or out of the
+  specified order.
+  """
+
+  def __init__(self, unexpected_method, expected):
+    """Init exception.
+
+    Args:
+      # unexpected_method: MockMethod that was called but was not at the head of
+      #   the expected_method queue.
+      # expected: MockMethod or UnorderedGroup the method should have
+      #   been in.
+      unexpected_method: MockMethod
+      expected: MockMethod or UnorderedGroup
+    """
+
+    Error.__init__(self)
+    self._unexpected_method = unexpected_method
+    self._expected = expected
+
+  def __str__(self):
+    return "Unexpected method call: %s.  Expecting: %s" % \
+      (self._unexpected_method, self._expected)
+
+
+class UnknownMethodCallError(Error):
+  """Raised if an unknown method is requested of the mock object."""
+
+  def __init__(self, unknown_method_name):
+    """Init exception.
+
+    Args:
+      # unknown_method_name: Method call that is not part of the mocked class's
+      #   public interface.
+      unknown_method_name: str
+    """
+
+    Error.__init__(self)
+    self._unknown_method_name = unknown_method_name
+
+  def __str__(self):
+    return "Method called is not a member of the object: %s" % \
+      self._unknown_method_name
+
+
+class Mox(object):
+  """Mox: a factory for creating mock objects."""
+
+  # A list of types that should be stubbed out with MockObjects (as
+  # opposed to MockAnythings).
+  _USE_MOCK_OBJECT = [types.ClassType, types.InstanceType, types.ModuleType,
+                      types.ObjectType, types.TypeType]
+
+  def __init__(self):
+    """Initialize a new Mox."""
+
+    self._mock_objects = []
+    self.stubs = stubout.StubOutForTesting()
+
+  def CreateMock(self, class_to_mock):
+    """Create a new mock object.
+
+    Args:
+      # class_to_mock: the class to be mocked
+      class_to_mock: class
+
+    Returns:
+      MockObject that can be used as the class_to_mock would be.
+    """
+
+    new_mock = MockObject(class_to_mock)
+    self._mock_objects.append(new_mock)
+    return new_mock
+
+  def CreateMockAnything(self):
+    """Create a mock that will accept any method calls.
+
+    This does not enforce an interface.
+    """
+
+    new_mock = MockAnything()
+    self._mock_objects.append(new_mock)
+    return new_mock
+
+  def ReplayAll(self):
+    """Set all mock objects to replay mode."""
+
+    for mock_obj in self._mock_objects:
+      mock_obj._Replay()
+
+
+  def VerifyAll(self):
+    """Call verify on all mock objects created."""
+
+    for mock_obj in self._mock_objects:
+      mock_obj._Verify()
+
+  def ResetAll(self):
+    """Call reset on all mock objects.  This does not unset stubs."""
+
+    for mock_obj in self._mock_objects:
+      mock_obj._Reset()
+
+  def StubOutWithMock(self, obj, attr_name, use_mock_anything=False):
+    """Replace a method, attribute, etc. with a Mock.
+
+    This will replace a class or module with a MockObject, and everything else
+    (method, function, etc) with a MockAnything.  This can be overridden to
+    always use a MockAnything by setting use_mock_anything to True.
+
+    Args:
+      obj: A Python object (class, module, instance, callable).
+      attr_name: str.  The name of the attribute to replace with a mock.
+      use_mock_anything: bool. True if a MockAnything should be used regardless
+        of the type of attribute.
+    """
+
+    attr_to_replace = getattr(obj, attr_name)
+    if type(attr_to_replace) in self._USE_MOCK_OBJECT and not use_mock_anything:
+      stub = self.CreateMock(attr_to_replace)
+    else:
+      stub = self.CreateMockAnything()
+
+    self.stubs.Set(obj, attr_name, stub)
+
+  def UnsetStubs(self):
+    """Restore stubs to their original state."""
+
+    self.stubs.UnsetAll()
+
+def Replay(*args):
+  """Put mocks into Replay mode.
+
+  Args:
+    # args is any number of mocks to put into replay mode.
+  """
+
+  for mock in args:
+    mock._Replay()
+
+
+def Verify(*args):
+  """Verify mocks.
+
+  Args:
+    # args is any number of mocks to be verified.
+  """
+
+  for mock in args:
+    mock._Verify()
+
+
+def Reset(*args):
+  """Reset mocks.
+
+  Args:
+    # args is any number of mocks to be reset.
+  """
+
+  for mock in args:
+    mock._Reset()
+
+
+class MockAnything:
+  """A mock that can be used to mock anything.
+
+  This is helpful for mocking classes that do not provide a public interface.
+  """
+
+  def __init__(self):
+    """ """
+    self._Reset()
+
+  def __getattr__(self, method_name):
+    """Intercept method calls on this object.
+
+     A new MockMethod is returned that is aware of the MockAnything's
+     state (record or replay).  The call will be recorded or replayed
+     by the MockMethod's __call__.
+
+    Args:
+      # method name: the name of the method being called.
+      method_name: str
+
+    Returns:
+      A new MockMethod aware of MockAnything's state (record or replay).
+    """
+
+    return self._CreateMockMethod(method_name)
+
+  def _CreateMockMethod(self, method_name):
+    """Create a new mock method call and return it.
+
+    Args:
+      # method name: the name of the method being called.
+      method_name: str
+
+    Returns:
+      A new MockMethod aware of MockAnything's state (record or replay).
+    """
+
+    return MockMethod(method_name, self._expected_calls_queue,
+                      self._replay_mode)
+
+  def __nonzero__(self):
+    """Return 1 for nonzero so the mock can be used as a conditional."""
+
+    return 1
+
+  def __eq__(self, rhs):
+    """Provide custom logic to compare objects."""
+
+    return (isinstance(rhs, MockAnything) and
+            self._replay_mode == rhs._replay_mode and
+            self._expected_calls_queue == rhs._expected_calls_queue)
+
+  def __ne__(self, rhs):
+    """Provide custom logic to compare objects."""
+
+    return not self == rhs
+
+  def _Replay(self):
+    """Start replaying expected method calls."""
+
+    self._replay_mode = True
+
+  def _Verify(self):
+    """Verify that all of the expected calls have been made.
+
+    Raises:
+      ExpectedMethodCallsError: if there are still more method calls in the
+        expected queue.
+    """
+
+    # If the list of expected calls is not empty, raise an exception
+    if self._expected_calls_queue:
+      # The last MultipleTimesGroup is not popped from the queue.
+      if (len(self._expected_calls_queue) == 1 and
+          isinstance(self._expected_calls_queue[0], MultipleTimesGroup) and
+          self._expected_calls_queue[0].IsSatisfied()):
+        pass
+      else:
+        raise ExpectedMethodCallsError(self._expected_calls_queue)
+
+  def _Reset(self):
+    """Reset the state of this mock to record mode with an empty queue."""
+
+    # Maintain a list of method calls we are expecting
+    self._expected_calls_queue = deque()
+
+    # Make sure we are in setup mode, not replay mode
+    self._replay_mode = False
+
+
+class MockObject(MockAnything, object):
+  """A mock object that simulates the public/protected interface of a class."""
+
+  def __init__(self, class_to_mock):
+    """Initialize a mock object.
+
+    This determines the methods and properties of the class and stores them.
+
+    Args:
+      # class_to_mock: class to be mocked
+      class_to_mock: class
+    """
+
+    # This is used to hack around the mixin/inheritance of MockAnything, which
+    # is not a proper object (it can be anything. :-)
+    MockAnything.__dict__['__init__'](self)
+
+    # Get a list of all the public and special methods we should mock.
+    self._known_methods = set()
+    self._known_vars = set()
+    self._class_to_mock = class_to_mock
+    for method in dir(class_to_mock):
+      if callable(getattr(class_to_mock, method)):
+        self._known_methods.add(method)
+      else:
+        self._known_vars.add(method)
+
+  def __getattr__(self, name):
+    """Intercept attribute request on this object.
+
+    If the attribute is a public class variable, it will be returned and not
+    recorded as a call.
+
+    If the attribute is not a variable, it is handled like a method
+    call. The method name is checked against the set of mockable
+    methods, and a new MockMethod is returned that is aware of the
+    MockObject's state (record or replay).  The call will be recorded
+    or replayed by the MockMethod's __call__.
+
+    Args:
+      # name: the name of the attribute being requested.
+      name: str
+
+    Returns:
+      Either a class variable or a new MockMethod that is aware of the state
+      of the mock (record or replay).
+
+    Raises:
+      UnknownMethodCallError if the MockObject does not mock the requested
+          method.
+    """
+
+    if name in self._known_vars:
+      return getattr(self._class_to_mock, name)
+
+    if name in self._known_methods:
+      return self._CreateMockMethod(name)
+
+    raise UnknownMethodCallError(name)
+
+  def __eq__(self, rhs):
+    """Provide custom logic to compare objects."""
+
+    return (isinstance(rhs, MockObject) and
+            self._class_to_mock == rhs._class_to_mock and
+            self._replay_mode == rhs._replay_mode and
+            self._expected_calls_queue == rhs._expected_calls_queue)
+
+  def __setitem__(self, key, value):
+    """Provide custom logic for mocking classes that support item assignment.
+
+    Args:
+      key: Key to set the value for.
+      value: Value to set.
+
+    Returns:
+      Expected return value in replay mode.  A MockMethod object for the
+      __setitem__ method that has already been called if not in replay mode.
+
+    Raises:
+      TypeError if the underlying class does not support item assignment.
+      UnexpectedMethodCallError if the object does not expect the call to
+        __setitem__.
+
+    """
+    setitem = self._class_to_mock.__dict__.get('__setitem__', None)
+
+    # Verify the class supports item assignment.
+    if setitem is None:
+      raise TypeError('object does not support item assignment')
+
+    # If we are in replay mode then simply call the mock __setitem__ method.
+    if self._replay_mode:
+      return MockMethod('__setitem__', self._expected_calls_queue,
+                        self._replay_mode)(key, value)
+
+
+    # Otherwise, create a mock method __setitem__.
+    return self._CreateMockMethod('__setitem__')(key, value)
+
+  def __getitem__(self, key):
+    """Provide custom logic for mocking classes that are subscriptable.
+
+    Args:
+      key: Key to return the value for.
+
+    Returns:
+      Expected return value in replay mode.  A MockMethod object for the
+      __getitem__ method that has already been called if not in replay mode.
+
+    Raises:
+      TypeError if the underlying class is not subscriptable.
+      UnexpectedMethodCallError if the object does not expect the call to
+        __setitem__.
+
+    """
+    getitem = self._class_to_mock.__dict__.get('__getitem__', None)
+
+    # Verify the class supports item assignment.
+    if getitem is None:
+      raise TypeError('unsubscriptable object')
+
+    # If we are in replay mode then simply call the mock __getitem__ method.
+    if self._replay_mode:
+      return MockMethod('__getitem__', self._expected_calls_queue,
+                        self._replay_mode)(key)
+
+
+    # Otherwise, create a mock method __getitem__.
+    return self._CreateMockMethod('__getitem__')(key)
+
+  def __call__(self, *params, **named_params):
+    """Provide custom logic for mocking classes that are callable."""
+
+    # Verify the class we are mocking is callable
+    callable = self._class_to_mock.__dict__.get('__call__', None)
+    if callable is None:
+      raise TypeError('Not callable')
+
+    # Because the call is happening directly on this object instead of a method,
+    # the call on the mock method is made right here
+    mock_method = self._CreateMockMethod('__call__')
+    return mock_method(*params, **named_params)
+
+  @property
+  def __class__(self):
+    """Return the class that is being mocked."""
+
+    return self._class_to_mock
+
+
+class MockMethod(object):
+  """Callable mock method.
+
+  A MockMethod should act exactly like the method it mocks, accepting parameters
+  and returning a value, or throwing an exception (as specified).  When this
+  method is called, it can optionally verify whether the called method (name and
+  signature) matches the expected method.
+  """
+
+  def __init__(self, method_name, call_queue, replay_mode):
+    """Construct a new mock method.
+
+    Args:
+      # method_name: the name of the method
+      # call_queue: deque of calls, verify this call against the head, or add
+      #     this call to the queue.
+      # replay_mode: False if we are recording, True if we are verifying calls
+      #     against the call queue.
+      method_name: str
+      call_queue: list or deque
+      replay_mode: bool
+    """
+
+    self._name = method_name
+    self._call_queue = call_queue
+    if not isinstance(call_queue, deque):
+      self._call_queue = deque(self._call_queue)
+    self._replay_mode = replay_mode
+
+    self._params = None
+    self._named_params = None
+    self._return_value = None
+    self._exception = None
+    self._side_effects = None
+
+  def __call__(self, *params, **named_params):
+    """Log parameters and return the specified return value.
+
+    If the Mock(Anything/Object) associated with this call is in record mode,
+    this MockMethod will be pushed onto the expected call queue.  If the mock
+    is in replay mode, this will pop a MockMethod off the top of the queue and
+    verify this call is equal to the expected call.
+
+    Raises:
+      UnexpectedMethodCall if this call is supposed to match an expected method
+        call and it does not.
+    """
+
+    self._params = params
+    self._named_params = named_params
+
+    if not self._replay_mode:
+      self._call_queue.append(self)
+      return self
+
+    expected_method = self._VerifyMethodCall()
+
+    if expected_method._side_effects:
+      expected_method._side_effects(*params, **named_params)
+
+    if expected_method._exception:
+      raise expected_method._exception
+
+    return expected_method._return_value
+
+  def __getattr__(self, name):
+    """Raise an AttributeError with a helpful message."""
+
+    raise AttributeError('MockMethod has no attribute "%s". '
+        'Did you remember to put your mocks in replay mode?' % name)
+
+  def _PopNextMethod(self):
+    """Pop the next method from our call queue."""
+    try:
+      return self._call_queue.popleft()
+    except IndexError:
+      raise UnexpectedMethodCallError(self, None)
+
+  def _VerifyMethodCall(self):
+    """Verify the called method is expected.
+
+    This can be an ordered method, or part of an unordered set.
+
+    Returns:
+      The expected mock method.
+
+    Raises:
+      UnexpectedMethodCall if the method called was not expected.
+    """
+
+    expected = self._PopNextMethod()
+
+    # Loop here, because we might have a MethodGroup followed by another
+    # group.
+    while isinstance(expected, MethodGroup):
+      expected, method = expected.MethodCalled(self)
+      if method is not None:
+        return method
+
+    # This is a mock method, so just check equality.
+    if expected != self:
+      raise UnexpectedMethodCallError(self, expected)
+
+    return expected
+
+  def __str__(self):
+    params = ', '.join(
+        [repr(p) for p in self._params or []] +
+        ['%s=%r' % x for x in sorted((self._named_params or {}).items())])
+    desc = "%s(%s) -> %r" % (self._name, params, self._return_value)
+    return desc
+
+  def __eq__(self, rhs):
+    """Test whether this MockMethod is equivalent to another MockMethod.
+
+    Args:
+      # rhs: the right hand side of the test
+      rhs: MockMethod
+    """
+
+    return (isinstance(rhs, MockMethod) and
+            self._name == rhs._name and
+            self._params == rhs._params and
+            self._named_params == rhs._named_params)
+
+  def __ne__(self, rhs):
+    """Test whether this MockMethod is not equivalent to another MockMethod.
+
+    Args:
+      # rhs: the right hand side of the test
+      rhs: MockMethod
+    """
+
+    return not self == rhs
+
+  def GetPossibleGroup(self):
+    """Returns a possible group from the end of the call queue or None if no
+    other methods are on the stack.
+    """
+
+    # Remove this method from the tail of the queue so we can add it to a group.
+    this_method = self._call_queue.pop()
+    assert this_method == self
+
+    # Determine if the tail of the queue is a group, or just a regular ordered
+    # mock method.
+    group = None
+    try:
+      group = self._call_queue[-1]
+    except IndexError:
+      pass
+
+    return group
+
+  def _CheckAndCreateNewGroup(self, group_name, group_class):
+    """Checks if the last method (a possible group) is an instance of our
+    group_class. Adds the current method to this group or creates a new one.
+
+    Args:
+
+      group_name: the name of the group.
+      group_class: the class used to create instance of this new group
+    """
+    group = self.GetPossibleGroup()
+
+    # If this is a group, and it is the correct group, add the method.
+    if isinstance(group, group_class) and group.group_name() == group_name:
+      group.AddMethod(self)
+      return self
+
+    # Create a new group and add the method.
+    new_group = group_class(group_name)
+    new_group.AddMethod(self)
+    self._call_queue.append(new_group)
+    return self
+
+  def InAnyOrder(self, group_name="default"):
+    """Move this method into a group of unordered calls.
+
+    A group of unordered calls must be defined together, and must be executed
+    in full before the next expected method can be called.  There can be
+    multiple groups that are expected serially, if they are given
+    different group names.  The same group name can be reused if there is a
+    standard method call, or a group with a different name, spliced between
+    usages.
+
+    Args:
+      group_name: the name of the unordered group.
+
+    Returns:
+      self
+    """
+    return self._CheckAndCreateNewGroup(group_name, UnorderedGroup)
+
+  def MultipleTimes(self, group_name="default"):
+    """Move this method into group of calls which may be called multiple times.
+
+    A group of repeating calls must be defined together, and must be executed in
+    full before the next expected mehtod can be called.
+
+    Args:
+      group_name: the name of the unordered group.
+
+    Returns:
+      self
+    """
+    return self._CheckAndCreateNewGroup(group_name, MultipleTimesGroup)
+
+  def AndReturn(self, return_value):
+    """Set the value to return when this method is called.
+
+    Args:
+      # return_value can be anything.
+    """
+
+    self._return_value = return_value
+    return return_value
+
+  def AndRaise(self, exception):
+    """Set the exception to raise when this method is called.
+
+    Args:
+      # exception: the exception to raise when this method is called.
+      exception: Exception
+    """
+
+    self._exception = exception
+
+  def WithSideEffects(self, side_effects):
+    """Set the side effects that are simulated when this method is called.
+
+    Args:
+      side_effects: A callable which modifies the parameters or other relevant
+        state which a given test case depends on.
+
+    Returns:
+      Self for chaining with AndReturn and AndRaise.
+    """
+    self._side_effects = side_effects
+    return self
+
+class Comparator:
+  """Base class for all Mox comparators.
+
+  A Comparator can be used as a parameter to a mocked method when the exact
+  value is not known.  For example, the code you are testing might build up a
+  long SQL string that is passed to your mock DAO. You're only interested that
+  the IN clause contains the proper primary keys, so you can set your mock
+  up as follows:
+
+  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
+
+  Now whatever query is passed in must contain the string 'IN (1, 2, 4, 5)'.
+
+  A Comparator may replace one or more parameters, for example:
+  # return at most 10 rows
+  mock_dao.RunQuery(StrContains('SELECT'), 10)
+
+  or
+
+  # Return some non-deterministic number of rows
+  mock_dao.RunQuery(StrContains('SELECT'), IsA(int))
+  """
+
+  def equals(self, rhs):
+    """Special equals method that all comparators must implement.
+
+    Args:
+      rhs: any python object
+    """
+
+    raise NotImplementedError, 'method must be implemented by a subclass.'
+
+  def __eq__(self, rhs):
+    return self.equals(rhs)
+
+  def __ne__(self, rhs):
+    return not self.equals(rhs)
+
+
+class IsA(Comparator):
+  """This class wraps a basic Python type or class.  It is used to verify
+  that a parameter is of the given type or class.
+
+  Example:
+  mock_dao.Connect(IsA(DbConnectInfo))
+  """
+
+  def __init__(self, class_name):
+    """Initialize IsA
+
+    Args:
+      class_name: basic python type or a class
+    """
+
+    self._class_name = class_name
+
+  def equals(self, rhs):
+    """Check to see if the RHS is an instance of class_name.
+
+    Args:
+      # rhs: the right hand side of the test
+      rhs: object
+
+    Returns:
+      bool
+    """
+
+    try:
+      return isinstance(rhs, self._class_name)
+    except TypeError:
+      # Check raw types if there was a type error.  This is helpful for
+      # things like cStringIO.StringIO.
+      return type(rhs) == type(self._class_name)
+
+  def __repr__(self):
+    return str(self._class_name)
+
+class IsAlmost(Comparator):
+  """Comparison class used to check whether a parameter is nearly equal
+  to a given value.  Generally useful for floating point numbers.
+
+  Example mock_dao.SetTimeout((IsAlmost(3.9)))
+  """
+
+  def __init__(self, float_value, places=7):
+    """Initialize IsAlmost.
+
+    Args:
+      float_value: The value for making the comparison.
+      places: The number of decimal places to round to.
+    """
+
+    self._float_value = float_value
+    self._places = places
+
+  def equals(self, rhs):
+    """Check to see if RHS is almost equal to float_value
+
+    Args:
+      rhs: the value to compare to float_value
+
+    Returns:
+      bool
+    """
+
+    try:
+      return round(rhs-self._float_value, self._places) == 0
+    except TypeError:
+      # This is probably because either float_value or rhs is not a number.
+      return False
+
+  def __repr__(self):
+    return str(self._float_value)
+
+class StrContains(Comparator):
+  """Comparison class used to check whether a substring exists in a
+  string parameter.  This can be useful in mocking a database with SQL
+  passed in as a string parameter, for example.
+
+  Example:
+  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
+  """
+
+  def __init__(self, search_string):
+    """Initialize.
+
+    Args:
+      # search_string: the string you are searching for
+      search_string: str
+    """
+
+    self._search_string = search_string
+
+  def equals(self, rhs):
+    """Check to see if the search_string is contained in the rhs string.
+
+    Args:
+      # rhs: the right hand side of the test
+      rhs: object
+
+    Returns:
+      bool
+    """
+
+    try:
+      return rhs.find(self._search_string) > -1
+    except Exception:
+      return False
+
+  def __repr__(self):
+    return '<str containing \'%s\'>' % self._search_string
+
+
+class Regex(Comparator):
+  """Checks if a string matches a regular expression.
+
+  This uses a given regular expression to determine equality.
+  """
+
+  def __init__(self, pattern, flags=0):
+    """Initialize.
+
+    Args:
+      # pattern is the regular expression to search for
+      pattern: str
+      # flags passed to re.compile function as the second argument
+      flags: int
+    """
+
+    self.regex = re.compile(pattern, flags=flags)
+
+  def equals(self, rhs):
+    """Check to see if rhs matches regular expression pattern.
+
+    Returns:
+      bool
+    """
+
+    return self.regex.search(rhs) is not None
+
+  def __repr__(self):
+    s = '<regular expression \'%s\'' % self.regex.pattern
+    if self.regex.flags:
+      s += ', flags=%d' % self.regex.flags
+    s += '>'
+    return s
+
+
+class In(Comparator):
+  """Checks whether an item (or key) is in a list (or dict) parameter.
+
+  Example:
+  mock_dao.GetUsersInfo(In('expectedUserName')).AndReturn(mock_result)
+  """
+
+  def __init__(self, key):
+    """Initialize.
+
+    Args:
+      # key is any thing that could be in a list or a key in a dict
+    """
+
+    self._key = key
+
+  def equals(self, rhs):
+    """Check to see whether key is in rhs.
+
+    Args:
+      rhs: dict
+
+    Returns:
+      bool
+    """
+
+    return self._key in rhs
+
+  def __repr__(self):
+    return '<sequence or map containing \'%s\'>' % self._key
+
+
+class ContainsKeyValue(Comparator):
+  """Checks whether a key/value pair is in a dict parameter.
+
+  Example:
+  mock_dao.UpdateUsers(ContainsKeyValue('stevepm', stevepm_user_info))
+  """
+
+  def __init__(self, key, value):
+    """Initialize.
+
+    Args:
+      # key: a key in a dict
+      # value: the corresponding value
+    """
+
+    self._key = key
+    self._value = value
+
+  def equals(self, rhs):
+    """Check whether the given key/value pair is in the rhs dict.
+
+    Returns:
+      bool
+    """
+
+    try:
+      return rhs[self._key] == self._value
+    except Exception:
+      return False
+
+  def __repr__(self):
+    return '<map containing the entry \'%s: %s\'>' % (self._key, self._value)
+
+
+class SameElementsAs(Comparator):
+  """Checks whether iterables contain the same elements (ignoring order).
+
+  Example:
+  mock_dao.ProcessUsers(SameElementsAs('stevepm', 'salomaki'))
+  """
+
+  def __init__(self, expected_seq):
+    """Initialize.
+
+    Args:
+      expected_seq: a sequence
+    """
+
+    self._expected_seq = expected_seq
+
+  def equals(self, actual_seq):
+    """Check to see whether actual_seq has same elements as expected_seq.
+
+    Args:
+      actual_seq: sequence
+
+    Returns:
+      bool
+    """
+
+    try:
+      expected = dict([(element, None) for element in self._expected_seq])
+      actual = dict([(element, None) for element in actual_seq])
+    except TypeError:
+      # Fall back to slower list-compare if any of the objects are unhashable.
+      expected = list(self._expected_seq)
+      actual = list(actual_seq)
+      expected.sort()
+      actual.sort()
+    return expected == actual
+
+  def __repr__(self):
+    return '<sequence with same elements as \'%s\'>' % self._expected_seq
+
+
+class And(Comparator):
+  """Evaluates one or more Comparators on RHS and returns an AND of the results.
+  """
+
+  def __init__(self, *args):
+    """Initialize.
+
+    Args:
+      *args: One or more Comparator
+    """
+
+    self._comparators = args
+
+  def equals(self, rhs):
+    """Checks whether all Comparators are equal to rhs.
+
+    Args:
+      # rhs: can be anything
+
+    Returns:
+      bool
+    """
+
+    for comparator in self._comparators:
+      if not comparator.equals(rhs):
+        return False
+
+    return True
+
+  def __repr__(self):
+    return '<AND %s>' % str(self._comparators)
+
+
+class Or(Comparator):
+  """Evaluates one or more Comparators on RHS and returns an OR of the results.
+  """
+
+  def __init__(self, *args):
+    """Initialize.
+
+    Args:
+      *args: One or more Mox comparators
+    """
+
+    self._comparators = args
+
+  def equals(self, rhs):
+    """Checks whether any Comparator is equal to rhs.
+
+    Args:
+      # rhs: can be anything
+
+    Returns:
+      bool
+    """
+
+    for comparator in self._comparators:
+      if comparator.equals(rhs):
+        return True
+
+    return False
+
+  def __repr__(self):
+    return '<OR %s>' % str(self._comparators)
+
+
+class Func(Comparator):
+  """Call a function that should verify the parameter passed in is correct.
+
+  You may need the ability to perform more advanced operations on the parameter
+  in order to validate it.  You can use this to have a callable validate any
+  parameter. The callable should return either True or False.
+
+
+  Example:
+
+  def myParamValidator(param):
+    # Advanced logic here
+    return True
+
+  mock_dao.DoSomething(Func(myParamValidator), true)
+  """
+
+  def __init__(self, func):
+    """Initialize.
+
+    Args:
+      func: callable that takes one parameter and returns a bool
+    """
+
+    self._func = func
+
+  def equals(self, rhs):
+    """Test whether rhs passes the function test.
+
+    rhs is passed into func.
+
+    Args:
+      rhs: any python object
+
+    Returns:
+      the result of func(rhs)
+    """
+
+    return self._func(rhs)
+
+  def __repr__(self):
+    return str(self._func)
+
+
+class IgnoreArg(Comparator):
+  """Ignore an argument.
+
+  This can be used when we don't care about an argument of a method call.
+
+  Example:
+  # Check if CastMagic is called with 3 as first arg and 'disappear' as third.
+  mymock.CastMagic(3, IgnoreArg(), 'disappear')
+  """
+
+  def equals(self, unused_rhs):
+    """Ignores arguments and returns True.
+
+    Args:
+      unused_rhs: any python object
+
+    Returns:
+      always returns True
+    """
+
+    return True
+
+  def __repr__(self):
+    return '<IgnoreArg>'
+
+
+class MethodGroup(object):
+  """Base class containing common behaviour for MethodGroups."""
+
+  def __init__(self, group_name):
+    self._group_name = group_name
+
+  def group_name(self):
+    return self._group_name
+
+  def __str__(self):
+    return '<%s "%s">' % (self.__class__.__name__, self._group_name)
+
+  def AddMethod(self, mock_method):
+    raise NotImplementedError
+
+  def MethodCalled(self, mock_method):
+    raise NotImplementedError
+
+  def IsSatisfied(self):
+    raise NotImplementedError
+
+class UnorderedGroup(MethodGroup):
+  """UnorderedGroup holds a set of method calls that may occur in any order.
+
+  This construct is helpful for non-deterministic events, such as iterating
+  over the keys of a dict.
+  """
+
+  def __init__(self, group_name):
+    super(UnorderedGroup, self).__init__(group_name)
+    self._methods = []
+
+  def AddMethod(self, mock_method):
+    """Add a method to this group.
+
+    Args:
+      mock_method: A mock method to be added to this group.
+    """
+
+    self._methods.append(mock_method)
+
+  def MethodCalled(self, mock_method):
+    """Remove a method call from the group.
+
+    If the method is not in the set, an UnexpectedMethodCallError will be
+    raised.
+
+    Args:
+      mock_method: a mock method that should be equal to a method in the group.
+
+    Returns:
+      The mock method from the group
+
+    Raises:
+      UnexpectedMethodCallError if the mock_method was not in the group.
+    """
+
+    # Check to see if this method exists, and if so, remove it from the set
+    # and return it.
+    for method in self._methods:
+      if method == mock_method:
+        # Remove the called mock_method instead of the method in the group.
+        # The called method will match any comparators when equality is checked
+        # during removal.  The method in the group could pass a comparator to
+        # another comparator during the equality check.
+        self._methods.remove(mock_method)
+
+        # If this group is not empty, put it back at the head of the queue.
+        if not self.IsSatisfied():
+          mock_method._call_queue.appendleft(self)
+
+        return self, method
+
+    raise UnexpectedMethodCallError(mock_method, self)
+
+  def IsSatisfied(self):
+    """Return True if there are not any methods in this group."""
+
+    return len(self._methods) == 0
+
+
+class MultipleTimesGroup(MethodGroup):
+  """MultipleTimesGroup holds methods that may be called any number of times.
+
+  Note: Each method must be called at least once.
+
+  This is helpful, if you don't know or care how many times a method is called.
+  """
+
+  def __init__(self, group_name):
+    super(MultipleTimesGroup, self).__init__(group_name)
+    self._methods = set()
+    self._methods_called = set()
+
+  def AddMethod(self, mock_method):
+    """Add a method to this group.
+
+    Args:
+      mock_method: A mock method to be added to this group.
+    """
+
+    self._methods.add(mock_method)
+
+  def MethodCalled(self, mock_method):
+    """Remove a method call from the group.
+
+    If the method is not in the set, an UnexpectedMethodCallError will be
+    raised.
+
+    Args:
+      mock_method: a mock method that should be equal to a method in the group.
+
+    Returns:
+      The mock method from the group
+
+    Raises:
+      UnexpectedMethodCallError if the mock_method was not in the group.
+    """
+
+    # Check to see if this method exists, and if so add it to the set of
+    # called methods.
+
+    for method in self._methods:
+      if method == mock_method:
+        self._methods_called.add(mock_method)
+        # Always put this group back on top of the queue, because we don't know
+        # when we are done.
+        mock_method._call_queue.appendleft(self)
+        return self, method
+
+    if self.IsSatisfied():
+      next_method = mock_method._PopNextMethod();
+      return next_method, None
+    else:
+      raise UnexpectedMethodCallError(mock_method, self)
+
+  def IsSatisfied(self):
+    """Return True if all methods in this group are called at least once."""
+    # NOTE(psycho): We can't use the simple set difference here because we want
+    # to match different parameters which are considered the same e.g. IsA(str)
+    # and some string. This solution is O(n^2) but n should be small.
+    tmp = self._methods.copy()
+    for called in self._methods_called:
+      for expected in tmp:
+        if called == expected:
+          tmp.remove(expected)
+          if not tmp:
+            return True
+          break
+    return False
+
+
+class MoxMetaTestBase(type):
+  """Metaclass to add mox cleanup and verification to every test.
+
+  As the mox unit testing class is being constructed (MoxTestBase or a
+  subclass), this metaclass will modify all test functions to call the
+  CleanUpMox method of the test class after they finish. This means that
+  unstubbing and verifying will happen for every test with no additional code,
+  and any failures will result in test failures as opposed to errors.
+  """
+
+  def __init__(cls, name, bases, d):
+    type.__init__(cls, name, bases, d)
+
+    # also get all the attributes from the base classes to account
+    # for a case when test class is not the immediate child of MoxTestBase
+    for base in bases:
+      for attr_name in dir(base):
+        d[attr_name] = getattr(base, attr_name)
+
+    for func_name, func in d.items():
+      if func_name.startswith('test') and callable(func):
+        setattr(cls, func_name, MoxMetaTestBase.CleanUpTest(cls, func))
+
+  @staticmethod
+  def CleanUpTest(cls, func):
+    """Adds Mox cleanup code to any MoxTestBase method.
+
+    Always unsets stubs after a test. Will verify all mocks for tests that
+    otherwise pass.
+
+    Args:
+      cls: MoxTestBase or subclass; the class whose test method we are altering.
+      func: method; the method of the MoxTestBase test class we wish to alter.
+
+    Returns:
+      The modified method.
+    """
+    def new_method(self, *args, **kwargs):
+      mox_obj = getattr(self, 'mox', None)
+      cleanup_mox = False
+      if mox_obj and isinstance(mox_obj, Mox):
+        cleanup_mox = True
+      try:
+        func(self, *args, **kwargs)
+      finally:
+        if cleanup_mox:
+          mox_obj.UnsetStubs()
+      if cleanup_mox:
+        mox_obj.VerifyAll()
+    new_method.__name__ = func.__name__
+    new_method.__doc__ = func.__doc__
+    new_method.__module__ = func.__module__
+    return new_method
+
+
+class MoxTestBase(unittest.TestCase):
+  """Convenience test class to make stubbing easier.
+
+  Sets up a "mox" attribute which is an instance of Mox - any mox tests will
+  want this. Also automatically unsets any stubs and verifies that all mock
+  methods have been called at the end of each test, eliminating boilerplate
+  code.
+  """
+
+  __metaclass__ = MoxMetaTestBase
+
+  def setUp(self):
+    self.mox = Mox()
diff --git a/src/third_party/protobuf-3/python/setup.py b/src/third_party/protobuf-3/python/setup.py
new file mode 100755
index 0000000..0f4b53c
--- /dev/null
+++ b/src/third_party/protobuf-3/python/setup.py
@@ -0,0 +1,250 @@
+#! /usr/bin/env python
+#
+# See README for usage instructions.
+import glob
+import os
+import subprocess
+import sys
+
+# We must use setuptools, not distutils, because we need to use the
+# namespace_packages option for the "google" package.
+from setuptools import setup, Extension, find_packages
+
+from distutils.command.clean import clean as _clean
+
+if sys.version_info[0] == 3:
+  # Python 3
+  from distutils.command.build_py import build_py_2to3 as _build_py
+else:
+  # Python 2
+  from distutils.command.build_py import build_py as _build_py
+from distutils.spawn import find_executable
+
+# Find the Protocol Compiler.
+if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
+  protoc = os.environ['PROTOC']
+elif os.path.exists("../src/protoc"):
+  protoc = "../src/protoc"
+elif os.path.exists("../src/protoc.exe"):
+  protoc = "../src/protoc.exe"
+elif os.path.exists("../vsprojects/Debug/protoc.exe"):
+  protoc = "../vsprojects/Debug/protoc.exe"
+elif os.path.exists("../vsprojects/Release/protoc.exe"):
+  protoc = "../vsprojects/Release/protoc.exe"
+else:
+  protoc = find_executable("protoc")
+
+
+def GetVersion():
+  """Gets the version from google/protobuf/__init__.py
+
+  Do not import google.protobuf.__init__ directly, because an installed
+  protobuf library may be loaded instead."""
+
+  with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
+    exec(version_file.read(), globals())
+    return __version__
+
+
+def generate_proto(source, require = True):
+  """Invokes the Protocol Compiler to generate a _pb2.py from the given
+  .proto file.  Does nothing if the output already exists and is newer than
+  the input."""
+
+  if not require and not os.path.exists(source):
+    return
+
+  output = source.replace(".proto", "_pb2.py").replace("../src/", "")
+
+  if (not os.path.exists(output) or
+      (os.path.exists(source) and
+       os.path.getmtime(source) > os.path.getmtime(output))):
+    print("Generating %s..." % output)
+
+    if not os.path.exists(source):
+      sys.stderr.write("Can't find required file: %s\n" % source)
+      sys.exit(-1)
+
+    if protoc is None:
+      sys.stderr.write(
+          "protoc is not installed nor found in ../src.  Please compile it "
+          "or install the binary package.\n")
+      sys.exit(-1)
+
+    protoc_command = [ protoc, "-I../src", "-I.", "--python_out=.", source ]
+    if subprocess.call(protoc_command) != 0:
+      sys.exit(-1)
+
+def GenerateUnittestProtos():
+  generate_proto("../src/google/protobuf/map_unittest.proto", False)
+  generate_proto("../src/google/protobuf/unittest_arena.proto", False)
+  generate_proto("../src/google/protobuf/unittest_no_arena.proto", False)
+  generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False)
+  generate_proto("../src/google/protobuf/unittest.proto", False)
+  generate_proto("../src/google/protobuf/unittest_custom_options.proto", False)
+  generate_proto("../src/google/protobuf/unittest_import.proto", False)
+  generate_proto("../src/google/protobuf/unittest_import_public.proto", False)
+  generate_proto("../src/google/protobuf/unittest_mset.proto", False)
+  generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False)
+  generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False)
+  generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False)
+  generate_proto("../src/google/protobuf/util/json_format_proto3.proto", False)
+  generate_proto("google/protobuf/internal/any_test.proto", False)
+  generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False)
+  generate_proto("google/protobuf/internal/descriptor_pool_test2.proto", False)
+  generate_proto("google/protobuf/internal/factory_test1.proto", False)
+  generate_proto("google/protobuf/internal/factory_test2.proto", False)
+  generate_proto("google/protobuf/internal/import_test_package/inner.proto", False)
+  generate_proto("google/protobuf/internal/import_test_package/outer.proto", False)
+  generate_proto("google/protobuf/internal/missing_enum_values.proto", False)
+  generate_proto("google/protobuf/internal/message_set_extensions.proto", False)
+  generate_proto("google/protobuf/internal/more_extensions.proto", False)
+  generate_proto("google/protobuf/internal/more_extensions_dynamic.proto", False)
+  generate_proto("google/protobuf/internal/more_messages.proto", False)
+  generate_proto("google/protobuf/internal/packed_field_test.proto", False)
+  generate_proto("google/protobuf/internal/test_bad_identifiers.proto", False)
+  generate_proto("google/protobuf/pyext/python.proto", False)
+
+
+class clean(_clean):
+  def run(self):
+    # Delete generated files in the code tree.
+    for (dirpath, dirnames, filenames) in os.walk("."):
+      for filename in filenames:
+        filepath = os.path.join(dirpath, filename)
+        if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
+          filepath.endswith(".so") or filepath.endswith(".o") or \
+          filepath.endswith('google/protobuf/compiler/__init__.py') or \
+          filepath.endswith('google/protobuf/util/__init__.py'):
+          os.remove(filepath)
+    # _clean is an old-style class, so super() doesn't work.
+    _clean.run(self)
+
+class build_py(_build_py):
+  def run(self):
+    # Generate necessary .proto file if it doesn't exist.
+    generate_proto("../src/google/protobuf/descriptor.proto")
+    generate_proto("../src/google/protobuf/compiler/plugin.proto")
+    generate_proto("../src/google/protobuf/any.proto")
+    generate_proto("../src/google/protobuf/api.proto")
+    generate_proto("../src/google/protobuf/duration.proto")
+    generate_proto("../src/google/protobuf/empty.proto")
+    generate_proto("../src/google/protobuf/field_mask.proto")
+    generate_proto("../src/google/protobuf/source_context.proto")
+    generate_proto("../src/google/protobuf/struct.proto")
+    generate_proto("../src/google/protobuf/timestamp.proto")
+    generate_proto("../src/google/protobuf/type.proto")
+    generate_proto("../src/google/protobuf/wrappers.proto")
+    GenerateUnittestProtos()
+
+    # Make sure google.protobuf/** are valid packages.
+    for path in ['', 'internal/', 'compiler/', 'pyext/', 'util/']:
+      try:
+        open('google/protobuf/%s__init__.py' % path, 'a').close()
+      except EnvironmentError:
+        pass
+    # _build_py is an old-style class, so super() doesn't work.
+    _build_py.run(self)
+
+class test_conformance(_build_py):
+  target = 'test_python'
+  def run(self):
+    if sys.version_info >= (2, 7):
+      # Python 2.6 dodges these extra failures.
+      os.environ["CONFORMANCE_PYTHON_EXTRA_FAILURES"] = (
+          "--failure_list failure_list_python-post26.txt")
+    cmd = 'cd ../conformance && make %s' % (test_conformance.target)
+    status = subprocess.check_call(cmd, shell=True)
+
+
+def get_option_from_sys_argv(option_str):
+  if option_str in sys.argv:
+    sys.argv.remove(option_str)
+    return True
+  return False
+
+
+if __name__ == '__main__':
+  ext_module_list = []
+  warnings_as_errors = '--warnings_as_errors'
+  if get_option_from_sys_argv('--cpp_implementation'):
+    # Link libprotobuf.a and libprotobuf-lite.a statically with the
+    # extension. Note that those libraries have to be compiled with
+    # -fPIC for this to work.
+    compile_static_ext = get_option_from_sys_argv('--compile_static_extension')
+    extra_compile_args = ['-Wno-write-strings',
+                          '-Wno-invalid-offsetof',
+                          '-Wno-sign-compare']
+    libraries = ['protobuf']
+    extra_objects = None
+    if compile_static_ext:
+      libraries = None
+      extra_objects = ['../src/.libs/libprotobuf.a',
+                       '../src/.libs/libprotobuf-lite.a']
+    test_conformance.target = 'test_python_cpp'
+
+    if "clang" in os.popen('$CC --version 2> /dev/null').read():
+      extra_compile_args.append('-Wno-shorten-64-to-32')
+
+    if warnings_as_errors in sys.argv:
+      extra_compile_args.append('-Werror')
+      sys.argv.remove(warnings_as_errors)
+
+    # C++ implementation extension
+    ext_module_list.extend([
+        Extension(
+            "google.protobuf.pyext._message",
+            glob.glob('google/protobuf/pyext/*.cc'),
+            include_dirs=[".", "../src"],
+            libraries=libraries,
+            extra_objects=extra_objects,
+            library_dirs=['../src/.libs'],
+            extra_compile_args=extra_compile_args,
+        ),
+        Extension(
+            "google.protobuf.internal._api_implementation",
+            glob.glob('google/protobuf/internal/api_implementation.cc'),
+            extra_compile_args=['-DPYTHON_PROTO2_CPP_IMPL_V2'],
+        ),
+    ])
+    os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
+
+  # Keep this list of dependencies in sync with tox.ini.
+  install_requires = ['six>=1.9', 'setuptools']
+  if sys.version_info <= (2,7):
+    install_requires.append('ordereddict')
+    install_requires.append('unittest2')
+
+  setup(
+      name='protobuf',
+      version=GetVersion(),
+      description='Protocol Buffers',
+      long_description="Protocol Buffers are Google's data interchange format",
+      url='https://developers.google.com/protocol-buffers/',
+      maintainer='protobuf@googlegroups.com',
+      maintainer_email='protobuf@googlegroups.com',
+      license='New BSD License',
+      classifiers=[
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.6",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
+        "Programming Language :: Python :: 3.4",
+        ],
+      namespace_packages=['google'],
+      packages=find_packages(
+          exclude=[
+              'import_test_package',
+          ],
+      ),
+      test_suite='google.protobuf.internal',
+      cmdclass={
+          'clean': clean,
+          'build_py': build_py,
+          'test_conformance': test_conformance,
+      },
+      install_requires=install_requires,
+      ext_modules=ext_module_list,
+  )
diff --git a/src/third_party/protobuf-3/python/stubout.py b/src/third_party/protobuf-3/python/stubout.py
new file mode 100755
index 0000000..aee4f2d
--- /dev/null
+++ b/src/third_party/protobuf-3/python/stubout.py
@@ -0,0 +1,140 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is used for testing.  The original is at:
+#   http://code.google.com/p/pymox/
+
+class StubOutForTesting:
+  """Sample Usage:
+     You want os.path.exists() to always return true during testing.
+
+     stubs = StubOutForTesting()
+     stubs.Set(os.path, 'exists', lambda x: 1)
+       ...
+     stubs.UnsetAll()
+
+     The above changes os.path.exists into a lambda that returns 1.  Once
+     the ... part of the code finishes, the UnsetAll() looks up the old value
+     of os.path.exists and restores it.
+
+  """
+  def __init__(self):
+    self.cache = []
+    self.stubs = []
+
+  def __del__(self):
+    self.SmartUnsetAll()
+    self.UnsetAll()
+
+  def SmartSet(self, obj, attr_name, new_attr):
+    """Replace obj.attr_name with new_attr. This method is smart and works
+       at the module, class, and instance level while preserving proper
+       inheritance. It will not stub out C types however unless that has been
+       explicitly allowed by the type.
+
+       This method supports the case where attr_name is a staticmethod or a
+       classmethod of obj.
+
+       Notes:
+      - If obj is an instance, then it is its class that will actually be
+        stubbed. Note that the method Set() does not do that: if obj is
+        an instance, it (and not its class) will be stubbed.
+      - The stubbing is using the builtin getattr and setattr. So, the __get__
+        and __set__ will be called when stubbing (TODO: A better idea would
+        probably be to manipulate obj.__dict__ instead of getattr() and
+        setattr()).
+
+       Raises AttributeError if the attribute cannot be found.
+    """
+    if (inspect.ismodule(obj) or
+        (not inspect.isclass(obj) and obj.__dict__.has_key(attr_name))):
+      orig_obj = obj
+      orig_attr = getattr(obj, attr_name)
+
+    else:
+      if not inspect.isclass(obj):
+        mro = list(inspect.getmro(obj.__class__))
+      else:
+        mro = list(inspect.getmro(obj))
+
+      mro.reverse()
+
+      orig_attr = None
+
+      for cls in mro:
+        try:
+          orig_obj = cls
+          orig_attr = getattr(obj, attr_name)
+        except AttributeError:
+          continue
+
+    if orig_attr is None:
+      raise AttributeError("Attribute not found.")
+
+    # Calling getattr() on a staticmethod transforms it to a 'normal' function.
+    # We need to ensure that we put it back as a staticmethod.
+    old_attribute = obj.__dict__.get(attr_name)
+    if old_attribute is not None and isinstance(old_attribute, staticmethod):
+      orig_attr = staticmethod(orig_attr)
+
+    self.stubs.append((orig_obj, attr_name, orig_attr))
+    setattr(orig_obj, attr_name, new_attr)
+
+  def SmartUnsetAll(self):
+    """Reverses all the SmartSet() calls, restoring things to their original
+    definition.  Its okay to call SmartUnsetAll() repeatedly, as later calls
+    have no effect if no SmartSet() calls have been made.
+
+    """
+    self.stubs.reverse()
+
+    for args in self.stubs:
+      setattr(*args)
+
+    self.stubs = []
+
+  def Set(self, parent, child_name, new_child):
+    """Replace child_name's old definition with new_child, in the context
+    of the given parent.  The parent could be a module when the child is a
+    function at module scope.  Or the parent could be a class when a class'
+    method is being replaced.  The named child is set to new_child, while
+    the prior definition is saved away for later, when UnsetAll() is called.
+
+    This method supports the case where child_name is a staticmethod or a
+    classmethod of parent.
+    """
+    old_child = getattr(parent, child_name)
+
+    old_attribute = parent.__dict__.get(child_name)
+    if old_attribute is not None and isinstance(old_attribute, staticmethod):
+      old_child = staticmethod(old_child)
+
+    self.cache.append((parent, old_child, child_name))
+    setattr(parent, child_name, new_child)
+
+  def UnsetAll(self):
+    """Reverses all the Set() calls, restoring things to their original
+    definition.  Its okay to call UnsetAll() repeatedly, as later calls have
+    no effect if no Set() calls have been made.
+
+    """
+    # Undo calls to Set() in reverse order, in case Set() was called on the
+    # same arguments repeatedly (want the original call to be last one undone)
+    self.cache.reverse()
+
+    for (parent, old_child, child_name) in self.cache:
+      setattr(parent, child_name, old_child)
+    self.cache = []
diff --git a/src/third_party/protobuf-3/python/tox.ini b/src/third_party/protobuf-3/python/tox.ini
new file mode 100644
index 0000000..cf8d540
--- /dev/null
+++ b/src/third_party/protobuf-3/python/tox.ini
@@ -0,0 +1,24 @@
+[tox]
+envlist =
+    py{26,27,33,34}-{cpp,python}
+
+[testenv]
+usedevelop=true
+passenv = CC
+setenv =
+    cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
+    cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs
+    cpp: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+commands =
+    python setup.py -q build_py
+    python: python setup.py -q build
+    cpp: python setup.py -q build --cpp_implementation --warnings_as_errors
+    python: python setup.py -q test -q
+    cpp: python setup.py -q test -q --cpp_implementation
+    python: python setup.py -q test_conformance
+    cpp: python setup.py -q test_conformance --cpp_implementation
+deps =
+    # Keep this list of dependencies in sync with setup.py.
+    six>=1.9
+    py26: ordereddict
+    py26: unittest2
diff --git a/src/third_party/protobuf-3/ruby/Gemfile b/src/third_party/protobuf-3/ruby/Gemfile
new file mode 100644
index 0000000..fa75df1
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/src/third_party/protobuf-3/ruby/Gemfile.lock b/src/third_party/protobuf-3/ruby/Gemfile.lock
new file mode 100644
index 0000000..d0eb9cc
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/Gemfile.lock
@@ -0,0 +1,30 @@
+PATH
+  remote: .
+  specs:
+    google-protobuf (3.0.0.alpha.5.0.5)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    power_assert (0.2.2)
+    rake (10.4.2)
+    rake-compiler (0.9.5)
+      rake
+    rake-compiler-dock (0.5.1)
+    rubygems-tasks (0.2.4)
+    test-unit (3.0.9)
+      power_assert
+
+PLATFORMS
+  java
+  ruby
+
+DEPENDENCIES
+  google-protobuf!
+  rake-compiler
+  rake-compiler-dock
+  rubygems-tasks
+  test-unit
+
+BUNDLED WITH
+   1.11.2
diff --git a/src/third_party/protobuf-3/ruby/README.md b/src/third_party/protobuf-3/ruby/README.md
new file mode 100644
index 0000000..f28e05a
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/README.md
@@ -0,0 +1,114 @@
+This directory contains the Ruby extension that implements Protocol Buffers
+functionality in Ruby.
+
+The Ruby extension makes use of generated Ruby code that defines message and
+enum types in a Ruby DSL. You may write definitions in this DSL directly, but
+we recommend using protoc's Ruby generation support with .proto files. The
+build process in this directory only installs the extension; you need to
+install protoc as well to have Ruby code generation functionality.
+
+Installation from Gem
+---------------------
+
+When we release a version of Protocol Buffers, we will upload a Gem to
+[RubyGems](https://www.rubygems.org/). To use this pre-packaged gem, simply
+install it as you would any other gem:
+
+    $ gem install [--prerelease] google-protobuf
+
+The `--pre` flag is necessary if we have not yet made a non-alpha/beta release
+of the Ruby extension; it allows `gem` to consider these "pre-release"
+alpha/beta versions.
+
+Once the gem is installed, you may or may not need `protoc`. If you write your
+message type descriptions directly in the Ruby DSL, you do not need it.
+However, if you wish to generate the Ruby DSL from a `.proto` file, you will
+also want to install Protocol Buffers itself, as described in this repository's
+main `README` file. The version of `protoc` included in the latest release
+supports the `--ruby_out` option to generate Ruby code.
+
+A simple example of using the Ruby extension follows. More extensive
+documentation may be found in the RubyDoc comments (`call-seq` tags) in the
+source, and we plan to release separate, more detailed, documentation at a
+later date.
+
+```ruby
+require 'google/protobuf'
+
+# generated from my_proto_types.proto with protoc:
+#  $ protoc --ruby_out=. my_proto_types.proto
+require 'my_proto_types'
+
+mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"])
+mymessage.field1 = 43
+mymessage.field2.push("d")
+mymessage.field3 = SubMessage.new(:foo => 100)
+
+encoded_data = MyTestMessage.encode(mymessage)
+decoded = MyTestMessage.decode(encoded_data)
+assert decoded == mymessage
+
+puts "JSON:"
+puts MyTestMessage.encode_json(mymessage)
+```
+
+Installation from Source (Building Gem)
+---------------------------------------
+
+To build this Ruby extension, you will need:
+
+* Rake
+* Bundler
+* Ruby development headers
+* a C compiler
+
+To Build the JRuby extension, you will need:
+
+* Maven
+* The latest version of the protobuf java library (see ../java/README.md)
+* Install JRuby via rbenv or RVM
+
+First switch to the desired platform with rbenv or RVM.
+
+Then install the required Ruby gems:
+
+    $ gem install bundler
+    $ bundle
+
+Then build the Gem:
+
+    $ rake
+    $ rake clobber_package gem
+    $ gem install `ls pkg/google-protobuf-*.gem`
+
+To run the specs:
+
+    $ rake test
+
+This gem includes the upb parsing and serialization library as a single-file
+amalgamation. It is up-to-date with upb git commit
+`535bc2fe2f2b467f59347ffc9449e11e47791257`.
+
+Version Number Scheme
+---------------------
+
+We are using a version number scheme that is a hybrid of Protocol Buffers'
+overall version number and some Ruby-specific rules. Gem does not allow
+re-uploads of a gem with the same version number, so we add a sequence number
+("upload version") to the version. We also format alphabetical tags (alpha,
+pre, ...) slightly differently, and we avoid hyphens. In more detail:
+
+* First, we determine the prefix: a Protocol Buffers version "3.0.0-alpha-2"
+  becomes "3.0.0.alpha.2". When we release 3.0.0, this prefix will be simply
+  "3.0.0".
+* We then append the upload version: "3.0.0.alpha.2.0" or "3.0.0.0". If we need
+  to upload a new version of the gem to fix an issue, the version becomes
+  "3.0.0.alpha.2.1" or "3.0.0.1".
+* If we are working on a prerelease version, we append a prerelease tag:
+  "3.0.0.alpha.3.0.pre". The prerelease tag comes at the end so that when
+  version numbers are sorted, any prerelease builds are ordered between the
+  prior version and current version.
+
+These rules are designed to work with the sorting rules for
+[Gem::Version](http://ruby-doc.org/stdlib-2.0/libdoc/rubygems/rdoc/Gem/Version.html):
+release numbers should sort in actual release order.
diff --git a/src/third_party/protobuf-3/ruby/Rakefile b/src/third_party/protobuf-3/ruby/Rakefile
new file mode 100644
index 0000000..fa29c31
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/Rakefile
@@ -0,0 +1,103 @@
+require "rubygems"
+require "rubygems/package_task"
+require "rake/extensiontask" unless RUBY_PLATFORM == "java"
+require "rake/testtask"
+
+spec = Gem::Specification.load("google-protobuf.gemspec")
+
+well_known_protos = %w[
+  google/protobuf/any.proto
+  google/protobuf/api.proto
+  google/protobuf/duration.proto
+  google/protobuf/empty.proto
+  google/protobuf/field_mask.proto
+  google/protobuf/source_context.proto
+  google/protobuf/struct.proto
+  google/protobuf/timestamp.proto
+  google/protobuf/type.proto
+  google/protobuf/wrappers.proto
+]
+
+# These are omitted for now because we don't support proto2.
+proto2_protos = %w[
+  google/protobuf/descriptor.proto
+  google/protobuf/compiler/plugin.proto
+]
+
+genproto_output = []
+
+# We won't have access to .. from within docker, but the proto files
+# will be there, thanks to the :genproto rule dependency for gem:native.
+unless ENV['IN_DOCKER'] == 'true'
+  well_known_protos.each do |proto_file|
+    input_file = "../src/" + proto_file
+    output_file = "lib/" + proto_file.sub(/\.proto$/, ".rb")
+    genproto_output << output_file
+    file output_file => input_file do |file_task|
+      sh "../src/protoc -I../src --ruby_out=lib #{input_file}"
+    end
+  end
+end
+
+if RUBY_PLATFORM == "java"
+  if `which mvn` == ''
+    raise ArgumentError, "maven needs to be installed"
+  end
+  task :clean do
+    system("mvn clean")
+  end
+
+  task :compile do
+    system("mvn package")
+  end
+else
+  Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
+    ext.ext_dir = "ext/google/protobuf_c"
+    ext.lib_dir = "lib/google"
+    ext.cross_compile = true
+    ext.cross_platform = [
+      'x86-mingw32', 'x64-mingw32',
+      'x86_64-linux', 'x86-linux',
+      'universal-darwin'
+    ]
+  end
+
+  task 'gem:windows' do
+    require 'rake_compiler_dock'
+    RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0"
+  end
+
+  if RUBY_PLATFORM =~ /darwin/
+    task 'gem:native' do
+      system "rake genproto"
+      system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0"
+    end
+  else
+    task 'gem:native' => [:genproto, 'gem:windows']
+  end
+end
+
+
+# Proto for tests.
+genproto_output << "tests/generated_code.rb"
+file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
+  sh "../src/protoc --ruby_out=. tests/generated_code.proto"
+end
+
+task :genproto => genproto_output
+
+task :clean do
+  sh "rm -f #{genproto_output.join(' ')}"
+end
+
+Gem::PackageTask.new(spec) do |pkg|
+end
+
+Rake::TestTask.new(:test => :build) do |t|
+  t.test_files = FileList["tests/*.rb"]
+end
+
+task :build => [:clean, :compile, :genproto]
+task :default => [:build]
+
+# vim:sw=2:et
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/defs.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/defs.c
new file mode 100644
index 0000000..7e93baf
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/defs.c
@@ -0,0 +1,1763 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Common utilities.
+// -----------------------------------------------------------------------------
+
+static const char* get_str(VALUE str) {
+  Check_Type(str, T_STRING);
+  return RSTRING_PTR(str);
+}
+
+static VALUE rb_str_maybe_null(const char* s) {
+  if (s == NULL) {
+    s = "";
+  }
+  return rb_str_new2(s);
+}
+
+static upb_def* check_notfrozen(const upb_def* def) {
+  if (upb_def_isfrozen(def)) {
+    rb_raise(rb_eRuntimeError,
+             "Attempt to modify a frozen descriptor. Once descriptors are "
+             "added to the descriptor pool, they may not be modified.");
+  }
+  return (upb_def*)def;
+}
+
+static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
+  return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def));
+}
+
+static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
+  return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def));
+}
+
+static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) {
+  return (upb_oneofdef*)check_notfrozen((const upb_def*)def);
+}
+
+static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
+  return (upb_enumdef*)check_notfrozen((const upb_def*)def);
+}
+
+// -----------------------------------------------------------------------------
+// DescriptorPool.
+// -----------------------------------------------------------------------------
+
+#define DEFINE_CLASS(name, string_name)                             \
+    VALUE c ## name;                                                \
+    const rb_data_type_t _ ## name ## _type = {                     \
+      string_name,                                                  \
+      { name ## _mark, name ## _free, NULL },                       \
+    };                                                              \
+    name* ruby_to_ ## name(VALUE val) {                             \
+      name* ret;                                                    \
+      TypedData_Get_Struct(val, name, &_ ## name ## _type, ret);    \
+      return ret;                                                   \
+    }                                                               \
+
+#define DEFINE_SELF(type, var, rb_var)                              \
+    type* var = ruby_to_ ## type(rb_var)
+
+// Global singleton DescriptorPool. The user is free to create others, but this
+// is used by generated code.
+VALUE generated_pool;
+
+DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
+
+void DescriptorPool_mark(void* _self) {
+}
+
+void DescriptorPool_free(void* _self) {
+  DescriptorPool* self = _self;
+  upb_symtab_unref(self->symtab, &self->symtab);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.new => pool
+ *
+ * Creates a new, empty, descriptor pool.
+ */
+VALUE DescriptorPool_alloc(VALUE klass) {
+  DescriptorPool* self = ALLOC(DescriptorPool);
+  self->symtab = upb_symtab_new(&self->symtab);
+  return TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
+}
+
+void DescriptorPool_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "DescriptorPool", rb_cObject);
+  rb_define_alloc_func(klass, DescriptorPool_alloc);
+  rb_define_method(klass, "add", DescriptorPool_add, 1);
+  rb_define_method(klass, "build", DescriptorPool_build, 0);
+  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
+  rb_define_singleton_method(klass, "generated_pool",
+                             DescriptorPool_generated_pool, 0);
+  cDescriptorPool = klass;
+  rb_gc_register_address(&cDescriptorPool);
+
+  generated_pool = rb_class_new_instance(0, NULL, klass);
+  rb_gc_register_address(&generated_pool);
+}
+
+static void add_descriptor_to_pool(DescriptorPool* self,
+                                   Descriptor* descriptor) {
+  CHECK_UPB(
+      upb_symtab_add(self->symtab, (upb_def**)&descriptor->msgdef, 1,
+                     NULL, &status),
+      "Adding Descriptor to DescriptorPool failed");
+}
+
+static void add_enumdesc_to_pool(DescriptorPool* self,
+                                 EnumDescriptor* enumdesc) {
+  CHECK_UPB(
+      upb_symtab_add(self->symtab, (upb_def**)&enumdesc->enumdef, 1,
+                     NULL, &status),
+      "Adding EnumDescriptor to DescriptorPool failed");
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.add(descriptor)
+ *
+ * Adds the given Descriptor or EnumDescriptor to this pool. All references to
+ * other types in a Descriptor's fields must be resolvable within this pool or
+ * an exception will be raised.
+ */
+VALUE DescriptorPool_add(VALUE _self, VALUE def) {
+  DEFINE_SELF(DescriptorPool, self, _self);
+  VALUE def_klass = rb_obj_class(def);
+  if (def_klass == cDescriptor) {
+    add_descriptor_to_pool(self, ruby_to_Descriptor(def));
+  } else if (def_klass == cEnumDescriptor) {
+    add_enumdesc_to_pool(self, ruby_to_EnumDescriptor(def));
+  } else {
+    rb_raise(rb_eArgError,
+             "Second argument must be a Descriptor or EnumDescriptor.");
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.build(&block)
+ *
+ * Invokes the block with a Builder instance as self. All message and enum types
+ * added within the block are committed to the pool atomically, and may refer
+ * (co)recursively to each other. The user should call Builder#add_message and
+ * Builder#add_enum within the block as appropriate.  This is the recommended,
+ * idiomatic way to define new message and enum types.
+ */
+VALUE DescriptorPool_build(VALUE _self) {
+  VALUE ctx = rb_class_new_instance(0, NULL, cBuilder);
+  VALUE block = rb_block_proc();
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  rb_funcall(ctx, rb_intern("finalize_to_pool"), 1, _self);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.lookup(name) => descriptor
+ *
+ * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
+ * exists with the given name.
+ */
+VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
+  DEFINE_SELF(DescriptorPool, self, _self);
+  const char* name_str = get_str(name);
+  const upb_def* def = upb_symtab_lookup(self->symtab, name_str);
+  if (!def) {
+    return Qnil;
+  }
+  return get_def_obj(def);
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.generated_pool => descriptor_pool
+ *
+ * Class method that returns the global DescriptorPool. This is a singleton into
+ * which generated-code message and enum types are registered. The user may also
+ * register types in this pool for convenience so that they do not have to hold
+ * a reference to a private pool instance.
+ */
+VALUE DescriptorPool_generated_pool(VALUE _self) {
+  return generated_pool;
+}
+
+// -----------------------------------------------------------------------------
+// Descriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
+
+void Descriptor_mark(void* _self) {
+  Descriptor* self = _self;
+  rb_gc_mark(self->klass);
+  rb_gc_mark(self->typeclass_references);
+}
+
+void Descriptor_free(void* _self) {
+  Descriptor* self = _self;
+  upb_msgdef_unref(self->msgdef, &self->msgdef);
+  if (self->layout) {
+    free_layout(self->layout);
+  }
+  if (self->fill_handlers) {
+    upb_handlers_unref(self->fill_handlers, &self->fill_handlers);
+  }
+  if (self->fill_method) {
+    upb_pbdecodermethod_unref(self->fill_method, &self->fill_method);
+  }
+  if (self->json_fill_method) {
+    upb_json_parsermethod_unref(self->json_fill_method,
+                                &self->json_fill_method);
+  }
+  if (self->pb_serialize_handlers) {
+    upb_handlers_unref(self->pb_serialize_handlers,
+                       &self->pb_serialize_handlers);
+  }
+  if (self->json_serialize_handlers) {
+    upb_handlers_unref(self->json_serialize_handlers,
+                       &self->json_serialize_handlers);
+  }
+  if (self->json_serialize_handlers_preserve) {
+    upb_handlers_unref(self->json_serialize_handlers_preserve,
+                       &self->json_serialize_handlers_preserve);
+  }
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.new => descriptor
+ *
+ * Creates a new, empty, message type descriptor. At a minimum, its name must be
+ * set before it is added to a pool. It cannot be used to create messages until
+ * it is added to a pool, after which it becomes immutable (as part of a
+ * finalization process).
+ */
+VALUE Descriptor_alloc(VALUE klass) {
+  Descriptor* self = ALLOC(Descriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
+  self->msgdef = upb_msgdef_new(&self->msgdef);
+  self->klass = Qnil;
+  self->layout = NULL;
+  self->fill_handlers = NULL;
+  self->fill_method = NULL;
+  self->json_fill_method = NULL;
+  self->pb_serialize_handlers = NULL;
+  self->json_serialize_handlers = NULL;
+  self->json_serialize_handlers_preserve = NULL;
+  self->typeclass_references = rb_ary_new();
+  return ret;
+}
+
+void Descriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "Descriptor", rb_cObject);
+  rb_define_alloc_func(klass, Descriptor_alloc);
+  rb_define_method(klass, "each", Descriptor_each, 0);
+  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
+  rb_define_method(klass, "add_field", Descriptor_add_field, 1);
+  rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1);
+  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
+  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
+  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
+  rb_define_method(klass, "name", Descriptor_name, 0);
+  rb_define_method(klass, "name=", Descriptor_name_set, 1);
+  rb_include_module(klass, rb_mEnumerable);
+  cDescriptor = klass;
+  rb_gc_register_address(&cDescriptor);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.name => name
+ *
+ * Returns the name of this message type as a fully-qualfied string (e.g.,
+ * My.Package.MessageType).
+ */
+VALUE Descriptor_name(VALUE _self) {
+  DEFINE_SELF(Descriptor, self, _self);
+  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
+}
+
+/*
+ * call-seq:
+ *    Descriptor.name = name
+ *
+ * Assigns a name to this message type. The descriptor must not have been added
+ * to a pool yet.
+ */
+VALUE Descriptor_name_set(VALUE _self, VALUE str) {
+  DEFINE_SELF(Descriptor, self, _self);
+  upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+  const char* name = get_str(str);
+  CHECK_UPB(
+      upb_msgdef_setfullname(mut_def, name, &status),
+      "Error setting Descriptor name");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each(&block)
+ *
+ * Iterates over fields in this message type, yielding to the block on each one.
+ */
+VALUE Descriptor_each(VALUE _self) {
+  DEFINE_SELF(Descriptor, self, _self);
+
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, self->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE obj = get_def_obj(field);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup(name) => FieldDescriptor
+ *
+ * Returns the field descriptor for the field with the given name, if present,
+ * or nil if none.
+ */
+VALUE Descriptor_lookup(VALUE _self, VALUE name) {
+  DEFINE_SELF(Descriptor, self, _self);
+  const char* s = get_str(name);
+  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
+  if (field == NULL) {
+    return Qnil;
+  }
+  return get_def_obj(field);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.add_field(field) => nil
+ *
+ * Adds the given FieldDescriptor to this message type. This descriptor must not
+ * have been added to a pool yet. Raises an exception if a field with the same
+ * name or number already exists. Sub-type references (e.g. for fields of type
+ * message) are not resolved at this point.
+ */
+VALUE Descriptor_add_field(VALUE _self, VALUE obj) {
+  DEFINE_SELF(Descriptor, self, _self);
+  upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+  FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
+  upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
+  CHECK_UPB(
+      upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
+      "Adding field to Descriptor failed");
+  add_def_obj(def->fielddef, obj);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.add_oneof(oneof) => nil
+ *
+ * Adds the given OneofDescriptor to this message type. This descriptor must not
+ * have been added to a pool yet. Raises an exception if a oneof with the same
+ * name already exists, or if any of the oneof's fields' names or numbers
+ * conflict with an existing field in this message type. All fields in the oneof
+ * are added to the message descriptor. Sub-type references (e.g. for fields of
+ * type message) are not resolved at this point.
+ */
+VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
+  DEFINE_SELF(Descriptor, self, _self);
+  upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+  OneofDescriptor* def = ruby_to_OneofDescriptor(obj);
+  upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef);
+  CHECK_UPB(
+      upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status),
+      "Adding oneof to Descriptor failed");
+  add_def_obj(def->oneofdef, obj);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each_oneof(&block) => nil
+ *
+ * Invokes the given block for each oneof in this message type, passing the
+ * corresponding OneofDescriptor.
+ */
+VALUE Descriptor_each_oneof(VALUE _self) {
+  DEFINE_SELF(Descriptor, self, _self);
+
+  upb_msg_oneof_iter it;
+  for (upb_msg_oneof_begin(&it, self->msgdef);
+       !upb_msg_oneof_done(&it);
+       upb_msg_oneof_next(&it)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
+    VALUE obj = get_def_obj(oneof);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup_oneof(name) => OneofDescriptor
+ *
+ * Returns the oneof descriptor for the oneof with the given name, if present,
+ * or nil if none.
+ */
+VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
+  DEFINE_SELF(Descriptor, self, _self);
+  const char* s = get_str(name);
+  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
+  if (oneof == NULL) {
+    return Qnil;
+  }
+  return get_def_obj(oneof);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.msgclass => message_klass
+ *
+ * Returns the Ruby class created for this message type. Valid only once the
+ * message type has been added to a pool.
+ */
+VALUE Descriptor_msgclass(VALUE _self) {
+  DEFINE_SELF(Descriptor, self, _self);
+  if (!upb_def_isfrozen((const upb_def*)self->msgdef)) {
+    rb_raise(rb_eRuntimeError,
+             "Cannot fetch message class from a Descriptor not yet in a pool.");
+  }
+  if (self->klass == Qnil) {
+    self->klass = build_class_from_descriptor(self);
+  }
+  return self->klass;
+}
+
+// -----------------------------------------------------------------------------
+// FieldDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
+
+void FieldDescriptor_mark(void* _self) {
+}
+
+void FieldDescriptor_free(void* _self) {
+  FieldDescriptor* self = _self;
+  upb_fielddef_unref(self->fielddef, &self->fielddef);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+VALUE FieldDescriptor_alloc(VALUE klass) {
+  FieldDescriptor* self = ALLOC(FieldDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
+  upb_fielddef* fielddef = upb_fielddef_new(&self->fielddef);
+  upb_fielddef_setpacked(fielddef, false);
+  self->fielddef = fielddef;
+  return ret;
+}
+
+void FieldDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "FieldDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, FieldDescriptor_alloc);
+  rb_define_method(klass, "name", FieldDescriptor_name, 0);
+  rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
+  rb_define_method(klass, "type", FieldDescriptor_type, 0);
+  rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
+  rb_define_method(klass, "label", FieldDescriptor_label, 0);
+  rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
+  rb_define_method(klass, "number", FieldDescriptor_number, 0);
+  rb_define_method(klass, "number=", FieldDescriptor_number_set, 1);
+  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
+  rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
+  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
+  rb_define_method(klass, "get", FieldDescriptor_get, 1);
+  rb_define_method(klass, "set", FieldDescriptor_set, 2);
+  cFieldDescriptor = klass;
+  rb_gc_register_address(&cFieldDescriptor);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+VALUE FieldDescriptor_name(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.name = name
+ *
+ * Sets the name of this field. Cannot be called once the containing message
+ * type, if any, is added to a pool.
+ */
+VALUE FieldDescriptor_name_set(VALUE _self, VALUE str) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+  const char* name = get_str(str);
+  CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
+            "Error setting FieldDescriptor name");
+  return Qnil;
+}
+
+upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_TYPE_ ## upb;                                         \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
+  switch (type) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
+    CONVERT(FLOAT, float);
+    CONVERT(DOUBLE, double);
+    CONVERT(BOOL, bool);
+    CONVERT(STRING, string);
+    CONVERT(BYTES, bytes);
+    CONVERT(MESSAGE, message);
+    CONVERT(ENUM, enum);
+    CONVERT(INT32, int32);
+    CONVERT(INT64, int64);
+    CONVERT(UINT32, uint32);
+    CONVERT(UINT64, uint64);
+#undef CONVERT
+  }
+  return Qnil;
+}
+
+upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_DESCRIPTOR_TYPE_ ## upb;                              \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(GROUP, group);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+  CONVERT(SINT32, sint32);
+  CONVERT(SINT64, sint64);
+  CONVERT(FIXED32, fixed32);
+  CONVERT(FIXED64, fixed64);
+  CONVERT(SFIXED32, sfixed32);
+  CONVERT(SFIXED64, sfixed64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
+  switch (type) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
+    CONVERT(FLOAT, float);
+    CONVERT(DOUBLE, double);
+    CONVERT(BOOL, bool);
+    CONVERT(STRING, string);
+    CONVERT(BYTES, bytes);
+    CONVERT(MESSAGE, message);
+    CONVERT(GROUP, group);
+    CONVERT(ENUM, enum);
+    CONVERT(INT32, int32);
+    CONVERT(INT64, int64);
+    CONVERT(UINT32, uint32);
+    CONVERT(UINT64, uint64);
+    CONVERT(SINT32, sint32);
+    CONVERT(SINT64, sint64);
+    CONVERT(FIXED32, fixed32);
+    CONVERT(FIXED64, fixed64);
+    CONVERT(SFIXED32, sfixed32);
+    CONVERT(SFIXED64, sfixed64);
+#undef CONVERT
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ *     :bytes, :message.
+ */
+VALUE FieldDescriptor_type(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  if (!upb_fielddef_typeisset(self->fielddef)) {
+    return Qnil;
+  }
+  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.type = type
+ *
+ * Sets this field's type. Cannot be called if field is part of a message type
+ * already in a pool.
+ */
+VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+  upb_fielddef_setdescriptortype(mut_def, ruby_to_descriptortype(type));
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.label => label
+ *
+ * Returns this field's label (i.e., plurality), as a Ruby symbol.
+ *
+ * Valid field labels are:
+ *     :optional, :repeated
+ */
+VALUE FieldDescriptor_label(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  switch (upb_fielddef_label(self->fielddef)) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
+
+    CONVERT(OPTIONAL, optional);
+    CONVERT(REQUIRED, required);
+    CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.label = label
+ *
+ * Sets the label on this field. Cannot be called if field is part of a message
+ * type already in a pool.
+ */
+VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+  upb_label_t upb_label = -1;
+  bool converted = false;
+
+  if (TYPE(label) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field label.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(label) == rb_intern( # ruby )) {                        \
+    upb_label = UPB_LABEL_ ## upb;                                   \
+    converted = true;                                                \
+  }
+
+  CONVERT(OPTIONAL, optional);
+  CONVERT(REQUIRED, required);
+  CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+
+  if (!converted) {
+    rb_raise(rb_eArgError, "Unknown field label.");
+  }
+
+  upb_fielddef_setlabel(mut_def, upb_label);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.number => number
+ *
+ * Returns the tag number for this field.
+ */
+VALUE FieldDescriptor_number(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  return INT2NUM(upb_fielddef_number(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.number = number
+ *
+ * Sets the tag number for this field. Cannot be called if field is part of a
+ * message type already in a pool.
+ */
+VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+  CHECK_UPB(upb_fielddef_setnumber(mut_def, NUM2INT(number), &status),
+            "Error setting field number");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.submsg_name => submsg_name
+ *
+ * Returns the name of the message or enum type corresponding to this field, if
+ * it is a message or enum field (respectively), or nil otherwise. This type
+ * name will be resolved within the context of the pool to which the containing
+ * message type is added.
+ */
+VALUE FieldDescriptor_submsg_name(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  if (!upb_fielddef_hassubdef(self->fielddef)) {
+    return Qnil;
+  }
+  return rb_str_maybe_null(upb_fielddef_subdefname(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.submsg_name = submsg_name
+ *
+ * Sets the name of the message or enum type corresponding to this field, if it
+ * is a message or enum field (respectively). This type name will be resolved
+ * within the context of the pool to which the containing message type is added.
+ * Cannot be called on field that are not of message or enum type, or on fields
+ * that are part of a message type already added to a pool.
+ */
+VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+  const char* str = get_str(value);
+  if (!upb_fielddef_hassubdef(self->fielddef)) {
+    rb_raise(rb_eTypeError, "FieldDescriptor does not have subdef.");
+  }
+  CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
+            "Error setting submessage name");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.subtype => message_or_enum_descriptor
+ *
+ * Returns the message or enum descriptor corresponding to this field's type if
+ * it is a message or enum field, respectively, or nil otherwise. Cannot be
+ * called *until* the containing message type is added to a pool (and thus
+ * resolved).
+ */
+VALUE FieldDescriptor_subtype(VALUE _self) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  const upb_def* def;
+
+  if (!upb_fielddef_hassubdef(self->fielddef)) {
+    return Qnil;
+  }
+  def = upb_fielddef_subdef(self->fielddef);
+  if (def == NULL) {
+    return Qnil;
+  }
+  return get_def_obj(def);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  MessageHeader* msg;
+  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(rb_eTypeError, "get method called on wrong message type");
+  }
+  return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
+  DEFINE_SELF(FieldDescriptor, self, _self);
+  MessageHeader* msg;
+  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(rb_eTypeError, "set method called on wrong message type");
+  }
+  layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
+  return Qnil;
+}
+
+// -----------------------------------------------------------------------------
+// OneofDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
+
+void OneofDescriptor_mark(void* _self) {
+}
+
+void OneofDescriptor_free(void* _self) {
+  OneofDescriptor* self = _self;
+  upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.new => oneof_descriptor
+ *
+ * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
+ * to being added to a message descriptor which is subsequently added to a pool.
+ */
+VALUE OneofDescriptor_alloc(VALUE klass) {
+  OneofDescriptor* self = ALLOC(OneofDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
+  self->oneofdef = upb_oneofdef_new(&self->oneofdef);
+  return ret;
+}
+
+void OneofDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, OneofDescriptor_alloc);
+  rb_define_method(klass, "name", OneofDescriptor_name, 0);
+  rb_define_method(klass, "name=", OneofDescriptor_name_set, 1);
+  rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
+  rb_define_method(klass, "each", OneofDescriptor_each, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  cOneofDescriptor = klass;
+  rb_gc_register_address(&cOneofDescriptor);
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name => name
+ *
+ * Returns the name of this oneof.
+ */
+VALUE OneofDescriptor_name(VALUE _self) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name = name
+ *
+ * Sets a new name for this oneof. The oneof must not have been added to a
+ * message descriptor yet.
+ */
+VALUE OneofDescriptor_name_set(VALUE _self, VALUE value) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
+  const char* str = get_str(value);
+  CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status),
+            "Error setting oneof name");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.add_field(field) => nil
+ *
+ * Adds a field to this oneof. The field may have been added to this oneof in
+ * the past, or the message to which this oneof belongs (if any), but may not
+ * have already been added to any other oneof or message. Otherwise, an
+ * exception is raised.
+ *
+ * All fields added to the oneof via this method will be automatically added to
+ * the message to which this oneof belongs, if it belongs to one currently, or
+ * else will be added to any message to which the oneof is later added at the
+ * time that it is added.
+ */
+VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
+  FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
+  upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
+  CHECK_UPB(
+      upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status),
+      "Adding field to OneofDescriptor failed");
+  add_def_obj(def->fielddef, obj);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.each(&block) => nil
+ *
+ * Iterates through fields in this oneof, yielding to the block on each one.
+ */
+VALUE OneofDescriptor_each(VALUE _self, VALUE field) {
+  DEFINE_SELF(OneofDescriptor, self, _self);
+  upb_oneof_iter it;
+  for (upb_oneof_begin(&it, self->oneofdef);
+       !upb_oneof_done(&it);
+       upb_oneof_next(&it)) {
+    const upb_fielddef* f = upb_oneof_iter_field(&it);
+    VALUE obj = get_def_obj(f);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+// -----------------------------------------------------------------------------
+// EnumDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
+
+void EnumDescriptor_mark(void* _self) {
+  EnumDescriptor* self = _self;
+  rb_gc_mark(self->module);
+}
+
+void EnumDescriptor_free(void* _self) {
+  EnumDescriptor* self = _self;
+  upb_enumdef_unref(self->enumdef, &self->enumdef);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.new => enum_descriptor
+ *
+ * Creates a new, empty, enum descriptor. Must be added to a pool before the
+ * enum type can be used. The enum type may only be modified prior to adding to
+ * a pool.
+ */
+VALUE EnumDescriptor_alloc(VALUE klass) {
+  EnumDescriptor* self = ALLOC(EnumDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
+  self->enumdef = upb_enumdef_new(&self->enumdef);
+  self->module = Qnil;
+  return ret;
+}
+
+void EnumDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, EnumDescriptor_alloc);
+  rb_define_method(klass, "name", EnumDescriptor_name, 0);
+  rb_define_method(klass, "name=", EnumDescriptor_name_set, 1);
+  rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2);
+  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
+  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
+  rb_define_method(klass, "each", EnumDescriptor_each, 0);
+  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  cEnumDescriptor = klass;
+  rb_gc_register_address(&cEnumDescriptor);
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.name => name
+ *
+ * Returns the name of this enum type.
+ */
+VALUE EnumDescriptor_name(VALUE _self) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.name = name
+ *
+ * Sets the name of this enum type. Cannot be called if the enum type has
+ * already been added to a pool.
+ */
+VALUE EnumDescriptor_name_set(VALUE _self, VALUE str) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
+  const char* name = get_str(str);
+  CHECK_UPB(upb_enumdef_setfullname(mut_def, name, &status),
+            "Error setting EnumDescriptor name");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.add_value(key, value)
+ *
+ * Adds a new key => value mapping to this enum type. Key must be given as a
+ * Ruby symbol. Cannot be called if the enum type has already been added to a
+ * pool. Will raise an exception if the key or value is already in use.
+ */
+VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
+  const char* name_str = rb_id2name(SYM2ID(name));
+  int32_t val = NUM2INT(number);
+  CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status),
+            "Error adding value to enum");
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_name(name) => value
+ *
+ * Returns the numeric value corresponding to the given key name (as a Ruby
+ * symbol), or nil if none.
+ */
+VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  const char* name_str= rb_id2name(SYM2ID(name));
+  int32_t val = 0;
+  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
+    return INT2NUM(val);
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_value(name) => value
+ *
+ * Returns the key name (as a Ruby symbol) corresponding to the integer value,
+ * or nil if none.
+ */
+VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  int32_t val = NUM2INT(number);
+  const char* name = upb_enumdef_iton(self->enumdef, val);
+  if (name != NULL) {
+    return ID2SYM(rb_intern(name));
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.each(&block)
+ *
+ * Iterates over key => value mappings in this enum's definition, yielding to
+ * the block with (key, value) arguments for each one.
+ */
+VALUE EnumDescriptor_each(VALUE _self) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+
+  upb_enum_iter it;
+  for (upb_enum_begin(&it, self->enumdef);
+       !upb_enum_done(&it);
+       upb_enum_next(&it)) {
+    VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
+    VALUE number = INT2NUM(upb_enum_iter_number(&it));
+    rb_yield_values(2, key, number);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.enummodule => module
+ *
+ * Returns the Ruby module corresponding to this enum type. Cannot be called
+ * until the enum descriptor has been added to a pool.
+ */
+VALUE EnumDescriptor_enummodule(VALUE _self) {
+  DEFINE_SELF(EnumDescriptor, self, _self);
+  if (!upb_def_isfrozen((const upb_def*)self->enumdef)) {
+    rb_raise(rb_eRuntimeError,
+             "Cannot fetch enum module from an EnumDescriptor not yet "
+             "in a pool.");
+  }
+  if (self->module == Qnil) {
+    self->module = build_module_from_enumdesc(self);
+  }
+  return self->module;
+}
+
+// -----------------------------------------------------------------------------
+// MessageBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(MessageBuilderContext,
+    "Google::Protobuf::Internal::MessageBuilderContext");
+
+void MessageBuilderContext_mark(void* _self) {
+  MessageBuilderContext* self = _self;
+  rb_gc_mark(self->descriptor);
+  rb_gc_mark(self->builder);
+}
+
+void MessageBuilderContext_free(void* _self) {
+  MessageBuilderContext* self = _self;
+  xfree(self);
+}
+
+VALUE MessageBuilderContext_alloc(VALUE klass) {
+  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(
+      klass, &_MessageBuilderContext_type, self);
+  self->descriptor = Qnil;
+  self->builder = Qnil;
+  return ret;
+}
+
+void MessageBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "MessageBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   MessageBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
+  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
+  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
+  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
+  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
+  cMessageBuilderContext = klass;
+  rb_gc_register_address(&cMessageBuilderContext);
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.new(desc, builder) => context
+ *
+ * Create a new message builder context around the given message descriptor and
+ * builder context. This class is intended to serve as a DSL context to be used
+ * with #instance_eval.
+ */
+VALUE MessageBuilderContext_initialize(VALUE _self,
+                                       VALUE msgdef,
+                                       VALUE builder) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  self->descriptor = msgdef;
+  self->builder = builder;
+  return Qnil;
+}
+
+static VALUE msgdef_add_field(VALUE msgdef,
+                              const char* label, VALUE name,
+                              VALUE type, VALUE number,
+                              VALUE type_class) {
+  VALUE fielddef = rb_class_new_instance(0, NULL, cFieldDescriptor);
+  VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
+
+  rb_funcall(fielddef, rb_intern("label="), 1, ID2SYM(rb_intern(label)));
+  rb_funcall(fielddef, rb_intern("name="), 1, name_str);
+  rb_funcall(fielddef, rb_intern("type="), 1, type);
+  rb_funcall(fielddef, rb_intern("number="), 1, number);
+
+  if (type_class != Qnil) {
+    if (TYPE(type_class) != T_STRING) {
+      rb_raise(rb_eArgError, "Expected string for type class");
+    }
+    // Make it an absolute type name by prepending a dot.
+    type_class = rb_str_append(rb_str_new2("."), type_class);
+    rb_funcall(fielddef, rb_intern("submsg_name="), 1, type_class);
+  }
+
+  rb_funcall(msgdef, rb_intern("add_field"), 1, fielddef);
+  return fielddef;
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.optional(name, type, number, type_class = nil)
+ *
+ * Defines a new optional field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE name, type, number, type_class;
+
+  if (argc < 3) {
+    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  }
+  name = argv[0];
+  type = argv[1];
+  number = argv[2];
+  type_class = (argc > 3) ? argv[3] : Qnil;
+
+  return msgdef_add_field(self->descriptor, "optional",
+                          name, type, number, type_class);
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.required(name, type, number, type_class = nil)
+ *
+ * Defines a new required field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ *
+ * Proto3 does not have required fields, but this method exists for
+ * completeness. Any attempt to add a message type with required fields to a
+ * pool will currently result in an error.
+ */
+VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE name, type, number, type_class;
+
+  if (argc < 3) {
+    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  }
+  name = argv[0];
+  type = argv[1];
+  number = argv[2];
+  type_class = (argc > 3) ? argv[3] : Qnil;
+
+  return msgdef_add_field(self->descriptor, "required",
+                          name, type, number, type_class);
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.repeated(name, type, number, type_class = nil)
+ *
+ * Defines a new repeated field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE name, type, number, type_class;
+
+  if (argc < 3) {
+    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  }
+  name = argv[0];
+  type = argv[1];
+  number = argv[2];
+  type_class = (argc > 3) ? argv[3] : Qnil;
+
+  return msgdef_add_field(self->descriptor, "repeated",
+                          name, type, number, type_class);
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.map(name, key_type, value_type, number,
+ *                               value_type_class = nil)
+ *
+ * Defines a new map field on this message type with the given key and value
+ * types, tag number, and type class (for message and enum value types). The key
+ * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type
+ * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the
+ * type_class must be a string, if present (as accepted by
+ * FieldDescriptor#submsg_name=).
+ */
+VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE name, key_type, value_type, number, type_class;
+  VALUE mapentry_desc, mapentry_desc_name;
+
+  if (argc < 4) {
+    rb_raise(rb_eArgError, "Expected at least 4 arguments.");
+  }
+  name = argv[0];
+  key_type = argv[1];
+  value_type = argv[2];
+  number = argv[3];
+  type_class = (argc > 4) ? argv[4] : Qnil;
+
+  // Validate the key type. We can't accept enums, messages, or floats/doubles
+  // as map keys. (We exclude these explicitly, and the field-descriptor setter
+  // below then ensures that the type is one of the remaining valid options.)
+  if (SYM2ID(key_type) == rb_intern("float") ||
+      SYM2ID(key_type) == rb_intern("double") ||
+      SYM2ID(key_type) == rb_intern("enum") ||
+      SYM2ID(key_type) == rb_intern("message")) {
+    rb_raise(rb_eArgError,
+             "Cannot add a map field with a float, double, enum, or message "
+             "type.");
+  }
+
+  // Create a new message descriptor for the map entry message, and create a
+  // repeated submessage field here with that type.
+  mapentry_desc = rb_class_new_instance(0, NULL, cDescriptor);
+  mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0);
+  mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
+  mapentry_desc_name = rb_str_cat2(mapentry_desc_name,
+                                   rb_id2name(SYM2ID(name)));
+  Descriptor_name_set(mapentry_desc, mapentry_desc_name);
+
+  {
+    // The 'mapentry' attribute has no Ruby setter because we do not want the
+    // user attempting to DIY the setup below; we want to ensure that the fields
+    // are correct. So we reach into the msgdef here to set the bit manually.
+    Descriptor* mapentry_desc_self = ruby_to_Descriptor(mapentry_desc);
+    upb_msgdef_setmapentry((upb_msgdef*)mapentry_desc_self->msgdef, true);
+  }
+
+  {
+    // optional <type> key = 1;
+    VALUE key_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
+    FieldDescriptor_name_set(key_field, rb_str_new2("key"));
+    FieldDescriptor_label_set(key_field, ID2SYM(rb_intern("optional")));
+    FieldDescriptor_number_set(key_field, INT2NUM(1));
+    FieldDescriptor_type_set(key_field, key_type);
+    Descriptor_add_field(mapentry_desc, key_field);
+  }
+
+  {
+    // optional <type> value = 2;
+    VALUE value_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
+    FieldDescriptor_name_set(value_field, rb_str_new2("value"));
+    FieldDescriptor_label_set(value_field, ID2SYM(rb_intern("optional")));
+    FieldDescriptor_number_set(value_field, INT2NUM(2));
+    FieldDescriptor_type_set(value_field, value_type);
+    if (type_class != Qnil) {
+      VALUE submsg_name = rb_str_new2("."); // prepend '.' to make absolute.
+      submsg_name = rb_str_append(submsg_name, type_class);
+      FieldDescriptor_submsg_name_set(value_field, submsg_name);
+    }
+    Descriptor_add_field(mapentry_desc, value_field);
+  }
+
+  {
+    // Add the map-entry message type to the current builder, and use the type
+    // to create the map field itself.
+    Builder* builder_self = ruby_to_Builder(self->builder);
+    rb_ary_push(builder_self->pending_list, mapentry_desc);
+  }
+
+  {
+    VALUE map_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
+    VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
+    VALUE submsg_name;
+
+    FieldDescriptor_name_set(map_field, name_str);
+    FieldDescriptor_number_set(map_field, number);
+    FieldDescriptor_label_set(map_field, ID2SYM(rb_intern("repeated")));
+    FieldDescriptor_type_set(map_field, ID2SYM(rb_intern("message")));
+    submsg_name = rb_str_new2("."); // prepend '.' to make name absolute.
+    submsg_name = rb_str_append(submsg_name, mapentry_desc_name);
+    FieldDescriptor_submsg_name_set(map_field, submsg_name);
+    Descriptor_add_field(self->descriptor, map_field);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.oneof(name, &block) => nil
+ *
+ * Creates a new OneofDescriptor with the given name, creates a
+ * OneofBuilderContext attached to that OneofDescriptor, evaluates the given
+ * block in the context of that OneofBuilderContext with #instance_eval, and
+ * then adds the oneof to the message.
+ *
+ * This is the recommended, idiomatic way to build oneof definitions.
+ */
+VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
+  DEFINE_SELF(MessageBuilderContext, self, _self);
+  VALUE oneofdef = rb_class_new_instance(0, NULL, cOneofDescriptor);
+  VALUE args[2] = { oneofdef, self->builder };
+  VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
+  VALUE block = rb_block_proc();
+  VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
+  rb_funcall(oneofdef, rb_intern("name="), 1, name_str);
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  Descriptor_add_oneof(self->descriptor, oneofdef);
+
+  return Qnil;
+}
+
+// -----------------------------------------------------------------------------
+// OneofBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(OneofBuilderContext,
+    "Google::Protobuf::Internal::OneofBuilderContext");
+
+void OneofBuilderContext_mark(void* _self) {
+  OneofBuilderContext* self = _self;
+  rb_gc_mark(self->descriptor);
+  rb_gc_mark(self->builder);
+}
+
+void OneofBuilderContext_free(void* _self) {
+  OneofBuilderContext* self = _self;
+  xfree(self);
+}
+
+VALUE OneofBuilderContext_alloc(VALUE klass) {
+  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(
+      klass, &_OneofBuilderContext_type, self);
+  self->descriptor = Qnil;
+  self->builder = Qnil;
+  return ret;
+}
+
+void OneofBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   OneofBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
+  cOneofBuilderContext = klass;
+  rb_gc_register_address(&cOneofBuilderContext);
+}
+
+/*
+ * call-seq:
+ *     OneofBuilderContext.new(desc, builder) => context
+ *
+ * Create a new oneof builder context around the given oneof descriptor and
+ * builder context. This class is intended to serve as a DSL context to be used
+ * with #instance_eval.
+ */
+VALUE OneofBuilderContext_initialize(VALUE _self,
+                                     VALUE oneofdef,
+                                     VALUE builder) {
+  DEFINE_SELF(OneofBuilderContext, self, _self);
+  self->descriptor = oneofdef;
+  self->builder = builder;
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofBuilderContext.optional(name, type, number, type_class = nil)
+ *
+ * Defines a new optional field in this oneof with the given type, tag number,
+ * and type class (for message and enum fields). The type must be a Ruby symbol
+ * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
+ * if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+  DEFINE_SELF(OneofBuilderContext, self, _self);
+  VALUE name, type, number, type_class;
+
+  if (argc < 3) {
+    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  }
+  name = argv[0];
+  type = argv[1];
+  number = argv[2];
+  type_class = (argc > 3) ? argv[3] : Qnil;
+
+  return msgdef_add_field(self->descriptor, "optional",
+                          name, type, number, type_class);
+}
+
+// -----------------------------------------------------------------------------
+// EnumBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(EnumBuilderContext,
+    "Google::Protobuf::Internal::EnumBuilderContext");
+
+void EnumBuilderContext_mark(void* _self) {
+  EnumBuilderContext* self = _self;
+  rb_gc_mark(self->enumdesc);
+}
+
+void EnumBuilderContext_free(void* _self) {
+  EnumBuilderContext* self = _self;
+  xfree(self);
+}
+
+VALUE EnumBuilderContext_alloc(VALUE klass) {
+  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(
+      klass, &_EnumBuilderContext_type, self);
+  self->enumdesc = Qnil;
+  return ret;
+}
+
+void EnumBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   EnumBuilderContext_initialize, 1);
+  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
+  cEnumBuilderContext = klass;
+  rb_gc_register_address(&cEnumBuilderContext);
+}
+
+/*
+ * call-seq:
+ *     EnumBuilderContext.new(enumdesc) => context
+ *
+ * Create a new builder context around the given enum descriptor. This class is
+ * intended to serve as a DSL context to be used with #instance_eval.
+ */
+VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdef) {
+  DEFINE_SELF(EnumBuilderContext, self, _self);
+  self->enumdesc = enumdef;
+  return Qnil;
+}
+
+static VALUE enumdef_add_value(VALUE enumdef,
+                               VALUE name, VALUE number) {
+  rb_funcall(enumdef, rb_intern("add_value"), 2, name, number);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumBuilder.add_value(name, number)
+ *
+ * Adds the given name => number mapping to the enum type. Name must be a Ruby
+ * symbol.
+ */
+VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
+  DEFINE_SELF(EnumBuilderContext, self, _self);
+  return enumdef_add_value(self->enumdesc, name, number);
+}
+
+// -----------------------------------------------------------------------------
+// Builder.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
+
+void Builder_mark(void* _self) {
+  Builder* self = _self;
+  rb_gc_mark(self->pending_list);
+}
+
+void Builder_free(void* _self) {
+  Builder* self = _self;
+  xfree(self->defs);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     Builder.new => builder
+ *
+ * Creates a new Builder. A Builder can accumulate a set of new message and enum
+ * descriptors and atomically register them into a pool in a way that allows for
+ * (co)recursive type references.
+ */
+VALUE Builder_alloc(VALUE klass) {
+  Builder* self = ALLOC(Builder);
+  VALUE ret = TypedData_Wrap_Struct(
+      klass, &_Builder_type, self);
+  self->pending_list = rb_ary_new();
+  self->defs = NULL;
+  return ret;
+}
+
+void Builder_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
+  rb_define_alloc_func(klass, Builder_alloc);
+  rb_define_method(klass, "add_message", Builder_add_message, 1);
+  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
+  rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
+  cBuilder = klass;
+  rb_gc_register_address(&cBuilder);
+}
+
+/*
+ * call-seq:
+ *     Builder.add_message(name, &block)
+ *
+ * Creates a new, empty descriptor with the given name, and invokes the block in
+ * the context of a MessageBuilderContext on that descriptor. The block can then
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+ * methods to define the message fields.
+ *
+ * This is the recommended, idiomatic way to build message definitions.
+ */
+VALUE Builder_add_message(VALUE _self, VALUE name) {
+  DEFINE_SELF(Builder, self, _self);
+  VALUE msgdef = rb_class_new_instance(0, NULL, cDescriptor);
+  VALUE args[2] = { msgdef, _self };
+  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
+  VALUE block = rb_block_proc();
+  rb_funcall(msgdef, rb_intern("name="), 1, name);
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  rb_ary_push(self->pending_list, msgdef);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Builder.add_enum(name, &block)
+ *
+ * Creates a new, empty enum descriptor with the given name, and invokes the
+ * block in the context of an EnumBuilderContext on that descriptor. The block
+ * can then call EnumBuilderContext#add_value to define the enum values.
+ *
+ * This is the recommended, idiomatic way to build enum definitions.
+ */
+VALUE Builder_add_enum(VALUE _self, VALUE name) {
+  DEFINE_SELF(Builder, self, _self);
+  VALUE enumdef = rb_class_new_instance(0, NULL, cEnumDescriptor);
+  VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
+  VALUE block = rb_block_proc();
+  rb_funcall(enumdef, rb_intern("name="), 1, name);
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  rb_ary_push(self->pending_list, enumdef);
+  return Qnil;
+}
+
+static void validate_msgdef(const upb_msgdef* msgdef) {
+  // Verify that no required fields exist. proto3 does not support these.
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
+      rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
+    }
+  }
+}
+
+static void validate_enumdef(const upb_enumdef* enumdef) {
+  // Verify that an entry exists with integer value 0. (This is the default
+  // value.)
+  const char* lookup = upb_enumdef_iton(enumdef, 0);
+  if (lookup == NULL) {
+    rb_raise(rb_eTypeError,
+             "Enum definition does not contain a value for '0'.");
+  }
+}
+
+/*
+ * call-seq:
+ *     Builder.finalize_to_pool(pool)
+ *
+ * Adds all accumulated message and enum descriptors created in this builder
+ * context to the given pool. The operation occurs atomically, and all
+ * descriptors can refer to each other (including in cycles). This is the only
+ * way to build (co)recursive message definitions.
+ *
+ * This method is usually called automatically by DescriptorPool#build after it
+ * invokes the given user block in the context of the builder. The user should
+ * not normally need to call this manually because a Builder is not normally
+ * created manually.
+ */
+VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) {
+  DEFINE_SELF(Builder, self, _self);
+
+  DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb);
+
+  REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list));
+
+  for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
+    VALUE def_rb = rb_ary_entry(self->pending_list, i);
+    if (CLASS_OF(def_rb) == cDescriptor) {
+      self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef;
+      validate_msgdef((const upb_msgdef*)self->defs[i]);
+    } else if (CLASS_OF(def_rb) == cEnumDescriptor) {
+      self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef;
+      validate_enumdef((const upb_enumdef*)self->defs[i]);
+    }
+  }
+
+  CHECK_UPB(upb_symtab_add(pool->symtab, (upb_def**)self->defs,
+                           RARRAY_LEN(self->pending_list), NULL, &status),
+            "Unable to add defs to DescriptorPool");
+
+  for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
+    VALUE def_rb = rb_ary_entry(self->pending_list, i);
+    add_def_obj(self->defs[i], def_rb);
+  }
+
+  self->pending_list = rb_ary_new();
+  return Qnil;
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/encode_decode.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/encode_decode.c
new file mode 100644
index 0000000..f6bea50
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/encode_decode.c
@@ -0,0 +1,1233 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// This function is equivalent to rb_str_cat(), but unlike the real
+// rb_str_cat(), it doesn't leak memory in some versions of Ruby.
+// For more information, see:
+//   https://bugs.ruby-lang.org/issues/11328
+VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
+  char *p;
+  size_t oldlen = RSTRING_LEN(rb_str);
+  rb_str_modify_expand(rb_str, len);
+  p = RSTRING_PTR(rb_str);
+  memcpy(p + oldlen, str, len);
+  rb_str_set_len(rb_str, oldlen + len);
+  return rb_str;
+}
+
+// -----------------------------------------------------------------------------
+// Parsing.
+// -----------------------------------------------------------------------------
+
+#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
+
+// Creates a handlerdata that simply contains the offset for this field.
+static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
+  size_t* hd_ofs = ALLOC(size_t);
+  *hd_ofs = ofs;
+  upb_handlers_addcleanup(h, hd_ofs, free);
+  return hd_ofs;
+}
+
+typedef struct {
+  size_t ofs;
+  const upb_msgdef *md;
+} submsg_handlerdata_t;
+
+// Creates a handlerdata that contains offset and submessage type information.
+static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
+                                        const upb_fielddef* f) {
+  submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
+  hd->ofs = ofs;
+  hd->md = upb_fielddef_msgsubdef(f);
+  upb_handlers_addcleanup(h, hd, free);
+  return hd;
+}
+
+typedef struct {
+  size_t ofs;              // union data slot
+  size_t case_ofs;         // oneof_case field
+  uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
+  const upb_msgdef *md;    // msgdef, for oneof submessage handler
+} oneof_handlerdata_t;
+
+static const void *newoneofhandlerdata(upb_handlers *h,
+                                       uint32_t ofs,
+                                       uint32_t case_ofs,
+                                       const upb_fielddef *f) {
+  oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
+  hd->ofs = ofs;
+  hd->case_ofs = case_ofs;
+  // We reuse the field tag number as a oneof union discriminant tag. Note that
+  // we don't expose these numbers to the user, so the only requirement is that
+  // we have some unique ID for each union case/possibility. The field tag
+  // numbers are already present and are easy to use so there's no reason to
+  // create a separate ID space. In addition, using the field tag number here
+  // lets us easily look up the field in the oneof accessor.
+  hd->oneof_case_num = upb_fielddef_number(f);
+  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
+    hd->md = upb_fielddef_msgsubdef(f);
+  } else {
+    hd->md = NULL;
+  }
+  upb_handlers_addcleanup(h, hd, free);
+  return hd;
+}
+
+// A handler that starts a repeated field.  Gets the Repeated*Field instance for
+// this field (such an instance always exists even in an empty message).
+static void *startseq_handler(void* closure, const void* hd) {
+  MessageHeader* msg = closure;
+  const size_t *ofs = hd;
+  return (void*)DEREF(msg, *ofs, VALUE);
+}
+
+// Handlers that append primitive values to a repeated field.
+#define DEFINE_APPEND_HANDLER(type, ctype)                 \
+  static bool append##type##_handler(void *closure, const void *hd, \
+                                     ctype val) {                   \
+    VALUE ary = (VALUE)closure;                                     \
+    RepeatedField_push_native(ary, &val);                           \
+    return true;                                                    \
+  }
+
+DEFINE_APPEND_HANDLER(bool,   bool)
+DEFINE_APPEND_HANDLER(int32,  int32_t)
+DEFINE_APPEND_HANDLER(uint32, uint32_t)
+DEFINE_APPEND_HANDLER(float,  float)
+DEFINE_APPEND_HANDLER(int64,  int64_t)
+DEFINE_APPEND_HANDLER(uint64, uint64_t)
+DEFINE_APPEND_HANDLER(double, double)
+
+// Appends a string to a repeated field.
+static void* appendstr_handler(void *closure,
+                               const void *hd,
+                               size_t size_hint) {
+  VALUE ary = (VALUE)closure;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyStringUtf8Encoding);
+  RepeatedField_push(ary, str);
+  return (void*)str;
+}
+
+// Appends a 'bytes' string to a repeated field.
+static void* appendbytes_handler(void *closure,
+                                 const void *hd,
+                                 size_t size_hint) {
+  VALUE ary = (VALUE)closure;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyString8bitEncoding);
+  RepeatedField_push(ary, str);
+  return (void*)str;
+}
+
+// Sets a non-repeated string field in a message.
+static void* str_handler(void *closure,
+                         const void *hd,
+                         size_t size_hint) {
+  MessageHeader* msg = closure;
+  const size_t *ofs = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyStringUtf8Encoding);
+  DEREF(msg, *ofs, VALUE) = str;
+  return (void*)str;
+}
+
+// Sets a non-repeated 'bytes' field in a message.
+static void* bytes_handler(void *closure,
+                           const void *hd,
+                           size_t size_hint) {
+  MessageHeader* msg = closure;
+  const size_t *ofs = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyString8bitEncoding);
+  DEREF(msg, *ofs, VALUE) = str;
+  return (void*)str;
+}
+
+static size_t stringdata_handler(void* closure, const void* hd,
+                                 const char* str, size_t len,
+                                 const upb_bufhandle* handle) {
+  VALUE rb_str = (VALUE)closure;
+  noleak_rb_str_cat(rb_str, str, len);
+  return len;
+}
+
+// Appends a submessage to a repeated field (a regular Ruby array for now).
+static void *appendsubmsg_handler(void *closure, const void *hd) {
+  VALUE ary = (VALUE)closure;
+  const submsg_handlerdata_t *submsgdata = hd;
+  VALUE subdesc =
+      get_def_obj((void*)submsgdata->md);
+  VALUE subklass = Descriptor_msgclass(subdesc);
+  MessageHeader* submsg;
+
+  VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass);
+  RepeatedField_push(ary, submsg_rb);
+
+  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+  return submsg;
+}
+
+// Sets a non-repeated submessage field in a message.
+static void *submsg_handler(void *closure, const void *hd) {
+  MessageHeader* msg = closure;
+  const submsg_handlerdata_t* submsgdata = hd;
+  VALUE subdesc =
+      get_def_obj((void*)submsgdata->md);
+  VALUE subklass = Descriptor_msgclass(subdesc);
+  VALUE submsg_rb;
+  MessageHeader* submsg;
+
+  if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
+    DEREF(msg, submsgdata->ofs, VALUE) =
+        rb_class_new_instance(0, NULL, subklass);
+  }
+
+  submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
+  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+  return submsg;
+}
+
+// Handler data for startmap/endmap handlers.
+typedef struct {
+  size_t ofs;
+  upb_fieldtype_t key_field_type;
+  upb_fieldtype_t value_field_type;
+
+  // We know that we can hold this reference because the handlerdata has the
+  // same lifetime as the upb_handlers struct, and the upb_handlers struct holds
+  // a reference to the upb_msgdef, which in turn has references to its subdefs.
+  const upb_def* value_field_subdef;
+} map_handlerdata_t;
+
+// Temporary frame for map parsing: at the beginning of a map entry message, a
+// submsg handler allocates a frame to hold (i) a reference to the Map object
+// into which this message will be inserted and (ii) storage slots to
+// temporarily hold the key and value for this map entry until the end of the
+// submessage. When the submessage ends, another handler is called to insert the
+// value into the map.
+typedef struct {
+  VALUE map;
+  char key_storage[NATIVE_SLOT_MAX_SIZE];
+  char value_storage[NATIVE_SLOT_MAX_SIZE];
+} map_parse_frame_t;
+
+// Handler to begin a map entry: allocates a temporary frame. This is the
+// 'startsubmsg' handler on the msgdef that contains the map field.
+static void *startmapentry_handler(void *closure, const void *hd) {
+  MessageHeader* msg = closure;
+  const map_handlerdata_t* mapdata = hd;
+  VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
+
+  map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
+  frame->map = map_rb;
+
+  native_slot_init(mapdata->key_field_type, &frame->key_storage);
+  native_slot_init(mapdata->value_field_type, &frame->value_storage);
+
+  return frame;
+}
+
+// Handler to end a map entry: inserts the value defined during the message into
+// the map. This is the 'endmsg' handler on the map entry msgdef.
+static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
+  map_parse_frame_t* frame = closure;
+  const map_handlerdata_t* mapdata = hd;
+
+  VALUE key = native_slot_get(
+      mapdata->key_field_type, Qnil,
+      &frame->key_storage);
+
+  VALUE value_field_typeclass = Qnil;
+  VALUE value;
+
+  if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
+      mapdata->value_field_type == UPB_TYPE_ENUM) {
+    value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
+  }
+
+  value = native_slot_get(
+      mapdata->value_field_type, value_field_typeclass,
+      &frame->value_storage);
+
+  Map_index_set(frame->map, key, value);
+  free(frame);
+
+  return true;
+}
+
+// Allocates a new map_handlerdata_t given the map entry message definition. If
+// the offset of the field within the parent message is also given, that is
+// added to the handler data as well. Note that this is called *twice* per map
+// field: once in the parent message handler setup when setting the startsubmsg
+// handler and once in the map entry message handler setup when setting the
+// key/value and endmsg handlers. The reason is that there is no easy way to
+// pass the handlerdata down to the sub-message handler setup.
+static map_handlerdata_t* new_map_handlerdata(
+    size_t ofs,
+    const upb_msgdef* mapentry_def,
+    Descriptor* desc) {
+  const upb_fielddef* key_field;
+  const upb_fielddef* value_field;
+  map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
+  hd->ofs = ofs;
+  key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
+  assert(key_field != NULL);
+  hd->key_field_type = upb_fielddef_type(key_field);
+  value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
+  assert(value_field != NULL);
+  hd->value_field_type = upb_fielddef_type(value_field);
+  hd->value_field_subdef = upb_fielddef_subdef(value_field);
+
+  return hd;
+}
+
+// Handlers that set primitive values in oneofs.
+#define DEFINE_ONEOF_HANDLER(type, ctype)                           \
+  static bool oneof##type##_handler(void *closure, const void *hd,  \
+                                     ctype val) {                   \
+    const oneof_handlerdata_t *oneofdata = hd;                      \
+    DEREF(closure, oneofdata->case_ofs, uint32_t) =                 \
+        oneofdata->oneof_case_num;                                  \
+    DEREF(closure, oneofdata->ofs, ctype) = val;                    \
+    return true;                                                    \
+  }
+
+DEFINE_ONEOF_HANDLER(bool,   bool)
+DEFINE_ONEOF_HANDLER(int32,  int32_t)
+DEFINE_ONEOF_HANDLER(uint32, uint32_t)
+DEFINE_ONEOF_HANDLER(float,  float)
+DEFINE_ONEOF_HANDLER(int64,  int64_t)
+DEFINE_ONEOF_HANDLER(uint64, uint64_t)
+DEFINE_ONEOF_HANDLER(double, double)
+
+#undef DEFINE_ONEOF_HANDLER
+
+// Handlers for strings in a oneof.
+static void *oneofstr_handler(void *closure,
+                              const void *hd,
+                              size_t size_hint) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyStringUtf8Encoding);
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+  DEREF(msg, oneofdata->ofs, VALUE) = str;
+  return (void*)str;
+}
+
+static void *oneofbytes_handler(void *closure,
+                                const void *hd,
+                                size_t size_hint) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  VALUE str = rb_str_new2("");
+  rb_enc_associate(str, kRubyString8bitEncoding);
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+  DEREF(msg, oneofdata->ofs, VALUE) = str;
+  return (void*)str;
+}
+
+// Handler for a submessage field in a oneof.
+static void *oneofsubmsg_handler(void *closure,
+                                 const void *hd) {
+  MessageHeader* msg = closure;
+  const oneof_handlerdata_t *oneofdata = hd;
+  uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
+
+  VALUE subdesc =
+      get_def_obj((void*)oneofdata->md);
+  VALUE subklass = Descriptor_msgclass(subdesc);
+  VALUE submsg_rb;
+  MessageHeader* submsg;
+
+  if (oldcase != oneofdata->oneof_case_num ||
+      DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
+    DEREF(msg, oneofdata->ofs, VALUE) =
+        rb_class_new_instance(0, NULL, subklass);
+  }
+  // Set the oneof case *after* allocating the new class instance -- otherwise,
+  // if the Ruby GC is invoked as part of a call into the VM, it might invoke
+  // our mark routines, and our mark routines might see the case value
+  // indicating a VALUE is present and expect a valid VALUE. See comment in
+  // layout_set() for more detail: basically, the change to the value and the
+  // case must be atomic w.r.t. the Ruby VM.
+  DEREF(msg, oneofdata->case_ofs, uint32_t) =
+      oneofdata->oneof_case_num;
+
+  submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
+  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+  return submsg;
+}
+
+// Set up handlers for a repeated field.
+static void add_handlers_for_repeated_field(upb_handlers *h,
+                                            const upb_fielddef *f,
+                                            size_t offset) {
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+  upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+  upb_handlers_setstartseq(h, f, startseq_handler, &attr);
+  upb_handlerattr_uninit(&attr);
+
+  switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype)                                 \
+  case utype:                                                     \
+    upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
+    break;
+
+    SET_HANDLER(UPB_TYPE_BOOL,   bool);
+    SET_HANDLER(UPB_TYPE_INT32,  int32);
+    SET_HANDLER(UPB_TYPE_UINT32, uint32);
+    SET_HANDLER(UPB_TYPE_ENUM,   int32);
+    SET_HANDLER(UPB_TYPE_FLOAT,  float);
+    SET_HANDLER(UPB_TYPE_INT64,  int64);
+    SET_HANDLER(UPB_TYPE_UINT64, uint64);
+    SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+      upb_handlers_setstartstr(h, f, is_bytes ?
+                               appendbytes_handler : appendstr_handler,
+                               NULL);
+      upb_handlers_setstring(h, f, stringdata_handler, NULL);
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+      upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
+      upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
+      upb_handlerattr_uninit(&attr);
+      break;
+    }
+  }
+}
+
+// Set up handlers for a singular field.
+static void add_handlers_for_singular_field(upb_handlers *h,
+                                            const upb_fielddef *f,
+                                            size_t offset) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_DOUBLE:
+      upb_shim_set(h, f, offset, -1);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+      upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+      upb_handlers_setstartstr(h, f,
+                               is_bytes ? bytes_handler : str_handler,
+                               &attr);
+      upb_handlers_setstring(h, f, stringdata_handler, &attr);
+      upb_handlerattr_uninit(&attr);
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+      upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
+      upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
+      upb_handlerattr_uninit(&attr);
+      break;
+    }
+  }
+}
+
+// Adds handlers to a map field.
+static void add_handlers_for_mapfield(upb_handlers* h,
+                                      const upb_fielddef* fielddef,
+                                      size_t offset,
+                                      Descriptor* desc) {
+  const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
+  map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+
+  upb_handlers_addcleanup(h, hd, free);
+  upb_handlerattr_sethandlerdata(&attr, hd);
+  upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
+  upb_handlerattr_uninit(&attr);
+}
+
+// Adds handlers to a map-entry msgdef.
+static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
+                                      upb_handlers* h,
+                                      Descriptor* desc) {
+  const upb_fielddef* key_field = map_entry_key(msgdef);
+  const upb_fielddef* value_field = map_entry_value(msgdef);
+  map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+
+  upb_handlers_addcleanup(h, hd, free);
+  upb_handlerattr_sethandlerdata(&attr, hd);
+  upb_handlers_setendmsg(h, endmap_handler, &attr);
+
+  add_handlers_for_singular_field(
+      h, key_field,
+      offsetof(map_parse_frame_t, key_storage));
+  add_handlers_for_singular_field(
+      h, value_field,
+      offsetof(map_parse_frame_t, value_storage));
+}
+
+// Set up handlers for a oneof field.
+static void add_handlers_for_oneof_field(upb_handlers *h,
+                                         const upb_fielddef *f,
+                                         size_t offset,
+                                         size_t oneof_case_offset) {
+
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+  upb_handlerattr_sethandlerdata(
+      &attr, newoneofhandlerdata(h, offset, oneof_case_offset, f));
+
+  switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype)                                 \
+  case utype:                                                     \
+    upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
+    break;
+
+    SET_HANDLER(UPB_TYPE_BOOL,   bool);
+    SET_HANDLER(UPB_TYPE_INT32,  int32);
+    SET_HANDLER(UPB_TYPE_UINT32, uint32);
+    SET_HANDLER(UPB_TYPE_ENUM,   int32);
+    SET_HANDLER(UPB_TYPE_FLOAT,  float);
+    SET_HANDLER(UPB_TYPE_INT64,  int64);
+    SET_HANDLER(UPB_TYPE_UINT64, uint64);
+    SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+      upb_handlers_setstartstr(h, f, is_bytes ?
+                               oneofbytes_handler : oneofstr_handler,
+                               &attr);
+      upb_handlers_setstring(h, f, stringdata_handler, NULL);
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
+      break;
+    }
+  }
+
+  upb_handlerattr_uninit(&attr);
+}
+
+
+static void add_handlers_for_message(const void *closure, upb_handlers *h) {
+  const upb_msgdef* msgdef = upb_handlers_msgdef(h);
+  Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
+  upb_msg_field_iter i;
+
+  // If this is a mapentry message type, set up a special set of handlers and
+  // bail out of the normal (user-defined) message type handling.
+  if (upb_msgdef_mapentry(msgdef)) {
+    add_handlers_for_mapentry(msgdef, h, desc);
+    return;
+  }
+
+  // Ensure layout exists. We may be invoked to create handlers for a given
+  // message if we are included as a submsg of another message type before our
+  // class is actually built, so to work around this, we just create the layout
+  // (and handlers, in the class-building function) on-demand.
+  if (desc->layout == NULL) {
+    desc->layout = create_layout(desc->msgdef);
+  }
+
+  for (upb_msg_field_begin(&i, desc->msgdef);
+       !upb_msg_field_done(&i);
+       upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
+        sizeof(MessageHeader);
+
+    if (upb_fielddef_containingoneof(f)) {
+      size_t oneof_case_offset =
+          desc->layout->fields[upb_fielddef_index(f)].case_offset +
+          sizeof(MessageHeader);
+      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
+    } else if (is_map_field(f)) {
+      add_handlers_for_mapfield(h, f, offset, desc);
+    } else if (upb_fielddef_isseq(f)) {
+      add_handlers_for_repeated_field(h, f, offset);
+    } else {
+      add_handlers_for_singular_field(h, f, offset);
+    }
+  }
+}
+
+// Creates upb handlers for populating a message.
+static const upb_handlers *new_fill_handlers(Descriptor* desc,
+                                             const void* owner) {
+  // TODO(cfallin, haberman): once upb gets a caching/memoization layer for
+  // handlers, reuse subdef handlers so that e.g. if we already parse
+  // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
+  // parse A-with-field-of-type-B-with-field-of-type-C.
+  return upb_handlers_newfrozen(desc->msgdef, owner,
+                                add_handlers_for_message, NULL);
+}
+
+// Constructs the handlers for filling a message's data into an in-memory
+// object.
+const upb_handlers* get_fill_handlers(Descriptor* desc) {
+  if (!desc->fill_handlers) {
+    desc->fill_handlers =
+        new_fill_handlers(desc, &desc->fill_handlers);
+  }
+  return desc->fill_handlers;
+}
+
+// Constructs the upb decoder method for parsing messages of this type.
+// This is called from the message class creation code.
+const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc,
+                                                     const void* owner) {
+  const upb_handlers* handlers = get_fill_handlers(desc);
+  upb_pbdecodermethodopts opts;
+  upb_pbdecodermethodopts_init(&opts, handlers);
+
+  return upb_pbdecodermethod_new(&opts, owner);
+}
+
+static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
+  if (desc->fill_method == NULL) {
+    desc->fill_method = new_fillmsg_decodermethod(
+        desc, &desc->fill_method);
+  }
+  return desc->fill_method;
+}
+
+static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
+  if (desc->json_fill_method == NULL) {
+    desc->json_fill_method =
+        upb_json_parsermethod_new(desc->msgdef, &desc->json_fill_method);
+  }
+  return desc->json_fill_method;
+}
+
+
+// Stack-allocated context during an encode/decode operation. Contains the upb
+// environment and its stack-based allocator, an initial buffer for allocations
+// to avoid malloc() when possible, and a template for Ruby exception messages
+// if any error occurs.
+#define STACK_ENV_STACKBYTES 4096
+typedef struct {
+  upb_env env;
+  const char* ruby_error_template;
+  char allocbuf[STACK_ENV_STACKBYTES];
+} stackenv;
+
+static void stackenv_init(stackenv* se, const char* errmsg);
+static void stackenv_uninit(stackenv* se);
+
+// Callback invoked by upb if any error occurs during parsing or serialization.
+static bool env_error_func(void* ud, const upb_status* status) {
+  stackenv* se = ud;
+  // Free the env -- rb_raise will longjmp up the stack past the encode/decode
+  // function so it would not otherwise have been freed.
+  stackenv_uninit(se);
+
+  // TODO(haberman): have a way to verify that this is actually a parse error,
+  // instead of just throwing "parse error" unconditionally.
+  rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status));
+  // Never reached: rb_raise() always longjmp()s up the stack, past all of our
+  // code, back to Ruby.
+  return false;
+}
+
+static void stackenv_init(stackenv* se, const char* errmsg) {
+  se->ruby_error_template = errmsg;
+  upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL);
+  upb_env_seterrorfunc(&se->env, env_error_func, se);
+}
+
+static void stackenv_uninit(stackenv* se) {
+  upb_env_uninit(&se->env);
+}
+
+/*
+ * call-seq:
+ *     MessageClass.decode(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+VALUE Message_decode(VALUE klass, VALUE data) {
+  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
+  Descriptor* desc = ruby_to_Descriptor(descriptor);
+  VALUE msgklass = Descriptor_msgclass(descriptor);
+  VALUE msg_rb;
+  MessageHeader* msg;
+
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
+  }
+
+  msg_rb = rb_class_new_instance(0, NULL, msgklass);
+  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+
+  {
+    const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
+    const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
+    stackenv se;
+    upb_sink sink;
+    upb_pbdecoder* decoder;
+    stackenv_init(&se, "Error occurred during parsing: %s");
+
+    upb_sink_reset(&sink, h, msg);
+    decoder = upb_pbdecoder_create(&se.env, method, &sink);
+    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
+                      upb_pbdecoder_input(decoder));
+
+    stackenv_uninit(&se);
+  }
+
+  return msg_rb;
+}
+
+/*
+ * call-seq:
+ *     MessageClass.decode_json(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+VALUE Message_decode_json(VALUE klass, VALUE data) {
+  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
+  Descriptor* desc = ruby_to_Descriptor(descriptor);
+  VALUE msgklass = Descriptor_msgclass(descriptor);
+  VALUE msg_rb;
+  MessageHeader* msg;
+
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for JSON data.");
+  }
+  // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
+  // convert, because string handlers pass data directly to message string
+  // fields.
+
+  msg_rb = rb_class_new_instance(0, NULL, msgklass);
+  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+
+  {
+    const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
+    stackenv se;
+    upb_sink sink;
+    upb_json_parser* parser;
+    stackenv_init(&se, "Error occurred during parsing: %s");
+
+    upb_sink_reset(&sink, get_fill_handlers(desc), msg);
+    parser = upb_json_parser_create(&se.env, method, &sink);
+    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
+                      upb_json_parser_input(parser));
+
+    stackenv_uninit(&se);
+  }
+
+  return msg_rb;
+}
+
+// -----------------------------------------------------------------------------
+// Serializing.
+// -----------------------------------------------------------------------------
+//
+// The code below also comes from upb's prototype Ruby binding, developed by
+// haberman@.
+
+/* stringsink *****************************************************************/
+
+// This should probably be factored into a common upb component.
+
+typedef struct {
+  upb_byteshandler handler;
+  upb_bytessink sink;
+  char *ptr;
+  size_t len, size;
+} stringsink;
+
+static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
+  stringsink *sink = _sink;
+  sink->len = 0;
+  return sink;
+}
+
+static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
+                                size_t len, const upb_bufhandle *handle) {
+  stringsink *sink = _sink;
+  size_t new_size = sink->size;
+
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  while (sink->len + len > new_size) {
+    new_size *= 2;
+  }
+
+  if (new_size != sink->size) {
+    sink->ptr = realloc(sink->ptr, new_size);
+    sink->size = new_size;
+  }
+
+  memcpy(sink->ptr + sink->len, ptr, len);
+  sink->len += len;
+
+  return len;
+}
+
+void stringsink_init(stringsink *sink) {
+  upb_byteshandler_init(&sink->handler);
+  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
+  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
+
+  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
+
+  sink->size = 32;
+  sink->ptr = malloc(sink->size);
+  sink->len = 0;
+}
+
+void stringsink_uninit(stringsink *sink) {
+  free(sink->ptr);
+}
+
+/* msgvisitor *****************************************************************/
+
+// TODO: If/when we support proto2 semantics in addition to the current proto3
+// semantics, which means that we have true field presence, we will want to
+// modify msgvisitor so that it emits all present fields rather than all
+// non-default-value fields.
+//
+// Likewise, when implementing JSON serialization, we may need to have a
+// 'verbose' mode that outputs all fields and a 'concise' mode that outputs only
+// those with non-default values.
+
+static void putmsg(VALUE msg, const Descriptor* desc,
+                   upb_sink *sink, int depth);
+
+static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
+  upb_selector_t ret;
+  bool ok = upb_handlers_getselector(f, type, &ret);
+  UPB_ASSERT_VAR(ok, ok);
+  return ret;
+}
+
+static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
+  upb_sink subsink;
+
+  if (str == Qnil) return;
+
+  assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
+
+  // Ensure that the string has the correct encoding. We also check at field-set
+  // time, but the user may have mutated the string object since then.
+  native_slot_validate_string_encoding(upb_fielddef_type(f), str);
+
+  upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
+                    &subsink);
+  upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
+                     RSTRING_LEN(str), NULL);
+  upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
+                      int depth) {
+  upb_sink subsink;
+  VALUE descriptor;
+  Descriptor* subdesc;
+
+  if (submsg == Qnil) return;
+
+  descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
+  subdesc = ruby_to_Descriptor(descriptor);
+
+  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
+  putmsg(submsg, subdesc, &subsink, depth + 1);
+  upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
+}
+
+static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
+                   int depth) {
+  upb_sink subsink;
+  upb_fieldtype_t type = upb_fielddef_type(f);
+  upb_selector_t sel = 0;
+  int size;
+
+  if (ary == Qnil) return;
+
+  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
+
+  if (upb_fielddef_isprimitive(f)) {
+    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+  }
+
+  size = NUM2INT(RepeatedField_length(ary));
+  for (int i = 0; i < size; i++) {
+    void* memory = RepeatedField_index_native(ary, i);
+    switch (type) {
+#define T(upbtypeconst, upbtype, ctype)                         \
+  case upbtypeconst:                                            \
+    upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory));   \
+    break;
+
+      T(UPB_TYPE_FLOAT,  float,  float)
+      T(UPB_TYPE_DOUBLE, double, double)
+      T(UPB_TYPE_BOOL,   bool,   int8_t)
+      case UPB_TYPE_ENUM:
+      T(UPB_TYPE_INT32,  int32,  int32_t)
+      T(UPB_TYPE_UINT32, uint32, uint32_t)
+      T(UPB_TYPE_INT64,  int64,  int64_t)
+      T(UPB_TYPE_UINT64, uint64, uint64_t)
+
+      case UPB_TYPE_STRING:
+      case UPB_TYPE_BYTES:
+        putstr(*((VALUE *)memory), f, &subsink);
+        break;
+      case UPB_TYPE_MESSAGE:
+        putsubmsg(*((VALUE *)memory), f, &subsink, depth);
+        break;
+
+#undef T
+
+    }
+  }
+  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
+}
+
+static void put_ruby_value(VALUE value,
+                           const upb_fielddef *f,
+                           VALUE type_class,
+                           int depth,
+                           upb_sink *sink) {
+  upb_selector_t sel = 0;
+  if (upb_fielddef_isprimitive(f)) {
+    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+  }
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+      upb_sink_putint32(sink, sel, NUM2INT(value));
+      break;
+    case UPB_TYPE_INT64:
+      upb_sink_putint64(sink, sel, NUM2LL(value));
+      break;
+    case UPB_TYPE_UINT32:
+      upb_sink_putuint32(sink, sel, NUM2UINT(value));
+      break;
+    case UPB_TYPE_UINT64:
+      upb_sink_putuint64(sink, sel, NUM2ULL(value));
+      break;
+    case UPB_TYPE_FLOAT:
+      upb_sink_putfloat(sink, sel, NUM2DBL(value));
+      break;
+    case UPB_TYPE_DOUBLE:
+      upb_sink_putdouble(sink, sel, NUM2DBL(value));
+      break;
+    case UPB_TYPE_ENUM: {
+      if (TYPE(value) == T_SYMBOL) {
+        value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
+      }
+      upb_sink_putint32(sink, sel, NUM2INT(value));
+      break;
+    }
+    case UPB_TYPE_BOOL:
+      upb_sink_putbool(sink, sel, value == Qtrue);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      putstr(value, f, sink);
+      break;
+    case UPB_TYPE_MESSAGE:
+      putsubmsg(value, f, sink, depth);
+  }
+}
+
+static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
+                   int depth) {
+  Map* self;
+  upb_sink subsink;
+  const upb_fielddef* key_field;
+  const upb_fielddef* value_field;
+  Map_iter it;
+
+  if (map == Qnil) return;
+  self = ruby_to_Map(map);
+
+  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
+
+  assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
+  key_field = map_field_key(f);
+  value_field = map_field_value(f);
+
+  for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
+    VALUE key = Map_iter_key(&it);
+    VALUE value = Map_iter_value(&it);
+    upb_status status;
+
+    upb_sink entry_sink;
+    upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
+                         &entry_sink);
+    upb_sink_startmsg(&entry_sink);
+
+    put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink);
+    put_ruby_value(value, value_field, self->value_type_class, depth + 1,
+                   &entry_sink);
+
+    upb_sink_endmsg(&entry_sink, &status);
+    upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
+  }
+
+  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
+}
+
+static void putmsg(VALUE msg_rb, const Descriptor* desc,
+                   upb_sink *sink, int depth) {
+  MessageHeader* msg;
+  upb_msg_field_iter i;
+  upb_status status;
+
+  upb_sink_startmsg(sink);
+
+  // Protect against cycles (possible because users may freely reassign message
+  // and repeated fields) by imposing a maximum recursion depth.
+  if (depth > ENCODE_MAX_NESTING) {
+    rb_raise(rb_eRuntimeError,
+             "Maximum recursion depth exceeded during encoding.");
+  }
+
+  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+
+  for (upb_msg_field_begin(&i, desc->msgdef);
+       !upb_msg_field_done(&i);
+       upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    bool is_matching_oneof = false;
+    uint32_t offset =
+        desc->layout->fields[upb_fielddef_index(f)].offset +
+        sizeof(MessageHeader);
+
+    if (upb_fielddef_containingoneof(f)) {
+      uint32_t oneof_case_offset =
+          desc->layout->fields[upb_fielddef_index(f)].case_offset +
+          sizeof(MessageHeader);
+      // For a oneof, check that this field is actually present -- skip all the
+      // below if not.
+      if (DEREF(msg, oneof_case_offset, uint32_t) !=
+          upb_fielddef_number(f)) {
+        continue;
+      }
+      // Otherwise, fall through to the appropriate singular-field handler
+      // below.
+      is_matching_oneof = true;
+    }
+
+    if (is_map_field(f)) {
+      VALUE map = DEREF(msg, offset, VALUE);
+      if (map != Qnil) {
+        putmap(map, f, sink, depth);
+      }
+    } else if (upb_fielddef_isseq(f)) {
+      VALUE ary = DEREF(msg, offset, VALUE);
+      if (ary != Qnil) {
+        putary(ary, f, sink, depth);
+      }
+    } else if (upb_fielddef_isstring(f)) {
+      VALUE str = DEREF(msg, offset, VALUE);
+      if (is_matching_oneof || RSTRING_LEN(str) > 0) {
+        putstr(str, f, sink);
+      }
+    } else if (upb_fielddef_issubmsg(f)) {
+      putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
+    } else {
+      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+
+#define T(upbtypeconst, upbtype, ctype, default_value)                \
+  case upbtypeconst: {                                                \
+      ctype value = DEREF(msg, offset, ctype);                        \
+      if (is_matching_oneof || value != default_value) {              \
+        upb_sink_put##upbtype(sink, sel, value);                      \
+      }                                                               \
+    }                                                                 \
+    break;
+
+      switch (upb_fielddef_type(f)) {
+        T(UPB_TYPE_FLOAT,  float,  float, 0.0)
+        T(UPB_TYPE_DOUBLE, double, double, 0.0)
+        T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
+        case UPB_TYPE_ENUM:
+        T(UPB_TYPE_INT32,  int32,  int32_t, 0)
+        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
+        T(UPB_TYPE_INT64,  int64,  int64_t, 0)
+        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
+
+        case UPB_TYPE_STRING:
+        case UPB_TYPE_BYTES:
+        case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
+      }
+
+#undef T
+
+    }
+  }
+
+  upb_sink_endmsg(sink, &status);
+}
+
+static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
+  if (desc->pb_serialize_handlers == NULL) {
+    desc->pb_serialize_handlers =
+        upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
+  }
+  return desc->pb_serialize_handlers;
+}
+
+static const upb_handlers* msgdef_json_serialize_handlers(
+    Descriptor* desc, bool preserve_proto_fieldnames) {
+  if (preserve_proto_fieldnames) {
+    if (desc->json_serialize_handlers == NULL) {
+      desc->json_serialize_handlers =
+          upb_json_printer_newhandlers(
+              desc->msgdef, true, &desc->json_serialize_handlers);
+    }
+    return desc->json_serialize_handlers;
+  } else {
+    if (desc->json_serialize_handlers_preserve == NULL) {
+      desc->json_serialize_handlers_preserve =
+          upb_json_printer_newhandlers(
+              desc->msgdef, false, &desc->json_serialize_handlers_preserve);
+    }
+    return desc->json_serialize_handlers_preserve;
+  }
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode(msg) => bytes
+ *
+ * Encodes the given message object to its serialized form in protocol buffers
+ * wire format.
+ */
+VALUE Message_encode(VALUE klass, VALUE msg_rb) {
+  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
+  Descriptor* desc = ruby_to_Descriptor(descriptor);
+
+  stringsink sink;
+  stringsink_init(&sink);
+
+  {
+    const upb_handlers* serialize_handlers =
+        msgdef_pb_serialize_handlers(desc);
+
+    stackenv se;
+    upb_pb_encoder* encoder;
+    VALUE ret;
+
+    stackenv_init(&se, "Error occurred during encoding: %s");
+    encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
+
+    putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0);
+
+    ret = rb_str_new(sink.ptr, sink.len);
+
+    stackenv_uninit(&se);
+    stringsink_uninit(&sink);
+
+    return ret;
+  }
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode_json(msg) => json_string
+ *
+ * Encodes the given message object into its serialized JSON representation.
+ */
+VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
+  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
+  Descriptor* desc = ruby_to_Descriptor(descriptor);
+  VALUE msg_rb;
+  VALUE preserve_proto_fieldnames = Qfalse;
+  stringsink sink;
+
+  if (argc < 1 || argc > 2) {
+    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
+  }
+
+  msg_rb = argv[0];
+
+  if (argc == 2) {
+    VALUE hash_args = argv[1];
+    if (TYPE(hash_args) != T_HASH) {
+      rb_raise(rb_eArgError, "Expected hash arguments.");
+    }
+    preserve_proto_fieldnames = rb_hash_lookup2(
+        hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
+  }
+
+  stringsink_init(&sink);
+
+  {
+    const upb_handlers* serialize_handlers =
+        msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
+    upb_json_printer* printer;
+    stackenv se;
+    VALUE ret;
+
+    stackenv_init(&se, "Error occurred during encoding: %s");
+    printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);
+
+    putmsg(msg_rb, desc, upb_json_printer_input(printer), 0);
+
+    ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
+
+    stackenv_uninit(&se);
+    stringsink_uninit(&sink);
+
+    return ret;
+  }
+}
+
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/extconf.rb b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/extconf.rb
new file mode 100644
index 0000000..b368dcc
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/extconf.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/ruby
+
+require 'mkmf'
+
+$CFLAGS += " -std=c99 -O3 -DNDEBUG"
+
+$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
+         "repeated_field.o", "map.o", "encode_decode.o", "upb.o"]
+
+create_makefile("google/protobuf_c")
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/map.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/map.c
new file mode 100644
index 0000000..92fc728
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/map.c
@@ -0,0 +1,808 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Basic map operations on top of upb's strtable.
+//
+// Note that we roll our own `Map` container here because, as for
+// `RepeatedField`, we want a strongly-typed container. This is so that any user
+// errors due to incorrect map key or value types are raised as close as
+// possible to the error site, rather than at some deferred point (e.g.,
+// serialization).
+//
+// We build our `Map` on top of upb_strtable so that we're able to take
+// advantage of the native_slot storage abstraction, as RepeatedField does.
+// (This is not quite a perfect mapping -- see the key conversions below -- but
+// gives us full support and error-checking for all value types for free.)
+// -----------------------------------------------------------------------------
+
+// Map values are stored using the native_slot abstraction (as with repeated
+// field values), but keys are a bit special. Since we use a strtable, we need
+// to store keys as sequences of bytes such that equality of those bytes maps
+// one-to-one to equality of keys. We store strings directly (i.e., they map to
+// their own bytes) and integers as native integers (using the native_slot
+// abstraction).
+
+// Note that there is another tradeoff here in keeping string keys as native
+// strings rather than Ruby strings: traversing the Map requires conversion to
+// Ruby string values on every traversal, potentially creating more garbage. We
+// should consider ways to cache a Ruby version of the key if this becomes an
+// issue later.
+
+// Forms a key to use with the underlying strtable from a Ruby key value. |buf|
+// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
+// construct a key byte sequence if needed. |out_key| and |out_length| provide
+// the resulting key data/length.
+#define TABLE_KEY_BUF_LENGTH 8  // sizeof(uint64_t)
+static void table_key(Map* self, VALUE key,
+                      char* buf,
+                      const char** out_key,
+                      size_t* out_length) {
+  switch (self->key_type) {
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_STRING:
+      // Strings: use string content directly.
+      Check_Type(key, T_STRING);
+      native_slot_validate_string_encoding(self->key_type, key);
+      *out_key = RSTRING_PTR(key);
+      *out_length = RSTRING_LEN(key);
+      break;
+
+    case UPB_TYPE_BOOL:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      native_slot_set(self->key_type, Qnil, buf, key);
+      *out_key = buf;
+      *out_length = native_slot_size(self->key_type);
+      break;
+
+    default:
+      // Map constructor should not allow a Map with another key type to be
+      // constructed.
+      assert(false);
+      break;
+  }
+}
+
+static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
+  switch (self->key_type) {
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_STRING: {
+      VALUE ret = rb_str_new(buf, length);
+      rb_enc_associate(ret,
+                       (self->key_type == UPB_TYPE_BYTES) ?
+                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
+      return ret;
+    }
+
+    case UPB_TYPE_BOOL:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      return native_slot_get(self->key_type, Qnil, buf);
+
+    default:
+      assert(false);
+      return Qnil;
+  }
+}
+
+static void* value_memory(upb_value* v) {
+  return (void*)(&v->val);
+}
+
+// -----------------------------------------------------------------------------
+// Map container type.
+// -----------------------------------------------------------------------------
+
+const rb_data_type_t Map_type = {
+  "Google::Protobuf::Map",
+  { Map_mark, Map_free, NULL },
+};
+
+VALUE cMap;
+
+Map* ruby_to_Map(VALUE _self) {
+  Map* self;
+  TypedData_Get_Struct(_self, Map, &Map_type, self);
+  return self;
+}
+
+void Map_mark(void* _self) {
+  Map* self = _self;
+
+  rb_gc_mark(self->value_type_class);
+
+  if (self->value_type == UPB_TYPE_STRING ||
+      self->value_type == UPB_TYPE_BYTES ||
+      self->value_type == UPB_TYPE_MESSAGE) {
+    upb_strtable_iter it;
+    for (upb_strtable_begin(&it, &self->table);
+         !upb_strtable_done(&it);
+         upb_strtable_next(&it)) {
+      upb_value v = upb_strtable_iter_value(&it);
+      void* mem = value_memory(&v);
+      native_slot_mark(self->value_type, mem);
+    }
+  }
+}
+
+void Map_free(void* _self) {
+  Map* self = _self;
+  upb_strtable_uninit(&self->table);
+  xfree(self);
+}
+
+VALUE Map_alloc(VALUE klass) {
+  Map* self = ALLOC(Map);
+  memset(self, 0, sizeof(Map));
+  self->value_type_class = Qnil;
+  return TypedData_Wrap_Struct(klass, &Map_type, self);
+}
+
+static bool needs_typeclass(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_MESSAGE:
+    case UPB_TYPE_ENUM:
+      return true;
+    default:
+      return false;
+  }
+}
+
+/*
+ * call-seq:
+ *     Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
+ *     => new map
+ *
+ * Allocates a new Map container. This constructor may be called with 2, 3, or 4
+ * arguments. The first two arguments are always present and are symbols (taking
+ * on the same values as field-type symbols in message descriptors) that
+ * indicate the type of the map key and value fields.
+ *
+ * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
+ * :string, :bytes.
+ *
+ * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
+ * :string, :bytes, :enum, :message.
+ *
+ * The third argument, value_typeclass, must be present if value_type is :enum
+ * or :message. As in RepeatedField#new, this argument must be a message class
+ * (for :message) or enum module (for :enum).
+ *
+ * The last argument, if present, provides initial content for map. Note that
+ * this may be an ordinary Ruby hashmap or another Map instance with identical
+ * key and value types. Also note that this argument may be present whether or
+ * not value_typeclass is present (and it is unambiguously separate from
+ * value_typeclass because value_typeclass's presence is strictly determined by
+ * value_type). The contents of this initial hashmap or Map instance are
+ * shallow-copied into the new Map: the original map is unmodified, but
+ * references to underlying objects will be shared if the value type is a
+ * message type.
+ */
+VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  int init_value_arg;
+
+  // We take either two args (:key_type, :value_type), three args (:key_type,
+  // :value_type, "ValueMessageType"), or four args (the above plus an initial
+  // hashmap).
+  if (argc < 2 || argc > 4) {
+    rb_raise(rb_eArgError, "Map constructor expects 2, 3 or 4 arguments.");
+  }
+
+  self->key_type = ruby_to_fieldtype(argv[0]);
+  self->value_type = ruby_to_fieldtype(argv[1]);
+
+  // Check that the key type is an allowed type.
+  switch (self->key_type) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_BOOL:
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      // These are OK.
+      break;
+    default:
+      rb_raise(rb_eArgError, "Invalid key type for map.");
+  }
+
+  init_value_arg = 2;
+  if (needs_typeclass(self->value_type) && argc > 2) {
+    self->value_type_class = argv[2];
+    validate_type_class(self->value_type, self->value_type_class);
+    init_value_arg = 3;
+  }
+
+  // Table value type is always UINT64: this ensures enough space to store the
+  // native_slot value.
+  if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) {
+    rb_raise(rb_eRuntimeError, "Could not allocate table.");
+  }
+
+  if (argc > init_value_arg) {
+    Map_merge_into_self(_self, argv[init_value_arg]);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Map.each(&block)
+ *
+ * Invokes &block on each |key, value| pair in the map, in unspecified order.
+ * Note that Map also includes Enumerable; map thus acts like a normal Ruby
+ * sequence.
+ */
+VALUE Map_each(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    VALUE key = table_key_to_ruby(
+        self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    VALUE value = native_slot_get(self->value_type,
+                                  self->value_type_class,
+                                  mem);
+
+    rb_yield_values(2, key, value);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Map.keys => [list_of_keys]
+ *
+ * Returns the list of keys contained in the map, in unspecified order.
+ */
+VALUE Map_keys(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  VALUE ret = rb_ary_new();
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    VALUE key = table_key_to_ruby(
+        self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+
+    rb_ary_push(ret, key);
+  }
+
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     Map.values => [list_of_values]
+ *
+ * Returns the list of values contained in the map, in unspecified order.
+ */
+VALUE Map_values(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  VALUE ret = rb_ary_new();
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    VALUE value = native_slot_get(self->value_type,
+                                  self->value_type_class,
+                                  mem);
+
+    rb_ary_push(ret, value);
+  }
+
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     Map.[](key) => value
+ *
+ * Accesses the element at the given key. Throws an exception if the key type is
+ * incorrect. Returns nil when the key is not present in the map.
+ */
+VALUE Map_index(VALUE _self, VALUE key) {
+  Map* self = ruby_to_Map(_self);
+
+  char keybuf[TABLE_KEY_BUF_LENGTH];
+  const char* keyval = NULL;
+  size_t length = 0;
+  upb_value v;
+  table_key(self, key, keybuf, &keyval, &length);
+
+  if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
+    void* mem = value_memory(&v);
+    return native_slot_get(self->value_type, self->value_type_class, mem);
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     Map.[]=(key, value) => value
+ *
+ * Inserts or overwrites the value at the given key with the given new value.
+ * Throws an exception if the key type is incorrect. Returns the new value that
+ * was just inserted.
+ */
+VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
+  Map* self = ruby_to_Map(_self);
+
+  char keybuf[TABLE_KEY_BUF_LENGTH];
+  const char* keyval = NULL;
+  size_t length = 0;
+  upb_value v;
+  void* mem;
+  table_key(self, key, keybuf, &keyval, &length);
+
+  mem = value_memory(&v);
+  native_slot_set(self->value_type, self->value_type_class, mem, value);
+
+  // Replace any existing value by issuing a 'remove' operation first.
+  upb_strtable_remove2(&self->table, keyval, length, NULL);
+  if (!upb_strtable_insert2(&self->table, keyval, length, v)) {
+    rb_raise(rb_eRuntimeError, "Could not insert into table");
+  }
+
+  // Ruby hashmap's :[]= method also returns the inserted value.
+  return value;
+}
+
+/*
+ * call-seq:
+ *     Map.has_key?(key) => bool
+ *
+ * Returns true if the given key is present in the map. Throws an exception if
+ * the key has the wrong type.
+ */
+VALUE Map_has_key(VALUE _self, VALUE key) {
+  Map* self = ruby_to_Map(_self);
+
+  char keybuf[TABLE_KEY_BUF_LENGTH];
+  const char* keyval = NULL;
+  size_t length = 0;
+  table_key(self, key, keybuf, &keyval, &length);
+
+  if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) {
+    return Qtrue;
+  } else {
+    return Qfalse;
+  }
+}
+
+/*
+ * call-seq:
+ *     Map.delete(key) => old_value
+ *
+ * Deletes the value at the given key, if any, returning either the old value or
+ * nil if none was present. Throws an exception if the key is of the wrong type.
+ */
+VALUE Map_delete(VALUE _self, VALUE key) {
+  Map* self = ruby_to_Map(_self);
+
+  char keybuf[TABLE_KEY_BUF_LENGTH];
+  const char* keyval = NULL;
+  size_t length = 0;
+  upb_value v;
+  table_key(self, key, keybuf, &keyval, &length);
+
+  if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
+    void* mem = value_memory(&v);
+    return native_slot_get(self->value_type, self->value_type_class, mem);
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     Map.clear
+ *
+ * Removes all entries from the map.
+ */
+VALUE Map_clear(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  // Uninit and reinit the table -- this is faster than iterating and doing a
+  // delete-lookup on each key.
+  upb_strtable_uninit(&self->table);
+  if (!upb_strtable_init(&self->table, UPB_CTYPE_INT64)) {
+    rb_raise(rb_eRuntimeError, "Unable to re-initialize table");
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Map.length
+ *
+ * Returns the number of entries (key-value pairs) in the map.
+ */
+VALUE Map_length(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  return ULL2NUM(upb_strtable_count(&self->table));
+}
+
+static VALUE Map_new_this_type(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  VALUE new_map = Qnil;
+  VALUE key_type = fieldtype_to_ruby(self->key_type);
+  VALUE value_type = fieldtype_to_ruby(self->value_type);
+  if (self->value_type_class != Qnil) {
+    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 3,
+                         key_type, value_type, self->value_type_class);
+  } else {
+    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
+                         key_type, value_type);
+  }
+  return new_map;
+}
+
+/*
+ * call-seq:
+ *     Map.dup => new_map
+ *
+ * Duplicates this map with a shallow copy. References to all non-primitive
+ * element objects (e.g., submessages) are shared.
+ */
+VALUE Map_dup(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  VALUE new_map = Map_new_this_type(_self);
+  Map* new_self = ruby_to_Map(new_map);
+
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    upb_value dup;
+    void* dup_mem = value_memory(&dup);
+    native_slot_dup(self->value_type, dup_mem, mem);
+
+    if (!upb_strtable_insert2(&new_self->table,
+                              upb_strtable_iter_key(&it),
+                              upb_strtable_iter_keylength(&it),
+                              dup)) {
+      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
+    }
+  }
+
+  return new_map;
+}
+
+// Used by Google::Protobuf.deep_copy but not exposed directly.
+VALUE Map_deep_copy(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  VALUE new_map = Map_new_this_type(_self);
+  Map* new_self = ruby_to_Map(new_map);
+
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    upb_value dup;
+    void* dup_mem = value_memory(&dup);
+    native_slot_deep_copy(self->value_type, dup_mem, mem);
+
+    if (!upb_strtable_insert2(&new_self->table,
+                              upb_strtable_iter_key(&it),
+                              upb_strtable_iter_keylength(&it),
+                              dup)) {
+      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
+    }
+  }
+
+  return new_map;
+}
+
+/*
+ * call-seq:
+ *     Map.==(other) => boolean
+ *
+ * Compares this map to another. Maps are equal if they have identical key sets,
+ * and for each key, the values in both maps compare equal. Elements are
+ * compared as per normal Ruby semantics, by calling their :== methods (or
+ * performing a more efficient comparison for primitive types).
+ *
+ * Maps with dissimilar key types or value types/typeclasses are never equal,
+ * even if value comparison (for example, between integers and floats) would
+ * have otherwise indicated that every element has equal value.
+ */
+VALUE Map_eq(VALUE _self, VALUE _other) {
+  Map* self = ruby_to_Map(_self);
+  Map* other;
+  upb_strtable_iter it;
+
+  // Allow comparisons to Ruby hashmaps by converting to a temporary Map
+  // instance. Slow, but workable.
+  if (TYPE(_other) == T_HASH) {
+    VALUE other_map = Map_new_this_type(_self);
+    Map_merge_into_self(other_map, _other);
+    _other = other_map;
+  }
+
+  other = ruby_to_Map(_other);
+
+  if (self == other) {
+    return Qtrue;
+  }
+  if (self->key_type != other->key_type ||
+      self->value_type != other->value_type ||
+      self->value_type_class != other->value_type_class) {
+    return Qfalse;
+  }
+  if (upb_strtable_count(&self->table) != upb_strtable_count(&other->table)) {
+    return Qfalse;
+  }
+
+  // For each member of self, check that an equal member exists at the same key
+  // in other.
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    upb_value other_v;
+    void* other_mem = value_memory(&other_v);
+
+    if (!upb_strtable_lookup2(&other->table,
+                              upb_strtable_iter_key(&it),
+                              upb_strtable_iter_keylength(&it),
+                              &other_v)) {
+      // Not present in other map.
+      return Qfalse;
+    }
+
+    if (!native_slot_eq(self->value_type, mem, other_mem)) {
+      // Present, but value not equal.
+      return Qfalse;
+    }
+  }
+
+  return Qtrue;
+}
+
+/*
+ * call-seq:
+ *     Map.hash => hash_value
+ *
+ * Returns a hash value based on this map's contents.
+ */
+VALUE Map_hash(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  st_index_t h = rb_hash_start(0);
+  VALUE hash_sym = rb_intern("hash");
+
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+    VALUE key = table_key_to_ruby(
+        self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    VALUE value = native_slot_get(self->value_type,
+                                  self->value_type_class,
+                                  mem);
+
+    h = rb_hash_uint(h, NUM2LONG(rb_funcall(key, hash_sym, 0)));
+    h = rb_hash_uint(h, NUM2LONG(rb_funcall(value, hash_sym, 0)));
+  }
+
+  return INT2FIX(h);
+}
+
+/*
+ * call-seq:
+ *     Map.inspect => string
+ *
+ * Returns a string representing this map's elements. It will be formatted as
+ * "{key => value, key => value, ...}", with each key and value string
+ * representation computed by its own #inspect method.
+ */
+VALUE Map_inspect(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  VALUE str = rb_str_new2("{");
+
+  bool first = true;
+  VALUE inspect_sym = rb_intern("inspect");
+
+  upb_strtable_iter it;
+  for (upb_strtable_begin(&it, &self->table);
+       !upb_strtable_done(&it);
+       upb_strtable_next(&it)) {
+    VALUE key = table_key_to_ruby(
+        self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+
+    upb_value v = upb_strtable_iter_value(&it);
+    void* mem = value_memory(&v);
+    VALUE value = native_slot_get(self->value_type,
+                                  self->value_type_class,
+                                  mem);
+
+    if (!first) {
+      str = rb_str_cat2(str, ", ");
+    } else {
+      first = false;
+    }
+    str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
+    str = rb_str_cat2(str, "=>");
+    str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
+  }
+
+  str = rb_str_cat2(str, "}");
+  return str;
+}
+
+/*
+ * call-seq:
+ *     Map.merge(other_map) => map
+ *
+ * Copies key/value pairs from other_map into a copy of this map. If a key is
+ * set in other_map and this map, the value from other_map overwrites the value
+ * in the new copy of this map. Returns the new copy of this map with merged
+ * contents.
+ */
+VALUE Map_merge(VALUE _self, VALUE hashmap) {
+  VALUE dupped = Map_dup(_self);
+  return Map_merge_into_self(dupped, hashmap);
+}
+
+static int merge_into_self_callback(VALUE key, VALUE value, VALUE self) {
+  Map_index_set(self, key, value);
+  return ST_CONTINUE;
+}
+
+// Used only internally -- shared by #merge and #initialize.
+VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
+  if (TYPE(hashmap) == T_HASH) {
+    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
+  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
+             RTYPEDDATA_TYPE(hashmap) == &Map_type) {
+
+    Map* self = ruby_to_Map(_self);
+    Map* other = ruby_to_Map(hashmap);
+    upb_strtable_iter it;
+
+    if (self->key_type != other->key_type ||
+        self->value_type != other->value_type ||
+        self->value_type_class != other->value_type_class) {
+      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
+    }
+
+    for (upb_strtable_begin(&it, &other->table);
+         !upb_strtable_done(&it);
+         upb_strtable_next(&it)) {
+
+      // Replace any existing value by issuing a 'remove' operation first.
+      upb_value v;
+      upb_value oldv;
+      upb_strtable_remove2(&self->table,
+                           upb_strtable_iter_key(&it),
+                           upb_strtable_iter_keylength(&it),
+                           &oldv);
+
+      v = upb_strtable_iter_value(&it);
+      upb_strtable_insert2(&self->table,
+                           upb_strtable_iter_key(&it),
+                           upb_strtable_iter_keylength(&it),
+                           v);
+    }
+  } else {
+    rb_raise(rb_eArgError, "Unknown type merging into Map");
+  }
+  return _self;
+}
+
+// Internal method: map iterator initialization (used for serialization).
+void Map_begin(VALUE _self, Map_iter* iter) {
+  Map* self = ruby_to_Map(_self);
+  iter->self = self;
+  upb_strtable_begin(&iter->it, &self->table);
+}
+
+void Map_next(Map_iter* iter) {
+  upb_strtable_next(&iter->it);
+}
+
+bool Map_done(Map_iter* iter) {
+  return upb_strtable_done(&iter->it);
+}
+
+VALUE Map_iter_key(Map_iter* iter) {
+  return table_key_to_ruby(
+      iter->self,
+      upb_strtable_iter_key(&iter->it),
+      upb_strtable_iter_keylength(&iter->it));
+}
+
+VALUE Map_iter_value(Map_iter* iter) {
+  upb_value v = upb_strtable_iter_value(&iter->it);
+  void* mem = value_memory(&v);
+  return native_slot_get(iter->self->value_type,
+                         iter->self->value_type_class,
+                         mem);
+}
+
+void Map_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
+  rb_define_alloc_func(klass, Map_alloc);
+  cMap = klass;
+  rb_gc_register_address(&cMap);
+
+  rb_define_method(klass, "initialize", Map_init, -1);
+  rb_define_method(klass, "each", Map_each, 0);
+  rb_define_method(klass, "keys", Map_keys, 0);
+  rb_define_method(klass, "values", Map_values, 0);
+  rb_define_method(klass, "[]", Map_index, 1);
+  rb_define_method(klass, "[]=", Map_index_set, 2);
+  rb_define_method(klass, "has_key?", Map_has_key, 1);
+  rb_define_method(klass, "delete", Map_delete, 1);
+  rb_define_method(klass, "clear", Map_clear, 0);
+  rb_define_method(klass, "length", Map_length, 0);
+  rb_define_method(klass, "dup", Map_dup, 0);
+  rb_define_method(klass, "==", Map_eq, 1);
+  rb_define_method(klass, "hash", Map_hash, 0);
+  rb_define_method(klass, "inspect", Map_inspect, 0);
+  rb_define_method(klass, "merge", Map_merge, 1);
+  rb_include_module(klass, rb_mEnumerable);
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/message.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/message.c
new file mode 100644
index 0000000..e16250f
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/message.c
@@ -0,0 +1,578 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Class/module creation from msgdefs and enumdefs, respectively.
+// -----------------------------------------------------------------------------
+
+void* Message_data(void* msg) {
+  return ((uint8_t *)msg) + sizeof(MessageHeader);
+}
+
+void Message_mark(void* _self) {
+  MessageHeader* self = (MessageHeader *)_self;
+  layout_mark(self->descriptor->layout, Message_data(self));
+}
+
+void Message_free(void* self) {
+  xfree(self);
+}
+
+rb_data_type_t Message_type = {
+  "Message",
+  { Message_mark, Message_free, NULL },
+};
+
+VALUE Message_alloc(VALUE klass) {
+  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
+  Descriptor* desc = ruby_to_Descriptor(descriptor);
+  MessageHeader* msg = (MessageHeader*)ALLOC_N(
+      uint8_t, sizeof(MessageHeader) + desc->layout->size);
+  VALUE ret;
+
+  memset(Message_data(msg), 0, desc->layout->size);
+
+  // We wrap first so that everything in the message object is GC-rooted in case
+  // a collection happens during object creation in layout_init().
+  ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
+  msg->descriptor = desc;
+  rb_ivar_set(ret, descriptor_instancevar_interned, descriptor);
+
+  layout_init(desc->layout, Message_data(msg));
+
+  return ret;
+}
+
+static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
+  upb_oneof_iter it;
+  size_t case_ofs;
+  uint32_t oneof_case;
+  const upb_fielddef* first_field;
+  const upb_fielddef* f;
+
+  // If no fields in the oneof, always nil.
+  if (upb_oneofdef_numfields(o) == 0) {
+    return Qnil;
+  }
+  // Grab the first field in the oneof so we can get its layout info to find the
+  // oneof_case field.
+  upb_oneof_begin(&it, o);
+  assert(!upb_oneof_done(&it));
+  first_field = upb_oneof_iter_field(&it);
+  assert(upb_fielddef_containingoneof(first_field) != NULL);
+
+  case_ofs =
+      self->descriptor->layout->
+      fields[upb_fielddef_index(first_field)].case_offset;
+  oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs));
+
+  if (oneof_case == ONEOF_CASE_NONE) {
+    return Qnil;
+  }
+
+  // oneof_case is a field index, so find that field.
+  f = upb_oneofdef_itof(o, oneof_case);
+  assert(f != NULL);
+
+  return ID2SYM(rb_intern(upb_fielddef_name(f)));
+}
+
+/*
+ * call-seq:
+ *     Message.method_missing(*args)
+ *
+ * Provides accessors and setters for message fields according to their field
+ * names. For any field whose name does not conflict with a built-in method, an
+ * accessor is provided with the same name as the field, and a setter is
+ * provided with the name of the field plus the '=' suffix. Thus, given a
+ * message instance 'msg' with field 'foo', the following code is valid:
+ *
+ *     msg.foo = 42
+ *     puts msg.foo
+ *
+ * This method also provides read-only accessors for oneofs. If a oneof exists
+ * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
+ * the name of the field in that oneof that is currently set, or nil if none.
+ */
+VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
+  MessageHeader* self;
+  VALUE method_name, method_str;
+  char* name;
+  size_t name_len;
+  bool setter;
+  const upb_oneofdef* o;
+  const upb_fielddef* f;
+
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  if (argc < 1) {
+    rb_raise(rb_eArgError, "Expected method name as first argument.");
+  }
+  method_name = argv[0];
+  if (!SYMBOL_P(method_name)) {
+    rb_raise(rb_eArgError, "Expected symbol as method name.");
+  }
+  method_str = rb_id2str(SYM2ID(method_name));
+  name = RSTRING_PTR(method_str);
+  name_len = RSTRING_LEN(method_str);
+  setter = false;
+
+  // Setters have names that end in '='.
+  if (name[name_len - 1] == '=') {
+    setter = true;
+    name_len--;
+  }
+
+  // See if this name corresponds to either a oneof or field in this message.
+  if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f,
+                             &o)) {
+    return rb_call_super(argc, argv);
+  }
+
+  if (o != NULL) {
+    // This is a oneof -- return which field inside the oneof is set.
+    if (setter) {
+      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
+    }
+    return which_oneof_field(self, o);
+  } else {
+    // This is a field -- get or set the field's value.
+    assert(f);
+    if (setter) {
+      if (argc < 2) {
+        rb_raise(rb_eArgError, "No value provided to setter.");
+      }
+      layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
+      return Qnil;
+    } else {
+      return layout_get(self->descriptor->layout, Message_data(self), f);
+    }
+  }
+}
+
+int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+  MessageHeader* self;
+  VALUE method_str;
+  char* name;
+  const upb_fielddef* f;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  if (!SYMBOL_P(key)) {
+    rb_raise(rb_eArgError,
+             "Expected symbols as hash keys in initialization map.");
+  }
+
+  method_str = rb_id2str(SYM2ID(key));
+  name = RSTRING_PTR(method_str);
+  f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
+  if (f == NULL) {
+    rb_raise(rb_eArgError,
+             "Unknown field name '%s' in initialization map entry.", name);
+  }
+
+  if (is_map_field(f)) {
+    VALUE map;
+
+    if (TYPE(val) != T_HASH) {
+      rb_raise(rb_eArgError,
+               "Expected Hash object as initializer value for map field '%s'.", name);
+    }
+    map = layout_get(self->descriptor->layout, Message_data(self), f);
+    Map_merge_into_self(map, val);
+  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+    VALUE ary;
+
+    if (TYPE(val) != T_ARRAY) {
+      rb_raise(rb_eArgError,
+               "Expected array as initializer value for repeated field '%s'.", name);
+    }
+    ary = layout_get(self->descriptor->layout, Message_data(self), f);
+    for (int i = 0; i < RARRAY_LEN(val); i++) {
+      RepeatedField_push(ary, rb_ary_entry(val, i));
+    }
+  } else {
+    layout_set(self->descriptor->layout, Message_data(self), f, val);
+  }
+  return 0;
+}
+
+/*
+ * call-seq:
+ *     Message.new(kwargs) => new_message
+ *
+ * Creates a new instance of the given message class. Keyword arguments may be
+ * provided with keywords corresponding to field names.
+ *
+ * Note that no literal Message class exists. Only concrete classes per message
+ * type exist, as provided by the #msgclass method on Descriptors after they
+ * have been added to a pool. The method definitions described here on the
+ * Message class are provided on each concrete message class.
+ */
+VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
+  VALUE hash_args;
+
+  if (argc == 0) {
+    return Qnil;
+  }
+  if (argc != 1) {
+    rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
+  }
+  hash_args = argv[0];
+  if (TYPE(hash_args) != T_HASH) {
+    rb_raise(rb_eArgError, "Expected hash arguments.");
+  }
+
+  rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Message.dup => new_message
+ *
+ * Performs a shallow copy of this message and returns the new copy.
+ */
+VALUE Message_dup(VALUE _self) {
+  MessageHeader* self;
+  VALUE new_msg;
+  MessageHeader* new_msg_self;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+
+  layout_dup(self->descriptor->layout,
+             Message_data(new_msg_self),
+             Message_data(self));
+
+  return new_msg;
+}
+
+// Internal only; used by Google::Protobuf.deep_copy.
+VALUE Message_deep_copy(VALUE _self) {
+  MessageHeader* self;
+  MessageHeader* new_msg_self;
+  VALUE new_msg;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+
+  layout_deep_copy(self->descriptor->layout,
+                   Message_data(new_msg_self),
+                   Message_data(self));
+
+  return new_msg;
+}
+
+/*
+ * call-seq:
+ *     Message.==(other) => boolean
+ *
+ * Performs a deep comparison of this message with another. Messages are equal
+ * if they have the same type and if each field is equal according to the :==
+ * method's semantics (a more efficient comparison may actually be done if the
+ * field is of a primitive type).
+ */
+VALUE Message_eq(VALUE _self, VALUE _other) {
+  MessageHeader* self;
+  MessageHeader* other;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
+
+  if (self->descriptor != other->descriptor) {
+    return Qfalse;
+  }
+
+  return layout_eq(self->descriptor->layout,
+                   Message_data(self),
+                   Message_data(other));
+}
+
+/*
+ * call-seq:
+ *     Message.hash => hash_value
+ *
+ * Returns a hash value that represents this message's field values.
+ */
+VALUE Message_hash(VALUE _self) {
+  MessageHeader* self;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  return layout_hash(self->descriptor->layout, Message_data(self));
+}
+
+/*
+ * call-seq:
+ *     Message.inspect => string
+ *
+ * Returns a human-readable string representing this message. It will be
+ * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
+ * field's value is represented according to its own #inspect method.
+ */
+VALUE Message_inspect(VALUE _self) {
+  MessageHeader* self;
+  VALUE str;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  str = rb_str_new2("<");
+  str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
+  str = rb_str_cat2(str, ": ");
+  str = rb_str_append(str, layout_inspect(
+      self->descriptor->layout, Message_data(self)));
+  str = rb_str_cat2(str, ">");
+  return str;
+}
+
+
+VALUE Message_to_h(VALUE _self) {
+  MessageHeader* self;
+  VALUE hash;
+  upb_msg_field_iter it;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+  hash = rb_hash_new();
+
+  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
+                                 field);
+    VALUE msg_key   = ID2SYM(rb_intern(upb_fielddef_name(field)));
+    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      msg_value = RepeatedField_to_ary(msg_value);
+    }
+    rb_hash_aset(hash, msg_key, msg_value);
+  }
+  return hash;
+}
+
+
+
+/*
+ * call-seq:
+ *     Message.[](index) => value
+ *
+ * Accesses a field's value by field name. The provided field name should be a
+ * string.
+ */
+VALUE Message_index(VALUE _self, VALUE field_name) {
+  MessageHeader* self;
+  const upb_fielddef* field;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  Check_Type(field_name, T_STRING);
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+  if (field == NULL) {
+    return Qnil;
+  }
+  return layout_get(self->descriptor->layout, Message_data(self), field);
+}
+
+/*
+ * call-seq:
+ *     Message.[]=(index, value)
+ *
+ * Sets a field's value by field name. The provided field name should be a
+ * string.
+ */
+VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
+  MessageHeader* self;
+  const upb_fielddef* field;
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  Check_Type(field_name, T_STRING);
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+  if (field == NULL) {
+    rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
+  }
+  layout_set(self->descriptor->layout, Message_data(self), field, value);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Message.descriptor => descriptor
+ *
+ * Class method that returns the Descriptor instance corresponding to this
+ * message class's type.
+ */
+VALUE Message_descriptor(VALUE klass) {
+  return rb_ivar_get(klass, descriptor_instancevar_interned);
+}
+
+VALUE build_class_from_descriptor(Descriptor* desc) {
+  const char *name;
+  VALUE klass;
+
+  if (desc->layout == NULL) {
+    desc->layout = create_layout(desc->msgdef);
+  }
+  if (desc->fill_method == NULL) {
+    desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
+  }
+
+  name = upb_msgdef_fullname(desc->msgdef);
+  if (name == NULL) {
+    rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
+  }
+
+  klass = rb_define_class_id(
+      // Docs say this parameter is ignored. User will assign return value to
+      // their own toplevel constant class name.
+      rb_intern("Message"),
+      rb_cObject);
+  rb_ivar_set(klass, descriptor_instancevar_interned,
+              get_def_obj(desc->msgdef));
+  rb_define_alloc_func(klass, Message_alloc);
+  rb_require("google/protobuf/message_exts");
+  rb_include_module(klass, rb_eval_string("Google::Protobuf::MessageExts"));
+  rb_extend_object(
+      klass, rb_eval_string("Google::Protobuf::MessageExts::ClassMethods"));
+
+  rb_define_method(klass, "method_missing",
+                   Message_method_missing, -1);
+  rb_define_method(klass, "initialize", Message_initialize, -1);
+  rb_define_method(klass, "dup", Message_dup, 0);
+  // Also define #clone so that we don't inherit Object#clone.
+  rb_define_method(klass, "clone", Message_dup, 0);
+  rb_define_method(klass, "==", Message_eq, 1);
+  rb_define_method(klass, "hash", Message_hash, 0);
+  rb_define_method(klass, "to_h", Message_to_h, 0);
+  rb_define_method(klass, "to_hash", Message_to_h, 0);
+  rb_define_method(klass, "inspect", Message_inspect, 0);
+  rb_define_method(klass, "[]", Message_index, 1);
+  rb_define_method(klass, "[]=", Message_index_set, 2);
+  rb_define_singleton_method(klass, "decode", Message_decode, 1);
+  rb_define_singleton_method(klass, "encode", Message_encode, 1);
+  rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
+  rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
+  rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
+
+  return klass;
+}
+
+/*
+ * call-seq:
+ *     Enum.lookup(number) => name
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by number and returns its name as a Ruby symbol, or nil if not found.
+ */
+VALUE enum_lookup(VALUE self, VALUE number) {
+  int32_t num = NUM2INT(number);
+  VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
+  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+
+  const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
+  if (name == NULL) {
+    return Qnil;
+  } else {
+    return ID2SYM(rb_intern(name));
+  }
+}
+
+/*
+ * call-seq:
+ *     Enum.resolve(name) => number
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by name (as a Ruby symbol) and returns its name, or nil if not found.
+ */
+VALUE enum_resolve(VALUE self, VALUE sym) {
+  const char* name = rb_id2name(SYM2ID(sym));
+  VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
+  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+
+  int32_t num = 0;
+  bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
+  if (!found) {
+    return Qnil;
+  } else {
+    return INT2NUM(num);
+  }
+}
+
+/*
+ * call-seq:
+ *     Enum.descriptor
+ *
+ * This module method, provided on each generated enum module, returns the
+ * EnumDescriptor corresponding to this enum type.
+ */
+VALUE enum_descriptor(VALUE self) {
+  return rb_ivar_get(self, descriptor_instancevar_interned);
+}
+
+VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
+  VALUE mod = rb_define_module_id(
+      rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
+
+  upb_enum_iter it;
+  for (upb_enum_begin(&it, enumdesc->enumdef);
+       !upb_enum_done(&it);
+       upb_enum_next(&it)) {
+    const char* name = upb_enum_iter_name(&it);
+    int32_t value = upb_enum_iter_number(&it);
+    if (name[0] < 'A' || name[0] > 'Z') {
+      rb_raise(rb_eTypeError,
+               "Enum value '%s' does not start with an uppercase letter "
+               "as is required for Ruby constants.",
+               name);
+    }
+    rb_define_const(mod, name, INT2NUM(value));
+  }
+
+  rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
+  rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
+  rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
+  rb_ivar_set(mod, descriptor_instancevar_interned,
+              get_def_obj(enumdesc->enumdef));
+
+  return mod;
+}
+
+/*
+ * call-seq:
+ *     Google::Protobuf.deep_copy(obj) => copy_of_obj
+ *
+ * Performs a deep copy of a RepeatedField instance, a Map instance, or a
+ * message object, recursively copying its members.
+ */
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
+  VALUE klass = CLASS_OF(obj);
+  if (klass == cRepeatedField) {
+    return RepeatedField_deep_copy(obj);
+  } else if (klass == cMap) {
+    return Map_deep_copy(obj);
+  } else {
+    return Message_deep_copy(obj);
+  }
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.c
new file mode 100644
index 0000000..7cde4ae
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.c
@@ -0,0 +1,115 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+
+// This is a hash table from def objects (encoded by converting pointers to
+// Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
+VALUE upb_def_to_ruby_obj_map;
+
+VALUE cError;
+VALUE cParseError;
+
+void add_def_obj(const void* def, VALUE value) {
+  rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
+}
+
+VALUE get_def_obj(const void* def) {
+  return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def));
+}
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+// Raises a Ruby error if |status| is not OK, using its error message.
+void check_upb_status(const upb_status* status, const char* msg) {
+  if (!upb_ok(status)) {
+    rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status));
+  }
+}
+
+// String encodings: we look these up once, at load time, and then cache them
+// here.
+rb_encoding* kRubyStringUtf8Encoding;
+rb_encoding* kRubyStringASCIIEncoding;
+rb_encoding* kRubyString8bitEncoding;
+
+// Ruby-interned string: "descriptor". We use this identifier to store an
+// instance variable on message classes we create in order to link them back to
+// their descriptors.
+//
+// We intern this once at module load time then use the interned identifier at
+// runtime in order to avoid the cost of repeatedly interning in hot paths.
+const char* kDescriptorInstanceVar = "descriptor";
+ID descriptor_instancevar_interned;
+
+// -----------------------------------------------------------------------------
+// Initialization/entry point.
+// -----------------------------------------------------------------------------
+
+// This must be named "Init_protobuf_c" because the Ruby module is named
+// "protobuf_c" -- the VM looks for this symbol in our .so.
+void Init_protobuf_c() {
+  VALUE google = rb_define_module("Google");
+  VALUE protobuf = rb_define_module_under(google, "Protobuf");
+  VALUE internal = rb_define_module_under(protobuf, "Internal");
+
+  descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
+  DescriptorPool_register(protobuf);
+  Descriptor_register(protobuf);
+  FieldDescriptor_register(protobuf);
+  OneofDescriptor_register(protobuf);
+  EnumDescriptor_register(protobuf);
+  MessageBuilderContext_register(internal);
+  OneofBuilderContext_register(internal);
+  EnumBuilderContext_register(internal);
+  Builder_register(internal);
+  RepeatedField_register(protobuf);
+  Map_register(protobuf);
+
+  cError = rb_const_get(protobuf, rb_intern("Error"));
+  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+
+  rb_define_singleton_method(protobuf, "deep_copy",
+                             Google_Protobuf_deep_copy, 1);
+
+  kRubyStringUtf8Encoding = rb_utf8_encoding();
+  kRubyStringASCIIEncoding = rb_usascii_encoding();
+  kRubyString8bitEncoding = rb_ascii8bit_encoding();
+
+  upb_def_to_ruby_obj_map = rb_hash_new();
+  rb_gc_register_address(&upb_def_to_ruby_obj_map);
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.h b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.h
new file mode 100644
index 0000000..2834c89
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/protobuf.h
@@ -0,0 +1,538 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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_RUBY_PROTOBUF_H__
+#define __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
+
+#include <ruby/ruby.h>
+#include <ruby/vm.h>
+#include <ruby/encoding.h>
+
+#include "upb.h"
+
+// Forward decls.
+struct DescriptorPool;
+struct Descriptor;
+struct FieldDescriptor;
+struct EnumDescriptor;
+struct MessageLayout;
+struct MessageField;
+struct MessageHeader;
+struct MessageBuilderContext;
+struct EnumBuilderContext;
+struct Builder;
+
+typedef struct DescriptorPool DescriptorPool;
+typedef struct Descriptor Descriptor;
+typedef struct FieldDescriptor FieldDescriptor;
+typedef struct OneofDescriptor OneofDescriptor;
+typedef struct EnumDescriptor EnumDescriptor;
+typedef struct MessageLayout MessageLayout;
+typedef struct MessageField MessageField;
+typedef struct MessageHeader MessageHeader;
+typedef struct MessageBuilderContext MessageBuilderContext;
+typedef struct OneofBuilderContext OneofBuilderContext;
+typedef struct EnumBuilderContext EnumBuilderContext;
+typedef struct Builder Builder;
+
+/*
+ It can be a bit confusing how the C structs defined below and the Ruby
+ objects interact and hold references to each other. First, a few principles:
+
+ - Ruby's "TypedData" abstraction lets a Ruby VALUE hold a pointer to a C
+   struct (or arbitrary memory chunk), own it, and free it when collected.
+   Thus, each struct below will have a corresponding Ruby object
+   wrapping/owning it.
+
+ - To get back from an underlying upb {msg,enum}def to the Ruby object, we
+   keep a global hashmap, accessed by get_def_obj/add_def_obj below.
+
+ The in-memory structure is then something like:
+
+   Ruby                        |      upb
+                               |
+   DescriptorPool  ------------|-----------> upb_symtab____________________
+                               |                | (message types)          \
+                               |                v                           \
+   Descriptor   ---------------|-----------> upb_msgdef         (enum types)|
+    |--> msgclass              |                |   ^                       |
+    |    (dynamically built)   |                |   | (submsg fields)       |
+    |--> MessageLayout         |                |   |                       /
+    |--------------------------|> decoder method|   |                      /
+    \--------------------------|> serialize     |   |                     /
+                               |  handlers      v   |                    /
+   FieldDescriptor  -----------|-----------> upb_fielddef               /
+                               |                    |                  /
+                               |                    v (enum fields)   /
+   EnumDescriptor  ------------|-----------> upb_enumdef  <----------'
+                               |
+                               |
+               ^               |               \___/
+               `---------------|-----------------'    (get_def_obj map)
+ */
+
+// -----------------------------------------------------------------------------
+// Ruby class structure definitions.
+// -----------------------------------------------------------------------------
+
+struct DescriptorPool {
+  upb_symtab* symtab;
+};
+
+struct Descriptor {
+  const upb_msgdef* msgdef;
+  MessageLayout* layout;
+  VALUE klass;  // begins as nil
+  const upb_handlers* fill_handlers;
+  const upb_pbdecodermethod* fill_method;
+  const upb_json_parsermethod* json_fill_method;
+  const upb_handlers* pb_serialize_handlers;
+  const upb_handlers* json_serialize_handlers;
+  const upb_handlers* json_serialize_handlers_preserve;
+  // Handlers hold type class references for sub-message fields directly in some
+  // cases. We need to keep these rooted because they might otherwise be
+  // collected.
+  VALUE typeclass_references;
+};
+
+struct FieldDescriptor {
+  const upb_fielddef* fielddef;
+};
+
+struct OneofDescriptor {
+  const upb_oneofdef* oneofdef;
+};
+
+struct EnumDescriptor {
+  const upb_enumdef* enumdef;
+  VALUE module;  // begins as nil
+};
+
+struct MessageBuilderContext {
+  VALUE descriptor;
+  VALUE builder;
+};
+
+struct OneofBuilderContext {
+  VALUE descriptor;
+  VALUE builder;
+};
+
+struct EnumBuilderContext {
+  VALUE enumdesc;
+};
+
+struct Builder {
+  VALUE pending_list;
+  upb_def** defs;  // used only while finalizing
+};
+
+extern VALUE cDescriptorPool;
+extern VALUE cDescriptor;
+extern VALUE cFieldDescriptor;
+extern VALUE cEnumDescriptor;
+extern VALUE cMessageBuilderContext;
+extern VALUE cOneofBuilderContext;
+extern VALUE cEnumBuilderContext;
+extern VALUE cBuilder;
+
+extern VALUE cError;
+extern VALUE cParseError;
+
+// We forward-declare all of the Ruby method implementations here because we
+// sometimes call the methods directly across .c files, rather than going
+// through Ruby's method dispatching (e.g. during message parse). It's cleaner
+// to keep the list of object methods together than to split them between
+// static-in-file definitions and header declarations.
+
+void DescriptorPool_mark(void* _self);
+void DescriptorPool_free(void* _self);
+VALUE DescriptorPool_alloc(VALUE klass);
+void DescriptorPool_register(VALUE module);
+DescriptorPool* ruby_to_DescriptorPool(VALUE value);
+VALUE DescriptorPool_add(VALUE _self, VALUE def);
+VALUE DescriptorPool_build(VALUE _self);
+VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
+VALUE DescriptorPool_generated_pool(VALUE _self);
+
+void Descriptor_mark(void* _self);
+void Descriptor_free(void* _self);
+VALUE Descriptor_alloc(VALUE klass);
+void Descriptor_register(VALUE module);
+Descriptor* ruby_to_Descriptor(VALUE value);
+VALUE Descriptor_name(VALUE _self);
+VALUE Descriptor_name_set(VALUE _self, VALUE str);
+VALUE Descriptor_each(VALUE _self);
+VALUE Descriptor_lookup(VALUE _self, VALUE name);
+VALUE Descriptor_add_field(VALUE _self, VALUE obj);
+VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
+VALUE Descriptor_each_oneof(VALUE _self);
+VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
+VALUE Descriptor_msgclass(VALUE _self);
+extern const rb_data_type_t _Descriptor_type;
+
+void FieldDescriptor_mark(void* _self);
+void FieldDescriptor_free(void* _self);
+VALUE FieldDescriptor_alloc(VALUE klass);
+void FieldDescriptor_register(VALUE module);
+FieldDescriptor* ruby_to_FieldDescriptor(VALUE value);
+VALUE FieldDescriptor_name(VALUE _self);
+VALUE FieldDescriptor_name_set(VALUE _self, VALUE str);
+VALUE FieldDescriptor_type(VALUE _self);
+VALUE FieldDescriptor_type_set(VALUE _self, VALUE type);
+VALUE FieldDescriptor_label(VALUE _self);
+VALUE FieldDescriptor_label_set(VALUE _self, VALUE label);
+VALUE FieldDescriptor_number(VALUE _self);
+VALUE FieldDescriptor_number_set(VALUE _self, VALUE number);
+VALUE FieldDescriptor_submsg_name(VALUE _self);
+VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value);
+VALUE FieldDescriptor_subtype(VALUE _self);
+VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
+VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
+upb_fieldtype_t ruby_to_fieldtype(VALUE type);
+VALUE fieldtype_to_ruby(upb_fieldtype_t type);
+
+void OneofDescriptor_mark(void* _self);
+void OneofDescriptor_free(void* _self);
+VALUE OneofDescriptor_alloc(VALUE klass);
+void OneofDescriptor_register(VALUE module);
+OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
+VALUE OneofDescriptor_name(VALUE _self);
+VALUE OneofDescriptor_name_set(VALUE _self, VALUE value);
+VALUE OneofDescriptor_add_field(VALUE _self, VALUE field);
+VALUE OneofDescriptor_each(VALUE _self, VALUE field);
+
+void EnumDescriptor_mark(void* _self);
+void EnumDescriptor_free(void* _self);
+VALUE EnumDescriptor_alloc(VALUE klass);
+void EnumDescriptor_register(VALUE module);
+EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
+VALUE EnumDescriptor_name(VALUE _self);
+VALUE EnumDescriptor_name_set(VALUE _self, VALUE str);
+VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number);
+VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name);
+VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number);
+VALUE EnumDescriptor_each(VALUE _self);
+VALUE EnumDescriptor_enummodule(VALUE _self);
+extern const rb_data_type_t _EnumDescriptor_type;
+
+void MessageBuilderContext_mark(void* _self);
+void MessageBuilderContext_free(void* _self);
+VALUE MessageBuilderContext_alloc(VALUE klass);
+void MessageBuilderContext_register(VALUE module);
+MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
+VALUE MessageBuilderContext_initialize(VALUE _self,
+                                       VALUE descriptor,
+                                       VALUE builder);
+VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
+
+void OneofBuilderContext_mark(void* _self);
+void OneofBuilderContext_free(void* _self);
+VALUE OneofBuilderContext_alloc(VALUE klass);
+void OneofBuilderContext_register(VALUE module);
+OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
+VALUE OneofBuilderContext_initialize(VALUE _self,
+                                     VALUE descriptor,
+                                     VALUE builder);
+VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
+
+void EnumBuilderContext_mark(void* _self);
+void EnumBuilderContext_free(void* _self);
+VALUE EnumBuilderContext_alloc(VALUE klass);
+void EnumBuilderContext_register(VALUE module);
+EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
+VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc);
+VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
+
+void Builder_mark(void* _self);
+void Builder_free(void* _self);
+VALUE Builder_alloc(VALUE klass);
+void Builder_register(VALUE module);
+Builder* ruby_to_Builder(VALUE value);
+VALUE Builder_add_message(VALUE _self, VALUE name);
+VALUE Builder_add_enum(VALUE _self, VALUE name);
+VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
+
+// -----------------------------------------------------------------------------
+// Native slot storage abstraction.
+// -----------------------------------------------------------------------------
+
+#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
+
+size_t native_slot_size(upb_fieldtype_t type);
+void native_slot_set(upb_fieldtype_t type,
+                     VALUE type_class,
+                     void* memory,
+                     VALUE value);
+// Atomically (with respect to Ruby VM calls) either update the value and set a
+// oneof case, or do neither. If |case_memory| is null, then no case value is
+// set.
+void native_slot_set_value_and_case(upb_fieldtype_t type,
+                                    VALUE type_class,
+                                    void* memory,
+                                    VALUE value,
+                                    uint32_t* case_memory,
+                                    uint32_t case_number);
+VALUE native_slot_get(upb_fieldtype_t type,
+                      VALUE type_class,
+                      const void* memory);
+void native_slot_init(upb_fieldtype_t type, void* memory);
+void native_slot_mark(upb_fieldtype_t type, void* memory);
+void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
+void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
+bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
+
+void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value);
+void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
+
+extern rb_encoding* kRubyStringUtf8Encoding;
+extern rb_encoding* kRubyStringASCIIEncoding;
+extern rb_encoding* kRubyString8bitEncoding;
+
+VALUE field_type_class(const upb_fielddef* field);
+
+#define MAP_KEY_FIELD 1
+#define MAP_VALUE_FIELD 2
+
+// Oneof case slot value to indicate that no oneof case is set. The value `0` is
+// safe because field numbers are used as case identifiers, and no field can
+// have a number of 0.
+#define ONEOF_CASE_NONE 0
+
+// These operate on a map field (i.e., a repeated field of submessages whose
+// submessage type is a map-entry msgdef).
+bool is_map_field(const upb_fielddef* field);
+const upb_fielddef* map_field_key(const upb_fielddef* field);
+const upb_fielddef* map_field_value(const upb_fielddef* field);
+
+// These operate on a map-entry msgdef.
+const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
+const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
+
+// -----------------------------------------------------------------------------
+// Repeated field container type.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  upb_fieldtype_t field_type;
+  VALUE field_type_class;
+  void* elements;
+  int size;
+  int capacity;
+} RepeatedField;
+
+void RepeatedField_mark(void* self);
+void RepeatedField_free(void* self);
+VALUE RepeatedField_alloc(VALUE klass);
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self);
+void RepeatedField_register(VALUE module);
+
+extern const rb_data_type_t RepeatedField_type;
+extern VALUE cRepeatedField;
+
+RepeatedField* ruby_to_RepeatedField(VALUE value);
+
+VALUE RepeatedField_each(VALUE _self);
+VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self);
+void* RepeatedField_index_native(VALUE _self, int index);
+VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val);
+void RepeatedField_reserve(RepeatedField* self, int new_size);
+VALUE RepeatedField_push(VALUE _self, VALUE val);
+void RepeatedField_push_native(VALUE _self, void* data);
+VALUE RepeatedField_pop_one(VALUE _self);
+VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self);
+VALUE RepeatedField_replace(VALUE _self, VALUE list);
+VALUE RepeatedField_clear(VALUE _self);
+VALUE RepeatedField_length(VALUE _self);
+VALUE RepeatedField_dup(VALUE _self);
+VALUE RepeatedField_deep_copy(VALUE _self);
+VALUE RepeatedField_to_ary(VALUE _self);
+VALUE RepeatedField_eq(VALUE _self, VALUE _other);
+VALUE RepeatedField_hash(VALUE _self);
+VALUE RepeatedField_inspect(VALUE _self);
+VALUE RepeatedField_plus(VALUE _self, VALUE list);
+
+// Defined in repeated_field.c; also used by Map.
+void validate_type_class(upb_fieldtype_t type, VALUE klass);
+
+// -----------------------------------------------------------------------------
+// Map container type.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  upb_fieldtype_t key_type;
+  upb_fieldtype_t value_type;
+  VALUE value_type_class;
+  upb_strtable table;
+} Map;
+
+void Map_mark(void* self);
+void Map_free(void* self);
+VALUE Map_alloc(VALUE klass);
+VALUE Map_init(int argc, VALUE* argv, VALUE self);
+void Map_register(VALUE module);
+
+extern const rb_data_type_t Map_type;
+extern VALUE cMap;
+
+Map* ruby_to_Map(VALUE value);
+
+VALUE Map_each(VALUE _self);
+VALUE Map_keys(VALUE _self);
+VALUE Map_values(VALUE _self);
+VALUE Map_index(VALUE _self, VALUE key);
+VALUE Map_index_set(VALUE _self, VALUE key, VALUE value);
+VALUE Map_has_key(VALUE _self, VALUE key);
+VALUE Map_delete(VALUE _self, VALUE key);
+VALUE Map_clear(VALUE _self);
+VALUE Map_length(VALUE _self);
+VALUE Map_dup(VALUE _self);
+VALUE Map_deep_copy(VALUE _self);
+VALUE Map_eq(VALUE _self, VALUE _other);
+VALUE Map_hash(VALUE _self);
+VALUE Map_inspect(VALUE _self);
+VALUE Map_merge(VALUE _self, VALUE hashmap);
+VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
+
+typedef struct {
+  Map* self;
+  upb_strtable_iter it;
+} Map_iter;
+
+void Map_begin(VALUE _self, Map_iter* iter);
+void Map_next(Map_iter* iter);
+bool Map_done(Map_iter* iter);
+VALUE Map_iter_key(Map_iter* iter);
+VALUE Map_iter_value(Map_iter* iter);
+
+// -----------------------------------------------------------------------------
+// Message layout / storage.
+// -----------------------------------------------------------------------------
+
+#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
+
+struct MessageField {
+  size_t offset;
+  size_t case_offset;  // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
+};
+
+struct MessageLayout {
+  const upb_msgdef* msgdef;
+  MessageField* fields;
+  size_t size;
+};
+
+MessageLayout* create_layout(const upb_msgdef* msgdef);
+void free_layout(MessageLayout* layout);
+VALUE layout_get(MessageLayout* layout,
+                 const void* storage,
+                 const upb_fielddef* field);
+void layout_set(MessageLayout* layout,
+                void* storage,
+                const upb_fielddef* field,
+                VALUE val);
+void layout_init(MessageLayout* layout, void* storage);
+void layout_mark(MessageLayout* layout, void* storage);
+void layout_dup(MessageLayout* layout, void* to, void* from);
+void layout_deep_copy(MessageLayout* layout, void* to, void* from);
+VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2);
+VALUE layout_hash(MessageLayout* layout, void* storage);
+VALUE layout_inspect(MessageLayout* layout, void* storage);
+
+// -----------------------------------------------------------------------------
+// Message class creation.
+// -----------------------------------------------------------------------------
+
+struct MessageHeader {
+  Descriptor* descriptor;  // kept alive by self.class.descriptor reference.
+  // Data comes after this.
+};
+
+extern rb_data_type_t Message_type;
+
+VALUE build_class_from_descriptor(Descriptor* descriptor);
+void* Message_data(void* msg);
+void Message_mark(void* self);
+void Message_free(void* self);
+VALUE Message_alloc(VALUE klass);
+VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self);
+VALUE Message_initialize(int argc, VALUE* argv, VALUE _self);
+VALUE Message_dup(VALUE _self);
+VALUE Message_deep_copy(VALUE _self);
+VALUE Message_eq(VALUE _self, VALUE _other);
+VALUE Message_hash(VALUE _self);
+VALUE Message_inspect(VALUE _self);
+VALUE Message_index(VALUE _self, VALUE field_name);
+VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
+VALUE Message_descriptor(VALUE klass);
+VALUE Message_decode(VALUE klass, VALUE data);
+VALUE Message_encode(VALUE klass, VALUE msg_rb);
+VALUE Message_decode_json(VALUE klass, VALUE data);
+VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
+
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
+
+VALUE build_module_from_enumdesc(EnumDescriptor* enumdef);
+VALUE enum_lookup(VALUE self, VALUE number);
+VALUE enum_resolve(VALUE self, VALUE sym);
+
+const upb_pbdecodermethod *new_fillmsg_decodermethod(
+    Descriptor* descriptor, const void *owner);
+
+// Maximum depth allowed during encoding, to avoid stack overflows due to
+// cycles.
+#define ENCODE_MAX_NESTING 63
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+void add_def_obj(const void* def, VALUE value);
+VALUE get_def_obj(const void* def);
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+void check_upb_status(const upb_status* status, const char* msg);
+
+#define CHECK_UPB(code, msg) do {                                             \
+    upb_status status = UPB_STATUS_INIT;                                      \
+    code;                                                                     \
+    check_upb_status(&status, msg);                                           \
+} while (0)
+
+extern ID descriptor_instancevar_interned;
+
+#endif  // __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/repeated_field.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/repeated_field.c
new file mode 100644
index 0000000..83afbc9
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/repeated_field.c
@@ -0,0 +1,651 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Repeated field container type.
+// -----------------------------------------------------------------------------
+
+const rb_data_type_t RepeatedField_type = {
+  "Google::Protobuf::RepeatedField",
+  { RepeatedField_mark, RepeatedField_free, NULL },
+};
+
+VALUE cRepeatedField;
+
+RepeatedField* ruby_to_RepeatedField(VALUE _self) {
+  RepeatedField* self;
+  TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
+  return self;
+}
+
+void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) {
+  return ((uint8_t *)self->elements) + index * element_size;
+}
+
+static int index_position(VALUE _index, RepeatedField* repeated_field) {
+  int index = NUM2INT(_index);
+  if (index < 0 && repeated_field->size > 0) {
+    index = repeated_field->size + index;
+  }
+  return index;
+}
+
+VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  int element_size = native_slot_size(self->field_type);
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+
+  size_t off = beg * element_size;
+  VALUE ary = rb_ary_new2(len);
+  for (int i = beg; i < beg + len; i++, off += element_size) {
+    void* mem = ((uint8_t *)self->elements) + off;
+    VALUE elem = native_slot_get(field_type, field_type_class, mem);
+    rb_ary_push(ary, elem);
+  }
+  return ary;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.each(&block)
+ *
+ * Invokes the block once for each element of the repeated field. RepeatedField
+ * also includes Enumerable; combined with this method, the repeated field thus
+ * acts like an ordinary Ruby sequence.
+ */
+VALUE RepeatedField_each(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+  int element_size = native_slot_size(field_type);
+
+  size_t off = 0;
+  for (int i = 0; i < self->size; i++, off += element_size) {
+    void* memory = (void *) (((uint8_t *)self->elements) + off);
+    VALUE val = native_slot_get(field_type, field_type_class, memory);
+    rb_yield(val);
+  }
+  return _self;
+}
+
+
+/*
+ * call-seq:
+ *     RepeatedField.[](index) => value
+ *
+ * Accesses the element at the given index. Returns nil on out-of-bounds
+ */
+VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  int element_size = native_slot_size(self->field_type);
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+
+  VALUE arg = argv[0];
+  long beg, len;
+
+  if (argc == 1){
+    if (FIXNUM_P(arg)) {
+      /* standard case */
+      void* memory;
+      int index = index_position(argv[0], self);
+      if (index < 0 || index >= self->size) {
+        return Qnil;
+      }
+      memory = RepeatedField_memoryat(self, index, element_size);
+      return native_slot_get(field_type, field_type_class, memory);
+    }else{
+      /* check if idx is Range */
+      switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) {
+        case Qfalse:
+          break;
+        case Qnil:
+          return Qnil;
+        default:
+          return RepeatedField_subarray(_self, beg, len);
+      }
+    }
+  }
+  /* assume 2 arguments */
+  beg = NUM2LONG(argv[0]);
+  len = NUM2LONG(argv[1]);
+  if (beg < 0) {
+    beg += self->size;
+  }
+  if (beg >= self->size) {
+    return Qnil;
+  }
+  return RepeatedField_subarray(_self, beg, len);
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.[]=(index, value)
+ *
+ * Sets the element at the given index. On out-of-bounds assignments, extends
+ * the array and fills the hole (if any) with default values.
+ */
+VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+  int element_size = native_slot_size(field_type);
+  void* memory;
+
+  int index = index_position(_index, self);
+  if (index < 0 || index >= (INT_MAX - 1)) {
+    return Qnil;
+  }
+  if (index >= self->size) {
+    upb_fieldtype_t field_type = self->field_type;
+    int element_size = native_slot_size(field_type);
+    RepeatedField_reserve(self, index + 1);
+    for (int i = self->size; i <= index; i++) {
+      void* elem = RepeatedField_memoryat(self, i, element_size);
+      native_slot_init(field_type, elem);
+    }
+    self->size = index + 1;
+  }
+
+  memory = RepeatedField_memoryat(self, index, element_size);
+  native_slot_set(field_type, field_type_class, memory, val);
+  return Qnil;
+}
+
+static int kInitialSize = 8;
+
+void RepeatedField_reserve(RepeatedField* self, int new_size) {
+  void* old_elems = self->elements;
+  int elem_size = native_slot_size(self->field_type);
+  if (new_size <= self->capacity) {
+    return;
+  }
+  if (self->capacity == 0) {
+    self->capacity = kInitialSize;
+  }
+  while (self->capacity < new_size) {
+    self->capacity *= 2;
+  }
+  self->elements = ALLOC_N(uint8_t, elem_size * self->capacity);
+  if (old_elems != NULL) {
+    memcpy(self->elements, old_elems, self->size * elem_size);
+    xfree(old_elems);
+  }
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.push(value)
+ *
+ * Adds a new element to the repeated field.
+ */
+VALUE RepeatedField_push(VALUE _self, VALUE val) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  int element_size = native_slot_size(field_type);
+  void* memory;
+
+  RepeatedField_reserve(self, self->size + 1);
+  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
+  native_slot_set(field_type, self->field_type_class, memory, val);
+  // native_slot_set may raise an error; bump size only after set.
+  self->size++;
+  return _self;
+}
+
+
+// Used by parsing handlers.
+void RepeatedField_push_native(VALUE _self, void* data) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  int element_size = native_slot_size(field_type);
+  void* memory;
+
+  RepeatedField_reserve(self, self->size + 1);
+  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
+  memcpy(memory, data, element_size);
+  self->size++;
+}
+
+void* RepeatedField_index_native(VALUE _self, int index) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  int element_size = native_slot_size(field_type);
+  return RepeatedField_memoryat(self, index, element_size);
+}
+
+/*
+ * Private ruby method, used by RepeatedField.pop
+ */
+VALUE RepeatedField_pop_one(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+  int element_size = native_slot_size(field_type);
+  int index;
+  void* memory;
+  VALUE ret;
+
+  if (self->size == 0) {
+    return Qnil;
+  }
+  index = self->size - 1;
+  memory = RepeatedField_memoryat(self, index, element_size);
+  ret = native_slot_get(field_type, field_type_class, memory);
+  self->size--;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.replace(list)
+ *
+ * Replaces the contents of the repeated field with the given list of elements.
+ */
+VALUE RepeatedField_replace(VALUE _self, VALUE list) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  Check_Type(list, T_ARRAY);
+  self->size = 0;
+  for (int i = 0; i < RARRAY_LEN(list); i++) {
+    RepeatedField_push(_self, rb_ary_entry(list, i));
+  }
+  return list;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.clear
+ *
+ * Clears (removes all elements from) this repeated field.
+ */
+VALUE RepeatedField_clear(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  self->size = 0;
+  return _self;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.length
+ *
+ * Returns the length of this repeated field.
+ */
+VALUE RepeatedField_length(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  return INT2NUM(self->size);
+}
+
+static VALUE RepeatedField_new_this_type(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE new_rptfield = Qnil;
+  VALUE element_type = fieldtype_to_ruby(self->field_type);
+  if (self->field_type_class != Qnil) {
+    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
+                              element_type, self->field_type_class);
+  } else {
+    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
+                              element_type);
+  }
+  return new_rptfield;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.dup => repeated_field
+ *
+ * Duplicates this repeated field with a shallow copy. References to all
+ * non-primitive element objects (e.g., submessages) are shared.
+ */
+VALUE RepeatedField_dup(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(_self);
+  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
+  upb_fieldtype_t field_type = self->field_type;
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  RepeatedField_reserve(new_rptfield_self, self->size);
+  for (int i = 0; i < self->size; i++, off += elem_size) {
+    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
+    void* from_mem = (uint8_t *)self->elements + off;
+    native_slot_dup(field_type, to_mem, from_mem);
+    new_rptfield_self->size++;
+  }
+
+  return new_rptfield;
+}
+
+// Internal only: used by Google::Protobuf.deep_copy.
+VALUE RepeatedField_deep_copy(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(_self);
+  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
+  upb_fieldtype_t field_type = self->field_type;
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  RepeatedField_reserve(new_rptfield_self, self->size);
+  for (int i = 0; i < self->size; i++, off += elem_size) {
+    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
+    void* from_mem = (uint8_t *)self->elements + off;
+    native_slot_deep_copy(field_type, to_mem, from_mem);
+    new_rptfield_self->size++;
+  }
+
+  return new_rptfield;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.to_ary => array
+ *
+ * Used when converted implicitly into array, e.g. compared to an Array.
+ * Also called as a fallback of Object#to_a
+ */
+VALUE RepeatedField_to_ary(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  VALUE ary = rb_ary_new2(self->size);
+  for (int i = 0; i < self->size; i++, off += elem_size) {
+    void* mem = ((uint8_t *)self->elements) + off;
+    VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
+    rb_ary_push(ary, elem);
+  }
+  return ary;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.==(other) => boolean
+ *
+ * Compares this repeated field to another. Repeated fields are equal if their
+ * element types are equal, their lengths are equal, and each element is equal.
+ * Elements are compared as per normal Ruby semantics, by calling their :==
+ * methods (or performing a more efficient comparison for primitive types).
+ *
+ * Repeated fields with dissimilar element types are never equal, even if value
+ * comparison (for example, between integers and floats) would have otherwise
+ * indicated that every element has equal value.
+ */
+VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
+  RepeatedField* self;
+  RepeatedField* other;
+
+  if (_self == _other) {
+    return Qtrue;
+  }
+
+  if (TYPE(_other) == T_ARRAY) {
+    VALUE self_ary = RepeatedField_to_ary(_self);
+    return rb_equal(self_ary, _other);
+  }
+
+  self = ruby_to_RepeatedField(_self);
+  other = ruby_to_RepeatedField(_other);
+  if (self->field_type != other->field_type ||
+      self->field_type_class != other->field_type_class ||
+      self->size != other->size) {
+    return Qfalse;
+  }
+
+  {
+    upb_fieldtype_t field_type = self->field_type;
+    size_t elem_size = native_slot_size(field_type);
+    size_t off = 0;
+    for (int i = 0; i < self->size; i++, off += elem_size) {
+      void* self_mem = ((uint8_t *)self->elements) + off;
+      void* other_mem = ((uint8_t *)other->elements) + off;
+      if (!native_slot_eq(field_type, self_mem, other_mem)) {
+        return Qfalse;
+      }
+    }
+    return Qtrue;
+  }
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.hash => hash_value
+ *
+ * Returns a hash value computed from this repeated field's elements.
+ */
+VALUE RepeatedField_hash(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+
+  VALUE hash = LL2NUM(0);
+
+  upb_fieldtype_t field_type = self->field_type;
+  VALUE field_type_class = self->field_type_class;
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  for (int i = 0; i < self->size; i++, off += elem_size) {
+    void* mem = ((uint8_t *)self->elements) + off;
+    VALUE elem = native_slot_get(field_type, field_type_class, mem);
+    hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
+    hash = rb_funcall(hash, rb_intern("^"), 1,
+                      rb_funcall(elem, rb_intern("hash"), 0));
+  }
+
+  return hash;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.+(other) => repeated field
+ *
+ * Returns a new repeated field that contains the concatenated list of this
+ * repeated field's elements and other's elements. The other (second) list may
+ * be either another repeated field or a Ruby array.
+ */
+VALUE RepeatedField_plus(VALUE _self, VALUE list) {
+  VALUE dupped = RepeatedField_dup(_self);
+
+  if (TYPE(list) == T_ARRAY) {
+    for (int i = 0; i < RARRAY_LEN(list); i++) {
+      VALUE elem = rb_ary_entry(list, i);
+      RepeatedField_push(dupped, elem);
+    }
+  } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
+             RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
+    RepeatedField* self = ruby_to_RepeatedField(_self);
+    RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
+    if (self->field_type != list_rptfield->field_type ||
+        self->field_type_class != list_rptfield->field_type_class) {
+      rb_raise(rb_eArgError,
+               "Attempt to append RepeatedField with different element type.");
+    }
+    for (int i = 0; i < list_rptfield->size; i++) {
+      void* mem = RepeatedField_index_native(list, i);
+      RepeatedField_push_native(dupped, mem);
+    }
+  } else {
+    rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
+  }
+
+  return dupped;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.concat(other) => self
+ *
+ * concats the passed in array to self.  Returns a Ruby array.
+ */
+VALUE RepeatedField_concat(VALUE _self, VALUE list) {
+  Check_Type(list, T_ARRAY);
+  for (int i = 0; i < RARRAY_LEN(list); i++) {
+    RepeatedField_push(_self, rb_ary_entry(list, i));
+  }
+  return _self;
+}
+
+
+void validate_type_class(upb_fieldtype_t type, VALUE klass) {
+  if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) {
+    rb_raise(rb_eArgError,
+             "Type class has no descriptor. Please pass a "
+             "class or enum as returned by the DescriptorPool.");
+  }
+  if (type == UPB_TYPE_MESSAGE) {
+    VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned);
+    if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
+        RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
+      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
+    }
+    if (rb_get_alloc_func(klass) != &Message_alloc) {
+      rb_raise(rb_eArgError,
+               "Message class was not returned by the DescriptorPool.");
+    }
+  } else if (type == UPB_TYPE_ENUM) {
+    VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned);
+    if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
+        RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
+      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
+    }
+  }
+}
+
+void RepeatedField_init_args(int argc, VALUE* argv,
+                             VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE ary = Qnil;
+  if (argc < 1) {
+    rb_raise(rb_eArgError, "Expected at least 1 argument.");
+  }
+  self->field_type = ruby_to_fieldtype(argv[0]);
+
+  if (self->field_type == UPB_TYPE_MESSAGE ||
+      self->field_type == UPB_TYPE_ENUM) {
+    if (argc < 2) {
+      rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
+    }
+    self->field_type_class = argv[1];
+    if (argc > 2) {
+      ary = argv[2];
+    }
+    validate_type_class(self->field_type, self->field_type_class);
+  } else {
+    if (argc > 2) {
+      rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
+    }
+    if (argc > 1) {
+      ary = argv[1];
+    }
+  }
+
+  if (ary != Qnil) {
+    if (!RB_TYPE_P(ary, T_ARRAY)) {
+      rb_raise(rb_eArgError, "Expected array as initialize argument");
+    }
+    for (int i = 0; i < RARRAY_LEN(ary); i++) {
+      RepeatedField_push(_self, rb_ary_entry(ary, i));
+    }
+  }
+}
+
+// Mark, free, alloc, init and class setup functions.
+
+void RepeatedField_mark(void* _self) {
+  RepeatedField* self = (RepeatedField*)_self;
+  upb_fieldtype_t field_type = self->field_type;
+  int element_size = native_slot_size(field_type);
+  rb_gc_mark(self->field_type_class);
+  for (int i = 0; i < self->size; i++) {
+    void* memory = (((uint8_t *)self->elements) + i * element_size);
+    native_slot_mark(self->field_type, memory);
+  }
+}
+
+void RepeatedField_free(void* _self) {
+  RepeatedField* self = (RepeatedField*)_self;
+  xfree(self->elements);
+  xfree(self);
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.new(type, type_class = nil, initial_elems = [])
+ *
+ * Creates a new repeated field. The provided type must be a Ruby symbol, and
+ * can take on the same values as those accepted by FieldDescriptor#type=. If
+ * the type is :message or :enum, type_class must be non-nil, and must be the
+ * Ruby class or module returned by Descriptor#msgclass or
+ * EnumDescriptor#enummodule, respectively. An initial list of elements may also
+ * be provided.
+ */
+VALUE RepeatedField_alloc(VALUE klass) {
+  RepeatedField* self = ALLOC(RepeatedField);
+  self->elements = NULL;
+  self->size = 0;
+  self->capacity = 0;
+  self->field_type = -1;
+  self->field_type_class = Qnil;
+  return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
+}
+
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
+  RepeatedField_init_args(argc, argv, self);
+  return Qnil;
+}
+
+void RepeatedField_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "RepeatedField", rb_cObject);
+  rb_define_alloc_func(klass, RepeatedField_alloc);
+  cRepeatedField = klass;
+  rb_gc_register_address(&cRepeatedField);
+
+  rb_define_method(klass, "initialize",
+                   RepeatedField_init, -1);
+  rb_define_method(klass, "each", RepeatedField_each, 0);
+  rb_define_method(klass, "[]", RepeatedField_index, -1);
+  rb_define_method(klass, "at", RepeatedField_index, -1);
+  rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
+  rb_define_method(klass, "push", RepeatedField_push, 1);
+  rb_define_method(klass, "<<", RepeatedField_push, 1);
+  rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
+  rb_define_method(klass, "replace", RepeatedField_replace, 1);
+  rb_define_method(klass, "clear", RepeatedField_clear, 0);
+  rb_define_method(klass, "length", RepeatedField_length, 0);
+  rb_define_method(klass, "size", RepeatedField_length, 0);
+  rb_define_method(klass, "dup", RepeatedField_dup, 0);
+  // Also define #clone so that we don't inherit Object#clone.
+  rb_define_method(klass, "clone", RepeatedField_dup, 0);
+  rb_define_method(klass, "==", RepeatedField_eq, 1);
+  rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
+  rb_define_method(klass, "hash", RepeatedField_hash, 0);
+  rb_define_method(klass, "+", RepeatedField_plus, 1);
+  rb_define_method(klass, "concat", RepeatedField_concat, 1);
+  rb_include_module(klass, rb_mEnumerable);
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/storage.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/storage.c
new file mode 100644
index 0000000..b1f65f4
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/storage.c
@@ -0,0 +1,863 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include "protobuf.h"
+
+#include <math.h>
+
+#include <ruby/encoding.h>
+
+// -----------------------------------------------------------------------------
+// Ruby <-> native slot management.
+// -----------------------------------------------------------------------------
+
+#define DEREF(memory, type) *(type*)(memory)
+
+size_t native_slot_size(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_FLOAT:   return 4;
+    case UPB_TYPE_DOUBLE:  return 8;
+    case UPB_TYPE_BOOL:    return 1;
+    case UPB_TYPE_STRING:  return sizeof(VALUE);
+    case UPB_TYPE_BYTES:   return sizeof(VALUE);
+    case UPB_TYPE_MESSAGE: return sizeof(VALUE);
+    case UPB_TYPE_ENUM:    return 4;
+    case UPB_TYPE_INT32:   return 4;
+    case UPB_TYPE_INT64:   return 8;
+    case UPB_TYPE_UINT32:  return 4;
+    case UPB_TYPE_UINT64:  return 8;
+    default: return 0;
+  }
+}
+
+static bool is_ruby_num(VALUE value) {
+  return (TYPE(value) == T_FLOAT ||
+          TYPE(value) == T_FIXNUM ||
+          TYPE(value) == T_BIGNUM);
+}
+
+void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
+  if (!is_ruby_num(val)) {
+    rb_raise(rb_eTypeError, "Expected number type for integral field.");
+  }
+
+  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
+  // bound; we just need to do precision checks (i.e., disallow rounding) and
+  // check for < 0 on unsigned types.
+  if (TYPE(val) == T_FLOAT) {
+    double dbl_val = NUM2DBL(val);
+    if (floor(dbl_val) != dbl_val) {
+      rb_raise(rb_eRangeError,
+               "Non-integral floating point value assigned to integer field.");
+    }
+  }
+  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
+    if (NUM2DBL(val) < 0) {
+      rb_raise(rb_eRangeError,
+               "Assigning negative value to unsigned integer field.");
+    }
+  }
+}
+
+void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
+  bool bad_encoding = false;
+  rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
+  if (type == UPB_TYPE_STRING) {
+    bad_encoding =
+        string_encoding != kRubyStringUtf8Encoding &&
+        string_encoding != kRubyStringASCIIEncoding;
+  } else {
+    bad_encoding =
+        string_encoding != kRubyString8bitEncoding;
+  }
+  // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT
+  // (for bytes fields).
+  if (bad_encoding) {
+    rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)",
+             (type == UPB_TYPE_STRING) ? "string" : "bytes",
+             (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT",
+             rb_enc_name(string_encoding));
+  }
+}
+
+void native_slot_set(upb_fieldtype_t type, VALUE type_class,
+                     void* memory, VALUE value) {
+  native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
+}
+
+void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
+                                    void* memory, VALUE value,
+                                    uint32_t* case_memory,
+                                    uint32_t case_number) {
+  // Note that in order to atomically change the value in memory and the case
+  // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
+  // all Ruby VM calls are complete. The case is then set at the bottom of this
+  // function.
+  switch (type) {
+    case UPB_TYPE_FLOAT:
+      if (!is_ruby_num(value)) {
+        rb_raise(rb_eTypeError, "Expected number type for float field.");
+      }
+      DEREF(memory, float) = NUM2DBL(value);
+      break;
+    case UPB_TYPE_DOUBLE:
+      if (!is_ruby_num(value)) {
+        rb_raise(rb_eTypeError, "Expected number type for double field.");
+      }
+      DEREF(memory, double) = NUM2DBL(value);
+      break;
+    case UPB_TYPE_BOOL: {
+      int8_t val = -1;
+      if (value == Qtrue) {
+        val = 1;
+      } else if (value == Qfalse) {
+        val = 0;
+      } else {
+        rb_raise(rb_eTypeError, "Invalid argument for boolean field.");
+      }
+      DEREF(memory, int8_t) = val;
+      break;
+    }
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      if (CLASS_OF(value) != rb_cString) {
+        rb_raise(rb_eTypeError, "Invalid argument for string field.");
+      }
+      native_slot_validate_string_encoding(type, value);
+      DEREF(memory, VALUE) = value;
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      if (CLASS_OF(value) == CLASS_OF(Qnil)) {
+        value = Qnil;
+      } else if (CLASS_OF(value) != type_class) {
+        rb_raise(rb_eTypeError,
+                 "Invalid type %s to assign to submessage field.",
+                 rb_class2name(CLASS_OF(value)));
+      }
+      DEREF(memory, VALUE) = value;
+      break;
+    }
+    case UPB_TYPE_ENUM: {
+      int32_t int_val = 0;
+      if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
+        rb_raise(rb_eTypeError,
+                 "Expected number or symbol type for enum field.");
+      }
+      if (TYPE(value) == T_SYMBOL) {
+        // Ensure that the given symbol exists in the enum module.
+        VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
+        if (lookup == Qnil) {
+          rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
+        } else {
+          int_val = NUM2INT(lookup);
+        }
+      } else {
+        native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
+        int_val = NUM2INT(value);
+      }
+      DEREF(memory, int32_t) = int_val;
+      break;
+    }
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      native_slot_check_int_range_precision(type, value);
+      switch (type) {
+      case UPB_TYPE_INT32:
+        DEREF(memory, int32_t) = NUM2INT(value);
+        break;
+      case UPB_TYPE_INT64:
+        DEREF(memory, int64_t) = NUM2LL(value);
+        break;
+      case UPB_TYPE_UINT32:
+        DEREF(memory, uint32_t) = NUM2UINT(value);
+        break;
+      case UPB_TYPE_UINT64:
+        DEREF(memory, uint64_t) = NUM2ULL(value);
+        break;
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (case_memory != NULL) {
+    *case_memory = case_number;
+  }
+}
+
+VALUE native_slot_get(upb_fieldtype_t type,
+                      VALUE type_class,
+                      const void* memory) {
+  switch (type) {
+    case UPB_TYPE_FLOAT:
+      return DBL2NUM(DEREF(memory, float));
+    case UPB_TYPE_DOUBLE:
+      return DBL2NUM(DEREF(memory, double));
+    case UPB_TYPE_BOOL:
+      return DEREF(memory, int8_t) ? Qtrue : Qfalse;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_MESSAGE:
+      return DEREF(memory, VALUE);
+    case UPB_TYPE_ENUM: {
+      int32_t val = DEREF(memory, int32_t);
+      VALUE symbol = enum_lookup(type_class, INT2NUM(val));
+      if (symbol == Qnil) {
+        return INT2NUM(val);
+      } else {
+        return symbol;
+      }
+    }
+    case UPB_TYPE_INT32:
+      return INT2NUM(DEREF(memory, int32_t));
+    case UPB_TYPE_INT64:
+      return LL2NUM(DEREF(memory, int64_t));
+    case UPB_TYPE_UINT32:
+      return UINT2NUM(DEREF(memory, uint32_t));
+    case UPB_TYPE_UINT64:
+      return ULL2NUM(DEREF(memory, uint64_t));
+    default:
+      return Qnil;
+  }
+}
+
+void native_slot_init(upb_fieldtype_t type, void* memory) {
+  switch (type) {
+    case UPB_TYPE_FLOAT:
+      DEREF(memory, float) = 0.0;
+      break;
+    case UPB_TYPE_DOUBLE:
+      DEREF(memory, double) = 0.0;
+      break;
+    case UPB_TYPE_BOOL:
+      DEREF(memory, int8_t) = 0;
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      DEREF(memory, VALUE) = rb_str_new2("");
+      rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
+                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
+      break;
+    case UPB_TYPE_MESSAGE:
+      DEREF(memory, VALUE) = Qnil;
+      break;
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32:
+      DEREF(memory, int32_t) = 0;
+      break;
+    case UPB_TYPE_INT64:
+      DEREF(memory, int64_t) = 0;
+      break;
+    case UPB_TYPE_UINT32:
+      DEREF(memory, uint32_t) = 0;
+      break;
+    case UPB_TYPE_UINT64:
+      DEREF(memory, uint64_t) = 0;
+      break;
+    default:
+      break;
+  }
+}
+
+void native_slot_mark(upb_fieldtype_t type, void* memory) {
+  switch (type) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_MESSAGE:
+      rb_gc_mark(DEREF(memory, VALUE));
+      break;
+    default:
+      break;
+  }
+}
+
+void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
+  memcpy(to, from, native_slot_size(type));
+}
+
+void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
+  switch (type) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      VALUE from_val = DEREF(from, VALUE);
+      DEREF(to, VALUE) = (from_val != Qnil) ?
+          rb_funcall(from_val, rb_intern("dup"), 0) : Qnil;
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      VALUE from_val = DEREF(from, VALUE);
+      DEREF(to, VALUE) = (from_val != Qnil) ?
+          Message_deep_copy(from_val) : Qnil;
+      break;
+    }
+    default:
+      memcpy(to, from, native_slot_size(type));
+  }
+}
+
+bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
+  switch (type) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_MESSAGE: {
+      VALUE val1 = DEREF(mem1, VALUE);
+      VALUE val2 = DEREF(mem2, VALUE);
+      VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
+      return ret == Qtrue;
+    }
+    default:
+      return !memcmp(mem1, mem2, native_slot_size(type));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Map field utilities.
+// -----------------------------------------------------------------------------
+
+const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
+  const upb_msgdef* subdef;
+  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
+      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
+    return NULL;
+  }
+  subdef = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
+}
+
+const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
+  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
+  assert(subdef);
+  return subdef;
+}
+
+bool is_map_field(const upb_fielddef *field) {
+  return tryget_map_entry_msgdef(field) != NULL;
+}
+
+const upb_fielddef* map_field_key(const upb_fielddef* field) {
+  const upb_msgdef* subdef = map_entry_msgdef(field);
+  return map_entry_key(subdef);
+}
+
+const upb_fielddef* map_field_value(const upb_fielddef* field) {
+  const upb_msgdef* subdef = map_entry_msgdef(field);
+  return map_entry_value(subdef);
+}
+
+const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
+  const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
+  assert(key_field != NULL);
+  return key_field;
+}
+
+const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
+  const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
+  assert(value_field != NULL);
+  return value_field;
+}
+
+// -----------------------------------------------------------------------------
+// Memory layout management.
+// -----------------------------------------------------------------------------
+
+static size_t align_up_to(size_t offset, size_t granularity) {
+  // Granularity must be a power of two.
+  return (offset + granularity - 1) & ~(granularity - 1);
+}
+
+MessageLayout* create_layout(const upb_msgdef* msgdef) {
+  MessageLayout* layout = ALLOC(MessageLayout);
+  int nfields = upb_msgdef_numfields(msgdef);
+  upb_msg_field_iter it;
+  upb_msg_oneof_iter oit;
+  size_t off = 0;
+
+  layout->fields = ALLOC_N(MessageField, nfields);
+
+  for (upb_msg_field_begin(&it, msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    size_t field_size;
+
+    if (upb_fielddef_containingoneof(field)) {
+      // Oneofs are handled separately below.
+      continue;
+    }
+
+    // Allocate |field_size| bytes for this field in the layout.
+    field_size = 0;
+    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      field_size = sizeof(VALUE);
+    } else {
+      field_size = native_slot_size(upb_fielddef_type(field));
+    }
+    // Align current offset up to |size| granularity.
+    off = align_up_to(off, field_size);
+    layout->fields[upb_fielddef_index(field)].offset = off;
+    layout->fields[upb_fielddef_index(field)].case_offset =
+        MESSAGE_FIELD_NO_CASE;
+    off += field_size;
+  }
+
+  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
+  // one slot per oneof.
+  //
+  // We assign all value slots first, then pack the 'case' fields at the end,
+  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
+  // bytes respectively and we want to avoid alignment overhead.
+  //
+  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
+  // space for oneof cases is conceptually as wide as field tag numbers. In
+  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
+  // members (8 or 16 bits respectively), so conceivably we could assign
+  // consecutive case numbers and then pick a smaller oneof case slot size, but
+  // the complexity to implement this indirection is probably not worthwhile.
+  for (upb_msg_oneof_begin(&oit, msgdef);
+       !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
+    // all fields.
+    size_t field_size = NATIVE_SLOT_MAX_SIZE;
+    // Align the offset.
+    off = align_up_to(off, field_size);
+    // Assign all fields in the oneof this same offset.
+    for (upb_oneof_begin(&fit, oneof);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].offset = off;
+    }
+    off += field_size;
+  }
+
+  // Now the case fields.
+  for (upb_msg_oneof_begin(&oit, msgdef);
+       !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    size_t field_size = sizeof(uint32_t);
+    // Align the offset.
+    off = (off + field_size - 1) & ~(field_size - 1);
+    // Assign all fields in the oneof this same offset.
+    for (upb_oneof_begin(&fit, oneof);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* field = upb_oneof_iter_field(&fit);
+      layout->fields[upb_fielddef_index(field)].case_offset = off;
+    }
+    off += field_size;
+  }
+
+  layout->size = off;
+
+  layout->msgdef = msgdef;
+  upb_msgdef_ref(layout->msgdef, &layout->msgdef);
+
+  return layout;
+}
+
+void free_layout(MessageLayout* layout) {
+  xfree(layout->fields);
+  upb_msgdef_unref(layout->msgdef, &layout->msgdef);
+  xfree(layout);
+}
+
+VALUE field_type_class(const upb_fielddef* field) {
+  VALUE type_class = Qnil;
+  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+    VALUE submsgdesc =
+        get_def_obj(upb_fielddef_subdef(field));
+    type_class = Descriptor_msgclass(submsgdesc);
+  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
+    VALUE subenumdesc =
+        get_def_obj(upb_fielddef_subdef(field));
+    type_class = EnumDescriptor_enummodule(subenumdesc);
+  }
+  return type_class;
+}
+
+static void* slot_memory(MessageLayout* layout,
+                         const void* storage,
+                         const upb_fielddef* field) {
+  return ((uint8_t *)storage) +
+      layout->fields[upb_fielddef_index(field)].offset;
+}
+
+static uint32_t* slot_oneof_case(MessageLayout* layout,
+                                 const void* storage,
+                                 const upb_fielddef* field) {
+  return (uint32_t *)(((uint8_t *)storage) +
+      layout->fields[upb_fielddef_index(field)].case_offset);
+}
+
+
+VALUE layout_get(MessageLayout* layout,
+                 const void* storage,
+                 const upb_fielddef* field) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (*oneof_case != upb_fielddef_number(field)) {
+      return Qnil;
+    }
+    return native_slot_get(upb_fielddef_type(field),
+                           field_type_class(field),
+                           memory);
+  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+    return *((VALUE *)memory);
+  } else {
+    return native_slot_get(upb_fielddef_type(field),
+                           field_type_class(field),
+                           memory);
+  }
+}
+
+static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
+  RepeatedField* self;
+  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
+    rb_raise(rb_eTypeError, "Expected repeated field array");
+  }
+
+  self = ruby_to_RepeatedField(val);
+  if (self->field_type != upb_fielddef_type(field)) {
+    rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
+  }
+
+  if (self->field_type == UPB_TYPE_MESSAGE ||
+      self->field_type == UPB_TYPE_ENUM) {
+    if (self->field_type_class !=
+        get_def_obj(upb_fielddef_subdef(field))) {
+      rb_raise(rb_eTypeError,
+               "Repeated field array has wrong message/enum class");
+    }
+  }
+}
+
+static void check_map_field_type(VALUE val, const upb_fielddef* field) {
+  const upb_fielddef* key_field = map_field_key(field);
+  const upb_fielddef* value_field = map_field_value(field);
+  Map* self;
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &Map_type) {
+    rb_raise(rb_eTypeError, "Expected Map instance");
+  }
+
+  self = ruby_to_Map(val);
+  if (self->key_type != upb_fielddef_type(key_field)) {
+    rb_raise(rb_eTypeError, "Map key type does not match field's key type");
+  }
+  if (self->value_type != upb_fielddef_type(value_field)) {
+    rb_raise(rb_eTypeError, "Map value type does not match field's value type");
+  }
+  if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
+      upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
+    if (self->value_type_class !=
+        get_def_obj(upb_fielddef_subdef(value_field))) {
+      rb_raise(rb_eTypeError,
+               "Map value type has wrong message/enum class");
+    }
+  }
+}
+
+
+void layout_set(MessageLayout* layout,
+                void* storage,
+                const upb_fielddef* field,
+                VALUE val) {
+  void* memory = slot_memory(layout, storage, field);
+  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+  if (upb_fielddef_containingoneof(field)) {
+    if (val == Qnil) {
+      // Assigning nil to a oneof field clears the oneof completely.
+      *oneof_case = ONEOF_CASE_NONE;
+      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+    } else {
+      // The transition between field types for a single oneof (union) slot is
+      // somewhat complex because we need to ensure that a GC triggered at any
+      // point by a call into the Ruby VM sees a valid state for this field and
+      // does not either go off into the weeds (following what it thinks is a
+      // VALUE but is actually a different field type) or miss an object (seeing
+      // what it thinks is a primitive field but is actually a VALUE for the new
+      // field type).
+      //
+      // In order for the transition to be safe, the oneof case slot must be in
+      // sync with the value slot whenever the Ruby VM has been called. Thus, we
+      // use native_slot_set_value_and_case(), which ensures that both the value
+      // and case number are altered atomically (w.r.t. the Ruby VM).
+      native_slot_set_value_and_case(
+          upb_fielddef_type(field), field_type_class(field),
+          memory, val,
+          oneof_case, upb_fielddef_number(field));
+    }
+  } else if (is_map_field(field)) {
+    check_map_field_type(val, field);
+    DEREF(memory, VALUE) = val;
+  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+    check_repeated_field_type(val, field);
+    DEREF(memory, VALUE) = val;
+  } else {
+    native_slot_set(upb_fielddef_type(field), field_type_class(field),
+                    memory, val);
+  }
+}
+
+void layout_init(MessageLayout* layout,
+                 void* storage) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    void* memory = slot_memory(layout, storage, field);
+    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+      *oneof_case = ONEOF_CASE_NONE;
+    } else if (is_map_field(field)) {
+      VALUE map = Qnil;
+
+      const upb_fielddef* key_field = map_field_key(field);
+      const upb_fielddef* value_field = map_field_value(field);
+      VALUE type_class = field_type_class(value_field);
+
+      if (type_class != Qnil) {
+        VALUE args[3] = {
+          fieldtype_to_ruby(upb_fielddef_type(key_field)),
+          fieldtype_to_ruby(upb_fielddef_type(value_field)),
+          type_class,
+        };
+        map = rb_class_new_instance(3, args, cMap);
+      } else {
+        VALUE args[2] = {
+          fieldtype_to_ruby(upb_fielddef_type(key_field)),
+          fieldtype_to_ruby(upb_fielddef_type(value_field)),
+        };
+        map = rb_class_new_instance(2, args, cMap);
+      }
+
+      DEREF(memory, VALUE) = map;
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      VALUE ary = Qnil;
+
+      VALUE type_class = field_type_class(field);
+
+      if (type_class != Qnil) {
+        VALUE args[2] = {
+          fieldtype_to_ruby(upb_fielddef_type(field)),
+          type_class,
+        };
+        ary = rb_class_new_instance(2, args, cRepeatedField);
+      } else {
+        VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
+        ary = rb_class_new_instance(1, args, cRepeatedField);
+      }
+
+      DEREF(memory, VALUE) = ary;
+    } else {
+      native_slot_init(upb_fielddef_type(field), memory);
+    }
+  }
+}
+
+void layout_mark(MessageLayout* layout, void* storage) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    void* memory = slot_memory(layout, storage, field);
+    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*oneof_case == upb_fielddef_number(field)) {
+        native_slot_mark(upb_fielddef_type(field), memory);
+      }
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      rb_gc_mark(DEREF(memory, VALUE));
+    } else {
+      native_slot_mark(upb_fielddef_type(field), memory);
+    }
+  }
+}
+
+void layout_dup(MessageLayout* layout, void* to, void* from) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+
+    void* to_memory = slot_memory(layout, to, field);
+    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
+    void* from_memory = slot_memory(layout, from, field);
+    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*from_oneof_case == upb_fielddef_number(field)) {
+        *to_oneof_case = *from_oneof_case;
+        native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
+      }
+    } else if (is_map_field(field)) {
+      DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
+    } else {
+      native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
+    }
+  }
+}
+
+void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+
+    void* to_memory = slot_memory(layout, to, field);
+    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
+    void* from_memory = slot_memory(layout, from, field);
+    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*from_oneof_case == upb_fielddef_number(field)) {
+        *to_oneof_case = *from_oneof_case;
+        native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
+      }
+    } else if (is_map_field(field)) {
+      DEREF(to_memory, VALUE) =
+          Map_deep_copy(DEREF(from_memory, VALUE));
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      DEREF(to_memory, VALUE) =
+          RepeatedField_deep_copy(DEREF(from_memory, VALUE));
+    } else {
+      native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
+    }
+  }
+}
+
+VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+
+    void* msg1_memory = slot_memory(layout, msg1, field);
+    uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
+    void* msg2_memory = slot_memory(layout, msg2, field);
+    uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
+
+    if (upb_fielddef_containingoneof(field)) {
+      if (*msg1_oneof_case != *msg2_oneof_case ||
+          (*msg1_oneof_case == upb_fielddef_number(field) &&
+           !native_slot_eq(upb_fielddef_type(field),
+                           msg1_memory,
+                           msg2_memory))) {
+        return Qfalse;
+      }
+    } else if (is_map_field(field)) {
+      if (!Map_eq(DEREF(msg1_memory, VALUE),
+                  DEREF(msg2_memory, VALUE))) {
+        return Qfalse;
+      }
+    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
+                            DEREF(msg2_memory, VALUE))) {
+        return Qfalse;
+      }
+    } else {
+      if (!native_slot_eq(upb_fielddef_type(field),
+                          msg1_memory, msg2_memory)) {
+        return Qfalse;
+      }
+    }
+  }
+  return Qtrue;
+}
+
+VALUE layout_hash(MessageLayout* layout, void* storage) {
+  upb_msg_field_iter it;
+  st_index_t h = rb_hash_start(0);
+  VALUE hash_sym = rb_intern("hash");
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE field_val = layout_get(layout, storage, field);
+    h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
+  }
+  h = rb_hash_end(h);
+
+  return INT2FIX(h);
+}
+
+VALUE layout_inspect(MessageLayout* layout, void* storage) {
+  VALUE str = rb_str_new2("");
+
+  upb_msg_field_iter it;
+  bool first = true;
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE field_val = layout_get(layout, storage, field);
+
+    if (!first) {
+      str = rb_str_cat2(str, ", ");
+    } else {
+      first = false;
+    }
+    str = rb_str_cat2(str, upb_fielddef_name(field));
+    str = rb_str_cat2(str, ": ");
+
+    str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
+  }
+
+  return str;
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.c b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.c
new file mode 100644
index 0000000..74a2a1d
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.c
@@ -0,0 +1,12812 @@
+// Amalgamated source file
+#include "upb.h"
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+  size_t len;
+  char str[1];  /* Null-terminated string data follows. */
+} str_t;
+
+static str_t *newstr(const char *data, size_t len) {
+  str_t *ret = upb_gmalloc(sizeof(*ret) + len);
+  if (!ret) return NULL;
+  ret->len = len;
+  memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static void freestr(str_t *s) { upb_gfree(s); }
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+  return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
+  bool start = true;
+  size_t i;
+  for (i = 0; i < len; i++) {
+    char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
+        return false;
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        upb_status_seterrf(
+            s, "invalid name: path components must start with a letter (%s)",
+            str);
+        return false;
+      }
+      start = false;
+    } else {
+      if (!upb_isalphanum(c)) {
+        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
+                           str);
+        return false;
+      }
+    }
+  }
+  return !start;
+}
+
+static bool upb_isoneof(const upb_refcounted *def) {
+  return def->vtbl == &upb_oneofdef_vtbl;
+}
+
+static bool upb_isfield(const upb_refcounted *def) {
+  return def->vtbl == &upb_fielddef_vtbl;
+}
+
+static const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) {
+  return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL;
+}
+
+static const upb_fielddef *upb_trygetfield(const upb_refcounted *def) {
+  return upb_isfield(def) ? (const upb_fielddef*)def : NULL;
+}
+
+
+/* upb_def ********************************************************************/
+
+upb_deftype_t upb_def_type(const upb_def *d) { return d->type; }
+
+const char *upb_def_fullname(const upb_def *d) { return d->fullname; }
+
+const char *upb_def_name(const upb_def *d) {
+  const char *p;
+
+  if (d->fullname == NULL) {
+    return NULL;
+  } else if ((p = strrchr(d->fullname, '.')) == NULL) {
+    /* No '.' in the name, return the full string. */
+    return d->fullname;
+  } else {
+    /* Return one past the last '.'. */
+    return p + 1;
+  }
+}
+
+bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
+  assert(!upb_def_isfrozen(def));
+  if (!upb_isident(fullname, strlen(fullname), true, s)) {
+    return false;
+  }
+
+  fullname = upb_gstrdup(fullname);
+  if (!fullname) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+
+  upb_gfree((void*)def->fullname);
+  def->fullname = fullname;
+  return true;
+}
+
+const upb_filedef *upb_def_file(const upb_def *d) { return d->file; }
+
+upb_def *upb_def_dup(const upb_def *def, const void *o) {
+  switch (def->type) {
+    case UPB_DEF_MSG:
+      return upb_msgdef_upcast_mutable(
+          upb_msgdef_dup(upb_downcast_msgdef(def), o));
+    case UPB_DEF_FIELD:
+      return upb_fielddef_upcast_mutable(
+          upb_fielddef_dup(upb_downcast_fielddef(def), o));
+    case UPB_DEF_ENUM:
+      return upb_enumdef_upcast_mutable(
+          upb_enumdef_dup(upb_downcast_enumdef(def), o));
+    default: assert(false); return NULL;
+  }
+}
+
+static bool upb_def_init(upb_def *def, upb_deftype_t type,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner) {
+  if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false;
+  def->type = type;
+  def->fullname = NULL;
+  def->came_from_user = false;
+  def->file = NULL;
+  return true;
+}
+
+static void upb_def_uninit(upb_def *def) {
+  upb_gfree((void*)def->fullname);
+}
+
+static const char *msgdef_name(const upb_msgdef *m) {
+  const char *name = upb_def_fullname(upb_msgdef_upcast(m));
+  return name ? name : "(anonymous)";
+}
+
+static bool upb_validate_field(upb_fielddef *f, upb_status *s) {
+  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "fielddef must have name and number set");
+    return false;
+  }
+
+  if (!f->type_is_set_) {
+    upb_status_seterrmsg(s, "fielddef type was not initialized");
+    return false;
+  }
+
+  if (upb_fielddef_lazy(f) &&
+      upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) {
+    upb_status_seterrmsg(s,
+                         "only length-delimited submessage fields may be lazy");
+    return false;
+  }
+
+  if (upb_fielddef_hassubdef(f)) {
+    const upb_def *subdef;
+
+    if (f->subdef_is_symbolic) {
+      upb_status_seterrf(s, "field '%s.%s' has not been resolved",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+
+    subdef = upb_fielddef_subdef(f);
+    if (subdef == NULL) {
+      upb_status_seterrf(s, "field %s.%s is missing required subdef",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+
+    if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) {
+      upb_status_seterrf(s,
+                         "subdef of field %s.%s is not frozen or being frozen",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f));
+      return false;
+    }
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    bool has_default_name = upb_fielddef_enumhasdefaultstr(f);
+    bool has_default_number = upb_fielddef_enumhasdefaultint32(f);
+
+    /* Previously verified by upb_validate_enumdef(). */
+    assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
+
+    /* We've already validated that we have an associated enumdef and that it
+     * has at least one member, so at least one of these should be true.
+     * Because if the user didn't set anything, we'll pick up the enum's
+     * default, but if the user *did* set something we should at least pick up
+     * the one they set (int32 or string). */
+    assert(has_default_name || has_default_number);
+
+    if (!has_default_name) {
+      upb_status_seterrf(s,
+                         "enum default for field %s.%s (%d) is not in the enum",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f),
+                         upb_fielddef_defaultint32(f));
+      return false;
+    }
+
+    if (!has_default_number) {
+      upb_status_seterrf(s,
+                         "enum default for field %s.%s (%s) is not in the enum",
+                         msgdef_name(f->msg.def), upb_fielddef_name(f),
+                         upb_fielddef_defaultstr(f, NULL));
+      return false;
+    }
+
+    /* Lift the effective numeric default into the field's default slot, in case
+     * we were only getting it "by reference" from the enumdef. */
+    upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f));
+  }
+
+  /* Ensure that MapEntry submessages only appear as repeated fields, not
+   * optional/required (singular) fields. */
+  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+      upb_fielddef_msgsubdef(f) != NULL) {
+    const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
+    if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) {
+      upb_status_seterrf(s,
+                         "Field %s refers to mapentry message but is not "
+                         "a repeated field",
+                         upb_fielddef_name(f) ? upb_fielddef_name(f) :
+                         "(unnamed)");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) {
+  if (upb_enumdef_numvals(e) == 0) {
+    upb_status_seterrf(s, "enum %s has no members (must have at least one)",
+                       upb_enumdef_fullname(e));
+    return false;
+  }
+
+  return true;
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+  uint32_t ret = upb_fielddef_number(f);
+  const uint32_t high_bit = 1 << 30;
+  assert(ret < high_bit);
+  if (!upb_fielddef_issubmsg(f))
+    ret |= high_bit;
+  return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+  return field_rank(f1) - field_rank(f2);
+}
+
+static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
+  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
+   * lowest indexes, but we do not publicly guarantee this. */
+  upb_msg_field_iter j;
+  int i;
+  uint32_t selector;
+  int n = upb_msgdef_numfields(m);
+  upb_fielddef **fields;
+
+  if (n == 0) {
+    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
+    m->submsg_field_count = 0;
+    return true;
+  }
+
+  fields = upb_gmalloc(n * sizeof(*fields));
+  if (!fields) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+
+  m->submsg_field_count = 0;
+  for(i = 0, upb_msg_field_begin(&j, m);
+      !upb_msg_field_done(&j);
+      upb_msg_field_next(&j), i++) {
+    upb_fielddef *f = upb_msg_iter_field(&j);
+    assert(f->msg.def == m);
+    if (!upb_validate_field(f, s)) {
+      upb_gfree(fields);
+      return false;
+    }
+    if (upb_fielddef_issubmsg(f)) {
+      m->submsg_field_count++;
+    }
+    fields[i] = f;
+  }
+
+  qsort(fields, n, sizeof(*fields), cmp_fields);
+
+  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = fields[i];
+    f->index_ = i;
+    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
+    selector += upb_handlers_selectorcount(f);
+  }
+  m->selector_count = selector;
+
+#ifndef NDEBUG
+  {
+    /* Verify that all selectors for the message are distinct. */
+#define TRY(type) \
+    if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v);
+
+    upb_inttable t;
+    upb_value v;
+    upb_selector_t sel;
+
+    upb_inttable_init(&t, UPB_CTYPE_BOOL);
+    v = upb_value_bool(true);
+    upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
+    upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
+    for(upb_msg_field_begin(&j, m);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+      upb_fielddef *f = upb_msg_iter_field(&j);
+      /* These calls will assert-fail in upb_table if the value already
+       * exists. */
+      TRY(UPB_HANDLER_INT32);
+      TRY(UPB_HANDLER_INT64)
+      TRY(UPB_HANDLER_UINT32)
+      TRY(UPB_HANDLER_UINT64)
+      TRY(UPB_HANDLER_FLOAT)
+      TRY(UPB_HANDLER_DOUBLE)
+      TRY(UPB_HANDLER_BOOL)
+      TRY(UPB_HANDLER_STARTSTR)
+      TRY(UPB_HANDLER_STRING)
+      TRY(UPB_HANDLER_ENDSTR)
+      TRY(UPB_HANDLER_STARTSUBMSG)
+      TRY(UPB_HANDLER_ENDSUBMSG)
+      TRY(UPB_HANDLER_STARTSEQ)
+      TRY(UPB_HANDLER_ENDSEQ)
+    }
+    upb_inttable_uninit(&t);
+  }
+#undef TRY
+#endif
+
+  upb_gfree(fields);
+  return true;
+}
+
+bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) {
+  size_t i;
+
+  /* First perform validation, in two passes so we can check that we have a
+   * transitive closure without needing to search. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    if (upb_def_isfrozen(def)) {
+      /* Could relax this requirement if it's annoying. */
+      upb_status_seterrmsg(s, "def is already frozen");
+      goto err;
+    } else if (def->type == UPB_DEF_FIELD) {
+      upb_status_seterrmsg(s, "standalone fielddefs can not be frozen");
+      goto err;
+    } else if (def->type == UPB_DEF_ENUM) {
+      if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
+        goto err;
+      }
+    } else {
+      /* Set now to detect transitive closure in the second pass. */
+      def->came_from_user = true;
+    }
+  }
+
+  /* Second pass of validation.  Also assign selector bases and indexes, and
+   * compact tables. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+    upb_enumdef *e = upb_dyncast_enumdef_mutable(def);
+    if (m) {
+      upb_inttable_compact(&m->itof);
+      if (!assign_msg_indices(m, s)) {
+        goto err;
+      }
+    } else if (e) {
+      upb_inttable_compact(&e->iton);
+    }
+  }
+
+  return true;
+
+err:
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    def->came_from_user = false;
+  }
+  assert(!(s && upb_ok(s)));
+  return false;
+}
+
+bool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) {
+  /* Def graph contains FieldDefs between each MessageDef, so double the
+   * limit. */
+  const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
+
+  if (!_upb_def_validate(defs, n, s)) {
+    return false;
+  }
+
+
+  /* Validation all passed; freeze the objects. */
+  return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth);
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+static void upb_enumdef_free(upb_refcounted *r) {
+  upb_enumdef *e = (upb_enumdef*)r;
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &e->iton);
+  for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    /* To clean up the upb_gstrdup() from upb_enumdef_addval(). */
+    upb_gfree(upb_value_getcstr(upb_inttable_iter_value(&i)));
+  }
+  upb_strtable_uninit(&e->ntoi);
+  upb_inttable_uninit(&e->iton);
+  upb_def_uninit(upb_enumdef_upcast_mutable(e));
+  upb_gfree(e);
+}
+
+const struct upb_refcounted_vtbl upb_enumdef_vtbl = {NULL, &upb_enumdef_free};
+
+upb_enumdef *upb_enumdef_new(const void *owner) {
+  upb_enumdef *e = upb_gmalloc(sizeof(*e));
+  if (!e) return NULL;
+
+  if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM,
+                    &upb_enumdef_vtbl, owner)) {
+    goto err2;
+  }
+
+  if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
+  if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
+  return e;
+
+err1:
+  upb_strtable_uninit(&e->ntoi);
+err2:
+  upb_gfree(e);
+  return NULL;
+}
+
+upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) {
+  upb_enum_iter i;
+  upb_enumdef *new_e = upb_enumdef_new(owner);
+  if (!new_e) return NULL;
+  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
+    bool success = upb_enumdef_addval(
+        new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL);
+    if (!success) {
+      upb_enumdef_unref(new_e, owner);
+      return NULL;
+    }
+  }
+  return new_e;
+}
+
+bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) {
+  upb_def *d = upb_enumdef_upcast_mutable(e);
+  return upb_def_freeze(&d, 1, status);
+}
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+  return upb_def_fullname(upb_enumdef_upcast(e));
+}
+
+const char *upb_enumdef_name(const upb_enumdef *e) {
+  return upb_def_name(upb_enumdef_upcast(e));
+}
+
+bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
+                             upb_status *s) {
+  return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s);
+}
+
+bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
+                        upb_status *status) {
+  char *name2;
+
+  if (!upb_isident(name, strlen(name), false, status)) {
+    return false;
+  }
+
+  if (upb_enumdef_ntoiz(e, name, NULL)) {
+    upb_status_seterrf(status, "name '%s' is already defined", name);
+    return false;
+  }
+
+  if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) {
+    upb_status_seterrmsg(status, "out of memory");
+    return false;
+  }
+
+  if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+    name2 = upb_gstrdup(name);
+    if (!name2 || !upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))) {
+      upb_status_seterrmsg(status, "out of memory");
+      upb_strtable_remove(&e->ntoi, name, NULL);
+      return false;
+    }
+  }
+
+  if (upb_enumdef_numvals(e) == 1) {
+    bool ok = upb_enumdef_setdefault(e, num, NULL);
+    UPB_ASSERT_VAR(ok, ok);
+  }
+
+  return true;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+  assert(upb_enumdef_iton(e, e->defaultval));
+  return e->defaultval;
+}
+
+bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) {
+  assert(!upb_enumdef_isfrozen(e));
+  if (!upb_enumdef_iton(e, val)) {
+    upb_status_seterrf(s, "number '%d' is not in the enum.", val);
+    return false;
+  }
+  e->defaultval = val;
+  return true;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+  return upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+  /* We iterate over the ntoi table, to account for duplicate numbers. */
+  upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+                      size_t len, int32_t *num) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+    return false;
+  }
+  if (num) *num = upb_value_getint32(v);
+  return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup32(&def->iton, num, &v) ?
+      upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+  return upb_strtable_iter_key(iter);
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+  return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+static void upb_fielddef_init_default(upb_fielddef *f);
+
+static void upb_fielddef_uninit_default(upb_fielddef *f) {
+  if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes)
+    freestr(f->defaultval.bytes);
+}
+
+const char *upb_fielddef_fullname(const upb_fielddef *e) {
+  return upb_def_fullname(upb_fielddef_upcast(e));
+}
+
+static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const upb_fielddef *f = (const upb_fielddef*)r;
+  if (upb_fielddef_containingtype(f)) {
+    visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure);
+  }
+  if (upb_fielddef_containingoneof(f)) {
+    visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure);
+  }
+  if (upb_fielddef_subdef(f)) {
+    visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure);
+  }
+}
+
+static void freefield(upb_refcounted *r) {
+  upb_fielddef *f = (upb_fielddef*)r;
+  upb_fielddef_uninit_default(f);
+  if (f->subdef_is_symbolic)
+    upb_gfree(f->sub.name);
+  upb_def_uninit(upb_fielddef_upcast_mutable(f));
+  upb_gfree(f);
+}
+
+static const char *enumdefaultstr(const upb_fielddef *f) {
+  const upb_enumdef *e;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  e = upb_fielddef_enumsubdef(f);
+  if (f->default_is_string && f->defaultval.bytes) {
+    /* Default was explicitly set as a string. */
+    str_t *s = f->defaultval.bytes;
+    return s->str;
+  } else if (e) {
+    if (!f->default_is_string) {
+      /* Default was explicitly set as an integer; look it up in enumdef. */
+      const char *name = upb_enumdef_iton(e, f->defaultval.sint);
+      if (name) {
+        return name;
+      }
+    } else {
+      /* Default is completely unset; pull enumdef default. */
+      if (upb_enumdef_numvals(e) > 0) {
+        const char *name = upb_enumdef_iton(e, upb_enumdef_default(e));
+        assert(name);
+        return name;
+      }
+    }
+  }
+  return NULL;
+}
+
+static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
+  const upb_enumdef *e;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  e = upb_fielddef_enumsubdef(f);
+  if (!f->default_is_string) {
+    /* Default was explicitly set as an integer. */
+    *val = f->defaultval.sint;
+    return true;
+  } else if (e) {
+    if (f->defaultval.bytes) {
+      /* Default was explicitly set as a str; try to lookup corresponding int. */
+      str_t *s = f->defaultval.bytes;
+      if (upb_enumdef_ntoiz(e, s->str, val)) {
+        return true;
+      }
+    } else {
+      /* Default is unset; try to pull in enumdef default. */
+      if (upb_enumdef_numvals(e) > 0) {
+        *val = upb_enumdef_default(e);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield};
+
+upb_fielddef *upb_fielddef_new(const void *o) {
+  upb_fielddef *f = upb_gmalloc(sizeof(*f));
+  if (!f) return NULL;
+  if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD,
+                    &upb_fielddef_vtbl, o)) {
+    upb_gfree(f);
+    return NULL;
+  }
+  f->msg.def = NULL;
+  f->sub.def = NULL;
+  f->oneof = NULL;
+  f->subdef_is_symbolic = false;
+  f->msg_is_symbolic = false;
+  f->label_ = UPB_LABEL_OPTIONAL;
+  f->type_ = UPB_TYPE_INT32;
+  f->number_ = 0;
+  f->type_is_set_ = false;
+  f->tagdelim = false;
+  f->is_extension_ = false;
+  f->lazy_ = false;
+  f->packed_ = true;
+
+  /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work
+   * with all integer types and is in some since more "default" since the most
+   * normal-looking proto2 types int32/int64/uint32/uint64 use variable.
+   *
+   * Other options to consider:
+   * - there is no default; users must set this manually (like type).
+   * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to
+   *   be an optimal default for signed integers. */
+  f->intfmt = UPB_INTFMT_VARIABLE;
+  return f;
+}
+
+upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
+  const char *srcname;
+  upb_fielddef *newf = upb_fielddef_new(owner);
+  if (!newf) return NULL;
+  upb_fielddef_settype(newf, upb_fielddef_type(f));
+  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
+  upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
+  upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
+  if (f->default_is_string && f->defaultval.bytes) {
+    str_t *s = f->defaultval.bytes;
+    upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
+  } else {
+    newf->default_is_string = f->default_is_string;
+    newf->defaultval = f->defaultval;
+  }
+
+  if (f->subdef_is_symbolic) {
+    srcname = f->sub.name;  /* Might be NULL. */
+  } else {
+    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
+  }
+  if (srcname) {
+    char *newname = upb_gmalloc(strlen(f->sub.def->fullname) + 2);
+    if (!newname) {
+      upb_fielddef_unref(newf, owner);
+      return NULL;
+    }
+    strcpy(newname, ".");
+    strcat(newname, f->sub.def->fullname);
+    upb_fielddef_setsubdefname(newf, newname, NULL);
+    upb_gfree(newname);
+  }
+
+  return newf;
+}
+
+bool upb_fielddef_typeisset(const upb_fielddef *f) {
+  return f->type_is_set_;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+  assert(f->type_is_set_);
+  return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+  return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+  return f->label_;
+}
+
+upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) {
+  return f->intfmt;
+}
+
+bool upb_fielddef_istagdelim(const upb_fielddef *f) {
+  return f->tagdelim;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+  return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+  return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+  return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+  return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+  return upb_def_fullname(upb_fielddef_upcast(f));
+}
+
+size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) {
+  const char *name = upb_fielddef_name(f);
+  size_t src, dst = 0;
+  bool ucase_next = false;
+
+#define WRITE(byte) \
+  ++dst; \
+  if (dst < len) buf[dst - 1] = byte; \
+  else if (dst == len) buf[dst - 1] = '\0'
+
+  if (!name) {
+    WRITE('\0');
+    return 0;
+  }
+
+  /* Implement the transformation as described in the spec:
+   *   1. upper case all letters after an underscore.
+   *   2. remove all underscores.
+   */
+  for (src = 0; name[src]; src++) {
+    if (name[src] == '_') {
+      ucase_next = true;
+      continue;
+    }
+
+    if (ucase_next) {
+      WRITE(toupper(name[src]));
+      ucase_next = false;
+    } else {
+      WRITE(name[src]);
+    }
+  }
+
+  WRITE('\0');
+  return dst;
+
+#undef WRITE
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+  return f->msg_is_symbolic ? NULL : f->msg.def;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
+upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
+  return (upb_msgdef*)upb_fielddef_containingtype(f);
+}
+
+const char *upb_fielddef_containingtypename(upb_fielddef *f) {
+  return f->msg_is_symbolic ? f->msg.name : NULL;
+}
+
+static void release_containingtype(upb_fielddef *f) {
+  if (f->msg_is_symbolic) upb_gfree(f->msg.name);
+}
+
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+                                        upb_status *s) {
+  char *name_copy;
+  assert(!upb_fielddef_isfrozen(f));
+  if (upb_fielddef_containingtype(f)) {
+    upb_status_seterrmsg(s, "field has already been added to a message.");
+    return false;
+  }
+  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
+   * may have a leading "."). */
+
+  name_copy = upb_gstrdup(name);
+  if (!name_copy) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+
+  release_containingtype(f);
+  f->msg.name = name_copy;
+  f->msg_is_symbolic = true;
+  return true;
+}
+
+bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
+  if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) {
+    upb_status_seterrmsg(s, "Already added to message or oneof");
+    return false;
+  }
+  return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s);
+}
+
+static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
+  UPB_UNUSED(f);
+  UPB_UNUSED(type);
+  assert(f->type_is_set_ && upb_fielddef_type(f) == type);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT64);
+  return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+  if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    int32_t val;
+    bool ok = enumdefaultint32(f, &val);
+    UPB_ASSERT_VAR(ok, ok);
+    return val;
+  } else {
+    chkdefaulttype(f, UPB_TYPE_INT32);
+    return f->defaultval.sint;
+  }
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT64);
+  return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT32);
+  return f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_BOOL);
+  return f->defaultval.uint;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_FLOAT);
+  return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_DOUBLE);
+  return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+  assert(f->type_is_set_);
+  assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+         upb_fielddef_type(f) == UPB_TYPE_ENUM);
+
+  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+    const char *ret = enumdefaultstr(f);
+    assert(ret);
+    /* Enum defaults can't have embedded NULLs. */
+    if (len) *len = strlen(ret);
+    return ret;
+  }
+
+  if (f->default_is_string) {
+    str_t *str = f->defaultval.bytes;
+    if (len) *len = str->len;
+    return str->str;
+  }
+
+  return NULL;
+}
+
+static void upb_fielddef_init_default(upb_fielddef *f) {
+  f->default_is_string = false;
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break;
+    case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64: f->defaultval.sint = 0; break;
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_BOOL: f->defaultval.uint = 0; break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      f->defaultval.bytes = newstr("", 0);
+      f->default_is_string = true;
+      break;
+    case UPB_TYPE_MESSAGE: break;
+    case UPB_TYPE_ENUM:
+      /* This is our special sentinel that indicates "not set" for an enum. */
+      f->default_is_string = true;
+      f->defaultval.bytes = NULL;
+      break;
+  }
+}
+
+const upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
+  return f->subdef_is_symbolic ? NULL : f->sub.def;
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+  const upb_def *def = upb_fielddef_subdef(f);
+  return def ? upb_dyncast_msgdef(def) : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+  const upb_def *def = upb_fielddef_subdef(f);
+  return def ? upb_dyncast_enumdef(def) : NULL;
+}
+
+upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) {
+  return (upb_def*)upb_fielddef_subdef(f);
+}
+
+const char *upb_fielddef_subdefname(const upb_fielddef *f) {
+  if (f->subdef_is_symbolic) {
+    return f->sub.name;
+  } else if (f->sub.def) {
+    return upb_def_fullname(f->sub.def);
+  } else {
+    return NULL;
+  }
+}
+
+bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
+  if (upb_fielddef_containingtype(f)) {
+    upb_status_seterrmsg(
+        s, "cannot change field number after adding to a message");
+    return false;
+  }
+  if (number == 0 || number > UPB_MAX_FIELDNUMBER) {
+    upb_status_seterrf(s, "invalid field number (%u)", number);
+    return false;
+  }
+  f->number_ = number;
+  return true;
+}
+
+void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checktype(type));
+  upb_fielddef_uninit_default(f);
+  f->type_ = type;
+  f->type_is_set_ = true;
+  upb_fielddef_init_default(f);
+}
+
+void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
+  assert(!upb_fielddef_isfrozen(f));
+  switch (type) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      upb_fielddef_settype(f, UPB_TYPE_DOUBLE);
+      break;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      upb_fielddef_settype(f, UPB_TYPE_FLOAT);
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      upb_fielddef_settype(f, UPB_TYPE_INT64);
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      upb_fielddef_settype(f, UPB_TYPE_UINT64);
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      upb_fielddef_settype(f, UPB_TYPE_INT32);
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      upb_fielddef_settype(f, UPB_TYPE_UINT32);
+      break;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      upb_fielddef_settype(f, UPB_TYPE_BOOL);
+      break;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      upb_fielddef_settype(f, UPB_TYPE_STRING);
+      break;
+    case UPB_DESCRIPTOR_TYPE_BYTES:
+      upb_fielddef_settype(f, UPB_TYPE_BYTES);
+      break;
+    case UPB_DESCRIPTOR_TYPE_GROUP:
+    case UPB_DESCRIPTOR_TYPE_MESSAGE:
+      upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
+      break;
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      upb_fielddef_settype(f, UPB_TYPE_ENUM);
+      break;
+    default: assert(false);
+  }
+
+  if (type == UPB_DESCRIPTOR_TYPE_FIXED64 ||
+      type == UPB_DESCRIPTOR_TYPE_FIXED32 ||
+      type == UPB_DESCRIPTOR_TYPE_SFIXED64 ||
+      type == UPB_DESCRIPTOR_TYPE_SFIXED32) {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED);
+  } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 ||
+             type == UPB_DESCRIPTOR_TYPE_SINT32) {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG);
+  } else {
+    upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE);
+  }
+
+  upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP);
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_FLOAT:  return UPB_DESCRIPTOR_TYPE_FLOAT;
+    case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE;
+    case UPB_TYPE_BOOL:   return UPB_DESCRIPTOR_TYPE_BOOL;
+    case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING;
+    case UPB_TYPE_BYTES:  return UPB_DESCRIPTOR_TYPE_BYTES;
+    case UPB_TYPE_ENUM:   return UPB_DESCRIPTOR_TYPE_ENUM;
+    case UPB_TYPE_INT32:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED32;
+        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT32;
+      }
+    case UPB_TYPE_INT64:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED64;
+        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT64;
+      }
+    case UPB_TYPE_UINT32:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED32;
+        case UPB_INTFMT_ZIGZAG:   return -1;
+      }
+    case UPB_TYPE_UINT64:
+      switch (upb_fielddef_intfmt(f)) {
+        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64;
+        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED64;
+        case UPB_INTFMT_ZIGZAG:   return -1;
+      }
+    case UPB_TYPE_MESSAGE:
+      return upb_fielddef_istagdelim(f) ?
+          UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE;
+  }
+  return 0;
+}
+
+void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->is_extension_ = is_extension;
+}
+
+void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->lazy_ = lazy;
+}
+
+void upb_fielddef_setpacked(upb_fielddef *f, bool packed) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->packed_ = packed;
+}
+
+void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checklabel(label));
+  f->label_ = label;
+}
+
+void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_checkintfmt(fmt));
+  f->intfmt = fmt;
+}
+
+void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
+  assert(!upb_fielddef_isfrozen(f));
+  f->tagdelim = tag_delim;
+  f->tagdelim = tag_delim;
+}
+
+static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
+  if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
+      upb_fielddef_type(f) != type) {
+    assert(false);
+    return false;
+  }
+  if (f->default_is_string) {
+    str_t *s = f->defaultval.bytes;
+    assert(s || type == UPB_TYPE_ENUM);
+    if (s) freestr(s);
+  }
+  f->default_is_string = false;
+  return true;
+}
+
+void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) {
+  if (checksetdefault(f, UPB_TYPE_INT64))
+    f->defaultval.sint = value;
+}
+
+void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) {
+  if ((upb_fielddef_type(f) == UPB_TYPE_ENUM &&
+       checksetdefault(f, UPB_TYPE_ENUM)) ||
+      checksetdefault(f, UPB_TYPE_INT32)) {
+    f->defaultval.sint = value;
+  }
+}
+
+void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) {
+  if (checksetdefault(f, UPB_TYPE_UINT64))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) {
+  if (checksetdefault(f, UPB_TYPE_UINT32))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) {
+  if (checksetdefault(f, UPB_TYPE_BOOL))
+    f->defaultval.uint = value;
+}
+
+void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) {
+  if (checksetdefault(f, UPB_TYPE_FLOAT))
+    f->defaultval.flt = value;
+}
+
+void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
+  if (checksetdefault(f, UPB_TYPE_DOUBLE))
+    f->defaultval.dbl = value;
+}
+
+bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
+                                upb_status *s) {
+  str_t *str2;
+  assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
+  if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
+    return false;
+
+  if (f->default_is_string) {
+    str_t *s = f->defaultval.bytes;
+    assert(s || f->type_ == UPB_TYPE_ENUM);
+    if (s) freestr(s);
+  } else {
+    assert(f->type_ == UPB_TYPE_ENUM);
+  }
+
+  str2 = newstr(str, len);
+  f->defaultval.bytes = str2;
+  f->default_is_string = true;
+  return true;
+}
+
+void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
+                                 upb_status *s) {
+  assert(f->type_is_set_);
+  upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s);
+}
+
+bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) {
+  int32_t val;
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  return enumdefaultint32(f, &val);
+}
+
+bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) {
+  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+  return enumdefaultstr(f) != NULL;
+}
+
+static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef,
+                                 upb_status *s) {
+  if (f->type_ == UPB_TYPE_MESSAGE) {
+    if (upb_dyncast_msgdef(subdef)) return true;
+    upb_status_seterrmsg(s, "invalid subdef type for this submessage field");
+    return false;
+  } else if (f->type_ == UPB_TYPE_ENUM) {
+    if (upb_dyncast_enumdef(subdef)) return true;
+    upb_status_seterrmsg(s, "invalid subdef type for this enum field");
+    return false;
+  } else {
+    upb_status_seterrmsg(s, "only message and enum fields can have a subdef");
+    return false;
+  }
+}
+
+static void release_subdef(upb_fielddef *f) {
+  if (f->subdef_is_symbolic) {
+    upb_gfree(f->sub.name);
+  } else if (f->sub.def) {
+    upb_unref2(f->sub.def, f);
+  }
+}
+
+bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
+                            upb_status *s) {
+  assert(!upb_fielddef_isfrozen(f));
+  assert(upb_fielddef_hassubdef(f));
+  if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false;
+  release_subdef(f);
+  f->sub.def = subdef;
+  f->subdef_is_symbolic = false;
+  if (f->sub.def) upb_ref2(f->sub.def, f);
+  return true;
+}
+
+bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
+                               upb_status *s) {
+  return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s);
+}
+
+bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
+                                upb_status *s) {
+  return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s);
+}
+
+bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
+                                upb_status *s) {
+  char *name_copy;
+  assert(!upb_fielddef_isfrozen(f));
+  if (!upb_fielddef_hassubdef(f)) {
+    upb_status_seterrmsg(s, "field type does not accept a subdef");
+    return false;
+  }
+
+  name_copy = upb_gstrdup(name);
+  if (!name_copy) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+
+  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
+   * may have a leading "."). */
+  release_subdef(f);
+  f->sub.name = name_copy;
+  f->subdef_is_symbolic = true;
+  return true;
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+  if (upb_fielddef_isseq(f)) return false;
+  if (upb_fielddef_issubmsg(f)) return true;
+
+  /* Primitive field: return true unless there is a message that specifies
+   * presence should not exist. */
+  if (f->msg_is_symbolic || !f->msg.def) return true;
+  return f->msg.def->syntax == UPB_SYNTAX_PROTO2;
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+  return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+  return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
+                     void *closure) {
+  upb_msg_oneof_iter o;
+  const upb_msgdef *m = (const upb_msgdef*)r;
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    visit(r, upb_fielddef_upcast2(f), closure);
+  }
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_msg_iter_oneof(&o);
+    visit(r, upb_oneofdef_upcast(f), closure);
+  }
+}
+
+static void freemsg(upb_refcounted *r) {
+  upb_msgdef *m = (upb_msgdef*)r;
+  upb_strtable_uninit(&m->ntof);
+  upb_inttable_uninit(&m->itof);
+  upb_def_uninit(upb_msgdef_upcast_mutable(m));
+  upb_gfree(m);
+}
+
+const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg};
+
+upb_msgdef *upb_msgdef_new(const void *owner) {
+  upb_msgdef *m = upb_gmalloc(sizeof(*m));
+  if (!m) return NULL;
+
+  if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl,
+                    owner)) {
+    goto err2;
+  }
+
+  if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
+  m->map_entry = false;
+  m->syntax = UPB_SYNTAX_PROTO2;
+  return m;
+
+err1:
+  upb_inttable_uninit(&m->itof);
+err2:
+  upb_gfree(m);
+  return NULL;
+}
+
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
+  bool ok;
+  upb_msg_field_iter i;
+  upb_msg_oneof_iter o;
+
+  upb_msgdef *newm = upb_msgdef_new(owner);
+  if (!newm) return NULL;
+  ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm),
+                           upb_def_fullname(upb_msgdef_upcast(m)),
+                           NULL);
+  newm->map_entry = m->map_entry;
+  newm->syntax = m->syntax;
+  UPB_ASSERT_VAR(ok, ok);
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
+    /* Fields in oneofs are dup'd below. */
+    if (upb_fielddef_containingoneof(f)) continue;
+    if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
+      upb_msgdef_unref(newm, owner);
+      return NULL;
+    }
+  }
+  for(upb_msg_oneof_begin(&o, m);
+      !upb_msg_oneof_done(&o);
+      upb_msg_oneof_next(&o)) {
+    upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
+    if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
+      upb_msgdef_unref(newm, owner);
+      return NULL;
+    }
+  }
+  return newm;
+}
+
+bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) {
+  upb_def *d = upb_msgdef_upcast_mutable(m);
+  return upb_def_freeze(&d, 1, status);
+}
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+  return upb_def_fullname(upb_msgdef_upcast(m));
+}
+
+const char *upb_msgdef_name(const upb_msgdef *m) {
+  return upb_def_name(upb_msgdef_upcast(m));
+}
+
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
+                            upb_status *s) {
+  return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s);
+}
+
+bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax) {
+  if (syntax != UPB_SYNTAX_PROTO2 && syntax != UPB_SYNTAX_PROTO3) {
+    return false;
+  }
+
+  m->syntax = syntax;
+  return true;
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+  return m->syntax;
+}
+
+/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
+ * on status |s| and return false if not. */
+static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
+                            upb_status *s) {
+  if (upb_fielddef_containingtype(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a message");
+    return false;
+  } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) {
+    upb_status_seterrmsg(s, "duplicate field number");
+    return false;
+  } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) {
+    upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
+    return false;
+  }
+  return true;
+}
+
+static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) {
+  release_containingtype(f);
+  f->msg.def = m;
+  f->msg_is_symbolic = false;
+  upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, m);
+  upb_ref2(m, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+}
+
+bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
+                         upb_status *s) {
+  /* TODO: extensions need to have a separate namespace, because proto2 allows a
+   * top-level extension (ie. one not in any package) to have the same name as a
+   * field from the message.
+   *
+   * This also implies that there needs to be a separate lookup-by-name method
+   * for extensions.  It seems desirable for iteration to return both extensions
+   * and non-extensions though.
+   *
+   * We also need to validate that the field number is in an extension range iff
+   * it is an extension.
+   *
+   * This method is idempotent. Check if |f| is already part of this msgdef and
+   * return immediately if so. */
+  if (upb_fielddef_containingtype(f) == m) {
+    return true;
+  }
+
+  /* Check constraints for all fields before performing any action. */
+  if (!check_field_add(m, f, s)) {
+    return false;
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    /* Fields in a oneof can only be added by adding the oneof to the msgdef. */
+    upb_status_seterrmsg(s, "fielddef is part of a oneof");
+    return false;
+  }
+
+  /* Constraint checks ok, perform the action. */
+  add_field(m, f, ref_donor);
+  return true;
+}
+
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s) {
+  upb_oneof_iter it;
+
+  /* Check various conditions that would prevent this oneof from being added. */
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneofdef already belongs to a message");
+    return false;
+  } else if (upb_oneofdef_name(o) == NULL) {
+    upb_status_seterrmsg(s, "oneofdef name was not set");
+    return false;
+  } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) {
+    upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
+    return false;
+  }
+
+  /* Check that all of the oneof's fields do not conflict with names or numbers
+   * of fields already in the message. */
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&it);
+    if (!check_field_add(m, f, s)) {
+      return false;
+    }
+  }
+
+  /* Everything checks out -- commit now. */
+
+  /* Add oneof itself first. */
+  o->parent = m;
+  upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o));
+  upb_ref2(o, m);
+  upb_ref2(m, o);
+
+  /* Add each field of the oneof directly to the msgdef. */
+  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
+    upb_fielddef *f = upb_oneof_iter_field(&it);
+    add_field(m, f, NULL);
+  }
+
+  if (ref_donor) upb_oneofdef_unref(o, ref_donor);
+
+  return true;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup32(&m->itof, i, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return upb_trygetfield(upb_value_getptr(val));
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return upb_trygetoneof(upb_value_getptr(val));
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  *o = upb_trygetoneof(upb_value_getptr(val));
+  *f = upb_trygetfield(upb_value_getptr(val));
+  assert((*o != NULL) ^ (*f != NULL));  /* Exactly one of the two should be set. */
+  return true;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+  /* The number table contains only fields. */
+  return upb_inttable_count(&m->itof);
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  /* The name table includes oneofs, and the number table does not. */
+  return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof);
+}
+
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
+  assert(!upb_msgdef_isfrozen(m));
+  m->map_entry = map_entry;
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+  return m->map_entry;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+  upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntof);
+  /* We need to skip past any initial fields. */
+  while (!upb_strtable_done(iter) &&
+         !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) {
+    upb_strtable_next(iter);
+  }
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+  /* We need to skip past fields to return only oneofs. */
+  do {
+    upb_strtable_next(iter);
+  } while (!upb_strtable_done(iter) &&
+           !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter))));
+}
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter));
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const upb_oneofdef *o = (const upb_oneofdef*)r;
+  upb_oneof_iter i;
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    const upb_fielddef *f = upb_oneof_iter_field(&i);
+    visit(r, upb_fielddef_upcast2(f), closure);
+  }
+  if (o->parent) {
+    visit(r, upb_msgdef_upcast2(o->parent), closure);
+  }
+}
+
+static void freeoneof(upb_refcounted *r) {
+  upb_oneofdef *o = (upb_oneofdef*)r;
+  upb_strtable_uninit(&o->ntof);
+  upb_inttable_uninit(&o->itof);
+  upb_gfree((void*)o->name);
+  upb_gfree(o);
+}
+
+const struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof};
+
+upb_oneofdef *upb_oneofdef_new(const void *owner) {
+  upb_oneofdef *o = upb_gmalloc(sizeof(*o));
+
+  if (!o) {
+    return NULL;
+  }
+
+  o->parent = NULL;
+  o->name = NULL;
+
+  if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_vtbl,
+                           owner)) {
+    goto err2;
+  }
+
+  if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
+
+  return o;
+
+err1:
+  upb_inttable_uninit(&o->itof);
+err2:
+  upb_gfree(o);
+  return NULL;
+}
+
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
+  bool ok;
+  upb_oneof_iter i;
+  upb_oneofdef *newo = upb_oneofdef_new(owner);
+  if (!newo) return NULL;
+  ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL);
+  UPB_ASSERT_VAR(ok, ok);
+  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+    upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
+    if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
+      upb_oneofdef_unref(newo, owner);
+      return NULL;
+    }
+  }
+  return newo;
+}
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; }
+
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) {
+  assert(!upb_oneofdef_isfrozen(o));
+  if (upb_oneofdef_containingtype(o)) {
+    upb_status_seterrmsg(s, "oneof already added to a message");
+    return false;
+  }
+
+  if (!upb_isident(name, strlen(name), true, s)) {
+    return false;
+  }
+
+  name = upb_gstrdup(name);
+  if (!name) {
+    upb_status_seterrmsg(s, "One of memory");
+    return false;
+  }
+
+  upb_gfree((void*)o->name);
+  o->name = name;
+  return true;
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return upb_strtable_count(&o->ntof);
+}
+
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s) {
+  assert(!upb_oneofdef_isfrozen(o));
+  assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
+
+  /* This method is idempotent. Check if |f| is already part of this oneofdef
+   * and return immediately if so. */
+  if (upb_fielddef_containingoneof(f) == o) {
+    return true;
+  }
+
+  /* The field must have an OPTIONAL label. */
+  if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+    upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label");
+    return false;
+  }
+
+  /* Check that no field with this name or number exists already in the oneof.
+   * Also check that the field is not already part of a oneof. */
+  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
+    upb_status_seterrmsg(s, "field name or number were not set");
+    return false;
+  } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) ||
+             upb_oneofdef_ntofz(o, upb_fielddef_name(f))) {
+    upb_status_seterrmsg(s, "duplicate field name or number");
+    return false;
+  } else if (upb_fielddef_containingoneof(f) != NULL) {
+    upb_status_seterrmsg(s, "fielddef already belongs to a oneof");
+    return false;
+  }
+
+  /* We allow adding a field to the oneof either if the field is not part of a
+   * msgdef, or if it is and we are also part of the same msgdef. */
+  if (o->parent == NULL) {
+    /* If we're not in a msgdef, the field cannot be either. Otherwise we would
+     * need to magically add this oneof to a msgdef to remain consistent, which
+     * is surprising behavior. */
+    if (upb_fielddef_containingtype(f) != NULL) {
+      upb_status_seterrmsg(s, "fielddef already belongs to a message, but "
+                              "oneof does not");
+      return false;
+    }
+  } else {
+    /* If we're in a msgdef, the user can add fields that either aren't in any
+     * msgdef (in which case they're added to our msgdef) or already a part of
+     * our msgdef. */
+    if (upb_fielddef_containingtype(f) != NULL &&
+        upb_fielddef_containingtype(f) != o->parent) {
+      upb_status_seterrmsg(s, "fielddef belongs to a different message "
+                              "than oneof");
+      return false;
+    }
+  }
+
+  /* Commit phase. First add the field to our parent msgdef, if any, because
+   * that may fail; then add the field to our own tables. */
+
+  if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) {
+    if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) {
+      return false;
+    }
+  }
+
+  release_containingtype(f);
+  f->oneof = o;
+  upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f));
+  upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f));
+  upb_ref2(f, o);
+  upb_ref2(o, f);
+  if (ref_donor) upb_fielddef_unref(f, ref_donor);
+
+  return true;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup32(&o->itof, num, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+/* upb_filedef ****************************************************************/
+
+static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit,
+                         void *closure) {
+  const upb_filedef *f = (const upb_filedef*)r;
+  size_t i;
+
+  for(i = 0; i < upb_filedef_defcount(f); i++) {
+    visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure);
+  }
+}
+
+static void freefiledef(upb_refcounted *r) {
+  upb_filedef *f = (upb_filedef*)r;
+  size_t i;
+
+  for(i = 0; i < upb_filedef_depcount(f); i++) {
+    upb_filedef_unref(upb_filedef_dep(f, i), f);
+  }
+
+  upb_inttable_uninit(&f->defs);
+  upb_inttable_uninit(&f->deps);
+  upb_gfree((void*)f->name);
+  upb_gfree((void*)f->package);
+  upb_gfree(f);
+}
+
+const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef};
+
+upb_filedef *upb_filedef_new(const void *owner) {
+  upb_filedef *f = upb_gmalloc(sizeof(*f));
+
+  if (!f) {
+    return NULL;
+  }
+
+  f->package = NULL;
+  f->name = NULL;
+  f->syntax = UPB_SYNTAX_PROTO2;
+
+  if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
+                           owner)) {
+    goto err;
+  }
+
+  if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) {
+    goto err;
+  }
+
+  if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) {
+    goto err2;
+  }
+
+  return f;
+
+
+err2:
+  upb_inttable_uninit(&f->defs);
+
+err:
+  upb_gfree(f);
+  return NULL;
+}
+
+const char *upb_filedef_name(const upb_filedef *f) {
+  return f->name;
+}
+
+const char *upb_filedef_package(const upb_filedef *f) {
+  return f->package;
+}
+
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+  return f->syntax;
+}
+
+size_t upb_filedef_defcount(const upb_filedef *f) {
+  return upb_inttable_count(&f->defs);
+}
+
+size_t upb_filedef_depcount(const upb_filedef *f) {
+  return upb_inttable_count(&f->deps);
+}
+
+const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) {
+  upb_value v;
+
+  if (upb_inttable_lookup32(&f->defs, i, &v)) {
+    return upb_value_getconstptr(v);
+  } else {
+    return NULL;
+  }
+}
+
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) {
+  upb_value v;
+
+  if (upb_inttable_lookup32(&f->deps, i, &v)) {
+    return upb_value_getconstptr(v);
+  } else {
+    return NULL;
+  }
+}
+
+bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) {
+  name = upb_gstrdup(name);
+  if (!name) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+  upb_gfree((void*)f->name);
+  f->name = name;
+  return true;
+}
+
+bool upb_filedef_setpackage(upb_filedef *f, const char *package,
+                            upb_status *s) {
+  if (!upb_isident(package, strlen(package), true, s)) return false;
+  package = upb_gstrdup(package);
+  if (!package) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+  upb_gfree((void*)f->package);
+  f->package = package;
+  return true;
+}
+
+bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
+                           upb_status *s) {
+  UPB_UNUSED(s);
+  if (syntax != UPB_SYNTAX_PROTO2 &&
+      syntax != UPB_SYNTAX_PROTO3) {
+    upb_status_seterrmsg(s, "Unknown syntax value.");
+    return false;
+  }
+  f->syntax = syntax;
+
+  {
+    /* Set all messages in this file to match. */
+    size_t i;
+    for (i = 0; i < upb_filedef_defcount(f); i++) {
+      /* Casting const away is safe since all defs in mutable filedef must
+       * also be mutable. */
+      upb_def *def = (upb_def*)upb_filedef_def(f, i);
+
+      upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+      if (m) {
+        m->syntax = syntax;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
+                        upb_status *s) {
+  if (def->file) {
+    upb_status_seterrmsg(s, "Def is already part of another filedef.");
+    return false;
+  }
+
+  if (upb_inttable_push(&f->defs, upb_value_constptr(def))) {
+    def->file = f;
+    upb_ref2(def, f);
+    if (ref_donor) upb_def_unref(def, ref_donor);
+    if (def->type == UPB_DEF_MSG) {
+      upb_downcast_msgdef_mutable(def)->syntax = f->syntax;
+    }
+    return true;
+  } else {
+    upb_upberr_setoom(s);
+    return false;
+  }
+}
+
+bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) {
+  if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) {
+    /* Regular ref instead of ref2 because files can't form cycles. */
+    upb_filedef_ref(dep, f);
+    return true;
+  } else {
+    return false;
+  }
+}
+/*
+** TODO(haberman): it's unclear whether a lot of the consistency checks should
+** assert() or return false.
+*/
+
+
+#include <string.h>
+
+
+static void *upb_calloc(size_t size) {
+  void *mem = upb_gmalloc(size);
+  if (mem) {
+    memset(mem, 0, size);
+  }
+  return mem;
+}
+
+/* Defined for the sole purpose of having a unique pointer value for
+ * UPB_NO_CLOSURE. */
+char _upb_noclosure;
+
+static void freehandlers(upb_refcounted *r) {
+  upb_handlers *h = (upb_handlers*)r;
+
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &h->cleanup_);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    void *val = (void*)upb_inttable_iter_key(&i);
+    upb_value func_val = upb_inttable_iter_value(&i);
+    upb_handlerfree *func = upb_value_getfptr(func_val);
+    func(val);
+  }
+
+  upb_inttable_uninit(&h->cleanup_);
+  upb_msgdef_unref(h->msg, h);
+  upb_gfree(h->sub);
+  upb_gfree(h);
+}
+
+static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
+                          void *closure) {
+  const upb_handlers *h = (const upb_handlers*)r;
+  upb_msg_field_iter i;
+  for(upb_msg_field_begin(&i, h->msg);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_handlers *sub;
+    if (!upb_fielddef_issubmsg(f)) continue;
+    sub = upb_handlers_getsubhandlers(h, f);
+    if (sub) visit(r, upb_handlers_upcast(sub), closure);
+  }
+}
+
+static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
+
+typedef struct {
+  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
+  upb_handlers_callback *callback;
+  const void *closure;
+} dfs_state;
+
+/* TODO(haberman): discard upb_handlers* objects that do not actually have any
+ * handlers set and cannot reach any upb_handlers* object that does.  This is
+ * slightly tricky to do correctly. */
+static upb_handlers *newformsg(const upb_msgdef *m, const void *owner,
+                               dfs_state *s) {
+  upb_msg_field_iter i;
+  upb_handlers *h = upb_handlers_new(m, owner);
+  if (!h) return NULL;
+  if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
+
+  s->callback(s->closure, h);
+
+  /* For each submessage field, get or create a handlers object and set it as
+   * the subhandlers. */
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_msgdef *subdef;
+    upb_value subm_ent;
+
+    if (!upb_fielddef_issubmsg(f)) continue;
+
+    subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
+    if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
+      upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
+    } else {
+      upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s);
+      if (!sub_mh) goto oom;
+      upb_handlers_setsubhandlers(h, f, sub_mh);
+      upb_handlers_unref(sub_mh, &sub_mh);
+    }
+  }
+  return h;
+
+oom:
+  upb_handlers_unref(h, owner);
+  return NULL;
+}
+
+/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
+ * subhandlers for this submessage field. */
+#define SUBH(h, selector) (h->sub[selector])
+
+/* The selector for a submessage field is the field index. */
+#define SUBH_F(h, f) SUBH(h, f->index_)
+
+static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
+                         upb_handlertype_t type) {
+  upb_selector_t sel;
+  assert(!upb_handlers_isfrozen(h));
+  if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
+    upb_status_seterrf(
+        &h->status_, "type mismatch: field %s does not belong to message %s",
+        upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h)));
+    return -1;
+  }
+  if (!upb_handlers_getselector(f, type, &sel)) {
+    upb_status_seterrf(
+        &h->status_,
+        "type mismatch: cannot register handler type %d for field %s",
+        type, upb_fielddef_name(f));
+    return -1;
+  }
+  return sel;
+}
+
+static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
+                             upb_handlertype_t type) {
+  int32_t sel = trygetsel(h, f, type);
+  assert(sel >= 0);
+  return sel;
+}
+
+static const void **returntype(upb_handlers *h, const upb_fielddef *f,
+                               upb_handlertype_t type) {
+  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_;
+}
+
+static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
+                  upb_handlertype_t type, upb_func *func,
+                  upb_handlerattr *attr) {
+  upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER;
+  const void *closure_type;
+  const void **context_closure_type;
+
+  assert(!upb_handlers_isfrozen(h));
+
+  if (sel < 0) {
+    upb_status_seterrmsg(&h->status_,
+                         "incorrect handler type for this field.");
+    return false;
+  }
+
+  if (h->table[sel].func) {
+    upb_status_seterrmsg(&h->status_,
+                         "cannot change handler once it has been set.");
+    return false;
+  }
+
+  if (attr) {
+    set_attr = *attr;
+  }
+
+  /* Check that the given closure type matches the closure type that has been
+   * established for this context (if any). */
+  closure_type = upb_handlerattr_closuretype(&set_attr);
+
+  if (type == UPB_HANDLER_STRING) {
+    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
+  } else if (f && upb_fielddef_isseq(f) &&
+             type != UPB_HANDLER_STARTSEQ &&
+             type != UPB_HANDLER_ENDSEQ) {
+    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
+  } else {
+    context_closure_type = &h->top_closure_type;
+  }
+
+  if (closure_type && *context_closure_type &&
+      closure_type != *context_closure_type) {
+    /* TODO(haberman): better message for debugging. */
+    if (f) {
+      upb_status_seterrf(&h->status_,
+                         "closure type does not match for field %s",
+                         upb_fielddef_name(f));
+    } else {
+      upb_status_seterrmsg(
+          &h->status_, "closure type does not match for message-level handler");
+    }
+    return false;
+  }
+
+  if (closure_type)
+    *context_closure_type = closure_type;
+
+  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
+   * matches any pre-existing expectations about what type is expected. */
+  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
+    const void *return_type = upb_handlerattr_returnclosuretype(&set_attr);
+    const void *table_return_type =
+        upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+    if (return_type && table_return_type && return_type != table_return_type) {
+      upb_status_seterrmsg(&h->status_, "closure return type does not match");
+      return false;
+    }
+
+    if (table_return_type && !return_type)
+      upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type);
+  }
+
+  h->table[sel].func = (upb_func*)func;
+  h->table[sel].attr = set_attr;
+  return true;
+}
+
+/* Returns the effective closure type for this handler (which will propagate
+ * from outer frames if this frame has no START* handler).  Not implemented for
+ * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
+ * the effective closure type is unspecified (either no handler was registered
+ * to specify it or the handler that was registered did not specify the closure
+ * type). */
+const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
+                                   upb_handlertype_t type) {
+  const void *ret;
+  upb_selector_t sel;
+
+  assert(type != UPB_HANDLER_STRING);
+  ret = h->top_closure_type;
+
+  if (upb_fielddef_isseq(f) &&
+      type != UPB_HANDLER_STARTSEQ &&
+      type != UPB_HANDLER_ENDSEQ &&
+      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
+    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+  }
+
+  if (type == UPB_HANDLER_STRING &&
+      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
+    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+  }
+
+  /* The effective type of the submessage; not used yet.
+   * if (type == SUBMESSAGE &&
+   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
+   *   ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+   * } */
+
+  return ret;
+}
+
+/* Checks whether the START* handler specified by f & type is missing even
+ * though it is required to convert the established type of an outer frame
+ * ("closure_type") into the established type of an inner frame (represented in
+ * the return closure type of this handler's attr. */
+bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
+                upb_status *status) {
+  const void *closure_type;
+  const upb_handlerattr *attr;
+  const void *return_closure_type;
+
+  upb_selector_t sel = handlers_getsel(h, f, type);
+  if (h->table[sel].func) return true;
+  closure_type = effective_closure_type(h, f, type);
+  attr = &h->table[sel].attr;
+  return_closure_type = upb_handlerattr_returnclosuretype(attr);
+  if (closure_type && return_closure_type &&
+      closure_type != return_closure_type) {
+    upb_status_seterrf(status,
+                       "expected start handler to return sub type for field %f",
+                       upb_fielddef_name(f));
+    return false;
+  }
+  return true;
+}
+
+/* Public interface ***********************************************************/
+
+upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) {
+  int extra;
+  upb_handlers *h;
+
+  assert(upb_msgdef_isfrozen(md));
+
+  extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
+  h = upb_calloc(sizeof(*h) + extra);
+  if (!h) return NULL;
+
+  h->msg = md;
+  upb_msgdef_ref(h->msg, h);
+  upb_status_clear(&h->status_);
+
+  if (md->submsg_field_count > 0) {
+    h->sub = upb_calloc(md->submsg_field_count * sizeof(*h->sub));
+    if (!h->sub) goto oom;
+  } else {
+    h->sub = 0;
+  }
+
+  if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner))
+    goto oom;
+  if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom;
+
+  /* calloc() above initialized all handlers to NULL. */
+  return h;
+
+oom:
+  freehandlers(upb_handlers_upcast_mutable(h));
+  return NULL;
+}
+
+const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
+                                           const void *owner,
+                                           upb_handlers_callback *callback,
+                                           const void *closure) {
+  dfs_state state;
+  upb_handlers *ret;
+  bool ok;
+  upb_refcounted *r;
+
+  state.callback = callback;
+  state.closure = closure;
+  if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
+
+  ret = newformsg(m, owner, &state);
+
+  upb_inttable_uninit(&state.tab);
+  if (!ret) return NULL;
+
+  r = upb_handlers_upcast_mutable(ret);
+  ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
+  UPB_ASSERT_VAR(ok, ok);
+
+  return ret;
+}
+
+const upb_status *upb_handlers_status(upb_handlers *h) {
+  assert(!upb_handlers_isfrozen(h));
+  return &h->status_;
+}
+
+void upb_handlers_clearerr(upb_handlers *h) {
+  assert(!upb_handlers_isfrozen(h));
+  upb_status_clear(&h->status_);
+}
+
+#define SETTER(name, handlerctype, handlertype) \
+  bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
+                                handlerctype func, upb_handlerattr *attr) { \
+    int32_t sel = trygetsel(h, f, handlertype); \
+    return doset(h, sel, f, handlertype, (upb_func*)func, attr); \
+  }
+
+SETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
+SETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
+SETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
+SETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
+SETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
+SETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
+SETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
+SETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
+SETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
+SETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
+SETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
+SETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
+SETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
+SETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
+
+#undef SETTER
+
+bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
+                              upb_handlerattr *attr) {
+  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+               (upb_func *)func, attr);
+}
+
+bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
+                            upb_handlerattr *attr) {
+  assert(!upb_handlers_isfrozen(h));
+  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+               (upb_func *)func, attr);
+}
+
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+                                 const upb_handlers *sub) {
+  assert(sub);
+  assert(!upb_handlers_isfrozen(h));
+  assert(upb_fielddef_issubmsg(f));
+  if (SUBH_F(h, f)) return false;  /* Can't reset. */
+  if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
+    return false;
+  }
+  SUBH_F(h, f) = sub;
+  upb_ref2(sub, h);
+  return true;
+}
+
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+                                                const upb_fielddef *f) {
+  assert(upb_fielddef_issubmsg(f));
+  return SUBH_F(h, f);
+}
+
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
+                          upb_handlerattr *attr) {
+  if (!upb_handlers_gethandler(h, sel))
+    return false;
+  *attr = h->table[sel].attr;
+  return true;
+}
+
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+                                                    upb_selector_t sel) {
+  /* STARTSUBMSG selector in sel is the field's selector base. */
+  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
+}
+
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
+
+bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
+  bool ok;
+  if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) {
+    return false;
+  }
+  ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func));
+  UPB_ASSERT_VAR(ok, ok);
+  return true;
+}
+
+
+/* "Static" methods ***********************************************************/
+
+bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
+  /* TODO: verify we have a transitive closure. */
+  int i;
+  for (i = 0; i < n; i++) {
+    upb_msg_field_iter j;
+    upb_handlers *h = handlers[i];
+
+    if (!upb_ok(&h->status_)) {
+      upb_status_seterrf(s, "handlers for message %s had error status: %s",
+                         upb_msgdef_fullname(upb_handlers_msgdef(h)),
+                         upb_status_errmsg(&h->status_));
+      return false;
+    }
+
+    /* Check that there are no closure mismatches due to missing Start* handlers
+     * or subhandlers with different type-level types. */
+    for(upb_msg_field_begin(&j, h->msg);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+
+      const upb_fielddef *f = upb_msg_iter_field(&j);
+      if (upb_fielddef_isseq(f)) {
+        if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
+          return false;
+      }
+
+      if (upb_fielddef_isstring(f)) {
+        if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
+          return false;
+      }
+
+      if (upb_fielddef_issubmsg(f)) {
+        bool hashandler = false;
+        if (upb_handlers_gethandler(
+                h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
+            upb_handlers_gethandler(
+                h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
+          hashandler = true;
+        }
+
+        if (upb_fielddef_isseq(f) &&
+            (upb_handlers_gethandler(
+                 h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
+             upb_handlers_gethandler(
+                 h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
+          hashandler = true;
+        }
+
+        if (hashandler && !upb_handlers_getsubhandlers(h, f)) {
+          /* For now we add an empty subhandlers in this case.  It makes the
+           * decoder code generator simpler, because it only has to handle two
+           * cases (submessage has handlers or not) as opposed to three
+           * (submessage has handlers in enclosing message but no subhandlers).
+           *
+           * This makes parsing less efficient in the case that we want to
+           * notice a submessage but skip its contents (like if we're testing
+           * for submessage presence or counting the number of repeated
+           * submessages).  In this case we will end up parsing the submessage
+           * field by field and throwing away the results for each, instead of
+           * skipping the whole delimited thing at once.  If this is an issue we
+           * can revisit it, but do remember that this only arises when you have
+           * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the
+           * submessage but no subhandlers.  The uses cases for this are
+           * limited. */
+          upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub);
+          upb_handlers_setsubhandlers(h, f, sub);
+          upb_handlers_unref(sub, &sub);
+        }
+
+        /* TODO(haberman): check type of submessage.
+         * This is slightly tricky; also consider whether we should check that
+         * they match at setsubhandlers time. */
+      }
+    }
+  }
+
+  if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
+                             UPB_MAX_HANDLER_DEPTH)) {
+    return false;
+  }
+
+  return true;
+}
+
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
+    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
+    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
+    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
+    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
+    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
+    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
+    default: assert(false); return -1;  /* Invalid input. */
+  }
+}
+
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+                              upb_selector_t *s) {
+  switch (type) {
+    case UPB_HANDLER_INT32:
+    case UPB_HANDLER_INT64:
+    case UPB_HANDLER_UINT32:
+    case UPB_HANDLER_UINT64:
+    case UPB_HANDLER_FLOAT:
+    case UPB_HANDLER_DOUBLE:
+    case UPB_HANDLER_BOOL:
+      if (!upb_fielddef_isprimitive(f) ||
+          upb_handlers_getprimitivehandlertype(f) != type)
+        return false;
+      *s = f->selector_base;
+      break;
+    case UPB_HANDLER_STRING:
+      if (upb_fielddef_isstring(f)) {
+        *s = f->selector_base;
+      } else if (upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 3;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_STARTSTR:
+      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 1;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_ENDSTR:
+      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
+        *s = f->selector_base + 2;
+      } else {
+        return false;
+      }
+      break;
+    case UPB_HANDLER_STARTSEQ:
+      if (!upb_fielddef_isseq(f)) return false;
+      *s = f->selector_base - 2;
+      break;
+    case UPB_HANDLER_ENDSEQ:
+      if (!upb_fielddef_isseq(f)) return false;
+      *s = f->selector_base - 1;
+      break;
+    case UPB_HANDLER_STARTSUBMSG:
+      if (!upb_fielddef_issubmsg(f)) return false;
+      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
+       * selector can also be used as an index into the "sub" array of
+       * subhandlers.  The indexes for the two into these two tables are the
+       * same, except that in the handler table the static selectors come first. */
+      *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
+      break;
+    case UPB_HANDLER_ENDSUBMSG:
+      if (!upb_fielddef_issubmsg(f)) return false;
+      *s = f->selector_base;
+      break;
+  }
+  assert((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
+  return true;
+}
+
+uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) ? 2 : 0;
+}
+
+uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
+  uint32_t ret = 1;
+  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
+  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
+  if (upb_fielddef_issubmsg(f)) {
+    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
+    ret += 0;
+    if (upb_fielddef_lazy(f)) {
+      /* STARTSTR/ENDSTR/STRING (for lazy) */
+      ret += 3;
+    }
+  }
+  return ret;
+}
+
+
+/* upb_handlerattr ************************************************************/
+
+void upb_handlerattr_init(upb_handlerattr *attr) {
+  upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER;
+  memcpy(attr, &from, sizeof(*attr));
+}
+
+void upb_handlerattr_uninit(upb_handlerattr *attr) {
+  UPB_UNUSED(attr);
+}
+
+bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) {
+  attr->handler_data_ = hd;
+  return true;
+}
+
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) {
+  attr->closure_type_ = type;
+  return true;
+}
+
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) {
+  return attr->closure_type_;
+}
+
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+                                          const void *type) {
+  attr->return_closure_type_ = type;
+  return true;
+}
+
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) {
+  return attr->return_closure_type_;
+}
+
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) {
+  attr->alwaysok_ = alwaysok;
+  return true;
+}
+
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) {
+  return attr->alwaysok_;
+}
+
+/* upb_bufhandle **************************************************************/
+
+size_t upb_bufhandle_objofs(const upb_bufhandle *h) {
+  return h->objofs_;
+}
+
+/* upb_byteshandler ***********************************************************/
+
+void upb_byteshandler_init(upb_byteshandler* h) {
+  memset(h, 0, sizeof(*h));
+}
+
+/* For when we support handlerfree callbacks. */
+void upb_byteshandler_uninit(upb_byteshandler* h) {
+  UPB_UNUSED(h);
+}
+
+bool upb_byteshandler_setstartstr(upb_byteshandler *h,
+                                  upb_startstr_handlerfunc *func, void *d) {
+  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+
+bool upb_byteshandler_setstring(upb_byteshandler *h,
+                                upb_string_handlerfunc *func, void *d) {
+  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+
+bool upb_byteshandler_setendstr(upb_byteshandler *h,
+                                upb_endfield_handlerfunc *func, void *d) {
+  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
+  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d;
+  return true;
+}
+/*
+** upb::RefCounted Implementation
+**
+** Our key invariants are:
+** 1. reference cycles never span groups
+** 2. for ref2(to, from), we increment to's count iff group(from) != group(to)
+**
+** The previous two are how we avoid leaking cycles.  Other important
+** invariants are:
+** 3. for mutable objects "from" and "to", if there exists a ref2(to, from)
+**    this implies group(from) == group(to).  (In practice, what we implement
+**    is even stronger; "from" and "to" will share a group if there has *ever*
+**    been a ref2(to, from), but all that is necessary for correctness is the
+**    weaker one).
+** 4. mutable and immutable objects are never in the same group.
+*/
+
+
+#include <setjmp.h>
+
+static void freeobj(upb_refcounted *o);
+
+const char untracked_val;
+const void *UPB_UNTRACKED_REF = &untracked_val;
+
+/* arch-specific atomic primitives  *******************************************/
+
+#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/
+
+static void atomic_inc(uint32_t *a) { (*a)++; }
+static bool atomic_dec(uint32_t *a) { return --(*a) == 0; }
+
+#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/
+
+static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); }
+static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; }
+
+#elif defined(WIN32) /*-------------------------------------------------------*/
+
+#include <Windows.h>
+
+static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); }
+static bool atomic_dec(upb_atomic_t *a) {
+  return InterlockedDecrement(&a->val) == 0;
+}
+
+#else
+#error Atomic primitives not defined for your platform/CPU.  \
+       Implement them or compile with UPB_THREAD_UNSAFE.
+#endif
+
+/* All static objects point to this refcount.
+ * It is special-cased in ref/unref below.  */
+uint32_t static_refcount = -1;
+
+/* We can avoid atomic ops for statically-declared objects.
+ * This is a minor optimization but nice since we can avoid degrading under
+ * contention in this case. */
+
+static void refgroup(uint32_t *group) {
+  if (group != &static_refcount)
+    atomic_inc(group);
+}
+
+static bool unrefgroup(uint32_t *group) {
+  if (group == &static_refcount) {
+    return false;
+  } else {
+    return atomic_dec(group);
+  }
+}
+
+
+/* Reference tracking (debug only) ********************************************/
+
+#ifdef UPB_DEBUG_REFS
+
+#ifdef UPB_THREAD_UNSAFE
+
+static void upb_lock() {}
+static void upb_unlock() {}
+
+#else
+
+/* User must define functions that lock/unlock a global mutex and link this
+ * file against them. */
+void upb_lock();
+void upb_unlock();
+
+#endif
+
+/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some
+ * code-paths that can normally never fail, like upb_refcounted_ref().  Since
+ * we have no way to propagage out-of-memory errors back to the user, and since
+ * these errors can only occur in UPB_DEBUG_REFS mode, we use an allocator that
+ * immediately aborts on failure (avoiding the global allocator, which might
+ * inject failures). */
+
+#include <stdlib.h>
+
+static void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr,
+                                     size_t oldsize, size_t size) {
+  UPB_UNUSED(alloc);
+  UPB_UNUSED(oldsize);
+  if (size == 0) {
+    free(ptr);
+    return NULL;
+  } else {
+    void *ret = realloc(ptr, size);
+
+    if (!ret) {
+      abort();
+    }
+
+    return ret;
+  }
+}
+
+upb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc};
+
+typedef struct {
+  int count;  /* How many refs there are (duplicates only allowed for ref2). */
+  bool is_ref2;
+} trackedref;
+
+static trackedref *trackedref_new(bool is_ref2) {
+  trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret));
+  ret->count = 1;
+  ret->is_ref2 = is_ref2;
+  return ret;
+}
+
+static void track(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+
+  assert(owner);
+  if (owner == UPB_UNTRACKED_REF) return;
+
+  upb_lock();
+  if (upb_inttable_lookupptr(r->refs, owner, &v)) {
+    trackedref *ref = upb_value_getptr(v);
+    /* Since we allow multiple ref2's for the same to/from pair without
+     * allocating separate memory for each one, we lose the fine-grained
+     * tracking behavior we get with regular refs.  Since ref2s only happen
+     * inside upb, we'll accept this limitation until/unless there is a really
+     * difficult upb-internal bug that can't be figured out without it. */
+    assert(ref2);
+    assert(ref->is_ref2);
+    ref->count++;
+  } else {
+    trackedref *ref = trackedref_new(ref2);
+    upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref),
+                            &upb_alloc_debugrefs);
+    if (ref2) {
+      /* We know this cast is safe when it is a ref2, because it's coming from
+       * another refcounted object. */
+      const upb_refcounted *from = owner;
+      assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
+      upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL),
+                              &upb_alloc_debugrefs);
+    }
+  }
+  upb_unlock();
+}
+
+static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+  bool found;
+  trackedref *ref;
+
+  assert(owner);
+  if (owner == UPB_UNTRACKED_REF) return;
+
+  upb_lock();
+  found = upb_inttable_lookupptr(r->refs, owner, &v);
+  /* This assert will fail if an owner attempts to release a ref it didn't have. */
+  UPB_ASSERT_VAR(found, found);
+  ref = upb_value_getptr(v);
+  assert(ref->is_ref2 == ref2);
+  if (--ref->count == 0) {
+    free(ref);
+    upb_inttable_removeptr(r->refs, owner, NULL);
+    if (ref2) {
+      /* We know this cast is safe when it is a ref2, because it's coming from
+       * another refcounted object. */
+      const upb_refcounted *from = owner;
+      bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
+      assert(removed);
+    }
+  }
+  upb_unlock();
+}
+
+static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
+  upb_value v;
+  bool found;
+  trackedref *ref;
+
+  upb_lock();
+  found = upb_inttable_lookupptr(r->refs, owner, &v);
+  UPB_ASSERT_VAR(found, found);
+  ref = upb_value_getptr(v);
+  assert(ref->is_ref2 == ref2);
+  upb_unlock();
+}
+
+/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that
+ * originate from the given owner. */
+static void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
+  upb_inttable_iter i;
+
+  upb_lock();
+  upb_inttable_begin(&i, owner->ref2s);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_value v;
+    upb_value count;
+    trackedref *ref;
+    bool found;
+
+    upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
+
+    /* To get the count we need to look in the target's table. */
+    found = upb_inttable_lookupptr(to->refs, owner, &v);
+    assert(found);
+    ref = upb_value_getptr(v);
+    count = upb_value_int32(ref->count);
+
+    upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs);
+  }
+  upb_unlock();
+}
+
+typedef struct {
+  upb_inttable ref2;
+  const upb_refcounted *obj;
+} check_state;
+
+static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj,
+                        void *closure) {
+  check_state *s = closure;
+  upb_inttable *ref2 = &s->ref2;
+  upb_value v;
+  bool removed;
+  int32_t newcount;
+
+  assert(obj == s->obj);
+  assert(subobj);
+  removed = upb_inttable_removeptr(ref2, subobj, &v);
+  /* The following assertion will fail if the visit() function visits a subobj
+   * that it did not have a ref2 on, or visits the same subobj too many times. */
+  assert(removed);
+  newcount = upb_value_getint32(v) - 1;
+  if (newcount > 0) {
+    upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount),
+                         &upb_alloc_debugrefs);
+  }
+}
+
+static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
+                  void *closure) {
+  /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know
+   * exactly the set of nodes that visit() should visit.  So we verify visit()'s
+   * correctness here. */
+  check_state state;
+  state.obj = r;
+  upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs);
+  getref2s(r, &state.ref2);
+
+  /* This should visit any children in the ref2 table. */
+  if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state);
+
+  /* This assertion will fail if the visit() function missed any children. */
+  assert(upb_inttable_count(&state.ref2) == 0);
+  upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs);
+  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
+}
+
+static void trackinit(upb_refcounted *r) {
+  r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs));
+  r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s));
+  upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
+  upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
+}
+
+static void trackfree(const upb_refcounted *r) {
+  upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs);
+  upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs);
+  upb_free(&upb_alloc_debugrefs, r->refs);
+  upb_free(&upb_alloc_debugrefs, r->ref2s);
+}
+
+#else
+
+static void track(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
+  UPB_UNUSED(r);
+  UPB_UNUSED(owner);
+  UPB_UNUSED(ref2);
+}
+
+static void trackinit(upb_refcounted *r) {
+  UPB_UNUSED(r);
+}
+
+static void trackfree(const upb_refcounted *r) {
+  UPB_UNUSED(r);
+}
+
+static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
+                  void *closure) {
+  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
+}
+
+#endif  /* UPB_DEBUG_REFS */
+
+
+/* freeze() *******************************************************************/
+
+/* The freeze() operation is by far the most complicated part of this scheme.
+ * We compute strongly-connected components and then mutate the graph such that
+ * we preserve the invariants documented at the top of this file.  And we must
+ * handle out-of-memory errors gracefully (without leaving the graph
+ * inconsistent), which adds to the fun. */
+
+/* The state used by the freeze operation (shared across many functions). */
+typedef struct {
+  int depth;
+  int maxdepth;
+  uint64_t index;
+  /* Maps upb_refcounted* -> attributes (color, etc).  attr layout varies by
+   * color. */
+  upb_inttable objattr;
+  upb_inttable stack;   /* stack of upb_refcounted* for Tarjan's algorithm. */
+  upb_inttable groups;  /* array of uint32_t*, malloc'd refcounts for new groups */
+  upb_status *status;
+  jmp_buf err;
+} tarjan;
+
+static void release_ref2(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure);
+
+/* Node attributes -----------------------------------------------------------*/
+
+/* After our analysis phase all nodes will be either GRAY or WHITE. */
+
+typedef enum {
+  BLACK = 0,  /* Object has not been seen. */
+  GRAY,   /* Object has been found via a refgroup but may not be reachable. */
+  GREEN,  /* Object is reachable and is currently on the Tarjan stack. */
+  WHITE   /* Object is reachable and has been assigned a group (SCC). */
+} color_t;
+
+UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); }
+UPB_NORETURN static void oom(tarjan *t) {
+  upb_status_seterrmsg(t->status, "out of memory");
+  err(t);
+}
+
+static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) {
+  upb_value v;
+  return upb_inttable_lookupptr(&t->objattr, r, &v) ?
+      upb_value_getuint64(v) : 0;
+}
+
+static uint64_t getattr(const tarjan *t, const upb_refcounted *r) {
+  upb_value v;
+  bool found = upb_inttable_lookupptr(&t->objattr, r, &v);
+  UPB_ASSERT_VAR(found, found);
+  return upb_value_getuint64(v);
+}
+
+static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) {
+  upb_inttable_removeptr(&t->objattr, r, NULL);
+  upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr));
+}
+
+static color_t color(tarjan *t, const upb_refcounted *r) {
+  return trygetattr(t, r) & 0x3;  /* Color is always stored in the low 2 bits. */
+}
+
+static void set_gray(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == BLACK);
+  setattr(t, r, GRAY);
+}
+
+/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */
+static void push(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == BLACK || color(t, r) == GRAY);
+  /* This defines the attr layout for the GREEN state.  "index" and "lowlink"
+   * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */
+  setattr(t, r, GREEN | (t->index << 2) | (t->index << 33));
+  if (++t->index == 0x80000000) {
+    upb_status_seterrmsg(t->status, "too many objects to freeze");
+    err(t);
+  }
+  upb_inttable_push(&t->stack, upb_value_ptr((void*)r));
+}
+
+/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its
+ * SCC group. */
+static upb_refcounted *pop(tarjan *t) {
+  upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack));
+  assert(color(t, r) == GREEN);
+  /* This defines the attr layout for nodes in the WHITE state.
+   * Top of group stack is [group, NULL]; we point at group. */
+  setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8);
+  return r;
+}
+
+static void tarjan_newgroup(tarjan *t) {
+  uint32_t *group = upb_gmalloc(sizeof(*group));
+  if (!group) oom(t);
+  /* Push group and empty group leader (we'll fill in leader later). */
+  if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) ||
+      !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) {
+    upb_gfree(group);
+    oom(t);
+  }
+  *group = 0;
+}
+
+static uint32_t idx(tarjan *t, const upb_refcounted *r) {
+  assert(color(t, r) == GREEN);
+  return (getattr(t, r) >> 2) & 0x7FFFFFFF;
+}
+
+static uint32_t lowlink(tarjan *t, const upb_refcounted *r) {
+  if (color(t, r) == GREEN) {
+    return getattr(t, r) >> 33;
+  } else {
+    return UINT32_MAX;
+  }
+}
+
+static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) {
+  assert(color(t, r) == GREEN);
+  setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF));
+}
+
+static uint32_t *group(tarjan *t, upb_refcounted *r) {
+  uint64_t groupnum;
+  upb_value v;
+  bool found;
+
+  assert(color(t, r) == WHITE);
+  groupnum = getattr(t, r) >> 8;
+  found = upb_inttable_lookup(&t->groups, groupnum, &v);
+  UPB_ASSERT_VAR(found, found);
+  return upb_value_getptr(v);
+}
+
+/* If the group leader for this object's group has not previously been set,
+ * the given object is assigned to be its leader. */
+static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) {
+  uint64_t leader_slot;
+  upb_value v;
+  bool found;
+
+  assert(color(t, r) == WHITE);
+  leader_slot = (getattr(t, r) >> 8) + 1;
+  found = upb_inttable_lookup(&t->groups, leader_slot, &v);
+  UPB_ASSERT_VAR(found, found);
+  if (upb_value_getptr(v)) {
+    return upb_value_getptr(v);
+  } else {
+    upb_inttable_remove(&t->groups, leader_slot, NULL);
+    upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r));
+    return r;
+  }
+}
+
+
+/* Tarjan's algorithm --------------------------------------------------------*/
+
+/* See:
+ *   http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */
+static void do_tarjan(const upb_refcounted *obj, tarjan *t);
+
+static void tarjan_visit(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure) {
+  tarjan *t = closure;
+  if (++t->depth > t->maxdepth) {
+    upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth);
+    err(t);
+  } else if (subobj->is_frozen || color(t, subobj) == WHITE) {
+    /* Do nothing: we don't want to visit or color already-frozen nodes,
+     * and WHITE nodes have already been assigned a SCC. */
+  } else if (color(t, subobj) < GREEN) {
+    /* Subdef has not yet been visited; recurse on it. */
+    do_tarjan(subobj, t);
+    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj)));
+  } else if (color(t, subobj) == GREEN) {
+    /* Subdef is in the stack and hence in the current SCC. */
+    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj)));
+  }
+  --t->depth;
+}
+
+static void do_tarjan(const upb_refcounted *obj, tarjan *t) {
+  if (color(t, obj) == BLACK) {
+    /* We haven't seen this object's group; mark the whole group GRAY. */
+    const upb_refcounted *o = obj;
+    do { set_gray(t, o); } while ((o = o->next) != obj);
+  }
+
+  push(t, obj);
+  visit(obj, tarjan_visit, t);
+  if (lowlink(t, obj) == idx(t, obj)) {
+    tarjan_newgroup(t);
+    while (pop(t) != obj)
+      ;
+  }
+}
+
+
+/* freeze() ------------------------------------------------------------------*/
+
+static void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
+                     void *_t) {
+  tarjan *t = _t;
+  assert(color(t, r) > BLACK);
+  if (color(t, subobj) > BLACK && r->group != subobj->group) {
+    /* Previously this ref was not reflected in subobj->group because they
+     * were in the same group; now that they are split a ref must be taken. */
+    refgroup(subobj->group);
+  }
+}
+
+static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                   int maxdepth) {
+  volatile bool ret = false;
+  int i;
+  upb_inttable_iter iter;
+
+  /* We run in two passes so that we can allocate all memory before performing
+   * any mutation of the input -- this allows us to leave the input unchanged
+   * in the case of memory allocation failure. */
+  tarjan t;
+  t.index = 0;
+  t.depth = 0;
+  t.maxdepth = maxdepth;
+  t.status = s;
+  if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1;
+  if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2;
+  if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3;
+  if (setjmp(t.err) != 0) goto err4;
+
+
+  for (i = 0; i < n; i++) {
+    if (color(&t, roots[i]) < GREEN) {
+      do_tarjan(roots[i], &t);
+    }
+  }
+
+  /* If we've made it this far, no further errors are possible so it's safe to
+   * mutate the objects without risk of leaving them in an inconsistent state. */
+  ret = true;
+
+  /* The transformation that follows requires care.  The preconditions are:
+   * - all objects in attr map are WHITE or GRAY, and are in mutable groups
+   *   (groups of all mutable objs)
+   * - no ref2(to, from) refs have incremented count(to) if both "to" and
+   *   "from" are in our attr map (this follows from invariants (2) and (3)) */
+
+  /* Pass 1: we remove WHITE objects from their mutable groups, and add them to
+   * new groups  according to the SCC's we computed.  These new groups will
+   * consist of only frozen objects.  None will be immediately collectible,
+   * because WHITE objects are by definition reachable from one of "roots",
+   * which the caller must own refs on. */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    /* Since removal from a singly-linked list requires access to the object's
+     * predecessor, we consider obj->next instead of obj for moving.  With the
+     * while() loop we guarantee that we will visit every node's predecessor.
+     * Proof:
+     *  1. every node's predecessor is in our attr map.
+     *  2. though the loop body may change a node's predecessor, it will only
+     *     change it to be the node we are currently operating on, so with a
+     *     while() loop we guarantee ourselves the chance to remove each node. */
+    while (color(&t, obj->next) == WHITE &&
+           group(&t, obj->next) != obj->next->group) {
+      upb_refcounted *leader;
+
+      /* Remove from old group. */
+      upb_refcounted *move = obj->next;
+      if (obj == move) {
+        /* Removing the last object from a group. */
+        assert(*obj->group == obj->individual_count);
+        upb_gfree(obj->group);
+      } else {
+        obj->next = move->next;
+        /* This may decrease to zero; we'll collect GRAY objects (if any) that
+         * remain in the group in the third pass. */
+        assert(*move->group >= move->individual_count);
+        *move->group -= move->individual_count;
+      }
+
+      /* Add to new group. */
+      leader = groupleader(&t, move);
+      if (move == leader) {
+        /* First object added to new group is its leader. */
+        move->group = group(&t, move);
+        move->next = move;
+        *move->group = move->individual_count;
+      } else {
+        /* Group already has at least one object in it. */
+        assert(leader->group == group(&t, move));
+        move->group = group(&t, move);
+        move->next = leader->next;
+        leader->next = move;
+        *move->group += move->individual_count;
+      }
+
+      move->is_frozen = true;
+    }
+  }
+
+  /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must
+   * increment count(to) if group(obj) != group(to) (which could now be the
+   * case if "to" was just frozen). */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    visit(obj, crossref, &t);
+  }
+
+  /* Pass 3: GRAY objects are collected if their group's refcount dropped to
+   * zero when we removed its white nodes.  This can happen if they had only
+   * been kept alive by virtue of sharing a group with an object that was just
+   * frozen.
+   *
+   * It is important that we do this last, since the GRAY object's free()
+   * function could call unref2() on just-frozen objects, which will decrement
+   * refs that were added in pass 2. */
+  upb_inttable_begin(&iter, &t.objattr);
+  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
+    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
+    if (obj->group == NULL || *obj->group == 0) {
+      if (obj->group) {
+        upb_refcounted *o;
+
+        /* We eagerly free() the group's count (since we can't easily determine
+         * the group's remaining size it's the easiest way to ensure it gets
+         * done). */
+        upb_gfree(obj->group);
+
+        /* Visit to release ref2's (done in a separate pass since release_ref2
+         * depends on o->group being unmodified so it can test merged()). */
+        o = obj;
+        do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj);
+
+        /* Mark "group" fields as NULL so we know to free the objects later in
+         * this loop, but also don't try to delete the group twice. */
+        o = obj;
+        do { o->group = NULL; } while ((o = o->next) != obj);
+      }
+      freeobj(obj);
+    }
+  }
+
+err4:
+  if (!ret) {
+    upb_inttable_begin(&iter, &t.groups);
+    for(; !upb_inttable_done(&iter); upb_inttable_next(&iter))
+      upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter)));
+  }
+  upb_inttable_uninit(&t.groups);
+err3:
+  upb_inttable_uninit(&t.stack);
+err2:
+  upb_inttable_uninit(&t.objattr);
+err1:
+  return ret;
+}
+
+
+/* Misc internal functions  ***************************************************/
+
+static bool merged(const upb_refcounted *r, const upb_refcounted *r2) {
+  return r->group == r2->group;
+}
+
+static void merge(upb_refcounted *r, upb_refcounted *from) {
+  upb_refcounted *base;
+  upb_refcounted *tmp;
+
+  if (merged(r, from)) return;
+  *r->group += *from->group;
+  upb_gfree(from->group);
+  base = from;
+
+  /* Set all refcount pointers in the "from" chain to the merged refcount.
+   *
+   * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound
+   * if the user continuously extends a group by one object.  Prevent this by
+   * using one of the techniques in this paper:
+   *     ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */
+  do { from->group = r->group; } while ((from = from->next) != base);
+
+  /* Merge the two circularly linked lists by swapping their next pointers. */
+  tmp = r->next;
+  r->next = base->next;
+  base->next = tmp;
+}
+
+static void unref(const upb_refcounted *r);
+
+static void release_ref2(const upb_refcounted *obj,
+                         const upb_refcounted *subobj,
+                         void *closure) {
+  UPB_UNUSED(closure);
+  untrack(subobj, obj, true);
+  if (!merged(obj, subobj)) {
+    assert(subobj->is_frozen);
+    unref(subobj);
+  }
+}
+
+static void unref(const upb_refcounted *r) {
+  if (unrefgroup(r->group)) {
+    const upb_refcounted *o;
+
+    upb_gfree(r->group);
+
+    /* In two passes, since release_ref2 needs a guarantee that any subobjs
+     * are alive. */
+    o = r;
+    do { visit(o, release_ref2, NULL); } while((o = o->next) != r);
+
+    o = r;
+    do {
+      const upb_refcounted *next = o->next;
+      assert(o->is_frozen || o->individual_count == 0);
+      freeobj((upb_refcounted*)o);
+      o = next;
+    } while(o != r);
+  }
+}
+
+static void freeobj(upb_refcounted *o) {
+  trackfree(o);
+  o->vtbl->free((upb_refcounted*)o);
+}
+
+
+/* Public interface ***********************************************************/
+
+bool upb_refcounted_init(upb_refcounted *r,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner) {
+#ifndef NDEBUG
+  /* Endianness check.  This is unrelated to upb_refcounted, it's just a
+   * convenient place to put the check that we can be assured will run for
+   * basically every program using upb. */
+  const int x = 1;
+#ifdef UPB_BIG_ENDIAN
+  assert(*(char*)&x != 1);
+#else
+  assert(*(char*)&x == 1);
+#endif
+#endif
+
+  r->next = r;
+  r->vtbl = vtbl;
+  r->individual_count = 0;
+  r->is_frozen = false;
+  r->group = upb_gmalloc(sizeof(*r->group));
+  if (!r->group) return false;
+  *r->group = 0;
+  trackinit(r);
+  upb_refcounted_ref(r, owner);
+  return true;
+}
+
+bool upb_refcounted_isfrozen(const upb_refcounted *r) {
+  return r->is_frozen;
+}
+
+void upb_refcounted_ref(const upb_refcounted *r, const void *owner) {
+  track(r, owner, false);
+  if (!r->is_frozen)
+    ((upb_refcounted*)r)->individual_count++;
+  refgroup(r->group);
+}
+
+void upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
+  untrack(r, owner, false);
+  if (!r->is_frozen)
+    ((upb_refcounted*)r)->individual_count--;
+  unref(r);
+}
+
+void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
+  assert(!from->is_frozen);  /* Non-const pointer implies this. */
+  track(r, from, true);
+  if (r->is_frozen) {
+    refgroup(r->group);
+  } else {
+    merge((upb_refcounted*)r, from);
+  }
+}
+
+void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
+  assert(!from->is_frozen);  /* Non-const pointer implies this. */
+  untrack(r, from, true);
+  if (r->is_frozen) {
+    unref(r);
+  } else {
+    assert(merged(r, from));
+  }
+}
+
+void upb_refcounted_donateref(
+    const upb_refcounted *r, const void *from, const void *to) {
+  assert(from != to);
+  if (to != NULL)
+    upb_refcounted_ref(r, to);
+  if (from != NULL)
+    upb_refcounted_unref(r, from);
+}
+
+void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
+  checkref(r, owner, false);
+}
+
+bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                           int maxdepth) {
+  int i;
+  bool ret;
+  for (i = 0; i < n; i++) {
+    assert(!roots[i]->is_frozen);
+  }
+  ret = freeze(roots, n, s, maxdepth);
+  assert(!s || ret == upb_ok(s));
+  return ret;
+}
+
+
+/* Fallback implementation if the shim is not specialized by the JIT. */
+#define SHIM_WRITER(type, ctype)                                              \
+  bool upb_shim_set ## type (void *c, const void *hd, ctype val) {            \
+    uint8_t *m = c;                                                           \
+    const upb_shim_data *d = hd;                                              \
+    if (d->hasbit > 0)                                                        \
+      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
+    *(ctype*)&m[d->offset] = val;                                             \
+    return true;                                                              \
+  }                                                                           \
+
+SHIM_WRITER(double, double)
+SHIM_WRITER(float,  float)
+SHIM_WRITER(int32,  int32_t)
+SHIM_WRITER(int64,  int64_t)
+SHIM_WRITER(uint32, uint32_t)
+SHIM_WRITER(uint64, uint64_t)
+SHIM_WRITER(bool,   bool)
+#undef SHIM_WRITER
+
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+                  int32_t hasbit) {
+  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+  bool ok;
+
+  upb_shim_data *d = upb_gmalloc(sizeof(*d));
+  if (!d) return false;
+  d->offset = offset;
+  d->hasbit = hasbit;
+
+  upb_handlerattr_sethandlerdata(&attr, d);
+  upb_handlerattr_setalwaysok(&attr, true);
+  upb_handlers_addcleanup(h, d, upb_gfree);
+
+#define TYPE(u, l) \
+  case UPB_TYPE_##u: \
+    ok = upb_handlers_set##l(h, f, upb_shim_set##l, &attr); break;
+
+  ok = false;
+
+  switch (upb_fielddef_type(f)) {
+    TYPE(INT64,  int64);
+    TYPE(INT32,  int32);
+    TYPE(ENUM,   int32);
+    TYPE(UINT64, uint64);
+    TYPE(UINT32, uint32);
+    TYPE(DOUBLE, double);
+    TYPE(FLOAT,  float);
+    TYPE(BOOL,   bool);
+    default: assert(false); break;
+  }
+#undef TYPE
+
+  upb_handlerattr_uninit(&attr);
+  return ok;
+}
+
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
+                                      upb_fieldtype_t *type) {
+  upb_func *f = upb_handlers_gethandler(h, s);
+
+  if ((upb_int64_handlerfunc*)f == upb_shim_setint64) {
+    *type = UPB_TYPE_INT64;
+  } else if ((upb_int32_handlerfunc*)f == upb_shim_setint32) {
+    *type = UPB_TYPE_INT32;
+  } else if ((upb_uint64_handlerfunc*)f == upb_shim_setuint64) {
+    *type = UPB_TYPE_UINT64;
+  } else if ((upb_uint32_handlerfunc*)f == upb_shim_setuint32) {
+    *type = UPB_TYPE_UINT32;
+  } else if ((upb_double_handlerfunc*)f == upb_shim_setdouble) {
+    *type = UPB_TYPE_DOUBLE;
+  } else if ((upb_float_handlerfunc*)f == upb_shim_setfloat) {
+    *type = UPB_TYPE_FLOAT;
+  } else if ((upb_bool_handlerfunc*)f == upb_shim_setbool) {
+    *type = UPB_TYPE_BOOL;
+  } else {
+    return NULL;
+  }
+
+  return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
+}
+
+
+#include <string.h>
+
+static void upb_symtab_free(upb_refcounted *r) {
+  upb_symtab *s = (upb_symtab*)r;
+  upb_strtable_iter i;
+  upb_strtable_begin(&i, &s->symtab);
+  for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
+    upb_def_unref(def, s);
+  }
+  upb_strtable_uninit(&s->symtab);
+  upb_gfree(s);
+}
+
+upb_symtab *upb_symtab_new(const void *owner) {
+  static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
+
+  upb_symtab *s = upb_gmalloc(sizeof(*s));
+  if (!s) {
+    return NULL;
+  }
+
+  upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner);
+  upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
+  return s;
+}
+
+void upb_symtab_freeze(upb_symtab *s) {
+  upb_refcounted *r;
+  bool ok;
+
+  assert(!upb_symtab_isfrozen(s));
+  r = upb_symtab_upcast_mutable(s);
+  /* The symtab does not take ref2's (see refcounted.h) on the defs, because
+   * defs cannot refer back to the table and therefore cannot create cycles.  So
+   * 0 will suffice for maxdepth here. */
+  ok = upb_refcounted_freeze(&r, 1, NULL, 0);
+  UPB_ASSERT_VAR(ok, ok);
+}
+
+const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return ret;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return def ? upb_dyncast_msgdef(def) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
+      upb_value_getptr(v) : NULL;
+  return def ? upb_dyncast_enumdef(def) : NULL;
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static upb_def *upb_resolvename(const upb_strtable *t,
+                                const char *base, const char *sym) {
+  if(strlen(sym) == 0) return NULL;
+  if(sym[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    upb_value v;
+    return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL;
+  } else {
+    /* Remove components from base until we find an entry or run out.
+     * TODO: This branch is totally broken, but currently not used. */
+    (void)base;
+    assert(false);
+    return NULL;
+  }
+}
+
+const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
+                                  const char *sym) {
+  upb_def *ret = upb_resolvename(&s->symtab, base, sym);
+  return ret;
+}
+
+/* Starts a depth-first traversal at "def", recursing into any subdefs
+ * (ie. submessage types).  Adds duplicates of existing defs to addtab
+ * wherever necessary, so that the resulting symtab will be consistent once
+ * addtab is added.
+ *
+ * More specifically, if any def D is found in the DFS that:
+ *
+ *   1. can reach a def that is being replaced by something in addtab, AND
+ *
+ *   2. is not itself being replaced already (ie. this name doesn't already
+ *      exist in addtab)
+ *
+ * ...then a duplicate (new copy) of D will be added to addtab.
+ *
+ * Returns true if this happened for any def reachable from "def."
+ *
+ * It is slightly tricky to do this correctly in the presence of cycles.  If we
+ * detect that our DFS has hit a cycle, we might not yet know if any SCCs on
+ * our stack can reach a def in addtab or not.  Once we figure this out, that
+ * answer needs to apply to *all* defs in these SCCs, even if we visited them
+ * already.  So a straight up one-pass cycle-detecting DFS won't work.
+ *
+ * To work around this problem, we traverse each SCC (which we already
+ * computed, since these defs are frozen) as a single node.  We first compute
+ * whether the SCC as a whole can reach any def in addtab, then we dup (or not)
+ * the entire SCC.  This requires breaking the encapsulation of upb_refcounted,
+ * since that is where we get the data about what SCC we are in. */
+static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
+                            const void *new_owner, upb_inttable *seen,
+                            upb_status *s) {
+  upb_value v;
+  bool need_dup;
+  const upb_def *base;
+  const void* memoize_key;
+
+  /* Memoize results of this function for efficiency (since we're traversing a
+   * DAG this is not needed to limit the depth of the search).
+   *
+   * We memoize by SCC instead of by individual def. */
+  memoize_key = def->base.group;
+
+  if (upb_inttable_lookupptr(seen, memoize_key, &v))
+    return upb_value_getbool(v);
+
+  /* Visit submessages for all messages in the SCC. */
+  need_dup = false;
+  base = def;
+  do {
+    upb_value v;
+    const upb_msgdef *m;
+
+    assert(upb_def_isfrozen(def));
+    if (def->type == UPB_DEF_FIELD) continue;
+    if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
+      need_dup = true;
+    }
+
+    /* For messages, continue the recursion by visiting all subdefs, but only
+     * ones in different SCCs. */
+    m = upb_dyncast_msgdef(def);
+    if (m) {
+      upb_msg_field_iter i;
+      for(upb_msg_field_begin(&i, m);
+          !upb_msg_field_done(&i);
+          upb_msg_field_next(&i)) {
+        upb_fielddef *f = upb_msg_iter_field(&i);
+        const upb_def *subdef;
+
+        if (!upb_fielddef_hassubdef(f)) continue;
+        subdef = upb_fielddef_subdef(f);
+
+        /* Skip subdefs in this SCC. */
+        if (def->base.group == subdef->base.group) continue;
+
+        /* |= to avoid short-circuit; we need its side-effects. */
+        need_dup |= upb_resolve_dfs(subdef, addtab, new_owner, seen, s);
+        if (!upb_ok(s)) return false;
+      }
+    }
+  } while ((def = (upb_def*)def->base.next) != base);
+
+  if (need_dup) {
+    /* Dup all defs in this SCC that don't already have entries in addtab. */
+    def = base;
+    do {
+      const char *name;
+
+      if (def->type == UPB_DEF_FIELD) continue;
+      name = upb_def_fullname(def);
+      if (!upb_strtable_lookup(addtab, name, NULL)) {
+        upb_def *newdef = upb_def_dup(def, new_owner);
+        if (!newdef) goto oom;
+        newdef->came_from_user = false;
+        if (!upb_strtable_insert(addtab, name, upb_value_ptr(newdef)))
+          goto oom;
+      }
+    } while ((def = (upb_def*)def->base.next) != base);
+  }
+
+  upb_inttable_insertptr(seen, memoize_key, upb_value_bool(need_dup));
+  return need_dup;
+
+oom:
+  upb_status_seterrmsg(s, "out of memory");
+  return false;
+}
+
+/* TODO(haberman): we need a lot more testing of error conditions.
+ * The came_from_user stuff in particular is not tested. */
+static bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+                       void *ref_donor, upb_refcounted *freeze_also,
+                       upb_status *status) {
+  size_t i;
+  size_t add_n;
+  size_t freeze_n;
+  upb_strtable_iter iter;
+  upb_refcounted **add_objs = NULL;
+  upb_def **add_defs = NULL;
+  size_t add_objs_size;
+  upb_strtable addtab;
+  upb_inttable seen;
+
+  if (n == 0 && !freeze_also) {
+    return true;
+  }
+
+  assert(!upb_symtab_isfrozen(s));
+  if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) {
+    upb_status_seterrmsg(status, "out of memory");
+    return false;
+  }
+
+  /* Add new defs to our "add" set. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    const char *fullname;
+    upb_fielddef *f;
+
+    if (upb_def_isfrozen(def)) {
+      upb_status_seterrmsg(status, "added defs must be mutable");
+      goto err;
+    }
+    assert(!upb_def_isfrozen(def));
+    fullname = upb_def_fullname(def);
+    if (!fullname) {
+      upb_status_seterrmsg(
+          status, "Anonymous defs cannot be added to a symtab");
+      goto err;
+    }
+
+    f = upb_dyncast_fielddef_mutable(def);
+
+    if (f) {
+      if (!upb_fielddef_containingtypename(f)) {
+        upb_status_seterrmsg(status,
+                             "Standalone fielddefs must have a containing type "
+                             "(extendee) name set");
+        goto err;
+      }
+    } else {
+      if (upb_strtable_lookup(&addtab, fullname, NULL)) {
+        upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
+        goto err;
+      }
+      /* We need this to back out properly, because if there is a failure we
+       * need to donate the ref back to the caller. */
+      def->came_from_user = true;
+      upb_def_donateref(def, ref_donor, s);
+      if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
+        goto oom_err;
+    }
+  }
+
+  /* Add standalone fielddefs (ie. extensions) to the appropriate messages.
+   * If the appropriate message only exists in the existing symtab, duplicate
+   * it so we have a mutable copy we can add the fields to. */
+  for (i = 0; i < n; i++) {
+    upb_def *def = defs[i];
+    upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
+    const char *msgname;
+    upb_value v;
+    upb_msgdef *m;
+
+    if (!f) continue;
+    msgname = upb_fielddef_containingtypename(f);
+    /* We validated this earlier in this function. */
+    assert(msgname);
+
+    /* If the extendee name is absolutely qualified, move past the initial ".".
+     * TODO(haberman): it is not obvious what it would mean if this was not
+     * absolutely qualified. */
+    if (msgname[0] == '.') {
+      msgname++;
+    }
+
+    if (upb_strtable_lookup(&addtab, msgname, &v)) {
+      /* Extendee is in the set of defs the user asked us to add. */
+      m = upb_value_getptr(v);
+    } else {
+      /* Need to find and dup the extendee from the existing symtab. */
+      const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname);
+      if (!frozen_m) {
+        upb_status_seterrf(status,
+                           "Tried to extend message %s that does not exist "
+                           "in this SymbolTable.",
+                           msgname);
+        goto err;
+      }
+      m = upb_msgdef_dup(frozen_m, s);
+      if (!m) goto oom_err;
+      if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
+        upb_msgdef_unref(m, s);
+        goto oom_err;
+      }
+    }
+
+    if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
+      goto err;
+    }
+  }
+
+  /* Add dups of any existing def that can reach a def with the same name as
+   * anything in our "add" set. */
+  if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err;
+  upb_strtable_begin(&iter, &s->symtab);
+  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+    upb_resolve_dfs(def, &addtab, s, &seen, status);
+    if (!upb_ok(status)) goto err;
+  }
+  upb_inttable_uninit(&seen);
+
+  /* Now using the table, resolve symbolic references for subdefs. */
+  upb_strtable_begin(&iter, &addtab);
+  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    const char *base;
+    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+    upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+    upb_msg_field_iter j;
+
+    if (!m) continue;
+    /* Type names are resolved relative to the message in which they appear. */
+    base = upb_msgdef_fullname(m);
+
+    for(upb_msg_field_begin(&j, m);
+        !upb_msg_field_done(&j);
+        upb_msg_field_next(&j)) {
+      upb_fielddef *f = upb_msg_iter_field(&j);
+      const char *name = upb_fielddef_subdefname(f);
+      if (name && !upb_fielddef_subdef(f)) {
+        /* Try the lookup in the current set of to-be-added defs first. If not
+         * there, try existing defs. */
+        upb_def *subdef = upb_resolvename(&addtab, base, name);
+        if (subdef == NULL) {
+          subdef = upb_resolvename(&s->symtab, base, name);
+        }
+        if (subdef == NULL) {
+          upb_status_seterrf(
+              status, "couldn't resolve name '%s' in message '%s'", name, base);
+          goto err;
+        } else if (!upb_fielddef_setsubdef(f, subdef, status)) {
+          goto err;
+        }
+      }
+    }
+  }
+
+  /* We need an array of the defs in addtab, for passing to
+   * upb_refcounted_freeze(). */
+  add_objs_size = upb_strtable_count(&addtab);
+  if (freeze_also) {
+    add_objs_size++;
+  }
+
+  add_defs = upb_gmalloc(sizeof(void*) * add_objs_size);
+  if (add_defs == NULL) goto oom_err;
+  upb_strtable_begin(&iter, &addtab);
+  for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+    add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
+  }
+
+  /* Validate defs. */
+  if (!_upb_def_validate(add_defs, add_n, status)) {
+    goto err;
+  }
+
+  /* Cheat a little and give the array a new type.
+   * This is probably undefined behavior, but this code will be deleted soon. */
+  add_objs = (upb_refcounted**)add_defs;
+
+  freeze_n = add_n;
+  if (freeze_also) {
+    add_objs[freeze_n++] = freeze_also;
+  }
+
+  if (!upb_refcounted_freeze(add_objs, freeze_n, status,
+                             UPB_MAX_MESSAGE_DEPTH * 2)) {
+    goto err;
+  }
+
+  /* This must be delayed until all errors have been detected, since error
+   * recovery code uses this table to cleanup defs. */
+  upb_strtable_uninit(&addtab);
+
+  /* TODO(haberman) we don't properly handle errors after this point (like
+   * OOM in upb_strtable_insert() below). */
+  for (i = 0; i < add_n; i++) {
+    upb_def *def = (upb_def*)add_objs[i];
+    const char *name = upb_def_fullname(def);
+    upb_value v;
+    bool success;
+
+    if (upb_strtable_remove(&s->symtab, name, &v)) {
+      const upb_def *def = upb_value_getptr(v);
+      upb_def_unref(def, s);
+    }
+    success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
+    UPB_ASSERT_VAR(success, success == true);
+  }
+  upb_gfree(add_defs);
+  return true;
+
+oom_err:
+  upb_status_seterrmsg(status, "out of memory");
+err: {
+    /* For defs the user passed in, we need to donate the refs back.  For defs
+     * we dup'd, we need to just unref them. */
+    upb_strtable_begin(&iter, &addtab);
+    for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+      upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
+      bool came_from_user = def->came_from_user;
+      def->came_from_user = false;
+      if (came_from_user) {
+        upb_def_donateref(def, s, ref_donor);
+      } else {
+        upb_def_unref(def, s);
+      }
+    }
+  }
+  upb_strtable_uninit(&addtab);
+  upb_gfree(add_defs);
+  assert(!upb_ok(status));
+  return false;
+}
+
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+                    void *ref_donor, upb_status *status) {
+  return symtab_add(s, defs, n, ref_donor, NULL, status);
+}
+
+bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) {
+  size_t n;
+  size_t i;
+  upb_def **defs;
+  bool ret;
+
+  n = upb_filedef_defcount(file);
+  defs = upb_gmalloc(sizeof(*defs) * n);
+
+  if (defs == NULL) {
+    upb_status_seterrmsg(status, "Out of memory");
+    return false;
+  }
+
+  for (i = 0; i < n; i++) {
+    defs[i] = upb_filedef_mutabledef(file, i);
+  }
+
+  ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status);
+
+  upb_gfree(defs);
+  return ret;
+}
+
+/* Iteration. */
+
+static void advance_to_matching(upb_symtab_iter *iter) {
+  if (iter->type == UPB_DEF_ANY)
+    return;
+
+  while (!upb_strtable_done(&iter->iter) &&
+         iter->type != upb_symtab_iter_def(iter)->type) {
+    upb_strtable_next(&iter->iter);
+  }
+}
+
+void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
+                      upb_deftype_t type) {
+  upb_strtable_begin(&iter->iter, &s->symtab);
+  iter->type = type;
+  advance_to_matching(iter);
+}
+
+void upb_symtab_next(upb_symtab_iter *iter) {
+  upb_strtable_next(&iter->iter);
+  advance_to_matching(iter);
+}
+
+bool upb_symtab_done(const upb_symtab_iter *iter) {
+  return upb_strtable_done(&iter->iter);
+}
+
+const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
+  return upb_value_getptr(upb_strtable_iter_value(&iter->iter));
+}
+/*
+** upb_table Implementation
+**
+** Implementation is heavily inspired by Lua's ltable.c.
+*/
+
+
+#include <string.h>
+
+#define UPB_MAXARRSIZE 16  /* 64k. */
+
+/* From Chromium. */
+#define ARRAY_SIZE(x) \
+    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+#ifdef NDEBUG
+static void upb_check_alloc(upb_table *t, upb_alloc *a) {
+  UPB_UNUSED(t);
+  UPB_UNUSED(a);
+}
+#else
+static void upb_check_alloc(upb_table *t, upb_alloc *a) {
+  assert(t->alloc == a);
+}
+#endif
+
+static const double MAX_LOAD = 0.85;
+
+/* The minimum utilization of the array part of a mixed hash/array table.  This
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
+ * cache effects).  The lower this is, the more memory we'll use. */
+static const double MIN_DENSITY = 0.1;
+
+bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
+
+int log2ceil(uint64_t v) {
+  int ret = 0;
+  bool pow2 = is_pow2(v);
+  while (v >>= 1) ret++;
+  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
+  return UPB_MIN(UPB_MAXARRSIZE, ret);
+}
+
+char *upb_strdup(const char *s, upb_alloc *a) {
+  return upb_strdup2(s, strlen(s), a);
+}
+
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
+  size_t n;
+  char *p;
+
+  /* Prevent overflow errors. */
+  if (len == SIZE_MAX) return NULL;
+  /* Always null-terminate, even if binary data; but don't rely on the input to
+   * have a null-terminating byte since it may be a raw binary buffer. */
+  n = len + 1;
+  p = upb_malloc(a, n);
+  if (p) {
+    memcpy(p, s, len);
+    p[len] = 0;
+  }
+  return p;
+}
+
+/* A type to represent the lookup key of either a strtable or an inttable. */
+typedef union {
+  uintptr_t num;
+  struct {
+    const char *str;
+    size_t len;
+  } str;
+} lookupkey_t;
+
+static lookupkey_t strkey2(const char *str, size_t len) {
+  lookupkey_t k;
+  k.str.str = str;
+  k.str.len = len;
+  return k;
+}
+
+static lookupkey_t intkey(uintptr_t key) {
+  lookupkey_t k;
+  k.num = key;
+  return k;
+}
+
+typedef uint32_t hashfunc_t(upb_tabkey key);
+typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
+
+/* Base table (shared code) ***************************************************/
+
+/* For when we need to cast away const. */
+static upb_tabent *mutable_entries(upb_table *t) {
+  return (upb_tabent*)t->entries;
+}
+
+static bool isfull(upb_table *t) {
+  if (upb_table_size(t) == 0) {
+    return true;
+  } else {
+    return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
+  }
+}
+
+static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2,
+                 upb_alloc *a) {
+  size_t bytes;
+
+  t->count = 0;
+  t->ctype = ctype;
+  t->size_lg2 = size_lg2;
+  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+#ifndef NDEBUG
+  t->alloc = a;
+#endif
+  bytes = upb_table_size(t) * sizeof(upb_tabent);
+  if (bytes > 0) {
+    t->entries = upb_malloc(a, bytes);
+    if (!t->entries) return false;
+    memset(mutable_entries(t), 0, bytes);
+  } else {
+    t->entries = NULL;
+  }
+  return true;
+}
+
+static void uninit(upb_table *t, upb_alloc *a) {
+  upb_check_alloc(t, a);
+  upb_free(a, mutable_entries(t));
+}
+
+static upb_tabent *emptyent(upb_table *t) {
+  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
+  while (1) { if (upb_tabent_isempty(--e)) return e; assert(e > t->entries); }
+}
+
+static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
+  return (upb_tabent*)upb_getentry(t, hash);
+}
+
+static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
+                                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e;
+
+  if (t->size_lg2 == 0) return NULL;
+  e = upb_getentry(t, hash);
+  if (upb_tabent_isempty(e)) return NULL;
+  while (1) {
+    if (eql(e->key, key)) return e;
+    if ((e = e->next) == NULL) return NULL;
+  }
+}
+
+static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
+                                     uint32_t hash, eqlfunc_t *eql) {
+  return (upb_tabent*)findentry(t, key, hash, eql);
+}
+
+static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
+                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e = findentry(t, key, hash, eql);
+  if (e) {
+    if (v) {
+      _upb_value_setval(v, e->val.val, t->ctype);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* The given key must not already exist in the table. */
+static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
+                   upb_value val, uint32_t hash,
+                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
+  upb_tabent *mainpos_e;
+  upb_tabent *our_e;
+
+  UPB_UNUSED(eql);
+  UPB_UNUSED(key);
+  assert(findentry(t, key, hash, eql) == NULL);
+  assert(val.ctype == t->ctype);
+
+  t->count++;
+  mainpos_e = getentry_mutable(t, hash);
+  our_e = mainpos_e;
+
+  if (upb_tabent_isempty(mainpos_e)) {
+    /* Our main position is empty; use it. */
+    our_e->next = NULL;
+  } else {
+    /* Collision. */
+    upb_tabent *new_e = emptyent(t);
+    /* Head of collider's chain. */
+    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
+    if (chain == mainpos_e) {
+      /* Existing ent is in its main posisiton (it has the same hash as us, and
+       * is the head of our chain).  Insert to new ent and append to this chain. */
+      new_e->next = mainpos_e->next;
+      mainpos_e->next = new_e;
+      our_e = new_e;
+    } else {
+      /* Existing ent is not in its main position (it is a node in some other
+       * chain).  This implies that no existing ent in the table has our hash.
+       * Evict it (updating its chain) and use its ent for head of our chain. */
+      *new_e = *mainpos_e;  /* copies next. */
+      while (chain->next != mainpos_e) {
+        chain = (upb_tabent*)chain->next;
+        assert(chain);
+      }
+      chain->next = new_e;
+      our_e = mainpos_e;
+      our_e->next = NULL;
+    }
+  }
+  our_e->key = tabkey;
+  our_e->val.val = val.val;
+  assert(findentry(t, key, hash, eql) == our_e);
+}
+
+static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
+               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
+  upb_tabent *chain = getentry_mutable(t, hash);
+  if (upb_tabent_isempty(chain)) return false;
+  if (eql(chain->key, key)) {
+    /* Element to remove is at the head of its chain. */
+    t->count--;
+    if (val) {
+      _upb_value_setval(val, chain->val.val, t->ctype);
+    }
+    if (chain->next) {
+      upb_tabent *move = (upb_tabent*)chain->next;
+      *chain = *move;
+      if (removed) *removed = move->key;
+      move->key = 0;  /* Make the slot empty. */
+    } else {
+      if (removed) *removed = chain->key;
+      chain->key = 0;  /* Make the slot empty. */
+    }
+    return true;
+  } else {
+    /* Element to remove is either in a non-head position or not in the
+     * table. */
+    while (chain->next && !eql(chain->next->key, key))
+      chain = (upb_tabent*)chain->next;
+    if (chain->next) {
+      /* Found element to remove. */
+      upb_tabent *rm;
+
+      if (val) {
+        _upb_value_setval(val, chain->next->val.val, t->ctype);
+      }
+      rm = (upb_tabent*)chain->next;
+      if (removed) *removed = rm->key;
+      rm->key = 0;
+      chain->next = rm->next;
+      t->count--;
+      return true;
+    } else {
+      return false;
+    }
+  }
+}
+
+static size_t next(const upb_table *t, size_t i) {
+  do {
+    if (++i >= upb_table_size(t))
+      return SIZE_MAX;
+  } while(upb_tabent_isempty(&t->entries[i]));
+
+  return i;
+}
+
+static size_t begin(const upb_table *t) {
+  return next(t, -1);
+}
+
+
+/* upb_strtable ***************************************************************/
+
+/* A simple "subclass" of upb_table that only adds a hash function for strings. */
+
+static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
+  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
+  if (str == NULL) return 0;
+  memcpy(str, &k2.str.len, sizeof(uint32_t));
+  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1);
+  return (uintptr_t)str;
+}
+
+static uint32_t strhash(upb_tabkey key) {
+  uint32_t len;
+  char *str = upb_tabstr(key, &len);
+  return MurmurHash2(str, len, 0);
+}
+
+static bool streql(upb_tabkey k1, lookupkey_t k2) {
+  uint32_t len;
+  char *str = upb_tabstr(k1, &len);
+  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
+}
+
+bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
+  return init(&t->t, ctype, 2, a);
+}
+
+void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
+  size_t i;
+  for (i = 0; i < upb_table_size(&t->t); i++)
+    upb_free(a, (void*)t->t.entries[i].key);
+  uninit(&t->t, a);
+}
+
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
+  upb_strtable new_table;
+  upb_strtable_iter i;
+
+  upb_check_alloc(&t->t, a);
+
+  if (!init(&new_table.t, t->t.ctype, size_lg2, a))
+    return false;
+  upb_strtable_begin(&i, t);
+  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    upb_strtable_insert3(
+        &new_table,
+        upb_strtable_iter_key(&i),
+        upb_strtable_iter_keylength(&i),
+        upb_strtable_iter_value(&i),
+        a);
+  }
+  upb_strtable_uninit2(t, a);
+  *t = new_table;
+  return true;
+}
+
+bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
+                          upb_value v, upb_alloc *a) {
+  lookupkey_t key;
+  upb_tabkey tabkey;
+  uint32_t hash;
+
+  upb_check_alloc(&t->t, a);
+
+  if (isfull(&t->t)) {
+    /* Need to resize.  New table of double the size, add old elements to it. */
+    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
+      return false;
+    }
+  }
+
+  key = strkey2(k, len);
+  tabkey = strcopy(key, a);
+  if (tabkey == 0) return false;
+
+  hash = MurmurHash2(key.str.str, key.str.len, 0);
+  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
+  return true;
+}
+
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v) {
+  uint32_t hash = MurmurHash2(key, len, 0);
+  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
+}
+
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+                         upb_value *val, upb_alloc *alloc) {
+  uint32_t hash = MurmurHash2(key, strlen(key), 0);
+  upb_tabkey tabkey;
+  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
+    upb_free(alloc, (void*)tabkey);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* Iteration */
+
+static const upb_tabent *str_tabent(const upb_strtable_iter *i) {
+  return &i->t->t.entries[i->index];
+}
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
+  i->t = t;
+  i->index = begin(&t->t);
+}
+
+void upb_strtable_next(upb_strtable_iter *i) {
+  i->index = next(&i->t->t, i->index);
+}
+
+bool upb_strtable_done(const upb_strtable_iter *i) {
+  return i->index >= upb_table_size(&i->t->t) ||
+         upb_tabent_isempty(str_tabent(i));
+}
+
+const char *upb_strtable_iter_key(const upb_strtable_iter *i) {
+  assert(!upb_strtable_done(i));
+  return upb_tabstr(str_tabent(i)->key, NULL);
+}
+
+size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) {
+  uint32_t len;
+  assert(!upb_strtable_done(i));
+  upb_tabstr(str_tabent(i)->key, &len);
+  return len;
+}
+
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
+  assert(!upb_strtable_done(i));
+  return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
+}
+
+void upb_strtable_iter_setdone(upb_strtable_iter *i) {
+  i->index = SIZE_MAX;
+}
+
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2) {
+  if (upb_strtable_done(i1) && upb_strtable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index;
+}
+
+
+/* upb_inttable ***************************************************************/
+
+/* For inttables we use a hybrid structure where small keys are kept in an
+ * array and large keys are put in the hash table. */
+
+static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
+
+static bool inteql(upb_tabkey k1, lookupkey_t k2) {
+  return k1 == k2.num;
+}
+
+static upb_tabval *mutable_array(upb_inttable *t) {
+  return (upb_tabval*)t->array;
+}
+
+static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
+  if (key < t->array_size) {
+    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
+  } else {
+    upb_tabent *e =
+        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
+    return e ? &e->val : NULL;
+  }
+}
+
+static const upb_tabval *inttable_val_const(const upb_inttable *t,
+                                            uintptr_t key) {
+  return inttable_val((upb_inttable*)t, key);
+}
+
+size_t upb_inttable_count(const upb_inttable *t) {
+  return t->t.count + t->array_count;
+}
+
+static void check(upb_inttable *t) {
+  UPB_UNUSED(t);
+#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
+  {
+    /* This check is very expensive (makes inserts/deletes O(N)). */
+    size_t count = 0;
+    upb_inttable_iter i;
+    upb_inttable_begin(&i, t);
+    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
+      assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+    }
+    assert(count == upb_inttable_count(t));
+  }
+#endif
+}
+
+bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
+                            size_t asize, int hsize_lg2, upb_alloc *a) {
+  size_t array_bytes;
+
+  if (!init(&t->t, ctype, hsize_lg2, a)) return false;
+  /* Always make the array part at least 1 long, so that we know key 0
+   * won't be in the hash part, which simplifies things. */
+  t->array_size = UPB_MAX(1, asize);
+  t->array_count = 0;
+  array_bytes = t->array_size * sizeof(upb_value);
+  t->array = upb_malloc(a, array_bytes);
+  if (!t->array) {
+    uninit(&t->t, a);
+    return false;
+  }
+  memset(mutable_array(t), 0xff, array_bytes);
+  check(t);
+  return true;
+}
+
+bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
+  return upb_inttable_sizedinit(t, ctype, 0, 4, a);
+}
+
+void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
+  uninit(&t->t, a);
+  upb_free(a, mutable_array(t));
+}
+
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+                          upb_alloc *a) {
+  upb_tabval tabval;
+  tabval.val = val.val;
+  UPB_UNUSED(tabval);
+  assert(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
+
+  upb_check_alloc(&t->t, a);
+
+  if (key < t->array_size) {
+    assert(!upb_arrhas(t->array[key]));
+    t->array_count++;
+    mutable_array(t)[key].val = val.val;
+  } else {
+    if (isfull(&t->t)) {
+      /* Need to resize the hash part, but we re-use the array part. */
+      size_t i;
+      upb_table new_table;
+
+      if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) {
+        return false;
+      }
+
+      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
+        const upb_tabent *e = &t->t.entries[i];
+        uint32_t hash;
+        upb_value v;
+
+        _upb_value_setval(&v, e->val.val, t->t.ctype);
+        hash = upb_inthash(e->key);
+        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
+      }
+
+      assert(t->t.count == new_table.count);
+
+      uninit(&t->t, a);
+      t->t = new_table;
+    }
+    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
+  }
+  check(t);
+  return true;
+}
+
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
+  const upb_tabval *table_v = inttable_val_const(t, key);
+  if (!table_v) return false;
+  if (v) _upb_value_setval(v, table_v->val, t->t.ctype);
+  return true;
+}
+
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
+  upb_tabval *table_v = inttable_val(t, key);
+  if (!table_v) return false;
+  table_v->val = val.val;
+  return true;
+}
+
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
+  bool success;
+  if (key < t->array_size) {
+    if (upb_arrhas(t->array[key])) {
+      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
+      t->array_count--;
+      if (val) {
+        _upb_value_setval(val, t->array[key].val, t->t.ctype);
+      }
+      mutable_array(t)[key] = empty;
+      success = true;
+    } else {
+      success = false;
+    }
+  } else {
+    upb_tabkey removed;
+    uint32_t hash = upb_inthash(key);
+    success = rm(&t->t, intkey(key), val, &removed, hash, &inteql);
+  }
+  check(t);
+  return success;
+}
+
+bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
+  upb_check_alloc(&t->t, a);
+  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
+}
+
+upb_value upb_inttable_pop(upb_inttable *t) {
+  upb_value val;
+  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
+  UPB_ASSERT_VAR(ok, ok);
+  return val;
+}
+
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+                             upb_alloc *a) {
+  upb_check_alloc(&t->t, a);
+  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
+}
+
+bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
+                            upb_value *v) {
+  return upb_inttable_lookup(t, (uintptr_t)key, v);
+}
+
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
+  return upb_inttable_remove(t, (uintptr_t)key, val);
+}
+
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
+  /* A power-of-two histogram of the table keys. */
+  size_t counts[UPB_MAXARRSIZE + 1] = {0};
+
+  /* The max key in each bucket. */
+  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
+
+  upb_inttable_iter i;
+  size_t arr_count;
+  int size_lg2;
+  upb_inttable new_t;
+
+  upb_check_alloc(&t->t, a);
+
+  upb_inttable_begin(&i, t);
+  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    uintptr_t key = upb_inttable_iter_key(&i);
+    int bucket = log2ceil(key);
+    max[bucket] = UPB_MAX(max[bucket], key);
+    counts[bucket]++;
+  }
+
+  /* Find the largest power of two that satisfies the MIN_DENSITY
+   * definition (while actually having some keys). */
+  arr_count = upb_inttable_count(t);
+
+  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
+    if (counts[size_lg2] == 0) {
+      /* We can halve again without losing any entries. */
+      continue;
+    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
+      break;
+    }
+
+    arr_count -= counts[size_lg2];
+  }
+
+  assert(arr_count <= upb_inttable_count(t));
+
+  {
+    /* Insert all elements into new, perfectly-sized table. */
+    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
+    size_t hash_count = upb_inttable_count(t) - arr_count;
+    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+    size_t hashsize_lg2 = log2ceil(hash_size);
+
+    upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a);
+    upb_inttable_begin(&i, t);
+    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+      uintptr_t k = upb_inttable_iter_key(&i);
+      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
+    }
+    assert(new_t.array_size == arr_size);
+    assert(new_t.t.size_lg2 == hashsize_lg2);
+  }
+  upb_inttable_uninit2(t, a);
+  *t = new_t;
+}
+
+/* Iteration. */
+
+static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
+  assert(!i->array_part);
+  return &i->t->t.entries[i->index];
+}
+
+static upb_tabval int_arrent(const upb_inttable_iter *i) {
+  assert(i->array_part);
+  return i->t->array[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
+  i->t = t;
+  i->index = -1;
+  i->array_part = true;
+  upb_inttable_next(i);
+}
+
+void upb_inttable_next(upb_inttable_iter *iter) {
+  const upb_inttable *t = iter->t;
+  if (iter->array_part) {
+    while (++iter->index < t->array_size) {
+      if (upb_arrhas(int_arrent(iter))) {
+        return;
+      }
+    }
+    iter->array_part = false;
+    iter->index = begin(&t->t);
+  } else {
+    iter->index = next(&t->t, iter->index);
+  }
+}
+
+bool upb_inttable_done(const upb_inttable_iter *i) {
+  if (i->array_part) {
+    return i->index >= i->t->array_size ||
+           !upb_arrhas(int_arrent(i));
+  } else {
+    return i->index >= upb_table_size(&i->t->t) ||
+           upb_tabent_isempty(int_tabent(i));
+  }
+}
+
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
+  assert(!upb_inttable_done(i));
+  return i->array_part ? i->index : int_tabent(i)->key;
+}
+
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
+  assert(!upb_inttable_done(i));
+  return _upb_value_val(
+      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
+      i->t->t.ctype);
+}
+
+void upb_inttable_iter_setdone(upb_inttable_iter *i) {
+  i->index = SIZE_MAX;
+  i->array_part = false;
+}
+
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                                          const upb_inttable_iter *i2) {
+  if (upb_inttable_done(i1) && upb_inttable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index &&
+         i1->array_part == i2->array_part;
+}
+
+#ifdef UPB_UNALIGNED_READS_OK
+/* -----------------------------------------------------------------------------
+ * MurmurHash2, by Austin Appleby (released as public domain).
+ * Reformatted and C99-ified by Joshua Haberman.
+ * Note - This code makes a few assumptions about how your machine behaves -
+ *   1. We can read a 4-byte value from any address without crashing
+ *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
+ * And it has a few limitations -
+ *   1. It will not work incrementally.
+ *   2. It will not produce the same results on little-endian and big-endian
+ *      machines. */
+uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) {
+  /* 'm' and 'r' are mixing constants generated offline.
+   * They're not really 'magic', they just happen to work well. */
+  const uint32_t m = 0x5bd1e995;
+  const int32_t r = 24;
+
+  /* Initialize the hash to a 'random' value */
+  uint32_t h = seed ^ len;
+
+  /* Mix 4 bytes at a time into the hash */
+  const uint8_t * data = (const uint8_t *)key;
+  while(len >= 4) {
+    uint32_t k = *(uint32_t *)data;
+
+    k *= m;
+    k ^= k >> r;
+    k *= m;
+
+    h *= m;
+    h ^= k;
+
+    data += 4;
+    len -= 4;
+  }
+
+  /* Handle the last few bytes of the input array */
+  switch(len) {
+    case 3: h ^= data[2] << 16;
+    case 2: h ^= data[1] << 8;
+    case 1: h ^= data[0]; h *= m;
+  };
+
+  /* Do a few final mixes of the hash to ensure the last few
+   * bytes are well-incorporated. */
+  h ^= h >> 13;
+  h *= m;
+  h ^= h >> 15;
+
+  return h;
+}
+
+#else /* !UPB_UNALIGNED_READS_OK */
+
+/* -----------------------------------------------------------------------------
+ * MurmurHashAligned2, by Austin Appleby
+ * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
+ * on certain platforms.
+ * Performance will be lower than MurmurHash2 */
+
+#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
+
+uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) {
+  const uint32_t m = 0x5bd1e995;
+  const int32_t r = 24;
+  const uint8_t * data = (const uint8_t *)key;
+  uint32_t h = seed ^ len;
+  uint8_t align = (uintptr_t)data & 3;
+
+  if(align && (len >= 4)) {
+    /* Pre-load the temp registers */
+    uint32_t t = 0, d = 0;
+    int32_t sl;
+    int32_t sr;
+
+    switch(align) {
+      case 1: t |= data[2] << 16;
+      case 2: t |= data[1] << 8;
+      case 3: t |= data[0];
+    }
+
+    t <<= (8 * align);
+
+    data += 4-align;
+    len -= 4-align;
+
+    sl = 8 * (4-align);
+    sr = 8 * align;
+
+    /* Mix */
+
+    while(len >= 4) {
+      uint32_t k;
+
+      d = *(uint32_t *)data;
+      t = (t >> sr) | (d << sl);
+
+      k = t;
+
+      MIX(h,k,m);
+
+      t = d;
+
+      data += 4;
+      len -= 4;
+    }
+
+    /* Handle leftover data in temp registers */
+
+    d = 0;
+
+    if(len >= align) {
+      uint32_t k;
+
+      switch(align) {
+        case 3: d |= data[2] << 16;
+        case 2: d |= data[1] << 8;
+        case 1: d |= data[0];
+      }
+
+      k = (t >> sr) | (d << sl);
+      MIX(h,k,m);
+
+      data += align;
+      len -= align;
+
+      /* ----------
+       * Handle tail bytes */
+
+      switch(len) {
+        case 3: h ^= data[2] << 16;
+        case 2: h ^= data[1] << 8;
+        case 1: h ^= data[0]; h *= m;
+      };
+    } else {
+      switch(len) {
+        case 3: d |= data[2] << 16;
+        case 2: d |= data[1] << 8;
+        case 1: d |= data[0];
+        case 0: h ^= (t >> sr) | (d << sl); h *= m;
+      }
+    }
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+  } else {
+    while(len >= 4) {
+      uint32_t k = *(uint32_t *)data;
+
+      MIX(h,k,m);
+
+      data += 4;
+      len -= 4;
+    }
+
+    /* ----------
+     * Handle tail bytes */
+
+    switch(len) {
+      case 3: h ^= data[2] << 16;
+      case 2: h ^= data[1] << 8;
+      case 1: h ^= data[0]; h *= m;
+    };
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+  }
+}
+#undef MIX
+
+#endif /* UPB_UNALIGNED_READS_OK */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool upb_dumptostderr(void *closure, const upb_status* status) {
+  UPB_UNUSED(closure);
+  fprintf(stderr, "%s\n", upb_status_errmsg(status));
+  return false;
+}
+
+/* Guarantee null-termination and provide ellipsis truncation.
+ * It may be tempting to "optimize" this by initializing these final
+ * four bytes up-front and then being careful never to overwrite them,
+ * this is safer and simpler. */
+static void nullz(upb_status *status) {
+  const char *ellipsis = "...";
+  size_t len = strlen(ellipsis);
+  assert(sizeof(status->msg) > len);
+  memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
+}
+
+
+/* upb_upberr *****************************************************************/
+
+upb_errorspace upb_upberr = {"upb error"};
+
+void upb_upberr_setoom(upb_status *status) {
+  status->error_space_ = &upb_upberr;
+  upb_status_seterrmsg(status, "Out of memory");
+}
+
+
+/* upb_status *****************************************************************/
+
+void upb_status_clear(upb_status *status) {
+  if (!status) return;
+  status->ok_ = true;
+  status->code_ = 0;
+  status->msg[0] = '\0';
+}
+
+bool upb_ok(const upb_status *status) { return status->ok_; }
+
+upb_errorspace *upb_status_errspace(const upb_status *status) {
+  return status->error_space_;
+}
+
+int upb_status_errcode(const upb_status *status) { return status->code_; }
+
+const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
+
+void upb_status_seterrmsg(upb_status *status, const char *msg) {
+  if (!status) return;
+  status->ok_ = false;
+  strncpy(status->msg, msg, sizeof(status->msg));
+  nullz(status);
+}
+
+void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(status, fmt, args);
+  va_end(args);
+}
+
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
+  if (!status) return;
+  status->ok_ = false;
+  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+  nullz(status);
+}
+
+void upb_status_copy(upb_status *to, const upb_status *from) {
+  if (!to) return;
+  *to = *from;
+}
+
+
+/* upb_alloc ******************************************************************/
+
+static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                                  size_t size) {
+  UPB_UNUSED(alloc);
+  UPB_UNUSED(oldsize);
+  if (size == 0) {
+    free(ptr);
+    return NULL;
+  } else {
+    return realloc(ptr, size);
+  }
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+
+/* upb_arena ******************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+static const size_t maxalign = 16;
+
+static size_t align_up(size_t size) {
+  return ((size + maxalign - 1) / maxalign) * maxalign;
+}
+
+typedef struct mem_block {
+  struct mem_block *next;
+  size_t size;
+  size_t used;
+  bool owned;
+  /* Data follows. */
+} mem_block;
+
+typedef struct cleanup_ent {
+  struct cleanup_ent *next;
+  upb_cleanup_func *cleanup;
+  void *ud;
+} cleanup_ent;
+
+static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
+                               bool owned) {
+  mem_block *block = ptr;
+
+  block->next = a->block_head;
+  block->size = size;
+  block->used = align_up(sizeof(mem_block));
+  block->owned = owned;
+
+  a->block_head = block;
+
+  /* TODO(haberman): ASAN poison. */
+}
+
+
+static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
+  size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
+  mem_block *block = upb_malloc(a->block_alloc, block_size);
+
+  if (!block) {
+    return NULL;
+  }
+
+  upb_arena_addblock(a, block, block_size, true);
+  a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
+
+  return block;
+}
+
+static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                               size_t size) {
+  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
+  mem_block *block = a->block_head;
+  void *ret;
+
+  if (size == 0) {
+    return NULL;  /* We are an arena, don't need individual frees. */
+  }
+
+  size = align_up(size);
+
+  /* TODO(haberman): special-case if this is a realloc of the last alloc? */
+
+  if (!block || block->size - block->used < size) {
+    /* Slow path: have to allocate a new block. */
+    block = upb_arena_allocblock(a, size);
+
+    if (!block) {
+      return NULL;  /* Out of memory. */
+    }
+  }
+
+  ret = (char*)block + block->used;
+  block->used += size;
+
+  if (oldsize > 0) {
+    memcpy(ret, ptr, oldsize);  /* Preserve existing data. */
+  }
+
+  /* TODO(haberman): ASAN unpoison. */
+
+  a->bytes_allocated += size;
+  return ret;
+}
+
+/* Public Arena API ***********************************************************/
+
+void upb_arena_init(upb_arena *a) {
+  a->alloc.func = &upb_arena_doalloc;
+  a->block_alloc = &upb_alloc_global;
+  a->bytes_allocated = 0;
+  a->next_block_size = 256;
+  a->max_block_size = 16384;
+  a->cleanup_head = NULL;
+  a->block_head = NULL;
+}
+
+void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) {
+  upb_arena_init(a);
+
+  if (size > sizeof(mem_block)) {
+    upb_arena_addblock(a, mem, size, false);
+  }
+
+  if (alloc) {
+    a->block_alloc = alloc;
+  }
+}
+
+void upb_arena_uninit(upb_arena *a) {
+  cleanup_ent *ent = a->cleanup_head;
+  mem_block *block = a->block_head;
+
+  while (ent) {
+    ent->cleanup(ent->ud);
+    ent = ent->next;
+  }
+
+  /* Must do this after running cleanup functions, because this will delete
+   * the memory we store our cleanup entries in! */
+  while (block) {
+    mem_block *next = block->next;
+
+    if (block->owned) {
+      upb_free(a->block_alloc, block);
+    }
+
+    block = next;
+  }
+}
+
+bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) {
+  cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent));
+  if (!ent) {
+    return false;  /* Out of memory. */
+  }
+
+  ent->cleanup = func;
+  ent->ud = ud;
+  ent->next = a->cleanup_head;
+  a->cleanup_head = ent;
+
+  return true;
+}
+
+size_t upb_arena_bytesallocated(const upb_arena *a) {
+  return a->bytes_allocated;
+}
+
+
+/* Standard error functions ***************************************************/
+
+static bool default_err(void *ud, const upb_status *status) {
+  UPB_UNUSED(ud);
+  UPB_UNUSED(status);
+  return false;
+}
+
+static bool write_err_to(void *ud, const upb_status *status) {
+  upb_status *copy_to = ud;
+  upb_status_copy(copy_to, status);
+  return false;
+}
+
+
+/* upb_env ********************************************************************/
+
+void upb_env_initonly(upb_env *e) {
+  e->ok_ = true;
+  e->error_func_ = &default_err;
+  e->error_ud_ = NULL;
+}
+
+void upb_env_init(upb_env *e) {
+  upb_arena_init(&e->arena_);
+  upb_env_initonly(e);
+}
+
+void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc) {
+  upb_arena_init2(&e->arena_, mem, n, alloc);
+  upb_env_initonly(e);
+}
+
+void upb_env_uninit(upb_env *e) {
+  upb_arena_uninit(&e->arena_);
+}
+
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud) {
+  e->error_func_ = func;
+  e->error_ud_ = ud;
+}
+
+void upb_env_reporterrorsto(upb_env *e, upb_status *s) {
+  e->error_func_ = &write_err_to;
+  e->error_ud_ = s;
+}
+
+bool upb_env_reporterror(upb_env *e, const upb_status *status) {
+  e->ok_ = false;
+  return e->error_func_(e->error_ud_, status);
+}
+
+void *upb_env_malloc(upb_env *e, size_t size) {
+  return upb_malloc(&e->arena_.alloc, size);
+}
+
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
+  return upb_realloc(&e->arena_.alloc, ptr, oldsize, size);
+}
+
+void upb_env_free(upb_env *e, void *ptr) {
+  upb_free(&e->arena_.alloc, ptr);
+}
+
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
+  return upb_arena_addcleanup(&e->arena_, func, ud);
+}
+
+size_t upb_env_bytesallocated(const upb_env *e) {
+  return upb_arena_bytesallocated(&e->arena_);
+}
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     upb/descriptor/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <assert.h>
+
+
+static const upb_msgdef msgs[22];
+static const upb_fielddef fields[105];
+static const upb_enumdef enums[5];
+static const upb_tabent strentries[236];
+static const upb_tabent intentries[18];
+static const upb_tabval arrays[184];
+
+#ifdef UPB_DEBUG_REFS
+static upb_inttable reftables[264];
+#endif
+
+static const upb_msgdef msgs[22] = {
+  UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 40, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]),
+  UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]),
+  UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]),
+  UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]),
+  UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 23, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]),
+  UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]),
+  UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]),
+  UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]),
+  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
+  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[107], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[115], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[122], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
+  UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[123], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[125], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[129], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[130], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[132], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[139], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[148], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
+};
+
+static const upb_fielddef fields[105] = {
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 17, 6, {0},&reftables[50], &reftables[51]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 13, 4, {0},&reftables[52], &reftables[53]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 27, 14, {0},&reftables[54], &reftables[55]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[62], &reftables[63]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[64], &reftables[65]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[66], &reftables[67]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[70], &reftables[71]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[72], &reftables[73]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[82], &reftables[83]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[84], &reftables[85]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 21, 3, {0},&reftables[92], &reftables[93]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 12, 0, {0},&reftables[94], &reftables[95]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 5, 0, {0},&reftables[96], &reftables[97]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 14, 5, {0},&reftables[98], &reftables[99]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 6, 1, {0},&reftables[100], &reftables[101]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 7, 2, {0},&reftables[102], &reftables[103]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 5, 1, {0},&reftables[104], &reftables[105]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 20, 9, {0},&reftables[106], &reftables[107]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 18, 7, {0},&reftables[108], &reftables[109]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 13, 4, {0},&reftables[110], &reftables[111]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 9, 2, {0},&reftables[112], &reftables[113]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 6, 1, {0},&reftables[114], &reftables[115]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 22, 11, {0},&reftables[116], &reftables[117]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 30, 15, {0},&reftables[118], &reftables[119]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 20, 9, {0},&reftables[120], &reftables[121]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 10, 5, {0},&reftables[122], &reftables[123]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[124], &reftables[125]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 9, 4, {0},&reftables[126], &reftables[127]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 8, 2, {0},&reftables[128], &reftables[129]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 16, 4, {0},&reftables[130], &reftables[131]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[132], &reftables[133]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 9, 4, {0},&reftables[134], &reftables[135]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[142], &reftables[143]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[144], &reftables[145]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[146], &reftables[147]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[148], &reftables[149]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[150], &reftables[151]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[152], &reftables[153]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[154], &reftables[155]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[156], &reftables[157]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[158], &reftables[159]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[170], &reftables[171]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[186], &reftables[187]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[190], &reftables[191]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[192], &reftables[193]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[202], &reftables[203]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[204], &reftables[205]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[206], &reftables[207]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[208], &reftables[209]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[210], &reftables[211]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[212], &reftables[213]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[214], &reftables[215]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[216], &reftables[217]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[218], &reftables[219]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[220], &reftables[221]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[222], &reftables[223]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[224], &reftables[225]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[226], &reftables[227]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[228], &reftables[229]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[230], &reftables[231]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[232], &reftables[233]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[234], &reftables[235]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[236], &reftables[237]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[248], &reftables[249]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[250], &reftables[251]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[252], &reftables[253]),
+};
+
+static const upb_enumdef enums[5] = {
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[151], 4, 3), 0, &reftables[254], &reftables[255]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[155], 19, 18), 0, &reftables[256], &reftables[257]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[174], 3, 3), 0, &reftables[258], &reftables[259]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[260], &reftables[261]),
+  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 4, 3), 0, &reftables[262], &reftables[263]),
+};
+
+static const upb_tabent strentries[236] = {
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
+  {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
+  {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), &strentries[26]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[34]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[93]), &strentries[50]},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[85]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
+  {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
+  {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
+  {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
+  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[87]), &strentries[167]},
+  {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[90]), &strentries[182]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL},
+  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL},
+};
+
+static const upb_tabent intentries[18] = {
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
+};
+
+static const upb_tabval arrays[184] = {
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_PTR_INIT(&fields[25]),
+  UPB_TABVALUE_PTR_INIT(&fields[60]),
+  UPB_TABVALUE_PTR_INIT(&fields[19]),
+  UPB_TABVALUE_PTR_INIT(&fields[24]),
+  UPB_TABVALUE_PTR_INIT(&fields[22]),
+  UPB_TABVALUE_PTR_INIT(&fields[68]),
+  UPB_TABVALUE_PTR_INIT(&fields[65]),
+  UPB_TABVALUE_PTR_INIT(&fields[83]),
+  UPB_TABVALUE_PTR_INIT(&fields[82]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[89]),
+  UPB_TABVALUE_PTR_INIT(&fields[18]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[88]),
+  UPB_TABVALUE_PTR_INIT(&fields[17]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[49]),
+  UPB_TABVALUE_PTR_INIT(&fields[102]),
+  UPB_TABVALUE_PTR_INIT(&fields[74]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[1]),
+  UPB_TABVALUE_PTR_INIT(&fields[13]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[53]),
+  UPB_TABVALUE_PTR_INIT(&fields[62]),
+  UPB_TABVALUE_PTR_INIT(&fields[73]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[15]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[55]),
+  UPB_TABVALUE_PTR_INIT(&fields[21]),
+  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[40]),
+  UPB_TABVALUE_PTR_INIT(&fields[93]),
+  UPB_TABVALUE_PTR_INIT(&fields[94]),
+  UPB_TABVALUE_PTR_INIT(&fields[7]),
+  UPB_TABVALUE_PTR_INIT(&fields[71]),
+  UPB_TABVALUE_PTR_INIT(&fields[66]),
+  UPB_TABVALUE_PTR_INIT(&fields[38]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[6]),
+  UPB_TABVALUE_PTR_INIT(&fields[77]),
+  UPB_TABVALUE_PTR_INIT(&fields[10]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[41]),
+  UPB_TABVALUE_PTR_INIT(&fields[39]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[103]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[54]),
+  UPB_TABVALUE_PTR_INIT(&fields[76]),
+  UPB_TABVALUE_PTR_INIT(&fields[8]),
+  UPB_TABVALUE_PTR_INIT(&fields[47]),
+  UPB_TABVALUE_PTR_INIT(&fields[20]),
+  UPB_TABVALUE_PTR_INIT(&fields[85]),
+  UPB_TABVALUE_PTR_INIT(&fields[23]),
+  UPB_TABVALUE_PTR_INIT(&fields[69]),
+  UPB_TABVALUE_PTR_INIT(&fields[86]),
+  UPB_TABVALUE_PTR_INIT(&fields[80]),
+  UPB_TABVALUE_PTR_INIT(&fields[104]),
+  UPB_TABVALUE_PTR_INIT(&fields[91]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[26]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[35]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[34]),
+  UPB_TABVALUE_PTR_INIT(&fields[67]),
+  UPB_TABVALUE_PTR_INIT(&fields[33]),
+  UPB_TABVALUE_PTR_INIT(&fields[27]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[3]),
+  UPB_TABVALUE_PTR_INIT(&fields[32]),
+  UPB_TABVALUE_PTR_INIT(&fields[81]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[31]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[12]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[36]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[2]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[64]),
+  UPB_TABVALUE_PTR_INIT(&fields[5]),
+  UPB_TABVALUE_PTR_INIT(&fields[37]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[46]),
+  UPB_TABVALUE_PTR_INIT(&fields[61]),
+  UPB_TABVALUE_PTR_INIT(&fields[9]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[45]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[56]),
+  UPB_TABVALUE_PTR_INIT(&fields[29]),
+  UPB_TABVALUE_PTR_INIT(&fields[75]),
+  UPB_TABVALUE_PTR_INIT(&fields[70]),
+  UPB_TABVALUE_PTR_INIT(&fields[4]),
+  UPB_TABVALUE_PTR_INIT(&fields[84]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[57]),
+  UPB_TABVALUE_PTR_INIT(&fields[48]),
+  UPB_TABVALUE_PTR_INIT(&fields[72]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[44]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[78]),
+  UPB_TABVALUE_PTR_INIT(&fields[87]),
+  UPB_TABVALUE_PTR_INIT(&fields[42]),
+  UPB_TABVALUE_PTR_INIT(&fields[92]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[43]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[51]),
+  UPB_TABVALUE_PTR_INIT(&fields[28]),
+  UPB_TABVALUE_PTR_INIT(&fields[79]),
+  UPB_TABVALUE_PTR_INIT(&fields[59]),
+  UPB_TABVALUE_PTR_INIT(&fields[16]),
+  UPB_TABVALUE_PTR_INIT(&fields[90]),
+  UPB_TABVALUE_PTR_INIT(&fields[0]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[58]),
+  UPB_TABVALUE_PTR_INIT(&fields[30]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"),
+  UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"),
+  UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"),
+  UPB_TABVALUE_PTR_INIT("TYPE_INT64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_UINT64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_INT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_BOOL"),
+  UPB_TABVALUE_PTR_INIT("TYPE_STRING"),
+  UPB_TABVALUE_PTR_INIT("TYPE_GROUP"),
+  UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"),
+  UPB_TABVALUE_PTR_INIT("TYPE_BYTES"),
+  UPB_TABVALUE_PTR_INIT("TYPE_UINT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_ENUM"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SINT32"),
+  UPB_TABVALUE_PTR_INIT("TYPE_SINT64"),
+  UPB_TABVALUE_PTR_INIT("STRING"),
+  UPB_TABVALUE_PTR_INIT("CORD"),
+  UPB_TABVALUE_PTR_INIT("STRING_PIECE"),
+  UPB_TABVALUE_PTR_INIT("JS_NORMAL"),
+  UPB_TABVALUE_PTR_INIT("JS_STRING"),
+  UPB_TABVALUE_PTR_INIT("JS_NUMBER"),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT("SPEED"),
+  UPB_TABVALUE_PTR_INIT("CODE_SIZE"),
+  UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"),
+};
+
+#ifdef UPB_DEBUG_REFS
+static upb_inttable reftables[264] = {
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+};
+#endif
+
+static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {
+  upb_msgdef_ref(m, owner);
+  return m;
+}
+
+static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {
+  upb_enumdef_ref(e, owner);
+  return e;
+}
+
+/* Public API. */
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); }
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); }
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); }
+const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); }
+const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); }
+const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); }
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); }
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); }
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); }
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); }
+
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); }
+/*
+** XXX: The routines in this file that consume a string do not currently
+** support having the string span buffers.  In the future, as upb_sink and
+** its buffering/sharing functionality evolve there should be an easy and
+** idiomatic way of correctly handling this case.  For now, we accept this
+** limitation since we currently only parse descriptors from single strings.
+*/
+
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Compares a NULL-terminated string with a non-NULL-terminated string. */
+static bool upb_streq(const char *str, const char *buf, size_t n) {
+  return strlen(str) == n && memcmp(str, buf, n) == 0;
+}
+
+/* We keep a stack of all the messages scopes we are currently in, as well as
+ * the top-level file scope.  This is necessary to correctly qualify the
+ * definitions that are contained inside.  "name" tracks the name of the
+ * message or package (a bare name -- not qualified by any enclosing scopes). */
+typedef struct {
+  char *name;
+  /* Index of the first def that is under this scope.  For msgdefs, the
+   * msgdef itself is at start-1. */
+  int start;
+} upb_descreader_frame;
+
+/* The maximum number of nested declarations that are allowed, ie.
+ * message Foo {
+ *   message Bar {
+ *     message Baz {
+ *     }
+ *   }
+ * }
+ *
+ * This is a resource limit that affects how big our runtime stack can grow.
+ * TODO: make this a runtime-settable property of the Reader instance. */
+#define UPB_MAX_MESSAGE_NESTING 64
+
+struct upb_descreader {
+  upb_sink sink;
+  upb_inttable files;
+  upb_filedef *file;  /* The last file in files. */
+  upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
+  int stack_len;
+
+  uint32_t number;
+  char *name;
+  bool saw_number;
+  bool saw_name;
+
+  char *default_string;
+
+  upb_fielddef *f;
+};
+
+static char *upb_strndup(const char *buf, size_t n) {
+  char *ret = upb_gmalloc(n + 1);
+  if (!ret) return NULL;
+  memcpy(ret, buf, n);
+  ret[n] = '\0';
+  return ret;
+}
+
+/* Returns a newly allocated string that joins input strings together, for
+ * example:
+ *   join("Foo.Bar", "Baz") -> "Foo.Bar.Baz"
+ *   join("", "Baz") -> "Baz"
+ * Caller owns a ref on the returned string. */
+static char *upb_join(const char *base, const char *name) {
+  if (!base || strlen(base) == 0) {
+    return upb_gstrdup(name);
+  } else {
+    char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2);
+    if (!ret) {
+      return NULL;
+    }
+    ret[0] = '\0';
+    strcat(ret, base);
+    strcat(ret, ".");
+    strcat(ret, name);
+    return ret;
+  }
+}
+
+/* Qualify the defname for all defs starting with offset "start" with "str". */
+static bool upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) {
+  size_t i;
+  for (i = start; i < upb_filedef_defcount(f); i++) {
+    upb_def *def = upb_filedef_mutabledef(f, i);
+    char *name = upb_join(str, upb_def_fullname(def));
+    if (!name) {
+      /* Need better logic here; at this point we've qualified some names but
+       * not others. */
+      return false;
+    }
+    upb_def_setfullname(def, name, NULL);
+    upb_gfree(name);
+  }
+  return true;
+}
+
+
+/* upb_descreader  ************************************************************/
+
+static upb_msgdef *upb_descreader_top(upb_descreader *r) {
+  int index;
+  assert(r->stack_len > 1);
+  index = r->stack[r->stack_len-1].start - 1;
+  assert(index >= 0);
+  return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index));
+}
+
+static upb_def *upb_descreader_last(upb_descreader *r) {
+  return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1);
+}
+
+/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two
+ * entities that have names and can contain sub-definitions. */
+void upb_descreader_startcontainer(upb_descreader *r) {
+  upb_descreader_frame *f = &r->stack[r->stack_len++];
+  f->start = upb_filedef_defcount(r->file);
+  f->name = NULL;
+}
+
+bool upb_descreader_endcontainer(upb_descreader *r) {
+  upb_descreader_frame *f = &r->stack[--r->stack_len];
+  if (!upb_descreader_qualify(r->file, f->name, f->start)) {
+    return false;
+  }
+  upb_gfree(f->name);
+  f->name = NULL;
+  return true;
+}
+
+void upb_descreader_setscopename(upb_descreader *r, char *str) {
+  upb_descreader_frame *f = &r->stack[r->stack_len-1];
+  upb_gfree(f->name);
+  f->name = str;
+}
+
+/** Handlers for google.protobuf.FileDescriptorSet. ***************************/
+
+static void *fileset_startfile(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->file = upb_filedef_new(&r->files);
+  upb_inttable_push(&r->files, upb_value_ptr(r->file));
+  return r;
+}
+
+/** Handlers for google.protobuf.FileDescriptorProto. *************************/
+
+static bool file_start(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  upb_descreader_startcontainer(r);
+  return true;
+}
+
+static bool file_end(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(status);
+  return upb_descreader_endcontainer(r);
+}
+
+static size_t file_onname(void *closure, const void *hd, const char *buf,
+                          size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  name = upb_strndup(buf, n);
+  /* XXX: see comment at the top of the file. */
+  ok = upb_filedef_setname(r->file, name, NULL);
+  upb_gfree(name);
+  UPB_ASSERT_VAR(ok, ok);
+  return n;
+}
+
+static size_t file_onpackage(void *closure, const void *hd, const char *buf,
+                             size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *package;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  package = upb_strndup(buf, n);
+  /* XXX: see comment at the top of the file. */
+  upb_descreader_setscopename(r, package);
+  ok = upb_filedef_setpackage(r->file, package, NULL);
+  UPB_ASSERT_VAR(ok, ok);
+  return n;
+}
+
+static size_t file_onsyntax(void *closure, const void *hd, const char *buf,
+                            size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  if (upb_streq("proto2", buf, n)) {
+    ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL);
+  } else if (upb_streq("proto3", buf, n)) {
+    ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL);
+  } else {
+    ok = false;
+  }
+
+  UPB_ASSERT_VAR(ok, ok);
+  return n;
+}
+
+static void *file_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_msgdef_new(&m);
+  bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
+  UPB_UNUSED(hd);
+  UPB_ASSERT_VAR(ok, ok);
+  return r;
+}
+
+static void *file_startenum(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_enumdef *e = upb_enumdef_new(&e);
+  bool ok = upb_filedef_addenum(r->file, e, &e, NULL);
+  UPB_UNUSED(hd);
+  UPB_ASSERT_VAR(ok, ok);
+  return r;
+}
+
+static void *file_startext(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  bool ok;
+  r->f = upb_fielddef_new(r);
+  ok = upb_filedef_addext(r->file, r->f, r, NULL);
+  UPB_UNUSED(hd);
+  UPB_ASSERT_VAR(ok, ok);
+  return r;
+}
+
+/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/
+
+static bool enumval_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->saw_number = false;
+  r->saw_name = false;
+  return true;
+}
+
+static size_t enumval_onname(void *closure, const void *hd, const char *buf,
+                             size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  upb_gfree(r->name);
+  r->name = upb_strndup(buf, n);
+  r->saw_name = true;
+  return n;
+}
+
+static bool enumval_onnumber(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  r->number = val;
+  r->saw_number = true;
+  return true;
+}
+
+static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_enumdef *e;
+  UPB_UNUSED(hd);
+
+  if(!r->saw_number || !r->saw_name) {
+    upb_status_seterrmsg(status, "Enum value missing name or number.");
+    return false;
+  }
+  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
+  upb_enumdef_addval(e, r->name, r->number, status);
+  upb_gfree(r->name);
+  r->name = NULL;
+  return true;
+}
+
+/** Handlers for google.protobuf.EnumDescriptorProto. *************************/
+
+static bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_enumdef *e;
+  UPB_UNUSED(hd);
+
+  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
+  if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
+    upb_status_seterrmsg(status, "Enum had no name.");
+    return false;
+  }
+  if (upb_enumdef_numvals(e) == 0) {
+    upb_status_seterrmsg(status, "Enum had no values.");
+    return false;
+  }
+  return true;
+}
+
+static size_t enum_onname(void *closure, const void *hd, const char *buf,
+                          size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *fullname = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  /* XXX: see comment at the top of the file. */
+  upb_def_setfullname(upb_descreader_last(r), fullname, NULL);
+  upb_gfree(fullname);
+  return n;
+}
+
+/** Handlers for google.protobuf.FieldDescriptorProto *************************/
+
+static bool field_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  assert(r->f);
+  upb_gfree(r->default_string);
+  r->default_string = NULL;
+
+  /* fielddefs default to packed, but descriptors default to non-packed. */
+  upb_fielddef_setpacked(r->f, false);
+  return true;
+}
+
+/* Converts the default value in string "str" into "d".  Passes a ref on str.
+ * Returns true on success. */
+static bool parse_default(char *str, upb_fielddef *f) {
+  bool success = true;
+  char *end;
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32: {
+      long val = strtol(str, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultint32(f, val);
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      /* XXX: Need to write our own strtoll, since it's not available in c89. */
+      long long val = strtol(str, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultint64(f, val);
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultuint32(f, val);
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      /* XXX: Need to write our own strtoull, since it's not available in c89. */
+      unsigned long long val = strtoul(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultuint64(f, val);
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultdouble(f, val);
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      /* XXX: Need to write our own strtof, since it's not available in c89. */
+      float val = strtod(str, &end);
+      if (errno == ERANGE || *end)
+        success = false;
+      else
+        upb_fielddef_setdefaultfloat(f, val);
+      break;
+    }
+    case UPB_TYPE_BOOL: {
+      if (strcmp(str, "false") == 0)
+        upb_fielddef_setdefaultbool(f, false);
+      else if (strcmp(str, "true") == 0)
+        upb_fielddef_setdefaultbool(f, true);
+      else
+        success = false;
+      break;
+    }
+    default: abort();
+  }
+  return success;
+}
+
+static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_fielddef *f = r->f;
+  UPB_UNUSED(hd);
+
+  /* TODO: verify that all required fields were present. */
+  assert(upb_fielddef_number(f) != 0);
+  assert(upb_fielddef_name(f) != NULL);
+  assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
+
+  if (r->default_string) {
+    if (upb_fielddef_issubmsg(f)) {
+      upb_status_seterrmsg(status, "Submessages cannot have defaults.");
+      return false;
+    }
+    if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
+      upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
+    } else {
+      if (r->default_string && !parse_default(r->default_string, f)) {
+        /* We don't worry too much about giving a great error message since the
+         * compiler should have ensured this was correct. */
+        upb_status_seterrmsg(status, "Error converting default value.");
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+static bool field_onlazy(void *closure, const void *hd, bool val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setlazy(r->f, val);
+  return true;
+}
+
+static bool field_onpacked(void *closure, const void *hd, bool val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setpacked(r->f, val);
+  return true;
+}
+
+static bool field_ontype(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setdescriptortype(r->f, val);
+  return true;
+}
+
+static bool field_onlabel(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_fielddef_setlabel(r->f, val);
+  return true;
+}
+
+static bool field_onnumber(void *closure, const void *hd, int32_t val) {
+  upb_descreader *r = closure;
+  bool ok;
+  UPB_UNUSED(hd);
+
+  ok = upb_fielddef_setnumber(r->f, val, NULL);
+  UPB_ASSERT_VAR(ok, ok);
+  return true;
+}
+
+static size_t field_onname(void *closure, const void *hd, const char *buf,
+                           size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setname(r->f, name, NULL);
+  upb_gfree(name);
+  return n;
+}
+
+static size_t field_ontypename(void *closure, const void *hd, const char *buf,
+                               size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setsubdefname(r->f, name, NULL);
+  upb_gfree(name);
+  return n;
+}
+
+static size_t field_onextendee(void *closure, const void *hd, const char *buf,
+                               size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* XXX: see comment at the top of the file. */
+  upb_fielddef_setcontainingtypename(r->f, name, NULL);
+  upb_gfree(name);
+  return n;
+}
+
+static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
+                                 size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  /* Have to convert from string to the correct type, but we might not know the
+   * type yet, so we save it as a string until the end of the field.
+   * XXX: see comment at the top of the file. */
+  upb_gfree(r->default_string);
+  r->default_string = upb_strndup(buf, n);
+  return n;
+}
+
+/** Handlers for google.protobuf.DescriptorProto ******************************/
+
+static bool msg_start(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  UPB_UNUSED(hd);
+
+  upb_descreader_startcontainer(r);
+  return true;
+}
+
+static bool msg_end(void *closure, const void *hd, upb_status *status) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  UPB_UNUSED(hd);
+
+  if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) {
+    upb_status_seterrmsg(status, "Encountered message with no name.");
+    return false;
+  }
+  return upb_descreader_endcontainer(r);
+}
+
+static size_t msg_name(void *closure, const void *hd, const char *buf,
+                       size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  /* XXX: see comment at the top of the file. */
+  char *name = upb_strndup(buf, n);
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL);
+  upb_descreader_setscopename(r, name);  /* Passes ownership of name. */
+  return n;
+}
+
+static void *msg_startmsg(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_msgdef_new(&m);
+  bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
+  UPB_UNUSED(hd);
+  UPB_ASSERT_VAR(ok, ok);
+  return r;
+}
+
+static void *msg_startext(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_fielddef *f = upb_fielddef_new(&f);
+  bool ok = upb_filedef_addext(r->file, f, &f, NULL);
+  UPB_UNUSED(hd);
+  UPB_ASSERT_VAR(ok, ok);
+  return r;
+}
+
+static void *msg_startfield(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  r->f = upb_fielddef_new(&r->f);
+  /* We can't add the new field to the message until its name/number are
+   * filled in. */
+  UPB_UNUSED(hd);
+  return r;
+}
+
+static bool msg_endfield(void *closure, const void *hd) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  UPB_UNUSED(hd);
+
+  upb_msgdef_addfield(m, r->f, &r->f, NULL);
+  r->f = NULL;
+  return true;
+}
+
+static bool msg_onmapentry(void *closure, const void *hd, bool mapentry) {
+  upb_descreader *r = closure;
+  upb_msgdef *m = upb_descreader_top(r);
+  UPB_UNUSED(hd);
+
+  upb_msgdef_setmapentry(m, mapentry);
+  r->f = NULL;
+  return true;
+}
+
+
+
+/** Code to register handlers *************************************************/
+
+#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m)
+
+static void reghandlers(const void *closure, upb_handlers *h) {
+  const upb_msgdef *m = upb_handlers_msgdef(h);
+  UPB_UNUSED(closure);
+
+  if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) {
+    upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file),
+                                &fileset_startfile, NULL);
+  } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) {
+    upb_handlers_setstartmsg(h, &msg_start, NULL);
+    upb_handlers_setendmsg(h, &msg_end, NULL);
+    upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL);
+    upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext,
+                                NULL);
+    upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type),
+                                &msg_startmsg, NULL);
+    upb_handlers_setstartsubmsg(h, F(DescriptorProto, field),
+                                &msg_startfield, NULL);
+    upb_handlers_setendsubmsg(h, F(DescriptorProto, field),
+                              &msg_endfield, NULL);
+    upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type),
+                                &file_startenum, NULL);
+  } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) {
+    upb_handlers_setstartmsg(h, &file_start, NULL);
+    upb_handlers_setendmsg(h, &file_end, NULL);
+    upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname,
+                           NULL);
+    upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage,
+                           NULL);
+    upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax,
+                           NULL);
+    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type),
+                                &file_startmsg, NULL);
+    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type),
+                                &file_startenum, NULL);
+    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension),
+                                &file_startext, NULL);
+  } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) {
+    upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
+    upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
+    upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL);
+    upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber,
+                          NULL);
+  } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) {
+    upb_handlers_setendmsg(h, &enum_endmsg, NULL);
+    upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL);
+  } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) {
+    upb_handlers_setstartmsg(h, &field_startmsg, NULL);
+    upb_handlers_setendmsg(h, &field_endmsg, NULL);
+    upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype,
+                          NULL);
+    upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel,
+                          NULL);
+    upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber,
+                          NULL);
+    upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname,
+                           NULL);
+    upb_handlers_setstring(h, F(FieldDescriptorProto, type_name),
+                           &field_ontypename, NULL);
+    upb_handlers_setstring(h, F(FieldDescriptorProto, extendee),
+                           &field_onextendee, NULL);
+    upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
+                           &field_ondefaultval, NULL);
+  } else if (upbdefs_google_protobuf_FieldOptions_is(m)) {
+    upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
+    upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
+  } else if (upbdefs_google_protobuf_MessageOptions_is(m)) {
+    upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL);
+  }
+
+  assert(upb_ok(upb_handlers_status(h)));
+}
+
+#undef F
+
+void descreader_cleanup(void *_r) {
+  upb_descreader *r = _r;
+  size_t i;
+
+  for (i = 0; i < upb_descreader_filecount(r); i++) {
+    upb_filedef_unref(upb_descreader_file(r, i), &r->files);
+  }
+
+  upb_gfree(r->name);
+  upb_inttable_uninit(&r->files);
+  upb_gfree(r->default_string);
+  while (r->stack_len > 0) {
+    upb_descreader_frame *f = &r->stack[--r->stack_len];
+    upb_gfree(f->name);
+  }
+}
+
+
+/* Public API  ****************************************************************/
+
+upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
+  upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader));
+  if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) {
+    return NULL;
+  }
+
+  upb_inttable_init(&r->files, UPB_CTYPE_PTR);
+  upb_sink_reset(upb_descreader_input(r), h, r);
+  r->stack_len = 0;
+  r->name = NULL;
+  r->default_string = NULL;
+
+  return r;
+}
+
+size_t upb_descreader_filecount(const upb_descreader *r) {
+  return upb_inttable_count(&r->files);
+}
+
+upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) {
+  upb_value v;
+  if (upb_inttable_lookup(&r->files, i, &v)) {
+    return upb_value_getptr(v);
+  } else {
+    return NULL;
+  }
+}
+
+upb_sink *upb_descreader_input(upb_descreader *r) {
+  return &r->sink;
+}
+
+const upb_handlers *upb_descreader_newhandlers(const void *owner) {
+  const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
+  const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL);
+  upb_msgdef_unref(m, &m);
+  return h;
+}
+/*
+** protobuf decoder bytecode compiler
+**
+** Code to compile a upb::Handlers into bytecode for decoding a protobuf
+** according to that specific schema and destination handlers.
+**
+** Compiling to bytecode is always the first step.  If we are using the
+** interpreted decoder we leave it as bytecode and interpret that.  If we are
+** using a JIT decoder we use a code generator to turn the bytecode into native
+** code, LLVM IR, etc.
+**
+** Bytecode definition is in decoder.int.h.
+*/
+
+#include <stdarg.h>
+
+#ifdef UPB_DUMP_BYTECODE
+#include <stdio.h>
+#endif
+
+#define MAXLABEL 5
+#define EMPTYLABEL -1
+
+/* mgroup *********************************************************************/
+
+static void freegroup(upb_refcounted *r) {
+  mgroup *g = (mgroup*)r;
+  upb_inttable_uninit(&g->methods);
+#ifdef UPB_USE_JIT_X64
+  upb_pbdecoder_freejit(g);
+#endif
+  upb_gfree(g->bytecode);
+  upb_gfree(g);
+}
+
+static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
+                       void *closure) {
+  const mgroup *g = (const mgroup*)r;
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &g->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
+    visit(r, upb_pbdecodermethod_upcast(method), closure);
+  }
+}
+
+mgroup *newgroup(const void *owner) {
+  mgroup *g = upb_gmalloc(sizeof(*g));
+  static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup};
+  upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner);
+  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
+  g->bytecode = NULL;
+  g->bytecode_end = NULL;
+  return g;
+}
+
+
+/* upb_pbdecodermethod ********************************************************/
+
+static void freemethod(upb_refcounted *r) {
+  upb_pbdecodermethod *method = (upb_pbdecodermethod*)r;
+
+  if (method->dest_handlers_) {
+    upb_handlers_unref(method->dest_handlers_, method);
+  }
+
+  upb_inttable_uninit(&method->dispatch);
+  upb_gfree(method);
+}
+
+static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
+                        void *closure) {
+  const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r;
+  visit(r, m->group, closure);
+}
+
+static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
+                                      mgroup *group) {
+  static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod};
+  upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
+  upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret);
+  upb_byteshandler_init(&ret->input_handler_);
+
+  /* The method references the group and vice-versa, in a circular reference. */
+  upb_ref2(ret, group);
+  upb_ref2(group, ret);
+  upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret));
+  upb_pbdecodermethod_unref(ret, &ret);
+
+  ret->group = mgroup_upcast_mutable(group);
+  ret->dest_handlers_ = dest_handlers;
+  ret->is_native_ = false;  /* If we JIT, it will update this later. */
+  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
+
+  if (ret->dest_handlers_) {
+    upb_handlers_ref(ret->dest_handlers_, ret);
+  }
+  return ret;
+}
+
+const upb_handlers *upb_pbdecodermethod_desthandlers(
+    const upb_pbdecodermethod *m) {
+  return m->dest_handlers_;
+}
+
+const upb_byteshandler *upb_pbdecodermethod_inputhandler(
+    const upb_pbdecodermethod *m) {
+  return &m->input_handler_;
+}
+
+bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
+  return m->is_native_;
+}
+
+const upb_pbdecodermethod *upb_pbdecodermethod_new(
+    const upb_pbdecodermethodopts *opts, const void *owner) {
+  const upb_pbdecodermethod *ret;
+  upb_pbcodecache cache;
+
+  upb_pbcodecache_init(&cache);
+  ret = upb_pbcodecache_getdecodermethod(&cache, opts);
+  upb_pbdecodermethod_ref(ret, owner);
+  upb_pbcodecache_uninit(&cache);
+  return ret;
+}
+
+
+/* bytecode compiler **********************************************************/
+
+/* Data used only at compilation time. */
+typedef struct {
+  mgroup *group;
+
+  uint32_t *pc;
+  int fwd_labels[MAXLABEL];
+  int back_labels[MAXLABEL];
+
+  /* For fields marked "lazy", parse them lazily or eagerly? */
+  bool lazy;
+} compiler;
+
+static compiler *newcompiler(mgroup *group, bool lazy) {
+  compiler *ret = upb_gmalloc(sizeof(*ret));
+  int i;
+
+  ret->group = group;
+  ret->lazy = lazy;
+  for (i = 0; i < MAXLABEL; i++) {
+    ret->fwd_labels[i] = EMPTYLABEL;
+    ret->back_labels[i] = EMPTYLABEL;
+  }
+  return ret;
+}
+
+static void freecompiler(compiler *c) {
+  upb_gfree(c);
+}
+
+const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
+
+/* How many words an instruction is. */
+static int instruction_len(uint32_t instr) {
+  switch (getop(instr)) {
+    case OP_SETDISPATCH: return 1 + ptr_words;
+    case OP_TAGN: return 3;
+    case OP_SETBIGGROUPNUM: return 2;
+    default: return 1;
+  }
+}
+
+bool op_has_longofs(int32_t instruction) {
+  switch (getop(instruction)) {
+    case OP_CALL:
+    case OP_BRANCH:
+    case OP_CHECKDELIM:
+      return true;
+    /* The "tag" instructions only have 8 bytes available for the jump target,
+     * but that is ok because these opcodes only require short jumps. */
+    case OP_TAG1:
+    case OP_TAG2:
+    case OP_TAGN:
+      return false;
+    default:
+      assert(false);
+      return false;
+  }
+}
+
+static int32_t getofs(uint32_t instruction) {
+  if (op_has_longofs(instruction)) {
+    return (int32_t)instruction >> 8;
+  } else {
+    return (int8_t)(instruction >> 8);
+  }
+}
+
+static void setofs(uint32_t *instruction, int32_t ofs) {
+  if (op_has_longofs(*instruction)) {
+    *instruction = getop(*instruction) | ofs << 8;
+  } else {
+    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
+  }
+  assert(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
+}
+
+static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
+
+/* Defines a local label at the current PC location.  All previous forward
+ * references are updated to point to this location.  The location is noted
+ * for any future backward references. */
+static void label(compiler *c, unsigned int label) {
+  int val;
+  uint32_t *codep;
+
+  assert(label < MAXLABEL);
+  val = c->fwd_labels[label];
+  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
+  while (codep) {
+    int ofs = getofs(*codep);
+    setofs(codep, c->pc - codep - instruction_len(*codep));
+    codep = ofs ? codep + ofs : NULL;
+  }
+  c->fwd_labels[label] = EMPTYLABEL;
+  c->back_labels[label] = pcofs(c);
+}
+
+/* Creates a reference to a numbered label; either a forward reference
+ * (positive arg) or backward reference (negative arg).  For forward references
+ * the value returned now is actually a "next" pointer into a linked list of all
+ * instructions that use this label and will be patched later when the label is
+ * defined with label().
+ *
+ * The returned value is the offset that should be written into the instruction.
+ */
+static int32_t labelref(compiler *c, int label) {
+  assert(label < MAXLABEL);
+  if (label == LABEL_DISPATCH) {
+    /* No resolving required. */
+    return 0;
+  } else if (label < 0) {
+    /* Backward local label.  Relative to the next instruction. */
+    uint32_t from = (c->pc + 1) - c->group->bytecode;
+    return c->back_labels[-label] - from;
+  } else {
+    /* Forward local label: prepend to (possibly-empty) linked list. */
+    int *lptr = &c->fwd_labels[label];
+    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
+    *lptr = pcofs(c);
+    return ret;
+  }
+}
+
+static void put32(compiler *c, uint32_t v) {
+  mgroup *g = c->group;
+  if (c->pc == g->bytecode_end) {
+    int ofs = pcofs(c);
+    size_t oldsize = g->bytecode_end - g->bytecode;
+    size_t newsize = UPB_MAX(oldsize * 2, 64);
+    /* TODO(haberman): handle OOM. */
+    g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
+                                            newsize * sizeof(uint32_t));
+    g->bytecode_end = g->bytecode + newsize;
+    c->pc = g->bytecode + ofs;
+  }
+  *c->pc++ = v;
+}
+
+static void putop(compiler *c, opcode op, ...) {
+  va_list ap;
+  va_start(ap, op);
+
+  switch (op) {
+    case OP_SETDISPATCH: {
+      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
+      put32(c, OP_SETDISPATCH);
+      put32(c, ptr);
+      if (sizeof(uintptr_t) > sizeof(uint32_t))
+        put32(c, (uint64_t)ptr >> 32);
+      break;
+    }
+    case OP_STARTMSG:
+    case OP_ENDMSG:
+    case OP_PUSHLENDELIM:
+    case OP_POP:
+    case OP_SETDELIM:
+    case OP_HALT:
+    case OP_RET:
+    case OP_DISPATCH:
+      put32(c, op);
+      break;
+    case OP_PARSE_DOUBLE:
+    case OP_PARSE_FLOAT:
+    case OP_PARSE_INT64:
+    case OP_PARSE_UINT64:
+    case OP_PARSE_INT32:
+    case OP_PARSE_FIXED64:
+    case OP_PARSE_FIXED32:
+    case OP_PARSE_BOOL:
+    case OP_PARSE_UINT32:
+    case OP_PARSE_SFIXED32:
+    case OP_PARSE_SFIXED64:
+    case OP_PARSE_SINT32:
+    case OP_PARSE_SINT64:
+    case OP_STARTSEQ:
+    case OP_ENDSEQ:
+    case OP_STARTSUBMSG:
+    case OP_ENDSUBMSG:
+    case OP_STARTSTR:
+    case OP_STRING:
+    case OP_ENDSTR:
+    case OP_PUSHTAGDELIM:
+      put32(c, op | va_arg(ap, upb_selector_t) << 8);
+      break;
+    case OP_SETBIGGROUPNUM:
+      put32(c, op);
+      put32(c, va_arg(ap, int));
+      break;
+    case OP_CALL: {
+      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
+      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
+      break;
+    }
+    case OP_CHECKDELIM:
+    case OP_BRANCH: {
+      uint32_t instruction = op;
+      int label = va_arg(ap, int);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      break;
+    }
+    case OP_TAG1:
+    case OP_TAG2: {
+      int label = va_arg(ap, int);
+      uint64_t tag = va_arg(ap, uint64_t);
+      uint32_t instruction = op | (tag << 16);
+      assert(tag <= 0xffff);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      break;
+    }
+    case OP_TAGN: {
+      int label = va_arg(ap, int);
+      uint64_t tag = va_arg(ap, uint64_t);
+      uint32_t instruction = op | (upb_value_size(tag) << 16);
+      setofs(&instruction, labelref(c, label));
+      put32(c, instruction);
+      put32(c, tag);
+      put32(c, tag >> 32);
+      break;
+    }
+  }
+
+  va_end(ap);
+}
+
+#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE)
+
+const char *upb_pbdecoder_getopname(unsigned int op) {
+#define QUOTE(x) #x
+#define EXPAND_AND_QUOTE(x) QUOTE(x)
+#define OPNAME(x) OP_##x
+#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
+#define T(x) OP(PARSE_##x)
+  /* Keep in sync with list in decoder.int.h. */
+  switch ((opcode)op) {
+    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
+    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
+    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
+    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
+    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
+    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
+    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
+  }
+  return "<unknown op>";
+#undef OP
+#undef T
+}
+
+#endif
+
+#ifdef UPB_DUMP_BYTECODE
+
+static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
+
+  uint32_t *begin = p;
+
+  while (p < end) {
+    fprintf(f, "%p  %8tx", p, p - begin);
+    uint32_t instr = *p++;
+    uint8_t op = getop(instr);
+    fprintf(f, " %s", upb_pbdecoder_getopname(op));
+    switch ((opcode)op) {
+      case OP_SETDISPATCH: {
+        const upb_inttable *dispatch;
+        memcpy(&dispatch, p, sizeof(void*));
+        p += ptr_words;
+        const upb_pbdecodermethod *method =
+            (void *)((char *)dispatch -
+                     offsetof(upb_pbdecodermethod, dispatch));
+        fprintf(f, " %s", upb_msgdef_fullname(
+                              upb_handlers_msgdef(method->dest_handlers_)));
+        break;
+      }
+      case OP_DISPATCH:
+      case OP_STARTMSG:
+      case OP_ENDMSG:
+      case OP_PUSHLENDELIM:
+      case OP_POP:
+      case OP_SETDELIM:
+      case OP_HALT:
+      case OP_RET:
+        break;
+      case OP_PARSE_DOUBLE:
+      case OP_PARSE_FLOAT:
+      case OP_PARSE_INT64:
+      case OP_PARSE_UINT64:
+      case OP_PARSE_INT32:
+      case OP_PARSE_FIXED64:
+      case OP_PARSE_FIXED32:
+      case OP_PARSE_BOOL:
+      case OP_PARSE_UINT32:
+      case OP_PARSE_SFIXED32:
+      case OP_PARSE_SFIXED64:
+      case OP_PARSE_SINT32:
+      case OP_PARSE_SINT64:
+      case OP_STARTSEQ:
+      case OP_ENDSEQ:
+      case OP_STARTSUBMSG:
+      case OP_ENDSUBMSG:
+      case OP_STARTSTR:
+      case OP_STRING:
+      case OP_ENDSTR:
+      case OP_PUSHTAGDELIM:
+        fprintf(f, " %d", instr >> 8);
+        break;
+      case OP_SETBIGGROUPNUM:
+        fprintf(f, " %d", *p++);
+        break;
+      case OP_CHECKDELIM:
+      case OP_CALL:
+      case OP_BRANCH:
+        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        break;
+      case OP_TAG1:
+      case OP_TAG2: {
+        fprintf(f, " tag:0x%x", instr >> 16);
+        if (getofs(instr)) {
+          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        }
+        break;
+      }
+      case OP_TAGN: {
+        uint64_t tag = *p++;
+        tag |= (uint64_t)*p++ << 32;
+        fprintf(f, " tag:0x%llx", (long long)tag);
+        fprintf(f, " n:%d", instr >> 16);
+        if (getofs(instr)) {
+          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
+        }
+        break;
+      }
+    }
+    fputs("\n", f);
+  }
+}
+
+#endif
+
+static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
+  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
+  uint64_t encoded_tag = upb_vencode32(tag);
+  /* No tag should be greater than 5 bytes. */
+  assert(encoded_tag <= 0xffffffffff);
+  return encoded_tag;
+}
+
+static void putchecktag(compiler *c, const upb_fielddef *f,
+                        int wire_type, int dest) {
+  uint64_t tag = get_encoded_tag(f, wire_type);
+  switch (upb_value_size(tag)) {
+    case 1:
+      putop(c, OP_TAG1, dest, tag);
+      break;
+    case 2:
+      putop(c, OP_TAG2, dest, tag);
+      break;
+    default:
+      putop(c, OP_TAGN, dest, tag);
+      break;
+  }
+}
+
+static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
+  upb_selector_t selector;
+  bool ok = upb_handlers_getselector(f, type, &selector);
+  UPB_ASSERT_VAR(ok, ok);
+  return selector;
+}
+
+/* Takes an existing, primary dispatch table entry and repacks it with a
+ * different alternate wire type.  Called when we are inserting a secondary
+ * dispatch table entry for an alternate wire type. */
+static uint64_t repack(uint64_t dispatch, int new_wt2) {
+  uint64_t ofs;
+  uint8_t wt1;
+  uint8_t old_wt2;
+  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
+  assert(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
+  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
+}
+
+/* Marks the current bytecode position as the dispatch target for this message,
+ * field, and wire type. */
+static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
+                           const upb_fielddef *f, int wire_type) {
+  /* Offset is relative to msg base. */
+  uint64_t ofs = pcofs(c) - method->code_base.ofs;
+  uint32_t fn = upb_fielddef_number(f);
+  upb_inttable *d = &method->dispatch;
+  upb_value v;
+  if (upb_inttable_remove(d, fn, &v)) {
+    /* TODO: prioritize based on packed setting in .proto file. */
+    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
+    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
+    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
+  } else {
+    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
+    upb_inttable_insert(d, fn, upb_value_uint64(val));
+  }
+}
+
+static void putpush(compiler *c, const upb_fielddef *f) {
+  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
+    putop(c, OP_PUSHLENDELIM);
+  } else {
+    uint32_t fn = upb_fielddef_number(f);
+    if (fn >= 1 << 24) {
+      putop(c, OP_PUSHTAGDELIM, 0);
+      putop(c, OP_SETBIGGROUPNUM, fn);
+    } else {
+      putop(c, OP_PUSHTAGDELIM, fn);
+    }
+  }
+}
+
+static upb_pbdecodermethod *find_submethod(const compiler *c,
+                                           const upb_pbdecodermethod *method,
+                                           const upb_fielddef *f) {
+  const upb_handlers *sub =
+      upb_handlers_getsubhandlers(method->dest_handlers_, f);
+  upb_value v;
+  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
+             ? upb_value_getptr(v)
+             : NULL;
+}
+
+static void putsel(compiler *c, opcode op, upb_selector_t sel,
+                   const upb_handlers *h) {
+  if (upb_handlers_gethandler(h, sel)) {
+    putop(c, op, sel);
+  }
+}
+
+/* Puts an opcode to call a callback, but only if a callback actually exists for
+ * this field and handler type. */
+static void maybeput(compiler *c, opcode op, const upb_handlers *h,
+                     const upb_fielddef *f, upb_handlertype_t type) {
+  putsel(c, op, getsel(f, type), h);
+}
+
+static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
+  if (!upb_fielddef_lazy(f))
+    return false;
+
+  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) ||
+         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) ||
+         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+
+/* bytecode compiler code generation ******************************************/
+
+/* Symbolic names for our local labels. */
+#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
+#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
+#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
+#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
+
+/* Generates bytecode to parse a single non-lazy message field. */
+static void generate_msgfield(compiler *c, const upb_fielddef *f,
+                              upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
+  int wire_type;
+
+  if (!sub_m) {
+    /* Don't emit any code for this field at all; it will be parsed as an
+     * unknown field.
+     *
+     * TODO(haberman): we should change this to parse it as a string field
+     * instead.  It will probably be faster, but more importantly, once we
+     * start vending unknown fields, a field shouldn't be treated as unknown
+     * just because it doesn't have subhandlers registered. */
+    return;
+  }
+
+  label(c, LABEL_FIELD);
+
+  wire_type =
+      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
+          ? UPB_WIRE_TYPE_DELIMITED
+          : UPB_WIRE_TYPE_START_GROUP;
+
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
+   label(c, LABEL_LOOPSTART);
+    putpush(c, f);
+    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
+    putop(c, OP_CALL, sub_m);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
+    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
+      putop(c, OP_SETDELIM);
+    }
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putpush(c, f);
+    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
+    putop(c, OP_CALL, sub_m);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
+    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
+      putop(c, OP_SETDELIM);
+    }
+  }
+}
+
+/* Generates bytecode to parse a single string or lazy submessage field. */
+static void generate_delimfield(compiler *c, const upb_fielddef *f,
+                                upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+
+  label(c, LABEL_FIELD);
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
+   label(c, LABEL_LOOPSTART);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
+    /* Need to emit even if no handler to skip past the string. */
+    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
+    putop(c, OP_SETDELIM);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
+    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
+    putop(c, OP_POP);
+    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
+    putop(c, OP_SETDELIM);
+  }
+}
+
+/* Generates bytecode to parse a single primitive field. */
+static void generate_primitivefield(compiler *c, const upb_fielddef *f,
+                                    upb_pbdecodermethod *method) {
+  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
+  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
+  opcode parse_type;
+  upb_selector_t sel;
+  int wire_type;
+
+  label(c, LABEL_FIELD);
+
+  /* From a decoding perspective, ENUM is the same as INT32. */
+  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
+    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
+
+  parse_type = (opcode)descriptor_type;
+
+  /* TODO(haberman): generate packed or non-packed first depending on "packed"
+   * setting in the fielddef.  This will favor (in speed) whichever was
+   * specified. */
+
+  assert((int)parse_type >= 0 && parse_type <= OP_MAX);
+  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
+  if (upb_fielddef_isseq(f)) {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
+    putop(c, OP_PUSHLENDELIM);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
+   label(c, LABEL_LOOPSTART);
+    putop(c, parse_type, sel);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, OP_PUSHTAGDELIM, 0);
+    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
+   label(c, LABEL_LOOPSTART);
+    putop(c, parse_type, sel);
+    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
+    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
+    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
+   label(c, LABEL_LOOPBREAK);
+    putop(c, OP_POP);  /* Packed and non-packed join. */
+    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
+    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
+  } else {
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    putchecktag(c, f, wire_type, LABEL_DISPATCH);
+   dispatchtarget(c, method, f, wire_type);
+    putop(c, parse_type, sel);
+  }
+}
+
+/* Adds bytecode for parsing the given message to the given decoderplan,
+ * while adding all dispatch targets to this message's dispatch table. */
+static void compile_method(compiler *c, upb_pbdecodermethod *method) {
+  const upb_handlers *h;
+  const upb_msgdef *md;
+  uint32_t* start_pc;
+  upb_msg_field_iter i;
+  upb_value val;
+
+  assert(method);
+
+  /* Clear all entries in the dispatch table. */
+  upb_inttable_uninit(&method->dispatch);
+  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
+
+  h = upb_pbdecodermethod_desthandlers(method);
+  md = upb_handlers_msgdef(h);
+
+ method->code_base.ofs = pcofs(c);
+  putop(c, OP_SETDISPATCH, &method->dispatch);
+  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
+ label(c, LABEL_FIELD);
+  start_pc = c->pc;
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    upb_fieldtype_t type = upb_fielddef_type(f);
+
+    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
+      generate_msgfield(c, f, method);
+    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
+               type == UPB_TYPE_MESSAGE) {
+      generate_delimfield(c, f, method);
+    } else {
+      generate_primitivefield(c, f, method);
+    }
+  }
+
+  /* If there were no fields, or if no handlers were defined, we need to
+   * generate a non-empty loop body so that we can at least dispatch for unknown
+   * fields and check for the end of the message. */
+  if (c->pc == start_pc) {
+    /* Check for end-of-message. */
+    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
+    /* Unconditionally dispatch. */
+    putop(c, OP_DISPATCH, 0);
+  }
+
+  /* For now we just loop back to the last field of the message (or if none,
+   * the DISPATCH opcode for the message). */
+  putop(c, OP_BRANCH, -LABEL_FIELD);
+
+  /* Insert both a label and a dispatch table entry for this end-of-msg. */
+ label(c, LABEL_ENDMSG);
+  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
+  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
+
+  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
+  putop(c, OP_RET);
+
+  upb_inttable_compact(&method->dispatch);
+}
+
+/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
+ * Returns the method for these handlers.
+ *
+ * Generates a new method for every destination handlers reachable from "h". */
+static void find_methods(compiler *c, const upb_handlers *h) {
+  upb_value v;
+  upb_msg_field_iter i;
+  const upb_msgdef *md;
+
+  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
+    return;
+  newmethod(h, c->group);
+
+  /* Find submethods. */
+  md = upb_handlers_msgdef(h);
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    const upb_handlers *sub_h;
+    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
+      /* We only generate a decoder method for submessages with handlers.
+       * Others will be parsed as unknown fields. */
+      find_methods(c, sub_h);
+    }
+  }
+}
+
+/* (Re-)compile bytecode for all messages in "msgs."
+ * Overwrites any existing bytecode in "c". */
+static void compile_methods(compiler *c) {
+  upb_inttable_iter i;
+
+  /* Start over at the beginning of the bytecode. */
+  c->pc = c->group->bytecode;
+
+  upb_inttable_begin(&i, &c->group->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
+    compile_method(c, method);
+  }
+}
+
+static void set_bytecode_handlers(mgroup *g) {
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &g->methods);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
+    upb_byteshandler *h = &m->input_handler_;
+
+    m->code_base.ptr = g->bytecode + m->code_base.ofs;
+
+    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
+    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
+    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
+  }
+}
+
+
+/* JIT setup. *****************************************************************/
+
+#ifdef UPB_USE_JIT_X64
+
+static void sethandlers(mgroup *g, bool allowjit) {
+  g->jit_code = NULL;
+  if (allowjit) {
+    /* Compile byte-code into machine code, create handlers. */
+    upb_pbdecoder_jit(g);
+  } else {
+    set_bytecode_handlers(g);
+  }
+}
+
+#else  /* UPB_USE_JIT_X64 */
+
+static void sethandlers(mgroup *g, bool allowjit) {
+  /* No JIT compiled in; use bytecode handlers unconditionally. */
+  UPB_UNUSED(allowjit);
+  set_bytecode_handlers(g);
+}
+
+#endif  /* UPB_USE_JIT_X64 */
+
+
+/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
+ * handlers and other mgroups (but verify we have a transitive closure). */
+const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
+                         const void *owner) {
+  mgroup *g;
+  compiler *c;
+
+  UPB_UNUSED(allowjit);
+  assert(upb_handlers_isfrozen(dest));
+
+  g = newgroup(owner);
+  c = newcompiler(g, lazy);
+  find_methods(c, dest);
+
+  /* We compile in two passes:
+   * 1. all messages are assigned relative offsets from the beginning of the
+   *    bytecode (saved in method->code_base).
+   * 2. forwards OP_CALL instructions can be correctly linked since message
+   *    offsets have been previously assigned.
+   *
+   * Could avoid the second pass by linking OP_CALL instructions somehow. */
+  compile_methods(c);
+  compile_methods(c);
+  g->bytecode_end = c->pc;
+  freecompiler(c);
+
+#ifdef UPB_DUMP_BYTECODE
+  {
+    FILE *f = fopen("/tmp/upb-bytecode", "w");
+    assert(f);
+    dumpbc(g->bytecode, g->bytecode_end, stderr);
+    dumpbc(g->bytecode, g->bytecode_end, f);
+    fclose(f);
+
+    f = fopen("/tmp/upb-bytecode.bin", "wb");
+    assert(f);
+    fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
+    fclose(f);
+  }
+#endif
+
+  sethandlers(g, allowjit);
+  return g;
+}
+
+
+/* upb_pbcodecache ************************************************************/
+
+void upb_pbcodecache_init(upb_pbcodecache *c) {
+  upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR);
+  c->allow_jit_ = true;
+}
+
+void upb_pbcodecache_uninit(upb_pbcodecache *c) {
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &c->groups);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i));
+    mgroup_unref(group, c);
+  }
+  upb_inttable_uninit(&c->groups);
+}
+
+bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) {
+  return c->allow_jit_;
+}
+
+bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) {
+  if (upb_inttable_count(&c->groups) > 0)
+    return false;
+  c->allow_jit_ = allow;
+  return true;
+}
+
+const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
+    upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) {
+  upb_value v;
+  bool ok;
+
+  /* Right now we build a new DecoderMethod every time.
+   * TODO(haberman): properly cache methods by their true key. */
+  const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c);
+  upb_inttable_push(&c->groups, upb_value_constptr(g));
+
+  ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v);
+  UPB_ASSERT_VAR(ok, ok);
+  return upb_value_getptr(v);
+}
+
+
+/* upb_pbdecodermethodopts ****************************************************/
+
+void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
+                                  const upb_handlers *h) {
+  opts->handlers = h;
+  opts->lazy = false;
+}
+
+void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) {
+  opts->lazy = lazy;
+}
+/*
+** upb::Decoder (Bytecode Decoder VM)
+**
+** Bytecode must previously have been generated using the bytecode compiler in
+** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
+** parse the input.
+**
+** Decoding is fully resumable; we just keep a pointer to the current bytecode
+** instruction and resume from there.  A fair amount of the logic here is to
+** handle the fact that values can span buffer seams and we have to be able to
+** be capable of suspending/resuming from any byte in the stream.  This
+** sometimes requires keeping a few trailing bytes from the last buffer around
+** in the "residual" buffer.
+*/
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#ifdef UPB_DUMP_BYTECODE
+#include <stdio.h>
+#endif
+
+#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
+
+/* Error messages that are shared between the bytecode and JIT decoders. */
+const char *kPbDecoderStackOverflow = "Nesting too deep.";
+const char *kPbDecoderSubmessageTooLong =
+    "Submessage end extends past enclosing submessage.";
+
+/* Error messages shared within this file. */
+static const char *kUnterminatedVarint = "Unterminated varint.";
+
+/* upb_pbdecoder **************************************************************/
+
+static opcode halt = OP_HALT;
+
+/* A dummy character we can point to when the user passes us a NULL buffer.
+ * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
+ * behavior, which would invalidate functions like curbufleft(). */
+static const char dummy_char;
+
+/* Whether an op consumes any of the input buffer. */
+static bool consumes_input(opcode op) {
+  switch (op) {
+    case OP_SETDISPATCH:
+    case OP_STARTMSG:
+    case OP_ENDMSG:
+    case OP_STARTSEQ:
+    case OP_ENDSEQ:
+    case OP_STARTSUBMSG:
+    case OP_ENDSUBMSG:
+    case OP_STARTSTR:
+    case OP_ENDSTR:
+    case OP_PUSHTAGDELIM:
+    case OP_POP:
+    case OP_SETDELIM:
+    case OP_SETBIGGROUPNUM:
+    case OP_CHECKDELIM:
+    case OP_CALL:
+    case OP_RET:
+    case OP_BRANCH:
+      return false;
+    default:
+      return true;
+  }
+}
+
+static size_t stacksize(upb_pbdecoder *d, size_t entries) {
+  UPB_UNUSED(d);
+  return entries * sizeof(upb_pbdecoder_frame);
+}
+
+static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
+  UPB_UNUSED(d);
+
+#ifdef UPB_USE_JIT_X64
+  if (d->method_->is_native_) {
+    /* Each native stack frame needs two pointers, plus we need a few frames for
+     * the enter/exit trampolines. */
+    size_t ret = entries * sizeof(void*) * 2;
+    ret += sizeof(void*) * 10;
+    return ret;
+  }
+#endif
+
+  return entries * sizeof(uint32_t*);
+}
+
+
+static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
+
+/* It's unfortunate that we have to micro-manage the compiler with
+ * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
+ * specific to one hardware configuration.  But empirically on a Core i7,
+ * performance increases 30-50% with these annotations.  Every instance where
+ * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
+ * benchmarks. */
+
+static void seterr(upb_pbdecoder *d, const char *msg) {
+  upb_status status = UPB_STATUS_INIT;
+  upb_status_seterrmsg(&status, msg);
+  upb_env_reporterror(d->env, &status);
+}
+
+void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
+  seterr(d, msg);
+}
+
+
+/* Buffering ******************************************************************/
+
+/* We operate on one buffer at a time, which is either the user's buffer passed
+ * to our "decode" callback or some residual bytes from the previous buffer. */
+
+/* How many bytes can be safely read from d->ptr without reading past end-of-buf
+ * or past the current delimited end. */
+static size_t curbufleft(const upb_pbdecoder *d) {
+  assert(d->data_end >= d->ptr);
+  return d->data_end - d->ptr;
+}
+
+/* How many bytes are available before end-of-buffer. */
+static size_t bufleft(const upb_pbdecoder *d) {
+  return d->end - d->ptr;
+}
+
+/* Overall stream offset of d->ptr. */
+uint64_t offset(const upb_pbdecoder *d) {
+  return d->bufstart_ofs + (d->ptr - d->buf);
+}
+
+/* How many bytes are available before the end of this delimited region. */
+size_t delim_remaining(const upb_pbdecoder *d) {
+  return d->top->end_ofs - offset(d);
+}
+
+/* Advances d->ptr. */
+static void advance(upb_pbdecoder *d, size_t len) {
+  assert(curbufleft(d) >= len);
+  d->ptr += len;
+}
+
+static bool in_buf(const char *p, const char *buf, const char *end) {
+  return p >= buf && p <= end;
+}
+
+static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
+  return in_buf(p, d->residual, d->residual_end);
+}
+
+/* Calculates the delim_end value, which is affected by both the current buffer
+ * and the parsing stack, so must be called whenever either is updated. */
+static void set_delim_end(upb_pbdecoder *d) {
+  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
+  if (delim_ofs <= (size_t)(d->end - d->buf)) {
+    d->delim_end = d->buf + delim_ofs;
+    d->data_end = d->delim_end;
+  } else {
+    d->data_end = d->end;
+    d->delim_end = NULL;
+  }
+}
+
+static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
+  d->ptr = buf;
+  d->buf = buf;
+  d->end = end;
+  set_delim_end(d);
+}
+
+static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
+  assert(curbufleft(d) == 0);
+  d->bufstart_ofs += (d->end - d->buf);
+  switchtobuf(d, buf, buf + len);
+}
+
+static void checkpoint(upb_pbdecoder *d) {
+  /* The assertion here is in the interests of efficiency, not correctness.
+   * We are trying to ensure that we don't checkpoint() more often than
+   * necessary. */
+  assert(d->checkpoint != d->ptr);
+  d->checkpoint = d->ptr;
+}
+
+/* Skips "bytes" bytes in the stream, which may be more than available.  If we
+ * skip more bytes than are available, we return a long read count to the caller
+ * indicating how many bytes can be skipped over before passing actual data
+ * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
+ * won't actually be read.
+ */
+static int32_t skip(upb_pbdecoder *d, size_t bytes) {
+  assert(!in_residual_buf(d, d->ptr) || d->size_param == 0);
+  assert(d->skip == 0);
+  if (bytes > delim_remaining(d)) {
+    seterr(d, "Skipped value extended beyond enclosing submessage.");
+    return upb_pbdecoder_suspend(d);
+  } else if (bufleft(d) >= bytes) {
+    /* Skipped data is all in current buffer, and more is still available. */
+    advance(d, bytes);
+    d->skip = 0;
+    return DECODE_OK;
+  } else {
+    /* Skipped data extends beyond currently available buffers. */
+    d->pc = d->last;
+    d->skip = bytes - curbufleft(d);
+    d->bufstart_ofs += (d->end - d->buf);
+    d->residual_end = d->residual;
+    switchtobuf(d, d->residual, d->residual_end);
+    return d->size_param + d->skip;
+  }
+}
+
+
+/* Resumes the decoder from an initial state or from a previous suspend. */
+int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
+                             size_t size, const upb_bufhandle *handle) {
+  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
+
+  /* d->skip and d->residual_end could probably elegantly be represented
+   * as a single variable, to more easily represent this invariant. */
+  assert(!(d->skip && d->residual_end > d->residual));
+
+  /* We need to remember the original size_param, so that the value we return
+   * is relative to it, even if we do some skipping first. */
+  d->size_param = size;
+  d->handle = handle;
+
+  /* Have to handle this case specially (ie. not with skip()) because the user
+   * is allowed to pass a NULL buffer here, which won't allow us to safely
+   * calculate a d->end or use our normal functions like curbufleft(). */
+  if (d->skip && d->skip >= size) {
+    d->skip -= size;
+    d->bufstart_ofs += size;
+    buf = &dummy_char;
+    size = 0;
+
+    /* We can't just return now, because we might need to execute some ops
+     * like CHECKDELIM, which could call some callbacks and pop the stack. */
+  }
+
+  /* We need to pretend that this was the actual buffer param, since some of the
+   * calculations assume that d->ptr/d->buf is relative to this. */
+  d->buf_param = buf;
+
+  if (!buf) {
+    /* NULL buf is ok if its entire span is covered by the "skip" above, but
+     * by this point we know that "skip" doesn't cover the buffer. */
+    seterr(d, "Passed NULL buffer over non-skippable region.");
+    return upb_pbdecoder_suspend(d);
+  }
+
+  if (d->residual_end > d->residual) {
+    /* We have residual bytes from the last buffer. */
+    assert(d->ptr == d->residual);
+  } else {
+    switchtobuf(d, buf, buf + size);
+  }
+
+  d->checkpoint = d->ptr;
+
+  /* Handle skips that don't cover the whole buffer (as above). */
+  if (d->skip) {
+    size_t skip_bytes = d->skip;
+    d->skip = 0;
+    CHECK_RETURN(skip(d, skip_bytes));
+    checkpoint(d);
+  }
+
+  /* If we're inside an unknown group, continue to parse unknown values. */
+  if (d->top->groupnum < 0) {
+    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
+    checkpoint(d);
+  }
+
+  return DECODE_OK;
+}
+
+/* Suspends the decoder at the last checkpoint, without saving any residual
+ * bytes.  If there are any unconsumed bytes, returns a short byte count. */
+size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
+  d->pc = d->last;
+  if (d->checkpoint == d->residual) {
+    /* Checkpoint was in residual buf; no user bytes were consumed. */
+    d->ptr = d->residual;
+    return 0;
+  } else {
+    size_t ret = d->size_param - (d->end - d->checkpoint);
+    assert(!in_residual_buf(d, d->checkpoint));
+    assert(d->buf == d->buf_param || d->buf == &dummy_char);
+
+    d->bufstart_ofs += (d->checkpoint - d->buf);
+    d->residual_end = d->residual;
+    switchtobuf(d, d->residual, d->residual_end);
+    return ret;
+  }
+}
+
+/* Suspends the decoder at the last checkpoint, and saves any unconsumed
+ * bytes in our residual buffer.  This is necessary if we need more user
+ * bytes to form a complete value, which might not be contiguous in the
+ * user's buffers.  Always consumes all user bytes. */
+static size_t suspend_save(upb_pbdecoder *d) {
+  /* We hit end-of-buffer before we could parse a full value.
+   * Save any unconsumed bytes (if any) to the residual buffer. */
+  d->pc = d->last;
+
+  if (d->checkpoint == d->residual) {
+    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
+    assert((d->residual_end - d->residual) + d->size_param <=
+           sizeof(d->residual));
+    if (!in_residual_buf(d, d->ptr)) {
+      d->bufstart_ofs -= (d->residual_end - d->residual);
+    }
+    memcpy(d->residual_end, d->buf_param, d->size_param);
+    d->residual_end += d->size_param;
+  } else {
+    /* Checkpoint was in user buf; old residual bytes not needed. */
+    size_t save;
+    assert(!in_residual_buf(d, d->checkpoint));
+
+    d->ptr = d->checkpoint;
+    save = curbufleft(d);
+    assert(save <= sizeof(d->residual));
+    memcpy(d->residual, d->ptr, save);
+    d->residual_end = d->residual + save;
+    d->bufstart_ofs = offset(d);
+  }
+
+  switchtobuf(d, d->residual, d->residual_end);
+  return d->size_param;
+}
+
+/* Copies the next "bytes" bytes into "buf" and advances the stream.
+ * Requires that this many bytes are available in the current buffer. */
+UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
+                                         size_t bytes) {
+  assert(bytes <= curbufleft(d));
+  memcpy(buf, d->ptr, bytes);
+  advance(d, bytes);
+}
+
+/* Slow path for getting the next "bytes" bytes, regardless of whether they are
+ * available in the current buffer or not.  Returns a status code as described
+ * in decoder.int.h. */
+UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
+                                          size_t bytes) {
+  const size_t avail = curbufleft(d);
+  consumebytes(d, buf, avail);
+  bytes -= avail;
+  assert(bytes > 0);
+  if (in_residual_buf(d, d->ptr)) {
+    advancetobuf(d, d->buf_param, d->size_param);
+  }
+  if (curbufleft(d) >= bytes) {
+    consumebytes(d, (char *)buf + avail, bytes);
+    return DECODE_OK;
+  } else if (d->data_end == d->delim_end) {
+    seterr(d, "Submessage ended in the middle of a value or group");
+    return upb_pbdecoder_suspend(d);
+  } else {
+    return suspend_save(d);
+  }
+}
+
+/* Gets the next "bytes" bytes, regardless of whether they are available in the
+ * current buffer or not.  Returns a status code as described in decoder.int.h.
+ */
+UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
+                                        size_t bytes) {
+  if (curbufleft(d) >= bytes) {
+    /* Buffer has enough data to satisfy. */
+    consumebytes(d, buf, bytes);
+    return DECODE_OK;
+  } else {
+    return getbytes_slow(d, buf, bytes);
+  }
+}
+
+UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
+                                          size_t bytes) {
+  size_t ret = curbufleft(d);
+  memcpy(buf, d->ptr, ret);
+  if (in_residual_buf(d, d->ptr)) {
+    size_t copy = UPB_MIN(bytes - ret, d->size_param);
+    memcpy((char *)buf + ret, d->buf_param, copy);
+    ret += copy;
+  }
+  return ret;
+}
+
+UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
+                                        size_t bytes) {
+  if (curbufleft(d) >= bytes) {
+    memcpy(buf, d->ptr, bytes);
+    return bytes;
+  } else {
+    return peekbytes_slow(d, buf, bytes);
+  }
+}
+
+
+/* Decoding of wire types *****************************************************/
+
+/* Slow path for decoding a varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
+                                                      uint64_t *u64) {
+  uint8_t byte = 0x80;
+  int bitpos;
+  *u64 = 0;
+  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
+    CHECK_RETURN(getbytes(d, &byte, 1));
+    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
+  }
+  if(bitpos == 70 && (byte & 0x80)) {
+    seterr(d, kUnterminatedVarint);
+    return upb_pbdecoder_suspend(d);
+  }
+  return DECODE_OK;
+}
+
+/* Decodes a varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
+  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
+    *u64 = *d->ptr;
+    advance(d, 1);
+    return DECODE_OK;
+  } else if (curbufleft(d) >= 10) {
+    /* Fast case. */
+    upb_decoderet r = upb_vdecode_fast(d->ptr);
+    if (r.p == NULL) {
+      seterr(d, kUnterminatedVarint);
+      return upb_pbdecoder_suspend(d);
+    }
+    advance(d, r.p - d->ptr);
+    *u64 = r.val;
+    return DECODE_OK;
+  } else {
+    /* Slow case -- varint spans buffer seam. */
+    return upb_pbdecoder_decode_varint_slow(d, u64);
+  }
+}
+
+/* Decodes a 32-bit varint from the current buffer position.
+ * Returns a status code as described in decoder.int.h. */
+UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
+  uint64_t u64;
+  int32_t ret = decode_varint(d, &u64);
+  if (ret >= 0) return ret;
+  if (u64 > UINT32_MAX) {
+    seterr(d, "Unterminated 32-bit varint");
+    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
+     * so we know this path will always be treated as error by our caller.
+     * Right now the size_t -> int32_t can overflow and produce negative values.
+     */
+    *u32 = 0;
+    return upb_pbdecoder_suspend(d);
+  }
+  *u32 = u64;
+  return DECODE_OK;
+}
+
+/* Decodes a fixed32 from the current buffer position.
+ * Returns a status code as described in decoder.int.h.
+ * TODO: proper byte swapping for big-endian machines. */
+UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
+  return getbytes(d, u32, 4);
+}
+
+/* Decodes a fixed64 from the current buffer position.
+ * Returns a status code as described in decoder.int.h.
+ * TODO: proper byte swapping for big-endian machines. */
+UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
+  return getbytes(d, u64, 8);
+}
+
+/* Non-static versions of the above functions.
+ * These are called by the JIT for fallback paths. */
+int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
+  return decode_fixed32(d, u32);
+}
+
+int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
+  return decode_fixed64(d, u64);
+}
+
+static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
+static float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
+
+/* Pushes a frame onto the decoder stack. */
+static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
+  upb_pbdecoder_frame *fr = d->top;
+
+  if (end > fr->end_ofs) {
+    seterr(d, kPbDecoderSubmessageTooLong);
+    return false;
+  } else if (fr == d->limit) {
+    seterr(d, kPbDecoderStackOverflow);
+    return false;
+  }
+
+  fr++;
+  fr->end_ofs = end;
+  fr->dispatch = NULL;
+  fr->groupnum = 0;
+  d->top = fr;
+  return true;
+}
+
+static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
+  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
+   * field number) prior to hitting any enclosing submessage end, pushing our
+   * existing delim end prevents us from continuing to parse values from a
+   * corrupt proto that doesn't give us an END tag in time. */
+  if (!decoder_push(d, d->top->end_ofs))
+    return false;
+  d->top->groupnum = arg;
+  return true;
+}
+
+/* Pops a frame from the decoder stack. */
+static void decoder_pop(upb_pbdecoder *d) { d->top--; }
+
+UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
+                                                 uint64_t expected) {
+  uint64_t data = 0;
+  size_t bytes = upb_value_size(expected);
+  size_t read = peekbytes(d, &data, bytes);
+  if (read == bytes && data == expected) {
+    /* Advance past matched bytes. */
+    int32_t ok = getbytes(d, &data, read);
+    UPB_ASSERT_VAR(ok, ok < 0);
+    return DECODE_OK;
+  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
+    return suspend_save(d);
+  } else {
+    return DECODE_MISMATCH;
+  }
+}
+
+int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
+                                  uint8_t wire_type) {
+  if (fieldnum >= 0)
+    goto have_tag;
+
+  while (true) {
+    uint32_t tag;
+    CHECK_RETURN(decode_v32(d, &tag));
+    wire_type = tag & 0x7;
+    fieldnum = tag >> 3;
+
+have_tag:
+    if (fieldnum == 0) {
+      seterr(d, "Saw invalid field number (0)");
+      return upb_pbdecoder_suspend(d);
+    }
+
+    /* TODO: deliver to unknown field callback. */
+    switch (wire_type) {
+      case UPB_WIRE_TYPE_32BIT:
+        CHECK_RETURN(skip(d, 4));
+        break;
+      case UPB_WIRE_TYPE_64BIT:
+        CHECK_RETURN(skip(d, 8));
+        break;
+      case UPB_WIRE_TYPE_VARINT: {
+        uint64_t u64;
+        CHECK_RETURN(decode_varint(d, &u64));
+        break;
+      }
+      case UPB_WIRE_TYPE_DELIMITED: {
+        uint32_t len;
+        CHECK_RETURN(decode_v32(d, &len));
+        CHECK_RETURN(skip(d, len));
+        break;
+      }
+      case UPB_WIRE_TYPE_START_GROUP:
+        CHECK_SUSPEND(pushtagdelim(d, -fieldnum));
+        break;
+      case UPB_WIRE_TYPE_END_GROUP:
+        if (fieldnum == -d->top->groupnum) {
+          decoder_pop(d);
+        } else if (fieldnum == d->top->groupnum) {
+          return DECODE_ENDGROUP;
+        } else {
+          seterr(d, "Unmatched ENDGROUP tag.");
+          return upb_pbdecoder_suspend(d);
+        }
+        break;
+      default:
+        seterr(d, "Invalid wire type");
+        return upb_pbdecoder_suspend(d);
+    }
+
+    if (d->top->groupnum >= 0) {
+      return DECODE_OK;
+    }
+
+    /* Unknown group -- continue looping over unknown fields. */
+    checkpoint(d);
+  }
+}
+
+static void goto_endmsg(upb_pbdecoder *d) {
+  upb_value v;
+  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
+  UPB_ASSERT_VAR(found, found);
+  d->pc = d->top->base + upb_value_getuint64(v);
+}
+
+/* Parses a tag and jumps to the corresponding bytecode instruction for this
+ * field.
+ *
+ * If the tag is unknown (or the wire type doesn't match), parses the field as
+ * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
+ * instruction for the end of message. */
+static int32_t dispatch(upb_pbdecoder *d) {
+  upb_inttable *dispatch = d->top->dispatch;
+  uint32_t tag;
+  uint8_t wire_type;
+  uint32_t fieldnum;
+  upb_value val;
+  int32_t retval;
+
+  /* Decode tag. */
+  CHECK_RETURN(decode_v32(d, &tag));
+  wire_type = tag & 0x7;
+  fieldnum = tag >> 3;
+
+  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
+   * check the wire type against two possibilities. */
+  if (fieldnum != DISPATCH_ENDMSG &&
+      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
+    uint64_t v = upb_value_getuint64(val);
+    if (wire_type == (v & 0xff)) {
+      d->pc = d->top->base + (v >> 16);
+      return DECODE_OK;
+    } else if (wire_type == ((v >> 8) & 0xff)) {
+      bool found =
+          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
+      UPB_ASSERT_VAR(found, found);
+      d->pc = d->top->base + upb_value_getuint64(val);
+      return DECODE_OK;
+    }
+  }
+
+  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
+   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
+   * we need to back up to, so that when we're done skipping unknown data we
+   * can re-check the delimited end. */
+  d->last--;  /* Necessary if we get suspended */
+  d->pc = d->last;
+  assert(getop(*d->last) == OP_CHECKDELIM);
+
+  /* Unknown field or ENDGROUP. */
+  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
+
+  CHECK_RETURN(retval);
+
+  if (retval == DECODE_ENDGROUP) {
+    goto_endmsg(d);
+    return DECODE_OK;
+  }
+
+  return DECODE_OK;
+}
+
+/* Callers know that the stack is more than one deep because the opcodes that
+ * call this only occur after PUSH operations. */
+upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
+  assert(d->top != d->stack);
+  return d->top - 1;
+}
+
+
+/* The main decoding loop *****************************************************/
+
+/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
+ * switch() statement. */
+size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
+                      const upb_bufhandle* handle) {
+
+#define VMCASE(op, code) \
+  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
+#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
+  VMCASE(OP_PARSE_ ## type, { \
+    ctype val; \
+    CHECK_RETURN(decode_ ## wt(d, &val)); \
+    upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \
+  })
+
+  while(1) {
+    int32_t instruction;
+    opcode op;
+    uint32_t arg;
+    int32_t longofs;
+
+    d->last = d->pc;
+    instruction = *d->pc++;
+    op = getop(instruction);
+    arg = instruction >> 8;
+    longofs = arg;
+    assert(d->ptr != d->residual_end);
+    UPB_UNUSED(group);
+#ifdef UPB_DUMP_BYTECODE
+    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
+                    "%x %s (%d)\n",
+            (int)offset(d),
+            (int)(d->ptr - d->buf),
+            (int)(d->data_end - d->ptr),
+            (int)(d->end - d->ptr),
+            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
+            (int)(d->pc - 1 - group->bytecode),
+            upb_pbdecoder_getopname(op),
+            arg);
+#endif
+    switch (op) {
+      /* Technically, we are losing data if we see a 32-bit varint that is not
+       * properly sign-extended.  We could detect this and error about the data
+       * loss, but proto2 does not do this, so we pass. */
+      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
+      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
+      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
+      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
+      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
+      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
+      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
+      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
+      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
+      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
+      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
+      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
+      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
+
+      VMCASE(OP_SETDISPATCH,
+        d->top->base = d->pc - 1;
+        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
+        d->pc += sizeof(void*) / sizeof(uint32_t);
+      )
+      VMCASE(OP_STARTMSG,
+        CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink));
+      )
+      VMCASE(OP_ENDMSG,
+        CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status));
+      )
+      VMCASE(OP_STARTSEQ,
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink));
+      )
+      VMCASE(OP_ENDSEQ,
+        CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg));
+      )
+      VMCASE(OP_STARTSUBMSG,
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink));
+      )
+      VMCASE(OP_ENDSUBMSG,
+        CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg));
+      )
+      VMCASE(OP_STARTSTR,
+        uint32_t len = delim_remaining(d);
+        upb_pbdecoder_frame *outer = outer_frame(d);
+        CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink));
+        if (len == 0) {
+          d->pc++;  /* Skip OP_STRING. */
+        }
+      )
+      VMCASE(OP_STRING,
+        uint32_t len = curbufleft(d);
+        size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle);
+        if (n > len) {
+          if (n > delim_remaining(d)) {
+            seterr(d, "Tried to skip past end of string.");
+            return upb_pbdecoder_suspend(d);
+          } else {
+            int32_t ret = skip(d, n);
+            /* This shouldn't return DECODE_OK, because n > len. */
+            assert(ret >= 0);
+            return ret;
+          }
+        }
+        advance(d, n);
+        if (n < len || d->delim_end == NULL) {
+          /* We aren't finished with this string yet. */
+          d->pc--;  /* Repeat OP_STRING. */
+          if (n > 0) checkpoint(d);
+          return upb_pbdecoder_suspend(d);
+        }
+      )
+      VMCASE(OP_ENDSTR,
+        CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg));
+      )
+      VMCASE(OP_PUSHTAGDELIM,
+        CHECK_SUSPEND(pushtagdelim(d, arg));
+      )
+      VMCASE(OP_SETBIGGROUPNUM,
+        d->top->groupnum = *d->pc++;
+      )
+      VMCASE(OP_POP,
+        assert(d->top > d->stack);
+        decoder_pop(d);
+      )
+      VMCASE(OP_PUSHLENDELIM,
+        uint32_t len;
+        CHECK_RETURN(decode_v32(d, &len));
+        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
+        set_delim_end(d);
+      )
+      VMCASE(OP_SETDELIM,
+        set_delim_end(d);
+      )
+      VMCASE(OP_CHECKDELIM,
+        /* We are guaranteed of this assert because we never allow ourselves to
+         * consume bytes beyond data_end, which covers delim_end when non-NULL.
+         */
+        assert(!(d->delim_end && d->ptr > d->delim_end));
+        if (d->ptr == d->delim_end)
+          d->pc += longofs;
+      )
+      VMCASE(OP_CALL,
+        d->callstack[d->call_len++] = d->pc;
+        d->pc += longofs;
+      )
+      VMCASE(OP_RET,
+        assert(d->call_len > 0);
+        d->pc = d->callstack[--d->call_len];
+      )
+      VMCASE(OP_BRANCH,
+        d->pc += longofs;
+      )
+      VMCASE(OP_TAG1,
+        uint8_t expected;
+        CHECK_SUSPEND(curbufleft(d) > 0);
+        expected = (arg >> 8) & 0xff;
+        if (*d->ptr == expected) {
+          advance(d, 1);
+        } else {
+          int8_t shortofs;
+         badtag:
+          shortofs = arg;
+          if (shortofs == LABEL_DISPATCH) {
+            CHECK_RETURN(dispatch(d));
+          } else {
+            d->pc += shortofs;
+            break; /* Avoid checkpoint(). */
+          }
+        }
+      )
+      VMCASE(OP_TAG2,
+        uint16_t expected;
+        CHECK_SUSPEND(curbufleft(d) > 0);
+        expected = (arg >> 8) & 0xffff;
+        if (curbufleft(d) >= 2) {
+          uint16_t actual;
+          memcpy(&actual, d->ptr, 2);
+          if (expected == actual) {
+            advance(d, 2);
+          } else {
+            goto badtag;
+          }
+        } else {
+          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
+          if (result == DECODE_MISMATCH) goto badtag;
+          if (result >= 0) return result;
+        }
+      )
+      VMCASE(OP_TAGN, {
+        uint64_t expected;
+        int32_t result;
+        memcpy(&expected, d->pc, 8);
+        d->pc += 2;
+        result = upb_pbdecoder_checktag_slow(d, expected);
+        if (result == DECODE_MISMATCH) goto badtag;
+        if (result >= 0) return result;
+      })
+      VMCASE(OP_DISPATCH, {
+        CHECK_RETURN(dispatch(d));
+      })
+      VMCASE(OP_HALT, {
+        return d->size_param;
+      })
+    }
+  }
+}
+
+
+/* BytesHandler handlers ******************************************************/
+
+void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
+  upb_pbdecoder *d = closure;
+  UPB_UNUSED(size_hint);
+  d->top->end_ofs = UINT64_MAX;
+  d->bufstart_ofs = 0;
+  d->call_len = 1;
+  d->callstack[0] = &halt;
+  d->pc = pc;
+  d->skip = 0;
+  return d;
+}
+
+void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) {
+  upb_pbdecoder *d = closure;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(size_hint);
+  d->top->end_ofs = UINT64_MAX;
+  d->bufstart_ofs = 0;
+  d->call_len = 0;
+  d->skip = 0;
+  return d;
+}
+
+bool upb_pbdecoder_end(void *closure, const void *handler_data) {
+  upb_pbdecoder *d = closure;
+  const upb_pbdecodermethod *method = handler_data;
+  uint64_t end;
+  char dummy;
+
+  if (d->residual_end > d->residual) {
+    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
+    return false;
+  }
+
+  if (d->skip) {
+    seterr(d, "Unexpected EOF inside skipped data");
+    return false;
+  }
+
+  if (d->top->end_ofs != UINT64_MAX) {
+    seterr(d, "Unexpected EOF inside delimited string");
+    return false;
+  }
+
+  /* The user's end() call indicates that the message ends here. */
+  end = offset(d);
+  d->top->end_ofs = end;
+
+#ifdef UPB_USE_JIT_X64
+  if (method->is_native_) {
+    const mgroup *group = (const mgroup*)method->group;
+    if (d->top != d->stack)
+      d->stack->end_ofs = 0;
+    group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL);
+  } else
+#endif
+  {
+    const uint32_t *p = d->pc;
+    d->stack->end_ofs = end;
+    /* Check the previous bytecode, but guard against beginning. */
+    if (p != method->code_base.ptr) p--;
+    if (getop(*p) == OP_CHECKDELIM) {
+      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
+      assert(getop(*d->pc) == OP_TAG1 ||
+             getop(*d->pc) == OP_TAG2 ||
+             getop(*d->pc) == OP_TAGN ||
+             getop(*d->pc) == OP_DISPATCH);
+      d->pc = p;
+    }
+    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
+  }
+
+  if (d->call_len != 0) {
+    seterr(d, "Unexpected EOF inside submessage or group");
+    return false;
+  }
+
+  return true;
+}
+
+size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
+                            size_t size, const upb_bufhandle *handle) {
+  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
+
+  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
+  CHECK_RETURN(result);
+
+  return run_decoder_vm(decoder, group, handle);
+}
+
+
+/* Public API *****************************************************************/
+
+void upb_pbdecoder_reset(upb_pbdecoder *d) {
+  d->top = d->stack;
+  d->top->groupnum = 0;
+  d->ptr = d->residual;
+  d->buf = d->residual;
+  d->end = d->residual;
+  d->residual_end = d->residual;
+}
+
+upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
+                                    upb_sink *sink) {
+  const size_t default_max_nesting = 64;
+#ifndef NDEBUG
+  size_t size_before = upb_env_bytesallocated(e);
+#endif
+
+  upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder));
+  if (!d) return NULL;
+
+  d->method_ = m;
+  d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting));
+  d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting));
+  if (!d->stack || !d->callstack) {
+    return NULL;
+  }
+
+  d->env = e;
+  d->limit = d->stack + default_max_nesting - 1;
+  d->stack_size = default_max_nesting;
+  d->status = NULL;
+
+  upb_pbdecoder_reset(d);
+  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
+
+  assert(sink);
+  if (d->method_->dest_handlers_) {
+    if (sink->handlers != d->method_->dest_handlers_)
+      return NULL;
+  }
+  upb_sink_reset(&d->top->sink, sink->handlers, sink->closure);
+
+  /* If this fails, increase the value in decoder.h. */
+  assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE);
+  return d;
+}
+
+uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
+  return offset(d);
+}
+
+const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
+  return d->method_;
+}
+
+upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) {
+  return &d->input_;
+}
+
+size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
+  return d->stack_size;
+}
+
+bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
+  assert(d->top >= d->stack);
+
+  if (max < (size_t)(d->top - d->stack)) {
+    /* Can't set a limit smaller than what we are currently at. */
+    return false;
+  }
+
+  if (max > d->stack_size) {
+    /* Need to reallocate stack and callstack to accommodate. */
+    size_t old_size = stacksize(d, d->stack_size);
+    size_t new_size = stacksize(d, max);
+    void *p = upb_env_realloc(d->env, d->stack, old_size, new_size);
+    if (!p) {
+      return false;
+    }
+    d->stack = p;
+
+    old_size = callstacksize(d, d->stack_size);
+    new_size = callstacksize(d, max);
+    p = upb_env_realloc(d->env, d->callstack, old_size, new_size);
+    if (!p) {
+      return false;
+    }
+    d->callstack = p;
+
+    d->stack_size = max;
+  }
+
+  d->limit = d->stack + max - 1;
+  return true;
+}
+/*
+** upb::Encoder
+**
+** Since we are implementing pure handlers (ie. without any out-of-band access
+** to pre-computed lengths), we have to buffer all submessages before we can
+** emit even their first byte.
+**
+** Not knowing the size of submessages also means we can't write a perfect
+** zero-copy implementation, even with buffering.  Lengths are stored as
+** varints, which means that we don't know how many bytes to reserve for the
+** length until we know what the length is.
+**
+** This leaves us with three main choices:
+**
+** 1. buffer all submessage data in a temporary buffer, then copy it exactly
+**    once into the output buffer.
+**
+** 2. attempt to buffer data directly into the output buffer, estimating how
+**    many bytes each length will take.  When our guesses are wrong, use
+**    memmove() to grow or shrink the allotted space.
+**
+** 3. buffer directly into the output buffer, allocating a max length
+**    ahead-of-time for each submessage length.  If we overallocated, we waste
+**    space, but no memcpy() or memmove() is required.  This approach requires
+**    defining a maximum size for submessages and rejecting submessages that
+**    exceed that size.
+**
+** (2) and (3) have the potential to have better performance, but they are more
+** complicated and subtle to implement:
+**
+**   (3) requires making an arbitrary choice of the maximum message size; it
+**       wastes space when submessages are shorter than this and fails
+**       completely when they are longer.  This makes it more finicky and
+**       requires configuration based on the input.  It also makes it impossible
+**       to perfectly match the output of reference encoders that always use the
+**       optimal amount of space for each length.
+**
+**   (2) requires guessing the the size upfront, and if multiple lengths are
+**       guessed wrong the minimum required number of memmove() operations may
+**       be complicated to compute correctly.  Implemented properly, it may have
+**       a useful amortized or average cost, but more investigation is required
+**       to determine this and what the optimal algorithm is to achieve it.
+**
+**   (1) makes you always pay for exactly one copy, but its implementation is
+**       the simplest and its performance is predictable.
+**
+** So for now, we implement (1) only.  If we wish to optimize later, we should
+** be able to do it without affecting users.
+**
+** The strategy is to buffer the segments of data that do *not* depend on
+** unknown lengths in one buffer, and keep a separate buffer of segment pointers
+** and lengths.  When the top-level submessage ends, we can go beginning to end,
+** alternating the writing of lengths with memcpy() of the rest of the data.
+** At the top level though, no buffering is required.
+*/
+
+
+
+/* The output buffer is divided into segments; a segment is a string of data
+ * that is "ready to go" -- it does not need any varint lengths inserted into
+ * the middle.  The seams between segments are where varints will be inserted
+ * once they are known.
+ *
+ * We also use the concept of a "run", which is a range of encoded bytes that
+ * occur at a single submessage level.  Every segment contains one or more runs.
+ *
+ * A segment can span messages.  Consider:
+ *
+ *                  .--Submessage lengths---------.
+ *                  |       |                     |
+ *                  |       V                     V
+ *                  V      | |---------------    | |-----------------
+ * Submessages:    | |-----------------------------------------------
+ * Top-level msg: ------------------------------------------------------------
+ *
+ * Segments:          -----   -------------------   -----------------
+ * Runs:              *----   *--------------*---   *----------------
+ * (* marks the start)
+ *
+ * Note that the top-level menssage is not in any segment because it does not
+ * have any length preceding it.
+ *
+ * A segment is only interrupted when another length needs to be inserted.  So
+ * observe how the second segment spans both the inner submessage and part of
+ * the next enclosing message. */
+typedef struct {
+  uint32_t msglen;  /* The length to varint-encode before this segment. */
+  uint32_t seglen;  /* Length of the segment. */
+} upb_pb_encoder_segment;
+
+struct upb_pb_encoder {
+  upb_env *env;
+
+  /* Our input and output. */
+  upb_sink input_;
+  upb_bytessink *output_;
+
+  /* The "subclosure" -- used as the inner closure as part of the bytessink
+   * protocol. */
+  void *subc;
+
+  /* The output buffer and limit, and our current write position.  "buf"
+   * initially points to "initbuf", but is dynamically allocated if we need to
+   * grow beyond the initial size. */
+  char *buf, *ptr, *limit;
+
+  /* The beginning of the current run, or undefined if we are at the top
+   * level. */
+  char *runbegin;
+
+  /* The list of segments we are accumulating. */
+  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
+
+  /* The stack of enclosing submessages.  Each entry in the stack points to the
+   * segment where this submessage's length is being accumulated. */
+  int *stack, *top, *stacklimit;
+
+  /* Depth of startmsg/endmsg calls. */
+  int depth;
+};
+
+/* low-level buffering ********************************************************/
+
+/* Low-level functions for interacting with the output buffer. */
+
+/* TODO(haberman): handle pushback */
+static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
+  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
+  UPB_ASSERT_VAR(n, n == len);
+}
+
+static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
+  return &e->segbuf[*e->top];
+}
+
+/* Call to ensure that at least "bytes" bytes are available for writing at
+ * e->ptr.  Returns false if the bytes could not be allocated. */
+static bool reserve(upb_pb_encoder *e, size_t bytes) {
+  if ((size_t)(e->limit - e->ptr) < bytes) {
+    /* Grow buffer. */
+    char *new_buf;
+    size_t needed = bytes + (e->ptr - e->buf);
+    size_t old_size = e->limit - e->buf;
+
+    size_t new_size = old_size;
+
+    while (new_size < needed) {
+      new_size *= 2;
+    }
+
+    new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size);
+
+    if (new_buf == NULL) {
+      return false;
+    }
+
+    e->ptr = new_buf + (e->ptr - e->buf);
+    e->runbegin = new_buf + (e->runbegin - e->buf);
+    e->limit = new_buf + new_size;
+    e->buf = new_buf;
+  }
+
+  return true;
+}
+
+/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
+ * previously called reserve() with at least this many bytes. */
+static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
+  assert((size_t)(e->limit - e->ptr) >= bytes);
+  e->ptr += bytes;
+}
+
+/* Call when all of the bytes for a handler have been written.  Flushes the
+ * bytes if possible and necessary, returning false if this failed. */
+static bool commit(upb_pb_encoder *e) {
+  if (!e->top) {
+    /* We aren't inside a delimited region.  Flush our accumulated bytes to
+     * the output.
+     *
+     * TODO(haberman): in the future we may want to delay flushing for
+     * efficiency reasons. */
+    putbuf(e, e->buf, e->ptr - e->buf);
+    e->ptr = e->buf;
+  }
+
+  return true;
+}
+
+/* Writes the given bytes to the buffer, handling reserve/advance. */
+static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
+  if (!reserve(e, len)) {
+    return false;
+  }
+
+  memcpy(e->ptr, data, len);
+  encoder_advance(e, len);
+  return true;
+}
+
+/* Finish the current run by adding the run totals to the segment and message
+ * length. */
+static void accumulate(upb_pb_encoder *e) {
+  size_t run_len;
+  assert(e->ptr >= e->runbegin);
+  run_len = e->ptr - e->runbegin;
+  e->segptr->seglen += run_len;
+  top(e)->msglen += run_len;
+  e->runbegin = e->ptr;
+}
+
+/* Call to indicate the start of delimited region for which the full length is
+ * not yet known.  All data will be buffered until the length is known.
+ * Delimited regions may be nested; their lengths will all be tracked properly. */
+static bool start_delim(upb_pb_encoder *e) {
+  if (e->top) {
+    /* We are already buffering, advance to the next segment and push it on the
+     * stack. */
+    accumulate(e);
+
+    if (++e->top == e->stacklimit) {
+      /* TODO(haberman): grow stack? */
+      return false;
+    }
+
+    if (++e->segptr == e->seglimit) {
+      /* Grow segment buffer. */
+      size_t old_size =
+          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
+      size_t new_size = old_size * 2;
+      upb_pb_encoder_segment *new_buf =
+          upb_env_realloc(e->env, e->segbuf, old_size, new_size);
+
+      if (new_buf == NULL) {
+        return false;
+      }
+
+      e->segptr = new_buf + (e->segptr - e->segbuf);
+      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
+      e->segbuf = new_buf;
+    }
+  } else {
+    /* We were previously at the top level, start buffering. */
+    e->segptr = e->segbuf;
+    e->top = e->stack;
+    e->runbegin = e->ptr;
+  }
+
+  *e->top = e->segptr - e->segbuf;
+  e->segptr->seglen = 0;
+  e->segptr->msglen = 0;
+
+  return true;
+}
+
+/* Call to indicate the end of a delimited region.  We now know the length of
+ * the delimited region.  If we are not nested inside any other delimited
+ * regions, we can now emit all of the buffered data we accumulated. */
+static bool end_delim(upb_pb_encoder *e) {
+  size_t msglen;
+  accumulate(e);
+  msglen = top(e)->msglen;
+
+  if (e->top == e->stack) {
+    /* All lengths are now available, emit all buffered data. */
+    char buf[UPB_PB_VARINT_MAX_LEN];
+    upb_pb_encoder_segment *s;
+    const char *ptr = e->buf;
+    for (s = e->segbuf; s <= e->segptr; s++) {
+      size_t lenbytes = upb_vencode64(s->msglen, buf);
+      putbuf(e, buf, lenbytes);
+      putbuf(e, ptr, s->seglen);
+      ptr += s->seglen;
+    }
+
+    e->ptr = e->buf;
+    e->top = NULL;
+  } else {
+    /* Need to keep buffering; propagate length info into enclosing
+     * submessages. */
+    --e->top;
+    top(e)->msglen += msglen + upb_varint_size(msglen);
+  }
+
+  return true;
+}
+
+
+/* tag_t **********************************************************************/
+
+/* A precomputed (pre-encoded) tag and length. */
+
+typedef struct {
+  uint8_t bytes;
+  char tag[7];
+} tag_t;
+
+/* Allocates a new tag for this field, and sets it in these handlerattr. */
+static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
+                    upb_handlerattr *attr) {
+  uint32_t n = upb_fielddef_number(f);
+
+  tag_t *tag = upb_gmalloc(sizeof(tag_t));
+  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
+
+  upb_handlerattr_init(attr);
+  upb_handlerattr_sethandlerdata(attr, tag);
+  upb_handlers_addcleanup(h, tag, upb_gfree);
+}
+
+static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
+  return encode_bytes(e, tag->tag, tag->bytes);
+}
+
+
+/* encoding of wire types *****************************************************/
+
+static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
+  /* TODO(haberman): byte-swap for big endian. */
+  return encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
+  /* TODO(haberman): byte-swap for big endian. */
+  return encode_bytes(e, &val, sizeof(uint32_t));
+}
+
+static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
+  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
+    return false;
+  }
+
+  encoder_advance(e, upb_vencode64(val, e->ptr));
+  return true;
+}
+
+static uint64_t dbl2uint64(double d) {
+  uint64_t ret;
+  memcpy(&ret, &d, sizeof(uint64_t));
+  return ret;
+}
+
+static uint32_t flt2uint32(float d) {
+  uint32_t ret;
+  memcpy(&ret, &d, sizeof(uint32_t));
+  return ret;
+}
+
+
+/* encoding of proto types ****************************************************/
+
+static bool startmsg(void *c, const void *hd) {
+  upb_pb_encoder *e = c;
+  UPB_UNUSED(hd);
+  if (e->depth++ == 0) {
+    upb_bytessink_start(e->output_, 0, &e->subc);
+  }
+  return true;
+}
+
+static bool endmsg(void *c, const void *hd, upb_status *status) {
+  upb_pb_encoder *e = c;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(status);
+  if (--e->depth == 0) {
+    upb_bytessink_end(e->output_);
+  }
+  return true;
+}
+
+static void *encode_startdelimfield(void *c, const void *hd) {
+  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
+  return ok ? c : UPB_BREAK;
+}
+
+static bool encode_enddelimfield(void *c, const void *hd) {
+  UPB_UNUSED(hd);
+  return end_delim(c);
+}
+
+static void *encode_startgroup(void *c, const void *hd) {
+  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
+}
+
+static bool encode_endgroup(void *c, const void *hd) {
+  return encode_tag(c, hd) && commit(c);
+}
+
+static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
+  UPB_UNUSED(size_hint);
+  return encode_startdelimfield(c, hd);
+}
+
+static size_t encode_strbuf(void *c, const void *hd, const char *buf,
+                            size_t len, const upb_bufhandle *h) {
+  UPB_UNUSED(hd);
+  UPB_UNUSED(h);
+  return encode_bytes(c, buf, len) ? len : 0;
+}
+
+#define T(type, ctype, convert, encode)                                  \
+  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
+    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
+  }                                                                      \
+  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
+    UPB_UNUSED(hd);                                                      \
+    return encode(e, (convert)(val));                                    \
+  }
+
+T(double,   double,   dbl2uint64,   encode_fixed64)
+T(float,    float,    flt2uint32,   encode_fixed32)
+T(int64,    int64_t,  uint64_t,     encode_varint)
+T(int32,    int32_t,  uint32_t,     encode_varint)
+T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
+T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
+T(bool,     bool,     bool,         encode_varint)
+T(uint32,   uint32_t, uint32_t,     encode_varint)
+T(uint64,   uint64_t, uint64_t,     encode_varint)
+T(enum,     int32_t,  uint32_t,     encode_varint)
+T(sfixed32, int32_t,  uint32_t,     encode_fixed32)
+T(sfixed64, int64_t,  uint64_t,     encode_fixed64)
+T(sint32,   int32_t,  upb_zzenc_32, encode_varint)
+T(sint64,   int64_t,  upb_zzenc_64, encode_varint)
+
+#undef T
+
+
+/* code to build the handlers *************************************************/
+
+static void newhandlers_callback(const void *closure, upb_handlers *h) {
+  const upb_msgdef *m;
+  upb_msg_field_iter i;
+
+  UPB_UNUSED(closure);
+
+  upb_handlers_setstartmsg(h, startmsg, NULL);
+  upb_handlers_setendmsg(h, endmsg, NULL);
+
+  m = upb_handlers_msgdef(h);
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
+                  upb_fielddef_packed(f);
+    upb_handlerattr attr;
+    upb_wiretype_t wt =
+        packed ? UPB_WIRE_TYPE_DELIMITED
+               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
+
+    /* Pre-encode the tag for this field. */
+    new_tag(h, f, wt, &attr);
+
+    if (packed) {
+      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
+      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
+    }
+
+#define T(upper, lower, upbtype)                                     \
+  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
+    if (packed) {                                                    \
+      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
+    } else {                                                         \
+      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
+    }                                                                \
+    break;
+
+    switch (upb_fielddef_descriptortype(f)) {
+      T(DOUBLE,   double,   double);
+      T(FLOAT,    float,    float);
+      T(INT64,    int64,    int64);
+      T(INT32,    int32,    int32);
+      T(FIXED64,  fixed64,  uint64);
+      T(FIXED32,  fixed32,  uint32);
+      T(BOOL,     bool,     bool);
+      T(UINT32,   uint32,   uint32);
+      T(UINT64,   uint64,   uint64);
+      T(ENUM,     enum,     int32);
+      T(SFIXED32, sfixed32, int32);
+      T(SFIXED64, sfixed64, int64);
+      T(SINT32,   sint32,   int32);
+      T(SINT64,   sint64,   int64);
+      case UPB_DESCRIPTOR_TYPE_STRING:
+      case UPB_DESCRIPTOR_TYPE_BYTES:
+        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
+        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
+        upb_handlers_setstring(h, f, encode_strbuf, &attr);
+        break;
+      case UPB_DESCRIPTOR_TYPE_MESSAGE:
+        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
+        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
+        break;
+      case UPB_DESCRIPTOR_TYPE_GROUP: {
+        /* Endgroup takes a different tag (wire_type = END_GROUP). */
+        upb_handlerattr attr2;
+        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
+
+        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
+        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
+
+        upb_handlerattr_uninit(&attr2);
+        break;
+      }
+    }
+
+#undef T
+
+    upb_handlerattr_uninit(&attr);
+  }
+}
+
+void upb_pb_encoder_reset(upb_pb_encoder *e) {
+  e->segptr = NULL;
+  e->top = NULL;
+  e->depth = 0;
+}
+
+
+/* public API *****************************************************************/
+
+const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
+                                               const void *owner) {
+  return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL);
+}
+
+upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
+                                      upb_bytessink *output) {
+  const size_t initial_bufsize = 256;
+  const size_t initial_segbufsize = 16;
+  /* TODO(haberman): make this configurable. */
+  const size_t stack_size = 64;
+#ifndef NDEBUG
+  const size_t size_before = upb_env_bytesallocated(env);
+#endif
+
+  upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder));
+  if (!e) return NULL;
+
+  e->buf = upb_env_malloc(env, initial_bufsize);
+  e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf));
+  e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack));
+
+  if (!e->buf || !e->segbuf || !e->stack) {
+    return NULL;
+  }
+
+  e->limit = e->buf + initial_bufsize;
+  e->seglimit = e->segbuf + initial_segbufsize;
+  e->stacklimit = e->stack + stack_size;
+
+  upb_pb_encoder_reset(e);
+  upb_sink_reset(&e->input_, h, e);
+
+  e->env = env;
+  e->output_ = output;
+  e->subc = output->closure;
+  e->ptr = e->buf;
+
+  /* If this fails, increase the value in encoder.h. */
+  assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE);
+  return e;
+}
+
+upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
+
+
+
+upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
+                                 upb_status *status) {
+  /* Create handlers. */
+  const upb_pbdecodermethod *decoder_m;
+  const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h);
+  upb_env env;
+  upb_pbdecodermethodopts opts;
+  upb_pbdecoder *decoder;
+  upb_descreader *reader;
+  bool ok;
+  size_t i;
+  upb_filedef **ret = NULL;
+
+  upb_pbdecodermethodopts_init(&opts, reader_h);
+  decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m);
+
+  upb_env_init(&env);
+  upb_env_reporterrorsto(&env, status);
+
+  reader = upb_descreader_create(&env, reader_h);
+  decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader));
+
+  /* Push input data. */
+  ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder));
+
+  if (!ok) {
+    goto cleanup;
+  }
+
+  ret = upb_gmalloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1));
+
+  if (!ret) {
+    goto cleanup;
+  }
+
+  for (i = 0; i < upb_descreader_filecount(reader); i++) {
+    ret[i] = upb_descreader_file(reader, i);
+    upb_filedef_ref(ret[i], owner);
+  }
+
+  ret[i] = NULL;
+
+cleanup:
+  upb_env_uninit(&env);
+  upb_handlers_unref(reader_h, &reader_h);
+  upb_pbdecodermethod_unref(decoder_m, &decoder_m);
+  return ret;
+}
+/*
+ * upb::pb::TextPrinter
+ *
+ * OPT: This is not optimized at all.  It uses printf() which parses the format
+ * string every time, and it allocates memory for every put.
+ */
+
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+struct upb_textprinter {
+  upb_sink input_;
+  upb_bytessink *output_;
+  int indent_depth_;
+  bool single_line_;
+  void *subc;
+};
+
+#define CHECK(x) if ((x) < 0) goto err;
+
+static const char *shortname(const char *longname) {
+  const char *last = strrchr(longname, '.');
+  return last ? last + 1 : longname;
+}
+
+static int indent(upb_textprinter *p) {
+  int i;
+  if (!p->single_line_)
+    for (i = 0; i < p->indent_depth_; i++)
+      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
+  return 0;
+}
+
+static int endfield(upb_textprinter *p) {
+  const char ch = (p->single_line_ ? ' ' : '\n');
+  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
+  return 0;
+}
+
+static int putescaped(upb_textprinter *p, const char *buf, size_t len,
+                      bool preserve_utf8) {
+  /* Based on CEscapeInternal() from Google's protobuf release. */
+  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
+  const char *end = buf + len;
+
+  /* I think hex is prettier and more useful, but proto2 uses octal; should
+   * investigate whether it can parse hex also. */
+  const bool use_hex = false;
+  bool last_hex_escape = false; /* true if last output char was \xNN */
+
+  for (; buf < end; buf++) {
+    bool is_hex_escape;
+
+    if (dstend - dst < 4) {
+      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
+      dst = dstbuf;
+    }
+
+    is_hex_escape = false;
+    switch (*buf) {
+      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
+      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
+      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
+      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
+      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
+      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
+      default:
+        /* Note that if we emit \xNN and the buf character after that is a hex
+         * digit then that digit must be escaped too to prevent it being
+         * interpreted as part of the character code by C. */
+        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
+            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
+          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
+          is_hex_escape = use_hex;
+          dst += 4;
+        } else {
+          *(dst++) = *buf; break;
+        }
+    }
+    last_hex_escape = is_hex_escape;
+  }
+  /* Flush remaining data. */
+  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
+  return 0;
+}
+
+bool putf(upb_textprinter *p, const char *fmt, ...) {
+  va_list args;
+  va_list args_copy;
+  char *str;
+  int written;
+  int len;
+  bool ok;
+
+  va_start(args, fmt);
+
+  /* Run once to get the length of the string. */
+  _upb_va_copy(args_copy, args);
+  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
+  va_end(args_copy);
+
+  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
+  str = upb_gmalloc(len + 1);
+  if (!str) return false;
+  written = vsprintf(str, fmt, args);
+  va_end(args);
+  UPB_ASSERT_VAR(written, written == len);
+
+  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
+  upb_gfree(str);
+  return ok;
+}
+
+
+/* handlers *******************************************************************/
+
+static bool textprinter_startmsg(void *c, const void *hd) {
+  upb_textprinter *p = c;
+  UPB_UNUSED(hd);
+  if (p->indent_depth_ == 0) {
+    upb_bytessink_start(p->output_, 0, &p->subc);
+  }
+  return true;
+}
+
+static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
+  upb_textprinter *p = c;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(s);
+  if (p->indent_depth_ == 0) {
+    upb_bytessink_end(p->output_);
+  }
+  return true;
+}
+
+#define TYPE(name, ctype, fmt) \
+  static bool textprinter_put ## name(void *closure, const void *handler_data, \
+                                      ctype val) {                             \
+    upb_textprinter *p = closure;                                              \
+    const upb_fielddef *f = handler_data;                                      \
+    CHECK(indent(p));                                                          \
+    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
+    CHECK(endfield(p));                                                        \
+    return true;                                                               \
+  err:                                                                         \
+    return false;                                                              \
+}
+
+static bool textprinter_putbool(void *closure, const void *handler_data,
+                                bool val) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  CHECK(indent(p));
+  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
+  CHECK(endfield(p));
+  return true;
+err:
+  return false;
+}
+
+#define STRINGIFY_HELPER(x) #x
+#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
+
+TYPE(int32,  int32_t,  "%" PRId32)
+TYPE(int64,  int64_t,  "%" PRId64)
+TYPE(uint32, uint32_t, "%" PRIu32)
+TYPE(uint64, uint64_t, "%" PRIu64)
+TYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
+TYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
+
+#undef TYPE
+
+/* Output a symbolic value from the enum if found, else just print as int32. */
+static bool textprinter_putenum(void *closure, const void *handler_data,
+                                int32_t val) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
+  const char *label = upb_enumdef_iton(enum_def, val);
+  if (label) {
+    indent(p);
+    putf(p, "%s: %s", upb_fielddef_name(f), label);
+    endfield(p);
+  } else {
+    if (!textprinter_putint32(closure, handler_data, val))
+      return false;
+  }
+  return true;
+}
+
+static void *textprinter_startstr(void *closure, const void *handler_data,
+                      size_t size_hint) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = handler_data;
+  UPB_UNUSED(size_hint);
+  indent(p);
+  putf(p, "%s: \"", upb_fielddef_name(f));
+  return p;
+}
+
+static bool textprinter_endstr(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  UPB_UNUSED(handler_data);
+  putf(p, "\"");
+  endfield(p);
+  return true;
+}
+
+static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
+                                 size_t len, const upb_bufhandle *handle) {
+  upb_textprinter *p = closure;
+  const upb_fielddef *f = hd;
+  UPB_UNUSED(handle);
+  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
+  return len;
+err:
+  return 0;
+}
+
+static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  const char *name = handler_data;
+  CHECK(indent(p));
+  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
+  p->indent_depth_++;
+  return p;
+err:
+  return UPB_BREAK;
+}
+
+static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
+  upb_textprinter *p = closure;
+  UPB_UNUSED(handler_data);
+  p->indent_depth_--;
+  CHECK(indent(p));
+  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
+  CHECK(endfield(p));
+  return true;
+err:
+  return false;
+}
+
+static void onmreg(const void *c, upb_handlers *h) {
+  const upb_msgdef *m = upb_handlers_msgdef(h);
+  upb_msg_field_iter i;
+  UPB_UNUSED(c);
+
+  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
+  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
+
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    upb_fielddef *f = upb_msg_iter_field(&i);
+    upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+    upb_handlerattr_sethandlerdata(&attr, f);
+    switch (upb_fielddef_type(f)) {
+      case UPB_TYPE_INT32:
+        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
+        break;
+      case UPB_TYPE_INT64:
+        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
+        break;
+      case UPB_TYPE_UINT32:
+        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
+        break;
+      case UPB_TYPE_UINT64:
+        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
+        break;
+      case UPB_TYPE_FLOAT:
+        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
+        break;
+      case UPB_TYPE_DOUBLE:
+        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
+        break;
+      case UPB_TYPE_BOOL:
+        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
+        break;
+      case UPB_TYPE_STRING:
+      case UPB_TYPE_BYTES:
+        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
+        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
+        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
+        break;
+      case UPB_TYPE_MESSAGE: {
+        const char *name =
+            upb_fielddef_istagdelim(f)
+                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
+                : upb_fielddef_name(f);
+        upb_handlerattr_sethandlerdata(&attr, name);
+        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
+        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
+        break;
+      }
+      case UPB_TYPE_ENUM:
+        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
+        break;
+    }
+  }
+}
+
+static void textprinter_reset(upb_textprinter *p, bool single_line) {
+  p->single_line_ = single_line;
+  p->indent_depth_ = 0;
+}
+
+
+/* Public API *****************************************************************/
+
+upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
+                                        upb_bytessink *output) {
+  upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter));
+  if (!p) return NULL;
+
+  p->output_ = output;
+  upb_sink_reset(&p->input_, h, p);
+  textprinter_reset(p, false);
+
+  return p;
+}
+
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+                                                const void *owner) {
+  return upb_handlers_newfrozen(m, owner, &onmreg, NULL);
+}
+
+upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
+
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
+  p->single_line_ = single_line;
+}
+
+
+/* Index is descriptor type. */
+const uint8_t upb_pb_native_wire_types[] = {
+  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
+  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
+  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
+  UPB_WIRE_TYPE_VARINT,        /* INT64 */
+  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
+  UPB_WIRE_TYPE_VARINT,        /* INT32 */
+  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
+  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
+  UPB_WIRE_TYPE_VARINT,        /* BOOL */
+  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
+  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
+  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
+  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
+  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
+  UPB_WIRE_TYPE_VARINT,        /* ENUM */
+  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
+  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
+  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
+  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
+};
+
+/* A basic branch-based decoder, uses 32-bit values to get good performance
+ * on 32-bit architectures (but performs well on 64-bits also).
+ * This scheme comes from the original Google Protobuf implementation
+ * (proto2). */
+upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
+  upb_decoderet err = {NULL, 0};
+  const char *p = r.p;
+  uint32_t low = (uint32_t)r.val;
+  uint32_t high = 0;
+  uint32_t b;
+  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
+  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
+  b = *(p++); low  |= (b & 0x7fU) << 28;
+              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
+  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
+  return err;
+
+done:
+  r.val = ((uint64_t)high << 32) | low;
+  r.p = p;
+  return r;
+}
+
+/* Like the previous, but uses 64-bit values. */
+upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
+  const char *p = r.p;
+  uint64_t val = r.val;
+  uint64_t b;
+  upb_decoderet err = {NULL, 0};
+  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
+  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
+  return err;
+
+done:
+  r.val = val;
+  r.p = p;
+  return r;
+}
+
+/* Given an encoded varint v, returns an integer with a single bit set that
+ * indicates the end of the varint.  Subtracting one from this value will
+ * yield a mask that leaves only bits that are part of the varint.  Returns
+ * 0 if the varint is unterminated. */
+static uint64_t upb_get_vstopbit(uint64_t v) {
+  uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
+  return ~cbits & (cbits+1);
+}
+
+/* A branchless decoder.  Credit to Pascal Massimino for the bit-twiddling. */
+upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
+  uint64_t b;
+  uint64_t stop_bit;
+  upb_decoderet my_r;
+  memcpy(&b, r.p, sizeof(b));
+  stop_bit = upb_get_vstopbit(b);
+  b =  (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
+  b +=       b & 0x007f007f007f007fULL;
+  b +=  3 * (b & 0x0000ffff0000ffffULL);
+  b += 15 * (b & 0x00000000ffffffffULL);
+  if (stop_bit == 0) {
+    /* Error: unterminated varint. */
+    upb_decoderet err_r = {(void*)0, 0};
+    return err_r;
+  }
+  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
+                            r.val | (b << 7));
+  return my_r;
+}
+
+/* A branchless decoder.  Credit to Daniel Wright for the bit-twiddling. */
+upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
+  uint64_t b;
+  uint64_t stop_bit;
+  upb_decoderet my_r;
+  memcpy(&b, r.p, sizeof(b));
+  stop_bit = upb_get_vstopbit(b);
+  b &= (stop_bit - 1);
+  b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
+  b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
+  b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
+  if (stop_bit == 0) {
+    /* Error: unterminated varint. */
+    upb_decoderet err_r = {(void*)0, 0};
+    return err_r;
+  }
+  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
+                            r.val | (b << 14));
+  return my_r;
+}
+
+#line 1 "upb/json/parser.rl"
+/*
+** upb::json::Parser (upb_json_parser)
+**
+** A parser that uses the Ragel State Machine Compiler to generate
+** the finite automata.
+**
+** Ragel only natively handles regular languages, but we can manually
+** program it a bit to handle context-free languages like JSON, by using
+** the "fcall" and "fret" constructs.
+**
+** This parser can handle the basics, but needs several things to be fleshed
+** out:
+**
+** - handling of unicode escape sequences (including high surrogate pairs).
+** - properly check and report errors for unknown fields, stack overflow,
+**   improper array nesting (or lack of nesting).
+** - handling of base64 sequences with padding characters.
+** - handling of push-back (non-success returns from sink functions).
+** - handling of keys/escape-sequences/etc that span input buffers.
+*/
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define UPB_JSON_MAX_DEPTH 64
+
+typedef struct {
+  upb_sink sink;
+
+  /* The current message in which we're parsing, and the field whose value we're
+   * expecting next. */
+  const upb_msgdef *m;
+  const upb_fielddef *f;
+
+  /* The table mapping json name to fielddef for this message. */
+  upb_strtable *name_table;
+
+  /* We are in a repeated-field context, ready to emit mapentries as
+   * submessages. This flag alters the start-of-object (open-brace) behavior to
+   * begin a sequence of mapentry messages rather than a single submessage. */
+  bool is_map;
+
+  /* We are in a map-entry message context. This flag is set when parsing the
+   * value field of a single map entry and indicates to all value-field parsers
+   * (subobjects, strings, numbers, and bools) that the map-entry submessage
+   * should end as soon as the value is parsed. */
+  bool is_mapentry;
+
+  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
+   * message's map field that we're currently parsing. This differs from |f|
+   * because |f| is the field in the *current* message (i.e., the map-entry
+   * message itself), not the parent's field that leads to this map. */
+  const upb_fielddef *mapfield;
+} upb_jsonparser_frame;
+
+struct upb_json_parser {
+  upb_env *env;
+  const upb_json_parsermethod *method;
+  upb_bytessink input_;
+
+  /* Stack to track the JSON scopes we are in. */
+  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
+  upb_jsonparser_frame *top;
+  upb_jsonparser_frame *limit;
+
+  upb_status status;
+
+  /* Ragel's internal parsing stack for the parsing state machine. */
+  int current_state;
+  int parser_stack[UPB_JSON_MAX_DEPTH];
+  int parser_top;
+
+  /* The handle for the current buffer. */
+  const upb_bufhandle *handle;
+
+  /* Accumulate buffer.  See details in parser.rl. */
+  const char *accumulated;
+  size_t accumulated_len;
+  char *accumulate_buf;
+  size_t accumulate_buf_size;
+
+  /* Multi-part text data.  See details in parser.rl. */
+  int multipart_state;
+  upb_selector_t string_selector;
+
+  /* Input capture.  See details in parser.rl. */
+  const char *capture;
+
+  /* Intermediate result of parsing a unicode escape sequence. */
+  uint32_t digit;
+};
+
+struct upb_json_parsermethod {
+  upb_refcounted base;
+
+  upb_byteshandler input_handler_;
+
+  /* Mainly for the purposes of refcounting, so all the fielddefs we point
+   * to stay alive. */
+  const upb_msgdef *msg;
+
+  /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
+  upb_inttable name_tables;
+};
+
+#define PARSER_CHECK_RETURN(x) if (!(x)) return false
+
+/* Used to signal that a capture has been suspended. */
+static char suspend_capture;
+
+static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
+                                             upb_handlertype_t type) {
+  upb_selector_t sel;
+  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
+  UPB_ASSERT_VAR(ok, ok);
+  return sel;
+}
+
+static upb_selector_t parser_getsel(upb_json_parser *p) {
+  return getsel_for_handlertype(
+      p, upb_handlers_getprimitivehandlertype(p->top->f));
+}
+
+static bool check_stack(upb_json_parser *p) {
+  if ((p->top + 1) == p->limit) {
+    upb_status_seterrmsg(&p->status, "Nesting too deep");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  return true;
+}
+
+static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
+  upb_value v;
+  bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
+  UPB_ASSERT_VAR(ok, ok);
+  frame->name_table = upb_value_getptr(v);
+}
+
+/* There are GCC/Clang built-ins for overflow checking which we could start
+ * using if there was any performance benefit to it. */
+
+static bool checked_add(size_t a, size_t b, size_t *c) {
+  if (SIZE_MAX - a < b) return false;
+  *c = a + b;
+  return true;
+}
+
+static size_t saturating_multiply(size_t a, size_t b) {
+  /* size_t is unsigned, so this is defined behavior even on overflow. */
+  size_t ret = a * b;
+  if (b != 0 && ret / b != a) {
+    ret = SIZE_MAX;
+  }
+  return ret;
+}
+
+
+/* Base64 decoding ************************************************************/
+
+/* TODO(haberman): make this streaming. */
+
+static const signed char b64table[] = {
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
+  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
+  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
+  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
+};
+
+/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
+ * bits will be 1 for unrecognized characters makes it easier to check for
+ * this error condition later (see below). */
+int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
+
+/* Returns true if the given character is not a valid base64 character or
+ * padding. */
+bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
+
+static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
+                        size_t len) {
+  const char *limit = ptr + len;
+  for (; ptr < limit; ptr += 4) {
+    uint32_t val;
+    char output[3];
+
+    if (limit - ptr < 4) {
+      upb_status_seterrf(&p->status,
+                         "Base64 input for bytes field not a multiple of 4: %s",
+                         upb_fielddef_name(p->top->f));
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12 |
+          b64lookup(ptr[2]) << 6  |
+          b64lookup(ptr[3]);
+
+    /* Test the upper bit; returns true if any of the characters returned -1. */
+    if (val & 0x80000000) {
+      goto otherchar;
+    }
+
+    output[0] = val >> 16;
+    output[1] = (val >> 8) & 0xff;
+    output[2] = val & 0xff;
+    upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
+  }
+  return true;
+
+otherchar:
+  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
+      nonbase64(ptr[3]) ) {
+    upb_status_seterrf(&p->status,
+                       "Non-base64 characters in bytes field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  } if (ptr[2] == '=') {
+    uint32_t val;
+    char output;
+
+    /* Last group contains only two input bytes, one output byte. */
+    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
+      goto badpadding;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12;
+
+    assert(!(val & 0x80000000));
+    output = val >> 16;
+    upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
+    return true;
+  } else {
+    uint32_t val;
+    char output[2];
+
+    /* Last group contains only three input bytes, two output bytes. */
+    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
+      goto badpadding;
+    }
+
+    val = b64lookup(ptr[0]) << 18 |
+          b64lookup(ptr[1]) << 12 |
+          b64lookup(ptr[2]) << 6;
+
+    output[0] = val >> 16;
+    output[1] = (val >> 8) & 0xff;
+    upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
+    return true;
+  }
+
+badpadding:
+  upb_status_seterrf(&p->status,
+                     "Incorrect base64 padding for field: %s (%.*s)",
+                     upb_fielddef_name(p->top->f),
+                     4, ptr);
+  upb_env_reporterror(p->env, &p->status);
+  return false;
+}
+
+
+/* Accumulate buffer **********************************************************/
+
+/* Functionality for accumulating a buffer.
+ *
+ * Some parts of the parser need an entire value as a contiguous string.  For
+ * example, to look up a member name in a hash table, or to turn a string into
+ * a number, the relevant library routines need the input string to be in
+ * contiguous memory, even if the value spanned two or more buffers in the
+ * input.  These routines handle that.
+ *
+ * In the common case we can just point to the input buffer to get this
+ * contiguous string and avoid any actual copy.  So we optimistically begin
+ * this way.  But there are a few cases where we must instead copy into a
+ * separate buffer:
+ *
+ *   1. The string was not contiguous in the input (it spanned buffers).
+ *
+ *   2. The string included escape sequences that need to be interpreted to get
+ *      the true value in a contiguous buffer. */
+
+static void assert_accumulate_empty(upb_json_parser *p) {
+  UPB_UNUSED(p);
+  assert(p->accumulated == NULL);
+  assert(p->accumulated_len == 0);
+}
+
+static void accumulate_clear(upb_json_parser *p) {
+  p->accumulated = NULL;
+  p->accumulated_len = 0;
+}
+
+/* Used internally by accumulate_append(). */
+static bool accumulate_realloc(upb_json_parser *p, size_t need) {
+  void *mem;
+  size_t old_size = p->accumulate_buf_size;
+  size_t new_size = UPB_MAX(old_size, 128);
+  while (new_size < need) {
+    new_size = saturating_multiply(new_size, 2);
+  }
+
+  mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+  if (!mem) {
+    upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  p->accumulate_buf = mem;
+  p->accumulate_buf_size = new_size;
+  return true;
+}
+
+/* Logically appends the given data to the append buffer.
+ * If "can_alias" is true, we will try to avoid actually copying, but the buffer
+ * must be valid until the next accumulate_append() call (if any). */
+static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
+                              bool can_alias) {
+  size_t need;
+
+  if (!p->accumulated && can_alias) {
+    p->accumulated = buf;
+    p->accumulated_len = len;
+    return true;
+  }
+
+  if (!checked_add(p->accumulated_len, len, &need)) {
+    upb_status_seterrmsg(&p->status, "Integer overflow.");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
+    return false;
+  }
+
+  if (p->accumulated != p->accumulate_buf) {
+    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
+    p->accumulated = p->accumulate_buf;
+  }
+
+  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
+  p->accumulated_len += len;
+  return true;
+}
+
+/* Returns a pointer to the data accumulated since the last accumulate_clear()
+ * call, and writes the length to *len.  This with point either to the input
+ * buffer or a temporary accumulate buffer. */
+static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
+  assert(p->accumulated);
+  *len = p->accumulated_len;
+  return p->accumulated;
+}
+
+
+/* Mult-part text data ********************************************************/
+
+/* When we have text data in the input, it can often come in multiple segments.
+ * For example, there may be some raw string data followed by an escape
+ * sequence.  The two segments are processed with different logic.  Also buffer
+ * seams in the input can cause multiple segments.
+ *
+ * As we see segments, there are two main cases for how we want to process them:
+ *
+ *  1. we want to push the captured input directly to string handlers.
+ *
+ *  2. we need to accumulate all the parts into a contiguous buffer for further
+ *     processing (field name lookup, string->number conversion, etc). */
+
+/* This is the set of states for p->multipart_state. */
+enum {
+  /* We are not currently processing multipart data. */
+  MULTIPART_INACTIVE = 0,
+
+  /* We are processing multipart data by accumulating it into a contiguous
+   * buffer. */
+  MULTIPART_ACCUMULATE = 1,
+
+  /* We are processing multipart data by pushing each part directly to the
+   * current string handlers. */
+  MULTIPART_PUSHEAGERLY = 2
+};
+
+/* Start a multi-part text value where we accumulate the data for processing at
+ * the end. */
+static void multipart_startaccum(upb_json_parser *p) {
+  assert_accumulate_empty(p);
+  assert(p->multipart_state == MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_ACCUMULATE;
+}
+
+/* Start a multi-part text value where we immediately push text data to a string
+ * value with the given selector. */
+static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
+  assert_accumulate_empty(p);
+  assert(p->multipart_state == MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_PUSHEAGERLY;
+  p->string_selector = sel;
+}
+
+static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
+                           bool can_alias) {
+  switch (p->multipart_state) {
+    case MULTIPART_INACTIVE:
+      upb_status_seterrmsg(
+          &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+
+    case MULTIPART_ACCUMULATE:
+      if (!accumulate_append(p, buf, len, can_alias)) {
+        return false;
+      }
+      break;
+
+    case MULTIPART_PUSHEAGERLY: {
+      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
+      upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
+      break;
+    }
+  }
+
+  return true;
+}
+
+/* Note: this invalidates the accumulate buffer!  Call only after reading its
+ * contents. */
+static void multipart_end(upb_json_parser *p) {
+  assert(p->multipart_state != MULTIPART_INACTIVE);
+  p->multipart_state = MULTIPART_INACTIVE;
+  accumulate_clear(p);
+}
+
+
+/* Input capture **************************************************************/
+
+/* Functionality for capturing a region of the input as text.  Gracefully
+ * handles the case where a buffer seam occurs in the middle of the captured
+ * region. */
+
+static void capture_begin(upb_json_parser *p, const char *ptr) {
+  assert(p->multipart_state != MULTIPART_INACTIVE);
+  assert(p->capture == NULL);
+  p->capture = ptr;
+}
+
+static bool capture_end(upb_json_parser *p, const char *ptr) {
+  assert(p->capture);
+  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
+    p->capture = NULL;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* This is called at the end of each input buffer (ie. when we have hit a
+ * buffer seam).  If we are in the middle of capturing the input, this
+ * processes the unprocessed capture region. */
+static void capture_suspend(upb_json_parser *p, const char **ptr) {
+  if (!p->capture) return;
+
+  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
+    /* We use this as a signal that we were in the middle of capturing, and
+     * that capturing should resume at the beginning of the next buffer.
+     * 
+     * We can't use *ptr here, because we have no guarantee that this pointer
+     * will be valid when we resume (if the underlying memory is freed, then
+     * using the pointer at all, even to compare to NULL, is likely undefined
+     * behavior). */
+    p->capture = &suspend_capture;
+  } else {
+    /* Need to back up the pointer to the beginning of the capture, since
+     * we were not able to actually preserve it. */
+    *ptr = p->capture;
+  }
+}
+
+static void capture_resume(upb_json_parser *p, const char *ptr) {
+  if (p->capture) {
+    assert(p->capture == &suspend_capture);
+    p->capture = ptr;
+  }
+}
+
+
+/* Callbacks from the parser **************************************************/
+
+/* These are the functions called directly from the parser itself.
+ * We define these in the same order as their declarations in the parser. */
+
+static char escape_char(char in) {
+  switch (in) {
+    case 'r': return '\r';
+    case 't': return '\t';
+    case 'n': return '\n';
+    case 'f': return '\f';
+    case 'b': return '\b';
+    case '/': return '/';
+    case '"': return '"';
+    case '\\': return '\\';
+    default:
+      assert(0);
+      return 'x';
+  }
+}
+
+static bool escape(upb_json_parser *p, const char *ptr) {
+  char ch = escape_char(*ptr);
+  return multipart_text(p, &ch, 1, false);
+}
+
+static void start_hex(upb_json_parser *p) {
+  p->digit = 0;
+}
+
+static void hexdigit(upb_json_parser *p, const char *ptr) {
+  char ch = *ptr;
+
+  p->digit <<= 4;
+
+  if (ch >= '0' && ch <= '9') {
+    p->digit += (ch - '0');
+  } else if (ch >= 'a' && ch <= 'f') {
+    p->digit += ((ch - 'a') + 10);
+  } else {
+    assert(ch >= 'A' && ch <= 'F');
+    p->digit += ((ch - 'A') + 10);
+  }
+}
+
+static bool end_hex(upb_json_parser *p) {
+  uint32_t codepoint = p->digit;
+
+  /* emit the codepoint as UTF-8. */
+  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
+  int length = 0;
+  if (codepoint <= 0x7F) {
+    utf8[0] = codepoint;
+    length = 1;
+  } else if (codepoint <= 0x07FF) {
+    utf8[1] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[0] = (codepoint & 0x1F) | 0xC0;
+    length = 2;
+  } else /* codepoint <= 0xFFFF */ {
+    utf8[2] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[1] = (codepoint & 0x3F) | 0x80;
+    codepoint >>= 6;
+    utf8[0] = (codepoint & 0x0F) | 0xE0;
+    length = 3;
+  }
+  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
+   * we have to wait for the next escape to get the full code point). */
+
+  return multipart_text(p, utf8, length, false);
+}
+
+static void start_text(upb_json_parser *p, const char *ptr) {
+  capture_begin(p, ptr);
+}
+
+static bool end_text(upb_json_parser *p, const char *ptr) {
+  return capture_end(p, ptr);
+}
+
+static void start_number(upb_json_parser *p, const char *ptr) {
+  multipart_startaccum(p);
+  capture_begin(p, ptr);
+}
+
+static bool parse_number(upb_json_parser *p);
+
+static bool end_number(upb_json_parser *p, const char *ptr) {
+  if (!capture_end(p, ptr)) {
+    return false;
+  }
+
+  return parse_number(p);
+}
+
+static bool parse_number(upb_json_parser *p) {
+  size_t len;
+  const char *buf;
+  const char *myend;
+  char *end;
+
+  /* strtol() and friends unfortunately do not support specifying the length of
+   * the input string, so we need to force a copy into a NULL-terminated buffer. */
+  if (!multipart_text(p, "\0", 1, false)) {
+    return false;
+  }
+
+  buf = accumulate_getptr(p, &len);
+  myend = buf + len - 1;  /* One for NULL. */
+
+  /* XXX: We are using strtol to parse integers, but this is wrong as even
+   * integers can be represented as 1e6 (for example), which strtol can't
+   * handle correctly.
+   *
+   * XXX: Also, we can't handle large integers properly because strto[u]ll
+   * isn't in C89.
+   *
+   * XXX: Also, we don't properly check floats for overflow, since strtof
+   * isn't in C89. */
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32: {
+      long val = strtol(p->accumulated, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      long long val = strtol(p->accumulated, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(p->accumulated, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      unsigned long long val = strtoul(p->accumulated, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(p->accumulated, &end);
+      if (errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      float val = strtod(p->accumulated, &end);
+      if (errno == ERANGE || end != myend)
+        goto err;
+      else
+        upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
+      break;
+    }
+    default:
+      assert(false);
+  }
+
+  multipart_end(p);
+
+  return true;
+
+err:
+  upb_status_seterrf(&p->status, "error parsing number: %s", buf);
+  upb_env_reporterror(p->env, &p->status);
+  multipart_end(p);
+  return false;
+}
+
+static bool parser_putbool(upb_json_parser *p, bool val) {
+  bool ok;
+
+  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
+    upb_status_seterrf(&p->status,
+                       "Boolean value specified for non-bool field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+  UPB_ASSERT_VAR(ok, ok);
+
+  return true;
+}
+
+static bool start_stringval(upb_json_parser *p) {
+  assert(p->top->f);
+
+  if (upb_fielddef_isstring(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    if (!check_stack(p)) return false;
+
+    /* Start a new parser frame: parser frames correspond one-to-one with
+     * handler frames, and string events occur in a sub-frame. */
+    inner = p->top + 1;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+    upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+    inner->m = p->top->m;
+    inner->f = p->top->f;
+    inner->name_table = NULL;
+    inner->is_map = false;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
+      /* For STRING fields we push data directly to the handlers as it is
+       * parsed.  We don't do this yet for BYTES fields, because our base64
+       * decoder is not streaming.
+       *
+       * TODO(haberman): make base64 decoding streaming also. */
+      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
+      return true;
+    } else {
+      multipart_startaccum(p);
+      return true;
+    }
+  } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
+    /* No need to push a frame -- symbolic enum names in quotes remain in the
+     * current parser frame.
+     *
+     * Enum string values must accumulate so we can look up the value in a table
+     * once it is complete. */
+    multipart_startaccum(p);
+    return true;
+  } else {
+    upb_status_seterrf(&p->status,
+                       "String specified for non-string/non-enum field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+}
+
+static bool end_stringval(upb_json_parser *p) {
+  bool ok = true;
+
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_BYTES:
+      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
+                       p->accumulated, p->accumulated_len)) {
+        return false;
+      }
+      /* Fall through. */
+
+    case UPB_TYPE_STRING: {
+      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
+      upb_sink_endstr(&p->top->sink, sel);
+      p->top--;
+      break;
+    }
+
+    case UPB_TYPE_ENUM: {
+      /* Resolve enum symbolic name to integer value. */
+      const upb_enumdef *enumdef =
+          (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
+
+      size_t len;
+      const char *buf = accumulate_getptr(p, &len);
+
+      int32_t int_val = 0;
+      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
+
+      if (ok) {
+        upb_selector_t sel = parser_getsel(p);
+        upb_sink_putint32(&p->top->sink, sel, int_val);
+      } else {
+        upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
+        upb_env_reporterror(p->env, &p->status);
+      }
+
+      break;
+    }
+
+    default:
+      assert(false);
+      upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
+      upb_env_reporterror(p->env, &p->status);
+      ok = false;
+      break;
+  }
+
+  multipart_end(p);
+
+  return ok;
+}
+
+static void start_member(upb_json_parser *p) {
+  assert(!p->top->f);
+  multipart_startaccum(p);
+}
+
+/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
+ * field based on the current contents of the accumulate buffer. */
+static bool parse_mapentry_key(upb_json_parser *p) {
+
+  size_t len;
+  const char *buf = accumulate_getptr(p, &len);
+
+  /* Emit the key field. We do a bit of ad-hoc parsing here because the
+   * parser state machine has already decided that this is a string field
+   * name, and we are reinterpreting it as some arbitrary key type. In
+   * particular, integer and bool keys are quoted, so we need to parse the
+   * quoted string contents here. */
+
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(&p->status, "mapentry message has no key");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+  switch (upb_fielddef_type(p->top->f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      /* Invoke end_number. The accum buffer has the number's text already. */
+      if (!parse_number(p)) {
+        return false;
+      }
+      break;
+    case UPB_TYPE_BOOL:
+      if (len == 4 && !strncmp(buf, "true", 4)) {
+        if (!parser_putbool(p, true)) {
+          return false;
+        }
+      } else if (len == 5 && !strncmp(buf, "false", 5)) {
+        if (!parser_putbool(p, false)) {
+          return false;
+        }
+      } else {
+        upb_status_seterrmsg(&p->status,
+                             "Map bool key not 'true' or 'false'");
+        upb_env_reporterror(p->env, &p->status);
+        return false;
+      }
+      multipart_end(p);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      upb_sink subsink;
+      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+      upb_sink_startstr(&p->top->sink, sel, len, &subsink);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
+      upb_sink_putstring(&subsink, sel, buf, len, NULL);
+      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
+      upb_sink_endstr(&subsink, sel);
+      multipart_end(p);
+      break;
+    }
+    default:
+      upb_status_seterrmsg(&p->status, "Invalid field type for map key");
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+  }
+
+  return true;
+}
+
+/* Helper: emit one map entry (as a submessage in the map field sequence). This
+ * is invoked from end_membername(), at the end of the map entry's key string,
+ * with the map key in the accumulate buffer. It parses the key from that
+ * buffer, emits the handler calls to start the mapentry submessage (setting up
+ * its subframe in the process), and sets up state in the subframe so that the
+ * value parser (invoked next) will emit the mapentry's value field and then
+ * end the mapentry message. */
+
+static bool handle_mapentry(upb_json_parser *p) {
+  const upb_fielddef *mapfield;
+  const upb_msgdef *mapentrymsg;
+  upb_jsonparser_frame *inner;
+  upb_selector_t sel;
+
+  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
+   * for the mapentry itself, and then set |f| in that frame so that the map
+   * value field is parsed, and also set a flag to end the frame after the
+   * map-entry value is parsed. */
+  if (!check_stack(p)) return false;
+
+  mapfield = p->top->mapfield;
+  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
+
+  inner = p->top + 1;
+  p->top->f = mapfield;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+  upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+  inner->m = mapentrymsg;
+  inner->name_table = NULL;
+  inner->mapfield = mapfield;
+  inner->is_map = false;
+
+  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
+   * the key field value to the sink, and these handlers will pop the frame
+   * if they see is_mapentry (when invoked by the parser state machine, they
+   * would have just seen the map-entry value, not key). */
+  inner->is_mapentry = false;
+  p->top = inner;
+
+  /* send STARTMSG in submsg frame. */
+  upb_sink_startmsg(&p->top->sink);
+
+  parse_mapentry_key(p);
+
+  /* Set up the value field to receive the map-entry value. */
+  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
+  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
+  p->top->mapfield = mapfield;
+  if (p->top->f == NULL) {
+    upb_status_seterrmsg(&p->status, "mapentry message has no value");
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  return true;
+}
+
+static bool end_membername(upb_json_parser *p) {
+  assert(!p->top->f);
+
+  if (p->top->is_map) {
+    return handle_mapentry(p);
+  } else {
+    size_t len;
+    const char *buf = accumulate_getptr(p, &len);
+    upb_value v;
+
+    if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
+      p->top->f = upb_value_getconstptr(v);
+      multipart_end(p);
+
+      return true;
+    } else {
+      /* TODO(haberman): Ignore unknown fields if requested/configured to do
+       * so. */
+      upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
+      upb_env_reporterror(p->env, &p->status);
+      return false;
+    }
+  }
+}
+
+static void end_member(upb_json_parser *p) {
+  /* If we just parsed a map-entry value, end that frame too. */
+  if (p->top->is_mapentry) {
+    upb_status s = UPB_STATUS_INIT;
+    upb_selector_t sel;
+    bool ok;
+    const upb_fielddef *mapfield;
+
+    assert(p->top > p->stack);
+    /* send ENDMSG on submsg. */
+    upb_sink_endmsg(&p->top->sink, &s);
+    mapfield = p->top->mapfield;
+
+    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
+    p->top--;
+    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
+    UPB_ASSERT_VAR(ok, ok);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
+
+  p->top->f = NULL;
+}
+
+static bool start_subobject(upb_json_parser *p) {
+  assert(p->top->f);
+
+  if (upb_fielddef_ismap(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    /* Beginning of a map. Start a new parser frame in a repeated-field
+     * context. */
+    if (!check_stack(p)) return false;
+
+    inner = p->top + 1;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+    upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    inner->name_table = NULL;
+    inner->mapfield = p->top->f;
+    inner->f = NULL;
+    inner->is_map = true;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else if (upb_fielddef_issubmsg(p->top->f)) {
+    upb_jsonparser_frame *inner;
+    upb_selector_t sel;
+
+    /* Beginning of a subobject. Start a new parser frame in the submsg
+     * context. */
+    if (!check_stack(p)) return false;
+
+    inner = p->top + 1;
+
+    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+    upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+    inner->m = upb_fielddef_msgsubdef(p->top->f);
+    set_name_table(p, inner);
+    inner->f = NULL;
+    inner->is_map = false;
+    inner->is_mapentry = false;
+    p->top = inner;
+
+    return true;
+  } else {
+    upb_status_seterrf(&p->status,
+                       "Object specified for non-message/group field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+}
+
+static void end_subobject(upb_json_parser *p) {
+  if (p->top->is_map) {
+    upb_selector_t sel;
+    p->top--;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+    upb_sink_endseq(&p->top->sink, sel);
+  } else {
+    upb_selector_t sel;
+    p->top--;
+    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
+    upb_sink_endsubmsg(&p->top->sink, sel);
+  }
+}
+
+static bool start_array(upb_json_parser *p) {
+  upb_jsonparser_frame *inner;
+  upb_selector_t sel;
+
+  assert(p->top->f);
+
+  if (!upb_fielddef_isseq(p->top->f)) {
+    upb_status_seterrf(&p->status,
+                       "Array specified for non-repeated field: %s",
+                       upb_fielddef_name(p->top->f));
+    upb_env_reporterror(p->env, &p->status);
+    return false;
+  }
+
+  if (!check_stack(p)) return false;
+
+  inner = p->top + 1;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+  upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+  inner->m = p->top->m;
+  inner->name_table = NULL;
+  inner->f = p->top->f;
+  inner->is_map = false;
+  inner->is_mapentry = false;
+  p->top = inner;
+
+  return true;
+}
+
+static void end_array(upb_json_parser *p) {
+  upb_selector_t sel;
+
+  assert(p->top > p->stack);
+
+  p->top--;
+  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+  upb_sink_endseq(&p->top->sink, sel);
+}
+
+static void start_object(upb_json_parser *p) {
+  if (!p->top->is_map) {
+    upb_sink_startmsg(&p->top->sink);
+  }
+}
+
+static void end_object(upb_json_parser *p) {
+  if (!p->top->is_map) {
+    upb_status status;
+    upb_status_clear(&status);
+    upb_sink_endmsg(&p->top->sink, &status);
+    if (!upb_ok(&status)) {
+      upb_env_reporterror(p->env, &status);
+    }
+  }
+}
+
+
+#define CHECK_RETURN_TOP(x) if (!(x)) goto error
+
+
+/* The actual parser **********************************************************/
+
+/* What follows is the Ragel parser itself.  The language is specified in Ragel
+ * and the actions call our C functions above.
+ *
+ * Ragel has an extensive set of functionality, and we use only a small part of
+ * it.  There are many action types but we only use a few:
+ *
+ *   ">" -- transition into a machine
+ *   "%" -- transition out of a machine
+ *   "@" -- transition into a final state of a machine.
+ *
+ * "@" transitions are tricky because a machine can transition into a final
+ * state repeatedly.  But in some cases we know this can't happen, for example
+ * a string which is delimited by a final '"' can only transition into its
+ * final state once, when the closing '"' is seen. */
+
+
+#line 1245 "upb/json/parser.rl"
+
+
+
+#line 1157 "upb/json/parser.c"
+static const char _json_actions[] = {
+	0, 1, 0, 1, 2, 1, 3, 1, 
+	5, 1, 6, 1, 7, 1, 8, 1, 
+	10, 1, 12, 1, 13, 1, 14, 1, 
+	15, 1, 16, 1, 17, 1, 21, 1, 
+	25, 1, 27, 2, 3, 8, 2, 4, 
+	5, 2, 6, 2, 2, 6, 8, 2, 
+	11, 9, 2, 13, 15, 2, 14, 15, 
+	2, 18, 1, 2, 19, 27, 2, 20, 
+	9, 2, 22, 27, 2, 23, 27, 2, 
+	24, 27, 2, 26, 27, 3, 14, 11, 
+	9
+};
+
+static const unsigned char _json_key_offsets[] = {
+	0, 0, 4, 9, 14, 15, 19, 24, 
+	29, 34, 38, 42, 45, 48, 50, 54, 
+	58, 60, 62, 67, 69, 71, 80, 86, 
+	92, 98, 104, 106, 115, 116, 116, 116, 
+	121, 126, 131, 132, 133, 134, 135, 135, 
+	136, 137, 138, 138, 139, 140, 141, 141, 
+	146, 151, 152, 156, 161, 166, 171, 175, 
+	175, 178, 178, 178
+};
+
+static const char _json_trans_keys[] = {
+	32, 123, 9, 13, 32, 34, 125, 9, 
+	13, 32, 34, 125, 9, 13, 34, 32, 
+	58, 9, 13, 32, 93, 125, 9, 13, 
+	32, 44, 125, 9, 13, 32, 44, 125, 
+	9, 13, 32, 34, 9, 13, 45, 48, 
+	49, 57, 48, 49, 57, 46, 69, 101, 
+	48, 57, 69, 101, 48, 57, 43, 45, 
+	48, 57, 48, 57, 48, 57, 46, 69, 
+	101, 48, 57, 34, 92, 34, 92, 34, 
+	47, 92, 98, 102, 110, 114, 116, 117, 
+	48, 57, 65, 70, 97, 102, 48, 57, 
+	65, 70, 97, 102, 48, 57, 65, 70, 
+	97, 102, 48, 57, 65, 70, 97, 102, 
+	34, 92, 34, 45, 91, 102, 110, 116, 
+	123, 48, 57, 34, 32, 93, 125, 9, 
+	13, 32, 44, 93, 9, 13, 32, 93, 
+	125, 9, 13, 97, 108, 115, 101, 117, 
+	108, 108, 114, 117, 101, 32, 34, 125, 
+	9, 13, 32, 34, 125, 9, 13, 34, 
+	32, 58, 9, 13, 32, 93, 125, 9, 
+	13, 32, 44, 125, 9, 13, 32, 44, 
+	125, 9, 13, 32, 34, 9, 13, 32, 
+	9, 13, 0
+};
+
+static const char _json_single_lengths[] = {
+	0, 2, 3, 3, 1, 2, 3, 3, 
+	3, 2, 2, 1, 3, 0, 2, 2, 
+	0, 0, 3, 2, 2, 9, 0, 0, 
+	0, 0, 2, 7, 1, 0, 0, 3, 
+	3, 3, 1, 1, 1, 1, 0, 1, 
+	1, 1, 0, 1, 1, 1, 0, 3, 
+	3, 1, 2, 3, 3, 3, 2, 0, 
+	1, 0, 0, 0
+};
+
+static const char _json_range_lengths[] = {
+	0, 1, 1, 1, 0, 1, 1, 1, 
+	1, 1, 1, 1, 0, 1, 1, 1, 
+	1, 1, 1, 0, 0, 0, 3, 3, 
+	3, 3, 0, 1, 0, 0, 0, 1, 
+	1, 1, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 1, 
+	1, 0, 1, 1, 1, 1, 1, 0, 
+	1, 0, 0, 0
+};
+
+static const short _json_index_offsets[] = {
+	0, 0, 4, 9, 14, 16, 20, 25, 
+	30, 35, 39, 43, 46, 50, 52, 56, 
+	60, 62, 64, 69, 72, 75, 85, 89, 
+	93, 97, 101, 104, 113, 115, 116, 117, 
+	122, 127, 132, 134, 136, 138, 140, 141, 
+	143, 145, 147, 148, 150, 152, 154, 155, 
+	160, 165, 167, 171, 176, 181, 186, 190, 
+	191, 194, 195, 196
+};
+
+static const char _json_indicies[] = {
+	0, 2, 0, 1, 3, 4, 5, 3, 
+	1, 6, 7, 8, 6, 1, 9, 1, 
+	10, 11, 10, 1, 11, 1, 1, 11, 
+	12, 13, 14, 15, 13, 1, 16, 17, 
+	8, 16, 1, 17, 7, 17, 1, 18, 
+	19, 20, 1, 19, 20, 1, 22, 23, 
+	23, 21, 24, 1, 23, 23, 24, 21, 
+	25, 25, 26, 1, 26, 1, 26, 21, 
+	22, 23, 23, 20, 21, 28, 29, 27, 
+	31, 32, 30, 33, 33, 33, 33, 33, 
+	33, 33, 33, 34, 1, 35, 35, 35, 
+	1, 36, 36, 36, 1, 37, 37, 37, 
+	1, 38, 38, 38, 1, 40, 41, 39, 
+	42, 43, 44, 45, 46, 47, 48, 43, 
+	1, 49, 1, 50, 51, 53, 54, 1, 
+	53, 52, 55, 56, 54, 55, 1, 56, 
+	1, 1, 56, 52, 57, 1, 58, 1, 
+	59, 1, 60, 1, 61, 62, 1, 63, 
+	1, 64, 1, 65, 66, 1, 67, 1, 
+	68, 1, 69, 70, 71, 72, 70, 1, 
+	73, 74, 75, 73, 1, 76, 1, 77, 
+	78, 77, 1, 78, 1, 1, 78, 79, 
+	80, 81, 82, 80, 1, 83, 84, 75, 
+	83, 1, 84, 74, 84, 1, 85, 86, 
+	86, 1, 1, 1, 1, 0
+};
+
+static const char _json_trans_targs[] = {
+	1, 0, 2, 3, 4, 56, 3, 4, 
+	56, 5, 5, 6, 7, 8, 9, 56, 
+	8, 9, 11, 12, 18, 57, 13, 15, 
+	14, 16, 17, 20, 58, 21, 20, 58, 
+	21, 19, 22, 23, 24, 25, 26, 20, 
+	58, 21, 28, 30, 31, 34, 39, 43, 
+	47, 29, 59, 59, 32, 31, 29, 32, 
+	33, 35, 36, 37, 38, 59, 40, 41, 
+	42, 59, 44, 45, 46, 59, 48, 49, 
+	55, 48, 49, 55, 50, 50, 51, 52, 
+	53, 54, 55, 53, 54, 59, 56
+};
+
+static const char _json_trans_actions[] = {
+	0, 0, 0, 21, 77, 53, 0, 47, 
+	23, 17, 0, 0, 15, 19, 19, 50, 
+	0, 0, 0, 0, 0, 1, 0, 0, 
+	0, 0, 0, 3, 13, 0, 0, 35, 
+	5, 11, 0, 38, 7, 7, 7, 41, 
+	44, 9, 62, 56, 25, 0, 0, 0, 
+	31, 29, 33, 59, 15, 0, 27, 0, 
+	0, 0, 0, 0, 0, 68, 0, 0, 
+	0, 71, 0, 0, 0, 65, 21, 77, 
+	53, 0, 47, 23, 17, 0, 0, 15, 
+	19, 19, 50, 0, 0, 74, 0
+};
+
+static const int json_start = 1;
+
+static const int json_en_number_machine = 10;
+static const int json_en_string_machine = 19;
+static const int json_en_value_machine = 27;
+static const int json_en_main = 1;
+
+
+#line 1248 "upb/json/parser.rl"
+
+size_t parse(void *closure, const void *hd, const char *buf, size_t size,
+             const upb_bufhandle *handle) {
+  upb_json_parser *parser = closure;
+
+  /* Variables used by Ragel's generated code. */
+  int cs = parser->current_state;
+  int *stack = parser->parser_stack;
+  int top = parser->parser_top;
+
+  const char *p = buf;
+  const char *pe = buf + size;
+
+  parser->handle = handle;
+
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  capture_resume(parser, buf);
+
+  
+#line 1328 "upb/json/parser.c"
+	{
+	int _klen;
+	unsigned int _trans;
+	const char *_acts;
+	unsigned int _nacts;
+	const char *_keys;
+
+	if ( p == pe )
+		goto _test_eof;
+	if ( cs == 0 )
+		goto _out;
+_resume:
+	_keys = _json_trans_keys + _json_key_offsets[cs];
+	_trans = _json_index_offsets[cs];
+
+	_klen = _json_single_lengths[cs];
+	if ( _klen > 0 ) {
+		const char *_lower = _keys;
+		const char *_mid;
+		const char *_upper = _keys + _klen - 1;
+		while (1) {
+			if ( _upper < _lower )
+				break;
+
+			_mid = _lower + ((_upper-_lower) >> 1);
+			if ( (*p) < *_mid )
+				_upper = _mid - 1;
+			else if ( (*p) > *_mid )
+				_lower = _mid + 1;
+			else {
+				_trans += (unsigned int)(_mid - _keys);
+				goto _match;
+			}
+		}
+		_keys += _klen;
+		_trans += _klen;
+	}
+
+	_klen = _json_range_lengths[cs];
+	if ( _klen > 0 ) {
+		const char *_lower = _keys;
+		const char *_mid;
+		const char *_upper = _keys + (_klen<<1) - 2;
+		while (1) {
+			if ( _upper < _lower )
+				break;
+
+			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
+			if ( (*p) < _mid[0] )
+				_upper = _mid - 2;
+			else if ( (*p) > _mid[1] )
+				_lower = _mid + 2;
+			else {
+				_trans += (unsigned int)((_mid - _keys)>>1);
+				goto _match;
+			}
+		}
+		_trans += _klen;
+	}
+
+_match:
+	_trans = _json_indicies[_trans];
+	cs = _json_trans_targs[_trans];
+
+	if ( _json_trans_actions[_trans] == 0 )
+		goto _again;
+
+	_acts = _json_actions + _json_trans_actions[_trans];
+	_nacts = (unsigned int) *_acts++;
+	while ( _nacts-- > 0 )
+	{
+		switch ( *_acts++ )
+		{
+	case 0:
+#line 1160 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+	case 1:
+#line 1161 "upb/json/parser.rl"
+	{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
+	break;
+	case 2:
+#line 1165 "upb/json/parser.rl"
+	{ start_text(parser, p); }
+	break;
+	case 3:
+#line 1166 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_text(parser, p)); }
+	break;
+	case 4:
+#line 1172 "upb/json/parser.rl"
+	{ start_hex(parser); }
+	break;
+	case 5:
+#line 1173 "upb/json/parser.rl"
+	{ hexdigit(parser, p); }
+	break;
+	case 6:
+#line 1174 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_hex(parser)); }
+	break;
+	case 7:
+#line 1180 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(escape(parser, p)); }
+	break;
+	case 8:
+#line 1186 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+	case 9:
+#line 1189 "upb/json/parser.rl"
+	{ {stack[top++] = cs; cs = 19; goto _again;} }
+	break;
+	case 10:
+#line 1191 "upb/json/parser.rl"
+	{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
+	break;
+	case 11:
+#line 1196 "upb/json/parser.rl"
+	{ start_member(parser); }
+	break;
+	case 12:
+#line 1197 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_membername(parser)); }
+	break;
+	case 13:
+#line 1200 "upb/json/parser.rl"
+	{ end_member(parser); }
+	break;
+	case 14:
+#line 1206 "upb/json/parser.rl"
+	{ start_object(parser); }
+	break;
+	case 15:
+#line 1209 "upb/json/parser.rl"
+	{ end_object(parser); }
+	break;
+	case 16:
+#line 1215 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_array(parser)); }
+	break;
+	case 17:
+#line 1219 "upb/json/parser.rl"
+	{ end_array(parser); }
+	break;
+	case 18:
+#line 1224 "upb/json/parser.rl"
+	{ start_number(parser, p); }
+	break;
+	case 19:
+#line 1225 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_number(parser, p)); }
+	break;
+	case 20:
+#line 1227 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_stringval(parser)); }
+	break;
+	case 21:
+#line 1228 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(end_stringval(parser)); }
+	break;
+	case 22:
+#line 1230 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
+	break;
+	case 23:
+#line 1232 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
+	break;
+	case 24:
+#line 1234 "upb/json/parser.rl"
+	{ /* null value */ }
+	break;
+	case 25:
+#line 1236 "upb/json/parser.rl"
+	{ CHECK_RETURN_TOP(start_subobject(parser)); }
+	break;
+	case 26:
+#line 1237 "upb/json/parser.rl"
+	{ end_subobject(parser); }
+	break;
+	case 27:
+#line 1242 "upb/json/parser.rl"
+	{ p--; {cs = stack[--top]; goto _again;} }
+	break;
+#line 1514 "upb/json/parser.c"
+		}
+	}
+
+_again:
+	if ( cs == 0 )
+		goto _out;
+	if ( ++p != pe )
+		goto _resume;
+	_test_eof: {}
+	_out: {}
+	}
+
+#line 1269 "upb/json/parser.rl"
+
+  if (p != pe) {
+    upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
+    upb_env_reporterror(parser->env, &parser->status);
+  } else {
+    capture_suspend(parser, &p);
+  }
+
+error:
+  /* Save parsing state back to parser. */
+  parser->current_state = cs;
+  parser->parser_top = top;
+
+  return p - buf;
+}
+
+bool end(void *closure, const void *hd) {
+  UPB_UNUSED(closure);
+  UPB_UNUSED(hd);
+
+  /* Prevent compile warning on unused static constants. */
+  UPB_UNUSED(json_start);
+  UPB_UNUSED(json_en_number_machine);
+  UPB_UNUSED(json_en_string_machine);
+  UPB_UNUSED(json_en_value_machine);
+  UPB_UNUSED(json_en_main);
+  return true;
+}
+
+static void json_parser_reset(upb_json_parser *p) {
+  int cs;
+  int top;
+
+  p->top = p->stack;
+  p->top->f = NULL;
+  p->top->is_map = false;
+  p->top->is_mapentry = false;
+
+  /* Emit Ragel initialization of the parser. */
+  
+#line 1568 "upb/json/parser.c"
+	{
+	cs = json_start;
+	top = 0;
+	}
+
+#line 1309 "upb/json/parser.rl"
+  p->current_state = cs;
+  p->parser_top = top;
+  accumulate_clear(p);
+  p->multipart_state = MULTIPART_INACTIVE;
+  p->capture = NULL;
+  p->accumulated = NULL;
+  upb_status_clear(&p->status);
+}
+
+static void visit_json_parsermethod(const upb_refcounted *r,
+                                    upb_refcounted_visit *visit,
+                                    void *closure) {
+  const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
+  visit(r, upb_msgdef_upcast2(method->msg), closure);
+}
+
+static void free_json_parsermethod(upb_refcounted *r) {
+  upb_json_parsermethod *method = (upb_json_parsermethod*)r;
+
+  upb_inttable_iter i;
+  upb_inttable_begin(&i, &method->name_tables);
+  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    upb_value val = upb_inttable_iter_value(&i);
+    upb_strtable *t = upb_value_getptr(val);
+    upb_strtable_uninit(t);
+    upb_gfree(t);
+  }
+
+  upb_inttable_uninit(&method->name_tables);
+
+  upb_gfree(r);
+}
+
+static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
+  upb_msg_field_iter i;
+  upb_strtable *t;
+
+  /* It would be nice to stack-allocate this, but protobufs do not limit the
+   * length of fields to any reasonable limit. */
+  char *buf = NULL;
+  size_t len = 0;
+
+  if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
+    return;
+  }
+
+  /* TODO(haberman): handle malloc failure. */
+  t = upb_gmalloc(sizeof(*t));
+  upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
+  upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
+
+  for(upb_msg_field_begin(&i, md);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+
+    /* Add an entry for the JSON name. */
+    size_t field_len = upb_fielddef_getjsonname(f, buf, len);
+    if (field_len > len) {
+      size_t len2;
+      buf = upb_grealloc(buf, 0, field_len);
+      len = field_len;
+      len2 = upb_fielddef_getjsonname(f, buf, len);
+      UPB_ASSERT_VAR(len2, len == len2);
+    }
+    upb_strtable_insert(t, buf, upb_value_constptr(f));
+
+    if (strcmp(buf, upb_fielddef_name(f)) != 0) {
+      /* Since the JSON name is different from the regular field name, add an
+       * entry for the raw name (compliant proto3 JSON parsers must accept
+       * both). */
+      upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      add_jsonname_table(m, upb_fielddef_msgsubdef(f));
+    }
+  }
+
+  upb_gfree(buf);
+}
+
+/* Public API *****************************************************************/
+
+upb_json_parser *upb_json_parser_create(upb_env *env,
+                                        const upb_json_parsermethod *method,
+                                        upb_sink *output) {
+#ifndef NDEBUG
+  const size_t size_before = upb_env_bytesallocated(env);
+#endif
+  upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
+  if (!p) return false;
+
+  p->env = env;
+  p->method = method;
+  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
+  p->accumulate_buf = NULL;
+  p->accumulate_buf_size = 0;
+  upb_bytessink_reset(&p->input_, &method->input_handler_, p);
+
+  json_parser_reset(p);
+  upb_sink_reset(&p->top->sink, output->handlers, output->closure);
+  p->top->m = upb_handlers_msgdef(output->handlers);
+  set_name_table(p, p->top);
+
+  /* If this fails, uncomment and increase the value in parser.h. */
+  /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
+  assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
+  return p;
+}
+
+upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
+  return &p->input_;
+}
+
+upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
+                                                 const void* owner) {
+  static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
+                                                  free_json_parsermethod};
+  upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret));
+  upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
+
+  ret->msg = md;
+  upb_ref2(md, ret);
+
+  upb_byteshandler_init(&ret->input_handler_);
+  upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
+  upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
+
+  upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
+
+  add_jsonname_table(ret, md);
+
+  return ret;
+}
+
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+    const upb_json_parsermethod *m) {
+  return &m->input_handler_;
+}
+/*
+** This currently uses snprintf() to format primitives, and could be optimized
+** further.
+*/
+
+
+#include <string.h>
+#include <stdint.h>
+
+struct upb_json_printer {
+  upb_sink input_;
+  /* BytesSink closure. */
+  void *subc_;
+  upb_bytessink *output_;
+
+  /* We track the depth so that we know when to emit startstr/endstr on the
+   * output. */
+  int depth_;
+
+  /* Have we emitted the first element? This state is necessary to emit commas
+   * without leaving a trailing comma in arrays/maps. We keep this state per
+   * frame depth.
+   *
+   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
+   * We count frames (contexts in which we separate elements by commas) as both
+   * repeated fields and messages (maps), and the worst case is a
+   * message->repeated field->submessage->repeated field->... nesting. */
+  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
+};
+
+/* StringPiece; a pointer plus a length. */
+typedef struct {
+  char *ptr;
+  size_t len;
+} strpc;
+
+void freestrpc(void *ptr) {
+  strpc *pc = ptr;
+  upb_gfree(pc->ptr);
+  upb_gfree(pc);
+}
+
+/* Convert fielddef name to JSON name and return as a string piece. */
+strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
+                bool preserve_fieldnames) {
+  /* TODO(haberman): handle malloc failure. */
+  strpc *ret = upb_gmalloc(sizeof(*ret));
+  if (preserve_fieldnames) {
+    ret->ptr = upb_gstrdup(upb_fielddef_name(f));
+    ret->len = strlen(ret->ptr);
+  } else {
+    size_t len;
+    ret->len = upb_fielddef_getjsonname(f, NULL, 0);
+    ret->ptr = upb_gmalloc(ret->len);
+    len = upb_fielddef_getjsonname(f, ret->ptr, ret->len);
+    UPB_ASSERT_VAR(len, len == ret->len);
+    ret->len--;  /* NULL */
+  }
+
+  upb_handlers_addcleanup(h, ret, freestrpc);
+  return ret;
+}
+
+/* ------------ JSON string printing: values, maps, arrays ------------------ */
+
+static void print_data(
+    upb_json_printer *p, const char *buf, unsigned int len) {
+  /* TODO: Will need to change if we support pushback from the sink. */
+  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
+  UPB_ASSERT_VAR(n, n == len);
+}
+
+static void print_comma(upb_json_printer *p) {
+  if (!p->first_elem_[p->depth_]) {
+    print_data(p, ",", 1);
+  }
+  p->first_elem_[p->depth_] = false;
+}
+
+/* Helpers that print properly formatted elements to the JSON output stream. */
+
+/* Used for escaping control chars in strings. */
+static const char kControlCharLimit = 0x20;
+
+UPB_INLINE bool is_json_escaped(char c) {
+  /* See RFC 4627. */
+  unsigned char uc = (unsigned char)c;
+  return uc < kControlCharLimit || uc == '"' || uc == '\\';
+}
+
+UPB_INLINE const char* json_nice_escape(char c) {
+  switch (c) {
+    case '"':  return "\\\"";
+    case '\\': return "\\\\";
+    case '\b': return "\\b";
+    case '\f': return "\\f";
+    case '\n': return "\\n";
+    case '\r': return "\\r";
+    case '\t': return "\\t";
+    default:   return NULL;
+  }
+}
+
+/* Write a properly escaped string chunk. The surrounding quotes are *not*
+ * printed; this is so that the caller has the option of emitting the string
+ * content in chunks. */
+static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
+  const char* unescaped_run = NULL;
+  unsigned int i;
+  for (i = 0; i < len; i++) {
+    char c = buf[i];
+    /* Handle escaping. */
+    if (is_json_escaped(c)) {
+      /* Use a "nice" escape, like \n, if one exists for this character. */
+      const char* escape = json_nice_escape(c);
+      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
+       * escape. */
+      char escape_buf[8];
+      if (!escape) {
+        unsigned char byte = (unsigned char)c;
+        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
+        escape = escape_buf;
+      }
+
+      /* N.B. that we assume that the input encoding is equal to the output
+       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
+       * can simply pass the bytes through. */
+
+      /* If there's a current run of unescaped chars, print that run first. */
+      if (unescaped_run) {
+        print_data(p, unescaped_run, &buf[i] - unescaped_run);
+        unescaped_run = NULL;
+      }
+      /* Then print the escape code. */
+      print_data(p, escape, strlen(escape));
+    } else {
+      /* Add to the current unescaped run of characters. */
+      if (unescaped_run == NULL) {
+        unescaped_run = &buf[i];
+      }
+    }
+  }
+
+  /* If the string ended in a run of unescaped characters, print that last run. */
+  if (unescaped_run) {
+    print_data(p, unescaped_run, &buf[len] - unescaped_run);
+  }
+}
+
+#define CHKLENGTH(x) if (!(x)) return -1;
+
+/* Helpers that format floating point values according to our custom formats.
+ * Right now we use %.8g and %.17g for float/double, respectively, to match
+ * proto2::util::JsonFormat's defaults.  May want to change this later. */
+
+static size_t fmt_double(double val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%.17g", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_float(float val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%.8g", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_bool(bool val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_int64(long val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%ld", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) {
+  size_t n = _upb_snprintf(buf, length, "%llu", val);
+  CHKLENGTH(n > 0 && n < length);
+  return n;
+}
+
+/* Print a map key given a field name. Called by scalar field handlers and by
+ * startseq for repeated fields. */
+static bool putkey(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  const strpc *key = handler_data;
+  print_comma(p);
+  print_data(p, "\"", 1);
+  putstring(p, key->ptr, key->len);
+  print_data(p, "\":", 2);
+  return true;
+}
+
+#define CHKFMT(val) if ((val) == (size_t)-1) return false;
+#define CHK(val)    if (!(val)) return false;
+
+#define TYPE_HANDLERS(type, fmt_func)                                        \
+  static bool put##type(void *closure, const void *handler_data, type val) { \
+    upb_json_printer *p = closure;                                           \
+    char data[64];                                                           \
+    size_t length = fmt_func(val, data, sizeof(data));                       \
+    UPB_UNUSED(handler_data);                                                \
+    CHKFMT(length);                                                          \
+    print_data(p, data, length);                                             \
+    return true;                                                             \
+  }                                                                          \
+  static bool scalar_##type(void *closure, const void *handler_data,         \
+                            type val) {                                      \
+    CHK(putkey(closure, handler_data));                                      \
+    CHK(put##type(closure, handler_data, val));                              \
+    return true;                                                             \
+  }                                                                          \
+  static bool repeated_##type(void *closure, const void *handler_data,       \
+                              type val) {                                    \
+    upb_json_printer *p = closure;                                           \
+    print_comma(p);                                                          \
+    CHK(put##type(closure, handler_data, val));                              \
+    return true;                                                             \
+  }
+
+#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
+  static bool putmapkey_##type(void *closure, const void *handler_data,      \
+                            type val) {                                      \
+    upb_json_printer *p = closure;                                           \
+    print_data(p, "\"", 1);                                                  \
+    CHK(put##type(closure, handler_data, val));                              \
+    print_data(p, "\":", 2);                                                 \
+    return true;                                                             \
+  }
+
+TYPE_HANDLERS(double,   fmt_double)
+TYPE_HANDLERS(float,    fmt_float)
+TYPE_HANDLERS(bool,     fmt_bool)
+TYPE_HANDLERS(int32_t,  fmt_int64)
+TYPE_HANDLERS(uint32_t, fmt_int64)
+TYPE_HANDLERS(int64_t,  fmt_int64)
+TYPE_HANDLERS(uint64_t, fmt_uint64)
+
+/* double and float are not allowed to be map keys. */
+TYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
+TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64)
+TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64)
+
+#undef TYPE_HANDLERS
+#undef TYPE_HANDLERS_MAPKEY
+
+typedef struct {
+  void *keyname;
+  const upb_enumdef *enumdef;
+} EnumHandlerData;
+
+static bool scalar_enum(void *closure, const void *handler_data,
+                        int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+  const char *symbolic_name;
+
+  CHK(putkey(closure, hd->keyname));
+
+  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
+  if (symbolic_name) {
+    print_data(p, "\"", 1);
+    putstring(p, symbolic_name, strlen(symbolic_name));
+    print_data(p, "\"", 1);
+  } else {
+    putint32_t(closure, NULL, val);
+  }
+
+  return true;
+}
+
+static void print_enum_symbolic_name(upb_json_printer *p,
+                                     const upb_enumdef *def,
+                                     int32_t val) {
+  const char *symbolic_name = upb_enumdef_iton(def, val);
+  if (symbolic_name) {
+    print_data(p, "\"", 1);
+    putstring(p, symbolic_name, strlen(symbolic_name));
+    print_data(p, "\"", 1);
+  } else {
+    putint32_t(p, NULL, val);
+  }
+}
+
+static bool repeated_enum(void *closure, const void *handler_data,
+                          int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+  print_comma(p);
+
+  print_enum_symbolic_name(p, hd->enumdef, val);
+
+  return true;
+}
+
+static bool mapvalue_enum(void *closure, const void *handler_data,
+                          int32_t val) {
+  const EnumHandlerData *hd = handler_data;
+  upb_json_printer *p = closure;
+
+  print_enum_symbolic_name(p, hd->enumdef, val);
+
+  return true;
+}
+
+static void *scalar_startsubmsg(void *closure, const void *handler_data) {
+  return putkey(closure, handler_data) ? closure : UPB_BREAK;
+}
+
+static void *repeated_startsubmsg(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_comma(p);
+  return closure;
+}
+
+static void start_frame(upb_json_printer *p) {
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "{", 1);
+}
+
+static void end_frame(upb_json_printer *p) {
+  print_data(p, "}", 1);
+  p->depth_--;
+}
+
+static bool printer_startmsg(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  if (p->depth_ == 0) {
+    upb_bytessink_start(p->output_, 0, &p->subc_);
+  }
+  start_frame(p);
+  return true;
+}
+
+static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(s);
+  end_frame(p);
+  if (p->depth_ == 0) {
+    upb_bytessink_end(p->output_);
+  }
+  return true;
+}
+
+static void *startseq(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  CHK(putkey(closure, handler_data));
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "[", 1);
+  return closure;
+}
+
+static bool endseq(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "]", 1);
+  p->depth_--;
+  return true;
+}
+
+static void *startmap(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  CHK(putkey(closure, handler_data));
+  p->depth_++;
+  p->first_elem_[p->depth_] = true;
+  print_data(p, "{", 1);
+  return closure;
+}
+
+static bool endmap(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "}", 1);
+  p->depth_--;
+  return true;
+}
+
+static size_t putstr(void *closure, const void *handler_data, const char *str,
+                     size_t len, const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(handle);
+  putstring(p, str, len);
+  return len;
+}
+
+/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
+static size_t putbytes(void *closure, const void *handler_data, const char *str,
+                       size_t len, const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+
+  /* This is the regular base64, not the "web-safe" version. */
+  static const char base64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  /* Base64-encode. */
+  char data[16000];
+  const char *limit = data + sizeof(data);
+  const unsigned char *from = (const unsigned char*)str;
+  char *to = data;
+  size_t remaining = len;
+  size_t bytes;
+
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(handle);
+
+  while (remaining > 2) {
+    /* TODO(haberman): handle encoded lengths > sizeof(data) */
+    UPB_ASSERT_VAR(limit, (limit - to) >= 4);
+
+    to[0] = base64[from[0] >> 2];
+    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
+    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
+    to[3] = base64[from[2] & 0x3f];
+
+    remaining -= 3;
+    to += 4;
+    from += 3;
+  }
+
+  switch (remaining) {
+    case 2:
+      to[0] = base64[from[0] >> 2];
+      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
+      to[2] = base64[(from[1] & 0xf) << 2];
+      to[3] = '=';
+      to += 4;
+      from += 2;
+      break;
+    case 1:
+      to[0] = base64[from[0] >> 2];
+      to[1] = base64[((from[0] & 0x3) << 4)];
+      to[2] = '=';
+      to[3] = '=';
+      to += 4;
+      from += 1;
+      break;
+  }
+
+  bytes = to - data;
+  print_data(p, "\"", 1);
+  putstring(p, data, bytes);
+  print_data(p, "\"", 1);
+  return len;
+}
+
+static void *scalar_startstr(void *closure, const void *handler_data,
+                             size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  CHK(putkey(closure, handler_data));
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t scalar_str(void *closure, const void *handler_data,
+                         const char *str, size_t len,
+                         const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool scalar_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static void *repeated_startstr(void *closure, const void *handler_data,
+                               size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  print_comma(p);
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t repeated_str(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool repeated_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static void *mapkeyval_startstr(void *closure, const void *handler_data,
+                                size_t size_hint) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  UPB_UNUSED(size_hint);
+  print_data(p, "\"", 1);
+  return p;
+}
+
+static size_t mapkey_str(void *closure, const void *handler_data,
+                         const char *str, size_t len,
+                         const upb_bufhandle *handle) {
+  CHK(putstr(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static bool mapkey_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\":", 2);
+  return true;
+}
+
+static bool mapvalue_endstr(void *closure, const void *handler_data) {
+  upb_json_printer *p = closure;
+  UPB_UNUSED(handler_data);
+  print_data(p, "\"", 1);
+  return true;
+}
+
+static size_t scalar_bytes(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  CHK(putkey(closure, handler_data));
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static size_t repeated_bytes(void *closure, const void *handler_data,
+                             const char *str, size_t len,
+                             const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  print_comma(p);
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  return len;
+}
+
+static size_t mapkey_bytes(void *closure, const void *handler_data,
+                           const char *str, size_t len,
+                           const upb_bufhandle *handle) {
+  upb_json_printer *p = closure;
+  CHK(putbytes(closure, handler_data, str, len, handle));
+  print_data(p, ":", 1);
+  return len;
+}
+
+static void set_enum_hd(upb_handlers *h,
+                        const upb_fielddef *f,
+                        bool preserve_fieldnames,
+                        upb_handlerattr *attr) {
+  EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
+  hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
+  hd->keyname = newstrpc(h, f, preserve_fieldnames);
+  upb_handlers_addcleanup(h, hd, upb_gfree);
+  upb_handlerattr_sethandlerdata(attr, hd);
+}
+
+/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
+ * in a map).
+ *
+ * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
+ * key or value cases properly. The right way to do this is to allocate a
+ * temporary structure at the start of a mapentry submessage, store key and
+ * value data in it as key and value handlers are called, and then print the
+ * key/value pair once at the end of the submessage. If we don't do this, we
+ * should at least detect the case and throw an error. However, so far all of
+ * our sources that emit mapentry messages do so canonically (with one key
+ * field, and then one value field), so this is not a pressing concern at the
+ * moment. */
+void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
+                                  upb_handlers *h) {
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+
+  /* A mapentry message is printed simply as '"key": value'. Rather than
+   * special-case key and value for every type below, we just handle both
+   * fields explicitly here. */
+  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
+  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
+
+  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+
+  UPB_UNUSED(closure);
+
+  switch (upb_fielddef_type(key_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
+      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
+      break;
+    default:
+      assert(false);
+      break;
+  }
+
+  switch (upb_fielddef_type(value_field)) {
+    case UPB_TYPE_INT32:
+      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_INT64:
+      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT32:
+      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
+      break;
+    case UPB_TYPE_UINT64:
+      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
+      break;
+    case UPB_TYPE_BOOL:
+      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
+      break;
+    case UPB_TYPE_FLOAT:
+      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
+      break;
+    case UPB_TYPE_DOUBLE:
+      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
+      break;
+    case UPB_TYPE_STRING:
+      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
+      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
+      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
+      break;
+    case UPB_TYPE_BYTES:
+      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
+      break;
+    case UPB_TYPE_ENUM: {
+      upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+      set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
+      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
+      upb_handlerattr_uninit(&enum_attr);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      /* No handler necessary -- the submsg handlers will print the message
+       * as appropriate. */
+      break;
+  }
+
+  upb_handlerattr_uninit(&empty_attr);
+}
+
+void printer_sethandlers(const void *closure, upb_handlers *h) {
+  const upb_msgdef *md = upb_handlers_msgdef(h);
+  bool is_mapentry = upb_msgdef_mapentry(md);
+  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+  upb_msg_field_iter i;
+  const bool *preserve_fieldnames_ptr = closure;
+  const bool preserve_fieldnames = *preserve_fieldnames_ptr;
+
+  if (is_mapentry) {
+    /* mapentry messages are sufficiently different that we handle them
+     * separately. */
+    printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
+    return;
+  }
+
+  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
+  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
+
+#define TYPE(type, name, ctype)                                               \
+  case type:                                                                  \
+    if (upb_fielddef_isseq(f)) {                                              \
+      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
+    } else {                                                                  \
+      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
+    }                                                                         \
+    break;
+
+  upb_msg_field_begin(&i, md);
+  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
+
+    upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
+    upb_handlerattr_sethandlerdata(&name_attr,
+                                   newstrpc(h, f, preserve_fieldnames));
+
+    if (upb_fielddef_ismap(f)) {
+      upb_handlers_setstartseq(h, f, startmap, &name_attr);
+      upb_handlers_setendseq(h, f, endmap, &name_attr);
+    } else if (upb_fielddef_isseq(f)) {
+      upb_handlers_setstartseq(h, f, startseq, &name_attr);
+      upb_handlers_setendseq(h, f, endseq, &empty_attr);
+    }
+
+    switch (upb_fielddef_type(f)) {
+      TYPE(UPB_TYPE_FLOAT,  float,  float);
+      TYPE(UPB_TYPE_DOUBLE, double, double);
+      TYPE(UPB_TYPE_BOOL,   bool,   bool);
+      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
+      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
+      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
+      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
+      case UPB_TYPE_ENUM: {
+        /* For now, we always emit symbolic names for enums. We may want an
+         * option later to control this behavior, but we will wait for a real
+         * need first. */
+        upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+        set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
+
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
+        } else {
+          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
+        }
+
+        upb_handlerattr_uninit(&enum_attr);
+        break;
+      }
+      case UPB_TYPE_STRING:
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
+          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
+          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
+        } else {
+          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
+          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
+          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
+        }
+        break;
+      case UPB_TYPE_BYTES:
+        /* XXX: this doesn't support strings that span buffers yet. The base64
+         * encoder will need to be made resumable for this to work properly. */
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
+        } else {
+          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
+        }
+        break;
+      case UPB_TYPE_MESSAGE:
+        if (upb_fielddef_isseq(f)) {
+          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
+        } else {
+          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
+        }
+        break;
+    }
+
+    upb_handlerattr_uninit(&name_attr);
+  }
+
+  upb_handlerattr_uninit(&empty_attr);
+#undef TYPE
+}
+
+static void json_printer_reset(upb_json_printer *p) {
+  p->depth_ = 0;
+}
+
+
+/* Public API *****************************************************************/
+
+upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
+                                          upb_bytessink *output) {
+#ifndef NDEBUG
+  size_t size_before = upb_env_bytesallocated(e);
+#endif
+
+  upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
+  if (!p) return NULL;
+
+  p->output_ = output;
+  json_printer_reset(p);
+  upb_sink_reset(&p->input_, h, p);
+
+  /* If this fails, increase the value in printer.h. */
+  assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
+  return p;
+}
+
+upb_sink *upb_json_printer_input(upb_json_printer *p) {
+  return &p->input_;
+}
+
+const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+                                                 bool preserve_fieldnames,
+                                                 const void *owner) {
+  return upb_handlers_newfrozen(
+      md, owner, printer_sethandlers, &preserve_fieldnames);
+}
diff --git a/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.h b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.h
new file mode 100644
index 0000000..2faf74e
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/ext/google/protobuf_c/upb.h
@@ -0,0 +1,8569 @@
+// Amalgamated source file
+/*
+** Defs are upb's internal representation of the constructs that can appear
+** in a .proto file:
+**
+** - upb::MessageDef (upb_msgdef): describes a "message" construct.
+** - upb::FieldDef (upb_fielddef): describes a message field.
+** - upb::FileDef (upb_filedef): describes a .proto file and its defs.
+** - upb::EnumDef (upb_enumdef): describes an enum.
+** - upb::OneofDef (upb_oneofdef): describes a oneof.
+** - upb::Def (upb_def): base class of all the others.
+**
+** TODO: definitions of services.
+**
+** Like upb_refcounted objects, defs are mutable only until frozen, and are
+** only thread-safe once frozen.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+/*
+** upb::RefCounted (upb_refcounted)
+**
+** A refcounting scheme that supports circular refs.  It accomplishes this by
+** partitioning the set of objects into groups such that no cycle spans groups;
+** we can then reference-count the group as a whole and ignore refs within the
+** group.  When objects are mutable, these groups are computed very
+** conservatively; we group any objects that have ever had a link between them.
+** When objects are frozen, we compute strongly-connected components which
+** allows us to be precise and only group objects that are actually cyclic.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_REFCOUNTED_H_
+#define UPB_REFCOUNTED_H_
+
+/*
+** upb_table
+**
+** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
+** This file defines very fast int->upb_value (inttable) and string->upb_value
+** (strtable) hash tables.
+**
+** The table uses chained scatter with Brent's variation (inspired by the Lua
+** implementation of hash tables).  The hash function for strings is Austin
+** Appleby's "MurmurHash."
+**
+** The inttable uses uintptr_t as its key, which guarantees it can be used to
+** store pointers or integers of at least 32 bits (upb isn't really useful on
+** systems where sizeof(void*) < 4).
+**
+** The table must be homogenous (all values of the same type).  In debug
+** mode, we check this on insert and lookup.
+*/
+
+#ifndef UPB_TABLE_H_
+#define UPB_TABLE_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+/*
+** This file contains shared definitions that are widely used across upb.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_H_
+#define UPB_H_
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+namespace upb {
+class Allocator;
+class Arena;
+class Environment;
+class ErrorSpace;
+class Status;
+template <int N> class InlinedArena;
+template <int N> class InlinedEnvironment;
+}
+#endif
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
+ * doesn't provide these preprocessor symbols. */
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define UPB_BIG_ENDIAN
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#endif
+
+/* A few hacky workarounds for functions not in C89.
+ * For internal use only!
+ * TODO(haberman): fix these by including our own implementations, or finding
+ * another workaround.
+ */
+#ifdef __GNUC__
+#define _upb_snprintf __builtin_snprintf
+#define _upb_vsnprintf __builtin_vsnprintf
+#define _upb_va_copy(a, b) __va_copy(a, b)
+#elif __STDC_VERSION__ >= 199901L
+/* C99 versions. */
+#define _upb_snprintf snprintf
+#define _upb_vsnprintf vsnprintf
+#define _upb_va_copy(a, b) va_copy(a, b)
+#else
+#error Need implementations of [v]snprintf and va_copy
+#endif
+
+
+#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \
+      defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11)
+#define UPB_CXX11
+#endif
+
+/* UPB_DISALLOW_COPY_AND_ASSIGN()
+ * UPB_DISALLOW_POD_OPS()
+ *
+ * Declare these in the "private" section of a C++ class to forbid copy/assign
+ * or all POD ops (construct, destruct, copy, assign) on that class. */
+#ifdef UPB_CXX11
+#include <type_traits>
+#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
+  class_name(const class_name&) = delete; \
+  void operator=(const class_name&) = delete;
+#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \
+  class_name() = delete; \
+  ~class_name() = delete; \
+  UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
+#define UPB_ASSERT_STDLAYOUT(type) \
+  static_assert(std::is_standard_layout<type>::value, \
+                #type " must be standard layout");
+#define UPB_FINAL final
+#else  /* !defined(UPB_CXX11) */
+#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
+  class_name(const class_name&); \
+  void operator=(const class_name&);
+#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \
+  class_name(); \
+  ~class_name(); \
+  UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
+#define UPB_ASSERT_STDLAYOUT(type)
+#define UPB_FINAL
+#endif
+
+/* UPB_DECLARE_TYPE()
+ * UPB_DECLARE_DERIVED_TYPE()
+ * UPB_DECLARE_DERIVED_TYPE2()
+ *
+ * Macros for declaring C and C++ types both, including inheritance.
+ * The inheritance doesn't use real C++ inheritance, to stay compatible with C.
+ *
+ * These macros also provide upcasts:
+ *  - in C: types-specific functions (ie. upb_foo_upcast(foo))
+ *  - in C++: upb::upcast(foo) along with implicit conversions
+ *
+ * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */
+
+#define UPB_C_UPCASTS(ty, base)                                      \
+  UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \
+  UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; }
+
+#define UPB_C_UPCASTS2(ty, base, base2)                                 \
+  UPB_C_UPCASTS(ty, base)                                               \
+  UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \
+  UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; }
+
+#ifdef __cplusplus
+
+#define UPB_BEGIN_EXTERN_C extern "C" {
+#define UPB_END_EXTERN_C }
+#define UPB_PRIVATE_FOR_CPP private:
+#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname;
+
+#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase)  \
+  UPB_DECLARE_TYPE(cppname, cname)                                \
+  UPB_C_UPCASTS(cname, cbase)                                     \
+  namespace upb {                                                 \
+  template <>                                                     \
+  class Pointer<cppname> : public PointerBase<cppname, cppbase> { \
+   public:                                                        \
+    explicit Pointer(cppname* ptr)                                \
+        : PointerBase<cppname, cppbase>(ptr) {}                   \
+  };                                                              \
+  template <>                                                     \
+  class Pointer<const cppname>                                    \
+      : public PointerBase<const cppname, const cppbase> {        \
+   public:                                                        \
+    explicit Pointer(const cppname* ptr)                          \
+        : PointerBase<const cppname, const cppbase>(ptr) {}       \
+  };                                                              \
+  }
+
+#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase,  \
+                                  cbase2)                                    \
+  UPB_DECLARE_TYPE(cppname, cname)                                           \
+  UPB_C_UPCASTS2(cname, cbase, cbase2)                                       \
+  namespace upb {                                                            \
+  template <>                                                                \
+  class Pointer<cppname> : public PointerBase2<cppname, cppbase, cppbase2> { \
+   public:                                                                   \
+    explicit Pointer(cppname* ptr)                                           \
+        : PointerBase2<cppname, cppbase, cppbase2>(ptr) {}                   \
+  };                                                                         \
+  template <>                                                                \
+  class Pointer<const cppname>                                               \
+      : public PointerBase2<const cppname, const cppbase, const cppbase2> {  \
+   public:                                                                   \
+    explicit Pointer(const cppname* ptr)                                     \
+        : PointerBase2<const cppname, const cppbase, const cppbase2>(ptr) {} \
+  };                                                                         \
+  }
+
+#else  /* !defined(__cplusplus) */
+
+#define UPB_BEGIN_EXTERN_C
+#define UPB_END_EXTERN_C
+#define UPB_PRIVATE_FOR_CPP
+#define UPB_DECLARE_TYPE(cppname, cname) \
+  struct cname;                          \
+  typedef struct cname cname;
+#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \
+  UPB_DECLARE_TYPE(cppname, cname)                               \
+  UPB_C_UPCASTS(cname, cbase)
+#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2,    \
+                                  cname, cbase, cbase2)          \
+  UPB_DECLARE_TYPE(cppname, cname)                               \
+  UPB_C_UPCASTS2(cname, cbase, cbase2)
+
+#endif  /* defined(__cplusplus) */
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* For asserting something about a variable when the variable is not used for
+ * anything else.  This prevents "unused variable" warnings when compiling in
+ * debug mode. */
+#define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate)
+
+/* Generic function type. */
+typedef void upb_func();
+
+
+/* C++ Casts ******************************************************************/
+
+#ifdef __cplusplus
+
+namespace upb {
+
+template <class T> class Pointer;
+
+/* Casts to a subclass.  The caller must know that cast is correct; an
+ * incorrect cast will throw an assertion failure in debug mode.
+ *
+ * Example:
+ *   upb::Def* def = GetDef();
+ *   // Assert-fails if this was not actually a MessageDef.
+ *   upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def);
+ *
+ * Note that downcasts are only defined for some types (at the moment you can
+ * only downcast from a upb::Def to a specific Def type). */
+template<class To, class From> To down_cast(From* f);
+
+/* Casts to a subclass.  If the class does not actually match the given To type,
+ * returns NULL.
+ *
+ * Example:
+ *   upb::Def* def = GetDef();
+ *   // md will be NULL if this was not actually a MessageDef.
+ *   upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def);
+ *
+ * Note that dynamic casts are only defined for some types (at the moment you
+ * can only downcast from a upb::Def to a specific Def type).. */
+template<class To, class From> To dyn_cast(From* f);
+
+/* Casts to any base class, or the type itself (ie. can be a no-op).
+ *
+ * Example:
+ *   upb::MessageDef* md = GetDef();
+ *   // This will fail to compile if this wasn't actually a base class.
+ *   upb::Def* def = upb::upcast(md);
+ */
+template <class T> inline Pointer<T> upcast(T *f) { return Pointer<T>(f); }
+
+/* Attempt upcast to specific base class.
+ *
+ * Example:
+ *   upb::MessageDef* md = GetDef();
+ *   upb::upcast_to<upb::Def>(md)->MethodOnDef();
+ */
+template <class T, class F> inline T* upcast_to(F *f) {
+  return static_cast<T*>(upcast(f));
+}
+
+/* PointerBase<T>: implementation detail of upb::upcast().
+ * It is implicitly convertable to pointers to the Base class(es).
+ */
+template <class T, class Base>
+class PointerBase {
+ public:
+  explicit PointerBase(T* ptr) : ptr_(ptr) {}
+  operator T*() { return ptr_; }
+  operator Base*() { return (Base*)ptr_; }
+
+ private:
+  T* ptr_;
+};
+
+template <class T, class Base, class Base2>
+class PointerBase2 : public PointerBase<T, Base> {
+ public:
+  explicit PointerBase2(T* ptr) : PointerBase<T, Base>(ptr) {}
+  operator Base2*() { return Pointer<Base>(*this); }
+};
+
+}
+
+#endif
+
+
+/* upb::ErrorSpace ************************************************************/
+
+/* A upb::ErrorSpace represents some domain of possible error values.  This lets
+ * upb::Status attach specific error codes to operations, like POSIX/C errno,
+ * Win32 error codes, etc.  Clients who want to know the very specific error
+ * code can check the error space and then know the type of the integer code.
+ *
+ * NOTE: upb::ErrorSpace is currently not used and should be considered
+ * experimental.  It is important primarily in cases where upb is performing
+ * I/O, but upb doesn't currently have any components that do this. */
+
+UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace)
+
+#ifdef __cplusplus
+class upb::ErrorSpace {
+#else
+struct upb_errorspace {
+#endif
+  const char *name;
+};
+
+
+/* upb::Status ****************************************************************/
+
+/* upb::Status represents a success or failure status and error message.
+ * It owns no resources and allocates no memory, so it should work
+ * even in OOM situations. */
+UPB_DECLARE_TYPE(upb::Status, upb_status)
+
+/* The maximum length of an error message before it will get truncated. */
+#define UPB_STATUS_MAX_MESSAGE 128
+
+UPB_BEGIN_EXTERN_C
+
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+upb_errorspace *upb_status_errspace(const upb_status *status);
+int upb_status_errcode(const upb_status *status);
+
+/* Any of the functions that write to a status object allow status to be NULL,
+ * to support use cases where the function's caller does not care about the
+ * status message. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
+void upb_status_copy(upb_status *to, const upb_status *from);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+class upb::Status {
+ public:
+  Status() { upb_status_clear(this); }
+
+  /* Returns true if there is no error. */
+  bool ok() const { return upb_ok(this); }
+
+  /* Optional error space and code, useful if the caller wants to
+   * programmatically check the specific kind of error. */
+  ErrorSpace* error_space() { return upb_status_errspace(this); }
+  int error_code() const { return upb_status_errcode(this); }
+
+  /* The returned string is invalidated by any other call into the status. */
+  const char *error_message() const { return upb_status_errmsg(this); }
+
+  /* The error message will be truncated if it is longer than
+   * UPB_STATUS_MAX_MESSAGE-4. */
+  void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); }
+  void SetFormattedErrorMessage(const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    upb_status_vseterrf(this, fmt, args);
+    va_end(args);
+  }
+
+  /* Resets the status to a successful state with no message. */
+  void Clear() { upb_status_clear(this); }
+
+  void CopyFrom(const Status& other) { upb_status_copy(this, &other); }
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Status)
+#else
+struct upb_status {
+#endif
+  bool ok_;
+
+  /* Specific status code defined by some error space (optional). */
+  int code_;
+  upb_errorspace *error_space_;
+
+  /* TODO(haberman): add file/line of error? */
+
+  /* Error message; NULL-terminated. */
+  char msg[UPB_STATUS_MAX_MESSAGE];
+};
+
+#define UPB_STATUS_INIT {true, 0, NULL, {0}}
+
+
+/** Built-in error spaces. ****************************************************/
+
+/* Errors raised by upb that we want to be able to detect programmatically. */
+typedef enum {
+  UPB_NOMEM   /* Can't reuse ENOMEM because it is POSIX, not ISO C. */
+} upb_errcode_t;
+
+extern upb_errorspace upb_upberr;
+
+void upb_upberr_setoom(upb_status *s);
+
+/* Since errno is defined by standard C, we define an error space for it in
+ * core upb.  Other error spaces should be defined in other, platform-specific
+ * modules. */
+
+extern upb_errorspace upb_errnoerr;
+
+
+/** upb::Allocator ************************************************************/
+
+/* A upb::Allocator is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does).  The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+UPB_DECLARE_TYPE(upb::Allocator, upb_alloc)
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size);
+
+#ifdef __cplusplus
+
+class upb::Allocator UPB_FINAL {
+ public:
+  Allocator() {}
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Allocator)
+
+ public:
+#else
+struct upb_alloc {
+#endif  /* __cplusplus */
+  upb_alloc_func *func;
+};
+
+UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
+  assert(size > 0);
+  return alloc->func(alloc, NULL, 0, size);
+}
+
+UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size) {
+  assert(size > 0);
+  return alloc->func(alloc, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
+  alloc->func(alloc, ptr, 0, 0);
+}
+
+/* The global allocator used by upb.  Uses the standard malloc()/free(). */
+
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void *upb_gmalloc(size_t size) {
+  return upb_malloc(&upb_alloc_global, size);
+}
+
+UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
+  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_gfree(void *ptr) {
+  upb_free(&upb_alloc_global, ptr);
+}
+
+/* upb::Arena *****************************************************************/
+
+/* upb::Arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks.  Arenas by nature do not require the individual allocations
+ * to be freed.  However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb::Arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb::Allocator interface, but it would not be as efficient for the
+ * single-threaded case. */
+UPB_DECLARE_TYPE(upb::Arena, upb_arena)
+
+typedef void upb_cleanup_func(void *ud);
+
+#define UPB_ARENA_BLOCK_OVERHEAD (sizeof(size_t)*4)
+
+UPB_BEGIN_EXTERN_C
+
+void upb_arena_init(upb_arena *a);
+void upb_arena_init2(upb_arena *a, void *mem, size_t n, upb_alloc *alloc);
+void upb_arena_uninit(upb_arena *a);
+upb_alloc *upb_arena_alloc(upb_arena *a);
+bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud);
+size_t upb_arena_bytesallocated(const upb_arena *a);
+void upb_arena_setnextblocksize(upb_arena *a, size_t size);
+void upb_arena_setmaxblocksize(upb_arena *a, size_t size);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+class upb::Arena {
+ public:
+  /* A simple arena with no initial memory block and the default allocator. */
+  Arena() { upb_arena_init(this); }
+
+  /* Constructs an arena with the given initial block which allocates blocks
+   * with the given allocator.  The given allocator must outlive the Arena.
+   *
+   * If you pass NULL for the allocator it will default to the global allocator
+   * upb_alloc_global, and NULL/0 for the initial block will cause there to be
+   * no initial block. */
+  Arena(void *mem, size_t len, Allocator* a) {
+    upb_arena_init2(this, mem, len, a);
+  }
+
+  ~Arena() { upb_arena_uninit(this); }
+
+  /* Sets the size of the next block the Arena will request (unless the
+   * requested allocation is larger).  Each block will double in size until the
+   * max limit is reached. */
+  void SetNextBlockSize(size_t size) { upb_arena_setnextblocksize(this, size); }
+
+  /* Sets the maximum block size.  No blocks larger than this will be requested
+   * from the underlying allocator unless individual arena allocations are
+   * larger. */
+  void SetMaxBlockSize(size_t size) { upb_arena_setmaxblocksize(this, size); }
+
+  /* Allows this arena to be used as a generic allocator.
+   *
+   * The arena does not need free() calls so when using Arena as an allocator
+   * it is safe to skip them.  However they are no-ops so there is no harm in
+   * calling free() either. */
+  Allocator* allocator() { return upb_arena_alloc(this); }
+
+  /* Add a cleanup function to run when the arena is destroyed.
+   * Returns false on out-of-memory. */
+  bool AddCleanup(upb_cleanup_func* func, void* ud) {
+    return upb_arena_addcleanup(this, func, ud);
+  }
+
+  /* Total number of bytes that have been allocated.  It is undefined what
+   * Realloc() does to this counter. */
+  size_t BytesAllocated() const {
+    return upb_arena_bytesallocated(this);
+  }
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Arena)
+
+#else
+struct upb_arena {
+#endif  /* __cplusplus */
+  /* We implement the allocator interface.
+   * This must be the first member of upb_arena! */
+  upb_alloc alloc;
+
+  /* Allocator to allocate arena blocks.  We are responsible for freeing these
+   * when we are destroyed. */
+  upb_alloc *block_alloc;
+
+  size_t bytes_allocated;
+  size_t next_block_size;
+  size_t max_block_size;
+
+  /* Linked list of blocks.  Points to an arena_block, defined in env.c */
+  void *block_head;
+
+  /* Cleanup entries.  Pointer to a cleanup_ent, defined in env.c */
+  void *cleanup_head;
+
+  /* For future expansion, since the size of this struct is exposed to users. */
+  void *future1;
+  void *future2;
+};
+
+
+/* upb::Environment ***********************************************************/
+
+/* A upb::Environment provides a means for injecting malloc and an
+ * error-reporting callback into encoders/decoders.  This allows them to be
+ * independent of nearly all assumptions about their actual environment.
+ *
+ * It is also a container for allocating the encoders/decoders themselves that
+ * insulates clients from knowing their actual size.  This provides ABI
+ * compatibility even if the size of the objects change.  And this allows the
+ * structure definitions to be in the .c files instead of the .h files, making
+ * the .h files smaller and more readable.
+ *
+ * We might want to consider renaming this to "Pipeline" if/when the concept of
+ * a pipeline element becomes more formalized. */
+UPB_DECLARE_TYPE(upb::Environment, upb_env)
+
+/* A function that receives an error report from an encoder or decoder.  The
+ * callback can return true to request that the error should be recovered, but
+ * if the error is not recoverable this has no effect. */
+typedef bool upb_error_func(void *ud, const upb_status *status);
+
+UPB_BEGIN_EXTERN_C
+
+void upb_env_init(upb_env *e);
+void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc);
+void upb_env_uninit(upb_env *e);
+
+void upb_env_initonly(upb_env *e);
+
+upb_arena *upb_env_arena(upb_env *e);
+bool upb_env_ok(const upb_env *e);
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud);
+
+/* Convenience wrappers around the methods of the contained arena. */
+void upb_env_reporterrorsto(upb_env *e, upb_status *s);
+bool upb_env_reporterror(upb_env *e, const upb_status *s);
+void *upb_env_malloc(upb_env *e, size_t size);
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size);
+void upb_env_free(upb_env *e, void *ptr);
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud);
+size_t upb_env_bytesallocated(const upb_env *e);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+class upb::Environment {
+ public:
+  /* The given Arena must outlive this environment. */
+  Environment() { upb_env_initonly(this); }
+
+  Environment(void *mem, size_t len, Allocator *a) : arena_(mem, len, a) {
+    upb_env_initonly(this);
+  }
+
+  Arena* arena() { return upb_env_arena(this); }
+
+  /* Set a custom error reporting function. */
+  void SetErrorFunction(upb_error_func* func, void* ud) {
+    upb_env_seterrorfunc(this, func, ud);
+  }
+
+  /* Set the error reporting function to simply copy the status to the given
+   * status and abort. */
+  void ReportErrorsTo(Status* status) { upb_env_reporterrorsto(this, status); }
+
+  /* Returns true if all allocations and AddCleanup() calls have succeeded,
+   * and no errors were reported with ReportError() (except ones that recovered
+   * successfully). */
+  bool ok() const { return upb_env_ok(this); }
+
+  /* Reports an error to this environment's callback, returning true if
+   * the caller should try to recover. */
+  bool ReportError(const Status* status) {
+    return upb_env_reporterror(this, status);
+  }
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(Environment)
+
+#else
+struct upb_env {
+#endif  /* __cplusplus */
+  upb_arena arena_;
+  upb_error_func *error_func_;
+  void *error_ud_;
+  bool ok_;
+};
+
+
+/* upb::InlinedArena **********************************************************/
+/* upb::InlinedEnvironment ****************************************************/
+
+/* upb::InlinedArena and upb::InlinedEnvironment seed their arenas with a
+ * predefined amount of memory.  No heap memory will be allocated until the
+ * initial block is exceeded.
+ *
+ * These types only exist in C++ */
+
+#ifdef __cplusplus
+
+template <int N> class upb::InlinedArena : public upb::Arena {
+ public:
+  InlinedArena() : Arena(initial_block_, N, NULL) {}
+  explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {}
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena)
+
+  char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD];
+};
+
+template <int N> class upb::InlinedEnvironment : public upb::Environment {
+ public:
+  InlinedEnvironment() : Environment(initial_block_, N, NULL) {}
+  explicit InlinedEnvironment(Allocator *a)
+      : Environment(initial_block_, N, a) {}
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(InlinedEnvironment)
+
+  char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD];
+};
+
+#endif  /* __cplusplus */
+
+
+
+#endif  /* UPB_H_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* upb_value ******************************************************************/
+
+/* A tagged union (stored untagged inside the table) so that we can check that
+ * clients calling table accessors are correctly typed without having to have
+ * an explosion of accessors. */
+typedef enum {
+  UPB_CTYPE_INT32    = 1,
+  UPB_CTYPE_INT64    = 2,
+  UPB_CTYPE_UINT32   = 3,
+  UPB_CTYPE_UINT64   = 4,
+  UPB_CTYPE_BOOL     = 5,
+  UPB_CTYPE_CSTR     = 6,
+  UPB_CTYPE_PTR      = 7,
+  UPB_CTYPE_CONSTPTR = 8,
+  UPB_CTYPE_FPTR     = 9
+} upb_ctype_t;
+
+typedef struct {
+  uint64_t val;
+#ifndef NDEBUG
+  /* In debug mode we carry the value type around also so we can check accesses
+   * to be sure the right member is being read. */
+  upb_ctype_t ctype;
+#endif
+} upb_value;
+
+#ifdef NDEBUG
+#define SET_TYPE(dest, val)      UPB_UNUSED(val)
+#else
+#define SET_TYPE(dest, val) dest = val
+#endif
+
+/* Like strdup(), which isn't always available since it's not ANSI C. */
+char *upb_strdup(const char *s, upb_alloc *a);
+/* Variant that works with a length-delimited rather than NULL-delimited string,
+ * as supported by strtable. */
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
+
+UPB_INLINE char *upb_gstrdup(const char *s) {
+  return upb_strdup(s, &upb_alloc_global);
+}
+
+UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val,
+                                  upb_ctype_t ctype) {
+  v->val = val;
+  SET_TYPE(v->ctype, ctype);
+}
+
+UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) {
+  upb_value ret;
+  _upb_value_setval(&ret, val, ctype);
+  return ret;
+}
+
+/* For each value ctype, define the following set of functions:
+ *
+ * // Get/set an int32 from a upb_value.
+ * int32_t upb_value_getint32(upb_value val);
+ * void upb_value_setint32(upb_value *val, int32_t cval);
+ *
+ * // Construct a new upb_value from an int32.
+ * upb_value upb_value_int32(int32_t val); */
+#define FUNCS(name, membername, type_t, converter, proto_type) \
+  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
+    val->val = (converter)cval; \
+    SET_TYPE(val->ctype, proto_type); \
+  } \
+  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
+    upb_value ret; \
+    upb_value_set ## name(&ret, val); \
+    return ret; \
+  } \
+  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
+    assert(val.ctype == proto_type); \
+    return (type_t)(converter)val.val; \
+  }
+
+FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
+FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
+FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
+FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
+FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
+FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
+FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
+FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
+FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
+
+#undef FUNCS
+#undef SET_TYPE
+
+
+/* upb_tabkey *****************************************************************/
+
+/* Either:
+ *   1. an actual integer key, or
+ *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
+ *
+ * ...depending on whether this is a string table or an int table.  We would
+ * make this a union of those two types, but C89 doesn't support statically
+ * initializing a non-first union member. */
+typedef uintptr_t upb_tabkey;
+
+#define UPB_TABKEY_NUM(n) n
+#define UPB_TABKEY_NONE 0
+/* The preprocessor isn't quite powerful enough to turn the compile-time string
+ * length into a byte-wise string representation, so code generation needs to
+ * help it along.
+ *
+ * "len1" is the low byte and len4 is the high byte. */
+#ifdef UPB_BIG_ENDIAN
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+    (uintptr_t)(len4 len3 len2 len1 strval)
+#else
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+    (uintptr_t)(len1 len2 len3 len4 strval)
+#endif
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+  char* mem = (char*)key;
+  if (len) memcpy(len, mem, sizeof(*len));
+  return mem + sizeof(*len);
+}
+
+
+/* upb_tabval *****************************************************************/
+
+#ifdef __cplusplus
+
+/* Status initialization not supported.
+ *
+ * This separate definition is necessary because in C++, UINTPTR_MAX isn't
+ * reliably available. */
+typedef struct {
+  uint64_t val;
+} upb_tabval;
+
+#else
+
+/* C -- supports static initialization, but to support static initialization of
+ * both integers and points for both 32 and 64 bit targets, it takes a little
+ * bit of doing. */
+
+#if UINTPTR_MAX == 0xffffffffffffffffULL
+#define UPB_PTR_IS_64BITS
+#elif UINTPTR_MAX != 0xffffffff
+#error Could not determine how many bits pointers are.
+#endif
+
+typedef union {
+  /* For static initialization.
+   *
+   * Unfortunately this ugliness is necessary -- it is the only way that we can,
+   * with -std=c89 -pedantic, statically initialize this to either a pointer or
+   * an integer on 32-bit platforms. */
+  struct {
+#ifdef UPB_PTR_IS_64BITS
+    uintptr_t val;
+#else
+    uintptr_t val1;
+    uintptr_t val2;
+#endif
+  } staticinit;
+
+  /* The normal accessor that we use for everything at runtime. */
+  uint64_t val;
+} upb_tabval;
+
+#ifdef UPB_PTR_IS_64BITS
+#define UPB_TABVALUE_INT_INIT(v) {{v}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1}}
+#else
+
+/* 32-bit pointers */
+
+#ifdef UPB_BIG_ENDIAN
+#define UPB_TABVALUE_INT_INIT(v) {{0, v}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1, -1}}
+#else
+#define UPB_TABVALUE_INT_INIT(v) {{v, 0}}
+#define UPB_TABVALUE_EMPTY_INIT  {{-1, -1}}
+#endif
+
+#endif
+
+#define UPB_TABVALUE_PTR_INIT(v) UPB_TABVALUE_INT_INIT((uintptr_t)v)
+
+#undef UPB_PTR_IS_64BITS
+
+#endif  /* __cplusplus */
+
+
+/* upb_table ******************************************************************/
+
+typedef struct _upb_tabent {
+  upb_tabkey key;
+  upb_tabval val;
+
+  /* Internal chaining.  This is const so we can create static initializers for
+   * tables.  We cast away const sometimes, but *only* when the containing
+   * upb_table is known to be non-const.  This requires a bit of care, but
+   * the subtlety is confined to table.c. */
+  const struct _upb_tabent *next;
+} upb_tabent;
+
+typedef struct {
+  size_t count;          /* Number of entries in the hash part. */
+  size_t mask;           /* Mask to turn hash value -> bucket. */
+  upb_ctype_t ctype;     /* Type of all values. */
+  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
+
+  /* Hash table entries.
+   * Making this const isn't entirely accurate; what we really want is for it to
+   * have the same const-ness as the table it's inside.  But there's no way to
+   * declare that in C.  So we have to make it const so that we can statically
+   * initialize const hash tables.  Then we cast away const when we have to.
+   */
+  const upb_tabent *entries;
+
+#ifndef NDEBUG
+  /* This table's allocator.  We make the user pass it in to every relevant
+   * function and only use this to check it in debug mode.  We do this solely
+   * to keep upb_table as small as possible.  This might seem slightly paranoid
+   * but the plan is to use upb_table for all map fields and extension sets in
+   * a forthcoming message representation, so there could be a lot of these.
+   * If this turns out to be too annoying later, we can change it (since this
+   * is an internal-only header file). */
+  upb_alloc *alloc;
+#endif
+} upb_table;
+
+#ifdef NDEBUG
+#  define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+     {count, mask, ctype, size_lg2, entries}
+#else
+#  ifdef UPB_DEBUG_REFS
+/* At the moment the only mutable tables we statically initialize are debug
+ * ref tables. */
+#    define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+       {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs}
+#  else
+#    define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+       {count, mask, ctype, size_lg2, entries, NULL}
+#  endif
+#endif
+
+typedef struct {
+  upb_table t;
+} upb_strtable;
+
+#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
+  {UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries)}
+
+#define UPB_EMPTY_STRTABLE_INIT(ctype)                           \
+  UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL)
+
+typedef struct {
+  upb_table t;              /* For entries that don't fit in the array part. */
+  const upb_tabval *array;  /* Array part of the table. See const note above. */
+  size_t array_size;        /* Array part size. */
+  size_t array_count;       /* Array part number of elements. */
+} upb_inttable;
+
+#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
+  {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount}
+
+#define UPB_EMPTY_INTTABLE_INIT(ctype) \
+  UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
+
+#define UPB_ARRAY_EMPTYENT -1
+
+UPB_INLINE size_t upb_table_size(const upb_table *t) {
+  if (t->size_lg2 == 0)
+    return 0;
+  else
+    return 1 << t->size_lg2;
+}
+
+/* Internal-only functions, in .h file only out of necessity. */
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
+  return e->key == 0;
+}
+
+/* Used by some of the unit tests for generic hashing functionality. */
+uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed);
+
+UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
+  return key;
+}
+
+UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
+  return (uint32_t)key;
+}
+
+static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
+  return t->entries + (hash & t->mask);
+}
+
+UPB_INLINE bool upb_arrhas(upb_tabval key) {
+  return key.val != (uint64_t)-1;
+}
+
+/* Initialize and uninitialize a table, respectively.  If memory allocation
+ * failed, false is returned that the table is uninitialized. */
+bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
+bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
+void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
+void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
+  return upb_inttable_init2(table, ctype, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
+  return upb_strtable_init2(table, ctype, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
+  upb_inttable_uninit2(table, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
+  upb_strtable_uninit2(table, &upb_alloc_global);
+}
+
+/* Returns the number of values in the table. */
+size_t upb_inttable_count(const upb_inttable *t);
+UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
+  return t->t.count;
+}
+
+/* Inserts the given key into the hashtable with the given value.  The key must
+ * not already exist in the hash table.  For string tables, the key must be
+ * NULL-terminated, and the table will make an internal copy of the key.
+ * Inttables must not insert a value of UINTPTR_MAX.
+ *
+ * If a table resize was required but memory allocation failed, false is
+ * returned and the table is unchanged. */
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+                          upb_alloc *a);
+bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
+                          upb_value val, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
+                                    upb_value val) {
+  return upb_inttable_insert2(t, key, val, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
+                                     size_t len, upb_value val) {
+  return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
+}
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
+                                    upb_value val) {
+  return upb_strtable_insert2(t, key, strlen(key), val);
+}
+
+/* Looks up key in this table, returning "true" if the key was found.
+ * If v is non-NULL, copies the value for this key into *v. */
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+/* Removes an item from the table.  Returns true if the remove was successful,
+ * and stores the removed item in *val if non-NULL. */
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+                          upb_value *val, upb_alloc *alloc);
+
+UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
+                                     size_t len, upb_value *val) {
+  return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
+}
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_remove2(t, key, strlen(key), v);
+}
+
+/* Updates an existing entry in an inttable.  If the entry does not exist,
+ * returns false and does nothing.  Unlike insert/remove, this does not
+ * invalidate iterators. */
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
+
+/* Handy routines for treating an inttable like a stack.  May not be mixed with
+ * other insert/remove calls. */
+bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
+upb_value upb_inttable_pop(upb_inttable *t);
+
+UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
+  return upb_inttable_push2(t, val, &upb_alloc_global);
+}
+
+/* Convenience routines for inttables with pointer keys. */
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+                             upb_alloc *a);
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
+bool upb_inttable_lookupptr(
+    const upb_inttable *t, const void *key, upb_value *val);
+
+UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
+                                       upb_value val) {
+  return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
+}
+
+/* Optimizes the table for the current set of entries, for both memory use and
+ * lookup time.  Client should call this after all entries have been inserted;
+ * inserting more entries is legal, but will likely require a table resize. */
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
+
+UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
+  upb_inttable_compact2(t, &upb_alloc_global);
+}
+
+/* A special-case inlinable version of the lookup routine for 32-bit
+ * integers. */
+UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
+                                      upb_value *v) {
+  *v = upb_value_int32(0);  /* Silence compiler warnings. */
+  if (key < t->array_size) {
+    upb_tabval arrval = t->array[key];
+    if (upb_arrhas(arrval)) {
+      _upb_value_setval(v, arrval.val, t->t.ctype);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    const upb_tabent *e;
+    if (t->t.entries == NULL) return false;
+    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
+      if ((uint32_t)e->key == key) {
+        _upb_value_setval(v, e->val.val, t->t.ctype);
+        return true;
+      }
+      if (e->next == NULL) return false;
+    }
+  }
+}
+
+/* Exposed for testing only. */
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
+
+/* Iterators ******************************************************************/
+
+/* Iterators for int and string tables.  We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ *  - we must be able to guarantee that we don't crash or corrupt memory even if
+ *    the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ *  - iterators must be copyable
+ *  - iterators must be comparable
+ *  - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed.  Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+
+
+/* upb_strtable_iter **********************************************************/
+
+/*   upb_strtable_iter i;
+ *   upb_strtable_begin(&i, t);
+ *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ *     const char *key = upb_strtable_iter_key(&i);
+ *     const upb_value val = upb_strtable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_strtable *t;
+  size_t index;
+} upb_strtable_iter;
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
+void upb_strtable_next(upb_strtable_iter *i);
+bool upb_strtable_done(const upb_strtable_iter *i);
+const char *upb_strtable_iter_key(const upb_strtable_iter *i);
+size_t upb_strtable_iter_keylength(const upb_strtable_iter *i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
+void upb_strtable_iter_setdone(upb_strtable_iter *i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2);
+
+
+/* upb_inttable_iter **********************************************************/
+
+/*   upb_inttable_iter i;
+ *   upb_inttable_begin(&i, t);
+ *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ *     uintptr_t key = upb_inttable_iter_key(&i);
+ *     upb_value val = upb_inttable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_inttable *t;
+  size_t index;
+  bool array_part;
+} upb_inttable_iter;
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
+void upb_inttable_next(upb_inttable_iter *i);
+bool upb_inttable_done(const upb_inttable_iter *i);
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
+void upb_inttable_iter_setdone(upb_inttable_iter *i);
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                               const upb_inttable_iter *i2);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_TABLE_H_ */
+
+/* Reference tracking will check ref()/unref() operations to make sure the
+ * ref ownership is correct.  Where possible it will also make tools like
+ * Valgrind attribute ref leaks to the code that took the leaked ref, not
+ * the code that originally created the object.
+ *
+ * Enabling this requires the application to define upb_lock()/upb_unlock()
+ * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE).
+ * For this reason we don't enable it by default, even in debug builds.
+ */
+
+/* #define UPB_DEBUG_REFS */
+
+#ifdef __cplusplus
+namespace upb {
+class RefCounted;
+template <class T> class reffed_ptr;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted)
+
+struct upb_refcounted_vtbl;
+
+#ifdef __cplusplus
+
+class upb::RefCounted {
+ public:
+  /* Returns true if the given object is frozen. */
+  bool IsFrozen() const;
+
+  /* Increases the ref count, the new ref is owned by "owner" which must not
+   * already own a ref (and should not itself be a refcounted object if the ref
+   * could possibly be circular; see below).
+   * Thread-safe iff "this" is frozen. */
+  void Ref(const void *owner) const;
+
+  /* Release a ref that was acquired from upb_refcounted_ref() and collects any
+   * objects it can. */
+  void Unref(const void *owner) const;
+
+  /* Moves an existing ref from "from" to "to", without changing the overall
+   * ref count.  DonateRef(foo, NULL, owner) is the same as Ref(foo, owner),
+   * but "to" may not be NULL. */
+  void DonateRef(const void *from, const void *to) const;
+
+  /* Verifies that a ref to the given object is currently held by the given
+   * owner.  Only effective in UPB_DEBUG_REFS builds. */
+  void CheckRef(const void *owner) const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted)
+#else
+struct upb_refcounted {
+#endif
+  /* TODO(haberman): move the actual structure definition to structdefs.int.h.
+   * The only reason they are here is because inline functions need to see the
+   * definition of upb_handlers, which needs to see this definition.  But we
+   * can change the upb_handlers inline functions to deal in raw offsets
+   * instead.
+   */
+
+  /* A single reference count shared by all objects in the group. */
+  uint32_t *group;
+
+  /* A singly-linked list of all objects in the group. */
+  upb_refcounted *next;
+
+  /* Table of function pointers for this type. */
+  const struct upb_refcounted_vtbl *vtbl;
+
+  /* Maintained only when mutable, this tracks the number of refs (but not
+   * ref2's) to this object.  *group should be the sum of all individual_count
+   * in the group. */
+  uint32_t individual_count;
+
+  bool is_frozen;
+
+#ifdef UPB_DEBUG_REFS
+  upb_inttable *refs;  /* Maps owner -> trackedref for incoming refs. */
+  upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */
+#endif
+};
+
+#ifdef UPB_DEBUG_REFS
+extern upb_alloc upb_alloc_debugrefs;
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+    {&static_refcount, NULL, vtbl, 0, true, refs, ref2s}
+#else
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+    {&static_refcount, NULL, vtbl, 0, true}
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* It is better to use tracked refs when possible, for the extra debugging
+ * capability.  But if this is not possible (because you don't have easy access
+ * to a stable pointer value that is associated with the ref), you can pass
+ * UPB_UNTRACKED_REF instead.  */
+extern const void *UPB_UNTRACKED_REF;
+
+/* Native C API. */
+bool upb_refcounted_isfrozen(const upb_refcounted *r);
+void upb_refcounted_ref(const upb_refcounted *r, const void *owner);
+void upb_refcounted_unref(const upb_refcounted *r, const void *owner);
+void upb_refcounted_donateref(
+    const upb_refcounted *r, const void *from, const void *to);
+void upb_refcounted_checkref(const upb_refcounted *r, const void *owner);
+
+#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \
+  UPB_INLINE bool type ## _isfrozen(const type *v) { \
+    return upb_refcounted_isfrozen(upcastfunc(v)); \
+  } \
+  UPB_INLINE void type ## _ref(const type *v, const void *owner) { \
+    upb_refcounted_ref(upcastfunc(v), owner); \
+  } \
+  UPB_INLINE void type ## _unref(const type *v, const void *owner) { \
+    upb_refcounted_unref(upcastfunc(v), owner); \
+  } \
+  UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \
+    upb_refcounted_donateref(upcastfunc(v), from, to); \
+  } \
+  UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \
+    upb_refcounted_checkref(upcastfunc(v), owner); \
+  }
+
+#define UPB_REFCOUNTED_CPPMETHODS \
+  bool IsFrozen() const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->IsFrozen(); \
+  } \
+  void Ref(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->Ref(owner); \
+  } \
+  void Unref(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->Unref(owner); \
+  } \
+  void DonateRef(const void *from, const void *to) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->DonateRef(from, to); \
+  } \
+  void CheckRef(const void *owner) const { \
+    return upb::upcast_to<const upb::RefCounted>(this)->CheckRef(owner); \
+  }
+
+/* Internal-to-upb Interface **************************************************/
+
+typedef void upb_refcounted_visit(const upb_refcounted *r,
+                                  const upb_refcounted *subobj,
+                                  void *closure);
+
+struct upb_refcounted_vtbl {
+  /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2.
+   * Must be longjmp()-safe. */
+  void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c);
+
+  /* Must free the object and release all references to other objects. */
+  void (*free)(upb_refcounted *r);
+};
+
+/* Initializes the refcounted with a single ref for the given owner.  Returns
+ * false if memory could not be allocated. */
+bool upb_refcounted_init(upb_refcounted *r,
+                         const struct upb_refcounted_vtbl *vtbl,
+                         const void *owner);
+
+/* Adds a ref from one refcounted object to another ("from" must not already
+ * own a ref).  These refs may be circular; cycles will be collected correctly
+ * (if conservatively).  These refs do not need to be freed in from's free()
+ * function. */
+void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from);
+
+/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any
+ * object it can.  This is only necessary when "from" no longer points to "r",
+ * and not from from's "free" function. */
+void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from);
+
+#define upb_ref2(r, from) \
+    upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from)
+#define upb_unref2(r, from) \
+    upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from)
+
+/* Freezes all mutable object reachable by ref2() refs from the given roots.
+ * This will split refcounting groups into precise SCC groups, so that
+ * refcounting of frozen objects can be more aggressive.  If memory allocation
+ * fails, or if more than 2**31 mutable objects are reachable from "roots", or
+ * if the maximum depth of the graph exceeds "maxdepth", false is returned and
+ * the objects are unchanged.
+ *
+ * After this operation succeeds, the objects are frozen/const, and may not be
+ * used through non-const pointers.  In particular, they may not be passed as
+ * the second parameter of upb_refcounted_{ref,unref}2().  On the upside, all
+ * operations on frozen refcounteds are threadsafe, and objects will be freed
+ * at the precise moment that they become unreachable.
+ *
+ * Caller must own refs on each object in the "roots" list. */
+bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
+                           int maxdepth);
+
+/* Shared by all compiled-in refcounted objects. */
+extern uint32_t static_refcount;
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ Wrappers. */
+namespace upb {
+inline bool RefCounted::IsFrozen() const {
+  return upb_refcounted_isfrozen(this);
+}
+inline void RefCounted::Ref(const void *owner) const {
+  upb_refcounted_ref(this, owner);
+}
+inline void RefCounted::Unref(const void *owner) const {
+  upb_refcounted_unref(this, owner);
+}
+inline void RefCounted::DonateRef(const void *from, const void *to) const {
+  upb_refcounted_donateref(this, from, to);
+}
+inline void RefCounted::CheckRef(const void *owner) const {
+  upb_refcounted_checkref(this, owner);
+}
+}  /* namespace upb */
+#endif
+
+
+/* upb::reffed_ptr ************************************************************/
+
+#ifdef __cplusplus
+
+#include <algorithm>  /* For std::swap(). */
+
+/* Provides RAII semantics for upb refcounted objects.  Each reffed_ptr owns a
+ * ref on whatever object it points to (if any). */
+template <class T> class upb::reffed_ptr {
+ public:
+  reffed_ptr() : ptr_(NULL) {}
+
+  /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+  template <class U>
+  reffed_ptr(U* val, const void* ref_donor = NULL)
+      : ptr_(upb::upcast(val)) {
+    if (ref_donor) {
+      assert(ptr_);
+      ptr_->DonateRef(ref_donor, this);
+    } else if (ptr_) {
+      ptr_->Ref(this);
+    }
+  }
+
+  template <class U>
+  reffed_ptr(const reffed_ptr<U>& other)
+      : ptr_(upb::upcast(other.get())) {
+    if (ptr_) ptr_->Ref(this);
+  }
+
+  reffed_ptr(const reffed_ptr& other)
+      : ptr_(upb::upcast(other.get())) {
+    if (ptr_) ptr_->Ref(this);
+  }
+
+  ~reffed_ptr() { if (ptr_) ptr_->Unref(this); }
+
+  template <class U>
+  reffed_ptr& operator=(const reffed_ptr<U>& other) {
+    reset(other.get());
+    return *this;
+  }
+
+  reffed_ptr& operator=(const reffed_ptr& other) {
+    reset(other.get());
+    return *this;
+  }
+
+  /* TODO(haberman): add C++11 move construction/assignment for greater
+   * efficiency. */
+
+  void swap(reffed_ptr& other) {
+    if (ptr_ == other.ptr_) {
+      return;
+    }
+
+    if (ptr_) ptr_->DonateRef(this, &other);
+    if (other.ptr_) other.ptr_->DonateRef(&other, this);
+    std::swap(ptr_, other.ptr_);
+  }
+
+  T& operator*() const {
+    assert(ptr_);
+    return *ptr_;
+  }
+
+  T* operator->() const {
+    assert(ptr_);
+    return ptr_;
+  }
+
+  T* get() const { return ptr_; }
+
+  /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+  template <class U>
+  void reset(U* ptr = NULL, const void* ref_donor = NULL) {
+    reffed_ptr(ptr, ref_donor).swap(*this);
+  }
+
+  template <class U>
+  reffed_ptr<U> down_cast() {
+    return reffed_ptr<U>(upb::down_cast<U*>(get()));
+  }
+
+  template <class U>
+  reffed_ptr<U> dyn_cast() {
+    return reffed_ptr<U>(upb::dyn_cast<U*>(get()));
+  }
+
+  /* Plain release() is unsafe; if we were the only owner, it would leak the
+   * object.  Instead we provide this: */
+  T* ReleaseTo(const void* new_owner) {
+    T* ret = NULL;
+    ptr_->DonateRef(this, new_owner);
+    std::swap(ret, ptr_);
+    return ret;
+  }
+
+ private:
+  T* ptr_;
+};
+
+#endif  /* __cplusplus */
+
+#endif  /* UPB_REFCOUNT_H_ */
+
+#ifdef __cplusplus
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace upb {
+class Def;
+class EnumDef;
+class FieldDef;
+class FileDef;
+class MessageDef;
+class OneofDef;
+}
+#endif
+
+UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted)
+UPB_DECLARE_DERIVED_TYPE(upb::OneofDef, upb::RefCounted, upb_oneofdef,
+                         upb_refcounted)
+UPB_DECLARE_DERIVED_TYPE(upb::FileDef, upb::RefCounted, upb_filedef,
+                         upb_refcounted)
+
+/* The maximum message depth that the type graph can have.  This is a resource
+ * limit for the C stack since we sometimes need to recursively traverse the
+ * graph.  Cycles are ok; the traversal will stop when it detects a cycle, but
+ * we must hit the cycle before the maximum depth is reached.
+ *
+ * If having a single static limit is too inflexible, we can add another variant
+ * of Def::Freeze that allows specifying this as a parameter. */
+#define UPB_MAX_MESSAGE_DEPTH 64
+
+
+/* upb::Def: base class for top-level defs  ***********************************/
+
+/* All the different kind of defs that can be defined at the top-level and put
+ * in a SymbolTable or appear in a FileDef::defs() list.  This excludes some
+ * defs (like oneofs and files).  It only includes fields because they can be
+ * defined as extensions. */
+typedef enum {
+  UPB_DEF_MSG,
+  UPB_DEF_FIELD,
+  UPB_DEF_ENUM,
+  UPB_DEF_SERVICE,   /* Not yet implemented. */
+  UPB_DEF_ANY = -1   /* Wildcard for upb_symtab_get*() */
+} upb_deftype_t;
+
+#ifdef __cplusplus
+
+/* The base class of all defs.  Its base is upb::RefCounted (use upb::upcast()
+ * to convert). */
+class upb::Def {
+ public:
+  typedef upb_deftype_t Type;
+
+  Def* Dup(const void *owner) const;
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  Type def_type() const;
+
+  /* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */
+  const char *full_name() const;
+
+  /* The final part of a def's name (eg. Message). */
+  const char *name() const;
+
+  /* The def must be mutable.  Caller retains ownership of fullname.  Defs are
+   * not required to have a name; if a def has no name when it is frozen, it
+   * will remain an anonymous def.  On failure, returns false and details in "s"
+   * if non-NULL. */
+  bool set_full_name(const char* fullname, upb::Status* s);
+  bool set_full_name(const std::string &fullname, upb::Status* s);
+
+  /* The file in which this def appears.  It is not necessary to add a def to a
+   * file (and consequently the accessor may return NULL).  Set this by calling
+   * file->Add(def). */
+  FileDef* file() const;
+
+  /* Freezes the given defs; this validates all constraints and marks the defs
+   * as frozen (read-only).  "defs" may not contain any fielddefs, but fields
+   * of any msgdefs will be frozen.
+   *
+   * Symbolic references to sub-types and enum defaults must have already been
+   * resolved.  Any mutable defs reachable from any of "defs" must also be in
+   * the list; more formally, "defs" must be a transitive closure of mutable
+   * defs.
+   *
+   * After this operation succeeds, the finalized defs must only be accessed
+   * through a const pointer! */
+  static bool Freeze(Def* const* defs, size_t n, Status* status);
+  static bool Freeze(const std::vector<Def*>& defs, Status* status);
+
+ private:
+  UPB_DISALLOW_POD_OPS(Def, upb::Def)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_def *upb_def_dup(const upb_def *def, const void *owner);
+
+/* Include upb_refcounted methods like upb_def_ref()/upb_def_unref(). */
+UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast)
+
+upb_deftype_t upb_def_type(const upb_def *d);
+const char *upb_def_fullname(const upb_def *d);
+const char *upb_def_name(const upb_def *d);
+const upb_filedef *upb_def_file(const upb_def *d);
+bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s);
+bool upb_def_freeze(upb_def *const *defs, size_t n, upb_status *s);
+
+/* Temporary API: for internal use only. */
+bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s);
+
+UPB_END_EXTERN_C
+
+
+/* upb::Def casts *************************************************************/
+
+#ifdef __cplusplus
+#define UPB_CPP_CASTS(cname, cpptype)                                          \
+  namespace upb {                                                              \
+  template <>                                                                  \
+  inline cpptype *down_cast<cpptype *, Def>(Def * def) {                       \
+    return upb_downcast_##cname##_mutable(def);                                \
+  }                                                                            \
+  template <>                                                                  \
+  inline cpptype *dyn_cast<cpptype *, Def>(Def * def) {                        \
+    return upb_dyncast_##cname##_mutable(def);                                 \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *down_cast<const cpptype *, const Def>(                 \
+      const Def *def) {                                                        \
+    return upb_downcast_##cname(def);                                          \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *dyn_cast<const cpptype *, const Def>(const Def *def) { \
+    return upb_dyncast_##cname(def);                                           \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *down_cast<const cpptype *, Def>(Def * def) {           \
+    return upb_downcast_##cname(def);                                          \
+  }                                                                            \
+  template <>                                                                  \
+  inline const cpptype *dyn_cast<const cpptype *, Def>(Def * def) {            \
+    return upb_dyncast_##cname(def);                                           \
+  }                                                                            \
+  }  /* namespace upb */
+#else
+#define UPB_CPP_CASTS(cname, cpptype)
+#endif  /* __cplusplus */
+
+/* Dynamic casts, for determining if a def is of a particular type at runtime.
+ * Downcasts, for when some wants to assert that a def is of a particular type.
+ * These are only checked if we are building debug. */
+#define UPB_DEF_CASTS(lower, upper, cpptype)                               \
+  UPB_INLINE const upb_##lower *upb_dyncast_##lower(const upb_def *def) {  \
+    if (upb_def_type(def) != UPB_DEF_##upper) return NULL;                 \
+    return (upb_##lower *)def;                                             \
+  }                                                                        \
+  UPB_INLINE const upb_##lower *upb_downcast_##lower(const upb_def *def) { \
+    assert(upb_def_type(def) == UPB_DEF_##upper);                          \
+    return (const upb_##lower *)def;                                       \
+  }                                                                        \
+  UPB_INLINE upb_##lower *upb_dyncast_##lower##_mutable(upb_def *def) {    \
+    return (upb_##lower *)upb_dyncast_##lower(def);                        \
+  }                                                                        \
+  UPB_INLINE upb_##lower *upb_downcast_##lower##_mutable(upb_def *def) {   \
+    return (upb_##lower *)upb_downcast_##lower(def);                       \
+  }                                                                        \
+  UPB_CPP_CASTS(lower, cpptype)
+
+#define UPB_DEFINE_DEF(cppname, lower, upper, cppmethods, members)             \
+  UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, cppmethods,            \
+                   members)                                                    \
+  UPB_DEF_CASTS(lower, upper, cppname)
+
+#define UPB_DECLARE_DEF_TYPE(cppname, lower, upper) \
+  UPB_DECLARE_DERIVED_TYPE2(cppname, upb::Def, upb::RefCounted, \
+                            upb_ ## lower, upb_def, upb_refcounted) \
+  UPB_DEF_CASTS(lower, upper, cppname)
+
+UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD)
+UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG)
+UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM)
+
+#undef UPB_DECLARE_DEF_TYPE
+#undef UPB_DEF_CASTS
+#undef UPB_CPP_CASTS
+
+
+/* upb::FieldDef **************************************************************/
+
+/* The types a field can have.  Note that this list is not identical to the
+ * types defined in descriptor.proto, which gives INT32 and SINT32 separate
+ * types (we distinguish the two with the "integer encoding" enum below). */
+typedef enum {
+  UPB_TYPE_FLOAT    = 1,
+  UPB_TYPE_DOUBLE   = 2,
+  UPB_TYPE_BOOL     = 3,
+  UPB_TYPE_STRING   = 4,
+  UPB_TYPE_BYTES    = 5,
+  UPB_TYPE_MESSAGE  = 6,
+  UPB_TYPE_ENUM     = 7,  /* Enum values are int32. */
+  UPB_TYPE_INT32    = 8,
+  UPB_TYPE_UINT32   = 9,
+  UPB_TYPE_INT64    = 10,
+  UPB_TYPE_UINT64   = 11
+} upb_fieldtype_t;
+
+/* The repeated-ness of each field; this matches descriptor.proto. */
+typedef enum {
+  UPB_LABEL_OPTIONAL = 1,
+  UPB_LABEL_REQUIRED = 2,
+  UPB_LABEL_REPEATED = 3
+} upb_label_t;
+
+/* How integers should be encoded in serializations that offer multiple
+ * integer encoding methods. */
+typedef enum {
+  UPB_INTFMT_VARIABLE = 1,
+  UPB_INTFMT_FIXED = 2,
+  UPB_INTFMT_ZIGZAG = 3   /* Only for signed types (INT32/INT64). */
+} upb_intfmt_t;
+
+/* Descriptor types, as defined in descriptor.proto. */
+typedef enum {
+  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
+  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
+  UPB_DESCRIPTOR_TYPE_INT64    = 3,
+  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
+  UPB_DESCRIPTOR_TYPE_INT32    = 5,
+  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
+  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
+  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
+  UPB_DESCRIPTOR_TYPE_STRING   = 9,
+  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
+  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
+  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
+  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
+  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
+  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
+  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
+  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
+  UPB_DESCRIPTOR_TYPE_SINT64   = 18
+} upb_descriptortype_t;
+
+typedef enum {
+  UPB_SYNTAX_PROTO2 = 2,
+  UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
+/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+#ifdef __cplusplus
+
+/* A upb_fielddef describes a single field in a message.  It is most often
+ * found as a part of a upb_msgdef, but can also stand alone to represent
+ * an extension.
+ *
+ * Its base class is upb::Def (use upb::upcast() to convert). */
+class upb::FieldDef {
+ public:
+  typedef upb_fieldtype_t Type;
+  typedef upb_label_t Label;
+  typedef upb_intfmt_t IntegerFormat;
+  typedef upb_descriptortype_t DescriptorType;
+
+  /* These return true if the given value is a valid member of the enumeration. */
+  static bool CheckType(int32_t val);
+  static bool CheckLabel(int32_t val);
+  static bool CheckDescriptorType(int32_t val);
+  static bool CheckIntegerFormat(int32_t val);
+
+  /* These convert to the given enumeration; they require that the value is
+   * valid. */
+  static Type ConvertType(int32_t val);
+  static Label ConvertLabel(int32_t val);
+  static DescriptorType ConvertDescriptorType(int32_t val);
+  static IntegerFormat ConvertIntegerFormat(int32_t val);
+
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<FieldDef> New();
+
+  /* Duplicates the given field, returning NULL if memory allocation failed.
+   * When a fielddef is duplicated, the subdef (if any) is made symbolic if it
+   * wasn't already.  If the subdef is set but has no name (which is possible
+   * since msgdefs are not required to have a name) the new fielddef's subdef
+   * will be unset. */
+  FieldDef* Dup(const void* owner) const;
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+
+  bool type_is_set() const;  /* set_[descriptor_]type() has been called? */
+  Type type() const;         /* Requires that type_is_set() == true. */
+  Label label() const;       /* Defaults to UPB_LABEL_OPTIONAL. */
+  const char* name() const;  /* NULL if uninitialized. */
+  uint32_t number() const;   /* Returns 0 if uninitialized. */
+  bool is_extension() const;
+
+  /* Copies the JSON name for this field into the given buffer.  Returns the
+   * actual size of the JSON name, including the NULL terminator.  If the
+   * return value is 0, the JSON name is unset.  If the return value is
+   * greater than len, the JSON name was truncated.  The buffer is always
+   * NULL-terminated if len > 0.
+   *
+   * The JSON name always defaults to a camelCased version of the regular
+   * name.  However if the regular name is unset, the JSON name will be unset
+   * also.
+   */
+  size_t GetJsonName(char* buf, size_t len) const;
+
+  /* Convenience version of the above function which copies the JSON name
+   * into the given string, returning false if the name is not set. */
+  template <class T>
+  bool GetJsonName(T* str) {
+    str->resize(GetJsonName(NULL, 0));
+    GetJsonName(&(*str)[0], str->size());
+    return str->size() > 0;
+  }
+
+  /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
+   * indicates whether this field should have lazy parsing handlers that yield
+   * the unparsed string for the submessage.
+   *
+   * TODO(haberman): I think we want to move this into a FieldOptions container
+   * when we add support for custom options (the FieldOptions struct will
+   * contain both regular FieldOptions like "lazy" *and* custom options). */
+  bool lazy() const;
+
+  /* For non-string, non-submessage fields, this indicates whether binary
+   * protobufs are encoded in packed or non-packed format.
+   *
+   * TODO(haberman): see note above about putting options like this into a
+   * FieldOptions container. */
+  bool packed() const;
+
+  /* An integer that can be used as an index into an array of fields for
+   * whatever message this field belongs to.  Guaranteed to be less than
+   * f->containing_type()->field_count().  May only be accessed once the def has
+   * been finalized. */
+  uint32_t index() const;
+
+  /* The MessageDef to which this field belongs.
+   *
+   * If this field has been added to a MessageDef, that message can be retrieved
+   * directly (this is always the case for frozen FieldDefs).
+   *
+   * If the field has not yet been added to a MessageDef, you can set the name
+   * of the containing type symbolically instead.  This is mostly useful for
+   * extensions, where the extension is declared separately from the message. */
+  const MessageDef* containing_type() const;
+  const char* containing_type_name();
+
+  /* The OneofDef to which this field belongs, or NULL if this field is not part
+   * of a oneof. */
+  const OneofDef* containing_oneof() const;
+
+  /* The field's type according to the enum in descriptor.proto.  This is not
+   * the same as UPB_TYPE_*, because it distinguishes between (for example)
+   * INT32 and SINT32, whereas our "type" enum does not.  This return of
+   * descriptor_type() is a function of type(), integer_format(), and
+   * is_tag_delimited().  Likewise set_descriptor_type() sets all three
+   * appropriately. */
+  DescriptorType descriptor_type() const;
+
+  /* Convenient field type tests. */
+  bool IsSubMessage() const;
+  bool IsString() const;
+  bool IsSequence() const;
+  bool IsPrimitive() const;
+  bool IsMap() const;
+
+  /* Whether this field must be able to explicitly represent presence:
+   *
+   * * This is always false for repeated fields (an empty repeated field is
+   *   equivalent to a repeated field with zero entries).
+   *
+   * * This is always true for submessages.
+   *
+   * * For other fields, it depends on the message (see
+   *   MessageDef::SetPrimitivesHavePresence())
+   */
+  bool HasPresence() const;
+
+  /* How integers are encoded.  Only meaningful for integer types.
+   * Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */
+  IntegerFormat integer_format() const;
+
+  /* Whether a submessage field is tag-delimited or not (if false, then
+   * length-delimited).  May only be set when type() == UPB_TYPE_MESSAGE. */
+  bool is_tag_delimited() const;
+
+  /* Returns the non-string default value for this fielddef, which may either
+   * be something the client set explicitly or the "default default" (0 for
+   * numbers, empty for strings).  The field's type indicates the type of the
+   * returned value, except for enum fields that are still mutable.
+   *
+   * Requires that the given function matches the field's current type. */
+  int64_t default_int64() const;
+  int32_t default_int32() const;
+  uint64_t default_uint64() const;
+  uint32_t default_uint32() const;
+  bool default_bool() const;
+  float default_float() const;
+  double default_double() const;
+
+  /* The resulting string is always NULL-terminated.  If non-NULL, the length
+   * will be stored in *len. */
+  const char *default_string(size_t* len) const;
+
+  /* For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either
+   * string or int32, and both of these methods will always return true.
+   *
+   * For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated.
+   * Enum defaults are unusual. They can be specified either as string or int32,
+   * but to be valid the enum must have that value as a member.  And if no
+   * default is specified, the "default default" comes from the EnumDef.
+   *
+   * We allow reading the default as either an int32 or a string, but only if
+   * we have a meaningful value to report.  We have a meaningful value if it was
+   * set explicitly, or if we could get the "default default" from the EnumDef.
+   * Also if you explicitly set the name and we find the number in the EnumDef */
+  bool EnumHasStringDefault() const;
+  bool EnumHasInt32Default() const;
+
+  /* Submessage and enum fields must reference a "subdef", which is the
+   * upb::MessageDef or upb::EnumDef that defines their type.  Note that when
+   * the FieldDef is mutable it may not have a subdef *yet*, but this function
+   * still returns true to indicate that the field's type requires a subdef. */
+  bool HasSubDef() const;
+
+  /* Returns the enum or submessage def for this field, if any.  The field's
+   * type must match (ie. you may only call enum_subdef() for fields where
+   * type() == UPB_TYPE_ENUM).  Returns NULL if the subdef has not been set or
+   * is currently set symbolically. */
+  const EnumDef* enum_subdef() const;
+  const MessageDef* message_subdef() const;
+
+  /* Returns the generic subdef for this field.  Requires that HasSubDef() (ie.
+   * only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). */
+  const Def* subdef() const;
+
+  /* Returns the symbolic name of the subdef.  If the subdef is currently set
+   * unresolved (ie. set symbolically) returns the symbolic name.  If it has
+   * been resolved to a specific subdef, returns the name from that subdef. */
+  const char* subdef_name() const;
+
+  /* Setters (non-const methods), only valid for mutable FieldDefs! ***********/
+
+  bool set_full_name(const char* fullname, upb::Status* s);
+  bool set_full_name(const std::string& fullname, upb::Status* s);
+
+  /* This may only be called if containing_type() == NULL (ie. the field has not
+   * been added to a message yet). */
+  bool set_containing_type_name(const char *name, Status* status);
+  bool set_containing_type_name(const std::string& name, Status* status);
+
+  /* Defaults to false.  When we freeze, we ensure that this can only be true
+   * for length-delimited message fields.  Prior to freezing this can be true or
+   * false with no restrictions. */
+  void set_lazy(bool lazy);
+
+  /* Defaults to true.  Sets whether this field is encoded in packed format. */
+  void set_packed(bool packed);
+
+  /* "type" or "descriptor_type" MUST be set explicitly before the fielddef is
+   * finalized.  These setters require that the enum value is valid; if the
+   * value did not come directly from an enum constant, the caller should
+   * validate it first with the functions above (CheckFieldType(), etc). */
+  void set_type(Type type);
+  void set_label(Label label);
+  void set_descriptor_type(DescriptorType type);
+  void set_is_extension(bool is_extension);
+
+  /* "number" and "name" must be set before the FieldDef is added to a
+   * MessageDef, and may not be set after that.
+   *
+   * "name" is the same as full_name()/set_full_name(), but since fielddefs
+   * most often use simple, non-qualified names, we provide this accessor
+   * also.  Generally only extensions will want to think of this name as
+   * fully-qualified. */
+  bool set_number(uint32_t number, upb::Status* s);
+  bool set_name(const char* name, upb::Status* s);
+  bool set_name(const std::string& name, upb::Status* s);
+
+  /* Sets the JSON name to the given string. */
+  /* TODO(haberman): implement.  Right now only default json_name (camelCase)
+   * is supported. */
+  bool set_json_name(const char* json_name, upb::Status* s);
+  bool set_json_name(const std::string& name, upb::Status* s);
+
+  /* Clears the JSON name. This will make it revert to its default, which is
+   * a camelCased version of the regular field name. */
+  void clear_json_name();
+
+  void set_integer_format(IntegerFormat format);
+  bool set_tag_delimited(bool tag_delimited, upb::Status* s);
+
+  /* Sets default value for the field.  The call must exactly match the type
+   * of the field.  Enum fields may use either setint32 or setstring to set
+   * the default numerically or symbolically, respectively, but symbolic
+   * defaults must be resolved before finalizing (see ResolveEnumDefault()).
+   *
+   * Changing the type of a field will reset its default. */
+  void set_default_int64(int64_t val);
+  void set_default_int32(int32_t val);
+  void set_default_uint64(uint64_t val);
+  void set_default_uint32(uint32_t val);
+  void set_default_bool(bool val);
+  void set_default_float(float val);
+  void set_default_double(double val);
+  bool set_default_string(const void *str, size_t len, Status *s);
+  bool set_default_string(const std::string &str, Status *s);
+  void set_default_cstr(const char *str, Status *s);
+
+  /* Before a fielddef is frozen, its subdef may be set either directly (with a
+   * upb::Def*) or symbolically.  Symbolic refs must be resolved before the
+   * containing msgdef can be frozen (see upb_resolve() above).  upb always
+   * guarantees that any def reachable from a live def will also be kept alive.
+   *
+   * Both methods require that upb_hassubdef(f) (so the type must be set prior
+   * to calling these methods).  Returns false if this is not the case, or if
+   * the given subdef is not of the correct type.  The subdef is reset if the
+   * field's type is changed.  The subdef can be set to NULL to clear it. */
+  bool set_subdef(const Def* subdef, Status* s);
+  bool set_enum_subdef(const EnumDef* subdef, Status* s);
+  bool set_message_subdef(const MessageDef* subdef, Status* s);
+  bool set_subdef_name(const char* name, Status* s);
+  bool set_subdef_name(const std::string &name, Status* s);
+
+ private:
+  UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef)
+};
+
+# endif  /* defined(__cplusplus) */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_fielddef *upb_fielddef_new(const void *owner);
+upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner);
+
+/* Include upb_refcounted methods like upb_fielddef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_fielddef, upb_fielddef_upcast2)
+
+/* Methods from upb_def. */
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+bool upb_fielddef_setfullname(upb_fielddef *f, const char *fullname,
+                              upb_status *s);
+
+bool upb_fielddef_typeisset(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
+const char *upb_fielddef_containingtypename(upb_fielddef *f);
+upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_istagdelim(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f);
+bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+const upb_def *upb_fielddef_subdef(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const char *upb_fielddef_subdefname(const upb_fielddef *f);
+
+void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type);
+void upb_fielddef_setdescriptortype(upb_fielddef *f, int type);
+void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label);
+bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s);
+bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_setjsonname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_clearjsonname(upb_fielddef *f);
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+                                        upb_status *s);
+void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension);
+void upb_fielddef_setlazy(upb_fielddef *f, bool lazy);
+void upb_fielddef_setpacked(upb_fielddef *f, bool packed);
+void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt);
+void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim);
+void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t val);
+void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t val);
+void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t val);
+void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t val);
+void upb_fielddef_setdefaultbool(upb_fielddef *f, bool val);
+void upb_fielddef_setdefaultfloat(upb_fielddef *f, float val);
+void upb_fielddef_setdefaultdouble(upb_fielddef *f, double val);
+bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
+                                upb_status *s);
+void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
+                                 upb_status *s);
+bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
+                            upb_status *s);
+bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
+                               upb_status *s);
+bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
+                                upb_status *s);
+bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
+                                upb_status *s);
+
+bool upb_fielddef_checklabel(int32_t label);
+bool upb_fielddef_checktype(int32_t type);
+bool upb_fielddef_checkdescriptortype(int32_t type);
+bool upb_fielddef_checkintfmt(int32_t fmt);
+
+UPB_END_EXTERN_C
+
+
+/* upb::MessageDef ************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+#ifdef __cplusplus
+
+/* Structure that describes a single .proto message type.
+ *
+ * Its base class is upb::Def (use upb::upcast() to convert). */
+class upb::MessageDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<MessageDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+  const char* name() const;
+  bool set_full_name(const char* fullname, Status* s);
+  bool set_full_name(const std::string& fullname, Status* s);
+
+  /* Call to freeze this MessageDef.
+   * WARNING: this will fail if this message has any unfrozen submessages!
+   * Messages with cycles must be frozen as a batch using upb::Def::Freeze(). */
+  bool Freeze(Status* s);
+
+  /* The number of fields that belong to the MessageDef. */
+  int field_count() const;
+
+  /* The number of oneofs that belong to the MessageDef. */
+  int oneof_count() const;
+
+  /* Adds a field (upb_fielddef object) to a msgdef.  Requires that the msgdef
+   * and the fielddefs are mutable.  The fielddef's name and number must be
+   * set, and the message may not already contain any field with this name or
+   * number, and this fielddef may not be part of another message.  In error
+   * cases false is returned and the msgdef is unchanged.
+   *
+   * If the given field is part of a oneof, this call succeeds if and only if
+   * that oneof is already part of this msgdef. (Note that adding a oneof to a
+   * msgdef automatically adds all of its fields to the msgdef at the time that
+   * the oneof is added, so it is usually more idiomatic to add the oneof's
+   * fields first then add the oneof to the msgdef. This case is supported for
+   * convenience.)
+   *
+   * If |f| is already part of this MessageDef, this method performs no action
+   * and returns true (success). Thus, this method is idempotent. */
+  bool AddField(FieldDef* f, Status* s);
+  bool AddField(const reffed_ptr<FieldDef>& f, Status* s);
+
+  /* Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef,
+   * oneof, and any fielddefs are mutable, that the fielddefs contained in the
+   * oneof do not have any name or number conflicts with existing fields in the
+   * msgdef, and that the oneof's name is unique among all oneofs in the msgdef.
+   * If the oneof is added successfully, all of its fields will be added
+   * directly to the msgdef as well. In error cases, false is returned and the
+   * msgdef is unchanged. */
+  bool AddOneof(OneofDef* o, Status* s);
+  bool AddOneof(const reffed_ptr<OneofDef>& o, Status* s);
+
+  upb_syntax_t syntax() const;
+
+  /* Returns false if we don't support this syntax value. */
+  bool set_syntax(upb_syntax_t syntax);
+
+  /* Set this to false to indicate that primitive fields should not have
+   * explicit presence information associated with them.  This will affect all
+   * fields added to this message.  Defaults to true. */
+  void SetPrimitivesHavePresence(bool have_presence);
+
+  /* These return NULL if the field is not found. */
+  FieldDef* FindFieldByNumber(uint32_t number);
+  FieldDef* FindFieldByName(const char *name, size_t len);
+  const FieldDef* FindFieldByNumber(uint32_t number) const;
+  const FieldDef* FindFieldByName(const char* name, size_t len) const;
+
+
+  FieldDef* FindFieldByName(const char *name) {
+    return FindFieldByName(name, strlen(name));
+  }
+  const FieldDef* FindFieldByName(const char *name) const {
+    return FindFieldByName(name, strlen(name));
+  }
+
+  template <class T>
+  FieldDef* FindFieldByName(const T& str) {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+  template <class T>
+  const FieldDef* FindFieldByName(const T& str) const {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+
+  OneofDef* FindOneofByName(const char* name, size_t len);
+  const OneofDef* FindOneofByName(const char* name, size_t len) const;
+
+  OneofDef* FindOneofByName(const char* name) {
+    return FindOneofByName(name, strlen(name));
+  }
+  const OneofDef* FindOneofByName(const char* name) const {
+    return FindOneofByName(name, strlen(name));
+  }
+
+  template<class T>
+  OneofDef* FindOneofByName(const T& str) {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+  template<class T>
+  const OneofDef* FindOneofByName(const T& str) const {
+    return FindOneofByName(str.c_str(), str.size());
+  }
+
+  /* Returns a new msgdef that is a copy of the given msgdef (and a copy of all
+   * the fields) but with any references to submessages broken and replaced
+   * with just the name of the submessage.  Returns NULL if memory allocation
+   * failed.
+   *
+   * TODO(haberman): which is more useful, keeping fields resolved or
+   * unresolving them?  If there's no obvious answer, Should this functionality
+   * just be moved into symtab.c? */
+  MessageDef* Dup(const void* owner) const;
+
+  /* Is this message a map entry? */
+  void setmapentry(bool map_entry);
+  bool mapentry() const;
+
+  /* Iteration over fields.  The order is undefined. */
+  class field_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit field_iterator(MessageDef* md);
+    static field_iterator end(MessageDef* md);
+
+    void operator++();
+    FieldDef* operator*() const;
+    bool operator!=(const field_iterator& other) const;
+    bool operator==(const field_iterator& other) const;
+
+   private:
+    upb_msg_field_iter iter_;
+  };
+
+  class const_field_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_field_iterator(const MessageDef* md);
+    static const_field_iterator end(const MessageDef* md);
+
+    void operator++();
+    const FieldDef* operator*() const;
+    bool operator!=(const const_field_iterator& other) const;
+    bool operator==(const const_field_iterator& other) const;
+
+   private:
+    upb_msg_field_iter iter_;
+  };
+
+  /* Iteration over oneofs. The order is undefined. */
+  class oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit oneof_iterator(MessageDef* md);
+    static oneof_iterator end(MessageDef* md);
+
+    void operator++();
+    OneofDef* operator*() const;
+    bool operator!=(const oneof_iterator& other) const;
+    bool operator==(const oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class const_oneof_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_oneof_iterator(const MessageDef* md);
+    static const_oneof_iterator end(const MessageDef* md);
+
+    void operator++();
+    const OneofDef* operator*() const;
+    bool operator!=(const const_oneof_iterator& other) const;
+    bool operator==(const const_oneof_iterator& other) const;
+
+   private:
+    upb_msg_oneof_iter iter_;
+  };
+
+  class FieldAccessor {
+   public:
+    explicit FieldAccessor(MessageDef* msg) : msg_(msg) {}
+    field_iterator begin() { return msg_->field_begin(); }
+    field_iterator end() { return msg_->field_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstFieldAccessor {
+   public:
+    explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_field_iterator begin() { return msg_->field_begin(); }
+    const_field_iterator end() { return msg_->field_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  class OneofAccessor {
+   public:
+    explicit OneofAccessor(MessageDef* msg) : msg_(msg) {}
+    oneof_iterator begin() { return msg_->oneof_begin(); }
+    oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    MessageDef* msg_;
+  };
+
+  class ConstOneofAccessor {
+   public:
+    explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {}
+    const_oneof_iterator begin() { return msg_->oneof_begin(); }
+    const_oneof_iterator end() { return msg_->oneof_end(); }
+   private:
+    const MessageDef* msg_;
+  };
+
+  field_iterator field_begin();
+  field_iterator field_end();
+  const_field_iterator field_begin() const;
+  const_field_iterator field_end() const;
+
+  oneof_iterator oneof_begin();
+  oneof_iterator oneof_end();
+  const_oneof_iterator oneof_begin() const;
+  const_oneof_iterator oneof_end() const;
+
+  FieldAccessor fields() { return FieldAccessor(this); }
+  ConstFieldAccessor fields() const { return ConstFieldAccessor(this); }
+  OneofAccessor oneofs() { return OneofAccessor(this); }
+  ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); }
+
+ private:
+  UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Returns NULL if memory allocation failed. */
+upb_msgdef *upb_msgdef_new(const void *owner);
+
+/* Include upb_refcounted methods like upb_msgdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2)
+
+bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status);
+
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+const char *upb_msgdef_name(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
+
+bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
+                         upb_status *s);
+bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
+                         upb_status *s);
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
+
+/* Field lookup in a couple of different variations:
+ *   - itof = int to field
+ *   - ntof = name to field
+ *   - ntofz = name to field, null-terminated string. */
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len);
+int upb_msgdef_numfields(const upb_msgdef *m);
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+                                                const char *name) {
+  return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+UPB_INLINE upb_fielddef *upb_msgdef_itof_mutable(upb_msgdef *m, uint32_t i) {
+  return (upb_fielddef*)upb_msgdef_itof(m, i);
+}
+
+UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m,
+                                                 const char *name, size_t len) {
+  return (upb_fielddef *)upb_msgdef_ntof(m, name, len);
+}
+
+/* Oneof lookup:
+ *   - ntoo = name to oneof
+ *   - ntooz = name to oneof, null-terminated string. */
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m,
+                                                 const char *name, size_t len) {
+  return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len);
+}
+
+/* Lookup of either field or oneof by name.  Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o);
+
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+                                       const upb_fielddef **f,
+                                       const upb_oneofdef **o) {
+  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
+
+/* Iteration over fields and oneofs.  For example:
+ *
+ * upb_msg_field_iter i;
+ * for(upb_msg_field_begin(&i, m);
+ *     !upb_msg_field_done(&i);
+ *     upb_msg_field_next(&i)) {
+ *   upb_fielddef *f = upb_msg_iter_field(&i);
+ *   // ...
+ * }
+ *
+ * For C we don't have separate iterators for const and non-const.
+ * It is the caller's responsibility to cast the upb_fielddef* to
+ * const if the upb_msgdef* is const. */
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+
+/* Similar to above, we also support iterating through the oneofs in a
+ * msgdef. */
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter);
+
+UPB_END_EXTERN_C
+
+
+/* upb::EnumDef ***************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+#ifdef __cplusplus
+
+/* Class that represents an enum.  Its base class is upb::Def (convert with
+ * upb::upcast()). */
+class upb::EnumDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<EnumDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Functionality from upb::Def. */
+  const char* full_name() const;
+  const char* name() const;
+  bool set_full_name(const char* fullname, Status* s);
+  bool set_full_name(const std::string& fullname, Status* s);
+
+  /* Call to freeze this EnumDef. */
+  bool Freeze(Status* s);
+
+  /* The value that is used as the default when no field default is specified.
+   * If not set explicitly, the first value that was added will be used.
+   * The default value must be a member of the enum.
+   * Requires that value_count() > 0. */
+  int32_t default_value() const;
+
+  /* Sets the default value.  If this value is not valid, returns false and an
+   * error message in status. */
+  bool set_default_value(int32_t val, Status* status);
+
+  /* Returns the number of values currently defined in the enum.  Note that
+   * multiple names can refer to the same number, so this may be greater than
+   * the total number of unique numbers. */
+  int value_count() const;
+
+  /* Adds a single name/number pair to the enum.  Fails if this name has
+   * already been used by another value. */
+  bool AddValue(const char* name, int32_t num, Status* status);
+  bool AddValue(const std::string& name, int32_t num, Status* status);
+
+  /* Lookups from name to integer, returning true if found. */
+  bool FindValueByName(const char* name, int32_t* num) const;
+
+  /* Finds the name corresponding to the given number, or NULL if none was
+   * found.  If more than one name corresponds to this number, returns the
+   * first one that was added. */
+  const char* FindValueByNumber(int32_t num) const;
+
+  /* Returns a new EnumDef with all the same values.  The new EnumDef will be
+   * owned by the given owner. */
+  EnumDef* Dup(const void* owner) const;
+
+  /* Iteration over name/value pairs.  The order is undefined.
+   * Adding an enum val invalidates any iterators.
+   *
+   * TODO: make compatible with range-for, with elements as pairs? */
+  class Iterator {
+   public:
+    explicit Iterator(const EnumDef*);
+
+    int32_t number();
+    const char *name();
+    bool Done();
+    void Next();
+
+   private:
+    upb_enum_iter iter_;
+  };
+
+ private:
+  UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_enumdef *upb_enumdef_new(const void *owner);
+upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner);
+
+/* Include upb_refcounted methods like upb_enumdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_enumdef, upb_enumdef_upcast2)
+
+bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status);
+
+/* From upb_def. */
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
+bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
+                             upb_status *s);
+
+int32_t upb_enumdef_default(const upb_enumdef *e);
+bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s);
+int upb_enumdef_numvals(const upb_enumdef *e);
+bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
+                        upb_status *status);
+
+/* Enum lookups:
+ * - ntoi:  look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton:  look up an integer, returning the name as a null-terminated
+ *          string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+                      int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+                                  const char *name, int32_t *num) {
+  return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+/*  upb_enum_iter i;
+ *  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
+ *    // ...
+ *  }
+ */
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+UPB_END_EXTERN_C
+
+/* upb::OneofDef **************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+#ifdef __cplusplus
+
+/* Class that represents a oneof. */
+class upb::OneofDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<OneofDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Returns the MessageDef that owns this OneofDef. */
+  const MessageDef* containing_type() const;
+
+  /* Returns the name of this oneof. This is the name used to look up the oneof
+   * by name once added to a message def. */
+  const char* name() const;
+  bool set_name(const char* name, Status* s);
+  bool set_name(const std::string& name, Status* s);
+
+  /* Returns the number of fields currently defined in the oneof. */
+  int field_count() const;
+
+  /* Adds a field to the oneof. The field must not have been added to any other
+   * oneof or msgdef. If the oneof is not yet part of a msgdef, then when the
+   * oneof is eventually added to a msgdef, all fields added to the oneof will
+   * also be added to the msgdef at that time. If the oneof is already part of a
+   * msgdef, the field must either be a part of that msgdef already, or must not
+   * be a part of any msgdef; in the latter case, the field is added to the
+   * msgdef as a part of this operation.
+   *
+   * The field may only have an OPTIONAL label, never REQUIRED or REPEATED.
+   *
+   * If |f| is already part of this MessageDef, this method performs no action
+   * and returns true (success). Thus, this method is idempotent. */
+  bool AddField(FieldDef* field, Status* s);
+  bool AddField(const reffed_ptr<FieldDef>& field, Status* s);
+
+  /* Looks up by name. */
+  const FieldDef* FindFieldByName(const char* name, size_t len) const;
+  FieldDef* FindFieldByName(const char* name, size_t len);
+  const FieldDef* FindFieldByName(const char* name) const {
+    return FindFieldByName(name, strlen(name));
+  }
+  FieldDef* FindFieldByName(const char* name) {
+    return FindFieldByName(name, strlen(name));
+  }
+
+  template <class T>
+  FieldDef* FindFieldByName(const T& str) {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+  template <class T>
+  const FieldDef* FindFieldByName(const T& str) const {
+    return FindFieldByName(str.c_str(), str.size());
+  }
+
+  /* Looks up by tag number. */
+  const FieldDef* FindFieldByNumber(uint32_t num) const;
+
+  /* Returns a new OneofDef with all the same fields. The OneofDef will be owned
+   * by the given owner. */
+  OneofDef* Dup(const void* owner) const;
+
+  /* Iteration over fields.  The order is undefined. */
+  class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> {
+   public:
+    explicit iterator(OneofDef* md);
+    static iterator end(OneofDef* md);
+
+    void operator++();
+    FieldDef* operator*() const;
+    bool operator!=(const iterator& other) const;
+    bool operator==(const iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  class const_iterator
+      : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
+   public:
+    explicit const_iterator(const OneofDef* md);
+    static const_iterator end(const OneofDef* md);
+
+    void operator++();
+    const FieldDef* operator*() const;
+    bool operator!=(const const_iterator& other) const;
+    bool operator==(const const_iterator& other) const;
+
+   private:
+    upb_oneof_iter iter_;
+  };
+
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_oneofdef *upb_oneofdef_new(const void *owner);
+upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner);
+
+/* Include upb_refcounted methods like upb_oneofdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast)
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s);
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
+                           const void *ref_donor,
+                           upb_status *s);
+
+/* Oneof lookups:
+ * - ntof:  look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof:  look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/*  upb_oneof_iter i;
+ *  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
+ *    // ...
+ *  }
+ */
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+
+UPB_END_EXTERN_C
+
+
+/* upb::FileDef ***************************************************************/
+
+#ifdef __cplusplus
+
+/* Class that represents a .proto file with some things defined in it.
+ *
+ * Many users won't care about FileDefs, but they are necessary if you want to
+ * read the values of file-level options. */
+class upb::FileDef {
+ public:
+  /* Returns NULL if memory allocation failed. */
+  static reffed_ptr<FileDef> New();
+
+  /* upb::RefCounted methods like Ref()/Unref(). */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Get/set name of the file (eg. "foo/bar.proto"). */
+  const char* name() const;
+  bool set_name(const char* name, Status* s);
+  bool set_name(const std::string& name, Status* s);
+
+  /* Package name for definitions inside the file (eg. "foo.bar"). */
+  const char* package() const;
+  bool set_package(const char* package, Status* s);
+
+  /* Syntax for the file.  Defaults to proto2. */
+  upb_syntax_t syntax() const;
+  void set_syntax(upb_syntax_t syntax);
+
+  /* Get the list of defs from the file.  These are returned in the order that
+   * they were added to the FileDef. */
+  int def_count() const;
+  const Def* def(int index) const;
+  Def* def(int index);
+
+  /* Get the list of dependencies from the file.  These are returned in the
+   * order that they were added to the FileDef. */
+  int dependency_count() const;
+  const FileDef* dependency(int index) const;
+
+  /* Adds defs to this file.  The def must not already belong to another
+   * file.
+   *
+   * Note: this does *not* ensure that this def's name is unique in this file!
+   * Use a SymbolTable if you want to check this property.  Especially since
+   * properly checking uniqueness would require a check across *all* files
+   * (including dependencies). */
+  bool AddDef(Def* def, Status* s);
+  bool AddMessage(MessageDef* m, Status* s);
+  bool AddEnum(EnumDef* e, Status* s);
+  bool AddExtension(FieldDef* f, Status* s);
+
+  /* Adds a dependency of this file. */
+  bool AddDependency(const FileDef* file);
+
+  /* Freezes this FileDef and all messages/enums under it.  All subdefs must be
+   * resolved and all messages/enums must validate.  Returns true if this
+   * succeeded.
+   *
+   * TODO(haberman): should we care whether the file's dependencies are frozen
+   * already? */
+  bool Freeze(Status* s);
+
+ private:
+  UPB_DISALLOW_POD_OPS(FileDef, upb::FileDef)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+upb_filedef *upb_filedef_new(const void *owner);
+
+/* Include upb_refcounted methods like upb_msgdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_filedef, upb_filedef_upcast)
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+size_t upb_filedef_defcount(const upb_filedef *f);
+size_t upb_filedef_depcount(const upb_filedef *f);
+const upb_def *upb_filedef_def(const upb_filedef *f, size_t i);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i);
+
+bool upb_filedef_freeze(upb_filedef *f, upb_status *s);
+bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s);
+bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s);
+bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s);
+
+bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
+                        upb_status *s);
+bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep);
+
+UPB_INLINE bool upb_filedef_addmsg(upb_filedef *f, upb_msgdef *m,
+                                   const void *ref_donor, upb_status *s) {
+  return upb_filedef_adddef(f, upb_msgdef_upcast_mutable(m), ref_donor, s);
+}
+
+UPB_INLINE bool upb_filedef_addenum(upb_filedef *f, upb_enumdef *e,
+                                    const void *ref_donor, upb_status *s) {
+  return upb_filedef_adddef(f, upb_enumdef_upcast_mutable(e), ref_donor, s);
+}
+
+UPB_INLINE bool upb_filedef_addext(upb_filedef *file, upb_fielddef *f,
+                                   const void *ref_donor, upb_status *s) {
+  return upb_filedef_adddef(file, upb_fielddef_upcast_mutable(f), ref_donor, s);
+}
+UPB_INLINE upb_def *upb_filedef_mutabledef(upb_filedef *f, int i) {
+  return (upb_def*)upb_filedef_def(f, i);
+}
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+UPB_INLINE const char* upb_safecstr(const std::string& str) {
+  assert(str.size() == std::strlen(str.c_str()));
+  return str.c_str();
+}
+
+/* Inline C++ wrappers. */
+namespace upb {
+
+inline Def* Def::Dup(const void* owner) const {
+  return upb_def_dup(this, owner);
+}
+inline Def::Type Def::def_type() const { return upb_def_type(this); }
+inline const char* Def::full_name() const { return upb_def_fullname(this); }
+inline const char* Def::name() const { return upb_def_name(this); }
+inline bool Def::set_full_name(const char* fullname, Status* s) {
+  return upb_def_setfullname(this, fullname, s);
+}
+inline bool Def::set_full_name(const std::string& fullname, Status* s) {
+  return upb_def_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool Def::Freeze(Def* const* defs, size_t n, Status* status) {
+  return upb_def_freeze(defs, n, status);
+}
+inline bool Def::Freeze(const std::vector<Def*>& defs, Status* status) {
+  return upb_def_freeze((Def* const*)&defs[0], defs.size(), status);
+}
+
+inline bool FieldDef::CheckType(int32_t val) {
+  return upb_fielddef_checktype(val);
+}
+inline bool FieldDef::CheckLabel(int32_t val) {
+  return upb_fielddef_checklabel(val);
+}
+inline bool FieldDef::CheckDescriptorType(int32_t val) {
+  return upb_fielddef_checkdescriptortype(val);
+}
+inline bool FieldDef::CheckIntegerFormat(int32_t val) {
+  return upb_fielddef_checkintfmt(val);
+}
+inline FieldDef::Type FieldDef::ConvertType(int32_t val) {
+  assert(CheckType(val));
+  return static_cast<FieldDef::Type>(val);
+}
+inline FieldDef::Label FieldDef::ConvertLabel(int32_t val) {
+  assert(CheckLabel(val));
+  return static_cast<FieldDef::Label>(val);
+}
+inline FieldDef::DescriptorType FieldDef::ConvertDescriptorType(int32_t val) {
+  assert(CheckDescriptorType(val));
+  return static_cast<FieldDef::DescriptorType>(val);
+}
+inline FieldDef::IntegerFormat FieldDef::ConvertIntegerFormat(int32_t val) {
+  assert(CheckIntegerFormat(val));
+  return static_cast<FieldDef::IntegerFormat>(val);
+}
+
+inline reffed_ptr<FieldDef> FieldDef::New() {
+  upb_fielddef *f = upb_fielddef_new(&f);
+  return reffed_ptr<FieldDef>(f, &f);
+}
+inline FieldDef* FieldDef::Dup(const void* owner) const {
+  return upb_fielddef_dup(this, owner);
+}
+inline const char* FieldDef::full_name() const {
+  return upb_fielddef_fullname(this);
+}
+inline bool FieldDef::set_full_name(const char* fullname, Status* s) {
+  return upb_fielddef_setfullname(this, fullname, s);
+}
+inline bool FieldDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_fielddef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool FieldDef::type_is_set() const {
+  return upb_fielddef_typeisset(this);
+}
+inline FieldDef::Type FieldDef::type() const { return upb_fielddef_type(this); }
+inline FieldDef::DescriptorType FieldDef::descriptor_type() const {
+  return upb_fielddef_descriptortype(this);
+}
+inline FieldDef::Label FieldDef::label() const {
+  return upb_fielddef_label(this);
+}
+inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); }
+inline const char* FieldDef::name() const { return upb_fielddef_name(this); }
+inline bool FieldDef::is_extension() const {
+  return upb_fielddef_isextension(this);
+}
+inline size_t FieldDef::GetJsonName(char* buf, size_t len) const {
+  return upb_fielddef_getjsonname(this, buf, len);
+}
+inline bool FieldDef::lazy() const {
+  return upb_fielddef_lazy(this);
+}
+inline void FieldDef::set_lazy(bool lazy) {
+  upb_fielddef_setlazy(this, lazy);
+}
+inline bool FieldDef::packed() const {
+  return upb_fielddef_packed(this);
+}
+inline uint32_t FieldDef::index() const {
+  return upb_fielddef_index(this);
+}
+inline void FieldDef::set_packed(bool packed) {
+  upb_fielddef_setpacked(this, packed);
+}
+inline const MessageDef* FieldDef::containing_type() const {
+  return upb_fielddef_containingtype(this);
+}
+inline const OneofDef* FieldDef::containing_oneof() const {
+  return upb_fielddef_containingoneof(this);
+}
+inline const char* FieldDef::containing_type_name() {
+  return upb_fielddef_containingtypename(this);
+}
+inline bool FieldDef::set_number(uint32_t number, Status* s) {
+  return upb_fielddef_setnumber(this, number, s);
+}
+inline bool FieldDef::set_name(const char *name, Status* s) {
+  return upb_fielddef_setname(this, name, s);
+}
+inline bool FieldDef::set_name(const std::string& name, Status* s) {
+  return upb_fielddef_setname(this, upb_safecstr(name), s);
+}
+inline bool FieldDef::set_json_name(const char *name, Status* s) {
+  return upb_fielddef_setjsonname(this, name, s);
+}
+inline bool FieldDef::set_json_name(const std::string& name, Status* s) {
+  return upb_fielddef_setjsonname(this, upb_safecstr(name), s);
+}
+inline void FieldDef::clear_json_name() {
+  upb_fielddef_clearjsonname(this);
+}
+inline bool FieldDef::set_containing_type_name(const char *name, Status* s) {
+  return upb_fielddef_setcontainingtypename(this, name, s);
+}
+inline bool FieldDef::set_containing_type_name(const std::string &name,
+                                               Status *s) {
+  return upb_fielddef_setcontainingtypename(this, upb_safecstr(name), s);
+}
+inline void FieldDef::set_type(upb_fieldtype_t type) {
+  upb_fielddef_settype(this, type);
+}
+inline void FieldDef::set_is_extension(bool is_extension) {
+  upb_fielddef_setisextension(this, is_extension);
+}
+inline void FieldDef::set_descriptor_type(FieldDef::DescriptorType type) {
+  upb_fielddef_setdescriptortype(this, type);
+}
+inline void FieldDef::set_label(upb_label_t label) {
+  upb_fielddef_setlabel(this, label);
+}
+inline bool FieldDef::IsSubMessage() const {
+  return upb_fielddef_issubmsg(this);
+}
+inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); }
+inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); }
+inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); }
+inline int64_t FieldDef::default_int64() const {
+  return upb_fielddef_defaultint64(this);
+}
+inline int32_t FieldDef::default_int32() const {
+  return upb_fielddef_defaultint32(this);
+}
+inline uint64_t FieldDef::default_uint64() const {
+  return upb_fielddef_defaultuint64(this);
+}
+inline uint32_t FieldDef::default_uint32() const {
+  return upb_fielddef_defaultuint32(this);
+}
+inline bool FieldDef::default_bool() const {
+  return upb_fielddef_defaultbool(this);
+}
+inline float FieldDef::default_float() const {
+  return upb_fielddef_defaultfloat(this);
+}
+inline double FieldDef::default_double() const {
+  return upb_fielddef_defaultdouble(this);
+}
+inline const char* FieldDef::default_string(size_t* len) const {
+  return upb_fielddef_defaultstr(this, len);
+}
+inline void FieldDef::set_default_int64(int64_t value) {
+  upb_fielddef_setdefaultint64(this, value);
+}
+inline void FieldDef::set_default_int32(int32_t value) {
+  upb_fielddef_setdefaultint32(this, value);
+}
+inline void FieldDef::set_default_uint64(uint64_t value) {
+  upb_fielddef_setdefaultuint64(this, value);
+}
+inline void FieldDef::set_default_uint32(uint32_t value) {
+  upb_fielddef_setdefaultuint32(this, value);
+}
+inline void FieldDef::set_default_bool(bool value) {
+  upb_fielddef_setdefaultbool(this, value);
+}
+inline void FieldDef::set_default_float(float value) {
+  upb_fielddef_setdefaultfloat(this, value);
+}
+inline void FieldDef::set_default_double(double value) {
+  upb_fielddef_setdefaultdouble(this, value);
+}
+inline bool FieldDef::set_default_string(const void *str, size_t len,
+                                         Status *s) {
+  return upb_fielddef_setdefaultstr(this, str, len, s);
+}
+inline bool FieldDef::set_default_string(const std::string& str, Status* s) {
+  return upb_fielddef_setdefaultstr(this, str.c_str(), str.size(), s);
+}
+inline void FieldDef::set_default_cstr(const char* str, Status* s) {
+  return upb_fielddef_setdefaultcstr(this, str, s);
+}
+inline bool FieldDef::HasSubDef() const { return upb_fielddef_hassubdef(this); }
+inline const Def* FieldDef::subdef() const { return upb_fielddef_subdef(this); }
+inline const MessageDef *FieldDef::message_subdef() const {
+  return upb_fielddef_msgsubdef(this);
+}
+inline const EnumDef *FieldDef::enum_subdef() const {
+  return upb_fielddef_enumsubdef(this);
+}
+inline const char* FieldDef::subdef_name() const {
+  return upb_fielddef_subdefname(this);
+}
+inline bool FieldDef::set_subdef(const Def* subdef, Status* s) {
+  return upb_fielddef_setsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_enum_subdef(const EnumDef* subdef, Status* s) {
+  return upb_fielddef_setenumsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_message_subdef(const MessageDef* subdef, Status* s) {
+  return upb_fielddef_setmsgsubdef(this, subdef, s);
+}
+inline bool FieldDef::set_subdef_name(const char* name, Status* s) {
+  return upb_fielddef_setsubdefname(this, name, s);
+}
+inline bool FieldDef::set_subdef_name(const std::string& name, Status* s) {
+  return upb_fielddef_setsubdefname(this, upb_safecstr(name), s);
+}
+
+inline reffed_ptr<MessageDef> MessageDef::New() {
+  upb_msgdef *m = upb_msgdef_new(&m);
+  return reffed_ptr<MessageDef>(m, &m);
+}
+inline const char *MessageDef::full_name() const {
+  return upb_msgdef_fullname(this);
+}
+inline const char *MessageDef::name() const {
+  return upb_msgdef_name(this);
+}
+inline upb_syntax_t MessageDef::syntax() const {
+  return upb_msgdef_syntax(this);
+}
+inline bool MessageDef::set_full_name(const char* fullname, Status* s) {
+  return upb_msgdef_setfullname(this, fullname, s);
+}
+inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_msgdef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool MessageDef::set_syntax(upb_syntax_t syntax) {
+  return upb_msgdef_setsyntax(this, syntax);
+}
+inline bool MessageDef::Freeze(Status* status) {
+  return upb_msgdef_freeze(this, status);
+}
+inline int MessageDef::field_count() const {
+  return upb_msgdef_numfields(this);
+}
+inline int MessageDef::oneof_count() const {
+  return upb_msgdef_numoneofs(this);
+}
+inline bool MessageDef::AddField(upb_fielddef* f, Status* s) {
+  return upb_msgdef_addfield(this, f, NULL, s);
+}
+inline bool MessageDef::AddField(const reffed_ptr<FieldDef>& f, Status* s) {
+  return upb_msgdef_addfield(this, f.get(), NULL, s);
+}
+inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) {
+  return upb_msgdef_addoneof(this, o, NULL, s);
+}
+inline bool MessageDef::AddOneof(const reffed_ptr<OneofDef>& o, Status* s) {
+  return upb_msgdef_addoneof(this, o.get(), NULL, s);
+}
+inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) {
+  return upb_msgdef_itof_mutable(this, number);
+}
+inline FieldDef* MessageDef::FindFieldByName(const char* name, size_t len) {
+  return upb_msgdef_ntof_mutable(this, name, len);
+}
+inline const FieldDef* MessageDef::FindFieldByNumber(uint32_t number) const {
+  return upb_msgdef_itof(this, number);
+}
+inline const FieldDef *MessageDef::FindFieldByName(const char *name,
+                                                   size_t len) const {
+  return upb_msgdef_ntof(this, name, len);
+}
+inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) {
+  return upb_msgdef_ntoo_mutable(this, name, len);
+}
+inline const OneofDef* MessageDef::FindOneofByName(const char* name,
+                                                   size_t len) const {
+  return upb_msgdef_ntoo(this, name, len);
+}
+inline MessageDef* MessageDef::Dup(const void *owner) const {
+  return upb_msgdef_dup(this, owner);
+}
+inline void MessageDef::setmapentry(bool map_entry) {
+  upb_msgdef_setmapentry(this, map_entry);
+}
+inline bool MessageDef::mapentry() const {
+  return upb_msgdef_mapentry(this);
+}
+inline MessageDef::field_iterator MessageDef::field_begin() {
+  return field_iterator(this);
+}
+inline MessageDef::field_iterator MessageDef::field_end() {
+  return field_iterator::end(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_begin() const {
+  return const_field_iterator(this);
+}
+inline MessageDef::const_field_iterator MessageDef::field_end() const {
+  return const_field_iterator::end(this);
+}
+
+inline MessageDef::oneof_iterator MessageDef::oneof_begin() {
+  return oneof_iterator(this);
+}
+inline MessageDef::oneof_iterator MessageDef::oneof_end() {
+  return oneof_iterator::end(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const {
+  return const_oneof_iterator(this);
+}
+inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const {
+  return const_oneof_iterator::end(this);
+}
+
+inline MessageDef::field_iterator::field_iterator(MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
+}
+inline MessageDef::field_iterator MessageDef::field_iterator::end(
+    MessageDef* md) {
+  MessageDef::field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline FieldDef* MessageDef::field_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void MessageDef::field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
+}
+inline bool MessageDef::field_iterator::operator==(
+    const field_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::field_iterator::operator!=(
+    const field_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::const_field_iterator::const_field_iterator(
+    const MessageDef* md) {
+  upb_msg_field_begin(&iter_, md);
+}
+inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end(
+    const MessageDef *md) {
+  MessageDef::const_field_iterator iter(md);
+  upb_msg_field_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const FieldDef* MessageDef::const_field_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void MessageDef::const_field_iterator::operator++() {
+  return upb_msg_field_next(&iter_);
+}
+inline bool MessageDef::const_field_iterator::operator==(
+    const const_field_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::const_field_iterator::operator!=(
+    const const_field_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end(
+    MessageDef* md) {
+  MessageDef::oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline OneofDef* MessageDef::oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::oneof_iterator::operator==(
+    const oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::oneof_iterator::operator!=(
+    const oneof_iterator &other) const {
+  return !(*this == other);
+}
+
+inline MessageDef::const_oneof_iterator::const_oneof_iterator(
+    const MessageDef* md) {
+  upb_msg_oneof_begin(&iter_, md);
+}
+inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end(
+    const MessageDef *md) {
+  MessageDef::const_oneof_iterator iter(md);
+  upb_msg_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const {
+  return upb_msg_iter_oneof(&iter_);
+}
+inline void MessageDef::const_oneof_iterator::operator++() {
+  return upb_msg_oneof_next(&iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator==(
+    const const_oneof_iterator &other) const {
+  return upb_strtable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool MessageDef::const_oneof_iterator::operator!=(
+    const const_oneof_iterator &other) const {
+  return !(*this == other);
+}
+
+inline reffed_ptr<EnumDef> EnumDef::New() {
+  upb_enumdef *e = upb_enumdef_new(&e);
+  return reffed_ptr<EnumDef>(e, &e);
+}
+inline const char* EnumDef::full_name() const {
+  return upb_enumdef_fullname(this);
+}
+inline const char* EnumDef::name() const {
+  return upb_enumdef_name(this);
+}
+inline bool EnumDef::set_full_name(const char* fullname, Status* s) {
+  return upb_enumdef_setfullname(this, fullname, s);
+}
+inline bool EnumDef::set_full_name(const std::string& fullname, Status* s) {
+  return upb_enumdef_setfullname(this, upb_safecstr(fullname), s);
+}
+inline bool EnumDef::Freeze(Status* status) {
+  return upb_enumdef_freeze(this, status);
+}
+inline int32_t EnumDef::default_value() const {
+  return upb_enumdef_default(this);
+}
+inline bool EnumDef::set_default_value(int32_t val, Status* status) {
+  return upb_enumdef_setdefault(this, val, status);
+}
+inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); }
+inline bool EnumDef::AddValue(const char* name, int32_t num, Status* status) {
+  return upb_enumdef_addval(this, name, num, status);
+}
+inline bool EnumDef::AddValue(const std::string& name, int32_t num,
+                              Status* status) {
+  return upb_enumdef_addval(this, upb_safecstr(name), num, status);
+}
+inline bool EnumDef::FindValueByName(const char* name, int32_t *num) const {
+  return upb_enumdef_ntoiz(this, name, num);
+}
+inline const char* EnumDef::FindValueByNumber(int32_t num) const {
+  return upb_enumdef_iton(this, num);
+}
+inline EnumDef* EnumDef::Dup(const void* owner) const {
+  return upb_enumdef_dup(this, owner);
+}
+
+inline EnumDef::Iterator::Iterator(const EnumDef* e) {
+  upb_enum_begin(&iter_, e);
+}
+inline int32_t EnumDef::Iterator::number() {
+  return upb_enum_iter_number(&iter_);
+}
+inline const char* EnumDef::Iterator::name() {
+  return upb_enum_iter_name(&iter_);
+}
+inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); }
+inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); }
+
+inline reffed_ptr<OneofDef> OneofDef::New() {
+  upb_oneofdef *o = upb_oneofdef_new(&o);
+  return reffed_ptr<OneofDef>(o, &o);
+}
+
+inline const MessageDef* OneofDef::containing_type() const {
+  return upb_oneofdef_containingtype(this);
+}
+inline const char* OneofDef::name() const {
+  return upb_oneofdef_name(this);
+}
+inline bool OneofDef::set_name(const char* name, Status* s) {
+  return upb_oneofdef_setname(this, name, s);
+}
+inline bool OneofDef::set_name(const std::string& name, Status* s) {
+  return upb_oneofdef_setname(this, upb_safecstr(name), s);
+}
+inline int OneofDef::field_count() const {
+  return upb_oneofdef_numfields(this);
+}
+inline bool OneofDef::AddField(FieldDef* field, Status* s) {
+  return upb_oneofdef_addfield(this, field, NULL, s);
+}
+inline bool OneofDef::AddField(const reffed_ptr<FieldDef>& field, Status* s) {
+  return upb_oneofdef_addfield(this, field.get(), NULL, s);
+}
+inline const FieldDef* OneofDef::FindFieldByName(const char* name,
+                                                 size_t len) const {
+  return upb_oneofdef_ntof(this, name, len);
+}
+inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const {
+  return upb_oneofdef_itof(this, num);
+}
+inline OneofDef::iterator OneofDef::begin() { return iterator(this); }
+inline OneofDef::iterator OneofDef::end() { return iterator::end(this); }
+inline OneofDef::const_iterator OneofDef::begin() const {
+  return const_iterator(this);
+}
+inline OneofDef::const_iterator OneofDef::end() const {
+  return const_iterator::end(this);
+}
+
+inline OneofDef::iterator::iterator(OneofDef* o) {
+  upb_oneof_begin(&iter_, o);
+}
+inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) {
+  OneofDef::iterator iter(o);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline FieldDef* OneofDef::iterator::operator*() const {
+  return upb_oneof_iter_field(&iter_);
+}
+inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); }
+inline bool OneofDef::iterator::operator==(const iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::iterator::operator!=(const iterator &other) const {
+  return !(*this == other);
+}
+
+inline OneofDef::const_iterator::const_iterator(const OneofDef* md) {
+  upb_oneof_begin(&iter_, md);
+}
+inline OneofDef::const_iterator OneofDef::const_iterator::end(
+    const OneofDef *md) {
+  OneofDef::const_iterator iter(md);
+  upb_oneof_iter_setdone(&iter.iter_);
+  return iter;
+}
+inline const FieldDef* OneofDef::const_iterator::operator*() const {
+  return upb_msg_iter_field(&iter_);
+}
+inline void OneofDef::const_iterator::operator++() {
+  return upb_oneof_next(&iter_);
+}
+inline bool OneofDef::const_iterator::operator==(
+    const const_iterator &other) const {
+  return upb_inttable_iter_isequal(&iter_, &other.iter_);
+}
+inline bool OneofDef::const_iterator::operator!=(
+    const const_iterator &other) const {
+  return !(*this == other);
+}
+
+inline reffed_ptr<FileDef> FileDef::New() {
+  upb_filedef *f = upb_filedef_new(&f);
+  return reffed_ptr<FileDef>(f, &f);
+}
+
+inline const char* FileDef::name() const {
+  return upb_filedef_name(this);
+}
+inline bool FileDef::set_name(const char* name, Status* s) {
+  return upb_filedef_setname(this, name, s);
+}
+inline bool FileDef::set_name(const std::string& name, Status* s) {
+  return upb_filedef_setname(this, upb_safecstr(name), s);
+}
+inline const char* FileDef::package() const {
+  return upb_filedef_package(this);
+}
+inline bool FileDef::set_package(const char* package, Status* s) {
+  return upb_filedef_setpackage(this, package, s);
+}
+inline int FileDef::def_count() const {
+  return upb_filedef_defcount(this);
+}
+inline const Def* FileDef::def(int index) const {
+  return upb_filedef_def(this, index);
+}
+inline Def* FileDef::def(int index) {
+  return const_cast<Def*>(upb_filedef_def(this, index));
+}
+inline int FileDef::dependency_count() const {
+  return upb_filedef_depcount(this);
+}
+inline const FileDef* FileDef::dependency(int index) const {
+  return upb_filedef_dep(this, index);
+}
+inline bool FileDef::AddDef(Def* def, Status* s) {
+  return upb_filedef_adddef(this, def, NULL, s);
+}
+inline bool FileDef::AddMessage(MessageDef* m, Status* s) {
+  return upb_filedef_addmsg(this, m, NULL, s);
+}
+inline bool FileDef::AddEnum(EnumDef* e, Status* s) {
+  return upb_filedef_addenum(this, e, NULL, s);
+}
+inline bool FileDef::AddExtension(FieldDef* f, Status* s) {
+  return upb_filedef_addext(this, f, NULL, s);
+}
+inline bool FileDef::AddDependency(const FileDef* file) {
+  return upb_filedef_adddep(this, file);
+}
+
+}  /* namespace upb */
+#endif
+
+#endif /* UPB_DEF_H_ */
+/*
+** This file contains definitions of structs that should be considered private
+** and NOT stable across versions of upb.
+**
+** The only reason they are declared here and not in .c files is to allow upb
+** and the application (if desired) to embed statically-initialized instances
+** of structures like defs.
+**
+** If you include this file, all guarantees of ABI compatibility go out the
+** window!  Any code that includes this file needs to recompile against the
+** exact same version of upb that they are linking against.
+**
+** You also need to recompile if you change the value of the UPB_DEBUG_REFS
+** flag.
+*/
+
+
+#ifndef UPB_STATICINIT_H_
+#define UPB_STATICINIT_H_
+
+#ifdef __cplusplus
+/* Because of how we do our typedefs, this header can't be included from C++. */
+#error This file cannot be included from C++
+#endif
+
+/* upb_refcounted *************************************************************/
+
+
+/* upb_def ********************************************************************/
+
+struct upb_def {
+  upb_refcounted base;
+
+  const char *fullname;
+  const upb_filedef* file;
+  char type;  /* A upb_deftype_t (char to save space) */
+
+  /* Used as a flag during the def's mutable stage.  Must be false unless
+   * it is currently being used by a function on the stack.  This allows
+   * us to easily determine which defs were passed into the function's
+   * current invocation. */
+  bool came_from_user;
+};
+
+#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \
+    { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false }
+
+
+/* upb_fielddef ***************************************************************/
+
+struct upb_fielddef {
+  upb_def base;
+
+  union {
+    int64_t sint;
+    uint64_t uint;
+    double dbl;
+    float flt;
+    void *bytes;
+  } defaultval;
+  union {
+    const upb_msgdef *def;  /* If !msg_is_symbolic. */
+    char *name;             /* If msg_is_symbolic. */
+  } msg;
+  union {
+    const upb_def *def;  /* If !subdef_is_symbolic. */
+    char *name;          /* If subdef_is_symbolic. */
+  } sub;  /* The msgdef or enumdef for this field, if upb_hassubdef(f). */
+  bool subdef_is_symbolic;
+  bool msg_is_symbolic;
+  const upb_oneofdef *oneof;
+  bool default_is_string;
+  bool type_is_set_;     /* False until type is explicitly set. */
+  bool is_extension_;
+  bool lazy_;
+  bool packed_;
+  upb_intfmt_t intfmt;
+  bool tagdelim;
+  upb_fieldtype_t type_;
+  upb_label_t label_;
+  uint32_t number_;
+  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
+  uint32_t index_;
+};
+
+extern const struct upb_refcounted_vtbl upb_fielddef_vtbl;
+
+#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy,   \
+                          packed, name, num, msgdef, subdef, selector_base,    \
+                          index, defaultval, refs, ref2s)                      \
+  {                                                                            \
+    UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s),        \
+        defaultval, {msgdef}, {subdef}, NULL, false, false,                    \
+        type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \
+        lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \
+  }
+
+
+/* upb_msgdef *****************************************************************/
+
+struct upb_msgdef {
+  upb_def base;
+
+  size_t selector_count;
+  uint32_t submsg_field_count;
+
+  /* Tables for looking up fields by number and name. */
+  upb_inttable itof;  /* int to field */
+  upb_strtable ntof;  /* name to field/oneof */
+
+  /* Is this a map-entry message? */
+  bool map_entry;
+
+  /* Whether this message has proto2 or proto3 semantics. */
+  upb_syntax_t syntax;
+
+  /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+extern const struct upb_refcounted_vtbl upb_msgdef_vtbl;
+
+/* TODO: also support static initialization of the oneofs table. This will be
+ * needed if we compile in descriptors that contain oneofs. */
+#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \
+                        map_entry, syntax, refs, ref2s)                       \
+  {                                                                           \
+    UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s),         \
+        selector_count, submsg_field_count, itof, ntof, map_entry, syntax     \
+  }
+
+
+/* upb_enumdef ****************************************************************/
+
+struct upb_enumdef {
+  upb_def base;
+
+  upb_strtable ntoi;
+  upb_inttable iton;
+  int32_t defaultval;
+};
+
+extern const struct upb_refcounted_vtbl upb_enumdef_vtbl;
+
+#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \
+  { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi,    \
+    iton, defaultval }
+
+
+/* upb_oneofdef ***************************************************************/
+
+struct upb_oneofdef {
+  upb_refcounted base;
+
+  const char *name;
+  upb_strtable ntof;
+  upb_inttable itof;
+  const upb_msgdef *parent;
+};
+
+extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl;
+
+#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \
+  { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), name, ntof, itof }
+
+
+/* upb_symtab *****************************************************************/
+
+struct upb_symtab {
+  upb_refcounted base;
+
+  upb_strtable symtab;
+};
+
+struct upb_filedef {
+  upb_refcounted base;
+
+  const char *name;
+  const char *package;
+  upb_syntax_t syntax;
+
+  upb_inttable defs;
+  upb_inttable deps;
+};
+
+extern const struct upb_refcounted_vtbl upb_filedef_vtbl;
+
+#endif  /* UPB_STATICINIT_H_ */
+/*
+** upb::Handlers (upb_handlers)
+**
+** A upb_handlers is like a virtual table for a upb_msgdef.  Each field of the
+** message can have associated functions that will be called when we are
+** parsing or visiting a stream of data.  This is similar to how handlers work
+** in SAX (the Simple API for XML).
+**
+** The handlers have no idea where the data is coming from, so a single set of
+** handlers could be used with two completely different data sources (for
+** example, a parser and a visitor over in-memory objects).  This decoupling is
+** the most important feature of upb, because it allows parsers and serializers
+** to be highly reusable.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_HANDLERS_H
+#define UPB_HANDLERS_H
+
+
+#ifdef __cplusplus
+namespace upb {
+class BufferHandle;
+class BytesHandler;
+class HandlerAttributes;
+class Handlers;
+template <class T> class Handler;
+template <class T> struct CanonicalType;
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle)
+UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler)
+UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr)
+UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted,
+                         upb_handlers, upb_refcounted)
+
+/* The maximum depth that the handler graph can have.  This is a resource limit
+ * for the C stack since we sometimes need to recursively traverse the graph.
+ * Cycles are ok; the traversal will stop when it detects a cycle, but we must
+ * hit the cycle before the maximum depth is reached.
+ *
+ * If having a single static limit is too inflexible, we can add another variant
+ * of Handlers::Freeze that allows specifying this as a parameter. */
+#define UPB_MAX_HANDLER_DEPTH 64
+
+/* All the different types of handlers that can be registered.
+ * Only needed for the advanced functions in upb::Handlers. */
+typedef enum {
+  UPB_HANDLER_INT32,
+  UPB_HANDLER_INT64,
+  UPB_HANDLER_UINT32,
+  UPB_HANDLER_UINT64,
+  UPB_HANDLER_FLOAT,
+  UPB_HANDLER_DOUBLE,
+  UPB_HANDLER_BOOL,
+  UPB_HANDLER_STARTSTR,
+  UPB_HANDLER_STRING,
+  UPB_HANDLER_ENDSTR,
+  UPB_HANDLER_STARTSUBMSG,
+  UPB_HANDLER_ENDSUBMSG,
+  UPB_HANDLER_STARTSEQ,
+  UPB_HANDLER_ENDSEQ
+} upb_handlertype_t;
+
+#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
+
+#define UPB_BREAK NULL
+
+/* A convenient definition for when no closure is needed. */
+extern char _upb_noclosure;
+#define UPB_NO_CLOSURE &_upb_noclosure
+
+/* A selector refers to a specific field handler in the Handlers object
+ * (for example: the STARTSUBMSG handler for field "field15"). */
+typedef int32_t upb_selector_t;
+
+UPB_BEGIN_EXTERN_C
+
+/* Forward-declares for C inline accessors.  We need to declare these here
+ * so we can "friend" them in the class declarations in C++. */
+UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
+                                             upb_selector_t s);
+UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr);
+UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+                                                   upb_selector_t s);
+
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h);
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+                                     const void *type);
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+                                     size_t ofs);
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h);
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h);
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h);
+
+UPB_END_EXTERN_C
+
+
+/* Static selectors for upb::Handlers. */
+#define UPB_STARTMSG_SELECTOR 0
+#define UPB_ENDMSG_SELECTOR 1
+#define UPB_STATIC_SELECTOR_COUNT 2
+
+/* Static selectors for upb::BytesHandler. */
+#define UPB_STARTSTR_SELECTOR 0
+#define UPB_STRING_SELECTOR 1
+#define UPB_ENDSTR_SELECTOR 2
+
+typedef void upb_handlerfree(void *d);
+
+#ifdef __cplusplus
+
+/* A set of attributes that accompanies a handler's function pointer. */
+class upb::HandlerAttributes {
+ public:
+  HandlerAttributes();
+  ~HandlerAttributes();
+
+  /* Sets the handler data that will be passed as the second parameter of the
+   * handler.  To free this pointer when the handlers are freed, call
+   * Handlers::AddCleanup(). */
+  bool SetHandlerData(const void *handler_data);
+  const void* handler_data() const;
+
+  /* Use this to specify the type of the closure.  This will be checked against
+   * all other closure types for handler that use the same closure.
+   * Registration will fail if this does not match all other non-NULL closure
+   * types. */
+  bool SetClosureType(const void *closure_type);
+  const void* closure_type() const;
+
+  /* Use this to specify the type of the returned closure.  Only used for
+   * Start*{String,SubMessage,Sequence} handlers.  This must match the closure
+   * type of any handlers that use it (for example, the StringBuf handler must
+   * match the closure returned from StartString). */
+  bool SetReturnClosureType(const void *return_closure_type);
+  const void* return_closure_type() const;
+
+  /* Set to indicate that the handler always returns "ok" (either "true" or a
+   * non-NULL closure).  This is a hint that can allow code generators to
+   * generate more efficient code. */
+  bool SetAlwaysOk(bool always_ok);
+  bool always_ok() const;
+
+ private:
+  friend UPB_INLINE const void * ::upb_handlerattr_handlerdata(
+      const upb_handlerattr *attr);
+#else
+struct upb_handlerattr {
+#endif
+  const void *handler_data_;
+  const void *closure_type_;
+  const void *return_closure_type_;
+  bool alwaysok_;
+};
+
+#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false}
+
+typedef struct {
+  upb_func *func;
+
+  /* It is wasteful to include the entire attributes here:
+   *
+   * * Some of the information is redundant (like storing the closure type
+   *   separately for each handler that must match).
+   * * Some of the info is only needed prior to freeze() (like closure types).
+   * * alignment padding wastes a lot of space for alwaysok_.
+   *
+   * If/when the size and locality of handlers is an issue, we can optimize this
+   * not to store the entire attr like this.  We do not expose the table's
+   * layout to allow this optimization in the future. */
+  upb_handlerattr attr;
+} upb_handlers_tabent;
+
+#ifdef __cplusplus
+
+/* Extra information about a buffer that is passed to a StringBuf handler.
+ * TODO(haberman): allow the handle to be pinned so that it will outlive
+ * the handler invocation. */
+class upb::BufferHandle {
+ public:
+  BufferHandle();
+  ~BufferHandle();
+
+  /* The beginning of the buffer.  This may be different than the pointer
+   * passed to a StringBuf handler because the handler may receive data
+   * that is from the middle or end of a larger buffer. */
+  const char* buffer() const;
+
+  /* The offset within the attached object where this buffer begins.  Only
+   * meaningful if there is an attached object. */
+  size_t object_offset() const;
+
+  /* Note that object_offset is the offset of "buf" within the attached
+   * object. */
+  void SetBuffer(const char* buf, size_t object_offset);
+
+  /* The BufferHandle can have an "attached object", which can be used to
+   * tunnel through a pointer to the buffer's underlying representation. */
+  template <class T>
+  void SetAttachedObject(const T* obj);
+
+  /* Returns NULL if the attached object is not of this type. */
+  template <class T>
+  const T* GetAttachedObject() const;
+
+ private:
+  friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h);
+  friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h,
+                                                const void *obj,
+                                                const void *type);
+  friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h,
+                                                const char *buf, size_t ofs);
+  friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h);
+  friend UPB_INLINE const void* ::upb_bufhandle_objtype(
+      const upb_bufhandle *h);
+  friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h);
+#else
+struct upb_bufhandle {
+#endif
+  const char *buf_;
+  const void *obj_;
+  const void *objtype_;
+  size_t objofs_;
+};
+
+#ifdef __cplusplus
+
+/* A upb::Handlers object represents the set of handlers associated with a
+ * message in the graph of messages.  You can think of it as a big virtual
+ * table with functions corresponding to all the events that can fire while
+ * parsing or visiting a message of a specific type.
+ *
+ * Any handlers that are not set behave as if they had successfully consumed
+ * the value.  Any unset Start* handlers will propagate their closure to the
+ * inner frame.
+ *
+ * The easiest way to create the *Handler objects needed by the Set* methods is
+ * with the UpbBind() and UpbMakeHandler() macros; see below. */
+class upb::Handlers {
+ public:
+  typedef upb_selector_t Selector;
+  typedef upb_handlertype_t Type;
+
+  typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
+  typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
+  typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
+  typedef Handler<bool (*)(void *, const void *, Status*)> EndMessageHandler;
+  typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
+  typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
+                             const BufferHandle *)> StringHandler;
+
+  template <class T> struct ValueHandler {
+    typedef Handler<bool(*)(void *, const void *, T)> H;
+  };
+
+  typedef ValueHandler<int32_t>::H     Int32Handler;
+  typedef ValueHandler<int64_t>::H     Int64Handler;
+  typedef ValueHandler<uint32_t>::H    UInt32Handler;
+  typedef ValueHandler<uint64_t>::H    UInt64Handler;
+  typedef ValueHandler<float>::H       FloatHandler;
+  typedef ValueHandler<double>::H      DoubleHandler;
+  typedef ValueHandler<bool>::H        BoolHandler;
+
+  /* Any function pointer can be converted to this and converted back to its
+   * correct type. */
+  typedef void GenericFunction();
+
+  typedef void HandlersCallback(const void *closure, upb_handlers *h);
+
+  /* Returns a new handlers object for the given frozen msgdef.
+   * Returns NULL if memory allocation failed. */
+  static reffed_ptr<Handlers> New(const MessageDef *m);
+
+  /* Convenience function for registering a graph of handlers that mirrors the
+   * graph of msgdefs for some message.  For "m" and all its children a new set
+   * of handlers will be created and the given callback will be invoked,
+   * allowing the client to register handlers for this message.  Note that any
+   * subhandlers set by the callback will be overwritten. */
+  static reffed_ptr<const Handlers> NewFrozen(const MessageDef *m,
+                                              HandlersCallback *callback,
+                                              const void *closure);
+
+  /* Functionality from upb::RefCounted. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* All handler registration functions return bool to indicate success or
+   * failure; details about failures are stored in this status object.  If a
+   * failure does occur, it must be cleared before the Handlers are frozen,
+   * otherwise the freeze() operation will fail.  The functions may *only* be
+   * used while the Handlers are mutable. */
+  const Status* status();
+  void ClearError();
+
+  /* Call to freeze these Handlers.  Requires that any SubHandlers are already
+   * frozen.  For cycles, you must use the static version below and freeze the
+   * whole graph at once. */
+  bool Freeze(Status* s);
+
+  /* Freezes the given set of handlers.  You may not freeze a handler without
+   * also freezing any handlers they point to. */
+  static bool Freeze(Handlers*const* handlers, int n, Status* s);
+  static bool Freeze(const std::vector<Handlers*>& handlers, Status* s);
+
+  /* Returns the msgdef associated with this handlers object. */
+  const MessageDef* message_def() const;
+
+  /* Adds the given pointer and function to the list of cleanup functions that
+   * will be run when these handlers are freed.  If this pointer has previously
+   * been registered, the function returns false and does nothing. */
+  bool AddCleanup(void *ptr, upb_handlerfree *cleanup);
+
+  /* Sets the startmsg handler for the message, which is defined as follows:
+   *
+   *   bool startmsg(MyType* closure) {
+   *     // Called when the message begins.  Returns true if processing should
+   *     // continue.
+   *     return true;
+   *   }
+   */
+  bool SetStartMessageHandler(const StartMessageHandler& handler);
+
+  /* Sets the endmsg handler for the message, which is defined as follows:
+   *
+   *   bool endmsg(MyType* closure, upb_status *status) {
+   *     // Called when processing of this message ends, whether in success or
+   *     // failure.  "status" indicates the final status of processing, and
+   *     // can also be modified in-place to update the final status.
+   *   }
+   */
+  bool SetEndMessageHandler(const EndMessageHandler& handler);
+
+  /* Sets the value handler for the given field, which is defined as follows
+   * (this is for an int32 field; other field types will pass their native
+   * C/C++ type for "val"):
+   *
+   *   bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
+   *     // Called when the field's value is encountered.  "d" contains
+   *     // whatever data was bound to this field when it was registered.
+   *     // Returns true if processing should continue.
+   *     return true;
+   *   }
+   *
+   *   handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
+   *
+   * The value type must exactly match f->type().
+   * For example, a handler that takes an int32_t parameter may only be used for
+   * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
+   *
+   * Returns false if the handler failed to register; in this case the cleanup
+   * handler (if any) will be called immediately.
+   */
+  bool SetInt32Handler (const FieldDef* f,  const Int32Handler& h);
+  bool SetInt64Handler (const FieldDef* f,  const Int64Handler& h);
+  bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h);
+  bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h);
+  bool SetFloatHandler (const FieldDef* f,  const FloatHandler& h);
+  bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h);
+  bool SetBoolHandler  (const FieldDef* f,   const BoolHandler& h);
+
+  /* Like the previous, but templated on the type on the value (ie. int32).
+   * This is mostly useful to call from other templates.  To call this you must
+   * specify the template parameter explicitly, ie:
+   *   h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
+  template <class T>
+  bool SetValueHandler(
+      const FieldDef *f,
+      const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler);
+
+  /* Sets handlers for a string field, which are defined as follows:
+   *
+   *   MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
+   *                          size_t size_hint) {
+   *     // Called when a string value begins.  The return value indicates the
+   *     // closure for the string.  "size_hint" indicates the size of the
+   *     // string if it is known, however if the string is length-delimited
+   *     // and the end-of-string is not available size_hint will be zero.
+   *     // This case is indistinguishable from the case where the size is
+   *     // known to be zero.
+   *     //
+   *     // TODO(haberman): is it important to distinguish these cases?
+   *     // If we had ssize_t as a type we could make -1 "unknown", but
+   *     // ssize_t is POSIX (not ANSI) and therefore less portable.
+   *     // In practice I suspect it won't be important to distinguish.
+   *     return closure;
+   *   }
+   *
+   *   size_t str(MyClosure* closure, const MyHandlerData* d,
+   *              const char *str, size_t len) {
+   *     // Called for each buffer of string data; the multiple physical buffers
+   *     // are all part of the same logical string.  The return value indicates
+   *     // how many bytes were consumed.  If this number is less than "len",
+   *     // this will also indicate that processing should be halted for now,
+   *     // like returning false or UPB_BREAK from any other callback.  If
+   *     // number is greater than "len", the excess bytes will be skipped over
+   *     // and not passed to the callback.
+   *     return len;
+   *   }
+   *
+   *   bool endstr(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a string value ends.  Return value indicates whether
+   *     // processing should continue.
+   *     return true;
+   *   }
+   */
+  bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h);
+  bool SetStringHandler(const FieldDef* f, const StringHandler& h);
+  bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h);
+
+  /* Sets the startseq handler, which is defined as follows:
+   *
+   *   MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a sequence (repeated field) begins.  The returned
+   *     // pointer indicates the closure for the sequence (or UPB_BREAK
+   *     // to interrupt processing).
+   *     return closure;
+   *   }
+   *
+   *   h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * repeated field.
+   */
+  bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h);
+
+  /* Sets the startsubmsg handler for the given field, which is defined as
+   * follows:
+   *
+   *   MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a submessage begins.  The returned pointer indicates the
+   *     // closure for the sequence (or UPB_BREAK to interrupt processing).
+   *     return closure;
+   *   }
+   *
+   *   h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
+   *                                           new MyHandlerData(...)));
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * submessage/group field.
+   */
+  bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h);
+
+  /* Sets the endsubmsg handler for the given field, which is defined as
+   * follows:
+   *
+   *   bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a submessage ends.  Returns true to continue processing.
+   *     return true;
+   *   }
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * submessage/group field.
+   */
+  bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h);
+
+  /* Starts the endsubseq handler for the given field, which is defined as
+   * follows:
+   *
+   *   bool endseq(MyClosure* c, const MyHandlerData* d) {
+   *     // Called when a sequence ends.  Returns true continue processing.
+   *     return true;
+   *   }
+   *
+   * Returns "false" if "f" does not belong to this message or is not a
+   * repeated field.
+   */
+  bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h);
+
+  /* Sets or gets the object that specifies handlers for the given field, which
+   * must be a submessage or group.  Returns NULL if no handlers are set. */
+  bool SetSubHandlers(const FieldDef* f, const Handlers* sub);
+  const Handlers* GetSubHandlers(const FieldDef* f) const;
+
+  /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the
+   * field. */
+  const Handlers* GetSubHandlers(Selector startsubmsg) const;
+
+  /* A selector refers to a specific field handler in the Handlers object
+   * (for example: the STARTSUBMSG handler for field "field15").
+   * On success, returns true and stores the selector in "s".
+   * If the FieldDef or Type are invalid, returns false.
+   * The returned selector is ONLY valid for Handlers whose MessageDef
+   * contains this FieldDef. */
+  static bool GetSelector(const FieldDef* f, Type type, Selector* s);
+
+  /* Given a START selector of any kind, returns the corresponding END selector. */
+  static Selector GetEndSelector(Selector start_selector);
+
+  /* Returns the function pointer for this handler.  It is the client's
+   * responsibility to cast to the correct function type before calling it. */
+  GenericFunction* GetHandler(Selector selector);
+
+  /* Sets the given attributes to the attributes for this selector. */
+  bool GetAttributes(Selector selector, HandlerAttributes* attr);
+
+  /* Returns the handler data that was registered with this handler. */
+  const void* GetHandlerData(Selector selector);
+
+  /* Could add any of the following functions as-needed, with some minor
+   * implementation changes:
+   *
+   * const FieldDef* GetFieldDef(Selector selector);
+   * static bool IsSequence(Selector selector); */
+
+ private:
+  UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers)
+
+  friend UPB_INLINE GenericFunction *::upb_handlers_gethandler(
+      const upb_handlers *h, upb_selector_t s);
+  friend UPB_INLINE const void *::upb_handlers_gethandlerdata(
+      const upb_handlers *h, upb_selector_t s);
+#else
+struct upb_handlers {
+#endif
+  upb_refcounted base;
+
+  const upb_msgdef *msg;
+  const upb_handlers **sub;
+  const void *top_closure_type;
+  upb_inttable cleanup_;
+  upb_status status_;  /* Used only when mutable. */
+  upb_handlers_tabent table[1];  /* Dynamically-sized field handler array. */
+};
+
+#ifdef __cplusplus
+
+namespace upb {
+
+/* Convenience macros for creating a Handler object that is wrapped with a
+ * type-safe wrapper function that converts the "void*" parameters/returns
+ * of the underlying C API into nice C++ function.
+ *
+ * Sample usage:
+ *   void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
+ *     // do stuff ...
+ *   }
+ *
+ *   // Handler that doesn't need any data bound to it.
+ *   void OnValue2(MyClosure* c, int32_t val) {
+ *     // do stuff ...
+ *   }
+ *
+ *   // Handler that returns bool so it can return failure if necessary.
+ *   bool OnValue3(MyClosure* c, int32_t val) {
+ *     // do stuff ...
+ *     return ok;
+ *   }
+ *
+ *   // Member function handler.
+ *   class MyClosure {
+ *    public:
+ *     void OnValue(int32_t val) {
+ *       // do stuff ...
+ *     }
+ *   };
+ *
+ *   // Takes ownership of the MyHandlerData.
+ *   handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
+ *   handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
+ *   handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
+ *   handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
+ */
+
+#ifdef UPB_CXX11
+
+/* In C++11, the "template" disambiguator can appear even outside templates,
+ * so all calls can safely use this pair of macros. */
+
+#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
+
+/* We have to be careful to only evaluate "d" once. */
+#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+
+#else
+
+/* Prior to C++11, the "template" disambiguator may only appear inside a
+ * template, so the regular macro must not use "template" */
+
+#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc<f>()
+
+#define UpbBind(f, d) upb::MatchFunc(f).GetFunc<f>((d))
+
+#endif  /* UPB_CXX11 */
+
+/* This macro must be used in C++98 for calls from inside a template.  But we
+ * define this variant in all cases; code that wants to be compatible with both
+ * C++98 and C++11 should always use this macro when calling from a template. */
+#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc<f>()
+
+/* We have to be careful to only evaluate "d" once. */
+#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+
+/* Handler: a struct that contains the (handler, data, deleter) tuple that is
+ * used to register all handlers.  Users can Make() these directly but it's
+ * more convenient to use the UpbMakeHandler/UpbBind macros above. */
+template <class T> class Handler {
+ public:
+  /* The underlying, handler function signature that upb uses internally. */
+  typedef T FuncPtr;
+
+  /* Intentionally implicit. */
+  template <class F> Handler(F func);
+  ~Handler();
+
+ private:
+  void AddCleanup(Handlers* h) const {
+    if (cleanup_func_) {
+      bool ok = h->AddCleanup(cleanup_data_, cleanup_func_);
+      UPB_ASSERT_VAR(ok, ok);
+    }
+  }
+
+  UPB_DISALLOW_COPY_AND_ASSIGN(Handler)
+  friend class Handlers;
+  FuncPtr handler_;
+  mutable HandlerAttributes attr_;
+  mutable bool registered_;
+  void *cleanup_data_;
+  upb_handlerfree *cleanup_func_;
+};
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+
+/* Handler function typedefs. */
+typedef bool upb_startmsg_handlerfunc(void *c, const void*);
+typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
+typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
+typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
+typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
+typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
+typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
+typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
+typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
+typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
+                                       size_t size_hint);
+typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
+                                      size_t n, const upb_bufhandle* handle);
+
+/* upb_bufhandle */
+size_t upb_bufhandle_objofs(const upb_bufhandle *h);
+
+/* upb_handlerattr */
+void upb_handlerattr_init(upb_handlerattr *attr);
+void upb_handlerattr_uninit(upb_handlerattr *attr);
+
+bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd);
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type);
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+                                          const void *type);
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok);
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr);
+
+UPB_INLINE const void *upb_handlerattr_handlerdata(
+    const upb_handlerattr *attr) {
+  return attr->handler_data_;
+}
+
+/* upb_handlers */
+typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
+upb_handlers *upb_handlers_new(const upb_msgdef *m,
+                               const void *owner);
+const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
+                                           const void *owner,
+                                           upb_handlers_callback *callback,
+                                           const void *closure);
+
+/* Include refcounted methods like upb_handlers_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast)
+
+const upb_status *upb_handlers_status(upb_handlers *h);
+void upb_handlers_clearerr(upb_handlers *h);
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
+bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
+
+bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
+                           upb_int32_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
+                           upb_int64_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
+                            upb_uint32_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
+                            upb_uint64_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
+                           upb_float_handlerfunc *func, upb_handlerattr *attr);
+bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
+                            upb_double_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
+                          upb_bool_handlerfunc *func,
+                          upb_handlerattr *attr);
+bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
+                              upb_startstr_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
+                            upb_string_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
+                            upb_endfield_handlerfunc *func,
+                            upb_handlerattr *attr);
+bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
+                              upb_startfield_handlerfunc *func,
+                              upb_handlerattr *attr);
+bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
+                                 upb_startfield_handlerfunc *func,
+                                 upb_handlerattr *attr);
+bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
+                               upb_endfield_handlerfunc *func,
+                               upb_handlerattr *attr);
+bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
+                            upb_endfield_handlerfunc *func,
+                            upb_handlerattr *attr);
+
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+                                 const upb_handlers *sub);
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+                                                const upb_fielddef *f);
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+                                                    upb_selector_t sel);
+
+UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
+                                             upb_selector_t s) {
+  return (upb_func *)h->table[s].func;
+}
+
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
+                          upb_handlerattr *attr);
+
+UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+                                                   upb_selector_t s) {
+  return upb_handlerattr_handlerdata(&h->table[s].attr);
+}
+
+#ifdef __cplusplus
+
+/* Handler types for single fields.
+ * Right now we only have one for TYPE_BYTES but ones for other types
+ * should follow.
+ *
+ * These follow the same handlers protocol for fields of a message. */
+class upb::BytesHandler {
+ public:
+  BytesHandler();
+  ~BytesHandler();
+#else
+struct upb_byteshandler {
+#endif
+  upb_handlers_tabent table[3];
+};
+
+void upb_byteshandler_init(upb_byteshandler *h);
+
+/* Caller must ensure that "d" outlives the handlers.
+ * TODO(haberman): should this have a "freeze" operation?  It's not necessary
+ * for memory management, but could be useful to force immutability and provide
+ * a convenient moment to verify that all registration succeeded. */
+bool upb_byteshandler_setstartstr(upb_byteshandler *h,
+                                  upb_startstr_handlerfunc *func, void *d);
+bool upb_byteshandler_setstring(upb_byteshandler *h,
+                                upb_string_handlerfunc *func, void *d);
+bool upb_byteshandler_setendstr(upb_byteshandler *h,
+                                upb_endfield_handlerfunc *func, void *d);
+
+/* "Static" methods */
+bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s);
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+                              upb_selector_t *s);
+UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
+  return start + 1;
+}
+
+/* Internal-only. */
+uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
+uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
+
+UPB_END_EXTERN_C
+
+/*
+** Inline definitions for handlers.h, which are particularly long and a bit
+** tricky.
+*/
+
+#ifndef UPB_HANDLERS_INL_H_
+#define UPB_HANDLERS_INL_H_
+
+#include <limits.h>
+
+/* C inline methods. */
+
+/* upb_bufhandle */
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) {
+  h->obj_ = NULL;
+  h->objtype_ = NULL;
+  h->buf_ = NULL;
+  h->objofs_ = 0;
+}
+UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) {
+  UPB_UNUSED(h);
+}
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+                                     const void *type) {
+  h->obj_ = obj;
+  h->objtype_ = type;
+}
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+                                     size_t ofs) {
+  h->buf_ = buf;
+  h->objofs_ = ofs;
+}
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) {
+  return h->obj_;
+}
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) {
+  return h->objtype_;
+}
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) {
+  return h->buf_;
+}
+
+
+#ifdef __cplusplus
+
+/* Type detection and typedefs for integer types.
+ * For platforms where there are multiple 32-bit or 64-bit types, we need to be
+ * able to enumerate them so we can properly create overloads for all variants.
+ *
+ * If any platform existed where there were three integer types with the same
+ * size, this would have to become more complicated.  For example, short, int,
+ * and long could all be 32-bits.  Even more diabolically, short, int, long,
+ * and long long could all be 64 bits and still be standard-compliant.
+ * However, few platforms are this strange, and it's unlikely that upb will be
+ * used on the strangest ones. */
+
+/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
+ * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
+ * of stdint.h.  We can't guarantee that someone else didn't include these first
+ * without defining __STDC_LIMIT_MACROS. */
+#define UPB_INT32_MAX 0x7fffffffLL
+#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
+#define UPB_INT64_MAX 0x7fffffffffffffffLL
+#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
+
+#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
+#define UPB_INT_IS_32BITS 1
+#endif
+
+#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
+#define UPB_LONG_IS_32BITS 1
+#endif
+
+#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
+#define UPB_LONG_IS_64BITS 1
+#endif
+
+#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
+#define UPB_LLONG_IS_64BITS 1
+#endif
+
+/* We use macros instead of typedefs so we can undefine them later and avoid
+ * leaking them outside this header file. */
+#if UPB_INT_IS_32BITS
+#define UPB_INT32_T int
+#define UPB_UINT32_T unsigned int
+
+#if UPB_LONG_IS_32BITS
+#define UPB_TWO_32BIT_TYPES 1
+#define UPB_INT32ALT_T long
+#define UPB_UINT32ALT_T unsigned long
+#endif  /* UPB_LONG_IS_32BITS */
+
+#elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
+#define UPB_INT32_T long
+#define UPB_UINT32_T unsigned long
+#endif  /* UPB_INT_IS_32BITS */
+
+
+#if UPB_LONG_IS_64BITS
+#define UPB_INT64_T long
+#define UPB_UINT64_T unsigned long
+
+#if UPB_LLONG_IS_64BITS
+#define UPB_TWO_64BIT_TYPES 1
+#define UPB_INT64ALT_T long long
+#define UPB_UINT64ALT_T unsigned long long
+#endif  /* UPB_LLONG_IS_64BITS */
+
+#elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
+#define UPB_INT64_T long long
+#define UPB_UINT64_T unsigned long long
+#endif  /* UPB_LONG_IS_64BITS */
+
+#undef UPB_INT32_MAX
+#undef UPB_INT32_MIN
+#undef UPB_INT64_MAX
+#undef UPB_INT64_MIN
+#undef UPB_INT_IS_32BITS
+#undef UPB_LONG_IS_32BITS
+#undef UPB_LONG_IS_64BITS
+#undef UPB_LLONG_IS_64BITS
+
+
+namespace upb {
+
+typedef void CleanupFunc(void *ptr);
+
+/* Template to remove "const" from "const T*" and just return "T*".
+ *
+ * We define a nonsense default because otherwise it will fail to instantiate as
+ * a function parameter type even in cases where we don't expect any caller to
+ * actually match the overload. */
+class CouldntRemoveConst {};
+template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
+template <class T> struct remove_constptr<const T *> { typedef T *type; };
+
+/* Template that we use below to remove a template specialization from
+ * consideration if it matches a specific type. */
+template <class T, class U> struct disable_if_same { typedef void Type; };
+template <class T> struct disable_if_same<T, T> {};
+
+template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
+
+template <class T1, class T2>
+struct FirstUnlessVoidOrBool {
+  typedef T1 value;
+};
+
+template <class T2>
+struct FirstUnlessVoidOrBool<void, T2> {
+  typedef T2 value;
+};
+
+template <class T2>
+struct FirstUnlessVoidOrBool<bool, T2> {
+  typedef T2 value;
+};
+
+template<class T, class U>
+struct is_same {
+  static bool value;
+};
+
+template<class T>
+struct is_same<T, T> {
+  static bool value;
+};
+
+template<class T, class U>
+bool is_same<T, U>::value = false;
+
+template<class T>
+bool is_same<T, T>::value = true;
+
+/* FuncInfo *******************************************************************/
+
+/* Info about the user's original, pre-wrapped function. */
+template <class C, class R = void>
+struct FuncInfo {
+  /* The type of the closure that the function takes (its first param). */
+  typedef C Closure;
+
+  /* The return type. */
+  typedef R Return;
+};
+
+/* Func ***********************************************************************/
+
+/* Func1, Func2, Func3: Template classes representing a function and its
+ * signature.
+ *
+ * Since the function is a template parameter, calling the function can be
+ * inlined at compile-time and does not require a function pointer at runtime.
+ * These functions are not bound to a handler data so have no data or cleanup
+ * handler. */
+struct UnboundFunc {
+  CleanupFunc *GetCleanup() { return NULL; }
+  void *GetData() { return NULL; }
+};
+
+template <class R, class P1, R F(P1), class I>
+struct Func1 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1) { return F(p1); }
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct Func2 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2) { return F(p1, p2); }
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
+struct Func3 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I>
+struct Func4 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I>
+struct Func5 : public UnboundFunc {
+  typedef R Return;
+  typedef I FuncInfo;
+  static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    return F(p1, p2, p3, p4, p5);
+  }
+};
+
+/* BoundFunc ******************************************************************/
+
+/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
+ * shall be bound to the function's second parameter.
+ * 
+ * Note that the second parameter is a const pointer, but our stored bound value
+ * is non-const so we can free it when the handlers are destroyed. */
+template <class T>
+struct BoundFunc {
+  typedef typename remove_constptr<T>::type MutableP2;
+  explicit BoundFunc(MutableP2 data_) : data(data_) {}
+  CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
+  MutableP2 GetData() { return data; }
+  MutableP2 data;
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct BoundFunc2 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
+struct BoundFunc3 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I>
+struct BoundFunc4 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I>
+struct BoundFunc5 : public BoundFunc<P2> {
+  typedef BoundFunc<P2> Base;
+  typedef I FuncInfo;
+  explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
+/* FuncSig ********************************************************************/
+
+/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
+ * *signature*, but without a specific function attached.
+ *
+ * These classes contain member functions that can be invoked with a
+ * specific function to return a Func/BoundFunc class. */
+template <class R, class P1>
+struct FuncSig1 {
+  template <R F(P1)>
+  Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
+    return Func1<R, P1, F, FuncInfo<P1, R> >();
+  }
+};
+
+template <class R, class P1, class P2>
+struct FuncSig2 {
+  template <R F(P1, P2)>
+  Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
+    return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2)>
+  BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3>
+struct FuncSig3 {
+  template <R F(P1, P2, P3)>
+  Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
+    return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3)>
+  BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3, class P4>
+struct FuncSig4 {
+  template <R F(P1, P2, P3, P4)>
+  Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
+    return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3, P4)>
+  BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct FuncSig5 {
+  template <R F(P1, P2, P3, P4, P5)>
+  Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
+    return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
+  }
+
+  template <R F(P1, P2, P3, P4, P5)>
+  BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
+      typename remove_constptr<P2>::type param2) {
+    return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
+  }
+};
+
+/* Overloaded template function that can construct the appropriate FuncSig*
+ * class given a function pointer by deducing the template parameters. */
+template <class R, class P1>
+inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig1<R, P1>();
+}
+
+template <class R, class P1, class P2>
+inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig2<R, P1, P2>();
+}
+
+template <class R, class P1, class P2, class P3>
+inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig3<R, P1, P2, P3>();
+}
+
+template <class R, class P1, class P2, class P3, class P4>
+inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig4<R, P1, P2, P3, P4>();
+}
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return FuncSig5<R, P1, P2, P3, P4, P5>();
+}
+
+/* MethodSig ******************************************************************/
+
+/* CallMethod*: a function template that calls a given method. */
+template <class R, class C, R (C::*F)()>
+R CallMethod0(C *obj) {
+  return ((*obj).*F)();
+}
+
+template <class R, class C, class P1, R (C::*F)(P1)>
+R CallMethod1(C *obj, P1 arg1) {
+  return ((*obj).*F)(arg1);
+}
+
+template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
+R CallMethod2(C *obj, P1 arg1, P2 arg2) {
+  return ((*obj).*F)(arg1, arg2);
+}
+
+template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
+R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
+  return ((*obj).*F)(arg1, arg2, arg3);
+}
+
+template <class R, class C, class P1, class P2, class P3, class P4,
+          R (C::*F)(P1, P2, P3, P4)>
+R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
+  return ((*obj).*F)(arg1, arg2, arg3, arg4);
+}
+
+/* MethodSig: like FuncSig, but for member functions.
+ *
+ * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
+ * more logic is required to special-case methods. */
+template <class R, class C>
+struct MethodSig0 {
+  template <R (C::*F)()>
+  Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
+    return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
+  }
+};
+
+template <class R, class C, class P1>
+struct MethodSig1 {
+  template <R (C::*F)(P1)>
+  Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
+    return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1)>
+  BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
+      typename remove_constptr<P1>::type param1) {
+    return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
+        param1);
+  }
+};
+
+template <class R, class C, class P1, class P2>
+struct MethodSig2 {
+  template <R (C::*F)(P1, P2)>
+  Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+  GetFunc() {
+    return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2)>
+  BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+                      FuncInfo<C *, R> >(param1);
+  }
+};
+
+template <class R, class C, class P1, class P2, class P3>
+struct MethodSig3 {
+  template <R (C::*F)(P1, P2, P3)>
+  Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
+  GetFunc() {
+    return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2, P3)>
+  BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+             FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+                      FuncInfo<C *, R> >(param1);
+  }
+};
+
+template <class R, class C, class P1, class P2, class P3, class P4>
+struct MethodSig4 {
+  template <R (C::*F)(P1, P2, P3, P4)>
+  Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+        FuncInfo<C *, R> >
+  GetFunc() {
+    return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+                 FuncInfo<C *, R> >();
+  }
+
+  template <R (C::*F)(P1, P2, P3, P4)>
+  BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+             FuncInfo<C *, R> >
+  GetFunc(typename remove_constptr<P1>::type param1) {
+    return BoundFunc5<R, C *, P1, P2, P3, P4,
+                      CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
+        param1);
+  }
+};
+
+template <class R, class C>
+inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig0<R, C>();
+}
+
+template <class R, class C, class P1>
+inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig1<R, C, P1>();
+}
+
+template <class R, class C, class P1, class P2>
+inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig2<R, C, P1, P2>();
+}
+
+template <class R, class C, class P1, class P2, class P3>
+inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig3<R, C, P1, P2, P3>();
+}
+
+template <class R, class C, class P1, class P2, class P3, class P4>
+inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
+  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
+  return MethodSig4<R, C, P1, P2, P3, P4>();
+}
+
+/* MaybeWrapReturn ************************************************************/
+
+/* Template class that attempts to wrap the return value of the function so it
+ * matches the expected type.  There are two main adjustments it may make:
+ *
+ *   1. If the function returns void, make it return the expected type and with
+ *      a value that always indicates success.
+ *   2. If the function returns bool, make it return the expected type with a
+ *      value that indicates success or failure.
+ *
+ * The "expected type" for return is:
+ *   1. void* for start handlers.  If the closure parameter has a different type
+ *      we will cast it to void* for the return in the success case.
+ *   2. size_t for string buffer handlers.
+ *   3. bool for everything else. */
+
+/* Template parameters are FuncN type and desired return type. */
+template <class F, class R, class Enable = void>
+struct MaybeWrapReturn;
+
+/* If the return type matches, return the given function unwrapped. */
+template <class F>
+struct MaybeWrapReturn<F, typename F::Return> {
+  typedef F Func;
+};
+
+/* Function wrapper that munges the return value from void to (bool)true. */
+template <class P1, class P2, void F(P1, P2)>
+bool ReturnTrue2(P1 p1, P2 p2) {
+  F(p1, p2);
+  return true;
+}
+
+template <class P1, class P2, class P3, void F(P1, P2, P3)>
+bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
+  F(p1, p2, p3);
+  return true;
+}
+
+/* Function wrapper that munges the return value from void to (void*)arg1  */
+template <class P1, class P2, void F(P1, P2)>
+void *ReturnClosure2(P1 p1, P2 p2) {
+  F(p1, p2);
+  return p1;
+}
+
+template <class P1, class P2, class P3, void F(P1, P2, P3)>
+void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
+  F(p1, p2, p3);
+  return p1;
+}
+
+/* Function wrapper that munges the return value from R to void*. */
+template <class R, class P1, class P2, R F(P1, P2)>
+void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
+  return F(p1, p2);
+}
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
+  return F(p1, p2, p3);
+}
+
+/* Function wrapper that munges the return value from bool to void*. */
+template <class P1, class P2, bool F(P1, P2)>
+void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
+  return F(p1, p2) ? p1 : UPB_BREAK;
+}
+
+template <class P1, class P2, class P3, bool F(P1, P2, P3)>
+void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
+  return F(p1, p2, p3) ? p1 : UPB_BREAK;
+}
+
+/* For the string callback, which takes five params, returns the size param. */
+template <class P1, class P2,
+          void F(P1, P2, const char *, size_t, const BufferHandle *)>
+size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
+                       const BufferHandle *p5) {
+  F(p1, p2, p3, p4, p5);
+  return p4;
+}
+
+/* For the string callback, which takes five params, returns the size param or
+ * zero. */
+template <class P1, class P2,
+          bool F(P1, P2, const char *, size_t, const BufferHandle *)>
+size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
+                  const BufferHandle *p5) {
+  return F(p1, p2, p3, p4, p5) ? p4 : 0;
+}
+
+/* If we have a function returning void but want a function returning bool, wrap
+ * it in a function that returns true. */
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
+  typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
+  typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
+};
+
+/* If our function returns void but we want one returning void*, wrap it in a
+ * function that returns the first argument. */
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
+  typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
+  typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
+};
+
+/* If our function returns R* but we want one returning void*, wrap it in a
+ * function that casts to void*. */
+template <class R, class P1, class P2, R *F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
+                       typename disable_if_same<R *, void *>::Type> {
+  typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
+};
+
+template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
+                       typename disable_if_same<R *, void *>::Type> {
+  typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
+      Func;
+};
+
+/* If our function returns bool but we want one returning void*, wrap it in a
+ * function that returns either the first param or UPB_BREAK. */
+template <class P1, class P2, bool F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
+  typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
+};
+
+template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
+  typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
+      Func;
+};
+
+/* If our function returns void but we want one returning size_t, wrap it in a
+ * function that returns the size argument. */
+template <class P1, class P2,
+          void F(P1, P2, const char *, size_t, const BufferHandle *), class I>
+struct MaybeWrapReturn<
+    Func5<void, P1, P2, const char *, size_t, const BufferHandle *, F, I>,
+          size_t> {
+  typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *,
+                ReturnStringLen<P1, P2, F>, I> Func;
+};
+
+/* If our function returns bool but we want one returning size_t, wrap it in a
+ * function that returns either 0 or the buf size. */
+template <class P1, class P2,
+          bool F(P1, P2, const char *, size_t, const BufferHandle *), class I>
+struct MaybeWrapReturn<
+    Func5<bool, P1, P2, const char *, size_t, const BufferHandle *, F, I>,
+    size_t> {
+  typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *,
+                ReturnNOr0<P1, P2, F>, I> Func;
+};
+
+/* ConvertParams **************************************************************/
+
+/* Template class that converts the function parameters if necessary, and
+ * ignores the HandlerData parameter if appropriate.
+ *
+ * Template parameter is the are FuncN function type. */
+template <class F, class T>
+struct ConvertParams;
+
+/* Function that discards the handler data parameter. */
+template <class R, class P1, R F(P1)>
+R IgnoreHandlerData2(void *p1, const void *hd) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1));
+}
+
+template <class R, class P1, class P2Wrapper, class P2Wrapped,
+          R F(P1, P2Wrapped)>
+R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2);
+}
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2, p3);
+}
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
+R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
+  UPB_UNUSED(hd);
+  return F(static_cast<P1>(p1), p2, p3, p4);
+}
+
+template <class R, class P1, R F(P1, const char*, size_t)>
+R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
+                                size_t p3, const BufferHandle *handle) {
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+  return F(static_cast<P1>(p1), p2, p3);
+}
+
+/* Function that casts the handler data parameter. */
+template <class R, class P1, class P2, R F(P1, P2)>
+R CastHandlerData2(void *c, const void *hd) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd));
+}
+
+template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
+          R F(P1, P2, P3Wrapped)>
+R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
+}
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5)>
+R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
+}
+
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
+R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
+                              size_t p4, const BufferHandle *handle) {
+  UPB_UNUSED(handle);
+  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
+}
+
+/* For unbound functions, ignore the handler data. */
+template <class R, class P1, R F(P1), class I, class T>
+struct ConvertParams<Func1<R, P1, F, I>, T> {
+  typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
+};
+
+template <class R, class P1, class P2, R F(P1, P2), class I,
+          class R2, class P1_2, class P2_2, class P3_2>
+struct ConvertParams<Func2<R, P1, P2, F, I>,
+                     R2 (*)(P1_2, P2_2, P3_2)> {
+  typedef Func3<R, void *, const void *, P3_2,
+                IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
+};
+
+/* For StringBuffer only; this ignores both the handler data and the
+ * BufferHandle. */
+template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
+struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
+  typedef Func5<R, void *, const void *, const char *, size_t,
+                const BufferHandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
+                I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+          class I, class T>
+struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
+  typedef Func5<R, void *, const void *, P2, P3, P4,
+                IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
+};
+
+/* For bound functions, cast the handler data. */
+template <class R, class P1, class P2, R F(P1, P2), class I, class T>
+struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
+  typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
+      Func;
+};
+
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
+          class R2, class P1_2, class P2_2, class P3_2>
+struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
+                     R2 (*)(P1_2, P2_2, P3_2)> {
+  typedef Func3<R, void *, const void *, P3_2,
+                CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
+};
+
+/* For StringBuffer only; this ignores the BufferHandle. */
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
+          class I, class T>
+struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
+  typedef Func5<R, void *, const void *, const char *, size_t,
+                const BufferHandle *, CastHandlerDataIgnoreHandle<R, P1, P2, F>,
+                I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+          R F(P1, P2, P3, P4, P5), class I, class T>
+struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
+  typedef Func5<R, void *, const void *, P3, P4, P5,
+                CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
+};
+
+/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
+ * variant C type. */
+#define TYPE_METHODS(utype, ltype, ctype, vtype)                               \
+  template <> struct CanonicalType<vtype> {                                    \
+    typedef ctype Type;                                                        \
+  };                                                                           \
+  template <>                                                                  \
+  inline bool Handlers::SetValueHandler<vtype>(                                \
+      const FieldDef *f,                                                       \
+      const Handlers::utype ## Handler& handler) {                             \
+    assert(!handler.registered_);                                              \
+    handler.AddCleanup(this);                                                  \
+    handler.registered_ = true;                                                \
+    return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \
+  }                                                                            \
+
+TYPE_METHODS(Double, double, double,   double)
+TYPE_METHODS(Float,  float,  float,    float)
+TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
+TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
+TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
+TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
+TYPE_METHODS(Bool,   bool,   bool,     bool)
+
+#ifdef UPB_TWO_32BIT_TYPES
+TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
+TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
+#endif
+
+#ifdef UPB_TWO_64BIT_TYPES
+TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
+TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
+#endif
+#undef TYPE_METHODS
+
+template <> struct CanonicalType<Status*> {
+  typedef Status* Type;
+};
+
+/* Type methods that are only one-per-canonical-type and not
+ * one-per-cvariant. */
+
+#define TYPE_METHODS(utype, ctype) \
+    inline bool Handlers::Set##utype##Handler(const FieldDef *f, \
+                                              const utype##Handler &h) { \
+      return SetValueHandler<ctype>(f, h); \
+    } \
+
+TYPE_METHODS(Double, double)
+TYPE_METHODS(Float,  float)
+TYPE_METHODS(UInt64, uint64_t)
+TYPE_METHODS(UInt32, uint32_t)
+TYPE_METHODS(Int64,  int64_t)
+TYPE_METHODS(Int32,  int32_t)
+TYPE_METHODS(Bool,   bool)
+#undef TYPE_METHODS
+
+template <class F> struct ReturnOf;
+
+template <class R, class P1, class P2>
+struct ReturnOf<R (*)(P1, P2)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3>
+struct ReturnOf<R (*)(P1, P2, P3)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3, class P4>
+struct ReturnOf<R (*)(P1, P2, P3, P4)> {
+  typedef R Return;
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
+  typedef R Return;
+};
+
+template<class T> const void *UniquePtrForType() {
+  static const char ch = 0;
+  return &ch;
+}
+
+template <class T>
+template <class F>
+inline Handler<T>::Handler(F func)
+    : registered_(false),
+      cleanup_data_(func.GetData()),
+      cleanup_func_(func.GetCleanup()) {
+  upb_handlerattr_sethandlerdata(&attr_, func.GetData());
+  typedef typename ReturnOf<T>::Return Return;
+  typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
+  typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
+      ReturnWrappedFunc;
+  handler_ = ReturnWrappedFunc().Call;
+
+  /* Set attributes based on what templates can statically tell us about the
+   * user's function. */
+
+  /* If the original function returns void, then we know that we wrapped it to
+   * always return ok. */
+  bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
+  attr_.SetAlwaysOk(always_ok);
+
+  /* Closure parameter and return type. */
+  attr_.SetClosureType(UniquePtrForType<typename F::FuncInfo::Closure>());
+
+  /* We use the closure type (from the first parameter) if the return type is
+   * void or bool, since these are the two cases we wrap to return the closure's
+   * type anyway.
+   *
+   * This is all nonsense for non START* handlers, but it doesn't matter because
+   * in that case the value will be ignored. */
+  typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
+                                         typename F::FuncInfo::Closure>::value
+      EffectiveReturn;
+  attr_.SetReturnClosureType(UniquePtrForType<EffectiveReturn>());
+}
+
+template <class T>
+inline Handler<T>::~Handler() {
+  assert(registered_);
+}
+
+inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); }
+inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); }
+inline bool HandlerAttributes::SetHandlerData(const void *hd) {
+  return upb_handlerattr_sethandlerdata(this, hd);
+}
+inline const void* HandlerAttributes::handler_data() const {
+  return upb_handlerattr_handlerdata(this);
+}
+inline bool HandlerAttributes::SetClosureType(const void *type) {
+  return upb_handlerattr_setclosuretype(this, type);
+}
+inline const void* HandlerAttributes::closure_type() const {
+  return upb_handlerattr_closuretype(this);
+}
+inline bool HandlerAttributes::SetReturnClosureType(const void *type) {
+  return upb_handlerattr_setreturnclosuretype(this, type);
+}
+inline const void* HandlerAttributes::return_closure_type() const {
+  return upb_handlerattr_returnclosuretype(this);
+}
+inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) {
+  return upb_handlerattr_setalwaysok(this, always_ok);
+}
+inline bool HandlerAttributes::always_ok() const {
+  return upb_handlerattr_alwaysok(this);
+}
+
+inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); }
+inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); }
+inline const char* BufferHandle::buffer() const {
+  return upb_bufhandle_buf(this);
+}
+inline size_t BufferHandle::object_offset() const {
+  return upb_bufhandle_objofs(this);
+}
+inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) {
+  upb_bufhandle_setbuf(this, buf, ofs);
+}
+template <class T>
+void BufferHandle::SetAttachedObject(const T* obj) {
+  upb_bufhandle_setobj(this, obj, UniquePtrForType<T>());
+}
+template <class T>
+const T* BufferHandle::GetAttachedObject() const {
+  return upb_bufhandle_objtype(this) == UniquePtrForType<T>()
+      ? static_cast<const T *>(upb_bufhandle_obj(this))
+                               : NULL;
+}
+
+inline reffed_ptr<Handlers> Handlers::New(const MessageDef *m) {
+  upb_handlers *h = upb_handlers_new(m, &h);
+  return reffed_ptr<Handlers>(h, &h);
+}
+inline reffed_ptr<const Handlers> Handlers::NewFrozen(
+    const MessageDef *m, upb_handlers_callback *callback,
+    const void *closure) {
+  const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+inline const Status* Handlers::status() {
+  return upb_handlers_status(this);
+}
+inline void Handlers::ClearError() {
+  return upb_handlers_clearerr(this);
+}
+inline bool Handlers::Freeze(Status *s) {
+  upb::Handlers* h = this;
+  return upb_handlers_freeze(&h, 1, s);
+}
+inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) {
+  return upb_handlers_freeze(handlers, n, s);
+}
+inline bool Handlers::Freeze(const std::vector<Handlers*>& h, Status* status) {
+  return upb_handlers_freeze((Handlers* const*)&h[0], h.size(), status);
+}
+inline const MessageDef *Handlers::message_def() const {
+  return upb_handlers_msgdef(this);
+}
+inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) {
+  return upb_handlers_addcleanup(this, p, func);
+}
+inline bool Handlers::SetStartMessageHandler(
+    const Handlers::StartMessageHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndMessageHandler(
+    const Handlers::EndMessageHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartStringHandler(const FieldDef *f,
+                                            const StartStringHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndStringHandler(const FieldDef *f,
+                                          const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStringHandler(const FieldDef *f,
+                                       const StringHandler& handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartSequenceHandler(
+    const FieldDef *f, const StartFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetStartSubMessageHandler(
+    const FieldDef *f, const StartFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f,
+                                              const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetEndSequenceHandler(const FieldDef *f,
+                                            const EndFieldHandler &handler) {
+  assert(!handler.registered_);
+  handler.registered_ = true;
+  handler.AddCleanup(this);
+  return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_);
+}
+inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) {
+  return upb_handlers_setsubhandlers(this, f, sub);
+}
+inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const {
+  return upb_handlers_getsubhandlers(this, f);
+}
+inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const {
+  return upb_handlers_getsubhandlers_sel(this, sel);
+}
+inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type,
+                                  Handlers::Selector *s) {
+  return upb_handlers_getselector(f, type, s);
+}
+inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) {
+  return upb_handlers_getendselector(start);
+}
+inline Handlers::GenericFunction *Handlers::GetHandler(
+    Handlers::Selector selector) {
+  return upb_handlers_gethandler(this, selector);
+}
+inline const void *Handlers::GetHandlerData(Handlers::Selector selector) {
+  return upb_handlers_gethandlerdata(this, selector);
+}
+
+inline BytesHandler::BytesHandler() {
+  upb_byteshandler_init(this);
+}
+
+inline BytesHandler::~BytesHandler() {}
+
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+
+#undef UPB_TWO_32BIT_TYPES
+#undef UPB_TWO_64BIT_TYPES
+#undef UPB_INT32_T
+#undef UPB_UINT32_T
+#undef UPB_INT32ALT_T
+#undef UPB_UINT32ALT_T
+#undef UPB_INT64_T
+#undef UPB_UINT64_T
+#undef UPB_INT64ALT_T
+#undef UPB_UINT64ALT_T
+
+#endif  /* UPB_HANDLERS_INL_H_ */
+
+#endif  /* UPB_HANDLERS_H */
+/*
+** upb::Sink (upb_sink)
+** upb::BytesSink (upb_bytessink)
+**
+** A upb_sink is an object that binds a upb_handlers object to some runtime
+** state.  It is the object that can actually receive data via the upb_handlers
+** interface.
+**
+** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
+** thread-safe.  You can create as many of them as you want, but each one may
+** only be used in a single thread at a time.
+**
+** If we compare with class-based OOP, a you can think of a upb_def as an
+** abstract base class, a upb_handlers as a concrete derived class, and a
+** upb_sink as an object (class instance).
+*/
+
+#ifndef UPB_SINK_H
+#define UPB_SINK_H
+
+
+#ifdef __cplusplus
+namespace upb {
+class BufferSource;
+class BytesSink;
+class Sink;
+}
+#endif
+
+UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc)
+UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink)
+UPB_DECLARE_TYPE(upb::Sink, upb_sink)
+
+#ifdef __cplusplus
+
+/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
+ * state.  It represents an endpoint to which data can be sent.
+ *
+ * TODO(haberman): right now all of these functions take selectors.  Should they
+ * take selectorbase instead?
+ *
+ * ie. instead of calling:
+ *   sink->StartString(FOO_FIELD_START_STRING, ...)
+ * a selector base would let you say:
+ *   sink->StartString(FOO_FIELD, ...)
+ *
+ * This would make call sites a little nicer and require emitting fewer selector
+ * definitions in .h files.
+ *
+ * But the current scheme has the benefit that you can retrieve a function
+ * pointer for any handler with handlers->GetHandler(selector), without having
+ * to have a separate GetHandler() function for each handler type.  The JIT
+ * compiler uses this.  To accommodate we'd have to expose a separate
+ * GetHandler() for every handler type.
+ *
+ * Also to ponder: selectors right now are independent of a specific Handlers
+ * instance.  In other words, they allocate a number to every possible handler
+ * that *could* be registered, without knowing anything about what handlers
+ * *are* registered.  That means that using selectors as table offsets prohibits
+ * us from compacting the handler table at Freeze() time.  If the table is very
+ * sparse, this could be wasteful.
+ *
+ * Having another selector-like thing that is specific to a Handlers instance
+ * would allow this compacting, but then it would be impossible to write code
+ * ahead-of-time that can be bound to any Handlers instance at runtime.  For
+ * example, a .proto file parser written as straight C will not know what
+ * Handlers it will be bound to, so when it calls sink->StartString() what
+ * selector will it pass?  It needs a selector like we have today, that is
+ * independent of any particular upb::Handlers.
+ *
+ * Is there a way then to allow Handlers table compaction? */
+class upb::Sink {
+ public:
+  /* Constructor with no initialization; must be Reset() before use. */
+  Sink() {}
+
+  /* Constructs a new sink for the given frozen handlers and closure.
+   *
+   * TODO: once the Handlers know the expected closure type, verify that T
+   * matches it. */
+  template <class T> Sink(const Handlers* handlers, T* closure);
+
+  /* Resets the value of the sink. */
+  template <class T> void Reset(const Handlers* handlers, T* closure);
+
+  /* Returns the top-level object that is bound to this sink.
+   *
+   * TODO: once the Handlers know the expected closure type, verify that T
+   * matches it. */
+  template <class T> T* GetObject() const;
+
+  /* Functions for pushing data into the sink.
+   *
+   * These return false if processing should stop (either due to error or just
+   * to suspend).
+   *
+   * These may not be called from within one of the same sink's handlers (in
+   * other words, handlers are not re-entrant). */
+
+  /* Should be called at the start and end of every message; both the top-level
+   * message and submessages.  This means that submessages should use the
+   * following sequence:
+   *   sink->StartSubMessage(startsubmsg_selector);
+   *   sink->StartMessage();
+   *   // ...
+   *   sink->EndMessage(&status);
+   *   sink->EndSubMessage(endsubmsg_selector); */
+  bool StartMessage();
+  bool EndMessage(Status* status);
+
+  /* Putting of individual values.  These work for both repeated and
+   * non-repeated fields, but for repeated fields you must wrap them in
+   * calls to StartSequence()/EndSequence(). */
+  bool PutInt32(Handlers::Selector s, int32_t val);
+  bool PutInt64(Handlers::Selector s, int64_t val);
+  bool PutUInt32(Handlers::Selector s, uint32_t val);
+  bool PutUInt64(Handlers::Selector s, uint64_t val);
+  bool PutFloat(Handlers::Selector s, float val);
+  bool PutDouble(Handlers::Selector s, double val);
+  bool PutBool(Handlers::Selector s, bool val);
+
+  /* Putting of string/bytes values.  Each string can consist of zero or more
+   * non-contiguous buffers of data.
+   *
+   * For StartString(), the function will write a sink for the string to "sub."
+   * The sub-sink must be used for any/all PutStringBuffer() calls. */
+  bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub);
+  size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len,
+                         const BufferHandle *handle);
+  bool EndString(Handlers::Selector s);
+
+  /* For submessage fields.
+   *
+   * For StartSubMessage(), the function will write a sink for the string to
+   * "sub." The sub-sink must be used for any/all handlers called within the
+   * submessage. */
+  bool StartSubMessage(Handlers::Selector s, Sink* sub);
+  bool EndSubMessage(Handlers::Selector s);
+
+  /* For repeated fields of any type, the sequence of values must be wrapped in
+   * these calls.
+   *
+   * For StartSequence(), the function will write a sink for the string to
+   * "sub." The sub-sink must be used for any/all handlers called within the
+   * sequence. */
+  bool StartSequence(Handlers::Selector s, Sink* sub);
+  bool EndSequence(Handlers::Selector s);
+
+  /* Copy and assign specifically allowed.
+   * We don't even bother making these members private because so many
+   * functions need them and this is mainly just a dumb data container anyway.
+   */
+#else
+struct upb_sink {
+#endif
+  const upb_handlers *handlers;
+  void *closure;
+};
+
+#ifdef __cplusplus
+class upb::BytesSink {
+ public:
+  BytesSink() {}
+
+  /* Constructs a new sink for the given frozen handlers and closure.
+   *
+   * TODO(haberman): once the Handlers know the expected closure type, verify
+   * that T matches it. */
+  template <class T> BytesSink(const BytesHandler* handler, T* closure);
+
+  /* Resets the value of the sink. */
+  template <class T> void Reset(const BytesHandler* handler, T* closure);
+
+  bool Start(size_t size_hint, void **subc);
+  size_t PutBuffer(void *subc, const char *buf, size_t len,
+                   const BufferHandle *handle);
+  bool End();
+#else
+struct upb_bytessink {
+#endif
+  const upb_byteshandler *handler;
+  void *closure;
+};
+
+#ifdef __cplusplus
+
+/* A class for pushing a flat buffer of data to a BytesSink.
+ * You can construct an instance of this to get a resumable source,
+ * or just call the static PutBuffer() to do a non-resumable push all in one
+ * go. */
+class upb::BufferSource {
+ public:
+  BufferSource();
+  BufferSource(const char* buf, size_t len, BytesSink* sink);
+
+  /* Returns true if the entire buffer was pushed successfully.  Otherwise the
+   * next call to PutNext() will resume where the previous one left off.
+   * TODO(haberman): implement this. */
+  bool PutNext();
+
+  /* A static version; with this version is it not possible to resume in the
+   * case of failure or a partially-consumed buffer. */
+  static bool PutBuffer(const char* buf, size_t len, BytesSink* sink);
+
+  template <class T> static bool PutBuffer(const T& str, BytesSink* sink) {
+    return PutBuffer(str.c_str(), str.size(), sink);
+  }
+#else
+struct upb_bufsrc {
+  char dummy;
+#endif
+};
+
+UPB_BEGIN_EXTERN_C
+
+/* Inline definitions. */
+
+UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h,
+                                    void *closure) {
+  s->handler = h;
+  s->closure = closure;
+}
+
+UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint,
+                                    void **subc) {
+  typedef upb_startstr_handlerfunc func;
+  func *start;
+  *subc = s->closure;
+  if (!s->handler) return true;
+  start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func;
+
+  if (!start) return true;
+  *subc = start(s->closure, upb_handlerattr_handlerdata(
+                                &s->handler->table[UPB_STARTSTR_SELECTOR].attr),
+                size_hint);
+  return *subc != NULL;
+}
+
+UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc,
+                                       const char *buf, size_t size,
+                                       const upb_bufhandle* handle) {
+  typedef upb_string_handlerfunc func;
+  func *putbuf;
+  if (!s->handler) return true;
+  putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func;
+
+  if (!putbuf) return true;
+  return putbuf(subc, upb_handlerattr_handlerdata(
+                          &s->handler->table[UPB_STRING_SELECTOR].attr),
+                buf, size, handle);
+}
+
+UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) {
+  typedef upb_endfield_handlerfunc func;
+  func *end;
+  if (!s->handler) return true;
+  end = (func *)s->handler->table[UPB_ENDSTR_SELECTOR].func;
+
+  if (!end) return true;
+  return end(s->closure,
+             upb_handlerattr_handlerdata(
+                 &s->handler->table[UPB_ENDSTR_SELECTOR].attr));
+}
+
+UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len,
+                                  upb_bytessink *sink) {
+  void *subc;
+  bool ret;
+  upb_bufhandle handle;
+  upb_bufhandle_init(&handle);
+  upb_bufhandle_setbuf(&handle, buf, 0);
+  ret = upb_bytessink_start(sink, len, &subc);
+  if (ret && len != 0) {
+    ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
+  }
+  if (ret) {
+    ret = upb_bytessink_end(sink);
+  }
+  upb_bufhandle_uninit(&handle);
+  return ret;
+}
+
+#define PUTVAL(type, ctype)                                                    \
+  UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel,          \
+                                     ctype val) {                              \
+    typedef upb_##type##_handlerfunc functype;                                 \
+    functype *func;                                                            \
+    const void *hd;                                                            \
+    if (!s->handlers) return true;                                             \
+    func = (functype *)upb_handlers_gethandler(s->handlers, sel);              \
+    if (!func) return true;                                                    \
+    hd = upb_handlers_gethandlerdata(s->handlers, sel);                        \
+    return func(s->closure, hd, val);                                          \
+  }
+
+PUTVAL(int32,  int32_t)
+PUTVAL(int64,  int64_t)
+PUTVAL(uint32, uint32_t)
+PUTVAL(uint64, uint64_t)
+PUTVAL(float,  float)
+PUTVAL(double, double)
+PUTVAL(bool,   bool)
+#undef PUTVAL
+
+UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
+  s->handlers = h;
+  s->closure = c;
+}
+
+UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel,
+                                     const char *buf, size_t n,
+                                     const upb_bufhandle *handle) {
+  typedef upb_string_handlerfunc func;
+  func *handler;
+  const void *hd;
+  if (!s->handlers) return n;
+  handler = (func *)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!handler) return n;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return handler(s->closure, hd, buf, n, handle);
+}
+
+UPB_INLINE bool upb_sink_startmsg(upb_sink *s) {
+  typedef upb_startmsg_handlerfunc func;
+  func *startmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR);
+
+  if (!startmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR);
+  return startmsg(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) {
+  typedef upb_endmsg_handlerfunc func;
+  func *endmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR);
+
+  if (!endmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR);
+  return endmsg(s->closure, hd, status);
+}
+
+UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel,
+                                  upb_sink *sub) {
+  typedef upb_startfield_handlerfunc func;
+  func *startseq;
+  const void *hd;
+  sub->closure = s->closure;
+  sub->handlers = s->handlers;
+  if (!s->handlers) return true;
+  startseq = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startseq) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startseq(s->closure, hd);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endseq;
+  const void *hd;
+  if (!s->handlers) return true;
+  endseq = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endseq) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endseq(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel,
+                                  size_t size_hint, upb_sink *sub) {
+  typedef upb_startstr_handlerfunc func;
+  func *startstr;
+  const void *hd;
+  sub->closure = s->closure;
+  sub->handlers = s->handlers;
+  if (!s->handlers) return true;
+  startstr = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startstr) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startstr(s->closure, hd, size_hint);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endstr;
+  const void *hd;
+  if (!s->handlers) return true;
+  endstr = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endstr) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endstr(s->closure, hd);
+}
+
+UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel,
+                                     upb_sink *sub) {
+  typedef upb_startfield_handlerfunc func;
+  func *startsubmsg;
+  const void *hd;
+  sub->closure = s->closure;
+  if (!s->handlers) {
+    sub->handlers = NULL;
+    return true;
+  }
+  sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel);
+  startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!startsubmsg) return true;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  sub->closure = startsubmsg(s->closure, hd);
+  return sub->closure ? true : false;
+}
+
+UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
+  typedef upb_endfield_handlerfunc func;
+  func *endsubmsg;
+  const void *hd;
+  if (!s->handlers) return true;
+  endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel);
+
+  if (!endsubmsg) return s->closure;
+  hd = upb_handlers_gethandlerdata(s->handlers, sel);
+  return endsubmsg(s->closure, hd);
+}
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+template <class T> Sink::Sink(const Handlers* handlers, T* closure) {
+  upb_sink_reset(this, handlers, closure);
+}
+template <class T>
+inline void Sink::Reset(const Handlers* handlers, T* closure) {
+  upb_sink_reset(this, handlers, closure);
+}
+inline bool Sink::StartMessage() {
+  return upb_sink_startmsg(this);
+}
+inline bool Sink::EndMessage(Status* status) {
+  return upb_sink_endmsg(this, status);
+}
+inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) {
+  return upb_sink_putint32(this, sel, val);
+}
+inline bool Sink::PutInt64(Handlers::Selector sel, int64_t val) {
+  return upb_sink_putint64(this, sel, val);
+}
+inline bool Sink::PutUInt32(Handlers::Selector sel, uint32_t val) {
+  return upb_sink_putuint32(this, sel, val);
+}
+inline bool Sink::PutUInt64(Handlers::Selector sel, uint64_t val) {
+  return upb_sink_putuint64(this, sel, val);
+}
+inline bool Sink::PutFloat(Handlers::Selector sel, float val) {
+  return upb_sink_putfloat(this, sel, val);
+}
+inline bool Sink::PutDouble(Handlers::Selector sel, double val) {
+  return upb_sink_putdouble(this, sel, val);
+}
+inline bool Sink::PutBool(Handlers::Selector sel, bool val) {
+  return upb_sink_putbool(this, sel, val);
+}
+inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint,
+                              Sink *sub) {
+  return upb_sink_startstr(this, sel, size_hint, sub);
+}
+inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf,
+                                    size_t len, const BufferHandle* handle) {
+  return upb_sink_putstring(this, sel, buf, len, handle);
+}
+inline bool Sink::EndString(Handlers::Selector sel) {
+  return upb_sink_endstr(this, sel);
+}
+inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) {
+  return upb_sink_startsubmsg(this, sel, sub);
+}
+inline bool Sink::EndSubMessage(Handlers::Selector sel) {
+  return upb_sink_endsubmsg(this, sel);
+}
+inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) {
+  return upb_sink_startseq(this, sel, sub);
+}
+inline bool Sink::EndSequence(Handlers::Selector sel) {
+  return upb_sink_endseq(this, sel);
+}
+
+template <class T>
+BytesSink::BytesSink(const BytesHandler* handler, T* closure) {
+  Reset(handler, closure);
+}
+
+template <class T>
+void BytesSink::Reset(const BytesHandler *handler, T *closure) {
+  upb_bytessink_reset(this, handler, closure);
+}
+inline bool BytesSink::Start(size_t size_hint, void **subc) {
+  return upb_bytessink_start(this, size_hint, subc);
+}
+inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len,
+                                   const BufferHandle *handle) {
+  return upb_bytessink_putbuf(this, subc, buf, len, handle);
+}
+inline bool BytesSink::End() {
+  return upb_bytessink_end(this);
+}
+
+inline bool BufferSource::PutBuffer(const char *buf, size_t len,
+                                    BytesSink *sink) {
+  return upb_bufsrc_putbuf(buf, len, sink);
+}
+
+}  /* namespace upb */
+#endif
+
+#endif
+/*
+** For handlers that do very tiny, very simple operations, the function call
+** overhead of calling a handler can be significant.  This file allows the
+** user to define handlers that do something very simple like store the value
+** to memory and/or set a hasbit.  JIT compilers can then special-case these
+** handlers and emit specialized code for them instead of actually calling the
+** handler.
+**
+** The functionality is very simple/limited right now but may expand to be able
+** to call another function.
+*/
+
+#ifndef UPB_SHIM_H
+#define UPB_SHIM_H
+
+
+typedef struct {
+  size_t offset;
+  int32_t hasbit;
+} upb_shim_data;
+
+#ifdef __cplusplus
+
+namespace upb {
+
+struct Shim {
+  typedef upb_shim_data Data;
+
+  /* Sets a handler for the given field that writes the value to the given
+   * offset and, if hasbit >= 0, sets a bit at the given bit offset.  Returns
+   * true if the handler was set successfully. */
+  static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit);
+
+  /* If this handler is a shim, returns the corresponding upb::Shim::Data and
+   * stores the type in "type".  Otherwise returns NULL. */
+  static const Data* GetData(const Handlers* h, Handlers::Selector s,
+                             FieldDef::Type* type);
+};
+
+}  /* namespace upb */
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+                  int32_t hasbit);
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
+                                      upb_fieldtype_t *type);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ Wrappers. */
+namespace upb {
+inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs,
+                      int32_t hasbit) {
+  return upb_shim_set(h, f, ofs, hasbit);
+}
+inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s,
+                                       FieldDef::Type* type) {
+  return upb_shim_getdata(h, s, type);
+}
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_SHIM_H */
+/*
+** upb::SymbolTable (upb_symtab)
+**
+** A symtab (symbol table) stores a name->def map of upb_defs.  Clients could
+** always create such tables themselves, but upb_symtab has logic for resolving
+** symbolic references, and in particular, for keeping a whole set of consistent
+** defs when replacing some subset of those defs.  This logic is nontrivial.
+**
+** This is a mixed C/C++ interface that offers a full API to both languages.
+** See the top-level README for more information.
+*/
+
+#ifndef UPB_SYMTAB_H_
+#define UPB_SYMTAB_H_
+
+
+#ifdef __cplusplus
+#include <vector>
+namespace upb { class SymbolTable; }
+#endif
+
+UPB_DECLARE_DERIVED_TYPE(upb::SymbolTable, upb::RefCounted,
+                         upb_symtab, upb_refcounted)
+
+typedef struct {
+ UPB_PRIVATE_FOR_CPP
+  upb_strtable_iter iter;
+  upb_deftype_t type;
+} upb_symtab_iter;
+
+#ifdef __cplusplus
+
+/* Non-const methods in upb::SymbolTable are NOT thread-safe. */
+class upb::SymbolTable {
+ public:
+  /* Returns a new symbol table with a single ref owned by "owner."
+   * Returns NULL if memory allocation failed. */
+  static reffed_ptr<SymbolTable> New();
+
+  /* Include RefCounted base methods. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* For all lookup functions, the returned pointer is not owned by the
+   * caller; it may be invalidated by any non-const call or unref of the
+   * SymbolTable!  To protect against this, take a ref if desired. */
+
+  /* Freezes the symbol table: prevents further modification of it.
+   * After the Freeze() operation is successful, the SymbolTable must only be
+   * accessed via a const pointer.
+   *
+   * Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not
+   * a necessary step in using a SymbolTable.  If you have no need for it to be
+   * immutable, there is no need to freeze it ever.  However sometimes it is
+   * useful, and SymbolTables that are statically compiled into the binary are
+   * always frozen by nature. */
+  void Freeze();
+
+  /* Resolves the given symbol using the rules described in descriptor.proto,
+   * namely:
+   *
+   *    If the name starts with a '.', it is fully-qualified.  Otherwise,
+   *    C++-like scoping rules are used to find the type (i.e. first the nested
+   *    types within this message are searched, then within the parent, on up
+   *    to the root namespace).
+   *
+   * If not found, returns NULL. */
+  const Def* Resolve(const char* base, const char* sym) const;
+
+  /* Finds an entry in the symbol table with this exact name.  If not found,
+   * returns NULL. */
+  const Def* Lookup(const char *sym) const;
+  const MessageDef* LookupMessage(const char *sym) const;
+  const EnumDef* LookupEnum(const char *sym) const;
+
+  /* TODO: introduce a C++ iterator, but make it nice and templated so that if
+   * you ask for an iterator of MessageDef the iterated elements are strongly
+   * typed as MessageDef*. */
+
+  /* Adds the given mutable defs to the symtab, resolving all symbols
+   * (including enum default values) and finalizing the defs.  Only one def per
+   * name may be in the list, but defs can replace existing defs in the symtab.
+   * All defs must have a name -- anonymous defs are not allowed.  Anonymous
+   * defs can still be frozen by calling upb_def_freeze() directly.
+   *
+   * Any existing defs that can reach defs that are being replaced will
+   * themselves be replaced also, so that the resulting set of defs is fully
+   * consistent.
+   *
+   * This logic implemented in this method is a convenience; ultimately it
+   * calls some combination of upb_fielddef_setsubdef(), upb_def_dup(), and
+   * upb_freeze(), any of which the client could call themself.  However, since
+   * the logic for doing so is nontrivial, we provide it here.
+   *
+   * The entire operation either succeeds or fails.  If the operation fails,
+   * the symtab is unchanged, false is returned, and status indicates the
+   * error.  The caller passes a ref on all defs to the symtab (even if the
+   * operation fails).
+   *
+   * TODO(haberman): currently failure will leave the symtab unchanged, but may
+   * leave the defs themselves partially resolved.  Does this matter?  If so we
+   * could do a prepass that ensures that all symbols are resolvable and bail
+   * if not, so we don't mutate anything until we know the operation will
+   * succeed.
+   *
+   * TODO(haberman): since the defs must be mutable, refining a frozen def
+   * requires making mutable copies of the entire tree.  This is wasteful if
+   * only a few messages are changing.  We may want to add a way of adding a
+   * tree of frozen defs to the symtab (perhaps an alternate constructor where
+   * you pass the root of the tree?) */
+  bool Add(Def*const* defs, size_t n, void* ref_donor, Status* status);
+
+  bool Add(const std::vector<Def*>& defs, void *owner, Status* status) {
+    return Add((Def*const*)&defs[0], defs.size(), owner, status);
+  }
+
+  /* Resolves all subdefs for messages in this file and attempts to freeze the
+   * file.  If this succeeds, adds all the symbols to this SymbolTable
+   * (replacing any existing ones with the same names). */
+  bool AddFile(FileDef* file, Status* s);
+
+ private:
+  UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable)
+};
+
+#endif  /* __cplusplus */
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+
+/* Include refcounted methods like upb_symtab_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_symtab, upb_symtab_upcast)
+
+upb_symtab *upb_symtab_new(const void *owner);
+void upb_symtab_freeze(upb_symtab *s);
+const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
+                                  const char *sym);
+const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+                    void *ref_donor, upb_status *status);
+bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status* status);
+
+/* upb_symtab_iter i;
+ * for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i);
+ *     upb_symtab_next(&i)) {
+ *   const upb_def *def = upb_symtab_iter_def(&i);
+ *    // ...
+ * }
+ *
+ * For C we don't have separate iterators for const and non-const.
+ * It is the caller's responsibility to cast the upb_fielddef* to
+ * const if the upb_msgdef* is const. */
+void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
+                      upb_deftype_t type);
+void upb_symtab_next(upb_symtab_iter *iter);
+bool upb_symtab_done(const upb_symtab_iter *iter);
+const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ inline wrappers. */
+namespace upb {
+inline reffed_ptr<SymbolTable> SymbolTable::New() {
+  upb_symtab *s = upb_symtab_new(&s);
+  return reffed_ptr<SymbolTable>(s, &s);
+}
+
+inline void SymbolTable::Freeze() {
+  return upb_symtab_freeze(this);
+}
+inline const Def *SymbolTable::Resolve(const char *base,
+                                       const char *sym) const {
+  return upb_symtab_resolve(this, base, sym);
+}
+inline const Def* SymbolTable::Lookup(const char *sym) const {
+  return upb_symtab_lookup(this, sym);
+}
+inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const {
+  return upb_symtab_lookupmsg(this, sym);
+}
+inline bool SymbolTable::Add(
+    Def*const* defs, size_t n, void* ref_donor, Status* status) {
+  return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status);
+}
+inline bool SymbolTable::AddFile(FileDef* file, Status* s) {
+  return upb_symtab_addfile(this, file, s);
+}
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_SYMTAB_H_ */
+/*
+** upb::descriptor::Reader (upb_descreader)
+**
+** Provides a way of building upb::Defs from data in descriptor.proto format.
+*/
+
+#ifndef UPB_DESCRIPTOR_H
+#define UPB_DESCRIPTOR_H
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace descriptor {
+class Reader;
+}  /* namespace descriptor */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader)
+
+#ifdef __cplusplus
+
+/* Class that receives descriptor data according to the descriptor.proto schema
+ * and use it to build upb::Defs corresponding to that schema. */
+class upb::descriptor::Reader {
+ public:
+  /* These handlers must have come from NewHandlers() and must outlive the
+   * Reader.
+   *
+   * TODO: generate the handlers statically (like we do with the
+   * descriptor.proto defs) so that there is no need to pass this parameter (or
+   * to build/memory-manage the handlers at runtime at all).  Unfortunately this
+   * is a bit tricky to implement for Handlers, but necessary to simplify this
+   * interface. */
+  static Reader* Create(Environment* env, const Handlers* handlers);
+
+  /* The reader's input; this is where descriptor.proto data should be sent. */
+  Sink* input();
+
+  /* Use to get the FileDefs that have been parsed. */
+  size_t file_count() const;
+  FileDef* file(size_t i) const;
+
+  /* Builds and returns handlers for the reader, owned by "owner." */
+  static Handlers* NewHandlers(const void* owner);
+
+ private:
+  UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h);
+upb_sink *upb_descreader_input(upb_descreader *r);
+size_t upb_descreader_filecount(const upb_descreader *r);
+upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i);
+const upb_handlers *upb_descreader_newhandlers(const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+/* C++ implementation details. ************************************************/
+namespace upb {
+namespace descriptor {
+inline Reader* Reader::Create(Environment* e, const Handlers *h) {
+  return upb_descreader_create(e, h);
+}
+inline Sink* Reader::input() { return upb_descreader_input(this); }
+inline size_t Reader::file_count() const {
+  return upb_descreader_filecount(this);
+}
+inline FileDef* Reader::file(size_t i) const {
+  return upb_descreader_file(this, i);
+}
+}  /* namespace descriptor */
+}  /* namespace upb */
+#endif
+
+#endif  /* UPB_DESCRIPTOR_H */
+/* This file contains accessors for a set of compiled-in defs.
+ * Note that unlike Google's protobuf, it does *not* define
+ * generated classes or any other kind of data structure for
+ * actually storing protobufs.  It only contains *defs* which
+ * let you reflect over a protobuf *schema*.
+ */
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     upb/descriptor/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_
+#define UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_
+
+
+UPB_BEGIN_EXTERN_C
+
+/* Enums */
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
+  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
+  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
+} google_protobuf_FieldDescriptorProto_Label;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
+  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
+  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
+  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
+  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
+  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
+  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
+  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
+  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
+  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
+} google_protobuf_FieldDescriptorProto_Type;
+
+typedef enum {
+  google_protobuf_FieldOptions_STRING = 0,
+  google_protobuf_FieldOptions_CORD = 1,
+  google_protobuf_FieldOptions_STRING_PIECE = 2
+} google_protobuf_FieldOptions_CType;
+
+typedef enum {
+  google_protobuf_FieldOptions_JS_NORMAL = 0,
+  google_protobuf_FieldOptions_JS_STRING = 1,
+  google_protobuf_FieldOptions_JS_NUMBER = 2
+} google_protobuf_FieldOptions_JSType;
+
+typedef enum {
+  google_protobuf_FileOptions_SPEED = 1,
+  google_protobuf_FileOptions_CODE_SIZE = 2,
+  google_protobuf_FileOptions_LITE_RUNTIME = 3
+} google_protobuf_FileOptions_OptimizeMode;
+
+/* MessageDefs: call these functions to get a ref to a msgdef. */
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner);
+
+/* EnumDefs: call these functions to get a ref to an enumdef. */
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner);
+
+/* Functions to test whether this message is of a certain type. */
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ExtensionRange") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ReservedRange") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumValueDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumValueOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorSet_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorSet") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MessageOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.MessageOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MethodDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MethodOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_OneofDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.OneofDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_ServiceDescriptorProto_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_ServiceOptions_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_Location_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo.Location") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_NamePart_is(const upb_msgdef *m) {
+  return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption.NamePart") == 0;
+}
+
+/* Functions to test whether this enum is of a certain type. */
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Label_is(const upb_enumdef *e) {
+  return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Label") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Type_is(const upb_enumdef *e) {
+  return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Type") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_CType_is(const upb_enumdef *e) {
+  return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.CType") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_JSType_is(const upb_enumdef *e) {
+  return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.JSType") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileOptions_OptimizeMode_is(const upb_enumdef *e) {
+  return strcmp(upb_enumdef_fullname(e), "google.protobuf.FileOptions.OptimizeMode") == 0;
+}
+
+
+/* Functions to get a fielddef from a msgdef reference. */
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_end(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_start(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_end(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_start(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_enum_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension_range(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_field(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_nested_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_oneof_decl(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_range(const upb_msgdef *m) { assert(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_allow_alias(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_number(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_default_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_extendee(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_json_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_label(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_number(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_oneof_index(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_ctype(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_jstype(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_lazy(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_packed(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_weak(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_dependency(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_enum_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_extension(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_message_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_package(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_public_dependency(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_service(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_source_code_info(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_syntax(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 12); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_weak_dependency(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_f_file(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileDescriptorSet_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_enable_arenas(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 31); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_generic_services(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 16); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_csharp_namespace(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 37); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 23); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_go_package(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generate_equals_and_hash(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 20); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generic_services(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 17); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_multiple_files(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_outer_classname(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_package(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_string_check_utf8(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 27); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_javanano_use_deprecated_package(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 38); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_map_entry(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_message_set_wire_format(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_no_standard_descriptor_accessor(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_client_streaming(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_input_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_output_type(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_server_streaming(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 33); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_OneofDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_method(const upb_msgdef *m) { assert(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_options(const upb_msgdef *m) { assert(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_deprecated(const upb_msgdef *m) { assert(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 33); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_uninterpreted_option(const upb_msgdef *m) { assert(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_comments(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_detached_comments(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_path(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_span(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_trailing_comments(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_f_location(const upb_msgdef *m) { assert(upbdefs_google_protobuf_SourceCodeInfo_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_is_extension(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_name_part(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_aggregate_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_double_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_identifier_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_name(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_negative_int_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_positive_int_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_string_value(const upb_msgdef *m) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 7); }
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upbdefs {
+namespace google {
+namespace protobuf {
+
+class DescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  DescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_DescriptorProto_is(m));
+  }
+
+  static DescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_get(&m);
+    return DescriptorProto(m, &m);
+  }
+
+  class ExtensionRange : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+   public:
+    ExtensionRange(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+        : reffed_ptr(m, ref_donor) {
+      assert(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m));
+    }
+
+    static ExtensionRange get() {
+      const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(&m);
+      return ExtensionRange(m, &m);
+    }
+  };
+
+  class ReservedRange : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+   public:
+    ReservedRange(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+        : reffed_ptr(m, ref_donor) {
+      assert(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m));
+    }
+
+    static ReservedRange get() {
+      const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(&m);
+      return ReservedRange(m, &m);
+    }
+  };
+};
+
+class EnumDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  EnumDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_EnumDescriptorProto_is(m));
+  }
+
+  static EnumDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumDescriptorProto_get(&m);
+    return EnumDescriptorProto(m, &m);
+  }
+};
+
+class EnumOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  EnumOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_EnumOptions_is(m));
+  }
+
+  static EnumOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumOptions_get(&m);
+    return EnumOptions(m, &m);
+  }
+};
+
+class EnumValueDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  EnumValueDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m));
+  }
+
+  static EnumValueDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueDescriptorProto_get(&m);
+    return EnumValueDescriptorProto(m, &m);
+  }
+};
+
+class EnumValueOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  EnumValueOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_EnumValueOptions_is(m));
+  }
+
+  static EnumValueOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueOptions_get(&m);
+    return EnumValueOptions(m, &m);
+  }
+};
+
+class FieldDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  FieldDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m));
+  }
+
+  static FieldDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldDescriptorProto_get(&m);
+    return FieldDescriptorProto(m, &m);
+  }
+
+  class Label : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+   public:
+    Label(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+        : reffed_ptr(e, ref_donor) {
+      assert(upbdefs_google_protobuf_FieldDescriptorProto_Label_is(e));
+    }
+    static Label get() {
+      const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Label_get(&e);
+      return Label(e, &e);
+    }
+  };
+
+  class Type : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+   public:
+    Type(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+        : reffed_ptr(e, ref_donor) {
+      assert(upbdefs_google_protobuf_FieldDescriptorProto_Type_is(e));
+    }
+    static Type get() {
+      const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Type_get(&e);
+      return Type(e, &e);
+    }
+  };
+};
+
+class FieldOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  FieldOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_FieldOptions_is(m));
+  }
+
+  static FieldOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldOptions_get(&m);
+    return FieldOptions(m, &m);
+  }
+
+  class CType : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+   public:
+    CType(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+        : reffed_ptr(e, ref_donor) {
+      assert(upbdefs_google_protobuf_FieldOptions_CType_is(e));
+    }
+    static CType get() {
+      const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_CType_get(&e);
+      return CType(e, &e);
+    }
+  };
+
+  class JSType : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+   public:
+    JSType(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+        : reffed_ptr(e, ref_donor) {
+      assert(upbdefs_google_protobuf_FieldOptions_JSType_is(e));
+    }
+    static JSType get() {
+      const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_JSType_get(&e);
+      return JSType(e, &e);
+    }
+  };
+};
+
+class FileDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  FileDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_FileDescriptorProto_is(m));
+  }
+
+  static FileDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorProto_get(&m);
+    return FileDescriptorProto(m, &m);
+  }
+};
+
+class FileDescriptorSet : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  FileDescriptorSet(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_FileDescriptorSet_is(m));
+  }
+
+  static FileDescriptorSet get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
+    return FileDescriptorSet(m, &m);
+  }
+};
+
+class FileOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  FileOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_FileOptions_is(m));
+  }
+
+  static FileOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_FileOptions_get(&m);
+    return FileOptions(m, &m);
+  }
+
+  class OptimizeMode : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+   public:
+    OptimizeMode(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+        : reffed_ptr(e, ref_donor) {
+      assert(upbdefs_google_protobuf_FileOptions_OptimizeMode_is(e));
+    }
+    static OptimizeMode get() {
+      const ::upb::EnumDef* e = upbdefs_google_protobuf_FileOptions_OptimizeMode_get(&e);
+      return OptimizeMode(e, &e);
+    }
+  };
+};
+
+class MessageOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  MessageOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_MessageOptions_is(m));
+  }
+
+  static MessageOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_MessageOptions_get(&m);
+    return MessageOptions(m, &m);
+  }
+};
+
+class MethodDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  MethodDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_MethodDescriptorProto_is(m));
+  }
+
+  static MethodDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodDescriptorProto_get(&m);
+    return MethodDescriptorProto(m, &m);
+  }
+};
+
+class MethodOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  MethodOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_MethodOptions_is(m));
+  }
+
+  static MethodOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodOptions_get(&m);
+    return MethodOptions(m, &m);
+  }
+};
+
+class OneofDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  OneofDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_OneofDescriptorProto_is(m));
+  }
+
+  static OneofDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_OneofDescriptorProto_get(&m);
+    return OneofDescriptorProto(m, &m);
+  }
+};
+
+class ServiceDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  ServiceDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_ServiceDescriptorProto_is(m));
+  }
+
+  static ServiceDescriptorProto get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceDescriptorProto_get(&m);
+    return ServiceDescriptorProto(m, &m);
+  }
+};
+
+class ServiceOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  ServiceOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_ServiceOptions_is(m));
+  }
+
+  static ServiceOptions get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceOptions_get(&m);
+    return ServiceOptions(m, &m);
+  }
+};
+
+class SourceCodeInfo : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  SourceCodeInfo(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_SourceCodeInfo_is(m));
+  }
+
+  static SourceCodeInfo get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_get(&m);
+    return SourceCodeInfo(m, &m);
+  }
+
+  class Location : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+   public:
+    Location(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+        : reffed_ptr(m, ref_donor) {
+      assert(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m));
+    }
+
+    static Location get() {
+      const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_Location_get(&m);
+      return Location(m, &m);
+    }
+  };
+};
+
+class UninterpretedOption : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+  UninterpretedOption(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+      : reffed_ptr(m, ref_donor) {
+    assert(upbdefs_google_protobuf_UninterpretedOption_is(m));
+  }
+
+  static UninterpretedOption get() {
+    const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_get(&m);
+    return UninterpretedOption(m, &m);
+  }
+
+  class NamePart : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+   public:
+    NamePart(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+        : reffed_ptr(m, ref_donor) {
+      assert(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m));
+    }
+
+    static NamePart get() {
+      const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_NamePart_get(&m);
+      return NamePart(m, &m);
+    }
+  };
+};
+
+}  /* namespace protobuf */
+}  /* namespace google */
+}  /* namespace upbdefs */
+
+#endif  /* __cplusplus */
+
+#endif  /* UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ */
+/*
+** Internal-only definitions for the decoder.
+*/
+
+#ifndef UPB_DECODER_INT_H_
+#define UPB_DECODER_INT_H_
+
+/*
+** upb::pb::Decoder
+**
+** A high performance, streaming, resumable decoder for the binary protobuf
+** format.
+**
+** This interface works the same regardless of what decoder backend is being
+** used.  A client of this class does not need to know whether decoding is using
+** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder.  By default,
+** it will always use the fastest available decoder.  However, you can call
+** set_allow_jit(false) to disable any JIT decoder that might be available.
+** This is primarily useful for testing purposes.
+*/
+
+#ifndef UPB_DECODER_H_
+#define UPB_DECODER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class CodeCache;
+class Decoder;
+class DecoderMethod;
+class DecoderMethodOptions;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache)
+UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder)
+UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts)
+
+UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted,
+                         upb_pbdecodermethod, upb_refcounted)
+
+/* The maximum number of bytes we are required to buffer internally between
+ * calls to the decoder.  The value is 14: a 5 byte unknown tag plus ten-byte
+ * varint, less one because we are buffering an incomplete value.
+ *
+ * Should only be used by unit tests. */
+#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
+
+#ifdef __cplusplus
+
+/* The parameters one uses to construct a DecoderMethod.
+ * TODO(haberman): move allowjit here?  Seems more convenient for users.
+ * TODO(haberman): move this to be heap allocated for ABI stability. */
+class upb::pb::DecoderMethodOptions {
+ public:
+  /* Parameter represents the destination handlers that this method will push
+   * to. */
+  explicit DecoderMethodOptions(const Handlers* dest_handlers);
+
+  /* Should the decoder push submessages to lazy handlers for fields that have
+   * them?  The caller should set this iff the lazy handlers expect data that is
+   * in protobuf binary format and the caller wishes to lazy parse it. */
+  void set_lazy(bool lazy);
+#else
+struct upb_pbdecodermethodopts {
+#endif
+  const upb_handlers *handlers;
+  bool lazy;
+};
+
+#ifdef __cplusplus
+
+/* Represents the code to parse a protobuf according to a destination
+ * Handlers. */
+class upb::pb::DecoderMethod {
+ public:
+  /* Include base methods from upb::ReferenceCounted. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* The destination handlers that are statically bound to this method.
+   * This method is only capable of outputting to a sink that uses these
+   * handlers. */
+  const Handlers* dest_handlers() const;
+
+  /* The input handlers for this decoder method. */
+  const BytesHandler* input_handler() const;
+
+  /* Whether this method is native. */
+  bool is_native() const;
+
+  /* Convenience method for generating a DecoderMethod without explicitly
+   * creating a CodeCache. */
+  static reffed_ptr<const DecoderMethod> New(const DecoderMethodOptions& opts);
+
+ private:
+  UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod)
+};
+
+#endif
+
+/* Preallocation hint: decoder won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the decoder library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_PB_DECODER_SIZE 4416
+
+#ifdef __cplusplus
+
+/* A Decoder receives binary protobuf data on its input sink and pushes the
+ * decoded data to its output sink. */
+class upb::pb::Decoder {
+ public:
+  /* Constructs a decoder instance for the given method, which must outlive this
+   * decoder.  Any errors during parsing will be set on the given status, which
+   * must also outlive this decoder.
+   *
+   * The sink must match the given method. */
+  static Decoder* Create(Environment* env, const DecoderMethod* method,
+                         Sink* output);
+
+  /* Returns the DecoderMethod this decoder is parsing from. */
+  const DecoderMethod* method() const;
+
+  /* The sink on which this decoder receives input. */
+  BytesSink* input();
+
+  /* Returns number of bytes successfully parsed.
+   *
+   * This can be useful for determining the stream position where an error
+   * occurred.
+   *
+   * This value may not be up-to-date when called from inside a parsing
+   * callback. */
+  uint64_t BytesParsed() const;
+
+  /* Gets/sets the parsing nexting limit.  If the total number of nested
+   * submessages and repeated fields hits this limit, parsing will fail.  This
+   * is a resource limit that controls the amount of memory used by the parsing
+   * stack.
+   *
+   * Setting the limit will fail if the parser is currently suspended at a depth
+   * greater than this, or if memory allocation of the stack fails. */
+  size_t max_nesting() const;
+  bool set_max_nesting(size_t max);
+
+  void Reset();
+
+  static const size_t kSize = UPB_PB_DECODER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder)
+};
+
+#endif  /* __cplusplus */
+
+#ifdef __cplusplus
+
+/* A class for caching protobuf processing code, whether bytecode for the
+ * interpreted decoder or machine code for the JIT.
+ *
+ * This class is not thread-safe.
+ *
+ * TODO(haberman): move this to be heap allocated for ABI stability. */
+class upb::pb::CodeCache {
+ public:
+  CodeCache();
+  ~CodeCache();
+
+  /* Whether the cache is allowed to generate machine code.  Defaults to true.
+   * There is no real reason to turn it off except for testing or if you are
+   * having a specific problem with the JIT.
+   *
+   * Note that allow_jit = true does not *guarantee* that the code will be JIT
+   * compiled.  If this platform is not supported or the JIT was not compiled
+   * in, the code may still be interpreted. */
+  bool allow_jit() const;
+
+  /* This may only be called when the object is first constructed, and prior to
+   * any code generation, otherwise returns false and does nothing. */
+  bool set_allow_jit(bool allow);
+
+  /* Returns a DecoderMethod that can push data to the given handlers.
+   * If a suitable method already exists, it will be returned from the cache.
+   *
+   * Specifying the destination handlers here allows the DecoderMethod to be
+   * statically bound to the destination handlers if possible, which can allow
+   * more efficient decoding.  However the returned method may or may not
+   * actually be statically bound.  But in all cases, the returned method can
+   * push data to the given handlers. */
+  const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts);
+
+  /* If/when someone needs to explicitly create a dynamically-bound
+   * DecoderMethod*, we can add a method to get it here. */
+
+ private:
+  UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache)
+#else
+struct upb_pbcodecache {
+#endif
+  bool allow_jit_;
+
+  /* Array of mgroups. */
+  upb_inttable groups;
+};
+
+UPB_BEGIN_EXTERN_C
+
+upb_pbdecoder *upb_pbdecoder_create(upb_env *e,
+                                    const upb_pbdecodermethod *method,
+                                    upb_sink *output);
+const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
+upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d);
+uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
+size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
+bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
+void upb_pbdecoder_reset(upb_pbdecoder *d);
+
+void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
+                                  const upb_handlers *h);
+void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy);
+
+
+/* Include refcounted methods like upb_pbdecodermethod_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast)
+
+const upb_handlers *upb_pbdecodermethod_desthandlers(
+    const upb_pbdecodermethod *m);
+const upb_byteshandler *upb_pbdecodermethod_inputhandler(
+    const upb_pbdecodermethod *m);
+bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
+const upb_pbdecodermethod *upb_pbdecodermethod_new(
+    const upb_pbdecodermethodopts *opts, const void *owner);
+
+void upb_pbcodecache_init(upb_pbcodecache *c);
+void upb_pbcodecache_uninit(upb_pbcodecache *c);
+bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
+bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
+const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
+    upb_pbcodecache *c, const upb_pbdecodermethodopts *opts);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+
+namespace pb {
+
+/* static */
+inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m,
+                                Sink* sink) {
+  return upb_pbdecoder_create(env, m, sink);
+}
+inline const DecoderMethod* Decoder::method() const {
+  return upb_pbdecoder_method(this);
+}
+inline BytesSink* Decoder::input() {
+  return upb_pbdecoder_input(this);
+}
+inline uint64_t Decoder::BytesParsed() const {
+  return upb_pbdecoder_bytesparsed(this);
+}
+inline size_t Decoder::max_nesting() const {
+  return upb_pbdecoder_maxnesting(this);
+}
+inline bool Decoder::set_max_nesting(size_t max) {
+  return upb_pbdecoder_setmaxnesting(this, max);
+}
+inline void Decoder::Reset() { upb_pbdecoder_reset(this); }
+
+inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) {
+  upb_pbdecodermethodopts_init(this, h);
+}
+inline void DecoderMethodOptions::set_lazy(bool lazy) {
+  upb_pbdecodermethodopts_setlazy(this, lazy);
+}
+
+inline const Handlers* DecoderMethod::dest_handlers() const {
+  return upb_pbdecodermethod_desthandlers(this);
+}
+inline const BytesHandler* DecoderMethod::input_handler() const {
+  return upb_pbdecodermethod_inputhandler(this);
+}
+inline bool DecoderMethod::is_native() const {
+  return upb_pbdecodermethod_isnative(this);
+}
+/* static */
+inline reffed_ptr<const DecoderMethod> DecoderMethod::New(
+    const DecoderMethodOptions &opts) {
+  const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m);
+  return reffed_ptr<const DecoderMethod>(m, &m);
+}
+
+inline CodeCache::CodeCache() {
+  upb_pbcodecache_init(this);
+}
+inline CodeCache::~CodeCache() {
+  upb_pbcodecache_uninit(this);
+}
+inline bool CodeCache::allow_jit() const {
+  return upb_pbcodecache_allowjit(this);
+}
+inline bool CodeCache::set_allow_jit(bool allow) {
+  return upb_pbcodecache_setallowjit(this, allow);
+}
+inline const DecoderMethod *CodeCache::GetDecoderMethod(
+    const DecoderMethodOptions& opts) {
+  return upb_pbcodecache_getdecodermethod(this, &opts);
+}
+
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif  /* __cplusplus */
+
+#endif  /* UPB_DECODER_H_ */
+
+/* C++ names are not actually used since this type isn't exposed to users. */
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class MessageGroup;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted,
+                         mgroup, upb_refcounted)
+
+/* Opcode definitions.  The canonical meaning of each opcode is its
+ * implementation in the interpreter (the JIT is written to match this).
+ *
+ * All instructions have the opcode in the low byte.
+ * Instruction format for most instructions is:
+ *
+ * +-------------------+--------+
+ * |     arg (24)      | op (8) |
+ * +-------------------+--------+
+ *
+ * Exceptions are indicated below.  A few opcodes are multi-word. */
+typedef enum {
+  /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
+   * Arg for all of these is the upb selector for this field. */
+#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
+  T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
+  T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
+#undef T
+  OP_STARTMSG       = 9,   /* No arg. */
+  OP_ENDMSG         = 10,  /* No arg. */
+  OP_STARTSEQ       = 11,
+  OP_ENDSEQ         = 12,
+  OP_STARTSUBMSG    = 14,
+  OP_ENDSUBMSG      = 19,
+  OP_STARTSTR       = 20,
+  OP_STRING         = 21,
+  OP_ENDSTR         = 22,
+
+  OP_PUSHTAGDELIM   = 23,  /* No arg. */
+  OP_PUSHLENDELIM   = 24,  /* No arg. */
+  OP_POP            = 25,  /* No arg. */
+  OP_SETDELIM       = 26,  /* No arg. */
+  OP_SETBIGGROUPNUM = 27,  /* two words:
+                            *   | unused (24)     | opc (8) |
+                            *   |        groupnum (32)      | */
+  OP_CHECKDELIM     = 28,
+  OP_CALL           = 29,
+  OP_RET            = 30,
+  OP_BRANCH         = 31,
+
+  /* Different opcodes depending on how many bytes expected. */
+  OP_TAG1           = 32,  /* | match tag (16) | jump target (8) | opc (8) | */
+  OP_TAG2           = 33,  /* | match tag (16) | jump target (8) | opc (8) | */
+  OP_TAGN           = 34,  /* three words: */
+                           /*   | unused (16) | jump target(8) | opc (8) | */
+                           /*   |           match tag 1 (32)             | */
+                           /*   |           match tag 2 (32)             | */
+
+  OP_SETDISPATCH    = 35,  /* N words: */
+                           /*   | unused (24)         | opc | */
+                           /*   | upb_inttable* (32 or 64)  | */
+
+  OP_DISPATCH       = 36,  /* No arg. */
+
+  OP_HALT           = 37   /* No arg. */
+} opcode;
+
+#define OP_MAX OP_HALT
+
+UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; }
+
+/* Method group; represents a set of decoder methods that had their code
+ * emitted together, and must therefore be freed together.  Immutable once
+ * created.  It is possible we may want to expose this to users at some point.
+ *
+ * Overall ownership of Decoder objects looks like this:
+ *
+ *                +----------+
+ *                |          | <---> DecoderMethod
+ *                | method   |
+ * CodeCache ---> |  group   | <---> DecoderMethod
+ *                |          |
+ *                | (mgroup) | <---> DecoderMethod
+ *                +----------+
+ */
+struct mgroup {
+  upb_refcounted base;
+
+  /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod.  We own refs on the
+   * methods. */
+  upb_inttable methods;
+
+  /* When we add the ability to link to previously existing mgroups, we'll
+   * need an array of mgroups we reference here, and own refs on them. */
+
+  /* The bytecode for our methods, if any exists.  Owned by us. */
+  uint32_t *bytecode;
+  uint32_t *bytecode_end;
+
+#ifdef UPB_USE_JIT_X64
+  /* JIT-generated machine code, if any. */
+  upb_string_handlerfunc *jit_code;
+  /* The size of the jit_code (required to munmap()). */
+  size_t jit_size;
+  char *debug_info;
+  void *dl;
+#endif
+};
+
+/* The maximum that any submessages can be nested.  Matches proto2's limit.
+ * This specifies the size of the decoder's statically-sized array and therefore
+ * setting it high will cause the upb::pb::Decoder object to be larger.
+ *
+ * If necessary we can add a runtime-settable property to Decoder that allow
+ * this to be larger than the compile-time setting, but this would add
+ * complexity, particularly since we would have to decide how/if to give users
+ * the ability to set a custom memory allocation function. */
+#define UPB_DECODER_MAX_NESTING 64
+
+/* Internal-only struct used by the decoder. */
+typedef struct {
+  /* Space optimization note: we store two pointers here that the JIT
+   * doesn't need at all; the upb_handlers* inside the sink and
+   * the dispatch table pointer.  We can optimze so that the JIT uses
+   * smaller stack frames than the interpreter.  The only thing we need
+   * to guarantee is that the fallback routines can find end_ofs. */
+  upb_sink sink;
+
+  /* The absolute stream offset of the end-of-frame delimiter.
+   * Non-delimited frames (groups and non-packed repeated fields) reuse the
+   * delimiter of their parent, even though the frame may not end there.
+   *
+   * NOTE: the JIT stores a slightly different value here for non-top frames.
+   * It stores the value relative to the end of the enclosed message.  But the
+   * top frame is still stored the same way, which is important for ensuring
+   * that calls from the JIT into C work correctly. */
+  uint64_t end_ofs;
+  const uint32_t *base;
+
+  /* 0 indicates a length-delimited field.
+   * A positive number indicates a known group.
+   * A negative number indicates an unknown group. */
+  int32_t groupnum;
+  upb_inttable *dispatch;  /* Not used by the JIT. */
+} upb_pbdecoder_frame;
+
+struct upb_pbdecodermethod {
+  upb_refcounted base;
+
+  /* While compiling, the base is relative in "ofs", after compiling it is
+   * absolute in "ptr". */
+  union {
+    uint32_t ofs;     /* PC offset of method. */
+    void *ptr;        /* Pointer to bytecode or machine code for this method. */
+  } code_base;
+
+  /* The decoder method group to which this method belongs.  We own a ref.
+   * Owning a ref on the entire group is more coarse-grained than is strictly
+   * necessary; all we truly require is that methods we directly reference
+   * outlive us, while the group could contain many other messages we don't
+   * require.  But the group represents the messages that were
+   * allocated+compiled together, so it makes the most sense to free them
+   * together also. */
+  const upb_refcounted *group;
+
+  /* Whether this method is native code or bytecode. */
+  bool is_native_;
+
+  /* The handler one calls to invoke this method. */
+  upb_byteshandler input_handler_;
+
+  /* The destination handlers this method is bound to.  We own a ref. */
+  const upb_handlers *dest_handlers_;
+
+  /* Dispatch table -- used by both bytecode decoder and JIT when encountering a
+   * field number that wasn't the one we were expecting to see.  See
+   * decoder.int.h for the layout of this table. */
+  upb_inttable dispatch;
+};
+
+struct upb_pbdecoder {
+  upb_env *env;
+
+  /* Our input sink. */
+  upb_bytessink input_;
+
+  /* The decoder method we are parsing with (owned). */
+  const upb_pbdecodermethod *method_;
+
+  size_t call_len;
+  const uint32_t *pc, *last;
+
+  /* Current input buffer and its stream offset. */
+  const char *buf, *ptr, *end, *checkpoint;
+
+  /* End of the delimited region, relative to ptr, NULL if not in this buf. */
+  const char *delim_end;
+
+  /* End of the delimited region, relative to ptr, end if not in this buf. */
+  const char *data_end;
+
+  /* Overall stream offset of "buf." */
+  uint64_t bufstart_ofs;
+
+  /* Buffer for residual bytes not parsed from the previous buffer. */
+  char residual[UPB_DECODER_MAX_RESIDUAL_BYTES];
+  char *residual_end;
+
+  /* Bytes of data that should be discarded from the input beore we start
+   * parsing again.  We set this when we internally determine that we can
+   * safely skip the next N bytes, but this region extends past the current
+   * user buffer. */
+  size_t skip;
+
+  /* Stores the user buffer passed to our decode function. */
+  const char *buf_param;
+  size_t size_param;
+  const upb_bufhandle *handle;
+
+  /* Our internal stack. */
+  upb_pbdecoder_frame *stack, *top, *limit;
+  const uint32_t **callstack;
+  size_t stack_size;
+
+  upb_status *status;
+
+#ifdef UPB_USE_JIT_X64
+  /* Used momentarily by the generated code to store a value while a user
+   * function is called. */
+  uint32_t tmp_len;
+
+  const void *saved_rsp;
+#endif
+};
+
+/* Decoder entry points; used as handlers. */
+void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
+void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint);
+size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
+                            size_t size, const upb_bufhandle *handle);
+bool upb_pbdecoder_end(void *closure, const void *handler_data);
+
+/* Decoder-internal functions that the JIT calls to handle fallback paths. */
+int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
+                             size_t size, const upb_bufhandle *handle);
+size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
+int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
+                                  uint8_t wire_type);
+int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
+int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
+int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
+int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
+void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
+
+/* Error messages that are shared between the bytecode and JIT decoders. */
+extern const char *kPbDecoderStackOverflow;
+extern const char *kPbDecoderSubmessageTooLong;
+
+/* Access to decoderplan members needed by the decoder. */
+const char *upb_pbdecoder_getopname(unsigned int op);
+
+/* JIT codegen entry point. */
+void upb_pbdecoder_jit(mgroup *group);
+void upb_pbdecoder_freejit(mgroup *group);
+UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast)
+
+/* A special label that means "do field dispatch for this message and branch to
+ * wherever that takes you." */
+#define LABEL_DISPATCH 0
+
+/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or
+ * RET) for branching to when we find an appropriate ENDGROUP tag. */
+#define DISPATCH_ENDMSG 0
+
+/* It's important to use this invalid wire type instead of 0 (which is a valid
+ * wire type). */
+#define NO_WIRE_TYPE 0xff
+
+/* The dispatch table layout is:
+ *   [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
+ *
+ * If wt1 matches, jump to the 48-bit offset.  If wt2 matches, lookup
+ * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
+ *
+ * We need two wire types because of packed/non-packed compatibility.  A
+ * primitive repeated field can use either wire type and be valid.  While we
+ * could key the table on fieldnum+wiretype, the table would be 8x sparser.
+ *
+ * Storing two wire types in the primary value allows us to quickly rule out
+ * the second wire type without needing to do a separate lookup (this case is
+ * less common than an unknown field). */
+UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1,
+                                               uint8_t wt2) {
+  return (ofs << 16) | (wt2 << 8) | wt1;
+}
+
+UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
+                                             uint8_t *wt1, uint8_t *wt2) {
+  *wt1 = (uint8_t)dispatch;
+  *wt2 = (uint8_t)(dispatch >> 8);
+  *ofs = dispatch >> 16;
+}
+
+/* All of the functions in decoder.c that return int32_t return values according
+ * to the following scheme:
+ *   1. negative values indicate a return code from the following list.
+ *   2. positive values indicate that error or end of buffer was hit, and
+ *      that the decode function should immediately return the given value
+ *      (the decoder state has already been suspended and is ready to be
+ *      resumed). */
+#define DECODE_OK -1
+#define DECODE_MISMATCH -2  /* Used only from checktag_slow(). */
+#define DECODE_ENDGROUP -3  /* Used only from checkunknown(). */
+
+#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; }
+
+#endif  /* UPB_DECODER_INT_H_ */
+/*
+** A number of routines for varint manipulation (we keep them all around to
+** have multiple approaches available for benchmarking).
+*/
+
+#ifndef UPB_VARINT_DECODER_H_
+#define UPB_VARINT_DECODER_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A list of types as they are encoded on-the-wire. */
+typedef enum {
+  UPB_WIRE_TYPE_VARINT      = 0,
+  UPB_WIRE_TYPE_64BIT       = 1,
+  UPB_WIRE_TYPE_DELIMITED   = 2,
+  UPB_WIRE_TYPE_START_GROUP = 3,
+  UPB_WIRE_TYPE_END_GROUP   = 4,
+  UPB_WIRE_TYPE_32BIT       = 5
+} upb_wiretype_t;
+
+#define UPB_MAX_WIRE_TYPE 5
+
+/* The maximum number of bytes that it takes to encode a 64-bit varint.
+ * Note that with a better encoding this could be 9 (TODO: write up a
+ * wiki document about this). */
+#define UPB_PB_VARINT_MAX_LEN 10
+
+/* Array of the "native" (ie. non-packed-repeated) wire type for the given a
+ * descriptor type (upb_descriptortype_t). */
+extern const uint8_t upb_pb_native_wire_types[];
+
+/* Zig-zag encoding/decoding **************************************************/
+
+UPB_INLINE int32_t upb_zzdec_32(uint32_t n) {
+  return (n >> 1) ^ -(int32_t)(n & 1);
+}
+UPB_INLINE int64_t upb_zzdec_64(uint64_t n) {
+  return (n >> 1) ^ -(int64_t)(n & 1);
+}
+UPB_INLINE uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); }
+UPB_INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); }
+
+/* Decoding *******************************************************************/
+
+/* All decoding functions return this struct by value. */
+typedef struct {
+  const char *p;  /* NULL if the varint was unterminated. */
+  uint64_t val;
+} upb_decoderet;
+
+UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) {
+  upb_decoderet ret;
+  ret.p = p;
+  ret.val = val;
+  return ret;
+}
+
+/* Four functions for decoding a varint of at most eight bytes.  They are all
+ * functionally identical, but are implemented in different ways and likely have
+ * different performance profiles.  We keep them around for performance testing.
+ *
+ * Note that these functions may not read byte-by-byte, so they must not be used
+ * unless there are at least eight bytes left in the buffer! */
+upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_wright(upb_decoderet r);
+upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r);
+
+/* Template for a function that checks the first two bytes with branching
+ * and dispatches 2-10 bytes with a separate function.  Note that this may read
+ * up to 10 bytes, so it must not be used unless there are at least ten bytes
+ * left in the buffer! */
+#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function)                  \
+UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) {         \
+  uint8_t *p = (uint8_t*)_p;                                                   \
+  upb_decoderet r;                                                             \
+  if ((*p & 0x80) == 0) {                                                      \
+  /* Common case: one-byte varint. */                                          \
+    return upb_decoderet_make(_p + 1, *p & 0x7fU);                             \
+  }                                                                            \
+  r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7));    \
+  if ((*(p + 1) & 0x80) == 0) {                                                \
+    /* Two-byte varint. */                                                     \
+    return r;                                                                  \
+  }                                                                            \
+  /* Longer varint, fallback to out-of-line function. */                       \
+  return decode_max8_function(r);                                              \
+}
+
+UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
+UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
+UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright)
+UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino)
+#undef UPB_VARINT_DECODER_CHECK2
+
+/* Our canonical functions for decoding varints, based on the currently
+ * favored best-performing implementations. */
+UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
+  if (sizeof(long) == 8)
+    return upb_vdecode_check2_branch64(p);
+  else
+    return upb_vdecode_check2_branch32(p);
+}
+
+UPB_INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) {
+  return upb_vdecode_max8_massimino(r);
+}
+
+
+/* Encoding *******************************************************************/
+
+UPB_INLINE int upb_value_size(uint64_t val) {
+#ifdef __GNUC__
+  int high_bit = 63 - __builtin_clzll(val);  /* 0-based, undef if val == 0. */
+#else
+  int high_bit = 0;
+  uint64_t tmp = val;
+  while(tmp >>= 1) high_bit++;
+#endif
+  return val == 0 ? 1 : high_bit / 8 + 1;
+}
+
+/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN
+ * bytes long), returning how many bytes were used.
+ *
+ * TODO: benchmark and optimize if necessary. */
+UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) {
+  size_t i;
+  if (val == 0) { buf[0] = 0; return 1; }
+  i = 0;
+  while (val) {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  }
+  return i;
+}
+
+UPB_INLINE size_t upb_varint_size(uint64_t val) {
+  char buf[UPB_PB_VARINT_MAX_LEN];
+  return upb_vencode64(val, buf);
+}
+
+/* Encodes a 32-bit varint, *not* sign-extended. */
+UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
+  char buf[UPB_PB_VARINT_MAX_LEN];
+  size_t bytes = upb_vencode64(val, buf);
+  uint64_t ret = 0;
+  assert(bytes <= 5);
+  memcpy(&ret, buf, bytes);
+  assert(ret <= 0xffffffffffU);
+  return ret;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_VARINT_DECODER_H_ */
+/*
+** upb::pb::Encoder (upb_pb_encoder)
+**
+** Implements a set of upb_handlers that write protobuf data to the binary wire
+** format.
+**
+** This encoder implementation does not have any access to any out-of-band or
+** precomputed lengths for submessages, so it must buffer submessages internally
+** before it can emit the first byte.
+*/
+
+#ifndef UPB_ENCODER_H_
+#define UPB_ENCODER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class Encoder;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder)
+
+#define UPB_PBENCODER_MAX_NESTING 100
+
+/* upb::pb::Encoder ***********************************************************/
+
+/* Preallocation hint: decoder won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the decoder library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_PB_ENCODER_SIZE 768
+
+#ifdef __cplusplus
+
+class upb::pb::Encoder {
+ public:
+  /* Creates a new encoder in the given environment.  The Handlers must have
+   * come from NewHandlers() below. */
+  static Encoder* Create(Environment* env, const Handlers* handlers,
+                         BytesSink* output);
+
+  /* The input to the encoder. */
+  Sink* input();
+
+  /* Creates a new set of handlers for this MessageDef. */
+  static reffed_ptr<const Handlers> NewHandlers(const MessageDef* msg);
+
+  static const size_t kSize = UPB_PB_ENCODER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
+                                               const void *owner);
+upb_sink *upb_pb_encoder_input(upb_pb_encoder *p);
+upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h,
+                                      upb_bytessink* output);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace pb {
+inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers,
+                                BytesSink* output) {
+  return upb_pb_encoder_create(env, handlers, output);
+}
+inline Sink* Encoder::input() {
+  return upb_pb_encoder_input(this);
+}
+inline reffed_ptr<const Handlers> Encoder::NewHandlers(
+    const upb::MessageDef *md) {
+  const Handlers* h = upb_pb_encoder_newhandlers(md, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_ENCODER_H_ */
+/*
+** upb's core components like upb_decoder and upb_msg are carefully designed to
+** avoid depending on each other for maximum orthogonality.  In other words,
+** you can use a upb_decoder to decode into *any* kind of structure; upb_msg is
+** just one such structure.  A upb_msg can be serialized/deserialized into any
+** format, protobuf binary format is just one such format.
+**
+** However, for convenience we provide functions here for doing common
+** operations like deserializing protobuf binary format into a upb_msg.  The
+** compromise is that this file drags in almost all of upb as a dependency,
+** which could be undesirable if you're trying to use a trimmed-down build of
+** upb.
+**
+** While these routines are convenient, they do not reuse any encoding/decoding
+** state.  For example, if a decoder is JIT-based, it will be re-JITted every
+** time these functions are called.  For this reason, if you are parsing lots
+** of data and efficiency is an issue, these may not be the best functions to
+** use (though they are useful for prototyping, before optimizing).
+*/
+
+#ifndef UPB_GLUE_H
+#define UPB_GLUE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+#include <vector>
+
+extern "C" {
+#endif
+
+/* Loads a binary descriptor and returns a NULL-terminated array of unfrozen
+ * filedefs.  The caller owns the returned array, which must be freed with
+ * upb_gfree(). */
+upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
+                                 upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+
+namespace upb {
+
+inline bool LoadDescriptor(const char* buf, size_t n, Status* status,
+                           std::vector<reffed_ptr<FileDef> >* files) {
+  FileDef** parsed_files = upb_loaddescriptor(buf, n, &parsed_files, status);
+
+  if (parsed_files) {
+    FileDef** p = parsed_files;
+    while (*p) {
+      files->push_back(reffed_ptr<FileDef>(*p, &parsed_files));
+      ++p;
+    }
+    free(parsed_files);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* Templated so it can accept both string and std::string. */
+template <typename T>
+bool LoadDescriptor(const T& desc, Status* status,
+                    std::vector<reffed_ptr<FileDef> >* files) {
+  return LoadDescriptor(desc.c_str(), desc.size(), status, files);
+}
+
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_GLUE_H */
+/*
+** upb::pb::TextPrinter (upb_textprinter)
+**
+** Handlers for writing to protobuf text format.
+*/
+
+#ifndef UPB_TEXT_H_
+#define UPB_TEXT_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class TextPrinter;
+}  /* namespace pb */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter)
+
+#ifdef __cplusplus
+
+class upb::pb::TextPrinter {
+ public:
+  /* The given handlers must have come from NewHandlers().  It must outlive the
+   * TextPrinter. */
+  static TextPrinter *Create(Environment *env, const upb::Handlers *handlers,
+                             BytesSink *output);
+
+  void SetSingleLineMode(bool single_line);
+
+  Sink* input();
+
+  /* If handler caching becomes a requirement we can add a code cache as in
+   * decoder.h */
+  static reffed_ptr<const Handlers> NewHandlers(const MessageDef* md);
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* C API. */
+upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
+                                        upb_bytessink *output);
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
+upb_sink *upb_textprinter_input(upb_textprinter *p);
+
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+                                                const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace pb {
+inline TextPrinter *TextPrinter::Create(Environment *env,
+                                        const upb::Handlers *handlers,
+                                        BytesSink *output) {
+  return upb_textprinter_create(env, handlers, output);
+}
+inline void TextPrinter::SetSingleLineMode(bool single_line) {
+  upb_textprinter_setsingleline(this, single_line);
+}
+inline Sink* TextPrinter::input() {
+  return upb_textprinter_input(this);
+}
+inline reffed_ptr<const Handlers> TextPrinter::NewHandlers(
+    const MessageDef *md) {
+  const Handlers* h = upb_textprinter_newhandlers(md, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace pb */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_TEXT_H_ */
+/*
+** upb::json::Parser (upb_json_parser)
+**
+** Parses JSON according to a specific schema.
+** Support for parsing arbitrary JSON (schema-less) will be added later.
+*/
+
+#ifndef UPB_JSON_PARSER_H_
+#define UPB_JSON_PARSER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace json {
+class Parser;
+class ParserMethod;
+}  /* namespace json */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
+UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted,
+                         upb_json_parsermethod, upb_refcounted)
+
+/* upb::json::Parser **********************************************************/
+
+/* Preallocation hint: parser won't allocate more bytes than this when first
+ * constructed.  This hint may be an overestimate for some build configurations.
+ * But if the parser library is upgraded without recompiling the application,
+ * it may be an underestimate. */
+#define UPB_JSON_PARSER_SIZE 4112
+
+#ifdef __cplusplus
+
+/* Parses an incoming BytesStream, pushing the results to the destination
+ * sink. */
+class upb::json::Parser {
+ public:
+  static Parser* Create(Environment* env, const ParserMethod* method,
+                        Sink* output);
+
+  BytesSink* input();
+
+ private:
+  UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser)
+};
+
+class upb::json::ParserMethod {
+ public:
+  /* Include base methods from upb::ReferenceCounted. */
+  UPB_REFCOUNTED_CPPMETHODS
+
+  /* Returns handlers for parsing according to the specified schema. */
+  static reffed_ptr<const ParserMethod> New(const upb::MessageDef* md);
+
+  /* The destination handlers that are statically bound to this method.
+   * This method is only capable of outputting to a sink that uses these
+   * handlers. */
+  const Handlers* dest_handlers() const;
+
+  /* The input handlers for this decoder method. */
+  const BytesHandler* input_handler() const;
+
+ private:
+  UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+upb_json_parser* upb_json_parser_create(upb_env* e,
+                                        const upb_json_parsermethod* m,
+                                        upb_sink* output);
+upb_bytessink *upb_json_parser_input(upb_json_parser *p);
+
+upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md,
+                                                 const void* owner);
+const upb_handlers *upb_json_parsermethod_desthandlers(
+    const upb_json_parsermethod *m);
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+    const upb_json_parsermethod *m);
+
+/* Include refcounted methods like upb_json_parsermethod_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast)
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace json {
+inline Parser* Parser::Create(Environment* env, const ParserMethod* method,
+                              Sink* output) {
+  return upb_json_parser_create(env, method, output);
+}
+inline BytesSink* Parser::input() {
+  return upb_json_parser_input(this);
+}
+
+inline const Handlers* ParserMethod::dest_handlers() const {
+  return upb_json_parsermethod_desthandlers(this);
+}
+inline const BytesHandler* ParserMethod::input_handler() const {
+  return upb_json_parsermethod_inputhandler(this);
+}
+/* static */
+inline reffed_ptr<const ParserMethod> ParserMethod::New(
+    const MessageDef* md) {
+  const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m);
+  return reffed_ptr<const ParserMethod>(m, &m);
+}
+
+}  /* namespace json */
+}  /* namespace upb */
+
+#endif
+
+
+#endif  /* UPB_JSON_PARSER_H_ */
+/*
+** upb::json::Printer
+**
+** Handlers that emit JSON according to a specific protobuf schema.
+*/
+
+#ifndef UPB_JSON_TYPED_PRINTER_H_
+#define UPB_JSON_TYPED_PRINTER_H_
+
+
+#ifdef __cplusplus
+namespace upb {
+namespace json {
+class Printer;
+}  /* namespace json */
+}  /* namespace upb */
+#endif
+
+UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer)
+
+
+/* upb::json::Printer *********************************************************/
+
+#define UPB_JSON_PRINTER_SIZE 176
+
+#ifdef __cplusplus
+
+/* Prints an incoming stream of data to a BytesSink in JSON format. */
+class upb::json::Printer {
+ public:
+  static Printer* Create(Environment* env, const upb::Handlers* handlers,
+                         BytesSink* output);
+
+  /* The input to the printer. */
+  Sink* input();
+
+  /* Returns handlers for printing according to the specified schema.
+   * If preserve_proto_fieldnames is true, the output JSON will use the
+   * original .proto field names (ie. {"my_field":3}) instead of using
+   * camelCased names, which is the default: (eg. {"myField":3}). */
+  static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md,
+                                                bool preserve_proto_fieldnames);
+
+  static const size_t kSize = UPB_JSON_PRINTER_SIZE;
+
+ private:
+  UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+/* Native C API. */
+upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
+                                          upb_bytessink *output);
+upb_sink *upb_json_printer_input(upb_json_printer *p);
+const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+                                                 bool preserve_fieldnames,
+                                                 const void *owner);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+namespace upb {
+namespace json {
+inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers,
+                                BytesSink* output) {
+  return upb_json_printer_create(env, handlers, output);
+}
+inline Sink* Printer::input() { return upb_json_printer_input(this); }
+inline reffed_ptr<const Handlers> Printer::NewHandlers(
+    const upb::MessageDef *md, bool preserve_proto_fieldnames) {
+  const Handlers* h = upb_json_printer_newhandlers(
+      md, preserve_proto_fieldnames, &h);
+  return reffed_ptr<const Handlers>(h, &h);
+}
+}  /* namespace json */
+}  /* namespace upb */
+
+#endif
+
+#endif  /* UPB_JSON_TYPED_PRINTER_H_ */
diff --git a/src/third_party/protobuf-3/ruby/google-protobuf.gemspec b/src/third_party/protobuf-3/ruby/google-protobuf.gemspec
new file mode 100644
index 0000000..c542abf
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/google-protobuf.gemspec
@@ -0,0 +1,25 @@
+Gem::Specification.new do |s|
+  s.name        = "google-protobuf"
+  s.version     = "3.0.0.alpha.6.0.0"
+  s.licenses    = ["BSD"]
+  s.summary     = "Protocol Buffers"
+  s.description = "Protocol Buffers are Google's data interchange format."
+  s.homepage    = "https://developers.google.com/protocol-buffers"
+  s.authors     = ["Protobuf Authors"]
+  s.email       = "protobuf@googlegroups.com"
+  s.require_paths = ["lib"]
+  s.files       = Dir.glob('lib/**/*.rb')
+  if RUBY_PLATFORM == "java"
+    s.files     += ["lib/google/protobuf_java.jar"]
+  else
+    s.files     += Dir.glob('ext/**/*')
+    s.extensions= ["ext/google/protobuf_c/extconf.rb"]
+    s.add_development_dependency "rake-compiler-dock"
+  end
+  s.test_files  = ["tests/basic.rb",
+                  "tests/stress.rb",
+                  "tests/generated_code_test.rb"]
+  s.add_development_dependency "rake-compiler"
+  s.add_development_dependency "test-unit"
+  s.add_development_dependency "rubygems-tasks"
+end
diff --git a/src/third_party/protobuf-3/ruby/lib/google/protobuf.rb b/src/third_party/protobuf-3/ruby/lib/google/protobuf.rb
new file mode 100644
index 0000000..62bdd1b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/lib/google/protobuf.rb
@@ -0,0 +1,76 @@
+# 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.
+
+# require mixins before we hook them into the java & c code
+require 'google/protobuf/message_exts'
+
+# We define these before requiring the platform-specific modules.
+# That way the module init can grab references to these.
+module Google
+  module Protobuf
+    class Error < StandardError; end
+    class ParseError < Error; end
+  end
+end
+
+if RUBY_PLATFORM == "java"
+  require 'json'
+  require 'google/protobuf_java'
+else
+  begin
+    require "google/#{RUBY_VERSION.sub(/\.\d$/, '')}/protobuf_c"
+  rescue LoadError
+    require 'google/protobuf_c'
+  end
+end
+
+require 'google/protobuf/repeated_field'
+
+module Google
+  module Protobuf
+
+    def self.encode(msg)
+      msg.to_proto
+    end
+
+    def self.encode_json(msg)
+      msg.to_json
+    end
+
+    def self.decode(klass, proto)
+      klass.decode(proto)
+    end
+
+    def self.decode_json(klass, json)
+      klass.decode_json(json)
+    end
+
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/lib/google/protobuf/message_exts.rb b/src/third_party/protobuf-3/ruby/lib/google/protobuf/message_exts.rb
new file mode 100644
index 0000000..e10266b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/lib/google/protobuf/message_exts.rb
@@ -0,0 +1,53 @@
+# 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.
+
+module Google
+  module Protobuf
+    module MessageExts
+
+      #this is only called in jruby; mri loades the ClassMethods differently
+      def self.included(klass)
+        klass.extend(ClassMethods)
+      end
+
+      module ClassMethods
+      end
+
+      def to_json
+        self.class.encode_json(self)
+      end
+
+      def to_proto
+        self.class.encode(self)
+      end
+
+    end
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/lib/google/protobuf/repeated_field.rb b/src/third_party/protobuf-3/ruby/lib/google/protobuf/repeated_field.rb
new file mode 100644
index 0000000..0ad2060
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/lib/google/protobuf/repeated_field.rb
@@ -0,0 +1,188 @@
+# 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.
+
+require 'forwardable'
+
+#
+# This class makes RepeatedField act (almost-) like a Ruby Array.
+# It has convenience methods that extend the core C or Java based
+# methods.
+#
+# This is a best-effort to mirror Array behavior.  Two comments:
+#  1) patches always welcome :)
+#  2) if performance is an issue, feel free to rewrite the method
+#     in jruby and C.  The source code has plenty of examples
+#
+# KNOWN ISSUES
+#   - #[]= doesn't allow less used approaches such as `arr[1, 2] = 'fizz'`
+#   - #concat should return the orig array
+#   - #push should accept multiple arguments and push them all at the same time
+#
+module Google
+  module Protobuf
+    class RepeatedField
+      extend Forwardable
+
+      # methods defined in C or Java:
+      #   +
+      #   [], at
+      #   []=
+      #   concat
+      #   clear
+      #   dup, clone
+      #   each
+      #   push, <<
+      #   replace
+      #   length, size
+      #   ==
+      #   to_ary, to_a
+      #   also all enumerable
+      #
+      # NOTE:  using delegators rather than method_missing to make the
+      #        relationship explicit instead of implicit
+      def_delegators :to_ary,
+        :&, :*, :-, :'<=>',
+        :assoc, :bsearch, :bsearch_index, :combination, :compact, :count,
+        :cycle, :dig, :drop, :drop_while, :eql?, :fetch, :find_index, :flatten,
+        :include?, :index, :inspect, :join,
+        :pack, :permutation, :product, :pretty_print, :pretty_print_cycle,
+        :rassoc, :repeated_combination, :repeated_permutation, :reverse,
+        :rindex, :rotate, :sample, :shuffle, :shelljoin, :slice,
+        :to_s, :transpose, :uniq, :|
+
+
+      def first(n=nil)
+        n ? self[0..n] : self[0]
+      end
+
+
+      def last(n=nil)
+        n ? self[(self.size-n-1)..-1] : self[-1]
+      end
+
+
+      def pop(n=nil)
+        if n
+          results = []
+          n.times{ results << pop_one }
+          return results
+        else
+          return pop_one
+        end
+      end
+
+
+      def empty?
+        self.size == 0
+      end
+
+      # array aliases into enumerable
+      alias_method :each_index, :each_with_index
+      alias_method :slice, :[]
+      alias_method :values_at, :select
+      alias_method :map, :collect
+
+
+      class << self
+        def define_array_wrapper_method(method_name)
+          define_method(method_name) do |*args, &block|
+            arr = self.to_a
+            result = arr.send(method_name, *args)
+            self.replace(arr)
+            return result if result
+            return block ? block.call : result
+          end
+        end
+        private :define_array_wrapper_method
+
+
+        def define_array_wrapper_with_result_method(method_name)
+          define_method(method_name) do |*args, &block|
+            # result can be an Enumerator, Array, or nil
+            # Enumerator can sometimes be returned if a block is an optional argument and it is not passed in
+            # nil usually specifies that no change was made
+            result = self.to_a.send(method_name, *args, &block)
+            if result
+              new_arr = result.to_a
+              self.replace(new_arr)
+              if result.is_a?(Enumerator)
+                # generate a fresh enum; rewinding the exiting one, in Ruby 2.2, will
+                # reset the enum with the same length, but all the #next calls will
+                # return nil
+                result = new_arr.to_enum
+                # generate a wrapper enum so any changes which occur by a chained
+                # enum can be captured
+                ie = ProxyingEnumerator.new(self, result)
+                result = ie.to_enum
+              end
+            end
+            result
+          end
+        end
+        private :define_array_wrapper_with_result_method
+      end
+
+
+      %w(delete delete_at delete_if shift slice! unshift).each do |method_name|
+        define_array_wrapper_method(method_name)
+      end
+
+
+      %w(collect! compact! fill flatten! insert reverse!
+        rotate! select! shuffle! sort! sort_by! uniq!).each do |method_name|
+        define_array_wrapper_with_result_method(method_name)
+      end
+      alias_method :keep_if, :select!
+      alias_method :map!, :collect!
+      alias_method :reject!, :delete_if
+
+
+      # propagates changes made by user of enumerator back to the original repeated field.
+      # This only applies in cases where the calling function which created the enumerator,
+      # such as #sort!, modifies itself rather than a new array, such as #sort
+      class ProxyingEnumerator < Struct.new(:repeated_field, :external_enumerator)
+        def each(*args, &block)
+          results = []
+          external_enumerator.each_with_index do |val, i|
+            result = yield(val)
+            results << result
+            #nil means no change occured from yield; usually occurs when #to_a is called
+            if result
+              repeated_field[i] = result if result != val
+            end
+          end
+          results
+        end
+      end
+
+
+    end
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/pom.xml b/src/third_party/protobuf-3/ruby/pom.xml
new file mode 100644
index 0000000..4cbd6d3
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+      <groupId>com.google</groupId>
+      <artifactId>google</artifactId>
+      <version>1</version>
+    </parent>
+
+    <groupId>com.google.protobuf.jruby</groupId>
+    <artifactId>protobuf-jruby</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>Protocol Buffer JRuby native extension</name>
+    <description>
+      Protocol Buffers are a way of encoding structured data in an efficient yet
+      extensible format.
+    </description>
+    <inceptionYear>2014</inceptionYear>
+    <url>https://developers.google.com/protocol-buffers/</url>
+    <licenses>
+      <license>
+        <name>New BSD license</name>
+        <url>http://www.opensource.org/licenses/bsd-license.php</url>
+        <distribution>repo</distribution>
+      </license>
+    </licenses>
+    <scm>
+      <url>https://github.com/google/protobuf</url>
+      <connection>
+        scm:git:https://github.com/google/protobuf.git
+      </connection>
+    </scm>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <ruby.sources>lib/google</ruby.sources>
+        <jar.finalName>protobuf_java</jar.finalName>
+    </properties>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <finalName>${jar.finalName}</finalName>
+                    <outputDirectory>${ruby.sources}</outputDirectory>
+                    <appendAssemblyId>false</appendAssemblyId>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-compiler-plugin</artifactId>
+              <configuration>
+                <source>1.6</source>
+                <target>1.6</target>
+              </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jruby</groupId>
+            <artifactId>jruby-complete</artifactId>
+            <version>1.7.13</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>3.0.0-alpha-3</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
new file mode 100644
index 0000000..5addae5
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
@@ -0,0 +1,167 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.*;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "Builder")
+public class RubyBuilder extends RubyObject {
+    public static void createRubyBuilder(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cBuilder = protobuf.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyBuilder(runtime, klazz);
+            }
+        });
+        cBuilder.defineAnnotatedMethods(RubyBuilder.class);
+    }
+
+    public RubyBuilder(Ruby runtime, RubyClass metaClass) {
+        super(runtime, metaClass);
+        this.cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
+        this.cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
+        this.cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MessageBuilderContext");
+        this.cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumBuilderContext");
+    }
+
+    /*
+     * call-seq:
+     *     Builder.new => builder
+     *
+     * Creates a new Builder. A Builder can accumulate a set of new message and enum
+     * descriptors and atomically register them into a pool in a way that allows for
+     * (co)recursive type references.
+     */
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        Ruby runtime = context.runtime;
+        this.pendingList = runtime.newArray();
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     Builder.add_message(name, &block)
+     *
+     * Creates a new, empty descriptor with the given name, and invokes the block in
+     * the context of a MessageBuilderContext on that descriptor. The block can then
+     * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+     * methods to define the message fields.
+     *
+     * This is the recommended, idiomatic way to build message definitions.
+     */
+    @JRubyMethod(name = "add_message")
+    public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) {
+        RubyDescriptor msgdef = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
+        IRubyObject ctx = cMessageBuilderContext.newInstance(context, msgdef, this, Block.NULL_BLOCK);
+        msgdef.setName(context, name);
+        if (block.isGiven()) {
+            if (block.arity() == Arity.ONE_ARGUMENT) {
+                block.yield(context, ctx);
+            } else {
+                Binding binding = block.getBinding();
+                binding.setSelf(ctx);
+                block.yieldSpecific(context);
+            }
+        }
+        this.pendingList.add(msgdef);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Builder.add_enum(name, &block)
+     *
+     * Creates a new, empty enum descriptor with the given name, and invokes the block in
+     * the context of an EnumBuilderContext on that descriptor. The block can then
+     * call EnumBuilderContext#add_value to define the enum values.
+     *
+     * This is the recommended, idiomatic way to build enum definitions.
+     */
+    @JRubyMethod(name = "add_enum")
+    public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) {
+        RubyEnumDescriptor enumDef = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
+        IRubyObject ctx = cEnumBuilderContext.newInstance(context, enumDef, Block.NULL_BLOCK);
+        enumDef.setName(context, name);
+
+        if (block.isGiven()) {
+            if (block.arity() == Arity.ONE_ARGUMENT) {
+                block.yield(context, ctx);
+            } else {
+                Binding binding = block.getBinding();
+                binding.setSelf(ctx);
+                block.yieldSpecific(context);
+            }
+        }
+
+        this.pendingList.add(enumDef);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Builder.finalize_to_pool(pool)
+     *
+     * Adds all accumulated message and enum descriptors created in this builder
+     * context to the given pool. The operation occurs atomically, and all
+     * descriptors can refer to each other (including in cycles). This is the only
+     * way to build (co)recursive message definitions.
+     *
+     * This method is usually called automatically by DescriptorPool#build after it
+     * invokes the given user block in the context of the builder. The user should
+     * not normally need to call this manually because a Builder is not normally
+     * created manually.
+     */
+    @JRubyMethod(name = "finalize_to_pool")
+    public IRubyObject finalizeToPool(ThreadContext context, IRubyObject rbPool) {
+        RubyDescriptorPool pool = (RubyDescriptorPool) rbPool;
+        for (int i = 0; i < this.pendingList.size(); i++) {
+            IRubyObject defRb = this.pendingList.entry(i);
+            if (defRb instanceof RubyDescriptor) {
+                pool.addToSymtab(context, (RubyDescriptor) defRb);
+            } else {
+                pool.addToSymtab(context, (RubyEnumDescriptor) defRb);
+            }
+        }
+        this.pendingList = context.runtime.newArray();
+        return context.runtime.getNil();
+    }
+
+    protected RubyArray pendingList;
+    private RubyClass cDescriptor, cEnumDescriptor, cMessageBuilderContext, cEnumBuilderContext;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
new file mode 100644
index 0000000..dd9179b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
@@ -0,0 +1,269 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+@JRubyClass(name = "Descriptor", include = "Enumerable")
+public class RubyDescriptor extends RubyObject {
+    public static void createRubyDescriptor(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cDescriptor = protobuf.defineClassUnder("Descriptor", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyDescriptor(runtime, klazz);
+            }
+        });
+        cDescriptor.includeModule(runtime.getEnumerable());
+        cDescriptor.defineAnnotatedMethods(RubyDescriptor.class);
+    }
+
+    public RubyDescriptor(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.new => descriptor
+     *
+     * Creates a new, empty, message type descriptor. At a minimum, its name must be
+     * set before it is added to a pool. It cannot be used to create messages until
+     * it is added to a pool, after which it becomes immutable (as part of a
+     * finalization process).
+     */
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        this.builder = DescriptorProtos.DescriptorProto.newBuilder();
+        this.fieldDefMap = new HashMap<String, RubyFieldDescriptor>();
+        this.oneofDefs = new HashMap<IRubyObject, RubyOneofDescriptor>();
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.name => name
+     *
+     * Returns the name of this message type as a fully-qualfied string (e.g.,
+     * My.Package.MessageType).
+     */
+    @JRubyMethod(name = "name")
+    public IRubyObject getName(ThreadContext context) {
+        return this.name;
+    }
+
+    /*
+     * call-seq:
+     *    Descriptor.name = name
+     *
+     * Assigns a name to this message type. The descriptor must not have been added
+     * to a pool yet.
+     */
+    @JRubyMethod(name = "name=")
+    public IRubyObject setName(ThreadContext context, IRubyObject name) {
+        this.name = name;
+        this.builder.setName(Utils.escapeIdentifier(this.name.asJavaString()));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.add_field(field) => nil
+     *
+     * Adds the given FieldDescriptor to this message type. The descriptor must not
+     * have been added to a pool yet. Raises an exception if a field with the same
+     * name or number already exists. Sub-type references (e.g. for fields of type
+     * message) are not resolved at this point.
+     */
+    @JRubyMethod(name = "add_field")
+    public IRubyObject addField(ThreadContext context, IRubyObject obj) {
+        RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) obj;
+        this.fieldDefMap.put(fieldDef.getName(context).asJavaString(), fieldDef);
+        this.builder.addField(fieldDef.build());
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.lookup(name) => FieldDescriptor
+     *
+     * Returns the field descriptor for the field with the given name, if present,
+     * or nil if none.
+     */
+    @JRubyMethod
+    public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) {
+        return this.fieldDefMap.get(fieldName.asJavaString());
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.msgclass => message_klass
+     *
+     * Returns the Ruby class created for this message type. Valid only once the
+     * message type has been added to a pool.
+     */
+    @JRubyMethod
+    public IRubyObject msgclass(ThreadContext context) {
+        if (this.klazz == null) {
+            this.klazz = buildClassFromDescriptor(context);
+        }
+        return this.klazz;
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.each(&block)
+     *
+     * Iterates over fields in this message type, yielding to the block on each one.
+     */
+    @JRubyMethod
+    public IRubyObject each(ThreadContext context, Block block) {
+        for (Map.Entry<String, RubyFieldDescriptor> entry : fieldDefMap.entrySet()) {
+            block.yield(context, entry.getValue());
+        }
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.add_oneof(oneof) => nil
+     *
+     * Adds the given OneofDescriptor to this message type. This descriptor must not
+     * have been added to a pool yet. Raises an exception if a oneof with the same
+     * name already exists, or if any of the oneof's fields' names or numbers
+     * conflict with an existing field in this message type. All fields in the oneof
+     * are added to the message descriptor. Sub-type references (e.g. for fields of
+     * type message) are not resolved at this point.
+     */
+    @JRubyMethod(name = "add_oneof")
+    public IRubyObject addOneof(ThreadContext context, IRubyObject obj) {
+        RubyOneofDescriptor def = (RubyOneofDescriptor) obj;
+        builder.addOneofDecl(def.build(builder.getOneofDeclCount()));
+        for (RubyFieldDescriptor fieldDescriptor : def.getFields()) {
+            addField(context, fieldDescriptor);
+        }
+        oneofDefs.put(def.getName(context), def);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.each_oneof(&block) => nil
+     *
+     * Invokes the given block for each oneof in this message type, passing the
+     * corresponding OneofDescriptor.
+     */
+    @JRubyMethod(name = "each_oneof")
+    public IRubyObject eachOneof(ThreadContext context, Block block) {
+        for (RubyOneofDescriptor oneofDescriptor : oneofDefs.values()) {
+            block.yieldSpecific(context, oneofDescriptor);
+        }
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Descriptor.lookup_oneof(name) => OneofDescriptor
+     *
+     * Returns the oneof descriptor for the oneof with the given name, if present,
+     * or nil if none.
+     */
+    @JRubyMethod(name = "lookup_oneof")
+    public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) {
+        if (name instanceof RubySymbol) {
+            name = ((RubySymbol) name).id2name();
+        }
+        return oneofDefs.containsKey(name) ? oneofDefs.get(name) : context.runtime.getNil();
+    }
+
+    public void setDescriptor(Descriptors.Descriptor descriptor) {
+        this.descriptor = descriptor;
+    }
+
+    public Descriptors.Descriptor getDescriptor() {
+        return this.descriptor;
+    }
+
+    public DescriptorProtos.DescriptorProto.Builder getBuilder() {
+        return builder;
+    }
+
+    public void setMapEntry(boolean isMapEntry) {
+        this.builder.setOptions(DescriptorProtos.MessageOptions.newBuilder().setMapEntry(isMapEntry));
+    }
+
+    private RubyModule buildClassFromDescriptor(ThreadContext context) {
+        Ruby runtime = context.runtime;
+
+        ObjectAllocator allocator = new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyMessage(runtime, klazz, descriptor);
+            }
+        };
+
+        // rb_define_class_id
+        RubyClass klass = RubyClass.newClass(runtime, runtime.getObject());
+        klass.setAllocator(allocator);
+        klass.makeMetaClass(runtime.getObject().getMetaClass());
+        klass.inherit(runtime.getObject());
+        RubyModule messageExts = runtime.getClassFromPath("Google::Protobuf::MessageExts");
+        klass.include(new IRubyObject[] {messageExts});
+        klass.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
+        klass.defineAnnotatedMethods(RubyMessage.class);
+        return klass;
+    }
+
+    protected RubyFieldDescriptor lookup(String fieldName) {
+        return fieldDefMap.get(Utils.unescapeIdentifier(fieldName));
+    }
+
+    private IRubyObject name;
+    private RubyModule klazz;
+
+    private DescriptorProtos.DescriptorProto.Builder builder;
+    private Descriptors.Descriptor descriptor;
+    private Map<String, RubyFieldDescriptor> fieldDefMap;
+    private Map<IRubyObject, RubyOneofDescriptor> oneofDefs;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
new file mode 100644
index 0000000..0345cb9
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
@@ -0,0 +1,169 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.*;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JRubyClass(name = "DescriptorPool")
+public class RubyDescriptorPool extends RubyObject {
+    public static void createRubyDescriptorPool(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cDescriptorPool = protobuf.defineClassUnder("DescriptorPool", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyDescriptorPool(runtime, klazz);
+            }
+        });
+
+        cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class);
+        descriptorPool = (RubyDescriptorPool) cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK);
+    }
+
+    public RubyDescriptorPool(Ruby ruby, RubyClass klazz) {
+        super(ruby, klazz);
+    }
+
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        this.symtab = new HashMap<IRubyObject, IRubyObject>();
+        this.cBuilder = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Builder");
+        this.builder = DescriptorProtos.FileDescriptorProto.newBuilder();
+        return this;
+    }
+
+    @JRubyMethod
+    public IRubyObject build(ThreadContext context, Block block) {
+        RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, Block.NULL_BLOCK);
+        if (block.arity() == Arity.ONE_ARGUMENT) {
+            block.yield(context, ctx);
+        } else {
+            Binding binding = block.getBinding();
+            binding.setSelf(ctx);
+            block.yieldSpecific(context);
+        }
+        ctx.finalizeToPool(context, this);
+        buildFileDescriptor(context);
+        return context.runtime.getNil();
+    }
+
+    @JRubyMethod
+    public IRubyObject lookup(ThreadContext context, IRubyObject name) {
+        IRubyObject descriptor = this.symtab.get(name);
+        if (descriptor == null) {
+            return context.runtime.getNil();
+        }
+        return descriptor;
+    }
+
+    /*
+     * call-seq:
+     *     DescriptorPool.generated_pool => descriptor_pool
+     *
+     * Class method that returns the global DescriptorPool. This is a singleton into
+     * which generated-code message and enum types are registered. The user may also
+     * register types in this pool for convenience so that they do not have to hold
+     * a reference to a private pool instance.
+     */
+    @JRubyMethod(meta = true, name = "generated_pool")
+    public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv) {
+        return descriptorPool;
+    }
+
+    protected void addToSymtab(ThreadContext context, RubyDescriptor def) {
+        symtab.put(def.getName(context), def);
+        this.builder.addMessageType(def.getBuilder());
+    }
+
+    protected void addToSymtab(ThreadContext context, RubyEnumDescriptor def) {
+        symtab.put(def.getName(context), def);
+        this.builder.addEnumType(def.getBuilder());
+    }
+
+    private void buildFileDescriptor(ThreadContext context) {
+        Ruby runtime = context.runtime;
+        try {
+            this.builder.setSyntax("proto3");
+            final Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(
+                    this.builder.build(), new Descriptors.FileDescriptor[]{});
+
+            for (Descriptors.EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) {
+                String enumName = Utils.unescapeIdentifier(enumDescriptor.getName());
+                if (enumDescriptor.findValueByNumber(0) == null) {
+                    throw runtime.newTypeError("Enum definition " + enumName
+                            + " does not contain a value for '0'");
+                }
+                ((RubyEnumDescriptor) symtab.get(runtime.newString(enumName)))
+                        .setDescriptor(enumDescriptor);
+            }
+            for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) {
+                RubyDescriptor rubyDescriptor = ((RubyDescriptor)
+                        symtab.get(runtime.newString(Utils.unescapeIdentifier(descriptor.getName()))));
+                for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) {
+                    if (fieldDescriptor.isRequired()) {
+                        throw runtime.newTypeError("Required fields are unsupported in proto3");
+                    }
+                    RubyFieldDescriptor rubyFieldDescriptor = rubyDescriptor.lookup(fieldDescriptor.getName());
+                    rubyFieldDescriptor.setFieldDef(fieldDescriptor);
+                    if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+                        RubyDescriptor subType = (RubyDescriptor) lookup(context,
+                                runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getMessageType().getName())));
+                        rubyFieldDescriptor.setSubType(subType);
+                    }
+                    if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.ENUM) {
+                        RubyEnumDescriptor subType = (RubyEnumDescriptor) lookup(context,
+                                runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getEnumType().getName())));
+                        rubyFieldDescriptor.setSubType(subType);
+                    }
+                }
+                rubyDescriptor.setDescriptor(descriptor);
+            }
+        } catch (Descriptors.DescriptorValidationException e) {
+            throw runtime.newRuntimeError(e.getMessage());
+        }
+    }
+
+    private static RubyDescriptorPool descriptorPool;
+
+    private RubyClass cBuilder;
+    private Map<IRubyObject, IRubyObject> symtab;
+    private DescriptorProtos.FileDescriptorProto.Builder builder;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
new file mode 100644
index 0000000..929d869
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
@@ -0,0 +1,86 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+public class RubyEnum {
+    /*
+     * call-seq:
+     *     Enum.lookup(number) => name
+     *
+     * This module method, provided on each generated enum module, looks up an enum
+     * value by number and returns its name as a Ruby symbol, or nil if not found.
+     */
+    @JRubyMethod(meta = true)
+    public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) {
+        RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+        Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
+        Descriptors.EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number));
+        if (value == null) return context.runtime.getNil();
+        return context.runtime.newSymbol(value.getName());
+    }
+
+    /*
+     * call-seq:
+     *     Enum.resolve(name) => number
+     *
+     * This module method, provided on each generated enum module, looks up an enum
+     * value by name (as a Ruby symbol) and returns its name, or nil if not found.
+     */
+    @JRubyMethod(meta = true)
+    public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) {
+        RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+        Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
+        Descriptors.EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
+        if (value == null) return context.runtime.getNil();
+        return context.runtime.newFixnum(value.getNumber());
+    }
+
+    /*
+     * call-seq:
+     *     Enum.descriptor
+     *
+     * This module method, provided on each generated enum module, returns the
+     * EnumDescriptor corresponding to this enum type.
+     */
+    @JRubyMethod(meta = true, name = "descriptor")
+    public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) {
+        return ((RubyModule) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR);
+    }
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
new file mode 100644
index 0000000..e4cac34
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
@@ -0,0 +1,82 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "EnumBuilderContext")
+public class RubyEnumBuilderContext extends RubyObject {
+    public static void createRubyEnumBuilderContext(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cMessageBuilderContext = protobuf.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyEnumBuilderContext(runtime, klazz);
+            }
+        });
+        cMessageBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class);
+    }
+
+    public RubyEnumBuilderContext(Ruby ruby, RubyClass klazz) {
+        super(ruby, klazz);
+    }
+
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context, IRubyObject enumDescriptor) {
+        this.enumDescriptor = (RubyEnumDescriptor) enumDescriptor;
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     EnumBuilder.add_value(name, number)
+     *
+     * Adds the given name => number mapping to the enum type. Name must be a Ruby
+     * symbol.
+     */
+    @JRubyMethod
+    public IRubyObject value(ThreadContext context, IRubyObject name, IRubyObject number) {
+        this.enumDescriptor.addValue(context, name, number);
+        return context.runtime.getNil();
+    }
+
+    private RubyEnumDescriptor enumDescriptor;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
new file mode 100644
index 0000000..4df832d
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
@@ -0,0 +1,185 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.RubyNumeric;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "EnumDescriptor", include = "Enumerable")
+public class RubyEnumDescriptor extends RubyObject {
+    public static void createRubyEnumDescriptor(Ruby runtime) {
+        RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cEnumDescriptor = mProtobuf.defineClassUnder("EnumDescriptor", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyEnumDescriptor(runtime, klazz);
+            }
+        });
+        cEnumDescriptor.includeModule(runtime.getEnumerable());
+        cEnumDescriptor.defineAnnotatedMethods(RubyEnumDescriptor.class);
+    }
+
+    public RubyEnumDescriptor(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.new => enum_descriptor
+     *
+     * Creates a new, empty, enum descriptor. Must be added to a pool before the
+     * enum type can be used. The enum type may only be modified prior to adding to
+     * a pool.
+     */
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        this.builder = DescriptorProtos.EnumDescriptorProto.newBuilder();
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.name => name
+     *
+     * Returns the name of this enum type.
+     */
+    @JRubyMethod(name = "name")
+    public IRubyObject getName(ThreadContext context) {
+        return this.name;
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.name = name
+     *
+     * Sets the name of this enum type. Cannot be called if the enum type has
+     * already been added to a pool.
+     */
+    @JRubyMethod(name = "name=")
+    public IRubyObject setName(ThreadContext context, IRubyObject name) {
+        this.name = name;
+        this.builder.setName(Utils.escapeIdentifier(name.asJavaString()));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.add_value(key, value)
+     *
+     * Adds a new key => value mapping to this enum type. Key must be given as a
+     * Ruby symbol. Cannot be called if the enum type has already been added to a
+     * pool. Will raise an exception if the key or value is already in use.
+     */
+    @JRubyMethod(name = "add_value")
+    public IRubyObject addValue(ThreadContext context, IRubyObject name, IRubyObject number) {
+        DescriptorProtos.EnumValueDescriptorProto.Builder valueBuilder = DescriptorProtos.EnumValueDescriptorProto.newBuilder();
+        valueBuilder.setName(name.asJavaString());
+        valueBuilder.setNumber(RubyNumeric.num2int(number));
+        this.builder.addValue(valueBuilder);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.each(&block)
+     *
+     * Iterates over key => value mappings in this enum's definition, yielding to
+     * the block with (key, value) arguments for each one.
+     */
+    @JRubyMethod
+    public IRubyObject each(ThreadContext context, Block block) {
+        Ruby runtime = context.runtime;
+        for (Descriptors.EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) {
+            block.yield(context, runtime.newArray(runtime.newSymbol(enumValueDescriptor.getName()),
+                    runtime.newFixnum(enumValueDescriptor.getNumber())));
+        }
+        return runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     EnumDescriptor.enummodule => module
+     *
+     * Returns the Ruby module corresponding to this enum type. Cannot be called
+     * until the enum descriptor has been added to a pool.
+     */
+    @JRubyMethod
+    public IRubyObject enummodule(ThreadContext context) {
+        if (this.klazz == null) {
+            this.klazz = buildModuleFromDescriptor(context);
+        }
+        return this.klazz;
+    }
+
+    public void setDescriptor(Descriptors.EnumDescriptor descriptor) {
+        this.descriptor = descriptor;
+    }
+
+    public Descriptors.EnumDescriptor getDescriptor() {
+        return this.descriptor;
+    }
+
+    public DescriptorProtos.EnumDescriptorProto.Builder getBuilder() {
+        return this.builder;
+    }
+
+    private RubyModule buildModuleFromDescriptor(ThreadContext context) {
+        Ruby runtime = context.runtime;
+        Utils.checkNameAvailability(context, name.asJavaString());
+
+        RubyModule enumModule = RubyModule.newModule(runtime);
+        for (Descriptors.EnumValueDescriptor value : descriptor.getValues()) {
+            enumModule.defineConstant(value.getName(), runtime.newFixnum(value.getNumber()));
+        }
+
+        enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
+        enumModule.defineAnnotatedMethods(RubyEnum.class);
+        return enumModule;
+    }
+
+    private IRubyObject name;
+    private RubyModule klazz;
+    private Descriptors.EnumDescriptor descriptor;
+    private DescriptorProtos.EnumDescriptorProto.Builder builder;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
new file mode 100644
index 0000000..f3c488b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
@@ -0,0 +1,277 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "FieldDescriptor")
+public class RubyFieldDescriptor extends RubyObject {
+    public static void createRubyFileDescriptor(Ruby runtime) {
+        RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyFieldDescriptor(runtime, klazz);
+            }
+        });
+        cFieldDescriptor.defineAnnotatedMethods(RubyFieldDescriptor.class);
+    }
+
+    public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.new => field
+     *
+     * Returns a new field descriptor. Its name, type, etc. must be set before it is
+     * added to a message type.
+     */
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        builder = DescriptorProtos.FieldDescriptorProto.newBuilder();
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.label
+     *
+     * Return the label of this field.
+     */
+    @JRubyMethod(name = "label")
+    public IRubyObject getLabel(ThreadContext context) {
+        return this.label;
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.label = label
+     *
+     * Sets the label on this field. Cannot be called if field is part of a message
+     * type already in a pool.
+     */
+    @JRubyMethod(name = "label=")
+    public IRubyObject setLabel(ThreadContext context, IRubyObject value) {
+        String labelName = value.asJavaString();
+        this.label = context.runtime.newSymbol(labelName.toLowerCase());
+        this.builder.setLabel(
+                DescriptorProtos.FieldDescriptorProto.Label.valueOf("LABEL_" + labelName.toUpperCase()));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.name => name
+     *
+     * Returns the name of this field as a Ruby String, or nil if it is not set.
+     */
+    @JRubyMethod(name = "name")
+    public IRubyObject getName(ThreadContext context) {
+        return this.name;
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.name = name
+     *
+     * Sets the name of this field. Cannot be called once the containing message
+     * type, if any, is added to a pool.
+     */
+    @JRubyMethod(name = "name=")
+    public IRubyObject setName(ThreadContext context, IRubyObject value) {
+        String nameStr = value.asJavaString();
+        this.name = context.runtime.newString(nameStr);
+        this.builder.setName(Utils.escapeIdentifier(nameStr));
+        return context.runtime.getNil();
+    }
+
+
+    @JRubyMethod(name = "subtype")
+    public IRubyObject getSubType(ThreadContext context) {
+        return subType;
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.type => type
+     *
+     * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+     *
+     * Valid field types are:
+     *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+     *     :bytes, :message.
+     */
+    @JRubyMethod(name = "type")
+    public IRubyObject getType(ThreadContext context) {
+        return Utils.fieldTypeToRuby(context, this.builder.getType());
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.type = type
+     *
+     * Sets this field's type. Cannot be called if field is part of a message type
+     * already in a pool.
+     */
+    @JRubyMethod(name = "type=")
+    public IRubyObject setType(ThreadContext context, IRubyObject value) {
+        this.builder.setType(DescriptorProtos.FieldDescriptorProto.Type.valueOf("TYPE_" + value.asJavaString().toUpperCase()));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.number => number
+     *
+     * Returns this field's number, as a Ruby Integer, or nil if not yet set.
+     *
+     */
+    @JRubyMethod(name = "number")
+    public IRubyObject getnumber(ThreadContext context) {
+        return this.number;
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.number = number
+     *
+     * Sets the tag number for this field. Cannot be called if field is part of a
+     * message type already in a pool.
+     */
+    @JRubyMethod(name = "number=")
+    public IRubyObject setNumber(ThreadContext context, IRubyObject value) {
+        this.number = value;
+        this.builder.setNumber(RubyNumeric.num2int(value));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.submsg_name = submsg_name
+     *
+     * Sets the name of the message or enum type corresponding to this field, if it
+     * is a message or enum field (respectively). This type name will be resolved
+     * within the context of the pool to which the containing message type is added.
+     * Cannot be called on field that are not of message or enum type, or on fields
+     * that are part of a message type already added to a pool.
+     */
+    @JRubyMethod(name = "submsg_name=")
+    public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
+        this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.get(message) => value
+     *
+     * Returns the value set for this field on the given message. Raises an
+     * exception if message is of the wrong type.
+     */
+    @JRubyMethod(name = "get")
+    public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) {
+        RubyMessage message = (RubyMessage) msgRb;
+        if (message.getDescriptor() != fieldDef.getContainingType()) {
+            throw context.runtime.newTypeError("set method called on wrong message type");
+        }
+        return message.getField(context, fieldDef);
+    }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.set(message, value)
+     *
+     * Sets the value corresponding to this field to the given value on the given
+     * message. Raises an exception if message is of the wrong type. Performs the
+     * ordinary type-checks for field setting.
+     */
+    @JRubyMethod(name = "set")
+    public IRubyObject setValue(ThreadContext context, IRubyObject msgRb, IRubyObject value) {
+        RubyMessage message = (RubyMessage) msgRb;
+        if (message.getDescriptor() != fieldDef.getContainingType()) {
+            throw context.runtime.newTypeError("set method called on wrong message type");
+        }
+        message.setField(context, fieldDef, value);
+        return context.runtime.getNil();
+    }
+
+    protected void setSubType(IRubyObject rubyDescriptor) {
+        this.subType = rubyDescriptor;
+    }
+
+    protected void setFieldDef(Descriptors.FieldDescriptor fieldDescriptor) {
+        this.fieldDef = fieldDescriptor;
+    }
+
+    protected void setOneofName(IRubyObject name) {
+        oneofName = name;
+    }
+
+    protected void setOneofIndex(int index) {
+        hasOneofIndex = true;
+        oneofIndex = index;
+    }
+
+    protected IRubyObject getOneofName() {
+        return oneofName;
+    }
+
+    protected Descriptors.FieldDescriptor getFieldDef() {
+        return fieldDef;
+    }
+
+    protected DescriptorProtos.FieldDescriptorProto build() {
+        if (hasOneofIndex)
+            builder.setOneofIndex(oneofIndex);
+        return this.builder.build();
+    }
+
+    private DescriptorProtos.FieldDescriptorProto.Builder builder;
+    private IRubyObject name;
+    private IRubyObject label;
+    private IRubyObject number;
+    private IRubyObject subType;
+    private IRubyObject oneofName;
+    private Descriptors.FieldDescriptor fieldDef;
+    private int oneofIndex;
+    private boolean hasOneofIndex = false;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
new file mode 100644
index 0000000..2d4c03b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
@@ -0,0 +1,434 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.MapEntry;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.internal.runtime.methods.DynamicMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.ByteList;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JRubyClass(name = "Map", include = "Enumerable")
+public class RubyMap extends RubyObject {
+    public static void createRubyMap(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cMap = protobuf.defineClassUnder("Map", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+                return new RubyMap(ruby, rubyClass);
+            }
+        });
+        cMap.includeModule(runtime.getEnumerable());
+        cMap.defineAnnotatedMethods(RubyMap.class);
+    }
+
+    public RubyMap(Ruby ruby, RubyClass rubyClass) {
+        super(ruby, rubyClass);
+    }
+
+    /*
+     * call-seq:
+     *     Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
+     *     => new map
+     *
+     * Allocates a new Map container. This constructor may be called with 2, 3, or 4
+     * arguments. The first two arguments are always present and are symbols (taking
+     * on the same values as field-type symbols in message descriptors) that
+     * indicate the type of the map key and value fields.
+     *
+     * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
+     * :string, :bytes.
+     *
+     * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
+     * :string, :bytes, :enum, :message.
+     *
+     * The third argument, value_typeclass, must be present if value_type is :enum
+     * or :message. As in RepeatedField#new, this argument must be a message class
+     * (for :message) or enum module (for :enum).
+     *
+     * The last argument, if present, provides initial content for map. Note that
+     * this may be an ordinary Ruby hashmap or another Map instance with identical
+     * key and value types. Also note that this argument may be present whether or
+     * not value_typeclass is present (and it is unambiguously separate from
+     * value_typeclass because value_typeclass's presence is strictly determined by
+     * value_type). The contents of this initial hashmap or Map instance are
+     * shallow-copied into the new Map: the original map is unmodified, but
+     * references to underlying objects will be shared if the value type is a
+     * message type.
+     */
+
+    @JRubyMethod(required = 2, optional = 2)
+    public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
+        this.table = new HashMap<IRubyObject, IRubyObject>();
+        this.keyType = Utils.rubyToFieldType(args[0]);
+        this.valueType = Utils.rubyToFieldType(args[1]);
+
+        switch(keyType) {
+            case INT32:
+            case INT64:
+            case UINT32:
+            case UINT64:
+            case BOOL:
+            case STRING:
+            case BYTES:
+                // These are OK.
+                break;
+            default:
+                throw context.runtime.newArgumentError("Invalid key type for map.");
+        }
+
+        int initValueArg = 2;
+        if (needTypeclass(this.valueType) && args.length > 2) {
+            this.valueTypeClass = args[2];
+            Utils.validateTypeClass(context, this.valueType, this.valueTypeClass);
+            initValueArg = 3;
+        } else {
+            this.valueTypeClass = context.runtime.getNilClass();
+        }
+
+        // Table value type is always UINT64: this ensures enough space to store the
+        // native_slot value.
+        if (args.length > initValueArg) {
+            mergeIntoSelf(context, args[initValueArg]);
+        }
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     Map.[]=(key, value) => value
+     *
+     * Inserts or overwrites the value at the given key with the given new value.
+     * Throws an exception if the key type is incorrect. Returns the new value that
+     * was just inserted.
+     */
+    @JRubyMethod(name = "[]=")
+    public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
+        Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
+        Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
+        IRubyObject symbol;
+        if (valueType == Descriptors.FieldDescriptor.Type.ENUM &&
+                Utils.isRubyNum(value) &&
+                ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
+            value = symbol;
+        }
+        this.table.put(key, value);
+        return value;
+    }
+
+    /*
+     * call-seq:
+     *     Map.[](key) => value
+     *
+     * Accesses the element at the given key. Throws an exception if the key type is
+     * incorrect. Returns nil when the key is not present in the map.
+     */
+    @JRubyMethod(name = "[]")
+    public IRubyObject index(ThreadContext context, IRubyObject key) {
+        if (table.containsKey(key))
+            return this.table.get(key);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Map.==(other) => boolean
+     *
+     * Compares this map to another. Maps are equal if they have identical key sets,
+     * and for each key, the values in both maps compare equal. Elements are
+     * compared as per normal Ruby semantics, by calling their :== methods (or
+     * performing a more efficient comparison for primitive types).
+     *
+     * Maps with dissimilar key types or value types/typeclasses are never equal,
+     * even if value comparison (for example, between integers and floats) would
+     * have otherwise indicated that every element has equal value.
+     */
+    @JRubyMethod(name = "==")
+    public IRubyObject eq(ThreadContext context, IRubyObject _other) {
+        if (_other instanceof RubyHash)
+            return toHash(context).op_equal(context, _other);
+        RubyMap other = (RubyMap) _other;
+        if (this == other) return context.runtime.getTrue();
+        if (!typeCompatible(other) || this.table.size() != other.table.size())
+            return context.runtime.getFalse();
+        for (IRubyObject key : table.keySet()) {
+            if (! other.table.containsKey(key))
+                return context.runtime.getFalse();
+            if (! other.table.get(key).equals(table.get(key)))
+                return context.runtime.getFalse();
+        }
+        return context.runtime.getTrue();
+    }
+
+    /*
+     * call-seq:
+     *     Map.inspect => string
+     *
+     * Returns a string representing this map's elements. It will be formatted as
+     * "{key => value, key => value, ...}", with each key and value string
+     * representation computed by its own #inspect method.
+     */
+    @JRubyMethod
+    public IRubyObject inspect() {
+        return toHash(getRuntime().getCurrentContext()).inspect();
+    }
+
+    /*
+     * call-seq:
+     *     Map.hash => hash_value
+     *
+     * Returns a hash value based on this map's contents.
+     */
+    @JRubyMethod
+    public IRubyObject hash(ThreadContext context) {
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            for (IRubyObject key : table.keySet()) {
+                digest.update((byte) key.hashCode());
+                digest.update((byte) table.get(key).hashCode());
+            }
+            return context.runtime.newString(new ByteList(digest.digest()));
+        } catch (NoSuchAlgorithmException ignore) {
+            return context.runtime.newFixnum(System.identityHashCode(table));
+        }
+    }
+
+    /*
+     * call-seq:
+     *     Map.keys => [list_of_keys]
+     *
+     * Returns the list of keys contained in the map, in unspecified order.
+     */
+    @JRubyMethod
+    public IRubyObject keys(ThreadContext context) {
+        return RubyArray.newArray(context.runtime, table.keySet());
+    }
+
+    /*
+     * call-seq:
+     *     Map.values => [list_of_values]
+     *
+     * Returns the list of values contained in the map, in unspecified order.
+     */
+    @JRubyMethod
+    public IRubyObject values(ThreadContext context) {
+        return RubyArray.newArray(context.runtime, table.values());
+    }
+
+    /*
+     * call-seq:
+     *     Map.clear
+     *
+     * Removes all entries from the map.
+     */
+    @JRubyMethod
+    public IRubyObject clear(ThreadContext context) {
+        table.clear();
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Map.each(&block)
+     *
+     * Invokes &block on each |key, value| pair in the map, in unspecified order.
+     * Note that Map also includes Enumerable; map thus acts like a normal Ruby
+     * sequence.
+     */
+    @JRubyMethod
+    public IRubyObject each(ThreadContext context, Block block) {
+        for (IRubyObject key : table.keySet()) {
+            block.yieldSpecific(context, key, table.get(key));
+        }
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     Map.delete(key) => old_value
+     *
+     * Deletes the value at the given key, if any, returning either the old value or
+     * nil if none was present. Throws an exception if the key is of the wrong type.
+     */
+    @JRubyMethod
+    public IRubyObject delete(ThreadContext context, IRubyObject key) {
+        return table.remove(key);
+    }
+
+    /*
+     * call-seq:
+     *     Map.has_key?(key) => bool
+     *
+     * Returns true if the given key is present in the map. Throws an exception if
+     * the key has the wrong type.
+     */
+    @JRubyMethod(name = "has_key?")
+    public IRubyObject hasKey(ThreadContext context, IRubyObject key) {
+        return this.table.containsKey(key) ? context.runtime.getTrue() : context.runtime.getFalse();
+    }
+
+    /*
+     * call-seq:
+     *     Map.length
+     *
+     * Returns the number of entries (key-value pairs) in the map.
+     */
+    @JRubyMethod
+    public IRubyObject length(ThreadContext context) {
+        return context.runtime.newFixnum(this.table.size());
+    }
+
+    /*
+     * call-seq:
+     *     Map.dup => new_map
+     *
+     * Duplicates this map with a shallow copy. References to all non-primitive
+     * element objects (e.g., submessages) are shared.
+     */
+    @JRubyMethod
+    public IRubyObject dup(ThreadContext context) {
+        RubyMap newMap = newThisType(context);
+        for (Map.Entry<IRubyObject, IRubyObject> entry : table.entrySet()) {
+            newMap.table.put(entry.getKey(), entry.getValue());
+        }
+        return newMap;
+    }
+
+    @JRubyMethod(name = {"to_h", "to_hash"})
+    public RubyHash toHash(ThreadContext context) {
+        return RubyHash.newHash(context.runtime, table, context.runtime.getNil());
+    }
+
+    // Used by Google::Protobuf.deep_copy but not exposed directly.
+    protected IRubyObject deepCopy(ThreadContext context) {
+        RubyMap newMap = newThisType(context);
+        switch (valueType) {
+            case MESSAGE:
+                for (IRubyObject key : table.keySet()) {
+                    RubyMessage message = (RubyMessage) table.get(key);
+                    newMap.table.put(key.dup(), message.deepCopy(context));
+                }
+                break;
+            default:
+                for (IRubyObject key : table.keySet()) {
+                    newMap.table.put(key.dup(), table.get(key).dup());
+                }
+        }
+        return newMap;
+    }
+
+    protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor) {
+        List<DynamicMessage> list = new ArrayList<DynamicMessage>();
+        RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
+        Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef();
+        Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef();
+        for (IRubyObject key : table.keySet()) {
+            RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK);
+            mapMessage.setField(context, keyField, key);
+            mapMessage.setField(context, valueField, table.get(key));
+            list.add(mapMessage.build(context));
+        }
+        return list;
+    }
+
+    protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) {
+        if (hashmap instanceof RubyHash) {
+            ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() {
+                @Override
+                public void visit(IRubyObject key, IRubyObject val) {
+                    indexSet(context, key, val);
+                }
+            });
+        } else if (hashmap instanceof RubyMap) {
+            RubyMap other = (RubyMap) hashmap;
+            if (!typeCompatible(other)) {
+                throw context.runtime.newTypeError("Attempt to merge Map with mismatching types");
+            }
+        } else {
+            throw context.runtime.newTypeError("Unknown type merging into Map");
+        }
+        return this;
+    }
+
+    protected boolean typeCompatible(RubyMap other) {
+        return this.keyType == other.keyType &&
+                this.valueType == other.valueType &&
+                this.valueTypeClass == other.valueTypeClass;
+    }
+
+    private RubyMap newThisType(ThreadContext context) {
+        RubyMap newMap;
+        if (needTypeclass(valueType)) {
+            newMap = (RubyMap) metaClass.newInstance(context,
+                    Utils.fieldTypeToRuby(context, keyType),
+                    Utils.fieldTypeToRuby(context, valueType),
+                    valueTypeClass, Block.NULL_BLOCK);
+        } else {
+            newMap = (RubyMap) metaClass.newInstance(context,
+                    Utils.fieldTypeToRuby(context, keyType),
+                    Utils.fieldTypeToRuby(context, valueType),
+                    Block.NULL_BLOCK);
+        }
+        newMap.table = new HashMap<IRubyObject, IRubyObject>();
+        return newMap;
+    }
+
+    private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) {
+        switch(type) {
+            case MESSAGE:
+            case ENUM:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private Descriptors.FieldDescriptor.Type keyType;
+    private Descriptors.FieldDescriptor.Type valueType;
+    private IRubyObject valueTypeClass;
+    private Map<IRubyObject, IRubyObject> table;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
new file mode 100644
index 0000000..39213c4
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -0,0 +1,765 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.*;
+import org.jruby.*;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.ByteList;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RubyMessage extends RubyObject {
+    public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor) {
+        super(ruby, klazz);
+        this.descriptor = descriptor;
+    }
+
+    /*
+     * call-seq:
+     *     Message.new(kwargs) => new_message
+     *
+     * Creates a new instance of the given message class. Keyword arguments may be
+     * provided with keywords corresponding to field names.
+     *
+     * Note that no literal Message class exists. Only concrete classes per message
+     * type exist, as provided by the #msgclass method on Descriptors after they
+     * have been added to a pool. The method definitions described here on the
+     * Message class are provided on each concrete message class.
+     */
+    @JRubyMethod(optional = 1)
+    public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) {
+        final Ruby runtime = context.runtime;
+        this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField");
+        this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map");
+        this.builder = DynamicMessage.newBuilder(this.descriptor);
+        this.repeatedFields = new HashMap<Descriptors.FieldDescriptor, RubyRepeatedField>();
+        this.maps = new HashMap<Descriptors.FieldDescriptor, RubyMap>();
+        this.fields = new HashMap<Descriptors.FieldDescriptor, IRubyObject>();
+        this.oneofCases = new HashMap<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor>();
+        if (args.length == 1) {
+            if (!(args[0] instanceof RubyHash)) {
+                throw runtime.newArgumentError("expected Hash arguments.");
+            }
+            RubyHash hash = args[0].convertToHash();
+            hash.visitAll(new RubyHash.Visitor() {
+                @Override
+                public void visit(IRubyObject key, IRubyObject value) {
+                    if (!(key instanceof RubySymbol))
+                        throw runtime.newTypeError("Expected symbols as hash keys in initialization map.");
+                    final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key);
+
+                    if (Utils.isMapEntry(fieldDescriptor)) {
+                        if (!(value instanceof RubyHash))
+                            throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" +  key.asJavaString() + "'.");
+
+                        final RubyMap map = newMapForField(context, fieldDescriptor);
+                        map.mergeIntoSelf(context, value);
+                        maps.put(fieldDescriptor, map);
+                    } else if (fieldDescriptor.isRepeated()) {
+                        if (!(value instanceof RubyArray))
+                            throw runtime.newArgumentError("Expected array as initializer value for repeated field '" +  key.asJavaString() + "'.");
+                        RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, value);
+                        addRepeatedField(fieldDescriptor, repeatedField);
+                    } else {
+                        Descriptors.OneofDescriptor oneof = fieldDescriptor.getContainingOneof();
+                        if (oneof != null) {
+                            oneofCases.put(oneof, fieldDescriptor);
+                        }
+                        fields.put(fieldDescriptor, value);
+                    }
+
+                }
+            });
+        }
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     Message.[]=(index, value)
+     *
+     * Sets a field's value by field name. The provided field name should be a
+     * string.
+     */
+    @JRubyMethod(name = "[]=")
+    public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyObject value) {
+        Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
+        return setField(context, fieldDescriptor, value);
+    }
+
+    /*
+     * call-seq:
+     *     Message.[](index) => value
+     *
+     * Accesses a field's value by field name. The provided field name should be a
+     * string.
+     */
+    @JRubyMethod(name = "[]")
+    public IRubyObject index(ThreadContext context, IRubyObject fieldName) {
+        Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
+        return getField(context, fieldDescriptor);
+    }
+
+    /*
+     * call-seq:
+     *     Message.inspect => string
+     *
+     * Returns a human-readable string representing this message. It will be
+     * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
+     * field's value is represented according to its own #inspect method.
+     */
+    @JRubyMethod
+    public IRubyObject inspect() {
+        String cname = metaClass.getName();
+        StringBuilder sb = new StringBuilder("<");
+        sb.append(cname);
+        sb.append(": ");
+        sb.append(this.layoutInspect());
+        sb.append(">");
+
+        return getRuntime().newString(sb.toString());
+    }
+
+    /*
+     * call-seq:
+     *     Message.hash => hash_value
+     *
+     * Returns a hash value that represents this message's field values.
+     */
+    @JRubyMethod
+    public IRubyObject hash(ThreadContext context) {
+        int hashCode = System.identityHashCode(this);
+        return context.runtime.newFixnum(hashCode);
+    }
+
+    /*
+     * call-seq:
+     *     Message.==(other) => boolean
+     *
+     * Performs a deep comparison of this message with another. Messages are equal
+     * if they have the same type and if each field is equal according to the :==
+     * method's semantics (a more efficient comparison may actually be done if the
+     * field is of a primitive type).
+     */
+    @JRubyMethod(name = "==")
+    public IRubyObject eq(ThreadContext context, IRubyObject other) {
+        Ruby runtime = context.runtime;
+        if (!(other instanceof RubyMessage))
+            return runtime.getFalse();
+        RubyMessage message = (RubyMessage) other;
+        if (descriptor != message.descriptor) {
+            return runtime.getFalse();
+        }
+
+        for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
+            IRubyObject thisVal = getField(context, fdef);
+            IRubyObject thatVal = message.getField(context, fdef);
+            IRubyObject ret = thisVal.callMethod(context, "==", thatVal);
+            if (!ret.isTrue()) {
+                return runtime.getFalse();
+            }
+        }
+        return runtime.getTrue();
+    }
+
+    /*
+     * call-seq:
+     *     Message.method_missing(*args)
+     *
+     * Provides accessors and setters for message fields according to their field
+     * names. For any field whose name does not conflict with a built-in method, an
+     * accessor is provided with the same name as the field, and a setter is
+     * provided with the name of the field plus the '=' suffix. Thus, given a
+     * message instance 'msg' with field 'foo', the following code is valid:
+     *
+     *     msg.foo = 42
+     *     puts msg.foo
+     */
+    @JRubyMethod(name = "method_missing", rest = true)
+    public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) {
+        if (args.length == 1) {
+            RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
+            IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]);
+            if (oneofDescriptor.isNil()) {
+                if (!hasField(args[0])) {
+                    return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK);
+                }
+                return index(context, args[0]);
+            }
+            RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor;
+            Descriptors.FieldDescriptor fieldDescriptor =
+                    oneofCases.get(rubyOneofDescriptor.getOneofDescriptor());
+            if (fieldDescriptor == null)
+                return context.runtime.getNil();
+
+            return context.runtime.newSymbol(fieldDescriptor.getName());
+        } else {
+            // fieldName is RubySymbol
+            RubyString field = args[0].asString();
+            RubyString equalSign = context.runtime.newString(Utils.EQUAL_SIGN);
+            if (field.end_with_p(context, equalSign).isTrue()) {
+                field.chomp_bang(context, equalSign);
+            }
+
+            if (!hasField(field)) {
+                return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK);
+            }
+            return indexSet(context, field, args[1]);
+        }
+    }
+
+    /**
+     * call-seq:
+     * Message.dup => new_message
+     * Performs a shallow copy of this message and returns the new copy.
+     */
+    @JRubyMethod
+    public IRubyObject dup(ThreadContext context) {
+        RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
+        IRubyObject value;
+        for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) {
+            if (fieldDescriptor.isRepeated()) {
+                dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor));
+            } else if (fields.containsKey(fieldDescriptor)) {
+                dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor));
+            } else if (this.builder.hasField(fieldDescriptor)) {
+                dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor)));
+            }
+        }
+        for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
+            dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor));
+        }
+        return dup;
+    }
+
+    /*
+     * call-seq:
+     *     Message.descriptor => descriptor
+     *
+     * Class method that returns the Descriptor instance corresponding to this
+     * message class's type.
+     */
+    @JRubyMethod(name = "descriptor", meta = true)
+    public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) {
+        return ((RubyClass) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR);
+    }
+
+    /*
+     * call-seq:
+     *     MessageClass.encode(msg) => bytes
+     *
+     * Encodes the given message object to its serialized form in protocol buffers
+     * wire format.
+     */
+    @JRubyMethod(meta = true)
+    public static IRubyObject encode(ThreadContext context, IRubyObject recv, IRubyObject value) {
+        RubyMessage message = (RubyMessage) value;
+        return context.runtime.newString(new ByteList(message.build(context).toByteArray()));
+    }
+
+    /*
+     * call-seq:
+     *     MessageClass.decode(data) => message
+     *
+     * Decodes the given data (as a string containing bytes in protocol buffers wire
+     * format) under the interpretration given by this message class's definition
+     * and returns a message object with the corresponding field values.
+     */
+    @JRubyMethod(meta = true)
+    public static IRubyObject decode(ThreadContext context, IRubyObject recv, IRubyObject data) {
+        byte[] bin = data.convertToString().getBytes();
+        RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK);
+        try {
+            ret.builder.mergeFrom(bin);
+        } catch (InvalidProtocolBufferException e) {
+            throw context.runtime.newRuntimeError(e.getMessage());
+        }
+        return ret;
+    }
+
+    /*
+     * call-seq:
+     *     MessageClass.encode_json(msg) => json_string
+     *
+     * Encodes the given message object into its serialized JSON representation.
+     */
+    @JRubyMethod(name = "encode_json", meta = true)
+    public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject msgRb) {
+        RubyMessage message = (RubyMessage) msgRb;
+        return Helpers.invoke(context, message.toHash(context), "to_json");
+    }
+
+    /*
+     * call-seq:
+     *     MessageClass.decode_json(data) => message
+     *
+     * Decodes the given data (as a string containing bytes in protocol buffers wire
+     * format) under the interpretration given by this message class's definition
+     * and returns a message object with the corresponding field values.
+     */
+    @JRubyMethod(name = "decode_json", meta = true)
+    public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject json) {
+        Ruby runtime = context.runtime;
+        RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK);
+        RubyModule jsonModule = runtime.getClassFromPath("JSON");
+        RubyHash opts = RubyHash.newHash(runtime);
+        opts.fastASet(runtime.newSymbol("symbolize_names"), runtime.getTrue());
+        IRubyObject[] args = new IRubyObject[] { Helpers.invoke(context, jsonModule, "parse", json, opts) };
+        ret.initialize(context, args);
+        return ret;
+    }
+
+    @JRubyMethod(name = {"to_h", "to_hash"})
+    public IRubyObject toHash(ThreadContext context) {
+        Ruby runtime = context.runtime;
+        RubyHash ret = RubyHash.newHash(runtime);
+        for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
+            IRubyObject value = getField(context, fdef);
+            if (!value.isNil()) {
+                if (value.respondsTo("to_h")) {
+                    value = Helpers.invoke(context, value, "to_h");
+                } else if (value.respondsTo("to_a")) {
+                    value = Helpers.invoke(context, value, "to_a");
+                }
+            }
+            ret.fastASet(runtime.newSymbol(fdef.getName()), value);
+        }
+        return ret;
+    }
+
+    protected DynamicMessage build(ThreadContext context) {
+        return build(context, 0);
+    }
+
+    protected DynamicMessage build(ThreadContext context, int depth) {
+        if (depth > SINK_MAXIMUM_NESTING) {
+            throw context.runtime.newRuntimeError("Maximum recursion depth exceeded during encoding.");
+        }
+        for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
+            this.builder.clearField(fieldDescriptor);
+            RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+            for (DynamicMessage kv : maps.get(fieldDescriptor).build(context, mapDescriptor)) {
+                this.builder.addRepeatedField(fieldDescriptor, kv);
+            }
+        }
+        for (Descriptors.FieldDescriptor fieldDescriptor : repeatedFields.keySet()) {
+            RubyRepeatedField repeatedField = repeatedFields.get(fieldDescriptor);
+            this.builder.clearField(fieldDescriptor);
+            for (int i = 0; i < repeatedField.size(); i++) {
+                Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth);
+                this.builder.addRepeatedField(fieldDescriptor, item);
+            }
+        }
+        for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) {
+            IRubyObject value = fields.get(fieldDescriptor);
+            this.builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth));
+        }
+        return this.builder.build();
+    }
+
+    protected Descriptors.Descriptor getDescriptor() {
+        return this.descriptor;
+    }
+
+    // Internal use only, called by Google::Protobuf.deep_copy
+    protected IRubyObject deepCopy(ThreadContext context) {
+        RubyMessage copy = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
+        for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
+            if (fdef.isRepeated()) {
+                copy.addRepeatedField(fdef, this.getRepeatedField(context, fdef).deepCopy(context));
+            } else if (fields.containsKey(fdef)) {
+                copy.fields.put(fdef, fields.get(fdef));
+            } else if (this.builder.hasField(fdef)) {
+                copy.fields.put(fdef, wrapField(context, fdef, this.builder.getField(fdef)));
+            }
+        }
+        return copy;
+    }
+
+    private RubyRepeatedField getRepeatedField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+        if (this.repeatedFields.containsKey(fieldDescriptor)) {
+            return this.repeatedFields.get(fieldDescriptor);
+        }
+        int count = this.builder.getRepeatedFieldCount(fieldDescriptor);
+        RubyRepeatedField ret = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
+        for (int i = 0; i < count; i++) {
+            ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i)));
+        }
+        addRepeatedField(fieldDescriptor, ret);
+        return ret;
+    }
+
+    private void addRepeatedField(Descriptors.FieldDescriptor fieldDescriptor, RubyRepeatedField repeatedField) {
+        this.repeatedFields.put(fieldDescriptor, repeatedField);
+    }
+
+    private IRubyObject buildFrom(ThreadContext context, DynamicMessage dynamicMessage) {
+        this.builder.mergeFrom(dynamicMessage);
+        return this;
+    }
+
+    private Descriptors.FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) {
+        String nameStr = fieldName.asJavaString();
+        Descriptors.FieldDescriptor ret = this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr));
+        if (ret == null)
+            throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found");
+        return ret;
+    }
+
+    private boolean hasField(IRubyObject fieldName) {
+        String nameStr = fieldName.asJavaString();
+        return this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)) != null;
+    }
+
+    private void checkRepeatedFieldType(ThreadContext context, IRubyObject value,
+                                        Descriptors.FieldDescriptor fieldDescriptor) {
+        Ruby runtime = context.runtime;
+        if (!(value instanceof RubyRepeatedField)) {
+            throw runtime.newTypeError("Expected repeated field array");
+        }
+    }
+
+    // convert a ruby object to protobuf type, with type check
+    private Object convert(ThreadContext context,
+                           Descriptors.FieldDescriptor fieldDescriptor,
+                           IRubyObject value, int depth) {
+        Ruby runtime = context.runtime;
+        Object val = null;
+        switch (fieldDescriptor.getType()) {
+            case INT32:
+            case INT64:
+            case UINT32:
+            case UINT64:
+                if (!Utils.isRubyNum(value)) {
+                    throw runtime.newTypeError("Expected number type for integral field.");
+                }
+                Utils.checkIntTypePrecision(context, fieldDescriptor.getType(), value);
+                switch (fieldDescriptor.getType()) {
+                    case INT32:
+                        val = RubyNumeric.num2int(value);
+                        break;
+                    case INT64:
+                        val = RubyNumeric.num2long(value);
+                        break;
+                    case UINT32:
+                        val = Utils.num2uint(value);
+                        break;
+                    case UINT64:
+                        val = Utils.num2ulong(context.runtime, value);
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case FLOAT:
+                if (!Utils.isRubyNum(value))
+                    throw runtime.newTypeError("Expected number type for float field.");
+                val = (float) RubyNumeric.num2dbl(value);
+                break;
+            case DOUBLE:
+                if (!Utils.isRubyNum(value))
+                    throw runtime.newTypeError("Expected number type for double field.");
+                val = RubyNumeric.num2dbl(value);
+                break;
+            case BOOL:
+                if (!(value instanceof RubyBoolean))
+                    throw runtime.newTypeError("Invalid argument for boolean field.");
+                val = value.isTrue();
+                break;
+            case BYTES:
+            case STRING:
+                Utils.validateStringEncoding(context.runtime, fieldDescriptor.getType(), value);
+                RubyString str = (RubyString) value;
+                switch (fieldDescriptor.getType()) {
+                    case BYTES:
+                        val = ByteString.copyFrom(str.getBytes());
+                        break;
+                    case STRING:
+                        val = str.asJavaString();
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case MESSAGE:
+                RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+                if (!value.getMetaClass().equals(typeClass))
+                    throw runtime.newTypeError(value, "Invalid type to assign to submessage field.");
+                val = ((RubyMessage) value).build(context, depth + 1);
+                break;
+            case ENUM:
+                Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
+
+                if (Utils.isRubyNum(value)) {
+                    val = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+                } else if (value instanceof RubySymbol) {
+                    val = enumDescriptor.findValueByName(value.asJavaString());
+                } else {
+                    throw runtime.newTypeError("Expected number or symbol type for enum field.");
+                }
+                if (val == null) {
+                    throw runtime.newRangeError("Enum value " + value + " is not found.");
+                }
+                break;
+            default:
+                break;
+        }
+        return val;
+    }
+
+    private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, Object value) {
+        if (value == null) {
+            return context.runtime.getNil();
+        }
+        Ruby runtime = context.runtime;
+        switch (fieldDescriptor.getType()) {
+            case INT32:
+            case INT64:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTES:
+            case STRING:
+                return Utils.wrapPrimaryValue(context, fieldDescriptor.getType(), value);
+            case MESSAGE:
+                RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+                RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK);
+                return msg.buildFrom(context, (DynamicMessage) value);
+            case ENUM:
+                Descriptors.EnumValueDescriptor enumValueDescriptor = (Descriptors.EnumValueDescriptor) value;
+                if (enumValueDescriptor.getIndex() == -1) { // UNKNOWN ENUM VALUE
+                    return runtime.newFixnum(enumValueDescriptor.getNumber());
+                }
+                return runtime.newSymbol(enumValueDescriptor.getName());
+            default:
+                return runtime.newString(value.toString());
+        }
+    }
+
+    private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context,
+                                                              Descriptors.FieldDescriptor fieldDescriptor) {
+        IRubyObject typeClass = context.runtime.getNilClass();
+
+        IRubyObject descriptor = getDescriptorForField(context, fieldDescriptor);
+        Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType();
+        if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+            typeClass = ((RubyDescriptor) descriptor).msgclass(context);
+
+        } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+            typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context);
+        }
+        return new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass);
+    }
+
+    protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+        Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+        if (oneofDescriptor != null) {
+            if (oneofCases.containsKey(oneofDescriptor)) {
+                if (oneofCases.get(oneofDescriptor) != fieldDescriptor)
+                    return context.runtime.getNil();
+                return fields.get(fieldDescriptor);
+            } else {
+                Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor);
+                if (oneofCase != fieldDescriptor) return context.runtime.getNil();
+                IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase));
+                fields.put(fieldDescriptor, value);
+                return value;
+            }
+        }
+
+        if (Utils.isMapEntry(fieldDescriptor)) {
+            RubyMap map = maps.get(fieldDescriptor);
+            if (map == null) {
+                map = newMapForField(context, fieldDescriptor);
+                int mapSize = this.builder.getRepeatedFieldCount(fieldDescriptor);
+                Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+                Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+                RubyDescriptor kvDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+                RubyClass kvClass = (RubyClass) kvDescriptor.msgclass(context);
+                for (int i = 0; i < mapSize; i++) {
+                    RubyMessage kvMessage = (RubyMessage) kvClass.newInstance(context, Block.NULL_BLOCK);
+                    DynamicMessage message = (DynamicMessage) this.builder.getRepeatedField(fieldDescriptor, i);
+                    kvMessage.buildFrom(context, message);
+                    map.indexSet(context, kvMessage.getField(context, keyField), kvMessage.getField(context, valueField));
+                }
+                maps.put(fieldDescriptor, map);
+            }
+            return map;
+        }
+        if (fieldDescriptor.isRepeated()) {
+            return getRepeatedField(context, fieldDescriptor);
+        }
+        if (fieldDescriptor.getType() != Descriptors.FieldDescriptor.Type.MESSAGE ||
+                this.builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) {
+            if (fields.containsKey(fieldDescriptor)) {
+                return fields.get(fieldDescriptor);
+            } else {
+                IRubyObject value = wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor));
+                if (this.builder.hasField(fieldDescriptor)) {
+                    fields.put(fieldDescriptor, value);
+                }
+                return value;
+            }
+        }
+        return context.runtime.getNil();
+    }
+
+    protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+        if (Utils.isMapEntry(fieldDescriptor)) {
+            if (!(value instanceof RubyMap)) {
+                throw context.runtime.newTypeError("Expected Map instance");
+            }
+            RubyMap thisMap = (RubyMap) getField(context, fieldDescriptor);
+            thisMap.mergeIntoSelf(context, value);
+        } else if (fieldDescriptor.isRepeated()) {
+            checkRepeatedFieldType(context, value, fieldDescriptor);
+            if (value instanceof RubyRepeatedField) {
+                addRepeatedField(fieldDescriptor, (RubyRepeatedField) value);
+            } else {
+                RubyArray ary = value.convertToArray();
+                RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, ary);
+                addRepeatedField(fieldDescriptor, repeatedField);
+            }
+        } else {
+            Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+            if (oneofDescriptor != null) {
+                Descriptors.FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor);
+                if (oneofCase != null && oneofCase != fieldDescriptor) {
+                    fields.remove(oneofCase);
+                }
+                if (value.isNil()) {
+                    oneofCases.remove(oneofDescriptor);
+                    fields.remove(fieldDescriptor);
+                } else {
+                    oneofCases.put(oneofDescriptor, fieldDescriptor);
+                    fields.put(fieldDescriptor, value);
+                }
+            } else {
+                Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
+                IRubyObject typeClass = context.runtime.getObject();
+                boolean addValue = true;
+                if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
+                    typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+                    if (value.isNil()){
+                        addValue = false;
+                    }
+                } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+                    typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
+                    Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
+                    if (Utils.isRubyNum(value)) {
+                        Descriptors.EnumValueDescriptor val =
+                                enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+                        if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName());
+                    }
+                }
+                if (addValue) {
+                    Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+                    this.fields.put(fieldDescriptor, value);
+                } else {
+                    this.fields.remove(fieldDescriptor);
+                }
+            }
+        }
+        return context.runtime.getNil();
+    }
+
+    private String layoutInspect() {
+        ThreadContext context = getRuntime().getCurrentContext();
+        StringBuilder sb = new StringBuilder();
+        for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
+            sb.append(Utils.unescapeIdentifier(fdef.getName()));
+            sb.append(": ");
+            sb.append(getField(context, fdef).inspect());
+            sb.append(", ");
+        }
+        return sb.substring(0, sb.length() - 2);
+    }
+
+    private IRubyObject getDescriptorForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+        RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
+        return thisRbDescriptor.lookup(fieldDescriptor.getName()).getSubType(context);
+    }
+
+    private RubyRepeatedField rubyToRepeatedField(ThreadContext context,
+                                                  Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+        RubyArray arr = value.convertToArray();
+        RubyRepeatedField repeatedField = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
+        for (int i = 0; i < arr.size(); i++) {
+            repeatedField.push(context, arr.eltInternal(i));
+        }
+        return repeatedField;
+    }
+
+    private RubyMap newMapForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+        RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+        Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+        Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+        IRubyObject keyType = RubySymbol.newSymbol(context.runtime, keyField.getType().name());
+        IRubyObject valueType = RubySymbol.newSymbol(context.runtime, valueField.getType().name());
+        if (valueField.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+            RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context,
+                    context.runtime.newString("value"));
+            RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubType(context);
+            return (RubyMap) cMap.newInstance(context, keyType, valueType,
+                    rubyDescriptor.msgclass(context), Block.NULL_BLOCK);
+        } else {
+            return (RubyMap) cMap.newInstance(context, keyType, valueType, Block.NULL_BLOCK);
+        }
+    }
+
+    private Descriptors.FieldDescriptor getOneofCase(Descriptors.OneofDescriptor oneof) {
+        if (oneofCases.containsKey(oneof)) {
+            return oneofCases.get(oneof);
+        }
+        return builder.getOneofFieldDescriptor(oneof);
+    }
+
+    private Descriptors.Descriptor descriptor;
+    private DynamicMessage.Builder builder;
+    private RubyClass cRepeatedField;
+    private RubyClass cMap;
+    private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields;
+    private Map<Descriptors.FieldDescriptor, RubyMap> maps;
+    private Map<Descriptors.FieldDescriptor, IRubyObject> fields;
+    private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofCases;
+
+    private static final int SINK_MAXIMUM_NESTING = 64;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
new file mode 100644
index 0000000..a619b80
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
@@ -0,0 +1,217 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Binding;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "MessageBuilderContext")
+public class RubyMessageBuilderContext extends RubyObject {
+    public static void createRubyMessageBuilderContext(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cMessageBuilderContext = protobuf.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyMessageBuilderContext(runtime, klazz);
+            }
+        });
+        cMessageBuilderContext.defineAnnotatedMethods(RubyMessageBuilderContext.class);
+    }
+
+    public RubyMessageBuilderContext(Ruby ruby, RubyClass klazz) {
+        super(ruby, klazz);
+    }
+
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context, IRubyObject descriptor, IRubyObject rubyBuilder) {
+        this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+        this.cDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Descriptor");
+        this.cOneofDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::OneofDescriptor");
+        this.cOneofBuilderContext = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext");
+        this.descriptor = (RubyDescriptor) descriptor;
+        this.builder = (RubyBuilder) rubyBuilder;
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     MessageBuilderContext.optional(name, type, number, type_class = nil)
+     *
+     * Defines a new optional field on this message type with the given type, tag
+     * number, and type class (for message and enum fields). The type must be a Ruby
+     * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+     * string, if present (as accepted by FieldDescriptor#submsg_name=).
+     */
+    @JRubyMethod(required = 3, optional = 1)
+    public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
+        Ruby runtime = context.runtime;
+        IRubyObject typeClass = runtime.getNil();
+        if (args.length > 3) typeClass = args[3];
+        msgdefAddField(context, "optional", args[0], args[1], args[2], typeClass);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     MessageBuilderContext.required(name, type, number, type_class = nil)
+     *
+     * Defines a new required field on this message type with the given type, tag
+     * number, and type class (for message and enum fields). The type must be a Ruby
+     * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+     * string, if present (as accepted by FieldDescriptor#submsg_name=).
+     *
+     * Proto3 does not have required fields, but this method exists for
+     * completeness. Any attempt to add a message type with required fields to a
+     * pool will currently result in an error.
+     */
+    @JRubyMethod(required = 3, optional = 1)
+    public IRubyObject required(ThreadContext context, IRubyObject[] args) {
+        IRubyObject typeClass = context.runtime.getNil();
+        if (args.length > 3) typeClass = args[3];
+        msgdefAddField(context, "required", args[0], args[1], args[2], typeClass);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     MessageBuilderContext.repeated(name, type, number, type_class = nil)
+     *
+     * Defines a new repeated field on this message type with the given type, tag
+     * number, and type class (for message and enum fields). The type must be a Ruby
+     * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+     * string, if present (as accepted by FieldDescriptor#submsg_name=).
+     */
+    @JRubyMethod(required = 3, optional = 1)
+    public IRubyObject repeated(ThreadContext context, IRubyObject[] args) {
+        IRubyObject typeClass = context.runtime.getNil();
+        if (args.length > 3) typeClass = args[3];
+        msgdefAddField(context, "repeated", args[0], args[1], args[2], typeClass);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     MessageBuilderContext.map(name, key_type, value_type, number,
+     *                               value_type_class = nil)
+     *
+     * Defines a new map field on this message type with the given key and value
+     * types, tag number, and type class (for message and enum value types). The key
+     * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type
+     * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the
+     * type_class must be a string, if present (as accepted by
+     * FieldDescriptor#submsg_name=).
+     */
+    @JRubyMethod(required = 4, optional = 1)
+    public IRubyObject map(ThreadContext context, IRubyObject[] args) {
+        Ruby runtime = context.runtime;
+        IRubyObject name = args[0];
+        IRubyObject keyType = args[1];
+        IRubyObject valueType = args[2];
+        IRubyObject number = args[3];
+        IRubyObject typeClass = args.length > 4 ? args[4] : context.runtime.getNil();
+
+        // Validate the key type. We can't accept enums, messages, or floats/doubles
+        // as map keys. (We exclude these explicitly, and the field-descriptor setter
+        // below then ensures that the type is one of the remaining valid options.)
+        if (keyType.equals(RubySymbol.newSymbol(runtime, "float")) ||
+                keyType.equals(RubySymbol.newSymbol(runtime, "double")) ||
+                keyType.equals(RubySymbol.newSymbol(runtime, "enum")) ||
+                keyType.equals(RubySymbol.newSymbol(runtime, "message")))
+            throw runtime.newArgumentError("Cannot add a map field with a float, double, enum, or message type.");
+
+        // Create a new message descriptor for the map entry message, and create a
+        // repeated submessage field here with that type.
+        RubyDescriptor mapentryDesc = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
+        IRubyObject mapentryDescName = RubySymbol.newSymbol(runtime, name).id2name(context);
+        mapentryDesc.setName(context, mapentryDescName);
+        mapentryDesc.setMapEntry(true);
+
+        //optional <type> key = 1;
+        RubyFieldDescriptor keyField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+        keyField.setName(context, runtime.newString("key"));
+        keyField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
+        keyField.setNumber(context, runtime.newFixnum(1));
+        keyField.setType(context, keyType);
+        mapentryDesc.addField(context, keyField);
+
+        //optional <type> value = 2;
+        RubyFieldDescriptor valueField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+        valueField.setName(context, runtime.newString("value"));
+        valueField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
+        valueField.setNumber(context, runtime.newFixnum(2));
+        valueField.setType(context, valueType);
+        if (! typeClass.isNil()) valueField.setSubmsgName(context, typeClass);
+        mapentryDesc.addField(context, valueField);
+
+        // Add the map-entry message type to the current builder, and use the type to
+        // create the map field itself.
+        this.builder.pendingList.add(mapentryDesc);
+
+        msgdefAddField(context, "repeated", name, runtime.newSymbol("message"), number, mapentryDescName);
+        return runtime.getNil();
+    }
+
+    @JRubyMethod
+    public IRubyObject oneof(ThreadContext context, IRubyObject name, Block block) {
+        RubyOneofDescriptor oneofdef = (RubyOneofDescriptor)
+                cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
+        RubyOneofBuilderContext ctx = (RubyOneofBuilderContext)
+                cOneofBuilderContext.newInstance(context, oneofdef, Block.NULL_BLOCK);
+        oneofdef.setName(context, name);
+        Binding binding = block.getBinding();
+        binding.setSelf(ctx);
+        block.yieldSpecific(context);
+        descriptor.addOneof(context, oneofdef);
+        return context.runtime.getNil();
+    }
+
+    private void msgdefAddField(ThreadContext context, String label, IRubyObject name,
+                                IRubyObject type, IRubyObject number, IRubyObject typeClass) {
+        descriptor.addField(context,
+                Utils.msgdefCreateField(context, label, name, type, number, typeClass, cFieldDescriptor));
+    }
+
+    private RubyDescriptor descriptor;
+    private RubyBuilder builder;
+    private RubyClass cFieldDescriptor;
+    private RubyClass cOneofDescriptor;
+    private RubyClass cOneofBuilderContext;
+    private RubyClass cDescriptor;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
new file mode 100644
index 0000000..c9b99e0
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
@@ -0,0 +1,84 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "OneofBuilderContext")
+public class RubyOneofBuilderContext extends RubyObject {
+    public static void createRubyOneofBuilderContext(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyModule internal = protobuf.defineModuleUnder("Internal");
+        RubyClass cRubyOneofBuidlerContext = internal.defineClassUnder("OneofBuilderContext", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+                return new RubyOneofBuilderContext(ruby, rubyClass);
+            }
+        });
+        cRubyOneofBuidlerContext.defineAnnotatedMethods(RubyOneofBuilderContext.class);
+    }
+
+    public RubyOneofBuilderContext(Ruby ruby, RubyClass rubyClass) {
+        super(ruby, rubyClass);
+    }
+
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context, IRubyObject oneofdef) {
+        this.descriptor = (RubyOneofDescriptor) oneofdef;
+        this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+        return this;
+    }
+
+    @JRubyMethod(required = 3, optional = 1)
+    public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
+        IRubyObject name = args[0];
+        IRubyObject type = args[1];
+        IRubyObject number = args[2];
+        IRubyObject typeClass = args.length > 3 ? args[3] : context.runtime.getNil();
+        RubyFieldDescriptor fieldDescriptor = Utils.msgdefCreateField(context, "optional",
+                name, type, number, typeClass, cFieldDescriptor);
+        descriptor.addField(context, fieldDescriptor);
+        return this;
+    }
+
+    private RubyOneofDescriptor descriptor;
+    private RubyClass cFieldDescriptor;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
new file mode 100644
index 0000000..cc4ab66
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
@@ -0,0 +1,124 @@
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.*;
+
+@JRubyClass(name = "OneofDescriptor", include = "Enumerable")
+public class RubyOneofDescriptor extends RubyObject {
+
+    public static void createRubyOneofDescriptor(Ruby runtime) {
+        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cRubyOneofDescriptor = protobuf.defineClassUnder("OneofDescriptor", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+                return new RubyOneofDescriptor(ruby, rubyClass);
+            }
+        });
+        cRubyOneofDescriptor.defineAnnotatedMethods(RubyOneofDescriptor.class);
+        cRubyOneofDescriptor.includeModule(runtime.getEnumerable());
+    }
+
+    public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) {
+        super(ruby, rubyClass);
+    }
+
+    @JRubyMethod
+    public IRubyObject initialize(ThreadContext context) {
+        builder = DescriptorProtos.OneofDescriptorProto.newBuilder();
+        fields = new ArrayList<RubyFieldDescriptor>();
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     OneofDescriptor.name => name
+     *
+     * Returns the name of this oneof.
+     */
+    @JRubyMethod(name = "name")
+    public IRubyObject getName(ThreadContext context) {
+        return name;
+    }
+
+    /*
+     * call-seq:
+     *     OneofDescriptor.name = name
+     *
+     * Sets a new name for this oneof. The oneof must not have been added to a
+     * message descriptor yet.
+     */
+    @JRubyMethod(name = "name=")
+    public IRubyObject setName(ThreadContext context, IRubyObject name) {
+        this.name = context.runtime.newString(name.asJavaString());
+        this.builder.setName(name.asJavaString());
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     OneofDescriptor.add_field(field) => nil
+     *
+     * Adds a field to this oneof. The field may have been added to this oneof in
+     * the past, or the message to which this oneof belongs (if any), but may not
+     * have already been added to any other oneof or message. Otherwise, an
+     * exception is raised.
+     *
+     * All fields added to the oneof via this method will be automatically added to
+     * the message to which this oneof belongs, if it belongs to one currently, or
+     * else will be added to any message to which the oneof is later added at the
+     * time that it is added.
+     */
+    @JRubyMethod(name = "add_field")
+    public IRubyObject addField(ThreadContext context, IRubyObject obj) {
+        RubyFieldDescriptor fieldDescriptor = (RubyFieldDescriptor) obj;
+        fieldDescriptor.setOneofName(this.name);
+        fields.add(fieldDescriptor);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     OneofDescriptor.each(&block) => nil
+     *
+     * Iterates through fields in this oneof, yielding to the block on each one.
+     */
+    @JRubyMethod
+    public IRubyObject each(ThreadContext context, Block block) {
+        for (RubyFieldDescriptor field : fields) {
+            block.yieldSpecific(context, field);
+        }
+        return context.runtime.getNil();
+    }
+
+    public DescriptorProtos.OneofDescriptorProto build(int index) {
+        for (RubyFieldDescriptor field: fields) {
+            field.setOneofIndex(index);
+        }
+        return this.builder.build();
+    }
+
+    protected Collection<RubyFieldDescriptor> getFields() {
+        return fields;
+    }
+
+    protected Descriptors.OneofDescriptor getOneofDescriptor() {
+        RubyFieldDescriptor fieldDescriptor = fields.get(0);
+        return fieldDescriptor.getFieldDef().getContainingOneof();
+    }
+
+    private IRubyObject name;
+    private DescriptorProtos.OneofDescriptorProto.Builder builder;
+    private List<RubyFieldDescriptor> fields;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
new file mode 100644
index 0000000..2cf210d
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
@@ -0,0 +1,68 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyModule;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.anno.JRubyModule;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyModule(name = "Protobuf")
+public class RubyProtobuf {
+
+    public static void createProtobuf(Ruby runtime) {
+        RubyModule mGoogle = runtime.getModule("Google");
+        RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf");
+        mProtobuf.defineAnnotatedMethods(RubyProtobuf.class);
+    }
+
+    /*
+     * call-seq:
+     *     Google::Protobuf.deep_copy(obj) => copy_of_obj
+     *
+     * Performs a deep copy of either a RepeatedField instance or a message object,
+     * recursively copying its members.
+     */
+    @JRubyMethod(name = "deep_copy", meta = true)
+    public static IRubyObject deepCopy(ThreadContext context, IRubyObject self, IRubyObject message) {
+        if (message instanceof RubyMessage) {
+            return ((RubyMessage) message).deepCopy(context);
+        } else if (message instanceof RubyRepeatedField) {
+            return ((RubyRepeatedField) message).deepCopy(context);
+        } else {
+            return ((RubyMap) message).deepCopy(context);
+        }
+    }
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
new file mode 100644
index 0000000..946f9e7
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -0,0 +1,409 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import java.util.Arrays;
+
+@JRubyClass(name = "RepeatedClass", include = "Enumerable")
+public class RubyRepeatedField extends RubyObject {
+    public static void createRubyRepeatedField(Ruby runtime) {
+        RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+        RubyClass cRepeatedField = mProtobuf.defineClassUnder("RepeatedField", runtime.getObject(),
+                new ObjectAllocator() {
+                    @Override
+                    public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                        return new RubyRepeatedField(runtime, klazz);
+                    }
+                });
+        cRepeatedField.defineAnnotatedMethods(RubyRepeatedField.class);
+        cRepeatedField.includeModule(runtime.getEnumerable());
+    }
+
+    public RubyRepeatedField(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    public RubyRepeatedField(Ruby runtime, RubyClass klazz, Descriptors.FieldDescriptor.Type fieldType, IRubyObject typeClass) {
+        this(runtime, klazz);
+        this.fieldType = fieldType;
+        this.storage = runtime.newArray();
+        this.typeClass = typeClass;
+    }
+
+    @JRubyMethod(required = 1, optional = 2)
+    public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
+        Ruby runtime = context.runtime;
+        this.storage = runtime.newArray();
+        IRubyObject ary = null;
+        if (!(args[0] instanceof RubySymbol)) {
+            throw runtime.newArgumentError("Expected Symbol for type name");
+        }
+        this.fieldType = Utils.rubyToFieldType(args[0]);
+        if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE
+                || fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+            if (args.length < 2)
+                throw runtime.newArgumentError("Expected at least 2 arguments for message/enum");
+            typeClass = args[1];
+            if (args.length > 2)
+                ary = args[2];
+            Utils.validateTypeClass(context, fieldType, typeClass);
+        } else {
+            if (args.length > 2)
+                throw runtime.newArgumentError("Too many arguments: expected 1 or 2");
+            if (args.length > 1)
+                ary = args[1];
+        }
+        if (ary != null) {
+            RubyArray arr = ary.convertToArray();
+            for (int i = 0; i < arr.size(); i++) {
+                this.storage.add(arr.eltInternal(i));
+            }
+        }
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.[]=(index, value)
+     *
+     * Sets the element at the given index. On out-of-bounds assignments, extends
+     * the array and fills the hole (if any) with default values.
+     */
+    @JRubyMethod(name = "[]=")
+    public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
+        int arrIndex = normalizeArrayIndex(index);
+        Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+        IRubyObject defaultValue = defaultValue(context);
+        for (int i = this.storage.size(); i < arrIndex; i++) {
+            this.storage.set(i, defaultValue);
+        }
+        this.storage.set(arrIndex, value);
+        return context.runtime.getNil();
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.[](index) => value
+     *
+     * Accesses the element at the given index. Returns nil on out-of-bounds
+     */
+    @JRubyMethod(required=1, optional=1, name = {"at", "[]"})
+    public IRubyObject index(ThreadContext context, IRubyObject[] args) {
+        if (args.length == 1){
+            IRubyObject arg = args[0];
+            if (Utils.isRubyNum(arg)) {
+                /* standard case */
+                int arrIndex = normalizeArrayIndex(arg);
+                if (arrIndex < 0 || arrIndex >= this.storage.size()) {
+                    return context.runtime.getNil();
+                }
+                return this.storage.eltInternal(arrIndex);
+            } else if (arg instanceof RubyRange) {
+                RubyRange range = ((RubyRange) arg);
+                int beg = RubyNumeric.num2int(range.first(context));
+                int to = RubyNumeric.num2int(range.last(context));
+                int len = to - beg + 1;
+                return this.storage.subseq(beg, len);
+            }
+        }
+        /* assume 2 arguments */
+        int beg = RubyNumeric.num2int(args[0]);
+        int len = RubyNumeric.num2int(args[1]);
+        if (beg < 0) {
+            beg += this.storage.size();
+        }
+        if (beg >= this.storage.size()) {
+            return context.runtime.getNil();
+        }
+        return this.storage.subseq(beg, len);
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.push(value)
+     *
+     * Adds a new element to the repeated field.
+     */
+    @JRubyMethod(name = {"push", "<<"})
+    public IRubyObject push(ThreadContext context, IRubyObject value) {
+        if (!(fieldType == Descriptors.FieldDescriptor.Type.MESSAGE &&
+            value == context.runtime.getNil())) {
+            Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+        }
+        this.storage.add(value);
+        return this.storage;
+    }
+
+    /*
+     * private Ruby method used by RepeatedField.pop
+     */
+    @JRubyMethod(visibility = org.jruby.runtime.Visibility.PRIVATE)
+    public IRubyObject pop_one(ThreadContext context) {
+        IRubyObject ret = this.storage.last();
+        this.storage.remove(ret);
+        return ret;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.replace(list)
+     *
+     * Replaces the contents of the repeated field with the given list of elements.
+     */
+    @JRubyMethod
+    public IRubyObject replace(ThreadContext context, IRubyObject list) {
+        RubyArray arr = (RubyArray) list;
+        checkArrayElementType(context, arr);
+        this.storage = arr;
+        return this.storage;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.clear
+     *
+     * Clears (removes all elements from) this repeated field.
+     */
+    @JRubyMethod
+    public IRubyObject clear(ThreadContext context) {
+        this.storage.clear();
+        return this.storage;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.length
+     *
+     * Returns the length of this repeated field.
+     */
+    @JRubyMethod(name = {"length", "size"})
+    public IRubyObject length(ThreadContext context) {
+        return context.runtime.newFixnum(this.storage.size());
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.+(other) => repeated field
+     *
+     * Returns a new repeated field that contains the concatenated list of this
+     * repeated field's elements and other's elements. The other (second) list may
+     * be either another repeated field or a Ruby array.
+     */
+    @JRubyMethod(name = {"+"})
+    public IRubyObject plus(ThreadContext context, IRubyObject list) {
+        RubyRepeatedField dup = (RubyRepeatedField) dup(context);
+        if (list instanceof RubyArray) {
+            checkArrayElementType(context, (RubyArray) list);
+            dup.storage.addAll((RubyArray) list);
+        } else {
+            RubyRepeatedField repeatedField = (RubyRepeatedField) list;
+            if (! fieldType.equals(repeatedField.fieldType) || (typeClass != null && !
+                    typeClass.equals(repeatedField.typeClass)))
+                throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type.");
+            dup.storage.addAll((RubyArray) repeatedField.toArray(context));
+        }
+        return dup;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.concat(other) => self
+     *
+     * concats the passed in array to self.  Returns a Ruby array.
+     */
+    @JRubyMethod
+    public IRubyObject concat(ThreadContext context, IRubyObject list) {
+        if (list instanceof RubyArray) {
+            checkArrayElementType(context, (RubyArray) list);
+            this.storage.addAll((RubyArray) list);
+        } else {
+            RubyRepeatedField repeatedField = (RubyRepeatedField) list;
+            if (! fieldType.equals(repeatedField.fieldType) || (typeClass != null && !
+                    typeClass.equals(repeatedField.typeClass)))
+                throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type.");
+            this.storage.addAll((RubyArray) repeatedField.toArray(context));
+        }
+        return this.storage;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.hash => hash_value
+     *
+     * Returns a hash value computed from this repeated field's elements.
+     */
+    @JRubyMethod
+    public IRubyObject hash(ThreadContext context) {
+        int hashCode = this.storage.hashCode();
+        return context.runtime.newFixnum(hashCode);
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.==(other) => boolean
+     *
+     * Compares this repeated field to another. Repeated fields are equal if their
+     * element types are equal, their lengths are equal, and each element is equal.
+     * Elements are compared as per normal Ruby semantics, by calling their :==
+     * methods (or performing a more efficient comparison for primitive types).
+     */
+    @JRubyMethod(name = "==")
+    public IRubyObject eq(ThreadContext context, IRubyObject other) {
+        return this.toArray(context).op_equal(context, other);
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.each(&block)
+     *
+     * Invokes the block once for each element of the repeated field. RepeatedField
+     * also includes Enumerable; combined with this method, the repeated field thus
+     * acts like an ordinary Ruby sequence.
+     */
+    @JRubyMethod
+    public IRubyObject each(ThreadContext context, Block block) {
+        this.storage.each(context, block);
+        return this.storage;
+    }
+
+
+    @JRubyMethod(name = {"to_ary", "to_a"})
+    public IRubyObject toArray(ThreadContext context) {
+        return this.storage;
+    }
+
+    /*
+     * call-seq:
+     *     RepeatedField.dup => repeated_field
+     *
+     * Duplicates this repeated field with a shallow copy. References to all
+     * non-primitive element objects (e.g., submessages) are shared.
+     */
+    @JRubyMethod
+    public IRubyObject dup(ThreadContext context) {
+        RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
+        for (int i = 0; i < this.storage.size(); i++) {
+            dup.push(context, this.storage.eltInternal(i));
+        }
+        return dup;
+    }
+
+    // Java API
+    protected IRubyObject get(int index) {
+        return this.storage.eltInternal(index);
+    }
+
+    protected RubyRepeatedField deepCopy(ThreadContext context) {
+        RubyRepeatedField copy = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
+        for (int i = 0; i < size(); i++) {
+            IRubyObject value = storage.eltInternal(i);
+            if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
+                copy.storage.add(((RubyMessage) value).deepCopy(context));
+            } else {
+                copy.storage.add(value);
+            }
+        }
+        return copy;
+    }
+
+    protected int size() {
+        return this.storage.size();
+    }
+
+    private IRubyObject defaultValue(ThreadContext context) {
+        SentinelOuterClass.Sentinel sentinel = SentinelOuterClass.Sentinel.getDefaultInstance();
+        Object value;
+        switch (fieldType) {
+            case INT32:
+                value = sentinel.getDefaultInt32();
+                break;
+            case INT64:
+                value = sentinel.getDefaultInt64();
+                break;
+            case UINT32:
+                value = sentinel.getDefaultUnit32();
+                break;
+            case UINT64:
+                value = sentinel.getDefaultUint64();
+                break;
+            case FLOAT:
+                value = sentinel.getDefaultFloat();
+                break;
+            case DOUBLE:
+                value = sentinel.getDefaultDouble();
+                break;
+            case BOOL:
+                value = sentinel.getDefaultBool();
+                break;
+            case BYTES:
+                value = sentinel.getDefaultBytes();
+                break;
+            case STRING:
+                value = sentinel.getDefaultString();
+                break;
+            case ENUM:
+                IRubyObject defaultEnumLoc = context.runtime.newFixnum(0);
+                return RubyEnum.lookup(context, typeClass, defaultEnumLoc);
+            default:
+                return context.runtime.getNil();
+        }
+        return Utils.wrapPrimaryValue(context, fieldType, value);
+    }
+
+    private void checkArrayElementType(ThreadContext context, RubyArray arr) {
+        for (int i = 0; i < arr.getLength(); i++) {
+            Utils.checkType(context, fieldType, arr.eltInternal(i), (RubyModule) typeClass);
+        }
+    }
+
+    private int normalizeArrayIndex(IRubyObject index) {
+        int arrIndex = RubyNumeric.num2int(index);
+        int arrSize = this.storage.size();
+        if (arrIndex < 0 && arrSize > 0) {
+            arrIndex = arrSize + arrIndex;
+        }
+        return arrIndex;
+    }
+
+    private RubyArray storage;
+    private Descriptors.FieldDescriptor.Type fieldType;
+    private IRubyObject typeClass;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java
new file mode 100644
index 0000000..54f2c72
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java
@@ -0,0 +1,776 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: sentinel.proto
+
+package com.google.protobuf.jruby;
+
+public final class SentinelOuterClass {
+  private SentinelOuterClass() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface SentinelOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:com.google.protobuf.jruby.Sentinel)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional int32 default_int32 = 1;</code>
+     */
+    int getDefaultInt32();
+
+    /**
+     * <code>optional int64 default_int64 = 2;</code>
+     */
+    long getDefaultInt64();
+
+    /**
+     * <code>optional uint32 default_unit32 = 3;</code>
+     */
+    int getDefaultUnit32();
+
+    /**
+     * <code>optional uint64 default_uint64 = 4;</code>
+     */
+    long getDefaultUint64();
+
+    /**
+     * <code>optional string default_string = 5;</code>
+     */
+    java.lang.String getDefaultString();
+    /**
+     * <code>optional string default_string = 5;</code>
+     */
+    com.google.protobuf.ByteString
+        getDefaultStringBytes();
+
+    /**
+     * <code>optional bool default_bool = 6;</code>
+     */
+    boolean getDefaultBool();
+
+    /**
+     * <code>optional float default_float = 7;</code>
+     */
+    float getDefaultFloat();
+
+    /**
+     * <code>optional double default_double = 8;</code>
+     */
+    double getDefaultDouble();
+
+    /**
+     * <code>optional bytes default_bytes = 9;</code>
+     */
+    com.google.protobuf.ByteString getDefaultBytes();
+  }
+  /**
+   * Protobuf type {@code com.google.protobuf.jruby.Sentinel}
+   */
+  public  static final class Sentinel extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:com.google.protobuf.jruby.Sentinel)
+      SentinelOrBuilder {
+    // Use Sentinel.newBuilder() to construct.
+    private Sentinel(com.google.protobuf.GeneratedMessage.Builder builder) {
+      super(builder);
+    }
+    private Sentinel() {
+      defaultInt32_ = 0;
+      defaultInt64_ = 0L;
+      defaultUnit32_ = 0;
+      defaultUint64_ = 0L;
+      defaultString_ = "";
+      defaultBool_ = false;
+      defaultFloat_ = 0F;
+      defaultDouble_ = 0D;
+      defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
+    }
+
+    public static final com.google.protobuf.Parser<Sentinel> PARSER =
+        new com.google.protobuf.AbstractParser<Sentinel>() {
+      public Sentinel parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        Builder builder = newBuilder();
+        try {
+          builder.mergeFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(builder.buildPartial());
+        } catch (java.io.IOException e) {
+          throw new com.google.protobuf.InvalidProtocolBufferException(
+              e.getMessage()).setUnfinishedMessage(builder.buildPartial());
+        }
+        return builder.buildPartial();
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Sentinel> getParserForType() {
+      return PARSER;
+    }
+
+    public static final int DEFAULT_INT32_FIELD_NUMBER = 1;
+    private int defaultInt32_;
+    /**
+     * <code>optional int32 default_int32 = 1;</code>
+     */
+    public int getDefaultInt32() {
+      return defaultInt32_;
+    }
+
+    public static final int DEFAULT_INT64_FIELD_NUMBER = 2;
+    private long defaultInt64_;
+    /**
+     * <code>optional int64 default_int64 = 2;</code>
+     */
+    public long getDefaultInt64() {
+      return defaultInt64_;
+    }
+
+    public static final int DEFAULT_UNIT32_FIELD_NUMBER = 3;
+    private int defaultUnit32_;
+    /**
+     * <code>optional uint32 default_unit32 = 3;</code>
+     */
+    public int getDefaultUnit32() {
+      return defaultUnit32_;
+    }
+
+    public static final int DEFAULT_UINT64_FIELD_NUMBER = 4;
+    private long defaultUint64_;
+    /**
+     * <code>optional uint64 default_uint64 = 4;</code>
+     */
+    public long getDefaultUint64() {
+      return defaultUint64_;
+    }
+
+    public static final int DEFAULT_STRING_FIELD_NUMBER = 5;
+    private java.lang.Object defaultString_;
+    /**
+     * <code>optional string default_string = 5;</code>
+     */
+    public java.lang.String getDefaultString() {
+      java.lang.Object ref = defaultString_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          defaultString_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string default_string = 5;</code>
+     */
+    public com.google.protobuf.ByteString
+        getDefaultStringBytes() {
+      java.lang.Object ref = defaultString_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        defaultString_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int DEFAULT_BOOL_FIELD_NUMBER = 6;
+    private boolean defaultBool_;
+    /**
+     * <code>optional bool default_bool = 6;</code>
+     */
+    public boolean getDefaultBool() {
+      return defaultBool_;
+    }
+
+    public static final int DEFAULT_FLOAT_FIELD_NUMBER = 7;
+    private float defaultFloat_;
+    /**
+     * <code>optional float default_float = 7;</code>
+     */
+    public float getDefaultFloat() {
+      return defaultFloat_;
+    }
+
+    public static final int DEFAULT_DOUBLE_FIELD_NUMBER = 8;
+    private double defaultDouble_;
+    /**
+     * <code>optional double default_double = 8;</code>
+     */
+    public double getDefaultDouble() {
+      return defaultDouble_;
+    }
+
+    public static final int DEFAULT_BYTES_FIELD_NUMBER = 9;
+    private com.google.protobuf.ByteString defaultBytes_;
+    /**
+     * <code>optional bytes default_bytes = 9;</code>
+     */
+    public com.google.protobuf.ByteString getDefaultBytes() {
+      return defaultBytes_;
+    }
+
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return new Builder(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(com.google.protobuf.jruby.SentinelOuterClass.Sentinel prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code com.google.protobuf.jruby.Sentinel}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:com.google.protobuf.jruby.Sentinel)
+        com.google.protobuf.jruby.SentinelOuterClass.SentinelOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
+      }
+
+      // Construct using com.google.protobuf.jruby.SentinelOuterClass.Sentinel.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      public Builder clear() {
+        super.clear();
+        defaultInt32_ = 0;
+
+        defaultInt64_ = 0L;
+
+        defaultUnit32_ = 0;
+
+        defaultUint64_ = 0L;
+
+        defaultString_ = "";
+
+        defaultBool_ = false;
+
+        defaultFloat_ = 0F;
+
+        defaultDouble_ = 0D;
+
+        defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+
+        return this;
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+      }
+
+      public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
+        return com.google.protobuf.jruby.SentinelOuterClass.Sentinel.getDefaultInstance();
+      }
+
+      public com.google.protobuf.jruby.SentinelOuterClass.Sentinel build() {
+        com.google.protobuf.jruby.SentinelOuterClass.Sentinel result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public com.google.protobuf.jruby.SentinelOuterClass.Sentinel buildPartial() {
+        com.google.protobuf.jruby.SentinelOuterClass.Sentinel result = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel(this);
+        result.defaultInt32_ = defaultInt32_;
+        result.defaultInt64_ = defaultInt64_;
+        result.defaultUnit32_ = defaultUnit32_;
+        result.defaultUint64_ = defaultUint64_;
+        result.defaultString_ = defaultString_;
+        result.defaultBool_ = defaultBool_;
+        result.defaultFloat_ = defaultFloat_;
+        result.defaultDouble_ = defaultDouble_;
+        result.defaultBytes_ = defaultBytes_;
+        onBuilt();
+        return result;
+      }
+
+
+      private int defaultInt32_ ;
+      /**
+       * <code>optional int32 default_int32 = 1;</code>
+       */
+      public int getDefaultInt32() {
+        return defaultInt32_;
+      }
+      /**
+       * <code>optional int32 default_int32 = 1;</code>
+       */
+      public Builder setDefaultInt32(int value) {
+        
+        defaultInt32_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 default_int32 = 1;</code>
+       */
+      public Builder clearDefaultInt32() {
+        
+        defaultInt32_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private long defaultInt64_ ;
+      /**
+       * <code>optional int64 default_int64 = 2;</code>
+       */
+      public long getDefaultInt64() {
+        return defaultInt64_;
+      }
+      /**
+       * <code>optional int64 default_int64 = 2;</code>
+       */
+      public Builder setDefaultInt64(long value) {
+        
+        defaultInt64_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 default_int64 = 2;</code>
+       */
+      public Builder clearDefaultInt64() {
+        
+        defaultInt64_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private int defaultUnit32_ ;
+      /**
+       * <code>optional uint32 default_unit32 = 3;</code>
+       */
+      public int getDefaultUnit32() {
+        return defaultUnit32_;
+      }
+      /**
+       * <code>optional uint32 default_unit32 = 3;</code>
+       */
+      public Builder setDefaultUnit32(int value) {
+        
+        defaultUnit32_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional uint32 default_unit32 = 3;</code>
+       */
+      public Builder clearDefaultUnit32() {
+        
+        defaultUnit32_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private long defaultUint64_ ;
+      /**
+       * <code>optional uint64 default_uint64 = 4;</code>
+       */
+      public long getDefaultUint64() {
+        return defaultUint64_;
+      }
+      /**
+       * <code>optional uint64 default_uint64 = 4;</code>
+       */
+      public Builder setDefaultUint64(long value) {
+        
+        defaultUint64_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional uint64 default_uint64 = 4;</code>
+       */
+      public Builder clearDefaultUint64() {
+        
+        defaultUint64_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object defaultString_ = "";
+      /**
+       * <code>optional string default_string = 5;</code>
+       */
+      public java.lang.String getDefaultString() {
+        java.lang.Object ref = defaultString_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            defaultString_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string default_string = 5;</code>
+       */
+      public com.google.protobuf.ByteString
+          getDefaultStringBytes() {
+        java.lang.Object ref = defaultString_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          defaultString_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string default_string = 5;</code>
+       */
+      public Builder setDefaultString(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        defaultString_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string default_string = 5;</code>
+       */
+      public Builder clearDefaultString() {
+        
+        defaultString_ = getDefaultInstance().getDefaultString();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string default_string = 5;</code>
+       */
+      public Builder setDefaultStringBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        defaultString_ = value;
+        onChanged();
+        return this;
+      }
+
+      private boolean defaultBool_ ;
+      /**
+       * <code>optional bool default_bool = 6;</code>
+       */
+      public boolean getDefaultBool() {
+        return defaultBool_;
+      }
+      /**
+       * <code>optional bool default_bool = 6;</code>
+       */
+      public Builder setDefaultBool(boolean value) {
+        
+        defaultBool_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool default_bool = 6;</code>
+       */
+      public Builder clearDefaultBool() {
+        
+        defaultBool_ = false;
+        onChanged();
+        return this;
+      }
+
+      private float defaultFloat_ ;
+      /**
+       * <code>optional float default_float = 7;</code>
+       */
+      public float getDefaultFloat() {
+        return defaultFloat_;
+      }
+      /**
+       * <code>optional float default_float = 7;</code>
+       */
+      public Builder setDefaultFloat(float value) {
+        
+        defaultFloat_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional float default_float = 7;</code>
+       */
+      public Builder clearDefaultFloat() {
+        
+        defaultFloat_ = 0F;
+        onChanged();
+        return this;
+      }
+
+      private double defaultDouble_ ;
+      /**
+       * <code>optional double default_double = 8;</code>
+       */
+      public double getDefaultDouble() {
+        return defaultDouble_;
+      }
+      /**
+       * <code>optional double default_double = 8;</code>
+       */
+      public Builder setDefaultDouble(double value) {
+        
+        defaultDouble_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional double default_double = 8;</code>
+       */
+      public Builder clearDefaultDouble() {
+        
+        defaultDouble_ = 0D;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.ByteString defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes default_bytes = 9;</code>
+       */
+      public com.google.protobuf.ByteString getDefaultBytes() {
+        return defaultBytes_;
+      }
+      /**
+       * <code>optional bytes default_bytes = 9;</code>
+       */
+      public Builder setDefaultBytes(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        defaultBytes_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes default_bytes = 9;</code>
+       */
+      public Builder clearDefaultBytes() {
+        
+        defaultBytes_ = getDefaultInstance().getDefaultBytes();
+        onChanged();
+        return this;
+      }
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:com.google.protobuf.jruby.Sentinel)
+    }
+
+    // @@protoc_insertion_point(class_scope:com.google.protobuf.jruby.Sentinel)
+    private static final com.google.protobuf.jruby.SentinelOuterClass.Sentinel defaultInstance;static {
+      defaultInstance = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel();
+    }
+
+    public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\016sentinel.proto\022\031com.google.protobuf.jr" +
+      "uby\"\334\001\n\010Sentinel\022\025\n\rdefault_int32\030\001 \001(\005\022" +
+      "\025\n\rdefault_int64\030\002 \001(\003\022\026\n\016default_unit32" +
+      "\030\003 \001(\r\022\026\n\016default_uint64\030\004 \001(\004\022\026\n\016defaul" +
+      "t_string\030\005 \001(\t\022\024\n\014default_bool\030\006 \001(\010\022\025\n\r" +
+      "default_float\030\007 \001(\002\022\026\n\016default_double\030\010 " +
+      "\001(\001\022\025\n\rdefault_bytes\030\t \001(\014B\002H\002b\006proto3"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+    internal_static_com_google_protobuf_jruby_Sentinel_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_com_google_protobuf_jruby_Sentinel_descriptor,
+        new java.lang.String[] { "DefaultInt32", "DefaultInt64", "DefaultUnit32", "DefaultUint64", "DefaultString", "DefaultBool", "DefaultFloat", "DefaultDouble", "DefaultBytes", });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
new file mode 100644
index 0000000..596a097
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
@@ -0,0 +1,300 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jcodings.Encoding;
+import org.jcodings.specific.ASCIIEncoding;
+import org.jcodings.specific.USASCIIEncoding;
+import org.jcodings.specific.UTF8Encoding;
+import org.jruby.*;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.math.BigInteger;
+
+public class Utils {
+    public static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
+        return Descriptors.FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
+    }
+
+    public static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type) {
+        return fieldTypeToRuby(context, type.name());
+    }
+
+    public static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type) {
+        return fieldTypeToRuby(context, type.name());
+    }
+
+    private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName) {
+
+        return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
+    }
+
+    public static void checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
+                            IRubyObject value, RubyModule typeClass) {
+        Ruby runtime = context.runtime;
+        Object val;
+        switch(fieldType) {
+            case INT32:
+            case INT64:
+            case UINT32:
+            case UINT64:
+                if (!isRubyNum(value)) {
+                    throw runtime.newTypeError("Expected number type for integral field.");
+                }
+                switch(fieldType) {
+                    case INT32:
+                        RubyNumeric.num2int(value);
+                        break;
+                    case INT64:
+                        RubyNumeric.num2long(value);
+                        break;
+                    case UINT32:
+                        num2uint(value);
+                        break;
+                    default:
+                        num2ulong(context.runtime, value);
+                        break;
+                }
+                checkIntTypePrecision(context, fieldType, value);
+                break;
+            case FLOAT:
+                if (!isRubyNum(value))
+                    throw runtime.newTypeError("Expected number type for float field.");
+                break;
+            case DOUBLE:
+                if (!isRubyNum(value))
+                    throw runtime.newTypeError("Expected number type for double field.");
+                break;
+            case BOOL:
+                if (!(value instanceof RubyBoolean))
+                    throw runtime.newTypeError("Invalid argument for boolean field.");
+                break;
+            case BYTES:
+            case STRING:
+                validateStringEncoding(context.runtime, fieldType, value);
+                break;
+            case MESSAGE:
+                if (value.getMetaClass() != typeClass) {
+                    throw runtime.newTypeError(value, typeClass);
+                }
+                break;
+            case ENUM:
+                if (value instanceof RubySymbol) {
+                    Descriptors.EnumDescriptor enumDescriptor =
+                            ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).getDescriptor();
+                    val = enumDescriptor.findValueByName(value.asJavaString());
+                    if (val == null)
+                        throw runtime.newRangeError("Enum value " + value + " is not found.");
+                } else if(!isRubyNum(value)) {
+                    throw runtime.newTypeError("Expected number or symbol type for enum field.");
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) {
+        Ruby runtime = context.runtime;
+        switch (fieldType) {
+            case INT32:
+                return runtime.newFixnum((Integer) value);
+            case INT64:
+                return runtime.newFixnum((Long) value);
+            case UINT32:
+                return runtime.newFixnum(((Integer) value) & (-1l >>> 32));
+            case UINT64:
+                long ret = (Long) value;
+                return ret >= 0 ? runtime.newFixnum(ret) :
+                        RubyBignum.newBignum(runtime, UINT64_COMPLEMENTARY.add(new BigInteger(ret + "")));
+            case FLOAT:
+                return runtime.newFloat((Float) value);
+            case DOUBLE:
+                return runtime.newFloat((Double) value);
+            case BOOL:
+                return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
+            case BYTES:
+                return runtime.newString(((ByteString) value).toStringUtf8());
+            case STRING:
+                return runtime.newString(value.toString());
+            default:
+                return runtime.getNil();
+        }
+    }
+
+    public static int num2uint(IRubyObject value) {
+        long longVal = RubyNumeric.num2long(value);
+        if (longVal > UINT_MAX)
+            throw value.getRuntime().newRangeError("Integer " + longVal + " too big to convert to 'unsigned int'");
+        long num = longVal;
+        if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE)
+            // encode to UINT32
+            num = (-longVal ^ (-1l >>> 32) ) + 1;
+        RubyNumeric.checkInt(value, num);
+        return (int) num;
+    }
+
+    public static long num2ulong(Ruby runtime, IRubyObject value) {
+        if (value instanceof RubyFloat) {
+            RubyBignum bignum = RubyBignum.newBignum(runtime, ((RubyFloat) value).getDoubleValue());
+            return RubyBignum.big2ulong(bignum);
+        } else if (value instanceof RubyBignum) {
+            return RubyBignum.big2ulong((RubyBignum) value);
+        } else {
+            return RubyNumeric.num2long(value);
+        }
+    }
+
+    public static void validateStringEncoding(Ruby runtime, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+        if (!(value instanceof RubyString))
+            throw runtime.newTypeError("Invalid argument for string field.");
+        Encoding encoding = ((RubyString) value).getEncoding();
+        switch(type) {
+            case BYTES:
+                if (encoding != ASCIIEncoding.INSTANCE)
+                    throw runtime.newTypeError("Encoding for bytes fields" +
+                            " must be \"ASCII-8BIT\", but was " + encoding);
+                break;
+            case STRING:
+                if (encoding != UTF8Encoding.INSTANCE
+                        && encoding != USASCIIEncoding.INSTANCE)
+                    throw runtime.newTypeError("Encoding for string fields" +
+                            " must be \"UTF-8\" or \"ASCII\", but was " + encoding);
+                break;
+            default:
+                break;
+        }
+    }
+
+    public static void checkNameAvailability(ThreadContext context, String name) {
+        if (context.runtime.getObject().getConstantAt(name) != null)
+            throw context.runtime.newNameError(name + " is already defined", name);
+    }
+
+    /**
+     * Replace invalid "." in descriptor with __DOT__
+     * @param name
+     * @return
+     */
+    public static String escapeIdentifier(String name) {
+        return name.replace(".", BADNAME_REPLACEMENT);
+    }
+
+    /**
+     * Replace __DOT__ in descriptor name with "."
+     * @param name
+     * @return
+     */
+    public static String unescapeIdentifier(String name) {
+        return name.replace(BADNAME_REPLACEMENT, ".");
+    }
+
+    public static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor) {
+        return fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+                fieldDescriptor.isRepeated() &&
+                fieldDescriptor.getMessageType().getOptions().getMapEntry();
+    }
+
+    public static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name,
+                                      IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor) {
+        Ruby runtime = context.runtime;
+        RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+        fieldDef.setLabel(context, runtime.newString(label));
+        fieldDef.setName(context, name);
+        fieldDef.setType(context, type);
+        fieldDef.setNumber(context, number);
+
+        if (!typeClass.isNil()) {
+            if (!(typeClass instanceof RubyString)) {
+                throw runtime.newArgumentError("expected string for type class");
+            }
+            fieldDef.setSubmsgName(context, typeClass);
+        }
+        return fieldDef;
+    }
+
+    protected static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+        if (value instanceof RubyFloat) {
+            double doubleVal = RubyNumeric.num2dbl(value);
+            if (Math.floor(doubleVal) != doubleVal) {
+                throw context.runtime.newRangeError("Non-integral floating point value assigned to integer field.");
+            }
+        }
+        if (type == Descriptors.FieldDescriptor.Type.UINT32 || type == Descriptors.FieldDescriptor.Type.UINT64) {
+            if (RubyNumeric.num2dbl(value) < 0) {
+                throw context.runtime.newRangeError("Assigning negative value to unsigned integer field.");
+            }
+        }
+    }
+
+    protected static boolean isRubyNum(Object value) {
+        return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum;
+    }
+
+    protected static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+        Ruby runtime = context.runtime;
+        if (!(value instanceof RubyModule)) {
+            throw runtime.newArgumentError("TypeClass has incorrect type");
+        }
+        RubyModule klass = (RubyModule) value;
+        IRubyObject descriptor = klass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR);
+        if (descriptor.isNil()) {
+            throw runtime.newArgumentError("Type class has no descriptor. Please pass a " +
+                    "class or enum as returned by the DescriptorPool.");
+        }
+        if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+            if (! (descriptor instanceof RubyDescriptor)) {
+                throw runtime.newArgumentError("Descriptor has an incorrect type");
+            }
+        } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+            if (! (descriptor instanceof RubyEnumDescriptor)) {
+                throw runtime.newArgumentError("Descriptor has an incorrect type");
+            }
+        }
+    }
+
+    public static String BADNAME_REPLACEMENT = "__DOT__";
+
+    public static String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
+
+    public static String EQUAL_SIGN = "=";
+
+    private static BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64)
+
+    private static long UINT_MAX = 0xffffffffl;
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/java/google/ProtobufJavaService.java b/src/third_party/protobuf-3/ruby/src/main/java/google/ProtobufJavaService.java
new file mode 100644
index 0000000..bffb492
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/java/google/ProtobufJavaService.java
@@ -0,0 +1,60 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 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.
+ */
+
+package google;
+
+import com.google.protobuf.jruby.*;
+import org.jruby.Ruby;
+import org.jruby.runtime.load.BasicLibraryService;
+
+import java.io.IOException;
+
+public class ProtobufJavaService implements BasicLibraryService {
+    @Override
+    public boolean basicLoad(Ruby ruby) throws IOException {
+        ruby.defineModule("Google");
+        RubyProtobuf.createProtobuf(ruby);
+        RubyDescriptor.createRubyDescriptor(ruby);
+        RubyBuilder.createRubyBuilder(ruby);
+        RubyFieldDescriptor.createRubyFileDescriptor(ruby);
+        RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby);
+        RubyEnumDescriptor.createRubyEnumDescriptor(ruby);
+        RubyEnumBuilderContext.createRubyEnumBuilderContext(ruby);
+        RubyDescriptorPool.createRubyDescriptorPool(ruby);
+        RubyRepeatedField.createRubyRepeatedField(ruby);
+        RubyFieldDescriptor.createRubyFileDescriptor(ruby);
+        RubyMap.createRubyMap(ruby);
+        RubyOneofDescriptor.createRubyOneofDescriptor(ruby);
+        RubyOneofBuilderContext.createRubyOneofBuilderContext(ruby);
+        return true;
+    }
+}
diff --git a/src/third_party/protobuf-3/ruby/src/main/sentinel.proto b/src/third_party/protobuf-3/ruby/src/main/sentinel.proto
new file mode 100644
index 0000000..722041b
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/src/main/sentinel.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+package com.google.protobuf.jruby;
+option optimize_for = CODE_SIZE;
+
+message Sentinel {
+  int32 default_int32 = 1;
+  int64 default_int64 = 2;
+  uint32 default_unit32 = 3;
+  uint64 default_uint64 = 4;
+  string default_string = 5;
+  bool default_bool = 6;
+  float default_float = 7;
+  double default_double = 8;
+  bytes default_bytes = 9;
+}
diff --git a/src/third_party/protobuf-3/ruby/tests/basic.rb b/src/third_party/protobuf-3/ruby/tests/basic.rb
new file mode 100644
index 0000000..77c186e
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/tests/basic.rb
@@ -0,0 +1,1174 @@
+#!/usr/bin/ruby
+
+require 'google/protobuf'
+require 'test/unit'
+
+# ------------- generated code --------------
+
+module BasicTest
+  pool = Google::Protobuf::DescriptorPool.new
+  pool.build do
+    add_message "Foo" do
+      optional :bar, :message, 1, "Bar"
+      repeated :baz, :message, 2, "Baz"
+    end
+
+    add_message "Bar" do
+      optional :msg, :string, 1
+    end
+
+    add_message "Baz" do
+      optional :msg, :string, 1
+    end
+
+    add_message "TestMessage" do
+      optional :optional_int32,  :int32,        1
+      optional :optional_int64,  :int64,        2
+      optional :optional_uint32, :uint32,       3
+      optional :optional_uint64, :uint64,       4
+      optional :optional_bool,   :bool,         5
+      optional :optional_float,  :float,        6
+      optional :optional_double, :double,       7
+      optional :optional_string, :string,       8
+      optional :optional_bytes,  :bytes,        9
+      optional :optional_msg,    :message,      10, "TestMessage2"
+      optional :optional_enum,   :enum,         11, "TestEnum"
+
+      repeated :repeated_int32,  :int32,        12
+      repeated :repeated_int64,  :int64,        13
+      repeated :repeated_uint32, :uint32,       14
+      repeated :repeated_uint64, :uint64,       15
+      repeated :repeated_bool,   :bool,         16
+      repeated :repeated_float,  :float,        17
+      repeated :repeated_double, :double,       18
+      repeated :repeated_string, :string,       19
+      repeated :repeated_bytes,  :bytes,        20
+      repeated :repeated_msg,    :message,      21, "TestMessage2"
+      repeated :repeated_enum,   :enum,         22, "TestEnum"
+    end
+    add_message "TestMessage2" do
+      optional :foo, :int32, 1
+    end
+
+    add_message "Recursive1" do
+      optional :foo, :message, 1, "Recursive2"
+    end
+    add_message "Recursive2" do
+      optional :foo, :message, 1, "Recursive1"
+    end
+
+    add_enum "TestEnum" do
+      value :Default, 0
+      value :A, 1
+      value :B, 2
+      value :C, 3
+    end
+
+    add_message "BadFieldNames" do
+      optional :dup, :int32, 1
+      optional :class, :int32, 2
+      optional :"a.b", :int32, 3
+    end
+
+    add_message "MapMessage" do
+      map :map_string_int32, :string, :int32, 1
+      map :map_string_msg, :string, :message, 2, "TestMessage2"
+    end
+    add_message "MapMessageWireEquiv" do
+      repeated :map_string_int32, :message, 1, "MapMessageWireEquiv_entry1"
+      repeated :map_string_msg, :message, 2, "MapMessageWireEquiv_entry2"
+    end
+    add_message "MapMessageWireEquiv_entry1" do
+      optional :key, :string, 1
+      optional :value, :int32, 2
+    end
+    add_message "MapMessageWireEquiv_entry2" do
+      optional :key, :string, 1
+      optional :value, :message, 2, "TestMessage2"
+    end
+
+    add_message "OneofMessage" do
+      oneof :my_oneof do
+        optional :a, :string, 1
+        optional :b, :int32, 2
+        optional :c, :message, 3, "TestMessage2"
+        optional :d, :enum, 4, "TestEnum"
+      end
+    end
+  end
+
+  Foo = pool.lookup("Foo").msgclass
+  Bar = pool.lookup("Bar").msgclass
+  Baz = pool.lookup("Baz").msgclass
+  TestMessage = pool.lookup("TestMessage").msgclass
+  TestMessage2 = pool.lookup("TestMessage2").msgclass
+  Recursive1 = pool.lookup("Recursive1").msgclass
+  Recursive2 = pool.lookup("Recursive2").msgclass
+  TestEnum = pool.lookup("TestEnum").enummodule
+  BadFieldNames = pool.lookup("BadFieldNames").msgclass
+  MapMessage = pool.lookup("MapMessage").msgclass
+  MapMessageWireEquiv = pool.lookup("MapMessageWireEquiv").msgclass
+  MapMessageWireEquiv_entry1 =
+    pool.lookup("MapMessageWireEquiv_entry1").msgclass
+  MapMessageWireEquiv_entry2 =
+    pool.lookup("MapMessageWireEquiv_entry2").msgclass
+  OneofMessage = pool.lookup("OneofMessage").msgclass
+
+# ------------ test cases ---------------
+
+  class MessageContainerTest < Test::Unit::TestCase
+
+    def test_defaults
+      m = TestMessage.new
+      assert m.optional_int32 == 0
+      assert m.optional_int64 == 0
+      assert m.optional_uint32 == 0
+      assert m.optional_uint64 == 0
+      assert m.optional_bool == false
+      assert m.optional_float == 0.0
+      assert m.optional_double == 0.0
+      assert m.optional_string == ""
+      assert m.optional_bytes == ""
+      assert m.optional_msg == nil
+      assert m.optional_enum == :Default
+    end
+
+    def test_setters
+      m = TestMessage.new
+      m.optional_int32 = -42
+      assert m.optional_int32 == -42
+      m.optional_int64 = -0x1_0000_0000
+      assert m.optional_int64 == -0x1_0000_0000
+      m.optional_uint32 = 0x9000_0000
+      assert m.optional_uint32 == 0x9000_0000
+      m.optional_uint64 = 0x9000_0000_0000_0000
+      assert m.optional_uint64 == 0x9000_0000_0000_0000
+      m.optional_bool = true
+      assert m.optional_bool == true
+      m.optional_float = 0.5
+      assert m.optional_float == 0.5
+      m.optional_double = 0.5
+      m.optional_string = "hello"
+      assert m.optional_string == "hello"
+      m.optional_bytes = "world".encode!('ASCII-8BIT')
+      assert m.optional_bytes == "world"
+      m.optional_msg = TestMessage2.new(:foo => 42)
+      assert m.optional_msg == TestMessage2.new(:foo => 42)
+      m.optional_msg = nil
+      assert m.optional_msg == nil
+    end
+
+    def test_ctor_args
+      m = TestMessage.new(:optional_int32 => -42,
+                          :optional_msg => TestMessage2.new,
+                          :optional_enum => :C,
+                          :repeated_string => ["hello", "there", "world"])
+      assert m.optional_int32 == -42
+      assert m.optional_msg.class == TestMessage2
+      assert m.repeated_string.length == 3
+      assert m.optional_enum == :C
+      assert m.repeated_string[0] == "hello"
+      assert m.repeated_string[1] == "there"
+      assert m.repeated_string[2] == "world"
+    end
+
+    def test_inspect
+      m = TestMessage.new(:optional_int32 => -42,
+                          :optional_enum => :A,
+                          :optional_msg => TestMessage2.new,
+                          :repeated_string => ["hello", "there", "world"])
+      expected = '<BasicTest::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: "", optional_bytes: "", optional_msg: <BasicTest::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: ["hello", "there", "world"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>'
+      assert_equal expected, m.inspect
+    end
+
+    def test_hash
+      m1 = TestMessage.new(:optional_int32 => 42)
+      m2 = TestMessage.new(:optional_int32 => 102)
+      assert m1.hash != 0
+      assert m2.hash != 0
+      # relying on the randomness here -- if hash function changes and we are
+      # unlucky enough to get a collision, then change the values above.
+      assert m1.hash != m2.hash
+    end
+
+    def test_unknown_field_errors
+      e = assert_raise NoMethodError do
+        TestMessage.new.hello
+      end
+      assert_match(/hello/, e.message)
+
+      e = assert_raise NoMethodError do
+        TestMessage.new.hello = "world"
+      end
+      assert_match(/hello/, e.message)
+    end
+
+    def test_initialization_map_errors
+      e = assert_raise ArgumentError do
+        TestMessage.new(:hello => "world")
+      end
+      assert_match(/hello/, e.message)
+
+      e = assert_raise ArgumentError do
+        MapMessage.new(:map_string_int32 => "hello")
+      end
+      assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'."
+
+      e = assert_raise ArgumentError do
+        TestMessage.new(:repeated_uint32 => "hello")
+      end
+      assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'."
+    end
+
+    def test_type_errors
+      m = TestMessage.new
+      assert_raise TypeError do
+        m.optional_int32 = "hello"
+      end
+      assert_raise TypeError do
+        m.optional_string = 42
+      end
+      assert_raise TypeError do
+        m.optional_string = nil
+      end
+      assert_raise TypeError do
+        m.optional_bool = 42
+      end
+      assert_raise TypeError do
+        m.optional_msg = TestMessage.new  # expects TestMessage2
+      end
+
+      assert_raise TypeError do
+        m.repeated_int32 = []  # needs RepeatedField
+      end
+
+      assert_raise TypeError do
+        m.repeated_int32.push "hello"
+      end
+
+      assert_raise TypeError do
+        m.repeated_msg.push TestMessage.new
+      end
+    end
+
+    def test_string_encoding
+      m = TestMessage.new
+
+      # Assigning a normal (ASCII or UTF8) string to a bytes field, or
+      # ASCII-8BIT to a string field, raises an error.
+      assert_raise TypeError do
+        m.optional_bytes = "Test string ASCII".encode!('ASCII')
+      end
+      assert_raise TypeError do
+        m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
+      end
+      assert_raise TypeError do
+        m.optional_string = ["FFFF"].pack('H*')
+      end
+
+      # "Ordinary" use case.
+      m.optional_bytes = ["FFFF"].pack('H*')
+      m.optional_string = "\u0100"
+
+      # strings are mutable so we can do this, but serialize should catch it.
+      m.optional_string = "asdf".encode!('UTF-8')
+      m.optional_string.encode!('ASCII-8BIT')
+      assert_raise TypeError do
+        data = TestMessage.encode(m)
+      end
+    end
+
+    def test_rptfield_int32
+      l = Google::Protobuf::RepeatedField.new(:int32)
+      assert l.count == 0
+      l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
+      assert l.count == 3
+      assert_equal [1, 2, 3], l
+      assert_equal l, [1, 2, 3]
+      l.push 4
+      assert l == [1, 2, 3, 4]
+      dst_list = []
+      l.each { |val| dst_list.push val }
+      assert dst_list == [1, 2, 3, 4]
+      assert l.to_a == [1, 2, 3, 4]
+      assert l[0] == 1
+      assert l[3] == 4
+      l[0] = 5
+      assert l == [5, 2, 3, 4]
+
+      l2 = l.dup
+      assert l == l2
+      assert l.object_id != l2.object_id
+      l2.push 6
+      assert l.count == 4
+      assert l2.count == 5
+
+      assert l.inspect == '[5, 2, 3, 4]'
+
+      l.concat([7, 8, 9])
+      assert l == [5, 2, 3, 4, 7, 8, 9]
+      assert l.pop == 9
+      assert l == [5, 2, 3, 4, 7, 8]
+
+      assert_raise TypeError do
+        m = TestMessage.new
+        l.push m
+      end
+
+      m = TestMessage.new
+      m.repeated_int32 = l
+      assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
+      assert m.repeated_int32.object_id == l.object_id
+      l.push 42
+      assert m.repeated_int32.pop == 42
+
+      l3 = l + l.dup
+      assert l3.count == l.count * 2
+      l.count.times do |i|
+        assert l3[i] == l[i]
+        assert l3[l.count + i] == l[i]
+      end
+
+      l.clear
+      assert l.count == 0
+      l += [1, 2, 3, 4]
+      l.replace([5, 6, 7, 8])
+      assert l == [5, 6, 7, 8]
+
+      l4 = Google::Protobuf::RepeatedField.new(:int32)
+      l4[5] = 42
+      assert l4 == [0, 0, 0, 0, 0, 42]
+
+      l4 << 100
+      assert l4 == [0, 0, 0, 0, 0, 42, 100]
+      l4 << 101 << 102
+      assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
+    end
+
+    def test_parent_rptfield
+      #make sure we set the RepeatedField and can add to it
+      m = TestMessage.new
+      assert m.repeated_string == []
+      m.repeated_string << 'ok'
+      m.repeated_string.push('ok2')
+      assert m.repeated_string == ['ok', 'ok2']
+      m.repeated_string += ['ok3']
+      assert m.repeated_string == ['ok', 'ok2', 'ok3']
+    end
+
+    def test_rptfield_msg
+      l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
+      l.push TestMessage.new
+      assert l.count == 1
+      assert_raise TypeError do
+        l.push TestMessage2.new
+      end
+      assert_raise TypeError do
+        l.push 42
+      end
+
+      l2 = l.dup
+      assert l2[0] == l[0]
+      assert l2[0].object_id == l[0].object_id
+
+      l2 = Google::Protobuf.deep_copy(l)
+      assert l2[0] == l[0]
+      assert l2[0].object_id != l[0].object_id
+
+      l3 = l + l2
+      assert l3.count == 2
+      assert l3[0] == l[0]
+      assert l3[1] == l2[0]
+      l3[0].optional_int32 = 1000
+      assert l[0].optional_int32 == 1000
+
+      new_msg = TestMessage.new(:optional_int32 => 200)
+      l4 = l + [new_msg]
+      assert l4.count == 2
+      new_msg.optional_int32 = 1000
+      assert l4[1].optional_int32 == 1000
+    end
+
+    def test_rptfield_enum
+      l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
+      l.push :A
+      l.push :B
+      l.push :C
+      assert l.count == 3
+      assert_raise RangeError do
+        l.push :D
+      end
+      assert l[0] == :A
+
+      l.push 4
+      assert l[3] == 4
+    end
+
+    def test_rptfield_initialize
+      assert_raise ArgumentError do
+        l = Google::Protobuf::RepeatedField.new
+      end
+      assert_raise ArgumentError do
+        l = Google::Protobuf::RepeatedField.new(:message)
+      end
+      assert_raise ArgumentError do
+        l = Google::Protobuf::RepeatedField.new([1, 2, 3])
+      end
+      assert_raise ArgumentError do
+        l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
+      end
+    end
+
+    def test_rptfield_array_ducktyping
+      l = Google::Protobuf::RepeatedField.new(:int32)
+      length_methods = %w(count length size)
+      length_methods.each do |lm|
+        assert l.send(lm)  == 0
+      end
+      # out of bounds returns a nil
+      assert l[0] == nil
+      assert l[1] == nil
+      assert l[-1] == nil
+      l.push 4
+      length_methods.each do |lm|
+        assert l.send(lm) == 1
+      end
+      assert l[0] == 4
+      assert l[1] == nil
+      assert l[-1] == 4
+      assert l[-2] == nil
+
+      l.push 2
+      length_methods.each do |lm|
+        assert l.send(lm) == 2
+      end
+      assert l[0] == 4
+      assert l[1] == 2
+      assert l[2] == nil
+      assert l[-1] == 2
+      assert l[-2] == 4
+      assert l[-3] == nil
+
+      #adding out of scope will backfill with empty objects
+    end
+
+    def test_map_basic
+      # allowed key types:
+      # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
+
+      m = Google::Protobuf::Map.new(:string, :int32)
+      m["asdf"] = 1
+      assert m["asdf"] == 1
+      m["jkl;"] = 42
+      assert m == { "jkl;" => 42, "asdf" => 1 }
+      assert m.has_key?("asdf")
+      assert !m.has_key?("qwerty")
+      assert m.length == 2
+
+      m2 = m.dup
+      assert m == m2
+      assert m.hash != 0
+      assert m.hash == m2.hash
+
+      collected = {}
+      m.each { |k,v| collected[v] = k }
+      assert collected == { 42 => "jkl;", 1 => "asdf" }
+
+      assert m.delete("asdf") == 1
+      assert !m.has_key?("asdf")
+      assert m["asdf"] == nil
+      assert !m.has_key?("asdf")
+
+      # We only assert on inspect value when there is one map entry because the
+      # order in which elements appear is unspecified (depends on the internal
+      # hash function). We don't want a brittle test.
+      assert m.inspect == "{\"jkl;\"=>42}"
+
+      assert m.keys == ["jkl;"]
+      assert m.values == [42]
+
+      m.clear
+      assert m.length == 0
+      assert m == {}
+
+      assert_raise TypeError do
+        m[1] = 1
+      end
+      assert_raise RangeError do
+        m["asdf"] = 0x1_0000_0000
+      end
+    end
+
+    def test_map_ctor
+      m = Google::Protobuf::Map.new(:string, :int32,
+                                    {"a" => 1, "b" => 2, "c" => 3})
+      assert m == {"a" => 1, "c" => 3, "b" => 2}
+    end
+
+    def test_map_keytypes
+      m = Google::Protobuf::Map.new(:int32, :int32)
+      m[1] = 42
+      m[-1] = 42
+      assert_raise RangeError do
+        m[0x8000_0000] = 1
+      end
+      assert_raise TypeError do
+        m["asdf"] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:int64, :int32)
+      m[0x1000_0000_0000_0000] = 1
+      assert_raise RangeError do
+        m[0x1_0000_0000_0000_0000] = 1
+      end
+      assert_raise TypeError do
+        m["asdf"] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:uint32, :int32)
+      m[0x8000_0000] = 1
+      assert_raise RangeError do
+        m[0x1_0000_0000] = 1
+      end
+      assert_raise RangeError do
+        m[-1] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:uint64, :int32)
+      m[0x8000_0000_0000_0000] = 1
+      assert_raise RangeError do
+        m[0x1_0000_0000_0000_0000] = 1
+      end
+      assert_raise RangeError do
+        m[-1] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:bool, :int32)
+      m[true] = 1
+      m[false] = 2
+      assert_raise TypeError do
+        m[1] = 1
+      end
+      assert_raise TypeError do
+        m["asdf"] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:string, :int32)
+      m["asdf"] = 1
+      assert_raise TypeError do
+        m[1] = 1
+      end
+      assert_raise TypeError do
+        bytestring = ["FFFF"].pack("H*")
+        m[bytestring] = 1
+      end
+
+      m = Google::Protobuf::Map.new(:bytes, :int32)
+      bytestring = ["FFFF"].pack("H*")
+      m[bytestring] = 1
+      assert_raise TypeError do
+        m["asdf"] = 1
+      end
+      assert_raise TypeError do
+        m[1] = 1
+      end
+    end
+
+    def test_map_msg_enum_valuetypes
+      m = Google::Protobuf::Map.new(:string, :message, TestMessage)
+      m["asdf"] = TestMessage.new
+      assert_raise TypeError do
+        m["jkl;"] = TestMessage2.new
+      end
+
+      m = Google::Protobuf::Map.new(
+        :string, :message, TestMessage,
+        { "a" => TestMessage.new(:optional_int32 => 42),
+          "b" => TestMessage.new(:optional_int32 => 84) })
+      assert m.length == 2
+      assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
+
+      m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
+                                    { "x" => :A, "y" => :B, "z" => :C })
+      assert m.length == 3
+      assert m["z"] == :C
+      m["z"] = 2
+      assert m["z"] == :B
+      m["z"] = 4
+      assert m["z"] == 4
+      assert_raise RangeError do
+        m["z"] = :Z
+      end
+      assert_raise TypeError do
+        m["z"] = "z"
+      end
+    end
+
+    def test_map_dup_deep_copy
+      m = Google::Protobuf::Map.new(
+        :string, :message, TestMessage,
+        { "a" => TestMessage.new(:optional_int32 => 42),
+          "b" => TestMessage.new(:optional_int32 => 84) })
+
+      m2 = m.dup
+      assert m == m2
+      assert m.object_id != m2.object_id
+      assert m["a"].object_id == m2["a"].object_id
+      assert m["b"].object_id == m2["b"].object_id
+
+      m2 = Google::Protobuf.deep_copy(m)
+      assert m == m2
+      assert m.object_id != m2.object_id
+      assert m["a"].object_id != m2["a"].object_id
+      assert m["b"].object_id != m2["b"].object_id
+    end
+
+    def test_map_field
+      m = MapMessage.new
+      assert m.map_string_int32 == {}
+      assert m.map_string_msg == {}
+
+      m = MapMessage.new(
+        :map_string_int32 => {"a" => 1, "b" => 2},
+        :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
+                            "b" => TestMessage2.new(:foo => 2)})
+      assert m.map_string_int32.keys.sort == ["a", "b"]
+      assert m.map_string_int32["a"] == 1
+      assert m.map_string_msg["b"].foo == 2
+
+      m.map_string_int32["c"] = 3
+      assert m.map_string_int32["c"] == 3
+      m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
+      assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
+      m.map_string_msg.delete("b")
+      m.map_string_msg.delete("c")
+      assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
+
+      assert_raise TypeError do
+        m.map_string_msg["e"] = TestMessage.new # wrong value type
+      end
+      # ensure nothing was added by the above
+      assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
+
+      m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
+      assert_raise TypeError do
+        m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
+      end
+      assert_raise TypeError do
+        m.map_string_int32 = {}
+      end
+
+      assert_raise TypeError do
+        m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
+      end
+    end
+
+    def test_map_encode_decode
+      m = MapMessage.new(
+        :map_string_int32 => {"a" => 1, "b" => 2},
+        :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
+                            "b" => TestMessage2.new(:foo => 2)})
+      m2 = MapMessage.decode(MapMessage.encode(m))
+      assert m == m2
+
+      m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
+      assert m3.map_string_int32.length == 2
+
+      kv = {}
+      m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
+      assert kv == {"a" => 1, "b" => 2}
+
+      kv = {}
+      m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
+      assert kv == {"a" => TestMessage2.new(:foo => 1),
+                    "b" => TestMessage2.new(:foo => 2)}
+    end
+
+    def test_oneof_descriptors
+      d = OneofMessage.descriptor
+      o = d.lookup_oneof("my_oneof")
+      assert o != nil
+      assert o.class == Google::Protobuf::OneofDescriptor
+      assert o.name == "my_oneof"
+      oneof_count = 0
+      d.each_oneof{ |oneof|
+        oneof_count += 1
+        assert oneof == o
+      }
+      assert oneof_count == 1
+      assert o.count == 4
+      field_names = o.map{|f| f.name}.sort
+      assert field_names == ["a", "b", "c", "d"]
+    end
+
+    def test_oneof
+      d = OneofMessage.new
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == nil
+
+      d.a = "hi"
+      assert d.a == "hi"
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == :a
+
+      d.b = 42
+      assert d.a == nil
+      assert d.b == 42
+      assert d.c == nil
+      assert d.d == nil
+      assert d.my_oneof == :b
+
+      d.c = TestMessage2.new(:foo => 100)
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c.foo == 100
+      assert d.d == nil
+      assert d.my_oneof == :c
+
+      d.d = :C
+      assert d.a == nil
+      assert d.b == nil
+      assert d.c == nil
+      assert d.d == :C
+      assert d.my_oneof == :d
+
+      d2 = OneofMessage.decode(OneofMessage.encode(d))
+      assert d2 == d
+
+      encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
+      encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
+      encoded_field_c = OneofMessage.encode(
+        OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
+      encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
+
+      d3 = OneofMessage.decode(
+        encoded_field_c + encoded_field_a + encoded_field_d)
+      assert d3.a == nil
+      assert d3.b == nil
+      assert d3.c == nil
+      assert d3.d == :B
+
+      d4 = OneofMessage.decode(
+        encoded_field_c + encoded_field_a + encoded_field_d +
+        encoded_field_c)
+      assert d4.a == nil
+      assert d4.b == nil
+      assert d4.c.foo == 1
+      assert d4.d == nil
+
+      d5 = OneofMessage.new(:a => "hello")
+      assert d5.a != nil
+      d5.a = nil
+      assert d5.a == nil
+      assert OneofMessage.encode(d5) == ''
+      assert d5.my_oneof == nil
+    end
+
+    def test_enum_field
+      m = TestMessage.new
+      assert m.optional_enum == :Default
+      m.optional_enum = :A
+      assert m.optional_enum == :A
+      assert_raise RangeError do
+        m.optional_enum = :ASDF
+      end
+      m.optional_enum = 1
+      assert m.optional_enum == :A
+      m.optional_enum = 100
+      assert m.optional_enum == 100
+    end
+
+    def test_dup
+      m = TestMessage.new
+      m.optional_string = "hello"
+      m.optional_int32 = 42
+      tm1 = TestMessage2.new(:foo => 100)
+      tm2 = TestMessage2.new(:foo => 200)
+      m.repeated_msg.push tm1
+      assert m.repeated_msg[-1] == tm1
+      m.repeated_msg.push tm2
+      assert m.repeated_msg[-1] == tm2
+      m2 = m.dup
+      assert m == m2
+      m.optional_int32 += 1
+      assert m != m2
+      assert m.repeated_msg[0] == m2.repeated_msg[0]
+      assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
+    end
+
+    def test_deep_copy
+      m = TestMessage.new(:optional_int32 => 42,
+                          :repeated_msg => [TestMessage2.new(:foo => 100)])
+      m2 = Google::Protobuf.deep_copy(m)
+      assert m == m2
+      assert m.repeated_msg == m2.repeated_msg
+      assert m.repeated_msg.object_id != m2.repeated_msg.object_id
+      assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
+    end
+
+    def test_eq
+      m = TestMessage.new(:optional_int32 => 42,
+                          :repeated_int32 => [1, 2, 3])
+      m2 = TestMessage.new(:optional_int32 => 43,
+                           :repeated_int32 => [1, 2, 3])
+      assert m != m2
+    end
+
+    def test_enum_lookup
+      assert TestEnum::A == 1
+      assert TestEnum::B == 2
+      assert TestEnum::C == 3
+
+      assert TestEnum::lookup(1) == :A
+      assert TestEnum::lookup(2) == :B
+      assert TestEnum::lookup(3) == :C
+
+      assert TestEnum::resolve(:A) == 1
+      assert TestEnum::resolve(:B) == 2
+      assert TestEnum::resolve(:C) == 3
+    end
+
+    def test_parse_serialize
+      m = TestMessage.new(:optional_int32 => 42,
+                          :optional_string => "hello world",
+                          :optional_enum => :B,
+                          :repeated_string => ["a", "b", "c"],
+                          :repeated_int32 => [42, 43, 44],
+                          :repeated_enum => [:A, :B, :C, 100],
+                          :repeated_msg => [TestMessage2.new(:foo => 1),
+                                            TestMessage2.new(:foo => 2)])
+      data = TestMessage.encode m
+      m2 = TestMessage.decode data
+      assert m == m2
+
+      data = Google::Protobuf.encode m
+      m2 = Google::Protobuf.decode(TestMessage, data)
+      assert m == m2
+    end
+
+    def test_encode_decode_helpers
+      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+      json = m.to_json
+      m2 = TestMessage.decode_json(json)
+      assert m2.optional_string == 'foo'
+      assert m2.repeated_string == ['bar1', 'bar2']
+
+      proto = m.to_proto
+      m2 = TestMessage.decode(proto)
+      assert m2.optional_string == 'foo'
+      assert m2.repeated_string == ['bar1', 'bar2']
+    end
+
+    def test_protobuf_encode_decode_helpers
+      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+      encoded_msg = Google::Protobuf.encode(m)
+      assert_equal m.to_proto, encoded_msg
+
+      decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
+      assert_equal TestMessage.decode(m.to_proto), decoded_msg
+    end
+
+    def test_protobuf_encode_decode_json_helpers
+      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+      encoded_msg = Google::Protobuf.encode_json(m)
+      assert_equal m.to_json, encoded_msg
+
+      decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
+      assert_equal TestMessage.decode_json(m.to_json), decoded_msg
+    end
+
+    def test_to_h
+      m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+      expected_result = {
+        :optional_bool=>true,
+        :optional_bytes=>"",
+        :optional_double=>-10.100001,
+        :optional_enum=>:Default,
+        :optional_float=>0.0,
+        :optional_int32=>0,
+        :optional_int64=>0,
+        :optional_msg=>nil,
+        :optional_string=>"foo",
+        :optional_uint32=>0,
+        :optional_uint64=>0,
+        :repeated_bool=>[],
+        :repeated_bytes=>[],
+        :repeated_double=>[],
+        :repeated_enum=>[],
+        :repeated_float=>[],
+        :repeated_int32=>[],
+        :repeated_int64=>[],
+        :repeated_msg=>[],
+        :repeated_string=>["bar1", "bar2"],
+        :repeated_uint32=>[],
+        :repeated_uint64=>[]
+      }
+      assert_equal expected_result, m.to_h
+    end
+
+
+    def test_def_errors
+      s = Google::Protobuf::DescriptorPool.new
+      assert_raise TypeError do
+        s.build do
+          # enum with no default (integer value 0)
+          add_enum "MyEnum" do
+            value :A, 1
+          end
+        end
+      end
+      assert_raise TypeError do
+        s.build do
+          # message with required field (unsupported in proto3)
+          add_message "MyMessage" do
+            required :foo, :int32, 1
+          end
+        end
+      end
+    end
+
+    def test_corecursive
+      # just be sure that we can instantiate types with corecursive field-type
+      # references.
+      m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
+      assert Recursive1.descriptor.lookup("foo").subtype ==
+        Recursive2.descriptor
+      assert Recursive2.descriptor.lookup("foo").subtype ==
+        Recursive1.descriptor
+
+      serialized = Recursive1.encode(m)
+      m2 = Recursive1.decode(serialized)
+      assert m == m2
+    end
+
+    def test_serialize_cycle
+      m = Recursive1.new(:foo => Recursive2.new)
+      m.foo.foo = m
+      assert_raise RuntimeError do
+        serialized = Recursive1.encode(m)
+      end
+    end
+
+    def test_bad_field_names
+      m = BadFieldNames.new(:dup => 1, :class => 2)
+      m2 = m.dup
+      assert m == m2
+      assert m['dup'] == 1
+      assert m['class'] == 2
+      m['dup'] = 3
+      assert m['dup'] == 3
+      m['a.b'] = 4
+      assert m['a.b'] == 4
+    end
+
+    def test_int_ranges
+      m = TestMessage.new
+
+      m.optional_int32 = 0
+      m.optional_int32 = -0x8000_0000
+      m.optional_int32 = +0x7fff_ffff
+      m.optional_int32 = 1.0
+      m.optional_int32 = -1.0
+      m.optional_int32 = 2e9
+      assert_raise RangeError do
+        m.optional_int32 = -0x8000_0001
+      end
+      assert_raise RangeError do
+        m.optional_int32 = +0x8000_0000
+      end
+      assert_raise RangeError do
+        m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+      end
+      assert_raise RangeError do
+        m.optional_int32 = 1e12
+      end
+      assert_raise RangeError do
+        m.optional_int32 = 1.5
+      end
+
+      m.optional_uint32 = 0
+      m.optional_uint32 = +0xffff_ffff
+      m.optional_uint32 = 1.0
+      m.optional_uint32 = 4e9
+      assert_raise RangeError do
+        m.optional_uint32 = -1
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = -1.5
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = -1.5e12
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = -0x1000_0000_0000_0000
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = +0x1_0000_0000
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = 1e12
+      end
+      assert_raise RangeError do
+        m.optional_uint32 = 1.5
+      end
+
+      m.optional_int64 = 0
+      m.optional_int64 = -0x8000_0000_0000_0000
+      m.optional_int64 = +0x7fff_ffff_ffff_ffff
+      m.optional_int64 = 1.0
+      m.optional_int64 = -1.0
+      m.optional_int64 = 8e18
+      m.optional_int64 = -8e18
+      assert_raise RangeError do
+        m.optional_int64 = -0x8000_0000_0000_0001
+      end
+      assert_raise RangeError do
+        m.optional_int64 = +0x8000_0000_0000_0000
+      end
+      assert_raise RangeError do
+        m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+      end
+      assert_raise RangeError do
+        m.optional_int64 = 1e50
+      end
+      assert_raise RangeError do
+        m.optional_int64 = 1.5
+      end
+
+      m.optional_uint64 = 0
+      m.optional_uint64 = +0xffff_ffff_ffff_ffff
+      m.optional_uint64 = 1.0
+      m.optional_uint64 = 16e18
+      assert_raise RangeError do
+        m.optional_uint64 = -1
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = -1.5
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = -1.5e12
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = -0x1_0000_0000_0000_0000
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = +0x1_0000_0000_0000_0000
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = 1e50
+      end
+      assert_raise RangeError do
+        m.optional_uint64 = 1.5
+      end
+    end
+
+    def test_stress_test
+      m = TestMessage.new
+      m.optional_int32 = 42
+      m.optional_int64 = 0x100000000
+      m.optional_string = "hello world"
+      10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
+      10.times do m.repeated_string.push "hello world" end
+
+      data = TestMessage.encode(m)
+
+      l = 0
+      10_000.times do
+        m = TestMessage.decode(data)
+        data_new = TestMessage.encode(m)
+        assert data_new == data
+        data = data_new
+      end
+    end
+
+    def test_reflection
+      m = TestMessage.new(:optional_int32 => 1234)
+      msgdef = m.class.descriptor
+      assert msgdef.class == Google::Protobuf::Descriptor
+      assert msgdef.any? {|field| field.name == "optional_int32"}
+      optional_int32 = msgdef.lookup "optional_int32"
+      assert optional_int32.class == Google::Protobuf::FieldDescriptor
+      assert optional_int32 != nil
+      assert optional_int32.name == "optional_int32"
+      assert optional_int32.type == :int32
+      optional_int32.set(m, 5678)
+      assert m.optional_int32 == 5678
+      m.optional_int32 = 1000
+      assert optional_int32.get(m) == 1000
+
+      optional_msg = msgdef.lookup "optional_msg"
+      assert optional_msg.subtype == TestMessage2.descriptor
+
+      optional_msg.set(m, optional_msg.subtype.msgclass.new)
+
+      assert msgdef.msgclass == TestMessage
+
+      optional_enum = msgdef.lookup "optional_enum"
+      assert optional_enum.subtype == TestEnum.descriptor
+      assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
+      optional_enum.subtype.each do |k, v|
+        # set with integer, check resolution to symbolic name
+        optional_enum.set(m, v)
+        assert optional_enum.get(m) == k
+      end
+    end
+
+    def test_json
+      # TODO: Fix JSON in JRuby version.
+      return if RUBY_PLATFORM == "java"
+      m = TestMessage.new(:optional_int32 => 1234,
+                          :optional_int64 => -0x1_0000_0000,
+                          :optional_uint32 => 0x8000_0000,
+                          :optional_uint64 => 0xffff_ffff_ffff_ffff,
+                          :optional_bool => true,
+                          :optional_float => 1.0,
+                          :optional_double => -1e100,
+                          :optional_string => "Test string",
+                          :optional_bytes => ["FFFFFFFF"].pack('H*'),
+                          :optional_msg => TestMessage2.new(:foo => 42),
+                          :repeated_int32 => [1, 2, 3, 4],
+                          :repeated_string => ["a", "b", "c"],
+                          :repeated_bool => [true, false, true, false],
+                          :repeated_msg => [TestMessage2.new(:foo => 1),
+                                            TestMessage2.new(:foo => 2)])
+
+      json_text = TestMessage.encode_json(m)
+      m2 = TestMessage.decode_json(json_text)
+      assert m == m2
+
+      # Crash case from GitHub issue 283.
+      bar = Bar.new(msg: "bar")
+      baz1 = Baz.new(msg: "baz")
+      baz2 = Baz.new(msg: "quux")
+      Foo.encode_json(Foo.new)
+      Foo.encode_json(Foo.new(bar: bar))
+      Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
+    end
+
+    def test_json_maps
+      # TODO: Fix JSON in JRuby version.
+      return if RUBY_PLATFORM == "java"
+      m = MapMessage.new(:map_string_int32 => {"a" => 1})
+      expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
+      expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
+      assert MapMessage.encode_json(m) == expected
+
+      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
+      assert json == expected_preserve
+
+      m2 = MapMessage.decode_json(MapMessage.encode_json(m))
+      assert m == m2
+    end
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/tests/generated_code.proto b/src/third_party/protobuf-3/ruby/tests/generated_code.proto
new file mode 100644
index 0000000..42d82a6
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/tests/generated_code.proto
@@ -0,0 +1,67 @@
+syntax = "proto3";
+
+package A.B.C;
+
+message TestMessage {
+  int32 optional_int32 = 1;
+  int64 optional_int64 = 2;
+  uint32 optional_uint32 = 3;
+  uint64 optional_uint64 = 4;
+  bool optional_bool = 5;
+  double optional_double = 6;
+  float optional_float = 7;
+  string optional_string = 8;
+  bytes optional_bytes = 9;
+  TestEnum optional_enum = 10;
+  TestMessage optional_msg = 11;
+
+  repeated int32 repeated_int32 = 21;
+  repeated int64 repeated_int64 = 22;
+  repeated uint32 repeated_uint32 = 23;
+  repeated uint64 repeated_uint64 = 24;
+  repeated bool repeated_bool = 25;
+  repeated double repeated_double = 26;
+  repeated float repeated_float = 27;
+  repeated string repeated_string = 28;
+  repeated bytes repeated_bytes = 29;
+  repeated TestEnum repeated_enum = 30;
+  repeated TestMessage repeated_msg = 31;
+
+  oneof my_oneof {
+    int32 oneof_int32 = 41;
+    int64 oneof_int64 = 42;
+    uint32 oneof_uint32 = 43;
+    uint64 oneof_uint64 = 44;
+    bool oneof_bool = 45;
+    double oneof_double = 46;
+    float oneof_float = 47;
+    string oneof_string = 48;
+    bytes oneof_bytes = 49;
+    TestEnum oneof_enum = 50;
+    TestMessage oneof_msg = 51;
+  }
+
+  map<int32, string> map_int32_string = 61;
+  map<int64, string> map_int64_string = 62;
+  map<uint32, string> map_uint32_string = 63;
+  map<uint64, string> map_uint64_string = 64;
+  map<bool, string> map_bool_string = 65;
+  map<string, string> map_string_string = 66;
+  map<string, TestMessage> map_string_msg = 67;
+  map<string, TestEnum> map_string_enum = 68;
+  map<string, int32> map_string_int32 = 69;
+  map<string, bool> map_string_bool = 70;
+
+  message NestedMessage {
+    int32 foo = 1;
+  }
+
+  NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+  Default = 0;
+  A = 1;
+  B = 2;
+  C = 3;
+}
diff --git a/src/third_party/protobuf-3/ruby/tests/generated_code_test.rb b/src/third_party/protobuf-3/ruby/tests/generated_code_test.rb
new file mode 100644
index 0000000..daef357
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/tests/generated_code_test.rb
@@ -0,0 +1,17 @@
+#!/usr/bin/ruby
+
+# generated_code.rb is in the same directory as this test.
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
+
+require 'generated_code'
+require 'test/unit'
+
+class GeneratedCodeTest < Test::Unit::TestCase
+  def test_generated_msg
+    # just test that we can instantiate the message. The purpose of this test
+    # is to ensure that the output of the code generator is valid Ruby and
+    # successfully creates message definitions and classes, not to test every
+    # aspect of the extension (basic.rb is for that).
+    m = A::B::C::TestMessage.new()
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/tests/repeated_field_test.rb b/src/third_party/protobuf-3/ruby/tests/repeated_field_test.rb
new file mode 100644
index 0000000..25727b7
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/tests/repeated_field_test.rb
@@ -0,0 +1,640 @@
+#!/usr/bin/ruby
+
+require 'google/protobuf'
+require 'test/unit'
+
+class RepeatedFieldTest < Test::Unit::TestCase
+
+  def test_acts_like_enumerator
+    m = TestMessage.new
+    (Enumerable.instance_methods - TestMessage.new.repeated_string.methods).each do |method_name|
+      assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
+    end
+  end
+
+  def test_acts_like_an_array
+    m = TestMessage.new
+    arr_methods = ([].methods - TestMessage.new.repeated_string.methods)
+    # jRuby additions to the Array class that we can ignore
+    arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,
+      :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
+      :nitems, :iter_for_reverse_each, :indexes]
+    arr_methods.each do |method_name|
+      assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
+    end
+  end
+
+  def test_first
+    m = TestMessage.new
+    repeated_field_names(TestMessage).each do |field_name|
+      assert_nil m.send(field_name).first
+    end
+    fill_test_msg(m)
+    assert_equal -10, m.repeated_int32.first
+    assert_equal -1_000_000, m.repeated_int64.first
+    assert_equal 10, m.repeated_uint32.first
+    assert_equal 1_000_000, m.repeated_uint64.first
+    assert_equal true, m.repeated_bool.first
+    assert_equal -1.01,  m.repeated_float.first.round(2)
+    assert_equal -1.0000000000001, m.repeated_double.first
+    assert_equal 'foo', m.repeated_string.first
+    assert_equal "bar".encode!('ASCII-8BIT'), m.repeated_bytes.first
+    assert_equal TestMessage2.new(:foo => 1), m.repeated_msg.first
+    assert_equal :A, m.repeated_enum.first
+  end
+
+
+  def test_last
+    m = TestMessage.new
+    repeated_field_names(TestMessage).each do |field_name|
+      assert_nil m.send(field_name).first
+    end
+    fill_test_msg(m)
+    assert_equal -11, m.repeated_int32.last
+    assert_equal -1_000_001, m.repeated_int64.last
+    assert_equal 11, m.repeated_uint32.last
+    assert_equal 1_000_001, m.repeated_uint64.last
+    assert_equal false, m.repeated_bool.last
+    assert_equal -1.02, m.repeated_float.last.round(2)
+    assert_equal -1.0000000000002, m.repeated_double.last
+    assert_equal 'bar', m.repeated_string.last
+    assert_equal "foo".encode!('ASCII-8BIT'), m.repeated_bytes.last
+    assert_equal TestMessage2.new(:foo => 2), m.repeated_msg.last
+    assert_equal :B, m.repeated_enum.last
+  end
+
+
+  def test_pop
+    m = TestMessage.new
+    repeated_field_names(TestMessage).each do |field_name|
+      assert_nil m.send(field_name).pop
+    end
+    fill_test_msg(m)
+
+    assert_equal -11, m.repeated_int32.pop
+    assert_equal -10, m.repeated_int32.pop
+    assert_equal -1_000_001, m.repeated_int64.pop
+    assert_equal -1_000_000, m.repeated_int64.pop
+    assert_equal 11, m.repeated_uint32.pop
+    assert_equal 10, m.repeated_uint32.pop
+    assert_equal 1_000_001, m.repeated_uint64.pop
+    assert_equal 1_000_000, m.repeated_uint64.pop
+    assert_equal false, m.repeated_bool.pop
+    assert_equal true, m.repeated_bool.pop
+    assert_equal -1.02,  m.repeated_float.pop.round(2)
+    assert_equal -1.01,  m.repeated_float.pop.round(2)
+    assert_equal -1.0000000000002, m.repeated_double.pop
+    assert_equal -1.0000000000001, m.repeated_double.pop
+    assert_equal 'bar', m.repeated_string.pop
+    assert_equal 'foo', m.repeated_string.pop
+    assert_equal "foo".encode!('ASCII-8BIT'), m.repeated_bytes.pop
+    assert_equal "bar".encode!('ASCII-8BIT'), m.repeated_bytes.pop
+    assert_equal TestMessage2.new(:foo => 2), m.repeated_msg.pop
+    assert_equal TestMessage2.new(:foo => 1), m.repeated_msg.pop
+    assert_equal :B, m.repeated_enum.pop
+    assert_equal :A, m.repeated_enum.pop
+    repeated_field_names(TestMessage).each do |field_name|
+      assert_nil m.send(field_name).pop
+    end
+
+    fill_test_msg(m)
+    assert_equal ['bar', 'foo'], m.repeated_string.pop(2)
+    assert_nil m.repeated_string.pop
+  end
+
+
+  def test_each
+    m = TestMessage.new
+    5.times{|i| m.repeated_string << 'string' }
+    count = 0
+    m.repeated_string.each do |val|
+      assert_equal 'string', val
+      count += 1
+    end
+    assert_equal 5, count
+    result = m.repeated_string.each{|val| val + '_junk'}
+    assert_equal ['string'] * 5, result
+  end
+
+
+  def test_empty?
+    m = TestMessage.new
+    assert_equal true, m.repeated_string.empty?
+    m.repeated_string << 'foo'
+    assert_equal false, m.repeated_string.empty?
+    m.repeated_string << 'bar'
+    assert_equal false, m.repeated_string.empty?
+  end
+
+  def test_array_accessor
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[1]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[-2]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[20]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[1, 2]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[0..2]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[-1, 1]
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[10, 12]
+    end
+  end
+
+  def test_array_settor
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[1] = 'junk'
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[-2] = 'snappy'
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr[3] = ''
+    end
+    # slight deviation; we are strongly typed, and nil is not allowed
+    # for string types;
+    m.repeated_string[5] = 'spacious'
+    assert_equal ["foo", "snappy", "baz", "", "", "spacious"], m.repeated_string
+
+    #make sure it sests the default types for other fields besides strings
+    %w(repeated_int32 repeated_int64 repeated_uint32 repeated_uint64).each do |field_name|
+      m.send(field_name)[3] = 10
+      assert_equal [0,0,0,10], m.send(field_name)
+    end
+    m.repeated_float[3] = 10.1
+    #wonky mri float handling
+    assert_equal [0,0,0], m.repeated_float.to_a[0..2]
+    assert_equal 10.1, m.repeated_float[3].round(1)
+    m.repeated_double[3] = 10.1
+    assert_equal [0,0,0,10.1], m.repeated_double
+    m.repeated_bool[3] = true
+    assert_equal [false, false, false, true], m.repeated_bool
+    m.repeated_bytes[3] = "bar".encode!('ASCII-8BIT')
+    assert_equal ['', '', '', "bar".encode!('ASCII-8BIT')], m.repeated_bytes
+    m.repeated_msg[3] = TestMessage2.new(:foo => 1)
+    assert_equal [nil, nil, nil, TestMessage2.new(:foo => 1)], m.repeated_msg
+    m.repeated_enum[3] = :A
+    assert_equal [:Default, :Default, :Default, :A], m.repeated_enum
+
+    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+    #   arr[20] = 'spacious'
+    # end
+    # TODO: accessor doesn't allow other ruby-like methods
+    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+    #   arr[1, 2] = 'fizz'
+    # end
+    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+    #   arr[0..2] = 'buzz'
+    # end
+  end
+
+  def test_push
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.push('fizz')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr << 'fizz'
+    end
+    #TODO: push should support multiple
+    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+    #   arr.push('fizz', 'buzz')
+    # end
+  end
+
+  def test_clear
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.clear
+    end
+  end
+
+  def test_concat
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    m.repeated_string.concat(['fizz', 'buzz'])
+    assert_equal %w(foo bar baz fizz buzz), m.repeated_string
+    #TODO: concat should return the orig array
+    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+    #   arr.concat(['fizz', 'buzz'])
+    # end
+  end
+
+  def test_equal
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    assert_equal reference_arr, m.repeated_string
+    reference_arr << 'fizz'
+    assert_not_equal reference_arr, m.repeated_string
+    m.repeated_string << 'fizz'
+    assert_equal reference_arr, m.repeated_string
+  end
+
+  def test_hash
+    # just a sanity check
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    assert m.repeated_string.hash.is_a?(Integer)
+    hash = m.repeated_string.hash
+    assert_equal hash, m.repeated_string.hash
+    m.repeated_string << 'j'
+    assert_not_equal hash, m.repeated_string.hash
+  end
+
+  def test_plus
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr + ['fizz', 'buzz']
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr += ['fizz', 'buzz']
+    end
+  end
+
+  def test_replace
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.replace(['fizz', 'buzz'])
+    end
+  end
+
+  def test_to_a
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.to_a
+    end
+  end
+
+  def test_to_ary
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.to_ary
+    end
+  end
+
+  # emulate Array behavior
+  ##########################
+
+  def test_collect!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.collect!{|x| x + "!" }
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.collect!.with_index{|x, i| x[0...i] }
+    end
+  end
+
+  def test_compact!
+    m = TestMessage.new
+    m.repeated_msg << TestMessage2.new(:foo => 1)
+    m.repeated_msg << nil
+    m.repeated_msg << TestMessage2.new(:foo => 2)
+    reference_arr = m.repeated_string.to_a
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.compact!
+    end
+  end
+
+  def test_delete
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.delete('bar')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.delete('nope')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.delete('nope'){'within'}
+    end
+  end
+
+  def test_delete_at
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.delete_at(2)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.delete_at(10)
+    end
+  end
+
+  def test_fill
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.fill("x")
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.fill("z", 2, 2)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.fill("y", 0..1)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.fill { |i| (i*i).to_s }
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.fill(-2) { |i| (i*i*i).to_s }
+    end
+  end
+
+  def test_flatten!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.flatten!
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.flatten!(1)
+    end
+  end
+
+  def test_insert
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.insert(2, 'fizz')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.insert(3, 'fizz', 'buzz', 'bazz')
+    end
+  end
+
+  def test_inspect
+    m = TestMessage.new
+    assert_equal '[]', m.repeated_string.inspect
+    m.repeated_string << 'foo'
+    assert_equal m.repeated_string.to_a.inspect, m.repeated_string.inspect
+    m.repeated_string << 'bar'
+    assert_equal m.repeated_string.to_a.inspect, m.repeated_string.inspect
+  end
+
+  def test_reverse!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.reverse!
+    end
+  end
+
+  def test_rotate!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.rotate!
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.rotate!(2)
+    end
+  end
+
+  def test_select!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.select! { |v| v =~ /[aeiou]/ }
+    end
+  end
+
+  def test_shift
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    # should return an element
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.shift
+    end
+    # should return an array
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.shift(2)
+    end
+    # should return nil
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.shift
+    end
+  end
+
+  def test_shuffle!
+    m = TestMessage.new
+    m.repeated_string += %w(foo bar baz)
+    orig_repeated_string = m.repeated_string.clone
+    result = m.repeated_string.shuffle!
+    assert_equal m.repeated_string, result
+    # NOTE: sometimes it doesn't change the order...
+    # assert_not_equal m.repeated_string.to_a, orig_repeated_string.to_a
+  end
+
+  def test_slice!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz bar fizz buzz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.slice!(2)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.slice!(1,2)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.slice!(0..1)
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.slice!(10)
+    end
+  end
+
+  def test_sort!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.sort!
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.sort! { |x,y| y <=> x }
+    end
+  end
+
+  def test_sort_by!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.sort_by!
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.sort_by!(&:hash)
+    end
+  end
+
+  def test_uniq!
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.uniq!
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.uniq!{|s| s[0] }
+    end
+  end
+
+  def test_unshift
+    m = TestMessage.new
+    reference_arr = %w(foo bar baz)
+    m.repeated_string += reference_arr.clone
+
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.unshift('1')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.unshift('a', 'b')
+    end
+    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
+      arr.unshift('')
+    end
+  end
+
+
+  ##### HELPER METHODS
+
+  def check_self_modifying_method(repeated_field, ref_array)
+    expected_result = yield(ref_array)
+    actual_result = yield(repeated_field)
+    if expected_result.is_a?(Enumerator)
+      assert_equal expected_result.to_a, actual_result.to_a
+    else
+      assert_equal expected_result, actual_result
+    end
+    assert_equal ref_array, repeated_field
+  end
+
+
+  def repeated_field_names(klass)
+    klass.descriptor.find_all{|f| f.label == :repeated}.map(&:name)
+  end
+
+
+  def fill_test_msg(test_msg)
+    test_msg.repeated_int32  += [-10, -11]
+    test_msg.repeated_int64  += [-1_000_000, -1_000_001]
+    test_msg.repeated_uint32 += [10, 11]
+    test_msg.repeated_uint64 += [1_000_000, 1_000_001]
+    test_msg.repeated_bool   += [true, false]
+    test_msg.repeated_float  += [-1.01, -1.02]
+    test_msg.repeated_double += [-1.0000000000001, -1.0000000000002]
+    test_msg.repeated_string += %w(foo bar)
+    test_msg.repeated_bytes  += ["bar".encode!('ASCII-8BIT'), "foo".encode!('ASCII-8BIT')]
+    test_msg.repeated_msg    << TestMessage2.new(:foo => 1)
+    test_msg.repeated_msg    << TestMessage2.new(:foo => 2)
+    test_msg.repeated_enum   << :A
+    test_msg.repeated_enum   << :B
+  end
+
+
+  pool = Google::Protobuf::DescriptorPool.new
+  pool.build do
+
+    add_message "TestMessage" do
+      optional :optional_int32,  :int32,        1
+      optional :optional_int64,  :int64,        2
+      optional :optional_uint32, :uint32,       3
+      optional :optional_uint64, :uint64,       4
+      optional :optional_bool,   :bool,         5
+      optional :optional_float,  :float,        6
+      optional :optional_double, :double,       7
+      optional :optional_string, :string,       8
+      optional :optional_bytes,  :bytes,        9
+      optional :optional_msg,    :message,      10, "TestMessage2"
+      optional :optional_enum,   :enum,         11, "TestEnum"
+
+      repeated :repeated_int32,  :int32,        12
+      repeated :repeated_int64,  :int64,        13
+      repeated :repeated_uint32, :uint32,       14
+      repeated :repeated_uint64, :uint64,       15
+      repeated :repeated_bool,   :bool,         16
+      repeated :repeated_float,  :float,        17
+      repeated :repeated_double, :double,       18
+      repeated :repeated_string, :string,       19
+      repeated :repeated_bytes,  :bytes,        20
+      repeated :repeated_msg,    :message,      21, "TestMessage2"
+      repeated :repeated_enum,   :enum,         22, "TestEnum"
+    end
+    add_message "TestMessage2" do
+      optional :foo, :int32, 1
+    end
+
+    add_enum "TestEnum" do
+      value :Default, 0
+      value :A, 1
+      value :B, 2
+      value :C, 3
+    end
+  end
+
+  TestMessage = pool.lookup("TestMessage").msgclass
+  TestMessage2 = pool.lookup("TestMessage2").msgclass
+  TestEnum = pool.lookup("TestEnum").enummodule
+
+
+end
diff --git a/src/third_party/protobuf-3/ruby/tests/stress.rb b/src/third_party/protobuf-3/ruby/tests/stress.rb
new file mode 100644
index 0000000..082d5e2
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/tests/stress.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/ruby
+
+require 'google/protobuf'
+require 'test/unit'
+
+module StressTest
+  pool = Google::Protobuf::DescriptorPool.new
+  pool.build do
+    add_message "TestMessage" do
+      optional :a,  :int32,        1
+      repeated :b,  :message,      2, "M"
+    end
+    add_message "M" do
+      optional :foo, :string, 1
+    end
+  end
+
+  TestMessage = pool.lookup("TestMessage").msgclass
+  M = pool.lookup("M").msgclass
+
+  class StressTest < Test::Unit::TestCase
+    def get_msg
+      TestMessage.new(:a => 1000,
+                      :b => [M.new(:foo => "hello"),
+                             M.new(:foo => "world")])
+    end
+    def test_stress
+      m = get_msg
+      data = TestMessage.encode(m)
+      100_000.times do
+        mnew = TestMessage.decode(data)
+        mnew = mnew.dup
+        assert_equal mnew.inspect, m.inspect
+        assert TestMessage.encode(mnew) == data
+      end
+    end
+  end
+end
diff --git a/src/third_party/protobuf-3/ruby/travis-test.sh b/src/third_party/protobuf-3/ruby/travis-test.sh
new file mode 100755
index 0000000..75db7d9
--- /dev/null
+++ b/src/third_party/protobuf-3/ruby/travis-test.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+# Exit on any error.
+set -e
+
+test_version() {
+  version=$1
+  if [ "$version" == "jruby" ] ; then
+    # No conformance tests yet -- JRuby is too broken to run them.
+    bash --login -c \
+      "rvm install $version && rvm use $version && \
+       which ruby && \
+       gem install bundler && bundle && \
+       rake test"
+  else
+    bash --login -c \
+      "rvm install $version && rvm use $version && \
+       which ruby && \
+       gem install bundler && bundle && \
+       rake test &&
+       cd ../conformance && make test_ruby"
+  fi
+}
+
+test_version $1
diff --git a/src/third_party/protobuf-3/six.BUILD b/src/third_party/protobuf-3/six.BUILD
new file mode 100644
index 0000000..fb0b360
--- /dev/null
+++ b/src/third_party/protobuf-3/six.BUILD
@@ -0,0 +1,13 @@
+genrule(
+  name = "copy_six",
+  srcs = ["six-1.10.0/six.py"],
+  outs = ["six.py"],
+  cmd = "cp $< $(@)",
+)
+
+py_library(
+  name = "six",
+  srcs = ["six.py"],
+  srcs_version = "PY2AND3",
+  visibility = ["//visibility:public"],
+)
diff --git a/src/third_party/protobuf-3/src/Makefile.am b/src/third_party/protobuf-3/src/Makefile.am
new file mode 100644
index 0000000..8006550
--- /dev/null
+++ b/src/third_party/protobuf-3/src/Makefile.am
@@ -0,0 +1,834 @@
+## Process this file with automake to produce Makefile.in
+
+if HAVE_ZLIB
+GZCHECKPROGRAMS = zcgzip zcgunzip
+GZHEADERS = google/protobuf/io/gzip_stream.h
+GZTESTS = google/protobuf/io/gzip_stream_unittest.sh
+ZLIB_DEF = -DHAVE_ZLIB=1
+else
+GZCHECKPROGRAMS =
+GZHEADERS =
+GZTESTS =
+ZLIB_DEF =
+endif
+
+if HAVE_PTHREAD
+PTHREAD_DEF = -DHAVE_PTHREAD=1
+else
+PTHREAD_DEF =
+endif
+
+if GCC
+# These are good warnings to turn on by default
+NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
+else
+NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF)
+endif
+
+AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
+
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
+
+# If I say "dist_include_DATA", automake complains that $(includedir) is not
+# a "legitimate" directory for DATA.  Screw you, automake.
+protodir = $(includedir)
+nobase_dist_proto_DATA = google/protobuf/descriptor.proto     \
+                         google/protobuf/any.proto            \
+                         google/protobuf/api.proto            \
+                         google/protobuf/duration.proto       \
+                         google/protobuf/empty.proto          \
+                         google/protobuf/field_mask.proto     \
+                         google/protobuf/source_context.proto \
+                         google/protobuf/struct.proto         \
+                         google/protobuf/timestamp.proto      \
+                         google/protobuf/type.proto           \
+                         google/protobuf/wrappers.proto       \
+                         google/protobuf/compiler/plugin.proto
+
+# Not sure why these don't get cleaned automatically.
+clean-local:
+	rm -f *.loT
+
+CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
+             testzip.jar testzip.list testzip.proto testzip.zip
+
+MAINTAINERCLEANFILES =   \
+  Makefile.in
+
+nobase_include_HEADERS =                                        \
+  google/protobuf/stubs/atomic_sequence_num.h                   \
+  google/protobuf/stubs/atomicops.h                             \
+  google/protobuf/stubs/atomicops_internals_power.h             \
+  google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
+  google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
+  google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
+  google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
+  google/protobuf/stubs/atomicops_internals_generic_gcc.h       \
+  google/protobuf/stubs/atomicops_internals_macosx.h            \
+  google/protobuf/stubs/atomicops_internals_mips_gcc.h          \
+  google/protobuf/stubs/atomicops_internals_pnacl.h             \
+  google/protobuf/stubs/atomicops_internals_solaris.h           \
+  google/protobuf/stubs/atomicops_internals_tsan.h              \
+  google/protobuf/stubs/atomicops_internals_x86_gcc.h           \
+  google/protobuf/stubs/atomicops_internals_x86_msvc.h          \
+  google/protobuf/stubs/callback.h                              \
+  google/protobuf/stubs/bytestream.h                            \
+  google/protobuf/stubs/casts.h                                 \
+  google/protobuf/stubs/common.h                                \
+  google/protobuf/stubs/fastmem.h                               \
+  google/protobuf/stubs/hash.h                                  \
+  google/protobuf/stubs/logging.h                               \
+  google/protobuf/stubs/macros.h                                \
+  google/protobuf/stubs/mutex.h                                 \
+  google/protobuf/stubs/once.h                                  \
+  google/protobuf/stubs/platform_macros.h                       \
+  google/protobuf/stubs/port.h                                  \
+  google/protobuf/stubs/scoped_ptr.h                            \
+  google/protobuf/stubs/shared_ptr.h                            \
+  google/protobuf/stubs/singleton.h                             \
+  google/protobuf/stubs/status.h                                \
+  google/protobuf/stubs/stl_util.h                              \
+  google/protobuf/stubs/stringpiece.h                           \
+  google/protobuf/stubs/template_util.h                         \
+  google/protobuf/stubs/type_traits.h                           \
+  google/protobuf/any.pb.h                                      \
+  google/protobuf/api.pb.h                                      \
+  google/protobuf/any.h                                         \
+  google/protobuf/arena.h                                       \
+  google/protobuf/arenastring.h                                 \
+  google/protobuf/descriptor_database.h                         \
+  google/protobuf/descriptor.h                                  \
+  google/protobuf/descriptor.pb.h                               \
+  google/protobuf/duration.pb.h                                 \
+  google/protobuf/dynamic_message.h                             \
+  google/protobuf/empty.pb.h                                    \
+  google/protobuf/extension_set.h                               \
+  google/protobuf/field_mask.pb.h                               \
+  google/protobuf/generated_enum_reflection.h                   \
+  google/protobuf/generated_enum_util.h                         \
+  google/protobuf/generated_message_reflection.h                \
+  google/protobuf/generated_message_util.h                      \
+  google/protobuf/map_entry.h                                   \
+  google/protobuf/map_entry_lite.h                              \
+  google/protobuf/map_field.h                                   \
+  google/protobuf/map_field_inl.h                               \
+  google/protobuf/map_field_lite.h                              \
+  google/protobuf/map.h                                         \
+  google/protobuf/map_type_handler.h                            \
+  google/protobuf/message.h                                     \
+  google/protobuf/message_lite.h                                \
+  google/protobuf/metadata.h                                    \
+  google/protobuf/reflection.h                                  \
+  google/protobuf/reflection_ops.h                              \
+  google/protobuf/repeated_field.h                              \
+  google/protobuf/repeated_field_reflection.h                   \
+  google/protobuf/service.h                                     \
+  google/protobuf/source_context.pb.h                           \
+  google/protobuf/struct.pb.h                                   \
+  google/protobuf/text_format.h                                 \
+  google/protobuf/timestamp.pb.h                                \
+  google/protobuf/type.pb.h                                     \
+  google/protobuf/unknown_field_set.h                           \
+  google/protobuf/wire_format.h                                 \
+  google/protobuf/wire_format_lite.h                            \
+  google/protobuf/wire_format_lite_inl.h                        \
+  google/protobuf/wrappers.pb.h                                 \
+  google/protobuf/io/coded_stream.h                             \
+  $(GZHEADERS)                                                  \
+  google/protobuf/io/printer.h                                  \
+  google/protobuf/io/strtod.h                                   \
+  google/protobuf/io/tokenizer.h                                \
+  google/protobuf/io/zero_copy_stream.h                         \
+  google/protobuf/io/zero_copy_stream_impl.h                    \
+  google/protobuf/io/zero_copy_stream_impl_lite.h               \
+  google/protobuf/compiler/code_generator.h                     \
+  google/protobuf/compiler/command_line_interface.h             \
+  google/protobuf/compiler/importer.h                           \
+  google/protobuf/compiler/parser.h                             \
+  google/protobuf/compiler/plugin.h                             \
+  google/protobuf/compiler/plugin.pb.h                          \
+  google/protobuf/compiler/cpp/cpp_generator.h                  \
+  google/protobuf/compiler/csharp/csharp_generator.h            \
+  google/protobuf/compiler/csharp/csharp_names.h                \
+  google/protobuf/compiler/java/java_generator.h                \
+  google/protobuf/compiler/java/java_names.h                    \
+  google/protobuf/compiler/javanano/javanano_generator.h        \
+  google/protobuf/compiler/js/js_generator.h                    \
+  google/protobuf/compiler/objectivec/objectivec_generator.h    \
+  google/protobuf/compiler/objectivec/objectivec_helpers.h      \
+  google/protobuf/compiler/python/python_generator.h            \
+  google/protobuf/compiler/ruby/ruby_generator.h                \
+  google/protobuf/util/type_resolver.h                          \
+  google/protobuf/util/field_comparator.h                       \
+  google/protobuf/util/field_mask_util.h                        \
+  google/protobuf/util/json_util.h                              \
+  google/protobuf/util/time_util.h                              \
+  google/protobuf/util/type_resolver_util.h                     \
+  google/protobuf/util/message_differencer.h
+
+lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
+
+libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
+libprotobuf_lite_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
+libprotobuf_lite_la_SOURCES =                                  \
+  google/protobuf/stubs/atomicops_internals_x86_gcc.cc         \
+  google/protobuf/stubs/atomicops_internals_x86_msvc.cc        \
+  google/protobuf/stubs/bytestream.cc                          \
+  google/protobuf/stubs/bytestream.h                           \
+  google/protobuf/stubs/common.cc                              \
+  google/protobuf/stubs/hash.h                                 \
+  google/protobuf/stubs/int128.cc                              \
+  google/protobuf/stubs/int128.h                               \
+  google/protobuf/stubs/map_util.h                             \
+  google/protobuf/stubs/mathutil.h                             \
+  google/protobuf/stubs/once.cc                                \
+  google/protobuf/stubs/shared_ptr.h                           \
+  google/protobuf/stubs/status.cc                              \
+  google/protobuf/stubs/status.h                               \
+  google/protobuf/stubs/status_macros.h                        \
+  google/protobuf/stubs/statusor.cc                            \
+  google/protobuf/stubs/statusor.h                             \
+  google/protobuf/stubs/stringpiece.cc                         \
+  google/protobuf/stubs/stringpiece.h                          \
+  google/protobuf/stubs/stringprintf.cc                        \
+  google/protobuf/stubs/stringprintf.h                         \
+  google/protobuf/stubs/structurally_valid.cc                  \
+  google/protobuf/stubs/strutil.cc                             \
+  google/protobuf/stubs/strutil.h                              \
+  google/protobuf/stubs/time.cc                                \
+  google/protobuf/stubs/time.h                                 \
+  google/protobuf/arena.cc                                     \
+  google/protobuf/arenastring.cc                               \
+  google/protobuf/extension_set.cc                             \
+  google/protobuf/generated_message_util.cc                    \
+  google/protobuf/message_lite.cc                              \
+  google/protobuf/repeated_field.cc                            \
+  google/protobuf/wire_format_lite.cc                          \
+  google/protobuf/io/coded_stream.cc                           \
+  google/protobuf/io/coded_stream_inl.h                        \
+  google/protobuf/io/zero_copy_stream.cc                       \
+  google/protobuf/io/zero_copy_stream_impl_lite.cc
+
+libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
+libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
+libprotobuf_la_SOURCES =                                       \
+  $(libprotobuf_lite_la_SOURCES)                               \
+  google/protobuf/any.pb.cc                                    \
+  google/protobuf/api.pb.cc                                    \
+  google/protobuf/stubs/mathlimits.cc                          \
+  google/protobuf/stubs/mathlimits.h                           \
+  google/protobuf/any.cc                                       \
+  google/protobuf/descriptor.cc                                \
+  google/protobuf/descriptor_database.cc                       \
+  google/protobuf/descriptor.pb.cc                             \
+  google/protobuf/duration.pb.cc                               \
+  google/protobuf/dynamic_message.cc                           \
+  google/protobuf/empty.pb.cc                                  \
+  google/protobuf/extension_set_heavy.cc                       \
+  google/protobuf/field_mask.pb.cc                             \
+  google/protobuf/generated_message_reflection.cc              \
+  google/protobuf/map_field.cc                                 \
+  google/protobuf/message.cc                                   \
+  google/protobuf/reflection_internal.h                        \
+  google/protobuf/reflection_ops.cc                            \
+  google/protobuf/service.cc                                   \
+  google/protobuf/source_context.pb.cc                         \
+  google/protobuf/struct.pb.cc                                 \
+  google/protobuf/stubs/substitute.cc                          \
+  google/protobuf/stubs/substitute.h                           \
+  google/protobuf/text_format.cc                               \
+  google/protobuf/timestamp.pb.cc                              \
+  google/protobuf/type.pb.cc                                   \
+  google/protobuf/unknown_field_set.cc                         \
+  google/protobuf/wire_format.cc                               \
+  google/protobuf/wrappers.pb.cc                               \
+  google/protobuf/io/gzip_stream.cc                            \
+  google/protobuf/io/printer.cc                                \
+  google/protobuf/io/strtod.cc                                 \
+  google/protobuf/io/tokenizer.cc                              \
+  google/protobuf/io/zero_copy_stream_impl.cc                  \
+  google/protobuf/compiler/importer.cc                         \
+  google/protobuf/compiler/parser.cc                           \
+  google/protobuf/util/field_comparator.cc                     \
+  google/protobuf/util/field_mask_util.cc                      \
+  google/protobuf/util/internal/constants.h                    \
+  google/protobuf/util/internal/datapiece.cc                   \
+  google/protobuf/util/internal/datapiece.h                    \
+  google/protobuf/util/internal/default_value_objectwriter.cc  \
+  google/protobuf/util/internal/default_value_objectwriter.h   \
+  google/protobuf/util/internal/error_listener.cc              \
+  google/protobuf/util/internal/error_listener.h               \
+  google/protobuf/util/internal/expecting_objectwriter.h       \
+  google/protobuf/util/internal/field_mask_utility.cc          \
+  google/protobuf/util/internal/field_mask_utility.h           \
+  google/protobuf/util/internal/json_escaping.cc               \
+  google/protobuf/util/internal/json_escaping.h                \
+  google/protobuf/util/internal/json_objectwriter.cc           \
+  google/protobuf/util/internal/json_objectwriter.h            \
+  google/protobuf/util/internal/json_stream_parser.cc          \
+  google/protobuf/util/internal/json_stream_parser.h           \
+  google/protobuf/util/internal/location_tracker.h             \
+  google/protobuf/util/internal/mock_error_listener.h          \
+  google/protobuf/util/internal/object_location_tracker.h      \
+  google/protobuf/util/internal/object_source.h                \
+  google/protobuf/util/internal/object_writer.cc               \
+  google/protobuf/util/internal/object_writer.h                \
+  google/protobuf/util/internal/protostream_objectsource.cc    \
+  google/protobuf/util/internal/protostream_objectsource.h     \
+  google/protobuf/util/internal/protostream_objectwriter.cc    \
+  google/protobuf/util/internal/protostream_objectwriter.h     \
+  google/protobuf/util/internal/proto_writer.cc                \
+  google/protobuf/util/internal/proto_writer.h                 \
+  google/protobuf/util/internal/structured_objectwriter.h      \
+  google/protobuf/util/internal/type_info.cc                   \
+  google/protobuf/util/internal/type_info.h                    \
+  google/protobuf/util/internal/type_info_test_helper.cc       \
+  google/protobuf/util/internal/type_info_test_helper.h        \
+  google/protobuf/util/internal/utility.cc                     \
+  google/protobuf/util/internal/utility.h                      \
+  google/protobuf/util/json_util.cc                            \
+  google/protobuf/util/message_differencer.cc                  \
+  google/protobuf/util/time_util.cc                            \
+  google/protobuf/util/type_resolver_util.cc
+
+nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
+
+libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
+libprotoc_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
+libprotoc_la_SOURCES =                                         \
+  google/protobuf/compiler/code_generator.cc                   \
+  google/protobuf/compiler/command_line_interface.cc           \
+  google/protobuf/compiler/plugin.cc                           \
+  google/protobuf/compiler/plugin.pb.cc                        \
+  google/protobuf/compiler/subprocess.cc                       \
+  google/protobuf/compiler/subprocess.h                        \
+  google/protobuf/compiler/zip_writer.cc                       \
+  google/protobuf/compiler/zip_writer.h                        \
+  google/protobuf/compiler/cpp/cpp_enum.cc                     \
+  google/protobuf/compiler/cpp/cpp_enum.h                      \
+  google/protobuf/compiler/cpp/cpp_enum_field.cc               \
+  google/protobuf/compiler/cpp/cpp_enum_field.h                \
+  google/protobuf/compiler/cpp/cpp_extension.cc                \
+  google/protobuf/compiler/cpp/cpp_extension.h                 \
+  google/protobuf/compiler/cpp/cpp_field.cc                    \
+  google/protobuf/compiler/cpp/cpp_field.h                     \
+  google/protobuf/compiler/cpp/cpp_file.cc                     \
+  google/protobuf/compiler/cpp/cpp_file.h                      \
+  google/protobuf/compiler/cpp/cpp_generator.cc                \
+  google/protobuf/compiler/cpp/cpp_helpers.cc                  \
+  google/protobuf/compiler/cpp/cpp_helpers.h                   \
+  google/protobuf/compiler/cpp/cpp_map_field.cc                \
+  google/protobuf/compiler/cpp/cpp_map_field.h                 \
+  google/protobuf/compiler/cpp/cpp_message.cc                  \
+  google/protobuf/compiler/cpp/cpp_message.h                   \
+  google/protobuf/compiler/cpp/cpp_message_field.cc            \
+  google/protobuf/compiler/cpp/cpp_message_field.h             \
+  google/protobuf/compiler/cpp/cpp_options.h                   \
+  google/protobuf/compiler/cpp/cpp_primitive_field.cc          \
+  google/protobuf/compiler/cpp/cpp_primitive_field.h           \
+  google/protobuf/compiler/cpp/cpp_service.cc                  \
+  google/protobuf/compiler/cpp/cpp_service.h                   \
+  google/protobuf/compiler/cpp/cpp_string_field.cc             \
+  google/protobuf/compiler/cpp/cpp_string_field.h              \
+  google/protobuf/compiler/java/java_context.cc                \
+  google/protobuf/compiler/java/java_context.h                 \
+  google/protobuf/compiler/java/java_enum.cc                   \
+  google/protobuf/compiler/java/java_enum_lite.cc              \
+  google/protobuf/compiler/java/java_enum_field.cc             \
+  google/protobuf/compiler/java/java_enum_field.h              \
+  google/protobuf/compiler/java/java_enum_field_lite.cc        \
+  google/protobuf/compiler/java/java_enum_field_lite.h         \
+  google/protobuf/compiler/java/java_enum.h                    \
+  google/protobuf/compiler/java/java_enum_lite.h               \
+  google/protobuf/compiler/java/java_extension.cc              \
+  google/protobuf/compiler/java/java_extension.h               \
+  google/protobuf/compiler/java/java_extension_lite.cc         \
+  google/protobuf/compiler/java/java_extension_lite.h          \
+  google/protobuf/compiler/java/java_field.cc                  \
+  google/protobuf/compiler/java/java_field.h                   \
+  google/protobuf/compiler/java/java_file.cc                   \
+  google/protobuf/compiler/java/java_file.h                    \
+  google/protobuf/compiler/java/java_generator.cc              \
+  google/protobuf/compiler/java/java_generator_factory.cc      \
+  google/protobuf/compiler/java/java_generator_factory.h       \
+  google/protobuf/compiler/java/java_helpers.cc                \
+  google/protobuf/compiler/java/java_helpers.h                 \
+  google/protobuf/compiler/java/java_lazy_message_field.cc     \
+  google/protobuf/compiler/java/java_lazy_message_field.h      \
+  google/protobuf/compiler/java/java_lazy_message_field_lite.cc\
+  google/protobuf/compiler/java/java_lazy_message_field_lite.h \
+  google/protobuf/compiler/java/java_map_field.cc              \
+  google/protobuf/compiler/java/java_map_field.h               \
+  google/protobuf/compiler/java/java_map_field_lite.cc         \
+  google/protobuf/compiler/java/java_map_field_lite.h          \
+  google/protobuf/compiler/java/java_message.cc                \
+  google/protobuf/compiler/java/java_message_lite.cc           \
+  google/protobuf/compiler/java/java_message_builder.cc        \
+  google/protobuf/compiler/java/java_message_builder_lite.cc   \
+  google/protobuf/compiler/java/java_message_field.cc          \
+  google/protobuf/compiler/java/java_message_field.h           \
+  google/protobuf/compiler/java/java_message_field_lite.cc     \
+  google/protobuf/compiler/java/java_message_field_lite.h      \
+  google/protobuf/compiler/java/java_message.h                 \
+  google/protobuf/compiler/java/java_message_lite.h            \
+  google/protobuf/compiler/java/java_message_builder.h         \
+  google/protobuf/compiler/java/java_message_builder_lite.h    \
+  google/protobuf/compiler/java/java_name_resolver.cc          \
+  google/protobuf/compiler/java/java_name_resolver.h           \
+  google/protobuf/compiler/java/java_primitive_field.cc        \
+  google/protobuf/compiler/java/java_primitive_field.h         \
+  google/protobuf/compiler/java/java_primitive_field_lite.cc   \
+  google/protobuf/compiler/java/java_primitive_field_lite.h    \
+  google/protobuf/compiler/java/java_shared_code_generator.cc  \
+  google/protobuf/compiler/java/java_shared_code_generator.h   \
+  google/protobuf/compiler/java/java_service.cc                \
+  google/protobuf/compiler/java/java_service.h                 \
+  google/protobuf/compiler/java/java_string_field.cc           \
+  google/protobuf/compiler/java/java_string_field.h            \
+  google/protobuf/compiler/java/java_string_field_lite.cc      \
+  google/protobuf/compiler/java/java_string_field_lite.h       \
+  google/protobuf/compiler/java/java_doc_comment.cc            \
+  google/protobuf/compiler/java/java_doc_comment.h             \
+  google/protobuf/compiler/js/js_generator.cc                  \
+  google/protobuf/compiler/javanano/javanano_enum.cc           \
+  google/protobuf/compiler/javanano/javanano_enum.h            \
+  google/protobuf/compiler/javanano/javanano_enum_field.cc     \
+  google/protobuf/compiler/javanano/javanano_enum_field.h      \
+  google/protobuf/compiler/javanano/javanano_extension.cc      \
+  google/protobuf/compiler/javanano/javanano_extension.h       \
+  google/protobuf/compiler/javanano/javanano_field.cc          \
+  google/protobuf/compiler/javanano/javanano_field.h           \
+  google/protobuf/compiler/javanano/javanano_file.cc           \
+  google/protobuf/compiler/javanano/javanano_file.h            \
+  google/protobuf/compiler/javanano/javanano_generator.cc      \
+  google/protobuf/compiler/javanano/javanano_generator.h       \
+  google/protobuf/compiler/javanano/javanano_helpers.cc        \
+  google/protobuf/compiler/javanano/javanano_helpers.h         \
+  google/protobuf/compiler/javanano/javanano_map_field.cc      \
+  google/protobuf/compiler/javanano/javanano_map_field.h       \
+  google/protobuf/compiler/javanano/javanano_message.cc        \
+  google/protobuf/compiler/javanano/javanano_message.h         \
+  google/protobuf/compiler/javanano/javanano_message_field.cc  \
+  google/protobuf/compiler/javanano/javanano_message_field.h   \
+  google/protobuf/compiler/javanano/javanano_params.h          \
+  google/protobuf/compiler/javanano/javanano_primitive_field.cc \
+  google/protobuf/compiler/javanano/javanano_primitive_field.h \
+  google/protobuf/compiler/objectivec/objectivec_enum.cc       \
+  google/protobuf/compiler/objectivec/objectivec_enum.h        \
+  google/protobuf/compiler/objectivec/objectivec_enum_field.cc \
+  google/protobuf/compiler/objectivec/objectivec_enum_field.h  \
+  google/protobuf/compiler/objectivec/objectivec_extension.cc  \
+  google/protobuf/compiler/objectivec/objectivec_extension.h   \
+  google/protobuf/compiler/objectivec/objectivec_field.cc      \
+  google/protobuf/compiler/objectivec/objectivec_field.h       \
+  google/protobuf/compiler/objectivec/objectivec_file.cc       \
+  google/protobuf/compiler/objectivec/objectivec_file.h        \
+  google/protobuf/compiler/objectivec/objectivec_generator.cc  \
+  google/protobuf/compiler/objectivec/objectivec_helpers.cc    \
+  google/protobuf/compiler/objectivec/objectivec_helpers.h     \
+  google/protobuf/compiler/objectivec/objectivec_map_field.cc  \
+  google/protobuf/compiler/objectivec/objectivec_map_field.h   \
+  google/protobuf/compiler/objectivec/objectivec_message.cc    \
+  google/protobuf/compiler/objectivec/objectivec_message.h     \
+  google/protobuf/compiler/objectivec/objectivec_message_field.cc \
+  google/protobuf/compiler/objectivec/objectivec_message_field.h \
+  google/protobuf/compiler/objectivec/objectivec_oneof.cc      \
+  google/protobuf/compiler/objectivec/objectivec_oneof.h       \
+  google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \
+  google/protobuf/compiler/objectivec/objectivec_primitive_field.h \
+  google/protobuf/compiler/python/python_generator.cc          \
+  google/protobuf/compiler/ruby/ruby_generator.cc              \
+  google/protobuf/compiler/csharp/csharp_doc_comment.cc        \
+  google/protobuf/compiler/csharp/csharp_doc_comment.h         \
+  google/protobuf/compiler/csharp/csharp_enum.cc               \
+  google/protobuf/compiler/csharp/csharp_enum.h                \
+  google/protobuf/compiler/csharp/csharp_enum_field.cc         \
+  google/protobuf/compiler/csharp/csharp_enum_field.h          \
+  google/protobuf/compiler/csharp/csharp_field_base.cc         \
+  google/protobuf/compiler/csharp/csharp_field_base.h          \
+  google/protobuf/compiler/csharp/csharp_generator.cc          \
+  google/protobuf/compiler/csharp/csharp_helpers.cc            \
+  google/protobuf/compiler/csharp/csharp_helpers.h             \
+  google/protobuf/compiler/csharp/csharp_map_field.cc          \
+  google/protobuf/compiler/csharp/csharp_map_field.h           \
+  google/protobuf/compiler/csharp/csharp_message.cc            \
+  google/protobuf/compiler/csharp/csharp_message.h             \
+  google/protobuf/compiler/csharp/csharp_message_field.cc      \
+  google/protobuf/compiler/csharp/csharp_message_field.h       \
+  google/protobuf/compiler/csharp/csharp_options.h             \
+  google/protobuf/compiler/csharp/csharp_primitive_field.cc    \
+  google/protobuf/compiler/csharp/csharp_primitive_field.h     \
+  google/protobuf/compiler/csharp/csharp_reflection_class.cc     \
+  google/protobuf/compiler/csharp/csharp_reflection_class.h      \
+  google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \
+  google/protobuf/compiler/csharp/csharp_repeated_enum_field.h \
+  google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \
+  google/protobuf/compiler/csharp/csharp_repeated_message_field.h \
+  google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \
+  google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h \
+  google/protobuf/compiler/csharp/csharp_source_generator_base.cc \
+  google/protobuf/compiler/csharp/csharp_source_generator_base.h \
+  google/protobuf/compiler/csharp/csharp_wrapper_field.cc      \
+  google/protobuf/compiler/csharp/csharp_wrapper_field.h
+
+bin_PROGRAMS = protoc
+protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
+protoc_SOURCES = google/protobuf/compiler/main.cc
+
+# Tests ==============================================================
+
+protoc_inputs =                                                   \
+  google/protobuf/any_test.proto                                  \
+  google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto     \
+  google/protobuf/map_lite_unittest.proto                         \
+  google/protobuf/map_proto2_unittest.proto                       \
+  google/protobuf/map_unittest.proto                              \
+  google/protobuf/unittest_arena.proto                            \
+  google/protobuf/unittest_custom_options.proto                   \
+  google/protobuf/unittest_drop_unknown_fields.proto              \
+  google/protobuf/unittest_embed_optimize_for.proto               \
+  google/protobuf/unittest_empty.proto                            \
+  google/protobuf/unittest_enormous_descriptor.proto              \
+  google/protobuf/unittest_import_lite.proto                      \
+  google/protobuf/unittest_import.proto                           \
+  google/protobuf/unittest_import_public_lite.proto               \
+  google/protobuf/unittest_import_public.proto                    \
+  google/protobuf/unittest_lite_imports_nonlite.proto             \
+  google/protobuf/unittest_lite.proto                             \
+  google/protobuf/unittest_mset.proto                             \
+  google/protobuf/unittest_mset_wire_format.proto                 \
+  google/protobuf/unittest_no_arena_lite.proto                    \
+  google/protobuf/unittest_no_arena_import.proto                  \
+  google/protobuf/unittest_no_arena.proto                         \
+  google/protobuf/unittest_no_field_presence.proto                \
+  google/protobuf/unittest_no_generic_services.proto              \
+  google/protobuf/unittest_optimize_for.proto                     \
+  google/protobuf/unittest_preserve_unknown_enum2.proto           \
+  google/protobuf/unittest_preserve_unknown_enum.proto            \
+  google/protobuf/unittest.proto                                  \
+  google/protobuf/unittest_proto3_arena.proto                     \
+  google/protobuf/unittest_proto3_arena_lite.proto                     \
+  google/protobuf/unittest_proto3_lite.proto                     \
+  google/protobuf/unittest_well_known_types.proto                 \
+  google/protobuf/util/internal/testdata/anys.proto               \
+  google/protobuf/util/internal/testdata/books.proto              \
+  google/protobuf/util/internal/testdata/default_value.proto      \
+  google/protobuf/util/internal/testdata/default_value_test.proto \
+  google/protobuf/util/internal/testdata/field_mask.proto         \
+  google/protobuf/util/internal/testdata/maps.proto               \
+  google/protobuf/util/internal/testdata/oneofs.proto             \
+  google/protobuf/util/internal/testdata/struct.proto             \
+  google/protobuf/util/internal/testdata/timestamp_duration.proto \
+  google/protobuf/util/json_format_proto3.proto                   \
+  google/protobuf/util/message_differencer_unittest.proto         \
+  google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
+
+EXTRA_DIST =                                                   \
+  $(protoc_inputs)                                             \
+  solaris/libstdc++.la                                         \
+  google/protobuf/io/gzip_stream.h                             \
+  google/protobuf/io/gzip_stream_unittest.sh                   \
+  google/protobuf/testdata/golden_message                      \
+  google/protobuf/testdata/golden_message_oneof_implemented    \
+  google/protobuf/testdata/golden_message_proto3               \
+  google/protobuf/testdata/golden_packed_fields_message        \
+  google/protobuf/testdata/bad_utf8_string                     \
+  google/protobuf/testdata/map_test_data.txt                   \
+  google/protobuf/testdata/text_format_unittest_data.txt       \
+  google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt  \
+  google/protobuf/testdata/text_format_unittest_data_pointy.txt             \
+  google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt       \
+  google/protobuf/testdata/text_format_unittest_extensions_data.txt         \
+  google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt  \
+  google/protobuf/package_info.h                               \
+  google/protobuf/io/package_info.h                            \
+  google/protobuf/compiler/ruby/ruby_generated_code.proto      \
+  google/protobuf/compiler/ruby/ruby_generated_code.rb         \
+  google/protobuf/compiler/package_info.h                      \
+  google/protobuf/compiler/zip_output_unittest.sh
+
+protoc_lite_outputs =                                          \
+  google/protobuf/map_lite_unittest.pb.cc                      \
+  google/protobuf/map_lite_unittest.pb.h                       \
+  google/protobuf/unittest_lite.pb.cc                          \
+  google/protobuf/unittest_lite.pb.h                           \
+  google/protobuf/unittest_no_arena_lite.pb.cc                 \
+  google/protobuf/unittest_no_arena_lite.pb.h                  \
+  google/protobuf/unittest_import_lite.pb.cc                   \
+  google/protobuf/unittest_import_lite.pb.h                    \
+  google/protobuf/unittest_import_public_lite.pb.cc            \
+  google/protobuf/unittest_import_public_lite.pb.h
+
+protoc_outputs =                                                  \
+  $(protoc_lite_outputs)                                          \
+  google/protobuf/any_test.pb.cc                                  \
+  google/protobuf/any_test.pb.h                                   \
+  google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc     \
+  google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h      \
+  google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc    \
+  google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h     \
+  google/protobuf/map_proto2_unittest.pb.cc                       \
+  google/protobuf/map_proto2_unittest.pb.h                        \
+  google/protobuf/map_unittest.pb.cc                              \
+  google/protobuf/map_unittest.pb.h                               \
+  google/protobuf/unittest_arena.pb.cc                            \
+  google/protobuf/unittest_arena.pb.h                             \
+  google/protobuf/unittest_custom_options.pb.cc                   \
+  google/protobuf/unittest_custom_options.pb.h                    \
+  google/protobuf/unittest_drop_unknown_fields.pb.cc              \
+  google/protobuf/unittest_drop_unknown_fields.pb.h               \
+  google/protobuf/unittest_embed_optimize_for.pb.cc               \
+  google/protobuf/unittest_embed_optimize_for.pb.h                \
+  google/protobuf/unittest_empty.pb.cc                            \
+  google/protobuf/unittest_empty.pb.h                             \
+  google/protobuf/unittest_enormous_descriptor.pb.cc              \
+  google/protobuf/unittest_enormous_descriptor.pb.h               \
+  google/protobuf/unittest_import.pb.cc                           \
+  google/protobuf/unittest_import.pb.h                            \
+  google/protobuf/unittest_import_public.pb.cc                    \
+  google/protobuf/unittest_import_public.pb.h                     \
+  google/protobuf/unittest_lite_imports_nonlite.pb.cc             \
+  google/protobuf/unittest_lite_imports_nonlite.pb.h              \
+  google/protobuf/unittest_mset.pb.cc                             \
+  google/protobuf/unittest_mset.pb.h                              \
+  google/protobuf/unittest_mset_wire_format.pb.cc                 \
+  google/protobuf/unittest_mset_wire_format.pb.h                  \
+  google/protobuf/unittest_no_arena_import.pb.cc                  \
+  google/protobuf/unittest_no_arena_import.pb.h                   \
+  google/protobuf/unittest_no_arena.pb.cc                         \
+  google/protobuf/unittest_no_arena.pb.h                          \
+  google/protobuf/unittest_no_field_presence.pb.cc                \
+  google/protobuf/unittest_no_field_presence.pb.h                 \
+  google/protobuf/unittest_no_generic_services.pb.cc              \
+  google/protobuf/unittest_no_generic_services.pb.h               \
+  google/protobuf/unittest_optimize_for.pb.cc                     \
+  google/protobuf/unittest_optimize_for.pb.h                      \
+  google/protobuf/unittest.pb.cc                                  \
+  google/protobuf/unittest.pb.h                                   \
+  google/protobuf/unittest_preserve_unknown_enum2.pb.cc           \
+  google/protobuf/unittest_preserve_unknown_enum2.pb.h            \
+  google/protobuf/unittest_preserve_unknown_enum.pb.cc            \
+  google/protobuf/unittest_preserve_unknown_enum.pb.h             \
+  google/protobuf/unittest_proto3_arena.pb.cc                     \
+  google/protobuf/unittest_proto3_arena.pb.h                      \
+  google/protobuf/unittest_proto3_arena_lite.pb.cc                     \
+  google/protobuf/unittest_proto3_arena_lite.pb.h                      \
+  google/protobuf/unittest_proto3_lite.pb.cc                     \
+  google/protobuf/unittest_proto3_lite.pb.h                      \
+  google/protobuf/unittest_well_known_types.pb.cc                 \
+  google/protobuf/unittest_well_known_types.pb.h                  \
+  google/protobuf/util/internal/testdata/anys.pb.cc               \
+  google/protobuf/util/internal/testdata/anys.pb.h                \
+  google/protobuf/util/internal/testdata/books.pb.cc              \
+  google/protobuf/util/internal/testdata/books.pb.h               \
+  google/protobuf/util/internal/testdata/default_value.pb.cc      \
+  google/protobuf/util/internal/testdata/default_value.pb.h       \
+  google/protobuf/util/internal/testdata/default_value_test.pb.cc \
+  google/protobuf/util/internal/testdata/default_value_test.pb.h  \
+  google/protobuf/util/internal/testdata/field_mask.pb.cc         \
+  google/protobuf/util/internal/testdata/field_mask.pb.h          \
+  google/protobuf/util/internal/testdata/maps.pb.cc               \
+  google/protobuf/util/internal/testdata/maps.pb.h                \
+  google/protobuf/util/internal/testdata/oneofs.pb.cc             \
+  google/protobuf/util/internal/testdata/oneofs.pb.h              \
+  google/protobuf/util/internal/testdata/struct.pb.cc             \
+  google/protobuf/util/internal/testdata/struct.pb.h              \
+  google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \
+  google/protobuf/util/internal/testdata/timestamp_duration.pb.h  \
+  google/protobuf/util/json_format_proto3.pb.cc                   \
+  google/protobuf/util/json_format_proto3.pb.h                    \
+  google/protobuf/util/message_differencer_unittest.pb.cc         \
+  google/protobuf/util/message_differencer_unittest.pb.h
+
+BUILT_SOURCES = $(protoc_outputs)
+
+if USE_EXTERNAL_PROTOC
+
+unittest_proto_middleman: $(protoc_inputs)
+	$(PROTOC) -I$(srcdir) --cpp_out=. $^
+	touch unittest_proto_middleman
+
+else
+
+# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
+# relative to srcdir, which may not be the same as the current directory when
+# building out-of-tree.
+unittest_proto_middleman: protoc$(EXEEXT) $(protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) )
+	touch unittest_proto_middleman
+
+endif
+
+$(protoc_outputs): unittest_proto_middleman
+
+COMMON_TEST_SOURCES =                                          \
+  google/protobuf/arena_test_util.cc                           \
+  google/protobuf/arena_test_util.h                            \
+  google/protobuf/map_test_util.cc                             \
+  google/protobuf/map_test_util.h                              \
+  google/protobuf/map_test_util_impl.h                         \
+  google/protobuf/test_util.cc                                 \
+  google/protobuf/test_util.h                                  \
+  google/protobuf/testing/googletest.cc                        \
+  google/protobuf/testing/googletest.h                         \
+  google/protobuf/testing/file.cc                              \
+  google/protobuf/testing/file.h
+
+check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
+                 protobuf-lite-test test_plugin protobuf-lite-arena-test \
+                 $(GZCHECKPROGRAMS)
+protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
+                      ../gmock/gtest/lib/libgtest.la              \
+                      ../gmock/lib/libgmock.la                    \
+                      ../gmock/lib/libgmock_main.la
+protobuf_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include \
+                         -I$(srcdir)/../gmock/include
+# Disable optimization for tests unless the user explicitly asked for it,
+# since test_util.cc takes forever to compile with optimization (with GCC).
+# See configure.ac for more info.
+protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_test_SOURCES =                                        \
+  google/protobuf/stubs/bytestream_unittest.cc                 \
+  google/protobuf/stubs/common_unittest.cc                     \
+  google/protobuf/stubs/int128_unittest.cc                     \
+  google/protobuf/stubs/once_unittest.cc                       \
+  google/protobuf/stubs/statusor_test.cc                       \
+  google/protobuf/stubs/status_test.cc                         \
+  google/protobuf/stubs/stringpiece_unittest.cc                \
+  google/protobuf/stubs/stringprintf_unittest.cc               \
+  google/protobuf/stubs/structurally_valid_unittest.cc         \
+  google/protobuf/stubs/strutil_unittest.cc                    \
+  google/protobuf/stubs/template_util_unittest.cc              \
+  google/protobuf/stubs/time_test.cc                           \
+  google/protobuf/stubs/type_traits_unittest.cc                \
+  google/protobuf/any_test.cc                                  \
+  google/protobuf/arenastring_unittest.cc                      \
+  google/protobuf/arena_unittest.cc                            \
+  google/protobuf/descriptor_database_unittest.cc              \
+  google/protobuf/descriptor_unittest.cc                       \
+  google/protobuf/drop_unknown_fields_test.cc                  \
+  google/protobuf/dynamic_message_unittest.cc                  \
+  google/protobuf/extension_set_unittest.cc                    \
+  google/protobuf/generated_message_reflection_unittest.cc     \
+  google/protobuf/map_field_test.cc                            \
+  google/protobuf/map_test.cc                                  \
+  google/protobuf/message_unittest.cc                          \
+  google/protobuf/no_field_presence_test.cc                    \
+  google/protobuf/preserve_unknown_enum_test.cc                \
+  google/protobuf/proto3_arena_unittest.cc                     \
+  google/protobuf/proto3_arena_lite_unittest.cc                     \
+  google/protobuf/proto3_lite_unittest.cc                     \
+  google/protobuf/reflection_ops_unittest.cc                   \
+  google/protobuf/repeated_field_reflection_unittest.cc        \
+  google/protobuf/repeated_field_unittest.cc                   \
+  google/protobuf/text_format_unittest.cc                      \
+  google/protobuf/unknown_field_set_unittest.cc                \
+  google/protobuf/well_known_types_unittest.cc                 \
+  google/protobuf/wire_format_unittest.cc                      \
+  google/protobuf/io/coded_stream_unittest.cc                  \
+  google/protobuf/io/printer_unittest.cc                       \
+  google/protobuf/io/tokenizer_unittest.cc                     \
+  google/protobuf/io/zero_copy_stream_unittest.cc              \
+  google/protobuf/compiler/command_line_interface_unittest.cc  \
+  google/protobuf/compiler/importer_unittest.cc                \
+  google/protobuf/compiler/mock_code_generator.cc              \
+  google/protobuf/compiler/mock_code_generator.h               \
+  google/protobuf/compiler/parser_unittest.cc                  \
+  google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc       \
+  google/protobuf/compiler/cpp/cpp_unittest.h                  \
+  google/protobuf/compiler/cpp/cpp_unittest.cc                 \
+  google/protobuf/compiler/cpp/cpp_plugin_unittest.cc          \
+  google/protobuf/compiler/cpp/metadata_test.cc                \
+  google/protobuf/compiler/java/java_plugin_unittest.cc        \
+  google/protobuf/compiler/java/java_doc_comment_unittest.cc   \
+  google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \
+  google/protobuf/compiler/python/python_plugin_unittest.cc    \
+  google/protobuf/compiler/ruby/ruby_generator_unittest.cc     \
+  google/protobuf/compiler/csharp/csharp_generator_unittest.cc \
+  google/protobuf/util/field_comparator_test.cc                \
+  google/protobuf/util/field_mask_util_test.cc                 \
+  google/protobuf/util/internal/default_value_objectwriter_test.cc \
+  google/protobuf/util/internal/json_objectwriter_test.cc      \
+  google/protobuf/util/internal/json_stream_parser_test.cc     \
+  google/protobuf/util/internal/protostream_objectsource_test.cc \
+  google/protobuf/util/internal/protostream_objectwriter_test.cc \
+  google/protobuf/util/internal/type_info_test_helper.cc       \
+  google/protobuf/util/json_util_test.cc                       \
+  google/protobuf/util/message_differencer_unittest.cc         \
+  google/protobuf/util/time_util_test.cc                       \
+  google/protobuf/util/type_resolver_util_test.cc              \
+  $(COMMON_TEST_SOURCES)
+
+
+nodist_protobuf_test_SOURCES = $(protoc_outputs)
+
+# Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined.
+protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
+                      libprotoc.la                                   \
+                      ../gmock/gtest/lib/libgtest.la                 \
+                      ../gmock/lib/libgmock.la                       \
+                      ../gmock/lib/libgmock_main.la
+protobuf_lazy_descriptor_test_CPPFLAGS = -I$(srcdir)/../gmock/include       \
+                                         -I$(srcdir)/../gmock/gtest/include \
+                                         -DPROTOBUF_TEST_NO_DESCRIPTORS
+protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_lazy_descriptor_test_SOURCES =                        \
+  google/protobuf/compiler/cpp/cpp_unittest.cc                 \
+  $(COMMON_TEST_SOURCES)
+nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
+
+COMMON_LITE_TEST_SOURCES =                                             \
+  google/protobuf/arena_test_util.cc                                   \
+  google/protobuf/arena_test_util.h                                    \
+  google/protobuf/map_lite_test_util.cc                                \
+  google/protobuf/map_lite_test_util.h                                 \
+  google/protobuf/test_util_lite.cc                                    \
+  google/protobuf/test_util_lite.h
+
+# Build lite_unittest separately, since it doesn't use gtest. It can't
+# depend on gtest because our internal version of gtest depend on proto
+# full runtime and we want to make sure this test builds without full
+# runtime.
+protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
+protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_lite_test_SOURCES =                                           \
+  google/protobuf/lite_unittest.cc                                     \
+  $(COMMON_LITE_TEST_SOURCES)
+nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
+
+# lite_arena_unittest depends on gtest because teboring@ found that without
+# gtest when building the test internally our memory sanitizer doesn't detect
+# memory leaks (don't know why).
+protobuf_lite_arena_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \
+                      ../gmock/gtest/lib/libgtest.la                 \
+                      ../gmock/lib/libgmock.la                       \
+                      ../gmock/lib/libgmock_main.la
+protobuf_lite_arena_test_CPPFLAGS = -I$(srcdir)/../gmock/include       \
+                                    -I$(srcdir)/../gmock/gtest/include
+protobuf_lite_arena_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_lite_arena_test_SOURCES =       \
+  google/protobuf/lite_arena_unittest.cc \
+  $(COMMON_LITE_TEST_SOURCES)
+nodist_protobuf_lite_arena_test_SOURCES = $(protoc_lite_outputs)
+
+# Test plugin binary.
+test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
+                    ../gmock/gtest/lib/libgtest.la
+test_plugin_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include
+test_plugin_SOURCES =                                          \
+  google/protobuf/compiler/mock_code_generator.cc              \
+  google/protobuf/testing/file.cc                              \
+  google/protobuf/testing/file.h                               \
+  google/protobuf/compiler/test_plugin.cc
+
+if HAVE_ZLIB
+zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
+zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
+
+zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
+zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
+endif
+
+TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
+        google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS)     \
+        protobuf-lite-arena-test
diff --git a/src/third_party/protobuf-3/src/README.md b/src/third_party/protobuf-3/src/README.md
new file mode 100644
index 0000000..63d6e24
--- /dev/null
+++ b/src/third_party/protobuf-3/src/README.md
@@ -0,0 +1,212 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
+
+Copyright 2008 Google Inc.
+
+https://developers.google.com/protocol-buffers/
+
+C++ Installation - Unix
+-----------------------
+
+To build protobuf from source, the following tools are needed:
+
+  * autoconf
+  * automake
+  * libtool
+  * curl (used to download gmock)
+  * make
+  * g++
+  * unzip
+
+On Ubuntu, you can install them with:
+
+  $ sudo apt-get install autoconf automake libtool curl make g++ unzip
+
+On other platforms, please use the corresponding package managing tool to
+install them before proceeding.
+
+If you get the source from github, you need to generate the configure script
+first:
+
+    $ ./autogen.sh
+
+This will download gmock source (which is used for C++ Protocol Buffer
+unit-tests) to the current directory and run automake, autoconf, etc.
+to generate the configure script and various template makefiles.
+
+You can skip this step if you are using a release package (which already
+contains gmock and the configure script).
+
+To build and install the C++ Protocol Buffer runtime and the Protocol
+Buffer compiler (protoc) execute the following:
+
+    $ ./configure
+    $ make
+    $ make check
+    $ sudo make install
+    $ sudo ldconfig # refresh shared library cache.
+
+If "make check" fails, you can still install, but it is likely that
+some features of this library will not work correctly on your system.
+Proceed at your own risk.
+
+For advanced usage information on configure and make, please refer to the
+autoconf documentation:
+
+  http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts
+
+**Hint on install location**
+
+  By default, the package will be installed to /usr/local.  However,
+  on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH.
+  You can add it, but it may be easier to just install to /usr
+  instead.  To do this, invoke configure as follows:
+
+    ./configure --prefix=/usr
+
+  If you already built the package with a different prefix, make sure
+  to run "make clean" before building again.
+
+**Compiling dependent packages**
+
+  To compile a package that uses Protocol Buffers, you need to pass
+  various flags to your compiler and linker.  As of version 2.2.0,
+  Protocol Buffers integrates with pkg-config to manage this.  If you
+  have pkg-config installed, then you can invoke it to get a list of
+  flags like so:
+
+    pkg-config --cflags protobuf         # print compiler flags
+    pkg-config --libs protobuf           # print linker flags
+    pkg-config --cflags --libs protobuf  # print both
+
+  For example:
+
+    c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf`
+
+  Note that packages written prior to the 2.2.0 release of Protocol
+  Buffers may not yet integrate with pkg-config to get flags, and may
+  not pass the correct set of flags to correctly link against
+  libprotobuf.  If the package in question uses autoconf, you can
+  often fix the problem by invoking its configure script like:
+
+    configure CXXFLAGS="$(pkg-config --cflags protobuf)" \
+              LIBS="$(pkg-config --libs protobuf)"
+
+  This will force it to use the correct flags.
+
+  If you are writing an autoconf-based package that uses Protocol
+  Buffers, you should probably use the PKG_CHECK_MODULES macro in your
+  configure script like:
+
+    PKG_CHECK_MODULES([protobuf], [protobuf])
+
+  See the pkg-config man page for more info.
+
+  If you only want protobuf-lite, substitute "protobuf-lite" in place
+  of "protobuf" in these examples.
+
+**Note for Mac users**
+
+  For a Mac system, Unix tools are not available by default. You will first need
+  to install Xcode from the Mac AppStore and then run the following command from
+  a terminal:
+
+    $ sudo xcode-select --install
+
+  To install Unix tools, you can install "port" following the instructions at
+  https://www.macports.org . This will reside in /opt/local/bin/port for most
+  Mac installations.
+
+    $ sudo /opt/local/bin/port install autoconf automake libtool
+
+  Then follow the Unix instructions above.
+
+**Note for cross-compiling**
+
+  The makefiles normally invoke the protoc executable that they just
+  built in order to build tests.  When cross-compiling, the protoc
+  executable may not be executable on the host machine.  In this case,
+  you must build a copy of protoc for the host machine first, then use
+  the --with-protoc option to tell configure to use it instead.  For
+  example:
+
+    ./configure --with-protoc=protoc
+
+  This will use the installed protoc (found in your $PATH) instead of
+  trying to execute the one built during the build process.  You can
+  also use an executable that hasn't been installed.  For example, if
+  you built the protobuf package for your host machine in ../host,
+  you might do:
+
+    ./configure --with-protoc=../host/src/protoc
+
+  Either way, you must make sure that the protoc executable you use
+  has the same version as the protobuf source code you are trying to
+  use it with.
+
+**Note for Solaris users**
+
+  Solaris 10 x86 has a bug that will make linking fail, complaining
+  about libstdc++.la being invalid.  We have included a work-around
+  in this package.  To use the work-around, run configure as follows:
+
+    ./configure LDFLAGS=-L$PWD/src/solaris
+
+  See src/solaris/libstdc++.la for more info on this bug.
+
+**Note for HP C++ Tru64 users**
+
+  To compile invoke configure as follows:
+
+    ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM"
+
+  Also, you will need to use gmake instead of make.
+
+**Note for AIX users**
+
+  Compile using the IBM xlC C++ compiler as follows:
+
+    ./configure CXX=xlC
+
+  Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`.
+
+C++ Installation - Windows
+--------------------------
+
+If you only need the protoc binary, you can download it from the release
+page:
+
+  https://github.com/google/protobuf/releases
+
+In the downloads section, download the zip file protoc-$VERSION-win32.zip.
+It contains the protoc binary as well as public proto files of protobuf
+library.
+
+To build from source using Microsoft Visual C++, see [cmake/README.md](../cmake/README.md).
+
+To build from source using Cygwin or MinGW, follow the Unix installation
+instructions, above.
+
+Binary Compatibility Warning
+----------------------------
+
+Due to the nature of C++, it is unlikely that any two versions of the
+Protocol Buffers C++ runtime libraries will have compatible ABIs.
+That is, if you linked an executable against an older version of
+libprotobuf, it is unlikely to work with a newer version without
+re-compiling.  This problem, when it occurs, will normally be detected
+immediately on startup of your app.  Still, you may want to consider
+using static linkage.  You can configure this package to install
+static libraries only using:
+
+    ./configure --disable-shared
+
+Usage
+-----
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+    https://developers.google.com/protocol-buffers/
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any.cc b/src/third_party/protobuf-3/src/google/protobuf/any.cc
new file mode 100644
index 0000000..f7b1d31
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any.cc
@@ -0,0 +1,114 @@
+// 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.
+
+#include <google/protobuf/any.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+string GetTypeUrl(const Descriptor* message,
+                  const string& type_url_prefix) {
+  if (!type_url_prefix.empty() &&
+      type_url_prefix[type_url_prefix.size() - 1] == '/') {
+    return type_url_prefix + message->full_name();
+  } else {
+    return type_url_prefix + "/" + message->full_name();
+  }
+}
+}  // namespace
+
+const char kAnyFullTypeName[] = "google.protobuf.Any";
+const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
+const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
+
+AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
+    : type_url_(type_url), value_(value) {
+}
+
+void AnyMetadata::PackFrom(const Message& message) {
+  PackFrom(message, kTypeGoogleApisComPrefix);
+}
+
+void AnyMetadata::PackFrom(const Message& message,
+                           const string& type_url_prefix) {
+  type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
+                        GetTypeUrl(message.GetDescriptor(), type_url_prefix));
+  message.SerializeToString(value_->MutableNoArena(
+      &::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+}
+
+bool AnyMetadata::UnpackTo(Message* message) const {
+  if (!InternalIs(message->GetDescriptor())) {
+    return false;
+  }
+  return message->ParseFromString(
+      value_->GetNoArena(&::google::protobuf::internal::GetEmptyString()));
+}
+
+bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
+  const string type_url = type_url_->GetNoArena(
+             &::google::protobuf::internal::GetEmptyString());
+  string full_name;
+  if (!ParseAnyTypeUrl(type_url, &full_name)) {
+    return false;
+  }
+  return full_name == descriptor->full_name();
+}
+
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
+  size_t pos = type_url.find_last_of("/");
+  if (pos == string::npos || pos + 1 == type_url.size()) {
+    return false;
+  }
+  *full_type_name = type_url.substr(pos + 1);
+  return true;
+}
+
+
+bool GetAnyFieldDescriptors(const Message& message,
+                            const FieldDescriptor** type_url_field,
+                            const FieldDescriptor** value_field) {
+    const Descriptor* descriptor = message.GetDescriptor();
+    if (descriptor->full_name() != kAnyFullTypeName) {
+      return false;
+    }
+    *type_url_field = descriptor->FindFieldByNumber(1);
+    *value_field = descriptor->FindFieldByNumber(2);
+    return (*type_url_field != NULL &&
+            (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+            *value_field != NULL &&
+            (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any.h b/src/third_party/protobuf-3/src/google/protobuf/any.h
new file mode 100644
index 0000000..04e5416
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any.h
@@ -0,0 +1,107 @@
+// 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_ANY_H__
+#define GOOGLE_PROTOBUF_ANY_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/arenastring.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Helper class used to implement google::protobuf::Any.
+class LIBPROTOBUF_EXPORT AnyMetadata {
+  typedef ArenaStringPtr UrlType;
+  typedef ArenaStringPtr ValueType;
+ public:
+  // AnyMetadata does not take ownership of "type_url" and "value".
+  AnyMetadata(UrlType* type_url, ValueType* value);
+
+  // Packs a message using the default type URL prefix: "type.googleapis.com".
+  // The resulted type URL will be "type.googleapis.com/<message_full_name>".
+  void PackFrom(const Message& message);
+  // Packs a message using the given type URL prefix. The type URL will be
+  // constructed by concatenating the message type's full name to the prefix
+  // with an optional "/" separator if the prefix doesn't already end up "/".
+  // For example, both PackFrom(message, "type.googleapis.com") and
+  // PackFrom(message, "type.googleapis.com/") yield the same result type
+  // URL: "type.googleapis.com/<message_full_name>".
+  void PackFrom(const Message& message, const string& type_url_prefix);
+
+  // Unpacks the payload into the given message. Returns false if the message's
+  // type doesn't match the type specified in the type URL (i.e., the full
+  // name after the last "/" of the type URL doesn't match the message's actaul
+  // full name) or parsing the payload has failed.
+  bool UnpackTo(Message* message) const;
+
+  // Checks whether the type specified in the type URL matches the given type.
+  // A type is consdiered matching if its full name matches the full name after
+  // the last "/" in the type URL.
+  template<typename T>
+  bool Is() const {
+    return InternalIs(T::default_instance().GetDescriptor());
+  }
+
+ private:
+  bool InternalIs(const Descriptor* message) const;
+
+  UrlType* type_url_;
+  ValueType* value_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
+};
+
+extern const char kAnyFullTypeName[];          // "google.protobuf.Any".
+extern const char kTypeGoogleApisComPrefix[];  // "type.googleapis.com/".
+extern const char kTypeGoogleProdComPrefix[];  // "type.googleprod.com/".
+
+// Get the proto type name from Any::type_url value. For example, passing
+// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
+// *full_type_name. Returns false if type_url does not start with
+// "type.googleapis.com" or "type.googleprod.com".
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
+
+// See if message is of type google.protobuf.Any, if so, return the descriptors
+// for "type_url" and "value" fields.
+bool GetAnyFieldDescriptors(const Message& message,
+                            const FieldDescriptor** type_url_field,
+                            const FieldDescriptor** value_field);
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ANY_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/any.pb.cc
new file mode 100644
index 0000000..fbde4a6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any.pb.cc
@@ -0,0 +1,499 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/any.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Any_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Any_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/any.proto");
+  GOOGLE_CHECK(file != NULL);
+  Any_descriptor_ = file->message_type(0);
+  static const int Any_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_),
+  };
+  Any_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Any_descriptor_,
+      Any::default_instance_,
+      Any_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Any),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Any_descriptor_, &Any::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto() {
+  delete Any::default_instance_;
+  delete Any_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\031google/protobuf/any.proto\022\017google.prot"
+    "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
+    " \001(\014Br\n\023com.google.protobufB\010AnyProtoP\001Z"
+    "%github.com/golang/protobuf/ptypes/any\240\001"
+    "\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes"
+    "b\006proto3", 208);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/any.proto", &protobuf_RegisterTypes);
+  Any::default_instance_ = new Any();
+  Any::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fany_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+void Any::PackFrom(const ::google::protobuf::Message& message) {
+  _any_metadata_.PackFrom(message);
+}
+
+void Any::PackFrom(const ::google::protobuf::Message& message,
+                           const ::std::string& type_url_prefix) {
+  _any_metadata_.PackFrom(message, type_url_prefix);
+}
+
+bool Any::UnpackTo(::google::protobuf::Message* message) const {
+  return _any_metadata_.UnpackTo(message);
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Any::kTypeUrlFieldNumber;
+const int Any::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Any::Any()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Any)
+}
+
+void Any::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Any::Any(const Any& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL),
+    _any_metadata_(&type_url_, &value_) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
+}
+
+void Any::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Any::~Any() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Any)
+  SharedDtor();
+}
+
+void Any::SharedDtor() {
+  type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void Any::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Any::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Any_descriptor_;
+}
+
+const Any& Any::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+  return *default_instance_;
+}
+
+Any* Any::default_instance_ = NULL;
+
+Any* Any::New(::google::protobuf::Arena* arena) const {
+  Any* n = new Any;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Any::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool Any::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Any)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string type_url = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_type_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->type_url().data(), this->type_url().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Any.type_url"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_value;
+        break;
+      }
+
+      // optional bytes value = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Any)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Any)
+  return false;
+#undef DO_
+}
+
+void Any::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Any)
+  // optional string type_url = 1;
+  if (this->type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->type_url().data(), this->type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Any.type_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->type_url(), output);
+  }
+
+  // optional bytes value = 2;
+  if (this->value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      2, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Any)
+}
+
+::google::protobuf::uint8* Any::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
+  // optional string type_url = 1;
+  if (this->type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->type_url().data(), this->type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Any.type_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->type_url(), target);
+  }
+
+  // optional bytes value = 2;
+  if (this->value().size() > 0) {
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        2, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
+  return target;
+}
+
+int Any::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
+  int total_size = 0;
+
+  // optional string type_url = 1;
+  if (this->type_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->type_url());
+  }
+
+  // optional bytes value = 2;
+  if (this->value().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::BytesSize(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Any::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Any* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Any>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
+    MergeFrom(*source);
+  }
+}
+
+void Any::MergeFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.type_url().size() > 0) {
+
+    type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
+  }
+  if (from.value().size() > 0) {
+
+    value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
+  }
+}
+
+void Any::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Any::CopyFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Any::IsInitialized() const {
+
+  return true;
+}
+
+void Any::Swap(Any* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Any::InternalSwap(Any* other) {
+  type_url_.Swap(&other->type_url_);
+  value_.Swap(&other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Any::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Any_descriptor_;
+  metadata.reflection = Any_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Any
+
+// optional string type_url = 1;
+void Any::clear_type_url() {
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Any::type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
+  return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_type_url(const ::std::string& value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
+}
+ void Any::set_type_url(const char* value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
+}
+ void Any::set_type_url(const char* value, size_t size) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
+}
+ ::std::string* Any::mutable_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
+  return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Any::release_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
+  
+  return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_allocated_type_url(::std::string* type_url) {
+  if (type_url != NULL) {
+    
+  } else {
+    
+  }
+  type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
+}
+
+// optional bytes value = 2;
+void Any::clear_value() {
+  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Any::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
+  return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_value(const ::std::string& value) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
+}
+ void Any::set_value(const char* value) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
+}
+ void Any::set_value(const void* value, size_t size) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
+}
+ ::std::string* Any::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
+  return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Any::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
+  
+  return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any.pb.h b/src/third_party/protobuf-3/src/google/protobuf/any.pb.h
new file mode 100644
index 0000000..100a67f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any.pb.h
@@ -0,0 +1,254 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/any.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
+
+class Any;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message {
+ public:
+  Any();
+  virtual ~Any();
+
+  Any(const Any& from);
+
+  inline Any& operator=(const Any& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Any& default_instance();
+
+  // implements Any -----------------------------------------------
+
+  void PackFrom(const ::google::protobuf::Message& message);
+  void PackFrom(const ::google::protobuf::Message& message,
+                const ::std::string& type_url_prefix);
+  bool UnpackTo(::google::protobuf::Message* message) const;
+  template<typename T> bool Is() const {
+    return _any_metadata_.Is<T>();
+  }
+
+  void Swap(Any* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Any* New() const { return New(NULL); }
+
+  Any* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Any& from);
+  void MergeFrom(const Any& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Any* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string type_url = 1;
+  void clear_type_url();
+  static const int kTypeUrlFieldNumber = 1;
+  const ::std::string& type_url() const;
+  void set_type_url(const ::std::string& value);
+  void set_type_url(const char* value);
+  void set_type_url(const char* value, size_t size);
+  ::std::string* mutable_type_url();
+  ::std::string* release_type_url();
+  void set_allocated_type_url(::std::string* type_url);
+
+  // optional bytes value = 2;
+  void clear_value();
+  static const int kValueFieldNumber = 2;
+  const ::std::string& value() const;
+  void set_value(const ::std::string& value);
+  void set_value(const char* value);
+  void set_value(const void* value, size_t size);
+  ::std::string* mutable_value();
+  ::std::string* release_value();
+  void set_allocated_value(::std::string* value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Any)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr type_url_;
+  ::google::protobuf::internal::ArenaStringPtr value_;
+  mutable int _cached_size_;
+  ::google::protobuf::internal::AnyMetadata _any_metadata_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
+
+  void InitAsDefaultInstance();
+  static Any* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Any
+
+// optional string type_url = 1;
+inline void Any::clear_type_url() {
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Any::type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
+  return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_type_url(const ::std::string& value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
+}
+inline void Any::set_type_url(const char* value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
+}
+inline void Any::set_type_url(const char* value, size_t size) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
+}
+inline ::std::string* Any::mutable_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
+  return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Any::release_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
+  
+  return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_allocated_type_url(::std::string* type_url) {
+  if (type_url != NULL) {
+    
+  } else {
+    
+  }
+  type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
+}
+
+// optional bytes value = 2;
+inline void Any::clear_value() {
+  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Any::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
+  return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_value(const ::std::string& value) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
+}
+inline void Any::set_value(const char* value) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
+}
+inline void Any::set_value(const void* value, size_t size) {
+  
+  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
+}
+inline ::std::string* Any::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
+  return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Any::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
+  
+  return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any.proto b/src/third_party/protobuf-3/src/google/protobuf/any.proto
new file mode 100644
index 0000000..45db6ed
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any.proto
@@ -0,0 +1,130 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "AnyProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+//     Foo foo = ...;
+//     Any any;
+//     any.PackFrom(foo);
+//     ...
+//     if (any.UnpackTo(&foo)) {
+//       ...
+//     }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+//     Foo foo = ...;
+//     Any any = Any.pack(foo);
+//     ...
+//     if (any.is(Foo.class)) {
+//       foo = any.unpack(Foo.class);
+//     }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+//     package google.profile;
+//     message Person {
+//       string first_name = 1;
+//       string last_name = 2;
+//     }
+//
+//     {
+//       "@type": "type.googleapis.com/google.profile.Person",
+//       "firstName": <string>,
+//       "lastName": <string>
+//     }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+//     {
+//       "@type": "type.googleapis.com/google.protobuf.Duration",
+//       "value": "1.212s"
+//     }
+//
+message Any {
+  // A URL/resource name whose content describes the type of the
+  // serialized protocol buffer message.
+  //
+  // For URLs which use the schema `http`, `https`, or no schema, the
+  // following restrictions and interpretations apply:
+  //
+  // * If no schema is provided, `https` is assumed.
+  // * The last segment of the URL's path must represent the fully
+  //   qualified name of the type (as in `path/google.protobuf.Duration`).
+  //   The name should be in a canonical form (e.g., leading "." is
+  //   not accepted).
+  // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+  //   value in binary format, or produce an error.
+  // * Applications are allowed to cache lookup results based on the
+  //   URL, or have them precompiled into a binary to avoid any
+  //   lookup. Therefore, binary compatibility needs to be preserved
+  //   on changes to types. (Use versioned type names to manage
+  //   breaking changes.)
+  //
+  // Schemas other than `http`, `https` (or the empty schema) might be
+  // used with implementation specific semantics.
+  //
+  string type_url = 1;
+
+  // Must be a valid serialized protocol buffer of the above specified type.
+  bytes value = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any_test.cc b/src/third_party/protobuf-3/src/google/protobuf/any_test.cc
new file mode 100644
index 0000000..1bfaa63
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any_test.cc
@@ -0,0 +1,89 @@
+// 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.
+
+#include <google/protobuf/any_test.pb.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(AnyTest, TestPackAndUnpack) {
+  protobuf_unittest::TestAny submessage;
+  submessage.set_int32_value(12345);
+  protobuf_unittest::TestAny message;
+  message.mutable_any_value()->PackFrom(submessage);
+
+  string data = message.SerializeAsString();
+
+  ASSERT_TRUE(message.ParseFromString(data));
+  EXPECT_TRUE(message.has_any_value());
+  ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
+  EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestPackAndUnpackAny) {
+  // We can pack a Any message inside another Any message.
+  protobuf_unittest::TestAny submessage;
+  submessage.set_int32_value(12345);
+  google::protobuf::Any any;
+  any.PackFrom(submessage);
+  protobuf_unittest::TestAny message;
+  message.mutable_any_value()->PackFrom(any);
+
+  string data = message.SerializeAsString();
+
+  ASSERT_TRUE(message.ParseFromString(data));
+  EXPECT_TRUE(message.has_any_value());
+  ASSERT_TRUE(message.any_value().UnpackTo(&any));
+  ASSERT_TRUE(any.UnpackTo(&submessage));
+  EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestIs) {
+  protobuf_unittest::TestAny submessage;
+  submessage.set_int32_value(12345);
+  google::protobuf::Any any;
+  any.PackFrom(submessage);
+  ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
+  EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
+  EXPECT_FALSE(any.Is<google::protobuf::Any>());
+
+  protobuf_unittest::TestAny message;
+  message.mutable_any_value()->PackFrom(any);
+  ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
+  EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
+  EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
+}
+
+}  // namespace
+}  // namespace protobuf
+
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/any_test.proto b/src/third_party/protobuf-3/src/google/protobuf/any_test.proto
new file mode 100644
index 0000000..0c5b30b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/any_test.proto
@@ -0,0 +1,41 @@
+// 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.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+  int32 int32_value = 1;
+  google.protobuf.Any any_value = 2;
+  repeated google.protobuf.Any repeated_any_value = 3;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/api.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/api.pb.cc
new file mode 100644
index 0000000..cbeba30
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/api.pb.cc
@@ -0,0 +1,2023 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/api.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Api_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Api_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Method_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Method_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Mixin_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Mixin_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/api.proto");
+  GOOGLE_CHECK(file != NULL);
+  Api_descriptor_ = file->message_type(0);
+  static const int Api_offsets_[7] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, methods_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, version_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, source_context_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, mixins_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, syntax_),
+  };
+  Api_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Api_descriptor_,
+      Api::default_instance_,
+      Api_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Api),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _is_default_instance_));
+  Method_descriptor_ = file->message_type(1);
+  static const int Method_offsets_[7] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_type_url_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_streaming_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_type_url_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_streaming_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, syntax_),
+  };
+  Method_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Method_descriptor_,
+      Method::default_instance_,
+      Method_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Method),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _is_default_instance_));
+  Mixin_descriptor_ = file->message_type(2);
+  static const int Mixin_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, root_),
+  };
+  Mixin_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Mixin_descriptor_,
+      Mixin::default_instance_,
+      Mixin_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Mixin),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Api_descriptor_, &Api::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Method_descriptor_, &Method::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Mixin_descriptor_, &Mixin::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto() {
+  delete Api::default_instance_;
+  delete Api_reflection_;
+  delete Method::default_instance_;
+  delete Method_reflection_;
+  delete Mixin::default_instance_;
+  delete Mixin_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\031google/protobuf/api.proto\022\017google.prot"
+    "obuf\032$google/protobuf/source_context.pro"
+    "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
+    "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p"
+    "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google"
+    ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou"
+    "rce_context\030\005 \001(\0132\036.google.protobuf.Sour"
+    "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto"
+    "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto"
+    "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r"
+    "equest_type_url\030\002 \001(\t\022\031\n\021request_streami"
+    "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r"
+    "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013"
+    "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001("
+    "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n"
+    "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBK\n\023com.google.pr"
+    "otobufB\010ApiProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pro"
+    "tobuf.WellKnownTypesb\006proto3", 708);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/api.proto", &protobuf_RegisterTypes);
+  Api::default_instance_ = new Api();
+  Method::default_instance_ = new Method();
+  Mixin::default_instance_ = new Mixin();
+  Api::default_instance_->InitAsDefaultInstance();
+  Method::default_instance_->InitAsDefaultInstance();
+  Mixin::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fapi_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Api::kNameFieldNumber;
+const int Api::kMethodsFieldNumber;
+const int Api::kOptionsFieldNumber;
+const int Api::kVersionFieldNumber;
+const int Api::kSourceContextFieldNumber;
+const int Api::kMixinsFieldNumber;
+const int Api::kSyntaxFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Api::Api()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Api)
+}
+
+void Api::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+  source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Api::Api(const Api& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Api)
+}
+
+void Api::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  source_context_ = NULL;
+  syntax_ = 0;
+}
+
+Api::~Api() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Api)
+  SharedDtor();
+}
+
+void Api::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete source_context_;
+  }
+}
+
+void Api::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Api::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Api_descriptor_;
+}
+
+const Api& Api::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  return *default_instance_;
+}
+
+Api* Api::default_instance_ = NULL;
+
+Api* Api::New(::google::protobuf::Arena* arena) const {
+  Api* n = new Api;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Api::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+  syntax_ = 0;
+  methods_.Clear();
+  options_.Clear();
+  mixins_.Clear();
+}
+
+bool Api::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Api)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Api.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_methods;
+        break;
+      }
+
+      // repeated .google.protobuf.Method methods = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_methods:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_methods:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_methods()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_methods;
+        if (input->ExpectTag(26)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 3;
+      case 3: {
+        if (tag == 26) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(34)) goto parse_version;
+        break;
+      }
+
+      // optional string version = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_version:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_version()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->version().data(), this->version().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Api.version"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(42)) goto parse_source_context;
+        break;
+      }
+
+      // optional .google.protobuf.SourceContext source_context = 5;
+      case 5: {
+        if (tag == 42) {
+         parse_source_context:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_context()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_mixins;
+        break;
+      }
+
+      // repeated .google.protobuf.Mixin mixins = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_mixins:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_mixins:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_mixins()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_loop_mixins;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(56)) goto parse_syntax;
+        break;
+      }
+
+      // optional .google.protobuf.Syntax syntax = 7;
+      case 7: {
+        if (tag == 56) {
+         parse_syntax:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Api)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Api)
+  return false;
+#undef DO_
+}
+
+void Api::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Api)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Api.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.Method methods = 2;
+  for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->methods(i), output);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, this->options(i), output);
+  }
+
+  // optional string version = 4;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), this->version().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Api.version");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->version(), output);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      5, *this->source_context_, output);
+  }
+
+  // repeated .google.protobuf.Mixin mixins = 6;
+  for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6, this->mixins(i), output);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      7, this->syntax(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Api)
+}
+
+::google::protobuf::uint8* Api::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Api.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.Method methods = 2;
+  for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->methods(i), target);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(i), target);
+  }
+
+  // optional string version = 4;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), this->version().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Api.version");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->version(), target);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, *this->source_context_, target);
+  }
+
+  // repeated .google.protobuf.Mixin mixins = 6;
+  for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->mixins(i), target);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      7, this->syntax(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api)
+  return target;
+}
+
+int Api::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional string version = 4;
+  if (this->version().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->version());
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        *this->source_context_);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+  }
+
+  // repeated .google.protobuf.Method methods = 2;
+  total_size += 1 * this->methods_size();
+  for (int i = 0; i < this->methods_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->methods(i));
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  // repeated .google.protobuf.Mixin mixins = 6;
+  total_size += 1 * this->mixins_size();
+  for (int i = 0; i < this->mixins_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->mixins(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Api::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Api* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Api>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Api)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Api)
+    MergeFrom(*source);
+  }
+}
+
+void Api::MergeFrom(const Api& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  methods_.MergeFrom(from.methods_);
+  options_.MergeFrom(from.options_);
+  mixins_.MergeFrom(from.mixins_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.version().size() > 0) {
+
+    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+  }
+  if (from.has_source_context()) {
+    mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+  }
+  if (from.syntax() != 0) {
+    set_syntax(from.syntax());
+  }
+}
+
+void Api::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Api)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Api::CopyFrom(const Api& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Api)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Api::IsInitialized() const {
+
+  return true;
+}
+
+void Api::Swap(Api* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Api::InternalSwap(Api* other) {
+  name_.Swap(&other->name_);
+  methods_.UnsafeArenaSwap(&other->methods_);
+  options_.UnsafeArenaSwap(&other->options_);
+  version_.Swap(&other->version_);
+  std::swap(source_context_, other->source_context_);
+  mixins_.UnsafeArenaSwap(&other->mixins_);
+  std::swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Api::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Api_descriptor_;
+  metadata.reflection = Api_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Api
+
+// optional string name = 1;
+void Api::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Api::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
+}
+ void Api::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
+}
+ void Api::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
+}
+ ::std::string* Api::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Api::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
+}
+
+// repeated .google.protobuf.Method methods = 2;
+int Api::methods_size() const {
+  return methods_.size();
+}
+void Api::clear_methods() {
+  methods_.Clear();
+}
+const ::google::protobuf::Method& Api::methods(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
+  return methods_.Get(index);
+}
+::google::protobuf::Method* Api::mutable_methods(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
+  return methods_.Mutable(index);
+}
+::google::protobuf::Method* Api::add_methods() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
+  return methods_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+Api::mutable_methods() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
+  return &methods_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+  return methods_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+int Api::options_size() const {
+  return options_.size();
+}
+void Api::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& Api::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* Api::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* Api::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Api::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+  return options_;
+}
+
+// optional string version = 4;
+void Api::clear_version() {
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Api::version() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
+  return version_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_version(const ::std::string& value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
+}
+ void Api::set_version(const char* value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
+}
+ void Api::set_version(const char* value, size_t size) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
+}
+ ::std::string* Api::mutable_version() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
+  return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Api::release_version() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
+  
+  return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_allocated_version(::std::string* version) {
+  if (version != NULL) {
+    
+  } else {
+    
+  }
+  version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+bool Api::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+void Api::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+const ::google::protobuf::SourceContext& Api::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+::google::protobuf::SourceContext* Api::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
+  return source_context_;
+}
+::google::protobuf::SourceContext* Api::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
+}
+
+// repeated .google.protobuf.Mixin mixins = 6;
+int Api::mixins_size() const {
+  return mixins_.size();
+}
+void Api::clear_mixins() {
+  mixins_.Clear();
+}
+const ::google::protobuf::Mixin& Api::mixins(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
+  return mixins_.Get(index);
+}
+::google::protobuf::Mixin* Api::mutable_mixins(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
+  return mixins_.Mutable(index);
+}
+::google::protobuf::Mixin* Api::add_mixins() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
+  return mixins_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+Api::mutable_mixins() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
+  return &mixins_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+Api::mixins() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
+  return mixins_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+void Api::clear_syntax() {
+  syntax_ = 0;
+}
+ ::google::protobuf::Syntax Api::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Api::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Method::kNameFieldNumber;
+const int Method::kRequestTypeUrlFieldNumber;
+const int Method::kRequestStreamingFieldNumber;
+const int Method::kResponseTypeUrlFieldNumber;
+const int Method::kResponseStreamingFieldNumber;
+const int Method::kOptionsFieldNumber;
+const int Method::kSyntaxFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Method::Method()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Method)
+}
+
+void Method::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Method::Method(const Method& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Method)
+}
+
+void Method::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  request_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  request_streaming_ = false;
+  response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  response_streaming_ = false;
+  syntax_ = 0;
+}
+
+Method::~Method() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Method)
+  SharedDtor();
+}
+
+void Method::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  request_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  response_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void Method::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Method::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Method_descriptor_;
+}
+
+const Method& Method::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  return *default_instance_;
+}
+
+Method* Method::default_instance_ = NULL;
+
+Method* Method::New(::google::protobuf::Arena* arena) const {
+  Method* n = new Method;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Method::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(Method, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Method*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(request_streaming_, syntax_);
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  options_.Clear();
+}
+
+bool Method::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Method)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Method.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_request_type_url;
+        break;
+      }
+
+      // optional string request_type_url = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_request_type_url:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_request_type_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->request_type_url().data(), this->request_type_url().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Method.request_type_url"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_request_streaming;
+        break;
+      }
+
+      // optional bool request_streaming = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_request_streaming:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &request_streaming_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_response_type_url;
+        break;
+      }
+
+      // optional string response_type_url = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_response_type_url:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_response_type_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->response_type_url().data(), this->response_type_url().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Method.response_type_url"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_response_streaming;
+        break;
+      }
+
+      // optional bool response_streaming = 5;
+      case 5: {
+        if (tag == 40) {
+         parse_response_streaming:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &response_streaming_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_options;
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_options:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(56)) goto parse_syntax;
+        break;
+      }
+
+      // optional .google.protobuf.Syntax syntax = 7;
+      case 7: {
+        if (tag == 56) {
+         parse_syntax:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Method)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Method)
+  return false;
+#undef DO_
+}
+
+void Method::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Method)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string request_type_url = 2;
+  if (this->request_type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->request_type_url().data(), this->request_type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.request_type_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->request_type_url(), output);
+  }
+
+  // optional bool request_streaming = 3;
+  if (this->request_streaming() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->request_streaming(), output);
+  }
+
+  // optional string response_type_url = 4;
+  if (this->response_type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->response_type_url().data(), this->response_type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.response_type_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->response_type_url(), output);
+  }
+
+  // optional bool response_streaming = 5;
+  if (this->response_streaming() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->response_streaming(), output);
+  }
+
+  // repeated .google.protobuf.Option options = 6;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6, this->options(i), output);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      7, this->syntax(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Method)
+}
+
+::google::protobuf::uint8* Method::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string request_type_url = 2;
+  if (this->request_type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->request_type_url().data(), this->request_type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.request_type_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->request_type_url(), target);
+  }
+
+  // optional bool request_streaming = 3;
+  if (this->request_streaming() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->request_streaming(), target);
+  }
+
+  // optional string response_type_url = 4;
+  if (this->response_type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->response_type_url().data(), this->response_type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Method.response_type_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->response_type_url(), target);
+  }
+
+  // optional bool response_streaming = 5;
+  if (this->response_streaming() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->response_streaming(), target);
+  }
+
+  // repeated .google.protobuf.Option options = 6;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->options(i), target);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      7, this->syntax(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method)
+  return target;
+}
+
+int Method::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional string request_type_url = 2;
+  if (this->request_type_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->request_type_url());
+  }
+
+  // optional bool request_streaming = 3;
+  if (this->request_streaming() != 0) {
+    total_size += 1 + 1;
+  }
+
+  // optional string response_type_url = 4;
+  if (this->response_type_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->response_type_url());
+  }
+
+  // optional bool response_streaming = 5;
+  if (this->response_streaming() != 0) {
+    total_size += 1 + 1;
+  }
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  if (this->syntax() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+  }
+
+  // repeated .google.protobuf.Option options = 6;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Method::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Method* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Method>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Method)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Method)
+    MergeFrom(*source);
+  }
+}
+
+void Method::MergeFrom(const Method& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  options_.MergeFrom(from.options_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.request_type_url().size() > 0) {
+
+    request_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.request_type_url_);
+  }
+  if (from.request_streaming() != 0) {
+    set_request_streaming(from.request_streaming());
+  }
+  if (from.response_type_url().size() > 0) {
+
+    response_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
+  }
+  if (from.response_streaming() != 0) {
+    set_response_streaming(from.response_streaming());
+  }
+  if (from.syntax() != 0) {
+    set_syntax(from.syntax());
+  }
+}
+
+void Method::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Method)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Method::CopyFrom(const Method& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Method)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Method::IsInitialized() const {
+
+  return true;
+}
+
+void Method::Swap(Method* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Method::InternalSwap(Method* other) {
+  name_.Swap(&other->name_);
+  request_type_url_.Swap(&other->request_type_url_);
+  std::swap(request_streaming_, other->request_streaming_);
+  response_type_url_.Swap(&other->response_type_url_);
+  std::swap(response_streaming_, other->response_streaming_);
+  options_.UnsafeArenaSwap(&other->options_);
+  std::swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Method::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Method_descriptor_;
+  metadata.reflection = Method_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Method
+
+// optional string name = 1;
+void Method::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
+}
+ void Method::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
+}
+ void Method::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
+}
+ ::std::string* Method::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
+}
+
+// optional string request_type_url = 2;
+void Method::clear_request_type_url() {
+  request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::request_type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
+  return request_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_request_type_url(const ::std::string& value) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
+}
+ void Method::set_request_type_url(const char* value) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
+}
+ void Method::set_request_type_url(const char* value, size_t size) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
+}
+ ::std::string* Method::mutable_request_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
+  return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_request_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
+  
+  return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_request_type_url(::std::string* request_type_url) {
+  if (request_type_url != NULL) {
+    
+  } else {
+    
+  }
+  request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
+}
+
+// optional bool request_streaming = 3;
+void Method::clear_request_streaming() {
+  request_streaming_ = false;
+}
+ bool Method::request_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
+  return request_streaming_;
+}
+ void Method::set_request_streaming(bool value) {
+  
+  request_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
+}
+
+// optional string response_type_url = 4;
+void Method::clear_response_type_url() {
+  response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::response_type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
+  return response_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_response_type_url(const ::std::string& value) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
+}
+ void Method::set_response_type_url(const char* value) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
+}
+ void Method::set_response_type_url(const char* value, size_t size) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
+}
+ ::std::string* Method::mutable_response_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
+  return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_response_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
+  
+  return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_response_type_url(::std::string* response_type_url) {
+  if (response_type_url != NULL) {
+    
+  } else {
+    
+  }
+  response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
+}
+
+// optional bool response_streaming = 5;
+void Method::clear_response_streaming() {
+  response_streaming_ = false;
+}
+ bool Method::response_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
+  return response_streaming_;
+}
+ void Method::set_response_streaming(bool value) {
+  
+  response_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
+}
+
+// repeated .google.protobuf.Option options = 6;
+int Method::options_size() const {
+  return options_.size();
+}
+void Method::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& Method::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* Method::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* Method::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Method::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Method.options)
+  return options_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+void Method::clear_syntax() {
+  syntax_ = 0;
+}
+ ::google::protobuf::Syntax Method::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Method::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Mixin::kNameFieldNumber;
+const int Mixin::kRootFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Mixin::Mixin()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Mixin)
+}
+
+void Mixin::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Mixin::Mixin(const Mixin& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin)
+}
+
+void Mixin::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  root_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Mixin::~Mixin() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Mixin)
+  SharedDtor();
+}
+
+void Mixin::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  root_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void Mixin::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Mixin::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Mixin_descriptor_;
+}
+
+const Mixin& Mixin::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  return *default_instance_;
+}
+
+Mixin* Mixin::default_instance_ = NULL;
+
+Mixin* Mixin::New(::google::protobuf::Arena* arena) const {
+  Mixin* n = new Mixin;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Mixin::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool Mixin::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Mixin)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Mixin.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_root;
+        break;
+      }
+
+      // optional string root = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_root:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_root()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->root().data(), this->root().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Mixin.root"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Mixin)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Mixin)
+  return false;
+#undef DO_
+}
+
+void Mixin::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Mixin)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Mixin.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string root = 2;
+  if (this->root().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->root().data(), this->root().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Mixin.root");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->root(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Mixin)
+}
+
+::google::protobuf::uint8* Mixin::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Mixin.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string root = 2;
+  if (this->root().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->root().data(), this->root().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Mixin.root");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->root(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin)
+  return target;
+}
+
+int Mixin::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional string root = 2;
+  if (this->root().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->root());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Mixin::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Mixin* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Mixin>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Mixin)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Mixin)
+    MergeFrom(*source);
+  }
+}
+
+void Mixin::MergeFrom(const Mixin& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.root().size() > 0) {
+
+    root_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.root_);
+  }
+}
+
+void Mixin::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Mixin)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Mixin::CopyFrom(const Mixin& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Mixin)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Mixin::IsInitialized() const {
+
+  return true;
+}
+
+void Mixin::Swap(Mixin* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Mixin::InternalSwap(Mixin* other) {
+  name_.Swap(&other->name_);
+  root_.Swap(&other->root_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Mixin::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Mixin_descriptor_;
+  metadata.reflection = Mixin_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Mixin
+
+// optional string name = 1;
+void Mixin::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Mixin::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
+}
+ void Mixin::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
+}
+ void Mixin::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
+}
+ ::std::string* Mixin::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Mixin::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
+}
+
+// optional string root = 2;
+void Mixin::clear_root() {
+  root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Mixin::root() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
+  return root_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_root(const ::std::string& value) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
+}
+ void Mixin::set_root(const char* value) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
+}
+ void Mixin::set_root(const char* value, size_t size) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
+}
+ ::std::string* Mixin::mutable_root() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
+  return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Mixin::release_root() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
+  
+  return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_allocated_root(::std::string* root) {
+  if (root != NULL) {
+    
+  } else {
+    
+  }
+  root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/api.pb.h b/src/third_party/protobuf-3/src/google/protobuf/api.pb.h
new file mode 100644
index 0000000..bb35e47
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/api.pb.h
@@ -0,0 +1,984 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/source_context.pb.h>
+#include <google/protobuf/type.pb.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+class Api;
+class Method;
+class Mixin;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
+ public:
+  Api();
+  virtual ~Api();
+
+  Api(const Api& from);
+
+  inline Api& operator=(const Api& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Api& default_instance();
+
+  void Swap(Api* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Api* New() const { return New(NULL); }
+
+  Api* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Api& from);
+  void MergeFrom(const Api& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Api* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.Method methods = 2;
+  int methods_size() const;
+  void clear_methods();
+  static const int kMethodsFieldNumber = 2;
+  const ::google::protobuf::Method& methods(int index) const;
+  ::google::protobuf::Method* mutable_methods(int index);
+  ::google::protobuf::Method* add_methods();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+      mutable_methods();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+      methods() const;
+
+  // repeated .google.protobuf.Option options = 3;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // optional string version = 4;
+  void clear_version();
+  static const int kVersionFieldNumber = 4;
+  const ::std::string& version() const;
+  void set_version(const ::std::string& value);
+  void set_version(const char* value);
+  void set_version(const char* value, size_t size);
+  ::std::string* mutable_version();
+  ::std::string* release_version();
+  void set_allocated_version(::std::string* version);
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  bool has_source_context() const;
+  void clear_source_context();
+  static const int kSourceContextFieldNumber = 5;
+  const ::google::protobuf::SourceContext& source_context() const;
+  ::google::protobuf::SourceContext* mutable_source_context();
+  ::google::protobuf::SourceContext* release_source_context();
+  void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+  // repeated .google.protobuf.Mixin mixins = 6;
+  int mixins_size() const;
+  void clear_mixins();
+  static const int kMixinsFieldNumber = 6;
+  const ::google::protobuf::Mixin& mixins(int index) const;
+  ::google::protobuf::Mixin* mutable_mixins(int index);
+  ::google::protobuf::Mixin* add_mixins();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+      mutable_mixins();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+      mixins() const;
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  void clear_syntax();
+  static const int kSyntaxFieldNumber = 7;
+  ::google::protobuf::Syntax syntax() const;
+  void set_syntax(::google::protobuf::Syntax value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Api)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method > methods_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  ::google::protobuf::internal::ArenaStringPtr version_;
+  ::google::protobuf::SourceContext* source_context_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin > mixins_;
+  int syntax_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+  void InitAsDefaultInstance();
+  static Api* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message {
+ public:
+  Method();
+  virtual ~Method();
+
+  Method(const Method& from);
+
+  inline Method& operator=(const Method& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Method& default_instance();
+
+  void Swap(Method* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Method* New() const { return New(NULL); }
+
+  Method* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Method& from);
+  void MergeFrom(const Method& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Method* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string request_type_url = 2;
+  void clear_request_type_url();
+  static const int kRequestTypeUrlFieldNumber = 2;
+  const ::std::string& request_type_url() const;
+  void set_request_type_url(const ::std::string& value);
+  void set_request_type_url(const char* value);
+  void set_request_type_url(const char* value, size_t size);
+  ::std::string* mutable_request_type_url();
+  ::std::string* release_request_type_url();
+  void set_allocated_request_type_url(::std::string* request_type_url);
+
+  // optional bool request_streaming = 3;
+  void clear_request_streaming();
+  static const int kRequestStreamingFieldNumber = 3;
+  bool request_streaming() const;
+  void set_request_streaming(bool value);
+
+  // optional string response_type_url = 4;
+  void clear_response_type_url();
+  static const int kResponseTypeUrlFieldNumber = 4;
+  const ::std::string& response_type_url() const;
+  void set_response_type_url(const ::std::string& value);
+  void set_response_type_url(const char* value);
+  void set_response_type_url(const char* value, size_t size);
+  ::std::string* mutable_response_type_url();
+  ::std::string* release_response_type_url();
+  void set_allocated_response_type_url(::std::string* response_type_url);
+
+  // optional bool response_streaming = 5;
+  void clear_response_streaming();
+  static const int kResponseStreamingFieldNumber = 5;
+  bool response_streaming() const;
+  void set_response_streaming(bool value);
+
+  // repeated .google.protobuf.Option options = 6;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 6;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // optional .google.protobuf.Syntax syntax = 7;
+  void clear_syntax();
+  static const int kSyntaxFieldNumber = 7;
+  ::google::protobuf::Syntax syntax() const;
+  void set_syntax(::google::protobuf::Syntax value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Method)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr request_type_url_;
+  ::google::protobuf::internal::ArenaStringPtr response_type_url_;
+  bool request_streaming_;
+  bool response_streaming_;
+  int syntax_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+  void InitAsDefaultInstance();
+  static Method* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message {
+ public:
+  Mixin();
+  virtual ~Mixin();
+
+  Mixin(const Mixin& from);
+
+  inline Mixin& operator=(const Mixin& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Mixin& default_instance();
+
+  void Swap(Mixin* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Mixin* New() const { return New(NULL); }
+
+  Mixin* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Mixin& from);
+  void MergeFrom(const Mixin& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Mixin* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string root = 2;
+  void clear_root();
+  static const int kRootFieldNumber = 2;
+  const ::std::string& root() const;
+  void set_root(const ::std::string& value);
+  void set_root(const char* value);
+  void set_root(const char* value, size_t size);
+  ::std::string* mutable_root();
+  ::std::string* release_root();
+  void set_allocated_root(::std::string* root);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Mixin)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr root_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+  void InitAsDefaultInstance();
+  static Mixin* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Api
+
+// optional string name = 1;
+inline void Api::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Api::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
+}
+inline void Api::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
+}
+inline void Api::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
+}
+inline ::std::string* Api::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Api::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
+}
+
+// repeated .google.protobuf.Method methods = 2;
+inline int Api::methods_size() const {
+  return methods_.size();
+}
+inline void Api::clear_methods() {
+  methods_.Clear();
+}
+inline const ::google::protobuf::Method& Api::methods(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
+  return methods_.Get(index);
+}
+inline ::google::protobuf::Method* Api::mutable_methods(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
+  return methods_.Mutable(index);
+}
+inline ::google::protobuf::Method* Api::add_methods() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
+  return methods_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+Api::mutable_methods() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
+  return &methods_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+  return methods_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int Api::options_size() const {
+  return options_.size();
+}
+inline void Api::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& Api::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* Api::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Api::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Api::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+  return options_;
+}
+
+// optional string version = 4;
+inline void Api::clear_version() {
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Api::version() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
+  return version_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_version(const ::std::string& value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
+}
+inline void Api::set_version(const char* value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
+}
+inline void Api::set_version(const char* value, size_t size) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
+}
+inline ::std::string* Api::mutable_version() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
+  return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Api::release_version() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
+  
+  return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_allocated_version(::std::string* version) {
+  if (version != NULL) {
+    
+  } else {
+    
+  }
+  version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+inline bool Api::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Api::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Api::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
+  return source_context_;
+}
+inline ::google::protobuf::SourceContext* Api::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+inline void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
+}
+
+// repeated .google.protobuf.Mixin mixins = 6;
+inline int Api::mixins_size() const {
+  return mixins_.size();
+}
+inline void Api::clear_mixins() {
+  mixins_.Clear();
+}
+inline const ::google::protobuf::Mixin& Api::mixins(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
+  return mixins_.Get(index);
+}
+inline ::google::protobuf::Mixin* Api::mutable_mixins(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
+  return mixins_.Mutable(index);
+}
+inline ::google::protobuf::Mixin* Api::add_mixins() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
+  return mixins_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+Api::mutable_mixins() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
+  return &mixins_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+Api::mixins() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
+  return mixins_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+inline void Api::clear_syntax() {
+  syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Api::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Api::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// Method
+
+// optional string name = 1;
+inline void Method::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
+}
+inline void Method::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
+}
+inline void Method::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
+}
+inline ::std::string* Method::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
+}
+
+// optional string request_type_url = 2;
+inline void Method::clear_request_type_url() {
+  request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::request_type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
+  return request_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_request_type_url(const ::std::string& value) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
+}
+inline void Method::set_request_type_url(const char* value) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
+}
+inline void Method::set_request_type_url(const char* value, size_t size) {
+  
+  request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
+}
+inline ::std::string* Method::mutable_request_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
+  return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_request_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
+  
+  return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_request_type_url(::std::string* request_type_url) {
+  if (request_type_url != NULL) {
+    
+  } else {
+    
+  }
+  request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
+}
+
+// optional bool request_streaming = 3;
+inline void Method::clear_request_streaming() {
+  request_streaming_ = false;
+}
+inline bool Method::request_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
+  return request_streaming_;
+}
+inline void Method::set_request_streaming(bool value) {
+  
+  request_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
+}
+
+// optional string response_type_url = 4;
+inline void Method::clear_response_type_url() {
+  response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::response_type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
+  return response_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_response_type_url(const ::std::string& value) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
+}
+inline void Method::set_response_type_url(const char* value) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
+}
+inline void Method::set_response_type_url(const char* value, size_t size) {
+  
+  response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
+}
+inline ::std::string* Method::mutable_response_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
+  return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_response_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
+  
+  return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_response_type_url(::std::string* response_type_url) {
+  if (response_type_url != NULL) {
+    
+  } else {
+    
+  }
+  response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
+}
+
+// optional bool response_streaming = 5;
+inline void Method::clear_response_streaming() {
+  response_streaming_ = false;
+}
+inline bool Method::response_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
+  return response_streaming_;
+}
+inline void Method::set_response_streaming(bool value) {
+  
+  response_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
+}
+
+// repeated .google.protobuf.Option options = 6;
+inline int Method::options_size() const {
+  return options_.size();
+}
+inline void Method::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& Method::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* Method::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Method::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Method::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Method.options)
+  return options_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+inline void Method::clear_syntax() {
+  syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Method::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Method::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// Mixin
+
+// optional string name = 1;
+inline void Mixin::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Mixin::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
+}
+inline void Mixin::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
+}
+inline void Mixin::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
+}
+inline ::std::string* Mixin::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Mixin::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
+}
+
+// optional string root = 2;
+inline void Mixin::clear_root() {
+  root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Mixin::root() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
+  return root_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_root(const ::std::string& value) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
+}
+inline void Mixin::set_root(const char* value) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
+}
+inline void Mixin::set_root(const char* value, size_t size) {
+  
+  root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
+}
+inline ::std::string* Mixin::mutable_root() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
+  return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Mixin::release_root() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
+  
+  return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_allocated_root(::std::string* root) {
+  if (root != NULL) {
+    
+  } else {
+    
+  }
+  root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/api.proto b/src/third_party/protobuf-3/src/google/protobuf/api.proto
new file mode 100644
index 0000000..dbe87b8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/api.proto
@@ -0,0 +1,202 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/source_context.proto";
+import "google/protobuf/type.proto";
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "ApiProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// Api is a light-weight descriptor for a protocol buffer service.
+message Api {
+
+  // The fully qualified name of this api, including package name
+  // followed by the api's simple name.
+  string name = 1;
+
+  // The methods of this api, in unspecified order.
+  repeated Method methods = 2;
+
+  // Any metadata attached to the API.
+  repeated Option options = 3;
+
+  // A version string for this api. If specified, must have the form
+  // `major-version.minor-version`, as in `1.10`. If the minor version
+  // is omitted, it defaults to zero. If the entire version field is
+  // empty, the major version is derived from the package name, as
+  // outlined below. If the field is not empty, the version in the
+  // package name will be verified to be consistent with what is
+  // provided here.
+  //
+  // The versioning schema uses [semantic
+  // versioning](http://semver.org) where the major version number
+  // indicates a breaking change and the minor version an additive,
+  // non-breaking change. Both version numbers are signals to users
+  // what to expect from different versions, and should be carefully
+  // chosen based on the product plan.
+  //
+  // The major version is also reflected in the package name of the
+  // API, which must end in `v<major-version>`, as in
+  // `google.feature.v1`. For major versions 0 and 1, the suffix can
+  // be omitted. Zero major versions must only be used for
+  // experimental, none-GA apis.
+  //
+  //
+  string version = 4;
+
+  // Source context for the protocol buffer service represented by this
+  // message.
+  SourceContext source_context = 5;
+
+  // Included APIs. See [Mixin][].
+  repeated Mixin mixins = 6;
+
+  // The source syntax of the service.
+  Syntax syntax = 7;
+}
+
+// Method represents a method of an api.
+message Method {
+
+  // The simple name of this method.
+  string name = 1;
+
+  // A URL of the input message type.
+  string request_type_url = 2;
+
+  // If true, the request is streamed.
+  bool request_streaming = 3;
+
+  // The URL of the output message type.
+  string response_type_url = 4;
+
+  // If true, the response is streamed.
+  bool response_streaming = 5;
+
+  // Any metadata attached to the method.
+  repeated Option options = 6;
+
+  // The source syntax of this method.
+  Syntax syntax = 7;
+}
+
+// Declares an API to be included in this API. The including API must
+// redeclare all the methods from the included API, but documentation
+// and options are inherited as follows:
+//
+// - If after comment and whitespace stripping, the documentation
+//   string of the redeclared method is empty, it will be inherited
+//   from the original method.
+//
+// - Each annotation belonging to the service config (http,
+//   visibility) which is not set in the redeclared method will be
+//   inherited.
+//
+// - If an http annotation is inherited, the path pattern will be
+//   modified as follows. Any version prefix will be replaced by the
+//   version of the including API plus the [root][] path if specified.
+//
+// Example of a simple mixin:
+//
+//     package google.acl.v1;
+//     service AccessControl {
+//       // Get the underlying ACL object.
+//       rpc GetAcl(GetAclRequest) returns (Acl) {
+//         option (google.api.http).get = "/v1/{resource=**}:getAcl";
+//       }
+//     }
+//
+//     package google.storage.v2;
+//     service Storage {
+//       rpc GetAcl(GetAclRequest) returns (Acl);
+//
+//       // Get a data record.
+//       rpc GetData(GetDataRequest) returns (Data) {
+//         option (google.api.http).get = "/v2/{resource=**}";
+//       }
+//     }
+//
+// Example of a mixin configuration:
+//
+//     apis:
+//     - name: google.storage.v2.Storage
+//       mixins:
+//       - name: google.acl.v1.AccessControl
+//
+// The mixin construct implies that all methods in `AccessControl` are
+// also declared with same name and request/response types in
+// `Storage`. A documentation generator or annotation processor will
+// see the effective `Storage.GetAcl` method after inherting
+// documentation and annotations as follows:
+//
+//     service Storage {
+//       // Get the underlying ACL object.
+//       rpc GetAcl(GetAclRequest) returns (Acl) {
+//         option (google.api.http).get = "/v2/{resource=**}:getAcl";
+//       }
+//       ...
+//     }
+//
+// Note how the version in the path pattern changed from `v1` to `v2`.
+//
+// If the `root` field in the mixin is specified, it should be a
+// relative path under which inherited HTTP paths are placed. Example:
+//
+//     apis:
+//     - name: google.storage.v2.Storage
+//       mixins:
+//       - name: google.acl.v1.AccessControl
+//         root: acls
+//
+// This implies the following inherited HTTP annotation:
+//
+//     service Storage {
+//       // Get the underlying ACL object.
+//       rpc GetAcl(GetAclRequest) returns (Acl) {
+//         option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+//       }
+//       ...
+//     }
+message Mixin {
+  // The fully qualified name of the API which is included.
+  string name = 1;
+
+  // If non-empty specifies a path under which inherited HTTP paths
+  // are rooted.
+  string root = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena.cc b/src/third_party/protobuf-3/src/google/protobuf/arena.cc
new file mode 100755
index 0000000..613e589
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena.cc
@@ -0,0 +1,321 @@
+// 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.
+
+#include <google/protobuf/arena.h>
+
+
+#ifdef ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
+namespace google {
+namespace protobuf {
+
+
+google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+Arena::ThreadCache& Arena::thread_cache() {
+  static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
+      new internal::ThreadLocalStorage<ThreadCache>();
+  return *thread_cache_->Get();
+}
+#elif defined(PROTOBUF_USE_DLLS)
+Arena::ThreadCache& Arena::thread_cache() {
+  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
+  return thread_cache_;
+}
+#else
+GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
+#endif
+
+void Arena::Init() {
+  lifecycle_id_ = lifecycle_id_generator_.GetNext();
+  blocks_ = 0;
+  hint_ = 0;
+  owns_first_block_ = true;
+  cleanup_list_ = 0;
+
+  if (options_.initial_block != NULL && options_.initial_block_size > 0) {
+    GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
+        << ": Initial block size too small for header.";
+
+    // Add first unowned block to list.
+    Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
+    first_block->size = options_.initial_block_size;
+    first_block->pos = kHeaderSize;
+    first_block->next = NULL;
+    // Thread which calls Init() owns the first block. This allows the
+    // single-threaded case to allocate on the first block without taking any
+    // locks.
+    first_block->owner = &thread_cache();
+    SetThreadCacheBlock(first_block);
+    AddBlockInternal(first_block);
+    owns_first_block_ = false;
+  }
+
+  // Call the initialization hook
+  if (options_.on_arena_init != NULL) {
+    hooks_cookie_ = options_.on_arena_init(this);
+  } else {
+    hooks_cookie_ = NULL;
+  }
+}
+
+Arena::~Arena() {
+  uint64 space_allocated = ResetInternal();
+
+  // Call the destruction hook
+  if (options_.on_arena_destruction != NULL) {
+    options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
+  }
+}
+
+uint64 Arena::Reset() {
+  // Invalidate any ThreadCaches pointing to any blocks we just destroyed.
+  lifecycle_id_ = lifecycle_id_generator_.GetNext();
+  return ResetInternal();
+}
+
+uint64 Arena::ResetInternal() {
+  CleanupList();
+  uint64 space_allocated = FreeBlocks();
+
+  // Call the reset hook
+  if (options_.on_arena_reset != NULL) {
+    options_.on_arena_reset(this, hooks_cookie_, space_allocated);
+  }
+
+  return space_allocated;
+}
+
+Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
+                              size_t start_block_size, size_t max_block_size) {
+  size_t size;
+  if (my_last_block != NULL) {
+    // Double the current block size, up to a limit.
+    size = 2 * (my_last_block->size);
+    if (size > max_block_size) size = max_block_size;
+  } else {
+    size = start_block_size;
+  }
+  if (n > size - kHeaderSize) {
+    // TODO(sanjay): Check if n + kHeaderSize would overflow
+    size = kHeaderSize + n;
+  }
+
+  Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
+  b->pos = kHeaderSize + n;
+  b->size = size;
+  if (b->avail() == 0) {
+    // Do not attempt to reuse this block.
+    b->owner = NULL;
+  } else {
+    b->owner = me;
+  }
+#ifdef ADDRESS_SANITIZER
+  // Poison the rest of the block for ASAN. It was unpoisoned by the underlying
+  // malloc but it's not yet usable until we return it as part of an allocation.
+  ASAN_POISON_MEMORY_REGION(
+      reinterpret_cast<char*>(b) + b->pos, b->size - b->pos);
+#endif
+  return b;
+}
+
+void Arena::AddBlock(Block* b) {
+  MutexLock l(&blocks_lock_);
+  AddBlockInternal(b);
+}
+
+void Arena::AddBlockInternal(Block* b) {
+  b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+  if (b->avail() != 0) {
+    // Direct future allocations to this block.
+    google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+  }
+}
+
+void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
+  Node* node = reinterpret_cast<Node*>(AllocateAligned(sizeof(Node)));
+  node->elem = elem;
+  node->cleanup = cleanup;
+  node->next = reinterpret_cast<Node*>(
+      google::protobuf::internal::NoBarrier_AtomicExchange(&cleanup_list_,
+            reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
+}
+
+void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
+  // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
+  n = (n + 7) & -8;
+
+  // Monitor allocation if needed.
+  if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) &&
+      options_.on_arena_allocation != NULL) {
+    options_.on_arena_allocation(allocated, n, hooks_cookie_);
+  }
+
+  // If this thread already owns a block in this arena then try to use that.
+  // This fast path optimizes the case where multiple threads allocate from the
+  // same arena.
+  if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ &&
+      thread_cache().last_block_used_ != NULL) {
+    if (thread_cache().last_block_used_->avail() < n) {
+      return SlowAlloc(n);
+    }
+    return AllocFromBlock(thread_cache().last_block_used_, n);
+  }
+
+  // Check whether we own the last accessed block on this arena.
+  // This fast path optimizes the case where a single thread uses multiple
+  // arenas.
+  void* me = &thread_cache();
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
+  if (!b || b->owner != me || b->avail() < n) {
+    return SlowAlloc(n);
+  }
+  return AllocFromBlock(b, n);
+}
+
+void* Arena::AllocFromBlock(Block* b, size_t n) {
+  size_t p = b->pos;
+  b->pos = p + n;
+#ifdef ADDRESS_SANITIZER
+  ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b) + p, n);
+#endif
+  return reinterpret_cast<char*>(b) + p;
+}
+
+void* Arena::SlowAlloc(size_t n) {
+  void* me = &thread_cache();
+  Block* b = FindBlock(me);  // Find block owned by me.
+  // See if allocation fits in my latest block.
+  if (b != NULL && b->avail() >= n) {
+    SetThreadCacheBlock(b);
+    google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+    return AllocFromBlock(b, n);
+  }
+  b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
+  AddBlock(b);
+  if (b->owner == me) {  // If this block can be reused (see NewBlock()).
+    SetThreadCacheBlock(b);
+  }
+  return reinterpret_cast<char*>(b) + kHeaderSize;
+}
+
+uint64 Arena::SpaceAllocated() const {
+  uint64 space_allocated = 0;
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  while (b != NULL) {
+    space_allocated += (b->size);
+    b = b->next;
+  }
+  return space_allocated;
+}
+
+uint64 Arena::SpaceUsed() const {
+  uint64 space_used = 0;
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  while (b != NULL) {
+    space_used += (b->pos - kHeaderSize);
+    b = b->next;
+  }
+  return space_used;
+}
+
+pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
+  uint64 allocated = 0;
+  uint64 used = 0;
+
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  while (b != NULL) {
+    allocated += b->size;
+    used += (b->pos - kHeaderSize);
+    b = b->next;
+  }
+  return std::make_pair(allocated, used);
+}
+
+uint64 Arena::FreeBlocks() {
+  uint64 space_allocated = 0;
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  Block* first_block = NULL;
+  while (b != NULL) {
+    space_allocated += (b->size);
+    Block* next = b->next;
+    if (next != NULL) {
+      options_.block_dealloc(b, b->size);
+    } else {
+      if (owns_first_block_) {
+        options_.block_dealloc(b, b->size);
+      } else {
+        // User passed in the first block, skip free'ing the memory.
+        first_block = b;
+      }
+    }
+    b = next;
+  }
+  blocks_ = 0;
+  hint_ = 0;
+  if (!owns_first_block_) {
+    // Make the first block that was passed in through ArenaOptions
+    // available for reuse.
+    first_block->pos = kHeaderSize;
+    // Thread which calls Reset() owns the first block. This allows the
+    // single-threaded case to allocate on the first block without taking any
+    // locks.
+    first_block->owner = &thread_cache();
+    SetThreadCacheBlock(first_block);
+    AddBlockInternal(first_block);
+  }
+  return space_allocated;
+}
+
+void Arena::CleanupList() {
+  Node* head =
+      reinterpret_cast<Node*>(google::protobuf::internal::NoBarrier_Load(&cleanup_list_));
+  while (head != NULL) {
+    head->cleanup(head->elem);
+    head = head->next;
+  }
+  cleanup_list_ = 0;
+}
+
+Arena::Block* Arena::FindBlock(void* me) {
+  // TODO(sanjay): We might want to keep a separate list with one
+  // entry per thread.
+  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&blocks_));
+  while (b != NULL && b->owner != me) {
+    b = b->next;
+  }
+  return b;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena.h b/src/third_party/protobuf-3/src/google/protobuf/arena.h
new file mode 100644
index 0000000..8840201
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena.h
@@ -0,0 +1,925 @@
+// 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_ARENA_H__
+#define GOOGLE_PROTOBUF_ARENA_H__
+
+#include <limits>
+#ifdef max
+#undef max  // Visual Studio defines this macro
+#endif
+#if __cplusplus >= 201103L
+#include <google/protobuf/stubs/type_traits.h>
+#endif
+#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
+// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
+#include <exception>
+#include <typeinfo>
+namespace std {
+using type_info = ::type_info;
+}
+#else
+#include <typeinfo>
+#endif
+
+#include <google/protobuf/stubs/atomic_sequence_num.h>
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+
+namespace google {
+namespace protobuf {
+
+class Arena;       // defined below
+class Message;     // message.h
+
+namespace internal {
+class ArenaString; // arenastring.h
+class LazyField;   // lazy_field.h
+
+template<typename Type>
+class GenericTypeHandler; // repeated_field.h
+
+// Templated cleanup methods.
+template<typename T> void arena_destruct_object(void* object) {
+  reinterpret_cast<T*>(object)->~T();
+}
+template<typename T> void arena_delete_object(void* object) {
+  delete reinterpret_cast<T*>(object);
+}
+inline void arena_free(void* object, size_t /* size */) {
+  free(object);
+}
+
+}  // namespace internal
+
+// ArenaOptions provides optional additional parameters to arena construction
+// that control its block-allocation behavior.
+struct ArenaOptions {
+  // This defines the size of the first block requested from the system malloc.
+  // Subsequent block sizes will increase in a geometric series up to a maximum.
+  size_t start_block_size;
+
+  // This defines the maximum block size requested from system malloc (unless an
+  // individual arena allocation request occurs with a size larger than this
+  // maximum). Requested block sizes increase up to this value, then remain
+  // here.
+  size_t max_block_size;
+
+  // An initial block of memory for the arena to use, or NULL for none. If
+  // provided, the block must live at least as long as the arena itself. The
+  // creator of the Arena retains ownership of the block after the Arena is
+  // destroyed.
+  char* initial_block;
+
+  // The size of the initial block, if provided.
+  size_t initial_block_size;
+
+  // A function pointer to an alloc method that returns memory blocks of size
+  // requested. By default, it contains a ptr to the malloc function.
+  //
+  // NOTE: block_alloc and dealloc functions are expected to behave like
+  // malloc and free, including Asan poisoning.
+  void* (*block_alloc)(size_t);
+  // A function pointer to a dealloc method that takes ownership of the blocks
+  // from the arena. By default, it contains a ptr to a wrapper function that
+  // calls free.
+  void (*block_dealloc)(void*, size_t);
+
+  // Hooks for adding external functionality such as user-specific metrics
+  // collection, specific debugging abilities, etc.
+  // Init hook may return a pointer to a cookie to be stored in the arena.
+  // reset and destruction hooks will then be called with the same cookie
+  // pointer. This allows us to save an external object per arena instance and
+  // use it on the other hooks (Note: It is just as legal for init to return
+  // NULL and not use the cookie feature).
+  // on_arena_reset and on_arena_destruction also receive the space used in
+  // the arena just before the reset.
+  void* (*on_arena_init)(Arena* arena);
+  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
+  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
+
+  // type_info is promised to be static - its lifetime extends to
+  // match program's lifetime (It is given by typeid operator).
+  // Note: typeid(void) will be passed as allocated_type every time we
+  // intentionally want to avoid monitoring an allocation. (i.e. internal
+  // allocations for managing the arena)
+  void (*on_arena_allocation)(const std::type_info* allocated_type,
+      uint64 alloc_size, void* cookie);
+
+  ArenaOptions()
+      : start_block_size(kDefaultStartBlockSize),
+        max_block_size(kDefaultMaxBlockSize),
+        initial_block(NULL),
+        initial_block_size(0),
+        block_alloc(&malloc),
+        block_dealloc(&internal::arena_free),
+        on_arena_init(NULL),
+        on_arena_reset(NULL),
+        on_arena_destruction(NULL),
+        on_arena_allocation(NULL) {}
+
+ private:
+  // Constants define default starting block size and max block size for
+  // arena allocator behavior -- see descriptions above.
+  static const size_t kDefaultStartBlockSize = 256;
+  static const size_t kDefaultMaxBlockSize   = 8192;
+};
+
+// Support for non-RTTI environments. (The metrics hooks API uses type
+// information.)
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+#define RTTI_TYPE_ID(type) (&typeid(type))
+#else
+#define RTTI_TYPE_ID(type) (NULL)
+#endif
+
+// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
+// with new/delete, and improves performance by aggregating allocations into
+// larger blocks and freeing allocations all at once. Protocol messages are
+// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
+// are automatically freed when the arena is destroyed.
+//
+// This is a thread-safe implementation: multiple threads may allocate from the
+// arena concurrently. Destruction is not thread-safe and the destructing
+// thread must synchronize with users of the arena first.
+//
+// An arena provides two allocation interfaces: CreateMessage<T>, which works
+// for arena-enabled proto2 message types as well as other types that satisfy
+// the appropriate protocol (described below), and Create<T>, which works for
+// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
+// because this interface (i) passes the arena pointer to the created object so
+// that its sub-objects and internal allocations can use the arena too, and (ii)
+// elides the object's destructor call when possible. Create<T> does not place
+// any special requirements on the type T, and will invoke the object's
+// destructor when the arena is destroyed.
+//
+// The arena message allocation protocol, required by CreateMessage<T>, is as
+// follows:
+//
+// - The type T must have (at least) two constructors: a constructor with no
+//   arguments, called when a T is allocated on the heap; and a constructor with
+//   a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
+//   second constructor is called with a NULL arena pointer, it must be
+//   equivalent to invoking the first (no-argument) constructor.
+//
+// - The type T must have a particular type trait: a nested type
+//   |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
+//   such type trait exists, then the instantiation CreateMessage<T> will fail
+//   to compile.
+//
+// - The type T *may* have the type trait |DestructorSkippable_|. If this type
+//   trait is present in the type, then its destructor will not be called if and
+//   only if it was passed a non-NULL arena pointer. If this type trait is not
+//   present on the type, then its destructor is always called when the
+//   containing arena is destroyed.
+//
+// - One- and two-user-argument forms of CreateMessage<T>() also exist that
+//   forward these constructor arguments to T's constructor: for example,
+//   CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
+//   arg1, arg2).
+//
+// This protocol is implemented by all arena-enabled proto2 message classes as
+// well as RepeatedPtrField.
+
+#if __cplusplus >= 201103L
+class LIBPROTOBUF_EXPORT Arena final {
+#else
+class LIBPROTOBUF_EXPORT Arena {
+#endif
+ public:
+  // Arena constructor taking custom options. See ArenaOptions below for
+  // descriptions of the options available.
+  explicit Arena(const ArenaOptions& options) : options_(options) {
+    Init();
+  }
+
+  // Default constructor with sensible default options, tuned for average
+  // use-cases.
+  Arena() {
+    Init();
+  }
+
+  // Destructor deletes all owned heap allocated objects, and destructs objects
+  // that have non-trivial destructors, except for proto2 message objects whose
+  // destructors can be skipped. Also, frees all blocks except the initial block
+  // if it was passed in.
+  ~Arena();
+
+  // API to create proto2 message objects on the arena. If the arena passed in
+  // is NULL, then a heap allocated object is returned. Type T must be a message
+  // defined in a .proto file with cc_enable_arenas set to true, otherwise a
+  // compilation error will occur.
+  //
+  // RepeatedField and RepeatedPtrField may also be instantiated directly on an
+  // arena with this method.
+  //
+  // This function also accepts any type T that satisfies the arena message
+  // allocation protocol, documented above.
+  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* CreateMessage(::google::protobuf::Arena* arena) {
+    if (arena == NULL) {
+      return new T;
+    } else {
+      return arena->CreateMessageInternal<T>(static_cast<T*>(0));
+    }
+  }
+
+  // One-argument form of CreateMessage. This is useful for constructing objects
+  // that implement the arena message construction protocol described above but
+  // take additional constructor arguments.
+  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
+    if (arena == NULL) {
+      return new T(NULL, arg);
+    } else {
+      return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+                                             arg);
+    }
+  }
+
+  // Two-argument form of CreateMessage. This is useful for constructing objects
+  // that implement the arena message construction protocol described above but
+  // take additional constructor arguments.
+  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* CreateMessage(::google::protobuf::Arena* arena,
+                          const Arg1& arg1,
+                          const Arg2& arg2) {
+    if (arena == NULL) {
+      return new T(NULL, arg1, arg2);
+    } else {
+      return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+                                             arg1, arg2);
+    }
+  }
+
+  // API to create any objects on the arena. Note that only the object will
+  // be created on the arena; the underlying ptrs (in case of a proto2 message)
+  // will be still heap allocated. Proto messages should usually be allocated
+  // with CreateMessage<T>() instead.
+  //
+  // Note that even if T satisfies the arena message construction protocol
+  // (InternalArenaConstructable_ trait and optional DestructorSkippable_
+  // trait), as described above, this function does not follow the protocol;
+  // instead, it treats T as a black-box type, just as if it did not have these
+  // traits. Specifically, T's constructor arguments will always be only those
+  // passed to Create<T>() -- no additional arena pointer is implicitly added.
+  // Furthermore, the destructor will always be called at arena destruction time
+  // (unless the destructor is trivial). Hence, from T's point of view, it is as
+  // if the object were allocated on the heap (except that the underlying memory
+  // is obtained from the arena).
+  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* Create(::google::protobuf::Arena* arena) {
+    if (arena == NULL) {
+      return new T();
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
+    }
+  }
+
+  // Version of the above with one constructor argument for the created object.
+  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
+    if (arena == NULL) {
+      return new T(arg);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg);
+    }
+  }
+
+  // Version of the above with two constructor arguments for the created object.
+  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
+    if (arena == NULL) {
+      return new T(arg1, arg2);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2);
+    }
+  }
+
+  // Version of the above with three constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2, arg3);
+    }
+  }
+
+  // Version of the above with four constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2, arg3, arg4);
+    }
+  }
+
+  // Version of the above with five constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4,
+                                           const Arg5& arg5) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4, arg5);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2, arg3, arg4, arg5);
+    }
+  }
+
+  // Version of the above with six constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4,
+                                           const Arg5& arg5, const Arg6& arg6) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4, arg5, arg6);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+  }
+
+  // Version of the above with seven constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4,
+                                           const Arg5& arg5, const Arg6& arg6,
+                                           const Arg7& arg7) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    } else {
+      return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+                                      arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+  }
+
+  // Version of the above with eight constructor arguments for the created
+  // object.
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+            typename Arg8>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+                                           const Arg1& arg1, const Arg2& arg2,
+                                           const Arg3& arg3, const Arg4& arg4,
+                                           const Arg5& arg5, const Arg6& arg6,
+                                           const Arg7& arg7, const Arg8& arg8) {
+    if (arena == NULL) {
+      return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+    } else {
+      return arena->CreateInternal<T>(
+          google::protobuf::internal::has_trivial_destructor<T>::value,
+          arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+    }
+  }
+
+  // Create an array of object type T on the arena *without* invoking the
+  // constructor of T. If `arena` is null, then the return value should be freed
+  // with `delete[] x;` (or `::operator delete[](x);`).
+  // To ensure safe uses, this function checks at compile time
+  // (when compiled as C++11) that T is trivially default-constructible and
+  // trivially destructible.
+  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
+    GOOGLE_CHECK_LE(num_elements,
+             std::numeric_limits<size_t>::max() / sizeof(T))
+        << "Requested size is too large to fit into size_t.";
+    if (arena == NULL) {
+      return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
+    } else {
+      return arena->CreateInternalRawArray<T>(num_elements);
+    }
+  }
+
+  // Returns the total space used by the arena, which is the sums of the sizes
+  // of the underlying blocks. The total space used may not include the new
+  // blocks that are allocated by this arena from other threads concurrently
+  // with the call to this method.
+  GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceAllocated() const;
+  // As above, but does not include any free space in underlying blocks.
+  GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
+
+  // Combines SpaceAllocated and SpaceUsed. Returns a pair of
+  // <space_allocated, space_used>.
+  GOOGLE_ATTRIBUTE_NOINLINE pair<uint64, uint64> SpaceAllocatedAndUsed() const;
+
+  // Frees all storage allocated by this arena after calling destructors
+  // registered with OwnDestructor() and freeing objects registered with Own().
+  // Any objects allocated on this arena are unusable after this call. It also
+  // returns the total space used by the arena which is the sums of the sizes
+  // of the allocated blocks. This method is not thread-safe.
+  GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset();
+
+  // Adds |object| to a list of heap-allocated objects to be freed with |delete|
+  // when the arena is destroyed or reset.
+  template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
+  void Own(T* object) {
+    OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>());
+  }
+
+  // Adds |object| to a list of objects whose destructors will be manually
+  // called when the arena is destroyed or reset. This differs from Own() in
+  // that it does not free the underlying memory with |delete|; hence, it is
+  // normally only used for objects that are placement-newed into
+  // arena-allocated memory.
+  template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
+  void OwnDestructor(T* object) {
+    if (object != NULL) {
+      AddListNode(object, &internal::arena_destruct_object<T>);
+    }
+  }
+
+  // Adds a custom member function on an object to the list of destructors that
+  // will be manually called when the arena is destroyed or reset. This differs
+  // from OwnDestructor() in that any member function may be specified, not only
+  // the class destructor.
+  GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
+                                              void (*destruct)(void*)) {
+    AddListNode(object, destruct);
+  }
+
+  // Retrieves the arena associated with |value| if |value| is an arena-capable
+  // message, or NULL otherwise. This differs from value->GetArena() in that the
+  // latter is a virtual call, while this method is a templated call that
+  // resolves at compile-time.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static ::google::protobuf::Arena* GetArena(const T* value) {
+    return GetArenaInternal(value, static_cast<T*>(0));
+  }
+
+ private:
+  struct InternalIsArenaConstructableHelper {
+    template<typename U>
+    static char ArenaConstructable(
+        const typename U::InternalArenaConstructable_*);
+    template<typename U>
+    static double ArenaConstructable(...);
+  };
+
+ public:
+  // Helper typetrait that indicates support for arenas in a type T at compile
+  // time. This is public only to allow construction of higher-level templated
+  // utilities. is_arena_constructable<T>::value is true if the message type T
+  // has arena support enabled, and false otherwise.
+  //
+  // This is inside Arena because only Arena has the friend relationships
+  // necessary to see the underlying generated code traits.
+  template <typename T>
+  struct is_arena_constructable
+      : public google::protobuf::internal::integral_constant<
+            bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
+                         const T>(static_cast<const T*>(0))) == sizeof(char)> {
+  };
+
+ private:
+  // Blocks are variable length malloc-ed objects.  The following structure
+  // describes the common header for all blocks.
+  struct Block {
+    void* owner;   // &ThreadCache of thread that owns this block, or
+                   // &this->owner if not yet owned by a thread.
+    Block* next;   // Next block in arena (may have different owner)
+    // ((char*) &block) + pos is next available byte. It is always
+    // aligned at a multiple of 8 bytes.
+    size_t pos;
+    size_t size;  // total size of the block.
+    GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
+    // data follows
+  };
+
+  template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
+  friend class MockArena;              // For unit-testing.
+  friend class internal::ArenaString;  // For AllocateAligned.
+  friend class internal::LazyField;    // For CreateMaybeMessage.
+
+  struct ThreadCache {
+    // The ThreadCache is considered valid as long as this matches the
+    // lifecycle_id of the arena being used.
+    int64 last_lifecycle_id_seen;
+    Block* last_block_used_;
+  };
+
+  static const size_t kHeaderSize = sizeof(Block);
+  static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
+  // local storage class we implemented.
+  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
+  static ThreadCache& thread_cache();
+#elif defined(PROTOBUF_USE_DLLS)
+  // Thread local variables cannot be exposed through DLL interface but we can
+  // wrap them in static functions.
+  static ThreadCache& thread_cache();
+#else
+  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
+  static ThreadCache& thread_cache() { return thread_cache_; }
+#endif
+
+  // SFINAE for skipping addition to delete list for a message type when created
+  // with CreateMessage. This is mainly to skip proto2/proto1 message objects
+  // with cc_enable_arenas=true from being part of the delete list. Also, note,
+  // compiler will optimize out the branch in CreateInternal<T>.
+  template<typename T>
+  static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
+    return true;
+  }
+
+  // For message objects that don't have the DestructorSkippable_ trait, we
+  // always add to the delete list.
+  template<typename T>
+  static inline bool SkipDeleteList(...) {
+    return google::protobuf::internal::has_trivial_destructor<T>::value;
+  }
+
+ private:
+  struct InternalIsDestructorSkippableHelper {
+    template<typename U>
+    static char DestructorSkippable(
+        const typename U::DestructorSkippable_*);
+    template<typename U>
+    static double DestructorSkippable(...);
+  };
+
+ public:
+  // Helper typetrait that indicates whether the desctructor of type T should be
+  // called when arena is destroyed at compile time. This is only to allow
+  // construction of higher-level templated utilities.
+  // is_destructor_skippable<T>::value is true if the destructor of the message
+  // type T should not be called when arena is destroyed or false otherwise.
+  // This is inside Arena because only Arena has the friend relationships
+  // necessary to see the underlying generated code traits.
+  template<typename T>
+  struct is_destructor_skippable
+      : public google::protobuf::internal::integral_constant<
+            bool,
+            sizeof(InternalIsDestructorSkippableHelper::DestructorSkippable<
+                   const T>(static_cast<const T*>(0))) == sizeof(char) ||
+                google::protobuf::internal::has_trivial_destructor<T>::value> {};
+
+  // CreateMessage<T> requires that T supports arenas, but this private method
+  // works whether or not T supports arenas. These are not exposed to user code
+  // as it can cause confusing API usages, and end up having double free in
+  // user code. These are used only internally from LazyField and Repeated
+  // fields, since they are designed to work in all mode combinations.
+  template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static Msg* CreateMaybeMessage(
+      Arena* arena, typename Msg::InternalArenaConstructable_*) {
+    return CreateMessage<Msg>(arena);
+  }
+
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static T* CreateMaybeMessage(Arena* arena, ...) {
+    return Create<T>(arena);
+  }
+
+  // Just allocate the required size for the given type assuming the
+  // type has a trivial constructor.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateInternalRawArray(size_t num_elements) {
+    GOOGLE_CHECK_LE(num_elements,
+             std::numeric_limits<size_t>::max() / sizeof(T))
+        << "Requested size is too large to fit into size_t.";
+    return static_cast<T*>(
+        AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
+  }
+
+  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateInternal(bool skip_explicit_ownership) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateInternal(
+      bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3,
+                                            const Arg4& arg4) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3, arg4);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3,
+                                            const Arg4& arg4,
+                                            const Arg5& arg5) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3, arg4, arg5);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3,
+                                            const Arg4& arg4,
+                                            const Arg5& arg5,
+                                            const Arg6& arg6) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3, arg4, arg5, arg6);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3,
+                                            const Arg4& arg4,
+                                            const Arg5& arg5,
+                                            const Arg6& arg6,
+                                            const Arg7& arg7) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T, typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+            typename Arg8>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2,
+                                            const Arg3& arg3,
+                                            const Arg4& arg4,
+                                            const Arg5& arg5,
+                                            const Arg6& arg6,
+                                            const Arg7& arg7,
+                                            const Arg8& arg8) {
+    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+        T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+    if (!skip_explicit_ownership) {
+      AddListNode(t, &internal::arena_destruct_object<T>);
+    }
+    return t;
+  }
+
+  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
+    return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+                                     this);
+  }
+
+  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+                           const Arg& arg) {
+    return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+                                     this, arg);
+  }
+
+  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+                           const Arg1& arg1, const Arg2& arg2) {
+    return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+                                     this, arg1, arg2);
+  }
+
+  // CreateInArenaStorage is used to implement map field. Without it,
+  // google::protobuf::Map need to call generated message's protected arena constructor,
+  // which needs to declare google::protobuf::Map as friend of generated message.
+  template <typename T>
+  static void CreateInArenaStorage(T* ptr, Arena* arena) {
+    CreateInArenaStorageInternal(ptr, arena,
+                                 typename is_arena_constructable<T>::type());
+    RegisterDestructorInternal(ptr, arena,
+                               typename is_destructor_skippable<T>::type());
+  }
+
+  template <typename T>
+  static void CreateInArenaStorageInternal(
+      T* ptr, Arena* arena, google::protobuf::internal::true_type) {
+    new (ptr) T(arena);
+  }
+  template <typename T>
+  static void CreateInArenaStorageInternal(
+      T* ptr, Arena* /*arena*/, google::protobuf::internal::false_type) {
+    new (ptr) T;
+  }
+
+  template <typename T>
+  static void RegisterDestructorInternal(
+      T* /*ptr*/, Arena* /*arena*/, google::protobuf::internal::true_type) {}
+  template <typename T>
+  static void RegisterDestructorInternal(
+      T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+    arena->OwnDestructor(ptr);
+  }
+
+  // These implement Own(), which registers an object for deletion (destructor
+  // call and operator delete()). The second parameter has type 'true_type' if T
+  // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
+  // all template instantiations to one for generic Message reduces code size,
+  // using the virtual destructor instead.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  void OwnInternal(T* object, google::protobuf::internal::true_type) {
+    if (object != NULL) {
+      AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
+    }
+  }
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  void OwnInternal(T* object, google::protobuf::internal::false_type) {
+    if (object != NULL) {
+      AddListNode(object, &internal::arena_delete_object<T>);
+    }
+  }
+
+  // Implementation for GetArena(). Only message objects with
+  // InternalArenaConstructable_ tags can be associated with an arena, and such
+  // objects must implement a GetArenaNoVirtual() method.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static ::google::protobuf::Arena* GetArenaInternal(
+      const T* value, typename T::InternalArenaConstructable_*) {
+    return value->GetArenaNoVirtual();
+  }
+
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static ::google::protobuf::Arena* GetArenaInternal(const T* /*value*/, ...) {
+    return NULL;
+  }
+
+  // Allocate and also optionally call on_arena_allocation callback with the
+  // allocated type info when the hooks are in place in ArenaOptions and
+  // the cookie is not null.
+  void* AllocateAligned(const std::type_info* allocated, size_t n);
+
+  // Allocate an internal allocation, avoiding optional typed monitoring.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
+    return AllocateAligned(NULL, n);
+  }
+
+  void Init();
+
+  // Free all blocks and return the total space used which is the sums of sizes
+  // of the all the allocated blocks.
+  uint64 FreeBlocks();
+
+  // Add object pointer and cleanup function pointer to the list.
+  // TODO(rohananil, cfallin): We could pass in a sub-arena into this method
+  // to avoid polluting blocks of this arena with list nodes. This would help in
+  // mixed mode (where many protobufs have cc_enable_arenas=false), and is an
+  // alternative to a chunked linked-list, but with extra overhead of *next.
+  void AddListNode(void* elem, void (*cleanup)(void*));
+  // Delete or Destruct all objects owned by the arena.
+  void CleanupList();
+  uint64 ResetInternal();
+
+  inline void SetThreadCacheBlock(Block* block) {
+    thread_cache().last_block_used_ = block;
+    thread_cache().last_lifecycle_id_seen = lifecycle_id_;
+  }
+
+  int64 lifecycle_id_;  // Unique for each arena. Changes on Reset().
+
+  google::protobuf::internal::AtomicWord blocks_;  // Head of linked list of all allocated blocks
+  google::protobuf::internal::AtomicWord hint_;    // Fast thread-local block access
+
+  // Node contains the ptr of the object to be cleaned up and the associated
+  // cleanup function ptr.
+  struct Node {
+    void* elem;              // Pointer to the object to be cleaned up.
+    void (*cleanup)(void*);  // Function pointer to the destructor or deleter.
+    Node* next;              // Next node in the list.
+  };
+
+  google::protobuf::internal::AtomicWord cleanup_list_;  // Head of a linked list of nodes containing object
+                             // ptrs and cleanup methods.
+
+  bool owns_first_block_;    // Indicates that arena owns the first block
+  Mutex blocks_lock_;
+
+  void AddBlock(Block* b);
+  // Access must be synchronized, either by blocks_lock_ or by being called from
+  // Init()/Reset().
+  void AddBlockInternal(Block* b);
+  void* SlowAlloc(size_t n);
+  Block* FindBlock(void* me);
+  Block* NewBlock(void* me, Block* my_last_block, size_t n,
+                  size_t start_block_size, size_t max_block_size);
+  static void* AllocFromBlock(Block* b, size_t n);
+  template <typename Key, typename T>
+  friend class Map;
+
+  // The arena may save a cookie it receives from the external on_init hook
+  // and then use it when calling the on_reset and on_destruction hooks.
+  void* hooks_cookie_;
+
+  ArenaOptions options_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
+};
+
+// Defined above for supporting environments without RTTI.
+#undef RTTI_TYPE_ID
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ARENA_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena_nc.cc b/src/third_party/protobuf-3/src/google/protobuf/arena_nc.cc
new file mode 100644
index 0000000..f2f0842
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena_nc.cc
@@ -0,0 +1,45 @@
+// 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.
+
+// Negative compilation test for arena usage.
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/unittest.pb.h>
+
+#ifdef TEST_ARENA_PRIVATE_CONSTRUCTOR
+
+namespace google {
+void ArenaPrivateConstructor() {
+  google::protobuf::Arena arena;
+  protobuf_unittest::TestAllTypes message(&arena);
+}
+
+#endif
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena_nc_test.py b/src/third_party/protobuf-3/src/google/protobuf/arena_nc_test.py
new file mode 100644
index 0000000..56a7dd0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena_nc_test.py
@@ -0,0 +1,61 @@
+#! /usr/bin/env python
+#
+# 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.
+
+"""Negative compilation unit tests for arena API."""
+
+import unittest
+
+from google3.testing.pybase import fake_target_util
+from google3.testing.pybase import unittest
+
+
+class ArenaNcTest(unittest.TestCase):
+
+  def testCompilerErrors(self):
+    """Runs a list of tests to verify compiler error messages."""
+
+    # Defines a list of test specs, where each element is a tuple
+    # (test name, list of regexes for matching the compiler errors).
+    test_specs = [
+        ('ARENA_PRIVATE_CONSTRUCTOR',
+         [r'calling a protected constructor']),
+        ('SANITY', None)]
+
+    fake_target_util.AssertCcCompilerErrors(
+        self,                         # The current test case.
+        'google3/google/protobuf/arena_nc',  # The fake target file.
+        'arena_nc.o',                 # The sub-target to build.
+        test_specs                    # List of test specifications.
+        )
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.cc b/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.cc
new file mode 100644
index 0000000..df9c5bd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.cc
@@ -0,0 +1,50 @@
+// 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.
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+
+
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+NoHeapChecker::~NoHeapChecker() {
+  capture_alloc.Unhook();
+  EXPECT_EQ(0, capture_alloc.alloc_count());
+  EXPECT_EQ(0, capture_alloc.free_count());
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.h b/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.h
new file mode 100644
index 0000000..690cc70
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena_test_util.h
@@ -0,0 +1,60 @@
+// 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_ARENA_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class NoHeapChecker {
+ public:
+  NoHeapChecker() {
+    capture_alloc.Hook();
+  }
+  ~NoHeapChecker();
+ private:
+  class NewDeleteCapture {
+   public:
+    // TOOD(xiaofeng): Implement this for opensource protobuf.
+    void Hook() {}
+    void Unhook() {}
+    int alloc_count() { return 0; }
+    int free_count() { return 0; }
+  } capture_alloc;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arena_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/arena_unittest.cc
new file mode 100644
index 0000000..ab25ffe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arena_unittest.cc
@@ -0,0 +1,1354 @@
+// 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.
+
+#include <google/protobuf/arena.h>
+
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <typeinfo>
+#include <vector>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_arena.pb.h>
+#include <google/protobuf/unittest_no_arena.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+using proto2_arena_unittest::ArenaMessage;
+using protobuf_unittest::TestAllTypes;
+using protobuf_unittest::TestAllExtensions;
+using protobuf_unittest::TestOneof2;
+using protobuf_unittest::TestEmptyMessage;
+
+namespace protobuf {
+namespace {
+
+class Notifier {
+ public:
+  Notifier() : count_(0) {}
+  void Notify() {
+    count_++;
+  }
+  int GetCount() {
+    return count_;
+  }
+
+ private:
+  int count_;
+};
+
+class SimpleDataType {
+ public:
+  SimpleDataType() : notifier_(NULL) {}
+  void SetNotifier(Notifier* notifier) {
+    notifier_ = notifier;
+  }
+  virtual ~SimpleDataType() {
+    if (notifier_ != NULL) {
+      notifier_->Notify();
+    }
+  };
+ private:
+  Notifier* notifier_;
+};
+
+// A simple class that does not allow copying and so cannot be used as a
+// parameter type without "const &".
+class PleaseDontCopyMe {
+ public:
+  explicit PleaseDontCopyMe(int value) : value_(value) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
+};
+
+// A class that takes four different types as constructor arguments.
+class MustBeConstructedWithOneThroughFour {
+ public:
+  MustBeConstructedWithOneThroughFour(
+      int one, const char* two, const string& three,
+      const PleaseDontCopyMe* four)
+      : one_(one), two_(two), three_(three), four_(four) {}
+
+  int one_;
+  const char* const two_;
+  string three_;
+  const PleaseDontCopyMe* four_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
+};
+
+// A class that takes eight different types as constructor arguments.
+class MustBeConstructedWithOneThroughEight {
+ public:
+  MustBeConstructedWithOneThroughEight(
+      int one, const char* two, const string& three,
+      const PleaseDontCopyMe* four, int five, const char* six,
+      const string& seven, const string& eight)
+      : one_(one), two_(two), three_(three), four_(four), five_(five),
+        six_(six), seven_(seven), eight_(eight) {}
+
+  int one_;
+  const char* const two_;
+  string three_;
+  const PleaseDontCopyMe* four_;
+  int five_;
+  const char* const six_;
+  string seven_;
+  string eight_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
+};
+
+}  // namespace
+
+TEST(ArenaTest, ArenaConstructable) {
+  EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
+  EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
+  EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
+}
+
+TEST(ArenaTest, BasicCreate) {
+  Arena arena;
+  EXPECT_TRUE(Arena::Create<int32>(&arena) != NULL);
+  EXPECT_TRUE(Arena::Create<int64>(&arena) != NULL);
+  EXPECT_TRUE(Arena::Create<float>(&arena) != NULL);
+  EXPECT_TRUE(Arena::Create<double>(&arena) != NULL);
+  EXPECT_TRUE(Arena::Create<string>(&arena) != NULL);
+  arena.Own(new int32);
+  arena.Own(new int64);
+  arena.Own(new float);
+  arena.Own(new double);
+  arena.Own(new string);
+  arena.Own<int>(NULL);
+  Notifier notifier;
+  SimpleDataType* data = Arena::Create<SimpleDataType>(&arena);
+  data->SetNotifier(&notifier);
+  data = new SimpleDataType;
+  data->SetNotifier(&notifier);
+  arena.Own(data);
+  arena.Reset();
+  EXPECT_EQ(2, notifier.GetCount());
+}
+
+TEST(ArenaTest, CreateWithFourConstructorArguments) {
+  Arena arena;
+  const string three("3");
+  const PleaseDontCopyMe four(4);
+  const MustBeConstructedWithOneThroughFour* new_object =
+      Arena::Create<MustBeConstructedWithOneThroughFour>(
+          &arena, 1, "2", three, &four);
+  EXPECT_TRUE(new_object != NULL);
+  ASSERT_EQ(1, new_object->one_);
+  ASSERT_STREQ("2", new_object->two_);
+  ASSERT_EQ("3", new_object->three_);
+  ASSERT_EQ(4, new_object->four_->value());
+}
+
+TEST(ArenaTest, CreateWithEightConstructorArguments) {
+  Arena arena;
+  const string three("3");
+  const PleaseDontCopyMe four(4);
+  const string seven("7");
+  const string eight("8");
+  const MustBeConstructedWithOneThroughEight* new_object =
+      Arena::Create<MustBeConstructedWithOneThroughEight>(
+          &arena, 1, "2", three, &four, 5, "6", seven, eight);
+  EXPECT_TRUE(new_object != NULL);
+  ASSERT_EQ(1, new_object->one_);
+  ASSERT_STREQ("2", new_object->two_);
+  ASSERT_EQ("3", new_object->three_);
+  ASSERT_EQ(4, new_object->four_->value());
+  ASSERT_EQ(5, new_object->five_);
+  ASSERT_STREQ("6", new_object->six_);
+  ASSERT_EQ("7", new_object->seven_);
+  ASSERT_EQ("8", new_object->eight_);
+}
+
+TEST(ArenaTest, InitialBlockTooSmall) {
+  // Construct a small (64 byte) initial block of memory to be used by the
+  // arena allocator; then, allocate an object which will not fit in the
+  // initial block.
+  std::vector<char> arena_block(64);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  char* p = ::google::protobuf::Arena::CreateArray<char>(&arena, 96);
+  uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
+
+  // Ensure that the arena allocator did not return memory pointing into the
+  // initial block of memory.
+  uintptr_t arena_start = reinterpret_cast<uintptr_t>(&arena_block[0]);
+  uintptr_t arena_end = arena_start + arena_block.size();
+  EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
+
+  // Write to the memory we allocated; this should (but is not guaranteed to)
+  // trigger a check for heap corruption if the object was allocated from the
+  // initially-provided block.
+  memset(p, '\0', 96);
+}
+
+TEST(ArenaTest, Parsing) {
+  TestAllTypes original;
+  TestUtil::SetAllFields(&original);
+
+  // Test memory leak.
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+  TestUtil::ExpectAllFieldsSet(*arena_message);
+
+  // Test that string fields have null terminator bytes (earlier bug).
+  EXPECT_EQ(strlen(original.optional_string().c_str()),
+            strlen(arena_message->optional_string().c_str()));
+}
+
+TEST(ArenaTest, UnknownFields) {
+  TestAllTypes original;
+  TestUtil::SetAllFields(&original);
+
+  // Test basic parsing into (populating) and reading out of unknown fields on
+  // an arena.
+  Arena arena;
+  TestEmptyMessage* arena_message =
+      Arena::CreateMessage<TestEmptyMessage>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+
+  TestAllTypes copied;
+  copied.ParseFromString(arena_message->SerializeAsString());
+  TestUtil::ExpectAllFieldsSet(copied);
+
+  // Exercise UFS manual manipulation (setters).
+  arena_message = Arena::CreateMessage<TestEmptyMessage>(&arena);
+  arena_message->mutable_unknown_fields()->AddVarint(
+      TestAllTypes::kOptionalInt32FieldNumber, 42);
+  copied.Clear();
+  copied.ParseFromString(arena_message->SerializeAsString());
+  EXPECT_TRUE(copied.has_optional_int32());
+  EXPECT_EQ(42, copied.optional_int32());
+
+  // Exercise UFS swap path.
+  TestEmptyMessage* arena_message_2 =
+      Arena::CreateMessage<TestEmptyMessage>(&arena);
+  arena_message_2->Swap(arena_message);
+  copied.Clear();
+  copied.ParseFromString(arena_message_2->SerializeAsString());
+  EXPECT_TRUE(copied.has_optional_int32());
+  EXPECT_EQ(42, copied.optional_int32());
+
+  // Test field manipulation.
+  TestEmptyMessage* arena_message_3 =
+      Arena::CreateMessage<TestEmptyMessage>(&arena);
+  arena_message_3->mutable_unknown_fields()->AddVarint(1000, 42);
+  arena_message_3->mutable_unknown_fields()->AddFixed32(1001, 42);
+  arena_message_3->mutable_unknown_fields()->AddFixed64(1002, 42);
+  arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003);
+  arena_message_3->mutable_unknown_fields()->DeleteSubrange(0, 2);
+  arena_message_3->mutable_unknown_fields()->DeleteByNumber(1002);
+  arena_message_3->mutable_unknown_fields()->DeleteByNumber(1003);
+  EXPECT_TRUE(arena_message_3->unknown_fields().empty());
+}
+
+TEST(ArenaTest, Swap) {
+  Arena arena1;
+  Arena arena2;
+  TestAllTypes* arena1_message;
+  TestAllTypes* arena2_message;
+
+  // Case 1: Swap(), no UFS on either message, both messages on different
+  // arenas. Arena pointers should remain the same after swap.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  arena1_message->Swap(arena2_message);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+
+  // Case 2: Swap(), UFS on one message, both messages on different arenas.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
+  arena1_message->Swap(arena2_message);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+  EXPECT_EQ(0, arena1_message->unknown_fields().field_count());
+  EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
+  EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
+
+  // Case 3: Swap(), UFS on both messages, both messages on different arenas.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
+  arena2_message->mutable_unknown_fields()->AddVarint(2, 84);
+  arena1_message->Swap(arena2_message);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+  EXPECT_EQ(1, arena1_message->unknown_fields().field_count());
+  EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
+  EXPECT_EQ(84, arena1_message->unknown_fields().field(0).varint());
+  EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
+}
+
+TEST(ArenaTest, ReflectionSwapFields) {
+  Arena arena1;
+  Arena arena2;
+  TestAllTypes* arena1_message;
+  TestAllTypes* arena2_message;
+
+  // Case 1: messages on different arenas, only one message is set.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  TestUtil::SetAllFields(arena1_message);
+  const Reflection* reflection = arena1_message->GetReflection();
+  std::vector<const FieldDescriptor*> fields;
+  reflection->ListFields(*arena1_message, &fields);
+  reflection->SwapFields(arena1_message, arena2_message, fields);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+  string output;
+  arena1_message->SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+  TestUtil::ExpectAllFieldsSet(*arena2_message);
+  reflection->SwapFields(arena1_message, arena2_message, fields);
+  arena2_message->SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+  TestUtil::ExpectAllFieldsSet(*arena1_message);
+
+  // Case 2: messages on different arenas, both messages are set.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  TestUtil::SetAllFields(arena1_message);
+  TestUtil::SetAllFields(arena2_message);
+  reflection->SwapFields(arena1_message, arena2_message, fields);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+  TestUtil::ExpectAllFieldsSet(*arena1_message);
+  TestUtil::ExpectAllFieldsSet(*arena2_message);
+
+  // Case 3: messages on different arenas with different lifetimes.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  {
+    Arena arena3;
+    TestAllTypes* arena3_message = Arena::CreateMessage<TestAllTypes>(&arena3);
+    TestUtil::SetAllFields(arena3_message);
+    reflection->SwapFields(arena1_message, arena3_message, fields);
+  }
+  TestUtil::ExpectAllFieldsSet(*arena1_message);
+
+  // Case 4: one message on arena, the other on heap.
+  arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  TestAllTypes message;
+  TestUtil::SetAllFields(arena1_message);
+  reflection->SwapFields(arena1_message, &message, fields);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(NULL, message.GetArena());
+  arena1_message->SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(ArenaTest, SetAllocatedMessage) {
+  Arena arena;
+  TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+  nested->set_bb(118);
+  arena_message->set_allocated_optional_nested_message(nested);
+  EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+
+  protobuf_unittest_no_arena::TestNoArenaMessage no_arena_message;
+  EXPECT_FALSE(no_arena_message.has_arena_message());
+  no_arena_message.set_allocated_arena_message(NULL);
+  EXPECT_FALSE(no_arena_message.has_arena_message());
+  no_arena_message.set_allocated_arena_message(new ArenaMessage);
+  EXPECT_TRUE(no_arena_message.has_arena_message());
+}
+
+TEST(ArenaTest, ReleaseMessage) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->mutable_optional_nested_message()->set_bb(118);
+  google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
+      arena_message->release_optional_nested_message());
+  EXPECT_EQ(118, nested->bb());
+
+  TestAllTypes::NestedMessage* released_null =
+      arena_message->release_optional_nested_message();
+  EXPECT_EQ(NULL, released_null);
+}
+
+TEST(ArenaTest, SetAllocatedString) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  string* allocated_str = new string("hello");
+  arena_message->set_allocated_optional_string(allocated_str);
+  EXPECT_EQ("hello", arena_message->optional_string());
+}
+
+TEST(ArenaTest, ReleaseString) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->set_optional_string("hello");
+  google::protobuf::scoped_ptr<string> released_str(
+      arena_message->release_optional_string());
+  EXPECT_EQ("hello", *released_str);
+
+  // Test default value.
+}
+
+
+TEST(ArenaTest, SwapBetweenArenasWithAllFieldsSet) {
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  {
+    Arena arena2;
+    TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+    TestUtil::SetAllFields(arena2_message);
+    arena2_message->Swap(arena1_message);
+    string output;
+    arena2_message->SerializeToString(&output);
+    EXPECT_EQ(0, output.size());
+  }
+  TestUtil::ExpectAllFieldsSet(*arena1_message);
+}
+
+TEST(ArenaTest, SwapBetweenArenaAndNonArenaWithAllFieldsSet) {
+  TestAllTypes non_arena_message;
+  TestUtil::SetAllFields(&non_arena_message);
+  {
+    Arena arena2;
+    TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+    TestUtil::SetAllFields(arena2_message);
+    arena2_message->Swap(&non_arena_message);
+    TestUtil::ExpectAllFieldsSet(*arena2_message);
+    TestUtil::ExpectAllFieldsSet(non_arena_message);
+  }
+}
+
+TEST(ArenaTest, UnsafeArenaSwap) {
+  Arena shared_arena;
+  TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
+  TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
+  TestUtil::SetAllFields(message1);
+  message1->UnsafeArenaSwap(message2);
+  TestUtil::ExpectAllFieldsSet(*message2);
+}
+
+TEST(ArenaTest, SwapBetweenArenasUsingReflection) {
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  {
+    Arena arena2;
+    TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+    TestUtil::SetAllFields(arena2_message);
+    const Reflection* r = arena2_message->GetReflection();
+    r->Swap(arena1_message, arena2_message);
+    string output;
+    arena2_message->SerializeToString(&output);
+    EXPECT_EQ(0, output.size());
+  }
+  TestUtil::ExpectAllFieldsSet(*arena1_message);
+}
+
+TEST(ArenaTest, SwapBetweenArenaAndNonArenaUsingReflection) {
+  TestAllTypes non_arena_message;
+  TestUtil::SetAllFields(&non_arena_message);
+  {
+    Arena arena2;
+    TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+    TestUtil::SetAllFields(arena2_message);
+    const Reflection* r = arena2_message->GetReflection();
+    r->Swap(&non_arena_message, arena2_message);
+    TestUtil::ExpectAllFieldsSet(*arena2_message);
+    TestUtil::ExpectAllFieldsSet(non_arena_message);
+  }
+}
+
+TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
+  TestAllTypes::NestedMessage* nested_msg = NULL;
+  string* nested_string = NULL;
+  {
+    Arena arena;
+    TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+    arena_message->mutable_optional_nested_message()->set_bb(42);
+    *arena_message->mutable_optional_string() = "Hello";
+    nested_msg = arena_message->release_optional_nested_message();
+    nested_string = arena_message->release_optional_string();
+  }
+  EXPECT_EQ(42, nested_msg->bb());
+  EXPECT_EQ("Hello", *nested_string);
+  delete nested_msg;
+  delete nested_string;
+}
+
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
+  TestAllTypes::NestedMessage* nested_msg = NULL;
+  // Note: no string: reflection API only supports releasing submessages.
+  {
+    Arena arena;
+    TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+    arena_message->mutable_optional_nested_message()->set_bb(42);
+    const Reflection* r = arena_message->GetReflection();
+    const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
+        "optional_nested_message");
+    nested_msg = static_cast<TestAllTypes::NestedMessage*>(
+        r->ReleaseMessage(arena_message, f));
+  }
+  EXPECT_EQ(42, nested_msg->bb());
+  delete nested_msg;
+}
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
+
+TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  TestAllTypes::NestedMessage* nested_msg = NULL;
+  TestAllTypes::NestedMessage* orig_nested_msg = NULL;
+  string* nested_string = NULL;
+  string* orig_nested_string = NULL;
+  arena_message->mutable_optional_nested_message()->set_bb(42);
+  *arena_message->mutable_optional_string() = "Hello";
+  orig_nested_msg = arena_message->mutable_optional_nested_message();
+  orig_nested_string = arena_message->mutable_optional_string();
+  nested_msg = arena_message->unsafe_arena_release_optional_nested_message();
+  nested_string = arena_message->unsafe_arena_release_optional_string();
+
+  EXPECT_EQ(orig_nested_msg, nested_msg);
+  EXPECT_EQ(orig_nested_string, nested_string);
+  // Released pointers still on arena; no 'delete' calls needed here.
+}
+
+TEST(ArenaTest, SetAllocatedAcrossArenas) {
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  TestAllTypes::NestedMessage* heap_submessage =
+      new TestAllTypes::NestedMessage();
+  heap_submessage->set_bb(42);
+  arena1_message->set_allocated_optional_nested_message(heap_submessage);
+  // Should keep same object and add to arena's Own()-list.
+  EXPECT_EQ(heap_submessage,
+            arena1_message->mutable_optional_nested_message());
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    arena1_message->set_allocated_optional_nested_message(arena2_submessage);
+    EXPECT_NE(arena2_submessage,
+              arena1_message->mutable_optional_nested_message());
+  }
+
+  TestAllTypes::NestedMessage* arena1_submessage =
+      Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+  arena1_submessage->set_bb(42);
+  TestAllTypes* heap_message = new TestAllTypes;
+  heap_message->set_allocated_optional_nested_message(arena1_submessage);
+  EXPECT_NE(arena1_submessage,
+            heap_message->mutable_optional_nested_message());
+  delete heap_message;
+}
+
+TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
+  // Same as above, with reflection.
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  const Reflection* r = arena1_message->GetReflection();
+  const Descriptor* d = arena1_message->GetDescriptor();
+  const FieldDescriptor* msg_field = d->FindFieldByName(
+      "optional_nested_message");
+  TestAllTypes::NestedMessage* heap_submessage =
+      new TestAllTypes::NestedMessage();
+  heap_submessage->set_bb(42);
+  r->SetAllocatedMessage(arena1_message, heap_submessage, msg_field);
+  // Should keep same object and add to arena's Own()-list.
+  EXPECT_EQ(heap_submessage,
+            arena1_message->mutable_optional_nested_message());
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field);
+    EXPECT_NE(arena2_submessage,
+              arena1_message->mutable_optional_nested_message());
+  }
+
+  TestAllTypes::NestedMessage* arena1_submessage =
+      Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+  arena1_submessage->set_bb(42);
+  TestAllTypes* heap_message = new TestAllTypes;
+  r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field);
+  EXPECT_NE(arena1_submessage,
+            heap_message->mutable_optional_nested_message());
+  delete heap_message;
+}
+
+TEST(ArenaTest, AddAllocatedWithReflection) {
+  Arena arena1;
+  ArenaMessage* arena1_message = Arena::CreateMessage<ArenaMessage>(&arena1);
+  const Reflection* r = arena1_message->GetReflection();
+  const Descriptor* d = arena1_message->GetDescriptor();
+  const FieldDescriptor* fd =
+      d->FindFieldByName("repeated_import_no_arena_message");
+  // Message with cc_enable_arenas = false;
+  r->AddMessage(arena1_message, fd);
+  r->AddMessage(arena1_message, fd);
+  r->AddMessage(arena1_message, fd);
+  EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
+  // Message with cc_enable_arenas = true;
+  fd = d->FindFieldByName("repeated_nested_message");
+  r->AddMessage(arena1_message, fd);
+  r->AddMessage(arena1_message, fd);
+  r->AddMessage(arena1_message, fd);
+  EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
+}
+
+TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
+  {
+    RepeatedPtrField<TestAllTypes> repeated_field;
+    EXPECT_TRUE(repeated_field.empty());
+    EXPECT_EQ(0, repeated_field.size());
+    // Ownership is passed to repeated_field.
+    TestAllTypes* cleared = new TestAllTypes();
+    repeated_field.AddCleared(cleared);
+    EXPECT_TRUE(repeated_field.empty());
+    EXPECT_EQ(0, repeated_field.size());
+  }
+  {
+    RepeatedPtrField<TestAllTypes> repeated_field;
+    EXPECT_TRUE(repeated_field.empty());
+    EXPECT_EQ(0, repeated_field.size());
+    // Ownership is passed to repeated_field.
+    TestAllTypes* cleared = new TestAllTypes();
+    repeated_field.AddAllocated(cleared);
+    EXPECT_FALSE(repeated_field.empty());
+    EXPECT_EQ(1, repeated_field.size());
+  }
+}
+
+TEST(ArenaTest, AddAllocatedToRepeatedField) {
+  // Heap->arena case.
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  for (int i = 0; i < 10; i++) {
+    TestAllTypes::NestedMessage* heap_submessage =
+        new TestAllTypes::NestedMessage();
+    heap_submessage->set_bb(42);
+    arena1_message->mutable_repeated_nested_message()->
+        AddAllocated(heap_submessage);
+    // Should not copy object -- will use arena_->Own().
+    EXPECT_EQ(heap_submessage,
+              &arena1_message->repeated_nested_message(i));
+    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+  }
+
+  // Arena1->Arena2 case.
+  arena1_message->Clear();
+  for (int i = 0; i < 10; i++) {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    arena1_message->mutable_repeated_nested_message()->
+        AddAllocated(arena2_submessage);
+    // Should copy object.
+    EXPECT_NE(arena2_submessage,
+              &arena1_message->repeated_nested_message(i));
+    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+  }
+
+  // Arena->heap case.
+  TestAllTypes* heap_message = new TestAllTypes();
+  for (int i = 0; i < 10; i++) {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    heap_message->mutable_repeated_nested_message()->
+        AddAllocated(arena2_submessage);
+    // Should copy object.
+    EXPECT_NE(arena2_submessage,
+              &heap_message->repeated_nested_message(i));
+    EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+  }
+  delete heap_message;
+
+  // Heap-arena case for strings (which are not arena-allocated).
+  arena1_message->Clear();
+  for (int i = 0; i < 10; i++) {
+    string* s = new string("Test");
+    arena1_message->mutable_repeated_string()->
+        AddAllocated(s);
+    // Should not copy.
+    EXPECT_EQ(s, &arena1_message->repeated_string(i));
+    EXPECT_EQ("Test", arena1_message->repeated_string(i));
+  }
+}
+
+TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
+  // Heap->arena case.
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  const Reflection* r = arena1_message->GetReflection();
+  const Descriptor* d = arena1_message->GetDescriptor();
+  const FieldDescriptor* fd =
+      d->FindFieldByName("repeated_nested_message");
+  for (int i = 0; i < 10; i++) {
+    TestAllTypes::NestedMessage* heap_submessage =
+        new TestAllTypes::NestedMessage;
+    heap_submessage->set_bb(42);
+    r->AddAllocatedMessage(arena1_message, fd, heap_submessage);
+    // Should not copy object -- will use arena_->Own().
+    EXPECT_EQ(heap_submessage,
+              &arena1_message->repeated_nested_message(i));
+    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+  }
+
+  // Arena1->Arena2 case.
+  arena1_message->Clear();
+  for (int i = 0; i < 10; i++) {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
+    // Should copy object.
+    EXPECT_NE(arena2_submessage,
+              &arena1_message->repeated_nested_message(i));
+    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+  }
+
+  // Arena->heap case.
+  TestAllTypes* heap_message = new TestAllTypes;
+  for (int i = 0; i < 10; i++) {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
+    // Should copy object.
+    EXPECT_NE(arena2_submessage,
+              &heap_message->repeated_nested_message(i));
+    EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+  }
+  delete heap_message;
+}
+
+TEST(ArenaTest, ReleaseLastRepeatedField) {
+  // Release from arena-allocated repeated field and ensure that returned object
+  // is heap-allocated.
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  for (int i = 0; i < 10; i++) {
+    TestAllTypes::NestedMessage* nested =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
+    nested->set_bb(42);
+    arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
+  }
+
+  for (int i = 0; i < 10; i++) {
+    const TestAllTypes::NestedMessage *orig_submessage =
+        &arena_message->repeated_nested_message(10 - 1 - i);  // last element
+    TestAllTypes::NestedMessage *released =
+        arena_message->mutable_repeated_nested_message()->ReleaseLast();
+    EXPECT_NE(released, orig_submessage);
+    EXPECT_EQ(42, released->bb());
+    delete released;
+  }
+
+  // Test UnsafeArenaReleaseLast().
+  for (int i = 0; i < 10; i++) {
+    TestAllTypes::NestedMessage* nested =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
+    nested->set_bb(42);
+    arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
+  }
+
+  for (int i = 0; i < 10; i++) {
+    const TestAllTypes::NestedMessage *orig_submessage =
+        &arena_message->repeated_nested_message(10 - 1 - i);  // last element
+    TestAllTypes::NestedMessage *released =
+        arena_message->mutable_repeated_nested_message()->
+        UnsafeArenaReleaseLast();
+    EXPECT_EQ(released, orig_submessage);
+    EXPECT_EQ(42, released->bb());
+    // no delete -- |released| is on the arena.
+  }
+
+  // Test string case as well. ReleaseLast() in this case must copy the string,
+  // even though it was originally heap-allocated and its pointer was simply
+  // appended to the repeated field's internal vector, because the string was
+  // placed on the arena's destructor list and cannot be removed from that list
+  // (so the arena permanently owns the original instance).
+  arena_message->Clear();
+  for (int i = 0; i < 10; i++) {
+    string* s = new string("Test");
+    arena_message->mutable_repeated_string()->AddAllocated(s);
+  }
+  for (int i = 0; i < 10; i++) {
+    const string* orig_element = &arena_message->repeated_string(10 - 1 - i);
+    string* released = arena_message->mutable_repeated_string()->ReleaseLast();
+    EXPECT_NE(released, orig_element);
+    EXPECT_EQ("Test", *released);
+    delete released;
+  }
+}
+
+TEST(ArenaTest, UnsafeArenaReleaseAdd) {
+  // Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an
+  // arena-allocated string from one message to another.
+  Arena arena;
+  TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+  TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+  string* arena_string = Arena::Create<string>(&arena);
+  *arena_string = "Test content";
+
+  message1->unsafe_arena_set_allocated_optional_string(arena_string);
+  EXPECT_EQ(arena_string, message1->mutable_optional_string());
+  message2->unsafe_arena_set_allocated_optional_string(
+      message1->unsafe_arena_release_optional_string());
+  EXPECT_EQ(arena_string, message2->mutable_optional_string());
+}
+
+TEST(ArenaTest, UnsafeArenaAddAllocated) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  for (int i = 0; i < 10; i++) {
+    string* arena_string = Arena::Create<string>(&arena);
+    message->mutable_repeated_string()->UnsafeArenaAddAllocated(arena_string);
+    EXPECT_EQ(arena_string, message->mutable_repeated_string(i));
+  }
+}
+
+TEST(ArenaTest, UnsafeArenaRelease) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+
+  string* s = new string("test string");
+  message->unsafe_arena_set_allocated_optional_string(s);
+  EXPECT_TRUE(message->has_optional_string());
+  EXPECT_EQ("test string", message->optional_string());
+  s = message->unsafe_arena_release_optional_string();
+  EXPECT_FALSE(message->has_optional_string());
+  delete s;
+
+  s = new string("test string");
+  message->unsafe_arena_set_allocated_oneof_string(s);
+  EXPECT_TRUE(message->has_oneof_string());
+  EXPECT_EQ("test string", message->oneof_string());
+  s = message->unsafe_arena_release_oneof_string();
+  EXPECT_FALSE(message->has_oneof_string());
+  delete s;
+}
+
+TEST(ArenaTest, ArenaOneofReflection) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  const Descriptor* desc = message->GetDescriptor();
+  const Reflection* refl = message->GetReflection();
+
+  const FieldDescriptor* string_field = desc->FindFieldByName(
+      "oneof_string");
+  const FieldDescriptor* msg_field = desc->FindFieldByName(
+      "oneof_nested_message");
+  const OneofDescriptor* oneof = desc->FindOneofByName(
+      "oneof_field");
+
+  refl->SetString(message, string_field, "Test value");
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  refl->ClearOneof(message, oneof);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+
+  Message* submsg = refl->MutableMessage(message, msg_field);
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  refl->ClearOneof(message, oneof);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+  refl->MutableMessage(message, msg_field);
+  EXPECT_TRUE(refl->HasOneof(*message, oneof));
+  submsg = refl->ReleaseMessage(message, msg_field);
+  EXPECT_FALSE(refl->HasOneof(*message, oneof));
+  EXPECT_TRUE(submsg->GetArena() == NULL);
+  delete submsg;
+}
+
+namespace {
+void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
+  // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
+  // between arenas.
+  RepeatedPtrField<TestAllTypes> field1(arena1);
+  RepeatedPtrField<TestAllTypes> field2(arena2);
+  for (int i = 0; i < 10; i++) {
+    TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena1);
+    t->set_optional_string("field1");
+    t->set_optional_int32(i);
+    if (arena1 != NULL) {
+      field1.UnsafeArenaAddAllocated(t);
+    } else {
+      field1.AddAllocated(t);
+    }
+  }
+  for (int i = 0; i < 5; i++) {
+    TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena2);
+    t->set_optional_string("field2");
+    t->set_optional_int32(i);
+    if (arena2 != NULL) {
+      field2.UnsafeArenaAddAllocated(t);
+    } else {
+      field2.AddAllocated(t);
+    }
+  }
+  field1.Swap(&field2);
+  EXPECT_EQ(5, field1.size());
+  EXPECT_EQ(10, field2.size());
+  EXPECT_TRUE(string("field1") == field2.Get(0).optional_string());
+  EXPECT_TRUE(string("field2") == field1.Get(0).optional_string());
+  // Ensure that fields retained their original order:
+  for (int i = 0; i < field1.size(); i++) {
+    EXPECT_EQ(i, field1.Get(i).optional_int32());
+  }
+  for (int i = 0; i < field2.size(); i++) {
+    EXPECT_EQ(i, field2.Get(i).optional_int32());
+  }
+}
+}  // namespace
+
+TEST(ArenaTest, SwapRepeatedField) {
+  Arena arena;
+  TestSwapRepeatedField(&arena, &arena);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithDifferentArenas) {
+  Arena arena1;
+  Arena arena2;
+  TestSwapRepeatedField(&arena1, &arena2);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnRightHandSide) {
+  Arena arena;
+  TestSwapRepeatedField(&arena, NULL);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnLeftHandSide) {
+  Arena arena;
+  TestSwapRepeatedField(NULL, &arena);
+}
+
+TEST(ArenaTest, ExtensionsOnArena) {
+  Arena arena;
+  // Ensure no leaks.
+  TestAllExtensions* message_ext =
+      Arena::CreateMessage<TestAllExtensions>(&arena);
+  message_ext->SetExtension(
+      protobuf_unittest::optional_int32_extension, 42);
+  message_ext->SetExtension(
+      protobuf_unittest::optional_string_extension, string("test"));
+  message_ext->MutableExtension(
+      protobuf_unittest::optional_nested_message_extension)->set_bb(42);
+}
+
+TEST(ArenaTest, RepeatedFieldOnArena) {
+  // Preallocate an initial arena block to avoid mallocs during hooked region.
+  std::vector<char> arena_block(1024 * 1024);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  {
+    internal::NoHeapChecker no_heap;
+
+    // Fill some repeated fields on the arena to test for leaks. Also verify no
+    // memory allocations.
+    RepeatedField<int32> repeated_int32(&arena);
+    RepeatedPtrField<TestAllTypes> repeated_message(&arena);
+    for (int i = 0; i < 100; i++) {
+      repeated_int32.Add(42);
+      repeated_message.Add()->set_optional_int32(42);
+      EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
+      const TestAllTypes* msg_in_repeated_field = &repeated_message.Get(0);
+      TestAllTypes* msg = repeated_message.UnsafeArenaReleaseLast();
+      EXPECT_EQ(msg_in_repeated_field, msg);
+    }
+
+    // UnsafeArenaExtractSubrange (i) should not leak and (ii) should return
+    // on-arena pointers.
+    for (int i = 0; i < 10; i++) {
+      repeated_message.Add()->set_optional_int32(42);
+    }
+    TestAllTypes* extracted_messages[5];
+    repeated_message.UnsafeArenaExtractSubrange(0, 5, extracted_messages);
+    EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
+    EXPECT_EQ(5, repeated_message.size());
+  }
+
+  // Now, outside the scope of the NoHeapChecker, test ExtractSubrange's copying
+  // semantics.
+  {
+    RepeatedPtrField<TestAllTypes> repeated_message(&arena);
+    for (int i = 0; i < 100; i++) {
+      repeated_message.Add()->set_optional_int32(42);
+    }
+
+    TestAllTypes* extracted_messages[5];
+    // ExtractSubrange should copy to the heap.
+    repeated_message.ExtractSubrange(0, 5, extracted_messages);
+    EXPECT_EQ(NULL, extracted_messages[0]->GetArena());
+    // We need to free the heap-allocated messages to prevent a leak.
+    for (int i = 0; i < 5; i++) {
+      delete extracted_messages[i];
+      extracted_messages[i] = NULL;
+    }
+  }
+
+  // Now check that we can create RepeatedFields/RepeatedPtrFields themselves on
+  // the arena. They have the necessary type traits so that they can behave like
+  // messages in this way. This is useful for higher-level generic templated
+  // code that may allocate messages or repeated fields of messages on an arena.
+  {
+    RepeatedPtrField<TestAllTypes>* repeated_ptr_on_arena =
+        Arena::CreateMessage< RepeatedPtrField<TestAllTypes> >(&arena);
+    for (int i = 0; i < 10; i++) {
+      // Add some elements and let the leak-checker ensure that everything is
+      // freed.
+      repeated_ptr_on_arena->Add();
+    }
+
+    RepeatedField<int>* repeated_int_on_arena =
+        Arena::CreateMessage< RepeatedField<int> >(&arena);
+    for (int i = 0; i < 100; i++) {
+      repeated_int_on_arena->Add(i);
+    }
+
+  }
+
+  arena.Reset();
+}
+
+
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+TEST(ArenaTest, MutableMessageReflection) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  const Reflection* r = message->GetReflection();
+  const Descriptor* d = message->GetDescriptor();
+  const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
+  TestAllTypes::NestedMessage* submessage =
+      static_cast<TestAllTypes::NestedMessage*>(
+          r->MutableMessage(message, field));
+  TestAllTypes::NestedMessage* submessage_expected =
+      message->mutable_optional_nested_message();
+
+  EXPECT_EQ(submessage_expected, submessage);
+  EXPECT_EQ(&arena, submessage->GetArena());
+
+  const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
+  submessage = static_cast<TestAllTypes::NestedMessage*>(
+      r->MutableMessage(message, oneof_field));
+  submessage_expected = message->mutable_oneof_nested_message();
+
+  EXPECT_EQ(submessage_expected, submessage);
+  EXPECT_EQ(&arena, submessage->GetArena());
+}
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
+
+
+namespace {
+
+void FillArenaAwareFields(TestAllTypes* message) {
+  string test_string = "hello world";
+  message->set_optional_int32(42);
+  message->set_optional_string(test_string);
+  message->set_optional_bytes(test_string);
+  message->mutable_optional_nested_message()->set_bb(42);
+
+  message->set_oneof_uint32(42);
+  message->mutable_oneof_nested_message()->set_bb(42);
+  message->set_oneof_string(test_string);
+  message->set_oneof_bytes(test_string);
+
+  message->add_repeated_int32(42);
+  // No repeated string: not yet arena-aware.
+  message->add_repeated_nested_message()->set_bb(42);
+  message->mutable_optional_lazy_message()->set_bb(42);
+}
+
+}
+
+// Test: no allocations occur on heap while touching all supported field types.
+TEST(ArenaTest, NoHeapAllocationsTest) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  {
+
+    TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+    FillArenaAwareFields(message);
+  }
+
+  arena.Reset();
+}
+
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+// Test construction on an arena via generic MessageLite interface. We should be
+// able to successfully deserialize on the arena without incurring heap
+// allocations, i.e., everything should still be arena-allocation-aware.
+TEST(ArenaTest, MessageLiteOnArena) {
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+  const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance();
+
+  TestAllTypes initial_message;
+  FillArenaAwareFields(&initial_message);
+  string serialized;
+  initial_message.SerializeToString(&serialized);
+
+  {
+
+    google::protobuf::MessageLite* generic_message = prototype->New(&arena);
+    EXPECT_TRUE(generic_message != NULL);
+    EXPECT_EQ(&arena, generic_message->GetArena());
+    EXPECT_TRUE(generic_message->ParseFromString(serialized));
+    TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
+    EXPECT_EQ(42, deserialized->optional_int32());
+  }
+
+  arena.Reset();
+}
+#endif  // !GOOGLE_PROTOBUF_NO_RTTI
+
+
+// RepeatedField should support non-POD types, and invoke constructors and
+// destructors appropriately, because it's used this way by lots of other code
+// (even if this was not its original intent).
+TEST(ArenaTest, RepeatedFieldWithNonPODType) {
+  {
+    RepeatedField<string> field_on_heap;
+    for (int i = 0; i < 100; i++) {
+      *field_on_heap.Add() = "test string long enough to exceed inline buffer";
+    }
+  }
+  {
+    Arena arena;
+    RepeatedField<string> field_on_arena(&arena);
+    for (int i = 0; i < 100; i++) {
+      *field_on_arena.Add() = "test string long enough to exceed inline buffer";
+    }
+  }
+}
+
+// Align n to next multiple of 8
+namespace {
+uint64 Align8(uint64 n) { return (n + 7) & -8; }
+}  // namespace
+
+TEST(ArenaTest, SpaceAllocated_and_Used) {
+  ArenaOptions options;
+  options.start_block_size = 256;
+  options.max_block_size = 8192;
+  Arena arena_1(options);
+  EXPECT_EQ(0, arena_1.SpaceAllocated());
+  EXPECT_EQ(0, arena_1.SpaceUsed());
+  EXPECT_EQ(0, arena_1.Reset());
+  ::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
+  // Arena will allocate slightly more than 320 for the block headers.
+  EXPECT_LE(320, arena_1.SpaceAllocated());
+  EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
+  EXPECT_LE(320, arena_1.Reset());
+
+  // Test with initial block.
+  std::vector<char> arena_block(1024);
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena_2(options);
+  EXPECT_EQ(1024, arena_2.SpaceAllocated());
+  EXPECT_EQ(0, arena_2.SpaceUsed());
+  EXPECT_EQ(1024, arena_2.Reset());
+  ::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
+  EXPECT_EQ(1024, arena_2.SpaceAllocated());
+  EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
+  EXPECT_EQ(1024, arena_2.Reset());
+
+  // Reset options to test doubling policy explicitly.
+  options.initial_block = NULL;
+  options.initial_block_size = 0;
+  Arena arena_3(options);
+  EXPECT_EQ(0, arena_3.SpaceUsed());
+  ::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
+  EXPECT_EQ(256, arena_3.SpaceAllocated());
+  EXPECT_EQ(Align8(190), arena_3.SpaceUsed());
+  ::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
+  EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
+  EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed());
+  EXPECT_EQ(256 + 512, arena_3.Reset());
+}
+
+TEST(ArenaTest, Alignment) {
+  ::google::protobuf::Arena arena;
+  for (int i = 0; i < 200; i++) {
+    void* p = ::google::protobuf::Arena::CreateArray<char>(&arena, i);
+    GOOGLE_CHECK_EQ(reinterpret_cast<uintptr_t>(p) % 8, 0) << i << ": " << p;
+  }
+}
+
+TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
+  ::google::protobuf::Arena arena;
+  ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena);
+  const ArenaMessage* const_pointer_to_message = message;
+  EXPECT_EQ(&arena, Arena::GetArena(message));
+  EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
+  ArenaMessage message;
+  const ArenaMessage* const_pointer_to_message = &message;
+  EXPECT_EQ(NULL, Arena::GetArena(&message));
+  EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
+  ::google::protobuf::Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  EXPECT_FALSE(message->has_optional_string());
+
+  string owned_string = "test with long enough content to heap-allocate";
+  message->unsafe_arena_set_allocated_optional_string(&owned_string);
+  EXPECT_TRUE(message->has_optional_string());
+
+  message->unsafe_arena_set_allocated_optional_string(NULL);
+  EXPECT_FALSE(message->has_optional_string());
+}
+
+// A helper utility class to only contain static hook functions, some
+// counters to be used to verify the counters have been called and a cookie
+// value to be verified.
+class ArenaHooksTestUtil {
+ public:
+  static void* on_init(::google::protobuf::Arena* arena) {
+    ++num_init;
+    int* cookie = new int(kCookieValue);
+    return static_cast<void*>(cookie);
+  }
+
+  static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size,
+                            void* cookie) {
+    ++num_allocations;
+    int cookie_value = *static_cast<int*>(cookie);
+    EXPECT_EQ(kCookieValue, cookie_value);
+  }
+
+  static void on_reset(::google::protobuf::Arena* arena, void* cookie,
+                       uint64 space_used) {
+    ++num_reset;
+    int cookie_value = *static_cast<int*>(cookie);
+    EXPECT_EQ(kCookieValue, cookie_value);
+  }
+
+  static void on_destruction(::google::protobuf::Arena* arena, void* cookie,
+                             uint64 space_used) {
+    ++num_destruct;
+    int cookie_value = *static_cast<int*>(cookie);
+    EXPECT_EQ(kCookieValue, cookie_value);
+    delete static_cast<int*>(cookie);
+  }
+
+  static const int kCookieValue = 999;
+  static uint32 num_init;
+  static uint32 num_allocations;
+  static uint32 num_reset;
+  static uint32 num_destruct;
+};
+uint32 ArenaHooksTestUtil::num_init = 0;
+uint32 ArenaHooksTestUtil::num_allocations = 0;
+uint32 ArenaHooksTestUtil::num_reset = 0;
+uint32 ArenaHooksTestUtil::num_destruct = 0;
+const int ArenaHooksTestUtil::kCookieValue;
+
+// Test the hooks are correctly called and that the cookie is passed.
+TEST(ArenaTest, ArenaHooksSanity) {
+  ::google::protobuf::ArenaOptions options;
+  options.on_arena_init = ArenaHooksTestUtil::on_init;
+  options.on_arena_allocation = ArenaHooksTestUtil::on_allocation;
+  options.on_arena_reset = ArenaHooksTestUtil::on_reset;
+  options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
+
+  // Scope for defining the arena
+  {
+    ::google::protobuf::Arena arena(options);
+    EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
+    EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
+    ::google::protobuf::Arena::Create<uint64>(&arena);
+    if (google::protobuf::internal::has_trivial_destructor<uint64>::value) {
+      EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
+    } else {
+      EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
+    }
+    arena.Reset();
+    arena.Reset();
+    EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
+  }
+  EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
+  EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arenastring.cc b/src/third_party/protobuf-3/src/google/protobuf/arenastring.cc
new file mode 100644
index 0000000..5a22ada
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arenastring.cc
@@ -0,0 +1,70 @@
+// 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.
+
+// The ArenaString implementation is not included in the open-source release. Do
+// not include this file in the distribution.
+
+#include <google/protobuf/arenastring.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+
+void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
+                                       ArenaStringPtr value) {
+  const ::std::string* me = *UnsafeRawStringPointer();
+  const ::std::string* other = *value.UnsafeRawStringPointer();
+  // If the pointers are the same then do nothing.
+  if (me != other) {
+    SetNoArena(default_value, value.GetNoArena(default_value));
+  }
+}
+
+::std::string* ArenaStringPtr::MutableNoArena(
+     const ::std::string* default_value) {
+  if (ptr_ == default_value) {
+    CreateInstanceNoArena(default_value);
+  }
+  return ptr_;
+}
+
+
+void ArenaStringPtr::DestroyNoArena(const ::std::string* default_value) {
+  if (ptr_ != default_value) {
+    delete ptr_;
+  }
+  ptr_ = NULL;
+}
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arenastring.h b/src/third_party/protobuf-3/src/google/protobuf/arenastring.h
new file mode 100755
index 0000000..d983cf6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arenastring.h
@@ -0,0 +1,304 @@
+// 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_ARENASTRING_H__
+#define GOOGLE_PROTOBUF_ARENASTRING_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/fastmem.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_message_util.h>
+
+
+
+// This is the implementation of arena string fields written for the open-source
+// release. The ArenaStringPtr struct below is an internal implementation class
+// and *should not be used* by user code. It is used to collect string
+// operations together into one place and abstract away the underlying
+// string-field pointer representation, so that (for example) an alternate
+// implementation that knew more about ::std::string's internals could integrate more
+// closely with the arena allocator.
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+struct LIBPROTOBUF_EXPORT ArenaStringPtr {
+  inline void Set(const ::std::string* default_value,
+                  const ::std::string& value, ::google::protobuf::Arena* arena) {
+    if (ptr_ == default_value) {
+      CreateInstance(arena, &value);
+    } else {
+      *ptr_ = value;
+    }
+  }
+
+  // Basic accessors.
+  inline const ::std::string& Get(const ::std::string* /* default_value */) const {
+    return *ptr_;
+  }
+
+  inline ::std::string* Mutable(const ::std::string* default_value,
+                           ::google::protobuf::Arena* arena) {
+    if (ptr_ == default_value) {
+      CreateInstance(arena, default_value);
+    }
+    return ptr_;
+  }
+
+  // Release returns a ::std::string* instance that is heap-allocated and is not
+  // Own()'d by any arena. If the field was not set, it returns NULL. The caller
+  // retains ownership. Clears this field back to NULL state. Used to implement
+  // release_<field>() methods on generated classes.
+  inline ::std::string* Release(const ::std::string* default_value,
+                           ::google::protobuf::Arena* arena) {
+    if (ptr_ == default_value) {
+      return NULL;
+    }
+    ::std::string* released = NULL;
+    if (arena != NULL) {
+      // ptr_ is owned by the arena -- we need to return a copy.
+      released = new ::std::string(*ptr_);
+    } else {
+      released = ptr_;
+    }
+    ptr_ = const_cast< ::std::string* >(default_value);
+    return released;
+  }
+
+  // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
+  // have its destructor already registered) if arena != NULL. If the field was
+  // not set, this returns NULL. This method clears this field back to NULL
+  // state. Used to implement unsafe_arena_release_<field>() methods on
+  // generated classes.
+  inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
+                                      ::google::protobuf::Arena* /* arena */) {
+    if (ptr_ == default_value) {
+      return NULL;
+    }
+    ::std::string* released = ptr_;
+    ptr_ = const_cast< ::std::string* >(default_value);
+    return released;
+  }
+
+  // Takes a string that is heap-allocated, and takes ownership. The string's
+  // destructor is registered with the arena. Used to implement
+  // set_allocated_<field> in generated classes.
+  inline void SetAllocated(const ::std::string* default_value,
+                           ::std::string* value, ::google::protobuf::Arena* arena) {
+    if (arena == NULL && ptr_ != default_value) {
+      Destroy(default_value, arena);
+    }
+    if (value != NULL) {
+      ptr_ = value;
+      if (arena != NULL) {
+        arena->Own(value);
+      }
+    } else {
+      ptr_ = const_cast< ::std::string* >(default_value);
+    }
+  }
+
+  // Takes a string that has lifetime equal to the arena's lifetime. The arena
+  // must be non-null. It is safe only to pass this method a value returned by
+  // UnsafeArenaRelease() on another field of a message in the same arena. Used
+  // to implement unsafe_arena_set_allocated_<field> in generated classes.
+  inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
+                                      ::std::string* value,
+                                      ::google::protobuf::Arena* /* arena */) {
+    if (value != NULL) {
+      ptr_ = value;
+    } else {
+      ptr_ = const_cast< ::std::string* >(default_value);
+    }
+  }
+
+  // Swaps internal pointers. Arena-safety semantics: this is guarded by the
+  // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
+  // 'unsafe' if called directly.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
+    std::swap(ptr_, other->ptr_);
+  }
+
+  // Frees storage (if not on an arena) and sets field to default value.
+  inline void Destroy(const ::std::string* default_value,
+                      ::google::protobuf::Arena* arena) {
+    if (arena == NULL && ptr_ != default_value) {
+      delete ptr_;
+    }
+    ptr_ = const_cast< ::std::string* >(default_value);
+  }
+
+  // Clears content, but keeps allocated string if arena != NULL, to avoid the
+  // overhead of heap operations. After this returns, the content (as seen by
+  // the user) will always be the empty string. Assumes that |default_value|
+  // is an empty string.
+  inline void ClearToEmpty(const ::std::string* default_value,
+                           ::google::protobuf::Arena* /* arena */) {
+    if (ptr_ == default_value) {
+      // Already set to default (which is empty) -- do nothing.
+    } else {
+      ptr_->clear();
+    }
+  }
+
+  // Clears content, but keeps allocated string if arena != NULL, to avoid the
+  // overhead of heap operations. After this returns, the content (as seen by
+  // the user) will always be equal to |default_value|.
+  inline void ClearToDefault(const ::std::string* default_value,
+                             ::google::protobuf::Arena* /* arena */) {
+    if (ptr_ == default_value) {
+      // Already set to default -- do nothing.
+    } else {
+      // Have another allocated string -- rather than throwing this away and
+      // resetting ptr_ to the canonical default string instance, we just reuse
+      // this instance.
+      *ptr_ = *default_value;
+    }
+  }
+
+  // Called from generated code / reflection runtime only. Resets value to point
+  // to a default string pointer, with the semantics that this ArenaStringPtr
+  // does not own the pointed-to memory. Disregards initial value of ptr_ (so
+  // this is the *ONLY* safe method to call after construction or when
+  // reinitializing after becoming the active field in a oneof union).
+  inline void UnsafeSetDefault(const ::std::string* default_value) {
+    // Casting away 'const' is safe here: accessors ensure that ptr_ is only
+    // returned as a const if it is equal to default_value.
+    ptr_ = const_cast< ::std::string* >(default_value);
+  }
+
+  // The 'NoArena' variants of methods below assume arena == NULL and are
+  // optimized to provide very little overhead relative to a raw string pointer
+  // (while still being in-memory compatible with other code that assumes
+  // ArenaStringPtr). Note the invariant that a class instance that has only
+  // ever been mutated by NoArena methods must *only* be in the String state
+  // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
+  // tagged-pointer manipulations to be avoided.
+  inline void SetNoArena(const ::std::string* default_value,
+                         const ::std::string& value) {
+    if (ptr_ == default_value) {
+      CreateInstanceNoArena(&value);
+    } else {
+      *ptr_ = value;
+    }
+  }
+
+  void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
+
+  inline const ::std::string& GetNoArena(const ::std::string* /* default_value */) const {
+    return *ptr_;
+  }
+
+  ::std::string* MutableNoArena(const ::std::string* default_value);
+
+  inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
+    if (ptr_ == default_value) {
+      return NULL;
+    } else {
+      ::std::string* released = ptr_;
+      ptr_ = const_cast< ::std::string* >(default_value);
+      return released;
+    }
+  }
+
+  inline void SetAllocatedNoArena(const ::std::string* default_value,
+                                  ::std::string* value) {
+    if (ptr_ != default_value) {
+      delete ptr_;
+    }
+    if (value != NULL) {
+      ptr_ = value;
+    } else {
+      ptr_ = const_cast< ::std::string* >(default_value);
+    }
+  }
+
+  void DestroyNoArena(const ::std::string* default_value);
+
+  inline void ClearToEmptyNoArena(const ::std::string* default_value) {
+    if (ptr_ == default_value) {
+      // Nothing: already equal to default (which is the empty string).
+    } else {
+      ptr_->clear();
+    }
+  }
+
+  inline void ClearToDefaultNoArena(const ::std::string* default_value) {
+    if (ptr_ == default_value) {
+      // Nothing: already set to default.
+    } else {
+      // Reuse existing allocated instance.
+      *ptr_ = *default_value;
+    }
+  }
+
+  // Internal accessor used only at parse time to provide direct access to the
+  // raw pointer from the shared parse routine (in the non-arenas case). The
+  // parse routine does the string allocation in order to save code size in the
+  // generated parsing code.
+  inline ::std::string** UnsafeRawStringPointer() {
+    return &ptr_;
+  }
+
+ private:
+  ::std::string* ptr_;
+
+  GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
+                                         const ::std::string* initial_value) {
+    // Assumes ptr_ is not NULL.
+    if (initial_value != NULL) {
+      ptr_ = new ::std::string(*initial_value);
+    } else {
+      ptr_ = new ::std::string();
+    }
+    if (arena != NULL) {
+      arena->Own(ptr_);
+    }
+  }
+  GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
+    if (initial_value != NULL) {
+      ptr_ = new ::std::string(*initial_value);
+    } else {
+      ptr_ = new ::std::string();
+    }
+  }
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ARENASTRING_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/arenastring_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/arenastring_unittest.cc
new file mode 100644
index 0000000..ea405d7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/arenastring_unittest.cc
@@ -0,0 +1,110 @@
+// 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.
+
+// Based on mvels@'s frankenstring.
+
+#include <google/protobuf/arenastring.h>
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <cstdlib>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using google::protobuf::internal::ArenaString;
+using google::protobuf::internal::ArenaStringPtr;
+
+namespace protobuf {
+
+
+static string WrapString(const char* value) {
+  return value;
+}
+
+// Test ArenaStringPtr with arena == NULL.
+TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
+  ArenaStringPtr field;
+  ::std::string default_value = "default";
+  field.UnsafeSetDefault(&default_value);
+  EXPECT_EQ(string("default"), field.Get(&default_value));
+  field.Set(&default_value, WrapString("Test short"), NULL);
+  EXPECT_EQ(string("Test short"), field.Get(&default_value));
+  field.Set(&default_value, WrapString("Test long long long long value"), NULL);
+  EXPECT_EQ(string("Test long long long long value"), field.Get(&default_value));
+  field.Set(&default_value, string(""), NULL);
+  field.Destroy(&default_value, NULL);
+
+  ArenaStringPtr field2;
+  field2.UnsafeSetDefault(&default_value);
+  ::std::string* mut = field2.Mutable(&default_value, NULL);
+  EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
+  EXPECT_EQ(mut, &field2.Get(&default_value));
+  EXPECT_NE(&default_value, mut);
+  EXPECT_EQ(string("default"), *mut);
+  *mut = "Test long long long long value";  // ensure string allocates storage
+  EXPECT_EQ(string("Test long long long long value"), field2.Get(&default_value));
+  field2.Destroy(&default_value, NULL);
+}
+
+TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
+  google::protobuf::Arena arena;
+  ArenaStringPtr field;
+  ::std::string default_value = "default";
+  field.UnsafeSetDefault(&default_value);
+  EXPECT_EQ(string("default"), field.Get(&default_value));
+  field.Set(&default_value, WrapString("Test short"), &arena);
+  EXPECT_EQ(string("Test short"), field.Get(&default_value));
+  field.Set(&default_value, WrapString("Test long long long long value"), &arena);
+  EXPECT_EQ(string("Test long long long long value"),
+            field.Get(&default_value));
+  field.Set(&default_value, string(""), &arena);
+  field.Destroy(&default_value, &arena);
+
+  ArenaStringPtr field2;
+  field2.UnsafeSetDefault(&default_value);
+  ::std::string* mut = field2.Mutable(&default_value, &arena);
+  EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
+  EXPECT_EQ(mut, &field2.Get(&default_value));
+  EXPECT_NE(&default_value, mut);
+  EXPECT_EQ(string("default"), *mut);
+  *mut = "Test long long long long value";  // ensure string allocates storage
+  EXPECT_EQ(string("Test long long long long value"),
+            field2.Get(&default_value));
+  field2.Destroy(&default_value, &arena);
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.cc
new file mode 100644
index 0000000..473eb4e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.cc
@@ -0,0 +1,85 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/code_generator.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+CodeGenerator::~CodeGenerator() {}
+GeneratorContext::~GeneratorContext() {}
+
+io::ZeroCopyOutputStream*
+GeneratorContext::OpenForAppend(const string& filename) {
+  return NULL;
+}
+
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
+    const string& filename, const string& insertion_point) {
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
+  return NULL;  // make compiler happy
+}
+
+void GeneratorContext::ListParsedFiles(
+    vector<const FileDescriptor*>* output) {
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
+}
+
+// Parses a set of comma-delimited name/value pairs.
+void ParseGeneratorParameter(const string& text,
+                             vector<pair<string, string> >* output) {
+  vector<string> parts = Split(text, ",", true);
+
+  for (int i = 0; i < parts.size(); i++) {
+    string::size_type equals_pos = parts[i].find_first_of('=');
+    pair<string, string> value;
+    if (equals_pos == string::npos) {
+      value.first = parts[i];
+      value.second = "";
+    } else {
+      value.first = parts[i].substr(0, equals_pos);
+      value.second = parts[i].substr(equals_pos + 1);
+    }
+    output->push_back(value);
+  }
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.h
new file mode 100644
index 0000000..b989f15
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/code_generator.h
@@ -0,0 +1,176 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Defines the abstract interface implemented by each of the language-specific
+// code generators.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <string>
+#include <vector>
+#include <utility>
+
+namespace google {
+namespace protobuf {
+
+namespace io { class ZeroCopyOutputStream; }
+class FileDescriptor;
+
+namespace compiler {
+
+// Defined in this file.
+class CodeGenerator;
+class GeneratorContext;
+
+// The abstract interface to a class which generates code implementing a
+// particular proto file in a particular language.  A number of these may
+// be registered with CommandLineInterface to support various languages.
+class LIBPROTOC_EXPORT CodeGenerator {
+ public:
+  inline CodeGenerator() {}
+  virtual ~CodeGenerator();
+
+  // Generates code for the given proto file, generating one or more files in
+  // the given output directory.
+  //
+  // A parameter to be passed to the generator can be specified on the
+  // command line.  This is intended to be used by Java and similar languages
+  // to specify which specific class from the proto file is to be generated,
+  // though it could have other uses as well.  It is empty if no parameter was
+  // given.
+  //
+  // Returns true if successful.  Otherwise, sets *error to a description of
+  // the problem (e.g. "invalid parameter") and returns false.
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* generator_context,
+                        string* error) const = 0;
+
+  // Generates code for all given proto files, generating one or more files in
+  // the given output directory.
+  //
+  // This method should be called instead of |Generate()| when
+  // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics
+  // when more than one `.proto` file is specified on one compiler invocation.
+  //
+  // WARNING: Please do not use unless legacy semantics force the code generator
+  // to produce a single output file for all input files, or otherwise require
+  // an examination of all input files first. The canonical code generator
+  // design produces one output file per input .proto file, and we do not wish
+  // to encourage alternate designs.
+  //
+  // A parameter is given as passed on the command line, as in |Generate()|
+  // above.
+  //
+  // Returns true if successful.  Otherwise, sets *error to a description of
+  // the problem (e.g. "invalid parameter") and returns false.
+  virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+                           const string& parameter,
+                           GeneratorContext* generator_context,
+                           string* error) const {
+    *error = "Unimplemented GenerateAll() method.";
+    return false;
+  }
+
+  // Returns true if the code generator expects to receive all FileDescriptors
+  // at once (via |GenerateAll()|), rather than one at a time (via
+  // |Generate()|). This is required to implement legacy semantics.
+  virtual bool HasGenerateAll() const { return false; }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
+};
+
+// CodeGenerators generate one or more files in a given directory.  This
+// abstract interface represents the directory to which the CodeGenerator is
+// to write and other information about the context in which the Generator
+// runs.
+class LIBPROTOC_EXPORT GeneratorContext {
+ public:
+  inline GeneratorContext() {}
+  virtual ~GeneratorContext();
+
+  // Opens the given file, truncating it if it exists, and returns a
+  // ZeroCopyOutputStream that writes to the file.  The caller takes ownership
+  // of the returned object.  This method never fails (a dummy stream will be
+  // returned instead).
+  //
+  // The filename given should be relative to the root of the source tree.
+  // E.g. the C++ generator, when generating code for "foo/bar.proto", will
+  // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
+  // "foo/" is included in these filenames.  The filename is not allowed to
+  // contain "." or ".." components.
+  virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
+
+  // Similar to Open() but the output will be appended to the file if exists
+  virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
+
+  // Creates a ZeroCopyOutputStream which will insert code into the given file
+  // at the given insertion point.  See plugin.proto (plugin.pb.h) for more
+  // information on insertion points.  The default implementation
+  // assert-fails -- it exists only for backwards-compatibility.
+  //
+  // WARNING:  This feature is currently EXPERIMENTAL and is subject to change.
+  virtual io::ZeroCopyOutputStream* OpenForInsert(
+      const string& filename, const string& insertion_point);
+
+  // Returns a vector of FileDescriptors for all the files being compiled
+  // in this run.  Useful for languages, such as Go, that treat files
+  // differently when compiled as a set rather than individually.
+  virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
+};
+
+// The type GeneratorContext was once called OutputDirectory. This typedef
+// provides backward compatibility.
+typedef GeneratorContext OutputDirectory;
+
+// Several code generators treat the parameter argument as holding a
+// list of options separated by commas.  This helper function parses
+// a set of comma-delimited name/value pairs: e.g.,
+//   "foo=bar,baz,qux=corge"
+// parses to the pairs:
+//   ("foo", "bar"), ("baz", ""), ("qux", "corge")
+extern void ParseGeneratorParameter(const string&,
+            vector<pair<string, string> >*);
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.cc
new file mode 100644
index 0000000..fcad6b6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.cc
@@ -0,0 +1,1879 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/stubs/platform_macros.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef _MSC_VER
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fstream>
+#include <iostream>
+#include <ctype.h>
+
+#ifdef GOOGLE_PROTOBUF_ARCH_SPARC
+#include <limits.h> //For PATH_MAX
+#endif
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/subprocess.h>
+#include <google/protobuf/compiler/zip_writer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#if defined(_WIN32)
+#define mkdir(name, mode) mkdir(name)
+#ifndef W_OK
+#define W_OK 02  // not defined by MSVC for whatever reason
+#endif
+#ifndef F_OK
+#define F_OK 00  // not defined by MSVC for whatever reason
+#endif
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#endif
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
+#endif
+#endif
+
+namespace {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const char* kPathSeparator = ";";
+#else
+static const char* kPathSeparator = ":";
+#endif
+
+// Returns true if the text looks like a Windows-style absolute path, starting
+// with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
+// copy in importer.cc?
+static bool IsWindowsAbsolutePath(const string& text) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+  return text.size() >= 3 && text[1] == ':' &&
+         isalpha(text[0]) &&
+         (text[2] == '/' || text[2] == '\\') &&
+         text.find_last_of(':') == 1;
+#else
+  return false;
+#endif
+}
+
+void SetFdToTextMode(int fd) {
+#ifdef _WIN32
+  if (_setmode(fd, _O_TEXT) == -1) {
+    // This should never happen, I think.
+    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno);
+  }
+#endif
+  // (Text and binary are the same on non-Windows platforms.)
+}
+
+void SetFdToBinaryMode(int fd) {
+#ifdef _WIN32
+  if (_setmode(fd, _O_BINARY) == -1) {
+    // This should never happen, I think.
+    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno);
+  }
+#endif
+  // (Text and binary are the same on non-Windows platforms.)
+}
+
+void AddTrailingSlash(string* path) {
+  if (!path->empty() && path->at(path->size() - 1) != '/') {
+    path->push_back('/');
+  }
+}
+
+bool VerifyDirectoryExists(const string& path) {
+  if (path.empty()) return true;
+
+  if (access(path.c_str(), F_OK) == -1) {
+    std::cerr << path << ": " << strerror(errno) << std::endl;
+    return false;
+  } else {
+    return true;
+  }
+}
+
+// Try to create the parent directory of the given file, creating the parent's
+// parent if necessary, and so on.  The full file name is actually
+// (prefix + filename), but we assume |prefix| already exists and only create
+// directories listed in |filename|.
+bool TryCreateParentDirectory(const string& prefix, const string& filename) {
+  // Recursively create parent directories to the output file.
+  vector<string> parts = Split(filename, "/", true);
+  string path_so_far = prefix;
+  for (int i = 0; i < parts.size() - 1; i++) {
+    path_so_far += parts[i];
+    if (mkdir(path_so_far.c_str(), 0777) != 0) {
+      if (errno != EEXIST) {
+        std::cerr << filename << ": while trying to create directory "
+                  << path_so_far << ": " << strerror(errno) << std::endl;
+        return false;
+      }
+    }
+    path_so_far += '/';
+  }
+
+  return true;
+}
+
+// Get the absolute path of this protoc binary.
+bool GetProtocAbsolutePath(string* path) {
+#ifdef _WIN32
+  char buffer[MAX_PATH];
+  int len = GetModuleFileNameA(NULL, buffer, MAX_PATH);
+#elif __APPLE__
+  char buffer[PATH_MAX];
+  int len = 0;
+
+  char dirtybuffer[PATH_MAX];
+  uint32_t size = sizeof(dirtybuffer);
+  if (_NSGetExecutablePath(dirtybuffer, &size) == 0) {
+    realpath(dirtybuffer, buffer);
+    len = strlen(buffer);
+  }
+#else
+  char buffer[PATH_MAX];
+  int len = readlink("/proc/self/exe", buffer, PATH_MAX);
+#endif
+  if (len > 0) {
+    path->assign(buffer, len);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Whether a path is where google/protobuf/descriptor.proto and other well-known
+// type protos are installed.
+bool IsInstalledProtoPath(const string& path) {
+  // Checking the descriptor.proto file should be good enough.
+  string file_path = path + "/google/protobuf/descriptor.proto";
+  return access(file_path.c_str(), F_OK) != -1;
+}
+
+// Add the paths where google/protobuf/descritor.proto and other well-known
+// type protos are installed.
+void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
+  // TODO(xiaofeng): The code currently only checks relative paths of where
+  // the protoc binary is installed. We probably should make it handle more
+  // cases than that.
+  string path;
+  if (!GetProtocAbsolutePath(&path)) {
+    return;
+  }
+  // Strip the binary name.
+  size_t pos = path.find_last_of("/\\");
+  if (pos == string::npos || pos == 0) {
+    return;
+  }
+  path = path.substr(0, pos);
+  // Check the binary's directory.
+  if (IsInstalledProtoPath(path)) {
+    paths->push_back(pair<string, string>("", path));
+    return;
+  }
+  // Check if there is an include subdirectory.
+  if (IsInstalledProtoPath(path + "/include")) {
+    paths->push_back(pair<string, string>("", path + "/include"));
+    return;
+  }
+  // Check if the upper level directory has an "include" subdirectory.
+  pos = path.find_last_of("/\\");
+  if (pos == string::npos || pos == 0) {
+    return;
+  }
+  path = path.substr(0, pos);
+  if (IsInstalledProtoPath(path + "/include")) {
+    paths->push_back(pair<string, string>("", path + "/include"));
+    return;
+  }
+}
+}  // namespace
+
+// A MultiFileErrorCollector that prints errors to stderr.
+class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
+                                           public io::ErrorCollector {
+ public:
+  ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
+    : format_(format), tree_(tree) {}
+  ~ErrorPrinter() {}
+
+  // implements MultiFileErrorCollector ------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    AddErrorOrWarning(filename, line, column, message, "error", std::cerr);
+  }
+
+  void AddWarning(const string& filename, int line, int column,
+                  const string& message) {
+    AddErrorOrWarning(filename, line, column, message, "warning", std::clog);
+  }
+
+  // implements io::ErrorCollector -----------------------------------
+  void AddError(int line, int column, const string& message) {
+    AddError("input", line, column, message);
+  }
+
+  void AddWarning(int line, int column, const string& message) {
+    AddErrorOrWarning("input", line, column, message, "warning", std::clog);
+  }
+
+ private:
+  void AddErrorOrWarning(
+      const string& filename, int line, int column,
+      const string& message, const string& type, ostream& out) {
+    // Print full path when running under MSVS
+    string dfile;
+    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
+        tree_ != NULL &&
+        tree_->VirtualFileToDiskFile(filename, &dfile)) {
+      out << dfile;
+    } else {
+      out << filename;
+    }
+
+    // Users typically expect 1-based line/column numbers, so we add 1
+    // to each here.
+    if (line != -1) {
+      // Allow for both GCC- and Visual-Studio-compatible output.
+      switch (format_) {
+        case CommandLineInterface::ERROR_FORMAT_GCC:
+          out << ":" << (line + 1) << ":" << (column + 1);
+          break;
+        case CommandLineInterface::ERROR_FORMAT_MSVS:
+          out << "(" << (line + 1) << ") : "
+              << type << " in column=" << (column + 1);
+          break;
+      }
+    }
+
+    if (type == "warning") {
+      out << ": warning: " << message << std::endl;
+    } else {
+      out << ": " << message << std::endl;
+    }
+  }
+
+  const ErrorFormat format_;
+  DiskSourceTree *tree_;
+};
+
+// -------------------------------------------------------------------
+
+// A GeneratorContext implementation that buffers files in memory, then dumps
+// them all to disk on demand.
+class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
+ public:
+  GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
+  ~GeneratorContextImpl();
+
+  // Write all files in the directory to disk at the given output location,
+  // which must end in a '/'.
+  bool WriteAllToDisk(const string& prefix);
+
+  // Write the contents of this directory to a ZIP-format archive with the
+  // given name.
+  bool WriteAllToZip(const string& filename);
+
+  // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR
+  // format, unless one has already been written.
+  void AddJarManifest();
+
+  // Get name of all output files.
+  void GetOutputFilenames(vector<string>* output_filenames);
+
+  // implements GeneratorContext --------------------------------------
+  io::ZeroCopyOutputStream* Open(const string& filename);
+  io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
+  io::ZeroCopyOutputStream* OpenForInsert(
+      const string& filename, const string& insertion_point);
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
+
+ private:
+  friend class MemoryOutputStream;
+
+  // map instead of hash_map so that files are written in order (good when
+  // writing zips).
+  map<string, string*> files_;
+  const vector<const FileDescriptor*>& parsed_files_;
+  bool had_error_;
+};
+
+class CommandLineInterface::MemoryOutputStream
+    : public io::ZeroCopyOutputStream {
+ public:
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename,
+                     bool append_mode);
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename,
+                     const string& insertion_point);
+  virtual ~MemoryOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  virtual bool Next(void** data, int* size) { return inner_->Next(data, size); }
+  virtual void BackUp(int count)            {        inner_->BackUp(count);    }
+  virtual int64 ByteCount() const           { return inner_->ByteCount();      }
+
+ private:
+  // Where to insert the string when it's done.
+  GeneratorContextImpl* directory_;
+  string filename_;
+  string insertion_point_;
+
+  // The string we're building.
+  string data_;
+
+  // Whether we should append the output stream to the existing file.
+  bool append_mode_;
+
+  // StringOutputStream writing to data_.
+  google::protobuf::scoped_ptr<io::StringOutputStream> inner_;
+};
+
+// -------------------------------------------------------------------
+
+CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
+    const vector<const FileDescriptor*>& parsed_files)
+    : parsed_files_(parsed_files),
+      had_error_(false) {
+}
+
+CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
+  STLDeleteValues(&files_);
+}
+
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
+    const string& prefix) {
+  if (had_error_) {
+    return false;
+  }
+
+  if (!VerifyDirectoryExists(prefix)) {
+    return false;
+  }
+
+  for (map<string, string*>::const_iterator iter = files_.begin();
+       iter != files_.end(); ++iter) {
+    const string& relative_filename = iter->first;
+    const char* data = iter->second->data();
+    int size = iter->second->size();
+
+    if (!TryCreateParentDirectory(prefix, relative_filename)) {
+      return false;
+    }
+    string filename = prefix + relative_filename;
+
+    // Create the output file.
+    int file_descriptor;
+    do {
+      file_descriptor =
+        open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+    } while (file_descriptor < 0 && errno == EINTR);
+
+    if (file_descriptor < 0) {
+      int error = errno;
+      std::cerr << filename << ": " << strerror(error);
+      return false;
+    }
+
+    // Write the file.
+    while (size > 0) {
+      int write_result;
+      do {
+        write_result = write(file_descriptor, data, size);
+      } while (write_result < 0 && errno == EINTR);
+
+      if (write_result <= 0) {
+        // Write error.
+
+        // FIXME(kenton):  According to the man page, if write() returns zero,
+        //   there was no error; write() simply did not write anything.  It's
+        //   unclear under what circumstances this might happen, but presumably
+        //   errno won't be set in this case.  I am confused as to how such an
+        //   event should be handled.  For now I'm treating it as an error,
+        //   since retrying seems like it could lead to an infinite loop.  I
+        //   suspect this never actually happens anyway.
+
+        if (write_result < 0) {
+          int error = errno;
+          std::cerr << filename << ": write: " << strerror(error);
+        } else {
+          std::cerr << filename << ": write() returned zero?" << std::endl;
+        }
+        return false;
+      }
+
+      data += write_result;
+      size -= write_result;
+    }
+
+    if (close(file_descriptor) != 0) {
+      int error = errno;
+      std::cerr << filename << ": close: " << strerror(error);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
+    const string& filename) {
+  if (had_error_) {
+    return false;
+  }
+
+  // Create the output file.
+  int file_descriptor;
+  do {
+    file_descriptor =
+      open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+  } while (file_descriptor < 0 && errno == EINTR);
+
+  if (file_descriptor < 0) {
+    int error = errno;
+    std::cerr << filename << ": " << strerror(error);
+    return false;
+  }
+
+  // Create the ZipWriter
+  io::FileOutputStream stream(file_descriptor);
+  ZipWriter zip_writer(&stream);
+
+  for (map<string, string*>::const_iterator iter = files_.begin();
+       iter != files_.end(); ++iter) {
+    zip_writer.Write(iter->first, *iter->second);
+  }
+
+  zip_writer.WriteDirectory();
+
+  if (stream.GetErrno() != 0) {
+    std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+  }
+
+  if (!stream.Close()) {
+    std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+  }
+
+  return true;
+}
+
+void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
+  string** map_slot = &files_["META-INF/MANIFEST.MF"];
+  if (*map_slot == NULL) {
+    *map_slot = new string(
+        "Manifest-Version: 1.0\n"
+        "Created-By: 1.6.0 (protoc)\n"
+        "\n");
+  }
+}
+
+void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
+    vector<string>* output_filenames) {
+  for (map<string, string*>::iterator iter = files_.begin();
+       iter != files_.end(); ++iter) {
+    output_filenames->push_back(iter->first);
+  }
+}
+
+io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
+    const string& filename) {
+  return new MemoryOutputStream(this, filename, false);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForAppend(
+    const string& filename) {
+  return new MemoryOutputStream(this, filename, true);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForInsert(
+    const string& filename, const string& insertion_point) {
+  return new MemoryOutputStream(this, filename, insertion_point);
+}
+
+// -------------------------------------------------------------------
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+    GeneratorContextImpl* directory, const string& filename, bool append_mode)
+    : directory_(directory),
+      filename_(filename),
+      append_mode_(append_mode),
+      inner_(new io::StringOutputStream(&data_)) {
+}
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+    GeneratorContextImpl* directory, const string& filename,
+    const string& insertion_point)
+    : directory_(directory),
+      filename_(filename),
+      insertion_point_(insertion_point),
+      inner_(new io::StringOutputStream(&data_)) {
+}
+
+CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
+  // Make sure all data has been written.
+  inner_.reset();
+
+  // Insert into the directory.
+  string** map_slot = &directory_->files_[filename_];
+
+  if (insertion_point_.empty()) {
+    // This was just a regular Open().
+    if (*map_slot != NULL) {
+      if (append_mode_) {
+        (*map_slot)->append(data_);
+      } else {
+        std::cerr << filename_ << ": Tried to write the same file twice."
+                  << std::endl;
+        directory_->had_error_ = true;
+      }
+      return;
+    }
+
+    *map_slot = new string;
+    (*map_slot)->swap(data_);
+  } else {
+    // This was an OpenForInsert().
+
+    // If the data doens't end with a clean line break, add one.
+    if (!data_.empty() && data_[data_.size() - 1] != '\n') {
+      data_.push_back('\n');
+    }
+
+    // Find the file we are going to insert into.
+    if (*map_slot == NULL) {
+      std::cerr << filename_
+                << ": Tried to insert into file that doesn't exist."
+                << std::endl;
+      directory_->had_error_ = true;
+      return;
+    }
+    string* target = *map_slot;
+
+    // Find the insertion point.
+    string magic_string = strings::Substitute(
+        "@@protoc_insertion_point($0)", insertion_point_);
+    string::size_type pos = target->find(magic_string);
+
+    if (pos == string::npos) {
+      std::cerr << filename_ << ": insertion point \"" << insertion_point_
+                << "\" not found." << std::endl;
+      directory_->had_error_ = true;
+      return;
+    }
+
+    // Seek backwards to the beginning of the line, which is where we will
+    // insert the data.  Note that this has the effect of pushing the insertion
+    // point down, so the data is inserted before it.  This is intentional
+    // because it means that multiple insertions at the same point will end
+    // up in the expected order in the final output.
+    pos = target->find_last_of('\n', pos);
+    if (pos == string::npos) {
+      // Insertion point is on the first line.
+      pos = 0;
+    } else {
+      // Advance to character after '\n'.
+      ++pos;
+    }
+
+    // Extract indent.
+    string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos);
+
+    if (indent_.empty()) {
+      // No indent.  This makes things easier.
+      target->insert(pos, data_);
+    } else {
+      // Calculate how much space we need.
+      int indent_size = 0;
+      for (int i = 0; i < data_.size(); i++) {
+        if (data_[i] == '\n') indent_size += indent_.size();
+      }
+
+      // Make a hole for it.
+      target->insert(pos, data_.size() + indent_size, '\0');
+
+      // Now copy in the data.
+      string::size_type data_pos = 0;
+      char* target_ptr = string_as_array(target) + pos;
+      while (data_pos < data_.size()) {
+        // Copy indent.
+        memcpy(target_ptr, indent_.data(), indent_.size());
+        target_ptr += indent_.size();
+
+        // Copy line from data_.
+        // We already guaranteed that data_ ends with a newline (above), so this
+        // search can't fail.
+        string::size_type line_length =
+            data_.find_first_of('\n', data_pos) + 1 - data_pos;
+        memcpy(target_ptr, data_.data() + data_pos, line_length);
+        target_ptr += line_length;
+        data_pos += line_length;
+      }
+
+      GOOGLE_CHECK_EQ(target_ptr,
+          string_as_array(target) + pos + data_.size() + indent_size);
+    }
+  }
+}
+
+// ===================================================================
+
+CommandLineInterface::CommandLineInterface()
+  : mode_(MODE_COMPILE),
+    print_mode_(PRINT_NONE),
+    error_format_(ERROR_FORMAT_GCC),
+    imports_in_descriptor_set_(false),
+    source_info_in_descriptor_set_(false),
+    disallow_services_(false),
+    inputs_are_proto_path_relative_(false) {}
+CommandLineInterface::~CommandLineInterface() {}
+
+void CommandLineInterface::RegisterGenerator(const string& flag_name,
+                                             CodeGenerator* generator,
+                                             const string& help_text) {
+  GeneratorInfo info;
+  info.flag_name = flag_name;
+  info.generator = generator;
+  info.help_text = help_text;
+  generators_by_flag_name_[flag_name] = info;
+}
+
+void CommandLineInterface::RegisterGenerator(const string& flag_name,
+                                             const string& option_flag_name,
+                                             CodeGenerator* generator,
+                                             const string& help_text) {
+  GeneratorInfo info;
+  info.flag_name = flag_name;
+  info.option_flag_name = option_flag_name;
+  info.generator = generator;
+  info.help_text = help_text;
+  generators_by_flag_name_[flag_name] = info;
+  generators_by_option_name_[option_flag_name] = info;
+}
+
+void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
+  plugin_prefix_ = exe_name_prefix;
+}
+
+int CommandLineInterface::Run(int argc, const char* const argv[]) {
+  Clear();
+  switch (ParseArguments(argc, argv)) {
+    case PARSE_ARGUMENT_DONE_AND_EXIT:
+      return 0;
+    case PARSE_ARGUMENT_FAIL:
+      return 1;
+    case PARSE_ARGUMENT_DONE_AND_CONTINUE:
+      break;
+  }
+
+  AddDefaultProtoPaths(&proto_path_);
+
+  // Set up the source tree.
+  DiskSourceTree source_tree;
+  for (int i = 0; i < proto_path_.size(); i++) {
+    source_tree.MapPath(proto_path_[i].first, proto_path_[i].second);
+  }
+
+  // Map input files to virtual paths if necessary.
+  if (!inputs_are_proto_path_relative_) {
+    if (!MakeInputsBeProtoPathRelative(&source_tree)) {
+      return 1;
+    }
+  }
+
+  // Allocate the Importer.
+  ErrorPrinter error_collector(error_format_, &source_tree);
+  Importer importer(&source_tree, &error_collector);
+
+  vector<const FileDescriptor*> parsed_files;
+
+  // Parse each file.
+  for (int i = 0; i < input_files_.size(); i++) {
+    // Import the file.
+    importer.AddUnusedImportTrackFile(input_files_[i]);
+    const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
+    importer.ClearUnusedImportTrackFiles();
+    if (parsed_file == NULL) return 1;
+    parsed_files.push_back(parsed_file);
+
+    // Enforce --disallow_services.
+    if (disallow_services_ && parsed_file->service_count() > 0) {
+      cerr << parsed_file->name() << ": This file contains services, but "
+              "--disallow_services was used." << endl;
+      return 1;
+    }
+  }
+
+  // We construct a separate GeneratorContext for each output location.  Note
+  // that two code generators may output to the same location, in which case
+  // they should share a single GeneratorContext so that OpenForInsert() works.
+  GeneratorContextMap output_directories;
+
+  // Generate output.
+  if (mode_ == MODE_COMPILE) {
+    for (int i = 0; i < output_directives_.size(); i++) {
+      string output_location = output_directives_[i].output_location;
+      if (!HasSuffixString(output_location, ".zip") &&
+          !HasSuffixString(output_location, ".jar")) {
+        AddTrailingSlash(&output_location);
+      }
+      GeneratorContextImpl** map_slot = &output_directories[output_location];
+
+      if (*map_slot == NULL) {
+        // First time we've seen this output location.
+        *map_slot = new GeneratorContextImpl(parsed_files);
+      }
+
+      if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
+        STLDeleteValues(&output_directories);
+        return 1;
+      }
+    }
+  }
+
+  // Write all output to disk.
+  for (GeneratorContextMap::iterator iter = output_directories.begin();
+       iter != output_directories.end(); ++iter) {
+    const string& location = iter->first;
+    GeneratorContextImpl* directory = iter->second;
+    if (HasSuffixString(location, "/")) {
+      if (!directory->WriteAllToDisk(location)) {
+        STLDeleteValues(&output_directories);
+        return 1;
+      }
+    } else {
+      if (HasSuffixString(location, ".jar")) {
+        directory->AddJarManifest();
+      }
+
+      if (!directory->WriteAllToZip(location)) {
+        STLDeleteValues(&output_directories);
+        return 1;
+      }
+    }
+  }
+
+  if (!dependency_out_name_.empty()) {
+    if (!GenerateDependencyManifestFile(parsed_files, output_directories,
+                                        &source_tree)) {
+      return 1;
+    }
+  }
+
+  STLDeleteValues(&output_directories);
+
+  if (!descriptor_set_name_.empty()) {
+    if (!WriteDescriptorSet(parsed_files)) {
+      return 1;
+    }
+  }
+
+  if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) {
+    if (codec_type_.empty()) {
+      // HACK:  Define an EmptyMessage type to use for decoding.
+      DescriptorPool pool;
+      FileDescriptorProto file;
+      file.set_name("empty_message.proto");
+      file.add_message_type()->set_name("EmptyMessage");
+      GOOGLE_CHECK(pool.BuildFile(file) != NULL);
+      codec_type_ = "EmptyMessage";
+      if (!EncodeOrDecode(&pool)) {
+        return 1;
+      }
+    } else {
+      if (!EncodeOrDecode(importer.pool())) {
+        return 1;
+      }
+    }
+  }
+
+  if (mode_ == MODE_PRINT) {
+    switch (print_mode_) {
+      case PRINT_FREE_FIELDS:
+        for (int i = 0; i < parsed_files.size(); ++i) {
+          const FileDescriptor* fd = parsed_files[i];
+          for (int j = 0; j < fd->message_type_count(); ++j) {
+            PrintFreeFieldNumbers(fd->message_type(j));
+          }
+        }
+        break;
+      case PRINT_NONE:
+        GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of "
+                     "flag parsing in the CommonadLineInterface.";
+        return 1;
+
+      // Do not add a default case.
+    }
+  }
+
+  return 0;
+}
+
+void CommandLineInterface::Clear() {
+  // Clear all members that are set by Run().  Note that we must not clear
+  // members which are set by other methods before Run() is called.
+  executable_name_.clear();
+  proto_path_.clear();
+  input_files_.clear();
+  output_directives_.clear();
+  codec_type_.clear();
+  descriptor_set_name_.clear();
+  dependency_out_name_.clear();
+
+  mode_ = MODE_COMPILE;
+  print_mode_ = PRINT_NONE;
+  imports_in_descriptor_set_ = false;
+  source_info_in_descriptor_set_ = false;
+  disallow_services_ = false;
+}
+
+bool CommandLineInterface::MakeInputsBeProtoPathRelative(
+    DiskSourceTree* source_tree) {
+  for (int i = 0; i < input_files_.size(); i++) {
+    string virtual_file, shadowing_disk_file;
+    switch (source_tree->DiskFileToVirtualFile(
+        input_files_[i], &virtual_file, &shadowing_disk_file)) {
+      case DiskSourceTree::SUCCESS:
+        input_files_[i] = virtual_file;
+        break;
+      case DiskSourceTree::SHADOWED:
+        std::cerr << input_files_[i]
+                  << ": Input is shadowed in the --proto_path by \""
+                  << shadowing_disk_file
+                  << "\".  Either use the latter file as your input or reorder "
+                     "the --proto_path so that the former file's location "
+                     "comes first." << std::endl;
+        return false;
+      case DiskSourceTree::CANNOT_OPEN:
+        std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
+        return false;
+      case DiskSourceTree::NO_MAPPING:
+        // First check if the file exists at all.
+        if (access(input_files_[i].c_str(), F_OK) < 0) {
+          // File does not even exist.
+          std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+        } else {
+          std::cerr
+              << input_files_[i]
+              << ": File does not reside within any path "
+                 "specified using --proto_path (or -I).  You must specify a "
+                 "--proto_path which encompasses this file.  Note that the "
+                 "proto_path must be an exact prefix of the .proto file "
+                 "names -- protoc is too dumb to figure out when two paths "
+                 "(e.g. absolute and relative) are equivalent (it's harder "
+                 "than you think)." << std::endl;
+        }
+        return false;
+    }
+  }
+
+  return true;
+}
+
+
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
+  executable_name_ = argv[0];
+
+  vector<string> arguments;
+  for (int i = 1; i < argc; ++i) {
+    arguments.push_back(argv[i]);
+  }
+
+  // Iterate through all arguments and parse them.
+  for (int i = 0; i < arguments.size(); ++i) {
+    string name, value;
+
+    if (ParseArgument(arguments[i].c_str(), &name, &value)) {
+      // Returned true => Use the next argument as the flag value.
+      if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') {
+        std::cerr << "Missing value for flag: " << name << std::endl;
+        if (name == "--decode") {
+          std::cerr << "To decode an unknown message, use --decode_raw."
+                    << std::endl;
+        }
+        return PARSE_ARGUMENT_FAIL;
+      } else {
+        ++i;
+        value = arguments[i];
+      }
+    }
+
+    ParseArgumentStatus status = InterpretArgument(name, value);
+    if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE)
+      return status;
+  }
+
+  // If no --proto_path was given, use the current working directory.
+  if (proto_path_.empty()) {
+    // Don't use make_pair as the old/default standard library on Solaris
+    // doesn't support it without explicit template parameters, which are
+    // incompatible with C++0x's make_pair.
+    proto_path_.push_back(pair<string, string>("", "."));
+  }
+
+  // Check some errror cases.
+  bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
+  if (decoding_raw && !input_files_.empty()) {
+    std::cerr << "When using --decode_raw, no input files should be given."
+              << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  } else if (!decoding_raw && input_files_.empty()) {
+    std::cerr << "Missing input file." << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  }
+  if (mode_ == MODE_COMPILE && output_directives_.empty() &&
+      descriptor_set_name_.empty()) {
+    std::cerr << "Missing output directives." << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  }
+  if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
+    std::cerr << "Can only use --dependency_out=FILE when generating code."
+              << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  }
+  if (!dependency_out_name_.empty() && input_files_.size() > 1) {
+    std::cerr
+        << "Can only process one input file when using --dependency_out=FILE."
+        << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  }
+  if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
+    std::cerr << "--include_imports only makes sense when combined with "
+                 "--descriptor_set_out." << std::endl;
+  }
+  if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
+    std::cerr << "--include_source_info only makes sense when combined with "
+                 "--descriptor_set_out." << std::endl;
+  }
+
+  return PARSE_ARGUMENT_DONE_AND_CONTINUE;
+}
+
+bool CommandLineInterface::ParseArgument(const char* arg,
+                                         string* name, string* value) {
+  bool parsed_value = false;
+
+  if (arg[0] != '-') {
+    // Not a flag.
+    name->clear();
+    parsed_value = true;
+    *value = arg;
+  } else if (arg[1] == '-') {
+    // Two dashes:  Multi-character name, with '=' separating name and
+    //   value.
+    const char* equals_pos = strchr(arg, '=');
+    if (equals_pos != NULL) {
+      *name = string(arg, equals_pos - arg);
+      *value = equals_pos + 1;
+      parsed_value = true;
+    } else {
+      *name = arg;
+    }
+  } else {
+    // One dash:  One-character name, all subsequent characters are the
+    //   value.
+    if (arg[1] == '\0') {
+      // arg is just "-".  We treat this as an input file, except that at
+      // present this will just lead to a "file not found" error.
+      name->clear();
+      *value = arg;
+      parsed_value = true;
+    } else {
+      *name = string(arg, 2);
+      *value = arg + 2;
+      parsed_value = !value->empty();
+    }
+  }
+
+  // Need to return true iff the next arg should be used as the value for this
+  // one, false otherwise.
+
+  if (parsed_value) {
+    // We already parsed a value for this flag.
+    return false;
+  }
+
+  if (*name == "-h" || *name == "--help" ||
+      *name == "--disallow_services" ||
+      *name == "--include_imports" ||
+      *name == "--include_source_info" ||
+      *name == "--version" ||
+      *name == "--decode_raw" ||
+      *name == "--print_free_field_numbers") {
+    // HACK:  These are the only flags that don't take a value.
+    //   They probably should not be hard-coded like this but for now it's
+    //   not worth doing better.
+    return false;
+  }
+
+  // Next argument is the flag value.
+  return true;
+}
+
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::InterpretArgument(const string& name,
+                                        const string& value) {
+  if (name.empty()) {
+    // Not a flag.  Just a filename.
+    if (value.empty()) {
+      std::cerr
+          << "You seem to have passed an empty string as one of the "
+             "arguments to " << executable_name_
+          << ".  This is actually "
+             "sort of hard to do.  Congrats.  Unfortunately it is not valid "
+             "input so the program is going to die now." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    input_files_.push_back(value);
+
+  } else if (name == "-I" || name == "--proto_path") {
+    // Java's -classpath (and some other languages) delimits path components
+    // with colons.  Let's accept that syntax too just to make things more
+    // intuitive.
+    vector<string> parts = Split(
+        value, kPathSeparator, true);
+
+    for (int i = 0; i < parts.size(); i++) {
+      string virtual_path;
+      string disk_path;
+
+      string::size_type equals_pos = parts[i].find_first_of('=');
+      if (equals_pos == string::npos) {
+        virtual_path = "";
+        disk_path = parts[i];
+      } else {
+        virtual_path = parts[i].substr(0, equals_pos);
+        disk_path = parts[i].substr(equals_pos + 1);
+      }
+
+      if (disk_path.empty()) {
+        std::cerr
+            << "--proto_path passed empty directory name.  (Use \".\" for "
+               "current directory.)" << std::endl;
+        return PARSE_ARGUMENT_FAIL;
+      }
+
+      // Make sure disk path exists, warn otherwise.
+      if (access(disk_path.c_str(), F_OK) < 0) {
+        std::cerr << disk_path << ": warning: directory does not exist."
+                  << std::endl;
+      }
+
+      // Don't use make_pair as the old/default standard library on Solaris
+      // doesn't support it without explicit template parameters, which are
+      // incompatible with C++0x's make_pair.
+      proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
+    }
+
+  } else if (name == "-o" || name == "--descriptor_set_out") {
+    if (!descriptor_set_name_.empty()) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (value.empty()) {
+      std::cerr << name << " requires a non-empty value." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (mode_ != MODE_COMPILE) {
+      std::cerr
+          << "Cannot use --encode or --decode and generate descriptors at the "
+             "same time." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    descriptor_set_name_ = value;
+
+  } else if (name == "--dependency_out") {
+    if (!dependency_out_name_.empty()) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (value.empty()) {
+      std::cerr << name << " requires a non-empty value." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    dependency_out_name_ = value;
+
+  } else if (name == "--include_imports") {
+    if (imports_in_descriptor_set_) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    imports_in_descriptor_set_ = true;
+
+  } else if (name == "--include_source_info") {
+    if (source_info_in_descriptor_set_) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    source_info_in_descriptor_set_ = true;
+
+  } else if (name == "-h" || name == "--help") {
+    PrintHelpText();
+    return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
+
+  } else if (name == "--version") {
+    if (!version_info_.empty()) {
+      std::cout << version_info_ << std::endl;
+    }
+    cout << "libprotoc "
+         << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
+         << endl;
+    return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
+
+  } else if (name == "--disallow_services") {
+    disallow_services_ = true;
+
+  } else if (name == "--encode" || name == "--decode" ||
+             name == "--decode_raw") {
+    if (mode_ != MODE_COMPILE) {
+      std::cerr << "Only one of --encode and --decode can be specified."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+      std::cerr << "Cannot use " << name
+                << " and generate code or descriptors at the same time."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
+
+    if (value.empty() && name != "--decode_raw") {
+      std::cerr << "Type name for " << name << " cannot be blank." << std::endl;
+      if (name == "--decode") {
+        std::cerr << "To decode an unknown message, use --decode_raw."
+                  << std::endl;
+      }
+      return PARSE_ARGUMENT_FAIL;
+    } else if (!value.empty() && name == "--decode_raw") {
+      std::cerr << "--decode_raw does not take a parameter." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    codec_type_ = value;
+
+  } else if (name == "--error_format") {
+    if (value == "gcc") {
+      error_format_ = ERROR_FORMAT_GCC;
+    } else if (value == "msvs") {
+      error_format_ = ERROR_FORMAT_MSVS;
+    } else {
+      std::cerr << "Unknown error format: " << value << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+  } else if (name == "--plugin") {
+    if (plugin_prefix_.empty()) {
+      std::cerr << "This compiler does not support plugins." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    string plugin_name;
+    string path;
+
+    string::size_type equals_pos = value.find_first_of('=');
+    if (equals_pos == string::npos) {
+      // Use the basename of the file.
+      string::size_type slash_pos = value.find_last_of('/');
+      if (slash_pos == string::npos) {
+        plugin_name = value;
+      } else {
+        plugin_name = value.substr(slash_pos + 1);
+      }
+      path = value;
+    } else {
+      plugin_name = value.substr(0, equals_pos);
+      path = value.substr(equals_pos + 1);
+    }
+
+    plugins_[plugin_name] = path;
+
+  } else if (name == "--print_free_field_numbers") {
+    if (mode_ != MODE_COMPILE) {
+      std::cerr << "Cannot use " << name
+                << " and use --encode, --decode or print "
+                << "other info at the same time." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+      std::cerr << "Cannot use " << name
+                << " and generate code or descriptors at the same time."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    mode_ = MODE_PRINT;
+    print_mode_ = PRINT_FREE_FIELDS;
+  } else {
+    // Some other flag.  Look it up in the generators list.
+    const GeneratorInfo* generator_info =
+        FindOrNull(generators_by_flag_name_, name);
+    if (generator_info == NULL &&
+        (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
+      // Check if it's a generator option flag.
+      generator_info = FindOrNull(generators_by_option_name_, name);
+      if (generator_info == NULL) {
+        std::cerr << "Unknown flag: " << name << std::endl;
+        return PARSE_ARGUMENT_FAIL;
+      } else {
+        string* parameters = &generator_parameters_[generator_info->flag_name];
+        if (!parameters->empty()) {
+          parameters->append(",");
+        }
+        parameters->append(value);
+      }
+    } else {
+      // It's an output flag.  Add it to the output directives.
+      if (mode_ != MODE_COMPILE) {
+        std::cerr << "Cannot use --encode, --decode or print .proto info and "
+                     "generate code at the same time." << std::endl;
+        return PARSE_ARGUMENT_FAIL;
+      }
+
+      OutputDirective directive;
+      directive.name = name;
+      if (generator_info == NULL) {
+        directive.generator = NULL;
+      } else {
+        directive.generator = generator_info->generator;
+      }
+
+      // Split value at ':' to separate the generator parameter from the
+      // filename.  However, avoid doing this if the colon is part of a valid
+      // Windows-style absolute path.
+      string::size_type colon_pos = value.find_first_of(':');
+      if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
+        directive.output_location = value;
+      } else {
+        directive.parameter = value.substr(0, colon_pos);
+        directive.output_location = value.substr(colon_pos + 1);
+      }
+
+      output_directives_.push_back(directive);
+    }
+  }
+
+  return PARSE_ARGUMENT_DONE_AND_CONTINUE;
+}
+
+void CommandLineInterface::PrintHelpText() {
+  // Sorry for indentation here; line wrapping would be uglier.
+  std::cerr <<
+"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
+"Parse PROTO_FILES and generate output based on the options given:\n"
+"  -IPATH, --proto_path=PATH   Specify the directory in which to search for\n"
+"                              imports.  May be specified multiple times;\n"
+"                              directories will be searched in order.  If not\n"
+"                              given, the current working directory is used.\n"
+"  --version                   Show version info and exit.\n"
+"  -h, --help                  Show this text and exit.\n"
+"  --encode=MESSAGE_TYPE       Read a text-format message of the given type\n"
+"                              from standard input and write it in binary\n"
+"                              to standard output.  The message type must\n"
+"                              be defined in PROTO_FILES or their imports.\n"
+"  --decode=MESSAGE_TYPE       Read a binary message of the given type from\n"
+"                              standard input and write it in text format\n"
+"                              to standard output.  The message type must\n"
+"                              be defined in PROTO_FILES or their imports.\n"
+"  --decode_raw                Read an arbitrary protocol message from\n"
+"                              standard input and write the raw tag/value\n"
+"                              pairs in text format to standard output.  No\n"
+"                              PROTO_FILES should be given when using this\n"
+"                              flag.\n"
+"  -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,\n"
+"    --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n"
+"                              the input files to FILE.\n"
+"  --include_imports           When using --descriptor_set_out, also include\n"
+"                              all dependencies of the input files in the\n"
+"                              set, so that the set is self-contained.\n"
+"  --include_source_info       When using --descriptor_set_out, do not strip\n"
+"                              SourceCodeInfo from the FileDescriptorProto.\n"
+"                              This results in vastly larger descriptors that\n"
+"                              include information about the original\n"
+"                              location of each decl in the source file as\n"
+"                              well as surrounding comments.\n"
+"  --dependency_out=FILE       Write a dependency output file in the format\n"
+"                              expected by make. This writes the transitive\n"
+"                              set of input file paths to FILE\n"
+"  --error_format=FORMAT       Set the format in which to print errors.\n"
+"                              FORMAT may be 'gcc' (the default) or 'msvs'\n"
+"                              (Microsoft Visual Studio format).\n"
+"  --print_free_field_numbers  Print the free field numbers of the messages\n"
+"                              defined in the given proto files. Groups share\n"
+"                              the same field number space with the parent \n"
+"                              message. Extension ranges are counted as \n"
+"                              occupied fields numbers.\n"
+      << std::endl;
+  if (!plugin_prefix_.empty()) {
+    std::cerr <<
+"  --plugin=EXECUTABLE         Specifies a plugin executable to use.\n"
+"                              Normally, protoc searches the PATH for\n"
+"                              plugins, but you may specify additional\n"
+"                              executables not in the path using this flag.\n"
+"                              Additionally, EXECUTABLE may be of the form\n"
+"                              NAME=PATH, in which case the given plugin name\n"
+"                              is mapped to the given executable even if\n"
+"                              the executable's own name differs." << std::endl;
+  }
+
+  for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
+       iter != generators_by_flag_name_.end(); ++iter) {
+    // FIXME(kenton):  If the text is long enough it will wrap, which is ugly,
+    //   but fixing this nicely (e.g. splitting on spaces) is probably more
+    //   trouble than it's worth.
+    std::cerr << "  " << iter->first << "=OUT_DIR "
+              << string(19 - iter->first.size(), ' ')  // Spaces for alignment.
+              << iter->second.help_text << std::endl;
+  }
+}
+
+bool CommandLineInterface::GenerateOutput(
+    const vector<const FileDescriptor*>& parsed_files,
+    const OutputDirective& output_directive,
+    GeneratorContext* generator_context) {
+  // Call the generator.
+  string error;
+  if (output_directive.generator == NULL) {
+    // This is a plugin.
+    GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") &&
+          HasSuffixString(output_directive.name, "_out"))
+        << "Bad name for plugin generator: " << output_directive.name;
+
+    // Strip the "--" and "_out" and add the plugin prefix.
+    string plugin_name = plugin_prefix_ + "gen-" +
+        output_directive.name.substr(2, output_directive.name.size() - 6);
+
+    if (!GeneratePluginOutput(parsed_files, plugin_name,
+                              output_directive.parameter,
+                              generator_context, &error)) {
+      std::cerr << output_directive.name << ": " << error << std::endl;
+      return false;
+    }
+  } else {
+    // Regular generator.
+    string parameters = output_directive.parameter;
+    if (!generator_parameters_[output_directive.name].empty()) {
+      if (!parameters.empty()) {
+        parameters.append(",");
+      }
+      parameters.append(generator_parameters_[output_directive.name]);
+    }
+    if (output_directive.generator->HasGenerateAll()) {
+      if (!output_directive.generator->GenerateAll(
+          parsed_files, parameters, generator_context, &error)) {
+          // Generator returned an error.
+          std::cerr << output_directive.name << ": "
+                    << ": " << error << std::endl;
+          return false;
+      }
+    } else {
+      for (int i = 0; i < parsed_files.size(); i++) {
+        if (!output_directive.generator->Generate(parsed_files[i], parameters,
+                                                  generator_context, &error)) {
+          // Generator returned an error.
+          std::cerr << output_directive.name << ": " << parsed_files[i]->name()
+                    << ": " << error << std::endl;
+          return false;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+bool CommandLineInterface::GenerateDependencyManifestFile(
+    const vector<const FileDescriptor*>& parsed_files,
+    const GeneratorContextMap& output_directories,
+    DiskSourceTree* source_tree) {
+  FileDescriptorSet file_set;
+
+  set<const FileDescriptor*> already_seen;
+  for (int i = 0; i < parsed_files.size(); i++) {
+    GetTransitiveDependencies(parsed_files[i],
+                              false,
+                              false,
+                              &already_seen,
+                              file_set.mutable_file());
+  }
+
+  vector<string> output_filenames;
+  for (GeneratorContextMap::const_iterator iter = output_directories.begin();
+       iter != output_directories.end(); ++iter) {
+    const string& location = iter->first;
+    GeneratorContextImpl* directory = iter->second;
+    vector<string> relative_output_filenames;
+    directory->GetOutputFilenames(&relative_output_filenames);
+    for (int i = 0; i < relative_output_filenames.size(); i++) {
+      string output_filename = location + relative_output_filenames[i];
+      if (output_filename.compare(0, 2, "./") == 0) {
+        output_filename = output_filename.substr(2);
+      }
+      output_filenames.push_back(output_filename);
+    }
+  }
+
+  int fd;
+  do {
+    fd = open(dependency_out_name_.c_str(),
+              O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+  } while (fd < 0 && errno == EINTR);
+
+  if (fd < 0) {
+    perror(dependency_out_name_.c_str());
+    return false;
+  }
+
+  io::FileOutputStream out(fd);
+  io::Printer printer(&out, '$');
+
+  for (int i = 0; i < output_filenames.size(); i++) {
+    printer.Print(output_filenames[i].c_str());
+    if (i == output_filenames.size() - 1) {
+      printer.Print(":");
+    } else {
+      printer.Print(" \\\n");
+    }
+  }
+
+  for (int i = 0; i < file_set.file_size(); i++) {
+    const FileDescriptorProto& file = file_set.file(i);
+    const string& virtual_file = file.name();
+    string disk_file;
+    if (source_tree &&
+        source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) {
+      printer.Print(" $disk_file$", "disk_file", disk_file);
+      if (i < file_set.file_size() - 1) printer.Print("\\\n");
+    } else {
+      std::cerr << "Unable to identify path for file " << virtual_file
+                << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool CommandLineInterface::GeneratePluginOutput(
+    const vector<const FileDescriptor*>& parsed_files,
+    const string& plugin_name,
+    const string& parameter,
+    GeneratorContext* generator_context,
+    string* error) {
+  CodeGeneratorRequest request;
+  CodeGeneratorResponse response;
+
+  // Build the request.
+  if (!parameter.empty()) {
+    request.set_parameter(parameter);
+  }
+
+  set<const FileDescriptor*> already_seen;
+  for (int i = 0; i < parsed_files.size(); i++) {
+    request.add_file_to_generate(parsed_files[i]->name());
+    GetTransitiveDependencies(parsed_files[i],
+                              true,  // Include json_name for plugins.
+                              true,  // Include source code info.
+                              &already_seen, request.mutable_proto_file());
+  }
+
+  // Invoke the plugin.
+  Subprocess subprocess;
+
+  if (plugins_.count(plugin_name) > 0) {
+    subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME);
+  } else {
+    subprocess.Start(plugin_name, Subprocess::SEARCH_PATH);
+  }
+
+  string communicate_error;
+  if (!subprocess.Communicate(request, &response, &communicate_error)) {
+    *error = strings::Substitute("$0: $1", plugin_name, communicate_error);
+    return false;
+  }
+
+  // Write the files.  We do this even if there was a generator error in order
+  // to match the behavior of a compiled-in generator.
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> current_output;
+  for (int i = 0; i < response.file_size(); i++) {
+    const CodeGeneratorResponse::File& output_file = response.file(i);
+
+    if (!output_file.insertion_point().empty()) {
+      // Open a file for insert.
+      // We reset current_output to NULL first so that the old file is closed
+      // before the new one is opened.
+      current_output.reset();
+      current_output.reset(generator_context->OpenForInsert(
+          output_file.name(), output_file.insertion_point()));
+    } else if (!output_file.name().empty()) {
+      // Starting a new file.  Open it.
+      // We reset current_output to NULL first so that the old file is closed
+      // before the new one is opened.
+      current_output.reset();
+      current_output.reset(generator_context->Open(output_file.name()));
+    } else if (current_output == NULL) {
+      *error = strings::Substitute(
+        "$0: First file chunk returned by plugin did not specify a file name.",
+        plugin_name);
+      return false;
+    }
+
+    // Use CodedOutputStream for convenience; otherwise we'd need to provide
+    // our own buffer-copying loop.
+    io::CodedOutputStream writer(current_output.get());
+    writer.WriteString(output_file.content());
+  }
+
+  // Check for errors.
+  if (!response.error().empty()) {
+    // Generator returned an error.
+    *error = response.error();
+    return false;
+  }
+
+  return true;
+}
+
+bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
+  // Look up the type.
+  const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
+  if (type == NULL) {
+    std::cerr << "Type not defined: " << codec_type_ << std::endl;
+    return false;
+  }
+
+  DynamicMessageFactory dynamic_factory(pool);
+  google::protobuf::scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
+
+  if (mode_ == MODE_ENCODE) {
+    SetFdToTextMode(STDIN_FILENO);
+    SetFdToBinaryMode(STDOUT_FILENO);
+  } else {
+    SetFdToBinaryMode(STDIN_FILENO);
+    SetFdToTextMode(STDOUT_FILENO);
+  }
+
+  io::FileInputStream in(STDIN_FILENO);
+  io::FileOutputStream out(STDOUT_FILENO);
+
+  if (mode_ == MODE_ENCODE) {
+    // Input is text.
+    ErrorPrinter error_collector(error_format_);
+    TextFormat::Parser parser;
+    parser.RecordErrorsTo(&error_collector);
+    parser.AllowPartialMessage(true);
+
+    if (!parser.Parse(&in, message.get())) {
+      std::cerr << "Failed to parse input." << std::endl;
+      return false;
+    }
+  } else {
+    // Input is binary.
+    if (!message->ParsePartialFromZeroCopyStream(&in)) {
+      std::cerr << "Failed to parse input." << std::endl;
+      return false;
+    }
+  }
+
+  if (!message->IsInitialized()) {
+    std::cerr << "warning:  Input message is missing required fields:  "
+              << message->InitializationErrorString() << std::endl;
+  }
+
+  if (mode_ == MODE_ENCODE) {
+    // Output is binary.
+    if (!message->SerializePartialToZeroCopyStream(&out)) {
+      std::cerr << "output: I/O error." << std::endl;
+      return false;
+    }
+  } else {
+    // Output is text.
+    if (!TextFormat::Print(*message, &out)) {
+      std::cerr << "output: I/O error." << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool CommandLineInterface::WriteDescriptorSet(
+    const vector<const FileDescriptor*> parsed_files) {
+  FileDescriptorSet file_set;
+
+  if (imports_in_descriptor_set_) {
+    set<const FileDescriptor*> already_seen;
+    for (int i = 0; i < parsed_files.size(); i++) {
+      GetTransitiveDependencies(parsed_files[i],
+                                true,  // Include json_name
+                                source_info_in_descriptor_set_,
+                                &already_seen, file_set.mutable_file());
+    }
+  } else {
+    set<const FileDescriptor*> already_seen;
+    for (int i = 0; i < parsed_files.size(); i++) {
+      if (!already_seen.insert(parsed_files[i]).second) {
+        continue;
+      }
+      FileDescriptorProto* file_proto = file_set.add_file();
+      parsed_files[i]->CopyTo(file_proto);
+      parsed_files[i]->CopyJsonNameTo(file_proto);
+      if (source_info_in_descriptor_set_) {
+        parsed_files[i]->CopySourceCodeInfoTo(file_proto);
+      }
+    }
+  }
+
+  int fd;
+  do {
+    fd = open(descriptor_set_name_.c_str(),
+              O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+  } while (fd < 0 && errno == EINTR);
+
+  if (fd < 0) {
+    perror(descriptor_set_name_.c_str());
+    return false;
+  }
+
+  io::FileOutputStream out(fd);
+  if (!file_set.SerializeToZeroCopyStream(&out)) {
+    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+              << std::endl;
+    out.Close();
+    return false;
+  }
+  if (!out.Close()) {
+    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+              << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+void CommandLineInterface::GetTransitiveDependencies(
+    const FileDescriptor* file,
+    bool include_json_name,
+    bool include_source_code_info,
+    set<const FileDescriptor*>* already_seen,
+    RepeatedPtrField<FileDescriptorProto>* output) {
+  if (!already_seen->insert(file).second) {
+    // Already saw this file.  Skip.
+    return;
+  }
+
+  // Add all dependencies.
+  for (int i = 0; i < file->dependency_count(); i++) {
+    GetTransitiveDependencies(file->dependency(i),
+                              include_json_name,
+                              include_source_code_info,
+                              already_seen, output);
+  }
+
+  // Add this file.
+  FileDescriptorProto* new_descriptor = output->Add();
+  file->CopyTo(new_descriptor);
+  if (include_json_name) {
+    file->CopyJsonNameTo(new_descriptor);
+  }
+  if (include_source_code_info) {
+    file->CopySourceCodeInfoTo(new_descriptor);
+  }
+}
+
+namespace {
+
+// Utility function for PrintFreeFieldNumbers.
+// Stores occupied ranges into the ranges parameter, and next level of sub
+// message types into the nested_messages parameter.  The FieldRange is left
+// inclusive, right exclusive. i.e. [a, b).
+//
+// Nested Messages:
+// Note that it only stores the nested message type, iff the nested type is
+// either a direct child of the given descriptor, or the nested type is a
+// decendent of the given descriptor and all the nodes between the
+// nested type and the given descriptor are group types. e.g.
+//
+// message Foo {
+//   message Bar {
+//     message NestedBar {}
+//   }
+//   group Baz = 1 {
+//     group NestedBazGroup = 2 {
+//       message Quz {
+//         message NestedQuz {}
+//       }
+//     }
+//     message NestedBaz {}
+//   }
+// }
+//
+// In this case, Bar, Quz and NestedBaz will be added into the nested types.
+// Since free field numbers of group types will not be printed, this makes sure
+// the nested message types in groups will not be dropped. The nested_messages
+// parameter will contain the direct children (when groups are ignored in the
+// tree) of the given descriptor for the caller to traverse. The declaration
+// order of the nested messages is also preserved.
+typedef pair<int, int> FieldRange;
+void GatherOccupiedFieldRanges(const Descriptor* descriptor,
+                               set<FieldRange>* ranges,
+                               vector<const Descriptor*>* nested_messages) {
+  set<const Descriptor*> groups;
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* fd = descriptor->field(i);
+    ranges->insert(FieldRange(fd->number(), fd->number() + 1));
+    if (fd->type() == FieldDescriptor::TYPE_GROUP) {
+      groups.insert(fd->message_type());
+    }
+  }
+  for (int i = 0; i < descriptor->extension_range_count(); ++i) {
+    ranges->insert(FieldRange(descriptor->extension_range(i)->start,
+                              descriptor->extension_range(i)->end));
+  }
+  for (int i = 0; i < descriptor->reserved_range_count(); ++i) {
+    ranges->insert(FieldRange(descriptor->reserved_range(i)->start,
+                              descriptor->reserved_range(i)->end));
+  }
+  // Handle the nested messages/groups in declaration order to make it
+  // post-order strict.
+  for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+    const Descriptor* nested_desc = descriptor->nested_type(i);
+    if (groups.find(nested_desc) != groups.end()) {
+      GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages);
+    } else {
+      nested_messages->push_back(nested_desc);
+    }
+  }
+}
+
+// Utility function for PrintFreeFieldNumbers.
+// Actually prints the formatted free field numbers for given message name and
+// occupied ranges.
+void FormatFreeFieldNumbers(const string& name,
+                            const set<FieldRange>& ranges) {
+  string output;
+  StringAppendF(&output, "%-35s free:", name.c_str());
+  int next_free_number = 1;
+  for (set<FieldRange>::const_iterator i = ranges.begin();
+       i != ranges.end(); ++i) {
+    // This happens when groups re-use parent field numbers, in which
+    // case we skip the FieldRange entirely.
+    if (next_free_number >= i->second) continue;
+
+    if (next_free_number < i->first) {
+      if (next_free_number + 1 == i->first) {
+        // Singleton
+        StringAppendF(&output, " %d", next_free_number);
+      } else {
+        // Range
+        StringAppendF(&output, " %d-%d", next_free_number, i->first - 1);
+      }
+    }
+    next_free_number = i->second;
+  }
+  if (next_free_number <= FieldDescriptor::kMaxNumber) {
+    StringAppendF(&output, " %d-INF", next_free_number);
+  }
+  std::cout << output << std::endl;
+}
+
+}  // namespace
+
+void CommandLineInterface::PrintFreeFieldNumbers(
+    const Descriptor* descriptor) {
+  set<FieldRange> ranges;
+  vector<const Descriptor*> nested_messages;
+  GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
+
+  for (int i = 0; i < nested_messages.size(); ++i) {
+    PrintFreeFieldNumbers(nested_messages[i]);
+  }
+  FormatFreeFieldNumbers(descriptor->full_name(), ranges);
+}
+
+
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.h
new file mode 100644
index 0000000..d137766
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface.h
@@ -0,0 +1,394 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Implements the Protocol Compiler front-end such that it may be reused by
+// custom compilers written to support other languages.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
+#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <utility>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;            // descriptor.h
+class DescriptorPool;        // descriptor.h
+class FileDescriptor;        // descriptor.h
+class FileDescriptorProto;   // descriptor.pb.h
+template<typename T> class RepeatedPtrField;  // repeated_field.h
+
+namespace compiler {
+
+class CodeGenerator;        // code_generator.h
+class GeneratorContext;      // code_generator.h
+class DiskSourceTree;       // importer.h
+
+// This class implements the command-line interface to the protocol compiler.
+// It is designed to make it very easy to create a custom protocol compiler
+// supporting the languages of your choice.  For example, if you wanted to
+// create a custom protocol compiler binary which includes both the regular
+// C++ support plus support for your own custom output "Foo", you would
+// write a class "FooGenerator" which implements the CodeGenerator interface,
+// then write a main() procedure like this:
+//
+//   int main(int argc, char* argv[]) {
+//     google::protobuf::compiler::CommandLineInterface cli;
+//
+//     // Support generation of C++ source and headers.
+//     google::protobuf::compiler::cpp::CppGenerator cpp_generator;
+//     cli.RegisterGenerator("--cpp_out", &cpp_generator,
+//       "Generate C++ source and header.");
+//
+//     // Support generation of Foo code.
+//     FooGenerator foo_generator;
+//     cli.RegisterGenerator("--foo_out", &foo_generator,
+//       "Generate Foo file.");
+//
+//     return cli.Run(argc, argv);
+//   }
+//
+// The compiler is invoked with syntax like:
+//   protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
+//
+// For a full description of the command-line syntax, invoke it with --help.
+class LIBPROTOC_EXPORT CommandLineInterface {
+ public:
+  CommandLineInterface();
+  ~CommandLineInterface();
+
+  // Register a code generator for a language.
+  //
+  // Parameters:
+  // * flag_name: The command-line flag used to specify an output file of
+  //   this type.  The name must start with a '-'.  If the name is longer
+  //   than one letter, it must start with two '-'s.
+  // * generator: The CodeGenerator which will be called to generate files
+  //   of this type.
+  // * help_text: Text describing this flag in the --help output.
+  //
+  // Some generators accept extra parameters.  You can specify this parameter
+  // on the command-line by placing it before the output directory, separated
+  // by a colon:
+  //   protoc --foo_out=enable_bar:outdir
+  // The text before the colon is passed to CodeGenerator::Generate() as the
+  // "parameter".
+  void RegisterGenerator(const string& flag_name,
+                         CodeGenerator* generator,
+                         const string& help_text);
+
+  // Register a code generator for a language.
+  // Besides flag_name you can specify another option_flag_name that could be
+  // used to pass extra parameters to the registered code generator.
+  // Suppose you have registered a generator by calling:
+  //   command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
+  // Then you could invoke the compiler with a command like:
+  //   protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
+  // This will pass "enable_bar,enable_baz" as the parameter to the generator.
+  void RegisterGenerator(const string& flag_name,
+                         const string& option_flag_name,
+                         CodeGenerator* generator,
+                         const string& help_text);
+
+  // Enables "plugins".  In this mode, if a command-line flag ends with "_out"
+  // but does not match any registered generator, the compiler will attempt to
+  // find a "plugin" to implement the generator.  Plugins are just executables.
+  // They should live somewhere in the PATH.
+  //
+  // The compiler determines the executable name to search for by concatenating
+  // exe_name_prefix with the unrecognized flag name, removing "_out".  So, for
+  // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
+  // the compiler will try to run the program "protoc-foo".
+  //
+  // The plugin program should implement the following usage:
+  //   plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
+  // --out indicates the output directory (as passed to the --foo_out
+  // parameter); if omitted, the current directory should be used.  --parameter
+  // gives the generator parameter, if any was provided.  The PROTO_FILES list
+  // the .proto files which were given on the compiler command-line; these are
+  // the files for which the plugin is expected to generate output code.
+  // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
+  // descriptor.proto).  This is piped to the plugin's stdin.  The set will
+  // include descriptors for all the files listed in PROTO_FILES as well as
+  // all files that they import.  The plugin MUST NOT attempt to read the
+  // PROTO_FILES directly -- it must use the FileDescriptorSet.
+  //
+  // The plugin should generate whatever files are necessary, as code generators
+  // normally do.  It should write the names of all files it generates to
+  // stdout.  The names should be relative to the output directory, NOT absolute
+  // names or relative to the current directory.  If any errors occur, error
+  // messages should be written to stderr.  If an error is fatal, the plugin
+  // should exit with a non-zero exit code.
+  void AllowPlugins(const string& exe_name_prefix);
+
+  // Run the Protocol Compiler with the given command-line parameters.
+  // Returns the error code which should be returned by main().
+  //
+  // It may not be safe to call Run() in a multi-threaded environment because
+  // it calls strerror().  I'm not sure why you'd want to do this anyway.
+  int Run(int argc, const char* const argv[]);
+
+  // Call SetInputsAreCwdRelative(true) if the input files given on the command
+  // line should be interpreted relative to the proto import path specified
+  // using --proto_path or -I flags.  Otherwise, input file names will be
+  // interpreted relative to the current working directory (or as absolute
+  // paths if they start with '/'), though they must still reside inside
+  // a directory given by --proto_path or the compiler will fail.  The latter
+  // mode is generally more intuitive and easier to use, especially e.g. when
+  // defining implicit rules in Makefiles.
+  void SetInputsAreProtoPathRelative(bool enable) {
+    inputs_are_proto_path_relative_ = enable;
+  }
+
+  // Provides some text which will be printed when the --version flag is
+  // used.  The version of libprotoc will also be printed on the next line
+  // after this text.
+  void SetVersionInfo(const string& text) {
+    version_info_ = text;
+  }
+
+
+ private:
+  // -----------------------------------------------------------------
+
+  class ErrorPrinter;
+  class GeneratorContextImpl;
+  class MemoryOutputStream;
+  typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
+
+  // Clear state from previous Run().
+  void Clear();
+
+  // Remaps each file in input_files_ so that it is relative to one of the
+  // directories in proto_path_.  Returns false if an error occurred.  This
+  // is only used if inputs_are_proto_path_relative_ is false.
+  bool MakeInputsBeProtoPathRelative(
+    DiskSourceTree* source_tree);
+
+  // Return status for ParseArguments() and InterpretArgument().
+  enum ParseArgumentStatus {
+    PARSE_ARGUMENT_DONE_AND_CONTINUE,
+    PARSE_ARGUMENT_DONE_AND_EXIT,
+    PARSE_ARGUMENT_FAIL
+  };
+
+  // Parse all command-line arguments.
+  ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
+
+
+  // Parses a command-line argument into a name/value pair.  Returns
+  // true if the next argument in the argv should be used as the value,
+  // false otherwise.
+  //
+  // Examples:
+  //   "-Isrc/protos" ->
+  //     name = "-I", value = "src/protos"
+  //   "--cpp_out=src/foo.pb2.cc" ->
+  //     name = "--cpp_out", value = "src/foo.pb2.cc"
+  //   "foo.proto" ->
+  //     name = "", value = "foo.proto"
+  bool ParseArgument(const char* arg, string* name, string* value);
+
+  // Interprets arguments parsed with ParseArgument.
+  ParseArgumentStatus InterpretArgument(const string& name,
+                                        const string& value);
+
+  // Print the --help text to stderr.
+  void PrintHelpText();
+
+  // Generate the given output file from the given input.
+  struct OutputDirective;  // see below
+  bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
+                      const OutputDirective& output_directive,
+                      GeneratorContext* generator_context);
+  bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
+                            const string& plugin_name,
+                            const string& parameter,
+                            GeneratorContext* generator_context,
+                            string* error);
+
+  // Implements --encode and --decode.
+  bool EncodeOrDecode(const DescriptorPool* pool);
+
+  // Implements the --descriptor_set_out option.
+  bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+
+  // Implements the --dependency_out option
+  bool GenerateDependencyManifestFile(
+      const vector<const FileDescriptor*>& parsed_files,
+      const GeneratorContextMap& output_directories,
+      DiskSourceTree* source_tree);
+
+  // Get all transitive dependencies of the given file (including the file
+  // itself), adding them to the given list of FileDescriptorProtos.  The
+  // protos will be ordered such that every file is listed before any file that
+  // depends on it, so that you can call DescriptorPool::BuildFile() on them
+  // in order.  Any files in *already_seen will not be added, and each file
+  // added will be inserted into *already_seen.  If include_source_code_info is
+  // true then include the source code information in the FileDescriptorProtos.
+  // If include_json_name is true, populate the json_name field of
+  // FieldDescriptorProto for all fields.
+  static void GetTransitiveDependencies(
+      const FileDescriptor* file,
+      bool include_json_name,
+      bool include_source_code_info,
+      set<const FileDescriptor*>* already_seen,
+      RepeatedPtrField<FileDescriptorProto>* output);
+
+  // Implements the --print_free_field_numbers. This function prints free field
+  // numbers into stdout for the message and it's nested message types in
+  // post-order, i.e. nested types first. Printed range are left-right
+  // inclusive, i.e. [a, b].
+  //
+  // Groups:
+  // For historical reasons, groups are considered to share the same
+  // field number space with the parent message, thus it will not print free
+  // field numbers for groups. The field numbers used in the groups are
+  // excluded in the free field numbers of the parent message.
+  //
+  // Extension Ranges:
+  // Extension ranges are considered ocuppied field numbers and they will not be
+  // listed as free numbers in the output.
+  void PrintFreeFieldNumbers(const Descriptor* descriptor);
+
+  // -----------------------------------------------------------------
+
+  // The name of the executable as invoked (i.e. argv[0]).
+  string executable_name_;
+
+  // Version info set with SetVersionInfo().
+  string version_info_;
+
+  // Registered generators.
+  struct GeneratorInfo {
+    string flag_name;
+    string option_flag_name;
+    CodeGenerator* generator;
+    string help_text;
+  };
+  typedef map<string, GeneratorInfo> GeneratorMap;
+  GeneratorMap generators_by_flag_name_;
+  GeneratorMap generators_by_option_name_;
+  // A map from generator names to the parameters specified using the option
+  // flag. For example, if the user invokes the compiler with:
+  //   protoc --foo_out=outputdir --foo_opt=enable_bar ...
+  // Then there will be an entry ("--foo_out", "enable_bar") in this map.
+  map<string, string> generator_parameters_;
+
+  // See AllowPlugins().  If this is empty, plugins aren't allowed.
+  string plugin_prefix_;
+
+  // Maps specific plugin names to files.  When executing a plugin, this map
+  // is searched first to find the plugin executable.  If not found here, the
+  // PATH (or other OS-specific search strategy) is searched.
+  map<string, string> plugins_;
+
+  // Stuff parsed from command line.
+  enum Mode {
+    MODE_COMPILE,  // Normal mode:  parse .proto files and compile them.
+    MODE_ENCODE,   // --encode:  read text from stdin, write binary to stdout.
+    MODE_DECODE,   // --decode:  read binary from stdin, write text to stdout.
+    MODE_PRINT,    // Print mode: print info of the given .proto files and exit.
+  };
+
+  Mode mode_;
+
+  enum PrintMode {
+    PRINT_NONE,               // Not in MODE_PRINT
+    PRINT_FREE_FIELDS,        // --print_free_fields
+  };
+
+  PrintMode print_mode_;
+
+  enum ErrorFormat {
+    ERROR_FORMAT_GCC,   // GCC error output format (default).
+    ERROR_FORMAT_MSVS   // Visual Studio output (--error_format=msvs).
+  };
+
+  ErrorFormat error_format_;
+
+  vector<pair<string, string> > proto_path_;  // Search path for proto files.
+  vector<string> input_files_;                // Names of the input proto files.
+
+  // output_directives_ lists all the files we are supposed to output and what
+  // generator to use for each.
+  struct OutputDirective {
+    string name;                // E.g. "--foo_out"
+    CodeGenerator* generator;   // NULL for plugins
+    string parameter;
+    string output_location;
+  };
+  vector<OutputDirective> output_directives_;
+
+  // When using --encode or --decode, this names the type we are encoding or
+  // decoding.  (Empty string indicates --decode_raw.)
+  string codec_type_;
+
+  // If --descriptor_set_out was given, this is the filename to which the
+  // FileDescriptorSet should be written.  Otherwise, empty.
+  string descriptor_set_name_;
+
+  // If --dependency_out was given, this is the path to the file where the
+  // dependency file will be written. Otherwise, empty.
+  string dependency_out_name_;
+
+  // True if --include_imports was given, meaning that we should
+  // write all transitive dependencies to the DescriptorSet.  Otherwise, only
+  // the .proto files listed on the command-line are added.
+  bool imports_in_descriptor_set_;
+
+  // True if --include_source_info was given, meaning that we should not strip
+  // SourceCodeInfo from the DescriptorSet.
+  bool source_info_in_descriptor_set_;
+
+  // Was the --disallow_services flag used?
+  bool disallow_services_;
+
+  // See SetInputsAreProtoPathRelative().
+  bool inputs_are_proto_path_relative_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface_unittest.cc
new file mode 100644
index 0000000..9b504d2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -0,0 +1,1834 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
+#include <google/protobuf/compiler/subprocess.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
+// which case tcmalloc will print warnings that fail the plugin tests.
+#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
+#if defined(_WIN32)
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef F_OK
+#define F_OK 00  // not defined by MSVC for whatever reason
+#endif
+#endif
+
+namespace {
+
+bool FileExists(const string& path) {
+  return File::Exists(path);
+}
+
+class CommandLineInterfaceTest : public testing::Test {
+ protected:
+  virtual void SetUp();
+  virtual void TearDown();
+
+  // Runs the CommandLineInterface with the given command line.  The
+  // command is automatically split on spaces, and the string "$tmpdir"
+  // is replaced with TestTempDir().
+  void Run(const string& command);
+
+  // -----------------------------------------------------------------
+  // Methods to set up the test (called before Run()).
+
+  class NullCodeGenerator;
+
+  // Normally plugins are allowed for all tests.  Call this to explicitly
+  // disable them.
+  void DisallowPlugins() { disallow_plugins_ = true; }
+
+  // Create a temp file within temp_directory_ with the given name.
+  // The containing directory is also created if necessary.
+  void CreateTempFile(const string& name, const string& contents);
+
+  // Create a subdirectory within temp_directory_.
+  void CreateTempDir(const string& name);
+
+#ifdef PROTOBUF_OPENSOURCE
+  // Change working directory to temp directory.
+  void SwitchToTempDirectory() {
+    File::ChangeWorkingDirectory(temp_directory_);
+  }
+#else  // !PROTOBUF_OPENSOURCE
+  // TODO(teboring): Figure out how to change and get working directory in
+  // google3.
+#endif  // !PROTOBUF_OPENSOURCE
+
+  void SetInputsAreProtoPathRelative(bool enable) {
+    cli_.SetInputsAreProtoPathRelative(enable);
+  }
+
+  // -----------------------------------------------------------------
+  // Methods to check the test results (called after Run()).
+
+  // Checks that no text was written to stderr during Run(), and Run()
+  // returned 0.
+  void ExpectNoErrors();
+
+  // Checks that Run() returned non-zero and the stderr output is exactly
+  // the text given.  expected_test may contain references to "$tmpdir",
+  // which will be replaced by the temporary directory path.
+  void ExpectErrorText(const string& expected_text);
+
+  // Checks that Run() returned non-zero and the stderr contains the given
+  // substring.
+  void ExpectErrorSubstring(const string& expected_substring);
+
+  // Like ExpectErrorSubstring, but checks that Run() returned zero.
+  void ExpectErrorSubstringWithZeroReturnCode(
+      const string& expected_substring);
+
+  // Checks that the captured stdout is the same as the expected_text.
+  void ExpectCapturedStdout(const string& expected_text);
+
+  // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
+  // does not fail otherwise.
+  bool HasAlternateErrorSubstring(const string& expected_substring);
+
+  // Checks that MockCodeGenerator::Generate() was called in the given
+  // context (or the generator in test_plugin.cc, which produces the same
+  // output).  That is, this tests if the generator with the given name
+  // was called with the given parameter and proto file and produced the
+  // given output file.  This is checked by reading the output file and
+  // checking that it contains the content that MockCodeGenerator would
+  // generate given these inputs.  message_name is the name of the first
+  // message that appeared in the proto file; this is just to make extra
+  // sure that the correct file was parsed.
+  void ExpectGenerated(const string& generator_name,
+                       const string& parameter,
+                       const string& proto_name,
+                       const string& message_name);
+  void ExpectGenerated(const string& generator_name,
+                       const string& parameter,
+                       const string& proto_name,
+                       const string& message_name,
+                       const string& output_directory);
+  void ExpectGeneratedWithMultipleInputs(const string& generator_name,
+                                         const string& all_proto_names,
+                                         const string& proto_name,
+                                         const string& message_name);
+  void ExpectGeneratedWithInsertions(const string& generator_name,
+                                     const string& parameter,
+                                     const string& insertions,
+                                     const string& proto_name,
+                                     const string& message_name);
+
+  void ExpectNullCodeGeneratorCalled(const string& parameter);
+
+  void ReadDescriptorSet(const string& filename,
+                         FileDescriptorSet* descriptor_set);
+
+  void ExpectFileContent(const string& filename,
+                         const string& content);
+
+ private:
+  // The object we are testing.
+  CommandLineInterface cli_;
+
+  // Was DisallowPlugins() called?
+  bool disallow_plugins_;
+
+  // We create a directory within TestTempDir() in order to add extra
+  // protection against accidentally deleting user files (since we recursively
+  // delete this directory during the test).  This is the full path of that
+  // directory.
+  string temp_directory_;
+
+  // The result of Run().
+  int return_code_;
+
+  // The captured stderr output.
+  string error_text_;
+
+  // The captured stdout.
+  string captured_stdout_;
+
+  // Pointers which need to be deleted later.
+  vector<CodeGenerator*> mock_generators_to_delete_;
+
+  NullCodeGenerator* null_generator_;
+};
+
+class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
+ public:
+  NullCodeGenerator() : called_(false) {}
+  ~NullCodeGenerator() {}
+
+  mutable bool called_;
+  mutable string parameter_;
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* context,
+                string* error) const {
+    called_ = true;
+    parameter_ = parameter;
+    return true;
+  }
+};
+
+// ===================================================================
+
+void CommandLineInterfaceTest::SetUp() {
+  // Most of these tests were written before this option was added, so we
+  // run with the option on (which used to be the only way) except in certain
+  // tests where we turn it off.
+  cli_.SetInputsAreProtoPathRelative(true);
+
+  temp_directory_ = TestTempDir() + "/proto2_cli_test_temp";
+
+  // If the temp directory already exists, it must be left over from a
+  // previous run.  Delete it.
+  if (FileExists(temp_directory_)) {
+    File::DeleteRecursively(temp_directory_, NULL, NULL);
+  }
+
+  // Create the temp directory.
+  GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777));
+
+  // Register generators.
+  CodeGenerator* generator = new MockCodeGenerator("test_generator");
+  mock_generators_to_delete_.push_back(generator);
+  cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output.");
+  cli_.RegisterGenerator("-t", generator, "Test output.");
+
+  generator = new MockCodeGenerator("alt_generator");
+  mock_generators_to_delete_.push_back(generator);
+  cli_.RegisterGenerator("--alt_out", generator, "Alt output.");
+
+  generator = null_generator_ = new NullCodeGenerator();
+  mock_generators_to_delete_.push_back(generator);
+  cli_.RegisterGenerator("--null_out", generator, "Null output.");
+
+  disallow_plugins_ = false;
+}
+
+void CommandLineInterfaceTest::TearDown() {
+  // Delete the temp directory.
+  if (FileExists(temp_directory_)) {
+    File::DeleteRecursively(temp_directory_, NULL, NULL);
+  }
+
+  // Delete all the MockCodeGenerators.
+  for (int i = 0; i < mock_generators_to_delete_.size(); i++) {
+    delete mock_generators_to_delete_[i];
+  }
+  mock_generators_to_delete_.clear();
+}
+
+void CommandLineInterfaceTest::Run(const string& command) {
+  vector<string> args = Split(command, " ", true);
+
+  if (!disallow_plugins_) {
+    cli_.AllowPlugins("prefix-");
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
+    string plugin_path;
+#ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH
+    plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH;
+#else
+    const char* possible_paths[] = {
+      // When building with shared libraries, libtool hides the real executable
+      // in .libs and puts a fake wrapper in the current directory.
+      // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program
+      // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another
+      // program wrapped in this way (e.g. test_plugin.exe), the latter fails
+      // with error code 127 and no explanation message.  Presumably the problem
+      // is that the wrapper for protobuf-tests.exe set some environment
+      // variables that confuse the wrapper for test_plugin.exe.  Luckily, it
+      // turns out that if we simply invoke the wrapped test_plugin.exe
+      // directly, it works -- I guess the environment variables set by the
+      // protobuf-tests.exe wrapper happen to be correct for it too.  So we do
+      // that.
+      ".libs/test_plugin.exe",  // Win32 w/autotool (Cygwin / MinGW)
+      "test_plugin.exe",        // Other Win32 (MSVC)
+      "test_plugin",            // Unix
+    };
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) {
+      if (access(possible_paths[i], F_OK) == 0) {
+        plugin_path = possible_paths[i];
+        break;
+      }
+    }
+#endif
+
+    if (plugin_path.empty()) {
+#else
+    string plugin_path = "third_party/protobuf/test_plugin";
+
+    if (access(plugin_path.c_str(), F_OK) != 0) {
+#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
+      GOOGLE_LOG(ERROR)
+          << "Plugin executable not found.  Plugin tests are likely to fail.";
+    } else {
+      args.push_back("--plugin=prefix-gen-plug=" + plugin_path);
+    }
+  }
+
+  google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
+
+  for (int i = 0; i < args.size(); i++) {
+    args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
+    argv[i] = args[i].c_str();
+  }
+
+  // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and
+  // stdout at the same time. Need to figure out why and add this capture back
+  // for Cygwin.
+#if !defined(__CYGWIN__)
+  CaptureTestStdout();
+#endif
+  CaptureTestStderr();
+
+  return_code_ = cli_.Run(args.size(), argv.get());
+
+  error_text_ = GetCapturedTestStderr();
+#if !defined(__CYGWIN__)
+  captured_stdout_ = GetCapturedTestStdout();
+#endif
+}
+
+// -------------------------------------------------------------------
+
+void CommandLineInterfaceTest::CreateTempFile(
+    const string& name,
+    const string& contents) {
+  // Create parent directory, if necessary.
+  string::size_type slash_pos = name.find_last_of('/');
+  if (slash_pos != string::npos) {
+    string dir = name.substr(0, slash_pos);
+    if (!FileExists(temp_directory_ + "/" + dir)) {
+      GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir,
+                                          0777));
+    }
+  }
+
+  // Write file.
+  string full_name = temp_directory_ + "/" + name;
+  GOOGLE_CHECK_OK(File::SetContents(
+      full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
+      true));
+}
+
+void CommandLineInterfaceTest::CreateTempDir(const string& name) {
+  GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name,
+                                      0777));
+}
+
+// -------------------------------------------------------------------
+
+void CommandLineInterfaceTest::ExpectNoErrors() {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_EQ("", error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectErrorText(const string& expected_text) {
+  EXPECT_NE(0, return_code_);
+  EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true),
+            error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectErrorSubstring(
+    const string& expected_substring) {
+  EXPECT_NE(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode(
+    const string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
+bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
+    const string& expected_substring) {
+  EXPECT_NE(0, return_code_);
+  return error_text_.find(expected_substring) != string::npos;
+}
+
+void CommandLineInterfaceTest::ExpectGenerated(
+    const string& generator_name,
+    const string& parameter,
+    const string& proto_name,
+    const string& message_name) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, parameter, "", proto_name, message_name, proto_name,
+      temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGenerated(
+    const string& generator_name,
+    const string& parameter,
+    const string& proto_name,
+    const string& message_name,
+    const string& output_directory) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, parameter, "", proto_name, message_name, proto_name,
+      temp_directory_ + "/" + output_directory);
+}
+
+void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
+    const string& generator_name,
+    const string& all_proto_names,
+    const string& proto_name,
+    const string& message_name) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, "", "", proto_name, message_name,
+      all_proto_names,
+      temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
+    const string& generator_name,
+    const string& parameter,
+    const string& insertions,
+    const string& proto_name,
+    const string& message_name) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, parameter, insertions, proto_name, message_name,
+      proto_name, temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
+    const string& parameter) {
+  EXPECT_TRUE(null_generator_->called_);
+  EXPECT_EQ(parameter, null_generator_->parameter_);
+}
+
+void CommandLineInterfaceTest::ReadDescriptorSet(
+    const string& filename, FileDescriptorSet* descriptor_set) {
+  string path = temp_directory_ + "/" + filename;
+  string file_contents;
+  GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
+
+  if (!descriptor_set->ParseFromString(file_contents)) {
+    FAIL() << "Could not parse file contents: " << path;
+  }
+}
+
+void CommandLineInterfaceTest::ExpectCapturedStdout(
+    const string& expected_text) {
+  EXPECT_EQ(expected_text, captured_stdout_);
+}
+
+
+void CommandLineInterfaceTest::ExpectFileContent(
+    const string& filename, const string& content) {
+  string path = temp_directory_ + "/" + filename;
+  string file_contents;
+  GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
+
+  EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true),
+            file_contents);
+}
+
+// ===================================================================
+
+TEST_F(CommandLineInterfaceTest, BasicOutput) {
+  // Test that the common case works.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, BasicPlugin) {
+  // Test that basic plugins work.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
+  // Invoke a generator and a plugin at the same time.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputs) {
+  // Test parsing multiple input files.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto bar.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
+  // Test parsing multiple input files with an import of a separate file.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"baz.proto\";\n"
+    "message Bar {\n"
+    "  optional Baz a = 1;\n"
+    "}\n");
+  CreateTempFile("baz.proto",
+    "syntax = \"proto2\";\n"
+    "message Baz {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto bar.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, CreateDirectory) {
+  // Test that when we output to a sub-directory, it is created.
+
+  CreateTempFile("bar/baz/foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempDir("out");
+  CreateTempDir("plugout");
+
+  Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
+      "--proto_path=$tmpdir bar/baz/foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out");
+  ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
+  // Test that generator parameters are correctly parsed from the command line.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=TestParameter:$tmpdir "
+      "--plug_out=TestPluginParameter:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo");
+  ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
+  // Test that generator parameters specified with the option flag are
+  // correctly passed to the code generator.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  // Create the "a" and "b" sub-directories.
+  CreateTempDir("a");
+  CreateTempDir("b");
+
+  Run("protocol_compiler "
+      "--test_opt=foo1 "
+      "--test_out=bar:$tmpdir/a "
+      "--test_opt=foo2 "
+      "--test_out=baz:$tmpdir/b "
+      "--test_opt=foo3 "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated(
+      "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+  ExpectGenerated(
+      "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, Insert) {
+  // Test running a generator that inserts code into another's output.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler "
+      "--test_out=TestParameter:$tmpdir "
+      "--plug_out=TestPluginParameter:$tmpdir "
+      "--test_out=insert=test_generator,test_plugin:$tmpdir "
+      "--plug_out=insert=test_generator,test_plugin:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithInsertions(
+      "test_generator", "TestParameter", "test_generator,test_plugin",
+      "foo.proto", "Foo");
+  ExpectGeneratedWithInsertions(
+      "test_plugin", "TestPluginParameter", "test_generator,test_plugin",
+      "foo.proto", "Foo");
+}
+
+#if defined(_WIN32)
+
+TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
+  // Test that the output path can be a Windows-style path.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --null_out=C:\\ "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectNullCodeGeneratorCalled("");
+}
+
+TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
+  // Test that we can have a windows-style output path and a parameter.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --null_out=bar:C:\\ "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectNullCodeGeneratorCalled("bar");
+}
+
+TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
+  // Test that the directories can end in backslashes.  Some users claim this
+  // doesn't work on their system.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir\\ "
+      "--proto_path=$tmpdir\\ foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+#endif  // defined(_WIN32) || defined(__CYGWIN__)
+
+TEST_F(CommandLineInterfaceTest, PathLookup) {
+  // Test that specifying multiple directories in the proto search path works.
+
+  CreateTempFile("b/bar.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+  CreateTempFile("a/foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n"
+    "message Foo {\n"
+    "  optional Bar a = 1;\n"
+    "}\n");
+  CreateTempFile("b/foo.proto", "this should not be parsed\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
+  // Same as PathLookup, but we provide the proto_path in a single flag.
+
+  CreateTempFile("b/bar.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+  CreateTempFile("a/foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n"
+    "message Foo {\n"
+    "  optional Bar a = 1;\n"
+    "}\n");
+  CreateTempFile("b/foo.proto", "this should not be parsed\n");
+
+#undef PATH_SEPARATOR
+#if defined(_WIN32)
+#define PATH_SEPARATOR ";"
+#else
+#define PATH_SEPARATOR ":"
+#endif
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto");
+
+#undef PATH_SEPARATOR
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, NonRootMapping) {
+  // Test setting up a search path mapping a directory to a non-root location.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=bar=$tmpdir bar/foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
+  // Test that we can have multiple generators and use both in one invocation,
+  // each with a different output directory.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  // Create the "a" and "b" sub-directories.
+  CreateTempDir("a");
+  CreateTempDir("b");
+
+  Run("protocol_compiler "
+      "--test_out=$tmpdir/a "
+      "--alt_out=$tmpdir/b "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a");
+  ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
+  // Test that --disallow_services doesn't cause a problem when there are no
+  // services.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --disallow_services --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
+  // Test that --disallow_services produces an error when there are services.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n"
+    "service Bar {}\n");
+
+  Run("protocol_compiler --disallow_services --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("foo.proto: This file contains services");
+}
+
+TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
+  // Test that services work fine as long as --disallow_services is not used.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n"
+    "service Bar {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
+  // Test that we can accept working-directory-relative input files.
+
+  SetInputsAreProtoPathRelative(false);
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir $tmpdir/foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  EXPECT_EQ(1, descriptor_set.file_size());
+  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+  // Descriptor set should not have source code info.
+  EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+  // Descriptor set should have json_name.
+  EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name());
+  EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name());
+  EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+  CreateTempFile("baz.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Baz {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  EXPECT_EQ(3, descriptor_set.file_size());
+  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+  EXPECT_EQ("foo.proto", descriptor_set.file(1).name());
+  EXPECT_EQ("baz.proto", descriptor_set.file(2).name());
+  // Descriptor set should not have source code info.
+  EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+  // Descriptor set should have json_name.
+  EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name());
+  EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name());
+  EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--include_source_info --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  EXPECT_EQ(1, descriptor_set.file_size());
+  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+  // Source code info included.
+  EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--include_imports --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  EXPECT_EQ(2, descriptor_set.file_size());
+  if (descriptor_set.file(0).name() == "bar.proto") {
+    std::swap(descriptor_set.mutable_file()->mutable_data()[0],
+              descriptor_set.mutable_file()->mutable_data()[1]);
+  }
+  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+  EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+  // Descriptor set should not have source code info.
+  EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+  EXPECT_FALSE(descriptor_set.file(1).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  EXPECT_EQ(2, descriptor_set.file_size());
+  if (descriptor_set.file(0).name() == "bar.proto") {
+    std::swap(descriptor_set.mutable_file()->mutable_data()[0],
+              descriptor_set.mutable_file()->mutable_data()[1]);
+  }
+  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+  EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+  // Source code info included.
+  EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+  EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
+}
+
+#ifdef _WIN32
+// TODO(teboring): Figure out how to write test on windows.
+#else
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+      "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto");
+
+  ExpectErrorText(
+      "Can only process one input file when using --dependency_out=FILE.\n");
+}
+
+#ifdef PROTOBUF_OPENSOURCE
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  string current_working_directory = getcwd(NULL, 0);
+  SwitchToTempDirectory();
+
+  Run("protocol_compiler --dependency_out=manifest --test_out=. "
+      "bar.proto");
+
+  ExpectNoErrors();
+
+  ExpectFileContent("manifest",
+                    "bar.proto.MockCodeGenerator.test_generator: "
+                    "foo.proto\\\n bar.proto");
+
+  File::ChangeWorkingDirectory(current_working_directory);
+}
+#else  // !PROTOBUF_OPENSOURCE
+// TODO(teboring): Figure out how to change and get working directory in
+// google3.
+#endif  // !PROTOBUF_OPENSOURCE
+
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+      "--test_out=$tmpdir --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  ExpectFileContent("manifest",
+                    "$tmpdir/bar.proto.MockCodeGenerator.test_generator: "
+                    "$tmpdir/foo.proto\\\n $tmpdir/bar.proto");
+}
+#endif  // !_WIN32
+
+
+// -------------------------------------------------------------------
+
+TEST_F(CommandLineInterfaceTest, ParseErrors) {
+  // Test that parse errors are reported.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "badsyntax\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText(
+    "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
+  // Test that parse errors are reported from multiple files.
+
+  // We set up files such that foo.proto actually depends on bar.proto in
+  // two ways:  Directly and through baz.proto.  bar.proto's errors should
+  // only be reported once.
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "badsyntax\n");
+  CreateTempFile("baz.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n");
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n"
+    "import \"baz.proto\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText(
+    "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n"
+    "baz.proto: Import \"bar.proto\" was not found or had errors.\n"
+    "foo.proto: Import \"bar.proto\" was not found or had errors.\n"
+    "foo.proto: Import \"baz.proto\" was not found or had errors.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
+  // Test what happens if the input file is not found.
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText(
+    "foo.proto: File not found.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
+  // Test what happens when a working-directory-relative input file is not
+  // found.
+
+  SetInputsAreProtoPathRelative(false);
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir $tmpdir/foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
+  // Test what happens when a working-directory-relative input file is not
+  // mapped to a virtual path.
+
+  SetInputsAreProtoPathRelative(false);
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  // Create a directory called "bar" so that we can point --proto_path at it.
+  CreateTempFile("bar/dummy", "");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.proto: File does not reside within any path "
+      "specified using --proto_path (or -I).  You must specify a "
+      "--proto_path which encompasses this file.  Note that the "
+      "proto_path must be an exact prefix of the .proto file "
+      "names -- protoc is too dumb to figure out when two paths "
+      "(e.g. absolute and relative) are equivalent (it's harder "
+      "than you think).\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
+  // Check what happens if the input file is not found *and* is not mapped
+  // in the proto_path.
+
+  SetInputsAreProtoPathRelative(false);
+
+  // Create a directory called "bar" so that we can point --proto_path at it.
+  CreateTempFile("bar/dummy", "");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
+  // Test what happens when a working-directory-relative input file is shadowed
+  // by another file in the virtual path.
+
+  SetInputsAreProtoPathRelative(false);
+
+  CreateTempFile("foo/foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar/foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar "
+      "$tmpdir/bar/foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path "
+    "by \"$tmpdir/foo/foo.proto\".  Either use the latter "
+    "file as your input or reorder the --proto_path so that the "
+    "former file's location comes first.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
+  // Test what happens if the input file is not found.
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/foo foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo: warning: directory does not exist.\n"
+    "foo.proto: File not found.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingInputError) {
+  // Test that we get an error if no inputs are given.
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir");
+
+  ExpectErrorText("Missing input file.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingOutputError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText("Missing output directives.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputWriteError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  string output_file =
+      MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto");
+
+  // Create a directory blocking our output location.
+  CreateTempDir(output_file);
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  // MockCodeGenerator no longer detects an error because we actually write to
+  // an in-memory location first, then dump to disk at the end.  This is no
+  // big deal.
+  //   ExpectErrorSubstring("MockCodeGenerator detected write error.");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+  if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+    return;
+  }
+#endif
+
+  ExpectErrorSubstring(output_file + ": Is a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  string output_file =
+      MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto");
+
+  // Create a directory blocking our output location.
+  CreateTempDir(output_file);
+
+  Run("protocol_compiler --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+  if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+    return;
+  }
+#endif
+
+  ExpectErrorSubstring(output_file + ": Is a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir/nosuchdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir/nosuchdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir/foo.proto "
+      "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Windows with MSVCRT.dll produces EINVAL instead of ENOTDIR.
+  if (HasAlternateErrorSubstring("foo.proto/: Invalid argument")) {
+    return;
+  }
+#endif
+
+  ExpectErrorSubstring("foo.proto/: Not a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorError) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_Error {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+      "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
+  // Test a generator plugin that returns an error.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_Error {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+      "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
+  // Test a generator plugin that exits with an error code.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_Exit {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit.");
+  ExpectErrorSubstring(
+      "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
+  // Test a generator plugin that crashes.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_Abort {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort.");
+
+#ifdef _WIN32
+  // Windows doesn't have signals.  It looks like abort()ing causes the process
+  // to exit with status code 3, but let's not depend on the exact number here.
+  ExpectErrorSubstring(
+      "--plug_out: prefix-gen-plug: Plugin failed with status code");
+#else
+  // Don't depend on the exact signal number.
+  ExpectErrorSubstring(
+      "--plug_out: prefix-gen-plug: Plugin killed by signal");
+#endif
+}
+
+TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_HasSourceCodeInfo {}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+      "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
+}
+
+TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_HasJsonName {\n"
+    "  optional int32 value = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("Saw json_name: 1");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
+  // Test what happens if the plugin isn't found.
+
+  CreateTempFile("error.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --badplug_out=TestParameter:$tmpdir "
+      "--plugin=prefix-gen-badplug=no_such_file "
+      "--proto_path=$tmpdir error.proto");
+
+#ifdef _WIN32
+  ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " +
+      Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
+#else
+  // Error written to stdout by child process after exec() fails.
+  ExpectErrorSubstring(
+      "no_such_file: program not found or is not executable");
+
+  // Error written by parent process when child fails.
+  ExpectErrorSubstring(
+      "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
+#endif
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
+  // Test what happens if plugins aren't allowed.
+
+  CreateTempFile("error.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  DisallowPlugins();
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--proto_path=$tmpdir error.proto");
+
+  ExpectErrorSubstring("Unknown flag: --plug_out");
+}
+
+TEST_F(CommandLineInterfaceTest, HelpText) {
+  Run("test_exec_name --help");
+
+  ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
+  ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
+  ExpectErrorSubstringWithZeroReturnCode("Test output.");
+  ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
+  ExpectErrorSubstringWithZeroReturnCode("Alt output.");
+}
+
+TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
+  // Test --error_format=gcc (which is the default, but we want to verify
+  // that it can be set explicitly).
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "badsyntax\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir --error_format=gcc foo.proto");
+
+  ExpectErrorText(
+    "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
+  // Test --error_format=msvs
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "badsyntax\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir --error_format=msvs foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement "
+      "(e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
+  // Test --error_format=msvs
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "badsyntax\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir --error_format=invalid foo.proto");
+
+  ExpectErrorText(
+    "Unknown error format: invalid\n");
+}
+
+// -------------------------------------------------------------------
+// Flag parsing tests
+
+TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
+  // Test that a single-character flag works.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler -t$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
+  // Test that separating the flag value with a space works.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out $tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
+  // Test that separating the flag value with a space works for
+  // single-character flags.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler -t $tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingValueError) {
+  // Test that we get an error if a flag is missing its value.
+
+  Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText("Missing value for flag: --test_out\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
+  // Test that we get an error if the last argument is a flag requiring a
+  // value.
+
+  Run("protocol_compiler --test_out");
+
+  ExpectErrorText("Missing value for flag: --test_out\n");
+}
+
+TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) {
+  CreateTempFile(
+      "foo.proto",
+      "syntax = \"proto2\";\n"
+      "package foo;\n"
+      "message Foo {\n"
+      "  optional int32 a = 2;\n"
+      "  optional string b = 4;\n"
+      "  optional string c = 5;\n"
+      "  optional int64 d = 8;\n"
+      "  optional double e = 10;\n"
+      "}\n");
+  CreateTempFile(
+      "bar.proto",
+      "syntax = \"proto2\";\n"
+      "message Bar {\n"
+      "  optional int32 a = 2;\n"
+      "  extensions 4 to 5;\n"
+      "  optional int64 d = 8;\n"
+      "  extensions 10;\n"
+      "}\n");
+  CreateTempFile(
+      "baz.proto",
+      "syntax = \"proto2\";\n"
+      "message Baz {\n"
+      "  optional int32 a = 2;\n"
+      "  optional int64 d = 8;\n"
+      "  extensions 15 to max;\n"  // unordered.
+      "  extensions 13;\n"
+      "  extensions 10 to 12;\n"
+      "  extensions 5;\n"
+      "  extensions 4;\n"
+      "}\n");
+  CreateTempFile(
+      "quz.proto",
+      "syntax = \"proto2\";\n"
+      "message Quz {\n"
+      "  message Foo {}\n"  // nested message
+      "  optional int32 a = 2;\n"
+      "  optional group C = 4 {\n"
+      "    optional int32 d = 5;\n"
+      "  }\n"
+      "  extensions 8 to 10;\n"
+      "  optional group E = 11 {\n"
+      "    optional int32 f = 9;\n"    // explicitly reuse extension range 8-10
+      "    optional group G = 15 {\n"  // nested group
+      "      message Foo {}\n"         // nested message inside nested group
+      "    }\n"
+      "  }\n"
+      "}\n");
+
+  Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir "
+      "foo.proto bar.proto baz.proto quz.proto");
+
+  ExpectNoErrors();
+
+  // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and
+  // stdout at the same time. Need to figure out why and add this test back
+  // for Cygwin.
+#if !defined(__CYGWIN__)
+  ExpectCapturedStdout(
+      "foo.Foo                             free: 1 3 6-7 9 11-INF\n"
+      "Bar                                 free: 1 3 6-7 9 11-INF\n"
+      "Baz                                 free: 1 3 6-7 9 14\n"
+      "Quz.Foo                             free: 1-INF\n"
+      "Quz.E.G.Foo                         free: 1-INF\n"
+      "Quz                                 free: 1 3 6-7 12-14 16-INF\n");
+#endif
+}
+
+// ===================================================================
+
+// Test for --encode and --decode.  Note that it would be easier to do this
+// test as a shell script, but we'd like to be able to run the test on
+// platforms that don't have a Bourne-compatible shell available (especially
+// Windows/MSVC).
+class EncodeDecodeTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    duped_stdin_ = dup(STDIN_FILENO);
+  }
+
+  virtual void TearDown() {
+    dup2(duped_stdin_, STDIN_FILENO);
+    close(duped_stdin_);
+  }
+
+  void RedirectStdinFromText(const string& input) {
+    string filename = TestTempDir() + "/test_stdin";
+    GOOGLE_CHECK_OK(File::SetContents(filename, input, true));
+    GOOGLE_CHECK(RedirectStdinFromFile(filename));
+  }
+
+  bool RedirectStdinFromFile(const string& filename) {
+    int fd = open(filename.c_str(), O_RDONLY);
+    if (fd < 0) return false;
+    dup2(fd, STDIN_FILENO);
+    close(fd);
+    return true;
+  }
+
+  // Remove '\r' characters from text.
+  string StripCR(const string& text) {
+    string result;
+
+    for (int i = 0; i < text.size(); i++) {
+      if (text[i] != '\r') {
+        result.push_back(text[i]);
+      }
+    }
+
+    return result;
+  }
+
+  enum Type { TEXT, BINARY };
+  enum ReturnCode { SUCCESS, ERROR };
+
+  bool Run(const string& command) {
+    vector<string> args;
+    args.push_back("protoc");
+    SplitStringUsing(command, " ", &args);
+    args.push_back("--proto_path=" + TestSourceDir());
+
+    google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
+    for (int i = 0; i < args.size(); i++) {
+      argv[i] = args[i].c_str();
+    }
+
+    CommandLineInterface cli;
+    cli.SetInputsAreProtoPathRelative(true);
+
+    CaptureTestStdout();
+    CaptureTestStderr();
+
+    int result = cli.Run(args.size(), argv.get());
+
+    captured_stdout_ = GetCapturedTestStdout();
+    captured_stderr_ = GetCapturedTestStderr();
+
+    return result == 0;
+  }
+
+  void ExpectStdoutMatchesBinaryFile(const string& filename) {
+    string expected_output;
+    GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true));
+
+    // Don't use EXPECT_EQ because we don't want to print raw binary data to
+    // stdout on failure.
+    EXPECT_TRUE(captured_stdout_ == expected_output);
+  }
+
+  void ExpectStdoutMatchesTextFile(const string& filename) {
+    string expected_output;
+    GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true));
+
+    ExpectStdoutMatchesText(expected_output);
+  }
+
+  void ExpectStdoutMatchesText(const string& expected_text) {
+    EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_));
+  }
+
+  void ExpectStderrMatchesText(const string& expected_text) {
+    EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_));
+  }
+
+ private:
+  int duped_stdin_;
+  string captured_stdout_;
+  string captured_stderr_;
+};
+
+TEST_F(EncodeDecodeTest, Encode) {
+  RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/"
+    "testdata/text_format_unittest_data_oneof_implemented.txt");
+  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
+                  "--encode=protobuf_unittest.TestAllTypes"));
+  ExpectStdoutMatchesBinaryFile(TestSourceDir() +
+    "/google/protobuf/testdata/golden_message_oneof_implemented");
+  ExpectStderrMatchesText("");
+}
+
+TEST_F(EncodeDecodeTest, Decode) {
+  RedirectStdinFromFile(TestSourceDir() +
+    "/google/protobuf/testdata/golden_message_oneof_implemented");
+  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
+                  "--decode=protobuf_unittest.TestAllTypes"));
+  ExpectStdoutMatchesTextFile(TestSourceDir() +
+    "/google/protobuf/"
+    "testdata/text_format_unittest_data_oneof_implemented.txt");
+  ExpectStderrMatchesText("");
+}
+
+TEST_F(EncodeDecodeTest, Partial) {
+  RedirectStdinFromText("");
+  EXPECT_TRUE(Run("google/protobuf/unittest.proto "
+                  "--encode=protobuf_unittest.TestRequired"));
+  ExpectStdoutMatchesText("");
+  ExpectStderrMatchesText(
+    "warning:  Input message is missing required fields:  a, b, c\n");
+}
+
+TEST_F(EncodeDecodeTest, DecodeRaw) {
+  protobuf_unittest::TestAllTypes message;
+  message.set_optional_int32(123);
+  message.set_optional_string("foo");
+  string data;
+  message.SerializeToString(&data);
+
+  RedirectStdinFromText(data);
+  EXPECT_TRUE(Run("--decode_raw"));
+  ExpectStdoutMatchesText("1: 123\n"
+                          "14: \"foo\"\n");
+  ExpectStderrMatchesText("");
+}
+
+TEST_F(EncodeDecodeTest, UnknownType) {
+  EXPECT_FALSE(Run("google/protobuf/unittest.proto "
+                   "--encode=NoSuchType"));
+  ExpectStdoutMatchesText("");
+  ExpectStderrMatchesText("Type not defined: NoSuchType\n");
+}
+
+TEST_F(EncodeDecodeTest, ProtoParseError) {
+  EXPECT_FALSE(Run("google/protobuf/no_such_file.proto "
+                   "--encode=NoSuchType"));
+  ExpectStdoutMatchesText("");
+  ExpectStderrMatchesText(
+    "google/protobuf/no_such_file.proto: File not found.\n");
+}
+
+}  // anonymous namespace
+
+#endif  // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
new file mode 100644
index 0000000..77451ab
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -0,0 +1,159 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This test insures that google/protobuf/descriptor.pb.{h,cc} match exactly
+// what would be generated by the protocol compiler.  These files are not
+// generated automatically at build time because they are compiled into the
+// protocol compiler itself.  So, if they were auto-generated, you'd have a
+// chicken-and-egg problem.
+//
+// If this test fails, run the script
+// "generate_descriptor_proto.sh" and add
+// descriptor.pb.{h,cc} to your changelist.
+
+#include <map>
+
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+};
+
+class MockGeneratorContext : public GeneratorContext {
+ public:
+  MockGeneratorContext() {}
+  ~MockGeneratorContext() {
+    STLDeleteValues(&files_);
+  }
+
+  void ExpectFileMatches(const string& virtual_filename,
+                         const string& physical_filename) {
+    string* expected_contents = FindPtrOrNull(files_, virtual_filename);
+    ASSERT_TRUE(expected_contents != NULL)
+      << "Generator failed to generate file: " << virtual_filename;
+
+    string actual_contents;
+    GOOGLE_CHECK_OK(
+        File::GetContents(TestSourceDir() + "/" + physical_filename,
+                          &actual_contents, true));
+    EXPECT_TRUE(actual_contents == *expected_contents)
+      << physical_filename << " needs to be regenerated.  Please run "
+         "google/protobuf/compiler/release_compiler.sh and "
+         "generate_descriptor_proto.sh. Then add this file "
+         "to your CL.";
+  }
+
+  // implements GeneratorContext --------------------------------------
+
+  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+    string** map_slot = &files_[filename];
+    delete *map_slot;
+    *map_slot = new string;
+
+    return new io::StringOutputStream(*map_slot);
+  }
+
+ private:
+  map<string, string*> files_;
+};
+
+TEST(BootstrapTest, GeneratedDescriptorMatches) {
+  MockErrorCollector error_collector;
+  DiskSourceTree source_tree;
+  source_tree.MapPath("", TestSourceDir());
+  Importer importer(&source_tree, &error_collector);
+  const FileDescriptor* proto_file =
+    importer.Import("google/protobuf/descriptor.proto");
+  const FileDescriptor* plugin_proto_file =
+    importer.Import("google/protobuf/compiler/plugin.proto");
+  EXPECT_EQ("", error_collector.text_);
+  ASSERT_TRUE(proto_file != NULL);
+  ASSERT_TRUE(plugin_proto_file != NULL);
+
+  CppGenerator generator;
+  MockGeneratorContext context;
+  string error;
+  string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
+  ASSERT_TRUE(generator.Generate(proto_file, parameter,
+                                 &context, &error));
+  parameter = "dllexport_decl=LIBPROTOC_EXPORT";
+  ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
+                                 &context, &error));
+
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
+                            "google/protobuf/descriptor.pb.h");
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
+                            "google/protobuf/descriptor.pb.cc");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
+                            "google/protobuf/compiler/plugin.pb.h");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
+                            "google/protobuf/compiler/plugin.pb.cc");
+}
+
+}  // namespace
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.cc
new file mode 100644
index 0000000..c81c598
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -0,0 +1,319 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+
+#include <google/protobuf/compiler/cpp/cpp_enum.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
+// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
+// generation of the GOOGLE_ARRAYSIZE constant.
+bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
+  int32 max_value = descriptor->value(0)->number();
+  for (int i = 0; i < descriptor->value_count(); i++) {
+    if (descriptor->value(i)->number() > max_value) {
+      max_value = descriptor->value(i)->number();
+    }
+  }
+  return max_value != ::google::protobuf::kint32max;
+}
+}  // namespace
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
+                             const Options& options)
+  : descriptor_(descriptor),
+    classname_(ClassName(descriptor, false)),
+    options_(options),
+    generate_array_size_(ShouldGenerateArraySize(descriptor)) {
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::FillForwardDeclaration(
+    map<string, const EnumDescriptor*>* enum_names) {
+  if (!options_.proto_h) {
+    return;
+  }
+  (*enum_names)[classname_] = descriptor_;
+}
+
+void EnumGenerator::GenerateDefinition(io::Printer* printer) {
+  map<string, string> vars;
+  vars["classname"] = classname_;
+  vars["short_name"] = descriptor_->name();
+  vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
+
+  printer->Print(vars, "enum $enumbase$ {\n");
+  printer->Annotate("enumbase", descriptor_);
+  printer->Indent();
+
+  const EnumValueDescriptor* min_value = descriptor_->value(0);
+  const EnumValueDescriptor* max_value = descriptor_->value(0);
+
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    vars["name"] = EnumValueName(descriptor_->value(i));
+    // In C++, an value of -2147483648 gets interpreted as the negative of
+    // 2147483648, and since 2147483648 can't fit in an integer, this produces a
+    // compiler warning.  This works around that issue.
+    vars["number"] = Int32ToString(descriptor_->value(i)->number());
+    vars["prefix"] = (descriptor_->containing_type() == NULL) ?
+      "" : classname_ + "_";
+    vars["deprecation"] = descriptor_->value(i)->options().deprecated() ?
+        " PROTOBUF_DEPRECATED" : "";
+
+    if (i > 0) printer->Print(",\n");
+    printer->Print(vars, "$prefix$$name$$deprecation$ = $number$");
+
+    if (descriptor_->value(i)->number() < min_value->number()) {
+      min_value = descriptor_->value(i);
+    }
+    if (descriptor_->value(i)->number() > max_value->number()) {
+      max_value = descriptor_->value(i);
+    }
+  }
+
+  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    // For new enum semantics: generate min and max sentinel values equal to
+    // INT32_MIN and INT32_MAX
+    if (descriptor_->value_count() > 0) printer->Print(",\n");
+    printer->Print(vars,
+        "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n"
+        "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max");
+  }
+
+  printer->Outdent();
+  printer->Print("\n};\n");
+
+  vars["min_name"] = EnumValueName(min_value);
+  vars["max_name"] = EnumValueName(max_value);
+
+  if (options_.dllexport_decl.empty()) {
+    vars["dllexport"] = "";
+  } else {
+    vars["dllexport"] = options_.dllexport_decl + " ";
+  }
+
+  printer->Print(vars,
+    "$dllexport$bool $classname$_IsValid(int value);\n"
+    "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
+    "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n");
+
+  if (generate_array_size_) {
+    printer->Print(vars,
+      "const int $prefix$$short_name$_ARRAYSIZE = "
+      "$prefix$$short_name$_MAX + 1;\n\n");
+  }
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
+    // The _Name and _Parse methods
+    printer->Print(
+        vars,
+        "inline const ::std::string& $classname$_Name($classname$ value) {\n"
+        "  return ::google::protobuf::internal::NameOfEnum(\n"
+        "    $classname$_descriptor(), value);\n"
+        "}\n");
+    printer->Print(vars,
+      "inline bool $classname$_Parse(\n"
+      "    const ::std::string& name, $classname$* value) {\n"
+      "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
+      "    $classname$_descriptor(), name, value);\n"
+      "}\n");
+  }
+}
+
+void EnumGenerator::
+GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+  printer->Print(
+      "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
+      "{};\n",
+      "classname", ClassName(descriptor_, true));
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+      "template <>\n"
+      "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
+      "  return $classname$_descriptor();\n"
+      "}\n",
+      "classname", ClassName(descriptor_, true));
+  }
+}
+
+void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
+  map<string, string> vars;
+  vars["nested_name"] = descriptor_->name();
+  vars["classname"] = classname_;
+  vars["constexpr"] = options_.proto_h ? "constexpr " : "";
+  printer->Print(vars, "typedef $classname$ $nested_name$;\n");
+
+  for (int j = 0; j < descriptor_->value_count(); j++) {
+    vars["tag"] = EnumValueName(descriptor_->value(j));
+    vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
+      "PROTOBUF_DEPRECATED_ATTR " : "";
+    printer->Print(vars,
+      "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n"
+      "  $classname$_$tag$;\n");
+  }
+
+  printer->Print(vars,
+    "static inline bool $nested_name$_IsValid(int value) {\n"
+    "  return $classname$_IsValid(value);\n"
+    "}\n"
+    "static const $nested_name$ $nested_name$_MIN =\n"
+    "  $classname$_$nested_name$_MIN;\n"
+    "static const $nested_name$ $nested_name$_MAX =\n"
+    "  $classname$_$nested_name$_MAX;\n");
+  if (generate_array_size_) {
+    printer->Print(vars,
+      "static const int $nested_name$_ARRAYSIZE =\n"
+      "  $classname$_$nested_name$_ARRAYSIZE;\n");
+  }
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "static inline const ::google::protobuf::EnumDescriptor*\n"
+      "$nested_name$_descriptor() {\n"
+      "  return $classname$_descriptor();\n"
+      "}\n");
+    printer->Print(vars,
+                   "static inline const ::std::string& "
+                   "$nested_name$_Name($nested_name$ value) {"
+                   "\n"
+                   "  return $classname$_Name(value);\n"
+                   "}\n");
+    printer->Print(vars,
+      "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
+      "    $nested_name$* value) {\n"
+      "  return $classname$_Parse(name, value);\n"
+      "}\n");
+  }
+}
+
+void EnumGenerator::GenerateDescriptorInitializer(
+    io::Printer* printer, int index) {
+  map<string, string> vars;
+  vars["classname"] = classname_;
+  vars["index"] = SimpleItoa(index);
+
+  if (descriptor_->containing_type() == NULL) {
+    printer->Print(vars,
+      "$classname$_descriptor_ = file->enum_type($index$);\n");
+  } else {
+    vars["parent"] = ClassName(descriptor_->containing_type(), false);
+    printer->Print(vars,
+      "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
+  }
+}
+
+void EnumGenerator::GenerateMethods(io::Printer* printer) {
+  map<string, string> vars;
+  vars["classname"] = classname_;
+  vars["constexpr"] = options_.proto_h ? "constexpr " : "";
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  return $classname$_descriptor_;\n"
+      "}\n");
+  }
+
+  printer->Print(vars,
+    "bool $classname$_IsValid(int value) {\n"
+    "  switch(value) {\n");
+
+  // Multiple values may have the same number.  Make sure we only cover
+  // each number once by first constructing a set containing all valid
+  // numbers, then printing a case statement for each element.
+
+  set<int> numbers;
+  for (int j = 0; j < descriptor_->value_count(); j++) {
+    const EnumValueDescriptor* value = descriptor_->value(j);
+    numbers.insert(value->number());
+  }
+
+  for (set<int>::iterator iter = numbers.begin();
+       iter != numbers.end(); ++iter) {
+    printer->Print(
+      "    case $number$:\n",
+      "number", Int32ToString(*iter));
+  }
+
+  printer->Print(vars,
+    "      return true;\n"
+    "    default:\n"
+    "      return false;\n"
+    "  }\n"
+    "}\n"
+    "\n");
+
+  if (descriptor_->containing_type() != NULL) {
+    // We need to "define" the static constants which were declared in the
+    // header, to give the linker a place to put them.  Or at least the C++
+    // standard says we have to.  MSVC actually insists that we do _not_ define
+    // them again in the .cc file, prior to VC++ 2015.
+    printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n");
+
+    vars["parent"] = ClassName(descriptor_->containing_type(), false);
+    vars["nested_name"] = descriptor_->name();
+    for (int i = 0; i < descriptor_->value_count(); i++) {
+      vars["value"] = EnumValueName(descriptor_->value(i));
+      printer->Print(vars,
+        "$constexpr$const $classname$ $parent$::$value$;\n");
+    }
+    printer->Print(vars,
+      "const $classname$ $parent$::$nested_name$_MIN;\n"
+      "const $classname$ $parent$::$nested_name$_MAX;\n");
+    if (generate_array_size_) {
+      printer->Print(vars,
+        "const int $parent$::$nested_name$_ARRAYSIZE;\n");
+    }
+
+    printer->Print("#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900\n");
+  }
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.h
new file mode 100644
index 0000000..90edf00
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -0,0 +1,111 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+
+#include <map>
+#include <set>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumGenerator {
+ public:
+  // See generator.cc for the meaning of dllexport_decl.
+  EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
+  ~EnumGenerator();
+
+  // Header stuff.
+
+  // Fills the name to use when declaring the enum. This is for use when
+  // generating other .proto.h files. This code should be placed within the
+  // enum's package namespace, but NOT within any class, even for nested
+  // enums. A given key in enum_names will map from an enum class name to the
+  // EnumDescriptor that was responsible for its inclusion in the map. This can
+  // be used to associate the descriptor with the code generated for it.
+  void FillForwardDeclaration(map<string, const EnumDescriptor*>* enum_names);
+
+  // Generate header code defining the enum.  This code should be placed
+  // within the enum's package namespace, but NOT within any class, even for
+  // nested enums.
+  void GenerateDefinition(io::Printer* printer);
+
+  // Generate specialization of GetEnumDescriptor<MyEnum>().
+  // Precondition: in ::google::protobuf namespace.
+  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+
+  // For enums nested within a message, generate code to import all the enum's
+  // symbols (e.g. the enum type name, all its values, etc.) into the class's
+  // namespace.  This should be placed inside the class definition in the
+  // header.
+  void GenerateSymbolImports(io::Printer* printer);
+
+  // Source file stuff.
+
+  // Generate code that initializes the global variable storing the enum's
+  // descriptor.
+  void GenerateDescriptorInitializer(io::Printer* printer, int index);
+
+  // Generate non-inline methods related to the enum, such as IsValidValue().
+  // Goes in the .cc file.
+  void GenerateMethods(io::Printer* printer);
+
+ private:
+  const EnumDescriptor* descriptor_;
+  const string classname_;
+  const Options& options_;
+  // whether to generate the *_ARRAYSIZE constant.
+  const bool generate_array_size_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
new file mode 100644
index 0000000..10252b3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -0,0 +1,507 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+                      map<string, string>* variables,
+                      const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  const EnumValueDescriptor* default_value = descriptor->default_value_enum();
+  (*variables)["type"] = ClassName(descriptor->enum_type(), true);
+  (*variables)["default"] = Int32ToString(default_value->number());
+  (*variables)["full_name"] = descriptor->full_name();
+}
+
+}  // namespace
+
+// ===================================================================
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetEnumVariables(descriptor, &variables_, options);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_, "int $name$_;\n");
+}
+
+void EnumFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecated_attr$$type$ $name$() const;\n"
+    "$deprecated_attr$void set_$name$($type$ value);\n");
+}
+
+void EnumFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return static_cast< $type$ >($name$_);\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n");
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables,
+    "  assert($type$_IsValid(value));\n");
+  }
+  printer->Print(variables,
+    "  $set_hasbit$\n"
+    "  $name$_ = value;\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n");
+}
+
+void EnumFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "set_$name$(from.$name$());\n");
+}
+
+void EnumFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+}
+
+void EnumFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int value;\n"
+    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+    "         int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+    "       input, &value)));\n");
+  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables_,
+      "set_$name$(static_cast< $type$ >(value));\n");
+  } else {
+    printer->Print(variables_,
+      "if ($type$_IsValid(value)) {\n"
+      "  set_$name$(static_cast< $type$ >(value));\n");
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(variables_,
+        "} else {\n"
+        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+    } else {
+      printer->Print(
+        "} else {\n"
+        "  unknown_fields_stream.WriteVarint32($tag$);\n"
+        "  unknown_fields_stream.WriteVarint32(value);\n",
+        "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
+    }
+    printer->Print(variables_,
+      "}\n");
+  }
+}
+
+void EnumFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
+    "  $number$, this->$name$(), output);\n");
+}
+
+void EnumFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+    "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
+    "  $number$, this->$name$(), target);\n");
+}
+
+void EnumFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "total_size += $tag_size$ +\n"
+    "  ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
+}
+
+// ===================================================================
+
+EnumOneofFieldGenerator::
+EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options)
+  : EnumFieldGenerator(descriptor, options) {
+  SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
+
+void EnumOneofFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  if (has_$name$()) {\n"
+    "    return static_cast< $type$ >($oneof_prefix$$name$_);\n"
+    "  }\n"
+    "  return static_cast< $type$ >($default$);\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n");
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables,
+    "  assert($type$_IsValid(value));\n");
+  }
+  printer->Print(variables,
+    "  if (!has_$name$()) {\n"
+    "    clear_$oneof_name$();\n"
+    "    set_has_$name$();\n"
+    "  }\n"
+    "  $oneof_prefix$$name$_ = value;\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n");
+}
+
+void EnumOneofFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
+}
+
+void EnumOneofFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  // Don't print any swapping code. Swapping the union will swap this field.
+}
+
+void EnumOneofFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "  $classname$_default_oneof_instance_->$name$_ = $default$;\n");
+}
+
+// ===================================================================
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetEnumVariables(descriptor, &variables_, options);
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::RepeatedField<int> $name$_;\n");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    printer->Print(variables_,
+      "mutable int _$name$_cached_byte_size_;\n");
+  }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecated_attr$$type$ $name$(int index) const;\n"
+    "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
+    "$deprecated_attr$void add_$name$($type$ value);\n");
+  printer->Print(variables_,
+    "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
+    "$deprecated_attr$::google::protobuf::RepeatedField<int>* mutable_$name$();\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$(int index) const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return static_cast< $type$ >($name$_.Get(index));\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables,
+    "  assert($type$_IsValid(value));\n");
+  }
+  printer->Print(variables,
+    "  $name$_.Set(index, value);\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n"
+    "$inline$ void $classname$::add_$name$($type$ value) {\n");
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables,
+    "  assert($type$_IsValid(value));\n");
+  }
+  printer->Print(variables,
+    "  $name$_.Add(value);\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "}\n");
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
+    "$classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$inline$ ::google::protobuf::RepeatedField<int>*\n"
+    "$classname$::mutable_$name$() {\n"
+    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+    "  return &$name$_;\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Clear();\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  // Not needed for repeated fields.
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
+  printer->Print(variables_,
+    "int value;\n"
+    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+    "         int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+    "       input, &value)));\n");
+  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    printer->Print(variables_,
+      "add_$name$(static_cast< $type$ >(value));\n");
+  } else {
+    printer->Print(variables_,
+      "if ($type$_IsValid(value)) {\n"
+      "  add_$name$(static_cast< $type$ >(value));\n");
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(variables_,
+        "} else {\n"
+        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+    } else {
+      printer->Print(
+        "} else {\n"
+        "  unknown_fields_stream.WriteVarint32(tag);\n"
+        "  unknown_fields_stream.WriteVarint32(value);\n");
+    }
+    printer->Print("}\n");
+  }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+  if (!descriptor_->is_packed()) {
+      // This path is rarely executed, so we use a non-inlined implementation.
+    if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+      printer->Print(variables_,
+        "DO_((::google::protobuf::internal::"
+                    "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       NULL,\n"
+        "       NULL,\n"
+        "       this->mutable_$name$())));\n");
+    } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(variables_,
+        "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       $type$_IsValid,\n"
+        "       mutable_unknown_fields(),\n"
+        "       this->mutable_$name$())));\n");
+    } else {
+      printer->Print(variables_,
+        "DO_((::google::protobuf::internal::"
+                     "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+        "       input,\n"
+        "       $number$,\n"
+        "       $type$_IsValid,\n"
+        "       &unknown_fields_stream,\n"
+        "       this->mutable_$name$())));\n");
+    }
+  } else {
+    printer->Print(variables_,
+      "::google::protobuf::uint32 length;\n"
+      "DO_(input->ReadVarint32(&length));\n"
+      "::google::protobuf::io::CodedInputStream::Limit limit = "
+          "input->PushLimit(length);\n"
+      "while (input->BytesUntilLimit() > 0) {\n"
+      "  int value;\n"
+      "  DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+      "         int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+      "       input, &value)));\n");
+    if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+      printer->Print(variables_,
+      "  add_$name$(static_cast< $type$ >(value));\n");
+    } else {
+      printer->Print(variables_,
+      "  if ($type$_IsValid(value)) {\n"
+      "    add_$name$(static_cast< $type$ >(value));\n"
+      "  } else {\n");
+      if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+        printer->Print(variables_,
+        "    mutable_unknown_fields()->AddVarint($number$, value);\n");
+      } else {
+        printer->Print(variables_,
+        "    unknown_fields_stream.WriteVarint32(tag);\n"
+        "    unknown_fields_stream.WriteVarint32(value);\n");
+      }
+      printer->Print(
+      "  }\n");
+    }
+    printer->Print(variables_,
+      "}\n"
+      "input->PopLimit(limit);\n");
+  }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    // Write the tag and the size.
+    printer->Print(variables_,
+      "if (this->$name$_size() > 0) {\n"
+      "  ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    output);\n"
+      "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "  ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
+      "    this->$name$(i), output);\n");
+  } else {
+    printer->Print(variables_,
+      "  ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
+      "    $number$, this->$name$(i), output);\n");
+  }
+  printer->Print("}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    // Write the tag and the size.
+    printer->Print(variables_,
+      "if (this->$name$_size() > 0) {\n"
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    target);\n"
+      "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
+      "    _$name$_cached_byte_size_, target);\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
+      "    this->$name$(i), target);\n");
+  } else {
+    printer->Print(variables_,
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
+      "    $number$, this->$name$(i), target);\n");
+  }
+  printer->Print("}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int data_size = 0;\n");
+  printer->Indent();
+  printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n"
+      "  data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
+      "    this->$name$(i));\n"
+      "}\n");
+
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "if (data_size > 0) {\n"
+      "  total_size += $tag_size$ +\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "}\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+      "_$name$_cached_byte_size_ = data_size;\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+      "total_size += data_size;\n");
+  } else {
+    printer->Print(variables_,
+      "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.h
new file mode 100644
index 0000000..fe21c57
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -0,0 +1,124 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumFieldGenerator : public FieldGenerator {
+ public:
+  EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+  ~EnumFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class EnumOneofFieldGenerator : public EnumFieldGenerator {
+ public:
+  EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
+  ~EnumOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public FieldGenerator {
+ public:
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
+  ~RepeatedEnumFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.cc
new file mode 100644
index 0000000..c42f162
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -0,0 +1,210 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <map>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+// Returns the fully-qualified class name of the message that this field
+// extends. This function is used in the Google-internal code to handle some
+// legacy cases.
+string ExtendeeClassName(const FieldDescriptor* descriptor) {
+  const Descriptor* extendee = descriptor->containing_type();
+  return ClassName(extendee, true);
+}
+
+}  // anonymous namespace
+
+ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+  : descriptor_(descriptor),
+    options_(options) {
+  // Construct type_traits_.
+  if (descriptor_->is_repeated()) {
+    type_traits_ = "Repeated";
+  }
+
+  switch (descriptor_->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_ENUM:
+      type_traits_.append("EnumTypeTraits< ");
+      type_traits_.append(ClassName(descriptor_->enum_type(), true));
+      type_traits_.append(", ");
+      type_traits_.append(ClassName(descriptor_->enum_type(), true));
+      type_traits_.append("_IsValid>");
+      break;
+    case FieldDescriptor::CPPTYPE_STRING:
+      type_traits_.append("StringTypeTraits");
+      break;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      type_traits_.append("MessageTypeTraits< ");
+      type_traits_.append(ClassName(descriptor_->message_type(), true));
+      type_traits_.append(" >");
+      break;
+    default:
+      type_traits_.append("PrimitiveTypeTraits< ");
+      type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
+      type_traits_.append(" >");
+      break;
+  }
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
+  map<string, string> vars;
+  vars["extendee"     ] = ExtendeeClassName(descriptor_);
+  vars["number"       ] = SimpleItoa(descriptor_->number());
+  vars["type_traits"  ] = type_traits_;
+  vars["name"         ] = descriptor_->name();
+  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
+  vars["constant_name"] = FieldConstantName(descriptor_);
+
+  // If this is a class member, it needs to be declared "static".  Otherwise,
+  // it needs to be "extern".  In the latter case, it also needs the DLL
+  // export/import specifier.
+  if (descriptor_->extension_scope() == NULL) {
+    vars["qualifier"] = "extern";
+    if (!options_.dllexport_decl.empty()) {
+      vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
+    }
+  } else {
+    vars["qualifier"] = "static";
+  }
+
+  printer->Print(vars,
+    "static const int $constant_name$ = $number$;\n"
+    "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
+    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+    "  $name$;\n"
+    );
+
+}
+
+void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
+  // If this is a class member, it needs to be declared in its class scope.
+  string scope = (descriptor_->extension_scope() == NULL) ? "" :
+    ClassName(descriptor_->extension_scope(), false) + "::";
+  string name = scope + descriptor_->name();
+
+  map<string, string> vars;
+  vars["extendee"     ] = ExtendeeClassName(descriptor_);
+  vars["type_traits"  ] = type_traits_;
+  vars["name"         ] = name;
+  vars["constant_name"] = FieldConstantName(descriptor_);
+  vars["default"      ] = DefaultValue(descriptor_);
+  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
+  vars["scope"        ] = scope;
+
+  if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+    // We need to declare a global string which will contain the default value.
+    // We cannot declare it at class scope because that would require exposing
+    // it in the header which would be annoying for other reasons.  So we
+    // replace :: with _ in the name and declare it as a global.
+    string global_name = StringReplace(name, "::", "_", true);
+    vars["global_name"] = global_name;
+    printer->Print(vars,
+      "const ::std::string $global_name$_default($default$);\n");
+
+    // Update the default to refer to the string global.
+    vars["default"] = global_name + "_default";
+  }
+
+  // Likewise, class members need to declare the field constant variable.
+  if (descriptor_->extension_scope() != NULL) {
+    printer->Print(vars,
+      "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"
+      "const int $scope$$constant_name$;\n"
+      "#endif\n");
+  }
+
+  printer->Print(vars,
+    "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
+    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+    "  $name$($constant_name$, $default$);\n");
+}
+
+void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
+  map<string, string> vars;
+  vars["extendee"   ] = ExtendeeClassName(descriptor_);
+  vars["number"     ] = SimpleItoa(descriptor_->number());
+  vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+  vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
+  vars["is_packed"  ] = (descriptor_->is_repeated() &&
+                         descriptor_->options().packed())
+                        ? "true" : "false";
+
+  switch (descriptor_->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_ENUM:
+      printer->Print(vars,
+        "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
+        "  &$extendee$::default_instance(),\n"
+        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+      printer->Print(
+        "  &$type$_IsValid);\n",
+        "type", ClassName(descriptor_->enum_type(), true));
+      break;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      printer->Print(vars,
+        "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
+        "  &$extendee$::default_instance(),\n"
+        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+      printer->Print(
+        "  &$type$::default_instance());\n",
+        "type", ClassName(descriptor_->message_type(), true));
+      break;
+    default:
+      printer->Print(vars,
+        "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
+        "  &$extendee$::default_instance(),\n"
+        "  $number$, $field_type$, $is_repeated$, $is_packed$);\n");
+      break;
+  }
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.h
new file mode 100644
index 0000000..1c1caf1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -0,0 +1,86 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+
+namespace google {
+namespace protobuf {
+  class FieldDescriptor;       // descriptor.h
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Generates code for an extension, which may be within the scope of some
+// message or may be at file scope.  This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ExtensionGenerator {
+ public:
+  // See generator.cc for the meaning of dllexport_decl.
+  explicit ExtensionGenerator(const FieldDescriptor* descriptor,
+                              const Options& options);
+  ~ExtensionGenerator();
+
+  // Header stuff.
+  void GenerateDeclaration(io::Printer* printer);
+
+  // Source file stuff.
+  void GenerateDefinition(io::Printer* printer);
+
+  // Generate code to register the extension.
+  void GenerateRegistration(io::Printer* printer);
+
+ private:
+  const FieldDescriptor* descriptor_;
+  string type_traits_;
+  Options options_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.cc
new file mode 100644
index 0000000..b3ba3a2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -0,0 +1,201 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+#include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
+#include <google/protobuf/compiler/cpp/cpp_map_field.h>
+#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormat;
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables,
+                             const Options& options) {
+  (*variables)["name"] = FieldName(descriptor);
+  (*variables)["index"] = SimpleItoa(descriptor->index());
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
+  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
+
+  // non_null_ptr_to_name is usable only if has_$name$ is true.  It yields a
+  // pointer that will not be NULL.  Subclasses of FieldGenerator may set
+  // (*variables)["non_null_ptr_to_name"] differently.
+  (*variables)["non_null_ptr_to_name"] =
+      StrCat("&this->", FieldName(descriptor), "()");
+
+  (*variables)["tag_size"] = SimpleItoa(
+    WireFormat::TagSize(descriptor->number(), descriptor->type()));
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? " PROTOBUF_DEPRECATED" : "";
+  (*variables)["deprecated_attr"] = descriptor->options().deprecated()
+      ? "PROTOBUF_DEPRECATED_ATTR " : "";
+
+  (*variables)["cppget"] = "Get";
+
+  if (HasFieldPresence(descriptor->file())) {
+    (*variables)["set_hasbit"] =
+        "set_has_" + FieldName(descriptor) + "();";
+    (*variables)["clear_hasbit"] =
+        "clear_has_" + FieldName(descriptor) + "();";
+  } else {
+    (*variables)["set_hasbit"] = "";
+    (*variables)["clear_hasbit"] = "";
+  }
+
+  // By default, empty string, so that generic code used for both oneofs and
+  // singular fields can be written.
+  (*variables)["oneof_prefix"] = "";
+}
+
+void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
+                                  map<string, string>* variables) {
+  const string prefix = descriptor->containing_oneof()->name() + "_.";
+  (*variables)["oneof_prefix"] = prefix;
+  (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+  (*variables)["non_null_ptr_to_name"] =
+      StrCat(prefix, (*variables)["name"], "_");
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+void FieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+  // Reaching here indicates a bug. Cases are:
+  //   - This FieldGenerator should support packing, but this method should be
+  //     overridden.
+  //   - This FieldGenerator doesn't support packing, and this method should
+  //     never have been called.
+  GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
+             << "called on field generator that does not support packing.";
+
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+                                     const Options& options)
+    : descriptor_(descriptor),
+      options_(options),
+      field_generators_(
+          new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+  // Construct all the FieldGenerators.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
+  }
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+                                                 const Options& options) {
+  if (field->is_repeated()) {
+    switch (field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (field->is_map()) {
+          return new MapFieldGenerator(field, options);
+        } else {
+          return new RepeatedMessageFieldGenerator(field, options);
+        }
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // RepeatedStringFieldGenerator handles unknown ctypes.
+          case FieldOptions::STRING:
+            return new RepeatedStringFieldGenerator(field, options);
+        }
+      case FieldDescriptor::CPPTYPE_ENUM:
+        return new RepeatedEnumFieldGenerator(field, options);
+      default:
+        return new RepeatedPrimitiveFieldGenerator(field, options);
+    }
+  } else if (field->containing_oneof()) {
+    switch (field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        return new MessageOneofFieldGenerator(field, options);
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // StringOneofFieldGenerator handles unknown ctypes.
+          case FieldOptions::STRING:
+            return new StringOneofFieldGenerator(field, options);
+        }
+      case FieldDescriptor::CPPTYPE_ENUM:
+        return new EnumOneofFieldGenerator(field, options);
+      default:
+        return new PrimitiveOneofFieldGenerator(field, options);
+    }
+  } else {
+    switch (field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        return new MessageFieldGenerator(field, options);
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // StringFieldGenerator handles unknown ctypes.
+          case FieldOptions::STRING:
+            return new StringFieldGenerator(field, options);
+        }
+      case FieldDescriptor::CPPTYPE_ENUM:
+        return new EnumFieldGenerator(field, options);
+      default:
+        return new PrimitiveFieldGenerator(field, options);
+    }
+  }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+    const FieldDescriptor* field) const {
+  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+  return *field_generators_[field->index()];
+}
+
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.h
new file mode 100644
index 0000000..3b01252
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -0,0 +1,229 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Helper function: set variables in the map that are the same for all
+// field code generators.
+// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
+// 'deprecation'].
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables,
+                             const Options& options);
+
+void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
+                                  map<string, string>* variables);
+
+class FieldGenerator {
+ public:
+  explicit FieldGenerator(const Options& options) : options_(options) {}
+  virtual ~FieldGenerator();
+
+  // Generate lines of code declaring members fields of the message class
+  // needed to represent this field.  These are placed inside the message
+  // class.
+  virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
+
+  // Generate static default variable for this field. These are placed inside
+  // the message class. Most field types don't need this, so the default
+  // implementation is empty.
+  virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
+
+  // Generate prototypes for accessors that will manipulate imported
+  // messages inline.  These are for .proto.h headers.
+  //
+  // In .proto.h mode, the headers of imports are not #included. However,
+  // functions that manipulate the imported message types need access to
+  // the class definition of the imported message, meaning that the headers
+  // must be #included. To get around this, functions that manipulate
+  // imported message objects are defined as dependent functions in a base
+  // template class. By making them dependent template functions, the
+  // function templates will not be instantiated until they are called, so
+  // we can defer to those translation units to #include the necessary
+  // generated headers.
+  //
+  // See:
+  // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
+  //
+  // Most field types don't need this, so the default implementation is empty.
+  virtual void GenerateDependentAccessorDeclarations(
+      io::Printer* printer) const {}
+
+  // Generate prototypes for all of the accessor functions related to this
+  // field.  These are placed inside the class definition.
+  virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
+
+  // Generate inline definitions of depenent accessor functions for this field.
+  // These are placed inside the header after all class definitions.
+  virtual void GenerateDependentInlineAccessorDefinitions(
+    io::Printer* printer) const {}
+
+  // Generate inline definitions of accessor functions for this field.
+  // These are placed inside the header after all class definitions.
+  // In non-.proto.h mode, this generates dependent accessor functions as well.
+  virtual void GenerateInlineAccessorDefinitions(
+    io::Printer* printer, bool is_inline) const = 0;
+
+  // Generate definitions of accessors that aren't inlined.  These are
+  // placed somewhere in the .cc file.
+  // Most field types don't need this, so the default implementation is empty.
+  virtual void GenerateNonInlineAccessorDefinitions(
+    io::Printer* /*printer*/) const {}
+
+  // Generate lines of code (statements, not declarations) which clear the
+  // field.  This is used to define the clear_$name$() method as well as
+  // the Clear() method for the whole message.
+  virtual void GenerateClearingCode(io::Printer* printer) const = 0;
+
+  // Generate lines of code (statements, not declarations) which merges the
+  // contents of the field from the current message to the target message,
+  // which is stored in the generated code variable "from".
+  // This is used to fill in the MergeFrom method for the whole message.
+  // Details of this usage can be found in message.cc under the
+  // GenerateMergeFrom method.
+  virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+
+  // Generate lines of code (statements, not declarations) which swaps
+  // this field and the corresponding field of another message, which
+  // is stored in the generated code variable "other". This is used to
+  // define the Swap method. Details of usage can be found in
+  // message.cc under the GenerateSwap method.
+  virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
+
+  // Generate initialization code for private members declared by
+  // GeneratePrivateMembers(). These go into the message class's SharedCtor()
+  // method, invoked by each of the generated constructors.
+  virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
+
+  // Generate any code that needs to go in the class's SharedDtor() method,
+  // invoked by the destructor.
+  // Most field types don't need this, so the default implementation is empty.
+  virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
+
+  // Generate a manual destructor invocation for use when the message is on an
+  // arena. The code that this method generates will be executed inside a
+  // shared-for-the-whole-message-class method registered with OwnDestructor().
+  // The method should return |true| if it generated any code that requires a
+  // call; this allows the message generator to eliminate the OwnDestructor()
+  // registration if no fields require it.
+  virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
+    return false;
+  }
+
+  // Generate code that allocates the fields's default instance.
+  virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
+      const {}
+
+  // Generate code that should be run when ShutdownProtobufLibrary() is called,
+  // to delete all dynamically-allocated objects.
+  virtual void GenerateShutdownCode(io::Printer* /*printer*/) const {}
+
+  // Generate lines to decode this field, which will be placed inside the
+  // message's MergeFromCodedStream() method.
+  virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
+
+  // Generate lines to decode this field from a packed value, which will be
+  // placed inside the message's MergeFromCodedStream() method.
+  virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
+      const;
+
+  // Generate lines to serialize this field, which are placed within the
+  // message's SerializeWithCachedSizes() method.
+  virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
+
+  // Generate lines to serialize this field directly to the array "target",
+  // which are placed within the message's SerializeWithCachedSizesToArray()
+  // method. This must also advance "target" past the written bytes.
+  virtual void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const = 0;
+
+  // Generate lines to compute the serialized size of this field, which
+  // are placed in the message's ByteSize() method.
+  virtual void GenerateByteSize(io::Printer* printer) const = 0;
+
+ protected:
+  const Options& options_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+  FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+  ~FieldGeneratorMap();
+
+  const FieldGenerator& get(const FieldDescriptor* field) const;
+
+ private:
+  const Descriptor* descriptor_;
+  const Options& options_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
+
+  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+                                       const Options& options);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.cc
new file mode 100644
index 0000000..de20476
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -0,0 +1,1068 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+
+#include <google/protobuf/compiler/cpp/cpp_enum.h>
+#include <google/protobuf/compiler/cpp/cpp_service.h>
+#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// ===================================================================
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
+    : file_(file),
+      options_(options),
+      message_generators_(
+          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
+      enum_generators_(
+          new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
+      service_generators_(
+          new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
+      extension_generators_(
+          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
+
+  for (int i = 0; i < file->message_type_count(); i++) {
+    message_generators_[i].reset(
+      new MessageGenerator(file->message_type(i), options));
+  }
+
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    enum_generators_[i].reset(
+      new EnumGenerator(file->enum_type(i), options));
+  }
+
+  for (int i = 0; i < file->service_count(); i++) {
+    service_generators_[i].reset(
+      new ServiceGenerator(file->service(i), options));
+  }
+
+  for (int i = 0; i < file->extension_count(); i++) {
+    extension_generators_[i].reset(
+      new ExtensionGenerator(file->extension(i), options));
+  }
+
+  SplitStringUsing(file_->package(), ".", &package_parts_);
+}
+
+FileGenerator::~FileGenerator() {}
+
+void FileGenerator::GenerateProtoHeader(io::Printer* printer,
+                                        const string& info_path) {
+  if (!options_.proto_h) {
+    return;
+  }
+
+  string filename_identifier = FilenameIdentifier(file_->name());
+  GenerateTopHeaderGuard(printer, filename_identifier);
+
+
+  GenerateLibraryIncludes(printer);
+
+  for (int i = 0; i < file_->public_dependency_count(); i++) {
+    const FileDescriptor* dep = file_->public_dependency(i);
+    const char* extension = ".proto.h";
+    string dependency = StripProto(dep->name()) + extension;
+    printer->Print(
+      "#include \"$dependency$\"  // IWYU pragma: export\n",
+      "dependency", dependency);
+  }
+
+  GenerateMetadataPragma(printer, info_path);
+
+  printer->Print(
+    "// @@protoc_insertion_point(includes)\n");
+
+
+  GenerateForwardDeclarations(printer);
+
+  // Open namespace.
+  GenerateNamespaceOpeners(printer);
+
+  GenerateGlobalStateFunctionDeclarations(printer);
+
+  printer->Print("\n");
+
+  GenerateEnumDefinitions(printer);
+
+  printer->Print(kThickSeparator);
+  printer->Print("\n");
+
+  GenerateMessageDefinitions(printer);
+
+  printer->Print("\n");
+  printer->Print(kThickSeparator);
+  printer->Print("\n");
+
+  GenerateServiceDefinitions(printer);
+
+  GenerateExtensionIdentifiers(printer);
+
+  printer->Print("\n");
+  printer->Print(kThickSeparator);
+  printer->Print("\n");
+
+  GenerateInlineFunctionDefinitions(printer);
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(namespace_scope)\n"
+    "\n");
+
+  // Close up namespace.
+  GenerateNamespaceClosers(printer);
+
+  // We need to specialize some templates in the ::google::protobuf namespace:
+  GenerateProto2NamespaceEnumSpecializations(printer);
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(global_scope)\n"
+    "\n");
+
+  GenerateBottomHeaderGuard(printer, filename_identifier);
+}
+
+void FileGenerator::GeneratePBHeader(io::Printer* printer,
+                                     const string& info_path) {
+  string filename_identifier =
+      FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
+  GenerateTopHeaderGuard(printer, filename_identifier);
+
+  if (options_.proto_h) {
+    printer->Print("#include \"$basename$.proto.h\"  // IWYU pragma: export\n",
+                   "basename", StripProto(file_->name()));
+  } else {
+    GenerateLibraryIncludes(printer);
+  }
+  GenerateDependencyIncludes(printer);
+  GenerateMetadataPragma(printer, info_path);
+
+  printer->Print(
+    "// @@protoc_insertion_point(includes)\n");
+
+
+
+  // Open namespace.
+  GenerateNamespaceOpeners(printer);
+
+  if (!options_.proto_h) {
+    GenerateGlobalStateFunctionDeclarations(printer);
+    GenerateMessageForwardDeclarations(printer);
+
+    printer->Print("\n");
+
+    GenerateEnumDefinitions(printer);
+
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+
+    GenerateMessageDefinitions(printer);
+
+    printer->Print("\n");
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+
+    GenerateServiceDefinitions(printer);
+
+    GenerateExtensionIdentifiers(printer);
+
+    printer->Print("\n");
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+
+    GenerateInlineFunctionDefinitions(printer);
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(namespace_scope)\n");
+
+  // Close up namespace.
+  GenerateNamespaceClosers(printer);
+
+  if (!options_.proto_h) {
+    // We need to specialize some templates in the ::google::protobuf namespace:
+    GenerateProto2NamespaceEnumSpecializations(printer);
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(global_scope)\n"
+    "\n");
+
+  GenerateBottomHeaderGuard(printer, filename_identifier);
+}
+
+void FileGenerator::GenerateSource(io::Printer* printer) {
+  const bool use_system_include = IsWellKnownMessage(file_);
+  string header =
+      StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
+  printer->Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "// source: $filename$\n"
+    "\n"
+    // The generated code calls accessors that might be deprecated. We don't
+    // want the compiler to warn in generated code.
+    "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
+    "#include $left$$header$$right$\n"
+    "\n"
+    "#include <algorithm>\n"    // for swap()
+    "\n"
+    "#include <google/protobuf/stubs/common.h>\n"
+    "#include <google/protobuf/stubs/port.h>\n"
+    "#include <google/protobuf/stubs/once.h>\n"
+    "#include <google/protobuf/io/coded_stream.h>\n"
+    "#include <google/protobuf/wire_format_lite_inl.h>\n",
+    "filename", file_->name(),
+    "header", header,
+    "left", use_system_include ? "<" : "\"",
+    "right", use_system_include ? ">" : "\"");
+
+  // Unknown fields implementation in lite mode uses StringOutputStream
+  if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
+    printer->Print(
+      "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
+  }
+
+  if (HasDescriptorMethods(file_, options_)) {
+    printer->Print(
+      "#include <google/protobuf/descriptor.h>\n"
+      "#include <google/protobuf/generated_message_reflection.h>\n"
+      "#include <google/protobuf/reflection_ops.h>\n"
+      "#include <google/protobuf/wire_format.h>\n");
+  }
+
+  if (options_.proto_h) {
+    // Use the smaller .proto.h files.
+    for (int i = 0; i < file_->dependency_count(); i++) {
+      const FileDescriptor* dep = file_->dependency(i);
+      const char* extension = ".proto.h";
+      string dependency = StripProto(dep->name()) + extension;
+      printer->Print(
+          "#include \"$dependency$\"\n",
+          "dependency", dependency);
+    }
+  }
+
+  printer->Print(
+    "// @@protoc_insertion_point(includes)\n");
+
+  GenerateNamespaceOpeners(printer);
+
+  if (HasDescriptorMethods(file_, options_)) {
+    printer->Print(
+      "\n"
+      "namespace {\n"
+      "\n");
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateDescriptorDeclarations(printer);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      printer->Print(
+        "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
+        "name", ClassName(file_->enum_type(i), false));
+    }
+
+    if (HasGenericServices(file_, options_)) {
+      for (int i = 0; i < file_->service_count(); i++) {
+        printer->Print(
+          "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
+          "name", file_->service(i)->name());
+      }
+    }
+
+    printer->Print(
+      "\n"
+      "}  // namespace\n"
+      "\n");
+  }
+
+  // Define our externally-visible BuildDescriptors() function.  (For the lite
+  // library, all this does is initialize default instances.)
+  GenerateBuildDescriptors(printer);
+
+  // Generate enums.
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateMethods(printer);
+  }
+
+  // Generate classes.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    if (i == 0 && HasGeneratedMethods(file_, options_)) {
+      printer->Print(
+          "\n"
+          "namespace {\n"
+          "\n"
+          "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
+          "GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {\n"
+          "  GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
+          "}\n"
+          "\n"
+          "}  // namespace\n"
+          "\n");
+    }
+    printer->Print("\n");
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+    message_generators_[i]->GenerateClassMethods(printer);
+
+    printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+    // Generate class inline methods.
+    message_generators_[i]->GenerateInlineMethods(printer,
+                                                  /* is_inline = */ false);
+    printer->Print("#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  }
+
+  if (HasGenericServices(file_, options_)) {
+    // Generate services.
+    for (int i = 0; i < file_->service_count(); i++) {
+      if (i == 0) printer->Print("\n");
+      printer->Print(kThickSeparator);
+      printer->Print("\n");
+      service_generators_[i]->GenerateImplementation(printer);
+    }
+  }
+
+  // Define extensions.
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->GenerateDefinition(printer);
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(namespace_scope)\n");
+
+  GenerateNamespaceClosers(printer);
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(global_scope)\n");
+}
+
+class FileGenerator::ForwardDeclarations {
+ public:
+  ~ForwardDeclarations() {
+    for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
+                                                      end = namespaces_.end();
+         it != end; ++it) {
+      delete it->second;
+    }
+    namespaces_.clear();
+  }
+
+  ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
+    ForwardDeclarations*& ns = namespaces_[ns_name];
+    if (ns == NULL) {
+      ns = new ForwardDeclarations;
+    }
+    return ns;
+  }
+
+  map<string, const Descriptor*>& classes() { return classes_; }
+  map<string, const EnumDescriptor*>& enums() { return enums_; }
+
+  void Print(io::Printer* printer) const {
+    for (map<string, const EnumDescriptor *>::const_iterator
+             it = enums_.begin(),
+             end = enums_.end();
+         it != end; ++it) {
+      printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
+      printer->Annotate("enumname", it->second);
+      printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
+                     it->first);
+    }
+    for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
+                                                         end = classes_.end();
+         it != end; ++it) {
+      printer->Print("class $classname$;\n", "classname", it->first);
+      printer->Annotate("classname", it->second);
+    }
+    for (map<string, ForwardDeclarations *>::const_iterator
+             it = namespaces_.begin(),
+             end = namespaces_.end();
+         it != end; ++it) {
+      printer->Print("namespace $nsname$ {\n",
+                     "nsname", it->first);
+      it->second->Print(printer);
+      printer->Print("}  // namespace $nsname$\n",
+                     "nsname", it->first);
+    }
+  }
+
+
+ private:
+  map<string, ForwardDeclarations*> namespaces_;
+  map<string, const Descriptor*> classes_;
+  map<string, const EnumDescriptor*> enums_;
+};
+
+void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
+  // AddDescriptors() is a file-level procedure which adds the encoded
+  // FileDescriptorProto for this .proto file to the global DescriptorPool for
+  // generated files (DescriptorPool::generated_pool()). It either runs at
+  // static initialization time (by default) or when default_instance() is
+  // called for the first time (in LITE_RUNTIME mode with
+  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
+  // constructs default instances and registers extensions.
+  //
+  // Its sibling, AssignDescriptors(), actually pulls the compiled
+  // FileDescriptor from the DescriptorPool and uses it to populate all of
+  // the global variables which store pointers to the descriptor objects.
+  // It also constructs the reflection objects.  It is called the first time
+  // anyone calls descriptor() or GetReflection() on one of the types defined
+  // in the file.
+
+  // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
+  // and we only use AddDescriptors() to allocate default instances.
+  if (HasDescriptorMethods(file_, options_)) {
+    printer->Print(
+      "\n"
+      "void $assigndescriptorsname$() {\n",
+      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+    printer->Indent();
+
+    // Make sure the file has found its way into the pool.  If a descriptor
+    // is requested *during* static init then AddDescriptors() may not have
+    // been called yet, so we call it manually.  Note that it's fine if
+    // AddDescriptors() is called multiple times.
+    printer->Print(
+      "$adddescriptorsname$();\n",
+      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+
+    // Get the file's descriptor from the pool.
+    printer->Print(
+      "const ::google::protobuf::FileDescriptor* file =\n"
+      "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
+      "    \"$filename$\");\n"
+      // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
+      // being unused when compiling an empty .proto file.
+      "GOOGLE_CHECK(file != NULL);\n",
+      "filename", file_->name());
+
+    // Go through all the stuff defined in this file and generated code to
+    // assign the global descriptor pointers based on the file descriptor.
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    }
+    if (HasGenericServices(file_, options_)) {
+      for (int i = 0; i < file_->service_count(); i++) {
+        service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+      }
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n");
+
+    // ---------------------------------------------------------------
+
+    // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
+    // AssignDescriptors().  All later times, waits for the first call to
+    // complete and then returns.
+    printer->Print(
+      "namespace {\n"
+      "\n"
+      "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+      "inline void protobuf_AssignDescriptorsOnce() {\n"
+      "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
+      "                 &$assigndescriptorsname$);\n"
+      "}\n"
+      "\n",
+      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+
+    // protobuf_RegisterTypes():  Calls
+    // MessageFactory::InternalRegisterGeneratedType() for each message type.
+    printer->Print(
+      "void protobuf_RegisterTypes(const ::std::string&) {\n"
+      "  protobuf_AssignDescriptorsOnce();\n");
+    printer->Indent();
+
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateTypeRegistrations(printer);
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n"
+      "}  // namespace\n");
+  }
+
+  // -----------------------------------------------------------------
+
+  // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
+  printer->Print(
+    "\n"
+    "void $shutdownfilename$() {\n",
+    "shutdownfilename", GlobalShutdownFileName(file_->name()));
+  printer->Indent();
+
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateShutdownCode(printer);
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n\n");
+
+  // -----------------------------------------------------------------
+
+  // Now generate the AddDescriptors() function.
+  PrintHandlingOptionalStaticInitializers(
+      file_, options_, printer,
+      // With static initializers.
+      // Note that we don't need any special synchronization in the following
+      // code
+      // because it is called at static init time before any threads exist.
+      "void $adddescriptorsname$() {\n"
+      "  static bool already_here = false;\n"
+      "  if (already_here) return;\n"
+      "  already_here = true;\n"
+      "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+      "\n",
+      // Without.
+      "void $adddescriptorsname$_impl() {\n"
+      "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+      "\n",
+      // Vars.
+      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+
+  printer->Indent();
+
+  // Call the AddDescriptors() methods for all of our dependencies, to make
+  // sure they get added first.
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    const FileDescriptor* dependency = file_->dependency(i);
+    // Print the namespace prefix for the dependency.
+    string add_desc_name = QualifiedFileLevelSymbol(
+        dependency->package(), GlobalAddDescriptorsName(dependency->name()));
+    // Call its AddDescriptors function.
+    printer->Print(
+      "$name$();\n",
+      "name", add_desc_name);
+  }
+
+  if (HasDescriptorMethods(file_, options_)) {
+    // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
+    // and embed it as a string literal, which is parsed and built into real
+    // descriptors at initialization time.
+    FileDescriptorProto file_proto;
+    file_->CopyTo(&file_proto);
+    string file_data;
+    file_proto.SerializeToString(&file_data);
+
+#ifdef _MSC_VER
+    bool breakdown_large_file = true;
+#else
+    bool breakdown_large_file = false;
+#endif
+    // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
+    // bytes in length". Declare a static array of characters rather than use a
+    // string literal.
+    if (breakdown_large_file && file_data.size() > 65535) {
+      // This has to be explicitly marked as a signed char because the generated
+      // code puts negative values in the array, and sometimes plain char is
+      // unsigned. That implicit narrowing conversion is not allowed in C++11.
+      // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
+      // has details on why.
+      printer->Print(
+          "static const signed char descriptor[] = {\n");
+      printer->Indent();
+
+      // Only write 25 bytes per line.
+      static const int kBytesPerLine = 25;
+      for (int i = 0; i < file_data.size();) {
+          for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
+            printer->Print(
+                "$char$, ",
+                "char", SimpleItoa(file_data[i]));
+          }
+          printer->Print(
+              "\n");
+      }
+
+      printer->Outdent();
+      printer->Print(
+          "};\n");
+
+      printer->Print(
+          "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
+          "size", SimpleItoa(file_data.size()));
+
+    } else {
+      printer->Print(
+        "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
+
+      // Only write 40 bytes per line.
+      static const int kBytesPerLine = 40;
+      for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+        printer->Print("\n  \"$data$\"",
+                       "data",
+                       EscapeTrigraphs(
+                           CEscape(file_data.substr(i, kBytesPerLine))));
+    }
+    printer->Print(
+        ", $size$);\n",
+        "size", SimpleItoa(file_data.size()));
+    }
+
+    // Call MessageFactory::InternalRegisterGeneratedFile().
+    printer->Print(
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
+      "  \"$filename$\", &protobuf_RegisterTypes);\n",
+      "filename", file_->name());
+  }
+
+  // Allocate and initialize default instances.  This can't be done lazily
+  // since default instances are returned by simple accessors and are used with
+  // extensions.  Speaking of which, we also register extensions at this time.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+  }
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->GenerateRegistration(printer);
+  }
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+  }
+
+  printer->Print(
+    "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
+    "shutdownfilename", GlobalShutdownFileName(file_->name()));
+
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  PrintHandlingOptionalStaticInitializers(
+      file_, options_, printer,
+      // With static initializers.
+      "// Force AddDescriptors() to be called at static initialization time.\n"
+      "struct StaticDescriptorInitializer_$filename$ {\n"
+      "  StaticDescriptorInitializer_$filename$() {\n"
+      "    $adddescriptorsname$();\n"
+      "  }\n"
+      "} static_descriptor_initializer_$filename$_;\n",
+      // Without.
+      "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
+      "void $adddescriptorsname$() {\n"
+      "  ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
+      "                 &$adddescriptorsname$_impl);\n"
+      "}\n",
+      // Vars.
+      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
+      FilenameIdentifier(file_->name()));
+}
+
+void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
+  if (package_parts_.size() > 0) printer->Print("\n");
+
+  for (int i = 0; i < package_parts_.size(); i++) {
+    printer->Print("namespace $part$ {\n",
+                   "part", package_parts_[i]);
+  }
+}
+
+void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
+  if (package_parts_.size() > 0) printer->Print("\n");
+
+  for (int i = package_parts_.size() - 1; i >= 0; i--) {
+    printer->Print("}  // namespace $part$\n",
+                   "part", package_parts_[i]);
+  }
+}
+
+void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
+  ForwardDeclarations decls;
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    FileGenerator dependency(file_->dependency(i), options_);
+    dependency.FillForwardDeclarations(&decls);
+  }
+  FillForwardDeclarations(&decls);
+  decls.Print(printer);
+}
+
+void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
+  for (int i = 0; i < file_->public_dependency_count(); i++) {
+    FileGenerator dependency(file_->public_dependency(i), options_);
+    dependency.FillForwardDeclarations(decls);
+  }
+  for (int i = 0; i < package_parts_.size(); i++) {
+    decls = decls->AddOrGetNamespace(package_parts_[i]);
+  }
+  // Generate enum definitions.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
+  }
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    enum_generators_[i]->FillForwardDeclaration(&decls->enums());
+  }
+  // Generate forward declarations of classes.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->FillMessageForwardDeclarations(
+        &decls->classes());
+  }
+}
+
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
+                                           const string& filename_identifier) {
+  // Generate top of header.
+  printer->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n"
+      "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
+      "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+      "\n"
+      "#include <string>\n",
+      "filename", file_->name(), "filename_identifier", filename_identifier);
+  printer->Print("\n");
+}
+
+void FileGenerator::GenerateBottomHeaderGuard(
+    io::Printer* printer, const string& filename_identifier) {
+  printer->Print(
+    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
+    "filename_identifier", filename_identifier);
+}
+
+void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+
+  printer->Print(
+    "#include <google/protobuf/stubs/common.h>\n"
+    "\n");
+
+  // Verify the protobuf library header version is compatible with the protoc
+  // version before going any further.
+  printer->Print(
+    "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
+    "#error This file was generated by a newer version of protoc which is\n"
+    "#error incompatible with your Protocol Buffer headers.  Please update\n"
+    "#error your headers.\n"
+    "#endif\n"
+    "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
+    "#error This file was generated by an older version of protoc which is\n"
+    "#error incompatible with your Protocol Buffer headers.  Please\n"
+    "#error regenerate this file with a newer version of protoc.\n"
+    "#endif\n"
+    "\n",
+    "min_header_version",
+      SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
+    "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
+
+  // OK, it's now safe to #include other files.
+  printer->Print(
+    "#include <google/protobuf/arena.h>\n"
+    "#include <google/protobuf/arenastring.h>\n"
+    "#include <google/protobuf/generated_message_util.h>\n");
+  if (UseUnknownFieldSet(file_, options_)) {
+    printer->Print(
+      "#include <google/protobuf/metadata.h>\n");
+  }
+  if (file_->message_type_count() > 0) {
+    if (HasDescriptorMethods(file_, options_)) {
+      printer->Print(
+        "#include <google/protobuf/message.h>\n");
+    } else {
+      printer->Print(
+        "#include <google/protobuf/message_lite.h>\n");
+    }
+  }
+  printer->Print(
+    "#include <google/protobuf/repeated_field.h>\n"
+    "#include <google/protobuf/extension_set.h>\n");
+  if (HasMapFields(file_)) {
+    printer->Print(
+        "#include <google/protobuf/map.h>\n");
+    if (HasDescriptorMethods(file_, options_)) {
+      printer->Print(
+          "#include <google/protobuf/map_field_inl.h>\n");
+    } else {
+      printer->Print(
+          "#include <google/protobuf/map_field_lite.h>\n");
+    }
+  }
+
+  if (HasEnumDefinitions(file_)) {
+    if (HasDescriptorMethods(file_, options_)) {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_reflection.h>\n");
+    } else {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_util.h>\n");
+    }
+  }
+
+  if (HasGenericServices(file_, options_)) {
+    printer->Print(
+      "#include <google/protobuf/service.h>\n");
+  }
+
+  if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
+    printer->Print(
+      "#include <google/protobuf/unknown_field_set.h>\n");
+  }
+
+
+  if (IsAnyMessage(file_)) {
+    printer->Print(
+      "#include <google/protobuf/any.h>\n");
+  }
+}
+
+void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
+                                           const string& info_path) {
+  if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
+      !options_.annotation_guard_name.empty()) {
+    printer->Print(
+        "#ifdef $guard$\n"
+        "#pragma $pragma$ \"$info_path$\"\n"
+        "#endif  // $guard$\n",
+        "guard", options_.annotation_guard_name, "pragma",
+        options_.annotation_pragma_name, "info_path", info_path);
+  }
+}
+
+void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
+  set<string> public_import_names;
+  for (int i = 0; i < file_->public_dependency_count(); i++) {
+    public_import_names.insert(file_->public_dependency(i)->name());
+  }
+
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
+    const string& name = file_->dependency(i)->name();
+    bool public_import = (public_import_names.count(name) != 0);
+
+
+    printer->Print(
+      "#include $left$$dependency$.pb.h$right$$iwyu$\n",
+      "dependency", StripProto(name),
+      "iwyu", (public_import) ? "  // IWYU pragma: export" : "",
+      "left", use_system_include ? "<" : "\"",
+      "right", use_system_include ? ">" : "\"");
+  }
+}
+
+void FileGenerator::GenerateGlobalStateFunctionDeclarations(
+    io::Printer* printer) {
+  // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
+  // functions, so that we can declare them to be friends of each class.
+  printer->Print(
+    "\n"
+    "// Internal implementation detail -- do not call these.\n"
+    "void $dllexport_decl$$adddescriptorsname$();\n",
+    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
+    "dllexport_decl",
+    options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+
+  printer->Print(
+    // Note that we don't put dllexport_decl on these because they are only
+    // called by the .pb.cc file in which they are defined.
+    "void $assigndescriptorsname$();\n"
+    "void $shutdownfilename$();\n"
+    "\n",
+    "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
+    "shutdownfilename", GlobalShutdownFileName(file_->name()));
+}
+
+void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
+  map<string, const Descriptor*> classes;
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->FillMessageForwardDeclarations(&classes);
+  }
+  for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
+                                                       end = classes.end();
+       it != end; ++it) {
+    printer->Print("class $classname$;\n", "classname", it->first);
+    printer->Annotate("classname", it->second);
+  }
+}
+
+void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
+  // Generate class definitions.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    if (i > 0) {
+      printer->Print("\n");
+      printer->Print(kThinSeparator);
+      printer->Print("\n");
+    }
+    message_generators_[i]->GenerateClassDefinition(printer);
+  }
+}
+
+void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
+  // Generate enum definitions.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateEnumDefinitions(printer);
+  }
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateDefinition(printer);
+  }
+}
+
+void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
+  if (HasGenericServices(file_, options_)) {
+    // Generate service definitions.
+    for (int i = 0; i < file_->service_count(); i++) {
+      if (i > 0) {
+        printer->Print("\n");
+        printer->Print(kThinSeparator);
+        printer->Print("\n");
+      }
+      service_generators_[i]->GenerateDeclarations(printer);
+    }
+
+    printer->Print("\n");
+    printer->Print(kThickSeparator);
+    printer->Print("\n");
+  }
+}
+
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
+  // Declare extension identifiers.
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->GenerateDeclaration(printer);
+  }
+}
+
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
+  // An aside about inline functions in .proto.h mode:
+  //
+  // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
+  // moving much of the inline functions to the .pb.cc file, which can be a
+  // significant performance benefit for compilation time, at the expense
+  // of non-inline function calls.
+  //
+  // However, in .proto.h mode, the definition of the internal dependent
+  // base class must remain in the header, and can never be out-lined. The
+  // dependent base class also needs access to has-bit manipuation
+  // functions, so the has-bit functions must be unconditionally inlined in
+  // proto_h mode.
+  //
+  // This gives us three flavors of functions:
+  //
+  //  1. Functions on the message not used by the internal dependent base
+  //     class: in .proto.h mode, only some functions are defined on the
+  //     message class; others are defined on the dependent base class.
+  //     These are guarded and can be out-lined. These are generated by
+  //     GenerateInlineMethods, and include has_* bit functions in
+  //     non-proto_h mode.
+  //
+  //  2. Functions on the internal dependent base class: these functions
+  //     are dependent on a template parameter, so they always need to
+  //     remain in the header.
+  //
+  //  3. Functions on the message that are used by the dependent base: the
+  //     dependent base class down casts itself to the message
+  //     implementation class to access these functions (the has_* bit
+  //     manipulation functions). Unlike #1, these functions must
+  //     unconditionally remain in the header. These are emitted by
+  //     GenerateDependentInlineMethods, even though they are not actually
+  //     dependent.
+
+  printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  // Generate class inline methods.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    if (i > 0) {
+      printer->Print(kThinSeparator);
+      printer->Print("\n");
+    }
+    message_generators_[i]->GenerateInlineMethods(printer,
+                                                  /* is_inline = */ true);
+  }
+  printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    if (i > 0) {
+      printer->Print(kThinSeparator);
+      printer->Print("\n");
+    }
+    // Methods of the dependent base class must always be inline in the header.
+    message_generators_[i]->GenerateDependentInlineMethods(printer);
+  }
+}
+
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
+    io::Printer* printer) {
+  // Emit GetEnumDescriptor specializations into google::protobuf namespace:
+  if (HasEnumDefinitions(file_)) {
+    // The SWIG conditional is to avoid a null-pointer dereference
+    // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
+    //   namespace X { void Y<Z::W>(); }
+    // which appears in GetEnumDescriptor() specializations.
+    printer->Print(
+        "\n"
+        "#ifndef SWIG\n"
+        "namespace google {\nnamespace protobuf {\n"
+        "\n");
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+    }
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+    }
+    printer->Print(
+        "\n"
+        "}  // namespace protobuf\n}  // namespace google\n"
+        "#endif  // SWIG\n");
+  }
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.h
new file mode 100644
index 0000000..5dcf692
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -0,0 +1,164 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+
+namespace google {
+namespace protobuf {
+  class FileDescriptor;        // descriptor.h
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumGenerator;           // enum.h
+class MessageGenerator;        // message.h
+class ServiceGenerator;        // service.h
+class ExtensionGenerator;      // extension.h
+
+class FileGenerator {
+ public:
+  // See generator.cc for the meaning of dllexport_decl.
+  FileGenerator(const FileDescriptor* file, const Options& options);
+  ~FileGenerator();
+
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this proto header.
+  void GenerateProtoHeader(io::Printer* printer,
+                           const string& info_path);
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this PB header.
+  void GeneratePBHeader(io::Printer* printer,
+                        const string& info_path);
+  void GenerateSource(io::Printer* printer);
+
+ private:
+  // Internal type used by GenerateForwardDeclarations (defined in file.cc).
+  class ForwardDeclarations;
+
+  // Generate the BuildDescriptors() procedure, which builds all descriptors
+  // for types defined in the file.
+  void GenerateBuildDescriptors(io::Printer* printer);
+
+  void GenerateNamespaceOpeners(io::Printer* printer);
+  void GenerateNamespaceClosers(io::Printer* printer);
+
+  // For other imports, generates their forward-declarations.
+  void GenerateForwardDeclarations(io::Printer* printer);
+
+  // Internal helper used by GenerateForwardDeclarations: fills 'decls'
+  // with all necessary forward-declarations for this file and its
+  // transient depednencies.
+  void FillForwardDeclarations(ForwardDeclarations* decls);
+
+  // Generates top or bottom of a header file.
+  void GenerateTopHeaderGuard(io::Printer* printer,
+                              const string& filename_identifier);
+  void GenerateBottomHeaderGuard(io::Printer* printer,
+                                 const string& filename_identifier);
+
+  // Generates #include directives.
+  void GenerateLibraryIncludes(io::Printer* printer);
+  void GenerateDependencyIncludes(io::Printer* printer);
+
+  // Generate a pragma to pull in metadata using the given info_path (if
+  // non-empty). info_path should be relative to printer's output.
+  void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
+
+  // Generates a couple of different pieces before definitions:
+  void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
+
+  // Generates types for classes.
+  void GenerateMessageDefinitions(io::Printer* printer);
+
+  // Generates forward-declarations for just this file's classes. This is
+  // used for .pb.h headers, but not in proto_h mode.
+  void GenerateMessageForwardDeclarations(io::Printer* printer);
+
+  // Fills in types for forward declarations. This is used internally, and
+  // also by other FileGenerators to determine imports' declarations.
+  void FillMessageForwardDeclarations(ForwardDeclarations* decls);
+  void FillMessageDefinitions(ForwardDeclarations* decls);
+
+  // Generates enum definitions.
+  void GenerateEnumForwardDeclarations(io::Printer* printer);
+  void FillEnumForwardDeclarations(ForwardDeclarations* decls);
+  void GenerateEnumDefinitions(io::Printer* printer);
+
+  // Generates generic service definitions.
+  void GenerateServiceDefinitions(io::Printer* printer);
+
+  // Generates extension identifiers.
+  void GenerateExtensionIdentifiers(io::Printer* printer);
+
+  // Generates inline function defintions.
+  void GenerateInlineFunctionDefinitions(io::Printer* printer);
+
+  void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
+
+  const FileDescriptor* file_;
+  const Options options_;
+
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> > service_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+
+  // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
+  vector<string> package_parts_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.cc
new file mode 100644
index 0000000..31d189c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -0,0 +1,168 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+
+#include <vector>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <utility>
+
+#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+CppGenerator::CppGenerator() {}
+CppGenerator::~CppGenerator() {}
+
+bool CppGenerator::Generate(const FileDescriptor* file,
+                            const string& parameter,
+                            GeneratorContext* generator_context,
+                            string* error) const {
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
+  // -----------------------------------------------------------------
+  // parse generator options
+
+  // TODO(kenton):  If we ever have more options, we may want to create a
+  //   class that encapsulates them which we can pass down to all the
+  //   generator classes.  Currently we pass dllexport_decl down to all of
+  //   them via the constructors, but we don't want to have to add another
+  //   constructor parameter for every option.
+
+  // If the dllexport_decl option is passed to the compiler, we need to write
+  // it in front of every symbol that should be exported if this .proto is
+  // compiled into a Windows DLL.  E.g., if the user invokes the protocol
+  // compiler as:
+  //   protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto
+  // then we'll define classes like this:
+  //   class FOO_EXPORT Foo {
+  //     ...
+  //   }
+  // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
+  // __declspec(dllimport) depending on what is being compiled.
+  //
+  Options file_options;
+
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "dllexport_decl") {
+      file_options.dllexport_decl = options[i].second;
+    } else if (options[i].first == "safe_boundary_check") {
+      file_options.safe_boundary_check = true;
+    } else if (options[i].first == "annotate_headers") {
+      file_options.annotate_headers = true;
+    } else if (options[i].first == "annotation_pragma_name") {
+      file_options.annotation_pragma_name = options[i].second;
+    } else if (options[i].first == "annotation_guard_name") {
+      file_options.annotation_guard_name = options[i].second;
+    } else if (options[i].first == "lite") {
+      file_options.enforce_lite = true;
+    } else {
+      *error = "Unknown generator option: " + options[i].first;
+      return false;
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+
+  string basename = StripProto(file->name());
+
+  FileGenerator file_generator(file, file_options);
+
+  // Generate header(s).
+  if (file_options.proto_h) {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".proto.h"));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".proto.h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GenerateProtoHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
+  }
+
+  basename.append(".pb");
+  {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".h"));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GeneratePBHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
+  }
+
+  // Generate cc file.
+  {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".cc"));
+    io::Printer printer(output.get(), '$');
+    file_generator.GenerateSource(&printer);
+  }
+
+  return true;
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.h
new file mode 100644
index 0000000..3d517cf
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -0,0 +1,72 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Generates C++ code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// CodeGenerator implementation which generates a C++ source file and
+// header.  If you create your own protocol compiler binary and you want
+// it to support C++ output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator {
+ public:
+  CppGenerator();
+  ~CppGenerator();
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* generator_context,
+                string* error) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.cc
new file mode 100644
index 0000000..2ad4d36
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -0,0 +1,704 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <limits>
+#include <map>
+#include <vector>
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+static const char kAnyMessageName[] = "Any";
+static const char kAnyProtoFile[] = "google/protobuf/any.proto";
+static const char kGoogleProtobufPrefix[] = "google/protobuf/";
+
+string DotsToUnderscores(const string& name) {
+  return StringReplace(name, ".", "_", true);
+}
+
+string DotsToColons(const string& name) {
+  return StringReplace(name, ".", "::", true);
+}
+
+const char* const kKeywordList[] = {
+  "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
+  "bool", "break", "case", "catch", "char", "class", "compl", "const",
+  "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
+  "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
+  "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
+  "mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL",
+  "operator", "or", "or_eq", "private", "protected", "public", "register",
+  "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
+  "static_assert", "static_cast", "struct", "switch", "template", "this",
+  "thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
+  "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
+  "while", "xor", "xor_eq"
+};
+
+hash_set<string> MakeKeywordsMap() {
+  hash_set<string> result;
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) {
+    result.insert(kKeywordList[i]);
+  }
+  return result;
+}
+
+hash_set<string> kKeywords = MakeKeywordsMap();
+
+// Returns whether the provided descriptor has an extension. This includes its
+// nested types.
+bool HasExtension(const Descriptor* descriptor) {
+  if (descriptor->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+    if (HasExtension(descriptor->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
+  string result;
+  // Note:  I distrust ctype.h due to locales.
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      if (cap_next_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      // Capital letters are left as-is.
+      result += input[i];
+      cap_next_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_next_letter = true;
+    } else {
+      cap_next_letter = true;
+    }
+  }
+  return result;
+}
+
+const char kThickSeparator[] =
+  "// ===================================================================\n";
+const char kThinSeparator[] =
+  "// -------------------------------------------------------------------\n";
+
+string ClassName(const Descriptor* descriptor, bool qualified) {
+
+  // Find "outer", the descriptor of the top-level message in which
+  // "descriptor" is embedded.
+  const Descriptor* outer = descriptor;
+  while (outer->containing_type() != NULL) outer = outer->containing_type();
+
+  const string& outer_name = outer->full_name();
+  string inner_name = descriptor->full_name().substr(outer_name.size());
+
+  if (qualified) {
+    return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
+  } else {
+    return outer->name() + DotsToUnderscores(inner_name);
+  }
+}
+
+string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
+  if (enum_descriptor->containing_type() == NULL) {
+    if (qualified) {
+      return "::" + DotsToColons(enum_descriptor->full_name());
+    } else {
+      return enum_descriptor->name();
+    }
+  } else {
+    string result = ClassName(enum_descriptor->containing_type(), qualified);
+    result += '_';
+    result += enum_descriptor->name();
+    return result;
+  }
+}
+
+
+string DependentBaseClassTemplateName(const Descriptor* descriptor) {
+  return ClassName(descriptor, false) + "_InternalBase";
+}
+
+string SuperClassName(const Descriptor* descriptor, const Options& options) {
+  return HasDescriptorMethods(descriptor->file(), options)
+             ? "::google::protobuf::Message"
+             : "::google::protobuf::MessageLite";
+}
+
+string DependentBaseDownCast() {
+  return "reinterpret_cast<T*>(this)->";
+}
+
+string DependentBaseConstDownCast() {
+  return "reinterpret_cast<const T*>(this)->";
+}
+
+string FieldName(const FieldDescriptor* field) {
+  string result = field->name();
+  LowerString(&result);
+  if (kKeywords.count(result) > 0) {
+    result.append("_");
+  }
+  return result;
+}
+
+string EnumValueName(const EnumValueDescriptor* enum_value) {
+  string result = enum_value->name();
+  if (kKeywords.count(result) > 0) {
+    result.append("_");
+  }
+  return result;
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+  string field_name = UnderscoresToCamelCase(field->name(), true);
+  string result = "k" + field_name + "FieldNumber";
+
+  if (!field->is_extension() &&
+      field->containing_type()->FindFieldByCamelcaseName(
+        field->camelcase_name()) != field) {
+    // This field's camelcase name is not unique.  As a hack, add the field
+    // number to the constant name.  This makes the constant rather useless,
+    // but what can we do?
+    result += "_" + SimpleItoa(field->number());
+  }
+
+  return result;
+}
+
+bool IsFieldDependent(const FieldDescriptor* field) {
+  if (field->containing_oneof() != NULL &&
+      field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+    return true;
+  }
+  if (field->is_map()) {
+    const Descriptor* map_descriptor = field->message_type();
+    for (int i = 0; i < map_descriptor->field_count(); i++) {
+      if (IsFieldDependent(map_descriptor->field(i))) {
+        return true;
+      }
+    }
+    return false;
+  }
+  if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    return false;
+  }
+  if (field->containing_oneof() != NULL) {
+    // Oneof fields will always be dependent.
+    //
+    // This is a unique case for field codegen. Field generators are
+    // responsible for generating all the field-specific accessor
+    // functions, except for the clear_*() function; instead, field
+    // generators produce inline clearing code.
+    //
+    // For non-oneof fields, the Message class uses the inline clearing
+    // code to define the field's clear_*() function, as well as in the
+    // destructor. For oneof fields, the Message class generates a much
+    // more complicated clear_*() function, which clears only the oneof
+    // member that is set, in addition to clearing methods for each of the
+    // oneof members individually.
+    //
+    // Since oneofs do not have their own generator class, the Message code
+    // generation logic would be significantly complicated in order to
+    // split dependent and non-dependent manipulation logic based on
+    // whether the oneof truly needs to be dependent; so, for oneof fields,
+    // we just assume it (and its constituents) should be manipulated by a
+    // dependent base class function.
+    //
+    // This is less precise than how dependent message-typed fields are
+    // handled, but the cost is limited to only the generated code for the
+    // oneof field, which seems like an acceptable tradeoff.
+    return true;
+  }
+  if (field->file() == field->message_type()->file()) {
+    return false;
+  }
+  return true;
+}
+
+string DependentTypeName(const FieldDescriptor* field) {
+  return "InternalBase_" + field->name() + "_T";
+}
+
+string FieldMessageTypeName(const FieldDescriptor* field) {
+  // Note:  The Google-internal version of Protocol Buffers uses this function
+  //   as a hook point for hacks to support legacy code.
+  return ClassName(field->message_type(), true);
+}
+
+string StripProto(const string& filename) {
+  if (HasSuffixString(filename, ".protodevel")) {
+    return StripSuffixString(filename, ".protodevel");
+  } else {
+    return StripSuffixString(filename, ".proto");
+  }
+}
+
+const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
+  switch (type) {
+    case FieldDescriptor::CPPTYPE_INT32  : return "::google::protobuf::int32";
+    case FieldDescriptor::CPPTYPE_INT64  : return "::google::protobuf::int64";
+    case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
+    case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
+    case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
+    case FieldDescriptor::CPPTYPE_FLOAT  : return "float";
+    case FieldDescriptor::CPPTYPE_BOOL   : return "bool";
+    case FieldDescriptor::CPPTYPE_ENUM   : return "int";
+    case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
+    case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
+
+    // No default because we want the compiler to complain if any new
+    // CppTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return "Int32";
+    case FieldDescriptor::TYPE_INT64   : return "Int64";
+    case FieldDescriptor::TYPE_UINT32  : return "UInt32";
+    case FieldDescriptor::TYPE_UINT64  : return "UInt64";
+    case FieldDescriptor::TYPE_SINT32  : return "SInt32";
+    case FieldDescriptor::TYPE_SINT64  : return "SInt64";
+    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
+    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
+    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
+    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT   : return "Float";
+    case FieldDescriptor::TYPE_DOUBLE  : return "Double";
+
+    case FieldDescriptor::TYPE_BOOL    : return "Bool";
+    case FieldDescriptor::TYPE_ENUM    : return "Enum";
+
+    case FieldDescriptor::TYPE_STRING  : return "String";
+    case FieldDescriptor::TYPE_BYTES   : return "Bytes";
+    case FieldDescriptor::TYPE_GROUP   : return "Group";
+    case FieldDescriptor::TYPE_MESSAGE : return "Message";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+string Int32ToString(int number) {
+  // gcc rejects the decimal form of kint32min.
+  if (number == kint32min) {
+    GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error);
+    return "(~0x7fffffff)";
+  } else {
+    return SimpleItoa(number);
+  }
+}
+
+string Int64ToString(int64 number) {
+  // gcc rejects the decimal form of kint64min
+  if (number == kint64min) {
+    // Make sure we are in a 2's complement system.
+    GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff),
+                   kint64min_value_error);
+    return "GOOGLE_LONGLONG(~0x7fffffffffffffff)";
+  }
+  return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
+}
+
+string DefaultValue(const FieldDescriptor* field) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return Int32ToString(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return SimpleItoa(field->default_value_uint32()) + "u";
+    case FieldDescriptor::CPPTYPE_INT64:
+      return Int64ToString(field->default_value_int64());
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = field->default_value_double();
+      if (value == numeric_limits<double>::infinity()) {
+        return "::google::protobuf::internal::Infinity()";
+      } else if (value == -numeric_limits<double>::infinity()) {
+        return "-::google::protobuf::internal::Infinity()";
+      } else if (value != value) {
+        return "::google::protobuf::internal::NaN()";
+      } else {
+        return SimpleDtoa(value);
+      }
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      {
+        float value = field->default_value_float();
+        if (value == numeric_limits<float>::infinity()) {
+          return "static_cast<float>(::google::protobuf::internal::Infinity())";
+        } else if (value == -numeric_limits<float>::infinity()) {
+          return "static_cast<float>(-::google::protobuf::internal::Infinity())";
+        } else if (value != value) {
+          return "static_cast<float>(::google::protobuf::internal::NaN())";
+        } else {
+          string float_value = SimpleFtoa(value);
+          // If floating point value contains a period (.) or an exponent
+          // (either E or e), then append suffix 'f' to make it a float
+          // literal.
+          if (float_value.find_first_of(".eE") != string::npos) {
+            float_value.push_back('f');
+          }
+          return float_value;
+        }
+      }
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "true" : "false";
+    case FieldDescriptor::CPPTYPE_ENUM:
+      // Lazy:  Generate a static_cast because we don't have a helper function
+      //   that constructs the full name of an enum value.
+      return strings::Substitute(
+          "static_cast< $0 >($1)",
+          ClassName(field->enum_type(), true),
+          Int32ToString(field->default_value_enum()->number()));
+    case FieldDescriptor::CPPTYPE_STRING:
+      return "\"" + EscapeTrigraphs(
+        CEscape(field->default_value_string())) +
+        "\"";
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return FieldMessageTypeName(field) + "::default_instance()";
+  }
+  // Can't actually get here; make compiler happy.  (We could add a default
+  // case above but then we wouldn't get the nice compiler warning when a
+  // new type is added.)
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+// Convert a file name into a valid identifier.
+string FilenameIdentifier(const string& filename) {
+  string result;
+  for (int i = 0; i < filename.size(); i++) {
+    if (ascii_isalnum(filename[i])) {
+      result.push_back(filename[i]);
+    } else {
+      // Not alphanumeric.  To avoid any possibility of name conflicts we
+      // use the hex code for the character.
+      StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
+    }
+  }
+  return result;
+}
+
+// Return the name of the AddDescriptors() function for a given file.
+string GlobalAddDescriptorsName(const string& filename) {
+  return "protobuf_AddDesc_" + FilenameIdentifier(filename);
+}
+
+// Return the name of the AssignDescriptors() function for a given file.
+string GlobalAssignDescriptorsName(const string& filename) {
+  return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
+}
+
+// Return the name of the ShutdownFile() function for a given file.
+string GlobalShutdownFileName(const string& filename) {
+  return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
+}
+
+// Return the qualified C++ name for a file level symbol.
+string QualifiedFileLevelSymbol(const string& package, const string& name) {
+  if (package.empty()) {
+    return StrCat("::", name);
+  }
+  return StrCat("::", DotsToColons(package), "::", name);
+}
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+  return StringReplace(to_escape, "?", "\\?", true);
+}
+
+// Escaped function name to eliminate naming conflict.
+string SafeFunctionName(const Descriptor* descriptor,
+                        const FieldDescriptor* field,
+                        const string& prefix) {
+  // Do not use FieldName() since it will escape keywords.
+  string name = field->name();
+  LowerString(&name);
+  string function_name = prefix + name;
+  if (descriptor->FindFieldByName(function_name)) {
+    // Single underscore will also make it conflicting with the private data
+    // member. We use double underscore to escape function names.
+    function_name.append("__");
+  } else if (kKeywords.count(name) > 0) {
+    // If the field name is a keyword, we append the underscore back to keep it
+    // consistent with other function names.
+    function_name.append("_");
+  }
+  return function_name;
+}
+
+bool StaticInitializersForced(const FileDescriptor* file,
+                              const Options& options) {
+  if (HasDescriptorMethods(file, options) || file->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    if (HasExtension(file->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void PrintHandlingOptionalStaticInitializers(
+    const FileDescriptor* file, const Options& options, io::Printer* printer,
+    const char* with_static_init, const char* without_static_init,
+    const char* var1, const string& val1, const char* var2,
+    const string& val2) {
+  map<string, string> vars;
+  if (var1) {
+    vars[var1] = val1;
+  }
+  if (var2) {
+    vars[var2] = val2;
+  }
+  PrintHandlingOptionalStaticInitializers(
+      vars, file, options, printer, with_static_init, without_static_init);
+}
+
+void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
+                                             const FileDescriptor* file,
+                                             const Options& options,
+                                             io::Printer* printer,
+                                             const char* with_static_init,
+                                             const char* without_static_init) {
+  if (StaticInitializersForced(file, options)) {
+    printer->Print(vars, with_static_init);
+  } else {
+    printer->Print(vars, (string(
+      "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
+      without_static_init +
+      "#else\n" +
+      with_static_init +
+      "#endif\n").c_str());
+  }
+}
+
+
+static bool HasMapFields(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    if (descriptor->field(i)->is_map()) {
+      return true;
+    }
+  }
+  for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+    if (HasMapFields(descriptor->nested_type(i))) return true;
+  }
+  return false;
+}
+
+bool HasMapFields(const FileDescriptor* file) {
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    if (HasMapFields(file->message_type(i))) return true;
+  }
+  return false;
+}
+
+static bool HasEnumDefinitions(const Descriptor* message_type) {
+  if (message_type->enum_type_count() > 0) return true;
+  for (int i = 0; i < message_type->nested_type_count(); ++i) {
+    if (HasEnumDefinitions(message_type->nested_type(i))) return true;
+  }
+  return false;
+}
+
+bool HasEnumDefinitions(const FileDescriptor* file) {
+  if (file->enum_type_count() > 0) return true;
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    if (HasEnumDefinitions(file->message_type(i))) return true;
+  }
+  return false;
+}
+
+bool IsStringOrMessage(const FieldDescriptor* field) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+    case FieldDescriptor::CPPTYPE_BOOL:
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return false;
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return true;
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
+  GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+  // Open-source protobuf release only supports STRING ctype.
+  return FieldOptions::STRING;
+
+}
+
+bool IsAnyMessage(const FileDescriptor* descriptor) {
+  return descriptor->name() == kAnyProtoFile;
+}
+
+bool IsAnyMessage(const Descriptor* descriptor) {
+  return descriptor->name() == kAnyMessageName &&
+         descriptor->file()->name() == kAnyProtoFile;
+}
+
+bool IsWellKnownMessage(const FileDescriptor* descriptor) {
+  return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix);
+}
+
+enum Utf8CheckMode {
+  STRICT = 0,  // Parsing will fail if non UTF-8 data is in string fields.
+  VERIFY = 1,  // Only log an error but parsing will succeed.
+  NONE = 2,  // No UTF-8 check.
+};
+
+// Which level of UTF-8 enforcemant is placed on this file.
+static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+                                      const Options& options) {
+  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    return STRICT;
+  } else if (GetOptimizeFor(field->file(), options) !=
+             FileOptions::LITE_RUNTIME) {
+    return VERIFY;
+  } else {
+    return NONE;
+  }
+}
+
+static void GenerateUtf8CheckCode(const FieldDescriptor* field,
+                                  const Options& options, bool for_parse,
+                                  const map<string, string>& variables,
+                                  const char* parameters,
+                                  const char* strict_function,
+                                  const char* verify_function,
+                                  io::Printer* printer) {
+  switch (GetUtf8CheckMode(field, options)) {
+    case STRICT: {
+      if (for_parse) {
+        printer->Print("DO_(");
+      }
+      printer->Print(
+          "::google::protobuf::internal::WireFormatLite::$function$(\n",
+          "function", strict_function);
+      printer->Indent();
+      printer->Print(variables, parameters);
+      if (for_parse) {
+        printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
+      } else {
+        printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
+      }
+      printer->Print("\"$full_name$\")", "full_name", field->full_name());
+      if (for_parse) {
+        printer->Print(")");
+      }
+      printer->Print(";\n");
+      printer->Outdent();
+      break;
+    }
+    case VERIFY: {
+      printer->Print(
+          "::google::protobuf::internal::WireFormat::$function$(\n",
+          "function", verify_function);
+      printer->Indent();
+      printer->Print(variables, parameters);
+      if (for_parse) {
+        printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
+      } else {
+        printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
+      }
+      printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
+      printer->Outdent();
+      break;
+    }
+    case NONE:
+      break;
+  }
+}
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+                                    const Options& options, bool for_parse,
+                                    const map<string, string>& variables,
+                                    const char* parameters,
+                                    io::Printer* printer) {
+  GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
+                        "VerifyUtf8String", "VerifyUTF8StringNamedField",
+                        printer);
+}
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+                                  const Options& options, bool for_parse,
+                                  const map<string, string>& variables,
+                                  const char* parameters,
+                                  io::Printer* printer) {
+  GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
+                        "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.h
new file mode 100644
index 0000000..018acfc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -0,0 +1,306 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer;
+}
+
+namespace compiler {
+namespace cpp {
+
+// Commonly-used separator comments.  Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+// Returns the non-nested type name for the given type.  If "qualified" is
+// true, prefix the type with the full namespace.  For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the qualified ClassName for Qux would be:
+//   ::foo::bar::Baz_Qux
+// While the non-qualified version would be:
+//   Baz_Qux
+string ClassName(const Descriptor* descriptor, bool qualified);
+string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+
+// Name of the CRTP class template (for use with proto_h).
+// This is a class name, like "ProtoName_InternalBase".
+string DependentBaseClassTemplateName(const Descriptor* descriptor);
+
+// Name of the base class: either the dependent base class (for use with
+// proto_h) or google::protobuf::Message.
+string SuperClassName(const Descriptor* descriptor, const Options& options);
+
+// Returns a string that down-casts from the dependent base class to the
+// derived class.
+string DependentBaseDownCast();
+string DependentBaseConstDownCast();
+
+// Get the (unqualified) name that should be used for this field in C++ code.
+// The name is coerced to lower-case to emulate proto1 behavior.  People
+// should be using lowercase-with-underscores style for proto field names
+// anyway, so normally this just returns field->name().
+string FieldName(const FieldDescriptor* field);
+
+// Get the sanitized name that should be used for the given enum in C++ code.
+string EnumValueName(const EnumValueDescriptor* enum_value);
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+string FieldConstantName(const FieldDescriptor *field);
+
+// Returns the scope where the field was defined (for extensions, this is
+// different from the message type to which the field applies).
+inline const Descriptor* FieldScope(const FieldDescriptor* field) {
+  return field->is_extension() ?
+    field->extension_scope() : field->containing_type();
+}
+
+// Returns true if the given 'field_descriptor' has a message type that is
+// a dependency of the file where the field is defined (i.e., the field
+// type is defined in a different file than the message holding the field).
+//
+// This only applies to Message-typed fields. Enum-typed fields may refer
+// to an enum in a dependency; however, enums are specified and
+// forward-declared with an enum-base, so the definition is not required to
+// manipulate the field value.
+bool IsFieldDependent(const FieldDescriptor* field_descriptor);
+
+// Returns the name that should be used for forcing dependent lookup from a
+// dependent base class.
+string DependentTypeName(const FieldDescriptor* field);
+
+// Returns the fully-qualified type name field->message_type().  Usually this
+// is just ClassName(field->message_type(), true);
+string FieldMessageTypeName(const FieldDescriptor* field);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+LIBPROTOC_EXPORT string StripProto(const string& filename);
+
+// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
+// Note:  non-built-in type names will be qualified, meaning they will start
+// with a ::.  If you are using the type as a template parameter, you will
+// need to insure there is a space between the < and the ::, because the
+// ridiculous C++ standard defines "<:" to be a synonym for "[".
+const char* PrimitiveTypeName(FieldDescriptor::CppType type);
+
+// Get the declared type name in CamelCase format, as is used e.g. for the
+// methods of WireFormat.  For example, TYPE_INT32 becomes "Int32".
+const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
+
+// Return the code that evaluates to the number when compiled.
+string Int32ToString(int number);
+
+// Return the code that evaluates to the number when compiled.
+string Int64ToString(int64 number);
+
+// Get code that evaluates to the field's default value.
+string DefaultValue(const FieldDescriptor* field);
+
+// Convert a file name into a valid identifier.
+string FilenameIdentifier(const string& filename);
+
+// Return the name of the AddDescriptors() function for a given file.
+string GlobalAddDescriptorsName(const string& filename);
+
+// Return the name of the AssignDescriptors() function for a given file.
+string GlobalAssignDescriptorsName(const string& filename);
+
+// Return the qualified C++ name for a file level symbol.
+string QualifiedFileLevelSymbol(const string& package, const string& name);
+
+// Return the name of the ShutdownFile() function for a given file.
+string GlobalShutdownFileName(const string& filename);
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape);
+
+// Escaped function name to eliminate naming conflict.
+string SafeFunctionName(const Descriptor* descriptor,
+                        const FieldDescriptor* field,
+                        const string& prefix);
+
+// Returns true if unknown fields are preseved after parsing.
+inline bool PreserveUnknownFields(const Descriptor* message) {
+  return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
+::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+    const FileDescriptor* file, const Options& options);
+
+// If PreserveUnknownFields() is true, determines whether unknown
+// fields will be stored in an UnknownFieldSet or a string.
+// If PreserveUnknownFields() is false, this method will not be
+// used.
+inline bool UseUnknownFieldSet(const FileDescriptor* file,
+                               const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
+}
+
+
+// Does the file have any map fields, necessitating the file to include
+// map_field_inl.h and map.h.
+bool HasMapFields(const FileDescriptor* file);
+
+// Does this file have any enum type definitions?
+bool HasEnumDefinitions(const FileDescriptor* file);
+
+// Does this file have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+inline bool HasGeneratedMethods(const FileDescriptor* file,
+                                const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
+}
+
+// Do message classes in this file have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const FileDescriptor* file,
+                                 const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor* file,
+                               const Options& options) {
+  return file->service_count() > 0 &&
+         GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
+         file->options().cc_generic_services();
+}
+
+// Should we generate a separate, super-optimized code path for serializing to
+// flat arrays?  We don't do this in Lite mode because we'd rather reduce code
+// size.
+inline bool HasFastArraySerialization(const FileDescriptor* file,
+                                      const Options& options) {
+  return GetOptimizeFor(file, options) == FileOptions::SPEED;
+}
+
+// Returns whether we have to generate code with static initializers.
+bool StaticInitializersForced(const FileDescriptor* file,
+                              const Options& options);
+
+// Prints 'with_static_init' if static initializers have to be used for the
+// provided file. Otherwise emits both 'with_static_init' and
+// 'without_static_init' using #ifdef.
+void PrintHandlingOptionalStaticInitializers(
+    const FileDescriptor* file, const Options& options, io::Printer* printer,
+    const char* with_static_init, const char* without_static_init,
+    const char* var1 = NULL, const string& val1 = "", const char* var2 = NULL,
+    const string& val2 = "");
+
+void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
+                                             const FileDescriptor* file,
+                                             const Options& options,
+                                             io::Printer* printer,
+                                             const char* with_static_init,
+                                             const char* without_static_init);
+
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
+// Returns true if the field's CPPTYPE is string or message.
+bool IsStringOrMessage(const FieldDescriptor* field);
+
+// For a string field, returns the effective ctype.  If the actual ctype is
+// not supported, returns the default of STRING.
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
+
+string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
+
+inline bool HasFieldPresence(const FileDescriptor* file) {
+  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns true if 'enum' semantics are such that unknown values are preserved
+// in the enum field itself, rather than going to the UnknownFieldSet.
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool SupportsArenas(const FileDescriptor* file) {
+  return file->options().cc_enable_arenas();
+}
+
+inline bool SupportsArenas(const Descriptor* desc) {
+  return SupportsArenas(desc->file());
+}
+
+inline bool SupportsArenas(const FieldDescriptor* field) {
+  return SupportsArenas(field->file());
+}
+
+bool IsAnyMessage(const FileDescriptor* descriptor);
+bool IsAnyMessage(const Descriptor* descriptor);
+
+bool IsWellKnownMessage(const FileDescriptor* descriptor);
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+                                    const Options& options, bool for_parse,
+                                    const map<string, string>& variables,
+                                    const char* parameters,
+                                    io::Printer* printer);
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+                                  const Options& options, bool for_parse,
+                                  const map<string, string>& variables,
+                                  const char* parameters, io::Printer* printer);
+
+inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+    const FileDescriptor* file, const Options& options) {
+  return options.enforce_lite
+      ? FileOptions::LITE_RUNTIME
+      : file->options().optimize_for();
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.cc
new file mode 100644
index 0000000..f585c31
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -0,0 +1,411 @@
+// 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.
+
+#include <google/protobuf/compiler/cpp/cpp_map_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+bool IsProto3Field(const FieldDescriptor* field_descriptor) {
+  const FileDescriptor* file_descriptor = field_descriptor->file();
+  return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         map<string, string>* variables,
+                         const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  (*variables)["type"] = FieldMessageTypeName(descriptor);
+  (*variables)["stream_writer"] =
+      (*variables)["declared_type"] +
+      (HasFastArraySerialization(descriptor->message_type()->file(), options)
+           ? "MaybeToArray"
+           : "");
+  (*variables)["full_name"] = descriptor->full_name();
+
+  const FieldDescriptor* key =
+      descriptor->message_type()->FindFieldByName("key");
+  const FieldDescriptor* val =
+      descriptor->message_type()->FindFieldByName("value");
+  (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
+  switch (val->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      (*variables)["val_cpp"] = FieldMessageTypeName(val);
+      (*variables)["wrapper"] = "EntryWrapper";
+      break;
+    case FieldDescriptor::CPPTYPE_ENUM:
+      (*variables)["val_cpp"] = ClassName(val->enum_type(), true);
+      (*variables)["wrapper"] = "EnumEntryWrapper";
+      break;
+    default:
+      (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
+      (*variables)["wrapper"] = "EntryWrapper";
+  }
+  (*variables)["key_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(key->type()));
+  (*variables)["val_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(val->type()));
+  (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+
+  if (HasDescriptorMethods(descriptor->file(), options)) {
+    (*variables)["lite"] = "";
+  } else {
+    (*variables)["lite"] = "Lite";
+  }
+
+  if (!IsProto3Field(descriptor) &&
+      val->type() == FieldDescriptor::TYPE_ENUM) {
+    const EnumValueDescriptor* default_value = val->default_value_enum();
+    (*variables)["default_enum_value"] = Int32ToString(default_value->number());
+  } else {
+    (*variables)["default_enum_value"] = "0";
+  }
+}
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Options& options)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
+  SetMessageVariables(descriptor, &variables_, options);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+      "typedef ::google::protobuf::internal::MapEntryLite<\n"
+      "    $key_cpp$, $val_cpp$,\n"
+      "    $key_wire_type$,\n"
+      "    $val_wire_type$,\n"
+      "    $default_enum_value$ >\n"
+      "    $map_classname$;\n"
+      "::google::protobuf::internal::MapField$lite$<\n"
+      "    $key_cpp$, $val_cpp$,\n"
+      "    $key_wire_type$,\n"
+      "    $val_wire_type$,\n"
+      "    $default_enum_value$ > $name$_;\n");
+}
+
+void MapFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "    $name$() const;\n"
+      "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "    mutable_$name$();\n");
+}
+
+void MapFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+      "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "$classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_map:$full_name$)\n"
+      "  return $name$_.GetMap();\n"
+      "}\n"
+      "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "$classname$::mutable_$name$() {\n"
+      "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
+      "  return $name$_.MutableMap();\n"
+      "}\n");
+}
+
+void MapFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+  printer->Print(variables, "$this_message$$name$_.Clear();\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void MapFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+}
+
+void MapFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(variables_,
+        "$name$_.SetAssignDescriptorCallback(\n"
+        "    protobuf_AssignDescriptorsOnce);\n"
+        "$name$_.SetEntryDescriptor(\n"
+        "    &$type$_descriptor_);\n");
+  }
+}
+
+void MapFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  const FieldDescriptor* value_field =
+      descriptor_->message_type()->FindFieldByName("value");
+  printer->Print(variables_,
+      "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
+
+  if (IsProto3Field(descriptor_) ||
+      value_field->type() != FieldDescriptor::TYPE_ENUM) {
+    printer->Print(variables_,
+        "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+        "    input, entry.get()));\n");
+    switch (value_field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()].Swap("
+            "entry->mutable_value());\n");
+        break;
+      case FieldDescriptor::CPPTYPE_ENUM:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()] =\n"
+            "    static_cast< $val_cpp$ >(*entry->mutable_value());\n");
+        break;
+      default:
+        printer->Print(variables_,
+            "(*mutable_$name$())[entry->key()] = *entry->mutable_value();\n");
+        break;
+    }
+  } else {
+    printer->Print(variables_,
+        "{\n"
+        "  ::std::string data;\n"
+        "  DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
+        "  DO_(entry->ParseFromString(data));\n"
+        "  if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
+        "    (*mutable_$name$())[entry->key()] =\n"
+        "        static_cast< $val_cpp$ >(*entry->mutable_value());\n"
+        "  } else {\n");
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
+      printer->Print(variables_,
+          "    mutable_unknown_fields()"
+          "->AddLengthDelimited($number$, data);\n");
+    } else {
+      printer->Print(variables_,
+          "    unknown_fields_stream.WriteVarint32($tag$);\n"
+          "    unknown_fields_stream.WriteVarint32(data.size());\n"
+          "    unknown_fields_stream.WriteString(data);\n");
+    }
+
+
+    printer->Print(variables_,
+        "  }\n"
+        "}\n");
+  }
+
+  const FieldDescriptor* key_field =
+      descriptor_->message_type()->FindFieldByName("key");
+  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        key_field, options_, true, variables_,
+        "entry->key().data(), entry->key().length(),\n", printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(value_field, options_, true, variables_,
+                                   "entry->mutable_value()->data(),\n"
+                                   "entry->mutable_value()->length(),\n",
+                                   printer);
+  }
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "if (entry->GetArena() != NULL) entry.release();\n");
+  }
+}
+
+void MapFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = this->$name$().begin();\n"
+      "      it != this->$name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
+      "        $number$, *entry, output);\n");
+
+  printer->Indent();
+  printer->Indent();
+
+  const FieldDescriptor* key_field =
+      descriptor_->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value_field =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
+                                   "it->first.data(), it->first.length(),\n",
+                                   printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
+                                   "it->second.data(), it->second.length(),\n",
+                                   printer);
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = this->$name$().begin();\n"
+      "      it != this->$name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    target = ::google::protobuf::internal::WireFormatLite::\n"
+      "        Write$declared_type$NoVirtualToArray(\n"
+      "            $number$, *entry, target);\n");
+
+  printer->Indent();
+  printer->Indent();
+
+  const FieldDescriptor* key_field =
+      descriptor_->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value_field =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
+                                   "it->first.data(), it->first.length(),\n",
+                                   printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
+                                   "it->second.data(), it->second.length(),\n",
+                                   printer);
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
+}
+
+void MapFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+      "total_size += $tag_size$ * this->$name$_size();\n"
+      "{\n"
+      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = this->$name$().begin();\n"
+      "      it != this->$name$().end(); ++it) {\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "      entry.release();\n"
+        "    }\n");
+  }
+
+  printer->Print(variables_,
+      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
+      "    total_size += ::google::protobuf::internal::WireFormatLite::\n"
+      "        $declared_type$SizeNoVirtual(*entry);\n"
+      "  }\n");
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+        "    entry.release();\n"
+        "  }\n");
+  }
+
+  printer->Print("}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.h
new file mode 100644
index 0000000..087dcde
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -0,0 +1,76 @@
+// 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_COMPILER_CPP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+  MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+  ~MapFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  const bool dependent_field_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.cc
new file mode 100644
index 0000000..3f8e3b7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -0,0 +1,3798 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <utility>
+#include <vector>
+#include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_enum.h>
+#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/descriptor.pb.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+template <class T>
+void PrintFieldComment(io::Printer* printer, const T* field) {
+  // Print the field's (or oneof's) proto-syntax definition as a comment.
+  // We don't want to print group bodies so we cut off after the first
+  // line.
+  DebugStringOptions options;
+  options.elide_group_body = true;
+  options.elide_oneof_body = true;
+  string def = field->DebugStringWithOptions(options);
+  printer->Print("// $def$\n",
+    "def", def.substr(0, def.find_first_of('\n')));
+}
+
+struct FieldOrderingByNumber {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    return a->number() < b->number();
+  }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+    new const FieldDescriptor*[descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByNumber());
+  return fields;
+}
+
+// Functor for sorting extension ranges by their "start" field number.
+struct ExtensionRangeSorter {
+  bool operator()(const Descriptor::ExtensionRange* left,
+                  const Descriptor::ExtensionRange* right) const {
+    return left->start < right->start;
+  }
+};
+
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
+                                                  const Options& options) {
+  return false;
+}
+
+// Returns true if the message type has any required fields.  If it doesn't,
+// we can optimize out calls to its IsInitialized() method.
+//
+// already_seen is used to avoid checking the same type multiple times
+// (and also to protect against recursion).
+static bool HasRequiredFields(const Descriptor* type, const Options& options,
+                              hash_set<const Descriptor*>* already_seen) {
+  if (already_seen->count(type) > 0) {
+    // Since the first occurrence of a required field causes the whole
+    // function to return true, we can assume that if the type is already
+    // in the cache it didn't have any required fields.
+    return false;
+  }
+  already_seen->insert(type);
+
+  // If the type has extensions, an extension with message type could contain
+  // required fields, so we have to be conservative and assume such an
+  // extension exists.
+  if (type->extension_range_count() > 0) return true;
+
+  for (int i = 0; i < type->field_count(); i++) {
+    const FieldDescriptor* field = type->field(i);
+    if (field->is_required()) {
+      return true;
+    }
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !ShouldIgnoreRequiredFieldCheck(field, options)) {
+      if (HasRequiredFields(field->message_type(), options, already_seen)) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+static bool HasRequiredFields(const Descriptor* type, const Options& options) {
+  hash_set<const Descriptor*> already_seen;
+  return HasRequiredFields(type, options, &already_seen);
+}
+
+// This returns an estimate of the compiler's alignment for the field.  This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules.  The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field) {
+  if (field == NULL) return 0;
+  if (field->is_repeated()) return 8;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return 1;
+
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return 4;
+
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return 8;
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;  // Make compiler happy.
+}
+
+// FieldGroup is just a helper for OptimizePadding below.  It holds a vector of
+// fields that are grouped together because they have compatible alignment, and
+// a preferred location in the final field ordering.
+class FieldGroup {
+ public:
+  FieldGroup()
+      : preferred_location_(0) {}
+
+  // A group with a single field.
+  FieldGroup(float preferred_location, const FieldDescriptor* field)
+      : preferred_location_(preferred_location),
+        fields_(1, field) {}
+
+  // Append the fields in 'other' to this group.
+  void Append(const FieldGroup& other) {
+    if (other.fields_.empty()) {
+      return;
+    }
+    // Preferred location is the average among all the fields, so we weight by
+    // the number of fields on each FieldGroup object.
+    preferred_location_ =
+        (preferred_location_ * fields_.size() +
+         (other.preferred_location_ * other.fields_.size())) /
+        (fields_.size() + other.fields_.size());
+    fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
+  }
+
+  void SetPreferredLocation(float location) { preferred_location_ = location; }
+  const vector<const FieldDescriptor*>& fields() const { return fields_; }
+
+  // FieldGroup objects sort by their preferred location.
+  bool operator<(const FieldGroup& other) const {
+    return preferred_location_ < other.preferred_location_;
+  }
+
+ private:
+  // "preferred_location_" is an estimate of where this group should go in the
+  // final list of fields.  We compute this by taking the average index of each
+  // field in this group in the original ordering of fields.  This is very
+  // approximate, but should put this group close to where its member fields
+  // originally went.
+  float preferred_location_;
+  vector<const FieldDescriptor*> fields_;
+  // We rely on the default copy constructor and operator= so this type can be
+  // used in a vector.
+};
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, the alignment padding is minimized.  We try to do this while keeping
+// each field as close as possible to its original position so that we don't
+// reduce cache locality much for function that access each field in order.
+void OptimizePadding(vector<const FieldDescriptor*>* fields) {
+  // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+  vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
+  for (int i = 0; i < fields->size(); ++i) {
+    switch (EstimateAlignmentSize((*fields)[i])) {
+      case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
+      default:
+        GOOGLE_LOG(FATAL) << "Unknown alignment size.";
+    }
+  }
+
+  // Now group fields aligned to 1 byte into sets of 4, and treat those like a
+  // single field aligned to 4 bytes.
+  for (int i = 0; i < aligned_to_1.size(); i += 4) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
+      field_group.Append(aligned_to_1[j]);
+    }
+    aligned_to_4.push_back(field_group);
+  }
+  // Sort by preferred location to keep fields as close to their original
+  // location as possible.  Using stable_sort ensures that the output is
+  // consistent across runs.
+  std::stable_sort(aligned_to_4.begin(), aligned_to_4.end());
+
+  // Now group fields aligned to 4 bytes (or the 4-field groups created above)
+  // into pairs, and treat those like a single field aligned to 8 bytes.
+  for (int i = 0; i < aligned_to_4.size(); i += 2) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
+      field_group.Append(aligned_to_4[j]);
+    }
+    if (i == aligned_to_4.size() - 1) {
+      // Move incomplete 4-byte block to the end.
+      field_group.SetPreferredLocation(fields->size() + 1);
+    }
+    aligned_to_8.push_back(field_group);
+  }
+  // Sort by preferred location.
+  std::stable_sort(aligned_to_8.begin(), aligned_to_8.end());
+
+  // Now pull out all the FieldDescriptors in order.
+  fields->clear();
+  for (int i = 0; i < aligned_to_8.size(); ++i) {
+    fields->insert(fields->end(),
+                   aligned_to_8[i].fields().begin(),
+                   aligned_to_8[i].fields().end());
+  }
+}
+
+string MessageTypeProtoName(const FieldDescriptor* field) {
+  return field->message_type()->full_name();
+}
+
+// Emits an if-statement with a condition that evaluates to true if |field| is
+// considered non-default (will be sent over the wire), for message types
+// without true field presence. Should only be called if
+// !HasFieldPresence(message_descriptor).
+bool EmitFieldNonDefaultCondition(io::Printer* printer,
+                                  const string& prefix,
+                                  const FieldDescriptor* field) {
+  // Merge and serialize semantics: primitive fields are merged/serialized only
+  // if non-zero (numeric) or non-empty (string).
+  if (!field->is_repeated() && !field->containing_oneof()) {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      printer->Print(
+          "if ($prefix$$name$().size() > 0) {\n",
+          "prefix", prefix,
+          "name", FieldName(field));
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Message fields still have has_$name$() methods.
+      printer->Print(
+          "if ($prefix$has_$name$()) {\n",
+          "prefix", prefix,
+          "name", FieldName(field));
+    } else {
+      printer->Print(
+          "if ($prefix$$name$() != 0) {\n",
+          "prefix", prefix,
+          "name", FieldName(field));
+    }
+    printer->Indent();
+    return true;
+  } else if (field->containing_oneof()) {
+    printer->Print(
+        "if (has_$name$()) {\n",
+        "name", FieldName(field));
+    printer->Indent();
+    return true;
+  }
+  return false;
+}
+
+// Does the given field have a has_$name$() method?
+bool HasHasMethod(const FieldDescriptor* field) {
+  if (HasFieldPresence(field->file())) {
+    // In proto1/proto2, every field has a has_$name$() method.
+    return true;
+  }
+  // For message types without true field presence, only fields with a message
+  // type have a has_$name$() method.
+  return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+}
+
+// Collects map entry message type information.
+void CollectMapInfo(const Descriptor* descriptor,
+                    map<string, string>* variables) {
+  GOOGLE_CHECK(IsMapEntryMessage(descriptor));
+  const FieldDescriptor* key = descriptor->FindFieldByName("key");
+  const FieldDescriptor* val = descriptor->FindFieldByName("value");
+  (*variables)["key"] = PrimitiveTypeName(key->cpp_type());
+  switch (val->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      (*variables)["val"] = FieldMessageTypeName(val);
+      break;
+    case FieldDescriptor::CPPTYPE_ENUM:
+      (*variables)["val"] = ClassName(val->enum_type(), true);
+      break;
+    default:
+      (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
+  }
+  (*variables)["key_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(key->type()));
+  (*variables)["val_wire_type"] =
+      "::google::protobuf::internal::WireFormatLite::TYPE_" +
+      ToUpper(DeclaredTypeMethodName(val->type()));
+}
+
+// Does the given field have a private (internal helper only) has_$name$()
+// method?
+bool HasPrivateHasMethod(const FieldDescriptor* field) {
+  // Only for oneofs in message types with no field presence. has_$name$(),
+  // based on the oneof case, is still useful internally for generated code.
+  return (!HasFieldPresence(field->file()) &&
+          field->containing_oneof() != NULL);
+}
+
+}  // anonymous namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+                                   const Options& options)
+    : descriptor_(descriptor),
+      classname_(ClassName(descriptor, false)),
+      options_(options),
+      field_generators_(descriptor, options),
+      nested_generators_(new google::protobuf::scoped_ptr<
+          MessageGenerator>[descriptor->nested_type_count()]),
+      enum_generators_(
+          new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
+      extension_generators_(new google::protobuf::scoped_ptr<
+          ExtensionGenerator>[descriptor->extension_count()]),
+      use_dependent_base_(false) {
+
+  for (int i = 0; i < descriptor->nested_type_count(); i++) {
+    nested_generators_[i].reset(
+      new MessageGenerator(descriptor->nested_type(i), options));
+  }
+
+  for (int i = 0; i < descriptor->enum_type_count(); i++) {
+    enum_generators_[i].reset(
+      new EnumGenerator(descriptor->enum_type(i), options));
+  }
+
+  for (int i = 0; i < descriptor->extension_count(); i++) {
+    extension_generators_[i].reset(
+      new ExtensionGenerator(descriptor->extension(i), options));
+  }
+
+  num_required_fields_ = 0;
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (descriptor->field(i)->is_required()) {
+      ++num_required_fields_;
+    }
+    if (options.proto_h && IsFieldDependent(descriptor->field(i))) {
+      use_dependent_base_ = true;
+    }
+  }
+  if (options.proto_h && descriptor->oneof_decl_count() > 0) {
+    // Always make oneofs dependent.
+    use_dependent_base_ = true;
+  }
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+void MessageGenerator::
+FillMessageForwardDeclarations(map<string, const Descriptor*>* class_names) {
+  (*class_names)[classname_] = descriptor_;
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need forward declaration. Since map entry
+    // message cannot be a top level class, we just need to avoid calling
+    // GenerateForwardDeclaration here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->FillMessageForwardDeclarations(class_names);
+  }
+}
+
+void MessageGenerator::
+FillEnumForwardDeclarations(map<string, const EnumDescriptor*>* enum_names) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
+  }
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->FillForwardDeclaration(enum_names);
+  }
+}
+
+void MessageGenerator::
+GenerateEnumDefinitions(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateEnumDefinitions(printer);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateDefinition(printer);
+  }
+}
+
+void MessageGenerator::
+GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+  }
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+  }
+}
+
+void MessageGenerator::
+GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    PrintFieldComment(printer, field);
+
+    map<string, string> vars;
+    SetCommonFieldVariables(field, &vars, options_);
+
+    if (use_dependent_base_ && IsFieldDependent(field)) {
+      // If the message is dependent, the inline clear_*() method will need
+      // to delete the message type, so it must be in the dependent base
+      // class. (See also GenerateFieldAccessorDeclarations.)
+      printer->Print(vars, "$deprecated_attr$void clear_$name$();\n");
+    }
+    // Generate type-specific accessor declarations.
+    field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
+    printer->Print("\n");
+  }
+}
+
+void MessageGenerator::
+GenerateFieldAccessorDeclarations(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    PrintFieldComment(printer, field);
+
+    map<string, string> vars;
+    SetCommonFieldVariables(field, &vars, options_);
+    vars["constant_name"] = FieldConstantName(field);
+
+    bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
+    if (dependent_field &&
+        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->is_map()) {
+      // If this field is dependent, the dependent base class determines
+      // the message type from the derived class (which is a template
+      // parameter). This typedef is for that:
+      printer->Print(
+          "private:\n"
+          "typedef $field_type$ $dependent_type$;\n"
+          "public:\n",
+          "field_type", FieldMessageTypeName(field),
+          "dependent_type", DependentTypeName(field));
+    }
+
+    if (field->is_repeated()) {
+      printer->Print(vars, "$deprecated_attr$int $name$_size() const;\n");
+    } else if (HasHasMethod(field)) {
+      printer->Print(vars, "$deprecated_attr$bool has_$name$() const;\n");
+    } else if (HasPrivateHasMethod(field)) {
+      printer->Print(vars,
+          "private:\n"
+          "bool has_$name$() const;\n"
+          "public:\n");
+    }
+
+    if (!dependent_field) {
+      // If this field is dependent, then its clear_() method is in the
+      // depenent base class. (See also GenerateDependentAccessorDeclarations.)
+      printer->Print(vars, "$deprecated_attr$void clear_$name$();\n");
+    }
+    printer->Print(vars,
+                   "$deprecated_attr$static const int $constant_name$ = "
+                   "$number$;\n");
+
+    // Generate type-specific accessor declarations.
+    field_generators_.get(field).GenerateAccessorDeclarations(printer);
+
+    printer->Print("\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    // Generate accessors for extensions.  We just call a macro located in
+    // extension_set.h since the accessors about 80 lines of static code.
+    printer->Print(
+      "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n",
+      "classname", classname_);
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "$camel_oneof_name$Case $oneof_name$_case() const;\n",
+        "camel_oneof_name",
+        UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+  }
+}
+
+void MessageGenerator::
+GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
+  if (!use_dependent_base_) return;
+
+  printer->Print("// $classname$\n\n", "classname",
+                 DependentBaseClassTemplateName(descriptor_));
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    PrintFieldComment(printer, field);
+
+    // These functions are not really dependent: they are part of the
+    // (non-dependent) derived class. However, they need to live outside
+    // any #ifdef guards, so we treat them as if they were dependent.
+    //
+    // See the comment in FileGenerator::GenerateInlineFunctionDefinitions
+    // for a more complete explanation.
+    if (use_dependent_base_ && IsFieldDependent(field)) {
+      map<string, string> vars;
+      SetCommonFieldVariables(field, &vars, options_);
+      vars["inline"] = "inline ";
+      if (field->containing_oneof()) {
+        vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
+        vars["oneof_name"] = field->containing_oneof()->name();
+        vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
+        GenerateOneofMemberHasBits(field, vars, printer);
+      } else if (!field->is_repeated()) {
+        // There will be no header guard, so this always has to be inline.
+        GenerateSingularFieldHasBits(field, vars, printer);
+      }
+      // vars needed for clear_(), which is in the dependent base:
+      // (See also GenerateDependentFieldAccessorDeclarations.)
+      vars["tmpl"] = "template<class T>\n";
+      vars["dependent_classname"] =
+          DependentBaseClassTemplateName(descriptor_) + "<T>";
+      vars["this_message"] = DependentBaseDownCast();
+      vars["this_const_message"] = DependentBaseConstDownCast();
+      GenerateFieldClear(field, vars, printer);
+    }
+
+    // Generate type-specific accessors.
+    field_generators_.get(field)
+        .GenerateDependentInlineAccessorDefinitions(printer);
+
+    printer->Print("\n");
+  }
+
+  // Generate has_$name$() and clear_has_$name$() functions for oneofs
+  // Similar to other has-bits, these must always be in the header if we
+  // are using a dependent base class.
+  GenerateOneofHasBits(printer, true /* is_inline */);
+}
+
+void MessageGenerator::
+GenerateSingularFieldHasBits(const FieldDescriptor* field,
+                             map<string, string> vars,
+                             io::Printer* printer) {
+  if (HasFieldPresence(descriptor_->file())) {
+    // N.B.: without field presence, we do not use has-bits or generate
+    // has_$name$() methods.
+    vars["has_array_index"] = SimpleItoa(field->index() / 32);
+    vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32),
+                                           strings::ZERO_PAD_8));
+    printer->Print(vars,
+      "$inline$"
+      "bool $classname$::has_$name$() const {\n"
+      "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+      "}\n"
+      "$inline$"
+      "void $classname$::set_has_$name$() {\n"
+      "  _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+      "}\n"
+      "$inline$"
+      "void $classname$::clear_has_$name$() {\n"
+      "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+      "}\n");
+  } else {
+    // Message fields have a has_$name$() method.
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      bool is_lazy = false;
+      if (is_lazy) {
+        printer->Print(vars,
+          "$inline$"
+          "bool $classname$::has_$name$() const {\n"
+          "  return !$name$_.IsCleared();\n"
+          "}\n");
+      } else {
+        printer->Print(vars,
+          "$inline$"
+          "bool $classname$::has_$name$() const {\n"
+          "  return !_is_default_instance_ && $name$_ != NULL;\n"
+          "}\n");
+      }
+    }
+  }
+}
+
+void MessageGenerator::
+GenerateOneofHasBits(io::Printer* printer, bool is_inline) {
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    map<string, string> vars;
+    vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    vars["cap_oneof_name"] =
+        ToUpper(descriptor_->oneof_decl(i)->name());
+    vars["classname"] = classname_;
+    vars["inline"] = (is_inline ? "inline " : "");
+    printer->Print(
+        vars,
+        "$inline$"
+        "bool $classname$::has_$oneof_name$() const {\n"
+        "  return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
+        "}\n"
+        "$inline$"
+        "void $classname$::clear_has_$oneof_name$() {\n"
+        "  _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
+        "}\n");
+  }
+}
+
+void MessageGenerator::
+GenerateOneofMemberHasBits(const FieldDescriptor* field,
+                           const map<string, string>& vars,
+                           io::Printer* printer) {
+  // Singular field in a oneof
+  // N.B.: Without field presence, we do not use has-bits or generate
+  // has_$name$() methods, but oneofs still have set_has_$name$().
+  // Oneofs also have has_$name$() but only as a private helper
+  // method, so that generated code is slightly cleaner (vs.  comparing
+  // _oneof_case_[index] against a constant everywhere).
+  printer->Print(vars,
+    "$inline$"
+    "bool $classname$::has_$name$() const {\n"
+    "  return $oneof_name$_case() == k$field_name$;\n"
+    "}\n");
+  printer->Print(vars,
+    "$inline$"
+    "void $classname$::set_has_$name$() {\n"
+    "  _oneof_case_[$oneof_index$] = k$field_name$;\n"
+    "}\n");
+}
+
+void MessageGenerator::
+GenerateFieldClear(const FieldDescriptor* field,
+                   const map<string, string>& vars,
+                   io::Printer* printer) {
+  // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and
+  // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is
+  // set by the Generate*Definitions functions.)
+  printer->Print(vars,
+    "$tmpl$"
+    "$inline$"
+    "void $dependent_classname$::clear_$name$() {\n");
+
+  printer->Indent();
+
+  if (field->containing_oneof()) {
+    // Clear this field only if it is the active field in this oneof,
+    // otherwise ignore
+    printer->Print(vars,
+      "if ($this_message$has_$name$()) {\n");
+    printer->Indent();
+    field_generators_.get(field)
+        .GenerateClearingCode(printer);
+    printer->Print(vars,
+      "$this_message$clear_has_$oneof_name$();\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  } else {
+    field_generators_.get(field)
+        .GenerateClearingCode(printer);
+    if (HasFieldPresence(descriptor_->file())) {
+      if (!field->is_repeated()) {
+        printer->Print(vars,
+                       "$this_message$clear_has_$name$();\n");
+      }
+    }
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
+  printer->Print("// $classname$\n\n", "classname", classname_);
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    PrintFieldComment(printer, field);
+
+    map<string, string> vars;
+    SetCommonFieldVariables(field, &vars, options_);
+    vars["inline"] = is_inline ? "inline " : "";
+    if (use_dependent_base_ && IsFieldDependent(field)) {
+      vars["tmpl"] = "template<class T>\n";
+      vars["dependent_classname"] =
+          DependentBaseClassTemplateName(descriptor_) + "<T>";
+      vars["this_message"] = "reinterpret_cast<T*>(this)->";
+      vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+    } else {
+      vars["tmpl"] = "";
+      vars["dependent_classname"] = vars["classname"];
+      vars["this_message"] = "";
+      vars["this_const_message"] = "";
+    }
+
+    // Generate has_$name$() or $name$_size().
+    if (field->is_repeated()) {
+      printer->Print(vars,
+        "$inline$"
+        "int $classname$::$name$_size() const {\n"
+        "  return $name$_.size();\n"
+        "}\n");
+    } else if (field->containing_oneof()) {
+      vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
+      vars["oneof_name"] = field->containing_oneof()->name();
+      vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
+      if (!use_dependent_base_ || !IsFieldDependent(field)) {
+        GenerateOneofMemberHasBits(field, vars, printer);
+      }
+    } else {
+      // Singular field.
+      if (!use_dependent_base_ || !IsFieldDependent(field)) {
+        GenerateSingularFieldHasBits(field, vars, printer);
+      }
+    }
+
+    if (!use_dependent_base_ || !IsFieldDependent(field)) {
+      GenerateFieldClear(field, vars, printer);
+    }
+
+    // Generate type-specific accessors.
+    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
+                                                                   is_inline);
+
+    printer->Print("\n");
+  }
+
+  if (!use_dependent_base_) {
+    // Generate has_$name$() and clear_has_$name$() functions for oneofs
+    // If we aren't using a dependent base, they can be with the other functions
+    // that are #ifdef-guarded.
+    GenerateOneofHasBits(printer, is_inline);
+  }
+}
+
+// Helper for the code that emits the Clear() method.
+static bool CanClearByZeroing(const FieldDescriptor* field) {
+  if (field->is_repeated() || field->is_extension()) return false;
+  switch (field->cpp_type()) {
+    case internal::WireFormatLite::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() == 0;
+    case internal::WireFormatLite::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case internal::WireFormatLite::CPPTYPE_INT64:
+      return field->default_value_int64() == 0;
+    case internal::WireFormatLite::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case internal::WireFormatLite::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0;
+    case internal::WireFormatLite::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0;
+    case internal::WireFormatLite::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0;
+    case internal::WireFormatLite::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+    default:
+      return false;
+  }
+}
+
+void MessageGenerator::
+GenerateDependentBaseClassDefinition(io::Printer* printer) {
+  if (!use_dependent_base_) {
+    return;
+  }
+
+  map<string, string> vars;
+  vars["classname"] = DependentBaseClassTemplateName(descriptor_);
+  vars["superclass"] = SuperClassName(descriptor_, options_);
+
+  printer->Print(vars,
+    "template <class T>\n"
+    "class $classname$ : public $superclass$ {\n"
+    " public:\n");
+  printer->Indent();
+
+  printer->Print(vars,
+    "$classname$() {}\n"
+    "virtual ~$classname$() {}\n"
+    "\n");
+
+  // Generate dependent accessor methods for all fields.
+  GenerateDependentFieldAccessorDeclarations(printer);
+
+  printer->Outdent();
+  printer->Print("};\n");
+}
+
+void MessageGenerator::
+GenerateClassDefinition(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need class definition. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateClassDefinition here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateClassDefinition(printer);
+    printer->Print("\n");
+    printer->Print(kThinSeparator);
+    printer->Print("\n");
+  }
+
+  if (use_dependent_base_) {
+    GenerateDependentBaseClassDefinition(printer);
+      printer->Print("\n");
+  }
+
+  map<string, string> vars;
+  vars["classname"] = classname_;
+  vars["field_count"] = SimpleItoa(descriptor_->field_count());
+  vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count());
+  if (options_.dllexport_decl.empty()) {
+    vars["dllexport"] = "";
+  } else {
+    vars["dllexport"] = options_.dllexport_decl + " ";
+  }
+  if (use_dependent_base_) {
+    vars["superclass"] =
+        DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
+  } else {
+    vars["superclass"] = SuperClassName(descriptor_, options_);
+  }
+  printer->Print(vars,
+    "class $dllexport$$classname$ : public $superclass$ {\n");
+  printer->Annotate("classname", descriptor_);
+  if (use_dependent_base_) {
+    printer->Print(vars, "  friend class $superclass$;\n");
+  }
+  printer->Print(" public:\n");
+  printer->Indent();
+
+  printer->Print(vars,
+    "$classname$();\n"
+    "virtual ~$classname$();\n"
+    "\n"
+    "$classname$(const $classname$& from);\n"
+    "\n"
+    "inline $classname$& operator=(const $classname$& from) {\n"
+    "  CopyFrom(from);\n"
+    "  return *this;\n"
+    "}\n"
+    "\n");
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
+        "  return _internal_metadata_.unknown_fields();\n"
+        "}\n"
+        "\n"
+        "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
+        "  return _internal_metadata_.mutable_unknown_fields();\n"
+        "}\n"
+        "\n");
+    } else {
+      if (SupportsArenas(descriptor_)) {
+        printer->Print(
+          "inline const ::std::string& unknown_fields() const {\n"
+          "  return _unknown_fields_.Get(\n"
+          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+          "}\n"
+          "\n"
+          "inline ::std::string* mutable_unknown_fields() {\n"
+          "  return _unknown_fields_.Mutable(\n"
+          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+          "      GetArenaNoVirtual());\n"
+          "}\n"
+          "\n");
+      } else {
+        printer->Print(
+          "inline const ::std::string& unknown_fields() const {\n"
+          "  return _unknown_fields_.GetNoArena(\n"
+          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+          "}\n"
+          "\n"
+          "inline ::std::string* mutable_unknown_fields() {\n"
+          "  return _unknown_fields_.MutableNoArena(\n"
+          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+          "}\n"
+          "\n");
+      }
+    }
+  }
+
+  // N.B.: We exclude GetArena() when arena support is disabled, falling back on
+  // MessageLite's implementation which returns NULL rather than generating our
+  // own method which returns NULL, in order to reduce code size.
+  if (SupportsArenas(descriptor_)) {
+    // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a
+    // MessageLite* (e.g., in RepeatedField::AddAllocated()).
+    printer->Print(
+        "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n"
+        "inline void* GetMaybeArenaPointer() const {\n"
+        "  return MaybeArenaPtr();\n"
+        "}\n");
+  }
+
+  // Only generate this member if it's not disabled.
+  if (HasDescriptorMethods(descriptor_->file(), options_) &&
+      !descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(vars,
+      "static const ::google::protobuf::Descriptor* descriptor();\n");
+  }
+
+  printer->Print(vars,
+    "static const $classname$& default_instance();\n"
+    "\n");
+
+  // Generate enum values for every field in oneofs. One list is generated for
+  // each oneof with an additional *_NOT_SET value.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "enum $camel_oneof_name$Case {\n",
+        "camel_oneof_name",
+        UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      printer->Print(
+          "k$field_name$ = $field_number$,\n",
+          "field_name",
+          UnderscoresToCamelCase(
+              descriptor_->oneof_decl(i)->field(j)->name(), true),
+          "field_number",
+          SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number()));
+    }
+    printer->Print(
+        "$cap_oneof_name$_NOT_SET = 0,\n",
+        "cap_oneof_name",
+        ToUpper(descriptor_->oneof_decl(i)->name()));
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "\n");
+  }
+
+  if (!StaticInitializersForced(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
+      "// Returns the internal default instance pointer. This function can\n"
+      "// return NULL thus should not be used by the user. This is intended\n"
+      "// for Protobuf internal code. Please use default_instance() declared\n"
+      "// above instead.\n"
+      "static inline const $classname$* internal_default_instance() {\n"
+      "  return default_instance_;\n"
+      "}\n"
+      "#endif\n"
+      "\n");
+  }
+
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(vars,
+      "void UnsafeArenaSwap($classname$* other);\n");
+  }
+
+  if (IsAnyMessage(descriptor_)) {
+    printer->Print(vars,
+      "// implements Any -----------------------------------------------\n"
+      "\n"
+      "void PackFrom(const ::google::protobuf::Message& message);\n"
+      "void PackFrom(const ::google::protobuf::Message& message,\n"
+      "              const ::std::string& type_url_prefix);\n"
+      "bool UnpackTo(::google::protobuf::Message* message) const;\n"
+      "template<typename T> bool Is() const {\n"
+      "  return _any_metadata_.Is<T>();\n"
+      "}\n"
+      "\n");
+  }
+
+  printer->Print(vars,
+    "GOOGLE_ATTRIBUTE_NOINLINE void Swap($classname$* other);\n"
+    "\n"
+    "// implements Message ----------------------------------------------\n"
+    "\n"
+    "inline $classname$* New() const { return New(NULL); }\n"
+    "\n"
+    "$classname$* New(::google::protobuf::Arena* arena) const;\n");
+
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
+      printer->Print(vars,
+        "void CopyFrom(const ::google::protobuf::Message& from);\n"
+        "void MergeFrom(const ::google::protobuf::Message& from);\n");
+    } else {
+      printer->Print(vars,
+        "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
+    }
+
+    printer->Print(vars,
+      "void CopyFrom(const $classname$& from);\n"
+      "void MergeFrom(const $classname$& from);\n"
+      "void Clear();\n"
+      "bool IsInitialized() const;\n"
+      "\n"
+      "int ByteSize() const;\n"
+      "bool MergePartialFromCodedStream(\n"
+      "    ::google::protobuf::io::CodedInputStream* input);\n"
+      "void SerializeWithCachedSizes(\n"
+      "    ::google::protobuf::io::CodedOutputStream* output) const;\n");
+    // DiscardUnknownFields() is implemented in message.cc using reflections. We
+    // need to implement this function in generated code for messages.
+    if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "void DiscardUnknownFields();\n");
+    }
+    if (HasFastArraySerialization(descriptor_->file(), options_)) {
+      printer->Print(
+        "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
+    }
+  }
+
+  // Check all FieldDescriptors including those in oneofs to estimate
+  // whether ::std::string is likely to be used, and depending on that
+  // estimate, set uses_string_ to true or false.  That contols
+  // whether to force initialization of empty_string_ in SharedCtor().
+  // It's often advantageous to do so to keep "is empty_string_
+  // inited?" code from appearing all over the place.
+  vector<const FieldDescriptor*> descriptors;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    descriptors.push_back(descriptor_->field(i));
+  }
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      descriptors.push_back(descriptor_->oneof_decl(i)->field(j));
+    }
+  }
+  uses_string_ = false;
+  if (PreserveUnknownFields(descriptor_) &&
+      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+    uses_string_ = true;
+  }
+  for (int i = 0; i < descriptors.size(); i++) {
+    const FieldDescriptor* field = descriptors[i];
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      switch (field->options().ctype()) {
+        default: uses_string_ = true; break;
+      }
+    }
+  }
+
+  printer->Print(
+    "int GetCachedSize() const { return _cached_size_; }\n"
+    "private:\n"
+    "void SharedCtor();\n"
+    "void SharedDtor();\n"
+    "void SetCachedSize(int size) const;\n"
+    "void InternalSwap($classname$* other);\n",
+    "classname", classname_);
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(
+      "protected:\n"
+      "explicit $classname$(::google::protobuf::Arena* arena);\n"
+      "private:\n"
+      "static void ArenaDtor(void* object);\n"
+      "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n",
+      "classname", classname_);
+  }
+
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+      "private:\n"
+      "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+      "  return _internal_metadata_.arena();\n"
+      "}\n"
+      "inline void* MaybeArenaPtr() const {\n"
+      "  return _internal_metadata_.raw_arena_ptr();\n"
+      "}\n"
+      "public:\n"
+      "\n");
+  } else {
+    printer->Print(
+      "private:\n"
+      "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+      "  return _arena_ptr_;\n"
+      "}\n"
+      "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n"
+      "  return _arena_ptr_;\n"
+      "}\n"
+      "public:\n"
+      "\n");
+  }
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+      "::google::protobuf::Metadata GetMetadata() const;\n"
+      "\n");
+  } else {
+    printer->Print(
+      "::std::string GetTypeName() const;\n"
+      "\n");
+  }
+
+  printer->Print(
+    "// nested types ----------------------------------------------------\n"
+    "\n");
+
+  // Import all nested message classes into this class's scope with typedefs.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    const Descriptor* nested_type = descriptor_->nested_type(i);
+    if (!IsMapEntryMessage(nested_type)) {
+      printer->Print("typedef $nested_full_name$ $nested_name$;\n",
+                     "nested_name", nested_type->name(),
+                     "nested_full_name", ClassName(nested_type, false));
+    }
+  }
+
+  if (descriptor_->nested_type_count() > 0) {
+    printer->Print("\n");
+  }
+
+  // Import all nested enums and their values into this class's scope with
+  // typedefs and constants.
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateSymbolImports(printer);
+    printer->Print("\n");
+  }
+
+  printer->Print(
+    "// accessors -------------------------------------------------------\n"
+    "\n");
+
+  // Generate accessor methods for all fields.
+  GenerateFieldAccessorDeclarations(printer);
+
+  // Declare extension identifiers.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators_[i]->GenerateDeclaration(printer);
+  }
+
+
+  printer->Print(
+    "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  // Generate private members.
+  printer->Outdent();
+  printer->Print(" private:\n");
+  printer->Indent();
+
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->is_repeated()) {
+      // set_has_***() generated in all proto1/2 code and in oneofs (only) for
+      // messages without true field presence.
+      if (HasFieldPresence(descriptor_->file()) ||
+          descriptor_->field(i)->containing_oneof()) {
+        printer->Print(
+          "inline void set_has_$name$();\n",
+          "name", FieldName(descriptor_->field(i)));
+      }
+      // clear_has_***() generated only for non-oneof fields
+      // in proto1/2.
+      if (!descriptor_->field(i)->containing_oneof() &&
+          HasFieldPresence(descriptor_->file())) {
+        printer->Print(
+          "inline void clear_has_$name$();\n",
+          "name", FieldName(descriptor_->field(i)));
+      }
+    }
+  }
+  printer->Print("\n");
+
+  // Generate oneof function declarations
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "inline bool has_$oneof_name$() const;\n"
+        "void clear_$oneof_name$();\n"
+        "inline void clear_has_$oneof_name$();\n\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+  }
+
+  if (HasGeneratedMethods(descriptor_->file(), options_) &&
+      !descriptor_->options().message_set_wire_format() &&
+      num_required_fields_ > 1) {
+    printer->Print(
+        "// helper for ByteSize()\n"
+        "int RequiredFieldsByteSizeFallback() const;\n\n");
+  }
+
+  // Prepare decls for _cached_size_ and _has_bits_.  Their position in the
+  // output will be determined later.
+
+  bool need_to_emit_cached_size = true;
+  // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
+  const string cached_size_decl = "mutable int _cached_size_;\n";
+
+  // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields.
+  size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4;
+  if (descriptor_->field_count() == 0) {
+    // Zero-size arrays aren't technically allowed, and MSVC in particular
+    // doesn't like them.  We still need to declare these arrays to make
+    // other code compile.  Since this is an uncommon case, we'll just declare
+    // them with size 1 and waste some space.  Oh well.
+    sizeof_has_bits = 4;
+  }
+  const string has_bits_decl = sizeof_has_bits == 0 ? "" :
+      "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n";
+
+
+  // To minimize padding, data members are divided into three sections:
+  // (1) members assumed to align to 8 bytes
+  // (2) members corresponding to message fields, re-ordered to optimize
+  //     alignment.
+  // (3) members assumed to align to 4 bytes.
+
+  // Members assumed to align to 8 bytes:
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "::google::protobuf::internal::ExtensionSet _extensions_;\n"
+      "\n");
+  }
+
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+      "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
+  } else {
+    printer->Print(
+      "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n"
+      "::google::protobuf::Arena* _arena_ptr_;\n"
+      "\n");
+  }
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(
+      "friend class ::google::protobuf::Arena;\n"
+      "typedef void InternalArenaConstructable_;\n"
+      "typedef void DestructorSkippable_;\n");
+  }
+
+  if (HasFieldPresence(descriptor_->file())) {
+    // _has_bits_ is frequently accessed, so to reduce code size and improve
+    // speed, it should be close to the start of the object.  But, try not to
+    // waste space:_has_bits_ by itself always makes sense if its size is a
+    // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together
+    // will work well.
+    printer->Print(has_bits_decl.c_str());
+    if ((sizeof_has_bits % 8) != 0) {
+      printer->Print(cached_size_decl.c_str());
+      need_to_emit_cached_size = false;
+    }
+  } else {
+    // Without field presence, we need another way to disambiguate the default
+    // instance, because the default instance's submessage fields (if any) store
+    // pointers to the default instances of the submessages even when they
+    // aren't present. Alternatives to this approach might be to (i) use a
+    // tagged pointer on all message fields, setting a tag bit for "not really
+    // present, just default instance"; or (ii) comparing |this| against the
+    // return value from GeneratedMessageFactory::GetPrototype() in all
+    // has_$field$() calls. However, both of these options are much more
+    // expensive (in code size and CPU overhead) than just checking a field in
+    // the message. Long-term, the best solution would be to rearchitect the
+    // default instance design not to store pointers to submessage default
+    // instances, and have reflection get those some other way; but that change
+    // would have too much impact on proto2.
+    printer->Print(
+      "bool _is_default_instance_;\n");
+  }
+
+  // Field members:
+
+  // List fields which doesn't belong to any oneof
+  vector<const FieldDescriptor*> fields;
+  hash_map<string, int> fieldname_to_chunk;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      fields.push_back(field);
+      fieldname_to_chunk[FieldName(field)] = i / 8;
+    }
+  }
+  OptimizePadding(&fields);
+  // Emit some private and static members
+  runs_of_fields_ = vector< vector<string> >(1);
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    const FieldGenerator& generator = field_generators_.get(field);
+    generator.GenerateStaticMembers(printer);
+    generator.GeneratePrivateMembers(printer);
+    if (CanClearByZeroing(field)) {
+      const string& fieldname = FieldName(field);
+      if (!runs_of_fields_.back().empty() &&
+          (fieldname_to_chunk[runs_of_fields_.back().back()] !=
+           fieldname_to_chunk[fieldname])) {
+        runs_of_fields_.push_back(vector<string>());
+      }
+      runs_of_fields_.back().push_back(fieldname);
+    } else if (!runs_of_fields_.back().empty()) {
+      runs_of_fields_.push_back(vector<string>());
+    }
+  }
+
+  // For each oneof generate a union
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "union $camel_oneof_name$Union {\n"
+        // explicit empty constructor is needed when union contains
+        // ArenaStringPtr members for string fields.
+        "  $camel_oneof_name$Union() {}\n",
+        "camel_oneof_name",
+        UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      field_generators_.get(descriptor_->oneof_decl(i)->
+                            field(j)).GeneratePrivateMembers(printer);
+    }
+    printer->Outdent();
+    printer->Print(
+        "} $oneof_name$_;\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      field_generators_.get(descriptor_->oneof_decl(i)->
+                            field(j)).GenerateStaticMembers(printer);
+    }
+  }
+
+  // Members assumed to align to 4 bytes:
+
+  if (need_to_emit_cached_size) {
+    printer->Print(cached_size_decl.c_str());
+    need_to_emit_cached_size = false;
+  }
+
+  // Generate _oneof_case_.
+  if (descriptor_->oneof_decl_count() > 0) {
+    printer->Print(vars,
+      "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n"
+      "\n");
+  }
+
+  // Generate _any_metadata_ for the Any type.
+  if (IsAnyMessage(descriptor_)) {
+    printer->Print(vars,
+      "::google::protobuf::internal::AnyMetadata _any_metadata_;\n");
+  }
+
+  // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
+  // friends so that they can access private static variables like
+  // default_instance_ and reflection_.
+  PrintHandlingOptionalStaticInitializers(
+      descriptor_->file(), options_, printer,
+      // With static initializers.
+      "friend void $dllexport_decl$ $adddescriptorsname$();\n",
+      // Without.
+      "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
+      // Vars.
+      "dllexport_decl", options_.dllexport_decl, "adddescriptorsname",
+      GlobalAddDescriptorsName(descriptor_->file()->name()));
+
+  printer->Print(
+    "friend void $assigndescriptorsname$();\n"
+    "friend void $shutdownfilename$();\n"
+    "\n",
+    "assigndescriptorsname",
+      GlobalAssignDescriptorsName(descriptor_->file()->name()),
+    "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
+
+  printer->Print(
+    "void InitAsDefaultInstance();\n"
+    "static $classname$* default_instance_;\n",
+    "classname", classname_);
+
+  printer->Outdent();
+  printer->Print(vars, "};");
+  GOOGLE_DCHECK(!need_to_emit_cached_size);
+}
+
+void MessageGenerator::
+GenerateDependentInlineMethods(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need inline methods. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateInlineMethods here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateDependentInlineMethods(printer);
+    printer->Print(kThinSeparator);
+    printer->Print("\n");
+  }
+
+  GenerateDependentFieldAccessorDefinitions(printer);
+}
+
+void MessageGenerator::
+GenerateInlineMethods(io::Printer* printer, bool is_inline) {
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need inline methods. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateInlineMethods here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
+    printer->Print(kThinSeparator);
+    printer->Print("\n");
+  }
+
+  GenerateFieldAccessorDefinitions(printer, is_inline);
+
+  // Generate oneof_case() functions.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    map<string, string> vars;
+    vars["class_name"] = classname_;
+    vars["camel_oneof_name"] = UnderscoresToCamelCase(
+        descriptor_->oneof_decl(i)->name(), true);
+    vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    vars["inline"] = is_inline ? "inline " : "";
+    printer->Print(
+        vars,
+        "$inline$"
+        "$class_name$::$camel_oneof_name$Case $class_name$::"
+        "$oneof_name$_case() const {\n"
+        "  return $class_name$::$camel_oneof_name$Case("
+        "_oneof_case_[$oneof_index$]);\n"
+        "}\n");
+  }
+}
+
+void MessageGenerator::
+GenerateDescriptorDeclarations(io::Printer* printer) {
+  if (!IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
+      "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
+      "  $name$_reflection_ = NULL;\n",
+      "name", classname_);
+  } else {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
+      "name", classname_);
+  }
+
+  // Generate oneof default instance for reflection usage.
+  if (descriptor_->oneof_decl_count() > 0) {
+    printer->Print("struct $name$OneofInstance {\n",
+                   "name", classname_);
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+      for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+        const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+        printer->Print("  ");
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+            (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+             EffectiveStringCType(field) != FieldOptions::STRING)) {
+          printer->Print("const ");
+        }
+        field_generators_.get(field).GeneratePrivateMembers(printer);
+      }
+    }
+
+    printer->Print("}* $name$_default_oneof_instance_ = NULL;\n",
+                   "name", classname_);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateDescriptorDeclarations(printer);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    printer->Print(
+      "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
+      "name", ClassName(descriptor_->enum_type(i), false));
+  }
+}
+
+void MessageGenerator::
+GenerateDescriptorInitializer(io::Printer* printer, int index) {
+  // TODO(kenton):  Passing the index to this method is redundant; just use
+  //   descriptor_->index() instead.
+  map<string, string> vars;
+  vars["classname"] = classname_;
+  vars["index"] = SimpleItoa(index);
+
+  // Obtain the descriptor from the parent's descriptor.
+  if (descriptor_->containing_type() == NULL) {
+    printer->Print(vars,
+      "$classname$_descriptor_ = file->message_type($index$);\n");
+  } else {
+    vars["parent"] = ClassName(descriptor_->containing_type(), false);
+    printer->Print(vars,
+      "$classname$_descriptor_ = "
+        "$parent$_descriptor_->nested_type($index$);\n");
+  }
+
+  if (IsMapEntryMessage(descriptor_)) return;
+
+  // Generate the offsets.
+  GenerateOffsets(printer);
+
+  const bool pass_pool_and_factory = false;
+  vars["fn"] = pass_pool_and_factory ?
+      "new ::google::protobuf::internal::GeneratedMessageReflection" :
+      "::google::protobuf::internal::GeneratedMessageReflection"
+      "::NewGeneratedMessageReflection";
+  // Construct the reflection object.
+  printer->Print(vars,
+    "$classname$_reflection_ =\n"
+    "  $fn$(\n"
+    "    $classname$_descriptor_,\n"
+    "    $classname$::default_instance_,\n"
+    "    $classname$_offsets_,\n");
+  if (!HasFieldPresence(descriptor_->file())) {
+    // If we don't have field presence, then _has_bits_ does not exist.
+    printer->Print(vars,
+    "    -1,\n");
+  } else {
+    printer->Print(vars,
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n");
+  }
+
+  // Unknown field offset: either points to the unknown field set if embedded
+  // directly, or indicates that the unknown field set is stored as part of the
+  // internal metadata if not.
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+    "    -1,\n");
+  } else {
+    printer->Print(vars,
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+      "$classname$, _unknown_fields_),\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(vars,
+      "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+        "$classname$, _extensions_),\n");
+  } else {
+    // No extensions.
+    printer->Print(vars,
+      "    -1,\n");
+  }
+
+  if (descriptor_->oneof_decl_count() > 0) {
+    printer->Print(vars,
+    "    $classname$_default_oneof_instance_,\n"
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+      "$classname$, _oneof_case_[0]),\n");
+  }
+
+  if (pass_pool_and_factory) {
+    printer->Print(
+        "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
+      printer->Print(vars,
+                     "    ::google::protobuf::MessageFactory::generated_factory(),\n");
+  }
+
+  printer->Print(vars,
+    "    sizeof($classname$),\n");
+
+  // Arena offset: either an offset to the metadata struct that contains the
+  // arena pointer and unknown field set (in a space-efficient way) if we use
+  // that implementation strategy, or an offset directly to the arena pointer if
+  // not (because e.g. we don't have an unknown field set).
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+    "$classname$, _internal_metadata_),\n");
+  } else {
+    printer->Print(vars,
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+    "$classname$, _arena_),\n");
+  }
+
+  // is_default_instance_ offset.
+  if (HasFieldPresence(descriptor_->file())) {
+    printer->Print(vars,
+    "    -1);\n");
+  } else {
+    printer->Print(vars,
+    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+    "$classname$, _is_default_instance_));\n");
+  }
+
+  // Handle nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
+  }
+}
+
+void MessageGenerator::
+GenerateTypeRegistrations(io::Printer* printer) {
+  // Register this message type with the message factory.
+  if (!IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
+      "    $classname$_descriptor_, &$classname$::default_instance());\n",
+      "classname", classname_);
+  }
+  else {
+    map<string, string> vars;
+    CollectMapInfo(descriptor_, &vars);
+    vars["classname"] = classname_;
+
+    const FieldDescriptor* val = descriptor_->FindFieldByName("value");
+    if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+        val->type() == FieldDescriptor::TYPE_ENUM) {
+      const EnumValueDescriptor* default_value = val->default_value_enum();
+      vars["default_enum_value"] = Int32ToString(default_value->number());
+    } else {
+      vars["default_enum_value"] = "0";
+    }
+
+    printer->Print(vars,
+      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
+      "      $classname$_descriptor_,\n"
+      "      ::google::protobuf::internal::MapEntry<\n"
+      "          $key$,\n"
+      "          $val$,\n"
+      "          $key_wire_type$,\n"
+      "          $val_wire_type$,\n"
+      "          $default_enum_value$>::CreateDefaultInstance(\n"
+      "              $classname$_descriptor_));\n");
+  }
+
+  // Handle nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateTypeRegistrations(printer);
+  }
+}
+
+void MessageGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) {
+  // Construct the default instances of all fields, as they will be used
+  // when creating the default instance of the entire message.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateDefaultInstanceAllocator(printer);
+  }
+
+  if (IsMapEntryMessage(descriptor_)) return;
+
+  // Construct the default instance.  We can't call InitAsDefaultInstance() yet
+  // because we need to make sure all default instances that this one might
+  // depend on are constructed first.
+  printer->Print(
+    "$classname$::default_instance_ = new $classname$();\n",
+    "classname", classname_);
+
+  if ((descriptor_->oneof_decl_count() > 0) &&
+      HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+    "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
+    "classname", classname_);
+  }
+
+  // Handle nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+  }
+
+}
+
+void MessageGenerator::
+GenerateDefaultInstanceInitializer(io::Printer* printer) {
+  printer->Print(
+    "$classname$::default_instance_->InitAsDefaultInstance();\n",
+    "classname", classname_);
+
+  // Register extensions.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators_[i]->GenerateRegistration(printer);
+  }
+
+  // Handle nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need to initialize default instance manually.
+    // Since map entry message cannot be a top level class, we just need to
+    // avoid calling DefaultInstanceInitializer here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+  }
+}
+
+void MessageGenerator::
+GenerateShutdownCode(io::Printer* printer) {
+  printer->Print(
+    "delete $classname$::default_instance_;\n",
+    "classname", classname_);
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    if (descriptor_->oneof_decl_count() > 0) {
+      printer->Print(
+        "delete $classname$_default_oneof_instance_;\n",
+        "classname", classname_);
+    }
+    printer->Print(
+      "delete $classname$_reflection_;\n",
+      "classname", classname_);
+  }
+
+  // Handle default instances of fields.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateShutdownCode(printer);
+  }
+
+  // Handle nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateShutdownCode(printer);
+  }
+}
+
+void MessageGenerator::
+GenerateClassMethods(io::Printer* printer) {
+  // mutable_unknown_fields wrapper function for LazyStringOutputStream
+  // callback.
+  if (PreserveUnknownFields(descriptor_) &&
+      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+        "static ::std::string* MutableUnknownFieldsFor$classname$(\n"
+        "    $classname$* ptr) {\n"
+        "  return ptr->mutable_unknown_fields();\n"
+        "}\n"
+        "\n",
+        "classname", classname_);
+  }
+  if (IsAnyMessage(descriptor_)) {
+    printer->Print(
+      "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
+      "  _any_metadata_.PackFrom(message);\n"
+      "}\n"
+      "\n"
+      "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n"
+      "                           const ::std::string& type_url_prefix) {\n"
+      "  _any_metadata_.PackFrom(message, type_url_prefix);\n"
+      "}\n"
+      "\n"
+      "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
+      "  return _any_metadata_.UnpackTo(message);\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    enum_generators_[i]->GenerateMethods(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // map entry message doesn't need class methods. Since map entry message
+    // cannot be a top level class, we just need to avoid calling
+    // GenerateClassMethods here.
+    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+    nested_generators_[i]->GenerateClassMethods(printer);
+    printer->Print("\n");
+    printer->Print(kThinSeparator);
+    printer->Print("\n");
+  }
+
+  // Generate non-inline field definitions.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateNonInlineAccessorDefinitions(printer);
+  }
+
+  // Generate field number constants.
+  printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor *field = descriptor_->field(i);
+    printer->Print(
+      "const int $classname$::$constant_name$;\n",
+      "classname", ClassName(FieldScope(field), false),
+      "constant_name", FieldConstantName(field));
+  }
+  printer->Print(
+    "#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900\n"
+    "\n");
+
+  // Define extension identifiers.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators_[i]->GenerateDefinition(printer);
+  }
+
+  GenerateStructors(printer);
+  printer->Print("\n");
+
+  if (descriptor_->oneof_decl_count() > 0) {
+    GenerateOneofClear(printer);
+    printer->Print("\n");
+  }
+
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    GenerateClear(printer);
+    printer->Print("\n");
+
+    GenerateMergeFromCodedStream(printer);
+    printer->Print("\n");
+
+    GenerateSerializeWithCachedSizes(printer);
+    printer->Print("\n");
+
+    if (HasFastArraySerialization(descriptor_->file(), options_)) {
+      GenerateSerializeWithCachedSizesToArray(printer);
+      printer->Print("\n");
+    }
+
+    GenerateByteSize(printer);
+    printer->Print("\n");
+
+    GenerateMergeFrom(printer);
+    printer->Print("\n");
+
+    GenerateCopyFrom(printer);
+    printer->Print("\n");
+
+    GenerateIsInitialized(printer);
+    printer->Print("\n");
+  }
+
+  GenerateSwap(printer);
+  printer->Print("\n");
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+      "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  ::google::protobuf::Metadata metadata;\n"
+      "  metadata.descriptor = $classname$_descriptor_;\n"
+      "  metadata.reflection = $classname$_reflection_;\n"
+      "  return metadata;\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  } else {
+    printer->Print(
+      "::std::string $classname$::GetTypeName() const {\n"
+      "  return \"$type_name$\";\n"
+      "}\n"
+      "\n",
+      "classname", classname_,
+      "type_name", descriptor_->full_name());
+  }
+
+}
+
+void MessageGenerator::
+GenerateOffsets(io::Printer* printer) {
+  printer->Print("static const int $classname$_offsets_[$field_count$] = {\n",
+                 "classname", classname_, "field_count",
+                 SimpleItoa(std::max(1, descriptor_->field_count() +
+                                            descriptor_->oneof_decl_count())));
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof()) {
+      printer->Print(
+          "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET("
+          "$classname$_default_oneof_instance_, $name$_),\n",
+          "classname", classname_,
+          "name", FieldName(field));
+    } else {
+      printer->Print(
+          "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+                                                 "$name$_),\n",
+          "classname", classname_,
+          "name", FieldName(field));
+    }
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    printer->Print(
+      "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
+      "classname", classname_,
+      "name", oneof->name());
+  }
+
+  printer->Outdent();
+  printer->Print("};\n");
+}
+
+void MessageGenerator::
+GenerateSharedConstructorCode(io::Printer* printer) {
+  printer->Print(
+    "void $classname$::SharedCtor() {\n",
+    "classname", classname_);
+  printer->Indent();
+
+  if (!HasFieldPresence(descriptor_->file())) {
+    printer->Print(
+      "  _is_default_instance_ = false;\n");
+  }
+
+  printer->Print(StrCat(
+      uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
+      "_cached_size_ = 0;\n").c_str());
+
+  if (PreserveUnknownFields(descriptor_) &&
+      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+        "_unknown_fields_.UnsafeSetDefault(\n"
+        "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateConstructorCode(printer);
+    }
+  }
+
+  if (HasFieldPresence(descriptor_->file())) {
+    printer->Print(
+      "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "clear_has_$oneof_name$();\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+  }
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void MessageGenerator::
+GenerateSharedDestructorCode(io::Printer* printer) {
+  printer->Print(
+    "void $classname$::SharedDtor() {\n",
+    "classname", classname_);
+  printer->Indent();
+  if (SupportsArenas(descriptor_)) {
+    // Do nothing when the message is allocated in an arena.
+    printer->Print(
+      "if (GetArenaNoVirtual() != NULL) {\n"
+      "  return;\n"
+      "}\n"
+      "\n");
+  }
+
+  // Write the desctructor for _unknown_fields_ in lite runtime.
+  if (PreserveUnknownFields(descriptor_) &&
+      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+    if (SupportsArenas(descriptor_)) {
+      printer->Print(
+          "_unknown_fields_.Destroy(\n"
+          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+          "    GetArenaNoVirtual());\n");
+    } else {
+      printer->Print(
+          "_unknown_fields_.DestroyNoArena(\n"
+          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+    }
+  }
+
+  // Write the destructors for each field except oneof members.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+                       .GenerateDestructorCode(printer);
+    }
+  }
+
+  // Generate code to destruct oneofs. Clearing should do the work.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "if (has_$oneof_name$()) {\n"
+        "  clear_$oneof_name$();\n"
+        "}\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+  }
+
+  PrintHandlingOptionalStaticInitializers(
+      descriptor_->file(), options_, printer,
+      // With static initializers.
+      "if (this != default_instance_) {\n",
+      // Without.
+      "if (this != &default_instance()) {\n");
+
+  // We need to delete all embedded messages.
+  // TODO(kenton):  If we make unset messages point at default instances
+  //   instead of NULL, then it would make sense to move this code into
+  //   MessageFieldGenerator::GenerateDestructorCode().
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (!field->is_repeated() &&
+        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Skip oneof members
+      if (!field->containing_oneof()) {
+        printer->Print(
+            "  delete $name$_;\n",
+            "name", FieldName(field));
+      }
+    }
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void MessageGenerator::
+GenerateArenaDestructorCode(io::Printer* printer) {
+  // Generate the ArenaDtor() method. Track whether any fields actually produced
+  // code that needs to be called.
+  printer->Print(
+      "void $classname$::ArenaDtor(void* object) {\n",
+      "classname", classname_);
+  printer->Indent();
+
+  // This code is placed inside a static method, rather than an ordinary one,
+  // since that simplifies Arena's destructor list (ordinary function pointers
+  // rather than member function pointers). _this is the object being
+  // destructed.
+  printer->Print(
+      "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
+      // avoid an "unused variable" warning in case no fields have dtor code.
+      "(void)_this;\n",
+      "classname", classname_);
+
+  bool need_registration = false;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (field_generators_.get(descriptor_->field(i))
+                         .GenerateArenaDestructorCode(printer)) {
+      need_registration = true;
+    }
+  }
+  printer->Outdent();
+  printer->Print(
+      "}\n");
+
+  if (need_registration) {
+    printer->Print(
+        "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+        "  if (arena != NULL) {\n"
+        "    arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
+        "  }\n"
+        "}\n",
+        "classname", classname_);
+  } else {
+    printer->Print(
+        "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+        "}\n",
+        "classname", classname_);
+  }
+}
+
+void MessageGenerator::
+GenerateStructors(io::Printer* printer) {
+  string superclass;
+  if (use_dependent_base_) {
+    superclass =
+        DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
+  } else {
+    superclass = SuperClassName(descriptor_, options_);
+  }
+  string initializer_with_arena = superclass + "()";
+
+  if (descriptor_->extension_range_count() > 0) {
+    initializer_with_arena += ",\n  _extensions_(arena)";
+  }
+
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    initializer_with_arena += ",\n  _internal_metadata_(arena)";
+  } else {
+    initializer_with_arena += ",\n  _arena_ptr_(arena)";
+  }
+
+  // Initialize member variables with arena constructor.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    bool has_arena_constructor = descriptor_->field(i)->is_repeated();
+    if (has_arena_constructor) {
+      initializer_with_arena += string(",\n  ") +
+          FieldName(descriptor_->field(i)) + string("_(arena)");
+    }
+  }
+
+  if (IsAnyMessage(descriptor_)) {
+    initializer_with_arena += ",\n  _any_metadata_(&type_url, &value_)";
+  }
+
+  string initializer_null;
+  initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ?
+    ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)");
+  if (IsAnyMessage(descriptor_)) {
+    initializer_null += ", _any_metadata_(&type_url_, &value_)";
+  }
+
+  printer->Print(
+      "$classname$::$classname$()\n"
+      "  : $superclass$()$initializer$ {\n"
+      "  SharedCtor();\n"
+      "  // @@protoc_insertion_point(constructor:$full_name$)\n"
+      "}\n",
+      "classname", classname_,
+      "superclass", superclass,
+      "full_name", descriptor_->full_name(),
+      "initializer", initializer_null);
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(
+        "\n"
+        "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
+        "  : $initializer$ {\n"
+        "  SharedCtor();\n"
+        "  RegisterArenaDtor(arena);\n"
+        "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
+        "}\n",
+        "initializer", initializer_with_arena,
+        "classname", classname_,
+        "superclass", superclass,
+        "full_name", descriptor_->full_name());
+  }
+
+  printer->Print(
+    "\n"
+    "void $classname$::InitAsDefaultInstance() {\n",
+    "classname", classname_);
+
+  if (!HasFieldPresence(descriptor_->file())) {
+    printer->Print(
+      "  _is_default_instance_ = true;\n");
+  }
+
+  // The default instance needs all of its embedded message pointers
+  // cross-linked to other default instances.  We can't do this initialization
+  // in the constructor because some other default instances may not have been
+  // constructed yet at that time.
+  // TODO(kenton):  Maybe all message fields (even for non-default messages)
+  //   should be initialized to point at default instances rather than NULL?
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (!field->is_repeated() &&
+        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        (field->containing_oneof() == NULL ||
+         HasDescriptorMethods(descriptor_->file(), options_))) {
+      string name;
+      if (field->containing_oneof()) {
+        name = classname_ + "_default_oneof_instance_->";
+      }
+      name += FieldName(field);
+      PrintHandlingOptionalStaticInitializers(
+          descriptor_->file(), options_, printer,
+          // With static initializers.
+          "  $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
+          // Without.
+          "  $name$_ = const_cast< $type$*>(\n"
+          "      $type$::internal_default_instance());\n",
+          // Vars.
+          "name", name, "type", FieldMessageTypeName(field));
+    } else if (field->containing_oneof() &&
+               HasDescriptorMethods(descriptor_->file(), options_)) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateConstructorCode(printer);
+    }
+  }
+  printer->Print(
+    "}\n"
+    "\n");
+
+  // Generate the copy constructor.
+  printer->Print(
+    "$classname$::$classname$(const $classname$& from)\n"
+    "  : $superclass$()",
+    "classname", classname_,
+    "superclass", superclass,
+    "full_name", descriptor_->full_name());
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+        ",\n    _internal_metadata_(NULL)");
+  } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(",\n    _arena_ptr_(NULL)");
+  }
+  if (IsAnyMessage(descriptor_)) {
+    printer->Print(",\n    _any_metadata_(&type_url_, &value_)");
+  }
+  printer->Print(" {\n");
+  printer->Print(
+    "  SharedCtor();\n"
+    "  MergeFrom(from);\n"
+    "  // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
+    "}\n"
+    "\n",
+    "classname", classname_,
+    "superclass", superclass,
+    "full_name", descriptor_->full_name());
+
+  // Generate the shared constructor code.
+  GenerateSharedConstructorCode(printer);
+
+  // Generate the destructor.
+  printer->Print(
+    "$classname$::~$classname$() {\n"
+    "  // @@protoc_insertion_point(destructor:$full_name$)\n"
+    "  SharedDtor();\n"
+    "}\n"
+    "\n",
+    "classname", classname_,
+    "full_name", descriptor_->full_name());
+
+  // Generate the shared destructor code.
+  GenerateSharedDestructorCode(printer);
+
+  // Generate the arena-specific destructor code.
+  if (SupportsArenas(descriptor_)) {
+    GenerateArenaDestructorCode(printer);
+  }
+
+  // Generate SetCachedSize.
+  printer->Print(
+    "void $classname$::SetCachedSize(int size) const {\n"
+    "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+    "  _cached_size_ = size;\n"
+    "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+    "}\n",
+    "classname", classname_);
+
+  // Only generate this member if it's not disabled.
+  if (HasDescriptorMethods(descriptor_->file(), options_) &&
+      !descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(
+      "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
+      "  protobuf_AssignDescriptorsOnce();\n"
+      "  return $classname$_descriptor_;\n"
+      "}\n"
+      "\n",
+      "classname", classname_,
+      "adddescriptorsname",
+      GlobalAddDescriptorsName(descriptor_->file()->name()));
+  }
+
+  printer->Print(
+    "const $classname$& $classname$::default_instance() {\n",
+    "classname", classname_);
+
+  PrintHandlingOptionalStaticInitializers(
+      descriptor_->file(), options_, printer,
+      // With static initializers.
+      "  if (default_instance_ == NULL) $adddescriptorsname$();\n",
+      // Without.
+      "  $adddescriptorsname$();\n",
+      // Vars.
+      "adddescriptorsname",
+      GlobalAddDescriptorsName(descriptor_->file()->name()));
+
+  printer->Print(
+    "  return *default_instance_;\n"
+    "}\n"
+    "\n"
+    "$classname$* $classname$::default_instance_ = NULL;\n"
+    "\n",
+    "classname", classname_);
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(
+      "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+      "  return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
+      "}\n",
+      "classname", classname_);
+  } else {
+    printer->Print(
+      "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+      "  $classname$* n = new $classname$;\n"
+      "  if (arena != NULL) {\n"
+      "    arena->Own(n);\n"
+      "  }\n"
+      "  return n;\n"
+      "}\n",
+      "classname", classname_);
+  }
+
+}
+
+// Return the number of bits set in n, a non-negative integer.
+static int popcnt(uint32 n) {
+  int result = 0;
+  while (n != 0) {
+    result += (n & 1);
+    n = n / 2;
+  }
+  return result;
+}
+
+void MessageGenerator::
+GenerateClear(io::Printer* printer) {
+  printer->Print(
+      "void $classname$::Clear() {\n"
+      "// @@protoc_insertion_point(message_clear_start:$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
+  printer->Indent();
+
+  // Step 1: Extensions
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print("_extensions_.Clear();\n");
+  }
+
+  // Step 2: Everything but extensions, repeateds, unions.
+  // These are handled in chunks of 8.  The first chunk is
+  // the non-extensions-non-repeateds-non-unions in
+  //  descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
+  // and the second chunk is the same for
+  //  descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
+  // etc.
+  set<int> step2_indices;
+  hash_map<string, int> fieldname_to_chunk;
+  hash_map<int, string> memsets_for_chunk;
+  hash_map<int, int> memset_field_count_for_chunk;
+  hash_set<string> handled;  // fields that appear anywhere in memsets_for_chunk
+  hash_map<int, uint32> fields_mask_for_chunk;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_repeated() && !field->containing_oneof()) {
+      step2_indices.insert(i);
+      int chunk = i / 8;
+      fieldname_to_chunk[FieldName(field)] = chunk;
+      fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32);
+    }
+  }
+
+  // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
+  // The generated code uses two macros to help it clear runs of fields:
+  // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
+  // positions of two fields in the Message.
+  // ZR_ zeroes a non-empty range of fields via memset.
+  const char* macros =
+      "#if defined(__clang__)\n"
+      "#define ZR_HELPER_(f) \\\n"
+      "  _Pragma(\"clang diagnostic push\") \\\n"
+      "  _Pragma(\"clang diagnostic ignored \\\"-Winvalid-offsetof\\\"\") \\\n"
+      "  __builtin_offsetof($classname$, f) \\\n"
+      "  _Pragma(\"clang diagnostic pop\")\n"
+      "#else\n"
+      "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
+      "  &reinterpret_cast<$classname$*>(16)->f)\n"
+      "#endif\n\n"
+      "#define ZR_(first, last) do {\\\n"
+      "  ::memset(&first, 0,\\\n"
+      "           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
+      "} while (0)\n\n";
+  for (int i = 0; i < runs_of_fields_.size(); i++) {
+    const vector<string>& run = runs_of_fields_[i];
+    if (run.size() < 2) continue;
+    const string& first_field_name = run[0];
+    const string& last_field_name = run.back();
+    int chunk = fieldname_to_chunk[run[0]];
+    memsets_for_chunk[chunk].append(
+      "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n");
+    for (int j = 0; j < run.size(); j++) {
+      GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]);
+      handled.insert(run[j]);
+    }
+    memset_field_count_for_chunk[chunk] += run.size();
+  }
+  const bool macros_are_needed = handled.size() > 0;
+  if (macros_are_needed) {
+    printer->Outdent();
+    printer->Print(macros,
+                   "classname", classname_);
+    printer->Indent();
+  }
+  // Step 2b: Finish step 2, ignoring fields handled in step 2a.
+  int last_index = -1;
+  bool chunk_block_in_progress = false;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (step2_indices.count(i) == 0) continue;
+    const FieldDescriptor* field = descriptor_->field(i);
+    const string fieldname = FieldName(field);
+    if (i / 8 != last_index / 8 || last_index < 0) {
+      // End previous chunk, if there was one.
+      if (chunk_block_in_progress) {
+        printer->Outdent();
+        printer->Print("}\n");
+        chunk_block_in_progress = false;
+      }
+      // Start chunk.
+      const string& memsets = memsets_for_chunk[i / 8];
+      uint32 mask = fields_mask_for_chunk[i / 8];
+      int count = popcnt(mask);
+      GOOGLE_DCHECK_GE(count, 1);
+      if (count == 1 ||
+          (count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
+        // No "if" here because the chunk is trivial.
+      } else {
+        if (HasFieldPresence(descriptor_->file())) {
+          printer->Print(
+            "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
+            "index", SimpleItoa(i / 8 * 8),
+            "mask", SimpleItoa(mask));
+          printer->Indent();
+          chunk_block_in_progress = true;
+        }
+      }
+      printer->Print(memsets.c_str());
+    }
+    last_index = i;
+    if (handled.count(fieldname) > 0) continue;
+
+    // It's faster to just overwrite primitive types, but we should
+    // only clear strings and messages if they were set.
+    // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
+    bool should_check_bit =
+      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+      field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
+
+    bool have_enclosing_if = false;
+    if (should_check_bit &&
+        // If no field presence, then always clear strings/messages as well.
+        HasFieldPresence(descriptor_->file())) {
+      printer->Print("if (has_$name$()) {\n", "name", fieldname);
+      printer->Indent();
+      have_enclosing_if = true;
+    }
+
+    if (use_dependent_base_ && IsFieldDependent(field)) {
+      printer->Print("clear_$name$();\n", "name", fieldname);
+    } else {
+      field_generators_.get(field).GenerateClearingCode(printer);
+    }
+
+    if (have_enclosing_if) {
+      printer->Outdent();
+      printer->Print("}\n");
+    }
+  }
+
+  if (chunk_block_in_progress) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+  if (macros_are_needed) {
+    printer->Outdent();
+    printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
+    printer->Indent();
+  }
+
+  // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (field->is_repeated()) {
+      if (use_dependent_base_ && IsFieldDependent(field)) {
+        printer->Print("clear_$name$();\n", "name", FieldName(field));
+      } else {
+        field_generators_.get(field).GenerateClearingCode(printer);
+      }
+    }
+  }
+
+  // Step 4: Unions.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "clear_$oneof_name$();\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name());
+  }
+
+  if (HasFieldPresence(descriptor_->file())) {
+    // Step 5: Everything else.
+    printer->Print(
+      "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "if (_internal_metadata_.have_unknown_fields()) {\n"
+        "  mutable_unknown_fields()->Clear();\n"
+        "}\n");
+    } else {
+      if (SupportsArenas(descriptor_)) {
+        printer->Print(
+          "_unknown_fields_.ClearToEmpty(\n"
+          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+          "    GetArenaNoVirtual());\n");
+      } else {
+        printer->Print(
+          "_unknown_fields_.ClearToEmptyNoArena(\n"
+          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+      }
+    }
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateOneofClear(io::Printer* printer) {
+  // Generated function clears the active field and union case (e.g. foo_case_).
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    map<string, string> oneof_vars;
+    oneof_vars["classname"] = classname_;
+    oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
+    oneof_vars["full_name"] = descriptor_->full_name();
+    string message_class;
+
+    printer->Print(oneof_vars,
+                   "void $classname$::clear_$oneofname$() {\n"
+                   "// @@protoc_insertion_point(one_of_clear_start:"
+                   "$full_name$)\n");
+    printer->Indent();
+    printer->Print(oneof_vars,
+        "switch($oneofname$_case()) {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+          "case k$field_name$: {\n",
+          "field_name", UnderscoresToCamelCase(field->name(), true));
+      printer->Indent();
+      // We clear only allocated objects in oneofs
+      if (!IsStringOrMessage(field)) {
+        printer->Print(
+            "// No need to clear\n");
+      } else {
+        field_generators_.get(field).GenerateClearingCode(printer);
+      }
+      printer->Print(
+          "break;\n");
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+    printer->Print(
+        "case $cap_oneof_name$_NOT_SET: {\n"
+        "  break;\n"
+        "}\n",
+        "cap_oneof_name",
+        ToUpper(descriptor_->oneof_decl(i)->name()));
+    printer->Outdent();
+    printer->Print(
+        "}\n"
+        "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
+        "oneof_index", SimpleItoa(i),
+        "cap_oneof_name",
+        ToUpper(descriptor_->oneof_decl(i)->name()));
+    printer->Outdent();
+    printer->Print(
+        "}\n"
+        "\n");
+  }
+}
+
+void MessageGenerator::
+GenerateSwap(io::Printer* printer) {
+  if (SupportsArenas(descriptor_)) {
+    // Generate the Swap member function. This is a lightweight wrapper around
+    // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory
+    // ownership situation: swapping across arenas or between an arena and a
+    // heap requires copying.
+    printer->Print(
+        "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\n"
+        "  if (other == this) return;\n"
+        "  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
+        "    InternalSwap(other);\n"
+        "  } else {\n"
+        "    $classname$ temp;\n"
+        "    temp.MergeFrom(*this);\n"
+        "    CopyFrom(*other);\n"
+        "    other->CopyFrom(temp);\n"
+        "  }\n"
+        "}\n"
+        "void $classname$::UnsafeArenaSwap($classname$* other) {\n"
+        "  if (other == this) return;\n"
+        "  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n"
+        "  InternalSwap(other);\n"
+        "}\n",
+        "classname", classname_);
+  } else {
+    printer->Print(
+        "void $classname$::Swap($classname$* other) {\n"
+        "  if (other == this) return;\n"
+        "  InternalSwap(other);\n"
+        "}\n",
+        "classname", classname_);
+  }
+
+  // Generate the UnsafeArenaSwap member function.
+  printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
+                 "classname", classname_);
+  printer->Indent();
+
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      field_generators_.get(field).GenerateSwappingCode(printer);
+    }
+
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+      printer->Print(
+        "std::swap($oneof_name$_, other->$oneof_name$_);\n"
+        "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
+        "oneof_name", descriptor_->oneof_decl(i)->name(),
+        "i", SimpleItoa(i));
+    }
+
+    if (HasFieldPresence(descriptor_->file())) {
+      for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
+        printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
+                       "i", SimpleItoa(i));
+      }
+    }
+
+    // Ignore PreserveUnknownFields here - always swap internal_metadata as it
+    // may contain more than just unknown fields.
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+          "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+    } else {
+      printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+    }
+
+    printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print("_extensions_.Swap(&other->_extensions_);\n");
+    }
+  } else {
+    printer->Print("GetReflection()->Swap(this, other);");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateMergeFrom(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    // Generate the generalized MergeFrom (aka that which takes in the Message
+    // base class as a parameter).
+    printer->Print(
+        "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
+        "// @@protoc_insertion_point(generalized_merge_from_start:"
+        "$full_name$)\n"
+        "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
+    printer->Indent();
+
+    // Cast the message to the proper type. If we find that the message is
+    // *not* of the proper type, we can still call Merge via the reflection
+    // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
+    // for each message.
+    printer->Print(
+      "const $classname$* source = \n"
+      "    ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
+      "        &from);\n"
+      "if (source == NULL) {\n"
+      "// @@protoc_insertion_point(generalized_merge_from_cast_fail:"
+      "$full_name$)\n"
+      "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
+      "} else {\n"
+      "// @@protoc_insertion_point(generalized_merge_from_cast_success:"
+      "$full_name$)\n"
+      "  MergeFrom(*source);\n"
+      "}\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
+
+    printer->Outdent();
+    printer->Print("}\n\n");
+  } else {
+    // Generate CheckTypeAndMergeFrom().
+    printer->Print(
+      "void $classname$::CheckTypeAndMergeFrom(\n"
+      "    const ::google::protobuf::MessageLite& from) {\n"
+      "  MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
+      "}\n"
+      "\n",
+      "classname", classname_);
+  }
+
+  // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
+  printer->Print(
+      "void $classname$::MergeFrom(const $classname$& from) {\n"
+      "// @@protoc_insertion_point(class_specific_merge_from_start:"
+      "$full_name$)\n"
+      "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
+  printer->Indent();
+
+  // Merge Repeated fields. These fields do not require a
+  // check as we can simply iterate over them.
+  for (int i = 0; i < descriptor_->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (field->is_repeated()) {
+      field_generators_.get(field).GenerateMergingCode(printer);
+    }
+  }
+
+  // Merge oneof fields. Oneof field requires oneof case check.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    printer->Print(
+        "switch (from.$oneofname$_case()) {\n",
+        "oneofname", descriptor_->oneof_decl(i)->name());
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+          "case k$field_name$: {\n",
+          "field_name", UnderscoresToCamelCase(field->name(), true));
+      printer->Indent();
+      field_generators_.get(field).GenerateMergingCode(printer);
+      printer->Print(
+          "break;\n");
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+    printer->Print(
+        "case $cap_oneof_name$_NOT_SET: {\n"
+        "  break;\n"
+        "}\n",
+        "cap_oneof_name",
+        ToUpper(descriptor_->oneof_decl(i)->name()));
+    printer->Outdent();
+    printer->Print(
+        "}\n");
+  }
+
+  // Merge Optional and Required fields (after a _has_bit check).
+  int last_index = -1;
+
+  for (int i = 0; i < descriptor_->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (!field->is_repeated() && !field->containing_oneof()) {
+      if (HasFieldPresence(descriptor_->file())) {
+        // See above in GenerateClear for an explanation of this.
+        if (i / 8 != last_index / 8 || last_index < 0) {
+          if (last_index >= 0) {
+            printer->Outdent();
+            printer->Print("}\n");
+          }
+          printer->Print(
+            "if (from._has_bits_[$index$ / 32] & "
+            "(0xffu << ($index$ % 32))) {\n",
+            "index", SimpleItoa(field->index()));
+          printer->Indent();
+        }
+      }
+
+      last_index = i;
+
+      bool have_enclosing_if = false;
+      if (HasFieldPresence(descriptor_->file())) {
+        printer->Print(
+          "if (from.has_$name$()) {\n",
+          "name", FieldName(field));
+        printer->Indent();
+        have_enclosing_if = true;
+      } else {
+        // Merge semantics without true field presence: primitive fields are
+        // merged only if non-zero (numeric) or non-empty (string).
+        have_enclosing_if = EmitFieldNonDefaultCondition(
+            printer, "from.", field);
+      }
+
+      field_generators_.get(field).GenerateMergingCode(printer);
+
+      if (have_enclosing_if) {
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+  }
+
+  if (HasFieldPresence(descriptor_->file()) &&
+      last_index >= 0) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "if (from._internal_metadata_.have_unknown_fields()) {\n"
+        "  mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
+        "}\n");
+    } else {
+      printer->Print(
+        "if (!from.unknown_fields().empty()) {\n"
+        "  mutable_unknown_fields()->append(from.unknown_fields());\n"
+        "}\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateCopyFrom(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    // Generate the generalized CopyFrom (aka that which takes in the Message
+    // base class as a parameter).
+    printer->Print(
+        "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n"
+        "// @@protoc_insertion_point(generalized_copy_from_start:"
+        "$full_name$)\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
+    printer->Indent();
+
+    printer->Print(
+      "if (&from == this) return;\n"
+      "Clear();\n"
+      "MergeFrom(from);\n");
+
+    printer->Outdent();
+    printer->Print("}\n\n");
+  }
+
+  // Generate the class-specific CopyFrom.
+  printer->Print(
+      "void $classname$::CopyFrom(const $classname$& from) {\n"
+      "// @@protoc_insertion_point(class_specific_copy_from_start:"
+      "$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
+  printer->Indent();
+
+  printer->Print(
+    "if (&from == this) return;\n"
+    "Clear();\n"
+    "MergeFrom(from);\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "bool $classname$::MergePartialFromCodedStream(\n"
+      "    ::google::protobuf::io::CodedInputStream* input) {\n",
+      "classname", classname_);
+
+    PrintHandlingOptionalStaticInitializers(
+        descriptor_->file(), options_, printer,
+        // With static initializers.
+        "  return _extensions_.ParseMessageSet(input, default_instance_,\n"
+        "                                      mutable_unknown_fields());\n",
+        // Without.
+        "  return _extensions_.ParseMessageSet(input, &default_instance(),\n"
+        "                                      mutable_unknown_fields());\n",
+        // Vars.
+        "classname", classname_);
+
+    printer->Print(
+      "}\n");
+    return;
+  }
+
+  printer->Print(
+    "bool $classname$::MergePartialFromCodedStream(\n"
+    "    ::google::protobuf::io::CodedInputStream* input) {\n"
+    "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n"
+    "  ::google::protobuf::uint32 tag;\n",
+    "classname", classname_);
+
+  if (PreserveUnknownFields(descriptor_) &&
+      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+    // Use LazyStringOutputString to avoid initializing unknown fields string
+    // unless it is actually needed. For the same reason, disable eager refresh
+    // on the CodedOutputStream.
+    printer->Print(
+      "  ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
+      "      ::google::protobuf::internal::NewPermanentCallback(\n"
+      "          &MutableUnknownFieldsFor$classname$, this));\n"
+      "  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
+      "      &unknown_fields_string, false);\n",
+      "classname", classname_);
+  }
+
+  printer->Print(
+    "  // @@protoc_insertion_point(parse_start:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Indent();
+  printer->Print("for (;;) {\n");
+  printer->Indent();
+
+  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
+      SortFieldsByNumber(descriptor_));
+  uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
+      WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
+  const int kCutoff0 = 127;               // fits in 1-byte varint
+  const int kCutoff1 = (127 << 7) + 127;  // fits in 2-byte varint
+  printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = "
+                 "input->ReadTagWithCutoff($max$);\n"
+                 "tag = p.first;\n"
+                 "if (!p.second) goto handle_unusual;\n",
+                 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 :
+                                   (maxtag <= kCutoff1 ? kCutoff1 :
+                                    maxtag)));
+  if (descriptor_->field_count() > 0) {
+    // We don't even want to print the switch() if we have no fields because
+    // MSVC dislikes switch() statements that contain only a default value.
+
+    // Note:  If we just switched on the tag rather than the field number, we
+    // could avoid the need for the if() to check the wire type at the beginning
+    // of each case.  However, this is actually a bit slower in practice as it
+    // creates a jump table that is 8x larger and sparser, and meanwhile the
+    // if()s are highly predictable.
+    printer->Print("switch (::google::protobuf::internal::WireFormatLite::"
+                   "GetTagFieldNumber(tag)) {\n");
+
+    printer->Indent();
+
+    // Find repeated messages and groups now, to simplify what follows.
+    hash_set<int> fields_with_parse_loop;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = ordered_fields[i];
+      if (field->is_repeated() &&
+          (field->type() == FieldDescriptor::TYPE_MESSAGE ||
+           field->type() == FieldDescriptor::TYPE_GROUP)) {
+        fields_with_parse_loop.insert(i);
+      }
+    }
+
+    // need_label is true if we generated "goto parse_$name$" while handling the
+    // previous field.
+    bool need_label = false;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = ordered_fields[i];
+      const bool loops = fields_with_parse_loop.count(i) > 0;
+      const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0;
+
+      PrintFieldComment(printer, field);
+
+      printer->Print(
+        "case $number$: {\n",
+        "number", SimpleItoa(field->number()));
+      printer->Indent();
+      const FieldGenerator& field_generator = field_generators_.get(field);
+
+      // Emit code to parse the common, expected case.
+      printer->Print("if (tag == $commontag$) {\n",
+                     "commontag", SimpleItoa(WireFormat::MakeTag(field)));
+
+      if (need_label ||
+          (field->is_repeated() && !field->is_packed() && !loops)) {
+        printer->Print(
+            " parse_$name$:\n",
+            "name", field->name());
+      }
+      if (loops) {
+        printer->Print(
+          "  DO_(input->IncrementRecursionDepth());\n"
+          " parse_loop_$name$:\n",
+          "name", field->name());
+      }
+
+      printer->Indent();
+      if (field->is_packed()) {
+        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+      } else {
+        field_generator.GenerateMergeFromCodedStream(printer);
+      }
+      printer->Outdent();
+
+      // Emit code to parse unexpectedly packed or unpacked values.
+      if (field->is_packed()) {
+        internal::WireFormatLite::WireType wiretype =
+            WireFormat::WireTypeForFieldType(field->type());
+        printer->Print("} else if (tag == $uncommontag$) {\n",
+                       "uncommontag", SimpleItoa(
+                           internal::WireFormatLite::MakeTag(
+                               field->number(), wiretype)));
+        printer->Indent();
+        field_generator.GenerateMergeFromCodedStream(printer);
+        printer->Outdent();
+      } else if (field->is_packable() && !field->is_packed()) {
+        internal::WireFormatLite::WireType wiretype =
+            internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+        printer->Print("} else if (tag == $uncommontag$) {\n",
+                       "uncommontag", SimpleItoa(
+                           internal::WireFormatLite::MakeTag(
+                               field->number(), wiretype)));
+        printer->Indent();
+        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+        printer->Outdent();
+      }
+
+      printer->Print(
+        "} else {\n"
+        "  goto handle_unusual;\n"
+        "}\n");
+
+      // switch() is slow since it can't be predicted well.  Insert some if()s
+      // here that attempt to predict the next tag.
+      // For non-packed repeated fields, expect the same tag again.
+      if (loops) {
+        printer->Print(
+          "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n",
+          "tag", SimpleItoa(WireFormat::MakeTag(field)),
+          "name", field->name());
+      } else if (field->is_repeated() && !field->is_packed()) {
+        printer->Print(
+          "if (input->ExpectTag($tag$)) goto parse_$name$;\n",
+          "tag", SimpleItoa(WireFormat::MakeTag(field)),
+          "name", field->name());
+      }
+
+      // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet?
+      bool emitted_goto_next_tag = false;
+
+      // For repeated messages/groups, we need to decrement recursion depth,
+      // unless the next tag is also for a repeated message/group.
+      if (loops) {
+        if (next_field_loops) {
+          const FieldDescriptor* next_field = ordered_fields[i + 1];
+          printer->Print(
+            "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n",
+            "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+            "next_name", next_field->name());
+          emitted_goto_next_tag = true;
+        }
+        printer->Print(
+          "input->UnsafeDecrementRecursionDepth();\n");
+      }
+
+      // If there are more fields, expect the next one.
+      need_label = false;
+      if (!emitted_goto_next_tag) {
+        if (i + 1 == descriptor_->field_count()) {
+          // Expect EOF.
+          // TODO(kenton):  Expect group end-tag?
+          printer->Print(
+            "if (input->ExpectAtEnd()) goto success;\n");
+        } else {
+          const FieldDescriptor* next_field = ordered_fields[i + 1];
+          printer->Print(
+            "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
+            "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+            "next_name", next_field->name());
+          need_label = true;
+        }
+      }
+
+      printer->Print(
+        "break;\n");
+
+      printer->Outdent();
+      printer->Print("}\n\n");
+    }
+
+    printer->Print("default: {\n");
+    printer->Indent();
+  }
+
+  printer->Outdent();
+  printer->Print("handle_unusual:\n");
+  printer->Indent();
+  // If tag is 0 or an end-group tag then this must be the end of the message.
+  printer->Print(
+    "if (tag == 0 ||\n"
+    "    ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+    "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
+    "  goto success;\n"
+    "}\n");
+
+  // Handle extension ranges.
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "if (");
+    for (int i = 0; i < descriptor_->extension_range_count(); i++) {
+      const Descriptor::ExtensionRange* range =
+        descriptor_->extension_range(i);
+      if (i > 0) printer->Print(" ||\n    ");
+
+      uint32 start_tag = WireFormatLite::MakeTag(
+        range->start, static_cast<WireFormatLite::WireType>(0));
+      uint32 end_tag = WireFormatLite::MakeTag(
+        range->end, static_cast<WireFormatLite::WireType>(0));
+
+      if (range->end > FieldDescriptor::kMaxNumber) {
+        printer->Print(
+          "($start$u <= tag)",
+          "start", SimpleItoa(start_tag));
+      } else {
+        printer->Print(
+          "($start$u <= tag && tag < $end$u)",
+          "start", SimpleItoa(start_tag),
+          "end", SimpleItoa(end_tag));
+      }
+    }
+    printer->Print(") {\n");
+    if (PreserveUnknownFields(descriptor_)) {
+      if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+        PrintHandlingOptionalStaticInitializers(
+            descriptor_->file(), options_, printer,
+            // With static initializers.
+            "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+            "                              mutable_unknown_fields()));\n",
+            // Without.
+            "  DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+            "                              mutable_unknown_fields()));\n");
+      } else {
+        PrintHandlingOptionalStaticInitializers(
+            descriptor_->file(), options_, printer,
+            // With static initializers.
+            "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+            "                              &unknown_fields_stream));\n",
+            // Without.
+            "  DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+            "                              &unknown_fields_stream));\n");
+      }
+    } else {
+      PrintHandlingOptionalStaticInitializers(
+          descriptor_->file(), options_, printer,
+          // With static initializers.
+          "  DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
+          // Without.
+          "  DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
+    }
+    printer->Print(
+      "  continue;\n"
+      "}\n");
+  }
+
+  // We really don't recognize this tag.  Skip it.
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
+        "      input, tag, mutable_unknown_fields()));\n");
+    } else {
+      printer->Print(
+        "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
+        "    input, tag, &unknown_fields_stream));\n");
+    }
+  } else {
+    printer->Print(
+      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
+  }
+
+  if (descriptor_->field_count() > 0) {
+    printer->Print("break;\n");
+    printer->Outdent();
+    printer->Print("}\n");    // default:
+    printer->Outdent();
+    printer->Print("}\n");    // switch
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+    "  }\n"                   // for (;;)
+    "success:\n"
+    "  // @@protoc_insertion_point(parse_success:$full_name$)\n"
+    "  return true;\n"
+    "failure:\n"
+    "  // @@protoc_insertion_point(parse_failure:$full_name$)\n"
+    "  return false;\n"
+    "#undef DO_\n"
+    "}\n", "full_name", descriptor_->full_name());
+}
+
+void MessageGenerator::GenerateSerializeOneField(
+    io::Printer* printer, const FieldDescriptor* field, bool to_array) {
+  PrintFieldComment(printer, field);
+
+  bool have_enclosing_if = false;
+  if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
+    printer->Print(
+      "if (has_$name$()) {\n",
+      "name", FieldName(field));
+    printer->Indent();
+    have_enclosing_if = true;
+  } else if (!HasFieldPresence(descriptor_->file())) {
+    have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
+  }
+
+  if (to_array) {
+    field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
+        printer);
+  } else {
+    field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
+  }
+
+  if (have_enclosing_if) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+  printer->Print("\n");
+}
+
+void MessageGenerator::GenerateSerializeOneExtensionRange(
+    io::Printer* printer, const Descriptor::ExtensionRange* range,
+    bool to_array) {
+  map<string, string> vars;
+  vars["start"] = SimpleItoa(range->start);
+  vars["end"] = SimpleItoa(range->end);
+  printer->Print(vars,
+    "// Extension range [$start$, $end$)\n");
+  if (to_array) {
+    printer->Print(vars,
+      "target = _extensions_.SerializeWithCachedSizesToArray(\n"
+      "    $start$, $end$, target);\n\n");
+  } else {
+    printer->Print(vars,
+      "_extensions_.SerializeWithCachedSizes(\n"
+      "    $start$, $end$, output);\n\n");
+  }
+}
+
+void MessageGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "void $classname$::SerializeWithCachedSizes(\n"
+      "    ::google::protobuf::io::CodedOutputStream* output) const {\n"
+      "  _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
+      "classname", classname_);
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    printer->Print(
+      "  ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
+      "      unknown_fields(), output);\n");
+    printer->Print(
+      "}\n");
+    return;
+  }
+
+  printer->Print(
+    "void $classname$::SerializeWithCachedSizes(\n"
+    "    ::google::protobuf::io::CodedOutputStream* output) const {\n",
+    "classname", classname_);
+  printer->Indent();
+
+  printer->Print(
+    "// @@protoc_insertion_point(serialize_start:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  GenerateSerializeWithCachedSizesBody(printer, false);
+
+  printer->Print(
+    "// @@protoc_insertion_point(serialize_end:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+}
+
+void MessageGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+      "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
+      "    ::google::protobuf::uint8* target) const {\n"
+      "  target =\n"
+      "      _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
+      "classname", classname_);
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    printer->Print(
+      "  target = ::google::protobuf::internal::WireFormat::\n"
+      "             SerializeUnknownMessageSetItemsToArray(\n"
+      "               unknown_fields(), target);\n");
+    printer->Print(
+      "  return target;\n"
+      "}\n");
+    return;
+  }
+
+  printer->Print(
+    "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
+    "    ::google::protobuf::uint8* target) const {\n",
+    "classname", classname_);
+  printer->Indent();
+
+  printer->Print(
+    "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  GenerateSerializeWithCachedSizesBody(printer, true);
+
+  printer->Print(
+    "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print(
+    "  return target;\n"
+    "}\n");
+}
+
+void MessageGenerator::
+GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
+  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
+      SortFieldsByNumber(descriptor_));
+
+  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeSorter());
+
+  // Merge the fields and the extension ranges, both sorted by field number.
+  int i, j;
+  for (i = 0, j = 0;
+       i < descriptor_->field_count() || j < sorted_extensions.size();
+       ) {
+    if (i == descriptor_->field_count()) {
+      GenerateSerializeOneExtensionRange(printer,
+                                         sorted_extensions[j++],
+                                         to_array);
+    } else if (j == sorted_extensions.size()) {
+      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
+    } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
+      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
+    } else {
+      GenerateSerializeOneExtensionRange(printer,
+                                         sorted_extensions[j++],
+                                         to_array);
+    }
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
+      printer->Indent();
+      if (to_array) {
+        printer->Print(
+          "target = "
+              "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+          "    unknown_fields(), target);\n");
+      } else {
+        printer->Print(
+          "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+          "    unknown_fields(), output);\n");
+      }
+      printer->Outdent();
+
+      printer->Print(
+        "}\n");
+    } else {
+      printer->Print(
+        "output->WriteRaw(unknown_fields().data(),\n"
+        "                 static_cast<int>(unknown_fields().size()));\n");
+    }
+  }
+}
+
+static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) {
+  vector<uint32> result;
+  uint32 mask = 0;
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (i > 0 && i % 32 == 0) {
+      result.push_back(mask);
+      mask = 0;
+    }
+    if (desc->field(i)->is_required()) {
+      mask |= (1 << (i & 31));
+    }
+  }
+  if (mask != 0) {
+    result.push_back(mask);
+  }
+  return result;
+}
+
+// Create an expression that evaluates to
+//  "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
+// masks is allowed to be shorter than _has_bits_, but at least one element of
+// masks must be non-zero.
+static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
+  vector<string> parts;
+  for (int i = 0; i < masks.size(); i++) {
+    if (masks[i] == 0) continue;
+    string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8));
+    // Each xor evaluates to 0 if the expected bits are present.
+    parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
+  }
+  GOOGLE_CHECK(!parts.empty());
+  // If we have multiple parts, each expected to be 0, then bitwise-or them.
+  string result = parts.size() == 1 ? parts[0] :
+      StrCat("(", Join(parts, "\n       | "), ")");
+  return result + " == 0";
+}
+
+void MessageGenerator::
+GenerateByteSize(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    printer->Print(
+        "int $classname$::ByteSize() const {\n"
+        "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
+        "  int total_size = _extensions_.MessageSetByteSize();\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    printer->Print(
+      "if (_internal_metadata_.have_unknown_fields()) {\n"
+      "  total_size += ::google::protobuf::internal::WireFormat::\n"
+      "      ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
+      "}\n");
+    printer->Print(
+      "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+      "  _cached_size_ = total_size;\n"
+      "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+      "  return total_size;\n"
+      "}\n");
+    return;
+  }
+
+  if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+    // Emit a function (rarely used, we hope) that handles the required fields
+    // by checking for each one individually.
+    printer->Print(
+        "int $classname$::RequiredFieldsByteSizeFallback() const {\n"
+        "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
+        "$full_name$)\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
+    printer->Indent();
+    printer->Print("int total_size = 0;\n");
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      if (field->is_required()) {
+        printer->Print("\n"
+                       "if (has_$name$()) {\n",
+                       "name", FieldName(field));
+        printer->Indent();
+        PrintFieldComment(printer, field);
+        field_generators_.get(field).GenerateByteSize(printer);
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+    printer->Print("\n"
+                   "return total_size;\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  printer->Print(
+      "int $classname$::ByteSize() const {\n"
+      "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
+  printer->Indent();
+  printer->Print(
+    "int total_size = 0;\n"
+    "\n");
+
+  // Handle required fields (if any).  We expect all of them to be
+  // present, so emit one conditional that checks for that.  If they are all
+  // present then the fast path executes; otherwise the slow path executes.
+  if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+    // The fast path works if all required fields are present.
+    vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_);
+    printer->Print((string("if (") +
+                    ConditionalToCheckBitmasks(masks_for_has_bits) +
+                    ") {  // All required fields are present.\n").c_str());
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      if (!field->is_required()) continue;
+      PrintFieldComment(printer, field);
+      field_generators_.get(field).GenerateByteSize(printer);
+      printer->Print("\n");
+    }
+    printer->Outdent();
+    printer->Print("} else {\n"  // the slow path
+                   "  total_size += RequiredFieldsByteSizeFallback();\n"
+                   "}\n");
+  } else {
+    // num_required_fields_ <= 1: no need to be tricky
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      if (!field->is_required()) continue;
+      PrintFieldComment(printer, field);
+      printer->Print("if (has_$name$()) {\n",
+                     "name", FieldName(field));
+      printer->Indent();
+      field_generators_.get(field).GenerateByteSize(printer);
+      printer->Outdent();
+      printer->Print("}\n");
+    }
+  }
+
+  // Handle optional fields (worry below about repeateds, oneofs, etc.).
+  // These are handled in chunks of 8.  The first chunk is
+  // the non-requireds-non-repeateds-non-unions-non-extensions in
+  //  descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
+  // and the second chunk is the same for
+  //  descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
+  // etc.
+  hash_map<int, uint32> fields_mask_for_chunk;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_required() && !field->is_repeated() &&
+        !field->containing_oneof()) {
+      fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32);
+    }
+  }
+
+  int last_index = -1;
+  bool chunk_block_in_progress = false;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_required() && !field->is_repeated() &&
+        !field->containing_oneof()) {
+      // See above in GenerateClear for an explanation of this.
+      // TODO(kenton):  Share code?  Unclear how to do so without
+      //   over-engineering.
+      if (i / 8 != last_index / 8 || last_index < 0) {
+        // End previous chunk, if there was one.
+        if (chunk_block_in_progress) {
+          printer->Outdent();
+          printer->Print("}\n");
+          chunk_block_in_progress = false;
+        }
+        // Start chunk.
+        uint32 mask = fields_mask_for_chunk[i / 8];
+        int count = popcnt(mask);
+        GOOGLE_DCHECK_GE(count, 1);
+        if (count == 1) {
+          // No "if" here because the chunk is trivial.
+        } else {
+          if (HasFieldPresence(descriptor_->file())) {
+            printer->Print(
+              "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
+              "index", SimpleItoa(i),
+              "mask", SimpleItoa(mask));
+            printer->Indent();
+            chunk_block_in_progress = true;
+          }
+        }
+      }
+      last_index = i;
+
+      PrintFieldComment(printer, field);
+
+      bool have_enclosing_if = false;
+      if (HasFieldPresence(descriptor_->file())) {
+        printer->Print(
+          "if (has_$name$()) {\n",
+          "name", FieldName(field));
+        printer->Indent();
+        have_enclosing_if = true;
+      } else {
+        // Without field presence: field is serialized only if it has a
+        // non-default value.
+        have_enclosing_if = EmitFieldNonDefaultCondition(
+            printer, "this->", field);
+      }
+
+      field_generators_.get(field).GenerateByteSize(printer);
+
+      if (have_enclosing_if) {
+        printer->Outdent();
+        printer->Print(
+          "}\n"
+          "\n");
+      }
+    }
+  }
+
+  if (chunk_block_in_progress) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  // Repeated fields don't use _has_bits_ so we count them in a separate
+  // pass.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (field->is_repeated()) {
+      PrintFieldComment(printer, field);
+      field_generators_.get(field).GenerateByteSize(printer);
+      printer->Print("\n");
+    }
+  }
+
+  // Fields inside a oneof don't use _has_bits_ so we count them in a separate
+  // pass.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+        "switch ($oneofname$_case()) {\n",
+        "oneofname", descriptor_->oneof_decl(i)->name());
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      PrintFieldComment(printer, field);
+      printer->Print(
+          "case k$field_name$: {\n",
+          "field_name", UnderscoresToCamelCase(field->name(), true));
+      printer->Indent();
+      field_generators_.get(field).GenerateByteSize(printer);
+      printer->Print(
+          "break;\n");
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+    printer->Print(
+        "case $cap_oneof_name$_NOT_SET: {\n"
+        "  break;\n"
+        "}\n",
+        "cap_oneof_name",
+        ToUpper(descriptor_->oneof_decl(i)->name()));
+    printer->Outdent();
+    printer->Print(
+        "}\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "total_size += _extensions_.ByteSize();\n"
+      "\n");
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(
+        "if (_internal_metadata_.have_unknown_fields()) {\n"
+        "  total_size +=\n"
+        "    ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+        "      unknown_fields());\n"
+        "}\n");
+    } else {
+      printer->Print(
+        "total_size += unknown_fields().size();\n"
+        "\n");
+    }
+  }
+
+  // We update _cached_size_ even though this is a const method.  In theory,
+  // this is not thread-compatible, because concurrent writes have undefined
+  // results.  In practice, since any concurrent writes will be writing the
+  // exact same value, it works on all common processors.  In a future version
+  // of C++, _cached_size_ should be made into an atomic<int>.
+  printer->Print(
+    "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+    "_cached_size_ = total_size;\n"
+    "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+    "return total_size;\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateIsInitialized(io::Printer* printer) {
+  printer->Print(
+    "bool $classname$::IsInitialized() const {\n",
+    "classname", classname_);
+  printer->Indent();
+
+  if (HasFieldPresence(descriptor_->file())) {
+    // Check that all required fields in this message are set.  We can do this
+    // most efficiently by checking 32 "has bits" at a time.
+    int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
+    for (int i = 0; i < has_bits_array_size; i++) {
+      uint32 mask = 0;
+      for (int bit = 0; bit < 32; bit++) {
+        int index = i * 32 + bit;
+        if (index >= descriptor_->field_count()) break;
+        const FieldDescriptor* field = descriptor_->field(index);
+
+        if (field->is_required()) {
+          mask |= 1 << bit;
+        }
+      }
+
+      if (mask != 0) {
+        printer->Print(
+          "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
+          "i", SimpleItoa(i),
+          "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8)));
+      }
+    }
+  }
+
+  // Now check that all embedded messages are initialized.
+  printer->Print("\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+        HasRequiredFields(field->message_type(), options_)) {
+      if (field->is_repeated()) {
+        printer->Print(
+          "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
+          " return false;\n",
+          "name", FieldName(field));
+      } else {
+        if (field->options().weak() || !field->containing_oneof()) {
+          // For weak fields, use the data member (::google::protobuf::Message*) instead
+          // of the getter to avoid a link dependency on the weak message type
+          // which is only forward declared.
+          printer->Print(
+              "if (has_$name$()) {\n"
+              "  if (!this->$name$_->IsInitialized()) return false;\n"
+              "}\n",
+            "name", FieldName(field));
+        } else {
+          printer->Print(
+            "if (has_$name$()) {\n"
+            "  if (!this->$name$().IsInitialized()) return false;\n"
+            "}\n",
+            "name", FieldName(field));
+        }
+      }
+    }
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "\n"
+      "if (!_extensions_.IsInitialized()) return false;");
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  return true;\n"
+    "}\n");
+}
+
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.h
new file mode 100644
index 0000000..31223e1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -0,0 +1,208 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumGenerator;           // enum.h
+class ExtensionGenerator;      // extension.h
+
+class MessageGenerator {
+ public:
+  // See generator.cc for the meaning of dllexport_decl.
+  MessageGenerator(const Descriptor* descriptor, const Options& options);
+  ~MessageGenerator();
+
+  // Header stuff.
+
+  // Return names for foward declarations of this class and all its nested
+  // types. A given key in {class,enum}_names will map from a class name to the
+  // descriptor that was responsible for its inclusion in the map. This can be
+  // used to associate the descriptor with the code generated for it.
+  void FillMessageForwardDeclarations(
+      map<string, const Descriptor*>* class_names);
+  void FillEnumForwardDeclarations(
+      map<string, const EnumDescriptor*>* enum_names);
+
+  // Generate definitions of all nested enums (must come before class
+  // definitions because those classes use the enums definitions).
+  void GenerateEnumDefinitions(io::Printer* printer);
+
+  // Generate specializations of GetEnumDescriptor<MyEnum>().
+  // Precondition: in ::google::protobuf namespace.
+  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+
+  // Generate definitions for this class and all its nested types.
+  void GenerateClassDefinition(io::Printer* printer);
+
+  // Generate definitions of inline methods (placed at the end of the header
+  // file).
+  void GenerateInlineMethods(io::Printer* printer, bool is_inline);
+
+  // Dependent methods are always inline.
+  void GenerateDependentInlineMethods(io::Printer* printer);
+
+  // Source file stuff.
+
+  // Generate code which declares all the global descriptor pointers which
+  // will be initialized by the methods below.
+  void GenerateDescriptorDeclarations(io::Printer* printer);
+
+  // Generate code that initializes the global variable storing the message's
+  // descriptor.
+  void GenerateDescriptorInitializer(io::Printer* printer, int index);
+
+  // Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
+  // for all types.
+  void GenerateTypeRegistrations(io::Printer* printer);
+
+  // Generates code that allocates the message's default instance.
+  void GenerateDefaultInstanceAllocator(io::Printer* printer);
+
+  // Generates code that initializes the message's default instance.  This
+  // is separate from allocating because all default instances must be
+  // allocated before any can be initialized.
+  void GenerateDefaultInstanceInitializer(io::Printer* printer);
+
+  // Generates code that should be run when ShutdownProtobufLibrary() is called,
+  // to delete all dynamically-allocated objects.
+  void GenerateShutdownCode(io::Printer* printer);
+
+  // Generate all non-inline methods for this class.
+  void GenerateClassMethods(io::Printer* printer);
+
+ private:
+  // Generate declarations and definitions of accessors for fields.
+  void GenerateDependentBaseClassDefinition(io::Printer* printer);
+  void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
+  void GenerateFieldAccessorDeclarations(io::Printer* printer);
+  void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
+  void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
+
+  // Generate the field offsets array.
+  void GenerateOffsets(io::Printer* printer);
+
+  // Generate constructors and destructor.
+  void GenerateStructors(io::Printer* printer);
+
+  // The compiler typically generates multiple copies of each constructor and
+  // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
+  // Placing common code in a separate method reduces the generated code size.
+  //
+  // Generate the shared constructor code.
+  void GenerateSharedConstructorCode(io::Printer* printer);
+  // Generate the shared destructor code.
+  void GenerateSharedDestructorCode(io::Printer* printer);
+  // Generate the arena-specific destructor code.
+  void GenerateArenaDestructorCode(io::Printer* printer);
+
+  // Generate standard Message methods.
+  void GenerateClear(io::Printer* printer);
+  void GenerateOneofClear(io::Printer* printer);
+  void GenerateMergeFromCodedStream(io::Printer* printer);
+  void GenerateSerializeWithCachedSizes(io::Printer* printer);
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
+  void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
+                                            bool to_array);
+  void GenerateByteSize(io::Printer* printer);
+  void GenerateMergeFrom(io::Printer* printer);
+  void GenerateCopyFrom(io::Printer* printer);
+  void GenerateSwap(io::Printer* printer);
+  void GenerateIsInitialized(io::Printer* printer);
+
+  // Helpers for GenerateSerializeWithCachedSizes().
+  void GenerateSerializeOneField(io::Printer* printer,
+                                 const FieldDescriptor* field,
+                                 bool unbounded);
+  void GenerateSerializeOneExtensionRange(
+      io::Printer* printer, const Descriptor::ExtensionRange* range,
+      bool unbounded);
+
+
+  // Generates has_foo() functions and variables for singular field has-bits.
+  void GenerateSingularFieldHasBits(const FieldDescriptor* field,
+                                    map<string, string> vars,
+                                    io::Printer* printer);
+  // Generates has_foo() functions and variables for oneof field has-bits.
+  void GenerateOneofHasBits(io::Printer* printer, bool is_inline);
+  // Generates has_foo_bar() functions for oneof members.
+  void GenerateOneofMemberHasBits(const FieldDescriptor* field,
+                                  const map<string, string>& vars,
+                                  io::Printer* printer);
+  // Generates the clear_foo() method for a field.
+  void GenerateFieldClear(const FieldDescriptor* field,
+                          const map<string, string>& vars,
+                          io::Printer* printer);
+
+  const Descriptor* descriptor_;
+  string classname_;
+  Options options_;
+  FieldGeneratorMap field_generators_;
+  vector< vector<string> > runs_of_fields_;  // that might be trivially cleared
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+  int num_required_fields_;
+  bool uses_string_;
+  bool use_dependent_base_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.cc
new file mode 100644
index 0000000..332c026
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -0,0 +1,1055 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         map<string, string>* variables,
+                         const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  (*variables)["type"] = FieldMessageTypeName(descriptor);
+  if (descriptor->options().weak() || !descriptor->containing_oneof()) {
+    (*variables)["non_null_ptr_to_name"] =
+        StrCat("this->", (*variables)["name"], "_");
+  }
+  (*variables)["stream_writer"] =
+      (*variables)["declared_type"] +
+      (HasFastArraySerialization(descriptor->message_type()->file(), options)
+           ? "MaybeToArray"
+           : "");
+  // NOTE: Escaped here to unblock proto1->proto2 migration.
+  // TODO(liujisi): Extend this to apply for other conflicting methods.
+  (*variables)["release_name"] =
+      SafeFunctionName(descriptor->containing_type(),
+                       descriptor, "release_");
+  (*variables)["full_name"] = descriptor->full_name();
+  if (options.proto_h && IsFieldDependent(descriptor)) {
+    (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
+    (*variables)["dependent_typename"] =
+        "typename T::" + DependentTypeName(descriptor);
+  } else {
+    (*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
+    (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
+  }
+}
+
+}  // namespace
+
+// ===================================================================
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
+  SetMessageVariables(descriptor, &variables_, options);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_, "$type$* $name$_;\n");
+}
+
+void MessageFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$() const;\n");
+}
+
+void MessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+  if (!dependent_field_) {
+    return;
+  }
+  // Arena manipulation code is out-of-line in the derived message class.
+  printer->Print(variables_,
+    "$deprecated_attr$$type$* mutable_$name$();\n"
+    "$deprecated_attr$$type$* $release_name$();\n"
+    "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
+}
+
+void MessageFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+       "private:\n"
+       "void _slow_mutable_$name$();\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables_,
+       "void _slow_set_allocated_$name$(\n"
+       "    ::google::protobuf::Arena* message_arena, $type$** $name$);\n");
+    }
+    printer->Print(variables_,
+       "$type$* _slow_$release_name$();\n"
+       "public:\n");
+  }
+  GenerateGetterDeclaration(printer);
+  if (!dependent_field_) {
+    printer->Print(variables_,
+      "$deprecated_attr$$type$* mutable_$name$();\n"
+      "$deprecated_attr$$type$* $release_name$();\n"
+      "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
+  }
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n"
+      "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
+      "    $type$* $name$);\n");
+  }
+}
+
+void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
+    io::Printer* printer) const {
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "void $classname$::_slow_mutable_$name$() {\n");
+      if (SupportsArenas(descriptor_->message_type())) {
+        printer->Print(variables_,
+          "  $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+          "      GetArenaNoVirtual());\n");
+      } else {
+        printer->Print(variables_,
+          "  $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+          "      GetArenaNoVirtual());\n");
+      }
+    printer->Print(variables_,
+      "}\n"
+      "$type$* $classname$::_slow_$release_name$() {\n"
+      "  if ($name$_ == NULL) {\n"
+      "    return NULL;\n"
+      "  } else {\n"
+      "    $type$* temp = new $type$;\n"
+      "    temp->MergeFrom(*$name$_);\n"
+      "    $name$_ = NULL;\n"
+      "    return temp;\n"
+      "  }\n"
+      "}\n"
+      "$type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  $type$* temp = $name$_;\n"
+      "  $name$_ = NULL;\n"
+      "  return temp;\n"
+      "}\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      // NOTE: the same logic is mirrored in weak_message_field.cc. Any
+      // arena-related semantics changes should be made in both places.
+      printer->Print(variables_,
+          "void $classname$::_slow_set_allocated_$name$(\n"
+          "    ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
+          "    if (message_arena != NULL && \n"
+          "        ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
+          "      message_arena->Own(*$name$);\n"
+          "    } else if (message_arena !=\n"
+          "               ::google::protobuf::Arena::GetArena(*$name$)) {\n"
+          "      $type$* new_$name$ = \n"
+          "            ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+          "            message_arena);\n"
+          "      new_$name$->CopyFrom(**$name$);\n"
+          "      *$name$ = new_$name$;\n"
+          "    }\n"
+          "}\n");
+    }
+    printer->Print(variables_,
+      "void $classname$::unsafe_arena_set_allocated_$name$(\n"
+      "    $type$* $name$) {\n"
+      // If we're not on an arena, free whatever we were holding before.
+      // (If we are on arena, we can just forget the earlier pointer.)
+      "  if (GetArenaNoVirtual() == NULL) {\n"
+      "    delete $name$_;\n"
+      "  }\n"
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+      ":$full_name$)\n"
+      "}\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+  if (!dependent_field_) {
+    return;
+  }
+
+  map<string, string> variables(variables_);
+  // For the CRTP base class, all mutation methods are dependent, and so
+  // they must be in the header.
+  variables["dependent_classname"] =
+      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+  variables["this_message"] = DependentBaseDownCast();
+  if (!variables["set_hasbit"].empty()) {
+    variables["set_hasbit"] =
+        variables["this_message"] + variables["set_hasbit"];
+  }
+  if (!variables["clear_hasbit"].empty()) {
+    variables["clear_hasbit"] =
+        variables["this_message"] + variables["clear_hasbit"];
+  }
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "template <class T>\n"
+      "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  if ($name$_ == NULL) {\n"
+      "    $this_message$_slow_mutable_$name$();\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n"
+      "template <class T>\n"
+      "inline $type$* $dependent_classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  $clear_hasbit$\n"
+      "  if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+      "    return $this_message$_slow_$release_name$();\n"
+      "  } else {\n"
+      "    $dependent_typename$* temp = $name$_;\n"
+      "    $name$_ = NULL;\n"
+      "    return temp;\n"
+      "  }\n"
+      "}\n"
+      "template <class T>\n"
+      "inline void $dependent_classname$::"
+      "set_allocated_$name$($type$* $name$) {\n"
+      "  ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  if (message_arena == NULL) {\n"
+      "    delete $name$_;\n"
+      "  }\n"
+      "  if ($name$ != NULL) {\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      // If we're on an arena and the incoming message is not, simply Own() it
+      // rather than copy to the arena -- either way we need a heap dealloc,
+      // so we might as well defer it. Otherwise, if incoming message is on a
+      // different ownership domain (specific arena, or the heap) than we are,
+      // copy to our arena (or heap, as the case may be).
+      printer->Print(variables,
+        "    $this_message$_slow_set_allocated_$name$(message_arena, "
+        "&$name$);\n");
+    } else {
+      printer->Print(variables,
+        "    if (message_arena != NULL) {\n"
+        "      message_arena->Own($name$);\n"
+        "    }\n");
+    }
+    printer->Print(variables,
+      "  }\n"
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      // TODO(dlj): move insertion points to message class.
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "template <class T>\n"
+      "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  if ($name$_ == NULL) {\n"
+      "    $name$_ = new $dependent_typename$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n"
+      "template <class T>\n"
+      "inline $type$* $dependent_classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  $dependent_typename$* temp = $name$_;\n"
+      "  $name$_ = NULL;\n"
+      "  return temp;\n"
+      "}\n"
+      "template <class T>\n"
+      "inline void $dependent_classname$::"
+      "set_allocated_$name$($type$* $name$) {\n"
+      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+      "  delete $name$_;\n");
+
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables,
+      "  if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
+      "->GetArena() != NULL) {\n"
+      "    $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
+      "    new_$name$->CopyFrom(*$name$);\n"
+      "    $name$ = new_$name$;\n"
+      "  }\n");
+    }
+
+    printer->Print(variables,
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline " : "";
+  printer->Print(variables,
+    "$inline$const $type$& $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n");
+
+  PrintHandlingOptionalStaticInitializers(
+      variables, descriptor_->file(), options_, printer,
+      // With static initializers.
+      "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
+      // Without.
+      "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+  printer->Print(variables, "}\n");
+
+  if (dependent_field_) {
+    return;
+  }
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "$inline$"
+      "$type$* $classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  if ($name$_ == NULL) {\n"
+      "    _slow_mutable_$name$();\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n"
+      "$inline$"
+      "$type$* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  if (GetArenaNoVirtual() != NULL) {\n"
+      "    return _slow_$release_name$();\n"
+      "  } else {\n"
+      "    $type$* temp = $name$_;\n"
+      "    $name$_ = NULL;\n"
+      "    return temp;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ "
+      "void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
+      "  if (message_arena == NULL) {\n"
+      "    delete $name$_;\n"
+      "  }\n"
+      "  if ($name$ != NULL) {\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      // If we're on an arena and the incoming message is not, simply Own() it
+      // rather than copy to the arena -- either way we need a heap dealloc,
+      // so we might as well defer it. Otherwise, if incoming message is on a
+      // different ownership domain (specific arena, or the heap) than we are,
+      // copy to our arena (or heap, as the case may be).
+      printer->Print(variables,
+        "    _slow_set_allocated_$name$(message_arena, &$name$);\n");
+    } else {
+      printer->Print(variables,
+        "    if (message_arena != NULL) {\n"
+        "      message_arena->Own($name$);\n"
+        "    }\n");
+    }
+    printer->Print(variables,
+      "  }\n"
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "$inline$"
+      "$type$* $classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  if ($name$_ == NULL) {\n"
+      "    $name$_ = new $type$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n"
+      "$inline$"
+      "$type$* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  $type$* temp = $name$_;\n"
+      "  $name$_ = NULL;\n"
+      "  return temp;\n"
+      "}\n"
+      "$inline$"
+      "void $classname$::set_allocated_$name$($type$* $name$) {\n"
+      "  delete $name$_;\n");
+
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables,
+      "  if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
+      "    $type$* new_$name$ = new $type$;\n"
+      "    new_$name$->CopyFrom(*$name$);\n"
+      "    $name$ = new_$name$;\n"
+      "  }\n");
+    }
+
+    printer->Print(variables,
+      "  $name$_ = $name$;\n"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+  if (!HasFieldPresence(descriptor_->file())) {
+    // If we don't have has-bits, message presence is indicated only by ptr !=
+    // NULL. Thus on clear, we need to delete the object.
+    printer->Print(variables,
+      "if ($this_message$GetArenaNoVirtual() == NULL && "
+      "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
+      "$this_message$$name$_ = NULL;\n");
+  } else {
+    printer->Print(variables,
+      "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
+      "$dependent_type$::Clear();\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+}
+
+void MessageFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+}
+
+void MessageFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = NULL;\n");
+}
+
+void MessageFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+      "     input, mutable_$name$()));\n");
+  } else {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+      "      $number$, input, mutable_$name$()));\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
+    "  $number$, *$non_null_ptr_to_name$, output);\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+    "target = ::google::protobuf::internal::WireFormatLite::\n"
+    "  Write$declared_type$NoVirtualToArray(\n"
+    "    $number$, *$non_null_ptr_to_name$, target);\n");
+}
+
+void MessageFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "total_size += $tag_size$ +\n"
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
+    "    *$non_null_ptr_to_name$);\n");
+}
+
+// ===================================================================
+
+MessageOneofFieldGenerator::
+MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                           const Options& options)
+  : MessageFieldGenerator(descriptor, options),
+    dependent_base_(options.proto_h) {
+  SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+
+void MessageOneofFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+  // Oneof field getters must be dependent as they call default_instance().
+  // Otherwise, the logic is the same as MessageFields.
+  if (!dependent_field_) {
+    return;
+  }
+  printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$() const;\n");
+  MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+  // Oneof field getters must be dependent as they call default_instance().
+  // Unlike MessageField, this means there is no (non-dependent) getter to
+  // generate.
+  if (dependent_field_) {
+    return;
+  }
+  printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$() const;\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+  // For the CRTP base class, all mutation methods are dependent, and so
+  // they must be in the header.
+  if (!dependent_base_) {
+    return;
+  }
+  map<string, string> variables(variables_);
+  variables["inline"] = "inline ";
+  variables["dependent_classname"] =
+      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+  variables["this_message"] = "reinterpret_cast<T*>(this)->";
+  // Const message access is needed for the dependent getter.
+  variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+  variables["tmpl"] = "template <class T>\n";
+  variables["field_member"] = variables["this_message"] +
+                              variables["oneof_prefix"] + variables["name"] +
+                              "_";
+  InternalGenerateInlineAccessorDefinitions(variables, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  if (dependent_base_) {
+    return;
+  }
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline " : "";
+  variables["dependent_classname"] = variables["classname"];
+  variables["this_message"] = "";
+  variables["this_const_message"] = "";
+  variables["tmpl"] = "";
+  variables["field_member"] =
+      variables["oneof_prefix"] + variables["name"] + "_";
+  variables["dependent_type"] = variables["type"];
+  InternalGenerateInlineAccessorDefinitions(variables, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  variables["field_member"] =
+      variables["oneof_prefix"] + variables["name"] + "_";
+
+  //printer->Print(variables,
+}
+
+void MessageOneofFieldGenerator::
+InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
+                                          io::Printer* printer) const {
+  printer->Print(variables,
+    "$tmpl$"
+    "$inline$ "
+    "const $type$& $dependent_classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return $this_const_message$has_$name$()\n"
+    "      ? *$this_const_message$$oneof_prefix$$name$_\n"
+    "      : $dependent_type$::default_instance();\n"
+    "}\n");
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "$tmpl$"
+      "$inline$"
+      "$type$* $dependent_classname$::mutable_$name$() {\n"
+      "  if (!$this_message$has_$name$()) {\n"
+      "    $this_message$clear_$oneof_name$();\n"
+      "    $this_message$set_has_$name$();\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables,
+         "    $field_member$ = \n"
+         "      ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+         "      $this_message$GetArenaNoVirtual());\n");
+    } else {
+      printer->Print(variables,
+         "    $this_message$$oneof_prefix$$name$_ = \n"
+         "      ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
+         "      $this_message$GetArenaNoVirtual());\n");
+    }
+    printer->Print(variables,
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $field_member$;\n"
+      "}\n"
+      "$tmpl$"
+      "$inline$"
+      "$type$* $dependent_classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  if ($this_message$has_$name$()) {\n"
+      "    $this_message$clear_has_$oneof_name$();\n"
+      "    if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+      // N.B.: safe to use the underlying field pointer here because we are sure
+      // that it is non-NULL (because has_$name$() returned true).
+      "      $dependent_typename$* temp = new $dependent_typename$;\n"
+      "      temp->MergeFrom(*$field_member$);\n"
+      "      $field_member$ = NULL;\n"
+      "      return temp;\n"
+      "    } else {\n"
+      "      $dependent_typename$* temp = $field_member$;\n"
+      "      $field_member$ = NULL;\n"
+      "      return temp;\n"
+      "    }\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$tmpl$"
+      "$inline$"
+      "void $dependent_classname$::"
+      "set_allocated_$name$($type$* $name$) {\n"
+      "  $this_message$clear_$oneof_name$();\n"
+      "  if ($name$) {\n");
+
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables,
+        // If incoming message is on the heap and we are on an arena, just Own()
+        // it (see above). If it's on a different arena than we are or one of us
+        // is on the heap, we make a copy to our arena/heap.
+        "    if ($this_message$GetArenaNoVirtual() != NULL &&\n"
+        "        ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
+        "      $this_message$GetArenaNoVirtual()->Own($name$);\n"
+        "    } else if ($this_message$GetArenaNoVirtual() !=\n"
+        "               ::google::protobuf::Arena::GetArena($name$)) {\n"
+        "      $dependent_typename$* new_$name$ = \n"
+        "          ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+        "          $this_message$GetArenaNoVirtual());\n"
+        "      new_$name$->CopyFrom(*$name$);\n"
+        "      $name$ = new_$name$;\n"
+        "    }\n");
+    } else {
+      printer->Print(variables,
+        "    if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+        "      $this_message$GetArenaNoVirtual()->Own($name$);\n"
+        "    }\n");
+    }
+
+    printer->Print(variables,
+      "    $this_message$set_has_$name$();\n"
+      "    $field_member$ = $name$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n"
+      "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release"
+      ":$full_name$)\n"
+      "  if (has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    $type$* temp = $oneof_prefix$$name$_;\n"
+      "    $oneof_prefix$$name$_ = NULL;\n"
+      "    return temp;\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
+      "($type$* $name$) {\n"
+      // We rely on the oneof clear method to free the earlier contents of this
+      // oneof. We can directly use the pointer we're given to set the new
+      // value.
+      "  clear_$oneof_name$();\n"
+      "  if ($name$) {\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_ = $name$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+      "$full_name$)\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "$tmpl$"
+      "$inline$"
+      "$type$* $dependent_classname$::mutable_$name$() {\n"
+      "  if (!$this_message$has_$name$()) {\n"
+      "    $this_message$clear_$oneof_name$();\n"
+      "    $this_message$set_has_$name$();\n"
+      "    $field_member$ = new $dependent_typename$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $field_member$;\n"
+      "}\n"
+      "$tmpl$"
+      "$inline$"
+      "$type$* $dependent_classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  if ($this_message$has_$name$()) {\n"
+      "    $this_message$clear_has_$oneof_name$();\n"
+      "    $dependent_typename$* temp = $field_member$;\n"
+      "    $field_member$ = NULL;\n"
+      "    return temp;\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$tmpl$"
+      "$inline$"
+      "void $dependent_classname$::"
+      "set_allocated_$name$($type$* $name$) {\n"
+      "  $this_message$clear_$oneof_name$();\n"
+      "  if ($name$) {\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables,
+        "    if (static_cast< $dependent_typename$*>($name$)->"
+        "GetArena() != NULL) {\n"
+        "      $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
+        "      new_$name$->CopyFrom(*$name$);\n"
+        "      $name$ = new_$name$;\n"
+        "    }\n");
+    }
+    printer->Print(variables,
+      "    $this_message$set_has_$name$();\n"
+      "    $field_member$ = $name$;\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  }
+}
+
+void MessageOneofFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
+      "  delete $this_message$$oneof_prefix$$name$_;\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "delete $this_message$$oneof_prefix$$name$_;\n");
+  }
+}
+
+void MessageOneofFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  // Don't print any swapping code. Swapping the union will swap this field.
+}
+
+void MessageOneofFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  // Don't print any constructor code. The field is in a union. We allocate
+  // space only when this field is used.
+}
+
+// ===================================================================
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+      dependent_getter_(dependent_field_ && options.safe_boundary_check) {
+  SetMessageVariables(descriptor, &variables_, options);
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecated_attr$$type$* mutable_$name$(int index);\n"
+    "$deprecated_attr$$type$* add_$name$();\n");
+  if (dependent_getter_) {
+    printer->Print(variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "    $name$() const;\n");
+  }
+  printer->Print(variables_,
+    "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
+    "    mutable_$name$();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+  if (dependent_getter_) {
+    printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$(int index) const;\n");
+  }
+  if (dependent_field_) {
+    InternalGenerateTypeDependentAccessorDeclarations(printer);
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  if (!dependent_getter_) {
+    printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$(int index) const;\n");
+  }
+  if (!dependent_field_) {
+    InternalGenerateTypeDependentAccessorDeclarations(printer);
+  }
+  if (!dependent_getter_) {
+    printer->Print(variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "    $name$() const;\n");
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+  if (!dependent_field_) {
+    return;
+  }
+  map<string, string> variables(variables_);
+  // For the CRTP base class, all mutation methods are dependent, and so
+  // they must be in the header.
+  variables["dependent_classname"] =
+      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+  variables["this_message"] = DependentBaseDownCast();
+  variables["this_const_message"] = DependentBaseConstDownCast();
+
+  if (dependent_getter_) {
+    printer->Print(variables,
+      "template <class T>\n"
+      "inline const $type$& $dependent_classname$::$name$(int index) const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $this_const_message$$name$_.$cppget$(index);\n"
+      "}\n");
+  }
+
+  // Generate per-element accessors:
+  printer->Print(variables,
+    "template <class T>\n"
+    "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
+    // TODO(dlj): move insertion points
+    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+    "  return $this_message$$name$_.Mutable(index);\n"
+    "}\n"
+    "template <class T>\n"
+    "inline $type$* $dependent_classname$::add_$name$() {\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "  return $this_message$$name$_.Add();\n"
+    "}\n");
+
+
+  if (dependent_getter_) {
+    printer->Print(variables,
+      "template <class T>\n"
+      "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "$dependent_classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+      "  return $this_const_message$$name$_;\n"
+      "}\n");
+  }
+
+  // Generate mutable access to the entire list:
+  printer->Print(variables,
+    "template <class T>\n"
+    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+    "$dependent_classname$::mutable_$name$() {\n"
+    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+    "  return &$this_message$$name$_;\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline " : "";
+
+  if (!dependent_getter_) {
+    printer->Print(variables,
+      "$inline$"
+      "const $type$& $classname$::$name$(int index) const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $name$_.$cppget$(index);\n"
+      "}\n");
+  }
+
+  if (!dependent_field_) {
+    printer->Print(variables,
+      "$inline$"
+      "$type$* $classname$::mutable_$name$(int index) {\n"
+      // TODO(dlj): move insertion points
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_.Mutable(index);\n"
+      "}\n"
+      "$inline$"
+      "$type$* $classname$::add_$name$() {\n"
+      "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+      "  return $name$_.Add();\n"
+      "}\n");
+  }
+
+
+  if (!dependent_field_) {
+    printer->Print(variables,
+      "$inline$"
+      "::google::protobuf::RepeatedPtrField< $type$ >*\n"
+      "$classname$::mutable_$name$() {\n"
+      "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+      "  return &$name$_;\n"
+      "}\n");
+  }
+  if (!dependent_getter_) {
+    printer->Print(variables,
+      "$inline$"
+      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "$classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+      "  return $name$_;\n"
+      "}\n");
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+  printer->Print(variables, "$this_message$$name$_.Clear();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  // Not needed for repeated fields.
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::"
+      "ReadMessageNoVirtualNoRecursionDepth(\n"
+      "      input, add_$name$()));\n");
+  } else {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::"
+      "ReadGroupNoVirtualNoRecursionDepth(\n"
+      "      $number$, input, add_$name$()));\n");
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
+    "    $number$, this->$name$(i), output);\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "  target = ::google::protobuf::internal::WireFormatLite::\n"
+    "    Write$declared_type$NoVirtualToArray(\n"
+    "      $number$, this->$name$(i), target);\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "total_size += $tag_size$ * this->$name$_size();\n"
+    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "  total_size +=\n"
+    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
+    "      this->$name$(i));\n"
+    "}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.h
new file mode 100644
index 0000000..d8d9279
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -0,0 +1,150 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MessageFieldGenerator : public FieldGenerator {
+ public:
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
+  ~MessageFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ protected:
+  void GenerateArenaManipulationCode(const map<string, string>& variables,
+                                     io::Printer* printer) const;
+
+  virtual void GenerateGetterDeclaration(io::Printer* printer) const;
+
+  const FieldDescriptor* descriptor_;
+  const bool dependent_field_;
+  map<string, string> variables_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class MessageOneofFieldGenerator : public MessageFieldGenerator {
+ public:
+  MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
+  ~MessageOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
+  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+
+ protected:
+  void GenerateGetterDeclaration(io::Printer* printer) const;
+
+ private:
+  void InternalGenerateInlineAccessorDefinitions(
+      const map<string, string>& variables, io::Printer* printer) const;
+
+  const bool dependent_base_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public FieldGenerator {
+ public:
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options);
+  ~RepeatedMessageFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  void InternalGenerateTypeDependentAccessorDeclarations(
+      io::Printer* printer) const;
+
+  const FieldDescriptor* descriptor_;
+  const bool dependent_field_;
+  const bool dependent_getter_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_options.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 0000000..ab1d2ed
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -0,0 +1,67 @@
+// 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.
+
+// Author: rennie@google.com (Jeffrey Rennie)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Generator options (see generator.cc for a description of each):
+struct Options {
+  Options()
+      : safe_boundary_check(false),
+        proto_h(false),
+        annotate_headers(false),
+        enforce_lite(false) {}
+
+  string dllexport_decl;
+  bool safe_boundary_check;
+  bool proto_h;
+  bool annotate_headers;
+  bool enforce_lite;
+  string annotation_pragma_name;
+  string annotation_guard_name;
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
new file mode 100644
index 0000000..34a41d8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -0,0 +1,252 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* context,
+                        string* error) const {
+    TryInsert("test.pb.h", "includes", context);
+    TryInsert("test.pb.h", "namespace_scope", context);
+    TryInsert("test.pb.h", "global_scope", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
+
+    TryInsert("test.pb.cc", "includes", context);
+    TryInsert("test.pb.cc", "namespace_scope", context);
+    TryInsert("test.pb.cc", "global_scope", context);
+
+    // Check field accessors for an optional int32:
+    TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
+
+    // Check field accessors for a repeated int32:
+    TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
+
+    // Check field accessors for a required string:
+    TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
+              context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+
+    // Check field accessors for a repeated string:
+    TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+
+    // Check field accessors for an int inside oneof{}:
+    TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
+
+    // Check field accessors for a string inside oneof{}:
+    TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+
+    // Check field accessors for an optional message:
+    TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
+    TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
+
+    // Check field accessors for a repeated message:
+    TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
+    TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
+    TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
+    TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
+              context);
+
+    // Check field accessors for a message inside oneof{}:
+    TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
+    TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context);
+
+    // Check field accessors for an optional enum:
+    TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
+
+    // Check field accessors for a repeated enum:
+    TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
+    TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
+    TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
+    TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
+
+    // Check field accessors for an enum inside oneof{}:
+    TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
+
+    // Check field accessors for a required cord:
+    TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
+
+    // Check field accessors for a repeated cord:
+    TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
+    TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
+    TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
+    TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
+
+    // Check field accessors for a cord inside oneof{}:
+    TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
+    TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
+    TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
+
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 GeneratorContext* context) const {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        context->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(CppPluginTest, PluginTest) {
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
+                             "syntax = \"proto2\";\n"
+                             "package foo;\n"
+                             "\n"
+                             "enum Thud { VALUE = 0; }\n"
+                             "\n"
+                             "message Bar {\n"
+                             "  message Baz {}\n"
+                             "  optional int32 optInt = 1;\n"
+                             "  repeated int32 repeatedInt = 2;\n"
+                             "\n"
+                             "  required string requiredString = 3;\n"
+                             "  repeated string repeatedString = 4;\n"
+                             "\n"
+                             "  optional Baz optMessage = 6;\n"
+                             "  repeated Baz repeatedMessage = 7;\n"
+                             "\n"
+                             "  optional Thud optEnum = 8;\n"
+                             "  repeated Thud repeatedEnum = 9;\n"
+                             "\n"
+                             "  required string requiredCord = 10 [\n"
+                             "    ctype = CORD\n"
+                             "  ];\n"
+                             "  repeated string repeatedCord = 11 [\n"
+                             "    ctype = CORD\n"
+                             "  ];\n"
+                             "\n"
+                             "  oneof Qux {\n"
+                             "    int64 oneOfInt = 20;\n"
+                             "    string oneOfString = 21;\n"
+                             "    Baz oneOfMessage = 22;\n"
+                             "    Thud oneOfEnum = 23;"
+                             "    string oneOfCord = 24 [\n"
+                             "      ctype = CORD\n"
+                             "    ];\n"
+                             "  }\n"
+                             "}\n",
+                             true));
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  CppGenerator cpp_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string cpp_out = "--cpp_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    cpp_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
new file mode 100644
index 0000000..650f038
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -0,0 +1,458 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormatLite;
+
+namespace {
+
+// For encodings with fixed sizes, returns that size in bytes.  Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return -1;
+    case FieldDescriptor::TYPE_INT64   : return -1;
+    case FieldDescriptor::TYPE_UINT32  : return -1;
+    case FieldDescriptor::TYPE_UINT64  : return -1;
+    case FieldDescriptor::TYPE_SINT32  : return -1;
+    case FieldDescriptor::TYPE_SINT64  : return -1;
+    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
+
+    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
+    case FieldDescriptor::TYPE_ENUM    : return -1;
+
+    case FieldDescriptor::TYPE_STRING  : return -1;
+    case FieldDescriptor::TYPE_BYTES   : return -1;
+    case FieldDescriptor::TYPE_GROUP   : return -1;
+    case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           map<string, string>* variables,
+                           const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
+  (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+  int fixed_size = FixedSize(descriptor->type());
+  if (fixed_size != -1) {
+    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+  }
+  (*variables)["wire_format_field_type"] =
+      "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
+          static_cast<FieldDescriptorProto_Type>(descriptor->type()));
+  (*variables)["full_name"] = descriptor->full_name();
+}
+
+}  // namespace
+
+// ===================================================================
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetPrimitiveVariables(descriptor, &variables_, options);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+void PrimitiveFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_, "$type$ $name$_;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecated_attr$$type$ $name$() const;\n"
+    "$deprecated_attr$void set_$name$($type$ value);\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n"
+    "  $set_hasbit$\n"
+    "  $name$_ = value;\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "set_$name$(from.$name$());\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+    "         $type$, $wire_format_field_type$>(\n"
+    "       input, &$name$_)));\n"
+    "$set_hasbit$\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
+      "$number$, this->$name$(), output);\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+    "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
+      "$number$, this->$name$(), target);\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  int fixed_size = FixedSize(descriptor_->type());
+  if (fixed_size == -1) {
+    printer->Print(variables_,
+      "total_size += $tag_size$ +\n"
+      "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
+      "    this->$name$());\n");
+  } else {
+    printer->Print(variables_,
+      "total_size += $tag_size$ + $fixed_size$;\n");
+  }
+}
+
+// ===================================================================
+
+PrimitiveOneofFieldGenerator::
+PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options)
+  : PrimitiveFieldGenerator(descriptor, options) {
+  SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  if (has_$name$()) {\n"
+    "    return $oneof_prefix$$name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$($type$ value) {\n"
+    "  if (!has_$name$()) {\n"
+    "    clear_$oneof_name$();\n"
+    "    set_has_$name$();\n"
+    "  }\n"
+    "  $oneof_prefix$$name$_ = value;\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  // Don't print any swapping code. Swapping the union will swap this field.
+}
+
+void PrimitiveOneofFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "  $classname$_default_oneof_instance_->$name$_ = $default$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "clear_$oneof_name$();\n"
+    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+    "         $type$, $wire_format_field_type$>(\n"
+    "       input, &$oneof_prefix$$name$_)));\n"
+    "set_has_$name$();\n");
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetPrimitiveVariables(descriptor, &variables_, options);
+
+  if (descriptor->is_packed()) {
+    variables_["packed_reader"] = "ReadPackedPrimitive";
+    variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
+  } else {
+    variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
+    variables_["repeated_reader"] = "ReadRepeatedPrimitive";
+  }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    printer->Print(variables_,
+      "mutable int _$name$_cached_byte_size_;\n");
+  }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecated_attr$$type$ $name$(int index) const;\n"
+    "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
+    "$deprecated_attr$void add_$name$($type$ value);\n");
+  printer->Print(variables_,
+    "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
+    "    $name$() const;\n"
+    "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
+    "    mutable_$name$();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ $type$ $classname$::$name$(int index) const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return $name$_.Get(index);\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
+    "  $name$_.Set(index, value);\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "}\n"
+    "$inline$ void $classname$::add_$name$($type$ value) {\n"
+    "  $name$_.Add(value);\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "}\n");
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
+    "$classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
+    "$classname$::mutable_$name$() {\n"
+    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+    "  return &$name$_;\n"
+    "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Clear();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  // Not needed for repeated fields.
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
+    "         $type$, $wire_format_field_type$>(\n"
+    "       $tag_size$, $tag$, input, this->mutable_$name$())));\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+  printer->Print(variables_,
+    "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
+    "         $type$, $wire_format_field_type$>(\n"
+    "       input, this->mutable_$name$())));\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    // Write the tag and the size.
+    printer->Print(variables_,
+      "if (this->$name$_size() > 0) {\n"
+      "  ::google::protobuf::internal::WireFormatLite::WriteTag("
+          "$number$, "
+          "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
+          "output);\n"
+      "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
+      "    this->$name$(i), output);\n");
+  } else {
+    printer->Print(variables_,
+      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+      "    $number$, this->$name$(i), output);\n");
+  }
+  printer->Print("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    // Write the tag and the size.
+    printer->Print(variables_,
+      "if (this->$name$_size() > 0) {\n"
+      "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
+      "    $number$,\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
+      "    target);\n"
+      "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
+      "    _$name$_cached_byte_size_, target);\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "  target = ::google::protobuf::internal::WireFormatLite::\n"
+      "    Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
+  } else {
+    printer->Print(variables_,
+      "  target = ::google::protobuf::internal::WireFormatLite::\n"
+      "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
+  }
+  printer->Print("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int data_size = 0;\n");
+  printer->Indent();
+  int fixed_size = FixedSize(descriptor_->type());
+  if (fixed_size == -1) {
+    printer->Print(variables_,
+      "for (int i = 0; i < this->$name$_size(); i++) {\n"
+      "  data_size += ::google::protobuf::internal::WireFormatLite::\n"
+      "    $declared_type$Size(this->$name$(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "data_size = $fixed_size$ * this->$name$_size();\n");
+  }
+
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "if (data_size > 0) {\n"
+      "  total_size += $tag_size$ +\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "}\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+      "_$name$_cached_byte_size_ = data_size;\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+      "total_size += data_size;\n");
+  } else {
+    printer->Print(variables_,
+      "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
new file mode 100644
index 0000000..655ebde
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -0,0 +1,126 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class PrimitiveFieldGenerator : public FieldGenerator {
+ public:
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
+  ~PrimitiveFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options);
+  ~PrimitiveOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                  const Options& options);
+  ~RepeatedPrimitiveFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.cc
new file mode 100644
index 0000000..226c2aa
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -0,0 +1,334 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_service.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
+                                   const Options& options)
+  : descriptor_(descriptor) {
+  vars_["classname"] = descriptor_->name();
+  vars_["full_name"] = descriptor_->full_name();
+  if (options.dllexport_decl.empty()) {
+    vars_["dllexport"] = "";
+  } else {
+    vars_["dllexport"] = options.dllexport_decl + " ";
+  }
+}
+
+ServiceGenerator::~ServiceGenerator() {}
+
+void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
+  // Forward-declare the stub type.
+  printer->Print(vars_,
+    "class $classname$_Stub;\n"
+    "\n");
+
+  GenerateInterface(printer);
+  GenerateStubDefinition(printer);
+}
+
+void ServiceGenerator::GenerateInterface(io::Printer* printer) {
+  printer->Print(vars_,
+    "class $dllexport$$classname$ : public ::google::protobuf::Service {\n"
+    " protected:\n"
+    "  // This class should be treated as an abstract interface.\n"
+    "  inline $classname$() {};\n"
+    " public:\n"
+    "  virtual ~$classname$();\n");
+  printer->Indent();
+
+  printer->Print(vars_,
+    "\n"
+    "typedef $classname$_Stub Stub;\n"
+    "\n"
+    "static const ::google::protobuf::ServiceDescriptor* descriptor();\n"
+    "\n");
+
+  GenerateMethodSignatures(VIRTUAL, printer);
+
+  printer->Print(
+    "\n"
+    "// implements Service ----------------------------------------------\n"
+    "\n"
+    "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n"
+    "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
+    "                ::google::protobuf::RpcController* controller,\n"
+    "                const ::google::protobuf::Message* request,\n"
+    "                ::google::protobuf::Message* response,\n"
+    "                ::google::protobuf::Closure* done);\n"
+    "const ::google::protobuf::Message& GetRequestPrototype(\n"
+    "  const ::google::protobuf::MethodDescriptor* method) const;\n"
+    "const ::google::protobuf::Message& GetResponsePrototype(\n"
+    "  const ::google::protobuf::MethodDescriptor* method) const;\n");
+
+  printer->Outdent();
+  printer->Print(vars_,
+    "\n"
+    " private:\n"
+    "  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
+    "};\n"
+    "\n");
+}
+
+void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
+  printer->Print(vars_,
+    "class $dllexport$$classname$_Stub : public $classname$ {\n"
+    " public:\n");
+
+  printer->Indent();
+
+  printer->Print(vars_,
+    "$classname$_Stub(::google::protobuf::RpcChannel* channel);\n"
+    "$classname$_Stub(::google::protobuf::RpcChannel* channel,\n"
+    "                 ::google::protobuf::Service::ChannelOwnership ownership);\n"
+    "~$classname$_Stub();\n"
+    "\n"
+    "inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n"
+    "\n"
+    "// implements $classname$ ------------------------------------------\n"
+    "\n");
+
+  GenerateMethodSignatures(NON_VIRTUAL, printer);
+
+  printer->Outdent();
+  printer->Print(vars_,
+    " private:\n"
+    "  ::google::protobuf::RpcChannel* channel_;\n"
+    "  bool owns_channel_;\n"
+    "  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
+    "};\n"
+    "\n");
+}
+
+void ServiceGenerator::GenerateMethodSignatures(
+    VirtualOrNon virtual_or_non, io::Printer* printer) {
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> sub_vars;
+    sub_vars["name"] = method->name();
+    sub_vars["input_type"] = ClassName(method->input_type(), true);
+    sub_vars["output_type"] = ClassName(method->output_type(), true);
+    sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : "";
+
+    printer->Print(sub_vars,
+      "$virtual$void $name$(::google::protobuf::RpcController* controller,\n"
+      "                     const $input_type$* request,\n"
+      "                     $output_type$* response,\n"
+      "                     ::google::protobuf::Closure* done);\n");
+  }
+}
+
+// ===================================================================
+
+void ServiceGenerator::GenerateDescriptorInitializer(
+    io::Printer* printer, int index) {
+  map<string, string> vars;
+  vars["classname"] = descriptor_->name();
+  vars["index"] = SimpleItoa(index);
+
+  printer->Print(vars,
+    "$classname$_descriptor_ = file->service($index$);\n");
+}
+
+// ===================================================================
+
+void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
+  printer->Print(vars_,
+    "$classname$::~$classname$() {}\n"
+    "\n"
+    "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
+    "  protobuf_AssignDescriptorsOnce();\n"
+    "  return $classname$_descriptor_;\n"
+    "}\n"
+    "\n"
+    "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
+    "  protobuf_AssignDescriptorsOnce();\n"
+    "  return $classname$_descriptor_;\n"
+    "}\n"
+    "\n");
+
+  // Generate methods of the interface.
+  GenerateNotImplementedMethods(printer);
+  GenerateCallMethod(printer);
+  GenerateGetPrototype(REQUEST, printer);
+  GenerateGetPrototype(RESPONSE, printer);
+
+  // Generate stub implementation.
+  printer->Print(vars_,
+    "$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n"
+    "  : channel_(channel), owns_channel_(false) {}\n"
+    "$classname$_Stub::$classname$_Stub(\n"
+    "    ::google::protobuf::RpcChannel* channel,\n"
+    "    ::google::protobuf::Service::ChannelOwnership ownership)\n"
+    "  : channel_(channel),\n"
+    "    owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n"
+    "$classname$_Stub::~$classname$_Stub() {\n"
+    "  if (owns_channel_) delete channel_;\n"
+    "}\n"
+    "\n");
+
+  GenerateStubMethods(printer);
+}
+
+void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> sub_vars;
+    sub_vars["classname"] = descriptor_->name();
+    sub_vars["name"] = method->name();
+    sub_vars["index"] = SimpleItoa(i);
+    sub_vars["input_type"] = ClassName(method->input_type(), true);
+    sub_vars["output_type"] = ClassName(method->output_type(), true);
+
+    printer->Print(sub_vars,
+      "void $classname$::$name$(::google::protobuf::RpcController* controller,\n"
+      "                         const $input_type$*,\n"
+      "                         $output_type$*,\n"
+      "                         ::google::protobuf::Closure* done) {\n"
+      "  controller->SetFailed(\"Method $name$() not implemented.\");\n"
+      "  done->Run();\n"
+      "}\n"
+      "\n");
+  }
+}
+
+void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
+  printer->Print(vars_,
+    "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
+    "                             ::google::protobuf::RpcController* controller,\n"
+    "                             const ::google::protobuf::Message* request,\n"
+    "                             ::google::protobuf::Message* response,\n"
+    "                             ::google::protobuf::Closure* done) {\n"
+    "  GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n"
+    "  switch(method->index()) {\n");
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> sub_vars;
+    sub_vars["name"] = method->name();
+    sub_vars["index"] = SimpleItoa(i);
+    sub_vars["input_type"] = ClassName(method->input_type(), true);
+    sub_vars["output_type"] = ClassName(method->output_type(), true);
+
+    // Note:  down_cast does not work here because it only works on pointers,
+    //   not references.
+    printer->Print(sub_vars,
+      "    case $index$:\n"
+      "      $name$(controller,\n"
+      "             ::google::protobuf::down_cast<const $input_type$*>(request),\n"
+      "             ::google::protobuf::down_cast< $output_type$*>(response),\n"
+      "             done);\n"
+      "      break;\n");
+  }
+
+  printer->Print(vars_,
+    "    default:\n"
+    "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
+    "      break;\n"
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
+                                            io::Printer* printer) {
+  if (which == REQUEST) {
+    printer->Print(vars_,
+      "const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n");
+  } else {
+    printer->Print(vars_,
+      "const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n");
+  }
+
+  printer->Print(vars_,
+    "    const ::google::protobuf::MethodDescriptor* method) const {\n"
+    "  GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
+    "  switch(method->index()) {\n");
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    const Descriptor* type =
+      (which == REQUEST) ? method->input_type() : method->output_type();
+
+    map<string, string> sub_vars;
+    sub_vars["index"] = SimpleItoa(i);
+    sub_vars["type"] = ClassName(type, true);
+
+    printer->Print(sub_vars,
+      "    case $index$:\n"
+      "      return $type$::default_instance();\n");
+  }
+
+  printer->Print(vars_,
+    "    default:\n"
+    "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
+    "      return *static_cast< ::google::protobuf::Message*>(NULL);\n"
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> sub_vars;
+    sub_vars["classname"] = descriptor_->name();
+    sub_vars["name"] = method->name();
+    sub_vars["index"] = SimpleItoa(i);
+    sub_vars["input_type"] = ClassName(method->input_type(), true);
+    sub_vars["output_type"] = ClassName(method->output_type(), true);
+
+    printer->Print(sub_vars,
+      "void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n"
+      "                              const $input_type$* request,\n"
+      "                              $output_type$* response,\n"
+      "                              ::google::protobuf::Closure* done) {\n"
+      "  channel_->CallMethod(descriptor()->method($index$),\n"
+      "                       controller, request, response, done);\n"
+      "}\n");
+  }
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.h
new file mode 100644
index 0000000..ede2fd8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -0,0 +1,118 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class ServiceGenerator {
+ public:
+  // See generator.cc for the meaning of dllexport_decl.
+  explicit ServiceGenerator(const ServiceDescriptor* descriptor,
+                            const Options& options);
+  ~ServiceGenerator();
+
+  // Header stuff.
+
+  // Generate the class definitions for the service's interface and the
+  // stub implementation.
+  void GenerateDeclarations(io::Printer* printer);
+
+  // Source file stuff.
+
+  // Generate code that initializes the global variable storing the service's
+  // descriptor.
+  void GenerateDescriptorInitializer(io::Printer* printer, int index);
+
+  // Generate implementations of everything declared by GenerateDeclarations().
+  void GenerateImplementation(io::Printer* printer);
+
+ private:
+  enum RequestOrResponse { REQUEST, RESPONSE };
+  enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };
+
+  // Header stuff.
+
+  // Generate the service abstract interface.
+  void GenerateInterface(io::Printer* printer);
+
+  // Generate the stub class definition.
+  void GenerateStubDefinition(io::Printer* printer);
+
+  // Prints signatures for all methods in the
+  void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
+                                io::Printer* printer);
+
+  // Source file stuff.
+
+  // Generate the default implementations of the service methods, which
+  // produce a "not implemented" error.
+  void GenerateNotImplementedMethods(io::Printer* printer);
+
+  // Generate the CallMethod() method of the service.
+  void GenerateCallMethod(io::Printer* printer);
+
+  // Generate the Get{Request,Response}Prototype() methods.
+  void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
+
+  // Generate the stub's implementations of the service methods.
+  void GenerateStubMethods(io::Printer* printer);
+
+  const ServiceDescriptor* descriptor_;
+  map<string, string> vars_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.cc
new file mode 100644
index 0000000..1d74345
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -0,0 +1,871 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void SetStringVariables(const FieldDescriptor* descriptor,
+                        map<string, string>* variables,
+                        const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
+  (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_length"] =
+      SimpleItoa(descriptor->default_value_string().length());
+  string default_variable_string =
+      descriptor->default_value_string().empty()
+          ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
+          : "_default_" + FieldName(descriptor) + "_";
+  (*variables)["default_variable"] = default_variable_string;
+  (*variables)["default_value_init"] =
+      descriptor->default_value_string().empty()
+      ? "" : "*" + default_variable_string;
+  (*variables)["pointer_type"] =
+      descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+  // NOTE: Escaped here to unblock proto1->proto2 migration.
+  // TODO(liujisi): Extend this to apply for other conflicting methods.
+  (*variables)["release_name"] =
+      SafeFunctionName(descriptor->containing_type(),
+                       descriptor, "release_");
+  (*variables)["full_name"] = descriptor->full_name();
+
+  (*variables)["string_piece"] = "::std::string";
+}
+
+}  // namespace
+
+// ===================================================================
+
+StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetStringVariables(descriptor, &variables_, options);
+}
+
+StringFieldGenerator::~StringFieldGenerator() {}
+
+void StringFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
+  // string fields, even when SupportArenas(descriptor_) == false. Why?
+  // The simple answer is to avoid unmaintainable complexity. The reflection
+  // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
+  // string*, except for the pointer tags and related ownership semantics. We
+  // could modify the runtime code to use string* for the not-supporting-arenas
+  // case, but this would require a way to detect which type of class was
+  // generated (adding overhead and complexity to GeneratedMessageReflection)
+  // and littering the runtime code paths with conditionals. It's simpler to
+  // stick with this but use lightweight accessors that assume arena == NULL.
+  // There should be very little overhead anyway because it's just a tagged
+  // pointer in-memory.
+  printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
+}
+
+void StringFieldGenerator::
+GenerateStaticMembers(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_, "static ::std::string* $default_variable$;\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  // If we're using StringFieldGenerator for a field with a ctype, it's
+  // because that ctype isn't actually implemented.  In particular, this is
+  // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
+  // We aren't releasing Cord because it has too many Google-specific
+  // dependencies and we aren't releasing StringPiece because it's hardly
+  // useful outside of Google and because it would get confusing to have
+  // multiple instances of the StringPiece class in different libraries (PCRE
+  // already includes it for their C++ bindings, which came from Google).
+  //
+  // In any case, we make all the accessors private while still actually
+  // using a string to represent the field internally.  This way, we can
+  // guarantee that if we do ever implement the ctype, it won't break any
+  // existing users who might be -- for whatever reason -- already using .proto
+  // files that applied the ctype.  The field can still be accessed via the
+  // reflection interface since the reflection interface is independent of
+  // the string's underlying representation.
+
+  bool unknown_ctype =
+      descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+  if (unknown_ctype) {
+    printer->Outdent();
+    printer->Print(
+      " private:\n"
+      "  // Hidden due to unknown ctype option.\n");
+    printer->Indent();
+  }
+
+  printer->Print(variables_,
+    "$deprecated_attr$const ::std::string& $name$() const;\n"
+    "$deprecated_attr$void set_$name$(const ::std::string& value);\n"
+    "$deprecated_attr$void set_$name$(const char* value);\n"
+    "$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
+                 ";\n"
+    "$deprecated_attr$::std::string* mutable_$name$();\n"
+    "$deprecated_attr$::std::string* $release_name$();\n"
+    "$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n");
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n"
+      "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
+      "    ::std::string* $name$);\n");
+  }
+
+
+  if (unknown_ctype) {
+    printer->Outdent();
+    printer->Print(" public:\n");
+    printer->Indent();
+  }
+}
+
+void StringFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $name$_.Get($default_variable$);\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.Set($default_variable$, $string_piece$(value),\n"
+      "              GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+      "}\n"
+      "$inline$ "
+      "void $classname$::set_$name$(const $pointer_type$* value,\n"
+      "    size_t size) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.Set($default_variable$, $string_piece$(\n"
+      "      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+      "  $clear_hasbit$\n"
+      "  return $name$_.UnsafeArenaRelease($default_variable$,\n"
+      "      GetArenaNoVirtual());\n"
+      "}\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "  if ($name$ != NULL) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  $name$_.SetAllocated($default_variable$, $name$,\n"
+      "      GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
+      "    ::std::string* $name$) {\n"
+      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+      "  if ($name$ != NULL) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
+      "      $name$, GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+      "$full_name$)\n"
+      "}\n");
+  } else {
+    // No-arena case.
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $name$_.GetNoArena($default_variable$);\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.SetNoArena($default_variable$, value);\n"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
+      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+      "}\n"
+      "$inline$ "
+      "void $classname$::set_$name$(const $pointer_type$* value, "
+      "size_t size) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.SetNoArena($default_variable$,\n"
+      "      $string_piece$(reinterpret_cast<const char*>(value), size));\n"
+      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $name$_.MutableNoArena($default_variable$);\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  $clear_hasbit$\n"
+      "  return $name$_.ReleaseNoArena($default_variable$);\n"
+      "}\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "  if ($name$ != NULL) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    // Initialized in GenerateDefaultInstanceAllocator.
+    printer->Print(variables_,
+      "::std::string* $classname$::$default_variable$ = NULL;\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  // Two-dimension specialization here: supporting arenas or not, and default
+  // value is the empty string or not. Complexity here ensures the minimal
+  // number of branches / amount of extraneous code at runtime (given that the
+  // below methods are inlined one-liners)!
+  if (SupportsArenas(descriptor_)) {
+    if (descriptor_->default_value_string().empty()) {
+      printer->Print(variables_,
+        "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
+    } else {
+      printer->Print(variables_,
+        "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
+    }
+  } else {
+    if (descriptor_->default_value_string().empty()) {
+      printer->Print(variables_,
+        "$name$_.ClearToEmptyNoArena($default_variable$);\n");
+    } else {
+      printer->Print(variables_,
+        "$name$_.ClearToDefaultNoArena($default_variable$);\n");
+    }
+  }
+}
+
+void StringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
+    // TODO(gpike): improve this
+    printer->Print(variables_, "set_$name$(from.$name$());\n");
+  } else {
+    printer->Print(variables_,
+      "$set_hasbit$\n"
+      "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+}
+
+void StringFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_.UnsafeSetDefault($default_variable$);\n");
+}
+
+void StringFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_.DestroyNoArena($default_variable$);\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_,
+      "$classname$::$default_variable$ =\n"
+      "    new ::std::string($default$, $default_length$);\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateShutdownCode(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_,
+      "delete $classname$::$default_variable$;\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+    "      input, this->mutable_$name$()));\n");
+
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, true, variables_,
+        "this->$name$().data(), this->$name$().length(),\n", printer);
+  }
+}
+
+void StringFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, false, variables_,
+        "this->$name$().data(), this->$name$().length(),\n", printer);
+  }
+  printer->Print(variables_,
+    "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
+    "  $number$, this->$name$(), output);\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, false, variables_,
+        "this->$name$().data(), this->$name$().length(),\n", printer);
+  }
+  printer->Print(variables_,
+    "target =\n"
+    "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
+    "    $number$, this->$name$(), target);\n");
+}
+
+void StringFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "total_size += $tag_size$ +\n"
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
+    "    this->$name$());\n");
+}
+
+// ===================================================================
+
+StringOneofFieldGenerator::
+StringOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options)
+    : StringFieldGenerator(descriptor, options),
+      dependent_field_(options.proto_h) {
+  SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
+
+void StringOneofFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  if (has_$name$()) {\n"
+      "    return $oneof_prefix$$name$_.Get($default_variable$);\n"
+      "  }\n"
+      "  return *$default_variable$;\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.Set($default_variable$, value,\n"
+      "      GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.Set($default_variable$,\n"
+      "      $string_piece$(value), GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+      "}\n"
+      "$inline$ "
+      "void $classname$::set_$name$(const $pointer_type$* value,\n"
+      "                             size_t size) {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
+      "      reinterpret_cast<const char*>(value), size),\n"
+      "      GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
+      "      GetArenaNoVirtual());\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  if (has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    return $oneof_prefix$$name$_.Release($default_variable$,\n"
+      "        GetArenaNoVirtual());\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+      "  if (has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
+      "        $default_variable$, GetArenaNoVirtual());\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "  if (!has_$name$()) {\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  clear_$oneof_name$();\n"
+      "  if ($name$ != NULL) {\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
+      "        GetArenaNoVirtual());\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
+      "::std::string* $name$) {\n"
+      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+      "  if (!has_$name$()) {\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  clear_$oneof_name$();\n"
+      "  if ($name$) {\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
+      "$name$, GetArenaNoVirtual());\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+      "$full_name$)\n"
+      "}\n");
+  } else {
+    // No-arena case.
+    printer->Print(variables,
+      "$inline$ const ::std::string& $classname$::$name$() const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  if (has_$name$()) {\n"
+      "    return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
+      "  }\n"
+      "  return *$default_variable$;\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+      "}\n"
+      "$inline$ void $classname$::set_$name$(const char* value) {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
+      "      $string_piece$(value));\n"
+      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+      "}\n"
+      "$inline$ "
+      "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  $oneof_prefix$$name$_.SetNoArena($default_variable$, $string_piece$(\n"
+      "      reinterpret_cast<const char*>(value), size));\n"
+      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+      "  if (!has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+      "  return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::$release_name$() {\n"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  if (has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
+      "  } else {\n"
+      "    return NULL;\n"
+      "  }\n"
+      "}\n"
+      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+      "  if (!has_$name$()) {\n"
+      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+      "  }\n"
+      "  clear_$oneof_name$();\n"
+      "  if ($name$ != NULL) {\n"
+      "    set_has_$name$();\n"
+      "    $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
+      "        $name$);\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
+  }
+}
+
+void StringOneofFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  map<string, string> variables(variables_);
+  if (dependent_field_) {
+    variables["this_message"] = DependentBaseDownCast();
+    // This clearing code may be in the dependent base class. If the default
+    // value is an empty string, then the $default_variable$ is a global
+    // singleton. If the default is not empty, we need to down-cast to get the
+    // default value's global singleton instance. See SetStringVariables() for
+    // possible values of default_variable.
+    if (!descriptor_->default_value_string().empty()) {
+      variables["default_variable"] =
+          DependentBaseDownCast() + variables["default_variable"];
+    }
+  } else {
+    variables["this_message"] = "";
+  }
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables,
+      "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
+      "    $this_message$GetArenaNoVirtual());\n");
+  } else {
+    printer->Print(variables,
+      "$this_message$$oneof_prefix$$name$_."
+      "DestroyNoArena($default_variable$);\n");
+  }
+}
+
+void StringOneofFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  // Don't print any swapping code. Swapping the union will swap this field.
+}
+
+void StringOneofFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "  $classname$_default_oneof_instance_->$name$_.UnsafeSetDefault("
+    "$default_variable$);\n");
+}
+
+void StringOneofFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "if (has_$name$()) {\n"
+      "  $oneof_prefix$$name$_.Destroy($default_variable$,\n"
+      "      GetArenaNoVirtual());\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "if (has_$name$()) {\n"
+      "  $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
+      "}\n");
+  }
+}
+
+void StringOneofFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+      "      input, this->mutable_$name$()));\n");
+
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, true, variables_,
+        "this->$name$().data(), this->$name$().length(),\n", printer);
+  }
+}
+
+
+// ===================================================================
+
+RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
+  SetStringVariables(descriptor, &variables_, options);
+}
+
+RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
+
+void RepeatedStringFieldGenerator::
+GeneratePrivateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  // See comment above about unknown ctypes.
+  bool unknown_ctype =
+      descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+  if (unknown_ctype) {
+    printer->Outdent();
+    printer->Print(
+      " private:\n"
+      "  // Hidden due to unknown ctype option.\n");
+    printer->Indent();
+  }
+
+  printer->Print(variables_,
+    "$deprecated_attr$const ::std::string& $name$(int index) const;\n"
+    "$deprecated_attr$::std::string* mutable_$name$(int index);\n"
+    "$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n"
+    "$deprecated_attr$void set_$name$(int index, const char* value);\n"
+    ""
+    "$deprecated_attr$void set_$name$("
+                 "int index, const $pointer_type$* value, size_t size);\n"
+    "$deprecated_attr$::std::string* add_$name$();\n"
+    "$deprecated_attr$void add_$name$(const ::std::string& value);\n"
+    "$deprecated_attr$void add_$name$(const char* value);\n"
+    "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)"
+                 ";\n");
+
+  printer->Print(variables_,
+    "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
+                 "const;\n"
+    "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+                 ";\n");
+
+  if (unknown_ctype) {
+    printer->Outdent();
+    printer->Print(" public:\n");
+    printer->Indent();
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                  bool is_inline) const {
+  map<string, string> variables(variables_);
+  variables["inline"] = is_inline ? "inline" : "";
+  printer->Print(variables,
+    "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return $name$_.$cppget$(index);\n"
+    "}\n"
+    "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
+    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+    "  return $name$_.Mutable(index);\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "  $name$_.Mutable(index)->assign(value);\n"
+    "}\n"
+    "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
+    "  $name$_.Mutable(index)->assign(value);\n"
+    "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+    "}\n"
+    "$inline$ void "
+    "$classname$::set_$name$"
+    "(int index, const $pointer_type$* value, size_t size) {\n"
+    "  $name$_.Mutable(index)->assign(\n"
+    "    reinterpret_cast<const char*>(value), size);\n"
+    "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+    "}\n"
+    "$inline$ ::std::string* $classname$::add_$name$() {\n"
+    "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
+    "  return $name$_.Add();\n"
+    "}\n"
+    "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
+    "  $name$_.Add()->assign(value);\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "}\n"
+    "$inline$ void $classname$::add_$name$(const char* value) {\n"
+    "  $name$_.Add()->assign(value);\n"
+    "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
+    "}\n"
+    "$inline$ void "
+    "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
+    "  $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
+    "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
+    "}\n");
+  printer->Print(variables,
+    "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+    "$classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+    "$classname$::mutable_$name$() {\n"
+    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+    "  return &$name$_;\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateClearingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.Clear();\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSwappingCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateConstructorCode(io::Printer* printer) const {
+  // Not needed for repeated fields.
+}
+
+void RepeatedStringFieldGenerator::
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+  printer->Print(variables_,
+    "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+    "      input, this->add_$name$()));\n");
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, true, variables_,
+        "this->$name$(this->$name$_size() - 1).data(),\n"
+        "this->$name$(this->$name$_size() - 1).length(),\n",
+        printer);
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  printer->Indent();
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, false, variables_,
+        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+  }
+  printer->Outdent();
+  printer->Print(variables_,
+    "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+    "    $number$, this->$name$(i), output);\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+  printer->Indent();
+  if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        descriptor_, options_, false, variables_,
+        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+  }
+  printer->Outdent();
+  printer->Print(variables_,
+    "  target = ::google::protobuf::internal::WireFormatLite::\n"
+    "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateByteSize(io::Printer* printer) const {
+  printer->Print(variables_,
+    "total_size += $tag_size$ * this->$name$_size();\n"
+    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "  total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
+    "    this->$name$(i));\n"
+    "}\n");
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.h
new file mode 100644
index 0000000..cb4e877
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -0,0 +1,132 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class StringFieldGenerator : public FieldGenerator {
+ public:
+  StringFieldGenerator(const FieldDescriptor* descriptor,
+                       const Options& options);
+  ~StringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateStaticMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateDestructorCode(io::Printer* printer) const;
+  void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
+  void GenerateShutdownCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
+};
+
+class StringOneofFieldGenerator : public StringFieldGenerator {
+ public:
+  StringOneofFieldGenerator(const FieldDescriptor* descriptor,
+                            const Options& options);
+  ~StringOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateDestructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+
+ private:
+  const bool dependent_field_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
+};
+
+class RepeatedStringFieldGenerator : public FieldGenerator {
+ public:
+  RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options);
+  ~RepeatedStringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GeneratePrivateMembers(io::Printer* printer) const;
+  void GenerateAccessorDeclarations(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer,
+                                         bool is_inline) const;
+  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMergeFromCodedStream(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
+  void GenerateByteSize(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
new file mode 100644
index 0000000..4e25b2e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -0,0 +1,156 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the C++ code generator.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+package protobuf_unittest;
+
+// Test that fields can have names like "input" and "i" which are also used
+// internally by the code generator for local variables.
+message TestConflictingSymbolNames {
+  message BuildDescriptors {}
+  message TypeTraits {}
+
+  optional int32 input = 1;
+  optional int32 output = 2;
+  optional string length = 3;
+  repeated int32 i = 4;
+  repeated string new_element = 5 [ctype=STRING_PIECE];
+  optional int32 total_size = 6;
+  optional int32 tag = 7;
+
+  enum TestEnum { FOO = 0; }
+  message Data1 { repeated int32 data = 1; }
+  message Data2 { repeated TestEnum data = 1; }
+  message Data3 { repeated string data = 1; }
+  message Data4 { repeated Data4 data = 1; }
+  message Data5 { repeated string data = 1 [ctype=STRING_PIECE]; }
+  message Data6 { repeated string data = 1 [ctype=CORD]; }
+
+  optional int32 source = 8;
+  optional int32 value = 9;
+  optional int32 file = 10;
+  optional int32 from = 11;
+  optional int32 handle_uninterpreted = 12;
+  repeated int32 index = 13;
+  optional int32 controller = 14;
+  optional int32 already_here = 15;
+
+  optional uint32 uint32 = 16;
+  optional uint64 uint64 = 17;
+  optional string string = 18;
+  optional int32 memset = 19;
+  optional int32 int32 = 20;
+  optional int64 int64 = 21;
+
+  optional uint32 cached_size = 22;
+  optional uint32 extensions = 23;
+  optional uint32 bit = 24;
+  optional uint32 bits = 25;
+  optional uint32 offsets = 26;
+  optional uint32 reflection = 27;
+
+  message Cord {}
+  optional string some_cord = 28 [ctype=CORD];
+
+  message StringPiece {}
+  optional string some_string_piece = 29 [ctype=STRING_PIECE];
+
+  // Some keywords.
+  optional uint32 int = 30;
+  optional uint32 friend = 31;
+  optional uint32 class = 37;
+  optional uint32 typedecl = 39;
+  optional uint32 auto = 40;
+
+  // The generator used to #define a macro called "DO" inside the .cc file.
+  message DO {}
+  optional DO do = 32;
+
+  // Some template parameter names for extensions.
+  optional int32 field_type = 33;
+  optional bool is_packed = 34;
+
+  // test conflicting release_$name$. "length" and "do" field in this message
+  // must remain string or message fields to make the test valid.
+  optional string release_length = 35;
+  // A more extreme case, the field name "do" here is a keyword, which will be
+  // escaped to "do_" already. Test there is no conflict even with escaped field
+  // names.
+  optional DO release_do = 36;
+
+  // For clashing local variables in Serialize and ByteSize calculation.
+  optional string target = 38;
+
+  extensions 1000 to max;  // NO_PROTO3
+}
+
+message TestConflictingSymbolNamesExtension {                    // NO_PROTO3
+  extend TestConflictingSymbolNames {                            // NO_PROTO3
+    repeated int32 repeated_int32_ext = 20423638 [packed=true];  // NO_PROTO3
+  }                                                              // NO_PROTO3
+}                                                                // NO_PROTO3
+
+message TestConflictingEnumNames {  // NO_PROTO3
+  enum NestedConflictingEnum {      // NO_PROTO3
+    and = 1;                        // NO_PROTO3
+    class = 2;                      // NO_PROTO3
+    int = 3;                        // NO_PROTO3
+    typedef = 4;                    // NO_PROTO3
+    XOR = 5;                        // NO_PROTO3
+  }                                 // NO_PROTO3
+
+  optional NestedConflictingEnum conflicting_enum = 1;  // NO_PROTO3
+}  // NO_PROTO3
+
+enum ConflictingEnum {  // NO_PROTO3
+  NOT_EQ = 1;           // NO_PROTO3
+  volatile = 2;         // NO_PROTO3
+  return = 3;           // NO_PROTO3
+}  // NO_PROTO3
+
+message DummyMessage {}
+
+service TestConflictingMethodNames {
+  rpc Closure(DummyMessage) returns (DummyMessage);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
new file mode 100644
index 0000000..cb6ca1b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
@@ -0,0 +1,43 @@
+// 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.
+
+// Test that proto2 compiler can generate valid code when the enum value
+// is INT_MAX. Note that this is a compile-only test and this proto is not
+// referenced in any C++ code.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message TestLargeEnumValue {
+  enum EnumWithLargeValue {
+    VALUE_1 = 1;
+    VALUE_MAX = 0x7fffffff;
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.cc
new file mode 100644
index 0000000..5d82946
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -0,0 +1,2139 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// To test the code generator, we actually use it to generate code for
+// google/protobuf/unittest.proto, then test that.  This means that we
+// are actually testing the parser and other parts of the system at the same
+// time, and that problems in the generator may show up as compile-time errors
+// rather than unittest failures, which may be surprising.  However, testing
+// the output of the C++ generator directly would be very hard.  We can't very
+// well just check it against golden files since those files would have to be
+// updated for any small change; such a test would be very brittle and probably
+// not very helpful.  What we really want to test is that the code compiles
+// correctly and produces the interfaces we expect, which is why this test
+// is written this way.
+
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_optimize_for.pb.h>
+#include <google/protobuf/unittest_embed_optimize_for.pb.h>
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// We exclude this large proto from cmake build because it's too large for
+// visual studio to compile (report internal errors).
+#include <google/protobuf/unittest_enormous_descriptor.pb.h>
+#endif
+#include <google/protobuf/unittest_no_generic_services.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+namespace protobuf_unittest = ::protobuf_unittest;
+
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+};
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Test that generated code has proper descriptors:
+// Parse a descriptor directly (using google::protobuf::compiler::Importer) and
+// compare it to the one that was produced by generated code.
+TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
+  const FileDescriptor* generated_descriptor =
+    unittest::TestAllTypes::descriptor()->file();
+
+  // Set up the Importer.
+  MockErrorCollector error_collector;
+  DiskSourceTree source_tree;
+  source_tree.MapPath("", TestSourceDir());
+  Importer importer(&source_tree, &error_collector);
+
+  // Import (parse) unittest.proto.
+  const FileDescriptor* parsed_descriptor =
+    importer.Import("google/protobuf/unittest.proto");
+  EXPECT_EQ("", error_collector.text_);
+  ASSERT_TRUE(parsed_descriptor != NULL);
+
+  // Test that descriptors are generated correctly by converting them to
+  // FileDescriptorProtos and comparing.
+  FileDescriptorProto generated_decsriptor_proto, parsed_descriptor_proto;
+  generated_descriptor->CopyTo(&generated_decsriptor_proto);
+  parsed_descriptor->CopyTo(&parsed_descriptor_proto);
+
+  EXPECT_EQ(parsed_descriptor_proto.DebugString(),
+            generated_decsriptor_proto.DebugString());
+}
+
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// Test that generated code has proper descriptors:
+// Touch a descriptor generated from an enormous message to validate special
+// handling for descriptors exceeding the C++ standard's recommended minimum
+// limit for string literal size
+TEST(GeneratedDescriptorTest, EnormousDescriptor) {
+  const Descriptor* generated_descriptor =
+    TestEnormousDescriptor::descriptor();
+
+  EXPECT_TRUE(generated_descriptor != NULL);
+}
+#endif
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+TEST(GeneratedMessageTest, Defaults) {
+  // Check that all default values are set correctly in the initial message.
+  unittest::TestAllTypes message;
+
+  TestUtil::ExpectClear(message);
+
+  // Messages should return pointers to default instances until first use.
+  // (This is not checked by ExpectClear() since it is not actually true after
+  // the fields have been set and then cleared.)
+  EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(),
+            &message.optionalgroup());
+  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+  EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
+            &message.optional_foreign_message());
+  EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
+            &message.optional_import_message());
+}
+
+#ifndef PROTOBUF_USE_DLLS
+TEST(GeneratedMessageTest, Int32StringConversion) {
+  EXPECT_EQ("971", Int32ToString(971));
+  EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min));
+  EXPECT_EQ("2147483647", Int32ToString(kint32max));
+}
+
+TEST(GeneratedMessageTest, Int64StringConversion) {
+  EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971));
+  EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min));
+  EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min));
+  EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max));
+}
+#endif  // !PROTOBUF_USE_DLLS
+
+TEST(GeneratedMessageTest, FloatingPointDefaults) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ(0.0f, extreme_default.zero_float());
+  EXPECT_EQ(1.0f, extreme_default.one_float());
+  EXPECT_EQ(1.5f, extreme_default.small_float());
+  EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
+  EXPECT_EQ(-1.5f, extreme_default.negative_float());
+  EXPECT_EQ(2.0e8f, extreme_default.large_float());
+  EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
+  EXPECT_EQ(numeric_limits<double>::infinity(),
+            extreme_default.inf_double());
+  EXPECT_EQ(-numeric_limits<double>::infinity(),
+            extreme_default.neg_inf_double());
+  EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
+  EXPECT_EQ(numeric_limits<float>::infinity(),
+            extreme_default.inf_float());
+  EXPECT_EQ(-numeric_limits<float>::infinity(),
+            extreme_default.neg_inf_float());
+  EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
+}
+
+TEST(GeneratedMessageTest, Trigraph) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
+}
+
+TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+  EXPECT_EQ(~0x7fffffff, kint32min);
+  EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min);
+  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
+  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+}
+
+TEST(GeneratedMessageTest, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  unittest::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+
+  TestUtil::ModifyRepeatedFields(&message);
+  TestUtil::ExpectRepeatedFieldsModified(message);
+}
+
+TEST(GeneratedMessageTest, MutableStringDefault) {
+  // mutable_foo() for a string should return a string initialized to its
+  // default value.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ("hello", *message.mutable_default_string());
+
+  // Note that the first time we call mutable_foo(), we get a newly-allocated
+  // string, but if we clear it and call it again, we get the same object again.
+  // We should verify that it has its default value in both cases.
+  message.set_default_string("blah");
+  message.Clear();
+
+  EXPECT_EQ("hello", *message.mutable_default_string());
+}
+
+TEST(GeneratedMessageTest, StringDefaults) {
+  unittest::TestExtremeDefaultValues message;
+  // Check if '\000' can be used in default string value.
+  EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
+  EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
+}
+
+TEST(GeneratedMessageTest, ReleaseString) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+
+  message.set_default_string("blah");
+  EXPECT_TRUE(message.has_default_string());
+  google::protobuf::scoped_ptr<string> str(message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+}
+
+TEST(GeneratedMessageTest, ReleaseMessage) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  google::protobuf::scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
+      message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_EQ(1, nest->bb());
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+}
+
+TEST(GeneratedMessageTest, SetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  unittest::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_string());
+  const string kHello("hello");
+  message.set_optional_string(kHello);
+  EXPECT_TRUE(message.has_optional_string());
+
+  message.set_allocated_optional_string(NULL);
+  EXPECT_FALSE(message.has_optional_string());
+  EXPECT_EQ("", message.optional_string());
+
+  message.set_allocated_optional_string(new string(kHello));
+  EXPECT_TRUE(message.has_optional_string());
+  EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GeneratedMessageTest, SetAllocatedMessage) {
+  // Check that set_allocated_foo() can be called in all cases.
+  unittest::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  EXPECT_TRUE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  unittest::TestAllTypes::NestedMessage* nest =
+      message.release_optional_nested_message();
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(nest);
+  EXPECT_TRUE(message.has_optional_nested_message());
+  EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
+TEST(GeneratedMessageTest, Clear) {
+  // Set every field to a unique value, clear the message, then check that
+  // it is cleared.
+  unittest::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  message.Clear();
+  TestUtil::ExpectClear(message);
+
+  // Unlike with the defaults test, we do NOT expect that requesting embedded
+  // messages will return a pointer to the default instance.  Instead, they
+  // should return the objects that were created when mutable_blah() was
+  // called.
+  EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
+            &message.optionalgroup());
+  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
+            &message.optional_foreign_message());
+  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
+            &message.optional_import_message());
+}
+
+TEST(GeneratedMessageTest, EmbeddedNullsInBytesCharStar) {
+  unittest::TestAllTypes message;
+
+  const char* value = "\0lalala\0\0";
+  message.set_optional_bytes(value, 9);
+  ASSERT_EQ(9, message.optional_bytes().size());
+  EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9));
+
+  message.add_repeated_bytes(value, 9);
+  ASSERT_EQ(9, message.repeated_bytes(0).size());
+  EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9));
+}
+
+TEST(GeneratedMessageTest, ClearOneField) {
+  // Set every field to a unique value, then clear one value and insure that
+  // only that one value is cleared.
+  unittest::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  int64 original_value = message.optional_int64();
+
+  // Clear the field and make sure it shows up as cleared.
+  message.clear_optional_int64();
+  EXPECT_FALSE(message.has_optional_int64());
+  EXPECT_EQ(0, message.optional_int64());
+
+  // Other adjacent fields should not be cleared.
+  EXPECT_TRUE(message.has_optional_int32());
+  EXPECT_TRUE(message.has_optional_uint32());
+
+  // Make sure if we set it again, then all fields are set.
+  message.set_optional_int64(original_value);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageTest, StringCharStarLength) {
+  // Verify that we can use a char*,length to set one of the string fields.
+  unittest::TestAllTypes message;
+  message.set_optional_string("abcdef", 3);
+  EXPECT_EQ("abc", message.optional_string());
+
+  // Verify that we can use a char*,length to add to a repeated string field.
+  message.add_repeated_string("abcdef", 3);
+  EXPECT_EQ(1, message.repeated_string_size());
+  EXPECT_EQ("abc", message.repeated_string(0));
+
+  // Verify that we can use a char*,length to set a repeated string field.
+  message.set_repeated_string(0, "wxyz", 2);
+  EXPECT_EQ("wx", message.repeated_string(0));
+}
+
+
+TEST(GeneratedMessageTest, CopyFrom) {
+  unittest::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+  message2.CopyFrom(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+
+TEST(GeneratedMessageTest, SwapWithEmpty) {
+  unittest::TestAllTypes message1, message2;
+  TestUtil::SetAllFields(&message1);
+
+  TestUtil::ExpectAllFieldsSet(message1);
+  TestUtil::ExpectClear(message2);
+  message1.Swap(&message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+  TestUtil::ExpectClear(message1);
+}
+
+TEST(GeneratedMessageTest, SwapWithSelf) {
+  unittest::TestAllTypes message;
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+  message.Swap(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageTest, SwapWithOther) {
+  unittest::TestAllTypes message1, message2;
+
+  message1.set_optional_int32(123);
+  message1.set_optional_string("abc");
+  message1.mutable_optional_nested_message()->set_bb(1);
+  message1.set_optional_nested_enum(unittest::TestAllTypes::FOO);
+  message1.add_repeated_int32(1);
+  message1.add_repeated_int32(2);
+  message1.add_repeated_string("a");
+  message1.add_repeated_string("b");
+  message1.add_repeated_nested_message()->set_bb(7);
+  message1.add_repeated_nested_message()->set_bb(8);
+  message1.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
+  message1.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
+
+  message2.set_optional_int32(456);
+  message2.set_optional_string("def");
+  message2.mutable_optional_nested_message()->set_bb(2);
+  message2.set_optional_nested_enum(unittest::TestAllTypes::BAR);
+  message2.add_repeated_int32(3);
+  message2.add_repeated_string("c");
+  message2.add_repeated_nested_message()->set_bb(9);
+  message2.add_repeated_nested_enum(unittest::TestAllTypes::BAZ);
+
+  message1.Swap(&message2);
+
+  EXPECT_EQ(456, message1.optional_int32());
+  EXPECT_EQ("def", message1.optional_string());
+  EXPECT_EQ(2, message1.optional_nested_message().bb());
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message1.optional_nested_enum());
+  ASSERT_EQ(1, message1.repeated_int32_size());
+  EXPECT_EQ(3, message1.repeated_int32(0));
+  ASSERT_EQ(1, message1.repeated_string_size());
+  EXPECT_EQ("c", message1.repeated_string(0));
+  ASSERT_EQ(1, message1.repeated_nested_message_size());
+  EXPECT_EQ(9, message1.repeated_nested_message(0).bb());
+  ASSERT_EQ(1, message1.repeated_nested_enum_size());
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message1.repeated_nested_enum(0));
+
+  EXPECT_EQ(123, message2.optional_int32());
+  EXPECT_EQ("abc", message2.optional_string());
+  EXPECT_EQ(1, message2.optional_nested_message().bb());
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message2.optional_nested_enum());
+  ASSERT_EQ(2, message2.repeated_int32_size());
+  EXPECT_EQ(1, message2.repeated_int32(0));
+  EXPECT_EQ(2, message2.repeated_int32(1));
+  ASSERT_EQ(2, message2.repeated_string_size());
+  EXPECT_EQ("a", message2.repeated_string(0));
+  EXPECT_EQ("b", message2.repeated_string(1));
+  ASSERT_EQ(2, message2.repeated_nested_message_size());
+  EXPECT_EQ(7, message2.repeated_nested_message(0).bb());
+  EXPECT_EQ(8, message2.repeated_nested_message(1).bb());
+  ASSERT_EQ(2, message2.repeated_nested_enum_size());
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message2.repeated_nested_enum(0));
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message2.repeated_nested_enum(1));
+}
+
+TEST(GeneratedMessageTest, CopyConstructor) {
+  unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+
+  unittest::TestAllTypes message2(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(GeneratedMessageTest, CopyAssignmentOperator) {
+  unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+
+  unittest::TestAllTypes message2;
+  message2 = message1;
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Make sure that self-assignment does something sane.
+  message2.operator=(message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
+    !defined(GOOGLE_PROTOBUF_NO_RTTI)
+TEST(GeneratedMessageTest, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  unittest::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+#endif
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
+  // Test copying from a DynamicMessage, which must fall back to using
+  // reflection.
+  unittest::TestAllTypes message2;
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(factory.GetPrototype(
+                     unittest::TestAllTypes::descriptor())->New());
+
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+  reflection_tester.SetAllFieldsViaReflection(message1.get());
+
+  message2.CopyFrom(*message1);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
+  // Test merging with a non-empty message. Code is a modified form
+  // of that found in google/protobuf/reflection_ops_unittest.cc.
+  unittest::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  // This field will test merging into an empty spot.
+  message2.set_optional_int32(message1.optional_int32());
+  message1.clear_optional_int32();
+
+  // This tests overwriting.
+  message2.set_optional_string(message1.optional_string());
+  message1.set_optional_string("something else");
+
+  // This tests concatenating.
+  message2.add_repeated_int32(message1.repeated_int32(1));
+  int32 i = message1.repeated_int32(0);
+  message1.clear_repeated_int32();
+  message1.add_repeated_int32(i);
+
+  message1.MergeFrom(message2);
+
+  TestUtil::ExpectAllFieldsSet(message1);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
+    !defined(GOOGLE_PROTOBUF_NO_RTTI)
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+TEST(GeneratedMessageTest, MergeFromSelf) {
+  unittest::TestAllTypes message;
+  EXPECT_DEATH(message.MergeFrom(message), "Check failed:.*pb[.]cc");
+  EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
+               "Check failed:.*pb[.]cc");
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI
+
+// Test the generated SerializeWithCachedSizesToArray(),
+TEST(GeneratedMessageTest, SerializationToArray) {
+  unittest::TestAllTypes message1, message2;
+  string data;
+  TestUtil::SetAllFields(&message1);
+  int size = message1.ByteSize();
+  data.resize(size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(size, end - start);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GeneratedMessageTest, PackedFieldsSerializationToArray) {
+  unittest::TestPackedTypes packed_message1, packed_message2;
+  string packed_data;
+  TestUtil::SetPackedFields(&packed_message1);
+  int packed_size = packed_message1.ByteSize();
+  packed_data.resize(packed_size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&packed_data));
+  uint8* end = packed_message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(packed_size, end - start);
+  EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
+  TestUtil::ExpectPackedFieldsSet(packed_message2);
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+TEST(GeneratedMessageTest, SerializationToStream) {
+  unittest::TestAllTypes message1, message2;
+  TestUtil::SetAllFields(&message1);
+  int size = message1.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GeneratedMessageTest, PackedFieldsSerializationToStream) {
+  unittest::TestPackedTypes message1, message2;
+  TestUtil::SetPackedFields(&message1);
+  int size = message1.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectPackedFieldsSet(message2);
+}
+
+
+TEST(GeneratedMessageTest, Required) {
+  // Test that IsInitialized() returns false if required fields are missing.
+  unittest::TestRequired message;
+
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_a(1);
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_b(2);
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GeneratedMessageTest, RequiredForeign) {
+  // Test that IsInitialized() returns false if required fields in nested
+  // messages are missing.
+  unittest::TestRequiredForeign message;
+
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.mutable_optional_message();
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.mutable_optional_message()->set_a(1);
+  message.mutable_optional_message()->set_b(2);
+  message.mutable_optional_message()->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.add_repeated_message();
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.mutable_repeated_message(0)->set_a(1);
+  message.mutable_repeated_message(0)->set_b(2);
+  message.mutable_repeated_message(0)->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GeneratedMessageTest, ForeignNested) {
+  // Test that TestAllTypes::NestedMessage can be embedded directly into
+  // another message.
+  unittest::TestForeignNested message;
+
+  // If this compiles and runs without crashing, it must work.  We have
+  // nothing more to test.
+  unittest::TestAllTypes::NestedMessage* nested =
+    message.mutable_foreign_nested();
+  nested->set_bb(1);
+}
+
+TEST(GeneratedMessageTest, ReallyLargeTagNumber) {
+  // Test that really large tag numbers don't break anything.
+  unittest::TestReallyLargeTagNumber message1, message2;
+  string data;
+
+  // For the most part, if this compiles and runs then we're probably good.
+  // (The most likely cause for failure would be if something were attempting
+  // to allocate a lookup table of some sort using tag numbers as the index.)
+  // We'll try serializing just for fun.
+  message1.set_a(1234);
+  message1.set_bb(5678);
+  message1.SerializeToString(&data);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  EXPECT_EQ(1234, message2.a());
+  EXPECT_EQ(5678, message2.bb());
+}
+
+TEST(GeneratedMessageTest, MutualRecursion) {
+  // Test that mutually-recursive message types work.
+  unittest::TestMutualRecursionA message;
+  unittest::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a();
+  unittest::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a();
+
+  // Again, if the above compiles and runs, that's all we really have to
+  // test, but just for run we'll check that the system didn't somehow come
+  // up with a pointer loop...
+  EXPECT_NE(&message, nested);
+  EXPECT_NE(&message, nested2);
+  EXPECT_NE(nested, nested2);
+}
+
+TEST(GeneratedMessageTest, CamelCaseFieldNames) {
+  // This test is mainly checking that the following compiles, which verifies
+  // that the field names were coerced to lower-case.
+  //
+  // Protocol buffers standard style is to use lowercase-with-underscores for
+  // field names.  Some old proto1 .protos unfortunately used camel-case field
+  // names.  In proto1, these names were forced to lower-case.  So, we do the
+  // same thing in proto2.
+
+  unittest::TestCamelCaseFieldNames message;
+
+  message.set_primitivefield(2);
+  message.set_stringfield("foo");
+  message.set_enumfield(unittest::FOREIGN_FOO);
+  message.mutable_messagefield()->set_c(6);
+
+  message.add_repeatedprimitivefield(8);
+  message.add_repeatedstringfield("qux");
+  message.add_repeatedenumfield(unittest::FOREIGN_BAR);
+  message.add_repeatedmessagefield()->set_c(15);
+
+  EXPECT_EQ(2, message.primitivefield());
+  EXPECT_EQ("foo", message.stringfield());
+  EXPECT_EQ(unittest::FOREIGN_FOO, message.enumfield());
+  EXPECT_EQ(6, message.messagefield().c());
+
+  EXPECT_EQ(8, message.repeatedprimitivefield(0));
+  EXPECT_EQ("qux", message.repeatedstringfield(0));
+  EXPECT_EQ(unittest::FOREIGN_BAR, message.repeatedenumfield(0));
+  EXPECT_EQ(15, message.repeatedmessagefield(0).c());
+}
+
+TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
+  // test_bad_identifiers.proto successfully compiled, then it works.  The
+  // following is just a token usage to insure that the code is, in fact,
+  // being compiled and linked.
+
+  protobuf_unittest::TestConflictingSymbolNames message;
+  message.set_uint32(1);
+  EXPECT_EQ(3, message.ByteSize());
+
+  message.set_friend_(5);
+  EXPECT_EQ(5, message.friend_());
+
+  message.set_class_(6);
+  EXPECT_EQ(6, message.class_());
+
+  // Instantiate extension template functions to test conflicting template
+  // parameter names.
+  typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
+  message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
+  EXPECT_EQ(123,
+            message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
+}
+
+TEST(GeneratedMessageTest, TestConflictingEnumNames) {
+  protobuf_unittest::TestConflictingEnumNames message;
+  message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_);
+  EXPECT_EQ(1, message.conflicting_enum());
+  message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR);
+  EXPECT_EQ(5, message.conflicting_enum());
+
+
+  protobuf_unittest::ConflictingEnum conflicting_enum;
+  conflicting_enum = protobuf_unittest::NOT_EQ;
+  EXPECT_EQ(1, conflicting_enum);
+  conflicting_enum = protobuf_unittest::return_;
+  EXPECT_EQ(3, conflicting_enum);
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMessageTest, TestOptimizedForSize) {
+  // We rely on the tests in reflection_ops_unittest and wire_format_unittest
+  // to really test that reflection-based methods work.  Here we are mostly
+  // just making sure that TestOptimizedForSize actually builds and seems to
+  // function.
+
+  protobuf_unittest::TestOptimizedForSize message, message2;
+  message.set_i(1);
+  message.mutable_msg()->set_c(2);
+  message2.CopyFrom(message);
+  EXPECT_EQ(1, message2.i());
+  EXPECT_EQ(2, message2.msg().c());
+}
+
+TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) {
+  // Verifies that something optimized for speed can contain something optimized
+  // for size.
+
+  protobuf_unittest::TestEmbedOptimizedForSize message, message2;
+  message.mutable_optional_message()->set_i(1);
+  message.add_repeated_message()->mutable_msg()->set_c(2);
+  string data;
+  message.SerializeToString(&data);
+  ASSERT_TRUE(message2.ParseFromString(data));
+  EXPECT_EQ(1, message2.optional_message().i());
+  EXPECT_EQ(2, message2.repeated_message(0).msg().c());
+}
+
+TEST(GeneratedMessageTest, TestSpaceUsed) {
+  unittest::TestAllTypes message1;
+  // sizeof provides a lower bound on SpaceUsed().
+  EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed());
+  const int empty_message_size = message1.SpaceUsed();
+
+  // Setting primitive types shouldn't affect the space used.
+  message1.set_optional_int32(123);
+  message1.set_optional_int64(12345);
+  message1.set_optional_uint32(123);
+  message1.set_optional_uint64(12345);
+  EXPECT_EQ(empty_message_size, message1.SpaceUsed());
+
+  // On some STL implementations, setting the string to a small value should
+  // only increase SpaceUsed() by the size of a string object, though this is
+  // not true everywhere.
+  message1.set_optional_string("abc");
+  EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
+
+  // Setting a string to a value larger than the string object itself should
+  // increase SpaceUsed(), because it cannot store the value internally.
+  message1.set_optional_string(string(sizeof(string) + 1, 'x'));
+  int min_expected_increase = message1.optional_string().capacity() +
+      sizeof(string);
+  EXPECT_LE(empty_message_size + min_expected_increase,
+            message1.SpaceUsed());
+
+  int previous_size = message1.SpaceUsed();
+  // Adding an optional message should increase the size by the size of the
+  // nested message type. NestedMessage is simple enough (1 int field) that it
+  // is equal to sizeof(NestedMessage)
+  message1.mutable_optional_nested_message();
+  ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage),
+            message1.optional_nested_message().SpaceUsed());
+  EXPECT_EQ(previous_size +
+            sizeof(unittest::TestAllTypes::NestedMessage),
+            message1.SpaceUsed());
+}
+
+TEST(GeneratedMessageTest, TestOneofSpaceUsed) {
+  unittest::TestOneof2 message1;
+  EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed());
+
+  const int empty_message_size = message1.SpaceUsed();
+  // Setting primitive types shouldn't affect the space used.
+  message1.set_foo_int(123);
+  message1.set_bar_int(12345);
+  EXPECT_EQ(empty_message_size, message1.SpaceUsed());
+
+  // Setting a string in oneof to a small value should only increase SpaceUsed()
+  // by the size of a string object.
+  message1.set_foo_string("abc");
+  EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
+
+  // Setting a string in oneof to a value larger than the string object itself
+  // should increase SpaceUsed(), because it cannot store the value internally.
+  message1.set_foo_string(string(sizeof(string) + 1, 'x'));
+  int min_expected_increase = message1.foo_string().capacity() +
+      sizeof(string);
+  EXPECT_LE(empty_message_size + min_expected_increase,
+            message1.SpaceUsed());
+
+  // Setting a message in oneof should delete the other fields and increase the
+  // size by the size of the nested message type. NestedMessage is simple enough
+  // that it is equal to sizeof(NestedMessage)
+  message1.mutable_foo_message();
+  ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage),
+            message1.foo_message().SpaceUsed());
+  EXPECT_EQ(empty_message_size +
+            sizeof(unittest::TestOneof2::NestedMessage),
+            message1.SpaceUsed());
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+
+TEST(GeneratedMessageTest, FieldConstantValues) {
+  unittest::TestRequired message;
+  EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
+  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
+  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
+}
+
+TEST(GeneratedMessageTest, ExtensionConstantValues) {
+  EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000);
+  EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001);
+  EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1);
+  EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16);
+  EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18);
+  EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21);
+  EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31);
+  EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46);
+  EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48);
+  EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
+}
+
+TEST(GeneratedMessageTest, ParseFromTruncated) {
+  const string long_string = string(128, 'q');
+  FileDescriptorProto p;
+  p.add_extension()->set_name(long_string);
+  const string msg = p.SerializeAsString();
+  int successful_count = 0;
+  for (int i = 0; i <= msg.size(); i++) {
+    if (p.ParseFromArray(msg.c_str(), i)) {
+      ++successful_count;
+    }
+  }
+  // We don't really care about how often we succeeded.
+  // As long as we didn't crash, we're happy.
+  EXPECT_GE(successful_count, 1);
+}
+
+// ===================================================================
+
+TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
+  // Test that our nested enum values can be used as switch cases.  This test
+  // doesn't actually do anything, the proof that it works is that it
+  // compiles.
+  int i =0;
+  unittest::TestAllTypes::NestedEnum a = unittest::TestAllTypes::BAR;
+  switch (a) {
+    case unittest::TestAllTypes::FOO:
+      i = 1;
+      break;
+    case unittest::TestAllTypes::BAR:
+      i = 2;
+      break;
+    case unittest::TestAllTypes::BAZ:
+      i = 3;
+      break;
+    case unittest::TestAllTypes::NEG:
+      i = -1;
+      break;
+    // no default case:  We want to make sure the compiler recognizes that
+    //   all cases are covered.  (GCC warns if you do not cover all cases of
+    //   an enum in a switch.)
+  }
+
+  // Token check just for fun.
+  EXPECT_EQ(2, i);
+}
+
+TEST(GeneratedEnumTest, IsValidValue) {
+  // Test enum IsValidValue.
+  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(1));
+  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(2));
+  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(3));
+
+  EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(0));
+  EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(4));
+
+  // Make sure it also works when there are dups.
+  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(1));
+  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(2));
+  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(3));
+
+  EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(0));
+  EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(4));
+}
+
+TEST(GeneratedEnumTest, MinAndMax) {
+  EXPECT_EQ(unittest::TestAllTypes::NEG,
+            unittest::TestAllTypes::NestedEnum_MIN);
+  EXPECT_EQ(unittest::TestAllTypes::BAZ,
+            unittest::TestAllTypes::NestedEnum_MAX);
+  EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+  EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN);
+  EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX);
+  EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE);
+
+  EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN);
+  EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX);
+  EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE);
+
+  EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN);
+  EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX);
+  EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
+
+  // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
+  void* null_pointer = 0;  // NULL may be integer-type, not pointer-type.
+  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN);
+  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX);
+  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+  EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN);
+  EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
+  EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
+
+  // Make sure we can use _MIN and _MAX as switch cases.
+  switch (unittest::SPARSE_A) {
+    case unittest::TestSparseEnum_MIN:
+    case unittest::TestSparseEnum_MAX:
+      break;
+    default:
+      break;
+  }
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedEnumTest, Name) {
+  // "Names" in the presence of dup values are a bit arbitrary.
+  EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO1));
+  EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO2));
+
+  EXPECT_EQ("SPARSE_A", unittest::TestSparseEnum_Name(unittest::SPARSE_A));
+  EXPECT_EQ("SPARSE_B", unittest::TestSparseEnum_Name(unittest::SPARSE_B));
+  EXPECT_EQ("SPARSE_C", unittest::TestSparseEnum_Name(unittest::SPARSE_C));
+  EXPECT_EQ("SPARSE_D", unittest::TestSparseEnum_Name(unittest::SPARSE_D));
+  EXPECT_EQ("SPARSE_E", unittest::TestSparseEnum_Name(unittest::SPARSE_E));
+  EXPECT_EQ("SPARSE_F", unittest::TestSparseEnum_Name(unittest::SPARSE_F));
+  EXPECT_EQ("SPARSE_G", unittest::TestSparseEnum_Name(unittest::SPARSE_G));
+}
+
+TEST(GeneratedEnumTest, Parse) {
+  unittest::TestEnumWithDupValue dup_value = unittest::FOO1;
+  EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO1", &dup_value));
+  EXPECT_EQ(unittest::FOO1, dup_value);
+  EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO2", &dup_value));
+  EXPECT_EQ(unittest::FOO2, dup_value);
+  EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
+}
+
+TEST(GeneratedEnumTest, GetEnumDescriptor) {
+  EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(),
+            GetEnumDescriptor<unittest::TestAllTypes::NestedEnum>());
+  EXPECT_EQ(unittest::ForeignEnum_descriptor(),
+            GetEnumDescriptor<unittest::ForeignEnum>());
+  EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(),
+            GetEnumDescriptor<unittest::TestEnumWithDupValue>());
+  EXPECT_EQ(unittest::TestSparseEnum_descriptor(),
+            GetEnumDescriptor<unittest::TestSparseEnum>());
+}
+
+enum NonProtoEnum {
+  kFoo = 1,
+};
+
+TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) {
+  EXPECT_TRUE(is_proto_enum<unittest::TestAllTypes::NestedEnum>::value);
+  EXPECT_TRUE(is_proto_enum<unittest::ForeignEnum>::value);
+  EXPECT_TRUE(is_proto_enum<unittest::TestEnumWithDupValue>::value);
+  EXPECT_TRUE(is_proto_enum<unittest::TestSparseEnum>::value);
+
+  EXPECT_FALSE(is_proto_enum<int>::value);
+  EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value);
+}
+
+#endif  // PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Support code for testing services.
+class GeneratedServiceTest : public testing::Test {
+ protected:
+  class MockTestService : public unittest::TestService {
+   public:
+    MockTestService()
+      : called_(false),
+        method_(""),
+        controller_(NULL),
+        request_(NULL),
+        response_(NULL),
+        done_(NULL) {}
+
+    ~MockTestService() {}
+
+    void Reset() { called_ = false; }
+
+    // implements TestService ----------------------------------------
+
+    void Foo(RpcController* controller,
+             const unittest::FooRequest* request,
+             unittest::FooResponse* response,
+             Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = "Foo";
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    void Bar(RpcController* controller,
+             const unittest::BarRequest* request,
+             unittest::BarResponse* response,
+             Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = "Bar";
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    // ---------------------------------------------------------------
+
+    bool called_;
+    string method_;
+    RpcController* controller_;
+    const Message* request_;
+    Message* response_;
+    Closure* done_;
+  };
+
+  class MockRpcChannel : public RpcChannel {
+   public:
+    MockRpcChannel()
+      : called_(false),
+        method_(NULL),
+        controller_(NULL),
+        request_(NULL),
+        response_(NULL),
+        done_(NULL),
+        destroyed_(NULL) {}
+
+    ~MockRpcChannel() {
+      if (destroyed_ != NULL) *destroyed_ = true;
+    }
+
+    void Reset() { called_ = false; }
+
+    // implements TestService ----------------------------------------
+
+    void CallMethod(const MethodDescriptor* method,
+                    RpcController* controller,
+                    const Message* request,
+                    Message* response,
+                    Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = method;
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    // ---------------------------------------------------------------
+
+    bool called_;
+    const MethodDescriptor* method_;
+    RpcController* controller_;
+    const Message* request_;
+    Message* response_;
+    Closure* done_;
+    bool* destroyed_;
+  };
+
+  class MockController : public RpcController {
+   public:
+    void Reset() {
+      ADD_FAILURE() << "Reset() not expected during this test.";
+    }
+    bool Failed() const {
+      ADD_FAILURE() << "Failed() not expected during this test.";
+      return false;
+    }
+    string ErrorText() const {
+      ADD_FAILURE() << "ErrorText() not expected during this test.";
+      return "";
+    }
+    void StartCancel() {
+      ADD_FAILURE() << "StartCancel() not expected during this test.";
+    }
+    void SetFailed(const string& reason) {
+      ADD_FAILURE() << "SetFailed() not expected during this test.";
+    }
+    bool IsCanceled() const {
+      ADD_FAILURE() << "IsCanceled() not expected during this test.";
+      return false;
+    }
+    void NotifyOnCancel(Closure* callback) {
+      ADD_FAILURE() << "NotifyOnCancel() not expected during this test.";
+    }
+  };
+
+  GeneratedServiceTest()
+    : descriptor_(unittest::TestService::descriptor()),
+      foo_(descriptor_->FindMethodByName("Foo")),
+      bar_(descriptor_->FindMethodByName("Bar")),
+      stub_(&mock_channel_),
+      done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {}
+
+  virtual void SetUp() {
+    ASSERT_TRUE(foo_ != NULL);
+    ASSERT_TRUE(bar_ != NULL);
+  }
+
+  const ServiceDescriptor* descriptor_;
+  const MethodDescriptor* foo_;
+  const MethodDescriptor* bar_;
+
+  MockTestService mock_service_;
+  MockController mock_controller_;
+
+  MockRpcChannel mock_channel_;
+  unittest::TestService::Stub stub_;
+
+  // Just so we don't have to re-define these with every test.
+  unittest::FooRequest foo_request_;
+  unittest::FooResponse foo_response_;
+  unittest::BarRequest bar_request_;
+  unittest::BarResponse bar_response_;
+  google::protobuf::scoped_ptr<Closure> done_;
+};
+
+TEST_F(GeneratedServiceTest, GetDescriptor) {
+  // Test that GetDescriptor() works.
+
+  EXPECT_EQ(descriptor_, mock_service_.GetDescriptor());
+}
+
+TEST_F(GeneratedServiceTest, GetChannel) {
+  EXPECT_EQ(&mock_channel_, stub_.channel());
+}
+
+TEST_F(GeneratedServiceTest, OwnsChannel) {
+  MockRpcChannel* channel = new MockRpcChannel;
+  bool destroyed = false;
+  channel->destroyed_ = &destroyed;
+
+  {
+    unittest::TestService::Stub owning_stub(channel,
+                                            Service::STUB_OWNS_CHANNEL);
+    EXPECT_FALSE(destroyed);
+  }
+
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(GeneratedServiceTest, CallMethod) {
+  // Test that CallMethod() works.
+
+  // Call Foo() via CallMethod().
+  mock_service_.CallMethod(foo_, &mock_controller_,
+                           &foo_request_, &foo_response_, done_.get());
+
+  ASSERT_TRUE(mock_service_.called_);
+
+  EXPECT_EQ("Foo"            , mock_service_.method_    );
+  EXPECT_EQ(&mock_controller_, mock_service_.controller_);
+  EXPECT_EQ(&foo_request_    , mock_service_.request_   );
+  EXPECT_EQ(&foo_response_   , mock_service_.response_  );
+  EXPECT_EQ(done_.get()      , mock_service_.done_      );
+
+  // Try again, but call Bar() instead.
+  mock_service_.Reset();
+  mock_service_.CallMethod(bar_, &mock_controller_,
+                           &bar_request_, &bar_response_, done_.get());
+
+  ASSERT_TRUE(mock_service_.called_);
+  EXPECT_EQ("Bar", mock_service_.method_);
+}
+
+TEST_F(GeneratedServiceTest, CallMethodTypeFailure) {
+  // Verify death if we call Foo() with Bar's message types.
+
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
+  EXPECT_DEBUG_DEATH(
+    mock_service_.CallMethod(foo_, &mock_controller_,
+                             &foo_request_, &bar_response_, done_.get()),
+    "dynamic_cast");
+
+  mock_service_.Reset();
+  EXPECT_DEBUG_DEATH(
+    mock_service_.CallMethod(foo_, &mock_controller_,
+                             &bar_request_, &foo_response_, done_.get()),
+    "dynamic_cast");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST_F(GeneratedServiceTest, GetPrototypes) {
+  // Test Get{Request,Response}Prototype() methods.
+
+  EXPECT_EQ(&unittest::FooRequest::default_instance(),
+            &mock_service_.GetRequestPrototype(foo_));
+  EXPECT_EQ(&unittest::BarRequest::default_instance(),
+            &mock_service_.GetRequestPrototype(bar_));
+
+  EXPECT_EQ(&unittest::FooResponse::default_instance(),
+            &mock_service_.GetResponsePrototype(foo_));
+  EXPECT_EQ(&unittest::BarResponse::default_instance(),
+            &mock_service_.GetResponsePrototype(bar_));
+}
+
+TEST_F(GeneratedServiceTest, Stub) {
+  // Test that the stub class works.
+
+  // Call Foo() via the stub.
+  stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get());
+
+  ASSERT_TRUE(mock_channel_.called_);
+
+  EXPECT_EQ(foo_             , mock_channel_.method_    );
+  EXPECT_EQ(&mock_controller_, mock_channel_.controller_);
+  EXPECT_EQ(&foo_request_    , mock_channel_.request_   );
+  EXPECT_EQ(&foo_response_   , mock_channel_.response_  );
+  EXPECT_EQ(done_.get()      , mock_channel_.done_      );
+
+  // Call Bar() via the stub.
+  mock_channel_.Reset();
+  stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get());
+
+  ASSERT_TRUE(mock_channel_.called_);
+  EXPECT_EQ(bar_, mock_channel_.method_);
+}
+
+TEST_F(GeneratedServiceTest, NotImplemented) {
+  // Test that failing to implement a method of a service causes it to fail
+  // with a "not implemented" error message.
+
+  // A service which doesn't implement any methods.
+  class UnimplementedService : public unittest::TestService {
+   public:
+    UnimplementedService() {}
+  };
+
+  UnimplementedService unimplemented_service;
+
+  // And a controller which expects to get a "not implemented" error.
+  class ExpectUnimplementedController : public MockController {
+   public:
+    ExpectUnimplementedController() : called_(false) {}
+
+    void SetFailed(const string& reason) {
+      EXPECT_FALSE(called_);
+      called_ = true;
+      EXPECT_EQ("Method Foo() not implemented.", reason);
+    }
+
+    bool called_;
+  };
+
+  ExpectUnimplementedController controller;
+
+  // Call Foo.
+  unimplemented_service.Foo(&controller, &foo_request_, &foo_response_,
+                            done_.get());
+
+  EXPECT_TRUE(controller.called_);
+}
+
+// ===================================================================
+
+class OneofTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+  }
+
+  void ExpectEnumCasesWork(const unittest::TestOneof2 &message) {
+    switch (message.foo_case()) {
+      case unittest::TestOneof2::kFooInt:
+        EXPECT_TRUE(message.has_foo_int());
+        break;
+      case unittest::TestOneof2::kFooString:
+        EXPECT_TRUE(message.has_foo_string());
+        break;
+      case unittest::TestOneof2::kFooCord:
+        EXPECT_TRUE(message.has_foo_cord());
+        break;
+      case unittest::TestOneof2::kFooStringPiece:
+        EXPECT_TRUE(message.has_foo_string_piece());
+        break;
+      case unittest::TestOneof2::kFooBytes:
+        EXPECT_TRUE(message.has_foo_bytes());
+        break;
+      case unittest::TestOneof2::kFooEnum:
+        EXPECT_TRUE(message.has_foo_enum());
+        break;
+      case unittest::TestOneof2::kFooMessage:
+        EXPECT_TRUE(message.has_foo_message());
+        break;
+      case unittest::TestOneof2::kFoogroup:
+        EXPECT_TRUE(message.has_foogroup());
+        break;
+      case unittest::TestOneof2::kFooLazyMessage:
+        EXPECT_TRUE(message.has_foo_lazy_message());
+        break;
+      case unittest::TestOneof2::FOO_NOT_SET:
+        break;
+    }
+  }
+};
+
+TEST_F(OneofTest, SettingOneFieldClearsOthers) {
+  unittest::TestOneof2 message;
+
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.set_foo_string("foo");
+  EXPECT_TRUE(message.has_foo_string());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+  message.set_foo_bytes("qux");
+  EXPECT_TRUE(message.has_foo_bytes());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.set_foo_enum(unittest::TestOneof2::FOO);
+  EXPECT_TRUE(message.has_foo_enum());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.mutable_foo_message()->set_qux_int(234);
+  EXPECT_TRUE(message.has_foo_message());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.mutable_foogroup()->set_a(345);
+  EXPECT_TRUE(message.has_foogroup());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+  // we repeat this because we didn't test if this properly clears other fields
+  // at the beginning.
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+}
+
+TEST_F(OneofTest, EnumCases) {
+  unittest::TestOneof2 message;
+
+  message.set_foo_int(123);
+  ExpectEnumCasesWork(message);
+  message.set_foo_string("foo");
+  ExpectEnumCasesWork(message);
+  message.set_foo_bytes("qux");
+  ExpectEnumCasesWork(message);
+  message.set_foo_enum(unittest::TestOneof2::FOO);
+  ExpectEnumCasesWork(message);
+  message.mutable_foo_message()->set_qux_int(234);
+  ExpectEnumCasesWork(message);
+  message.mutable_foogroup()->set_a(345);
+  ExpectEnumCasesWork(message);
+}
+
+TEST_F(OneofTest, PrimitiveType) {
+  unittest::TestOneof2 message;
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_int(), 0);
+
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  EXPECT_EQ(message.foo_int(), 123);
+  message.clear_foo_int();
+  EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, EnumType) {
+  unittest::TestOneof2 message;
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_enum(), 1);
+
+  message.set_foo_enum(unittest::TestOneof2::FOO);
+  EXPECT_TRUE(message.has_foo_enum());
+  EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO);
+  message.clear_foo_enum();
+  EXPECT_FALSE(message.has_foo_enum());
+}
+
+TEST_F(OneofTest, SetString) {
+  // Check that setting a string field in various ways works
+  unittest::TestOneof2 message;
+
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_string(), "");
+
+  message.set_foo_string("foo");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "foo");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string(string("bar"));
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "bar");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+
+  message.set_foo_string("qux", 3);
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "qux");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.mutable_foo_string()->assign("quux");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "quux");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string("corge");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "corge");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, ReleaseString) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestOneof2 message;
+
+  EXPECT_EQ(NULL, message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string("blah");
+  EXPECT_TRUE(message.has_foo_string());
+  google::protobuf::scoped_ptr<string> str(message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+
+  EXPECT_EQ(NULL, message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, SetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  unittest::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_string());
+  const string kHello("hello");
+  message.set_foo_string(kHello);
+  EXPECT_TRUE(message.has_foo_string());
+
+  message.set_allocated_foo_string(NULL);
+  EXPECT_FALSE(message.has_foo_string());
+  EXPECT_EQ("", message.foo_string());
+
+  message.set_allocated_foo_string(new string(kHello));
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(kHello, message.foo_string());
+}
+
+
+TEST_F(OneofTest, SetMessage) {
+  // Check that setting a message field works
+  unittest::TestOneof2 message;
+
+  // Unset field returns default instance
+  EXPECT_EQ(&message.foo_message(),
+            &unittest::TestOneof2_NestedMessage::default_instance());
+  EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+  message.mutable_foo_message()->set_qux_int(234);
+  EXPECT_TRUE(message.has_foo_message());
+  EXPECT_EQ(message.foo_message().qux_int(), 234);
+  message.clear_foo_message();
+  EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, ReleaseMessage) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestOneof2 message;
+
+  EXPECT_EQ(NULL, message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message.has_foo_message());
+  google::protobuf::scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
+      message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+  ASSERT_TRUE(mes != NULL);
+  EXPECT_EQ(1, mes->qux_int());
+
+  EXPECT_EQ(NULL, message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, SetAllocatedMessage) {
+  // Check that set_allocated_foo() works for messages.
+  unittest::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message.has_foo_message());
+
+  message.set_allocated_foo_message(NULL);
+  EXPECT_FALSE(message.has_foo_message());
+  EXPECT_EQ(&message.foo_message(),
+            &unittest::TestOneof2_NestedMessage::default_instance());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  unittest::TestOneof2_NestedMessage* mes = message.release_foo_message();
+  ASSERT_TRUE(mes != NULL);
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.set_allocated_foo_message(mes);
+  EXPECT_TRUE(message.has_foo_message());
+  EXPECT_EQ(1, message.foo_message().qux_int());
+}
+
+
+TEST_F(OneofTest, Clear) {
+  unittest::TestOneof2 message;
+
+  message.set_foo_int(1);
+  EXPECT_TRUE(message.has_foo_int());
+  message.clear_foo_int();
+  EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, Defaults) {
+  unittest::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_int());
+  EXPECT_EQ(message.foo_int(), 0);
+
+  EXPECT_FALSE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "");
+
+
+  EXPECT_FALSE(message.has_foo_bytes());
+  EXPECT_EQ(message.foo_bytes(), "");
+
+  EXPECT_FALSE(message.has_foo_enum());
+  EXPECT_EQ(message.foo_enum(), 1);
+
+  EXPECT_FALSE(message.has_foo_message());
+  EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+  EXPECT_FALSE(message.has_foogroup());
+  EXPECT_EQ(message.foogroup().a(), 0);
+
+
+  EXPECT_FALSE(message.has_bar_int());
+  EXPECT_EQ(message.bar_int(), 5);
+
+  EXPECT_FALSE(message.has_bar_string());
+  EXPECT_EQ(message.bar_string(), "STRING");
+
+
+  EXPECT_FALSE(message.has_bar_bytes());
+  EXPECT_EQ(message.bar_bytes(), "BYTES");
+
+  EXPECT_FALSE(message.has_bar_enum());
+  EXPECT_EQ(message.bar_enum(), 2);
+}
+
+TEST_F(OneofTest, SwapWithEmpty) {
+  unittest::TestOneof2 message1, message2;
+  message1.set_foo_string("FOO");
+  EXPECT_TRUE(message1.has_foo_string());
+  message1.Swap(&message2);
+  EXPECT_FALSE(message1.has_foo_string());
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapWithSelf) {
+  unittest::TestOneof2 message;
+  message.set_foo_string("FOO");
+  EXPECT_TRUE(message.has_foo_string());
+  message.Swap(&message);
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapBothHasFields) {
+  unittest::TestOneof2 message1, message2;
+
+  message1.set_foo_string("FOO");
+  EXPECT_TRUE(message1.has_foo_string());
+  message2.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message2.has_foo_message());
+
+  message1.Swap(&message2);
+  EXPECT_FALSE(message1.has_foo_string());
+  EXPECT_FALSE(message2.has_foo_message());
+  EXPECT_TRUE(message1.has_foo_message());
+  EXPECT_EQ(message1.foo_message().qux_int(), 1);
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, CopyConstructor) {
+  unittest::TestOneof2 message1;
+  message1.set_foo_bytes("FOO");
+
+  unittest::TestOneof2 message2(message1);
+  EXPECT_TRUE(message2.has_foo_bytes());
+  EXPECT_EQ(message2.foo_bytes(), "FOO");
+}
+
+TEST_F(OneofTest, CopyFrom) {
+  unittest::TestOneof2 message1, message2;
+  message1.set_foo_enum(unittest::TestOneof2::BAR);
+  EXPECT_TRUE(message1.has_foo_enum());
+
+  message2.CopyFrom(message1);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR);
+}
+
+TEST_F(OneofTest, CopyAssignmentOperator) {
+  unittest::TestOneof2 message1;
+  message1.mutable_foo_message()->set_qux_int(123);
+  EXPECT_TRUE(message1.has_foo_message());
+
+  unittest::TestOneof2 message2;
+  message2 = message1;
+  EXPECT_EQ(message2.foo_message().qux_int(), 123);
+
+  // Make sure that self-assignment does something sane.
+  message2 = message2;
+  EXPECT_EQ(message2.foo_message().qux_int(), 123);
+}
+
+TEST_F(OneofTest, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  unittest::TestOneof2 message1, message2;
+  message1.mutable_foogroup()->set_a(123);
+  EXPECT_TRUE(message1.has_foogroup());
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  EXPECT_TRUE(message2.has_foogroup());
+  EXPECT_EQ(message2.foogroup().a(), 123);
+}
+
+// Test the generated SerializeWithCachedSizesToArray(),
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToArray) {
+  // Primitive type
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_int(123);
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_int(), 123);
+  }
+
+  // String
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_string("foo");
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_string(), "foo");
+  }
+
+
+  // Bytes
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_bytes("qux");
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_bytes(), "qux");
+  }
+
+  // Enum
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_enum(unittest::TestOneof2::FOO);
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
+  }
+
+  // Message
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foo_message()->set_qux_int(234);
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_message().qux_int(), 234);
+  }
+
+  // Group
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foogroup()->set_a(345);
+    int size = message1.ByteSize();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foogroup().a(), 345);
+  }
+
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToStream) {
+  // Primitive type
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_int(123);
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_int(), 123);
+  }
+
+  // String
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_string("foo");
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_string(), "foo");
+  }
+
+
+  // Bytes
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_bytes("qux");
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_bytes(), "qux");
+  }
+
+  // Enum
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_enum(unittest::TestOneof2::FOO);
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
+  }
+
+  // Message
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foo_message()->set_qux_int(234);
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_message().qux_int(), 234);
+  }
+
+  // Group
+  {
+    unittest::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foogroup()->set_a(345);
+    int size = message1.ByteSize();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foogroup().a(), 345);
+  }
+
+}
+
+TEST_F(OneofTest, MergeFrom) {
+  unittest::TestOneof2 message1, message2;
+
+  message1.set_foo_int(123);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_int());
+  EXPECT_EQ(message2.foo_int(), 123);
+
+  message1.set_foo_string("foo");
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "foo");
+
+
+  message1.set_foo_bytes("qux");
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_bytes());
+  EXPECT_EQ(message2.foo_bytes(), "qux");
+
+  message1.set_foo_enum(unittest::TestOneof2::FOO);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
+
+  message1.mutable_foo_message()->set_qux_int(234);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_message());
+  EXPECT_EQ(message2.foo_message().qux_int(), 234);
+
+  message1.mutable_foogroup()->set_a(345);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foogroup());
+  EXPECT_EQ(message2.foogroup().a(), 345);
+
+}
+
+}  // namespace cpp_unittest
+}  // namespace cpp
+}  // namespace compiler
+
+namespace no_generic_services_test {
+  // Verify that no class called "TestService" was defined in
+  // unittest_no_generic_services.pb.h by defining a different type by the same
+  // name.  If such a service was generated, this will not compile.
+  struct TestService {
+    int i;
+  };
+}
+
+namespace compiler {
+namespace cpp {
+namespace cpp_unittest {
+
+TEST_F(GeneratedServiceTest, NoGenericServices) {
+  // Verify that non-services in unittest_no_generic_services.proto were
+  // generated.
+  no_generic_services_test::TestMessage message;
+  message.set_a(1);
+  message.SetExtension(no_generic_services_test::test_extension, 123);
+  no_generic_services_test::TestEnum e = no_generic_services_test::FOO;
+  EXPECT_EQ(e, 1);
+
+  // Verify that a ServiceDescriptor is generated for the service even if the
+  // class itself is not.
+  const FileDescriptor* file =
+      no_generic_services_test::TestMessage::descriptor()->file();
+
+  ASSERT_EQ(1, file->service_count());
+  EXPECT_EQ("TestService", file->service(0)->name());
+  ASSERT_EQ(1, file->service(0)->method_count());
+  EXPECT_EQ("Foo", file->service(0)->method(0)->name());
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+// This test must run last.  It verifies that descriptors were or were not
+// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined.
+// When this is defined, we skip all tests which are expected to trigger
+// descriptor initialization.  This verifies that everything else still works
+// if descriptors are not initialized.
+TEST(DescriptorInitializationTest, Initialized) {
+#ifdef PROTOBUF_TEST_NO_DESCRIPTORS
+  bool should_have_descriptors = false;
+#else
+  bool should_have_descriptors = true;
+#endif
+
+  EXPECT_EQ(should_have_descriptors,
+    DescriptorPool::generated_pool()->InternalIsFileLoaded(
+      "google/protobuf/unittest.proto"));
+}
+
+}  // namespace cpp_unittest
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 0000000..69c8f44
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/cpp_unittest.h
@@ -0,0 +1,51 @@
+// 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.
+
+// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
+// any problems with the generated class names. We use this header to ensure
+// unittest.cc will declare the namespace prior to other includes, while obeying
+// normal include ordering.
+//
+// When generating a class name of "foo.Bar" we must ensure we prefix the class
+// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
+// trigger that case here by declaring google::protobuf::protobuf_unittest.
+//
+// See ClassName in helpers.h for more details.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+
+namespace google {
+namespace protobuf {
+namespace protobuf_unittest {}
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/metadata_test.cc
new file mode 100644
index 0000000..edd3078
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -0,0 +1,242 @@
+// 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.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+// A CodeGenerator that captures the FileDescriptor it's passed as a
+// FileDescriptorProto.
+class DescriptorCapturingGenerator : public CodeGenerator {
+ public:
+  // Does not own file; file must outlive the Generator.
+  explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
+      : file_(file) {}
+
+  virtual bool Generate(const FileDescriptor* file, const string& parameter,
+                        GeneratorContext* context, string* error) const {
+    file->CopyTo(file_);
+    return true;
+  }
+
+ private:
+  FileDescriptorProto* file_;
+};
+
+class CppMetadataTest : public ::testing::Test {
+ public:
+  // Adds a file with name `filename` and content `data`.
+  void AddFile(const string& filename, const string& data) {
+    GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
+                               true));
+  }
+
+  // Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
+  // code from the previously added file with name `filename`. Returns true on
+  // success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
+  // pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
+  bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
+                       string* pb_h, GeneratedCodeInfo* pb_h_info,
+                       string* proto_h, GeneratedCodeInfo* proto_h_info,
+                       string* pb_cc) {
+    google::protobuf::compiler::CommandLineInterface cli;
+    cli.SetInputsAreProtoPathRelative(true);
+
+    CppGenerator cpp_generator;
+    DescriptorCapturingGenerator capturing_generator(file);
+    cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+    cli.RegisterGenerator("--capture_out", &capturing_generator, "");
+
+    string proto_path = "-I" + TestTempDir();
+    string cpp_out =
+        "--cpp_out=annotate_headers=true,"
+        "annotation_pragma_name=pragma_name,"
+        "annotation_guard_name=guard_name:" +
+        TestTempDir();
+    string capture_out = "--capture_out=" + TestTempDir();
+
+    const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(),
+                          capture_out.c_str(), filename.c_str()};
+
+    if (cli.Run(5, argv) != 0) {
+      return false;
+    }
+
+    string output_base = TestTempDir() + "/" + StripProto(filename);
+
+    if (pb_cc != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.cc", pb_cc, true));
+    }
+
+    if (pb_h != NULL && pb_h_info != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.h", pb_h, true));
+      if (!DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
+        return false;
+      }
+    }
+
+    if (proto_h != NULL && proto_h_info != NULL) {
+      GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
+                                 true));
+      if (!DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  // Decodes GeneratedCodeInfo stored in path and copies it to info.
+  // Returns true on success.
+  bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
+    string data;
+    GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
+    io::ArrayInputStream input(data.data(), data.size());
+    return info->ParseFromZeroCopyStream(&input);
+  }
+};
+
+const char kSmallTestFile[] =
+    "syntax = \"proto2\";\n"
+    "package foo;\n"
+    "enum Enum { VALUE = 0; }\n"
+    "message Message { }\n";
+
+// Finds the Annotation for a given source file and path (or returns null if it
+// couldn't).
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const vector<int>& path) {
+  for (int i = 0; i < info.annotation_size(); ++i) {
+    const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
+    if (annotation->source_file() != source_file ||
+        annotation->path_size() != path.size()) {
+      continue;
+    }
+    int node = 0;
+    for (; node < path.size(); ++node) {
+      if (annotation->path(node) != path[node]) {
+        break;
+      }
+    }
+    if (node == path.size()) {
+      return annotation;
+    }
+  }
+  return NULL;
+}
+
+// Returns true if the provided annotation covers a given substring in
+// file_content.
+bool AnnotationMatchesSubstring(const string& file_content,
+                                const GeneratedCodeInfo::Annotation* annotation,
+                                const string& expected_text) {
+  uint32 begin = annotation->begin();
+  uint32 end = annotation->end();
+  if (end < begin || end > file_content.size()) {
+    return false;
+  }
+  return file_content.substr(begin, end - begin) == expected_text;
+}
+
+TEST_F(CppMetadataTest, CapturesEnumNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Enum", file.enum_type(0).name());
+  vector<int> enum_path;
+  enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+  enum_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* enum_annotation =
+      FindAnnotationOnPath(info, "test.proto", enum_path);
+  EXPECT_TRUE(NULL != enum_annotation);
+  EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
+}
+
+TEST_F(CppMetadataTest, AddsPragma) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
+  EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
+              string::npos);
+}
+
+TEST_F(CppMetadataTest, CapturesMessageNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Message", file.message_type(0).name());
+  vector<int> message_path;
+  message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+  message_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* message_annotation =
+      FindAnnotationOnPath(info, "test.proto", message_path);
+  EXPECT_TRUE(NULL != message_annotation);
+  EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
+}
+
+}  // namespace
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
new file mode 100644
index 0000000..587e022
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -0,0 +1,114 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Functions to create C# XML documentation comments.
+// Currently this only includes documentation comments containing text specified as comments
+// in the .proto file; documentation comments generated just from field/message/enum/proto names
+// is inlined in the relevant code. If more control is required, that code can be moved here.
+
+void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
+    string comments = location.leading_comments.empty() ?
+        location.trailing_comments : location.leading_comments;
+    if (comments.empty()) {
+        return;
+    }
+    // XML escaping... no need for apostrophes etc as the whole text is going to be a child
+    // node of a summary element, not part of an attribute.
+    comments = StringReplace(comments, "&", "&amp;", true);
+    comments = StringReplace(comments, "<", "&lt;", true);
+    vector<string> lines = Split(comments, "\n", false /* skip_empty */);
+    // TODO: We really should work out which part to put in the summary and which to put in the remarks...
+    // but that needs to be part of a bigger effort to understand the markdown better anyway.
+    printer->Print("/// <summary>\n");
+    bool last_was_empty = false;
+    // We squash multiple blank lines down to one, and remove any trailing blank lines. We need
+    // to preserve the blank lines themselves, as this is relevant in the markdown.
+    // Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
+    // (We don't skip "just whitespace" lines, either.)
+    for (std::vector<string>::iterator it = lines.begin(); it != lines.end(); ++it) {
+        string line = *it;
+        if (line.empty()) {
+            last_was_empty = true;
+        } else {
+            if (last_was_empty) {
+                printer->Print("///\n");
+            }
+            last_was_empty = false;
+            printer->Print("/// $line$\n", "line", *it);
+        }
+    }
+    printer->Print("/// </summary>\n");
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(
+    io::Printer* printer, const DescriptorType* descriptor) {
+    SourceLocation location;
+    if (descriptor->GetSourceLocation(&location)) {
+        WriteDocCommentBodyImpl(printer, location);
+    }
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+    WriteDocCommentBody(printer, message);
+}
+
+void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
+    WriteDocCommentBody(printer, field);
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
+    WriteDocCommentBody(printer, enumDescriptor);
+}
+void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
+    WriteDocCommentBody(printer, value);
+}
+
+void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
+    WriteDocCommentBody(printer, method);
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
new file mode 100644
index 0000000..75eb0ea
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
@@ -0,0 +1,51 @@
+// 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_COMPILER_CSHARP_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+    void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+    void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
+    void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
+    void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
+    void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.cc
new file mode 100644
index 0000000..bdfcc2b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -0,0 +1,95 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
+    SourceGeneratorBase(descriptor->file(), options),
+    descriptor_(descriptor) {
+}
+
+EnumGenerator::~EnumGenerator() {
+}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+  WriteEnumDocComment(printer, descriptor_);
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print("$access_level$ enum $name$ {\n",
+                 "access_level", class_access_level(),
+                 "name", descriptor_->name());
+  printer->Indent();
+  std::set<string> used_names;
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+      WriteEnumValueDocComment(printer, descriptor_->value(i));
+      string original_name = descriptor_->value(i)->name();
+      string name = options()->legacy_enum_values
+          ? descriptor_->value(i)->name()
+          : GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
+      // Make sure we don't get any duplicate names due to prefix removal.
+      while (!used_names.insert(name).second) {
+        // It's possible we'll end up giving this warning multiple times, but that's better than not at all.
+        GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
+          << ") in " << descriptor_->name() << "; adding underscore to distinguish";
+        name += "_";
+      }
+      printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
+         "original_name", original_name,
+         "name", name,
+         "number", SimpleItoa(descriptor_->value(i)->number()));         
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+  printer->Print("\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.h
new file mode 100644
index 0000000..8925cdf
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum.h
@@ -0,0 +1,63 @@
+// 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_COMPILER_CSHARP_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumGenerator : public SourceGeneratorBase {
+ public:
+  EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
+  ~EnumGenerator();
+
+  void Generate(io::Printer* printer);
+
+ private:
+  const EnumDescriptor* descriptor_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
new file mode 100644
index 0000000..67c0b59
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -0,0 +1,120 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {
+}
+
+void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = ($type_name$) input.ReadEnum();\n");
+}
+
+void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "if ($has_property_check$) {\n"
+    "  output.WriteRawTag($tag_bytes$);\n"
+    "  output.WriteEnum((int) $property_name$);\n"
+    "}\n");
+}
+
+void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+      "  size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
+    "}\n");
+}
+
+void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+    printer->Print(
+        variables_,
+        "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
+}
+
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
+}
+
+EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
+}
+
+void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  // TODO(jonskeet): What about if we read the default value?
+  printer->Print(
+    variables_,
+    "$oneof_name$_ = input.ReadEnum();\n"
+    "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n");
+}
+
+void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  output.WriteRawTag($tag_bytes$);\n"
+    "  output.WriteEnum((int) $property_name$);\n"
+    "}\n");
+}
+
+void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
+    "}\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.h
new file mode 100644
index 0000000..9b7669b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -0,0 +1,81 @@
+// 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_COMPILER_CSHARP_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+  EnumFieldGenerator(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options *options);
+  ~EnumFieldGenerator();
+
+  virtual void GenerateCodecCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
+ public:
+  EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
+  ~EnumOneofFieldGenerator();
+
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.cc
new file mode 100644
index 0000000..e3c3404
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -0,0 +1,429 @@
+// 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.
+
+#include <limits>
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+void FieldGeneratorBase::SetCommonFieldVariables(
+    map<string, string>* variables) {
+  // Note: this will be valid even though the tag emitted for packed and unpacked versions of
+  // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
+  // never effects the tag size.
+  int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
+  uint tag = internal::WireFormat::MakeTag(descriptor_);
+  uint8 tag_array[5];
+  io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+  string tag_bytes = SimpleItoa(tag_array[0]);
+  for (int i = 1; i < tag_size; i++) {
+    tag_bytes += ", " + SimpleItoa(tag_array[i]);
+  }
+
+  (*variables)["access_level"] = "public";
+  (*variables)["tag"] = SimpleItoa(tag);
+  (*variables)["tag_size"] = SimpleItoa(tag_size);
+  (*variables)["tag_bytes"] = tag_bytes;
+
+  (*variables)["property_name"] = property_name();
+  (*variables)["type_name"] = type_name();
+  (*variables)["name"] = name();
+  (*variables)["descriptor_name"] = descriptor_->name();
+  (*variables)["default_value"] = default_value();
+  if (has_default_value()) {
+    (*variables)["name_def_message"] =
+      (*variables)["name"] + "_ = " + (*variables)["default_value"];
+  } else {
+    (*variables)["name_def_message"] = (*variables)["name"] + "_";
+  }
+  (*variables)["capitalized_type_name"] = capitalized_type_name();
+  (*variables)["number"] = number();
+  (*variables)["has_property_check"] =
+    (*variables)["property_name"] + " != " + (*variables)["default_value"];
+  (*variables)["other_has_property_check"] = "other." +
+    (*variables)["property_name"] + " != " + (*variables)["default_value"];
+}
+
+void FieldGeneratorBase::SetCommonOneofFieldVariables(
+    map<string, string>* variables) {
+  (*variables)["oneof_name"] = oneof_name();
+  (*variables)["has_property_check"] =
+    oneof_name() + "Case_ == " + oneof_property_name() +
+    "OneofCase." + property_name();
+  (*variables)["oneof_property_name"] = oneof_property_name();
+}
+
+FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
+                                       int fieldOrdinal, const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
+      descriptor_(descriptor),
+      fieldOrdinal_(fieldOrdinal) {
+  SetCommonFieldVariables(&variables_);
+}
+
+FieldGeneratorBase::~FieldGeneratorBase() {
+}
+
+void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
+  // No-op: only message fields and repeated fields need
+  // special handling for freezing, so default to not generating any code.
+}
+
+void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
+    // No-op: expect this to be overridden by appropriate types.
+    // Could fail if we get called here though...
+}
+
+void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
+  if (descriptor_->options().deprecated())
+  {
+    printer->Print("[global::System.ObsoleteAttribute()]\n");
+  }
+}
+
+void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
+  AddDeprecatedFlag(printer);
+}
+
+std::string FieldGeneratorBase::oneof_property_name() {
+  return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
+}
+
+std::string FieldGeneratorBase::oneof_name() {
+  return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
+}
+
+std::string FieldGeneratorBase::property_name() {
+  return GetPropertyName(descriptor_);
+}
+
+std::string FieldGeneratorBase::name() {
+  return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
+}
+
+std::string FieldGeneratorBase::type_name() {
+  return type_name(descriptor_);
+}
+
+std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
+  switch (descriptor->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+      return GetClassName(descriptor->enum_type());
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+      if (IsWrapperType(descriptor)) {
+        const FieldDescriptor* wrapped_field =
+            descriptor->message_type()->field(0);
+        string wrapped_field_type_name = type_name(wrapped_field);
+        // String and ByteString go to the same type; other wrapped types
+        // go to the nullable equivalent.
+        if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
+            wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
+          return wrapped_field_type_name;
+        } else {
+          return wrapped_field_type_name + "?";
+        }
+      }
+      return GetClassName(descriptor->message_type());
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "double";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "float";
+    case FieldDescriptor::TYPE_INT64:
+      return "long";
+    case FieldDescriptor::TYPE_UINT64:
+      return "ulong";
+    case FieldDescriptor::TYPE_INT32:
+      return "int";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "ulong";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "uint";
+    case FieldDescriptor::TYPE_BOOL:
+      return "bool";
+    case FieldDescriptor::TYPE_STRING:
+      return "string";
+    case FieldDescriptor::TYPE_BYTES:
+      return "pb::ByteString";
+    case FieldDescriptor::TYPE_UINT32:
+      return "uint";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "int";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "long";
+    case FieldDescriptor::TYPE_SINT32:
+      return "int";
+    case FieldDescriptor::TYPE_SINT64:
+      return "long";
+    default:
+      GOOGLE_LOG(FATAL)<< "Unknown field type.";
+      return "";
+  }
+}
+
+bool FieldGeneratorBase::has_default_value() {
+  switch (descriptor_->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+      return true;
+    case FieldDescriptor::TYPE_DOUBLE:
+      return descriptor_->default_value_double() != 0.0;
+    case FieldDescriptor::TYPE_FLOAT:
+      return descriptor_->default_value_float() != 0.0;
+    case FieldDescriptor::TYPE_INT64:
+      return descriptor_->default_value_int64() != 0L;
+    case FieldDescriptor::TYPE_UINT64:
+      return descriptor_->default_value_uint64() != 0L;
+    case FieldDescriptor::TYPE_INT32:
+      return descriptor_->default_value_int32() != 0;
+    case FieldDescriptor::TYPE_FIXED64:
+      return descriptor_->default_value_uint64() != 0L;
+    case FieldDescriptor::TYPE_FIXED32:
+      return descriptor_->default_value_uint32() != 0;
+    case FieldDescriptor::TYPE_BOOL:
+      return descriptor_->default_value_bool();
+    case FieldDescriptor::TYPE_STRING:
+      return true;
+    case FieldDescriptor::TYPE_BYTES:
+      return true;
+    case FieldDescriptor::TYPE_UINT32:
+      return descriptor_->default_value_uint32() != 0;
+    case FieldDescriptor::TYPE_SFIXED32:
+      return descriptor_->default_value_int32() != 0;
+    case FieldDescriptor::TYPE_SFIXED64:
+      return descriptor_->default_value_int64() != 0L;
+    case FieldDescriptor::TYPE_SINT32:
+      return descriptor_->default_value_int32() != 0;
+    case FieldDescriptor::TYPE_SINT64:
+      return descriptor_->default_value_int64() != 0L;
+    default:
+      GOOGLE_LOG(FATAL)<< "Unknown field type.";
+      return true;
+  }
+}
+
+bool FieldGeneratorBase::is_nullable_type() {
+  switch (descriptor_->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_BOOL:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SINT64:
+      return false;
+
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      return true;
+
+    default:
+      GOOGLE_LOG(FATAL)<< "Unknown field type.";
+      return true;
+  }
+}
+
+bool AllPrintableAscii(const std::string& text) {
+  for(int i = 0; i < text.size(); i++) {
+    if (text[i] < 0x20 || text[i] > 0x7e) {
+      return false;
+    }
+  }
+  return true;
+}
+
+std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
+  // No other default values needed for proto3...
+  return "\"\"";
+}
+
+std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
+  // No other default values needed for proto3...
+  return "pb::ByteString.Empty";
+}
+
+std::string FieldGeneratorBase::default_value() {
+    return default_value(descriptor_);
+}
+
+std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
+  switch (descriptor->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+      // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
+      // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
+     return "0";
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+      if (IsWrapperType(descriptor)) {
+        const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+        return default_value(wrapped_field);
+      } else {
+        return "null";
+      }
+    case FieldDescriptor::TYPE_DOUBLE: {
+      double value = descriptor->default_value_double();
+      if (value == numeric_limits<double>::infinity()) {
+        return "double.PositiveInfinity";
+      } else if (value == -numeric_limits<double>::infinity()) {
+        return "double.NegativeInfinity";
+      } else if (MathLimits<double>::IsNaN(value)) {
+        return "double.NaN";
+      }
+      return SimpleDtoa(value) + "D";
+    }
+    case FieldDescriptor::TYPE_FLOAT: {
+      float value = descriptor->default_value_float();
+      if (value == numeric_limits<float>::infinity()) {
+        return "float.PositiveInfinity";
+      } else if (value == -numeric_limits<float>::infinity()) {
+        return "float.NegativeInfinity";
+      } else if (MathLimits<float>::IsNaN(value)) {
+        return "float.NaN";
+      }
+      return SimpleFtoa(value) + "F";
+    }
+    case FieldDescriptor::TYPE_INT64:
+      return SimpleItoa(descriptor->default_value_int64()) + "L";
+    case FieldDescriptor::TYPE_UINT64:
+      return SimpleItoa(descriptor->default_value_uint64()) + "UL";
+    case FieldDescriptor::TYPE_INT32:
+      return SimpleItoa(descriptor->default_value_int32());
+    case FieldDescriptor::TYPE_FIXED64:
+      return SimpleItoa(descriptor->default_value_uint64()) + "UL";
+    case FieldDescriptor::TYPE_FIXED32:
+      return SimpleItoa(descriptor->default_value_uint32());
+    case FieldDescriptor::TYPE_BOOL:
+      if (descriptor->default_value_bool()) {
+        return "true";
+      } else {
+        return "false";
+      }
+    case FieldDescriptor::TYPE_STRING:
+      return GetStringDefaultValueInternal();
+    case FieldDescriptor::TYPE_BYTES:
+      return GetBytesDefaultValueInternal();
+    case FieldDescriptor::TYPE_UINT32:
+      return SimpleItoa(descriptor->default_value_uint32());
+    case FieldDescriptor::TYPE_SFIXED32:
+      return SimpleItoa(descriptor->default_value_int32());
+    case FieldDescriptor::TYPE_SFIXED64:
+      return SimpleItoa(descriptor->default_value_int64()) + "L";
+    case FieldDescriptor::TYPE_SINT32:
+      return SimpleItoa(descriptor->default_value_int32());
+    case FieldDescriptor::TYPE_SINT64:
+      return SimpleItoa(descriptor->default_value_int64()) + "L";
+    default:
+      GOOGLE_LOG(FATAL)<< "Unknown field type.";
+      return "";
+  }
+}
+
+std::string FieldGeneratorBase::number() {
+  return SimpleItoa(descriptor_->number());
+}
+
+std::string FieldGeneratorBase::capitalized_type_name() {
+  switch (descriptor_->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+      return "Enum";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "Message";
+    case FieldDescriptor::TYPE_GROUP:
+      return "Group";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "Double";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "Float";
+    case FieldDescriptor::TYPE_INT64:
+      return "Int64";
+    case FieldDescriptor::TYPE_UINT64:
+      return "UInt64";
+    case FieldDescriptor::TYPE_INT32:
+      return "Int32";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "Fixed64";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "Fixed32";
+    case FieldDescriptor::TYPE_BOOL:
+      return "Bool";
+    case FieldDescriptor::TYPE_STRING:
+      return "String";
+    case FieldDescriptor::TYPE_BYTES:
+      return "Bytes";
+    case FieldDescriptor::TYPE_UINT32:
+      return "UInt32";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "SFixed32";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "SFixed64";
+    case FieldDescriptor::TYPE_SINT32:
+      return "SInt32";
+    case FieldDescriptor::TYPE_SINT64:
+      return "SInt64";
+    default:
+      GOOGLE_LOG(FATAL)<< "Unknown field type.";
+      return "";
+  }
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.h
new file mode 100644
index 0000000..4109f3c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -0,0 +1,105 @@
+// 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_COMPILER_CSHARP_FIELD_BASE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+
+#include <string>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase : public SourceGeneratorBase {
+ public:
+  FieldGeneratorBase(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options* options);
+  ~FieldGeneratorBase();
+
+  virtual void GenerateCloningCode(io::Printer* printer) = 0;
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer) = 0;
+  virtual void GenerateMergingCode(io::Printer* printer) = 0;
+  virtual void GenerateParsingCode(io::Printer* printer) = 0;
+  virtual void GenerateSerializationCode(io::Printer* printer) = 0;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
+
+  virtual void WriteHash(io::Printer* printer) = 0;
+  virtual void WriteEquals(io::Printer* printer) = 0;
+  // Currently unused, as we use reflection to generate JSON
+  virtual void WriteToString(io::Printer* printer) = 0;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  const int fieldOrdinal_;
+  map<string, string> variables_;
+
+  void AddDeprecatedFlag(io::Printer* printer);
+  void AddNullCheck(io::Printer* printer);
+  void AddNullCheck(io::Printer* printer, const std::string& name);
+
+  void AddPublicMemberAttributes(io::Printer* printer);
+  void SetCommonOneofFieldVariables(map<string, string>* variables);
+
+  std::string oneof_property_name();
+  std::string oneof_name();
+  std::string property_name();
+  std::string name();
+  std::string type_name();
+  std::string type_name(const FieldDescriptor* descriptor);
+  bool has_default_value();
+  bool is_nullable_type();
+  std::string default_value();
+  std::string default_value(const FieldDescriptor* descriptor);
+  std::string number();
+  std::string capitalized_type_name();
+
+ private:
+  void SetCommonFieldVariables(map<string, string>* variables);
+  std::string GetStringDefaultValueInternal();
+  std::string GetBytesDefaultValueInternal();
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.cc
new file mode 100644
index 0000000..d74e8c8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -0,0 +1,118 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+void GenerateFile(const google::protobuf::FileDescriptor* file,
+                  io::Printer* printer,
+                  const Options* options) {
+  ReflectionClassGenerator reflectionClassGenerator(file, options);
+  reflectionClassGenerator.Generate(printer);
+}
+
+bool Generator::Generate(
+    const FileDescriptor* file,
+    const string& parameter,
+    GeneratorContext* generator_context,
+    string* error) const {
+
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
+  // We only support proto3 - but we make an exception for descriptor.proto.
+  if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
+    *error = "C# code generation only supports proto3 syntax";
+    return false;
+  }
+
+  struct Options cli_options;
+
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "file_extension") {
+      cli_options.file_extension = options[i].second;
+    } else if (options[i].first == "base_namespace") {
+      cli_options.base_namespace = options[i].second;
+      cli_options.base_namespace_specified = true;
+    } else if (options[i].first == "internal_access") {
+      cli_options.internal_access = true;
+    } else if (options[i].first == "legacy_enum_values") {
+      // TODO: Remove this before final release
+      cli_options.legacy_enum_values = true;
+    } else {
+      *error = "Unknown generator option: " + options[i].first;
+      return false;
+    }
+  }
+
+  string filename_error = "";
+  std::string filename = GetOutputFile(file,
+      cli_options.file_extension,
+      cli_options.base_namespace_specified,
+      cli_options.base_namespace,
+      &filename_error);
+
+  if (filename.empty()) {
+    *error = filename_error;
+    return false;
+  }
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '$');
+
+  GenerateFile(file, &printer, &cli_options);
+
+  return true;
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.h
new file mode 100644
index 0000000..9b54e91
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator.h
@@ -0,0 +1,58 @@
+// 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_COMPILER_CSHARP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class LIBPROTOC_EXPORT Generator
+    : public google::protobuf::compiler::CodeGenerator {
+  virtual bool Generate(
+      const FileDescriptor* file,
+      const string& parameter,
+      GeneratorContext* generator_context,
+      string* error) const;
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
new file mode 100644
index 0000000..5755fee
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include <memory>
+
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+namespace {
+
+TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
+  EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+  EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
+  EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
+  // Identifiers can't start with digits
+  EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
+  EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
+}
+
+}  // namespace
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.cc
new file mode 100644
index 0000000..6c154c5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -0,0 +1,506 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
+#include <vector>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
+#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+CSharpType GetCSharpType(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32:
+      return CSHARPTYPE_INT32;
+    case FieldDescriptor::TYPE_INT64:
+      return CSHARPTYPE_INT64;
+    case FieldDescriptor::TYPE_UINT32:
+      return CSHARPTYPE_UINT32;
+    case FieldDescriptor::TYPE_UINT64:
+      return CSHARPTYPE_UINT32;
+    case FieldDescriptor::TYPE_SINT32:
+      return CSHARPTYPE_INT32;
+    case FieldDescriptor::TYPE_SINT64:
+      return CSHARPTYPE_INT64;
+    case FieldDescriptor::TYPE_FIXED32:
+      return CSHARPTYPE_UINT32;
+    case FieldDescriptor::TYPE_FIXED64:
+      return CSHARPTYPE_UINT64;
+    case FieldDescriptor::TYPE_SFIXED32:
+      return CSHARPTYPE_INT32;
+    case FieldDescriptor::TYPE_SFIXED64:
+      return CSHARPTYPE_INT64;
+    case FieldDescriptor::TYPE_FLOAT:
+      return CSHARPTYPE_FLOAT;
+    case FieldDescriptor::TYPE_DOUBLE:
+      return CSHARPTYPE_DOUBLE;
+    case FieldDescriptor::TYPE_BOOL:
+      return CSHARPTYPE_BOOL;
+    case FieldDescriptor::TYPE_ENUM:
+      return CSHARPTYPE_ENUM;
+    case FieldDescriptor::TYPE_STRING:
+      return CSHARPTYPE_STRING;
+    case FieldDescriptor::TYPE_BYTES:
+      return CSHARPTYPE_BYTESTRING;
+    case FieldDescriptor::TYPE_GROUP:
+      return CSHARPTYPE_MESSAGE;
+    case FieldDescriptor::TYPE_MESSAGE:
+      return CSHARPTYPE_MESSAGE;
+
+      // No default because we want the compiler to complain if any new
+      // types are added.
+  }
+  GOOGLE_LOG(FATAL)<< "Can't get here.";
+  return (CSharpType) -1;
+}
+
+std::string StripDotProto(const std::string& proto_file) {
+  int lastindex = proto_file.find_last_of(".");
+  return proto_file.substr(0, lastindex);
+}
+
+std::string GetFileNamespace(const FileDescriptor* descriptor) {
+  if (descriptor->options().has_csharp_namespace()) {
+    return descriptor->options().csharp_namespace();
+  }
+  return UnderscoresToCamelCase(descriptor->package(), true, true);
+}
+
+// Returns the Pascal-cased last part of the proto file. For example,
+// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
+std::string GetFileNameBase(const FileDescriptor* descriptor) {
+    std::string proto_file = descriptor->name();
+    int lastslash = proto_file.find_last_of("/");
+    std::string base = proto_file.substr(lastslash + 1);
+    return UnderscoresToPascalCase(StripDotProto(base));
+}
+
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
+  // TODO: Detect collisions with existing messages,
+  // and append an underscore if necessary.
+  return GetFileNameBase(descriptor) + "Reflection";
+}
+
+// TODO(jtattermusch): can we reuse a utility function?
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period) {
+  string result;
+  // Note:  I distrust ctype.h due to locales.
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      if (cap_next_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      if (i == 0 && !cap_next_letter) {
+        // Force first letter to lower-case unless explicitly told to
+        // capitalize it.
+        result += input[i] + ('a' - 'A');
+      } else {
+        // Capital letters after the first are left as-is.
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_next_letter = true;
+    } else {
+      cap_next_letter = true;
+      if (input[i] == '.' && preserve_period) {
+        result += '.';
+      }
+    }
+  }
+  // Add a trailing "_" if the name should be altered.
+  if (input[input.size() - 1] == '#') {
+    result += '_';
+  }
+  return result;
+}
+
+std::string UnderscoresToPascalCase(const std::string& input) {
+  return UnderscoresToCamelCase(input, true);
+}
+
+// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
+// into a PascalCase string. Precise rules implemented:
+
+// Previous input character      Current character         Case
+// Any                           Non-alphanumeric          Skipped
+// None - first char of input    Alphanumeric              Upper
+// Non-letter (e.g. _ or 1)      Alphanumeric              Upper
+// Numeric                       Alphanumeric              Upper
+// Lower letter                  Alphanumeric              Same as current
+// Upper letter                  Alphanumeric              Lower
+std::string ShoutyToPascalCase(const std::string& input) {
+  string result;
+  // Simple way of implementing "always start with upper"
+  char previous = '_';
+  for (int i = 0; i < input.size(); i++) {
+    char current = input[i];
+    if (!ascii_isalnum(current)) {
+      previous = current;
+      continue;      
+    }
+    if (!ascii_isalnum(previous)) {
+      result += ascii_toupper(current);
+    } else if (ascii_isdigit(previous)) {
+      result += ascii_toupper(current);
+    } else if (ascii_islower(previous)) {
+      result += current;
+    } else {
+      result += ascii_tolower(current);
+    }
+    previous = current;
+  }
+  return result;
+}
+
+// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
+// (foo, foo_bar) => bar - underscore after prefix is skipped
+// (FOO, foo_bar) => bar - casing is ignored
+// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
+// (foobar, foo_barbaz) => baz - underscore in value is ignored
+// (foo, bar) => bar - prefix isn't matched; return original value
+std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
+  // First normalize to a lower-case no-underscores prefix to match against
+  std::string prefix_to_match = "";
+  for (size_t i = 0; i < prefix.size(); i++) {
+    if (prefix[i] != '_') {
+      prefix_to_match += ascii_tolower(prefix[i]);
+    }
+  }
+  
+  // This keeps track of how much of value we've consumed
+  size_t prefix_index, value_index;
+  for (prefix_index = 0, value_index = 0;
+      prefix_index < prefix_to_match.size() && value_index < value.size();
+      value_index++) {
+    // Skip over underscores in the value
+    if (value[value_index] == '_') {
+      continue;
+    }
+    if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
+      // Failed to match the prefix - bail out early.
+      return value;
+    }
+  }
+
+  // If we didn't finish looking through the prefix, we can't strip it.
+  if (prefix_index < prefix_to_match.size()) {
+    return value;
+  }
+
+  // Step over any underscores after the prefix
+  while (value_index < value.size() && value[value_index] == '_') {
+    value_index++;
+  }
+
+  // If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
+  if (value_index == value.size()) {
+    return value;
+  }
+
+  return value.substr(value_index);
+}
+
+// Format the enum value name in a pleasant way for C#:
+// - Strip the enum name as a prefix if possible
+// - Convert to PascalCase.
+// For example, an enum called Color with a value of COLOR_BLUE should
+// result in an enum value in C# called just Blue
+std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
+  std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
+  std::string result = ShoutyToPascalCase(stripped);
+  // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
+  // string is a valid identifier.
+  if (ascii_isdigit(result[0])) {
+    result = "_" + result;
+  }
+  return result;
+}
+
+std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
+  std::string result = GetFileNamespace(file);
+  if (result != "") {
+    result += '.';
+  }
+  string classname;
+  if (file->package().empty()) {
+    classname = name;
+  } else {
+    // Strip the proto package from full_name since we've replaced it with
+    // the C# namespace.
+    classname = name.substr(file->package().size() + 1);
+  }
+  result += StringReplace(classname, ".", ".Types.", true);
+  return "global::" + result;
+}
+
+std::string GetReflectionClassName(const FileDescriptor* descriptor) {
+  std::string result = GetFileNamespace(descriptor);
+  if (!result.empty()) {
+    result += '.';
+  }
+  result += GetReflectionClassUnqualifiedName(descriptor);
+  return "global::" + result;
+}
+
+std::string GetClassName(const Descriptor* descriptor) {
+  return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+std::string GetClassName(const EnumDescriptor* descriptor) {
+  return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+// Groups are hacky:  The name of the field is just the lower-cased name
+// of the group type.  In C#, though, we would like to retain the original
+// capitalization of the type name.
+std::string GetFieldName(const FieldDescriptor* descriptor) {
+  if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+    return descriptor->message_type()->name();
+  } else {
+    return descriptor->name();
+  }
+}
+
+std::string GetFieldConstantName(const FieldDescriptor* field) {
+  return GetPropertyName(field) + "FieldNumber";
+}
+
+std::string GetPropertyName(const FieldDescriptor* descriptor) {
+  // TODO(jtattermusch): consider introducing csharp_property_name field option
+  std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
+  // Avoid either our own type name or reserved names. Note that not all names
+  // are reserved - a field called to_string, write_to etc would still cause a problem.
+  // There are various ways of ending up with naming collisions, but we try to avoid obvious
+  // ones.
+  if (property_name == descriptor->containing_type()->name()
+      || property_name == "Types"
+      || property_name == "Descriptor") {
+    property_name += "_";
+  }
+  return property_name;
+}
+
+std::string GetOutputFile(
+    const google::protobuf::FileDescriptor* descriptor,
+    const std::string file_extension,
+    const bool generate_directories,
+    const std::string base_namespace,
+    string* error) {
+  string relative_filename = GetFileNameBase(descriptor) + file_extension;
+  if (!generate_directories) {
+    return relative_filename;
+  }
+  string ns = GetFileNamespace(descriptor);
+  string namespace_suffix = ns;
+  if (!base_namespace.empty()) {
+    // Check that the base_namespace is either equal to or a leading part of
+    // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
+    // be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
+    // to both.
+    string extended_ns = ns + ".";
+    if (extended_ns.find(base_namespace + ".") != 0) {
+      *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
+      return ""; // This will be ignored, because we've set an error.
+    }
+    namespace_suffix = ns.substr(base_namespace.length());
+    if (namespace_suffix.find(".") == 0) {
+      namespace_suffix = namespace_suffix.substr(1);
+    }
+  }
+
+  string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+  if (!namespace_dir.empty()) {
+    namespace_dir += "/";
+  }
+  return namespace_dir + relative_filename;
+}
+
+// TODO: c&p from Java protoc plugin
+// For encodings with fixed sizes, returns that size in bytes.  Otherwise
+// returns -1.
+int GetFixedSize(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return -1;
+    case FieldDescriptor::TYPE_INT64   : return -1;
+    case FieldDescriptor::TYPE_UINT32  : return -1;
+    case FieldDescriptor::TYPE_UINT64  : return -1;
+    case FieldDescriptor::TYPE_SINT32  : return -1;
+    case FieldDescriptor::TYPE_SINT64  : return -1;
+    case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return internal::WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return internal::WireFormatLite::kDoubleSize;
+
+    case FieldDescriptor::TYPE_BOOL    : return internal::WireFormatLite::kBoolSize;
+    case FieldDescriptor::TYPE_ENUM    : return -1;
+
+    case FieldDescriptor::TYPE_STRING  : return -1;
+    case FieldDescriptor::TYPE_BYTES   : return -1;
+    case FieldDescriptor::TYPE_GROUP   : return -1;
+    case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;
+}
+
+static const char base64_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::string StringToBase64(const std::string& input) {
+  std::string result;
+  size_t remaining = input.size();
+  const unsigned char *src = (const unsigned char*) input.c_str();
+  while (remaining > 2) {
+    result += base64_chars[src[0] >> 2];
+    result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+    result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
+    result += base64_chars[src[2] & 0x3f];
+    remaining -= 3;
+    src += 3;
+  }
+  switch (remaining) {
+    case 2:
+      result += base64_chars[src[0] >> 2];
+      result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+      result += base64_chars[(src[1] & 0xf) << 2];
+      result += '=';
+      src += 2;
+      break;
+    case 1:
+      result += base64_chars[src[0] >> 2];
+      result += base64_chars[((src[0] & 0x3) << 4)];
+      result += '=';
+      result += '=';
+      src += 1;
+      break;
+  }
+  return result;
+}
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
+  std::string fdp_bytes;
+  FileDescriptorProto fdp;
+  descriptor->CopyTo(&fdp);
+  fdp.SerializeToString(&fdp_bytes);
+  return StringToBase64(fdp_bytes);
+}
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+                                         int fieldOrdinal,
+                                         const Options* options) {
+  switch (descriptor->type()) {
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      if (descriptor->is_repeated()) {
+        if (descriptor->is_map()) {
+          return new MapFieldGenerator(descriptor, fieldOrdinal, options);
+        } else {
+          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
+        }
+      } else {
+        if (IsWrapperType(descriptor)) {
+          if (descriptor->containing_oneof()) {
+            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
+          } else {
+            return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
+          }
+        } else {
+          if (descriptor->containing_oneof()) {
+            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
+          } else {
+            return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
+          }
+        }
+      }
+    case FieldDescriptor::TYPE_ENUM:
+      if (descriptor->is_repeated()) {
+        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
+      } else {
+        if (descriptor->containing_oneof()) {
+          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
+        } else {
+          return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
+        }
+      }
+    default:
+      if (descriptor->is_repeated()) {
+        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+      } else {
+        if (descriptor->containing_oneof()) {
+          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
+        } else {
+          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+        }
+      }
+  }
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.h
new file mode 100644
index 0000000..1563ca7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -0,0 +1,132 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+class FieldGeneratorBase;
+
+// TODO: start using this enum.
+enum CSharpType {
+  CSHARPTYPE_INT32 = 1,
+  CSHARPTYPE_INT64 = 2,
+  CSHARPTYPE_UINT32 = 3,
+  CSHARPTYPE_UINT64 = 4,
+  CSHARPTYPE_FLOAT = 5,
+  CSHARPTYPE_DOUBLE = 6,
+  CSHARPTYPE_BOOL = 7,
+  CSHARPTYPE_STRING = 8,
+  CSHARPTYPE_BYTESTRING = 9,
+  CSHARPTYPE_MESSAGE = 10,
+  CSHARPTYPE_ENUM = 11,
+  MAX_CSHARPTYPE = 11
+};
+
+// Converts field type to corresponding C# type.
+CSharpType GetCSharpType(FieldDescriptor::Type type);
+
+std::string StripDotProto(const std::string& proto_file);
+
+// Gets unqualified name of the reflection class
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
+
+std::string GetClassName(const EnumDescriptor* descriptor);
+
+std::string GetFieldName(const FieldDescriptor* descriptor);
+
+std::string GetFieldConstantName(const FieldDescriptor* field);
+
+std::string GetPropertyName(const FieldDescriptor* descriptor);
+
+int GetFixedSize(FieldDescriptor::Type type);
+
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period);
+
+inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
+  return UnderscoresToCamelCase(input, cap_next_letter, false);
+}
+
+std::string UnderscoresToPascalCase(const std::string& input);
+
+// Note that we wouldn't normally want to export this (we're not expecting
+// it to be used outside libprotoc itself) but this exposes it for testing.
+std::string LIBPROTOBUF_EXPORT GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name);
+
+// TODO(jtattermusch): perhaps we could move this to strutil
+std::string StringToBase64(const std::string& input);
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+                                         int fieldOrdinal,
+                                         const Options* options);
+
+// Determines whether the given message is a map entry message,
+// i.e. one implicitly created by protoc due to a map<key, value> field.
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
+// Determines whether we're generating code for the proto representation of
+// descriptors etc, for use in the runtime. This is the only type which is
+// allowed to use proto2 syntax, and it generates internal classes.
+inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
+  return descriptor->name() == "google/protobuf/descriptor.proto";
+}
+
+inline bool IsWrapperType(const FieldDescriptor* descriptor) {
+  return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+      descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.cc
new file mode 100644
index 0000000..565d122
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -0,0 +1,141 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     int fieldOrdinal,
+                                     const Options* options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+}
+
+MapFieldGenerator::~MapFieldGenerator() {
+}
+
+void MapFieldGenerator::GenerateMembers(io::Printer* printer) {   
+  const FieldDescriptor* key_descriptor =
+      descriptor_->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  variables_["key_type_name"] = type_name(key_descriptor);
+  variables_["value_type_name"] = type_name(value_descriptor);
+  scoped_ptr<FieldGeneratorBase> key_generator(
+      CreateFieldGenerator(key_descriptor, 1, this->options()));
+  scoped_ptr<FieldGeneratorBase> value_generator(
+      CreateFieldGenerator(value_descriptor, 2, this->options()));
+
+  printer->Print(
+    variables_,
+    "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
+    "    = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
+  key_generator->GenerateCodecCode(printer);
+  printer->Print(", ");
+  value_generator->GenerateCodecCode(printer);
+  printer->Print(
+    variables_,
+    ", $tag$);\n"
+    "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "}\n");
+}
+
+void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "$name$_.Add(other.$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.WriteTo(output, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "size += $name$_.CalculateSize(_map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "hash ^= $property_name$.GetHashCode();\n");
+}
+void MapFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if (!$property_name$.Equals(other.$property_name$)) return false;\n");
+}
+
+void MapFieldGenerator::WriteToString(io::Printer* printer) {
+    // TODO: If we ever actually use ToString, we'll need to impleme this...
+}
+
+void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
+void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.h
new file mode 100644
index 0000000..84a33a0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -0,0 +1,73 @@
+// 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_COMPILER_CSHARP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MapFieldGenerator : public FieldGeneratorBase {
+ public:
+  MapFieldGenerator(const FieldDescriptor* descriptor,
+                    int fieldOrdinal,
+                    const Options* options);
+  ~MapFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.cc
new file mode 100644
index 0000000..532da6b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -0,0 +1,504 @@
+// 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.
+
+#include <sstream>
+#include <algorithm>
+#include <map>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
+  return d1->number() < d2->number();
+}
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+                                   const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
+      descriptor_(descriptor) {
+
+  // sorted field names
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_names_.push_back(descriptor_->field(i)->name());
+  }
+  std::sort(field_names_.begin(), field_names_.end());
+
+  // fields by number
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    fields_by_number_.push_back(descriptor_->field(i));
+  }
+  std::sort(fields_by_number_.begin(), fields_by_number_.end(),
+            CompareFieldNumbers);
+}
+
+MessageGenerator::~MessageGenerator() {
+}
+
+std::string MessageGenerator::class_name() {
+  return descriptor_->name();
+}
+
+std::string MessageGenerator::full_class_name() {
+  return GetClassName(descriptor_);
+}
+
+const std::vector<std::string>& MessageGenerator::field_names() {
+  return field_names_;
+}
+
+const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
+  return fields_by_number_;
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  vars["class_name"] = class_name();
+  vars["access_level"] = class_access_level();
+
+  WriteMessageDocComment(printer, descriptor_);
+  printer->Print(
+    "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(
+    vars,
+    "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
+  printer->Indent();
+
+  // All static fields and properties
+  printer->Print(
+      vars,
+      "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
+      "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
+
+  // Access the message descriptor via the relevant file descriptor or containing message descriptor.
+  if (!descriptor_->containing_type()) {
+    vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
+        + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
+  } else {
+    vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+        + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
+  }
+
+  printer->Print(
+    vars,
+    "public static pbr::MessageDescriptor Descriptor {\n"
+    "  get { return $descriptor_accessor$; }\n"
+    "}\n"
+    "\n"
+    "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+    "  get { return Descriptor; }\n"
+    "}\n"
+    "\n");
+
+  // Parameterless constructor and partial OnConstruction method.
+  printer->Print(
+    vars,
+    "public $class_name$() {\n"
+    "  OnConstruction();\n"
+    "}\n\n"
+    "partial void OnConstruction();\n\n");
+
+  GenerateCloningCode(printer);
+  GenerateFreezingCode(printer);
+
+  // Fields/properties
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+
+    // Rats: we lose the debug comment here :(
+    printer->Print(
+      "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
+      "public const int $field_constant_name$ = $index$;\n",
+      "field_name", fieldDescriptor->name(),
+      "field_constant_name", GetFieldConstantName(fieldDescriptor),
+      "index", SimpleItoa(fieldDescriptor->number()));
+    scoped_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(fieldDescriptor));
+    generator->GenerateMembers(printer);
+    printer->Print("\n");
+  }
+
+  // oneof properties
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    vars["original_name"] = descriptor_->oneof_decl(i)->name();
+    printer->Print(
+      vars,
+      "private object $name$_;\n"
+      "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
+      "public enum $property_name$OneofCase {\n");
+    printer->Indent();
+    printer->Print("None = 0,\n");
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print("$field_property_name$ = $index$,\n",
+                     "field_property_name", GetPropertyName(field),
+                     "index", SimpleItoa(field->number()));
+    }
+    printer->Outdent();
+    printer->Print("}\n");
+    // TODO: Should we put the oneof .proto comments here?
+    // It's unclear exactly where they should go.
+    printer->Print(
+      vars,
+      "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
+      "public $property_name$OneofCase $property_name$Case {\n"
+      "  get { return $name$Case_; }\n"
+      "}\n\n"
+      "public void Clear$property_name$() {\n"
+      "  $name$Case_ = $property_name$OneofCase.None;\n"
+      "  $name$_ = null;\n"
+      "}\n\n");
+  }
+
+  // Standard methods
+  GenerateFrameworkMethods(printer);
+  GenerateMessageSerializationMethods(printer);
+  GenerateMergingMethods(printer);
+
+  // Nested messages and enums
+  if (HasNestedGeneratedTypes()) {
+    printer->Print(
+      vars,
+      "#region Nested types\n"
+      "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n"
+      "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print("public static partial class Types {\n");
+    printer->Indent();
+    for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+      EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
+      enumGenerator.Generate(printer);
+    }
+    for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+      // Don't generate nested types for maps...
+      if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
+        MessageGenerator messageGenerator(
+            descriptor_->nested_type(i), this->options());
+        messageGenerator.Generate(printer);
+      }
+    }
+    printer->Outdent();
+    printer->Print("}\n"
+                   "#endregion\n"
+                   "\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+  printer->Print("\n");
+}
+
+// Helper to work out whether we need to generate a class to hold nested types/enums.
+// Only tricky because we don't want to generate map entry types.
+bool MessageGenerator::HasNestedGeneratedTypes()
+{
+  if (descriptor_->enum_type_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
+  map<string, string> vars;
+  vars["class_name"] = class_name();
+    printer->Print(
+    vars,
+    "public $class_name$($class_name$ other) : this() {\n");
+  printer->Indent();
+  // Clone non-oneof fields first
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      scoped_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(descriptor_->field(i)));
+      generator->GenerateCloningCode(printer);
+    }
+  }
+  // Clone just the right field for each oneof
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(
+        descriptor_->oneof_decl(i)->name(), true);
+    printer->Print(vars, "switch (other.$property_name$Case) {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+      vars["field_property_name"] = GetPropertyName(field);
+      printer->Print(
+          vars,
+          "case $property_name$OneofCase.$field_property_name$:\n");
+      printer->Indent();
+      generator->GenerateCloningCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Outdent();
+    printer->Print("}\n\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+
+  printer->Print(
+    vars,
+    "public $class_name$ Clone() {\n"
+    "  return new $class_name$(this);\n"
+    "}\n\n");
+}
+
+void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
+    map<string, string> vars;
+    vars["class_name"] = class_name();
+
+    // Equality
+    printer->Print(
+        vars,
+        "public override bool Equals(object other) {\n"
+        "  return Equals(other as $class_name$);\n"
+        "}\n\n"
+        "public bool Equals($class_name$ other) {\n"
+        "  if (ReferenceEquals(other, null)) {\n"
+        "    return false;\n"
+        "  }\n"
+        "  if (ReferenceEquals(other, this)) {\n"
+        "    return true;\n"
+        "  }\n");
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+        scoped_ptr<FieldGeneratorBase> generator(
+            CreateFieldGeneratorInternal(descriptor_->field(i)));
+        generator->WriteEquals(printer);
+    }
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+        printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
+            "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+    }
+    printer->Outdent();
+    printer->Print(
+        "  return true;\n"
+        "}\n\n");
+
+    // GetHashCode
+    // Start with a non-zero value to easily distinguish between null and "empty" messages.
+    printer->Print(
+        "public override int GetHashCode() {\n"
+        "  int hash = 1;\n");
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+        scoped_ptr<FieldGeneratorBase> generator(
+            CreateFieldGeneratorInternal(descriptor_->field(i)));
+        generator->WriteHash(printer);
+    }
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+        printer->Print("hash ^= (int) $name$Case_;\n",
+            "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
+    }
+    printer->Print("return hash;\n");
+    printer->Outdent();
+    printer->Print("}\n\n");
+
+    printer->Print(
+        "public override string ToString() {\n"
+        "  return pb::JsonFormatter.ToDiagnosticString(this);\n"
+        "}\n\n");
+}
+
+void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
+  printer->Print(
+      "public void WriteTo(pb::CodedOutputStream output) {\n");
+  printer->Indent();
+
+  // Serialize all the fields
+  for (int i = 0; i < fields_by_number().size(); i++) {
+    scoped_ptr<FieldGeneratorBase> generator(
+      CreateFieldGeneratorInternal(fields_by_number()[i]));
+    generator->GenerateSerializationCode(printer);
+  }
+
+  // TODO(jonskeet): Memoize size of frozen messages?
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n"
+    "public int CalculateSize() {\n");
+  printer->Indent();
+  printer->Print("int size = 0;\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    scoped_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(descriptor_->field(i)));
+    generator->GenerateSerializedSizeCode(printer);
+  }
+  printer->Print("return size;\n");
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
+  // Note:  These are separate from GenerateMessageSerializationMethods()
+  //   because they need to be generated even for messages that are optimized
+  //   for code size.
+  map<string, string> vars;
+  vars["class_name"] = class_name();
+
+  printer->Print(
+    vars,
+    "public void MergeFrom($class_name$ other) {\n");
+  printer->Indent();
+  printer->Print(
+    "if (other == null) {\n"
+    "  return;\n"
+    "}\n");
+  // Merge non-oneof fields
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {      
+      scoped_ptr<FieldGeneratorBase> generator(
+          CreateFieldGeneratorInternal(descriptor_->field(i)));
+      generator->GenerateMergingCode(printer);
+    }
+  }
+  // Merge oneof fields
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    printer->Print(vars, "switch (other.$property_name$Case) {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      vars["field_property_name"] = GetPropertyName(field);
+      printer->Print(
+        vars,
+        "case $property_name$OneofCase.$field_property_name$:\n"
+        "  $field_property_name$ = other.$field_property_name$;\n"
+        "  break;\n");
+    }
+    printer->Outdent();
+    printer->Print("}\n\n");
+  }
+  printer->Outdent();
+  printer->Print("}\n\n");
+  printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
+  printer->Indent();
+  printer->Print(
+    "uint tag;\n"
+    "while ((tag = input.ReadTag()) != 0) {\n"
+    "  switch(tag) {\n");
+  printer->Indent();
+  printer->Indent();
+  printer->Print(
+    "default:\n"
+    "  input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
+    "  break;\n");
+  for (int i = 0; i < fields_by_number().size(); i++) {
+    const FieldDescriptor* field = fields_by_number()[i];
+    internal::WireFormatLite::WireType wt =
+        internal::WireFormat::WireTypeForFieldType(field->type());
+    uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
+    // Handle both packed and unpacked repeated fields with the same Read*Array call;
+    // the two generated cases are the packed and unpacked tags.
+    // TODO(jonskeet): Check that is_packable is equivalent to
+    // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
+    // It looks like it is...
+    if (field->is_packable()) {
+      printer->Print(
+        "case $packed_tag$:\n",
+        "packed_tag",
+        SimpleItoa(
+            internal::WireFormatLite::MakeTag(
+                field->number(),
+                internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
+    }
+
+    printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
+    printer->Indent();
+    scoped_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(field));
+    generator->GenerateParsingCode(printer);
+    printer->Print("break;\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+  printer->Outdent();
+  printer->Print("}\n"); // switch
+  printer->Outdent();
+  printer->Print("}\n"); // while
+  printer->Outdent();
+  printer->Print("}\n\n"); // method
+}
+
+int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
+  for (int i = 0; i < field_names().size(); i++) {
+    if (field_names()[i] == descriptor->name()) {
+      return i;
+    }
+  }
+  GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
+  return -1;
+}
+
+FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
+    const FieldDescriptor* descriptor) {
+  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.h
new file mode 100644
index 0000000..f794d68
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -0,0 +1,89 @@
+// 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_COMPILER_CSHARP_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase;
+
+class MessageGenerator : public SourceGeneratorBase {
+ public:
+  MessageGenerator(const Descriptor* descriptor, const Options* options);
+  ~MessageGenerator();
+
+  void GenerateCloningCode(io::Printer* printer);
+  void GenerateFreezingCode(io::Printer* printer);
+  void GenerateFrameworkMethods(io::Printer* printer);
+  void Generate(io::Printer* printer);
+
+ private:
+  const Descriptor* descriptor_;
+  std::vector<std::string> field_names_;
+  std::vector<const FieldDescriptor*> fields_by_number_;
+
+  void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateMergingMethods(io::Printer* printer);
+
+  int GetFieldOrdinal(const FieldDescriptor* descriptor);
+  FieldGeneratorBase* CreateFieldGeneratorInternal(
+      const FieldDescriptor* descriptor);
+
+  bool HasNestedGeneratedTypes();
+
+  std::string class_name();
+  std::string full_class_name();
+
+  // field names sorted alphabetically
+  const std::vector<std::string>& field_names();
+
+  // field descriptors sorted by number
+  const std::vector<const FieldDescriptor*>& fields_by_number();
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.cc
new file mode 100644
index 0000000..338692f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -0,0 +1,200 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             int fieldOrdinal,
+                                             const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+  variables_["has_property_check"] = name() + "_ != null";
+  variables_["has_not_property_check"] = name() + "_ == null";
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {
+
+}
+
+void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "private $type_name$ $name$_;\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "  set {\n"
+    "    $name$_ = value;\n"
+    "  }\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if (other.$has_property_check$) {\n"
+    "  if ($has_not_property_check$) {\n"
+    "    $name$_ = new $type_name$();\n"
+    "  }\n"
+    "  $property_name$.MergeFrom(other.$property_name$);\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_not_property_check$) {\n"
+    "  $name$_ = new $type_name$();\n"
+    "}\n"
+    // TODO(jonskeet): Do we really need merging behaviour like this?
+    "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
+}
+
+void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  output.WriteRawTag($tag_bytes$);\n"
+    "  output.WriteMessage($property_name$);\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
+}
+void MessageFieldGenerator::WriteToString(io::Printer* printer) {
+  variables_["field_name"] = GetFieldName(descriptor_);
+  printer->Print(
+    variables_,
+    "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
+}
+
+void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
+}
+
+void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+}
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor,
+	  int fieldOrdinal,
+    const Options *options)
+    : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
+  SetCommonOneofFieldVariables(&variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
+
+}
+
+void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
+    "  set {\n"
+    "    $oneof_name$_ = value;\n"
+    "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+    "  }\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  // TODO(jonskeet): We may be able to do better than this
+  printer->Print(
+    variables_,
+    "$type_name$ subBuilder = new $type_name$();\n"
+    "if ($has_property_check$) {\n"
+    "  subBuilder.MergeFrom($property_name$);\n"
+    "}\n"
+    "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
+    "$property_name$ = subBuilder;\n");
+}
+
+void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$property_name$.Clone();\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.h
new file mode 100644
index 0000000..7d61475
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -0,0 +1,90 @@
+// 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_COMPILER_CSHARP_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MessageFieldGenerator : public FieldGeneratorBase {
+ public:
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
+  ~MessageFieldGenerator();
+
+  virtual void GenerateCodecCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class MessageOneofFieldGenerator : public MessageFieldGenerator {
+ public:
+  MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
+  ~MessageOneofFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_names.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_names.h
new file mode 100644
index 0000000..3080518
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -0,0 +1,103 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Provides a mechanism for mapping a descriptor to the
+// fully-qualified name of the corresponding C# class.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace csharp {
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The namespace to use for given file descriptor.
+string GetFileNamespace(const FileDescriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified C# class name.
+string GetClassName(const Descriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified name of the C# class that provides
+//   access to the file descriptor. Proto compiler generates
+//   such class for each .proto file processed.
+string GetReflectionClassName(const FileDescriptor* descriptor);
+
+// Generates output file name for given file descriptor. If generate_directories
+// is true, the output file will be put under directory corresponding to file's
+// namespace. base_namespace can be used to strip some of the top level
+// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar",
+// the resulting file will be put under directory "Foo" (and not "Bar/Foo").
+//
+// Requires:
+//   descriptor != NULL
+//   error != NULL
+//
+//  Returns:
+//    The file name to use as output file for given file descriptor. In case
+//    of failure, this function will return empty string and error parameter
+//    will contain the error message.
+string GetOutputFile(
+    const google::protobuf::FileDescriptor* descriptor,
+    const string file_extension,
+    const bool generate_directories,
+    const string base_namespace,
+    string* error);
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_options.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_options.h
new file mode 100644
index 0000000..4079bf7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_options.h
@@ -0,0 +1,86 @@
+// 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_COMPILER_CSHARP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Generator options (used by csharp_generator.cc):
+struct Options {
+  Options() :
+      file_extension(".cs"),
+      base_namespace(""),
+      base_namespace_specified(false),
+      internal_access(false),
+      legacy_enum_values(false) {
+  }
+  // Extension of the generated file. Defaults to ".cs"
+  string file_extension;
+  // Base namespace to use to create directory hierarchy. Defaults to "".
+  // This option allows the simple creation of a conventional C# file layout,
+  // where directories are created relative to a project-specific base
+  // namespace. For example, in a project with a base namespace of PetShop, a
+  // proto of user.proto with a C# namespace of PetShop.Model.Shared would
+  // generate Model/Shared/User.cs underneath the specified --csharp_out
+  // directory.
+  //
+  // If no base namespace is specified, all files are generated in the
+  // --csharp_out directory, with no subdirectories created automatically.
+  string base_namespace;
+  // Whether the base namespace has been explicitly specified by the user.
+  // This is required as the base namespace can be explicitly set to the empty
+  // string, meaning "create a full directory hierarchy, starting from the first
+  // segment of the namespace."
+  bool base_namespace_specified;
+  // Whether the generated classes should have accessibility level of "internal".
+  // Defaults to false that generates "public" classes.
+  bool internal_access;
+  // By default, C# codegen now uses PascalCased enum values names, after
+  // removing the enum type name as a prefix (if it *is* a prefix of the value).
+  // Setting this option reverts to the previous behavior of just copying the
+  // value name specified in the .proto file, allowing gradual migration.
+  // This option will be removed before final release.
+  bool legacy_enum_values;
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
new file mode 100644
index 0000000..3b7ca75
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -0,0 +1,218 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+  // TODO(jonskeet): Make this cleaner...
+  is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
+      && descriptor->type() != FieldDescriptor::TYPE_BYTES;
+  if (!is_value_type) {
+    variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
+    variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
+  }
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
+}
+
+void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+  // TODO(jonskeet): Work out whether we want to prevent the fields from ever being
+  // null, or whether we just handle it, in the cases of bytes and string.
+  // (Basically, should null-handling code be in the getter or the setter?)
+  printer->Print(
+    variables_,
+    "private $type_name$ $name_def_message$;\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "  set {\n");
+  if (is_value_type) {
+    printer->Print(
+      variables_,
+      "    $name$_ = value;\n");
+  } else {
+    printer->Print(
+      variables_,
+      "    $name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+  }
+  printer->Print(
+    "  }\n"
+    "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($other_has_property_check$) {\n"
+    "  $property_name$ = other.$property_name$;\n"
+    "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  // Note: invoke the property setter rather than writing straight to the field,
+  // so that we can normalize "null to empty" for strings and bytes.
+  printer->Print(
+    variables_,
+    "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  output.WriteRawTag($tag_bytes$);\n"
+    "  output.Write$capitalized_type_name$($property_name$);\n"
+    "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n");
+  printer->Indent();
+  int fixedSize = GetFixedSize(descriptor_->type());
+  if (fixedSize == -1) {
+    printer->Print(
+      variables_,
+      "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
+  } else {
+    printer->Print(
+      "size += $tag_size$ + $fixed_size$;\n",
+      "fixed_size", SimpleItoa(fixedSize),
+      "tag_size", variables_["tag_size"]);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($property_name$ != other.$property_name$) return false;\n");
+}
+void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "pb::FieldCodec.For$capitalized_type_name$($tag$)");
+}
+
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+  SetCommonOneofFieldVariables(&variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
+    "  set {\n");
+    if (is_value_type) {
+      printer->Print(
+        variables_,
+        "    $oneof_name$_ = value;\n");
+    } else {
+      printer->Print(
+        variables_,
+        "    $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+    }
+    printer->Print(
+      variables_,
+      "    $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+      "  }\n"
+      "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
+  printer->Print(variables_,
+    "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+    printer->Print(
+      variables_,
+      "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$property_name$;\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
new file mode 100644
index 0000000..5f466fc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -0,0 +1,94 @@
+// 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_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class PrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
+  ~PrimitiveFieldGenerator();
+
+  virtual void GenerateCodecCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ protected:
+  bool is_value_type;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                               int fieldOrdinal,
+                               const Options *options);
+  ~PrimitiveOneofFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
new file mode 100644
index 0000000..f7397c0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -0,0 +1,293 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
+                                                   const Options* options)
+    : SourceGeneratorBase(file, options),
+      file_(file) {
+  namespace_ = GetFileNamespace(file);
+  reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
+}
+
+ReflectionClassGenerator::~ReflectionClassGenerator() {
+}
+
+void ReflectionClassGenerator::Generate(io::Printer* printer) {
+  WriteIntroduction(printer);
+
+  WriteDescriptor(printer);
+  // Close the class declaration.
+  printer->Outdent();
+  printer->Print("}\n");
+
+  // write children: Enums
+  if (file_->enum_type_count() > 0) {
+    printer->Print("#region Enums\n");
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      EnumGenerator enumGenerator(file_->enum_type(i), this->options());
+      enumGenerator.Generate(printer);
+    }
+    printer->Print("#endregion\n");
+    printer->Print("\n");
+  }
+
+  // write children: Messages
+  if (file_->message_type_count() > 0) {
+    printer->Print("#region Messages\n");
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      MessageGenerator messageGenerator(file_->message_type(i), this->options());
+      messageGenerator.Generate(printer);
+    }
+    printer->Print("#endregion\n");
+    printer->Print("\n");
+  }
+
+  // TODO(jtattermusch): add insertion point for services.
+
+  if (!namespace_.empty()) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+  printer->Print("\n");
+  printer->Print("#endregion Designer generated code\n");
+}
+
+void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
+  printer->Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "// source: $file_name$\n"
+    "#pragma warning disable 1591, 0612, 3021\n"
+    "#region Designer generated code\n"
+    "\n"
+    "using pb = global::Google.Protobuf;\n"
+    "using pbc = global::Google.Protobuf.Collections;\n"
+    "using pbr = global::Google.Protobuf.Reflection;\n"
+    "using scg = global::System.Collections.Generic;\n",
+    "file_name", file_->name());
+
+  if (!namespace_.empty()) {
+    printer->Print("namespace $namespace$ {\n", "namespace", namespace_);
+    printer->Indent();
+    printer->Print("\n");
+  }
+
+  printer->Print(
+    "/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
+    "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n",
+    "file_name", file_->name());
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(
+    "$access_level$ static partial class $reflection_class_name$ {\n"
+    "\n",
+    "access_level", class_access_level(),
+    "reflection_class_name", reflectionClassname_);
+  printer->Indent();
+}
+
+void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) {
+  printer->Print(
+    "#region Descriptor\n"
+    "/// <summary>File descriptor for $file_name$</summary>\n"
+    "public static pbr::FileDescriptor Descriptor {\n"
+    "  get { return descriptor; }\n"
+    "}\n"
+    "private static pbr::FileDescriptor descriptor;\n"
+    "\n"
+    "static $reflection_class_name$() {\n",
+    "file_name", file_->name(),
+    "reflection_class_name", reflectionClassname_);
+  printer->Indent();
+  printer->Print(
+    "byte[] descriptorData = global::System.Convert.FromBase64String(\n");
+  printer->Indent();
+  printer->Indent();
+  printer->Print("string.Concat(\n");
+  printer->Indent();
+
+  // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
+  std::string base64 = FileDescriptorToBase64(file_);
+  while (base64.size() > 60) {
+    printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
+    base64 = base64.substr(60);
+  }
+  printer->Print("\"$base64$\"));\n", "base64", base64);
+  printer->Outdent();
+  printer->Outdent();
+  printer->Outdent();
+
+  // -----------------------------------------------------------------
+  // Invoke InternalBuildGeneratedFileFrom() to build the file.
+  printer->Print(
+      "descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n");
+  printer->Print("    new pbr::FileDescriptor[] { ");
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    // descriptor.proto is special: we don't allow access to the generated code, but there's
+    // a separately-exposed property to get at the file descriptor, specifically to allow this
+    // kind of dependency.
+    if (IsDescriptorProto(file_->dependency(i))) {
+      printer->Print("pbr::FileDescriptor.DescriptorProtoFileDescriptor, ");
+    } else {
+      printer->Print(
+      "$full_reflection_class_name$.Descriptor, ",
+      "full_reflection_class_name",
+      GetReflectionClassName(file_->dependency(i)));
+    }
+  }
+  printer->Print("},\n"
+      "    new pbr::GeneratedClrTypeInfo(");
+  // Specify all the generated code information, recursively.
+  if (file_->enum_type_count() > 0) {
+      printer->Print("new[] {");
+      for (int i = 0; i < file_->enum_type_count(); i++) {
+          printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+      }
+      printer->Print("}, ");
+  }
+  else {
+      printer->Print("null, ");
+  }
+  if (file_->message_type_count() > 0) {
+      printer->Print("new pbr::GeneratedClrTypeInfo[] {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (int i = 0; i < file_->message_type_count(); i++) {
+          WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
+      }
+      printer->Outdent();
+      printer->Print("\n}));\n");
+      printer->Outdent();
+      printer->Outdent();
+  }
+  else {
+      printer->Print("null));\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+  printer->Print("#endregion\n\n");
+}
+
+// Write out the generated code for a particular message. This consists of the CLR type, property names
+// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
+// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
+// We write a line break at the end of each generated code info, so that in the final file we'll see all
+// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
+// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
+// read even with multiple levels of nesting.
+// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
+// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
+// just controlling the formatting in the generated code.
+void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
+  if (IsMapEntryMessage(descriptor)) {
+    printer->Print("null, ");
+    return;
+  }
+  // Generated message type
+  printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor));
+  
+  // Fields
+  if (descriptor->field_count() > 0) {
+      std::vector<std::string> fields;
+      for (int i = 0; i < descriptor->field_count(); i++) {
+          fields.push_back(GetPropertyName(descriptor->field(i)));
+      }
+      printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Oneofs
+  if (descriptor->oneof_decl_count() > 0) {
+      std::vector<std::string> oneofs;
+      for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
+          oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
+      }
+      printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested enums
+  if (descriptor->enum_type_count() > 0) {
+      std::vector<std::string> enums;
+      for (int i = 0; i < descriptor->enum_type_count(); i++) {
+          enums.push_back(GetClassName(descriptor->enum_type(i)));
+      }
+      printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof("));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested types
+  if (descriptor->nested_type_count() > 0) {
+      // Need to specify array type explicitly here, as all elements may be null. 
+      printer->Print("new pbr::GeneratedClrTypeInfo[] { ");
+      for (int i = 0; i < descriptor->nested_type_count(); i++) {
+          WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
+      }
+      printer->Print("}");
+  }
+  else {
+      printer->Print("null");
+  }
+  printer->Print(last ? ")" : "),\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
new file mode 100644
index 0000000..e0c69f3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
@@ -0,0 +1,71 @@
+// 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_COMPILER_CSHARP_REFLECTION_CLASS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class ReflectionClassGenerator : public SourceGeneratorBase {
+ public:
+  ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
+  ~ReflectionClassGenerator();
+
+  void Generate(io::Printer* printer);
+
+ private:
+  const FileDescriptor* file_;
+
+  std::string namespace_;
+  std::string reflectionClassname_;
+
+  void WriteIntroduction(io::Printer* printer);
+  void WriteDescriptor(io::Printer* printer);
+  void WriteGeneratedCodeInfo(const Descriptor* descriptor,
+                              io::Printer* printer,
+                              bool last);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionClassGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
new file mode 100644
index 0000000..1befdc1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -0,0 +1,127 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
+
+}
+
+void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+    "    = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
+  printer->Print(variables_,
+    "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {  
+  printer->Print(
+    variables_,
+    "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
+  printer->Print(variables_,
+    "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
new file mode 100644
index 0000000..819b583
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -0,0 +1,75 @@
+// 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_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We
+// should probably have a RepeatedFieldGeneratorBase.
+class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
+ public:
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
+  ~RepeatedEnumFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
new file mode 100644
index 0000000..d51e638
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -0,0 +1,144 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
+
+}
+
+void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+    "    = ");
+  // Don't want to duplicate the codec code here... maybe we should have a
+  // "create single field generator for this repeated field"
+  // function, but it doesn't seem worth it for just this.
+  if (IsWrapperType(descriptor_)) {
+    scoped_ptr<FieldGeneratorBase> single_generator(
+      new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+    single_generator->GenerateCodecCode(printer);
+  } else {
+    scoped_ptr<FieldGeneratorBase> single_generator(
+      new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+    single_generator->GenerateCodecCode(printer);
+  }
+  printer->Print(";\n");
+  printer->Print(
+    variables_,
+    "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) {
+  variables_["field_name"] = GetFieldName(descriptor_);
+  printer->Print(
+    variables_,
+    "PrintField(\"$field_name$\", $name$_, writer);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
new file mode 100644
index 0000000..6e33648
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -0,0 +1,75 @@
+// 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_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
+ public:
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                int fieldOrdinal,
+                                const Options *options);
+  ~RepeatedMessageFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
new file mode 100644
index 0000000..bee3f36
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -0,0 +1,125 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
+
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+    "    = pb::FieldCodec.For$capitalized_type_name$($tag$);\n");
+  printer->Print(variables_,
+    "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "hash ^= $name$_.GetHashCode();\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+  printer->Print(variables_,
+    "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
new file mode 100644
index 0000000..a59348a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -0,0 +1,71 @@
+// 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_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
+  ~RepeatedPrimitiveFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
new file mode 100644
index 0000000..16411e4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -0,0 +1,73 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
+                                         const Options *options)
+    : descriptor_(descriptor), options_(options) {
+}
+
+SourceGeneratorBase::~SourceGeneratorBase() {
+}
+
+void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
+  // This hook can be used to reintroduce generated code attributes in the future.
+}
+
+std::string SourceGeneratorBase::class_access_level() {
+  return (IsDescriptorProto(descriptor_) || this->options()->internal_access) ? "internal" : "public";
+}
+
+const Options* SourceGeneratorBase::options() {
+  return this->options_;
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
new file mode 100644
index 0000000..2e73458
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -0,0 +1,68 @@
+// 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_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class SourceGeneratorBase {
+ protected:
+  SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
+  virtual ~SourceGeneratorBase();
+
+  std::string class_access_level();
+  const Options* options();
+
+  void WriteGeneratedCodeAttributes(io::Printer* printer);
+
+ private:
+  const FileDescriptor* descriptor_;
+  const Options *options_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
new file mode 100644
index 0000000..5cb86b6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -0,0 +1,211 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
+                                       int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+  variables_["has_property_check"] = name() + "_ != null";
+  variables_["has_not_property_check"] = name() + "_ == null";
+  const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+  is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING &&
+      wrapped_field->type() != FieldDescriptor::TYPE_BYTES;
+  if (is_value_type) {
+    variables_["nonnullable_type_name"] = type_name(wrapped_field);
+  }
+}
+
+WrapperFieldGenerator::~WrapperFieldGenerator() {
+}
+
+void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
+  printer->Print(
+        variables_,
+        "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = ");
+  GenerateCodecCode(printer);
+  printer->Print(
+    variables_,
+    ";\n"
+    "private $type_name$ $name$_;\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "  set {\n"
+    "    $name$_ = value;\n"
+    "  }\n"
+    "}\n");
+}
+
+void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if (other.$has_property_check$) {\n"
+    "  if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n"
+    "    $property_name$ = other.$property_name$;\n"
+    "  }\n"
+    "}\n");
+}
+
+void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$type_name$ value = _single_$name$_codec.Read(input);\n"
+    "if ($has_not_property_check$ || value != $default_value$) {\n"
+    "  $property_name$ = value;\n"
+    "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
+    "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+    "}\n");
+}
+
+void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+
+void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if ($property_name$ != other.$property_name$) return false;\n");
+}
+
+void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
+  // TODO: Implement if we ever actually need it...
+}
+
+void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$property_name$;\n");
+}
+
+void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+  if (is_value_type) {
+    printer->Print(
+      variables_,
+      "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)");
+  } else {
+    printer->Print(
+      variables_,
+      "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)");
+  }
+}
+
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
+    SetCommonOneofFieldVariables(&variables_);
+}
+
+WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() {
+}
+
+void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+  // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field.
+  printer->Print(
+        variables_,
+        "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = ");
+  GenerateCodecCode(printer);
+  printer->Print(";\n");
+  WritePropertyDocComment(printer, descriptor_);
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "$access_level$ $type_name$ $property_name$ {\n"
+    "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
+    "  set {\n"
+    "    $oneof_name$_ = value;\n"
+    "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+    "  }\n"
+    "}\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$property_name$ = _oneof_$name$_codec.Read(input);\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  // TODO: I suspect this is wrong...
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
+    "}\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  // TODO: I suspect this is wrong...
+  printer->Print(
+    variables_,
+    "if ($has_property_check$) {\n"
+    "  size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+    "}\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
new file mode 100644
index 0000000..250dfd2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -0,0 +1,91 @@
+// 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_COMPILER_CSHARP_WRAPPER_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class WrapperFieldGenerator : public FieldGeneratorBase {
+ public:
+  WrapperFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
+  ~WrapperFieldGenerator();
+
+  virtual void GenerateCodecCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  bool is_value_type; // True for int32 etc; false for bytes and string
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator);
+};
+
+class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
+ public:
+  WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
+  ~WrapperOneofFieldGenerator();
+
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.cc
new file mode 100644
index 0000000..0d9093c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.cc
@@ -0,0 +1,496 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/importer.h>
+
+#include <google/protobuf/compiler/parser.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#ifdef _WIN32
+#ifndef F_OK
+#define F_OK 00  // not defined by MSVC for whatever reason
+#endif
+#include <ctype.h>
+#endif
+
+// Returns true if the text looks like a Windows-style absolute path, starting
+// with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
+// copy in command_line_interface.cc?
+static bool IsWindowsAbsolutePath(const string& text) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+  return text.size() >= 3 && text[1] == ':' &&
+         isalpha(text[0]) &&
+         (text[2] == '/' || text[2] == '\\') &&
+         text.find_last_of(':') == 1;
+#else
+  return false;
+#endif
+}
+
+MultiFileErrorCollector::~MultiFileErrorCollector() {}
+
+// This class serves two purposes:
+// - It implements the ErrorCollector interface (used by Tokenizer and Parser)
+//   in terms of MultiFileErrorCollector, using a particular filename.
+// - It lets us check if any errors have occurred.
+class SourceTreeDescriptorDatabase::SingleFileErrorCollector
+    : public io::ErrorCollector {
+ public:
+  SingleFileErrorCollector(const string& filename,
+                           MultiFileErrorCollector* multi_file_error_collector)
+    : filename_(filename),
+      multi_file_error_collector_(multi_file_error_collector),
+      had_errors_(false) {}
+  ~SingleFileErrorCollector() {}
+
+  bool had_errors() { return had_errors_; }
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(int line, int column, const string& message) {
+    if (multi_file_error_collector_ != NULL) {
+      multi_file_error_collector_->AddError(filename_, line, column, message);
+    }
+    had_errors_ = true;
+  }
+
+ private:
+  string filename_;
+  MultiFileErrorCollector* multi_file_error_collector_;
+  bool had_errors_;
+};
+
+// ===================================================================
+
+SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase(
+    SourceTree* source_tree)
+  : source_tree_(source_tree),
+    error_collector_(NULL),
+    using_validation_error_collector_(false),
+    validation_error_collector_(this) {}
+
+SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {}
+
+bool SourceTreeDescriptorDatabase::FindFileByName(
+    const string& filename, FileDescriptorProto* output) {
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
+  if (input == NULL) {
+    if (error_collector_ != NULL) {
+      error_collector_->AddError(filename, -1, 0,
+                                 source_tree_->GetLastErrorMessage());
+    }
+    return false;
+  }
+
+  // Set up the tokenizer and parser.
+  SingleFileErrorCollector file_error_collector(filename, error_collector_);
+  io::Tokenizer tokenizer(input.get(), &file_error_collector);
+
+  Parser parser;
+  if (error_collector_ != NULL) {
+    parser.RecordErrorsTo(&file_error_collector);
+  }
+  if (using_validation_error_collector_) {
+    parser.RecordSourceLocationsTo(&source_locations_);
+  }
+
+  // Parse it.
+  output->set_name(filename);
+  return parser.Parse(&tokenizer, output) &&
+         !file_error_collector.had_errors();
+}
+
+bool SourceTreeDescriptorDatabase::FindFileContainingSymbol(
+    const string& symbol_name, FileDescriptorProto* output) {
+  return false;
+}
+
+bool SourceTreeDescriptorDatabase::FindFileContainingExtension(
+    const string& containing_type, int field_number,
+    FileDescriptorProto* output) {
+  return false;
+}
+
+// -------------------------------------------------------------------
+
+SourceTreeDescriptorDatabase::ValidationErrorCollector::
+ValidationErrorCollector(SourceTreeDescriptorDatabase* owner)
+  : owner_(owner) {}
+
+SourceTreeDescriptorDatabase::ValidationErrorCollector::
+~ValidationErrorCollector() {}
+
+void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError(
+    const string& filename,
+    const string& element_name,
+    const Message* descriptor,
+    ErrorLocation location,
+    const string& message) {
+  if (owner_->error_collector_ == NULL) return;
+
+  int line, column;
+  owner_->source_locations_.Find(descriptor, location, &line, &column);
+  owner_->error_collector_->AddError(filename, line, column, message);
+}
+
+void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning(
+    const string& filename,
+    const string& element_name,
+    const Message* descriptor,
+    ErrorLocation location,
+    const string& message) {
+  if (owner_->error_collector_ == NULL) return;
+
+  int line, column;
+  owner_->source_locations_.Find(descriptor, location, &line, &column);
+  owner_->error_collector_->AddWarning(filename, line, column, message);
+}
+
+// ===================================================================
+
+Importer::Importer(SourceTree* source_tree,
+                   MultiFileErrorCollector* error_collector)
+  : database_(source_tree),
+    pool_(&database_, database_.GetValidationErrorCollector()) {
+  pool_.EnforceWeakDependencies(true);
+  database_.RecordErrorsTo(error_collector);
+}
+
+Importer::~Importer() {}
+
+const FileDescriptor* Importer::Import(const string& filename) {
+  return pool_.FindFileByName(filename);
+}
+
+void Importer::AddUnusedImportTrackFile(const string& file_name) {
+  pool_.AddUnusedImportTrackFile(file_name);
+}
+
+void Importer::ClearUnusedImportTrackFiles() {
+  pool_.ClearUnusedImportTrackFiles();
+}
+
+// ===================================================================
+
+SourceTree::~SourceTree() {}
+
+string SourceTree::GetLastErrorMessage() {
+  return "File not found.";
+}
+
+DiskSourceTree::DiskSourceTree() {}
+
+DiskSourceTree::~DiskSourceTree() {}
+
+static inline char LastChar(const string& str) {
+  return str[str.size() - 1];
+}
+
+// Given a path, returns an equivalent path with these changes:
+// - On Windows, any backslashes are replaced with forward slashes.
+// - Any instances of the directory "." are removed.
+// - Any consecutive '/'s are collapsed into a single slash.
+// Note that the resulting string may be empty.
+//
+// TODO(kenton):  It would be nice to handle "..", e.g. so that we can figure
+//   out that "foo/bar.proto" is inside "baz/../foo".  However, if baz is a
+//   symlink or doesn't exist, then things get complicated, and we can't
+//   actually determine this without investigating the filesystem, probably
+//   in non-portable ways.  So, we punt.
+//
+// TODO(kenton):  It would be nice to use realpath() here except that it
+//   resolves symbolic links.  This could cause problems if people place
+//   symbolic links in their source tree.  For example, if you executed:
+//     protoc --proto_path=foo foo/bar/baz.proto
+//   then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize
+//   to a path which does not appear to be under foo, and thus the compiler
+//   will complain that baz.proto is not inside the --proto_path.
+static string CanonicalizePath(string path) {
+#ifdef _WIN32
+  // The Win32 API accepts forward slashes as a path delimiter even though
+  // backslashes are standard.  Let's avoid confusion and use only forward
+  // slashes.
+  if (HasPrefixString(path, "\\\\")) {
+    // Avoid converting two leading backslashes.
+    path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true);
+  } else {
+    path = StringReplace(path, "\\", "/", true);
+  }
+#endif
+
+  vector<string> canonical_parts;
+  vector<string> parts = Split(
+      path, "/", true);  // Note:  Removes empty parts.
+  for (int i = 0; i < parts.size(); i++) {
+    if (parts[i] == ".") {
+      // Ignore.
+    } else {
+      canonical_parts.push_back(parts[i]);
+    }
+  }
+  string result = Join(canonical_parts, "/");
+  if (!path.empty() && path[0] == '/') {
+    // Restore leading slash.
+    result = '/' + result;
+  }
+  if (!path.empty() && LastChar(path) == '/' &&
+      !result.empty() && LastChar(result) != '/') {
+    // Restore trailing slash.
+    result += '/';
+  }
+  return result;
+}
+
+static inline bool ContainsParentReference(const string& path) {
+  return path == ".." ||
+         HasPrefixString(path, "../") ||
+         HasSuffixString(path, "/..") ||
+         path.find("/../") != string::npos;
+}
+
+// Maps a file from an old location to a new one.  Typically, old_prefix is
+// a virtual path and new_prefix is its corresponding disk path.  Returns
+// false if the filename did not start with old_prefix, otherwise replaces
+// old_prefix with new_prefix and stores the result in *result.  Examples:
+//   string result;
+//   assert(ApplyMapping("foo/bar", "", "baz", &result));
+//   assert(result == "baz/foo/bar");
+//
+//   assert(ApplyMapping("foo/bar", "foo", "baz", &result));
+//   assert(result == "baz/bar");
+//
+//   assert(ApplyMapping("foo", "foo", "bar", &result));
+//   assert(result == "bar");
+//
+//   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
+//   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
+//   assert(!ApplyMapping("foobar", "foo", "baz", &result));
+static bool ApplyMapping(const string& filename,
+                         const string& old_prefix,
+                         const string& new_prefix,
+                         string* result) {
+  if (old_prefix.empty()) {
+    // old_prefix matches any relative path.
+    if (ContainsParentReference(filename)) {
+      // We do not allow the file name to use "..".
+      return false;
+    }
+    if (HasPrefixString(filename, "/") ||
+        IsWindowsAbsolutePath(filename)) {
+      // This is an absolute path, so it isn't matched by the empty string.
+      return false;
+    }
+    result->assign(new_prefix);
+    if (!result->empty()) result->push_back('/');
+    result->append(filename);
+    return true;
+  } else if (HasPrefixString(filename, old_prefix)) {
+    // old_prefix is a prefix of the filename.  Is it the whole filename?
+    if (filename.size() == old_prefix.size()) {
+      // Yep, it's an exact match.
+      *result = new_prefix;
+      return true;
+    } else {
+      // Not an exact match.  Is the next character a '/'?  Otherwise,
+      // this isn't actually a match at all.  E.g. the prefix "foo/bar"
+      // does not match the filename "foo/barbaz".
+      int after_prefix_start = -1;
+      if (filename[old_prefix.size()] == '/') {
+        after_prefix_start = old_prefix.size() + 1;
+      } else if (filename[old_prefix.size() - 1] == '/') {
+        // old_prefix is never empty, and canonicalized paths never have
+        // consecutive '/' characters.
+        after_prefix_start = old_prefix.size();
+      }
+      if (after_prefix_start != -1) {
+        // Yep.  So the prefixes are directories and the filename is a file
+        // inside them.
+        string after_prefix = filename.substr(after_prefix_start);
+        if (ContainsParentReference(after_prefix)) {
+          // We do not allow the file name to use "..".
+          return false;
+        }
+        result->assign(new_prefix);
+        if (!result->empty()) result->push_back('/');
+        result->append(after_prefix);
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+void DiskSourceTree::MapPath(const string& virtual_path,
+                             const string& disk_path) {
+  mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path)));
+}
+
+DiskSourceTree::DiskFileToVirtualFileResult
+DiskSourceTree::DiskFileToVirtualFile(
+    const string& disk_file,
+    string* virtual_file,
+    string* shadowing_disk_file) {
+  int mapping_index = -1;
+  string canonical_disk_file = CanonicalizePath(disk_file);
+
+  for (int i = 0; i < mappings_.size(); i++) {
+    // Apply the mapping in reverse.
+    if (ApplyMapping(canonical_disk_file, mappings_[i].disk_path,
+                     mappings_[i].virtual_path, virtual_file)) {
+      // Success.
+      mapping_index = i;
+      break;
+    }
+  }
+
+  if (mapping_index == -1) {
+    return NO_MAPPING;
+  }
+
+  // Iterate through all mappings with higher precedence and verify that none
+  // of them map this file to some other existing file.
+  for (int i = 0; i < mapping_index; i++) {
+    if (ApplyMapping(*virtual_file, mappings_[i].virtual_path,
+                     mappings_[i].disk_path, shadowing_disk_file)) {
+      if (access(shadowing_disk_file->c_str(), F_OK) >= 0) {
+        // File exists.
+        return SHADOWED;
+      }
+    }
+  }
+  shadowing_disk_file->clear();
+
+  // Verify that we can open the file.  Note that this also has the side-effect
+  // of verifying that we are not canonicalizing away any non-existent
+  // directories.
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
+  if (stream == NULL) {
+    return CANNOT_OPEN;
+  }
+
+  return SUCCESS;
+}
+
+bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
+                                           string* disk_file) {
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(
+      OpenVirtualFile(virtual_file, disk_file));
+  return stream != NULL;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) {
+  return OpenVirtualFile(filename, NULL);
+}
+
+string DiskSourceTree::GetLastErrorMessage() {
+  return last_error_message_;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
+    const string& virtual_file,
+    string* disk_file) {
+  if (virtual_file != CanonicalizePath(virtual_file) ||
+      ContainsParentReference(virtual_file)) {
+    // We do not allow importing of paths containing things like ".." or
+    // consecutive slashes since the compiler expects files to be uniquely
+    // identified by file name.
+    last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" "
+                          "are not allowed in the virtual path";
+    return NULL;
+  }
+
+  for (int i = 0; i < mappings_.size(); i++) {
+    string temp_disk_file;
+    if (ApplyMapping(virtual_file, mappings_[i].virtual_path,
+                     mappings_[i].disk_path, &temp_disk_file)) {
+      io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file);
+      if (stream != NULL) {
+        if (disk_file != NULL) {
+          *disk_file = temp_disk_file;
+        }
+        return stream;
+      }
+
+      if (errno == EACCES) {
+        // The file exists but is not readable.
+        last_error_message_ = "Read access is denied for file: " +
+                              temp_disk_file;
+        return NULL;
+      }
+    }
+  }
+  last_error_message_ = "File not found.";
+  return NULL;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
+    const string& filename) {
+  int file_descriptor;
+  do {
+    file_descriptor = open(filename.c_str(), O_RDONLY);
+  } while (file_descriptor < 0 && errno == EINTR);
+  if (file_descriptor >= 0) {
+    io::FileInputStream* result = new io::FileInputStream(file_descriptor);
+    result->SetCloseOnDelete(true);
+    return result;
+  } else {
+    return NULL;
+  }
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.h
new file mode 100644
index 0000000..cc8fcc3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer.h
@@ -0,0 +1,326 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file is the public interface to the .proto file parser.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
+#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
+
+#include <string>
+#include <vector>
+#include <set>
+#include <utility>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/compiler/parser.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io { class ZeroCopyInputStream; }
+
+namespace compiler {
+
+// Defined in this file.
+class Importer;
+class MultiFileErrorCollector;
+class SourceTree;
+class DiskSourceTree;
+
+// TODO(kenton):  Move all SourceTree stuff to a separate file?
+
+// An implementation of DescriptorDatabase which loads files from a SourceTree
+// and parses them.
+//
+// Note:  This class is not thread-safe since it maintains a table of source
+//   code locations for error reporting.  However, when a DescriptorPool wraps
+//   a DescriptorDatabase, it uses mutex locking to make sure only one method
+//   of the database is called at a time, even if the DescriptorPool is used
+//   from multiple threads.  Therefore, there is only a problem if you create
+//   multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase
+//   and use them from multiple threads.
+//
+// Note:  This class does not implement FindFileContainingSymbol() or
+//   FindFileContainingExtension(); these will always return false.
+class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase {
+ public:
+  SourceTreeDescriptorDatabase(SourceTree* source_tree);
+  ~SourceTreeDescriptorDatabase();
+
+  // Instructs the SourceTreeDescriptorDatabase to report any parse errors
+  // to the given MultiFileErrorCollector.  This should be called before
+  // parsing.  error_collector must remain valid until either this method
+  // is called again or the SourceTreeDescriptorDatabase is destroyed.
+  void RecordErrorsTo(MultiFileErrorCollector* error_collector) {
+    error_collector_ = error_collector;
+  }
+
+  // Gets a DescriptorPool::ErrorCollector which records errors to the
+  // MultiFileErrorCollector specified with RecordErrorsTo().  This collector
+  // has the ability to determine exact line and column numbers of errors
+  // from the information given to it by the DescriptorPool.
+  DescriptorPool::ErrorCollector* GetValidationErrorCollector() {
+    using_validation_error_collector_ = true;
+    return &validation_error_collector_;
+  }
+
+  // implements DescriptorDatabase -----------------------------------
+  bool FindFileByName(const string& filename, FileDescriptorProto* output);
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+
+ private:
+  class SingleFileErrorCollector;
+
+  SourceTree* source_tree_;
+  MultiFileErrorCollector* error_collector_;
+
+  class LIBPROTOBUF_EXPORT ValidationErrorCollector : public DescriptorPool::ErrorCollector {
+   public:
+    ValidationErrorCollector(SourceTreeDescriptorDatabase* owner);
+    ~ValidationErrorCollector();
+
+    // implements ErrorCollector ---------------------------------------
+    void AddError(const string& filename,
+                  const string& element_name,
+                  const Message* descriptor,
+                  ErrorLocation location,
+                  const string& message);
+
+    virtual void AddWarning(const string& filename,
+                            const string& element_name,
+                            const Message* descriptor,
+                            ErrorLocation location,
+                            const string& message);
+
+   private:
+    SourceTreeDescriptorDatabase* owner_;
+  };
+  friend class ValidationErrorCollector;
+
+  bool using_validation_error_collector_;
+  SourceLocationTable source_locations_;
+  ValidationErrorCollector validation_error_collector_;
+};
+
+// Simple interface for parsing .proto files.  This wraps the process
+// of opening the file, parsing it with a Parser, recursively parsing all its
+// imports, and then cross-linking the results to produce a FileDescriptor.
+//
+// This is really just a thin wrapper around SourceTreeDescriptorDatabase.
+// You may find that SourceTreeDescriptorDatabase is more flexible.
+//
+// TODO(kenton):  I feel like this class is not well-named.
+class LIBPROTOBUF_EXPORT Importer {
+ public:
+  Importer(SourceTree* source_tree,
+           MultiFileErrorCollector* error_collector);
+  ~Importer();
+
+  // Import the given file and build a FileDescriptor representing it.  If
+  // the file is already in the DescriptorPool, the existing FileDescriptor
+  // will be returned.  The FileDescriptor is property of the DescriptorPool,
+  // and will remain valid until it is destroyed.  If any errors occur, they
+  // will be reported using the error collector and Import() will return NULL.
+  //
+  // A particular Importer object will only report errors for a particular
+  // file once.  All future attempts to import the same file will return NULL
+  // without reporting any errors.  The idea is that you might want to import
+  // a lot of files without seeing the same errors over and over again.  If
+  // you want to see errors for the same files repeatedly, you can use a
+  // separate Importer object to import each one (but use the same
+  // DescriptorPool so that they can be cross-linked).
+  const FileDescriptor* Import(const string& filename);
+
+  // The DescriptorPool in which all imported FileDescriptors and their
+  // contents are stored.
+  inline const DescriptorPool* pool() const {
+    return &pool_;
+  }
+
+  void AddUnusedImportTrackFile(const string& file_name);
+  void ClearUnusedImportTrackFiles();
+
+ private:
+  SourceTreeDescriptorDatabase database_;
+  DescriptorPool pool_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
+};
+
+// If the importer encounters problems while trying to import the proto files,
+// it reports them to a MultiFileErrorCollector.
+class LIBPROTOBUF_EXPORT MultiFileErrorCollector {
+ public:
+  inline MultiFileErrorCollector() {}
+  virtual ~MultiFileErrorCollector();
+
+  // Line and column numbers are zero-based.  A line number of -1 indicates
+  // an error with the entire file (e.g. "not found").
+  virtual void AddError(const string& filename, int line, int column,
+                        const string& message) = 0;
+
+  virtual void AddWarning(const string& filename, int line, int column,
+                          const string& message) {}
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
+};
+
+// Abstract interface which represents a directory tree containing proto files.
+// Used by the default implementation of Importer to resolve import statements
+// Most users will probably want to use the DiskSourceTree implementation,
+// below.
+class LIBPROTOBUF_EXPORT SourceTree {
+ public:
+  inline SourceTree() {}
+  virtual ~SourceTree();
+
+  // Open the given file and return a stream that reads it, or NULL if not
+  // found.  The caller takes ownership of the returned object.  The filename
+  // must be a path relative to the root of the source tree and must not
+  // contain "." or ".." components.
+  virtual io::ZeroCopyInputStream* Open(const string& filename) = 0;
+
+  // If Open() returns NULL, calling this method immediately will return an
+  // description of the error.
+  // Subclasses should implement this method and return a meaningful value for
+  // better error reporting.
+  // TODO(xiaofeng): change this to a pure virtual function.
+  virtual string GetLastErrorMessage();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
+};
+
+// An implementation of SourceTree which loads files from locations on disk.
+// Multiple mappings can be set up to map locations in the DiskSourceTree to
+// locations in the physical filesystem.
+class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
+ public:
+  DiskSourceTree();
+  ~DiskSourceTree();
+
+  // Map a path on disk to a location in the SourceTree.  The path may be
+  // either a file or a directory.  If it is a directory, the entire tree
+  // under it will be mapped to the given virtual location.  To map a directory
+  // to the root of the source tree, pass an empty string for virtual_path.
+  //
+  // If multiple mapped paths apply when opening a file, they will be searched
+  // in order.  For example, if you do:
+  //   MapPath("bar", "foo/bar");
+  //   MapPath("", "baz");
+  // and then you do:
+  //   Open("bar/qux");
+  // the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux,
+  // returning the first one that opens successfuly.
+  //
+  // disk_path may be an absolute path or relative to the current directory,
+  // just like a path you'd pass to open().
+  void MapPath(const string& virtual_path, const string& disk_path);
+
+  // Return type for DiskFileToVirtualFile().
+  enum DiskFileToVirtualFileResult {
+    SUCCESS,
+    SHADOWED,
+    CANNOT_OPEN,
+    NO_MAPPING
+  };
+
+  // Given a path to a file on disk, find a virtual path mapping to that
+  // file.  The first mapping created with MapPath() whose disk_path contains
+  // the filename is used.  However, that virtual path may not actually be
+  // usable to open the given file.  Possible return values are:
+  // * SUCCESS: The mapping was found.  *virtual_file is filled in so that
+  //   calling Open(*virtual_file) will open the file named by disk_file.
+  // * SHADOWED: A mapping was found, but using Open() to open this virtual
+  //   path will end up returning some different file.  This is because some
+  //   other mapping with a higher precedence also matches this virtual path
+  //   and maps it to a different file that exists on disk.  *virtual_file
+  //   is filled in as it would be in the SUCCESS case.  *shadowing_disk_file
+  //   is filled in with the disk path of the file which would be opened if
+  //   you were to call Open(*virtual_file).
+  // * CANNOT_OPEN: The mapping was found and was not shadowed, but the
+  //   file specified cannot be opened.  When this value is returned,
+  //   errno will indicate the reason the file cannot be opened.  *virtual_file
+  //   will be set to the virtual path as in the SUCCESS case, even though
+  //   it is not useful.
+  // * NO_MAPPING: Indicates that no mapping was found which contains this
+  //   file.
+  DiskFileToVirtualFileResult
+    DiskFileToVirtualFile(const string& disk_file,
+                          string* virtual_file,
+                          string* shadowing_disk_file);
+
+  // Given a virtual path, find the path to the file on disk.
+  // Return true and update disk_file with the on-disk path if the file exists.
+  // Return false and leave disk_file untouched if the file doesn't exist.
+  bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file);
+
+  // implements SourceTree -------------------------------------------
+  virtual io::ZeroCopyInputStream* Open(const string& filename);
+
+  virtual string GetLastErrorMessage();
+
+ private:
+  struct Mapping {
+    string virtual_path;
+    string disk_path;
+
+    inline Mapping(const string& virtual_path_param,
+                   const string& disk_path_param)
+      : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
+  };
+  vector<Mapping> mappings_;
+  string last_error_message_;
+
+  // Like Open(), but returns the on-disk path in disk_file if disk_file is
+  // non-NULL and the file could be successfully opened.
+  io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file,
+                                           string* disk_file);
+
+  // Like Open() but given the actual on-disk path.
+  io::ZeroCopyInputStream* OpenDiskFile(const string& filename);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/importer_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer_unittest.cc
new file mode 100644
index 0000000..1b6e970
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/importer_unittest.cc
@@ -0,0 +1,523 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/importer.h>
+
+#include <google/protobuf/stubs/hash.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+bool FileExists(const string& path) {
+  return File::Exists(path);
+}
+
+#define EXPECT_SUBSTRING(needle, haystack) \
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, (needle), (haystack))
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+  string warning_text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+
+  void AddWarning(const string& filename, int line, int column,
+                  const string& message) {
+    strings::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+};
+
+// -------------------------------------------------------------------
+
+// A dummy implementation of SourceTree backed by a simple map.
+class MockSourceTree : public SourceTree {
+ public:
+  MockSourceTree() {}
+  ~MockSourceTree() {}
+
+  void AddFile(const string& name, const char* contents) {
+    files_[name] = contents;
+  }
+
+  // implements SourceTree -------------------------------------------
+  io::ZeroCopyInputStream* Open(const string& filename) {
+    const char* contents = FindPtrOrNull(files_, filename);
+    if (contents == NULL) {
+      return NULL;
+    } else {
+      return new io::ArrayInputStream(contents, strlen(contents));
+    }
+  }
+
+  string GetLastErrorMessage() {
+    return "File not found.";
+  }
+
+ private:
+  hash_map<string, const char*> files_;
+};
+
+// ===================================================================
+
+class ImporterTest : public testing::Test {
+ protected:
+  ImporterTest()
+    : importer_(&source_tree_, &error_collector_) {}
+
+  void AddFile(const string& filename, const char* text) {
+    source_tree_.AddFile(filename, text);
+  }
+
+  // Return the collected error text
+  string error() const { return error_collector_.text_; }
+  string warning() const { return error_collector_.warning_text_; }
+
+  MockErrorCollector error_collector_;
+  MockSourceTree source_tree_;
+  Importer importer_;
+};
+
+TEST_F(ImporterTest, Import) {
+  // Test normal importing.
+  AddFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  const FileDescriptor* file = importer_.Import("foo.proto");
+  EXPECT_EQ("", error_collector_.text_);
+  ASSERT_TRUE(file != NULL);
+
+  ASSERT_EQ(1, file->message_type_count());
+  EXPECT_EQ("Foo", file->message_type(0)->name());
+
+  // Importing again should return same object.
+  EXPECT_EQ(file, importer_.Import("foo.proto"));
+}
+
+TEST_F(ImporterTest, ImportNested) {
+  // Test that importing a file which imports another file works.
+  AddFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n"
+    "message Foo {\n"
+    "  optional Bar bar = 1;\n"
+    "}\n");
+  AddFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+
+  // Note that both files are actually parsed by the first call to Import()
+  // here, since foo.proto imports bar.proto.  The second call just returns
+  // the same ProtoFile for bar.proto which was constructed while importing
+  // foo.proto.  We test that this is the case below by checking that bar
+  // is among foo's dependencies (by pointer).
+  const FileDescriptor* foo = importer_.Import("foo.proto");
+  const FileDescriptor* bar = importer_.Import("bar.proto");
+  EXPECT_EQ("", error_collector_.text_);
+  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(bar != NULL);
+
+  // Check that foo's dependency is the same object as bar.
+  ASSERT_EQ(1, foo->dependency_count());
+  EXPECT_EQ(bar, foo->dependency(0));
+
+  // Check that foo properly cross-links bar.
+  ASSERT_EQ(1, foo->message_type_count());
+  ASSERT_EQ(1, bar->message_type_count());
+  ASSERT_EQ(1, foo->message_type(0)->field_count());
+  ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE,
+            foo->message_type(0)->field(0)->type());
+  EXPECT_EQ(bar->message_type(0),
+            foo->message_type(0)->field(0)->message_type());
+}
+
+TEST_F(ImporterTest, FileNotFound) {
+  // Error:  Parsing a file that doesn't exist.
+  EXPECT_TRUE(importer_.Import("foo.proto") == NULL);
+  EXPECT_EQ(
+    "foo.proto:-1:0: File not found.\n",
+    error_collector_.text_);
+}
+
+TEST_F(ImporterTest, ImportNotFound) {
+  // Error:  Importing a file that doesn't exist.
+  AddFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n");
+
+  EXPECT_TRUE(importer_.Import("foo.proto") == NULL);
+  EXPECT_EQ(
+    "bar.proto:-1:0: File not found.\n"
+    "foo.proto:-1:0: Import \"bar.proto\" was not found or had errors.\n",
+    error_collector_.text_);
+}
+
+TEST_F(ImporterTest, RecursiveImport) {
+  // Error:  Recursive import.
+  AddFile("recursive1.proto",
+    "syntax = \"proto2\";\n"
+    "import \"recursive2.proto\";\n");
+  AddFile("recursive2.proto",
+    "syntax = \"proto2\";\n"
+    "import \"recursive1.proto\";\n");
+
+  EXPECT_TRUE(importer_.Import("recursive1.proto") == NULL);
+  EXPECT_EQ(
+    "recursive1.proto:-1:0: File recursively imports itself: recursive1.proto "
+      "-> recursive2.proto -> recursive1.proto\n"
+    "recursive2.proto:-1:0: Import \"recursive1.proto\" was not found "
+      "or had errors.\n"
+    "recursive1.proto:-1:0: Import \"recursive2.proto\" was not found "
+      "or had errors.\n",
+    error_collector_.text_);
+}
+
+
+// ===================================================================
+
+class DiskSourceTreeTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_1");
+    dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_2");
+
+    for (int i = 0; i < dirnames_.size(); i++) {
+      if (FileExists(dirnames_[i])) {
+        File::DeleteRecursively(dirnames_[i], NULL, NULL);
+      }
+      GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777));
+    }
+  }
+
+  virtual void TearDown() {
+    for (int i = 0; i < dirnames_.size(); i++) {
+      if (FileExists(dirnames_[i])) {
+        File::DeleteRecursively(dirnames_[i], NULL, NULL);
+      }
+    }
+  }
+
+  void AddFile(const string& filename, const char* contents) {
+    GOOGLE_CHECK_OK(File::SetContents(filename, contents, true));
+  }
+
+  void AddSubdir(const string& dirname) {
+    GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777));
+  }
+
+  void ExpectFileContents(const string& filename,
+                          const char* expected_contents) {
+    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+
+    ASSERT_FALSE(input == NULL);
+
+    // Read all the data from the file.
+    string file_contents;
+    const void* data;
+    int size;
+    while (input->Next(&data, &size)) {
+      file_contents.append(reinterpret_cast<const char*>(data), size);
+    }
+
+    EXPECT_EQ(expected_contents, file_contents);
+  }
+
+  void ExpectCannotOpenFile(const string& filename,
+                            const string& error_message) {
+    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+    EXPECT_TRUE(input == NULL);
+    EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
+  }
+
+  DiskSourceTree source_tree_;
+
+  // Paths of two on-disk directories to use during the test.
+  vector<string> dirnames_;
+};
+
+TEST_F(DiskSourceTreeTest, MapRoot) {
+  // Test opening a file in a directory that is mapped to the root of the
+  // source tree.
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  source_tree_.MapPath("", dirnames_[0]);
+
+  ExpectFileContents("foo", "Hello World!");
+  ExpectCannotOpenFile("bar", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, MapDirectory) {
+  // Test opening a file in a directory that is mapped to somewhere other
+  // than the root of the source tree.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  source_tree_.MapPath("baz", dirnames_[0]);
+
+  ExpectFileContents("baz/foo", "Hello World!");
+  ExpectCannotOpenFile("baz/bar", "File not found.");
+  ExpectCannotOpenFile("foo", "File not found.");
+  ExpectCannotOpenFile("bar", "File not found.");
+
+  // Non-canonical file names should not work.
+  ExpectCannotOpenFile("baz//foo",
+                       "Backslashes, consecutive slashes, \".\", or \"..\" are "
+                       "not allowed in the virtual path");
+  ExpectCannotOpenFile("baz/../baz/foo",
+                       "Backslashes, consecutive slashes, \".\", or \"..\" are "
+                       "not allowed in the virtual path");
+  ExpectCannotOpenFile("baz/./foo",
+                       "Backslashes, consecutive slashes, \".\", or \"..\" are "
+                       "not allowed in the virtual path");
+  ExpectCannotOpenFile("baz/foo/", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, NoParent) {
+  // Test that we cannot open files in a parent of a mapped directory.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  AddSubdir(dirnames_[0] + "/bar");
+  AddFile(dirnames_[0] + "/bar/baz", "Blah.");
+  source_tree_.MapPath("", dirnames_[0] + "/bar");
+
+  ExpectFileContents("baz", "Blah.");
+  ExpectCannotOpenFile("../foo",
+                       "Backslashes, consecutive slashes, \".\", or \"..\" are "
+                       "not allowed in the virtual path");
+  ExpectCannotOpenFile("../bar/baz",
+                       "Backslashes, consecutive slashes, \".\", or \"..\" are "
+                       "not allowed in the virtual path");
+}
+
+TEST_F(DiskSourceTreeTest, MapFile) {
+  // Test opening a file that is mapped directly into the source tree.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  source_tree_.MapPath("foo", dirnames_[0] + "/foo");
+
+  ExpectFileContents("foo", "Hello World!");
+  ExpectCannotOpenFile("bar", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) {
+  // Test mapping and searching multiple directories.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+  AddFile(dirnames_[1] + "/bar", "Goodbye World!");
+  source_tree_.MapPath("", dirnames_[0]);
+  source_tree_.MapPath("", dirnames_[1]);
+
+  ExpectFileContents("foo", "Hello World!");
+  ExpectFileContents("bar", "Goodbye World!");
+  ExpectCannotOpenFile("baz", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) {
+  // Test that directories are always searched in order, even when a latter
+  // directory is more-specific than a former one.
+
+  // Create the "bar" directory so we can put a file in it.
+  GOOGLE_CHECK_OK(File::CreateDir(dirnames_[0] + "/bar", 0777));
+
+  // Add files and map paths.
+  AddFile(dirnames_[0] + "/bar/foo", "Hello World!");
+  AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+  source_tree_.MapPath("", dirnames_[0]);
+  source_tree_.MapPath("bar", dirnames_[1]);
+
+  // Check.
+  ExpectFileContents("bar/foo", "Hello World!");
+}
+
+TEST_F(DiskSourceTreeTest, DiskFileToVirtualFile) {
+  // Test DiskFileToVirtualFile.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+  source_tree_.MapPath("bar", dirnames_[0]);
+  source_tree_.MapPath("bar", dirnames_[1]);
+
+  string virtual_file;
+  string shadowing_disk_file;
+
+  EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+    source_tree_.DiskFileToVirtualFile(
+      "/foo", &virtual_file, &shadowing_disk_file));
+
+  EXPECT_EQ(DiskSourceTree::SHADOWED,
+    source_tree_.DiskFileToVirtualFile(
+      dirnames_[1] + "/foo", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("bar/foo", virtual_file);
+  EXPECT_EQ(dirnames_[0] + "/foo", shadowing_disk_file);
+
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      dirnames_[1] + "/baz", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("bar/baz", virtual_file);
+
+  EXPECT_EQ(DiskSourceTree::SUCCESS,
+    source_tree_.DiskFileToVirtualFile(
+      dirnames_[0] + "/foo", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("bar/foo", virtual_file);
+}
+
+TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) {
+  // Test handling of "..", ".", etc. in DiskFileToVirtualFile().
+
+  source_tree_.MapPath("dir1", "..");
+  source_tree_.MapPath("dir2", "../../foo");
+  source_tree_.MapPath("dir3", "./foo/bar/.");
+  source_tree_.MapPath("dir4", ".");
+  source_tree_.MapPath("", "/qux");
+  source_tree_.MapPath("dir5", "/quux/");
+
+  string virtual_file;
+  string shadowing_disk_file;
+
+  // "../.." should not be considered to be under "..".
+  EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+    source_tree_.DiskFileToVirtualFile(
+      "../../baz", &virtual_file, &shadowing_disk_file));
+
+  // "/foo" is not mapped (it should not be misintepreted as being under ".").
+  EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+    source_tree_.DiskFileToVirtualFile(
+      "/foo", &virtual_file, &shadowing_disk_file));
+
+#ifdef WIN32
+  // "C:\foo" is not mapped (it should not be misintepreted as being under ".").
+  EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+    source_tree_.DiskFileToVirtualFile(
+      "C:\\foo", &virtual_file, &shadowing_disk_file));
+#endif  // WIN32
+
+  // But "../baz" should be.
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "../baz", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("dir1/baz", virtual_file);
+
+  // "../../foo/baz" is under "../../foo".
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "../../foo/baz", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("dir2/baz", virtual_file);
+
+  // "foo/./bar/baz" is under "./foo/bar/.".
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "foo/bar/baz", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("dir3/baz", virtual_file);
+
+  // "bar" is under ".".
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "bar", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("dir4/bar", virtual_file);
+
+  // "/qux/baz" is under "/qux".
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "/qux/baz", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("baz", virtual_file);
+
+  // "/quux/bar" is under "/quux".
+  EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+    source_tree_.DiskFileToVirtualFile(
+      "/quux/bar", &virtual_file, &shadowing_disk_file));
+  EXPECT_EQ("dir5/bar", virtual_file);
+}
+
+TEST_F(DiskSourceTreeTest, VirtualFileToDiskFile) {
+  // Test VirtualFileToDiskFile.
+
+  AddFile(dirnames_[0] + "/foo", "Hello World!");
+  AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+  AddFile(dirnames_[1] + "/quux", "This file should not be hidden.");
+  source_tree_.MapPath("bar", dirnames_[0]);
+  source_tree_.MapPath("bar", dirnames_[1]);
+
+  // Existent files, shadowed and non-shadowed case.
+  string disk_file;
+  EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", &disk_file));
+  EXPECT_EQ(dirnames_[0] + "/foo", disk_file);
+  EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/quux", &disk_file));
+  EXPECT_EQ(dirnames_[1] + "/quux", disk_file);
+
+  // Nonexistent file in existent directory and vice versa.
+  string not_touched = "not touched";
+  EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("bar/baz", &not_touched));
+  EXPECT_EQ("not touched", not_touched);
+  EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", &not_touched));
+  EXPECT_EQ("not touched", not_touched);
+
+  // Accept NULL as output parameter.
+  EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", NULL));
+  EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", NULL));
+}
+
+}  // namespace
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.cc
new file mode 100644
index 0000000..0a11288
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.cc
@@ -0,0 +1,202 @@
+// 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.
+
+#include <google/protobuf/compiler/java/java_context.h>
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+Context::Context(const FileDescriptor* file)
+    : name_resolver_(new ClassNameResolver), enforce_lite_(false) {
+  InitializeFieldGeneratorInfo(file);
+}
+
+Context::~Context() {
+}
+
+ClassNameResolver* Context::GetNameResolver() {
+  return name_resolver_.get();
+}
+
+namespace {
+// Whether two fields have conflicting accessors (assuming name1 and name2
+// are different). name1 and name2 are field1 and field2's camel-case name
+// respectively.
+bool IsConflicting(const FieldDescriptor* field1, const string& name1,
+                   const FieldDescriptor* field2, const string& name2,
+                   string* info) {
+  if (field1->is_repeated()) {
+    if (field2->is_repeated()) {
+      // Both fields are repeated.
+      return false;
+    } else {
+      // field1 is repeated, and field2 is not.
+      if (name1 + "Count" == name2) {
+        *info = "both repeated field \"" + field1->name() + "\" and singular " +
+            "field \"" + field2->name() + "\" generates the method \"" +
+            "get" + name1 + "Count()\"";
+        return true;
+      }
+      if (name1 + "List" == name2) {
+        *info = "both repeated field \"" + field1->name() + "\" and singular " +
+            "field \"" + field2->name() + "\" generates the method \"" +
+            "get" + name1 + "List()\"";
+        return true;
+      }
+      // Well, there are obviously many more conflicting cases, but it probably
+      // doesn't worth the effort to exhaust all of them because they rarely
+      // happen and as we are continuing adding new methods/changing existing
+      // methods the number of different conflicting cases will keep growing.
+      // We can just add more cases here when they are found in the real world.
+      return false;
+    }
+  } else {
+    if (field2->is_repeated()) {
+      return IsConflicting(field2, name2, field1, name1, info);
+    } else {
+      // None of the two fields are repeated.
+      return false;
+    }
+  }
+}
+}  // namespace
+
+void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) {
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    InitializeFieldGeneratorInfoForMessage(file->message_type(i));
+  }
+}
+
+void Context::InitializeFieldGeneratorInfoForMessage(
+    const Descriptor* message) {
+  for (int i = 0; i < message->nested_type_count(); ++i) {
+    InitializeFieldGeneratorInfoForMessage(message->nested_type(i));
+  }
+  vector<const FieldDescriptor*> fields;
+  for (int i = 0; i < message->field_count(); ++i) {
+    fields.push_back(message->field(i));
+  }
+  InitializeFieldGeneratorInfoForFields(fields);
+
+  for (int i = 0; i < message->oneof_decl_count(); ++i) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    OneofGeneratorInfo info;
+    info.name = UnderscoresToCamelCase(oneof->name(), false);
+    info.capitalized_name = UnderscoresToCamelCase(oneof->name(), true);
+    oneof_generator_info_map_[oneof] = info;
+  }
+}
+
+void Context::InitializeFieldGeneratorInfoForFields(
+    const vector<const FieldDescriptor*>& fields) {
+  // Find out all fields that conflict with some other field in the same
+  // message.
+  vector<bool> is_conflict(fields.size());
+  vector<string> conflict_reason(fields.size());
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    const string& name = UnderscoresToCapitalizedCamelCase(field);
+    for (int j = i + 1; j < fields.size(); ++j) {
+      const FieldDescriptor* other = fields[j];
+      const string& other_name = UnderscoresToCapitalizedCamelCase(other);
+      if (name == other_name) {
+        is_conflict[i] = is_conflict[j] = true;
+        conflict_reason[i] = conflict_reason[j] =
+            "capitalized name of field \"" + field->name() +
+            "\" conflicts with field \"" + other->name() + "\"";
+      } else if (IsConflicting(field, name, other, other_name,
+                               &conflict_reason[j])) {
+        is_conflict[i] = is_conflict[j] = true;
+        conflict_reason[i] = conflict_reason[j];
+      }
+    }
+    if (is_conflict[i]) {
+      GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting "
+                   << "with another field: " << conflict_reason[i];
+    }
+  }
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    FieldGeneratorInfo info;
+    info.name = UnderscoresToCamelCase(field);
+    info.capitalized_name = UnderscoresToCapitalizedCamelCase(field);
+    // For fields conflicting with some other fields, we append the field
+    // number to their field names in generated code to avoid conflicts.
+    if (is_conflict[i]) {
+      info.name += SimpleItoa(field->number());
+      info.capitalized_name += SimpleItoa(field->number());
+      info.disambiguated_reason = conflict_reason[i];
+    }
+    field_generator_info_map_[field] = info;
+  }
+}
+
+const FieldGeneratorInfo* Context::GetFieldGeneratorInfo(
+    const FieldDescriptor* field) const {
+  const FieldGeneratorInfo* result =
+      FindOrNull(field_generator_info_map_, field);
+  if (result == NULL) {
+    GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: "
+               << field->full_name();
+  }
+  return result;
+}
+
+const OneofGeneratorInfo* Context::GetOneofGeneratorInfo(
+    const OneofDescriptor* oneof) const {
+  const OneofGeneratorInfo* result =
+      FindOrNull(oneof_generator_info_map_, oneof);
+  if (result == NULL) {
+    GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: "
+               << oneof->name();
+  }
+  return result;
+}
+
+// Does this message class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+bool Context::HasGeneratedMethods(const Descriptor* descriptor) const {
+  return enforce_lite_ || descriptor->file()->options().optimize_for() !=
+           FileOptions::CODE_SIZE;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.h
new file mode 100644
index 0000000..a480e45
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_context.h
@@ -0,0 +1,114 @@
+// 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_COMPILER_JAVA_CONTEXT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  class FileDescriptor;
+  class FieldDescriptor;
+  class OneofDescriptor;
+  class Descriptor;
+  class EnumDescriptor;
+  namespace compiler {
+    namespace java {
+      class ClassNameResolver;  // name_resolver.h
+    }
+  }
+}  // namespace protobuf
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+struct FieldGeneratorInfo;
+struct OneofGeneratorInfo;
+// A context object holds the information that is shared among all code
+// generators.
+class Context {
+ public:
+  explicit Context(const FileDescriptor* file);
+  ~Context();
+
+  // Get the name resolver associated with this context. The resolver
+  // can be used to map descriptors to Java class names.
+  ClassNameResolver* GetNameResolver();
+
+  // Get the FieldGeneratorInfo for a given field.
+  const FieldGeneratorInfo* GetFieldGeneratorInfo(
+      const FieldDescriptor* field) const;
+
+  // Get the OneofGeneratorInfo for a given oneof.
+  const OneofGeneratorInfo* GetOneofGeneratorInfo(
+      const OneofDescriptor* oneof) const;
+
+  // Enforces all the files (including transitive dependencies) to use
+  // LiteRuntime.
+  void SetEnforceLite(bool enforce_lite) {
+    enforce_lite_ = enforce_lite;
+  }
+
+  bool EnforceLite() const {
+    return enforce_lite_;
+  }
+
+  // Does this message class have generated parsing, serialization, and other
+  // standard methods for which reflection-based fallback implementations exist?
+  bool HasGeneratedMethods(const Descriptor* descriptor) const;
+
+ private:
+  void InitializeFieldGeneratorInfo(const FileDescriptor* file);
+  void InitializeFieldGeneratorInfoForMessage(const Descriptor* message);
+  void InitializeFieldGeneratorInfoForFields(
+      const vector<const FieldDescriptor*>& fields);
+
+  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
+  map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
+  map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
+  bool enforce_lite_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.cc
new file mode 100644
index 0000000..0b5caba
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -0,0 +1,233 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <vector>
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+string EscapeJavadoc(const string& input) {
+  string result;
+  result.reserve(input.size() * 2);
+
+  char prev = '*';
+
+  for (string::size_type i = 0; i < input.size(); i++) {
+    char c = input[i];
+    switch (c) {
+      case '*':
+        // Avoid "/*".
+        if (prev == '/') {
+          result.append("&#42;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '/':
+        // Avoid "*/".
+        if (prev == '*') {
+          result.append("&#47;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '@':
+        // '@' starts javadoc tags including the @deprecated tag, which will
+        // cause a compile-time error if inserted before a declaration that
+        // does not have a corresponding @Deprecated annotation.
+        result.append("&#64;");
+        break;
+      case '<':
+        // Avoid interpretation as HTML.
+        result.append("&lt;");
+        break;
+      case '>':
+        // Avoid interpretation as HTML.
+        result.append("&gt;");
+        break;
+      case '&':
+        // Avoid interpretation as HTML.
+        result.append("&amp;");
+        break;
+      case '\\':
+        // Java interprets Unicode escape sequences anywhere!
+        result.append("&#92;");
+        break;
+      default:
+        result.push_back(c);
+        break;
+    }
+
+    prev = c;
+  }
+
+  return result;
+}
+
+static void WriteDocCommentBodyForLocation(
+    io::Printer* printer, const SourceLocation& location) {
+  string comments = location.leading_comments.empty() ?
+      location.trailing_comments : location.leading_comments;
+  if (!comments.empty()) {
+    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
+    //   write it back as HTML, but this requires a Markdown parser.  For now
+    //   we just use <pre> to get fixed-width text formatting.
+
+    // If the comment itself contains block comment start or end markers,
+    // HTML-escape them so that they don't accidentally close the doc comment.
+    comments = EscapeJavadoc(comments);
+
+    vector<string> lines = Split(comments, "\n");
+    while (!lines.empty() && lines.back().empty()) {
+      lines.pop_back();
+    }
+
+    printer->Print(" * <pre>\n");
+    for (int i = 0; i < lines.size(); i++) {
+      // Most lines should start with a space.  Watch out for lines that start
+      // with a /, since putting that right after the leading asterisk will
+      // close the comment.
+      if (!lines[i].empty() && lines[i][0] == '/') {
+        printer->Print(" * $line$\n", "line", lines[i]);
+      } else {
+        printer->Print(" *$line$\n", "line", lines[i]);
+      }
+    }
+    printer->Print(
+        " * </pre>\n"
+        " *\n");
+  }
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(
+    io::Printer* printer, const DescriptorType* descriptor) {
+  SourceLocation location;
+  if (descriptor->GetSourceLocation(&location)) {
+    WriteDocCommentBodyForLocation(printer, location);
+  }
+}
+
+static string FirstLineOf(const string& value) {
+  string result = value;
+
+  string::size_type pos = result.find_first_of('\n');
+  if (pos != string::npos) {
+    result.erase(pos);
+  }
+
+  // If line ends in an opening brace, make it "{ ... }" so it looks nice.
+  if (!result.empty() && result[result.size() - 1] == '{') {
+    result.append(" ... }");
+  }
+
+  return result;
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, message);
+  printer->Print(
+    " * Protobuf type {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(message->full_name()));
+}
+
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
+  // In theory we should have slightly different comments for setters, getters,
+  // etc., but in practice everyone already knows the difference between these
+  // so it's redundant information.
+
+  // We start the comment with the main body based on the comments from the
+  // .proto file (if present). We then end with the field declaration, e.g.:
+  //   optional string foo = 5;
+  // If the field is a group, the debug string might end with {.
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, field);
+  printer->Print(
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
+  printer->Print(" */\n");
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, enum_);
+  printer->Print(
+    " * Protobuf enum {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(enum_->full_name()));
+}
+
+void WriteEnumValueDocComment(io::Printer* printer,
+                              const EnumValueDescriptor* value) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, value);
+  printer->Print(
+    " * <code>$def$</code>\n"
+    " */\n",
+    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+}
+
+void WriteServiceDocComment(io::Printer* printer,
+                            const ServiceDescriptor* service) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, service);
+  printer->Print(
+    " * Protobuf service {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(service->full_name()));
+}
+
+void WriteMethodDocComment(io::Printer* printer,
+                           const MethodDescriptor* method) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, method);
+  printer->Print(
+    " * <code>$def$</code>\n"
+    " */\n",
+    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.h
new file mode 100644
index 0000000..7d9535c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment.h
@@ -0,0 +1,69 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+void WriteEnumValueDocComment(io::Printer* printer,
+                              const EnumValueDescriptor* value);
+void WriteServiceDocComment(io::Printer* printer,
+                            const ServiceDescriptor* service);
+void WriteMethodDocComment(io::Printer* printer,
+                           const MethodDescriptor* method);
+
+// Exposed for testing only.
+LIBPROTOC_EXPORT string EscapeJavadoc(const string& input);
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
new file mode 100644
index 0000000..ae582ea
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -0,0 +1,67 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+TEST(JavaDocCommentTest, Escaping) {
+  EXPECT_EQ("foo /&#42; bar *&#47; baz", EscapeJavadoc("foo /* bar */ baz"));
+  EXPECT_EQ("foo /&#42;&#47; baz", EscapeJavadoc("foo /*/ baz"));
+  EXPECT_EQ("{&#64;foo}", EscapeJavadoc("{@foo}"));
+  EXPECT_EQ("&lt;i&gt;&amp;&lt;/i&gt;", EscapeJavadoc("<i>&</i>"));
+  EXPECT_EQ("foo&#92;u1234bar", EscapeJavadoc("foo\\u1234bar"));
+  EXPECT_EQ("&#64;deprecated", EscapeJavadoc("@deprecated"));
+}
+
+// TODO(kenton):  It's hard to write a robust test of the doc comments -- we
+//   can only really compare the output against a golden value, which is a
+//   fairly tedious and fragile testing strategy.  If we want to go that route,
+//   it probably makes sense to bite the bullet and write a test that compares
+//   the whole generated output for unittest.proto against a golden value, with
+//   a very simple script that can be run to regenerate it with the latest code.
+//   This would mean that updates to the golden file would have to be included
+//   in any change to the code generator, which would actually be fairly useful
+//   as it allows the reviewer to see clearly how the generated code is
+//   changing.
+
+}  // namespace
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.cc
new file mode 100644
index 0000000..947b80e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.cc
@@ -0,0 +1,395 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
+  if (descriptor->options().unknown_fields().field_count() > 0) return true;
+  for (int i = 0; i < descriptor->value_count(); ++i) {
+    const EnumValueDescriptor* value = descriptor->value(i);
+    if (value->options().unknown_fields().field_count() > 0) return true;
+  }
+  return false;
+}
+}  // namespace
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
+                             bool immutable_api,
+                             Context* context)
+  : descriptor_(descriptor), immutable_api_(immutable_api),
+    context_(context),
+    name_resolver_(context->GetNameResolver())  {
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    const EnumValueDescriptor* value = descriptor_->value(i);
+    const EnumValueDescriptor* canonical_value =
+      descriptor_->FindValueByNumber(value->number());
+
+    if (value == canonical_value) {
+      canonical_values_.push_back(value);
+    } else {
+      Alias alias;
+      alias.value = value;
+      alias.canonical_value = canonical_value;
+      aliases_.push_back(alias);
+    }
+  }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+  WriteEnumDocComment(printer, descriptor_);
+  printer->Print(
+    "public enum $classname$\n"
+    "    implements com.google.protobuf.ProtocolMessageEnum {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+
+  bool ordinal_is_index = true;
+  string index_text = "ordinal()";
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    if (canonical_values_[i]->index() != i) {
+      ordinal_is_index = false;
+      index_text = "index";
+      break;
+    }
+  }
+
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    map<string, string> vars;
+    vars["name"] = canonical_values_[i]->name();
+    vars["index"] = SimpleItoa(canonical_values_[i]->index());
+    vars["number"] = SimpleItoa(canonical_values_[i]->number());
+    WriteEnumValueDocComment(printer, canonical_values_[i]);
+    if (canonical_values_[i]->options().deprecated()) {
+      printer->Print("@java.lang.Deprecated\n");
+    }
+    if (ordinal_is_index) {
+      printer->Print(vars,
+        "$name$($number$),\n");
+    } else {
+      printer->Print(vars,
+        "$name$($index$, $number$),\n");
+    }
+  }
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    if (ordinal_is_index) {
+      printer->Print("UNRECOGNIZED(-1),\n");
+    } else {
+      printer->Print("UNRECOGNIZED(-1, -1),\n");
+    }
+  }
+
+  printer->Print(
+    ";\n"
+    "\n");
+
+  // -----------------------------------------------------------------
+
+  for (int i = 0; i < aliases_.size(); i++) {
+    map<string, string> vars;
+    vars["classname"] = descriptor_->name();
+    vars["name"] = aliases_[i].value->name();
+    vars["canonical_name"] = aliases_[i].canonical_value->name();
+    WriteEnumValueDocComment(printer, aliases_[i].value);
+    printer->Print(vars,
+      "public static final $classname$ $name$ = $canonical_name$;\n");
+  }
+
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    map<string, string> vars;
+    vars["name"] = descriptor_->value(i)->name();
+    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    WriteEnumValueDocComment(printer, descriptor_->value(i));
+    printer->Print(vars,
+      "public static final int $name$_VALUE = $number$;\n");
+  }
+  printer->Print("\n");
+
+  // -----------------------------------------------------------------
+
+  printer->Print(
+    "\n"
+    "public final int getNumber() {\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    if (ordinal_is_index) {
+      printer->Print(
+        "  if (this == UNRECOGNIZED) {\n"
+        "    throw new java.lang.IllegalArgumentException(\n"
+        "        \"Can't get the number of an unknown enum value.\");\n"
+        "  }\n");
+    } else {
+      printer->Print(
+        "  if (index == -1) {\n"
+        "    throw new java.lang.IllegalArgumentException(\n"
+        "        \"Can't get the number of an unknown enum value.\");\n"
+        "  }\n");
+    }
+  }
+  printer->Print(
+    "  return value;\n"
+    "}\n"
+    "\n"
+    "/**\n"
+    " * @deprecated Use {@link #forNumber(int)} instead.\n"
+    " */\n"
+    "@java.lang.Deprecated\n"
+    "public static $classname$ valueOf(int value) {\n"
+    "  return forNumber(value);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ forNumber(int value) {\n"
+    "  switch (value) {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    printer->Print(
+      "case $number$: return $name$;\n",
+      "name", canonical_values_[i]->name(),
+      "number", SimpleItoa(canonical_values_[i]->number()));
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+    "    default: return null;\n"
+    "  }\n"
+    "}\n"
+    "\n"
+    "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+    "    internalGetValueMap() {\n"
+    "  return internalValueMap;\n"
+    "}\n"
+    "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+    "    $classname$> internalValueMap =\n"
+    "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+    "        public $classname$ findValueByNumber(int number) {\n"
+    "          return $classname$.forNumber(number);\n"
+    "        }\n"
+    "      };\n"
+    "\n",
+    "classname", descriptor_->name());
+
+  // -----------------------------------------------------------------
+  // Reflection
+
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
+    printer->Print(
+      "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
+      "    getValueDescriptor() {\n"
+      "  return getDescriptor().getValues().get($index_text$);\n"
+      "}\n"
+      "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
+      "    getDescriptorForType() {\n"
+      "  return getDescriptor();\n"
+      "}\n"
+      "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
+      "    getDescriptor() {\n",
+      "index_text", index_text);
+
+    // TODO(kenton):  Cache statically?  Note that we can't access descriptors
+    //   at module init time because it wouldn't work with descriptor.proto, but
+    //   we can cache the value the first time getDescriptor() is called.
+    if (descriptor_->containing_type() == NULL) {
+      if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) {
+        printer->Print(
+          "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
+          "file", name_resolver_->GetClassName(descriptor_->file(),
+                                               immutable_api_),
+          "index", SimpleItoa(descriptor_->index()));
+      } else {
+        printer->Indent();
+        if (EnumHasCustomOptions(descriptor_)) {
+          // We need to load the immutable classes in order to parse custom
+          // options. However, since file level enums (no outer class) are
+          // shared by immutable code and mutable code, the immutable classes
+          // may not exist. So we try to use Java reflection to retrieve the
+          // descriptor from immutable classes.
+          printer->Print(
+            "try {\n"
+            "  java.lang.Class immutableFileClass =\n"
+            "      java.lang.Class.forName(\"$immutable_file_class_name$\");\n"
+            "  @java.lang.SuppressWarnings(\"unchecked\")\n"
+            "  java.lang.reflect.Method m =\n"
+            "      immutableFileClass.getMethod(\"getDescriptor\");\n"
+            "  com.google.protobuf.Descriptors.FileDescriptor file =\n"
+            "      (com.google.protobuf.Descriptors.FileDescriptor)\n"
+            "          m.invoke(immutableFileClass);\n"
+            "  return file.getEnumTypes().get($index$);\n"
+            "} catch (java.lang.Exception e) {\n"
+            // Immutable classes cannot be found. Proceed as if custom options
+            // don't exist.
+            "}\n",
+            "immutable_file_class_name",
+            name_resolver_->GetImmutableClassName(descriptor_->file()),
+            "index", SimpleItoa(descriptor_->index()));
+        }
+        printer->Print(
+          "return $immutable_package$.$descriptor_class$.$descriptor$\n"
+          "    .getEnumTypes().get($index$);\n",
+          "immutable_package", FileJavaPackage(descriptor_->file(), true),
+          "descriptor_class",
+          name_resolver_->GetDescriptorClassName(descriptor_->file()),
+          "descriptor", "getDescriptor()",
+          "index", SimpleItoa(descriptor_->index()));
+        printer->Outdent();
+      }
+    } else {
+      printer->Print(
+          "  return $parent$.$descriptor$.getEnumTypes().get($index$);\n",
+          "parent", name_resolver_->GetClassName(descriptor_->containing_type(),
+                                                 immutable_api_),
+          "descriptor", descriptor_->containing_type()->options()
+                        .no_standard_descriptor_accessor()
+                        ? "getDefaultInstance().getDescriptorForType()"
+                        : "getDescriptor()",
+          "index", SimpleItoa(descriptor_->index()));
+    }
+
+    printer->Print(
+      "}\n"
+      "\n"
+      "private static final $classname$[] VALUES = ",
+      "classname", descriptor_->name());
+
+    if (CanUseEnumValues()) {
+      // If the constants we are going to output are exactly the ones we
+      // have declared in the Java enum in the same order, then we can use
+      // the values() method that the Java compiler automatically generates
+      // for every enum.
+      printer->Print("values();\n");
+    } else {
+      printer->Print(
+        "{\n"
+        "  ");
+      for (int i = 0; i < descriptor_->value_count(); i++) {
+        printer->Print("$name$, ",
+          "name", descriptor_->value(i)->name());
+      }
+      printer->Print(
+          "\n"
+          "};\n");
+    }
+
+    printer->Print(
+      "\n"
+      "public static $classname$ valueOf(\n"
+      "    com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
+      "  if (desc.getType() != getDescriptor()) {\n"
+      "    throw new java.lang.IllegalArgumentException(\n"
+      "      \"EnumValueDescriptor is not for this type.\");\n"
+      "  }\n",
+      "classname", descriptor_->name());
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+        "  if (desc.getIndex() == -1) {\n"
+        "    return UNRECOGNIZED;\n"
+        "  }\n");
+    }
+    printer->Print(
+      "  return VALUES[desc.getIndex()];\n"
+      "}\n"
+      "\n");
+
+    if (!ordinal_is_index) {
+      printer->Print("private final int index;\n");
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  printer->Print(
+    "private final int value;\n\n");
+
+  if (ordinal_is_index) {
+    printer->Print(
+      "private $classname$(int value) {\n",
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "private $classname$(int index, int value) {\n",
+      "classname", descriptor_->name());
+  }
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite()) &&
+      !ordinal_is_index) {
+    printer->Print("  this.index = index;\n");
+  }
+  printer->Print(
+    "  this.value = value;\n"
+    "}\n");
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+bool EnumGenerator::CanUseEnumValues() {
+  if (canonical_values_.size() != descriptor_->value_count()) {
+    return false;
+  }
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.h
new file mode 100644
index 0000000..a0d91f5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum.h
@@ -0,0 +1,99 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumGenerator {
+ public:
+  explicit EnumGenerator(const EnumDescriptor* descriptor,
+                         bool immutable_api,
+                         Context* context);
+  ~EnumGenerator();
+
+  void Generate(io::Printer* printer);
+
+ private:
+  const EnumDescriptor* descriptor_;
+
+  // The proto language allows multiple enum constants to have the same numeric
+  // value.  Java, however, does not allow multiple enum constants to be
+  // considered equivalent.  We treat the first defined constant for any
+  // given numeric value as "canonical" and the rest as aliases of that
+  // canonical value.
+  vector<const EnumValueDescriptor*> canonical_values_;
+
+  struct Alias {
+    const EnumValueDescriptor* value;
+    const EnumValueDescriptor* canonical_value;
+  };
+  vector<Alias> aliases_;
+
+  bool immutable_api_;
+
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  bool CanUseEnumValues();
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.cc
new file mode 100644
index 0000000..3e54be3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -0,0 +1,962 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
+                      const FieldGeneratorInfo* info,
+                      ClassNameResolver* name_resolver,
+                      map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->enum_type());
+  (*variables)["mutable_type"] =
+      name_resolver->GetMutableClassName(descriptor->enum_type());
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_number"] = SimpleItoa(
+      descriptor->default_value_enum()->number());
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] = "onChanged();";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["set_has_field_bit_builder"] =
+        GenerateSetBit(builderBitIndex) + ";";
+    (*variables)["clear_has_field_bit_builder"] =
+        GenerateClearBit(builderBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["set_has_field_bit_builder"] = "";
+    (*variables)["clear_has_field_bit_builder"] = "";
+
+    (*variables)["is_field_present_message"] =
+        (*variables)["name"] + "_ != " +
+        (*variables)["default"] + ".getNumber()";
+  }
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+
+  if (SupportUnknownEnumValue(descriptor->file())) {
+    (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+  } else {
+    (*variables)["unknown"] = (*variables)["default"];
+  }
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableEnumFieldGenerator::
+ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
+                            int messageBitIndex,
+                            int builderBitIndex,
+                            Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex),
+    name_resolver_(context->GetNameResolver()) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+                   context->GetFieldGeneratorInfo(descriptor),
+                   name_resolver_, &variables_);
+}
+
+ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
+
+int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$int get$capitalized_name$Value();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private int $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  return $name$_;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
+    "  return result == null ? $unknown$ : result;\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private int $name$_ = $default_number$;\n");
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_builder$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  return $name$_;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "  $name$_ = value;\n"
+      "  $on_changed$\n"
+      "  return this;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
+    "  return result == null ? $unknown$ : result;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $set_has_field_bit_builder$\n"
+    "  $name$_ = value.getNumber();\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$\n"
+    "  $name$_ = $default_number$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default_number$;\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default_number$;\n"
+    "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "if (other.has$capitalized_name$()) {\n"
+      "  set$capitalized_name$(other.get$capitalized_name$());\n"
+      "}\n");
+  } else if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "if (other.$name$_ != $default_number$) {\n"
+      "  set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
+      "}\n");
+  } else {
+    GOOGLE_LOG(FATAL) << "Can't reach here.";
+  }
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+    "result.$name$_ = $name$_;\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = rawValue;\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  unknownFields.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  $set_has_field_bit_message$\n"
+      "  $name$_ = rawValue;\n"
+      "}\n");
+  }
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for enums
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.writeEnum($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSize($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && $name$_ == other.$name$_;\n");
+}
+
+void ImmutableEnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + $name$_;\n");
+}
+
+string ImmutableEnumFieldGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldGenerator::
+ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutableEnumFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldGenerator::
+~ImmutableEnumOneofFieldGenerator() {}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  if ($has_oneof_case_message$) {\n"
+      "    return (java.lang.Integer) $oneof_name$_;\n"
+      "  }\n"
+      "  return $default_number$;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
+    "    return result == null ? $unknown$ : result;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  if ($has_oneof_case_message$) {\n"
+      "    return ((java.lang.Integer) $oneof_name$_).intValue();\n"
+      "  }\n"
+      "  return $default_number$;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "  $set_oneof_case_message$;\n"
+      "  $oneof_name$_ = value;\n"
+      "  $on_changed$\n"
+      "  return this;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
+    "    return result == null ? $unknown$ : result;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value.getNumber();\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "    $on_changed$\n"
+    "  }\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  result.$oneof_name$_ = $oneof_name$_;\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
+  } else {
+    printer->Print(variables_,
+      "set$capitalized_name$(other.get$capitalized_name$());\n");
+  }
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = rawValue;\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  unknownFields.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  $set_oneof_case_message$;\n"
+      "  $oneof_name$_ = rawValue;\n"
+      "}\n");
+  }
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "result = result && get$capitalized_name$Value()\n"
+      "    == other.get$capitalized_name$Value();\n");
+  } else {
+    printer->Print(variables_,
+      "result = result && get$capitalized_name$()\n"
+      "    .equals(other.get$capitalized_name$());\n");
+  }
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "hash = (37 * hash) + $constant_name$;\n"
+      "hash = (53 * hash) + get$capitalized_name$Value();\n");
+  } else {
+    printer->Print(variables_,
+      "hash = (37 * hash) + $constant_name$;\n"
+      "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+  }
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldGenerator::
+RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
+                                    int messageBitIndex,
+                                    int builderBitIndex,
+                                    Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+                   context->GetFieldGeneratorInfo(descriptor),
+                   name_resolver_, &variables_);
+}
+
+RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
+
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList();\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$int get$capitalized_name$Value(int index);\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private java.util.List<java.lang.Integer> $name$_;\n"
+    "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
+    "    java.lang.Integer, $type$> $name$_converter_ =\n"
+    "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+    "            java.lang.Integer, $type$>() {\n"
+    "          public $type$ convert(java.lang.Integer from) {\n"
+    "            $type$ result = $type$.forNumber(from);\n"
+    "            return result == null ? $unknown$ : result;\n"
+    "          }\n"
+    "        };\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return new com.google.protobuf.Internal.ListAdapter<\n"
+    "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_converter_.convert($name$_.get(index));\n"
+    "}\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList() {\n"
+      "  return $name$_;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "  return $name$_.get(index);\n"
+      "}\n");
+  }
+
+  if (descriptor_->is_packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize;\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<java.lang.Integer> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    // Note:  We return an unmodifiable list because otherwise the caller
+    //   could hold on to the returned list and modify it after the message
+    //   has been built, thus mutating the message which is supposed to be
+    //   immutable.
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return new com.google.protobuf.Internal.ListAdapter<\n"
+    "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_converter_.convert($name$_.get(index));\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value.getNumber());\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value.getNumber());\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  for ($type$ value : values) {\n"
+    "    $name$_.add(value.getNumber());\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = java.util.Collections.emptyList();\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList() {\n"
+      "  return java.util.Collections.unmodifiableList($name$_);\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "  return $name$_.get(index);\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "    int index, int value) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  $name$_.set(index, value);\n"
+      "  $on_changed$\n"
+      "  return this;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  $name$_.add(value);\n"
+      "  $on_changed$\n"
+      "  return this;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "    java.lang.Iterable<java.lang.Integer> values) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  for (int value : values) {\n"
+      "    $name$_.add(value);\n"
+      "  }\n"
+      "  $on_changed$\n"
+      "  return this;\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
+  printer->Print(variables_,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  // Read and store the enum
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "if (!$get_mutable_bit_parser$) {\n"
+      "  $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+      "  $set_mutable_bit_parser$;\n"
+      "}\n"
+      "$name$_.add(rawValue);\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+        "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  unknownFields.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  if (!$get_mutable_bit_parser$) {\n"
+      "    $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+      "    $set_mutable_bit_parser$;\n"
+      "  }\n"
+      "  $name$_.add(rawValue);\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  // Wrap GenerateParsingCode's contents with a while loop.
+
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int oldLimit = input.pushLimit(length);\n"
+    "while(input.getBytesUntilLimit() > 0) {\n");
+  printer->Indent();
+
+  GenerateParsingCode(printer);
+
+  printer->Outdent();
+  printer->Print(variables_,
+    "}\n"
+    "input.popLimit(oldLimit);\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnumNoTag($name$_.get(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnum($number$, $name$_.get(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSizeNoTag($name$_.get(i));\n"
+    "}\n");
+  printer->Print(
+    "size += dataSize;\n");
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "    .computeRawVarint32Size(dataSize);\n"
+      "}");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * $name$_.size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + $name$_.hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.h
new file mode 100644
index 0000000..b8ff734
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field.h
@@ -0,0 +1,160 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;            // context.h
+      class ClassNameResolver;  // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit ImmutableEnumFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableEnumFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator);
+};
+
+class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
+ public:
+  ImmutableEnumOneofFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableEnumOneofFieldGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
+};
+
+class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit RepeatedImmutableEnumFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableEnumFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.cc
new file mode 100644
index 0000000..908d6db
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -0,0 +1,960 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
+                      const FieldGeneratorInfo* info,
+                      ClassNameResolver* name_resolver,
+                      map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->enum_type());
+  (*variables)["mutable_type"] =
+      name_resolver->GetMutableClassName(descriptor->enum_type());
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_number"] = SimpleItoa(
+      descriptor->default_value_enum()->number());
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["clear_has_field_bit_message"] =
+        GenerateClearBit(messageBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["clear_has_field_bit_message"] = "";
+
+    (*variables)["is_field_present_message"] =
+        (*variables)["name"] + "_ != " +
+        (*variables)["default"] + ".getNumber()";
+  }
+
+  // For repeated builders, the underlying list tracks mutability state.
+  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+
+  if (SupportUnknownEnumValue(descriptor->file())) {
+    (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+  } else {
+    (*variables)["unknown"] = (*variables)["default"];
+  }
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableEnumFieldLiteGenerator::
+ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+                            int messageBitIndex,
+                            int builderBitIndex,
+                            Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex),
+    name_resolver_(context->GetNameResolver()) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+                   context->GetFieldGeneratorInfo(descriptor),
+                   name_resolver_, &variables_);
+}
+
+ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$int get$capitalized_name$Value();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private int $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  return $name$_;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
+    "  return result == null ? $unknown$ : result;\n"
+    "}\n");
+
+  // Generate private setters for the builder to proxy into.
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "private void set$capitalized_name$Value(int value) {\n"
+      "  $set_has_field_bit_message$"
+      "  $name$_ = value;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $set_has_field_bit_message$\n"
+    "  $name$_ = value.getNumber();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_message$\n"
+    "  $name$_ = $default_number$;\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  return instance.get$capitalized_name$Value();\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "  copyOnWrite();\n"
+      "  instance.set$capitalized_name$Value(value);\n"
+      "  return this;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default_number$;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
+  } else if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_,"
+      "    other.$name$_ != $default_number$, other.$name$_);\n");
+  } else {
+    GOOGLE_LOG(FATAL) << "Can't reach here.";
+  }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  // noop for scalars
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = rawValue;\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  super.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  $set_has_field_bit_message$\n"
+      "  $name$_ = rawValue;\n"
+      "}\n");
+  }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.writeEnum($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSize($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && $name$_ == other.$name$_;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + $name$_;\n");
+}
+
+string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldLiteGenerator::
+ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutableEnumFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldLiteGenerator::
+~ImmutableEnumOneofFieldLiteGenerator() {}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  if ($has_oneof_case_message$) {\n"
+      "    return (java.lang.Integer) $oneof_name$_;\n"
+      "  }\n"
+      "  return $default_number$;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
+    "    return result == null ? $unknown$ : result;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+
+  // Generate private setters for the builder to proxy into.
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "private void set$capitalized_name$Value(int value) {\n"
+      "  $set_oneof_case_message$;\n"
+      "  $oneof_name$_ = value;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value.getNumber();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "  return instance.get$capitalized_name$Value();\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "  copyOnWrite();\n"
+      "  instance.set$capitalized_name$Value(value);\n"
+      "  return this;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$oneof_name$_ = visitor.visitOneofInt(\n"
+    "   $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = rawValue;\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  super.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  $set_oneof_case_message$;\n"
+      "  $oneof_name$_ = rawValue;\n"
+      "}\n");
+  }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "result = result && get$capitalized_name$Value()\n"
+      "    == other.get$capitalized_name$Value();\n");
+  } else {
+    printer->Print(variables_,
+      "result = result && get$capitalized_name$()\n"
+      "    .equals(other.get$capitalized_name$());\n");
+  }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "hash = (37 * hash) + $constant_name$;\n"
+      "hash = (53 * hash) + get$capitalized_name$Value();\n");
+  } else {
+    printer->Print(variables_,
+      "hash = (37 * hash) + $constant_name$;\n"
+      "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+  }
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldLiteGenerator::
+RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                    int messageBitIndex,
+                                    int builderBitIndex,
+                                    Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+                   context->GetFieldGeneratorInfo(descriptor),
+                   name_resolver_, &variables_);
+}
+
+RepeatedImmutableEnumFieldLiteGenerator::
+~RepeatedImmutableEnumFieldLiteGenerator() {}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList();\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$int get$capitalized_name$Value(int index);\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.Internal.IntList $name$_;\n"
+    "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
+    "    java.lang.Integer, $type$> $name$_converter_ =\n"
+    "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+    "            java.lang.Integer, $type$>() {\n"
+    "          public $type$ convert(java.lang.Integer from) {\n"
+    "            $type$ result = $type$.forNumber(from);\n"
+    "            return result == null ? $unknown$ : result;\n"
+    "          }\n"
+    "        };\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return new com.google.protobuf.Internal.ListAdapter<\n"
+    "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_converter_.convert($name$_.getInt(index));\n"
+    "}\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList() {\n"
+      "  return $name$_;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "  return $name$_.getInt(index);\n"
+      "}\n");
+  }
+
+  if (descriptor_->options().packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize;\n");
+  }
+
+  // Generate private setters for the builder to proxy into.
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$is_mutable$) {\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.setInt(index, value.getNumber());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.addInt(value.getNumber());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  for ($type$ value : values) {\n"
+    "    $name$_.addInt(value.getNumber());\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_ = emptyIntList();\n"
+    "}\n");
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "private void set$capitalized_name$Value(\n"
+      "    int index, int value) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  $name$_.setInt(index, value);\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "private void add$capitalized_name$Value(int value) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  $name$_.addInt(value);\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "private void addAll$capitalized_name$Value(\n"
+      "    java.lang.Iterable<java.lang.Integer> values) {\n"
+      "  ensure$capitalized_name$IsMutable();\n"
+      "  for (int value : values) {\n"
+      "    $name$_.addInt(value);\n"
+      "  }\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return instance.get$capitalized_name$List();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return instance.get$capitalized_name$Count();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return instance.get$capitalized_name$(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  copyOnWrite();\n"
+    "  instance.addAll$capitalized_name$(values);"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public java.util.List<java.lang.Integer>\n"
+      "get$capitalized_name$ValueList() {\n"
+      "  return java.util.Collections.unmodifiableList(\n"
+      "      instance.get$capitalized_name$ValueList());\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "  return instance.get$capitalized_name$Value(index);\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "    int index, int value) {\n"
+      "  copyOnWrite();\n"
+      "  instance.set$capitalized_name$Value(index, value);\n"
+      "  return this;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "  instance.add$capitalized_name$Value(value);\n"
+      "  return this;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "    java.lang.Iterable<java.lang.Integer> values) {\n"
+      "  copyOnWrite();\n"
+      "  instance.addAll$capitalized_name$Value(values);\n"
+      "  return this;\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = emptyIntList();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_= visitor.visitIntList($name$_, other.$name$_);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  // Read and store the enum
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_.addInt(input.readEnum());\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      // We store the unknown value in unknown fields.
+      "  super.mergeVarintField($number$, rawValue);\n"
+      "} else {\n"
+      "  $name$_.addInt(rawValue);\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int oldLimit = input.pushLimit(length);\n"
+    "while(input.getBytesUntilLimit() > 0) {\n");
+  printer->Indent();
+
+  // Read and store the enum
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_.addInt(input.readEnum());\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      // We store the unknown value in unknown fields.
+      "  super.mergeVarintField($number$, rawValue);\n"
+      "} else {\n"
+      "  $name$_.addInt(rawValue);\n"
+      "}\n");
+  }
+
+  printer->Outdent();
+  printer->Print(variables_,
+    "}\n"
+    "input.popLimit(oldLimit);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_mutable$) {\n"
+    "  $name$_.makeImmutable();\n"
+    "}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnumNoTag($name$_.getInt(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnum($number$, $name$_.getInt(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += com.google.protobuf.CodedOutputStream\n"
+    "    .computeEnumSizeNoTag($name$_.getInt(i));\n"
+    "}\n");
+  printer->Print(
+    "size += dataSize;\n");
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "    .computeRawVarint32Size(dataSize);\n"
+      "}");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * $name$_.size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + $name$_.hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.h
new file mode 100644
index 0000000..9201b8d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -0,0 +1,159 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;            // context.h
+      class ClassNameResolver;  // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+  explicit ImmutableEnumFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableEnumFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
+};
+
+class ImmutableEnumOneofFieldLiteGenerator
+    : public ImmutableEnumFieldLiteGenerator {
+ public:
+  ImmutableEnumOneofFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableEnumOneofFieldLiteGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableEnumFieldLiteGenerator
+    : public ImmutableFieldLiteGenerator {
+ public:
+  explicit RepeatedImmutableEnumFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableEnumFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.cc
new file mode 100644
index 0000000..c22da8d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -0,0 +1,218 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
+  if (descriptor->options().unknown_fields().field_count() > 0) return true;
+  for (int i = 0; i < descriptor->value_count(); ++i) {
+    const EnumValueDescriptor* value = descriptor->value(i);
+    if (value->options().unknown_fields().field_count() > 0) return true;
+  }
+  return false;
+}
+}  // namespace
+
+EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor,
+                             bool immutable_api,
+                             Context* context)
+  : descriptor_(descriptor), immutable_api_(immutable_api),
+    name_resolver_(context->GetNameResolver())  {
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    const EnumValueDescriptor* value = descriptor_->value(i);
+    const EnumValueDescriptor* canonical_value =
+      descriptor_->FindValueByNumber(value->number());
+
+    if (value == canonical_value) {
+      canonical_values_.push_back(value);
+    } else {
+      Alias alias;
+      alias.value = value;
+      alias.canonical_value = canonical_value;
+      aliases_.push_back(alias);
+    }
+  }
+}
+
+EnumLiteGenerator::~EnumLiteGenerator() {}
+
+void EnumLiteGenerator::Generate(io::Printer* printer) {
+  WriteEnumDocComment(printer, descriptor_);
+  printer->Print(
+    "public enum $classname$\n"
+    "    implements com.google.protobuf.Internal.EnumLite {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    map<string, string> vars;
+    vars["name"] = canonical_values_[i]->name();
+    vars["number"] = SimpleItoa(canonical_values_[i]->number());
+    WriteEnumValueDocComment(printer, canonical_values_[i]);
+    if (canonical_values_[i]->options().deprecated()) {
+      printer->Print("@java.lang.Deprecated\n");
+    }
+    printer->Print(vars,
+      "$name$($number$),\n");
+  }
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print("UNRECOGNIZED(-1),\n");
+  }
+
+  printer->Print(
+    ";\n"
+    "\n");
+
+  // -----------------------------------------------------------------
+
+  for (int i = 0; i < aliases_.size(); i++) {
+    map<string, string> vars;
+    vars["classname"] = descriptor_->name();
+    vars["name"] = aliases_[i].value->name();
+    vars["canonical_name"] = aliases_[i].canonical_value->name();
+    WriteEnumValueDocComment(printer, aliases_[i].value);
+    printer->Print(vars,
+      "public static final $classname$ $name$ = $canonical_name$;\n");
+  }
+
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    map<string, string> vars;
+    vars["name"] = descriptor_->value(i)->name();
+    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    WriteEnumValueDocComment(printer, descriptor_->value(i));
+    printer->Print(vars,
+      "public static final int $name$_VALUE = $number$;\n");
+  }
+  printer->Print("\n");
+
+  // -----------------------------------------------------------------
+
+  printer->Print(
+    "\n"
+    "public final int getNumber() {\n"
+    "  return value;\n"
+    "}\n"
+    "\n"
+    "/**\n"
+    " * @deprecated Use {@link #forNumber(int)} instead.\n"
+    " */\n"
+    "@java.lang.Deprecated\n"
+    "public static $classname$ valueOf(int value) {\n"
+    "  return forNumber(value);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ forNumber(int value) {\n"
+    "  switch (value) {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    printer->Print(
+      "case $number$: return $name$;\n",
+      "name", canonical_values_[i]->name(),
+      "number", SimpleItoa(canonical_values_[i]->number()));
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+    "    default: return null;\n"
+    "  }\n"
+    "}\n"
+    "\n"
+    "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+    "    internalGetValueMap() {\n"
+    "  return internalValueMap;\n"
+    "}\n"
+    "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+    "    $classname$> internalValueMap =\n"
+    "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+    "        public $classname$ findValueByNumber(int number) {\n"
+    "          return $classname$.forNumber(number);\n"
+    "        }\n"
+    "      };\n"
+    "\n",
+    "classname", descriptor_->name());
+
+  printer->Print(
+    "private final int value;\n\n"
+    "private $classname$(int value) {\n",
+    "classname", descriptor_->name());
+  printer->Print(
+    "  this.value = value;\n"
+    "}\n");
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+bool EnumLiteGenerator::CanUseEnumValues() {
+  if (canonical_values_.size() != descriptor_->value_count()) {
+    return false;
+  }
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.h
new file mode 100644
index 0000000..ee2f5f7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_enum_lite.h
@@ -0,0 +1,99 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumLiteGenerator {
+ public:
+  explicit EnumLiteGenerator(const EnumDescriptor* descriptor,
+                         bool immutable_api,
+                         Context* context);
+  ~EnumLiteGenerator();
+
+  void Generate(io::Printer* printer);
+
+ private:
+  const EnumDescriptor* descriptor_;
+
+  // The proto language allows multiple enum constants to have the same numeric
+  // value.  Java, however, does not allow multiple enum constants to be
+  // considered equivalent.  We treat the first defined constant for any
+  // given numeric value as "canonical" and the rest as aliases of that
+  // canonical value.
+  vector<const EnumValueDescriptor*> canonical_values_;
+
+  struct Alias {
+    const EnumValueDescriptor* value;
+    const EnumValueDescriptor* canonical_value;
+  };
+  vector<Alias> aliases_;
+
+  bool immutable_api_;
+
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  bool CanUseEnumValues();
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.cc
new file mode 100644
index 0000000..46b5faa
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.cc
@@ -0,0 +1,174 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_extension.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionGenerator::ImmutableExtensionGenerator(
+    const FieldDescriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  if (descriptor_->extension_scope() != NULL) {
+    scope_ = name_resolver_->GetImmutableClassName(
+        descriptor_->extension_scope());
+  } else {
+    scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+  }
+}
+
+ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {}
+
+// Initializes the vars referenced in the generated code templates.
+void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor,
+                                          const string& scope,
+                                          bool immutable,
+                                          ClassNameResolver* name_resolver,
+                                          map<string, string>* vars_pointer) {
+  map<string, string> &vars = *vars_pointer;
+  vars["scope"] = scope;
+  vars["name"] = UnderscoresToCamelCase(descriptor);
+  vars["containing_type"] =
+      name_resolver->GetClassName(descriptor->containing_type(), immutable);
+  vars["number"] = SimpleItoa(descriptor->number());
+  vars["constant_name"] = FieldConstantName(descriptor);
+  vars["index"] = SimpleItoa(descriptor->index());
+  vars["default"] = descriptor->is_repeated() ?
+      "" : DefaultValue(descriptor, immutable, name_resolver);
+  vars["type_constant"] = FieldTypeName(GetType(descriptor));
+  vars["packed"] = descriptor->options().packed() ? "true" : "false";
+  vars["enum_map"] = "null";
+  vars["prototype"] = "null";
+
+  JavaType java_type = GetJavaType(descriptor);
+  string singular_type;
+  switch (java_type) {
+    case JAVATYPE_MESSAGE:
+      singular_type = name_resolver->GetClassName(descriptor->message_type(),
+                                                   immutable);
+      vars["prototype"] = singular_type + ".getDefaultInstance()";
+      break;
+    case JAVATYPE_ENUM:
+      singular_type = name_resolver->GetClassName(descriptor->enum_type(),
+                                                   immutable);
+      vars["enum_map"] = singular_type + ".internalGetValueMap()";
+      break;
+    case JAVATYPE_STRING:
+      singular_type = "java.lang.String";
+      break;
+    case JAVATYPE_BYTES:
+      singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]";
+      break;
+    default:
+      singular_type = BoxedPrimitiveTypeName(java_type);
+      break;
+  }
+  vars["type"] = descriptor->is_repeated() ?
+      "java.util.List<" + singular_type + ">" : singular_type;
+  vars["singular_type"] = singular_type;
+}
+
+void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  const bool kUseImmutableNames = true;
+  InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+                   &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  if (descriptor_->extension_scope() == NULL) {
+    // Non-nested
+    printer->Print(
+        vars,
+        "public static final\n"
+        "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+        "    $containing_type$,\n"
+        "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+        "        .newFileScopedGeneratedExtension(\n"
+        "      $singular_type$.class,\n"
+        "      $prototype$);\n");
+  } else {
+    // Nested
+    printer->Print(
+        vars,
+        "public static final\n"
+        "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+        "    $containing_type$,\n"
+        "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+        "        .newMessageScopedGeneratedExtension(\n"
+        "      $scope$.getDefaultInstance(),\n"
+        "      $index$,\n"
+        "      $singular_type$.class,\n"
+        "      $prototype$);\n");
+  }
+}
+
+int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  int bytecode_estimate = 0;
+  if (descriptor_->extension_scope() == NULL) {
+    // Only applies to non-nested extensions.
+    printer->Print(
+        "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
+        "name", UnderscoresToCamelCase(descriptor_),
+        "index", SimpleItoa(descriptor_->index()));
+    bytecode_estimate += 21;
+  }
+  return bytecode_estimate;
+}
+
+int ImmutableExtensionGenerator::GenerateRegistrationCode(
+    io::Printer* printer) {
+  printer->Print(
+    "registry.add($scope$.$name$);\n",
+    "scope", scope_,
+    "name", UnderscoresToCamelCase(descriptor_));
+  return 7;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.h
new file mode 100644
index 0000000..bdd4226
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension.h
@@ -0,0 +1,113 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  class FieldDescriptor;       // descriptor.h
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for an extension, which may be within the scope of some
+// message or may be at file scope.  This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ExtensionGenerator {
+ public:
+  explicit ExtensionGenerator() {}
+  virtual ~ExtensionGenerator() {}
+
+  virtual void Generate(io::Printer* printer) = 0;
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateRegistrationCode(io::Printer* printer) = 0;
+
+ protected:
+  static void InitTemplateVars(const FieldDescriptor* descriptor,
+                               const string& scope,
+                               bool immutable,
+                               ClassNameResolver* name_resolver,
+                               map<string, string>* vars_pointer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+class ImmutableExtensionGenerator : public ExtensionGenerator {
+ public:
+  explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor,
+                                       Context* context);
+  virtual ~ImmutableExtensionGenerator();
+
+  virtual void Generate(io::Printer* printer);
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+  virtual int GenerateRegistrationCode(io::Printer* printer);
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  string scope_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.cc
new file mode 100644
index 0000000..23261ba
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.cc
@@ -0,0 +1,118 @@
+// 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.
+
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
+    const FieldDescriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  if (descriptor_->extension_scope() != NULL) {
+    scope_ = name_resolver_->GetImmutableClassName(
+        descriptor_->extension_scope());
+  } else {
+    scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+  }
+}
+
+ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {}
+
+void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  const bool kUseImmutableNames = true;
+  InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+                   &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  if (descriptor_->is_repeated()) {
+    printer->Print(
+        vars,
+        "public static final\n"
+        "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+        "    $containing_type$,\n"
+        "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+        "        .newRepeatedGeneratedExtension(\n"
+        "      $containing_type$.getDefaultInstance(),\n"
+        "      $prototype$,\n"
+        "      $enum_map$,\n"
+        "      $number$,\n"
+        "      com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+        "      $packed$,\n"
+        "      $singular_type$.class);\n");
+  } else {
+    printer->Print(
+        vars,
+        "public static final\n"
+        "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+        "    $containing_type$,\n"
+        "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+        "        .newSingularGeneratedExtension(\n"
+        "      $containing_type$.getDefaultInstance(),\n"
+        "      $default$,\n"
+        "      $prototype$,\n"
+        "      $enum_map$,\n"
+        "      $number$,\n"
+        "      com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+        "      $singular_type$.class);\n");
+  }
+}
+
+int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  return 0;
+}
+
+int ImmutableExtensionLiteGenerator::GenerateRegistrationCode(
+    io::Printer* printer) {
+  printer->Print(
+    "registry.add($scope$.$name$);\n",
+    "scope", scope_,
+    "name", UnderscoresToCamelCase(descriptor_));
+  return 7;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.h
new file mode 100644
index 0000000..4cd49bd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_extension_lite.h
@@ -0,0 +1,76 @@
+// 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_COMPILER_JAVA_EXTENSION_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for a lite extension, which may be within the scope of some
+// message or may be at file scope.  This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ImmutableExtensionLiteGenerator : public ExtensionGenerator {
+ public:
+  explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor,
+                                           Context* context);
+  virtual ~ImmutableExtensionLiteGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateRegistrationCode(io::Printer* printer);
+
+ private:
+  const FieldDescriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  string scope_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.cc
new file mode 100644
index 0000000..3c7bc5c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.cc
@@ -0,0 +1,332 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_map_field.h>
+#include <google/protobuf/compiler/java/java_map_field_lite.h>
+#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
+#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+ImmutableFieldGenerator* MakeImmutableGenerator(
+    const FieldDescriptor* field, int messageBitIndex, int builderBitIndex,
+    Context* context) {
+  if (field->is_repeated()) {
+    switch (GetJavaType(field)) {
+      case JAVATYPE_MESSAGE:
+        if (IsMapEntry(field->message_type())) {
+          return new ImmutableMapFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        } else {
+          if (IsLazy(field, context->EnforceLite())) {
+            return new RepeatedImmutableLazyMessageFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new RepeatedImmutableMessageFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        }
+      case JAVATYPE_ENUM:
+        return new RepeatedImmutableEnumFieldGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+      case JAVATYPE_STRING:
+        return new RepeatedImmutableStringFieldGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+      default:
+        return new RepeatedImmutablePrimitiveFieldGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+    }
+  } else {
+    if (field->containing_oneof()) {
+      switch (GetJavaType(field)) {
+        case JAVATYPE_MESSAGE:
+          if (IsLazy(field, context->EnforceLite())) {
+            return new ImmutableLazyMessageOneofFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new ImmutableMessageOneofFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        case JAVATYPE_ENUM:
+          return new ImmutableEnumOneofFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        case JAVATYPE_STRING:
+          return new ImmutableStringOneofFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        default:
+          return new ImmutablePrimitiveOneofFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+      }
+    } else {
+      switch (GetJavaType(field)) {
+        case JAVATYPE_MESSAGE:
+          if (IsLazy(field, context->EnforceLite())) {
+            return new ImmutableLazyMessageFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new ImmutableMessageFieldGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        case JAVATYPE_ENUM:
+          return new ImmutableEnumFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        case JAVATYPE_STRING:
+          return new ImmutableStringFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        default:
+          return new ImmutablePrimitiveFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+      }
+    }
+  }
+}
+
+ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
+    const FieldDescriptor* field, int messageBitIndex, int builderBitIndex,
+    Context* context) {
+  if (field->is_repeated()) {
+    switch (GetJavaType(field)) {
+      case JAVATYPE_MESSAGE:
+        if (IsMapEntry(field->message_type())) {
+          return new ImmutableMapFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        } else {
+          if (IsLazy(field, context->EnforceLite())) {
+            return new RepeatedImmutableLazyMessageFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new RepeatedImmutableMessageFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        }
+      case JAVATYPE_ENUM:
+        return new RepeatedImmutableEnumFieldLiteGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+      case JAVATYPE_STRING:
+        return new RepeatedImmutableStringFieldLiteGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+      default:
+        return new RepeatedImmutablePrimitiveFieldLiteGenerator(
+            field, messageBitIndex, builderBitIndex, context);
+    }
+  } else {
+    if (field->containing_oneof()) {
+      switch (GetJavaType(field)) {
+        case JAVATYPE_MESSAGE:
+          if (IsLazy(field, context->EnforceLite())) {
+            return new ImmutableLazyMessageOneofFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new ImmutableMessageOneofFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        case JAVATYPE_ENUM:
+          return new ImmutableEnumOneofFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        case JAVATYPE_STRING:
+          return new ImmutableStringOneofFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        default:
+          return new ImmutablePrimitiveOneofFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+      }
+    } else {
+      switch (GetJavaType(field)) {
+        case JAVATYPE_MESSAGE:
+          if (IsLazy(field, context->EnforceLite())) {
+            return new ImmutableLazyMessageFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          } else {
+            return new ImmutableMessageFieldLiteGenerator(
+                field, messageBitIndex, builderBitIndex, context);
+          }
+        case JAVATYPE_ENUM:
+          return new ImmutableEnumFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        case JAVATYPE_STRING:
+          return new ImmutableStringFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+        default:
+          return new ImmutablePrimitiveFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
+      }
+    }
+  }
+}
+
+
+static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) {
+  // Reaching here indicates a bug. Cases are:
+  //   - This FieldGenerator should support packing,
+  //     but this method should be overridden.
+  //   - This FieldGenerator doesn't support packing, and this method
+  //     should never have been called.
+  GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
+             << "called on field generator that does not support packing.";
+}
+
+}  // namespace
+
+ImmutableFieldGenerator::~ImmutableFieldGenerator() {}
+
+void ImmutableFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  ReportUnexpectedPackedFieldsCall(printer);
+}
+
+ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {}
+
+void ImmutableFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  ReportUnexpectedPackedFieldsCall(printer);
+}
+
+// ===================================================================
+
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
+    const Descriptor* descriptor, Context* context)
+    : descriptor_(descriptor),
+      field_generators_(new google::protobuf::scoped_ptr<
+          ImmutableFieldGenerator>[descriptor->field_count()]) {
+
+  // Construct all the FieldGenerators and assign them bit indices for their
+  // bit fields.
+  int messageBitIndex = 0;
+  int builderBitIndex = 0;
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    ImmutableFieldGenerator* generator = MakeImmutableGenerator(
+        descriptor->field(i), messageBitIndex, builderBitIndex, context);
+    field_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
+  }
+}
+
+template<>
+FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+    const Descriptor* descriptor, Context* context)
+    : descriptor_(descriptor),
+      field_generators_(new google::protobuf::scoped_ptr<
+          ImmutableFieldLiteGenerator>[descriptor->field_count()]) {
+  // Construct all the FieldGenerators and assign them bit indices for their
+  // bit fields.
+  int messageBitIndex = 0;
+  int builderBitIndex = 0;
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator(
+        descriptor->field(i), messageBitIndex, builderBitIndex, context);
+    field_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
+  }
+}
+
+template<>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
+
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             const FieldGeneratorInfo* info,
+                             map<string, string>* variables) {
+  (*variables)["field_name"] = descriptor->name();
+  (*variables)["name"] = info->name;
+  (*variables)["capitalized_name"] = info->capitalized_name;
+  (*variables)["disambiguated_reason"] = info->disambiguated_reason;
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+}
+
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             const OneofGeneratorInfo* info,
+                             map<string, string>* variables) {
+  (*variables)["oneof_name"] = info->name;
+  (*variables)["oneof_capitalized_name"] = info->capitalized_name;
+  (*variables)["oneof_index"] =
+      SimpleItoa(descriptor->containing_oneof()->index());
+  (*variables)["set_oneof_case_message"] = info->name +
+      "Case_ = " + SimpleItoa(descriptor->number());
+  (*variables)["clear_oneof_case_message"] = info->name +
+      "Case_ = 0";
+  (*variables)["has_oneof_case_message"] = info->name +
+      "Case_ == " + SimpleItoa(descriptor->number());
+}
+
+void PrintExtraFieldInfo(const map<string, string>& variables,
+                         io::Printer* printer) {
+  const map<string, string>::const_iterator it =
+      variables.find("disambiguated_reason");
+  if (it != variables.end() && !it->second.empty()) {
+    printer->Print(
+        variables,
+        "// An alternative name is used for field \"$field_name$\" because:\n"
+        "//     $disambiguated_reason$\n");
+  }
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.h
new file mode 100644
index 0000000..4dd4f57
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_field.h
@@ -0,0 +1,197 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/logging.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;                // context.h
+      class ClassNameResolver;      // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;                  // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableFieldGenerator {
+ public:
+  ImmutableFieldGenerator() {}
+  virtual ~ImmutableFieldGenerator();
+
+  virtual int GetNumBitsForMessage() const = 0;
+  virtual int GetNumBitsForBuilder() const = 0;
+  virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+  virtual void GenerateMembers(io::Printer* printer) const = 0;
+  virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+  virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0;
+  virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+  virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
+  virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+  virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
+  virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+  virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+      const = 0;
+
+  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+  virtual void GenerateHashCode(io::Printer* printer) const = 0;
+
+  virtual string GetBoxedType() const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator);
+};
+
+class ImmutableFieldLiteGenerator {
+ public:
+  ImmutableFieldLiteGenerator() {}
+  virtual ~ImmutableFieldLiteGenerator();
+
+  virtual int GetNumBitsForMessage() const = 0;
+  virtual int GetNumBitsForBuilder() const = 0;
+  virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+  virtual void GenerateMembers(io::Printer* printer) const = 0;
+  virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+  virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateVisitCode(io::Printer* printer) const = 0;
+  virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer)
+      const = 0;
+  virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+  virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
+  virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+  virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+      const = 0;
+
+  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+  virtual void GenerateHashCode(io::Printer* printer) const = 0;
+
+  virtual string GetBoxedType() const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
+};
+
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+template<typename FieldGeneratorType>
+class FieldGeneratorMap {
+ public:
+  explicit FieldGeneratorMap(const Descriptor* descriptor,
+                             Context* context);
+  ~FieldGeneratorMap();
+
+  const FieldGeneratorType& get(const FieldDescriptor* field) const;
+
+ private:
+  const Descriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGeneratorType> > field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+template<typename FieldGeneratorType>
+inline const FieldGeneratorType&
+FieldGeneratorMap<FieldGeneratorType>::get(const FieldDescriptor* field) const {
+  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+  return *field_generators_[field->index()];
+}
+
+// Instantiate template for mutable and immutable maps.
+template<>
+FieldGeneratorMap<ImmutableFieldGenerator>::
+FieldGeneratorMap(const Descriptor* descriptor,
+                  Context* context);
+
+template<>
+FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap();
+
+
+// Field information used in FieldGeneartors.
+struct FieldGeneratorInfo {
+  string name;
+  string capitalized_name;
+  string disambiguated_reason;
+};
+
+// Oneof information used in OneofFieldGeneartors.
+struct OneofGeneratorInfo {
+  string name;
+  string capitalized_name;
+};
+
+// Set some common variables used in variable FieldGenerators.
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             const FieldGeneratorInfo* info,
+                             map<string, string>* variables);
+
+// Set some common oneof variables used in OneofFieldGenerators.
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             const OneofGeneratorInfo* info,
+                             map<string, string>* variables);
+
+// Print useful comments before a field's accessors.
+void PrintExtraFieldInfo(const map<string, string>& variables,
+                         io::Printer* printer);
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.cc
new file mode 100644
index 0000000..c53aae6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.cc
@@ -0,0 +1,616 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_file.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_service.h>
+#include <google/protobuf/compiler/java/java_shared_code_generator.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+struct FieldDescriptorCompare {
+  bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) {
+    if(f1 == NULL) {
+      return false;
+    }
+    if(f2 == NULL) {
+      return true;
+    }
+    return f1->full_name() < f2->full_name();
+  }
+};
+
+typedef std::set<const FieldDescriptor*, FieldDescriptorCompare> FieldDescriptorSet;
+
+// Recursively searches the given message to collect extensions.
+// Returns true if all the extensions can be recognized. The extensions will be
+// appended in to the extensions parameter.
+// Returns false when there are unknown fields, in which case the data in the
+// extensions output parameter is not reliable and should be discarded.
+bool CollectExtensions(const Message& message,
+                       FieldDescriptorSet* extensions) {
+  const Reflection* reflection = message.GetReflection();
+
+  // There are unknown fields that could be extensions, thus this call fails.
+  if (reflection->GetUnknownFields(message).field_count() > 0) return false;
+
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+
+  for (int i = 0; i < fields.size(); i++) {
+    if (fields[i]->is_extension()) extensions->insert(fields[i]);
+
+    if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
+      if (fields[i]->is_repeated()) {
+        int size = reflection->FieldSize(message, fields[i]);
+        for (int j = 0; j < size; j++) {
+          const Message& sub_message =
+            reflection->GetRepeatedMessage(message, fields[i], j);
+          if (!CollectExtensions(sub_message, extensions)) return false;
+        }
+      } else {
+        const Message& sub_message = reflection->GetMessage(message, fields[i]);
+        if (!CollectExtensions(sub_message, extensions)) return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+// Finds all extensions in the given message and its sub-messages.  If the
+// message contains unknown fields (which could be extensions), then those
+// extensions are defined in alternate_pool.
+// The message will be converted to a DynamicMessage backed by alternate_pool
+// in order to handle this case.
+void CollectExtensions(const FileDescriptorProto& file_proto,
+                       const DescriptorPool& alternate_pool,
+                       FieldDescriptorSet* extensions,
+                       const string& file_data) {
+  if (!CollectExtensions(file_proto, extensions)) {
+    // There are unknown fields in the file_proto, which are probably
+    // extensions. We need to parse the data into a dynamic message based on the
+    // builder-pool to find out all extensions.
+    const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
+        file_proto.GetDescriptor()->full_name());
+    GOOGLE_CHECK(file_proto_desc)
+        << "Find unknown fields in FileDescriptorProto when building "
+        << file_proto.name()
+        << ". It's likely that those fields are custom options, however, "
+           "descriptor.proto is not in the transitive dependencies. "
+           "This normally should not happen. Please report a bug.";
+    DynamicMessageFactory factory;
+    google::protobuf::scoped_ptr<Message> dynamic_file_proto(
+        factory.GetPrototype(file_proto_desc)->New());
+    GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
+    GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
+
+    // Collect the extensions again from the dynamic message. There should be no
+    // more unknown fields this time, i.e. all the custom options should be
+    // parsed as extensions now.
+    extensions->clear();
+    GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
+        << "Find unknown fields in FileDescriptorProto when building "
+        << file_proto.name()
+        << ". It's likely that those fields are custom options, however, "
+           "those options cannot be recognized in the builder pool. "
+           "This normally should not happen. Please report a bug.";
+  }
+}
+
+// Compare two field descriptors, returning true if the first should come
+// before the second.
+bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) {
+  return a->full_name() < b->full_name();
+}
+
+// Our static initialization methods can become very, very large.
+// So large that if we aren't careful we end up blowing the JVM's
+// 64K bytes of bytecode/method. Fortunately, since these static
+// methods are executed only once near the beginning of a program,
+// there's usually plenty of stack space available and we can
+// extend our methods by simply chaining them to another method
+// with a tail call. This inserts the sequence call-next-method,
+// end this one, begin-next-method as needed.
+void MaybeRestartJavaMethod(io::Printer* printer,
+                            int *bytecode_estimate,
+                            int *method_num,
+                            const char *chain_statement,
+                            const char *method_decl) {
+  // The goal here is to stay under 64K bytes of jvm bytecode/method,
+  // since otherwise we hit a hardcoded limit in the jvm and javac will
+  // then fail with the error "code too large". This limit lets our
+  // estimates be off by a factor of two and still we're okay.
+  static const int bytesPerMethod = kMaxStaticSize;
+
+  if ((*bytecode_estimate) > bytesPerMethod) {
+    ++(*method_num);
+    printer->Print(chain_statement, "method_num", SimpleItoa(*method_num));
+    printer->Outdent();
+    printer->Print("}\n");
+    printer->Print(method_decl, "method_num", SimpleItoa(*method_num));
+    printer->Indent();
+    *bytecode_estimate = 0;
+  }
+}
+
+
+}  // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api,
+                             bool enforce_lite)
+    : file_(file),
+      java_package_(FileJavaPackage(file, immutable_api)),
+      message_generators_(
+          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
+      extension_generators_(
+          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
+      context_(new Context(file)),
+      name_resolver_(context_->GetNameResolver()),
+      immutable_api_(immutable_api) {
+  classname_ = name_resolver_->GetFileClassName(file, immutable_api);
+  context_->SetEnforceLite(enforce_lite);
+  generator_factory_.reset(
+      new ImmutableGeneratorFactory(context_.get()));
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    message_generators_[i].reset(
+        generator_factory_->NewMessageGenerator(file_->message_type(i)));
+  }
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    extension_generators_[i].reset(
+        generator_factory_->NewExtensionGenerator(file_->extension(i)));
+  }
+}
+
+FileGenerator::~FileGenerator() {}
+
+bool FileGenerator::Validate(string* error) {
+  // Check that no class name matches the file's class name.  This is a common
+  // problem that leads to Java compile errors that can be hard to understand.
+  // It's especially bad when using the java_multiple_files, since we would
+  // end up overwriting the outer class with one of the inner ones.
+  if (name_resolver_->HasConflictingClassName(file_, classname_)) {
+    error->assign(file_->name());
+    error->append(
+      ": Cannot generate Java output because the file's outer class name, \"");
+    error->append(classname_);
+    error->append(
+      "\", matches the name of one of the types declared inside it.  "
+      "Please either rename the type or use the java_outer_classname "
+      "option to specify a different outer class name for the .proto file.");
+    return false;
+  }
+  return true;
+}
+
+void FileGenerator::Generate(io::Printer* printer) {
+  // We don't import anything because we refer to all classes by their
+  // fully-qualified names in the generated source.
+  printer->Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "// source: $filename$\n"
+    "\n",
+    "filename", file_->name());
+  if (!java_package_.empty()) {
+    printer->Print(
+      "package $package$;\n"
+      "\n",
+      "package", java_package_);
+  }
+  printer->Print(
+    "public final class $classname$ {\n"
+    "  private $classname$() {}\n",
+    "classname", classname_);
+  printer->Indent();
+
+  // -----------------------------------------------------------------
+
+  printer->Print(
+    "public static void registerAllExtensions(\n"
+    "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
+    "lite",
+    HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite");
+
+  printer->Indent();
+
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->GenerateRegistrationCode(printer);
+  }
+
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateExtensionRegistrationCode(printer);
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+
+  // -----------------------------------------------------------------
+
+  if (!MultipleJavaFiles(file_, immutable_api_)) {
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+        EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
+            .Generate(printer);
+      } else {
+        EnumLiteGenerator(file_->enum_type(i), immutable_api_, context_.get())
+            .Generate(printer);
+      }
+    }
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      message_generators_[i]->GenerateInterface(printer);
+      message_generators_[i]->Generate(printer);
+    }
+    if (HasGenericServices(file_, context_->EnforceLite())) {
+      for (int i = 0; i < file_->service_count(); i++) {
+        google::protobuf::scoped_ptr<ServiceGenerator> generator(
+            generator_factory_->NewServiceGenerator(file_->service(i)));
+        generator->Generate(printer);
+      }
+    }
+  }
+
+  // Extensions must be generated in the outer class since they are values,
+  // not classes.
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->Generate(printer);
+  }
+
+  // Static variables. We'd like them to be final if possible, but due to
+  // the JVM's 64k size limit on static blocks, we have to initialize some
+  // of them in methods; thus they cannot be final.
+  int static_block_bytecode_estimate = 0;
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateStaticVariables(
+        printer, &static_block_bytecode_estimate);
+  }
+
+  printer->Print("\n");
+
+  if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+    if (immutable_api_) {
+      GenerateDescriptorInitializationCodeForImmutable(printer);
+    } else {
+      GenerateDescriptorInitializationCodeForMutable(printer);
+    }
+  } else {
+    printer->Print(
+      "static {\n");
+    printer->Indent();
+    int bytecode_estimate = 0;
+    int method_num = 0;
+
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+      MaybeRestartJavaMethod(
+        printer,
+        &bytecode_estimate, &method_num,
+        "_clinit_autosplit_$method_num$();\n",
+        "private static void _clinit_autosplit_$method_num$() {\n");
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "}\n");
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(outer_class_scope)\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
+    io::Printer* printer) {
+  printer->Print(
+    "public static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "    getDescriptor() {\n"
+    "  return descriptor;\n"
+    "}\n"
+    "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
+    "    descriptor;\n"
+    "static {\n",
+    // TODO(dweis): Mark this as final.
+    "final", "");
+  printer->Indent();
+
+  SharedCodeGenerator shared_code_generator(file_);
+  shared_code_generator.GenerateDescriptors(printer);
+
+  int bytecode_estimate = 0;
+  int method_num = 0;
+
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+    MaybeRestartJavaMethod(
+      printer,
+      &bytecode_estimate, &method_num,
+      "_clinit_autosplit_dinit_$method_num$();\n",
+      "private static void _clinit_autosplit_dinit_$method_num$() {\n");
+  }
+  for (int i = 0; i < file_->extension_count(); i++) {
+    bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+    MaybeRestartJavaMethod(
+      printer,
+      &bytecode_estimate, &method_num,
+      "_clinit_autosplit_dinit_$method_num$();\n",
+      "private static void _clinit_autosplit_dinit_$method_num$() {\n");
+  }
+
+  // Proto compiler builds a DescriptorPool, which holds all the descriptors to
+  // generate, when processing the ".proto" files. We call this DescriptorPool
+  // the parsed pool (a.k.a. file_->pool()).
+  //
+  // Note that when users try to extend the (.*)DescriptorProto in their
+  // ".proto" files, it does not affect the pre-built FileDescriptorProto class
+  // in proto compiler. When we put the descriptor data in the file_proto, those
+  // extensions become unknown fields.
+  //
+  // Now we need to find out all the extension value to the (.*)DescriptorProto
+  // in the file_proto message, and prepare an ExtensionRegistry to return.
+  //
+  // To find those extensions, we need to parse the data into a dynamic message
+  // of the FileDescriptor based on the builder-pool, then we can use
+  // reflections to find all extension fields
+  FileDescriptorProto file_proto;
+  file_->CopyTo(&file_proto);
+  string file_data;
+  file_proto.SerializeToString(&file_data);
+  FieldDescriptorSet extensions;
+  CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+  if (extensions.size() > 0) {
+    // Must construct an ExtensionRegistry containing all existing extensions
+    // and use it to parse the descriptor data again to recognize extensions.
+    printer->Print(
+      "com.google.protobuf.ExtensionRegistry registry =\n"
+      "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
+    FieldDescriptorSet::iterator it;
+    for (it = extensions.begin(); it != extensions.end(); it++) {
+      google::protobuf::scoped_ptr<ExtensionGenerator> generator(
+          generator_factory_->NewExtensionGenerator(*it));
+      bytecode_estimate += generator->GenerateRegistrationCode(printer);
+      MaybeRestartJavaMethod(
+        printer,
+        &bytecode_estimate, &method_num,
+        "_clinit_autosplit_dinit_$method_num$(registry);\n",
+        "private static void _clinit_autosplit_dinit_$method_num$(\n"
+        "    com.google.protobuf.ExtensionRegistry registry) {\n");
+    }
+    printer->Print(
+      "com.google.protobuf.Descriptors.FileDescriptor\n"
+      "    .internalUpdateFileDescriptor(descriptor, registry);\n");
+  }
+
+  // Force descriptor initialization of all dependencies.
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    if (ShouldIncludeDependency(file_->dependency(i), true)) {
+      string dependency =
+          name_resolver_->GetImmutableClassName(file_->dependency(i));
+      printer->Print(
+        "$dependency$.getDescriptor();\n",
+        "dependency", dependency);
+    }
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+}
+
+void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) {
+  printer->Print(
+    "public static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "    getDescriptor() {\n"
+    "  return descriptor;\n"
+    "}\n"
+    "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
+    "    descriptor;\n"
+    "static {\n");
+  printer->Indent();
+
+  printer->Print(
+    "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n",
+    "immutable_package", FileJavaPackage(file_, true),
+    "descriptor_classname", name_resolver_->GetDescriptorClassName(file_));
+
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateStaticVariableInitializers(printer);
+  }
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+  }
+
+  // Check if custom options exist. If any, try to load immutable classes since
+  // custom options are only represented with immutable messages.
+  FileDescriptorProto file_proto;
+  file_->CopyTo(&file_proto);
+  string file_data;
+  file_proto.SerializeToString(&file_data);
+  FieldDescriptorSet extensions;
+  CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+  if (extensions.size() > 0) {
+    // Try to load immutable messages' outer class. Its initialization code
+    // will take care of interpreting custom options.
+    printer->Print(
+      "try {\n"
+      // Note that we have to load the immutable class dynamically here as
+      // we want the mutable code to be independent from the immutable code
+      // at compile time. It is required to implement dual-compile for
+      // mutable and immutable API in blaze.
+      "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
+      "      \"$immutable_classname$\");\n"
+      "} catch (java.lang.ClassNotFoundException e) {\n"
+      // The immutable class can not be found. Custom options are left
+      // as unknown fields.
+      // TODO(xiaofeng): inform the user with a warning?
+      "}\n",
+      "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+  }
+
+  // Force descriptor initialization of all dependencies.
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    if (ShouldIncludeDependency(file_->dependency(i), false)) {
+      string dependency = name_resolver_->GetMutableClassName(
+          file_->dependency(i));
+      printer->Print(
+        "$dependency$.getDescriptor();\n",
+        "dependency", dependency);
+    }
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+}
+
+template<typename GeneratorClass, typename DescriptorClass>
+static void GenerateSibling(const string& package_dir,
+                            const string& java_package,
+                            const DescriptorClass* descriptor,
+                            GeneratorContext* context,
+                            vector<string>* file_list,
+                            const string& name_suffix,
+                            GeneratorClass* generator,
+                            void (GeneratorClass::*pfn)(io::Printer* printer)) {
+  string filename = package_dir + descriptor->name() + name_suffix + ".java";
+  file_list->push_back(filename);
+
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  io::Printer printer(output.get(), '$');
+
+  printer.Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "// source: $filename$\n"
+    "\n",
+    "filename", descriptor->file()->name());
+  if (!java_package.empty()) {
+    printer.Print(
+      "package $package$;\n"
+      "\n",
+      "package", java_package);
+  }
+
+  (generator->*pfn)(&printer);
+}
+
+void FileGenerator::GenerateSiblings(const string& package_dir,
+                                     GeneratorContext* context,
+                                     vector<string>* file_list) {
+  if (MultipleJavaFiles(file_, immutable_api_)) {
+    for (int i = 0; i < file_->enum_type_count(); i++) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+        EnumGenerator generator(file_->enum_type(i), immutable_api_,
+                                context_.get());
+        GenerateSibling<EnumGenerator>(package_dir, java_package_,
+                                       file_->enum_type(i),
+                                       context, file_list, "",
+                                       &generator,
+                                       &EnumGenerator::Generate);
+      } else {
+        EnumLiteGenerator generator(file_->enum_type(i), immutable_api_,
+                                    context_.get());
+        GenerateSibling<EnumLiteGenerator>(package_dir, java_package_,
+                                           file_->enum_type(i),
+                                           context, file_list, "",
+                                           &generator,
+                                           &EnumLiteGenerator::Generate);
+      }
+    }
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      if (immutable_api_) {
+        GenerateSibling<MessageGenerator>(package_dir, java_package_,
+                                          file_->message_type(i),
+                                          context, file_list,
+                                          "OrBuilder",
+                                          message_generators_[i].get(),
+                                          &MessageGenerator::GenerateInterface);
+      }
+      GenerateSibling<MessageGenerator>(package_dir, java_package_,
+                                        file_->message_type(i),
+                                        context, file_list, "",
+                                        message_generators_[i].get(),
+                                        &MessageGenerator::Generate);
+    }
+    if (HasGenericServices(file_, context_->EnforceLite())) {
+      for (int i = 0; i < file_->service_count(); i++) {
+        google::protobuf::scoped_ptr<ServiceGenerator> generator(
+            generator_factory_->NewServiceGenerator(file_->service(i)));
+        GenerateSibling<ServiceGenerator>(package_dir, java_package_,
+                                          file_->service(i),
+                                          context, file_list, "",
+                                          generator.get(),
+                                          &ServiceGenerator::Generate);
+      }
+    }
+  }
+}
+
+bool FileGenerator::ShouldIncludeDependency(
+    const FileDescriptor* descriptor, bool immutable_api) {
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.h
new file mode 100644
index 0000000..7dbeb94
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_file.h
@@ -0,0 +1,119 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  class FileDescriptor;          // descriptor.h
+  namespace io {
+    class Printer;               // printer.h
+  }
+  namespace compiler {
+    class GeneratorContext;      // code_generator.h
+    namespace java {
+      class Context;             // context.h
+      class MessageGenerator;    // message.h
+      class GeneratorFactory;    // generator_factory.h
+      class ExtensionGenerator;  // extension.h
+      class ClassNameResolver;   // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class FileGenerator {
+ public:
+  FileGenerator(const FileDescriptor* file, bool immutable_api = true,
+                bool enforce_lite = false);
+  ~FileGenerator();
+
+  // Checks for problems that would otherwise lead to cryptic compile errors.
+  // Returns true if there are no problems, or writes an error description to
+  // the given string and returns false otherwise.
+  bool Validate(string* error);
+
+  void Generate(io::Printer* printer);
+
+  // If we aren't putting everything into one file, this will write all the
+  // files other than the outer file (i.e. one for each message, enum, and
+  // service type).
+  void GenerateSiblings(const string& package_dir,
+                        GeneratorContext* generator_context,
+                        vector<string>* file_list);
+
+  const string& java_package() { return java_package_; }
+  const string& classname()    { return classname_;    }
+
+
+ private:
+  void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer);
+  void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer);
+
+  bool ShouldIncludeDependency(const FileDescriptor* descriptor,
+                               bool immutable_api_);
+
+  const FileDescriptor* file_;
+  string java_package_;
+  string classname_;
+
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
+  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+  google::protobuf::scoped_ptr<GeneratorFactory> generator_factory_;
+  google::protobuf::scoped_ptr<Context> context_;
+  ClassNameResolver* name_resolver_;
+  bool immutable_api_;
+
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.cc
new file mode 100644
index 0000000..a46c7fc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.cc
@@ -0,0 +1,177 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_generator.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/java/java_file.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_shared_code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+
+JavaGenerator::JavaGenerator() {}
+JavaGenerator::~JavaGenerator() {}
+
+bool JavaGenerator::Generate(const FileDescriptor* file,
+                             const string& parameter,
+                             GeneratorContext* context,
+                             string* error) const {
+  // -----------------------------------------------------------------
+  // parse generator options
+
+  // Name a file where we will write a list of generated file names, one
+  // per line.
+  string output_list_file;
+
+
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
+  bool generate_immutable_code = false;
+  bool generate_mutable_code = false;
+  bool generate_shared_code = false;
+  bool enforce_lite = false;
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "output_list_file") {
+      output_list_file = options[i].second;
+    } else if (options[i].first == "immutable") {
+      generate_immutable_code = true;
+    } else if (options[i].first == "mutable") {
+      generate_mutable_code = true;
+    } else if (options[i].first == "shared") {
+      generate_shared_code = true;
+    } else if (options[i].first == "lite") {
+      // When set, the protoc will generate the current files and all the
+      // transitive dependencies as lite runtime.
+      enforce_lite = true;
+    } else {
+      *error = "Unknown generator option: " + options[i].first;
+      return false;
+    }
+  }
+
+  if (enforce_lite && generate_mutable_code) {
+    *error = "lite runtime generator option cannot be used with mutable API.";
+    return false;
+  }
+
+  // By default we generate immutable code and shared code for immutable API.
+  if (!generate_immutable_code && !generate_mutable_code &&
+      !generate_shared_code) {
+    generate_immutable_code = true;
+    generate_shared_code = true;
+  }
+
+  // -----------------------------------------------------------------
+
+
+  vector<string> all_files;
+
+
+  vector<FileGenerator*> file_generators;
+  if (generate_immutable_code) {
+    file_generators.push_back(
+        new FileGenerator(file, /* immutable = */ true, enforce_lite));
+  }
+  if (generate_mutable_code) {
+    file_generators.push_back(
+        new FileGenerator(file, /* mutable = */ false, enforce_lite));
+  }
+  for (int i = 0; i < file_generators.size(); ++i) {
+    if (!file_generators[i]->Validate(error)) {
+      for (int j = 0; j < file_generators.size(); ++j) {
+        delete file_generators[j];
+      }
+      return false;
+    }
+  }
+
+  for (int i = 0; i < file_generators.size(); ++i) {
+    FileGenerator* file_generator = file_generators[i];
+
+    string package_dir = JavaPackageToDir(file_generator->java_package());
+
+    string java_filename = package_dir;
+    java_filename += file_generator->classname();
+    java_filename += ".java";
+    all_files.push_back(java_filename);
+
+    // Generate main java file.
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        context->Open(java_filename));
+    io::Printer printer(output.get(), '$');
+    file_generator->Generate(&printer);
+
+    // Generate sibling files.
+    file_generator->GenerateSiblings(package_dir, context, &all_files);
+  }
+
+  for (int i = 0; i < file_generators.size(); ++i) {
+    delete file_generators[i];
+  }
+  file_generators.clear();
+
+  // Generate output list if requested.
+  if (!output_list_file.empty()) {
+    // Generate output list.  This is just a simple text file placed in a
+    // deterministic location which lists the .java files being generated.
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+        context->Open(output_list_file));
+    io::Printer srclist_printer(srclist_raw_output.get(), '$');
+    for (int i = 0; i < all_files.size(); i++) {
+      srclist_printer.Print("$filename$\n", "filename", all_files[i]);
+    }
+  }
+
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.h
new file mode 100644
index 0000000..47f76be
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator.h
@@ -0,0 +1,72 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Generates Java code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// CodeGenerator implementation which generates Java code.  If you create your
+// own protocol compiler binary and you want it to support Java output, you
+// can do so by registering an instance of this CodeGenerator with the
+// CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator {
+ public:
+  JavaGenerator();
+  ~JavaGenerator();
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* context,
+                string* error) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.cc
new file mode 100644
index 0000000..3218b41
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -0,0 +1,87 @@
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_message_lite.h>
+#include <google/protobuf/compiler/java/java_service.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+GeneratorFactory::GeneratorFactory() {}
+GeneratorFactory::~GeneratorFactory() {}
+
+// ===================================================================
+
+ImmutableGeneratorFactory::ImmutableGeneratorFactory(
+    Context* context) : context_(context) {
+}
+ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {}
+
+MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
+    const Descriptor* descriptor) const {
+  if (HasDescriptorMethods(descriptor, context_->EnforceLite())) {
+    return new ImmutableMessageGenerator(descriptor, context_);
+  } else {
+    return new ImmutableMessageLiteGenerator(descriptor, context_);
+  }
+}
+
+ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
+    const FieldDescriptor* descriptor) const {
+  if (HasDescriptorMethods(descriptor->file(), context_->EnforceLite())) {
+    return new ImmutableExtensionGenerator(descriptor, context_);
+  } else {
+    return new ImmutableExtensionLiteGenerator(descriptor, context_);
+  }
+}
+
+ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator(
+    const ServiceDescriptor* descriptor) const {
+  return new ImmutableServiceGenerator(descriptor, context_);
+}
+
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.h
new file mode 100644
index 0000000..55365a9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_generator_factory.h
@@ -0,0 +1,101 @@
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  class FieldDescriptor;         // descriptor.h
+  class Descriptor;              // descriptor.h
+  class ServiceDescriptor;       // descriptor.h
+  namespace compiler {
+    namespace java {
+      class MessageGenerator;    // message.h
+      class ExtensionGenerator;  // extension.h
+      class ServiceGenerator;    // service.h
+      class Context;             // context.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class GeneratorFactory {
+ public:
+  GeneratorFactory();
+  virtual ~GeneratorFactory();
+
+  virtual MessageGenerator* NewMessageGenerator(
+      const Descriptor* descriptor) const = 0;
+
+  virtual ExtensionGenerator* NewExtensionGenerator(
+      const FieldDescriptor* descriptor) const = 0;
+
+  virtual ServiceGenerator* NewServiceGenerator(
+      const ServiceDescriptor* descriptor) const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory);
+};
+
+// Factory that creates generators for immutable-default messages.
+class ImmutableGeneratorFactory : public GeneratorFactory {
+ public:
+  ImmutableGeneratorFactory(Context* context);
+  virtual ~ImmutableGeneratorFactory();
+
+  virtual MessageGenerator* NewMessageGenerator(
+      const Descriptor* descriptor) const;
+
+  virtual ExtensionGenerator* NewExtensionGenerator(
+      const FieldDescriptor* descriptor) const;
+
+  virtual ServiceGenerator* NewServiceGenerator(
+      const ServiceDescriptor* descriptor) const;
+
+ private:
+  Context* context_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory);
+};
+
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.cc
new file mode 100644
index 0000000..e24894b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.cc
@@ -0,0 +1,757 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+const char kThickSeparator[] =
+  "// ===================================================================\n";
+const char kThinSeparator[] =
+  "// -------------------------------------------------------------------\n";
+
+namespace {
+
+const char* kDefaultPackage = "";
+
+// Names that should be avoided as field names.
+// Using them will cause the compiler to generate accessors whose names are
+// colliding with methods defined in base classes.
+const char* kForbiddenWordList[] = {
+  // message base class:
+  "cached_size", "serialized_size",
+  // java.lang.Object:
+  "class",
+};
+
+bool IsForbidden(const string& field_name) {
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
+    if (field_name == kForbiddenWordList[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+string FieldName(const FieldDescriptor* field) {
+  string field_name;
+  // Groups are hacky:  The name of the field is just the lower-cased name
+  // of the group type.  In Java, though, we would like to retain the original
+  // capitalization of the type name.
+  if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
+    field_name = field->message_type()->name();
+  } else {
+    field_name = field->name();
+  }
+  if (IsForbidden(field_name)) {
+    // Append a trailing "#" to indicate that the name should be decorated to
+    // avoid collision with other names.
+    field_name += "#";
+  }
+  return field_name;
+}
+
+
+}  // namespace
+
+string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
+  string result;
+  // Note:  I distrust ctype.h due to locales.
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      if (cap_next_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      if (i == 0 && !cap_next_letter) {
+        // Force first letter to lower-case unless explicitly told to
+        // capitalize it.
+        result += input[i] + ('a' - 'A');
+      } else {
+        // Capital letters after the first are left as-is.
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_next_letter = true;
+    } else {
+      cap_next_letter = true;
+    }
+  }
+  // Add a trailing "_" if the name should be altered.
+  if (input[input.size() - 1] == '#') {
+    result += '_';
+  }
+  return result;
+}
+
+string UnderscoresToCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCase(FieldName(field), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCase(FieldName(field), true);
+}
+
+string UnderscoresToCamelCase(const MethodDescriptor* method) {
+  return UnderscoresToCamelCase(method->name(), false);
+}
+
+string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
+  return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
+}
+
+string StripProto(const string& filename) {
+  if (HasSuffixString(filename, ".protodevel")) {
+    return StripSuffixString(filename, ".protodevel");
+  } else {
+    return StripSuffixString(filename, ".proto");
+  }
+}
+
+string FileClassName(const FileDescriptor* file, bool immutable) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetFileClassName(file, immutable);
+}
+
+string FileJavaPackage(const FileDescriptor* file, bool immutable) {
+  string result;
+
+  if (file->options().has_java_package()) {
+    result = file->options().java_package();
+  } else {
+    result = kDefaultPackage;
+    if (!file->package().empty()) {
+      if (!result.empty()) result += '.';
+      result += file->package();
+    }
+  }
+
+  return result;
+}
+
+string JavaPackageToDir(string package_name) {
+  string package_dir =
+    StringReplace(package_name, ".", "/", true);
+  if (!package_dir.empty()) package_dir += "/";
+  return package_dir;
+}
+
+// TODO(xiaofeng): This function is only kept for it's publicly referenced.
+// It should be removed after mutable API up-integration.
+string ToJavaName(const string& full_name,
+                  const FileDescriptor* file) {
+  string result;
+  if (file->options().java_multiple_files()) {
+    result = FileJavaPackage(file);
+  } else {
+    result = ClassName(file);
+  }
+  if (!result.empty()) {
+    result += '.';
+  }
+  if (file->package().empty()) {
+    result += full_name;
+  } else {
+    // Strip the proto package from full_name since we've replaced it with
+    // the Java package.
+    result += full_name.substr(file->package().size() + 1);
+  }
+  return result;
+}
+
+string ClassName(const Descriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+string ClassName(const EnumDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+string ClassName(const ServiceDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+string ClassName(const FileDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+string ExtraMessageInterfaces(const Descriptor* descriptor) {
+  string interfaces = "// @@protoc_insertion_point(message_implements:"
+      + descriptor->full_name() + ")";
+  return interfaces;
+}
+
+
+string ExtraBuilderInterfaces(const Descriptor* descriptor) {
+  string interfaces = "// @@protoc_insertion_point(builder_implements:"
+      + descriptor->full_name() + ")";
+  return interfaces;
+}
+
+string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
+  string interfaces = "// @@protoc_insertion_point(interface_extends:"
+      + descriptor->full_name() + ")";
+  return interfaces;
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+  string name = field->name() + "_FIELD_NUMBER";
+  UpperString(&name);
+  return name;
+}
+
+FieldDescriptor::Type GetType(const FieldDescriptor* field) {
+  return field->type();
+}
+
+JavaType GetJavaType(const FieldDescriptor* field) {
+  switch (GetType(field)) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+      return JAVATYPE_INT;
+
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      return JAVATYPE_LONG;
+
+    case FieldDescriptor::TYPE_FLOAT:
+      return JAVATYPE_FLOAT;
+
+    case FieldDescriptor::TYPE_DOUBLE:
+      return JAVATYPE_DOUBLE;
+
+    case FieldDescriptor::TYPE_BOOL:
+      return JAVATYPE_BOOLEAN;
+
+    case FieldDescriptor::TYPE_STRING:
+      return JAVATYPE_STRING;
+
+    case FieldDescriptor::TYPE_BYTES:
+      return JAVATYPE_BYTES;
+
+    case FieldDescriptor::TYPE_ENUM:
+      return JAVATYPE_ENUM;
+
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      return JAVATYPE_MESSAGE;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return JAVATYPE_INT;
+}
+
+const char* PrimitiveTypeName(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return "int";
+    case JAVATYPE_LONG   : return "long";
+    case JAVATYPE_FLOAT  : return "float";
+    case JAVATYPE_DOUBLE : return "double";
+    case JAVATYPE_BOOLEAN: return "boolean";
+    case JAVATYPE_STRING : return "java.lang.String";
+    case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
+    case JAVATYPE_ENUM   : return NULL;
+    case JAVATYPE_MESSAGE: return NULL;
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+const char* BoxedPrimitiveTypeName(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return "java.lang.Integer";
+    case JAVATYPE_LONG   : return "java.lang.Long";
+    case JAVATYPE_FLOAT  : return "java.lang.Float";
+    case JAVATYPE_DOUBLE : return "java.lang.Double";
+    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
+    case JAVATYPE_STRING : return "java.lang.String";
+    case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
+    case JAVATYPE_ENUM   : return NULL;
+    case JAVATYPE_MESSAGE: return NULL;
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+const char* FieldTypeName(FieldDescriptor::Type field_type) {
+  switch (field_type) {
+    case FieldDescriptor::TYPE_INT32   : return "INT32";
+    case FieldDescriptor::TYPE_UINT32  : return "UINT32";
+    case FieldDescriptor::TYPE_SINT32  : return "SINT32";
+    case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
+    case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
+    case FieldDescriptor::TYPE_INT64   : return "INT64";
+    case FieldDescriptor::TYPE_UINT64  : return "UINT64";
+    case FieldDescriptor::TYPE_SINT64  : return "SINT64";
+    case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
+    case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
+    case FieldDescriptor::TYPE_FLOAT   : return "FLOAT";
+    case FieldDescriptor::TYPE_DOUBLE  : return "DOUBLE";
+    case FieldDescriptor::TYPE_BOOL    : return "BOOL";
+    case FieldDescriptor::TYPE_STRING  : return "STRING";
+    case FieldDescriptor::TYPE_BYTES   : return "BYTES";
+    case FieldDescriptor::TYPE_ENUM    : return "ENUM";
+    case FieldDescriptor::TYPE_GROUP   : return "GROUP";
+    case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+bool AllAscii(const string& text) {
+  for (int i = 0; i < text.size(); i++) {
+    if ((text[i] & 0x80) != 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+string DefaultValue(const FieldDescriptor* field, bool immutable,
+                    ClassNameResolver* name_resolver) {
+  // Switch on CppType since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return SimpleItoa(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      // Need to print as a signed int since Java has no unsigned.
+      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
+    case FieldDescriptor::CPPTYPE_INT64:
+      return SimpleItoa(field->default_value_int64()) + "L";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
+             "L";
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = field->default_value_double();
+      if (value == numeric_limits<double>::infinity()) {
+        return "Double.POSITIVE_INFINITY";
+      } else if (value == -numeric_limits<double>::infinity()) {
+        return "Double.NEGATIVE_INFINITY";
+      } else if (value != value) {
+        return "Double.NaN";
+      } else {
+        return SimpleDtoa(value) + "D";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = field->default_value_float();
+      if (value == numeric_limits<float>::infinity()) {
+        return "Float.POSITIVE_INFINITY";
+      } else if (value == -numeric_limits<float>::infinity()) {
+        return "Float.NEGATIVE_INFINITY";
+      } else if (value != value) {
+        return "Float.NaN";
+      } else {
+        return SimpleFtoa(value) + "F";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "true" : "false";
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
+        if (field->has_default_value()) {
+          // See comments in Internal.java for gory details.
+          return strings::Substitute(
+            "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
+            CEscape(field->default_value_string()));
+        } else {
+          return "com.google.protobuf.ByteString.EMPTY";
+        }
+      } else {
+        if (AllAscii(field->default_value_string())) {
+          // All chars are ASCII.  In this case CEscape() works fine.
+          return "\"" + CEscape(field->default_value_string()) + "\"";
+        } else {
+          // See comments in Internal.java for gory details.
+          return strings::Substitute(
+              "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
+              CEscape(field->default_value_string()));
+        }
+      }
+
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
+          field->default_value_enum()->name();
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return name_resolver->GetClassName(field->message_type(), immutable) +
+          ".getDefaultInstance()";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
+  // Switch on CppType since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() == 0L;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0L;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0.0;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+const char* bit_masks[] = {
+  "0x00000001",
+  "0x00000002",
+  "0x00000004",
+  "0x00000008",
+  "0x00000010",
+  "0x00000020",
+  "0x00000040",
+  "0x00000080",
+
+  "0x00000100",
+  "0x00000200",
+  "0x00000400",
+  "0x00000800",
+  "0x00001000",
+  "0x00002000",
+  "0x00004000",
+  "0x00008000",
+
+  "0x00010000",
+  "0x00020000",
+  "0x00040000",
+  "0x00080000",
+  "0x00100000",
+  "0x00200000",
+  "0x00400000",
+  "0x00800000",
+
+  "0x01000000",
+  "0x02000000",
+  "0x04000000",
+  "0x08000000",
+  "0x10000000",
+  "0x20000000",
+  "0x40000000",
+  "0x80000000",
+};
+
+string GetBitFieldName(int index) {
+  string varName = "bitField";
+  varName += SimpleItoa(index);
+  varName += "_";
+  return varName;
+}
+
+string GetBitFieldNameForBit(int bitIndex) {
+  return GetBitFieldName(bitIndex / 32);
+}
+
+namespace {
+
+string GenerateGetBitInternal(const string& prefix, int bitIndex) {
+  string varName = prefix + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
+  return result;
+}
+
+string GenerateSetBitInternal(const string& prefix, int bitIndex) {
+  string varName = prefix + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " |= " + mask;
+  return result;
+}
+
+}  // namespace
+
+string GenerateGetBit(int bitIndex) {
+  return GenerateGetBitInternal("", bitIndex);
+}
+
+string GenerateSetBit(int bitIndex) {
+  return GenerateSetBitInternal("", bitIndex);
+}
+
+string GenerateClearBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " = (" + varName + " & ~" + mask + ")";
+  return result;
+}
+
+string GenerateGetBitFromLocal(int bitIndex) {
+  return GenerateGetBitInternal("from_", bitIndex);
+}
+
+string GenerateSetBitToLocal(int bitIndex) {
+  return GenerateSetBitInternal("to_", bitIndex);
+}
+
+string GenerateGetBitMutableLocal(int bitIndex) {
+  return GenerateGetBitInternal("mutable_", bitIndex);
+}
+
+string GenerateSetBitMutableLocal(int bitIndex) {
+  return GenerateSetBitInternal("mutable_", bitIndex);
+}
+
+bool IsReferenceType(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return false;
+    case JAVATYPE_LONG   : return false;
+    case JAVATYPE_FLOAT  : return false;
+    case JAVATYPE_DOUBLE : return false;
+    case JAVATYPE_BOOLEAN: return false;
+    case JAVATYPE_STRING : return true;
+    case JAVATYPE_BYTES  : return true;
+    case JAVATYPE_ENUM   : return true;
+    case JAVATYPE_MESSAGE: return true;
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
+  switch (GetType(field)) {
+    case FieldDescriptor::TYPE_INT32   : return "Int32";
+    case FieldDescriptor::TYPE_UINT32  : return "UInt32";
+    case FieldDescriptor::TYPE_SINT32  : return "SInt32";
+    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
+    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
+    case FieldDescriptor::TYPE_INT64   : return "Int64";
+    case FieldDescriptor::TYPE_UINT64  : return "UInt64";
+    case FieldDescriptor::TYPE_SINT64  : return "SInt64";
+    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
+    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT   : return "Float";
+    case FieldDescriptor::TYPE_DOUBLE  : return "Double";
+    case FieldDescriptor::TYPE_BOOL    : return "Bool";
+    case FieldDescriptor::TYPE_STRING  : return "String";
+    case FieldDescriptor::TYPE_BYTES   : {
+      return "Bytes";
+    }
+    case FieldDescriptor::TYPE_ENUM    : return "Enum";
+    case FieldDescriptor::TYPE_GROUP   : return "Group";
+    case FieldDescriptor::TYPE_MESSAGE : return "Message";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+// For encodings with fixed sizes, returns that size in bytes.  Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return -1;
+    case FieldDescriptor::TYPE_INT64   : return -1;
+    case FieldDescriptor::TYPE_UINT32  : return -1;
+    case FieldDescriptor::TYPE_UINT64  : return -1;
+    case FieldDescriptor::TYPE_SINT32  : return -1;
+    case FieldDescriptor::TYPE_SINT64  : return -1;
+    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
+
+    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
+    case FieldDescriptor::TYPE_ENUM    : return -1;
+
+    case FieldDescriptor::TYPE_STRING  : return -1;
+    case FieldDescriptor::TYPE_BYTES   : return -1;
+    case FieldDescriptor::TYPE_GROUP   : return -1;
+    case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;
+}
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it. The caller should delete the returned array.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+    new const FieldDescriptor*[descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByNumber());
+  return fields;
+}
+
+// Returns true if the message type has any required fields.  If it doesn't,
+// we can optimize out calls to its isInitialized() method.
+//
+// already_seen is used to avoid checking the same type multiple times
+// (and also to protect against recursion).
+bool HasRequiredFields(
+    const Descriptor* type,
+    hash_set<const Descriptor*>* already_seen) {
+  if (already_seen->count(type) > 0) {
+    // The type is already in cache.  This means that either:
+    // a. The type has no required fields.
+    // b. We are in the midst of checking if the type has required fields,
+    //    somewhere up the stack.  In this case, we know that if the type
+    //    has any required fields, they'll be found when we return to it,
+    //    and the whole call to HasRequiredFields() will return true.
+    //    Therefore, we don't have to check if this type has required fields
+    //    here.
+    return false;
+  }
+  already_seen->insert(type);
+
+  // If the type has extensions, an extension with message type could contain
+  // required fields, so we have to be conservative and assume such an
+  // extension exists.
+  if (type->extension_range_count() > 0) return true;
+
+  for (int i = 0; i < type->field_count(); i++) {
+    const FieldDescriptor* field = type->field(i);
+    if (field->is_required()) {
+      return true;
+    }
+    if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+      if (HasRequiredFields(field->message_type(), already_seen)) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool HasRequiredFields(const Descriptor* type) {
+  hash_set<const Descriptor*> already_seen;
+  return HasRequiredFields(type, &already_seen);
+}
+
+bool HasRepeatedFields(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (field->is_repeated()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.h
new file mode 100644
index 0000000..c850423
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_helpers.h
@@ -0,0 +1,352 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Commonly-used separator comments.  Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
+// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
+// "fooBarBaz" or "FooBarBaz", respectively.
+string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+
+// Similar, but for method names.  (Typically, this merely has the effect
+// of lower-casing the first letter of the name.)
+string UnderscoresToCamelCase(const MethodDescriptor* method);
+
+// Get an identifier that uniquely identifies this type within the file.
+// This is used to declare static variables related to this type at the
+// outermost file scope.
+string UniqueFileScopeIdentifier(const Descriptor* descriptor);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Gets the unqualified class name for the file.  For each .proto file, there
+// will be one Java class containing all the immutable messages and another
+// Java class containing all the mutable messages.
+// TODO(xiaofeng): remove the default value after updating client code.
+string FileClassName(const FileDescriptor* file, bool immutable = true);
+
+// Returns the file's Java package name.
+string FileJavaPackage(const FileDescriptor* file, bool immutable = true);
+
+// Returns output directory for the given package name.
+string JavaPackageToDir(string package_name);
+
+// Converts the given fully-qualified name in the proto namespace to its
+// fully-qualified name in the Java namespace, given that it is in the given
+// file.
+// TODO(xiaofeng): this method is deprecated and should be removed in the
+// future.
+string ToJavaName(const string& full_name,
+                  const FileDescriptor* file);
+
+// TODO(xiaofeng): the following methods are kept for they are exposed
+// publicly in //google/protobuf/compiler/java/names.h. They return
+// immutable names only and should be removed after mutable API is
+// integrated into google3.
+string ClassName(const Descriptor* descriptor);
+string ClassName(const EnumDescriptor* descriptor);
+string ClassName(const ServiceDescriptor* descriptor);
+string ClassName(const FileDescriptor* descriptor);
+
+// Comma-separate list of option-specified interfaces implemented by the
+// Message, to follow the "implements" declaration of the Message definition.
+string ExtraMessageInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces implemented by the
+// MutableMessage, to follow the "implements" declaration of the MutableMessage
+// definition.
+string ExtraMutableMessageInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces implemented by the
+// Builder, to follow the "implements" declaration of the Builder definition.
+string ExtraBuilderInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces extended by the
+// MessageOrBuilder, to follow the "extends" declaration of the
+// MessageOrBuilder definition.
+string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor);
+
+// Get the unqualified Java class name for mutable messages. i.e. without
+// package or outer classnames.
+inline string ShortMutableJavaClassName(const Descriptor* descriptor) {
+  return descriptor->name();
+}
+
+
+// Whether we should generate multiple java files for messages.
+inline bool MultipleJavaFiles(
+    const FileDescriptor* descriptor, bool immutable) {
+  return descriptor->options().java_multiple_files();
+}
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+string FieldConstantName(const FieldDescriptor *field);
+
+// Returns the type of the FieldDescriptor.
+// This does nothing interesting for the open source release, but is used for
+// hacks that improve compatibility with version 1 protocol buffers at Google.
+FieldDescriptor::Type GetType(const FieldDescriptor* field);
+
+enum JavaType {
+  JAVATYPE_INT,
+  JAVATYPE_LONG,
+  JAVATYPE_FLOAT,
+  JAVATYPE_DOUBLE,
+  JAVATYPE_BOOLEAN,
+  JAVATYPE_STRING,
+  JAVATYPE_BYTES,
+  JAVATYPE_ENUM,
+  JAVATYPE_MESSAGE
+};
+
+JavaType GetJavaType(const FieldDescriptor* field);
+
+const char* PrimitiveTypeName(JavaType type);
+
+// Get the fully-qualified class name for a boxed primitive type, e.g.
+// "java.lang.Integer" for JAVATYPE_INT.  Returns NULL for enum and message
+// types.
+const char* BoxedPrimitiveTypeName(JavaType type);
+
+// Get the name of the java enum constant representing this type. E.g.,
+// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full
+// name is "com.google.protobuf.WireFormat.FieldType.INT32".
+const char* FieldTypeName(const FieldDescriptor::Type field_type);
+
+class ClassNameResolver;
+string DefaultValue(const FieldDescriptor* field, bool immutable,
+                    ClassNameResolver* name_resolver);
+inline string ImmutableDefaultValue(const FieldDescriptor* field,
+                                    ClassNameResolver* name_resolver) {
+  return DefaultValue(field, true, name_resolver);
+}
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
+
+// Does this message have specialized equals() and hashCode() methods?
+inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
+  return descriptor->file()->options().java_generate_equals_and_hash();
+}
+
+// Does this message class have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const Descriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) {
+  return file->service_count() > 0 &&
+         HasDescriptorMethods(file, enforce_lite) &&
+         file->options().java_generic_services();
+}
+
+inline bool IsLazy(const FieldDescriptor* descriptor, bool enforce_lite) {
+  // Currently, the proto-lite version suports lazy field.
+  // TODO(niwasaki): Support lazy fields also for other proto runtimes.
+  if (HasDescriptorMethods(descriptor->file(), enforce_lite)) {
+    return false;
+  }
+  return descriptor->options().lazy();
+}
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given index.
+string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bitIndex / 32)
+string GetBitFieldNameForBit(int bitIndex);
+
+// Generates the java code for the expression that returns the boolean value
+// of the bit of the shared bitfields for the given bit index.
+// Example: "((bitField1_ & 0x04) == 0x04)"
+string GenerateGetBit(int bitIndex);
+
+// Generates the java code for the expression that sets the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ | 0x04)"
+string GenerateSetBit(int bitIndex);
+
+// Generates the java code for the expression that clears the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ & ~0x04)"
+string GenerateClearBit(int bitIndex);
+
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "((from_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitFromLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
+string GenerateSetBitToLocal(int bitIndex);
+
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "((mutable_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitMutableLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
+string GenerateSetBitMutableLocal(int bitIndex);
+
+// Returns whether the JavaType is a reference type.
+bool IsReferenceType(JavaType type);
+
+// Returns the capitalized name for calling relative functions in
+// CodedInputStream
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable);
+
+// For encodings with fixed sizes, returns that size in bytes.  Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type);
+
+// Comparators used to sort fields in MessageGenerator
+struct FieldOrderingByNumber {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    return a->number() < b->number();
+  }
+};
+
+struct ExtensionRangeOrdering {
+  bool operator()(const Descriptor::ExtensionRange* a,
+                  const Descriptor::ExtensionRange* b) const {
+    return a->start < b->start;
+  }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it. The caller should delete the returned array.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
+
+// Does this message class have any packed fields?
+inline bool HasPackedFields(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (descriptor->field(i)->is_packed()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Check a message type and its sub-message types recursively to see if any of
+// them has a required field. Return true if a required field is found.
+bool HasRequiredFields(const Descriptor* descriptor);
+
+// Whether a .proto file supports field presence test for non-message types.
+inline bool SupportFieldPresence(const FileDescriptor* descriptor) {
+  return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Whether generate classes expose public PARSER instances.
+inline bool ExposePublicParser(const FileDescriptor* descriptor) {
+  // TODO(liujisi): Mark the PARSER private in 3.1.x releases.
+  return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
+// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
+// but in the message and can be queried using additional getters that return
+// ints.
+inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) {
+  return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Check whether a mesasge has repeated fields.
+bool HasRepeatedFields(const Descriptor* descriptor);
+
+inline bool IsMapEntry(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
+inline bool IsMapField(const FieldDescriptor* descriptor) {
+  return descriptor->is_map();
+}
+
+inline bool PreserveUnknownFields(const Descriptor* descriptor) {
+  return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsAnyMessage(const Descriptor* descriptor) {
+  return descriptor->full_name() == "google.protobuf.Any";
+}
+
+inline bool CheckUtf8(const FieldDescriptor* descriptor) {
+  return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
+      descriptor->file()->options().java_string_check_utf8();
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.cc
new file mode 100644
index 0000000..0de8cbe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -0,0 +1,814 @@
+// 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.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableLazyMessageFieldGenerator::
+ImmutableLazyMessageFieldGenerator(
+    const FieldDescriptor* descriptor,
+    int messageBitIndex,
+    int builderBitIndex,
+    Context* context)
+    : ImmutableMessageFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
+    "    new com.google.protobuf.LazyFieldLite();\n");
+
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "  return $name$_;\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
+    "    new com.google.protobuf.LazyFieldLite();\n");
+
+  printer->Print(variables_,
+    // If this builder is non-null, it is used and the other fields are
+    // ignored.
+    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+    "\n");
+
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
+    "}\n");
+
+    printer->Print(variables_,
+      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
+      "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "$name$_.setValue(value);\n"
+    "$on_changed$\n",
+
+     NULL,  // Lazy fields are supported only for lite-runtime.
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "$name$_.setValue(builderForValue.build());\n"
+    "$on_changed$\n",
+
+    NULL,
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    "if ($get_has_field_bit_builder$ &&\n"
+    "    !$name$_.containsDefaultInstance()) {\n"
+    "  $name$_.setValue(\n"
+    "    $type$.newBuilder(\n"
+    "        get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+    "} else {\n"
+    "  $name$_.setValue(value);\n"
+    "}\n"
+    "$on_changed$\n",
+
+    NULL,
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_.clear();\n"
+    "$on_changed$\n",
+
+    NULL,
+
+    "$clear_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "  if ($name$Builder_ != null) {\n"
+    "    return $name$Builder_.getMessageOrBuilder();\n"
+    "  } else {\n"
+    "    return $name$_;\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> \n"
+    "    get$capitalized_name$FieldBuilder() {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+    "            $name$_,\n"
+    "            getParentForChildren(),\n"
+    "            isClean());\n"
+    "    $name$_ = null;\n"
+    "  }\n"
+    "  return $name$Builder_;\n"
+    "}\n");
+}
+
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.clear();\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.clear();\n");
+  printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  $name$_.merge(other.$name$_);\n"
+    "  $set_has_field_bit_builder$;\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+
+  printer->Print(variables_,
+      "result.$name$_.set(\n"
+      "    $name$_);\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+  printer->Print(variables_,
+    "$set_has_field_bit_message$;\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Do not de-serialize lazy fields.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeBytes($number$, $name$_.toByteString());\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, $name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+ImmutableLazyMessageOneofFieldGenerator::
+ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                        int messageBitIndex,
+                                        int builderBitIndex,
+                                        Context* context)
+    : ImmutableLazyMessageFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+  variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite";
+}
+
+ImmutableLazyMessageOneofFieldGenerator::
+~ImmutableLazyMessageOneofFieldGenerator() {}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
+    "        $type$.getDefaultInstance());\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
+    "        $type$.getDefaultInstance());\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "if (!($has_oneof_case_message$)) {\n"
+    "  $oneof_name$_ = new $lazy_type$();\n"
+    "  $set_oneof_case_message$;\n"
+    "}\n"
+    "(($lazy_type$) $oneof_name$_).setValue(value);\n"
+    "$on_changed$\n",
+
+     NULL,  // Lazy fields are supported only for lite-runtime.
+
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "if (!($has_oneof_case_message$)) {\n"
+    "  $oneof_name$_ = new $lazy_type$();\n"
+    "  $set_oneof_case_message$;\n"
+    "}\n"
+    "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n"
+    "$on_changed$\n",
+
+    NULL,
+
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    "if ($has_oneof_case_message$ &&\n"
+    "    !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n"
+    "  (($lazy_type$) $oneof_name$_).setValue(\n"
+    "    $type$.newBuilder(\n"
+    "        get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+    "} else {\n"
+    "  if (!($has_oneof_case_message$)) {\n"
+    "    $oneof_name$_ = new $lazy_type$();\n"
+    "    $set_oneof_case_message$;\n"
+    "  }\n"
+    "  (($lazy_type$) $oneof_name$_).setValue(value);\n"
+    "}\n"
+    "$on_changed$\n",
+
+    NULL,
+
+    "return this;\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  $clear_oneof_case_message$;\n"
+    "  $oneof_name$_ = null;\n"
+    "  $on_changed$\n"
+    "}\n",
+
+    NULL,
+
+    "return this;\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!($has_oneof_case_message$)) {\n"
+    "  $oneof_name$_ = new $lazy_type$();\n"
+    "}\n"
+    "(($lazy_type$) $oneof_name$_).merge(\n"
+    "    ($lazy_type$) other.$oneof_name$_);\n"
+    "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+                 "if ($has_oneof_case_message$) {\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+      "result.$oneof_name$_ = new $lazy_type$();\n"
+      "(($lazy_type$) result.$oneof_name$_).set(\n"
+      "    (($lazy_type$) $oneof_name$_));\n");
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!($has_oneof_case_message$)) {\n"
+    "  $oneof_name$_ = new $lazy_type$();\n"
+    "}\n"
+    "(($lazy_type$) $oneof_name$_).setByteString(\n"
+    "    input.readBytes(), extensionRegistry);\n"
+    "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Do not de-serialize lazy fields.
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.writeBytes(\n"
+    "      $number$, (($lazy_type$) $oneof_name$_).toByteString());\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableLazyMessageFieldGenerator::
+RepeatedImmutableLazyMessageFieldGenerator(
+    const FieldDescriptor* descriptor,
+    int messageBitIndex,
+    int builderBitIndex,
+    Context* context)
+    : RepeatedImmutableMessageFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+
+RepeatedImmutableLazyMessageFieldGenerator::
+~RepeatedImmutableLazyMessageFieldGenerator() {}
+
+void RepeatedImmutableLazyMessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  java.util.List<$type$> list =\n"
+    "      new java.util.ArrayList<$type$>($name$_.size());\n"
+    "  for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
+    "    list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
+    "  }\n"
+    "  return list;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder>\n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return get$capitalized_name$List();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return ($type$)\n"
+    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  return ($type$OrBuilder)\n"
+    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
+  printer->Print(variables_,
+    "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ =\n"
+    "        new java.util.ArrayList<com.google.protobuf.LazyFieldLite>(\n"
+    "            $name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n"
+    "\n");
+
+  printer->Print(variables_,
+    // If this builder is non-null, it is used and the other fields are
+    // ignored.
+    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+    "\n");
+
+  // The comments above the methods below are based on a hypothetical
+  // repeated field of type "Field" called "RepeatedField".
+
+  // List<Field> getRepeatedFieldList()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+
+    "java.util.List<$type$> list =\n"
+    "    new java.util.ArrayList<$type$>($name$_.size());\n"
+    "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
+    "  list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
+    "}\n"
+    "return java.util.Collections.unmodifiableList(list);\n",
+
+    "return $name$Builder_.getMessageList();\n",
+
+    NULL);
+
+  // int getRepeatedFieldCount()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public int get$capitalized_name$Count()",
+
+    "return $name$_.size();\n",
+    "return $name$Builder_.getCount();\n",
+
+    NULL);
+
+  // Field getRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$(int index)",
+
+    "return ($type$) $name$_.get(index).getValue(\n"
+    "    $type$.getDefaultInstance());\n",
+
+    "return $name$Builder_.getMessage(index);\n",
+
+    NULL);
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value)",
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+    "$on_changed$\n",
+    "$name$Builder_.setMessage(index, value);\n",
+    "return this;\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "    builderForValue.build()));\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "    builderForValue.build()));\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "    builderForValue.build()));\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "for (com.google.protobuf.MessageLite v : values) {\n"
+    "  $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n"
+    "}\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addAllMessages(values);\n",
+
+    "return this;\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "return this;\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder remove$capitalized_name$(int index)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.remove(index);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.remove(index);\n",
+
+    "return this;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+    "    int index) {\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    return $name$_.get(index);"
+    "  } else {\n"
+    "    return $name$Builder_.getMessageOrBuilder(index);\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "     get$capitalized_name$OrBuilderList() {\n"
+    "  if ($name$Builder_ != null) {\n"
+    "    return $name$Builder_.getMessageOrBuilderList();\n"
+    "  } else {\n"
+    "    return java.util.Collections.unmodifiableList($name$_);\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+    "      $type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+    "    int index) {\n"
+    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+    "      index, $type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$.Builder> \n"
+    "     get$capitalized_name$BuilderList() {\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+    "}\n"
+    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> \n"
+    "    get$capitalized_name$FieldBuilder() {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+    "            $name$_,\n"
+    "            $get_mutable_bit_builder$,\n"
+    "            getParentForChildren(),\n"
+    "            isClean());\n"
+    "    $name$_ = null;\n"
+    "  }\n"
+    "  return $name$Builder_;\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ =\n"
+    "      new java.util.ArrayList<com.google.protobuf.LazyFieldLite>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
+    "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
+    "    extensionRegistry, input.readBytes()));\n");
+}
+
+void RepeatedImmutableLazyMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.writeBytes($number$, $name$_.get(i).toByteString());\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.h
new file mode 100644
index 0000000..b1b7f28
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field.h
@@ -0,0 +1,121 @@
+// 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.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;  // context.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableLazyMessageFieldGenerator
+    : public ImmutableMessageFieldGenerator {
+ public:
+  explicit ImmutableLazyMessageFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableLazyMessageFieldGenerator();
+
+  // overroads ImmutableMessageFieldGenerator ---------------------------------
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator);
+};
+
+class ImmutableLazyMessageOneofFieldGenerator
+    : public ImmutableLazyMessageFieldGenerator {
+ public:
+  ImmutableLazyMessageOneofFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableLazyMessageOneofFieldGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator);
+};
+
+class RepeatedImmutableLazyMessageFieldGenerator
+    : public RepeatedImmutableMessageFieldGenerator {
+ public:
+  explicit RepeatedImmutableLazyMessageFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableLazyMessageFieldGenerator();
+
+  // overroads RepeatedImmutableMessageFieldGenerator -------------------------
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
new file mode 100644
index 0000000..62f3930
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -0,0 +1,706 @@
+// 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.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableLazyMessageFieldLiteGenerator::
+ImmutableLazyMessageFieldLiteGenerator(
+    const FieldDescriptor* descriptor,
+    int messageBitIndex,
+    int builderBitIndex,
+    Context* context)
+    : ImmutableMessageFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+ImmutableLazyMessageFieldLiteGenerator::
+~ImmutableLazyMessageFieldLiteGenerator() {}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
+    "    new com.google.protobuf.LazyFieldLite();\n");
+
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
+   "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $name$_.setValue(value);\n"
+    "  $set_has_field_bit_message$;\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  $name$_.setValue(builderForValue.build());\n"
+    "  $set_has_field_bit_message$;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void merge$capitalized_name$($type$ value) {\n"
+    "  if ($get_has_field_bit_message$ &&\n"
+    "      !$name$_.containsDefaultInstance()) {\n"
+    "    $name$_.setValue(\n"
+    "      $type$.newBuilder(\n"
+    "          get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+    "  } else {\n"
+    "    $name$_.setValue(value);\n"
+    "  }\n"
+    "  $set_has_field_bit_message$;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_.clear();\n"
+    "  $clear_has_field_bit_message$;\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return instance.has$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.merge$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.clear();\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = visitor.visitLazyMessage(\n"
+    "    has$capitalized_name$(), $name$_,\n"
+    "    other.has$capitalized_name$(), other.$name$_);\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.mergeFrom(input, extensionRegistry);\n");
+  printer->Print(variables_,
+    "$set_has_field_bit_message$;\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Do not de-serialize lazy fields.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeBytes($number$, $name$_.toByteString());\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, $name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                            int messageBitIndex,
+                                            int builderBitIndex,
+                                            Context* context)
+    : ImmutableLazyMessageFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+  variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite";
+}
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+~ImmutableLazyMessageOneofFieldLiteGenerator() {}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
+    "        $type$.getDefaultInstance());\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  if (!($has_oneof_case_message$)) {\n"
+    "    $oneof_name$_ = new $lazy_type$();\n"
+    "    $set_oneof_case_message$;\n"
+    "  }\n"
+    "  (($lazy_type$) $oneof_name$_).setValue(value);\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  if (!($has_oneof_case_message$)) {\n"
+    "    $oneof_name$_ = new $lazy_type$();\n"
+    "    $set_oneof_case_message$;\n"
+    "  }\n"
+    "  (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void merge$capitalized_name$($type$ value) {\n"
+    "  if ($has_oneof_case_message$ &&\n"
+    "      !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n"
+    "    (($lazy_type$) $oneof_name$_).setValue(\n"
+    "       $type$.newBuilder(\n"
+    "          get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+    "  } else {\n"
+    "    if (!($has_oneof_case_message$)) {\n"
+    "      $oneof_name$_ = new $lazy_type$();\n"
+    "      $set_oneof_case_message$;\n"
+    "    }\n"
+    "    (($lazy_type$) $oneof_name$_).setValue(value);\n"
+    "  }\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return instance.has$capitalized_name$();\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.merge$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$oneof_name$_ = visitor.visitOneofLazyMessage(\n"
+    "    $has_oneof_case_message$,\n"
+    "    ($lazy_type$) $oneof_name$_,\n"
+    "    ($lazy_type$) other.$oneof_name$_);\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!($has_oneof_case_message$)) {\n"
+    "  $oneof_name$_ = new $lazy_type$();\n"
+    "}\n"
+    "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n"
+    "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Do not de-serialize lazy fields.
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.writeBytes(\n"
+    "      $number$, (($lazy_type$) $oneof_name$_).toByteString());\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+RepeatedImmutableLazyMessageFieldLiteGenerator(
+    const FieldDescriptor* descriptor,
+    int messageBitIndex,
+    int builderBitIndex,
+    Context* context)
+    : RepeatedImmutableMessageFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+~RepeatedImmutableLazyMessageFieldLiteGenerator() {}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.Internal.ProtobufList<\n"
+    "    com.google.protobuf.LazyFieldLite> $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  java.util.List<$type$> list =\n"
+    "      new java.util.ArrayList<$type$>($name$_.size());\n"
+    "  for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
+    "    list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
+    "  }\n"
+    // TODO(dweis): Make this list immutable?
+    "  return list;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder>\n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return get$capitalized_name$List();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return ($type$)\n"
+    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  return ($type$OrBuilder)\n"
+    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$is_mutable$) {\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "   }\n"
+    "}\n"
+    "\n");
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(\n"
+    "      index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "      builderForValue.build()));\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(\n"
+    "      index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "      builderForValue.build()));\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+    "      builderForValue.build()));\n"
+    "}\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  for (com.google.protobuf.MessageLite v : values) {\n"
+    "    $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n"
+    "  }\n"
+    "}\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_ = emptyProtobufList();\n"
+    "}\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void remove$capitalized_name$(int index) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.remove(index);\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // List<Field> getRepeatedFieldList()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList(\n"
+    "      instance.get$capitalized_name$List());\n"
+    "}\n");
+
+  // int getRepeatedFieldCount()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return instance.get$capitalized_name$Count();\n"
+    "}\n");
+
+  // Field getRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return instance.get$capitalized_name$(index);\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(index, builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  copyOnWrite();\n"
+    "  instance.addAll$capitalized_name$(values);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+    "  copyOnWrite();\n"
+    "  instance.remove$capitalized_name$(index);\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n"
+    "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
+    "    extensionRegistry, input.readBytes()));\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.writeBytes($number$, $name$_.get(i).toByteString());\n"
+    "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeLazyFieldSize($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
new file mode 100644
index 0000000..47ebeb4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
@@ -0,0 +1,118 @@
+// 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.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;  // context.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableLazyMessageFieldLiteGenerator
+    : public ImmutableMessageFieldLiteGenerator {
+ public:
+  explicit ImmutableLazyMessageFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableLazyMessageFieldLiteGenerator();
+
+  // overroads ImmutableMessageFieldLiteGenerator ------------------------------
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator);
+};
+
+class ImmutableLazyMessageOneofFieldLiteGenerator
+    : public ImmutableLazyMessageFieldLiteGenerator {
+ public:
+  ImmutableLazyMessageOneofFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableLazyMessageOneofFieldLiteGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableLazyMessageFieldLiteGenerator
+    : public RepeatedImmutableMessageFieldLiteGenerator {
+ public:
+  explicit RepeatedImmutableLazyMessageFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableLazyMessageFieldLiteGenerator();
+
+  // overroads RepeatedImmutableMessageFieldLiteGenerator ----------------------
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.cc
new file mode 100644
index 0000000..2a551ca
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.cc
@@ -0,0 +1,497 @@
+// 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.
+
+#include <google/protobuf/compiler/java/java_map_field.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("value");
+}
+
+string TypeName(const FieldDescriptor* field,
+                ClassNameResolver* name_resolver,
+                bool boxed) {
+  if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+    return name_resolver->GetImmutableClassName(field->message_type());
+  } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+    return name_resolver->GetImmutableClassName(field->enum_type());
+  } else {
+    return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+                 : PrimitiveTypeName(GetJavaType(field));
+  }
+}
+
+string WireType(const FieldDescriptor* field) {
+  return "com.google.protobuf.WireFormat.FieldType." +
+      string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
+                         const FieldGeneratorInfo* info,
+                         Context* context,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+  ClassNameResolver* name_resolver = context->GetNameResolver();
+
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->message_type());
+  const FieldDescriptor* key = KeyField(descriptor);
+  const FieldDescriptor* value = ValueField(descriptor);
+  (*variables)["key_type"] = TypeName(key, name_resolver, false);
+  (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+  (*variables)["key_wire_type"] = WireType(key);
+  (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+  if (GetJavaType(value) == JAVATYPE_ENUM) {
+    // We store enums as Integers internally.
+    (*variables)["value_type"] = "int";
+    (*variables)["boxed_value_type"] = "java.lang.Integer";
+    (*variables)["value_wire_type"] = WireType(value);
+    (*variables)["value_default_value"] =
+        DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+    (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+    if (SupportUnknownEnumValue(descriptor->file())) {
+      // Map unknown values to a special UNRECOGNIZED value if supported.
+      (*variables)["unrecognized_value"] =
+          (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+    } else {
+      // Map unknown values to the default value if we don't have UNRECOGNIZED.
+      (*variables)["unrecognized_value"] =
+          DefaultValue(value, true, name_resolver);
+    }
+  } else {
+    (*variables)["value_type"] = TypeName(value, name_resolver, false);
+    (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+    (*variables)["value_wire_type"] = WireType(value);
+    (*variables)["value_default_value"] =
+        DefaultValue(value, true, name_resolver);
+  }
+  (*variables)["type_parameters"] =
+      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] = "onChanged();";
+
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
+  (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+      "DefaultEntryHolder.defaultEntry";
+  (*variables)["lite"] = "";
+  (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+  (*variables)["descriptor"] =
+      name_resolver->GetImmutableClassName(descriptor->file()) +
+      ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+      "_descriptor, ";
+}
+
+}  // namespace
+
+ImmutableMapFieldGenerator::
+ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
+                                       int messageBitIndex,
+                                       int builderBitIndex,
+                                       Context* context)
+  : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      context->GetFieldGeneratorInfo(descriptor),
+                      context, &variables_);
+}
+
+ImmutableMapFieldGenerator::
+~ImmutableMapFieldGenerator() {}
+
+int ImmutableMapFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$();\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$java.util.Map<$type_parameters$>\n"
+          "get$capitalized_name$Value();\n");
+    }
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$java.util.Map<$type_parameters$>\n"
+        "get$capitalized_name$();\n");
+  }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "private static final class $capitalized_name$DefaultEntryHolder {\n"
+      "  static final com.google.protobuf.MapEntry$lite$<\n"
+      "      $type_parameters$> defaultEntry =\n"
+      "          com.google.protobuf.MapEntry$lite$\n"
+      "          .<$type_parameters$>newDefaultInstance(\n"
+      "              $descriptor$\n"
+      "              $key_wire_type$,\n"
+      "              $key_default_value$,\n"
+      "              $value_wire_type$,\n"
+      "              $value_default_value$);\n"
+      "}\n");
+  printer->Print(
+      variables_,
+      "private com.google.protobuf.MapField$lite$<\n"
+      "    $type_parameters$> $name$_;\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGet$capitalized_name$() {\n"
+      "  if ($name$_ == null) {\n"
+      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "        $map_field_parameter$);\n"
+      "  }\n"
+      "  return $name$_;\n"
+      "}\n");
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "private static final\n"
+        "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+        "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+        "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+        "            $value_enum_type$.internalGetValueMap(),\n"
+        "            $unrecognized_value$);\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "get$capitalized_name$Value() {\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
+          "}\n");
+    }
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$() {\n"
+        "  return new com.google.protobuf.Internal.MapAdapter<\n"
+        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "          internalGet$capitalized_name$().getMap(),\n"
+        "          $name$ValueConverter);\n"
+        "}\n");
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
+        "}\n");
+  }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "private com.google.protobuf.MapField$lite$<\n"
+      "    $type_parameters$> $name$_;\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGet$capitalized_name$() {\n"
+      "  if ($name$_ == null) {\n"
+      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "        $map_field_parameter$);\n"
+      "  }\n"
+      "  return $name$_;\n"
+      "}\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGetMutable$capitalized_name$() {\n"
+      "  $on_changed$;\n"
+      "  if ($name$_ == null) {\n"
+      "    $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+      "        $map_field_parameter$);\n"
+      "  }\n"
+      "  if (!$name$_.isMutable()) {\n"
+      "    $name$_ = $name$_.copy();\n"
+      "  }\n"
+      "  return $name$_;\n"
+      "}\n");
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$() {\n"
+        "  return new com.google.protobuf.Internal.MapAdapter<\n"
+        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "          internalGet$capitalized_name$().getMap(),\n"
+        "          $name$ValueConverter);\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  return new com.google.protobuf.Internal.MapAdapter<\n"
+        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
+        "          $name$ValueConverter);\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "get$capitalized_name$Value() {\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
+          "}\n");
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "getMutable$capitalized_name$Value() {\n"
+          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+          "}\n");
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+          "  getMutable$capitalized_name$Value().putAll(values);\n"
+          "  return this;\n"
+          "}\n");
+    }
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "public java.util.Map<$type_parameters$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "    java.util.Map<$type_parameters$> values) {\n"
+        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+  }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "internalGetMutable$capitalized_name$().clear();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "internalGetMutable$capitalized_name$().mergeFrom(\n"
+      "    other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "result.$name$_ = internalGet$capitalized_name$();\n"
+      "result.$name$_.makeImmutable();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "if (!$get_mutable_bit_parser$) {\n"
+      "  $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+      "      $map_field_parameter$);\n"
+      "  $set_mutable_bit_parser$;\n"
+      "}\n");
+  if (!SupportUnknownEnumValue(descriptor_->file()) &&
+      GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+        "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+    printer->Print(
+        variables_,
+        "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
+        "  unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+        "} else {\n"
+        "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+        "}\n");
+  } else {
+    printer->Print(
+        variables_,
+        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+        "$name$ = input.readMessage(\n"
+        "    $default_entry$.getParserForType(), extensionRegistry);\n"
+        "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+  }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // Nothing to do here.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "for (java.util.Map.Entry<$type_parameters$> entry\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+      "  $name$ = $default_entry$.newBuilderForType()\n"
+      "      .setKey(entry.getKey())\n"
+      "      .setValue(entry.getValue())\n"
+      "      .build();\n"
+      "  output.writeMessage($number$, $name$);\n"
+      "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "for (java.util.Map.Entry<$type_parameters$> entry\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+      "  $name$ = $default_entry$.newBuilderForType()\n"
+      "      .setKey(entry.getKey())\n"
+      "      .setValue(entry.getValue())\n"
+      "      .build();\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeMessageSize($number$, $name$);\n"
+      "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "result = result && internalGet$capitalized_name$().equals(\n"
+      "    other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+      "  hash = (37 * hash) + $constant_name$;\n"
+      "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
+      "}\n");
+}
+
+string ImmutableMapFieldGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.h
new file mode 100644
index 0000000..f2768f3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field.h
@@ -0,0 +1,79 @@
+// 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_COMPILER_JAVA_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit ImmutableMapFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMapFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  ClassNameResolver* name_resolver_;
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.cc
new file mode 100644
index 0000000..b80d413
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -0,0 +1,482 @@
+// 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.
+
+#include <google/protobuf/compiler/java/java_map_field_lite.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("value");
+}
+
+string TypeName(const FieldDescriptor* field,
+                ClassNameResolver* name_resolver,
+                bool boxed) {
+  if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+    return name_resolver->GetImmutableClassName(field->message_type());
+  } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+    return name_resolver->GetImmutableClassName(field->enum_type());
+  } else {
+    return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+                 : PrimitiveTypeName(GetJavaType(field));
+  }
+}
+
+string WireType(const FieldDescriptor* field) {
+  return "com.google.protobuf.WireFormat.FieldType." +
+      string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
+                         const FieldGeneratorInfo* info,
+                         Context* context,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  ClassNameResolver* name_resolver = context->GetNameResolver();
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->message_type());
+  const FieldDescriptor* key = KeyField(descriptor);
+  const FieldDescriptor* value = ValueField(descriptor);
+  (*variables)["key_type"] = TypeName(key, name_resolver, false);
+  (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+  (*variables)["key_wire_type"] = WireType(key);
+  (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+  if (GetJavaType(value) == JAVATYPE_ENUM) {
+    // We store enums as Integers internally.
+    (*variables)["value_type"] = "int";
+    (*variables)["boxed_value_type"] = "java.lang.Integer";
+    (*variables)["value_wire_type"] = WireType(value);
+    (*variables)["value_default_value"] =
+        DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+    (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+    if (SupportUnknownEnumValue(descriptor->file())) {
+      // Map unknown values to a special UNRECOGNIZED value if supported.
+      (*variables)["unrecognized_value"] =
+          (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+    } else {
+      // Map unknown values to the default value if we don't have UNRECOGNIZED.
+      (*variables)["unrecognized_value"] =
+          DefaultValue(value, true, name_resolver);
+    }
+  } else {
+    (*variables)["value_type"] = TypeName(value, name_resolver, false);
+    (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+    (*variables)["value_wire_type"] = WireType(value);
+    (*variables)["value_default_value"] =
+        DefaultValue(value, true, name_resolver);
+  }
+  (*variables)["type_parameters"] =
+      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+
+  (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+      "DefaultEntryHolder.defaultEntry";
+  (*variables)["lite"] = "Lite";
+  (*variables)["descriptor"] = "";
+}
+
+}  // namespace
+
+ImmutableMapFieldLiteGenerator::
+ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                       int messageBitIndex,
+                                       int builderBitIndex,
+                                       Context* context)
+  : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      context->GetFieldGeneratorInfo(descriptor),
+                      context, &variables_);
+}
+
+ImmutableMapFieldLiteGenerator::
+~ImmutableMapFieldLiteGenerator() {}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$();\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$java.util.Map<$type_parameters$>\n"
+          "get$capitalized_name$Value();\n");
+    }
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$java.util.Map<$type_parameters$>\n"
+        "get$capitalized_name$();\n");
+  }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "private static final class $capitalized_name$DefaultEntryHolder {\n"
+      "  static final com.google.protobuf.MapEntry$lite$<\n"
+      "      $type_parameters$> defaultEntry =\n"
+      "          com.google.protobuf.MapEntry$lite$\n"
+      "          .<$type_parameters$>newDefaultInstance(\n"
+      "              $descriptor$\n"
+      "              $key_wire_type$,\n"
+      "              $key_default_value$,\n"
+      "              $value_wire_type$,\n"
+      "              $value_default_value$);\n"
+      "}\n");
+  printer->Print(
+      variables_,
+      "private com.google.protobuf.MapField$lite$<\n"
+      "    $type_parameters$> $name$_ =\n"
+      "        com.google.protobuf.MapField$lite$.emptyMapField();\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGet$capitalized_name$() {\n"
+      "  return $name$_;\n"
+      "}\n"
+      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "internalGetMutable$capitalized_name$() {\n"
+      "  if (!$name$_.isMutable()) {\n"
+      "    $name$_ = $name$_.copy();\n"
+      "  }\n"
+      "  return $name$_;\n"
+      "}\n");
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "private static final\n"
+        "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+        "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+        "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+        "            $value_enum_type$.internalGetValueMap(),\n"
+        "            $unrecognized_value$);\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "get$capitalized_name$Value() {\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
+          "}\n");
+    }
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$() {\n"
+        "  return new com.google.protobuf.Internal.MapAdapter<\n"
+        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "          internalGet$capitalized_name$().getMap(),\n"
+        "          $name$ValueConverter);\n"
+        "}\n");
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
+        "}\n");
+  }
+
+  // Generate private setters for the builder to proxy into.
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  return new com.google.protobuf.Internal.MapAdapter<\n"
+        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
+        "          $name$ValueConverter);\n"
+        "}\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "getMutable$capitalized_name$Value() {\n"
+          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+          "}\n");
+    }
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "private java.util.Map<$type_parameters$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+        "}\n");
+  }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "get$capitalized_name$() {\n"
+        "  return instance.get$capitalized_name$();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  copyOnWrite();\n"
+        "  return instance.getMutable$capitalized_name$();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "get$capitalized_name$Value() {\n"
+          "  return instance.get$capitalized_name$Value();\n"
+          "}\n");
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "getMutable$capitalized_name$Value() {\n"
+          "  copyOnWrite();\n"
+          "  return instance.getMutable$capitalized_name$Value();\n"
+          "}\n");
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+          "  getMutable$capitalized_name$Value().putAll(values);\n"
+          "  return this;\n"
+          "}\n");
+    }
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "  return instance.get$capitalized_name$();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "public java.util.Map<$type_parameters$>\n"
+        "getMutable$capitalized_name$() {\n"
+        "  copyOnWrite();\n"
+        "  return instance.getMutable$capitalized_name$();\n"
+        "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "public Builder putAll$capitalized_name$(\n"
+        "    java.util.Map<$type_parameters$> values) {\n"
+        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+  }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "$name$_ = visitor.visitMap(internalGetMutable$capitalized_name$(),\n"
+      "    other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.makeImmutable();\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "if (!$name$_.isMutable()) {\n"
+      "  $name$_ = $name$_.copy();\n"
+      "}\n");
+  if (!SupportUnknownEnumValue(descriptor_->file()) &&
+      GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+        "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+    printer->Print(
+        variables_,
+        "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
+        "  super.mergeLengthDelimitedField($number$, bytes);\n"
+        "} else {\n"
+        "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+        "}\n");
+  } else {
+    printer->Print(
+        variables_,
+        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+        "$name$ = input.readMessage(\n"
+        "    $default_entry$.getParserForType(), extensionRegistry);\n"
+        "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+  }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // Nothing to do here.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "for (java.util.Map.Entry<$type_parameters$> entry\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+      "  $name$ = $default_entry$.newBuilderForType()\n"
+      "      .setKey(entry.getKey())\n"
+      "      .setValue(entry.getValue())\n"
+      "      .build();\n"
+      "  output.writeMessage($number$, $name$);\n"
+      "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "for (java.util.Map.Entry<$type_parameters$> entry\n"
+      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+      "  $name$ = $default_entry$.newBuilderForType()\n"
+      "      .setKey(entry.getKey())\n"
+      "      .setValue(entry.getValue())\n"
+      "      .build();\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeMessageSize($number$, $name$);\n"
+      "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "result = result && internalGet$capitalized_name$().equals(\n"
+      "    other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+      "  hash = (37 * hash) + $constant_name$;\n"
+      "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
+      "}\n");
+}
+
+string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.h
new file mode 100644
index 0000000..555b5c5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -0,0 +1,78 @@
+// 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_COMPILER_JAVA_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+  explicit ImmutableMapFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMapFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  ClassNameResolver* name_resolver_;
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.cc
new file mode 100644
index 0000000..4c474a4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.cc
@@ -0,0 +1,1450 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message.h>
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message_builder.h>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+  return SupportFieldPresence(descriptor->file()) ||
+      HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+                                   ClassNameResolver* name_resolver) {
+  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+  return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+}  // namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor)
+  : descriptor_(descriptor) {}
+
+MessageGenerator::~MessageGenerator() {}
+
+// ===================================================================
+ImmutableMessageGenerator::ImmutableMessageGenerator(
+    const Descriptor* descriptor, Context* context)
+  : MessageGenerator(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()),
+    field_generators_(descriptor, context_) {
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
+}
+
+ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
+
+void ImmutableMessageGenerator::GenerateStaticVariables(
+    io::Printer* printer, int* bytecode_estimate) {
+  // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
+  // used in the construction of descriptors, we have a tricky bootstrapping
+  // problem.  To help control static initialization order, we make sure all
+  // descriptors and other static data that depends on them are members of
+  // the outermost class in the file.  This way, they will be initialized in
+  // a deterministic order.
+
+  map<string, string> vars;
+  vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+  vars["index"] = SimpleItoa(descriptor_->index());
+  vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+  if (descriptor_->containing_type() != NULL) {
+    vars["parent"] = UniqueFileScopeIdentifier(
+        descriptor_->containing_type());
+  }
+  if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+    // We can only make these package-private since the classes that use them
+    // are in separate files.
+    vars["private"] = "";
+  } else {
+    vars["private"] = "private ";
+  }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
+
+  // The descriptor for this type.
+  printer->Print(vars,
+    // TODO(teboring): final needs to be added back. The way to fix it is to
+    // generate methods that can construct the types, and then still declare the
+    // types, and then init them in clinit with the new method calls.
+    "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
+    "  internal_$identifier$_descriptor;\n");
+  *bytecode_estimate += 30;
+
+  // And the FieldAccessorTable.
+  GenerateFieldAccessorTable(printer, bytecode_estimate);
+
+  // Generate static members for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+        .GenerateStaticVariables(printer, bytecode_estimate);
+  }
+}
+
+int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
+    io::Printer* printer) {
+  int bytecode_estimate = 0;
+  map<string, string> vars;
+  vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+  vars["index"] = SimpleItoa(descriptor_->index());
+  vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+  if (descriptor_->containing_type() != NULL) {
+    vars["parent"] = UniqueFileScopeIdentifier(
+        descriptor_->containing_type());
+  }
+
+  // The descriptor for this type.
+  if (descriptor_->containing_type() == NULL) {
+    printer->Print(vars,
+      "internal_$identifier$_descriptor =\n"
+      "  getDescriptor().getMessageTypes().get($index$);\n");
+    bytecode_estimate += 30;
+  } else {
+    printer->Print(vars,
+      "internal_$identifier$_descriptor =\n"
+      "  internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+    bytecode_estimate += 30;
+  }
+
+  // And the FieldAccessorTable.
+  bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
+
+  // Generate static member initializers for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    bytecode_estimate +=
+        ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+            .GenerateStaticVariableInitializers(printer);
+  }
+  return bytecode_estimate;
+}
+
+void ImmutableMessageGenerator::
+GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
+  map<string, string> vars;
+  vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+  if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+    // We can only make these package-private since the classes that use them
+    // are in separate files.
+    vars["private"] = "";
+  } else {
+    vars["private"] = "private ";
+  }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
+  printer->Print(vars,
+    "$private$static $final$\n"
+    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "    internal_$identifier$_fieldAccessorTable;\n");
+
+  // 6 bytes per field and oneof
+  *bytecode_estimate += 10 + 6 * descriptor_->field_count()
+      + 6 * descriptor_->oneof_decl_count();
+}
+
+int ImmutableMessageGenerator::
+GenerateFieldAccessorTableInitializer(io::Printer* printer) {
+  int bytecode_estimate = 10;
+  printer->Print(
+    "internal_$identifier$_fieldAccessorTable = new\n"
+    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
+    "    internal_$identifier$_descriptor,\n"
+    "    new java.lang.String[] { ",
+    "identifier",
+    UniqueFileScopeIdentifier(descriptor_));
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+    bytecode_estimate += 6;
+    printer->Print(
+      "\"$field_name$\", ",
+      "field_name", info->capitalized_name);
+  }
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
+    bytecode_estimate += 6;
+    printer->Print(
+      "\"$oneof_name$\", ",
+      "oneof_name", info->capitalized_name);
+  }
+  printer->Print("});\n");
+  return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "public interface $classname$OrBuilder extends\n"
+      "    $extra_interfaces$\n"
+      "    com.google.protobuf.GeneratedMessage.\n"
+      "        ExtendableMessageOrBuilder<$classname$> {\n",
+      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "public interface $classname$OrBuilder extends\n"
+      "    $extra_interfaces$\n"
+      "    com.google.protobuf.MessageOrBuilder {\n",
+      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+      "classname", descriptor_->name());
+  }
+
+  printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      printer->Print("\n");
+      field_generators_.get(descriptor_->field(i))
+                       .GenerateInterfaceMembers(printer);
+    }
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+      printer->Print(
+          "\n"
+          "public $classname$.$oneof_capitalized_name$Case "
+          "get$oneof_capitalized_name$Case();\n",
+          "oneof_capitalized_name",
+          context_->GetOneofGeneratorInfo(
+              descriptor_->oneof_decl(i))->capitalized_name,
+          "classname",
+          context_->GetNameResolver()->GetImmutableClassName(
+              descriptor_));
+    }
+  printer->Outdent();
+
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::Generate(io::Printer* printer) {
+  bool is_own_file =
+    descriptor_->containing_type() == NULL &&
+    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+
+  map<string, string> variables;
+  variables["static"] = is_own_file ? " " : " static ";
+  variables["classname"] = descriptor_->name();
+  variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+
+  WriteMessageDocComment(printer, descriptor_);
+
+  // The builder_type stores the super type name of the nested Builder class.
+  string builder_type;
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(variables,
+      "public $static$final class $classname$ extends\n"
+      "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
+      "      $classname$> implements\n"
+      "    $extra_interfaces$\n"
+      "    $classname$OrBuilder {\n");
+    builder_type = strings::Substitute(
+             "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
+             name_resolver_->GetImmutableClassName(descriptor_));
+  } else {
+    printer->Print(variables,
+      "public $static$final class $classname$ extends\n"
+      "    com.google.protobuf.GeneratedMessage implements\n"
+      "    $extra_interfaces$\n"
+      "    $classname$OrBuilder {\n");
+    builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
+  }
+  printer->Indent();
+  // Using builder_type, instead of Builder, prevents the Builder class from
+  // being loaded into PermGen space when the default instance is created.
+  // This optimizes the PermGen space usage for clients that do not modify
+  // messages.
+  printer->Print(
+    "// Use $classname$.newBuilder() to construct.\n"
+    "private $classname$($buildertype$ builder) {\n"
+    "  super(builder);\n"
+    "}\n",
+    "classname", descriptor_->name(),
+    "buildertype", builder_type);
+  printer->Print(
+    "private $classname$() {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+  GenerateInitializers(printer);
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "public final com.google.protobuf.UnknownFieldSet\n"
+    "getUnknownFields() {\n");
+  if (PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "  return this.unknownFields;\n");
+  } else {
+    printer->Print(
+      "  return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
+  }
+  printer->Print(
+    "}\n");
+
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    GenerateParsingConstructor(printer);
+  }
+
+  GenerateDescriptorMethods(printer);
+
+  // Nested types
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    EnumGenerator(descriptor_->enum_type(i), true, context_)
+        .Generate(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // Don't generate Java classes for map entry messages.
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageGenerator messageGenerator(
+        descriptor_->nested_type(i), context_);
+    messageGenerator.GenerateInterface(printer);
+    messageGenerator.Generate(printer);
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Integers for bit fields.
+    int totalBits = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      totalBits += field_generators_.get(descriptor_->field(i))
+          .GetNumBitsForMessage();
+    }
+    int totalInts = (totalBits + 31) / 32;
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print("private int $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  // oneof
+  map<string, string> vars;
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->name;
+    vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->capitalized_name;
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    // oneofCase_ and oneof_
+    printer->Print(vars,
+      "private int $oneof_name$Case_ = 0;\n"
+      "private java.lang.Object $oneof_name$_;\n");
+    // OneofCase enum
+    printer->Print(vars,
+      "public enum $oneof_capitalized_name$Case\n"
+      "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "$field_name$($field_number$),\n",
+        "field_name",
+        ToUpper(field->name()),
+        "field_number",
+        SimpleItoa(field->number()));
+    }
+    printer->Print(
+      "$cap_oneof_name$_NOT_SET(0);\n",
+      "cap_oneof_name",
+      ToUpper(vars["oneof_name"]));
+    printer->Print(vars,
+      "private final int value;\n"
+      "private $oneof_capitalized_name$Case(int value) {\n"
+      "  this.value = value;\n"
+      "}\n");
+    printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
+      "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
+      "  switch (value) {\n");
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "    case $field_number$: return $field_name$;\n",
+        "field_number",
+        SimpleItoa(field->number()),
+        "field_name",
+        ToUpper(field->name()));
+    }
+    printer->Print(
+      "    case 0: return $cap_oneof_name$_NOT_SET;\n"
+      "    default: return null;\n"
+      "  }\n"
+      "}\n"
+      "public int getNumber() {\n"
+      "  return this.value;\n"
+      "}\n",
+      "cap_oneof_name", ToUpper(vars["oneof_name"]));
+    printer->Outdent();
+    printer->Print("};\n\n");
+    // oneofCase()
+    printer->Print(vars,
+      "public $oneof_capitalized_name$Case\n"
+      "get$oneof_capitalized_name$Case() {\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
+      "      $oneof_name$Case_);\n"
+      "}\n"
+      "\n");
+  }
+
+  if (IsAnyMessage(descriptor_)) {
+    GenerateAnyMethods(printer);
+  }
+
+  // Fields
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("public static final int $constant_name$ = $number$;\n",
+      "constant_name", FieldConstantName(descriptor_->field(i)),
+      "number", SimpleItoa(descriptor_->field(i)->number()));
+    field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+    printer->Print("\n");
+  }
+
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    GenerateIsInitialized(printer);
+    GenerateMessageSerializationMethods(printer);
+  }
+
+  if (HasEqualsAndHashCode(descriptor_)) {
+    GenerateEqualsAndHashCode(printer);
+  }
+
+
+  GenerateParseFromMethods(printer);
+  GenerateBuilder(printer);
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+
+  // Carefully initialize the default instance in such a way that it doesn't
+  // conflict with other initialization.
+  printer->Print(
+    "private static final $classname$ DEFAULT_INSTANCE;\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  printer->Print(
+    "static {\n"
+    "  DEFAULT_INSTANCE = new $classname$();\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+      "public static $classname$ getDefaultInstance() {\n"
+      "  return DEFAULT_INSTANCE;\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  GenerateParser(printer);
+
+  printer->Print(
+    "public $classname$ getDefaultInstanceForType() {\n"
+    "  return DEFAULT_INSTANCE;\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+  // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+  // the outer class's FileDescriptor.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+        .Generate(printer);
+  }
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+
+// ===================================================================
+
+void ImmutableMessageGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+      SortFieldsByNumber(descriptor_));
+
+  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeOrdering());
+
+  printer->Print(
+    "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
+    "                    throws java.io.IOException {\n");
+  printer->Indent();
+  if (HasPackedFields(descriptor_)) {
+    // writeTo(CodedOutputStream output) might be invoked without
+    // getSerializedSize() ever being called, but we need the memoized
+    // sizes in case this message has packed fields. Rather than emit checks for
+    // each packed field, just call getSerializedSize() up front.
+    // In most cases, getSerializedSize() will have already been called anyway
+    // by one of the wrapper writeTo() methods, making this call cheap.
+    printer->Print(
+      "getSerializedSize();\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessage\n"
+        "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+        "    extensionWriter = newMessageSetExtensionWriter();\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    } else {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessage\n"
+        "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+        "    extensionWriter = newExtensionWriter();\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    }
+  }
+
+  // Merge the fields and the extension ranges, both sorted by field number.
+  for (int i = 0, j = 0;
+       i < descriptor_->field_count() || j < sorted_extensions.size();
+       ) {
+    if (i == descriptor_->field_count()) {
+      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+    } else if (j == sorted_extensions.size()) {
+      GenerateSerializeOneField(printer, sorted_fields[i++]);
+    } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+      GenerateSerializeOneField(printer, sorted_fields[i++]);
+    } else {
+      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+    }
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "unknownFields.writeAsMessageSetTo(output);\n");
+    } else {
+      printer->Print(
+        "unknownFields.writeTo(output);\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n"
+    "public int getSerializedSize() {\n"
+    "  int size = memoizedSize;\n"
+    "  if (size != -1) return size;\n"
+    "\n"
+    "  size = 0;\n");
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "size += extensionsSerializedSizeAsMessageSet();\n");
+    } else {
+      printer->Print(
+        "size += extensionsSerializedSize();\n");
+    }
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "size += unknownFields.getSerializedSizeAsMessageSet();\n");
+    } else {
+      printer->Print(
+        "size += unknownFields.getSerializedSize();\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  memoizedSize = size;\n"
+    "  return size;\n"
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "private static final long serialVersionUID = 0L;\n");
+}
+
+void ImmutableMessageGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+  // Note:  These are separate from GenerateMessageSerializationMethods()
+  //   because they need to be generated even for messages that are optimized
+  //   for code size.
+  printer->Print(
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.ByteString data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.ByteString data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(byte[] data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    byte[] data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    java.io.InputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseDelimitedWithIOException(PARSER, input);\n"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(\n"
+    "    java.io.InputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+void ImmutableMessageGenerator::GenerateSerializeOneField(
+    io::Printer* printer, const FieldDescriptor* field) {
+  field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
+    io::Printer* printer, const Descriptor::ExtensionRange* range) {
+  printer->Print(
+    "extensionWriter.writeUntil($end$, output);\n",
+    "end", SimpleItoa(range->end));
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
+  // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+  printer->Print(
+    "public Builder newBuilderForType() { return newBuilder(); }\n");
+
+  printer->Print(
+    "public static Builder newBuilder() {\n"
+    "  return DEFAULT_INSTANCE.toBuilder();\n"
+    "}\n"
+    "public static Builder newBuilder($classname$ prototype) {\n"
+    "  return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+    "}\n"
+    "public Builder toBuilder() {\n"
+    "  return this == DEFAULT_INSTANCE\n"
+    "      ? new Builder() : new Builder().mergeFrom(this);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "protected Builder newBuilderForType(\n"
+    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "  Builder builder = new Builder(parent);\n"
+    "  return builder;\n"
+    "}\n");
+
+  MessageBuilderGenerator builderGenerator(descriptor_, context_);
+  builderGenerator.Generate(printer);
+}
+
+void ImmutableMessageGenerator::
+GenerateDescriptorMethods(io::Printer* printer) {
+  if (!descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(
+      "public static final com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptor() {\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
+      "}\n"
+      "\n",
+      "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
+  }
+  vector<const FieldDescriptor*> map_fields;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+        IsMapEntry(field->message_type())) {
+      map_fields.push_back(field);
+    }
+  }
+  if (!map_fields.empty()) {
+    printer->Print(
+      "@SuppressWarnings({\"rawtypes\"})\n"
+      "protected com.google.protobuf.MapField internalGetMapField(\n"
+      "    int number) {\n"
+      "  switch (number) {\n");
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < map_fields.size(); ++i) {
+      const FieldDescriptor* field = map_fields[i];
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      printer->Print(
+        "case $number$:\n"
+        "  return internalGet$capitalized_name$();\n",
+        "number", SimpleItoa(field->number()),
+        "capitalized_name", info->capitalized_name);
+    }
+    printer->Print(
+        "default:\n"
+        "  throw new RuntimeException(\n"
+        "      \"Invalid map field number: \" + number);\n");
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+        "  }\n"
+        "}\n");
+  }
+  printer->Print(
+    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "    internalGetFieldAccessorTable() {\n"
+    "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+    "      .ensureFieldAccessorsInitialized(\n"
+    "          $classname$.class, $classname$.Builder.class);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+    "identifier", UniqueFileScopeIdentifier(descriptor_));
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateIsInitialized(
+    io::Printer* printer) {
+  // Memoizes whether the protocol buffer is fully initialized (has all
+  // required fields). -1 means not yet computed. 0 means false and 1 means
+  // true.
+  printer->Print(
+    "private byte memoizedIsInitialized = -1;\n");
+  printer->Print(
+    "public final boolean isInitialized() {\n");
+  printer->Indent();
+
+  // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+  printer->Print(
+    "byte isInitialized = memoizedIsInitialized;\n"
+    "if (isInitialized == 1) return true;\n"
+    "if (isInitialized == 0) return false;\n"
+    "\n");
+
+  // Check that all required fields in this message are set.
+  // TODO(kenton):  We can optimize this when we switch to putting all the
+  //   "has" fields into a single bitfield.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+    if (field->is_required()) {
+      printer->Print(
+        "if (!has$name$()) {\n"
+        "  memoizedIsInitialized = 0;\n"
+        "  return false;\n"
+        "}\n",
+        "name", info->capitalized_name);
+    }
+  }
+
+  // Now check that all embedded messages are initialized.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+    if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+        HasRequiredFields(field->message_type())) {
+      switch (field->label()) {
+        case FieldDescriptor::LABEL_REQUIRED:
+          printer->Print(
+            "if (!get$name$().isInitialized()) {\n"
+             "  memoizedIsInitialized = 0;\n"
+             "  return false;\n"
+             "}\n",
+            "type", name_resolver_->GetImmutableClassName(
+                field->message_type()),
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_OPTIONAL:
+          if (!SupportFieldPresence(descriptor_->file()) &&
+              field->containing_oneof() != NULL) {
+            const OneofDescriptor* oneof = field->containing_oneof();
+            const OneofGeneratorInfo* oneof_info =
+                context_->GetOneofGeneratorInfo(oneof);
+            printer->Print(
+              "if ($oneof_name$Case_ == $field_number$) {\n",
+              "oneof_name", oneof_info->name,
+              "field_number", SimpleItoa(field->number()));
+          } else {
+            printer->Print(
+              "if (has$name$()) {\n",
+              "name", info->capitalized_name);
+          }
+          printer->Print(
+            "  if (!get$name$().isInitialized()) {\n"
+            "    memoizedIsInitialized = 0;\n"
+            "    return false;\n"
+            "  }\n"
+            "}\n",
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_REPEATED:
+          if (IsMapEntry(field->message_type())) {
+            printer->Print(
+              "for ($type$ item : get$name$().values()) {\n"
+              "  if (!item.isInitialized()) {\n"
+              "    memoizedIsInitialized = 0;\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", MapValueImmutableClassdName(field->message_type(),
+                                                  name_resolver_),
+              "name", info->capitalized_name);
+          } else {
+            printer->Print(
+              "for (int i = 0; i < get$name$Count(); i++) {\n"
+              "  if (!get$name$(i).isInitialized()) {\n"
+              "    memoizedIsInitialized = 0;\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", name_resolver_->GetImmutableClassName(
+                  field->message_type()),
+              "name", info->capitalized_name);
+          }
+          break;
+      }
+    }
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "if (!extensionsAreInitialized()) {\n"
+      "  memoizedIsInitialized = 0;\n"
+      "  return false;\n"
+      "}\n");
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "  memoizedIsInitialized = 1;\n");
+
+  printer->Print(
+    "  return true;\n"
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
+namespace {
+bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
+  if (field->is_repeated()) {
+    return false;
+  }
+  if (SupportFieldPresence(field->file())) {
+    return true;
+  }
+  return GetJavaType(field) == JAVATYPE_MESSAGE &&
+      field->containing_oneof() == NULL;
+}
+}  // namespace
+
+void ImmutableMessageGenerator::
+GenerateEqualsAndHashCode(io::Printer* printer) {
+  printer->Print(
+    "@java.lang.Override\n"
+    "public boolean equals(final java.lang.Object obj) {\n");
+  printer->Indent();
+  printer->Print(
+    "if (obj == this) {\n"
+    " return true;\n"
+    "}\n"
+    "if (!(obj instanceof $classname$)) {\n"
+    "  return super.equals(obj);\n"
+    "}\n"
+    "$classname$ other = ($classname$) obj;\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print("boolean result = true;\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "result = result && (has$name$() == other.has$name$());\n"
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateEqualsCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print(
+          "}\n");
+      }
+    }
+  }
+
+  // Compare oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "result = result && get$oneof_capitalized_name$Case().equals(\n"
+      "    other.get$oneof_capitalized_name$Case());\n",
+      "oneof_capitalized_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->capitalized_name);
+    printer->Print(
+      "if (!result) return false;\n"
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
+      printer->Indent();
+      field_generators_.get(field).GenerateEqualsCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    // Always consider unknown fields for equality. This will sometimes return
+    // false for non-canonical ordering when running in LITE_RUNTIME but it's
+    // the best we can do.
+    printer->Print(
+      "result = result && unknownFields.equals(other.unknownFields);\n");
+  }
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "result = result &&\n"
+      "    getExtensionFields().equals(other.getExtensionFields());\n");
+  }
+  printer->Print(
+    "return result;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "public int hashCode() {\n");
+  printer->Indent();
+  printer->Print(
+    "if (memoizedHashCode != 0) {\n");
+  printer->Indent();
+  printer->Print(
+    "return memoizedHashCode;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "int hash = 41;\n");
+
+  printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+
+  // hashCode non-oneofs.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateHashCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+  }
+
+  // hashCode oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
+      printer->Indent();
+      field_generators_.get(field).GenerateHashCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "hash = hashFields(hash, getExtensionFields());\n");
+  }
+
+  printer->Print(
+    "hash = (29 * hash) + unknownFields.hashCode();\n");
+  printer->Print(
+    "memoizedHashCode = hash;\n"
+    "return hash;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::
+GenerateExtensionRegistrationCode(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+      .GenerateRegistrationCode(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+      .GenerateExtensionRegistrationCode(printer);
+  }
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::
+GenerateParsingConstructor(io::Printer* printer) {
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+      SortFieldsByNumber(descriptor_));
+
+  printer->Print(
+      "private $classname$(\n"
+      "    com.google.protobuf.CodedInputStream input,\n"
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
+      "classname", descriptor_->name());
+  printer->Indent();
+
+  // Initialize all fields to default.
+  printer->Print(
+      "this();\n");
+
+  // Use builder bits to track mutable repeated fields.
+  int totalBuilderBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const ImmutableFieldGenerator& field =
+        field_generators_.get(descriptor_->field(i));
+    totalBuilderBits += field.GetNumBitsForBuilder();
+  }
+  int totalBuilderInts = (totalBuilderBits + 31) / 32;
+  for (int i = 0; i < totalBuilderInts; i++) {
+    printer->Print("int mutable_$bit_field_name$ = 0;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+      "    com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+  }
+
+  printer->Print(
+      "try {\n");
+  printer->Indent();
+
+  printer->Print(
+    "boolean done = false;\n"
+    "while (!done) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "int tag = input.readTag();\n"
+    "switch (tag) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "case 0:\n"          // zero signals EOF / limit reached
+    "  done = true;\n"
+    "  break;\n");
+
+  if (PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "default: {\n"
+      "  if (!parseUnknownField(input, unknownFields,\n"
+      "                         extensionRegistry, tag)) {\n"
+      "    done = true;\n"  // it's an endgroup tag
+      "  }\n"
+      "  break;\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "default: {\n"
+      "  if (!input.skipField(tag)) {\n"
+      "    done = true;\n"  // it's an endgroup tag
+      "  }\n");
+    printer->Print(
+      "  break;\n"
+      "}\n");
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
+      WireFormat::WireTypeForFieldType(field->type()));
+
+    printer->Print(
+      "case $tag$: {\n",
+      "tag", SimpleItoa(tag));
+    printer->Indent();
+
+    field_generators_.get(field).GenerateParsingCode(printer);
+
+    printer->Outdent();
+    printer->Print(
+      "  break;\n"
+      "}\n");
+
+    if (field->is_packable()) {
+      // To make packed = true wire compatible, we generate parsing code from a
+      // packed version of this field regardless of field->options().packed().
+      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+      printer->Print(
+        "case $tag$: {\n",
+        "tag", SimpleItoa(packed_tag));
+      printer->Indent();
+
+      field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+      printer->Outdent();
+      printer->Print(
+        "  break;\n"
+        "}\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // switch (tag)
+      "}\n");     // while (!done)
+
+  printer->Outdent();
+  printer->Print(
+      "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+      "  throw e.setUnfinishedMessage(this);\n"
+      "} catch (java.io.IOException e) {\n"
+      "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "      e).setUnfinishedMessage(this);\n"
+      "} finally {\n");
+  printer->Indent();
+
+  // Make repeated field list immutable.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    field_generators_.get(field).GenerateParsingDoneCode(printer);
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    // Make unknown fields immutable.
+    printer->Print("this.unknownFields = unknownFields.build();\n");
+  }
+
+  // Make extensions immutable.
+  printer->Print(
+      "makeExtensionsImmutable();\n");
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // finally
+      "}\n");
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
+  printer->Print(
+      "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
+      "    PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n",
+      "visibility",
+      ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public"
+                                              : "private",
+      "classname", descriptor_->name());
+  printer->Indent();
+  printer->Print(
+      "public $classname$ parsePartialFrom(\n"
+      "    com.google.protobuf.CodedInputStream input,\n"
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
+      "classname", descriptor_->name());
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    printer->Print(
+        "    return new $classname$(input, extensionRegistry);\n",
+        "classname", descriptor_->name());
+  } else {
+    // When parsing constructor isn't generated, use builder to parse
+    // messages. Note, will fallback to use reflection based mergeFieldFrom()
+    // in AbstractMessage.Builder.
+    printer->Indent();
+    printer->Print(
+        "Builder builder = newBuilder();\n"
+        "try {\n"
+        "  builder.mergeFrom(input, extensionRegistry);\n"
+        "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+        "  throw e.setUnfinishedMessage(builder.buildPartial());\n"
+        "} catch (java.io.IOException e) {\n"
+        "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+        "      e.getMessage()).setUnfinishedMessage(\n"
+        "          builder.buildPartial());\n"
+        "}\n"
+        "return builder.buildPartial();\n");
+    printer->Outdent();
+  }
+  printer->Print(
+        "}\n");
+  printer->Outdent();
+  printer->Print(
+      "};\n"
+      "\n");
+
+  printer->Print(
+      "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+      "  return PARSER;\n"
+      "}\n"
+      "\n"
+      "@java.lang.Override\n"
+      "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+      "  return PARSER;\n"
+      "}\n"
+      "\n",
+      "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateInitializationCode(printer);
+    }
+  }
+}
+
+
+void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
+  printer->Print(
+    "private static String getTypeUrl(\n"
+    "    java.lang.String typeUrlPrefix,\n"
+    "    com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
+    "  return typeUrlPrefix.endsWith(\"/\")\n"
+    "      ? typeUrlPrefix + descriptor.getFullName()\n"
+    "      : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
+    "}\n"
+    "\n"
+    "private static String getTypeNameFromTypeUrl(\n"
+    "    java.lang.String typeUrl) {\n"
+    "  int pos = typeUrl.lastIndexOf('/');\n"
+    "  return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
+    "}\n"
+    "\n"
+    "public static <T extends com.google.protobuf.Message> Any pack(\n"
+    "    T message) {\n"
+    "  return Any.newBuilder()\n"
+    "      .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
+    "                             message.getDescriptorForType()))\n"
+    "      .setValue(message.toByteString())\n"
+    "      .build();\n"
+    "}\n"
+    "\n"
+    "/**\n"
+    " * Packs a message uisng the given type URL prefix. The type URL will\n"
+    " * be constructed by concatenating the message type's full name to the\n"
+    " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
+    " * with \"/\" already.\n"
+    " */\n"
+    "public static <T extends com.google.protobuf.Message> Any pack(\n"
+    "    T message, java.lang.String typeUrlPrefix) {\n"
+    "  return Any.newBuilder()\n"
+    "      .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
+    "                             message.getDescriptorForType()))\n"
+    "      .setValue(message.toByteString())\n"
+    "      .build();\n"
+    "}\n"
+    "\n"
+    "public <T extends com.google.protobuf.Message> boolean is(\n"
+    "    java.lang.Class<T> clazz) {\n"
+    "  T defaultInstance =\n"
+    "      com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+    "  return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+    "      defaultInstance.getDescriptorForType().getFullName());\n"
+    "}\n"
+    "\n"
+    "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
+    "\n"
+    "public <T extends com.google.protobuf.Message> T unpack(\n"
+    "    java.lang.Class<T> clazz)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  if (!is(clazz)) {\n"
+    "    throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+    "        \"Type of the Any message does not match the given class.\");\n"
+    "  }\n"
+    "  if (cachedUnpackValue != null) {\n"
+    "    return (T) cachedUnpackValue;\n"
+    "  }\n"
+    "  T defaultInstance =\n"
+    "      com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+    "  T result = (T) defaultInstance.getParserForType()\n"
+    "      .parseFrom(getValue());\n"
+    "  cachedUnpackValue = result;\n"
+    "  return result;\n"
+    "}\n");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.h
new file mode 100644
index 0000000..e9fc57c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message.h
@@ -0,0 +1,143 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+static const int kMaxStaticSize = 1 << 15;  // aka 32k
+
+class MessageGenerator {
+ public:
+  explicit MessageGenerator(const Descriptor* descriptor);
+  virtual ~MessageGenerator();
+
+  // All static variables have to be declared at the top-level of the file
+  // so that we can control initialization order, which is important for
+  // DescriptorProto bootstrapping to work.
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate) = 0;
+
+  // Output code which initializes the static variables generated by
+  // GenerateStaticVariables(). Returns an estimate of bytecode size.
+  virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0;
+
+  // Generate the class itself.
+  virtual void Generate(io::Printer* printer) = 0;
+
+  // Generates the base interface that both the class and its builder implement
+  virtual void GenerateInterface(io::Printer* printer) = 0;
+
+  // Generate code to register all contained extensions with an
+  // ExtensionRegistry.
+  virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0;
+
+ protected:
+  const Descriptor* descriptor_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+class ImmutableMessageGenerator : public MessageGenerator {
+ public:
+  explicit ImmutableMessageGenerator(const Descriptor* descriptor,
+                                     Context* context);
+  virtual ~ImmutableMessageGenerator();
+
+  virtual void Generate(io::Printer* printer);
+  virtual void GenerateInterface(io::Printer* printer);
+  virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateStaticVariableInitializers(io::Printer* printer);
+
+ private:
+
+  void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  int GenerateFieldAccessorTableInitializer(io::Printer* printer);
+
+  void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateParseFromMethods(io::Printer* printer);
+  void GenerateSerializeOneField(io::Printer* printer,
+                                 const FieldDescriptor* field);
+  void GenerateSerializeOneExtensionRange(
+      io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+  void GenerateBuilder(io::Printer* printer);
+  void GenerateIsInitialized(io::Printer* printer);
+  void GenerateDescriptorMethods(io::Printer* printer);
+  void GenerateInitializers(io::Printer* printer);
+  void GenerateEqualsAndHashCode(io::Printer* printer);
+  void GenerateParser(io::Printer* printer);
+  void GenerateParsingConstructor(io::Printer* printer);
+  void GenerateAnyMethods(io::Printer* printer);
+
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.cc
new file mode 100644
index 0000000..b3e9e98
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -0,0 +1,662 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder.h>
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+  return SupportFieldPresence(descriptor->file()) ||
+      HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+                                   ClassNameResolver* name_resolver) {
+  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+  return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+}  // namespace
+
+MessageBuilderGenerator::MessageBuilderGenerator(
+    const Descriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()),
+    field_generators_(descriptor, context_) {
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
+}
+
+MessageBuilderGenerator::~MessageBuilderGenerator() {}
+
+void MessageBuilderGenerator::
+Generate(io::Printer* printer) {
+  WriteMessageDocComment(printer, descriptor_);
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "public static final class Builder extends\n"
+      "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+      "      $classname$, Builder> implements\n"
+      "    $extra_interfaces$\n"
+      "    $classname$OrBuilder {\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_),
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+  } else {
+    printer->Print(
+      "public static final class Builder extends\n"
+      "    com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+      "    $extra_interfaces$\n"
+      "    $classname$OrBuilder {\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_),
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+  }
+  printer->Indent();
+
+  GenerateDescriptorMethods(printer);
+  GenerateCommonBuilderMethods(printer);
+
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    GenerateIsInitialized(printer);
+    GenerateBuilderParsingMethods(printer);
+  }
+
+  // oneof
+  map<string, string> vars;
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->name;
+    vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->capitalized_name;
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    // oneofCase_ and oneof_
+    printer->Print(vars,
+      "private int $oneof_name$Case_ = 0;\n"
+      "private java.lang.Object $oneof_name$_;\n");
+    // oneofCase() and clearOneof()
+    printer->Print(vars,
+      "public $oneof_capitalized_name$Case\n"
+      "    get$oneof_capitalized_name$Case() {\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
+      "      $oneof_name$Case_);\n"
+      "}\n"
+      "\n"
+      "public Builder clear$oneof_capitalized_name$() {\n"
+      "  $oneof_name$Case_ = 0;\n"
+      "  $oneof_name$_ = null;\n");
+    printer->Print("  onChanged();\n");
+    printer->Print(
+      "  return this;\n"
+      "}\n"
+      "\n");
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Integers for bit fields.
+    int totalBits = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      totalBits += field_generators_.get(descriptor_->field(i))
+          .GetNumBitsForBuilder();
+    }
+    int totalInts = (totalBits + 31) / 32;
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print("private int $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("\n");
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateBuilderMembers(printer);
+  }
+
+  if (!PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "public final Builder setUnknownFields(\n"
+      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+      "  return this;\n"
+      "}\n"
+      "\n"
+      "public final Builder mergeUnknownFields(\n"
+      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+      "  return this;\n"
+      "}\n"
+      "\n");
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateDescriptorMethods(io::Printer* printer) {
+  if (!descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print(
+      "public static final com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptor() {\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
+      "}\n"
+      "\n",
+      "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
+  }
+  vector<const FieldDescriptor*> map_fields;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+        IsMapEntry(field->message_type())) {
+      map_fields.push_back(field);
+    }
+  }
+  if (!map_fields.empty()) {
+    printer->Print(
+      "@SuppressWarnings({\"rawtypes\"})\n"
+      "protected com.google.protobuf.MapField internalGetMapField(\n"
+      "    int number) {\n"
+      "  switch (number) {\n");
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < map_fields.size(); ++i) {
+      const FieldDescriptor* field = map_fields[i];
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      printer->Print(
+        "case $number$:\n"
+        "  return internalGet$capitalized_name$();\n",
+        "number", SimpleItoa(field->number()),
+        "capitalized_name", info->capitalized_name);
+    }
+    printer->Print(
+        "default:\n"
+        "  throw new RuntimeException(\n"
+        "      \"Invalid map field number: \" + number);\n");
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+        "  }\n"
+        "}\n");
+    printer->Print(
+      "@SuppressWarnings({\"rawtypes\"})\n"
+      "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
+      "    int number) {\n"
+      "  switch (number) {\n");
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < map_fields.size(); ++i) {
+      const FieldDescriptor* field = map_fields[i];
+      const FieldGeneratorInfo* info =
+          context_->GetFieldGeneratorInfo(field);
+      printer->Print(
+        "case $number$:\n"
+        "  return internalGetMutable$capitalized_name$();\n",
+        "number", SimpleItoa(field->number()),
+        "capitalized_name", info->capitalized_name);
+    }
+    printer->Print(
+        "default:\n"
+        "  throw new RuntimeException(\n"
+        "      \"Invalid map field number: \" + number);\n");
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+        "  }\n"
+        "}\n");
+  }
+  printer->Print(
+    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "    internalGetFieldAccessorTable() {\n"
+    "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+    "      .ensureFieldAccessorsInitialized(\n"
+    "          $classname$.class, $classname$.Builder.class);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+    "identifier", UniqueFileScopeIdentifier(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+  printer->Print(
+      "// Construct using $classname$.newBuilder()\n"
+      "private Builder() {\n"
+      "  maybeForceBuilderInitialization();\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "private Builder(\n"
+    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "  super(parent);\n"
+    "  maybeForceBuilderInitialization();\n"
+    "}\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "private void maybeForceBuilderInitialization() {\n"
+    "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+
+  printer->Indent();
+  printer->Indent();
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateFieldBuilderInitializationCode(printer);
+    }
+  }
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+    "  }\n"
+    "}\n");
+
+  printer->Print(
+    "public Builder clear() {\n"
+    "  super.clear();\n");
+
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateBuilderClearCode(printer);
+    }
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "$oneof_name$Case_ = 0;\n"
+      "$oneof_name$_ = null;\n",
+      "oneof_name", context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "  return this;\n"
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "public com.google.protobuf.Descriptors.Descriptor\n"
+    "    getDescriptorForType() {\n"
+    "  return $fileclass$.internal_$identifier$_descriptor;\n"
+    "}\n"
+    "\n",
+    "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+    "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+  // LITE runtime implements this in GeneratedMessageLite.
+  printer->Print(
+    "public $classname$ getDefaultInstanceForType() {\n"
+    "  return $classname$.getDefaultInstance();\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "public $classname$ build() {\n"
+    "  $classname$ result = buildPartial();\n"
+    "  if (!result.isInitialized()) {\n"
+    "    throw newUninitializedMessageException(result);\n"
+    "  }\n"
+    "  return result;\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "public $classname$ buildPartial() {\n"
+    "  $classname$ result = new $classname$(this);\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Indent();
+
+  int totalBuilderBits = 0;
+  int totalMessageBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const ImmutableFieldGenerator& field =
+        field_generators_.get(descriptor_->field(i));
+    totalBuilderBits += field.GetNumBitsForBuilder();
+    totalMessageBits += field.GetNumBitsForMessage();
+  }
+  int totalBuilderInts = (totalBuilderBits + 31) / 32;
+  int totalMessageInts = (totalMessageBits + 31) / 32;
+
+  if (GenerateHasBits(descriptor_)) {
+    // Local vars for from and to bit fields to avoid accessing the builder and
+    // message over and over for these fields. Seems to provide a slight
+    // perforamance improvement in micro benchmark and this is also what proto1
+    // code does.
+    for (int i = 0; i < totalBuilderInts; i++) {
+      printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+    for (int i = 0; i < totalMessageInts; i++) {
+      printer->Print("int to_$bit_field_name$ = 0;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  // Output generation code for each field.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Copy the bit field results to the generated message
+    for (int i = 0; i < totalMessageInts; i++) {
+      printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
+                   "oneof_name", context_->GetOneofGeneratorInfo(
+                       descriptor_->oneof_decl(i))->name);
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "  onBuilt();\n");
+
+  printer->Print(
+    "  return result;\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  // -----------------------------------------------------------------
+
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    printer->Print(
+      "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
+      "  if (other instanceof $classname$) {\n"
+      "    return mergeFrom(($classname$)other);\n"
+      "  } else {\n"
+      "    super.mergeFrom(other);\n"
+      "    return this;\n"
+      "  }\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+    printer->Print(
+      "public Builder mergeFrom($classname$ other) {\n"
+      // Optimization:  If other is the default instance, we know none of its
+      //   fields are set so we can skip the merge.
+      "  if (other == $classname$.getDefaultInstance()) return this;\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    printer->Indent();
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      if (!descriptor_->field(i)->containing_oneof()) {
+        field_generators_.get(
+            descriptor_->field(i)).GenerateMergingCode(printer);
+      }
+    }
+
+    // Merge oneof fields.
+    for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+      printer->Print(
+        "switch (other.get$oneof_capitalized_name$Case()) {\n",
+        "oneof_capitalized_name",
+        context_->GetOneofGeneratorInfo(
+            descriptor_->oneof_decl(i))->capitalized_name);
+      printer->Indent();
+      for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+        const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+        printer->Print(
+          "case $field_name$: {\n",
+          "field_name",
+          ToUpper(field->name()));
+        printer->Indent();
+        field_generators_.get(field).GenerateMergingCode(printer);
+        printer->Print(
+            "break;\n");
+        printer->Outdent();
+        printer->Print(
+            "}\n");
+      }
+      printer->Print(
+        "case $cap_oneof_name$_NOT_SET: {\n"
+        "  break;\n"
+        "}\n",
+        "cap_oneof_name",
+        ToUpper(context_->GetOneofGeneratorInfo(
+            descriptor_->oneof_decl(i))->name));
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+
+    printer->Outdent();
+
+    // if message type has extensions
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "  this.mergeExtensionFields(other);\n");
+    }
+
+    if (PreserveUnknownFields(descriptor_)) {
+      printer->Print(
+        "  this.mergeUnknownFields(other.unknownFields);\n");
+    }
+
+    printer->Print(
+      "  onChanged();\n");
+
+    printer->Print(
+      "  return this;\n"
+      "}\n"
+      "\n");
+  }
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateBuilderParsingMethods(io::Printer* printer) {
+  printer->Print(
+    "public Builder mergeFrom(\n"
+    "    com.google.protobuf.CodedInputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  $classname$ parsedMessage = null;\n"
+    "  try {\n"
+    "    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
+    "  } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+    "    parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
+    "    throw e.unwrapIOException();\n"
+    "  } finally {\n"
+    "    if (parsedMessage != null) {\n"
+    "      mergeFrom(parsedMessage);\n"
+    "    }\n"
+    "  }\n"
+    "  return this;\n"
+    "}\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateIsInitialized(
+    io::Printer* printer) {
+  printer->Print(
+    "public final boolean isInitialized() {\n");
+  printer->Indent();
+
+  // Check that all required fields in this message are set.
+  // TODO(kenton):  We can optimize this when we switch to putting all the
+  //   "has" fields into a single bitfield.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+    if (field->is_required()) {
+      printer->Print(
+        "if (!has$name$()) {\n"
+        "  return false;\n"
+        "}\n",
+        "name", info->capitalized_name);
+    }
+  }
+
+  // Now check that all embedded messages are initialized.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+    if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+        HasRequiredFields(field->message_type())) {
+      switch (field->label()) {
+        case FieldDescriptor::LABEL_REQUIRED:
+          printer->Print(
+            "if (!get$name$().isInitialized()) {\n"
+             "  return false;\n"
+             "}\n",
+            "type", name_resolver_->GetImmutableClassName(
+                field->message_type()),
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_OPTIONAL:
+          if (!SupportFieldPresence(descriptor_->file()) &&
+              field->containing_oneof() != NULL) {
+            const OneofDescriptor* oneof = field->containing_oneof();
+            const OneofGeneratorInfo* oneof_info =
+                context_->GetOneofGeneratorInfo(oneof);
+            printer->Print(
+              "if ($oneof_name$Case_ == $field_number$) {\n",
+              "oneof_name", oneof_info->name,
+              "field_number", SimpleItoa(field->number()));
+          } else {
+            printer->Print(
+              "if (has$name$()) {\n",
+              "name", info->capitalized_name);
+          }
+          printer->Print(
+            "  if (!get$name$().isInitialized()) {\n"
+            "    return false;\n"
+            "  }\n"
+            "}\n",
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_REPEATED:
+          if (IsMapEntry(field->message_type())) {
+            printer->Print(
+              "for ($type$ item : get$name$().values()) {\n"
+              "  if (!item.isInitialized()) {\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", MapValueImmutableClassdName(field->message_type(),
+                                                  name_resolver_),
+              "name", info->capitalized_name);
+          } else {
+            printer->Print(
+              "for (int i = 0; i < get$name$Count(); i++) {\n"
+              "  if (!get$name$(i).isInitialized()) {\n"
+              "    return false;\n"
+              "  }\n"
+              "}\n",
+              "type", name_resolver_->GetImmutableClassName(
+                  field->message_type()),
+              "name", info->capitalized_name);
+          }
+          break;
+      }
+    }
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "if (!extensionsAreInitialized()) {\n"
+      "  return false;\n"
+      "}\n");
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "  return true;\n"
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.h
new file mode 100644
index 0000000..015ea06
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder.h
@@ -0,0 +1,86 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderGenerator {
+ public:
+  explicit MessageBuilderGenerator(const Descriptor* descriptor,
+                                   Context* context);
+  virtual ~MessageBuilderGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+ private:
+  void GenerateCommonBuilderMethods(io::Printer* printer);
+  void GenerateDescriptorMethods(io::Printer* printer);
+  void GenerateBuilderParsingMethods(io::Printer* printer);
+  void GenerateIsInitialized(io::Printer* printer);
+
+  const Descriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.cc
new file mode 100644
index 0000000..dd429dc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -0,0 +1,179 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+  return SupportFieldPresence(descriptor->file()) ||
+      HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+                                   ClassNameResolver* name_resolver) {
+  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+  return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+}  // namespace
+
+MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
+    const Descriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()),
+    field_generators_(descriptor, context_) {
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
+}
+
+MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
+
+void MessageBuilderLiteGenerator::
+Generate(io::Printer* printer) {
+  WriteMessageDocComment(printer, descriptor_);
+  printer->Print(
+    "public static final class Builder extends\n"
+    "    com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n"
+    "      $classname$, Builder> implements\n"
+    "    $extra_interfaces$\n"
+    "    $classname$OrBuilder {\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+    "extendible",
+    descriptor_->extension_range_count() > 0 ? "Extendable" : "");
+  printer->Indent();
+
+  GenerateCommonBuilderMethods(printer);
+
+  // oneof
+  map<string, string> vars;
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->name;
+    vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->capitalized_name;
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+
+    // oneofCase() and clearOneof()
+    printer->Print(vars,
+      "public $oneof_capitalized_name$Case\n"
+      "    get$oneof_capitalized_name$Case() {\n"
+      "  return instance.get$oneof_capitalized_name$Case();\n"
+      "}\n"
+      "\n"
+      "public Builder clear$oneof_capitalized_name$() {\n"
+      "  copyOnWrite();\n"
+      "  instance.clear$oneof_capitalized_name$();\n"
+      "  return this;\n"
+      "}\n"
+      "\n");
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Integers for bit fields.
+    int totalBits = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      totalBits += field_generators_.get(descriptor_->field(i))
+          .GetNumBitsForBuilder();
+    }
+    int totalInts = (totalBits + 31) / 32;
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print("private int $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("\n");
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateBuilderMembers(printer);
+  }
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderLiteGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+  printer->Print(
+    "// Construct using $classname$.newBuilder()\n"
+    "private Builder() {\n"
+    "  super(DEFAULT_INSTANCE);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.h
new file mode 100644
index 0000000..8597b2e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_builder_lite.h
@@ -0,0 +1,83 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderLiteGenerator {
+ public:
+  explicit MessageBuilderLiteGenerator(const Descriptor* descriptor,
+                                   Context* context);
+  virtual ~MessageBuilderLiteGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+ private:
+  void GenerateCommonBuilderMethods(io::Printer* printer);
+
+  const Descriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.cc
new file mode 100644
index 0000000..455516f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.cc
@@ -0,0 +1,1291 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
+                         const FieldGeneratorInfo* info,
+                         ClassNameResolver* name_resolver,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->message_type());
+  (*variables)["mutable_type"] =
+      name_resolver->GetMutableClassName(descriptor->message_type());
+  (*variables)["group_or_message"] =
+    (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
+    "Group" : "Message";
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] = "onChanged();";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["set_has_field_bit_builder"] =
+        GenerateSetBit(builderBitIndex) + ";";
+    (*variables)["clear_has_field_bit_builder"] =
+        GenerateClearBit(builderBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["set_has_field_bit_builder"] = "";
+    (*variables)["clear_has_field_bit_builder"] = "";
+
+    (*variables)["is_field_present_message"] =
+        (*variables)["name"] + "_ != null";
+  }
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableMessageFieldGenerator::
+ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
+                      Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+    SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
+
+int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having a method specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  if (SupportFieldPresence(descriptor_->file()) ||
+      descriptor_->containing_oneof() == NULL) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+      "}\n");
+
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$OrBuilder "
+      "get$capitalized_name$OrBuilder() {\n"
+      "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+      "}\n");
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $name$_ != null;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+      "}\n");
+
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$OrBuilder "
+      "get$capitalized_name$OrBuilder() {\n"
+      "  return get$capitalized_name$();\n"
+      "}\n");
+  }
+}
+
+void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+  printer->Indent();
+  printer->Print(variables_, regular_case);
+  printer->Outdent();
+  printer->Print("} else {\n");
+  printer->Indent();
+  printer->Print(variables_, nested_builder_case);
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
+  bool support_field_presence = SupportFieldPresence(descriptor_->file());
+
+  printer->Print(variables_,
+    "private $type$ $name$_ = null;\n");
+
+  printer->Print(variables_,
+      // If this builder is non-null, it is used and the other fields are
+      // ignored.
+      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+      "\n");
+
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  if (support_field_presence) {
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_builder$;\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $name$Builder_ != null || $name$_ != null;\n"
+      "}\n");
+  }
+
+  // Field getField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$()",
+    "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
+    "return $name$Builder_.getMessage();\n",
+    NULL);
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "$name$_ = value;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(value);\n",
+
+    "$set_has_field_bit_builder$\n"
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "$name$_ = builderForValue.build();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(builderForValue.build());\n",
+
+    "$set_has_field_bit_builder$\n"
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    support_field_presence
+        ? "if ($get_has_field_bit_builder$ &&\n"
+          "    $name$_ != null &&\n"
+          "    $name$_ != $type$.getDefaultInstance()) {\n"
+          "  $name$_ =\n"
+          "    $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+          "} else {\n"
+          "  $name$_ = value;\n"
+          "}\n"
+          "$on_changed$\n"
+        : "if ($name$_ != null) {\n"
+          "  $name$_ =\n"
+          "    $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+          "} else {\n"
+          "  $name$_ = value;\n"
+          "}\n"
+          "$on_changed$\n",
+
+    "$name$Builder_.mergeFrom(value);\n",
+
+    "$set_has_field_bit_builder$\n"
+    "return this;\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = null;\n"
+    "$on_changed$\n",
+
+    support_field_presence
+        ? "$name$Builder_.clear();\n"
+        : "$name$_ = null;\n"
+          "$name$Builder_ = null;\n",
+
+    "$clear_has_field_bit_builder$\n"
+    "return this;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "  $set_has_field_bit_builder$\n"
+    "  $on_changed$\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "  if ($name$Builder_ != null) {\n"
+    "    return $name$Builder_.getMessageOrBuilder();\n"
+    "  } else {\n"
+    "    return $name$_ == null ?\n"
+    "        $type$.getDefaultInstance() : $name$_;\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> \n"
+    "    get$capitalized_name$FieldBuilder() {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+    "            get$capitalized_name$(),\n"
+    "            getParentForChildren(),\n"
+    "            isClean());\n"
+    "    $name$_ = null;\n"
+    "  }\n"
+    "  return $name$Builder_;\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "get$capitalized_name$FieldBuilder();\n");
+  }
+}
+
+
+void ImmutableMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {}
+
+void ImmutableMessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    PrintNestedBuilderCondition(printer,
+      "$name$_ = null;\n",
+
+      "$name$Builder_.clear();\n");
+    printer->Print(variables_, "$clear_has_field_bit_builder$\n");
+  } else {
+    PrintNestedBuilderCondition(printer,
+      "$name$_ = null;\n",
+
+      "$name$_ = null;\n"
+      "$name$Builder_ = null;\n");
+  }
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+        "if ($get_has_field_bit_from_local$) {\n"
+        "  $set_has_field_bit_to_local$;\n"
+        "}\n");
+  }
+
+  PrintNestedBuilderCondition(printer,
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$type$.Builder subBuilder = null;\n"
+    "if ($is_field_present_message$) {\n"
+    "  subBuilder = $name$_.toBuilder();\n"
+    "}\n");
+
+  if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "$name$_ = input.readGroup($number$, $type$.parser(),\n"
+      "    extensionRegistry);\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
+  }
+
+  printer->Print(variables_,
+    "if (subBuilder != null) {\n"
+    "  subBuilder.mergeFrom($name$_);\n"
+    "  $name$_ = subBuilder.buildPartial();\n"
+    "}\n"
+    "$set_has_field_bit_message$\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for messages.
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableMessageFieldGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldGenerator::
+ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutableMessageFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldGenerator::
+~ImmutableMessageOneofFieldGenerator() {}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "     return ($type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "     return ($type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+  printer->Print(variables_,
+    // If this builder is non-null, it is used and the other fields are
+    // ignored.
+    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+    "\n");
+
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    // boolean hasField()
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+
+  // Field getField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$()",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  return ($type$) $oneof_name$_;\n"
+    "}\n"
+    "return $type$.getDefaultInstance();\n",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  return $name$Builder_.getMessage();\n"
+    "}\n"
+    "return $type$.getDefaultInstance();\n",
+
+    NULL);
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "$oneof_name$_ = value;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(value);\n",
+
+    "$set_oneof_case_message$;\n"
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "$oneof_name$_ = builderForValue.build();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(builderForValue.build());\n",
+
+    "$set_oneof_case_message$;\n"
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    "if ($has_oneof_case_message$ &&\n"
+    "    $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+    "  $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+    "      .mergeFrom(value).buildPartial();\n"
+    "} else {\n"
+    "  $oneof_name$_ = value;\n"
+    "}\n"
+    "$on_changed$\n",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  $name$Builder_.mergeFrom(value);\n"
+    "}\n"
+    "$name$Builder_.setMessage(value);\n",
+
+    "$set_oneof_case_message$;\n"
+    "return this;\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  $clear_oneof_case_message$;\n"
+    "  $oneof_name$_ = null;\n"
+    "  $on_changed$\n"
+    "}\n",
+
+    "if ($has_oneof_case_message$) {\n"
+    "  $clear_oneof_case_message$;\n"
+    "  $oneof_name$_ = null;\n"
+    "}\n"
+    "$name$Builder_.clear();\n",
+
+    "return this;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "  if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
+    "    return $name$Builder_.getMessageOrBuilder();\n"
+    "  } else {\n"
+    "    if ($has_oneof_case_message$) {\n"
+    "      return ($type$) $oneof_name$_;\n"
+    "    }\n"
+    "    return $type$.getDefaultInstance();\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> \n"
+    "    get$capitalized_name$FieldBuilder() {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    if (!($has_oneof_case_message$)) {\n"
+    "      $oneof_name$_ = $type$.getDefaultInstance();\n"
+    "    }\n"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+    "            ($type$) $oneof_name$_,\n"
+    "            getParentForChildren(),\n"
+    "            isClean());\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "  $set_oneof_case_message$;\n"
+    "  $on_changed$;\n"
+    "  return $name$Builder_;\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+
+  printer->Print(variables_,
+                 "if ($has_oneof_case_message$) {\n");
+  printer->Indent();
+
+  PrintNestedBuilderCondition(printer,
+    "result.$oneof_name$_ = $oneof_name$_;\n",
+
+    "result.$oneof_name$_ = $name$Builder_.build();\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "merge$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$type$.Builder subBuilder = null;\n"
+    "if ($has_oneof_case_message$) {\n"
+    "  subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
+    "}\n");
+
+  if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
+      "    extensionRegistry);\n");
+  } else {
+    printer->Print(variables_,
+      "$oneof_name$_ =\n"
+      "    input.readMessage($type$.parser(), extensionRegistry);\n");
+  }
+
+  printer->Print(variables_,
+    "if (subBuilder != null) {\n"
+    "  subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
+    "  $oneof_name$_ = subBuilder.buildPartial();\n"
+    "}\n");
+  printer->Print(variables_,
+    "$set_oneof_case_message$;\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldGenerator::
+RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                       int messageBitIndex,
+                                       int builderBitIndex,
+                                       Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver())  {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      context->GetFieldGeneratorInfo(descriptor),
+                      name_resolver_, &variables_);
+}
+
+RepeatedImmutableMessageFieldGenerator::
+~RepeatedImmutableMessageFieldGenerator() {}
+
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having methods specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> \n"
+    "    get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+    "    get$capitalized_name$OrBuilderList();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index);\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private java.util.List<$type$> $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return $name$_;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+
+}
+
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+  printer->Indent();
+  printer->Print(variables_, regular_case);
+  printer->Outdent();
+  printer->Print("} else {\n");
+  printer->Indent();
+  printer->Print(variables_, nested_builder_case);
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
+  printer->Print(variables_,
+    // Used when the builder is null.
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<$type$> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n"
+    "\n");
+
+  printer->Print(variables_,
+    // If this builder is non-null, it is used and the other fields are
+    // ignored.
+    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+    "\n");
+
+  // The comments above the methods below are based on a hypothetical
+  // repeated field of type "Field" called "RepeatedField".
+
+  // List<Field> getRepeatedFieldList()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+
+    "return java.util.Collections.unmodifiableList($name$_);\n",
+    "return $name$Builder_.getMessageList();\n",
+
+    NULL);
+
+  // int getRepeatedFieldCount()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public int get$capitalized_name$Count()",
+
+    "return $name$_.size();\n",
+    "return $name$Builder_.getCount();\n",
+
+    NULL);
+
+  // Field getRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$(int index)",
+
+    "return $name$_.get(index);\n",
+
+    "return $name$Builder_.getMessage(index);\n",
+
+    NULL);
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value)",
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, value);\n"
+    "$on_changed$\n",
+    "$name$Builder_.setMessage(index, value);\n",
+    "return this;\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(value);\n"
+
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, value);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+    "    values, $name$_);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addAllMessages(values);\n",
+
+    "return this;\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "return this;\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder remove$capitalized_name$(int index)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.remove(index);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.remove(index);\n",
+
+    "return this;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+    "    int index) {\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    return $name$_.get(index);"
+    "  } else {\n"
+    "    return $name$Builder_.getMessageOrBuilder(index);\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "     get$capitalized_name$OrBuilderList() {\n"
+    "  if ($name$Builder_ != null) {\n"
+    "    return $name$Builder_.getMessageOrBuilderList();\n"
+    "  } else {\n"
+    "    return java.util.Collections.unmodifiableList($name$_);\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+    "      $type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+    "    int index) {\n"
+    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+    "      index, $type$.getDefaultInstance());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+      printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$.Builder> \n"
+    "     get$capitalized_name$BuilderList() {\n"
+    "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+    "}\n"
+    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "    $type$, $type$.Builder, $type$OrBuilder> \n"
+    "    get$capitalized_name$FieldBuilder() {\n"
+    "  if ($name$Builder_ == null) {\n"
+    "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+    "            $name$_,\n"
+    "            $get_mutable_bit_builder$,\n"
+    "            getParentForChildren(),\n"
+    "            isClean());\n"
+    "    $name$_ = null;\n"
+    "  }\n"
+    "  return $name$Builder_;\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  PrintNestedBuilderCondition(printer,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n",
+
+    "$name$Builder_.clear();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations (non-nested builder case):
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  PrintNestedBuilderCondition(printer,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n",
+
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$Builder_.isEmpty()) {\n"
+    "    $name$Builder_.dispose();\n"
+    "    $name$Builder_ = null;\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "    $name$Builder_ = \n"
+    "      com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+    "         get$capitalized_name$FieldBuilder() : null;\n"
+    "  } else {\n"
+    "    $name$Builder_.addAllMessages(other.$name$_);\n"
+    "  }\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below (non-nested builder case) ensures that the result has an
+  // immutable list. If our list is immutable, we can just reuse it. If not,
+  // we make it immutable.
+  PrintNestedBuilderCondition(printer,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new java.util.ArrayList<$type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n");
+
+  if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
+      "    extensionRegistry));\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n");
+  }
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.write$group_or_message$($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.h
new file mode 100644
index 0000000..ea8225a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field.h
@@ -0,0 +1,173 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit ImmutableMessageFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMessageFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
+};
+
+class ImmutableMessageOneofFieldGenerator
+    : public ImmutableMessageFieldGenerator {
+ public:
+  ImmutableMessageOneofFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMessageOneofFieldGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
+};
+
+class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit RepeatedImmutableMessageFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableMessageFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.cc
new file mode 100644
index 0000000..1428181
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -0,0 +1,941 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
+                         const FieldGeneratorInfo* info,
+                         ClassNameResolver* name_resolver,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] =
+      name_resolver->GetImmutableClassName(descriptor->message_type());
+  (*variables)["mutable_type"] =
+      name_resolver->GetMutableClassName(descriptor->message_type());
+  (*variables)["group_or_message"] =
+    (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
+    "Group" : "Message";
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["clear_has_field_bit_message"] =
+        GenerateClearBit(messageBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["clear_has_field_bit_message"] = "";
+
+    (*variables)["is_field_present_message"] =
+        (*variables)["name"] + "_ != null";
+  }
+
+  // For repeated builders, the underlying list tracks mutability state.
+  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableMessageFieldLiteGenerator::
+ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
+                      Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+    SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having a method specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  if (SupportFieldPresence(descriptor_->file()) ||
+      descriptor_->containing_oneof() == NULL) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+      "}\n");
+  } else {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $name$_ != null;\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+      "}\n");
+  }
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $name$_ = value;\n"
+    "  $set_has_field_bit_message$\n"
+    "  }\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  $name$_ = builderForValue.build();\n"
+    "  $set_has_field_bit_message$\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void merge$capitalized_name$($type$ value) {\n"
+    "  if ($name$_ != null &&\n"
+    "      $name$_ != $type$.getDefaultInstance()) {\n"
+    "    $name$_ =\n"
+    "      $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+    "  } else {\n"
+    "    $name$_ = value;\n"
+    "  }\n"
+    "  $set_has_field_bit_message$\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {"
+    "  $name$_ = null;\n"
+    "  $clear_has_field_bit_message$\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return instance.has$capitalized_name$();\n"
+    "}\n");
+
+  // Field getField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "  }\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.merge$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "get$capitalized_name$FieldBuilder();\n");
+  }
+}
+
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  // noop for scalars
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  // TODO(dweis): Update this code to avoid the builder allocation and instead
+  // only allocate a submessage that isn't made immutable. Rely on the top
+  // message calling makeImmutable once done to actually traverse the tree and
+  // finalize state. This will avoid:
+  // - transitive builder allocations
+  // - the extra transitive iteration for streamed fields
+  // - reallocations for copying repeated fields
+  printer->Print(variables_,
+      "$type$.Builder subBuilder = null;\n"
+      "if ($is_field_present_message$) {\n"
+      "  subBuilder = $name$_.toBuilder();\n"
+      "}\n");
+
+    if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+      printer->Print(variables_,
+        "$name$_ = input.readGroup($number$, $type$.parser(),\n"
+        "    extensionRegistry);\n");
+    } else {
+      printer->Print(variables_,
+        "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
+    }
+
+  printer->Print(variables_,
+    "if (subBuilder != null) {\n"
+    "  subBuilder.mergeFrom($name$_);\n"
+    "  $name$_ = subBuilder.buildPartial();\n"
+    "}\n"
+    "$set_has_field_bit_message$\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for messages.
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldLiteGenerator::
+ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutableMessageFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldLiteGenerator::
+~ImmutableMessageOneofFieldLiteGenerator() {}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "     return ($type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $type$.getDefaultInstance();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  $oneof_name$_ = value;\n"
+    "  $set_oneof_case_message$;\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  $oneof_name$_ = builderForValue.build();\n"
+    "  $set_oneof_case_message$;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void merge$capitalized_name$($type$ value) {\n"
+    "  if ($has_oneof_case_message$ &&\n"
+    "      $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+    "    $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+    "        .mergeFrom(value).buildPartial();\n"
+    "  } else {\n"
+    "    $oneof_name$_ = value;\n"
+    "  }\n"
+    "  $set_oneof_case_message$;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    // boolean hasField()
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+
+  // Field getField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.merge$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$oneof_name$_ = visitor.visitOneofMessage(\n"
+    "    $has_oneof_case_message$,\n"
+    "    $oneof_name$_,\n"
+    "    other.$oneof_name$_);\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$type$.Builder subBuilder = null;\n"
+    "if ($has_oneof_case_message$) {\n"
+    "  subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
+    "}\n");
+
+    if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+      printer->Print(variables_,
+        "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
+        "    extensionRegistry);\n");
+    } else {
+      printer->Print(variables_,
+        "$oneof_name$_ =\n"
+        "     input.readMessage($type$.parser(), extensionRegistry);\n");
+    }
+
+  printer->Print(variables_,
+    "if (subBuilder != null) {\n"
+    "  subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
+    "  $oneof_name$_ = subBuilder.buildPartial();\n"
+    "}\n");
+  printer->Print(variables_,
+    "$set_oneof_case_message$;\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldLiteGenerator::
+RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                       int messageBitIndex,
+                                       int builderBitIndex,
+                                       Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver())  {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      context->GetFieldGeneratorInfo(descriptor),
+                      name_resolver_, &variables_);
+}
+
+RepeatedImmutableMessageFieldLiteGenerator::
+~RepeatedImmutableMessageFieldLiteGenerator() {}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having methods specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> \n"
+    "    get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return $name$_;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$is_mutable$) {\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "   }\n"
+    "}\n"
+    "\n");
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, builderForValue.build());\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(index, value);\n"
+    "}\n");
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(builderForValue.build());\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(index, builderForValue.build());\n"
+    "}\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  com.google.protobuf.AbstractMessageLite.addAll(\n"
+    "      values, $name$_);\n"
+    "}\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_ = emptyProtobufList();\n"
+    "}\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void remove$capitalized_name$(int index) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.remove(index);\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // The comments above the methods below are based on a hypothetical
+  // repeated field of type "Field" called "RepeatedField".
+
+  // List<Field> getRepeatedFieldList()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList(\n"
+    "      instance.get$capitalized_name$List());\n"
+    "}\n");
+
+  // int getRepeatedFieldCount()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return instance.get$capitalized_name$Count();\n"
+    "}");
+
+  // Field getRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return instance.get$capitalized_name$(index);\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(index, builderForValue);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values) {\n"
+    "  copyOnWrite();\n"
+    "  instance.addAll$capitalized_name$(values);\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+    "  copyOnWrite();\n"
+    "  instance.remove$capitalized_name$(index);\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_= visitor.visitList($name$_, other.$name$_);\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
+
+    if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+      printer->Print(variables_,
+        "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
+        "    extensionRegistry));\n");
+    } else {
+      printer->Print(variables_,
+        "$name$_.add(\n"
+        "    input.readMessage($type$.parser(), extensionRegistry));\n");
+    }
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_mutable$) {\n"
+    "  $name$_.makeImmutable();\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.write$group_or_message$($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.h
new file mode 100644
index 0000000..6132154
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -0,0 +1,157 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+  explicit ImmutableMessageFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMessageFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator);
+};
+
+class ImmutableMessageOneofFieldLiteGenerator
+    : public ImmutableMessageFieldLiteGenerator {
+ public:
+  ImmutableMessageOneofFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableMessageOneofFieldLiteGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableMessageFieldLiteGenerator
+    : public ImmutableFieldLiteGenerator {
+ public:
+  explicit RepeatedImmutableMessageFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableMessageFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.cc
new file mode 100644
index 0000000..d4d2593
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -0,0 +1,1094 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_lite.h>
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message_builder.h>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+  return SupportFieldPresence(descriptor->file()) ||
+      HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+                                   ClassNameResolver* name_resolver) {
+  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+  return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+}  // namespace
+
+// ===================================================================
+ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator(
+    const Descriptor* descriptor, Context* context)
+  : MessageGenerator(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()),
+    field_generators_(descriptor, context_) {
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
+}
+
+ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
+
+void ImmutableMessageLiteGenerator::GenerateStaticVariables(
+    io::Printer* printer, int* bytecode_estimate) {
+  // Generate static members for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+        .GenerateStaticVariables(printer, bytecode_estimate);
+  }
+}
+
+int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers(
+    io::Printer* printer) {
+  int bytecode_estimate = 0;
+  // Generate static member initializers for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    bytecode_estimate +=
+        ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+            .GenerateStaticVariableInitializers(printer);
+  }
+  return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "public interface $classname$OrBuilder extends \n"
+      "    $extra_interfaces$\n"
+      "     com.google.protobuf.GeneratedMessageLite.\n"
+      "          ExtendableMessageOrBuilder<\n"
+      "              $classname$, $classname$.Builder> {\n",
+      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "public interface $classname$OrBuilder extends\n"
+      "    $extra_interfaces$\n"
+      "    com.google.protobuf.MessageLiteOrBuilder {\n",
+      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+      "classname", descriptor_->name());
+  }
+
+  printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      printer->Print("\n");
+      field_generators_.get(descriptor_->field(i))
+                       .GenerateInterfaceMembers(printer);
+    }
+    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+      printer->Print(
+          "\n"
+          "public $classname$.$oneof_capitalized_name$Case "
+          "get$oneof_capitalized_name$Case();\n",
+          "oneof_capitalized_name",
+          context_->GetOneofGeneratorInfo(
+              descriptor_->oneof_decl(i))->capitalized_name,
+          "classname",
+          context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+    }
+  printer->Outdent();
+
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
+  bool is_own_file =
+    descriptor_->containing_type() == NULL &&
+    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+
+  map<string, string> variables;
+  variables["static"] = is_own_file ? " " : " static ";
+  variables["classname"] = descriptor_->name();
+  variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+
+  WriteMessageDocComment(printer, descriptor_);
+
+  // The builder_type stores the super type name of the nested Builder class.
+  string builder_type;
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(variables,
+      "public $static$final class $classname$ extends\n"
+      "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+      "      $classname$, $classname$.Builder> implements\n"
+      "    $extra_interfaces$\n"
+      "    $classname$OrBuilder {\n");
+    builder_type = strings::Substitute(
+        "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+        name_resolver_->GetImmutableClassName(descriptor_));
+  } else {
+    printer->Print(variables,
+        "public $static$final class $classname$ extends\n"
+        "    com.google.protobuf.GeneratedMessageLite<\n"
+        "        $classname$, $classname$.Builder> implements\n"
+        "    $extra_interfaces$\n"
+        "    $classname$OrBuilder {\n");
+
+    builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
+  }
+  printer->Indent();
+
+
+  GenerateConstructor(printer);
+
+  // Nested types
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    EnumLiteGenerator(descriptor_->enum_type(i), true, context_)
+        .Generate(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // Don't generate Java classes for map entry messages.
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageLiteGenerator messageGenerator(
+        descriptor_->nested_type(i), context_);
+    messageGenerator.GenerateInterface(printer);
+    messageGenerator.Generate(printer);
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Integers for bit fields.
+    int totalBits = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      totalBits += field_generators_.get(descriptor_->field(i))
+          .GetNumBitsForMessage();
+    }
+    int totalInts = (totalBits + 31) / 32;
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print("private int $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  // oneof
+  map<string, string> vars;
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->name;
+    vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+        descriptor_->oneof_decl(i))->capitalized_name;
+    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+    // oneofCase_ and oneof_
+    printer->Print(vars,
+      "private int $oneof_name$Case_ = 0;\n"
+      "private java.lang.Object $oneof_name$_;\n");
+    // OneofCase enum
+    printer->Print(vars,
+      "public enum $oneof_capitalized_name$Case\n"
+      "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "$field_name$($field_number$),\n",
+        "field_name",
+        ToUpper(field->name()),
+        "field_number",
+        SimpleItoa(field->number()));
+    }
+    printer->Print(
+      "$cap_oneof_name$_NOT_SET(0);\n",
+      "cap_oneof_name",
+      ToUpper(vars["oneof_name"]));
+    printer->Print(vars,
+      "private final int value;\n"
+      "private $oneof_capitalized_name$Case(int value) {\n"
+      "  this.value = value;\n"
+      "}\n");
+    printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
+      "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
+      "  switch (value) {\n");
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "    case $field_number$: return $field_name$;\n",
+        "field_number",
+        SimpleItoa(field->number()),
+        "field_name",
+        ToUpper(field->name()));
+    }
+    printer->Print(
+      "    case 0: return $cap_oneof_name$_NOT_SET;\n"
+      "    default: return null;\n"
+      "  }\n"
+      "}\n"
+      "public int getNumber() {\n"
+      "  return this.value;\n"
+      "}\n",
+      "cap_oneof_name", ToUpper(vars["oneof_name"]));
+    printer->Outdent();
+    printer->Print("};\n\n");
+    // oneofCase()
+    printer->Print(vars,
+      "public $oneof_capitalized_name$Case\n"
+      "get$oneof_capitalized_name$Case() {\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
+      "      $oneof_name$Case_);\n"
+      "}\n"
+      "\n"
+      "private void clear$oneof_capitalized_name$() {\n"
+      "  $oneof_name$Case_ = 0;\n"
+      "  $oneof_name$_ = null;\n"
+      "}\n"
+      "\n");
+  }
+
+  // Fields
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("public static final int $constant_name$ = $number$;\n",
+      "constant_name", FieldConstantName(descriptor_->field(i)),
+      "number", SimpleItoa(descriptor_->field(i)->number()));
+    field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+    printer->Print("\n");
+  }
+
+  GenerateMessageSerializationMethods(printer);
+
+  GenerateParseFromMethods(printer);
+  GenerateBuilder(printer);
+
+  if (HasRequiredFields(descriptor_)) {
+    // Memoizes whether the protocol buffer is fully initialized (has all
+    // required fields). -1 means not yet computed. 0 means false and 1 means
+    // true.
+    printer->Print(
+      "private byte memoizedIsInitialized = -1;\n");
+  }
+
+  printer->Print(
+    "protected final Object dynamicMethod(\n"
+    "    com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+    "    Object arg0, Object arg1) {\n"
+    "  switch (method) {\n"
+    "    case NEW_MUTABLE_INSTANCE: {\n"
+    "      return new $classname$();\n"
+    "    }\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Indent();
+  printer->Indent();
+
+  printer->Print(
+    "case IS_INITIALIZED: {\n");
+  printer->Indent();
+  GenerateDynamicMethodIsInitialized(printer);
+  printer->Outdent();
+
+  printer->Print(
+    "}\n"
+    "case MAKE_IMMUTABLE: {\n");
+
+  printer->Indent();
+  GenerateDynamicMethodMakeImmutable(printer);
+  printer->Outdent();
+
+  printer->Print(
+    "}\n"
+    "case NEW_BUILDER: {\n");
+
+  printer->Indent();
+  GenerateDynamicMethodNewBuilder(printer);
+  printer->Outdent();
+
+  printer->Print(
+    "}\n"
+    "case VISIT: {\n");
+
+  printer->Indent();
+  GenerateDynamicMethodVisit(printer);
+  printer->Outdent();
+
+  printer->Print(
+    "}\n"
+    "case MERGE_FROM_STREAM: {\n");
+
+  printer->Indent();
+  GenerateDynamicMethodMergeFromStream(printer);
+  printer->Outdent();
+
+  printer->Print(
+    "}\n"
+    "case GET_DEFAULT_INSTANCE: {\n"
+    "  return DEFAULT_INSTANCE;\n"
+    "}\n"
+    "case GET_PARSER: {\n"
+    // Generally one would use the lazy initialization holder pattern for
+    // manipulating static fields but that has exceptional cost on Android as
+    // it will generate an extra class for every message. Instead, use the
+    // double-check locking pattern which works just as well.
+    "  if (PARSER == null) {"
+    "    synchronized ($classname$.class) {\n"
+    "      if (PARSER == null) {\n"
+    "        PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+    "      }\n"
+    "    }\n"
+    "  }\n"
+    "  return PARSER;\n"
+    "}\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+    "  }\n"
+    "  throw new UnsupportedOperationException();\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+
+  // Carefully initialize the default instance in such a way that it doesn't
+  // conflict with other initialization.
+  printer->Print(
+    "private static final $classname$ DEFAULT_INSTANCE;\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  printer->Print(
+    "static {\n"
+    "  DEFAULT_INSTANCE = new $classname$();\n"
+    "  DEFAULT_INSTANCE.makeImmutable();\n"
+    "}\n"
+    "\n",
+    "classname", descriptor_->name());
+  printer->Print(
+      "public static $classname$ getDefaultInstance() {\n"
+      "  return DEFAULT_INSTANCE;\n"
+      "}\n"
+      "\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  GenerateParser(printer);
+
+  // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+  // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+  // the outer class's FileDescriptor.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
+        .Generate(printer);
+  }
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+      SortFieldsByNumber(descriptor_));
+
+  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeOrdering());
+
+  printer->Print(
+    "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
+    "                    throws java.io.IOException {\n");
+  printer->Indent();
+  if (HasPackedFields(descriptor_)) {
+    // writeTo(CodedOutputStream output) might be invoked without
+    // getSerializedSize() ever being called, but we need the memoized
+    // sizes in case this message has packed fields. Rather than emit checks for
+    // each packed field, just call getSerializedSize() up front.
+    // In most cases, getSerializedSize() will have already been called anyway
+    // by one of the wrapper writeTo() methods, making this call cheap.
+    printer->Print(
+      "getSerializedSize();\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessageLite\n"
+        "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+        "    .ExtensionWriter extensionWriter =\n"
+        "      newMessageSetExtensionWriter();\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    } else {
+      printer->Print(
+        "com.google.protobuf.GeneratedMessageLite\n"
+        "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+        "    .ExtensionWriter extensionWriter =\n"
+        "      newExtensionWriter();\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    }
+  }
+
+  // Merge the fields and the extension ranges, both sorted by field number.
+  for (int i = 0, j = 0;
+       i < descriptor_->field_count() || j < sorted_extensions.size();
+       ) {
+    if (i == descriptor_->field_count()) {
+      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+    } else if (j == sorted_extensions.size()) {
+      GenerateSerializeOneField(printer, sorted_fields[i++]);
+    } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+      GenerateSerializeOneField(printer, sorted_fields[i++]);
+    } else {
+      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+    }
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "unknownFields.writeTo(output);\n");
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n"
+    "public int getSerializedSize() {\n"
+    "  int size = memoizedSerializedSize;\n"
+    "  if (size != -1) return size;\n"
+    "\n"
+    "  size = 0;\n");
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+        "size += extensionsSerializedSizeAsMessageSet();\n");
+    } else {
+      printer->Print(
+        "size += extensionsSerializedSize();\n");
+    }
+  }
+
+  if (PreserveUnknownFields(descriptor_)) {
+    printer->Print(
+      "size += unknownFields.getSerializedSize();\n");
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  memoizedSerializedSize = size;\n"
+    "  return size;\n"
+    "}\n"
+    "\n");
+}
+
+void ImmutableMessageLiteGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+  // Note:  These are separate from GenerateMessageSerializationMethods()
+  //   because they need to be generated even for messages that are optimized
+  //   for code size.
+  printer->Print(
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.ByteString data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.ByteString data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(byte[] data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    byte[] data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    java.io.InputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(\n"
+    "    java.io.InputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneField(
+    io::Printer* printer, const FieldDescriptor* field) {
+  field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange(
+    io::Printer* printer, const Descriptor::ExtensionRange* range) {
+  printer->Print(
+    "extensionWriter.writeUntil($end$, output);\n",
+    "end", SimpleItoa(range->end));
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) {
+  printer->Print(
+    "public static Builder newBuilder() {\n"
+    "  return DEFAULT_INSTANCE.toBuilder();\n"
+    "}\n"
+    "public static Builder newBuilder($classname$ prototype) {\n"
+    "  return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+    "}\n"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  MessageBuilderLiteGenerator builderGenerator(descriptor_, context_);
+  builderGenerator.Generate(printer);
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
+    io::Printer* printer) {
+  // Returns null for false, DEFAULT_INSTANCE for true.
+  if (!HasRequiredFields(descriptor_)) {
+    printer->Print("return DEFAULT_INSTANCE;\n");
+    return;
+  }
+
+  // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+  printer->Print(
+    "byte isInitialized = memoizedIsInitialized;\n"
+    "if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
+    "if (isInitialized == 0) return null;\n"
+    "\n"
+    "boolean shouldMemoize = ((Boolean) arg0).booleanValue();\n");
+
+  // Check that all required fields in this message are set.
+  // TODO(kenton):  We can optimize this when we switch to putting all the
+  //   "has" fields into a single bitfield.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+    if (field->is_required()) {
+      printer->Print(
+        "if (!has$name$()) {\n"
+        "  if (shouldMemoize) {\n"
+        "    memoizedIsInitialized = 0;\n"
+        "  }\n"
+        "  return null;\n"
+        "}\n",
+        "name", info->capitalized_name);
+    }
+  }
+
+  // Now check that all embedded messages are initialized.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+    if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+        HasRequiredFields(field->message_type())) {
+      switch (field->label()) {
+        case FieldDescriptor::LABEL_REQUIRED:
+          printer->Print(
+            "if (!get$name$().isInitialized()) {\n"
+            "  if (shouldMemoize) {\n"
+            "    memoizedIsInitialized = 0;\n"
+            "  }\n"
+            "  return null;\n"
+            "}\n",
+            "type", name_resolver_->GetImmutableClassName(
+                field->message_type()),
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_OPTIONAL:
+          if (!SupportFieldPresence(descriptor_->file()) &&
+              field->containing_oneof() != NULL) {
+            const OneofDescriptor* oneof = field->containing_oneof();
+            const OneofGeneratorInfo* oneof_info =
+                context_->GetOneofGeneratorInfo(oneof);
+            printer->Print(
+              "if ($oneof_name$Case_ == $field_number$) {\n",
+              "oneof_name", oneof_info->name,
+              "field_number", SimpleItoa(field->number()));
+          } else {
+            printer->Print(
+              "if (has$name$()) {\n",
+              "name", info->capitalized_name);
+          }
+          printer->Print(
+            "  if (!get$name$().isInitialized()) {\n"
+            "    if (shouldMemoize) {\n"
+            "      memoizedIsInitialized = 0;\n"
+            "    }\n"
+            "    return null;\n"
+            "  }\n"
+            "}\n",
+            "name", info->capitalized_name);
+          break;
+        case FieldDescriptor::LABEL_REPEATED:
+          if (IsMapEntry(field->message_type())) {
+            printer->Print(
+              "for ($type$ item : get$name$().values()) {\n"
+              "  if (!item.isInitialized()) {\n"
+              "    if (shouldMemoize) {\n"
+              "      memoizedIsInitialized = 0;\n"
+              "    }\n"
+              "    return null;\n"
+              "  }\n"
+              "}\n",
+              "type", MapValueImmutableClassdName(field->message_type(),
+                                                  name_resolver_),
+              "name", info->capitalized_name);
+          } else {
+            printer->Print(
+              "for (int i = 0; i < get$name$Count(); i++) {\n"
+              "  if (!get$name$(i).isInitialized()) {\n"
+              "    if (shouldMemoize) {\n"
+              "      memoizedIsInitialized = 0;\n"
+              "    }\n"
+              "    return null;\n"
+              "  }\n"
+              "}\n",
+              "type", name_resolver_->GetImmutableClassName(
+                  field->message_type()),
+              "name", info->capitalized_name);
+          }
+          break;
+      }
+    }
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "if (!extensionsAreInitialized()) {\n"
+      "  if (shouldMemoize) {\n"
+      "    memoizedIsInitialized = 0;\n"
+      "  }\n"
+      "  return null;\n"
+      "}\n");
+  }
+
+  printer->Print(
+    "if (shouldMemoize) memoizedIsInitialized = 1;\n");
+
+  printer->Print(
+    "return DEFAULT_INSTANCE;\n"
+    "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
+    io::Printer* printer) {
+
+  // Output generation code for each field.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateDynamicMethodMakeImmutableCode(printer);
+  }
+
+  printer->Print(
+    "return null;\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
+    io::Printer* printer) {
+  printer->Print(
+    "return new Builder();\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit(
+    io::Printer* printer) {
+  printer->Print(
+    "Visitor visitor = (Visitor) arg0;\n"
+    "$classname$ other = ($classname$) arg1;\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(
+          descriptor_->field(i)).GenerateVisitCode(printer);
+    }
+  }
+
+  // Merge oneof fields.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    printer->Print(
+      "switch (other.get$oneof_capitalized_name$Case()) {\n",
+      "oneof_capitalized_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->capitalized_name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_name$: {\n",
+        "field_name",
+        ToUpper(field->name()));
+      printer->Indent();
+      field_generators_.get(field).GenerateVisitCode(printer);
+      printer->Print(
+          "break;\n");
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+    printer->Print(
+      "case $cap_oneof_name$_NOT_SET: {\n"
+      "  visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n"
+      "  break;\n"
+      "}\n",
+      "cap_oneof_name",
+      ToUpper(context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name),
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Outdent();
+    printer->Print(
+      "}\n");
+  }
+
+  printer->Print(
+    "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n"
+    "    .INSTANCE) {\n");
+  printer->Indent();
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    const OneofDescriptor* field = descriptor_->oneof_decl(i);
+    printer->Print(
+      "if (other.$oneof_name$Case_ != 0) {\n"
+      "  $oneof_name$Case_ = other.$oneof_name$Case_;\n"
+      "}\n",
+      "oneof_name", context_->GetOneofGeneratorInfo(field)->name);
+  }
+
+  if (GenerateHasBits(descriptor_)) {
+    // Integers for bit fields.
+    int totalBits = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      totalBits += field_generators_.get(descriptor_->field(i))
+          .GetNumBitsForMessage();
+    }
+    int totalInts = (totalBits + 31) / 32;
+
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print(
+        "$bit_field_name$ |= other.$bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+
+
+  printer->Print(
+    "return this;\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
+    io::Printer* printer) {
+  printer->Print(
+      "com.google.protobuf.CodedInputStream input =\n"
+      "    (com.google.protobuf.CodedInputStream) arg0;\n"
+      "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n"
+      "    (com.google.protobuf.ExtensionRegistryLite) arg1;\n"
+      "try {\n");
+  printer->Indent();
+
+  printer->Print(
+    "boolean done = false;\n"
+    "while (!done) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "int tag = input.readTag();\n"
+    "switch (tag) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "case 0:\n"          // zero signals EOF / limit reached
+    "  done = true;\n"
+    "  break;\n");
+
+  if (PreserveUnknownFields(descriptor_)) {
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "default: {\n"
+        "  if (!parseUnknownField(getDefaultInstanceForType(),\n"
+        "                         input, extensionRegistry, tag)) {\n"
+        "    done = true;\n"  // it's an endgroup tag
+        "  }\n"
+        "  break;\n"
+        "}\n");
+    } else {
+      printer->Print(
+        "default: {\n"
+        "  if (!parseUnknownField(tag, input)) {\n"
+        "    done = true;\n"  // it's an endgroup tag
+        "  }\n"
+        "  break;\n"
+        "}\n");
+    }
+  } else {
+    printer->Print(
+      "default: {\n"
+      "  if (!input.skipField(tag)) {\n"
+      "    done = true;\n"  // it's an endgroup tag
+      "  }\n"
+      "  break;\n"
+      "}\n");
+  }
+
+  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+      SortFieldsByNumber(descriptor_));
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
+      WireFormat::WireTypeForFieldType(field->type()));
+
+    printer->Print(
+      "case $tag$: {\n",
+      "tag", SimpleItoa(tag));
+    printer->Indent();
+
+    field_generators_.get(field).GenerateParsingCode(printer);
+
+    printer->Outdent();
+    printer->Print(
+      "  break;\n"
+      "}\n");
+
+    if (field->is_packable()) {
+      // To make packed = true wire compatible, we generate parsing code from a
+      // packed version of this field regardless of field->options().packed().
+      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+      printer->Print(
+        "case $tag$: {\n",
+        "tag", SimpleItoa(packed_tag));
+      printer->Indent();
+
+      field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+      printer->Outdent();
+      printer->Print(
+        "  break;\n"
+        "}\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // switch (tag)
+      "}\n");     // while (!done)
+
+  printer->Outdent();
+  printer->Print(
+      "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+      "  throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+      "} catch (java.io.IOException e) {\n"
+      "  throw new RuntimeException(\n"
+      "      new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "          e.getMessage()).setUnfinishedMessage(this));\n"
+      "} finally {\n");
+  printer->Indent();
+
+  printer->Outdent();
+  printer->Print(
+      "}\n");     // finally
+}
+
+// ===================================================================
+
+namespace {
+bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
+  if (field->is_repeated()) {
+    return false;
+  }
+  if (SupportFieldPresence(field->file())) {
+    return true;
+  }
+  return GetJavaType(field) == JAVATYPE_MESSAGE &&
+      field->containing_oneof() == NULL;
+}
+}  // namespace
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateExtensionRegistrationCode(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
+      .GenerateRegistrationCode(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+      .GenerateExtensionRegistrationCode(printer);
+  }
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::
+GenerateConstructor(io::Printer* printer) {
+  printer->Print(
+      "private $classname$() {\n",
+      "classname", descriptor_->name());
+  printer->Indent();
+
+  // Initialize all fields to default.
+  GenerateInitializers(printer);
+
+  printer->Outdent();
+  printer->Print(
+      "}\n");
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
+  printer->Print(
+      "private static volatile com.google.protobuf.Parser<$classname$> PARSER;\n"
+      "\n"
+      "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+      "  return DEFAULT_INSTANCE.getParserForType();\n"
+      "}\n",
+      "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateInitializationCode(printer);
+    }
+  }
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.h
new file mode 100644
index 0000000..292c1c5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_message_lite.h
@@ -0,0 +1,93 @@
+// 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.
+
+// Author: dweis@google.com (Daniel Weis)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageLiteGenerator : public MessageGenerator {
+ public:
+  explicit ImmutableMessageLiteGenerator(const Descriptor* descriptor,
+                                     Context* context);
+  virtual ~ImmutableMessageLiteGenerator();
+
+  virtual void Generate(io::Printer* printer);
+  virtual void GenerateInterface(io::Printer* printer);
+  virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
+  virtual int GenerateStaticVariableInitializers(io::Printer* printer);
+
+ private:
+
+  void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateParseFromMethods(io::Printer* printer);
+  void GenerateSerializeOneField(io::Printer* printer,
+                                 const FieldDescriptor* field);
+  void GenerateSerializeOneExtensionRange(
+      io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+  void GenerateBuilder(io::Printer* printer);
+  void GenerateDynamicMethodIsInitialized(io::Printer* printer);
+  void GenerateDynamicMethodMakeImmutable(io::Printer* printer);
+  void GenerateDynamicMethodVisit(io::Printer* printer);
+  void GenerateDynamicMethodMergeFromStream(io::Printer* printer);
+  void GenerateDynamicMethodNewBuilder(io::Printer* printer);
+  void GenerateInitializers(io::Printer* printer);
+  void GenerateEqualsAndHashCode(io::Printer* printer);
+  void GenerateParser(io::Printer* printer);
+  void GenerateConstructor(io::Printer* printer);
+
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.cc
new file mode 100644
index 0000000..bffe4f1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -0,0 +1,273 @@
+// 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.
+
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+// A suffix that will be appended to the file's outer class name if the name
+// conflicts with some other types defined in the file.
+const char* kOuterClassNameSuffix = "OuterClass";
+
+// Strip package name from a descriptor's full name.
+// For example:
+//   Full name   : foo.Bar.Baz
+//   Package name: foo
+//   After strip : Bar.Baz
+string StripPackageName(const string& full_name,
+                        const FileDescriptor* file) {
+  if (file->package().empty()) {
+    return full_name;
+  } else {
+    // Strip package name
+    return full_name.substr(file->package().size() + 1);
+  }
+}
+
+// Get the name of a message's Java class without package name prefix.
+string ClassNameWithoutPackage(const Descriptor* descriptor,
+                               bool immutable) {
+  return StripPackageName(descriptor->full_name(),
+                          descriptor->file());
+}
+
+// Get the name of an enum's Java class without package name prefix.
+string ClassNameWithoutPackage(const EnumDescriptor* descriptor,
+                               bool immutable) {
+  // Doesn't append "Mutable" for enum type's name.
+  const Descriptor* message_descriptor = descriptor->containing_type();
+  if (message_descriptor == NULL) {
+    return descriptor->name();
+  } else {
+    return ClassNameWithoutPackage(message_descriptor, immutable) +
+           "." + descriptor->name();
+  }
+}
+
+// Get the name of a service's Java class without package name prefix.
+string ClassNameWithoutPackage(const ServiceDescriptor* descriptor,
+                               bool immutable) {
+  string full_name = StripPackageName(descriptor->full_name(),
+                                      descriptor->file());
+  // We don't allow nested service definitions.
+  GOOGLE_CHECK(full_name.find('.') == string::npos);
+  return full_name;
+}
+
+// Check whether a given message or its nested types has the given class name.
+bool MessageHasConflictingClassName(const Descriptor* message,
+                                    const string& classname) {
+  if (message->name() == classname) return true;
+  for (int i = 0; i < message->nested_type_count(); ++i) {
+    if (MessageHasConflictingClassName(message->nested_type(i), classname)) {
+      return true;
+    }
+  }
+  for (int i = 0; i < message->enum_type_count(); ++i) {
+    if (message->enum_type(i)->name() == classname) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+ClassNameResolver::ClassNameResolver() {
+}
+
+ClassNameResolver::~ClassNameResolver() {
+}
+
+string ClassNameResolver::GetFileDefaultImmutableClassName(
+    const FileDescriptor* file) {
+  string basename;
+  string::size_type last_slash = file->name().find_last_of('/');
+  if (last_slash == string::npos) {
+    basename = file->name();
+  } else {
+    basename = file->name().substr(last_slash + 1);
+  }
+  return UnderscoresToCamelCase(StripProto(basename), true);
+}
+
+string ClassNameResolver::GetFileImmutableClassName(
+    const FileDescriptor* file) {
+  string& class_name = file_immutable_outer_class_names_[file];
+  if (class_name.empty()) {
+    if (file->options().has_java_outer_classname()) {
+      class_name = file->options().java_outer_classname();
+    } else {
+      class_name = GetFileDefaultImmutableClassName(file);
+      if (HasConflictingClassName(file, class_name)) {
+        class_name += kOuterClassNameSuffix;
+      }
+    }
+  }
+  return class_name;
+}
+
+string ClassNameResolver::GetFileClassName(const FileDescriptor* file,
+                                           bool immutable) {
+  if (immutable) {
+    return GetFileImmutableClassName(file);
+  } else {
+    return "Mutable" + GetFileImmutableClassName(file);
+  }
+}
+
+// Check whether there is any type defined in the proto file that has
+// the given class name.
+bool ClassNameResolver::HasConflictingClassName(
+    const FileDescriptor* file, const string& classname) {
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    if (file->enum_type(i)->name() == classname) {
+      return true;
+    }
+  }
+  for (int i = 0; i < file->service_count(); i++) {
+    if (file->service(i)->name() == classname) {
+      return true;
+    }
+  }
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (MessageHasConflictingClassName(file->message_type(i), classname)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+string ClassNameResolver::GetDescriptorClassName(
+    const FileDescriptor* descriptor) {
+  return GetFileImmutableClassName(descriptor);
+}
+
+string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
+                                       bool immutable) {
+  string result = FileJavaPackage(descriptor, immutable);
+  if (!result.empty()) result += '.';
+  result += GetFileClassName(descriptor, immutable);
+  return result;
+}
+
+// Get the full name of a Java class by prepending the Java package name
+// or outer class name.
+string ClassNameResolver::GetClassFullName(const string& name_without_package,
+                                           const FileDescriptor* file,
+                                           bool immutable,
+                                           bool multiple_files) {
+  string result;
+  if (multiple_files) {
+    result = FileJavaPackage(file, immutable);
+  } else {
+    result = GetClassName(file, immutable);
+  }
+  if (!result.empty()) {
+    result += '.';
+  }
+  result += name_without_package;
+  return result;
+}
+
+string ClassNameResolver::GetClassName(const Descriptor* descriptor,
+                                       bool immutable) {
+  return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
+                          descriptor->file(), immutable,
+                          MultipleJavaFiles(descriptor->file(), immutable));
+}
+
+string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor,
+                                       bool immutable) {
+  return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
+                          descriptor->file(), immutable,
+                          MultipleJavaFiles(descriptor->file(), immutable));
+}
+
+string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor,
+                                       bool immutable) {
+  return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
+                          descriptor->file(), immutable,
+                          MultipleJavaFiles(descriptor->file(), immutable));
+}
+
+// Get the Java Class style full name of a message.
+string ClassNameResolver::GetJavaClassFullName(
+    const string& name_without_package,
+    const FileDescriptor* file,
+    bool immutable) {
+  string result;
+  if (MultipleJavaFiles(file, immutable)) {
+    result = FileJavaPackage(file, immutable);
+    if (!result.empty()) result += '.';
+  } else {
+    result = GetClassName(file, immutable);
+    if (!result.empty()) result += '$';
+  }
+  result += StringReplace(name_without_package, ".", "$", true);
+  return result;
+}
+
+string ClassNameResolver::GetExtensionIdentifierName(
+    const FieldDescriptor* descriptor, bool immutable) {
+  return GetClassName(descriptor->containing_type(), immutable) + "." +
+         descriptor->name();
+}
+
+
+string ClassNameResolver::GetJavaImmutableClassName(
+    const Descriptor* descriptor) {
+  return GetJavaClassFullName(
+      ClassNameWithoutPackage(descriptor, true),
+      descriptor->file(), true);
+}
+
+string ClassNameResolver::GetJavaImmutableClassName(
+    const EnumDescriptor* descriptor) {
+  return GetJavaClassFullName(
+      ClassNameWithoutPackage(descriptor, true),
+      descriptor->file(), true);
+}
+
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.h
new file mode 100644
index 0000000..570d8d8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_name_resolver.h
@@ -0,0 +1,125 @@
+// 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_COMPILER_JAVA_NAME_RESOLVER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace java {
+
+// Used to get the Java class related names for a given descriptor. It caches
+// the results to avoid redundant calculation across multiple name queries.
+// Thread-safety note: This class is *not* thread-safe.
+class ClassNameResolver {
+ public:
+  ClassNameResolver();
+  ~ClassNameResolver();
+
+  // Gets the unqualified outer class name for the file.
+  string GetFileClassName(const FileDescriptor* file, bool immutable);
+  // Gets the unqualified immutable outer class name of a file.
+  string GetFileImmutableClassName(const FileDescriptor* file);
+  // Gets the unqualified default immutable outer class name of a file
+  // (converted from the proto file's name).
+  string GetFileDefaultImmutableClassName(const FileDescriptor* file);
+
+  // Check whether there is any type defined in the proto file that has
+  // the given class name.
+  bool HasConflictingClassName(const FileDescriptor* file,
+                               const string& classname);
+
+  // Gets the name of the outer class that holds descriptor information.
+  // Descriptors are shared between immutable messages and mutable messages.
+  // Since both of them are generated optionally, the descriptors need to be
+  // put in another common place.
+  string GetDescriptorClassName(const FileDescriptor* file);
+
+  // Gets the fully-qualified class name corresponding to the given descriptor.
+  string GetClassName(const Descriptor* descriptor, bool immutable);
+  string GetClassName(const EnumDescriptor* descriptor, bool immutable);
+  string GetClassName(const ServiceDescriptor* descriptor, bool immutable);
+  string GetClassName(const FileDescriptor* descriptor, bool immutable);
+
+  template<class DescriptorType>
+  string GetImmutableClassName(const DescriptorType* descriptor) {
+    return GetClassName(descriptor, true);
+  }
+  template<class DescriptorType>
+  string GetMutableClassName(const DescriptorType* descriptor) {
+    return GetClassName(descriptor, false);
+  }
+
+  // Gets the fully qualified name of an extension identifier.
+  string GetExtensionIdentifierName(const FieldDescriptor* descriptor,
+                                    bool immutable);
+
+  // Gets the fully qualified name for generated classes in Java convention.
+  // Nested classes will be separated using '$' instead of '.'
+  // For example:
+  //   com.package.OuterClass$OuterMessage$InnerMessage
+  string GetJavaImmutableClassName(const Descriptor* descriptor);
+  string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
+ private:
+  // Get the full name of a Java class by prepending the Java package name
+  // or outer class name.
+  string GetClassFullName(const string& name_without_package,
+                          const FileDescriptor* file,
+                          bool immutable,
+                          bool multiple_files);
+  // Get the Java Class style full name of a message.
+  string GetJavaClassFullName(
+      const string& name_without_package,
+      const FileDescriptor* file,
+      bool immutable);
+  // Caches the result to provide better performance.
+  map<const FileDescriptor*, string> file_immutable_outer_class_names_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_names.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_names.h
new file mode 100644
index 0000000..0d61433
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_names.h
@@ -0,0 +1,87 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Provides a mechanism for mapping a descriptor to the
+// fully-qualified name of the corresponding Java class.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace java {
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified Java class name.
+string ClassName(const Descriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified Java class name.
+string ClassName(const EnumDescriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified Java class name.
+string ClassName(const FileDescriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The fully-qualified Java class name.
+string ClassName(const ServiceDescriptor* descriptor);
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_plugin_unittest.cc
new file mode 100644
index 0000000..3e4910c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -0,0 +1,128 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* context,
+                        string* error) const {
+    string filename = "Test.java";
+    TryInsert(filename, "outer_class_scope", context);
+    TryInsert(filename, "class_scope:foo.Bar", context);
+    TryInsert(filename, "class_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "builder_scope:foo.Bar", context);
+    TryInsert(filename, "builder_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "enum_scope:foo.Qux", context);
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 GeneratorContext* context) const {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        context->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(JavaPluginTest, PluginTest) {
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
+                             "syntax = \"proto2\";\n"
+                             "package foo;\n"
+                             "option java_package = \"\";\n"
+                             "option java_outer_classname = \"Test\";\n"
+                             "message Bar {\n"
+                             "  message Baz {}\n"
+                             "}\n"
+                             "enum Qux { BLAH = 1; }\n",
+                             true));
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  JavaGenerator java_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--java_out", &java_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string java_out = "--java_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    java_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.cc
new file mode 100644
index 0000000..e42ec28
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -0,0 +1,860 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           const FieldGeneratorInfo* info,
+                           ClassNameResolver* name_resolver,
+                           map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["field_type"] = (*variables)["type"];
+  (*variables)["field_list_type"] = "java.util.List<" +
+      (*variables)["boxed_type"] + ">";
+  (*variables)["empty_list"] = "java.util.Collections.emptyList()";
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+      "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
+  (*variables)["capitalized_type"] =
+      GetCapitalizedType(descriptor, /* immutable = */ true);
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  if (IsReferenceType(GetJavaType(descriptor))) {
+    (*variables)["null_check"] =
+        "  if (value == null) {\n"
+        "    throw new NullPointerException();\n"
+        "  }\n";
+  } else {
+    (*variables)["null_check"] = "";
+  }
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  int fixed_size = FixedSize(GetType(descriptor));
+  if (fixed_size != -1) {
+    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+  }
+  (*variables)["on_changed"] = "onChanged();";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["set_has_field_bit_builder"] =
+        GenerateSetBit(builderBitIndex) + ";";
+    (*variables)["clear_has_field_bit_builder"] =
+        GenerateClearBit(builderBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["set_has_field_bit_builder"] = "";
+    (*variables)["clear_has_field_bit_builder"] = "";
+
+    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+      (*variables)["is_field_present_message"] =
+          "!" + (*variables)["name"] + "_.isEmpty()";
+    } else {
+      (*variables)["is_field_present_message"] =
+          (*variables)["name"] + "_ != " + (*variables)["default"];
+    }
+  }
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutablePrimitiveFieldGenerator::
+ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
+
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $field_type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $field_type$ $name$_ $default_init$;\n");
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_builder$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_builder$\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$\n");
+  JavaType type = GetJavaType(descriptor_);
+  if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+    // The default value is not a simple literal so we want to avoid executing
+    // it multiple times.  Instead, get the default out of the default instance.
+    printer->Print(variables_,
+      "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  } else {
+    printer->Print(variables_,
+      "  $name$_ = $default$;\n");
+  }
+  printer->Print(variables_,
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "if (other.has$capitalized_name$()) {\n"
+      "  set$capitalized_name$(other.get$capitalized_name$());\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "if (other.get$capitalized_name$() != $default$) {\n"
+      "  set$capitalized_name$(other.get$capitalized_name$());\n"
+      "}\n");
+  }
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+    "result.$name$_ = $name$_;\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_has_field_bit_message$\n"
+    "$name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for primitives.
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.write$capitalized_type$($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$capitalized_type$Size($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "result = result && (get$capitalized_name$()\n"
+        "    == other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "result = result && (\n"
+        "    java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
+        "    == java.lang.Float.floatToIntBits(\n"
+        "        other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "result = result && (\n"
+        "    java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
+        "    == java.lang.Double.doubleToLongBits(\n"
+        "        other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "result = result && get$capitalized_name$()\n"
+        "    .equals(other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+void ImmutablePrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$();\n");
+      break;
+
+    case JAVATYPE_LONG:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+        "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
+  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldGenerator::
+ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutablePrimitiveFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldGenerator::
+~ImmutablePrimitiveOneofFieldGenerator() {}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($boxed_type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+}
+
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($boxed_type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "    $on_changed$\n"
+    "  }\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  result.$oneof_name$_ = $oneof_name$_;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "set$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_oneof_case_message$;\n"
+    "$oneof_name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.write$capitalized_type$(\n"
+    "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$capitalized_type$Size(\n"
+    "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldGenerator::
+RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                         int messageBitIndex,
+                                         int builderBitIndex,
+                                         Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldGenerator::
+~RepeatedImmutablePrimitiveFieldGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $field_list_type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+
+  if (descriptor_->is_packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize = -1;\n");
+  }
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
+  printer->Print(variables_,
+    "private $field_list_type$ $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
+    // Note:  We return an unmodifiable list because otherwise the caller
+    //   could hold on to the returned list and modify it after the message
+    //   has been built, thus mutating the message which is supposed to be
+    //   immutable.
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+    "      values, $name$_);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
+  printer->Print(variables_,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
+    "$name$_.add(input.read$capitalized_type$());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(length);\n"
+    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
+    "while (input.getBytesUntilLimit() > 0) {\n"
+    "  $name$_.add(input.read$capitalized_type$());\n"
+    "}\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->is_packed()) {
+    // We invoke getSerializedSize in writeTo for messages that have packed
+    // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+    // That makes it safe to rely on the memoized size here.
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$($number$, $name$_.get(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  if (FixedSize(GetType(descriptor_)) == -1) {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  dataSize += com.google.protobuf.CodedOutputStream\n"
+      "    .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  printer->Print(
+      "size += dataSize;\n");
+
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {\n"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeInt32SizeNoTag(dataSize);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->is_packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
+  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.h
new file mode 100644
index 0000000..d0cd12d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -0,0 +1,160 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit ImmutablePrimitiveFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutablePrimitiveFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldGenerator
+    : public ImmutablePrimitiveFieldGenerator {
+ public:
+  ImmutablePrimitiveOneofFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutablePrimitiveOneofFieldGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldGenerator
+    : public ImmutableFieldGenerator {
+ public:
+  explicit RepeatedImmutablePrimitiveFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  virtual ~RepeatedImmutablePrimitiveFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
new file mode 100644
index 0000000..690dad1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -0,0 +1,900 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           const FieldGeneratorInfo* info,
+                           ClassNameResolver* name_resolver,
+                           map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["field_type"] = (*variables)["type"];
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+      "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
+  (*variables)["capitalized_type"] =
+      GetCapitalizedType(descriptor, /* immutable = */ true);
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+
+  string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(
+        GetJavaType(descriptor)), true /* cap_next_letter */);
+  switch (GetJavaType(descriptor)) {
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_FLOAT:
+    case JAVATYPE_DOUBLE:
+    case JAVATYPE_BOOLEAN:
+      (*variables)["field_list_type"] =
+          "com.google.protobuf.Internal." + capitalized_type + "List";
+      (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+      (*variables)["make_name_unmodifiable"] =
+          (*variables)["name"] + "_.makeImmutable()";
+      (*variables)["repeated_get"] =
+          (*variables)["name"] + "_.get" + capitalized_type;
+      (*variables)["repeated_add"] =
+          (*variables)["name"] + "_.add" + capitalized_type;
+      (*variables)["repeated_set"] =
+          (*variables)["name"] + "_.set" + capitalized_type;
+      (*variables)["visit_type"] = capitalized_type;
+      (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
+      break;
+    default:
+      (*variables)["field_list_type"] =
+          "com.google.protobuf.Internal.ProtobufList<" +
+          (*variables)["boxed_type"] + ">";
+      (*variables)["empty_list"] = "emptyProtobufList()";
+      (*variables)["make_name_unmodifiable"] =
+          (*variables)["name"] + "_.makeImmutable()";
+      (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
+      (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
+      (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+      (*variables)["visit_type"] = "ByteString";
+      (*variables)["visit_type_list"] = "visitList";
+  }
+
+  if (IsReferenceType(GetJavaType(descriptor))) {
+    (*variables)["null_check"] =
+        "  if (value == null) {\n"
+        "    throw new NullPointerException();\n"
+        "  }\n";
+  } else {
+    (*variables)["null_check"] = "";
+  }
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  int fixed_size = FixedSize(GetType(descriptor));
+  if (fixed_size != -1) {
+    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+  }
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["clear_has_field_bit_message"] =
+        GenerateClearBit(messageBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["clear_has_field_bit_message"] = "";
+
+    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+      (*variables)["is_field_present_message"] =
+          "!" + (*variables)["name"] + "_.isEmpty()";
+    } else {
+      (*variables)["is_field_present_message"] =
+          (*variables)["name"] + "_ != " + (*variables)["default"];
+    }
+  }
+
+  // For repeated builders, the underlying list tracks mutability state.
+  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutablePrimitiveFieldLiteGenerator::
+ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $field_type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_message$\n"
+    "  $name$_ = value;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_message$\n");
+  JavaType type = GetJavaType(descriptor_);
+  if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+    // The default value is not a simple literal so we want to avoid executing
+    // it multiple times.  Instead, get the default out of the default instance.
+    printer->Print(variables_,
+      "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  } else {
+    printer->Print(variables_,
+      "  $name$_ = $default$;\n");
+  }
+  printer->Print(variables_,
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_ = visitor.visit$visit_type$(\n"
+      "    has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n"
+      "    other.$name$_ != $default$, other.$name$_);\n");
+  }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  // noop for scalars
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_has_field_bit_message$\n"
+    "$name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for primitives.
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.write$capitalized_type$($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$capitalized_type$Size($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "result = result && (get$capitalized_name$()\n"
+        "    == other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "result = result && (\n"
+        "    java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
+        "    == java.lang.Float.floatToIntBits(\n"
+        "        other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "result = result && (\n"
+        "    java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
+        "    == java.lang.Double.doubleToLongBits(\n"
+        "        other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "result = result && get$capitalized_name$()\n"
+        "    .equals(other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$();\n");
+      break;
+
+    case JAVATYPE_LONG:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+        "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                 int messageBitIndex,
+                                 int builderBitIndex,
+                                 Context* context)
+    : ImmutablePrimitiveFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+~ImmutablePrimitiveOneofFieldLiteGenerator() {}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    return ($boxed_type$) $oneof_name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "}\n");
+}
+
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // noop for primitives
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$oneof_name$_ = visitor.visitOneof$visit_type$(\n"
+      "    $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_oneof_case_message$;\n"
+    "$oneof_name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.write$capitalized_type$(\n"
+    "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .compute$capitalized_type$Size(\n"
+    "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                         int messageBitIndex,
+                                         int builderBitIndex,
+                                         Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private $field_list_type$ $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $repeated_get$(index);\n"
+    "}\n");
+
+  if (descriptor_->options().packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize = -1;\n");
+  }
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$is_mutable$) {\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "   }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $repeated_set$(index, value);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$($type$ value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $repeated_add$(value);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  com.google.protobuf.AbstractMessageLite.addAll(\n"
+    "      values, $name$_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList(\n"
+    "      instance.get$capitalized_name$List());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return instance.get$capitalized_name$Count();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return instance.get$capitalized_name$(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
+    "  copyOnWrite();\n"
+    "  instance.addAll$capitalized_name$(values);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  // TODO(dweis): Scan the input buffer to count, then initialize
+  // appropriately.
+  // TODO(dweis): Scan the input buffer to count and ensure capacity.
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n"
+    "$repeated_add$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(length);\n"
+    "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n");
+
+  int fixed_size = FixedSize(GetType(descriptor_));
+  if (fixed_size == -1) {
+    // TODO(dweis): Scan the input buffer to count, then initialize
+    // appropriately.
+    printer->Print(variables_,
+      "  $name$_ =\n"
+      "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "  final int currentSize = $name$_.size();\n"
+      "  $name$_ = $name$_.mutableCopyWithCapacity(\n"
+      "      currentSize + (length/$fixed_size$));\n");
+  }
+
+  // TODO(dweis): Scan the input buffer to count and ensure capacity.
+  printer->Print(variables_,
+    "}\n"
+    "while (input.getBytesUntilLimit() > 0) {\n"
+    "  $repeated_add$(input.read$capitalized_type$());\n"
+    "}\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_mutable$) {\n"
+    "  $make_name_unmodifiable$;\n"
+    "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->options().packed()) {
+    // We invoke getSerializedSize in writeTo for messages that have packed
+    // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+    // That makes it safe to rely on the memoized size here.
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  if (FixedSize(GetType(descriptor_)) == -1) {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  dataSize += com.google.protobuf.CodedOutputStream\n"
+      "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  printer->Print(
+      "size += dataSize;\n");
+
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {\n"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeInt32SizeNoTag(dataSize);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.h
new file mode 100644
index 0000000..6cfbbb9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -0,0 +1,163 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldLiteGenerator
+    : public ImmutableFieldLiteGenerator {
+ public:
+  explicit ImmutablePrimitiveFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutablePrimitiveFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldLiteGenerator
+    : public ImmutablePrimitiveFieldLiteGenerator {
+ public:
+  ImmutablePrimitiveOneofFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutablePrimitiveOneofFieldLiteGenerator();
+
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldLiteGenerator
+    : public ImmutableFieldLiteGenerator {
+ public:
+  explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.cc
new file mode 100644
index 0000000..11bfc12
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.cc
@@ -0,0 +1,472 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_service.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
+  : descriptor_(descriptor) {}
+
+ServiceGenerator::~ServiceGenerator() {}
+
+// ===================================================================
+ImmutableServiceGenerator::ImmutableServiceGenerator(
+    const ServiceDescriptor* descriptor, Context* context)
+    : ServiceGenerator(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()) {}
+
+ImmutableServiceGenerator::~ImmutableServiceGenerator() {}
+
+void ImmutableServiceGenerator::Generate(io::Printer* printer) {
+  bool is_own_file =
+    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+  WriteServiceDocComment(printer, descriptor_);
+  printer->Print(
+    "public $static$ abstract class $classname$\n"
+    "    implements com.google.protobuf.Service {\n",
+    "static", is_own_file ? "" : "static",
+    "classname", descriptor_->name());
+  printer->Indent();
+
+  printer->Print(
+    "protected $classname$() {}\n\n",
+    "classname", descriptor_->name());
+
+  GenerateInterface(printer);
+
+  GenerateNewReflectiveServiceMethod(printer);
+  GenerateNewReflectiveBlockingServiceMethod(printer);
+
+  GenerateAbstractMethods(printer);
+
+  // Generate getDescriptor() and getDescriptorForType().
+  printer->Print(
+    "public static final\n"
+    "    com.google.protobuf.Descriptors.ServiceDescriptor\n"
+    "    getDescriptor() {\n"
+    "  return $file$.getDescriptor().getServices().get($index$);\n"
+    "}\n",
+    "file", name_resolver_->GetImmutableClassName(descriptor_->file()),
+    "index", SimpleItoa(descriptor_->index()));
+  GenerateGetDescriptorForType(printer);
+
+  // Generate more stuff.
+  GenerateCallMethod(printer);
+  GenerateGetPrototype(REQUEST, printer);
+  GenerateGetPrototype(RESPONSE, printer);
+  GenerateStub(printer);
+  GenerateBlockingStub(printer);
+
+  // Add an insertion point.
+  printer->Print(
+    "\n"
+    "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "full_name", descriptor_->full_name());
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateGetDescriptorForType(
+    io::Printer* printer) {
+  printer->Print(
+    "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
+    "    getDescriptorForType() {\n"
+    "  return getDescriptor();\n"
+    "}\n");
+}
+
+void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) {
+  printer->Print("public interface Interface {\n");
+  printer->Indent();
+  GenerateAbstractMethods(printer);
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod(
+    io::Printer* printer) {
+  printer->Print(
+    "public static com.google.protobuf.Service newReflectiveService(\n"
+    "    final Interface impl) {\n"
+    "  return new $classname$() {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    printer->Print("@java.lang.Override\n");
+    GenerateMethodSignature(printer, method, IS_CONCRETE);
+    printer->Print(
+      " {\n"
+      "  impl.$method$(controller, request, done);\n"
+      "}\n\n",
+      "method", UnderscoresToCamelCase(method));
+  }
+
+  printer->Outdent();
+  printer->Print("};\n");
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
+    io::Printer* printer) {
+  printer->Print(
+    "public static com.google.protobuf.BlockingService\n"
+    "    newReflectiveBlockingService(final BlockingInterface impl) {\n"
+    "  return new com.google.protobuf.BlockingService() {\n");
+  printer->Indent();
+  printer->Indent();
+
+  GenerateGetDescriptorForType(printer);
+
+  GenerateCallBlockingMethod(printer);
+  GenerateGetPrototype(REQUEST, printer);
+  GenerateGetPrototype(RESPONSE, printer);
+
+  printer->Outdent();
+  printer->Print("};\n");
+  printer->Outdent();
+  printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    WriteMethodDocComment(printer, method);
+    GenerateMethodSignature(printer, method, IS_ABSTRACT);
+    printer->Print(";\n\n");
+  }
+}
+
+void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
+  printer->Print(
+    "\n"
+    "public final void callMethod(\n"
+    "    com.google.protobuf.Descriptors.MethodDescriptor method,\n"
+    "    com.google.protobuf.RpcController controller,\n"
+    "    com.google.protobuf.Message request,\n"
+    "    com.google.protobuf.RpcCallback<\n"
+    "      com.google.protobuf.Message> done) {\n"
+    "  if (method.getService() != getDescriptor()) {\n"
+    "    throw new java.lang.IllegalArgumentException(\n"
+    "      \"Service.callMethod() given method descriptor for wrong \" +\n"
+    "      \"service type.\");\n"
+    "  }\n"
+    "  switch(method.getIndex()) {\n");
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> vars;
+    vars["index"] = SimpleItoa(i);
+    vars["method"] = UnderscoresToCamelCase(method);
+    vars["input"] = name_resolver_->GetImmutableClassName(
+        method->input_type());
+    vars["output"] = name_resolver_->GetImmutableClassName(
+        method->output_type());
+    printer->Print(vars,
+      "case $index$:\n"
+      "  this.$method$(controller, ($input$)request,\n"
+      "    com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n"
+      "      done));\n"
+      "  return;\n");
+  }
+
+  printer->Print(
+    "default:\n"
+    "  throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void ImmutableServiceGenerator::GenerateCallBlockingMethod(
+    io::Printer* printer) {
+  printer->Print(
+    "\n"
+    "public final com.google.protobuf.Message callBlockingMethod(\n"
+    "    com.google.protobuf.Descriptors.MethodDescriptor method,\n"
+    "    com.google.protobuf.RpcController controller,\n"
+    "    com.google.protobuf.Message request)\n"
+    "    throws com.google.protobuf.ServiceException {\n"
+    "  if (method.getService() != getDescriptor()) {\n"
+    "    throw new java.lang.IllegalArgumentException(\n"
+    "      \"Service.callBlockingMethod() given method descriptor for \" +\n"
+    "      \"wrong service type.\");\n"
+    "  }\n"
+    "  switch(method.getIndex()) {\n");
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> vars;
+    vars["index"] = SimpleItoa(i);
+    vars["method"] = UnderscoresToCamelCase(method);
+    vars["input"] = name_resolver_->GetImmutableClassName(
+        method->input_type());
+    vars["output"] = name_resolver_->GetImmutableClassName(
+        method->output_type());
+    printer->Print(vars,
+      "case $index$:\n"
+      "  return impl.$method$(controller, ($input$)request);\n");
+  }
+
+  printer->Print(
+    "default:\n"
+    "  throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
+                                            io::Printer* printer) {
+  /*
+   * TODO(cpovirk): The exception message says "Service.foo" when it may be
+   * "BlockingService.foo."  Consider fixing.
+   */
+  printer->Print(
+    "public final com.google.protobuf.Message\n"
+    "    get$request_or_response$Prototype(\n"
+    "    com.google.protobuf.Descriptors.MethodDescriptor method) {\n"
+    "  if (method.getService() != getDescriptor()) {\n"
+    "    throw new java.lang.IllegalArgumentException(\n"
+    "      \"Service.get$request_or_response$Prototype() given method \" +\n"
+    "      \"descriptor for wrong service type.\");\n"
+    "  }\n"
+    "  switch(method.getIndex()) {\n",
+    "request_or_response", (which == REQUEST) ? "Request" : "Response");
+  printer->Indent();
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    map<string, string> vars;
+    vars["index"] = SimpleItoa(i);
+    vars["type"] = name_resolver_->GetImmutableClassName(
+      (which == REQUEST) ? method->input_type() : method->output_type());
+    printer->Print(vars,
+      "case $index$:\n"
+      "  return $type$.getDefaultInstance();\n");
+  }
+
+  printer->Print(
+    "default:\n"
+    "  throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+  printer->Outdent();
+  printer->Outdent();
+
+  printer->Print(
+    "  }\n"
+    "}\n"
+    "\n");
+}
+
+void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) {
+  printer->Print(
+    "public static Stub newStub(\n"
+    "    com.google.protobuf.RpcChannel channel) {\n"
+    "  return new Stub(channel);\n"
+    "}\n"
+    "\n"
+    "public static final class Stub extends $classname$ implements Interface {"
+    "\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  printer->Indent();
+
+  printer->Print(
+    "private Stub(com.google.protobuf.RpcChannel channel) {\n"
+    "  this.channel = channel;\n"
+    "}\n"
+    "\n"
+    "private final com.google.protobuf.RpcChannel channel;\n"
+    "\n"
+    "public com.google.protobuf.RpcChannel getChannel() {\n"
+    "  return channel;\n"
+    "}\n");
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    printer->Print("\n");
+    GenerateMethodSignature(printer, method, IS_CONCRETE);
+    printer->Print(" {\n");
+    printer->Indent();
+
+    map<string, string> vars;
+    vars["index"] = SimpleItoa(i);
+    vars["output"] = name_resolver_->GetImmutableClassName(
+        method->output_type());
+    printer->Print(vars,
+      "channel.callMethod(\n"
+      "  getDescriptor().getMethods().get($index$),\n"
+      "  controller,\n"
+      "  request,\n"
+      "  $output$.getDefaultInstance(),\n"
+      "  com.google.protobuf.RpcUtil.generalizeCallback(\n"
+      "    done,\n"
+      "    $output$.class,\n"
+      "    $output$.getDefaultInstance()));\n");
+
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+}
+
+void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
+  printer->Print(
+    "public static BlockingInterface newBlockingStub(\n"
+    "    com.google.protobuf.BlockingRpcChannel channel) {\n"
+    "  return new BlockingStub(channel);\n"
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "public interface BlockingInterface {");
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    GenerateBlockingMethodSignature(printer, method);
+    printer->Print(";\n");
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "private static final class BlockingStub implements BlockingInterface {\n");
+  printer->Indent();
+
+  printer->Print(
+    "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
+    "  this.channel = channel;\n"
+    "}\n"
+    "\n"
+    "private final com.google.protobuf.BlockingRpcChannel channel;\n");
+
+  for (int i = 0; i < descriptor_->method_count(); i++) {
+    const MethodDescriptor* method = descriptor_->method(i);
+    GenerateBlockingMethodSignature(printer, method);
+    printer->Print(" {\n");
+    printer->Indent();
+
+    map<string, string> vars;
+    vars["index"] = SimpleItoa(i);
+    vars["output"] = name_resolver_->GetImmutableClassName(
+        method->output_type());
+    printer->Print(vars,
+      "return ($output$) channel.callBlockingMethod(\n"
+      "  getDescriptor().getMethods().get($index$),\n"
+      "  controller,\n"
+      "  request,\n"
+      "  $output$.getDefaultInstance());\n");
+
+    printer->Outdent();
+    printer->Print(
+      "}\n"
+      "\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer,
+                                               const MethodDescriptor* method,
+                                               IsAbstract is_abstract) {
+  map<string, string> vars;
+  vars["name"] = UnderscoresToCamelCase(method);
+  vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+  vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+  vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
+  printer->Print(vars,
+    "public $abstract$ void $name$(\n"
+    "    com.google.protobuf.RpcController controller,\n"
+    "    $input$ request,\n"
+    "    com.google.protobuf.RpcCallback<$output$> done)");
+}
+
+void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
+    io::Printer* printer,
+    const MethodDescriptor* method) {
+  map<string, string> vars;
+  vars["method"] = UnderscoresToCamelCase(method);
+  vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+  vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+  printer->Print(vars,
+    "\n"
+    "public $output$ $method$(\n"
+    "    com.google.protobuf.RpcController controller,\n"
+    "    $input$ request)\n"
+    "    throws com.google.protobuf.ServiceException");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.h
new file mode 100644
index 0000000..6707e82
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_service.h
@@ -0,0 +1,135 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
+
+#include <map>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;            // context.h
+      class ClassNameResolver;  // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;              // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ServiceGenerator {
+ public:
+  explicit ServiceGenerator(const ServiceDescriptor* descriptor);
+  virtual ~ServiceGenerator();
+
+  virtual void Generate(io::Printer* printer) = 0;
+
+  enum RequestOrResponse { REQUEST, RESPONSE };
+  enum IsAbstract { IS_ABSTRACT, IS_CONCRETE };
+
+ protected:
+  const ServiceDescriptor* descriptor_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
+};
+
+class ImmutableServiceGenerator : public ServiceGenerator {
+ public:
+  explicit ImmutableServiceGenerator(const ServiceDescriptor* descriptor,
+                                     Context* context);
+  virtual ~ImmutableServiceGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+ private:
+
+  // Generate the getDescriptorForType() method.
+  void GenerateGetDescriptorForType(io::Printer* printer);
+
+  // Generate a Java interface for the service.
+  void GenerateInterface(io::Printer* printer);
+
+  // Generate newReflectiveService() method.
+  void GenerateNewReflectiveServiceMethod(io::Printer* printer);
+
+  // Generate newReflectiveBlockingService() method.
+  void GenerateNewReflectiveBlockingServiceMethod(io::Printer* printer);
+
+  // Generate abstract method declarations for all methods.
+  void GenerateAbstractMethods(io::Printer* printer);
+
+  // Generate the implementation of Service.callMethod().
+  void GenerateCallMethod(io::Printer* printer);
+
+  // Generate the implementation of BlockingService.callBlockingMethod().
+  void GenerateCallBlockingMethod(io::Printer* printer);
+
+  // Generate the implementations of Service.get{Request,Response}Prototype().
+  void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
+
+  // Generate a stub implementation of the service.
+  void GenerateStub(io::Printer* printer);
+
+  // Generate a method signature, possibly abstract, without body or trailing
+  // semicolon.
+  void GenerateMethodSignature(io::Printer* printer,
+                               const MethodDescriptor* method,
+                               IsAbstract is_abstract);
+
+  // Generate a blocking stub interface and implementation of the service.
+  void GenerateBlockingStub(io::Printer* printer);
+
+  // Generate the method signature for one method of a blocking stub.
+  void GenerateBlockingMethodSignature(io::Printer* printer,
+                                       const MethodDescriptor* method);
+
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+#endif  // NET_PROTO2_COMPILER_JAVA_SERVICE_H__
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.cc
new file mode 100644
index 0000000..74253c3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -0,0 +1,206 @@
+// 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.
+
+// Author: xiaofeng@google.com (Feng Xiao)
+
+#include <google/protobuf/compiler/java/java_shared_code_generator.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file)
+    : name_resolver_(new ClassNameResolver),
+      enforce_lite_(false),
+      file_(file) {}
+
+SharedCodeGenerator::~SharedCodeGenerator() {
+}
+
+void SharedCodeGenerator::Generate(GeneratorContext* context,
+                                   vector<string>* file_list) {
+  string java_package = FileJavaPackage(file_);
+  string package_dir = JavaPackageToDir(java_package);
+
+  if (HasDescriptorMethods(file_, enforce_lite_)) {
+    // Generate descriptors.
+    string classname = name_resolver_->GetDescriptorClassName(file_);
+    string filename = package_dir + classname + ".java";
+    file_list->push_back(filename);
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+    google::protobuf::scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
+
+    printer->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name());
+    if (!java_package.empty()) {
+      printer->Print(
+        "package $package$;\n"
+        "\n",
+        "package", java_package);
+    }
+    printer->Print(
+      "public final class $classname$ {\n"
+      "  public static com.google.protobuf.Descriptors.FileDescriptor\n"
+      "      descriptor;\n"
+      "  static {\n",
+      "classname", classname);
+    printer->Indent();
+    printer->Indent();
+    GenerateDescriptors(printer.get());
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+      "  }\n"
+      "}\n");
+
+    printer.reset();
+    output.reset();
+  }
+}
+
+
+void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
+  // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
+  // and embed it as a string literal, which is parsed and built into real
+  // descriptors at initialization time.  We unfortunately have to put it in
+  // a string literal, not a byte array, because apparently using a literal
+  // byte array causes the Java compiler to generate *instructions* to
+  // initialize each and every byte of the array, e.g. as if you typed:
+  //   b[0] = 123; b[1] = 456; b[2] = 789;
+  // This makes huge bytecode files and can easily hit the compiler's internal
+  // code size limits (error "code to large").  String literals are apparently
+  // embedded raw, which is what we want.
+  FileDescriptorProto file_proto;
+  file_->CopyTo(&file_proto);
+
+
+  string file_data;
+  file_proto.SerializeToString(&file_data);
+
+  printer->Print(
+    "java.lang.String[] descriptorData = {\n");
+  printer->Indent();
+
+  // Only write 40 bytes per line.
+  static const int kBytesPerLine = 40;
+  for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+    if (i > 0) {
+      // Every 400 lines, start a new string literal, in order to avoid the
+      // 64k length limit.
+      if (i % 400 == 0) {
+        printer->Print(",\n");
+      } else {
+        printer->Print(" +\n");
+      }
+    }
+    printer->Print("\"$data$\"",
+      "data", CEscape(file_data.substr(i, kBytesPerLine)));
+  }
+
+  printer->Outdent();
+  printer->Print("\n};\n");
+
+  // -----------------------------------------------------------------
+  // Create the InternalDescriptorAssigner.
+
+  printer->Print(
+    "com.google.protobuf.Descriptors.FileDescriptor."
+    "InternalDescriptorAssigner assigner =\n"
+    "    new com.google.protobuf.Descriptors.FileDescriptor."
+    "    InternalDescriptorAssigner() {\n"
+    "      public com.google.protobuf.ExtensionRegistry assignDescriptors(\n"
+    "          com.google.protobuf.Descriptors.FileDescriptor root) {\n"
+    "        descriptor = root;\n"
+    // Custom options will be handled when immutable messages' outer class is
+    // loaded. Here we just return null and let custom options be unknown
+    // fields.
+    "        return null;\n"
+    "      }\n"
+    "    };\n");
+
+  // -----------------------------------------------------------------
+  // Find out all dependencies.
+  vector<pair<string, string> > dependencies;
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    if (ShouldIncludeDependency(file_->dependency(i))) {
+      string filename = file_->dependency(i)->name();
+      string classname = FileJavaPackage(file_->dependency(i)) + "." +
+                         name_resolver_->GetDescriptorClassName(
+                             file_->dependency(i));
+      dependencies.push_back(std::make_pair(filename, classname));
+    }
+  }
+
+  // -----------------------------------------------------------------
+  // Invoke internalBuildGeneratedFileFrom() to build the file.
+  printer->Print(
+    "com.google.protobuf.Descriptors.FileDescriptor\n"
+    "  .internalBuildGeneratedFileFrom(descriptorData,\n");
+  printer->Print(
+    "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
+
+  for (int i = 0; i < dependencies.size(); i++) {
+    const string& dependency = dependencies[i].second;
+    printer->Print(
+        "      $dependency$.getDescriptor(),\n",
+        "dependency", dependency);
+  }
+
+  printer->Print(
+    "    }, assigner);\n");
+}
+
+bool SharedCodeGenerator::ShouldIncludeDependency(
+    const FileDescriptor* descriptor) {
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.h
new file mode 100644
index 0000000..3b573c0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -0,0 +1,99 @@
+// 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.
+
+// Author: xiaofeng@google.com (Feng Xiao)
+//
+// Generators that generate shared code between immutable API and mutable API.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  class FileDescriptor;        // descriptor.h
+  namespace compiler {
+    class GeneratorContext;    // code_generator.h
+    namespace java {
+      class ClassNameResolver;       // name_resolver.h
+    }
+  }
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// A generator that generates code that are shared between immutable API
+// and mutable API. Currently only descriptors are shared.
+class SharedCodeGenerator {
+ public:
+  explicit SharedCodeGenerator(const FileDescriptor* file);
+  ~SharedCodeGenerator();
+
+  void Generate(GeneratorContext* generator_context,
+                vector<string>* file_list);
+
+  void SetEnforceLite(bool value) {
+    enforce_lite_ = value;
+  }
+
+  void GenerateDescriptors(io::Printer* printer);
+
+ private:
+  // Returns whether the dependency should be included in the output file.
+  // Always returns true for opensource, but used internally at Google to help
+  // improve compatibility with version 1 of protocol buffers.
+  bool ShouldIncludeDependency(const FileDescriptor* descriptor);
+
+  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
+  bool enforce_lite_;
+  const FileDescriptor* file_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
+};
+
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.cc
new file mode 100644
index 0000000..b67eeb5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.cc
@@ -0,0 +1,997 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           const FieldGeneratorInfo* info,
+                           ClassNameResolver* name_resolver,
+                           map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
+
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_init"] =
+      "= " + ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["capitalized_type"] = "String";
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  (*variables)["null_check"] =
+      "  if (value == null) {\n"
+      "    throw new NullPointerException();\n"
+      "  }\n";
+  (*variables)["writeString"] =
+      "com.google.protobuf.GeneratedMessage.writeString";
+  (*variables)["computeStringSize"] =
+      "com.google.protobuf.GeneratedMessage.computeStringSize";
+
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] = "onChanged();";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["set_has_field_bit_builder"] =
+        GenerateSetBit(builderBitIndex) + ";";
+    (*variables)["clear_has_field_bit_builder"] =
+        GenerateClearBit(builderBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["set_has_field_bit_builder"] = "";
+    (*variables)["clear_has_field_bit_builder"] = "";
+
+    (*variables)["is_field_present_message"] =
+        "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+  }
+
+  // For repeated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableStringFieldGenerator::
+ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
+                              int messageBitIndex,
+                              int builderBitIndex,
+                              Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
+
+int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+//     strings, but rather fields that were raw bytes incorrectly marked
+//     as strings in the proto file. This is common because in the proto1
+//     syntax, string was the way to indicate bytes and C++ engineers can
+//     easily make this mistake without affecting the C++ API. By converting to
+//     strings immediately, some java code might corrupt these byte arrays as
+//     it passes through a java server even if the field was never accessed by
+//     application code.
+//
+//  2. There's a performance hit to converting between bytes and strings and
+//     it many cases, the field is never even read by the application code. This
+//     avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void ImmutableStringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.lang.String get$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private volatile java.lang.Object $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  java.lang.Object ref = $name$_;\n"
+    "  if (ref instanceof java.lang.String) {\n"
+    "    return (java.lang.String) ref;\n"
+    "  } else {\n"
+    "    com.google.protobuf.ByteString bs = \n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+      "    java.lang.String s = bs.toStringUtf8();\n");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "    $name$_ = s;\n");
+  } else {
+    printer->Print(variables_,
+      "    if (bs.isValidUtf8()) {\n"
+      "      $name$_ = s;\n"
+      "    }\n");
+  }
+  printer->Print(variables_,
+    "    return s;\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.Object ref = $name$_;\n"
+    "  if (ref instanceof java.lang.String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "            (java.lang.String) ref);\n"
+    "    $name$_ = b;\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private java.lang.Object $name$_ $default_init$;\n");
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_builder$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  java.lang.Object ref = $name$_;\n"
+    "  if (!(ref instanceof java.lang.String)) {\n"
+    "    com.google.protobuf.ByteString bs =\n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+    "    java.lang.String s = bs.toStringUtf8();\n");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "    $name$_ = s;\n");
+  } else {
+    printer->Print(variables_,
+      "    if (bs.isValidUtf8()) {\n"
+      "      $name$_ = s;\n"
+      "    }\n");
+  }
+  printer->Print(variables_,
+    "    return s;\n"
+    "  } else {\n"
+    "    return (java.lang.String) ref;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "            (java.lang.String) ref);\n"
+    "    $name$_ = b;\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_builder$\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$\n");
+  // The default value is not a simple literal so we want to avoid executing
+  // it multiple times.  Instead, get the default out of the default instance.
+  printer->Print(variables_,
+    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  printer->Print(variables_,
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  $set_has_field_bit_builder$\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void ImmutableStringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    // Allow a slight breach of abstraction here in order to avoid forcing
+    // all string fields to Strings when copying fields from a Message.
+    printer->Print(variables_,
+      "if (other.has$capitalized_name$()) {\n"
+      "  $set_has_field_bit_builder$\n"
+      "  $name$_ = other.$name$_;\n"
+      "  $on_changed$\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "if (!other.get$capitalized_name$().isEmpty()) {\n"
+      "  $name$_ = other.$name$_;\n"
+      "  $on_changed$\n"
+      "}\n");
+  }
+}
+
+void ImmutableStringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+    "result.$name$_ = $name$_;\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "java.lang.String s = input.readStringRequireUtf8();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = s;\n");
+  } else {
+    printer->Print(variables_,
+      "com.google.protobuf.ByteString bs = input.readBytes();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = bs;\n");
+  }
+}
+
+void ImmutableStringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for strings.
+}
+
+void ImmutableStringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  $writeString$(output, $number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += $computeStringSize$($number$, $name$_);\n"
+    "}\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableStringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  printer->Print(variables_,
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableStringFieldGenerator::GetBoxedType() const {
+  return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldGenerator::
+ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                   int messageBitIndex,
+                                   int builderBitIndex,
+                                   Context* context)
+    : ImmutableStringFieldGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldGenerator::
+~ImmutableStringOneofFieldGenerator() {}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  java.lang.Object ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = $oneof_name$_;\n"
+    "  }\n"
+    "  if (ref instanceof java.lang.String) {\n"
+    "    return (java.lang.String) ref;\n"
+    "  } else {\n"
+    "    com.google.protobuf.ByteString bs = \n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+    "    java.lang.String s = bs.toStringUtf8();\n");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+    "    if ($has_oneof_case_message$) {\n"
+    "      $oneof_name$_ = s;\n"
+    "    }\n");
+  } else {
+    printer->Print(variables_,
+    "    if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
+    "      $oneof_name$_ = s;\n"
+    "    }\n");
+  }
+  printer->Print(variables_,
+    "    return s;\n"
+    "  }\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.Object ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = $oneof_name$_;\n"
+    "  }\n"
+    "  if (ref instanceof java.lang.String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "            (java.lang.String) ref);\n"
+    "    if ($has_oneof_case_message$) {\n"
+    "      $oneof_name$_ = b;\n"
+    "    }\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $has_oneof_case_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  java.lang.Object ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = $oneof_name$_;\n"
+    "  }\n"
+    "  if (!(ref instanceof java.lang.String)) {\n"
+    "    com.google.protobuf.ByteString bs =\n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+    "    java.lang.String s = bs.toStringUtf8();\n"
+    "    if ($has_oneof_case_message$) {\n");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "      $oneof_name$_ = s;\n");
+  } else {
+    printer->Print(variables_,
+      "      if (bs.isValidUtf8()) {\n"
+      "        $oneof_name$_ = s;\n"
+      "      }\n");
+  }
+  printer->Print(variables_,
+    "    }\n"
+    "    return s;\n"
+    "  } else {\n"
+    "    return (java.lang.String) ref;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.Object ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = $oneof_name$_;\n"
+    "  }\n"
+    "  if (ref instanceof String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "            (java.lang.String) ref);\n"
+    "    if ($has_oneof_case_message$) {\n"
+    "      $oneof_name$_ = b;\n"
+    "    }\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "    $on_changed$\n"
+    "  }\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // Allow a slight breach of abstraction here in order to avoid forcing
+  // all string fields to Strings when copying fields from a Message.
+  printer->Print(variables_,
+    "$set_oneof_case_message$;\n"
+    "$oneof_name$_ = other.$oneof_name$_;\n"
+    "$on_changed$\n");
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  result.$oneof_name$_ = $oneof_name$_;\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "java.lang.String s = input.readStringRequireUtf8();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = s;\n");
+  } else {
+    printer->Print(variables_,
+      "com.google.protobuf.ByteString bs = input.readBytes();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = bs;\n");
+  }
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  $writeString$(output, $number$, $oneof_name$_);\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += $computeStringSize$($number$, $oneof_name$_);\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldGenerator::
+RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
+                                      int messageBitIndex,
+                                      int builderBitIndex,
+                                      Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldGenerator::
+~RepeatedImmutableStringFieldGenerator() {}
+
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ProtocolStringList\n"
+    "    get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index);\n");
+}
+
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return $name$_.getByteString(index);\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
+    // Note:  We return an unmodifiable list because otherwise the caller
+    //   could hold on to the returned list and modify it after the message
+    //   has been built, thus mutating the message which is supposed to be
+    //   immutable.
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_.getUnmodifiableView();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return $name$_.getByteString(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, java.lang.String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<java.lang.String> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+    "      values, $name$_);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
+
+  printer->Print(variables_,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = $name$_.getUnmodifiableView();\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+    "java.lang.String s = input.readStringRequireUtf8();\n");
+  } else {
+    printer->Print(variables_,
+    "com.google.protobuf.ByteString bs = input.readBytes();\n");
+  }
+  printer->Print(variables_,
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "$name$_.add(s);\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_.add(bs);\n");
+  }
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = $name$_.getUnmodifiableView();\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  $writeString$(output, $number$, $name$_.getRaw(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
+    "}\n");
+
+  printer->Print(
+      "size += dataSize;\n");
+
+  printer->Print(variables_,
+    "size += $tag_size$ * get$capitalized_name$List().size();\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
+  return "String";
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.h
new file mode 100644
index 0000000..a3b5735
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field.h
@@ -0,0 +1,159 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit ImmutableStringFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableStringFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator);
+};
+
+class ImmutableStringOneofFieldGenerator
+    : public ImmutableStringFieldGenerator {
+ public:
+  ImmutableStringOneofFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableStringOneofFieldGenerator();
+
+ private:
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator);
+};
+
+class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator {
+ public:
+  explicit RepeatedImmutableStringFieldGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableStringFieldGenerator();
+
+  // implements ImmutableFieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.cc
new file mode 100644
index 0000000..0b92c02
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -0,0 +1,872 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           const FieldGeneratorInfo* info,
+                           ClassNameResolver* name_resolver,
+                           map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*variables)["empty_list"] =
+      "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
+
+  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default_init"] =
+      "= " + ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["capitalized_type"] = "String";
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  (*variables)["null_check"] =
+      "  if (value == null) {\n"
+      "    throw new NullPointerException();\n"
+      "  }\n";
+
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+
+  if (SupportFieldPresence(descriptor->file())) {
+    // For singular messages and builders, one bit is used for the hasField bit.
+    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+    // Note that these have a trailing ";".
+    (*variables)["set_has_field_bit_message"] =
+        GenerateSetBit(messageBitIndex) + ";";
+    (*variables)["clear_has_field_bit_message"] =
+        GenerateClearBit(messageBitIndex) + ";";
+
+    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+  } else {
+    (*variables)["set_has_field_bit_message"] = "";
+    (*variables)["clear_has_field_bit_message"] = "";
+
+    (*variables)["is_field_present_message"] =
+        "!" + (*variables)["name"] + "_.isEmpty()";
+  }
+
+  // For repeated builders, the underlying list tracks mutability state.
+  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+ImmutableStringFieldLiteGenerator::
+ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+                              int messageBitIndex,
+                              int builderBitIndex,
+                              Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
+// strings are not stored as java.lang.String in the Message because of two
+// issues:
+//
+//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+//     strings, but rather fields that were raw bytes incorrectly marked
+//     as strings in the proto file. This is common because in the proto1
+//     syntax, string was the way to indicate bytes and C++ engineers can
+//     easily make this mistake without affecting the C++ API. By converting to
+//     strings immediately, some java code might corrupt these byte arrays as
+//     it passes through a java server even if the field was never accessed by
+//     application code.
+//
+//  2. There's a performance hit to converting between bytes and strings and
+//     it many cases, the field is never even read by the application code. This
+//     avoids unnecessary conversions in the common use cases.
+//
+// In the LITE_RUNTIME, we store strings as java.lang.String because we assume
+// that the users of this runtime are not subject to proto1 constraints and are
+// running code on devices that are user facing. That is, the developers are
+// properly incentivized to only fetch the data they need to read and wish to
+// reduce the number of allocations incurred when running on a user's device.
+
+// TODO(dweis): Consider dropping all of the *Bytes() methods. They really
+//     shouldn't be necessary or used on devices.
+void ImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$boolean has$capitalized_name$();\n");
+  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.lang.String get$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private java.lang.String $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_message$\n"
+    "  $name$_ = value;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_message$\n"
+    // The default value is not a simple literal so we want to avoid executing
+    // it multiple times.  Instead, get the default out of the default instance.
+    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  $set_has_field_bit_message$\n"
+    "  $name$_ = value.toStringUtf8();\n"
+    "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  return instance.get$capitalized_name$Bytes();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$Bytes(value);\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_ = visitor.visitString(\n"
+      "    has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n"
+      "    !other.$name$_.isEmpty(), other.$name$_);\n");
+  }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  // noop for scalars
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "String s = input.readStringRequireUtf8();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = s;\n");
+  } else {
+    // Lite runtime should attempt to reduce allocations by attempting to
+    // construct the string directly from the input stream buffer. This avoids
+    // spurious intermediary ByteString allocations, cutting overall allocations
+    // in half.
+    printer->Print(variables_,
+      "String s = input.readString();\n"
+      "$set_has_field_bit_message$\n"
+      "$name$_ = s;\n");
+  }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by serializing the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  output.writeString($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by computing on the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "if ($is_field_present_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeStringSize($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  printer->Print(variables_,
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
+  return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldLiteGenerator::
+ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                   int messageBitIndex,
+                                   int builderBitIndex,
+                                   Context* context)
+    : ImmutableStringFieldLiteGenerator(
+          descriptor, messageBitIndex, builderBitIndex, context) {
+  const OneofGeneratorInfo* info =
+      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+  SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldLiteGenerator::
+~ImmutableStringOneofFieldLiteGenerator() {}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  PrintExtraFieldInfo(variables_, printer);
+
+  if (SupportFieldPresence(descriptor_->file())) {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  java.lang.String ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = (java.lang.String) $oneof_name$_;\n"
+    "  }\n"
+    "  return ref;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.String ref $default_init$;\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    ref = (java.lang.String) $oneof_name$_;\n"
+    "  }\n"
+    "  return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  if ($has_oneof_case_message$) {\n"
+    "    $clear_oneof_case_message$;\n"
+    "    $oneof_name$_ = null;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  $set_oneof_case_message$;\n"
+    "  $oneof_name$_ = value.toStringUtf8();\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  if (SupportFieldPresence(descriptor_->file())) {
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return instance.has$capitalized_name$();\n"
+      "}\n");
+  }
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "  return instance.get$capitalized_name$();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  return instance.get$capitalized_name$Bytes();\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$Bytes(value);\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$oneof_name$_ = visitor.visitOneofString(\n"
+    "   $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "String s = input.readStringRequireUtf8();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = s;\n");
+  } else {
+    // Lite runtime should attempt to reduce allocations by attempting to
+    // construct the string directly from the input stream buffer. This avoids
+    // spurious intermediary ByteString allocations, cutting overall allocations
+    // in half.
+    printer->Print(variables_,
+      "String s = input.readString();\n"
+      "$set_oneof_case_message$;\n"
+      "$oneof_name$_ = s;\n");
+  }
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by serializing the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  output.writeString($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by computing on the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "if ($has_oneof_case_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeStringSize($number$, get$capitalized_name$());\n"
+    "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldLiteGenerator::
+RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+                                      int messageBitIndex,
+                                      int builderBitIndex,
+                                      Context* context)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        context->GetFieldGeneratorInfo(descriptor),
+                        name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldLiteGenerator::
+~RepeatedImmutableStringFieldLiteGenerator() {}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+  return 0;
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.util.List<String>\n"
+    "    get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index);\n");
+}
+
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
+  PrintExtraFieldInfo(variables_, printer);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "      $name$_.get(index));\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$is_mutable$) {\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "   }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void set$capitalized_name$(\n"
+    "    int index, java.lang.String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<java.lang.String> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  com.google.protobuf.AbstractMessageLite.addAll(\n"
+    "      values, $name$_);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "private void add$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$");
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+      "  checkByteStringIsUtf8(value);\n");
+  }
+  printer->Print(variables_,
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value.toStringUtf8());\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<String>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList(\n"
+    "      instance.get$capitalized_name$List());\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return instance.get$capitalized_name$Count();\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "  return instance.get$capitalized_name$(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return instance.get$capitalized_name$Bytes(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, java.lang.String value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.set$capitalized_name$(index, value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    java.lang.String value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$(value);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<java.lang.String> values) {\n"
+    "  copyOnWrite();\n"
+    "  instance.addAll$capitalized_name$(values);\n"
+    "  return this;\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  copyOnWrite();\n"
+    "  instance.clear$capitalized_name$();\n"
+    "  return this;\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "  copyOnWrite();\n"
+    "  instance.add$capitalized_name$Bytes(value);\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for strings
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_= visitor.visitList($name$_, other.$name$_);\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  if (CheckUtf8(descriptor_)) {
+    printer->Print(variables_,
+    "String s = input.readStringRequireUtf8();\n");
+  } else {
+    // Lite runtime should attempt to reduce allocations by attempting to
+    // construct the string directly from the input stream buffer. This avoids
+    // spurious intermediary ByteString allocations, cutting overall allocations
+    // in half.
+    printer->Print(variables_,
+    "String s = input.readString();\n");
+  }
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
+  printer->Print(variables_,
+    "$name$_.add(s);\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($is_mutable$) {\n"
+    "  $name$_.makeImmutable();\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by serializing the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.writeString($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  // Lite runtime should reduce allocations by computing on the string directly.
+  // This avoids spurious intermediary ByteString allocations, cutting overall
+  // allocations in half.
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += com.google.protobuf.CodedOutputStream\n"
+    "    .computeStringSizeNoTag($name$_.get(i));\n"
+    "}\n");
+
+  printer->Print(
+      "size += dataSize;\n");
+
+
+  printer->Print(variables_,
+    "size += $tag_size$ * get$capitalized_name$List().size();\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
+  return "String";
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.h
new file mode 100644
index 0000000..4148aa4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -0,0 +1,157 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+  namespace compiler {
+    namespace java {
+      class Context;           // context.h
+      class ClassNameResolver; // name_resolver.h
+    }
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+  explicit ImmutableStringFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableStringFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ protected:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+};
+
+class ImmutableStringOneofFieldLiteGenerator
+    : public ImmutableStringFieldLiteGenerator {
+ public:
+  ImmutableStringOneofFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~ImmutableStringOneofFieldLiteGenerator();
+
+ private:
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableStringFieldLiteGenerator
+    : public ImmutableFieldLiteGenerator {
+ public:
+  explicit RepeatedImmutableStringFieldLiteGenerator(
+      const FieldDescriptor* descriptor, int messageBitIndex,
+      int builderBitIndex, Context* context);
+  ~RepeatedImmutableStringFieldLiteGenerator();
+
+  // implements ImmutableFieldLiteGenerator ------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
+  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.cc
new file mode 100644
index 0000000..c6e8dfe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -0,0 +1,143 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
+  : params_(params), descriptor_(descriptor) {
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    const EnumValueDescriptor* value = descriptor_->value(i);
+    const EnumValueDescriptor* canonical_value =
+      descriptor_->FindValueByNumber(value->number());
+
+    if (value == canonical_value) {
+      canonical_values_.push_back(value);
+    } else {
+      Alias alias;
+      alias.value = value;
+      alias.canonical_value = canonical_value;
+      aliases_.push_back(alias);
+    }
+  }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+  printer->Print(
+      "\n"
+      "// enum $classname$\n",
+      "classname", descriptor_->name());
+
+  const string classname = RenameJavaKeywords(descriptor_->name());
+
+  // Start of container interface
+  // If generating intdefs, we use the container interface as the intdef if
+  // present. Otherwise, we just make an empty @interface parallel to the
+  // constants.
+  bool use_intdef = params_.generate_intdefs();
+  bool use_shell_class = params_.java_enum_style();
+  if (use_intdef) {
+    // @IntDef annotation so tools can enforce correctness
+    // Annotations will be discarded by the compiler
+    printer->Print("@java.lang.annotation.Retention("
+      "java.lang.annotation.RetentionPolicy.SOURCE)\n"
+      "@android.support.annotation.IntDef({\n");
+    printer->Indent();
+    for (int i = 0; i < canonical_values_.size(); i++) {
+      const string constant_name =
+          RenameJavaKeywords(canonical_values_[i]->name());
+      if (use_shell_class) {
+        printer->Print("$classname$.$name$,\n",
+          "classname", classname,
+          "name", constant_name);
+      } else {
+        printer->Print("$name$,\n", "name", constant_name);
+      }
+    }
+    printer->Outdent();
+    printer->Print("})\n");
+  }
+  if (use_shell_class || use_intdef) {
+    printer->Print(
+      "public $at_for_intdef$interface $classname$ {\n",
+      "classname", classname,
+      "at_for_intdef", use_intdef ? "@" : "");
+    if (use_shell_class) {
+        printer->Indent();
+    } else {
+        printer->Print("}\n\n");
+    }
+  }
+
+  // Canonical values
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    printer->Print(
+      "public static final int $name$ = $canonical_value$;\n",
+      "name", RenameJavaKeywords(canonical_values_[i]->name()),
+      "canonical_value", SimpleItoa(canonical_values_[i]->number()));
+  }
+
+  // Aliases
+  for (int i = 0; i < aliases_.size(); i++) {
+    printer->Print(
+      "public static final int $name$ = $canonical_name$;\n",
+      "name", RenameJavaKeywords(aliases_[i].value->name()),
+      "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
+  }
+
+  // End of container interface
+  if (use_shell_class) {
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.h
new file mode 100644
index 0000000..10dd364
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum.h
@@ -0,0 +1,87 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class EnumGenerator {
+ public:
+  explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
+  ~EnumGenerator();
+
+  void Generate(io::Printer* printer);
+
+ private:
+  const Params& params_;
+  const EnumDescriptor* descriptor_;
+
+  // The proto language allows multiple enum constants to have the same numeric
+  // value.  Java, however, does not allow multiple enum constants to be
+  // considered equivalent.  We treat the first defined constant for any
+  // given numeric value as "canonical" and the rest as aliases of that
+  // canonical value.
+  vector<const EnumValueDescriptor*> canonical_values_;
+
+  struct Alias {
+    const EnumValueDescriptor* value;
+    const EnumValueDescriptor* canonical_value;
+  };
+  vector<Alias> aliases_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
new file mode 100644
index 0000000..7666db3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -0,0 +1,544 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
+//   repeat code between this and the other field types.
+void SetEnumVariables(const Params& params,
+    const FieldDescriptor* descriptor, map<string, string>* variables) {
+  (*variables)["name"] =
+    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  (*variables)["capitalized_name"] =
+    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  if (params.use_reference_types_for_primitives()
+      && !params.reftypes_primitive_enums()
+      && !descriptor->is_repeated()) {
+    (*variables)["type"] = "java.lang.Integer";
+    (*variables)["default"] = "null";
+  } else {
+    (*variables)["type"] = "int";
+    (*variables)["default"] = DefaultValue(params, descriptor);
+  }
+  (*variables)["repeated_default"] =
+      "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+  (*variables)["non_packed_tag"] = SimpleItoa(
+      internal::WireFormatLite::MakeTag(descriptor->number(),
+          internal::WireFormat::WireTypeForFieldType(descriptor->type())));
+  (*variables)["message_name"] = descriptor->containing_type()->name();
+  const EnumDescriptor* enum_type = descriptor->enum_type();
+  (*variables)["message_type_intdef"] = "@"
+      + ToJavaName(params, enum_type->name(), true,
+          enum_type->containing_type(), enum_type->file());
+}
+
+void LoadEnumValues(const Params& params,
+    const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
+  string enum_class_name = ClassName(params, enum_descriptor);
+  for (int i = 0; i < enum_descriptor->value_count(); i++) {
+    const EnumValueDescriptor* value = enum_descriptor->value(i);
+    const EnumValueDescriptor* canonical_value =
+        enum_descriptor->FindValueByNumber(value->number());
+    if (value == canonical_value) {
+      canonical_values->push_back(
+          enum_class_name + "." + RenameJavaKeywords(value->name()));
+    }
+  }
+}
+
+void PrintCaseLabels(
+    io::Printer* printer, const vector<string>& canonical_values) {
+  for (int i = 0; i < canonical_values.size(); i++) {
+    printer->Print(
+      "  case $value$:\n",
+      "value", canonical_values[i]);
+  }
+}
+
+}  // namespace
+
+// ===================================================================
+
+EnumFieldGenerator::
+EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetEnumVariables(params, descriptor, &variables_);
+  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  if (params_.generate_intdefs()) {
+    printer->Print(variables_, "$message_type_intdef$\n");
+  }
+  printer->Print(variables_, "public $type$ $name$;\n");
+
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "public boolean has$capitalized_name$;\n");
+  }
+}
+
+void EnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = $default$;\n");
+
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "has$capitalized_name$ = false;\n");
+  }
+}
+
+void EnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int value = input.readInt32();\n"
+    "switch (value) {\n");
+  PrintCaseLabels(printer, canonical_values_);
+  printer->Print(variables_,
+    "    this.$name$ = value;\n");
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "    has$capitalized_name$ = true;\n");
+  }
+  printer->Print(
+    "    break;\n"
+    "}\n");
+  // No default case: in case of invalid value from the wire, preserve old
+  // field value. Also we are not storing the invalid value into the unknown
+  // fields, because there is no way to get the value out.
+}
+
+void EnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->is_required() && !params_.generate_has()) {
+    // Always serialize a required field if we don't have the 'has' signal.
+    printer->Print(variables_,
+      "output.writeInt32($number$, this.$name$);\n");
+  } else {
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
+    } else {
+      printer->Print(variables_,
+        "if (this.$name$ != $default$) {\n");
+    }
+    printer->Print(variables_,
+      "  output.writeInt32($number$, this.$name$);\n"
+      "}\n");
+  }
+}
+
+void EnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  if (descriptor_->is_required() && !params_.generate_has()) {
+    printer->Print(variables_,
+      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "  .computeInt32Size($number$, this.$name$);\n");
+  } else {
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
+    } else {
+      printer->Print(variables_,
+        "if (this.$name$ != $default$) {\n");
+    }
+    printer->Print(variables_,
+      "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "    .computeInt32Size($number$, this.$name$);\n"
+      "}\n");
+  }
+}
+
+void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
+  if (params_.use_reference_types_for_primitives()
+        && !params_.reftypes_primitive_enums()) {
+    printer->Print(variables_,
+      "if (this.$name$ == null) {\n"
+      "  if (other.$name$ != null) {\n"
+      "    return false;\n"
+      "  }\n"
+      "} else if (!this.$name$.equals(other.$name$)) {\n"
+      "  return false;"
+      "}\n");
+  } else {
+    // We define equality as serialized form equality. If generate_has(),
+    // then if the field value equals the default value in both messages,
+    // but one's 'has' field is set and the other's is not, the serialized
+    // forms are different and we should return false.
+    printer->Print(variables_,
+      "if (this.$name$ != other.$name$");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "    || (this.$name$ == $default$\n"
+        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "  return false;\n"
+      "}\n");
+  }
+}
+
+void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(
+    "result = 31 * result + ");
+  if (params_.use_reference_types_for_primitives()
+        && !params_.reftypes_primitive_enums()) {
+    printer->Print(variables_,
+      "(this.$name$ == null ? 0 : this.$name$)");
+  } else {
+    printer->Print(variables_,
+      "this.$name$");
+  }
+  printer->Print(";\n");
+}
+
+// ===================================================================
+
+AccessorEnumFieldGenerator::
+AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
+    const Params& params, int has_bit_index)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetEnumVariables(params, descriptor, &variables_);
+  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+  SetBitOperationVariables("has", has_bit_index, &variables_);
+}
+
+AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
+
+void AccessorEnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_, "private int $name$_;\n");
+  if (params_.generate_intdefs()) {
+    printer->Print(variables_, "$message_type_intdef$\n");
+  }
+  printer->Print(variables_,
+    "public int get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$(");
+  if (params_.generate_intdefs()) {
+    printer->Print(variables_,
+      "\n"
+      "    $message_type_intdef$ ");
+  }
+  printer->Print(variables_,
+    "int value) {\n"
+    "  $name$_ = value;\n"
+    "  $set_has$;\n"
+    "  return this;\n"
+    "}\n"
+    "public boolean has$capitalized_name$() {\n"
+    "  return $get_has$;\n"
+    "}\n"
+    "public $message_name$ clear$capitalized_name$() {\n"
+    "  $name$_ = $default$;\n"
+    "  $clear_has$;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int value = input.readInt32();\n"
+    "switch (value) {\n");
+  PrintCaseLabels(printer, canonical_values_);
+  printer->Print(variables_,
+    "    $name$_ = value;\n"
+    "    $set_has$;\n"
+    "    break;\n"
+    "}\n");
+  // No default case: in case of invalid value from the wire, preserve old
+  // field value. Also we are not storing the invalid value into the unknown
+  // fields, because there is no way to get the value out.
+}
+
+void AccessorEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has$) {\n"
+    "  output.writeInt32($number$, $name$_);\n"
+    "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "    .computeInt32Size($number$, $name$_);\n"
+    "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($different_has$\n"
+    "    || $name$_ != other.$name$_) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result + $name$_;\n");
+}
+
+// ===================================================================
+
+RepeatedEnumFieldGenerator::
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetEnumVariables(params, descriptor, &variables_);
+  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public $type$[] $name$;\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = $repeated_default$;\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // First, figure out the maximum length of the array, then parse,
+  // and finally copy the valid values to the field.
+  printer->Print(variables_,
+    "int length = com.google.protobuf.nano.WireFormatNano\n"
+    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
+    "int[] validValues = new int[length];\n"
+    "int validCount = 0;\n"
+    "for (int i = 0; i < length; i++) {\n"
+    "  if (i != 0) { // tag for first value already consumed.\n"
+    "    input.readTag();\n"
+    "  }\n"
+    "  int value = input.readInt32();\n"
+    "  switch (value) {\n");
+  printer->Indent();
+  PrintCaseLabels(printer, canonical_values_);
+  printer->Outdent();
+  printer->Print(variables_,
+    "      validValues[validCount++] = value;\n"
+    "      break;\n"
+    "  }\n"
+    "}\n"
+    "if (validCount != 0) {\n"
+    "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+    "  if (i == 0 && validCount == validValues.length) {\n"
+    "    this.$name$ = validValues;\n"
+    "  } else {\n"
+    "    int[] newArray = new int[i + validCount];\n"
+    "    if (i != 0) {\n"
+    "      java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+    "    }\n"
+    "    java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
+    "    this.$name$ = newArray;\n"
+    "  }\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int bytes = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(bytes);\n"
+    "// First pass to compute array length.\n"
+    "int arrayLength = 0;\n"
+    "int startPos = input.getPosition();\n"
+    "while (input.getBytesUntilLimit() > 0) {\n"
+    "  switch (input.readInt32()) {\n");
+  printer->Indent();
+  PrintCaseLabels(printer, canonical_values_);
+  printer->Outdent();
+  printer->Print(variables_,
+    "      arrayLength++;\n"
+    "      break;\n"
+    "  }\n"
+    "}\n"
+    "if (arrayLength != 0) {\n"
+    "  input.rewindToPosition(startPos);\n"
+    "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+    "  int[] newArray = new int[i + arrayLength];\n"
+    "  if (i != 0) {\n"
+    "    java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+    "  }\n"
+    "  while (input.getBytesUntilLimit() > 0) {\n"
+    "    int value = input.readInt32();\n"
+    "    switch (value) {\n");
+  printer->Indent();
+  printer->Indent();
+  PrintCaseLabels(printer, canonical_values_);
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(variables_,
+    "        newArray[i++] = value;\n"
+    "        break;\n"
+    "    }\n"
+    "  }\n"
+    "  this.$name$ = newArray;\n"
+    "}\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateRepeatedDataSizeCode(io::Printer* printer) const {
+  // Creates a variable dataSize and puts the serialized size in there.
+  printer->Print(variables_,
+    "int dataSize = 0;\n"
+    "for (int i = 0; i < this.$name$.length; i++) {\n"
+    "  int element = this.$name$[i];\n"
+    "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "      .computeInt32SizeNoTag(element);\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n");
+  printer->Indent();
+
+  if (descriptor_->options().packed()) {
+    GenerateRepeatedDataSizeCode(printer);
+    printer->Print(variables_,
+      "output.writeRawVarint32($tag$);\n"
+      "output.writeRawVarint32(dataSize);\n"
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  output.writeRawVarint32(this.$name$[i]);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  output.writeInt32($number$, this.$name$[i]);\n"
+      "}\n");
+  }
+
+  printer->Outdent();
+  printer->Print(variables_,
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n");
+  printer->Indent();
+
+  GenerateRepeatedDataSizeCode(printer);
+
+  printer->Print(
+    "size += dataSize;\n");
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "size += $tag_size$;\n"
+      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "    .computeRawVarint32Size(dataSize);\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * this.$name$.length;\n");
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n"
+    "  cloned.$name$ = this.$name$.clone();\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+    "    this.$name$, other.$name$)) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result\n"
+    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.h
new file mode 100644
index 0000000..b94790d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -0,0 +1,126 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class EnumFieldGenerator : public FieldGenerator {
+ public:
+  explicit EnumFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~EnumFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  vector<string> canonical_values_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class AccessorEnumFieldGenerator : public FieldGenerator {
+ public:
+  explicit AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
+      const Params& params, int has_bit_index);
+  ~AccessorEnumFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  vector<string> canonical_values_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public FieldGenerator {
+ public:
+  explicit RepeatedEnumFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~RepeatedEnumFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+  void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+  void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
+
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  vector<string> canonical_values_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.cc
new file mode 100644
index 0000000..0b9d1d8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.cc
@@ -0,0 +1,150 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: bduff@google.com (Brian Duff)
+
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* GetTypeConstantName(const FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return "TYPE_INT32"   ;
+    case FieldDescriptor::TYPE_UINT32  : return "TYPE_UINT32"  ;
+    case FieldDescriptor::TYPE_SINT32  : return "TYPE_SINT32"  ;
+    case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ;
+    case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32";
+    case FieldDescriptor::TYPE_INT64   : return "TYPE_INT64"   ;
+    case FieldDescriptor::TYPE_UINT64  : return "TYPE_UINT64"  ;
+    case FieldDescriptor::TYPE_SINT64  : return "TYPE_SINT64"  ;
+    case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ;
+    case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64";
+    case FieldDescriptor::TYPE_FLOAT   : return "TYPE_FLOAT"   ;
+    case FieldDescriptor::TYPE_DOUBLE  : return "TYPE_DOUBLE"  ;
+    case FieldDescriptor::TYPE_BOOL    : return "TYPE_BOOL"    ;
+    case FieldDescriptor::TYPE_STRING  : return "TYPE_STRING"  ;
+    case FieldDescriptor::TYPE_BYTES   : return "TYPE_BYTES"   ;
+    case FieldDescriptor::TYPE_ENUM    : return "TYPE_ENUM"    ;
+    case FieldDescriptor::TYPE_GROUP   : return "TYPE_GROUP"   ;
+    case FieldDescriptor::TYPE_MESSAGE : return "TYPE_MESSAGE" ;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+}  // namespace
+
+void SetVariables(const FieldDescriptor* descriptor, const Params params,
+                  map<string, string>* variables) {
+  (*variables)["extends"] = ClassName(params, descriptor->containing_type());
+  (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  bool repeated = descriptor->is_repeated();
+  (*variables)["repeated"] = repeated ? "Repeated" : "";
+  (*variables)["type"] = GetTypeConstantName(descriptor->type());
+  JavaType java_type = GetJavaType(descriptor->type());
+  string tag = SimpleItoa(WireFormat::MakeTag(descriptor));
+  if (java_type == JAVATYPE_MESSAGE) {
+    (*variables)["ext_type"] = "MessageTyped";
+    string message_type = ClassName(params, descriptor->message_type());
+    if (repeated) {
+      message_type += "[]";
+    }
+    (*variables)["class"] = message_type;
+    // For message typed extensions, tags_params contains a single tag
+    // for both singular and repeated cases.
+    (*variables)["tag_params"] = tag;
+  } else {
+    (*variables)["ext_type"] = "PrimitiveTyped";
+    if (!repeated) {
+      (*variables)["class"] = BoxedPrimitiveTypeName(java_type);
+      (*variables)["tag_params"] = tag;
+    } else {
+      (*variables)["class"] = PrimitiveTypeName(java_type) + "[]";
+      if (!descriptor->is_packable()) {
+        // Non-packable: nonPackedTag == tag, packedTag == 0
+        (*variables)["tag_params"] = tag + ", " + tag + ", 0";
+      } else if (descriptor->options().packed()) {
+        // Packable and packed: tag == packedTag
+        string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag(
+            descriptor->number(),
+            WireFormat::WireTypeForFieldType(descriptor->type())));
+        (*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag;
+      } else {
+        // Packable and not packed: tag == nonPackedTag
+        string packed_tag = SimpleItoa(WireFormatLite::MakeTag(
+            descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+        (*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag;
+      }
+    }
+  }
+}
+
+ExtensionGenerator::
+ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
+  : params_(params), descriptor_(descriptor) {
+  SetVariables(descriptor, params, &variables_);
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::Generate(io::Printer* printer) const {
+  printer->Print("\n");
+  PrintFieldComment(printer, descriptor_);
+  printer->Print(variables_,
+    "public static final com.google.protobuf.nano.Extension<\n"
+    "    $extends$,\n"
+    "    $class$> $name$ =\n"
+    "        com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
+    "            com.google.protobuf.nano.Extension.$type$,\n"
+    "            $class$.class,\n"
+    "            $tag_params$L);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.h
new file mode 100644
index 0000000..4843e29
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_extension.h
@@ -0,0 +1,74 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: bduff@google.com (Brian Duff)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class ExtensionGenerator {
+ public:
+  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
+  ~ExtensionGenerator();
+
+  void Generate(io::Printer* printer) const;
+
+ private:
+  const Params& params_;
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.cc
new file mode 100644
index 0000000..85257f3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -0,0 +1,209 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
+#include <google/protobuf/compiler/javanano/javanano_message_field.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+FieldGenerator::~FieldGenerator() {}
+
+bool FieldGenerator::SavedDefaultNeeded() const {
+  // No saved default for this field by default.
+  // Subclasses whose instances may need saved defaults will override this
+  // and return the appropriate value.
+  return false;
+}
+
+void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
+  // No saved default for this field by default.
+  // Subclasses whose instances may need saved defaults will override this
+  // and generate the appropriate init code to the printer.
+}
+
+void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
+  // Reaching here indicates a bug. Cases are:
+  //   - This FieldGenerator should support packing, but this method should be
+  //     overridden.
+  //   - This FieldGenerator doesn't support packing, and this method should
+  //     never have been called.
+  GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
+             << "called on field generator that does not support packing.";
+}
+
+// =============================================
+
+FieldGeneratorMap::FieldGeneratorMap(
+    const Descriptor* descriptor, const Params &params)
+  : descriptor_(descriptor),
+    field_generators_(
+      new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+
+  int next_has_bit_index = 0;
+  bool saved_defaults_needed = false;
+  // Construct all the FieldGenerators.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    FieldGenerator* field_generator = MakeGenerator(
+        descriptor->field(i), params, &next_has_bit_index);
+    saved_defaults_needed = saved_defaults_needed
+        || field_generator->SavedDefaultNeeded();
+    field_generators_[i].reset(field_generator);
+  }
+  total_bits_ = next_has_bit_index;
+  saved_defaults_needed_ = saved_defaults_needed;
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+    const Params &params, int* next_has_bit_index) {
+  JavaType java_type = GetJavaType(field);
+  if (field->is_repeated()) {
+    switch (java_type) {
+      case JAVATYPE_MESSAGE:
+        if (IsMapEntry(field->message_type())) {
+          return new MapFieldGenerator(field, params);
+        } else {
+          return new RepeatedMessageFieldGenerator(field, params);
+        }
+      case JAVATYPE_ENUM:
+        return new RepeatedEnumFieldGenerator(field, params);
+      default:
+        return new RepeatedPrimitiveFieldGenerator(field, params);
+    }
+  } else if (field->containing_oneof()) {
+    switch (java_type) {
+      case JAVATYPE_MESSAGE:
+        return new MessageOneofFieldGenerator(field, params);
+      case JAVATYPE_ENUM:
+      default:
+        return new PrimitiveOneofFieldGenerator(field, params);
+    }
+  } else if (params.optional_field_accessors() && field->is_optional()
+      && java_type != JAVATYPE_MESSAGE) {
+    // We need a has-bit for each primitive/enum field because their default
+    // values could be same as explicitly set values. But we don't need it
+    // for a message field because they have no defaults and Nano uses 'null'
+    // for unset messages, which cannot be set explicitly.
+    switch (java_type) {
+      case JAVATYPE_ENUM:
+        return new AccessorEnumFieldGenerator(
+            field, params, (*next_has_bit_index)++);
+      default:
+        return new AccessorPrimitiveFieldGenerator(
+            field, params, (*next_has_bit_index)++);
+    }
+  } else {
+    switch (java_type) {
+      case JAVATYPE_MESSAGE:
+        return new MessageFieldGenerator(field, params);
+      case JAVATYPE_ENUM:
+        return new EnumFieldGenerator(field, params);
+      default:
+        return new PrimitiveFieldGenerator(field, params);
+    }
+  }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+    const FieldDescriptor* field) const {
+  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+  return *field_generators_[field->index()];
+}
+
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables) {
+  (*variables)["oneof_name"] =
+      UnderscoresToCamelCase(descriptor->containing_oneof());
+  (*variables)["oneof_capitalized_name"] =
+      UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
+  (*variables)["oneof_index"] =
+      SimpleItoa(descriptor->containing_oneof()->index());
+  (*variables)["set_oneof_case"] =
+      "this." + (*variables)["oneof_name"] +
+      "Case_ = " + SimpleItoa(descriptor->number());
+  (*variables)["clear_oneof_case"] =
+      "this." + (*variables)["oneof_name"] + "Case_ = 0";
+  (*variables)["has_oneof_case"] =
+      "this." + (*variables)["oneof_name"] + "Case_ == " +
+      SimpleItoa(descriptor->number());
+}
+
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+                              const map<string, string>& variables,
+                              io::Printer* printer) {
+  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+    printer->Print(variables,
+      "if (this.has$capitalized_name$()) {\n"
+      "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
+      "                               (byte[]) other.$oneof_name$_)) {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(variables,
+      "if (this.has$capitalized_name$()) {\n"
+      "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  }
+}
+
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+                                const map<string, string>& variables,
+                                io::Printer* printer) {
+  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+    printer->Print(variables,
+      "result = 31 * result + ($has_oneof_case$\n"
+      "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
+  } else {
+    printer->Print(variables,
+      "result = 31 * result +\n"
+      "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
+  }
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.h
new file mode 100644
index 0000000..57c221f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -0,0 +1,130 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class FieldGenerator {
+ public:
+  FieldGenerator(const Params& params) : params_(params) {}
+  virtual ~FieldGenerator();
+
+  virtual bool SavedDefaultNeeded() const;
+  virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+
+  // Generates code for Java fields and methods supporting this field.
+  // If this field needs a saved default (SavedDefaultNeeded() is true),
+  // then @lazy_init controls how the static field for that default value
+  // and its initialization code should be generated. If @lazy_init is
+  // true, the static field is not declared final and the initialization
+  // code is generated only when GenerateInitSavedDefaultCode is called;
+  // otherwise, the static field is declared final and initialized inline.
+  // GenerateInitSavedDefaultCode will not be called in the latter case.
+  virtual void GenerateMembers(
+      io::Printer* printer, bool lazy_init) const = 0;
+
+  virtual void GenerateClearCode(io::Printer* printer) const = 0;
+  virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+
+  // Generates code to merge from packed serialized form. The default
+  // implementation will fail; subclasses which can handle packed serialized
+  // forms will override this and print appropriate code to the printer.
+  virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+
+  virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+  virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
+  virtual void GenerateFixClonedCode(io::Printer* printer) const {}
+
+ protected:
+  const Params& params_;
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+  explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
+  ~FieldGeneratorMap();
+
+  const FieldGenerator& get(const FieldDescriptor* field) const;
+  int total_bits() const { return total_bits_; }
+  bool saved_defaults_needed() const { return saved_defaults_needed_; }
+
+ private:
+  const Descriptor* descriptor_;
+  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+  int total_bits_;
+  bool saved_defaults_needed_;
+
+  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+      const Params &params, int* next_has_bit_index);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables);
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+                              const map<string, string>& variables,
+                              io::Printer* printer);
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+                                const map<string, string>& variables,
+                                io::Printer* printer);
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.cc
new file mode 100644
index 0000000..3676ab9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.cc
@@ -0,0 +1,263 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <iostream>
+
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_message.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+// Recursively searches the given message to see if it contains any extensions.
+bool UsesExtensions(const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+
+  // We conservatively assume that unknown fields are extensions.
+  if (reflection->GetUnknownFields(message).field_count() > 0) return true;
+
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+
+  for (int i = 0; i < fields.size(); i++) {
+    if (fields[i]->is_extension()) return true;
+
+    if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (fields[i]->is_repeated()) {
+        int size = reflection->FieldSize(message, fields[i]);
+        for (int j = 0; j < size; j++) {
+          const Message& sub_message =
+            reflection->GetRepeatedMessage(message, fields[i], j);
+          if (UsesExtensions(sub_message)) return true;
+        }
+      } else {
+        const Message& sub_message = reflection->GetMessage(message, fields[i]);
+        if (UsesExtensions(sub_message)) return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+}  // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params)
+  : file_(file),
+    params_(params),
+    java_package_(FileJavaPackage(params, file)),
+    classname_(FileClassName(params, file)) {}
+
+FileGenerator::~FileGenerator() {}
+
+bool FileGenerator::Validate(string* error) {
+  // Check for extensions
+  FileDescriptorProto file_proto;
+  file_->CopyTo(&file_proto);
+  if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) {
+    error->assign(file_->name());
+    error->append(
+        ": Java NANO_RUNTIME only supports extensions when the "
+        "'store_unknown_fields' generator option is 'true'.");
+    return false;
+  }
+
+  if (file_->service_count() != 0 && !params_.ignore_services()) {
+    error->assign(file_->name());
+    error->append(
+      ": Java NANO_RUNTIME does not support services\"");
+    return false;
+  }
+
+  if (!IsOuterClassNeeded(params_, file_)) {
+    return true;
+  }
+
+  // Check whether legacy javanano generator would omit the outer class.
+  if (!params_.has_java_outer_classname(file_->name())
+      && file_->message_type_count() == 1
+      && file_->enum_type_count() == 0 && file_->extension_count() == 0) {
+    cout << "INFO: " << file_->name() << ":" << endl;
+    cout << "Javanano generator has changed to align with java generator. "
+        "An outer class will be created for this file and the single message "
+        "in the file will become a nested class. Use java_multiple_files to "
+        "skip generating the outer class, or set an explicit "
+        "java_outer_classname to suppress this message." << endl;
+  }
+
+  // Check that no class name matches the file's class name.  This is a common
+  // problem that leads to Java compile errors that can be hard to understand.
+  // It's especially bad when using the java_multiple_files, since we would
+  // end up overwriting the outer class with one of the inner ones.
+  bool found_conflict = false;
+  for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
+    if (file_->message_type(i)->name() == classname_) {
+      found_conflict = true;
+    }
+  }
+  if (params_.java_enum_style()) {
+    for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) {
+      if (file_->enum_type(i)->name() == classname_) {
+        found_conflict = true;
+      }
+    }
+  }
+  if (found_conflict) {
+    error->assign(file_->name());
+    error->append(
+      ": Cannot generate Java output because the file's outer class name, \"");
+    error->append(classname_);
+    error->append(
+      "\", matches the name of one of the types declared inside it.  "
+      "Please either rename the type or use the java_outer_classname "
+      "option to specify a different outer class name for the .proto file.");
+    return false;
+  }
+  return true;
+}
+
+void FileGenerator::Generate(io::Printer* printer) {
+  // We don't import anything because we refer to all classes by their
+  // fully-qualified names in the generated source.
+  printer->Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
+  if (!java_package_.empty()) {
+    printer->Print(
+      "\n"
+      "package $package$;\n",
+      "package", java_package_);
+  }
+
+  // Note: constants (from enums, emitted in the loop below) may have the same names as constants
+  // in the nested classes. This causes Java warnings, but is not fatal, so we suppress those
+  // warnings here in the top-most class declaration.
+  printer->Print(
+    "\n"
+    "@SuppressWarnings(\"hiding\")\n"
+    "public interface $classname$ {\n",
+    "classname", classname_);
+  printer->Indent();
+
+  // -----------------------------------------------------------------
+
+  // Extensions.
+  for (int i = 0; i < file_->extension_count(); i++) {
+    ExtensionGenerator(file_->extension(i), params_).Generate(printer);
+  }
+
+  // Enums.
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    EnumGenerator(file_->enum_type(i), params_).Generate(printer);
+  }
+
+  // Messages.
+  if (!params_.java_multiple_files(file_->name())) {
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      MessageGenerator(file_->message_type(i), params_).Generate(printer);
+    }
+  }
+
+  // Static variables.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+}
+
+template<typename GeneratorClass, typename DescriptorClass>
+static void GenerateSibling(const string& package_dir,
+                            const string& java_package,
+                            const DescriptorClass* descriptor,
+                            GeneratorContext* output_directory,
+                            vector<string>* file_list,
+                            const Params& params) {
+  string filename = package_dir + descriptor->name() + ".java";
+  file_list->push_back(filename);
+
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+    output_directory->Open(filename));
+  io::Printer printer(output.get(), '$');
+
+  printer.Print(
+    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
+  if (!java_package.empty()) {
+    printer.Print(
+      "\n"
+      "package $package$;\n",
+      "package", java_package);
+  }
+
+  GeneratorClass(descriptor, params).Generate(&printer);
+}
+
+void FileGenerator::GenerateSiblings(const string& package_dir,
+                                     GeneratorContext* output_directory,
+                                     vector<string>* file_list) {
+  if (params_.java_multiple_files(file_->name())) {
+    for (int i = 0; i < file_->message_type_count(); i++) {
+      GenerateSibling<MessageGenerator>(package_dir, java_package_,
+                                        file_->message_type(i),
+                                        output_directory, file_list, params_);
+    }
+
+    if (params_.java_enum_style()) {
+      for (int i = 0; i < file_->enum_type_count(); i++) {
+        GenerateSibling<EnumGenerator>(package_dir, java_package_,
+                                       file_->enum_type(i),
+                                       output_directory, file_list, params_);
+      }
+    }
+  }
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.h
new file mode 100644
index 0000000..217eafe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_file.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+  class FileDescriptor;        // descriptor.h
+  namespace io {
+    class Printer;             // printer.h
+  }
+  namespace compiler {
+    class GeneratorContext;     // code_generator.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class FileGenerator {
+ public:
+  explicit FileGenerator(const FileDescriptor* file, const Params& params);
+  ~FileGenerator();
+
+  // Checks for problems that would otherwise lead to cryptic compile errors.
+  // Returns true if there are no problems, or writes an error description to
+  // the given string and returns false otherwise.
+  bool Validate(string* error);
+
+  void Generate(io::Printer* printer);
+
+  // If we aren't putting everything into one file, this will write all the
+  // files other than the outer file (i.e. one for each message, enum, and
+  // service type).
+  void GenerateSiblings(const string& package_dir,
+                        GeneratorContext* output_directory,
+                        vector<string>* file_list);
+
+  const string& java_package() { return java_package_; }
+  const string& classname()    { return classname_;    }
+
+ private:
+  const FileDescriptor* file_;
+  const Params& params_;
+  string java_package_;
+  string classname_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.cc
new file mode 100644
index 0000000..7c3a042
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -0,0 +1,230 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_generator.h>
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+string TrimString(const string& s) {
+  string::size_type start = s.find_first_not_of(" \n\r\t");
+  if (start == string::npos) {
+    return "";
+  }
+  string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
+  return s.substr(start, end - start);
+}
+
+} // namespace
+
+void UpdateParamsRecursively(Params& params,
+    const FileDescriptor* file) {
+  // Add any parameters for this file
+  if (file->options().has_java_outer_classname()) {
+    params.set_java_outer_classname(
+      file->name(), file->options().java_outer_classname());
+  }
+  if (file->options().has_java_package()) {
+    string result = file->options().java_package();
+    if (!result.empty()) {
+      result += ".";
+    }
+    result += "nano";
+    params.set_java_package(
+      file->name(), result);
+  }
+  if (file->options().has_java_multiple_files()) {
+    params.set_java_multiple_files(
+      file->name(), file->options().java_multiple_files());
+  }
+
+  // Loop through all dependent files recursively
+  // adding dep
+  for (int i = 0; i < file->dependency_count(); i++) {
+    UpdateParamsRecursively(params, file->dependency(i));
+  }
+}
+
+JavaNanoGenerator::JavaNanoGenerator() {}
+JavaNanoGenerator::~JavaNanoGenerator() {}
+
+bool JavaNanoGenerator::Generate(const FileDescriptor* file,
+                             const string& parameter,
+                             GeneratorContext* output_directory,
+                             string* error) const {
+  vector<pair<string, string> > options;
+
+  ParseGeneratorParameter(parameter, &options);
+
+  // -----------------------------------------------------------------
+  // parse generator options
+
+  // Name a file where we will write a list of generated file names, one
+  // per line.
+  string output_list_file;
+  Params params(file->name());
+
+  // Update per file params
+  UpdateParamsRecursively(params, file);
+
+  // Replace any existing options with ones from command line
+  for (int i = 0; i < options.size(); i++) {
+    string option_name = TrimString(options[i].first);
+    string option_value = TrimString(options[i].second);
+    if (option_name == "output_list_file") {
+      output_list_file = option_value;
+    } else if (option_name == "java_package") {
+        vector<string> parts;
+        SplitStringUsing(option_value, "|", &parts);
+        if (parts.size() != 2) {
+          *error = "Bad java_package, expecting filename|PackageName found '"
+            + option_value + "'";
+          return false;
+        }
+        params.set_java_package(parts[0], parts[1]);
+    } else if (option_name == "java_outer_classname") {
+        vector<string> parts;
+        SplitStringUsing(option_value, "|", &parts);
+        if (parts.size() != 2) {
+          *error = "Bad java_outer_classname, "
+                   "expecting filename|ClassName found '"
+                   + option_value + "'";
+          return false;
+        }
+        params.set_java_outer_classname(parts[0], parts[1]);
+    } else if (option_name == "store_unknown_fields") {
+      params.set_store_unknown_fields(option_value == "true");
+    } else if (option_name == "java_multiple_files") {
+      params.set_override_java_multiple_files(option_value == "true");
+    } else if (option_name == "java_nano_generate_has") {
+      params.set_generate_has(option_value == "true");
+    } else if (option_name == "enum_style") {
+      params.set_java_enum_style(option_value == "java");
+    } else if (option_name == "optional_field_style") {
+      params.set_optional_field_accessors(option_value == "accessors");
+      params.set_use_reference_types_for_primitives(option_value == "reftypes"
+          || option_value == "reftypes_compat_mode");
+      params.set_reftypes_primitive_enums(
+          option_value == "reftypes_compat_mode");
+      if (option_value == "reftypes_compat_mode") {
+        params.set_generate_clear(false);
+      }
+    } else if (option_name == "generate_equals") {
+      params.set_generate_equals(option_value == "true");
+    } else if (option_name == "ignore_services") {
+      params.set_ignore_services(option_value == "true");
+    } else if (option_name == "parcelable_messages") {
+      params.set_parcelable_messages(option_value == "true");
+    } else if (option_name == "generate_clone") {
+      params.set_generate_clone(option_value == "true");
+    } else if (option_name == "generate_intdefs") {
+      params.set_generate_intdefs(option_value == "true");
+    } else if (option_name == "generate_clear") {
+      params.set_generate_clear(option_value == "true");
+    } else {
+      *error = "Ignore unknown javanano generator option: " + option_name;
+    }
+  }
+
+  // Check illegal parameter combinations
+  // Note: the enum-like optional_field_style generator param ensures
+  // that we can never have illegal combinations of field styles
+  // (e.g. reftypes and accessors can't be on at the same time).
+  if (params.generate_has()
+      && (params.optional_field_accessors()
+          || params.use_reference_types_for_primitives())) {
+    error->assign("java_nano_generate_has=true cannot be used in conjunction"
+        " with optional_field_style=accessors or optional_field_style=reftypes");
+    return false;
+  }
+
+  // -----------------------------------------------------------------
+
+  FileGenerator file_generator(file, params);
+  if (!file_generator.Validate(error)) {
+    return false;
+  }
+
+  string package_dir =
+    StringReplace(file_generator.java_package(), ".", "/", true);
+  if (!package_dir.empty()) package_dir += "/";
+
+  vector<string> all_files;
+
+  if (IsOuterClassNeeded(params, file)) {
+    string java_filename = package_dir;
+    java_filename += file_generator.classname();
+    java_filename += ".java";
+    all_files.push_back(java_filename);
+
+    // Generate main java file.
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+      output_directory->Open(java_filename));
+    io::Printer printer(output.get(), '$');
+    file_generator.Generate(&printer);
+  }
+
+  // Generate sibling files.
+  file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
+
+  // Generate output list if requested.
+  if (!output_list_file.empty()) {
+    // Generate output list.  This is just a simple text file placed in a
+    // deterministic location which lists the .java files being generated.
+    scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+      output_directory->Open(output_list_file));
+    io::Printer srclist_printer(srclist_raw_output.get(), '$');
+    for (int i = 0; i < all_files.size(); i++) {
+      srclist_printer.Print("$filename$\n", "filename", all_files[i]);
+    }
+  }
+
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.h
new file mode 100644
index 0000000..6f9f7f2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_generator.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Generates Java nano code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// CodeGenerator implementation which generates Java nano code.  If you create your
+// own protocol compiler binary and you want it to support Java output for the
+// nano runtime, you can do so by registering an instance of this CodeGenerator with
+// the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator {
+ public:
+  JavaNanoGenerator();
+  ~JavaNanoGenerator();
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* output_directory,
+                string* error) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.cc
new file mode 100644
index 0000000..02811a2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -0,0 +1,591 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <limits>
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+const char kThickSeparator[] =
+  "// ===================================================================\n";
+const char kThinSeparator[] =
+  "// -------------------------------------------------------------------\n";
+
+class RenameKeywords {
+ private:
+  hash_set<string> java_keywords_set_;
+
+ public:
+  RenameKeywords() {
+    static const char* kJavaKeywordsList[] = {
+      // Reserved Java Keywords
+      "abstract", "assert", "boolean", "break", "byte", "case", "catch",
+      "char", "class", "const", "continue", "default", "do", "double", "else",
+      "enum", "extends", "final", "finally", "float", "for", "goto", "if",
+      "implements", "import", "instanceof", "int", "interface", "long",
+      "native", "new", "package", "private", "protected", "public", "return",
+      "short", "static", "strictfp", "super", "switch", "synchronized",
+      "this", "throw", "throws", "transient", "try", "void", "volatile", "while",
+
+      // Reserved Keywords for Literals
+      "false", "null", "true"
+    };
+
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) {
+      java_keywords_set_.insert(kJavaKeywordsList[i]);
+    }
+  }
+
+  // Used to rename the a field name if it's a java keyword.  Specifically
+  // this is used to rename the ["name"] or ["capitalized_name"] field params.
+  // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
+  string RenameJavaKeywordsImpl(const string& input) {
+    string result = input;
+
+    if (java_keywords_set_.find(result) != java_keywords_set_.end()) {
+      result += "_";
+    }
+
+    return result;
+  }
+
+};
+
+static RenameKeywords sRenameKeywords;
+
+namespace {
+
+const char* kDefaultPackage = "";
+
+const string& FieldName(const FieldDescriptor* field) {
+  // Groups are hacky:  The name of the field is just the lower-cased name
+  // of the group type.  In Java, though, we would like to retain the original
+  // capitalization of the type name.
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    return field->message_type()->name();
+  } else {
+    return field->name();
+  }
+}
+
+string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
+  string result;
+  // Note:  I distrust ctype.h due to locales.
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      if (cap_next_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      if (i == 0 && !cap_next_letter) {
+        // Force first letter to lower-case unless explicitly told to
+        // capitalize it.
+        result += input[i] + ('a' - 'A');
+      } else {
+        // Capital letters after the first are left as-is.
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_next_letter = true;
+    } else {
+      cap_next_letter = true;
+    }
+  }
+  return result;
+}
+
+}  // namespace
+
+string UnderscoresToCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCaseImpl(FieldName(field), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCaseImpl(FieldName(field), true);
+}
+
+string UnderscoresToCamelCase(const MethodDescriptor* method) {
+  return UnderscoresToCamelCaseImpl(method->name(), false);
+}
+
+string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
+  return UnderscoresToCamelCaseImpl(oneof->name(), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
+  return UnderscoresToCamelCaseImpl(oneof->name(), true);
+}
+
+string RenameJavaKeywords(const string& input) {
+  return sRenameKeywords.RenameJavaKeywordsImpl(input);
+}
+
+string StripProto(const string& filename) {
+  if (HasSuffixString(filename, ".protodevel")) {
+    return StripSuffixString(filename, ".protodevel");
+  } else {
+    return StripSuffixString(filename, ".proto");
+  }
+}
+
+string FileClassName(const Params& params, const FileDescriptor* file) {
+  if (params.has_java_outer_classname(file->name())) {
+    return params.java_outer_classname(file->name());
+  } else {
+    // Use the filename itself with underscores removed
+    // and a CamelCase style name.
+    string basename;
+    string::size_type last_slash = file->name().find_last_of('/');
+    if (last_slash == string::npos) {
+      basename = file->name();
+    } else {
+      basename = file->name().substr(last_slash + 1);
+    }
+    return UnderscoresToCamelCaseImpl(StripProto(basename), true);
+  }
+}
+
+string FileJavaPackage(const Params& params, const FileDescriptor* file) {
+  if (params.has_java_package(file->name())) {
+    return params.java_package(file->name());
+  } else {
+    string result = kDefaultPackage;
+    if (!file->package().empty()) {
+      if (!result.empty()) result += '.';
+      result += file->package();
+    }
+
+    if (!result.empty()) {
+      result += ".";
+    }
+    result += "nano";
+
+    return result;
+  }
+}
+
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
+  // If java_multiple_files is false, the outer class is always needed.
+  if (!params.java_multiple_files(file->name())) {
+    return true;
+  }
+
+  // File-scope extensions need the outer class as the scope.
+  if (file->extension_count() != 0) {
+    return true;
+  }
+
+  // If container interfaces are not generated, file-scope enums need the
+  // outer class as the scope.
+  if (file->enum_type_count() != 0 && !params.java_enum_style()) {
+    return true;
+  }
+
+  return false;
+}
+
+string ToJavaName(const Params& params, const string& name, bool is_class,
+    const Descriptor* parent, const FileDescriptor* file) {
+  string result;
+  if (parent != NULL) {
+    result.append(ClassName(params, parent));
+  } else if (is_class && params.java_multiple_files(file->name())) {
+    result.append(FileJavaPackage(params, file));
+  } else {
+    result.append(ClassName(params, file));
+  }
+  if (!result.empty()) result.append(1, '.');
+  result.append(RenameJavaKeywords(name));
+  return result;
+}
+
+string ClassName(const Params& params, const FileDescriptor* descriptor) {
+  string result = FileJavaPackage(params, descriptor);
+  if (!result.empty()) result += '.';
+  result += FileClassName(params, descriptor);
+  return result;
+}
+
+string ClassName(const Params& params, const EnumDescriptor* descriptor) {
+  const Descriptor* parent = descriptor->containing_type();
+  // When using Java enum style, an enum's class name contains the enum name.
+  // Use the standard ToJavaName translation.
+  if (params.java_enum_style()) {
+    return ToJavaName(params, descriptor->name(), true, parent,
+                      descriptor->file());
+  }
+  // Otherwise the enum members are accessed from the enclosing class.
+  if (parent != NULL) {
+    return ClassName(params, parent);
+  } else {
+    return ClassName(params, descriptor->file());
+  }
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+  string name = field->name() + "_FIELD_NUMBER";
+  UpperString(&name);
+  return name;
+}
+
+string FieldDefaultConstantName(const FieldDescriptor *field) {
+  return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
+}
+
+void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
+  // We don't want to print group bodies so we cut off after the first line
+  // (the second line for extensions).
+  string def = field->DebugString();
+  string::size_type first_line_end = def.find_first_of('\n');
+  printer->Print("// $def$\n",
+    "def", def.substr(0, first_line_end));
+  if (field->is_extension()) {
+    string::size_type second_line_start = first_line_end + 1;
+    string::size_type second_line_length =
+        def.find('\n', second_line_start) - second_line_start;
+    printer->Print("// $def$\n",
+      "def", def.substr(second_line_start, second_line_length));
+  }
+}
+
+JavaType GetJavaType(FieldDescriptor::Type field_type) {
+  switch (field_type) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+      return JAVATYPE_INT;
+
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      return JAVATYPE_LONG;
+
+    case FieldDescriptor::TYPE_FLOAT:
+      return JAVATYPE_FLOAT;
+
+    case FieldDescriptor::TYPE_DOUBLE:
+      return JAVATYPE_DOUBLE;
+
+    case FieldDescriptor::TYPE_BOOL:
+      return JAVATYPE_BOOLEAN;
+
+    case FieldDescriptor::TYPE_STRING:
+      return JAVATYPE_STRING;
+
+    case FieldDescriptor::TYPE_BYTES:
+      return JAVATYPE_BYTES;
+
+    case FieldDescriptor::TYPE_ENUM:
+      return JAVATYPE_ENUM;
+
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      return JAVATYPE_MESSAGE;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return JAVATYPE_INT;
+}
+
+string PrimitiveTypeName(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return "int";
+    case JAVATYPE_LONG   : return "long";
+    case JAVATYPE_FLOAT  : return "float";
+    case JAVATYPE_DOUBLE : return "double";
+    case JAVATYPE_BOOLEAN: return "boolean";
+    case JAVATYPE_STRING : return "java.lang.String";
+    case JAVATYPE_BYTES  : return "byte[]";
+    case JAVATYPE_ENUM   : return "int";
+    case JAVATYPE_MESSAGE: return "";
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+string BoxedPrimitiveTypeName(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return "java.lang.Integer";
+    case JAVATYPE_LONG   : return "java.lang.Long";
+    case JAVATYPE_FLOAT  : return "java.lang.Float";
+    case JAVATYPE_DOUBLE : return "java.lang.Double";
+    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
+    case JAVATYPE_STRING : return "java.lang.String";
+    case JAVATYPE_BYTES  : return "byte[]";
+    case JAVATYPE_ENUM   : return "java.lang.Integer";
+    case JAVATYPE_MESSAGE: return "";
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
+  switch (GetJavaType(field)) {
+    case JAVATYPE_INT    : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+    case JAVATYPE_LONG   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
+    case JAVATYPE_FLOAT  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
+    case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
+    case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
+    case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
+    case JAVATYPE_BYTES  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
+    case JAVATYPE_ENUM   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+    case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+string DefaultValue(const Params& params, const FieldDescriptor* field) {
+  if (field->label() == FieldDescriptor::LABEL_REPEATED) {
+    return EmptyArrayName(params, field);
+  }
+
+  if (params.use_reference_types_for_primitives()) {
+    if (params.reftypes_primitive_enums()
+          && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      return "Integer.MIN_VALUE";
+    }
+    return "null";
+  }
+
+  // Switch on cpp_type since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return SimpleItoa(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      // Need to print as a signed int since Java has no unsigned.
+      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
+    case FieldDescriptor::CPPTYPE_INT64:
+      return SimpleItoa(field->default_value_int64()) + "L";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
+             "L";
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = field->default_value_double();
+      if (value == numeric_limits<double>::infinity()) {
+        return "Double.POSITIVE_INFINITY";
+      } else if (value == -numeric_limits<double>::infinity()) {
+        return "Double.NEGATIVE_INFINITY";
+      } else if (value != value) {
+        return "Double.NaN";
+      } else {
+        return SimpleDtoa(value) + "D";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = field->default_value_float();
+      if (value == numeric_limits<float>::infinity()) {
+        return "Float.POSITIVE_INFINITY";
+      } else if (value == -numeric_limits<float>::infinity()) {
+        return "Float.NEGATIVE_INFINITY";
+      } else if (value != value) {
+        return "Float.NaN";
+      } else {
+        return SimpleFtoa(value) + "F";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "true" : "false";
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (!field->default_value_string().empty()) {
+        // Point it to the static final in the generated code.
+        return FieldDefaultConstantName(field);
+      } else {
+        if (field->type() == FieldDescriptor::TYPE_BYTES) {
+          return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
+        } else {
+          return "\"\"";
+        }
+      }
+
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return ClassName(params, field->enum_type()) + "." +
+             RenameJavaKeywords(field->default_value_enum()->name());
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "null";
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return "";
+}
+
+
+static const char* kBitMasks[] = {
+  "0x00000001",
+  "0x00000002",
+  "0x00000004",
+  "0x00000008",
+  "0x00000010",
+  "0x00000020",
+  "0x00000040",
+  "0x00000080",
+
+  "0x00000100",
+  "0x00000200",
+  "0x00000400",
+  "0x00000800",
+  "0x00001000",
+  "0x00002000",
+  "0x00004000",
+  "0x00008000",
+
+  "0x00010000",
+  "0x00020000",
+  "0x00040000",
+  "0x00080000",
+  "0x00100000",
+  "0x00200000",
+  "0x00400000",
+  "0x00800000",
+
+  "0x01000000",
+  "0x02000000",
+  "0x04000000",
+  "0x08000000",
+  "0x10000000",
+  "0x20000000",
+  "0x40000000",
+  "0x80000000",
+};
+
+string GetBitFieldName(int index) {
+  string var_name = "bitField";
+  var_name += SimpleItoa(index);
+  var_name += "_";
+  return var_name;
+}
+
+string GetBitFieldNameForBit(int bit_index) {
+  return GetBitFieldName(bit_index / 32);
+}
+
+string GenerateGetBit(int bit_index) {
+  string var_name = GetBitFieldNameForBit(bit_index);
+  int bit_in_var_index = bit_index % 32;
+
+  string mask = kBitMasks[bit_in_var_index];
+  string result = "((" + var_name + " & " + mask + ") != 0)";
+  return result;
+}
+
+string GenerateSetBit(int bit_index) {
+  string var_name = GetBitFieldNameForBit(bit_index);
+  int bit_in_var_index = bit_index % 32;
+
+  string mask = kBitMasks[bit_in_var_index];
+  string result = var_name + " |= " + mask;
+  return result;
+}
+
+string GenerateClearBit(int bit_index) {
+  string var_name = GetBitFieldNameForBit(bit_index);
+  int bit_in_var_index = bit_index % 32;
+
+  string mask = kBitMasks[bit_in_var_index];
+  string result = var_name + " = (" + var_name + " & ~" + mask + ")";
+  return result;
+}
+
+string GenerateDifferentBit(int bit_index) {
+  string var_name = GetBitFieldNameForBit(bit_index);
+  int bit_in_var_index = bit_index % 32;
+
+  string mask = kBitMasks[bit_in_var_index];
+  string result = "((" + var_name + " & " + mask
+      + ") != (other." + var_name + " & " + mask + "))";
+  return result;
+}
+
+void SetBitOperationVariables(const string name,
+    int bitIndex, map<string, string>* variables) {
+  (*variables)["get_" + name] = GenerateGetBit(bitIndex);
+  (*variables)["set_" + name] = GenerateSetBit(bitIndex);
+  (*variables)["clear_" + name] = GenerateClearBit(bitIndex);
+  (*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
+}
+
+bool HasMapField(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+        IsMapEntry(field->message_type())) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.h
new file mode 100644
index 0000000..014c85a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -0,0 +1,199 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// Commonly-used separator comments.  Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
+// "fooBarBaz" or "FooBarBaz", respectively.
+string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCamelCase(const OneofDescriptor* oneof);
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);
+
+// Appends an "_" to the end of a field where the name is a reserved java
+// keyword.  For example int32 public = 1 will generate int public_.
+string RenameJavaKeywords(const string& input);
+
+// Similar, but for method names.  (Typically, this merely has the effect
+// of lower-casing the first letter of the name.)
+string UnderscoresToCamelCase(const MethodDescriptor* method);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Gets the unqualified class name for the file.  Each .proto file becomes a
+// single Java class, with all its contents nested in that class.
+string FileClassName(const Params& params, const FileDescriptor* file);
+
+// Returns the file's Java package name.
+string FileJavaPackage(const Params& params, const FileDescriptor* file);
+
+// Returns whether the Java outer class is needed, i.e. whether the option
+// java_multiple_files is false, or the proto file contains any file-scope
+// enums/extensions.
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
+
+// Converts the given simple name of a proto entity to its fully-qualified name
+// in the Java namespace, given that it is in the given file enclosed in the
+// given parent message (or NULL for file-scope entities). Whether the file's
+// outer class name should be included in the return value depends on factors
+// inferrable from the given arguments, including is_class which indicates
+// whether the entity translates to a Java class.
+string ToJavaName(const Params& params, const string& name, bool is_class,
+    const Descriptor* parent, const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+inline string ClassName(const Params& params, const Descriptor* descriptor) {
+  return ToJavaName(params, descriptor->name(), true,
+                    descriptor->containing_type(), descriptor->file());
+}
+string ClassName(const Params& params, const EnumDescriptor* descriptor);
+inline string ClassName(const Params& params,
+    const ServiceDescriptor* descriptor) {
+  return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
+}
+inline string ExtensionIdentifierName(const Params& params,
+    const FieldDescriptor* descriptor) {
+  return ToJavaName(params, descriptor->name(), false,
+                    descriptor->extension_scope(), descriptor->file());
+}
+string ClassName(const Params& params, const FileDescriptor* descriptor);
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+string FieldConstantName(const FieldDescriptor *field);
+
+string FieldDefaultConstantName(const FieldDescriptor *field);
+
+// Print the field's proto-syntax definition as a comment.
+void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field);
+
+enum JavaType {
+  JAVATYPE_INT,
+  JAVATYPE_LONG,
+  JAVATYPE_FLOAT,
+  JAVATYPE_DOUBLE,
+  JAVATYPE_BOOLEAN,
+  JAVATYPE_STRING,
+  JAVATYPE_BYTES,
+  JAVATYPE_ENUM,
+  JAVATYPE_MESSAGE
+};
+
+JavaType GetJavaType(FieldDescriptor::Type field_type);
+
+inline JavaType GetJavaType(const FieldDescriptor* field) {
+  return GetJavaType(field->type());
+}
+
+string PrimitiveTypeName(JavaType type);
+
+// Get the fully-qualified class name for a boxed primitive type, e.g.
+// "java.lang.Integer" for JAVATYPE_INT.  Returns NULL for enum and message
+// types.
+string BoxedPrimitiveTypeName(JavaType type);
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field);
+
+string DefaultValue(const Params& params, const FieldDescriptor* field);
+
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given field index.
+string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bit_index / 32)
+string GetBitFieldNameForBit(int bit_index);
+
+// Generates the java code for the expression that returns whether the bit at
+// the given bit index is set.
+// Example: "((bitField1_ & 0x04000000) != 0)"
+string GenerateGetBit(int bit_index);
+
+// Generates the java code for the expression that sets the bit at the given
+// bit index.
+// Example: "bitField1_ |= 0x04000000"
+string GenerateSetBit(int bit_index);
+
+// Generates the java code for the expression that clears the bit at the given
+// bit index.
+// Example: "bitField1_ = (bitField1_ & ~0x04000000)"
+string GenerateClearBit(int bit_index);
+
+// Generates the java code for the expression that returns whether the bit at
+// the given bit index contains different values in the current object and
+// another object accessible via the variable 'other'.
+// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))"
+string GenerateDifferentBit(int bit_index);
+
+// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is
+// the given name of the bit, to the appropriate Java expressions for the given
+// bit index.
+void SetBitOperationVariables(const string name,
+    int bitIndex, map<string, string>* variables);
+
+inline bool IsMapEntry(const Descriptor* descriptor) {
+  // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
+  return descriptor->options().map_entry() &&
+      descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool HasMapField(const Descriptor* descriptor);
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.cc
new file mode 100644
index 0000000..83b2b0c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.cc
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+string TypeName(const Params& params, const FieldDescriptor* field,
+                bool boxed) {
+  JavaType java_type = GetJavaType(field);
+  switch (java_type) {
+    case JAVATYPE_MESSAGE:
+      return ClassName(params, field->message_type());
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_FLOAT:
+    case JAVATYPE_DOUBLE:
+    case JAVATYPE_BOOLEAN:
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+    case JAVATYPE_ENUM:
+      if (boxed) {
+        return BoxedPrimitiveTypeName(java_type);
+      } else {
+        return PrimitiveTypeName(java_type);
+      }
+    // No default because we want the compiler to complain if any new JavaTypes
+    // are added..
+  }
+
+  GOOGLE_LOG(FATAL) << "should not reach here.";
+  return "";
+}
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+  const Descriptor* message = descriptor->message_type();
+  GOOGLE_CHECK(message->options().map_entry());
+  return message->FindFieldByName("value");
+}
+
+void SetMapVariables(const Params& params,
+    const FieldDescriptor* descriptor, map<string, string>* variables) {
+  const FieldDescriptor* key = KeyField(descriptor);
+  const FieldDescriptor* value = ValueField(descriptor);
+  (*variables)["name"] =
+    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["key_type"] = TypeName(params, key, false);
+  (*variables)["boxed_key_type"] = TypeName(params,key, true);
+  (*variables)["key_desc_type"] =
+      "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
+  (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
+  (*variables)["value_type"] = TypeName(params, value, false);
+  (*variables)["boxed_value_type"] = TypeName(params, value, true);
+  (*variables)["value_desc_type"] =
+      "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
+  (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
+  (*variables)["type_parameters"] =
+      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+  (*variables)["value_default"] =
+      value->type() == FieldDescriptor::TYPE_MESSAGE
+          ? "new " + (*variables)["value_type"] + "()"
+          : "null";
+}
+}  // namespace
+
+// ===================================================================
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
+  SetMapVariables(params, descriptor, &variables_);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public java.util.Map<$type_parameters$> $name$;\n");
+}
+
+void MapFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = null;\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
+    "  input, this.$name$, mapFactory,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
+    "  $value_default$,\n"
+    "  $key_tag$, $value_tag$);\n"
+    "\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  com.google.protobuf.nano.InternalNano.serializeMapField(\n"
+    "    output, this.$name$, $number$,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
+    "    this.$name$, $number$,\n"
+    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+    "  this.$name$, other.$name$)) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void MapFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result +\n"
+    "    com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.h
new file mode 100644
index 0000000..c01bde3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_map_field.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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_COMPILER_JAVANANO_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+  explicit MapFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~MapFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.cc
new file mode 100644
index 0000000..a41da5a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -0,0 +1,676 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/javanano/javanano_message.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+struct FieldOrderingByNumber {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    return a->number() < b->number();
+  }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+    new const FieldDescriptor*[descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  sort(fields, fields + descriptor->field_count(),
+       FieldOrderingByNumber());
+  return fields;
+}
+
+}  // namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
+  : params_(params),
+    descriptor_(descriptor),
+    field_generators_(descriptor, params) {
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
+  // Generate static members for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    // TODO(kenton):  Reuse MessageGenerator objects?
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    MessageGenerator(descriptor_->nested_type(i), params_)
+      .GenerateStaticVariables(printer);
+  }
+}
+
+void MessageGenerator::GenerateStaticVariableInitializers(
+    io::Printer* printer) {
+  // Generate static member initializers for all nested types.
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+   // TODO(kenton):  Reuse MessageGenerator objects?
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    MessageGenerator(descriptor_->nested_type(i), params_)
+      .GenerateStaticVariableInitializers(printer);
+  }
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+  if (!params_.store_unknown_fields() &&
+      (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
+    GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
+        "'store_unknown_fields' generator option is 'true'\n";
+  }
+
+  const string& file_name = descriptor_->file()->name();
+  bool is_own_file =
+    params_.java_multiple_files(file_name)
+      && descriptor_->containing_type() == NULL;
+
+  if (is_own_file) {
+    // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
+    // may have the same names as constants in the nested classes. This causes Java warnings, but
+    // is not fatal, so we suppress those warnings here in the top-most class declaration.
+    printer->Print(
+      "\n"
+      "@SuppressWarnings(\"hiding\")\n"
+      "public final class $classname$ extends\n",
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "\n"
+      "public static final class $classname$ extends\n",
+      "classname", descriptor_->name());
+  }
+  if (params_.store_unknown_fields() && params_.parcelable_messages()) {
+    printer->Print(
+      "    com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
+      "classname", descriptor_->name());
+  } else if (params_.store_unknown_fields()) {
+    printer->Print(
+      "    com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
+      "classname", descriptor_->name());
+  } else if (params_.parcelable_messages()) {
+    printer->Print(
+      "    com.google.protobuf.nano.android.ParcelableMessageNano");
+  } else {
+    printer->Print(
+      "    com.google.protobuf.nano.MessageNano");
+  }
+  if (params_.generate_clone()) {
+    printer->Print(" implements java.lang.Cloneable {\n");
+  } else {
+    printer->Print(" {\n");
+  }
+  printer->Indent();
+
+  if (params_.parcelable_messages()) {
+    printer->Print(
+      "\n"
+      "// Used by Parcelable\n"
+      "@SuppressWarnings({\"unused\"})\n"
+      "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
+      "    new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
+      "        $classname$>($classname$.class);\n",
+      "classname", descriptor_->name());
+  }
+
+  // Nested types and extensions
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
+  }
+
+  // oneof
+  map<string, string> vars;
+  vars["message_name"] = descriptor_->name();
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+    vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
+    vars["oneof_capitalized_name"] =
+        UnderscoresToCapitalizedCamelCase(oneof_desc);
+    vars["oneof_index"] = SimpleItoa(oneof_desc->index());
+    // Oneof Constants
+    for (int j = 0; j < oneof_desc->field_count(); j++) {
+      const FieldDescriptor* field = oneof_desc->field(j);
+      vars["number"] = SimpleItoa(field->number());
+      vars["cap_field_name"] = ToUpper(field->name());
+      printer->Print(vars,
+        "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
+    }
+    // oneofCase_ and oneof_
+    printer->Print(vars,
+      "private int $oneof_name$Case_ = 0;\n"
+      "private java.lang.Object $oneof_name$_;\n");
+    printer->Print(vars,
+      "public int get$oneof_capitalized_name$Case() {\n"
+      "  return this.$oneof_name$Case_;\n"
+      "}\n");
+    // Oneof clear
+    printer->Print(vars,
+      "public $message_name$ clear$oneof_capitalized_name$() {\n"
+      "  this.$oneof_name$Case_ = 0;\n"
+      "  this.$oneof_name$_ = null;\n"
+      "  return this;\n"
+      "}\n");
+  }
+
+  // Lazy initialization of otherwise static final fields can help prevent the
+  // class initializer from being generated. We want to prevent it because it
+  // stops ProGuard from inlining any methods in this class into call sites and
+  // therefore reducing the method count. However, extensions are best kept as
+  // public static final fields with initializers, so with their existence we
+  // won't bother with lazy initialization.
+  bool lazy_init = descriptor_->extension_count() == 0;
+
+  // Empty array
+  if (lazy_init) {
+    printer->Print(
+      "\n"
+      "private static volatile $classname$[] _emptyArray;\n"
+      "public static $classname$[] emptyArray() {\n"
+      "  // Lazily initializes the empty array\n"
+      "  if (_emptyArray == null) {\n"
+      "    synchronized (\n"
+      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
+      "      if (_emptyArray == null) {\n"
+      "        _emptyArray = new $classname$[0];\n"
+      "      }\n"
+      "    }\n"
+      "  }\n"
+      "  return _emptyArray;\n"
+      "}\n",
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "\n"
+      "private static final $classname$[] EMPTY_ARRAY = {};\n"
+      "public static $classname$[] emptyArray() {\n"
+      "  return EMPTY_ARRAY;\n"
+      "}\n",
+      "classname", descriptor_->name());
+  }
+
+  // Integers for bit fields
+  int totalInts = (field_generators_.total_bits() + 31) / 32;
+  if (totalInts > 0) {
+    printer->Print("\n");
+    for (int i = 0; i < totalInts; i++) {
+      printer->Print("private int $bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
+  }
+
+  // Fields and maybe their default values
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("\n");
+    PrintFieldComment(printer, descriptor_->field(i));
+    field_generators_.get(descriptor_->field(i)).GenerateMembers(
+        printer, lazy_init);
+  }
+
+  // Constructor, with lazy init code if needed
+  if (lazy_init && field_generators_.saved_defaults_needed()) {
+    printer->Print(
+      "\n"
+      "private static volatile boolean _classInitialized;\n"
+      "\n"
+      "public $classname$() {\n"
+      "  // Lazily initializes the field defaults\n"
+      "  if (!_classInitialized) {\n"
+      "    synchronized (\n"
+      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
+      "      if (!_classInitialized) {\n",
+      "classname", descriptor_->name());
+    printer->Indent();
+    printer->Indent();
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateInitSavedDefaultCode(printer);
+    }
+    printer->Outdent();
+    printer->Outdent();
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+      "        _classInitialized = true;\n"
+      "      }\n"
+      "    }\n"
+      "  }\n");
+    if (params_.generate_clear()) {
+      printer->Print("  clear();\n");
+    }
+    printer->Print("}\n");
+  } else {
+    printer->Print(
+      "\n"
+      "public $classname$() {\n",
+      "classname", descriptor_->name());
+    if (params_.generate_clear()) {
+      printer->Print("  clear();\n");
+    } else {
+      printer->Indent();
+      GenerateFieldInitializers(printer);
+      printer->Outdent();
+    }
+    printer->Print("}\n");
+  }
+
+  // Other methods in this class
+
+  GenerateClear(printer);
+
+  if (params_.generate_clone()) {
+    GenerateClone(printer);
+  }
+
+  if (params_.generate_equals()) {
+    GenerateEquals(printer);
+    GenerateHashCode(printer);
+  }
+
+  GenerateMessageSerializationMethods(printer);
+  GenerateMergeFromMethods(printer);
+  GenerateParseFromMethods(printer);
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+  // Rely on the parent implementations of writeTo() and getSerializedSize()
+  // if there are no fields to serialize in this message.
+  if (descriptor_->field_count() == 0) {
+    return;
+  }
+
+  scoped_array<const FieldDescriptor*> sorted_fields(
+    SortFieldsByNumber(descriptor_));
+
+  printer->Print(
+    "\n"
+    "@Override\n"
+    "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
+    "    throws java.io.IOException {\n");
+  printer->Indent();
+
+  // Output the fields in sorted order
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    GenerateSerializeOneField(printer, sorted_fields[i]);
+  }
+
+  // The parent implementation will write any unknown fields if necessary.
+  printer->Print(
+    "super.writeTo(output);\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+
+  // The parent implementation will get the serialized size for unknown
+  // fields if necessary.
+  printer->Print(
+    "\n"
+    "@Override\n"
+    "protected int computeSerializedSize() {\n"
+    "  int size = super.computeSerializedSize();\n");
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  return size;\n"
+    "}\n");
+}
+
+void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
+  scoped_array<const FieldDescriptor*> sorted_fields(
+    SortFieldsByNumber(descriptor_));
+
+  printer->Print(
+    "\n"
+    "@Override\n"
+    "public $classname$ mergeFrom(\n"
+    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
+    "    throws java.io.IOException {\n",
+    "classname", descriptor_->name());
+
+  printer->Indent();
+  if (HasMapField(descriptor_)) {
+    printer->Print(
+      "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
+      "  com.google.protobuf.nano.MapFactories.getMapFactory();\n");
+  }
+
+  printer->Print(
+    "while (true) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "int tag = input.readTag();\n"
+    "switch (tag) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "case 0:\n"          // zero signals EOF / limit reached
+    "  return this;\n"
+    "default: {\n");
+
+  printer->Indent();
+  if (params_.store_unknown_fields()) {
+    printer->Print(
+        "if (!storeUnknownField(input, tag)) {\n"
+        "  return this;\n"
+        "}\n");
+  } else {
+    printer->Print(
+        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
+        "  return this;\n"   // it's an endgroup tag
+        "}\n");
+  }
+  printer->Print("break;\n");
+  printer->Outdent();
+  printer->Print("}\n");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
+      WireFormat::WireTypeForFieldType(field->type()));
+
+    printer->Print(
+      "case $tag$: {\n",
+      "tag", SimpleItoa(tag));
+    printer->Indent();
+
+    field_generators_.get(field).GenerateMergingCode(printer);
+
+    printer->Outdent();
+    printer->Print(
+      "  break;\n"
+      "}\n");
+
+    if (field->is_packable()) {
+      // To make packed = true wire compatible, we generate parsing code from a
+      // packed version of this field regardless of field->options().packed().
+      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+      printer->Print(
+        "case $tag$: {\n",
+        "tag", SimpleItoa(packed_tag));
+      printer->Indent();
+
+      field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
+
+      printer->Outdent();
+      printer->Print(
+        "  break;\n"
+        "}\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+    "    }\n"     // switch (tag)
+    "  }\n"       // while (true)
+    "}\n");
+}
+
+void MessageGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+  // Note:  These are separate from GenerateMessageSerializationMethods()
+  //   because they need to be generated even for messages that are optimized
+  //   for code size.
+  printer->Print(
+    "\n"
+    "public static $classname$ parseFrom(byte[] data)\n"
+    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
+    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ parseFrom(\n"
+    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
+    "    throws java.io.IOException {\n"
+    "  return new $classname$().mergeFrom(input);\n"
+    "}\n",
+    "classname", descriptor_->name());
+}
+
+void MessageGenerator::GenerateSerializeOneField(
+    io::Printer* printer, const FieldDescriptor* field) {
+  field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void MessageGenerator::GenerateClear(io::Printer* printer) {
+  if (!params_.generate_clear()) {
+    return;
+  }
+  printer->Print(
+    "\n"
+    "public $classname$ clear() {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+
+  GenerateFieldInitializers(printer);
+
+  printer->Outdent();
+  printer->Print(
+    "  return this;\n"
+    "}\n");
+}
+
+void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
+  // Clear bit fields.
+  int totalInts = (field_generators_.total_bits() + 31) / 32;
+  for (int i = 0; i < totalInts; i++) {
+    printer->Print("$bit_field_name$ = 0;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
+  // Call clear for all of the fields.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    field_generators_.get(field).GenerateClearCode(printer);
+  }
+
+  // Clear oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "clear$oneof_capitalized_name$();\n",
+      "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
+          descriptor_->oneof_decl(i)));
+  }
+
+  // Clear unknown fields.
+  if (params_.store_unknown_fields()) {
+    printer->Print("unknownFieldData = null;\n");
+  }
+  printer->Print("cachedSize = -1;\n");
+}
+
+void MessageGenerator::GenerateClone(io::Printer* printer) {
+  printer->Print(
+    "@Override\n"
+    "public $classname$ clone() {\n",
+    "classname", descriptor_->name());
+  printer->Indent();
+
+  printer->Print(
+    "$classname$ cloned;\n"
+    "try {\n"
+    "  cloned = ($classname$) super.clone();\n"
+    "} catch (java.lang.CloneNotSupportedException e) {\n"
+    "  throw new java.lang.AssertionError(e);\n"
+    "}\n",
+    "classname", descriptor_->name());
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "  return cloned;\n"
+    "}\n"
+    "\n");
+}
+
+void MessageGenerator::GenerateEquals(io::Printer* printer) {
+  // Don't override if there are no fields. We could generate an
+  // equals method that compares types, but often empty messages
+  // are used as namespaces.
+  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
+    return;
+  }
+
+  printer->Print(
+    "\n"
+    "@Override\n"
+    "public boolean equals(Object o) {\n");
+  printer->Indent();
+  printer->Print(
+    "if (o == this) {\n"
+    "  return true;\n"
+    "}\n"
+    "if (!(o instanceof $classname$)) {\n"
+    "  return false;\n"
+    "}\n"
+    "$classname$ other = ($classname$) o;\n",
+    "classname", descriptor_->name());
+
+  // Checking oneof case before checking each oneof field.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+    printer->Print(
+      "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
+      "  return false;\n"
+      "}\n",
+      "oneof_name", UnderscoresToCamelCase(oneof_desc));
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    field_generators_.get(field).GenerateEqualsCode(printer);
+  }
+
+  if (params_.store_unknown_fields()) {
+    printer->Print(
+      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
+      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
+      "} else {\n"
+      "  return unknownFieldData.equals(other.unknownFieldData);\n"
+      "}");
+  } else {
+    printer->Print(
+      "return true;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void MessageGenerator::GenerateHashCode(io::Printer* printer) {
+  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
+    return;
+  }
+
+  printer->Print(
+    "\n"
+    "@Override\n"
+    "public int hashCode() {\n");
+  printer->Indent();
+
+  printer->Print("int result = 17;\n");
+  printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    field_generators_.get(field).GenerateHashCodeCode(printer);
+  }
+
+  if (params_.store_unknown_fields()) {
+    printer->Print(
+      "result = 31 * result + \n"
+      "  (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
+      "  unknownFieldData.hashCode());\n");
+  }
+
+  printer->Print("return result;\n");
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.h
new file mode 100644
index 0000000..281ec64
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message.h
@@ -0,0 +1,97 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
+
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MessageGenerator {
+ public:
+  explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
+  ~MessageGenerator();
+
+  // All static variables have to be declared at the top-level of the file
+  // so that we can control initialization order, which is important for
+  // DescriptorProto bootstrapping to work.
+  void GenerateStaticVariables(io::Printer* printer);
+
+  // Output code which initializes the static variables generated by
+  // GenerateStaticVariables().
+  void GenerateStaticVariableInitializers(io::Printer* printer);
+
+  // Generate the class itself.
+  void Generate(io::Printer* printer);
+
+ private:
+  void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateMergeFromMethods(io::Printer* printer);
+  void GenerateParseFromMethods(io::Printer* printer);
+  void GenerateSerializeOneField(io::Printer* printer,
+                                 const FieldDescriptor* field);
+
+  void GenerateClear(io::Printer* printer);
+  void GenerateFieldInitializers(io::Printer* printer);
+  void GenerateEquals(io::Printer* printer);
+  void GenerateHashCode(io::Printer* printer);
+  void GenerateClone(io::Printer* printer);
+
+  const Params& params_;
+  const Descriptor* descriptor_;
+  FieldGeneratorMap field_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.cc
new file mode 100644
index 0000000..d1d04b5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -0,0 +1,363 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_message_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
+//   repeat code between this and the other field types.
+void SetMessageVariables(const Params& params,
+    const FieldDescriptor* descriptor, map<string, string>* variables) {
+  (*variables)["name"] =
+    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  (*variables)["capitalized_name"] =
+    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["type"] = ClassName(params, descriptor->message_type());
+  (*variables)["group_or_message"] =
+    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
+    "Group" : "Message";
+  (*variables)["message_name"] = descriptor->containing_type()->name();
+  //(*variables)["message_type"] = descriptor->message_type()->name();
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+}
+
+}  // namespace
+
+// ===================================================================
+
+MessageFieldGenerator::
+MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetMessageVariables(params, descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public $type$ $name$;\n");
+}
+
+void MessageFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = null;\n");
+}
+
+void MessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ == null) {\n"
+    "  this.$name$ = new $type$();\n"
+    "}\n");
+
+  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "input.readGroup(this.$name$, $number$);\n");
+  } else {
+    printer->Print(variables_,
+      "input.readMessage(this.$name$);\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  output.write$group_or_message$($number$, this.$name$);\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "    .compute$group_or_message$Size($number$, this.$name$);\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null) {\n"
+    "  cloned.$name$ = this.$name$.clone();\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ == null) { \n"
+    "  if (other.$name$ != null) {\n"
+    "    return false;\n"
+    "  }\n"
+    "} else {\n"
+    "  if (!this.$name$.equals(other.$name$)) {\n"
+    "    return false;\n"
+    "  }\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result +\n"
+    "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
+}
+// ===================================================================
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
+    SetMessageVariables(params, descriptor, &variables_);
+    SetCommonOneofVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case$;\n"
+    "}\n"
+    "public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case$) {\n"
+    "    return ($type$) this.$oneof_name$_;\n"
+    "  }\n"
+    "  return null;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$($type$ value) {\n"
+    "  if (value == null) { throw new java.lang.NullPointerException(); }\n"
+    "  $set_oneof_case$;\n"
+    "  this.$oneof_name$_ = value;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  // No clear method for oneof fields.
+}
+
+void MessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!($has_oneof_case$)) {\n"
+    "  this.$oneof_name$_ = new $type$();\n"
+    "}\n"
+    "input.readMessage(\n"
+    "    (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "$set_oneof_case$;\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  output.writeMessage($number$,\n"
+    "      (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "    .computeMessageSize($number$,\n"
+    "        (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$oneof_name$ != null) {\n"
+    "  cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
+    "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
+
+// ===================================================================
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+    : FieldGenerator(params), descriptor_(descriptor) {
+  SetMessageVariables(params, descriptor, &variables_);
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+  printer->Print(variables_,
+    "public $type$[] $name$;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = $type$.emptyArray();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // First, figure out the length of the array, then parse.
+  printer->Print(variables_,
+    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
+    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
+    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+    "$type$[] newArray =\n"
+    "    new $type$[i + arrayLength];\n"
+    "if (i != 0) {\n"
+    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+    "}\n"
+    "for (; i < newArray.length - 1; i++) {\n"
+    "  newArray[i] = new $type$();\n");
+
+  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "  input.readGroup(newArray[i], $number$);\n");
+  } else {
+    printer->Print(variables_,
+      "  input.readMessage(newArray[i]);\n");
+  }
+
+  printer->Print(variables_,
+    "  input.readTag();\n"
+    "}\n"
+    "// Last one without readTag.\n"
+    "newArray[i] = new $type$();\n");
+
+  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+    printer->Print(variables_,
+      "input.readGroup(newArray[i], $number$);\n");
+  } else {
+    printer->Print(variables_,
+      "input.readMessage(newArray[i]);\n");
+  }
+
+  printer->Print(variables_,
+    "this.$name$ = newArray;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n"
+    "  for (int i = 0; i < this.$name$.length; i++) {\n"
+    "    $type$ element = this.$name$[i];\n"
+    "    if (element != null) {\n"
+    "      output.write$group_or_message$($number$, element);\n"
+    "    }\n"
+    "  }\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n"
+    "  for (int i = 0; i < this.$name$.length; i++) {\n"
+    "    $type$ element = this.$name$[i];\n"
+    "    if (element != null) {\n"
+    "      size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "        .compute$group_or_message$Size($number$, element);\n"
+    "    }\n"
+    "  }\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n"
+    "  cloned.$name$ = new $type$[this.$name$.length];\n"
+    "  for (int i = 0; i < this.$name$.length; i++) {\n"
+    "    if (this.$name$[i] != null) {\n"
+    "      cloned.$name$[i] = this.$name$[i].clone();\n"
+    "    }\n"
+    "  }\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+    "    this.$name$, other.$name$)) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result\n"
+    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.h
new file mode 100644
index 0000000..e074735
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MessageFieldGenerator : public FieldGenerator {
+ public:
+  explicit MessageFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~MessageFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+  void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class MessageOneofFieldGenerator : public FieldGenerator {
+ public:
+  explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                                      const Params& params);
+  ~MessageOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+  void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public FieldGenerator {
+ public:
+  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+        const Params& params);
+  ~RepeatedMessageFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+  void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_params.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_params.h
new file mode 100644
index 0000000..e3b4bb9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -0,0 +1,258 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: wink@google.com (Wink Saville)
+
+#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
+#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
+
+#include <map>
+#include <set>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE };
+
+// Parameters for used by the generators
+class Params {
+ public:
+  typedef map<string, string> NameMap;
+  typedef set<string> NameSet;
+ private:
+  string empty_;
+  string base_name_;
+  eMultipleFiles override_java_multiple_files_;
+  bool store_unknown_fields_;
+  NameMap java_packages_;
+  NameMap java_outer_classnames_;
+  NameSet java_multiple_files_;
+  bool generate_has_;
+  bool java_enum_style_;
+  bool optional_field_accessors_;
+  bool use_reference_types_for_primitives_;
+  bool generate_equals_;
+  bool ignore_services_;
+  bool parcelable_messages_;
+  bool reftypes_primitive_enums_;
+  bool generate_clear_;
+  bool generate_clone_;
+  bool generate_intdefs_;
+
+ public:
+  Params(const string & base_name) :
+    empty_(""),
+    base_name_(base_name),
+    override_java_multiple_files_(JAVANANO_MUL_UNSET),
+    store_unknown_fields_(false),
+    generate_has_(false),
+    java_enum_style_(false),
+    optional_field_accessors_(false),
+    use_reference_types_for_primitives_(false),
+    generate_equals_(false),
+    ignore_services_(false),
+    parcelable_messages_(false),
+    reftypes_primitive_enums_(false),
+    generate_clear_(true),
+    generate_clone_(false),
+    generate_intdefs_(false) {
+  }
+
+  const string& base_name() const {
+    return base_name_;
+  }
+
+  bool has_java_package(const string& file_name) const {
+    return java_packages_.find(file_name)
+                        != java_packages_.end();
+  }
+  void set_java_package(const string& file_name,
+      const string& java_package) {
+    java_packages_[file_name] = java_package;
+  }
+  const string& java_package(const string& file_name) const {
+    NameMap::const_iterator itr;
+
+    itr = java_packages_.find(file_name);
+    if  (itr == java_packages_.end()) {
+      return empty_;
+    } else {
+      return itr->second;
+    }
+  }
+  const NameMap& java_packages() {
+    return java_packages_;
+  }
+
+  bool has_java_outer_classname(const string& file_name) const {
+    return java_outer_classnames_.find(file_name)
+                        != java_outer_classnames_.end();
+  }
+  void set_java_outer_classname(const string& file_name,
+      const string& java_outer_classname) {
+    java_outer_classnames_[file_name] = java_outer_classname;
+  }
+  const string& java_outer_classname(const string& file_name) const {
+    NameMap::const_iterator itr;
+
+    itr = java_outer_classnames_.find(file_name);
+    if  (itr == java_outer_classnames_.end()) {
+      return empty_;
+    } else {
+      return itr->second;
+    }
+  }
+  const NameMap& java_outer_classnames() {
+    return java_outer_classnames_;
+  }
+
+  void set_override_java_multiple_files(bool java_multiple_files) {
+    if (java_multiple_files) {
+      override_java_multiple_files_ = JAVANANO_MUL_TRUE;
+    } else {
+      override_java_multiple_files_ = JAVANANO_MUL_FALSE;
+    }
+  }
+  void clear_override_java_multiple_files() {
+    override_java_multiple_files_ = JAVANANO_MUL_UNSET;
+  }
+
+  void set_java_multiple_files(const string& file_name, bool value) {
+    if (value) {
+      java_multiple_files_.insert(file_name);
+    } else {
+      java_multiple_files_.erase(file_name);
+    }
+  }
+  bool java_multiple_files(const string& file_name) const {
+    switch (override_java_multiple_files_) {
+      case JAVANANO_MUL_FALSE:
+        return false;
+      case JAVANANO_MUL_TRUE:
+        return true;
+      default:
+        return java_multiple_files_.find(file_name)
+                != java_multiple_files_.end();
+    }
+  }
+
+  void set_store_unknown_fields(bool value) {
+    store_unknown_fields_ = value;
+  }
+  bool store_unknown_fields() const {
+    return store_unknown_fields_;
+  }
+
+  void set_generate_has(bool value) {
+    generate_has_ = value;
+  }
+  bool generate_has() const {
+    return generate_has_;
+  }
+
+  void set_java_enum_style(bool value) {
+    java_enum_style_ = value;
+  }
+  bool java_enum_style() const {
+    return java_enum_style_;
+  }
+
+  void set_optional_field_accessors(bool value) {
+    optional_field_accessors_ = value;
+  }
+  bool optional_field_accessors() const {
+    return optional_field_accessors_;
+  }
+
+  void set_use_reference_types_for_primitives(bool value) {
+    use_reference_types_for_primitives_ = value;
+  }
+  bool use_reference_types_for_primitives() const {
+    return use_reference_types_for_primitives_;
+  }
+
+  void set_generate_equals(bool value) {
+    generate_equals_ = value;
+  }
+  bool generate_equals() const {
+    return generate_equals_;
+  }
+
+  void set_ignore_services(bool value) {
+    ignore_services_ = value;
+  }
+  bool ignore_services() const {
+    return ignore_services_;
+  }
+
+  void set_parcelable_messages(bool value) {
+    parcelable_messages_ = value;
+  }
+  bool parcelable_messages() const {
+    return parcelable_messages_;
+  }
+
+  void set_reftypes_primitive_enums(bool value) {
+    reftypes_primitive_enums_ = value;
+  }
+  bool reftypes_primitive_enums() const {
+    return reftypes_primitive_enums_;
+  }
+
+  void set_generate_clear(bool value) {
+    generate_clear_ = value;
+  }
+  bool generate_clear() const {
+    return generate_clear_;
+  }
+
+  void set_generate_clone(bool value) {
+    generate_clone_ = value;
+  }
+  bool generate_clone() const {
+    return generate_clone_;
+  }
+
+  void set_generate_intdefs(bool value) {
+    generate_intdefs_ = value;
+  }
+  bool generate_intdefs() const {
+    return generate_intdefs_;
+  }
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
new file mode 100644
index 0000000..978abf2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -0,0 +1,968 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <math.h>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+bool IsReferenceType(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return false;
+    case JAVATYPE_LONG   : return false;
+    case JAVATYPE_FLOAT  : return false;
+    case JAVATYPE_DOUBLE : return false;
+    case JAVATYPE_BOOLEAN: return false;
+    case JAVATYPE_STRING : return true;
+    case JAVATYPE_BYTES  : return true;
+    case JAVATYPE_ENUM   : return false;
+    case JAVATYPE_MESSAGE: return true;
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+bool IsArrayType(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT    : return false;
+    case JAVATYPE_LONG   : return false;
+    case JAVATYPE_FLOAT  : return false;
+    case JAVATYPE_DOUBLE : return false;
+    case JAVATYPE_BOOLEAN: return false;
+    case JAVATYPE_STRING : return false;
+    case JAVATYPE_BYTES  : return true;
+    case JAVATYPE_ENUM   : return false;
+    case JAVATYPE_MESSAGE: return false;
+
+    // No default because we want the compiler to complain if any new
+    // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+const char* GetCapitalizedType(const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32   : return "Int32"   ;
+    case FieldDescriptor::TYPE_UINT32  : return "UInt32"  ;
+    case FieldDescriptor::TYPE_SINT32  : return "SInt32"  ;
+    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
+    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
+    case FieldDescriptor::TYPE_INT64   : return "Int64"   ;
+    case FieldDescriptor::TYPE_UINT64  : return "UInt64"  ;
+    case FieldDescriptor::TYPE_SINT64  : return "SInt64"  ;
+    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
+    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT   : return "Float"   ;
+    case FieldDescriptor::TYPE_DOUBLE  : return "Double"  ;
+    case FieldDescriptor::TYPE_BOOL    : return "Bool"    ;
+    case FieldDescriptor::TYPE_STRING  : return "String"  ;
+    case FieldDescriptor::TYPE_BYTES   : return "Bytes"   ;
+    case FieldDescriptor::TYPE_ENUM    : return "Enum"    ;
+    case FieldDescriptor::TYPE_GROUP   : return "Group"   ;
+    case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+// For encodings with fixed sizes, returns that size in bytes.  Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32   : return -1;
+    case FieldDescriptor::TYPE_INT64   : return -1;
+    case FieldDescriptor::TYPE_UINT32  : return -1;
+    case FieldDescriptor::TYPE_UINT64  : return -1;
+    case FieldDescriptor::TYPE_SINT32  : return -1;
+    case FieldDescriptor::TYPE_SINT64  : return -1;
+    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
+    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
+
+    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
+    case FieldDescriptor::TYPE_ENUM    : return -1;
+
+    case FieldDescriptor::TYPE_STRING  : return -1;
+    case FieldDescriptor::TYPE_BYTES   : return -1;
+    case FieldDescriptor::TYPE_GROUP   : return -1;
+    case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;
+}
+
+bool AllAscii(const string& text) {
+  for (int i = 0; i < text.size(); i++) {
+    if ((text[i] & 0x80) != 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
+                           map<string, string>* variables) {
+  (*variables)["name"] =
+    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+  (*variables)["capitalized_name"] =
+    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  if (params.use_reference_types_for_primitives()
+      && !descriptor->is_repeated()) {
+    (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  } else {
+    (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+  }
+  // Deals with defaults. For C++-string types (string and bytes),
+  // we might need to have the generated code do the unicode decoding
+  // (see comments in InternalNano.java for gory details.). We would
+  // like to do this once into a static field and re-use that from
+  // then on.
+  if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+      !descriptor->default_value_string().empty() &&
+      !params.use_reference_types_for_primitives()) {
+    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+      (*variables)["default"] = DefaultValue(params, descriptor);
+      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
+      (*variables)["default_constant_value"] = strings::Substitute(
+          "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
+          CEscape(descriptor->default_value_string()));
+      (*variables)["default_copy_if_needed"] =
+          (*variables)["default"] + ".clone()";
+    } else if (AllAscii(descriptor->default_value_string())) {
+      // All chars are ASCII.  In this case directly referencing a
+      // CEscape()'d string literal works fine.
+      (*variables)["default"] =
+          "\"" + CEscape(descriptor->default_value_string()) + "\"";
+      (*variables)["default_copy_if_needed"] = (*variables)["default"];
+    } else {
+      // Strings where some chars are non-ASCII. We need to save the
+      // default value.
+      (*variables)["default"] = DefaultValue(params, descriptor);
+      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
+      (*variables)["default_constant_value"] = strings::Substitute(
+          "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
+          CEscape(descriptor->default_value_string()));
+      (*variables)["default_copy_if_needed"] = (*variables)["default"];
+    }
+  } else {
+    // Non-string, non-bytes field. Defaults are literals.
+    (*variables)["default"] = DefaultValue(params, descriptor);
+    (*variables)["default_copy_if_needed"] = (*variables)["default"];
+  }
+  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), descriptor->type()));
+  (*variables)["non_packed_tag"] = SimpleItoa(
+      internal::WireFormatLite::MakeTag(descriptor->number(),
+          internal::WireFormat::WireTypeForFieldType(descriptor->type())));
+  int fixed_size = FixedSize(descriptor->type());
+  if (fixed_size != -1) {
+    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+  }
+  (*variables)["message_name"] = descriptor->containing_type()->name();
+  (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
+}
+}  // namespace
+
+// ===================================================================
+
+PrimitiveFieldGenerator::
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
+  return variables_.find("default_constant") != variables_.end();
+}
+
+void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
+  if (variables_.find("default_constant") != variables_.end()) {
+    printer->Print(variables_,
+      "$default_constant$ = $default_constant_value$;\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool lazy_init) const {
+  if (variables_.find("default_constant") != variables_.end()) {
+    // Those primitive types that need a saved default.
+    if (lazy_init) {
+      printer->Print(variables_,
+        "private static $type$ $default_constant$;\n");
+    } else {
+      printer->Print(variables_,
+        "private static final $type$ $default_constant$ =\n"
+        "    $default_constant_value$;\n");
+    }
+  }
+
+  printer->Print(variables_,
+    "public $type$ $name$;\n");
+
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "public boolean has$capitalized_name$;\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = $default_copy_if_needed$;\n");
+
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "has$capitalized_name$ = false;\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "this.$name$ = input.read$capitalized_type$();\n");
+
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "has$capitalized_name$ = true;\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationConditional(io::Printer* printer) const {
+  if (params_.use_reference_types_for_primitives()) {
+    // For reference type mode, serialize based on equality
+    // to null.
+    printer->Print(variables_,
+      "if (this.$name$ != null) {\n");
+    return;
+  }
+  if (params_.generate_has()) {
+    printer->Print(variables_,
+      "if (has$capitalized_name$ || ");
+  } else {
+    printer->Print(variables_,
+      "if (");
+  }
+  JavaType java_type = GetJavaType(descriptor_);
+  if (IsArrayType(java_type)) {
+    printer->Print(variables_,
+      "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
+  } else if (IsReferenceType(java_type)) {
+    printer->Print(variables_,
+      "!this.$name$.equals($default$)) {\n");
+  } else if (java_type == JAVATYPE_FLOAT) {
+    printer->Print(variables_,
+      "java.lang.Float.floatToIntBits(this.$name$)\n"
+      "    != java.lang.Float.floatToIntBits($default$)) {\n");
+  } else if (java_type == JAVATYPE_DOUBLE) {
+    printer->Print(variables_,
+      "java.lang.Double.doubleToLongBits(this.$name$)\n"
+      "    != java.lang.Double.doubleToLongBits($default$)) {\n");
+  } else {
+    printer->Print(variables_,
+      "this.$name$ != $default$) {\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->is_required() && !params_.generate_has()) {
+    // Always serialize a required field if we don't have the 'has' signal.
+    printer->Print(variables_,
+      "output.write$capitalized_type$($number$, this.$name$);\n");
+  } else {
+    GenerateSerializationConditional(printer);
+    printer->Print(variables_,
+      "  output.write$capitalized_type$($number$, this.$name$);\n"
+      "}\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  if (descriptor_->is_required() && !params_.generate_has()) {
+    printer->Print(variables_,
+      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "    .compute$capitalized_type$Size($number$, this.$name$);\n");
+  } else {
+    GenerateSerializationConditional(printer);
+    printer->Print(variables_,
+      "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "      .compute$capitalized_type$Size($number$, this.$name$);\n"
+      "}\n");
+  }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n"
+    "  cloned.$name$ = this.$name$.clone();\n"
+    "}\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  // We define equality as serialized form equality. If generate_has(),
+  // then if the field value equals the default value in both messages,
+  // but one's 'has' field is set and the other's is not, the serialized
+  // forms are different and we should return false.
+  JavaType java_type = GetJavaType(descriptor_);
+  if (java_type == JAVATYPE_BYTES) {
+    printer->Print(variables_,
+      "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "    || (java.util.Arrays.equals(this.$name$, $default$)\n"
+        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "  return false;\n"
+      "}\n");
+  } else if (java_type == JAVATYPE_STRING
+      || params_.use_reference_types_for_primitives()) {
+    printer->Print(variables_,
+      "if (this.$name$ == null) {\n"
+      "  if (other.$name$ != null) {\n"
+      "    return false;\n"
+      "  }\n"
+      "} else if (!this.$name$.equals(other.$name$)");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "    || (this.$name$.equals($default$)\n"
+        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "  return false;\n"
+      "}\n");
+  } else if (java_type == JAVATYPE_FLOAT) {
+    printer->Print(variables_,
+      "{\n"
+      "  int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
+      "  if (bits != java.lang.Float.floatToIntBits(other.$name$)");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "      || (bits == java.lang.Float.floatToIntBits($default$)\n"
+        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  } else if (java_type == JAVATYPE_DOUBLE) {
+    printer->Print(variables_,
+      "{\n"
+      "  long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
+      "  if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "      || (bits == java.lang.Double.doubleToLongBits($default$)\n"
+        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "    return false;\n"
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "if (this.$name$ != other.$name$");
+    if (params_.generate_has()) {
+      printer->Print(variables_,
+        "\n"
+        "    || (this.$name$ == $default$\n"
+        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
+    }
+    printer->Print(") {\n"
+      "  return false;\n"
+      "}\n");
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  JavaType java_type = GetJavaType(descriptor_);
+  if (java_type == JAVATYPE_BYTES) {
+    printer->Print(variables_,
+      "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
+  } else if (java_type == JAVATYPE_STRING
+      || params_.use_reference_types_for_primitives()) {
+    printer->Print(variables_,
+      "result = 31 * result\n"
+      "    + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
+  } else {
+    switch (java_type) {
+      // For all Java primitive types below, the hash codes match the
+      // results of BoxedType.valueOf(primitiveValue).hashCode().
+      case JAVATYPE_INT:
+        printer->Print(variables_,
+          "result = 31 * result + this.$name$;\n");
+        break;
+      case JAVATYPE_LONG:
+        printer->Print(variables_,
+          "result = 31 * result\n"
+          "    + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
+        break;
+      case JAVATYPE_FLOAT:
+        printer->Print(variables_,
+          "result = 31 * result\n"
+          "    + java.lang.Float.floatToIntBits(this.$name$);\n");
+        break;
+      case JAVATYPE_DOUBLE:
+        printer->Print(variables_,
+          "{\n"
+          "  long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
+          "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
+          "}\n");
+        break;
+      case JAVATYPE_BOOLEAN:
+        printer->Print(variables_,
+          "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
+        break;
+      default:
+        GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+        break;
+    }
+  }
+}
+
+// ===================================================================
+
+AccessorPrimitiveFieldGenerator::
+AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+     const Params& params, int has_bit_index)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetPrimitiveVariables(descriptor, params, &variables_);
+  SetBitOperationVariables("has", has_bit_index, &variables_);
+}
+
+AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
+
+bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
+  return variables_.find("default_constant") != variables_.end();
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateInitSavedDefaultCode(io::Printer* printer) const {
+  if (variables_.find("default_constant") != variables_.end()) {
+    printer->Print(variables_,
+      "$default_constant$ = $default_constant_value$;\n");
+  }
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool lazy_init) const {
+  if (variables_.find("default_constant") != variables_.end()) {
+    // Those primitive types that need a saved default.
+    if (lazy_init) {
+      printer->Print(variables_,
+        "private static $type$ $default_constant$;\n");
+    } else {
+      printer->Print(variables_,
+        "private static final $type$ $default_constant$ =\n"
+        "    $default_constant_value$;\n");
+    }
+  }
+  printer->Print(variables_,
+    "private $type$ $name$_;\n"
+    "public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$($type$ value) {\n");
+  if (IsReferenceType(GetJavaType(descriptor_))) {
+    printer->Print(variables_,
+      "  if (value == null) {\n"
+      "    throw new java.lang.NullPointerException();\n"
+      "  }\n");
+  }
+  printer->Print(variables_,
+    "  $name$_ = value;\n"
+    "  $set_has$;\n"
+    "  return this;\n"
+    "}\n"
+    "public boolean has$capitalized_name$() {\n"
+    "  return $get_has$;\n"
+    "}\n"
+    "public $message_name$ clear$capitalized_name$() {\n"
+    "  $name$_ = $default_copy_if_needed$;\n"
+    "  $clear_has$;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default_copy_if_needed$;\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = input.read$capitalized_type$();\n"
+    "$set_has$;\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has$) {\n"
+    "  output.write$capitalized_type$($number$, $name$_);\n"
+    "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "      .compute$capitalized_type$Size($number$, $name$_);\n"
+    "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    // For all Java primitive types below, the equality checks match the
+    // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "if ($different_has$\n"
+        "    || java.lang.Float.floatToIntBits($name$_)\n"
+        "        != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
+        "  return false;\n"
+        "}\n");
+      break;
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "if ($different_has$\n"
+        "    || java.lang.Double.doubleToLongBits($name$_)\n"
+        "        != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
+        "  return false;\n"
+        "}\n");
+      break;
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "if ($different_has$\n"
+        "    || $name$_ != other.$name$_) {\n"
+        "  return false;\n"
+        "}\n");
+      break;
+    case JAVATYPE_STRING:
+      // Accessor style would guarantee $name$_ non-null
+      printer->Print(variables_,
+        "if ($different_has$\n"
+        "    || !$name$_.equals(other.$name$_)) {\n"
+        "  return false;\n"
+        "}\n");
+      break;
+    case JAVATYPE_BYTES:
+      // Accessor style would guarantee $name$_ non-null
+      printer->Print(variables_,
+        "if ($different_has$\n"
+        "    || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
+        "  return false;\n"
+        "}\n");
+      break;
+    default:
+      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+      break;
+  }
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    // For all Java primitive types below, the hash codes match the
+    // results of BoxedType.valueOf(primitiveValue).hashCode().
+    case JAVATYPE_INT:
+      printer->Print(variables_,
+        "result = 31 * result + $name$_;\n");
+      break;
+    case JAVATYPE_LONG:
+      printer->Print(variables_,
+        "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
+      break;
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "result = 31 * result +\n"
+        "    java.lang.Float.floatToIntBits($name$_);\n");
+      break;
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "{\n"
+        "  long v = java.lang.Double.doubleToLongBits($name$_);\n"
+        "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
+        "}\n");
+      break;
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
+      break;
+    case JAVATYPE_STRING:
+      // Accessor style would guarantee $name$_ non-null
+      printer->Print(variables_,
+        "result = 31 * result + $name$_.hashCode();\n");
+      break;
+    case JAVATYPE_BYTES:
+      // Accessor style would guarantee $name$_ non-null
+      printer->Print(variables_,
+        "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
+      break;
+    default:
+      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+      break;
+  }
+}
+
+// ===================================================================
+
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+    SetPrimitiveVariables(descriptor, params, &variables_);
+    SetCommonOneofVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(
+    io::Printer* printer, bool /*unused lazy_init*/) const {
+  printer->Print(variables_,
+    "public boolean has$capitalized_name$() {\n"
+    "  return $has_oneof_case$;\n"
+    "}\n"
+    "public $type$ get$capitalized_name$() {\n"
+    "  if ($has_oneof_case$) {\n"
+    "    return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
+    "  }\n"
+    "  return $default$;\n"
+    "}\n"
+    "public $message_name$ set$capitalized_name$($type$ value) {\n"
+    "  $set_oneof_case$;\n"
+    "  this.$oneof_name$_ = value;\n"
+    "  return this;\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateClearCode(
+    io::Printer* printer) const {
+  // No clear method for oneof fields.
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "this.$oneof_name$_ = input.read$capitalized_type$();\n"
+    "$set_oneof_case$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  output.write$capitalized_type$(\n"
+    "      $number$, ($boxed_type$) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($has_oneof_case$) {\n"
+    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+    "      .compute$capitalized_type$Size(\n"
+    "          $number$, ($boxed_type$) this.$oneof_name$_);\n"
+    "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
+    io::Printer* printer) const {
+  GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
+    io::Printer* printer) const {
+  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Params& params)
+  : FieldGenerator(params), descriptor_(descriptor) {
+  SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
+  printer->Print(variables_,
+    "public $type$[] $name$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$ = $default$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // First, figure out the length of the array, then parse.
+  printer->Print(variables_,
+    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
+    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
+    "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
+
+  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+    printer->Print(variables_,
+      "byte[][] newArray = new byte[i + arrayLength][];\n");
+  } else {
+    printer->Print(variables_,
+      "$type$[] newArray = new $type$[i + arrayLength];\n");
+  }
+  printer->Print(variables_,
+    "if (i != 0) {\n"
+    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+    "}\n"
+    "for (; i < newArray.length - 1; i++) {\n"
+    "  newArray[i] = input.read$capitalized_type$();\n"
+    "  input.readTag();\n"
+    "}\n"
+    "// Last one without readTag.\n"
+    "newArray[i] = input.read$capitalized_type$();\n"
+    "this.$name$ = newArray;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(
+    "int length = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(length);\n");
+
+  // If we know the elements will all be of the same size, the arrayLength
+  // can be calculated much more easily. However, FixedSize() returns 1 for
+  // repeated bool fields, which are guaranteed to have the fixed size of
+  // 1 byte per value only if we control the output. On the wire they can
+  // legally appear as variable-size integers, so we need to use the slow
+  // way for repeated bool fields.
+  if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
+      || FixedSize(descriptor_->type()) == -1) {
+    printer->Print(variables_,
+      "// First pass to compute array length.\n"
+      "int arrayLength = 0;\n"
+      "int startPos = input.getPosition();\n"
+      "while (input.getBytesUntilLimit() > 0) {\n"
+      "  input.read$capitalized_type$();\n"
+      "  arrayLength++;\n"
+      "}\n"
+      "input.rewindToPosition(startPos);\n");
+  } else {
+    printer->Print(variables_,
+      "int arrayLength = length / $fixed_size$;\n");
+  }
+
+  printer->Print(variables_,
+    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+    "$type$[] newArray = new $type$[i + arrayLength];\n"
+    "if (i != 0) {\n"
+    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+    "}\n"
+    "for (; i < newArray.length; i++) {\n"
+    "  newArray[i] = input.read$capitalized_type$();\n"
+    "}\n"
+    "this.$name$ = newArray;\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateRepeatedDataSizeCode(io::Printer* printer) const {
+  // Creates a variable dataSize and puts the serialized size in there.
+  // If the element type is a Java reference type, also generates
+  // dataCount which stores the number of non-null elements in the field.
+  if (IsReferenceType(GetJavaType(descriptor_))) {
+    printer->Print(variables_,
+      "int dataCount = 0;\n"
+      "int dataSize = 0;\n"
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  $type$ element = this.$name$[i];\n"
+      "  if (element != null) {\n"
+      "    dataCount++;\n"
+      "    dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "        .compute$capitalized_type$SizeNoTag(element);\n"
+      "  }\n"
+      "}\n");
+  } else if (FixedSize(descriptor_->type()) == -1) {
+    printer->Print(variables_,
+      "int dataSize = 0;\n"
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  $type$ element = this.$name$[i];\n"
+      "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "      .compute$capitalized_type$SizeNoTag(element);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "int dataSize = $fixed_size$ * this.$name$.length;\n");
+  }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n");
+  printer->Indent();
+
+  if (descriptor_->is_packable() && descriptor_->options().packed()) {
+    GenerateRepeatedDataSizeCode(printer);
+    printer->Print(variables_,
+      "output.writeRawVarint32($tag$);\n"
+      "output.writeRawVarint32(dataSize);\n"
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  output.write$capitalized_type$NoTag(this.$name$[i]);\n"
+      "}\n");
+  } else if (IsReferenceType(GetJavaType(descriptor_))) {
+    printer->Print(variables_,
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  $type$ element = this.$name$[i];\n"
+      "  if (element != null) {\n"
+      "    output.write$capitalized_type$($number$, element);\n"
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < this.$name$.length; i++) {\n"
+      "  output.write$capitalized_type$($number$, this.$name$[i]);\n"
+      "}\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (this.$name$ != null && this.$name$.length > 0) {\n");
+  printer->Indent();
+
+  GenerateRepeatedDataSizeCode(printer);
+
+  printer->Print(
+    "size += dataSize;\n");
+  if (descriptor_->is_packable() && descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "size += $tag_size$;\n"
+      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+      "    .computeRawVarint32Size(dataSize);\n");
+  } else if (IsReferenceType(GetJavaType(descriptor_))) {
+    printer->Print(variables_,
+      "size += $tag_size$ * dataCount;\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * this.$name$.length;\n");
+  }
+
+  printer->Outdent();
+
+  printer->Print(
+    "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+    "    this.$name$, other.$name$)) {\n"
+    "  return false;\n"
+    "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = 31 * result\n"
+    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
new file mode 100644
index 0000000..a01981d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -0,0 +1,150 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class PrimitiveFieldGenerator : public FieldGenerator {
+ public:
+  explicit PrimitiveFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~PrimitiveFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  bool SavedDefaultNeeded() const;
+  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  void GenerateSerializationConditional(io::Printer* printer) const;
+
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class AccessorPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+  explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+      const Params &params, int has_bit_index);
+  ~AccessorPrimitiveFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  bool SavedDefaultNeeded() const;
+  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
+};
+
+class PrimitiveOneofFieldGenerator : public FieldGenerator {
+ public:
+  explicit PrimitiveOneofFieldGenerator(
+      const FieldDescriptor* descriptor, const Params& params);
+  ~PrimitiveOneofFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Params& params);
+  ~RepeatedPrimitiveFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+  void GenerateClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCodeCode(io::Printer* printer) const;
+  void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+  void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
+
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+}  // namespace javanano
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.cc
new file mode 100755
index 0000000..a66d28e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.cc
@@ -0,0 +1,3053 @@
+// 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.
+
+#include <google/protobuf/compiler/js/js_generator.h>
+
+#include <assert.h>
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace js {
+
+// Sorted list of JavaScript keywords. These cannot be used as names. If they
+// appear, we prefix them with "pb_".
+const char* kKeyword[] = {
+  "abstract",
+  "boolean",
+  "break",
+  "byte",
+  "case",
+  "catch",
+  "char",
+  "class",
+  "const",
+  "continue",
+  "debugger",
+  "default",
+  "delete",
+  "do",
+  "double",
+  "else",
+  "enum",
+  "export",
+  "extends",
+  "false",
+  "final",
+  "finally",
+  "float",
+  "for",
+  "function",
+  "goto",
+  "if",
+  "implements",
+  "import",
+  "in",
+  "instanceof",
+  "int",
+  "interface",
+  "long",
+  "native",
+  "new",
+  "null",
+  "package",
+  "private",
+  "protected",
+  "public",
+  "return",
+  "short",
+  "static",
+  "super",
+  "switch",
+  "synchronized",
+  "this",
+  "throw",
+  "throws",
+  "transient",
+  "try",
+  "typeof",
+  "var",
+  "void",
+  "volatile",
+  "while",
+  "with",
+};
+
+static const int kNumKeyword = sizeof(kKeyword) / sizeof(char*);
+
+namespace {
+
+// The mode of operation for bytes fields. Historically JSPB always carried
+// bytes as JS {string}, containing base64 content by convention. With binary
+// and proto3 serialization the new convention is to represent it as binary
+// data in Uint8Array. See b/26173701 for background on the migration.
+enum BytesMode {
+  BYTES_DEFAULT,  // Default type for getBytesField to return.
+  BYTES_B64,      // Explicitly coerce to base64 string where needed.
+  BYTES_U8,       // Explicitly coerce to Uint8Array where needed.
+};
+
+bool IsReserved(const string& ident) {
+  for (int i = 0; i < kNumKeyword; i++) {
+    if (ident == kKeyword[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
+// suffix stripped.
+// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
+string StripProto(const string& filename) {
+  const char* suffix = HasSuffixString(filename, ".protodevel")
+      ? ".protodevel" : ".proto";
+  return StripSuffixString(filename, suffix);
+}
+
+// Given a filename like foo/bar/baz.proto, returns the correspoding JavaScript
+// file foo/bar/baz.js.
+string GetJSFilename(const string& filename) {
+  return StripProto(filename) + "_pb.js";
+}
+
+// Given a filename like foo/bar/baz.proto, returns the root directory
+// path ../../
+string GetRootPath(const string& filename) {
+  size_t slashes = std::count(filename.begin(), filename.end(), '/');
+  if (slashes == 0) {
+    return "./";
+  }
+  string result = "";
+  for (size_t i = 0; i < slashes; i++) {
+    result += "../";
+  }
+  return result;
+}
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing.
+string ModuleAlias(const string& filename) {
+  // This scheme could technically cause problems if a file includes any 2 of:
+  //   foo/bar_baz.proto
+  //   foo_bar_baz.proto
+  //   foo_bar/baz.proto
+  //
+  // We'll worry about this problem if/when we actually see it.  This name isn't
+  // exposed to users so we can change it later if we need to.
+  string basename = StripProto(filename);
+  StripString(&basename, "-", '$');
+  StripString(&basename, "/", '_');
+  return basename + "_pb";
+}
+
+// Returns the fully normalized JavaScript path for the given
+// file descriptor's package.
+string GetPath(const GeneratorOptions& options,
+               const FileDescriptor* file) {
+  if (!options.namespace_prefix.empty()) {
+    return options.namespace_prefix;
+  } else if (!file->package().empty()) {
+    return "proto." + file->package();
+  } else {
+    return "proto";
+  }
+}
+
+// Forward declare, so that GetPrefix can call this method,
+// which in turn, calls GetPrefix.
+string GetPath(const GeneratorOptions& options,
+               const Descriptor* descriptor);
+
+// Returns the path prefix for a message or enumeration that
+// lives under the given file and containing type.
+string GetPrefix(const GeneratorOptions& options,
+                 const FileDescriptor* file_descriptor,
+                 const Descriptor* containing_type) {
+  string prefix = "";
+
+  if (containing_type == NULL) {
+    prefix = GetPath(options, file_descriptor);
+  } else {
+    prefix = GetPath(options, containing_type);
+  }
+
+  if (!prefix.empty()) {
+    prefix += ".";
+  }
+
+  return prefix;
+}
+
+
+// Returns the fully normalized JavaScript path for the given
+// message descriptor.
+string GetPath(const GeneratorOptions& options,
+               const Descriptor* descriptor) {
+  return GetPrefix(
+      options, descriptor->file(),
+      descriptor->containing_type()) + descriptor->name();
+}
+
+
+// Returns the fully normalized JavaScript path for the given
+// field's containing message descriptor.
+string GetPath(const GeneratorOptions& options,
+               const FieldDescriptor* descriptor) {
+  return GetPath(options, descriptor->containing_type());
+}
+
+// Returns the fully normalized JavaScript path for the given
+// enumeration descriptor.
+string GetPath(const GeneratorOptions& options,
+               const EnumDescriptor* enum_descriptor) {
+  return GetPrefix(
+      options, enum_descriptor->file(),
+      enum_descriptor->containing_type()) + enum_descriptor->name();
+}
+
+
+// Returns the fully normalized JavaScript path for the given
+// enumeration value descriptor.
+string GetPath(const GeneratorOptions& options,
+               const EnumValueDescriptor* value_descriptor) {
+  return GetPath(
+      options,
+      value_descriptor->type()) + "." + value_descriptor->name();
+}
+
+string MaybeCrossFileRef(const GeneratorOptions& options,
+                         const FileDescriptor* from_file,
+                         const Descriptor* to_message) {
+  if (options.import_style == GeneratorOptions::IMPORT_COMMONJS &&
+      from_file != to_message->file()) {
+    // Cross-file ref in CommonJS needs to use the module alias instead of
+    // the global name.
+    return ModuleAlias(to_message->file()->name()) + "." + to_message->name();
+  } else {
+    // Within a single file we use a full name.
+    return GetPath(options, to_message);
+  }
+}
+
+string SubmessageTypeRef(const GeneratorOptions& options,
+                         const FieldDescriptor* field) {
+  GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+  return MaybeCrossFileRef(options, field->file(), field->message_type());
+}
+
+// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields
+// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate,
+// and with reserved words triggering a "pb_" prefix.
+// - Getters/setters: LOWER_UNDERSCORE -> UPPER_CAMEL, except for group fields
+// (use the name directly), then append "List" if appropriate, then append "$"
+// if resulting name is equal to a reserved word.
+// - Enums: just uppercase.
+
+// Locale-independent version of ToLower that deals only with ASCII A-Z.
+char ToLowerASCII(char c) {
+  if (c >= 'A' && c <= 'Z') {
+    return (c - 'A') + 'a';
+  } else {
+    return c;
+  }
+}
+
+vector<string> ParseLowerUnderscore(const string& input) {
+  vector<string> words;
+  string running = "";
+  for (int i = 0; i < input.size(); i++) {
+    if (input[i] == '_') {
+      if (!running.empty()) {
+        words.push_back(running);
+        running.clear();
+      }
+    } else {
+      running += ToLowerASCII(input[i]);
+    }
+  }
+  if (!running.empty()) {
+    words.push_back(running);
+  }
+  return words;
+}
+
+vector<string> ParseUpperCamel(const string& input) {
+  vector<string> words;
+  string running = "";
+  for (int i = 0; i < input.size(); i++) {
+    if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) {
+      words.push_back(running);
+      running.clear();
+    }
+    running += ToLowerASCII(input[i]);
+  }
+  if (!running.empty()) {
+    words.push_back(running);
+  }
+  return words;
+}
+
+string ToLowerCamel(const vector<string>& words) {
+  string result;
+  for (int i = 0; i < words.size(); i++) {
+    string word = words[i];
+    if (i == 0 && (word[0] >= 'A' && word[0] <= 'Z')) {
+      word[0] = (word[0] - 'A') + 'a';
+    } else if (i != 0 && (word[0] >= 'a' && word[0] <= 'z')) {
+      word[0] = (word[0] - 'a') + 'A';
+    }
+    result += word;
+  }
+  return result;
+}
+
+string ToUpperCamel(const vector<string>& words) {
+  string result;
+  for (int i = 0; i < words.size(); i++) {
+    string word = words[i];
+    if (word[0] >= 'a' && word[0] <= 'z') {
+      word[0] = (word[0] - 'a') + 'A';
+    }
+    result += word;
+  }
+  return result;
+}
+
+// Based on code from descriptor.cc (Thanks Kenton!)
+// Uppercases the entire string, turning ValueName into
+// VALUENAME.
+string ToEnumCase(const string& input) {
+  string result;
+  result.reserve(input.size());
+
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      result.push_back(input[i] - 'a' + 'A');
+    } else {
+      result.push_back(input[i]);
+    }
+  }
+
+  return result;
+}
+
+string ToFileName(const string& input) {
+  string result;
+  result.reserve(input.size());
+
+  for (int i = 0; i < input.size(); i++) {
+    if ('A' <= input[i] && input[i] <= 'Z') {
+      result.push_back(input[i] - 'A' + 'a');
+    } else {
+      result.push_back(input[i]);
+    }
+  }
+
+  return result;
+}
+
+// When we're generating one output file per type name, this is the filename
+// that top-level extensions should go in.
+string GetExtensionFileName(const GeneratorOptions& options,
+                            const FileDescriptor* file) {
+  return options.output_dir + "/" + ToFileName(GetPath(options, file)) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetMessageFileName(const GeneratorOptions& options,
+                          const Descriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetEnumFileName(const GeneratorOptions& options,
+                       const EnumDescriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
+// Returns the message/response ID, if set.
+string GetMessageId(const Descriptor* desc) {
+  return string();
+}
+
+bool IgnoreExtensionField(const FieldDescriptor* field) {
+  // Exclude descriptor extensions from output "to avoid clutter" (from original
+  // codegen).
+  return field->is_extension() &&
+         field->containing_type()->file()->name() ==
+             "google/protobuf/descriptor.proto";
+}
+
+
+// Used inside Google only -- do not remove.
+bool IsResponse(const Descriptor* desc) { return false; }
+
+bool IgnoreField(const FieldDescriptor* field) {
+  return IgnoreExtensionField(field);
+}
+
+
+// Does JSPB ignore this entire oneof? True only if all fields are ignored.
+bool IgnoreOneof(const OneofDescriptor* oneof) {
+  for (int i = 0; i < oneof->field_count(); i++) {
+    if (!IgnoreField(oneof->field(i))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+string JSIdent(const FieldDescriptor* field,
+               bool is_upper_camel,
+               bool is_map) {
+  string result;
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    result = is_upper_camel ?
+        ToUpperCamel(ParseUpperCamel(field->message_type()->name())) :
+        ToLowerCamel(ParseUpperCamel(field->message_type()->name()));
+  } else {
+    result = is_upper_camel ?
+        ToUpperCamel(ParseLowerUnderscore(field->name())) :
+        ToLowerCamel(ParseLowerUnderscore(field->name()));
+  }
+  if (is_map) {
+    result += "Map";
+  } else if (field->is_repeated()) {
+    result += "List";
+  }
+  return result;
+}
+
+string JSObjectFieldName(const FieldDescriptor* field) {
+  string name = JSIdent(
+      field,
+      /* is_upper_camel = */ false,
+      /* is_map = */ false);
+  if (IsReserved(name)) {
+    name = "pb_" + name;
+  }
+  return name;
+}
+
+string JSByteGetterSuffix(BytesMode bytes_mode) {
+  switch (bytes_mode) {
+    case BYTES_DEFAULT:
+      return "";
+    case BYTES_B64:
+      return "B64";
+    case BYTES_U8:
+      return "U8";
+    default:
+      assert(false);
+  }
+}
+
+// Returns the field name as a capitalized portion of a getter/setter method
+// name, e.g. MyField for .getMyField().
+string JSGetterName(const FieldDescriptor* field,
+                    BytesMode bytes_mode = BYTES_DEFAULT) {
+  string name = JSIdent(field,
+                        /* is_upper_camel = */ true,
+                        /* is_map = */ false);
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    string suffix = JSByteGetterSuffix(bytes_mode);
+    if (!suffix.empty()) {
+      name += "_as" + suffix;
+    }
+  }
+  if (name == "Extension" || name == "JsPbMessageId") {
+    // Avoid conflicts with base-class names.
+    name += "$";
+  }
+  return name;
+}
+
+string JSMapGetterName(const FieldDescriptor* field) {
+  return JSIdent(field,
+                 /* is_upper_camel = */ true,
+                 /* is_map = */ true);
+}
+
+
+
+string JSOneofName(const OneofDescriptor* oneof) {
+  return ToUpperCamel(ParseLowerUnderscore(oneof->name()));
+}
+
+// Returns the index corresponding to this field in the JSPB array (underlying
+// data storage array).
+string JSFieldIndex(const FieldDescriptor* field) {
+  // Determine whether this field is a member of a group. Group fields are a bit
+  // wonky: their "containing type" is a message type created just for the
+  // group, and that type's parent type has a field with the group-message type
+  // as its message type and TYPE_GROUP as its field type. For such fields, the
+  // index we use is relative to the field number of the group submessage field.
+  // For all other fields, we just use the field number.
+  const Descriptor* containing_type = field->containing_type();
+  const Descriptor* parent_type = containing_type->containing_type();
+  if (parent_type != NULL) {
+    for (int i = 0; i < parent_type->field_count(); i++) {
+      if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP &&
+          parent_type->field(i)->message_type() == containing_type) {
+        return SimpleItoa(field->number() - parent_type->field(i)->number());
+      }
+    }
+  }
+  return SimpleItoa(field->number());
+}
+
+string JSOneofIndex(const OneofDescriptor* oneof) {
+  int index = -1;
+  for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) {
+    const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i);
+    // If at least one field in this oneof is not JSPB-ignored, count the oneof.
+    for (int j = 0; j < o->field_count(); j++) {
+      const FieldDescriptor* f = o->field(j);
+      if (!IgnoreField(f)) {
+        index++;
+        break;  // inner loop
+      }
+    }
+    if (o == oneof) {
+      break;
+    }
+  }
+  return SimpleItoa(index);
+}
+
+// Decodes a codepoint in \x0000 -- \xFFFF.
+uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
+  if (*length == 0) {
+    return 0;
+  }
+  size_t expected = 0;
+  if ((*bytes & 0x80) == 0) {
+    expected = 1;
+  } else if ((*bytes & 0xe0) == 0xc0) {
+    expected = 2;
+  } else if ((*bytes & 0xf0) == 0xe0) {
+    expected = 3;
+  } else {
+    // Too long -- don't accept.
+    *length = 0;
+    return 0;
+  }
+
+  if (*length < expected) {
+    // Not enough bytes -- don't accept.
+    *length = 0;
+    return 0;
+  }
+
+  *length = expected;
+  switch (expected) {
+    case 1: return bytes[0];
+    case 2: return ((bytes[0] & 0x1F) << 6)  |
+                   ((bytes[1] & 0x3F) << 0);
+    case 3: return ((bytes[0] & 0x0F) << 12) |
+                   ((bytes[1] & 0x3F) << 6)  |
+                   ((bytes[2] & 0x3F) << 0);
+    default: return 0;
+  }
+}
+
+// Escapes the contents of a string to be included within double-quotes ("") in
+// JavaScript. The input data should be a UTF-8 encoded C++ string of chars.
+// Returns false if |out| was truncated because |in| contained invalid UTF-8 or
+// codepoints outside the BMP.
+// TODO(lukestebbing): Support codepoints outside the BMP.
+bool EscapeJSString(const string& in, string* out) {
+  size_t decoded = 0;
+  for (size_t i = 0; i < in.size(); i += decoded) {
+    uint16 codepoint = 0;
+    // Decode the next UTF-8 codepoint.
+    size_t have_bytes = in.size() - i;
+    uint8 bytes[3] = {
+        static_cast<uint8>(in[i]),
+        static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0),
+        static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0),
+    };
+    codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
+    if (have_bytes == 0) {
+      return false;
+    }
+    decoded = have_bytes;
+
+    switch (codepoint) {
+      case '\'': *out += "\\x27"; break;
+      case '"': *out += "\\x22"; break;
+      case '<': *out += "\\x3c"; break;
+      case '=': *out += "\\x3d"; break;
+      case '>': *out += "\\x3e"; break;
+      case '&': *out += "\\x26"; break;
+      case '\b': *out += "\\b"; break;
+      case '\t': *out += "\\t"; break;
+      case '\n': *out += "\\n"; break;
+      case '\f': *out += "\\f"; break;
+      case '\r': *out += "\\r"; break;
+      case '\\': *out += "\\\\"; break;
+      default:
+        // TODO(lukestebbing): Once we're supporting codepoints outside the BMP,
+        // use a single Unicode codepoint escape if the output language is
+        // ECMAScript 2015 or above. Otherwise, use a surrogate pair.
+        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals
+        if (codepoint >= 0x20 && codepoint <= 0x7e) {
+          *out += static_cast<char>(codepoint);
+        } else if (codepoint >= 0x100) {
+          *out += StringPrintf("\\u%04x", codepoint);
+        } else {
+          *out += StringPrintf("\\x%02x", codepoint);
+        }
+        break;
+    }
+  }
+  return true;
+}
+
+string EscapeBase64(const string& in) {
+  static const char* kAlphabet =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  string result;
+
+  for (size_t i = 0; i < in.size(); i += 3) {
+    int value = (in[i] << 16) |
+        (((i + 1) < in.size()) ? (in[i + 1] << 8) : 0) |
+        (((i + 2) < in.size()) ? (in[i + 2] << 0) : 0);
+    result += kAlphabet[(value >> 18) & 0x3f];
+    result += kAlphabet[(value >> 12) & 0x3f];
+    if ((i + 1) < in.size()) {
+      result += kAlphabet[(value >>  6) & 0x3f];
+    } else {
+      result += '=';
+    }
+    if ((i + 2) < in.size()) {
+      result += kAlphabet[(value >>  0) & 0x3f];
+    } else {
+      result += '=';
+    }
+  }
+
+  return result;
+}
+
+// Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the
+// original codegen's formatting (which is just .toString() on java.lang.Double
+// or java.lang.Float).
+string PostProcessFloat(string result) {
+  // If inf, -inf or nan, replace with +Infinity, -Infinity or NaN.
+  if (result == "inf") {
+    return "Infinity";
+  } else if (result == "-inf") {
+    return "-Infinity";
+  } else if (result == "nan") {
+    return "NaN";
+  }
+
+  // If scientific notation (e.g., "1e10"), (i) capitalize the "e", (ii)
+  // ensure that the mantissa (portion prior to the "e") has at least one
+  // fractional digit (after the decimal point), and (iii) strip any unnecessary
+  // leading zeroes and/or '+' signs from the exponent.
+  string::size_type exp_pos = result.find('e');
+  if (exp_pos != string::npos) {
+    string mantissa = result.substr(0, exp_pos);
+    string exponent = result.substr(exp_pos + 1);
+
+    // Add ".0" to mantissa if no fractional part exists.
+    if (mantissa.find('.') == string::npos) {
+      mantissa += ".0";
+    }
+
+    // Strip the sign off the exponent and store as |exp_neg|.
+    bool exp_neg = false;
+    if (!exponent.empty() && exponent[0] == '+') {
+      exponent = exponent.substr(1);
+    } else if (!exponent.empty() && exponent[0] == '-') {
+      exp_neg = true;
+      exponent = exponent.substr(1);
+    }
+
+    // Strip any leading zeroes off the exponent.
+    while (exponent.size() > 1 && exponent[0] == '0') {
+      exponent = exponent.substr(1);
+    }
+
+    return mantissa + "E" + string(exp_neg ? "-" : "") + exponent;
+  }
+
+  // Otherwise, this is an ordinary decimal number. Append ".0" if result has no
+  // decimal/fractional part in order to match output of original codegen.
+  if (result.find('.') == string::npos) {
+    result += ".0";
+  }
+
+  return result;
+}
+
+string FloatToString(float value) {
+  string result = SimpleFtoa(value);
+  return PostProcessFloat(result);
+}
+
+string DoubleToString(double value) {
+  string result = SimpleDtoa(value);
+  return PostProcessFloat(result);
+}
+
+string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
+  return orig;
+}
+
+string JSFieldDefault(const FieldDescriptor* field) {
+  assert(field->has_default_value());
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return MaybeNumberString(
+          field, SimpleItoa(field->default_value_int32()));
+    case FieldDescriptor::CPPTYPE_UINT32:
+      // The original codegen is in Java, and Java protobufs store unsigned
+      // integer values as signed integer values. In order to exactly match the
+      // output, we need to reinterpret as base-2 signed. Ugh.
+      return MaybeNumberString(
+          field, SimpleItoa(static_cast<int32>(field->default_value_uint32())));
+    case FieldDescriptor::CPPTYPE_INT64:
+      return MaybeNumberString(
+          field, SimpleItoa(field->default_value_int64()));
+    case FieldDescriptor::CPPTYPE_UINT64:
+      // See above note for uint32 -- reinterpreting as signed.
+      return MaybeNumberString(
+          field, SimpleItoa(static_cast<int64>(field->default_value_uint64())));
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return SimpleItoa(field->default_value_enum()->number());
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "true" : "false";
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return FloatToString(field->default_value_float());
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return DoubleToString(field->default_value_double());
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (field->type() == FieldDescriptor::TYPE_STRING) {
+        string out;
+        bool is_valid = EscapeJSString(field->default_value_string(), &out);
+        if (!is_valid) {
+          // TODO(lukestebbing): Decide whether this should be a hard error.
+          GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name()
+                       << " was truncated since it contained invalid UTF-8 or"
+                          " codepoints outside the basic multilingual plane.";
+        }
+        return "\"" + out + "\"";
+      } else {  // Bytes
+        return "\"" + EscapeBase64(field->default_value_string()) + "\"";
+      }
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "null";
+  }
+  GOOGLE_LOG(FATAL) << "Shouldn't reach here.";
+  return "";
+}
+
+string ProtoTypeName(const GeneratorOptions& options,
+                     const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_BOOL:
+      return "bool";
+    case FieldDescriptor::TYPE_INT32:
+      return "int32";
+    case FieldDescriptor::TYPE_UINT32:
+      return "uint32";
+    case FieldDescriptor::TYPE_SINT32:
+      return "sint32";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "fixed32";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "sfixed32";
+    case FieldDescriptor::TYPE_INT64:
+      return "int64";
+    case FieldDescriptor::TYPE_UINT64:
+      return "uint64";
+    case FieldDescriptor::TYPE_SINT64:
+      return "sint64";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "fixed64";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "sfixed64";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "float";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "double";
+    case FieldDescriptor::TYPE_STRING:
+      return "string";
+    case FieldDescriptor::TYPE_BYTES:
+      return "bytes";
+    case FieldDescriptor::TYPE_GROUP:
+      return GetPath(options, field->message_type());
+    case FieldDescriptor::TYPE_ENUM:
+      return GetPath(options, field->enum_type());
+    case FieldDescriptor::TYPE_MESSAGE:
+      return GetPath(options, field->message_type());
+    default:
+      return "";
+  }
+}
+
+string JSIntegerTypeName(const FieldDescriptor* field) {
+  return "number";
+}
+
+string JSStringTypeName(const GeneratorOptions& options,
+                        const FieldDescriptor* field,
+                        BytesMode bytes_mode) {
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    switch (bytes_mode) {
+      case BYTES_DEFAULT:
+        return "(string|Uint8Array)";
+      case BYTES_B64:
+        return "string";
+      case BYTES_U8:
+        return "Uint8Array";
+      default:
+        assert(false);
+    }
+  }
+  return "string";
+}
+
+string JSTypeName(const GeneratorOptions& options,
+                  const FieldDescriptor* field,
+                  BytesMode bytes_mode) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return "boolean";
+    case FieldDescriptor::CPPTYPE_INT32:
+      return JSIntegerTypeName(field);
+    case FieldDescriptor::CPPTYPE_INT64:
+      return JSIntegerTypeName(field);
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return JSIntegerTypeName(field);
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return JSIntegerTypeName(field);
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return "number";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return "number";
+    case FieldDescriptor::CPPTYPE_STRING:
+      return JSStringTypeName(options, field, bytes_mode);
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return GetPath(options, field->enum_type());
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return GetPath(options, field->message_type());
+    default:
+      return "";
+  }
+}
+
+bool HasFieldPresence(const FieldDescriptor* field);
+
+string JSFieldTypeAnnotation(const GeneratorOptions& options,
+                             const FieldDescriptor* field,
+                             bool force_optional,
+                             bool force_present,
+                             bool singular_if_not_packed,
+                             BytesMode bytes_mode = BYTES_DEFAULT) {
+  bool is_primitive =
+      (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
+       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
+        (field->type() != FieldDescriptor::TYPE_BYTES ||
+            bytes_mode == BYTES_B64));
+
+  string jstype = JSTypeName(options, field, bytes_mode);
+
+  if (field->is_repeated() &&
+      (field->is_packed() || !singular_if_not_packed)) {
+    if (field->type() == FieldDescriptor::TYPE_BYTES &&
+        bytes_mode == BYTES_DEFAULT) {
+      jstype = "(Array<!Uint8Array>|Array<string>)";
+    } else {
+      if (!is_primitive) {
+        jstype = "!" + jstype;
+      }
+      jstype = "Array.<" + jstype + ">";
+    }
+    if (!force_optional) {
+      jstype = "!" + jstype;
+    }
+  }
+
+  if (field->is_optional() && is_primitive &&
+      (!field->has_default_value() || force_optional) && !force_present) {
+    jstype += "?";
+  } else if (field->is_required() && !is_primitive && !force_optional) {
+    jstype = "!" + jstype;
+  }
+
+  if (force_optional && HasFieldPresence(field)) {
+    jstype += "|undefined";
+  }
+  if (force_present && jstype[0] != '!' && !is_primitive) {
+    jstype = "!" + jstype;
+  }
+
+  return jstype;
+}
+
+string JSBinaryReaderMethodType(const FieldDescriptor* field) {
+  string name = field->type_name();
+  if (name[0] >= 'a' && name[0] <= 'z') {
+    name[0] = (name[0] - 'a') + 'A';
+  }
+
+  return name;
+}
+
+string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
+                                   bool is_writer) {
+  string name = JSBinaryReaderMethodType(field);
+  if (field->is_packed()) {
+    name = "Packed" + name;
+  } else if (is_writer && field->is_repeated()) {
+    name = "Repeated" + name;
+  }
+  return name;
+}
+
+string JSBinaryReaderMethodName(const FieldDescriptor* field) {
+  return "read" + JSBinaryReadWriteMethodName(field, /* is_writer = */ false);
+}
+
+string JSBinaryWriterMethodName(const FieldDescriptor* field) {
+  return "write" + JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
+}
+
+string JSReturnClause(const FieldDescriptor* desc) {
+  return "";
+}
+
+string JSReturnDoc(const GeneratorOptions& options,
+                   const FieldDescriptor* desc) {
+  return "";
+}
+
+bool HasRepeatedFields(const Descriptor* desc) {
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (desc->field(i)->is_repeated()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static const char* kRepeatedFieldArrayName = ".repeatedFields_";
+
+string RepeatedFieldsArrayName(const GeneratorOptions& options,
+                               const Descriptor* desc) {
+  return HasRepeatedFields(desc) ?
+      (GetPath(options, desc) + kRepeatedFieldArrayName) : "null";
+}
+
+bool HasOneofFields(const Descriptor* desc) {
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (desc->field(i)->containing_oneof()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static const char* kOneofGroupArrayName = ".oneofGroups_";
+
+string OneofFieldsArrayName(const GeneratorOptions& options,
+                            const Descriptor* desc) {
+  return HasOneofFields(desc) ?
+      (GetPath(options, desc) + kOneofGroupArrayName) : "null";
+}
+
+string RepeatedFieldNumberList(const Descriptor* desc) {
+  std::vector<string> numbers;
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (desc->field(i)->is_repeated()) {
+      numbers.push_back(JSFieldIndex(desc->field(i)));
+    }
+  }
+  return "[" + Join(numbers, ",") + "]";
+}
+
+string OneofGroupList(const Descriptor* desc) {
+  // List of arrays (one per oneof), each of which is a list of field indices
+  std::vector<string> oneof_entries;
+  for (int i = 0; i < desc->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = desc->oneof_decl(i);
+    if (IgnoreOneof(oneof)) {
+      continue;
+    }
+
+    std::vector<string> oneof_fields;
+    for (int j = 0; j < oneof->field_count(); j++) {
+      if (IgnoreField(oneof->field(j))) {
+        continue;
+      }
+      oneof_fields.push_back(JSFieldIndex(oneof->field(j)));
+    }
+    oneof_entries.push_back("[" + Join(oneof_fields, ",") + "]");
+  }
+  return "[" + Join(oneof_entries, ",") + "]";
+}
+
+string JSOneofArray(const GeneratorOptions& options,
+                    const FieldDescriptor* field) {
+  return OneofFieldsArrayName(options, field->containing_type()) + "[" +
+      JSOneofIndex(field->containing_oneof()) + "]";
+}
+
+string RelativeTypeName(const FieldDescriptor* field) {
+  assert(field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM ||
+         field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+  // For a field with an enum or message type, compute a name relative to the
+  // path name of the message type containing this field.
+  string package = field->file()->package();
+  string containing_type = field->containing_type()->full_name() + ".";
+  string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) ?
+      field->enum_type()->full_name() : field->message_type()->full_name();
+
+  // |prefix| is advanced as we find separators '.' past the common package
+  // prefix that yield common prefixes in the containing type's name and this
+  // type's name.
+  int prefix = 0;
+  for (int i = 0; i < type.size() && i < containing_type.size(); i++) {
+    if (type[i] != containing_type[i]) {
+      break;
+    }
+    if (type[i] == '.' && i >= package.size()) {
+      prefix = i + 1;
+    }
+  }
+
+  return type.substr(prefix);
+}
+
+string JSExtensionsObjectName(const GeneratorOptions& options,
+                              const FileDescriptor* from_file,
+                              const Descriptor* desc) {
+  if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
+    // TODO(haberman): fix this for the IMPORT_COMMONJS case.
+    return "jspb.Message.messageSetExtensions";
+  } else {
+    return MaybeCrossFileRef(options, from_file, desc) + ".extensions";
+  }
+}
+
+string FieldDefinition(const GeneratorOptions& options,
+                       const FieldDescriptor* field) {
+  string qualifier = field->is_repeated() ? "repeated" :
+      (field->is_optional() ? "optional" : "required");
+  string type, name;
+  if (field->type() == FieldDescriptor::TYPE_ENUM ||
+      field->type() == FieldDescriptor::TYPE_MESSAGE) {
+    type = RelativeTypeName(field);
+    name = field->name();
+  } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    type = "group";
+    name = field->message_type()->name();
+  } else {
+    type = ProtoTypeName(options, field);
+    name = field->name();
+  }
+  return StringPrintf("%s %s %s = %d;",
+                      qualifier.c_str(),
+                      type.c_str(),
+                      name.c_str(),
+                      field->number());
+}
+
+string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
+  string comments;
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL) {
+    comments +=
+        " * Note that Boolean fields may be set to 0/1 when serialized from "
+        "a Java server.\n"
+        " * You should avoid comparisons like {@code val === true/false} in "
+        "those cases.\n";
+  }
+  if (field->is_repeated()) {
+    comments +=
+        " * If you change this array by adding, removing or replacing "
+        "elements, or if you\n"
+        " * replace the array itself, then you must call the setter to "
+        "update it.\n";
+  }
+  if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
+    comments +=
+        " * Note that Uint8Array is not supported on all browsers.\n"
+        " * @see http://caniuse.com/Uint8Array\n";
+  }
+  return comments;
+}
+
+bool ShouldGenerateExtension(const FieldDescriptor* field) {
+  return
+      field->is_extension() &&
+      !IgnoreField(field);
+}
+
+bool HasExtensions(const Descriptor* desc) {
+  for (int i = 0; i < desc->extension_count(); i++) {
+    if (ShouldGenerateExtension(desc->extension(i))) {
+      return true;
+    }
+  }
+  for (int i = 0; i < desc->nested_type_count(); i++) {
+    if (HasExtensions(desc->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool HasExtensions(const FileDescriptor* file) {
+  for (int i = 0; i < file->extension_count(); i++) {
+    if (ShouldGenerateExtension(file->extension(i))) {
+      return true;
+    }
+  }
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (HasExtensions(file->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool IsExtendable(const Descriptor* desc) {
+  return desc->extension_range_count() > 0;
+}
+
+// Returns the max index in the underlying data storage array beyond which the
+// extension object is used.
+string GetPivot(const Descriptor* desc) {
+  static const int kDefaultPivot = (1 << 29);  // max field number (29 bits)
+
+  // Find the max field number
+  int max_field_number = 0;
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (!IgnoreField(desc->field(i)) &&
+        desc->field(i)->number() > max_field_number) {
+      max_field_number = desc->field(i)->number();
+    }
+  }
+
+  int pivot = -1;
+  if (IsExtendable(desc)) {
+    pivot = ((max_field_number + 1) < kDefaultPivot) ?
+        (max_field_number + 1) : kDefaultPivot;
+  }
+
+  return SimpleItoa(pivot);
+}
+
+// Returns true for fields that represent "null" as distinct from the default
+// value. See http://go/proto3#heading=h.kozewqqcqhuz for more information.
+bool HasFieldPresence(const FieldDescriptor* field) {
+  return
+      (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
+      (field->containing_oneof() != NULL) ||
+      (field->file()->syntax() != FileDescriptor::SYNTAX_PROTO3);
+}
+
+// For proto3 fields without presence, returns a string representing the default
+// value in JavaScript. See http://go/proto3#heading=h.kozewqqcqhuz for more
+// information.
+string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      return "0";
+    }
+
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return "0";
+
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return "false";
+
+    case FieldDescriptor::CPPTYPE_STRING:  // includes BYTES
+      return "\"\"";
+
+    default:
+      // MESSAGE is handled separately.
+      assert(false);
+      return "";
+  }
+}
+
+// We use this to implement the semantics that same file can be generated
+// multiple times, but the last one wins.  We never actually write the files,
+// but we keep a set of which descriptors were the final one for a given
+// filename.
+class FileDeduplicator {
+ public:
+  explicit FileDeduplicator(const GeneratorOptions& options)
+      : error_on_conflict_(options.error_on_name_conflict) {}
+
+  bool AddFile(const string& filename, const void* desc, string* error) {
+    if (descs_by_filename_.find(filename) != descs_by_filename_.end()) {
+      if (error_on_conflict_) {
+        *error = "Name conflict: file name " + filename +
+                 " would be generated by two descriptors";
+        return false;
+      }
+      allowed_descs_.erase(descs_by_filename_[filename]);
+    }
+
+    descs_by_filename_[filename] = desc;
+    allowed_descs_.insert(desc);
+    return true;
+  }
+
+  void GetAllowedSet(set<const void*>* allowed_set) {
+    *allowed_set = allowed_descs_;
+  }
+
+ private:
+  bool error_on_conflict_;
+  map<string, const void*> descs_by_filename_;
+  set<const void*> allowed_descs_;
+};
+
+void DepthFirstSearch(const FileDescriptor* file,
+                      vector<const FileDescriptor*>* list,
+                      set<const FileDescriptor*>* seen) {
+  if (!seen->insert(file).second) {
+    return;
+  }
+
+  // Add all dependencies.
+  for (int i = 0; i < file->dependency_count(); i++) {
+    DepthFirstSearch(file->dependency(i), list, seen);
+  }
+
+  // Add this file.
+  list->push_back(file);
+}
+
+// A functor for the predicate to remove_if() below.  Returns true if a given
+// FileDescriptor is not in the given set.
+class NotInSet {
+ public:
+  explicit NotInSet(const set<const FileDescriptor*>& file_set)
+      : file_set_(file_set) {}
+
+  bool operator()(const FileDescriptor* file) {
+    return file_set_.count(file) == 0;
+  }
+
+ private:
+  const set<const FileDescriptor*>& file_set_;
+};
+
+// This function generates an ordering of the input FileDescriptors that matches
+// the logic of the old code generator.  The order is significant because two
+// different input files can generate the same output file, and the last one
+// needs to win.
+void GenerateJspbFileOrder(const vector<const FileDescriptor*>& input,
+                           vector<const FileDescriptor*>* ordered) {
+  // First generate an ordering of all reachable files (including dependencies)
+  // with depth-first search.  This mimics the behavior of --include_imports,
+  // which is what the old codegen used.
+  ordered->clear();
+  set<const FileDescriptor*> seen;
+  set<const FileDescriptor*> input_set;
+  for (int i = 0; i < input.size(); i++) {
+    DepthFirstSearch(input[i], ordered, &seen);
+    input_set.insert(input[i]);
+  }
+
+  // Now remove the entries that are not actually in our input list.
+  ordered->erase(
+      std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)),
+      ordered->end());
+}
+
+// If we're generating code in file-per-type mode, avoid overwriting files
+// by choosing the last descriptor that writes each filename and permitting
+// only those to generate code.
+
+bool GenerateJspbAllowedSet(const GeneratorOptions& options,
+                            const vector<const FileDescriptor*>& files,
+                            set<const void*>* allowed_set,
+                            string* error) {
+  vector<const FileDescriptor*> files_ordered;
+  GenerateJspbFileOrder(files, &files_ordered);
+
+  // Choose the last descriptor for each filename.
+  FileDeduplicator dedup(options);
+  for (int i = 0; i < files_ordered.size(); i++) {
+    for (int j = 0; j < files_ordered[i]->message_type_count(); j++) {
+      const Descriptor* desc = files_ordered[i]->message_type(j);
+      if (!dedup.AddFile(GetMessageFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+    for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) {
+      const EnumDescriptor* desc = files_ordered[i]->enum_type(j);
+      if (!dedup.AddFile(GetEnumFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+
+    // Pull out all free-floating extensions and generate files for those too.
+    bool has_extension = false;
+
+    for (int j = 0; j < files_ordered[i]->extension_count(); j++) {
+      if (ShouldGenerateExtension(files_ordered[i]->extension(j))) {
+        has_extension = true;
+      }
+    }
+
+    if (has_extension) {
+      if (!dedup.AddFile(GetExtensionFileName(options, files_ordered[i]),
+                         files_ordered[i], error)) {
+        return false;
+      }
+    }
+  }
+
+  dedup.GetAllowedSet(allowed_set);
+
+  return true;
+}
+
+}  // anonymous namespace
+
+void Generator::GenerateHeader(const GeneratorOptions& options,
+                               io::Printer* printer) const {
+  printer->Print("/**\n"
+                 " * @fileoverview\n"
+                 " * @enhanceable\n"
+                 " * @public\n"
+                 " */\n"
+                 "// GENERATED CODE -- DO NOT EDIT!\n"
+                 "\n");
+}
+
+void Generator::FindProvidesForFile(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const FileDescriptor* file,
+                                    std::set<string>* provided) const {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    FindProvidesForMessage(options, printer, file->message_type(i), provided);
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    FindProvidesForEnum(options, printer, file->enum_type(i), provided);
+  }
+}
+
+void Generator::FindProvides(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const vector<const FileDescriptor*>& files,
+                             std::set<string>* provided) const {
+  for (int i = 0; i < files.size(); i++) {
+    FindProvidesForFile(options, printer, files[i], provided);
+  }
+
+  printer->Print("\n");
+}
+
+void Generator::FindProvidesForMessage(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const Descriptor* desc,
+    std::set<string>* provided) const {
+  string name = GetPath(options, desc);
+  provided->insert(name);
+
+  for (int i = 0; i < desc->enum_type_count(); i++) {
+    FindProvidesForEnum(options, printer, desc->enum_type(i),
+                        provided);
+  }
+  for (int i = 0; i < desc->nested_type_count(); i++) {
+    FindProvidesForMessage(options, printer, desc->nested_type(i),
+                           provided);
+  }
+}
+
+void Generator::FindProvidesForEnum(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const EnumDescriptor* enumdesc,
+                                    std::set<string>* provided) const {
+  string name = GetPath(options, enumdesc);
+  provided->insert(name);
+}
+
+void Generator::FindProvidesForFields(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const vector<const FieldDescriptor*>& fields,
+    std::set<string>* provided) const {
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+
+    if (IgnoreField(field)) {
+      continue;
+    }
+
+    string name =
+        GetPath(options, field->file()) + "." + JSObjectFieldName(field);
+    provided->insert(name);
+  }
+}
+
+void Generator::GenerateProvides(const GeneratorOptions& options,
+                                 io::Printer* printer,
+                                 std::set<string>* provided) const {
+  for (std::set<string>::iterator it = provided->begin();
+       it != provided->end(); ++it) {
+    printer->Print("goog.provide('$name$');\n",
+                   "name", *it);
+  }
+}
+
+void Generator::GenerateRequiresForMessage(const GeneratorOptions& options,
+                                           io::Printer* printer,
+                                           const Descriptor* desc,
+                                           std::set<string>* provided) const {
+  std::set<string> required;
+  std::set<string> forwards;
+  bool have_message = false;
+  FindRequiresForMessage(options, desc,
+                         &required, &forwards, &have_message);
+
+  GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+                       /* require_jspb = */ have_message,
+                       /* require_extension = */ HasExtensions(desc));
+}
+
+void Generator::GenerateRequiresForLibrary(
+    const GeneratorOptions& options, io::Printer* printer,
+    const vector<const FileDescriptor*>& files,
+    std::set<string>* provided) const {
+  GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::IMPORT_CLOSURE);
+  // For Closure imports we need to import every message type individually.
+  std::set<string> required;
+  std::set<string> forwards;
+  bool have_extensions = false;
+  bool have_message = false;
+
+  for (int i = 0; i < files.size(); i++) {
+    for (int j = 0; j < files[i]->message_type_count(); j++) {
+      FindRequiresForMessage(options,
+                             files[i]->message_type(j),
+                             &required, &forwards, &have_message);
+    }
+    if (!have_extensions && HasExtensions(files[i])) {
+      have_extensions = true;
+    }
+
+    for (int j = 0; j < files[i]->extension_count(); j++) {
+      const FieldDescriptor* extension = files[i]->extension(j);
+      if (IgnoreField(extension)) {
+        continue;
+      }
+      if (extension->containing_type()->full_name() !=
+        "google.protobuf.bridge.MessageSet") {
+        required.insert(GetPath(options, extension->containing_type()));
+      }
+      FindRequiresForField(options, extension, &required, &forwards);
+      have_extensions = true;
+    }
+  }
+
+  GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+                       /* require_jspb = */ have_message,
+                       /* require_extension = */ have_extensions);
+}
+
+void Generator::GenerateRequiresForExtensions(
+    const GeneratorOptions& options, io::Printer* printer,
+    const vector<const FieldDescriptor*>& fields,
+    std::set<string>* provided) const {
+  std::set<string> required;
+  std::set<string> forwards;
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    if (IgnoreField(field)) {
+      continue;
+    }
+    FindRequiresForExtension(options, field, &required, &forwards);
+  }
+
+  GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+                       /* require_jspb = */ false,
+                       /* require_extension = */ fields.size() > 0);
+}
+
+void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
+                                     io::Printer* printer,
+                                     std::set<string>* required,
+                                     std::set<string>* forwards,
+                                     std::set<string>* provided,
+                                     bool require_jspb,
+                                     bool require_extension) const {
+  if (require_jspb) {
+    printer->Print(
+        "goog.require('jspb.Message');\n");
+    if (options.binary) {
+      printer->Print(
+          "goog.require('jspb.BinaryReader');\n"
+          "goog.require('jspb.BinaryWriter');\n");
+    }
+  }
+  if (require_extension) {
+    printer->Print(
+        "goog.require('jspb.ExtensionFieldInfo');\n");
+  }
+
+  std::set<string>::iterator it;
+  for (it = required->begin(); it != required->end(); ++it) {
+    if (provided->find(*it) != provided->end()) {
+      continue;
+    }
+    printer->Print("goog.require('$name$');\n",
+                   "name", *it);
+  }
+
+  printer->Print("\n");
+
+  for (it = forwards->begin(); it != forwards->end(); ++it) {
+    if (provided->find(*it) != provided->end()) {
+      continue;
+    }
+    printer->Print("goog.forwardDeclare('$name$');\n",
+                   "name", *it);
+  }
+}
+
+bool NamespaceOnly(const Descriptor* desc) {
+  return false;
+}
+
+void Generator::FindRequiresForMessage(
+    const GeneratorOptions& options,
+    const Descriptor* desc,
+    std::set<string>* required,
+    std::set<string>* forwards,
+    bool* have_message) const {
+
+
+  if (!NamespaceOnly(desc)) {
+    *have_message = true;
+    for (int i = 0; i < desc->field_count(); i++) {
+      const FieldDescriptor* field = desc->field(i);
+      if (IgnoreField(field)) {
+        continue;
+      }
+      FindRequiresForField(options, field, required, forwards);
+    }
+  }
+
+  for (int i = 0; i < desc->extension_count(); i++) {
+    const FieldDescriptor* field = desc->extension(i);
+    if (IgnoreField(field)) {
+      continue;
+    }
+    FindRequiresForExtension(options, field, required, forwards);
+  }
+
+  for (int i = 0; i < desc->nested_type_count(); i++) {
+    FindRequiresForMessage(options, desc->nested_type(i), required, forwards,
+                           have_message);
+  }
+}
+
+void Generator::FindRequiresForField(const GeneratorOptions& options,
+                                     const FieldDescriptor* field,
+                                     std::set<string>* required,
+                                     std::set<string>* forwards) const {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+        // N.B.: file-level extensions with enum type do *not* create
+        // dependencies, as per original codegen.
+        !(field->is_extension() && field->extension_scope() == NULL)) {
+      if (options.add_require_for_enums) {
+        required->insert(GetPath(options, field->enum_type()));
+      } else {
+        forwards->insert(GetPath(options, field->enum_type()));
+      }
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      required->insert(GetPath(options, field->message_type()));
+    }
+}
+
+void Generator::FindRequiresForExtension(const GeneratorOptions& options,
+                                         const FieldDescriptor* field,
+                                         std::set<string>* required,
+                                         std::set<string>* forwards) const {
+    if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") {
+      required->insert(GetPath(options, field->containing_type()));
+    }
+    FindRequiresForField(options, field, required, forwards);
+}
+
+void Generator::GenerateTestOnly(const GeneratorOptions& options,
+                                 io::Printer* printer) const {
+  if (options.testonly) {
+    printer->Print("goog.setTestOnly();\n\n");
+  }
+  printer->Print("\n");
+}
+
+void Generator::GenerateClassesAndEnums(const GeneratorOptions& options,
+                                        io::Printer* printer,
+                                        const FileDescriptor* file) const {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    GenerateClass(options, printer, file->message_type(i));
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    GenerateEnum(options, printer, file->enum_type(i));
+  }
+}
+
+void Generator::GenerateClass(const GeneratorOptions& options,
+                              io::Printer* printer,
+                              const Descriptor* desc) const {
+  if (!NamespaceOnly(desc)) {
+    printer->Print("\n");
+    GenerateClassConstructor(options, printer, desc);
+    GenerateClassFieldInfo(options, printer, desc);
+
+
+    GenerateClassToObject(options, printer, desc);
+    if (options.binary) {
+      // These must come *before* the extension-field info generation in
+      // GenerateClassRegistration so that references to the binary
+      // serialization/deserialization functions may be placed in the extension
+      // objects.
+      GenerateClassDeserializeBinary(options, printer, desc);
+      GenerateClassSerializeBinary(options, printer, desc);
+    }
+    GenerateClassClone(options, printer, desc);
+    GenerateClassRegistration(options, printer, desc);
+    GenerateClassFields(options, printer, desc);
+    if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
+      GenerateClassExtensionFieldInfo(options, printer, desc);
+    }
+
+    if (options.import_style != GeneratorOptions:: IMPORT_CLOSURE) {
+      for (int i = 0; i < desc->extension_count(); i++) {
+        GenerateExtension(options, printer, desc->extension(i));
+      }
+    }
+  }
+
+  // Recurse on nested types.
+  for (int i = 0; i < desc->enum_type_count(); i++) {
+    GenerateEnum(options, printer, desc->enum_type(i));
+  }
+  for (int i = 0; i < desc->nested_type_count(); i++) {
+    GenerateClass(options, printer, desc->nested_type(i));
+  }
+}
+
+void Generator::GenerateClassConstructor(const GeneratorOptions& options,
+                                         io::Printer* printer,
+                                         const Descriptor* desc) const {
+  printer->Print(
+      "/**\n"
+      " * Generated by JsPbCodeGenerator.\n"
+      " * @param {Array=} opt_data Optional initial data array, typically "
+      "from a\n"
+      " * server response, or constructed directly in Javascript. The array "
+      "is used\n"
+      " * in place and becomes part of the constructed object. It is not "
+      "cloned.\n"
+      " * If no data is provided, the constructed object will be empty, but "
+      "still\n"
+      " * valid.\n"
+      " * @extends {jspb.Message}\n"
+      " * @constructor\n"
+      " */\n"
+      "$classname$ = function(opt_data) {\n",
+      "classname", GetPath(options, desc));
+  string message_id = GetMessageId(desc);
+  printer->Print(
+      "  jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, "
+      "$rptfields$, $oneoffields$);\n",
+      "messageId", !message_id.empty() ?
+                   ("'" + message_id + "'") :
+                   (IsResponse(desc) ? "''" : "0"),
+      "pivot", GetPivot(desc),
+      "rptfields", RepeatedFieldsArrayName(options, desc),
+      "oneoffields", OneofFieldsArrayName(options, desc));
+  printer->Print(
+      "};\n"
+      "goog.inherits($classname$, jspb.Message);\n"
+      "if (goog.DEBUG && !COMPILED) {\n"
+      "  $classname$.displayName = '$classname$';\n"
+      "}\n",
+      "classname", GetPath(options, desc));
+}
+
+void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
+                                       io::Printer* printer,
+                                       const Descriptor* desc) const {
+  if (HasRepeatedFields(desc)) {
+    printer->Print(
+        "/**\n"
+        " * List of repeated fields within this message type.\n"
+        " * @private {!Array<number>}\n"
+        " * @const\n"
+        " */\n"
+        "$classname$$rptfieldarray$ = $rptfields$;\n"
+        "\n",
+        "classname", GetPath(options, desc),
+        "rptfieldarray", kRepeatedFieldArrayName,
+        "rptfields", RepeatedFieldNumberList(desc));
+  }
+
+  if (HasOneofFields(desc)) {
+    printer->Print(
+        "/**\n"
+        " * Oneof group definitions for this message. Each group defines the "
+        "field\n"
+        " * numbers belonging to that group. When of these fields' value is "
+        "set, all\n"
+        " * other fields in the group are cleared. During deserialization, if "
+        "multiple\n"
+        " * fields are encountered for a group, only the last value seen will "
+        "be kept.\n"
+        " * @private {!Array<!Array<number>>}\n"
+        " * @const\n"
+        " */\n"
+        "$classname$$oneofgrouparray$ = $oneofgroups$;\n"
+        "\n",
+        "classname", GetPath(options, desc),
+        "oneofgrouparray", kOneofGroupArrayName,
+        "oneofgroups", OneofGroupList(desc));
+
+    for (int i = 0; i < desc->oneof_decl_count(); i++) {
+      if (IgnoreOneof(desc->oneof_decl(i))) {
+        continue;
+      }
+      GenerateOneofCaseDefinition(options, printer, desc->oneof_decl(i));
+    }
+  }
+}
+
+void Generator::GenerateClassXid(const GeneratorOptions& options,
+                                 io::Printer* printer,
+                                 const Descriptor* desc) const {
+  printer->Print(
+      "\n"
+      "\n"
+      "$class$.prototype.messageXid = xid('$class$');\n",
+      "class", GetPath(options, desc));
+}
+
+void Generator::GenerateOneofCaseDefinition(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const OneofDescriptor* oneof) const {
+  printer->Print(
+      "/**\n"
+      " * @enum {number}\n"
+      " */\n"
+      "$classname$.$oneof$Case = {\n"
+      "  $upcase$_NOT_SET: 0",
+      "classname", GetPath(options, oneof->containing_type()),
+      "oneof", JSOneofName(oneof),
+      "upcase", ToEnumCase(oneof->name()));
+
+  for (int i = 0; i < oneof->field_count(); i++) {
+    if (IgnoreField(oneof->field(i))) {
+      continue;
+    }
+
+    printer->Print(
+        ",\n"
+        "  $upcase$: $number$",
+        "upcase", ToEnumCase(oneof->field(i)->name()),
+        "number", JSFieldIndex(oneof->field(i)));
+  }
+
+  printer->Print(
+      "\n"
+      "};\n"
+      "\n"
+      "/**\n"
+      " * @return {$class$.$oneof$Case}\n"
+      " */\n"
+      "$class$.prototype.get$oneof$Case = function() {\n"
+      "  return /** @type {$class$.$oneof$Case} */(jspb.Message."
+      "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n"
+      "};\n"
+      "\n",
+      "class", GetPath(options, oneof->containing_type()),
+      "oneof", JSOneofName(oneof),
+      "oneofindex", JSOneofIndex(oneof));
+}
+
+void Generator::GenerateClassToObject(const GeneratorOptions& options,
+                                      io::Printer* printer,
+                                      const Descriptor* desc) const {
+  printer->Print(
+      "\n"
+      "\n"
+      "if (jspb.Message.GENERATE_TO_OBJECT) {\n"
+      "/**\n"
+      " * Creates an object representation of this proto suitable for use in "
+      "Soy templates.\n"
+      " * Field names that are reserved in JavaScript and will be renamed to "
+      "pb_name.\n"
+      " * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.\n"
+      " * For the list of reserved names please see:\n"
+      " *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.\n"
+      " * @param {boolean=} opt_includeInstance Whether to include the JSPB "
+      "instance\n"
+      " *     for transitional soy proto support: http://goto/soy-param-"
+      "migration\n"
+      " * @return {!Object}\n"
+      " */\n"
+      "$classname$.prototype.toObject = function(opt_includeInstance) {\n"
+      "  return $classname$.toObject(opt_includeInstance, this);\n"
+      "};\n"
+      "\n"
+      "\n"
+      "/**\n"
+      " * Static version of the {@see toObject} method.\n"
+      " * @param {boolean|undefined} includeInstance Whether to include the "
+      "JSPB\n"
+      " *     instance for transitional soy proto support:\n"
+      " *     http://goto/soy-param-migration\n"
+      " * @param {!$classname$} msg The msg instance to transform.\n"
+      " * @return {!Object}\n"
+      " */\n"
+      "$classname$.toObject = function(includeInstance, msg) {\n"
+      "  var f, obj = {",
+      "classname", GetPath(options, desc));
+
+  bool first = true;
+  for (int i = 0; i < desc->field_count(); i++) {
+    const FieldDescriptor* field = desc->field(i);
+    if (IgnoreField(field)) {
+      continue;
+    }
+
+    if (!first) {
+      printer->Print(",\n    ");
+    } else {
+      printer->Print("\n    ");
+      first = false;
+    }
+
+    GenerateClassFieldToObject(options, printer, field);
+  }
+
+  if (!first) {
+    printer->Print("\n  };\n\n");
+  } else {
+    printer->Print("\n\n  };\n\n");
+  }
+
+  if (IsExtendable(desc)) {
+    printer->Print(
+        "  jspb.Message.toObjectExtension(/** @type {!jspb.Message} */ (msg), "
+        "obj,\n"
+        "      $extObject$, $class$.prototype.getExtension,\n"
+        "      includeInstance);\n",
+        "extObject", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetPath(options, desc));
+  }
+
+  printer->Print(
+      "  if (includeInstance) {\n"
+      "    obj.$$jspbMessageInstance = msg;\n"
+      "  }\n"
+      "  return obj;\n"
+      "};\n"
+      "}\n"
+      "\n"
+      "\n",
+      "classname", GetPath(options, desc));
+}
+
+void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
+                                           io::Printer* printer,
+                                           const FieldDescriptor* field) const {
+  printer->Print("$fieldname$: ",
+                 "fieldname", JSObjectFieldName(field));
+
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    // Message field.
+    if (field->is_repeated()) {
+      {
+        printer->Print("jspb.Message.toObjectList(msg.get$getter$(),\n"
+                       "    $type$.toObject, includeInstance)",
+                       "getter", JSGetterName(field),
+                       "type", SubmessageTypeRef(options, field));
+      }
+    } else {
+      printer->Print("(f = msg.get$getter$()) && "
+                     "$type$.toObject(includeInstance, f)",
+                     "getter", JSGetterName(field),
+                     "type", SubmessageTypeRef(options, field));
+    }
+  } else {
+    // Simple field (singular or repeated).
+    if ((!HasFieldPresence(field) && !field->is_repeated()) ||
+        field->type() == FieldDescriptor::TYPE_BYTES) {
+      // Delegate to the generated get<field>() method in order not to duplicate
+      // the proto3-field-default-value or byte-coercion logic here.
+      printer->Print("msg.get$getter$()",
+                     "getter", JSGetterName(field, BYTES_B64));
+    } else {
+      if (field->has_default_value()) {
+        printer->Print("jspb.Message.getField(msg, $index$) == null ? "
+                       "$defaultValue$ : ",
+                       "index", JSFieldIndex(field),
+                       "defaultValue", JSFieldDefault(field));
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+          field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+        if (field->is_repeated()) {
+          printer->Print("jspb.Message.getRepeatedFloatingPointField("
+                         "msg, $index$)",
+                         "index", JSFieldIndex(field));
+        } else if (field->is_optional() && !field->has_default_value()) {
+          printer->Print("jspb.Message.getOptionalFloatingPointField("
+                         "msg, $index$)",
+                         "index", JSFieldIndex(field));
+        } else {
+          // Convert "NaN" to NaN.
+          printer->Print("+jspb.Message.getField(msg, $index$)",
+                         "index", JSFieldIndex(field));
+        }
+      } else {
+        printer->Print("jspb.Message.getField(msg, $index$)",
+                       "index", JSFieldIndex(field));
+      }
+    }
+  }
+}
+
+void Generator::GenerateClassFromObject(const GeneratorOptions& options,
+                                        io::Printer* printer,
+                                        const Descriptor* desc) const {
+  printer->Print(
+      "if (jspb.Message.GENERATE_FROM_OBJECT) {\n"
+      "/**\n"
+      " * Loads data from an object into a new instance of this proto.\n"
+      " * @param {!Object} obj The object representation of this proto to\n"
+      " *     load the data from.\n"
+      " * @return {!$classname$}\n"
+      " */\n"
+      "$classname$.fromObject = function(obj) {\n"
+      "  var f, msg = new $classname$();\n",
+      "classname", GetPath(options, desc));
+
+  for (int i = 0; i < desc->field_count(); i++) {
+    const FieldDescriptor* field = desc->field(i);
+    GenerateClassFieldFromObject(options, printer, field);
+  }
+
+  printer->Print(
+      "  return msg;\n"
+      "};\n"
+      "}\n");
+}
+
+void Generator::GenerateClassFieldFromObject(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const FieldDescriptor* field) const {
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    // Message field (singular or repeated)
+    if (field->is_repeated()) {
+      {
+        printer->Print(
+            "  goog.isDef(obj.$name$) && "
+            "jspb.Message.setRepeatedWrapperField(\n"
+            "      msg, $index$, goog.array.map(obj.$name$, function(i) {\n"
+            "        return $fieldclass$.fromObject(i);\n"
+            "      }));\n",
+            "name", JSObjectFieldName(field),
+            "index", JSFieldIndex(field),
+            "fieldclass", SubmessageTypeRef(options, field));
+      }
+    } else {
+      printer->Print(
+          "  goog.isDef(obj.$name$) && jspb.Message.setWrapperField(\n"
+          "      msg, $index$, $fieldclass$.fromObject(obj.$name$));\n",
+          "name", JSObjectFieldName(field),
+          "index", JSFieldIndex(field),
+          "fieldclass", SubmessageTypeRef(options, field));
+    }
+  } else {
+    // Simple (primitive) field.
+    printer->Print(
+        "  goog.isDef(obj.$name$) && jspb.Message.setField(msg, $index$, "
+        "obj.$name$);\n",
+        "name", JSObjectFieldName(field),
+        "index", JSFieldIndex(field));
+  }
+}
+
+void Generator::GenerateClassClone(const GeneratorOptions& options,
+                                   io::Printer* printer,
+                                   const Descriptor* desc) const {
+  printer->Print(
+      "/**\n"
+      " * Creates a deep clone of this proto. No data is shared with the "
+      "original.\n"
+      " * @return {!$name$} The clone.\n"
+      " */\n"
+      "$name$.prototype.cloneMessage = function() {\n"
+      "  return /** @type {!$name$} */ (jspb.Message.cloneMessage(this));\n"
+      "};\n\n\n",
+      "name", GetPath(options, desc));
+}
+
+void Generator::GenerateClassRegistration(const GeneratorOptions& options,
+                                          io::Printer* printer,
+                                          const Descriptor* desc) const {
+  // Register any extensions defined inside this message type.
+  for (int i = 0; i < desc->extension_count(); i++) {
+    const FieldDescriptor* extension = desc->extension(i);
+    if (ShouldGenerateExtension(extension)) {
+      GenerateExtension(options, printer, extension);
+    }
+  }
+
+}
+
+void Generator::GenerateClassFields(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const Descriptor* desc) const {
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (!IgnoreField(desc->field(i))) {
+      GenerateClassField(options, printer, desc->field(i));
+    }
+  }
+}
+
+void GenerateBytesWrapper(const GeneratorOptions& options,
+                          io::Printer* printer,
+                          const FieldDescriptor* field,
+                          BytesMode bytes_mode) {
+  string type =
+      JSFieldTypeAnnotation(options, field,
+                            /* force_optional = */ false,
+                            /* force_present = */ !HasFieldPresence(field),
+                            /* singular_if_not_packed = */ false,
+                            bytes_mode);
+  printer->Print(
+      "/**\n"
+      " * $fielddef$\n"
+      "$comment$"
+      " * This is a type-conversion wrapper around `get$defname$()`\n"
+      " * @return {$type$}\n"
+      " */\n"
+      "$class$.prototype.get$name$ = function() {\n"
+      "  return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n"
+      "      this.get$defname$()));\n"
+      "};\n"
+      "\n"
+      "\n",
+      "fielddef", FieldDefinition(options, field),
+      "comment", FieldComments(field, bytes_mode),
+      "type", type,
+      "class", GetPath(options, field->containing_type()),
+      "name", JSGetterName(field, bytes_mode),
+      "list", field->is_repeated() ? "List" : "",
+      "suffix", JSByteGetterSuffix(bytes_mode),
+      "defname", JSGetterName(field, BYTES_DEFAULT));
+}
+
+
+void Generator::GenerateClassField(const GeneratorOptions& options,
+                                   io::Printer* printer,
+                                   const FieldDescriptor* field) const {
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    printer->Print(
+        "/**\n"
+        " * $fielddef$\n"
+        "$comment$"
+        " * @return {$type$}\n"
+        " */\n",
+        "fielddef", FieldDefinition(options, field),
+        "comment", FieldComments(field, BYTES_DEFAULT),
+        "type", JSFieldTypeAnnotation(options, field,
+                                      /* force_optional = */ false,
+                                      /* force_present = */ false,
+                                      /* singular_if_not_packed = */ false));
+    printer->Print(
+        "$class$.prototype.get$name$ = function() {\n"
+        "  return /** @type{$type$} */ (\n"
+        "    jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, "
+        "$index$$required$));\n"
+        "};\n"
+        "\n"
+        "\n",
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field),
+        "type", JSFieldTypeAnnotation(options, field,
+                                      /* force_optional = */ false,
+                                      /* force_present = */ false,
+                                      /* singular_if_not_packed = */ false),
+        "rpt", (field->is_repeated() ? "Repeated" : ""),
+        "index", JSFieldIndex(field),
+        "wrapperclass", SubmessageTypeRef(options, field),
+        "required", (field->label() == FieldDescriptor::LABEL_REQUIRED ?
+                     ", 1" : ""));
+    printer->Print(
+        "/** @param {$optionaltype$} value $returndoc$ */\n"
+        "$class$.prototype.set$name$ = function(value) {\n"
+        "  jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
+        "optionaltype",
+        JSFieldTypeAnnotation(options, field,
+                              /* force_optional = */ true,
+                              /* force_present = */ false,
+                              /* singular_if_not_packed = */ false),
+        "returndoc", JSReturnDoc(options, field),
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field),
+        "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
+        "repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+
+    printer->Print(
+        "this, $index$$oneofgroup$, value);$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "index", JSFieldIndex(field),
+        "oneofgroup", (field->containing_oneof() ?
+                       (", " + JSOneofArray(options, field)) : ""),
+        "returnvalue", JSReturnClause(field));
+
+    printer->Print(
+        "$class$.prototype.clear$name$ = function() {\n"
+        "  this.set$name$($clearedvalue$);$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field),
+        "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+        "returnvalue", JSReturnClause(field));
+
+  } else {
+    bool untyped =
+        false;
+
+    // Simple (primitive) field, either singular or repeated.
+
+    // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
+    // at this point we "lie" to non-binary users and tell the the return
+    // type is always base64 string, pending a LSC to migrate to typed getters.
+    BytesMode bytes_mode =
+        field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ?
+            BYTES_B64 : BYTES_DEFAULT;
+    string typed_annotation =
+        JSFieldTypeAnnotation(options, field,
+                              /* force_optional = */ false,
+                              /* force_present = */ !HasFieldPresence(field),
+                              /* singular_if_not_packed = */ false,
+                              /* bytes_mode = */ bytes_mode);
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * @return {?} Raw field, untyped.\n"
+          " */\n");
+    } else {
+      printer->Print(
+          "/**\n"
+          " * $fielddef$\n"
+          "$comment$"
+          " * @return {$type$}\n"
+          " */\n",
+          "fielddef", FieldDefinition(options, field),
+          "comment", FieldComments(field, bytes_mode),
+          "type", typed_annotation);
+    }
+
+    printer->Print(
+        "$class$.prototype.get$name$ = function() {\n",
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field));
+
+    if (untyped) {
+      printer->Print(
+          "  return ");
+    } else {
+      printer->Print(
+          "  return /** @type {$type$} */ (",
+          "type", typed_annotation);
+    }
+
+    // For proto3 fields without presence, use special getters that will return
+    // defaults when the field is unset, possibly constructing a value if
+    // required.
+    if (!HasFieldPresence(field) && !field->is_repeated()) {
+      printer->Print("jspb.Message.getFieldProto3(this, $index$, $default$)",
+                     "index", JSFieldIndex(field),
+                     "default", Proto3PrimitiveFieldDefault(field));
+    } else {
+      if (field->has_default_value()) {
+        printer->Print("jspb.Message.getField(this, $index$) == null ? "
+                       "$defaultValue$ : ",
+                       "index", JSFieldIndex(field),
+                       "defaultValue", JSFieldDefault(field));
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+          field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+        if (field->is_repeated()) {
+          printer->Print("jspb.Message.getRepeatedFloatingPointField("
+                         "this, $index$)",
+                         "index", JSFieldIndex(field));
+        } else if (field->is_optional() && !field->has_default_value()) {
+          printer->Print("jspb.Message.getOptionalFloatingPointField("
+                         "this, $index$)",
+                         "index", JSFieldIndex(field));
+        } else {
+          // Convert "NaN" to NaN.
+          printer->Print("+jspb.Message.getField(this, $index$)",
+                         "index", JSFieldIndex(field));
+        }
+      } else {
+        printer->Print("jspb.Message.getField(this, $index$)",
+                       "index", JSFieldIndex(field));
+      }
+    }
+
+    if (untyped) {
+      printer->Print(
+          ";\n"
+          "};\n"
+          "\n"
+          "\n");
+    } else {
+      printer->Print(
+          ");\n"
+          "};\n"
+          "\n"
+          "\n");
+    }
+
+    if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
+      GenerateBytesWrapper(options, printer, field, BYTES_B64);
+      GenerateBytesWrapper(options, printer, field, BYTES_U8);
+    }
+
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * @param {*} value $returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    } else {
+      printer->Print(
+          "/** @param {$optionaltype$} value $returndoc$ */\n",
+          "optionaltype",
+          JSFieldTypeAnnotation(options, field,
+                                /* force_optional = */ true,
+                                /* force_present = */ !HasFieldPresence(field),
+                                /* singular_if_not_packed = */ false),
+          "returndoc", JSReturnDoc(options, field));
+    }
+    printer->Print(
+        "$class$.prototype.set$name$ = function(value) {\n"
+        "  jspb.Message.set$oneoftag$Field(this, $index$",
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field),
+        "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
+        "index", JSFieldIndex(field));
+    printer->Print(
+        "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "type",
+        untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+        "typeclose", untyped ? ")" : "",
+        "oneofgroup",
+        (field->containing_oneof() ? (", " + JSOneofArray(options, field))
+                                   : ""),
+        "returnvalue", JSReturnClause(field), "rptvalueinit",
+        (field->is_repeated() ? " || []" : ""));
+
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * Clears the value. $returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    }
+
+    if (HasFieldPresence(field)) {
+      printer->Print(
+          "$class$.prototype.clear$name$ = function() {\n"
+          "  jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ",
+          "class", GetPath(options, field->containing_type()),
+          "name", JSGetterName(field),
+          "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
+          "oneofgroup", (field->containing_oneof() ?
+                         (", " + JSOneofArray(options, field)) : ""),
+          "index", JSFieldIndex(field));
+      printer->Print(
+          "$clearedvalue$);$returnvalue$\n"
+          "};\n"
+          "\n"
+          "\n",
+          "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+          "returnvalue", JSReturnClause(field));
+    }
+  }
+}
+
+void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
+                                                io::Printer* printer,
+                                                const Descriptor* desc) const {
+  if (IsExtendable(desc)) {
+    printer->Print(
+        "\n"
+        "/**\n"
+        " * The extensions registered with this message class. This is a "
+        "map of\n"
+        " * extension field number to fieldInfo object.\n"
+        " *\n"
+        " * For example:\n"
+        " *     { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, "
+        "ctor: proto.example.MyMessage} }\n"
+        " *\n"
+        " * fieldName contains the JsCompiler renamed field name property "
+        "so that it\n"
+        " * works in OPTIMIZED mode.\n"
+        " *\n"
+        " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
+        " */\n"
+        "$class$.extensions = {};\n"
+        "\n",
+        "class", GetPath(options, desc));
+  }
+}
+
+
+void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
+                                               io::Printer* printer,
+                                               const Descriptor* desc) const {
+  // TODO(cfallin): Handle lazy decoding when requested by field option and/or
+  // by default for 'bytes' fields and packed repeated fields.
+
+  printer->Print(
+      "/**\n"
+      " * Deserializes binary data (in protobuf wire format).\n"
+      " * @param {jspb.ByteSource} bytes The bytes to deserialize.\n"
+      " * @return {!$class$}\n"
+      " */\n"
+      "$class$.deserializeBinary = function(bytes) {\n"
+      "  var reader = new jspb.BinaryReader(bytes);\n"
+      "  var msg = new $class$;\n"
+      "  return $class$.deserializeBinaryFromReader(msg, reader);\n"
+      "};\n"
+      "\n"
+      "\n"
+      "/**\n"
+      " * Deserializes binary data (in protobuf wire format) from the\n"
+      " * given reader into the given message object.\n"
+      " * @param {!$class$} msg The message object to deserialize into.\n"
+      " * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n"
+      " * @return {!$class$}\n"
+      " */\n"
+      "$class$.deserializeBinaryFromReader = function(msg, reader) {\n"
+      "  while (reader.nextField()) {\n"
+      "    if (reader.isEndGroup()) {\n"
+      "      break;\n"
+      "    }\n"
+      "    var field = reader.getFieldNumber();\n"
+      "    switch (field) {\n",
+      "class", GetPath(options, desc));
+
+  for (int i = 0; i < desc->field_count(); i++) {
+    GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
+  }
+
+  printer->Print(
+      "    default:\n");
+  if (IsExtendable(desc)) {
+    printer->Print(
+        "      jspb.Message.readBinaryExtension(msg, reader, $extobj$,\n"
+        "        $class$.prototype.getExtension,\n"
+        "        $class$.prototype.setExtension);\n"
+        "      break;\n",
+        "extobj", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetPath(options, desc));
+  } else {
+    printer->Print(
+        "      reader.skipField();\n"
+        "      break;\n");
+  }
+
+  printer->Print(
+      "    }\n"
+      "  }\n"
+      "  return msg;\n"
+      "};\n"
+      "\n"
+      "\n");
+}
+
+void Generator::GenerateClassDeserializeBinaryField(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const FieldDescriptor* field) const {
+
+  printer->Print("    case $num$:\n",
+                 "num", SimpleItoa(field->number()));
+
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    printer->Print(
+        "      var value = new $fieldclass$;\n"
+        "      reader.read$msgOrGroup$($grpfield$value,"
+        "$fieldclass$.deserializeBinaryFromReader);\n",
+        "fieldclass", SubmessageTypeRef(options, field),
+        "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ?
+                      "Group" : "Message",
+        "grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ?
+                    (SimpleItoa(field->number()) + ", ") : "");
+  } else {
+    printer->Print(
+        "      var value = /** @type {$fieldtype$} */ (reader.$reader$());\n",
+        "fieldtype", JSFieldTypeAnnotation(options, field, false, true,
+                                           /* singular_if_not_packed = */ true,
+                                           BYTES_U8),
+        "reader", JSBinaryReaderMethodName(field));
+  }
+
+  if (field->is_repeated() && !field->is_packed()) {
+    // Repeated fields receive a |value| one at at a time; append to array
+    // returned by get$name$(). Annoyingly, we have to call 'set' after
+    // changing the array.
+    printer->Print("      msg.get$name$().push(value);\n", "name",
+                   JSGetterName(field));
+    printer->Print("      msg.set$name$(msg.get$name$());\n", "name",
+                   JSGetterName(field));
+  } else {
+    // Singular fields, and packed repeated fields, receive a |value| either as
+    // the field's value or as the array of all the field's values; set this as
+    // the field's value directly.
+    printer->Print(
+        "      msg.set$name$(value);\n",
+        "name", JSGetterName(field));
+  }
+
+  printer->Print("      break;\n");
+}
+
+void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
+                                             io::Printer* printer,
+                                             const Descriptor* desc) const {
+  printer->Print(
+      "/**\n"
+      " * Class method variant: serializes the given message to binary data\n"
+      " * (in protobuf wire format), writing to the given BinaryWriter.\n"
+      " * @param {!$class$} message\n"
+      " * @param {!jspb.BinaryWriter} writer\n"
+      " */\n"
+      "$class$.serializeBinaryToWriter = function(message, "
+      "writer) {\n"
+      "  message.serializeBinaryToWriter(writer);\n"
+      "};\n"
+      "\n"
+      "\n"
+      "/**\n"
+      " * Serializes the message to binary data (in protobuf wire format).\n"
+      " * @return {!Uint8Array}\n"
+      " */\n"
+      "$class$.prototype.serializeBinary = function() {\n"
+      "  var writer = new jspb.BinaryWriter();\n"
+      "  this.serializeBinaryToWriter(writer);\n"
+      "  return writer.getResultBuffer();\n"
+      "};\n"
+      "\n"
+      "\n"
+      "/**\n"
+      " * Serializes the message to binary data (in protobuf wire format),\n"
+      " * writing to the given BinaryWriter.\n"
+      " * @param {!jspb.BinaryWriter} writer\n"
+      " */\n"
+      "$class$.prototype.serializeBinaryToWriter = function (writer) {\n"
+      "  var f = undefined;\n",
+      "class", GetPath(options, desc));
+
+  for (int i = 0; i < desc->field_count(); i++) {
+    GenerateClassSerializeBinaryField(options, printer, desc->field(i));
+  }
+
+  if (IsExtendable(desc)) {
+    printer->Print(
+        "  jspb.Message.serializeBinaryExtensions(this, writer, $extobj$,\n"
+        "    $class$.prototype.getExtension);\n",
+        "extobj", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetPath(options, desc));
+  }
+
+  printer->Print(
+      "};\n"
+      "\n"
+      "\n");
+}
+
+void Generator::GenerateClassSerializeBinaryField(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const FieldDescriptor* field) const {
+  printer->Print(
+      "  f = this.get$name$();\n",
+      "name", JSGetterName(field, BYTES_U8));
+
+  if (field->is_repeated()) {
+    printer->Print(
+        "  if (f.length > 0) {\n");
+  } else {
+    if (HasFieldPresence(field)) {
+      printer->Print(
+          "  if (f != null) {\n");
+    } else {
+      // No field presence: serialize onto the wire only if value is
+      // non-default.  Defaults are documented here:
+      // https://goto.google.com/lhdfm
+      switch (field->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_INT32:
+        case FieldDescriptor::CPPTYPE_INT64:
+        case FieldDescriptor::CPPTYPE_UINT32:
+        case FieldDescriptor::CPPTYPE_UINT64: {
+          {
+            printer->Print("  if (f !== 0) {\n");
+          }
+          break;
+        }
+
+        case FieldDescriptor::CPPTYPE_ENUM:
+        case FieldDescriptor::CPPTYPE_FLOAT:
+        case FieldDescriptor::CPPTYPE_DOUBLE:
+          printer->Print(
+              "  if (f !== 0.0) {\n");
+          break;
+        case FieldDescriptor::CPPTYPE_BOOL:
+          printer->Print(
+              "  if (f) {\n");
+          break;
+        case FieldDescriptor::CPPTYPE_STRING:
+          printer->Print(
+              "  if (f.length > 0) {\n");
+          break;
+        default:
+          assert(false);
+          break;
+      }
+    }
+  }
+
+  printer->Print(
+      "    writer.$writer$(\n"
+      "      $index$,\n"
+      "      f",
+      "writer", JSBinaryWriterMethodName(field),
+      "index", SimpleItoa(field->number()));
+
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    printer->Print(
+        ",\n"
+        "      $submsg$.serializeBinaryToWriter\n",
+        "submsg", SubmessageTypeRef(options, field));
+  } else {
+    printer->Print("\n");
+  }
+  printer->Print(
+      "    );\n"
+      "  }\n");
+}
+
+void Generator::GenerateEnum(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const EnumDescriptor* enumdesc) const {
+  printer->Print(
+      "/**\n"
+      " * @enum {number}\n"
+      " */\n"
+      "$name$ = {\n",
+      "name", GetPath(options, enumdesc));
+
+  for (int i = 0; i < enumdesc->value_count(); i++) {
+    const EnumValueDescriptor* value = enumdesc->value(i);
+    printer->Print(
+        "  $name$: $value$$comma$\n",
+        "name", ToEnumCase(value->name()),
+        "value", SimpleItoa(value->number()),
+        "comma", (i == enumdesc->value_count() - 1) ? "" : ",");
+  }
+
+  printer->Print(
+      "};\n"
+      "\n");
+}
+
+void Generator::GenerateExtension(const GeneratorOptions& options,
+                                  io::Printer* printer,
+                                  const FieldDescriptor* field) const {
+  string extension_scope =
+      (field->extension_scope() ?
+       GetPath(options, field->extension_scope()) :
+       GetPath(options, field->file()));
+
+  printer->Print(
+      "\n"
+      "/**\n"
+      " * A tuple of {field number, class constructor} for the extension\n"
+      " * field named `$name$`.\n"
+      " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n"
+      " */\n"
+      "$class$.$name$ = new jspb.ExtensionFieldInfo(\n",
+      "name", JSObjectFieldName(field),
+      "class", extension_scope,
+      "extensionType", JSFieldTypeAnnotation(
+          options, field,
+          /* force_optional = */ false,
+          /* force_present = */ true,
+          /* singular_if_not_packed = */ false));
+  printer->Print(
+      "    $index$,\n"
+      "    {$name$: 0},\n"
+      "    $ctor$,\n"
+      "     /** @type {?function((boolean|undefined),!jspb.Message=): "
+      "!Object} */ (\n"
+      "         $toObject$),\n"
+      "    $repeated$",
+      "index", SimpleItoa(field->number()),
+      "name", JSObjectFieldName(field),
+      "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
+               SubmessageTypeRef(options, field) : string("null")),
+      "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
+                   (SubmessageTypeRef(options, field) + ".toObject") :
+                   string("null")),
+      "repeated", (field->is_repeated() ? "1" : "0"));
+
+  if (options.binary) {
+    printer->Print(
+        ",\n"
+        "    jspb.BinaryReader.prototype.$binaryReaderFn$,\n"
+        "    jspb.BinaryWriter.prototype.$binaryWriterFn$,\n"
+        "    $binaryMessageSerializeFn$,\n"
+        "    $binaryMessageDeserializeFn$,\n"
+        "    $isPacked$);\n",
+        "binaryReaderFn", JSBinaryReaderMethodName(field),
+        "binaryWriterFn", JSBinaryWriterMethodName(field),
+        "binaryMessageSerializeFn",
+        (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
+        (SubmessageTypeRef(options, field) +
+         ".serializeBinaryToWriter") : "null",
+        "binaryMessageDeserializeFn",
+        (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
+        (SubmessageTypeRef(options, field) +
+         ".deserializeBinaryFromReader") : "null",
+        "isPacked", (field->is_packed() ? "true" : "false"));
+  } else {
+    printer->Print(");\n");
+  }
+
+  printer->Print(
+      "// This registers the extension field with the extended class, so that\n"
+      "// toObject() will function correctly.\n"
+      "$extendName$[$index$] = $class$.$name$;\n"
+      "\n",
+      "extendName", JSExtensionsObjectName(options, field->file(),
+                                           field->containing_type()),
+      "index", SimpleItoa(field->number()),
+      "class", extension_scope,
+      "name", JSObjectFieldName(field));
+}
+
+bool GeneratorOptions::ParseFromOptions(
+    const vector< pair< string, string > >& options,
+    string* error) {
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "add_require_for_enums") {
+      if (options[i].second != "") {
+        *error = "Unexpected option value for add_require_for_enums";
+        return false;
+      }
+      add_require_for_enums = true;
+    } else if (options[i].first == "binary") {
+      if (options[i].second != "") {
+        *error = "Unexpected option value for binary";
+        return false;
+      }
+      binary = true;
+    } else if (options[i].first == "testonly") {
+      if (options[i].second != "") {
+        *error = "Unexpected option value for testonly";
+        return false;
+      }
+      testonly = true;
+    } else if (options[i].first == "error_on_name_conflict") {
+      if (options[i].second != "") {
+        *error = "Unexpected option value for error_on_name_conflict";
+        return false;
+      }
+      error_on_name_conflict = true;
+    } else if (options[i].first == "output_dir") {
+      output_dir = options[i].second;
+    } else if (options[i].first == "namespace_prefix") {
+      namespace_prefix = options[i].second;
+    } else if (options[i].first == "library") {
+      library = options[i].second;
+    } else if (options[i].first == "import_style") {
+      if (options[i].second == "closure") {
+        import_style = IMPORT_CLOSURE;
+      } else if (options[i].second == "commonjs") {
+        import_style = IMPORT_COMMONJS;
+      } else if (options[i].second == "browser") {
+        import_style = IMPORT_BROWSER;
+      } else if (options[i].second == "es6") {
+        import_style = IMPORT_ES6;
+      } else {
+        *error = "Unknown import style " + options[i].second + ", expected " +
+                 "one of: closure, commonjs, browser, es6.";
+      }
+    } else {
+      // Assume any other option is an output directory, as long as it is a bare
+      // `key` rather than a `key=value` option.
+      if (options[i].second != "") {
+        *error = "Unknown option: " + options[i].first;
+        return false;
+      }
+      output_dir = options[i].first;
+    }
+  }
+
+  if (!library.empty() && import_style != IMPORT_CLOSURE) {
+    *error = "The library option should only be used for "
+             "import_style=closure";
+  }
+
+  return true;
+}
+
+void Generator::GenerateFilesInDepOrder(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const vector<const FileDescriptor*>& files) const {
+  // Build a std::set over all files so that the DFS can detect when it recurses
+  // into a dep not specified in the user's command line.
+  std::set<const FileDescriptor*> all_files(files.begin(), files.end());
+  // Track the in-progress set of files that have been generated already.
+  std::set<const FileDescriptor*> generated;
+  for (int i = 0; i < files.size(); i++) {
+    GenerateFileAndDeps(options, printer, files[i], &all_files, &generated);
+  }
+}
+
+void Generator::GenerateFileAndDeps(
+    const GeneratorOptions& options,
+    io::Printer* printer,
+    const FileDescriptor* root,
+    std::set<const FileDescriptor*>* all_files,
+    std::set<const FileDescriptor*>* generated) const {
+  // Skip if already generated.
+  if (generated->find(root) != generated->end()) {
+    return;
+  }
+  generated->insert(root);
+
+  // Generate all dependencies before this file's content.
+  for (int i = 0; i < root->dependency_count(); i++) {
+    const FileDescriptor* dep = root->dependency(i);
+    GenerateFileAndDeps(options, printer, dep, all_files, generated);
+  }
+
+  // Generate this file's content.  Only generate if the file is part of the
+  // original set requested to be generated; i.e., don't take all transitive
+  // deps down to the roots.
+  if (all_files->find(root) != all_files->end()) {
+    GenerateClassesAndEnums(options, printer, root);
+  }
+}
+
+void Generator::GenerateFile(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const FileDescriptor* file) const {
+  GenerateHeader(options, printer);
+
+  // Generate "require" statements.
+  if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+    printer->Print("var jspb = require('google-protobuf');\n");
+    printer->Print("var goog = jspb;\n");
+    printer->Print("var global = Function('return this')();\n\n");
+
+    for (int i = 0; i < file->dependency_count(); i++) {
+      const string& name = file->dependency(i)->name();
+      printer->Print(
+          "var $alias$ = require('$file$');\n",
+          "alias", ModuleAlias(name),
+          "file", GetRootPath(file->name()) + GetJSFilename(name));
+    }
+  }
+
+  // We aren't using Closure's import system, but we use goog.exportSymbol()
+  // to construct the expected tree of objects, eg.
+  //
+  //   goog.exportSymbol('foo.bar.Baz', null, this);
+  //
+  //   // Later generated code expects foo.bar = {} to exist:
+  //   foo.bar.Baz = function() { /* ... */ }
+  set<string> provided;
+
+  // Cover the case where this file declares extensions but no messages.
+  // This will ensure that the file-level object will be declared to hold
+  // the extensions.
+  for (int i = 0; i < file->extension_count(); i++) {
+    provided.insert(file->extension(i)->full_name());
+  }
+
+  FindProvidesForFile(options, printer, file, &provided);
+  for (std::set<string>::iterator it = provided.begin();
+       it != provided.end(); ++it) {
+    printer->Print("goog.exportSymbol('$name$', null, global);\n",
+                   "name", *it);
+  }
+
+  GenerateClassesAndEnums(options, printer, file);
+
+  // Extensions nested inside messages are emitted inside
+  // GenerateClassesAndEnums().
+  for (int i = 0; i < file->extension_count(); i++) {
+    GenerateExtension(options, printer, file->extension(i));
+  }
+
+  if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+    printer->Print("goog.object.extend(exports, $package$);\n",
+                   "package", GetPath(options, file));
+  }
+}
+
+bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
+                            const string& parameter,
+                            GeneratorContext* context,
+                            string* error) const {
+  vector< pair< string, string > > option_pairs;
+  ParseGeneratorParameter(parameter, &option_pairs);
+  GeneratorOptions options;
+  if (!options.ParseFromOptions(option_pairs, error)) {
+    return false;
+  }
+
+
+  // There are three schemes for where output files go:
+  //
+  // - import_style = IMPORT_CLOSURE, library non-empty: all output in one file
+  // - import_style = IMPORT_CLOSURE, library empty: one output file per type
+  // - import_style != IMPORT_CLOSURE: one output file per .proto file
+  if (options.import_style == GeneratorOptions::IMPORT_CLOSURE &&
+      options.library != "") {
+    // All output should go in a single file.
+    string filename = options.output_dir + "/" + options.library + ".js";
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+    GOOGLE_CHECK(output.get());
+    io::Printer printer(output.get(), '$');
+
+    // Pull out all extensions -- we need these to generate all
+    // provides/requires.
+    vector<const FieldDescriptor*> extensions;
+    for (int i = 0; i < files.size(); i++) {
+      for (int j = 0; j < files[i]->extension_count(); j++) {
+        const FieldDescriptor* extension = files[i]->extension(j);
+        extensions.push_back(extension);
+      }
+    }
+
+    GenerateHeader(options, &printer);
+
+    std::set<string> provided;
+    FindProvides(options, &printer, files, &provided);
+    FindProvidesForFields(options, &printer, extensions, &provided);
+    GenerateProvides(options, &printer, &provided);
+    GenerateTestOnly(options, &printer);
+    GenerateRequiresForLibrary(options, &printer, files, &provided);
+
+    GenerateFilesInDepOrder(options, &printer, files);
+
+    for (int i = 0; i < extensions.size(); i++) {
+      if (ShouldGenerateExtension(extensions[i])) {
+        GenerateExtension(options, &printer, extensions[i]);
+      }
+    }
+
+    if (printer.failed()) {
+      return false;
+    }
+  } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
+    set<const void*> allowed_set;
+    if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) {
+      return false;
+    }
+
+    for (int i = 0; i < files.size(); i++) {
+      const FileDescriptor* file = files[i];
+      for (int j = 0; j < file->message_type_count(); j++) {
+        const Descriptor* desc = file->message_type(j);
+        if (allowed_set.count(desc) == 0) {
+          continue;
+        }
+
+        string filename = GetMessageFileName(options, desc);
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+            context->Open(filename));
+        GOOGLE_CHECK(output.get());
+        io::Printer printer(output.get(), '$');
+
+        GenerateHeader(options, &printer);
+
+        std::set<string> provided;
+        FindProvidesForMessage(options, &printer, desc, &provided);
+        GenerateProvides(options, &printer, &provided);
+        GenerateTestOnly(options, &printer);
+        GenerateRequiresForMessage(options, &printer, desc, &provided);
+
+        GenerateClass(options, &printer, desc);
+
+        if (printer.failed()) {
+          return false;
+        }
+      }
+      for (int j = 0; j < file->enum_type_count(); j++) {
+        const EnumDescriptor* enumdesc = file->enum_type(j);
+        if (allowed_set.count(enumdesc) == 0) {
+          continue;
+        }
+
+        string filename = GetEnumFileName(options, enumdesc);
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+            context->Open(filename));
+        GOOGLE_CHECK(output.get());
+        io::Printer printer(output.get(), '$');
+
+        GenerateHeader(options, &printer);
+
+        std::set<string> provided;
+        FindProvidesForEnum(options, &printer, enumdesc, &provided);
+        GenerateProvides(options, &printer, &provided);
+        GenerateTestOnly(options, &printer);
+
+        GenerateEnum(options, &printer, enumdesc);
+
+        if (printer.failed()) {
+          return false;
+        }
+      }
+      // File-level extensions (message-level extensions are generated under
+      // the enclosing message).
+      if (allowed_set.count(file) == 1) {
+        string filename = GetExtensionFileName(options, file);
+
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+            context->Open(filename));
+        GOOGLE_CHECK(output.get());
+        io::Printer printer(output.get(), '$');
+
+        GenerateHeader(options, &printer);
+
+        std::set<string> provided;
+        vector<const FieldDescriptor*> fields;
+
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            fields.push_back(files[i]->extension(j));
+          }
+        }
+
+        FindProvidesForFields(options, &printer, fields, &provided);
+        GenerateProvides(options, &printer, &provided);
+        GenerateTestOnly(options, &printer);
+        GenerateRequiresForExtensions(options, &printer, fields, &provided);
+
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            GenerateExtension(options, &printer, files[i]->extension(j));
+          }
+        }
+      }
+    }
+  } else {
+    // Generate one output file per input (.proto) file.
+
+    for (int i = 0; i < files.size(); i++) {
+      const google::protobuf::FileDescriptor* file = files[i];
+
+      string filename = options.output_dir + "/" + GetJSFilename(file->name());
+      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+      GOOGLE_CHECK(output.get());
+      io::Printer printer(output.get(), '$');
+
+      GenerateFile(options, &printer, file);
+
+      if (printer.failed()) {
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+}  // namespace js
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.h
new file mode 100755
index 0000000..6fd7ca5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/js/js_generator.h
@@ -0,0 +1,281 @@
+// 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_COMPILER_JS_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
+
+#include <string>
+#include <set>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class OneofDescriptor;
+class FileDescriptor;
+
+namespace io { class Printer; }
+
+namespace compiler {
+namespace js {
+
+struct GeneratorOptions {
+  // Add a `goog.requires()` call for each enum type used. If not set, a forward
+  // declaration with `goog.forwardDeclare` is produced instead.
+  bool add_require_for_enums;
+  // Set this as a test-only module via `goog.setTestOnly();`.
+  bool testonly;
+  // Output path.
+  string output_dir;
+  // Namespace prefix.
+  string namespace_prefix;
+  // Create a library with name <name>_lib.js rather than a separate .js file
+  // per type?
+  string library;
+  // Error if there are two types that would generate the same output file?
+  bool error_on_name_conflict;
+  // Enable binary-format support?
+  bool binary;
+  // What style of imports should be used.
+  enum ImportStyle {
+    IMPORT_CLOSURE,    // goog.require()
+    IMPORT_COMMONJS,   // require()
+    IMPORT_BROWSER,    // no import statements
+    IMPORT_ES6,        // import { member } from ''
+  } import_style;
+
+  GeneratorOptions()
+      : add_require_for_enums(false),
+        testonly(false),
+        output_dir("."),
+        namespace_prefix(""),
+        library(""),
+        error_on_name_conflict(false),
+        binary(false),
+        import_style(IMPORT_CLOSURE) {}
+
+  bool ParseFromOptions(
+      const vector< pair< string, string > >& options,
+      string* error);
+};
+
+class LIBPROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+  Generator() {}
+  virtual ~Generator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* context,
+                        string* error) const {
+    *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+    return false;
+  }
+
+  virtual bool HasGenerateAll() const { return true; }
+
+  virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+                           const string& parameter,
+                           GeneratorContext* context,
+                           string* error) const;
+
+ private:
+  void GenerateHeader(const GeneratorOptions& options,
+                      io::Printer* printer) const;
+
+  // Generate goog.provides() calls.
+  void FindProvides(const GeneratorOptions& options,
+                    io::Printer* printer,
+                    const vector<const FileDescriptor*>& file,
+                    std::set<string>* provided) const;
+  void FindProvidesForFile(const GeneratorOptions& options,
+                           io::Printer* printer,
+                           const FileDescriptor* file,
+                           std::set<string>* provided) const;
+  void FindProvidesForMessage(const GeneratorOptions& options,
+                              io::Printer* printer,
+                              const Descriptor* desc,
+                              std::set<string>* provided) const;
+  void FindProvidesForEnum(const GeneratorOptions& options,
+                           io::Printer* printer,
+                           const EnumDescriptor* enumdesc,
+                           std::set<string>* provided) const;
+  // For extension fields at file scope.
+  void FindProvidesForFields(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const vector<const FieldDescriptor*>& fields,
+                             std::set<string>* provided) const;
+  // Print the goog.provides() found by the methods above.
+  void GenerateProvides(const GeneratorOptions& options,
+                        io::Printer* printer,
+                        std::set<string>* provided) const;
+
+  // Generate goog.setTestOnly() if indicated.
+  void GenerateTestOnly(const GeneratorOptions& options,
+                        io::Printer* printer) const;
+
+  // Generate goog.requires() calls.
+  void GenerateRequiresForLibrary(const GeneratorOptions& options,
+                                  io::Printer* printer,
+                                  const vector<const FileDescriptor*>& files,
+                                  std::set<string>* provided) const;
+  void GenerateRequiresForMessage(const GeneratorOptions& options,
+                        io::Printer* printer,
+                        const Descriptor* desc,
+                        std::set<string>* provided) const;
+  // For extension fields at file scope.
+  void GenerateRequiresForExtensions(
+      const GeneratorOptions& options, io::Printer* printer,
+      const vector<const FieldDescriptor*>& fields,
+      std::set<string>* provided) const;
+  void GenerateRequiresImpl(const GeneratorOptions& options,
+                            io::Printer* printer,
+                            std::set<string>* required,
+                            std::set<string>* forwards,
+                            std::set<string>* provided,
+                            bool require_jspb,
+                            bool require_extension) const;
+  void FindRequiresForMessage(const GeneratorOptions& options,
+                              const Descriptor* desc,
+                              std::set<string>* required,
+                              std::set<string>* forwards,
+                              bool* have_message) const;
+  void FindRequiresForField(const GeneratorOptions& options,
+                            const FieldDescriptor* field,
+                            std::set<string>* required,
+                            std::set<string>* forwards) const;
+  void FindRequiresForExtension(const GeneratorOptions& options,
+                                const FieldDescriptor* field,
+                                std::set<string>* required,
+                                std::set<string>* forwards) const;
+
+  void GenerateFile(const GeneratorOptions& options,
+                    io::Printer* printer,
+                    const FileDescriptor* file) const;
+
+  // Generate definitions for all message classes and enums in all files,
+  // processing the files in dependence order.
+  void GenerateFilesInDepOrder(const GeneratorOptions& options,
+                               io::Printer* printer,
+                               const vector<const FileDescriptor*>& file) const;
+  // Helper for above.
+  void GenerateFileAndDeps(const GeneratorOptions& options,
+                           io::Printer* printer,
+                           const FileDescriptor* root,
+                           std::set<const FileDescriptor*>* all_files,
+                           std::set<const FileDescriptor*>* generated) const;
+
+  // Generate definitions for all message classes and enums.
+  void GenerateClassesAndEnums(const GeneratorOptions& options,
+                               io::Printer* printer,
+                               const FileDescriptor* file) const;
+
+  // Generate definition for one class.
+  void GenerateClass(const GeneratorOptions& options,
+                     io::Printer* printer,
+                     const Descriptor* desc) const;
+  void GenerateClassConstructor(const GeneratorOptions& options,
+                                io::Printer* printer,
+                                const Descriptor* desc) const;
+  void GenerateClassFieldInfo(const GeneratorOptions& options,
+                              io::Printer* printer,
+                              const Descriptor* desc) const;
+  void GenerateClassXid(const GeneratorOptions& options,
+                        io::Printer* printer,
+                        const Descriptor* desc) const;
+  void GenerateOneofCaseDefinition(const GeneratorOptions& options,
+                                   io::Printer* printer,
+                                   const OneofDescriptor* oneof) const;
+  void GenerateClassToObject(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const Descriptor* desc) const;
+  void GenerateClassFieldToObject(const GeneratorOptions& options,
+                                  io::Printer* printer,
+                                  const FieldDescriptor* field) const;
+  void GenerateClassFromObject(const GeneratorOptions& options,
+                               io::Printer* printer,
+                               const Descriptor* desc) const;
+  void GenerateClassFieldFromObject(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const FieldDescriptor* field) const;
+  void GenerateClassClone(const GeneratorOptions& options,
+                          io::Printer* printer,
+                          const Descriptor* desc) const;
+  void GenerateClassRegistration(const GeneratorOptions& options,
+                                 io::Printer* printer,
+                                 const Descriptor* desc) const;
+  void GenerateClassFields(const GeneratorOptions& options,
+                           io::Printer* printer,
+                           const Descriptor* desc) const;
+  void GenerateClassField(const GeneratorOptions& options,
+                          io::Printer* printer,
+                          const FieldDescriptor* desc) const;
+  void GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
+                                       io::Printer* printer,
+                                       const Descriptor* desc) const;
+  void GenerateClassDeserialize(const GeneratorOptions& options,
+                                io::Printer* printer,
+                                const Descriptor* desc) const;
+  void GenerateClassDeserializeBinary(const GeneratorOptions& options,
+                                      io::Printer* printer,
+                                      const Descriptor* desc) const;
+  void GenerateClassDeserializeBinaryField(const GeneratorOptions& options,
+                                           io::Printer* printer,
+                                           const FieldDescriptor* field) const;
+  void GenerateClassSerializeBinary(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const Descriptor* desc) const;
+  void GenerateClassSerializeBinaryField(const GeneratorOptions& options,
+                                         io::Printer* printer,
+                                         const FieldDescriptor* field) const;
+
+  // Generate definition for one enum.
+  void GenerateEnum(const GeneratorOptions& options,
+                    io::Printer* printer,
+                    const EnumDescriptor* enumdesc) const;
+
+  // Generate an extension definition.
+  void GenerateExtension(const GeneratorOptions& options,
+                         io::Printer* printer,
+                         const FieldDescriptor* field) const;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
+};
+
+}  // namespace js
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/main.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/main.cc
new file mode 100644
index 0000000..66ad13b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/main.cc
@@ -0,0 +1,90 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/python/python_generator.h>
+#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/javanano/javanano_generator.h>
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
+#include <google/protobuf/compiler/js/js_generator.h>
+
+int main(int argc, char* argv[]) {
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.AllowPlugins("protoc-");
+
+  // Proto2 C++
+  google::protobuf::compiler::cpp::CppGenerator cpp_generator;
+  cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
+                        "Generate C++ header and source.");
+
+  // Proto2 Java
+  google::protobuf::compiler::java::JavaGenerator java_generator;
+  cli.RegisterGenerator("--java_out", &java_generator,
+                        "Generate Java source file.");
+
+
+  // Proto2 Python
+  google::protobuf::compiler::python::Generator py_generator;
+  cli.RegisterGenerator("--python_out", &py_generator,
+                        "Generate Python source file.");
+
+  // Java Nano
+  google::protobuf::compiler::javanano::JavaNanoGenerator javanano_generator;
+  cli.RegisterGenerator("--javanano_out", &javanano_generator,
+                        "Generate Java Nano source file.");
+
+  // Ruby
+  google::protobuf::compiler::ruby::Generator rb_generator;
+  cli.RegisterGenerator("--ruby_out", &rb_generator,
+                        "Generate Ruby source file.");
+
+  // CSharp
+  google::protobuf::compiler::csharp::Generator csharp_generator;
+  cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator,
+                        "Generate C# source file.");
+
+  // Objective C
+  google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
+  cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
+                        "Generate Objective C header and source.");
+
+  // JavaScript
+  google::protobuf::compiler::js::Generator js_generator;
+  cli.RegisterGenerator("--js_out", &js_generator,
+                        "Generate JavaScript source.");
+
+  return cli.Run(argc, argv);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.cc
new file mode 100644
index 0000000..82bb342
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.cc
@@ -0,0 +1,255 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/mock_code_generator.h>
+
+#include <stdlib.h>
+#include <iostream>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Returns the list of the names of files in all_files in the form of a
+// comma-separated string.
+string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
+  vector<string> names;
+  for (int i = 0; i < all_files.size(); i++) {
+    names.push_back(all_files[i]->name());
+  }
+  return Join(names, ",");
+}
+
+static const char* kFirstInsertionPointName = "first_mock_insertion_point";
+static const char* kSecondInsertionPointName = "second_mock_insertion_point";
+static const char* kFirstInsertionPoint =
+    "# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
+static const char* kSecondInsertionPoint =
+    "  # @@protoc_insertion_point(second_mock_insertion_point) is here\n";
+
+MockCodeGenerator::MockCodeGenerator(const string& name)
+    : name_(name) {}
+
+MockCodeGenerator::~MockCodeGenerator() {}
+
+void MockCodeGenerator::ExpectGenerated(
+    const string& name,
+    const string& parameter,
+    const string& insertions,
+    const string& file,
+    const string& first_message_name,
+    const string& first_parsed_file_name,
+    const string& output_directory) {
+  string content;
+  GOOGLE_CHECK_OK(
+      File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
+                        &content, true));
+
+  vector<string> lines = Split(content, "\n", true);
+
+  while (!lines.empty() && lines.back().empty()) {
+    lines.pop_back();
+  }
+  for (int i = 0; i < lines.size(); i++) {
+    lines[i] += "\n";
+  }
+
+  vector<string> insertion_list;
+  if (!insertions.empty()) {
+    SplitStringUsing(insertions, ",", &insertion_list);
+  }
+
+  EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
+  EXPECT_EQ(GetOutputFileContent(name, parameter, file,
+                                 first_parsed_file_name, first_message_name),
+            lines[0]);
+
+  EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
+  EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
+
+  for (int i = 0; i < insertion_list.size(); i++) {
+    EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
+                                   file, file, first_message_name),
+              lines[1 + i]);
+    // Second insertion point is indented, so the inserted text should
+    // automatically be indented too.
+    EXPECT_EQ("  " + GetOutputFileContent(insertion_list[i], "second_insert",
+                                          file, file, first_message_name),
+              lines[2 + insertion_list.size() + i]);
+  }
+}
+
+bool MockCodeGenerator::Generate(
+    const FileDescriptor* file,
+    const string& parameter,
+    GeneratorContext* context,
+    string* error) const {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
+      string command = StripPrefixString(file->message_type(i)->name(),
+                                         "MockCodeGenerator_");
+      if (command == "Error") {
+        *error = "Saw message type MockCodeGenerator_Error.";
+        return false;
+      } else if (command == "Exit") {
+        std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
+        exit(123);
+      } else if (command == "Abort") {
+        std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
+        abort();
+      } else if (command == "HasSourceCodeInfo") {
+        FileDescriptorProto file_descriptor_proto;
+        file->CopySourceCodeInfoTo(&file_descriptor_proto);
+        bool has_source_code_info =
+            file_descriptor_proto.has_source_code_info() &&
+            file_descriptor_proto.source_code_info().location_size() > 0;
+        std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+                  << has_source_code_info << "." << std::endl;
+        abort();
+      } else if (command == "HasJsonName") {
+        FieldDescriptorProto field_descriptor_proto;
+        file->message_type(i)->field(0)->CopyTo(&field_descriptor_proto);
+        std::cerr << "Saw json_name: "
+                  << field_descriptor_proto.has_json_name() << std::endl;
+        abort();
+      } else {
+        GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
+      }
+    }
+  }
+
+  if (HasPrefixString(parameter, "insert=")) {
+    vector<string> insert_into;
+    SplitStringUsing(StripPrefixString(parameter, "insert="),
+                     ",", &insert_into);
+
+    for (int i = 0; i < insert_into.size(); i++) {
+      {
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
+            GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
+        io::Printer printer(output.get(), '$');
+        printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
+                                              file, context));
+        if (printer.failed()) {
+          *error = "MockCodeGenerator detected write error.";
+          return false;
+        }
+      }
+
+      {
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+            context->OpenForInsert(GetOutputFileName(insert_into[i], file),
+                                   kSecondInsertionPointName));
+        io::Printer printer(output.get(), '$');
+        printer.PrintRaw(GetOutputFileContent(name_, "second_insert",
+                                              file, context));
+        if (printer.failed()) {
+          *error = "MockCodeGenerator detected write error.";
+          return false;
+        }
+      }
+    }
+  } else {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        context->Open(GetOutputFileName(name_, file)));
+
+    io::Printer printer(output.get(), '$');
+    printer.PrintRaw(GetOutputFileContent(name_, parameter,
+                                          file, context));
+    printer.PrintRaw(kFirstInsertionPoint);
+    printer.PrintRaw(kSecondInsertionPoint);
+
+    if (printer.failed()) {
+      *error = "MockCodeGenerator detected write error.";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+                                            const FileDescriptor* file) {
+  return GetOutputFileName(generator_name, file->name());
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+                                            const string& file) {
+  return file + ".MockCodeGenerator." + generator_name;
+}
+
+string MockCodeGenerator::GetOutputFileContent(
+    const string& generator_name,
+    const string& parameter,
+    const FileDescriptor* file,
+    GeneratorContext *context) {
+  vector<const FileDescriptor*> all_files;
+  context->ListParsedFiles(&all_files);
+  return GetOutputFileContent(
+      generator_name, parameter, file->name(),
+      CommaSeparatedList(all_files),
+      file->message_type_count() > 0 ?
+          file->message_type(0)->name() : "(none)");
+}
+
+string MockCodeGenerator::GetOutputFileContent(
+    const string& generator_name,
+    const string& parameter,
+    const string& file,
+    const string& parsed_file_list,
+    const string& first_message_name) {
+  return strings::Substitute("$0: $1, $2, $3, $4\n",
+      generator_name, parameter, file,
+      first_message_name, parsed_file_list);
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.h
new file mode 100644
index 0000000..e1665f8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/mock_code_generator.h
@@ -0,0 +1,122 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor;
+}  // namespace protobuf
+
+namespace protobuf {
+namespace compiler {
+
+// A mock CodeGenerator, used by command_line_interface_unittest.  This is in
+// its own file so that it can be used both directly and as a plugin.
+//
+// Generate() produces some output which can be checked by ExpectCalled().  The
+// generator can run in a different process (e.g. a plugin).
+//
+// If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines
+// into the files generated by other MockCodeGenerators instead of creating
+// its own file.  NAMES is a comma-separated list of the names of those other
+// MockCodeGenerators.
+//
+// MockCodeGenerator will also modify its behavior slightly if the input file
+// contains a message type with one of the following names:
+//   MockCodeGenerator_Error:  Causes Generate() to return false and set the
+//     error message to "Saw message type MockCodeGenerator_Error."
+//   MockCodeGenerator_Exit:  Generate() prints "Saw message type
+//     MockCodeGenerator_Exit." to stderr and then calls exit(123).
+//   MockCodeGenerator_Abort:  Generate() prints "Saw message type
+//     MockCodeGenerator_Abort." to stderr and then calls abort().
+//   MockCodeGenerator_HasSourceCodeInfo:  Causes Generate() to abort after
+//     printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
+//     stderr, where FOO is "1" if the supplied FileDescriptorProto has source
+//     code info, and "0" otherwise.
+class MockCodeGenerator : public CodeGenerator {
+ public:
+  MockCodeGenerator(const string& name);
+  virtual ~MockCodeGenerator();
+
+  // Expect (via gTest) that a MockCodeGenerator with the given name was called
+  // with the given parameters by inspecting the output location.
+  //
+  // |insertions| is a comma-separated list of names of MockCodeGenerators which
+  // should have inserted lines into this file.
+  // |parsed_file_list| is a comma-separated list of names of the files
+  // that are being compiled together in this run.
+  static void ExpectGenerated(const string& name,
+                              const string& parameter,
+                              const string& insertions,
+                              const string& file,
+                              const string& first_message_name,
+                              const string& parsed_file_list,
+                              const string& output_directory);
+
+  // Get the name of the file which would be written by the given generator.
+  static string GetOutputFileName(const string& generator_name,
+                                  const FileDescriptor* file);
+  static string GetOutputFileName(const string& generator_name,
+                                  const string& file);
+
+  // implements CodeGenerator ----------------------------------------
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* context,
+                        string* error) const;
+
+ private:
+  string name_;
+
+  static string GetOutputFileContent(const string& generator_name,
+                                     const string& parameter,
+                                     const FileDescriptor* file,
+                                     GeneratorContext *context);
+  static string GetOutputFileContent(const string& generator_name,
+                                     const string& parameter,
+                                     const string& file,
+                                     const string& parsed_file_list,
+                                     const string& first_message_name);
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
new file mode 100644
index 0000000..e76f8e9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -0,0 +1,219 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
+    : descriptor_(descriptor),
+      name_(EnumName(descriptor_)) {
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    const EnumValueDescriptor* value = descriptor_->value(i);
+    const EnumValueDescriptor* canonical_value =
+        descriptor_->FindValueByNumber(value->number());
+
+    if (value == canonical_value) {
+      base_values_.push_back(value);
+    }
+    all_values_.push_back(value);
+  }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::GenerateHeader(io::Printer* printer) {
+  string enum_comments;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    enum_comments = BuildCommentsString(location);
+  } else {
+    enum_comments = "";
+  }
+
+  printer->Print(
+      "#pragma mark - Enum $name$\n"
+      "\n",
+      "name", name_);
+
+  printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
+                 "comments", enum_comments,
+                 "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_),
+                 "name", name_);
+  printer->Indent();
+
+  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    // Include the unknown value.
+    printer->Print(
+      "/// Value used if any message's field encounters a value that is not defined\n"
+      "/// by this enum. The message will also have C functions to get/set the rawValue\n"
+      "/// of the field.\n"
+      "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
+      "name", name_);
+  }
+  for (int i = 0; i < all_values_.size(); i++) {
+    SourceLocation location;
+    if (all_values_[i]->GetSourceLocation(&location)) {
+      string comments = BuildCommentsString(location).c_str();
+      if (comments.length() > 0) {
+        if (i > 0) {
+          printer->Print("\n");
+        }
+        printer->Print(comments.c_str());
+      }
+    }
+
+    printer->Print(
+        "$name$$deprecated_attribute$ = $value$,\n",
+        "name", EnumValueName(all_values_[i]),
+        "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
+        "value", SimpleItoa(all_values_[i]->number()));
+  }
+  printer->Outdent();
+  printer->Print(
+      "};\n"
+      "\n"
+      "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
+      "\n"
+      "/// Checks to see if the given value is defined by the enum or was not known at\n"
+      "/// the time this source was generated.\n"
+      "BOOL $name$_IsValidValue(int32_t value);\n"
+      "\n",
+      "name", name_);
+}
+
+void EnumGenerator::GenerateSource(io::Printer* printer) {
+  printer->Print(
+      "#pragma mark - Enum $name$\n"
+      "\n",
+      "name", name_);
+
+  // Note: For the TextFormat decode info, we can't use the enum value as
+  // the key because protocol buffer enums have 'allow_alias', which lets
+  // a value be used more than once. Instead, the index into the list of
+  // enum value descriptions is used. Note: start with -1 so the first one
+  // will be zero.
+  TextFormatDecodeData text_format_decode_data;
+  int enum_value_description_key = -1;
+  string text_blob;
+
+  for (int i = 0; i < all_values_.size(); i++) {
+    ++enum_value_description_key;
+    string short_name(EnumValueShortName(all_values_[i]));
+    text_blob += short_name + '\0';
+    if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
+      text_format_decode_data.AddString(enum_value_description_key, short_name,
+                                        all_values_[i]->name());
+    }
+  }
+
+  printer->Print(
+      "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+      "  static GPBEnumDescriptor *descriptor = NULL;\n"
+      "  if (!descriptor) {\n",
+      "name", name_);
+
+  static const int kBytesPerLine = 40;  // allow for escaping
+  printer->Print(
+      "    static const char *valueNames =");
+  for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
+    printer->Print(
+        "\n        \"$data$\"",
+        "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine))));
+  }
+  printer->Print(
+      ";\n"
+      "    static const int32_t values[] = {\n");
+  for (int i = 0; i < all_values_.size(); i++) {
+    printer->Print("        $name$,\n",  "name", EnumValueName(all_values_[i]));
+  }
+  printer->Print("    };\n");
+
+  if (text_format_decode_data.num_entries() == 0) {
+    printer->Print(
+        "    GPBEnumDescriptor *worker =\n"
+        "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                       valueNames:valueNames\n"
+        "                                           values:values\n"
+        "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+        "                                     enumVerifier:$name$_IsValidValue];\n",
+        "name", name_);
+    } else {
+      printer->Print(
+        "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+        "    GPBEnumDescriptor *worker =\n"
+        "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                       valueNames:valueNames\n"
+        "                                           values:values\n"
+        "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+        "                                     enumVerifier:$name$_IsValidValue\n"
+        "                              extraTextFormatInfo:extraTextFormatInfo];\n",
+        "name", name_,
+        "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+    }
+    printer->Print(
+      "    if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {\n"
+      "      [worker release];\n"
+      "    }\n"
+      "  }\n"
+      "  return descriptor;\n"
+      "}\n\n");
+
+  printer->Print(
+      "BOOL $name$_IsValidValue(int32_t value__) {\n"
+      "  switch (value__) {\n",
+      "name", name_);
+
+  for (int i = 0; i < base_values_.size(); i++) {
+    printer->Print(
+        "    case $name$:\n",
+        "name", EnumValueName(base_values_[i]));
+  }
+
+  printer->Print(
+      "      return YES;\n"
+      "    default:\n"
+      "      return NO;\n"
+      "  }\n"
+      "}\n\n");
+}
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.h
new file mode 100644
index 0000000..0b41cf7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -0,0 +1,73 @@
+// 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_COMPILER_OBJECTIVEC_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer;  // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator {
+ public:
+  explicit EnumGenerator(const EnumDescriptor* descriptor);
+  ~EnumGenerator();
+
+  void GenerateHeader(io::Printer* printer);
+  void GenerateSource(io::Printer* printer);
+
+  const string& name() const { return name_; }
+
+ private:
+  const EnumDescriptor* descriptor_;
+  vector<const EnumValueDescriptor*> base_values_;
+  vector<const EnumValueDescriptor*> all_values_;
+  const string name_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
new file mode 100644
index 0000000..b63bc0d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -0,0 +1,147 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+                      map<string, string>* variables) {
+  string type = EnumName(descriptor->enum_type());
+  (*variables)["storage_type"] = type;
+  // For non repeated fields, if it was defined in a different file, the
+  // property decls need to use "enum NAME" rather than just "NAME" to support
+  // the forward declaration of the enums.
+  if (!descriptor->is_repeated() &&
+      (descriptor->file() != descriptor->enum_type()->file())) {
+    (*variables)["property_type"] = "enum " + type;
+  }
+  (*variables)["enum_verifier"] = type + "_IsValidValue";
+  (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
+
+  (*variables)["dataTypeSpecific_name"] = "enumDescFunc";
+  (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"];
+
+  const Descriptor* msg_descriptor = descriptor->containing_type();
+  (*variables)["owning_message_class"] = ClassName(msg_descriptor);
+}
+}  // namespace
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
+  SetEnumVariables(descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GenerateCFunctionDeclarations(
+    io::Printer* printer) const {
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    return;
+  }
+
+  printer->Print(
+      variables_,
+      "/// Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
+      "/// if the value was not defined by the enum at the time the code was generated.\n"
+      "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
+      "/// Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
+      "/// it to be set to a value that was not defined by the enum at the time the code\n"
+      "/// was generated.\n"
+      "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
+      "\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionImplementations(
+    io::Printer* printer) const {
+  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+
+  printer->Print(
+      variables_,
+      "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
+      "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+      "  GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+      "  return GPBGetMessageInt32Field(message, field);\n"
+      "}\n"
+      "\n"
+      "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
+      "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+      "  GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+      "  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n"
+      "}\n"
+      "\n");
+}
+
+void EnumFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  // If it is an enum defined in a different file, then we'll need a forward
+  // declaration for it.  When it is in our file, all the enums are output
+  // before the message, so it will be declared before it is needed.
+  if (descriptor_->file() != descriptor_->enum_type()->file()) {
+    // Enum name is already in "storage_type".
+    const string& name = variable("storage_type");
+    fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
+  }
+}
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
+  SetEnumVariables(descriptor, &variables_);
+  variables_["array_storage_type"] = "GPBEnumArray";
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  variables_["array_comment"] =
+      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
new file mode 100644
index 0000000..946faa8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -0,0 +1,80 @@
+// 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_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumFieldGenerator : public SingleFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ public:
+  virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+  virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ protected:
+  EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+  virtual ~EnumFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ public:
+  virtual void FinishInitialization();
+
+ protected:
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
+  virtual ~RepeatedEnumFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
new file mode 100644
index 0000000..3f7ab9d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -0,0 +1,136 @@
+// 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.
+
+#include <iostream>
+
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ExtensionGenerator::ExtensionGenerator(const string& root_class_name,
+                                       const FieldDescriptor* descriptor)
+    : method_name_(ExtensionMethodName(descriptor)),
+      root_class_and_method_name_(root_class_name + "_" + method_name_),
+      descriptor_(descriptor) {
+  if (descriptor->is_map()) {
+    // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+    // error cases, so it seems to be ok to use as a back door for errors.
+    cerr << "error: Extension is a map<>!"
+         << " That used to be blocked by the compiler." << endl;
+    cerr.flush();
+    abort();
+  }
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
+  map<string, string> vars;
+  vars["method_name"] = method_name_;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    vars["comments"] = BuildCommentsString(location);
+  } else {
+    vars["comments"] = "";
+  }
+  printer->Print(vars,
+                 "$comments$"
+                 "+ (GPBExtensionDescriptor *)$method_name$;\n");
+}
+
+void ExtensionGenerator::GenerateStaticVariablesInitialization(
+    io::Printer* printer) {
+  map<string, string> vars;
+  vars["root_class_and_method_name"] = root_class_and_method_name_;
+  vars["extended_type"] = ClassName(descriptor_->containing_type());
+  vars["number"] = SimpleItoa(descriptor_->number());
+
+  std::vector<string> options;
+  if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
+  if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
+  if (descriptor_->containing_type()->options().message_set_wire_format())
+    options.push_back("GPBExtensionSetWireFormat");
+
+  vars["options"] = BuildFlagsString(options);
+
+  ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+  string singular_type;
+  if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+    vars["type"] = string("GPBStringifySymbol(") +
+                   ClassName(descriptor_->message_type()) + ")";
+  } else {
+    vars["type"] = "NULL";
+  }
+
+  vars["default_name"] = GPBGenericValueFieldName(descriptor_);
+  if (descriptor_->is_repeated()) {
+    vars["default"] = "nil";
+  } else {
+    vars["default"] = DefaultValue(descriptor_);
+  }
+  string type = GetCapitalizedType(descriptor_);
+  vars["extension_type"] = string("GPBDataType") + type;
+
+  if (objc_type == OBJECTIVECTYPE_ENUM) {
+    vars["enum_desc_func_name"] =
+         EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
+  } else {
+    vars["enum_desc_func_name"] = "NULL";
+  }
+
+  printer->Print(vars,
+                 "{\n"
+                 "  .defaultValue.$default_name$ = $default$,\n"
+                 "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+                 "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
+                 "  .messageOrGroupClassName = $type$,\n"
+                 "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
+                 "  .fieldNumber = $number$,\n"
+                 "  .dataType = $extension_type$,\n"
+                 "  .options = $options$,\n"
+                 "},\n");
+}
+
+void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
+  printer->Print(
+      "[registry addExtension:$root_class_and_method_name$];\n",
+      "root_class_and_method_name", root_class_and_method_name_);
+}
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.h
new file mode 100644
index 0000000..e361e63
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -0,0 +1,69 @@
+// 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_COMPILER_OBJECTIVEC_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor;  // descriptor.h
+namespace io {
+class Printer;  // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator {
+ public:
+  ExtensionGenerator(const string& root_class_name,
+                     const FieldDescriptor* descriptor);
+  ~ExtensionGenerator();
+
+  void GenerateMembersHeader(io::Printer* printer);
+  void GenerateStaticVariablesInitialization(io::Printer* printer);
+  void GenerateRegistrationSource(io::Printer* printer);
+
+ private:
+  string method_name_;
+  string root_class_and_method_name_;
+  const FieldDescriptor* descriptor_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.cc
new file mode 100644
index 0000000..66cb4a1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -0,0 +1,477 @@
+// 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.
+
+#include <iostream>
+
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+                             map<string, string>* variables) {
+  string camel_case_name = FieldName(descriptor);
+  string raw_field_name;
+  if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+    raw_field_name = descriptor->message_type()->name();
+  } else {
+    raw_field_name = descriptor->name();
+  }
+  // The logic here has to match -[GGPBFieldDescriptor textFormatName].
+  const string un_camel_case_name(
+      UnCamelCaseFieldName(camel_case_name, descriptor));
+  const bool needs_custom_name = (raw_field_name != un_camel_case_name);
+
+  SourceLocation location;
+  if (descriptor->GetSourceLocation(&location)) {
+    (*variables)["comments"] = BuildCommentsString(location);
+  } else {
+    (*variables)["comments"] = "\n";
+  }
+  const string& classname = ClassName(descriptor->containing_type());
+  (*variables)["classname"] = classname;
+  (*variables)["name"] = camel_case_name;
+  const string& capitalized_name = FieldNameCapitalized(descriptor);
+  (*variables)["capitalized_name"] = capitalized_name;
+  (*variables)["raw_field_name"] = raw_field_name;
+  (*variables)["field_number_name"] =
+      classname + "_FieldNumber_" + capitalized_name;
+  (*variables)["field_number"] = SimpleItoa(descriptor->number());
+  (*variables)["field_type"] = GetCapitalizedType(descriptor);
+  (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
+  std::vector<string> field_flags;
+  if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
+  if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
+  if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
+  if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
+
+  // ObjC custom flags.
+  if (descriptor->has_default_value())
+    field_flags.push_back("GPBFieldHasDefaultValue");
+  if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
+  if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+    field_flags.push_back("GPBFieldHasEnumDescriptor");
+  }
+
+  (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+
+  (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
+
+  (*variables)["dataTypeSpecific_name"] = "className";
+  (*variables)["dataTypeSpecific_value"] = "NULL";
+
+  (*variables)["storage_offset_value"] =
+      "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
+  (*variables)["storage_offset_comment"] = "";
+
+  // Clear some common things so they can be set just when needed.
+  (*variables)["storage_attribute"] = "";
+}
+
+}  // namespace
+
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                     const Options& options) {
+  FieldGenerator* result = NULL;
+  if (field->is_repeated()) {
+    switch (GetObjectiveCType(field)) {
+      case OBJECTIVECTYPE_MESSAGE: {
+        if (field->is_map()) {
+          result = new MapFieldGenerator(field, options);
+        } else {
+          result = new RepeatedMessageFieldGenerator(field, options);
+        }
+        break;
+      }
+      case OBJECTIVECTYPE_ENUM:
+        result = new RepeatedEnumFieldGenerator(field, options);
+        break;
+      default:
+        result = new RepeatedPrimitiveFieldGenerator(field, options);
+        break;
+    }
+  } else {
+    switch (GetObjectiveCType(field)) {
+      case OBJECTIVECTYPE_MESSAGE: {
+        result = new MessageFieldGenerator(field, options);
+        break;
+      }
+      case OBJECTIVECTYPE_ENUM:
+        result = new EnumFieldGenerator(field, options);
+        break;
+      default:
+        if (IsReferenceType(field)) {
+          result = new PrimitiveObjFieldGenerator(field, options);
+        } else {
+          result = new PrimitiveFieldGenerator(field, options);
+        }
+        break;
+    }
+  }
+  result->FinishInitialization();
+  return result;
+}
+
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options)
+    : descriptor_(descriptor) {
+  SetCommonFieldVariables(descriptor, &variables_);
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "$field_number_name$ = $field_number$,\n");
+}
+
+void FieldGenerator::GenerateCFunctionDeclarations(
+    io::Printer* printer) const {
+  // Nothing
+}
+
+void FieldGenerator::GenerateCFunctionImplementations(
+    io::Printer* printer) const {
+  // Nothing
+}
+
+void FieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  // Nothing
+}
+
+void FieldGenerator::GenerateFieldDescription(
+    io::Printer* printer, bool include_default) const {
+  // Printed in the same order as the structure decl.
+  if (include_default) {
+    printer->Print(
+        variables_,
+        "{\n"
+        "  .defaultValue.$default_name$ = $default$,\n"
+        "  .core.name = \"$name$\",\n"
+        "  .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+        "  .core.number = $field_number_name$,\n"
+        "  .core.hasIndex = $has_index$,\n"
+        "  .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
+        "  .core.flags = $fieldflags$,\n"
+        "  .core.dataType = GPBDataType$field_type$,\n"
+        "},\n");
+  } else {
+    printer->Print(
+        variables_,
+        "{\n"
+        "  .name = \"$name$\",\n"
+        "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+        "  .number = $field_number_name$,\n"
+        "  .hasIndex = $has_index$,\n"
+        "  .offset = $storage_offset_value$,$storage_offset_comment$\n"
+        "  .flags = $fieldflags$,\n"
+        "  .dataType = GPBDataType$field_type$,\n"
+        "},\n");
+  }
+}
+
+void FieldGenerator::SetRuntimeHasBit(int has_index) {
+  variables_["has_index"] = SimpleItoa(has_index);
+}
+
+void FieldGenerator::SetNoHasBit(void) {
+  variables_["has_index"] = "GPBNoHasBit";
+}
+
+int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+  return 0;
+}
+
+void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
+  // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+  // error cases, so it seems to be ok to use as a back door for errors.
+  cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
+  cerr.flush();
+  abort();
+}
+
+void FieldGenerator::SetOneofIndexBase(int index_base) {
+  if (descriptor_->containing_oneof() != NULL) {
+    int index = descriptor_->containing_oneof()->index() + index_base;
+    // Flip the sign to mark it as a oneof.
+    variables_["has_index"] = SimpleItoa(-index);
+  }
+}
+
+void FieldGenerator::FinishInitialization(void) {
+  // If "property_type" wasn't set, make it "storage_type".
+  if ((variables_.find("property_type") == variables_.end()) &&
+      (variables_.find("storage_type") != variables_.end())) {
+    variables_["property_type"] = variable("storage_type");
+  }
+}
+
+SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options)
+    : FieldGenerator(descriptor, options) {
+  // Nothing
+}
+
+SingleFieldGenerator::~SingleFieldGenerator() {}
+
+void SingleFieldGenerator::GenerateFieldStorageDeclaration(
+    io::Printer* printer) const {
+  printer->Print(variables_, "$storage_type$ $name$;\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyDeclaration(
+    io::Printer* printer) const {
+  printer->Print(variables_, "$comments$");
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
+      "\n");
+  if (WantsHasProperty()) {
+    printer->Print(
+        variables_,
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+  }
+}
+
+void SingleFieldGenerator::GeneratePropertyImplementation(
+    io::Printer* printer) const {
+  if (WantsHasProperty()) {
+    printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
+  } else {
+    printer->Print(variables_, "@dynamic $name$;\n");
+  }
+}
+
+bool SingleFieldGenerator::WantsHasProperty(void) const {
+  if (descriptor_->containing_oneof() != NULL) {
+    // If in a oneof, it uses the oneofcase instead of a has bit.
+    return false;
+  }
+  if (HasFieldPresence(descriptor_->file())) {
+    // In proto1/proto2, every field has a has_$name$() method.
+    return true;
+  }
+  return false;
+}
+
+bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+  if (descriptor_->containing_oneof() != NULL) {
+    // The oneof tracks what is set instead.
+    return false;
+  }
+  return true;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
+  variables_["property_storage_attribute"] = "strong";
+  if (IsRetainedName(variables_["name"])) {
+    variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
+  }
+}
+
+ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
+
+void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
+    io::Printer* printer) const {
+  printer->Print(variables_, "$storage_type$ *$name$;\n");
+}
+
+void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
+    io::Printer* printer) const {
+
+  // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
+  // it uses pointers and deals with Objective C's rules around storage name
+  // conventions (init*, new*, etc.)
+
+  printer->Print(variables_, "$comments$");
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
+  if (WantsHasProperty()) {
+    printer->Print(
+        variables_,
+        "/// Test to see if @c $name$ has been set.\n"
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+  }
+  if (IsInitName(variables_.find("name")->second)) {
+    // If property name starts with init we need to annotate it to get past ARC.
+    // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+    printer->Print(variables_,
+                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+  }
+  printer->Print("\n");
+}
+
+RepeatedFieldGenerator::RepeatedFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
+  // Default to no comment and let the cases needing it fill it in.
+  variables_["array_comment"] = "";
+}
+
+RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
+
+void RepeatedFieldGenerator::FinishInitialization(void) {
+  FieldGenerator::FinishInitialization();
+  if (variables_.find("array_property_type") == variables_.end()) {
+    variables_["array_property_type"] = variable("array_storage_type");
+  }
+}
+
+void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
+    io::Printer* printer) const {
+  printer->Print(variables_, "$array_storage_type$ *$name$;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyImplementation(
+    io::Printer* printer) const {
+  printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyDeclaration(
+    io::Printer* printer) const {
+
+  // Repeated fields don't need the has* properties, but they do expose a
+  // *Count (to check without autocreation).  So for the field property we need
+  // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
+  // dealing with needing Objective C's rules around storage name conventions
+  // (init*, new*, etc.)
+
+  printer->Print(
+      variables_,
+      "$comments$"
+      "$array_comment$"
+      "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
+      "/// The number of items in @c $name$ without causing the array to be created.\n"
+      "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
+  if (IsInitName(variables_.find("name")->second)) {
+    // If property name starts with init we need to annotate it to get past ARC.
+    // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+    printer->Print(variables_,
+                   "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+  }
+  printer->Print("\n");
+}
+
+bool RepeatedFieldGenerator::WantsHasProperty(void) const {
+  // Consumer check the array size/existance rather than a has bit.
+  return false;
+}
+
+bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+  return false;  // The array having anything is what is used.
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+                                     const Options& options)
+    : descriptor_(descriptor),
+      field_generators_(
+          new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
+      extension_generators_(
+          new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+  // Construct all the FieldGenerators.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    field_generators_[i].reset(
+        FieldGenerator::Make(descriptor->field(i), options));
+  }
+  for (int i = 0; i < descriptor->extension_count(); i++) {
+    extension_generators_[i].reset(
+        FieldGenerator::Make(descriptor->extension(i), options));
+  }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+    const FieldDescriptor* field) const {
+  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+  return *field_generators_[field->index()];
+}
+
+const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
+  return *extension_generators_[index];
+}
+
+int FieldGeneratorMap::CalculateHasBits(void) {
+  int total_bits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (field_generators_[i]->RuntimeUsesHasBit()) {
+      field_generators_[i]->SetRuntimeHasBit(total_bits);
+      ++total_bits;
+    } else {
+      field_generators_[i]->SetNoHasBit();
+    }
+    int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
+    if (extra_bits) {
+      field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
+      total_bits += extra_bits;
+    }
+  }
+  return total_bits;
+}
+
+void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_[i]->SetOneofIndexBase(index_base);
+  }
+}
+
+bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (HasNonZeroDefaultValue(descriptor_->field(i))) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.h
new file mode 100644
index 0000000..a3a4b1b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -0,0 +1,194 @@
+// 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_COMPILER_OBJECTIVEC_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer;  // printer.h
+}  // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class FieldGenerator {
+ public:
+  static FieldGenerator* Make(const FieldDescriptor* field,
+                              const Options& options);
+
+  virtual ~FieldGenerator();
+
+  // Exposed for subclasses to fill in.
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
+
+  // Called by GenerateFieldDescription, exposed for classes that need custom
+  // generation.
+
+  // Exposed for subclasses to extend, base does nothing.
+  virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+  virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+  // Exposed for subclasses, should always call it on the parent class also.
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+  // Used during generation, not intended to be extended by subclasses.
+  void GenerateFieldDescription(
+      io::Printer* printer, bool include_default) const;
+  void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+  // Exposed to get and set the has bits information.
+  virtual bool RuntimeUsesHasBit(void) const = 0;
+  void SetRuntimeHasBit(int has_index);
+  void SetNoHasBit(void);
+  virtual int ExtraRuntimeHasBitsNeeded(void) const;
+  virtual void SetExtraRuntimeHasBitsBase(int index_base);
+  void SetOneofIndexBase(int index_base);
+
+  string variable(const char* key) const {
+    return variables_.find(key)->second;
+  }
+
+  bool needs_textformat_name_support() const {
+    const string& field_flags = variable("fieldflags");
+    return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos;
+  }
+  string generated_objc_name() const { return variable("name"); }
+  string raw_field_name() const { return variable("raw_field_name"); }
+
+ protected:
+  FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+
+  virtual void FinishInitialization(void);
+  virtual bool WantsHasProperty(void) const = 0;
+
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+class SingleFieldGenerator : public FieldGenerator {
+ public:
+  virtual ~SingleFieldGenerator();
+
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+  virtual bool RuntimeUsesHasBit(void) const;
+
+ protected:
+  SingleFieldGenerator(const FieldDescriptor* descriptor,
+                       const Options& options);
+  virtual bool WantsHasProperty(void) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingleFieldGenerator);
+};
+
+// Subclass with common support for when the field ends up as an ObjC Object.
+class ObjCObjFieldGenerator : public SingleFieldGenerator {
+ public:
+  virtual ~ObjCObjFieldGenerator();
+
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ protected:
+  ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
+};
+
+class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
+ public:
+  virtual ~RepeatedFieldGenerator();
+
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+  virtual bool RuntimeUsesHasBit(void) const;
+
+ protected:
+  RepeatedFieldGenerator(const FieldDescriptor* descriptor,
+                         const Options& options);
+  virtual void FinishInitialization(void);
+  virtual bool WantsHasProperty(void) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedFieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+  FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+  ~FieldGeneratorMap();
+
+  const FieldGenerator& get(const FieldDescriptor* field) const;
+  const FieldGenerator& get_extension(int index) const;
+
+  // Assigns the has bits and returns the number of bits needed.
+  int CalculateHasBits(void);
+
+  void SetOneofIndexBase(int index_base);
+
+  // Check if any field of this message has a non zero default.
+  bool DoesAnyFieldHaveNonZeroDefault(void) const;
+
+ private:
+  const Descriptor* descriptor_;
+  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+  scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.cc
new file mode 100644
index 0000000..ed4fc6a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -0,0 +1,382 @@
+// 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.
+
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <sstream>
+
+namespace google {
+namespace protobuf {
+
+// This is also found in GPBBootstrap.h, and needs to be kept in sync.  It
+// is the version check done to ensure generated code works with the current
+// runtime being used.
+const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
+
+namespace compiler {
+namespace objectivec {
+
+FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
+    : file_(file),
+      root_class_name_(FileClassName(file)),
+      is_public_dep_(false),
+      options_(options) {
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
+    enum_generators_.push_back(generator);
+  }
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    MessageGenerator *generator =
+        new MessageGenerator(root_class_name_, file_->message_type(i), options_);
+    message_generators_.push_back(generator);
+  }
+  for (int i = 0; i < file_->extension_count(); i++) {
+    ExtensionGenerator *generator =
+        new ExtensionGenerator(root_class_name_, file_->extension(i));
+    extension_generators_.push_back(generator);
+  }
+}
+
+FileGenerator::~FileGenerator() {
+  STLDeleteContainerPointers(dependency_generators_.begin(),
+                             dependency_generators_.end());
+  STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+  STLDeleteContainerPointers(message_generators_.begin(),
+                             message_generators_.end());
+  STLDeleteContainerPointers(extension_generators_.begin(),
+                             extension_generators_.end());
+}
+
+void FileGenerator::GenerateHeader(io::Printer *printer) {
+  printer->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name());
+
+  printer->Print(
+      "#import \"GPBProtocolBuffers.h\"\n"
+      "\n");
+
+  // Add some verification that the generated code matches the source the
+  // code is being compiled with.
+  printer->Print(
+      "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n"
+      "#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+      "#endif\n"
+      "\n",
+      "protoc_gen_objc_version",
+      SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
+
+  const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
+  for (vector<FileGenerator *>::const_iterator iter =
+           dependency_generators.begin();
+       iter != dependency_generators.end(); ++iter) {
+    if ((*iter)->IsPublicDependency()) {
+      printer->Print("#import \"$header$.pbobjc.h\"\n",
+                     "header", (*iter)->Path());
+    }
+  }
+
+  printer->Print(
+      "// @@protoc_insertion_point(imports)\n"
+      "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
+      "\n"
+      "CF_EXTERN_C_BEGIN\n"
+      "\n");
+
+  set<string> fwd_decls;
+  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    (*iter)->DetermineForwardDeclarations(&fwd_decls);
+  }
+  for (set<string>::const_iterator i(fwd_decls.begin());
+       i != fwd_decls.end(); ++i) {
+    printer->Print("$value$;\n", "value", *i);
+  }
+  if (fwd_decls.begin() != fwd_decls.end()) {
+    printer->Print("\n");
+  }
+
+  printer->Print(
+      "NS_ASSUME_NONNULL_BEGIN\n"
+      "\n");
+
+  // need to write out all enums first
+  for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+       iter != enum_generators_.end(); ++iter) {
+    (*iter)->GenerateHeader(printer);
+  }
+
+  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    (*iter)->GenerateEnumHeader(printer);
+  }
+
+  // For extensions to chain together, the Root gets created even if there
+  // are no extensions.
+  printer->Print(
+      "#pragma mark - $root_class_name$\n"
+      "\n"
+      "/// Exposes the extension registry for this file.\n"
+      "///\n"
+      "/// The base class provides:\n"
+      "/// @code\n"
+      "///   + (GPBExtensionRegistry *)extensionRegistry;\n"
+      "/// @endcode\n"
+      "/// which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
+      "/// this file and all files that it depends on.\n"
+      "@interface $root_class_name$ : GPBRootObject\n"
+      "@end\n"
+      "\n",
+      "root_class_name", root_class_name_);
+
+  if (extension_generators_.size() > 0) {
+    // The dynamic methods block is only needed if there are extensions.
+    printer->Print(
+        "@interface $root_class_name$ (DynamicMethods)\n",
+        "root_class_name", root_class_name_);
+
+    for (vector<ExtensionGenerator *>::iterator iter =
+             extension_generators_.begin();
+         iter != extension_generators_.end(); ++iter) {
+      (*iter)->GenerateMembersHeader(printer);
+    }
+
+    printer->Print("@end\n\n");
+  }  // extension_generators_.size() > 0
+
+  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    (*iter)->GenerateMessageHeader(printer);
+  }
+
+  printer->Print(
+      "NS_ASSUME_NONNULL_END\n"
+      "\n"
+      "CF_EXTERN_C_END\n"
+      "\n"
+      "#pragma clang diagnostic pop\n"
+      "\n"
+      "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateSource(io::Printer *printer) {
+  printer->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name());
+
+  string header_file = Path() + ".pbobjc.h";
+  printer->Print(
+      "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n"
+      "#import \"$header_file$\"\n",
+      "header_file", header_file);
+  const vector<FileGenerator *> &dependency_generators =
+      DependencyGenerators();
+  for (vector<FileGenerator *>::const_iterator iter =
+           dependency_generators.begin();
+       iter != dependency_generators.end(); ++iter) {
+    if (!(*iter)->IsPublicDependency()) {
+      printer->Print("#import \"$header$.pbobjc.h\"\n",
+                     "header", (*iter)->Path());
+    }
+  }
+  printer->Print(
+      "// @@protoc_insertion_point(imports)\n"
+      "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
+      "\n");
+
+  printer->Print(
+      "#pragma mark - $root_class_name$\n"
+      "\n"
+      "@implementation $root_class_name$\n\n",
+      "root_class_name", root_class_name_);
+
+  // Generate the extension initialization structures for the top level and
+  // any nested messages.
+  ostringstream extensions_stringstream;
+  if (file_->extension_count() + file_->message_type_count() > 0) {
+    io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
+    io::Printer extensions_printer(&extensions_outputstream, '$');
+    for (vector<ExtensionGenerator *>::iterator iter =
+             extension_generators_.begin();
+         iter != extension_generators_.end(); ++iter) {
+      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+    }
+    for (vector<MessageGenerator *>::iterator iter =
+             message_generators_.begin();
+         iter != message_generators_.end(); ++iter) {
+      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+    }
+    extensions_stringstream.flush();
+  }
+
+  // If there were any extensions or this file has any dependencies, output
+  // a registry to override to create the file specific registry.
+  const string& extensions_str = extensions_stringstream.str();
+  if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+    printer->Print(
+        "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+        "  // This is called by +initialize so there is no need to worry\n"
+        "  // about thread safety and initialization of registry.\n"
+        "  static GPBExtensionRegistry* registry = nil;\n"
+        "  if (!registry) {\n"
+        "    GPBDebugCheckRuntimeVersion();\n"
+        "    registry = [[GPBExtensionRegistry alloc] init];\n");
+
+    printer->Indent();
+    printer->Indent();
+
+    if (extensions_str.length() > 0) {
+      printer->Print(
+          "static GPBExtensionDescription descriptions[] = {\n");
+      printer->Indent();
+      printer->Print(extensions_str.c_str());
+      printer->Outdent();
+      printer->Print(
+          "};\n"
+          "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+          "  GPBExtensionDescriptor *extension =\n"
+          "      [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
+          "  [registry addExtension:extension];\n"
+          "  [self globallyRegisterExtension:extension];\n"
+          "  [extension release];\n"
+          "}\n");
+    }
+
+    const vector<FileGenerator *> &dependency_generators =
+        DependencyGenerators();
+    for (vector<FileGenerator *>::const_iterator iter =
+             dependency_generators.begin();
+         iter != dependency_generators.end(); ++iter) {
+      printer->Print(
+          "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+          "dependency", (*iter)->RootClassName());
+    }
+
+    printer->Outdent();
+    printer->Outdent();
+
+    printer->Print(
+        "  }\n"
+        "  return registry;\n"
+        "}\n"
+        "\n");
+  }
+
+  printer->Print("@end\n\n");
+
+  // File descriptor only needed if there are messages to use it.
+  if (message_generators_.size() > 0) {
+    string syntax;
+    switch (file_->syntax()) {
+      case FileDescriptor::SYNTAX_UNKNOWN:
+        syntax = "GPBFileSyntaxUnknown";
+        break;
+      case FileDescriptor::SYNTAX_PROTO2:
+        syntax = "GPBFileSyntaxProto2";
+        break;
+      case FileDescriptor::SYNTAX_PROTO3:
+        syntax = "GPBFileSyntaxProto3";
+        break;
+    }
+    printer->Print(
+        "#pragma mark - $root_class_name$_FileDescriptor\n"
+        "\n"
+        "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+        "  // This is called by +initialize so there is no need to worry\n"
+        "  // about thread safety of the singleton.\n"
+        "  static GPBFileDescriptor *descriptor = NULL;\n"
+        "  if (!descriptor) {\n"
+        "    GPBDebugCheckRuntimeVersion();\n"
+        "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+        "                                                     syntax:$syntax$];\n"
+        "  }\n"
+        "  return descriptor;\n"
+        "}\n"
+        "\n",
+        "root_class_name", root_class_name_,
+        "package", file_->package(),
+        "syntax", syntax);
+  }
+
+  for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+       iter != enum_generators_.end(); ++iter) {
+    (*iter)->GenerateSource(printer);
+  }
+  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    (*iter)->GenerateSource(printer);
+  }
+
+  printer->Print(
+    "\n"
+    "#pragma clang diagnostic pop\n"
+    "\n"
+    "// @@protoc_insertion_point(global_scope)\n");
+}
+
+const string FileGenerator::Path() const { return FilePath(file_); }
+
+const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
+  if (file_->dependency_count() != dependency_generators_.size()) {
+    set<string> public_import_names;
+    for (int i = 0; i < file_->public_dependency_count(); i++) {
+      public_import_names.insert(file_->public_dependency(i)->name());
+    }
+    for (int i = 0; i < file_->dependency_count(); i++) {
+      FileGenerator *generator =
+          new FileGenerator(file_->dependency(i), options_);
+      const string& name = file_->dependency(i)->name();
+      bool public_import = (public_import_names.count(name) != 0);
+      generator->SetIsPublicDependency(public_import);
+      dependency_generators_.push_back(generator);
+    }
+  }
+  return dependency_generators_;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.h
new file mode 100644
index 0000000..4c0fcd3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -0,0 +1,99 @@
+// 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_COMPILER_OBJECTIVEC_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor;  // descriptor.h
+namespace io {
+class Printer;  // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator;
+class ExtensionGenerator;
+class MessageGenerator;
+
+class FileGenerator {
+ public:
+  FileGenerator(const FileDescriptor* file, const Options& options);
+  ~FileGenerator();
+
+  void GenerateSource(io::Printer* printer);
+  void GenerateHeader(io::Printer* printer);
+
+  const string& RootClassName() const { return root_class_name_; }
+  const string Path() const;
+
+  bool IsPublicDependency() const { return is_public_dep_; }
+
+ protected:
+  void SetIsPublicDependency(bool is_public_dep) {
+    is_public_dep_ = is_public_dep;
+  }
+
+ private:
+  const FileDescriptor* file_;
+  string root_class_name_;
+
+  // Access this field through the DependencyGenerators accessor call below.
+  // Do not reference it directly.
+  vector<FileGenerator*> dependency_generators_;
+
+  vector<EnumGenerator*> enum_generators_;
+  vector<MessageGenerator*> message_generators_;
+  vector<ExtensionGenerator*> extension_generators_;
+  bool is_public_dep_;
+
+  const Options options_;
+
+  const vector<FileGenerator*>& DependencyGenerators();
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
new file mode 100644
index 0000000..72e295d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -0,0 +1,101 @@
+// 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.
+
+#include <iostream>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ObjectiveCGenerator::ObjectiveCGenerator() {}
+
+ObjectiveCGenerator::~ObjectiveCGenerator() {}
+
+bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
+                                   const string& parameter,
+                                   OutputDirectory* output_directory,
+                                   string* error) const {
+  // -----------------------------------------------------------------
+  // Parse generator options.
+
+  Options generation_options;
+
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "expected_prefixes_path") {
+      generation_options.expected_prefixes_path = options[i].second;
+    } else {
+      *error = "error: Unknown generator option: " + options[i].first;
+      return false;
+    }
+  }
+
+  // -----------------------------------------------------------------
+
+  // Validate the objc prefix/package pairing.
+  if (!ValidateObjCClassPrefix(file, generation_options, error)) {
+    // *error will have been filled in.
+    return false;
+  }
+
+  FileGenerator file_generator(file, generation_options);
+  string filepath = FilePath(file);
+
+  // Generate header.
+  {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+        output_directory->Open(filepath + ".pbobjc.h"));
+    io::Printer printer(output.get(), '$');
+    file_generator.GenerateHeader(&printer);
+  }
+
+  // Generate m file.
+  {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+        output_directory->Open(filepath + ".pbobjc.m"));
+    io::Printer printer(output.get(), '$');
+    file_generator.GenerateSource(&printer);
+  }
+
+  return true;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.h
new file mode 100644
index 0000000..09266b0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -0,0 +1,61 @@
+// 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.
+
+// Generates ObjectiveC code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
+ public:
+  ObjectiveCGenerator();
+  ~ObjectiveCGenerator();
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file, const string& parameter,
+                OutputDirectory* output_directory, string* error) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
new file mode 100644
index 0000000..196b39d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -0,0 +1,1295 @@
+// 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.
+
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <climits>
+#include <errno.h>
+#include <fcntl.h>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <stdlib.h>
+#include <vector>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error cases, so it seems to be ok to use as a back door for errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+Options::Options() {
+  // Default is the value of the env for the package prefixes.
+  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+  if (file_path) {
+    expected_prefixes_path = file_path;
+  }
+}
+
+namespace {
+
+hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
+  hash_set<string> result;
+  for (int i = 0; i < num_words; i++) {
+    result.insert(words[i]);
+  }
+  return result;
+}
+
+const char* const kUpperSegmentsList[] = {"url", "http", "https"};
+
+hash_set<string> kUpperSegments =
+    MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
+
+// Internal helper for name handing.
+// Do not expose this outside of helpers, stick to having functions for specific
+// cases (ClassName(), FieldName()), so there is always consistent suffix rules.
+string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
+  vector<string> values;
+  string current;
+
+  bool last_char_was_number = false;
+  bool last_char_was_lower = false;
+  bool last_char_was_upper = false;
+  for (int i = 0; i < input.size(); i++) {
+    char c = input[i];
+    if (ascii_isdigit(c)) {
+      if (!last_char_was_number) {
+        values.push_back(current);
+        current = "";
+      }
+      current += c;
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_number = true;
+    } else if (ascii_islower(c)) {
+      // lowercase letter can follow a lowercase or uppercase letter
+      if (!last_char_was_lower && !last_char_was_upper) {
+        values.push_back(current);
+        current = "";
+      }
+      current += c;  // already lower
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_lower = true;
+    } else if (ascii_isupper(c)) {
+      if (!last_char_was_upper) {
+        values.push_back(current);
+        current = "";
+      }
+      current += ascii_tolower(c);
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_upper = true;
+    } else {
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+    }
+  }
+  values.push_back(current);
+
+  string result;
+  bool first_segment_forces_upper = false;
+  for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+    string value = *i;
+    bool all_upper = (kUpperSegments.count(value) > 0);
+    if (all_upper && (result.length() == 0)) {
+      first_segment_forces_upper = true;
+    }
+    for (int j = 0; j < value.length(); j++) {
+      if (j == 0 || all_upper) {
+        value[j] = ascii_toupper(value[j]);
+      } else {
+        // Nothing, already in lower.
+      }
+    }
+    result += value;
+  }
+  if ((result.length() != 0) &&
+      !first_capitalized &&
+      !first_segment_forces_upper) {
+    result[0] = ascii_tolower(result[0]);
+  }
+  return result;
+}
+
+const char* const kReservedWordList[] = {
+    // Objective C "keywords" that aren't in C
+    // From
+    // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+    "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
+    "self",
+
+    // C/C++ keywords (Incl C++ 0x11)
+    // From http://en.cppreference.com/w/cpp/keywords
+    "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
+    "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
+    "compl", "const", "constexpr", "const_cast", "continue", "decltype",
+    "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
+    "export", "extern ", "false", "float", "for", "friend", "goto", "if",
+    "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
+    "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
+    "public", "register", "reinterpret_cast", "return", "short", "signed",
+    "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
+    "template", "this", "thread_local", "throw", "true", "try", "typedef",
+    "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+    "volatile", "wchar_t", "while", "xor", "xor_eq",
+
+    // C99 keywords
+    // From
+    // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+    "restrict",
+
+    // Objective-C Runtime typedefs
+    // From <obc/runtime.h>
+    "Category", "Ivar", "Method", "Protocol",
+
+    // NSObject Methods
+    // new is covered by C++ keywords.
+    "description", "debugDescription", "finalize", "hash", "dealloc", "init",
+    "class", "superclass", "retain", "release", "autorelease", "retainCount",
+    "zone", "isProxy", "copy", "mutableCopy", "classForCoder",
+
+    // GPBMessage Methods
+    // Only need to add instance methods that may conflict with
+    // method declared in protos. The main cases are methods
+    // that take no arguments, or setFoo:/hasFoo: type methods.
+    "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
+    "extensionsCurrentlySet", "isInitialized", "serializedSize",
+    "sortedExtensionsInUse", "unknownFields",
+
+    // MacTypes.h names
+    "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
+    "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
+    "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
+    "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
+    "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
+};
+
+hash_set<string> kReservedWords =
+    MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+
+string SanitizeNameForObjC(const string& input, const string& extension) {
+  if (kReservedWords.count(input) > 0) {
+    return input + extension;
+  }
+  return input;
+}
+
+string NameFromFieldDescriptor(const FieldDescriptor* field) {
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    return field->message_type()->name();
+  } else {
+    return field->name();
+  }
+}
+
+void PathSplit(const string& path, string* directory, string* basename) {
+  string::size_type last_slash = path.rfind('/');
+  if (last_slash == string::npos) {
+    if (directory) {
+      *directory = "";
+    }
+    if (basename) {
+      *basename = path;
+    }
+  } else {
+    if (directory) {
+      *directory = path.substr(0, last_slash);
+    }
+    if (basename) {
+      *basename = path.substr(last_slash + 1);
+    }
+  }
+}
+
+bool IsSpecialName(const string& name, const string* special_names,
+                   size_t count) {
+  for (size_t i = 0; i < count; ++i) {
+    size_t length = special_names[i].length();
+    if (name.compare(0, length, special_names[i]) == 0) {
+      if (name.length() > length) {
+        // If name is longer than the retained_name[i] that it matches
+        // the next character must be not lower case (newton vs newTon vs
+        // new_ton).
+        return !ascii_islower(name[length]);
+      } else {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+  return StringReplace(to_escape, "?", "\\?", true);
+}
+
+string StripProto(const string& filename) {
+  if (HasSuffixString(filename, ".protodevel")) {
+    return StripSuffixString(filename, ".protodevel");
+  } else {
+    return StripSuffixString(filename, ".proto");
+  }
+}
+
+bool IsRetainedName(const string& name) {
+  // List of prefixes from
+  // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
+  static const string retained_names[] = {"new", "alloc", "copy",
+                                          "mutableCopy"};
+  return IsSpecialName(name, retained_names,
+                       sizeof(retained_names) / sizeof(retained_names[0]));
+}
+
+bool IsInitName(const string& name) {
+  static const string init_names[] = {"init"};
+  return IsSpecialName(name, init_names,
+                       sizeof(init_names) / sizeof(init_names[0]));
+}
+
+string BaseFileName(const FileDescriptor* file) {
+  string basename;
+  PathSplit(file->name(), NULL, &basename);
+  return basename;
+}
+
+string FileName(const FileDescriptor* file) {
+  string path = FilePath(file);
+  string basename;
+  PathSplit(path, NULL, &basename);
+  return basename;
+}
+
+string FilePath(const FileDescriptor* file) {
+  string output;
+  string basename;
+  string directory;
+  PathSplit(file->name(), &directory, &basename);
+  if (directory.length() > 0) {
+    output = directory + "/";
+  }
+  basename = StripProto(basename);
+
+  // CamelCase to be more ObjC friendly.
+  basename = UnderscoresToCamelCase(basename, true);
+
+  output += basename;
+  return output;
+}
+
+string FileClassPrefix(const FileDescriptor* file) {
+  // Default is empty string, no need to check has_objc_class_prefix.
+  string result = file->options().objc_class_prefix();
+  return result;
+}
+
+string FileClassName(const FileDescriptor* file) {
+  string name = FileClassPrefix(file);
+  name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true);
+  name += "Root";
+  // There aren't really any reserved words that end in "Root", but playing
+  // it safe and checking.
+  return SanitizeNameForObjC(name, "_RootClass");
+}
+
+string ClassNameWorker(const Descriptor* descriptor) {
+  string name;
+  if (descriptor->containing_type() != NULL) {
+    name = ClassNameWorker(descriptor->containing_type());
+    name += "_";
+  }
+  return name + descriptor->name();
+}
+
+string ClassNameWorker(const EnumDescriptor* descriptor) {
+  string name;
+  if (descriptor->containing_type() != NULL) {
+    name = ClassNameWorker(descriptor->containing_type());
+    name += "_";
+  }
+  return name + descriptor->name();
+}
+
+string ClassName(const Descriptor* descriptor) {
+  // 1. Message names are used as is (style calls for CamelCase, trust it).
+  // 2. Check for reserved word at the very end and then suffix things.
+  string prefix = FileClassPrefix(descriptor->file());
+  string name = ClassNameWorker(descriptor);
+  return SanitizeNameForObjC(prefix + name, "_Class");
+}
+
+string EnumName(const EnumDescriptor* descriptor) {
+  // 1. Enum names are used as is (style calls for CamelCase, trust it).
+  // 2. Check for reserved word at the every end and then suffix things.
+  //      message Fixed {
+  //        message Size {...}
+  //        enum Mumble {...}
+  //      ...
+  //      }
+  //    yields Fixed_Class, Fixed_Size.
+  string name = FileClassPrefix(descriptor->file());
+  name += ClassNameWorker(descriptor);
+  return SanitizeNameForObjC(name, "_Enum");
+}
+
+string EnumValueName(const EnumValueDescriptor* descriptor) {
+  // Because of the Switch enum compatibility, the name on the enum has to have
+  // the suffix handing, so it slightly diverges from how nested classes work.
+  //   enum Fixed {
+  //     FOO = 1
+  //   }
+  // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
+  const string& class_name = EnumName(descriptor->type());
+  const string& value_str = UnderscoresToCamelCase(descriptor->name(), true);
+  const string& name = class_name + "_" + value_str;
+  // There aren't really any reserved words with an underscore and a leading
+  // capital letter, but playing it safe and checking.
+  return SanitizeNameForObjC(name, "_Value");
+}
+
+string EnumValueShortName(const EnumValueDescriptor* descriptor) {
+  // Enum value names (EnumValueName above) are the enum name turned into
+  // a class name and then the value name is CamelCased and concatenated; the
+  // whole thing then gets sanitized for reserved words.
+  // The "short name" is intended to be the final leaf, the value name; but
+  // you can't simply send that off to sanitize as that could result in it
+  // getting modified when the full name didn't.  For example enum
+  // "StorageModes" has a value "retain".  So the full name is
+  // "StorageModes_Retain", but if we sanitize "retain" it would become
+  // "RetainValue".
+  // So the right way to get the short name is to take the full enum name
+  // and then strip off the enum name (leaving the value name and anything
+  // done by sanitize).
+  const string& class_name = EnumName(descriptor->type());
+  const string& long_name_prefix = class_name + "_";
+  const string& long_name = EnumValueName(descriptor);
+  return StripPrefixString(long_name, long_name_prefix);
+}
+
+string UnCamelCaseEnumShortName(const string& name) {
+  string result;
+  for (int i = 0; i < name.size(); i++) {
+    char c = name[i];
+    if (i > 0 && ascii_isupper(c)) {
+      result += '_';
+    }
+    result += ascii_toupper(c);
+  }
+  return result;
+}
+
+string ExtensionMethodName(const FieldDescriptor* descriptor) {
+  const string& name = NameFromFieldDescriptor(descriptor);
+  const string& result = UnderscoresToCamelCase(name, false);
+  return SanitizeNameForObjC(result, "_Extension");
+}
+
+string FieldName(const FieldDescriptor* field) {
+  const string& name = NameFromFieldDescriptor(field);
+  string result = UnderscoresToCamelCase(name, false);
+  if (field->is_repeated() && !field->is_map()) {
+    // Add "Array" before do check for reserved worlds.
+    result += "Array";
+  } else {
+    // If it wasn't repeated, but ends in "Array", force on the _p suffix.
+    if (HasSuffixString(result, "Array")) {
+      result += "_p";
+    }
+  }
+  return SanitizeNameForObjC(result, "_p");
+}
+
+string FieldNameCapitalized(const FieldDescriptor* field) {
+  // Want the same suffix handling, so upcase the first letter of the other
+  // name.
+  string result = FieldName(field);
+  if (result.length() > 0) {
+    result[0] = ascii_toupper(result[0]);
+  }
+  return result;
+}
+
+string OneofEnumName(const OneofDescriptor* descriptor) {
+  const Descriptor* fieldDescriptor = descriptor->containing_type();
+  string name = ClassName(fieldDescriptor);
+  name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
+  // No sanitize needed because the OS never has names that end in _OneOfCase.
+  return name;
+}
+
+string OneofName(const OneofDescriptor* descriptor) {
+  string name = UnderscoresToCamelCase(descriptor->name(), false);
+  // No sanitize needed because it gets OneOfCase added and that shouldn't
+  // ever conflict.
+  return name;
+}
+
+string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+  // Use the common handling and then up-case the first letter.
+  string result = OneofName(descriptor);
+  if (result.length() > 0) {
+    result[0] = ascii_toupper(result[0]);
+  }
+  return result;
+}
+
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
+  string worker(name);
+  if (HasSuffixString(worker, "_p")) {
+    worker = StripSuffixString(worker, "_p");
+  }
+  if (field->is_repeated() && HasSuffixString(worker, "Array")) {
+    worker = StripSuffixString(worker, "Array");
+  }
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    if (worker.length() > 0) {
+      if (ascii_islower(worker[0])) {
+        worker[0] = ascii_toupper(worker[0]);
+      }
+    }
+    return worker;
+  } else {
+    string result;
+    for (int i = 0; i < worker.size(); i++) {
+      char c = worker[i];
+      if (ascii_isupper(c)) {
+        if (i > 0) {
+          result += '_';
+        }
+        result += ascii_tolower(c);
+      } else {
+        result += c;
+      }
+    }
+    return result;
+  }
+}
+
+string GetCapitalizedType(const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+      return "Int32";
+    case FieldDescriptor::TYPE_UINT32:
+      return "UInt32";
+    case FieldDescriptor::TYPE_SINT32:
+      return "SInt32";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "Fixed32";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "SFixed32";
+    case FieldDescriptor::TYPE_INT64:
+      return "Int64";
+    case FieldDescriptor::TYPE_UINT64:
+      return "UInt64";
+    case FieldDescriptor::TYPE_SINT64:
+      return "SInt64";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "Fixed64";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "Float";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "Double";
+    case FieldDescriptor::TYPE_BOOL:
+      return "Bool";
+    case FieldDescriptor::TYPE_STRING:
+      return "String";
+    case FieldDescriptor::TYPE_BYTES:
+      return "Bytes";
+    case FieldDescriptor::TYPE_ENUM:
+      return "Enum";
+    case FieldDescriptor::TYPE_GROUP:
+      return "Group";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "Message";
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
+  switch (field_type) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+      return OBJECTIVECTYPE_INT32;
+
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+      return OBJECTIVECTYPE_UINT32;
+
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      return OBJECTIVECTYPE_INT64;
+
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+      return OBJECTIVECTYPE_UINT64;
+
+    case FieldDescriptor::TYPE_FLOAT:
+      return OBJECTIVECTYPE_FLOAT;
+
+    case FieldDescriptor::TYPE_DOUBLE:
+      return OBJECTIVECTYPE_DOUBLE;
+
+    case FieldDescriptor::TYPE_BOOL:
+      return OBJECTIVECTYPE_BOOLEAN;
+
+    case FieldDescriptor::TYPE_STRING:
+      return OBJECTIVECTYPE_STRING;
+
+    case FieldDescriptor::TYPE_BYTES:
+      return OBJECTIVECTYPE_DATA;
+
+    case FieldDescriptor::TYPE_ENUM:
+      return OBJECTIVECTYPE_ENUM;
+
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      return OBJECTIVECTYPE_MESSAGE;
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return OBJECTIVECTYPE_INT32;
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field) {
+  ObjectiveCType type = GetObjectiveCType(field);
+  switch (type) {
+    case OBJECTIVECTYPE_INT32:
+    case OBJECTIVECTYPE_UINT32:
+    case OBJECTIVECTYPE_INT64:
+    case OBJECTIVECTYPE_UINT64:
+    case OBJECTIVECTYPE_FLOAT:
+    case OBJECTIVECTYPE_DOUBLE:
+    case OBJECTIVECTYPE_BOOLEAN:
+    case OBJECTIVECTYPE_ENUM:
+      return true;
+      break;
+    default:
+      return false;
+  }
+}
+
+bool IsReferenceType(const FieldDescriptor* field) {
+  return !IsPrimitiveType(field);
+}
+
+static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) {
+  if (val == "nan") {
+    return "NAN";
+  } else if (val == "inf") {
+    return "INFINITY";
+  } else if (val == "-inf") {
+    return "-INFINITY";
+  } else {
+    // float strings with ., e or E need to have f appended
+    if (add_float_suffix &&
+        (val.find(".") != string::npos || val.find("e") != string::npos ||
+         val.find("E") != string::npos)) {
+      val += "f";
+    }
+    return val;
+  }
+}
+
+string GPBGenericValueFieldName(const FieldDescriptor* field) {
+  // Returns the field within the GPBGenericValue union to use for the given
+  // field.
+  if (field->is_repeated()) {
+      return "valueMessage";
+  }
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return "valueInt32";
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return "valueUInt32";
+    case FieldDescriptor::CPPTYPE_INT64:
+      return "valueInt64";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return "valueUInt64";
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return "valueFloat";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return "valueDouble";
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return "valueBool";
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (field->type() == FieldDescriptor::TYPE_BYTES) {
+        return "valueData";
+      } else {
+        return "valueString";
+      }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return "valueEnum";
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "valueMessage";
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+
+string DefaultValue(const FieldDescriptor* field) {
+  // Repeated fields don't have defaults.
+  if (field->is_repeated()) {
+    return "nil";
+  }
+
+  // Switch on cpp_type since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      // gcc and llvm reject the decimal form of kint32min and kint64min.
+      if (field->default_value_int32() == INT_MIN) {
+        return "-0x80000000";
+      }
+      return SimpleItoa(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return SimpleItoa(field->default_value_uint32()) + "U";
+    case FieldDescriptor::CPPTYPE_INT64:
+      // gcc and llvm reject the decimal form of kint32min and kint64min.
+      if (field->default_value_int64() == LLONG_MIN) {
+        return "-0x8000000000000000LL";
+      }
+      return SimpleItoa(field->default_value_int64()) + "LL";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return SimpleItoa(field->default_value_uint64()) + "ULL";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return HandleExtremeFloatingPoint(
+          SimpleDtoa(field->default_value_double()), false);
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return HandleExtremeFloatingPoint(
+          SimpleFtoa(field->default_value_float()), true);
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "YES" : "NO";
+    case FieldDescriptor::CPPTYPE_STRING: {
+      const bool has_default_value = field->has_default_value();
+      const string& default_string = field->default_value_string();
+      if (!has_default_value || default_string.length() == 0) {
+        // If the field is defined as being the empty string,
+        // then we will just assign to nil, as the empty string is the
+        // default for both strings and data.
+        return "nil";
+      }
+      if (field->type() == FieldDescriptor::TYPE_BYTES) {
+        // We want constant fields in our data structures so we can
+        // declare them as static. To achieve this we cheat and stuff
+        // a escaped c string (prefixed with a length) into the data
+        // field, and cast it to an (NSData*) so it will compile.
+        // The runtime library knows how to handle it.
+
+        // Must convert to a standard byte order for packing length into
+        // a cstring.
+        uint32 length = ghtonl(default_string.length());
+        string bytes((const char*)&length, sizeof(length));
+        bytes.append(default_string);
+        return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
+      } else {
+        return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return EnumValueName(field->default_value_enum());
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "nil";
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
+  // Repeated fields don't have defaults.
+  if (field->is_repeated()) {
+    return false;
+  }
+
+  // As much as checking field->has_default_value() seems useful, it isn't
+  // because of enums. proto2 syntax allows the first item in an enum (the
+  // default) to be non zero. So checking field->has_default_value() would
+  // result in missing this non zero default.  See MessageWithOneBasedEnum in
+  // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
+
+  // Some proto file set the default to the zero value, so make sure the value
+  // isn't the zero case.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() != 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() != 0U;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() != 0LL;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() != 0ULL;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() != 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() != 0.0f;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool();
+    case FieldDescriptor::CPPTYPE_STRING: {
+      const string& default_string = field->default_value_string();
+      return default_string.length() != 0;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() != 0;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+string BuildFlagsString(const vector<string>& strings) {
+  if (strings.size() == 0) {
+    return "0";
+  }
+  string string;
+  for (size_t i = 0; i != strings.size(); ++i) {
+    if (i > 0) {
+      string.append(" | ");
+    }
+    string.append(strings[i]);
+  }
+  return string;
+}
+
+string BuildCommentsString(const SourceLocation& location) {
+  const string& comments = location.leading_comments.empty()
+                               ? location.trailing_comments
+                               : location.leading_comments;
+  vector<string> lines;
+  SplitStringAllowEmpty(comments, "\n", &lines);
+  while (!lines.empty() && lines.back().empty()) {
+    lines.pop_back();
+  }
+  string prefix("///");
+  string suffix("\n");
+  string final_comments;
+  for (int i = 0; i < lines.size(); i++) {
+    // HeaderDoc uses '\' and '@' for markers; escape them.
+    const string line = StringReplace(lines[i], "\\", "\\\\", true);
+    final_comments +=
+        prefix + StringReplace(line, "@", "\\@", true) + suffix;
+  }
+  return final_comments;
+}
+
+namespace {
+
+// Internal helper class that parses the expected package to prefix mappings
+// file.
+class Parser {
+ public:
+  Parser(map<string, string>* inout_package_to_prefix_map)
+      : prefix_map_(inout_package_to_prefix_map), line_(0) {}
+
+  // Parses a check of input, returning success/failure.
+  bool ParseChunk(StringPiece chunk);
+
+  // Should be called to finish parsing (after all input has been provided via
+  // ParseChunk()).  Returns success/failure.
+  bool Finish();
+
+  int last_line() const { return line_; }
+  string error_str() const { return error_str_; }
+
+ private:
+  bool ParseLoop();
+
+  map<string, string>* prefix_map_;
+  int line_;
+  string error_str_;
+  StringPiece p_;
+  string leftover_;
+};
+
+bool Parser::ParseChunk(StringPiece chunk) {
+  if (!leftover_.empty()) {
+    chunk.AppendToString(&leftover_);
+    p_ = StringPiece(leftover_);
+  } else {
+    p_ = chunk;
+  }
+  bool result = ParseLoop();
+  if (p_.empty()) {
+    leftover_.clear();
+  } else {
+    leftover_ = p_.ToString();
+  }
+  return result;
+}
+
+bool Parser::Finish() {
+  if (leftover_.empty()) {
+    return true;
+  }
+  // Force a newline onto the end to finish parsing.
+  p_ = StringPiece(leftover_ + "\n");
+  if (!ParseLoop()) {
+    return false;
+  }
+  return p_.empty();  // Everything used?
+}
+
+static bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; }
+
+bool ReadLine(StringPiece* input, StringPiece* line) {
+  for (int len = 0; len < input->size(); ++len) {
+    if (ascii_isnewline((*input)[len])) {
+      *line = StringPiece(input->data(), len);
+      ++len;  // advance over the newline
+      *input = StringPiece(input->data() + len, input->size() - len);
+      return true;
+    }
+  }
+  return false;  // Ran out of input with no newline.
+}
+
+void TrimWhitespace(StringPiece* input) {
+  while (!input->empty() && ascii_isspace(*input->data())) {
+    input->remove_prefix(1);
+  }
+  while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
+    input->remove_suffix(1);
+  }
+}
+
+void RemoveComment(StringPiece* input) {
+  int offset = input->find('#');
+  if (offset != StringPiece::npos) {
+    input->remove_suffix(input->length() - offset);
+  }
+}
+
+bool Parser::ParseLoop() {
+  StringPiece line;
+  while (ReadLine(&p_, &line)) {
+    ++line_;
+    RemoveComment(&line);
+    TrimWhitespace(&line);
+    if (line.size() == 0) {
+      continue;  // Blank line.
+    }
+    int offset = line.find('=');
+    if (offset == StringPiece::npos) {
+      error_str_ =
+          string("Line without equal sign: '") + line.ToString() + "'.";
+      return false;
+    }
+    StringPiece package(line, 0, offset);
+    StringPiece prefix(line, offset + 1, line.length() - offset - 1);
+    TrimWhitespace(&package);
+    TrimWhitespace(&prefix);
+    // Don't really worry about error checking the package/prefix for
+    // being valid.  Assume the file is validated when it is created/edited.
+    (*prefix_map_)[package.ToString()] = prefix.ToString();
+  }
+  return true;
+}
+
+bool LoadExpectedPackagePrefixes(const Options &generation_options,
+                                 map<string, string>* prefix_map,
+                                 string* out_error) {
+  if (generation_options.expected_prefixes_path.empty()) {
+    return true;
+  }
+
+  int fd;
+  do {
+    fd = open(generation_options.expected_prefixes_path.c_str(), O_RDONLY);
+  } while (fd < 0 && errno == EINTR);
+  if (fd < 0) {
+    *out_error =
+        string("error: Unable to open \"") +
+        generation_options.expected_prefixes_path +
+        "\", " + strerror(errno);
+    return false;
+  }
+  io::FileInputStream file_stream(fd);
+  file_stream.SetCloseOnDelete(true);
+
+  Parser parser(prefix_map);
+  const void* buf;
+  int buf_len;
+  while (file_stream.Next(&buf, &buf_len)) {
+    if (buf_len == 0) {
+      continue;
+    }
+
+    if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
+      *out_error =
+          string("error: ") + generation_options.expected_prefixes_path +
+          " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str();
+      return false;
+    }
+  }
+  return parser.Finish();
+}
+
+}  // namespace
+
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+                             const Options& generation_options,
+                             string* out_error) {
+  const string prefix = file->options().objc_class_prefix();
+  const string package = file->package();
+
+  // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+  // error cases, so it seems to be ok to use as a back door for warnings.
+
+  // Load any expected package prefixes to validate against those.
+  map<string, string> expected_package_prefixes;
+  if (!LoadExpectedPackagePrefixes(generation_options,
+                                   &expected_package_prefixes,
+                                   out_error)) {
+    return false;
+  }
+
+  // Check: Error - See if there was an expected prefix for the package and
+  // report if it doesn't match (wrong or missing).
+  map<string, string>::iterator package_match =
+      expected_package_prefixes.find(package);
+  if (package_match != expected_package_prefixes.end()) {
+    // There was an entry, and...
+    if (package_match->second == prefix) {
+      // ...it matches.  All good, out of here!
+      return true;
+    } else {
+      // ...it didn't match!
+      *out_error = "error: Expected 'option objc_class_prefix = \"" +
+                   package_match->second + "\";' for package '" + package +
+                   "' in '" + file->name() + "'";
+      if (prefix.length()) {
+        *out_error += "; but found '" + prefix + "' instead";
+      }
+      *out_error += ".";
+      return false;
+    }
+  }
+
+  // If there was no prefix option, we're done at this point.
+  if (prefix.length() == 0) {
+    // No prefix, nothing left to check.
+    return true;
+  }
+
+  // Check: Error - Make sure the prefix wasn't expected for a different
+  // package (overlap is allowed, but it has to be listed as an expected
+  // overlap).
+  for (map<string, string>::iterator i = expected_package_prefixes.begin();
+       i != expected_package_prefixes.end(); ++i) {
+    if (i->second == prefix) {
+      *out_error =
+          "error: Found 'option objc_class_prefix = \"" + prefix +
+          "\";' in '" + file->name() +
+          "'; that prefix is already used for 'package " + i->first +
+          ";'. It can only be reused by listing it in the expected file (" +
+          generation_options.expected_prefixes_path + ").";
+      return false;  // Only report first usage of the prefix.
+    }
+  }
+
+  // Check: Warning - Make sure the prefix is is a reasonable value according
+  // to Apple's rules (the checks above implicitly whitelist anything that
+  // doesn't meet these rules).
+  if (!ascii_isupper(prefix[0])) {
+    cerr << endl
+         << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+         << prefix << "\";' in '" << file->name() << "';"
+         << " it should start with a capital letter." << endl;
+    cerr.flush();
+  }
+  if (prefix.length() < 3) {
+    // Apple reserves 2 character prefixes for themselves. They do use some
+    // 3 character prefixes, but they haven't updated the rules/docs.
+    cerr << endl
+         << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+         << prefix << "\";' in '" << file->name() << "';"
+         << " Apple recommends they should be at least 3 characters long."
+         << endl;
+    cerr.flush();
+  }
+
+  // Check: Warning - If the given package/prefix pair wasn't expected, issue a
+  // warning issue a warning suggesting it gets added to the file.
+  if (!expected_package_prefixes.empty()) {
+    cerr << endl
+         << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
+         << prefix << "\";' in '" << file->name() << "';"
+         << " consider adding it to the expected prefixes file ("
+         << generation_options.expected_prefixes_path << ")." << endl;
+    cerr.flush();
+  }
+
+  return true;
+}
+
+void TextFormatDecodeData::AddString(int32 key,
+                                     const string& input_for_decode,
+                                     const string& desired_output) {
+  for (vector<DataEntry>::const_iterator i = entries_.begin();
+       i != entries_.end(); ++i) {
+    if (i->first == key) {
+      cerr << "error: duplicate key (" << key
+           << ") making TextFormat data, input: \"" << input_for_decode
+           << "\", desired: \"" << desired_output << "\"." << endl;
+      cerr.flush();
+      abort();
+    }
+  }
+
+  const string& data = TextFormatDecodeData::DecodeDataForString(
+      input_for_decode, desired_output);
+  entries_.push_back(DataEntry(key, data));
+}
+
+string TextFormatDecodeData::Data() const {
+  ostringstream data_stringstream;
+
+  if (num_entries() > 0) {
+    io::OstreamOutputStream data_outputstream(&data_stringstream);
+    io::CodedOutputStream output_stream(&data_outputstream);
+
+    output_stream.WriteVarint32(num_entries());
+    for (vector<DataEntry>::const_iterator i = entries_.begin();
+         i != entries_.end(); ++i) {
+      output_stream.WriteVarint32(i->first);
+      output_stream.WriteString(i->second);
+    }
+  }
+
+  data_stringstream.flush();
+  return data_stringstream.str();
+}
+
+namespace {
+
+// Helper to build up the decode data for a string.
+class DecodeDataBuilder {
+ public:
+  DecodeDataBuilder() { Reset(); }
+
+  bool AddCharacter(const char desired, const char input);
+  void AddUnderscore() {
+    Push();
+    need_underscore_ = true;
+  }
+  string Finish() {
+    Push();
+    return decode_data_;
+  }
+
+ private:
+  static const uint8 kAddUnderscore = 0x80;
+
+  static const uint8 kOpAsIs        = 0x00;
+  static const uint8 kOpFirstUpper  = 0x40;
+  static const uint8 kOpFirstLower  = 0x20;
+  static const uint8 kOpAllUpper    = 0x60;
+
+  static const int kMaxSegmentLen     = 0x1f;
+
+  void AddChar(const char desired) {
+    ++segment_len_;
+    is_all_upper_ &= ascii_isupper(desired);
+  }
+
+  void Push() {
+    uint8 op = (op_ | segment_len_);
+    if (need_underscore_) op |= kAddUnderscore;
+    if (op != 0) {
+      decode_data_ += (char)op;
+    }
+    Reset();
+  }
+
+  bool AddFirst(const char desired, const char input) {
+    if (desired == input) {
+      op_ = kOpAsIs;
+    } else if (desired == ascii_toupper(input)) {
+      op_ = kOpFirstUpper;
+    } else if (desired == ascii_tolower(input)) {
+      op_ = kOpFirstLower;
+    } else {
+      // Can't be transformed to match.
+      return false;
+    }
+    AddChar(desired);
+    return true;
+  }
+
+  void Reset() {
+    need_underscore_ = false;
+    op_ = 0;
+    segment_len_ = 0;
+    is_all_upper_ = true;
+  }
+
+  bool need_underscore_;
+  bool is_all_upper_;
+  uint8 op_;
+  int segment_len_;
+
+  string decode_data_;
+};
+
+bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
+  // If we've hit the max size, push to start a new segment.
+  if (segment_len_ == kMaxSegmentLen) {
+    Push();
+  }
+  if (segment_len_ == 0) {
+    return AddFirst(desired, input);
+  }
+
+  // Desired and input match...
+  if (desired == input) {
+    // If we aren't transforming it, or we're upper casing it and it is
+    // supposed to be uppercase; just add it to the segment.
+    if ((op_ != kOpAllUpper) || ascii_isupper(desired)) {
+      AddChar(desired);
+      return true;
+    }
+
+    // Add the current segment, and start the next one.
+    Push();
+    return AddFirst(desired, input);
+  }
+
+  // If we need to uppercase, and everything so far has been uppercase,
+  // promote op to AllUpper.
+  if ((desired == ascii_toupper(input)) && is_all_upper_) {
+    op_ = kOpAllUpper;
+    AddChar(desired);
+    return true;
+  }
+
+  // Give up, push and start a new segment.
+  Push();
+  return AddFirst(desired, input);
+}
+
+// If decode data can't be generated, a directive for the raw string
+// is used instead.
+string DirectDecodeString(const string& str) {
+  string result;
+  result += (char)'\0';  // Marker for full string.
+  result += str;
+  result += (char)'\0';  // End of string.
+  return result;
+}
+
+}  // namespace
+
+// static
+string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
+                                                 const string& desired_output) {
+  if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) {
+    cerr << "error: got empty string for making TextFormat data, input: \""
+         << input_for_decode << "\", desired: \"" << desired_output << "\"."
+         << endl;
+    cerr.flush();
+    abort();
+  }
+  if ((input_for_decode.find('\0') != string::npos) ||
+      (desired_output.find('\0') != string::npos)) {
+    cerr << "error: got a null char in a string for making TextFormat data,"
+         << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
+         << CEscape(desired_output) << "\"." << endl;
+    cerr.flush();
+    abort();
+  }
+
+  DecodeDataBuilder builder;
+
+  // Walk the output building it from the input.
+  int x = 0;
+  for (int y = 0; y < desired_output.size(); y++) {
+    const char d = desired_output[y];
+    if (d == '_') {
+      builder.AddUnderscore();
+      continue;
+    }
+
+    if (x >= input_for_decode.size()) {
+      // Out of input, no way to encode it, just return a full decode.
+      return DirectDecodeString(desired_output);
+    }
+    if (builder.AddCharacter(d, input_for_decode[x])) {
+      ++x;  // Consumed one input
+    } else {
+      // Couldn't transform for the next character, just return a full decode.
+      return DirectDecodeString(desired_output);
+    }
+  }
+
+  if (x != input_for_decode.size()) {
+    // Extra input (suffix from name sanitizing?), just return a full decode.
+    return DirectDecodeString(desired_output);
+  }
+
+  // Add the end marker.
+  return builder.Finish() + (char)'\0';
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
new file mode 100644
index 0000000..3f56d94
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -0,0 +1,204 @@
+// 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_COMPILER_OBJECTIVEC_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Generator options (see objectivec_generator.cc for a description of each):
+struct Options {
+  Options();
+  string expected_prefixes_path;
+};
+
+// Escape C++ trigraphs by escaping question marks to "\?".
+string EscapeTrigraphs(const string& to_escape);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Returns true if the name requires a ns_returns_not_retained attribute applied
+// to it.
+bool IsRetainedName(const string& name);
+
+// Returns true if the name starts with "init" and will need to have special
+// handling under ARC.
+bool IsInitName(const string& name);
+
+// Gets the name of the file we're going to generate (sans the .pb.h
+// extension).  This does not include the path to that file.
+string FileName(const FileDescriptor* file);
+
+// Gets the path of the file we're going to generate (sans the .pb.h
+// extension).  The path will be dependent on the objectivec package
+// declared in the proto package.
+string FilePath(const FileDescriptor* file);
+
+// Gets the name of the root class we'll generate in the file.  This class
+// is not meant for external consumption, but instead contains helpers that
+// the rest of the classes need
+string FileClassName(const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+string ClassName(const Descriptor* descriptor);
+string EnumName(const EnumDescriptor* descriptor);
+
+// Returns the fully-qualified name of the enum value corresponding to the
+// the descriptor.
+string EnumValueName(const EnumValueDescriptor* descriptor);
+
+// Returns the name of the enum value corresponding to the descriptor.
+string EnumValueShortName(const EnumValueDescriptor* descriptor);
+
+// Reverse what an enum does.
+string UnCamelCaseEnumShortName(const string& name);
+
+// Returns the name to use for the extension (used as the method off the file's
+// Root class).
+string ExtensionMethodName(const FieldDescriptor* descriptor);
+
+// Returns the transformed field name.
+string FieldName(const FieldDescriptor* field);
+string FieldNameCapitalized(const FieldDescriptor* field);
+
+// Returns the transformed oneof name.
+string OneofEnumName(const OneofDescriptor* descriptor);
+string OneofName(const OneofDescriptor* descriptor);
+string OneofNameCapitalized(const OneofDescriptor* descriptor);
+
+inline bool HasFieldPresence(const FileDescriptor* file) {
+  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
+// Reverse of the above.
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field);
+
+enum ObjectiveCType {
+  OBJECTIVECTYPE_INT32,
+  OBJECTIVECTYPE_UINT32,
+  OBJECTIVECTYPE_INT64,
+  OBJECTIVECTYPE_UINT64,
+  OBJECTIVECTYPE_FLOAT,
+  OBJECTIVECTYPE_DOUBLE,
+  OBJECTIVECTYPE_BOOLEAN,
+  OBJECTIVECTYPE_STRING,
+  OBJECTIVECTYPE_DATA,
+  OBJECTIVECTYPE_ENUM,
+  OBJECTIVECTYPE_MESSAGE
+};
+
+template<class TDescriptor>
+string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) {
+  if (descriptor->options().deprecated()) {
+    string result = "DEPRECATED_ATTRIBUTE";
+    if (preSpace) {
+      result.insert(0, " ");
+    }
+    if (postNewline) {
+      result.append("\n");
+    }
+    return result;
+  } else {
+    return "";
+  }
+}
+
+string GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
+
+inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
+  return GetObjectiveCType(field->type());
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field);
+bool IsReferenceType(const FieldDescriptor* field);
+
+string GPBGenericValueFieldName(const FieldDescriptor* field);
+string DefaultValue(const FieldDescriptor* field);
+bool HasNonZeroDefaultValue(const FieldDescriptor* field);
+
+string BuildFlagsString(const vector<string>& strings);
+
+// Builds a HeaderDoc style comment out of the comments in the .proto file.
+string BuildCommentsString(const SourceLocation& location);
+
+// Checks the prefix for a given file and outputs any warnings needed, if
+// there are flat out errors, then out_error is filled in and the result is
+// false.
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+                             const Options& generation_options,
+                             string* out_error);
+
+// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
+// the input into the expected output.
+class LIBPROTOC_EXPORT TextFormatDecodeData {
+ public:
+  TextFormatDecodeData() {}
+
+  void AddString(int32 key, const string& input_for_decode,
+                 const string& desired_output);
+  size_t num_entries() const { return entries_.size(); }
+  string Data() const;
+
+  static string DecodeDataForString(const string& input_for_decode,
+                                    const string& desired_output);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData);
+
+  typedef std::pair<int32, string> DataEntry;
+  vector<DataEntry> entries_;
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
new file mode 100644
index 0000000..dc1cef5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -0,0 +1,257 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
+  string input_for_decode("abcdefghIJ");
+  string desired_output_for_decode;
+  string expected;
+  string result;
+
+  // Different data, can't transform.
+
+  desired_output_for_decode = "zbcdefghIJ";
+  expected = string("\0zbcdefghIJ\0", 12);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  desired_output_for_decode = "abcdezghIJ";
+  expected = string("\0abcdezghIJ\0", 12);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  // Shortened data, can't transform.
+
+  desired_output_for_decode = "abcdefghI";
+  expected = string("\0abcdefghI\0", 11);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  // Extra data, can't transform.
+
+  desired_output_for_decode = "abcdefghIJz";
+  expected = string("\0abcdefghIJz\0", 13);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
+  string input_for_decode("abcdefghIJ");
+  string desired_output_for_decode;
+  string expected;
+  string result;
+
+  desired_output_for_decode = "abcdefghIJ";
+  expected = string("\x0A\x0", 2);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  desired_output_for_decode = "_AbcdefghIJ";
+  expected = string("\xCA\x0", 2);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  desired_output_for_decode = "ABCD__EfghI_j";
+  expected = string("\x64\x80\xC5\xA1\x0", 5);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+
+  // Long name so multiple decode ops are needed.
+
+  input_for_decode =
+      "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+  desired_output_for_decode =
+      "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
+  expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
+  result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+                                                     desired_output_for_decode);
+  EXPECT_EQ(expected, result);
+}
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
+  // Empty inputs.
+
+  EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+  EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+  EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+
+  // Null char in the string.
+
+  string str_with_null_char("ab\0c", 4);
+  EXPECT_EXIT(
+      TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
+      ::testing::KilledBySignal(SIGABRT),
+      "error: got a null char in a string for making TextFormat data, input:");
+  EXPECT_EXIT(
+      TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
+      ::testing::KilledBySignal(SIGABRT),
+      "error: got a null char in a string for making TextFormat data, input:");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
+  TextFormatDecodeData decode_data;
+
+  // Different data, can't transform.
+  decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
+  decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
+  // Shortened data, can't transform.
+  decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
+  // Extra data, can't transform.
+  decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
+
+  EXPECT_EQ(4, decode_data.num_entries());
+
+  uint8 expected_data[] = {
+      0x4,
+      0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+      0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
+      0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
+      0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
+  };
+  string expected((const char*)expected_data, sizeof(expected_data));
+
+  EXPECT_EQ(expected, decode_data.Data());
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
+  TextFormatDecodeData decode_data;
+
+  decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+  decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+  decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+  decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
+  decode_data.AddString(1000,
+                        "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
+                        "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+
+  EXPECT_EQ(5, decode_data.num_entries());
+
+  uint8 expected_data[] = {
+      0x5,
+      // All as is (00 op)
+      0x1,  0x0A, 0x0,
+      // Underscore, upper + 9 (10 op)
+      0x3,  0xCA, 0x0,
+      //  Upper + 3 (10 op), underscore, upper + 5 (10 op)
+      0x2,  0x44, 0xC6, 0x0,
+      // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+      // underscore, lower + 0 (01 op)
+      0x4,  0x64, 0x80, 0xC5, 0xA1, 0x0,
+      // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+      //   underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+      //   underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
+      //   op),
+      //   underscore, as is + 3 (00 op)
+      0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+  };
+  string expected((const char*)expected_data, sizeof(expected_data));
+
+  EXPECT_EQ(expected, decode_data.Data());
+}
+
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
+  TextFormatDecodeData decode_data;
+
+  // Empty inputs.
+
+  EXPECT_EXIT(decode_data.AddString(1, "", ""),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+  EXPECT_EXIT(decode_data.AddString(1, "a", ""),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+  EXPECT_EXIT(decode_data.AddString(1, "", "a"),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: got empty string for making TextFormat data, input:");
+
+  // Null char in the string.
+
+  string str_with_null_char("ab\0c", 4);
+  EXPECT_EXIT(
+      decode_data.AddString(1, str_with_null_char, "def"),
+      ::testing::KilledBySignal(SIGABRT),
+      "error: got a null char in a string for making TextFormat data, input:");
+  EXPECT_EXIT(
+      decode_data.AddString(1, "def", str_with_null_char),
+      ::testing::KilledBySignal(SIGABRT),
+      "error: got a null char in a string for making TextFormat data, input:");
+
+  // Duplicate keys
+
+  decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+  decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+  decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+  EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"),
+              ::testing::KilledBySignal(SIGABRT),
+              "error: duplicate key \\(2\\) making TextFormat data, input:");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+// TODO(thomasvl): Should probably add some unittests for all the special cases
+// of name mangling (class name, field name, enum names).  Rather than doing
+// this with an ObjC test in the objectivec directory, we should be able to
+// use src/google/protobuf/compiler/importer* (like other tests) to support a
+// virtual file system to feed in protos, once we have the Descriptor tree, the
+// tests could use the helper methods for generating names and validate the
+// right things are happening.
+
+}  // namespace
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
new file mode 100644
index 0000000..ac5d8ae
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it
+// provides a bunch of things (no has* methods, comments for contained type,
+// etc.).
+
+namespace {
+
+const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
+  ObjectiveCType type = GetObjectiveCType(descriptor);
+  switch (type) {
+    case OBJECTIVECTYPE_INT32:
+      return "Int32";
+    case OBJECTIVECTYPE_UINT32:
+      return "UInt32";
+    case OBJECTIVECTYPE_INT64:
+      return "Int64";
+    case OBJECTIVECTYPE_UINT64:
+      return "UInt64";
+    case OBJECTIVECTYPE_FLOAT:
+      return "Float";
+    case OBJECTIVECTYPE_DOUBLE:
+      return "Double";
+    case OBJECTIVECTYPE_BOOLEAN:
+      return "Bool";
+    case OBJECTIVECTYPE_STRING:
+      return (isKey ? "String" : "Object");
+    case OBJECTIVECTYPE_DATA:
+      return "Object";
+    case OBJECTIVECTYPE_ENUM:
+      return "Enum";
+    case OBJECTIVECTYPE_MESSAGE:
+      return "Object";
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+}  // namespace
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
+  const FieldDescriptor* key_descriptor =
+      descriptor->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value_descriptor =
+      descriptor->message_type()->FindFieldByName("value");
+  value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
+
+  // Pull over some variables_ from the value.
+  variables_["field_type"] = value_field_generator_->variable("field_type");
+  variables_["default"] = value_field_generator_->variable("default");
+  variables_["default_name"] = value_field_generator_->variable("default_name");
+
+  // Build custom field flags.
+  std::vector<string> field_flags;
+  field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
+  // Pull over the current text format custom name values that was calculated.
+  if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
+      string::npos) {
+    field_flags.push_back("GPBFieldTextFormatNameCustom");
+  }
+  // Pull over some info from the value's flags.
+  const string& value_field_flags =
+      value_field_generator_->variable("fieldflags");
+  if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) {
+    field_flags.push_back("GPBFieldHasDefaultValue");
+  }
+  if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
+    field_flags.push_back("GPBFieldHasEnumDescriptor");
+  }
+  variables_["fieldflags"] = BuildFlagsString(field_flags);
+
+  ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+  const bool value_is_object_type =
+      ((value_objc_type == OBJECTIVECTYPE_STRING) ||
+       (value_objc_type == OBJECTIVECTYPE_DATA) ||
+       (value_objc_type == OBJECTIVECTYPE_MESSAGE));
+  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+      value_is_object_type) {
+    variables_["array_storage_type"] = "NSMutableDictionary";
+    variables_["array_property_type"] =
+        "NSMutableDictionary<NSString*, " +
+        value_field_generator_->variable("storage_type") + "*>";
+  } else {
+    string class_name("GPB");
+    class_name += MapEntryTypeName(key_descriptor, true);
+    class_name += MapEntryTypeName(value_descriptor, false);
+    class_name += "Dictionary";
+    variables_["array_storage_type"] = class_name;
+    if (value_is_object_type) {
+      variables_["array_property_type"] =
+          class_name + "<" +
+          value_field_generator_->variable("storage_type") + "*>";
+    }
+  }
+
+  variables_["dataTypeSpecific_name"] =
+      value_field_generator_->variable("dataTypeSpecific_name");
+  variables_["dataTypeSpecific_value"] =
+      value_field_generator_->variable("dataTypeSpecific_value");
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  // Use the array_comment support in RepeatedFieldGenerator to output what the
+  // values in the map are.
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
+    variables_["array_comment"] =
+        "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+  }
+}
+
+void MapFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+    const string& value_storage_type =
+        value_field_generator_->variable("storage_type");
+    fwd_decls->insert("@class " + value_storage_type);
+  }
+}
+
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
new file mode 100644
index 0000000..bc68a68
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MapFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ public:
+  virtual void FinishInitialization(void);
+
+ protected:
+  MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+  virtual ~MapFieldGenerator();
+
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ private:
+  scoped_ptr<FieldGenerator> value_field_generator_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.cc
new file mode 100644
index 0000000..bf27259
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -0,0 +1,600 @@
+// 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.
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+struct FieldOrderingByNumber {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    return a->number() < b->number();
+  }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+  // The first item in the object structure is our uint32[] for has bits.
+  // We then want to order things to make the instances as small as
+  // possible. So we follow the has bits with:
+  //   1. Anything always 4 bytes - float, *32, enums
+  //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
+  //      builds and 4 bytes on 32bit builds.
+  //   3. Anything always 8 bytes - double, *64
+  //
+  // NOTE: Bools aren't listed, they were stored in the has bits.
+  //
+  // Why? Using 64bit builds as an example, this means worse case, we have
+  // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+  // are wasted before the 4 byte values. Then if we have an odd number of
+  // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+  // keep them aligned. But the structure will end 8 byte aligned, so no
+  // waste on the end. If you did the reverse order, you could waste 4 bytes
+  // before the first 8 byte value (after the has array), then a single
+  // bool on the end would need 7 bytes of padding to make the overall
+  // structure 8 byte aligned; so 11 bytes, wasted total.
+
+  // Anything repeated is a GPB*Array/NSArray, so pointer.
+  if (descriptor->is_repeated()) {
+    return 3;
+  }
+
+  switch (descriptor->type()) {
+    // All always 8 bytes.
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_FIXED64:
+      return 4;
+
+    // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+    // depending on the build architecture.
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      return 3;
+
+    // All always 4 bytes (enums are int32s).
+    case FieldDescriptor::TYPE_FLOAT:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_ENUM:
+      return 2;
+
+    // 0 bytes. Stored in the has bits.
+    case FieldDescriptor::TYPE_BOOL:
+      return 99;  // End of the list (doesn't really matter).
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return 0;
+}
+
+struct FieldOrderingByStorageSize {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    // Order by grouping.
+    const int order_group_a = OrderGroupForFieldDescriptor(a);
+    const int order_group_b = OrderGroupForFieldDescriptor(b);
+    if (order_group_a != order_group_b) {
+      return order_group_a < order_group_b;
+    }
+    // Within the group, order by field number (provides stable ordering).
+    return a->number() < b->number();
+  }
+};
+
+struct ExtensionRangeOrdering {
+  bool operator()(const Descriptor::ExtensionRange* a,
+                  const Descriptor::ExtensionRange* b) const {
+    return a->start < b->start;
+  }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+      new const FieldDescriptor* [descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+  return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+      new const FieldDescriptor* [descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  sort(fields, fields + descriptor->field_count(),
+       FieldOrderingByStorageSize());
+  return fields;
+}
+}  // namespace
+
+MessageGenerator::MessageGenerator(const string& root_classname,
+                                   const Descriptor* descriptor,
+                                   const Options& options)
+    : root_classname_(root_classname),
+      descriptor_(descriptor),
+      field_generators_(descriptor, options),
+      class_name_(ClassName(descriptor_)) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators_.push_back(
+        new ExtensionGenerator(class_name_, descriptor_->extension(i)));
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+    oneof_generators_.push_back(generator);
+  }
+
+  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+    EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
+    enum_generators_.push_back(generator);
+  }
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    MessageGenerator* generator =
+        new MessageGenerator(root_classname_,
+                             descriptor_->nested_type(i),
+                             options);
+    nested_message_generators_.push_back(generator);
+  }
+}
+
+MessageGenerator::~MessageGenerator() {
+  STLDeleteContainerPointers(extension_generators_.begin(),
+                             extension_generators_.end());
+  STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+  STLDeleteContainerPointers(nested_message_generators_.begin(),
+                             nested_message_generators_.end());
+  STLDeleteContainerPointers(oneof_generators_.begin(),
+                             oneof_generators_.end());
+}
+
+void MessageGenerator::GenerateStaticVariablesInitialization(
+    io::Printer* printer) {
+  for (vector<ExtensionGenerator*>::iterator iter =
+           extension_generators_.begin();
+       iter != extension_generators_.end(); ++iter) {
+    (*iter)->GenerateStaticVariablesInitialization(printer);
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->GenerateStaticVariablesInitialization(printer);
+  }
+}
+
+void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
+  if (!IsMapEntryMessage(descriptor_)) {
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+      field_generators_.get(fieldDescriptor)
+          .DetermineForwardDeclarations(fwd_decls);
+    }
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->DetermineForwardDeclarations(fwd_decls);
+  }
+}
+
+void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
+  for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+       iter != enum_generators_.end(); ++iter) {
+    (*iter)->GenerateHeader(printer);
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->GenerateEnumHeader(printer);
+  }
+}
+
+void MessageGenerator::GenerateExtensionRegistrationSource(
+    io::Printer* printer) {
+  for (vector<ExtensionGenerator*>::iterator iter =
+           extension_generators_.begin();
+       iter != extension_generators_.end(); ++iter) {
+    (*iter)->GenerateRegistrationSource(printer);
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->GenerateExtensionRegistrationSource(printer);
+  }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
+  // This a a map entry message, just recurse and do nothing directly.
+  if (IsMapEntryMessage(descriptor_)) {
+    for (vector<MessageGenerator*>::iterator iter =
+             nested_message_generators_.begin();
+         iter != nested_message_generators_.end(); ++iter) {
+      (*iter)->GenerateMessageHeader(printer);
+    }
+    return;
+  }
+
+  printer->Print(
+      "#pragma mark - $classname$\n"
+      "\n",
+      "classname", class_name_);
+
+  if (descriptor_->field_count()) {
+    scoped_array<const FieldDescriptor*> sorted_fields(
+        SortFieldsByNumber(descriptor_));
+
+    printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+                   "classname", class_name_);
+    printer->Indent();
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(sorted_fields[i])
+          .GenerateFieldNumberConstant(printer);
+    }
+
+    printer->Outdent();
+    printer->Print("};\n\n");
+  }
+
+  for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+       iter != oneof_generators_.end(); ++iter) {
+    (*iter)->GenerateCaseEnum(printer);
+  }
+
+  string message_comments;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    message_comments = BuildCommentsString(location);
+  } else {
+    message_comments = "";
+  }
+
+  printer->Print(
+      "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
+      "classname", class_name_,
+      "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, false, true),
+      "comments", message_comments);
+
+  vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() != NULL) {
+      const int oneof_index = field->containing_oneof()->index();
+      if (!seen_oneofs[oneof_index]) {
+        seen_oneofs[oneof_index] = 1;
+        oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+            printer);
+      }
+    }
+    field_generators_.get(field).GeneratePropertyDeclaration(printer);
+  }
+
+  printer->Print("@end\n\n");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateCFunctionDeclarations(printer);
+  }
+
+  if (!oneof_generators_.empty()) {
+    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+         iter != oneof_generators_.end(); ++iter) {
+      (*iter)->GenerateClearFunctionDeclaration(printer);
+    }
+    printer->Print("\n");
+  }
+
+  if (descriptor_->extension_count() > 0) {
+    printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+                   "classname", class_name_);
+    for (vector<ExtensionGenerator*>::iterator iter =
+             extension_generators_.begin();
+         iter != extension_generators_.end(); ++iter) {
+      (*iter)->GenerateMembersHeader(printer);
+    }
+    printer->Print("@end\n\n");
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->GenerateMessageHeader(printer);
+  }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) {
+  if (!IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+        "#pragma mark - $classname$\n"
+        "\n",
+        "classname", class_name_);
+
+    printer->Print("@implementation $classname$\n\n",
+                   "classname", class_name_);
+
+    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+         iter != oneof_generators_.end(); ++iter) {
+      (*iter)->GeneratePropertyImplementation(printer);
+    }
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(descriptor_->field(i))
+          .GeneratePropertyImplementation(printer);
+    }
+
+    scoped_array<const FieldDescriptor*> sorted_fields(
+        SortFieldsByNumber(descriptor_));
+    scoped_array<const FieldDescriptor*> size_order_fields(
+        SortFieldsByStorageSize(descriptor_));
+
+    vector<const Descriptor::ExtensionRange*> sorted_extensions;
+    for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+      sorted_extensions.push_back(descriptor_->extension_range(i));
+    }
+
+    sort(sorted_extensions.begin(), sorted_extensions.end(),
+         ExtensionRangeOrdering());
+
+    // Assign has bits:
+    // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
+    //    who needs has bits and assigning them.
+    // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+    //    index that groups all the elements in the oneof.
+    size_t num_has_bits = field_generators_.CalculateHasBits();
+    size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+    if (sizeof_has_storage == 0) {
+      // In the case where no field needs has bits, don't let the _has_storage_
+      // end up as zero length (zero length arrays are sort of a grey area
+      // since it has to be at the start of the struct). This also ensures a
+      // field with only oneofs keeps the required negative indices they need.
+      sizeof_has_storage = 1;
+    }
+    // Tell all the fields the oneof base.
+    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+         iter != oneof_generators_.end(); ++iter) {
+      (*iter)->SetOneofIndexBase(sizeof_has_storage);
+    }
+    field_generators_.SetOneofIndexBase(sizeof_has_storage);
+    // sizeof_has_storage needs enough bits for the single fields that aren't in
+    // any oneof, and then one int32 for each oneof (to store the field number).
+    sizeof_has_storage += descriptor_->oneof_decl_count();
+
+    printer->Print(
+        "\n"
+        "typedef struct $classname$__storage_ {\n"
+        "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
+        "classname", class_name_,
+        "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
+    printer->Indent();
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(size_order_fields[i])
+          .GenerateFieldStorageDeclaration(printer);
+    }
+    printer->Outdent();
+
+    printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
+
+
+    printer->Print(
+        "// This method is threadsafe because it is initially called\n"
+        "// in +initialize for each subclass.\n"
+        "+ (GPBDescriptor *)descriptor {\n"
+        "  static GPBDescriptor *descriptor = nil;\n"
+        "  if (!descriptor) {\n");
+
+    TextFormatDecodeData text_format_decode_data;
+    bool has_fields = descriptor_->field_count() > 0;
+    bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+    string field_description_type;
+    if (need_defaults) {
+      field_description_type = "GPBMessageFieldDescriptionWithDefault";
+    } else {
+      field_description_type = "GPBMessageFieldDescription";
+    }
+    if (has_fields) {
+      printer->Print(
+          "    static $field_description_type$ fields[] = {\n",
+          "field_description_type", field_description_type);
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (int i = 0; i < descriptor_->field_count(); ++i) {
+        const FieldGenerator& field_generator =
+            field_generators_.get(sorted_fields[i]);
+        field_generator.GenerateFieldDescription(printer, need_defaults);
+        if (field_generator.needs_textformat_name_support()) {
+          text_format_decode_data.AddString(sorted_fields[i]->number(),
+                                            field_generator.generated_objc_name(),
+                                            field_generator.raw_field_name());
+        }
+      }
+      printer->Outdent();
+      printer->Outdent();
+      printer->Outdent();
+      printer->Print(
+          "    };\n");
+    }
+
+    map<string, string> vars;
+    vars["classname"] = class_name_;
+    vars["rootclassname"] = root_classname_;
+    vars["fields"] = has_fields ? "fields" : "NULL";
+    if (has_fields) {
+      vars["fields_count"] =
+          "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
+    } else {
+      vars["fields_count"] = "0";
+    }
+
+    std::vector<string> init_flags;
+    if (need_defaults) {
+      init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
+    }
+    if (descriptor_->options().message_set_wire_format()) {
+      init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
+    }
+    vars["init_flags"] = BuildFlagsString(init_flags);
+
+    printer->Print(
+        vars,
+        "    GPBDescriptor *localDescriptor =\n"
+        "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+        "                                     rootClass:[$rootclassname$ class]\n"
+        "                                          file:$rootclassname$_FileDescriptor()\n"
+        "                                        fields:$fields$\n"
+        "                                    fieldCount:$fields_count$\n"
+        "                                   storageSize:sizeof($classname$__storage_)\n"
+        "                                         flags:$init_flags$];\n");
+    if (oneof_generators_.size() != 0) {
+      printer->Print(
+          "    static const char *oneofs[] = {\n");
+      for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+           iter != oneof_generators_.end(); ++iter) {
+        printer->Print(
+            "      \"$name$\",\n",
+            "name", (*iter)->DescriptorName());
+      }
+      printer->Print(
+          "    };\n"
+          "    [localDescriptor setupOneofs:oneofs\n"
+          "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
+          "                   firstHasIndex:$first_has_index$];\n",
+          "first_has_index", oneof_generators_[0]->HasIndexAsString());
+    }
+    if (text_format_decode_data.num_entries() != 0) {
+      const string text_format_data_str(text_format_decode_data.Data());
+      printer->Print(
+          "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+          "    static const char *extraTextFormatInfo =");
+      static const int kBytesPerLine = 40;  // allow for escaping
+      for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
+        printer->Print(
+            "\n        \"$data$\"",
+            "data", EscapeTrigraphs(
+                CEscape(text_format_data_str.substr(i, kBytesPerLine))));
+      }
+      printer->Print(
+          ";\n"
+          "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+          "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
+    }
+    if (sorted_extensions.size() != 0) {
+      printer->Print(
+          "    static const GPBExtensionRange ranges[] = {\n");
+      for (int i = 0; i < sorted_extensions.size(); i++) {
+        printer->Print("      { .start = $start$, .end = $end$ },\n",
+                       "start", SimpleItoa(sorted_extensions[i]->start),
+                       "end", SimpleItoa(sorted_extensions[i]->end));
+      }
+      printer->Print(
+          "    };\n"
+          "    [localDescriptor setupExtensionRanges:ranges\n"
+          "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+    }
+    printer->Print(
+        "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+        "    descriptor = localDescriptor;\n"
+        "  }\n"
+        "  return descriptor;\n"
+        "}\n\n"
+        "@end\n\n");
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateCFunctionImplementations(printer);
+    }
+
+    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+         iter != oneof_generators_.end(); ++iter) {
+      (*iter)->GenerateClearFunctionImplementation(printer);
+    }
+  }
+
+  for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+       iter != enum_generators_.end(); ++iter) {
+    (*iter)->GenerateSource(printer);
+  }
+
+  for (vector<MessageGenerator*>::iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    (*iter)->GenerateSource(printer);
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.h
new file mode 100644
index 0000000..8565e76
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -0,0 +1,96 @@
+// 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_COMPILER_OBJECTIVEC_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer;  // printer.h
+}  // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator;
+class EnumGenerator;
+
+class MessageGenerator {
+ public:
+  MessageGenerator(const string& root_classname,
+                   const Descriptor* descriptor,
+                   const Options& options);
+  ~MessageGenerator();
+
+  void GenerateStaticVariablesInitialization(io::Printer* printer);
+  void GenerateEnumHeader(io::Printer* printer);
+  void GenerateMessageHeader(io::Printer* printer);
+  void GenerateSource(io::Printer* printer);
+  void GenerateExtensionRegistrationSource(io::Printer* printer);
+  void DetermineForwardDeclarations(set<string>* fwd_decls);
+
+ private:
+  void GenerateParseFromMethodsHeader(io::Printer* printer);
+
+  void GenerateSerializeOneFieldSource(io::Printer* printer,
+                                       const FieldDescriptor* field);
+  void GenerateSerializeOneExtensionRangeSource(
+      io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+  void GenerateMessageDescriptionSource(io::Printer* printer);
+  void GenerateDescriptionOneFieldSource(io::Printer* printer,
+                                         const FieldDescriptor* field);
+
+  const string root_classname_;
+  const Descriptor* descriptor_;
+  FieldGeneratorMap field_generators_;
+  const string class_name_;
+  vector<ExtensionGenerator*> extension_generators_;
+  vector<EnumGenerator*> enum_generators_;
+  vector<MessageGenerator*> nested_message_generators_;
+  vector<OneofGenerator*> oneof_generators_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
new file mode 100644
index 0000000..d6ccd6d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -0,0 +1,108 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+                         map<string, string>* variables) {
+  const string& message_type = ClassName(descriptor->message_type());
+  (*variables)["type"] = message_type;
+  (*variables)["containing_class"] = ClassName(descriptor->containing_type());
+  (*variables)["storage_type"] = message_type;
+  (*variables)["group_or_message"] =
+      (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
+
+  (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
+}
+
+}  // namespace
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
+  SetMessageVariables(descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  // Class name is already in "storage_type".
+  fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+bool MessageFieldGenerator::WantsHasProperty(void) const {
+  if (descriptor_->containing_oneof() != NULL) {
+    // If in a oneof, it uses the oneofcase instead of a has bit.
+    return false;
+  }
+  // In both proto2 & proto3, message fields have a has* property to tell
+  // when it is a non default value.
+  return true;
+}
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
+  SetMessageVariables(descriptor, &variables_);
+  variables_["array_storage_type"] = "NSMutableArray";
+  variables_["array_property_type"] =
+      "NSMutableArray<" + variables_["storage_type"] + "*>";
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  // Class name is already in "storage_type".
+  fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
new file mode 100644
index 0000000..d2dba15
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -0,0 +1,81 @@
+// 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_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MessageFieldGenerator : public ObjCObjFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ protected:
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
+  virtual ~MessageFieldGenerator();
+  virtual bool WantsHasProperty(void) const;
+
+ public:
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ protected:
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options);
+  virtual ~RepeatedMessageFieldGenerator();
+
+ public:
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
new file mode 100644
index 0000000..44bafd7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -0,0 +1,138 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
+    : descriptor_(descriptor) {
+  variables_["enum_name"] = OneofEnumName(descriptor_);
+  variables_["name"] = OneofName(descriptor_);
+  variables_["capitalized_name"] = OneofNameCapitalized(descriptor_);
+  variables_["raw_index"] = SimpleItoa(descriptor_->index());
+  const Descriptor* msg_descriptor = descriptor_->containing_type();
+  variables_["owning_message_class"] = ClassName(msg_descriptor);
+
+  string comments;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    comments = BuildCommentsString(location);
+  } else {
+    comments = "";
+  }
+  variables_["comments"] = comments;
+}
+
+OneofGenerator::~OneofGenerator() {}
+
+void OneofGenerator::SetOneofIndexBase(int index_base) {
+  int index = descriptor_->index() + index_base;
+  // Flip the sign to mark it as a oneof.
+  variables_["index"] = SimpleItoa(-index);
+}
+
+void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "typedef GPB_ENUM($enum_name$) {\n");
+  printer->Indent();
+  printer->Print(
+      variables_,
+      "$enum_name$_GPBUnsetOneOfCase = 0,\n");
+  string enum_name = variables_["enum_name"];
+  for (int j = 0; j < descriptor_->field_count(); j++) {
+    const FieldDescriptor* field = descriptor_->field(j);
+    string field_name = FieldNameCapitalized(field);
+    printer->Print(
+        "$enum_name$_$field_name$ = $field_number$,\n",
+        "enum_name", enum_name,
+        "field_name", field_name,
+        "field_number", SimpleItoa(field->number()));
+  }
+  printer->Outdent();
+  printer->Print(
+      "};\n"
+      "\n");
+}
+
+void OneofGenerator::GeneratePublicCasePropertyDeclaration(
+    io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "$comments$"
+      "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
+      "\n");
+}
+
+void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "/// Clears whatever value was set for the oneof '$name$'.\n"
+      "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
+}
+
+void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "@dynamic $name$OneOfCase;\n");
+}
+
+void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
+      "  GPBDescriptor *descriptor = [message descriptor];\n"
+      "  GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
+      "  GPBMaybeClearOneof(message, oneof, $index$, 0);\n"
+      "}\n");
+}
+
+string OneofGenerator::DescriptorName(void) const {
+  return variables_.find("name")->second;
+}
+
+string OneofGenerator::HasIndexAsString(void) const {
+  return variables_.find("index")->second;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
new file mode 100644
index 0000000..3d9df4d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -0,0 +1,79 @@
+// 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_COMPILER_OBJECTIVEC_ONEOF_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer;  // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class OneofGenerator {
+ public:
+  explicit OneofGenerator(const OneofDescriptor* descriptor);
+  ~OneofGenerator();
+
+  void SetOneofIndexBase(int index_base);
+
+  void GenerateCaseEnum(io::Printer* printer);
+
+  void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
+  void GenerateClearFunctionDeclaration(io::Printer* printer);
+
+  void GeneratePropertyImplementation(io::Printer* printer);
+  void GenerateClearFunctionImplementation(io::Printer* printer);
+
+  string DescriptorName(void) const;
+  string HasIndexAsString(void) const;
+
+ private:
+  const OneofDescriptor* descriptor_;
+  map<string, string> variables_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
new file mode 100644
index 0000000..d49350f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -0,0 +1,192 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
+  ObjectiveCType type = GetObjectiveCType(descriptor);
+  switch (type) {
+    case OBJECTIVECTYPE_INT32:
+      return "int32_t";
+    case OBJECTIVECTYPE_UINT32:
+      return "uint32_t";
+    case OBJECTIVECTYPE_INT64:
+      return "int64_t";
+    case OBJECTIVECTYPE_UINT64:
+      return "uint64_t";
+    case OBJECTIVECTYPE_FLOAT:
+      return "float";
+    case OBJECTIVECTYPE_DOUBLE:
+      return "double";
+    case OBJECTIVECTYPE_BOOLEAN:
+      return "BOOL";
+    case OBJECTIVECTYPE_STRING:
+      return "NSString";
+    case OBJECTIVECTYPE_DATA:
+      return "NSData";
+    case OBJECTIVECTYPE_ENUM:
+      return "int32_t";
+    case OBJECTIVECTYPE_MESSAGE:
+      return NULL;  // Messages go through objectivec_message_field.cc|h.
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
+  ObjectiveCType type = GetObjectiveCType(descriptor);
+  switch (type) {
+    case OBJECTIVECTYPE_INT32:
+      return "Int32";
+    case OBJECTIVECTYPE_UINT32:
+      return "UInt32";
+    case OBJECTIVECTYPE_INT64:
+      return "Int64";
+    case OBJECTIVECTYPE_UINT64:
+      return "UInt64";
+    case OBJECTIVECTYPE_FLOAT:
+      return "Float";
+    case OBJECTIVECTYPE_DOUBLE:
+      return "Double";
+    case OBJECTIVECTYPE_BOOLEAN:
+      return "Bool";
+    case OBJECTIVECTYPE_STRING:
+      return "";  // Want NSArray
+    case OBJECTIVECTYPE_DATA:
+      return "";  // Want NSArray
+    case OBJECTIVECTYPE_ENUM:
+      return "Enum";
+    case OBJECTIVECTYPE_MESSAGE:
+      // Want NSArray (but goes through objectivec_message_field.cc|h).
+      return "";
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           map<string, string>* variables) {
+  std::string primitive_name = PrimitiveTypeName(descriptor);
+  (*variables)["type"] = primitive_name;
+  (*variables)["storage_type"] = primitive_name;
+}
+
+}  // namespace
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
+  SetPrimitiveVariables(descriptor, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
+    io::Printer* printer) const {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Nothing, BOOLs are stored in the has bits.
+  } else {
+    SingleFieldGenerator::GenerateFieldStorageDeclaration(printer);
+  }
+}
+
+int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Reserve a bit for the storage of the boolean.
+    return 1;
+  }
+  return 0;
+}
+
+void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Set into the offset the has bit to use for the actual value.
+    variables_["storage_offset_value"] = SimpleItoa(has_base);
+    variables_["storage_offset_comment"] =
+        "  // Stored in _has_storage_ to save space.";
+  }
+}
+
+PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
+  SetPrimitiveVariables(descriptor, &variables_);
+  variables_["property_storage_attribute"] = "copy";
+}
+
+PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
+  SetPrimitiveVariables(descriptor, &variables_);
+
+  string base_name = PrimitiveArrayTypeName(descriptor);
+  if (base_name.length()) {
+    variables_["array_storage_type"] = "GPB" + base_name + "Array";
+  } else {
+    variables_["array_storage_type"] = "NSMutableArray";
+    variables_["array_property_type"] =
+        "NSMutableArray<" + variables_["storage_type"] + "*>";
+  }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
new file mode 100644
index 0000000..69bb1fd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -0,0 +1,92 @@
+// 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_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class PrimitiveFieldGenerator : public SingleFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ protected:
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
+  virtual ~PrimitiveFieldGenerator();
+
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+
+  virtual int ExtraRuntimeHasBitsNeeded(void) const;
+  virtual void SetExtraRuntimeHasBitsBase(int index_base);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ protected:
+  PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
+  virtual ~PrimitiveObjFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
+
+ protected:
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                  const Options& options);
+  virtual ~RepeatedPrimitiveFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/package_info.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/package_info.h
new file mode 100644
index 0000000..fb6b473
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/package_info.h
@@ -0,0 +1,64 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file exists solely to document the google::protobuf::compiler namespace.
+// It is not compiled into anything, but it may be read by an automated
+// documentation generator.
+
+namespace google {
+
+namespace protobuf {
+
+// Implementation of the Protocol Buffer compiler.
+//
+// This package contains code for parsing .proto files and generating code
+// based on them.  There are two reasons you might be interested in this
+// package:
+// - You want to parse .proto files at runtime.  In this case, you should
+//   look at importer.h.  Since this functionality is widely useful, it is
+//   included in the libprotobuf base library; you do not have to link against
+//   libprotoc.
+// - You want to write a custom protocol compiler which generates different
+//   kinds of code, e.g. code in a different language which is not supported
+//   by the official compiler.  For this purpose, command_line_interface.h
+//   provides you with a complete compiler front-end, so all you need to do
+//   is write a custom implementation of CodeGenerator and a trivial main()
+//   function.  You can even make your compiler support the official languages
+//   in addition to your own.  Since this functionality is only useful to those
+//   writing custom compilers, it is in a separate library called "libprotoc"
+//   which you will have to link against.
+namespace compiler {}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.cc
new file mode 100644
index 0000000..90ded4d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.cc
@@ -0,0 +1,2109 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Recursive descent FTW.
+
+#include <float.h>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
+
+
+#include <google/protobuf/compiler/parser.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+using internal::WireFormat;
+
+namespace {
+
+typedef hash_map<string, FieldDescriptorProto::Type> TypeNameMap;
+
+TypeNameMap MakeTypeNameTable() {
+  TypeNameMap result;
+
+  result["double"  ] = FieldDescriptorProto::TYPE_DOUBLE;
+  result["float"   ] = FieldDescriptorProto::TYPE_FLOAT;
+  result["uint64"  ] = FieldDescriptorProto::TYPE_UINT64;
+  result["fixed64" ] = FieldDescriptorProto::TYPE_FIXED64;
+  result["fixed32" ] = FieldDescriptorProto::TYPE_FIXED32;
+  result["bool"    ] = FieldDescriptorProto::TYPE_BOOL;
+  result["string"  ] = FieldDescriptorProto::TYPE_STRING;
+  result["group"   ] = FieldDescriptorProto::TYPE_GROUP;
+
+  result["bytes"   ] = FieldDescriptorProto::TYPE_BYTES;
+  result["uint32"  ] = FieldDescriptorProto::TYPE_UINT32;
+  result["sfixed32"] = FieldDescriptorProto::TYPE_SFIXED32;
+  result["sfixed64"] = FieldDescriptorProto::TYPE_SFIXED64;
+  result["int32"   ] = FieldDescriptorProto::TYPE_INT32;
+  result["int64"   ] = FieldDescriptorProto::TYPE_INT64;
+  result["sint32"  ] = FieldDescriptorProto::TYPE_SINT32;
+  result["sint64"  ] = FieldDescriptorProto::TYPE_SINT64;
+
+  return result;
+}
+
+const TypeNameMap kTypeNames = MakeTypeNameTable();
+
+// Camel-case the field name and append "Entry" for generated map entry name.
+// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
+string MapEntryName(const string& field_name) {
+  string result;
+  static const char kSuffix[] = "Entry";
+  result.reserve(field_name.size() + sizeof(kSuffix));
+  bool cap_next = true;
+  for (int i = 0; i < field_name.size(); ++i) {
+    if (field_name[i] == '_') {
+      cap_next = true;
+    } else if (cap_next) {
+      // Note: Do not use ctype.h due to locales.
+      if ('a' <= field_name[i] && field_name[i] <= 'z') {
+        result.push_back(field_name[i] - 'a' + 'A');
+      } else {
+        result.push_back(field_name[i]);
+      }
+      cap_next = false;
+    } else {
+      result.push_back(field_name[i]);
+    }
+  }
+  result.append(kSuffix);
+  return result;
+}
+
+}  // anonymous namespace
+
+// Makes code slightly more readable.  The meaning of "DO(foo)" is
+// "Execute foo and fail if it fails.", where failure is indicated by
+// returning false.
+#define DO(STATEMENT) if (STATEMENT) {} else return false
+
+// ===================================================================
+
+Parser::Parser()
+  : input_(NULL),
+    error_collector_(NULL),
+    source_location_table_(NULL),
+    had_errors_(false),
+    require_syntax_identifier_(false),
+    stop_after_syntax_identifier_(false) {
+}
+
+Parser::~Parser() {
+}
+
+// ===================================================================
+
+inline bool Parser::LookingAt(const char* text) {
+  return input_->current().text == text;
+}
+
+inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) {
+  return input_->current().type == token_type;
+}
+
+inline bool Parser::AtEnd() {
+  return LookingAtType(io::Tokenizer::TYPE_END);
+}
+
+bool Parser::TryConsume(const char* text) {
+  if (LookingAt(text)) {
+    input_->Next();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool Parser::Consume(const char* text, const char* error) {
+  if (TryConsume(text)) {
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::Consume(const char* text) {
+  if (TryConsume(text)) {
+    return true;
+  } else {
+    AddError("Expected \"" + string(text) + "\".");
+    return false;
+  }
+}
+
+bool Parser::ConsumeIdentifier(string* output, const char* error) {
+  if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+    *output = input_->current().text;
+    input_->Next();
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::ConsumeInteger(int* output, const char* error) {
+  if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+    uint64 value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     kint32max, &value)) {
+      AddError("Integer out of range.");
+      // We still return true because we did, in fact, parse an integer.
+    }
+    *output = value;
+    input_->Next();
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::ConsumeSignedInteger(int* output, const char* error) {
+  bool is_negative = false;
+  uint64 max_value = kint32max;
+  if (TryConsume("-")) {
+    is_negative = true;
+    max_value += 1;
+  }
+  uint64 value = 0;
+  DO(ConsumeInteger64(max_value, &value, error));
+  if (is_negative) value *= -1;
+  *output = value;
+  return true;
+}
+
+bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
+                              const char* error) {
+  if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+    if (!io::Tokenizer::ParseInteger(input_->current().text, max_value,
+                                     output)) {
+      AddError("Integer out of range.");
+      // We still return true because we did, in fact, parse an integer.
+      *output = 0;
+    }
+    input_->Next();
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::ConsumeNumber(double* output, const char* error) {
+  if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
+    *output = io::Tokenizer::ParseFloat(input_->current().text);
+    input_->Next();
+    return true;
+  } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+    // Also accept integers.
+    uint64 value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     kuint64max, &value)) {
+      AddError("Integer out of range.");
+      // We still return true because we did, in fact, parse a number.
+    }
+    *output = value;
+    input_->Next();
+    return true;
+  } else if (LookingAt("inf")) {
+    *output = numeric_limits<double>::infinity();
+    input_->Next();
+    return true;
+  } else if (LookingAt("nan")) {
+    *output = numeric_limits<double>::quiet_NaN();
+    input_->Next();
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::ConsumeString(string* output, const char* error) {
+  if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+    io::Tokenizer::ParseString(input_->current().text, output);
+    input_->Next();
+    // Allow C++ like concatenation of adjacent string tokens.
+    while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+      io::Tokenizer::ParseStringAppend(input_->current().text, output);
+      input_->Next();
+    }
+    return true;
+  } else {
+    AddError(error);
+    return false;
+  }
+}
+
+bool Parser::TryConsumeEndOfDeclaration(
+    const char* text, const LocationRecorder* location) {
+  if (LookingAt(text)) {
+    string leading, trailing;
+    vector<string> detached;
+    input_->NextWithComments(&trailing, &detached, &leading);
+
+    // Save the leading comments for next time, and recall the leading comments
+    // from last time.
+    leading.swap(upcoming_doc_comments_);
+
+    if (location != NULL) {
+      upcoming_detached_comments_.swap(detached);
+      location->AttachComments(&leading, &trailing, &detached);
+    } else if (strcmp(text, "}") == 0) {
+      // If the current location is null and we are finishing the current scope,
+      // drop pending upcoming detached comments.
+      upcoming_detached_comments_.swap(detached);
+    } else {
+      // Otherwise, append the new detached comments to the existing upcoming
+      // detached comments.
+      upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
+                                         detached.begin(), detached.end());
+    }
+
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool Parser::ConsumeEndOfDeclaration(
+    const char* text, const LocationRecorder* location) {
+  if (TryConsumeEndOfDeclaration(text, location)) {
+    return true;
+  } else {
+    AddError("Expected \"" + string(text) + "\".");
+    return false;
+  }
+}
+
+// -------------------------------------------------------------------
+
+void Parser::AddError(int line, int column, const string& error) {
+  if (error_collector_ != NULL) {
+    error_collector_->AddError(line, column, error);
+  }
+  had_errors_ = true;
+}
+
+void Parser::AddError(const string& error) {
+  AddError(input_->current().line, input_->current().column, error);
+}
+
+// -------------------------------------------------------------------
+
+Parser::LocationRecorder::LocationRecorder(Parser* parser)
+  : parser_(parser),
+    location_(parser_->source_code_info_->add_location()) {
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) {
+  Init(parent);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1) {
+  Init(parent);
+  AddPath(path1);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1, int path2) {
+  Init(parent);
+  AddPath(path1);
+  AddPath(path2);
+}
+
+void Parser::LocationRecorder::Init(const LocationRecorder& parent) {
+  parser_ = parent.parser_;
+  location_ = parser_->source_code_info_->add_location();
+  location_->mutable_path()->CopyFrom(parent.location_->path());
+
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::~LocationRecorder() {
+  if (location_->span_size() <= 2) {
+    EndAt(parser_->input_->previous());
+  }
+}
+
+void Parser::LocationRecorder::AddPath(int path_component) {
+  location_->add_path(path_component);
+}
+
+void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
+  location_->set_span(0, token.line);
+  location_->set_span(1, token.column);
+}
+
+void Parser::LocationRecorder::StartAt(const LocationRecorder& other) {
+  location_->set_span(0, other.location_->span(0));
+  location_->set_span(1, other.location_->span(1));
+}
+
+void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) {
+  if (token.line != location_->span(0)) {
+    location_->add_span(token.line);
+  }
+  location_->add_span(token.end_column);
+}
+
+void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location) {
+  if (parser_->source_location_table_ != NULL) {
+    parser_->source_location_table_->Add(
+        descriptor, location, location_->span(0), location_->span(1));
+  }
+}
+
+void Parser::LocationRecorder::AttachComments(
+    string* leading, string* trailing,
+    vector<string>* detached_comments) const {
+  GOOGLE_CHECK(!location_->has_leading_comments());
+  GOOGLE_CHECK(!location_->has_trailing_comments());
+
+  if (!leading->empty()) {
+    location_->mutable_leading_comments()->swap(*leading);
+  }
+  if (!trailing->empty()) {
+    location_->mutable_trailing_comments()->swap(*trailing);
+  }
+  for (int i = 0; i < detached_comments->size(); ++i) {
+    location_->add_leading_detached_comments()->swap(
+        (*detached_comments)[i]);
+  }
+  detached_comments->clear();
+}
+
+// -------------------------------------------------------------------
+
+void Parser::SkipStatement() {
+  while (true) {
+    if (AtEnd()) {
+      return;
+    } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
+      if (TryConsumeEndOfDeclaration(";", NULL)) {
+        return;
+      } else if (TryConsume("{")) {
+        SkipRestOfBlock();
+        return;
+      } else if (LookingAt("}")) {
+        return;
+      }
+    }
+    input_->Next();
+  }
+}
+
+void Parser::SkipRestOfBlock() {
+  while (true) {
+    if (AtEnd()) {
+      return;
+    } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
+      if (TryConsumeEndOfDeclaration("}", NULL)) {
+        return;
+      } else if (TryConsume("{")) {
+        SkipRestOfBlock();
+      }
+    }
+    input_->Next();
+  }
+}
+
+// ===================================================================
+
+bool Parser::ValidateEnum(const EnumDescriptorProto* proto) {
+  bool has_allow_alias = false;
+  bool allow_alias = false;
+
+  for (int i = 0; i < proto->options().uninterpreted_option_size(); i++) {
+    const UninterpretedOption option = proto->options().uninterpreted_option(i);
+    if (option.name_size() > 1) {
+      continue;
+    }
+    if (!option.name(0).is_extension() &&
+        option.name(0).name_part() == "allow_alias") {
+      has_allow_alias = true;
+      if (option.identifier_value() == "true") {
+        allow_alias = true;
+      }
+      break;
+    }
+  }
+
+  if (has_allow_alias && !allow_alias) {
+    string error =
+        "\"" + proto->name() +
+        "\" declares 'option allow_alias = false;' which has no effect. "
+        "Please remove the declaration.";
+    // This needlessly clutters declarations with nops.
+    AddError(error);
+    return false;
+  }
+
+  set<int> used_values;
+  bool has_duplicates = false;
+  for (int i = 0; i < proto->value_size(); ++i) {
+    const EnumValueDescriptorProto enum_value = proto->value(i);
+    if (used_values.find(enum_value.number()) != used_values.end()) {
+      has_duplicates = true;
+      break;
+    } else {
+      used_values.insert(enum_value.number());
+    }
+  }
+  if (allow_alias && !has_duplicates) {
+    string error =
+        "\"" + proto->name() +
+        "\" declares support for enum aliases but no enum values share field "
+        "numbers. Please remove the unnecessary 'option allow_alias = true;' "
+        "declaration.";
+    // Generate an error if an enum declares support for duplicate enum values
+    // and does not use it protect future authors.
+    AddError(error);
+    return false;
+  }
+
+  return true;
+}
+
+bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
+  input_ = input;
+  had_errors_ = false;
+  syntax_identifier_.clear();
+
+  // Note that |file| could be NULL at this point if
+  // stop_after_syntax_identifier_ is true.  So, we conservatively allocate
+  // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto
+  // later on.
+  SourceCodeInfo source_code_info;
+  source_code_info_ = &source_code_info;
+
+  vector<string> top_doc_comments;
+  if (LookingAtType(io::Tokenizer::TYPE_START)) {
+    // Advance to first token.
+    input_->NextWithComments(NULL, &upcoming_detached_comments_,
+                             &upcoming_doc_comments_);
+  }
+
+  {
+    LocationRecorder root_location(this);
+
+    if (require_syntax_identifier_ || LookingAt("syntax")) {
+      if (!ParseSyntaxIdentifier(root_location)) {
+        // Don't attempt to parse the file if we didn't recognize the syntax
+        // identifier.
+        return false;
+      }
+      // Store the syntax into the file.
+      if (file != NULL) file->set_syntax(syntax_identifier_);
+    } else if (!stop_after_syntax_identifier_) {
+      GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: "
+                   << file->name() << ". Please use 'syntax = \"proto2\";' "
+                   << "or 'syntax = \"proto3\";' to specify a syntax "
+                   << "version. (Defaulted to proto2 syntax.)";
+      syntax_identifier_ = "proto2";
+    }
+
+    if (stop_after_syntax_identifier_) return !had_errors_;
+
+    // Repeatedly parse statements until we reach the end of the file.
+    while (!AtEnd()) {
+      if (!ParseTopLevelStatement(file, root_location)) {
+        // This statement failed to parse.  Skip it, but keep looping to parse
+        // other statements.
+        SkipStatement();
+
+        if (LookingAt("}")) {
+          AddError("Unmatched \"}\".");
+          input_->NextWithComments(NULL, &upcoming_detached_comments_,
+                                   &upcoming_doc_comments_);
+        }
+      }
+    }
+  }
+
+  input_ = NULL;
+  source_code_info_ = NULL;
+  source_code_info.Swap(file->mutable_source_code_info());
+  return !had_errors_;
+}
+
+bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
+  LocationRecorder syntax_location(parent,
+                                   FileDescriptorProto::kSyntaxFieldNumber);
+  DO(Consume(
+      "syntax",
+      "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
+  DO(Consume("="));
+  io::Tokenizer::Token syntax_token = input_->current();
+  string syntax;
+  DO(ConsumeString(&syntax, "Expected syntax identifier."));
+  DO(ConsumeEndOfDeclaration(";", &syntax_location));
+
+  syntax_identifier_ = syntax;
+
+  if (syntax != "proto2" && syntax != "proto3" &&
+      !stop_after_syntax_identifier_) {
+    AddError(syntax_token.line, syntax_token.column,
+      "Unrecognized syntax identifier \"" + syntax + "\".  This parser "
+      "only recognizes \"proto2\" and \"proto3\".");
+    return false;
+  }
+
+  return true;
+}
+
+bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
+                                    const LocationRecorder& root_location) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
+    // empty statement; ignore
+    return true;
+  } else if (LookingAt("message")) {
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size());
+    return ParseMessageDefinition(file->add_message_type(), location, file);
+  } else if (LookingAt("enum")) {
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size());
+    return ParseEnumDefinition(file->add_enum_type(), location, file);
+  } else if (LookingAt("service")) {
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kServiceFieldNumber, file->service_size());
+    return ParseServiceDefinition(file->add_service(), location, file);
+  } else if (LookingAt("extend")) {
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kExtensionFieldNumber);
+    return ParseExtend(file->mutable_extension(),
+                       file->mutable_message_type(),
+                       root_location,
+                       FileDescriptorProto::kMessageTypeFieldNumber,
+                       location, file);
+  } else if (LookingAt("import")) {
+    return ParseImport(file->mutable_dependency(),
+                       file->mutable_public_dependency(),
+                       file->mutable_weak_dependency(),
+                       root_location, file);
+  } else if (LookingAt("package")) {
+    return ParsePackage(file, root_location, file);
+  } else if (LookingAt("option")) {
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(file->mutable_options(), location, file,
+                       OPTION_STATEMENT);
+  } else {
+    AddError("Expected top-level statement (e.g. \"message\").");
+    return false;
+  }
+}
+
+// -------------------------------------------------------------------
+// Messages
+
+bool Parser::ParseMessageDefinition(
+    DescriptorProto* message,
+    const LocationRecorder& message_location,
+    const FileDescriptorProto* containing_file) {
+  DO(Consume("message"));
+  {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        message, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
+  }
+  DO(ParseMessageBlock(message, message_location, containing_file));
+  return true;
+}
+
+namespace {
+
+const int kMaxExtensionRangeSentinel = -1;
+
+bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
+  const MessageOptions& options = message.options();
+  for (int i = 0; i < options.uninterpreted_option_size(); ++i) {
+    const UninterpretedOption& uninterpreted = options.uninterpreted_option(i);
+    if (uninterpreted.name_size() == 1 &&
+        uninterpreted.name(0).name_part() == "message_set_wire_format" &&
+        uninterpreted.identifier_value() == "true") {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Modifies any extension ranges that specified 'max' as the end of the
+// extension range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
+  const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+  const int max_extension_number = is_message_set ?
+      kint32max :
+      FieldDescriptor::kMaxNumber + 1;
+  for (int i = 0; i < message->extension_range_size(); ++i) {
+    if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) {
+      message->mutable_extension_range(i)->set_end(max_extension_number);
+    }
+  }
+}
+
+}  // namespace
+
+bool Parser::ParseMessageBlock(DescriptorProto* message,
+                               const LocationRecorder& message_location,
+                               const FileDescriptorProto* containing_file) {
+  DO(ConsumeEndOfDeclaration("{", &message_location));
+
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
+    if (AtEnd()) {
+      AddError("Reached end of input in message definition (missing '}').");
+      return false;
+    }
+
+    if (!ParseMessageStatement(message, message_location, containing_file)) {
+      // This statement failed to parse.  Skip it, but keep looping to parse
+      // other statements.
+      SkipStatement();
+    }
+  }
+
+  if (message->extension_range_size() > 0) {
+    AdjustExtensionRangesWithMaxEndNumber(message);
+  }
+  return true;
+}
+
+bool Parser::ParseMessageStatement(DescriptorProto* message,
+                                   const LocationRecorder& message_location,
+                                   const FileDescriptorProto* containing_file) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
+    // empty statement; ignore
+    return true;
+  } else if (LookingAt("message")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNestedTypeFieldNumber,
+                              message->nested_type_size());
+    return ParseMessageDefinition(message->add_nested_type(), location,
+                                  containing_file);
+  } else if (LookingAt("enum")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kEnumTypeFieldNumber,
+                              message->enum_type_size());
+    return ParseEnumDefinition(message->add_enum_type(), location,
+                               containing_file);
+  } else if (LookingAt("extensions")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionRangeFieldNumber);
+    return ParseExtensions(message, location, containing_file);
+  } else if (LookingAt("reserved")) {
+    return ParseReserved(message, message_location);
+  } else if (LookingAt("extend")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionFieldNumber);
+    return ParseExtend(message->mutable_extension(),
+                       message->mutable_nested_type(),
+                       message_location,
+                       DescriptorProto::kNestedTypeFieldNumber,
+                       location, containing_file);
+  } else if (LookingAt("option")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kOptionsFieldNumber);
+    return ParseOption(message->mutable_options(), location,
+                       containing_file, OPTION_STATEMENT);
+  } else if (LookingAt("oneof")) {
+    int oneof_index = message->oneof_decl_size();
+    LocationRecorder oneof_location(message_location,
+                                    DescriptorProto::kOneofDeclFieldNumber,
+                                    oneof_index);
+
+    return ParseOneof(message->add_oneof_decl(), message,
+                      oneof_index, oneof_location, message_location,
+                      containing_file);
+  } else {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kFieldFieldNumber,
+                              message->field_size());
+    return ParseMessageField(message->add_field(),
+                             message->mutable_nested_type(),
+                             message_location,
+                             DescriptorProto::kNestedTypeFieldNumber,
+                             location,
+                             containing_file);
+  }
+}
+
+bool Parser::ParseMessageField(FieldDescriptorProto* field,
+                               RepeatedPtrField<DescriptorProto>* messages,
+                               const LocationRecorder& parent_location,
+                               int location_field_number_for_nested_type,
+                               const LocationRecorder& field_location,
+                               const FileDescriptorProto* containing_file) {
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kLabelFieldNumber);
+    FieldDescriptorProto::Label label;
+    if (ParseLabel(&label, containing_file)) {
+      field->set_label(label);
+      if (label == FieldDescriptorProto::LABEL_OPTIONAL &&
+          syntax_identifier_ == "proto3") {
+        AddError(
+            "Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+            "To define 'optional' fields in Proto3, simply remove the "
+            "'optional' label, as fields are 'optional' by default.");
+      }
+    }
+  }
+
+  return ParseMessageFieldNoLabel(field, messages, parent_location,
+                                  location_field_number_for_nested_type,
+                                  field_location,
+                                  containing_file);
+}
+
+bool Parser::ParseMessageFieldNoLabel(
+    FieldDescriptorProto* field,
+    RepeatedPtrField<DescriptorProto>* messages,
+    const LocationRecorder& parent_location,
+    int location_field_number_for_nested_type,
+    const LocationRecorder& field_location,
+    const FileDescriptorProto* containing_file) {
+  MapField map_field;
+  // Parse type.
+  {
+    LocationRecorder location(field_location);  // add path later
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+
+    bool type_parsed = false;
+    FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
+    string type_name;
+
+    // Special case map field. We only treat the field as a map field if the
+    // field type name starts with the word "map" with a following "<".
+    if (TryConsume("map")) {
+      if (LookingAt("<")) {
+        map_field.is_map_field = true;
+      } else {
+        // False positive
+        type_parsed = true;
+        type_name = "map";
+      }
+    }
+    if (map_field.is_map_field) {
+      if (field->has_oneof_index()) {
+        AddError("Map fields are not allowed in oneofs.");
+        return false;
+      }
+      if (field->has_label()) {
+        AddError(
+            "Field labels (required/optional/repeated) are not allowed on "
+            "map fields.");
+        return false;
+      }
+      if (field->has_extendee()) {
+        AddError("Map fields are not allowed to be extensions.");
+        return false;
+      }
+      field->set_label(FieldDescriptorProto::LABEL_REPEATED);
+      DO(Consume("<"));
+      DO(ParseType(&map_field.key_type, &map_field.key_type_name));
+      DO(Consume(","));
+      DO(ParseType(&map_field.value_type, &map_field.value_type_name));
+      DO(Consume(">"));
+      // Defer setting of the type name of the map field until the
+      // field name is parsed. Add the source location though.
+      location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+    } else {
+      // Handle the case where no explicit label is given for a non-map field.
+      if (!field->has_label() && DefaultToOptionalFields()) {
+        field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+      }
+      if (!field->has_label()) {
+        AddError("Expected \"required\", \"optional\", or \"repeated\".");
+        // We can actually reasonably recover here by just assuming the user
+        // forgot the label altogether.
+        field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+      }
+
+      // Handle the case where the actual type is a message or enum named "map",
+      // which we already consumed in the code above.
+      if (!type_parsed) {
+        DO(ParseType(&type, &type_name));
+      }
+      if (type_name.empty()) {
+        location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+        field->set_type(type);
+      } else {
+        location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+        field->set_type_name(type_name);
+      }
+    }
+  }
+
+  // Parse name and '='.
+  io::Tokenizer::Token name_token = input_->current();
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+  }
+  DO(Consume("=", "Missing field number."));
+
+  // Parse field number.
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        field, DescriptorPool::ErrorCollector::NUMBER);
+    int number;
+    DO(ConsumeInteger(&number, "Expected field number."));
+    field->set_number(number);
+  }
+
+  // Parse options.
+  DO(ParseFieldOptions(field, field_location, containing_file));
+
+  // Deal with groups.
+  if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) {
+    // Awkward:  Since a group declares both a message type and a field, we
+    //   have to create overlapping locations.
+    LocationRecorder group_location(parent_location);
+    group_location.StartAt(field_location);
+    group_location.AddPath(location_field_number_for_nested_type);
+    group_location.AddPath(messages->size());
+
+    DescriptorProto* group = messages->Add();
+    group->set_name(field->name());
+
+    // Record name location to match the field name's location.
+    {
+      LocationRecorder location(group_location,
+                                DescriptorProto::kNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+      location.RecordLegacyLocation(
+          group, DescriptorPool::ErrorCollector::NAME);
+    }
+
+    // The field's type_name also comes from the name.  Confusing!
+    {
+      LocationRecorder location(field_location,
+                                FieldDescriptorProto::kTypeNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+    }
+
+    // As a hack for backwards-compatibility, we force the group name to start
+    // with a capital letter and lower-case the field name.  New code should
+    // not use groups; it should use nested messages.
+    if (group->name()[0] < 'A' || 'Z' < group->name()[0]) {
+      AddError(name_token.line, name_token.column,
+        "Group names must start with a capital letter.");
+    }
+    LowerString(field->mutable_name());
+
+    field->set_type_name(group->name());
+    if (LookingAt("{")) {
+      DO(ParseMessageBlock(group, group_location, containing_file));
+    } else {
+      AddError("Missing group body.");
+      return false;
+    }
+  } else {
+    DO(ConsumeEndOfDeclaration(";", &field_location));
+  }
+
+  // Create a map entry type if this is a map field.
+  if (map_field.is_map_field) {
+    GenerateMapEntry(map_field, field, messages);
+  }
+
+  return true;
+}
+
+void Parser::GenerateMapEntry(const MapField& map_field,
+                              FieldDescriptorProto* field,
+                              RepeatedPtrField<DescriptorProto>* messages) {
+  DescriptorProto* entry = messages->Add();
+  string entry_name = MapEntryName(field->name());
+  field->set_type_name(entry_name);
+  entry->set_name(entry_name);
+  entry->mutable_options()->set_map_entry(true);
+  FieldDescriptorProto* key_field = entry->add_field();
+  key_field->set_name("key");
+  key_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+  key_field->set_number(1);
+  if (map_field.key_type_name.empty()) {
+    key_field->set_type(map_field.key_type);
+  } else {
+    key_field->set_type_name(map_field.key_type_name);
+  }
+  FieldDescriptorProto* value_field = entry->add_field();
+  value_field->set_name("value");
+  value_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+  value_field->set_number(2);
+  if (map_field.value_type_name.empty()) {
+    value_field->set_type(map_field.value_type);
+  } else {
+    value_field->set_type_name(map_field.value_type_name);
+  }
+  // Propagate the "enforce_utf8" option to key and value fields if they
+  // are strings. This helps simplify the implementation of code generators
+  // and also reflection-based parsing code.
+  //
+  // The following definition:
+  //   message Foo {
+  //     map<string, string> value = 1 [enforce_utf8 = false];
+  //   }
+  // will be interpreted as:
+  //   message Foo {
+  //     message ValueEntry {
+  //       option map_entry = true;
+  //       string key = 1 [enforce_utf8 = false];
+  //       string value = 2 [enforce_utf8 = false];
+  //     }
+  //     repeated ValueEntry value = 1 [enforce_utf8 = false];
+  //  }
+  //
+  // TODO(xiaofeng): Remove this when the "enforce_utf8" option is removed
+  // from protocol compiler.
+  for (int i = 0; i < field->options().uninterpreted_option_size(); ++i) {
+    const UninterpretedOption& option =
+        field->options().uninterpreted_option(i);
+    if (option.name_size() == 1 &&
+        option.name(0).name_part() == "enforce_utf8" &&
+        !option.name(0).is_extension()) {
+      if (key_field->type() == FieldDescriptorProto::TYPE_STRING) {
+        key_field->mutable_options()->add_uninterpreted_option()
+            ->CopyFrom(option);
+      }
+      if (value_field->type() == FieldDescriptorProto::TYPE_STRING) {
+        value_field->mutable_options()->add_uninterpreted_option()
+            ->CopyFrom(option);
+      }
+    }
+  }
+}
+
+bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
+                               const LocationRecorder& field_location,
+                               const FileDescriptorProto* containing_file) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
+
+  // Parse field options.
+  do {
+    if (LookingAt("default")) {
+      // We intentionally pass field_location rather than location here, since
+      // the default value is not actually an option.
+      DO(ParseDefaultAssignment(field, field_location, containing_file));
+    } else if (LookingAt("json_name")) {
+      // Like default value, this "json_name" is not an actual option.
+      DO(ParseJsonName(field, field_location, containing_file));
+    } else {
+      DO(ParseOption(field->mutable_options(), location,
+                     containing_file, OPTION_ASSIGNMENT));
+    }
+  } while (TryConsume(","));
+
+  DO(Consume("]"));
+  return true;
+}
+
+bool Parser::ParseDefaultAssignment(
+    FieldDescriptorProto* field,
+    const LocationRecorder& field_location,
+    const FileDescriptorProto* containing_file) {
+  if (field->has_default_value()) {
+    AddError("Already set option \"default\".");
+    field->clear_default_value();
+  }
+
+  DO(Consume("default"));
+  DO(Consume("="));
+
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kDefaultValueFieldNumber);
+  location.RecordLegacyLocation(
+      field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
+  string* default_value = field->mutable_default_value();
+
+  if (!field->has_type()) {
+    // The field has a type name, but we don't know if it is a message or an
+    // enum yet. (If it were a primitive type, |field| would have a type set
+    // already.) In this case, simply take the current string as the default
+    // value; we will catch the error later if it is not a valid enum value.
+    // (N.B. that we do not check whether the current token is an identifier:
+    // doing so throws strange errors when the user mistypes a primitive
+    // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default
+    // = 42]". In such a case the fundamental error is really that "int" is not
+    // a type, not that "42" is not an identifier. See b/12533582.)
+    *default_value = input_->current().text;
+    input_->Next();
+    return true;
+  }
+
+  switch (field->type()) {
+    case FieldDescriptorProto::TYPE_INT32:
+    case FieldDescriptorProto::TYPE_INT64:
+    case FieldDescriptorProto::TYPE_SINT32:
+    case FieldDescriptorProto::TYPE_SINT64:
+    case FieldDescriptorProto::TYPE_SFIXED32:
+    case FieldDescriptorProto::TYPE_SFIXED64: {
+      uint64 max_value = kint64max;
+      if (field->type() == FieldDescriptorProto::TYPE_INT32 ||
+          field->type() == FieldDescriptorProto::TYPE_SINT32 ||
+          field->type() == FieldDescriptorProto::TYPE_SFIXED32) {
+        max_value = kint32max;
+      }
+
+      // These types can be negative.
+      if (TryConsume("-")) {
+        default_value->append("-");
+        // Two's complement always has one more negative value than positive.
+        ++max_value;
+      }
+      // Parse the integer to verify that it is not out-of-range.
+      uint64 value;
+      DO(ConsumeInteger64(max_value, &value,
+                          "Expected integer for field default value."));
+      // And stringify it again.
+      default_value->append(SimpleItoa(value));
+      break;
+    }
+
+    case FieldDescriptorProto::TYPE_UINT32:
+    case FieldDescriptorProto::TYPE_UINT64:
+    case FieldDescriptorProto::TYPE_FIXED32:
+    case FieldDescriptorProto::TYPE_FIXED64: {
+      uint64 max_value = kuint64max;
+      if (field->type() == FieldDescriptorProto::TYPE_UINT32 ||
+          field->type() == FieldDescriptorProto::TYPE_FIXED32) {
+        max_value = kuint32max;
+      }
+
+      // Numeric, not negative.
+      if (TryConsume("-")) {
+        AddError("Unsigned field can't have negative default value.");
+      }
+      // Parse the integer to verify that it is not out-of-range.
+      uint64 value;
+      DO(ConsumeInteger64(max_value, &value,
+                          "Expected integer for field default value."));
+      // And stringify it again.
+      default_value->append(SimpleItoa(value));
+      break;
+    }
+
+    case FieldDescriptorProto::TYPE_FLOAT:
+    case FieldDescriptorProto::TYPE_DOUBLE:
+      // These types can be negative.
+      if (TryConsume("-")) {
+        default_value->append("-");
+      }
+      // Parse the integer because we have to convert hex integers to decimal
+      // floats.
+      double value;
+      DO(ConsumeNumber(&value, "Expected number."));
+      // And stringify it again.
+      default_value->append(SimpleDtoa(value));
+      break;
+
+    case FieldDescriptorProto::TYPE_BOOL:
+      if (TryConsume("true")) {
+        default_value->assign("true");
+      } else if (TryConsume("false")) {
+        default_value->assign("false");
+      } else {
+        AddError("Expected \"true\" or \"false\".");
+        return false;
+      }
+      break;
+
+    case FieldDescriptorProto::TYPE_STRING:
+      // Note: When file opton java_string_check_utf8 is true, if a
+      // non-string representation (eg byte[]) is later supported, it must
+      // be checked for UTF-8-ness.
+      DO(ConsumeString(default_value, "Expected string for field default "
+                       "value."));
+      break;
+
+    case FieldDescriptorProto::TYPE_BYTES:
+      DO(ConsumeString(default_value, "Expected string."));
+      *default_value = CEscape(*default_value);
+      break;
+
+    case FieldDescriptorProto::TYPE_ENUM:
+      DO(ConsumeIdentifier(default_value, "Expected enum identifier for field "
+                                          "default value."));
+      break;
+
+    case FieldDescriptorProto::TYPE_MESSAGE:
+    case FieldDescriptorProto::TYPE_GROUP:
+      AddError("Messages can't have default values.");
+      return false;
+  }
+
+  return true;
+}
+
+bool Parser::ParseJsonName(
+    FieldDescriptorProto* field,
+    const LocationRecorder& field_location,
+    const FileDescriptorProto* containing_file) {
+  if (field->has_json_name()) {
+    AddError("Already set option \"json_name\".");
+    field->clear_json_name();
+  }
+
+  DO(Consume("json_name"));
+  DO(Consume("="));
+
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kJsonNameFieldNumber);
+  location.RecordLegacyLocation(
+      field, DescriptorPool::ErrorCollector::OPTION_VALUE);
+  DO(ConsumeString(field->mutable_json_name(),
+                   "Expected string for JSON name."));
+  return true;
+}
+
+
+bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                                 const LocationRecorder& part_location,
+                                 const FileDescriptorProto* containing_file) {
+  UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
+  string identifier;  // We parse identifiers into this string.
+  if (LookingAt("(")) {  // This is an extension.
+    DO(Consume("("));
+
+    {
+      LocationRecorder location(
+          part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+      // An extension name consists of dot-separated identifiers, and may begin
+      // with a dot.
+      if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
+      while (LookingAt(".")) {
+        DO(Consume("."));
+        name->mutable_name_part()->append(".");
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
+    }
+
+    DO(Consume(")"));
+    name->set_is_extension(true);
+  } else {  // This is a regular field.
+    LocationRecorder location(
+        part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+    DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+    name->mutable_name_part()->append(identifier);
+    name->set_is_extension(false);
+  }
+  return true;
+}
+
+bool Parser::ParseUninterpretedBlock(string* value) {
+  // Note that enclosing braces are not added to *value.
+  // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting
+  // an expression, not a block of statements.
+  DO(Consume("{"));
+  int brace_depth = 1;
+  while (!AtEnd()) {
+    if (LookingAt("{")) {
+      brace_depth++;
+    } else if (LookingAt("}")) {
+      brace_depth--;
+      if (brace_depth == 0) {
+        input_->Next();
+        return true;
+      }
+    }
+    // TODO(sanjay): Interpret line/column numbers to preserve formatting
+    if (!value->empty()) value->push_back(' ');
+    value->append(input_->current().text);
+    input_->Next();
+  }
+  AddError("Unexpected end of stream while parsing aggregate value.");
+  return false;
+}
+
+// We don't interpret the option here. Instead we store it in an
+// UninterpretedOption, to be interpreted later.
+bool Parser::ParseOption(Message* options,
+                         const LocationRecorder& options_location,
+                         const FileDescriptorProto* containing_file,
+                         OptionStyle style) {
+  // Create an entry in the uninterpreted_option field.
+  const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
+      FindFieldByName("uninterpreted_option");
+  GOOGLE_CHECK(uninterpreted_option_field != NULL)
+      << "No field named \"uninterpreted_option\" in the Options proto.";
+
+  const Reflection* reflection = options->GetReflection();
+
+  LocationRecorder location(
+      options_location, uninterpreted_option_field->number(),
+      reflection->FieldSize(*options, uninterpreted_option_field));
+
+  if (style == OPTION_STATEMENT) {
+    DO(Consume("option"));
+  }
+
+  UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
+      options->GetReflection()->AddMessage(options,
+                                           uninterpreted_option_field));
+
+  // Parse dot-separated name.
+  {
+    LocationRecorder name_location(location,
+                                   UninterpretedOption::kNameFieldNumber);
+    name_location.RecordLegacyLocation(
+        uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME);
+
+    {
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location,
+                             containing_file));
+    }
+
+    while (LookingAt(".")) {
+      DO(Consume("."));
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location,
+                             containing_file));
+    }
+  }
+
+  DO(Consume("="));
+
+  {
+    LocationRecorder value_location(location);
+    value_location.RecordLegacyLocation(
+        uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
+
+    // All values are a single token, except for negative numbers, which consist
+    // of a single '-' symbol, followed by a positive number.
+    bool is_negative = TryConsume("-");
+
+    switch (input_->current().type) {
+      case io::Tokenizer::TYPE_START:
+        GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
+        return false;
+
+      case io::Tokenizer::TYPE_END:
+        AddError("Unexpected end of stream while parsing option value.");
+        return false;
+
+      case io::Tokenizer::TYPE_IDENTIFIER: {
+        value_location.AddPath(
+            UninterpretedOption::kIdentifierValueFieldNumber);
+        if (is_negative) {
+          AddError("Invalid '-' symbol before identifier.");
+          return false;
+        }
+        string value;
+        DO(ConsumeIdentifier(&value, "Expected identifier."));
+        uninterpreted_option->set_identifier_value(value);
+        break;
+      }
+
+      case io::Tokenizer::TYPE_INTEGER: {
+        uint64 value;
+        uint64 max_value =
+            is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
+        DO(ConsumeInteger64(max_value, &value, "Expected integer."));
+        if (is_negative) {
+          value_location.AddPath(
+              UninterpretedOption::kNegativeIntValueFieldNumber);
+          uninterpreted_option->set_negative_int_value(
+              -static_cast<int64>(value));
+        } else {
+          value_location.AddPath(
+              UninterpretedOption::kPositiveIntValueFieldNumber);
+          uninterpreted_option->set_positive_int_value(value);
+        }
+        break;
+      }
+
+      case io::Tokenizer::TYPE_FLOAT: {
+        value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
+        double value;
+        DO(ConsumeNumber(&value, "Expected number."));
+        uninterpreted_option->set_double_value(is_negative ? -value : value);
+        break;
+      }
+
+      case io::Tokenizer::TYPE_STRING: {
+        value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
+        if (is_negative) {
+          AddError("Invalid '-' symbol before string.");
+          return false;
+        }
+        string value;
+        DO(ConsumeString(&value, "Expected string."));
+        uninterpreted_option->set_string_value(value);
+        break;
+      }
+
+      case io::Tokenizer::TYPE_SYMBOL:
+        if (LookingAt("{")) {
+          value_location.AddPath(
+              UninterpretedOption::kAggregateValueFieldNumber);
+          DO(ParseUninterpretedBlock(
+              uninterpreted_option->mutable_aggregate_value()));
+        } else {
+          AddError("Expected option value.");
+          return false;
+        }
+        break;
+    }
+  }
+
+  if (style == OPTION_STATEMENT) {
+    DO(ConsumeEndOfDeclaration(";", &location));
+  }
+
+  return true;
+}
+
+bool Parser::ParseExtensions(DescriptorProto* message,
+                             const LocationRecorder& extensions_location,
+                             const FileDescriptorProto* containing_file) {
+  // Parse the declaration.
+  DO(Consume("extensions"));
+
+  do {
+    // Note that kExtensionRangeFieldNumber was already pushed by the parent.
+    LocationRecorder location(extensions_location,
+                              message->extension_range_size());
+
+    DescriptorProto::ExtensionRange* range = message->add_extension_range();
+    location.RecordLegacyLocation(
+        range, DescriptorPool::ErrorCollector::NUMBER);
+
+    int start, end;
+    io::Tokenizer::Token start_token;
+
+    {
+      LocationRecorder start_location(
+          location, DescriptorProto::ExtensionRange::kStartFieldNumber);
+      start_token = input_->current();
+      DO(ConsumeInteger(&start, "Expected field number range."));
+    }
+
+    if (TryConsume("to")) {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+      if (TryConsume("max")) {
+        // Set to the sentinel value - 1 since we increment the value below.
+        // The actual value of the end of the range should be set with
+        // AdjustExtensionRangesWithMaxEndNumber.
+        end = kMaxExtensionRangeSentinel - 1;
+      } else {
+        DO(ConsumeInteger(&end, "Expected integer."));
+      }
+    } else {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+      end_location.StartAt(start_token);
+      end_location.EndAt(start_token);
+      end = start;
+    }
+
+    // Users like to specify inclusive ranges, but in code we like the end
+    // number to be exclusive.
+    ++end;
+
+    range->set_start(start);
+    range->set_end(end);
+  } while (TryConsume(","));
+
+  DO(ConsumeEndOfDeclaration(";", &extensions_location));
+  return true;
+}
+
+// This is similar to extension range parsing, except that "max" is not
+// supported, and accepts field name literals.
+bool Parser::ParseReserved(DescriptorProto* message,
+                           const LocationRecorder& message_location) {
+  // Parse the declaration.
+  DO(Consume("reserved"));
+  if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kReservedNameFieldNumber);
+    return ParseReservedNames(message, location);
+  } else {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kReservedRangeFieldNumber);
+    return ParseReservedNumbers(message, location);
+  }
+}
+
+
+bool Parser::ParseReservedNames(DescriptorProto* message,
+                                const LocationRecorder& parent_location) {
+  do {
+    LocationRecorder location(parent_location, message->reserved_name_size());
+    DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
+  } while (TryConsume(","));
+  DO(ConsumeEndOfDeclaration(";", &parent_location));
+  return true;
+}
+
+bool Parser::ParseReservedNumbers(DescriptorProto* message,
+                                  const LocationRecorder& parent_location) {
+  bool first = true;
+  do {
+    LocationRecorder location(parent_location, message->reserved_range_size());
+
+    DescriptorProto::ReservedRange* range = message->add_reserved_range();
+    int start, end;
+    io::Tokenizer::Token start_token;
+    {
+      LocationRecorder start_location(
+          location, DescriptorProto::ReservedRange::kStartFieldNumber);
+      start_token = input_->current();
+      DO(ConsumeInteger(&start, (first ?
+                                 "Expected field name or number range." :
+                                 "Expected field number range.")));
+    }
+
+    if (TryConsume("to")) {
+      LocationRecorder end_location(
+          location, DescriptorProto::ReservedRange::kEndFieldNumber);
+      DO(ConsumeInteger(&end, "Expected integer."));
+    } else {
+      LocationRecorder end_location(
+          location, DescriptorProto::ReservedRange::kEndFieldNumber);
+      end_location.StartAt(start_token);
+      end_location.EndAt(start_token);
+      end = start;
+    }
+
+    // Users like to specify inclusive ranges, but in code we like the end
+    // number to be exclusive.
+    ++end;
+
+    range->set_start(start);
+    range->set_end(end);
+    first = false;
+  } while (TryConsume(","));
+
+  DO(ConsumeEndOfDeclaration(";", &parent_location));
+  return true;
+}
+
+bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& extend_location,
+                         const FileDescriptorProto* containing_file) {
+  DO(Consume("extend"));
+
+  // Parse the extendee type.
+  io::Tokenizer::Token extendee_start = input_->current();
+  string extendee;
+  DO(ParseUserDefinedType(&extendee));
+  io::Tokenizer::Token extendee_end = input_->previous();
+
+  // Parse the block.
+  DO(ConsumeEndOfDeclaration("{", &extend_location));
+
+  bool is_first = true;
+
+  do {
+    if (AtEnd()) {
+      AddError("Reached end of input in extend definition (missing '}').");
+      return false;
+    }
+
+    // Note that kExtensionFieldNumber was already pushed by the parent.
+    LocationRecorder location(extend_location, extensions->size());
+
+    FieldDescriptorProto* field = extensions->Add();
+
+    {
+      LocationRecorder extendee_location(
+          location, FieldDescriptorProto::kExtendeeFieldNumber);
+      extendee_location.StartAt(extendee_start);
+      extendee_location.EndAt(extendee_end);
+
+      if (is_first) {
+        extendee_location.RecordLegacyLocation(
+            field, DescriptorPool::ErrorCollector::EXTENDEE);
+        is_first = false;
+      }
+    }
+
+    field->set_extendee(extendee);
+
+    if (!ParseMessageField(field, messages, parent_location,
+                           location_field_number_for_nested_type,
+                           location,
+                           containing_file)) {
+      // This statement failed to parse.  Skip it, but keep looping to parse
+      // other statements.
+      SkipStatement();
+    }
+  } while (!TryConsumeEndOfDeclaration("}", NULL));
+
+  return true;
+}
+
+bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl,
+                        DescriptorProto* containing_type,
+                        int oneof_index,
+                        const LocationRecorder& oneof_location,
+                        const LocationRecorder& containing_type_location,
+                        const FileDescriptorProto* containing_file) {
+  DO(Consume("oneof"));
+
+  {
+    LocationRecorder name_location(oneof_location,
+                                   OneofDescriptorProto::kNameFieldNumber);
+    DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name."));
+  }
+
+  DO(ConsumeEndOfDeclaration("{", &oneof_location));
+
+  do {
+    if (AtEnd()) {
+      AddError("Reached end of input in oneof definition (missing '}').");
+      return false;
+    }
+
+    // Print a nice error if the user accidentally tries to place a label
+    // on an individual member of a oneof.
+    if (LookingAt("required") ||
+        LookingAt("optional") ||
+        LookingAt("repeated")) {
+      AddError("Fields in oneofs must not have labels (required / optional "
+               "/ repeated).");
+      // We can continue parsing here because we understand what the user
+      // meant.  The error report will still make parsing fail overall.
+      input_->Next();
+    }
+
+    LocationRecorder field_location(containing_type_location,
+                                    DescriptorProto::kFieldFieldNumber,
+                                    containing_type->field_size());
+
+    FieldDescriptorProto* field = containing_type->add_field();
+    field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+    field->set_oneof_index(oneof_index);
+
+    if (!ParseMessageFieldNoLabel(field,
+                                  containing_type->mutable_nested_type(),
+                                  containing_type_location,
+                                  DescriptorProto::kNestedTypeFieldNumber,
+                                  field_location,
+                                  containing_file)) {
+      // This statement failed to parse.  Skip it, but keep looping to parse
+      // other statements.
+      SkipStatement();
+    }
+  } while (!TryConsumeEndOfDeclaration("}", NULL));
+
+  return true;
+}
+
+// -------------------------------------------------------------------
+// Enums
+
+bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                                 const LocationRecorder& enum_location,
+                                 const FileDescriptorProto* containing_file) {
+  DO(Consume("enum"));
+
+  {
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_type, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
+  }
+
+  DO(ParseEnumBlock(enum_type, enum_location, containing_file));
+
+  DO(ValidateEnum(enum_type));
+
+  return true;
+}
+
+bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
+                            const LocationRecorder& enum_location,
+                            const FileDescriptorProto* containing_file) {
+  DO(ConsumeEndOfDeclaration("{", &enum_location));
+
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
+    if (AtEnd()) {
+      AddError("Reached end of input in enum definition (missing '}').");
+      return false;
+    }
+
+    if (!ParseEnumStatement(enum_type, enum_location, containing_file)) {
+      // This statement failed to parse.  Skip it, but keep looping to parse
+      // other statements.
+      SkipStatement();
+    }
+  }
+
+  return true;
+}
+
+bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
+                                const LocationRecorder& enum_location,
+                                const FileDescriptorProto* containing_file) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
+    // empty statement; ignore
+    return true;
+  } else if (LookingAt("option")) {
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(enum_type->mutable_options(), location,
+                       containing_file, OPTION_STATEMENT);
+  } else {
+    LocationRecorder location(enum_location,
+        EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
+    return ParseEnumConstant(enum_type->add_value(), location, containing_file);
+  }
+}
+
+bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                               const LocationRecorder& enum_value_location,
+                               const FileDescriptorProto* containing_file) {
+  // Parse name.
+  {
+    LocationRecorder location(enum_value_location,
+                              EnumValueDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_value->mutable_name(),
+                         "Expected enum constant name."));
+  }
+
+  DO(Consume("=", "Missing numeric value for enum constant."));
+
+  // Parse value.
+  {
+    LocationRecorder location(
+        enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NUMBER);
+
+    int number;
+    DO(ConsumeSignedInteger(&number, "Expected integer."));
+    enum_value->set_number(number);
+  }
+
+  DO(ParseEnumConstantOptions(enum_value, enum_value_location,
+                              containing_file));
+
+  DO(ConsumeEndOfDeclaration(";", &enum_value_location));
+
+  return true;
+}
+
+bool Parser::ParseEnumConstantOptions(
+    EnumValueDescriptorProto* value,
+    const LocationRecorder& enum_value_location,
+    const FileDescriptorProto* containing_file) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(
+      enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
+
+  do {
+    DO(ParseOption(value->mutable_options(), location,
+                   containing_file, OPTION_ASSIGNMENT));
+  } while (TryConsume(","));
+
+  DO(Consume("]"));
+  return true;
+}
+
+// -------------------------------------------------------------------
+// Services
+
+bool Parser::ParseServiceDefinition(
+    ServiceDescriptorProto* service,
+    const LocationRecorder& service_location,
+    const FileDescriptorProto* containing_file) {
+  DO(Consume("service"));
+
+  {
+    LocationRecorder location(service_location,
+                              ServiceDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        service, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
+  }
+
+  DO(ParseServiceBlock(service, service_location, containing_file));
+  return true;
+}
+
+bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
+                               const LocationRecorder& service_location,
+                               const FileDescriptorProto* containing_file) {
+  DO(ConsumeEndOfDeclaration("{", &service_location));
+
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
+    if (AtEnd()) {
+      AddError("Reached end of input in service definition (missing '}').");
+      return false;
+    }
+
+    if (!ParseServiceStatement(service, service_location, containing_file)) {
+      // This statement failed to parse.  Skip it, but keep looping to parse
+      // other statements.
+      SkipStatement();
+    }
+  }
+
+  return true;
+}
+
+bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
+                                   const LocationRecorder& service_location,
+                                   const FileDescriptorProto* containing_file) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
+    // empty statement; ignore
+    return true;
+  } else if (LookingAt("option")) {
+    LocationRecorder location(
+        service_location, ServiceDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(service->mutable_options(), location,
+                       containing_file, OPTION_STATEMENT);
+  } else {
+    LocationRecorder location(service_location,
+        ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
+    return ParseServiceMethod(service->add_method(), location, containing_file);
+  }
+}
+
+bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
+                                const LocationRecorder& method_location,
+                                const FileDescriptorProto* containing_file) {
+  DO(Consume("rpc"));
+
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+  }
+
+  // Parse input type.
+  DO(Consume("("));
+  {
+    if (LookingAt("stream")) {
+      LocationRecorder location(
+          method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
+      location.RecordLegacyLocation(
+          method, DescriptorPool::ErrorCollector::OTHER);
+      method->set_client_streaming(true);
+      DO(Consume("stream"));
+
+    }
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kInputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::INPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_input_type()));
+  }
+  DO(Consume(")"));
+
+  // Parse output type.
+  DO(Consume("returns"));
+  DO(Consume("("));
+  {
+    if (LookingAt("stream")) {
+      LocationRecorder location(
+          method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
+      location.RecordLegacyLocation(
+          method, DescriptorPool::ErrorCollector::OTHER);
+      DO(Consume("stream"));
+      method->set_server_streaming(true);
+
+    }
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kOutputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_output_type()));
+  }
+  DO(Consume(")"));
+
+  if (LookingAt("{")) {
+    // Options!
+    DO(ParseMethodOptions(method_location, containing_file,
+                          MethodDescriptorProto::kOptionsFieldNumber,
+                          method->mutable_options()));
+  } else {
+    DO(ConsumeEndOfDeclaration(";", &method_location));
+  }
+
+  return true;
+}
+
+
+bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
+                                const FileDescriptorProto* containing_file,
+                                const int optionsFieldNumber,
+                                Message* mutable_options) {
+  // Options!
+  ConsumeEndOfDeclaration("{", &parent_location);
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
+    if (AtEnd()) {
+      AddError("Reached end of input in method options (missing '}').");
+      return false;
+    }
+
+    if (TryConsumeEndOfDeclaration(";", NULL)) {
+      // empty statement; ignore
+    } else {
+      LocationRecorder location(parent_location,
+                                optionsFieldNumber);
+      if (!ParseOption(mutable_options, location,
+                       containing_file, OPTION_STATEMENT)) {
+        // This statement failed to parse.  Skip it, but keep looping to
+        // parse other statements.
+        SkipStatement();
+      }
+    }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------
+
+bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
+                        const FileDescriptorProto* containing_file) {
+  if (TryConsume("optional")) {
+    *label = FieldDescriptorProto::LABEL_OPTIONAL;
+    return true;
+  } else if (TryConsume("repeated")) {
+    *label = FieldDescriptorProto::LABEL_REPEATED;
+    return true;
+  } else if (TryConsume("required")) {
+    *label = FieldDescriptorProto::LABEL_REQUIRED;
+    return true;
+  }
+  return false;
+}
+
+bool Parser::ParseType(FieldDescriptorProto::Type* type,
+                       string* type_name) {
+  TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
+  if (iter != kTypeNames.end()) {
+    *type = iter->second;
+    input_->Next();
+  } else {
+    DO(ParseUserDefinedType(type_name));
+  }
+  return true;
+}
+
+bool Parser::ParseUserDefinedType(string* type_name) {
+  type_name->clear();
+
+  TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
+  if (iter != kTypeNames.end()) {
+    // Note:  The only place enum types are allowed is for field types, but
+    //   if we are parsing a field type then we would not get here because
+    //   primitives are allowed there as well.  So this error message doesn't
+    //   need to account for enums.
+    AddError("Expected message type.");
+
+    // Pretend to accept this type so that we can go on parsing.
+    *type_name = input_->current().text;
+    input_->Next();
+    return true;
+  }
+
+  // A leading "." means the name is fully-qualified.
+  if (TryConsume(".")) type_name->append(".");
+
+  // Consume the first part of the name.
+  string identifier;
+  DO(ConsumeIdentifier(&identifier, "Expected type name."));
+  type_name->append(identifier);
+
+  // Consume more parts.
+  while (TryConsume(".")) {
+    type_name->append(".");
+    DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+    type_name->append(identifier);
+  }
+
+  return true;
+}
+
+// ===================================================================
+
+bool Parser::ParsePackage(FileDescriptorProto* file,
+                          const LocationRecorder& root_location,
+                          const FileDescriptorProto* containing_file) {
+  if (file->has_package()) {
+    AddError("Multiple package definitions.");
+    // Don't append the new package to the old one.  Just replace it.  Not
+    // that it really matters since this is an error anyway.
+    file->clear_package();
+  }
+
+  DO(Consume("package"));
+
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kPackageFieldNumber);
+    location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME);
+
+    while (true) {
+      string identifier;
+      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+      file->mutable_package()->append(identifier);
+      if (!TryConsume(".")) break;
+      file->mutable_package()->append(".");
+    }
+
+    location.EndAt(input_->previous());
+
+    DO(ConsumeEndOfDeclaration(";", &location));
+  }
+
+  return true;
+}
+
+bool Parser::ParseImport(RepeatedPtrField<string>* dependency,
+                         RepeatedField<int32>* public_dependency,
+                         RepeatedField<int32>* weak_dependency,
+                         const LocationRecorder& root_location,
+                         const FileDescriptorProto* containing_file) {
+  DO(Consume("import"));
+  if (LookingAt("public")) {
+    LocationRecorder location(
+        root_location, FileDescriptorProto::kPublicDependencyFieldNumber,
+        public_dependency->size());
+    DO(Consume("public"));
+    *public_dependency->Add() = dependency->size();
+  } else if (LookingAt("weak")) {
+    LocationRecorder location(
+        root_location, FileDescriptorProto::kWeakDependencyFieldNumber,
+        weak_dependency->size());
+    DO(Consume("weak"));
+    *weak_dependency->Add() = dependency->size();
+  }
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kDependencyFieldNumber,
+                              dependency->size());
+    DO(ConsumeString(dependency->Add(),
+      "Expected a string naming the file to import."));
+
+    location.EndAt(input_->previous());
+
+    DO(ConsumeEndOfDeclaration(";", &location));
+  }
+  return true;
+}
+
+// ===================================================================
+
+SourceLocationTable::SourceLocationTable() {}
+SourceLocationTable::~SourceLocationTable() {}
+
+bool SourceLocationTable::Find(
+    const Message* descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    int* line, int* column) const {
+  const pair<int, int>* result =
+      FindOrNull(location_map_, std::make_pair(descriptor, location));
+  if (result == NULL) {
+    *line   = -1;
+    *column = 0;
+    return false;
+  } else {
+    *line   = result->first;
+    *column = result->second;
+    return true;
+  }
+}
+
+void SourceLocationTable::Add(
+    const Message* descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    int line, int column) {
+  location_map_[std::make_pair(descriptor, location)] =
+      std::make_pair(line, column);
+}
+
+void SourceLocationTable::Clear() {
+  location_map_.clear();
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.h
new file mode 100644
index 0000000..2c561c2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser.h
@@ -0,0 +1,569 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Implements parsing of .proto files to FileDescriptorProtos.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
+#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
+
+#include <map>
+#include <string>
+#include <utility>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/io/tokenizer.h>
+
+namespace google {
+namespace protobuf { class Message; }
+
+namespace protobuf {
+namespace compiler {
+
+// Defined in this file.
+class Parser;
+class SourceLocationTable;
+
+// Implements parsing of protocol definitions (such as .proto files).
+//
+// Note that most users will be more interested in the Importer class.
+// Parser is a lower-level class which simply converts a single .proto file
+// to a FileDescriptorProto.  It does not resolve import directives or perform
+// many other kinds of validation needed to construct a complete
+// FileDescriptor.
+class LIBPROTOBUF_EXPORT Parser {
+ public:
+  Parser();
+  ~Parser();
+
+  // Parse the entire input and construct a FileDescriptorProto representing
+  // it.  Returns true if no errors occurred, false otherwise.
+  bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
+
+  // Optional fetaures:
+
+  // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
+  //   FileDescriptorProto.
+  //
+  // Requests that locations of certain definitions be recorded to the given
+  // SourceLocationTable while parsing.  This can be used to look up exact line
+  // and column numbers for errors reported by DescriptorPool during validation.
+  // Set to NULL (the default) to discard source location information.
+  void RecordSourceLocationsTo(SourceLocationTable* location_table) {
+    source_location_table_ = location_table;
+  }
+
+  // Requests that errors be recorded to the given ErrorCollector while
+  // parsing.  Set to NULL (the default) to discard error messages.
+  void RecordErrorsTo(io::ErrorCollector* error_collector) {
+    error_collector_ = error_collector;
+  }
+
+  // Returns the identifier used in the "syntax = " declaration, if one was
+  // seen during the last call to Parse(), or the empty string otherwise.
+  const string& GetSyntaxIdentifier() { return syntax_identifier_; }
+
+  // If set true, input files will be required to begin with a syntax
+  // identifier.  Otherwise, files may omit this.  If a syntax identifier
+  // is provided, it must be 'syntax = "proto2";' and must appear at the
+  // top of this file regardless of whether or not it was required.
+  void SetRequireSyntaxIdentifier(bool value) {
+    require_syntax_identifier_ = value;
+  }
+
+  // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
+  // parsing as soon as it has seen the syntax identifier, or lack thereof.
+  // This is useful for quickly identifying the syntax of the file without
+  // parsing the whole thing.  If this is enabled, no error will be recorded
+  // if the syntax identifier is something other than "proto2" (since
+  // presumably the caller intends to deal with that), but other kinds of
+  // errors (e.g. parse errors) will still be reported.  When this is enabled,
+  // you may pass a NULL FileDescriptorProto to Parse().
+  void SetStopAfterSyntaxIdentifier(bool value) {
+    stop_after_syntax_identifier_ = value;
+  }
+
+ private:
+  class LocationRecorder;
+
+  // =================================================================
+  // Error recovery helpers
+
+  // Consume the rest of the current statement.  This consumes tokens
+  // until it sees one of:
+  //   ';'  Consumes the token and returns.
+  //   '{'  Consumes the brace then calls SkipRestOfBlock().
+  //   '}'  Returns without consuming.
+  //   EOF  Returns (can't consume).
+  // The Parser often calls SkipStatement() after encountering a syntax
+  // error.  This allows it to go on parsing the following lines, allowing
+  // it to report more than just one error in the file.
+  void SkipStatement();
+
+  // Consume the rest of the current block, including nested blocks,
+  // ending after the closing '}' is encountered and consumed, or at EOF.
+  void SkipRestOfBlock();
+
+  // -----------------------------------------------------------------
+  // Single-token consuming helpers
+  //
+  // These make parsing code more readable.
+
+  // True if the current token is TYPE_END.
+  inline bool AtEnd();
+
+  // True if the next token matches the given text.
+  inline bool LookingAt(const char* text);
+  // True if the next token is of the given type.
+  inline bool LookingAtType(io::Tokenizer::TokenType token_type);
+
+  // If the next token exactly matches the text given, consume it and return
+  // true.  Otherwise, return false without logging an error.
+  bool TryConsume(const char* text);
+
+  // These attempt to read some kind of token from the input.  If successful,
+  // they return true.  Otherwise they return false and add the given error
+  // to the error list.
+
+  // Consume a token with the exact text given.
+  bool Consume(const char* text, const char* error);
+  // Same as above, but automatically generates the error "Expected \"text\".",
+  // where "text" is the expected token text.
+  bool Consume(const char* text);
+  // Consume a token of type IDENTIFIER and store its text in "output".
+  bool ConsumeIdentifier(string* output, const char* error);
+  // Consume an integer and store its value in "output".
+  bool ConsumeInteger(int* output, const char* error);
+  // Consume a signed integer and store its value in "output".
+  bool ConsumeSignedInteger(int* output, const char* error);
+  // Consume a 64-bit integer and store its value in "output".  If the value
+  // is greater than max_value, an error will be reported.
+  bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
+  // Consume a number and store its value in "output".  This will accept
+  // tokens of either INTEGER or FLOAT type.
+  bool ConsumeNumber(double* output, const char* error);
+  // Consume a string literal and store its (unescaped) value in "output".
+  bool ConsumeString(string* output, const char* error);
+
+  // Consume a token representing the end of the statement.  Comments between
+  // this token and the next will be harvested for documentation.  The given
+  // LocationRecorder should refer to the declaration that was just parsed;
+  // it will be populated with these comments.
+  //
+  // TODO(kenton):  The LocationRecorder is const because historically locations
+  //   have been passed around by const reference, for no particularly good
+  //   reason.  We should probably go through and change them all to mutable
+  //   pointer to make this more intuitive.
+  bool TryConsumeEndOfDeclaration(
+      const char* text, const LocationRecorder* location);
+  bool TryConsumeEndOfDeclarationFinishScope(
+      const char* text, const LocationRecorder* location);
+
+  bool ConsumeEndOfDeclaration(
+      const char* text, const LocationRecorder* location);
+
+  // -----------------------------------------------------------------
+  // Error logging helpers
+
+  // Invokes error_collector_->AddError(), if error_collector_ is not NULL.
+  void AddError(int line, int column, const string& error);
+
+  // Invokes error_collector_->AddError() with the line and column number
+  // of the current token.
+  void AddError(const string& error);
+
+  // Records a location in the SourceCodeInfo.location table (see
+  // descriptor.proto).  We use RAII to ensure that the start and end locations
+  // are recorded -- the constructor records the start location and the
+  // destructor records the end location.  Since the parser is
+  // recursive-descent, this works out beautifully.
+  class LIBPROTOBUF_EXPORT LocationRecorder {
+   public:
+    // Construct the file's "root" location.
+    LocationRecorder(Parser* parser);
+
+    // Construct a location that represents a declaration nested within the
+    // given parent.  E.g. a field's location is nested within the location
+    // for a message type.  The parent's path will be copied, so you should
+    // call AddPath() only to add the path components leading from the parent
+    // to the child (as opposed to leading from the root to the child).
+    LocationRecorder(const LocationRecorder& parent);
+
+    // Convenience constructors that call AddPath() one or two times.
+    LocationRecorder(const LocationRecorder& parent, int path1);
+    LocationRecorder(const LocationRecorder& parent, int path1, int path2);
+
+    ~LocationRecorder();
+
+    // Add a path component.  See SourceCodeInfo.Location.path in
+    // descriptor.proto.
+    void AddPath(int path_component);
+
+    // By default the location is considered to start at the current token at
+    // the time the LocationRecorder is created.  StartAt() sets the start
+    // location to the given token instead.
+    void StartAt(const io::Tokenizer::Token& token);
+
+    // Start at the same location as some other LocationRecorder.
+    void StartAt(const LocationRecorder& other);
+
+    // By default the location is considered to end at the previous token at
+    // the time the LocationRecorder is destroyed.  EndAt() sets the end
+    // location to the given token instead.
+    void EndAt(const io::Tokenizer::Token& token);
+
+    // Records the start point of this location to the SourceLocationTable that
+    // was passed to RecordSourceLocationsTo(), if any.  SourceLocationTable
+    // is an older way of keeping track of source locations which is still
+    // used in some places.
+    void RecordLegacyLocation(const Message* descriptor,
+        DescriptorPool::ErrorCollector::ErrorLocation location);
+
+    // Attaches leading and trailing comments to the location.  The two strings
+    // will be swapped into place, so after this is called *leading and
+    // *trailing will be empty.
+    //
+    // TODO(kenton):  See comment on TryConsumeEndOfDeclaration(), above, for
+    //   why this is const.
+    void AttachComments(string* leading, string* trailing,
+                        vector<string>* detached_comments) const;
+
+   private:
+    // Indexes of parent and current location in the parent
+    // SourceCodeInfo.location repeated field. For top-level elements,
+    // parent_index_ is -1.
+    Parser* parser_;
+    SourceCodeInfo::Location* location_;
+
+    void Init(const LocationRecorder& parent);
+  };
+
+  // =================================================================
+  // Parsers for various language constructs
+
+  // Parses the "syntax = \"proto2\";" line at the top of the file.  Returns
+  // false if it failed to parse or if the syntax identifier was not
+  // recognized.
+  bool ParseSyntaxIdentifier(const LocationRecorder& parent);
+
+  // These methods parse various individual bits of code.  They return
+  // false if they completely fail to parse the construct.  In this case,
+  // it is probably necessary to skip the rest of the statement to recover.
+  // However, if these methods return true, it does NOT mean that there
+  // were no errors; only that there were no *syntax* errors.  For instance,
+  // if a service method is defined using proper syntax but uses a primitive
+  // type as its input or output, ParseMethodField() still returns true
+  // and only reports the error by calling AddError().  In practice, this
+  // makes logic much simpler for the caller.
+
+  // Parse a top-level message, enum, service, etc.
+  bool ParseTopLevelStatement(FileDescriptorProto* file,
+                              const LocationRecorder& root_location);
+
+  // Parse various language high-level language construrcts.
+  bool ParseMessageDefinition(DescriptorProto* message,
+                              const LocationRecorder& message_location,
+                              const FileDescriptorProto* containing_file);
+  bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                           const LocationRecorder& enum_location,
+                           const FileDescriptorProto* containing_file);
+  bool ParseServiceDefinition(ServiceDescriptorProto* service,
+                              const LocationRecorder& service_location,
+                              const FileDescriptorProto* containing_file);
+  bool ParsePackage(FileDescriptorProto* file,
+                    const LocationRecorder& root_location,
+                    const FileDescriptorProto* containing_file);
+  bool ParseImport(RepeatedPtrField<string>* dependency,
+                   RepeatedField<int32>* public_dependency,
+                   RepeatedField<int32>* weak_dependency,
+                   const LocationRecorder& root_location,
+                   const FileDescriptorProto* containing_file);
+
+  // These methods parse the contents of a message, enum, or service type and
+  // add them to the given object.  They consume the entire block including
+  // the beginning and ending brace.
+  bool ParseMessageBlock(DescriptorProto* message,
+                         const LocationRecorder& message_location,
+                         const FileDescriptorProto* containing_file);
+  bool ParseEnumBlock(EnumDescriptorProto* enum_type,
+                      const LocationRecorder& enum_location,
+                      const FileDescriptorProto* containing_file);
+  bool ParseServiceBlock(ServiceDescriptorProto* service,
+                         const LocationRecorder& service_location,
+                         const FileDescriptorProto* containing_file);
+
+  // Parse one statement within a message, enum, or service block, including
+  // final semicolon.
+  bool ParseMessageStatement(DescriptorProto* message,
+                             const LocationRecorder& message_location,
+                             const FileDescriptorProto* containing_file);
+  bool ParseEnumStatement(EnumDescriptorProto* message,
+                          const LocationRecorder& enum_location,
+                          const FileDescriptorProto* containing_file);
+  bool ParseServiceStatement(ServiceDescriptorProto* message,
+                             const LocationRecorder& service_location,
+                             const FileDescriptorProto* containing_file);
+
+  // Parse a field of a message.  If the field is a group, its type will be
+  // added to "messages".
+  //
+  // parent_location and location_field_number_for_nested_type are needed when
+  // parsing groups -- we need to generate a nested message type within the
+  // parent and record its location accordingly.  Since the parent could be
+  // either a FileDescriptorProto or a DescriptorProto, we must pass in the
+  // correct field number to use.
+  bool ParseMessageField(FieldDescriptorProto* field,
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& field_location,
+                         const FileDescriptorProto* containing_file);
+
+  // Like ParseMessageField() but expects the label has already been filled in
+  // by the caller.
+  bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
+                                RepeatedPtrField<DescriptorProto>* messages,
+                                const LocationRecorder& parent_location,
+                                int location_field_number_for_nested_type,
+                                const LocationRecorder& field_location,
+                                const FileDescriptorProto* containing_file);
+
+  // Parse an "extensions" declaration.
+  bool ParseExtensions(DescriptorProto* message,
+                       const LocationRecorder& extensions_location,
+                       const FileDescriptorProto* containing_file);
+
+  // Parse a "reserved" declaration.
+  bool ParseReserved(DescriptorProto* message,
+                     const LocationRecorder& message_location);
+  bool ParseReservedNames(DescriptorProto* message,
+                          const LocationRecorder& parent_location);
+  bool ParseReservedNumbers(DescriptorProto* message,
+                            const LocationRecorder& parent_location);
+
+  // Parse an "extend" declaration.  (See also comments for
+  // ParseMessageField().)
+  bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
+                   RepeatedPtrField<DescriptorProto>* messages,
+                   const LocationRecorder& parent_location,
+                   int location_field_number_for_nested_type,
+                   const LocationRecorder& extend_location,
+                   const FileDescriptorProto* containing_file);
+
+  // Parse a "oneof" declaration.  The caller is responsible for setting
+  // oneof_decl->label() since it will have had to parse the label before it
+  // knew it was parsing a oneof.
+  bool ParseOneof(OneofDescriptorProto* oneof_decl,
+                  DescriptorProto* containing_type,
+                  int oneof_index,
+                  const LocationRecorder& oneof_location,
+                  const LocationRecorder& containing_type_location,
+                  const FileDescriptorProto* containing_file);
+
+  // Parse a single enum value within an enum block.
+  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                         const LocationRecorder& enum_value_location,
+                         const FileDescriptorProto* containing_file);
+
+  // Parse enum constant options, i.e. the list in square brackets at the end
+  // of the enum constant value definition.
+  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
+                                const LocationRecorder& enum_value_location,
+                                const FileDescriptorProto* containing_file);
+
+  // Parse a single method within a service definition.
+  bool ParseServiceMethod(MethodDescriptorProto* method,
+                          const LocationRecorder& method_location,
+                          const FileDescriptorProto* containing_file);
+
+
+  // Parse options of a single method or stream.
+  bool ParseMethodOptions(const LocationRecorder& parent_location,
+                          const FileDescriptorProto* containing_file,
+                          const int optionsFieldNumber,
+                          Message* mutable_options);
+
+  // Parse "required", "optional", or "repeated" and fill in "label"
+  // with the value. Returns true if such a label is consumed.
+  bool ParseLabel(FieldDescriptorProto::Label* label,
+                  const FileDescriptorProto* containing_file);
+
+  // Parse a type name and fill in "type" (if it is a primitive) or
+  // "type_name" (if it is not) with the type parsed.
+  bool ParseType(FieldDescriptorProto::Type* type,
+                 string* type_name);
+  // Parse a user-defined type and fill in "type_name" with the name.
+  // If a primitive type is named, it is treated as an error.
+  bool ParseUserDefinedType(string* type_name);
+
+  // Parses field options, i.e. the stuff in square brackets at the end
+  // of a field definition.  Also parses default value.
+  bool ParseFieldOptions(FieldDescriptorProto* field,
+                         const LocationRecorder& field_location,
+                         const FileDescriptorProto* containing_file);
+
+  // Parse the "default" option.  This needs special handling because its
+  // type is the field's type.
+  bool ParseDefaultAssignment(FieldDescriptorProto* field,
+                              const LocationRecorder& field_location,
+                              const FileDescriptorProto* containing_file);
+
+  bool ParseJsonName(FieldDescriptorProto* field,
+                     const LocationRecorder& field_location,
+                     const FileDescriptorProto* containing_file);
+
+  enum OptionStyle {
+    OPTION_ASSIGNMENT,  // just "name = value"
+    OPTION_STATEMENT    // "option name = value;"
+  };
+
+  // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
+  // identifies a field of the given Message, and the value of that field
+  // is set to the parsed value.
+  bool ParseOption(Message* options,
+                   const LocationRecorder& options_location,
+                   const FileDescriptorProto* containing_file,
+                   OptionStyle style);
+
+  // Parses a single part of a multipart option name. A multipart name consists
+  // of names separated by dots. Each name is either an identifier or a series
+  // of identifiers separated by dots and enclosed in parentheses. E.g.,
+  // "foo.(bar.baz).qux".
+  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                           const LocationRecorder& part_location,
+                           const FileDescriptorProto* containing_file);
+
+  // Parses a string surrounded by balanced braces.  Strips off the outer
+  // braces and stores the enclosed string in *value.
+  // E.g.,
+  //     { foo }                     *value gets 'foo'
+  //     { foo { bar: box } }        *value gets 'foo { bar: box }'
+  //     {}                          *value gets ''
+  //
+  // REQUIRES: LookingAt("{")
+  // When finished successfully, we are looking at the first token past
+  // the ending brace.
+  bool ParseUninterpretedBlock(string* value);
+
+  struct MapField {
+    // Whether the field is a map field.
+    bool is_map_field;
+    // The types of the key and value if they are primitive types.
+    FieldDescriptorProto::Type key_type;
+    FieldDescriptorProto::Type value_type;
+    // Or the type names string if the types are customized types.
+    string key_type_name;
+    string value_type_name;
+
+    MapField() : is_map_field(false) {}
+  };
+  // Desugar the map syntax to generate a nested map entry message.
+  void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
+                        RepeatedPtrField<DescriptorProto>* messages);
+
+  // Whether fields without label default to optional fields.
+  bool DefaultToOptionalFields() const {
+    return syntax_identifier_ == "proto3";
+  }
+
+
+  bool ValidateEnum(const EnumDescriptorProto* proto);
+
+  // =================================================================
+
+  io::Tokenizer* input_;
+  io::ErrorCollector* error_collector_;
+  SourceCodeInfo* source_code_info_;
+  SourceLocationTable* source_location_table_;  // legacy
+  bool had_errors_;
+  bool require_syntax_identifier_;
+  bool stop_after_syntax_identifier_;
+  string syntax_identifier_;
+
+  // Leading doc comments for the next declaration.  These are not complete
+  // yet; use ConsumeEndOfDeclaration() to get the complete comments.
+  string upcoming_doc_comments_;
+
+  // Detached comments are not connected to any syntax entities. Elements in
+  // this vector are paragraphs of comments separated by empty lines. The
+  // detached comments will be put into the leading_detached_comments field for
+  // the next element (See SourceCodeInfo.Location in descriptor.proto), when
+  // ConsumeEndOfDeclaration() is called.
+  vector<string> upcoming_detached_comments_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
+};
+
+// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
+// DescriptorPool when validating descriptors -- to line and column numbers
+// within the original source code.
+//
+// This is semi-obsolete:  FileDescriptorProto.source_code_info now contains
+// far more complete information about source locations.  However, as of this
+// writing you still need to use SourceLocationTable when integrating with
+// DescriptorPool.
+class LIBPROTOBUF_EXPORT SourceLocationTable {
+ public:
+  SourceLocationTable();
+  ~SourceLocationTable();
+
+  // Finds the precise location of the given error and fills in *line and
+  // *column with the line and column numbers.  If not found, sets *line to
+  // -1 and *column to 0 (since line = -1 is used to mean "error has no exact
+  // location" in the ErrorCollector interface).  Returns true if found, false
+  // otherwise.
+  bool Find(const Message* descriptor,
+            DescriptorPool::ErrorCollector::ErrorLocation location,
+            int* line, int* column) const;
+
+  // Adds a location to the table.
+  void Add(const Message* descriptor,
+           DescriptorPool::ErrorCollector::ErrorLocation location,
+           int line, int column);
+
+  // Clears the contents of the table.
+  void Clear();
+
+ private:
+  typedef map<
+    pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
+    pair<int, int> > LocationMap;
+  LocationMap location_map_;
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/parser_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser_unittest.cc
new file mode 100644
index 0000000..1d623dd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/parser_unittest.cc
@@ -0,0 +1,3157 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+#include <algorithm>
+#include <map>
+
+#include <google/protobuf/compiler/parser.h>
+
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map_util.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+class MockErrorCollector : public io::ErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(int line, int column, const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
+                                 line, column, message);
+  }
+};
+
+class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  MockValidationErrorCollector(const SourceLocationTable& source_locations,
+                               io::ErrorCollector* wrapped_collector)
+    : source_locations_(source_locations),
+      wrapped_collector_(wrapped_collector) {}
+  ~MockValidationErrorCollector() {}
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename,
+                const string& element_name,
+                const Message* descriptor,
+                ErrorLocation location,
+                const string& message) {
+    int line, column;
+    source_locations_.Find(descriptor, location, &line, &column);
+    wrapped_collector_->AddError(line, column, message);
+  }
+
+ private:
+  const SourceLocationTable& source_locations_;
+  io::ErrorCollector* wrapped_collector_;
+};
+
+class ParserTest : public testing::Test {
+ protected:
+  ParserTest()
+    : require_syntax_identifier_(false) {}
+
+  // Set up the parser to parse the given text.
+  void SetupParser(const char* text) {
+    raw_input_.reset(new io::ArrayInputStream(text, strlen(text)));
+    input_.reset(new io::Tokenizer(raw_input_.get(), &error_collector_));
+    parser_.reset(new Parser());
+    parser_->RecordErrorsTo(&error_collector_);
+    parser_->SetRequireSyntaxIdentifier(require_syntax_identifier_);
+  }
+
+  // Parse the input and expect that the resulting FileDescriptorProto matches
+  // the given output.  The output is a FileDescriptorProto in protocol buffer
+  // text format.
+  void ExpectParsesTo(const char* input, const char* output) {
+    SetupParser(input);
+    FileDescriptorProto actual, expected;
+
+    parser_->Parse(input_.get(), &actual);
+    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+    ASSERT_EQ("", error_collector_.text_);
+
+    // We don't cover SourceCodeInfo in these tests.
+    actual.clear_source_code_info();
+
+    // Parse the ASCII representation in order to canonicalize it.  We could
+    // just compare directly to actual.DebugString(), but that would require
+    // that the caller precisely match the formatting that DebugString()
+    // produces.
+    ASSERT_TRUE(TextFormat::ParseFromString(output, &expected));
+
+    // Compare by comparing debug strings.
+    // TODO(kenton):  Use differencer, once it is available.
+    EXPECT_EQ(expected.DebugString(), actual.DebugString());
+  }
+
+  // Parse the text and expect that the given errors are reported.
+  void ExpectHasErrors(const char* text, const char* expected_errors) {
+    ExpectHasEarlyExitErrors(text, expected_errors);
+    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+  }
+
+  // Same as above but does not expect that the parser parses the complete
+  // input.
+  void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) {
+    SetupParser(text);
+    FileDescriptorProto file;
+    parser_->Parse(input_.get(), &file);
+    EXPECT_EQ(expected_errors, error_collector_.text_);
+  }
+
+  // Parse the text as a file and validate it (with a DescriptorPool), and
+  // expect that the validation step reports the given errors.
+  void ExpectHasValidationErrors(const char* text,
+                                 const char* expected_errors) {
+    SetupParser(text);
+    SourceLocationTable source_locations;
+    parser_->RecordSourceLocationsTo(&source_locations);
+
+    FileDescriptorProto file;
+    file.set_name("foo.proto");
+    parser_->Parse(input_.get(), &file);
+    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+    ASSERT_EQ("", error_collector_.text_);
+
+    MockValidationErrorCollector validation_error_collector(
+      source_locations, &error_collector_);
+    EXPECT_TRUE(pool_.BuildFileCollectingErrors(
+      file, &validation_error_collector) == NULL);
+    EXPECT_EQ(expected_errors, error_collector_.text_);
+  }
+
+  MockErrorCollector error_collector_;
+  DescriptorPool pool_;
+
+  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> raw_input_;
+  google::protobuf::scoped_ptr<io::Tokenizer> input_;
+  google::protobuf::scoped_ptr<Parser> parser_;
+  bool require_syntax_identifier_;
+};
+
+// ===================================================================
+
+TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
+  SetupParser(
+    "// blah\n"
+    "syntax = \"foobar\";\n"
+    "this line will not be parsed\n");
+  parser_->SetStopAfterSyntaxIdentifier(true);
+  EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+  EXPECT_EQ("", error_collector_.text_);
+  EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
+  SetupParser(
+    "// blah\n"
+    "this line will not be parsed\n");
+  parser_->SetStopAfterSyntaxIdentifier(true);
+  EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+  EXPECT_EQ("", error_collector_.text_);
+  EXPECT_EQ("", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
+  SetupParser(
+    "// blah\n"
+    "syntax = error;\n");
+  parser_->SetStopAfterSyntaxIdentifier(true);
+  EXPECT_FALSE(parser_->Parse(input_.get(), NULL));
+  EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
+}
+
+TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) {
+  SetupParser("message A {}");
+  FileDescriptorProto file;
+  CaptureTestStderr();
+  EXPECT_TRUE(parser_->Parse(input_.get(), &file));
+  EXPECT_TRUE(
+      GetCapturedTestStderr().find("No syntax specified") != string::npos);
+}
+
+// ===================================================================
+
+typedef ParserTest ParseMessageTest;
+
+TEST_F(ParseMessageTest, IgnoreBOM) {
+  char input[] = "   message TestMessage {\n"
+      "  required int32 foo = 1;\n"
+      "}\n";
+  // Set UTF-8 BOM.
+  input[0] = (char)0xEF;
+  input[1] = (char)0xBB;
+  input[2] = (char)0xBF;
+  ExpectParsesTo(input,
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, BOMError) {
+  char input[] = "   message TestMessage {\n"
+      "  required int32 foo = 1;\n"
+      "}\n";
+  input[0] = (char)0xEF;
+  ExpectHasErrors(input,
+                  "0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
+                  "Only UTF-8 is accepted for proto file.\n"
+                  "0:0: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(ParseMessageTest, SimpleMessage) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32 foo = 1;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
+  require_syntax_identifier_ = false;
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32 foo = 1;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "}");
+  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
+  ExpectParsesTo(
+    "syntax = \"proto2\";\n"
+    "message TestMessage {\n"
+    "  required int32 foo = 1;\n"
+    "}\n",
+
+    "syntax: 'proto2' "
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "}");
+  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
+  require_syntax_identifier_ = true;
+  ExpectParsesTo(
+    "syntax = \"proto2\";\n"
+    "message TestMessage {\n"
+    "  required int32 foo = 1;\n"
+    "}\n",
+
+    "syntax: 'proto2' "
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "}");
+  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, SimpleFields) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32 foo = 15;\n"
+    "  optional int32 bar = 34;\n"
+    "  repeated int32 baz = 3;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }"
+    "  field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }"
+    "  field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3  }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, PrimitiveFieldTypes) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32    foo = 1;\n"
+    "  required int64    foo = 1;\n"
+    "  required uint32   foo = 1;\n"
+    "  required uint64   foo = 1;\n"
+    "  required sint32   foo = 1;\n"
+    "  required sint64   foo = 1;\n"
+    "  required fixed32  foo = 1;\n"
+    "  required fixed64  foo = 1;\n"
+    "  required sfixed32 foo = 1;\n"
+    "  required sfixed64 foo = 1;\n"
+    "  required float    foo = 1;\n"
+    "  required double   foo = 1;\n"
+    "  required string   foo = 1;\n"
+    "  required bytes    foo = 1;\n"
+    "  required bool     foo = 1;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32    number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64    number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32  number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64  number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT    number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING   number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES    number:1 }"
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL     number:1 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, FieldDefaults) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32  foo = 1 [default=  1  ];\n"
+    "  required int32  foo = 1 [default= -2  ];\n"
+    "  required int64  foo = 1 [default=  3  ];\n"
+    "  required int64  foo = 1 [default= -4  ];\n"
+    "  required uint32 foo = 1 [default=  5  ];\n"
+    "  required uint64 foo = 1 [default=  6  ];\n"
+    "  required float  foo = 1 [default=  7.5];\n"
+    "  required float  foo = 1 [default= -8.5];\n"
+    "  required float  foo = 1 [default=  9  ];\n"
+    "  required double foo = 1 [default= 10.5];\n"
+    "  required double foo = 1 [default=-11.5];\n"
+    "  required double foo = 1 [default= 12  ];\n"
+    "  required double foo = 1 [default= inf ];\n"
+    "  required double foo = 1 [default=-inf ];\n"
+    "  required double foo = 1 [default= nan ];\n"
+    "  required string foo = 1 [default='13\\001'];\n"
+    "  required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
+    "  required bytes  foo = 1 [default='14\\002'];\n"
+    "  required bytes  foo = 1 [default='a' \"b\" \n 'c'];\n"
+    "  required bool   foo = 1 [default=true ];\n"
+    "  required Foo    foo = 1 [default=FOO  ];\n"
+
+    "  required int32  foo = 1 [default= 0x7FFFFFFF];\n"
+    "  required int32  foo = 1 [default=-0x80000000];\n"
+    "  required uint32 foo = 1 [default= 0xFFFFFFFF];\n"
+    "  required int64  foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n"
+    "  required int64  foo = 1 [default=-0x8000000000000000];\n"
+    "  required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n"
+    "  required double foo = 1 [default= 0xabcd];\n"
+    "}\n",
+
+#define ETC "name:\"foo\" label:LABEL_REQUIRED number:1"
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { type:TYPE_INT32   default_value:\"1\"         " ETC " }"
+    "  field { type:TYPE_INT32   default_value:\"-2\"        " ETC " }"
+    "  field { type:TYPE_INT64   default_value:\"3\"         " ETC " }"
+    "  field { type:TYPE_INT64   default_value:\"-4\"        " ETC " }"
+    "  field { type:TYPE_UINT32  default_value:\"5\"         " ETC " }"
+    "  field { type:TYPE_UINT64  default_value:\"6\"         " ETC " }"
+    "  field { type:TYPE_FLOAT   default_value:\"7.5\"       " ETC " }"
+    "  field { type:TYPE_FLOAT   default_value:\"-8.5\"      " ETC " }"
+    "  field { type:TYPE_FLOAT   default_value:\"9\"         " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"10.5\"      " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"-11.5\"     " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"12\"        " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"inf\"       " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"-inf\"      " ETC " }"
+    "  field { type:TYPE_DOUBLE  default_value:\"nan\"       " ETC " }"
+    "  field { type:TYPE_STRING  default_value:\"13\\001\"   " ETC " }"
+    "  field { type:TYPE_STRING  default_value:\"abc\"       " ETC " }"
+    "  field { type:TYPE_BYTES   default_value:\"14\\\\002\" " ETC " }"
+    "  field { type:TYPE_BYTES   default_value:\"abc\"       " ETC " }"
+    "  field { type:TYPE_BOOL    default_value:\"true\"      " ETC " }"
+    "  field { type_name:\"Foo\" default_value:\"FOO\"       " ETC " }"
+
+    "  field {"
+    "    type:TYPE_INT32   default_value:\"2147483647\"           " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT32   default_value:\"-2147483648\"          " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_UINT32  default_value:\"4294967295\"           " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT64   default_value:\"9223372036854775807\"  " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_INT64   default_value:\"-9223372036854775808\" " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_UINT64  default_value:\"18446744073709551615\" " ETC
+    "  }"
+    "  field {"
+    "    type:TYPE_DOUBLE  default_value:\"43981\"                " ETC
+    "  }"
+    "}");
+#undef ETC
+}
+
+TEST_F(ParseMessageTest, FieldJsonName) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  optional string foo = 1 [json_name = \"@type\"];\n"
+    "}\n",
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field {\n"
+    "    name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
+    "    json_name: \"@type\"\n"
+    "  }\n"
+    "}\n");
+}
+
+TEST_F(ParseMessageTest, FieldOptions) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  optional string foo = 1\n"
+    "      [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n"
+    "       (quux)=\"x\040y\", (baz.qux)=hey];\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
+    "          options { uninterpreted_option: { name { name_part: \"ctype\" "
+    "                                                   is_extension: false } "
+    "                                            identifier_value: \"CORD\"  }"
+    "                    uninterpreted_option: { name { name_part: \"foo\" "
+    "                                                   is_extension: true } "
+    "                                            positive_int_value: 7  }"
+    "                    uninterpreted_option: { name { name_part: \"foo\" "
+    "                                                   is_extension: false } "
+    "                                            name { name_part: \".bar.baz\""
+    "                                                   is_extension: true } "
+    "                                            name { name_part: \"qux\" "
+    "                                                   is_extension: false } "
+    "                                            name { name_part: \"quux\" "
+    "                                                   is_extension: false } "
+    "                                            name { name_part: \"corge\" "
+    "                                                   is_extension: true } "
+    "                                            negative_int_value: -33 }"
+    "                    uninterpreted_option: { name { name_part: \"quux\" "
+    "                                                   is_extension: true } "
+    "                                            string_value: \"x y\" }"
+    "                    uninterpreted_option: { name { name_part: \"baz.qux\" "
+    "                                                   is_extension: true } "
+    "                                            identifier_value: \"hey\" }"
+    "          }"
+    "  }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, Oneof) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  oneof foo {\n"
+    "    int32 a = 1;\n"
+    "    string b = 2;\n"
+    "    TestMessage c = 3;\n"
+    "    group D = 4 { optional int32 i = 5; }\n"
+    "  }\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+    "          oneof_index:0 }"
+    "  field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
+    "          oneof_index:0 }"
+    "  field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" "
+    "          number:3 oneof_index:0 }"
+    "  field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP "
+    "          type_name:\"D\" number:4 oneof_index:0 }"
+    "  oneof_decl {"
+    "    name: \"foo\""
+    "  }"
+    "  nested_type {"
+    "    name: \"D\""
+    "    field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }"
+    "  }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, MultipleOneofs) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  oneof foo {\n"
+    "    int32 a = 1;\n"
+    "    string b = 2;\n"
+    "  }\n"
+    "  oneof bar {\n"
+    "    int32 c = 3;\n"
+    "    string d = 4;\n"
+    "  }\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+    "          oneof_index:0 }"
+    "  field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
+    "          oneof_index:0 }"
+    "  field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 "
+    "          oneof_index:1 }"
+    "  field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 "
+    "          oneof_index:1 }"
+    "  oneof_decl {"
+    "    name: \"foo\""
+    "  }"
+    "  oneof_decl {"
+    "    name: \"bar\""
+    "  }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, Maps) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  map<int32, string> primitive_type_map = 1;\n"
+    "  map<KeyType, ValueType> composite_type_map = 2;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  nested_type {"
+    "    name: \"PrimitiveTypeMapEntry\""
+    "    field { "
+    "       name: \"key\" number: 1 label:LABEL_OPTIONAL"
+    "       type:TYPE_INT32"
+    "    }"
+    "    field { "
+    "       name: \"value\" number: 2 label:LABEL_OPTIONAL"
+    "       type:TYPE_STRING"
+    "    }"
+    "    options { map_entry: true }"
+    "  }"
+    "  nested_type {"
+    "    name: \"CompositeTypeMapEntry\""
+    "    field { "
+    "       name: \"key\" number: 1 label:LABEL_OPTIONAL"
+    "       type_name: \"KeyType\""
+    "    }"
+    "    field { "
+    "       name: \"value\" number: 2 label:LABEL_OPTIONAL"
+    "       type_name: \"ValueType\""
+    "    }"
+    "    options { map_entry: true }"
+    "  }"
+    "  field {"
+    "    name: \"primitive_type_map\""
+    "    label: LABEL_REPEATED"
+    "    type_name: \"PrimitiveTypeMapEntry\""
+    "    number: 1"
+    "  }"
+    "  field {"
+    "    name: \"composite_type_map\""
+    "    label: LABEL_REPEATED"
+    "    type_name: \"CompositeTypeMapEntry\""
+    "    number: 2"
+    "  }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, Group) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  optional group TestGroup = 1 {};\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  nested_type { name: \"TestGroup\" }"
+    "  field { name:\"testgroup\" label:LABEL_OPTIONAL number:1"
+    "          type:TYPE_GROUP type_name: \"TestGroup\" }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, NestedMessage) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  message Nested {}\n"
+    "  optional Nested test_nested = 1;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  nested_type { name: \"Nested\" }"
+    "  field { name:\"test_nested\" label:LABEL_OPTIONAL number:1"
+    "          type_name: \"Nested\" }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, NestedEnum) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  enum NestedEnum {}\n"
+    "  optional NestedEnum test_enum = 1;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  enum_type { name: \"NestedEnum\" }"
+    "  field { name:\"test_enum\" label:LABEL_OPTIONAL number:1"
+    "          type_name: \"NestedEnum\" }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, ReservedRange) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  required int32 foo = 1;\n"
+    "  reserved 2, 15, 9 to 11, 3;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+    "  reserved_range { start:2   end:3         }"
+    "  reserved_range { start:15  end:16        }"
+    "  reserved_range { start:9   end:12        }"
+    "  reserved_range { start:3   end:4         }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, ReservedNames) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  reserved \"foo\", \"bar\";\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  reserved_name: \"foo\""
+    "  reserved_name: \"bar\""
+    "}");
+}
+
+TEST_F(ParseMessageTest, ExtensionRange) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 10 to 19;\n"
+    "  extensions 30 to max;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range { start:10 end:20        }"
+    "  extension_range { start:30 end:536870912 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, CompoundExtensionRange) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 2, 15, 9 to 11, 100 to max, 3;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range { start:2   end:3         }"
+    "  extension_range { start:15  end:16        }"
+    "  extension_range { start:9   end:12        }"
+    "  extension_range { start:100 end:536870912 }"
+    "  extension_range { start:3   end:4         }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
+  // Messages using the message_set_wire_format option can accept larger
+  // extension numbers, as the numbers are not encoded as int32 field values
+  // rather than tags.
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 4 to max;\n"
+    "  option message_set_wire_format = true;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "    extension_range { start:4 end: 0x7fffffff }"
+    "  options {\n"
+    "    uninterpreted_option { \n"
+    "      name {\n"
+    "        name_part: \"message_set_wire_format\"\n"
+    "        is_extension: false\n"
+    "      }\n"
+    "      identifier_value: \"true\"\n"
+    "    }\n"
+    "  }\n"
+    "}");
+}
+
+TEST_F(ParseMessageTest, Extensions) {
+  ExpectParsesTo(
+    "extend Extendee1 { optional int32 foo = 12; }\n"
+    "extend Extendee2 { repeated TestMessage bar = 22; }\n",
+
+    "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
+    "            extendee: \"Extendee1\" } "
+    "extension { name:\"bar\" label:LABEL_REPEATED number:22"
+    "            type_name:\"TestMessage\" extendee: \"Extendee2\" }");
+}
+
+TEST_F(ParseMessageTest, ExtensionsInMessageScope) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extend Extendee1 { optional int32 foo = 12; }\n"
+    "  extend Extendee2 { repeated TestMessage bar = 22; }\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
+    "              extendee: \"Extendee1\" }"
+    "  extension { name:\"bar\" label:LABEL_REPEATED number:22"
+    "              type_name:\"TestMessage\" extendee: \"Extendee2\" }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
+  ExpectParsesTo(
+    "extend Extendee1 {\n"
+    "  optional int32 foo = 12;\n"
+    "  repeated TestMessage bar = 22;\n"
+    "}\n",
+
+    "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
+    "            extendee: \"Extendee1\" } "
+    "extension { name:\"bar\" label:LABEL_REPEATED number:22"
+    "            type_name:\"TestMessage\" extendee: \"Extendee1\" }");
+}
+
+TEST_F(ParseMessageTest, OptionalLabelProto3) {
+  ExpectParsesTo(
+    "syntax = \"proto3\";\n"
+    "message TestMessage {\n"
+    "  int32 foo = 1;\n"
+    "}\n",
+
+    "syntax: \"proto3\" "
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }");
+}
+
+// ===================================================================
+
+typedef ParserTest ParseEnumTest;
+
+TEST_F(ParseEnumTest, SimpleEnum) {
+  ExpectParsesTo(
+    "enum TestEnum {\n"
+    "  FOO = 0;\n"
+    "}\n",
+
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"FOO\" number:0 }"
+    "}");
+}
+
+TEST_F(ParseEnumTest, Values) {
+  ExpectParsesTo(
+    "enum TestEnum {\n"
+    "  FOO = 13;\n"
+    "  BAR = -10;\n"
+    "  BAZ = 500;\n"
+    "  HEX_MAX = 0x7FFFFFFF;\n"
+    "  HEX_MIN = -0x80000000;\n"
+    "  INT_MAX = 2147483647;\n"
+    "  INT_MIN = -2147483648;\n"
+    "}\n",
+
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"FOO\" number:13 }"
+    "  value { name:\"BAR\" number:-10 }"
+    "  value { name:\"BAZ\" number:500 }"
+    "  value { name:\"HEX_MAX\" number:2147483647 }"
+    "  value { name:\"HEX_MIN\" number:-2147483648 }"
+    "  value { name:\"INT_MAX\" number:2147483647 }"
+    "  value { name:\"INT_MIN\" number:-2147483648 }"
+    "}");
+}
+
+TEST_F(ParseEnumTest, ValueOptions) {
+  ExpectParsesTo(
+    "enum TestEnum {\n"
+    "  FOO = 13;\n"
+    "  BAR = -10 [ (something.text) = 'abc' ];\n"
+    "  BAZ = 500 [ (something.text) = 'def', other = 1 ];\n"
+    "}\n",
+
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name: \"FOO\" number: 13 }"
+    "  value { name: \"BAR\" number: -10 "
+    "    options { "
+    "      uninterpreted_option { "
+    "        name { name_part: \"something.text\" is_extension: true } "
+    "        string_value: \"abc\" "
+    "      } "
+    "    } "
+    "  } "
+    "  value { name: \"BAZ\" number: 500 "
+    "    options { "
+    "      uninterpreted_option { "
+    "        name { name_part: \"something.text\" is_extension: true } "
+    "        string_value: \"def\" "
+    "      } "
+    "      uninterpreted_option { "
+    "        name { name_part: \"other\" is_extension: false } "
+    "        positive_int_value: 1 "
+    "      } "
+    "    } "
+    "  } "
+    "}");
+}
+
+// ===================================================================
+
+typedef ParserTest ParseServiceTest;
+
+TEST_F(ParseServiceTest, SimpleService) {
+  ExpectParsesTo(
+    "service TestService {\n"
+    "  rpc Foo(In) returns (Out);\n"
+    "}\n",
+
+    "service {"
+    "  name: \"TestService\""
+    "  method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }"
+    "}");
+}
+
+TEST_F(ParseServiceTest, MethodsAndStreams) {
+  ExpectParsesTo(
+    "service TestService {\n"
+    "  rpc Foo(In1) returns (Out1);\n"
+    "  rpc Bar(In2) returns (Out2);\n"
+    "  rpc Baz(In3) returns (Out3);\n"
+    "}\n",
+
+    "service {"
+    "  name: \"TestService\""
+    "  method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }"
+    "  method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }"
+    "  method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }"
+    "}");
+}
+
+
+
+// ===================================================================
+// imports and packages
+
+typedef ParserTest ParseMiscTest;
+
+TEST_F(ParseMiscTest, ParseImport) {
+  ExpectParsesTo(
+    "import \"foo/bar/baz.proto\";\n",
+    "dependency: \"foo/bar/baz.proto\"");
+}
+
+TEST_F(ParseMiscTest, ParseMultipleImports) {
+  ExpectParsesTo(
+    "import \"foo.proto\";\n"
+    "import \"bar.proto\";\n"
+    "import \"baz.proto\";\n",
+    "dependency: \"foo.proto\""
+    "dependency: \"bar.proto\""
+    "dependency: \"baz.proto\"");
+}
+
+TEST_F(ParseMiscTest, ParsePublicImports) {
+  ExpectParsesTo(
+    "import \"foo.proto\";\n"
+    "import public \"bar.proto\";\n"
+    "import \"baz.proto\";\n"
+    "import public \"qux.proto\";\n",
+    "dependency: \"foo.proto\""
+    "dependency: \"bar.proto\""
+    "dependency: \"baz.proto\""
+    "dependency: \"qux.proto\""
+    "public_dependency: 1 "
+    "public_dependency: 3 ");
+}
+
+TEST_F(ParseMiscTest, ParsePackage) {
+  ExpectParsesTo(
+    "package foo.bar.baz;\n",
+    "package: \"foo.bar.baz\"");
+}
+
+TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
+  ExpectParsesTo(
+    "package foo   .   bar.  \n"
+    "  baz;\n",
+    "package: \"foo.bar.baz\"");
+}
+
+// ===================================================================
+// options
+
+TEST_F(ParseMiscTest, ParseFileOptions) {
+  ExpectParsesTo(
+    "option java_package = \"com.google.foo\";\n"
+    "option optimize_for = CODE_SIZE;",
+
+    "options {"
+    "uninterpreted_option { name { name_part: \"java_package\" "
+    "                              is_extension: false }"
+    "                       string_value: \"com.google.foo\"} "
+    "uninterpreted_option { name { name_part: \"optimize_for\" "
+    "                              is_extension: false }"
+    "                       identifier_value: \"CODE_SIZE\" } "
+    "}");
+}
+
+// ===================================================================
+// Error tests
+//
+// There are a very large number of possible errors that the parser could
+// report, so it's infeasible to test every single one of them.  Instead,
+// we test each unique call to AddError() in parser.h.  This does not mean
+// we are testing every possible error that Parser can generate because
+// each variant of the Consume() helper only counts as one unique call to
+// AddError().
+
+typedef ParserTest ParseErrorTest;
+
+TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
+  require_syntax_identifier_ = true;
+  ExpectHasEarlyExitErrors("message TestMessage {}",
+                           "0:0: File must begin with a syntax statement, e.g. "
+                           "'syntax = \"proto2\";'.\n");
+  EXPECT_EQ("", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
+  ExpectHasEarlyExitErrors(
+    "syntax = \"no_such_syntax\";",
+    "0:9: Unrecognized syntax identifier \"no_such_syntax\".  This parser "
+      "only recognizes \"proto2\" and \"proto3\".\n");
+  EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, SimpleSyntaxError) {
+  ExpectHasErrors(
+    "message TestMessage @#$ { blah }",
+    "0:20: Expected \"{\".\n");
+  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, ExpectedTopLevel) {
+  ExpectHasErrors(
+    "blah;",
+    "0:0: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(ParseErrorTest, UnmatchedCloseBrace) {
+  // This used to cause an infinite loop.  Doh.
+  ExpectHasErrors(
+    "}",
+    "0:0: Expected top-level statement (e.g. \"message\").\n"
+    "0:0: Unmatched \"}\".\n");
+}
+
+// -------------------------------------------------------------------
+// Message errors
+
+TEST_F(ParseErrorTest, MessageMissingName) {
+  ExpectHasErrors(
+    "message {}",
+    "0:8: Expected message name.\n");
+}
+
+TEST_F(ParseErrorTest, MessageMissingBody) {
+  ExpectHasErrors(
+    "message TestMessage;",
+    "0:19: Expected \"{\".\n");
+}
+
+TEST_F(ParseErrorTest, EofInMessage) {
+  ExpectHasErrors(
+    "message TestMessage {",
+    "0:21: Reached end of input in message definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, MissingFieldNumber) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional int32 foo;\n"
+    "}\n",
+    "1:20: Missing field number.\n");
+}
+
+TEST_F(ParseErrorTest, ExpectedFieldNumber) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional int32 foo = ;\n"
+    "}\n",
+    "1:23: Expected field number.\n");
+}
+
+TEST_F(ParseErrorTest, FieldNumberOutOfRange) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional int32 foo = 0x100000000;\n"
+    "}\n",
+    "1:23: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, MissingLabel) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  int32 foo = 1;\n"
+    "}\n",
+    "1:2: Expected \"required\", \"optional\", or \"repeated\".\n");
+}
+
+TEST_F(ParseErrorTest, ExpectedOptionName) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [];\n"
+    "}\n",
+    "1:27: Expected identifier.\n");
+}
+
+TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [.foo=1];\n"
+    "}\n",
+    "1:27: Expected identifier.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [default=true];\n"
+    "}\n",
+    "1:35: Expected integer for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional bool foo = 1 [default=blah];\n"
+    "}\n",
+    "1:33: Expected \"true\" or \"false\".\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueNotString) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional string foo = 1 [default=1];\n"
+    "}\n",
+    "1:35: Expected string for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [default=-1];\n"
+    "}\n",
+    "1:36: Unsigned field can't have negative default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueTooLarge) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional int32  foo = 1 [default= 0x80000000];\n"
+    "  optional int32  foo = 1 [default=-0x80000001];\n"
+    "  optional uint32 foo = 1 [default= 0x100000000];\n"
+    "  optional int64  foo = 1 [default= 0x80000000000000000];\n"
+    "  optional int64  foo = 1 [default=-0x80000000000000001];\n"
+    "  optional uint64 foo = 1 [default= 0x100000000000000000];\n"
+    "}\n",
+    "1:36: Integer out of range.\n"
+    "2:36: Integer out of range.\n"
+    "3:36: Integer out of range.\n"
+    "4:36: Integer out of range.\n"
+    "5:36: Integer out of range.\n"
+    "6:36: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, JsonNameNotString) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional string foo = 1 [json_name=1];\n"
+    "}\n",
+    "1:37: Expected string for JSON name.\n");
+}
+
+TEST_F(ParseErrorTest, DuplicateJsonName) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
+    "}\n",
+    "1:41: Already set option \"json_name\".\n");
+}
+
+TEST_F(ParseErrorTest, EnumValueOutOfRange) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  HEX_TOO_BIG   =  0x80000000;\n"
+    "  HEX_TOO_SMALL = -0x80000001;\n"
+    "  INT_TOO_BIG   =  2147483648;\n"
+    "  INT_TOO_SMALL = -2147483649;\n"
+    "}\n",
+    "1:19: Integer out of range.\n"
+    "2:19: Integer out of range.\n"
+    "3:19: Integer out of range.\n"
+    "4:19: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumAllowAliasFalse) {
+  ExpectHasErrors(
+    "enum Foo {\n"
+    "  option allow_alias = false;\n"
+    "  BAR = 1;\n"
+    "  BAZ = 2;\n"
+    "}\n",
+    "5:0: \"Foo\" declares 'option allow_alias = false;' which has no effect. "
+    "Please remove the declaration.\n");
+}
+
+TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) {
+  ExpectHasErrors(
+    "enum Foo {\n"
+    "  option allow_alias = true;\n"
+    "  BAR = 1;\n"
+    "  BAZ = 2;\n"
+    "}\n",
+    "5:0: \"Foo\" declares support for enum aliases but no enum values share "
+    "field numbers. Please remove the unnecessary 'option allow_alias = true;' "
+    "declaration.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueMissing) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [default=];\n"
+    "}\n",
+    "1:35: Expected integer for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueForGroup) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional group Foo = 1 [default=blah] {}\n"
+    "}\n",
+    "1:34: Messages can't have default values.\n");
+}
+
+TEST_F(ParseErrorTest, DuplicateDefaultValue) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional uint32 foo = 1 [default=1,default=2];\n"
+    "}\n",
+    "1:37: Already set option \"default\".\n");
+}
+
+TEST_F(ParseErrorTest, MissingOneofName) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  oneof {\n"
+    "    int32 bar = 1;\n"
+    "  }\n"
+    "}\n",
+    "1:8: Expected oneof name.\n");
+}
+
+TEST_F(ParseErrorTest, LabelInOneof) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  oneof foo {\n"
+    "    optional int32 bar = 1;\n"
+    "  }\n"
+    "}\n",
+    "2:4: Fields in oneofs must not have labels (required / optional "
+      "/ repeated).\n");
+}
+
+TEST_F(ParseErrorTest, MapInOneof) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  oneof foo {\n"
+    "    map<int32, int32> foo_map = 1;\n"
+    "    map message_field = 2;\n"  // a normal message field is OK
+    "  }\n"
+    "}\n",
+    "2:7: Map fields are not allowed in oneofs.\n");
+}
+
+TEST_F(ParseErrorTest, LabelForMap) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional map<int32, int32> int_map = 1;\n"
+    "  required map<int32, int32> int_map2 = 2;\n"
+    "  repeated map<int32, int32> int_map3 = 3;\n"
+    "  optional map map_message = 4;\n"  // a normal message field is OK
+    "}\n",
+    "1:14: Field labels (required/optional/repeated) are not allowed on map "
+    "fields.\n"
+    "2:14: Field labels (required/optional/repeated) are not allowed on map "
+    "fields.\n"
+    "3:14: Field labels (required/optional/repeated) are not allowed on map "
+    "fields.\n");
+}
+
+TEST_F(ParseErrorTest, MalformedMaps) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  map map_message = 1;\n"   // a normal message field lacking label
+    "  map<string> str_map = 2;\n"
+    "  map<string,> str_map2 = 3;\n"
+    "  map<,string> str_map3 = 4;\n"
+    "  map<> empty_map = 5;\n"
+    "  map<string,string str_map6 = 6;\n"
+    "}"
+    "extend SomeMessage {\n"
+    "  map<int32, int32> int_map = 1;\n"
+    "}",
+    "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
+    "2:12: Expected \",\".\n"
+    "3:13: Expected type name.\n"
+    "4:6: Expected type name.\n"
+    "5:6: Expected type name.\n"
+    "6:20: Expected \">\".\n"
+    "8:5: Map fields are not allowed to be extensions.\n");
+}
+
+TEST_F(ParseErrorTest, GroupNotCapitalized) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional group foo = 1 {}\n"
+    "}\n",
+    "1:17: Group names must start with a capital letter.\n");
+}
+
+TEST_F(ParseErrorTest, GroupMissingBody) {
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional group Foo = 1;\n"
+    "}\n",
+    "1:24: Missing group body.\n");
+}
+
+TEST_F(ParseErrorTest, ExtendingPrimitive) {
+  ExpectHasErrors(
+    "extend int32 { optional string foo = 4; }\n",
+    "0:7: Expected message type.\n");
+}
+
+TEST_F(ParseErrorTest, ErrorInExtension) {
+  ExpectHasErrors(
+    "message Foo { extensions 100 to 199; }\n"
+    "extend Foo { optional string foo; }\n",
+    "1:32: Missing field number.\n");
+}
+
+TEST_F(ParseErrorTest, MultipleParseErrors) {
+  // When a statement has a parse error, the parser should be able to continue
+  // parsing at the next statement.
+  ExpectHasErrors(
+    "message TestMessage {\n"
+    "  optional int32 foo;\n"
+    "  !invalid statement ending in a block { blah blah { blah } blah }\n"
+    "  optional int32 bar = 3 {}\n"
+    "}\n",
+    "1:20: Missing field number.\n"
+    "2:2: Expected \"required\", \"optional\", or \"repeated\".\n"
+    "2:2: Expected type name.\n"
+    "3:25: Expected \";\".\n");
+}
+
+TEST_F(ParseErrorTest, EofInAggregateValue) {
+  ExpectHasErrors(
+      "option (fileopt) = { i:100\n",
+      "1:0: Unexpected end of stream while parsing aggregate value.\n");
+}
+
+TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) {
+  ExpectHasErrors(
+      "syntax = 'proto3';\n"
+      "message TestMessage {\n"
+      "  optional int32 foo = 1;\n"
+      "}\n",
+      "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+      "To define 'optional' fields in Proto3, simply remove the 'optional' "
+      "label, as fields are 'optional' by default.\n");
+}
+
+
+// -------------------------------------------------------------------
+// Enum errors
+
+TEST_F(ParseErrorTest, EofInEnum) {
+  ExpectHasErrors(
+    "enum TestEnum {",
+    "0:15: Reached end of input in enum definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, EnumValueMissingNumber) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  FOO;\n"
+    "}\n",
+    "1:5: Missing numeric value for enum constant.\n");
+}
+
+// -------------------------------------------------------------------
+// Reserved field number errors
+
+TEST_F(ParseErrorTest, ReservedMaxNotAllowed) {
+  ExpectHasErrors(
+    "message Foo {\n"
+    "  reserved 10 to max;\n"
+    "}\n",
+    "1:17: Expected integer.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
+  ExpectHasErrors(
+    "message Foo {\n"
+    "  reserved 10, \"foo\";\n"
+    "}\n",
+    "1:15: Expected field number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMissingQuotes) {
+  ExpectHasErrors(
+    "message Foo {\n"
+    "  reserved foo;\n"
+    "}\n",
+    "1:11: Expected field name or number range.\n");
+}
+
+// -------------------------------------------------------------------
+// Service errors
+
+TEST_F(ParseErrorTest, EofInService) {
+  ExpectHasErrors(
+    "service TestService {",
+    "0:21: Reached end of input in service definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
+  ExpectHasErrors(
+    "service TestService {\n"
+    "  rpc Foo(int32) returns (string);\n"
+    "}\n",
+    "1:10: Expected message type.\n"
+    "1:26: Expected message type.\n");
+}
+
+
+TEST_F(ParseErrorTest, EofInMethodOptions) {
+  ExpectHasErrors(
+    "service TestService {\n"
+    "  rpc Foo(Bar) returns(Bar) {",
+    "1:29: Reached end of input in method options (missing '}').\n"
+    "1:29: Reached end of input in service definition (missing '}').\n");
+}
+
+
+TEST_F(ParseErrorTest, PrimitiveMethodInput) {
+  ExpectHasErrors(
+    "service TestService {\n"
+    "  rpc Foo(int32) returns(Bar);\n"
+    "}\n",
+    "1:10: Expected message type.\n");
+}
+
+
+TEST_F(ParseErrorTest, MethodOptionTypeError) {
+  // This used to cause an infinite loop.
+  ExpectHasErrors(
+    "message Baz {}\n"
+    "service Foo {\n"
+    "  rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n"
+    "}\n",
+    "2:45: Expected \"=\".\n");
+}
+
+
+// -------------------------------------------------------------------
+// Import and package errors
+
+TEST_F(ParseErrorTest, ImportNotQuoted) {
+  ExpectHasErrors(
+    "import foo;\n",
+    "0:7: Expected a string naming the file to import.\n");
+}
+
+TEST_F(ParseErrorTest, MultiplePackagesInFile) {
+  ExpectHasErrors(
+    "package foo;\n"
+    "package bar;\n",
+    "1:0: Multiple package definitions.\n");
+}
+
+// ===================================================================
+// Test that errors detected by DescriptorPool correctly report line and
+// column numbers.  We have one test for every call to RecordLocation() in
+// parser.cc.
+
+typedef ParserTest ParserValidationErrorTest;
+
+TEST_F(ParserValidationErrorTest, PackageNameError) {
+  // Create another file which defines symbol "foo".
+  FileDescriptorProto other_file;
+  other_file.set_name("bar.proto");
+  other_file.add_message_type()->set_name("foo");
+  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+  // Now try to define it as a package.
+  ExpectHasValidationErrors(
+    "package foo.bar;",
+    "0:8: \"foo\" is already defined (as something other than a package) "
+      "in file \"bar.proto\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, MessageNameError) {
+  ExpectHasValidationErrors(
+    "message Foo {}\n"
+    "message Foo {}\n",
+    "1:8: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldNameError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  optional int32 bar = 1;\n"
+    "  optional int32 bar = 2;\n"
+    "}\n",
+    "2:17: \"bar\" is already defined in \"Foo\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldTypeError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  optional Baz bar = 1;\n"
+    "}\n",
+    "1:11: \"Baz\" is not defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldNumberError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  optional int32 bar = 0;\n"
+    "}\n",
+    "1:23: Field numbers must be positive integers.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
+  ExpectHasValidationErrors(
+    "extend Baz { optional int32 bar = 1; }\n",
+    "0:7: \"Baz\" is not defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldDefaultValueError) {
+  ExpectHasValidationErrors(
+    "enum Baz { QUX = 1; }\n"
+    "message Foo {\n"
+    "  optional Baz bar = 1 [default=NO_SUCH_VALUE];\n"
+    "}\n",
+    "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FileOptionNameError) {
+  ExpectHasValidationErrors(
+    "option foo = 5;",
+    "0:7: Option \"foo\" unknown.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FileOptionValueError) {
+  ExpectHasValidationErrors(
+    "option java_outer_classname = 5;",
+    "0:30: Value must be quoted string for string option "
+    "\"google.protobuf.FileOptions.java_outer_classname\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldOptionNameError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  optional bool bar = 1 [foo=1];\n"
+    "}\n",
+    "1:25: Option \"foo\" unknown.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldOptionValueError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  optional int32 bar = 1 [ctype=1];\n"
+    "}\n",
+    "1:32: Value must be identifier for enum-valued option "
+    "\"google.protobuf.FieldOptions.ctype\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) {
+  ExpectHasValidationErrors(
+    "message Foo {\n"
+    "  extensions 0;\n"
+    "}\n",
+    "1:13: Extension numbers must be positive integers.\n");
+}
+
+TEST_F(ParserValidationErrorTest, EnumNameError) {
+  ExpectHasValidationErrors(
+    "enum Foo {A = 1;}\n"
+    "enum Foo {B = 1;}\n",
+    "1:5: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, EnumValueNameError) {
+  ExpectHasValidationErrors(
+    "enum Foo {\n"
+    "  BAR = 1;\n"
+    "  BAR = 1;\n"
+    "}\n",
+    "2:2: \"BAR\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ServiceNameError) {
+  ExpectHasValidationErrors(
+    "service Foo {}\n"
+    "service Foo {}\n",
+    "1:8: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, MethodNameError) {
+  ExpectHasValidationErrors(
+    "message Baz {}\n"
+    "service Foo {\n"
+    "  rpc Bar(Baz) returns(Baz);\n"
+    "  rpc Bar(Baz) returns(Baz);\n"
+    "}\n",
+    "3:6: \"Bar\" is already defined in \"Foo\".\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
+  ExpectHasValidationErrors(
+    "message Baz {}\n"
+    "service Foo {\n"
+    "  rpc Bar(Qux) returns(Baz);\n"
+    "}\n",
+    "2:10: \"Qux\" is not defined.\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
+  ExpectHasValidationErrors(
+    "message Baz {}\n"
+    "service Foo {\n"
+    "  rpc Bar(Baz) returns(Qux);\n"
+    "}\n",
+    "2:23: \"Qux\" is not defined.\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, ResovledUndefinedError) {
+  // Create another file which defines symbol ".base.bar".
+  FileDescriptorProto other_file;
+  other_file.set_name("base.proto");
+  other_file.set_package("base");
+  other_file.add_message_type()->set_name("bar");
+  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+  // Define "foo.base" and try "base.bar".
+  // "base.bar" is resolved to "foo.base.bar" which is not defined.
+  ExpectHasValidationErrors(
+    "package foo.base;\n"
+    "import \"base.proto\";\n"
+    "message qux {\n"
+    "  optional base.bar baz = 1;\n"
+    "  optional .base.bar quz = 2;\n"
+    "}\n",
+    "3:11: \"base.bar\" is resolved to \"foo.base.bar\","
+    " which is not defined. The innermost scope is searched first "
+    "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")"
+    " to start from the outermost scope.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
+  // Build descriptor message in test pool
+  FileDescriptorProto descriptor_proto;
+  DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto);
+  ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL);
+
+  // base2.proto:
+  //   package baz
+  //   import google/protobuf/descriptor.proto
+  //   message Bar { optional int32 foo = 1; }
+  //   extend FileOptions { optional Bar bar = 7672757; }
+  FileDescriptorProto other_file;
+  other_file.set_name("base2.proto");
+  other_file.set_package("baz");
+  other_file.add_dependency();
+  other_file.set_dependency(0, descriptor_proto.name());
+
+  DescriptorProto* message(other_file.add_message_type());
+  message->set_name("Bar");
+  FieldDescriptorProto* field(message->add_field());
+  field->set_name("foo");
+  field->set_number(1);
+  field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL);
+  field->set_type(FieldDescriptorProto_Type_TYPE_INT32);
+
+  FieldDescriptorProto* extension(other_file.add_extension());
+  extension->set_name("bar");
+  extension->set_number(7672757);
+  extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL);
+  extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE);
+  extension->set_type_name("Bar");
+  extension->set_extendee("google.protobuf.FileOptions");
+
+  EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+  // qux.proto:
+  //   package qux.baz
+  //   option (baz.bar).foo = 1;
+  //
+  // Although "baz.bar" is already defined, the lookup code will try
+  // "qux.baz.bar", since it's the match from the innermost scope,
+  // which will cause a symbol not defined error.
+  ExpectHasValidationErrors(
+      "package qux.baz;\n"
+      "import \"base2.proto\";\n"
+      "option (baz.bar).foo = 1;\n",
+      "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\","
+      " which is not defined. The innermost scope is searched first "
+      "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")"
+      " to start from the outermost scope.\n");
+}
+
+// ===================================================================
+// Test that the output from FileDescriptor::DebugString() (and all other
+// descriptor types) is parseable, and results in the same Descriptor
+// definitions again afoter parsing (note, however, that the order of messages
+// cannot be guaranteed to be the same)
+
+typedef ParserTest ParseDescriptorDebugTest;
+
+class CompareDescriptorNames {
+ public:
+  bool operator()(const DescriptorProto* left,
+                  const DescriptorProto* right) const {
+    return left->name() < right->name();
+  }
+};
+
+// Sorts nested DescriptorProtos of a DescriptoProto, by name.
+void SortMessages(DescriptorProto *descriptor_proto) {
+  int size = descriptor_proto->nested_type_size();
+  // recursively sort; we can't guarantee the order of nested messages either
+  for (int i = 0; i < size; ++i) {
+    SortMessages(descriptor_proto->mutable_nested_type(i));
+  }
+  DescriptorProto **data =
+    descriptor_proto->mutable_nested_type()->mutable_data();
+  std::sort(data, data + size, CompareDescriptorNames());
+}
+
+// Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
+void SortMessages(FileDescriptorProto *file_descriptor_proto) {
+  int size = file_descriptor_proto->message_type_size();
+  // recursively sort; we can't guarantee the order of nested messages either
+  for (int i = 0; i < size; ++i) {
+    SortMessages(file_descriptor_proto->mutable_message_type(i));
+  }
+  DescriptorProto **data =
+    file_descriptor_proto->mutable_message_type()->mutable_data();
+  std::sort(data, data + size, CompareDescriptorNames());
+}
+
+// Strips the message and enum field type names for comparison purpose only.
+void StripFieldTypeName(DescriptorProto* proto) {
+  for (int i = 0; i < proto->field_size(); ++i) {
+    string type_name = proto->field(i).type_name();
+    string::size_type pos = type_name.find_last_of(".");
+    if (pos != string::npos) {
+      proto->mutable_field(i)->mutable_type_name()->assign(
+          type_name.begin() + pos + 1, type_name.end());
+    }
+  }
+  for (int i = 0; i < proto->nested_type_size(); ++i) {
+    StripFieldTypeName(proto->mutable_nested_type(i));
+  }
+}
+
+void StripFieldTypeName(FileDescriptorProto* file_proto) {
+  for (int i = 0; i < file_proto->message_type_size(); ++i) {
+    StripFieldTypeName(file_proto->mutable_message_type(i));
+  }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
+  const FileDescriptor* original_file =
+     protobuf_unittest::TestAllTypes::descriptor()->file();
+  FileDescriptorProto expected;
+  original_file->CopyTo(&expected);
+
+  // Get the DebugString of the unittest.proto FileDecriptor, which includes
+  // all other descriptor types
+  string debug_string = original_file->DebugString();
+
+  // Parse the debug string
+  SetupParser(debug_string.c_str());
+  FileDescriptorProto parsed;
+  parser_->Parse(input_.get(), &parsed);
+  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+  ASSERT_EQ("", error_collector_.text_)
+      << "Failed to parse:\n" << debug_string;
+
+  // We now have a FileDescriptorProto, but to compare with the expected we
+  // need to link to a FileDecriptor, then output back to a proto. We'll
+  // also need to give it the same name as the original.
+  parsed.set_name("google/protobuf/unittest.proto");
+  // We need the imported dependency before we can build our parsed proto
+  const FileDescriptor* public_import =
+      protobuf_unittest_import::PublicImportMessage::descriptor()->file();
+  FileDescriptorProto public_import_proto;
+  public_import->CopyTo(&public_import_proto);
+  ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
+  const FileDescriptor* import =
+       protobuf_unittest_import::ImportMessage::descriptor()->file();
+  FileDescriptorProto import_proto;
+  import->CopyTo(&import_proto);
+  ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+  const FileDescriptor* actual = pool_.BuildFile(parsed);
+  parsed.Clear();
+  ASSERT_TRUE(actual != NULL)
+      << "Failed to validate:\n" << debug_string;
+  actual->CopyTo(&parsed);
+  ASSERT_TRUE(actual != NULL);
+
+  // The messages might be in different orders, making them hard to compare.
+  // So, sort the messages in the descriptor protos (including nested messages,
+  // recursively).
+  SortMessages(&expected);
+  SortMessages(&parsed);
+
+  // I really wanted to use StringDiff here for the debug output on fail,
+  // but the strings are too long for it, and if I increase its max size,
+  // we get a memory allocation failure :(
+  EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
+TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
+  const FileDescriptor* original_file =
+     protobuf_unittest::AggregateMessage::descriptor()->file();
+  FileDescriptorProto expected;
+  original_file->CopyTo(&expected);
+
+  string debug_string = original_file->DebugString();
+
+  // Parse the debug string
+  SetupParser(debug_string.c_str());
+  FileDescriptorProto parsed;
+  parser_->Parse(input_.get(), &parsed);
+  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+  ASSERT_EQ("", error_collector_.text_);
+
+  // We now have a FileDescriptorProto, but to compare with the expected we
+  // need to link to a FileDecriptor, then output back to a proto. We'll
+  // also need to give it the same name as the original.
+  parsed.set_name(original_file->name());
+
+  // unittest_custom_options.proto depends on descriptor.proto.
+  const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
+  FileDescriptorProto import_proto;
+  import->CopyTo(&import_proto);
+  ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+  const FileDescriptor* actual = pool_.BuildFile(parsed);
+  ASSERT_TRUE(actual != NULL);
+  parsed.Clear();
+  actual->CopyTo(&parsed);
+
+  // The messages might be in different orders, making them hard to compare.
+  // So, sort the messages in the descriptor protos (including nested messages,
+  // recursively).
+  SortMessages(&expected);
+  SortMessages(&parsed);
+
+  EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
+// Ensure that DebugStringWithOptions(), with |include_comments| set to true,
+// includes comments from the original parser input in all of the appropriate
+// places.
+TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
+  SetupParser(
+      "// Detached comment before syntax.\n"
+      "\n"
+      "// Syntax comment.\n"
+      "syntax = \"proto2\";\n"
+      "\n"
+      "// Detached comment before package.\n"
+      "\n"
+      "// Package comment.\n"
+      "package comment_test;\n"
+      "\n"
+      "// Detached comment before TestMessage1.\n"
+      "\n"
+      "// Message comment.\n"
+      "//\n"
+      "// More detail in message comment.\n"
+      "message TestMessage1 {\n"
+      "\n"
+      "  // Detached comment before foo.\n"
+      "\n"
+      "  // Field comment.\n"
+      "  optional int32 foo = 1;\n"
+      "\n"
+      "  // Detached comment before NestedMessage.\n"
+      "\n"
+      "  // Nested-message comment.\n"
+      "  message NestedMessage {\n"
+      "    optional int32 bar = 1;\n"
+      "  }\n"
+      "}\n"
+      "\n"
+      "// Detached comment before MyEnumType.\n"
+      "\n"
+      "// Enum comment.\n"
+      "enum MyEnumType {\n"
+      "\n"
+      "  // Detached comment before ASDF.\n"
+      "\n"
+      "  // Enum-value comment.\n"
+      "  ASDF = 1;\n"
+      "}\n"
+      "\n"
+      "// Detached comment before MyService.\n"
+      "\n"
+      "// Service comment.\n"
+      "service MyService {\n"
+      "\n"
+      "  // Detached comment before MyRPCCall.\n"
+      "\n"
+      "  // RPC comment.\n"
+      "  rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
+      "}\n");
+
+  FileDescriptorProto parsed_desc;
+  parsed_desc.set_name("foo.proto");
+  SourceLocationTable source_locations;
+  parser_->RecordSourceLocationsTo(&source_locations);
+  parser_->Parse(input_.get(), &parsed_desc);
+  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+  ASSERT_EQ("", error_collector_.text_);
+
+  // We need to import the FileDescriptorProto to get a FileDescriptor.
+  MockValidationErrorCollector collector(source_locations, &error_collector_);
+  const FileDescriptor* descriptor =
+      pool_.BuildFileCollectingErrors(parsed_desc, &collector);
+  ASSERT_TRUE(descriptor != NULL);
+
+  // Ensure that each of the comments appears somewhere in the DebugString().
+  // We don't test the exact comment placement or formatting, because we do not
+  // want to be too fragile here.
+  const char* expected_comments[] = {
+    "Detached comment before syntax.",
+    "Syntax comment.",
+    "Detached comment before package.",
+    "Package comment.",
+    "Detached comment before TestMessage1.",
+    "Message comment.",
+    "More detail in message comment.",
+    "Detached comment before foo.",
+    "Field comment",
+    "Detached comment before NestedMessage.",
+    "Nested-message comment",
+    "Detached comment before MyEnumType.",
+    "Enum comment",
+    "Detached comment before ASDF.",
+    "Enum-value comment",
+    "Detached comment before MyService.",
+    "Service comment",
+    "Detached comment before MyRPCCall.",
+    "RPC comment",
+  };
+
+  DebugStringOptions debug_string_options;
+  debug_string_options.include_comments = true;
+
+  {
+    const string debug_string =
+        descriptor->DebugStringWithOptions(debug_string_options);
+
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
+      string::size_type found_pos = debug_string.find(expected_comments[i]);
+      EXPECT_TRUE(found_pos != string::npos)
+          << "\"" << expected_comments[i] << "\" not found.";
+    }
+
+    // Result of DebugStringWithOptions should be parseable.
+    SetupParser(debug_string.c_str());
+    FileDescriptorProto parsed;
+    parser_->Parse(input_.get(), &parsed);
+    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+    ASSERT_EQ("", error_collector_.text_)
+        << "Failed to parse:\n" << debug_string;
+  }
+
+}
+
+TEST_F(ParseDescriptorDebugTest, TestMaps) {
+  SetupParser(
+      "syntax = \"proto3\"; "
+      "message Foo { "
+      "  message Bar { } "
+      "  map<int32, Bar> enum_message_map = 1; "
+      "  map<string, float> primitive_map = 2; "
+      "} ");
+  FileDescriptorProto original;
+  EXPECT_TRUE(parser_->Parse(input_.get(), &original));
+  original.set_name("foo.proto");
+  const FileDescriptor* file = pool_.BuildFile(original);
+  ASSERT_TRUE(file != NULL);
+
+  // Make sure the debug string uses map syntax and does not have the auto
+  // generated entry.
+  string debug_string = file->DebugString();
+  EXPECT_TRUE(debug_string.find("map<") != string::npos);
+  EXPECT_TRUE(debug_string.find("option map_entry") == string::npos);
+  EXPECT_TRUE(debug_string.find("MapEntry") == string::npos);
+
+  // Make sure the descriptor debug string is parsable.
+  FileDescriptorProto parsed;
+  SetupParser(debug_string.c_str());
+  parsed.set_name("foo.proto");
+  ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
+
+  original.clear_source_code_info();
+  parsed.clear_source_code_info();
+  StripFieldTypeName(&original);
+  StripFieldTypeName(&parsed);
+  EXPECT_EQ(original.DebugString(), parsed.DebugString());
+}
+
+// ===================================================================
+// SourceCodeInfo tests.
+
+// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
+// message to a particular sub-field.
+// * If the target is itself a message, sets *output_message to point at it,
+//   *output_field to NULL, and *output_index to -1.
+// * Otherwise, if the target is an element of a repeated field, sets
+//   *output_message to the containing message, *output_field to the descriptor
+//   of the field, and *output_index to the index of the element.
+// * Otherwise, the target is a field (possibly a repeated field, but not any
+//   one element).  Sets *output_message to the containing message,
+//   *output_field to the descriptor of the field, and *output_index to -1.
+// Returns true if the path was valid, false otherwise.  A gTest failure is
+// recorded before returning false.
+bool FollowPath(const Message& root,
+                const int* path_begin, const int* path_end,
+                const Message** output_message,
+                const FieldDescriptor** output_field,
+                int* output_index) {
+  if (path_begin == path_end) {
+    // Path refers to this whole message.
+    *output_message = &root;
+    *output_field = NULL;
+    *output_index = -1;
+    return true;
+  }
+
+  const Descriptor* descriptor = root.GetDescriptor();
+  const Reflection* reflection = root.GetReflection();
+
+  const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
+
+  if (field == NULL) {
+    ADD_FAILURE() << descriptor->name() << " has no field number: "
+                  << *path_begin;
+    return false;
+  }
+
+  ++path_begin;
+
+  if (field->is_repeated()) {
+    if (path_begin == path_end) {
+      // Path refers to the whole repeated field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    }
+
+    int index = *path_begin++;
+    int size = reflection->FieldSize(root, field);
+
+    if (index >= size) {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " has size " << size << ", but path contained index: "
+                    << index;
+      return false;
+    }
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Descend into child message.
+      const Message& child = reflection->GetRepeatedMessage(root, field, index);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this element.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = index;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  } else {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      const Message& child = reflection->GetMessage(root, field);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  }
+}
+
+// Check if two spans are equal.
+bool CompareSpans(const RepeatedField<int>& span1,
+                  const RepeatedField<int>& span2) {
+  if (span1.size() != span2.size()) return false;
+  for (int i = 0; i < span1.size(); i++) {
+    if (span1.Get(i) != span2.Get(i)) return false;
+  }
+  return true;
+}
+
+// Test fixture for source info tests, which check that source locations are
+// recorded correctly in FileDescriptorProto.source_code_info.location.
+class SourceInfoTest : public ParserTest {
+ protected:
+  // The parsed file (initialized by Parse()).
+  FileDescriptorProto file_;
+
+  // Parse the given text as a .proto file and populate the spans_ map with
+  // all the source location spans in its SourceCodeInfo table.
+  bool Parse(const char* text) {
+    ExtractMarkers(text);
+    SetupParser(text_without_markers_.c_str());
+    if (!parser_->Parse(input_.get(), &file_)) {
+      return false;
+    }
+
+    const SourceCodeInfo& source_info = file_.source_code_info();
+    for (int i = 0; i < source_info.location_size(); i++) {
+      const SourceCodeInfo::Location& location = source_info.location(i);
+      const Message* descriptor_proto = NULL;
+      const FieldDescriptor* field = NULL;
+      int index = 0;
+      if (!FollowPath(file_, location.path().begin(), location.path().end(),
+                      &descriptor_proto, &field, &index)) {
+        return false;
+      }
+
+      spans_.insert(
+          std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
+    }
+
+    return true;
+  }
+
+  virtual void TearDown() {
+    EXPECT_TRUE(spans_.empty())
+        << "Forgot to call HasSpan() for:\n"
+        << spans_.begin()->second->DebugString();
+  }
+
+  // -----------------------------------------------------------------
+  // HasSpan() checks that the span of source code delimited by the given
+  // tags (comments) correspond via the SourceCodeInfo table to the given
+  // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
+  // it should quickly become obvious.)
+
+  bool HasSpan(char start_marker, char end_marker,
+               const Message& descriptor_proto) {
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL);
+  }
+
+  bool HasSpanWithComment(char start_marker, char end_marker,
+                          const Message& descriptor_proto,
+                          const char* expected_leading_comments,
+                          const char* expected_trailing_comments,
+                          const char* expected_leading_detached_comments) {
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, NULL, -1,
+        expected_leading_comments, expected_trailing_comments,
+        expected_leading_detached_comments);
+  }
+
+  bool HasSpan(char start_marker, char end_marker,
+               const Message& descriptor_proto, const string& field_name) {
+    return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(char start_marker, char end_marker,
+               const Message& descriptor_proto, const string& field_name,
+               int index) {
+    return HasSpan(start_marker, end_marker, descriptor_proto,
+                   field_name, index, NULL, NULL, NULL);
+  }
+
+  bool HasSpan(char start_marker, char end_marker,
+               const Message& descriptor_proto,
+               const string& field_name, int index,
+               const char* expected_leading_comments,
+               const char* expected_trailing_comments,
+               const char* expected_leading_detached_comments) {
+    const FieldDescriptor* field =
+        descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
+    if (field == NULL) {
+      ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
+                    << " has no such field: " << field_name;
+      return false;
+    }
+
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, field, index,
+        expected_leading_comments, expected_trailing_comments,
+        expected_leading_detached_comments);
+  }
+
+  bool HasSpan(const Message& descriptor_proto) {
+    return HasSpanWithComment(
+        '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name) {
+    return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name,
+               int index) {
+    return HasSpan('\0', '\0', descriptor_proto, field_name, index);
+  }
+
+  bool HasSpanWithComment(
+      char start_marker, char end_marker, const Message& descriptor_proto,
+      const FieldDescriptor* field, int index,
+      const char* expected_leading_comments,
+      const char* expected_trailing_comments,
+      const char* expected_leading_detached_comments) {
+    pair<SpanMap::iterator, SpanMap::iterator> range =
+        spans_.equal_range(SpanKey(descriptor_proto, field, index));
+
+    if (start_marker == '\0') {
+      if (range.first == range.second) {
+        return false;
+      } else {
+        spans_.erase(range.first);
+        return true;
+      }
+    } else {
+      pair<int, int> start_pos = FindOrDie(markers_, start_marker);
+      pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+
+      RepeatedField<int> expected_span;
+      expected_span.Add(start_pos.first);
+      expected_span.Add(start_pos.second);
+      if (end_pos.first != start_pos.first) {
+        expected_span.Add(end_pos.first);
+      }
+      expected_span.Add(end_pos.second);
+
+      for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
+        if (CompareSpans(expected_span, iter->second->span())) {
+          if (expected_leading_comments == NULL) {
+            EXPECT_FALSE(iter->second->has_leading_comments());
+          } else {
+            EXPECT_TRUE(iter->second->has_leading_comments());
+            EXPECT_EQ(expected_leading_comments,
+                      iter->second->leading_comments());
+          }
+          if (expected_trailing_comments == NULL) {
+            EXPECT_FALSE(iter->second->has_trailing_comments());
+          } else {
+            EXPECT_TRUE(iter->second->has_trailing_comments());
+            EXPECT_EQ(expected_trailing_comments,
+                      iter->second->trailing_comments());
+          }
+          if (expected_leading_detached_comments == NULL) {
+            EXPECT_EQ(0, iter->second->leading_detached_comments_size());
+          } else {
+            EXPECT_EQ(
+                expected_leading_detached_comments,
+                Join(iter->second->leading_detached_comments(), "\n"));
+          }
+
+          spans_.erase(iter);
+          return true;
+        }
+      }
+
+      return false;
+    }
+  }
+
+ private:
+  struct SpanKey {
+    const Message* descriptor_proto;
+    const FieldDescriptor* field;
+    int index;
+
+    inline SpanKey() {}
+    inline SpanKey(const Message& descriptor_proto_param,
+                   const FieldDescriptor* field_param,
+                   int index_param)
+        : descriptor_proto(&descriptor_proto_param), field(field_param),
+          index(index_param) {}
+
+    inline bool operator<(const SpanKey& other) const {
+      if (descriptor_proto < other.descriptor_proto) return true;
+      if (descriptor_proto > other.descriptor_proto) return false;
+      if (field < other.field) return true;
+      if (field > other.field) return false;
+      return index < other.index;
+    }
+  };
+
+  typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
+  SpanMap spans_;
+  map<char, pair<int, int> > markers_;
+  string text_without_markers_;
+
+  void ExtractMarkers(const char* text) {
+    markers_.clear();
+    text_without_markers_.clear();
+    int line = 0;
+    int column = 0;
+    while (*text != '\0') {
+      if (*text == '$') {
+        ++text;
+        GOOGLE_CHECK_NE('\0', *text);
+        if (*text == '$') {
+          text_without_markers_ += '$';
+          ++column;
+        } else {
+          markers_[*text] = std::make_pair(line, column);
+          ++text;
+          GOOGLE_CHECK_EQ('$', *text);
+        }
+      } else if (*text == '\n') {
+        ++line;
+        column = 0;
+        text_without_markers_ += *text;
+      } else {
+        text_without_markers_ += *text;
+        ++column;
+      }
+      ++text;
+    }
+  }
+};
+
+TEST_F(SourceInfoTest, BasicFileDecls) {
+  EXPECT_TRUE(Parse(
+      "$a$syntax = \"proto2\";$i$\n"
+      "package $b$foo.bar$c$;\n"
+      "import $d$\"baz.proto\"$e$;\n"
+      "import $f$\"qux.proto\"$g$;$h$\n"
+      "\n"
+      "// comment ignored\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'h', file_));
+  EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
+  EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
+  EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
+  EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
+}
+
+TEST_F(SourceInfoTest, Messages) {
+  EXPECT_TRUE(Parse(
+      "$a$message $b$Foo$c$ {}$d$\n"
+      "$e$message $f$Bar$g$ {}$h$\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Fields) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
+      "  $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
+
+  EXPECT_TRUE(HasSpan('a', 'i', field1));
+  EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
+  EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
+  EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
+  EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
+
+  EXPECT_TRUE(HasSpan('j', 'r', field2));
+  EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
+  EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
+  EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
+  EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Extensions) {
+  EXPECT_TRUE(Parse(
+      "$a$extend $b$Foo$c$ {\n"
+      "  $d$optional$e$ int32 bar = 1;$f$\n"
+      "  $g$repeated$h$ X.Y baz = 2;$i$\n"
+      "}$j$\n"
+      "$k$extend $l$Bar$m$ {\n"
+      "  $n$optional int32 qux = 1;$o$\n"
+      "}$p$\n"));
+
+  const FieldDescriptorProto& field1 = file_.extension(0);
+  const FieldDescriptorProto& field2 = file_.extension(1);
+  const FieldDescriptorProto& field3 = file_.extension(2);
+
+  EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
+  EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
+
+  EXPECT_TRUE(HasSpan('d', 'f', field1));
+  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan('g', 'i', field2));
+  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan('n', 'o', field3));
+  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, NestedExtensions) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  $a$extend $b$Foo$c$ {\n"
+      "    $d$optional$e$ int32 bar = 1;$f$\n"
+      "    $g$repeated$h$ X.Y baz = 2;$i$\n"
+      "  }$j$\n"
+      "  $k$extend $l$Bar$m$ {\n"
+      "    $n$optional int32 qux = 1;$o$\n"
+      "  }$p$\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
+  const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
+
+  EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
+  EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
+
+  EXPECT_TRUE(HasSpan('d', 'f', field1));
+  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan('g', 'i', field2));
+  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan('n', 'o', field3));
+  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, ExtensionRanges) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+      "  $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
+      "}\n"));
+
+  const DescriptorProto::ExtensionRange& range1 =
+      file_.message_type(0).extension_range(0);
+  const DescriptorProto::ExtensionRange& range2 =
+      file_.message_type(0).extension_range(1);
+  const DescriptorProto::ExtensionRange& range3 =
+      file_.message_type(0).extension_range(2);
+
+  EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
+  EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
+
+  EXPECT_TRUE(HasSpan('b', 'e', range1));
+  EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+  EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
+
+  EXPECT_TRUE(HasSpan('f', 'g', range2));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
+
+  EXPECT_TRUE(HasSpan('j', 'm', range3));
+  EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
+  EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Oneofs) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  $a$oneof $c$foo$d$ {\n"
+      "    $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n"
+      "  }$r$\n"
+      "}\n"));
+
+  const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0);
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+  EXPECT_TRUE(HasSpan('a', 'r', oneof_decl));
+  EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name"));
+
+  EXPECT_TRUE(HasSpan('e', 'k', field));
+  EXPECT_TRUE(HasSpan('e', 'f', field, "type"));
+  EXPECT_TRUE(HasSpan('g', 'h', field, "name"));
+  EXPECT_TRUE(HasSpan('i', 'j', field, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedMessages) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  $a$message $b$Bar$c$ {\n"
+      "    $d$message $e$Baz$f$ {}$g$\n"
+      "  }$h$\n"
+      "  $i$message $j$Qux$k$ {}$l$\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = bar.nested_type(0);
+  const DescriptorProto& qux = file_.message_type(0).nested_type(1);
+
+  EXPECT_TRUE(HasSpan('a', 'h', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('d', 'g', baz));
+  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+  EXPECT_TRUE(HasSpan('i', 'l', qux));
+  EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Groups) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  message Bar {}\n"
+      "  $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
+      "    $i$message Qux {}$j$\n"
+      "  }$k$\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = file_.message_type(0).nested_type(1);
+  const DescriptorProto& qux = baz.nested_type(0);
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+  EXPECT_TRUE(HasSpan('a', 'k', field));
+  EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
+  EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
+  EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
+  EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
+  EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
+
+  EXPECT_TRUE(HasSpan('a', 'k', baz));
+  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+  EXPECT_TRUE(HasSpan('i', 'j', qux));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(bar));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(qux, "name"));
+}
+
+TEST_F(SourceInfoTest, Enums) {
+  EXPECT_TRUE(Parse(
+      "$a$enum $b$Foo$c$ {}$d$\n"
+      "$e$enum $f$Bar$g$ {}$h$\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, EnumValues) {
+  EXPECT_TRUE(Parse(
+      "enum Foo {\n"
+      "  $a$BAR$b$ = $c$1$d$;$e$\n"
+      "  $f$BAZ$g$ = $h$2$i$;$j$\n"
+      "}"));
+
+  const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
+  const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
+
+  EXPECT_TRUE(HasSpan('a', 'e', bar));
+  EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
+  EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
+  EXPECT_TRUE(HasSpan('f', 'j', baz));
+  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+  EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedEnums) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  $a$enum $b$Bar$c$ {}$d$\n"
+      "  $e$enum $f$Baz$g$ {}$h$\n"
+      "}\n"));
+
+  const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
+  const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
+
+  EXPECT_TRUE(HasSpan('a', 'd', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', baz));
+  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Services) {
+  EXPECT_TRUE(Parse(
+      "$a$service $b$Foo$c$ {}$d$\n"
+      "$e$service $f$Bar$g$ {}$h$\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, MethodsAndStreams) {
+  EXPECT_TRUE(Parse(
+      "service Foo {\n"
+      "  $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
+      "  $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
+      "}"));
+
+  const MethodDescriptorProto& bar = file_.service(0).method(0);
+  const MethodDescriptorProto& baz = file_.service(0).method(1);
+
+  EXPECT_TRUE(HasSpan('a', 'h', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
+  EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
+
+  EXPECT_TRUE(HasSpan('i', 'p', baz));
+  EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
+  EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
+  EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+}
+
+
+TEST_F(SourceInfoTest, Options) {
+  EXPECT_TRUE(Parse(
+      "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
+          "$h$123$i$;$j$\n"
+      "$k$option qux = $l$-123$m$;$n$\n"
+      "$o$option corge = $p$abc$q$;$r$\n"
+      "$s$option grault = $t$'blah'$u$;$v$\n"
+      "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
+      "$0$option waldo = $1$123.0$2$;$3$\n"
+  ));
+
+  const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
+  const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
+  const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
+  const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
+  const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
+
+  EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
+  EXPECT_TRUE(HasSpan('a', 'j', option1));
+  EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
+  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
+  EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
+  EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
+
+  EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
+  EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
+
+  EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
+  EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
+
+  EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
+  EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
+
+  EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
+  EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
+
+  EXPECT_TRUE(HasSpan('0', '3', file_.options()));
+  EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(option2));
+  EXPECT_TRUE(HasSpan(option3));
+  EXPECT_TRUE(HasSpan(option4));
+  EXPECT_TRUE(HasSpan(option5));
+  EXPECT_TRUE(HasSpan(option6));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option3, "name"));
+  EXPECT_TRUE(HasSpan(option4, "name"));
+  EXPECT_TRUE(HasSpan(option5, "name"));
+  EXPECT_TRUE(HasSpan(option6, "name"));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option3.name(0)));
+  EXPECT_TRUE(HasSpan(option4.name(0)));
+  EXPECT_TRUE(HasSpan(option5.name(0)));
+  EXPECT_TRUE(HasSpan(option6.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
+}
+
+TEST_F(SourceInfoTest, ScopedOptions) {
+  EXPECT_TRUE(Parse(
+    "message Foo {\n"
+    "  $a$option mopt = 1;$b$\n"
+    "}\n"
+    "enum Bar {\n"
+    "  $c$option eopt = 1;$d$\n"
+    "}\n"
+    "service Baz {\n"
+    "  $e$option sopt = 1;$f$\n"
+    "  rpc M(X) returns(Y) {\n"
+    "    $g$option mopt = 1;$h$\n"
+    "  }\n"
+    "  rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
+    "    $k$option mopt = 1;$l$\n"
+    "  }\n"
+    "}\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
+  EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
+  EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
+  EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+
+  EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1),
+                      "client_streaming"));
+  EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1),
+                      "server_streaming"));
+}
+
+TEST_F(SourceInfoTest, FieldOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for field options is understood.
+  EXPECT_TRUE(Parse(
+      "message Foo {"
+      "  optional int32 bar = 1 "
+          "$a$[default=$b$123$c$,$d$opt1=123$e$,"
+          "$f$opt2='hi'$g$]$h$;"
+      "}\n"
+  ));
+
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+  const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan('a', 'h', field.options()));
+  EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
+  EXPECT_TRUE(HasSpan('d', 'e', option1));
+  EXPECT_TRUE(HasSpan('f', 'g', option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field));
+  EXPECT_TRUE(HasSpan(field, "label"));
+  EXPECT_TRUE(HasSpan(field, "type"));
+  EXPECT_TRUE(HasSpan(field, "name"));
+  EXPECT_TRUE(HasSpan(field, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, EnumValueOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for enum options is understood.
+  EXPECT_TRUE(Parse(
+      "enum Foo {"
+      "  BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
+      "}\n"
+  ));
+
+  const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
+  const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan('a', 'f', value.options()));
+  EXPECT_TRUE(HasSpan('b', 'c', option1));
+  EXPECT_TRUE(HasSpan('d', 'e', option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(value));
+  EXPECT_TRUE(HasSpan(value, "name"));
+  EXPECT_TRUE(HasSpan(value, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments) {
+  EXPECT_TRUE(Parse(
+      "// Foo leading\n"
+      "// line 2\n"
+      "$a$message Foo {\n"
+      "  // Foo trailing\n"
+      "  // line 2\n"
+      "\n"
+      "  // detached\n"
+      "\n"
+      "  // bar leading\n"
+      "  $b$optional int32 bar = 1;$c$\n"
+      "  // bar trailing\n"
+      "}$d$\n"
+      "// ignored\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+
+  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+      " Foo leading\n line 2\n",
+      " Foo trailing\n line 2\n",
+      NULL));
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n",
+      " detached\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+}
+
+TEST_F(SourceInfoTest, DocComments2) {
+  EXPECT_TRUE(Parse(
+      "// detached before message.\n"
+      "\n"
+      "// Foo leading\n"
+      "// line 2\n"
+      "$a$message Foo {\n"
+      "  /* Foo trailing\n"
+      "   * line 2 */\n"
+      "  // detached\n"
+      "  /* bar leading\n"
+      "   */"
+      "  $b$optional int32 bar = 1;$c$  // bar trailing\n"
+      "  // ignored detached\n"
+      "}$d$\n"
+      "// ignored\n"
+      "\n"
+      "// detached before option\n"
+      "\n"
+      "// option leading\n"
+      "$e$option baz = 123;$f$\n"
+      "// option trailing\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+  const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
+
+  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+      " Foo leading\n line 2\n",
+      " Foo trailing\n line 2 ",
+      " detached before message.\n"));
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n",
+      " detached\n"));
+  EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
+      " option leading\n",
+      " option trailing\n",
+      " detached before option\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+  EXPECT_TRUE(HasSpan(file_.options()));
+  EXPECT_TRUE(HasSpan(baz, "name"));
+  EXPECT_TRUE(HasSpan(baz.name(0)));
+  EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments3) {
+  EXPECT_TRUE(Parse(
+      "$a$message Foo {\n"
+      "  // bar leading\n"
+      "  $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
+      "  // bar trailing\n"
+      "}$d$\n"
+      "// ignored\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n",
+      NULL));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+  EXPECT_TRUE(HasSpan(bar.options()));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(
+      bar.options().uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(
+      bar.options().uninterpreted_option(0), "aggregate_value"));
+}
+
+TEST_F(SourceInfoTest, DocCommentsTopLevel) {
+  EXPECT_TRUE(Parse(
+      "// detached before syntax paragraph 1\n"
+      "\n"
+      "// detached before syntax paragraph 2\n"
+      "\n"
+      "// syntax leading\n"
+      "$a$syntax = \"proto2\";$b$\n"
+      "// syntax trailing\n"
+      "\n"
+      "// syntax-package detached comments\n"
+      "\n"
+      ";\n"
+      "\n"
+      "// detached after empty before package\n"
+      "\n"
+      "// package leading\n"
+      "package $c$foo$d$;\n"
+      "// package trailing\n"
+      "\n"
+      "// ignored detach\n"
+      "\n"));
+
+  EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1,
+      " syntax leading\n",
+      " syntax trailing\n",
+      " detached before syntax paragraph 1\n"
+      "\n"
+      " detached before syntax paragraph 2\n"));
+  EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1,
+      " package leading\n",
+      " package trailing\n",
+      " syntax-package detached comments\n"
+      "\n"
+      " detached after empty before package\n"));
+
+  // ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, DocCommentsOneof) {
+  EXPECT_TRUE(Parse(
+      "// Foo leading\n"
+      "$a$message Foo {\n"
+      "  /* Foo trailing\n"
+      "   */\n"
+      "  // detached before oneof\n"
+      "  /* bar leading\n"
+      "   * line 2 */\n"
+      "  $b$oneof bar {\n"
+      "  /* bar trailing\n"
+      "   * line 2 */\n"
+      "  // detached before bar_int\n"
+      "  /* bar_int leading\n"
+      "   */\n"
+      "  $c$int32 bar_int = 1;$d$  // bar_int trailing\n"
+      "  // detach comment ignored\n"
+      "  }$e$\n"
+      "}$f$\n"));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const OneofDescriptorProto& bar = foo.oneof_decl(0);
+  const FieldDescriptorProto& bar_int = foo.field(0);
+
+  EXPECT_TRUE(HasSpanWithComment('a', 'f', foo,
+      " Foo leading\n",
+      " Foo trailing\n",
+      NULL));
+  EXPECT_TRUE(HasSpanWithComment('b', 'e', bar,
+      " bar leading\n line 2 ",
+      " bar trailing\n line 2 ",
+      " detached before oneof\n"));
+  EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int,
+      " bar_int leading\n",
+      " bar_int trailing\n",
+      " detached before bar_int\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar_int, "type"));
+  EXPECT_TRUE(HasSpan(bar_int, "name"));
+  EXPECT_TRUE(HasSpan(bar_int, "number"));
+}
+
+// ===================================================================
+
+}  // anonymous namespace
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.cc
new file mode 100644
index 0000000..2ff50f6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.cc
@@ -0,0 +1,194 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/plugin.h>
+
+#include <iostream>
+#include <set>
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#else
+#include <unistd.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class GeneratorResponseContext : public GeneratorContext {
+ public:
+  GeneratorResponseContext(CodeGeneratorResponse* response,
+                           const vector<const FileDescriptor*>& parsed_files)
+      : response_(response),
+        parsed_files_(parsed_files) {}
+  virtual ~GeneratorResponseContext() {}
+
+  // implements GeneratorContext --------------------------------------
+
+  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+    CodeGeneratorResponse::File* file = response_->add_file();
+    file->set_name(filename);
+    return new io::StringOutputStream(file->mutable_content());
+  }
+
+  virtual io::ZeroCopyOutputStream* OpenForInsert(
+      const string& filename, const string& insertion_point) {
+    CodeGeneratorResponse::File* file = response_->add_file();
+    file->set_name(filename);
+    file->set_insertion_point(insertion_point);
+    return new io::StringOutputStream(file->mutable_content());
+  }
+
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
+
+ private:
+  CodeGeneratorResponse* response_;
+  const vector<const FileDescriptor*>& parsed_files_;
+};
+
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg) {
+  DescriptorPool pool;
+  for (int i = 0; i < request.proto_file_size(); i++) {
+    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+    if (file == NULL) {
+      // BuildFile() already wrote an error message.
+      return false;
+    }
+  }
+
+  vector<const FileDescriptor*> parsed_files;
+  for (int i = 0; i < request.file_to_generate_size(); i++) {
+    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+    if (parsed_files.back() == NULL) {
+      *error_msg = "protoc asked plugin to generate a file but "
+                   "did not provide a descriptor for the file: " +
+                   request.file_to_generate(i);
+      return false;
+    }
+  }
+
+  GeneratorResponseContext context(response, parsed_files);
+
+  if (generator.HasGenerateAll()) {
+    string error;
+    bool succeeded = generator.GenerateAll(
+        parsed_files, request.parameter(), &context, &error);
+
+    if (!succeeded && error.empty()) {
+      error = "Code generator returned false but provided no error "
+              "description.";
+    }
+    if (!error.empty()) {
+      response->set_error(error);
+    }
+  } else {
+    for (int i = 0; i < parsed_files.size(); i++) {
+      const FileDescriptor* file = parsed_files[i];
+
+      string error;
+      bool succeeded = generator.Generate(
+          file, request.parameter(), &context, &error);
+
+      if (!succeeded && error.empty()) {
+        error = "Code generator returned false but provided no error "
+                "description.";
+      }
+      if (!error.empty()) {
+        response->set_error(file->name() + ": " + error);
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
+
+  if (argc > 1) {
+    std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl;
+    return 1;
+  }
+
+#ifdef _WIN32
+  _setmode(STDIN_FILENO, _O_BINARY);
+  _setmode(STDOUT_FILENO, _O_BINARY);
+#endif
+
+  CodeGeneratorRequest request;
+  if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
+    std::cerr << argv[0] << ": protoc sent unparseable request to plugin."
+              << std::endl;
+    return 1;
+  }
+
+  string error_msg;
+  CodeGeneratorResponse response;
+
+  if (GenerateCode(request, *generator, &response, &error_msg)) {
+    if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+      std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+      return 1;
+    }
+  } else {
+    if (!error_msg.empty()) {
+      std::cerr << argv[0] << ": " << error_msg << std::endl;
+    }
+    return 1;
+  }
+
+  return 0;
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.h
new file mode 100644
index 0000000..d2793a9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.h
@@ -0,0 +1,90 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Front-end for protoc code generator plugins written in C++.
+//
+// To implement a protoc plugin in C++, simply write an implementation of
+// CodeGenerator, then create a main() function like:
+//   int main(int argc, char* argv[]) {
+//     MyCodeGenerator generator;
+//     return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+//   }
+// You must link your plugin against libprotobuf and libprotoc.
+//
+// The core part of PluginMain is to invoke the given CodeGenerator on a
+// CodeGeneratorRequest to generate a CodeGeneratorResponse. This part is
+// abstracted out and made into function GenerateCode so that it can be reused,
+// for example, to implement a variant of PluginMain that does some
+// preprocessing on the input CodeGeneratorRequest before feeding the request
+// to the given code generator.
+//
+// To get protoc to use the plugin, do one of the following:
+// * Place the plugin binary somewhere in the PATH and give it the name
+//   "protoc-gen-NAME" (replacing "NAME" with the name of your plugin).  If you
+//   then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace
+//   "NAME" with your plugin's name), protoc will invoke your plugin to generate
+//   the output, which will be placed in OUT_DIR.
+// * Place the plugin binary anywhere, with any name, and pass the --plugin
+//   parameter to protoc to direct it to your plugin like so:
+//     protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR
+//   On Windows, make sure to include the .exe suffix:
+//     protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class CodeGenerator;    // code_generator.h
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
+
+// Implements main() for a protoc plugin exposing the given code generator.
+LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
+
+// Generates code using the given code generator. Returns true if the code
+// generation is successful. If the code geneartion fails, error_msg may be
+// populated to describe the failure cause.
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg);
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.cc
new file mode 100644
index 0000000..e9d50a1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.cc
@@ -0,0 +1,1600 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/compiler/plugin.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+const ::google::protobuf::Descriptor* CodeGeneratorRequest_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorRequest_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorResponse_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorResponse_File_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/compiler/plugin.proto");
+  GOOGLE_CHECK(file != NULL);
+  CodeGeneratorRequest_descriptor_ = file->message_type(0);
+  static const int CodeGeneratorRequest_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
+  };
+  CodeGeneratorRequest_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      CodeGeneratorRequest_descriptor_,
+      CodeGeneratorRequest::default_instance_,
+      CodeGeneratorRequest_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(CodeGeneratorRequest),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_),
+      -1);
+  CodeGeneratorResponse_descriptor_ = file->message_type(1);
+  static const int CodeGeneratorResponse_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
+  };
+  CodeGeneratorResponse_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      CodeGeneratorResponse_descriptor_,
+      CodeGeneratorResponse::default_instance_,
+      CodeGeneratorResponse_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(CodeGeneratorResponse),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_),
+      -1);
+  CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
+  static const int CodeGeneratorResponse_File_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
+  };
+  CodeGeneratorResponse_File_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      CodeGeneratorResponse_File_descriptor_,
+      CodeGeneratorResponse_File::default_instance_,
+      CodeGeneratorResponse_File_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(CodeGeneratorResponse_File),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_),
+      -1);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  delete CodeGeneratorRequest::default_instance_;
+  delete CodeGeneratorRequest_reflection_;
+  delete CodeGeneratorResponse::default_instance_;
+  delete CodeGeneratorResponse_reflection_;
+  delete CodeGeneratorResponse_File::default_instance_;
+  delete CodeGeneratorResponse_File_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n%google/protobuf/compiler/plugin.proto\022"
+    "\030google.protobuf.compiler\032 google/protob"
+    "uf/descriptor.proto\"}\n\024CodeGeneratorRequ"
+    "est\022\030\n\020file_to_generate\030\001 \003(\t\022\021\n\tparamet"
+    "er\030\002 \001(\t\0228\n\nproto_file\030\017 \003(\0132$.google.pr"
+    "otobuf.FileDescriptorProto\"\252\001\n\025CodeGener"
+    "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
+    "\01324.google.protobuf.compiler.CodeGenerat"
+    "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
+    "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
+    "7\n\034com.google.protobuf.compilerB\014PluginP"
+    "rotosZ\tplugin_go", 456);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
+  CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
+  CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse();
+  CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File();
+  CodeGeneratorRequest::default_instance_->InitAsDefaultInstance();
+  CodeGeneratorResponse::default_instance_->InitAsDefaultInstance();
+  CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
+const int CodeGeneratorRequest::kParameterFieldNumber;
+const int CodeGeneratorRequest::kProtoFileFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+CodeGeneratorRequest::CodeGeneratorRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
+void CodeGeneratorRequest::InitAsDefaultInstance() {
+}
+
+CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
+void CodeGeneratorRequest::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorRequest::~CodeGeneratorRequest() {
+  // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest)
+  SharedDtor();
+}
+
+void CodeGeneratorRequest::SharedDtor() {
+  parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorRequest_descriptor_;
+}
+
+const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  return *default_instance_;
+}
+
+CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
+
+CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
+  CodeGeneratorRequest* n = new CodeGeneratorRequest;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void CodeGeneratorRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
+  if (has_parameter()) {
+    parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  file_to_generate_.Clear();
+  proto_file_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool CodeGeneratorRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated string file_to_generate = 1;
+      case 1: {
+        if (tag == 10) {
+         parse_file_to_generate:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_file_to_generate()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->file_to_generate(this->file_to_generate_size() - 1).data(),
+            this->file_to_generate(this->file_to_generate_size() - 1).length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_file_to_generate;
+        if (input->ExpectTag(18)) goto parse_parameter;
+        break;
+      }
+
+      // optional string parameter = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_parameter:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_parameter()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->parameter().data(), this->parameter().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorRequest.parameter");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(122)) goto parse_proto_file;
+        break;
+      }
+
+      // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+      case 15: {
+        if (tag == 122) {
+         parse_proto_file:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_proto_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_proto_file()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(122)) goto parse_loop_proto_file;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest)
+  return false;
+#undef DO_
+}
+
+void CodeGeneratorRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest)
+  // repeated string file_to_generate = 1;
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->file_to_generate(i), output);
+  }
+
+  // optional string parameter = 2;
+  if (has_parameter()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->parameter().data(), this->parameter().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorRequest.parameter");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->parameter(), output);
+  }
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      15, this->proto_file(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
+::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
+  // repeated string file_to_generate = 1;
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(1, this->file_to_generate(i), target);
+  }
+
+  // optional string parameter = 2;
+  if (has_parameter()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->parameter().data(), this->parameter().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorRequest.parameter");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->parameter(), target);
+  }
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        15, this->proto_file(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest)
+  return target;
+}
+
+int CodeGeneratorRequest::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
+  int total_size = 0;
+
+  // optional string parameter = 2;
+  if (has_parameter()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->parameter());
+  }
+
+  // repeated string file_to_generate = 1;
+  total_size += 1 * this->file_to_generate_size();
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->file_to_generate(i));
+  }
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  total_size += 1 * this->proto_file_size();
+  for (int i = 0; i < this->proto_file_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->proto_file(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorRequest* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest)
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  file_to_generate_.MergeFrom(from.file_to_generate_);
+  proto_file_.MergeFrom(from.proto_file_);
+  if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    if (from.has_parameter()) {
+      set_has_parameter();
+      parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorRequest::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false;
+  return true;
+}
+
+void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
+  file_to_generate_.UnsafeArenaSwap(&other->file_to_generate_);
+  parameter_.Swap(&other->parameter_);
+  proto_file_.UnsafeArenaSwap(&other->proto_file_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorRequest_descriptor_;
+  metadata.reflection = CodeGeneratorRequest_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+int CodeGeneratorRequest::file_to_generate_size() const {
+  return file_to_generate_.size();
+}
+void CodeGeneratorRequest::clear_file_to_generate() {
+  file_to_generate_.Clear();
+}
+ const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Get(index);
+}
+ ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Mutable(index);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  file_to_generate_.Mutable(index)->assign(value);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+  file_to_generate_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+  file_to_generate_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Add();
+}
+ void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+  file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+bool CodeGeneratorRequest::has_parameter() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void CodeGeneratorRequest::set_has_parameter() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void CodeGeneratorRequest::clear_has_parameter() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void CodeGeneratorRequest::clear_parameter() {
+  parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_parameter();
+}
+ const ::std::string& CodeGeneratorRequest::parameter() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ ::std::string* CodeGeneratorRequest::mutable_parameter() {
+  set_has_parameter();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorRequest::release_parameter() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  clear_has_parameter();
+  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+  if (parameter != NULL) {
+    set_has_parameter();
+  } else {
+    clear_has_parameter();
+  }
+  parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+int CodeGeneratorRequest::proto_file_size() const {
+  return proto_file_.size();
+}
+void CodeGeneratorRequest::clear_proto_file() {
+  proto_file_.Clear();
+}
+const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Get(index);
+}
+::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Mutable(index);
+}
+::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return &proto_file_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int CodeGeneratorResponse_File::kNameFieldNumber;
+const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
+const int CodeGeneratorResponse_File::kContentFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
+void CodeGeneratorResponse_File::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
+void CodeGeneratorResponse_File::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
+  // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+  SharedDtor();
+}
+
+void CodeGeneratorResponse_File::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorResponse_File::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorResponse_File_descriptor_;
+}
+
+const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  return *default_instance_;
+}
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
+  CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void CodeGeneratorResponse_File::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (_has_bits_[0 / 32] & 7u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_insertion_point()) {
+      insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_content()) {
+      content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorResponse.File.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_insertion_point;
+        break;
+      }
+
+      // optional string insertion_point = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_insertion_point:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_insertion_point()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->insertion_point().data(), this->insertion_point().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(122)) goto parse_content;
+        break;
+      }
+
+      // optional string content = 15;
+      case 15: {
+        if (tag == 122) {
+         parse_content:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_content()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->content().data(), this->content().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorResponse.File.content");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File)
+  return false;
+#undef DO_
+}
+
+void CodeGeneratorResponse_File::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string insertion_point = 2;
+  if (has_insertion_point()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->insertion_point().data(), this->insertion_point().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->insertion_point(), output);
+  }
+
+  // optional string content = 15;
+  if (has_content()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->content().data(), this->content().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.content");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      15, this->content(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string insertion_point = 2;
+  if (has_insertion_point()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->insertion_point().data(), this->insertion_point().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->insertion_point(), target);
+  }
+
+  // optional string content = 15;
+  if (has_content()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->content().data(), this->content().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.File.content");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        15, this->content(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File)
+  return target;
+}
+
+int CodeGeneratorResponse_File::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 7u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional string insertion_point = 2;
+    if (has_insertion_point()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->insertion_point());
+    }
+
+    // optional string content = 15;
+    if (has_content()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->content());
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorResponse_File* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File)
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_insertion_point()) {
+      set_has_insertion_point();
+      insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_);
+    }
+    if (from.has_content()) {
+      set_has_content();
+      content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorResponse_File::IsInitialized() const {
+
+  return true;
+}
+
+void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
+  name_.Swap(&other->name_);
+  insertion_point_.Swap(&other->insertion_point_);
+  content_.Swap(&other->content_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorResponse_File_descriptor_;
+  metadata.reflection = CodeGeneratorResponse_File_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int CodeGeneratorResponse::kErrorFieldNumber;
+const int CodeGeneratorResponse::kFileFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+CodeGeneratorResponse::CodeGeneratorResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
+void CodeGeneratorResponse::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
+void CodeGeneratorResponse::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse::~CodeGeneratorResponse() {
+  // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse)
+  SharedDtor();
+}
+
+void CodeGeneratorResponse::SharedDtor() {
+  error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorResponse_descriptor_;
+}
+
+const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  return *default_instance_;
+}
+
+CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
+
+CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
+  CodeGeneratorResponse* n = new CodeGeneratorResponse;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void CodeGeneratorResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
+  if (has_error()) {
+    error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  file_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool CodeGeneratorResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string error = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_error()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->error().data(), this->error().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.CodeGeneratorResponse.error");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(122)) goto parse_file;
+        break;
+      }
+
+      // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+      case 15: {
+        if (tag == 122) {
+         parse_file:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_file()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(122)) goto parse_loop_file;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse)
+  return false;
+#undef DO_
+}
+
+void CodeGeneratorResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse)
+  // optional string error = 1;
+  if (has_error()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->error().data(), this->error().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.error");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->error(), output);
+  }
+
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      15, this->file(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
+  // optional string error = 1;
+  if (has_error()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->error().data(), this->error().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.CodeGeneratorResponse.error");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->error(), target);
+  }
+
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        15, this->file(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse)
+  return target;
+}
+
+int CodeGeneratorResponse::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
+  int total_size = 0;
+
+  // optional string error = 1;
+  if (has_error()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->error());
+  }
+
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  total_size += 1 * this->file_size();
+  for (int i = 0; i < this->file_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->file(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorResponse* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse)
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  file_.MergeFrom(from.file_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_error()) {
+      set_has_error();
+      error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorResponse::IsInitialized() const {
+
+  return true;
+}
+
+void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
+  error_.Swap(&other->error_);
+  file_.UnsafeArenaSwap(&other->file_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorResponse_descriptor_;
+  metadata.reflection = CodeGeneratorResponse_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+bool CodeGeneratorResponse_File::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void CodeGeneratorResponse_File::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void CodeGeneratorResponse_File::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& CodeGeneratorResponse_File::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+bool CodeGeneratorResponse_File::has_insertion_point() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_insertion_point() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void CodeGeneratorResponse_File::clear_has_insertion_point() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void CodeGeneratorResponse_File::clear_insertion_point() {
+  insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_insertion_point();
+}
+ const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+  set_has_insertion_point();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  clear_has_insertion_point();
+  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+  if (insertion_point != NULL) {
+    set_has_insertion_point();
+  } else {
+    clear_has_insertion_point();
+  }
+  insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+bool CodeGeneratorResponse_File::has_content() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_content() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void CodeGeneratorResponse_File::clear_has_content() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void CodeGeneratorResponse_File::clear_content() {
+  content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_content();
+}
+ const ::std::string& CodeGeneratorResponse_File::content() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_content() {
+  set_has_content();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_content() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  clear_has_content();
+  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+  if (content != NULL) {
+    set_has_content();
+  } else {
+    clear_has_content();
+  }
+  content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+bool CodeGeneratorResponse::has_error() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void CodeGeneratorResponse::set_has_error() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void CodeGeneratorResponse::clear_has_error() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void CodeGeneratorResponse::clear_error() {
+  error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_error();
+}
+ const ::std::string& CodeGeneratorResponse::error() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_error(const ::std::string& value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ ::std::string* CodeGeneratorResponse::mutable_error() {
+  set_has_error();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse::release_error() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
+  clear_has_error();
+  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+  if (error != NULL) {
+    set_has_error();
+  } else {
+    clear_has_error();
+  }
+  error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+int CodeGeneratorResponse::file_size() const {
+  return file_.size();
+}
+void CodeGeneratorResponse::clear_file() {
+  file_.Clear();
+}
+const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Get(index);
+}
+::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Mutable(index);
+}
+::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return &file_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.h
new file mode 100644
index 0000000..510202f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.pb.h
@@ -0,0 +1,818 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/descriptor.pb.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
+class CodeGeneratorResponse_File;
+
+// ===================================================================
+
+class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorRequest();
+  virtual ~CodeGeneratorRequest();
+
+  CodeGeneratorRequest(const CodeGeneratorRequest& from);
+
+  inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorRequest& default_instance();
+
+  void Swap(CodeGeneratorRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  inline CodeGeneratorRequest* New() const { return New(NULL); }
+
+  CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorRequest& from);
+  void MergeFrom(const CodeGeneratorRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(CodeGeneratorRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated string file_to_generate = 1;
+  int file_to_generate_size() const;
+  void clear_file_to_generate();
+  static const int kFileToGenerateFieldNumber = 1;
+  const ::std::string& file_to_generate(int index) const;
+  ::std::string* mutable_file_to_generate(int index);
+  void set_file_to_generate(int index, const ::std::string& value);
+  void set_file_to_generate(int index, const char* value);
+  void set_file_to_generate(int index, const char* value, size_t size);
+  ::std::string* add_file_to_generate();
+  void add_file_to_generate(const ::std::string& value);
+  void add_file_to_generate(const char* value);
+  void add_file_to_generate(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+
+  // optional string parameter = 2;
+  bool has_parameter() const;
+  void clear_parameter();
+  static const int kParameterFieldNumber = 2;
+  const ::std::string& parameter() const;
+  void set_parameter(const ::std::string& value);
+  void set_parameter(const char* value);
+  void set_parameter(const char* value, size_t size);
+  ::std::string* mutable_parameter();
+  ::std::string* release_parameter();
+  void set_allocated_parameter(::std::string* parameter);
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  int proto_file_size() const;
+  void clear_proto_file();
+  static const int kProtoFileFieldNumber = 15;
+  const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+  ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+  ::google::protobuf::FileDescriptorProto* add_proto_file();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+      mutable_proto_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+      proto_file() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
+ private:
+  inline void set_has_parameter();
+  inline void clear_has_parameter();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
+  ::google::protobuf::internal::ArenaStringPtr parameter_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+  void InitAsDefaultInstance();
+  static CodeGeneratorRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorResponse_File();
+  virtual ~CodeGeneratorResponse_File();
+
+  CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
+
+  inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorResponse_File& default_instance();
+
+  void Swap(CodeGeneratorResponse_File* other);
+
+  // implements Message ----------------------------------------------
+
+  inline CodeGeneratorResponse_File* New() const { return New(NULL); }
+
+  CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorResponse_File& from);
+  void MergeFrom(const CodeGeneratorResponse_File& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(CodeGeneratorResponse_File* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string insertion_point = 2;
+  bool has_insertion_point() const;
+  void clear_insertion_point();
+  static const int kInsertionPointFieldNumber = 2;
+  const ::std::string& insertion_point() const;
+  void set_insertion_point(const ::std::string& value);
+  void set_insertion_point(const char* value);
+  void set_insertion_point(const char* value, size_t size);
+  ::std::string* mutable_insertion_point();
+  ::std::string* release_insertion_point();
+  void set_allocated_insertion_point(::std::string* insertion_point);
+
+  // optional string content = 15;
+  bool has_content() const;
+  void clear_content();
+  static const int kContentFieldNumber = 15;
+  const ::std::string& content() const;
+  void set_content(const ::std::string& value);
+  void set_content(const char* value);
+  void set_content(const char* value, size_t size);
+  ::std::string* mutable_content();
+  ::std::string* release_content();
+  void set_allocated_content(::std::string* content);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_insertion_point();
+  inline void clear_has_insertion_point();
+  inline void set_has_content();
+  inline void clear_has_content();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr insertion_point_;
+  ::google::protobuf::internal::ArenaStringPtr content_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+  void InitAsDefaultInstance();
+  static CodeGeneratorResponse_File* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorResponse();
+  virtual ~CodeGeneratorResponse();
+
+  CodeGeneratorResponse(const CodeGeneratorResponse& from);
+
+  inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorResponse& default_instance();
+
+  void Swap(CodeGeneratorResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  inline CodeGeneratorResponse* New() const { return New(NULL); }
+
+  CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorResponse& from);
+  void MergeFrom(const CodeGeneratorResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(CodeGeneratorResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef CodeGeneratorResponse_File File;
+
+  // accessors -------------------------------------------------------
+
+  // optional string error = 1;
+  bool has_error() const;
+  void clear_error();
+  static const int kErrorFieldNumber = 1;
+  const ::std::string& error() const;
+  void set_error(const ::std::string& value);
+  void set_error(const char* value);
+  void set_error(const char* value, size_t size);
+  ::std::string* mutable_error();
+  ::std::string* release_error();
+  void set_allocated_error(::std::string* error);
+
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  int file_size() const;
+  void clear_file();
+  static const int kFileFieldNumber = 15;
+  const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+      mutable_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+      file() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
+ private:
+  inline void set_has_error();
+  inline void clear_has_error();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr error_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+  void InitAsDefaultInstance();
+  static CodeGeneratorResponse* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+inline int CodeGeneratorRequest::file_to_generate_size() const {
+  return file_to_generate_.size();
+}
+inline void CodeGeneratorRequest::clear_file_to_generate() {
+  file_to_generate_.Clear();
+}
+inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Get(index);
+}
+inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Mutable(index);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  file_to_generate_.Mutable(index)->assign(value);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+  file_to_generate_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+  file_to_generate_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_.Add();
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+  file_to_generate_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+  file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return file_to_generate_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+inline bool CodeGeneratorRequest::has_parameter() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorRequest::set_has_parameter() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_has_parameter() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_parameter() {
+  parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_parameter();
+}
+inline const ::std::string& CodeGeneratorRequest::parameter() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+  set_has_parameter();
+  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
+  set_has_parameter();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* CodeGeneratorRequest::release_parameter() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  clear_has_parameter();
+  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+  if (parameter != NULL) {
+    set_has_parameter();
+  } else {
+    clear_has_parameter();
+  }
+  parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+inline int CodeGeneratorRequest::proto_file_size() const {
+  return proto_file_.size();
+}
+inline void CodeGeneratorRequest::clear_proto_file() {
+  proto_file_.Clear();
+}
+inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Get(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Mutable(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return &proto_file_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_;
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+inline bool CodeGeneratorResponse_File::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse_File::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void CodeGeneratorResponse_File::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& CodeGeneratorResponse_File::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* CodeGeneratorResponse_File::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+inline bool CodeGeneratorResponse_File::has_insertion_point() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_insertion_point() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void CodeGeneratorResponse_File::clear_insertion_point() {
+  insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_insertion_point();
+}
+inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+  set_has_insertion_point();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  clear_has_insertion_point();
+  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+  if (insertion_point != NULL) {
+    set_has_insertion_point();
+  } else {
+    clear_has_insertion_point();
+  }
+  insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+inline bool CodeGeneratorResponse_File::has_content() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_content() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void CodeGeneratorResponse_File::clear_has_content() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void CodeGeneratorResponse_File::clear_content() {
+  content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_content();
+}
+inline const ::std::string& CodeGeneratorResponse_File::content() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+  set_has_content();
+  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
+  set_has_content();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* CodeGeneratorResponse_File::release_content() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  clear_has_content();
+  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+  if (content != NULL) {
+    set_has_content();
+  } else {
+    clear_has_content();
+  }
+  content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+inline bool CodeGeneratorResponse::has_error() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse::set_has_error() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse::clear_has_error() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void CodeGeneratorResponse::clear_error() {
+  error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_error();
+}
+inline const ::std::string& CodeGeneratorResponse::error() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline void CodeGeneratorResponse::set_error(const char* value) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+  set_has_error();
+  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline ::std::string* CodeGeneratorResponse::mutable_error() {
+  set_has_error();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+  return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* CodeGeneratorResponse::release_error() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
+  clear_has_error();
+  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+  if (error != NULL) {
+    set_has_error();
+  } else {
+    clear_has_error();
+  }
+  error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+inline int CodeGeneratorResponse::file_size() const {
+  return file_.size();
+}
+inline void CodeGeneratorResponse::clear_file() {
+  file_.Clear();
+}
+inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Get(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Mutable(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return &file_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_;
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.proto b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.proto
new file mode 100644
index 0000000..acaee1f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/plugin.proto
@@ -0,0 +1,150 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// WARNING:  The plugin interface is currently EXPERIMENTAL and is subject to
+//   change.
+//
+// protoc (aka the Protocol Compiler) can be extended via plugins.  A plugin is
+// just a program that reads a CodeGeneratorRequest from stdin and writes a
+// CodeGeneratorResponse to stdout.
+//
+// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
+// of dealing with the raw protocol defined here.
+//
+// A plugin executable needs only to be placed somewhere in the path.  The
+// plugin should be named "protoc-gen-$NAME", and will then be used when the
+// flag "--${NAME}_out" is passed to protoc.
+
+syntax = "proto2";
+package google.protobuf.compiler;
+option java_package = "com.google.protobuf.compiler";
+option java_outer_classname = "PluginProtos";
+
+option go_package = "plugin_go";
+
+import "google/protobuf/descriptor.proto";
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+message CodeGeneratorRequest {
+  // The .proto files that were explicitly listed on the command-line.  The
+  // code generator should generate code only for these files.  Each file's
+  // descriptor will be included in proto_file, below.
+  repeated string file_to_generate = 1;
+
+  // The generator parameter passed on the command-line.
+  optional string parameter = 2;
+
+  // FileDescriptorProtos for all files in files_to_generate and everything
+  // they import.  The files will appear in topological order, so each file
+  // appears before any file that imports it.
+  //
+  // protoc guarantees that all proto_files will be written after
+  // the fields above, even though this is not technically guaranteed by the
+  // protobuf wire format.  This theoretically could allow a plugin to stream
+  // in the FileDescriptorProtos and handle them one by one rather than read
+  // the entire set into memory at once.  However, as of this writing, this
+  // is not similarly optimized on protoc's end -- it will store all fields in
+  // memory at once before sending them to the plugin.
+  repeated FileDescriptorProto proto_file = 15;
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+message CodeGeneratorResponse {
+  // Error message.  If non-empty, code generation failed.  The plugin process
+  // should exit with status code zero even if it reports an error in this way.
+  //
+  // This should be used to indicate errors in .proto files which prevent the
+  // code generator from generating correct code.  Errors which indicate a
+  // problem in protoc itself -- such as the input CodeGeneratorRequest being
+  // unparseable -- should be reported by writing a message to stderr and
+  // exiting with a non-zero status code.
+  optional string error = 1;
+
+  // Represents a single generated file.
+  message File {
+    // The file name, relative to the output directory.  The name must not
+    // contain "." or ".." components and must be relative, not be absolute (so,
+    // the file cannot lie outside the output directory).  "/" must be used as
+    // the path separator, not "\".
+    //
+    // If the name is omitted, the content will be appended to the previous
+    // file.  This allows the generator to break large files into small chunks,
+    // and allows the generated text to be streamed back to protoc so that large
+    // files need not reside completely in memory at one time.  Note that as of
+    // this writing protoc does not optimize for this -- it will read the entire
+    // CodeGeneratorResponse before writing files to disk.
+    optional string name = 1;
+
+    // If non-empty, indicates that the named file should already exist, and the
+    // content here is to be inserted into that file at a defined insertion
+    // point.  This feature allows a code generator to extend the output
+    // produced by another code generator.  The original generator may provide
+    // insertion points by placing special annotations in the file that look
+    // like:
+    //   @@protoc_insertion_point(NAME)
+    // The annotation can have arbitrary text before and after it on the line,
+    // which allows it to be placed in a comment.  NAME should be replaced with
+    // an identifier naming the point -- this is what other generators will use
+    // as the insertion_point.  Code inserted at this point will be placed
+    // immediately above the line containing the insertion point (thus multiple
+    // insertions to the same point will come out in the order they were added).
+    // The double-@ is intended to make it unlikely that the generated code
+    // could contain things that look like insertion points by accident.
+    //
+    // For example, the C++ code generator places the following line in the
+    // .pb.h files that it generates:
+    //   // @@protoc_insertion_point(namespace_scope)
+    // This line appears within the scope of the file's package namespace, but
+    // outside of any particular class.  Another plugin can then specify the
+    // insertion_point "namespace_scope" to generate additional classes or
+    // other declarations that should be placed in this scope.
+    //
+    // Note that if the line containing the insertion point begins with
+    // whitespace, the same whitespace will be added to every line of the
+    // inserted text.  This is useful for languages like Python, where
+    // indentation matters.  In these languages, the insertion point comment
+    // should be indented the same amount as any inserted code will need to be
+    // in order to work correctly in that context.
+    //
+    // The code generator that generates the initial file and the one which
+    // inserts into it must both run as part of a single invocation of protoc.
+    // Code generators are executed in the order in which they appear on the
+    // command line.
+    //
+    // If |insertion_point| is present, |name| must also be present.
+    optional string insertion_point = 2;
+
+    // The file contents.
+    optional string content = 15;
+  }
+  repeated File file = 15;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.cc
new file mode 100644
index 0000000..0553dd0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.cc
@@ -0,0 +1,1331 @@
+// 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.
+
+//#PY25 compatible generated code for GAE.
+// Copyright 2007 Google Inc. All Rights Reserved.
+// Author: robinson@google.com (Will Robinson)
+//
+// This module outputs pure-Python protocol message classes that will
+// largely be constructed at runtime via the metaclass in reflection.py.
+// In other words, our job is basically to output a Python equivalent
+// of the C++ *Descriptor objects, and fix up all circular references
+// within these objects.
+//
+// Note that the runtime performance of protocol message classes created in
+// this way is expected to be lousy.  The plan is to create an alternate
+// generator that outputs a Python/C extension module that lets
+// performance-minded Python code leverage the fast C++ implementation
+// directly.
+
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/compiler/python/python_generator.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+
+namespace {
+
+// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
+// suffix stripped.
+// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
+string StripProto(const string& filename) {
+  const char* suffix = HasSuffixString(filename, ".protodevel")
+      ? ".protodevel" : ".proto";
+  return StripSuffixString(filename, suffix);
+}
+
+
+// Returns the Python module name expected for a given .proto filename.
+string ModuleName(const string& filename) {
+  string basename = StripProto(filename);
+  StripString(&basename, "-", '_');
+  StripString(&basename, "/", '.');
+  return basename + "_pb2";
+}
+
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing. See testPackageInitializationImport in
+// google/protobuf/python/reflection_test.py
+// to see why we need the alias.
+string ModuleAlias(const string& filename) {
+  string module_name = ModuleName(filename);
+  // We can't have dots in the module name, so we replace each with _dot_.
+  // But that could lead to a collision between a.b and a_dot_b, so we also
+  // duplicate each underscore.
+  GlobalReplaceSubstring("_", "__", &module_name);
+  GlobalReplaceSubstring(".", "_dot_", &module_name);
+  return module_name;
+}
+
+
+// Returns an import statement of form "from X.Y.Z import T" for the given
+// .proto filename.
+string ModuleImportStatement(const string& filename) {
+  string module_name = ModuleName(filename);
+  int last_dot_pos = module_name.rfind('.');
+  if (last_dot_pos == string::npos) {
+    // NOTE(petya): this is not tested as it would require a protocol buffer
+    // outside of any package, and I don't think that is easily achievable.
+    return "import " + module_name;
+  } else {
+    return "from " + module_name.substr(0, last_dot_pos) + " import " +
+        module_name.substr(last_dot_pos + 1);
+  }
+}
+
+
+// Returns the name of all containing types for descriptor,
+// in order from outermost to innermost, followed by descriptor's
+// own name.  Each name is separated by |separator|.
+template <typename DescriptorT>
+string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
+                                   const string& separator) {
+  string name = descriptor.name();
+  for (const Descriptor* current = descriptor.containing_type();
+       current != NULL; current = current->containing_type()) {
+    name = current->name() + separator + name;
+  }
+  return name;
+}
+
+
+// Name of the class attribute where we store the Python
+// descriptor.Descriptor instance for the generated class.
+// Must stay consistent with the _DESCRIPTOR_KEY constant
+// in proto2/public/reflection.py.
+const char kDescriptorKey[] = "DESCRIPTOR";
+
+
+// Does the file have top-level enums?
+inline bool HasTopLevelEnums(const FileDescriptor *file) {
+  return file->enum_type_count() > 0;
+}
+
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+  return file->service_count() > 0 &&
+         file->options().py_generic_services();
+}
+
+
+// Prints the common boilerplate needed at the top of every .py
+// file output by this generator.
+void PrintTopBoilerplate(
+    io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) {
+  // TODO(robinson): Allow parameterization of Python version?
+  printer->Print(
+      "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "# source: $filename$\n"
+      "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))"  //##PY25
+      "\n",
+      "filename", file->name());
+  if (HasTopLevelEnums(file)) {
+    printer->Print(
+        "from google.protobuf.internal import enum_type_wrapper\n");
+  }
+  printer->Print(
+      "from google.protobuf import descriptor as _descriptor\n"
+      "from google.protobuf import message as _message\n"
+      "from google.protobuf import reflection as _reflection\n"
+      "from google.protobuf import symbol_database as "
+      "_symbol_database\n");
+  if (HasGenericServices(file)) {
+    printer->Print(
+        "from google.protobuf import service as _service\n"
+        "from google.protobuf import service_reflection\n");
+  }
+
+  // Avoid circular imports if this module is descriptor_pb2.
+  if (!descriptor_proto) {
+    printer->Print(
+        "from google.protobuf import descriptor_pb2\n");
+  }
+  printer->Print(
+      "# @@protoc_insertion_point(imports)\n\n"
+      "_sym_db = _symbol_database.Default()\n");
+  printer->Print("\n\n");
+}
+
+
+// Returns a Python literal giving the default value for a field.
+// If the field specifies no explicit default value, we'll return
+// the default default value for the field type (zero for numbers,
+// empty string for strings, empty list for repeated fields, and
+// None for non-repeated, composite fields).
+//
+// TODO(robinson): Unify with code from
+// //compiler/cpp/internal/primitive_field.cc
+// //compiler/cpp/internal/enum_field.cc
+// //compiler/cpp/internal/string_field.cc
+string StringifyDefaultValue(const FieldDescriptor& field) {
+  if (field.is_repeated()) {
+    return "[]";
+  }
+
+  switch (field.cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return SimpleItoa(field.default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return SimpleItoa(field.default_value_uint32());
+    case FieldDescriptor::CPPTYPE_INT64:
+      return SimpleItoa(field.default_value_int64());
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return SimpleItoa(field.default_value_uint64());
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = field.default_value_double();
+      if (value == numeric_limits<double>::infinity()) {
+        // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
+        // a numeric literal that is too big for a double will become infinity.
+        return "1e10000";
+      } else if (value == -numeric_limits<double>::infinity()) {
+        // See above.
+        return "-1e10000";
+      } else if (value != value) {
+        // infinity * 0 = nan
+        return "(1e10000 * 0)";
+      } else {
+        return "float(" + SimpleDtoa(value) + ")";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = field.default_value_float();
+      if (value == numeric_limits<float>::infinity()) {
+        // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
+        // a numeric literal that is too big for a double will become infinity.
+        return "1e10000";
+      } else if (value == -numeric_limits<float>::infinity()) {
+        // See above.
+        return "-1e10000";
+      } else if (value != value) {
+        // infinity - infinity = nan
+        return "(1e10000 * 0)";
+      } else {
+        return "float(" + SimpleFtoa(value) + ")";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field.default_value_bool() ? "True" : "False";
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return SimpleItoa(field.default_value_enum()->number());
+    case FieldDescriptor::CPPTYPE_STRING:
+//##!PY25      return "b\"" + CEscape(field.default_value_string()) +
+//##!PY25             (field.type() != FieldDescriptor::TYPE_STRING ? "\"" :
+//##!PY25               "\".decode('utf-8')");
+      return "_b(\"" + CEscape(field.default_value_string()) +  //##PY25
+             (field.type() != FieldDescriptor::TYPE_STRING ? "\")" :  //##PY25
+               "\").decode('utf-8')");  //##PY25
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "None";
+  }
+  // (We could add a default case above but then we wouldn't get the nice
+  // compiler warning when a new type is added.)
+  GOOGLE_LOG(FATAL) << "Not reached.";
+  return "";
+}
+
+string StringifySyntax(FileDescriptor::Syntax syntax) {
+  switch (syntax) {
+    case FileDescriptor::SYNTAX_PROTO2:
+      return "proto2";
+    case FileDescriptor::SYNTAX_PROTO3:
+      return "proto3";
+    case FileDescriptor::SYNTAX_UNKNOWN:
+    default:
+      GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
+                    "and proto3 syntax.";
+      return "";
+  }
+}
+
+
+}  // namespace
+
+
+Generator::Generator() : file_(NULL) {
+}
+
+Generator::~Generator() {
+}
+
+bool Generator::Generate(const FileDescriptor* file,
+                         const string& parameter,
+                         GeneratorContext* context,
+                         string* error) const {
+
+  // Completely serialize all Generate() calls on this instance.  The
+  // thread-safety constraints of the CodeGenerator interface aren't clear so
+  // just be as conservative as possible.  It's easier to relax this later if
+  // we need to, but I doubt it will be an issue.
+  // TODO(kenton):  The proper thing to do would be to allocate any state on
+  //   the stack and use that, so that the Generator class itself does not need
+  //   to have any mutable members.  Then it is implicitly thread-safe.
+  MutexLock lock(&mutex_);
+  file_ = file;
+  string module_name = ModuleName(file->name());
+  string filename = module_name;
+  StripString(&filename, ".", '/');
+  filename += ".py";
+
+  FileDescriptorProto fdp;
+  file_->CopyTo(&fdp);
+  fdp.SerializeToString(&file_descriptor_serialized_);
+
+
+  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  GOOGLE_CHECK(output.get());
+  io::Printer printer(output.get(), '$');
+  printer_ = &printer;
+
+  PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+  PrintImports();
+  PrintFileDescriptor();
+  PrintTopLevelEnums();
+  PrintTopLevelExtensions();
+  PrintAllNestedEnumsInFile();
+  PrintMessageDescriptors();
+  FixForeignFieldsInDescriptors();
+  PrintMessages();
+  // We have to fix up the extensions after the message classes themselves,
+  // since they need to call static RegisterExtension() methods on these
+  // classes.
+  FixForeignFieldsInExtensions();
+  // Descriptor options may have custom extensions. These custom options
+  // can only be successfully parsed after we register corresponding
+  // extensions. Therefore we parse all options again here to recognize
+  // custom options that may be unknown when we define the descriptors.
+  FixAllDescriptorOptions();
+  if (HasGenericServices(file)) {
+    PrintServices();
+  }
+
+  printer.Print(
+    "# @@protoc_insertion_point(module_scope)\n");
+
+  return !printer.failed();
+}
+
+// Prints Python imports for all modules imported by |file|.
+void Generator::PrintImports() const {
+  for (int i = 0; i < file_->dependency_count(); ++i) {
+    const string& filename = file_->dependency(i)->name();
+    string import_statement = ModuleImportStatement(filename);
+    string module_alias = ModuleAlias(filename);
+    printer_->Print("$statement$ as $alias$\n", "statement",
+                    import_statement, "alias", module_alias);
+    CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
+  }
+  printer_->Print("\n");
+
+  // Print public imports.
+  for (int i = 0; i < file_->public_dependency_count(); ++i) {
+    string module_name = ModuleName(file_->public_dependency(i)->name());
+    printer_->Print("from $module$ import *\n", "module", module_name);
+  }
+  printer_->Print("\n");
+}
+
+// Prints the single file descriptor for this file.
+void Generator::PrintFileDescriptor() const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["name"] = file_->name();
+  m["package"] = file_->package();
+  m["syntax"] = StringifySyntax(file_->syntax());
+  const char file_descriptor_template[] =
+      "$descriptor_name$ = _descriptor.FileDescriptor(\n"
+      "  name='$name$',\n"
+      "  package='$package$',\n"
+      "  syntax='$syntax$',\n";
+  printer_->Print(m, file_descriptor_template);
+  printer_->Indent();
+  printer_->Print(
+//##!PY25      "serialized_pb=b'$value$'\n",
+      "serialized_pb=_b('$value$')\n",  //##PY25
+      "value", strings::CHexEscape(file_descriptor_serialized_));
+  if (file_->dependency_count() != 0) {
+    printer_->Print(",\ndependencies=[");
+    for (int i = 0; i < file_->dependency_count(); ++i) {
+      string module_alias = ModuleAlias(file_->dependency(i)->name());
+      printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+                      module_alias);
+    }
+    printer_->Print("]");
+  }
+
+  // TODO(falk): Also print options and fix the message_type, enum_type,
+  //             service and extension later in the generation.
+
+  printer_->Outdent();
+  printer_->Print(")\n");
+  printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
+                  kDescriptorKey);
+  printer_->Print("\n");
+}
+
+// Prints descriptors and module-level constants for all top-level
+// enums defined in |file|.
+void Generator::PrintTopLevelEnums() const {
+  vector<pair<string, int> > top_level_enum_values;
+  for (int i = 0; i < file_->enum_type_count(); ++i) {
+    const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+    PrintEnum(enum_descriptor);
+    printer_->Print("$name$ = "
+                    "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
+                    "name", enum_descriptor.name(),
+                    "descriptor_name",
+                    ModuleLevelDescriptorName(enum_descriptor));
+    printer_->Print("\n");
+
+    for (int j = 0; j < enum_descriptor.value_count(); ++j) {
+      const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
+      top_level_enum_values.push_back(
+          std::make_pair(value_descriptor.name(), value_descriptor.number()));
+    }
+  }
+
+  for (int i = 0; i < top_level_enum_values.size(); ++i) {
+    printer_->Print("$name$ = $value$\n",
+                    "name", top_level_enum_values[i].first,
+                    "value", SimpleItoa(top_level_enum_values[i].second));
+  }
+  printer_->Print("\n");
+}
+
+// Prints all enums contained in all message types in |file|.
+void Generator::PrintAllNestedEnumsInFile() const {
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    PrintNestedEnums(*file_->message_type(i));
+  }
+}
+
+// Prints a Python statement assigning the appropriate module-level
+// enum name to a Python EnumDescriptor object equivalent to
+// enum_descriptor.
+void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
+  map<string, string> m;
+  string module_level_descriptor_name =
+      ModuleLevelDescriptorName(enum_descriptor);
+  m["descriptor_name"] = module_level_descriptor_name;
+  m["name"] = enum_descriptor.name();
+  m["full_name"] = enum_descriptor.full_name();
+  m["file"] = kDescriptorKey;
+  const char enum_descriptor_template[] =
+      "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
+      "  name='$name$',\n"
+      "  full_name='$full_name$',\n"
+      "  filename=None,\n"
+      "  file=$file$,\n"
+      "  values=[\n";
+  string options_string;
+  enum_descriptor.options().SerializeToString(&options_string);
+  printer_->Print(m, enum_descriptor_template);
+  printer_->Indent();
+  printer_->Indent();
+  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+    PrintEnumValueDescriptor(*enum_descriptor.value(i));
+    printer_->Print(",\n");
+  }
+  printer_->Outdent();
+  printer_->Print("],\n");
+  printer_->Print("containing_type=None,\n");
+  printer_->Print("options=$options_value$,\n",
+                  "options_value",
+                  OptionsValue("EnumOptions", options_string));
+  EnumDescriptorProto edp;
+  PrintSerializedPbInterval(enum_descriptor, edp);
+  printer_->Outdent();
+  printer_->Print(")\n");
+  printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
+                  module_level_descriptor_name);
+  printer_->Print("\n");
+}
+
+// Recursively prints enums in nested types within descriptor, then
+// prints enums contained at the top level in descriptor.
+void Generator::PrintNestedEnums(const Descriptor& descriptor) const {
+  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+    PrintNestedEnums(*descriptor.nested_type(i));
+  }
+
+  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+    PrintEnum(*descriptor.enum_type(i));
+  }
+}
+
+void Generator::PrintTopLevelExtensions() const {
+  const bool is_extension = true;
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    const FieldDescriptor& extension_field = *file_->extension(i);
+    string constant_name = extension_field.name() + "_FIELD_NUMBER";
+    UpperString(&constant_name);
+    printer_->Print("$constant_name$ = $number$\n",
+      "constant_name", constant_name,
+      "number", SimpleItoa(extension_field.number()));
+    printer_->Print("$name$ = ", "name", extension_field.name());
+    PrintFieldDescriptor(extension_field, is_extension);
+    printer_->Print("\n");
+  }
+  printer_->Print("\n");
+}
+
+// Prints Python equivalents of all Descriptors in |file|.
+void Generator::PrintMessageDescriptors() const {
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    PrintDescriptor(*file_->message_type(i));
+    printer_->Print("\n");
+  }
+}
+
+void Generator::PrintServices() const {
+  for (int i = 0; i < file_->service_count(); ++i) {
+    PrintServiceDescriptor(*file_->service(i));
+    PrintServiceClass(*file_->service(i));
+    PrintServiceStub(*file_->service(i));
+    printer_->Print("\n");
+  }
+}
+
+void Generator::PrintServiceDescriptor(
+    const ServiceDescriptor& descriptor) const {
+  printer_->Print("\n");
+  string service_name = ModuleLevelServiceDescriptorName(descriptor);
+  string options_string;
+  descriptor.options().SerializeToString(&options_string);
+
+  printer_->Print(
+      "$service_name$ = _descriptor.ServiceDescriptor(\n",
+      "service_name", service_name);
+  printer_->Indent();
+  map<string, string> m;
+  m["name"] = descriptor.name();
+  m["full_name"] = descriptor.full_name();
+  m["file"] = kDescriptorKey;
+  m["index"] = SimpleItoa(descriptor.index());
+  m["options_value"] = OptionsValue("ServiceOptions", options_string);
+  const char required_function_arguments[] =
+      "name='$name$',\n"
+      "full_name='$full_name$',\n"
+      "file=$file$,\n"
+      "index=$index$,\n"
+      "options=$options_value$,\n";
+  printer_->Print(m, required_function_arguments);
+
+  ServiceDescriptorProto sdp;
+  PrintSerializedPbInterval(descriptor, sdp);
+
+  printer_->Print("methods=[\n");
+  for (int i = 0; i < descriptor.method_count(); ++i) {
+    const MethodDescriptor* method = descriptor.method(i);
+    method->options().SerializeToString(&options_string);
+
+    m.clear();
+    m["name"] = method->name();
+    m["full_name"] = method->full_name();
+    m["index"] = SimpleItoa(method->index());
+    m["serialized_options"] = CEscape(options_string);
+    m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
+    m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
+    m["options_value"] = OptionsValue("MethodOptions", options_string);
+    printer_->Print("_descriptor.MethodDescriptor(\n");
+    printer_->Indent();
+    printer_->Print(
+        m,
+        "name='$name$',\n"
+        "full_name='$full_name$',\n"
+        "index=$index$,\n"
+        "containing_service=None,\n"
+        "input_type=$input_type$,\n"
+        "output_type=$output_type$,\n"
+        "options=$options_value$,\n");
+    printer_->Outdent();
+    printer_->Print("),\n");
+  }
+
+  printer_->Outdent();
+  printer_->Print("])\n\n");
+}
+
+
+void Generator::PrintDescriptorKeyAndModuleName(
+    const ServiceDescriptor& descriptor) const {
+  printer_->Print(
+      "$descriptor_key$ = $descriptor_name$,\n",
+      "descriptor_key", kDescriptorKey,
+      "descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
+  printer_->Print(
+      "__module__ = '$module_name$'\n",
+      "module_name", ModuleName(file_->name()));
+}
+
+void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
+  // Print the service.
+  printer_->Print("$class_name$ = service_reflection.GeneratedServiceType("
+                  "'$class_name$', (_service.Service,), dict(\n",
+                  "class_name", descriptor.name());
+  printer_->Indent();
+  Generator::PrintDescriptorKeyAndModuleName(descriptor);
+  printer_->Print("))\n\n");
+  printer_->Outdent();
+}
+
+void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
+  // Print the service stub.
+  printer_->Print("$class_name$_Stub = "
+                  "service_reflection.GeneratedServiceStubType("
+                  "'$class_name$_Stub', ($class_name$,), dict(\n",
+                  "class_name", descriptor.name());
+  printer_->Indent();
+  Generator::PrintDescriptorKeyAndModuleName(descriptor);
+  printer_->Print("))\n\n");
+  printer_->Outdent();
+}
+
+// Prints statement assigning ModuleLevelDescriptorName(message_descriptor)
+// to a Python Descriptor object for message_descriptor.
+//
+// Mutually recursive with PrintNestedDescriptors().
+void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
+  PrintNestedDescriptors(message_descriptor);
+
+  printer_->Print("\n");
+  printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
+                  "descriptor_name",
+                  ModuleLevelDescriptorName(message_descriptor));
+  printer_->Indent();
+  map<string, string> m;
+  m["name"] = message_descriptor.name();
+  m["full_name"] = message_descriptor.full_name();
+  m["file"] = kDescriptorKey;
+  const char required_function_arguments[] =
+      "name='$name$',\n"
+      "full_name='$full_name$',\n"
+      "filename=None,\n"
+      "file=$file$,\n"
+      "containing_type=None,\n";
+  printer_->Print(m, required_function_arguments);
+  PrintFieldsInDescriptor(message_descriptor);
+  PrintExtensionsInDescriptor(message_descriptor);
+
+  // Nested types
+  printer_->Print("nested_types=[");
+  for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
+    const string nested_name = ModuleLevelDescriptorName(
+        *message_descriptor.nested_type(i));
+    printer_->Print("$name$, ", "name", nested_name);
+  }
+  printer_->Print("],\n");
+
+  // Enum types
+  printer_->Print("enum_types=[\n");
+  printer_->Indent();
+  for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
+    const string descriptor_name = ModuleLevelDescriptorName(
+        *message_descriptor.enum_type(i));
+    printer_->Print(descriptor_name.c_str());
+    printer_->Print(",\n");
+  }
+  printer_->Outdent();
+  printer_->Print("],\n");
+  string options_string;
+  message_descriptor.options().SerializeToString(&options_string);
+  printer_->Print(
+      "options=$options_value$,\n"
+      "is_extendable=$extendable$,\n"
+      "syntax='$syntax$'",
+      "options_value", OptionsValue("MessageOptions", options_string),
+      "extendable", message_descriptor.extension_range_count() > 0 ?
+                      "True" : "False",
+      "syntax", StringifySyntax(message_descriptor.file()->syntax()));
+  printer_->Print(",\n");
+
+  // Extension ranges
+  printer_->Print("extension_ranges=[");
+  for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
+    const Descriptor::ExtensionRange* range =
+        message_descriptor.extension_range(i);
+    printer_->Print("($start$, $end$), ",
+                    "start", SimpleItoa(range->start),
+                    "end", SimpleItoa(range->end));
+  }
+  printer_->Print("],\n");
+  printer_->Print("oneofs=[\n");
+  printer_->Indent();
+  for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) {
+    const OneofDescriptor* desc = message_descriptor.oneof_decl(i);
+    map<string, string> m;
+    m["name"] = desc->name();
+    m["full_name"] = desc->full_name();
+    m["index"] = SimpleItoa(desc->index());
+    printer_->Print(
+        m,
+        "_descriptor.OneofDescriptor(\n"
+        "  name='$name$', full_name='$full_name$',\n"
+        "  index=$index$, containing_type=None, fields=[]),\n");
+  }
+  printer_->Outdent();
+  printer_->Print("],\n");
+  // Serialization of proto
+  DescriptorProto edp;
+  PrintSerializedPbInterval(message_descriptor, edp);
+
+  printer_->Outdent();
+  printer_->Print(")\n");
+}
+
+// Prints Python Descriptor objects for all nested types contained in
+// message_descriptor.
+//
+// Mutually recursive with PrintDescriptor().
+void Generator::PrintNestedDescriptors(
+    const Descriptor& containing_descriptor) const {
+  for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
+    PrintDescriptor(*containing_descriptor.nested_type(i));
+  }
+}
+
+// Prints all messages in |file|.
+void Generator::PrintMessages() const {
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    vector<string> to_register;
+    PrintMessage(*file_->message_type(i), "", &to_register);
+    for (int j = 0; j < to_register.size(); ++j) {
+      printer_->Print("_sym_db.RegisterMessage($name$)\n", "name",
+                      to_register[j]);
+    }
+    printer_->Print("\n");
+  }
+}
+
+// Prints a Python class for the given message descriptor.  We defer to the
+// metaclass to do almost all of the work of actually creating a useful class.
+// The purpose of this function and its many helper functions above is merely
+// to output a Python version of the descriptors, which the metaclass in
+// reflection.py will use to construct the meat of the class itself.
+//
+// Mutually recursive with PrintNestedMessages().
+// Collect nested message names to_register for the symbol_database.
+void Generator::PrintMessage(const Descriptor& message_descriptor,
+                             const string& prefix,
+                             vector<string>* to_register) const {
+  string qualified_name(prefix + message_descriptor.name());
+  to_register->push_back(qualified_name);
+  printer_->Print(
+      "$name$ = _reflection.GeneratedProtocolMessageType('$name$', "
+      "(_message.Message,), dict(\n",
+      "name", message_descriptor.name());
+  printer_->Indent();
+
+  PrintNestedMessages(message_descriptor, qualified_name + ".", to_register);
+  map<string, string> m;
+  m["descriptor_key"] = kDescriptorKey;
+  m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
+  printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n");
+  printer_->Print("__module__ = '$module_name$'\n",
+                  "module_name", ModuleName(file_->name()));
+  printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n",
+                  "full_name", message_descriptor.full_name());
+  printer_->Print("))\n");
+  printer_->Outdent();
+}
+
+// Prints all nested messages within |containing_descriptor|.
+// Mutually recursive with PrintMessage().
+void Generator::PrintNestedMessages(const Descriptor& containing_descriptor,
+                                    const string& prefix,
+                                    vector<string>* to_register) const {
+  for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
+    printer_->Print("\n");
+    PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register);
+    printer_->Print(",\n");
+  }
+}
+
+// Recursively fixes foreign fields in all nested types in |descriptor|, then
+// sets the message_type and enum_type of all message and enum fields to point
+// to their respective descriptors.
+// Args:
+//   descriptor: descriptor to print fields for.
+//   containing_descriptor: if descriptor is a nested type, this is its
+//       containing type, or NULL if this is a root/top-level type.
+void Generator::FixForeignFieldsInDescriptor(
+    const Descriptor& descriptor,
+    const Descriptor* containing_descriptor) const {
+  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+    FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
+  }
+
+  for (int i = 0; i < descriptor.field_count(); ++i) {
+    const FieldDescriptor& field_descriptor = *descriptor.field(i);
+    FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
+  }
+
+  FixContainingTypeInDescriptor(descriptor, containing_descriptor);
+  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+    const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
+    FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
+  }
+  for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
+    map<string, string> m;
+    const OneofDescriptor* oneof = descriptor.oneof_decl(i);
+    m["descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+    m["oneof_name"] = oneof->name();
+    for (int j = 0; j < oneof->field_count(); ++j) {
+      m["field_name"] = oneof->field(j)->name();
+      printer_->Print(
+          m,
+          "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n"
+          "  $descriptor_name$.fields_by_name['$field_name$'])\n");
+      printer_->Print(
+          m,
+          "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = "
+          "$descriptor_name$.oneofs_by_name['$oneof_name$']\n");
+    }
+  }
+}
+
+void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["message_name"] = descriptor.name();
+  m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.message_types_by_name['$message_name$'] = "
+      "$message_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
+void Generator::AddEnumToFileDescriptor(
+    const EnumDescriptor& descriptor) const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["enum_name"] = descriptor.name();
+  m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.enum_types_by_name['$enum_name$'] = "
+      "$enum_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
+void Generator::AddExtensionToFileDescriptor(
+    const FieldDescriptor& descriptor) const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["field_name"] = descriptor.name();
+  const char file_descriptor_template[] =
+      "$descriptor_name$.extensions_by_name['$field_name$'] = "
+      "$field_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
+// Sets any necessary message_type and enum_type attributes
+// for the Python version of |field|.
+//
+// containing_type may be NULL, in which case this is a module-level field.
+//
+// python_dict_name is the name of the Python dict where we should
+// look the field up in the containing type.  (e.g., fields_by_name
+// or extensions_by_name).  We ignore python_dict_name if containing_type
+// is NULL.
+void Generator::FixForeignFieldsInField(const Descriptor* containing_type,
+                                        const FieldDescriptor& field,
+                                        const string& python_dict_name) const {
+  const string field_referencing_expression = FieldReferencingExpression(
+      containing_type, field, python_dict_name);
+  map<string, string> m;
+  m["field_ref"] = field_referencing_expression;
+  const Descriptor* foreign_message_type = field.message_type();
+  if (foreign_message_type) {
+    m["foreign_type"] = ModuleLevelDescriptorName(*foreign_message_type);
+    printer_->Print(m, "$field_ref$.message_type = $foreign_type$\n");
+  }
+  const EnumDescriptor* enum_type = field.enum_type();
+  if (enum_type) {
+    m["enum_type"] = ModuleLevelDescriptorName(*enum_type);
+    printer_->Print(m, "$field_ref$.enum_type = $enum_type$\n");
+  }
+}
+
+// Returns the module-level expression for the given FieldDescriptor.
+// Only works for fields in the .proto file this Generator is generating for.
+//
+// containing_type may be NULL, in which case this is a module-level field.
+//
+// python_dict_name is the name of the Python dict where we should
+// look the field up in the containing type.  (e.g., fields_by_name
+// or extensions_by_name).  We ignore python_dict_name if containing_type
+// is NULL.
+string Generator::FieldReferencingExpression(
+    const Descriptor* containing_type,
+    const FieldDescriptor& field,
+    const string& python_dict_name) const {
+  // We should only ever be looking up fields in the current file.
+  // The only things we refer to from other files are message descriptors.
+  GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
+                                << file_->name();
+  if (!containing_type) {
+    return field.name();
+  }
+  return strings::Substitute(
+      "$0.$1['$2']",
+      ModuleLevelDescriptorName(*containing_type),
+      python_dict_name, field.name());
+}
+
+// Prints containing_type for nested descriptors or enum descriptors.
+template <typename DescriptorT>
+void Generator::FixContainingTypeInDescriptor(
+    const DescriptorT& descriptor,
+    const Descriptor* containing_descriptor) const {
+  if (containing_descriptor != NULL) {
+    const string nested_name = ModuleLevelDescriptorName(descriptor);
+    const string parent_name = ModuleLevelDescriptorName(
+        *containing_descriptor);
+    printer_->Print(
+        "$nested_name$.containing_type = $parent_name$\n",
+        "nested_name", nested_name,
+        "parent_name", parent_name);
+  }
+}
+
+// Prints statements setting the message_type and enum_type fields in the
+// Python descriptor objects we've already output in ths file.  We must
+// do this in a separate step due to circular references (otherwise, we'd
+// just set everything in the initial assignment statements).
+void Generator::FixForeignFieldsInDescriptors() const {
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
+  }
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    AddMessageToFileDescriptor(*file_->message_type(i));
+  }
+  for (int i = 0; i < file_->enum_type_count(); ++i) {
+    AddEnumToFileDescriptor(*file_->enum_type(i));
+  }
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    AddExtensionToFileDescriptor(*file_->extension(i));
+  }
+  printer_->Print("\n");
+}
+
+// We need to not only set any necessary message_type fields, but
+// also need to call RegisterExtension() on each message we're
+// extending.
+void Generator::FixForeignFieldsInExtensions() const {
+  // Top-level extensions.
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    FixForeignFieldsInExtension(*file_->extension(i));
+  }
+  // Nested extensions.
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    FixForeignFieldsInNestedExtensions(*file_->message_type(i));
+  }
+  printer_->Print("\n");
+}
+
+void Generator::FixForeignFieldsInExtension(
+    const FieldDescriptor& extension_field) const {
+  GOOGLE_CHECK(extension_field.is_extension());
+  // extension_scope() will be NULL for top-level extensions, which is
+  // exactly what FixForeignFieldsInField() wants.
+  FixForeignFieldsInField(extension_field.extension_scope(), extension_field,
+                          "extensions_by_name");
+
+  map<string, string> m;
+  // Confusingly, for FieldDescriptors that happen to be extensions,
+  // containing_type() means "extended type."
+  // On the other hand, extension_scope() will give us what we normally
+  // mean by containing_type().
+  m["extended_message_class"] = ModuleLevelMessageName(
+      *extension_field.containing_type());
+  m["field"] = FieldReferencingExpression(extension_field.extension_scope(),
+                                          extension_field,
+                                          "extensions_by_name");
+  printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n");
+}
+
+void Generator::FixForeignFieldsInNestedExtensions(
+    const Descriptor& descriptor) const {
+  // Recursively fix up extensions in all nested types.
+  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+    FixForeignFieldsInNestedExtensions(*descriptor.nested_type(i));
+  }
+  // Fix up extensions directly contained within this type.
+  for (int i = 0; i < descriptor.extension_count(); ++i) {
+    FixForeignFieldsInExtension(*descriptor.extension(i));
+  }
+}
+
+// Returns a Python expression that instantiates a Python EnumValueDescriptor
+// object for the given C++ descriptor.
+void Generator::PrintEnumValueDescriptor(
+    const EnumValueDescriptor& descriptor) const {
+  // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
+  // More circular references.  ::sigh::
+  string options_string;
+  descriptor.options().SerializeToString(&options_string);
+  map<string, string> m;
+  m["name"] = descriptor.name();
+  m["index"] = SimpleItoa(descriptor.index());
+  m["number"] = SimpleItoa(descriptor.number());
+  m["options"] = OptionsValue("EnumValueOptions", options_string);
+  printer_->Print(
+      m,
+      "_descriptor.EnumValueDescriptor(\n"
+      "  name='$name$', index=$index$, number=$number$,\n"
+      "  options=$options$,\n"
+      "  type=None)");
+}
+
+// Returns a Python expression that calls descriptor._ParseOptions using
+// the given descriptor class name and serialized options protobuf string.
+string Generator::OptionsValue(
+    const string& class_name, const string& serialized_options) const {
+  if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
+    return "None";
+  } else {
+    string full_class_name = "descriptor_pb2." + class_name;
+//##!PY25    return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
+//##!PY25        + CEscape(serialized_options)+ "')";
+    return "_descriptor._ParseOptions(" + full_class_name + "(), _b('"  //##PY25
+        + CEscape(serialized_options)+ "'))";  //##PY25
+  }
+}
+
+// Prints an expression for a Python FieldDescriptor for |field|.
+void Generator::PrintFieldDescriptor(
+    const FieldDescriptor& field, bool is_extension) const {
+  string options_string;
+  field.options().SerializeToString(&options_string);
+  map<string, string> m;
+  m["name"] = field.name();
+  m["full_name"] = field.full_name();
+  m["index"] = SimpleItoa(field.index());
+  m["number"] = SimpleItoa(field.number());
+  m["type"] = SimpleItoa(field.type());
+  m["cpp_type"] = SimpleItoa(field.cpp_type());
+  m["label"] = SimpleItoa(field.label());
+  m["has_default_value"] = field.has_default_value() ? "True" : "False";
+  m["default_value"] = StringifyDefaultValue(field);
+  m["is_extension"] = is_extension ? "True" : "False";
+  m["options"] = OptionsValue("FieldOptions", options_string);
+  // We always set message_type and enum_type to None at this point, and then
+  // these fields in correctly after all referenced descriptors have been
+  // defined and/or imported (see FixForeignFieldsInDescriptors()).
+  const char field_descriptor_decl[] =
+    "_descriptor.FieldDescriptor(\n"
+    "  name='$name$', full_name='$full_name$', index=$index$,\n"
+    "  number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
+    "  has_default_value=$has_default_value$, default_value=$default_value$,\n"
+    "  message_type=None, enum_type=None, containing_type=None,\n"
+    "  is_extension=$is_extension$, extension_scope=None,\n"
+    "  options=$options$)";
+  printer_->Print(m, field_descriptor_decl);
+}
+
+// Helper for Print{Fields,Extensions}InDescriptor().
+void Generator::PrintFieldDescriptorsInDescriptor(
+    const Descriptor& message_descriptor,
+    bool is_extension,
+    const string& list_variable_name,
+    int (Descriptor::*CountFn)() const,
+    const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const {
+  printer_->Print("$list$=[\n", "list", list_variable_name);
+  printer_->Indent();
+  for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) {
+    PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i),
+                         is_extension);
+    printer_->Print(",\n");
+  }
+  printer_->Outdent();
+  printer_->Print("],\n");
+}
+
+// Prints a statement assigning "fields" to a list of Python FieldDescriptors,
+// one for each field present in message_descriptor.
+void Generator::PrintFieldsInDescriptor(
+    const Descriptor& message_descriptor) const {
+  const bool is_extension = false;
+  PrintFieldDescriptorsInDescriptor(
+      message_descriptor, is_extension, "fields",
+      &Descriptor::field_count, &Descriptor::field);
+}
+
+// Prints a statement assigning "extensions" to a list of Python
+// FieldDescriptors, one for each extension present in message_descriptor.
+void Generator::PrintExtensionsInDescriptor(
+    const Descriptor& message_descriptor) const {
+  const bool is_extension = true;
+  PrintFieldDescriptorsInDescriptor(
+      message_descriptor, is_extension, "extensions",
+      &Descriptor::extension_count, &Descriptor::extension);
+}
+
+bool Generator::GeneratingDescriptorProto() const {
+  return file_->name() == "google/protobuf/descriptor.proto";
+}
+
+// Returns the unique Python module-level identifier given to a descriptor.
+// This name is module-qualified iff the given descriptor describes an
+// entity that doesn't come from the current file.
+template <typename DescriptorT>
+string Generator::ModuleLevelDescriptorName(
+    const DescriptorT& descriptor) const {
+  // FIXME(robinson):
+  // We currently don't worry about collisions with underscores in the type
+  // names, so these would collide in nasty ways if found in the same file:
+  //   OuterProto.ProtoA.ProtoB
+  //   OuterProto_ProtoA.ProtoB  # Underscore instead of period.
+  // As would these:
+  //   OuterProto.ProtoA_.ProtoB
+  //   OuterProto.ProtoA._ProtoB  # Leading vs. trailing underscore.
+  // (Contrived, but certainly possible).
+  //
+  // The C++ implementation doesn't guard against this either.  Leaving
+  // it for now...
+  string name = NamePrefixedWithNestedTypes(descriptor, "_");
+  UpperString(&name);
+  // Module-private for now.  Easy to make public later; almost impossible
+  // to make private later.
+  name = "_" + name;
+  // We now have the name relative to its own module.  Also qualify with
+  // the module name iff this descriptor is from a different .proto file.
+  if (descriptor.file() != file_) {
+    name = ModuleAlias(descriptor.file()->name()) + "." + name;
+  }
+  return name;
+}
+
+// Returns the name of the message class itself, not the descriptor.
+// Like ModuleLevelDescriptorName(), module-qualifies the name iff
+// the given descriptor describes an entity that doesn't come from
+// the current file.
+string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const {
+  string name = NamePrefixedWithNestedTypes(descriptor, ".");
+  if (descriptor.file() != file_) {
+    name = ModuleAlias(descriptor.file()->name()) + "." + name;
+  }
+  return name;
+}
+
+// Returns the unique Python module-level identifier given to a service
+// descriptor.
+string Generator::ModuleLevelServiceDescriptorName(
+    const ServiceDescriptor& descriptor) const {
+  string name = descriptor.name();
+  UpperString(&name);
+  name = "_" + name;
+  if (descriptor.file() != file_) {
+    name = ModuleAlias(descriptor.file()->name()) + "." + name;
+  }
+  return name;
+}
+
+// Prints standard constructor arguments serialized_start and serialized_end.
+// Args:
+//   descriptor: The cpp descriptor to have a serialized reference.
+//   proto: A proto
+// Example printer output:
+// serialized_start=41,
+// serialized_end=43,
+//
+template <typename DescriptorT, typename DescriptorProtoT>
+void Generator::PrintSerializedPbInterval(
+    const DescriptorT& descriptor, DescriptorProtoT& proto) const {
+  descriptor.CopyTo(&proto);
+  string sp;
+  proto.SerializeToString(&sp);
+  int offset = file_descriptor_serialized_.find(sp);
+  GOOGLE_CHECK_GE(offset, 0);
+
+  printer_->Print("serialized_start=$serialized_start$,\n"
+                  "serialized_end=$serialized_end$,\n",
+                  "serialized_start", SimpleItoa(offset),
+                  "serialized_end", SimpleItoa(offset + sp.size()));
+}
+
+namespace {
+void PrintDescriptorOptionsFixingCode(const string& descriptor,
+                                      const string& options,
+                                      io::Printer* printer) {
+  // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
+  // in proto2 python runtime but it couldn't be used here because appengine
+  // uses a snapshot version of the library in which the new method is not
+  // yet present. After appengine has synced their runtime library, the code
+  // below should be cleaned up to use _SetOptions().
+  printer->Print(
+      "$descriptor$.has_options = True\n"
+      "$descriptor$._options = $options$\n",
+      "descriptor", descriptor, "options", options);
+}
+}  // namespace
+
+// Prints expressions that set the options field of all descriptors.
+void Generator::FixAllDescriptorOptions() const {
+  // Prints an expression that sets the file descriptor's options.
+  string file_options = OptionsValue(
+      "FileOptions", file_->options().SerializeAsString());
+  if (file_options != "None") {
+    PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
+  }
+  // Prints expressions that set the options for all top level enums.
+  for (int i = 0; i < file_->enum_type_count(); ++i) {
+    const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+    FixOptionsForEnum(enum_descriptor);
+  }
+  // Prints expressions that set the options for all top level extensions.
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    const FieldDescriptor& field = *file_->extension(i);
+    FixOptionsForField(field);
+  }
+  // Prints expressions that set the options for all messages, nested enums,
+  // nested extensions and message fields.
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    FixOptionsForMessage(*file_->message_type(i));
+  }
+}
+
+// Prints expressions that set the options for an enum descriptor and its
+// value descriptors.
+void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
+  string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
+  string enum_options = OptionsValue(
+      "EnumOptions", enum_descriptor.options().SerializeAsString());
+  if (enum_options != "None") {
+    PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
+  }
+  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+    const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
+    string value_options = OptionsValue(
+        "EnumValueOptions", value_descriptor.options().SerializeAsString());
+    if (value_options != "None") {
+      PrintDescriptorOptionsFixingCode(
+          StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
+                       value_descriptor.name().c_str()),
+          value_options, printer_);
+    }
+  }
+}
+
+// Prints expressions that set the options for field descriptors (including
+// extensions).
+void Generator::FixOptionsForField(
+    const FieldDescriptor& field) const {
+  string field_options = OptionsValue(
+      "FieldOptions", field.options().SerializeAsString());
+  if (field_options != "None") {
+    string field_name;
+    if (field.is_extension()) {
+      if (field.extension_scope() == NULL) {
+        // Top level extensions.
+        field_name = field.name();
+      } else {
+        field_name = FieldReferencingExpression(
+            field.extension_scope(), field, "extensions_by_name");
+      }
+    } else {
+      field_name = FieldReferencingExpression(
+          field.containing_type(), field, "fields_by_name");
+    }
+    PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
+  }
+}
+
+// Prints expressions that set the options for a message and all its inner
+// types (nested messages, nested enums, extensions, fields).
+void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
+  // Nested messages.
+  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+    FixOptionsForMessage(*descriptor.nested_type(i));
+  }
+  // Enums.
+  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+    FixOptionsForEnum(*descriptor.enum_type(i));
+  }
+  // Fields.
+  for (int i = 0; i < descriptor.field_count(); ++i) {
+    const FieldDescriptor& field = *descriptor.field(i);
+    FixOptionsForField(field);
+  }
+  // Extensions.
+  for (int i = 0; i < descriptor.extension_count(); ++i) {
+    const FieldDescriptor& field = *descriptor.extension(i);
+    FixOptionsForField(field);
+  }
+  // Message option for this message.
+  string message_options = OptionsValue(
+      "MessageOptions", descriptor.options().SerializeAsString());
+  if (message_options != "None") {
+    string descriptor_name = ModuleLevelDescriptorName(descriptor);
+    PrintDescriptorOptionsFixingCode(descriptor_name,
+                                     message_options,
+                                     printer_);
+  }
+}
+
+// If a dependency forwards other files through public dependencies, let's
+// copy over the corresponding module aliases.
+void Generator::CopyPublicDependenciesAliases(
+    const string& copy_from, const FileDescriptor* file) const {
+  for (int i = 0; i < file->public_dependency_count(); ++i) {
+    string module_alias = ModuleAlias(file->public_dependency(i)->name());
+    printer_->Print("$alias$ = $copy_from$.$alias$\n", "alias", module_alias,
+                    "copy_from", copy_from);
+    CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
+  }
+}
+
+}  // namespace python
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.h
new file mode 100644
index 0000000..aa0f5fc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_generator.h
@@ -0,0 +1,172 @@
+// 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.
+
+// Author: robinson@google.com (Will Robinson)
+//
+// Generates Python code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class EnumValueDescriptor;
+class FieldDescriptor;
+class ServiceDescriptor;
+
+namespace io { class Printer; }
+
+namespace compiler {
+namespace python {
+
+// CodeGenerator implementation for generated Python protocol buffer classes.
+// If you create your own protocol compiler binary and you want it to support
+// Python output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+  Generator();
+  virtual ~Generator();
+
+  // CodeGenerator methods.
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* generator_context,
+                        string* error) const;
+
+ private:
+  void PrintImports() const;
+  void PrintFileDescriptor() const;
+  void PrintTopLevelEnums() const;
+  void PrintAllNestedEnumsInFile() const;
+  void PrintNestedEnums(const Descriptor& descriptor) const;
+  void PrintEnum(const EnumDescriptor& enum_descriptor) const;
+
+  void PrintTopLevelExtensions() const;
+
+  void PrintFieldDescriptor(
+      const FieldDescriptor& field, bool is_extension) const;
+  void PrintFieldDescriptorsInDescriptor(
+      const Descriptor& message_descriptor,
+      bool is_extension,
+      const string& list_variable_name,
+      int (Descriptor::*CountFn)() const,
+      const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const;
+  void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const;
+  void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const;
+  void PrintMessageDescriptors() const;
+  void PrintDescriptor(const Descriptor& message_descriptor) const;
+  void PrintNestedDescriptors(const Descriptor& containing_descriptor) const;
+
+  void PrintMessages() const;
+  void PrintMessage(const Descriptor& message_descriptor, const string& prefix,
+                    vector<string>* to_register) const;
+  void PrintNestedMessages(const Descriptor& containing_descriptor,
+                           const string& prefix,
+                           vector<string>* to_register) const;
+
+  void FixForeignFieldsInDescriptors() const;
+  void FixForeignFieldsInDescriptor(
+      const Descriptor& descriptor,
+      const Descriptor* containing_descriptor) const;
+  void FixForeignFieldsInField(const Descriptor* containing_type,
+                               const FieldDescriptor& field,
+                               const string& python_dict_name) const;
+  void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
+  void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const;
+  void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const;
+  string FieldReferencingExpression(const Descriptor* containing_type,
+                                    const FieldDescriptor& field,
+                                    const string& python_dict_name) const;
+  template <typename DescriptorT>
+  void FixContainingTypeInDescriptor(
+      const DescriptorT& descriptor,
+      const Descriptor* containing_descriptor) const;
+
+  void FixForeignFieldsInExtensions() const;
+  void FixForeignFieldsInExtension(
+      const FieldDescriptor& extension_field) const;
+  void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
+
+  void PrintServices() const;
+  void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
+  void PrintServiceClass(const ServiceDescriptor& descriptor) const;
+  void PrintServiceStub(const ServiceDescriptor& descriptor) const;
+  void PrintDescriptorKeyAndModuleName(
+      const ServiceDescriptor& descriptor) const ;
+
+  void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
+  string OptionsValue(const string& class_name,
+                      const string& serialized_options) const;
+  bool GeneratingDescriptorProto() const;
+
+  template <typename DescriptorT>
+  string ModuleLevelDescriptorName(const DescriptorT& descriptor) const;
+  string ModuleLevelMessageName(const Descriptor& descriptor) const;
+  string ModuleLevelServiceDescriptorName(
+      const ServiceDescriptor& descriptor) const;
+
+  template <typename DescriptorT, typename DescriptorProtoT>
+  void PrintSerializedPbInterval(
+      const DescriptorT& descriptor, DescriptorProtoT& proto) const;
+
+  void FixAllDescriptorOptions() const;
+  void FixOptionsForField(const FieldDescriptor& field) const;
+  void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
+  void FixOptionsForMessage(const Descriptor& descriptor) const;
+
+  void CopyPublicDependenciesAliases(
+      const string& copy_from, const FileDescriptor* file) const;
+
+  // Very coarse-grained lock to ensure that Generate() is reentrant.
+  // Guards file_, printer_ and file_descriptor_serialized_.
+  mutable Mutex mutex_;
+  mutable const FileDescriptor* file_;  // Set in Generate().  Under mutex_.
+  mutable string file_descriptor_serialized_;
+  mutable io::Printer* printer_;  // Set in Generate().  Under mutex_.
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
+};
+
+}  // namespace python
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_plugin_unittest.cc
new file mode 100644
index 0000000..23f2449
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -0,0 +1,122 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/python/python_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        GeneratorContext* context,
+                        string* error) const {
+    TryInsert("test_pb2.py", "imports", context);
+    TryInsert("test_pb2.py", "module_scope", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context);
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 GeneratorContext* context) const {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        context->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(PythonPluginTest, PluginTest) {
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
+                             "syntax = \"proto2\";\n"
+                             "package foo;\n"
+                             "message Bar {\n"
+                             "  message Baz {}\n"
+                             "}\n",
+                             true));
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  python::Generator python_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--python_out", &python_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string python_out = "--python_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    python_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace python
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.proto b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
new file mode 100644
index 0000000..42d82a6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
@@ -0,0 +1,67 @@
+syntax = "proto3";
+
+package A.B.C;
+
+message TestMessage {
+  int32 optional_int32 = 1;
+  int64 optional_int64 = 2;
+  uint32 optional_uint32 = 3;
+  uint64 optional_uint64 = 4;
+  bool optional_bool = 5;
+  double optional_double = 6;
+  float optional_float = 7;
+  string optional_string = 8;
+  bytes optional_bytes = 9;
+  TestEnum optional_enum = 10;
+  TestMessage optional_msg = 11;
+
+  repeated int32 repeated_int32 = 21;
+  repeated int64 repeated_int64 = 22;
+  repeated uint32 repeated_uint32 = 23;
+  repeated uint64 repeated_uint64 = 24;
+  repeated bool repeated_bool = 25;
+  repeated double repeated_double = 26;
+  repeated float repeated_float = 27;
+  repeated string repeated_string = 28;
+  repeated bytes repeated_bytes = 29;
+  repeated TestEnum repeated_enum = 30;
+  repeated TestMessage repeated_msg = 31;
+
+  oneof my_oneof {
+    int32 oneof_int32 = 41;
+    int64 oneof_int64 = 42;
+    uint32 oneof_uint32 = 43;
+    uint64 oneof_uint64 = 44;
+    bool oneof_bool = 45;
+    double oneof_double = 46;
+    float oneof_float = 47;
+    string oneof_string = 48;
+    bytes oneof_bytes = 49;
+    TestEnum oneof_enum = 50;
+    TestMessage oneof_msg = 51;
+  }
+
+  map<int32, string> map_int32_string = 61;
+  map<int64, string> map_int64_string = 62;
+  map<uint32, string> map_uint32_string = 63;
+  map<uint64, string> map_uint64_string = 64;
+  map<bool, string> map_bool_string = 65;
+  map<string, string> map_string_string = 66;
+  map<string, TestMessage> map_string_msg = 67;
+  map<string, TestEnum> map_string_enum = 68;
+  map<string, int32> map_string_int32 = 69;
+  map<string, bool> map_string_bool = 70;
+
+  message NestedMessage {
+    int32 foo = 1;
+  }
+
+  NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+  Default = 0;
+  A = 1;
+  B = 2;
+  C = 3;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
new file mode 100644
index 0000000..49b23fb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
@@ -0,0 +1,74 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: ruby_generated_code.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "A.B.C.TestMessage" do
+    optional :optional_int32, :int32, 1
+    optional :optional_int64, :int64, 2
+    optional :optional_uint32, :uint32, 3
+    optional :optional_uint64, :uint64, 4
+    optional :optional_bool, :bool, 5
+    optional :optional_double, :double, 6
+    optional :optional_float, :float, 7
+    optional :optional_string, :string, 8
+    optional :optional_bytes, :bytes, 9
+    optional :optional_enum, :enum, 10, "A.B.C.TestEnum"
+    optional :optional_msg, :message, 11, "A.B.C.TestMessage"
+    repeated :repeated_int32, :int32, 21
+    repeated :repeated_int64, :int64, 22
+    repeated :repeated_uint32, :uint32, 23
+    repeated :repeated_uint64, :uint64, 24
+    repeated :repeated_bool, :bool, 25
+    repeated :repeated_double, :double, 26
+    repeated :repeated_float, :float, 27
+    repeated :repeated_string, :string, 28
+    repeated :repeated_bytes, :bytes, 29
+    repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
+    repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
+    map :map_int32_string, :int32, :string, 61
+    map :map_int64_string, :int64, :string, 62
+    map :map_uint32_string, :uint32, :string, 63
+    map :map_uint64_string, :uint64, :string, 64
+    map :map_bool_string, :bool, :string, 65
+    map :map_string_string, :string, :string, 66
+    map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage"
+    map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum"
+    map :map_string_int32, :string, :int32, 69
+    map :map_string_bool, :string, :bool, 70
+    optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
+    oneof :my_oneof do
+      optional :oneof_int32, :int32, 41
+      optional :oneof_int64, :int64, 42
+      optional :oneof_uint32, :uint32, 43
+      optional :oneof_uint64, :uint64, 44
+      optional :oneof_bool, :bool, 45
+      optional :oneof_double, :double, 46
+      optional :oneof_float, :float, 47
+      optional :oneof_string, :string, 48
+      optional :oneof_bytes, :bytes, 49
+      optional :oneof_enum, :enum, 50, "A.B.C.TestEnum"
+      optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
+    end
+  end
+  add_message "A.B.C.TestMessage.NestedMessage" do
+    optional :foo, :int32, 1
+  end
+  add_enum "A.B.C.TestEnum" do
+    value :Default, 0
+    value :A, 1
+    value :B, 2
+    value :C, 3
+  end
+end
+
+module A
+  module B
+    module C
+      TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
+      TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
+      TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
+    end
+  end
+end
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.cc
new file mode 100644
index 0000000..92c76fb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -0,0 +1,463 @@
+// 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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+
+// Forward decls.
+std::string IntToString(int32 value);
+std::string StripDotProto(const std::string& proto_file);
+std::string LabelForField(google::protobuf::FieldDescriptor* field);
+std::string TypeName(google::protobuf::FieldDescriptor* field);
+void GenerateMessage(const google::protobuf::Descriptor* message,
+                     google::protobuf::io::Printer* printer);
+void GenerateEnum(const google::protobuf::EnumDescriptor* en,
+                  google::protobuf::io::Printer* printer);
+void GenerateMessageAssignment(
+    const std::string& prefix,
+    const google::protobuf::Descriptor* message,
+    google::protobuf::io::Printer* printer);
+void GenerateEnumAssignment(
+    const std::string& prefix,
+    const google::protobuf::EnumDescriptor* en,
+    google::protobuf::io::Printer* printer);
+
+std::string IntToString(int32 value) {
+  std::ostringstream os;
+  os << value;
+  return os.str();
+}
+
+std::string StripDotProto(const std::string& proto_file) {
+  int lastindex = proto_file.find_last_of(".");
+  return proto_file.substr(0, lastindex);
+}
+
+std::string GetOutputFilename(const std::string& proto_file) {
+  return StripDotProto(proto_file) + ".rb";
+}
+
+std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
+  switch (field->label()) {
+    case FieldDescriptor::LABEL_OPTIONAL: return "optional";
+    case FieldDescriptor::LABEL_REQUIRED: return "required";
+    case FieldDescriptor::LABEL_REPEATED: return "repeated";
+    default: assert(false); return "";
+  }
+}
+
+std::string TypeName(const google::protobuf::FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32: return "int32";
+    case FieldDescriptor::TYPE_INT64: return "int64";
+    case FieldDescriptor::TYPE_UINT32: return "uint32";
+    case FieldDescriptor::TYPE_UINT64: return "uint64";
+    case FieldDescriptor::TYPE_SINT32: return "sint32";
+    case FieldDescriptor::TYPE_SINT64: return "sint64";
+    case FieldDescriptor::TYPE_FIXED32: return "fixed32";
+    case FieldDescriptor::TYPE_FIXED64: return "fixed64";
+    case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
+    case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
+    case FieldDescriptor::TYPE_DOUBLE: return "double";
+    case FieldDescriptor::TYPE_FLOAT: return "float";
+    case FieldDescriptor::TYPE_BOOL: return "bool";
+    case FieldDescriptor::TYPE_ENUM: return "enum";
+    case FieldDescriptor::TYPE_STRING: return "string";
+    case FieldDescriptor::TYPE_BYTES: return "bytes";
+    case FieldDescriptor::TYPE_MESSAGE: return "message";
+    case FieldDescriptor::TYPE_GROUP: return "group";
+    default: assert(false); return "";
+  }
+}
+
+void GenerateField(const google::protobuf::FieldDescriptor* field,
+                   google::protobuf::io::Printer* printer) {
+
+  if (field->is_map()) {
+    const FieldDescriptor* key_field =
+        field->message_type()->FindFieldByNumber(1);
+    const FieldDescriptor* value_field =
+        field->message_type()->FindFieldByNumber(2);
+
+    printer->Print(
+      "map :$name$, :$key_type$, :$value_type$, $number$",
+      "name", field->name(),
+      "key_type", TypeName(key_field),
+      "value_type", TypeName(value_field),
+      "number", IntToString(field->number()));
+
+    if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+        "subtype", value_field->message_type()->full_name());
+    } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+        "subtype", value_field->enum_type()->full_name());
+    } else {
+      printer->Print("\n");
+    }
+  } else {
+
+    printer->Print(
+      "$label$ :$name$, ",
+      "label", LabelForField(field),
+      "name", field->name());
+    printer->Print(
+      ":$type$, $number$",
+      "type", TypeName(field),
+      "number", IntToString(field->number()));
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+       "subtype", field->message_type()->full_name());
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      printer->Print(
+        ", \"$subtype$\"\n",
+        "subtype", field->enum_type()->full_name());
+    } else {
+      printer->Print("\n");
+    }
+  }
+}
+
+void GenerateOneof(const google::protobuf::OneofDescriptor* oneof,
+                   google::protobuf::io::Printer* printer) {
+  printer->Print(
+      "oneof :$name$ do\n",
+      "name", oneof->name());
+  printer->Indent();
+
+  for (int i = 0; i < oneof->field_count(); i++) {
+    const FieldDescriptor* field = oneof->field(i);
+    GenerateField(field, printer);
+  }
+
+  printer->Outdent();
+  printer->Print("end\n");
+}
+
+void GenerateMessage(const google::protobuf::Descriptor* message,
+                     google::protobuf::io::Printer* printer) {
+
+  // Don't generate MapEntry messages -- we use the Ruby extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+
+  printer->Print(
+    "add_message \"$name$\" do\n",
+    "name", message->full_name());
+  printer->Indent();
+
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if (!field->containing_oneof()) {
+      GenerateField(field, printer);
+    }
+  }
+
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    GenerateOneof(oneof, printer);
+  }
+
+  printer->Outdent();
+  printer->Print("end\n");
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateMessage(message->nested_type(i), printer);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateEnum(message->enum_type(i), printer);
+  }
+}
+
+void GenerateEnum(const google::protobuf::EnumDescriptor* en,
+                  google::protobuf::io::Printer* printer) {
+  printer->Print(
+    "add_enum \"$name$\" do\n",
+    "name", en->full_name());
+  printer->Indent();
+
+  for (int i = 0; i < en->value_count(); i++) {
+    const EnumValueDescriptor* value = en->value(i);
+    printer->Print(
+      "value :$name$, $number$\n",
+      "name", value->name(),
+      "number", IntToString(value->number()));
+  }
+
+  printer->Outdent();
+  printer->Print(
+    "end\n");
+}
+
+// Module names, class names, and enum value names need to be Ruby constants,
+// which must start with a capital letter.
+std::string RubifyConstant(const std::string& name) {
+  std::string ret = name;
+  if (!ret.empty()) {
+    if (ret[0] >= 'a' && ret[0] <= 'z') {
+      // If it starts with a lowercase letter, capitalize it.
+      ret[0] = ret[0] - 'a' + 'A';
+    } else if (ret[0] < 'A' || ret[0] > 'Z') {
+      // Otherwise (e.g. if it begins with an underscore), we need to come up
+      // with some prefix that starts with a capital letter. We could be smarter
+      // here, e.g. try to strip leading underscores, but this may cause other
+      // problems if the user really intended the name. So let's just prepend a
+      // well-known suffix.
+      ret = "PB_" + ret;
+    }
+  }
+  return ret;
+}
+
+void GenerateMessageAssignment(
+    const std::string& prefix,
+    const google::protobuf::Descriptor* message,
+    google::protobuf::io::Printer* printer) {
+
+  // Don't generate MapEntry messages -- we use the Ruby extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+
+  printer->Print(
+    "$prefix$$name$ = ",
+    "prefix", prefix,
+    "name", RubifyConstant(message->name()));
+  printer->Print(
+    "Google::Protobuf::DescriptorPool.generated_pool."
+    "lookup(\"$full_name$\").msgclass\n",
+    "full_name", message->full_name());
+
+  std::string nested_prefix = prefix + message->name() + "::";
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer);
+  }
+}
+
+void GenerateEnumAssignment(
+    const std::string& prefix,
+    const google::protobuf::EnumDescriptor* en,
+    google::protobuf::io::Printer* printer) {
+  printer->Print(
+    "$prefix$$name$ = ",
+    "prefix", prefix,
+    "name", RubifyConstant(en->name()));
+  printer->Print(
+    "Google::Protobuf::DescriptorPool.generated_pool."
+    "lookup(\"$full_name$\").enummodule\n",
+    "full_name", en->full_name());
+}
+
+int GeneratePackageModules(
+    std::string package_name,
+    google::protobuf::io::Printer* printer) {
+  int levels = 0;
+  while (!package_name.empty()) {
+    size_t dot_index = package_name.find(".");
+    string component;
+    if (dot_index == string::npos) {
+      component = package_name;
+      package_name = "";
+    } else {
+      component = package_name.substr(0, dot_index);
+      package_name = package_name.substr(dot_index + 1);
+    }
+    component = RubifyConstant(component);
+    printer->Print(
+      "module $name$\n",
+      "name", component);
+    printer->Indent();
+    levels++;
+  }
+  return levels;
+}
+
+void EndPackageModules(
+    int levels,
+    google::protobuf::io::Printer* printer) {
+  while (levels > 0) {
+    levels--;
+    printer->Outdent();
+    printer->Print(
+      "end\n");
+  }
+}
+
+bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file,
+                      string* error) {
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+         field->message_type()->file() == file) ||
+        (field->type() == FieldDescriptor::TYPE_ENUM &&
+         field->enum_type()->file() == file)) {
+      *error = "proto3 message field " + field->full_name() + " in file " +
+               file->name() + " has a dependency on a type from proto2 file " +
+               file->name() +
+               ".  Ruby doesn't support proto2 yet, so we must fail.";
+      return true;
+    }
+  }
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    if (UsesTypeFromFile(message->nested_type(i), file, error)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Ruby doesn't currently support proto2.  This causes a failure even for proto3
+// files that import proto2.  But in some cases, the proto2 file is only being
+// imported to extend another proto2 message.  The prime example is declaring
+// custom options by extending FileOptions/FieldOptions/etc.
+//
+// If the proto3 messages don't have any proto2 submessages, it is safe to omit
+// the dependency completely.  Users won't be able to use any proto2 extensions,
+// but they already couldn't because proto2 messages aren't supported.
+//
+// If/when we add proto2 support, we should remove this.
+bool MaybeEmitDependency(const FileDescriptor* import,
+                         const FileDescriptor* from,
+                         io::Printer* printer,
+                         string* error) {
+  if (import->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+    for (int i = 0; i < from->message_type_count(); i++) {
+      if (UsesTypeFromFile(from->message_type(i), import, error)) {
+        // Error text was already set by UsesTypeFromFile().
+        return false;
+      }
+    }
+
+    // Ok to omit this proto2 dependency -- so we won't print anything.
+    GOOGLE_LOG(WARNING) << "Omitting proto2 dependency '" << import->name()
+                        << "' from proto3 output file '"
+                        << GetOutputFilename(from->name())
+                        << "' because we don't support proto2 and no proto2 "
+                           "types from that file are being used.";
+    return true;
+  } else {
+    printer->Print(
+      "require '$name$'\n", "name", StripDotProto(import->name()));
+    return true;
+  }
+}
+
+bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
+                  string* error) {
+  printer->Print(
+    "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "# source: $filename$\n"
+    "\n",
+    "filename", file->name());
+
+  printer->Print(
+    "require 'google/protobuf'\n\n");
+
+  for (int i = 0; i < file->dependency_count(); i++) {
+    if (!MaybeEmitDependency(file->dependency(i), file, printer, error)) {
+      return false;
+    }
+  }
+
+  printer->Print(
+    "Google::Protobuf::DescriptorPool.generated_pool.build do\n");
+  printer->Indent();
+  for (int i = 0; i < file->message_type_count(); i++) {
+    GenerateMessage(file->message_type(i), printer);
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    GenerateEnum(file->enum_type(i), printer);
+  }
+  printer->Outdent();
+  printer->Print(
+    "end\n\n");
+
+  int levels = GeneratePackageModules(file->package(), printer);
+  for (int i = 0; i < file->message_type_count(); i++) {
+    GenerateMessageAssignment("", file->message_type(i), printer);
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    GenerateEnumAssignment("", file->enum_type(i), printer);
+  }
+  EndPackageModules(levels, printer);
+  return true;
+}
+
+bool Generator::Generate(
+    const FileDescriptor* file,
+    const string& parameter,
+    GeneratorContext* generator_context,
+    string* error) const {
+
+  if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+    *error =
+        "Can only generate Ruby code for proto3 .proto files.\n"
+        "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
+    return false;
+  }
+
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(GetOutputFilename(file->name())));
+  io::Printer printer(output.get(), '$');
+
+  return GenerateFile(file, &printer, error);
+}
+
+}  // namespace ruby
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.h
new file mode 100644
index 0000000..75555c3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -0,0 +1,58 @@
+// 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_COMPILER_RUBY_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+
+class LIBPROTOC_EXPORT Generator
+    : public google::protobuf::compiler::CodeGenerator {
+  virtual bool Generate(
+      const FileDescriptor* file,
+      const string& parameter,
+      GeneratorContext* generator_context,
+      string* error) const;
+};
+
+}  // namespace ruby
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
new file mode 100644
index 0000000..1b04cb3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include <memory>
+
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+namespace {
+
+string FindRubyTestDir(const string& file) {
+  // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc.
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
+  string prefix = ".";
+  while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) {
+    if (!File::Exists(prefix)) {
+      GOOGLE_LOG(FATAL)
+          << "Could not find Ruby test directory. Please run tests from "
+             "somewhere within the protobuf source package.";
+    }
+    prefix += "/..";
+  }
+  return prefix + "/src/google/protobuf/compiler/ruby";
+#else
+  return "third_party/protobuf/src/google/protobuf/compiler/ruby";
+#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
+}
+
+// This test is a simple golden-file test over the output of the Ruby code
+// generator. When we make changes to the Ruby extension and alter the Ruby code
+// generator to use those changes, we should (i) manually test the output of the
+// code generator with the extension, and (ii) update the golden output above.
+// Some day, we may integrate build systems between protoc and the language
+// extensions to the point where we can do this test in a more automated way.
+
+TEST(RubyGeneratorTest, GeneratorTest) {
+  string ruby_tests = FindRubyTestDir("/ruby_generated_code.proto");
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  ruby::Generator ruby_generator;
+  cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
+
+  // Copy generated_code.proto to the temporary test directory.
+  string test_input;
+  GOOGLE_CHECK_OK(File::GetContents(
+      ruby_tests + "/ruby_generated_code.proto",
+      &test_input,
+      true));
+  GOOGLE_CHECK_OK(File::SetContents(
+      TestTempDir() + "/ruby_generated_code.proto",
+      test_input,
+      true));
+
+  // Invoke the proto compiler (we will be inside TestTempDir() at this point).
+  string ruby_out = "--ruby_out=" + TestTempDir();
+  string proto_path = "--proto_path=" + TestTempDir();
+  const char* argv[] = {
+    "protoc",
+    ruby_out.c_str(),
+    proto_path.c_str(),
+    "ruby_generated_code.proto",
+  };
+
+  EXPECT_EQ(0, cli.Run(4, argv));
+
+  // Load the generated output and compare to the expected result.
+  string output;
+  GOOGLE_CHECK_OK(File::GetContents(
+      TestTempDir() + "/ruby_generated_code.rb",
+      &output,
+      true));
+  string expected_output;
+  GOOGLE_CHECK_OK(File::GetContents(
+      ruby_tests + "/ruby_generated_code.rb",
+      &expected_output,
+      true));
+  EXPECT_EQ(expected_output, output);
+}
+
+}  // namespace
+}  // namespace ruby
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.cc
new file mode 100644
index 0000000..6e25866
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.cc
@@ -0,0 +1,465 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/subprocess.h>
+
+#include <algorithm>
+#include <iostream>
+
+#ifndef _WIN32
+#include <errno.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <signal.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/substitute.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#ifdef _WIN32
+
+static void CloseHandleOrDie(HANDLE handle) {
+  if (!CloseHandle(handle)) {
+    GOOGLE_LOG(FATAL) << "CloseHandle: "
+                      << Subprocess::Win32ErrorMessage(GetLastError());
+  }
+}
+
+Subprocess::Subprocess()
+    : process_start_error_(ERROR_SUCCESS),
+      child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {}
+
+Subprocess::~Subprocess() {
+  if (child_stdin_ != NULL) {
+    CloseHandleOrDie(child_stdin_);
+  }
+  if (child_stdout_ != NULL) {
+    CloseHandleOrDie(child_stdout_);
+  }
+}
+
+void Subprocess::Start(const string& program, SearchMode search_mode) {
+  // Create the pipes.
+  HANDLE stdin_pipe_read;
+  HANDLE stdin_pipe_write;
+  HANDLE stdout_pipe_read;
+  HANDLE stdout_pipe_write;
+
+  if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) {
+    GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+  }
+  if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) {
+    GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+  }
+
+  // Make child side of the pipes inheritable.
+  if (!SetHandleInformation(stdin_pipe_read,
+                            HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
+    GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+                      << Win32ErrorMessage(GetLastError());
+  }
+  if (!SetHandleInformation(stdout_pipe_write,
+                            HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
+    GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+                      << Win32ErrorMessage(GetLastError());
+  }
+
+  // Setup STARTUPINFO to redirect handles.
+  STARTUPINFOA startup_info;
+  ZeroMemory(&startup_info, sizeof(startup_info));
+  startup_info.cb = sizeof(startup_info);
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = stdin_pipe_read;
+  startup_info.hStdOutput = stdout_pipe_write;
+  startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+  if (startup_info.hStdError == INVALID_HANDLE_VALUE) {
+    GOOGLE_LOG(FATAL) << "GetStdHandle: "
+                      << Win32ErrorMessage(GetLastError());
+  }
+
+  // CreateProcess() mutates its second parameter.  WTF?
+  char* name_copy = strdup(program.c_str());
+
+  // Create the process.
+  PROCESS_INFORMATION process_info;
+
+  if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
+                     (search_mode == SEARCH_PATH) ? name_copy : NULL,
+                     NULL,  // process security attributes
+                     NULL,  // thread security attributes
+                     TRUE,  // inherit handles?
+                     0,     // obscure creation flags
+                     NULL,  // environment (inherit from parent)
+                     NULL,  // current directory (inherit from parent)
+                     &startup_info,
+                     &process_info)) {
+    child_handle_ = process_info.hProcess;
+    CloseHandleOrDie(process_info.hThread);
+    child_stdin_ = stdin_pipe_write;
+    child_stdout_ = stdout_pipe_read;
+  } else {
+    process_start_error_ = GetLastError();
+    CloseHandleOrDie(stdin_pipe_write);
+    CloseHandleOrDie(stdout_pipe_read);
+  }
+
+  CloseHandleOrDie(stdin_pipe_read);
+  CloseHandleOrDie(stdout_pipe_write);
+  free(name_copy);
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+                             string* error) {
+  if (process_start_error_ != ERROR_SUCCESS) {
+    *error = Win32ErrorMessage(process_start_error_);
+    return false;
+  }
+
+  GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first.";
+
+  string input_data = input.SerializeAsString();
+  string output_data;
+
+  int input_pos = 0;
+
+  while (child_stdout_ != NULL) {
+    HANDLE handles[2];
+    int handle_count = 0;
+
+    if (child_stdin_ != NULL) {
+      handles[handle_count++] = child_stdin_;
+    }
+    if (child_stdout_ != NULL) {
+      handles[handle_count++] = child_stdout_;
+    }
+
+    DWORD wait_result =
+        WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
+
+    HANDLE signaled_handle = NULL;
+    if (wait_result >= WAIT_OBJECT_0 &&
+        wait_result < WAIT_OBJECT_0 + handle_count) {
+      signaled_handle = handles[wait_result - WAIT_OBJECT_0];
+    } else if (wait_result == WAIT_FAILED) {
+      GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: "
+                        << Win32ErrorMessage(GetLastError());
+    } else {
+      GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: "
+                        << wait_result;
+    }
+
+    if (signaled_handle == child_stdin_) {
+      DWORD n;
+      if (!WriteFile(child_stdin_,
+                     input_data.data() + input_pos,
+                     input_data.size() - input_pos,
+                     &n, NULL)) {
+        // Child closed pipe.  Presumably it will report an error later.
+        // Pretend we're done for now.
+        input_pos = input_data.size();
+      } else {
+        input_pos += n;
+      }
+
+      if (input_pos == input_data.size()) {
+        // We're done writing.  Close.
+        CloseHandleOrDie(child_stdin_);
+        child_stdin_ = NULL;
+      }
+    } else if (signaled_handle == child_stdout_) {
+      char buffer[4096];
+      DWORD n;
+
+      if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) {
+        // We're done reading.  Close.
+        CloseHandleOrDie(child_stdout_);
+        child_stdout_ = NULL;
+      } else {
+        output_data.append(buffer, n);
+      }
+    }
+  }
+
+  if (child_stdin_ != NULL) {
+    // Child did not finish reading input before it closed the output.
+    // Presumably it exited with an error.
+    CloseHandleOrDie(child_stdin_);
+    child_stdin_ = NULL;
+  }
+
+  DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE);
+
+  if (wait_result == WAIT_FAILED) {
+    GOOGLE_LOG(FATAL) << "WaitForSingleObject: "
+                      << Win32ErrorMessage(GetLastError());
+  } else if (wait_result != WAIT_OBJECT_0) {
+    GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: "
+                      << wait_result;
+  }
+
+  DWORD exit_code;
+  if (!GetExitCodeProcess(child_handle_, &exit_code)) {
+    GOOGLE_LOG(FATAL) << "GetExitCodeProcess: "
+                      << Win32ErrorMessage(GetLastError());
+  }
+
+  CloseHandleOrDie(child_handle_);
+  child_handle_ = NULL;
+
+  if (exit_code != 0) {
+    *error = strings::Substitute(
+        "Plugin failed with status code $0.", exit_code);
+    return false;
+  }
+
+  if (!output->ParseFromString(output_data)) {
+    *error = "Plugin output is unparseable: " + CEscape(output_data);
+    return false;
+  }
+
+  return true;
+}
+
+string Subprocess::Win32ErrorMessage(DWORD error_code) {
+  char* message;
+
+  // WTF?
+  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                FORMAT_MESSAGE_FROM_SYSTEM |
+                FORMAT_MESSAGE_IGNORE_INSERTS,
+                NULL, error_code, 0,
+                (LPTSTR)&message,  // NOT A BUG!
+                0, NULL);
+
+  string result = message;
+  LocalFree(message);
+  return result;
+}
+
+// ===================================================================
+
+#else  // _WIN32
+
+Subprocess::Subprocess()
+    : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {}
+
+Subprocess::~Subprocess() {
+  if (child_stdin_ != -1) {
+    close(child_stdin_);
+  }
+  if (child_stdout_ != -1) {
+    close(child_stdout_);
+  }
+}
+
+void Subprocess::Start(const string& program, SearchMode search_mode) {
+  // Note that we assume that there are no other threads, thus we don't have to
+  // do crazy stuff like using socket pairs or avoiding libc locks.
+
+  // [0] is read end, [1] is write end.
+  int stdin_pipe[2];
+  int stdout_pipe[2];
+
+  GOOGLE_CHECK(pipe(stdin_pipe) != -1);
+  GOOGLE_CHECK(pipe(stdout_pipe) != -1);
+
+  char* argv[2] = { strdup(program.c_str()), NULL };
+
+  child_pid_ = fork();
+  if (child_pid_ == -1) {
+    GOOGLE_LOG(FATAL) << "fork: " << strerror(errno);
+  } else if (child_pid_ == 0) {
+    // We are the child.
+    dup2(stdin_pipe[0], STDIN_FILENO);
+    dup2(stdout_pipe[1], STDOUT_FILENO);
+
+    close(stdin_pipe[0]);
+    close(stdin_pipe[1]);
+    close(stdout_pipe[0]);
+    close(stdout_pipe[1]);
+
+    switch (search_mode) {
+      case SEARCH_PATH:
+        execvp(argv[0], argv);
+        break;
+      case EXACT_NAME:
+        execv(argv[0], argv);
+        break;
+    }
+
+    // Write directly to STDERR_FILENO to avoid stdio code paths that may do
+    // stuff that is unsafe here.
+    int ignored;
+    ignored = write(STDERR_FILENO, argv[0], strlen(argv[0]));
+    const char* message = ": program not found or is not executable\n";
+    ignored = write(STDERR_FILENO, message, strlen(message));
+    (void) ignored;
+
+    // Must use _exit() rather than exit() to avoid flushing output buffers
+    // that will also be flushed by the parent.
+    _exit(1);
+  } else {
+    free(argv[0]);
+
+    close(stdin_pipe[0]);
+    close(stdout_pipe[1]);
+
+    child_stdin_ = stdin_pipe[1];
+    child_stdout_ = stdout_pipe[0];
+  }
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+                             string* error) {
+
+  GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
+
+  // The "sighandler_t" typedef is GNU-specific, so define our own.
+  typedef void SignalHandler(int);
+
+  // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us.
+  SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN);
+
+  string input_data = input.SerializeAsString();
+  string output_data;
+
+  int input_pos = 0;
+  int max_fd = std::max(child_stdin_, child_stdout_);
+
+  while (child_stdout_ != -1) {
+    fd_set read_fds;
+    fd_set write_fds;
+    FD_ZERO(&read_fds);
+    FD_ZERO(&write_fds);
+    if (child_stdout_ != -1) {
+      FD_SET(child_stdout_, &read_fds);
+    }
+    if (child_stdin_ != -1) {
+      FD_SET(child_stdin_, &write_fds);
+    }
+
+    if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
+      if (errno == EINTR) {
+        // Interrupted by signal.  Try again.
+        continue;
+      } else {
+        GOOGLE_LOG(FATAL) << "select: " << strerror(errno);
+      }
+    }
+
+    if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) {
+      int n = write(child_stdin_, input_data.data() + input_pos,
+                                  input_data.size() - input_pos);
+      if (n < 0) {
+        // Child closed pipe.  Presumably it will report an error later.
+        // Pretend we're done for now.
+        input_pos = input_data.size();
+      } else {
+        input_pos += n;
+      }
+
+      if (input_pos == input_data.size()) {
+        // We're done writing.  Close.
+        close(child_stdin_);
+        child_stdin_ = -1;
+      }
+    }
+
+    if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) {
+      char buffer[4096];
+      int n = read(child_stdout_, buffer, sizeof(buffer));
+
+      if (n > 0) {
+        output_data.append(buffer, n);
+      } else {
+        // We're done reading.  Close.
+        close(child_stdout_);
+        child_stdout_ = -1;
+      }
+    }
+  }
+
+  if (child_stdin_ != -1) {
+    // Child did not finish reading input before it closed the output.
+    // Presumably it exited with an error.
+    close(child_stdin_);
+    child_stdin_ = -1;
+  }
+
+  int status;
+  while (waitpid(child_pid_, &status, 0) == -1) {
+    if (errno != EINTR) {
+      GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno);
+    }
+  }
+
+  // Restore SIGPIPE handling.
+  signal(SIGPIPE, old_pipe_handler);
+
+  if (WIFEXITED(status)) {
+    if (WEXITSTATUS(status) != 0) {
+      int error_code = WEXITSTATUS(status);
+      *error = strings::Substitute(
+          "Plugin failed with status code $0.", error_code);
+      return false;
+    }
+  } else if (WIFSIGNALED(status)) {
+    int signal = WTERMSIG(status);
+    *error = strings::Substitute(
+        "Plugin killed by signal $0.", signal);
+    return false;
+  } else {
+    *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
+    return false;
+  }
+
+  if (!output->ParseFromString(output_data)) {
+    *error = "Plugin output is unparseable: " + CEscape(output_data);
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // !_WIN32
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.h
new file mode 100644
index 0000000..2513863
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/subprocess.h
@@ -0,0 +1,108 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+#define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN   // right...
+#include <windows.h>
+#else  // _WIN32
+#include <sys/types.h>
+#include <unistd.h>
+#endif  // !_WIN32
+#include <google/protobuf/stubs/common.h>
+
+#include <string>
+
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace compiler {
+
+// Utility class for launching sub-processes.
+class LIBPROTOC_EXPORT Subprocess {
+ public:
+  Subprocess();
+  ~Subprocess();
+
+  enum SearchMode {
+    SEARCH_PATH,   // Use PATH environment variable.
+    EXACT_NAME     // Program is an exact file name; don't use the PATH.
+  };
+
+  // Start the subprocess.  Currently we don't provide a way to specify
+  // arguments as protoc plugins don't have any.
+  void Start(const string& program, SearchMode search_mode);
+
+  // Serialize the input message and pipe it to the subprocess's stdin, then
+  // close the pipe.  Meanwhile, read from the subprocess's stdout and parse
+  // the data into *output.  All this is done carefully to avoid deadlocks.
+  // Returns true if successful.  On any sort of error, returns false and sets
+  // *error to a description of the problem.
+  bool Communicate(const Message& input, Message* output, string* error);
+
+#ifdef _WIN32
+  // Given an error code, returns a human-readable error message.  This is
+  // defined here so that CommandLineInterface can share it.
+  static string Win32ErrorMessage(DWORD error_code);
+#endif
+
+ private:
+#ifdef _WIN32
+  DWORD process_start_error_;
+  HANDLE child_handle_;
+
+  // The file handles for our end of the child's pipes.  We close each and
+  // set it to NULL when no longer needed.
+  HANDLE child_stdin_;
+  HANDLE child_stdout_;
+
+#else  // _WIN32
+  pid_t child_pid_;
+
+  // The file descriptors for our end of the child's pipes.  We close each and
+  // set it to -1 when no longer needed.
+  int child_stdin_;
+  int child_stdout_;
+
+#endif  // !_WIN32
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/test_plugin.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/test_plugin.cc
new file mode 100644
index 0000000..4830fd7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/test_plugin.cc
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is a dummy code generator plugin used by
+// command_line_interface_unittest.
+
+#include <string>
+#include <stdlib.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
+#include <google/protobuf/stubs/strutil.h>
+
+int main(int argc, char* argv[]) {
+#ifdef _MSC_VER
+  // Don't print a silly message or stick a modal dialog box in my face,
+  // please.
+  _set_abort_behavior(0, ~0);
+#endif  // !_MSC_VER
+
+  google::protobuf::compiler::MockCodeGenerator generator("test_plugin");
+  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_output_unittest.sh b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_output_unittest.sh
new file mode 100755
index 0000000..6fc7136
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2009 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.
+
+# Author: kenton@google.com (Kenton Varda)
+#
+# Test protoc's zip output mode.
+
+fail() {
+  echo "$@" >&2
+  exit 1
+}
+
+TEST_TMPDIR=.
+PROTOC=./protoc
+
+echo '
+  syntax = "proto2";
+  option java_multiple_files = true;
+  option java_package = "test.jar";
+  option java_outer_classname = "Outer";
+  message Foo {}
+  message Bar {}
+' > $TEST_TMPDIR/testzip.proto
+
+$PROTOC \
+    --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \
+    --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \
+    || fail 'protoc failed.'
+
+echo "Testing output to zip..."
+if unzip -h > /dev/null; then
+  unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
+
+  grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'testzip.pb.cc not found in output zip.'
+  grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'testzip.pb.h not found in output zip.'
+  grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'testzip_pb2.py not found in output zip.'
+  grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \
+    && fail 'Zip file contained manifest.'
+else
+  echo "Warning:  'unzip' command not available.  Skipping test."
+fi
+
+echo "Testing output to jar..."
+if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
+  jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.'
+
+  grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Foo.java not found in output jar.'
+  grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Bar.java not found in output jar.'
+  grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Outer.java not found in output jar.'
+  grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Manifest not found in output jar.'
+else
+  echo "Warning:  'jar' command not available.  Skipping test."
+fi
+
+echo PASS
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.cc b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.cc
new file mode 100644
index 0000000..458cced
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.cc
@@ -0,0 +1,218 @@
+// 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.
+
+// 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.
+
+// Author: ambrose@google.com (Ambrose Feinstein),
+//         kenton@google.com (Kenton Varda)
+//
+// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+#include <google/protobuf/compiler/zip_writer.h>
+#include <google/protobuf/io/coded_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+static const uint32 kCRC32Table[256] = {
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+  0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+  0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+  0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+  0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+  0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+  0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+  0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+  0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+  0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32 ComputeCRC32(const string &buf) {
+  uint32 x = ~0U;
+  for (int i = 0; i < buf.size(); ++i) {
+    unsigned char c = buf[i];
+    x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
+  }
+  return ~x;
+}
+
+static void WriteShort(io::CodedOutputStream *out, uint16 val) {
+  uint8 p[2];
+  p[0] = static_cast<uint8>(val);
+  p[1] = static_cast<uint8>(val >> 8);
+  out->WriteRaw(p, 2);
+}
+
+ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output)
+  : raw_output_(raw_output) {}
+ZipWriter::~ZipWriter() {}
+
+bool ZipWriter::Write(const string& filename, const string& contents) {
+  FileInfo info;
+
+  info.name = filename;
+  uint16 filename_size = filename.size();
+  info.offset = raw_output_->ByteCount();
+  info.size = contents.size();
+  info.crc32 = ComputeCRC32(contents);
+
+  files_.push_back(info);
+
+  // write file header
+  io::CodedOutputStream output(raw_output_);
+  output.WriteLittleEndian32(0x04034b50);  // magic
+  WriteShort(&output, 10);  // version needed to extract
+  WriteShort(&output, 0);  // flags
+  WriteShort(&output, 0);  // compression method: stored
+  WriteShort(&output, 0);  // last modified time
+  WriteShort(&output, 0);  // last modified date
+  output.WriteLittleEndian32(info.crc32);  // crc-32
+  output.WriteLittleEndian32(info.size);  // compressed size
+  output.WriteLittleEndian32(info.size);  // uncompressed size
+  WriteShort(&output, filename_size);  // file name length
+  WriteShort(&output, 0);   // extra field length
+  output.WriteString(filename);  // file name
+  output.WriteString(contents);  // file data
+
+  return !output.HadError();
+}
+
+bool ZipWriter::WriteDirectory() {
+  uint16 num_entries = files_.size();
+  uint32 dir_ofs = raw_output_->ByteCount();
+
+  // write central directory
+  io::CodedOutputStream output(raw_output_);
+  for (int i = 0; i < num_entries; ++i) {
+    const string &filename = files_[i].name;
+    uint16 filename_size = filename.size();
+    uint32 crc32 = files_[i].crc32;
+    uint32 size = files_[i].size;
+    uint32 offset = files_[i].offset;
+
+    output.WriteLittleEndian32(0x02014b50);  // magic
+    WriteShort(&output, 10);  // version made by
+    WriteShort(&output, 10);  // version needed to extract
+    WriteShort(&output, 0);  // flags
+    WriteShort(&output, 0);  // compression method: stored
+    WriteShort(&output, 0);  // last modified time
+    WriteShort(&output, 0);  // last modified date
+    output.WriteLittleEndian32(crc32);  // crc-32
+    output.WriteLittleEndian32(size);  // compressed size
+    output.WriteLittleEndian32(size);  // uncompressed size
+    WriteShort(&output, filename_size);  // file name length
+    WriteShort(&output, 0);   // extra field length
+    WriteShort(&output, 0);   // file comment length
+    WriteShort(&output, 0);   // starting disk number
+    WriteShort(&output, 0);   // internal file attributes
+    output.WriteLittleEndian32(0);  // external file attributes
+    output.WriteLittleEndian32(offset);  // local header offset
+    output.WriteString(filename);  // file name
+  }
+  uint32 dir_len = output.ByteCount();
+
+  // write end of central directory marker
+  output.WriteLittleEndian32(0x06054b50);  // magic
+  WriteShort(&output, 0);  // disk number
+  WriteShort(&output, 0);  // disk with start of central directory
+  WriteShort(&output, num_entries);  // central directory entries (this disk)
+  WriteShort(&output, num_entries);  // central directory entries (total)
+  output.WriteLittleEndian32(dir_len);  // central directory byte size
+  output.WriteLittleEndian32(dir_ofs);  // central directory offset
+  WriteShort(&output, 0);   // comment length
+
+  return output.HadError();
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.h b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.h
new file mode 100644
index 0000000..602e508
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/compiler/zip_writer.h
@@ -0,0 +1,93 @@
+// 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.
+
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class ZipWriter {
+ public:
+  ZipWriter(io::ZeroCopyOutputStream* raw_output);
+  ~ZipWriter();
+
+  bool Write(const string& filename, const string& contents);
+  bool WriteDirectory();
+
+ private:
+  struct FileInfo {
+    string name;
+    uint32 offset;
+    uint32 size;
+    uint32 crc32;
+  };
+
+  io::ZeroCopyOutputStream* raw_output_;
+  vector<FileInfo> files_;
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor.cc b/src/third_party/protobuf-3/src/google/protobuf/descriptor.cc
new file mode 100644
index 0000000..56e11fa
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor.cc
@@ -0,0 +1,6276 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <limits>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/strtod.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+#undef PACKAGE  // autoheader #defines this.  :(
+
+namespace google {
+namespace protobuf {
+
+const FieldDescriptor::CppType
+FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
+  static_cast<CppType>(0),  // 0 is reserved for errors
+
+  CPPTYPE_DOUBLE,   // TYPE_DOUBLE
+  CPPTYPE_FLOAT,    // TYPE_FLOAT
+  CPPTYPE_INT64,    // TYPE_INT64
+  CPPTYPE_UINT64,   // TYPE_UINT64
+  CPPTYPE_INT32,    // TYPE_INT32
+  CPPTYPE_UINT64,   // TYPE_FIXED64
+  CPPTYPE_UINT32,   // TYPE_FIXED32
+  CPPTYPE_BOOL,     // TYPE_BOOL
+  CPPTYPE_STRING,   // TYPE_STRING
+  CPPTYPE_MESSAGE,  // TYPE_GROUP
+  CPPTYPE_MESSAGE,  // TYPE_MESSAGE
+  CPPTYPE_STRING,   // TYPE_BYTES
+  CPPTYPE_UINT32,   // TYPE_UINT32
+  CPPTYPE_ENUM,     // TYPE_ENUM
+  CPPTYPE_INT32,    // TYPE_SFIXED32
+  CPPTYPE_INT64,    // TYPE_SFIXED64
+  CPPTYPE_INT32,    // TYPE_SINT32
+  CPPTYPE_INT64,    // TYPE_SINT64
+};
+
+const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
+  "ERROR",     // 0 is reserved for errors
+
+  "double",    // TYPE_DOUBLE
+  "float",     // TYPE_FLOAT
+  "int64",     // TYPE_INT64
+  "uint64",    // TYPE_UINT64
+  "int32",     // TYPE_INT32
+  "fixed64",   // TYPE_FIXED64
+  "fixed32",   // TYPE_FIXED32
+  "bool",      // TYPE_BOOL
+  "string",    // TYPE_STRING
+  "group",     // TYPE_GROUP
+  "message",   // TYPE_MESSAGE
+  "bytes",     // TYPE_BYTES
+  "uint32",    // TYPE_UINT32
+  "enum",      // TYPE_ENUM
+  "sfixed32",  // TYPE_SFIXED32
+  "sfixed64",  // TYPE_SFIXED64
+  "sint32",    // TYPE_SINT32
+  "sint64",    // TYPE_SINT64
+};
+
+const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
+  "ERROR",     // 0 is reserved for errors
+
+  "int32",     // CPPTYPE_INT32
+  "int64",     // CPPTYPE_INT64
+  "uint32",    // CPPTYPE_UINT32
+  "uint64",    // CPPTYPE_UINT64
+  "double",    // CPPTYPE_DOUBLE
+  "float",     // CPPTYPE_FLOAT
+  "bool",      // CPPTYPE_BOOL
+  "enum",      // CPPTYPE_ENUM
+  "string",    // CPPTYPE_STRING
+  "message",   // CPPTYPE_MESSAGE
+};
+
+const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
+  "ERROR",     // 0 is reserved for errors
+
+  "optional",  // LABEL_OPTIONAL
+  "required",  // LABEL_REQUIRED
+  "repeated",  // LABEL_REPEATED
+};
+
+const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
+  switch (syntax) {
+    case SYNTAX_PROTO2:
+      return "proto2";
+    case SYNTAX_PROTO3:
+      return "proto3";
+    case SYNTAX_UNKNOWN:
+      return "unknown";
+  }
+  GOOGLE_LOG(FATAL) << "can't reach here.";
+  return NULL;
+}
+
+static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FieldDescriptor::kMaxNumber;
+const int FieldDescriptor::kFirstReservedNumber;
+const int FieldDescriptor::kLastReservedNumber;
+#endif
+
+namespace {
+
+string ToCamelCase(const string& input, bool lower_first) {
+  bool capitalize_next = !lower_first;
+  string result;
+  result.reserve(input.size());
+
+  for (int i = 0; i < input.size(); i++) {
+    if (input[i] == '_') {
+      capitalize_next = true;
+    } else if (capitalize_next) {
+      // Note:  I distrust ctype.h due to locales.
+      if ('a' <= input[i] && input[i] <= 'z') {
+        result.push_back(input[i] - 'a' + 'A');
+      } else {
+        result.push_back(input[i]);
+      }
+      capitalize_next = false;
+    } else {
+      result.push_back(input[i]);
+    }
+  }
+
+  // Lower-case the first letter.
+  if (lower_first && !result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
+      result[0] = result[0] - 'A' + 'a';
+  }
+
+  return result;
+}
+
+// A DescriptorPool contains a bunch of hash_maps to implement the
+// various Find*By*() methods.  Since hashtable lookups are O(1), it's
+// most efficient to construct a fixed set of large hash_maps used by
+// all objects in the pool rather than construct one or more small
+// hash_maps for each object.
+//
+// The keys to these hash_maps are (parent, name) or (parent, number)
+// pairs.  Unfortunately STL doesn't provide hash functions for pair<>,
+// so we must invent our own.
+//
+// TODO(kenton):  Use StringPiece rather than const char* in keys?  It would
+//   be a lot cleaner but we'd just have to convert it back to const char*
+//   for the open source release.
+
+typedef pair<const void*, const char*> PointerStringPair;
+
+struct PointerStringPairEqual {
+  inline bool operator()(const PointerStringPair& a,
+                         const PointerStringPair& b) const {
+    return a.first == b.first && strcmp(a.second, b.second) == 0;
+  }
+};
+
+template<typename PairType>
+struct PointerIntegerPairHash {
+  size_t operator()(const PairType& p) const {
+    // FIXME(kenton):  What is the best way to compute this hash?  I have
+    // no idea!  This seems a bit better than an XOR.
+    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second;
+  }
+
+#ifdef _MSC_VER
+  // Used only by MSVC and platforms where hash_map is not available.
+  static const size_t bucket_size = 4;
+  static const size_t min_buckets = 8;
+#endif
+  inline bool operator()(const PairType& a, const PairType& b) const {
+    return a.first < b.first ||
+          (a.first == b.first && a.second < b.second);
+  }
+};
+
+typedef pair<const Descriptor*, int> DescriptorIntPair;
+typedef pair<const EnumDescriptor*, int> EnumIntPair;
+
+struct PointerStringPairHash {
+  size_t operator()(const PointerStringPair& p) const {
+    // FIXME(kenton):  What is the best way to compute this hash?  I have
+    // no idea!  This seems a bit better than an XOR.
+    hash<const char*> cstring_hash;
+    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) +
+           cstring_hash(p.second);
+  }
+
+#ifdef _MSC_VER
+  // Used only by MSVC and platforms where hash_map is not available.
+  static const size_t bucket_size = 4;
+  static const size_t min_buckets = 8;
+#endif
+  inline bool operator()(const PointerStringPair& a,
+                         const PointerStringPair& b) const {
+    if (a.first < b.first) return true;
+    if (a.first > b.first) return false;
+    return strcmp(a.second, b.second) < 0;
+  }
+};
+
+
+struct Symbol {
+  enum Type {
+    NULL_SYMBOL, MESSAGE, FIELD, ONEOF, ENUM, ENUM_VALUE, SERVICE, METHOD,
+    PACKAGE
+  };
+  Type type;
+  union {
+    const Descriptor* descriptor;
+    const FieldDescriptor* field_descriptor;
+    const OneofDescriptor* oneof_descriptor;
+    const EnumDescriptor* enum_descriptor;
+    const EnumValueDescriptor* enum_value_descriptor;
+    const ServiceDescriptor* service_descriptor;
+    const MethodDescriptor* method_descriptor;
+    const FileDescriptor* package_file_descriptor;
+  };
+
+  inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; }
+  inline bool IsNull() const { return type == NULL_SYMBOL; }
+  inline bool IsType() const {
+    return type == MESSAGE || type == ENUM;
+  }
+  inline bool IsAggregate() const {
+    return type == MESSAGE || type == PACKAGE
+        || type == ENUM || type == SERVICE;
+  }
+
+#define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD)  \
+  inline explicit Symbol(const TYPE* value) {    \
+    type = TYPE_CONSTANT;                        \
+    this->FIELD = value;                         \
+  }
+
+  CONSTRUCTOR(Descriptor         , MESSAGE   , descriptor             )
+  CONSTRUCTOR(FieldDescriptor    , FIELD     , field_descriptor       )
+  CONSTRUCTOR(OneofDescriptor    , ONEOF     , oneof_descriptor       )
+  CONSTRUCTOR(EnumDescriptor     , ENUM      , enum_descriptor        )
+  CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor  )
+  CONSTRUCTOR(ServiceDescriptor  , SERVICE   , service_descriptor     )
+  CONSTRUCTOR(MethodDescriptor   , METHOD    , method_descriptor      )
+  CONSTRUCTOR(FileDescriptor     , PACKAGE   , package_file_descriptor)
+#undef CONSTRUCTOR
+
+  const FileDescriptor* GetFile() const {
+    switch (type) {
+      case NULL_SYMBOL: return NULL;
+      case MESSAGE    : return descriptor           ->file();
+      case FIELD      : return field_descriptor     ->file();
+      case ONEOF      : return oneof_descriptor     ->containing_type()->file();
+      case ENUM       : return enum_descriptor      ->file();
+      case ENUM_VALUE : return enum_value_descriptor->type()->file();
+      case SERVICE    : return service_descriptor   ->file();
+      case METHOD     : return method_descriptor    ->service()->file();
+      case PACKAGE    : return package_file_descriptor;
+    }
+    return NULL;
+  }
+};
+
+const Symbol kNullSymbol;
+
+typedef hash_map<const char*, Symbol,
+                 hash<const char*>, streq>
+  SymbolsByNameMap;
+typedef hash_map<PointerStringPair, Symbol,
+                 PointerStringPairHash, PointerStringPairEqual>
+  SymbolsByParentMap;
+typedef hash_map<const char*, const FileDescriptor*,
+                 hash<const char*>, streq>
+  FilesByNameMap;
+typedef hash_map<PointerStringPair, const FieldDescriptor*,
+                 PointerStringPairHash, PointerStringPairEqual>
+  FieldsByNameMap;
+typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
+                 PointerIntegerPairHash<DescriptorIntPair> >
+  FieldsByNumberMap;
+typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
+                 PointerIntegerPairHash<EnumIntPair> >
+  EnumValuesByNumberMap;
+// This is a map rather than a hash_map, since we use it to iterate
+// through all the extensions that extend a given Descriptor, and an
+// ordered data structure that implements lower_bound is convenient
+// for that.
+typedef map<DescriptorIntPair, const FieldDescriptor*>
+  ExtensionsGroupedByDescriptorMap;
+typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
+
+set<string>* allowed_proto3_extendees_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_);
+
+void DeleteAllowedProto3Extendee() {
+  delete allowed_proto3_extendees_;
+}
+
+void InitAllowedProto3Extendee() {
+  allowed_proto3_extendees_ = new set<string>;
+  const char* kOptionNames[] = {
+      "FileOptions",      "MessageOptions", "FieldOptions", "EnumOptions",
+      "EnumValueOptions", "ServiceOptions", "MethodOptions"};
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
+    // descriptor.proto has a different package name in opensource. We allow
+    // both so the opensource protocol compiler can also compile internal
+    // proto3 files with custom options. See: b/27567912
+    allowed_proto3_extendees_->insert(string("google.protobuf.") +
+                                      kOptionNames[i]);
+    // Split the word to trick the opensource processing scripts so they
+    // will keep the origial package name.
+    allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]);
+  }
+
+  google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee);
+}
+
+// Checks whether the extendee type is allowed in proto3.
+// Only extensions to descriptor options are allowed. We use name comparison
+// instead of comparing the descriptor directly because the extensions may be
+// defined in a different pool.
+bool AllowedExtendeeInProto3(const string& name) {
+  ::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee);
+  return allowed_proto3_extendees_->find(name) !=
+         allowed_proto3_extendees_->end();
+}
+
+}  // anonymous namespace
+
+// ===================================================================
+// DescriptorPool::Tables
+
+class DescriptorPool::Tables {
+ public:
+  Tables();
+  ~Tables();
+
+  // Record the current state of the tables to the stack of checkpoints.
+  // Each call to AddCheckpoint() must be paired with exactly one call to either
+  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
+  //
+  // This is used when building files, since some kinds of validation errors
+  // cannot be detected until the file's descriptors have already been added to
+  // the tables.
+  //
+  // This supports recursive checkpoints, since building a file may trigger
+  // recursive building of other files. Note that recursive checkpoints are not
+  // normally necessary; explicit dependencies are built prior to checkpointing.
+  // So although we recursively build transitive imports, there is at most one
+  // checkpoint in the stack during dependency building.
+  //
+  // Recursive checkpoints only arise during cross-linking of the descriptors.
+  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
+  // friends. If the pending file references an unknown symbol
+  // (e.g., it is not defined in the pending file's explicit dependencies), and
+  // the pool is using a fallback database, and that database contains a file
+  // defining that symbol, and that file has not yet been built by the pool,
+  // the pool builds the file during cross-linking, leading to another
+  // checkpoint.
+  void AddCheckpoint();
+
+  // Mark the last checkpoint as having cleared successfully, removing it from
+  // the stack. If the stack is empty, all pending symbols will be committed.
+  //
+  // Note that this does not guarantee that the symbols added since the last
+  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
+  // everything past that point gets rolled back, including symbols added after
+  // checkpoints that were pushed onto the stack after it and marked as cleared.
+  void ClearLastCheckpoint();
+
+  // Roll back the Tables to the state of the checkpoint at the top of the
+  // stack, removing everything that was added after that point.
+  void RollbackToLastCheckpoint();
+
+  // The stack of files which are currently being built.  Used to detect
+  // cyclic dependencies when loading files from a DescriptorDatabase.  Not
+  // used when fallback_database_ == NULL.
+  vector<string> pending_files_;
+
+  // A set of files which we have tried to load from the fallback database
+  // and encountered errors.  We will not attempt to load them again during
+  // execution of the current public API call, but for compatibility with
+  // legacy clients, this is cleared at the beginning of each public API call.
+  // Not used when fallback_database_ == NULL.
+  hash_set<string> known_bad_files_;
+
+  // A set of symbols which we have tried to load from the fallback database
+  // and encountered errors. We will not attempt to load them again during
+  // execution of the current public API call, but for compatibility with
+  // legacy clients, this is cleared at the beginning of each public API call.
+  hash_set<string> known_bad_symbols_;
+
+  // The set of descriptors for which we've already loaded the full
+  // set of extensions numbers from fallback_database_.
+  hash_set<const Descriptor*> extensions_loaded_from_db_;
+
+  // -----------------------------------------------------------------
+  // Finding items.
+
+  // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
+  // if not found.
+  inline Symbol FindSymbol(const string& key) const;
+
+  // This implements the body of DescriptorPool::Find*ByName().  It should
+  // really be a private method of DescriptorPool, but that would require
+  // declaring Symbol in descriptor.h, which would drag all kinds of other
+  // stuff into the header.  Yay C++.
+  Symbol FindByNameHelper(
+    const DescriptorPool* pool, const string& name);
+
+  // These return NULL if not found.
+  inline const FileDescriptor* FindFile(const string& key) const;
+  inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
+                                              int number);
+  inline void FindAllExtensions(const Descriptor* extendee,
+                                vector<const FieldDescriptor*>* out) const;
+
+  // -----------------------------------------------------------------
+  // Adding items.
+
+  // These add items to the corresponding tables.  They return false if
+  // the key already exists in the table.  For AddSymbol(), the string passed
+  // in must be one that was constructed using AllocateString(), as it will
+  // be used as a key in the symbols_by_name_ map without copying.
+  bool AddSymbol(const string& full_name, Symbol symbol);
+  bool AddFile(const FileDescriptor* file);
+  bool AddExtension(const FieldDescriptor* field);
+
+  // -----------------------------------------------------------------
+  // Allocating memory.
+
+  // Allocate an object which will be reclaimed when the pool is
+  // destroyed.  Note that the object's destructor will never be called,
+  // so its fields must be plain old data (primitive data types and
+  // pointers).  All of the descriptor types are such objects.
+  template<typename Type> Type* Allocate();
+
+  // Allocate an array of objects which will be reclaimed when the
+  // pool in destroyed.  Again, destructors are never called.
+  template<typename Type> Type* AllocateArray(int count);
+
+  // Allocate a string which will be destroyed when the pool is destroyed.
+  // The string is initialized to the given value for convenience.
+  string* AllocateString(const string& value);
+
+  // Allocate a protocol message object.  Some older versions of GCC have
+  // trouble understanding explicit template instantiations in some cases, so
+  // in those cases we have to pass a dummy pointer of the right type as the
+  // parameter instead of specifying the type explicitly.
+  template<typename Type> Type* AllocateMessage(Type* dummy = NULL);
+
+  // Allocate a FileDescriptorTables object.
+  FileDescriptorTables* AllocateFileTables();
+
+ private:
+  vector<string*> strings_;    // All strings in the pool.
+  vector<Message*> messages_;  // All messages in the pool.
+  vector<FileDescriptorTables*> file_tables_;  // All file tables in the pool.
+  vector<void*> allocations_;  // All other memory allocated in the pool.
+
+  SymbolsByNameMap      symbols_by_name_;
+  FilesByNameMap        files_by_name_;
+  ExtensionsGroupedByDescriptorMap extensions_;
+
+  struct CheckPoint {
+    explicit CheckPoint(const Tables* tables)
+      : strings_before_checkpoint(tables->strings_.size()),
+        messages_before_checkpoint(tables->messages_.size()),
+        file_tables_before_checkpoint(tables->file_tables_.size()),
+        allocations_before_checkpoint(tables->allocations_.size()),
+        pending_symbols_before_checkpoint(
+            tables->symbols_after_checkpoint_.size()),
+        pending_files_before_checkpoint(
+            tables->files_after_checkpoint_.size()),
+        pending_extensions_before_checkpoint(
+            tables->extensions_after_checkpoint_.size()) {
+    }
+    int strings_before_checkpoint;
+    int messages_before_checkpoint;
+    int file_tables_before_checkpoint;
+    int allocations_before_checkpoint;
+    int pending_symbols_before_checkpoint;
+    int pending_files_before_checkpoint;
+    int pending_extensions_before_checkpoint;
+  };
+  vector<CheckPoint> checkpoints_;
+  vector<const char*      > symbols_after_checkpoint_;
+  vector<const char*      > files_after_checkpoint_;
+  vector<DescriptorIntPair> extensions_after_checkpoint_;
+
+  // Allocate some bytes which will be reclaimed when the pool is
+  // destroyed.
+  void* AllocateBytes(int size);
+};
+
+// Contains tables specific to a particular file.  These tables are not
+// modified once the file has been constructed, so they need not be
+// protected by a mutex.  This makes operations that depend only on the
+// contents of a single file -- e.g. Descriptor::FindFieldByName() --
+// lock-free.
+//
+// For historical reasons, the definitions of the methods of
+// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
+// These used to be a single class.
+class FileDescriptorTables {
+ public:
+  FileDescriptorTables();
+  ~FileDescriptorTables();
+
+  // Empty table, used with placeholder files.
+  inline static const FileDescriptorTables& GetEmptyInstance();
+
+  // -----------------------------------------------------------------
+  // Finding items.
+
+  // Find symbols.  These return a null Symbol (symbol.IsNull() is true)
+  // if not found.
+  inline Symbol FindNestedSymbol(const void* parent,
+                                 const string& name) const;
+  inline Symbol FindNestedSymbolOfType(const void* parent,
+                                       const string& name,
+                                       const Symbol::Type type) const;
+
+  // These return NULL if not found.
+  inline const FieldDescriptor* FindFieldByNumber(
+    const Descriptor* parent, int number) const;
+  inline const FieldDescriptor* FindFieldByLowercaseName(
+    const void* parent, const string& lowercase_name) const;
+  inline const FieldDescriptor* FindFieldByCamelcaseName(
+    const void* parent, const string& camelcase_name) const;
+  inline const EnumValueDescriptor* FindEnumValueByNumber(
+    const EnumDescriptor* parent, int number) const;
+  // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
+  inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
+      const EnumDescriptor* parent, int number) const;
+
+  // -----------------------------------------------------------------
+  // Adding items.
+
+  // These add items to the corresponding tables.  They return false if
+  // the key already exists in the table.  For AddAliasUnderParent(), the
+  // string passed in must be one that was constructed using AllocateString(),
+  // as it will be used as a key in the symbols_by_parent_ map without copying.
+  bool AddAliasUnderParent(const void* parent, const string& name,
+                           Symbol symbol);
+  bool AddFieldByNumber(const FieldDescriptor* field);
+  bool AddEnumValueByNumber(const EnumValueDescriptor* value);
+
+  // Adds the field to the lowercase_name and camelcase_name maps.  Never
+  // fails because we allow duplicates; the first field by the name wins.
+  void AddFieldByStylizedNames(const FieldDescriptor* field);
+
+  // Populates p->first->locations_by_path_ from p->second.
+  // Unusual signature dictated by GoogleOnceDynamic.
+  static void BuildLocationsByPath(
+      pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
+
+  // Returns the location denoted by the specified path through info,
+  // or NULL if not found.
+  // The value of info must be that of the corresponding FileDescriptor.
+  // (Conceptually a pure function, but stateful as an optimisation.)
+  const SourceCodeInfo_Location* GetSourceLocation(
+      const vector<int>& path, const SourceCodeInfo* info) const;
+
+ private:
+  SymbolsByParentMap    symbols_by_parent_;
+  FieldsByNameMap       fields_by_lowercase_name_;
+  FieldsByNameMap       fields_by_camelcase_name_;
+  FieldsByNumberMap     fields_by_number_;       // Not including extensions.
+  EnumValuesByNumberMap enum_values_by_number_;
+  mutable EnumValuesByNumberMap unknown_enum_values_by_number_
+      GOOGLE_GUARDED_BY(unknown_enum_values_mu_);
+
+  // Populated on first request to save space, hence constness games.
+  mutable GoogleOnceDynamic locations_by_path_once_;
+  mutable LocationsByPathMap locations_by_path_;
+
+  // Mutex to protect the unknown-enum-value map due to dynamic
+  // EnumValueDescriptor creation on unknown values.
+  mutable Mutex unknown_enum_values_mu_;
+};
+
+DescriptorPool::Tables::Tables()
+    // Start some hash_map and hash_set objects with a small # of buckets
+    : known_bad_files_(3),
+      known_bad_symbols_(3),
+      extensions_loaded_from_db_(3),
+      symbols_by_name_(3),
+      files_by_name_(3) {}
+
+
+DescriptorPool::Tables::~Tables() {
+  GOOGLE_DCHECK(checkpoints_.empty());
+  // Note that the deletion order is important, since the destructors of some
+  // messages may refer to objects in allocations_.
+  STLDeleteElements(&messages_);
+  for (int i = 0; i < allocations_.size(); i++) {
+    operator delete(allocations_[i]);
+  }
+  STLDeleteElements(&strings_);
+  STLDeleteElements(&file_tables_);
+}
+
+FileDescriptorTables::FileDescriptorTables()
+    // Initialize all the hash tables to start out with a small # of buckets
+    : symbols_by_parent_(3),
+      fields_by_lowercase_name_(3),
+      fields_by_camelcase_name_(3),
+      fields_by_number_(3),
+      enum_values_by_number_(3),
+      unknown_enum_values_by_number_(3) {
+}
+
+FileDescriptorTables::~FileDescriptorTables() {}
+
+namespace {
+
+FileDescriptorTables* file_descriptor_tables_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(file_descriptor_tables_once_init_);
+
+void DeleteFileDescriptorTables() {
+  delete file_descriptor_tables_;
+  file_descriptor_tables_ = NULL;
+}
+
+void InitFileDescriptorTables() {
+  file_descriptor_tables_ = new FileDescriptorTables();
+  internal::OnShutdown(&DeleteFileDescriptorTables);
+}
+
+inline void InitFileDescriptorTablesOnce() {
+  ::google::protobuf::GoogleOnceInit(
+      &file_descriptor_tables_once_init_, &InitFileDescriptorTables);
+}
+
+}  // anonymous namespace
+
+inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
+  InitFileDescriptorTablesOnce();
+  return *file_descriptor_tables_;
+}
+
+void DescriptorPool::Tables::AddCheckpoint() {
+  checkpoints_.push_back(CheckPoint(this));
+}
+
+void DescriptorPool::Tables::ClearLastCheckpoint() {
+  GOOGLE_DCHECK(!checkpoints_.empty());
+  checkpoints_.pop_back();
+  if (checkpoints_.empty()) {
+    // All checkpoints have been cleared: we can now commit all of the pending
+    // data.
+    symbols_after_checkpoint_.clear();
+    files_after_checkpoint_.clear();
+    extensions_after_checkpoint_.clear();
+  }
+}
+
+void DescriptorPool::Tables::RollbackToLastCheckpoint() {
+  GOOGLE_DCHECK(!checkpoints_.empty());
+  const CheckPoint& checkpoint = checkpoints_.back();
+
+  for (int i = checkpoint.pending_symbols_before_checkpoint;
+       i < symbols_after_checkpoint_.size();
+       i++) {
+    symbols_by_name_.erase(symbols_after_checkpoint_[i]);
+  }
+  for (int i = checkpoint.pending_files_before_checkpoint;
+       i < files_after_checkpoint_.size();
+       i++) {
+    files_by_name_.erase(files_after_checkpoint_[i]);
+  }
+  for (int i = checkpoint.pending_extensions_before_checkpoint;
+       i < extensions_after_checkpoint_.size();
+       i++) {
+    extensions_.erase(extensions_after_checkpoint_[i]);
+  }
+
+  symbols_after_checkpoint_.resize(
+      checkpoint.pending_symbols_before_checkpoint);
+  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
+  extensions_after_checkpoint_.resize(
+      checkpoint.pending_extensions_before_checkpoint);
+
+  STLDeleteContainerPointers(
+      strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
+  STLDeleteContainerPointers(
+      messages_.begin() + checkpoint.messages_before_checkpoint,
+      messages_.end());
+  STLDeleteContainerPointers(
+      file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
+      file_tables_.end());
+  for (int i = checkpoint.allocations_before_checkpoint;
+       i < allocations_.size();
+       i++) {
+    operator delete(allocations_[i]);
+  }
+
+  strings_.resize(checkpoint.strings_before_checkpoint);
+  messages_.resize(checkpoint.messages_before_checkpoint);
+  file_tables_.resize(checkpoint.file_tables_before_checkpoint);
+  allocations_.resize(checkpoint.allocations_before_checkpoint);
+  checkpoints_.pop_back();
+}
+
+// -------------------------------------------------------------------
+
+inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const {
+  const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
+  if (result == NULL) {
+    return kNullSymbol;
+  } else {
+    return *result;
+  }
+}
+
+inline Symbol FileDescriptorTables::FindNestedSymbol(
+    const void* parent, const string& name) const {
+  const Symbol* result =
+    FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str()));
+  if (result == NULL) {
+    return kNullSymbol;
+  } else {
+    return *result;
+  }
+}
+
+inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
+    const void* parent, const string& name, const Symbol::Type type) const {
+  Symbol result = FindNestedSymbol(parent, name);
+  if (result.type != type) return kNullSymbol;
+  return result;
+}
+
+Symbol DescriptorPool::Tables::FindByNameHelper(
+    const DescriptorPool* pool, const string& name) {
+  MutexLockMaybe lock(pool->mutex_);
+  known_bad_symbols_.clear();
+  known_bad_files_.clear();
+  Symbol result = FindSymbol(name);
+
+  if (result.IsNull() && pool->underlay_ != NULL) {
+    // Symbol not found; check the underlay.
+    result =
+      pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
+  }
+
+  if (result.IsNull()) {
+    // Symbol still not found, so check fallback database.
+    if (pool->TryFindSymbolInFallbackDatabase(name)) {
+      result = FindSymbol(name);
+    }
+  }
+
+  return result;
+}
+
+inline const FileDescriptor* DescriptorPool::Tables::FindFile(
+    const string& key) const {
+  return FindPtrOrNull(files_by_name_, key.c_str());
+}
+
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
+    const Descriptor* parent, int number) const {
+  return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
+}
+
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
+    const void* parent, const string& lowercase_name) const {
+  return FindPtrOrNull(fields_by_lowercase_name_,
+                       PointerStringPair(parent, lowercase_name.c_str()));
+}
+
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
+    const void* parent, const string& camelcase_name) const {
+  return FindPtrOrNull(fields_by_camelcase_name_,
+                       PointerStringPair(parent, camelcase_name.c_str()));
+}
+
+inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
+    const EnumDescriptor* parent, int number) const {
+  return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
+}
+
+inline const EnumValueDescriptor*
+FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
+    const EnumDescriptor* parent, int number) const {
+  // First try, with map of compiled-in values.
+  {
+    const EnumValueDescriptor* desc =
+        FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
+    if (desc != NULL) {
+      return desc;
+    }
+  }
+  // Second try, with reader lock held on unknown enum values: common case.
+  {
+    ReaderMutexLock l(&unknown_enum_values_mu_);
+    const EnumValueDescriptor* desc = FindPtrOrNull(
+        unknown_enum_values_by_number_, std::make_pair(parent, number));
+    if (desc != NULL) {
+      return desc;
+    }
+  }
+  // If not found, try again with writer lock held, and create new descriptor if
+  // necessary.
+  {
+    WriterMutexLock l(&unknown_enum_values_mu_);
+    const EnumValueDescriptor* desc = FindPtrOrNull(
+        unknown_enum_values_by_number_, std::make_pair(parent, number));
+    if (desc != NULL) {
+      return desc;
+    }
+
+    // Create an EnumValueDescriptor dynamically. We don't insert it into the
+    // EnumDescriptor (it's not a part of the enum as originally defined), but
+    // we do insert it into the table so that we can return the same pointer
+    // later.
+    string enum_value_name = StringPrintf(
+        "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
+    DescriptorPool::Tables* tables =
+        const_cast<DescriptorPool::Tables*>(DescriptorPool::generated_pool()->
+                                            tables_.get());
+    EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
+    result->name_ = tables->AllocateString(enum_value_name);
+    result->full_name_ = tables->AllocateString(parent->full_name() +
+                                                "." + enum_value_name);
+    result->number_ = number;
+    result->type_ = parent;
+    result->options_ = &EnumValueOptions::default_instance();
+    InsertIfNotPresent(&unknown_enum_values_by_number_,
+                       std::make_pair(parent, number), result);
+    return result;
+  }
+}
+
+
+inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
+    const Descriptor* extendee, int number) {
+  return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
+}
+
+inline void DescriptorPool::Tables::FindAllExtensions(
+    const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
+  ExtensionsGroupedByDescriptorMap::const_iterator it =
+      extensions_.lower_bound(std::make_pair(extendee, 0));
+  for (; it != extensions_.end() && it->first.first == extendee; ++it) {
+    out->push_back(it->second);
+  }
+}
+
+// -------------------------------------------------------------------
+
+bool DescriptorPool::Tables::AddSymbol(
+    const string& full_name, Symbol symbol) {
+  if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
+    symbols_after_checkpoint_.push_back(full_name.c_str());
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool FileDescriptorTables::AddAliasUnderParent(
+    const void* parent, const string& name, Symbol symbol) {
+  PointerStringPair by_parent_key(parent, name.c_str());
+  return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
+}
+
+bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
+  if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
+    files_after_checkpoint_.push_back(file->name().c_str());
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void FileDescriptorTables::AddFieldByStylizedNames(
+    const FieldDescriptor* field) {
+  const void* parent;
+  if (field->is_extension()) {
+    if (field->extension_scope() == NULL) {
+      parent = field->file();
+    } else {
+      parent = field->extension_scope();
+    }
+  } else {
+    parent = field->containing_type();
+  }
+
+  PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
+  InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field);
+
+  PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
+  InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field);
+}
+
+bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
+  DescriptorIntPair key(field->containing_type(), field->number());
+  return InsertIfNotPresent(&fields_by_number_, key, field);
+}
+
+bool FileDescriptorTables::AddEnumValueByNumber(
+    const EnumValueDescriptor* value) {
+  EnumIntPair key(value->type(), value->number());
+  return InsertIfNotPresent(&enum_values_by_number_, key, value);
+}
+
+bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
+  DescriptorIntPair key(field->containing_type(), field->number());
+  if (InsertIfNotPresent(&extensions_, key, field)) {
+    extensions_after_checkpoint_.push_back(key);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// -------------------------------------------------------------------
+
+template<typename Type>
+Type* DescriptorPool::Tables::Allocate() {
+  return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type)));
+}
+
+template<typename Type>
+Type* DescriptorPool::Tables::AllocateArray(int count) {
+  return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
+}
+
+string* DescriptorPool::Tables::AllocateString(const string& value) {
+  string* result = new string(value);
+  strings_.push_back(result);
+  return result;
+}
+
+template<typename Type>
+Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) {
+  Type* result = new Type;
+  messages_.push_back(result);
+  return result;
+}
+
+FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
+  FileDescriptorTables* result = new FileDescriptorTables;
+  file_tables_.push_back(result);
+  return result;
+}
+
+void* DescriptorPool::Tables::AllocateBytes(int size) {
+  // TODO(kenton):  Would it be worthwhile to implement this in some more
+  // sophisticated way?  Probably not for the open source release, but for
+  // internal use we could easily plug in one of our existing memory pool
+  // allocators...
+  if (size == 0) return NULL;
+
+  void* result = operator new(size);
+  allocations_.push_back(result);
+  return result;
+}
+
+void FileDescriptorTables::BuildLocationsByPath(
+    pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
+  for (int i = 0, len = p->second->location_size(); i < len; ++i) {
+    const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
+    p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
+  }
+}
+
+const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
+    const vector<int>& path, const SourceCodeInfo* info) const {
+  pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
+      std::make_pair(this, info));
+  locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
+  return FindPtrOrNull(locations_by_path_, Join(path, ","));
+}
+
+// ===================================================================
+// DescriptorPool
+
+DescriptorPool::ErrorCollector::~ErrorCollector() {}
+
+DescriptorPool::DescriptorPool()
+  : mutex_(NULL),
+    fallback_database_(NULL),
+    default_error_collector_(NULL),
+    underlay_(NULL),
+    tables_(new Tables),
+    enforce_dependencies_(true),
+    allow_unknown_(false),
+    enforce_weak_(false) {}
+
+DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
+                               ErrorCollector* error_collector)
+  : mutex_(new Mutex),
+    fallback_database_(fallback_database),
+    default_error_collector_(error_collector),
+    underlay_(NULL),
+    tables_(new Tables),
+    enforce_dependencies_(true),
+    allow_unknown_(false),
+    enforce_weak_(false) {
+}
+
+DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
+  : mutex_(NULL),
+    fallback_database_(NULL),
+    default_error_collector_(NULL),
+    underlay_(underlay),
+    tables_(new Tables),
+    enforce_dependencies_(true),
+    allow_unknown_(false),
+    enforce_weak_(false) {}
+
+DescriptorPool::~DescriptorPool() {
+  if (mutex_ != NULL) delete mutex_;
+}
+
+// DescriptorPool::BuildFile() defined later.
+// DescriptorPool::BuildFileCollectingErrors() defined later.
+
+void DescriptorPool::InternalDontEnforceDependencies() {
+  enforce_dependencies_ = false;
+}
+
+void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) {
+  unused_import_track_files_.insert(file_name);
+}
+
+void DescriptorPool::ClearUnusedImportTrackFiles() {
+  unused_import_track_files_.clear();
+}
+
+bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
+  MutexLockMaybe lock(mutex_);
+  return tables_->FindFile(filename) != NULL;
+}
+
+// generated_pool ====================================================
+
+namespace {
+
+
+EncodedDescriptorDatabase* generated_database_ = NULL;
+DescriptorPool* generated_pool_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
+
+void DeleteGeneratedPool() {
+  delete generated_database_;
+  generated_database_ = NULL;
+  delete generated_pool_;
+  generated_pool_ = NULL;
+}
+
+static void InitGeneratedPool() {
+  generated_database_ = new EncodedDescriptorDatabase;
+  generated_pool_ = new DescriptorPool(generated_database_);
+
+  internal::OnShutdown(&DeleteGeneratedPool);
+}
+
+inline void InitGeneratedPoolOnce() {
+  ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
+}
+
+}  // anonymous namespace
+
+const DescriptorPool* DescriptorPool::generated_pool() {
+  InitGeneratedPoolOnce();
+  return generated_pool_;
+}
+
+
+DescriptorPool* DescriptorPool::internal_generated_pool() {
+  InitGeneratedPoolOnce();
+  return generated_pool_;
+}
+
+void DescriptorPool::InternalAddGeneratedFile(
+    const void* encoded_file_descriptor, int size) {
+  // So, this function is called in the process of initializing the
+  // descriptors for generated proto classes.  Each generated .pb.cc file
+  // has an internal procedure called AddDescriptors() which is called at
+  // process startup, and that function calls this one in order to register
+  // the raw bytes of the FileDescriptorProto representing the file.
+  //
+  // We do not actually construct the descriptor objects right away.  We just
+  // hang on to the bytes until they are actually needed.  We actually construct
+  // the descriptor the first time one of the following things happens:
+  // * Someone calls a method like descriptor(), GetDescriptor(), or
+  //   GetReflection() on the generated types, which requires returning the
+  //   descriptor or an object based on it.
+  // * Someone looks up the descriptor in DescriptorPool::generated_pool().
+  //
+  // Once one of these happens, the DescriptorPool actually parses the
+  // FileDescriptorProto and generates a FileDescriptor (and all its children)
+  // based on it.
+  //
+  // Note that FileDescriptorProto is itself a generated protocol message.
+  // Therefore, when we parse one, we have to be very careful to avoid using
+  // any descriptor-based operations, since this might cause infinite recursion
+  // or deadlock.
+  InitGeneratedPoolOnce();
+  GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
+}
+
+
+// Find*By* methods ==================================================
+
+// TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
+//   there's any good way to factor it out.  Think about this some time when
+//   there's nothing more important to do (read: never).
+
+const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
+  MutexLockMaybe lock(mutex_);
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+  const FileDescriptor* result = tables_->FindFile(name);
+  if (result != NULL) return result;
+  if (underlay_ != NULL) {
+    result = underlay_->FindFileByName(name);
+    if (result != NULL) return result;
+  }
+  if (TryFindFileInFallbackDatabase(name)) {
+    result = tables_->FindFile(name);
+    if (result != NULL) return result;
+  }
+  return NULL;
+}
+
+const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
+    const string& symbol_name) const {
+  MutexLockMaybe lock(mutex_);
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+  Symbol result = tables_->FindSymbol(symbol_name);
+  if (!result.IsNull()) return result.GetFile();
+  if (underlay_ != NULL) {
+    const FileDescriptor* file_result =
+      underlay_->FindFileContainingSymbol(symbol_name);
+    if (file_result != NULL) return file_result;
+  }
+  if (TryFindSymbolInFallbackDatabase(symbol_name)) {
+    result = tables_->FindSymbol(symbol_name);
+    if (!result.IsNull()) return result.GetFile();
+  }
+  return NULL;
+}
+
+const Descriptor* DescriptorPool::FindMessageTypeByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL;
+}
+
+const FieldDescriptor* DescriptorPool::FindFieldByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  if (result.type == Symbol::FIELD &&
+      !result.field_descriptor->is_extension()) {
+    return result.field_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const FieldDescriptor* DescriptorPool::FindExtensionByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  if (result.type == Symbol::FIELD &&
+      result.field_descriptor->is_extension()) {
+    return result.field_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const OneofDescriptor* DescriptorPool::FindOneofByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL;
+}
+
+const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL;
+}
+
+const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::ENUM_VALUE) ?
+    result.enum_value_descriptor : NULL;
+}
+
+const ServiceDescriptor* DescriptorPool::FindServiceByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL;
+}
+
+const MethodDescriptor* DescriptorPool::FindMethodByName(
+    const string& name) const {
+  Symbol result = tables_->FindByNameHelper(this, name);
+  return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL;
+}
+
+const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
+    const Descriptor* extendee, int number) const {
+  MutexLockMaybe lock(mutex_);
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
+  if (result != NULL) {
+    return result;
+  }
+  if (underlay_ != NULL) {
+    result = underlay_->FindExtensionByNumber(extendee, number);
+    if (result != NULL) return result;
+  }
+  if (TryFindExtensionInFallbackDatabase(extendee, number)) {
+    result = tables_->FindExtension(extendee, number);
+    if (result != NULL) {
+      return result;
+    }
+  }
+  return NULL;
+}
+
+void DescriptorPool::FindAllExtensions(
+    const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
+  MutexLockMaybe lock(mutex_);
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+
+  // Initialize tables_->extensions_ from the fallback database first
+  // (but do this only once per descriptor).
+  if (fallback_database_ != NULL &&
+      tables_->extensions_loaded_from_db_.count(extendee) == 0) {
+    vector<int> numbers;
+    if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
+                                                    &numbers)) {
+      for (int i = 0; i < numbers.size(); ++i) {
+        int number = numbers[i];
+        if (tables_->FindExtension(extendee, number) == NULL) {
+          TryFindExtensionInFallbackDatabase(extendee, number);
+        }
+      }
+      tables_->extensions_loaded_from_db_.insert(extendee);
+    }
+  }
+
+  tables_->FindAllExtensions(extendee, out);
+  if (underlay_ != NULL) {
+    underlay_->FindAllExtensions(extendee, out);
+  }
+}
+
+
+// -------------------------------------------------------------------
+
+const FieldDescriptor*
+Descriptor::FindFieldByNumber(int key) const {
+  const FieldDescriptor* result =
+    file()->tables_->FindFieldByNumber(this, key);
+  if (result == NULL || result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindFieldByLowercaseName(const string& key) const {
+  const FieldDescriptor* result =
+    file()->tables_->FindFieldByLowercaseName(this, key);
+  if (result == NULL || result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindFieldByCamelcaseName(const string& key) const {
+  const FieldDescriptor* result =
+    file()->tables_->FindFieldByCamelcaseName(this, key);
+  if (result == NULL || result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindFieldByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+  if (!result.IsNull() && !result.field_descriptor->is_extension()) {
+    return result.field_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const OneofDescriptor*
+Descriptor::FindOneofByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
+  if (!result.IsNull()) {
+    return result.oneof_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindExtensionByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+  if (!result.IsNull() && result.field_descriptor->is_extension()) {
+    return result.field_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindExtensionByLowercaseName(const string& key) const {
+  const FieldDescriptor* result =
+    file()->tables_->FindFieldByLowercaseName(this, key);
+  if (result == NULL || !result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const FieldDescriptor*
+Descriptor::FindExtensionByCamelcaseName(const string& key) const {
+  const FieldDescriptor* result =
+    file()->tables_->FindFieldByCamelcaseName(this, key);
+  if (result == NULL || !result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const Descriptor*
+Descriptor::FindNestedTypeByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
+  if (!result.IsNull()) {
+    return result.descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumDescriptor*
+Descriptor::FindEnumTypeByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
+  if (!result.IsNull()) {
+    return result.enum_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumValueDescriptor*
+Descriptor::FindEnumValueByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
+  if (!result.IsNull()) {
+    return result.enum_value_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumValueDescriptor*
+EnumDescriptor::FindValueByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
+  if (!result.IsNull()) {
+    return result.enum_value_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumValueDescriptor*
+EnumDescriptor::FindValueByNumber(int key) const {
+  return file()->tables_->FindEnumValueByNumber(this, key);
+}
+
+const EnumValueDescriptor*
+EnumDescriptor::FindValueByNumberCreatingIfUnknown(int key) const {
+  return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
+}
+
+const MethodDescriptor*
+ServiceDescriptor::FindMethodByName(const string& key) const {
+  Symbol result =
+    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
+  if (!result.IsNull()) {
+    return result.method_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const Descriptor*
+FileDescriptor::FindMessageTypeByName(const string& key) const {
+  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
+  if (!result.IsNull()) {
+    return result.descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumDescriptor*
+FileDescriptor::FindEnumTypeByName(const string& key) const {
+  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
+  if (!result.IsNull()) {
+    return result.enum_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const EnumValueDescriptor*
+FileDescriptor::FindEnumValueByName(const string& key) const {
+  Symbol result =
+    tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
+  if (!result.IsNull()) {
+    return result.enum_value_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const ServiceDescriptor*
+FileDescriptor::FindServiceByName(const string& key) const {
+  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
+  if (!result.IsNull()) {
+    return result.service_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const FieldDescriptor*
+FileDescriptor::FindExtensionByName(const string& key) const {
+  Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+  if (!result.IsNull() && result.field_descriptor->is_extension()) {
+    return result.field_descriptor;
+  } else {
+    return NULL;
+  }
+}
+
+const FieldDescriptor*
+FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
+  const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
+  if (result == NULL || !result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const FieldDescriptor*
+FileDescriptor::FindExtensionByCamelcaseName(const string& key) const {
+  const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
+  if (result == NULL || !result->is_extension()) {
+    return NULL;
+  } else {
+    return result;
+  }
+}
+
+const Descriptor::ExtensionRange*
+Descriptor::FindExtensionRangeContainingNumber(int number) const {
+  // Linear search should be fine because we don't expect a message to have
+  // more than a couple extension ranges.
+  for (int i = 0; i < extension_range_count(); i++) {
+    if (number >= extension_range(i)->start &&
+        number <  extension_range(i)->end) {
+      return extension_range(i);
+    }
+  }
+  return NULL;
+}
+
+const Descriptor::ReservedRange*
+Descriptor::FindReservedRangeContainingNumber(int number) const {
+  // TODO(chrisn): Consider a non-linear search.
+  for (int i = 0; i < reserved_range_count(); i++) {
+    if (number >= reserved_range(i)->start &&
+        number <  reserved_range(i)->end) {
+      return reserved_range(i);
+    }
+  }
+  return NULL;
+}
+
+// -------------------------------------------------------------------
+
+bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
+  if (fallback_database_ == NULL) return false;
+
+  if (tables_->known_bad_files_.count(name) > 0) return false;
+
+  FileDescriptorProto file_proto;
+  if (!fallback_database_->FindFileByName(name, &file_proto) ||
+      BuildFileFromDatabase(file_proto) == NULL) {
+    tables_->known_bad_files_.insert(name);
+    return false;
+  }
+  return true;
+}
+
+bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
+  string prefix = name;
+  for (;;) {
+    string::size_type dot_pos = prefix.find_last_of('.');
+    if (dot_pos == string::npos) {
+      break;
+    }
+    prefix = prefix.substr(0, dot_pos);
+    Symbol symbol = tables_->FindSymbol(prefix);
+    // If the symbol type is anything other than PACKAGE, then its complete
+    // definition is already known.
+    if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
+      return true;
+    }
+  }
+  if (underlay_ != NULL) {
+    // Check to see if any prefix of this symbol exists in the underlay.
+    return underlay_->IsSubSymbolOfBuiltType(name);
+  }
+  return false;
+}
+
+bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
+  if (fallback_database_ == NULL) return false;
+
+  if (tables_->known_bad_symbols_.count(name) > 0) return false;
+
+  FileDescriptorProto file_proto;
+  if (// We skip looking in the fallback database if the name is a sub-symbol
+      // of any descriptor that already exists in the descriptor pool (except
+      // for package descriptors).  This is valid because all symbols except
+      // for packages are defined in a single file, so if the symbol exists
+      // then we should already have its definition.
+      //
+      // The other reason to do this is to support "overriding" type
+      // definitions by merging two databases that define the same type.  (Yes,
+      // people do this.)  The main difficulty with making this work is that
+      // FindFileContainingSymbol() is allowed to return both false positives
+      // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
+      // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
+      // When two such databases are merged, looking up a non-existent
+      // sub-symbol of a type that already exists in the descriptor pool can
+      // result in an attempt to load multiple definitions of the same type.
+      // The check below avoids this.
+      IsSubSymbolOfBuiltType(name)
+
+      // Look up file containing this symbol in fallback database.
+      || !fallback_database_->FindFileContainingSymbol(name, &file_proto)
+
+      // Check if we've already built this file. If so, it apparently doesn't
+      // contain the symbol we're looking for.  Some DescriptorDatabases
+      // return false positives.
+      || tables_->FindFile(file_proto.name()) != NULL
+
+      // Build the file.
+      || BuildFileFromDatabase(file_proto) == NULL) {
+    tables_->known_bad_symbols_.insert(name);
+    return false;
+  }
+
+  return true;
+}
+
+bool DescriptorPool::TryFindExtensionInFallbackDatabase(
+    const Descriptor* containing_type, int field_number) const {
+  if (fallback_database_ == NULL) return false;
+
+  FileDescriptorProto file_proto;
+  if (!fallback_database_->FindFileContainingExtension(
+        containing_type->full_name(), field_number, &file_proto)) {
+    return false;
+  }
+
+  if (tables_->FindFile(file_proto.name()) != NULL) {
+    // We've already loaded this file, and it apparently doesn't contain the
+    // extension we're looking for.  Some DescriptorDatabases return false
+    // positives.
+    return false;
+  }
+
+  if (BuildFileFromDatabase(file_proto) == NULL) {
+    return false;
+  }
+
+  return true;
+}
+
+// ===================================================================
+
+bool FieldDescriptor::is_map() const {
+  return type() == TYPE_MESSAGE && message_type()->options().map_entry();
+}
+
+string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
+  GOOGLE_CHECK(has_default_value()) << "No default value";
+  switch (cpp_type()) {
+    case CPPTYPE_INT32:
+      return SimpleItoa(default_value_int32());
+      break;
+    case CPPTYPE_INT64:
+      return SimpleItoa(default_value_int64());
+      break;
+    case CPPTYPE_UINT32:
+      return SimpleItoa(default_value_uint32());
+      break;
+    case CPPTYPE_UINT64:
+      return SimpleItoa(default_value_uint64());
+      break;
+    case CPPTYPE_FLOAT:
+      return SimpleFtoa(default_value_float());
+      break;
+    case CPPTYPE_DOUBLE:
+      return SimpleDtoa(default_value_double());
+      break;
+    case CPPTYPE_BOOL:
+      return default_value_bool() ? "true" : "false";
+      break;
+    case CPPTYPE_STRING:
+      if (quote_string_type) {
+        return "\"" + CEscape(default_value_string()) + "\"";
+      } else {
+        if (type() == TYPE_BYTES) {
+          return CEscape(default_value_string());
+        } else {
+          return default_value_string();
+        }
+      }
+      break;
+    case CPPTYPE_ENUM:
+      return default_value_enum()->name();
+      break;
+    case CPPTYPE_MESSAGE:
+      GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
+      break;
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string";
+  return "";
+}
+
+// CopyTo methods ====================================================
+
+void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
+  proto->set_name(name());
+  if (!package().empty()) proto->set_package(package());
+  // TODO(liujisi): Also populate when syntax="proto2".
+  if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
+
+  for (int i = 0; i < dependency_count(); i++) {
+    proto->add_dependency(dependency(i)->name());
+  }
+
+  for (int i = 0; i < public_dependency_count(); i++) {
+    proto->add_public_dependency(public_dependencies_[i]);
+  }
+
+  for (int i = 0; i < weak_dependency_count(); i++) {
+    proto->add_weak_dependency(weak_dependencies_[i]);
+  }
+
+  for (int i = 0; i < message_type_count(); i++) {
+    message_type(i)->CopyTo(proto->add_message_type());
+  }
+  for (int i = 0; i < enum_type_count(); i++) {
+    enum_type(i)->CopyTo(proto->add_enum_type());
+  }
+  for (int i = 0; i < service_count(); i++) {
+    service(i)->CopyTo(proto->add_service());
+  }
+  for (int i = 0; i < extension_count(); i++) {
+    extension(i)->CopyTo(proto->add_extension());
+  }
+
+  if (&options() != &FileOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
+  if (message_type_count() != proto->message_type_size() ||
+      extension_count() != proto->extension_size()) {
+    GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
+    return;
+  }
+  for (int i = 0; i < message_type_count(); i++) {
+    message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
+  }
+  for (int i = 0; i < extension_count(); i++) {
+    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
+  }
+}
+
+void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
+  if (source_code_info_ &&
+      source_code_info_ != &SourceCodeInfo::default_instance()) {
+    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
+  }
+}
+
+void Descriptor::CopyTo(DescriptorProto* proto) const {
+  proto->set_name(name());
+
+  for (int i = 0; i < field_count(); i++) {
+    field(i)->CopyTo(proto->add_field());
+  }
+  for (int i = 0; i < oneof_decl_count(); i++) {
+    oneof_decl(i)->CopyTo(proto->add_oneof_decl());
+  }
+  for (int i = 0; i < nested_type_count(); i++) {
+    nested_type(i)->CopyTo(proto->add_nested_type());
+  }
+  for (int i = 0; i < enum_type_count(); i++) {
+    enum_type(i)->CopyTo(proto->add_enum_type());
+  }
+  for (int i = 0; i < extension_range_count(); i++) {
+    DescriptorProto::ExtensionRange* range = proto->add_extension_range();
+    range->set_start(extension_range(i)->start);
+    range->set_end(extension_range(i)->end);
+  }
+  for (int i = 0; i < extension_count(); i++) {
+    extension(i)->CopyTo(proto->add_extension());
+  }
+  for (int i = 0; i < reserved_range_count(); i++) {
+    DescriptorProto::ReservedRange* range = proto->add_reserved_range();
+    range->set_start(reserved_range(i)->start);
+    range->set_end(reserved_range(i)->end);
+  }
+  for (int i = 0; i < reserved_name_count(); i++) {
+    proto->add_reserved_name(reserved_name(i));
+  }
+
+  if (&options() != &MessageOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
+  if (field_count() != proto->field_size() ||
+      nested_type_count() != proto->nested_type_size() ||
+      extension_count() != proto->extension_size()) {
+    GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
+    return;
+  }
+  for (int i = 0; i < field_count(); i++) {
+    field(i)->CopyJsonNameTo(proto->mutable_field(i));
+  }
+  for (int i = 0; i < nested_type_count(); i++) {
+    nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
+  }
+  for (int i = 0; i < extension_count(); i++) {
+    extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
+  }
+}
+
+void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
+  proto->set_name(name());
+  proto->set_number(number());
+  if (has_json_name_) {
+    proto->set_json_name(json_name());
+  }
+
+  // Some compilers do not allow static_cast directly between two enum types,
+  // so we must cast to int first.
+  proto->set_label(static_cast<FieldDescriptorProto::Label>(
+                     implicit_cast<int>(label())));
+  proto->set_type(static_cast<FieldDescriptorProto::Type>(
+                    implicit_cast<int>(type())));
+
+  if (is_extension()) {
+    if (!containing_type()->is_unqualified_placeholder_) {
+      proto->set_extendee(".");
+    }
+    proto->mutable_extendee()->append(containing_type()->full_name());
+  }
+
+  if (cpp_type() == CPPTYPE_MESSAGE) {
+    if (message_type()->is_placeholder_) {
+      // We don't actually know if the type is a message type.  It could be
+      // an enum.
+      proto->clear_type();
+    }
+
+    if (!message_type()->is_unqualified_placeholder_) {
+      proto->set_type_name(".");
+    }
+    proto->mutable_type_name()->append(message_type()->full_name());
+  } else if (cpp_type() == CPPTYPE_ENUM) {
+    if (!enum_type()->is_unqualified_placeholder_) {
+      proto->set_type_name(".");
+    }
+    proto->mutable_type_name()->append(enum_type()->full_name());
+  }
+
+  if (has_default_value()) {
+    proto->set_default_value(DefaultValueAsString(false));
+  }
+
+  if (containing_oneof() != NULL && !is_extension()) {
+    proto->set_oneof_index(containing_oneof()->index());
+  }
+
+  if (&options() != &FieldOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
+  proto->set_json_name(json_name());
+}
+
+void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
+  proto->set_name(name());
+}
+
+void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
+  proto->set_name(name());
+
+  for (int i = 0; i < value_count(); i++) {
+    value(i)->CopyTo(proto->add_value());
+  }
+
+  if (&options() != &EnumOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
+  proto->set_name(name());
+  proto->set_number(number());
+
+  if (&options() != &EnumValueOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
+  proto->set_name(name());
+
+  for (int i = 0; i < method_count(); i++) {
+    method(i)->CopyTo(proto->add_method());
+  }
+
+  if (&options() != &ServiceOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+}
+
+void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
+  proto->set_name(name());
+
+  if (!input_type()->is_unqualified_placeholder_) {
+    proto->set_input_type(".");
+  }
+  proto->mutable_input_type()->append(input_type()->full_name());
+
+  if (!output_type()->is_unqualified_placeholder_) {
+    proto->set_output_type(".");
+  }
+  proto->mutable_output_type()->append(output_type()->full_name());
+
+  if (&options() != &MethodOptions::default_instance()) {
+    proto->mutable_options()->CopyFrom(options());
+  }
+
+  if (client_streaming_) {
+    proto->set_client_streaming(true);
+  }
+  if (server_streaming_) {
+    proto->set_server_streaming(true);
+  }
+}
+
+// DebugString methods ===============================================
+
+namespace {
+
+// Used by each of the option formatters.
+bool RetrieveOptions(int depth,
+                     const Message &options,
+                     vector<string> *option_entries) {
+  option_entries->clear();
+  const Reflection* reflection = options.GetReflection();
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(options, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    int count = 1;
+    bool repeated = false;
+    if (fields[i]->is_repeated()) {
+      count = reflection->FieldSize(options, fields[i]);
+      repeated = true;
+    }
+    for (int j = 0; j < count; j++) {
+      string fieldval;
+      if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        string tmp;
+        TextFormat::Printer printer;
+        printer.SetInitialIndentLevel(depth + 1);
+        printer.PrintFieldValueToString(options, fields[i],
+                                        repeated ? j : -1, &tmp);
+        fieldval.append("{\n");
+        fieldval.append(tmp);
+        fieldval.append(depth * 2, ' ');
+        fieldval.append("}");
+      } else {
+        TextFormat::PrintFieldValueToString(options, fields[i],
+                                            repeated ? j : -1, &fieldval);
+      }
+      string name;
+      if (fields[i]->is_extension()) {
+        name = "(." + fields[i]->full_name() + ")";
+      } else {
+        name = fields[i]->name();
+      }
+      option_entries->push_back(name + " = " + fieldval);
+    }
+  }
+  return !option_entries->empty();
+}
+
+// Formats options that all appear together in brackets. Does not include
+// brackets.
+bool FormatBracketedOptions(int depth, const Message &options, string *output) {
+  vector<string> all_options;
+  if (RetrieveOptions(depth, options, &all_options)) {
+    output->append(Join(all_options, ", "));
+  }
+  return !all_options.empty();
+}
+
+// Formats options one per line
+bool FormatLineOptions(int depth, const Message &options, string *output) {
+  string prefix(depth * 2, ' ');
+  vector<string> all_options;
+  if (RetrieveOptions(depth, options, &all_options)) {
+    for (int i = 0; i < all_options.size(); i++) {
+      strings::SubstituteAndAppend(output, "$0option $1;\n",
+                                   prefix, all_options[i]);
+    }
+  }
+  return !all_options.empty();
+}
+
+class SourceLocationCommentPrinter {
+ public:
+  template<typename DescType>
+  SourceLocationCommentPrinter(const DescType* desc,
+                               const string& prefix,
+                               const DebugStringOptions& options)
+      : options_(options), prefix_(prefix) {
+    // Perform the SourceLocation lookup only if we're including user comments,
+    // because the lookup is fairly expensive.
+    have_source_loc_ = options.include_comments &&
+        desc->GetSourceLocation(&source_loc_);
+  }
+  SourceLocationCommentPrinter(const FileDescriptor* file,
+                               const vector<int>& path,
+                               const string& prefix,
+                               const DebugStringOptions& options)
+      : options_(options), prefix_(prefix) {
+    // Perform the SourceLocation lookup only if we're including user comments,
+    // because the lookup is fairly expensive.
+    have_source_loc_ = options.include_comments &&
+        file->GetSourceLocation(path, &source_loc_);
+  }
+  void AddPreComment(string* output) {
+    if (have_source_loc_) {
+      // Detached leading comments.
+      for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) {
+        *output += FormatComment(source_loc_.leading_detached_comments[i]);
+        *output += "\n";
+      }
+      // Attached leading comments.
+      if (!source_loc_.leading_comments.empty()) {
+        *output += FormatComment(source_loc_.leading_comments);
+      }
+    }
+  }
+  void AddPostComment(string* output) {
+    if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
+      *output += FormatComment(source_loc_.trailing_comments);
+    }
+  }
+
+  // Format comment such that each line becomes a full-line C++-style comment in
+  // the DebugString() output.
+  string FormatComment(const string& comment_text) {
+    string stripped_comment = comment_text;
+    StripWhitespace(&stripped_comment);
+    vector<string> lines = Split(stripped_comment, "\n");
+    string output;
+    for (int i = 0; i < lines.size(); ++i) {
+      const string& line = lines[i];
+      strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
+    }
+    return output;
+  }
+
+ private:
+
+  bool have_source_loc_;
+  SourceLocation source_loc_;
+  DebugStringOptions options_;
+  string prefix_;
+};
+
+}  // anonymous namespace
+
+string FileDescriptor::DebugString() const {
+  DebugStringOptions options;  // default options
+  return DebugStringWithOptions(options);
+}
+
+string FileDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& debug_string_options) const {
+  string contents;
+  {
+    vector<int> path;
+    path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
+    SourceLocationCommentPrinter syntax_comment(
+        this, path, "", debug_string_options);
+    syntax_comment.AddPreComment(&contents);
+    strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+                                 SyntaxName(syntax()));
+    syntax_comment.AddPostComment(&contents);
+  }
+
+  SourceLocationCommentPrinter
+      comment_printer(this, "", debug_string_options);
+  comment_printer.AddPreComment(&contents);
+
+  set<int> public_dependencies;
+  set<int> weak_dependencies;
+  public_dependencies.insert(public_dependencies_,
+                             public_dependencies_ + public_dependency_count_);
+  weak_dependencies.insert(weak_dependencies_,
+                           weak_dependencies_ + weak_dependency_count_);
+
+  for (int i = 0; i < dependency_count(); i++) {
+    if (public_dependencies.count(i) > 0) {
+      strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
+                                   dependency(i)->name());
+    } else if (weak_dependencies.count(i) > 0) {
+      strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
+                                   dependency(i)->name());
+    } else {
+      strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
+                                   dependency(i)->name());
+    }
+  }
+
+  if (!package().empty()) {
+    vector<int> path;
+    path.push_back(FileDescriptorProto::kPackageFieldNumber);
+    SourceLocationCommentPrinter package_comment(
+        this, path, "", debug_string_options);
+    package_comment.AddPreComment(&contents);
+    strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
+    package_comment.AddPostComment(&contents);
+  }
+
+  if (FormatLineOptions(0, options(), &contents)) {
+    contents.append("\n");  // add some space if we had options
+  }
+
+  for (int i = 0; i < enum_type_count(); i++) {
+    enum_type(i)->DebugString(0, &contents, debug_string_options);
+    contents.append("\n");
+  }
+
+  // Find all the 'group' type extensions; we will not output their nested
+  // definitions (those will be done with their group field descriptor).
+  set<const Descriptor*> groups;
+  for (int i = 0; i < extension_count(); i++) {
+    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
+      groups.insert(extension(i)->message_type());
+    }
+  }
+
+  for (int i = 0; i < message_type_count(); i++) {
+    if (groups.count(message_type(i)) == 0) {
+      message_type(i)->DebugString(0, &contents, debug_string_options,
+                                   /* include_opening_clause */ true);
+      contents.append("\n");
+    }
+  }
+
+  for (int i = 0; i < service_count(); i++) {
+    service(i)->DebugString(&contents, debug_string_options);
+    contents.append("\n");
+  }
+
+  const Descriptor* containing_type = NULL;
+  for (int i = 0; i < extension_count(); i++) {
+    if (extension(i)->containing_type() != containing_type) {
+      if (i > 0) contents.append("}\n\n");
+      containing_type = extension(i)->containing_type();
+      strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
+                                   containing_type->full_name());
+    }
+    extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents,
+                              debug_string_options);
+  }
+  if (extension_count() > 0) contents.append("}\n\n");
+
+  comment_printer.AddPostComment(&contents);
+
+  return contents;
+}
+
+string Descriptor::DebugString() const {
+  DebugStringOptions options;  // default options
+  return DebugStringWithOptions(options);
+}
+
+string Descriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(0, &contents, options, /* include_opening_clause */ true);
+  return contents;
+}
+
+void Descriptor::DebugString(int depth, string *contents,
+                             const DebugStringOptions&
+                             debug_string_options,
+                             bool include_opening_clause) const {
+  if (options().map_entry()) {
+    // Do not generate debug string for auto-generated map-entry type.
+    return;
+  }
+  string prefix(depth * 2, ' ');
+  ++depth;
+
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  if (include_opening_clause) {
+    strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
+  }
+  contents->append(" {\n");
+
+  FormatLineOptions(depth, options(), contents);
+
+  // Find all the 'group' types for fields and extensions; we will not output
+  // their nested definitions (those will be done with their group field
+  // descriptor).
+  set<const Descriptor*> groups;
+  for (int i = 0; i < field_count(); i++) {
+    if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
+      groups.insert(field(i)->message_type());
+    }
+  }
+  for (int i = 0; i < extension_count(); i++) {
+    if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
+      groups.insert(extension(i)->message_type());
+    }
+  }
+
+  for (int i = 0; i < nested_type_count(); i++) {
+    if (groups.count(nested_type(i)) == 0) {
+      nested_type(i)->DebugString(depth, contents, debug_string_options,
+                                  /* include_opening_clause */ true);
+    }
+  }
+  for (int i = 0; i < enum_type_count(); i++) {
+    enum_type(i)->DebugString(depth, contents, debug_string_options);
+  }
+  for (int i = 0; i < field_count(); i++) {
+    if (field(i)->containing_oneof() == NULL) {
+      field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents,
+                            debug_string_options);
+    } else if (field(i)->containing_oneof()->field(0) == field(i)) {
+      // This is the first field in this oneof, so print the whole oneof.
+      field(i)->containing_oneof()->DebugString(depth, contents,
+                                                debug_string_options);
+    }
+  }
+
+  for (int i = 0; i < extension_range_count(); i++) {
+    strings::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n",
+                                 prefix,
+                                 extension_range(i)->start,
+                                 extension_range(i)->end - 1);
+  }
+
+  // Group extensions by what they extend, so they can be printed out together.
+  const Descriptor* containing_type = NULL;
+  for (int i = 0; i < extension_count(); i++) {
+    if (extension(i)->containing_type() != containing_type) {
+      if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
+      containing_type = extension(i)->containing_type();
+      strings::SubstituteAndAppend(contents, "$0  extend .$1 {\n",
+                                   prefix, containing_type->full_name());
+    }
+    extension(i)->DebugString(
+        depth + 1, FieldDescriptor::PRINT_LABEL, contents,
+        debug_string_options);
+  }
+  if (extension_count() > 0)
+    strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
+
+  if (reserved_range_count() > 0) {
+    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    for (int i = 0; i < reserved_range_count(); i++) {
+      const Descriptor::ReservedRange* range = reserved_range(i);
+      if (range->end == range->start + 1) {
+        strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else {
+        strings::SubstituteAndAppend(contents, "$0 to $1, ",
+                                     range->start, range->end - 1);
+      }
+    }
+    contents->replace(contents->size() - 2, 2, ";\n");
+  }
+
+  if (reserved_name_count() > 0) {
+    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    for (int i = 0; i < reserved_name_count(); i++) {
+      strings::SubstituteAndAppend(contents, "\"$0\", ",
+                                   CEscape(reserved_name(i)));
+    }
+    contents->replace(contents->size() - 2, 2, ";\n");
+  }
+
+  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+  comment_printer.AddPostComment(contents);
+}
+
+string FieldDescriptor::DebugString() const {
+  DebugStringOptions options;  // default options
+  return DebugStringWithOptions(options);
+}
+
+string FieldDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& debug_string_options) const {
+  string contents;
+  int depth = 0;
+  if (is_extension()) {
+    strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
+                                 containing_type()->full_name());
+    depth = 1;
+  }
+  DebugString(depth, PRINT_LABEL, &contents, debug_string_options);
+  if (is_extension()) {
+    contents.append("}\n");
+  }
+  return contents;
+}
+
+// The field type string used in FieldDescriptor::DebugString()
+string FieldDescriptor::FieldTypeNameDebugString() const {
+  switch(type()) {
+    case TYPE_MESSAGE:
+      return "." + message_type()->full_name();
+    case TYPE_ENUM:
+      return "." + enum_type()->full_name();
+    default:
+      return kTypeToName[type()];
+  }
+}
+
+void FieldDescriptor::DebugString(int depth,
+                                  PrintLabelFlag print_label_flag,
+                                  string *contents,
+                                  const DebugStringOptions&
+                                  debug_string_options) const {
+  string prefix(depth * 2, ' ');
+  string field_type;
+
+  // Special case map fields.
+  if (is_map()) {
+    strings::SubstituteAndAppend(
+        &field_type, "map<$0, $1>",
+        message_type()->field(0)->FieldTypeNameDebugString(),
+        message_type()->field(1)->FieldTypeNameDebugString());
+  } else {
+    field_type = FieldTypeNameDebugString();
+  }
+
+  string label;
+  if (print_label_flag == PRINT_LABEL && !is_map()) {
+    label = kLabelToName[this->label()];
+    label.push_back(' ');
+  }
+
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4",
+                               prefix,
+                               label,
+                               field_type,
+                               type() == TYPE_GROUP ? message_type()->name() :
+                                                      name(),
+                               number());
+
+  bool bracketed = false;
+  if (has_default_value()) {
+    bracketed = true;
+    strings::SubstituteAndAppend(contents, " [default = $0",
+                                 DefaultValueAsString(true));
+  }
+
+  string formatted_options;
+  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
+    contents->append(bracketed ? ", " : " [");
+    bracketed = true;
+    contents->append(formatted_options);
+  }
+
+  if (bracketed) {
+    contents->append("]");
+  }
+
+  if (type() == TYPE_GROUP) {
+    if (debug_string_options.elide_group_body) {
+      contents->append(" { ... };\n");
+    } else {
+      message_type()->DebugString(depth, contents, debug_string_options,
+                                  /* include_opening_clause */ false);
+    }
+  } else {
+    contents->append(";\n");
+  }
+
+  comment_printer.AddPostComment(contents);
+}
+
+string OneofDescriptor::DebugString() const {
+  DebugStringOptions options;  // default values
+  return DebugStringWithOptions(options);
+}
+
+string OneofDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(0, &contents, options);
+  return contents;
+}
+
+void OneofDescriptor::DebugString(int depth, string* contents,
+                                  const DebugStringOptions&
+                                  debug_string_options) const {
+  string prefix(depth * 2, ' ');
+  ++depth;
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+  strings::SubstituteAndAppend(
+      contents, "$0 oneof $1 {", prefix, name());
+  if (debug_string_options.elide_oneof_body) {
+    contents->append(" ... }\n");
+  } else {
+    for (int i = 0; i < field_count(); i++) {
+      field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
+                            debug_string_options);
+    }
+    strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+  }
+  comment_printer.AddPostComment(contents);
+}
+
+string EnumDescriptor::DebugString() const {
+  DebugStringOptions options;  // default values
+  return DebugStringWithOptions(options);
+}
+
+string EnumDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(0, &contents, options);
+  return contents;
+}
+
+void EnumDescriptor::DebugString(int depth, string *contents,
+                                 const DebugStringOptions&
+                                 debug_string_options) const {
+  string prefix(depth * 2, ' ');
+  ++depth;
+
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  strings::SubstituteAndAppend(contents, "$0enum $1 {\n",
+                               prefix, name());
+
+  FormatLineOptions(depth, options(), contents);
+
+  for (int i = 0; i < value_count(); i++) {
+    value(i)->DebugString(depth, contents, debug_string_options);
+  }
+  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+
+  comment_printer.AddPostComment(contents);
+}
+
+string EnumValueDescriptor::DebugString() const {
+  DebugStringOptions options;  // default values
+  return DebugStringWithOptions(options);
+}
+
+string EnumValueDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(0, &contents, options);
+  return contents;
+}
+
+void EnumValueDescriptor::DebugString(int depth, string *contents,
+                                      const DebugStringOptions&
+                                      debug_string_options) const {
+  string prefix(depth * 2, ' ');
+
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  strings::SubstituteAndAppend(contents, "$0$1 = $2",
+                               prefix, name(), number());
+
+  string formatted_options;
+  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
+    strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
+  }
+  contents->append(";\n");
+
+  comment_printer.AddPostComment(contents);
+}
+
+string ServiceDescriptor::DebugString() const {
+  DebugStringOptions options;  // default values
+  return DebugStringWithOptions(options);
+}
+
+string ServiceDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(&contents, options);
+  return contents;
+}
+
+void ServiceDescriptor::DebugString(string *contents,
+                                    const DebugStringOptions&
+                                    debug_string_options) const {
+  SourceLocationCommentPrinter
+      comment_printer(this, /* prefix */ "", debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  strings::SubstituteAndAppend(contents, "service $0 {\n", name());
+
+  FormatLineOptions(1, options(), contents);
+
+  for (int i = 0; i < method_count(); i++) {
+    method(i)->DebugString(1, contents, debug_string_options);
+  }
+
+  contents->append("}\n");
+
+  comment_printer.AddPostComment(contents);
+}
+
+string MethodDescriptor::DebugString() const {
+  DebugStringOptions options;  // default values
+  return DebugStringWithOptions(options);
+}
+
+string MethodDescriptor::DebugStringWithOptions(
+    const DebugStringOptions& options) const {
+  string contents;
+  DebugString(0, &contents, options);
+  return contents;
+}
+
+void MethodDescriptor::DebugString(int depth, string *contents,
+                                   const DebugStringOptions&
+                                   debug_string_options) const {
+  string prefix(depth * 2, ' ');
+  ++depth;
+
+  SourceLocationCommentPrinter
+      comment_printer(this, prefix, debug_string_options);
+  comment_printer.AddPreComment(contents);
+
+  strings::SubstituteAndAppend(contents, "$0rpc $1($4.$2) returns ($5.$3)",
+                               prefix, name(),
+                               input_type()->full_name(),
+                               output_type()->full_name(),
+                               client_streaming() ? "stream " : "",
+                               server_streaming() ? "stream " : "");
+
+  string formatted_options;
+  if (FormatLineOptions(depth, options(), &formatted_options)) {
+    strings::SubstituteAndAppend(contents, " {\n$0$1}\n",
+                                 formatted_options, prefix);
+  } else {
+    contents->append(";\n");
+  }
+
+  comment_printer.AddPostComment(contents);
+}
+
+
+// Location methods ===============================================
+
+bool FileDescriptor::GetSourceLocation(const vector<int>& path,
+                                       SourceLocation* out_location) const {
+  GOOGLE_CHECK_NOTNULL(out_location);
+  if (source_code_info_) {
+    if (const SourceCodeInfo_Location* loc =
+        tables_->GetSourceLocation(path, source_code_info_)) {
+      const RepeatedField<int32>& span = loc->span();
+      if (span.size() == 3 || span.size() == 4) {
+        out_location->start_line   = span.Get(0);
+        out_location->start_column = span.Get(1);
+        out_location->end_line     = span.Get(span.size() == 3 ? 0 : 2);
+        out_location->end_column   = span.Get(span.size() - 1);
+
+        out_location->leading_comments = loc->leading_comments();
+        out_location->trailing_comments = loc->trailing_comments();
+        out_location->leading_detached_comments.assign(
+            loc->leading_detached_comments().begin(),
+            loc->leading_detached_comments().end());
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;  // empty path for root FileDescriptor
+  return GetSourceLocation(path, out_location);
+}
+
+bool FieldDescriptor::is_packed() const {
+  if (!is_packable()) return false;
+  if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+    return (options_ != NULL) && options_->packed();
+  } else {
+    return options_ == NULL || !options_->has_packed() || options_->packed();
+  }
+}
+
+bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return containing_type()->file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return service()->file()->GetSourceLocation(path, out_location);
+}
+
+bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumValueDescriptor::GetSourceLocation(
+    SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return type()->file()->GetSourceLocation(path, out_location);
+}
+
+void Descriptor::GetLocationPath(vector<int>* output) const {
+  if (containing_type()) {
+    containing_type()->GetLocationPath(output);
+    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
+    output->push_back(index());
+  } else {
+    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+    output->push_back(index());
+  }
+}
+
+void FieldDescriptor::GetLocationPath(vector<int>* output) const {
+  if (is_extension()) {
+    if (extension_scope() == NULL) {
+      output->push_back(FileDescriptorProto::kExtensionFieldNumber);
+      output->push_back(index());
+    } else {
+      extension_scope()->GetLocationPath(output);
+      output->push_back(DescriptorProto::kExtensionFieldNumber);
+      output->push_back(index());
+    }
+  } else {
+    containing_type()->GetLocationPath(output);
+    output->push_back(DescriptorProto::kFieldFieldNumber);
+    output->push_back(index());
+  }
+}
+
+void OneofDescriptor::GetLocationPath(vector<int>* output) const {
+  containing_type()->GetLocationPath(output);
+  output->push_back(DescriptorProto::kOneofDeclFieldNumber);
+  output->push_back(index());
+}
+
+void EnumDescriptor::GetLocationPath(vector<int>* output) const {
+  if (containing_type()) {
+    containing_type()->GetLocationPath(output);
+    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
+    output->push_back(index());
+  } else {
+    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+    output->push_back(index());
+  }
+}
+
+void EnumValueDescriptor::GetLocationPath(vector<int>* output) const {
+  type()->GetLocationPath(output);
+  output->push_back(EnumDescriptorProto::kValueFieldNumber);
+  output->push_back(index());
+}
+
+void ServiceDescriptor::GetLocationPath(vector<int>* output) const {
+  output->push_back(FileDescriptorProto::kServiceFieldNumber);
+  output->push_back(index());
+}
+
+void MethodDescriptor::GetLocationPath(vector<int>* output) const {
+  service()->GetLocationPath(output);
+  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
+  output->push_back(index());
+}
+
+// ===================================================================
+
+namespace {
+
+// Represents an options message to interpret. Extension names in the option
+// name are resolved relative to name_scope. element_name and orig_opt are
+// used only for error reporting (since the parser records locations against
+// pointers in the original options, not the mutable copy). The Message must be
+// one of the Options messages in descriptor.proto.
+struct OptionsToInterpret {
+  OptionsToInterpret(const string& ns,
+                     const string& el,
+                     const Message* orig_opt,
+                     Message* opt)
+      : name_scope(ns),
+        element_name(el),
+        original_options(orig_opt),
+        options(opt) {
+  }
+  string name_scope;
+  string element_name;
+  const Message* original_options;
+  Message* options;
+};
+
+}  // namespace
+
+class DescriptorBuilder {
+ public:
+  DescriptorBuilder(const DescriptorPool* pool,
+                    DescriptorPool::Tables* tables,
+                    DescriptorPool::ErrorCollector* error_collector);
+  ~DescriptorBuilder();
+
+  const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
+
+ private:
+  friend class OptionInterpreter;
+
+  // Non-recursive part of BuildFile functionality.
+  const FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto);
+
+  const DescriptorPool* pool_;
+  DescriptorPool::Tables* tables_;  // for convenience
+  DescriptorPool::ErrorCollector* error_collector_;
+
+  // As we build descriptors we store copies of the options messages in
+  // them. We put pointers to those copies in this vector, as we build, so we
+  // can later (after cross-linking) interpret those options.
+  vector<OptionsToInterpret> options_to_interpret_;
+
+  bool had_errors_;
+  string filename_;
+  FileDescriptor* file_;
+  FileDescriptorTables* file_tables_;
+  set<const FileDescriptor*> dependencies_;
+
+  // unused_dependency_ is used to record the unused imported files.
+  // Note: public import is not considered.
+  set<const FileDescriptor*> unused_dependency_;
+
+  // If LookupSymbol() finds a symbol that is in a file which is not a declared
+  // dependency of this file, it will fail, but will set
+  // possible_undeclared_dependency_ to point at that file.  This is only used
+  // by AddNotDefinedError() to report a more useful error message.
+  // possible_undeclared_dependency_name_ is the name of the symbol that was
+  // actually found in possible_undeclared_dependency_, which may be a parent
+  // of the symbol actually looked for.
+  const FileDescriptor* possible_undeclared_dependency_;
+  string possible_undeclared_dependency_name_;
+
+  // If LookupSymbol() could resolve a symbol which is not defined,
+  // record the resolved name.  This is only used by AddNotDefinedError()
+  // to report a more useful error message.
+  string undefine_resolved_name_;
+
+  void AddError(const string& element_name,
+                const Message& descriptor,
+                DescriptorPool::ErrorCollector::ErrorLocation location,
+                const string& error);
+  void AddError(const string& element_name,
+                const Message& descriptor,
+                DescriptorPool::ErrorCollector::ErrorLocation location,
+                const char* error);
+  void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
+  void AddTwiceListedError(const FileDescriptorProto& proto, int index);
+  void AddImportError(const FileDescriptorProto& proto, int index);
+
+  // Adds an error indicating that undefined_symbol was not defined.  Must
+  // only be called after LookupSymbol() fails.
+  void AddNotDefinedError(
+    const string& element_name,
+    const Message& descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    const string& undefined_symbol);
+
+  void AddWarning(const string& element_name, const Message& descriptor,
+                  DescriptorPool::ErrorCollector::ErrorLocation location,
+                  const string& error);
+
+  // Silly helper which determines if the given file is in the given package.
+  // I.e., either file->package() == package_name or file->package() is a
+  // nested package within package_name.
+  bool IsInPackage(const FileDescriptor* file, const string& package_name);
+
+  // Helper function which finds all public dependencies of the given file, and
+  // stores the them in the dependencies_ set in the builder.
+  void RecordPublicDependencies(const FileDescriptor* file);
+
+  // Like tables_->FindSymbol(), but additionally:
+  // - Search the pool's underlay if not found in tables_.
+  // - Insure that the resulting Symbol is from one of the file's declared
+  //   dependencies.
+  Symbol FindSymbol(const string& name);
+
+  // Like FindSymbol() but does not require that the symbol is in one of the
+  // file's declared dependencies.
+  Symbol FindSymbolNotEnforcingDeps(const string& name);
+
+  // This implements the body of FindSymbolNotEnforcingDeps().
+  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
+                                          const string& name);
+
+  // Like FindSymbol(), but looks up the name relative to some other symbol
+  // name.  This first searches siblings of relative_to, then siblings of its
+  // parents, etc.  For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
+  // the following calls, returning the first non-null result:
+  // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
+  // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
+  // on the DescriptorPool, this will generate a placeholder type if
+  // the name is not found (unless the name itself is malformed).  The
+  // placeholder_type parameter indicates what kind of placeholder should be
+  // constructed in this case.  The resolve_mode parameter determines whether
+  // any symbol is returned, or only symbols that are types.  Note, however,
+  // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
+  // if it believes that's all it could refer to.  The caller should always
+  // check that it receives the type of symbol it was expecting.
+  enum PlaceholderType {
+    PLACEHOLDER_MESSAGE,
+    PLACEHOLDER_ENUM,
+    PLACEHOLDER_EXTENDABLE_MESSAGE
+  };
+  enum ResolveMode {
+    LOOKUP_ALL, LOOKUP_TYPES
+  };
+  Symbol LookupSymbol(const string& name, const string& relative_to,
+                      PlaceholderType placeholder_type = PLACEHOLDER_MESSAGE,
+                      ResolveMode resolve_mode = LOOKUP_ALL);
+
+  // Like LookupSymbol() but will not return a placeholder even if
+  // AllowUnknownDependencies() has been used.
+  Symbol LookupSymbolNoPlaceholder(const string& name,
+                                   const string& relative_to,
+                                   ResolveMode resolve_mode = LOOKUP_ALL);
+
+  // Creates a placeholder type suitable for return from LookupSymbol().  May
+  // return kNullSymbol if the name is not a valid type name.
+  Symbol NewPlaceholder(const string& name, PlaceholderType placeholder_type);
+
+  // Creates a placeholder file.  Never returns NULL.  This is used when an
+  // import is not found and AllowUnknownDependencies() is enabled.
+  FileDescriptor* NewPlaceholderFile(const string& name);
+
+  // Calls tables_->AddSymbol() and records an error if it fails.  Returns
+  // true if successful or false if failed, though most callers can ignore
+  // the return value since an error has already been recorded.
+  bool AddSymbol(const string& full_name,
+                 const void* parent, const string& name,
+                 const Message& proto, Symbol symbol);
+
+  // Like AddSymbol(), but succeeds if the symbol is already defined as long
+  // as the existing definition is also a package (because it's OK to define
+  // the same package in two different files).  Also adds all parents of the
+  // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add
+  // "foo.bar" and "foo" to the table).
+  void AddPackage(const string& name, const Message& proto,
+                  const FileDescriptor* file);
+
+  // Checks that the symbol name contains only alphanumeric characters and
+  // underscores.  Records an error otherwise.
+  void ValidateSymbolName(const string& name, const string& full_name,
+                          const Message& proto);
+
+  // Like ValidateSymbolName(), but the name is allowed to contain periods and
+  // an error is indicated by returning false (not recording the error).
+  bool ValidateQualifiedName(const string& name);
+
+  // Used by BUILD_ARRAY macro (below) to avoid having to have the type
+  // specified as a macro parameter.
+  template <typename Type>
+  inline void AllocateArray(int size, Type** output) {
+    *output = tables_->AllocateArray<Type>(size);
+  }
+
+  // Allocates a copy of orig_options in tables_ and stores it in the
+  // descriptor. Remembers its uninterpreted options, to be interpreted
+  // later. DescriptorT must be one of the Descriptor messages from
+  // descriptor.proto.
+  template<class DescriptorT> void AllocateOptions(
+      const typename DescriptorT::OptionsType& orig_options,
+      DescriptorT* descriptor);
+  // Specialization for FileOptions.
+  void AllocateOptions(const FileOptions& orig_options,
+                       FileDescriptor* descriptor);
+
+  // Implementation for AllocateOptions(). Don't call this directly.
+  template<class DescriptorT> void AllocateOptionsImpl(
+      const string& name_scope,
+      const string& element_name,
+      const typename DescriptorT::OptionsType& orig_options,
+      DescriptorT* descriptor);
+
+  // These methods all have the same signature for the sake of the BUILD_ARRAY
+  // macro, below.
+  void BuildMessage(const DescriptorProto& proto,
+                    const Descriptor* parent,
+                    Descriptor* result);
+  void BuildFieldOrExtension(const FieldDescriptorProto& proto,
+                             const Descriptor* parent,
+                             FieldDescriptor* result,
+                             bool is_extension);
+  void BuildField(const FieldDescriptorProto& proto,
+                  const Descriptor* parent,
+                  FieldDescriptor* result) {
+    BuildFieldOrExtension(proto, parent, result, false);
+  }
+  void BuildExtension(const FieldDescriptorProto& proto,
+                      const Descriptor* parent,
+                      FieldDescriptor* result) {
+    BuildFieldOrExtension(proto, parent, result, true);
+  }
+  void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
+                           const Descriptor* parent,
+                           Descriptor::ExtensionRange* result);
+  void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
+                           const Descriptor* parent,
+                           Descriptor::ReservedRange* result);
+  void BuildOneof(const OneofDescriptorProto& proto,
+                  Descriptor* parent,
+                  OneofDescriptor* result);
+  void BuildEnum(const EnumDescriptorProto& proto,
+                 const Descriptor* parent,
+                 EnumDescriptor* result);
+  void BuildEnumValue(const EnumValueDescriptorProto& proto,
+                      const EnumDescriptor* parent,
+                      EnumValueDescriptor* result);
+  void BuildService(const ServiceDescriptorProto& proto,
+                    const void* dummy,
+                    ServiceDescriptor* result);
+  void BuildMethod(const MethodDescriptorProto& proto,
+                   const ServiceDescriptor* parent,
+                   MethodDescriptor* result);
+
+  void LogUnusedDependency(const FileDescriptorProto& proto,
+                           const FileDescriptor* result);
+
+  // Must be run only after building.
+  //
+  // NOTE: Options will not be available during cross-linking, as they
+  // have not yet been interpreted. Defer any handling of options to the
+  // Validate*Options methods.
+  void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
+  void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
+  void CrossLinkField(FieldDescriptor* field,
+                      const FieldDescriptorProto& proto);
+  void CrossLinkEnum(EnumDescriptor* enum_type,
+                     const EnumDescriptorProto& proto);
+  void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
+                          const EnumValueDescriptorProto& proto);
+  void CrossLinkService(ServiceDescriptor* service,
+                        const ServiceDescriptorProto& proto);
+  void CrossLinkMethod(MethodDescriptor* method,
+                       const MethodDescriptorProto& proto);
+
+  // Must be run only after cross-linking.
+  void InterpretOptions();
+
+  // A helper class for interpreting options.
+  class OptionInterpreter {
+   public:
+    // Creates an interpreter that operates in the context of the pool of the
+    // specified builder, which must not be NULL. We don't take ownership of the
+    // builder.
+    explicit OptionInterpreter(DescriptorBuilder* builder);
+
+    ~OptionInterpreter();
+
+    // Interprets the uninterpreted options in the specified Options message.
+    // On error, calls AddError() on the underlying builder and returns false.
+    // Otherwise returns true.
+    bool InterpretOptions(OptionsToInterpret* options_to_interpret);
+
+    class AggregateOptionFinder;
+
+   private:
+    // Interprets uninterpreted_option_ on the specified message, which
+    // must be the mutable copy of the original options message to which
+    // uninterpreted_option_ belongs.
+    bool InterpretSingleOption(Message* options);
+
+    // Adds the uninterpreted_option to the given options message verbatim.
+    // Used when AllowUnknownDependencies() is in effect and we can't find
+    // the option's definition.
+    void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
+                                Message* options);
+
+    // A recursive helper function that drills into the intermediate fields
+    // in unknown_fields to check if field innermost_field is set on the
+    // innermost message. Returns false and sets an error if so.
+    bool ExamineIfOptionIsSet(
+        vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
+        vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
+        const FieldDescriptor* innermost_field, const string& debug_msg_name,
+        const UnknownFieldSet& unknown_fields);
+
+    // Validates the value for the option field of the currently interpreted
+    // option and then sets it on the unknown_field.
+    bool SetOptionValue(const FieldDescriptor* option_field,
+                        UnknownFieldSet* unknown_fields);
+
+    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
+    // saves it into *unknown_fields.
+    bool SetAggregateOption(const FieldDescriptor* option_field,
+                            UnknownFieldSet* unknown_fields);
+
+    // Convenience functions to set an int field the right way, depending on
+    // its wire type (a single int CppType can represent multiple wire types).
+    void SetInt32(int number, int32 value, FieldDescriptor::Type type,
+                  UnknownFieldSet* unknown_fields);
+    void SetInt64(int number, int64 value, FieldDescriptor::Type type,
+                  UnknownFieldSet* unknown_fields);
+    void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
+                   UnknownFieldSet* unknown_fields);
+    void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
+                   UnknownFieldSet* unknown_fields);
+
+    // A helper function that adds an error at the specified location of the
+    // option we're currently interpreting, and returns false.
+    bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
+                        const string& msg) {
+      builder_->AddError(options_to_interpret_->element_name,
+                         *uninterpreted_option_, location, msg);
+      return false;
+    }
+
+    // A helper function that adds an error at the location of the option name
+    // and returns false.
+    bool AddNameError(const string& msg) {
+      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
+    }
+
+    // A helper function that adds an error at the location of the option name
+    // and returns false.
+    bool AddValueError(const string& msg) {
+      return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
+    }
+
+    // We interpret against this builder's pool. Is never NULL. We don't own
+    // this pointer.
+    DescriptorBuilder* builder_;
+
+    // The options we're currently interpreting, or NULL if we're not in a call
+    // to InterpretOptions.
+    const OptionsToInterpret* options_to_interpret_;
+
+    // The option we're currently interpreting within options_to_interpret_, or
+    // NULL if we're not in a call to InterpretOptions(). This points to a
+    // submessage of the original option, not the mutable copy. Therefore we
+    // can use it to find locations recorded by the parser.
+    const UninterpretedOption* uninterpreted_option_;
+
+    // Factory used to create the dynamic messages we need to parse
+    // any aggregate option values we encounter.
+    DynamicMessageFactory dynamic_factory_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
+  };
+
+  // Work-around for broken compilers:  According to the C++ standard,
+  // OptionInterpreter should have access to the private members of any class
+  // which has declared DescriptorBuilder as a friend.  Unfortunately some old
+  // versions of GCC and other compilers do not implement this correctly.  So,
+  // we have to have these intermediate methods to provide access.  We also
+  // redundantly declare OptionInterpreter a friend just to make things extra
+  // clear for these bad compilers.
+  friend class OptionInterpreter;
+  friend class OptionInterpreter::AggregateOptionFinder;
+
+  static inline bool get_allow_unknown(const DescriptorPool* pool) {
+    return pool->allow_unknown_;
+  }
+  static inline bool get_enforce_weak(const DescriptorPool* pool) {
+    return pool->enforce_weak_;
+  }
+  static inline bool get_is_placeholder(const Descriptor* descriptor) {
+    return descriptor->is_placeholder_;
+  }
+  static inline void assert_mutex_held(const DescriptorPool* pool) {
+    if (pool->mutex_ != NULL) {
+      pool->mutex_->AssertHeld();
+    }
+  }
+
+  // Must be run only after options have been interpreted.
+  //
+  // NOTE: Validation code must only reference the options in the mutable
+  // descriptors, which are the ones that have been interpreted. The const
+  // proto references are passed in only so they can be provided to calls to
+  // AddError(). Do not look at their options, which have not been interpreted.
+  void ValidateFileOptions(FileDescriptor* file,
+                           const FileDescriptorProto& proto);
+  void ValidateMessageOptions(Descriptor* message,
+                              const DescriptorProto& proto);
+  void ValidateFieldOptions(FieldDescriptor* field,
+                            const FieldDescriptorProto& proto);
+  void ValidateEnumOptions(EnumDescriptor* enm,
+                           const EnumDescriptorProto& proto);
+  void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
+                                const EnumValueDescriptorProto& proto);
+  void ValidateServiceOptions(ServiceDescriptor* service,
+                              const ServiceDescriptorProto& proto);
+  void ValidateMethodOptions(MethodDescriptor* method,
+                             const MethodDescriptorProto& proto);
+  void ValidateProto3(FileDescriptor* file,
+                      const FileDescriptorProto& proto);
+  void ValidateProto3Message(Descriptor* message,
+                             const DescriptorProto& proto);
+  void ValidateProto3Field(FieldDescriptor* field,
+                           const FieldDescriptorProto& proto);
+  void ValidateProto3Enum(EnumDescriptor* enm,
+                          const EnumDescriptorProto& proto);
+
+  // Returns true if the map entry message is compatible with the
+  // auto-generated entry message from map fields syntax.
+  bool ValidateMapEntry(FieldDescriptor* field,
+                        const FieldDescriptorProto& proto);
+
+  // Recursively detects naming conflicts with map entry types for a
+  // better error message.
+  void DetectMapConflicts(const Descriptor* message,
+                          const DescriptorProto& proto);
+
+};
+
+const FileDescriptor* DescriptorPool::BuildFile(
+    const FileDescriptorProto& proto) {
+  GOOGLE_CHECK(fallback_database_ == NULL)
+    << "Cannot call BuildFile on a DescriptorPool that uses a "
+       "DescriptorDatabase.  You must instead find a way to get your file "
+       "into the underlying database.";
+  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+  return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
+}
+
+const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
+    const FileDescriptorProto& proto,
+    ErrorCollector* error_collector) {
+  GOOGLE_CHECK(fallback_database_ == NULL)
+    << "Cannot call BuildFile on a DescriptorPool that uses a "
+       "DescriptorDatabase.  You must instead find a way to get your file "
+       "into the underlying database.";
+  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
+  tables_->known_bad_symbols_.clear();
+  tables_->known_bad_files_.clear();
+  return DescriptorBuilder(this, tables_.get(),
+                           error_collector).BuildFile(proto);
+}
+
+const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
+    const FileDescriptorProto& proto) const {
+  mutex_->AssertHeld();
+  if (tables_->known_bad_files_.count(proto.name()) > 0) {
+    return NULL;
+  }
+  const FileDescriptor* result =
+      DescriptorBuilder(this, tables_.get(),
+                        default_error_collector_).BuildFile(proto);
+  if (result == NULL) {
+    tables_->known_bad_files_.insert(proto.name());
+  }
+  return result;
+}
+
+DescriptorBuilder::DescriptorBuilder(
+    const DescriptorPool* pool,
+    DescriptorPool::Tables* tables,
+    DescriptorPool::ErrorCollector* error_collector)
+  : pool_(pool),
+    tables_(tables),
+    error_collector_(error_collector),
+    had_errors_(false),
+    possible_undeclared_dependency_(NULL),
+    undefine_resolved_name_("") {}
+
+DescriptorBuilder::~DescriptorBuilder() {}
+
+void DescriptorBuilder::AddError(
+    const string& element_name,
+    const Message& descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    const string& error) {
+  if (error_collector_ == NULL) {
+    if (!had_errors_) {
+      GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
+                 << "\":";
+    }
+    GOOGLE_LOG(ERROR) << "  " << element_name << ": " << error;
+  } else {
+    error_collector_->AddError(filename_, element_name,
+                               &descriptor, location, error);
+  }
+  had_errors_ = true;
+}
+
+void DescriptorBuilder::AddError(
+    const string& element_name,
+    const Message& descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    const char* error) {
+  AddError(element_name, descriptor, location, string(error));
+}
+
+void DescriptorBuilder::AddNotDefinedError(
+    const string& element_name,
+    const Message& descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    const string& undefined_symbol) {
+  if (possible_undeclared_dependency_ == NULL &&
+      undefine_resolved_name_.empty()) {
+    AddError(element_name, descriptor, location,
+             "\"" + undefined_symbol + "\" is not defined.");
+  } else {
+    if (possible_undeclared_dependency_ != NULL) {
+      AddError(element_name, descriptor, location,
+               "\"" + possible_undeclared_dependency_name_ +
+               "\" seems to be defined in \"" +
+               possible_undeclared_dependency_->name() + "\", which is not "
+               "imported by \"" + filename_ + "\".  To use it here, please "
+               "add the necessary import.");
+    }
+    if (!undefine_resolved_name_.empty()) {
+      AddError(element_name, descriptor, location,
+               "\"" + undefined_symbol + "\" is resolved to \"" +
+               undefine_resolved_name_ + "\", which is not defined. "
+               "The innermost scope is searched first in name resolution. "
+               "Consider using a leading '.'(i.e., \"."
+               + undefined_symbol +
+               "\") to start from the outermost scope.");
+    }
+  }
+}
+
+void DescriptorBuilder::AddWarning(
+    const string& element_name, const Message& descriptor,
+    DescriptorPool::ErrorCollector::ErrorLocation location,
+    const string& error) {
+  if (error_collector_ == NULL) {
+    GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
+  } else {
+    error_collector_->AddWarning(filename_, element_name, &descriptor, location,
+                                 error);
+  }
+}
+
+bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
+                                    const string& package_name) {
+  return HasPrefixString(file->package(), package_name) &&
+           (file->package().size() == package_name.size() ||
+            file->package()[package_name.size()] == '.');
+}
+
+void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
+  if (file == NULL || !dependencies_.insert(file).second) return;
+  for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
+    RecordPublicDependencies(file->public_dependency(i));
+  }
+}
+
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
+    const DescriptorPool* pool, const string& name) {
+  // If we are looking at an underlay, we must lock its mutex_, since we are
+  // accessing the underlay's tables_ directly.
+  MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
+
+  Symbol result = pool->tables_->FindSymbol(name);
+  if (result.IsNull() && pool->underlay_ != NULL) {
+    // Symbol not found; check the underlay.
+    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
+  }
+
+  if (result.IsNull()) {
+    // In theory, we shouldn't need to check fallback_database_ because the
+    // symbol should be in one of its file's direct dependencies, and we have
+    // already loaded those by the time we get here.  But we check anyway so
+    // that we can generate better error message when dependencies are missing
+    // (i.e., "missing dependency" rather than "type is not defined").
+    if (pool->TryFindSymbolInFallbackDatabase(name)) {
+      result = pool->tables_->FindSymbol(name);
+    }
+  }
+
+  return result;
+}
+
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
+  return FindSymbolNotEnforcingDepsHelper(pool_, name);
+}
+
+Symbol DescriptorBuilder::FindSymbol(const string& name) {
+  Symbol result = FindSymbolNotEnforcingDeps(name);
+
+  if (result.IsNull()) return result;
+
+  if (!pool_->enforce_dependencies_) {
+    // Hack for CompilerUpgrader.
+    return result;
+  }
+
+  // Only find symbols which were defined in this file or one of its
+  // dependencies.
+  const FileDescriptor* file = result.GetFile();
+  if (file == file_ || dependencies_.count(file) > 0) {
+    unused_dependency_.erase(file);
+    return result;
+  }
+
+  if (result.type == Symbol::PACKAGE) {
+    // Arg, this is overcomplicated.  The symbol is a package name.  It could
+    // be that the package was defined in multiple files.  result.GetFile()
+    // returns the first file we saw that used this package.  We've determined
+    // that that file is not a direct dependency of the file we are currently
+    // building, but it could be that some other file which *is* a direct
+    // dependency also defines the same package.  We can't really rule out this
+    // symbol unless none of the dependencies define it.
+    if (IsInPackage(file_, name)) return result;
+    for (set<const FileDescriptor*>::const_iterator it = dependencies_.begin();
+         it != dependencies_.end(); ++it) {
+      // Note:  A dependency may be NULL if it was not found or had errors.
+      if (*it != NULL && IsInPackage(*it, name)) return result;
+    }
+  }
+
+  possible_undeclared_dependency_ = file;
+  possible_undeclared_dependency_name_ = name;
+  return kNullSymbol;
+}
+
+Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
+    const string& name, const string& relative_to, ResolveMode resolve_mode) {
+  possible_undeclared_dependency_ = NULL;
+  undefine_resolved_name_.clear();
+
+  if (name.size() > 0 && name[0] == '.') {
+    // Fully-qualified name.
+    return FindSymbol(name.substr(1));
+  }
+
+  // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
+  // defined in multiple parent scopes, we only want to find "Bar.baz" in the
+  // innermost one.  E.g., the following should produce an error:
+  //   message Bar { message Baz {} }
+  //   message Foo {
+  //     message Bar {
+  //     }
+  //     optional Bar.Baz baz = 1;
+  //   }
+  // So, we look for just "Foo" first, then look for "Bar.baz" within it if
+  // found.
+  string::size_type name_dot_pos = name.find_first_of('.');
+  string first_part_of_name;
+  if (name_dot_pos == string::npos) {
+    first_part_of_name = name;
+  } else {
+    first_part_of_name = name.substr(0, name_dot_pos);
+  }
+
+  string scope_to_try(relative_to);
+
+  while (true) {
+    // Chop off the last component of the scope.
+    string::size_type dot_pos = scope_to_try.find_last_of('.');
+    if (dot_pos == string::npos) {
+      return FindSymbol(name);
+    } else {
+      scope_to_try.erase(dot_pos);
+    }
+
+    // Append ".first_part_of_name" and try to find.
+    string::size_type old_size = scope_to_try.size();
+    scope_to_try.append(1, '.');
+    scope_to_try.append(first_part_of_name);
+    Symbol result = FindSymbol(scope_to_try);
+    if (!result.IsNull()) {
+      if (first_part_of_name.size() < name.size()) {
+        // name is a compound symbol, of which we only found the first part.
+        // Now try to look up the rest of it.
+        if (result.IsAggregate()) {
+          scope_to_try.append(name, first_part_of_name.size(),
+                              name.size() - first_part_of_name.size());
+          result = FindSymbol(scope_to_try);
+          if (result.IsNull()) {
+            undefine_resolved_name_ = scope_to_try;
+          }
+          return result;
+        } else {
+          // We found a symbol but it's not an aggregate.  Continue the loop.
+        }
+      } else {
+        if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
+          // We found a symbol but it's not a type.  Continue the loop.
+        } else {
+          return result;
+        }
+      }
+    }
+
+    // Not found.  Remove the name so we can try again.
+    scope_to_try.erase(old_size);
+  }
+}
+
+Symbol DescriptorBuilder::LookupSymbol(
+    const string& name, const string& relative_to,
+    PlaceholderType placeholder_type, ResolveMode resolve_mode) {
+  Symbol result = LookupSymbolNoPlaceholder(
+      name, relative_to, resolve_mode);
+  if (result.IsNull() && pool_->allow_unknown_) {
+    // Not found, but AllowUnknownDependencies() is enabled.  Return a
+    // placeholder instead.
+    result = NewPlaceholder(name, placeholder_type);
+  }
+  return result;
+}
+
+Symbol DescriptorBuilder::NewPlaceholder(const string& name,
+                                         PlaceholderType placeholder_type) {
+  // Compute names.
+  const string* placeholder_full_name;
+  const string* placeholder_name;
+  const string* placeholder_package;
+
+  if (!ValidateQualifiedName(name)) return kNullSymbol;
+  if (name[0] == '.') {
+    // Fully-qualified.
+    placeholder_full_name = tables_->AllocateString(name.substr(1));
+  } else {
+    placeholder_full_name = tables_->AllocateString(name);
+  }
+
+  string::size_type dotpos = placeholder_full_name->find_last_of('.');
+  if (dotpos != string::npos) {
+    placeholder_package = tables_->AllocateString(
+      placeholder_full_name->substr(0, dotpos));
+    placeholder_name = tables_->AllocateString(
+      placeholder_full_name->substr(dotpos + 1));
+  } else {
+    placeholder_package = &internal::GetEmptyString();
+    placeholder_name = placeholder_full_name;
+  }
+
+  // Create the placeholders.
+  FileDescriptor* placeholder_file = NewPlaceholderFile(
+      *placeholder_full_name + ".placeholder.proto");
+  placeholder_file->package_ = placeholder_package;
+
+  if (placeholder_type == PLACEHOLDER_ENUM) {
+    placeholder_file->enum_type_count_ = 1;
+    placeholder_file->enum_types_ =
+      tables_->AllocateArray<EnumDescriptor>(1);
+
+    EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
+    memset(placeholder_enum, 0, sizeof(*placeholder_enum));
+
+    placeholder_enum->full_name_ = placeholder_full_name;
+    placeholder_enum->name_ = placeholder_name;
+    placeholder_enum->file_ = placeholder_file;
+    placeholder_enum->options_ = &EnumOptions::default_instance();
+    placeholder_enum->is_placeholder_ = true;
+    placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
+
+    // Enums must have at least one value.
+    placeholder_enum->value_count_ = 1;
+    placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
+
+    EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
+    memset(placeholder_value, 0, sizeof(*placeholder_value));
+
+    placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
+    // Note that enum value names are siblings of their type, not children.
+    placeholder_value->full_name_ =
+      placeholder_package->empty() ? placeholder_value->name_ :
+        tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE");
+
+    placeholder_value->number_ = 0;
+    placeholder_value->type_ = placeholder_enum;
+    placeholder_value->options_ = &EnumValueOptions::default_instance();
+
+    return Symbol(placeholder_enum);
+  } else {
+    placeholder_file->message_type_count_ = 1;
+    placeholder_file->message_types_ =
+      tables_->AllocateArray<Descriptor>(1);
+
+    Descriptor* placeholder_message = &placeholder_file->message_types_[0];
+    memset(placeholder_message, 0, sizeof(*placeholder_message));
+
+    placeholder_message->full_name_ = placeholder_full_name;
+    placeholder_message->name_ = placeholder_name;
+    placeholder_message->file_ = placeholder_file;
+    placeholder_message->options_ = &MessageOptions::default_instance();
+    placeholder_message->is_placeholder_ = true;
+    placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
+
+    if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
+      placeholder_message->extension_range_count_ = 1;
+      placeholder_message->extension_ranges_ =
+        tables_->AllocateArray<Descriptor::ExtensionRange>(1);
+      placeholder_message->extension_ranges_->start = 1;
+      // kMaxNumber + 1 because ExtensionRange::end is exclusive.
+      placeholder_message->extension_ranges_->end =
+        FieldDescriptor::kMaxNumber + 1;
+    }
+
+    return Symbol(placeholder_message);
+  }
+}
+
+FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
+    const string& name) {
+  FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
+  memset(placeholder, 0, sizeof(*placeholder));
+
+  placeholder->name_ = tables_->AllocateString(name);
+  placeholder->package_ = &internal::GetEmptyString();
+  placeholder->pool_ = pool_;
+  placeholder->options_ = &FileOptions::default_instance();
+  placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
+  placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
+  placeholder->is_placeholder_ = true;
+  placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;
+  // All other fields are zero or NULL.
+
+  return placeholder;
+}
+
+bool DescriptorBuilder::AddSymbol(
+    const string& full_name, const void* parent, const string& name,
+    const Message& proto, Symbol symbol) {
+  // If the caller passed NULL for the parent, the symbol is at file scope.
+  // Use its file as the parent instead.
+  if (parent == NULL) parent = file_;
+
+  if (tables_->AddSymbol(full_name, symbol)) {
+    if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
+      GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in "
+                     "symbols_by_name_, but was defined in symbols_by_parent_; "
+                     "this shouldn't be possible.";
+      return false;
+    }
+    return true;
+  } else {
+    const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
+    if (other_file == file_) {
+      string::size_type dot_pos = full_name.find_last_of('.');
+      if (dot_pos == string::npos) {
+        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+                 "\"" + full_name + "\" is already defined.");
+      } else {
+        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+                 "\"" + full_name.substr(dot_pos + 1) +
+                 "\" is already defined in \"" +
+                 full_name.substr(0, dot_pos) + "\".");
+      }
+    } else {
+      // Symbol seems to have been defined in a different file.
+      AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+               "\"" + full_name + "\" is already defined in file \"" +
+               other_file->name() + "\".");
+    }
+    return false;
+  }
+}
+
+void DescriptorBuilder::AddPackage(
+    const string& name, const Message& proto, const FileDescriptor* file) {
+  if (tables_->AddSymbol(name, Symbol(file))) {
+    // Success.  Also add parent package, if any.
+    string::size_type dot_pos = name.find_last_of('.');
+    if (dot_pos == string::npos) {
+      // No parents.
+      ValidateSymbolName(name, name, proto);
+    } else {
+      // Has parent.
+      string* parent_name = tables_->AllocateString(name.substr(0, dot_pos));
+      AddPackage(*parent_name, proto, file);
+      ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
+    }
+  } else {
+    Symbol existing_symbol = tables_->FindSymbol(name);
+    // It's OK to redefine a package.
+    if (existing_symbol.type != Symbol::PACKAGE) {
+      // Symbol seems to have been defined in a different file.
+      AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+               "\"" + name + "\" is already defined (as something other than "
+               "a package) in file \"" + existing_symbol.GetFile()->name() +
+               "\".");
+    }
+  }
+}
+
+void DescriptorBuilder::ValidateSymbolName(
+    const string& name, const string& full_name, const Message& proto) {
+  if (name.empty()) {
+    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+             "Missing name.");
+  } else {
+    for (int i = 0; i < name.size(); i++) {
+      // I don't trust isalnum() due to locales.  :(
+      if ((name[i] < 'a' || 'z' < name[i]) &&
+          (name[i] < 'A' || 'Z' < name[i]) &&
+          (name[i] < '0' || '9' < name[i]) &&
+          (name[i] != '_')) {
+        AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+                 "\"" + name + "\" is not a valid identifier.");
+      }
+    }
+  }
+}
+
+bool DescriptorBuilder::ValidateQualifiedName(const string& name) {
+  bool last_was_period = false;
+
+  for (int i = 0; i < name.size(); i++) {
+    // I don't trust isalnum() due to locales.  :(
+    if (('a' <= name[i] && name[i] <= 'z') ||
+        ('A' <= name[i] && name[i] <= 'Z') ||
+        ('0' <= name[i] && name[i] <= '9') ||
+        (name[i] == '_')) {
+      last_was_period = false;
+    } else if (name[i] == '.') {
+      if (last_was_period) return false;
+      last_was_period = true;
+    } else {
+      return false;
+    }
+  }
+
+  return !name.empty() && !last_was_period;
+}
+
+// -------------------------------------------------------------------
+
+// This generic implementation is good for all descriptors except
+// FileDescriptor.
+template<class DescriptorT> void DescriptorBuilder::AllocateOptions(
+    const typename DescriptorT::OptionsType& orig_options,
+    DescriptorT* descriptor) {
+  AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
+                      orig_options, descriptor);
+}
+
+// We specialize for FileDescriptor.
+void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
+                                        FileDescriptor* descriptor) {
+  // We add the dummy token so that LookupSymbol does the right thing.
+  AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(),
+                      orig_options, descriptor);
+}
+
+template<class DescriptorT> void DescriptorBuilder::AllocateOptionsImpl(
+    const string& name_scope,
+    const string& element_name,
+    const typename DescriptorT::OptionsType& orig_options,
+    DescriptorT* descriptor) {
+  // We need to use a dummy pointer to work around a bug in older versions of
+  // GCC.  Otherwise, the following two lines could be replaced with:
+  //   typename DescriptorT::OptionsType* options =
+  //       tables_->AllocateMessage<typename DescriptorT::OptionsType>();
+  typename DescriptorT::OptionsType* const dummy = NULL;
+  typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
+  // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
+  // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
+  // reflection based method, which requires the Descriptor. However, we are in
+  // the middle of building the descriptors, thus the deadlock.
+  options->ParseFromString(orig_options.SerializeAsString());
+  descriptor->options_ = options;
+
+  // Don't add to options_to_interpret_ unless there were uninterpreted
+  // options.  This not only avoids unnecessary work, but prevents a
+  // bootstrapping problem when building descriptors for descriptor.proto.
+  // descriptor.proto does not contain any uninterpreted options, but
+  // attempting to interpret options anyway will cause
+  // OptionsType::GetDescriptor() to be called which may then deadlock since
+  // we're still trying to build it.
+  if (options->uninterpreted_option_size() > 0) {
+    options_to_interpret_.push_back(
+        OptionsToInterpret(name_scope, element_name, &orig_options, options));
+  }
+}
+
+
+// A common pattern:  We want to convert a repeated field in the descriptor
+// to an array of values, calling some method to build each value.
+#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT)             \
+  OUTPUT->NAME##_count_ = INPUT.NAME##_size();                       \
+  AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_);             \
+  for (int i = 0; i < INPUT.NAME##_size(); i++) {                    \
+    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i);             \
+  }
+
+void DescriptorBuilder::AddRecursiveImportError(
+    const FileDescriptorProto& proto, int from_here) {
+  string error_message("File recursively imports itself: ");
+  for (int i = from_here; i < tables_->pending_files_.size(); i++) {
+    error_message.append(tables_->pending_files_[i]);
+    error_message.append(" -> ");
+  }
+  error_message.append(proto.name());
+
+  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
+           error_message);
+}
+
+void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
+                                            int index) {
+  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
+           "Import \"" + proto.dependency(index) + "\" was listed twice.");
+}
+
+void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
+                                       int index) {
+  string message;
+  if (pool_->fallback_database_ == NULL) {
+    message = "Import \"" + proto.dependency(index) +
+              "\" has not been loaded.";
+  } else {
+    message = "Import \"" + proto.dependency(index) +
+              "\" was not found or had errors.";
+  }
+  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message);
+}
+
+static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
+                                     const FileDescriptorProto& proto) {
+  FileDescriptorProto existing_proto;
+  existing_file->CopyTo(&existing_proto);
+  // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
+  // syntax="proto2".
+  if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+      proto.has_syntax()) {
+    existing_proto.set_syntax(
+        existing_file->SyntaxName(existing_file->syntax()));
+  }
+
+  return existing_proto.SerializeAsString() == proto.SerializeAsString();
+}
+
+const FileDescriptor* DescriptorBuilder::BuildFile(
+    const FileDescriptorProto& proto) {
+  filename_ = proto.name();
+
+  // Check if the file already exists and is identical to the one being built.
+  // Note:  This only works if the input is canonical -- that is, it
+  //   fully-qualifies all type names, has no UninterpretedOptions, etc.
+  //   This is fine, because this idempotency "feature" really only exists to
+  //   accommodate one hack in the proto1->proto2 migration layer.
+  const FileDescriptor* existing_file = tables_->FindFile(filename_);
+  if (existing_file != NULL) {
+    // File already in pool.  Compare the existing one to the input.
+    if (ExistingFileMatchesProto(existing_file, proto)) {
+      // They're identical.  Return the existing descriptor.
+      return existing_file;
+    }
+
+    // Not a match.  The error will be detected and handled later.
+  }
+
+  // Check to see if this file is already on the pending files list.
+  // TODO(kenton):  Allow recursive imports?  It may not work with some
+  //   (most?) programming languages.  E.g., in C++, a forward declaration
+  //   of a type is not sufficient to allow it to be used even in a
+  //   generated header file due to inlining.  This could perhaps be
+  //   worked around using tricks involving inserting #include statements
+  //   mid-file, but that's pretty ugly, and I'm pretty sure there are
+  //   some languages out there that do not allow recursive dependencies
+  //   at all.
+  for (int i = 0; i < tables_->pending_files_.size(); i++) {
+    if (tables_->pending_files_[i] == proto.name()) {
+      AddRecursiveImportError(proto, i);
+      return NULL;
+    }
+  }
+
+  // If we have a fallback_database_, attempt to load all dependencies now,
+  // before checkpointing tables_.  This avoids confusion with recursive
+  // checkpoints.
+  if (pool_->fallback_database_ != NULL) {
+    tables_->pending_files_.push_back(proto.name());
+    for (int i = 0; i < proto.dependency_size(); i++) {
+      if (tables_->FindFile(proto.dependency(i)) == NULL &&
+          (pool_->underlay_ == NULL ||
+           pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) {
+        // We don't care what this returns since we'll find out below anyway.
+        pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
+      }
+    }
+    tables_->pending_files_.pop_back();
+  }
+  return BuildFileImpl(proto);
+}
+
+const FileDescriptor* DescriptorBuilder::BuildFileImpl(
+    const FileDescriptorProto& proto) {
+  // Checkpoint the tables so that we can roll back if something goes wrong.
+  tables_->AddCheckpoint();
+
+  FileDescriptor* result = tables_->Allocate<FileDescriptor>();
+  file_ = result;
+
+  result->is_placeholder_ = false;
+  if (proto.has_source_code_info()) {
+    SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
+    info->CopyFrom(proto.source_code_info());
+    result->source_code_info_ = info;
+  } else {
+    result->source_code_info_ = &SourceCodeInfo::default_instance();
+  }
+
+  file_tables_ = tables_->AllocateFileTables();
+  file_->tables_ = file_tables_;
+
+  if (!proto.has_name()) {
+    AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
+             "Missing field: FileDescriptorProto.name.");
+  }
+
+  // TODO(liujisi): Report error when the syntax is empty after all the protos
+  // have added the syntax statement.
+  if (proto.syntax().empty() || proto.syntax() == "proto2") {
+    file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
+  } else if (proto.syntax() == "proto3") {
+    file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
+  } else {
+    file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
+    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
+             "Unrecognized syntax: " + proto.syntax());
+  }
+
+  result->name_ = tables_->AllocateString(proto.name());
+  if (proto.has_package()) {
+    result->package_ = tables_->AllocateString(proto.package());
+  } else {
+    // We cannot rely on proto.package() returning a valid string if
+    // proto.has_package() is false, because we might be running at static
+    // initialization time, in which case default values have not yet been
+    // initialized.
+    result->package_ = tables_->AllocateString("");
+  }
+  result->pool_ = pool_;
+
+  // Add to tables.
+  if (!tables_->AddFile(result)) {
+    AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
+             "A file with this name is already in the pool.");
+    // Bail out early so that if this is actually the exact same file, we
+    // don't end up reporting that every single symbol is already defined.
+    tables_->RollbackToLastCheckpoint();
+    return NULL;
+  }
+  if (!result->package().empty()) {
+    AddPackage(result->package(), proto, result);
+  }
+
+  // Make sure all dependencies are loaded.
+  set<string> seen_dependencies;
+  result->dependency_count_ = proto.dependency_size();
+  result->dependencies_ =
+    tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
+  unused_dependency_.clear();
+  set<int> weak_deps;
+  for (int i = 0; i < proto.weak_dependency_size(); ++i) {
+    weak_deps.insert(proto.weak_dependency(i));
+  }
+  for (int i = 0; i < proto.dependency_size(); i++) {
+    if (!seen_dependencies.insert(proto.dependency(i)).second) {
+      AddTwiceListedError(proto, i);
+    }
+
+    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
+    if (dependency == NULL && pool_->underlay_ != NULL) {
+      dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
+    }
+
+    if (dependency == NULL) {
+      if (pool_->allow_unknown_ ||
+          (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
+        dependency = NewPlaceholderFile(proto.dependency(i));
+      } else {
+        AddImportError(proto, i);
+      }
+    } else {
+      // Add to unused_dependency_ to track unused imported files.
+      // Note: do not track unused imported files for public import.
+      if (pool_->enforce_dependencies_ &&
+          (pool_->unused_import_track_files_.find(proto.name()) !=
+           pool_->unused_import_track_files_.end()) &&
+          (dependency->public_dependency_count() == 0)) {
+        unused_dependency_.insert(dependency);
+      }
+    }
+
+    result->dependencies_[i] = dependency;
+  }
+
+  // Check public dependencies.
+  int public_dependency_count = 0;
+  result->public_dependencies_ = tables_->AllocateArray<int>(
+      proto.public_dependency_size());
+  for (int i = 0; i < proto.public_dependency_size(); i++) {
+    // Only put valid public dependency indexes.
+    int index = proto.public_dependency(i);
+    if (index >= 0 && index < proto.dependency_size()) {
+      result->public_dependencies_[public_dependency_count++] = index;
+      // Do not track unused imported files for public import.
+      unused_dependency_.erase(result->dependency(index));
+    } else {
+      AddError(proto.name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "Invalid public dependency index.");
+    }
+  }
+  result->public_dependency_count_ = public_dependency_count;
+
+  // Build dependency set
+  dependencies_.clear();
+  for (int i = 0; i < result->dependency_count(); i++) {
+    RecordPublicDependencies(result->dependency(i));
+  }
+
+  // Check weak dependencies.
+  int weak_dependency_count = 0;
+  result->weak_dependencies_ = tables_->AllocateArray<int>(
+      proto.weak_dependency_size());
+  for (int i = 0; i < proto.weak_dependency_size(); i++) {
+    int index = proto.weak_dependency(i);
+    if (index >= 0 && index < proto.dependency_size()) {
+      result->weak_dependencies_[weak_dependency_count++] = index;
+    } else {
+      AddError(proto.name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "Invalid weak dependency index.");
+    }
+  }
+  result->weak_dependency_count_ = weak_dependency_count;
+
+  // Convert children.
+  BUILD_ARRAY(proto, result, message_type, BuildMessage  , NULL);
+  BUILD_ARRAY(proto, result, enum_type   , BuildEnum     , NULL);
+  BUILD_ARRAY(proto, result, service     , BuildService  , NULL);
+  BUILD_ARRAY(proto, result, extension   , BuildExtension, NULL);
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  // Note that the following steps must occur in exactly the specified order.
+
+  // Cross-link.
+  CrossLinkFile(result, proto);
+
+  // Interpret any remaining uninterpreted options gathered into
+  // options_to_interpret_ during descriptor building.  Cross-linking has made
+  // extension options known, so all interpretations should now succeed.
+  if (!had_errors_) {
+    OptionInterpreter option_interpreter(this);
+    for (vector<OptionsToInterpret>::iterator iter =
+             options_to_interpret_.begin();
+         iter != options_to_interpret_.end(); ++iter) {
+      option_interpreter.InterpretOptions(&(*iter));
+    }
+    options_to_interpret_.clear();
+  }
+
+  // Validate options.
+  if (!had_errors_) {
+    ValidateFileOptions(result, proto);
+  }
+
+  // Additional naming conflict check for map entry types. Only need to check
+  // this if there are already errors.
+  if (had_errors_) {
+    for (int i = 0; i < proto.message_type_size(); ++i) {
+      DetectMapConflicts(result->message_type(i), proto.message_type(i));
+    }
+  }
+
+
+  if (!unused_dependency_.empty()) {
+    LogUnusedDependency(proto, result);
+  }
+
+  if (had_errors_) {
+    tables_->RollbackToLastCheckpoint();
+    return NULL;
+  } else {
+    tables_->ClearLastCheckpoint();
+    return result;
+  }
+}
+
+void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
+                                     const Descriptor* parent,
+                                     Descriptor* result) {
+  const string& scope = (parent == NULL) ?
+    file_->package() : parent->full_name();
+  string* full_name = tables_->AllocateString(scope);
+  if (!full_name->empty()) full_name->append(1, '.');
+  full_name->append(proto.name());
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  result->name_            = tables_->AllocateString(proto.name());
+  result->full_name_       = full_name;
+  result->file_            = file_;
+  result->containing_type_ = parent;
+  result->is_placeholder_  = false;
+  result->is_unqualified_placeholder_ = false;
+
+  // Build oneofs first so that fields and extension ranges can refer to them.
+  BUILD_ARRAY(proto, result, oneof_decl     , BuildOneof         , result);
+  BUILD_ARRAY(proto, result, field          , BuildField         , result);
+  BUILD_ARRAY(proto, result, nested_type    , BuildMessage       , result);
+  BUILD_ARRAY(proto, result, enum_type      , BuildEnum          , result);
+  BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
+  BUILD_ARRAY(proto, result, extension      , BuildExtension     , result);
+  BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result);
+
+  // Copy reserved names.
+  int reserved_name_count = proto.reserved_name_size();
+  result->reserved_name_count_ = reserved_name_count;
+  result->reserved_names_ =
+      tables_->AllocateArray<const string*>(reserved_name_count);
+  for (int i = 0; i < reserved_name_count; ++i) {
+    result->reserved_names_[i] =
+        tables_->AllocateString(proto.reserved_name(i));
+  }
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  AddSymbol(result->full_name(), parent, result->name(),
+            proto, Symbol(result));
+
+  for (int i = 0; i < proto.reserved_range_size(); i++) {
+    const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
+    for (int j = i + 1; j < proto.reserved_range_size(); j++) {
+      const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
+      if (range1.end() > range2.start() && range2.end() > range1.start()) {
+        AddError(result->full_name(), proto.reserved_range(i),
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 strings::Substitute("Reserved range $0 to $1 overlaps with "
+                                     "already-defined range $2 to $3.",
+                                     range2.start(), range2.end() - 1,
+                                     range1.start(), range1.end() - 1));
+      }
+    }
+  }
+
+  hash_set<string> reserved_name_set;
+  for (int i = 0; i < proto.reserved_name_size(); i++) {
+    const string& name = proto.reserved_name(i);
+    if (reserved_name_set.find(name) == reserved_name_set.end()) {
+      reserved_name_set.insert(name);
+    } else {
+      AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+               strings::Substitute(
+                 "Field name \"$0\" is reserved multiple times.",
+                 name));
+    }
+  }
+
+  for (int i = 0; i < result->field_count(); i++) {
+    const FieldDescriptor* field = result->field(i);
+    for (int j = 0; j < result->extension_range_count(); j++) {
+      const Descriptor::ExtensionRange* range = result->extension_range(j);
+      if (range->start <= field->number() && field->number() < range->end) {
+        AddError(field->full_name(), proto.extension_range(j),
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 strings::Substitute(
+                   "Extension range $0 to $1 includes field \"$2\" ($3).",
+                   range->start, range->end - 1,
+                   field->name(), field->number()));
+      }
+    }
+    for (int j = 0; j < result->reserved_range_count(); j++) {
+      const Descriptor::ReservedRange* range = result->reserved_range(j);
+      if (range->start <= field->number() && field->number() < range->end) {
+        AddError(field->full_name(), proto.reserved_range(j),
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 strings::Substitute(
+                   "Field \"$0\" uses reserved number $1.",
+                   field->name(), field->number()));
+      }
+    }
+    if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
+      AddError(field->full_name(), proto.field(i),
+               DescriptorPool::ErrorCollector::NAME,
+               strings::Substitute(
+                 "Field name \"$0\" is reserved.", field->name()));
+    }
+  }
+
+  // Check that extension ranges don't overlap and don't include
+  // reserved field numbers.
+  for (int i = 0; i < result->extension_range_count(); i++) {
+    const Descriptor::ExtensionRange* range1 = result->extension_range(i);
+    for (int j = 0; j < result->reserved_range_count(); j++) {
+      const Descriptor::ReservedRange* range2 = result->reserved_range(j);
+      if (range1->end > range2->start && range2->end > range1->start) {
+        AddError(result->full_name(), proto.extension_range(j),
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 strings::Substitute("Extension range $0 to $1 overlaps with "
+                                     "reserved range $2 to $3.",
+                                     range1->start, range1->end - 1,
+                                     range2->start, range2->end - 1));
+      }
+    }
+    for (int j = i + 1; j < result->extension_range_count(); j++) {
+      const Descriptor::ExtensionRange* range2 = result->extension_range(j);
+      if (range1->end > range2->start && range2->end > range1->start) {
+        AddError(result->full_name(), proto.extension_range(j),
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 strings::Substitute("Extension range $0 to $1 overlaps with "
+                                     "already-defined range $2 to $3.",
+                                     range2->start, range2->end - 1,
+                                     range1->start, range1->end - 1));
+      }
+    }
+  }
+}
+
+
+void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
+                                              const Descriptor* parent,
+                                              FieldDescriptor* result,
+                                              bool is_extension) {
+  const string& scope = (parent == NULL) ?
+    file_->package() : parent->full_name();
+  string* full_name = tables_->AllocateString(scope);
+  if (!full_name->empty()) full_name->append(1, '.');
+  full_name->append(proto.name());
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  result->name_         = tables_->AllocateString(proto.name());
+  result->full_name_    = full_name;
+  result->file_         = file_;
+  result->number_       = proto.number();
+  result->is_extension_ = is_extension;
+
+  // If .proto files follow the style guide then the name should already be
+  // lower-cased.  If that's the case we can just reuse the string we already
+  // allocated rather than allocate a new one.
+  string lowercase_name(proto.name());
+  LowerString(&lowercase_name);
+  if (lowercase_name == proto.name()) {
+    result->lowercase_name_ = result->name_;
+  } else {
+    result->lowercase_name_ = tables_->AllocateString(lowercase_name);
+  }
+
+  // Don't bother with the above optimization for camel-case names since
+  // .proto files that follow the guide shouldn't be using names in this
+  // format, so the optimization wouldn't help much.
+  result->camelcase_name_ =
+      tables_->AllocateString(ToCamelCase(proto.name(),
+                                          /* lower_first = */ true));
+
+  if (proto.has_json_name()) {
+    result->has_json_name_ = true;
+    result->json_name_ = tables_->AllocateString(proto.json_name());
+  } else {
+    result->has_json_name_ = false;
+    result->json_name_ = result->camelcase_name_;
+  }
+
+  // Some compilers do not allow static_cast directly between two enum types,
+  // so we must cast to int first.
+  result->type_  = static_cast<FieldDescriptor::Type>(
+                     implicit_cast<int>(proto.type()));
+  result->label_ = static_cast<FieldDescriptor::Label>(
+                     implicit_cast<int>(proto.label()));
+
+  // An extension cannot have a required field (b/13365836).
+  if (result->is_extension_ &&
+      result->label_ == FieldDescriptor::LABEL_REQUIRED) {
+    AddError(result->full_name(), proto,
+             // Error location `TYPE`: we would really like to indicate
+             // `LABEL`, but the `ErrorLocation` enum has no entry for this, and
+             // we don't necessarily know about all implementations of the
+             // `ErrorCollector` interface to extend them to handle the new
+             // error location type properly.
+             DescriptorPool::ErrorCollector::TYPE,
+             "Message extensions cannot have required fields.");
+  }
+
+  // Some of these may be filled in when cross-linking.
+  result->containing_type_ = NULL;
+  result->extension_scope_ = NULL;
+  result->message_type_ = NULL;
+  result->enum_type_ = NULL;
+
+  result->has_default_value_ = proto.has_default_value();
+  if (proto.has_default_value() && result->is_repeated()) {
+    AddError(result->full_name(), proto,
+             DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+             "Repeated fields can't have default values.");
+  }
+
+  if (proto.has_type()) {
+    if (proto.has_default_value()) {
+      char* end_pos = NULL;
+      switch (result->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_INT32:
+          result->default_value_int32_ =
+            strtol(proto.default_value().c_str(), &end_pos, 0);
+          break;
+        case FieldDescriptor::CPPTYPE_INT64:
+          result->default_value_int64_ =
+            strto64(proto.default_value().c_str(), &end_pos, 0);
+          break;
+        case FieldDescriptor::CPPTYPE_UINT32:
+          result->default_value_uint32_ =
+            strtoul(proto.default_value().c_str(), &end_pos, 0);
+          break;
+        case FieldDescriptor::CPPTYPE_UINT64:
+          result->default_value_uint64_ =
+            strtou64(proto.default_value().c_str(), &end_pos, 0);
+          break;
+        case FieldDescriptor::CPPTYPE_FLOAT:
+          if (proto.default_value() == "inf") {
+            result->default_value_float_ = numeric_limits<float>::infinity();
+          } else if (proto.default_value() == "-inf") {
+            result->default_value_float_ = -numeric_limits<float>::infinity();
+          } else if (proto.default_value() == "nan") {
+            result->default_value_float_ = numeric_limits<float>::quiet_NaN();
+          } else  {
+            result->default_value_float_ = io::SafeDoubleToFloat(
+                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
+          }
+          break;
+        case FieldDescriptor::CPPTYPE_DOUBLE:
+          if (proto.default_value() == "inf") {
+            result->default_value_double_ = numeric_limits<double>::infinity();
+          } else if (proto.default_value() == "-inf") {
+            result->default_value_double_ = -numeric_limits<double>::infinity();
+          } else if (proto.default_value() == "nan") {
+            result->default_value_double_ = numeric_limits<double>::quiet_NaN();
+          } else  {
+            result->default_value_double_ =
+                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
+          }
+          break;
+        case FieldDescriptor::CPPTYPE_BOOL:
+          if (proto.default_value() == "true") {
+            result->default_value_bool_ = true;
+          } else if (proto.default_value() == "false") {
+            result->default_value_bool_ = false;
+          } else {
+            AddError(result->full_name(), proto,
+                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                     "Boolean default must be true or false.");
+          }
+          break;
+        case FieldDescriptor::CPPTYPE_ENUM:
+          // This will be filled in when cross-linking.
+          result->default_value_enum_ = NULL;
+          break;
+        case FieldDescriptor::CPPTYPE_STRING:
+          if (result->type() == FieldDescriptor::TYPE_BYTES) {
+            result->default_value_string_ = tables_->AllocateString(
+              UnescapeCEscapeString(proto.default_value()));
+          } else {
+            result->default_value_string_ =
+                tables_->AllocateString(proto.default_value());
+          }
+          break;
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          AddError(result->full_name(), proto,
+                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                   "Messages can't have default values.");
+          result->has_default_value_ = false;
+          break;
+      }
+
+      if (end_pos != NULL) {
+        // end_pos is only set non-NULL by the parsers for numeric types, above.
+        // This checks that the default was non-empty and had no extra junk
+        // after the end of the number.
+        if (proto.default_value().empty() || *end_pos != '\0') {
+          AddError(result->full_name(), proto,
+                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                   "Couldn't parse default value \"" + proto.default_value() +
+                   "\".");
+        }
+      }
+    } else {
+      // No explicit default value
+      switch (result->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_INT32:
+          result->default_value_int32_ = 0;
+          break;
+        case FieldDescriptor::CPPTYPE_INT64:
+          result->default_value_int64_ = 0;
+          break;
+        case FieldDescriptor::CPPTYPE_UINT32:
+          result->default_value_uint32_ = 0;
+          break;
+        case FieldDescriptor::CPPTYPE_UINT64:
+          result->default_value_uint64_ = 0;
+          break;
+        case FieldDescriptor::CPPTYPE_FLOAT:
+          result->default_value_float_ = 0.0f;
+          break;
+        case FieldDescriptor::CPPTYPE_DOUBLE:
+          result->default_value_double_ = 0.0;
+          break;
+        case FieldDescriptor::CPPTYPE_BOOL:
+          result->default_value_bool_ = false;
+          break;
+        case FieldDescriptor::CPPTYPE_ENUM:
+          // This will be filled in when cross-linking.
+          result->default_value_enum_ = NULL;
+          break;
+        case FieldDescriptor::CPPTYPE_STRING:
+          result->default_value_string_ = &internal::GetEmptyString();
+          break;
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          break;
+      }
+    }
+  }
+
+  if (result->number() <= 0) {
+    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
+             "Field numbers must be positive integers.");
+  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
+    // Only validate that the number is within the valid field range if it is
+    // not an extension. Since extension numbers are validated with the
+    // extendee's valid set of extension numbers, and those are in turn
+    // validated against the max allowed number, the check is unnecessary for
+    // extension fields.
+    // This avoids cross-linking issues that arise when attempting to check if
+    // the extendee is a message_set_wire_format message, which has a higher max
+    // on extension numbers.
+    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
+             strings::Substitute("Field numbers cannot be greater than $0.",
+                                 FieldDescriptor::kMaxNumber));
+  } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
+             result->number() <= FieldDescriptor::kLastReservedNumber) {
+    AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
+             strings::Substitute(
+               "Field numbers $0 through $1 are reserved for the protocol "
+               "buffer library implementation.",
+               FieldDescriptor::kFirstReservedNumber,
+               FieldDescriptor::kLastReservedNumber));
+  }
+
+  if (is_extension) {
+    if (!proto.has_extendee()) {
+      AddError(result->full_name(), proto,
+               DescriptorPool::ErrorCollector::EXTENDEE,
+               "FieldDescriptorProto.extendee not set for extension field.");
+    }
+
+    result->extension_scope_ = parent;
+
+    if (proto.has_oneof_index()) {
+      AddError(result->full_name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "FieldDescriptorProto.oneof_index should not be set for "
+               "extensions.");
+    }
+
+    // Fill in later (maybe).
+    result->containing_oneof_ = NULL;
+  } else {
+    if (proto.has_extendee()) {
+      AddError(result->full_name(), proto,
+               DescriptorPool::ErrorCollector::EXTENDEE,
+               "FieldDescriptorProto.extendee set for non-extension field.");
+    }
+
+    result->containing_type_ = parent;
+
+    if (proto.has_oneof_index()) {
+      if (proto.oneof_index() < 0 ||
+          proto.oneof_index() >= parent->oneof_decl_count()) {
+        AddError(result->full_name(), proto,
+                 DescriptorPool::ErrorCollector::OTHER,
+                 strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
+                                     "out of range for type \"$1\".",
+                                     proto.oneof_index(),
+                                     parent->name()));
+        result->containing_oneof_ = NULL;
+      } else {
+        result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
+      }
+    } else {
+      result->containing_oneof_ = NULL;
+    }
+  }
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+
+  AddSymbol(result->full_name(), parent, result->name(),
+            proto, Symbol(result));
+}
+
+void DescriptorBuilder::BuildExtensionRange(
+    const DescriptorProto::ExtensionRange& proto,
+    const Descriptor* parent,
+    Descriptor::ExtensionRange* result) {
+  result->start = proto.start();
+  result->end = proto.end();
+  if (result->start <= 0) {
+    AddError(parent->full_name(), proto,
+             DescriptorPool::ErrorCollector::NUMBER,
+             "Extension numbers must be positive integers.");
+  }
+
+  // Checking of the upper bound of the extension range is deferred until after
+  // options interpreting. This allows messages with message_set_wire_format to
+  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
+  // numbers are actually used as int32s in the message_set_wire_format.
+
+  if (result->start >= result->end) {
+    AddError(parent->full_name(), proto,
+             DescriptorPool::ErrorCollector::NUMBER,
+             "Extension range end number must be greater than start number.");
+  }
+}
+
+void DescriptorBuilder::BuildReservedRange(
+    const DescriptorProto::ReservedRange& proto,
+    const Descriptor* parent,
+    Descriptor::ReservedRange* result) {
+  result->start = proto.start();
+  result->end = proto.end();
+  if (result->start <= 0) {
+    AddError(parent->full_name(), proto,
+             DescriptorPool::ErrorCollector::NUMBER,
+             "Reserved numbers must be positive integers.");
+  }
+}
+
+void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
+                                   Descriptor* parent,
+                                   OneofDescriptor* result) {
+  string* full_name = tables_->AllocateString(parent->full_name());
+  full_name->append(1, '.');
+  full_name->append(proto.name());
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  result->name_ = tables_->AllocateString(proto.name());
+  result->full_name_ = full_name;
+
+  result->containing_type_ = parent;
+
+  // We need to fill these in later.
+  result->field_count_ = 0;
+  result->fields_ = NULL;
+
+  AddSymbol(result->full_name(), parent, result->name(),
+            proto, Symbol(result));
+}
+
+void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
+                                  const Descriptor* parent,
+                                  EnumDescriptor* result) {
+  const string& scope = (parent == NULL) ?
+    file_->package() : parent->full_name();
+  string* full_name = tables_->AllocateString(scope);
+  if (!full_name->empty()) full_name->append(1, '.');
+  full_name->append(proto.name());
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  result->name_            = tables_->AllocateString(proto.name());
+  result->full_name_       = full_name;
+  result->file_            = file_;
+  result->containing_type_ = parent;
+  result->is_placeholder_  = false;
+  result->is_unqualified_placeholder_ = false;
+
+  if (proto.value_size() == 0) {
+    // We cannot allow enums with no values because this would mean there
+    // would be no valid default value for fields of this type.
+    AddError(result->full_name(), proto,
+             DescriptorPool::ErrorCollector::NAME,
+             "Enums must contain at least one value.");
+  }
+
+  BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  AddSymbol(result->full_name(), parent, result->name(),
+            proto, Symbol(result));
+}
+
+void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
+                                       const EnumDescriptor* parent,
+                                       EnumValueDescriptor* result) {
+  result->name_   = tables_->AllocateString(proto.name());
+  result->number_ = proto.number();
+  result->type_   = parent;
+
+  // Note:  full_name for enum values is a sibling to the parent's name, not a
+  //   child of it.
+  string* full_name = tables_->AllocateString(*parent->full_name_);
+  full_name->resize(full_name->size() - parent->name_->size());
+  full_name->append(*result->name_);
+  result->full_name_ = full_name;
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  // Again, enum values are weird because we makes them appear as siblings
+  // of the enum type instead of children of it.  So, we use
+  // parent->containing_type() as the value's parent.
+  bool added_to_outer_scope =
+    AddSymbol(result->full_name(), parent->containing_type(), result->name(),
+              proto, Symbol(result));
+
+  // However, we also want to be able to search for values within a single
+  // enum type, so we add it as a child of the enum type itself, too.
+  // Note:  This could fail, but if it does, the error has already been
+  //   reported by the above AddSymbol() call, so we ignore the return code.
+  bool added_to_inner_scope =
+    file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
+
+  if (added_to_inner_scope && !added_to_outer_scope) {
+    // This value did not conflict with any values defined in the same enum,
+    // but it did conflict with some other symbol defined in the enum type's
+    // scope.  Let's print an additional error to explain this.
+    string outer_scope;
+    if (parent->containing_type() == NULL) {
+      outer_scope = file_->package();
+    } else {
+      outer_scope = parent->containing_type()->full_name();
+    }
+
+    if (outer_scope.empty()) {
+      outer_scope = "the global scope";
+    } else {
+      outer_scope = "\"" + outer_scope + "\"";
+    }
+
+    AddError(result->full_name(), proto,
+             DescriptorPool::ErrorCollector::NAME,
+             "Note that enum values use C++ scoping rules, meaning that "
+             "enum values are siblings of their type, not children of it.  "
+             "Therefore, \"" + result->name() + "\" must be unique within "
+             + outer_scope + ", not just within \"" + parent->name() + "\".");
+  }
+
+  // An enum is allowed to define two numbers that refer to the same value.
+  // FindValueByNumber() should return the first such value, so we simply
+  // ignore AddEnumValueByNumber()'s return code.
+  file_tables_->AddEnumValueByNumber(result);
+}
+
+void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
+                                     const void* /* dummy */,
+                                     ServiceDescriptor* result) {
+  string* full_name = tables_->AllocateString(file_->package());
+  if (!full_name->empty()) full_name->append(1, '.');
+  full_name->append(proto.name());
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  result->name_      = tables_->AllocateString(proto.name());
+  result->full_name_ = full_name;
+  result->file_      = file_;
+
+  BUILD_ARRAY(proto, result, method, BuildMethod, result);
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  AddSymbol(result->full_name(), NULL, result->name(),
+            proto, Symbol(result));
+}
+
+void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
+                                    const ServiceDescriptor* parent,
+                                    MethodDescriptor* result) {
+  result->name_    = tables_->AllocateString(proto.name());
+  result->service_ = parent;
+
+  string* full_name = tables_->AllocateString(parent->full_name());
+  full_name->append(1, '.');
+  full_name->append(*result->name_);
+  result->full_name_ = full_name;
+
+  ValidateSymbolName(proto.name(), *full_name, proto);
+
+  // These will be filled in when cross-linking.
+  result->input_type_ = NULL;
+  result->output_type_ = NULL;
+
+  // Copy options.
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptions(proto.options(), result);
+  }
+
+  result->client_streaming_ = proto.client_streaming();
+  result->server_streaming_ = proto.server_streaming();
+
+  AddSymbol(result->full_name(), parent, result->name(),
+            proto, Symbol(result));
+}
+
+#undef BUILD_ARRAY
+
+// -------------------------------------------------------------------
+
+void DescriptorBuilder::CrossLinkFile(
+    FileDescriptor* file, const FileDescriptorProto& proto) {
+  if (file->options_ == NULL) {
+    file->options_ = &FileOptions::default_instance();
+  }
+
+  for (int i = 0; i < file->message_type_count(); i++) {
+    CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
+  }
+
+  for (int i = 0; i < file->extension_count(); i++) {
+    CrossLinkField(&file->extensions_[i], proto.extension(i));
+  }
+
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
+  }
+
+  for (int i = 0; i < file->service_count(); i++) {
+    CrossLinkService(&file->services_[i], proto.service(i));
+  }
+}
+
+void DescriptorBuilder::CrossLinkMessage(
+    Descriptor* message, const DescriptorProto& proto) {
+  if (message->options_ == NULL) {
+    message->options_ = &MessageOptions::default_instance();
+  }
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
+  }
+
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
+  }
+
+  for (int i = 0; i < message->field_count(); i++) {
+    CrossLinkField(&message->fields_[i], proto.field(i));
+  }
+
+  for (int i = 0; i < message->extension_count(); i++) {
+    CrossLinkField(&message->extensions_[i], proto.extension(i));
+  }
+
+  // Set up field array for each oneof.
+
+  // First count the number of fields per oneof.
+  for (int i = 0; i < message->field_count(); i++) {
+    const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
+    if (oneof_decl != NULL) {
+      // Make sure fields belonging to the same oneof are defined consecutively.
+      // This enables optimizations in codegens and reflection libraries to
+      // skip fields in the oneof group, as only one of the field can be set.
+      // Note that field_count() returns how many fields in this oneof we have
+      // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
+      // safe.
+      if (oneof_decl->field_count() > 0 &&
+          message->field(i - 1)->containing_oneof() != oneof_decl) {
+        AddError(
+            message->full_name() + "." + message->field(i - 1)->name(),
+            proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
+            strings::Substitute(
+                "Fields in the same oneof must be defined consecutively. "
+                "\"$0\" cannot be defined before the completion of the "
+                "\"$1\" oneof definition.",
+                message->field(i - 1)->name(), oneof_decl->name()));
+      }
+      // Must go through oneof_decls_ array to get a non-const version of the
+      // OneofDescriptor.
+      ++message->oneof_decls_[oneof_decl->index()].field_count_;
+    }
+  }
+
+  // Then allocate the arrays.
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
+
+    if (oneof_decl->field_count() == 0) {
+      AddError(message->full_name() + "." + oneof_decl->name(),
+               proto.oneof_decl(i),
+               DescriptorPool::ErrorCollector::NAME,
+               "Oneof must have at least one field.");
+    }
+
+    oneof_decl->fields_ =
+      tables_->AllocateArray<const FieldDescriptor*>(oneof_decl->field_count_);
+    oneof_decl->field_count_ = 0;
+  }
+
+  // Then fill them in.
+  for (int i = 0; i < message->field_count(); i++) {
+    const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
+    if (oneof_decl != NULL) {
+      OneofDescriptor* mutable_oneof_decl =
+          &message->oneof_decls_[oneof_decl->index()];
+      message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
+      mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] =
+          message->field(i);
+    }
+  }
+}
+
+void DescriptorBuilder::CrossLinkField(
+    FieldDescriptor* field, const FieldDescriptorProto& proto) {
+  if (field->options_ == NULL) {
+    field->options_ = &FieldOptions::default_instance();
+  }
+
+  if (proto.has_extendee()) {
+    Symbol extendee = LookupSymbol(proto.extendee(), field->full_name(),
+                                   PLACEHOLDER_EXTENDABLE_MESSAGE);
+    if (extendee.IsNull()) {
+      AddNotDefinedError(field->full_name(), proto,
+                         DescriptorPool::ErrorCollector::EXTENDEE,
+                         proto.extendee());
+      return;
+    } else if (extendee.type != Symbol::MESSAGE) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::EXTENDEE,
+               "\"" + proto.extendee() + "\" is not a message type.");
+      return;
+    }
+    field->containing_type_ = extendee.descriptor;
+
+    const Descriptor::ExtensionRange* extension_range = field->containing_type()
+        ->FindExtensionRangeContainingNumber(field->number());
+
+    if (extension_range == NULL) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::NUMBER,
+               strings::Substitute("\"$0\" does not declare $1 as an "
+                                   "extension number.",
+                                   field->containing_type()->full_name(),
+                                   field->number()));
+    }
+  }
+
+  if (field->containing_oneof() != NULL) {
+    if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
+      // Note that this error will never happen when parsing .proto files.
+      // It can only happen if you manually construct a FileDescriptorProto
+      // that is incorrect.
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::NAME,
+               "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
+    }
+  }
+
+  if (proto.has_type_name()) {
+    // Assume we are expecting a message type unless the proto contains some
+    // evidence that it expects an enum type.  This only makes a difference if
+    // we end up creating a placeholder.
+    bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
+                          proto.has_default_value();
+
+    Symbol type =
+      LookupSymbol(proto.type_name(), field->full_name(),
+                   expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE,
+                   LOOKUP_TYPES);
+
+    // If the type is a weak type, we change the type to a google.protobuf.Empty field.
+    if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) {
+      type = FindSymbol(kNonLinkedWeakMessageReplacementName);
+    }
+
+    if (type.IsNull()) {
+      AddNotDefinedError(field->full_name(), proto,
+                         DescriptorPool::ErrorCollector::TYPE,
+                         proto.type_name());
+      return;
+    }
+
+    if (!proto.has_type()) {
+      // Choose field type based on symbol.
+      if (type.type == Symbol::MESSAGE) {
+        field->type_ = FieldDescriptor::TYPE_MESSAGE;
+      } else if (type.type == Symbol::ENUM) {
+        field->type_ = FieldDescriptor::TYPE_ENUM;
+      } else {
+        AddError(field->full_name(), proto,
+                 DescriptorPool::ErrorCollector::TYPE,
+                 "\"" + proto.type_name() + "\" is not a type.");
+        return;
+      }
+    }
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (type.type != Symbol::MESSAGE) {
+        AddError(field->full_name(), proto,
+                 DescriptorPool::ErrorCollector::TYPE,
+                 "\"" + proto.type_name() + "\" is not a message type.");
+        return;
+      }
+      field->message_type_ = type.descriptor;
+
+      if (field->has_default_value()) {
+        AddError(field->full_name(), proto,
+                 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                 "Messages can't have default values.");
+      }
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      if (type.type != Symbol::ENUM) {
+        AddError(field->full_name(), proto,
+                 DescriptorPool::ErrorCollector::TYPE,
+                 "\"" + proto.type_name() + "\" is not an enum type.");
+        return;
+      }
+      field->enum_type_ = type.enum_descriptor;
+
+      if (field->enum_type()->is_placeholder_) {
+        // We can't look up default values for placeholder types.  We'll have
+        // to just drop them.
+        field->has_default_value_ = false;
+      }
+
+      if (field->has_default_value()) {
+        // Ensure that the default value is an identifier. Parser cannot always
+        // verify this because it does not have complete type information.
+        // N.B. that this check yields better error messages but is not
+        // necessary for correctness (an enum symbol must be a valid identifier
+        // anyway), only for better errors.
+        if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
+          AddError(field->full_name(), proto,
+                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                   "Default value for an enum field must be an identifier.");
+        } else {
+          // We can't just use field->enum_type()->FindValueByName() here
+          // because that locks the pool's mutex, which we have already locked
+          // at this point.
+          Symbol default_value =
+            LookupSymbolNoPlaceholder(proto.default_value(),
+                                      field->enum_type()->full_name());
+
+          if (default_value.type == Symbol::ENUM_VALUE &&
+              default_value.enum_value_descriptor->type() ==
+              field->enum_type()) {
+            field->default_value_enum_ = default_value.enum_value_descriptor;
+          } else {
+            AddError(field->full_name(), proto,
+                     DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+                     "Enum type \"" + field->enum_type()->full_name() +
+                     "\" has no value named \"" + proto.default_value() +
+                     "\".");
+          }
+        }
+      } else if (field->enum_type()->value_count() > 0) {
+        // All enums must have at least one value, or we would have reported
+        // an error elsewhere.  We use the first defined value as the default
+        // if a default is not explicitly defined.
+        field->default_value_enum_ = field->enum_type()->value(0);
+      }
+    } else {
+      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+               "Field with primitive type has type_name.");
+    }
+  } else {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+        field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+               "Field with message or enum type missing type_name.");
+    }
+  }
+
+  // Add the field to the fields-by-number table.
+  // Note:  We have to do this *after* cross-linking because extensions do not
+  //   know their containing type until now.
+  if (!file_tables_->AddFieldByNumber(field)) {
+    const FieldDescriptor* conflicting_field =
+      file_tables_->FindFieldByNumber(field->containing_type(),
+                                      field->number());
+    if (field->is_extension()) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::NUMBER,
+               strings::Substitute("Extension number $0 has already been used "
+                                   "in \"$1\" by extension \"$2\".",
+                                   field->number(),
+                                   field->containing_type()->full_name(),
+                                   conflicting_field->full_name()));
+    } else {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::NUMBER,
+               strings::Substitute("Field number $0 has already been used in "
+                                   "\"$1\" by field \"$2\".",
+                                   field->number(),
+                                   field->containing_type()->full_name(),
+                                   conflicting_field->name()));
+    }
+  } else {
+    if (field->is_extension()) {
+      if (!tables_->AddExtension(field)) {
+        const FieldDescriptor* conflicting_field =
+            tables_->FindExtension(field->containing_type(), field->number());
+        string error_msg = strings::Substitute(
+            "Extension number $0 has already been used in \"$1\" by extension "
+            "\"$2\" defined in $3.",
+            field->number(),
+            field->containing_type()->full_name(),
+            conflicting_field->full_name(),
+            conflicting_field->file()->name());
+        // Conflicting extension numbers should be an error. However, before
+        // turning this into an error we need to fix all existing broken
+        // protos first.
+        // TODO(xiaofeng): Change this to an error.
+        AddWarning(field->full_name(), proto,
+                   DescriptorPool::ErrorCollector::NUMBER, error_msg);
+      }
+    }
+  }
+
+  // Add the field to the lowercase-name and camelcase-name tables.
+  file_tables_->AddFieldByStylizedNames(field);
+}
+
+void DescriptorBuilder::CrossLinkEnum(
+    EnumDescriptor* enum_type, const EnumDescriptorProto& proto) {
+  if (enum_type->options_ == NULL) {
+    enum_type->options_ = &EnumOptions::default_instance();
+  }
+
+  for (int i = 0; i < enum_type->value_count(); i++) {
+    CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
+  }
+}
+
+void DescriptorBuilder::CrossLinkEnumValue(
+    EnumValueDescriptor* enum_value,
+    const EnumValueDescriptorProto& /* proto */) {
+  if (enum_value->options_ == NULL) {
+    enum_value->options_ = &EnumValueOptions::default_instance();
+  }
+}
+
+void DescriptorBuilder::CrossLinkService(
+    ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
+  if (service->options_ == NULL) {
+    service->options_ = &ServiceOptions::default_instance();
+  }
+
+  for (int i = 0; i < service->method_count(); i++) {
+    CrossLinkMethod(&service->methods_[i], proto.method(i));
+  }
+}
+
+void DescriptorBuilder::CrossLinkMethod(
+    MethodDescriptor* method, const MethodDescriptorProto& proto) {
+  if (method->options_ == NULL) {
+    method->options_ = &MethodOptions::default_instance();
+  }
+
+  Symbol input_type = LookupSymbol(proto.input_type(), method->full_name());
+  if (input_type.IsNull()) {
+    AddNotDefinedError(method->full_name(), proto,
+                       DescriptorPool::ErrorCollector::INPUT_TYPE,
+                       proto.input_type());
+  } else if (input_type.type != Symbol::MESSAGE) {
+    AddError(method->full_name(), proto,
+             DescriptorPool::ErrorCollector::INPUT_TYPE,
+             "\"" + proto.input_type() + "\" is not a message type.");
+  } else {
+    method->input_type_ = input_type.descriptor;
+  }
+
+  Symbol output_type = LookupSymbol(proto.output_type(), method->full_name());
+  if (output_type.IsNull()) {
+    AddNotDefinedError(method->full_name(), proto,
+                       DescriptorPool::ErrorCollector::OUTPUT_TYPE,
+                       proto.output_type());
+  } else if (output_type.type != Symbol::MESSAGE) {
+    AddError(method->full_name(), proto,
+             DescriptorPool::ErrorCollector::OUTPUT_TYPE,
+             "\"" + proto.output_type() + "\" is not a message type.");
+  } else {
+    method->output_type_ = output_type.descriptor;
+  }
+}
+
+// -------------------------------------------------------------------
+
+#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type)  \
+  for (int i = 0; i < descriptor->array_name##_count(); ++i) {     \
+    Validate##type##Options(descriptor->array_name##s_ + i,        \
+                            proto.array_name(i));                  \
+  }
+
+// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
+// avoid problems that exist at init time.
+static bool IsLite(const FileDescriptor* file) {
+  // TODO(kenton):  I don't even remember how many of these conditions are
+  //   actually possible.  I'm just being super-safe.
+  return file != NULL &&
+         &file->options() != &FileOptions::default_instance() &&
+         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
+}
+
+void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
+                                            const FileDescriptorProto& proto) {
+  VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
+  VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
+  VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
+  VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
+
+  // Lite files can only be imported by other Lite files.
+  if (!IsLite(file)) {
+    for (int i = 0; i < file->dependency_count(); i++) {
+      if (IsLite(file->dependency(i))) {
+        AddError(
+          file->name(), proto,
+          DescriptorPool::ErrorCollector::OTHER,
+          "Files that do not use optimize_for = LITE_RUNTIME cannot import "
+          "files which do use this option.  This file is not lite, but it "
+          "imports \"" + file->dependency(i)->name() + "\" which is.");
+        break;
+      }
+    }
+  }
+  if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    ValidateProto3(file, proto);
+  }
+}
+
+void DescriptorBuilder::ValidateProto3(
+    FileDescriptor* file, const FileDescriptorProto& proto) {
+  for (int i = 0; i < file->extension_count(); ++i) {
+    ValidateProto3Field(file->extensions_ + i, proto.extension(i));
+  }
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
+  }
+  for (int i = 0; i < file->enum_type_count(); ++i) {
+    ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
+  }
+}
+
+static string ToLowercaseWithoutUnderscores(const string& name) {
+  string result;
+  for (int i = 0; i < name.size(); ++i) {
+    if (name[i] != '_') {
+      if (name[i] >= 'A' && name[i] <= 'Z') {
+        result.push_back(name[i] - 'A' + 'a');
+      } else {
+        result.push_back(name[i]);
+      }
+    }
+  }
+  return result;
+}
+
+void DescriptorBuilder::ValidateProto3Message(
+    Descriptor* message, const DescriptorProto& proto) {
+  for (int i = 0; i < message->nested_type_count(); ++i) {
+    ValidateProto3Message(message->nested_types_ + i,
+                                 proto.nested_type(i));
+  }
+  for (int i = 0; i < message->enum_type_count(); ++i) {
+    ValidateProto3Enum(message->enum_types_ + i,
+                              proto.enum_type(i));
+  }
+  for (int i = 0; i < message->field_count(); ++i) {
+    ValidateProto3Field(message->fields_ + i, proto.field(i));
+  }
+  for (int i = 0; i < message->extension_count(); ++i) {
+    ValidateProto3Field(message->extensions_ +i, proto.extension(i));
+  }
+  if (message->extension_range_count() > 0) {
+    AddError(message->full_name(), proto,
+             DescriptorPool::ErrorCollector::OTHER,
+             "Extension ranges are not allowed in proto3.");
+  }
+  if (message->options().message_set_wire_format()) {
+    // Using MessageSet doesn't make sense since we disallow extensions.
+    AddError(message->full_name(), proto,
+             DescriptorPool::ErrorCollector::OTHER,
+             "MessageSet is not supported in proto3.");
+  }
+
+  // In proto3, we reject field names if they conflict in camelCase.
+  // Note that we currently enforce a stricter rule: Field names must be
+  // unique after being converted to lowercase with underscores removed.
+  map<string, const FieldDescriptor*> name_to_field;
+  for (int i = 0; i < message->field_count(); ++i) {
+    string lowercase_name = ToLowercaseWithoutUnderscores(
+        message->field(i)->name());
+    if (name_to_field.find(lowercase_name) != name_to_field.end()) {
+      AddError(message->full_name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "The JSON camcel-case name of field \"" +
+               message->field(i)->name() + "\" conflicts with field \"" +
+               name_to_field[lowercase_name]->name() + "\". This is not " +
+               "allowed in proto3.");
+    } else {
+      name_to_field[lowercase_name] = message->field(i);
+    }
+  }
+}
+
+void DescriptorBuilder::ValidateProto3Field(
+    FieldDescriptor* field, const FieldDescriptorProto& proto) {
+  if (field->is_extension() &&
+      !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::OTHER,
+             "Extensions in proto3 are only allowed for defining options.");
+  }
+  if (field->is_required()) {
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::OTHER,
+             "Required fields are not allowed in proto3.");
+  }
+  if (field->has_default_value()) {
+    AddError(
+        field->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
+        "Explicit default values are not allowed in proto3.");
+  }
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+      field->enum_type() &&
+      field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+    // Proto3 messages can only use Proto3 enum types; otherwise we can't
+    // guarantee that the default value is zero.
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::TYPE,
+             "Enum type \"" + field->enum_type()->full_name() +
+             "\" is not a proto3 enum, but is used in \"" +
+             field->containing_type()->full_name() +
+             "\" which is a proto3 message type.");
+  }
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::TYPE,
+             "Groups are not supported in proto3 syntax.");
+  }
+}
+
+void DescriptorBuilder::ValidateProto3Enum(
+    EnumDescriptor* enm, const EnumDescriptorProto& proto) {
+  if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
+    AddError(
+        enm->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
+        "The first enum value must be zero in proto3.");
+  }
+}
+
+void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
+                                               const DescriptorProto& proto) {
+  VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
+  VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
+  VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
+  VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
+
+  const int64 max_extension_range =
+      static_cast<int64>(message->options().message_set_wire_format() ?
+                         kint32max :
+                         FieldDescriptor::kMaxNumber);
+  for (int i = 0; i < message->extension_range_count(); ++i) {
+    if (message->extension_range(i)->end > max_extension_range + 1) {
+      AddError(
+          message->full_name(), proto.extension_range(i),
+          DescriptorPool::ErrorCollector::NUMBER,
+          strings::Substitute("Extension numbers cannot be greater than $0.",
+                              max_extension_range));
+    }
+  }
+}
+
+void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
+    const FieldDescriptorProto& proto) {
+  // Only message type fields may be lazy.
+  if (field->options().lazy()) {
+    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::TYPE,
+               "[lazy = true] can only be specified for submessage fields.");
+    }
+  }
+
+  // Only repeated primitive fields may be packed.
+  if (field->options().packed() && !field->is_packable()) {
+    AddError(
+      field->full_name(), proto,
+      DescriptorPool::ErrorCollector::TYPE,
+      "[packed = true] can only be specified for repeated primitive fields.");
+  }
+
+  // Note:  Default instance may not yet be initialized here, so we have to
+  //   avoid reading from it.
+  if (field->containing_type_ != NULL &&
+      &field->containing_type()->options() !=
+      &MessageOptions::default_instance() &&
+      field->containing_type()->options().message_set_wire_format()) {
+    if (field->is_extension()) {
+      if (!field->is_optional() ||
+          field->type() != FieldDescriptor::TYPE_MESSAGE) {
+        AddError(field->full_name(), proto,
+                 DescriptorPool::ErrorCollector::TYPE,
+                 "Extensions of MessageSets must be optional messages.");
+      }
+    } else {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::NAME,
+               "MessageSets cannot have fields, only extensions.");
+    }
+  }
+
+  // Lite extensions can only be of Lite types.
+  if (IsLite(field->file()) &&
+      field->containing_type_ != NULL &&
+      !IsLite(field->containing_type()->file())) {
+    AddError(field->full_name(), proto,
+             DescriptorPool::ErrorCollector::EXTENDEE,
+             "Extensions to non-lite types can only be declared in non-lite "
+             "files.  Note that you cannot extend a non-lite type to contain "
+             "a lite type, but the reverse is allowed.");
+  }
+
+  // Validate map types.
+  if (field->is_map()) {
+    if (!ValidateMapEntry(field, proto)) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "map_entry should not be set explicitly. Use map<KeyType, "
+               "ValueType> instead.");
+    }
+  }
+
+}
+
+void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
+                                            const EnumDescriptorProto& proto) {
+  VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
+  if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
+    map<int, string> used_values;
+    for (int i = 0; i < enm->value_count(); ++i) {
+      const EnumValueDescriptor* enum_value = enm->value(i);
+      if (used_values.find(enum_value->number()) != used_values.end()) {
+        string error =
+            "\"" + enum_value->full_name() +
+            "\" uses the same enum value as \"" +
+            used_values[enum_value->number()] + "\". If this is intended, set "
+            "'option allow_alias = true;' to the enum definition.";
+        if (!enm->options().allow_alias()) {
+          // Generate error if duplicated enum values are explicitly disallowed.
+          AddError(enm->full_name(), proto,
+                   DescriptorPool::ErrorCollector::NUMBER,
+                   error);
+        } else {
+          // Generate warning if duplicated values are found but the option
+          // isn't set.
+          GOOGLE_LOG(ERROR) << error;
+        }
+      } else {
+        used_values[enum_value->number()] = enum_value->full_name();
+      }
+    }
+  }
+}
+
+void DescriptorBuilder::ValidateEnumValueOptions(
+    EnumValueDescriptor* /* enum_value */,
+    const EnumValueDescriptorProto& /* proto */) {
+  // Nothing to do so far.
+}
+void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
+    const ServiceDescriptorProto& proto) {
+  if (IsLite(service->file()) &&
+      (service->file()->options().cc_generic_services() ||
+       service->file()->options().java_generic_services())) {
+    AddError(service->full_name(), proto,
+             DescriptorPool::ErrorCollector::NAME,
+             "Files with optimize_for = LITE_RUNTIME cannot define services "
+             "unless you set both options cc_generic_services and "
+             "java_generic_sevices to false.");
+  }
+
+  VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
+}
+
+void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */,
+    const MethodDescriptorProto& /* proto */) {
+  // Nothing to do so far.
+}
+
+bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
+                                         const FieldDescriptorProto& proto) {
+  const Descriptor* message = field->message_type();
+  if (// Must not contain extensions, extension range or nested message or
+      // enums
+      message->extension_count() != 0 ||
+      field->label() != FieldDescriptor::LABEL_REPEATED ||
+      message->extension_range_count() != 0 ||
+      message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
+      // Must contain exactly two fields
+      message->field_count() != 2 ||
+      // Field name and message name must match
+      message->name() != ToCamelCase(field->name(), false) + "Entry" ||
+      // Entry message must be in the same containing type of the field.
+      field->containing_type() != message->containing_type()) {
+    return false;
+  }
+
+  const FieldDescriptor* key = message->field(0);
+  const FieldDescriptor* value = message->field(1);
+  if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
+      key->name() != "key") {
+    return false;
+  }
+  if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
+      value->number() != 2 || value->name() != "value") {
+    return false;
+  }
+
+  // Check key types are legal.
+  switch (key->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+      AddError(
+          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+          "Key in map fields cannot be enum types.");
+      break;
+    case FieldDescriptor::TYPE_FLOAT:
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_BYTES:
+      AddError(
+          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+          "Key in map fields cannot be float/double, bytes or message types.");
+      break;
+    case FieldDescriptor::TYPE_BOOL:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SFIXED64:
+      // Legal cases
+      break;
+    // Do not add a default, so that the compiler will complain when new types
+    // are added.
+  }
+
+  if (value->type() == FieldDescriptor::TYPE_ENUM) {
+    if (value->enum_type()->value(0)->number() != 0) {
+      AddError(
+          field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+          "Enum value in map must define 0 as the first value.");
+    }
+  }
+
+  return true;
+}
+
+void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
+                                           const DescriptorProto& proto) {
+  map<string, const Descriptor*> seen_types;
+  for (int i = 0; i < message->nested_type_count(); ++i) {
+    const Descriptor* nested = message->nested_type(i);
+    pair<map<string, const Descriptor*>::iterator, bool> result =
+        seen_types.insert(std::make_pair(nested->name(), nested));
+    if (!result.second) {
+      if (result.first->second->options().map_entry() ||
+          nested->options().map_entry()) {
+        AddError(message->full_name(), proto,
+                 DescriptorPool::ErrorCollector::NAME,
+                 "Expanded map entry type " + nested->name() +
+                 " conflicts with an existing nested message type.");
+      }
+    }
+    // Recursively test on the nested types.
+    DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
+  }
+  // Check for conflicted field names.
+  for (int i = 0; i < message->field_count(); ++i) {
+    const FieldDescriptor* field = message->field(i);
+    map<string, const Descriptor*>::iterator iter =
+        seen_types.find(field->name());
+    if (iter != seen_types.end() && iter->second->options().map_entry()) {
+      AddError(message->full_name(), proto,
+               DescriptorPool::ErrorCollector::NAME,
+               "Expanded map entry type " + iter->second->name() +
+               " conflicts with an existing field.");
+    }
+  }
+  // Check for conflicted enum names.
+  for (int i = 0; i < message->enum_type_count(); ++i) {
+    const EnumDescriptor* enum_desc = message->enum_type(i);
+    map<string, const Descriptor*>::iterator iter =
+        seen_types.find(enum_desc->name());
+    if (iter != seen_types.end() && iter->second->options().map_entry()) {
+      AddError(message->full_name(), proto,
+               DescriptorPool::ErrorCollector::NAME,
+               "Expanded map entry type " + iter->second->name() +
+               " conflicts with an existing enum type.");
+    }
+  }
+  // Check for conflicted oneof names.
+  for (int i = 0; i < message->oneof_decl_count(); ++i) {
+    const OneofDescriptor* oneof_desc = message->oneof_decl(i);
+    map<string, const Descriptor*>::iterator iter =
+        seen_types.find(oneof_desc->name());
+    if (iter != seen_types.end() && iter->second->options().map_entry()) {
+      AddError(message->full_name(), proto,
+               DescriptorPool::ErrorCollector::NAME,
+               "Expanded map entry type " + iter->second->name() +
+               " conflicts with an existing oneof type.");
+    }
+  }
+}
+
+
+#undef VALIDATE_OPTIONS_FROM_ARRAY
+
+// -------------------------------------------------------------------
+
+DescriptorBuilder::OptionInterpreter::OptionInterpreter(
+    DescriptorBuilder* builder) : builder_(builder) {
+  GOOGLE_CHECK(builder_);
+}
+
+DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {
+}
+
+bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
+    OptionsToInterpret* options_to_interpret) {
+  // Note that these may be in different pools, so we can't use the same
+  // descriptor and reflection objects on both.
+  Message* options = options_to_interpret->options;
+  const Message* original_options = options_to_interpret->original_options;
+
+  bool failed = false;
+  options_to_interpret_ = options_to_interpret;
+
+  // Find the uninterpreted_option field in the mutable copy of the options
+  // and clear them, since we're about to interpret them.
+  const FieldDescriptor* uninterpreted_options_field =
+      options->GetDescriptor()->FindFieldByName("uninterpreted_option");
+  GOOGLE_CHECK(uninterpreted_options_field != NULL)
+      << "No field named \"uninterpreted_option\" in the Options proto.";
+  options->GetReflection()->ClearField(options, uninterpreted_options_field);
+
+  // Find the uninterpreted_option field in the original options.
+  const FieldDescriptor* original_uninterpreted_options_field =
+      original_options->GetDescriptor()->
+          FindFieldByName("uninterpreted_option");
+  GOOGLE_CHECK(original_uninterpreted_options_field != NULL)
+      << "No field named \"uninterpreted_option\" in the Options proto.";
+
+  const int num_uninterpreted_options = original_options->GetReflection()->
+      FieldSize(*original_options, original_uninterpreted_options_field);
+  for (int i = 0; i < num_uninterpreted_options; ++i) {
+    uninterpreted_option_ = down_cast<const UninterpretedOption*>(
+        &original_options->GetReflection()->GetRepeatedMessage(
+            *original_options, original_uninterpreted_options_field, i));
+    if (!InterpretSingleOption(options)) {
+      // Error already added by InterpretSingleOption().
+      failed = true;
+      break;
+    }
+  }
+  // Reset these, so we don't have any dangling pointers.
+  uninterpreted_option_ = NULL;
+  options_to_interpret_ = NULL;
+
+  if (!failed) {
+    // InterpretSingleOption() added the interpreted options in the
+    // UnknownFieldSet, in case the option isn't yet known to us.  Now we
+    // serialize the options message and deserialize it back.  That way, any
+    // option fields that we do happen to know about will get moved from the
+    // UnknownFieldSet into the real fields, and thus be available right away.
+    // If they are not known, that's OK too. They will get reparsed into the
+    // UnknownFieldSet and wait there until the message is parsed by something
+    // that does know about the options.
+    string buf;
+    GOOGLE_CHECK(options->AppendPartialToString(&buf))
+        << "Protocol message could not be serialized.";
+    GOOGLE_CHECK(options->ParsePartialFromString(buf))
+        << "Protocol message serialized itself in invalid fashion.";
+    if (!options->IsInitialized()) {
+      builder_->AddWarning(
+          options_to_interpret->element_name, *original_options,
+          DescriptorPool::ErrorCollector::OTHER,
+          "Options could not be fully parsed using the proto descriptors "
+          "compiled into this binary. Missing required fields: " +
+          options->InitializationErrorString());
+    }
+  }
+  return !failed;
+}
+
+bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
+    Message* options) {
+  // First do some basic validation.
+  if (uninterpreted_option_->name_size() == 0) {
+    // This should never happen unless the parser has gone seriously awry or
+    // someone has manually created the uninterpreted option badly.
+    return AddNameError("Option must have a name.");
+  }
+  if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
+    return AddNameError("Option must not use reserved name "
+                        "\"uninterpreted_option\".");
+  }
+
+  const Descriptor* options_descriptor = NULL;
+  // Get the options message's descriptor from the builder's pool, so that we
+  // get the version that knows about any extension options declared in the
+  // file we're currently building. The descriptor should be there as long as
+  // the file we're building imported "google/protobuf/descriptors.proto".
+
+  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
+  // DescriptorPool::FindMessageTypeByName() because we're already holding the
+  // pool's mutex, and the latter method locks it again.  We don't use
+  // FindSymbol() because files that use custom options only need to depend on
+  // the file that defines the option, not descriptor.proto itself.
+  Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
+    options->GetDescriptor()->full_name());
+  if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
+    options_descriptor = symbol.descriptor;
+  } else {
+    // The options message's descriptor was not in the builder's pool, so use
+    // the standard version from the generated pool. We're not holding the
+    // generated pool's mutex, so we can search it the straightforward way.
+    options_descriptor = options->GetDescriptor();
+  }
+  GOOGLE_CHECK(options_descriptor);
+
+  // We iterate over the name parts to drill into the submessages until we find
+  // the leaf field for the option. As we drill down we remember the current
+  // submessage's descriptor in |descriptor| and the next field in that
+  // submessage in |field|. We also track the fields we're drilling down
+  // through in |intermediate_fields|. As we go, we reconstruct the full option
+  // name in |debug_msg_name|, for use in error messages.
+  const Descriptor* descriptor = options_descriptor;
+  const FieldDescriptor* field = NULL;
+  vector<const FieldDescriptor*> intermediate_fields;
+  string debug_msg_name = "";
+
+  for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
+    const string& name_part = uninterpreted_option_->name(i).name_part();
+    if (debug_msg_name.size() > 0) {
+      debug_msg_name += ".";
+    }
+    if (uninterpreted_option_->name(i).is_extension()) {
+      debug_msg_name += "(" + name_part + ")";
+      // Search for the extension's descriptor as an extension in the builder's
+      // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
+      // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
+      // relative lookups, and 2) because we're already holding the pool's
+      // mutex, and the latter method locks it again.
+      symbol = builder_->LookupSymbol(name_part,
+                                      options_to_interpret_->name_scope);
+      if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
+        field = symbol.field_descriptor;
+      }
+      // If we don't find the field then the field's descriptor was not in the
+      // builder's pool, but there's no point in looking in the generated
+      // pool. We require that you import the file that defines any extensions
+      // you use, so they must be present in the builder's pool.
+    } else {
+      debug_msg_name += name_part;
+      // Search for the field's descriptor as a regular field.
+      field = descriptor->FindFieldByName(name_part);
+    }
+
+    if (field == NULL) {
+      if (get_allow_unknown(builder_->pool_)) {
+        // We can't find the option, but AllowUnknownDependencies() is enabled,
+        // so we will just leave it as uninterpreted.
+        AddWithoutInterpreting(*uninterpreted_option_, options);
+        return true;
+      } else if (!(builder_->undefine_resolved_name_).empty()) {
+        // Option is resolved to a name which is not defined.
+        return AddNameError(
+            "Option \"" + debug_msg_name + "\" is resolved to \"(" +
+            builder_->undefine_resolved_name_ +
+            ")\", which is not defined. The innermost scope is searched first "
+            "in name resolution. Consider using a leading '.'(i.e., \"(." +
+            debug_msg_name.substr(1) +
+            "\") to start from the outermost scope.");
+      } else {
+        return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
+      }
+    } else if (field->containing_type() != descriptor) {
+      if (get_is_placeholder(field->containing_type())) {
+        // The field is an extension of a placeholder type, so we can't
+        // reliably verify whether it is a valid extension to use here (e.g.
+        // we don't know if it is an extension of the correct *Options message,
+        // or if it has a valid field number, etc.).  Just leave it as
+        // uninterpreted instead.
+        AddWithoutInterpreting(*uninterpreted_option_, options);
+        return true;
+      } else {
+        // This can only happen if, due to some insane misconfiguration of the
+        // pools, we find the options message in one pool but the field in
+        // another. This would probably imply a hefty bug somewhere.
+        return AddNameError("Option field \"" + debug_msg_name +
+                            "\" is not a field or extension of message \"" +
+                            descriptor->name() + "\".");
+      }
+    } else if (i < uninterpreted_option_->name_size() - 1) {
+      if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+        return AddNameError("Option \"" +  debug_msg_name +
+                            "\" is an atomic type, not a message.");
+      } else if (field->is_repeated()) {
+        return AddNameError("Option field \"" + debug_msg_name +
+                            "\" is a repeated message. Repeated message "
+                            "options must be initialized using an "
+                            "aggregate value.");
+      } else {
+        // Drill down into the submessage.
+        intermediate_fields.push_back(field);
+        descriptor = field->message_type();
+      }
+    }
+  }
+
+  // We've found the leaf field. Now we use UnknownFieldSets to set its value
+  // on the options message. We do so because the message may not yet know
+  // about its extension fields, so we may not be able to set the fields
+  // directly. But the UnknownFieldSets will serialize to the same wire-format
+  // message, so reading that message back in once the extension fields are
+  // known will populate them correctly.
+
+  // First see if the option is already set.
+  if (!field->is_repeated() && !ExamineIfOptionIsSet(
+          intermediate_fields.begin(),
+          intermediate_fields.end(),
+          field, debug_msg_name,
+          options->GetReflection()->GetUnknownFields(*options))) {
+    return false;  // ExamineIfOptionIsSet() already added the error.
+  }
+
+
+  // First set the value on the UnknownFieldSet corresponding to the
+  // innermost message.
+  google::protobuf::scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
+  if (!SetOptionValue(field, unknown_fields.get())) {
+    return false;  // SetOptionValue() already added the error.
+  }
+
+  // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
+  // the intermediate messages.
+  for (vector<const FieldDescriptor*>::reverse_iterator iter =
+           intermediate_fields.rbegin();
+       iter != intermediate_fields.rend(); ++iter) {
+    google::protobuf::scoped_ptr<UnknownFieldSet> parent_unknown_fields(
+        new UnknownFieldSet());
+    switch ((*iter)->type()) {
+      case FieldDescriptor::TYPE_MESSAGE: {
+        io::StringOutputStream outstr(
+            parent_unknown_fields->AddLengthDelimited((*iter)->number()));
+        io::CodedOutputStream out(&outstr);
+        internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out);
+        GOOGLE_CHECK(!out.HadError())
+            << "Unexpected failure while serializing option submessage "
+            << debug_msg_name << "\".";
+        break;
+      }
+
+      case FieldDescriptor::TYPE_GROUP: {
+         parent_unknown_fields->AddGroup((*iter)->number())
+                              ->MergeFrom(*unknown_fields);
+        break;
+      }
+
+      default:
+        GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
+                   << (*iter)->type();
+        return false;
+    }
+    unknown_fields.reset(parent_unknown_fields.release());
+  }
+
+  // Now merge the UnknownFieldSet corresponding to the top-level message into
+  // the options message.
+  options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
+      *unknown_fields);
+
+  return true;
+}
+
+void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
+    const UninterpretedOption& uninterpreted_option, Message* options) {
+  const FieldDescriptor* field =
+    options->GetDescriptor()->FindFieldByName("uninterpreted_option");
+  GOOGLE_CHECK(field != NULL);
+
+  options->GetReflection()->AddMessage(options, field)
+    ->CopyFrom(uninterpreted_option);
+}
+
+bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
+    vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
+    vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
+    const FieldDescriptor* innermost_field, const string& debug_msg_name,
+    const UnknownFieldSet& unknown_fields) {
+  // We do linear searches of the UnknownFieldSet and its sub-groups.  This
+  // should be fine since it's unlikely that any one options structure will
+  // contain more than a handful of options.
+
+  if (intermediate_fields_iter == intermediate_fields_end) {
+    // We're at the innermost submessage.
+    for (int i = 0; i < unknown_fields.field_count(); i++) {
+      if (unknown_fields.field(i).number() == innermost_field->number()) {
+        return AddNameError("Option \"" + debug_msg_name +
+                            "\" was already set.");
+      }
+    }
+    return true;
+  }
+
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    if (unknown_fields.field(i).number() ==
+        (*intermediate_fields_iter)->number()) {
+      const UnknownField* unknown_field = &unknown_fields.field(i);
+      FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
+      // Recurse into the next submessage.
+      switch (type) {
+        case FieldDescriptor::TYPE_MESSAGE:
+          if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+            UnknownFieldSet intermediate_unknown_fields;
+            if (intermediate_unknown_fields.ParseFromString(
+                    unknown_field->length_delimited()) &&
+                !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
+                                      intermediate_fields_end,
+                                      innermost_field, debug_msg_name,
+                                      intermediate_unknown_fields)) {
+              return false;  // Error already added.
+            }
+          }
+          break;
+
+        case FieldDescriptor::TYPE_GROUP:
+          if (unknown_field->type() == UnknownField::TYPE_GROUP) {
+            if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
+                                      intermediate_fields_end,
+                                      innermost_field, debug_msg_name,
+                                      unknown_field->group())) {
+              return false;  // Error already added.
+            }
+          }
+          break;
+
+        default:
+          GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
+          return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
+    const FieldDescriptor* option_field,
+    UnknownFieldSet* unknown_fields) {
+  // We switch on the CppType to validate.
+  switch (option_field->cpp_type()) {
+
+    case FieldDescriptor::CPPTYPE_INT32:
+      if (uninterpreted_option_->has_positive_int_value()) {
+        if (uninterpreted_option_->positive_int_value() >
+            static_cast<uint64>(kint32max)) {
+          return AddValueError("Value out of range for int32 option \"" +
+                               option_field->full_name() + "\".");
+        } else {
+          SetInt32(option_field->number(),
+                   uninterpreted_option_->positive_int_value(),
+                   option_field->type(), unknown_fields);
+        }
+      } else if (uninterpreted_option_->has_negative_int_value()) {
+        if (uninterpreted_option_->negative_int_value() <
+            static_cast<int64>(kint32min)) {
+          return AddValueError("Value out of range for int32 option \"" +
+                               option_field->full_name() + "\".");
+        } else {
+          SetInt32(option_field->number(),
+                   uninterpreted_option_->negative_int_value(),
+                   option_field->type(), unknown_fields);
+        }
+      } else {
+        return AddValueError("Value must be integer for int32 option \"" +
+                             option_field->full_name() + "\".");
+      }
+      break;
+
+    case FieldDescriptor::CPPTYPE_INT64:
+      if (uninterpreted_option_->has_positive_int_value()) {
+        if (uninterpreted_option_->positive_int_value() >
+            static_cast<uint64>(kint64max)) {
+          return AddValueError("Value out of range for int64 option \"" +
+                               option_field->full_name() + "\".");
+        } else {
+          SetInt64(option_field->number(),
+                   uninterpreted_option_->positive_int_value(),
+                   option_field->type(), unknown_fields);
+        }
+      } else if (uninterpreted_option_->has_negative_int_value()) {
+        SetInt64(option_field->number(),
+                 uninterpreted_option_->negative_int_value(),
+                 option_field->type(), unknown_fields);
+      } else {
+        return AddValueError("Value must be integer for int64 option \"" +
+                             option_field->full_name() + "\".");
+      }
+      break;
+
+    case FieldDescriptor::CPPTYPE_UINT32:
+      if (uninterpreted_option_->has_positive_int_value()) {
+        if (uninterpreted_option_->positive_int_value() > kuint32max) {
+          return AddValueError("Value out of range for uint32 option \"" +
+                               option_field->name() + "\".");
+        } else {
+          SetUInt32(option_field->number(),
+                    uninterpreted_option_->positive_int_value(),
+                    option_field->type(), unknown_fields);
+        }
+      } else {
+        return AddValueError("Value must be non-negative integer for uint32 "
+                             "option \"" + option_field->full_name() + "\".");
+      }
+      break;
+
+    case FieldDescriptor::CPPTYPE_UINT64:
+      if (uninterpreted_option_->has_positive_int_value()) {
+        SetUInt64(option_field->number(),
+                  uninterpreted_option_->positive_int_value(),
+                  option_field->type(), unknown_fields);
+      } else {
+        return AddValueError("Value must be non-negative integer for uint64 "
+                             "option \"" + option_field->full_name() + "\".");
+      }
+      break;
+
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value;
+      if (uninterpreted_option_->has_double_value()) {
+        value = uninterpreted_option_->double_value();
+      } else if (uninterpreted_option_->has_positive_int_value()) {
+        value = uninterpreted_option_->positive_int_value();
+      } else if (uninterpreted_option_->has_negative_int_value()) {
+        value = uninterpreted_option_->negative_int_value();
+      } else {
+        return AddValueError("Value must be number for float option \"" +
+                             option_field->full_name() + "\".");
+      }
+      unknown_fields->AddFixed32(option_field->number(),
+          google::protobuf::internal::WireFormatLite::EncodeFloat(value));
+      break;
+    }
+
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value;
+      if (uninterpreted_option_->has_double_value()) {
+        value = uninterpreted_option_->double_value();
+      } else if (uninterpreted_option_->has_positive_int_value()) {
+        value = uninterpreted_option_->positive_int_value();
+      } else if (uninterpreted_option_->has_negative_int_value()) {
+        value = uninterpreted_option_->negative_int_value();
+      } else {
+        return AddValueError("Value must be number for double option \"" +
+                             option_field->full_name() + "\".");
+      }
+      unknown_fields->AddFixed64(option_field->number(),
+          google::protobuf::internal::WireFormatLite::EncodeDouble(value));
+      break;
+    }
+
+    case FieldDescriptor::CPPTYPE_BOOL:
+      uint64 value;
+      if (!uninterpreted_option_->has_identifier_value()) {
+        return AddValueError("Value must be identifier for boolean option "
+                             "\"" + option_field->full_name() + "\".");
+      }
+      if (uninterpreted_option_->identifier_value() == "true") {
+        value = 1;
+      } else if (uninterpreted_option_->identifier_value() == "false") {
+        value = 0;
+      } else {
+        return AddValueError("Value must be \"true\" or \"false\" for boolean "
+                             "option \"" + option_field->full_name() + "\".");
+      }
+      unknown_fields->AddVarint(option_field->number(), value);
+      break;
+
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      if (!uninterpreted_option_->has_identifier_value()) {
+        return AddValueError("Value must be identifier for enum-valued option "
+                             "\"" + option_field->full_name() + "\".");
+      }
+      const EnumDescriptor* enum_type = option_field->enum_type();
+      const string& value_name = uninterpreted_option_->identifier_value();
+      const EnumValueDescriptor* enum_value = NULL;
+
+      if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
+        // Note that the enum value's fully-qualified name is a sibling of the
+        // enum's name, not a child of it.
+        string fully_qualified_name = enum_type->full_name();
+        fully_qualified_name.resize(fully_qualified_name.size() -
+                                    enum_type->name().size());
+        fully_qualified_name += value_name;
+
+        // Search for the enum value's descriptor in the builder's pool. Note
+        // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
+        // DescriptorPool::FindEnumValueByName() because we're already holding
+        // the pool's mutex, and the latter method locks it again.
+        Symbol symbol =
+          builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
+        if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) {
+          if (symbol.enum_value_descriptor->type() != enum_type) {
+            return AddValueError("Enum type \"" + enum_type->full_name() +
+                "\" has no value named \"" + value_name + "\" for option \"" +
+                option_field->full_name() +
+                "\". This appears to be a value from a sibling type.");
+          } else {
+            enum_value = symbol.enum_value_descriptor;
+          }
+        }
+      } else {
+        // The enum type is in the generated pool, so we can search for the
+        // value there.
+        enum_value = enum_type->FindValueByName(value_name);
+      }
+
+      if (enum_value == NULL) {
+        return AddValueError("Enum type \"" +
+                             option_field->enum_type()->full_name() +
+                             "\" has no value named \"" + value_name + "\" for "
+                             "option \"" + option_field->full_name() + "\".");
+      } else {
+        // Sign-extension is not a problem, since we cast directly from int32 to
+        // uint64, without first going through uint32.
+        unknown_fields->AddVarint(option_field->number(),
+          static_cast<uint64>(static_cast<int64>(enum_value->number())));
+      }
+      break;
+    }
+
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (!uninterpreted_option_->has_string_value()) {
+        return AddValueError("Value must be quoted string for string option "
+                             "\"" + option_field->full_name() + "\".");
+      }
+      // The string has already been unquoted and unescaped by the parser.
+      unknown_fields->AddLengthDelimited(option_field->number(),
+          uninterpreted_option_->string_value());
+      break;
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      if (!SetAggregateOption(option_field, unknown_fields)) {
+        return false;
+      }
+      break;
+  }
+
+  return true;
+}
+
+class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
+    : public TextFormat::Finder {
+ public:
+  DescriptorBuilder* builder_;
+
+  virtual const FieldDescriptor* FindExtension(
+      Message* message, const string& name) const {
+    assert_mutex_held(builder_->pool_);
+    const Descriptor* descriptor = message->GetDescriptor();
+    Symbol result = builder_->LookupSymbolNoPlaceholder(
+        name, descriptor->full_name());
+    if (result.type == Symbol::FIELD &&
+        result.field_descriptor->is_extension()) {
+      return result.field_descriptor;
+    } else if (result.type == Symbol::MESSAGE &&
+               descriptor->options().message_set_wire_format()) {
+      const Descriptor* foreign_type = result.descriptor;
+      // The text format allows MessageSet items to be specified using
+      // the type name, rather than the extension identifier. If the symbol
+      // lookup returned a Message, and the enclosing Message has
+      // message_set_wire_format = true, then return the message set
+      // extension, if one exists.
+      for (int i = 0; i < foreign_type->extension_count(); i++) {
+        const FieldDescriptor* extension = foreign_type->extension(i);
+        if (extension->containing_type() == descriptor &&
+            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
+            extension->is_optional() &&
+            extension->message_type() == foreign_type) {
+          // Found it.
+          return extension;
+        }
+      }
+    }
+    return NULL;
+  }
+};
+
+// A custom error collector to record any text-format parsing errors
+namespace {
+class AggregateErrorCollector : public io::ErrorCollector {
+ public:
+  string error_;
+
+  virtual void AddError(int /* line */, int /* column */,
+                        const string& message) {
+    if (!error_.empty()) {
+      error_ += "; ";
+    }
+    error_ += message;
+  }
+
+  virtual void AddWarning(int /* line */, int /* column */,
+                          const string& /* message */) {
+    // Ignore warnings
+  }
+};
+}
+
+// We construct a dynamic message of the type corresponding to
+// option_field, parse the supplied text-format string into this
+// message, and serialize the resulting message to produce the value.
+bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
+    const FieldDescriptor* option_field,
+    UnknownFieldSet* unknown_fields) {
+  if (!uninterpreted_option_->has_aggregate_value()) {
+    return AddValueError("Option \"" + option_field->full_name() +
+                         "\" is a message. To set the entire message, use "
+                         "syntax like \"" + option_field->name() +
+                         " = { <proto text format> }\". "
+                         "To set fields within it, use "
+                         "syntax like \"" + option_field->name() +
+                         ".foo = value\".");
+  }
+
+  const Descriptor* type = option_field->message_type();
+  google::protobuf::scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
+  GOOGLE_CHECK(dynamic.get() != NULL)
+      << "Could not create an instance of " << option_field->DebugString();
+
+  AggregateErrorCollector collector;
+  AggregateOptionFinder finder;
+  finder.builder_ = builder_;
+  TextFormat::Parser parser;
+  parser.RecordErrorsTo(&collector);
+  parser.SetFinder(&finder);
+  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
+                              dynamic.get())) {
+    AddValueError("Error while parsing option value for \"" +
+                  option_field->name() + "\": " + collector.error_);
+    return false;
+  } else {
+    string serial;
+    dynamic->SerializeToString(&serial);  // Never fails
+    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      unknown_fields->AddLengthDelimited(option_field->number(), serial);
+    } else {
+      GOOGLE_CHECK_EQ(option_field->type(),  FieldDescriptor::TYPE_GROUP);
+      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
+      group->ParseFromString(serial);
+    }
+    return true;
+  }
+}
+
+void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
+    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT32:
+      unknown_fields->AddVarint(number,
+        static_cast<uint64>(static_cast<int64>(value)));
+      break;
+
+    case FieldDescriptor::TYPE_SFIXED32:
+      unknown_fields->AddFixed32(number, static_cast<uint32>(value));
+      break;
+
+    case FieldDescriptor::TYPE_SINT32:
+      unknown_fields->AddVarint(number,
+          google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
+      break;
+  }
+}
+
+void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
+    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
+  switch (type) {
+    case FieldDescriptor::TYPE_INT64:
+      unknown_fields->AddVarint(number, static_cast<uint64>(value));
+      break;
+
+    case FieldDescriptor::TYPE_SFIXED64:
+      unknown_fields->AddFixed64(number, static_cast<uint64>(value));
+      break;
+
+    case FieldDescriptor::TYPE_SINT64:
+      unknown_fields->AddVarint(number,
+          google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
+      break;
+  }
+}
+
+void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value,
+    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
+  switch (type) {
+    case FieldDescriptor::TYPE_UINT32:
+      unknown_fields->AddVarint(number, static_cast<uint64>(value));
+      break;
+
+    case FieldDescriptor::TYPE_FIXED32:
+      unknown_fields->AddFixed32(number, static_cast<uint32>(value));
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
+      break;
+  }
+}
+
+void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value,
+    FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
+  switch (type) {
+    case FieldDescriptor::TYPE_UINT64:
+      unknown_fields->AddVarint(number, value);
+      break;
+
+    case FieldDescriptor::TYPE_FIXED64:
+      unknown_fields->AddFixed64(number, value);
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
+      break;
+  }
+}
+
+void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
+                                            const FileDescriptor* result) {
+
+  if (!unused_dependency_.empty()) {
+    std::set<string> annotation_extensions;
+    annotation_extensions.insert("google.protobuf.MessageOptions");
+    annotation_extensions.insert("google.protobuf.FileOptions");
+    annotation_extensions.insert("google.protobuf.FieldOptions");
+    annotation_extensions.insert("google.protobuf.EnumOptions");
+    annotation_extensions.insert("google.protobuf.EnumValueOptions");
+    annotation_extensions.insert("google.protobuf.ServiceOptions");
+    annotation_extensions.insert("google.protobuf.MethodOptions");
+    annotation_extensions.insert("google.protobuf.StreamOptions");
+    for (set<const FileDescriptor*>::const_iterator
+             it = unused_dependency_.begin();
+         it != unused_dependency_.end(); ++it) {
+      // Do not log warnings for proto files which extend annotations.
+      int i;
+      for (i = 0 ; i < (*it)->extension_count(); ++i) {
+        if (annotation_extensions.find(
+                (*it)->extension(i)->containing_type()->full_name())
+            != annotation_extensions.end()) {
+          break;
+        }
+      }
+      // Log warnings for unused imported files.
+      if (i == (*it)->extension_count()) {
+        string error_message = "Import " + (*it)->name() + " but not used.";
+        AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::OTHER,
+                   error_message);
+      }
+    }
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor.h b/src/third_party/protobuf-3/src/google/protobuf/descriptor.h
new file mode 100644
index 0000000..3ecc0a9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor.h
@@ -0,0 +1,1912 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains classes which describe a type of protocol message.
+// You can use a message's descriptor to learn at runtime what fields
+// it contains and what the types of those fields are.  The Message
+// interface also allows you to dynamically access and modify individual
+// fields by passing the FieldDescriptor of the field you are interested
+// in.
+//
+// Most users will not care about descriptors, because they will write
+// code specific to certain protocol types and will simply use the classes
+// generated by the protocol compiler directly.  Advanced users who want
+// to operate on arbitrary types (not known at compile time) may want to
+// read descriptors in order to learn about the contents of a message.
+// A very small number of users will want to construct their own
+// Descriptors, either because they are implementing Message manually or
+// because they are writing something like the protocol compiler.
+//
+// For an example of how you might use descriptors, see the code example
+// at the top of message.h.
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
+#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+
+// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
+#ifdef TYPE_BOOL
+#undef TYPE_BOOL
+#endif  // TYPE_BOOL
+
+namespace google {
+namespace protobuf {
+
+// Defined in this file.
+class Descriptor;
+class FieldDescriptor;
+class OneofDescriptor;
+class EnumDescriptor;
+class EnumValueDescriptor;
+class ServiceDescriptor;
+class MethodDescriptor;
+class FileDescriptor;
+class DescriptorDatabase;
+class DescriptorPool;
+
+// Defined in descriptor.proto
+class DescriptorProto;
+class FieldDescriptorProto;
+class OneofDescriptorProto;
+class EnumDescriptorProto;
+class EnumValueDescriptorProto;
+class ServiceDescriptorProto;
+class MethodDescriptorProto;
+class FileDescriptorProto;
+class MessageOptions;
+class FieldOptions;
+class EnumOptions;
+class EnumValueOptions;
+class ServiceOptions;
+class MethodOptions;
+class FileOptions;
+class UninterpretedOption;
+class SourceCodeInfo;
+
+// Defined in message.h
+class Message;
+
+// Defined in descriptor.cc
+class DescriptorBuilder;
+class FileDescriptorTables;
+
+// Defined in unknown_field_set.h.
+class UnknownField;
+
+// Defined in generated_message_reflection.h.
+namespace internal {
+class GeneratedMessageReflection;
+}  // namespace internal
+
+// Defined in command_line_interface.cc
+namespace compiler {
+class CommandLineInterface;
+}  // namespace compiler
+
+namespace descriptor_unittest {
+class DescriptorTest;
+}  // namespace descriptor_unittest
+
+// Defined in printer.h
+namespace io {
+class Printer;
+}  // namespace io
+
+// NB, all indices are zero-based.
+struct SourceLocation {
+  int start_line;
+  int end_line;
+  int start_column;
+  int end_column;
+
+  // Doc comments found at the source location.
+  // See the comments in SourceCodeInfo.Location (descriptor.proto) for details.
+  string leading_comments;
+  string trailing_comments;
+  vector<string> leading_detached_comments;
+};
+
+// Options when generating machine-parsable output from a descriptor with
+// DebugString().
+struct DebugStringOptions {
+  // include original user comments as recorded in SourceLocation entries. N.B.
+  // that this must be |false| by default: several other pieces of code (for
+  // example, the C++ code generation for fields in the proto compiler) rely on
+  // DebugString() output being unobstructed by user comments.
+  bool include_comments;
+  // If true, elide the braced body in the debug string.
+  bool elide_group_body;
+  bool elide_oneof_body;
+
+  DebugStringOptions()
+      : include_comments(false),
+        elide_group_body(false),
+        elide_oneof_body(false) {}
+};
+
+// Describes a type of protocol message, or a particular group within a
+// message.  To obtain the Descriptor for a given message object, call
+// Message::GetDescriptor().  Generated message classes also have a
+// static method called descriptor() which returns the type's descriptor.
+// Use DescriptorPool to construct your own descriptors.
+class LIBPROTOBUF_EXPORT Descriptor {
+ public:
+  // The name of the message type, not including its scope.
+  const string& name() const;
+
+  // The fully-qualified name of the message type, scope delimited by
+  // periods.  For example, message type "Foo" which is declared in package
+  // "bar" has full name "bar.Foo".  If a type "Baz" is nested within
+  // Foo, Baz's full_name is "bar.Foo.Baz".  To get only the part that
+  // comes after the last '.', use name().
+  const string& full_name() const;
+
+  // Index of this descriptor within the file or containing type's message
+  // type array.
+  int index() const;
+
+  // The .proto file in which this message type was defined.  Never NULL.
+  const FileDescriptor* file() const;
+
+  // If this Descriptor describes a nested type, this returns the type
+  // in which it is nested.  Otherwise, returns NULL.
+  const Descriptor* containing_type() const;
+
+  // Get options for this message type.  These are specified in the .proto file
+  // by placing lines like "option foo = 1234;" in the message definition.
+  // Allowed options are defined by MessageOptions in
+  // google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const MessageOptions& options() const;
+
+  // Write the contents of this Descriptor into the given DescriptorProto.
+  // The target DescriptorProto must be clear before calling this; if it
+  // isn't, the result may be garbage.
+  void CopyTo(DescriptorProto* proto) const;
+
+  // Write the contents of this decriptor in a human-readable form. Output
+  // will be suitable for re-parsing.
+  string DebugString() const;
+
+  // Similar to DebugString(), but additionally takes options (e.g.,
+  // include original user comments in output).
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+  // Returns true if this is a placeholder for an unknown type. This will
+  // only be the case if this descriptor comes from a DescriptorPool
+  // with AllowUnknownDependencies() set.
+  bool is_placeholder() const;
+
+  // Field stuff -----------------------------------------------------
+
+  // The number of fields in this message type.
+  int field_count() const;
+  // Gets a field by index, where 0 <= index < field_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FieldDescriptor* field(int index) const;
+
+  // Looks up a field by declared tag number.  Returns NULL if no such field
+  // exists.
+  const FieldDescriptor* FindFieldByNumber(int number) const;
+  // Looks up a field by name.  Returns NULL if no such field exists.
+  const FieldDescriptor* FindFieldByName(const string& name) const;
+
+  // Looks up a field by lowercased name (as returned by lowercase_name()).
+  // This lookup may be ambiguous if multiple field names differ only by case,
+  // in which case the field returned is chosen arbitrarily from the matches.
+  const FieldDescriptor* FindFieldByLowercaseName(
+      const string& lowercase_name) const;
+
+  // Looks up a field by camel-case name (as returned by camelcase_name()).
+  // This lookup may be ambiguous if multiple field names differ in a way that
+  // leads them to have identical camel-case names, in which case the field
+  // returned is chosen arbitrarily from the matches.
+  const FieldDescriptor* FindFieldByCamelcaseName(
+      const string& camelcase_name) const;
+
+  // The number of oneofs in this message type.
+  int oneof_decl_count() const;
+  // Get a oneof by index, where 0 <= index < oneof_decl_count().
+  // These are returned in the order they were defined in the .proto file.
+  const OneofDescriptor* oneof_decl(int index) const;
+
+  // Looks up a oneof by name.  Returns NULL if no such oneof exists.
+  const OneofDescriptor* FindOneofByName(const string& name) const;
+
+  // Nested type stuff -----------------------------------------------
+
+  // The number of nested types in this message type.
+  int nested_type_count() const;
+  // Gets a nested type by index, where 0 <= index < nested_type_count().
+  // These are returned in the order they were defined in the .proto file.
+  const Descriptor* nested_type(int index) const;
+
+  // Looks up a nested type by name.  Returns NULL if no such nested type
+  // exists.
+  const Descriptor* FindNestedTypeByName(const string& name) const;
+
+  // Enum stuff ------------------------------------------------------
+
+  // The number of enum types in this message type.
+  int enum_type_count() const;
+  // Gets an enum type by index, where 0 <= index < enum_type_count().
+  // These are returned in the order they were defined in the .proto file.
+  const EnumDescriptor* enum_type(int index) const;
+
+  // Looks up an enum type by name.  Returns NULL if no such enum type exists.
+  const EnumDescriptor* FindEnumTypeByName(const string& name) const;
+
+  // Looks up an enum value by name, among all enum types in this message.
+  // Returns NULL if no such value exists.
+  const EnumValueDescriptor* FindEnumValueByName(const string& name) const;
+
+  // Extensions ------------------------------------------------------
+
+  // A range of field numbers which are designated for third-party
+  // extensions.
+  struct ExtensionRange {
+    int start;  // inclusive
+    int end;    // exclusive
+  };
+
+  // The number of extension ranges in this message type.
+  int extension_range_count() const;
+  // Gets an extension range by index, where 0 <= index <
+  // extension_range_count(). These are returned in the order they were defined
+  // in the .proto file.
+  const ExtensionRange* extension_range(int index) const;
+
+  // Returns true if the number is in one of the extension ranges.
+  bool IsExtensionNumber(int number) const;
+
+  // Returns NULL if no extension range contains the given number.
+  const ExtensionRange* FindExtensionRangeContainingNumber(int number) const;
+
+  // The number of extensions -- extending *other* messages -- that were
+  // defined nested within this message type's scope.
+  int extension_count() const;
+  // Get an extension by index, where 0 <= index < extension_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FieldDescriptor* extension(int index) const;
+
+  // Looks up a named extension (which extends some *other* message type)
+  // defined within this message type's scope.
+  const FieldDescriptor* FindExtensionByName(const string& name) const;
+
+  // Similar to FindFieldByLowercaseName(), but finds extensions defined within
+  // this message type's scope.
+  const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const;
+
+  // Similar to FindFieldByCamelcaseName(), but finds extensions defined within
+  // this message type's scope.
+  const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+
+  // Reserved fields -------------------------------------------------
+
+  // A range of reserved field numbers.
+  struct ReservedRange {
+    int start;  // inclusive
+    int end;    // exclusive
+  };
+
+  // The number of reserved ranges in this message type.
+  int reserved_range_count() const;
+  // Gets an reserved range by index, where 0 <= index <
+  // reserved_range_count(). These are returned in the order they were defined
+  // in the .proto file.
+  const ReservedRange* reserved_range(int index) const;
+
+  // Returns true if the number is in one of the reserved ranges.
+  bool IsReservedNumber(int number) const;
+
+  // Returns NULL if no reserved range contains the given number.
+  const ReservedRange* FindReservedRangeContainingNumber(int number) const;
+
+  // The number of reserved field names in this message type.
+  int reserved_name_count() const;
+
+  // Gets a reserved name by index, where 0 <= index < reserved_name_count().
+  const string& reserved_name(int index) const;
+
+  // Returns true if the field name is reserved.
+  bool IsReservedName(const string& name) const;
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this message declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef MessageOptions OptionsType;
+
+  // Allows tests to test CopyTo(proto, true).
+  friend class ::google::protobuf::descriptor_unittest::DescriptorTest;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // Fill the json_name field of FieldDescriptorProto.
+  void CopyJsonNameTo(DescriptorProto* proto) const;
+
+  // Internal version of DebugString; controls the level of indenting for
+  // correct depth. Takes |options| to control debug-string options, and
+  // |include_opening_clause| to indicate whether the "message ... " part of the
+  // clause has already been generated (this varies depending on context).
+  void DebugString(int depth, string *contents,
+                   const DebugStringOptions& options,
+                   bool include_opening_clause) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const FileDescriptor* file_;
+  const Descriptor* containing_type_;
+  const MessageOptions* options_;
+
+  // True if this is a placeholder for an unknown type.
+  bool is_placeholder_;
+  // True if this is a placeholder and the type name wasn't fully-qualified.
+  bool is_unqualified_placeholder_;
+
+  int field_count_;
+  FieldDescriptor* fields_;
+  int oneof_decl_count_;
+  OneofDescriptor* oneof_decls_;
+  int nested_type_count_;
+  Descriptor* nested_types_;
+  int enum_type_count_;
+  EnumDescriptor* enum_types_;
+  int extension_range_count_;
+  ExtensionRange* extension_ranges_;
+  int extension_count_;
+  FieldDescriptor* extensions_;
+  int reserved_range_count_;
+  ReservedRange* reserved_ranges_;
+  int reserved_name_count_;
+  const string** reserved_names_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc
+  // and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  Descriptor() {}
+  friend class DescriptorBuilder;
+  friend class EnumDescriptor;
+  friend class FieldDescriptor;
+  friend class OneofDescriptor;
+  friend class MethodDescriptor;
+  friend class FileDescriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor);
+};
+
+// Describes a single field of a message.  To get the descriptor for a given
+// field, first get the Descriptor for the message in which it is defined,
+// then call Descriptor::FindFieldByName().  To get a FieldDescriptor for
+// an extension, do one of the following:
+// - Get the Descriptor or FileDescriptor for its containing scope, then
+//   call Descriptor::FindExtensionByName() or
+//   FileDescriptor::FindExtensionByName().
+// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber().
+// - Given a Reflection for a message object, call
+//   Reflection::FindKnownExtensionByName() or
+//   Reflection::FindKnownExtensionByNumber().
+// Use DescriptorPool to construct your own descriptors.
+class LIBPROTOBUF_EXPORT FieldDescriptor {
+ public:
+  // Identifies a field type.  0 is reserved for errors.  The order is weird
+  // for historical reasons.  Types 12 and up are new in proto2.
+  enum Type {
+    TYPE_DOUBLE         = 1,   // double, exactly eight bytes on the wire.
+    TYPE_FLOAT          = 2,   // float, exactly four bytes on the wire.
+    TYPE_INT64          = 3,   // int64, varint on the wire.  Negative numbers
+                               // take 10 bytes.  Use TYPE_SINT64 if negative
+                               // values are likely.
+    TYPE_UINT64         = 4,   // uint64, varint on the wire.
+    TYPE_INT32          = 5,   // int32, varint on the wire.  Negative numbers
+                               // take 10 bytes.  Use TYPE_SINT32 if negative
+                               // values are likely.
+    TYPE_FIXED64        = 6,   // uint64, exactly eight bytes on the wire.
+    TYPE_FIXED32        = 7,   // uint32, exactly four bytes on the wire.
+    TYPE_BOOL           = 8,   // bool, varint on the wire.
+    TYPE_STRING         = 9,   // UTF-8 text.
+    TYPE_GROUP          = 10,  // Tag-delimited message.  Deprecated.
+    TYPE_MESSAGE        = 11,  // Length-delimited message.
+
+    TYPE_BYTES          = 12,  // Arbitrary byte array.
+    TYPE_UINT32         = 13,  // uint32, varint on the wire
+    TYPE_ENUM           = 14,  // Enum, varint on the wire
+    TYPE_SFIXED32       = 15,  // int32, exactly four bytes on the wire
+    TYPE_SFIXED64       = 16,  // int64, exactly eight bytes on the wire
+    TYPE_SINT32         = 17,  // int32, ZigZag-encoded varint on the wire
+    TYPE_SINT64         = 18,  // int64, ZigZag-encoded varint on the wire
+
+    MAX_TYPE            = 18,  // Constant useful for defining lookup tables
+                               // indexed by Type.
+  };
+
+  // Specifies the C++ data type used to represent the field.  There is a
+  // fixed mapping from Type to CppType where each Type maps to exactly one
+  // CppType.  0 is reserved for errors.
+  enum CppType {
+    CPPTYPE_INT32       = 1,     // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32
+    CPPTYPE_INT64       = 2,     // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64
+    CPPTYPE_UINT32      = 3,     // TYPE_UINT32, TYPE_FIXED32
+    CPPTYPE_UINT64      = 4,     // TYPE_UINT64, TYPE_FIXED64
+    CPPTYPE_DOUBLE      = 5,     // TYPE_DOUBLE
+    CPPTYPE_FLOAT       = 6,     // TYPE_FLOAT
+    CPPTYPE_BOOL        = 7,     // TYPE_BOOL
+    CPPTYPE_ENUM        = 8,     // TYPE_ENUM
+    CPPTYPE_STRING      = 9,     // TYPE_STRING, TYPE_BYTES
+    CPPTYPE_MESSAGE     = 10,    // TYPE_MESSAGE, TYPE_GROUP
+
+    MAX_CPPTYPE         = 10,    // Constant useful for defining lookup tables
+                                 // indexed by CppType.
+  };
+
+  // Identifies whether the field is optional, required, or repeated.  0 is
+  // reserved for errors.
+  enum Label {
+    LABEL_OPTIONAL      = 1,    // optional
+    LABEL_REQUIRED      = 2,    // required
+    LABEL_REPEATED      = 3,    // repeated
+
+    MAX_LABEL           = 3,    // Constant useful for defining lookup tables
+                                // indexed by Label.
+  };
+
+  // Valid field numbers are positive integers up to kMaxNumber.
+  static const int kMaxNumber = (1 << 29) - 1;
+
+  // First field number reserved for the protocol buffer library implementation.
+  // Users may not declare fields that use reserved numbers.
+  static const int kFirstReservedNumber = 19000;
+  // Last field number reserved for the protocol buffer library implementation.
+  // Users may not declare fields that use reserved numbers.
+  static const int kLastReservedNumber  = 19999;
+
+  const string& name() const;        // Name of this field within the message.
+  const string& full_name() const;   // Fully-qualified name of the field.
+  const string& json_name() const;   // JSON name of this field.
+  const FileDescriptor* file() const;// File in which this field was defined.
+  bool is_extension() const;         // Is this an extension field?
+  int number() const;                // Declared tag number.
+
+  // Same as name() except converted to lower-case.  This (and especially the
+  // FindFieldByLowercaseName() method) can be useful when parsing formats
+  // which prefer to use lowercase naming style.  (Although, technically
+  // field names should be lowercased anyway according to the protobuf style
+  // guide, so this only makes a difference when dealing with old .proto files
+  // which do not follow the guide.)
+  const string& lowercase_name() const;
+
+  // Same as name() except converted to camel-case.  In this conversion, any
+  // time an underscore appears in the name, it is removed and the next
+  // letter is capitalized.  Furthermore, the first letter of the name is
+  // lower-cased.  Examples:
+  //   FooBar -> fooBar
+  //   foo_bar -> fooBar
+  //   fooBar -> fooBar
+  // This (and especially the FindFieldByCamelcaseName() method) can be useful
+  // when parsing formats which prefer to use camel-case naming style.
+  const string& camelcase_name() const;
+
+  Type type() const;                  // Declared type of this field.
+  const char* type_name() const;      // Name of the declared type.
+  CppType cpp_type() const;           // C++ type of this field.
+  const char* cpp_type_name() const;  // Name of the C++ type.
+  Label label() const;                // optional/required/repeated
+
+  bool is_required() const;      // shorthand for label() == LABEL_REQUIRED
+  bool is_optional() const;      // shorthand for label() == LABEL_OPTIONAL
+  bool is_repeated() const;      // shorthand for label() == LABEL_REPEATED
+  bool is_packable() const;      // shorthand for is_repeated() &&
+                                 //               IsTypePackable(type())
+  bool is_packed() const;        // shorthand for is_packable() &&
+                                 //               options().packed()
+  bool is_map() const;           // shorthand for type() == TYPE_MESSAGE &&
+                                 // message_type()->options().map_entry()
+
+  // Index of this field within the message's field array, or the file or
+  // extension scope's extensions array.
+  int index() const;
+
+  // Does this field have an explicitly-declared default value?
+  bool has_default_value() const;
+
+  // Get the field default value if cpp_type() == CPPTYPE_INT32.  If no
+  // explicit default was defined, the default is 0.
+  int32 default_value_int32() const;
+  // Get the field default value if cpp_type() == CPPTYPE_INT64.  If no
+  // explicit default was defined, the default is 0.
+  int64 default_value_int64() const;
+  // Get the field default value if cpp_type() == CPPTYPE_UINT32.  If no
+  // explicit default was defined, the default is 0.
+  uint32 default_value_uint32() const;
+  // Get the field default value if cpp_type() == CPPTYPE_UINT64.  If no
+  // explicit default was defined, the default is 0.
+  uint64 default_value_uint64() const;
+  // Get the field default value if cpp_type() == CPPTYPE_FLOAT.  If no
+  // explicit default was defined, the default is 0.0.
+  float default_value_float() const;
+  // Get the field default value if cpp_type() == CPPTYPE_DOUBLE.  If no
+  // explicit default was defined, the default is 0.0.
+  double default_value_double() const;
+  // Get the field default value if cpp_type() == CPPTYPE_BOOL.  If no
+  // explicit default was defined, the default is false.
+  bool default_value_bool() const;
+  // Get the field default value if cpp_type() == CPPTYPE_ENUM.  If no
+  // explicit default was defined, the default is the first value defined
+  // in the enum type (all enum types are required to have at least one value).
+  // This never returns NULL.
+  const EnumValueDescriptor* default_value_enum() const;
+  // Get the field default value if cpp_type() == CPPTYPE_STRING.  If no
+  // explicit default was defined, the default is the empty string.
+  const string& default_value_string() const;
+
+  // The Descriptor for the message of which this is a field.  For extensions,
+  // this is the extended type.  Never NULL.
+  const Descriptor* containing_type() const;
+
+  // If the field is a member of a oneof, this is the one, otherwise this is
+  // NULL.
+  const OneofDescriptor* containing_oneof() const;
+
+  // If the field is a member of a oneof, returns the index in that oneof.
+  int index_in_oneof() const;
+
+  // An extension may be declared within the scope of another message.  If this
+  // field is an extension (is_extension() is true), then extension_scope()
+  // returns that message, or NULL if the extension was declared at global
+  // scope.  If this is not an extension, extension_scope() is undefined (may
+  // assert-fail).
+  const Descriptor* extension_scope() const;
+
+  // If type is TYPE_MESSAGE or TYPE_GROUP, returns a descriptor for the
+  // message or the group type.  Otherwise, returns null.
+  const Descriptor* message_type() const;
+  // If type is TYPE_ENUM, returns a descriptor for the enum.  Otherwise,
+  // returns null.
+  const EnumDescriptor* enum_type() const;
+
+  // Get the FieldOptions for this field.  This includes things listed in
+  // square brackets after the field definition.  E.g., the field:
+  //   optional string text = 1 [ctype=CORD];
+  // has the "ctype" option set.  Allowed options are defined by FieldOptions
+  // in google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const FieldOptions& options() const;
+
+  // See Descriptor::CopyTo().
+  void CopyTo(FieldDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+  // Helper method to get the CppType for a particular Type.
+  static CppType TypeToCppType(Type type);
+
+  // Helper method to get the name of a Type.
+  static const char* TypeName(Type type);
+
+  // Helper method to get the name of a CppType.
+  static const char* CppTypeName(CppType cpp_type);
+
+  // Return true iff [packed = true] is valid for fields of this type.
+  static inline bool IsTypePackable(Type field_type);
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this field declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef FieldOptions OptionsType;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // Fill the json_name field of FieldDescriptorProto.
+  void CopyJsonNameTo(FieldDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL };
+  void DebugString(int depth, PrintLabelFlag print_label_flag,
+                   string* contents, const DebugStringOptions& options) const;
+
+  // formats the default value appropriately and returns it as a string.
+  // Must have a default value to call this. If quote_string_type is true, then
+  // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
+  string DefaultValueAsString(bool quote_string_type) const;
+
+  // Helper function that returns the field type name for DebugString.
+  string FieldTypeNameDebugString() const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const string* lowercase_name_;
+  const string* camelcase_name_;
+  // Whether the user has specified the json_name field option in the .proto
+  // file.
+  bool has_json_name_;
+  // If has_json_name_ is true, it's the value specified by the user.
+  // Otherwise, it has the same value as lowercase_name_.
+  const string* json_name_;
+  const FileDescriptor* file_;
+  int number_;
+  Type type_;
+  Label label_;
+  bool is_extension_;
+  int index_in_oneof_;
+  const Descriptor* containing_type_;
+  const OneofDescriptor* containing_oneof_;
+  const Descriptor* extension_scope_;
+  const Descriptor* message_type_;
+  const EnumDescriptor* enum_type_;
+  const FieldOptions* options_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in
+  // descriptor.cc and update them to initialize the field.
+
+  bool has_default_value_;
+  union {
+    int32  default_value_int32_;
+    int64  default_value_int64_;
+    uint32 default_value_uint32_;
+    uint64 default_value_uint64_;
+    float  default_value_float_;
+    double default_value_double_;
+    bool   default_value_bool_;
+
+    const EnumValueDescriptor* default_value_enum_;
+    const string* default_value_string_;
+  };
+
+  static const CppType kTypeToCppTypeMap[MAX_TYPE + 1];
+
+  static const char * const kTypeToName[MAX_TYPE + 1];
+
+  static const char * const kCppTypeToName[MAX_CPPTYPE + 1];
+
+  static const char * const kLabelToName[MAX_LABEL + 1];
+
+  // Must be constructed using DescriptorPool.
+  FieldDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class FileDescriptor;
+  friend class Descriptor;
+  friend class OneofDescriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor);
+};
+
+// Describes a oneof defined in a message type.
+class LIBPROTOBUF_EXPORT OneofDescriptor {
+ public:
+  const string& name() const;       // Name of this oneof.
+  const string& full_name() const;  // Fully-qualified name of the oneof.
+
+  // Index of this oneof within the message's oneof array.
+  int index() const;
+
+  // The Descriptor for the message containing this oneof.
+  const Descriptor* containing_type() const;
+
+  // The number of (non-extension) fields which are members of this oneof.
+  int field_count() const;
+  // Get a member of this oneof, in the order in which they were declared in the
+  // .proto file.  Does not include extensions.
+  const FieldDescriptor* field(int index) const;
+
+  // See Descriptor::CopyTo().
+  void CopyTo(OneofDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this oneof declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // See Descriptor::DebugString().
+  void DebugString(int depth, string* contents,
+                   const DebugStringOptions& options) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const Descriptor* containing_type_;
+  bool is_extendable_;
+  int field_count_;
+  const FieldDescriptor** fields_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<OneofDescriptor>() and AllocateArray<OneofDescriptor>()
+  // in descriptor.cc and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  OneofDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class Descriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor);
+};
+
+// Describes an enum type defined in a .proto file.  To get the EnumDescriptor
+// for a generated enum type, call TypeName_descriptor().  Use DescriptorPool
+// to construct your own descriptors.
+class LIBPROTOBUF_EXPORT EnumDescriptor {
+ public:
+  // The name of this enum type in the containing scope.
+  const string& name() const;
+
+  // The fully-qualified name of the enum type, scope delimited by periods.
+  const string& full_name() const;
+
+  // Index of this enum within the file or containing message's enum array.
+  int index() const;
+
+  // The .proto file in which this enum type was defined.  Never NULL.
+  const FileDescriptor* file() const;
+
+  // The number of values for this EnumDescriptor.  Guaranteed to be greater
+  // than zero.
+  int value_count() const;
+  // Gets a value by index, where 0 <= index < value_count().
+  // These are returned in the order they were defined in the .proto file.
+  const EnumValueDescriptor* value(int index) const;
+
+  // Looks up a value by name.  Returns NULL if no such value exists.
+  const EnumValueDescriptor* FindValueByName(const string& name) const;
+  // Looks up a value by number.  Returns NULL if no such value exists.  If
+  // multiple values have this number, the first one defined is returned.
+  const EnumValueDescriptor* FindValueByNumber(int number) const;
+
+  // If this enum type is nested in a message type, this is that message type.
+  // Otherwise, NULL.
+  const Descriptor* containing_type() const;
+
+  // Get options for this enum type.  These are specified in the .proto file by
+  // placing lines like "option foo = 1234;" in the enum definition.  Allowed
+  // options are defined by EnumOptions in google/protobuf/descriptor.proto,
+  // and any available extensions of that message.
+  const EnumOptions& options() const;
+
+  // See Descriptor::CopyTo().
+  void CopyTo(EnumDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
+  // Returns true if this is a placeholder for an unknown enum. This will
+  // only be the case if this descriptor comes from a DescriptorPool
+  // with AllowUnknownDependencies() set.
+  bool is_placeholder() const;
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this enum declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef EnumOptions OptionsType;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // Looks up a value by number.  If the value does not exist, dynamically
+  // creates a new EnumValueDescriptor for that value, assuming that it was
+  // unknown. If a new descriptor is created, this is done in a thread-safe way,
+  // and future calls will return the same value descriptor pointer.
+  //
+  // This is private but is used by GeneratedMessageReflection (which is
+  // friended below) to return a valid EnumValueDescriptor from GetEnum() when
+  // this feature is enabled.
+  const EnumValueDescriptor*
+      FindValueByNumberCreatingIfUnknown(int number) const;
+
+
+  // See Descriptor::DebugString().
+  void DebugString(int depth, string *contents,
+                   const DebugStringOptions& options) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const FileDescriptor* file_;
+  const Descriptor* containing_type_;
+  const EnumOptions* options_;
+
+  // True if this is a placeholder for an unknown type.
+  bool is_placeholder_;
+  // True if this is a placeholder and the type name wasn't fully-qualified.
+  bool is_unqualified_placeholder_;
+
+  int value_count_;
+  EnumValueDescriptor* values_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<EnumDescriptor>() and AllocateArray<EnumDescriptor>() in
+  // descriptor.cc and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  EnumDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class Descriptor;
+  friend class FieldDescriptor;
+  friend class EnumValueDescriptor;
+  friend class FileDescriptor;
+  friend class internal::GeneratedMessageReflection;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
+};
+
+// Describes an individual enum constant of a particular type.  To get the
+// EnumValueDescriptor for a given enum value, first get the EnumDescriptor
+// for its type, then use EnumDescriptor::FindValueByName() or
+// EnumDescriptor::FindValueByNumber().  Use DescriptorPool to construct
+// your own descriptors.
+class LIBPROTOBUF_EXPORT EnumValueDescriptor {
+ public:
+  const string& name() const;  // Name of this enum constant.
+  int index() const;           // Index within the enums's Descriptor.
+  int number() const;          // Numeric value of this enum constant.
+
+  // The full_name of an enum value is a sibling symbol of the enum type.
+  // e.g. the full name of FieldDescriptorProto::TYPE_INT32 is actually
+  // "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT
+  // "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32".  This is to conform
+  // with C++ scoping rules for enums.
+  const string& full_name() const;
+
+  // The type of this value.  Never NULL.
+  const EnumDescriptor* type() const;
+
+  // Get options for this enum value.  These are specified in the .proto file
+  // by adding text like "[foo = 1234]" after an enum value definition.
+  // Allowed options are defined by EnumValueOptions in
+  // google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const EnumValueOptions& options() const;
+
+  // See Descriptor::CopyTo().
+  void CopyTo(EnumValueDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this enum value declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef EnumValueOptions OptionsType;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // See Descriptor::DebugString().
+  void DebugString(int depth, string *contents,
+                   const DebugStringOptions& options) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  int number_;
+  const EnumDescriptor* type_;
+  const EnumValueOptions* options_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<EnumValueDescriptor>() and AllocateArray<EnumValueDescriptor>()
+  // in descriptor.cc and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  EnumValueDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class EnumDescriptor;
+  friend class FileDescriptorTables;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor);
+};
+
+// Describes an RPC service.  To get the ServiceDescriptor for a service,
+// call Service::GetDescriptor().  Generated service classes also have a
+// static method called descriptor() which returns the type's
+// ServiceDescriptor.  Use DescriptorPool to construct your own descriptors.
+class LIBPROTOBUF_EXPORT ServiceDescriptor {
+ public:
+  // The name of the service, not including its containing scope.
+  const string& name() const;
+  // The fully-qualified name of the service, scope delimited by periods.
+  const string& full_name() const;
+  // Index of this service within the file's services array.
+  int index() const;
+
+  // The .proto file in which this service was defined.  Never NULL.
+  const FileDescriptor* file() const;
+
+  // Get options for this service type.  These are specified in the .proto file
+  // by placing lines like "option foo = 1234;" in the service definition.
+  // Allowed options are defined by ServiceOptions in
+  // google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const ServiceOptions& options() const;
+
+  // The number of methods this service defines.
+  int method_count() const;
+  // Gets a MethodDescriptor by index, where 0 <= index < method_count().
+  // These are returned in the order they were defined in the .proto file.
+  const MethodDescriptor* method(int index) const;
+
+  // Look up a MethodDescriptor by name.
+  const MethodDescriptor* FindMethodByName(const string& name) const;
+  // See Descriptor::CopyTo().
+  void CopyTo(ServiceDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this service declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef ServiceOptions OptionsType;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // See Descriptor::DebugString().
+  void DebugString(string *contents, const DebugStringOptions& options) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const FileDescriptor* file_;
+  const ServiceOptions* options_;
+  int method_count_;
+  MethodDescriptor* methods_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<ServiceDescriptor>() and AllocateArray<ServiceDescriptor>() in
+  // descriptor.cc and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  ServiceDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class FileDescriptor;
+  friend class MethodDescriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor);
+};
+
+// Describes an individual service method.  To obtain a MethodDescriptor given
+// a service, first get its ServiceDescriptor, then call
+// ServiceDescriptor::FindMethodByName().  Use DescriptorPool to construct your
+// own descriptors.
+class LIBPROTOBUF_EXPORT MethodDescriptor {
+ public:
+  // Name of this method, not including containing scope.
+  const string& name() const;
+  // The fully-qualified name of the method, scope delimited by periods.
+  const string& full_name() const;
+  // Index within the service's Descriptor.
+  int index() const;
+
+  // Gets the service to which this method belongs.  Never NULL.
+  const ServiceDescriptor* service() const;
+
+  // Gets the type of protocol message which this method accepts as input.
+  const Descriptor* input_type() const;
+  // Gets the type of protocol message which this message produces as output.
+  const Descriptor* output_type() const;
+
+  // Gets whether the client streams multiple requests.
+  bool client_streaming() const;
+  // Gets whether the server streams multiple responses.
+  bool server_streaming() const;
+
+  // Get options for this method.  These are specified in the .proto file by
+  // placing lines like "option foo = 1234;" in curly-braces after a method
+  // declaration.  Allowed options are defined by MethodOptions in
+  // google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const MethodOptions& options() const;
+
+  // See Descriptor::CopyTo().
+  void CopyTo(MethodDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this method declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+ private:
+  typedef MethodOptions OptionsType;
+
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
+  // See Descriptor::DebugString().
+  void DebugString(int depth, string *contents,
+                   const DebugStringOptions& options) const;
+
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(std::vector<int>* output) const;
+
+  const string* name_;
+  const string* full_name_;
+  const ServiceDescriptor* service_;
+  const Descriptor* input_type_;
+  const Descriptor* output_type_;
+  const MethodOptions* options_;
+  bool client_streaming_;
+  bool server_streaming_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<MethodDescriptor>() and AllocateArray<MethodDescriptor>() in
+  // descriptor.cc and update them to initialize the field.
+
+  // Must be constructed using DescriptorPool.
+  MethodDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class ServiceDescriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
+};
+
+
+// Describes a whole .proto file.  To get the FileDescriptor for a compiled-in
+// file, get the descriptor for something defined in that file and call
+// descriptor->file().  Use DescriptorPool to construct your own descriptors.
+class LIBPROTOBUF_EXPORT FileDescriptor {
+ public:
+  // The filename, relative to the source tree.
+  // e.g. "google/protobuf/descriptor.proto"
+  const string& name() const;
+
+  // The package, e.g. "google.protobuf.compiler".
+  const string& package() const;
+
+  // The DescriptorPool in which this FileDescriptor and all its contents were
+  // allocated.  Never NULL.
+  const DescriptorPool* pool() const;
+
+  // The number of files imported by this one.
+  int dependency_count() const;
+  // Gets an imported file by index, where 0 <= index < dependency_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FileDescriptor* dependency(int index) const;
+
+  // The number of files public imported by this one.
+  // The public dependency list is a subset of the dependency list.
+  int public_dependency_count() const;
+  // Gets a public imported file by index, where 0 <= index <
+  // public_dependency_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FileDescriptor* public_dependency(int index) const;
+
+  // The number of files that are imported for weak fields.
+  // The weak dependency list is a subset of the dependency list.
+  int weak_dependency_count() const;
+  // Gets a weak imported file by index, where 0 <= index <
+  // weak_dependency_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FileDescriptor* weak_dependency(int index) const;
+
+  // Number of top-level message types defined in this file.  (This does not
+  // include nested types.)
+  int message_type_count() const;
+  // Gets a top-level message type, where 0 <= index < message_type_count().
+  // These are returned in the order they were defined in the .proto file.
+  const Descriptor* message_type(int index) const;
+
+  // Number of top-level enum types defined in this file.  (This does not
+  // include nested types.)
+  int enum_type_count() const;
+  // Gets a top-level enum type, where 0 <= index < enum_type_count().
+  // These are returned in the order they were defined in the .proto file.
+  const EnumDescriptor* enum_type(int index) const;
+
+  // Number of services defined in this file.
+  int service_count() const;
+  // Gets a service, where 0 <= index < service_count().
+  // These are returned in the order they were defined in the .proto file.
+  const ServiceDescriptor* service(int index) const;
+
+  // Number of extensions defined at file scope.  (This does not include
+  // extensions nested within message types.)
+  int extension_count() const;
+  // Gets an extension's descriptor, where 0 <= index < extension_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FieldDescriptor* extension(int index) const;
+
+  // Get options for this file.  These are specified in the .proto file by
+  // placing lines like "option foo = 1234;" at the top level, outside of any
+  // other definitions.  Allowed options are defined by FileOptions in
+  // google/protobuf/descriptor.proto, and any available extensions of that
+  // message.
+  const FileOptions& options() const;
+
+  // Syntax of this file.
+  enum Syntax {
+    SYNTAX_UNKNOWN = 0,
+    SYNTAX_PROTO2  = 2,
+    SYNTAX_PROTO3  = 3,
+  };
+  Syntax syntax() const;
+  static const char* SyntaxName(Syntax syntax);
+
+  // Find a top-level message type by name.  Returns NULL if not found.
+  const Descriptor* FindMessageTypeByName(const string& name) const;
+  // Find a top-level enum type by name.  Returns NULL if not found.
+  const EnumDescriptor* FindEnumTypeByName(const string& name) const;
+  // Find an enum value defined in any top-level enum by name.  Returns NULL if
+  // not found.
+  const EnumValueDescriptor* FindEnumValueByName(const string& name) const;
+  // Find a service definition by name.  Returns NULL if not found.
+  const ServiceDescriptor* FindServiceByName(const string& name) const;
+  // Find a top-level extension definition by name.  Returns NULL if not found.
+  const FieldDescriptor* FindExtensionByName(const string& name) const;
+  // Similar to FindExtensionByName(), but searches by lowercased-name.  See
+  // Descriptor::FindFieldByLowercaseName().
+  const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const;
+  // Similar to FindExtensionByName(), but searches by camelcased-name.  See
+  // Descriptor::FindFieldByCamelcaseName().
+  const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+
+  // See Descriptor::CopyTo().
+  // Notes:
+  // - This method does NOT copy source code information since it is relatively
+  //   large and rarely needed.  See CopySourceCodeInfoTo() below.
+  void CopyTo(FileDescriptorProto* proto) const;
+  // Write the source code information of this FileDescriptor into the given
+  // FileDescriptorProto.  See CopyTo() above.
+  void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
+  // Fill the json_name field of FieldDescriptorProto for all fields. Can only
+  // be called after CopyTo().
+  void CopyJsonNameTo(FileDescriptorProto* proto) const;
+
+  // See Descriptor::DebugString().
+  string DebugString() const;
+
+  // See Descriptor::DebugStringWithOptions().
+  string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+  // Returns true if this is a placeholder for an unknown file. This will
+  // only be the case if this descriptor comes from a DescriptorPool
+  // with AllowUnknownDependencies() set.
+  bool is_placeholder() const;
+
+  // Updates |*out_location| to the source location of the complete extent of
+  // this file declaration (namely, the empty path).
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of the declaration or declaration-part denoted by |path|.
+  // Returns false and leaves |*out_location| unchanged iff location
+  // information was not available.  (See SourceCodeInfo for
+  // description of path encoding.)
+  bool GetSourceLocation(const std::vector<int>& path,
+                         SourceLocation* out_location) const;
+
+ private:
+  typedef FileOptions OptionsType;
+
+  const string* name_;
+  const string* package_;
+  const DescriptorPool* pool_;
+  int dependency_count_;
+  const FileDescriptor** dependencies_;
+  int public_dependency_count_;
+  int* public_dependencies_;
+  int weak_dependency_count_;
+  int* weak_dependencies_;
+  int message_type_count_;
+  Descriptor* message_types_;
+  int enum_type_count_;
+  EnumDescriptor* enum_types_;
+  int service_count_;
+  ServiceDescriptor* services_;
+  int extension_count_;
+  Syntax syntax_;
+  bool is_placeholder_;
+  FieldDescriptor* extensions_;
+  const FileOptions* options_;
+
+  const FileDescriptorTables* tables_;
+  const SourceCodeInfo* source_code_info_;
+  // IMPORTANT:  If you add a new field, make sure to search for all instances
+  // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
+  // descriptor.cc and update them to initialize the field.
+
+  FileDescriptor() {}
+  friend class DescriptorBuilder;
+  friend class Descriptor;
+  friend class FieldDescriptor;
+  friend class OneofDescriptor;
+  friend class EnumDescriptor;
+  friend class EnumValueDescriptor;
+  friend class MethodDescriptor;
+  friend class ServiceDescriptor;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
+};
+
+// ===================================================================
+
+// Used to construct descriptors.
+//
+// Normally you won't want to build your own descriptors.  Message classes
+// constructed by the protocol compiler will provide them for you.  However,
+// if you are implementing Message on your own, or if you are writing a
+// program which can operate on totally arbitrary types and needs to load
+// them from some sort of database, you might need to.
+//
+// Since Descriptors are composed of a whole lot of cross-linked bits of
+// data that would be a pain to put together manually, the
+// DescriptorPool class is provided to make the process easier.  It can
+// take a FileDescriptorProto (defined in descriptor.proto), validate it,
+// and convert it to a set of nicely cross-linked Descriptors.
+//
+// DescriptorPool also helps with memory management.  Descriptors are
+// composed of many objects containing static data and pointers to each
+// other.  In all likelihood, when it comes time to delete this data,
+// you'll want to delete it all at once.  In fact, it is not uncommon to
+// have a whole pool of descriptors all cross-linked with each other which
+// you wish to delete all at once.  This class represents such a pool, and
+// handles the memory management for you.
+//
+// You can also search for descriptors within a DescriptorPool by name, and
+// extensions by number.
+class LIBPROTOBUF_EXPORT DescriptorPool {
+ public:
+  // Create a normal, empty DescriptorPool.
+  DescriptorPool();
+
+  // Constructs a DescriptorPool that, when it can't find something among the
+  // descriptors already in the pool, looks for it in the given
+  // DescriptorDatabase.
+  // Notes:
+  // - If a DescriptorPool is constructed this way, its BuildFile*() methods
+  //   must not be called (they will assert-fail).  The only way to populate
+  //   the pool with descriptors is to call the Find*By*() methods.
+  // - The Find*By*() methods may block the calling thread if the
+  //   DescriptorDatabase blocks.  This in turn means that parsing messages
+  //   may block if they need to look up extensions.
+  // - The Find*By*() methods will use mutexes for thread-safety, thus making
+  //   them slower even when they don't have to fall back to the database.
+  //   In fact, even the Find*By*() methods of descriptor objects owned by
+  //   this pool will be slower, since they will have to obtain locks too.
+  // - An ErrorCollector may optionally be given to collect validation errors
+  //   in files loaded from the database.  If not given, errors will be printed
+  //   to GOOGLE_LOG(ERROR).  Remember that files are built on-demand, so this
+  //   ErrorCollector may be called from any thread that calls one of the
+  //   Find*By*() methods.
+  // - The DescriptorDatabase must not be mutated during the lifetime of
+  //   the DescriptorPool. Even if the client takes care to avoid data races,
+  //   changes to the content of the DescriptorDatabase may not be reflected
+  //   in subsequent lookups in the DescriptorPool.
+  class ErrorCollector;
+  explicit DescriptorPool(DescriptorDatabase* fallback_database,
+                          ErrorCollector* error_collector = NULL);
+
+  ~DescriptorPool();
+
+  // Get a pointer to the generated pool.  Generated protocol message classes
+  // which are compiled into the binary will allocate their descriptors in
+  // this pool.  Do not add your own descriptors to this pool.
+  static const DescriptorPool* generated_pool();
+
+
+  // Find a FileDescriptor in the pool by file name.  Returns NULL if not
+  // found.
+  const FileDescriptor* FindFileByName(const string& name) const;
+
+  // Find the FileDescriptor in the pool which defines the given symbol.
+  // If any of the Find*ByName() methods below would succeed, then this is
+  // equivalent to calling that method and calling the result's file() method.
+  // Otherwise this returns NULL.
+  const FileDescriptor* FindFileContainingSymbol(
+      const string& symbol_name) const;
+
+  // Looking up descriptors ------------------------------------------
+  // These find descriptors by fully-qualified name.  These will find both
+  // top-level descriptors and nested descriptors.  They return NULL if not
+  // found.
+
+  const Descriptor* FindMessageTypeByName(const string& name) const;
+  const FieldDescriptor* FindFieldByName(const string& name) const;
+  const FieldDescriptor* FindExtensionByName(const string& name) const;
+  const OneofDescriptor* FindOneofByName(const string& name) const;
+  const EnumDescriptor* FindEnumTypeByName(const string& name) const;
+  const EnumValueDescriptor* FindEnumValueByName(const string& name) const;
+  const ServiceDescriptor* FindServiceByName(const string& name) const;
+  const MethodDescriptor* FindMethodByName(const string& name) const;
+
+  // Finds an extension of the given type by number.  The extendee must be
+  // a member of this DescriptorPool or one of its underlays.
+  const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee,
+                                               int number) const;
+
+  // Finds extensions of extendee. The extensions will be appended to
+  // out in an undefined order. Only extensions defined directly in
+  // this DescriptorPool or one of its underlays are guaranteed to be
+  // found: extensions defined in the fallback database might not be found
+  // depending on the database implementation.
+  void FindAllExtensions(const Descriptor* extendee,
+                         std::vector<const FieldDescriptor*>* out) const;
+
+  // Building descriptors --------------------------------------------
+
+  // When converting a FileDescriptorProto to a FileDescriptor, various
+  // errors might be detected in the input.  The caller may handle these
+  // programmatically by implementing an ErrorCollector.
+  class LIBPROTOBUF_EXPORT ErrorCollector {
+   public:
+    inline ErrorCollector() {}
+    virtual ~ErrorCollector();
+
+    // These constants specify what exact part of the construct is broken.
+    // This is useful e.g. for mapping the error back to an exact location
+    // in a .proto file.
+    enum ErrorLocation {
+      NAME,              // the symbol name, or the package name for files
+      NUMBER,            // field or extension range number
+      TYPE,              // field type
+      EXTENDEE,          // field extendee
+      DEFAULT_VALUE,     // field default value
+      INPUT_TYPE,        // method input type
+      OUTPUT_TYPE,       // method output type
+      OPTION_NAME,       // name in assignment
+      OPTION_VALUE,      // value in option assignment
+      OTHER              // some other problem
+    };
+
+    // Reports an error in the FileDescriptorProto. Use this function if the
+    // problem occurred should interrupt building the FileDescriptorProto.
+    virtual void AddError(
+      const string& filename,      // File name in which the error occurred.
+      const string& element_name,  // Full name of the erroneous element.
+      const Message* descriptor,   // Descriptor of the erroneous element.
+      ErrorLocation location,      // One of the location constants, above.
+      const string& message        // Human-readable error message.
+      ) = 0;
+
+    // Reports a warning in the FileDescriptorProto. Use this function if the
+    // problem occurred should NOT interrupt building the FileDescriptorProto.
+    virtual void AddWarning(
+      const string& /*filename*/,      // File name in which the error occurred.
+      const string& /*element_name*/,  // Full name of the erroneous element.
+      const Message* /*descriptor*/,   // Descriptor of the erroneous element.
+      ErrorLocation /*location*/,      // One of the location constants, above.
+      const string& /*message*/        // Human-readable error message.
+      ) {}
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
+  };
+
+  // Convert the FileDescriptorProto to real descriptors and place them in
+  // this DescriptorPool.  All dependencies of the file must already be in
+  // the pool.  Returns the resulting FileDescriptor, or NULL if there were
+  // problems with the input (e.g. the message was invalid, or dependencies
+  // were missing).  Details about the errors are written to GOOGLE_LOG(ERROR).
+  const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
+
+  // Same as BuildFile() except errors are sent to the given ErrorCollector.
+  const FileDescriptor* BuildFileCollectingErrors(
+    const FileDescriptorProto& proto,
+    ErrorCollector* error_collector);
+
+  // By default, it is an error if a FileDescriptorProto contains references
+  // to types or other files that are not found in the DescriptorPool (or its
+  // backing DescriptorDatabase, if any).  If you call
+  // AllowUnknownDependencies(), however, then unknown types and files
+  // will be replaced by placeholder descriptors (which can be identified by
+  // the is_placeholder() method).  This can allow you to
+  // perform some useful operations with a .proto file even if you do not
+  // have access to other .proto files on which it depends.  However, some
+  // heuristics must be used to fill in the gaps in information, and these
+  // can lead to descriptors which are inaccurate.  For example, the
+  // DescriptorPool may be forced to guess whether an unknown type is a message
+  // or an enum, as well as what package it resides in.  Furthermore,
+  // placeholder types will not be discoverable via FindMessageTypeByName()
+  // and similar methods, which could confuse some descriptor-based algorithms.
+  // Generally, the results of this option should be handled with extreme care.
+  void AllowUnknownDependencies() { allow_unknown_ = true; }
+
+  // By default, weak imports are allowed to be missing, in which case we will
+  // use a placeholder for the dependency and convert the field to be an Empty
+  // message field. If you call EnforceWeakDependencies(true), however, the
+  // DescriptorPool will report a import not found error.
+  void EnforceWeakDependencies(bool enforce) { enforce_weak_ = enforce; }
+
+  // Internal stuff --------------------------------------------------
+  // These methods MUST NOT be called from outside the proto2 library.
+  // These methods may contain hidden pitfalls and may be removed in a
+  // future library version.
+
+  // Create a DescriptorPool which is overlaid on top of some other pool.
+  // If you search for a descriptor in the overlay and it is not found, the
+  // underlay will be searched as a backup.  If the underlay has its own
+  // underlay, that will be searched next, and so on.  This also means that
+  // files built in the overlay will be cross-linked with the underlay's
+  // descriptors if necessary.  The underlay remains property of the caller;
+  // it must remain valid for the lifetime of the newly-constructed pool.
+  //
+  // Example:  Say you want to parse a .proto file at runtime in order to use
+  // its type with a DynamicMessage.  Say this .proto file has dependencies,
+  // but you know that all the dependencies will be things that are already
+  // compiled into the binary.  For ease of use, you'd like to load the types
+  // right out of generated_pool() rather than have to parse redundant copies
+  // of all these .protos and runtime.  But, you don't want to add the parsed
+  // types directly into generated_pool(): this is not allowed, and would be
+  // bad design anyway.  So, instead, you could use generated_pool() as an
+  // underlay for a new DescriptorPool in which you add only the new file.
+  //
+  // WARNING:  Use of underlays can lead to many subtle gotchas.  Instead,
+  //   try to formulate what you want to do in terms of DescriptorDatabases.
+  explicit DescriptorPool(const DescriptorPool* underlay);
+
+  // Called by generated classes at init time to add their descriptors to
+  // generated_pool.  Do NOT call this in your own code!  filename must be a
+  // permanent string (e.g. a string literal).
+  static void InternalAddGeneratedFile(
+      const void* encoded_file_descriptor, int size);
+
+
+  // For internal use only:  Gets a non-const pointer to the generated pool.
+  // This is called at static-initialization time only, so thread-safety is
+  // not a concern.  If both an underlay and a fallback database are present,
+  // the underlay takes precedence.
+  static DescriptorPool* internal_generated_pool();
+
+  // For internal use only:  Changes the behavior of BuildFile() such that it
+  // allows the file to make reference to message types declared in other files
+  // which it did not officially declare as dependencies.
+  void InternalDontEnforceDependencies();
+
+  // For internal use only.
+  void internal_set_underlay(const DescriptorPool* underlay) {
+    underlay_ = underlay;
+  }
+
+  // For internal (unit test) use only:  Returns true if a FileDescriptor has
+  // been constructed for the given file, false otherwise.  Useful for testing
+  // lazy descriptor initialization behavior.
+  bool InternalIsFileLoaded(const string& filename) const;
+
+
+  // Add a file to unused_import_track_files_. DescriptorBuilder will log
+  // warnings for those files if there is any unused import.
+  void AddUnusedImportTrackFile(const string& file_name);
+  void ClearUnusedImportTrackFiles();
+
+ private:
+  friend class Descriptor;
+  friend class FieldDescriptor;
+  friend class EnumDescriptor;
+  friend class ServiceDescriptor;
+  friend class FileDescriptor;
+  friend class DescriptorBuilder;
+  friend class FileDescriptorTables;
+
+  // Return true if the given name is a sub-symbol of any non-package
+  // descriptor that already exists in the descriptor pool.  (The full
+  // definition of such types is already known.)
+  bool IsSubSymbolOfBuiltType(const string& name) const;
+
+  // Tries to find something in the fallback database and link in the
+  // corresponding proto file.  Returns true if successful, in which case
+  // the caller should search for the thing again.  These are declared
+  // const because they are called by (semantically) const methods.
+  bool TryFindFileInFallbackDatabase(const string& name) const;
+  bool TryFindSymbolInFallbackDatabase(const string& name) const;
+  bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type,
+                                          int field_number) const;
+
+  // Like BuildFile() but called internally when the file has been loaded from
+  // fallback_database_.  Declared const because it is called by (semantically)
+  // const methods.
+  const FileDescriptor* BuildFileFromDatabase(
+    const FileDescriptorProto& proto) const;
+
+  // If fallback_database_ is NULL, this is NULL.  Otherwise, this is a mutex
+  // which must be locked while accessing tables_.
+  Mutex* mutex_;
+
+  // See constructor.
+  DescriptorDatabase* fallback_database_;
+  ErrorCollector* default_error_collector_;
+  const DescriptorPool* underlay_;
+
+  // This class contains a lot of hash maps with complicated types that
+  // we'd like to keep out of the header.
+  class Tables;
+  google::protobuf::scoped_ptr<Tables> tables_;
+
+  bool enforce_dependencies_;
+  bool allow_unknown_;
+  bool enforce_weak_;
+  std::set<string> unused_import_track_files_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool);
+};
+
+// inline methods ====================================================
+
+// These macros makes this repetitive code more readable.
+#define PROTOBUF_DEFINE_ACCESSOR(CLASS, FIELD, TYPE) \
+  inline TYPE CLASS::FIELD() const { return FIELD##_; }
+
+// Strings fields are stored as pointers but returned as const references.
+#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \
+  inline const string& CLASS::FIELD() const { return *FIELD##_; }
+
+// Arrays take an index parameter, obviously.
+#define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \
+  inline TYPE CLASS::FIELD(int index) const { return FIELD##s_ + index; }
+
+#define PROTOBUF_DEFINE_OPTIONS_ACCESSOR(CLASS, TYPE) \
+  inline const TYPE& CLASS::options() const { return *options_; }
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(Descriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(Descriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, file, const FileDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*)
+
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int)
+
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, field, const FieldDescriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, oneof_decl, const OneofDescriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, nested_type, const Descriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, enum_type, const EnumDescriptor*)
+
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_range_count, int)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range,
+                               const Descriptor::ExtensionRange*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
+                               const FieldDescriptor*)
+
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range,
+                               const Descriptor::ReservedRange*)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_name_count, int)
+
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, json_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, lowercase_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, number, int)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, type, FieldDescriptor::Type)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, label, FieldDescriptor::Label)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_oneof,
+                         const OneofDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, index_in_oneof, int)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 )
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 )
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint32, uint32)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint64, uint64)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float , float )
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_double, double)
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool  , bool  )
+PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_enum,
+                         const EnumValueDescriptor*)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, containing_type, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, field_count, int)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, file, const FileDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value,
+                               const EnumValueDescriptor*)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions)
+PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, is_placeholder, bool)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int)
+PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method,
+                               const MethodDescriptor*)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name)
+PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*)
+PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*)
+PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions)
+PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, client_streaming, bool)
+PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, server_streaming, bool)
+
+PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, is_placeholder, bool)
+
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, service,
+                               const ServiceDescriptor*)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension,
+                               const FieldDescriptor*)
+
+#undef PROTOBUF_DEFINE_ACCESSOR
+#undef PROTOBUF_DEFINE_STRING_ACCESSOR
+#undef PROTOBUF_DEFINE_ARRAY_ACCESSOR
+
+// A few accessors differ from the macros...
+
+inline bool Descriptor::IsExtensionNumber(int number) const {
+  return FindExtensionRangeContainingNumber(number) != NULL;
+}
+
+inline bool Descriptor::IsReservedNumber(int number) const {
+  return FindReservedRangeContainingNumber(number) != NULL;
+}
+
+inline bool Descriptor::IsReservedName(const string& name) const {
+  for (int i = 0; i < reserved_name_count(); i++) {
+    if (name == reserved_name(i)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually
+// an array of pointers rather than the usual array of objects.
+inline const string& Descriptor::reserved_name(int index) const {
+  return *reserved_names_[index];
+}
+
+inline bool FieldDescriptor::is_required() const {
+  return label() == LABEL_REQUIRED;
+}
+
+inline bool FieldDescriptor::is_optional() const {
+  return label() == LABEL_OPTIONAL;
+}
+
+inline bool FieldDescriptor::is_repeated() const {
+  return label() == LABEL_REPEATED;
+}
+
+inline bool FieldDescriptor::is_packable() const {
+  return is_repeated() && IsTypePackable(type());
+}
+
+// To save space, index() is computed by looking at the descriptor's position
+// in the parent's array of children.
+inline int FieldDescriptor::index() const {
+  if (!is_extension_) {
+    return static_cast<int>(this - containing_type_->fields_);
+  } else if (extension_scope_ != NULL) {
+    return static_cast<int>(this - extension_scope_->extensions_);
+  } else {
+    return static_cast<int>(this - file_->extensions_);
+  }
+}
+
+inline int Descriptor::index() const {
+  if (containing_type_ == NULL) {
+    return static_cast<int>(this - file_->message_types_);
+  } else {
+    return static_cast<int>(this - containing_type_->nested_types_);
+  }
+}
+
+inline int OneofDescriptor::index() const {
+  return static_cast<int>(this - containing_type_->oneof_decls_);
+}
+
+inline int EnumDescriptor::index() const {
+  if (containing_type_ == NULL) {
+    return static_cast<int>(this - file_->enum_types_);
+  } else {
+    return static_cast<int>(this - containing_type_->enum_types_);
+  }
+}
+
+inline int EnumValueDescriptor::index() const {
+  return static_cast<int>(this - type_->values_);
+}
+
+inline int ServiceDescriptor::index() const {
+  return static_cast<int>(this - file_->services_);
+}
+
+inline int MethodDescriptor::index() const {
+  return static_cast<int>(this - service_->methods_);
+}
+
+inline const char* FieldDescriptor::type_name() const {
+  return kTypeToName[type_];
+}
+
+inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
+  return kTypeToCppTypeMap[type_];
+}
+
+inline const char* FieldDescriptor::cpp_type_name() const {
+  return kCppTypeToName[kTypeToCppTypeMap[type_]];
+}
+
+inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
+  return kTypeToCppTypeMap[type];
+}
+
+inline const char* FieldDescriptor::TypeName(Type type) {
+  return kTypeToName[type];
+}
+
+inline const char* FieldDescriptor::CppTypeName(CppType cpp_type) {
+  return kCppTypeToName[cpp_type];
+}
+
+inline bool FieldDescriptor::IsTypePackable(Type field_type) {
+  return (field_type != FieldDescriptor::TYPE_STRING &&
+          field_type != FieldDescriptor::TYPE_GROUP &&
+          field_type != FieldDescriptor::TYPE_MESSAGE &&
+          field_type != FieldDescriptor::TYPE_BYTES);
+}
+
+inline const FileDescriptor* FileDescriptor::dependency(int index) const {
+  return dependencies_[index];
+}
+
+inline const FileDescriptor* FileDescriptor::public_dependency(
+    int index) const {
+  return dependencies_[public_dependencies_[index]];
+}
+
+inline const FileDescriptor* FileDescriptor::weak_dependency(
+    int index) const {
+  return dependencies_[weak_dependencies_[index]];
+}
+
+inline FileDescriptor::Syntax FileDescriptor::syntax() const {
+  return syntax_;
+}
+
+// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because fields_ is actually an array
+// of pointers rather than the usual array of objects.
+inline const FieldDescriptor* OneofDescriptor::field(int index) const {
+  return fields_[index];
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_DESCRIPTOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.cc
new file mode 100644
index 0000000..4d5c4d9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.cc
@@ -0,0 +1,15168 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/descriptor.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* FileDescriptorSet_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FileDescriptorSet_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FileDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FileDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* DescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  DescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  DescriptorProto_ExtensionRange_reflection_ = NULL;
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  DescriptorProto_ReservedRange_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FieldDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FieldDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* OneofDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  OneofDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* EnumDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  EnumDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* EnumValueDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  EnumValueDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* ServiceDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  ServiceDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* MethodDescriptorProto_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  MethodDescriptorProto_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FileOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FileOptions_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* MessageOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  MessageOptions_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FieldOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FieldOptions_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* EnumOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  EnumOptions_reflection_ = NULL;
+const ::google::protobuf::Descriptor* EnumValueOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  EnumValueOptions_reflection_ = NULL;
+const ::google::protobuf::Descriptor* ServiceOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  ServiceOptions_reflection_ = NULL;
+const ::google::protobuf::Descriptor* MethodOptions_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  MethodOptions_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UninterpretedOption_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  UninterpretedOption_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  UninterpretedOption_NamePart_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_Location_reflection_ = NULL;
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  GeneratedCodeInfo_reflection_ = NULL;
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_Annotation_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  GeneratedCodeInfo_Annotation_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/descriptor.proto");
+  GOOGLE_CHECK(file != NULL);
+  FileDescriptorSet_descriptor_ = file->message_type(0);
+  static const int FileDescriptorSet_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, file_),
+  };
+  FileDescriptorSet_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FileDescriptorSet_descriptor_,
+      FileDescriptorSet::default_instance_,
+      FileDescriptorSet_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(FileDescriptorSet),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_),
+      -1);
+  FileDescriptorProto_descriptor_ = file->message_type(1);
+  static const int FileDescriptorProto_offsets_[12] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, syntax_),
+  };
+  FileDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FileDescriptorProto_descriptor_,
+      FileDescriptorProto::default_instance_,
+      FileDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(FileDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_),
+      -1);
+  DescriptorProto_descriptor_ = file->message_type(2);
+  static const int DescriptorProto_offsets_[10] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, nested_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, enum_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_range_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_name_),
+  };
+  DescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      DescriptorProto_descriptor_,
+      DescriptorProto::default_instance_,
+      DescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(DescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_),
+      -1);
+  DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0);
+  static const int DescriptorProto_ExtensionRange_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_),
+  };
+  DescriptorProto_ExtensionRange_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      DescriptorProto_ExtensionRange_descriptor_,
+      DescriptorProto_ExtensionRange::default_instance_,
+      DescriptorProto_ExtensionRange_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(DescriptorProto_ExtensionRange),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_),
+      -1);
+  DescriptorProto_ReservedRange_descriptor_ = DescriptorProto_descriptor_->nested_type(1);
+  static const int DescriptorProto_ReservedRange_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, start_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, end_),
+  };
+  DescriptorProto_ReservedRange_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      DescriptorProto_ReservedRange_descriptor_,
+      DescriptorProto_ReservedRange::default_instance_,
+      DescriptorProto_ReservedRange_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(DescriptorProto_ReservedRange),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
+      -1);
+  FieldDescriptorProto_descriptor_ = file->message_type(3);
+  static const int FieldDescriptorProto_offsets_[10] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, json_name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_),
+  };
+  FieldDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FieldDescriptorProto_descriptor_,
+      FieldDescriptorProto::default_instance_,
+      FieldDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(FieldDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_),
+      -1);
+  FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0);
+  FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1);
+  OneofDescriptorProto_descriptor_ = file->message_type(4);
+  static const int OneofDescriptorProto_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, name_),
+  };
+  OneofDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      OneofDescriptorProto_descriptor_,
+      OneofDescriptorProto::default_instance_,
+      OneofDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(OneofDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_),
+      -1);
+  EnumDescriptorProto_descriptor_ = file->message_type(5);
+  static const int EnumDescriptorProto_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, options_),
+  };
+  EnumDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      EnumDescriptorProto_descriptor_,
+      EnumDescriptorProto::default_instance_,
+      EnumDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(EnumDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_),
+      -1);
+  EnumValueDescriptorProto_descriptor_ = file->message_type(6);
+  static const int EnumValueDescriptorProto_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, options_),
+  };
+  EnumValueDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      EnumValueDescriptorProto_descriptor_,
+      EnumValueDescriptorProto::default_instance_,
+      EnumValueDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(EnumValueDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_),
+      -1);
+  ServiceDescriptorProto_descriptor_ = file->message_type(7);
+  static const int ServiceDescriptorProto_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, options_),
+  };
+  ServiceDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      ServiceDescriptorProto_descriptor_,
+      ServiceDescriptorProto::default_instance_,
+      ServiceDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(ServiceDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_),
+      -1);
+  MethodDescriptorProto_descriptor_ = file->message_type(8);
+  static const int MethodDescriptorProto_offsets_[6] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, output_type_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, client_streaming_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, server_streaming_),
+  };
+  MethodDescriptorProto_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      MethodDescriptorProto_descriptor_,
+      MethodDescriptorProto::default_instance_,
+      MethodDescriptorProto_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(MethodDescriptorProto),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
+      -1);
+  FileOptions_descriptor_ = file->message_type(9);
+  static const int FileOptions_offsets_[15] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_string_check_utf8_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
+  };
+  FileOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FileOptions_descriptor_,
+      FileOptions::default_instance_,
+      FileOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_),
+      sizeof(FileOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_),
+      -1);
+  FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0);
+  MessageOptions_descriptor_ = file->message_type(10);
+  static const int MessageOptions_offsets_[5] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, map_entry_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_),
+  };
+  MessageOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      MessageOptions_descriptor_,
+      MessageOptions::default_instance_,
+      MessageOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_),
+      sizeof(MessageOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_),
+      -1);
+  FieldOptions_descriptor_ = file->message_type(11);
+  static const int FieldOptions_offsets_[7] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, jstype_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
+  };
+  FieldOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FieldOptions_descriptor_,
+      FieldOptions::default_instance_,
+      FieldOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_),
+      sizeof(FieldOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_),
+      -1);
+  FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
+  FieldOptions_JSType_descriptor_ = FieldOptions_descriptor_->enum_type(1);
+  EnumOptions_descriptor_ = file->message_type(12);
+  static const int EnumOptions_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_),
+  };
+  EnumOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      EnumOptions_descriptor_,
+      EnumOptions::default_instance_,
+      EnumOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_),
+      sizeof(EnumOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_),
+      -1);
+  EnumValueOptions_descriptor_ = file->message_type(13);
+  static const int EnumValueOptions_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_),
+  };
+  EnumValueOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      EnumValueOptions_descriptor_,
+      EnumValueOptions::default_instance_,
+      EnumValueOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_),
+      sizeof(EnumValueOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_),
+      -1);
+  ServiceOptions_descriptor_ = file->message_type(14);
+  static const int ServiceOptions_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_),
+  };
+  ServiceOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      ServiceOptions_descriptor_,
+      ServiceOptions::default_instance_,
+      ServiceOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_),
+      sizeof(ServiceOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_),
+      -1);
+  MethodOptions_descriptor_ = file->message_type(15);
+  static const int MethodOptions_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_),
+  };
+  MethodOptions_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      MethodOptions_descriptor_,
+      MethodOptions::default_instance_,
+      MethodOptions_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _has_bits_[0]),
+      -1,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_),
+      sizeof(MethodOptions),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_),
+      -1);
+  UninterpretedOption_descriptor_ = file->message_type(16);
+  static const int UninterpretedOption_offsets_[7] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_),
+  };
+  UninterpretedOption_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      UninterpretedOption_descriptor_,
+      UninterpretedOption::default_instance_,
+      UninterpretedOption_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(UninterpretedOption),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_),
+      -1);
+  UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0);
+  static const int UninterpretedOption_NamePart_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, is_extension_),
+  };
+  UninterpretedOption_NamePart_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      UninterpretedOption_NamePart_descriptor_,
+      UninterpretedOption_NamePart::default_instance_,
+      UninterpretedOption_NamePart_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(UninterpretedOption_NamePart),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_),
+      -1);
+  SourceCodeInfo_descriptor_ = file->message_type(17);
+  static const int SourceCodeInfo_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
+  };
+  SourceCodeInfo_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      SourceCodeInfo_descriptor_,
+      SourceCodeInfo::default_instance_,
+      SourceCodeInfo_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(SourceCodeInfo),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_),
+      -1);
+  SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
+  static const int SourceCodeInfo_Location_offsets_[5] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_),
+  };
+  SourceCodeInfo_Location_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      SourceCodeInfo_Location_descriptor_,
+      SourceCodeInfo_Location::default_instance_,
+      SourceCodeInfo_Location_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(SourceCodeInfo_Location),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_),
+      -1);
+  GeneratedCodeInfo_descriptor_ = file->message_type(18);
+  static const int GeneratedCodeInfo_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, annotation_),
+  };
+  GeneratedCodeInfo_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      GeneratedCodeInfo_descriptor_,
+      GeneratedCodeInfo::default_instance_,
+      GeneratedCodeInfo_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(GeneratedCodeInfo),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _internal_metadata_),
+      -1);
+  GeneratedCodeInfo_Annotation_descriptor_ = GeneratedCodeInfo_descriptor_->nested_type(0);
+  static const int GeneratedCodeInfo_Annotation_offsets_[4] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, path_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, source_file_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, begin_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, end_),
+  };
+  GeneratedCodeInfo_Annotation_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      GeneratedCodeInfo_Annotation_descriptor_,
+      GeneratedCodeInfo_Annotation::default_instance_,
+      GeneratedCodeInfo_Annotation_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _has_bits_[0]),
+      -1,
+      -1,
+      sizeof(GeneratedCodeInfo_Annotation),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _internal_metadata_),
+      -1);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FileDescriptorSet_descriptor_, &FileDescriptorSet::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FileDescriptorProto_descriptor_, &FileDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      DescriptorProto_descriptor_, &DescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      DescriptorProto_ReservedRange_descriptor_, &DescriptorProto_ReservedRange::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      OneofDescriptorProto_descriptor_, &OneofDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      EnumDescriptorProto_descriptor_, &EnumDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      EnumValueDescriptorProto_descriptor_, &EnumValueDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      ServiceDescriptorProto_descriptor_, &ServiceDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      MethodDescriptorProto_descriptor_, &MethodDescriptorProto::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FileOptions_descriptor_, &FileOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      MessageOptions_descriptor_, &MessageOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FieldOptions_descriptor_, &FieldOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      EnumOptions_descriptor_, &EnumOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      EnumValueOptions_descriptor_, &EnumValueOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      ServiceOptions_descriptor_, &ServiceOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      MethodOptions_descriptor_, &MethodOptions::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      UninterpretedOption_descriptor_, &UninterpretedOption::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      GeneratedCodeInfo_descriptor_, &GeneratedCodeInfo::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      GeneratedCodeInfo_Annotation_descriptor_, &GeneratedCodeInfo_Annotation::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() {
+  delete FileDescriptorSet::default_instance_;
+  delete FileDescriptorSet_reflection_;
+  delete FileDescriptorProto::default_instance_;
+  delete FileDescriptorProto_reflection_;
+  delete DescriptorProto::default_instance_;
+  delete DescriptorProto_reflection_;
+  delete DescriptorProto_ExtensionRange::default_instance_;
+  delete DescriptorProto_ExtensionRange_reflection_;
+  delete DescriptorProto_ReservedRange::default_instance_;
+  delete DescriptorProto_ReservedRange_reflection_;
+  delete FieldDescriptorProto::default_instance_;
+  delete FieldDescriptorProto_reflection_;
+  delete OneofDescriptorProto::default_instance_;
+  delete OneofDescriptorProto_reflection_;
+  delete EnumDescriptorProto::default_instance_;
+  delete EnumDescriptorProto_reflection_;
+  delete EnumValueDescriptorProto::default_instance_;
+  delete EnumValueDescriptorProto_reflection_;
+  delete ServiceDescriptorProto::default_instance_;
+  delete ServiceDescriptorProto_reflection_;
+  delete MethodDescriptorProto::default_instance_;
+  delete MethodDescriptorProto_reflection_;
+  delete FileOptions::default_instance_;
+  delete FileOptions_reflection_;
+  delete MessageOptions::default_instance_;
+  delete MessageOptions_reflection_;
+  delete FieldOptions::default_instance_;
+  delete FieldOptions_reflection_;
+  delete EnumOptions::default_instance_;
+  delete EnumOptions_reflection_;
+  delete EnumValueOptions::default_instance_;
+  delete EnumValueOptions_reflection_;
+  delete ServiceOptions::default_instance_;
+  delete ServiceOptions_reflection_;
+  delete MethodOptions::default_instance_;
+  delete MethodOptions_reflection_;
+  delete UninterpretedOption::default_instance_;
+  delete UninterpretedOption_reflection_;
+  delete UninterpretedOption_NamePart::default_instance_;
+  delete UninterpretedOption_NamePart_reflection_;
+  delete SourceCodeInfo::default_instance_;
+  delete SourceCodeInfo_reflection_;
+  delete SourceCodeInfo_Location::default_instance_;
+  delete SourceCodeInfo_Location_reflection_;
+  delete GeneratedCodeInfo::default_instance_;
+  delete GeneratedCodeInfo_reflection_;
+  delete GeneratedCodeInfo_Annotation::default_instance_;
+  delete GeneratedCodeInfo_Annotation_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n google/protobuf/descriptor.proto\022\017goog"
+    "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
+    "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
+    "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+    "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
+    "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
+    "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
+    "le.protobuf.DescriptorProto\0227\n\tenum_type"
+    "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP"
+    "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf."
+    "ServiceDescriptorProto\0228\n\textension\030\007 \003("
+    "\0132%.google.protobuf.FieldDescriptorProto"
+    "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
+    "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
+    "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
+    "(\t\"\360\004\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
+    "field\030\002 \003(\0132%.google.protobuf.FieldDescr"
+    "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p"
+    "rotobuf.FieldDescriptorProto\0225\n\013nested_t"
+    "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr"
+    "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf"
+    ".EnumDescriptorProto\022H\n\017extension_range\030"
+    "\005 \003(\0132/.google.protobuf.DescriptorProto."
+    "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo"
+    "gle.protobuf.OneofDescriptorProto\0220\n\007opt"
+    "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti"
+    "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro"
+    "tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
+    "eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
+    "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
+    "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\274\005\n\024FieldD"
+    "escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
+    " \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
+    "eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
+    ".google.protobuf.FieldDescriptorProto.Ty"
+    "pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022"
+    "\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t "
+    "\001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(\0132"
+    "\035.google.protobuf.FieldOptions\"\266\002\n\004Type\022"
+    "\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE"
+    "_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020"
+    "\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n"
+    "\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GR"
+    "OUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022"
+    "\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_"
+    "SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SI"
+    "NT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABE"
+    "L_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABE"
+    "L_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n\004"
+    "name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004na"
+    "me\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protobu"
+    "f.EnumValueDescriptorProto\022-\n\007options\030\003 "
+    "\001(\0132\034.google.protobuf.EnumOptions\"l\n\030Enu"
+    "mValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006n"
+    "umber\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.pr"
+    "otobuf.EnumValueOptions\"\220\001\n\026ServiceDescr"
+    "iptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\013"
+    "2&.google.protobuf.MethodDescriptorProto"
+    "\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Serv"
+    "iceOptions\"\301\001\n\025MethodDescriptorProto\022\014\n\004"
+    "name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output"
+    "_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
+    "otobuf.MethodOptions\022\037\n\020client_streaming"
+    "\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
+    "\005false\"\207\005\n\013FileOptions\022\024\n\014java_package\030\001"
+    " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
+    "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
+    "enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
+    "java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014o"
+    "ptimize_for\030\t \001(\0162).google.protobuf.File"
+    "Options.OptimizeMode:\005SPEED\022\022\n\ngo_packag"
+    "e\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fa"
+    "lse\022$\n\025java_generic_services\030\021 \001(\010:\005fals"
+    "e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
+    "\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
+    "enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
+    " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024uninte"
+    "rpreted_option\030\347\007 \003(\0132$.google.protobuf."
+    "UninterpretedOption\":\n\014OptimizeMode\022\t\n\005S"
+    "PEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*"
+    "\t\010\350\007\020\200\200\200\200\002J\004\010&\020\'\"\346\001\n\016MessageOptions\022&\n\027m"
+    "essage_set_wire_format\030\001 \001(\010:\005false\022.\n\037n"
+    "o_standard_descriptor_accessor\030\002 \001(\010:\005fa"
+    "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_en"
+    "try\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\013"
+    "2$.google.protobuf.UninterpretedOption*\t"
+    "\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001("
+    "\0162#.google.protobuf.FieldOptions.CType:\006"
+    "STRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$"
+    ".google.protobuf.FieldOptions.JSType:\tJS"
+    "_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecat"
+    "ed\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024"
+    "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+    "tobuf.UninterpretedOption\"/\n\005CType\022\n\n\006ST"
+    "RING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JS"
+    "Type\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS"
+    "_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013"
+    "allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f"
+    "alse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+    "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+    "\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001"
+    " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+    "(\0132$.google.protobuf.UninterpretedOption"
+    "*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndepreca"
+    "ted\030! \001(\010:\005false\022C\n\024uninterpreted_option"
+    "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
+    "ption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndep"
+    "recated\030! \001(\010:\005false\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOp"
+    "tion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Uni"
+    "nterpretedOption.NamePart\022\030\n\020identifier_"
+    "value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022"
+    "\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_va"
+    "lue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggre"
+    "gate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_par"
+    "t\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016Source"
+    "CodeInfo\022:\n\010location\030\001 \003(\0132(.google.prot"
+    "obuf.SourceCodeInfo.Location\032\206\001\n\010Locatio"
+    "n\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n"
+    "\020leading_comments\030\003 \001(\t\022\031\n\021trailing_comm"
+    "ents\030\004 \001(\t\022!\n\031leading_detached_comments\030"
+    "\006 \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotatio"
+    "n\030\001 \003(\0132-.google.protobuf.GeneratedCodeI"
+    "nfo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003"
+    "(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001"
+    "(\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020"
+    "DescriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032G"
+    "oogle.Protobuf.Reflection", 5145);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
+  FileDescriptorSet::default_instance_ = new FileDescriptorSet();
+  FileDescriptorProto::default_instance_ = new FileDescriptorProto();
+  DescriptorProto::default_instance_ = new DescriptorProto();
+  DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange();
+  DescriptorProto_ReservedRange::default_instance_ = new DescriptorProto_ReservedRange();
+  FieldDescriptorProto::default_instance_ = new FieldDescriptorProto();
+  OneofDescriptorProto::default_instance_ = new OneofDescriptorProto();
+  EnumDescriptorProto::default_instance_ = new EnumDescriptorProto();
+  EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto();
+  ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto();
+  MethodDescriptorProto::default_instance_ = new MethodDescriptorProto();
+  FileOptions::default_instance_ = new FileOptions();
+  MessageOptions::default_instance_ = new MessageOptions();
+  FieldOptions::default_instance_ = new FieldOptions();
+  EnumOptions::default_instance_ = new EnumOptions();
+  EnumValueOptions::default_instance_ = new EnumValueOptions();
+  ServiceOptions::default_instance_ = new ServiceOptions();
+  MethodOptions::default_instance_ = new MethodOptions();
+  UninterpretedOption::default_instance_ = new UninterpretedOption();
+  UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
+  SourceCodeInfo::default_instance_ = new SourceCodeInfo();
+  SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location();
+  GeneratedCodeInfo::default_instance_ = new GeneratedCodeInfo();
+  GeneratedCodeInfo_Annotation::default_instance_ = new GeneratedCodeInfo_Annotation();
+  FileDescriptorSet::default_instance_->InitAsDefaultInstance();
+  FileDescriptorProto::default_instance_->InitAsDefaultInstance();
+  DescriptorProto::default_instance_->InitAsDefaultInstance();
+  DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance();
+  DescriptorProto_ReservedRange::default_instance_->InitAsDefaultInstance();
+  FieldDescriptorProto::default_instance_->InitAsDefaultInstance();
+  OneofDescriptorProto::default_instance_->InitAsDefaultInstance();
+  EnumDescriptorProto::default_instance_->InitAsDefaultInstance();
+  EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance();
+  ServiceDescriptorProto::default_instance_->InitAsDefaultInstance();
+  MethodDescriptorProto::default_instance_->InitAsDefaultInstance();
+  FileOptions::default_instance_->InitAsDefaultInstance();
+  MessageOptions::default_instance_->InitAsDefaultInstance();
+  FieldOptions::default_instance_->InitAsDefaultInstance();
+  EnumOptions::default_instance_->InitAsDefaultInstance();
+  EnumValueOptions::default_instance_->InitAsDefaultInstance();
+  ServiceOptions::default_instance_->InitAsDefaultInstance();
+  MethodOptions::default_instance_->InitAsDefaultInstance();
+  UninterpretedOption::default_instance_->InitAsDefaultInstance();
+  UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance();
+  GeneratedCodeInfo::default_instance_->InitAsDefaultInstance();
+  GeneratedCodeInfo_Annotation::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FileDescriptorSet::kFileFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FileDescriptorSet::FileDescriptorSet()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet)
+}
+
+void FileDescriptorSet::InitAsDefaultInstance() {
+}
+
+FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
+}
+
+void FileDescriptorSet::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+FileDescriptorSet::~FileDescriptorSet() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet)
+  SharedDtor();
+}
+
+void FileDescriptorSet::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void FileDescriptorSet::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FileDescriptorSet_descriptor_;
+}
+
+const FileDescriptorSet& FileDescriptorSet::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+FileDescriptorSet* FileDescriptorSet::default_instance_ = NULL;
+
+FileDescriptorSet* FileDescriptorSet::New(::google::protobuf::Arena* arena) const {
+  FileDescriptorSet* n = new FileDescriptorSet;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FileDescriptorSet::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
+  file_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool FileDescriptorSet::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.FileDescriptorProto file = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_file()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_loop_file;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorSet)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorSet)
+  return false;
+#undef DO_
+}
+
+void FileDescriptorSet::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorSet)
+  // repeated .google.protobuf.FileDescriptorProto file = 1;
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->file(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorSet)
+}
+
+::google::protobuf::uint8* FileDescriptorSet::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet)
+  // repeated .google.protobuf.FileDescriptorProto file = 1;
+  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->file(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet)
+  return target;
+}
+
+int FileDescriptorSet::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet)
+  int total_size = 0;
+
+  // repeated .google.protobuf.FileDescriptorProto file = 1;
+  total_size += 1 * this->file_size();
+  for (int i = 0; i < this->file_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->file(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileDescriptorSet* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorSet)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorSet)
+    MergeFrom(*source);
+  }
+}
+
+void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  file_.MergeFrom(from.file_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorSet)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorSet)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FileDescriptorSet::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->file())) return false;
+  return true;
+}
+
+void FileDescriptorSet::Swap(FileDescriptorSet* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
+  file_.UnsafeArenaSwap(&other->file_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileDescriptorSet_descriptor_;
+  metadata.reflection = FileDescriptorSet_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorSet
+
+// repeated .google.protobuf.FileDescriptorProto file = 1;
+int FileDescriptorSet::file_size() const {
+  return file_.size();
+}
+void FileDescriptorSet::clear_file() {
+  file_.Clear();
+}
+const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
+  return file_.Get(index);
+}
+::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
+  return file_.Mutable(index);
+}
+::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
+  return file_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
+  return &file_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+  return file_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FileDescriptorProto::kNameFieldNumber;
+const int FileDescriptorProto::kPackageFieldNumber;
+const int FileDescriptorProto::kDependencyFieldNumber;
+const int FileDescriptorProto::kPublicDependencyFieldNumber;
+const int FileDescriptorProto::kWeakDependencyFieldNumber;
+const int FileDescriptorProto::kMessageTypeFieldNumber;
+const int FileDescriptorProto::kEnumTypeFieldNumber;
+const int FileDescriptorProto::kServiceFieldNumber;
+const int FileDescriptorProto::kExtensionFieldNumber;
+const int FileDescriptorProto::kOptionsFieldNumber;
+const int FileDescriptorProto::kSourceCodeInfoFieldNumber;
+const int FileDescriptorProto::kSyntaxFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FileDescriptorProto::FileDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto)
+}
+
+void FileDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
+  source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance());
+}
+
+FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto)
+}
+
+void FileDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  source_code_info_ = NULL;
+  syntax_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+FileDescriptorProto::~FileDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto)
+  SharedDtor();
+}
+
+void FileDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  syntax_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+    delete source_code_info_;
+  }
+}
+
+void FileDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FileDescriptorProto_descriptor_;
+}
+
+const FileDescriptorProto& FileDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+FileDescriptorProto* FileDescriptorProto::default_instance_ = NULL;
+
+FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  FileDescriptorProto* n = new FileDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FileDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
+  if (_has_bits_[0 / 32] & 3u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_package()) {
+      package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+  if (_has_bits_[8 / 32] & 3584u) {
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+    }
+    if (has_source_code_info()) {
+      if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+    }
+    if (has_syntax()) {
+      syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+  dependency_.Clear();
+  public_dependency_.Clear();
+  weak_dependency_.Clear();
+  message_type_.Clear();
+  enum_type_.Clear();
+  service_.Clear();
+  extension_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool FileDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_package;
+        break;
+      }
+
+      // optional string package = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_package:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_package()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->package().data(), this->package().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileDescriptorProto.package");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_dependency;
+        break;
+      }
+
+      // repeated string dependency = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_dependency:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_dependency()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->dependency(this->dependency_size() - 1).data(),
+            this->dependency(this->dependency_size() - 1).length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileDescriptorProto.dependency");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_dependency;
+        if (input->ExpectTag(34)) goto parse_message_type;
+        break;
+      }
+
+      // repeated .google.protobuf.DescriptorProto message_type = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_message_type:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_message_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_message_type()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_loop_message_type;
+        if (input->ExpectTag(42)) goto parse_loop_enum_type;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+      case 5: {
+        if (tag == 42) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_enum_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_enum_type()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(42)) goto parse_loop_enum_type;
+        if (input->ExpectTag(50)) goto parse_loop_service;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+      case 6: {
+        if (tag == 50) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_service:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_service()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_loop_service;
+        if (input->ExpectTag(58)) goto parse_loop_extension;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+      case 7: {
+        if (tag == 58) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_extension:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_extension()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(58)) goto parse_loop_extension;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(66)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.FileOptions options = 8;
+      case 8: {
+        if (tag == 66) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(74)) goto parse_source_code_info;
+        break;
+      }
+
+      // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+      case 9: {
+        if (tag == 74) {
+         parse_source_code_info:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_code_info()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(80)) goto parse_public_dependency;
+        break;
+      }
+
+      // repeated int32 public_dependency = 10;
+      case 10: {
+        if (tag == 80) {
+         parse_public_dependency:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 80, input, this->mutable_public_dependency())));
+        } else if (tag == 82) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_public_dependency())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(80)) goto parse_public_dependency;
+        if (input->ExpectTag(88)) goto parse_weak_dependency;
+        break;
+      }
+
+      // repeated int32 weak_dependency = 11;
+      case 11: {
+        if (tag == 88) {
+         parse_weak_dependency:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 88, input, this->mutable_weak_dependency())));
+        } else if (tag == 90) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_weak_dependency())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(88)) goto parse_weak_dependency;
+        if (input->ExpectTag(98)) goto parse_syntax;
+        break;
+      }
+
+      // optional string syntax = 12;
+      case 12: {
+        if (tag == 98) {
+         parse_syntax:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_syntax()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->syntax().data(), this->syntax().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileDescriptorProto.syntax");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void FileDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string package = 2;
+  if (has_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->package().data(), this->package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.package");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->package(), output);
+  }
+
+  // repeated string dependency = 3;
+  for (int i = 0; i < this->dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->dependency(i).data(), this->dependency(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.dependency");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->dependency(i), output);
+  }
+
+  // repeated .google.protobuf.DescriptorProto message_type = 4;
+  for (unsigned int i = 0, n = this->message_type_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, this->message_type(i), output);
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      5, this->enum_type(i), output);
+  }
+
+  // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+  for (unsigned int i = 0, n = this->service_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6, this->service(i), output);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      7, this->extension(i), output);
+  }
+
+  // optional .google.protobuf.FileOptions options = 8;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      8, *this->options_, output);
+  }
+
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      9, *this->source_code_info_, output);
+  }
+
+  // repeated int32 public_dependency = 10;
+  for (int i = 0; i < this->public_dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(
+      10, this->public_dependency(i), output);
+  }
+
+  // repeated int32 weak_dependency = 11;
+  for (int i = 0; i < this->weak_dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(
+      11, this->weak_dependency(i), output);
+  }
+
+  // optional string syntax = 12;
+  if (has_syntax()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->syntax().data(), this->syntax().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.syntax");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      12, this->syntax(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorProto)
+}
+
+::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string package = 2;
+  if (has_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->package().data(), this->package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.package");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->package(), target);
+  }
+
+  // repeated string dependency = 3;
+  for (int i = 0; i < this->dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->dependency(i).data(), this->dependency(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.dependency");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(3, this->dependency(i), target);
+  }
+
+  // repeated .google.protobuf.DescriptorProto message_type = 4;
+  for (unsigned int i = 0, n = this->message_type_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->message_type(i), target);
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, this->enum_type(i), target);
+  }
+
+  // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+  for (unsigned int i = 0, n = this->service_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->service(i), target);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        7, this->extension(i), target);
+  }
+
+  // optional .google.protobuf.FileOptions options = 8;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        8, *this->options_, target);
+  }
+
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        9, *this->source_code_info_, target);
+  }
+
+  // repeated int32 public_dependency = 10;
+  for (int i = 0; i < this->public_dependency_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32ToArray(10, this->public_dependency(i), target);
+  }
+
+  // repeated int32 weak_dependency = 11;
+  for (int i = 0; i < this->weak_dependency_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32ToArray(11, this->weak_dependency(i), target);
+  }
+
+  // optional string syntax = 12;
+  if (has_syntax()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->syntax().data(), this->syntax().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.syntax");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        12, this->syntax(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto)
+  return target;
+}
+
+int FileDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 3u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional string package = 2;
+    if (has_package()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->package());
+    }
+
+  }
+  if (_has_bits_[9 / 32] & 3584u) {
+    // optional .google.protobuf.FileOptions options = 8;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+    // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+    if (has_source_code_info()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->source_code_info_);
+    }
+
+    // optional string syntax = 12;
+    if (has_syntax()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->syntax());
+    }
+
+  }
+  // repeated string dependency = 3;
+  total_size += 1 * this->dependency_size();
+  for (int i = 0; i < this->dependency_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->dependency(i));
+  }
+
+  // repeated int32 public_dependency = 10;
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->public_dependency_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->public_dependency(i));
+    }
+    total_size += 1 * this->public_dependency_size() + data_size;
+  }
+
+  // repeated int32 weak_dependency = 11;
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->weak_dependency_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->weak_dependency(i));
+    }
+    total_size += 1 * this->weak_dependency_size() + data_size;
+  }
+
+  // repeated .google.protobuf.DescriptorProto message_type = 4;
+  total_size += 1 * this->message_type_size();
+  for (int i = 0; i < this->message_type_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->message_type(i));
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+  total_size += 1 * this->enum_type_size();
+  for (int i = 0; i < this->enum_type_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->enum_type(i));
+  }
+
+  // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+  total_size += 1 * this->service_size();
+  for (int i = 0; i < this->service_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->service(i));
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+  total_size += 1 * this->extension_size();
+  for (int i = 0; i < this->extension_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->extension(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  dependency_.MergeFrom(from.dependency_);
+  public_dependency_.MergeFrom(from.public_dependency_);
+  weak_dependency_.MergeFrom(from.weak_dependency_);
+  message_type_.MergeFrom(from.message_type_);
+  enum_type_.MergeFrom(from.enum_type_);
+  service_.MergeFrom(from.service_);
+  extension_.MergeFrom(from.extension_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_package()) {
+      set_has_package();
+      package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.package_);
+    }
+  }
+  if (from._has_bits_[9 / 32] & (0xffu << (9 % 32))) {
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options());
+    }
+    if (from.has_source_code_info()) {
+      mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
+    }
+    if (from.has_syntax()) {
+      set_has_syntax();
+      syntax_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.syntax_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FileDescriptorProto::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->message_type())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->service())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false;
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void FileDescriptorProto::Swap(FileDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  package_.Swap(&other->package_);
+  dependency_.UnsafeArenaSwap(&other->dependency_);
+  public_dependency_.UnsafeArenaSwap(&other->public_dependency_);
+  weak_dependency_.UnsafeArenaSwap(&other->weak_dependency_);
+  message_type_.UnsafeArenaSwap(&other->message_type_);
+  enum_type_.UnsafeArenaSwap(&other->enum_type_);
+  service_.UnsafeArenaSwap(&other->service_);
+  extension_.UnsafeArenaSwap(&other->extension_);
+  std::swap(options_, other->options_);
+  std::swap(source_code_info_, other->source_code_info_);
+  syntax_.Swap(&other->syntax_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileDescriptorProto_descriptor_;
+  metadata.reflection = FileDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorProto
+
+// optional string name = 1;
+bool FileDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FileDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void FileDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void FileDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& FileDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+}
+ ::std::string* FileDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+
+// optional string package = 2;
+bool FileDescriptorProto::has_package() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FileDescriptorProto::set_has_package() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void FileDescriptorProto::clear_has_package() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void FileDescriptorProto::clear_package() {
+  package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_package();
+}
+ const ::std::string& FileDescriptorProto::package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
+  return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_package(const ::std::string& value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value, size_t size) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+}
+ ::std::string* FileDescriptorProto::mutable_package() {
+  set_has_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
+  return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
+  clear_has_package();
+  return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_package(::std::string* package) {
+  if (package != NULL) {
+    set_has_package();
+  } else {
+    clear_has_package();
+  }
+  package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+
+// repeated string dependency = 3;
+int FileDescriptorProto::dependency_size() const {
+  return dependency_.size();
+}
+void FileDescriptorProto::clear_dependency() {
+  dependency_.Clear();
+}
+ const ::std::string& FileDescriptorProto::dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Get(index);
+}
+ ::std::string* FileDescriptorProto::mutable_dependency(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Mutable(index);
+}
+ void FileDescriptorProto::set_dependency(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
+  dependency_.Mutable(index)->assign(value);
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value) {
+  dependency_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+  dependency_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ ::std::string* FileDescriptorProto::add_dependency() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Add();
+}
+ void FileDescriptorProto::add_dependency(const ::std::string& value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+  dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency)
+  return &dependency_;
+}
+
+// repeated int32 public_dependency = 10;
+int FileDescriptorProto::public_dependency_size() const {
+  return public_dependency_.size();
+}
+void FileDescriptorProto::clear_public_dependency() {
+  public_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+  public_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+  public_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+int FileDescriptorProto::weak_dependency_size() const {
+  return weak_dependency_.size();
+}
+void FileDescriptorProto::clear_weak_dependency() {
+  weak_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+  weak_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+  weak_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return &weak_dependency_;
+}
+
+// repeated .google.protobuf.DescriptorProto message_type = 4;
+int FileDescriptorProto::message_type_size() const {
+  return message_type_.size();
+}
+void FileDescriptorProto::clear_message_type() {
+  message_type_.Clear();
+}
+const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Get(index);
+}
+::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Mutable(index);
+}
+::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
+  return &message_type_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+int FileDescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+void FileDescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
+  return &enum_type_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_;
+}
+
+// repeated .google.protobuf.ServiceDescriptorProto service = 6;
+int FileDescriptorProto::service_size() const {
+  return service_.size();
+}
+void FileDescriptorProto::clear_service() {
+  service_.Clear();
+}
+const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
+  return service_.Get(index);
+}
+::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
+  return service_.Mutable(index);
+}
+::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
+  return service_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
+  return &service_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+  return service_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 7;
+int FileDescriptorProto::extension_size() const {
+  return extension_.size();
+}
+void FileDescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Get(index);
+}
+::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
+  return &extension_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+  return extension_;
+}
+
+// optional .google.protobuf.FileOptions options = 8;
+bool FileDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+void FileDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000200u;
+}
+void FileDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+void FileDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FileOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::FileOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+bool FileDescriptorProto::has_source_code_info() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+void FileDescriptorProto::set_has_source_code_info() {
+  _has_bits_[0] |= 0x00000400u;
+}
+void FileDescriptorProto::clear_has_source_code_info() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+void FileDescriptorProto::clear_source_code_info() {
+  if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+  clear_has_source_code_info();
+}
+const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  set_has_source_code_info();
+  if (source_code_info_ == NULL) {
+    source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_;
+}
+::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info)
+  clear_has_source_code_info();
+  ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = NULL;
+  return temp;
+}
+void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+  delete source_code_info_;
+  source_code_info_ = source_code_info;
+  if (source_code_info) {
+    set_has_source_code_info();
+  } else {
+    clear_has_source_code_info();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+bool FileDescriptorProto::has_syntax() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+void FileDescriptorProto::set_has_syntax() {
+  _has_bits_[0] |= 0x00000800u;
+}
+void FileDescriptorProto::clear_has_syntax() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+void FileDescriptorProto::clear_syntax() {
+  syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_syntax();
+}
+ const ::std::string& FileDescriptorProto::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_syntax(const ::std::string& value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value, size_t size) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+ ::std::string* FileDescriptorProto::mutable_syntax() {
+  set_has_syntax();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_syntax() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
+  clear_has_syntax();
+  return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+  if (syntax != NULL) {
+    set_has_syntax();
+  } else {
+    clear_has_syntax();
+  }
+  syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int DescriptorProto_ExtensionRange::kStartFieldNumber;
+const int DescriptorProto_ExtensionRange::kEndFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange)
+}
+
+void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
+}
+
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange)
+}
+
+void DescriptorProto_ExtensionRange::SharedCtor() {
+  _cached_size_ = 0;
+  start_ = 0;
+  end_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
+  // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange)
+  SharedDtor();
+}
+
+void DescriptorProto_ExtensionRange::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return DescriptorProto_ExtensionRange_descriptor_;
+}
+
+const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::default_instance_ = NULL;
+
+DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::protobuf::Arena* arena) const {
+  DescriptorProto_ExtensionRange* n = new DescriptorProto_ExtensionRange;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void DescriptorProto_ExtensionRange::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(DescriptorProto_ExtensionRange, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(start_, end_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int32 start = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &start_)));
+          set_has_start();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_end;
+        break;
+      }
+
+      // optional int32 end = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_end:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &end_)));
+          set_has_end();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ExtensionRange)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ExtensionRange)
+  return false;
+#undef DO_
+}
+
+void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ExtensionRange)
+  // optional int32 start = 1;
+  if (has_start()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
+  }
+
+  // optional int32 end = 2;
+  if (has_end()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ExtensionRange)
+}
+
+::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange)
+  // optional int32 start = 1;
+  if (has_start()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
+  }
+
+  // optional int32 end = 2;
+  if (has_end()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange)
+  return target;
+}
+
+int DescriptorProto_ExtensionRange::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 3u) {
+    // optional int32 start = 1;
+    if (has_start()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->start());
+    }
+
+    // optional int32 end = 2;
+    if (has_end()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->end());
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto_ExtensionRange* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ExtensionRange)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ExtensionRange)
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_start()) {
+      set_start(from.start());
+    }
+    if (from.has_end()) {
+      set_end(from.end());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DescriptorProto_ExtensionRange::IsInitialized() const {
+
+  return true;
+}
+
+void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) {
+  std::swap(start_, other->start_);
+  std::swap(end_, other->end_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DescriptorProto_ExtensionRange_descriptor_;
+  metadata.reflection = DescriptorProto_ExtensionRange_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int DescriptorProto_ReservedRange::kStartFieldNumber;
+const int DescriptorProto_ReservedRange::kEndFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::InitAsDefaultInstance() {
+}
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::SharedCtor() {
+  _cached_size_ = 0;
+  start_ = 0;
+  end_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
+  // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange)
+  SharedDtor();
+}
+
+void DescriptorProto_ReservedRange::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void DescriptorProto_ReservedRange::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return DescriptorProto_ReservedRange_descriptor_;
+}
+
+const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::default_instance_ = NULL;
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::protobuf::Arena* arena) const {
+  DescriptorProto_ReservedRange* n = new DescriptorProto_ReservedRange;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void DescriptorProto_ReservedRange::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(DescriptorProto_ReservedRange, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(start_, end_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool DescriptorProto_ReservedRange::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int32 start = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &start_)));
+          set_has_start();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_end;
+        break;
+      }
+
+      // optional int32 end = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_end:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &end_)));
+          set_has_end();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ReservedRange)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ReservedRange)
+  return false;
+#undef DO_
+}
+
+void DescriptorProto_ReservedRange::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ReservedRange)
+  // optional int32 start = 1;
+  if (has_start()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
+  }
+
+  // optional int32 end = 2;
+  if (has_end()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+::google::protobuf::uint8* DescriptorProto_ReservedRange::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
+  // optional int32 start = 1;
+  if (has_start()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
+  }
+
+  // optional int32 end = 2;
+  if (has_end()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange)
+  return target;
+}
+
+int DescriptorProto_ReservedRange::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 3u) {
+    // optional int32 start = 1;
+    if (has_start()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->start());
+    }
+
+    // optional int32 end = 2;
+    if (has_end()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->end());
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto_ReservedRange* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ReservedRange)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ReservedRange)
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_start()) {
+      set_start(from.start());
+    }
+    if (from.has_end()) {
+      set_end(from.end());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ReservedRange)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ReservedRange)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DescriptorProto_ReservedRange::IsInitialized() const {
+
+  return true;
+}
+
+void DescriptorProto_ReservedRange::Swap(DescriptorProto_ReservedRange* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) {
+  std::swap(start_, other->start_);
+  std::swap(end_, other->end_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DescriptorProto_ReservedRange_descriptor_;
+  metadata.reflection = DescriptorProto_ReservedRange_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int DescriptorProto::kNameFieldNumber;
+const int DescriptorProto::kFieldFieldNumber;
+const int DescriptorProto::kExtensionFieldNumber;
+const int DescriptorProto::kNestedTypeFieldNumber;
+const int DescriptorProto::kEnumTypeFieldNumber;
+const int DescriptorProto::kExtensionRangeFieldNumber;
+const int DescriptorProto::kOneofDeclFieldNumber;
+const int DescriptorProto::kOptionsFieldNumber;
+const int DescriptorProto::kReservedRangeFieldNumber;
+const int DescriptorProto::kReservedNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+DescriptorProto::DescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto)
+}
+
+void DescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance());
+}
+
+DescriptorProto::DescriptorProto(const DescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto)
+}
+
+void DescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DescriptorProto::~DescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto)
+  SharedDtor();
+}
+
+void DescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void DescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return DescriptorProto_descriptor_;
+}
+
+const DescriptorProto& DescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+DescriptorProto* DescriptorProto::default_instance_ = NULL;
+
+DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const {
+  DescriptorProto* n = new DescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void DescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
+  if (_has_bits_[0 / 32] & 129u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+    }
+  }
+  field_.Clear();
+  extension_.Clear();
+  nested_type_.Clear();
+  enum_type_.Clear();
+  extension_range_.Clear();
+  oneof_decl_.Clear();
+  reserved_range_.Clear();
+  reserved_name_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool DescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.DescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_field;
+        break;
+      }
+
+      // repeated .google.protobuf.FieldDescriptorProto field = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_field:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_field:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_field()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_field;
+        if (input->ExpectTag(26)) goto parse_loop_nested_type;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.DescriptorProto nested_type = 3;
+      case 3: {
+        if (tag == 26) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_nested_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_nested_type()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_loop_nested_type;
+        if (input->ExpectTag(34)) goto parse_loop_enum_type;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+      case 4: {
+        if (tag == 34) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_enum_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_enum_type()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_loop_enum_type;
+        if (input->ExpectTag(42)) goto parse_loop_extension_range;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+      case 5: {
+        if (tag == 42) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_extension_range:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_extension_range()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(42)) goto parse_loop_extension_range;
+        if (input->ExpectTag(50)) goto parse_loop_extension;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+      case 6: {
+        if (tag == 50) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_extension:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_extension()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_loop_extension;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(58)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.MessageOptions options = 7;
+      case 7: {
+        if (tag == 58) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(66)) goto parse_oneof_decl;
+        break;
+      }
+
+      // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+      case 8: {
+        if (tag == 66) {
+         parse_oneof_decl:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_oneof_decl:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_oneof_decl()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(66)) goto parse_loop_oneof_decl;
+        if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+      case 9: {
+        if (tag == 74) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_reserved_range:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_reserved_range()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(82)) goto parse_reserved_name;
+        break;
+      }
+
+      // repeated string reserved_name = 10;
+      case 10: {
+        if (tag == 82) {
+         parse_reserved_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_reserved_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->reserved_name(this->reserved_name_size() - 1).data(),
+            this->reserved_name(this->reserved_name_size() - 1).length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.DescriptorProto.reserved_name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(82)) goto parse_reserved_name;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto)
+  return false;
+#undef DO_
+}
+
+void DescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.DescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto field = 2;
+  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->field(i), output);
+  }
+
+  // repeated .google.protobuf.DescriptorProto nested_type = 3;
+  for (unsigned int i = 0, n = this->nested_type_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, this->nested_type(i), output);
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, this->enum_type(i), output);
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+  for (unsigned int i = 0, n = this->extension_range_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      5, this->extension_range(i), output);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6, this->extension(i), output);
+  }
+
+  // optional .google.protobuf.MessageOptions options = 7;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      7, *this->options_, output);
+  }
+
+  // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+  for (unsigned int i = 0, n = this->oneof_decl_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      8, this->oneof_decl(i), output);
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+  for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      9, this->reserved_range(i), output);
+  }
+
+  // repeated string reserved_name = 10;
+  for (int i = 0; i < this->reserved_name_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->reserved_name(i).data(), this->reserved_name(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.DescriptorProto.reserved_name");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      10, this->reserved_name(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto)
+}
+
+::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.DescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto field = 2;
+  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->field(i), target);
+  }
+
+  // repeated .google.protobuf.DescriptorProto nested_type = 3;
+  for (unsigned int i = 0, n = this->nested_type_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->nested_type(i), target);
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->enum_type(i), target);
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+  for (unsigned int i = 0, n = this->extension_range_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, this->extension_range(i), target);
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, this->extension(i), target);
+  }
+
+  // optional .google.protobuf.MessageOptions options = 7;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        7, *this->options_, target);
+  }
+
+  // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+  for (unsigned int i = 0, n = this->oneof_decl_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        8, this->oneof_decl(i), target);
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+  for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        9, this->reserved_range(i), target);
+  }
+
+  // repeated string reserved_name = 10;
+  for (int i = 0; i < this->reserved_name_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->reserved_name(i).data(), this->reserved_name(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.DescriptorProto.reserved_name");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(10, this->reserved_name(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto)
+  return target;
+}
+
+int DescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 129u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional .google.protobuf.MessageOptions options = 7;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+  }
+  // repeated .google.protobuf.FieldDescriptorProto field = 2;
+  total_size += 1 * this->field_size();
+  for (int i = 0; i < this->field_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->field(i));
+  }
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+  total_size += 1 * this->extension_size();
+  for (int i = 0; i < this->extension_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->extension(i));
+  }
+
+  // repeated .google.protobuf.DescriptorProto nested_type = 3;
+  total_size += 1 * this->nested_type_size();
+  for (int i = 0; i < this->nested_type_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->nested_type(i));
+  }
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+  total_size += 1 * this->enum_type_size();
+  for (int i = 0; i < this->enum_type_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->enum_type(i));
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+  total_size += 1 * this->extension_range_size();
+  for (int i = 0; i < this->extension_range_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->extension_range(i));
+  }
+
+  // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+  total_size += 1 * this->oneof_decl_size();
+  for (int i = 0; i < this->oneof_decl_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->oneof_decl(i));
+  }
+
+  // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+  total_size += 1 * this->reserved_range_size();
+  for (int i = 0; i < this->reserved_range_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->reserved_range(i));
+  }
+
+  // repeated string reserved_name = 10;
+  total_size += 1 * this->reserved_name_size();
+  for (int i = 0; i < this->reserved_name_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->reserved_name(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto::MergeFrom(const DescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  field_.MergeFrom(from.field_);
+  extension_.MergeFrom(from.extension_);
+  nested_type_.MergeFrom(from.nested_type_);
+  enum_type_.MergeFrom(from.enum_type_);
+  extension_range_.MergeFrom(from.extension_range_);
+  oneof_decl_.MergeFrom(from.oneof_decl_);
+  reserved_range_.MergeFrom(from.reserved_range_);
+  reserved_name_.MergeFrom(from.reserved_name_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto::CopyFrom(const DescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DescriptorProto::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->field())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->nested_type())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false;
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void DescriptorProto::Swap(DescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void DescriptorProto::InternalSwap(DescriptorProto* other) {
+  name_.Swap(&other->name_);
+  field_.UnsafeArenaSwap(&other->field_);
+  extension_.UnsafeArenaSwap(&other->extension_);
+  nested_type_.UnsafeArenaSwap(&other->nested_type_);
+  enum_type_.UnsafeArenaSwap(&other->enum_type_);
+  extension_range_.UnsafeArenaSwap(&other->extension_range_);
+  oneof_decl_.UnsafeArenaSwap(&other->oneof_decl_);
+  std::swap(options_, other->options_);
+  reserved_range_.UnsafeArenaSwap(&other->reserved_range_);
+  reserved_name_.UnsafeArenaSwap(&other->reserved_name_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DescriptorProto_descriptor_;
+  metadata.reflection = DescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DescriptorProto_ExtensionRange
+
+// optional int32 start = 1;
+bool DescriptorProto_ExtensionRange::has_start() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ExtensionRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_start() {
+  start_ = 0;
+  clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
+  return start_;
+}
+ void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
+  set_has_start();
+  start_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
+}
+
+// optional int32 end = 2;
+bool DescriptorProto_ExtensionRange::has_end() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void DescriptorProto_ExtensionRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void DescriptorProto_ExtensionRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void DescriptorProto_ExtensionRange::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
+  return end_;
+}
+ void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+bool DescriptorProto_ReservedRange::has_start() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_start() {
+  start_ = 0;
+  clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+  return start_;
+}
+ void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+  set_has_start();
+  start_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+bool DescriptorProto_ReservedRange::has_end() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+  return end_;
+}
+ void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto
+
+// optional string name = 1;
+bool DescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& DescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+}
+ ::std::string* DescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* DescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+
+// repeated .google.protobuf.FieldDescriptorProto field = 2;
+int DescriptorProto::field_size() const {
+  return field_.size();
+}
+void DescriptorProto::clear_field() {
+  field_.Clear();
+}
+const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
+  return field_.Get(index);
+}
+::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
+  return field_.Mutable(index);
+}
+::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
+  return field_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
+  return &field_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+  return field_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 6;
+int DescriptorProto::extension_size() const {
+  return extension_.size();
+}
+void DescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
+  return extension_.Get(index);
+}
+::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
+  return extension_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
+  return &extension_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+  return extension_;
+}
+
+// repeated .google.protobuf.DescriptorProto nested_type = 3;
+int DescriptorProto::nested_type_size() const {
+  return nested_type_.size();
+}
+void DescriptorProto::clear_nested_type() {
+  nested_type_.Clear();
+}
+const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Get(index);
+}
+::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Mutable(index);
+}
+::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
+  return &nested_type_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+int DescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+void DescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
+  return &enum_type_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_;
+}
+
+// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+int DescriptorProto::extension_range_size() const {
+  return extension_range_.size();
+}
+void DescriptorProto::clear_extension_range() {
+  extension_range_.Clear();
+}
+const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Get(index);
+}
+::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Mutable(index);
+}
+::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
+  return &extension_range_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_;
+}
+
+// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+int DescriptorProto::oneof_decl_size() const {
+  return oneof_decl_.size();
+}
+void DescriptorProto::clear_oneof_decl() {
+  oneof_decl_.Clear();
+}
+const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Get(index);
+}
+::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Mutable(index);
+}
+::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+DescriptorProto::mutable_oneof_decl() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
+  return &oneof_decl_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_;
+}
+
+// optional .google.protobuf.MessageOptions options = 7;
+bool DescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void DescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+void DescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+void DescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MessageOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
+  return options_;
+}
+::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::MessageOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
+}
+
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+int DescriptorProto::reserved_range_size() const {
+  return reserved_range_.size();
+}
+void DescriptorProto::clear_reserved_range() {
+  reserved_range_.Clear();
+}
+const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Get(index);
+}
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Mutable(index);
+}
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+  return &reserved_range_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+int DescriptorProto::reserved_name_size() const {
+  return reserved_name_.size();
+}
+void DescriptorProto::clear_reserved_name() {
+  reserved_name_.Clear();
+}
+ const ::std::string& DescriptorProto::reserved_name(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Get(index);
+}
+ ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Mutable(index);
+}
+ void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+  reserved_name_.Mutable(index)->assign(value);
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value) {
+  reserved_name_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+  reserved_name_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ ::std::string* DescriptorProto::add_reserved_name() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Add();
+}
+ void DescriptorProto::add_reserved_name(const ::std::string& value) {
+  reserved_name_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value) {
+  reserved_name_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+  reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+  return &reserved_name_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldDescriptorProto_Type_descriptor_;
+}
+bool FieldDescriptorProto_Type_IsValid(int value) {
+  switch(value) {
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32;
+const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64;
+const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN;
+const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX;
+const int FieldDescriptorProto::Type_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldDescriptorProto_Label_descriptor_;
+}
+bool FieldDescriptorProto_Label_IsValid(int value) {
+  switch(value) {
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL;
+const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED;
+const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED;
+const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN;
+const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
+const int FieldDescriptorProto::Label_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FieldDescriptorProto::kNameFieldNumber;
+const int FieldDescriptorProto::kNumberFieldNumber;
+const int FieldDescriptorProto::kLabelFieldNumber;
+const int FieldDescriptorProto::kTypeFieldNumber;
+const int FieldDescriptorProto::kTypeNameFieldNumber;
+const int FieldDescriptorProto::kExtendeeFieldNumber;
+const int FieldDescriptorProto::kDefaultValueFieldNumber;
+const int FieldDescriptorProto::kOneofIndexFieldNumber;
+const int FieldDescriptorProto::kJsonNameFieldNumber;
+const int FieldDescriptorProto::kOptionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FieldDescriptorProto::FieldDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto)
+}
+
+void FieldDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance());
+}
+
+FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto)
+}
+
+void FieldDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  number_ = 0;
+  label_ = 1;
+  type_ = 1;
+  type_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  oneof_index_ = 0;
+  json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+FieldDescriptorProto::~FieldDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto)
+  SharedDtor();
+}
+
+void FieldDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  type_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  extendee_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void FieldDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldDescriptorProto_descriptor_;
+}
+
+const FieldDescriptorProto& FieldDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+FieldDescriptorProto* FieldDescriptorProto::default_instance_ = NULL;
+
+FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  FieldDescriptorProto* n = new FieldDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FieldDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
+  if (_has_bits_[0 / 32] & 255u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    number_ = 0;
+    label_ = 1;
+    type_ = 1;
+    if (has_type_name()) {
+      type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_extendee()) {
+      extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_default_value()) {
+      default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    oneof_index_ = 0;
+  }
+  if (_has_bits_[8 / 32] & 768u) {
+    if (has_json_name()) {
+      json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool FieldDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FieldDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_extendee;
+        break;
+      }
+
+      // optional string extendee = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_extendee:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_extendee()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->extendee().data(), this->extendee().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FieldDescriptorProto.extendee");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_number;
+        break;
+      }
+
+      // optional int32 number = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_number:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &number_)));
+          set_has_number();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_label;
+        break;
+      }
+
+      // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_label:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
+            set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
+          } else {
+            mutable_unknown_fields()->AddVarint(4, value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_type;
+        break;
+      }
+
+      // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+      case 5: {
+        if (tag == 40) {
+         parse_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
+            set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
+          } else {
+            mutable_unknown_fields()->AddVarint(5, value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_type_name;
+        break;
+      }
+
+      // optional string type_name = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_type_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_type_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->type_name().data(), this->type_name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FieldDescriptorProto.type_name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(58)) goto parse_default_value;
+        break;
+      }
+
+      // optional string default_value = 7;
+      case 7: {
+        if (tag == 58) {
+         parse_default_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_default_value()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->default_value().data(), this->default_value().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FieldDescriptorProto.default_value");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(66)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.FieldOptions options = 8;
+      case 8: {
+        if (tag == 66) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(72)) goto parse_oneof_index;
+        break;
+      }
+
+      // optional int32 oneof_index = 9;
+      case 9: {
+        if (tag == 72) {
+         parse_oneof_index:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &oneof_index_)));
+          set_has_oneof_index();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(82)) goto parse_json_name;
+        break;
+      }
+
+      // optional string json_name = 10;
+      case 10: {
+        if (tag == 82) {
+         parse_json_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_json_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->json_name().data(), this->json_name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FieldDescriptorProto.json_name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FieldDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FieldDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void FieldDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FieldDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string extendee = 2;
+  if (has_extendee()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->extendee().data(), this->extendee().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.extendee");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->extendee(), output);
+  }
+
+  // optional int32 number = 3;
+  if (has_number()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
+  }
+
+  // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+  if (has_label()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->label(), output);
+  }
+
+  // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+  if (has_type()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      5, this->type(), output);
+  }
+
+  // optional string type_name = 6;
+  if (has_type_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->type_name().data(), this->type_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.type_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      6, this->type_name(), output);
+  }
+
+  // optional string default_value = 7;
+  if (has_default_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.default_value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      7, this->default_value(), output);
+  }
+
+  // optional .google.protobuf.FieldOptions options = 8;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      8, *this->options_, output);
+  }
+
+  // optional int32 oneof_index = 9;
+  if (has_oneof_index()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output);
+  }
+
+  // optional string json_name = 10;
+  if (has_json_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->json_name().data(), this->json_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.json_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      10, this->json_name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FieldDescriptorProto)
+}
+
+::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string extendee = 2;
+  if (has_extendee()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->extendee().data(), this->extendee().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.extendee");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->extendee(), target);
+  }
+
+  // optional int32 number = 3;
+  if (has_number()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
+  }
+
+  // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+  if (has_label()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      4, this->label(), target);
+  }
+
+  // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+  if (has_type()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      5, this->type(), target);
+  }
+
+  // optional string type_name = 6;
+  if (has_type_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->type_name().data(), this->type_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.type_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        6, this->type_name(), target);
+  }
+
+  // optional string default_value = 7;
+  if (has_default_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.default_value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        7, this->default_value(), target);
+  }
+
+  // optional .google.protobuf.FieldOptions options = 8;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        8, *this->options_, target);
+  }
+
+  // optional int32 oneof_index = 9;
+  if (has_oneof_index()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target);
+  }
+
+  // optional string json_name = 10;
+  if (has_json_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->json_name().data(), this->json_name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FieldDescriptorProto.json_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        10, this->json_name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto)
+  return target;
+}
+
+int FieldDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 255u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional int32 number = 3;
+    if (has_number()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->number());
+    }
+
+    // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+    if (has_label()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->label());
+    }
+
+    // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+    if (has_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
+    }
+
+    // optional string type_name = 6;
+    if (has_type_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->type_name());
+    }
+
+    // optional string extendee = 2;
+    if (has_extendee()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->extendee());
+    }
+
+    // optional string default_value = 7;
+    if (has_default_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->default_value());
+    }
+
+    // optional int32 oneof_index = 9;
+    if (has_oneof_index()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->oneof_index());
+    }
+
+  }
+  if (_has_bits_[8 / 32] & 768u) {
+    // optional string json_name = 10;
+    if (has_json_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->json_name());
+    }
+
+    // optional .google.protobuf.FieldOptions options = 8;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_number()) {
+      set_number(from.number());
+    }
+    if (from.has_label()) {
+      set_label(from.label());
+    }
+    if (from.has_type()) {
+      set_type(from.type());
+    }
+    if (from.has_type_name()) {
+      set_has_type_name();
+      type_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_name_);
+    }
+    if (from.has_extendee()) {
+      set_has_extendee();
+      extendee_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.extendee_);
+    }
+    if (from.has_default_value()) {
+      set_has_default_value();
+      default_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.default_value_);
+    }
+    if (from.has_oneof_index()) {
+      set_oneof_index(from.oneof_index());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_json_name()) {
+      set_has_json_name();
+      json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_);
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FieldDescriptorProto::IsInitialized() const {
+
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void FieldDescriptorProto::Swap(FieldDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  std::swap(number_, other->number_);
+  std::swap(label_, other->label_);
+  std::swap(type_, other->type_);
+  type_name_.Swap(&other->type_name_);
+  extendee_.Swap(&other->extendee_);
+  default_value_.Swap(&other->default_value_);
+  std::swap(oneof_index_, other->oneof_index_);
+  json_name_.Swap(&other->json_name_);
+  std::swap(options_, other->options_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FieldDescriptorProto_descriptor_;
+  metadata.reflection = FieldDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldDescriptorProto
+
+// optional string name = 1;
+bool FieldDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FieldDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void FieldDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void FieldDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& FieldDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+}
+ ::std::string* FieldDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+
+// optional int32 number = 3;
+bool FieldDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FieldDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void FieldDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void FieldDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
+  return number_;
+}
+ void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+bool FieldDescriptorProto::has_label() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FieldDescriptorProto::set_has_label() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void FieldDescriptorProto::clear_has_label() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void FieldDescriptorProto::clear_label() {
+  label_ = 1;
+  clear_has_label();
+}
+ ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
+}
+ void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
+  assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+  set_has_label();
+  label_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+bool FieldDescriptorProto::has_type() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FieldDescriptorProto::set_has_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void FieldDescriptorProto::clear_has_type() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void FieldDescriptorProto::clear_type() {
+  type_ = 1;
+  clear_has_type();
+}
+ ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
+}
+ void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
+  assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+  set_has_type();
+  type_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type)
+}
+
+// optional string type_name = 6;
+bool FieldDescriptorProto::has_type_name() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FieldDescriptorProto::set_has_type_name() {
+  _has_bits_[0] |= 0x00000010u;
+}
+void FieldDescriptorProto::clear_has_type_name() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+void FieldDescriptorProto::clear_type_name() {
+  type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_type_name();
+}
+ const ::std::string& FieldDescriptorProto::type_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_type_name(const ::std::string& value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_type_name() {
+  set_has_type_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_type_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
+  clear_has_type_name();
+  return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+  if (type_name != NULL) {
+    set_has_type_name();
+  } else {
+    clear_has_type_name();
+  }
+  type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+
+// optional string extendee = 2;
+bool FieldDescriptorProto::has_extendee() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FieldDescriptorProto::set_has_extendee() {
+  _has_bits_[0] |= 0x00000020u;
+}
+void FieldDescriptorProto::clear_has_extendee() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+void FieldDescriptorProto::clear_extendee() {
+  extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_extendee();
+}
+ const ::std::string& FieldDescriptorProto::extendee() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_extendee(const ::std::string& value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+}
+ ::std::string* FieldDescriptorProto::mutable_extendee() {
+  set_has_extendee();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_extendee() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
+  clear_has_extendee();
+  return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+  if (extendee != NULL) {
+    set_has_extendee();
+  } else {
+    clear_has_extendee();
+  }
+  extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+
+// optional string default_value = 7;
+bool FieldDescriptorProto::has_default_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void FieldDescriptorProto::set_has_default_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+void FieldDescriptorProto::clear_has_default_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+void FieldDescriptorProto::clear_default_value() {
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_default_value();
+}
+ const ::std::string& FieldDescriptorProto::default_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_default_value(const ::std::string& value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+}
+ ::std::string* FieldDescriptorProto::mutable_default_value() {
+  set_has_default_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_default_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
+  clear_has_default_value();
+  return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+  if (default_value != NULL) {
+    set_has_default_value();
+  } else {
+    clear_has_default_value();
+  }
+  default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+
+// optional int32 oneof_index = 9;
+bool FieldDescriptorProto::has_oneof_index() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void FieldDescriptorProto::set_has_oneof_index() {
+  _has_bits_[0] |= 0x00000080u;
+}
+void FieldDescriptorProto::clear_has_oneof_index() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+void FieldDescriptorProto::clear_oneof_index() {
+  oneof_index_ = 0;
+  clear_has_oneof_index();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
+  return oneof_index_;
+}
+ void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) {
+  set_has_oneof_index();
+  oneof_index_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
+}
+
+// optional string json_name = 10;
+bool FieldDescriptorProto::has_json_name() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+void FieldDescriptorProto::set_has_json_name() {
+  _has_bits_[0] |= 0x00000100u;
+}
+void FieldDescriptorProto::clear_has_json_name() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+void FieldDescriptorProto::clear_json_name() {
+  json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_json_name();
+}
+ const ::std::string& FieldDescriptorProto::json_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
+  return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_json_name(const ::std::string& value) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
+}
+ void FieldDescriptorProto::set_json_name(const char* value) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
+}
+ void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_json_name() {
+  set_has_json_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
+  return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_json_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
+  clear_has_json_name();
+  return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
+  if (json_name != NULL) {
+    set_has_json_name();
+  } else {
+    clear_has_json_name();
+  }
+  json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
+}
+
+// optional .google.protobuf.FieldOptions options = 8;
+bool FieldDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+void FieldDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000200u;
+}
+void FieldDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+void FieldDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FieldOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::FieldOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int OneofDescriptorProto::kNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+OneofDescriptorProto::OneofDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto)
+}
+
+void OneofDescriptorProto::InitAsDefaultInstance() {
+}
+
+OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto)
+}
+
+void OneofDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+OneofDescriptorProto::~OneofDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto)
+  SharedDtor();
+}
+
+void OneofDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void OneofDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* OneofDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return OneofDescriptorProto_descriptor_;
+}
+
+const OneofDescriptorProto& OneofDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+OneofDescriptorProto* OneofDescriptorProto::default_instance_ = NULL;
+
+OneofDescriptorProto* OneofDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  OneofDescriptorProto* n = new OneofDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void OneofDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
+  if (has_name()) {
+    name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool OneofDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.OneofDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.OneofDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.OneofDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void OneofDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.OneofDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.OneofDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.OneofDescriptorProto)
+}
+
+::google::protobuf::uint8* OneofDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.OneofDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto)
+  return target;
+}
+
+int OneofDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (has_name()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const OneofDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.OneofDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool OneofDescriptorProto::IsInitialized() const {
+
+  return true;
+}
+
+void OneofDescriptorProto::Swap(OneofDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = OneofDescriptorProto_descriptor_;
+  metadata.reflection = OneofDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// OneofDescriptorProto
+
+// optional string name = 1;
+bool OneofDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void OneofDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void OneofDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void OneofDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& OneofDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+}
+ ::std::string* OneofDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* OneofDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EnumDescriptorProto::kNameFieldNumber;
+const int EnumDescriptorProto::kValueFieldNumber;
+const int EnumDescriptorProto::kOptionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EnumDescriptorProto::EnumDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto)
+}
+
+void EnumDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance());
+}
+
+EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto)
+}
+
+void EnumDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+EnumDescriptorProto::~EnumDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto)
+  SharedDtor();
+}
+
+void EnumDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void EnumDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return EnumDescriptorProto_descriptor_;
+}
+
+const EnumDescriptorProto& EnumDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+EnumDescriptorProto* EnumDescriptorProto::default_instance_ = NULL;
+
+EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  EnumDescriptorProto* n = new EnumDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void EnumDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
+  if (_has_bits_[0 / 32] & 5u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+    }
+  }
+  value_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool EnumDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.EnumDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_value;
+        break;
+      }
+
+      // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_value:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_value;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(26)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.EnumOptions options = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.EnumDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void EnumDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.EnumDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+  for (unsigned int i = 0, n = this->value_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->value(i), output);
+  }
+
+  // optional .google.protobuf.EnumOptions options = 3;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, *this->options_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumDescriptorProto)
+}
+
+::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.EnumDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+  for (unsigned int i = 0, n = this->value_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->value(i), target);
+  }
+
+  // optional .google.protobuf.EnumOptions options = 3;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, *this->options_, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto)
+  return target;
+}
+
+int EnumDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 5u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional .google.protobuf.EnumOptions options = 3;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+  }
+  // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+  total_size += 1 * this->value_size();
+  for (int i = 0; i < this->value_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->value(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  value_.MergeFrom(from.value_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EnumDescriptorProto::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->value())) return false;
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void EnumDescriptorProto::Swap(EnumDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  value_.UnsafeArenaSwap(&other->value_);
+  std::swap(options_, other->options_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumDescriptorProto_descriptor_;
+  metadata.reflection = EnumDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumDescriptorProto
+
+// optional string name = 1;
+bool EnumDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void EnumDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void EnumDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& EnumDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+}
+ ::std::string* EnumDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+
+// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+int EnumDescriptorProto::value_size() const {
+  return value_.size();
+}
+void EnumDescriptorProto::clear_value() {
+  value_.Clear();
+}
+const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
+  return value_.Get(index);
+}
+::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
+  return value_.Mutable(index);
+}
+::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
+  return value_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
+  return &value_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+  return value_;
+}
+
+// optional .google.protobuf.EnumOptions options = 3;
+bool EnumDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void EnumDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void EnumDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void EnumDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::EnumOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EnumValueDescriptorProto::kNameFieldNumber;
+const int EnumValueDescriptorProto::kNumberFieldNumber;
+const int EnumValueDescriptorProto::kOptionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EnumValueDescriptorProto::EnumValueDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto)
+}
+
+void EnumValueDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance());
+}
+
+EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto)
+}
+
+void EnumValueDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  number_ = 0;
+  options_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+EnumValueDescriptorProto::~EnumValueDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto)
+  SharedDtor();
+}
+
+void EnumValueDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void EnumValueDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return EnumValueDescriptorProto_descriptor_;
+}
+
+const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+EnumValueDescriptorProto* EnumValueDescriptorProto::default_instance_ = NULL;
+
+EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  EnumValueDescriptorProto* n = new EnumValueDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void EnumValueDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
+  if (_has_bits_[0 / 32] & 7u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    number_ = 0;
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool EnumValueDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.EnumValueDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_number;
+        break;
+      }
+
+      // optional int32 number = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_number:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &number_)));
+          set_has_number();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.EnumValueOptions options = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void EnumValueDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.EnumValueDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional int32 number = 2;
+  if (has_number()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
+  }
+
+  // optional .google.protobuf.EnumValueOptions options = 3;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, *this->options_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueDescriptorProto)
+}
+
+::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.EnumValueDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional int32 number = 2;
+  if (has_number()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
+  }
+
+  // optional .google.protobuf.EnumValueOptions options = 3;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, *this->options_, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto)
+  return target;
+}
+
+int EnumValueDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 7u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional int32 number = 2;
+    if (has_number()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->number());
+    }
+
+    // optional .google.protobuf.EnumValueOptions options = 3;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValueDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_number()) {
+      set_number(from.number());
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EnumValueDescriptorProto::IsInitialized() const {
+
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  std::swap(number_, other->number_);
+  std::swap(options_, other->options_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumValueDescriptorProto_descriptor_;
+  metadata.reflection = EnumValueDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueDescriptorProto
+
+// optional string name = 1;
+bool EnumValueDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumValueDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void EnumValueDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void EnumValueDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& EnumValueDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+}
+ ::std::string* EnumValueDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValueDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+
+// optional int32 number = 2;
+bool EnumValueDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void EnumValueDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void EnumValueDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void EnumValueDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+ ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
+  return number_;
+}
+ void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
+}
+
+// optional .google.protobuf.EnumValueOptions options = 3;
+bool EnumValueDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void EnumValueDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void EnumValueDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void EnumValueDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumValueOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::EnumValueOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ServiceDescriptorProto::kNameFieldNumber;
+const int ServiceDescriptorProto::kMethodFieldNumber;
+const int ServiceDescriptorProto::kOptionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ServiceDescriptorProto::ServiceDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto)
+}
+
+void ServiceDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance());
+}
+
+ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto)
+}
+
+void ServiceDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+ServiceDescriptorProto::~ServiceDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto)
+  SharedDtor();
+}
+
+void ServiceDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void ServiceDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return ServiceDescriptorProto_descriptor_;
+}
+
+const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+ServiceDescriptorProto* ServiceDescriptorProto::default_instance_ = NULL;
+
+ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  ServiceDescriptorProto* n = new ServiceDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void ServiceDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
+  if (_has_bits_[0 / 32] & 5u) {
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+    }
+  }
+  method_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool ServiceDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.ServiceDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_method;
+        break;
+      }
+
+      // repeated .google.protobuf.MethodDescriptorProto method = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_method:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_method:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_method()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_method;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(26)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.ServiceOptions options = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.ServiceDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void ServiceDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.ServiceDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.MethodDescriptorProto method = 2;
+  for (unsigned int i = 0, n = this->method_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->method(i), output);
+  }
+
+  // optional .google.protobuf.ServiceOptions options = 3;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, *this->options_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceDescriptorProto)
+}
+
+::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.ServiceDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.MethodDescriptorProto method = 2;
+  for (unsigned int i = 0, n = this->method_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->method(i), target);
+  }
+
+  // optional .google.protobuf.ServiceOptions options = 3;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, *this->options_, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto)
+  return target;
+}
+
+int ServiceDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 5u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional .google.protobuf.ServiceOptions options = 3;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+  }
+  // repeated .google.protobuf.MethodDescriptorProto method = 2;
+  total_size += 1 * this->method_size();
+  for (int i = 0; i < this->method_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->method(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ServiceDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  method_.MergeFrom(from.method_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ServiceDescriptorProto::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->method())) return false;
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  method_.UnsafeArenaSwap(&other->method_);
+  std::swap(options_, other->options_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = ServiceDescriptorProto_descriptor_;
+  metadata.reflection = ServiceDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceDescriptorProto
+
+// optional string name = 1;
+bool ServiceDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void ServiceDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void ServiceDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void ServiceDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& ServiceDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+}
+ ::std::string* ServiceDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* ServiceDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+
+// repeated .google.protobuf.MethodDescriptorProto method = 2;
+int ServiceDescriptorProto::method_size() const {
+  return method_.size();
+}
+void ServiceDescriptorProto::clear_method() {
+  method_.Clear();
+}
+const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Get(index);
+}
+::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Mutable(index);
+}
+::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
+  return &method_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+  return method_;
+}
+
+// optional .google.protobuf.ServiceOptions options = 3;
+bool ServiceDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void ServiceDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void ServiceDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void ServiceDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::ServiceOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::ServiceOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MethodDescriptorProto::kNameFieldNumber;
+const int MethodDescriptorProto::kInputTypeFieldNumber;
+const int MethodDescriptorProto::kOutputTypeFieldNumber;
+const int MethodDescriptorProto::kOptionsFieldNumber;
+const int MethodDescriptorProto::kClientStreamingFieldNumber;
+const int MethodDescriptorProto::kServerStreamingFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MethodDescriptorProto::MethodDescriptorProto()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto)
+}
+
+void MethodDescriptorProto::InitAsDefaultInstance() {
+  options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance());
+}
+
+MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto)
+}
+
+void MethodDescriptorProto::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  input_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  output_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  options_ = NULL;
+  client_streaming_ = false;
+  server_streaming_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MethodDescriptorProto::~MethodDescriptorProto() {
+  // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto)
+  SharedDtor();
+}
+
+void MethodDescriptorProto::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  input_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  output_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete options_;
+  }
+}
+
+void MethodDescriptorProto::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return MethodDescriptorProto_descriptor_;
+}
+
+const MethodDescriptorProto& MethodDescriptorProto::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+MethodDescriptorProto* MethodDescriptorProto::default_instance_ = NULL;
+
+MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* arena) const {
+  MethodDescriptorProto* n = new MethodDescriptorProto;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void MethodDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(MethodDescriptorProto, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MethodDescriptorProto*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  if (_has_bits_[0 / 32] & 63u) {
+    ZR_(client_streaming_, server_streaming_);
+    if (has_name()) {
+      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_input_type()) {
+      input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_output_type()) {
+      output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_options()) {
+      if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+    }
+  }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool MethodDescriptorProto::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.MethodDescriptorProto.name");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_input_type;
+        break;
+      }
+
+      // optional string input_type = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_input_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_input_type()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->input_type().data(), this->input_type().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.MethodDescriptorProto.input_type");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_output_type;
+        break;
+      }
+
+      // optional string output_type = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_output_type:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_output_type()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->output_type().data(), this->output_type().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.MethodDescriptorProto.output_type");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_options;
+        break;
+      }
+
+      // optional .google.protobuf.MethodOptions options = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_client_streaming;
+        break;
+      }
+
+      // optional bool client_streaming = 5 [default = false];
+      case 5: {
+        if (tag == 40) {
+         parse_client_streaming:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &client_streaming_)));
+          set_has_client_streaming();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(48)) goto parse_server_streaming;
+        break;
+      }
+
+      // optional bool server_streaming = 6 [default = false];
+      case 6: {
+        if (tag == 48) {
+         parse_server_streaming:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &server_streaming_)));
+          set_has_server_streaming();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.MethodDescriptorProto)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.MethodDescriptorProto)
+  return false;
+#undef DO_
+}
+
+void MethodDescriptorProto::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.MethodDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional string input_type = 2;
+  if (has_input_type()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->input_type().data(), this->input_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.input_type");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->input_type(), output);
+  }
+
+  // optional string output_type = 3;
+  if (has_output_type()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->output_type().data(), this->output_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.output_type");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->output_type(), output);
+  }
+
+  // optional .google.protobuf.MethodOptions options = 4;
+  if (has_options()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, *this->options_, output);
+  }
+
+  // optional bool client_streaming = 5 [default = false];
+  if (has_client_streaming()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->client_streaming(), output);
+  }
+
+  // optional bool server_streaming = 6 [default = false];
+  if (has_server_streaming()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(6, this->server_streaming(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.MethodDescriptorProto)
+}
+
+::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto)
+  // optional string name = 1;
+  if (has_name()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional string input_type = 2;
+  if (has_input_type()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->input_type().data(), this->input_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.input_type");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->input_type(), target);
+  }
+
+  // optional string output_type = 3;
+  if (has_output_type()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->output_type().data(), this->output_type().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.MethodDescriptorProto.output_type");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->output_type(), target);
+  }
+
+  // optional .google.protobuf.MethodOptions options = 4;
+  if (has_options()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, *this->options_, target);
+  }
+
+  // optional bool client_streaming = 5 [default = false];
+  if (has_client_streaming()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->client_streaming(), target);
+  }
+
+  // optional bool server_streaming = 6 [default = false];
+  if (has_server_streaming()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(6, this->server_streaming(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto)
+  return target;
+}
+
+int MethodDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 63u) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+
+    // optional string input_type = 2;
+    if (has_input_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->input_type());
+    }
+
+    // optional string output_type = 3;
+    if (has_output_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->output_type());
+    }
+
+    // optional .google.protobuf.MethodOptions options = 4;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
+    // optional bool client_streaming = 5 [default = false];
+    if (has_client_streaming()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool server_streaming = 6 [default = false];
+    if (has_server_streaming()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MethodDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodDescriptorProto)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodDescriptorProto)
+    MergeFrom(*source);
+  }
+}
+
+void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name()) {
+      set_has_name();
+      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+    }
+    if (from.has_input_type()) {
+      set_has_input_type();
+      input_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.input_type_);
+    }
+    if (from.has_output_type()) {
+      set_has_output_type();
+      output_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.output_type_);
+    }
+    if (from.has_options()) {
+      mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options());
+    }
+    if (from.has_client_streaming()) {
+      set_client_streaming(from.client_streaming());
+    }
+    if (from.has_server_streaming()) {
+      set_server_streaming(from.server_streaming());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodDescriptorProto)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MethodDescriptorProto::IsInitialized() const {
+
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void MethodDescriptorProto::Swap(MethodDescriptorProto* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
+  name_.Swap(&other->name_);
+  input_type_.Swap(&other->input_type_);
+  output_type_.Swap(&other->output_type_);
+  std::swap(options_, other->options_);
+  std::swap(client_streaming_, other->client_streaming_);
+  std::swap(server_streaming_, other->server_streaming_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MethodDescriptorProto_descriptor_;
+  metadata.reflection = MethodDescriptorProto_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodDescriptorProto
+
+// optional string name = 1;
+bool MethodDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MethodDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void MethodDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void MethodDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+ const ::std::string& MethodDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+}
+ ::std::string* MethodDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+
+// optional string input_type = 2;
+bool MethodDescriptorProto::has_input_type() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void MethodDescriptorProto::set_has_input_type() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void MethodDescriptorProto::clear_has_input_type() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void MethodDescriptorProto::clear_input_type() {
+  input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_input_type();
+}
+ const ::std::string& MethodDescriptorProto::input_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_input_type(const ::std::string& value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_input_type() {
+  set_has_input_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_input_type() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
+  clear_has_input_type();
+  return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+  if (input_type != NULL) {
+    set_has_input_type();
+  } else {
+    clear_has_input_type();
+  }
+  input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+
+// optional string output_type = 3;
+bool MethodDescriptorProto::has_output_type() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void MethodDescriptorProto::set_has_output_type() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void MethodDescriptorProto::clear_has_output_type() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void MethodDescriptorProto::clear_output_type() {
+  output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_output_type();
+}
+ const ::std::string& MethodDescriptorProto::output_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_output_type(const ::std::string& value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_output_type() {
+  set_has_output_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_output_type() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
+  clear_has_output_type();
+  return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+  if (output_type != NULL) {
+    set_has_output_type();
+  } else {
+    clear_has_output_type();
+  }
+  output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+
+// optional .google.protobuf.MethodOptions options = 4;
+bool MethodDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void MethodDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void MethodDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void MethodDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MethodOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
+  return options_;
+}
+::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::MethodOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
+
+// optional bool client_streaming = 5 [default = false];
+bool MethodDescriptorProto::has_client_streaming() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void MethodDescriptorProto::set_has_client_streaming() {
+  _has_bits_[0] |= 0x00000010u;
+}
+void MethodDescriptorProto::clear_has_client_streaming() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+void MethodDescriptorProto::clear_client_streaming() {
+  client_streaming_ = false;
+  clear_has_client_streaming();
+}
+ bool MethodDescriptorProto::client_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming)
+  return client_streaming_;
+}
+ void MethodDescriptorProto::set_client_streaming(bool value) {
+  set_has_client_streaming();
+  client_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming)
+}
+
+// optional bool server_streaming = 6 [default = false];
+bool MethodDescriptorProto::has_server_streaming() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void MethodDescriptorProto::set_has_server_streaming() {
+  _has_bits_[0] |= 0x00000020u;
+}
+void MethodDescriptorProto::clear_has_server_streaming() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+void MethodDescriptorProto::clear_server_streaming() {
+  server_streaming_ = false;
+  clear_has_server_streaming();
+}
+ bool MethodDescriptorProto::server_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming)
+  return server_streaming_;
+}
+ void MethodDescriptorProto::set_server_streaming(bool value) {
+  set_has_server_streaming();
+  server_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FileOptions_OptimizeMode_descriptor_;
+}
+bool FileOptions_OptimizeMode_IsValid(int value) {
+  switch(value) {
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const FileOptions_OptimizeMode FileOptions::SPEED;
+const FileOptions_OptimizeMode FileOptions::CODE_SIZE;
+const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME;
+const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN;
+const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
+const int FileOptions::OptimizeMode_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FileOptions::kJavaPackageFieldNumber;
+const int FileOptions::kJavaOuterClassnameFieldNumber;
+const int FileOptions::kJavaMultipleFilesFieldNumber;
+const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber;
+const int FileOptions::kJavaStringCheckUtf8FieldNumber;
+const int FileOptions::kOptimizeForFieldNumber;
+const int FileOptions::kGoPackageFieldNumber;
+const int FileOptions::kCcGenericServicesFieldNumber;
+const int FileOptions::kJavaGenericServicesFieldNumber;
+const int FileOptions::kPyGenericServicesFieldNumber;
+const int FileOptions::kDeprecatedFieldNumber;
+const int FileOptions::kCcEnableArenasFieldNumber;
+const int FileOptions::kObjcClassPrefixFieldNumber;
+const int FileOptions::kCsharpNamespaceFieldNumber;
+const int FileOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FileOptions::FileOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FileOptions)
+}
+
+void FileOptions::InitAsDefaultInstance() {
+}
+
+FileOptions::FileOptions(const FileOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions)
+}
+
+void FileOptions::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  java_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  java_outer_classname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  java_multiple_files_ = false;
+  java_generate_equals_and_hash_ = false;
+  java_string_check_utf8_ = false;
+  optimize_for_ = 1;
+  go_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  cc_generic_services_ = false;
+  java_generic_services_ = false;
+  py_generic_services_ = false;
+  deprecated_ = false;
+  cc_enable_arenas_ = false;
+  objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+FileOptions::~FileOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FileOptions)
+  SharedDtor();
+}
+
+void FileOptions::SharedDtor() {
+  java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void FileOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FileOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FileOptions_descriptor_;
+}
+
+const FileOptions& FileOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+FileOptions* FileOptions::default_instance_ = NULL;
+
+FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const {
+  FileOptions* n = new FileOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FileOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
+  _extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(FileOptions, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FileOptions*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  if (_has_bits_[0 / 32] & 255u) {
+    ZR_(java_multiple_files_, cc_generic_services_);
+    if (has_java_package()) {
+      java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_java_outer_classname()) {
+      java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    optimize_for_ = 1;
+    if (has_go_package()) {
+      go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+  if (_has_bits_[8 / 32] & 16128u) {
+    ZR_(java_generic_services_, cc_enable_arenas_);
+    if (has_objc_class_prefix()) {
+      objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_csharp_namespace()) {
+      csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool FileOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FileOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string java_package = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_java_package()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->java_package().data(), this->java_package().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.java_package");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(66)) goto parse_java_outer_classname;
+        break;
+      }
+
+      // optional string java_outer_classname = 8;
+      case 8: {
+        if (tag == 66) {
+         parse_java_outer_classname:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_java_outer_classname()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->java_outer_classname().data(), this->java_outer_classname().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.java_outer_classname");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(72)) goto parse_optimize_for;
+        break;
+      }
+
+      // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+      case 9: {
+        if (tag == 72) {
+         parse_optimize_for:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
+            set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
+          } else {
+            mutable_unknown_fields()->AddVarint(9, value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(80)) goto parse_java_multiple_files;
+        break;
+      }
+
+      // optional bool java_multiple_files = 10 [default = false];
+      case 10: {
+        if (tag == 80) {
+         parse_java_multiple_files:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_multiple_files_)));
+          set_has_java_multiple_files();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(90)) goto parse_go_package;
+        break;
+      }
+
+      // optional string go_package = 11;
+      case 11: {
+        if (tag == 90) {
+         parse_go_package:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_go_package()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->go_package().data(), this->go_package().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.go_package");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(128)) goto parse_cc_generic_services;
+        break;
+      }
+
+      // optional bool cc_generic_services = 16 [default = false];
+      case 16: {
+        if (tag == 128) {
+         parse_cc_generic_services:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &cc_generic_services_)));
+          set_has_cc_generic_services();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(136)) goto parse_java_generic_services;
+        break;
+      }
+
+      // optional bool java_generic_services = 17 [default = false];
+      case 17: {
+        if (tag == 136) {
+         parse_java_generic_services:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_generic_services_)));
+          set_has_java_generic_services();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(144)) goto parse_py_generic_services;
+        break;
+      }
+
+      // optional bool py_generic_services = 18 [default = false];
+      case 18: {
+        if (tag == 144) {
+         parse_py_generic_services:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &py_generic_services_)));
+          set_has_py_generic_services();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
+        break;
+      }
+
+      // optional bool java_generate_equals_and_hash = 20 [default = false];
+      case 20: {
+        if (tag == 160) {
+         parse_java_generate_equals_and_hash:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_generate_equals_and_hash_)));
+          set_has_java_generate_equals_and_hash();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(184)) goto parse_deprecated;
+        break;
+      }
+
+      // optional bool deprecated = 23 [default = false];
+      case 23: {
+        if (tag == 184) {
+         parse_deprecated:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(216)) goto parse_java_string_check_utf8;
+        break;
+      }
+
+      // optional bool java_string_check_utf8 = 27 [default = false];
+      case 27: {
+        if (tag == 216) {
+         parse_java_string_check_utf8:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_string_check_utf8_)));
+          set_has_java_string_check_utf8();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(248)) goto parse_cc_enable_arenas;
+        break;
+      }
+
+      // optional bool cc_enable_arenas = 31 [default = false];
+      case 31: {
+        if (tag == 248) {
+         parse_cc_enable_arenas:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &cc_enable_arenas_)));
+          set_has_cc_enable_arenas();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(290)) goto parse_objc_class_prefix;
+        break;
+      }
+
+      // optional string objc_class_prefix = 36;
+      case 36: {
+        if (tag == 290) {
+         parse_objc_class_prefix:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_objc_class_prefix()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.objc_class_prefix");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(298)) goto parse_csharp_namespace;
+        break;
+      }
+
+      // optional string csharp_namespace = 37;
+      case 37: {
+        if (tag == 298) {
+         parse_csharp_namespace:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_csharp_namespace()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->csharp_namespace().data(), this->csharp_namespace().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.csharp_namespace");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FileOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FileOptions)
+  return false;
+#undef DO_
+}
+
+void FileOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FileOptions)
+  // optional string java_package = 1;
+  if (has_java_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->java_package().data(), this->java_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.java_package");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->java_package(), output);
+  }
+
+  // optional string java_outer_classname = 8;
+  if (has_java_outer_classname()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.java_outer_classname");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      8, this->java_outer_classname(), output);
+  }
+
+  // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+  if (has_optimize_for()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      9, this->optimize_for(), output);
+  }
+
+  // optional bool java_multiple_files = 10 [default = false];
+  if (has_java_multiple_files()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
+  }
+
+  // optional string go_package = 11;
+  if (has_go_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->go_package().data(), this->go_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.go_package");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      11, this->go_package(), output);
+  }
+
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
+  }
+
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
+  }
+
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
+  }
+
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
+  }
+
+  // optional bool deprecated = 23 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(23, this->deprecated(), output);
+  }
+
+  // optional bool java_string_check_utf8 = 27 [default = false];
+  if (has_java_string_check_utf8()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(27, this->java_string_check_utf8(), output);
+  }
+
+  // optional bool cc_enable_arenas = 31 [default = false];
+  if (has_cc_enable_arenas()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output);
+  }
+
+  // optional string objc_class_prefix = 36;
+  if (has_objc_class_prefix()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.objc_class_prefix");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      36, this->objc_class_prefix(), output);
+  }
+
+  // optional string csharp_namespace = 37;
+  if (has_csharp_namespace()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->csharp_namespace().data(), this->csharp_namespace().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.csharp_namespace");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      37, this->csharp_namespace(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FileOptions)
+}
+
+::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions)
+  // optional string java_package = 1;
+  if (has_java_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->java_package().data(), this->java_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.java_package");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->java_package(), target);
+  }
+
+  // optional string java_outer_classname = 8;
+  if (has_java_outer_classname()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.java_outer_classname");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->java_outer_classname(), target);
+  }
+
+  // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+  if (has_optimize_for()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      9, this->optimize_for(), target);
+  }
+
+  // optional bool java_multiple_files = 10 [default = false];
+  if (has_java_multiple_files()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
+  }
+
+  // optional string go_package = 11;
+  if (has_go_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->go_package().data(), this->go_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.go_package");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        11, this->go_package(), target);
+  }
+
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
+  }
+
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
+  }
+
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
+  }
+
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
+  }
+
+  // optional bool deprecated = 23 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(23, this->deprecated(), target);
+  }
+
+  // optional bool java_string_check_utf8 = 27 [default = false];
+  if (has_java_string_check_utf8()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(27, this->java_string_check_utf8(), target);
+  }
+
+  // optional bool cc_enable_arenas = 31 [default = false];
+  if (has_cc_enable_arenas()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target);
+  }
+
+  // optional string objc_class_prefix = 36;
+  if (has_objc_class_prefix()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.objc_class_prefix");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        36, this->objc_class_prefix(), target);
+  }
+
+  // optional string csharp_namespace = 37;
+  if (has_csharp_namespace()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->csharp_namespace().data(), this->csharp_namespace().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.csharp_namespace");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        37, this->csharp_namespace(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions)
+  return target;
+}
+
+int FileOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 255u) {
+    // optional string java_package = 1;
+    if (has_java_package()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->java_package());
+    }
+
+    // optional string java_outer_classname = 8;
+    if (has_java_outer_classname()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->java_outer_classname());
+    }
+
+    // optional bool java_multiple_files = 10 [default = false];
+    if (has_java_multiple_files()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool java_generate_equals_and_hash = 20 [default = false];
+    if (has_java_generate_equals_and_hash()) {
+      total_size += 2 + 1;
+    }
+
+    // optional bool java_string_check_utf8 = 27 [default = false];
+    if (has_java_string_check_utf8()) {
+      total_size += 2 + 1;
+    }
+
+    // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+    if (has_optimize_for()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
+    }
+
+    // optional string go_package = 11;
+    if (has_go_package()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->go_package());
+    }
+
+    // optional bool cc_generic_services = 16 [default = false];
+    if (has_cc_generic_services()) {
+      total_size += 2 + 1;
+    }
+
+  }
+  if (_has_bits_[8 / 32] & 16128u) {
+    // optional bool java_generic_services = 17 [default = false];
+    if (has_java_generic_services()) {
+      total_size += 2 + 1;
+    }
+
+    // optional bool py_generic_services = 18 [default = false];
+    if (has_py_generic_services()) {
+      total_size += 2 + 1;
+    }
+
+    // optional bool deprecated = 23 [default = false];
+    if (has_deprecated()) {
+      total_size += 2 + 1;
+    }
+
+    // optional bool cc_enable_arenas = 31 [default = false];
+    if (has_cc_enable_arenas()) {
+      total_size += 2 + 1;
+    }
+
+    // optional string objc_class_prefix = 36;
+    if (has_objc_class_prefix()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->objc_class_prefix());
+    }
+
+    // optional string csharp_namespace = 37;
+    if (has_csharp_namespace()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->csharp_namespace());
+    }
+
+  }
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileOptions)
+    MergeFrom(*source);
+  }
+}
+
+void FileOptions::MergeFrom(const FileOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_java_package()) {
+      set_has_java_package();
+      java_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_package_);
+    }
+    if (from.has_java_outer_classname()) {
+      set_has_java_outer_classname();
+      java_outer_classname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_outer_classname_);
+    }
+    if (from.has_java_multiple_files()) {
+      set_java_multiple_files(from.java_multiple_files());
+    }
+    if (from.has_java_generate_equals_and_hash()) {
+      set_java_generate_equals_and_hash(from.java_generate_equals_and_hash());
+    }
+    if (from.has_java_string_check_utf8()) {
+      set_java_string_check_utf8(from.java_string_check_utf8());
+    }
+    if (from.has_optimize_for()) {
+      set_optimize_for(from.optimize_for());
+    }
+    if (from.has_go_package()) {
+      set_has_go_package();
+      go_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.go_package_);
+    }
+    if (from.has_cc_generic_services()) {
+      set_cc_generic_services(from.cc_generic_services());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_java_generic_services()) {
+      set_java_generic_services(from.java_generic_services());
+    }
+    if (from.has_py_generic_services()) {
+      set_py_generic_services(from.py_generic_services());
+    }
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+    if (from.has_cc_enable_arenas()) {
+      set_cc_enable_arenas(from.cc_enable_arenas());
+    }
+    if (from.has_objc_class_prefix()) {
+      set_has_objc_class_prefix();
+      objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_);
+    }
+    if (from.has_csharp_namespace()) {
+      set_has_csharp_namespace();
+      csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_);
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void FileOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileOptions::CopyFrom(const FileOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FileOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void FileOptions::Swap(FileOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FileOptions::InternalSwap(FileOptions* other) {
+  java_package_.Swap(&other->java_package_);
+  java_outer_classname_.Swap(&other->java_outer_classname_);
+  std::swap(java_multiple_files_, other->java_multiple_files_);
+  std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
+  std::swap(java_string_check_utf8_, other->java_string_check_utf8_);
+  std::swap(optimize_for_, other->optimize_for_);
+  go_package_.Swap(&other->go_package_);
+  std::swap(cc_generic_services_, other->cc_generic_services_);
+  std::swap(java_generic_services_, other->java_generic_services_);
+  std::swap(py_generic_services_, other->py_generic_services_);
+  std::swap(deprecated_, other->deprecated_);
+  std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
+  objc_class_prefix_.Swap(&other->objc_class_prefix_);
+  csharp_namespace_.Swap(&other->csharp_namespace_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata FileOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FileOptions_descriptor_;
+  metadata.reflection = FileOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileOptions
+
+// optional string java_package = 1;
+bool FileOptions::has_java_package() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FileOptions::set_has_java_package() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void FileOptions::clear_has_java_package() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void FileOptions::clear_java_package() {
+  java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_package();
+}
+ const ::std::string& FileOptions::java_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
+  return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_package(const ::std::string& value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value, size_t size) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+}
+ ::std::string* FileOptions::mutable_java_package() {
+  set_has_java_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
+  return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
+  clear_has_java_package();
+  return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_package(::std::string* java_package) {
+  if (java_package != NULL) {
+    set_has_java_package();
+  } else {
+    clear_has_java_package();
+  }
+  java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+
+// optional string java_outer_classname = 8;
+bool FileOptions::has_java_outer_classname() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FileOptions::set_has_java_outer_classname() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void FileOptions::clear_has_java_outer_classname() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void FileOptions::clear_java_outer_classname() {
+  java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_outer_classname();
+}
+ const ::std::string& FileOptions::java_outer_classname() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_outer_classname(const ::std::string& value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+}
+ ::std::string* FileOptions::mutable_java_outer_classname() {
+  set_has_java_outer_classname();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_outer_classname() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
+  clear_has_java_outer_classname();
+  return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+  if (java_outer_classname != NULL) {
+    set_has_java_outer_classname();
+  } else {
+    clear_has_java_outer_classname();
+  }
+  java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+
+// optional bool java_multiple_files = 10 [default = false];
+bool FileOptions::has_java_multiple_files() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FileOptions::set_has_java_multiple_files() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void FileOptions::clear_has_java_multiple_files() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void FileOptions::clear_java_multiple_files() {
+  java_multiple_files_ = false;
+  clear_has_java_multiple_files();
+}
+ bool FileOptions::java_multiple_files() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files)
+  return java_multiple_files_;
+}
+ void FileOptions::set_java_multiple_files(bool value) {
+  set_has_java_multiple_files();
+  java_multiple_files_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files)
+}
+
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+bool FileOptions::has_java_generate_equals_and_hash() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FileOptions::set_has_java_generate_equals_and_hash() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void FileOptions::clear_has_java_generate_equals_and_hash() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void FileOptions::clear_java_generate_equals_and_hash() {
+  java_generate_equals_and_hash_ = false;
+  clear_has_java_generate_equals_and_hash();
+}
+ bool FileOptions::java_generate_equals_and_hash() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash)
+  return java_generate_equals_and_hash_;
+}
+ void FileOptions::set_java_generate_equals_and_hash(bool value) {
+  set_has_java_generate_equals_and_hash();
+  java_generate_equals_and_hash_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash)
+}
+
+// optional bool java_string_check_utf8 = 27 [default = false];
+bool FileOptions::has_java_string_check_utf8() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FileOptions::set_has_java_string_check_utf8() {
+  _has_bits_[0] |= 0x00000010u;
+}
+void FileOptions::clear_has_java_string_check_utf8() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+void FileOptions::clear_java_string_check_utf8() {
+  java_string_check_utf8_ = false;
+  clear_has_java_string_check_utf8();
+}
+ bool FileOptions::java_string_check_utf8() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8)
+  return java_string_check_utf8_;
+}
+ void FileOptions::set_java_string_check_utf8(bool value) {
+  set_has_java_string_check_utf8();
+  java_string_check_utf8_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8)
+}
+
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+bool FileOptions::has_optimize_for() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FileOptions::set_has_optimize_for() {
+  _has_bits_[0] |= 0x00000020u;
+}
+void FileOptions::clear_has_optimize_for() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+void FileOptions::clear_optimize_for() {
+  optimize_for_ = 1;
+  clear_has_optimize_for();
+}
+ ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for)
+  return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
+}
+ void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
+  assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+  set_has_optimize_for();
+  optimize_for_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for)
+}
+
+// optional string go_package = 11;
+bool FileOptions::has_go_package() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void FileOptions::set_has_go_package() {
+  _has_bits_[0] |= 0x00000040u;
+}
+void FileOptions::clear_has_go_package() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+void FileOptions::clear_go_package() {
+  go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_go_package();
+}
+ const ::std::string& FileOptions::go_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
+  return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_go_package(const ::std::string& value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value, size_t size) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+}
+ ::std::string* FileOptions::mutable_go_package() {
+  set_has_go_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
+  return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_go_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
+  clear_has_go_package();
+  return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_go_package(::std::string* go_package) {
+  if (go_package != NULL) {
+    set_has_go_package();
+  } else {
+    clear_has_go_package();
+  }
+  go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+bool FileOptions::has_cc_generic_services() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+void FileOptions::clear_cc_generic_services() {
+  cc_generic_services_ = false;
+  clear_has_cc_generic_services();
+}
+ bool FileOptions::cc_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services)
+  return cc_generic_services_;
+}
+ void FileOptions::set_cc_generic_services(bool value) {
+  set_has_cc_generic_services();
+  cc_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services)
+}
+
+// optional bool java_generic_services = 17 [default = false];
+bool FileOptions::has_java_generic_services() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+void FileOptions::set_has_java_generic_services() {
+  _has_bits_[0] |= 0x00000100u;
+}
+void FileOptions::clear_has_java_generic_services() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+void FileOptions::clear_java_generic_services() {
+  java_generic_services_ = false;
+  clear_has_java_generic_services();
+}
+ bool FileOptions::java_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services)
+  return java_generic_services_;
+}
+ void FileOptions::set_java_generic_services(bool value) {
+  set_has_java_generic_services();
+  java_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services)
+}
+
+// optional bool py_generic_services = 18 [default = false];
+bool FileOptions::has_py_generic_services() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+void FileOptions::set_has_py_generic_services() {
+  _has_bits_[0] |= 0x00000200u;
+}
+void FileOptions::clear_has_py_generic_services() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+void FileOptions::clear_py_generic_services() {
+  py_generic_services_ = false;
+  clear_has_py_generic_services();
+}
+ bool FileOptions::py_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services)
+  return py_generic_services_;
+}
+ void FileOptions::set_py_generic_services(bool value) {
+  set_has_py_generic_services();
+  py_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
+}
+
+// optional bool deprecated = 23 [default = false];
+bool FileOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+void FileOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000400u;
+}
+void FileOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+void FileOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool FileOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated)
+  return deprecated_;
+}
+ void FileOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated)
+}
+
+// optional bool cc_enable_arenas = 31 [default = false];
+bool FileOptions::has_cc_enable_arenas() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+void FileOptions::set_has_cc_enable_arenas() {
+  _has_bits_[0] |= 0x00000800u;
+}
+void FileOptions::clear_has_cc_enable_arenas() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+void FileOptions::clear_cc_enable_arenas() {
+  cc_enable_arenas_ = false;
+  clear_has_cc_enable_arenas();
+}
+ bool FileOptions::cc_enable_arenas() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas)
+  return cc_enable_arenas_;
+}
+ void FileOptions::set_cc_enable_arenas(bool value) {
+  set_has_cc_enable_arenas();
+  cc_enable_arenas_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
+}
+
+// optional string objc_class_prefix = 36;
+bool FileOptions::has_objc_class_prefix() const {
+  return (_has_bits_[0] & 0x00001000u) != 0;
+}
+void FileOptions::set_has_objc_class_prefix() {
+  _has_bits_[0] |= 0x00001000u;
+}
+void FileOptions::clear_has_objc_class_prefix() {
+  _has_bits_[0] &= ~0x00001000u;
+}
+void FileOptions::clear_objc_class_prefix() {
+  objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_objc_class_prefix();
+}
+ const ::std::string& FileOptions::objc_class_prefix() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+ ::std::string* FileOptions::mutable_objc_class_prefix() {
+  set_has_objc_class_prefix();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_objc_class_prefix() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
+  clear_has_objc_class_prefix();
+  return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+  if (objc_class_prefix != NULL) {
+    set_has_objc_class_prefix();
+  } else {
+    clear_has_objc_class_prefix();
+  }
+  objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// optional string csharp_namespace = 37;
+bool FileOptions::has_csharp_namespace() const {
+  return (_has_bits_[0] & 0x00002000u) != 0;
+}
+void FileOptions::set_has_csharp_namespace() {
+  _has_bits_[0] |= 0x00002000u;
+}
+void FileOptions::clear_has_csharp_namespace() {
+  _has_bits_[0] &= ~0x00002000u;
+}
+void FileOptions::clear_csharp_namespace() {
+  csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_csharp_namespace();
+}
+ const ::std::string& FileOptions::csharp_namespace() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
+  return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_csharp_namespace(const ::std::string& value) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
+}
+ void FileOptions::set_csharp_namespace(const char* value) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
+}
+ void FileOptions::set_csharp_namespace(const char* value, size_t size) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
+}
+ ::std::string* FileOptions::mutable_csharp_namespace() {
+  set_has_csharp_namespace();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace)
+  return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_csharp_namespace() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
+  clear_has_csharp_namespace();
+  return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) {
+  if (csharp_namespace != NULL) {
+    set_has_csharp_namespace();
+  } else {
+    clear_has_csharp_namespace();
+  }
+  csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int FileOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void FileOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MessageOptions::kMessageSetWireFormatFieldNumber;
+const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber;
+const int MessageOptions::kDeprecatedFieldNumber;
+const int MessageOptions::kMapEntryFieldNumber;
+const int MessageOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MessageOptions::MessageOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.MessageOptions)
+}
+
+void MessageOptions::InitAsDefaultInstance() {
+}
+
+MessageOptions::MessageOptions(const MessageOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions)
+}
+
+void MessageOptions::SharedCtor() {
+  _cached_size_ = 0;
+  message_set_wire_format_ = false;
+  no_standard_descriptor_accessor_ = false;
+  deprecated_ = false;
+  map_entry_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MessageOptions::~MessageOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions)
+  SharedDtor();
+}
+
+void MessageOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void MessageOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* MessageOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return MessageOptions_descriptor_;
+}
+
+const MessageOptions& MessageOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+MessageOptions* MessageOptions::default_instance_ = NULL;
+
+MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const {
+  MessageOptions* n = new MessageOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void MessageOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
+  _extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(MessageOptions, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MessageOptions*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(message_set_wire_format_, map_entry_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool MessageOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool message_set_wire_format = 1 [default = false];
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &message_set_wire_format_)));
+          set_has_message_set_wire_format();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
+        break;
+      }
+
+      // optional bool no_standard_descriptor_accessor = 2 [default = false];
+      case 2: {
+        if (tag == 16) {
+         parse_no_standard_descriptor_accessor:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &no_standard_descriptor_accessor_)));
+          set_has_no_standard_descriptor_accessor();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_deprecated;
+        break;
+      }
+
+      // optional bool deprecated = 3 [default = false];
+      case 3: {
+        if (tag == 24) {
+         parse_deprecated:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(56)) goto parse_map_entry;
+        break;
+      }
+
+      // optional bool map_entry = 7;
+      case 7: {
+        if (tag == 56) {
+         parse_map_entry:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &map_entry_)));
+          set_has_map_entry();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.MessageOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.MessageOptions)
+  return false;
+#undef DO_
+}
+
+void MessageOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.MessageOptions)
+  // optional bool message_set_wire_format = 1 [default = false];
+  if (has_message_set_wire_format()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
+  }
+
+  // optional bool no_standard_descriptor_accessor = 2 [default = false];
+  if (has_no_standard_descriptor_accessor()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
+  }
+
+  // optional bool map_entry = 7;
+  if (has_map_entry()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(7, this->map_entry(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.MessageOptions)
+}
+
+::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions)
+  // optional bool message_set_wire_format = 1 [default = false];
+  if (has_message_set_wire_format()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
+  }
+
+  // optional bool no_standard_descriptor_accessor = 2 [default = false];
+  if (has_no_standard_descriptor_accessor()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
+  }
+
+  // optional bool map_entry = 7;
+  if (has_map_entry()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(7, this->map_entry(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions)
+  return target;
+}
+
+int MessageOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 15u) {
+    // optional bool message_set_wire_format = 1 [default = false];
+    if (has_message_set_wire_format()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool no_standard_descriptor_accessor = 2 [default = false];
+    if (has_no_standard_descriptor_accessor()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool deprecated = 3 [default = false];
+    if (has_deprecated()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool map_entry = 7;
+    if (has_map_entry()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MessageOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MessageOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MessageOptions)
+    MergeFrom(*source);
+  }
+}
+
+void MessageOptions::MergeFrom(const MessageOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_message_set_wire_format()) {
+      set_message_set_wire_format(from.message_set_wire_format());
+    }
+    if (from.has_no_standard_descriptor_accessor()) {
+      set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor());
+    }
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+    if (from.has_map_entry()) {
+      set_map_entry(from.map_entry());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MessageOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MessageOptions::CopyFrom(const MessageOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MessageOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MessageOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void MessageOptions::Swap(MessageOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MessageOptions::InternalSwap(MessageOptions* other) {
+  std::swap(message_set_wire_format_, other->message_set_wire_format_);
+  std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_);
+  std::swap(deprecated_, other->deprecated_);
+  std::swap(map_entry_, other->map_entry_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata MessageOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MessageOptions_descriptor_;
+  metadata.reflection = MessageOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MessageOptions
+
+// optional bool message_set_wire_format = 1 [default = false];
+bool MessageOptions::has_message_set_wire_format() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MessageOptions::set_has_message_set_wire_format() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void MessageOptions::clear_has_message_set_wire_format() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void MessageOptions::clear_message_set_wire_format() {
+  message_set_wire_format_ = false;
+  clear_has_message_set_wire_format();
+}
+ bool MessageOptions::message_set_wire_format() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format)
+  return message_set_wire_format_;
+}
+ void MessageOptions::set_message_set_wire_format(bool value) {
+  set_has_message_set_wire_format();
+  message_set_wire_format_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format)
+}
+
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+bool MessageOptions::has_no_standard_descriptor_accessor() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void MessageOptions::set_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void MessageOptions::clear_no_standard_descriptor_accessor() {
+  no_standard_descriptor_accessor_ = false;
+  clear_has_no_standard_descriptor_accessor();
+}
+ bool MessageOptions::no_standard_descriptor_accessor() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+  return no_standard_descriptor_accessor_;
+}
+ void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+  set_has_no_standard_descriptor_accessor();
+  no_standard_descriptor_accessor_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool MessageOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void MessageOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void MessageOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void MessageOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool MessageOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated)
+  return deprecated_;
+}
+ void MessageOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
+}
+
+// optional bool map_entry = 7;
+bool MessageOptions::has_map_entry() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void MessageOptions::set_has_map_entry() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void MessageOptions::clear_has_map_entry() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void MessageOptions::clear_map_entry() {
+  map_entry_ = false;
+  clear_has_map_entry();
+}
+ bool MessageOptions::map_entry() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+  return map_entry_;
+}
+ void MessageOptions::set_map_entry(bool value) {
+  set_has_map_entry();
+  map_entry_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int MessageOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void MessageOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldOptions_CType_descriptor_;
+}
+bool FieldOptions_CType_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const FieldOptions_CType FieldOptions::STRING;
+const FieldOptions_CType FieldOptions::CORD;
+const FieldOptions_CType FieldOptions::STRING_PIECE;
+const FieldOptions_CType FieldOptions::CType_MIN;
+const FieldOptions_CType FieldOptions::CType_MAX;
+const int FieldOptions::CType_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldOptions_JSType_descriptor_;
+}
+bool FieldOptions_JSType_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const FieldOptions_JSType FieldOptions::JS_NORMAL;
+const FieldOptions_JSType FieldOptions::JS_STRING;
+const FieldOptions_JSType FieldOptions::JS_NUMBER;
+const FieldOptions_JSType FieldOptions::JSType_MIN;
+const FieldOptions_JSType FieldOptions::JSType_MAX;
+const int FieldOptions::JSType_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FieldOptions::kCtypeFieldNumber;
+const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kJstypeFieldNumber;
+const int FieldOptions::kLazyFieldNumber;
+const int FieldOptions::kDeprecatedFieldNumber;
+const int FieldOptions::kWeakFieldNumber;
+const int FieldOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FieldOptions::FieldOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions)
+}
+
+void FieldOptions::InitAsDefaultInstance() {
+}
+
+FieldOptions::FieldOptions(const FieldOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions)
+}
+
+void FieldOptions::SharedCtor() {
+  _cached_size_ = 0;
+  ctype_ = 0;
+  packed_ = false;
+  jstype_ = 0;
+  lazy_ = false;
+  deprecated_ = false;
+  weak_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+FieldOptions::~FieldOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions)
+  SharedDtor();
+}
+
+void FieldOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void FieldOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FieldOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldOptions_descriptor_;
+}
+
+const FieldOptions& FieldOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+FieldOptions* FieldOptions::default_instance_ = NULL;
+
+FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const {
+  FieldOptions* n = new FieldOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FieldOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
+  _extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(FieldOptions, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FieldOptions*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  if (_has_bits_[0 / 32] & 63u) {
+    ZR_(ctype_, jstype_);
+    ZR_(packed_, weak_);
+  }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool FieldOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+      case 1: {
+        if (tag == 8) {
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
+            set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
+          } else {
+            mutable_unknown_fields()->AddVarint(1, value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_packed;
+        break;
+      }
+
+      // optional bool packed = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_packed:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &packed_)));
+          set_has_packed();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_deprecated;
+        break;
+      }
+
+      // optional bool deprecated = 3 [default = false];
+      case 3: {
+        if (tag == 24) {
+         parse_deprecated:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_lazy;
+        break;
+      }
+
+      // optional bool lazy = 5 [default = false];
+      case 5: {
+        if (tag == 40) {
+         parse_lazy:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &lazy_)));
+          set_has_lazy();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(48)) goto parse_jstype;
+        break;
+      }
+
+      // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+      case 6: {
+        if (tag == 48) {
+         parse_jstype:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::google::protobuf::FieldOptions_JSType_IsValid(value)) {
+            set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value));
+          } else {
+            mutable_unknown_fields()->AddVarint(6, value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(80)) goto parse_weak;
+        break;
+      }
+
+      // optional bool weak = 10 [default = false];
+      case 10: {
+        if (tag == 80) {
+         parse_weak:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &weak_)));
+          set_has_weak();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FieldOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FieldOptions)
+  return false;
+#undef DO_
+}
+
+void FieldOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FieldOptions)
+  // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+  if (has_ctype()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->ctype(), output);
+  }
+
+  // optional bool packed = 2;
+  if (has_packed()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
+  }
+
+  // optional bool lazy = 5 [default = false];
+  if (has_lazy()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
+  }
+
+  // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+  if (has_jstype()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      6, this->jstype(), output);
+  }
+
+  // optional bool weak = 10 [default = false];
+  if (has_weak()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FieldOptions)
+}
+
+::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions)
+  // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+  if (has_ctype()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->ctype(), target);
+  }
+
+  // optional bool packed = 2;
+  if (has_packed()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
+  }
+
+  // optional bool lazy = 5 [default = false];
+  if (has_lazy()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
+  }
+
+  // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+  if (has_jstype()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      6, this->jstype(), target);
+  }
+
+  // optional bool weak = 10 [default = false];
+  if (has_weak()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions)
+  return target;
+}
+
+int FieldOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 63u) {
+    // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+    if (has_ctype()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
+    }
+
+    // optional bool packed = 2;
+    if (has_packed()) {
+      total_size += 1 + 1;
+    }
+
+    // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+    if (has_jstype()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->jstype());
+    }
+
+    // optional bool lazy = 5 [default = false];
+    if (has_lazy()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool deprecated = 3 [default = false];
+    if (has_deprecated()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool weak = 10 [default = false];
+    if (has_weak()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldOptions)
+    MergeFrom(*source);
+  }
+}
+
+void FieldOptions::MergeFrom(const FieldOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_ctype()) {
+      set_ctype(from.ctype());
+    }
+    if (from.has_packed()) {
+      set_packed(from.packed());
+    }
+    if (from.has_jstype()) {
+      set_jstype(from.jstype());
+    }
+    if (from.has_lazy()) {
+      set_lazy(from.lazy());
+    }
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+    if (from.has_weak()) {
+      set_weak(from.weak());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldOptions::CopyFrom(const FieldOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FieldOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void FieldOptions::Swap(FieldOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FieldOptions::InternalSwap(FieldOptions* other) {
+  std::swap(ctype_, other->ctype_);
+  std::swap(packed_, other->packed_);
+  std::swap(jstype_, other->jstype_);
+  std::swap(lazy_, other->lazy_);
+  std::swap(deprecated_, other->deprecated_);
+  std::swap(weak_, other->weak_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata FieldOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FieldOptions_descriptor_;
+  metadata.reflection = FieldOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldOptions
+
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+bool FieldOptions::has_ctype() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FieldOptions::set_has_ctype() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void FieldOptions::clear_has_ctype() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void FieldOptions::clear_ctype() {
+  ctype_ = 0;
+  clear_has_ctype();
+}
+ ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype)
+  return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
+}
+ void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
+  assert(::google::protobuf::FieldOptions_CType_IsValid(value));
+  set_has_ctype();
+  ctype_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype)
+}
+
+// optional bool packed = 2;
+bool FieldOptions::has_packed() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FieldOptions::set_has_packed() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void FieldOptions::clear_has_packed() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void FieldOptions::clear_packed() {
+  packed_ = false;
+  clear_has_packed();
+}
+ bool FieldOptions::packed() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed)
+  return packed_;
+}
+ void FieldOptions::set_packed(bool value) {
+  set_has_packed();
+  packed_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
+}
+
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+bool FieldOptions::has_jstype() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FieldOptions::set_has_jstype() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void FieldOptions::clear_has_jstype() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void FieldOptions::clear_jstype() {
+  jstype_ = 0;
+  clear_has_jstype();
+}
+ ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+  return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+ void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+  assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+  set_has_jstype();
+  jstype_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
+// optional bool lazy = 5 [default = false];
+bool FieldOptions::has_lazy() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FieldOptions::set_has_lazy() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void FieldOptions::clear_has_lazy() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void FieldOptions::clear_lazy() {
+  lazy_ = false;
+  clear_has_lazy();
+}
+ bool FieldOptions::lazy() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy)
+  return lazy_;
+}
+ void FieldOptions::set_lazy(bool value) {
+  set_has_lazy();
+  lazy_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool FieldOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000010u;
+}
+void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+void FieldOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool FieldOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated)
+  return deprecated_;
+}
+ void FieldOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
+}
+
+// optional bool weak = 10 [default = false];
+bool FieldOptions::has_weak() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FieldOptions::set_has_weak() {
+  _has_bits_[0] |= 0x00000020u;
+}
+void FieldOptions::clear_has_weak() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+void FieldOptions::clear_weak() {
+  weak_ = false;
+  clear_has_weak();
+}
+ bool FieldOptions::weak() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
+  return weak_;
+}
+ void FieldOptions::set_weak(bool value) {
+  set_has_weak();
+  weak_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int FieldOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void FieldOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EnumOptions::kAllowAliasFieldNumber;
+const int EnumOptions::kDeprecatedFieldNumber;
+const int EnumOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EnumOptions::EnumOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.EnumOptions)
+}
+
+void EnumOptions::InitAsDefaultInstance() {
+}
+
+EnumOptions::EnumOptions(const EnumOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions)
+}
+
+void EnumOptions::SharedCtor() {
+  _cached_size_ = 0;
+  allow_alias_ = false;
+  deprecated_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+EnumOptions::~EnumOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions)
+  SharedDtor();
+}
+
+void EnumOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void EnumOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return EnumOptions_descriptor_;
+}
+
+const EnumOptions& EnumOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+EnumOptions* EnumOptions::default_instance_ = NULL;
+
+EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const {
+  EnumOptions* n = new EnumOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void EnumOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
+  _extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(EnumOptions, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<EnumOptions*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(allow_alias_, deprecated_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool EnumOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool allow_alias = 2;
+      case 2: {
+        if (tag == 16) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &allow_alias_)));
+          set_has_allow_alias();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_deprecated;
+        break;
+      }
+
+      // optional bool deprecated = 3 [default = false];
+      case 3: {
+        if (tag == 24) {
+         parse_deprecated:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.EnumOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumOptions)
+  return false;
+#undef DO_
+}
+
+void EnumOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumOptions)
+  // optional bool allow_alias = 2;
+  if (has_allow_alias()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumOptions)
+}
+
+::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions)
+  // optional bool allow_alias = 2;
+  if (has_allow_alias()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target);
+  }
+
+  // optional bool deprecated = 3 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions)
+  return target;
+}
+
+int EnumOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions)
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & 3u) {
+    // optional bool allow_alias = 2;
+    if (has_allow_alias()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bool deprecated = 3 [default = false];
+    if (has_deprecated()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumOptions)
+    MergeFrom(*source);
+  }
+}
+
+void EnumOptions::MergeFrom(const EnumOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_allow_alias()) {
+      set_allow_alias(from.allow_alias());
+    }
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumOptions::CopyFrom(const EnumOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EnumOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void EnumOptions::Swap(EnumOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EnumOptions::InternalSwap(EnumOptions* other) {
+  std::swap(allow_alias_, other->allow_alias_);
+  std::swap(deprecated_, other->deprecated_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata EnumOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumOptions_descriptor_;
+  metadata.reflection = EnumOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumOptions
+
+// optional bool allow_alias = 2;
+bool EnumOptions::has_allow_alias() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumOptions::set_has_allow_alias() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void EnumOptions::clear_has_allow_alias() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void EnumOptions::clear_allow_alias() {
+  allow_alias_ = false;
+  clear_has_allow_alias();
+}
+ bool EnumOptions::allow_alias() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias)
+  return allow_alias_;
+}
+ void EnumOptions::set_allow_alias(bool value) {
+  set_has_allow_alias();
+  allow_alias_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool EnumOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void EnumOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void EnumOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void EnumOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool EnumOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated)
+  return deprecated_;
+}
+ void EnumOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int EnumOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void EnumOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EnumValueOptions::kDeprecatedFieldNumber;
+const int EnumValueOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EnumValueOptions::EnumValueOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions)
+}
+
+void EnumValueOptions::InitAsDefaultInstance() {
+}
+
+EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions)
+}
+
+void EnumValueOptions::SharedCtor() {
+  _cached_size_ = 0;
+  deprecated_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+EnumValueOptions::~EnumValueOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions)
+  SharedDtor();
+}
+
+void EnumValueOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void EnumValueOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return EnumValueOptions_descriptor_;
+}
+
+const EnumValueOptions& EnumValueOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+EnumValueOptions* EnumValueOptions::default_instance_ = NULL;
+
+EnumValueOptions* EnumValueOptions::New(::google::protobuf::Arena* arena) const {
+  EnumValueOptions* n = new EnumValueOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void EnumValueOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
+  _extensions_.Clear();
+  deprecated_ = false;
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool EnumValueOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool deprecated = 1 [default = false];
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueOptions)
+  return false;
+#undef DO_
+}
+
+void EnumValueOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueOptions)
+  // optional bool deprecated = 1 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->deprecated(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueOptions)
+}
+
+::google::protobuf::uint8* EnumValueOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions)
+  // optional bool deprecated = 1 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->deprecated(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions)
+  return target;
+}
+
+int EnumValueOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions)
+  int total_size = 0;
+
+  // optional bool deprecated = 1 [default = false];
+  if (has_deprecated()) {
+    total_size += 1 + 1;
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValueOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueOptions)
+    MergeFrom(*source);
+  }
+}
+
+void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValueOptions::CopyFrom(const EnumValueOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EnumValueOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void EnumValueOptions::Swap(EnumValueOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
+  std::swap(deprecated_, other->deprecated_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata EnumValueOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumValueOptions_descriptor_;
+  metadata.reflection = EnumValueOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueOptions
+
+// optional bool deprecated = 1 [default = false];
+bool EnumValueOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumValueOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void EnumValueOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void EnumValueOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool EnumValueOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated)
+  return deprecated_;
+}
+ void EnumValueOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int EnumValueOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void EnumValueOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ServiceOptions::kDeprecatedFieldNumber;
+const int ServiceOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ServiceOptions::ServiceOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions)
+}
+
+void ServiceOptions::InitAsDefaultInstance() {
+}
+
+ServiceOptions::ServiceOptions(const ServiceOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions)
+}
+
+void ServiceOptions::SharedCtor() {
+  _cached_size_ = 0;
+  deprecated_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+ServiceOptions::~ServiceOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions)
+  SharedDtor();
+}
+
+void ServiceOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void ServiceOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* ServiceOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return ServiceOptions_descriptor_;
+}
+
+const ServiceOptions& ServiceOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+ServiceOptions* ServiceOptions::default_instance_ = NULL;
+
+ServiceOptions* ServiceOptions::New(::google::protobuf::Arena* arena) const {
+  ServiceOptions* n = new ServiceOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void ServiceOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
+  _extensions_.Clear();
+  deprecated_ = false;
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool ServiceOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool deprecated = 33 [default = false];
+      case 33: {
+        if (tag == 264) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.ServiceOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceOptions)
+  return false;
+#undef DO_
+}
+
+void ServiceOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceOptions)
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceOptions)
+}
+
+::google::protobuf::uint8* ServiceOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions)
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions)
+  return target;
+}
+
+int ServiceOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions)
+  int total_size = 0;
+
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    total_size += 2 + 1;
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ServiceOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceOptions)
+    MergeFrom(*source);
+  }
+}
+
+void ServiceOptions::MergeFrom(const ServiceOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ServiceOptions::CopyFrom(const ServiceOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ServiceOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void ServiceOptions::Swap(ServiceOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ServiceOptions::InternalSwap(ServiceOptions* other) {
+  std::swap(deprecated_, other->deprecated_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata ServiceOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = ServiceOptions_descriptor_;
+  metadata.reflection = ServiceOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceOptions
+
+// optional bool deprecated = 33 [default = false];
+bool ServiceOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void ServiceOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void ServiceOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void ServiceOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool ServiceOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated)
+  return deprecated_;
+}
+ void ServiceOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int ServiceOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void ServiceOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MethodOptions::kDeprecatedFieldNumber;
+const int MethodOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MethodOptions::MethodOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.MethodOptions)
+}
+
+void MethodOptions::InitAsDefaultInstance() {
+}
+
+MethodOptions::MethodOptions(const MethodOptions& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions)
+}
+
+void MethodOptions::SharedCtor() {
+  _cached_size_ = 0;
+  deprecated_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MethodOptions::~MethodOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions)
+  SharedDtor();
+}
+
+void MethodOptions::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void MethodOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* MethodOptions::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return MethodOptions_descriptor_;
+}
+
+const MethodOptions& MethodOptions::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+MethodOptions* MethodOptions::default_instance_ = NULL;
+
+MethodOptions* MethodOptions::New(::google::protobuf::Arena* arena) const {
+  MethodOptions* n = new MethodOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void MethodOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
+  _extensions_.Clear();
+  deprecated_ = false;
+  uninterpreted_option_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool MethodOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool deprecated = 33 [default = false];
+      case 33: {
+        if (tag == 264) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &deprecated_)));
+          set_has_deprecated();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (tag == 7994) {
+         parse_uninterpreted_option:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_uninterpreted_option:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input, default_instance_,
+                                      mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.MethodOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.MethodOptions)
+  return false;
+#undef DO_
+}
+
+void MethodOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.MethodOptions)
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(i), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.MethodOptions)
+}
+
+::google::protobuf::uint8* MethodOptions::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions)
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target);
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(i), target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.SerializeWithCachedSizesToArray(
+      1000, 536870912, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions)
+  return target;
+}
+
+int MethodOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions)
+  int total_size = 0;
+
+  // optional bool deprecated = 33 [default = false];
+  if (has_deprecated()) {
+    total_size += 2 + 1;
+  }
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  total_size += 2 * this->uninterpreted_option_size();
+  for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->uninterpreted_option(i));
+  }
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MethodOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodOptions)
+    MergeFrom(*source);
+  }
+}
+
+void MethodOptions::MergeFrom(const MethodOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_deprecated()) {
+      set_deprecated(from.deprecated());
+    }
+  }
+  _extensions_.MergeFrom(from._extensions_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MethodOptions::CopyFrom(const MethodOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MethodOptions::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+
+  if (!_extensions_.IsInitialized()) return false;  return true;
+}
+
+void MethodOptions::Swap(MethodOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MethodOptions::InternalSwap(MethodOptions* other) {
+  std::swap(deprecated_, other->deprecated_);
+  uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata MethodOptions::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = MethodOptions_descriptor_;
+  metadata.reflection = MethodOptions_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodOptions
+
+// optional bool deprecated = 33 [default = false];
+bool MethodOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MethodOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void MethodOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void MethodOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+ bool MethodOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated)
+  return deprecated_;
+}
+ void MethodOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int MethodOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void MethodOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int UninterpretedOption_NamePart::kNamePartFieldNumber;
+const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+UninterpretedOption_NamePart::UninterpretedOption_NamePart()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart)
+}
+
+void UninterpretedOption_NamePart::InitAsDefaultInstance() {
+}
+
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart)
+}
+
+void UninterpretedOption_NamePart::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_part_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  is_extension_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
+  // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart)
+  SharedDtor();
+}
+
+void UninterpretedOption_NamePart::SharedDtor() {
+  name_part_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void UninterpretedOption_NamePart::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return UninterpretedOption_NamePart_descriptor_;
+}
+
+const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+UninterpretedOption_NamePart* UninterpretedOption_NamePart::default_instance_ = NULL;
+
+UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protobuf::Arena* arena) const {
+  UninterpretedOption_NamePart* n = new UninterpretedOption_NamePart;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void UninterpretedOption_NamePart::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
+  if (_has_bits_[0 / 32] & 3u) {
+    if (has_name_part()) {
+      name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    is_extension_ = false;
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required string name_part = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name_part()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->name_part().data(), this->name_part().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.UninterpretedOption.NamePart.name_part");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_is_extension;
+        break;
+      }
+
+      // required bool is_extension = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_is_extension:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_extension_)));
+          set_has_is_extension();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption.NamePart)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption.NamePart)
+  return false;
+#undef DO_
+}
+
+void UninterpretedOption_NamePart::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption.NamePart)
+  // required string name_part = 1;
+  if (has_name_part()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name_part().data(), this->name_part().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.NamePart.name_part");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name_part(), output);
+  }
+
+  // required bool is_extension = 2;
+  if (has_is_extension()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption.NamePart)
+}
+
+::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart)
+  // required string name_part = 1;
+  if (has_name_part()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->name_part().data(), this->name_part().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.NamePart.name_part");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name_part(), target);
+  }
+
+  // required bool is_extension = 2;
+  if (has_is_extension()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart)
+  return target;
+}
+
+int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
+// @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart)
+  int total_size = 0;
+
+  if (has_name_part()) {
+    // required string name_part = 1;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name_part());
+  }
+
+  if (has_is_extension()) {
+    // required bool is_extension = 2;
+    total_size += 1 + 1;
+  }
+
+  return total_size;
+}
+int UninterpretedOption_NamePart::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart)
+  int total_size = 0;
+
+  if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) {  // All required fields are present.
+    // required string name_part = 1;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name_part());
+
+    // required bool is_extension = 2;
+    total_size += 1 + 1;
+
+  } else {
+    total_size += RequiredFieldsByteSizeFallback();
+  }
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UninterpretedOption_NamePart* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption.NamePart)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption.NamePart)
+    MergeFrom(*source);
+  }
+}
+
+void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_name_part()) {
+      set_has_name_part();
+      name_part_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_part_);
+    }
+    if (from.has_is_extension()) {
+      set_is_extension(from.is_extension());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption.NamePart)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption.NamePart)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UninterpretedOption_NamePart::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+  return true;
+}
+
+void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) {
+  name_part_.Swap(&other->name_part_);
+  std::swap(is_extension_, other->is_extension_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UninterpretedOption_NamePart_descriptor_;
+  metadata.reflection = UninterpretedOption_NamePart_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int UninterpretedOption::kNameFieldNumber;
+const int UninterpretedOption::kIdentifierValueFieldNumber;
+const int UninterpretedOption::kPositiveIntValueFieldNumber;
+const int UninterpretedOption::kNegativeIntValueFieldNumber;
+const int UninterpretedOption::kDoubleValueFieldNumber;
+const int UninterpretedOption::kStringValueFieldNumber;
+const int UninterpretedOption::kAggregateValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+UninterpretedOption::UninterpretedOption()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption)
+}
+
+void UninterpretedOption::InitAsDefaultInstance() {
+}
+
+UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption)
+}
+
+void UninterpretedOption::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  identifier_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  positive_int_value_ = GOOGLE_ULONGLONG(0);
+  negative_int_value_ = GOOGLE_LONGLONG(0);
+  double_value_ = 0;
+  string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  aggregate_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+UninterpretedOption::~UninterpretedOption() {
+  // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption)
+  SharedDtor();
+}
+
+void UninterpretedOption::SharedDtor() {
+  identifier_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  aggregate_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void UninterpretedOption::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return UninterpretedOption_descriptor_;
+}
+
+const UninterpretedOption& UninterpretedOption::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+UninterpretedOption* UninterpretedOption::default_instance_ = NULL;
+
+UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) const {
+  UninterpretedOption* n = new UninterpretedOption;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void UninterpretedOption::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(UninterpretedOption, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<UninterpretedOption*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  if (_has_bits_[0 / 32] & 126u) {
+    ZR_(positive_int_value_, double_value_);
+    if (has_identifier_value()) {
+      identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_string_value()) {
+      string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_aggregate_value()) {
+      aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  name_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool UninterpretedOption::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+      case 2: {
+        if (tag == 18) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_name()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_name;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(26)) goto parse_identifier_value;
+        break;
+      }
+
+      // optional string identifier_value = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_identifier_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_identifier_value()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->identifier_value().data(), this->identifier_value().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.UninterpretedOption.identifier_value");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_positive_int_value;
+        break;
+      }
+
+      // optional uint64 positive_int_value = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_positive_int_value:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &positive_int_value_)));
+          set_has_positive_int_value();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_negative_int_value;
+        break;
+      }
+
+      // optional int64 negative_int_value = 5;
+      case 5: {
+        if (tag == 40) {
+         parse_negative_int_value:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &negative_int_value_)));
+          set_has_negative_int_value();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(49)) goto parse_double_value;
+        break;
+      }
+
+      // optional double double_value = 6;
+      case 6: {
+        if (tag == 49) {
+         parse_double_value:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                 input, &double_value_)));
+          set_has_double_value();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(58)) goto parse_string_value;
+        break;
+      }
+
+      // optional bytes string_value = 7;
+      case 7: {
+        if (tag == 58) {
+         parse_string_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_string_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(66)) goto parse_aggregate_value;
+        break;
+      }
+
+      // optional string aggregate_value = 8;
+      case 8: {
+        if (tag == 66) {
+         parse_aggregate_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_aggregate_value()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->aggregate_value().data(), this->aggregate_value().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.UninterpretedOption.aggregate_value");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption)
+  return false;
+#undef DO_
+}
+
+void UninterpretedOption::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption)
+  // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+  for (unsigned int i = 0, n = this->name_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->name(i), output);
+  }
+
+  // optional string identifier_value = 3;
+  if (has_identifier_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->identifier_value().data(), this->identifier_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.identifier_value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->identifier_value(), output);
+  }
+
+  // optional uint64 positive_int_value = 4;
+  if (has_positive_int_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
+  }
+
+  // optional int64 negative_int_value = 5;
+  if (has_negative_int_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
+  }
+
+  // optional double double_value = 6;
+  if (has_double_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
+  }
+
+  // optional bytes string_value = 7;
+  if (has_string_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      7, this->string_value(), output);
+  }
+
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.aggregate_value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      8, this->aggregate_value(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption)
+}
+
+::google::protobuf::uint8* UninterpretedOption::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption)
+  // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+  for (unsigned int i = 0, n = this->name_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->name(i), target);
+  }
+
+  // optional string identifier_value = 3;
+  if (has_identifier_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->identifier_value().data(), this->identifier_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.identifier_value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->identifier_value(), target);
+  }
+
+  // optional uint64 positive_int_value = 4;
+  if (has_positive_int_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
+  }
+
+  // optional int64 negative_int_value = 5;
+  if (has_negative_int_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
+  }
+
+  // optional double double_value = 6;
+  if (has_double_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
+  }
+
+  // optional bytes string_value = 7;
+  if (has_string_value()) {
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        7, this->string_value(), target);
+  }
+
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.UninterpretedOption.aggregate_value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->aggregate_value(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption)
+  return target;
+}
+
+int UninterpretedOption::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption)
+  int total_size = 0;
+
+  if (_has_bits_[1 / 32] & 126u) {
+    // optional string identifier_value = 3;
+    if (has_identifier_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->identifier_value());
+    }
+
+    // optional uint64 positive_int_value = 4;
+    if (has_positive_int_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->positive_int_value());
+    }
+
+    // optional int64 negative_int_value = 5;
+    if (has_negative_int_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int64Size(
+          this->negative_int_value());
+    }
+
+    // optional double double_value = 6;
+    if (has_double_value()) {
+      total_size += 1 + 8;
+    }
+
+    // optional bytes string_value = 7;
+    if (has_string_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->string_value());
+    }
+
+    // optional string aggregate_value = 8;
+    if (has_aggregate_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->aggregate_value());
+    }
+
+  }
+  // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+  total_size += 1 * this->name_size();
+  for (int i = 0; i < this->name_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->name(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UninterpretedOption* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption)
+    MergeFrom(*source);
+  }
+}
+
+void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  name_.MergeFrom(from.name_);
+  if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    if (from.has_identifier_value()) {
+      set_has_identifier_value();
+      identifier_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.identifier_value_);
+    }
+    if (from.has_positive_int_value()) {
+      set_positive_int_value(from.positive_int_value());
+    }
+    if (from.has_negative_int_value()) {
+      set_negative_int_value(from.negative_int_value());
+    }
+    if (from.has_double_value()) {
+      set_double_value(from.double_value());
+    }
+    if (from.has_string_value()) {
+      set_has_string_value();
+      string_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.string_value_);
+    }
+    if (from.has_aggregate_value()) {
+      set_has_aggregate_value();
+      aggregate_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.aggregate_value_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UninterpretedOption::CopyFrom(const UninterpretedOption& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UninterpretedOption::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->name())) return false;
+  return true;
+}
+
+void UninterpretedOption::Swap(UninterpretedOption* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
+  name_.UnsafeArenaSwap(&other->name_);
+  identifier_value_.Swap(&other->identifier_value_);
+  std::swap(positive_int_value_, other->positive_int_value_);
+  std::swap(negative_int_value_, other->negative_int_value_);
+  std::swap(double_value_, other->double_value_);
+  string_value_.Swap(&other->string_value_);
+  aggregate_value_.Swap(&other->aggregate_value_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UninterpretedOption::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UninterpretedOption_descriptor_;
+  metadata.reflection = UninterpretedOption_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UninterpretedOption_NamePart
+
+// required string name_part = 1;
+bool UninterpretedOption_NamePart::has_name_part() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void UninterpretedOption_NamePart::set_has_name_part() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void UninterpretedOption_NamePart::clear_has_name_part() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void UninterpretedOption_NamePart::clear_name_part() {
+  name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name_part();
+}
+ const ::std::string& UninterpretedOption_NamePart::name_part() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
+  set_has_name_part();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption_NamePart::release_name_part() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
+  clear_has_name_part();
+  return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+  if (name_part != NULL) {
+    set_has_name_part();
+  } else {
+    clear_has_name_part();
+  }
+  name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+
+// required bool is_extension = 2;
+bool UninterpretedOption_NamePart::has_is_extension() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void UninterpretedOption_NamePart::set_has_is_extension() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void UninterpretedOption_NamePart::clear_has_is_extension() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void UninterpretedOption_NamePart::clear_is_extension() {
+  is_extension_ = false;
+  clear_has_is_extension();
+}
+ bool UninterpretedOption_NamePart::is_extension() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension)
+  return is_extension_;
+}
+ void UninterpretedOption_NamePart::set_is_extension(bool value) {
+  set_has_is_extension();
+  is_extension_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption
+
+// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+int UninterpretedOption::name_size() const {
+  return name_.size();
+}
+void UninterpretedOption::clear_name() {
+  name_.Clear();
+}
+const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
+  return name_.Get(index);
+}
+::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
+  return name_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+  // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
+  return name_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
+  return &name_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+  return name_;
+}
+
+// optional string identifier_value = 3;
+bool UninterpretedOption::has_identifier_value() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void UninterpretedOption::set_has_identifier_value() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void UninterpretedOption::clear_has_identifier_value() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void UninterpretedOption::clear_identifier_value() {
+  identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_identifier_value();
+}
+ const ::std::string& UninterpretedOption::identifier_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_identifier_value(const ::std::string& value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+}
+ ::std::string* UninterpretedOption::mutable_identifier_value() {
+  set_has_identifier_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_identifier_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
+  clear_has_identifier_value();
+  return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+  if (identifier_value != NULL) {
+    set_has_identifier_value();
+  } else {
+    clear_has_identifier_value();
+  }
+  identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+
+// optional uint64 positive_int_value = 4;
+bool UninterpretedOption::has_positive_int_value() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void UninterpretedOption::set_has_positive_int_value() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void UninterpretedOption::clear_has_positive_int_value() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void UninterpretedOption::clear_positive_int_value() {
+  positive_int_value_ = GOOGLE_ULONGLONG(0);
+  clear_has_positive_int_value();
+}
+ ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
+  return positive_int_value_;
+}
+ void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
+  set_has_positive_int_value();
+  positive_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
+}
+
+// optional int64 negative_int_value = 5;
+bool UninterpretedOption::has_negative_int_value() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void UninterpretedOption::set_has_negative_int_value() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void UninterpretedOption::clear_has_negative_int_value() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void UninterpretedOption::clear_negative_int_value() {
+  negative_int_value_ = GOOGLE_LONGLONG(0);
+  clear_has_negative_int_value();
+}
+ ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
+  return negative_int_value_;
+}
+ void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
+  set_has_negative_int_value();
+  negative_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
+}
+
+// optional double double_value = 6;
+bool UninterpretedOption::has_double_value() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void UninterpretedOption::set_has_double_value() {
+  _has_bits_[0] |= 0x00000010u;
+}
+void UninterpretedOption::clear_has_double_value() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+void UninterpretedOption::clear_double_value() {
+  double_value_ = 0;
+  clear_has_double_value();
+}
+ double UninterpretedOption::double_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value)
+  return double_value_;
+}
+ void UninterpretedOption::set_double_value(double value) {
+  set_has_double_value();
+  double_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
+}
+
+// optional bytes string_value = 7;
+bool UninterpretedOption::has_string_value() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void UninterpretedOption::set_has_string_value() {
+  _has_bits_[0] |= 0x00000020u;
+}
+void UninterpretedOption::clear_has_string_value() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+void UninterpretedOption::clear_string_value() {
+  string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_string_value();
+}
+ const ::std::string& UninterpretedOption::string_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_string_value(const ::std::string& value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const char* value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const void* value, size_t size) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+}
+ ::std::string* UninterpretedOption::mutable_string_value() {
+  set_has_string_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_string_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
+  clear_has_string_value();
+  return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+  if (string_value != NULL) {
+    set_has_string_value();
+  } else {
+    clear_has_string_value();
+  }
+  string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+
+// optional string aggregate_value = 8;
+bool UninterpretedOption::has_aggregate_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void UninterpretedOption::set_has_aggregate_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+void UninterpretedOption::clear_has_aggregate_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+void UninterpretedOption::clear_aggregate_value() {
+  aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_aggregate_value();
+}
+ const ::std::string& UninterpretedOption::aggregate_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ ::std::string* UninterpretedOption::mutable_aggregate_value() {
+  set_has_aggregate_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_aggregate_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
+  clear_has_aggregate_value();
+  return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+  if (aggregate_value != NULL) {
+    set_has_aggregate_value();
+  } else {
+    clear_has_aggregate_value();
+  }
+  aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SourceCodeInfo_Location::kPathFieldNumber;
+const int SourceCodeInfo_Location::kSpanFieldNumber;
+const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SourceCodeInfo_Location::SourceCodeInfo_Location()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location)
+}
+
+void SourceCodeInfo_Location::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location)
+}
+
+void SourceCodeInfo_Location::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  leading_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  trailing_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo_Location::~SourceCodeInfo_Location() {
+  // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location)
+  SharedDtor();
+}
+
+void SourceCodeInfo_Location::SharedDtor() {
+  leading_comments_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  trailing_comments_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo_Location::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_Location_descriptor_;
+}
+
+const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL;
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena* arena) const {
+  SourceCodeInfo_Location* n = new SourceCodeInfo_Location;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void SourceCodeInfo_Location::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
+  if (_has_bits_[0 / 32] & 12u) {
+    if (has_leading_comments()) {
+      leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+    if (has_trailing_comments()) {
+      trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+  path_.Clear();
+  span_.Clear();
+  leading_detached_comments_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool SourceCodeInfo_Location::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated int32 path = 1 [packed = true];
+      case 1: {
+        if (tag == 10) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_path())));
+        } else if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 10, input, this->mutable_path())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_span;
+        break;
+      }
+
+      // repeated int32 span = 2 [packed = true];
+      case 2: {
+        if (tag == 18) {
+         parse_span:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_span())));
+        } else if (tag == 16) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 18, input, this->mutable_span())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_leading_comments;
+        break;
+      }
+
+      // optional string leading_comments = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_leading_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_leading_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->leading_comments().data(), this->leading_comments().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.SourceCodeInfo.Location.leading_comments");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_trailing_comments;
+        break;
+      }
+
+      // optional string trailing_comments = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_trailing_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_trailing_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->trailing_comments().data(), this->trailing_comments().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.SourceCodeInfo.Location.trailing_comments");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_leading_detached_comments;
+        break;
+      }
+
+      // repeated string leading_detached_comments = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_leading_detached_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_leading_detached_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(),
+            this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_leading_detached_comments;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo.Location)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo.Location)
+  return false;
+#undef DO_
+}
+
+void SourceCodeInfo_Location::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo.Location)
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_path_cached_byte_size_);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->path(i), output);
+  }
+
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_span_cached_byte_size_);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->span(i), output);
+  }
+
+  // optional string leading_comments = 3;
+  if (has_leading_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->leading_comments().data(), this->leading_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.leading_comments");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->leading_comments(), output);
+  }
+
+  // optional string trailing_comments = 4;
+  if (has_trailing_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->trailing_comments().data(), this->trailing_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.trailing_comments");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->trailing_comments(), output);
+  }
+
+  // repeated string leading_detached_comments = 6;
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      6, this->leading_detached_comments(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo.Location)
+}
+
+::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location)
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      1,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _path_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->path(i), target);
+  }
+
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      2,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _span_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->span(i), target);
+  }
+
+  // optional string leading_comments = 3;
+  if (has_leading_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->leading_comments().data(), this->leading_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.leading_comments");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->leading_comments(), target);
+  }
+
+  // optional string trailing_comments = 4;
+  if (has_trailing_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->trailing_comments().data(), this->trailing_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.trailing_comments");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->trailing_comments(), target);
+  }
+
+  // repeated string leading_detached_comments = 6;
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(6, this->leading_detached_comments(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location)
+  return target;
+}
+
+int SourceCodeInfo_Location::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location)
+  int total_size = 0;
+
+  if (_has_bits_[2 / 32] & 12u) {
+    // optional string leading_comments = 3;
+    if (has_leading_comments()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->leading_comments());
+    }
+
+    // optional string trailing_comments = 4;
+    if (has_trailing_comments()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->trailing_comments());
+    }
+
+  }
+  // repeated int32 path = 1 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->path_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->path(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+    _path_cached_byte_size_ = data_size;
+    GOOGLE_SAFE_CONCURRENT_WRITES_END();
+    total_size += data_size;
+  }
+
+  // repeated int32 span = 2 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->span_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->span(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+    _span_cached_byte_size_ = data_size;
+    GOOGLE_SAFE_CONCURRENT_WRITES_END();
+    total_size += data_size;
+  }
+
+  // repeated string leading_detached_comments = 6;
+  total_size += 1 * this->leading_detached_comments_size();
+  for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->leading_detached_comments(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceCodeInfo_Location* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo.Location)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo.Location)
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  path_.MergeFrom(from.path_);
+  span_.MergeFrom(from.span_);
+  leading_detached_comments_.MergeFrom(from.leading_detached_comments_);
+  if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+    if (from.has_leading_comments()) {
+      set_has_leading_comments();
+      leading_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.leading_comments_);
+    }
+    if (from.has_trailing_comments()) {
+      set_has_trailing_comments();
+      trailing_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.trailing_comments_);
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo.Location)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo.Location)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo_Location::IsInitialized() const {
+
+  return true;
+}
+
+void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
+  path_.UnsafeArenaSwap(&other->path_);
+  span_.UnsafeArenaSwap(&other->span_);
+  leading_comments_.Swap(&other->leading_comments_);
+  trailing_comments_.Swap(&other->trailing_comments_);
+  leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_Location_descriptor_;
+  metadata.reflection = SourceCodeInfo_Location_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SourceCodeInfo::kLocationFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SourceCodeInfo::SourceCodeInfo()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo)
+}
+
+void SourceCodeInfo::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
+}
+
+void SourceCodeInfo::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo::~SourceCodeInfo() {
+  // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo)
+  SharedDtor();
+}
+
+void SourceCodeInfo::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_descriptor_;
+}
+
+const SourceCodeInfo& SourceCodeInfo::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL;
+
+SourceCodeInfo* SourceCodeInfo::New(::google::protobuf::Arena* arena) const {
+  SourceCodeInfo* n = new SourceCodeInfo;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void SourceCodeInfo::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
+  location_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool SourceCodeInfo::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_location:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_location()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_loop_location;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo)
+  return false;
+#undef DO_
+}
+
+void SourceCodeInfo::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo)
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (unsigned int i = 0, n = this->location_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->location(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo)
+}
+
+::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo)
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (unsigned int i = 0, n = this->location_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->location(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo)
+  return target;
+}
+
+int SourceCodeInfo::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo)
+  int total_size = 0;
+
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  total_size += 1 * this->location_size();
+  for (int i = 0; i < this->location_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->location(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceCodeInfo* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo)
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  location_.MergeFrom(from.location_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo::IsInitialized() const {
+
+  return true;
+}
+
+void SourceCodeInfo::Swap(SourceCodeInfo* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
+  location_.UnsafeArenaSwap(&other->location_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_descriptor_;
+  metadata.reflection = SourceCodeInfo_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+int SourceCodeInfo_Location::path_size() const {
+  return path_.size();
+}
+void SourceCodeInfo_Location::clear_path() {
+  path_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
+  return path_.Get(index);
+}
+ void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
+}
+ void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
+  return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
+  return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+int SourceCodeInfo_Location::span_size() const {
+  return span_.size();
+}
+void SourceCodeInfo_Location::clear_span() {
+  span_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
+  return span_.Get(index);
+}
+ void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+  span_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
+}
+ void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+  span_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
+  return span_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
+  return &span_;
+}
+
+// optional string leading_comments = 3;
+bool SourceCodeInfo_Location::has_leading_comments() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void SourceCodeInfo_Location::set_has_leading_comments() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void SourceCodeInfo_Location::clear_has_leading_comments() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void SourceCodeInfo_Location::clear_leading_comments() {
+  leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_leading_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+  set_has_leading_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  clear_has_leading_comments();
+  return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+  if (leading_comments != NULL) {
+    set_has_leading_comments();
+  } else {
+    clear_has_leading_comments();
+  }
+  leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+
+// optional string trailing_comments = 4;
+bool SourceCodeInfo_Location::has_trailing_comments() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void SourceCodeInfo_Location::set_has_trailing_comments() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void SourceCodeInfo_Location::clear_has_trailing_comments() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void SourceCodeInfo_Location::clear_trailing_comments() {
+  trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_trailing_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+  set_has_trailing_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  clear_has_trailing_comments();
+  return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+  if (trailing_comments != NULL) {
+    set_has_trailing_comments();
+  } else {
+    clear_has_trailing_comments();
+  }
+  trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+
+// repeated string leading_detached_comments = 6;
+int SourceCodeInfo_Location::leading_detached_comments_size() const {
+  return leading_detached_comments_.size();
+}
+void SourceCodeInfo_Location::clear_leading_detached_comments() {
+  leading_detached_comments_.Clear();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Get(index);
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Mutable(index);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  leading_detached_comments_.Mutable(index)->assign(value);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+  leading_detached_comments_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+  leading_detached_comments_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Add();
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+  leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return &leading_detached_comments_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+int SourceCodeInfo::location_size() const {
+  return location_.size();
+}
+void SourceCodeInfo::clear_location() {
+  location_.Clear();
+}
+const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
+  return location_.Get(index);
+}
+::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
+  return location_.Mutable(index);
+}
+::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
+  return location_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
+  return &location_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+  return location_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GeneratedCodeInfo_Annotation::kPathFieldNumber;
+const int GeneratedCodeInfo_Annotation::kSourceFileFieldNumber;
+const int GeneratedCodeInfo_Annotation::kBeginFieldNumber;
+const int GeneratedCodeInfo_Annotation::kEndFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+void GeneratedCodeInfo_Annotation::InitAsDefaultInstance() {
+}
+
+GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+void GeneratedCodeInfo_Annotation::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  source_file_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  begin_ = 0;
+  end_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() {
+  // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation)
+  SharedDtor();
+}
+
+void GeneratedCodeInfo_Annotation::SharedDtor() {
+  source_file_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_Annotation::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return GeneratedCodeInfo_Annotation_descriptor_;
+}
+
+const GeneratedCodeInfo_Annotation& GeneratedCodeInfo_Annotation::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::default_instance_ = NULL;
+
+GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::New(::google::protobuf::Arena* arena) const {
+  GeneratedCodeInfo_Annotation* n = new GeneratedCodeInfo_Annotation;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void GeneratedCodeInfo_Annotation::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(GeneratedCodeInfo_Annotation, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<GeneratedCodeInfo_Annotation*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  if (_has_bits_[0 / 32] & 14u) {
+    ZR_(begin_, end_);
+    if (has_source_file()) {
+      source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    }
+  }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  path_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated int32 path = 1 [packed = true];
+      case 1: {
+        if (tag == 10) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_path())));
+        } else if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 10, input, this->mutable_path())));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_source_file;
+        break;
+      }
+
+      // optional string source_file = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_source_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_source_file()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->source_file().data(), this->source_file().length(),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_begin;
+        break;
+      }
+
+      // optional int32 begin = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_begin:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &begin_)));
+          set_has_begin();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_end;
+        break;
+      }
+
+      // optional int32 end = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_end:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &end_)));
+          set_has_end();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo.Annotation)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo.Annotation)
+  return false;
+#undef DO_
+}
+
+void GeneratedCodeInfo_Annotation::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_path_cached_byte_size_);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->path(i), output);
+  }
+
+  // optional string source_file = 2;
+  if (has_source_file()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->source_file().data(), this->source_file().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->source_file(), output);
+  }
+
+  // optional int32 begin = 3;
+  if (has_begin()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->begin(), output);
+  }
+
+  // optional int32 end = 4;
+  if (has_end()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->end(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+::google::protobuf::uint8* GeneratedCodeInfo_Annotation::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      1,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _path_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->path(i), target);
+  }
+
+  // optional string source_file = 2;
+  if (has_source_file()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->source_file().data(), this->source_file().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->source_file(), target);
+  }
+
+  // optional int32 begin = 3;
+  if (has_begin()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->begin(), target);
+  }
+
+  // optional int32 end = 4;
+  if (has_end()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->end(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation)
+  return target;
+}
+
+int GeneratedCodeInfo_Annotation::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  int total_size = 0;
+
+  if (_has_bits_[1 / 32] & 14u) {
+    // optional string source_file = 2;
+    if (has_source_file()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->source_file());
+    }
+
+    // optional int32 begin = 3;
+    if (has_begin()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->begin());
+    }
+
+    // optional int32 end = 4;
+    if (has_end()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->end());
+    }
+
+  }
+  // repeated int32 path = 1 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->path_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->path(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+    _path_cached_byte_size_ = data_size;
+    GOOGLE_SAFE_CONCURRENT_WRITES_END();
+    total_size += data_size;
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const GeneratedCodeInfo_Annotation* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo.Annotation)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo.Annotation)
+    MergeFrom(*source);
+  }
+}
+
+void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  path_.MergeFrom(from.path_);
+  if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    if (from.has_source_file()) {
+      set_has_source_file();
+      source_file_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.source_file_);
+    }
+    if (from.has_begin()) {
+      set_begin(from.begin());
+    }
+    if (from.has_end()) {
+      set_end(from.end());
+    }
+  }
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void GeneratedCodeInfo_Annotation::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GeneratedCodeInfo_Annotation::IsInitialized() const {
+
+  return true;
+}
+
+void GeneratedCodeInfo_Annotation::Swap(GeneratedCodeInfo_Annotation* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) {
+  path_.UnsafeArenaSwap(&other->path_);
+  source_file_.Swap(&other->source_file_);
+  std::swap(begin_, other->begin_);
+  std::swap(end_, other->end_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = GeneratedCodeInfo_Annotation_descriptor_;
+  metadata.reflection = GeneratedCodeInfo_Annotation_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GeneratedCodeInfo::kAnnotationFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GeneratedCodeInfo::GeneratedCodeInfo()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo)
+}
+
+void GeneratedCodeInfo::InitAsDefaultInstance() {
+}
+
+GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
+}
+
+void GeneratedCodeInfo::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GeneratedCodeInfo::~GeneratedCodeInfo() {
+  // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo)
+  SharedDtor();
+}
+
+void GeneratedCodeInfo::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void GeneratedCodeInfo::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* GeneratedCodeInfo::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return GeneratedCodeInfo_descriptor_;
+}
+
+const GeneratedCodeInfo& GeneratedCodeInfo::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  return *default_instance_;
+}
+
+GeneratedCodeInfo* GeneratedCodeInfo::default_instance_ = NULL;
+
+GeneratedCodeInfo* GeneratedCodeInfo::New(::google::protobuf::Arena* arena) const {
+  GeneratedCodeInfo* n = new GeneratedCodeInfo;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void GeneratedCodeInfo::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
+  annotation_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  if (_internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->Clear();
+  }
+}
+
+bool GeneratedCodeInfo::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_annotation:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_annotation()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_loop_annotation;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo)
+  return false;
+#undef DO_
+}
+
+void GeneratedCodeInfo::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo)
+  // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+  for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->annotation(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo)
+}
+
+::google::protobuf::uint8* GeneratedCodeInfo::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo)
+  // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+  for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->annotation(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo)
+  return target;
+}
+
+int GeneratedCodeInfo::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo)
+  int total_size = 0;
+
+  // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+  total_size += 1 * this->annotation_size();
+  for (int i = 0; i < this->annotation_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->annotation(i));
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const GeneratedCodeInfo* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo)
+    MergeFrom(*source);
+  }
+}
+
+void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  annotation_.MergeFrom(from.annotation_);
+  if (from._internal_metadata_.have_unknown_fields()) {
+    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  }
+}
+
+void GeneratedCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GeneratedCodeInfo::IsInitialized() const {
+
+  return true;
+}
+
+void GeneratedCodeInfo::Swap(GeneratedCodeInfo* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
+  annotation_.UnsafeArenaSwap(&other->annotation_);
+  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata GeneratedCodeInfo::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = GeneratedCodeInfo_descriptor_;
+  metadata.reflection = GeneratedCodeInfo_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// GeneratedCodeInfo_Annotation
+
+// repeated int32 path = 1 [packed = true];
+int GeneratedCodeInfo_Annotation::path_size() const {
+  return path_.size();
+}
+void GeneratedCodeInfo_Annotation::clear_path() {
+  path_.Clear();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return path_.Get(index);
+}
+ void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+ void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+GeneratedCodeInfo_Annotation::path() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+GeneratedCodeInfo_Annotation::mutable_path() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return &path_;
+}
+
+// optional string source_file = 2;
+bool GeneratedCodeInfo_Annotation::has_source_file() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_source_file() {
+  _has_bits_[0] |= 0x00000002u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_source_file() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+void GeneratedCodeInfo_Annotation::clear_source_file() {
+  source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_source_file();
+}
+ const ::std::string& GeneratedCodeInfo_Annotation::source_file() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  return source_file_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
+  set_has_source_file();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+  // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  clear_has_source_file();
+  return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) {
+  if (source_file != NULL) {
+    set_has_source_file();
+  } else {
+    clear_has_source_file();
+  }
+  source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+
+// optional int32 begin = 3;
+bool GeneratedCodeInfo_Annotation::has_begin() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_begin() {
+  _has_bits_[0] |= 0x00000004u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_begin() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+void GeneratedCodeInfo_Annotation::clear_begin() {
+  begin_ = 0;
+  clear_has_begin();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+  return begin_;
+}
+ void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) {
+  set_has_begin();
+  begin_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+}
+
+// optional int32 end = 4;
+bool GeneratedCodeInfo_Annotation::has_end() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_end() {
+  _has_bits_[0] |= 0x00000008u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_end() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+void GeneratedCodeInfo_Annotation::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end)
+  return end_;
+}
+ void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
+}
+
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo
+
+// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+int GeneratedCodeInfo::annotation_size() const {
+  return annotation_.size();
+}
+void GeneratedCodeInfo::clear_annotation() {
+  annotation_.Clear();
+}
+const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Get(index);
+}
+::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Mutable(index);
+}
+::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() {
+  // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+GeneratedCodeInfo::mutable_annotation() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation)
+  return &annotation_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+GeneratedCodeInfo::annotation() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.h b/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.h
new file mode 100644
index 0000000..92a0a3a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor.pb.h
@@ -0,0 +1,7714 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+class DescriptorProto;
+class DescriptorProto_ExtensionRange;
+class DescriptorProto_ReservedRange;
+class EnumDescriptorProto;
+class EnumOptions;
+class EnumValueDescriptorProto;
+class EnumValueOptions;
+class FieldDescriptorProto;
+class FieldOptions;
+class FileDescriptorProto;
+class FileDescriptorSet;
+class FileOptions;
+class GeneratedCodeInfo;
+class GeneratedCodeInfo_Annotation;
+class MessageOptions;
+class MethodDescriptorProto;
+class MethodOptions;
+class OneofDescriptorProto;
+class ServiceDescriptorProto;
+class ServiceOptions;
+class SourceCodeInfo;
+class SourceCodeInfo_Location;
+class UninterpretedOption;
+class UninterpretedOption_NamePart;
+
+enum FieldDescriptorProto_Type {
+  FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
+  FieldDescriptorProto_Type_TYPE_FLOAT = 2,
+  FieldDescriptorProto_Type_TYPE_INT64 = 3,
+  FieldDescriptorProto_Type_TYPE_UINT64 = 4,
+  FieldDescriptorProto_Type_TYPE_INT32 = 5,
+  FieldDescriptorProto_Type_TYPE_FIXED64 = 6,
+  FieldDescriptorProto_Type_TYPE_FIXED32 = 7,
+  FieldDescriptorProto_Type_TYPE_BOOL = 8,
+  FieldDescriptorProto_Type_TYPE_STRING = 9,
+  FieldDescriptorProto_Type_TYPE_GROUP = 10,
+  FieldDescriptorProto_Type_TYPE_MESSAGE = 11,
+  FieldDescriptorProto_Type_TYPE_BYTES = 12,
+  FieldDescriptorProto_Type_TYPE_UINT32 = 13,
+  FieldDescriptorProto_Type_TYPE_ENUM = 14,
+  FieldDescriptorProto_Type_TYPE_SFIXED32 = 15,
+  FieldDescriptorProto_Type_TYPE_SFIXED64 = 16,
+  FieldDescriptorProto_Type_TYPE_SINT32 = 17,
+  FieldDescriptorProto_Type_TYPE_SINT64 = 18
+};
+LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
+const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
+const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
+const int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
+inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    FieldDescriptorProto_Type_descriptor(), value);
+}
+inline bool FieldDescriptorProto_Type_Parse(
+    const ::std::string& name, FieldDescriptorProto_Type* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<FieldDescriptorProto_Type>(
+    FieldDescriptorProto_Type_descriptor(), name, value);
+}
+enum FieldDescriptorProto_Label {
+  FieldDescriptorProto_Label_LABEL_OPTIONAL = 1,
+  FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
+  FieldDescriptorProto_Label_LABEL_REPEATED = 3
+};
+LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
+const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
+const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
+const int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
+inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    FieldDescriptorProto_Label_descriptor(), value);
+}
+inline bool FieldDescriptorProto_Label_Parse(
+    const ::std::string& name, FieldDescriptorProto_Label* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<FieldDescriptorProto_Label>(
+    FieldDescriptorProto_Label_descriptor(), name, value);
+}
+enum FileOptions_OptimizeMode {
+  FileOptions_OptimizeMode_SPEED = 1,
+  FileOptions_OptimizeMode_CODE_SIZE = 2,
+  FileOptions_OptimizeMode_LITE_RUNTIME = 3
+};
+LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
+const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
+const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME;
+const int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
+inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    FileOptions_OptimizeMode_descriptor(), value);
+}
+inline bool FileOptions_OptimizeMode_Parse(
+    const ::std::string& name, FileOptions_OptimizeMode* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<FileOptions_OptimizeMode>(
+    FileOptions_OptimizeMode_descriptor(), name, value);
+}
+enum FieldOptions_CType {
+  FieldOptions_CType_STRING = 0,
+  FieldOptions_CType_CORD = 1,
+  FieldOptions_CType_STRING_PIECE = 2
+};
+LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
+const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING;
+const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
+const int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
+inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    FieldOptions_CType_descriptor(), value);
+}
+inline bool FieldOptions_CType_Parse(
+    const ::std::string& name, FieldOptions_CType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_CType>(
+    FieldOptions_CType_descriptor(), name, value);
+}
+enum FieldOptions_JSType {
+  FieldOptions_JSType_JS_NORMAL = 0,
+  FieldOptions_JSType_JS_STRING = 1,
+  FieldOptions_JSType_JS_NUMBER = 2
+};
+LIBPROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value);
+const FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL;
+const FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER;
+const int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor();
+inline const ::std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    FieldOptions_JSType_descriptor(), value);
+}
+inline bool FieldOptions_JSType_Parse(
+    const ::std::string& name, FieldOptions_JSType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_JSType>(
+    FieldOptions_JSType_descriptor(), name, value);
+}
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message {
+ public:
+  FileDescriptorSet();
+  virtual ~FileDescriptorSet();
+
+  FileDescriptorSet(const FileDescriptorSet& from);
+
+  inline FileDescriptorSet& operator=(const FileDescriptorSet& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FileDescriptorSet& default_instance();
+
+  void Swap(FileDescriptorSet* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FileDescriptorSet* New() const { return New(NULL); }
+
+  FileDescriptorSet* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FileDescriptorSet& from);
+  void MergeFrom(const FileDescriptorSet& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FileDescriptorSet* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.FileDescriptorProto file = 1;
+  int file_size() const;
+  void clear_file();
+  static const int kFileFieldNumber = 1;
+  const ::google::protobuf::FileDescriptorProto& file(int index) const;
+  ::google::protobuf::FileDescriptorProto* mutable_file(int index);
+  ::google::protobuf::FileDescriptorProto* add_file();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+      mutable_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+      file() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static FileDescriptorSet* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Message {
+ public:
+  FileDescriptorProto();
+  virtual ~FileDescriptorProto();
+
+  FileDescriptorProto(const FileDescriptorProto& from);
+
+  inline FileDescriptorProto& operator=(const FileDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FileDescriptorProto& default_instance();
+
+  void Swap(FileDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FileDescriptorProto* New() const { return New(NULL); }
+
+  FileDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FileDescriptorProto& from);
+  void MergeFrom(const FileDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FileDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string package = 2;
+  bool has_package() const;
+  void clear_package();
+  static const int kPackageFieldNumber = 2;
+  const ::std::string& package() const;
+  void set_package(const ::std::string& value);
+  void set_package(const char* value);
+  void set_package(const char* value, size_t size);
+  ::std::string* mutable_package();
+  ::std::string* release_package();
+  void set_allocated_package(::std::string* package);
+
+  // repeated string dependency = 3;
+  int dependency_size() const;
+  void clear_dependency();
+  static const int kDependencyFieldNumber = 3;
+  const ::std::string& dependency(int index) const;
+  ::std::string* mutable_dependency(int index);
+  void set_dependency(int index, const ::std::string& value);
+  void set_dependency(int index, const char* value);
+  void set_dependency(int index, const char* value, size_t size);
+  ::std::string* add_dependency();
+  void add_dependency(const ::std::string& value);
+  void add_dependency(const char* value);
+  void add_dependency(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
+
+  // repeated int32 public_dependency = 10;
+  int public_dependency_size() const;
+  void clear_public_dependency();
+  static const int kPublicDependencyFieldNumber = 10;
+  ::google::protobuf::int32 public_dependency(int index) const;
+  void set_public_dependency(int index, ::google::protobuf::int32 value);
+  void add_public_dependency(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      public_dependency() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_public_dependency();
+
+  // repeated int32 weak_dependency = 11;
+  int weak_dependency_size() const;
+  void clear_weak_dependency();
+  static const int kWeakDependencyFieldNumber = 11;
+  ::google::protobuf::int32 weak_dependency(int index) const;
+  void set_weak_dependency(int index, ::google::protobuf::int32 value);
+  void add_weak_dependency(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      weak_dependency() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_weak_dependency();
+
+  // repeated .google.protobuf.DescriptorProto message_type = 4;
+  int message_type_size() const;
+  void clear_message_type();
+  static const int kMessageTypeFieldNumber = 4;
+  const ::google::protobuf::DescriptorProto& message_type(int index) const;
+  ::google::protobuf::DescriptorProto* mutable_message_type(int index);
+  ::google::protobuf::DescriptorProto* add_message_type();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+      mutable_message_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+      message_type() const;
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+  int enum_type_size() const;
+  void clear_enum_type();
+  static const int kEnumTypeFieldNumber = 5;
+  const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+  ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+  ::google::protobuf::EnumDescriptorProto* add_enum_type();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+      mutable_enum_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+      enum_type() const;
+
+  // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+  int service_size() const;
+  void clear_service();
+  static const int kServiceFieldNumber = 6;
+  const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
+  ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
+  ::google::protobuf::ServiceDescriptorProto* add_service();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+      mutable_service();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+      service() const;
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+  int extension_size() const;
+  void clear_extension();
+  static const int kExtensionFieldNumber = 7;
+  const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+  ::google::protobuf::FieldDescriptorProto* add_extension();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+      mutable_extension();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+      extension() const;
+
+  // optional .google.protobuf.FileOptions options = 8;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 8;
+  const ::google::protobuf::FileOptions& options() const;
+  ::google::protobuf::FileOptions* mutable_options();
+  ::google::protobuf::FileOptions* release_options();
+  void set_allocated_options(::google::protobuf::FileOptions* options);
+
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  bool has_source_code_info() const;
+  void clear_source_code_info();
+  static const int kSourceCodeInfoFieldNumber = 9;
+  const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+  ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+  ::google::protobuf::SourceCodeInfo* release_source_code_info();
+  void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+
+  // optional string syntax = 12;
+  bool has_syntax() const;
+  void clear_syntax();
+  static const int kSyntaxFieldNumber = 12;
+  const ::std::string& syntax() const;
+  void set_syntax(const ::std::string& value);
+  void set_syntax(const char* value);
+  void set_syntax(const char* value, size_t size);
+  ::std::string* mutable_syntax();
+  ::std::string* release_syntax();
+  void set_allocated_syntax(::std::string* syntax);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_package();
+  inline void clear_has_package();
+  inline void set_has_options();
+  inline void clear_has_options();
+  inline void set_has_source_code_info();
+  inline void clear_has_source_code_info();
+  inline void set_has_syntax();
+  inline void clear_has_syntax();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr package_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
+  ::google::protobuf::FileOptions* options_;
+  ::google::protobuf::SourceCodeInfo* source_code_info_;
+  ::google::protobuf::internal::ArenaStringPtr syntax_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static FileDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::protobuf::Message {
+ public:
+  DescriptorProto_ExtensionRange();
+  virtual ~DescriptorProto_ExtensionRange();
+
+  DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
+
+  inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const DescriptorProto_ExtensionRange& default_instance();
+
+  void Swap(DescriptorProto_ExtensionRange* other);
+
+  // implements Message ----------------------------------------------
+
+  inline DescriptorProto_ExtensionRange* New() const { return New(NULL); }
+
+  DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const DescriptorProto_ExtensionRange& from);
+  void MergeFrom(const DescriptorProto_ExtensionRange& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(DescriptorProto_ExtensionRange* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int32 start = 1;
+  bool has_start() const;
+  void clear_start();
+  static const int kStartFieldNumber = 1;
+  ::google::protobuf::int32 start() const;
+  void set_start(::google::protobuf::int32 value);
+
+  // optional int32 end = 2;
+  bool has_end() const;
+  void clear_end();
+  static const int kEndFieldNumber = 2;
+  ::google::protobuf::int32 end() const;
+  void set_end(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
+ private:
+  inline void set_has_start();
+  inline void clear_has_start();
+  inline void set_has_end();
+  inline void clear_has_end();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::int32 start_;
+  ::google::protobuf::int32 end_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static DescriptorProto_ExtensionRange* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT DescriptorProto_ReservedRange : public ::google::protobuf::Message {
+ public:
+  DescriptorProto_ReservedRange();
+  virtual ~DescriptorProto_ReservedRange();
+
+  DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
+
+  inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const DescriptorProto_ReservedRange& default_instance();
+
+  void Swap(DescriptorProto_ReservedRange* other);
+
+  // implements Message ----------------------------------------------
+
+  inline DescriptorProto_ReservedRange* New() const { return New(NULL); }
+
+  DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const DescriptorProto_ReservedRange& from);
+  void MergeFrom(const DescriptorProto_ReservedRange& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(DescriptorProto_ReservedRange* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int32 start = 1;
+  bool has_start() const;
+  void clear_start();
+  static const int kStartFieldNumber = 1;
+  ::google::protobuf::int32 start() const;
+  void set_start(::google::protobuf::int32 value);
+
+  // optional int32 end = 2;
+  bool has_end() const;
+  void clear_end();
+  static const int kEndFieldNumber = 2;
+  ::google::protobuf::int32 end() const;
+  void set_end(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange)
+ private:
+  inline void set_has_start();
+  inline void clear_has_start();
+  inline void set_has_end();
+  inline void clear_has_end();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::int32 start_;
+  ::google::protobuf::int32 end_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static DescriptorProto_ReservedRange* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
+ public:
+  DescriptorProto();
+  virtual ~DescriptorProto();
+
+  DescriptorProto(const DescriptorProto& from);
+
+  inline DescriptorProto& operator=(const DescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const DescriptorProto& default_instance();
+
+  void Swap(DescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline DescriptorProto* New() const { return New(NULL); }
+
+  DescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const DescriptorProto& from);
+  void MergeFrom(const DescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(DescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef DescriptorProto_ExtensionRange ExtensionRange;
+  typedef DescriptorProto_ReservedRange ReservedRange;
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.FieldDescriptorProto field = 2;
+  int field_size() const;
+  void clear_field();
+  static const int kFieldFieldNumber = 2;
+  const ::google::protobuf::FieldDescriptorProto& field(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
+  ::google::protobuf::FieldDescriptorProto* add_field();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+      mutable_field();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+      field() const;
+
+  // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+  int extension_size() const;
+  void clear_extension();
+  static const int kExtensionFieldNumber = 6;
+  const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+  ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+  ::google::protobuf::FieldDescriptorProto* add_extension();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+      mutable_extension();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+      extension() const;
+
+  // repeated .google.protobuf.DescriptorProto nested_type = 3;
+  int nested_type_size() const;
+  void clear_nested_type();
+  static const int kNestedTypeFieldNumber = 3;
+  const ::google::protobuf::DescriptorProto& nested_type(int index) const;
+  ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
+  ::google::protobuf::DescriptorProto* add_nested_type();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+      mutable_nested_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+      nested_type() const;
+
+  // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+  int enum_type_size() const;
+  void clear_enum_type();
+  static const int kEnumTypeFieldNumber = 4;
+  const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+  ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+  ::google::protobuf::EnumDescriptorProto* add_enum_type();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+      mutable_enum_type();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+      enum_type() const;
+
+  // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+  int extension_range_size() const;
+  void clear_extension_range();
+  static const int kExtensionRangeFieldNumber = 5;
+  const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
+  ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
+  ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+      mutable_extension_range();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+      extension_range() const;
+
+  // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+  int oneof_decl_size() const;
+  void clear_oneof_decl();
+  static const int kOneofDeclFieldNumber = 8;
+  const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
+  ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
+  ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+      mutable_oneof_decl();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+      oneof_decl() const;
+
+  // optional .google.protobuf.MessageOptions options = 7;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 7;
+  const ::google::protobuf::MessageOptions& options() const;
+  ::google::protobuf::MessageOptions* mutable_options();
+  ::google::protobuf::MessageOptions* release_options();
+  void set_allocated_options(::google::protobuf::MessageOptions* options);
+
+  // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+  int reserved_range_size() const;
+  void clear_reserved_range();
+  static const int kReservedRangeFieldNumber = 9;
+  const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const;
+  ::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index);
+  ::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+      mutable_reserved_range();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+      reserved_range() const;
+
+  // repeated string reserved_name = 10;
+  int reserved_name_size() const;
+  void clear_reserved_name();
+  static const int kReservedNameFieldNumber = 10;
+  const ::std::string& reserved_name(int index) const;
+  ::std::string* mutable_reserved_name(int index);
+  void set_reserved_name(int index, const ::std::string& value);
+  void set_reserved_name(int index, const char* value);
+  void set_reserved_name(int index, const char* value, size_t size);
+  ::std::string* add_reserved_name();
+  void add_reserved_name(const ::std::string& value);
+  void add_reserved_name(const char* value);
+  void add_reserved_name(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& reserved_name() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_reserved_name();
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_;
+  ::google::protobuf::MessageOptions* options_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange > reserved_range_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> reserved_name_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static DescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Message {
+ public:
+  FieldDescriptorProto();
+  virtual ~FieldDescriptorProto();
+
+  FieldDescriptorProto(const FieldDescriptorProto& from);
+
+  inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FieldDescriptorProto& default_instance();
+
+  void Swap(FieldDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FieldDescriptorProto* New() const { return New(NULL); }
+
+  FieldDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FieldDescriptorProto& from);
+  void MergeFrom(const FieldDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FieldDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef FieldDescriptorProto_Type Type;
+  static const Type TYPE_DOUBLE =
+    FieldDescriptorProto_Type_TYPE_DOUBLE;
+  static const Type TYPE_FLOAT =
+    FieldDescriptorProto_Type_TYPE_FLOAT;
+  static const Type TYPE_INT64 =
+    FieldDescriptorProto_Type_TYPE_INT64;
+  static const Type TYPE_UINT64 =
+    FieldDescriptorProto_Type_TYPE_UINT64;
+  static const Type TYPE_INT32 =
+    FieldDescriptorProto_Type_TYPE_INT32;
+  static const Type TYPE_FIXED64 =
+    FieldDescriptorProto_Type_TYPE_FIXED64;
+  static const Type TYPE_FIXED32 =
+    FieldDescriptorProto_Type_TYPE_FIXED32;
+  static const Type TYPE_BOOL =
+    FieldDescriptorProto_Type_TYPE_BOOL;
+  static const Type TYPE_STRING =
+    FieldDescriptorProto_Type_TYPE_STRING;
+  static const Type TYPE_GROUP =
+    FieldDescriptorProto_Type_TYPE_GROUP;
+  static const Type TYPE_MESSAGE =
+    FieldDescriptorProto_Type_TYPE_MESSAGE;
+  static const Type TYPE_BYTES =
+    FieldDescriptorProto_Type_TYPE_BYTES;
+  static const Type TYPE_UINT32 =
+    FieldDescriptorProto_Type_TYPE_UINT32;
+  static const Type TYPE_ENUM =
+    FieldDescriptorProto_Type_TYPE_ENUM;
+  static const Type TYPE_SFIXED32 =
+    FieldDescriptorProto_Type_TYPE_SFIXED32;
+  static const Type TYPE_SFIXED64 =
+    FieldDescriptorProto_Type_TYPE_SFIXED64;
+  static const Type TYPE_SINT32 =
+    FieldDescriptorProto_Type_TYPE_SINT32;
+  static const Type TYPE_SINT64 =
+    FieldDescriptorProto_Type_TYPE_SINT64;
+  static inline bool Type_IsValid(int value) {
+    return FieldDescriptorProto_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    FieldDescriptorProto_Type_Type_MIN;
+  static const Type Type_MAX =
+    FieldDescriptorProto_Type_Type_MAX;
+  static const int Type_ARRAYSIZE =
+    FieldDescriptorProto_Type_Type_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Type_descriptor() {
+    return FieldDescriptorProto_Type_descriptor();
+  }
+  static inline const ::std::string& Type_Name(Type value) {
+    return FieldDescriptorProto_Type_Name(value);
+  }
+  static inline bool Type_Parse(const ::std::string& name,
+      Type* value) {
+    return FieldDescriptorProto_Type_Parse(name, value);
+  }
+
+  typedef FieldDescriptorProto_Label Label;
+  static const Label LABEL_OPTIONAL =
+    FieldDescriptorProto_Label_LABEL_OPTIONAL;
+  static const Label LABEL_REQUIRED =
+    FieldDescriptorProto_Label_LABEL_REQUIRED;
+  static const Label LABEL_REPEATED =
+    FieldDescriptorProto_Label_LABEL_REPEATED;
+  static inline bool Label_IsValid(int value) {
+    return FieldDescriptorProto_Label_IsValid(value);
+  }
+  static const Label Label_MIN =
+    FieldDescriptorProto_Label_Label_MIN;
+  static const Label Label_MAX =
+    FieldDescriptorProto_Label_Label_MAX;
+  static const int Label_ARRAYSIZE =
+    FieldDescriptorProto_Label_Label_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Label_descriptor() {
+    return FieldDescriptorProto_Label_descriptor();
+  }
+  static inline const ::std::string& Label_Name(Label value) {
+    return FieldDescriptorProto_Label_Name(value);
+  }
+  static inline bool Label_Parse(const ::std::string& name,
+      Label* value) {
+    return FieldDescriptorProto_Label_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional int32 number = 3;
+  bool has_number() const;
+  void clear_number();
+  static const int kNumberFieldNumber = 3;
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
+
+  // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+  bool has_label() const;
+  void clear_label();
+  static const int kLabelFieldNumber = 4;
+  ::google::protobuf::FieldDescriptorProto_Label label() const;
+  void set_label(::google::protobuf::FieldDescriptorProto_Label value);
+
+  // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+  bool has_type() const;
+  void clear_type();
+  static const int kTypeFieldNumber = 5;
+  ::google::protobuf::FieldDescriptorProto_Type type() const;
+  void set_type(::google::protobuf::FieldDescriptorProto_Type value);
+
+  // optional string type_name = 6;
+  bool has_type_name() const;
+  void clear_type_name();
+  static const int kTypeNameFieldNumber = 6;
+  const ::std::string& type_name() const;
+  void set_type_name(const ::std::string& value);
+  void set_type_name(const char* value);
+  void set_type_name(const char* value, size_t size);
+  ::std::string* mutable_type_name();
+  ::std::string* release_type_name();
+  void set_allocated_type_name(::std::string* type_name);
+
+  // optional string extendee = 2;
+  bool has_extendee() const;
+  void clear_extendee();
+  static const int kExtendeeFieldNumber = 2;
+  const ::std::string& extendee() const;
+  void set_extendee(const ::std::string& value);
+  void set_extendee(const char* value);
+  void set_extendee(const char* value, size_t size);
+  ::std::string* mutable_extendee();
+  ::std::string* release_extendee();
+  void set_allocated_extendee(::std::string* extendee);
+
+  // optional string default_value = 7;
+  bool has_default_value() const;
+  void clear_default_value();
+  static const int kDefaultValueFieldNumber = 7;
+  const ::std::string& default_value() const;
+  void set_default_value(const ::std::string& value);
+  void set_default_value(const char* value);
+  void set_default_value(const char* value, size_t size);
+  ::std::string* mutable_default_value();
+  ::std::string* release_default_value();
+  void set_allocated_default_value(::std::string* default_value);
+
+  // optional int32 oneof_index = 9;
+  bool has_oneof_index() const;
+  void clear_oneof_index();
+  static const int kOneofIndexFieldNumber = 9;
+  ::google::protobuf::int32 oneof_index() const;
+  void set_oneof_index(::google::protobuf::int32 value);
+
+  // optional string json_name = 10;
+  bool has_json_name() const;
+  void clear_json_name();
+  static const int kJsonNameFieldNumber = 10;
+  const ::std::string& json_name() const;
+  void set_json_name(const ::std::string& value);
+  void set_json_name(const char* value);
+  void set_json_name(const char* value, size_t size);
+  ::std::string* mutable_json_name();
+  ::std::string* release_json_name();
+  void set_allocated_json_name(::std::string* json_name);
+
+  // optional .google.protobuf.FieldOptions options = 8;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 8;
+  const ::google::protobuf::FieldOptions& options() const;
+  ::google::protobuf::FieldOptions* mutable_options();
+  ::google::protobuf::FieldOptions* release_options();
+  void set_allocated_options(::google::protobuf::FieldOptions* options);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_label();
+  inline void clear_has_label();
+  inline void set_has_type();
+  inline void clear_has_type();
+  inline void set_has_type_name();
+  inline void clear_has_type_name();
+  inline void set_has_extendee();
+  inline void clear_has_extendee();
+  inline void set_has_default_value();
+  inline void clear_has_default_value();
+  inline void set_has_oneof_index();
+  inline void clear_has_oneof_index();
+  inline void set_has_json_name();
+  inline void clear_has_json_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::int32 number_;
+  int label_;
+  ::google::protobuf::internal::ArenaStringPtr type_name_;
+  ::google::protobuf::internal::ArenaStringPtr extendee_;
+  int type_;
+  ::google::protobuf::int32 oneof_index_;
+  ::google::protobuf::internal::ArenaStringPtr default_value_;
+  ::google::protobuf::internal::ArenaStringPtr json_name_;
+  ::google::protobuf::FieldOptions* options_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static FieldDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Message {
+ public:
+  OneofDescriptorProto();
+  virtual ~OneofDescriptorProto();
+
+  OneofDescriptorProto(const OneofDescriptorProto& from);
+
+  inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const OneofDescriptorProto& default_instance();
+
+  void Swap(OneofDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline OneofDescriptorProto* New() const { return New(NULL); }
+
+  OneofDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const OneofDescriptorProto& from);
+  void MergeFrom(const OneofDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(OneofDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static OneofDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Message {
+ public:
+  EnumDescriptorProto();
+  virtual ~EnumDescriptorProto();
+
+  EnumDescriptorProto(const EnumDescriptorProto& from);
+
+  inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const EnumDescriptorProto& default_instance();
+
+  void Swap(EnumDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline EnumDescriptorProto* New() const { return New(NULL); }
+
+  EnumDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const EnumDescriptorProto& from);
+  void MergeFrom(const EnumDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(EnumDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+  int value_size() const;
+  void clear_value();
+  static const int kValueFieldNumber = 2;
+  const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
+  ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
+  ::google::protobuf::EnumValueDescriptorProto* add_value();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+      mutable_value();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+      value() const;
+
+  // optional .google.protobuf.EnumOptions options = 3;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::EnumOptions& options() const;
+  ::google::protobuf::EnumOptions* mutable_options();
+  ::google::protobuf::EnumOptions* release_options();
+  void set_allocated_options(::google::protobuf::EnumOptions* options);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
+  ::google::protobuf::EnumOptions* options_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static EnumDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::Message {
+ public:
+  EnumValueDescriptorProto();
+  virtual ~EnumValueDescriptorProto();
+
+  EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
+
+  inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const EnumValueDescriptorProto& default_instance();
+
+  void Swap(EnumValueDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline EnumValueDescriptorProto* New() const { return New(NULL); }
+
+  EnumValueDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const EnumValueDescriptorProto& from);
+  void MergeFrom(const EnumValueDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(EnumValueDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional int32 number = 2;
+  bool has_number() const;
+  void clear_number();
+  static const int kNumberFieldNumber = 2;
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
+
+  // optional .google.protobuf.EnumValueOptions options = 3;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::EnumValueOptions& options() const;
+  ::google::protobuf::EnumValueOptions* mutable_options();
+  ::google::protobuf::EnumValueOptions* release_options();
+  void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_options();
+  inline void clear_has_options();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::EnumValueOptions* options_;
+  ::google::protobuf::int32 number_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static EnumValueDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Message {
+ public:
+  ServiceDescriptorProto();
+  virtual ~ServiceDescriptorProto();
+
+  ServiceDescriptorProto(const ServiceDescriptorProto& from);
+
+  inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const ServiceDescriptorProto& default_instance();
+
+  void Swap(ServiceDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline ServiceDescriptorProto* New() const { return New(NULL); }
+
+  ServiceDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const ServiceDescriptorProto& from);
+  void MergeFrom(const ServiceDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(ServiceDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.MethodDescriptorProto method = 2;
+  int method_size() const;
+  void clear_method();
+  static const int kMethodFieldNumber = 2;
+  const ::google::protobuf::MethodDescriptorProto& method(int index) const;
+  ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
+  ::google::protobuf::MethodDescriptorProto* add_method();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+      mutable_method();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+      method() const;
+
+  // optional .google.protobuf.ServiceOptions options = 3;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::ServiceOptions& options() const;
+  ::google::protobuf::ServiceOptions* mutable_options();
+  ::google::protobuf::ServiceOptions* release_options();
+  void set_allocated_options(::google::protobuf::ServiceOptions* options);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
+  ::google::protobuf::ServiceOptions* options_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static ServiceDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Message {
+ public:
+  MethodDescriptorProto();
+  virtual ~MethodDescriptorProto();
+
+  MethodDescriptorProto(const MethodDescriptorProto& from);
+
+  inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const MethodDescriptorProto& default_instance();
+
+  void Swap(MethodDescriptorProto* other);
+
+  // implements Message ----------------------------------------------
+
+  inline MethodDescriptorProto* New() const { return New(NULL); }
+
+  MethodDescriptorProto* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const MethodDescriptorProto& from);
+  void MergeFrom(const MethodDescriptorProto& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(MethodDescriptorProto* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  bool has_name() const;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string input_type = 2;
+  bool has_input_type() const;
+  void clear_input_type();
+  static const int kInputTypeFieldNumber = 2;
+  const ::std::string& input_type() const;
+  void set_input_type(const ::std::string& value);
+  void set_input_type(const char* value);
+  void set_input_type(const char* value, size_t size);
+  ::std::string* mutable_input_type();
+  ::std::string* release_input_type();
+  void set_allocated_input_type(::std::string* input_type);
+
+  // optional string output_type = 3;
+  bool has_output_type() const;
+  void clear_output_type();
+  static const int kOutputTypeFieldNumber = 3;
+  const ::std::string& output_type() const;
+  void set_output_type(const ::std::string& value);
+  void set_output_type(const char* value);
+  void set_output_type(const char* value, size_t size);
+  ::std::string* mutable_output_type();
+  ::std::string* release_output_type();
+  void set_allocated_output_type(::std::string* output_type);
+
+  // optional .google.protobuf.MethodOptions options = 4;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 4;
+  const ::google::protobuf::MethodOptions& options() const;
+  ::google::protobuf::MethodOptions* mutable_options();
+  ::google::protobuf::MethodOptions* release_options();
+  void set_allocated_options(::google::protobuf::MethodOptions* options);
+
+  // optional bool client_streaming = 5 [default = false];
+  bool has_client_streaming() const;
+  void clear_client_streaming();
+  static const int kClientStreamingFieldNumber = 5;
+  bool client_streaming() const;
+  void set_client_streaming(bool value);
+
+  // optional bool server_streaming = 6 [default = false];
+  bool has_server_streaming() const;
+  void clear_server_streaming();
+  static const int kServerStreamingFieldNumber = 6;
+  bool server_streaming() const;
+  void set_server_streaming(bool value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
+ private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_input_type();
+  inline void clear_has_input_type();
+  inline void set_has_output_type();
+  inline void clear_has_output_type();
+  inline void set_has_options();
+  inline void clear_has_options();
+  inline void set_has_client_streaming();
+  inline void clear_has_client_streaming();
+  inline void set_has_server_streaming();
+  inline void clear_has_server_streaming();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr input_type_;
+  ::google::protobuf::internal::ArenaStringPtr output_type_;
+  ::google::protobuf::MethodOptions* options_;
+  bool client_streaming_;
+  bool server_streaming_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static MethodDescriptorProto* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
+ public:
+  FileOptions();
+  virtual ~FileOptions();
+
+  FileOptions(const FileOptions& from);
+
+  inline FileOptions& operator=(const FileOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FileOptions& default_instance();
+
+  void Swap(FileOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FileOptions* New() const { return New(NULL); }
+
+  FileOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FileOptions& from);
+  void MergeFrom(const FileOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FileOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef FileOptions_OptimizeMode OptimizeMode;
+  static const OptimizeMode SPEED =
+    FileOptions_OptimizeMode_SPEED;
+  static const OptimizeMode CODE_SIZE =
+    FileOptions_OptimizeMode_CODE_SIZE;
+  static const OptimizeMode LITE_RUNTIME =
+    FileOptions_OptimizeMode_LITE_RUNTIME;
+  static inline bool OptimizeMode_IsValid(int value) {
+    return FileOptions_OptimizeMode_IsValid(value);
+  }
+  static const OptimizeMode OptimizeMode_MIN =
+    FileOptions_OptimizeMode_OptimizeMode_MIN;
+  static const OptimizeMode OptimizeMode_MAX =
+    FileOptions_OptimizeMode_OptimizeMode_MAX;
+  static const int OptimizeMode_ARRAYSIZE =
+    FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  OptimizeMode_descriptor() {
+    return FileOptions_OptimizeMode_descriptor();
+  }
+  static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) {
+    return FileOptions_OptimizeMode_Name(value);
+  }
+  static inline bool OptimizeMode_Parse(const ::std::string& name,
+      OptimizeMode* value) {
+    return FileOptions_OptimizeMode_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // optional string java_package = 1;
+  bool has_java_package() const;
+  void clear_java_package();
+  static const int kJavaPackageFieldNumber = 1;
+  const ::std::string& java_package() const;
+  void set_java_package(const ::std::string& value);
+  void set_java_package(const char* value);
+  void set_java_package(const char* value, size_t size);
+  ::std::string* mutable_java_package();
+  ::std::string* release_java_package();
+  void set_allocated_java_package(::std::string* java_package);
+
+  // optional string java_outer_classname = 8;
+  bool has_java_outer_classname() const;
+  void clear_java_outer_classname();
+  static const int kJavaOuterClassnameFieldNumber = 8;
+  const ::std::string& java_outer_classname() const;
+  void set_java_outer_classname(const ::std::string& value);
+  void set_java_outer_classname(const char* value);
+  void set_java_outer_classname(const char* value, size_t size);
+  ::std::string* mutable_java_outer_classname();
+  ::std::string* release_java_outer_classname();
+  void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+
+  // optional bool java_multiple_files = 10 [default = false];
+  bool has_java_multiple_files() const;
+  void clear_java_multiple_files();
+  static const int kJavaMultipleFilesFieldNumber = 10;
+  bool java_multiple_files() const;
+  void set_java_multiple_files(bool value);
+
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  bool has_java_generate_equals_and_hash() const;
+  void clear_java_generate_equals_and_hash();
+  static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
+  bool java_generate_equals_and_hash() const;
+  void set_java_generate_equals_and_hash(bool value);
+
+  // optional bool java_string_check_utf8 = 27 [default = false];
+  bool has_java_string_check_utf8() const;
+  void clear_java_string_check_utf8();
+  static const int kJavaStringCheckUtf8FieldNumber = 27;
+  bool java_string_check_utf8() const;
+  void set_java_string_check_utf8(bool value);
+
+  // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+  bool has_optimize_for() const;
+  void clear_optimize_for();
+  static const int kOptimizeForFieldNumber = 9;
+  ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
+  void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+
+  // optional string go_package = 11;
+  bool has_go_package() const;
+  void clear_go_package();
+  static const int kGoPackageFieldNumber = 11;
+  const ::std::string& go_package() const;
+  void set_go_package(const ::std::string& value);
+  void set_go_package(const char* value);
+  void set_go_package(const char* value, size_t size);
+  ::std::string* mutable_go_package();
+  ::std::string* release_go_package();
+  void set_allocated_go_package(::std::string* go_package);
+
+  // optional bool cc_generic_services = 16 [default = false];
+  bool has_cc_generic_services() const;
+  void clear_cc_generic_services();
+  static const int kCcGenericServicesFieldNumber = 16;
+  bool cc_generic_services() const;
+  void set_cc_generic_services(bool value);
+
+  // optional bool java_generic_services = 17 [default = false];
+  bool has_java_generic_services() const;
+  void clear_java_generic_services();
+  static const int kJavaGenericServicesFieldNumber = 17;
+  bool java_generic_services() const;
+  void set_java_generic_services(bool value);
+
+  // optional bool py_generic_services = 18 [default = false];
+  bool has_py_generic_services() const;
+  void clear_py_generic_services();
+  static const int kPyGenericServicesFieldNumber = 18;
+  bool py_generic_services() const;
+  void set_py_generic_services(bool value);
+
+  // optional bool deprecated = 23 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 23;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // optional bool cc_enable_arenas = 31 [default = false];
+  bool has_cc_enable_arenas() const;
+  void clear_cc_enable_arenas();
+  static const int kCcEnableArenasFieldNumber = 31;
+  bool cc_enable_arenas() const;
+  void set_cc_enable_arenas(bool value);
+
+  // optional string objc_class_prefix = 36;
+  bool has_objc_class_prefix() const;
+  void clear_objc_class_prefix();
+  static const int kObjcClassPrefixFieldNumber = 36;
+  const ::std::string& objc_class_prefix() const;
+  void set_objc_class_prefix(const ::std::string& value);
+  void set_objc_class_prefix(const char* value);
+  void set_objc_class_prefix(const char* value, size_t size);
+  ::std::string* mutable_objc_class_prefix();
+  ::std::string* release_objc_class_prefix();
+  void set_allocated_objc_class_prefix(::std::string* objc_class_prefix);
+
+  // optional string csharp_namespace = 37;
+  bool has_csharp_namespace() const;
+  void clear_csharp_namespace();
+  static const int kCsharpNamespaceFieldNumber = 37;
+  const ::std::string& csharp_namespace() const;
+  void set_csharp_namespace(const ::std::string& value);
+  void set_csharp_namespace(const char* value);
+  void set_csharp_namespace(const char* value, size_t size);
+  ::std::string* mutable_csharp_namespace();
+  ::std::string* release_csharp_namespace();
+  void set_allocated_csharp_namespace(::std::string* csharp_namespace);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
+ private:
+  inline void set_has_java_package();
+  inline void clear_has_java_package();
+  inline void set_has_java_outer_classname();
+  inline void clear_has_java_outer_classname();
+  inline void set_has_java_multiple_files();
+  inline void clear_has_java_multiple_files();
+  inline void set_has_java_generate_equals_and_hash();
+  inline void clear_has_java_generate_equals_and_hash();
+  inline void set_has_java_string_check_utf8();
+  inline void clear_has_java_string_check_utf8();
+  inline void set_has_optimize_for();
+  inline void clear_has_optimize_for();
+  inline void set_has_go_package();
+  inline void clear_has_go_package();
+  inline void set_has_cc_generic_services();
+  inline void clear_has_cc_generic_services();
+  inline void set_has_java_generic_services();
+  inline void clear_has_java_generic_services();
+  inline void set_has_py_generic_services();
+  inline void clear_has_py_generic_services();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+  inline void set_has_cc_enable_arenas();
+  inline void clear_has_cc_enable_arenas();
+  inline void set_has_objc_class_prefix();
+  inline void clear_has_objc_class_prefix();
+  inline void set_has_csharp_namespace();
+  inline void clear_has_csharp_namespace();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr java_package_;
+  ::google::protobuf::internal::ArenaStringPtr java_outer_classname_;
+  bool java_multiple_files_;
+  bool java_generate_equals_and_hash_;
+  bool java_string_check_utf8_;
+  bool cc_generic_services_;
+  int optimize_for_;
+  ::google::protobuf::internal::ArenaStringPtr go_package_;
+  ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
+  ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool java_generic_services_;
+  bool py_generic_services_;
+  bool deprecated_;
+  bool cc_enable_arenas_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static FileOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
+ public:
+  MessageOptions();
+  virtual ~MessageOptions();
+
+  MessageOptions(const MessageOptions& from);
+
+  inline MessageOptions& operator=(const MessageOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const MessageOptions& default_instance();
+
+  void Swap(MessageOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline MessageOptions* New() const { return New(NULL); }
+
+  MessageOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const MessageOptions& from);
+  void MergeFrom(const MessageOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(MessageOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool message_set_wire_format = 1 [default = false];
+  bool has_message_set_wire_format() const;
+  void clear_message_set_wire_format();
+  static const int kMessageSetWireFormatFieldNumber = 1;
+  bool message_set_wire_format() const;
+  void set_message_set_wire_format(bool value);
+
+  // optional bool no_standard_descriptor_accessor = 2 [default = false];
+  bool has_no_standard_descriptor_accessor() const;
+  void clear_no_standard_descriptor_accessor();
+  static const int kNoStandardDescriptorAccessorFieldNumber = 2;
+  bool no_standard_descriptor_accessor() const;
+  void set_no_standard_descriptor_accessor(bool value);
+
+  // optional bool deprecated = 3 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 3;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // optional bool map_entry = 7;
+  bool has_map_entry() const;
+  void clear_map_entry();
+  static const int kMapEntryFieldNumber = 7;
+  bool map_entry() const;
+  void set_map_entry(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
+ private:
+  inline void set_has_message_set_wire_format();
+  inline void clear_has_message_set_wire_format();
+  inline void set_has_no_standard_descriptor_accessor();
+  inline void clear_has_no_standard_descriptor_accessor();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+  inline void set_has_map_entry();
+  inline void clear_has_map_entry();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool message_set_wire_format_;
+  bool no_standard_descriptor_accessor_;
+  bool deprecated_;
+  bool map_entry_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static MessageOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
+ public:
+  FieldOptions();
+  virtual ~FieldOptions();
+
+  FieldOptions(const FieldOptions& from);
+
+  inline FieldOptions& operator=(const FieldOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FieldOptions& default_instance();
+
+  void Swap(FieldOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FieldOptions* New() const { return New(NULL); }
+
+  FieldOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FieldOptions& from);
+  void MergeFrom(const FieldOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FieldOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef FieldOptions_CType CType;
+  static const CType STRING =
+    FieldOptions_CType_STRING;
+  static const CType CORD =
+    FieldOptions_CType_CORD;
+  static const CType STRING_PIECE =
+    FieldOptions_CType_STRING_PIECE;
+  static inline bool CType_IsValid(int value) {
+    return FieldOptions_CType_IsValid(value);
+  }
+  static const CType CType_MIN =
+    FieldOptions_CType_CType_MIN;
+  static const CType CType_MAX =
+    FieldOptions_CType_CType_MAX;
+  static const int CType_ARRAYSIZE =
+    FieldOptions_CType_CType_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  CType_descriptor() {
+    return FieldOptions_CType_descriptor();
+  }
+  static inline const ::std::string& CType_Name(CType value) {
+    return FieldOptions_CType_Name(value);
+  }
+  static inline bool CType_Parse(const ::std::string& name,
+      CType* value) {
+    return FieldOptions_CType_Parse(name, value);
+  }
+
+  typedef FieldOptions_JSType JSType;
+  static const JSType JS_NORMAL =
+    FieldOptions_JSType_JS_NORMAL;
+  static const JSType JS_STRING =
+    FieldOptions_JSType_JS_STRING;
+  static const JSType JS_NUMBER =
+    FieldOptions_JSType_JS_NUMBER;
+  static inline bool JSType_IsValid(int value) {
+    return FieldOptions_JSType_IsValid(value);
+  }
+  static const JSType JSType_MIN =
+    FieldOptions_JSType_JSType_MIN;
+  static const JSType JSType_MAX =
+    FieldOptions_JSType_JSType_MAX;
+  static const int JSType_ARRAYSIZE =
+    FieldOptions_JSType_JSType_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  JSType_descriptor() {
+    return FieldOptions_JSType_descriptor();
+  }
+  static inline const ::std::string& JSType_Name(JSType value) {
+    return FieldOptions_JSType_Name(value);
+  }
+  static inline bool JSType_Parse(const ::std::string& name,
+      JSType* value) {
+    return FieldOptions_JSType_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+  bool has_ctype() const;
+  void clear_ctype();
+  static const int kCtypeFieldNumber = 1;
+  ::google::protobuf::FieldOptions_CType ctype() const;
+  void set_ctype(::google::protobuf::FieldOptions_CType value);
+
+  // optional bool packed = 2;
+  bool has_packed() const;
+  void clear_packed();
+  static const int kPackedFieldNumber = 2;
+  bool packed() const;
+  void set_packed(bool value);
+
+  // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+  bool has_jstype() const;
+  void clear_jstype();
+  static const int kJstypeFieldNumber = 6;
+  ::google::protobuf::FieldOptions_JSType jstype() const;
+  void set_jstype(::google::protobuf::FieldOptions_JSType value);
+
+  // optional bool lazy = 5 [default = false];
+  bool has_lazy() const;
+  void clear_lazy();
+  static const int kLazyFieldNumber = 5;
+  bool lazy() const;
+  void set_lazy(bool value);
+
+  // optional bool deprecated = 3 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 3;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // optional bool weak = 10 [default = false];
+  bool has_weak() const;
+  void clear_weak();
+  static const int kWeakFieldNumber = 10;
+  bool weak() const;
+  void set_weak(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
+ private:
+  inline void set_has_ctype();
+  inline void clear_has_ctype();
+  inline void set_has_packed();
+  inline void clear_has_packed();
+  inline void set_has_jstype();
+  inline void clear_has_jstype();
+  inline void set_has_lazy();
+  inline void clear_has_lazy();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+  inline void set_has_weak();
+  inline void clear_has_weak();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  int ctype_;
+  int jstype_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool packed_;
+  bool lazy_;
+  bool deprecated_;
+  bool weak_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static FieldOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
+ public:
+  EnumOptions();
+  virtual ~EnumOptions();
+
+  EnumOptions(const EnumOptions& from);
+
+  inline EnumOptions& operator=(const EnumOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const EnumOptions& default_instance();
+
+  void Swap(EnumOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline EnumOptions* New() const { return New(NULL); }
+
+  EnumOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const EnumOptions& from);
+  void MergeFrom(const EnumOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(EnumOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool allow_alias = 2;
+  bool has_allow_alias() const;
+  void clear_allow_alias();
+  static const int kAllowAliasFieldNumber = 2;
+  bool allow_alias() const;
+  void set_allow_alias(bool value);
+
+  // optional bool deprecated = 3 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 3;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
+ private:
+  inline void set_has_allow_alias();
+  inline void clear_has_allow_alias();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool allow_alias_;
+  bool deprecated_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static EnumOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
+ public:
+  EnumValueOptions();
+  virtual ~EnumValueOptions();
+
+  EnumValueOptions(const EnumValueOptions& from);
+
+  inline EnumValueOptions& operator=(const EnumValueOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const EnumValueOptions& default_instance();
+
+  void Swap(EnumValueOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline EnumValueOptions* New() const { return New(NULL); }
+
+  EnumValueOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const EnumValueOptions& from);
+  void MergeFrom(const EnumValueOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(EnumValueOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool deprecated = 1 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 1;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
+ private:
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool deprecated_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static EnumValueOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
+ public:
+  ServiceOptions();
+  virtual ~ServiceOptions();
+
+  ServiceOptions(const ServiceOptions& from);
+
+  inline ServiceOptions& operator=(const ServiceOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const ServiceOptions& default_instance();
+
+  void Swap(ServiceOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline ServiceOptions* New() const { return New(NULL); }
+
+  ServiceOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const ServiceOptions& from);
+  void MergeFrom(const ServiceOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(ServiceOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool deprecated = 33 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 33;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
+ private:
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool deprecated_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static ServiceOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
+ public:
+  MethodOptions();
+  virtual ~MethodOptions();
+
+  MethodOptions(const MethodOptions& from);
+
+  inline MethodOptions& operator=(const MethodOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const MethodOptions& default_instance();
+
+  void Swap(MethodOptions* other);
+
+  // implements Message ----------------------------------------------
+
+  inline MethodOptions* New() const { return New(NULL); }
+
+  MethodOptions* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const MethodOptions& from);
+  void MergeFrom(const MethodOptions& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(MethodOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool deprecated = 33 [default = false];
+  bool has_deprecated() const;
+  void clear_deprecated();
+  static const int kDeprecatedFieldNumber = 33;
+  bool deprecated() const;
+  void set_deprecated(bool value);
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
+ private:
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool deprecated_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static MethodOptions* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobuf::Message {
+ public:
+  UninterpretedOption_NamePart();
+  virtual ~UninterpretedOption_NamePart();
+
+  UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
+
+  inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const UninterpretedOption_NamePart& default_instance();
+
+  void Swap(UninterpretedOption_NamePart* other);
+
+  // implements Message ----------------------------------------------
+
+  inline UninterpretedOption_NamePart* New() const { return New(NULL); }
+
+  UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const UninterpretedOption_NamePart& from);
+  void MergeFrom(const UninterpretedOption_NamePart& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(UninterpretedOption_NamePart* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required string name_part = 1;
+  bool has_name_part() const;
+  void clear_name_part();
+  static const int kNamePartFieldNumber = 1;
+  const ::std::string& name_part() const;
+  void set_name_part(const ::std::string& value);
+  void set_name_part(const char* value);
+  void set_name_part(const char* value, size_t size);
+  ::std::string* mutable_name_part();
+  ::std::string* release_name_part();
+  void set_allocated_name_part(::std::string* name_part);
+
+  // required bool is_extension = 2;
+  bool has_is_extension() const;
+  void clear_is_extension();
+  static const int kIsExtensionFieldNumber = 2;
+  bool is_extension() const;
+  void set_is_extension(bool value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
+ private:
+  inline void set_has_name_part();
+  inline void clear_has_name_part();
+  inline void set_has_is_extension();
+  inline void clear_has_is_extension();
+
+  // helper for ByteSize()
+  int RequiredFieldsByteSizeFallback() const;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr name_part_;
+  bool is_extension_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static UninterpretedOption_NamePart* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Message {
+ public:
+  UninterpretedOption();
+  virtual ~UninterpretedOption();
+
+  UninterpretedOption(const UninterpretedOption& from);
+
+  inline UninterpretedOption& operator=(const UninterpretedOption& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const UninterpretedOption& default_instance();
+
+  void Swap(UninterpretedOption* other);
+
+  // implements Message ----------------------------------------------
+
+  inline UninterpretedOption* New() const { return New(NULL); }
+
+  UninterpretedOption* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const UninterpretedOption& from);
+  void MergeFrom(const UninterpretedOption& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(UninterpretedOption* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef UninterpretedOption_NamePart NamePart;
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+  int name_size() const;
+  void clear_name();
+  static const int kNameFieldNumber = 2;
+  const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
+  ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
+  ::google::protobuf::UninterpretedOption_NamePart* add_name();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+      mutable_name();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+      name() const;
+
+  // optional string identifier_value = 3;
+  bool has_identifier_value() const;
+  void clear_identifier_value();
+  static const int kIdentifierValueFieldNumber = 3;
+  const ::std::string& identifier_value() const;
+  void set_identifier_value(const ::std::string& value);
+  void set_identifier_value(const char* value);
+  void set_identifier_value(const char* value, size_t size);
+  ::std::string* mutable_identifier_value();
+  ::std::string* release_identifier_value();
+  void set_allocated_identifier_value(::std::string* identifier_value);
+
+  // optional uint64 positive_int_value = 4;
+  bool has_positive_int_value() const;
+  void clear_positive_int_value();
+  static const int kPositiveIntValueFieldNumber = 4;
+  ::google::protobuf::uint64 positive_int_value() const;
+  void set_positive_int_value(::google::protobuf::uint64 value);
+
+  // optional int64 negative_int_value = 5;
+  bool has_negative_int_value() const;
+  void clear_negative_int_value();
+  static const int kNegativeIntValueFieldNumber = 5;
+  ::google::protobuf::int64 negative_int_value() const;
+  void set_negative_int_value(::google::protobuf::int64 value);
+
+  // optional double double_value = 6;
+  bool has_double_value() const;
+  void clear_double_value();
+  static const int kDoubleValueFieldNumber = 6;
+  double double_value() const;
+  void set_double_value(double value);
+
+  // optional bytes string_value = 7;
+  bool has_string_value() const;
+  void clear_string_value();
+  static const int kStringValueFieldNumber = 7;
+  const ::std::string& string_value() const;
+  void set_string_value(const ::std::string& value);
+  void set_string_value(const char* value);
+  void set_string_value(const void* value, size_t size);
+  ::std::string* mutable_string_value();
+  ::std::string* release_string_value();
+  void set_allocated_string_value(::std::string* string_value);
+
+  // optional string aggregate_value = 8;
+  bool has_aggregate_value() const;
+  void clear_aggregate_value();
+  static const int kAggregateValueFieldNumber = 8;
+  const ::std::string& aggregate_value() const;
+  void set_aggregate_value(const ::std::string& value);
+  void set_aggregate_value(const char* value);
+  void set_aggregate_value(const char* value, size_t size);
+  ::std::string* mutable_aggregate_value();
+  ::std::string* release_aggregate_value();
+  void set_allocated_aggregate_value(::std::string* aggregate_value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
+ private:
+  inline void set_has_identifier_value();
+  inline void clear_has_identifier_value();
+  inline void set_has_positive_int_value();
+  inline void clear_has_positive_int_value();
+  inline void set_has_negative_int_value();
+  inline void clear_has_negative_int_value();
+  inline void set_has_double_value();
+  inline void clear_has_double_value();
+  inline void set_has_string_value();
+  inline void clear_has_string_value();
+  inline void set_has_aggregate_value();
+  inline void clear_has_aggregate_value();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
+  ::google::protobuf::internal::ArenaStringPtr identifier_value_;
+  ::google::protobuf::uint64 positive_int_value_;
+  ::google::protobuf::int64 negative_int_value_;
+  double double_value_;
+  ::google::protobuf::internal::ArenaStringPtr string_value_;
+  ::google::protobuf::internal::ArenaStringPtr aggregate_value_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static UninterpretedOption* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo_Location();
+  virtual ~SourceCodeInfo_Location();
+
+  SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
+
+  inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo_Location& default_instance();
+
+  void Swap(SourceCodeInfo_Location* other);
+
+  // implements Message ----------------------------------------------
+
+  inline SourceCodeInfo_Location* New() const { return New(NULL); }
+
+  SourceCodeInfo_Location* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo_Location& from);
+  void MergeFrom(const SourceCodeInfo_Location& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(SourceCodeInfo_Location* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated int32 path = 1 [packed = true];
+  int path_size() const;
+  void clear_path();
+  static const int kPathFieldNumber = 1;
+  ::google::protobuf::int32 path(int index) const;
+  void set_path(int index, ::google::protobuf::int32 value);
+  void add_path(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      path() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_path();
+
+  // repeated int32 span = 2 [packed = true];
+  int span_size() const;
+  void clear_span();
+  static const int kSpanFieldNumber = 2;
+  ::google::protobuf::int32 span(int index) const;
+  void set_span(int index, ::google::protobuf::int32 value);
+  void add_span(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      span() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_span();
+
+  // optional string leading_comments = 3;
+  bool has_leading_comments() const;
+  void clear_leading_comments();
+  static const int kLeadingCommentsFieldNumber = 3;
+  const ::std::string& leading_comments() const;
+  void set_leading_comments(const ::std::string& value);
+  void set_leading_comments(const char* value);
+  void set_leading_comments(const char* value, size_t size);
+  ::std::string* mutable_leading_comments();
+  ::std::string* release_leading_comments();
+  void set_allocated_leading_comments(::std::string* leading_comments);
+
+  // optional string trailing_comments = 4;
+  bool has_trailing_comments() const;
+  void clear_trailing_comments();
+  static const int kTrailingCommentsFieldNumber = 4;
+  const ::std::string& trailing_comments() const;
+  void set_trailing_comments(const ::std::string& value);
+  void set_trailing_comments(const char* value);
+  void set_trailing_comments(const char* value, size_t size);
+  ::std::string* mutable_trailing_comments();
+  ::std::string* release_trailing_comments();
+  void set_allocated_trailing_comments(::std::string* trailing_comments);
+
+  // repeated string leading_detached_comments = 6;
+  int leading_detached_comments_size() const;
+  void clear_leading_detached_comments();
+  static const int kLeadingDetachedCommentsFieldNumber = 6;
+  const ::std::string& leading_detached_comments(int index) const;
+  ::std::string* mutable_leading_detached_comments(int index);
+  void set_leading_detached_comments(int index, const ::std::string& value);
+  void set_leading_detached_comments(int index, const char* value);
+  void set_leading_detached_comments(int index, const char* value, size_t size);
+  ::std::string* add_leading_detached_comments();
+  void add_leading_detached_comments(const ::std::string& value);
+  void add_leading_detached_comments(const char* value);
+  void add_leading_detached_comments(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments();
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
+ private:
+  inline void set_has_leading_comments();
+  inline void clear_has_leading_comments();
+  inline void set_has_trailing_comments();
+  inline void clear_has_trailing_comments();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
+  mutable int _path_cached_byte_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_;
+  mutable int _span_cached_byte_size_;
+  ::google::protobuf::internal::ArenaStringPtr leading_comments_;
+  ::google::protobuf::internal::ArenaStringPtr trailing_comments_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static SourceCodeInfo_Location* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo();
+  virtual ~SourceCodeInfo();
+
+  SourceCodeInfo(const SourceCodeInfo& from);
+
+  inline SourceCodeInfo& operator=(const SourceCodeInfo& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo& default_instance();
+
+  void Swap(SourceCodeInfo* other);
+
+  // implements Message ----------------------------------------------
+
+  inline SourceCodeInfo* New() const { return New(NULL); }
+
+  SourceCodeInfo* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo& from);
+  void MergeFrom(const SourceCodeInfo& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(SourceCodeInfo* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef SourceCodeInfo_Location Location;
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  int location_size() const;
+  void clear_location();
+  static const int kLocationFieldNumber = 1;
+  const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+  ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+  ::google::protobuf::SourceCodeInfo_Location* add_location();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+      mutable_location();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+      location() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static SourceCodeInfo* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT GeneratedCodeInfo_Annotation : public ::google::protobuf::Message {
+ public:
+  GeneratedCodeInfo_Annotation();
+  virtual ~GeneratedCodeInfo_Annotation();
+
+  GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
+
+  inline GeneratedCodeInfo_Annotation& operator=(const GeneratedCodeInfo_Annotation& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const GeneratedCodeInfo_Annotation& default_instance();
+
+  void Swap(GeneratedCodeInfo_Annotation* other);
+
+  // implements Message ----------------------------------------------
+
+  inline GeneratedCodeInfo_Annotation* New() const { return New(NULL); }
+
+  GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const GeneratedCodeInfo_Annotation& from);
+  void MergeFrom(const GeneratedCodeInfo_Annotation& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(GeneratedCodeInfo_Annotation* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated int32 path = 1 [packed = true];
+  int path_size() const;
+  void clear_path();
+  static const int kPathFieldNumber = 1;
+  ::google::protobuf::int32 path(int index) const;
+  void set_path(int index, ::google::protobuf::int32 value);
+  void add_path(::google::protobuf::int32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      path() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_path();
+
+  // optional string source_file = 2;
+  bool has_source_file() const;
+  void clear_source_file();
+  static const int kSourceFileFieldNumber = 2;
+  const ::std::string& source_file() const;
+  void set_source_file(const ::std::string& value);
+  void set_source_file(const char* value);
+  void set_source_file(const char* value, size_t size);
+  ::std::string* mutable_source_file();
+  ::std::string* release_source_file();
+  void set_allocated_source_file(::std::string* source_file);
+
+  // optional int32 begin = 3;
+  bool has_begin() const;
+  void clear_begin();
+  static const int kBeginFieldNumber = 3;
+  ::google::protobuf::int32 begin() const;
+  void set_begin(::google::protobuf::int32 value);
+
+  // optional int32 end = 4;
+  bool has_end() const;
+  void clear_end();
+  static const int kEndFieldNumber = 4;
+  ::google::protobuf::int32 end() const;
+  void set_end(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation)
+ private:
+  inline void set_has_source_file();
+  inline void clear_has_source_file();
+  inline void set_has_begin();
+  inline void clear_has_begin();
+  inline void set_has_end();
+  inline void clear_has_end();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
+  mutable int _path_cached_byte_size_;
+  ::google::protobuf::internal::ArenaStringPtr source_file_;
+  ::google::protobuf::int32 begin_;
+  ::google::protobuf::int32 end_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static GeneratedCodeInfo_Annotation* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT GeneratedCodeInfo : public ::google::protobuf::Message {
+ public:
+  GeneratedCodeInfo();
+  virtual ~GeneratedCodeInfo();
+
+  GeneratedCodeInfo(const GeneratedCodeInfo& from);
+
+  inline GeneratedCodeInfo& operator=(const GeneratedCodeInfo& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const GeneratedCodeInfo& default_instance();
+
+  void Swap(GeneratedCodeInfo* other);
+
+  // implements Message ----------------------------------------------
+
+  inline GeneratedCodeInfo* New() const { return New(NULL); }
+
+  GeneratedCodeInfo* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const GeneratedCodeInfo& from);
+  void MergeFrom(const GeneratedCodeInfo& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(GeneratedCodeInfo* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef GeneratedCodeInfo_Annotation Annotation;
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+  int annotation_size() const;
+  void clear_annotation();
+  static const int kAnnotationFieldNumber = 1;
+  const ::google::protobuf::GeneratedCodeInfo_Annotation& annotation(int index) const;
+  ::google::protobuf::GeneratedCodeInfo_Annotation* mutable_annotation(int index);
+  ::google::protobuf::GeneratedCodeInfo_Annotation* add_annotation();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+      mutable_annotation();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+      annotation() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation > annotation_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+  void InitAsDefaultInstance();
+  static GeneratedCodeInfo* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorSet
+
+// repeated .google.protobuf.FileDescriptorProto file = 1;
+inline int FileDescriptorSet::file_size() const {
+  return file_.size();
+}
+inline void FileDescriptorSet::clear_file() {
+  file_.Clear();
+}
+inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
+  return file_.Get(index);
+}
+inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
+  return file_.Mutable(index);
+}
+inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
+  return file_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
+  return &file_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+  return file_;
+}
+
+// -------------------------------------------------------------------
+
+// FileDescriptorProto
+
+// optional string name = 1;
+inline bool FileDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void FileDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& FileDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
+}
+inline void FileDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
+}
+inline void FileDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+}
+inline ::std::string* FileDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+
+// optional string package = 2;
+inline bool FileDescriptorProto::has_package() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileDescriptorProto::set_has_package() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileDescriptorProto::clear_has_package() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void FileDescriptorProto::clear_package() {
+  package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_package();
+}
+inline const ::std::string& FileDescriptorProto::package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
+  return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_package(const ::std::string& value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
+}
+inline void FileDescriptorProto::set_package(const char* value) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
+}
+inline void FileDescriptorProto::set_package(const char* value, size_t size) {
+  set_has_package();
+  package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+}
+inline ::std::string* FileDescriptorProto::mutable_package() {
+  set_has_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
+  return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileDescriptorProto::release_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
+  clear_has_package();
+  return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_allocated_package(::std::string* package) {
+  if (package != NULL) {
+    set_has_package();
+  } else {
+    clear_has_package();
+  }
+  package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+
+// repeated string dependency = 3;
+inline int FileDescriptorProto::dependency_size() const {
+  return dependency_.size();
+}
+inline void FileDescriptorProto::clear_dependency() {
+  dependency_.Clear();
+}
+inline const ::std::string& FileDescriptorProto::dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Get(index);
+}
+inline ::std::string* FileDescriptorProto::mutable_dependency(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Mutable(index);
+}
+inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
+  dependency_.Mutable(index)->assign(value);
+}
+inline void FileDescriptorProto::set_dependency(int index, const char* value) {
+  dependency_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
+}
+inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+  dependency_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+inline ::std::string* FileDescriptorProto::add_dependency() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_.Add();
+}
+inline void FileDescriptorProto::add_dependency(const ::std::string& value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
+}
+inline void FileDescriptorProto::add_dependency(const char* value) {
+  dependency_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
+}
+inline void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+  dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency)
+  return dependency_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency)
+  return &dependency_;
+}
+
+// repeated int32 public_dependency = 10;
+inline int FileDescriptorProto::public_dependency_size() const {
+  return public_dependency_.size();
+}
+inline void FileDescriptorProto::clear_public_dependency() {
+  public_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+  public_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
+}
+inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+  public_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return public_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
+  return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+inline int FileDescriptorProto::weak_dependency_size() const {
+  return weak_dependency_.size();
+}
+inline void FileDescriptorProto::clear_weak_dependency() {
+  weak_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+  weak_dependency_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+  weak_dependency_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return weak_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
+  return &weak_dependency_;
+}
+
+// repeated .google.protobuf.DescriptorProto message_type = 4;
+inline int FileDescriptorProto::message_type_size() const {
+  return message_type_.size();
+}
+inline void FileDescriptorProto::clear_message_type() {
+  message_type_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
+  return &message_type_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+  return message_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+inline int FileDescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+inline void FileDescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
+  return &enum_type_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+  return enum_type_;
+}
+
+// repeated .google.protobuf.ServiceDescriptorProto service = 6;
+inline int FileDescriptorProto::service_size() const {
+  return service_.size();
+}
+inline void FileDescriptorProto::clear_service() {
+  service_.Clear();
+}
+inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
+  return service_.Get(index);
+}
+inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
+  return service_.Mutable(index);
+}
+inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
+  return service_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
+  return &service_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+  return service_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 7;
+inline int FileDescriptorProto::extension_size() const {
+  return extension_.size();
+}
+inline void FileDescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Get(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
+  return extension_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
+  return &extension_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+  return extension_;
+}
+
+// optional .google.protobuf.FileOptions options = 8;
+inline bool FileDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+inline void FileDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000200u;
+}
+inline void FileDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+inline void FileDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FileOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::FileOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+inline bool FileDescriptorProto::has_source_code_info() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+inline void FileDescriptorProto::set_has_source_code_info() {
+  _has_bits_[0] |= 0x00000400u;
+}
+inline void FileDescriptorProto::clear_has_source_code_info() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+inline void FileDescriptorProto::clear_source_code_info() {
+  if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+  clear_has_source_code_info();
+}
+inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  set_has_source_code_info();
+  if (source_code_info_ == NULL) {
+    source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
+  return source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info)
+  clear_has_source_code_info();
+  ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = NULL;
+  return temp;
+}
+inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+  delete source_code_info_;
+  source_code_info_ = source_code_info;
+  if (source_code_info) {
+    set_has_source_code_info();
+  } else {
+    clear_has_source_code_info();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+inline bool FileDescriptorProto::has_syntax() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+inline void FileDescriptorProto::set_has_syntax() {
+  _has_bits_[0] |= 0x00000800u;
+}
+inline void FileDescriptorProto::clear_has_syntax() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+inline void FileDescriptorProto::clear_syntax() {
+  syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_syntax();
+}
+inline const ::std::string& FileDescriptorProto::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_syntax(const ::std::string& value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+inline void FileDescriptorProto::set_syntax(const char* value) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+inline void FileDescriptorProto::set_syntax(const char* value, size_t size) {
+  set_has_syntax();
+  syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+inline ::std::string* FileDescriptorProto::mutable_syntax() {
+  set_has_syntax();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+  return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileDescriptorProto::release_syntax() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
+  clear_has_syntax();
+  return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+  if (syntax != NULL) {
+    set_has_syntax();
+  } else {
+    clear_has_syntax();
+  }
+  syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto_ExtensionRange
+
+// optional int32 start = 1;
+inline bool DescriptorProto_ExtensionRange::has_start() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_start() {
+  start_ = 0;
+  clear_has_start();
+}
+inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
+  return start_;
+}
+inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
+  set_has_start();
+  start_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
+}
+
+// optional int32 end = 2;
+inline bool DescriptorProto_ExtensionRange::has_end() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void DescriptorProto_ExtensionRange::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
+  return end_;
+}
+inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+inline bool DescriptorProto_ReservedRange::has_start() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_start() {
+  start_ = 0;
+  clear_has_start();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+  return start_;
+}
+inline void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+  set_has_start();
+  start_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+inline bool DescriptorProto_ReservedRange::has_end() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+  return end_;
+}
+inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto
+
+// optional string name = 1;
+inline bool DescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& DescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void DescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
+}
+inline void DescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
+}
+inline void DescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+}
+inline ::std::string* DescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* DescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void DescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+
+// repeated .google.protobuf.FieldDescriptorProto field = 2;
+inline int DescriptorProto::field_size() const {
+  return field_.size();
+}
+inline void DescriptorProto::clear_field() {
+  field_.Clear();
+}
+inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
+  return field_.Get(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
+  return field_.Mutable(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
+  return field_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
+  return &field_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+  return field_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 6;
+inline int DescriptorProto::extension_size() const {
+  return extension_.size();
+}
+inline void DescriptorProto::clear_extension() {
+  extension_.Clear();
+}
+inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
+  return extension_.Get(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
+  return extension_.Mutable(index);
+}
+inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
+  return extension_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
+  return &extension_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+  return extension_;
+}
+
+// repeated .google.protobuf.DescriptorProto nested_type = 3;
+inline int DescriptorProto::nested_type_size() const {
+  return nested_type_.size();
+}
+inline void DescriptorProto::clear_nested_type() {
+  nested_type_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
+  return &nested_type_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+  return nested_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+inline int DescriptorProto::enum_type_size() const {
+  return enum_type_.size();
+}
+inline void DescriptorProto::clear_enum_type() {
+  enum_type_.Clear();
+}
+inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Get(index);
+}
+inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Mutable(index);
+}
+inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
+  return &enum_type_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+  return enum_type_;
+}
+
+// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+inline int DescriptorProto::extension_range_size() const {
+  return extension_range_.size();
+}
+inline void DescriptorProto::clear_extension_range() {
+  extension_range_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
+  return &extension_range_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+  return extension_range_;
+}
+
+// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+inline int DescriptorProto::oneof_decl_size() const {
+  return oneof_decl_.size();
+}
+inline void DescriptorProto::clear_oneof_decl() {
+  oneof_decl_.Clear();
+}
+inline const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Get(index);
+}
+inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Mutable(index);
+}
+inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+DescriptorProto::mutable_oneof_decl() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
+  return &oneof_decl_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+  return oneof_decl_;
+}
+
+// optional .google.protobuf.MessageOptions options = 7;
+inline bool DescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void DescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void DescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void DescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MessageOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::MessageOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
+}
+
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+inline int DescriptorProto::reserved_range_size() const {
+  return reserved_range_.size();
+}
+inline void DescriptorProto::clear_reserved_range() {
+  reserved_range_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+  return &reserved_range_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+  return reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+inline int DescriptorProto::reserved_name_size() const {
+  return reserved_name_.size();
+}
+inline void DescriptorProto::clear_reserved_name() {
+  reserved_name_.Clear();
+}
+inline const ::std::string& DescriptorProto::reserved_name(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Get(index);
+}
+inline ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Mutable(index);
+}
+inline void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+  reserved_name_.Mutable(index)->assign(value);
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value) {
+  reserved_name_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+  reserved_name_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline ::std::string* DescriptorProto::add_reserved_name() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_.Add();
+}
+inline void DescriptorProto::add_reserved_name(const ::std::string& value) {
+  reserved_name_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value) {
+  reserved_name_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+  reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+  return reserved_name_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+  return &reserved_name_;
+}
+
+// -------------------------------------------------------------------
+
+// FieldDescriptorProto
+
+// optional string name = 1;
+inline bool FieldDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void FieldDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& FieldDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
+}
+inline void FieldDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
+}
+inline void FieldDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+}
+inline ::std::string* FieldDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+
+// optional int32 number = 3;
+inline bool FieldDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void FieldDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+inline ::google::protobuf::int32 FieldDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
+  return number_;
+}
+inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+inline bool FieldDescriptorProto::has_label() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldDescriptorProto::set_has_label() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldDescriptorProto::clear_has_label() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void FieldDescriptorProto::clear_label() {
+  label_ = 1;
+  clear_has_label();
+}
+inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
+}
+inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
+  assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+  set_has_label();
+  label_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+inline bool FieldDescriptorProto::has_type() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldDescriptorProto::clear_has_type() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void FieldDescriptorProto::clear_type() {
+  type_ = 1;
+  clear_has_type();
+}
+inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type)
+  return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
+}
+inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
+  assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+  set_has_type();
+  type_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type)
+}
+
+// optional string type_name = 6;
+inline bool FieldDescriptorProto::has_type_name() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type_name() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FieldDescriptorProto::clear_has_type_name() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void FieldDescriptorProto::clear_type_name() {
+  type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_type_name();
+}
+inline const ::std::string& FieldDescriptorProto::type_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_type_name(const ::std::string& value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
+}
+inline void FieldDescriptorProto::set_type_name(const char* value) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
+}
+inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+  set_has_type_name();
+  type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+}
+inline ::std::string* FieldDescriptorProto::mutable_type_name() {
+  set_has_type_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
+  return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_type_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
+  clear_has_type_name();
+  return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+  if (type_name != NULL) {
+    set_has_type_name();
+  } else {
+    clear_has_type_name();
+  }
+  type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+
+// optional string extendee = 2;
+inline bool FieldDescriptorProto::has_extendee() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldDescriptorProto::set_has_extendee() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldDescriptorProto::clear_has_extendee() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void FieldDescriptorProto::clear_extendee() {
+  extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_extendee();
+}
+inline const ::std::string& FieldDescriptorProto::extendee() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_extendee(const ::std::string& value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
+}
+inline void FieldDescriptorProto::set_extendee(const char* value) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
+}
+inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+  set_has_extendee();
+  extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+}
+inline ::std::string* FieldDescriptorProto::mutable_extendee() {
+  set_has_extendee();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
+  return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_extendee() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
+  clear_has_extendee();
+  return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+  if (extendee != NULL) {
+    set_has_extendee();
+  } else {
+    clear_has_extendee();
+  }
+  extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+
+// optional string default_value = 7;
+inline bool FieldDescriptorProto::has_default_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FieldDescriptorProto::set_has_default_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FieldDescriptorProto::clear_has_default_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void FieldDescriptorProto::clear_default_value() {
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_default_value();
+}
+inline const ::std::string& FieldDescriptorProto::default_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_default_value(const ::std::string& value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
+}
+inline void FieldDescriptorProto::set_default_value(const char* value) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
+}
+inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+  set_has_default_value();
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+}
+inline ::std::string* FieldDescriptorProto::mutable_default_value() {
+  set_has_default_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
+  return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_default_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
+  clear_has_default_value();
+  return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+  if (default_value != NULL) {
+    set_has_default_value();
+  } else {
+    clear_has_default_value();
+  }
+  default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+
+// optional int32 oneof_index = 9;
+inline bool FieldDescriptorProto::has_oneof_index() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FieldDescriptorProto::set_has_oneof_index() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FieldDescriptorProto::clear_has_oneof_index() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void FieldDescriptorProto::clear_oneof_index() {
+  oneof_index_ = 0;
+  clear_has_oneof_index();
+}
+inline ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
+  return oneof_index_;
+}
+inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) {
+  set_has_oneof_index();
+  oneof_index_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
+}
+
+// optional string json_name = 10;
+inline bool FieldDescriptorProto::has_json_name() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void FieldDescriptorProto::set_has_json_name() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void FieldDescriptorProto::clear_has_json_name() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void FieldDescriptorProto::clear_json_name() {
+  json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_json_name();
+}
+inline const ::std::string& FieldDescriptorProto::json_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
+  return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_json_name(const ::std::string& value) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline void FieldDescriptorProto::set_json_name(const char* value) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
+  set_has_json_name();
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline ::std::string* FieldDescriptorProto::mutable_json_name() {
+  set_has_json_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
+  return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_json_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
+  clear_has_json_name();
+  return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
+  if (json_name != NULL) {
+    set_has_json_name();
+  } else {
+    clear_has_json_name();
+  }
+  json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
+}
+
+// optional .google.protobuf.FieldOptions options = 8;
+inline bool FieldDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+inline void FieldDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000200u;
+}
+inline void FieldDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+inline void FieldDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::FieldOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::FieldOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+// -------------------------------------------------------------------
+
+// OneofDescriptorProto
+
+// optional string name = 1;
+inline bool OneofDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void OneofDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void OneofDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void OneofDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& OneofDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void OneofDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
+}
+inline void OneofDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
+}
+inline void OneofDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+}
+inline ::std::string* OneofDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* OneofDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void OneofDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+
+// -------------------------------------------------------------------
+
+// EnumDescriptorProto
+
+// optional string name = 1;
+inline bool EnumDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& EnumDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
+}
+inline void EnumDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
+}
+inline void EnumDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+}
+inline ::std::string* EnumDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EnumDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+
+// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+inline int EnumDescriptorProto::value_size() const {
+  return value_.size();
+}
+inline void EnumDescriptorProto::clear_value() {
+  value_.Clear();
+}
+inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
+  return value_.Get(index);
+}
+inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
+  return value_.Mutable(index);
+}
+inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
+  return value_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
+  return &value_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+  return value_;
+}
+
+// optional .google.protobuf.EnumOptions options = 3;
+inline bool EnumDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void EnumDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::EnumOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
+
+// -------------------------------------------------------------------
+
+// EnumValueDescriptorProto
+
+// optional string name = 1;
+inline bool EnumValueDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumValueDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumValueDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& EnumValueDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValueDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
+}
+inline void EnumValueDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
+}
+inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+}
+inline ::std::string* EnumValueDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EnumValueDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+
+// optional int32 number = 2;
+inline bool EnumValueDescriptorProto::has_number() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void EnumValueDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void EnumValueDescriptorProto::clear_number() {
+  number_ = 0;
+  clear_has_number();
+}
+inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
+  return number_;
+}
+inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
+  set_has_number();
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
+}
+
+// optional .google.protobuf.EnumValueOptions options = 3;
+inline bool EnumValueDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumValueDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void EnumValueDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::EnumValueOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::EnumValueOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
+
+// -------------------------------------------------------------------
+
+// ServiceDescriptorProto
+
+// optional string name = 1;
+inline bool ServiceDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void ServiceDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void ServiceDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& ServiceDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ServiceDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
+}
+inline void ServiceDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
+}
+inline void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+}
+inline ::std::string* ServiceDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ServiceDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+
+// repeated .google.protobuf.MethodDescriptorProto method = 2;
+inline int ServiceDescriptorProto::method_size() const {
+  return method_.size();
+}
+inline void ServiceDescriptorProto::clear_method() {
+  method_.Clear();
+}
+inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Get(index);
+}
+inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Mutable(index);
+}
+inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
+  return method_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
+  return &method_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+  return method_;
+}
+
+// optional .google.protobuf.ServiceOptions options = 3;
+inline bool ServiceDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void ServiceDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void ServiceDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::ServiceOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::ServiceOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
+
+// -------------------------------------------------------------------
+
+// MethodDescriptorProto
+
+// optional string name = 1;
+inline bool MethodDescriptorProto::has_name() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MethodDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MethodDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MethodDescriptorProto::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name();
+}
+inline const ::std::string& MethodDescriptorProto::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_name(const ::std::string& value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
+}
+inline void MethodDescriptorProto::set_name(const char* value) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
+}
+inline void MethodDescriptorProto::set_name(const char* value, size_t size) {
+  set_has_name();
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+}
+inline ::std::string* MethodDescriptorProto::mutable_name() {
+  set_has_name();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* MethodDescriptorProto::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
+  clear_has_name();
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    set_has_name();
+  } else {
+    clear_has_name();
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+
+// optional string input_type = 2;
+inline bool MethodDescriptorProto::has_input_type() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MethodDescriptorProto::set_has_input_type() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MethodDescriptorProto::clear_has_input_type() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void MethodDescriptorProto::clear_input_type() {
+  input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_input_type();
+}
+inline const ::std::string& MethodDescriptorProto::input_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_input_type(const ::std::string& value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
+}
+inline void MethodDescriptorProto::set_input_type(const char* value) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
+}
+inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+  set_has_input_type();
+  input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+}
+inline ::std::string* MethodDescriptorProto::mutable_input_type() {
+  set_has_input_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
+  return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* MethodDescriptorProto::release_input_type() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
+  clear_has_input_type();
+  return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+  if (input_type != NULL) {
+    set_has_input_type();
+  } else {
+    clear_has_input_type();
+  }
+  input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+
+// optional string output_type = 3;
+inline bool MethodDescriptorProto::has_output_type() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void MethodDescriptorProto::set_has_output_type() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void MethodDescriptorProto::clear_has_output_type() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void MethodDescriptorProto::clear_output_type() {
+  output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_output_type();
+}
+inline const ::std::string& MethodDescriptorProto::output_type() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_output_type(const ::std::string& value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
+}
+inline void MethodDescriptorProto::set_output_type(const char* value) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
+}
+inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+  set_has_output_type();
+  output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+}
+inline ::std::string* MethodDescriptorProto::mutable_output_type() {
+  set_has_output_type();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
+  return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* MethodDescriptorProto::release_output_type() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
+  clear_has_output_type();
+  return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+  if (output_type != NULL) {
+    set_has_output_type();
+  } else {
+    clear_has_output_type();
+  }
+  output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+
+// optional .google.protobuf.MethodOptions options = 4;
+inline bool MethodDescriptorProto::has_options() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void MethodDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void MethodDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void MethodDescriptorProto::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
+  return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::MethodOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
+  return options_;
+}
+inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options)
+  clear_has_options();
+  ::google::protobuf::MethodOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
+
+// optional bool client_streaming = 5 [default = false];
+inline bool MethodDescriptorProto::has_client_streaming() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void MethodDescriptorProto::set_has_client_streaming() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void MethodDescriptorProto::clear_has_client_streaming() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void MethodDescriptorProto::clear_client_streaming() {
+  client_streaming_ = false;
+  clear_has_client_streaming();
+}
+inline bool MethodDescriptorProto::client_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming)
+  return client_streaming_;
+}
+inline void MethodDescriptorProto::set_client_streaming(bool value) {
+  set_has_client_streaming();
+  client_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming)
+}
+
+// optional bool server_streaming = 6 [default = false];
+inline bool MethodDescriptorProto::has_server_streaming() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void MethodDescriptorProto::set_has_server_streaming() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void MethodDescriptorProto::clear_has_server_streaming() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void MethodDescriptorProto::clear_server_streaming() {
+  server_streaming_ = false;
+  clear_has_server_streaming();
+}
+inline bool MethodDescriptorProto::server_streaming() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming)
+  return server_streaming_;
+}
+inline void MethodDescriptorProto::set_server_streaming(bool value) {
+  set_has_server_streaming();
+  server_streaming_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming)
+}
+
+// -------------------------------------------------------------------
+
+// FileOptions
+
+// optional string java_package = 1;
+inline bool FileOptions::has_java_package() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileOptions::set_has_java_package() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileOptions::clear_has_java_package() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void FileOptions::clear_java_package() {
+  java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_package();
+}
+inline const ::std::string& FileOptions::java_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
+  return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_java_package(const ::std::string& value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
+}
+inline void FileOptions::set_java_package(const char* value) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
+}
+inline void FileOptions::set_java_package(const char* value, size_t size) {
+  set_has_java_package();
+  java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+}
+inline ::std::string* FileOptions::mutable_java_package() {
+  set_has_java_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
+  return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_java_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
+  clear_has_java_package();
+  return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_java_package(::std::string* java_package) {
+  if (java_package != NULL) {
+    set_has_java_package();
+  } else {
+    clear_has_java_package();
+  }
+  java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+
+// optional string java_outer_classname = 8;
+inline bool FileOptions::has_java_outer_classname() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileOptions::set_has_java_outer_classname() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileOptions::clear_has_java_outer_classname() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void FileOptions::clear_java_outer_classname() {
+  java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_java_outer_classname();
+}
+inline const ::std::string& FileOptions::java_outer_classname() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_java_outer_classname(const ::std::string& value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
+}
+inline void FileOptions::set_java_outer_classname(const char* value) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
+}
+inline void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+  set_has_java_outer_classname();
+  java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+}
+inline ::std::string* FileOptions::mutable_java_outer_classname() {
+  set_has_java_outer_classname();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
+  return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_java_outer_classname() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
+  clear_has_java_outer_classname();
+  return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+  if (java_outer_classname != NULL) {
+    set_has_java_outer_classname();
+  } else {
+    clear_has_java_outer_classname();
+  }
+  java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+
+// optional bool java_multiple_files = 10 [default = false];
+inline bool FileOptions::has_java_multiple_files() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FileOptions::set_has_java_multiple_files() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FileOptions::clear_has_java_multiple_files() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void FileOptions::clear_java_multiple_files() {
+  java_multiple_files_ = false;
+  clear_has_java_multiple_files();
+}
+inline bool FileOptions::java_multiple_files() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files)
+  return java_multiple_files_;
+}
+inline void FileOptions::set_java_multiple_files(bool value) {
+  set_has_java_multiple_files();
+  java_multiple_files_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files)
+}
+
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+inline bool FileOptions::has_java_generate_equals_and_hash() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FileOptions::set_has_java_generate_equals_and_hash() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FileOptions::clear_has_java_generate_equals_and_hash() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void FileOptions::clear_java_generate_equals_and_hash() {
+  java_generate_equals_and_hash_ = false;
+  clear_has_java_generate_equals_and_hash();
+}
+inline bool FileOptions::java_generate_equals_and_hash() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash)
+  return java_generate_equals_and_hash_;
+}
+inline void FileOptions::set_java_generate_equals_and_hash(bool value) {
+  set_has_java_generate_equals_and_hash();
+  java_generate_equals_and_hash_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash)
+}
+
+// optional bool java_string_check_utf8 = 27 [default = false];
+inline bool FileOptions::has_java_string_check_utf8() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FileOptions::set_has_java_string_check_utf8() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FileOptions::clear_has_java_string_check_utf8() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void FileOptions::clear_java_string_check_utf8() {
+  java_string_check_utf8_ = false;
+  clear_has_java_string_check_utf8();
+}
+inline bool FileOptions::java_string_check_utf8() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8)
+  return java_string_check_utf8_;
+}
+inline void FileOptions::set_java_string_check_utf8(bool value) {
+  set_has_java_string_check_utf8();
+  java_string_check_utf8_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8)
+}
+
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+inline bool FileOptions::has_optimize_for() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FileOptions::set_has_optimize_for() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FileOptions::clear_has_optimize_for() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void FileOptions::clear_optimize_for() {
+  optimize_for_ = 1;
+  clear_has_optimize_for();
+}
+inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for)
+  return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
+}
+inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
+  assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+  set_has_optimize_for();
+  optimize_for_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for)
+}
+
+// optional string go_package = 11;
+inline bool FileOptions::has_go_package() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FileOptions::set_has_go_package() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FileOptions::clear_has_go_package() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void FileOptions::clear_go_package() {
+  go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_go_package();
+}
+inline const ::std::string& FileOptions::go_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
+  return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_go_package(const ::std::string& value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
+}
+inline void FileOptions::set_go_package(const char* value) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
+}
+inline void FileOptions::set_go_package(const char* value, size_t size) {
+  set_has_go_package();
+  go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+}
+inline ::std::string* FileOptions::mutable_go_package() {
+  set_has_go_package();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
+  return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_go_package() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
+  clear_has_go_package();
+  return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_go_package(::std::string* go_package) {
+  if (go_package != NULL) {
+    set_has_go_package();
+  } else {
+    clear_has_go_package();
+  }
+  go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+inline bool FileOptions::has_cc_generic_services() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void FileOptions::clear_cc_generic_services() {
+  cc_generic_services_ = false;
+  clear_has_cc_generic_services();
+}
+inline bool FileOptions::cc_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services)
+  return cc_generic_services_;
+}
+inline void FileOptions::set_cc_generic_services(bool value) {
+  set_has_cc_generic_services();
+  cc_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services)
+}
+
+// optional bool java_generic_services = 17 [default = false];
+inline bool FileOptions::has_java_generic_services() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void FileOptions::set_has_java_generic_services() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void FileOptions::clear_has_java_generic_services() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void FileOptions::clear_java_generic_services() {
+  java_generic_services_ = false;
+  clear_has_java_generic_services();
+}
+inline bool FileOptions::java_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services)
+  return java_generic_services_;
+}
+inline void FileOptions::set_java_generic_services(bool value) {
+  set_has_java_generic_services();
+  java_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services)
+}
+
+// optional bool py_generic_services = 18 [default = false];
+inline bool FileOptions::has_py_generic_services() const {
+  return (_has_bits_[0] & 0x00000200u) != 0;
+}
+inline void FileOptions::set_has_py_generic_services() {
+  _has_bits_[0] |= 0x00000200u;
+}
+inline void FileOptions::clear_has_py_generic_services() {
+  _has_bits_[0] &= ~0x00000200u;
+}
+inline void FileOptions::clear_py_generic_services() {
+  py_generic_services_ = false;
+  clear_has_py_generic_services();
+}
+inline bool FileOptions::py_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services)
+  return py_generic_services_;
+}
+inline void FileOptions::set_py_generic_services(bool value) {
+  set_has_py_generic_services();
+  py_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
+}
+
+// optional bool deprecated = 23 [default = false];
+inline bool FileOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000400u) != 0;
+}
+inline void FileOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000400u;
+}
+inline void FileOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000400u;
+}
+inline void FileOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool FileOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated)
+  return deprecated_;
+}
+inline void FileOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated)
+}
+
+// optional bool cc_enable_arenas = 31 [default = false];
+inline bool FileOptions::has_cc_enable_arenas() const {
+  return (_has_bits_[0] & 0x00000800u) != 0;
+}
+inline void FileOptions::set_has_cc_enable_arenas() {
+  _has_bits_[0] |= 0x00000800u;
+}
+inline void FileOptions::clear_has_cc_enable_arenas() {
+  _has_bits_[0] &= ~0x00000800u;
+}
+inline void FileOptions::clear_cc_enable_arenas() {
+  cc_enable_arenas_ = false;
+  clear_has_cc_enable_arenas();
+}
+inline bool FileOptions::cc_enable_arenas() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas)
+  return cc_enable_arenas_;
+}
+inline void FileOptions::set_cc_enable_arenas(bool value) {
+  set_has_cc_enable_arenas();
+  cc_enable_arenas_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
+}
+
+// optional string objc_class_prefix = 36;
+inline bool FileOptions::has_objc_class_prefix() const {
+  return (_has_bits_[0] & 0x00001000u) != 0;
+}
+inline void FileOptions::set_has_objc_class_prefix() {
+  _has_bits_[0] |= 0x00001000u;
+}
+inline void FileOptions::clear_has_objc_class_prefix() {
+  _has_bits_[0] &= ~0x00001000u;
+}
+inline void FileOptions::clear_objc_class_prefix() {
+  objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_objc_class_prefix();
+}
+inline const ::std::string& FileOptions::objc_class_prefix() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+  set_has_objc_class_prefix();
+  objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline ::std::string* FileOptions::mutable_objc_class_prefix() {
+  set_has_objc_class_prefix();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+  return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_objc_class_prefix() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
+  clear_has_objc_class_prefix();
+  return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+  if (objc_class_prefix != NULL) {
+    set_has_objc_class_prefix();
+  } else {
+    clear_has_objc_class_prefix();
+  }
+  objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// optional string csharp_namespace = 37;
+inline bool FileOptions::has_csharp_namespace() const {
+  return (_has_bits_[0] & 0x00002000u) != 0;
+}
+inline void FileOptions::set_has_csharp_namespace() {
+  _has_bits_[0] |= 0x00002000u;
+}
+inline void FileOptions::clear_has_csharp_namespace() {
+  _has_bits_[0] &= ~0x00002000u;
+}
+inline void FileOptions::clear_csharp_namespace() {
+  csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_csharp_namespace();
+}
+inline const ::std::string& FileOptions::csharp_namespace() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
+  return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_csharp_namespace(const ::std::string& value) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
+}
+inline void FileOptions::set_csharp_namespace(const char* value) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
+}
+inline void FileOptions::set_csharp_namespace(const char* value, size_t size) {
+  set_has_csharp_namespace();
+  csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
+}
+inline ::std::string* FileOptions::mutable_csharp_namespace() {
+  set_has_csharp_namespace();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace)
+  return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_csharp_namespace() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
+  clear_has_csharp_namespace();
+  return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) {
+  if (csharp_namespace != NULL) {
+    set_has_csharp_namespace();
+  } else {
+    clear_has_csharp_namespace();
+  }
+  csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int FileOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void FileOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// MessageOptions
+
+// optional bool message_set_wire_format = 1 [default = false];
+inline bool MessageOptions::has_message_set_wire_format() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MessageOptions::set_has_message_set_wire_format() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MessageOptions::clear_has_message_set_wire_format() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MessageOptions::clear_message_set_wire_format() {
+  message_set_wire_format_ = false;
+  clear_has_message_set_wire_format();
+}
+inline bool MessageOptions::message_set_wire_format() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format)
+  return message_set_wire_format_;
+}
+inline void MessageOptions::set_message_set_wire_format(bool value) {
+  set_has_message_set_wire_format();
+  message_set_wire_format_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format)
+}
+
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MessageOptions::set_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void MessageOptions::clear_no_standard_descriptor_accessor() {
+  no_standard_descriptor_accessor_ = false;
+  clear_has_no_standard_descriptor_accessor();
+}
+inline bool MessageOptions::no_standard_descriptor_accessor() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+  return no_standard_descriptor_accessor_;
+}
+inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+  set_has_no_standard_descriptor_accessor();
+  no_standard_descriptor_accessor_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+}
+
+// optional bool deprecated = 3 [default = false];
+inline bool MessageOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void MessageOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void MessageOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void MessageOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool MessageOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated)
+  return deprecated_;
+}
+inline void MessageOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
+}
+
+// optional bool map_entry = 7;
+inline bool MessageOptions::has_map_entry() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void MessageOptions::set_has_map_entry() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void MessageOptions::clear_has_map_entry() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void MessageOptions::clear_map_entry() {
+  map_entry_ = false;
+  clear_has_map_entry();
+}
+inline bool MessageOptions::map_entry() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+  return map_entry_;
+}
+inline void MessageOptions::set_map_entry(bool value) {
+  set_has_map_entry();
+  map_entry_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int MessageOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void MessageOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// FieldOptions
+
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+inline bool FieldOptions::has_ctype() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldOptions::set_has_ctype() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldOptions::clear_has_ctype() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void FieldOptions::clear_ctype() {
+  ctype_ = 0;
+  clear_has_ctype();
+}
+inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype)
+  return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
+}
+inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
+  assert(::google::protobuf::FieldOptions_CType_IsValid(value));
+  set_has_ctype();
+  ctype_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype)
+}
+
+// optional bool packed = 2;
+inline bool FieldOptions::has_packed() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldOptions::set_has_packed() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldOptions::clear_has_packed() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void FieldOptions::clear_packed() {
+  packed_ = false;
+  clear_has_packed();
+}
+inline bool FieldOptions::packed() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed)
+  return packed_;
+}
+inline void FieldOptions::set_packed(bool value) {
+  set_has_packed();
+  packed_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
+}
+
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+inline bool FieldOptions::has_jstype() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldOptions::set_has_jstype() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldOptions::clear_has_jstype() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void FieldOptions::clear_jstype() {
+  jstype_ = 0;
+  clear_has_jstype();
+}
+inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+  return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+  assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+  set_has_jstype();
+  jstype_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
+// optional bool lazy = 5 [default = false];
+inline bool FieldOptions::has_lazy() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldOptions::set_has_lazy() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldOptions::clear_has_lazy() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void FieldOptions::clear_lazy() {
+  lazy_ = false;
+  clear_has_lazy();
+}
+inline bool FieldOptions::lazy() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy)
+  return lazy_;
+}
+inline void FieldOptions::set_lazy(bool value) {
+  set_has_lazy();
+  lazy_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy)
+}
+
+// optional bool deprecated = 3 [default = false];
+inline bool FieldOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void FieldOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool FieldOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated)
+  return deprecated_;
+}
+inline void FieldOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
+}
+
+// optional bool weak = 10 [default = false];
+inline bool FieldOptions::has_weak() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldOptions::set_has_weak() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldOptions::clear_has_weak() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void FieldOptions::clear_weak() {
+  weak_ = false;
+  clear_has_weak();
+}
+inline bool FieldOptions::weak() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
+  return weak_;
+}
+inline void FieldOptions::set_weak(bool value) {
+  set_has_weak();
+  weak_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int FieldOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void FieldOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// EnumOptions
+
+// optional bool allow_alias = 2;
+inline bool EnumOptions::has_allow_alias() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumOptions::set_has_allow_alias() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumOptions::clear_has_allow_alias() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumOptions::clear_allow_alias() {
+  allow_alias_ = false;
+  clear_has_allow_alias();
+}
+inline bool EnumOptions::allow_alias() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias)
+  return allow_alias_;
+}
+inline void EnumOptions::set_allow_alias(bool value) {
+  set_has_allow_alias();
+  allow_alias_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias)
+}
+
+// optional bool deprecated = 3 [default = false];
+inline bool EnumOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void EnumOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void EnumOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void EnumOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool EnumOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated)
+  return deprecated_;
+}
+inline void EnumOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int EnumOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void EnumOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// EnumValueOptions
+
+// optional bool deprecated = 1 [default = false];
+inline bool EnumValueOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumValueOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumValueOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumValueOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool EnumValueOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated)
+  return deprecated_;
+}
+inline void EnumValueOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int EnumValueOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void EnumValueOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// ServiceOptions
+
+// optional bool deprecated = 33 [default = false];
+inline bool ServiceOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void ServiceOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void ServiceOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void ServiceOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool ServiceOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated)
+  return deprecated_;
+}
+inline void ServiceOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int ServiceOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void ServiceOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// MethodOptions
+
+// optional bool deprecated = 33 [default = false];
+inline bool MethodOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MethodOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MethodOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MethodOptions::clear_deprecated() {
+  deprecated_ = false;
+  clear_has_deprecated();
+}
+inline bool MethodOptions::deprecated() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated)
+  return deprecated_;
+}
+inline void MethodOptions::set_deprecated(bool value) {
+  set_has_deprecated();
+  deprecated_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int MethodOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void MethodOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption_NamePart
+
+// required string name_part = 1;
+inline bool UninterpretedOption_NamePart::has_name_part() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_name_part() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void UninterpretedOption_NamePart::clear_has_name_part() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void UninterpretedOption_NamePart::clear_name_part() {
+  name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_name_part();
+}
+inline const ::std::string& UninterpretedOption_NamePart::name_part() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+  set_has_name_part();
+  name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
+  set_has_name_part();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
+  return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* UninterpretedOption_NamePart::release_name_part() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
+  clear_has_name_part();
+  return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+  if (name_part != NULL) {
+    set_has_name_part();
+  } else {
+    clear_has_name_part();
+  }
+  name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+
+// required bool is_extension = 2;
+inline bool UninterpretedOption_NamePart::has_is_extension() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_is_extension() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption_NamePart::clear_has_is_extension() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void UninterpretedOption_NamePart::clear_is_extension() {
+  is_extension_ = false;
+  clear_has_is_extension();
+}
+inline bool UninterpretedOption_NamePart::is_extension() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension)
+  return is_extension_;
+}
+inline void UninterpretedOption_NamePart::set_is_extension(bool value) {
+  set_has_is_extension();
+  is_extension_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption
+
+// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+inline int UninterpretedOption::name_size() const {
+  return name_.size();
+}
+inline void UninterpretedOption::clear_name() {
+  name_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
+  return name_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
+  return name_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+  // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
+  return name_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
+  return &name_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+  return name_;
+}
+
+// optional string identifier_value = 3;
+inline bool UninterpretedOption::has_identifier_value() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption::set_has_identifier_value() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption::clear_has_identifier_value() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void UninterpretedOption::clear_identifier_value() {
+  identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_identifier_value();
+}
+inline const ::std::string& UninterpretedOption::identifier_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_identifier_value(const ::std::string& value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
+}
+inline void UninterpretedOption::set_identifier_value(const char* value) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
+}
+inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+  set_has_identifier_value();
+  identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+}
+inline ::std::string* UninterpretedOption::mutable_identifier_value() {
+  set_has_identifier_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
+  return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* UninterpretedOption::release_identifier_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
+  clear_has_identifier_value();
+  return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+  if (identifier_value != NULL) {
+    set_has_identifier_value();
+  } else {
+    clear_has_identifier_value();
+  }
+  identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+
+// optional uint64 positive_int_value = 4;
+inline bool UninterpretedOption::has_positive_int_value() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void UninterpretedOption::set_has_positive_int_value() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void UninterpretedOption::clear_has_positive_int_value() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void UninterpretedOption::clear_positive_int_value() {
+  positive_int_value_ = GOOGLE_ULONGLONG(0);
+  clear_has_positive_int_value();
+}
+inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
+  return positive_int_value_;
+}
+inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
+  set_has_positive_int_value();
+  positive_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
+}
+
+// optional int64 negative_int_value = 5;
+inline bool UninterpretedOption::has_negative_int_value() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void UninterpretedOption::set_has_negative_int_value() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void UninterpretedOption::clear_has_negative_int_value() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void UninterpretedOption::clear_negative_int_value() {
+  negative_int_value_ = GOOGLE_LONGLONG(0);
+  clear_has_negative_int_value();
+}
+inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
+  return negative_int_value_;
+}
+inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
+  set_has_negative_int_value();
+  negative_int_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
+}
+
+// optional double double_value = 6;
+inline bool UninterpretedOption::has_double_value() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void UninterpretedOption::set_has_double_value() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void UninterpretedOption::clear_has_double_value() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void UninterpretedOption::clear_double_value() {
+  double_value_ = 0;
+  clear_has_double_value();
+}
+inline double UninterpretedOption::double_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value)
+  return double_value_;
+}
+inline void UninterpretedOption::set_double_value(double value) {
+  set_has_double_value();
+  double_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
+}
+
+// optional bytes string_value = 7;
+inline bool UninterpretedOption::has_string_value() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void UninterpretedOption::set_has_string_value() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void UninterpretedOption::clear_has_string_value() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void UninterpretedOption::clear_string_value() {
+  string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_string_value();
+}
+inline const ::std::string& UninterpretedOption::string_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_string_value(const ::std::string& value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
+}
+inline void UninterpretedOption::set_string_value(const char* value) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
+}
+inline void UninterpretedOption::set_string_value(const void* value, size_t size) {
+  set_has_string_value();
+  string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+}
+inline ::std::string* UninterpretedOption::mutable_string_value() {
+  set_has_string_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
+  return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* UninterpretedOption::release_string_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
+  clear_has_string_value();
+  return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+  if (string_value != NULL) {
+    set_has_string_value();
+  } else {
+    clear_has_string_value();
+  }
+  string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+
+// optional string aggregate_value = 8;
+inline bool UninterpretedOption::has_aggregate_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void UninterpretedOption::set_has_aggregate_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void UninterpretedOption::clear_has_aggregate_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void UninterpretedOption::clear_aggregate_value() {
+  aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_aggregate_value();
+}
+inline const ::std::string& UninterpretedOption::aggregate_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+  set_has_aggregate_value();
+  aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+}
+inline ::std::string* UninterpretedOption::mutable_aggregate_value() {
+  set_has_aggregate_value();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
+  return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* UninterpretedOption::release_aggregate_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
+  clear_has_aggregate_value();
+  return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+  if (aggregate_value != NULL) {
+    set_has_aggregate_value();
+  } else {
+    clear_has_aggregate_value();
+  }
+  aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+inline int SourceCodeInfo_Location::path_size() const {
+  return path_.size();
+}
+inline void SourceCodeInfo_Location::clear_path() {
+  path_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
+  return path_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
+}
+inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
+  return path_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
+  return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+inline int SourceCodeInfo_Location::span_size() const {
+  return span_.size();
+}
+inline void SourceCodeInfo_Location::clear_span() {
+  span_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
+  return span_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+  span_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
+}
+inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+  span_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
+  return span_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
+  return &span_;
+}
+
+// optional string leading_comments = 3;
+inline bool SourceCodeInfo_Location::has_leading_comments() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_leading_comments() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_has_leading_comments() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_leading_comments() {
+  leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_leading_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+  set_has_leading_comments();
+  leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+  set_has_leading_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  clear_has_leading_comments();
+  return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+  if (leading_comments != NULL) {
+    set_has_leading_comments();
+  } else {
+    clear_has_leading_comments();
+  }
+  leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+
+// optional string trailing_comments = 4;
+inline bool SourceCodeInfo_Location::has_trailing_comments() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_trailing_comments() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_has_trailing_comments() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_trailing_comments() {
+  trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_trailing_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+  set_has_trailing_comments();
+  trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+  set_has_trailing_comments();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  clear_has_trailing_comments();
+  return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+  if (trailing_comments != NULL) {
+    set_has_trailing_comments();
+  } else {
+    clear_has_trailing_comments();
+  }
+  trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+
+// repeated string leading_detached_comments = 6;
+inline int SourceCodeInfo_Location::leading_detached_comments_size() const {
+  return leading_detached_comments_.size();
+}
+inline void SourceCodeInfo_Location::clear_leading_detached_comments() {
+  leading_detached_comments_.Clear();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Get(index);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Mutable(index);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  leading_detached_comments_.Mutable(index)->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+  leading_detached_comments_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+  leading_detached_comments_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_.Add();
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+  leading_detached_comments_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+  leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return leading_detached_comments_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+  return &leading_detached_comments_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+inline int SourceCodeInfo::location_size() const {
+  return location_.size();
+}
+inline void SourceCodeInfo::clear_location() {
+  location_.Clear();
+}
+inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
+  return location_.Get(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
+  return location_.Mutable(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
+  return location_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
+  return &location_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+  return location_;
+}
+
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo_Annotation
+
+// repeated int32 path = 1 [packed = true];
+inline int GeneratedCodeInfo_Annotation::path_size() const {
+  return path_.size();
+}
+inline void GeneratedCodeInfo_Annotation::clear_path() {
+  path_.Clear();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return path_.Get(index);
+}
+inline void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+inline void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+GeneratedCodeInfo_Annotation::path() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return path_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+GeneratedCodeInfo_Annotation::mutable_path() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+  return &path_;
+}
+
+// optional string source_file = 2;
+inline bool GeneratedCodeInfo_Annotation::has_source_file() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_source_file() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_source_file() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_source_file() {
+  source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_source_file();
+}
+inline const ::std::string& GeneratedCodeInfo_Annotation::source_file() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  return source_file_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) {
+  set_has_source_file();
+  source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
+  set_has_source_file();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+  // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  clear_has_source_file();
+  return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) {
+  if (source_file != NULL) {
+    set_has_source_file();
+  } else {
+    clear_has_source_file();
+  }
+  source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+
+// optional int32 begin = 3;
+inline bool GeneratedCodeInfo_Annotation::has_begin() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_begin() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_begin() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_begin() {
+  begin_ = 0;
+  clear_has_begin();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+  return begin_;
+}
+inline void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) {
+  set_has_begin();
+  begin_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+}
+
+// optional int32 end = 4;
+inline bool GeneratedCodeInfo_Annotation::has_end() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_end() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_end() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_end() {
+  end_ = 0;
+  clear_has_end();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end)
+  return end_;
+}
+inline void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) {
+  set_has_end();
+  end_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
+}
+
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo
+
+// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+inline int GeneratedCodeInfo::annotation_size() const {
+  return annotation_.size();
+}
+inline void GeneratedCodeInfo::clear_annotation() {
+  annotation_.Clear();
+}
+inline const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Get(index);
+}
+inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Mutable(index);
+}
+inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() {
+  // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+GeneratedCodeInfo::mutable_annotation() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation)
+  return &annotation_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+GeneratedCodeInfo::annotation() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation)
+  return annotation_;
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Type> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() {
+  return ::google::protobuf::FieldDescriptorProto_Type_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Label> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() {
+  return ::google::protobuf::FieldDescriptorProto_Label_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::FileOptions_OptimizeMode> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() {
+  return ::google::protobuf::FileOptions_OptimizeMode_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::FieldOptions_CType> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() {
+  return ::google::protobuf::FieldOptions_CType_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::FieldOptions_JSType> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_JSType>() {
+  return ::google::protobuf::FieldOptions_JSType_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+#endif  // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor.proto b/src/third_party/protobuf-3/src/google/protobuf/descriptor.proto
new file mode 100644
index 0000000..08b1555
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor.proto
@@ -0,0 +1,803 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+syntax = "proto2";
+
+package google.protobuf;
+option go_package = "descriptor";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+  repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+  optional string name = 1;       // file name, relative to root of source tree
+  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
+
+  // Names of files imported by this file.
+  repeated string dependency = 3;
+  // Indexes of the public imported files in the dependency list above.
+  repeated int32 public_dependency = 10;
+  // Indexes of the weak imported files in the dependency list.
+  // For Google-internal migration only. Do not use.
+  repeated int32 weak_dependency = 11;
+
+  // All top-level definitions in this file.
+  repeated DescriptorProto message_type = 4;
+  repeated EnumDescriptorProto enum_type = 5;
+  repeated ServiceDescriptorProto service = 6;
+  repeated FieldDescriptorProto extension = 7;
+
+  optional FileOptions options = 8;
+
+  // This field contains optional information about the original source code.
+  // You may safely remove this entire field without harming runtime
+  // functionality of the descriptors -- the information is needed only by
+  // development tools.
+  optional SourceCodeInfo source_code_info = 9;
+
+  // The syntax of the proto file.
+  // The supported values are "proto2" and "proto3".
+  optional string syntax = 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+  optional string name = 1;
+
+  repeated FieldDescriptorProto field = 2;
+  repeated FieldDescriptorProto extension = 6;
+
+  repeated DescriptorProto nested_type = 3;
+  repeated EnumDescriptorProto enum_type = 4;
+
+  message ExtensionRange {
+    optional int32 start = 1;
+    optional int32 end = 2;
+  }
+  repeated ExtensionRange extension_range = 5;
+
+  repeated OneofDescriptorProto oneof_decl = 8;
+
+  optional MessageOptions options = 7;
+
+  // Range of reserved tag numbers. Reserved tag numbers may not be used by
+  // fields or extension ranges in the same message. Reserved ranges may
+  // not overlap.
+  message ReservedRange {
+    optional int32 start = 1; // Inclusive.
+    optional int32 end = 2;   // Exclusive.
+  }
+  repeated ReservedRange reserved_range = 9;
+  // Reserved field names, which may not be used by fields in the same message.
+  // A given name may only be reserved once.
+  repeated string reserved_name = 10;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+  enum Type {
+    // 0 is reserved for errors.
+    // Order is weird for historical reasons.
+    TYPE_DOUBLE         = 1;
+    TYPE_FLOAT          = 2;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+    // negative values are likely.
+    TYPE_INT64          = 3;
+    TYPE_UINT64         = 4;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+    // negative values are likely.
+    TYPE_INT32          = 5;
+    TYPE_FIXED64        = 6;
+    TYPE_FIXED32        = 7;
+    TYPE_BOOL           = 8;
+    TYPE_STRING         = 9;
+    TYPE_GROUP          = 10;  // Tag-delimited aggregate.
+    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
+
+    // New in version 2.
+    TYPE_BYTES          = 12;
+    TYPE_UINT32         = 13;
+    TYPE_ENUM           = 14;
+    TYPE_SFIXED32       = 15;
+    TYPE_SFIXED64       = 16;
+    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
+    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
+  };
+
+  enum Label {
+    // 0 is reserved for errors
+    LABEL_OPTIONAL      = 1;
+    LABEL_REQUIRED      = 2;
+    LABEL_REPEATED      = 3;
+    // TODO(sanjay): Should we add LABEL_MAP?
+  };
+
+  optional string name = 1;
+  optional int32 number = 3;
+  optional Label label = 4;
+
+  // If type_name is set, this need not be set.  If both this and type_name
+  // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+  optional Type type = 5;
+
+  // For message and enum types, this is the name of the type.  If the name
+  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+  // rules are used to find the type (i.e. first the nested types within this
+  // message are searched, then within the parent, on up to the root
+  // namespace).
+  optional string type_name = 6;
+
+  // For extensions, this is the name of the type being extended.  It is
+  // resolved in the same manner as type_name.
+  optional string extendee = 2;
+
+  // For numeric types, contains the original text representation of the value.
+  // For booleans, "true" or "false".
+  // For strings, contains the default text contents (not escaped in any way).
+  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+  // TODO(kenton):  Base-64 encode?
+  optional string default_value = 7;
+
+  // If set, gives the index of a oneof in the containing type's oneof_decl
+  // list.  This field is a member of that oneof.
+  optional int32 oneof_index = 9;
+
+  // JSON name of this field. The value is set by protocol compiler. If the
+  // user has set a "json_name" option on this field, that option's value
+  // will be used. Otherwise, it's deduced from the field's name by converting
+  // it to camelCase.
+  optional string json_name = 10;
+
+  optional FieldOptions options = 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+  optional string name = 1;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+  optional string name = 1;
+
+  repeated EnumValueDescriptorProto value = 2;
+
+  optional EnumOptions options = 3;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+  optional string name = 1;
+  optional int32 number = 2;
+
+  optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+  optional string name = 1;
+  repeated MethodDescriptorProto method = 2;
+
+  optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+  optional string name = 1;
+
+  // Input and output type names.  These are resolved in the same way as
+  // FieldDescriptorProto.type_name, but must refer to a message type.
+  optional string input_type = 2;
+  optional string output_type = 3;
+
+  optional MethodOptions options = 4;
+
+  // Identifies if client streams multiple client messages
+  optional bool client_streaming = 5 [default=false];
+  // Identifies if server streams multiple server messages
+  optional bool server_streaming = 6 [default=false];
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached.  These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them.  Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+//   organization, or for experimental options, use field numbers 50000
+//   through 99999.  It is up to you to ensure that you do not use the
+//   same number for multiple options.
+// * For options which will be published and used publicly by multiple
+//   independent entities, e-mail protobuf-global-extension-registry@google.com
+//   to reserve extension numbers. Simply provide your project name (e.g.
+//   Objective-C plugin) and your project website (if available) -- there's no
+//   need to explain how you intend to use them. Usually you only need one
+//   extension number. You can declare multiple options with only one extension
+//   number by putting them in a sub-message. See the Custom Options section of
+//   the docs for examples:
+//   https://developers.google.com/protocol-buffers/docs/proto#options
+//   If this turns out to be popular, a web service will be set up
+//   to automatically assign option numbers.
+
+
+message FileOptions {
+
+  // Sets the Java package where classes generated from this .proto will be
+  // placed.  By default, the proto package is used, but this is often
+  // inappropriate because proto packages do not normally start with backwards
+  // domain names.
+  optional string java_package = 1;
+
+
+  // If set, all the classes from the .proto file are wrapped in a single
+  // outer class with the given name.  This applies to both Proto1
+  // (equivalent to the old "--one_java_file" option) and Proto2 (where
+  // a .proto always translates to a single class, but you may want to
+  // explicitly choose the class name).
+  optional string java_outer_classname = 8;
+
+  // If set true, then the Java code generator will generate a separate .java
+  // file for each top-level message, enum, and service defined in the .proto
+  // file.  Thus, these types will *not* be nested inside the outer class
+  // named by java_outer_classname.  However, the outer class will still be
+  // generated to contain the file's getDescriptor() method as well as any
+  // top-level extensions defined in the file.
+  optional bool java_multiple_files = 10 [default=false];
+
+  // If set true, then the Java code generator will generate equals() and
+  // hashCode() methods for all messages defined in the .proto file.
+  // This increases generated code size, potentially substantially for large
+  // protos, which may harm a memory-constrained application.
+  // - In the full runtime this is a speed optimization, as the
+  // AbstractMessage base class includes reflection-based implementations of
+  // these methods.
+  // - In the lite runtime, setting this option changes the semantics of
+  // equals() and hashCode() to more closely match those of the full runtime;
+  // the generated methods compute their results based on field values rather
+  // than object identity. (Implementations should not assume that hashcodes
+  // will be consistent across runtimes or versions of the protocol compiler.)
+  optional bool java_generate_equals_and_hash = 20 [default=false];
+
+  // If set true, then the Java2 code generator will generate code that
+  // throws an exception whenever an attempt is made to assign a non-UTF-8
+  // byte sequence to a string field.
+  // Message reflection will do the same.
+  // However, an extension field still accepts non-UTF-8 byte sequences.
+  // This option has no effect on when used with the lite runtime.
+  optional bool java_string_check_utf8 = 27 [default=false];
+
+
+  // Generated classes can be optimized for speed or code size.
+  enum OptimizeMode {
+    SPEED = 1;        // Generate complete code for parsing, serialization,
+                      // etc.
+    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
+    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+  }
+  optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+  // Sets the Go package where structs generated from this .proto will be
+  // placed. If omitted, the Go package will be derived from the following:
+  //   - The basename of the package import path, if provided.
+  //   - Otherwise, the package statement in the .proto file, if present.
+  //   - Otherwise, the basename of the .proto file, without extension.
+  optional string go_package = 11;
+
+
+
+  // Should generic services be generated in each language?  "Generic" services
+  // are not specific to any particular RPC system.  They are generated by the
+  // main code generators in each language (without additional plugins).
+  // Generic services were the only kind of service generation supported by
+  // early versions of google.protobuf.
+  //
+  // Generic services are now considered deprecated in favor of using plugins
+  // that generate code specific to your particular RPC system.  Therefore,
+  // these default to false.  Old code which depends on generic services should
+  // explicitly set them to true.
+  optional bool cc_generic_services = 16 [default=false];
+  optional bool java_generic_services = 17 [default=false];
+  optional bool py_generic_services = 18 [default=false];
+
+  // Is this file deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for everything in the file, or it will be completely ignored; in the very
+  // least, this is a formalization for deprecating files.
+  optional bool deprecated = 23 [default=false];
+
+  // Enables the use of arenas for the proto messages in this file. This applies
+  // only to generated classes for C++.
+  optional bool cc_enable_arenas = 31 [default=false];
+
+
+  // Sets the objective c class prefix which is prepended to all objective c
+  // generated classes from this .proto. There is no default.
+  optional string objc_class_prefix = 36;
+
+  // Namespace for generated classes; defaults to the package.
+  optional string csharp_namespace = 37;
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+
+  reserved 38;
+}
+
+message MessageOptions {
+  // Set true to use the old proto1 MessageSet wire format for extensions.
+  // This is provided for backwards-compatibility with the MessageSet wire
+  // format.  You should not use this for any other reason:  It's less
+  // efficient, has fewer features, and is more complicated.
+  //
+  // The message must be defined exactly as follows:
+  //   message Foo {
+  //     option message_set_wire_format = true;
+  //     extensions 4 to max;
+  //   }
+  // Note that the message cannot have any defined fields; MessageSets only
+  // have extensions.
+  //
+  // All extensions of your type must be singular messages; e.g. they cannot
+  // be int32s, enums, or repeated messages.
+  //
+  // Because this is an option, the above two restrictions are not enforced by
+  // the protocol compiler.
+  optional bool message_set_wire_format = 1 [default=false];
+
+  // Disables the generation of the standard "descriptor()" accessor, which can
+  // conflict with a field of the same name.  This is meant to make migration
+  // from proto1 easier; new code should avoid fields named "descriptor".
+  optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+  // Is this message deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the message, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating messages.
+  optional bool deprecated = 3 [default=false];
+
+  // Whether the message is an automatically generated map entry type for the
+  // maps field.
+  //
+  // For maps fields:
+  //     map<KeyType, ValueType> map_field = 1;
+  // The parsed descriptor looks like:
+  //     message MapFieldEntry {
+  //         option map_entry = true;
+  //         optional KeyType key = 1;
+  //         optional ValueType value = 2;
+  //     }
+  //     repeated MapFieldEntry map_field = 1;
+  //
+  // Implementations may choose not to generate the map_entry=true message, but
+  // use a native map in the target language to hold the keys and values.
+  // The reflection APIs in such implementions still need to work as
+  // if the field is a repeated message field.
+  //
+  // NOTE: Do not set the option in .proto files. Always use the maps syntax
+  // instead. The option should only be implicitly set by the proto compiler
+  // parser.
+  optional bool map_entry = 7;
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message FieldOptions {
+  // The ctype option instructs the C++ code generator to use a different
+  // representation of the field than it normally would.  See the specific
+  // options below.  This option is not yet implemented in the open source
+  // release -- sorry, we'll try to include it in a future version!
+  optional CType ctype = 1 [default = STRING];
+  enum CType {
+    // Default mode.
+    STRING = 0;
+
+    CORD = 1;
+
+    STRING_PIECE = 2;
+  }
+  // The packed option can be enabled for repeated primitive fields to enable
+  // a more efficient representation on the wire. Rather than repeatedly
+  // writing the tag and type for each element, the entire array is encoded as
+  // a single length-delimited blob. In proto3, only explicit setting it to
+  // false will avoid using packed encoding.
+  optional bool packed = 2;
+
+
+  // The jstype option determines the JavaScript type used for values of the
+  // field.  The option is permitted only for 64 bit integral and fixed types
+  // (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
+  // represented as JavaScript strings.  This avoids loss of precision that can
+  // happen when a large value is converted to a floating point JavaScript
+  // numbers.  Specifying JS_NUMBER for the jstype causes the generated
+  // JavaScript code to use the JavaScript "number" type instead of strings.
+  // This option is an enum to permit additional types to be added,
+  // e.g. goog.math.Integer.
+  optional JSType jstype = 6 [default = JS_NORMAL];
+  enum JSType {
+    // Use the default type.
+    JS_NORMAL = 0;
+
+    // Use JavaScript strings.
+    JS_STRING = 1;
+
+    // Use JavaScript numbers.
+    JS_NUMBER = 2;
+  }
+
+  // Should this field be parsed lazily?  Lazy applies only to message-type
+  // fields.  It means that when the outer message is initially parsed, the
+  // inner message's contents will not be parsed but instead stored in encoded
+  // form.  The inner message will actually be parsed when it is first accessed.
+  //
+  // This is only a hint.  Implementations are free to choose whether to use
+  // eager or lazy parsing regardless of the value of this option.  However,
+  // setting this option true suggests that the protocol author believes that
+  // using lazy parsing on this field is worth the additional bookkeeping
+  // overhead typically needed to implement it.
+  //
+  // This option does not affect the public interface of any generated code;
+  // all method signatures remain the same.  Furthermore, thread-safety of the
+  // interface is not affected by this option; const methods remain safe to
+  // call from multiple threads concurrently, while non-const methods continue
+  // to require exclusive access.
+  //
+  //
+  // Note that implementations may choose not to check required fields within
+  // a lazy sub-message.  That is, calling IsInitialized() on the outher message
+  // may return true even if the inner message has missing required fields.
+  // This is necessary because otherwise the inner message would have to be
+  // parsed in order to perform the check, defeating the purpose of lazy
+  // parsing.  An implementation which chooses not to check required fields
+  // must be consistent about it.  That is, for any particular sub-message, the
+  // implementation must either *always* check its required fields, or *never*
+  // check its required fields, regardless of whether or not the message has
+  // been parsed.
+  optional bool lazy = 5 [default=false];
+
+  // Is this field deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for accessors, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating fields.
+  optional bool deprecated = 3 [default=false];
+
+  // For Google-internal migration only. Do not use.
+  optional bool weak = 10 [default=false];
+
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumOptions {
+
+  // Set this option to true to allow mapping different tag names to the same
+  // value.
+  optional bool allow_alias = 2;
+
+  // Is this enum deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating enums.
+  optional bool deprecated = 3 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumValueOptions {
+  // Is this enum value deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum value, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating enum values.
+  optional bool deprecated = 1 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this service deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the service, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating services.
+  optional bool deprecated = 33 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message MethodOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this method deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the method, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating methods.
+  optional bool deprecated = 33 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+  // The name of the uninterpreted option.  Each string represents a segment in
+  // a dot-separated name.  is_extension is true iff a segment represents an
+  // extension (denoted with parentheses in options specs in .proto files).
+  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+  // "foo.(bar.baz).qux".
+  message NamePart {
+    required string name_part = 1;
+    required bool is_extension = 2;
+  }
+  repeated NamePart name = 2;
+
+  // The value of the uninterpreted option, in whatever type the tokenizer
+  // identified it as during parsing. Exactly one of these should be set.
+  optional string identifier_value = 3;
+  optional uint64 positive_int_value = 4;
+  optional int64 negative_int_value = 5;
+  optional double double_value = 6;
+  optional bytes string_value = 7;
+  optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+  // A Location identifies a piece of source code in a .proto file which
+  // corresponds to a particular definition.  This information is intended
+  // to be useful to IDEs, code indexers, documentation generators, and similar
+  // tools.
+  //
+  // For example, say we have a file like:
+  //   message Foo {
+  //     optional string foo = 1;
+  //   }
+  // Let's look at just the field definition:
+  //   optional string foo = 1;
+  //   ^       ^^     ^^  ^  ^^^
+  //   a       bc     de  f  ghi
+  // We have the following locations:
+  //   span   path               represents
+  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+  //
+  // Notes:
+  // - A location may refer to a repeated field itself (i.e. not to any
+  //   particular index within it).  This is used whenever a set of elements are
+  //   logically enclosed in a single code segment.  For example, an entire
+  //   extend block (possibly containing multiple extension definitions) will
+  //   have an outer location whose path refers to the "extensions" repeated
+  //   field without an index.
+  // - Multiple locations may have the same path.  This happens when a single
+  //   logical declaration is spread out across multiple places.  The most
+  //   obvious example is the "extend" block again -- there may be multiple
+  //   extend blocks in the same scope, each of which will have the same path.
+  // - A location's span is not always a subset of its parent's span.  For
+  //   example, the "extendee" of an extension declaration appears at the
+  //   beginning of the "extend" block and is shared by all extensions within
+  //   the block.
+  // - Just because a location's span is a subset of some other location's span
+  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   both a type and a field in a single declaration.  Thus, the locations
+  //   corresponding to the type and field and their components will overlap.
+  // - Code which tries to interpret locations should probably be designed to
+  //   ignore those that it doesn't understand, as more types of locations could
+  //   be recorded in the future.
+  repeated Location location = 1;
+  message Location {
+    // Identifies which part of the FileDescriptorProto was defined at this
+    // location.
+    //
+    // Each element is a field number or an index.  They form a path from
+    // the root FileDescriptorProto to the place where the definition.  For
+    // example, this path:
+    //   [ 4, 3, 2, 7, 1 ]
+    // refers to:
+    //   file.message_type(3)  // 4, 3
+    //       .field(7)         // 2, 7
+    //       .name()           // 1
+    // This is because FileDescriptorProto.message_type has field number 4:
+    //   repeated DescriptorProto message_type = 4;
+    // and DescriptorProto.field has field number 2:
+    //   repeated FieldDescriptorProto field = 2;
+    // and FieldDescriptorProto.name has field number 1:
+    //   optional string name = 1;
+    //
+    // Thus, the above path gives the location of a field name.  If we removed
+    // the last element:
+    //   [ 4, 3, 2, 7 ]
+    // this path refers to the whole field declaration (from the beginning
+    // of the label to the terminating semicolon).
+    repeated int32 path = 1 [packed=true];
+
+    // Always has exactly three or four elements: start line, start column,
+    // end line (optional, otherwise assumed same as start line), end column.
+    // These are packed into a single field for efficiency.  Note that line
+    // and column numbers are zero-based -- typically you will want to add
+    // 1 to each before displaying to a user.
+    repeated int32 span = 2 [packed=true];
+
+    // If this SourceCodeInfo represents a complete declaration, these are any
+    // comments appearing before and after the declaration which appear to be
+    // attached to the declaration.
+    //
+    // A series of line comments appearing on consecutive lines, with no other
+    // tokens appearing on those lines, will be treated as a single comment.
+    //
+    // leading_detached_comments will keep paragraphs of comments that appear
+    // before (but not connected to) the current element. Each paragraph,
+    // separated by empty lines, will be one comment element in the repeated
+    // field.
+    //
+    // Only the comment content is provided; comment markers (e.g. //) are
+    // stripped out.  For block comments, leading whitespace and an asterisk
+    // will be stripped from the beginning of each line other than the first.
+    // Newlines are included in the output.
+    //
+    // Examples:
+    //
+    //   optional int32 foo = 1;  // Comment attached to foo.
+    //   // Comment attached to bar.
+    //   optional int32 bar = 2;
+    //
+    //   optional string baz = 3;
+    //   // Comment attached to baz.
+    //   // Another line attached to baz.
+    //
+    //   // Comment attached to qux.
+    //   //
+    //   // Another line attached to qux.
+    //   optional double qux = 4;
+    //
+    //   // Detached comment for corge. This is not leading or trailing comments
+    //   // to qux or corge because there are blank lines separating it from
+    //   // both.
+    //
+    //   // Detached comment for corge paragraph 2.
+    //
+    //   optional string corge = 5;
+    //   /* Block comment attached
+    //    * to corge.  Leading asterisks
+    //    * will be removed. */
+    //   /* Block comment attached to
+    //    * grault. */
+    //   optional int32 grault = 6;
+    //
+    //   // ignored detached comments.
+    optional string leading_comments = 3;
+    optional string trailing_comments = 4;
+    repeated string leading_detached_comments = 6;
+  }
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+  // An Annotation connects some span of text in generated code to an element
+  // of its generating .proto file.
+  repeated Annotation annotation = 1;
+  message Annotation {
+    // Identifies the element in the original source .proto file. This field
+    // is formatted the same as SourceCodeInfo.Location.path.
+    repeated int32 path = 1 [packed=true];
+
+    // Identifies the filesystem path to the original source .proto.
+    optional string source_file = 2;
+
+    // Identifies the starting offset in bytes in the generated code
+    // that relates to the identified object.
+    optional int32 begin = 3;
+
+    // Identifies the ending offset in bytes in the generated code that
+    // relates to the identified offset. The end offset should be one past
+    // the last relevant byte (so the length of the text = end - begin).
+    optional int32 end = 4;
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.cc b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.cc
new file mode 100644
index 0000000..2117c02
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.cc
@@ -0,0 +1,543 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/descriptor_database.h>
+
+#include <set>
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+
+DescriptorDatabase::~DescriptorDatabase() {}
+
+// ===================================================================
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
+    const FileDescriptorProto& file,
+    Value value) {
+  if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
+    GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
+    return false;
+  }
+
+  // We must be careful here -- calling file.package() if file.has_package() is
+  // false could access an uninitialized static-storage variable if we are being
+  // run at startup time.
+  string path = file.has_package() ? file.package() : string();
+  if (!path.empty()) path += '.';
+
+  for (int i = 0; i < file.message_type_size(); i++) {
+    if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
+    if (!AddNestedExtensions(file.message_type(i), value)) return false;
+  }
+  for (int i = 0; i < file.enum_type_size(); i++) {
+    if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
+  }
+  for (int i = 0; i < file.extension_size(); i++) {
+    if (!AddSymbol(path + file.extension(i).name(), value)) return false;
+    if (!AddExtension(file.extension(i), value)) return false;
+  }
+  for (int i = 0; i < file.service_size(); i++) {
+    if (!AddSymbol(path + file.service(i).name(), value)) return false;
+  }
+
+  return true;
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
+    const string& name, Value value) {
+  // We need to make sure not to violate our map invariant.
+
+  // If the symbol name is invalid it could break our lookup algorithm (which
+  // relies on the fact that '.' sorts before all other characters that are
+  // valid in symbol names).
+  if (!ValidateSymbolName(name)) {
+    GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
+    return false;
+  }
+
+  // Try to look up the symbol to make sure a super-symbol doesn't already
+  // exist.
+  typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
+
+  if (iter == by_symbol_.end()) {
+    // Apparently the map is currently empty.  Just insert and be done with it.
+    by_symbol_.insert(typename map<string, Value>::value_type(name, value));
+    return true;
+  }
+
+  if (IsSubSymbol(iter->first, name)) {
+    GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
+                  "symbol \"" << iter->first << "\".";
+    return false;
+  }
+
+  // OK, that worked.  Now we have to make sure that no symbol in the map is
+  // a sub-symbol of the one we are inserting.  The only symbol which could
+  // be so is the first symbol that is greater than the new symbol.  Since
+  // |iter| points at the last symbol that is less than or equal, we just have
+  // to increment it.
+  ++iter;
+
+  if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
+    GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
+                  "symbol \"" << iter->first << "\".";
+    return false;
+  }
+
+  // OK, no conflicts.
+
+  // Insert the new symbol using the iterator as a hint, the new entry will
+  // appear immediately before the one the iterator is pointing at.
+  by_symbol_.insert(iter, typename map<string, Value>::value_type(name, value));
+
+  return true;
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
+    const DescriptorProto& message_type,
+    Value value) {
+  for (int i = 0; i < message_type.nested_type_size(); i++) {
+    if (!AddNestedExtensions(message_type.nested_type(i), value)) return false;
+  }
+  for (int i = 0; i < message_type.extension_size(); i++) {
+    if (!AddExtension(message_type.extension(i), value)) return false;
+  }
+  return true;
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
+    const FieldDescriptorProto& field,
+    Value value) {
+  if (!field.extendee().empty() && field.extendee()[0] == '.') {
+    // The extension is fully-qualified.  We can use it as a lookup key in
+    // the by_symbol_ table.
+    if (!InsertIfNotPresent(
+            &by_extension_,
+            std::make_pair(field.extendee().substr(1), field.number()),
+            value)) {
+      GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
+                    "extend " << field.extendee() << " { "
+                 << field.name() << " = " << field.number() << " }";
+      return false;
+    }
+  } else {
+    // Not fully-qualified.  We can't really do anything here, unfortunately.
+    // We don't consider this an error, though, because the descriptor is
+    // valid.
+  }
+  return true;
+}
+
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
+    const string& filename) {
+  return FindWithDefault(by_name_, filename, Value());
+}
+
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
+    const string& name) {
+  typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
+
+  return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ?
+         iter->second : Value();
+}
+
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
+    const string& containing_type,
+    int field_number) {
+  return FindWithDefault(
+      by_extension_, std::make_pair(containing_type, field_number), Value());
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
+    const string& containing_type,
+    vector<int>* output) {
+  typename map<pair<string, int>, Value>::const_iterator it =
+      by_extension_.lower_bound(std::make_pair(containing_type, 0));
+  bool success = false;
+
+  for (; it != by_extension_.end() && it->first.first == containing_type;
+       ++it) {
+    output->push_back(it->first.second);
+    success = true;
+  }
+
+  return success;
+}
+
+template <typename Value>
+typename map<string, Value>::iterator
+SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
+    const string& name) {
+  // Find the last key in the map which sorts less than or equal to the
+  // symbol name.  Since upper_bound() returns the *first* key that sorts
+  // *greater* than the input, we want the element immediately before that.
+  typename map<string, Value>::iterator iter = by_symbol_.upper_bound(name);
+  if (iter != by_symbol_.begin()) --iter;
+  return iter;
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
+    const string& sub_symbol, const string& super_symbol) {
+  return sub_symbol == super_symbol ||
+         (HasPrefixString(super_symbol, sub_symbol) &&
+             super_symbol[sub_symbol.size()] == '.');
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
+    const string& name) {
+  for (int i = 0; i < name.size(); i++) {
+    // I don't trust ctype.h due to locales.  :(
+    if (name[i] != '.' && name[i] != '_' &&
+        (name[i] < '0' || name[i] > '9') &&
+        (name[i] < 'A' || name[i] > 'Z') &&
+        (name[i] < 'a' || name[i] > 'z')) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// -------------------------------------------------------------------
+
+SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
+SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
+  STLDeleteElements(&files_to_delete_);
+}
+
+bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
+  FileDescriptorProto* new_file = new FileDescriptorProto;
+  new_file->CopyFrom(file);
+  return AddAndOwn(new_file);
+}
+
+bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
+  files_to_delete_.push_back(file);
+  return index_.AddFile(*file, file);
+}
+
+bool SimpleDescriptorDatabase::FindFileByName(
+    const string& filename,
+    FileDescriptorProto* output) {
+  return MaybeCopy(index_.FindFile(filename), output);
+}
+
+bool SimpleDescriptorDatabase::FindFileContainingSymbol(
+    const string& symbol_name,
+    FileDescriptorProto* output) {
+  return MaybeCopy(index_.FindSymbol(symbol_name), output);
+}
+
+bool SimpleDescriptorDatabase::FindFileContainingExtension(
+    const string& containing_type,
+    int field_number,
+    FileDescriptorProto* output) {
+  return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
+}
+
+bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
+    const string& extendee_type,
+    vector<int>* output) {
+  return index_.FindAllExtensionNumbers(extendee_type, output);
+}
+
+
+bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
+                                         FileDescriptorProto* output) {
+  if (file == NULL) return false;
+  output->CopyFrom(*file);
+  return true;
+}
+
+// -------------------------------------------------------------------
+
+EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
+EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
+  for (int i = 0; i < files_to_delete_.size(); i++) {
+    operator delete(files_to_delete_[i]);
+  }
+}
+
+bool EncodedDescriptorDatabase::Add(
+    const void* encoded_file_descriptor, int size) {
+  FileDescriptorProto file;
+  if (file.ParseFromArray(encoded_file_descriptor, size)) {
+    return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size));
+  } else {
+    GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
+                  "EncodedDescriptorDatabase::Add().";
+    return false;
+  }
+}
+
+bool EncodedDescriptorDatabase::AddCopy(
+    const void* encoded_file_descriptor, int size) {
+  void* copy = operator new(size);
+  memcpy(copy, encoded_file_descriptor, size);
+  files_to_delete_.push_back(copy);
+  return Add(copy, size);
+}
+
+bool EncodedDescriptorDatabase::FindFileByName(
+    const string& filename,
+    FileDescriptorProto* output) {
+  return MaybeParse(index_.FindFile(filename), output);
+}
+
+bool EncodedDescriptorDatabase::FindFileContainingSymbol(
+    const string& symbol_name,
+    FileDescriptorProto* output) {
+  return MaybeParse(index_.FindSymbol(symbol_name), output);
+}
+
+bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
+    const string& symbol_name,
+    string* output) {
+  pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
+  if (encoded_file.first == NULL) return false;
+
+  // Optimization:  The name should be the first field in the encoded message.
+  //   Try to just read it directly.
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
+                             encoded_file.second);
+
+  const uint32 kNameTag = internal::WireFormatLite::MakeTag(
+      FileDescriptorProto::kNameFieldNumber,
+      internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+  if (input.ReadTag() == kNameTag) {
+    // Success!
+    return internal::WireFormatLite::ReadString(&input, output);
+  } else {
+    // Slow path.  Parse whole message.
+    FileDescriptorProto file_proto;
+    if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
+      return false;
+    }
+    *output = file_proto.name();
+    return true;
+  }
+}
+
+bool EncodedDescriptorDatabase::FindFileContainingExtension(
+    const string& containing_type,
+    int field_number,
+    FileDescriptorProto* output) {
+  return MaybeParse(index_.FindExtension(containing_type, field_number),
+                    output);
+}
+
+bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
+    const string& extendee_type,
+    vector<int>* output) {
+  return index_.FindAllExtensionNumbers(extendee_type, output);
+}
+
+bool EncodedDescriptorDatabase::MaybeParse(
+    pair<const void*, int> encoded_file,
+    FileDescriptorProto* output) {
+  if (encoded_file.first == NULL) return false;
+  return output->ParseFromArray(encoded_file.first, encoded_file.second);
+}
+
+// ===================================================================
+
+DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
+  : pool_(pool) {}
+DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
+
+bool DescriptorPoolDatabase::FindFileByName(
+    const string& filename,
+    FileDescriptorProto* output) {
+  const FileDescriptor* file = pool_.FindFileByName(filename);
+  if (file == NULL) return false;
+  output->Clear();
+  file->CopyTo(output);
+  return true;
+}
+
+bool DescriptorPoolDatabase::FindFileContainingSymbol(
+    const string& symbol_name,
+    FileDescriptorProto* output) {
+  const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
+  if (file == NULL) return false;
+  output->Clear();
+  file->CopyTo(output);
+  return true;
+}
+
+bool DescriptorPoolDatabase::FindFileContainingExtension(
+    const string& containing_type,
+    int field_number,
+    FileDescriptorProto* output) {
+  const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
+  if (extendee == NULL) return false;
+
+  const FieldDescriptor* extension =
+    pool_.FindExtensionByNumber(extendee, field_number);
+  if (extension == NULL) return false;
+
+  output->Clear();
+  extension->file()->CopyTo(output);
+  return true;
+}
+
+bool DescriptorPoolDatabase::FindAllExtensionNumbers(
+    const string& extendee_type,
+    vector<int>* output) {
+  const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
+  if (extendee == NULL) return false;
+
+  vector<const FieldDescriptor*> extensions;
+  pool_.FindAllExtensions(extendee, &extensions);
+
+  for (int i = 0; i < extensions.size(); ++i) {
+    output->push_back(extensions[i]->number());
+  }
+
+  return true;
+}
+
+// ===================================================================
+
+MergedDescriptorDatabase::MergedDescriptorDatabase(
+    DescriptorDatabase* source1,
+    DescriptorDatabase* source2) {
+  sources_.push_back(source1);
+  sources_.push_back(source2);
+}
+MergedDescriptorDatabase::MergedDescriptorDatabase(
+    const vector<DescriptorDatabase*>& sources)
+  : sources_(sources) {}
+MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
+
+bool MergedDescriptorDatabase::FindFileByName(
+    const string& filename,
+    FileDescriptorProto* output) {
+  for (int i = 0; i < sources_.size(); i++) {
+    if (sources_[i]->FindFileByName(filename, output)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool MergedDescriptorDatabase::FindFileContainingSymbol(
+    const string& symbol_name,
+    FileDescriptorProto* output) {
+  for (int i = 0; i < sources_.size(); i++) {
+    if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
+      // The symbol was found in source i.  However, if one of the previous
+      // sources defines a file with the same name (which presumably doesn't
+      // contain the symbol, since it wasn't found in that source), then we
+      // must hide it from the caller.
+      FileDescriptorProto temp;
+      for (int j = 0; j < i; j++) {
+        if (sources_[j]->FindFileByName(output->name(), &temp)) {
+          // Found conflicting file in a previous source.
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+bool MergedDescriptorDatabase::FindFileContainingExtension(
+    const string& containing_type,
+    int field_number,
+    FileDescriptorProto* output) {
+  for (int i = 0; i < sources_.size(); i++) {
+    if (sources_[i]->FindFileContainingExtension(
+          containing_type, field_number, output)) {
+      // The symbol was found in source i.  However, if one of the previous
+      // sources defines a file with the same name (which presumably doesn't
+      // contain the symbol, since it wasn't found in that source), then we
+      // must hide it from the caller.
+      FileDescriptorProto temp;
+      for (int j = 0; j < i; j++) {
+        if (sources_[j]->FindFileByName(output->name(), &temp)) {
+          // Found conflicting file in a previous source.
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+bool MergedDescriptorDatabase::FindAllExtensionNumbers(
+    const string& extendee_type,
+    vector<int>* output) {
+  set<int> merged_results;
+  vector<int> results;
+  bool success = false;
+
+  for (int i = 0; i < sources_.size(); i++) {
+    if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
+      std::copy(
+          results.begin(), results.end(),
+          insert_iterator<set<int> >(merged_results, merged_results.begin()));
+      success = true;
+    }
+    results.clear();
+  }
+
+  std::copy(merged_results.begin(), merged_results.end(),
+            insert_iterator<vector<int> >(*output, output->end()));
+
+  return success;
+}
+
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.h b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.h
new file mode 100644
index 0000000..86002d5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database.h
@@ -0,0 +1,369 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Interface for manipulating databases of descriptors.
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
+#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+// Defined in this file.
+class DescriptorDatabase;
+class SimpleDescriptorDatabase;
+class EncodedDescriptorDatabase;
+class DescriptorPoolDatabase;
+class MergedDescriptorDatabase;
+
+// Abstract interface for a database of descriptors.
+//
+// This is useful if you want to create a DescriptorPool which loads
+// descriptors on-demand from some sort of large database.  If the database
+// is large, it may be inefficient to enumerate every .proto file inside it
+// calling DescriptorPool::BuildFile() for each one.  Instead, a DescriptorPool
+// can be created which wraps a DescriptorDatabase and only builds particular
+// descriptors when they are needed.
+class LIBPROTOBUF_EXPORT DescriptorDatabase {
+ public:
+  inline DescriptorDatabase() {}
+  virtual ~DescriptorDatabase();
+
+  // Find a file by file name.  Fills in in *output and returns true if found.
+  // Otherwise, returns false, leaving the contents of *output undefined.
+  virtual bool FindFileByName(const string& filename,
+                              FileDescriptorProto* output) = 0;
+
+  // Find the file that declares the given fully-qualified symbol name.
+  // If found, fills in *output and returns true, otherwise returns false
+  // and leaves *output undefined.
+  virtual bool FindFileContainingSymbol(const string& symbol_name,
+                                        FileDescriptorProto* output) = 0;
+
+  // Find the file which defines an extension extending the given message type
+  // with the given field number.  If found, fills in *output and returns true,
+  // otherwise returns false and leaves *output undefined.  containing_type
+  // must be a fully-qualified type name.
+  virtual bool FindFileContainingExtension(const string& containing_type,
+                                           int field_number,
+                                           FileDescriptorProto* output) = 0;
+
+  // Finds the tag numbers used by all known extensions of
+  // extendee_type, and appends them to output in an undefined
+  // order. This method is best-effort: it's not guaranteed that the
+  // database will find all extensions, and it's not guaranteed that
+  // FindFileContainingExtension will return true on all of the found
+  // numbers. Returns true if the search was successful, otherwise
+  // returns false and leaves output unchanged.
+  //
+  // This method has a default implementation that always returns
+  // false.
+  virtual bool FindAllExtensionNumbers(const string& /* extendee_type */,
+                                       vector<int>* /* output */) {
+    return false;
+  }
+
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
+};
+
+// A DescriptorDatabase into which you can insert files manually.
+//
+// FindFileContainingSymbol() is fully-implemented.  When you add a file, its
+// symbols will be indexed for this purpose.  Note that the implementation
+// may return false positives, but only if it isn't possible for the symbol
+// to be defined in any other file.  In particular, if a file defines a symbol
+// "Foo", then searching for "Foo.[anything]" will match that file.  This way,
+// the database does not need to aggressively index all children of a symbol.
+//
+// FindFileContainingExtension() is mostly-implemented.  It works if and only
+// if the original FieldDescriptorProto defining the extension has a
+// fully-qualified type name in its "extendee" field (i.e. starts with a '.').
+// If the extendee is a relative name, SimpleDescriptorDatabase will not
+// attempt to resolve the type, so it will not know what type the extension is
+// extending.  Therefore, calling FindFileContainingExtension() with the
+// extension's containing type will never actually find that extension.  Note
+// that this is an unlikely problem, as all FileDescriptorProtos created by the
+// protocol compiler (as well as ones created by calling
+// FileDescriptor::CopyTo()) will always use fully-qualified names for all
+// types.  You only need to worry if you are constructing FileDescriptorProtos
+// yourself, or are calling compiler::Parser directly.
+class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
+ public:
+  SimpleDescriptorDatabase();
+  ~SimpleDescriptorDatabase();
+
+  // Adds the FileDescriptorProto to the database, making a copy.  The object
+  // can be deleted after Add() returns.  Returns false if the file conflicted
+  // with a file already in the database, in which case an error will have
+  // been written to GOOGLE_LOG(ERROR).
+  bool Add(const FileDescriptorProto& file);
+
+  // Adds the FileDescriptorProto to the database and takes ownership of it.
+  bool AddAndOwn(const FileDescriptorProto* file);
+
+  // implements DescriptorDatabase -----------------------------------
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output);
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+  bool FindAllExtensionNumbers(const string& extendee_type,
+                               vector<int>* output);
+
+ private:
+  // So that it can use DescriptorIndex.
+  friend class EncodedDescriptorDatabase;
+
+  // An index mapping file names, symbol names, and extension numbers to
+  // some sort of values.
+  template <typename Value>
+  class DescriptorIndex {
+   public:
+    // Helpers to recursively add particular descriptors and all their contents
+    // to the index.
+    bool AddFile(const FileDescriptorProto& file,
+                 Value value);
+    bool AddSymbol(const string& name, Value value);
+    bool AddNestedExtensions(const DescriptorProto& message_type,
+                             Value value);
+    bool AddExtension(const FieldDescriptorProto& field,
+                      Value value);
+
+    Value FindFile(const string& filename);
+    Value FindSymbol(const string& name);
+    Value FindExtension(const string& containing_type, int field_number);
+    bool FindAllExtensionNumbers(const string& containing_type,
+                                 vector<int>* output);
+
+   private:
+    map<string, Value> by_name_;
+    map<string, Value> by_symbol_;
+    map<pair<string, int>, Value> by_extension_;
+
+    // Invariant:  The by_symbol_ map does not contain any symbols which are
+    // prefixes of other symbols in the map.  For example, "foo.bar" is a
+    // prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
+    //
+    // This invariant is important because it means that given a symbol name,
+    // we can find a key in the map which is a prefix of the symbol in O(lg n)
+    // time, and we know that there is at most one such key.
+    //
+    // The prefix lookup algorithm works like so:
+    // 1) Find the last key in the map which is less than or equal to the
+    //    search key.
+    // 2) If the found key is a prefix of the search key, then return it.
+    //    Otherwise, there is no match.
+    //
+    // I am sure this algorithm has been described elsewhere, but since I
+    // wasn't able to find it quickly I will instead prove that it works
+    // myself.  The key to the algorithm is that if a match exists, step (1)
+    // will find it.  Proof:
+    // 1) Define the "search key" to be the key we are looking for, the "found
+    //    key" to be the key found in step (1), and the "match key" to be the
+    //    key which actually matches the serach key (i.e. the key we're trying
+    //    to find).
+    // 2) The found key must be less than or equal to the search key by
+    //    definition.
+    // 3) The match key must also be less than or equal to the search key
+    //    (because it is a prefix).
+    // 4) The match key cannot be greater than the found key, because if it
+    //    were, then step (1) of the algorithm would have returned the match
+    //    key instead (since it finds the *greatest* key which is less than or
+    //    equal to the search key).
+    // 5) Therefore, the found key must be between the match key and the search
+    //    key, inclusive.
+    // 6) Since the search key must be a sub-symbol of the match key, if it is
+    //    not equal to the match key, then search_key[match_key.size()] must
+    //    be '.'.
+    // 7) Since '.' sorts before any other character that is valid in a symbol
+    //    name, then if the found key is not equal to the match key, then
+    //    found_key[match_key.size()] must also be '.', because any other value
+    //    would make it sort after the search key.
+    // 8) Therefore, if the found key is not equal to the match key, then the
+    //    found key must be a sub-symbol of the match key.  However, this would
+    //    contradict our map invariant which says that no symbol in the map is
+    //    a sub-symbol of any other.
+    // 9) Therefore, the found key must match the match key.
+    //
+    // The above proof assumes the match key exists.  In the case that the
+    // match key does not exist, then step (1) will return some other symbol.
+    // That symbol cannot be a super-symbol of the search key since if it were,
+    // then it would be a match, and we're assuming the match key doesn't exist.
+    // Therefore, step 2 will correctly return no match.
+
+    // Find the last entry in the by_symbol_ map whose key is less than or
+    // equal to the given name.
+    typename map<string, Value>::iterator FindLastLessOrEqual(
+        const string& name);
+
+    // True if either the arguments are equal or super_symbol identifies a
+    // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
+    // "foo.bar.baz", but not a parent of "foo.barbaz").
+    bool IsSubSymbol(const string& sub_symbol, const string& super_symbol);
+
+    // Returns true if and only if all characters in the name are alphanumerics,
+    // underscores, or periods.
+    bool ValidateSymbolName(const string& name);
+  };
+
+
+  DescriptorIndex<const FileDescriptorProto*> index_;
+  vector<const FileDescriptorProto*> files_to_delete_;
+
+  // If file is non-NULL, copy it into *output and return true, otherwise
+  // return false.
+  bool MaybeCopy(const FileDescriptorProto* file,
+                 FileDescriptorProto* output);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
+};
+
+// Very similar to SimpleDescriptorDatabase, but stores all the descriptors
+// as raw bytes and generally tries to use as little memory as possible.
+//
+// The same caveats regarding FindFileContainingExtension() apply as with
+// SimpleDescriptorDatabase.
+class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
+ public:
+  EncodedDescriptorDatabase();
+  ~EncodedDescriptorDatabase();
+
+  // Adds the FileDescriptorProto to the database.  The descriptor is provided
+  // in encoded form.  The database does not make a copy of the bytes, nor
+  // does it take ownership; it's up to the caller to make sure the bytes
+  // remain valid for the life of the database.  Returns false and logs an error
+  // if the bytes are not a valid FileDescriptorProto or if the file conflicted
+  // with a file already in the database.
+  bool Add(const void* encoded_file_descriptor, int size);
+
+  // Like Add(), but makes a copy of the data, so that the caller does not
+  // need to keep it around.
+  bool AddCopy(const void* encoded_file_descriptor, int size);
+
+  // Like FindFileContainingSymbol but returns only the name of the file.
+  bool FindNameOfFileContainingSymbol(const string& symbol_name,
+                                      string* output);
+
+  // implements DescriptorDatabase -----------------------------------
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output);
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+  bool FindAllExtensionNumbers(const string& extendee_type,
+                               vector<int>* output);
+
+ private:
+  SimpleDescriptorDatabase::DescriptorIndex<pair<const void*, int> > index_;
+  vector<void*> files_to_delete_;
+
+  // If encoded_file.first is non-NULL, parse the data into *output and return
+  // true, otherwise return false.
+  bool MaybeParse(pair<const void*, int> encoded_file,
+                  FileDescriptorProto* output);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
+};
+
+// A DescriptorDatabase that fetches files from a given pool.
+class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
+ public:
+  explicit DescriptorPoolDatabase(const DescriptorPool& pool);
+  ~DescriptorPoolDatabase();
+
+  // implements DescriptorDatabase -----------------------------------
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output);
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+  bool FindAllExtensionNumbers(const string& extendee_type,
+                               vector<int>* output);
+
+ private:
+  const DescriptorPool& pool_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
+};
+
+// A DescriptorDatabase that wraps two or more others.  It first searches the
+// first database and, if that fails, tries the second, and so on.
+class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
+ public:
+  // Merge just two databases.  The sources remain property of the caller.
+  MergedDescriptorDatabase(DescriptorDatabase* source1,
+                           DescriptorDatabase* source2);
+  // Merge more than two databases.  The sources remain property of the caller.
+  // The vector may be deleted after the constructor returns but the
+  // DescriptorDatabases need to stick around.
+  explicit MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
+  ~MergedDescriptorDatabase();
+
+  // implements DescriptorDatabase -----------------------------------
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output);
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output);
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output);
+  // Merges the results of calling all databases. Returns true iff any
+  // of the databases returned true.
+  bool FindAllExtensionNumbers(const string& extendee_type,
+                               vector<int>* output);
+
+
+ private:
+  vector<DescriptorDatabase*> sources_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor_database_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database_unittest.cc
new file mode 100644
index 0000000..1fc3816
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor_database_unittest.cc
@@ -0,0 +1,754 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file makes extensive use of RFC 3092.  :)
+
+#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+static void AddToDatabase(SimpleDescriptorDatabase* database,
+                          const char* file_text) {
+  FileDescriptorProto file_proto;
+  EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+  database->Add(file_proto);
+}
+
+static void ExpectContainsType(const FileDescriptorProto& proto,
+                               const string& type_name) {
+  for (int i = 0; i < proto.message_type_size(); i++) {
+    if (proto.message_type(i).name() == type_name) return;
+  }
+  ADD_FAILURE() << "\"" << proto.name()
+                << "\" did not contain expected type \""
+                << type_name << "\".";
+}
+
+// ===================================================================
+
+#if GTEST_HAS_PARAM_TEST
+
+// SimpleDescriptorDatabase, EncodedDescriptorDatabase, and
+// DescriptorPoolDatabase call for very similar tests.  Instead of writing
+// three nearly-identical sets of tests, we use parameterized tests to apply
+// the same code to all three.
+
+// The parameterized test runs against a DescriptarDatabaseTestCase.  We have
+// implementations for each of the three classes we want to test.
+class DescriptorDatabaseTestCase {
+ public:
+  virtual ~DescriptorDatabaseTestCase() {}
+
+  virtual DescriptorDatabase* GetDatabase() = 0;
+  virtual bool AddToDatabase(const FileDescriptorProto& file) = 0;
+};
+
+// Factory function type.
+typedef DescriptorDatabaseTestCase* DescriptorDatabaseTestCaseFactory();
+
+// Specialization for SimpleDescriptorDatabase.
+class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+  static DescriptorDatabaseTestCase* New() {
+    return new SimpleDescriptorDatabaseTestCase;
+  }
+
+  virtual ~SimpleDescriptorDatabaseTestCase() {}
+
+  virtual DescriptorDatabase* GetDatabase() {
+    return &database_;
+  }
+  virtual bool AddToDatabase(const FileDescriptorProto& file) {
+    return database_.Add(file);
+  }
+
+ private:
+  SimpleDescriptorDatabase database_;
+};
+
+// Specialization for EncodedDescriptorDatabase.
+class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+  static DescriptorDatabaseTestCase* New() {
+    return new EncodedDescriptorDatabaseTestCase;
+  }
+
+  virtual ~EncodedDescriptorDatabaseTestCase() {}
+
+  virtual DescriptorDatabase* GetDatabase() {
+    return &database_;
+  }
+  virtual bool AddToDatabase(const FileDescriptorProto& file) {
+    string data;
+    file.SerializeToString(&data);
+    return database_.AddCopy(data.data(), data.size());
+  }
+
+ private:
+  EncodedDescriptorDatabase database_;
+};
+
+// Specialization for DescriptorPoolDatabase.
+class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+  static DescriptorDatabaseTestCase* New() {
+    return new EncodedDescriptorDatabaseTestCase;
+  }
+
+  DescriptorPoolDatabaseTestCase() : database_(pool_) {}
+  virtual ~DescriptorPoolDatabaseTestCase() {}
+
+  virtual DescriptorDatabase* GetDatabase() {
+    return &database_;
+  }
+  virtual bool AddToDatabase(const FileDescriptorProto& file) {
+    return pool_.BuildFile(file);
+  }
+
+ private:
+  DescriptorPool pool_;
+  DescriptorPoolDatabase database_;
+};
+
+// -------------------------------------------------------------------
+
+class DescriptorDatabaseTest
+    : public testing::TestWithParam<DescriptorDatabaseTestCaseFactory*> {
+ protected:
+  virtual void SetUp() {
+    test_case_.reset(GetParam()());
+    database_ = test_case_->GetDatabase();
+  }
+
+  void AddToDatabase(const char* file_descriptor_text) {
+    FileDescriptorProto file_proto;
+    EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
+    EXPECT_TRUE(test_case_->AddToDatabase(file_proto));
+  }
+
+  void AddToDatabaseWithError(const char* file_descriptor_text) {
+    FileDescriptorProto file_proto;
+    EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
+    EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
+  }
+
+  google::protobuf::scoped_ptr<DescriptorDatabaseTestCase> test_case_;
+  DescriptorDatabase* database_;
+};
+
+TEST_P(DescriptorDatabaseTest, FindFileByName) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { name:\"Foo\" }");
+  AddToDatabase(
+    "name: \"bar.proto\" "
+    "message_type { name:\"Bar\" }");
+
+  {
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileByName("foo.proto", &file));
+    EXPECT_EQ("foo.proto", file.name());
+    ExpectContainsType(file, "Foo");
+  }
+
+  {
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileByName("bar.proto", &file));
+    EXPECT_EQ("bar.proto", file.name());
+    ExpectContainsType(file, "Bar");
+  }
+
+  {
+    // Fails to find undefined files.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileByName("baz.proto", &file));
+  }
+}
+
+TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  field { name:\"qux\" }"
+    "  nested_type { name: \"Grault\" } "
+    "  enum_type { name: \"Garply\" } "
+    "} "
+    "enum_type { "
+    "  name: \"Waldo\" "
+    "  value { name:\"FRED\" } "
+    "} "
+    "extension { name: \"plugh\" } "
+    "service { "
+    "  name: \"Xyzzy\" "
+    "  method { name: \"Thud\" } "
+    "}"
+    );
+  AddToDatabase(
+    "name: \"bar.proto\" "
+    "package: \"corge\" "
+    "message_type { name: \"Bar\" }");
+
+  {
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Foo", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find fields.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find nested types.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Grault", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find nested enums.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Garply", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find enum types.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find enum values.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo.FRED", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find extensions.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("plugh", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find services.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find methods.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy.Thud", &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    // Can find things in packages.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingSymbol("corge.Bar", &file));
+    EXPECT_EQ("bar.proto", file.name());
+  }
+
+  {
+    // Fails to find undefined symbols.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileContainingSymbol("Baz", &file));
+  }
+
+  {
+    // Names must be fully-qualified.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileContainingSymbol("Bar", &file));
+  }
+}
+
+TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  extension_range { start: 1 end: 1000 } "
+    "  extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+    "              extendee: \".Foo\" }"
+    "}");
+  AddToDatabase(
+    "name: \"bar.proto\" "
+    "package: \"corge\" "
+    "dependency: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Bar\" "
+    "  extension_range { start: 1 end: 1000 } "
+    "} "
+    "extension { name:\"grault\" extendee: \".Foo\"       number:32 } "
+    "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
+    "extension { name:\"waldo\"  extendee: \"Bar\"        number:56 } ");
+
+  {
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 5, &file));
+    EXPECT_EQ("foo.proto", file.name());
+  }
+
+  {
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 32, &file));
+    EXPECT_EQ("bar.proto", file.name());
+  }
+
+  {
+    // Can find extensions for qualified type names.
+    FileDescriptorProto file;
+    EXPECT_TRUE(database_->FindFileContainingExtension("corge.Bar", 70, &file));
+    EXPECT_EQ("bar.proto", file.name());
+  }
+
+  {
+    // Can't find extensions whose extendee was not fully-qualified in the
+    // FileDescriptorProto.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 56, &file));
+    EXPECT_FALSE(
+        database_->FindFileContainingExtension("corge.Bar", 56, &file));
+  }
+
+  {
+    // Can't find non-existent extension numbers.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileContainingExtension("Foo", 12, &file));
+  }
+
+  {
+    // Can't find extensions for non-existent types.
+    FileDescriptorProto file;
+    EXPECT_FALSE(
+        database_->FindFileContainingExtension("NoSuchType", 5, &file));
+  }
+
+  {
+    // Can't find extensions for unqualified type names.
+    FileDescriptorProto file;
+    EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 70, &file));
+  }
+}
+
+TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  extension_range { start: 1 end: 1000 } "
+    "  extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+    "              extendee: \".Foo\" }"
+    "}");
+  AddToDatabase(
+    "name: \"bar.proto\" "
+    "package: \"corge\" "
+    "dependency: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Bar\" "
+    "  extension_range { start: 1 end: 1000 } "
+    "} "
+    "extension { name:\"grault\" extendee: \".Foo\"       number:32 } "
+    "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
+    "extension { name:\"waldo\"  extendee: \"Bar\"        number:56 } ");
+
+  {
+    vector<int> numbers;
+    EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
+    ASSERT_EQ(2, numbers.size());
+    std::sort(numbers.begin(), numbers.end());
+    EXPECT_EQ(5, numbers[0]);
+    EXPECT_EQ(32, numbers[1]);
+  }
+
+  {
+    vector<int> numbers;
+    EXPECT_TRUE(database_->FindAllExtensionNumbers("corge.Bar", &numbers));
+    // Note: won't find extension 56 due to the name not being fully qualified.
+    ASSERT_EQ(1, numbers.size());
+    EXPECT_EQ(70, numbers[0]);
+  }
+
+  {
+    // Can't find extensions for non-existent types.
+    vector<int> numbers;
+    EXPECT_FALSE(database_->FindAllExtensionNumbers("NoSuchType", &numbers));
+  }
+
+  {
+    // Can't find extensions for unqualified types.
+    vector<int> numbers;
+    EXPECT_FALSE(database_->FindAllExtensionNumbers("Bar", &numbers));
+  }
+}
+
+TEST_P(DescriptorDatabaseTest, ConflictingFileError) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "}");
+  AddToDatabaseWithError(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Bar\" "
+    "}");
+}
+
+TEST_P(DescriptorDatabaseTest, ConflictingTypeError) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "}");
+  AddToDatabaseWithError(
+    "name: \"bar.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "}");
+}
+
+TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) {
+  AddToDatabase(
+    "name: \"foo.proto\" "
+    "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+    "            extendee: \".Foo\" }");
+  AddToDatabaseWithError(
+    "name: \"bar.proto\" "
+    "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+    "            extendee: \".Foo\" }");
+}
+
+INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest,
+    testing::Values(&SimpleDescriptorDatabaseTestCase::New));
+INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest,
+    testing::Values(&EncodedDescriptorDatabaseTestCase::New));
+INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
+    testing::Values(&DescriptorPoolDatabaseTestCase::New));
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) {
+  // Create two files, one of which is in two parts.
+  FileDescriptorProto file1, file2a, file2b;
+  file1.set_name("foo.proto");
+  file1.set_package("foo");
+  file1.add_message_type()->set_name("Foo");
+  file2a.set_name("bar.proto");
+  file2b.set_package("bar");
+  file2b.add_message_type()->set_name("Bar");
+
+  // Normal serialization allows our optimization to kick in.
+  string data1 = file1.SerializeAsString();
+
+  // Force out-of-order serialization to test slow path.
+  string data2 = file2b.SerializeAsString() + file2a.SerializeAsString();
+
+  // Create EncodedDescriptorDatabase containing both files.
+  EncodedDescriptorDatabase db;
+  db.Add(data1.data(), data1.size());
+  db.Add(data2.data(), data2.size());
+
+  // Test!
+  string filename;
+  EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename));
+  EXPECT_EQ("foo.proto", filename);
+  EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename));
+  EXPECT_EQ("foo.proto", filename);
+  EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename));
+  EXPECT_EQ("bar.proto", filename);
+  EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename));
+  EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename));
+  EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename));
+}
+
+// ===================================================================
+
+class MergedDescriptorDatabaseTest : public testing::Test {
+ protected:
+  MergedDescriptorDatabaseTest()
+    : forward_merged_(&database1_, &database2_),
+      reverse_merged_(&database2_, &database1_) {}
+
+  virtual void SetUp() {
+    AddToDatabase(&database1_,
+      "name: \"foo.proto\" "
+      "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
+      "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+    AddToDatabase(&database2_,
+      "name: \"bar.proto\" "
+      "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } "
+      "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+
+    // baz.proto exists in both pools, with different definitions.
+    AddToDatabase(&database1_,
+      "name: \"baz.proto\" "
+      "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
+      "message_type { name:\"FromPool1\" } "
+      "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } "
+      "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+    AddToDatabase(&database2_,
+      "name: \"baz.proto\" "
+      "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } "
+      "message_type { name:\"FromPool2\" } "
+      "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+  }
+
+  SimpleDescriptorDatabase database1_;
+  SimpleDescriptorDatabase database2_;
+
+  MergedDescriptorDatabase forward_merged_;
+  MergedDescriptorDatabase reverse_merged_;
+};
+
+TEST_F(MergedDescriptorDatabaseTest, FindFileByName) {
+  {
+    // Can find file that is only in database1_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileByName("foo.proto", &file));
+    EXPECT_EQ("foo.proto", file.name());
+    ExpectContainsType(file, "Foo");
+  }
+
+  {
+    // Can find file that is only in database2_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileByName("bar.proto", &file));
+    EXPECT_EQ("bar.proto", file.name());
+    ExpectContainsType(file, "Bar");
+  }
+
+  {
+    // In forward_merged_, database1_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileByName("baz.proto", &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool1");
+  }
+
+  {
+    // In reverse_merged_, database2_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(reverse_merged_.FindFileByName("baz.proto", &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool2");
+  }
+
+  {
+    // Can't find non-existent file.
+    FileDescriptorProto file;
+    EXPECT_FALSE(forward_merged_.FindFileByName("no_such.proto", &file));
+  }
+}
+
+TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) {
+  {
+    // Can find file that is only in database1_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Foo", &file));
+    EXPECT_EQ("foo.proto", file.name());
+    ExpectContainsType(file, "Foo");
+  }
+
+  {
+    // Can find file that is only in database2_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Bar", &file));
+    EXPECT_EQ("bar.proto", file.name());
+    ExpectContainsType(file, "Bar");
+  }
+
+  {
+    // In forward_merged_, database1_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Baz", &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool1");
+  }
+
+  {
+    // In reverse_merged_, database2_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(reverse_merged_.FindFileContainingSymbol("Baz", &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool2");
+  }
+
+  {
+    // FromPool1 only shows up in forward_merged_ because it is masked by
+    // database2_'s baz.proto in reverse_merged_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("FromPool1", &file));
+    EXPECT_FALSE(reverse_merged_.FindFileContainingSymbol("FromPool1", &file));
+  }
+
+  {
+    // Can't find non-existent symbol.
+    FileDescriptorProto file;
+    EXPECT_FALSE(
+      forward_merged_.FindFileContainingSymbol("NoSuchType", &file));
+  }
+}
+
+TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) {
+  {
+    // Can find file that is only in database1_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(
+      forward_merged_.FindFileContainingExtension("Foo", 3, &file));
+    EXPECT_EQ("foo.proto", file.name());
+    ExpectContainsType(file, "Foo");
+  }
+
+  {
+    // Can find file that is only in database2_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(
+      forward_merged_.FindFileContainingExtension("Bar", 5, &file));
+    EXPECT_EQ("bar.proto", file.name());
+    ExpectContainsType(file, "Bar");
+  }
+
+  {
+    // In forward_merged_, database1_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(
+      forward_merged_.FindFileContainingExtension("Baz", 12, &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool1");
+  }
+
+  {
+    // In reverse_merged_, database2_'s baz.proto takes precedence.
+    FileDescriptorProto file;
+    EXPECT_TRUE(
+      reverse_merged_.FindFileContainingExtension("Baz", 12, &file));
+    EXPECT_EQ("baz.proto", file.name());
+    ExpectContainsType(file, "FromPool2");
+  }
+
+  {
+    // Baz's extension 13 only shows up in forward_merged_ because it is
+    // masked by database2_'s baz.proto in reverse_merged_.
+    FileDescriptorProto file;
+    EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 13, &file));
+    EXPECT_FALSE(reverse_merged_.FindFileContainingExtension("Baz", 13, &file));
+  }
+
+  {
+    // Can't find non-existent extension.
+    FileDescriptorProto file;
+    EXPECT_FALSE(
+      forward_merged_.FindFileContainingExtension("Foo", 6, &file));
+  }
+}
+
+TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
+  {
+    // Message only has extension in database1_
+    vector<int> numbers;
+    EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Foo", &numbers));
+    ASSERT_EQ(1, numbers.size());
+    EXPECT_EQ(3, numbers[0]);
+  }
+
+  {
+    // Message only has extension in database2_
+    vector<int> numbers;
+    EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Bar", &numbers));
+    ASSERT_EQ(1, numbers.size());
+    EXPECT_EQ(5, numbers[0]);
+  }
+
+  {
+    // Merge results from the two databases.
+    vector<int> numbers;
+    EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
+    ASSERT_EQ(2, numbers.size());
+    std::sort(numbers.begin(), numbers.end());
+    EXPECT_EQ(12, numbers[0]);
+    EXPECT_EQ(13, numbers[1]);
+  }
+
+  {
+    vector<int> numbers;
+    EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
+    ASSERT_EQ(2, numbers.size());
+    std::sort(numbers.begin(), numbers.end());
+    EXPECT_EQ(12, numbers[0]);
+    EXPECT_EQ(13, numbers[1]);
+  }
+
+  {
+    // Can't find extensions for a non-existent message.
+    vector<int> numbers;
+    EXPECT_FALSE(reverse_merged_.FindAllExtensionNumbers("Blah", &numbers));
+  }
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/descriptor_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/descriptor_unittest.cc
new file mode 100644
index 0000000..f937b9e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/descriptor_unittest.cc
@@ -0,0 +1,6613 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file makes extensive use of RFC 3092.  :)
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace descriptor_unittest {
+
+// Some helpers to make assembling descriptors faster.
+DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
+  DescriptorProto* result = file->add_message_type();
+  result->set_name(name);
+  return result;
+}
+
+DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
+  DescriptorProto* result = parent->add_nested_type();
+  result->set_name(name);
+  return result;
+}
+
+EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
+  EnumDescriptorProto* result = file->add_enum_type();
+  result->set_name(name);
+  return result;
+}
+
+EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
+                                   const string& name) {
+  EnumDescriptorProto* result = parent->add_enum_type();
+  result->set_name(name);
+  return result;
+}
+
+ServiceDescriptorProto* AddService(FileDescriptorProto* file,
+                                   const string& name) {
+  ServiceDescriptorProto* result = file->add_service();
+  result->set_name(name);
+  return result;
+}
+
+FieldDescriptorProto* AddField(DescriptorProto* parent,
+                               const string& name, int number,
+                               FieldDescriptorProto::Label label,
+                               FieldDescriptorProto::Type type) {
+  FieldDescriptorProto* result = parent->add_field();
+  result->set_name(name);
+  result->set_number(number);
+  result->set_label(label);
+  result->set_type(type);
+  return result;
+}
+
+FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
+                                   const string& extendee,
+                                   const string& name, int number,
+                                   FieldDescriptorProto::Label label,
+                                   FieldDescriptorProto::Type type) {
+  FieldDescriptorProto* result = file->add_extension();
+  result->set_name(name);
+  result->set_number(number);
+  result->set_label(label);
+  result->set_type(type);
+  result->set_extendee(extendee);
+  return result;
+}
+
+FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
+                                         const string& extendee,
+                                         const string& name, int number,
+                                         FieldDescriptorProto::Label label,
+                                         FieldDescriptorProto::Type type) {
+  FieldDescriptorProto* result = parent->add_extension();
+  result->set_name(name);
+  result->set_number(number);
+  result->set_label(label);
+  result->set_type(type);
+  result->set_extendee(extendee);
+  return result;
+}
+
+DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
+                                                   int start, int end) {
+  DescriptorProto::ExtensionRange* result = parent->add_extension_range();
+  result->set_start(start);
+  result->set_end(end);
+  return result;
+}
+
+DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
+                                                 int start, int end) {
+  DescriptorProto::ReservedRange* result = parent->add_reserved_range();
+  result->set_start(start);
+  result->set_end(end);
+  return result;
+}
+
+EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
+                                       const string& name, int number) {
+  EnumValueDescriptorProto* result = enum_proto->add_value();
+  result->set_name(name);
+  result->set_number(number);
+  return result;
+}
+
+MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
+                                 const string& name,
+                                 const string& input_type,
+                                 const string& output_type) {
+  MethodDescriptorProto* result = service->add_method();
+  result->set_name(name);
+  result->set_input_type(input_type);
+  result->set_output_type(output_type);
+  return result;
+}
+
+// Empty enums technically aren't allowed.  We need to insert a dummy value
+// into them.
+void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
+  AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
+}
+
+class MockErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+  string warning_text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename,
+                const string& element_name, const Message* descriptor,
+                ErrorLocation location, const string& message) {
+    const char* location_name = NULL;
+    switch (location) {
+      case NAME         : location_name = "NAME"         ; break;
+      case NUMBER       : location_name = "NUMBER"       ; break;
+      case TYPE         : location_name = "TYPE"         ; break;
+      case EXTENDEE     : location_name = "EXTENDEE"     ; break;
+      case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
+      case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
+      case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
+      case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
+      case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
+      case OTHER        : location_name = "OTHER"        ; break;
+    }
+
+    strings::SubstituteAndAppend(
+      &text_, "$0: $1: $2: $3\n",
+      filename, element_name, location_name, message);
+  }
+
+  // implements ErrorCollector ---------------------------------------
+  void AddWarning(const string& filename, const string& element_name,
+                  const Message* descriptor, ErrorLocation location,
+                  const string& message) {
+    const char* location_name = NULL;
+    switch (location) {
+      case NAME         : location_name = "NAME"         ; break;
+      case NUMBER       : location_name = "NUMBER"       ; break;
+      case TYPE         : location_name = "TYPE"         ; break;
+      case EXTENDEE     : location_name = "EXTENDEE"     ; break;
+      case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
+      case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
+      case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
+      case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
+      case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
+      case OTHER        : location_name = "OTHER"        ; break;
+    }
+
+    strings::SubstituteAndAppend(
+      &warning_text_, "$0: $1: $2: $3\n",
+      filename, element_name, location_name, message);
+  }
+};
+
+// ===================================================================
+
+// Test simple files.
+class FileDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   // in "foo.proto"
+    //   message FooMessage { extensions 1; }
+    //   enum FooEnum {FOO_ENUM_VALUE = 1;}
+    //   service FooService {}
+    //   extend FooMessage { optional int32 foo_extension = 1; }
+    //
+    //   // in "bar.proto"
+    //   package bar_package;
+    //   message BarMessage { extensions 1; }
+    //   enum BarEnum {BAR_ENUM_VALUE = 1;}
+    //   service BarService {}
+    //   extend BarMessage { optional int32 bar_extension = 1; }
+    //
+    // Also, we have an empty file "baz.proto".  This file's purpose is to
+    // make sure that even though it has the same package as foo.proto,
+    // searching it for members of foo.proto won't work.
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+    AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
+    AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
+    AddService(&foo_file, "FooService");
+    AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+
+    FileDescriptorProto bar_file;
+    bar_file.set_name("bar.proto");
+    bar_file.set_package("bar_package");
+    bar_file.add_dependency("foo.proto");
+    AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
+    AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
+    AddService(&bar_file, "BarService");
+    AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+
+    FileDescriptorProto baz_file;
+    baz_file.set_name("baz.proto");
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    bar_file_ = pool_.BuildFile(bar_file);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    baz_file_ = pool_.BuildFile(baz_file);
+    ASSERT_TRUE(baz_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->message_type_count());
+    foo_message_ = foo_file_->message_type(0);
+    ASSERT_EQ(1, foo_file_->enum_type_count());
+    foo_enum_ = foo_file_->enum_type(0);
+    ASSERT_EQ(1, foo_enum_->value_count());
+    foo_enum_value_ = foo_enum_->value(0);
+    ASSERT_EQ(1, foo_file_->service_count());
+    foo_service_ = foo_file_->service(0);
+    ASSERT_EQ(1, foo_file_->extension_count());
+    foo_extension_ = foo_file_->extension(0);
+
+    ASSERT_EQ(1, bar_file_->message_type_count());
+    bar_message_ = bar_file_->message_type(0);
+    ASSERT_EQ(1, bar_file_->enum_type_count());
+    bar_enum_ = bar_file_->enum_type(0);
+    ASSERT_EQ(1, bar_enum_->value_count());
+    bar_enum_value_ = bar_enum_->value(0);
+    ASSERT_EQ(1, bar_file_->service_count());
+    bar_service_ = bar_file_->service(0);
+    ASSERT_EQ(1, bar_file_->extension_count());
+    bar_extension_ = bar_file_->extension(0);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+  const FileDescriptor* bar_file_;
+  const FileDescriptor* baz_file_;
+
+  const Descriptor*          foo_message_;
+  const EnumDescriptor*      foo_enum_;
+  const EnumValueDescriptor* foo_enum_value_;
+  const ServiceDescriptor*   foo_service_;
+  const FieldDescriptor*     foo_extension_;
+
+  const Descriptor*          bar_message_;
+  const EnumDescriptor*      bar_enum_;
+  const EnumValueDescriptor* bar_enum_value_;
+  const ServiceDescriptor*   bar_service_;
+  const FieldDescriptor*     bar_extension_;
+};
+
+TEST_F(FileDescriptorTest, Name) {
+  EXPECT_EQ("foo.proto", foo_file_->name());
+  EXPECT_EQ("bar.proto", bar_file_->name());
+  EXPECT_EQ("baz.proto", baz_file_->name());
+}
+
+TEST_F(FileDescriptorTest, Package) {
+  EXPECT_EQ("", foo_file_->package());
+  EXPECT_EQ("bar_package", bar_file_->package());
+}
+
+TEST_F(FileDescriptorTest, Dependencies) {
+  EXPECT_EQ(0, foo_file_->dependency_count());
+  EXPECT_EQ(1, bar_file_->dependency_count());
+  EXPECT_EQ(foo_file_, bar_file_->dependency(0));
+}
+
+TEST_F(FileDescriptorTest, FindMessageTypeByName) {
+  EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
+  EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
+
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
+  EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
+  EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
+
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
+}
+
+TEST_F(FileDescriptorTest, FindEnumTypeByName) {
+  EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
+  EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
+
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
+  EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
+  EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
+
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
+}
+
+TEST_F(FileDescriptorTest, FindEnumValueByName) {
+  EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
+  EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
+
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
+  EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
+  EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
+
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
+}
+
+TEST_F(FileDescriptorTest, FindServiceByName) {
+  EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
+  EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
+
+  EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
+  EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
+  EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
+
+  EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
+  EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
+}
+
+TEST_F(FileDescriptorTest, FindExtensionByName) {
+  EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
+  EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
+
+  EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
+  EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
+  EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
+
+  EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
+  EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
+}
+
+TEST_F(FileDescriptorTest, FindExtensionByNumber) {
+  EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
+  EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
+
+  EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
+}
+
+TEST_F(FileDescriptorTest, BuildAgain) {
+  // Test that if te call BuildFile again on the same input we get the same
+  // FileDescriptor back.
+  FileDescriptorProto file;
+  foo_file_->CopyTo(&file);
+  EXPECT_EQ(foo_file_, pool_.BuildFile(file));
+
+  // But if we change the file then it won't work.
+  file.set_package("some.other.package");
+  EXPECT_TRUE(pool_.BuildFile(file) == NULL);
+}
+
+TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
+  // Test that if te call BuildFile again on the same input we get the same
+  // FileDescriptor back even if syntax param is specified.
+  FileDescriptorProto proto_syntax2;
+  proto_syntax2.set_name("foo_syntax2");
+  proto_syntax2.set_syntax("proto2");
+
+  const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
+  EXPECT_TRUE(proto2_descriptor != NULL);
+  EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
+
+  FileDescriptorProto implicit_proto2;
+  implicit_proto2.set_name("foo_implicit_syntax2");
+
+  const FileDescriptor* implicit_proto2_descriptor =
+      pool_.BuildFile(implicit_proto2);
+  EXPECT_TRUE(implicit_proto2_descriptor != NULL);
+  // We get the same FileDescriptor back if syntax param is explicitly
+  // specified.
+  implicit_proto2.set_syntax("proto2");
+  EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2));
+
+  FileDescriptorProto proto_syntax3;
+  proto_syntax3.set_name("foo_syntax3");
+  proto_syntax3.set_syntax("proto3");
+
+  const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
+  EXPECT_TRUE(proto3_descriptor != NULL);
+  EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
+}
+
+TEST_F(FileDescriptorTest, Syntax) {
+  FileDescriptorProto proto;
+  proto.set_name("foo");
+  // Enable the test when we also populate the syntax for proto2.
+#if 0
+  {
+    proto.set_syntax("proto2");
+    DescriptorPool pool;
+    const FileDescriptor* file = pool.BuildFile(proto);
+    EXPECT_TRUE(file != NULL);
+    EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax());
+    FileDescriptorProto other;
+    file->CopyTo(&other);
+    EXPECT_EQ("proto2", other.syntax());
+  }
+#endif
+  {
+    proto.set_syntax("proto3");
+    DescriptorPool pool;
+    const FileDescriptor* file = pool.BuildFile(proto);
+    EXPECT_TRUE(file != NULL);
+    EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax());
+    FileDescriptorProto other;
+    file->CopyTo(&other);
+    EXPECT_EQ("proto3", other.syntax());
+  }
+}
+
+// ===================================================================
+
+// Test simple flat messages and fields.
+class DescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   // in "foo.proto"
+    //   message TestForeign {}
+    //   enum TestEnum {}
+    //
+    //   message TestMessage {
+    //     required string      foo = 1;
+    //     optional TestEnum    bar = 6;
+    //     repeated TestForeign baz = 500000000;
+    //     optional group       qux = 15 {}
+    //   }
+    //
+    //   // in "bar.proto"
+    //   package corge.grault;
+    //   message TestMessage2 {
+    //     required string foo = 1;
+    //     required string bar = 2;
+    //     required string quux = 6;
+    //   }
+    //
+    //   // in "map.proto"
+    //   message TestMessage3 {
+    //     map<int32, int32> map_int32_int32 = 1;
+    //   }
+    //
+    //   // in "json.proto"
+    //   message TestMessage4 {
+    //     optional int32 field_name1 = 1;
+    //     optional int32 fieldName2 = 2;
+    //     optional int32 FieldName3 = 3;
+    //     optional int32 _field_name4 = 4;
+    //     optional int32 FIELD_NAME5 = 5;
+    //     optional int32 field_name6 = 6 [json_name = "@type"];
+    //   }
+    //
+    // We cheat and use TestForeign as the type for qux rather than create
+    // an actual nested type.
+    //
+    // Since all primitive types (including string) use the same building
+    // code, there's no need to test each one individually.
+    //
+    // TestMessage2 is primarily here to test FindFieldByName and friends.
+    // All messages created from the same DescriptorPool share the same lookup
+    // table, so we need to insure that they don't interfere.
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+    AddMessage(&foo_file, "TestForeign");
+    AddEmptyEnum(&foo_file, "TestEnum");
+
+    DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
+    AddField(message, "foo", 1,
+             FieldDescriptorProto::LABEL_REQUIRED,
+             FieldDescriptorProto::TYPE_STRING);
+    AddField(message, "bar", 6,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_ENUM)
+      ->set_type_name("TestEnum");
+    AddField(message, "baz", 500000000,
+             FieldDescriptorProto::LABEL_REPEATED,
+             FieldDescriptorProto::TYPE_MESSAGE)
+      ->set_type_name("TestForeign");
+    AddField(message, "qux", 15,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_GROUP)
+      ->set_type_name("TestForeign");
+
+    FileDescriptorProto bar_file;
+    bar_file.set_name("bar.proto");
+    bar_file.set_package("corge.grault");
+
+    DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
+    AddField(message2, "foo", 1,
+             FieldDescriptorProto::LABEL_REQUIRED,
+             FieldDescriptorProto::TYPE_STRING);
+    AddField(message2, "bar", 2,
+             FieldDescriptorProto::LABEL_REQUIRED,
+             FieldDescriptorProto::TYPE_STRING);
+    AddField(message2, "quux", 6,
+             FieldDescriptorProto::LABEL_REQUIRED,
+             FieldDescriptorProto::TYPE_STRING);
+
+    FileDescriptorProto map_file;
+    map_file.set_name("map.proto");
+    DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3");
+
+    DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry");
+    AddField(entry, "key", 1,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(entry, "value", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    entry->mutable_options()->set_map_entry(true);
+
+    AddField(message3, "map_int32_int32", 1,
+             FieldDescriptorProto::LABEL_REPEATED,
+             FieldDescriptorProto::TYPE_MESSAGE)
+        ->set_type_name("MapInt32Int32Entry");
+
+    FileDescriptorProto json_file;
+    json_file.set_name("json.proto");
+    json_file.set_syntax("proto3");
+    DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4");
+    AddField(message4, "field_name1", 1,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message4, "fieldName2", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message4, "FieldName3", 3,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message4, "_field_name4", 4,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message4, "FIELD_NAME5", 5,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message4, "field_name6", 6,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32)
+        ->set_json_name("@type");
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    bar_file_ = pool_.BuildFile(bar_file);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    map_file_ = pool_.BuildFile(map_file);
+    ASSERT_TRUE(map_file_ != NULL);
+
+    json_file_ = pool_.BuildFile(json_file);
+    ASSERT_TRUE(json_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->enum_type_count());
+    enum_ = foo_file_->enum_type(0);
+
+    ASSERT_EQ(2, foo_file_->message_type_count());
+    foreign_ = foo_file_->message_type(0);
+    message_ = foo_file_->message_type(1);
+
+    ASSERT_EQ(4, message_->field_count());
+    foo_ = message_->field(0);
+    bar_ = message_->field(1);
+    baz_ = message_->field(2);
+    qux_ = message_->field(3);
+
+    ASSERT_EQ(1, bar_file_->message_type_count());
+    message2_ = bar_file_->message_type(0);
+
+    ASSERT_EQ(3, message2_->field_count());
+    foo2_  = message2_->field(0);
+    bar2_  = message2_->field(1);
+    quux2_ = message2_->field(2);
+
+    ASSERT_EQ(1, map_file_->message_type_count());
+    message3_ = map_file_->message_type(0);
+
+    ASSERT_EQ(1, message3_->field_count());
+    map_  = message3_->field(0);
+
+    ASSERT_EQ(1, json_file_->message_type_count());
+    message4_ = json_file_->message_type(0);
+  }
+
+  void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) {
+    message->CopyTo(proto);
+    message->CopyJsonNameTo(proto);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+  const FileDescriptor* bar_file_;
+  const FileDescriptor* map_file_;
+  const FileDescriptor* json_file_;
+
+  const Descriptor* message_;
+  const Descriptor* message2_;
+  const Descriptor* message3_;
+  const Descriptor* message4_;
+  const Descriptor* foreign_;
+  const EnumDescriptor* enum_;
+
+  const FieldDescriptor* foo_;
+  const FieldDescriptor* bar_;
+  const FieldDescriptor* baz_;
+  const FieldDescriptor* qux_;
+
+  const FieldDescriptor* foo2_;
+  const FieldDescriptor* bar2_;
+  const FieldDescriptor* quux2_;
+
+  const FieldDescriptor* map_;
+};
+
+TEST_F(DescriptorTest, Name) {
+  EXPECT_EQ("TestMessage", message_->name());
+  EXPECT_EQ("TestMessage", message_->full_name());
+  EXPECT_EQ(foo_file_, message_->file());
+
+  EXPECT_EQ("TestMessage2", message2_->name());
+  EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
+  EXPECT_EQ(bar_file_, message2_->file());
+}
+
+TEST_F(DescriptorTest, ContainingType) {
+  EXPECT_TRUE(message_->containing_type() == NULL);
+  EXPECT_TRUE(message2_->containing_type() == NULL);
+}
+
+TEST_F(DescriptorTest, FieldsByIndex) {
+  ASSERT_EQ(4, message_->field_count());
+  EXPECT_EQ(foo_, message_->field(0));
+  EXPECT_EQ(bar_, message_->field(1));
+  EXPECT_EQ(baz_, message_->field(2));
+  EXPECT_EQ(qux_, message_->field(3));
+}
+
+TEST_F(DescriptorTest, FindFieldByName) {
+  // All messages in the same DescriptorPool share a single lookup table for
+  // fields.  So, in addition to testing that FindFieldByName finds the fields
+  // of the message, we need to test that it does *not* find the fields of
+  // *other* messages.
+
+  EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
+  EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
+  EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
+  EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
+  EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
+  EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
+
+  EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
+  EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
+  EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
+  EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
+  EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
+}
+
+TEST_F(DescriptorTest, FindFieldByNumber) {
+  EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
+  EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
+  EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
+  EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
+  EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
+  EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
+
+  EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
+  EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
+  EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
+  EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
+  EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
+}
+
+TEST_F(DescriptorTest, FieldName) {
+  EXPECT_EQ("foo", foo_->name());
+  EXPECT_EQ("bar", bar_->name());
+  EXPECT_EQ("baz", baz_->name());
+  EXPECT_EQ("qux", qux_->name());
+}
+
+TEST_F(DescriptorTest, FieldFullName) {
+  EXPECT_EQ("TestMessage.foo", foo_->full_name());
+  EXPECT_EQ("TestMessage.bar", bar_->full_name());
+  EXPECT_EQ("TestMessage.baz", baz_->full_name());
+  EXPECT_EQ("TestMessage.qux", qux_->full_name());
+
+  EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
+}
+
+TEST_F(DescriptorTest, FieldJsonName) {
+  EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
+  EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
+  EXPECT_EQ("fieldName3", message4_->field(2)->json_name());
+  EXPECT_EQ("fieldName4", message4_->field(3)->json_name());
+  EXPECT_EQ("fIELDNAME5", message4_->field(4)->json_name());
+  EXPECT_EQ("@type", message4_->field(5)->json_name());
+
+  DescriptorProto proto;
+  message4_->CopyTo(&proto);
+  ASSERT_EQ(6, proto.field_size());
+  EXPECT_FALSE(proto.field(0).has_json_name());
+  EXPECT_FALSE(proto.field(1).has_json_name());
+  EXPECT_FALSE(proto.field(2).has_json_name());
+  EXPECT_FALSE(proto.field(3).has_json_name());
+  EXPECT_FALSE(proto.field(4).has_json_name());
+  EXPECT_EQ("@type", proto.field(5).json_name());
+
+  proto.Clear();
+  CopyWithJsonName(message4_, &proto);
+  ASSERT_EQ(6, proto.field_size());
+  EXPECT_EQ("fieldName1", proto.field(0).json_name());
+  EXPECT_EQ("fieldName2", proto.field(1).json_name());
+  EXPECT_EQ("fieldName3", proto.field(2).json_name());
+  EXPECT_EQ("fieldName4", proto.field(3).json_name());
+  EXPECT_EQ("fIELDNAME5", proto.field(4).json_name());
+  EXPECT_EQ("@type", proto.field(5).json_name());
+}
+
+TEST_F(DescriptorTest, FieldFile) {
+  EXPECT_EQ(foo_file_, foo_->file());
+  EXPECT_EQ(foo_file_, bar_->file());
+  EXPECT_EQ(foo_file_, baz_->file());
+  EXPECT_EQ(foo_file_, qux_->file());
+
+  EXPECT_EQ(bar_file_, foo2_->file());
+  EXPECT_EQ(bar_file_, bar2_->file());
+  EXPECT_EQ(bar_file_, quux2_->file());
+}
+
+TEST_F(DescriptorTest, FieldIndex) {
+  EXPECT_EQ(0, foo_->index());
+  EXPECT_EQ(1, bar_->index());
+  EXPECT_EQ(2, baz_->index());
+  EXPECT_EQ(3, qux_->index());
+}
+
+TEST_F(DescriptorTest, FieldNumber) {
+  EXPECT_EQ(        1, foo_->number());
+  EXPECT_EQ(        6, bar_->number());
+  EXPECT_EQ(500000000, baz_->number());
+  EXPECT_EQ(       15, qux_->number());
+}
+
+TEST_F(DescriptorTest, FieldType) {
+  EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , bar_->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , qux_->type());
+}
+
+TEST_F(DescriptorTest, FieldLabel) {
+  EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
+
+  EXPECT_TRUE (foo_->is_required());
+  EXPECT_FALSE(foo_->is_optional());
+  EXPECT_FALSE(foo_->is_repeated());
+
+  EXPECT_FALSE(bar_->is_required());
+  EXPECT_TRUE (bar_->is_optional());
+  EXPECT_FALSE(bar_->is_repeated());
+
+  EXPECT_FALSE(baz_->is_required());
+  EXPECT_FALSE(baz_->is_optional());
+  EXPECT_TRUE (baz_->is_repeated());
+}
+
+TEST_F(DescriptorTest, IsMap) {
+  EXPECT_TRUE(map_->is_map());
+  EXPECT_FALSE(baz_->is_map());
+  EXPECT_TRUE(map_->message_type()->options().map_entry());
+}
+
+TEST_F(DescriptorTest, FieldHasDefault) {
+  EXPECT_FALSE(foo_->has_default_value());
+  EXPECT_FALSE(bar_->has_default_value());
+  EXPECT_FALSE(baz_->has_default_value());
+  EXPECT_FALSE(qux_->has_default_value());
+}
+
+TEST_F(DescriptorTest, FieldContainingType) {
+  EXPECT_EQ(message_, foo_->containing_type());
+  EXPECT_EQ(message_, bar_->containing_type());
+  EXPECT_EQ(message_, baz_->containing_type());
+  EXPECT_EQ(message_, qux_->containing_type());
+
+  EXPECT_EQ(message2_, foo2_ ->containing_type());
+  EXPECT_EQ(message2_, bar2_ ->containing_type());
+  EXPECT_EQ(message2_, quux2_->containing_type());
+}
+
+TEST_F(DescriptorTest, FieldMessageType) {
+  EXPECT_TRUE(foo_->message_type() == NULL);
+  EXPECT_TRUE(bar_->message_type() == NULL);
+
+  EXPECT_EQ(foreign_, baz_->message_type());
+  EXPECT_EQ(foreign_, qux_->message_type());
+}
+
+TEST_F(DescriptorTest, FieldEnumType) {
+  EXPECT_TRUE(foo_->enum_type() == NULL);
+  EXPECT_TRUE(baz_->enum_type() == NULL);
+  EXPECT_TRUE(qux_->enum_type() == NULL);
+
+  EXPECT_EQ(enum_, bar_->enum_type());
+}
+
+// ===================================================================
+
+// Test simple flat messages and fields.
+class OneofDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   package garply;
+    //   message TestOneof {
+    //     optional int32 a = 1;
+    //     oneof foo {
+    //       string b = 2;
+    //       TestOneof c = 3;
+    //     }
+    //     oneof bar {
+    //       float d = 4;
+    //     }
+    //   }
+
+    FileDescriptorProto baz_file;
+    baz_file.set_name("baz.proto");
+    baz_file.set_package("garply");
+
+    DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof");
+    oneof_message->add_oneof_decl()->set_name("foo");
+    oneof_message->add_oneof_decl()->set_name("bar");
+
+    AddField(oneof_message, "a", 1,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(oneof_message, "b", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_STRING);
+    oneof_message->mutable_field(1)->set_oneof_index(0);
+    AddField(oneof_message, "c", 3,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_MESSAGE);
+    oneof_message->mutable_field(2)->set_oneof_index(0);
+    oneof_message->mutable_field(2)->set_type_name("TestOneof");
+
+    AddField(oneof_message, "d", 4,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_FLOAT);
+    oneof_message->mutable_field(3)->set_oneof_index(1);
+
+    // Build the descriptors and get the pointers.
+    baz_file_ = pool_.BuildFile(baz_file);
+    ASSERT_TRUE(baz_file_ != NULL);
+
+    ASSERT_EQ(1, baz_file_->message_type_count());
+    oneof_message_ = baz_file_->message_type(0);
+
+    ASSERT_EQ(2, oneof_message_->oneof_decl_count());
+    oneof_ = oneof_message_->oneof_decl(0);
+    oneof2_ = oneof_message_->oneof_decl(1);
+
+    ASSERT_EQ(4, oneof_message_->field_count());
+    a_ = oneof_message_->field(0);
+    b_ = oneof_message_->field(1);
+    c_ = oneof_message_->field(2);
+    d_ = oneof_message_->field(3);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* baz_file_;
+
+  const Descriptor* oneof_message_;
+
+  const OneofDescriptor* oneof_;
+  const OneofDescriptor* oneof2_;
+  const FieldDescriptor* a_;
+  const FieldDescriptor* b_;
+  const FieldDescriptor* c_;
+  const FieldDescriptor* d_;
+  const FieldDescriptor* e_;
+  const FieldDescriptor* f_;
+};
+
+TEST_F(OneofDescriptorTest, Normal) {
+  EXPECT_EQ("foo", oneof_->name());
+  EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name());
+  EXPECT_EQ(0, oneof_->index());
+  ASSERT_EQ(2, oneof_->field_count());
+  EXPECT_EQ(b_, oneof_->field(0));
+  EXPECT_EQ(c_, oneof_->field(1));
+  EXPECT_TRUE(a_->containing_oneof() == NULL);
+  EXPECT_EQ(oneof_, b_->containing_oneof());
+  EXPECT_EQ(oneof_, c_->containing_oneof());
+}
+
+TEST_F(OneofDescriptorTest, FindByName) {
+  EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
+  EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
+  EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL);
+}
+
+// ===================================================================
+
+class StylizedFieldNamesTest : public testing::Test {
+ protected:
+  void SetUp() {
+    FileDescriptorProto file;
+    file.set_name("foo.proto");
+
+    AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
+
+    DescriptorProto* message = AddMessage(&file, "TestMessage");
+    AddField(message, "foo_foo", 1,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message, "FooBar", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message, "fooBaz", 3,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message, "fooFoo", 4,  // Camel-case conflict with foo_foo.
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+    AddField(message, "foobar", 5,  // Lower-case conflict with FooBar.
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+
+    AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_INT32);
+    AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_INT32);
+    AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_INT32);
+    AddNestedExtension(message, "ExtendableMessage", "barFoo", 4,  // Conflict
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_INT32);
+    AddNestedExtension(message, "ExtendableMessage", "barbar", 5,  // Conflict
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_INT32);
+
+    AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+    AddExtension(&file, "ExtendableMessage", "BazBar", 12,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+    AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+    AddExtension(&file, "ExtendableMessage", "bazFoo", 14,  // Conflict
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+    AddExtension(&file, "ExtendableMessage", "bazbar", 15,  // Conflict
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+
+    file_ = pool_.BuildFile(file);
+    ASSERT_TRUE(file_ != NULL);
+    ASSERT_EQ(2, file_->message_type_count());
+    message_ = file_->message_type(1);
+    ASSERT_EQ("TestMessage", message_->name());
+    ASSERT_EQ(5, message_->field_count());
+    ASSERT_EQ(5, message_->extension_count());
+    ASSERT_EQ(5, file_->extension_count());
+  }
+
+  DescriptorPool pool_;
+  const FileDescriptor* file_;
+  const Descriptor* message_;
+};
+
+TEST_F(StylizedFieldNamesTest, LowercaseName) {
+  EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
+  EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
+  EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
+  EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
+  EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
+
+  EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
+  EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
+  EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
+  EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
+  EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
+
+  EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
+  EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
+  EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
+  EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
+  EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
+}
+
+TEST_F(StylizedFieldNamesTest, CamelcaseName) {
+  EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
+  EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
+  EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
+  EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
+  EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
+
+  EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
+  EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
+  EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
+  EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
+  EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
+
+  EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
+  EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
+  EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
+  EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
+  EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
+}
+
+TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
+  EXPECT_EQ(message_->field(0),
+            message_->FindFieldByLowercaseName("foo_foo"));
+  EXPECT_EQ(message_->field(1),
+            message_->FindFieldByLowercaseName("foobar"));
+  EXPECT_EQ(message_->field(2),
+            message_->FindFieldByLowercaseName("foobaz"));
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
+
+  EXPECT_EQ(message_->extension(0),
+            message_->FindExtensionByLowercaseName("bar_foo"));
+  EXPECT_EQ(message_->extension(1),
+            message_->FindExtensionByLowercaseName("barbar"));
+  EXPECT_EQ(message_->extension(2),
+            message_->FindExtensionByLowercaseName("barbaz"));
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+
+  EXPECT_EQ(file_->extension(0),
+            file_->FindExtensionByLowercaseName("baz_foo"));
+  EXPECT_EQ(file_->extension(1),
+            file_->FindExtensionByLowercaseName("bazbar"));
+  EXPECT_EQ(file_->extension(2),
+            file_->FindExtensionByLowercaseName("bazbaz"));
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+}
+
+TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
+  EXPECT_EQ(message_->field(0),
+            message_->FindFieldByCamelcaseName("fooFoo"));
+  EXPECT_EQ(message_->field(1),
+            message_->FindFieldByCamelcaseName("fooBar"));
+  EXPECT_EQ(message_->field(2),
+            message_->FindFieldByCamelcaseName("fooBaz"));
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
+
+  EXPECT_EQ(message_->extension(0),
+            message_->FindExtensionByCamelcaseName("barFoo"));
+  EXPECT_EQ(message_->extension(1),
+            message_->FindExtensionByCamelcaseName("barBar"));
+  EXPECT_EQ(message_->extension(2),
+            message_->FindExtensionByCamelcaseName("barBaz"));
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+
+  EXPECT_EQ(file_->extension(0),
+            file_->FindExtensionByCamelcaseName("bazFoo"));
+  EXPECT_EQ(file_->extension(1),
+            file_->FindExtensionByCamelcaseName("bazBar"));
+  EXPECT_EQ(file_->extension(2),
+            file_->FindExtensionByCamelcaseName("bazBaz"));
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+}
+
+// ===================================================================
+
+// Test enum descriptors.
+class EnumDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   // in "foo.proto"
+    //   enum TestEnum {
+    //     FOO = 1;
+    //     BAR = 2;
+    //   }
+    //
+    //   // in "bar.proto"
+    //   package corge.grault;
+    //   enum TestEnum2 {
+    //     FOO = 1;
+    //     BAZ = 3;
+    //   }
+    //
+    // TestEnum2 is primarily here to test FindValueByName and friends.
+    // All enums created from the same DescriptorPool share the same lookup
+    // table, so we need to insure that they don't interfere.
+
+    // TestEnum
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+
+    EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
+    AddEnumValue(enum_proto, "FOO", 1);
+    AddEnumValue(enum_proto, "BAR", 2);
+
+    // TestEnum2
+    FileDescriptorProto bar_file;
+    bar_file.set_name("bar.proto");
+    bar_file.set_package("corge.grault");
+
+    EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
+    AddEnumValue(enum2_proto, "FOO", 1);
+    AddEnumValue(enum2_proto, "BAZ", 3);
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    bar_file_ = pool_.BuildFile(bar_file);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->enum_type_count());
+    enum_ = foo_file_->enum_type(0);
+
+    ASSERT_EQ(2, enum_->value_count());
+    foo_ = enum_->value(0);
+    bar_ = enum_->value(1);
+
+    ASSERT_EQ(1, bar_file_->enum_type_count());
+    enum2_ = bar_file_->enum_type(0);
+
+    ASSERT_EQ(2, enum2_->value_count());
+    foo2_ = enum2_->value(0);
+    baz2_ = enum2_->value(1);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+  const FileDescriptor* bar_file_;
+
+  const EnumDescriptor* enum_;
+  const EnumDescriptor* enum2_;
+
+  const EnumValueDescriptor* foo_;
+  const EnumValueDescriptor* bar_;
+
+  const EnumValueDescriptor* foo2_;
+  const EnumValueDescriptor* baz2_;
+};
+
+TEST_F(EnumDescriptorTest, Name) {
+  EXPECT_EQ("TestEnum", enum_->name());
+  EXPECT_EQ("TestEnum", enum_->full_name());
+  EXPECT_EQ(foo_file_, enum_->file());
+
+  EXPECT_EQ("TestEnum2", enum2_->name());
+  EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
+  EXPECT_EQ(bar_file_, enum2_->file());
+}
+
+TEST_F(EnumDescriptorTest, ContainingType) {
+  EXPECT_TRUE(enum_->containing_type() == NULL);
+  EXPECT_TRUE(enum2_->containing_type() == NULL);
+}
+
+TEST_F(EnumDescriptorTest, ValuesByIndex) {
+  ASSERT_EQ(2, enum_->value_count());
+  EXPECT_EQ(foo_, enum_->value(0));
+  EXPECT_EQ(bar_, enum_->value(1));
+}
+
+TEST_F(EnumDescriptorTest, FindValueByName) {
+  EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
+  EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
+  EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
+  EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
+
+  EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(enum_ ->FindValueByName("BAZ"          ) == NULL);
+  EXPECT_TRUE(enum2_->FindValueByName("BAR"          ) == NULL);
+}
+
+TEST_F(EnumDescriptorTest, FindValueByNumber) {
+  EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
+  EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
+  EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
+  EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
+
+  EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
+  EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
+  EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
+}
+
+TEST_F(EnumDescriptorTest, ValueName) {
+  EXPECT_EQ("FOO", foo_->name());
+  EXPECT_EQ("BAR", bar_->name());
+}
+
+TEST_F(EnumDescriptorTest, ValueFullName) {
+  EXPECT_EQ("FOO", foo_->full_name());
+  EXPECT_EQ("BAR", bar_->full_name());
+  EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
+  EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
+}
+
+TEST_F(EnumDescriptorTest, ValueIndex) {
+  EXPECT_EQ(0, foo_->index());
+  EXPECT_EQ(1, bar_->index());
+}
+
+TEST_F(EnumDescriptorTest, ValueNumber) {
+  EXPECT_EQ(1, foo_->number());
+  EXPECT_EQ(2, bar_->number());
+}
+
+TEST_F(EnumDescriptorTest, ValueType) {
+  EXPECT_EQ(enum_ , foo_ ->type());
+  EXPECT_EQ(enum_ , bar_ ->type());
+  EXPECT_EQ(enum2_, foo2_->type());
+  EXPECT_EQ(enum2_, baz2_->type());
+}
+
+// ===================================================================
+
+// Test service descriptors.
+class ServiceDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following messages and service:
+    //    // in "foo.proto"
+    //    message FooRequest  {}
+    //    message FooResponse {}
+    //    message BarRequest  {}
+    //    message BarResponse {}
+    //    message BazRequest  {}
+    //    message BazResponse {}
+    //
+    //    service TestService {
+    //      rpc Foo(FooRequest) returns (FooResponse);
+    //      rpc Bar(BarRequest) returns (BarResponse);
+    //    }
+    //
+    //    // in "bar.proto"
+    //    package corge.grault
+    //    service TestService2 {
+    //      rpc Foo(FooRequest) returns (FooResponse);
+    //      rpc Baz(BazRequest) returns (BazResponse);
+    //    }
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+
+    AddMessage(&foo_file, "FooRequest");
+    AddMessage(&foo_file, "FooResponse");
+    AddMessage(&foo_file, "BarRequest");
+    AddMessage(&foo_file, "BarResponse");
+    AddMessage(&foo_file, "BazRequest");
+    AddMessage(&foo_file, "BazResponse");
+
+    ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
+    AddMethod(service, "Foo", "FooRequest", "FooResponse");
+    AddMethod(service, "Bar", "BarRequest", "BarResponse");
+
+    FileDescriptorProto bar_file;
+    bar_file.set_name("bar.proto");
+    bar_file.set_package("corge.grault");
+    bar_file.add_dependency("foo.proto");
+
+    ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
+    AddMethod(service2, "Foo", "FooRequest", "FooResponse");
+    AddMethod(service2, "Baz", "BazRequest", "BazResponse");
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    bar_file_ = pool_.BuildFile(bar_file);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    ASSERT_EQ(6, foo_file_->message_type_count());
+    foo_request_  = foo_file_->message_type(0);
+    foo_response_ = foo_file_->message_type(1);
+    bar_request_  = foo_file_->message_type(2);
+    bar_response_ = foo_file_->message_type(3);
+    baz_request_  = foo_file_->message_type(4);
+    baz_response_ = foo_file_->message_type(5);
+
+    ASSERT_EQ(1, foo_file_->service_count());
+    service_ = foo_file_->service(0);
+
+    ASSERT_EQ(2, service_->method_count());
+    foo_ = service_->method(0);
+    bar_ = service_->method(1);
+
+    ASSERT_EQ(1, bar_file_->service_count());
+    service2_ = bar_file_->service(0);
+
+    ASSERT_EQ(2, service2_->method_count());
+    foo2_ = service2_->method(0);
+    baz2_ = service2_->method(1);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+  const FileDescriptor* bar_file_;
+
+  const Descriptor* foo_request_;
+  const Descriptor* foo_response_;
+  const Descriptor* bar_request_;
+  const Descriptor* bar_response_;
+  const Descriptor* baz_request_;
+  const Descriptor* baz_response_;
+
+  const ServiceDescriptor* service_;
+  const ServiceDescriptor* service2_;
+
+  const MethodDescriptor* foo_;
+  const MethodDescriptor* bar_;
+
+  const MethodDescriptor* foo2_;
+  const MethodDescriptor* baz2_;
+};
+
+TEST_F(ServiceDescriptorTest, Name) {
+  EXPECT_EQ("TestService", service_->name());
+  EXPECT_EQ("TestService", service_->full_name());
+  EXPECT_EQ(foo_file_, service_->file());
+
+  EXPECT_EQ("TestService2", service2_->name());
+  EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
+  EXPECT_EQ(bar_file_, service2_->file());
+}
+
+TEST_F(ServiceDescriptorTest, MethodsByIndex) {
+  ASSERT_EQ(2, service_->method_count());
+  EXPECT_EQ(foo_, service_->method(0));
+  EXPECT_EQ(bar_, service_->method(1));
+}
+
+TEST_F(ServiceDescriptorTest, FindMethodByName) {
+  EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
+  EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
+  EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
+  EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
+
+  EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
+  EXPECT_TRUE(service_ ->FindMethodByName("Baz"         ) == NULL);
+  EXPECT_TRUE(service2_->FindMethodByName("Bar"         ) == NULL);
+}
+
+TEST_F(ServiceDescriptorTest, MethodName) {
+  EXPECT_EQ("Foo", foo_->name());
+  EXPECT_EQ("Bar", bar_->name());
+}
+
+TEST_F(ServiceDescriptorTest, MethodFullName) {
+  EXPECT_EQ("TestService.Foo", foo_->full_name());
+  EXPECT_EQ("TestService.Bar", bar_->full_name());
+  EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
+  EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
+}
+
+TEST_F(ServiceDescriptorTest, MethodIndex) {
+  EXPECT_EQ(0, foo_->index());
+  EXPECT_EQ(1, bar_->index());
+}
+
+TEST_F(ServiceDescriptorTest, MethodParent) {
+  EXPECT_EQ(service_, foo_->service());
+  EXPECT_EQ(service_, bar_->service());
+}
+
+TEST_F(ServiceDescriptorTest, MethodInputType) {
+  EXPECT_EQ(foo_request_, foo_->input_type());
+  EXPECT_EQ(bar_request_, bar_->input_type());
+}
+
+TEST_F(ServiceDescriptorTest, MethodOutputType) {
+  EXPECT_EQ(foo_response_, foo_->output_type());
+  EXPECT_EQ(bar_response_, bar_->output_type());
+}
+
+// ===================================================================
+
+// Test nested types.
+class NestedDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   // in "foo.proto"
+    //   message TestMessage {
+    //     message Foo {}
+    //     message Bar {}
+    //     enum Baz { A = 1; }
+    //     enum Qux { B = 1; }
+    //   }
+    //
+    //   // in "bar.proto"
+    //   package corge.grault;
+    //   message TestMessage2 {
+    //     message Foo {}
+    //     message Baz {}
+    //     enum Qux  { A = 1; }
+    //     enum Quux { C = 1; }
+    //   }
+    //
+    // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
+    // All messages created from the same DescriptorPool share the same lookup
+    // table, so we need to insure that they don't interfere.
+    //
+    // We add enum values to the enums in order to test searching for enum
+    // values across a message's scope.
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+
+    DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
+    AddNestedMessage(message, "Foo");
+    AddNestedMessage(message, "Bar");
+    EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
+    AddEnumValue(baz, "A", 1);
+    EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
+    AddEnumValue(qux, "B", 1);
+
+    FileDescriptorProto bar_file;
+    bar_file.set_name("bar.proto");
+    bar_file.set_package("corge.grault");
+
+    DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
+    AddNestedMessage(message2, "Foo");
+    AddNestedMessage(message2, "Baz");
+    EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
+    AddEnumValue(qux2, "A", 1);
+    EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
+    AddEnumValue(quux2, "C", 1);
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    bar_file_ = pool_.BuildFile(bar_file);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->message_type_count());
+    message_ = foo_file_->message_type(0);
+
+    ASSERT_EQ(2, message_->nested_type_count());
+    foo_ = message_->nested_type(0);
+    bar_ = message_->nested_type(1);
+
+    ASSERT_EQ(2, message_->enum_type_count());
+    baz_ = message_->enum_type(0);
+    qux_ = message_->enum_type(1);
+
+    ASSERT_EQ(1, baz_->value_count());
+    a_ = baz_->value(0);
+    ASSERT_EQ(1, qux_->value_count());
+    b_ = qux_->value(0);
+
+    ASSERT_EQ(1, bar_file_->message_type_count());
+    message2_ = bar_file_->message_type(0);
+
+    ASSERT_EQ(2, message2_->nested_type_count());
+    foo2_ = message2_->nested_type(0);
+    baz2_ = message2_->nested_type(1);
+
+    ASSERT_EQ(2, message2_->enum_type_count());
+    qux2_ = message2_->enum_type(0);
+    quux2_ = message2_->enum_type(1);
+
+    ASSERT_EQ(1, qux2_->value_count());
+    a2_ = qux2_->value(0);
+    ASSERT_EQ(1, quux2_->value_count());
+    c2_ = quux2_->value(0);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+  const FileDescriptor* bar_file_;
+
+  const Descriptor* message_;
+  const Descriptor* message2_;
+
+  const Descriptor* foo_;
+  const Descriptor* bar_;
+  const EnumDescriptor* baz_;
+  const EnumDescriptor* qux_;
+  const EnumValueDescriptor* a_;
+  const EnumValueDescriptor* b_;
+
+  const Descriptor* foo2_;
+  const Descriptor* baz2_;
+  const EnumDescriptor* qux2_;
+  const EnumDescriptor* quux2_;
+  const EnumValueDescriptor* a2_;
+  const EnumValueDescriptor* c2_;
+};
+
+TEST_F(NestedDescriptorTest, MessageName) {
+  EXPECT_EQ("Foo", foo_ ->name());
+  EXPECT_EQ("Bar", bar_ ->name());
+  EXPECT_EQ("Foo", foo2_->name());
+  EXPECT_EQ("Baz", baz2_->name());
+
+  EXPECT_EQ("TestMessage.Foo", foo_->full_name());
+  EXPECT_EQ("TestMessage.Bar", bar_->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
+}
+
+TEST_F(NestedDescriptorTest, MessageContainingType) {
+  EXPECT_EQ(message_ , foo_ ->containing_type());
+  EXPECT_EQ(message_ , bar_ ->containing_type());
+  EXPECT_EQ(message2_, foo2_->containing_type());
+  EXPECT_EQ(message2_, baz2_->containing_type());
+}
+
+TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
+  ASSERT_EQ(2, message_->nested_type_count());
+  EXPECT_EQ(foo_, message_->nested_type(0));
+  EXPECT_EQ(bar_, message_->nested_type(1));
+}
+
+TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
+  EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
+  EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
+}
+
+TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
+  EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
+  EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
+  EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
+  EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
+
+  EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
+  EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz"       ) == NULL);
+  EXPECT_TRUE(message2_->FindNestedTypeByName("Bar"       ) == NULL);
+
+  EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
+}
+
+TEST_F(NestedDescriptorTest, EnumName) {
+  EXPECT_EQ("Baz" , baz_ ->name());
+  EXPECT_EQ("Qux" , qux_ ->name());
+  EXPECT_EQ("Qux" , qux2_->name());
+  EXPECT_EQ("Quux", quux2_->name());
+
+  EXPECT_EQ("TestMessage.Baz", baz_->full_name());
+  EXPECT_EQ("TestMessage.Qux", qux_->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
+  EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
+}
+
+TEST_F(NestedDescriptorTest, EnumContainingType) {
+  EXPECT_EQ(message_ , baz_  ->containing_type());
+  EXPECT_EQ(message_ , qux_  ->containing_type());
+  EXPECT_EQ(message2_, qux2_ ->containing_type());
+  EXPECT_EQ(message2_, quux2_->containing_type());
+}
+
+TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
+  ASSERT_EQ(2, message_->nested_type_count());
+  EXPECT_EQ(foo_, message_->nested_type(0));
+  EXPECT_EQ(bar_, message_->nested_type(1));
+}
+
+TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
+  EXPECT_EQ(baz_  , message_ ->FindEnumTypeByName("Baz" ));
+  EXPECT_EQ(qux_  , message_ ->FindEnumTypeByName("Qux" ));
+  EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
+  EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
+
+  EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
+  EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux"      ) == NULL);
+  EXPECT_TRUE(message2_->FindEnumTypeByName("Baz"       ) == NULL);
+
+  EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
+}
+
+TEST_F(NestedDescriptorTest, FindEnumValueByName) {
+  EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
+  EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
+  EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
+  EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
+
+  EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(message_ ->FindEnumValueByName("C"            ) == NULL);
+  EXPECT_TRUE(message2_->FindEnumValueByName("B"            ) == NULL);
+
+  EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
+}
+
+// ===================================================================
+
+// Test extensions.
+class ExtensionDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   enum Baz {}
+    //   message Qux {}
+    //
+    //   message Foo {
+    //     extensions 10 to 19;
+    //     extensions 30 to 39;
+    //   }
+    //   extends Foo with optional int32 foo_int32 = 10;
+    //   extends Foo with repeated TestEnum foo_enum = 19;
+    //   message Bar {
+    //     extends Foo with optional Qux foo_message = 30;
+    //     // (using Qux as the group type)
+    //     extends Foo with repeated group foo_group = 39;
+    //   }
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+
+    AddEmptyEnum(&foo_file, "Baz");
+    AddMessage(&foo_file, "Qux");
+
+    DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+    AddExtensionRange(foo, 10, 20);
+    AddExtensionRange(foo, 30, 40);
+
+    AddExtension(&foo_file, "Foo", "foo_int32", 10,
+                 FieldDescriptorProto::LABEL_OPTIONAL,
+                 FieldDescriptorProto::TYPE_INT32);
+    AddExtension(&foo_file, "Foo", "foo_enum", 19,
+                 FieldDescriptorProto::LABEL_REPEATED,
+                 FieldDescriptorProto::TYPE_ENUM)
+      ->set_type_name("Baz");
+
+    DescriptorProto* bar = AddMessage(&foo_file, "Bar");
+    AddNestedExtension(bar, "Foo", "foo_message", 30,
+                       FieldDescriptorProto::LABEL_OPTIONAL,
+                       FieldDescriptorProto::TYPE_MESSAGE)
+      ->set_type_name("Qux");
+    AddNestedExtension(bar, "Foo", "foo_group", 39,
+                       FieldDescriptorProto::LABEL_REPEATED,
+                       FieldDescriptorProto::TYPE_GROUP)
+      ->set_type_name("Qux");
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->enum_type_count());
+    baz_ = foo_file_->enum_type(0);
+
+    ASSERT_EQ(3, foo_file_->message_type_count());
+    qux_ = foo_file_->message_type(0);
+    foo_ = foo_file_->message_type(1);
+    bar_ = foo_file_->message_type(2);
+  }
+
+  DescriptorPool pool_;
+
+  const FileDescriptor* foo_file_;
+
+  const Descriptor* foo_;
+  const Descriptor* bar_;
+  const EnumDescriptor* baz_;
+  const Descriptor* qux_;
+};
+
+TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
+  EXPECT_EQ(0, bar_->extension_range_count());
+  ASSERT_EQ(2, foo_->extension_range_count());
+
+  EXPECT_EQ(10, foo_->extension_range(0)->start);
+  EXPECT_EQ(30, foo_->extension_range(1)->start);
+
+  EXPECT_EQ(20, foo_->extension_range(0)->end);
+  EXPECT_EQ(40, foo_->extension_range(1)->end);
+};
+
+TEST_F(ExtensionDescriptorTest, Extensions) {
+  EXPECT_EQ(0, foo_->extension_count());
+  ASSERT_EQ(2, foo_file_->extension_count());
+  ASSERT_EQ(2, bar_->extension_count());
+
+  EXPECT_TRUE(foo_file_->extension(0)->is_extension());
+  EXPECT_TRUE(foo_file_->extension(1)->is_extension());
+  EXPECT_TRUE(bar_->extension(0)->is_extension());
+  EXPECT_TRUE(bar_->extension(1)->is_extension());
+
+  EXPECT_EQ("foo_int32"  , foo_file_->extension(0)->name());
+  EXPECT_EQ("foo_enum"   , foo_file_->extension(1)->name());
+  EXPECT_EQ("foo_message", bar_->extension(0)->name());
+  EXPECT_EQ("foo_group"  , bar_->extension(1)->name());
+
+  EXPECT_EQ(10, foo_file_->extension(0)->number());
+  EXPECT_EQ(19, foo_file_->extension(1)->number());
+  EXPECT_EQ(30, bar_->extension(0)->number());
+  EXPECT_EQ(39, bar_->extension(1)->number());
+
+  EXPECT_EQ(FieldDescriptor::TYPE_INT32  , foo_file_->extension(0)->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , foo_file_->extension(1)->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
+  EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , bar_->extension(1)->type());
+
+  EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
+  EXPECT_EQ(qux_, bar_->extension(0)->message_type());
+  EXPECT_EQ(qux_, bar_->extension(1)->message_type());
+
+  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
+  EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
+
+  EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
+  EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
+  EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
+  EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
+
+  EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
+  EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
+  EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
+  EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
+};
+
+TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
+  EXPECT_FALSE(foo_->IsExtensionNumber( 9));
+  EXPECT_TRUE (foo_->IsExtensionNumber(10));
+  EXPECT_TRUE (foo_->IsExtensionNumber(19));
+  EXPECT_FALSE(foo_->IsExtensionNumber(20));
+  EXPECT_FALSE(foo_->IsExtensionNumber(29));
+  EXPECT_TRUE (foo_->IsExtensionNumber(30));
+  EXPECT_TRUE (foo_->IsExtensionNumber(39));
+  EXPECT_FALSE(foo_->IsExtensionNumber(40));
+}
+
+TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
+  // Note that FileDescriptor::FindExtensionByName() is tested by
+  // FileDescriptorTest.
+  ASSERT_EQ(2, bar_->extension_count());
+
+  EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
+  EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"  ));
+
+  EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
+  EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
+  EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
+}
+
+TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
+  vector<const FieldDescriptor*> extensions;
+  pool_.FindAllExtensions(foo_, &extensions);
+  ASSERT_EQ(4, extensions.size());
+  EXPECT_EQ(10, extensions[0]->number());
+  EXPECT_EQ(19, extensions[1]->number());
+  EXPECT_EQ(30, extensions[2]->number());
+  EXPECT_EQ(39, extensions[3]->number());
+}
+
+TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
+  DescriptorPool pool;
+  FileDescriptorProto file_proto;
+  // Add "google/protobuf/descriptor.proto".
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  // Add "foo.proto":
+  //   import "google/protobuf/descriptor.proto";
+  //   extend google.protobuf.FieldOptions {
+  //     optional int32 option1 = 1000;
+  //   }
+  file_proto.Clear();
+  file_proto.set_name("foo.proto");
+  file_proto.add_dependency("google/protobuf/descriptor.proto");
+  AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
+               FieldDescriptorProto::LABEL_OPTIONAL,
+               FieldDescriptorProto::TYPE_INT32);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  // Add "bar.proto":
+  //   import "google/protobuf/descriptor.proto";
+  //   extend google.protobuf.FieldOptions {
+  //     optional int32 option2 = 1000;
+  //   }
+  file_proto.Clear();
+  file_proto.set_name("bar.proto");
+  file_proto.add_dependency("google/protobuf/descriptor.proto");
+  AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000,
+               FieldDescriptorProto::LABEL_OPTIONAL,
+               FieldDescriptorProto::TYPE_INT32);
+  // Currently we only generate a warning for conflicting extension numbers.
+  // TODO(xiaofeng): Change it to an error.
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+}
+
+// ===================================================================
+
+// Test reserved fields.
+class ReservedDescriptorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    // Build descriptors for the following definitions:
+    //
+    //   message Foo {
+    //     reserved 2, 9 to 11, 15;
+    //     reserved "foo", "bar";
+    //   }
+
+    FileDescriptorProto foo_file;
+    foo_file.set_name("foo.proto");
+
+    DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+    AddReservedRange(foo, 2, 3);
+    AddReservedRange(foo, 9, 12);
+    AddReservedRange(foo, 15, 16);
+
+    foo->add_reserved_name("foo");
+    foo->add_reserved_name("bar");
+
+    // Build the descriptors and get the pointers.
+    foo_file_ = pool_.BuildFile(foo_file);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->message_type_count());
+    foo_ = foo_file_->message_type(0);
+  }
+
+  DescriptorPool pool_;
+  const FileDescriptor* foo_file_;
+  const Descriptor* foo_;
+};
+
+TEST_F(ReservedDescriptorTest, ReservedRanges) {
+  ASSERT_EQ(3, foo_->reserved_range_count());
+
+  EXPECT_EQ(2, foo_->reserved_range(0)->start);
+  EXPECT_EQ(3, foo_->reserved_range(0)->end);
+
+  EXPECT_EQ(9, foo_->reserved_range(1)->start);
+  EXPECT_EQ(12, foo_->reserved_range(1)->end);
+
+  EXPECT_EQ(15, foo_->reserved_range(2)->start);
+  EXPECT_EQ(16, foo_->reserved_range(2)->end);
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedNumber) {
+  EXPECT_FALSE(foo_->IsReservedNumber(1));
+  EXPECT_TRUE (foo_->IsReservedNumber(2));
+  EXPECT_FALSE(foo_->IsReservedNumber(3));
+  EXPECT_FALSE(foo_->IsReservedNumber(8));
+  EXPECT_TRUE (foo_->IsReservedNumber(9));
+  EXPECT_TRUE (foo_->IsReservedNumber(10));
+  EXPECT_TRUE (foo_->IsReservedNumber(11));
+  EXPECT_FALSE(foo_->IsReservedNumber(12));
+  EXPECT_FALSE(foo_->IsReservedNumber(13));
+  EXPECT_FALSE(foo_->IsReservedNumber(14));
+  EXPECT_TRUE (foo_->IsReservedNumber(15));
+  EXPECT_FALSE(foo_->IsReservedNumber(16));
+};
+
+TEST_F(ReservedDescriptorTest, ReservedNames) {
+  ASSERT_EQ(2, foo_->reserved_name_count());
+
+  EXPECT_EQ("foo", foo_->reserved_name(0));
+  EXPECT_EQ("bar", foo_->reserved_name(1));
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedName) {
+  EXPECT_TRUE (foo_->IsReservedName("foo"));
+  EXPECT_TRUE (foo_->IsReservedName("bar"));
+  EXPECT_FALSE(foo_->IsReservedName("baz"));
+};
+
+// ===================================================================
+
+class MiscTest : public testing::Test {
+ protected:
+  // Function which makes a field descriptor of the given type.
+  const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
+    FileDescriptorProto file_proto;
+    file_proto.set_name("foo.proto");
+    AddEmptyEnum(&file_proto, "DummyEnum");
+
+    DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
+    FieldDescriptorProto* field =
+      AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
+               static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
+
+    if (type == FieldDescriptor::TYPE_MESSAGE ||
+        type == FieldDescriptor::TYPE_GROUP) {
+      field->set_type_name("TestMessage");
+    } else if (type == FieldDescriptor::TYPE_ENUM) {
+      field->set_type_name("DummyEnum");
+    }
+
+    // Build the descriptors and get the pointers.
+    pool_.reset(new DescriptorPool());
+    const FileDescriptor* file = pool_->BuildFile(file_proto);
+
+    if (file != NULL &&
+        file->message_type_count() == 1 &&
+        file->message_type(0)->field_count() == 1) {
+      return file->message_type(0)->field(0);
+    } else {
+      return NULL;
+    }
+  }
+
+  const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->type_name() : "";
+  }
+
+  FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->cpp_type() :
+        static_cast<FieldDescriptor::CppType>(0);
+  }
+
+  const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->cpp_type_name() : "";
+  }
+
+  const Descriptor* GetMessageDescriptorForFieldType(
+      FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->message_type() : NULL;
+  }
+
+  const EnumDescriptor* GetEnumDescriptorForFieldType(
+    FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->enum_type() : NULL;
+  }
+
+  google::protobuf::scoped_ptr<DescriptorPool> pool_;
+};
+
+TEST_F(MiscTest, TypeNames) {
+  // Test that correct type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("double"  , GetTypeNameForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_STREQ("float"   , GetTypeNameForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_STREQ("int64"   , GetTypeNameForFieldType(FD::TYPE_INT64   ));
+  EXPECT_STREQ("uint64"  , GetTypeNameForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_STREQ("int32"   , GetTypeNameForFieldType(FD::TYPE_INT32   ));
+  EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_STREQ("bool"    , GetTypeNameForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_STREQ("string"  , GetTypeNameForFieldType(FD::TYPE_STRING  ));
+  EXPECT_STREQ("group"   , GetTypeNameForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_STREQ("bytes"   , GetTypeNameForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_STREQ("uint32"  , GetTypeNameForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_STREQ("enum"    , GetTypeNameForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_STREQ("sint32"  , GetTypeNameForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_STREQ("sint64"  , GetTypeNameForFieldType(FD::TYPE_SINT64  ));
+}
+
+TEST_F(MiscTest, StaticTypeNames) {
+  // Test that correct type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("double"  , FD::TypeName(FD::TYPE_DOUBLE  ));
+  EXPECT_STREQ("float"   , FD::TypeName(FD::TYPE_FLOAT   ));
+  EXPECT_STREQ("int64"   , FD::TypeName(FD::TYPE_INT64   ));
+  EXPECT_STREQ("uint64"  , FD::TypeName(FD::TYPE_UINT64  ));
+  EXPECT_STREQ("int32"   , FD::TypeName(FD::TYPE_INT32   ));
+  EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 ));
+  EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 ));
+  EXPECT_STREQ("bool"    , FD::TypeName(FD::TYPE_BOOL    ));
+  EXPECT_STREQ("string"  , FD::TypeName(FD::TYPE_STRING  ));
+  EXPECT_STREQ("group"   , FD::TypeName(FD::TYPE_GROUP   ));
+  EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE ));
+  EXPECT_STREQ("bytes"   , FD::TypeName(FD::TYPE_BYTES   ));
+  EXPECT_STREQ("uint32"  , FD::TypeName(FD::TYPE_UINT32  ));
+  EXPECT_STREQ("enum"    , FD::TypeName(FD::TYPE_ENUM    ));
+  EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32));
+  EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64));
+  EXPECT_STREQ("sint32"  , FD::TypeName(FD::TYPE_SINT32  ));
+  EXPECT_STREQ("sint64"  , FD::TypeName(FD::TYPE_SINT64  ));
+}
+
+TEST_F(MiscTest, CppTypes) {
+  // Test that CPP types are assigned correctly.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_EQ(FD::CPPTYPE_FLOAT  , GetCppTypeForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_INT64   ));
+  EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_INT32   ));
+  EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_EQ(FD::CPPTYPE_BOOL   , GetCppTypeForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING  ));
+  EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_EQ(FD::CPPTYPE_ENUM   , GetCppTypeForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
+}
+
+TEST_F(MiscTest, CppTypeNames) {
+  // Test that correct CPP type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_STREQ("float"  , GetCppTypeNameForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_INT64   ));
+  EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_INT32   ));
+  EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_STREQ("bool"   , GetCppTypeNameForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING  ));
+  EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_STREQ("enum"   , GetCppTypeNameForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SINT64  ));
+}
+
+TEST_F(MiscTest, StaticCppTypeNames) {
+  // Test that correct CPP type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("int32"  , FD::CppTypeName(FD::CPPTYPE_INT32  ));
+  EXPECT_STREQ("int64"  , FD::CppTypeName(FD::CPPTYPE_INT64  ));
+  EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 ));
+  EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 ));
+  EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE ));
+  EXPECT_STREQ("float"  , FD::CppTypeName(FD::CPPTYPE_FLOAT  ));
+  EXPECT_STREQ("bool"   , FD::CppTypeName(FD::CPPTYPE_BOOL   ));
+  EXPECT_STREQ("enum"   , FD::CppTypeName(FD::CPPTYPE_ENUM   ));
+  EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING ));
+  EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE));
+}
+
+TEST_F(MiscTest, MessageType) {
+  // Test that message_type() is NULL for non-aggregate fields
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64   ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32   ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING  ));
+  EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64  ));
+}
+
+TEST_F(MiscTest, EnumType) {
+  // Test that enum_type() is NULL for non-enum fields
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64   ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32   ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING  ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64  ));
+}
+
+
+TEST_F(MiscTest, DefaultValues) {
+  // Test that setting default values works.
+  FileDescriptorProto file_proto;
+  file_proto.set_name("foo.proto");
+
+  EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
+  AddEnumValue(enum_type_proto, "A", 1);
+  AddEnumValue(enum_type_proto, "B", 2);
+
+  DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
+
+  typedef FieldDescriptorProto FD;  // avoid ugly line wrapping
+  const FD::Label label = FD::LABEL_OPTIONAL;
+
+  // Create fields of every CPP type with default values.
+  AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
+    ->set_default_value("-1");
+  AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
+    ->set_default_value("-1000000000000");
+  AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
+    ->set_default_value("42");
+  AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
+    ->set_default_value("2000000000000");
+  AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
+    ->set_default_value("4.5");
+  AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
+    ->set_default_value("10e100");
+  AddField(message_proto, "bool"  , 7, label, FD::TYPE_BOOL  )
+    ->set_default_value("true");
+  AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
+    ->set_default_value("hello");
+  AddField(message_proto, "data"  , 9, label, FD::TYPE_BYTES )
+    ->set_default_value("\\001\\002\\003");
+
+  FieldDescriptorProto* enum_field =
+    AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
+  enum_field->set_type_name("DummyEnum");
+  enum_field->set_default_value("B");
+
+  // Strings are allowed to have empty defaults.  (At one point, due to
+  // a bug, empty defaults for strings were rejected.  Oops.)
+  AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
+    ->set_default_value("");
+
+  // Add a second set of fields with implicit defalut values.
+  AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
+  AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
+  AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
+  AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
+  AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
+  AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
+  AddField(message_proto, "implicit_bool"  , 27, label, FD::TYPE_BOOL  );
+  AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
+  AddField(message_proto, "implicit_data"  , 29, label, FD::TYPE_BYTES );
+  AddField(message_proto, "implicit_enum"  , 30, label, FD::TYPE_ENUM)
+    ->set_type_name("DummyEnum");
+
+  // Build it.
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+
+  ASSERT_EQ(1, file->enum_type_count());
+  const EnumDescriptor* enum_type = file->enum_type(0);
+  ASSERT_EQ(2, enum_type->value_count());
+  const EnumValueDescriptor* enum_value_a = enum_type->value(0);
+  const EnumValueDescriptor* enum_value_b = enum_type->value(1);
+
+  ASSERT_EQ(1, file->message_type_count());
+  const Descriptor* message = file->message_type(0);
+
+  ASSERT_EQ(21, message->field_count());
+
+  // Check the default values.
+  ASSERT_TRUE(message->field(0)->has_default_value());
+  ASSERT_TRUE(message->field(1)->has_default_value());
+  ASSERT_TRUE(message->field(2)->has_default_value());
+  ASSERT_TRUE(message->field(3)->has_default_value());
+  ASSERT_TRUE(message->field(4)->has_default_value());
+  ASSERT_TRUE(message->field(5)->has_default_value());
+  ASSERT_TRUE(message->field(6)->has_default_value());
+  ASSERT_TRUE(message->field(7)->has_default_value());
+  ASSERT_TRUE(message->field(8)->has_default_value());
+  ASSERT_TRUE(message->field(9)->has_default_value());
+  ASSERT_TRUE(message->field(10)->has_default_value());
+
+  EXPECT_EQ(-1              , message->field(0)->default_value_int32 ());
+  EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
+            message->field(1)->default_value_int64 ());
+  EXPECT_EQ(42              , message->field(2)->default_value_uint32());
+  EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
+            message->field(3)->default_value_uint64());
+  EXPECT_EQ(4.5             , message->field(4)->default_value_float ());
+  EXPECT_EQ(10e100          , message->field(5)->default_value_double());
+  EXPECT_TRUE(                message->field(6)->default_value_bool  ());
+  EXPECT_EQ("hello"         , message->field(7)->default_value_string());
+  EXPECT_EQ("\001\002\003"  , message->field(8)->default_value_string());
+  EXPECT_EQ(enum_value_b    , message->field(9)->default_value_enum  ());
+  EXPECT_EQ(""              , message->field(10)->default_value_string());
+
+  ASSERT_FALSE(message->field(11)->has_default_value());
+  ASSERT_FALSE(message->field(12)->has_default_value());
+  ASSERT_FALSE(message->field(13)->has_default_value());
+  ASSERT_FALSE(message->field(14)->has_default_value());
+  ASSERT_FALSE(message->field(15)->has_default_value());
+  ASSERT_FALSE(message->field(16)->has_default_value());
+  ASSERT_FALSE(message->field(17)->has_default_value());
+  ASSERT_FALSE(message->field(18)->has_default_value());
+  ASSERT_FALSE(message->field(19)->has_default_value());
+  ASSERT_FALSE(message->field(20)->has_default_value());
+
+  EXPECT_EQ(0    , message->field(11)->default_value_int32 ());
+  EXPECT_EQ(0    , message->field(12)->default_value_int64 ());
+  EXPECT_EQ(0    , message->field(13)->default_value_uint32());
+  EXPECT_EQ(0    , message->field(14)->default_value_uint64());
+  EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
+  EXPECT_EQ(0.0  , message->field(16)->default_value_double());
+  EXPECT_FALSE(    message->field(17)->default_value_bool  ());
+  EXPECT_EQ(""   , message->field(18)->default_value_string());
+  EXPECT_EQ(""   , message->field(19)->default_value_string());
+  EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
+}
+
+TEST_F(MiscTest, FieldOptions) {
+  // Try setting field options.
+
+  FileDescriptorProto file_proto;
+  file_proto.set_name("foo.proto");
+
+  DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
+  AddField(message_proto, "foo", 1,
+           FieldDescriptorProto::LABEL_OPTIONAL,
+           FieldDescriptorProto::TYPE_INT32);
+  FieldDescriptorProto* bar_proto =
+    AddField(message_proto, "bar", 2,
+             FieldDescriptorProto::LABEL_OPTIONAL,
+             FieldDescriptorProto::TYPE_INT32);
+
+  FieldOptions* options = bar_proto->mutable_options();
+  options->set_ctype(FieldOptions::CORD);
+
+  // Build the descriptors and get the pointers.
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+
+  ASSERT_EQ(1, file->message_type_count());
+  const Descriptor* message = file->message_type(0);
+
+  ASSERT_EQ(2, message->field_count());
+  const FieldDescriptor* foo = message->field(0);
+  const FieldDescriptor* bar = message->field(1);
+
+  // "foo" had no options set, so it should return the default options.
+  EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
+
+  // "bar" had options set.
+  EXPECT_NE(&FieldOptions::default_instance(), options);
+  EXPECT_TRUE(bar->options().has_ctype());
+  EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
+}
+
+// ===================================================================
+enum DescriptorPoolMode {
+  NO_DATABASE,
+  FALLBACK_DATABASE
+};
+
+class AllowUnknownDependenciesTest
+    : public testing::TestWithParam<DescriptorPoolMode> {
+ protected:
+  DescriptorPoolMode mode() {
+    return GetParam();
+   }
+
+  virtual void SetUp() {
+    FileDescriptorProto foo_proto, bar_proto;
+
+    switch (mode()) {
+      case NO_DATABASE:
+        pool_.reset(new DescriptorPool);
+        break;
+      case FALLBACK_DATABASE:
+        pool_.reset(new DescriptorPool(&db_));
+        break;
+    }
+
+    pool_->AllowUnknownDependencies();
+
+    ASSERT_TRUE(TextFormat::ParseFromString(
+      "name: 'foo.proto'"
+      "dependency: 'bar.proto'"
+      "dependency: 'baz.proto'"
+      "message_type {"
+      "  name: 'Foo'"
+      "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
+      "  field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
+      "  field { name:'qux' number:3 label:LABEL_OPTIONAL"
+      "    type_name: '.corge.Qux'"
+      "    type: TYPE_ENUM"
+      "    options {"
+      "      uninterpreted_option {"
+      "        name {"
+      "          name_part: 'grault'"
+      "          is_extension: true"
+      "        }"
+      "        positive_int_value: 1234"
+      "      }"
+      "    }"
+      "  }"
+      "}",
+      &foo_proto));
+    ASSERT_TRUE(TextFormat::ParseFromString(
+      "name: 'bar.proto'"
+      "message_type { name: 'Bar' }",
+      &bar_proto));
+
+    // Collect pointers to stuff.
+    bar_file_ = BuildFile(bar_proto);
+    ASSERT_TRUE(bar_file_ != NULL);
+
+    ASSERT_EQ(1, bar_file_->message_type_count());
+    bar_type_ = bar_file_->message_type(0);
+
+    foo_file_ = BuildFile(foo_proto);
+    ASSERT_TRUE(foo_file_ != NULL);
+
+    ASSERT_EQ(1, foo_file_->message_type_count());
+    foo_type_ = foo_file_->message_type(0);
+
+    ASSERT_EQ(3, foo_type_->field_count());
+    bar_field_ = foo_type_->field(0);
+    baz_field_ = foo_type_->field(1);
+    qux_field_ = foo_type_->field(2);
+  }
+
+  const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
+    switch (mode()) {
+      case NO_DATABASE:
+        return pool_->BuildFile(proto);
+        break;
+      case FALLBACK_DATABASE: {
+        EXPECT_TRUE(db_.Add(proto));
+        return pool_->FindFileByName(proto.name());
+      }
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return NULL;
+  }
+
+  const FileDescriptor* bar_file_;
+  const Descriptor* bar_type_;
+  const FileDescriptor* foo_file_;
+  const Descriptor* foo_type_;
+  const FieldDescriptor* bar_field_;
+  const FieldDescriptor* baz_field_;
+  const FieldDescriptor* qux_field_;
+
+  SimpleDescriptorDatabase db_;        // used if in FALLBACK_DATABASE mode.
+  google::protobuf::scoped_ptr<DescriptorPool> pool_;
+};
+
+TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
+  ASSERT_EQ(2, foo_file_->dependency_count());
+  EXPECT_EQ(bar_file_, foo_file_->dependency(0));
+  EXPECT_FALSE(bar_file_->is_placeholder());
+
+  const FileDescriptor* baz_file = foo_file_->dependency(1);
+  EXPECT_EQ("baz.proto", baz_file->name());
+  EXPECT_EQ(0, baz_file->message_type_count());
+  EXPECT_TRUE(baz_file->is_placeholder());
+
+  // Placeholder files should not be findable.
+  EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
+  EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
+
+  // Copy*To should not crash for placeholder files.
+  FileDescriptorProto baz_file_proto;
+  baz_file->CopyTo(&baz_file_proto);
+  baz_file->CopySourceCodeInfoTo(&baz_file_proto);
+  EXPECT_FALSE(baz_file_proto.has_source_code_info());
+}
+
+TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
+  ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
+  EXPECT_EQ(bar_type_, bar_field_->message_type());
+  EXPECT_FALSE(bar_type_->is_placeholder());
+
+  ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
+  const Descriptor* baz_type = baz_field_->message_type();
+  EXPECT_EQ("Baz", baz_type->name());
+  EXPECT_EQ("Baz", baz_type->full_name());
+  EXPECT_EQ(0, baz_type->extension_range_count());
+  EXPECT_TRUE(baz_type->is_placeholder());
+
+  ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
+  const EnumDescriptor* qux_type = qux_field_->enum_type();
+  EXPECT_EQ("Qux", qux_type->name());
+  EXPECT_EQ("corge.Qux", qux_type->full_name());
+  EXPECT_TRUE(qux_type->is_placeholder());
+
+  // Placeholder types should not be findable.
+  EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
+  EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
+  EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
+}
+
+TEST_P(AllowUnknownDependenciesTest, CopyTo) {
+  // FieldDescriptor::CopyTo() should write non-fully-qualified type names
+  // for placeholder types which were not originally fully-qualified.
+  FieldDescriptorProto proto;
+
+  // Bar is not a placeholder, so it is fully-qualified.
+  bar_field_->CopyTo(&proto);
+  EXPECT_EQ(".Bar", proto.type_name());
+  EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
+
+  // Baz is an unqualified placeholder.
+  proto.Clear();
+  baz_field_->CopyTo(&proto);
+  EXPECT_EQ("Baz", proto.type_name());
+  EXPECT_FALSE(proto.has_type());
+
+  // Qux is a fully-qualified placeholder.
+  proto.Clear();
+  qux_field_->CopyTo(&proto);
+  EXPECT_EQ(".corge.Qux", proto.type_name());
+  EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
+}
+
+TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
+  // Qux should still have the uninterpreted option attached.
+  ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
+  const UninterpretedOption& option =
+    qux_field_->options().uninterpreted_option(0);
+  ASSERT_EQ(1, option.name_size());
+  EXPECT_EQ("grault", option.name(0).name_part());
+}
+
+TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
+  // Test that we can extend an unknown type.  This is slightly tricky because
+  // it means that the placeholder type must have an extension range.
+
+  FileDescriptorProto extension_proto;
+
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: 'extension.proto'"
+    "extension { extendee: 'UnknownType' name:'some_extension' number:123"
+    "            label:LABEL_OPTIONAL type:TYPE_INT32 }",
+    &extension_proto));
+  const FileDescriptor* file = BuildFile(extension_proto);
+
+  ASSERT_TRUE(file != NULL);
+
+  ASSERT_EQ(1, file->extension_count());
+  const Descriptor* extendee = file->extension(0)->containing_type();
+  EXPECT_EQ("UnknownType", extendee->name());
+  EXPECT_TRUE(extendee->is_placeholder());
+  ASSERT_EQ(1, extendee->extension_range_count());
+  EXPECT_EQ(1, extendee->extension_range(0)->start);
+  EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
+}
+
+TEST_P(AllowUnknownDependenciesTest, CustomOption) {
+  // Test that we can use a custom option without having parsed
+  // descriptor.proto.
+
+  FileDescriptorProto option_proto;
+
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"unknown_custom_options.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { "
+    "  extendee: \"google.protobuf.FileOptions\" "
+    "  name: \"some_option\" "
+    "  number: 123456 "
+    "  label: LABEL_OPTIONAL "
+    "  type: TYPE_INT32 "
+    "} "
+    "options { "
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"some_option\" "
+    "      is_extension: true "
+    "    } "
+    "    positive_int_value: 1234 "
+    "  } "
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"unknown_option\" "
+    "      is_extension: true "
+    "    } "
+    "    positive_int_value: 1234 "
+    "  } "
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"optimize_for\" "
+    "      is_extension: false "
+    "    } "
+    "    identifier_value: \"SPEED\" "
+    "  } "
+    "}",
+    &option_proto));
+
+  const FileDescriptor* file = BuildFile(option_proto);
+  ASSERT_TRUE(file != NULL);
+
+  // Verify that no extension options were set, but they were left as
+  // uninterpreted_options.
+  vector<const FieldDescriptor*> fields;
+  file->options().GetReflection()->ListFields(file->options(), &fields);
+  ASSERT_EQ(2, fields.size());
+  EXPECT_TRUE(file->options().has_optimize_for());
+  EXPECT_EQ(2, file->options().uninterpreted_option_size());
+}
+
+TEST_P(AllowUnknownDependenciesTest,
+       UndeclaredDependencyTriggersBuildOfDependency) {
+  // Crazy case: suppose foo.proto refers to a symbol without declaring the
+  // dependency that finds it. In the event that the pool is backed by a
+  // DescriptorDatabase, the pool will attempt to find the symbol in the
+  // database. If successful, it will build the undeclared dependency to verify
+  // that the file does indeed contain the symbol. If that file fails to build,
+  // then its descriptors must be rolled back. However, we still want foo.proto
+  // to build successfully, since we are allowing unknown dependencies.
+
+  FileDescriptorProto undeclared_dep_proto;
+  // We make this file fail to build by giving it two fields with tag 1.
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"invalid_file_as_undeclared_dep.proto\" "
+    "package: \"undeclared\" "
+    "message_type: {  "
+    "  name: \"Quux\"  "
+    "  field { "
+    "    name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
+    "  }"
+    "  field { "
+    "    name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
+    "  }"
+    "}",
+    &undeclared_dep_proto));
+  // We can't use the BuildFile() helper because we don't actually want to build
+  // it into the descriptor pool in the fallback database case: it just needs to
+  // be sitting in the database so that it gets built during the building of
+  // test.proto below.
+  switch (mode()) {
+    case NO_DATABASE: {
+      ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
+      break;
+    }
+    case FALLBACK_DATABASE: {
+      ASSERT_TRUE(db_.Add(undeclared_dep_proto));
+    }
+  }
+
+  FileDescriptorProto test_proto;
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"test.proto\" "
+    "message_type: { "
+    "  name: \"Corge\" "
+    "  field { "
+    "    name:'quux' number:1 label: LABEL_OPTIONAL "
+    "    type_name:'undeclared.Quux' type: TYPE_MESSAGE "
+    "  }"
+    "}",
+    &test_proto));
+
+  const FileDescriptor* file = BuildFile(test_proto);
+  ASSERT_TRUE(file != NULL);
+  GOOGLE_LOG(INFO) << file->DebugString();
+
+  EXPECT_EQ(0, file->dependency_count());
+  ASSERT_EQ(1, file->message_type_count());
+  const Descriptor* corge_desc = file->message_type(0);
+  ASSERT_EQ("Corge", corge_desc->name());
+  ASSERT_EQ(1, corge_desc->field_count());
+  EXPECT_FALSE(corge_desc->is_placeholder());
+
+  const FieldDescriptor* quux_field = corge_desc->field(0);
+  ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
+  ASSERT_EQ("Quux", quux_field->message_type()->name());
+  ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
+  EXPECT_TRUE(quux_field->message_type()->is_placeholder());
+  // The place holder type should not be findable.
+  ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
+}
+
+INSTANTIATE_TEST_CASE_P(DatabaseSource,
+                        AllowUnknownDependenciesTest,
+                        testing::Values(NO_DATABASE, FALLBACK_DATABASE));
+
+// ===================================================================
+
+TEST(CustomOptions, OptionLocations) {
+  const Descriptor* message =
+      protobuf_unittest::TestMessageWithCustomOptions::descriptor();
+  const FileDescriptor* file = message->file();
+  const FieldDescriptor* field = message->FindFieldByName("field1");
+  const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
+  // TODO(benjy): Support EnumValue options, once the compiler does.
+  const ServiceDescriptor* service =
+      file->FindServiceByName("TestServiceWithCustomOptions");
+  const MethodDescriptor* method = service->FindMethodByName("Foo");
+
+  EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
+            file->options().GetExtension(protobuf_unittest::file_opt1));
+  EXPECT_EQ(-56,
+            message->options().GetExtension(protobuf_unittest::message_opt1));
+  EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
+            field->options().GetExtension(protobuf_unittest::field_opt1));
+  EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
+            field->options().GetExtension(protobuf_unittest::field_opt2));
+  EXPECT_EQ(-789,
+            enm->options().GetExtension(protobuf_unittest::enum_opt1));
+  EXPECT_EQ(123,
+            enm->value(1)->options().GetExtension(
+              protobuf_unittest::enum_value_opt1));
+  EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
+            service->options().GetExtension(protobuf_unittest::service_opt1));
+  EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
+            method->options().GetExtension(protobuf_unittest::method_opt1));
+
+  // See that the regular options went through unscathed.
+  EXPECT_TRUE(message->options().has_message_set_wire_format());
+  EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
+}
+
+TEST(CustomOptions, OptionTypes) {
+  const MessageOptions* options = NULL;
+
+  options =
+      &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
+  EXPECT_EQ(false    , options->GetExtension(protobuf_unittest::bool_opt));
+  EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
+  EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
+  EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint32_opt));
+  EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint64_opt));
+  EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
+  EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
+  EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed32_opt));
+  EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed64_opt));
+  EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
+  EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
+
+  options =
+      &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
+  EXPECT_EQ(true      , options->GetExtension(protobuf_unittest::bool_opt));
+  EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
+  EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
+  EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
+  EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
+  EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
+  EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
+  EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
+  EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
+  EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
+  EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
+
+  options =
+      &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
+  EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
+  EXPECT_FLOAT_EQ(12.3456789,
+                  options->GetExtension(protobuf_unittest::float_opt));
+  EXPECT_DOUBLE_EQ(1.234567890123456789,
+                   options->GetExtension(protobuf_unittest::double_opt));
+  EXPECT_EQ("Hello, \"World\"",
+            options->GetExtension(protobuf_unittest::string_opt));
+
+  EXPECT_EQ(string("Hello\0World", 11),
+            options->GetExtension(protobuf_unittest::bytes_opt));
+
+  EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
+            options->GetExtension(protobuf_unittest::enum_opt));
+
+  options =
+      &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
+  EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
+  EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
+
+  options =
+      &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
+  EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
+  EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
+}
+
+TEST(CustomOptions, ComplexExtensionOptions) {
+  const MessageOptions* options =
+      &protobuf_unittest::VariousComplexOptions::descriptor()->options();
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
+            GetExtension(protobuf_unittest::quux), 324);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
+            GetExtension(protobuf_unittest::corge).qux(), 876);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
+            GetExtension(protobuf_unittest::grault), 654);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
+            743);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
+            GetExtension(protobuf_unittest::quux), 1999);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
+            GetExtension(protobuf_unittest::corge).qux(), 2008);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
+            GetExtension(protobuf_unittest::garply).foo(), 741);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
+            GetExtension(protobuf_unittest::garply).
+            GetExtension(protobuf_unittest::quux), 1998);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
+            GetExtension(protobuf_unittest::garply).
+            GetExtension(protobuf_unittest::corge).qux(), 2121);
+  EXPECT_EQ(options->GetExtension(
+      protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
+            waldo(), 1971);
+  EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
+            fred().waldo(), 321);
+  EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
+  EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
+                complexoptiontype5().plugh());
+  EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
+}
+
+TEST(CustomOptions, OptionsFromOtherFile) {
+  // Test that to use a custom option, we only need to import the file
+  // defining the option; we do not also have to import descriptor.proto.
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+    ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" "
+    "options { "
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"file_opt1\" "
+    "      is_extension: true "
+    "    } "
+    "    positive_int_value: 1234 "
+    "  } "
+    // Test a non-extension option too.  (At one point this failed due to a
+    // bug.)
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"java_package\" "
+    "      is_extension: false "
+    "    } "
+    "    string_value: \"foo\" "
+    "  } "
+    // Test that enum-typed options still work too.  (At one point this also
+    // failed due to a bug.)
+    "  uninterpreted_option { "
+    "    name { "
+    "      name_part: \"optimize_for\" "
+    "      is_extension: false "
+    "    } "
+    "    identifier_value: \"SPEED\" "
+    "  } "
+    "}"
+    ,
+    &file_proto));
+
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+  EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
+  EXPECT_TRUE(file->options().has_java_package());
+  EXPECT_EQ("foo", file->options().java_package());
+  EXPECT_TRUE(file->options().has_optimize_for());
+  EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
+}
+
+TEST(CustomOptions, MessageOptionThreeFieldsSet) {
+  // This tests a bug which previously existed in custom options parsing.  The
+  // bug occurred when you defined a custom option with message type and then
+  // set three fields of that option on a single definition (see the example
+  // below).  The bug is a bit hard to explain, so check the change history if
+  // you want to know more.
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+    ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // The following represents the definition:
+  //
+  //   import "google/protobuf/unittest_custom_options.proto"
+  //   package protobuf_unittest;
+  //   message Foo {
+  //     option (complex_opt1).foo  = 1234;
+  //     option (complex_opt1).foo2 = 1234;
+  //     option (complex_opt1).foo3 = 1234;
+  //   }
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  options { "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo2\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo3\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 1234 "
+    "    } "
+    "  } "
+    "}",
+    &file_proto));
+
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+  ASSERT_EQ(1, file->message_type_count());
+
+  const MessageOptions& options = file->message_type(0)->options();
+  EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
+}
+
+TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
+  // This test verifies that repeated fields in custom options can be
+  // given multiple values by repeating the option with a different value.
+  // This test checks repeated leaf values. Each repeated custom value
+  // appears in a different uninterpreted_option, which will be concatenated
+  // when they are merged into the final option value.
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+    ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // The following represents the definition:
+  //
+  //   import "google/protobuf/unittest_custom_options.proto"
+  //   package protobuf_unittest;
+  //   message Foo {
+  //     option (complex_opt1).foo4 = 12;
+  //     option (complex_opt1).foo4 = 34;
+  //     option (complex_opt1).foo4 = 56;
+  //   }
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  options { "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo4\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 12 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo4\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 34 "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt1\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"foo4\" "
+    "        is_extension: false "
+    "      } "
+    "      positive_int_value: 56 "
+    "    } "
+    "  } "
+    "}",
+    &file_proto));
+
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+  ASSERT_EQ(1, file->message_type_count());
+
+  const MessageOptions& options = file->message_type(0)->options();
+  EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
+  EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
+  EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
+  EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
+}
+
+TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
+  // This test verifies that repeated fields in custom options can be
+  // given multiple values by repeating the option with a different value.
+  // This test checks repeated message values. Each repeated custom value
+  // appears in a different uninterpreted_option, which will be concatenated
+  // when they are merged into the final option value.
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+    ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // The following represents the definition:
+  //
+  //   import "google/protobuf/unittest_custom_options.proto"
+  //   package protobuf_unittest;
+  //   message Foo {
+  //     option (complex_opt2).barney = {waldo: 1};
+  //     option (complex_opt2).barney = {waldo: 10};
+  //     option (complex_opt2).barney = {waldo: 100};
+  //   }
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" "
+    "message_type { "
+    "  name: \"Foo\" "
+    "  options { "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt2\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"barney\" "
+    "        is_extension: false "
+    "      } "
+    "      aggregate_value: \"waldo: 1\" "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt2\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"barney\" "
+    "        is_extension: false "
+    "      } "
+    "      aggregate_value: \"waldo: 10\" "
+    "    } "
+    "    uninterpreted_option { "
+    "      name { "
+    "        name_part: \"complex_opt2\" "
+    "        is_extension: true "
+    "      } "
+    "      name { "
+    "        name_part: \"barney\" "
+    "        is_extension: false "
+    "      } "
+    "      aggregate_value: \"waldo: 100\" "
+    "    } "
+    "  } "
+    "}",
+    &file_proto));
+
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_TRUE(file != NULL);
+  ASSERT_EQ(1, file->message_type_count());
+
+  const MessageOptions& options = file->message_type(0)->options();
+  EXPECT_EQ(3, options.GetExtension(
+      protobuf_unittest::complex_opt2).barney_size());
+  EXPECT_EQ(1,options.GetExtension(
+      protobuf_unittest::complex_opt2).barney(0).waldo());
+  EXPECT_EQ(10, options.GetExtension(
+      protobuf_unittest::complex_opt2).barney(1).waldo());
+  EXPECT_EQ(100, options.GetExtension(
+      protobuf_unittest::complex_opt2).barney(2).waldo());
+}
+
+// Check that aggregate options were parsed and saved correctly in
+// the appropriate descriptors.
+TEST(CustomOptions, AggregateOptions) {
+  const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
+  const FileDescriptor* file = msg->file();
+  const FieldDescriptor* field = msg->FindFieldByName("fieldname");
+  const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
+  const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
+  const ServiceDescriptor* service = file->FindServiceByName(
+      "AggregateService");
+  const MethodDescriptor* method = service->FindMethodByName("Method");
+
+  // Tests for the different types of data embedded in fileopt
+  const protobuf_unittest::Aggregate& file_options =
+      file->options().GetExtension(protobuf_unittest::fileopt);
+  EXPECT_EQ(100, file_options.i());
+  EXPECT_EQ("FileAnnotation", file_options.s());
+  EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
+  EXPECT_EQ("FileExtensionAnnotation",
+            file_options.file().GetExtension(protobuf_unittest::fileopt).s());
+  EXPECT_EQ("EmbeddedMessageSetElement",
+            file_options.mset().GetExtension(
+                protobuf_unittest::AggregateMessageSetElement
+                ::message_set_extension).s());
+
+  // Simple tests for all the other types of annotations
+  EXPECT_EQ("MessageAnnotation",
+            msg->options().GetExtension(protobuf_unittest::msgopt).s());
+  EXPECT_EQ("FieldAnnotation",
+            field->options().GetExtension(protobuf_unittest::fieldopt).s());
+  EXPECT_EQ("EnumAnnotation",
+            enumd->options().GetExtension(protobuf_unittest::enumopt).s());
+  EXPECT_EQ("EnumValueAnnotation",
+            enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
+  EXPECT_EQ("ServiceAnnotation",
+            service->options().GetExtension(protobuf_unittest::serviceopt).s());
+  EXPECT_EQ("MethodAnnotation",
+            method->options().GetExtension(protobuf_unittest::methodopt).s());
+}
+
+TEST(CustomOptions, UnusedImportWarning) {
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  protobuf_unittest::TestMessageWithCustomOptions::descriptor()
+      ->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  pool.AddUnusedImportTrackFile("custom_options_import.proto");
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"custom_options_import.proto\" "
+    "package: \"protobuf_unittest\" "
+    "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
+    &file_proto));
+
+  MockErrorCollector error_collector;
+  EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector));
+  EXPECT_EQ("", error_collector.warning_text_);
+}
+
+// Verifies that proto files can correctly be parsed, even if the
+// custom options defined in the file are incompatible with those
+// compiled in the binary. See http://b/19276250.
+TEST(CustomOptions, OptionsWithRequiredEnums) {
+  DescriptorPool pool;
+
+  FileDescriptorProto file_proto;
+  MessageOptions::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // Create a new file descriptor proto containing a subset of the
+  // messages defined in google/protobuf/unittest_custom_options.proto.
+  file_proto.Clear();
+  file_proto.set_name("unittest_custom_options.proto");
+  file_proto.set_package("protobuf_unittest");
+  file_proto.add_dependency("google/protobuf/descriptor.proto");
+
+  // Add the "required_enum_opt" extension.
+  FieldDescriptorProto* extension = file_proto.add_extension();
+  protobuf_unittest::OldOptionType::descriptor()->file()
+      ->FindExtensionByName("required_enum_opt")->CopyTo(extension);
+
+  // Add a test message that uses the "required_enum_opt" option.
+  DescriptorProto* test_message_type = file_proto.add_message_type();
+  protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor()
+      ->CopyTo(test_message_type);
+
+  // Instruct the extension to use NewOptionType instead of
+  // OldOptionType, and add the descriptor of NewOptionType.
+  extension->set_type_name(".protobuf_unittest.NewOptionType");
+  DescriptorProto* new_option_type = file_proto.add_message_type();
+  protobuf_unittest::NewOptionType::descriptor()
+      ->CopyTo(new_option_type);
+
+  // Replace the value of the "required_enum_opt" option used in the
+  // test message with an enum value that only exists in NewOptionType.
+  ASSERT_TRUE(TextFormat::ParseFromString(
+      "uninterpreted_option { "
+      "  name { "
+      "    name_part: 'required_enum_opt' "
+      "    is_extension: true "
+      "  } "
+      "  aggregate_value: 'value: NEW_VALUE' "
+      "}",
+      test_message_type->mutable_options()));
+
+  // Add the file descriptor to the pool.
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // Find the test message.
+  const Descriptor* test_message = pool.FindMessageTypeByName(
+      "protobuf_unittest.TestMessageWithRequiredEnumOption");
+  ASSERT_TRUE(test_message != NULL);
+
+  const MessageOptions& options = test_message->options();
+  // Extract the "required_enum_opt" option. Since the binary does not
+  // know that the extension was updated, this will still return an
+  // OldOptionType message.
+  ASSERT_TRUE(
+      options.HasExtension(protobuf_unittest::required_enum_opt));
+  const protobuf_unittest::OldOptionType& old_enum_opt =
+      options.GetExtension(protobuf_unittest::required_enum_opt);
+
+  // Confirm that the required enum field is missing.
+  EXPECT_FALSE(old_enum_opt.IsInitialized());
+  EXPECT_FALSE(old_enum_opt.has_value());
+
+  string buf;
+  // Verify that the required enum field does show up when the option
+  // is re-parsed as a NewOptionType message;
+  protobuf_unittest::NewOptionType new_enum_opt;
+  EXPECT_TRUE(old_enum_opt.AppendPartialToString(&buf));
+  EXPECT_TRUE(new_enum_opt.ParseFromString(buf));
+  EXPECT_EQ(protobuf_unittest::NewOptionType::NEW_VALUE, new_enum_opt.value());
+}
+
+// ===================================================================
+
+class ValidationErrorTest : public testing::Test {
+ protected:
+  // Parse file_text as a FileDescriptorProto in text format and add it
+  // to the DescriptorPool.  Expect no errors.
+  const FileDescriptor* BuildFile(const string& file_text) {
+    FileDescriptorProto file_proto;
+    EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+    return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
+  }
+
+  // Parse file_text as a FileDescriptorProto in text format and add it
+  // to the DescriptorPool.  Expect errors to be produced which match the
+  // given error text.
+  void BuildFileWithErrors(const string& file_text,
+                           const string& expected_errors) {
+    FileDescriptorProto file_proto;
+    ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+
+    MockErrorCollector error_collector;
+    EXPECT_TRUE(
+      pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
+    EXPECT_EQ(expected_errors, error_collector.text_);
+  }
+
+  // Parse file_text as a FileDescriptorProto in text format and add it
+  // to the DescriptorPool.  Expect errors to be produced which match the
+  // given warning text.
+  void BuildFileWithWarnings(const string& file_text,
+                             const string& expected_warnings) {
+    FileDescriptorProto file_proto;
+    ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+
+    MockErrorCollector error_collector;
+    EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
+    EXPECT_EQ(expected_warnings, error_collector.warning_text_);
+  }
+
+  // Builds some already-parsed file in our test pool.
+  void BuildFileInTestPool(const FileDescriptor* file) {
+    FileDescriptorProto file_proto;
+    file->CopyTo(&file_proto);
+    ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
+  }
+
+  // Build descriptor.proto in our test pool. This allows us to extend it in
+  // the test pool, so we can test custom options.
+  void BuildDescriptorMessagesInTestPool() {
+    BuildFileInTestPool(DescriptorProto::descriptor()->file());
+  }
+
+  DescriptorPool pool_;
+};
+
+TEST_F(ValidationErrorTest, AlreadyDefined) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" }"
+    "message_type { name: \"Foo\" }",
+
+    "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "package: \"foo.bar\" "
+    "message_type { name: \"Foo\" }"
+    "message_type { name: \"Foo\" }",
+
+    "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
+      "\"foo.bar\".\n");
+}
+
+TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" }");
+
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Foo\" }",
+
+    "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
+      "\"foo.proto\".\n");
+}
+
+TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type { name: \"foo\" }");
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "package: \"foo.bar\"",
+
+    "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
+      "than a package) in file \"foo.proto\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
+    "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
+
+    "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
+    "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
+      "meaning that enum values are siblings of their type, not children of "
+      "it.  Therefore, \"FOO\" must be unique within the global scope, not "
+      "just within \"Bar\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "package: \"pkg\" "
+    "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
+    "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
+
+    "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
+    "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
+      "meaning that enum values are siblings of their type, not children of "
+      "it.  Therefore, \"FOO\" must be unique within \"pkg\", not just within "
+      "\"Bar\".\n");
+}
+
+TEST_F(ValidationErrorTest, MissingName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { }",
+
+    "foo.proto: : NAME: Missing name.\n");
+}
+
+TEST_F(ValidationErrorTest, InvalidName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"$\" }",
+
+    "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, InvalidPackageName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "package: \"foo.$\"",
+
+    "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, MissingFileName) {
+  BuildFileWithErrors(
+    "",
+
+    ": : OTHER: Missing field: FileDescriptorProto.name.\n");
+}
+
+TEST_F(ValidationErrorTest, DupeDependency) {
+  BuildFile("name: \"foo.proto\"");
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "dependency: \"foo.proto\" "
+    "dependency: \"foo.proto\" ",
+
+    "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
+}
+
+TEST_F(ValidationErrorTest, UnknownDependency) {
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "dependency: \"foo.proto\" ",
+
+    "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
+}
+
+TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
+  BuildFile("name: \"foo.proto\"");
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "dependency: \"foo.proto\" "
+    "public_dependency: 1",
+    "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
+}
+
+TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
+  // Used to crash:  If we depend on a non-existent file and then refer to a
+  // package defined in a file that we didn't import, and that package is
+  // nested within a parent package which this file is also in, and we don't
+  // include that parent package in the name (i.e. we do a relative lookup)...
+  // Yes, really.
+  BuildFile(
+    "name: 'foo.proto' "
+    "package: 'outer.foo' ");
+  BuildFileWithErrors(
+    "name: 'bar.proto' "
+    "dependency: 'baz.proto' "
+    "package: 'outer.bar' "
+    "message_type { "
+    "  name: 'Bar' "
+    "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
+    "}",
+
+    "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
+    "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
+      "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
+      "please add the necessary import.\n");
+}
+
+TEST_F(ValidationErrorTest, DupeFile) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" }");
+  // Note:  We should *not* get redundant errors about "Foo" already being
+  //   defined.
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    // Add another type so that the files aren't identical (in which case there
+    // would be no error).
+    "enum_type { name: \"Bar\" }",
+
+    "foo.proto: foo.proto: OTHER: A file with this name is already in the "
+      "pool.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldInExtensionRange) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  extension_range { start: 10 end: 20 }"
+    "}",
+
+    "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
+      "\"bar\" (10).\n"
+    "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
+      "\"baz\" (19).\n");
+}
+
+TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: 10 end: 20 }"
+    "  extension_range { start: 20 end: 30 }"
+    "  extension_range { start: 19 end: 21 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
+      "already-defined range 10 to 19.\n"
+    "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
+      "already-defined range 20 to 29.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedFieldError) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  reserved_range { start: 10 end: 20 }"
+    "}",
+
+    "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: 10 end: 20 }"
+    "  reserved_range { start: 5 end: 15 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Extension range 10 to 19"
+    " overlaps with reserved range 5 to 14.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: 10 end: 20 }"
+    "  reserved_range { start: 5 end: 10 }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  reserved_range { start: 10 end: 20 }"
+    "  reserved_range { start: 5 end: 15 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
+    " overlaps with already-defined range 10 to 19.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameError) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  reserved_name: \"foo\""
+    "  reserved_name: \"bar\""
+    "}",
+
+    "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
+    "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameRedundant) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  reserved_name: \"foo\""
+    "  reserved_name: \"foo\""
+    "}",
+
+    "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
+  const FileDescriptor* file = BuildFile(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  reserved_name: \"foo\""
+    "  reserved_name: \"bar\""
+    "  reserved_range { start: 5 end: 6 }"
+    "  reserved_range { start: 10 end: 20 }"
+    "}");
+
+  ASSERT_EQ(
+    "syntax = \"proto2\";\n\n"
+    "message Foo {\n"
+    "  reserved 5, 10 to 19;\n"
+    "  reserved \"foo\", \"bar\";\n"
+    "}\n\n",
+    file->DebugString());
+}
+
+TEST_F(ValidationErrorTest, InvalidDefaults) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+
+    // Invalid number.
+    "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
+    "          default_value: \"abc\" }"
+
+    // Empty default value.
+    "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
+    "          default_value: \"\" }"
+
+    // Invalid boolean.
+    "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
+    "          default_value: \"abc\" }"
+
+    // Messages can't have defaults.
+    "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
+    "          default_value: \"abc\" type_name: \"Foo\" }"
+
+    // Same thing, but we don't know that this field has message type until
+    // we look up the type name.
+    "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
+    "          default_value: \"abc\" type_name: \"Foo\" }"
+
+    // Repeateds can't have defaults.
+    "  field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
+    "          default_value: \"1\" }"
+    "}",
+
+    "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n"
+    "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
+    "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
+      "false.\n"
+    "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
+    "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
+      "values.\n"
+    // This ends up being reported later because the error is detected at
+    // cross-linking time.
+    "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
+      "values.\n");
+}
+
+TEST_F(ValidationErrorTest, NegativeFieldNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
+}
+
+TEST_F(ValidationErrorTest, HugeFieldNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: 0x70000000 "
+    "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
+      "536870911.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedFieldNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
+      "reserved for the protocol buffer library implementation.\n"
+    "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
+      "reserved for the protocol buffer library implementation.\n");
+}
+
+TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
+    "              type_name: \"Foo\" }"
+    "}",
+
+    "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
+      "extension field.\n");
+}
+
+TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "  extension_range { start: 1 end: 2 }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
+    "          type_name: \"Foo\" extendee: \"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
+      "non-extension field.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+    "          oneof_index: 1 }"
+    "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+    "          oneof_index: 0 }"
+    "  oneof_decl { name:\"bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of "
+      "range for type \"Foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+    "          oneof_index: -1 }"
+    "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+    "          oneof_index: 0 }"
+    "  oneof_decl { name:\"bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of "
+      "range for type \"Foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
+  // Fields belonging to the same oneof must be defined consecutively.
+  BuildFileWithErrors(
+      "name: \"foo.proto\" "
+      "message_type {"
+      "  name: \"Foo\""
+      "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  oneof_decl { name:\"foos\" }"
+      "}",
+
+      "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined "
+      "consecutively. \"bar\" cannot be defined before the completion of the "
+      "\"foos\" oneof definition.\n");
+
+  // Prevent interleaved fields, which belong to different oneofs.
+  BuildFileWithErrors(
+      "name: \"foo2.proto\" "
+      "message_type {"
+      "  name: \"Foo2\""
+      "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 1 }"
+      "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 1 }"
+      "  oneof_decl { name:\"foos\" }"
+      "  oneof_decl { name:\"bars\" }"
+      "}",
+      "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined "
+      "consecutively. \"bar1\" cannot be defined before the completion of the "
+      "\"foos\" oneof definition.\n"
+      "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
+      "consecutively. \"foo2\" cannot be defined before the completion of the "
+      "\"bars\" oneof definition.\n");
+
+  // Another case for normal fields and different oneof fields interleave.
+  BuildFileWithErrors(
+      "name: \"foo3.proto\" "
+      "message_type {"
+      "  name: \"Foo3\""
+      "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 1 }"
+      "  field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "  field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          oneof_index: 0 }"
+      "  oneof_decl { name:\"foos\" }"
+      "  oneof_decl { name:\"bars\" }"
+      "}",
+      "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined "
+      "consecutively. \"baz\" cannot be defined before the completion of the "
+      "\"foos\" oneof definition.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldNumberConflict) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
+      "\"Foo\" by field \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"MessageSet\""
+    "  options { message_set_wire_format: true }"
+    "  extension_range { start: 4 end: 5 }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
+    "              extendee: \"MessageSet\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
+      "messages.\n");
+}
+
+TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"MessageSet\""
+    "  options { message_set_wire_format: true }"
+    "  extension_range { start: 4 end: 5 }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
+    "              type_name: \"Foo\" extendee: \"MessageSet\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
+      "messages.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldInMessageSet) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  options { message_set_wire_format: true }"
+    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
+      "extensions.\n");
+}
+
+TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: -10 end: -1 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
+}
+
+TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: 1 end: 0x70000000 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
+      "536870911.\n");
+}
+
+TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension_range { start: 10 end: 10 }"
+    "  extension_range { start: 10 end: 5 }"
+    "}",
+
+    "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
+      "start number.\n"
+    "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
+      "start number.\n");
+}
+
+TEST_F(ValidationErrorTest, EmptyEnum) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Foo\" }"
+    // Also use the empty enum in a message to make sure there are no crashes
+    // during validation (possible if the code attempts to derive a default
+    // value for the field).
+    "message_type {"
+    "  name: \"Bar\""
+    "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
+    "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
+    "          default_value: \"NO_SUCH_VALUE\" }"
+    "}",
+
+    "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
+    "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
+      "\"NO_SUCH_VALUE\".\n");
+}
+
+TEST_F(ValidationErrorTest, UndefinedExtendee) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
+    "              extendee: \"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
+}
+
+TEST_F(ValidationErrorTest, NonMessageExtendee) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
+    "              extendee: \"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
+}
+
+TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
+    "              extendee: \"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
+      "number.\n");
+}
+
+TEST_F(ValidationErrorTest, RequiredExtension) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "  extension_range { start: 1000 end: 10000 }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  extension {"
+    "    name:\"foo\""
+    "    number:1000"
+    "    label:LABEL_REQUIRED"
+    "    type:TYPE_INT32"
+    "    extendee: \"Bar\""
+    "  }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: Message extensions cannot have required "
+    "fields.\n");
+}
+
+TEST_F(ValidationErrorTest, UndefinedFieldType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
+}
+
+TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
+  // See b/12533582. Previously this failed because the default value was not
+  // accepted by the parser, which assumed an enum type, leading to an unclear
+  // error message. We want this input to yield a validation error instead,
+  // since the unknown type is the primary problem.
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
+    "          default_value:\"1\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
+}
+
+TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  nested_type { name:\"Baz\" }"
+    "  field { name:\"foo\" number:1"
+    "          label:LABEL_OPTIONAL"
+    "          type_name:\"Foo.Baz.Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" } ");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+      "which is not imported by \"foo.proto\".  To use it here, please add the "
+      "necessary import.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
+  // Test for hidden dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import "bar.proto"
+  //
+  // // foo.proto
+  // import "forward.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\"");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"forward.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+      "which is not imported by \"foo.proto\".  To use it here, please add the "
+      "necessary import.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import public "bar.proto"
+  //
+  // // foo.proto
+  // import "forward.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
+  //                          // forward.proto, so when "foo.proto" imports
+  //                          // "forward.proto", it imports "bar.proto" too.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "dependency: \"forward.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import public "bar.proto"
+  //
+  // // forward2.proto
+  // import public "forward.proto"
+  //
+  // // foo.proto
+  // import "forward2.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Correct, public imports are transitive.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"forward2.proto\""
+    "dependency: \"forward.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "dependency: \"forward2.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest,
+       FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import "bar.proto"
+  //
+  // // forward2.proto
+  // import public "forward.proto"
+  //
+  // // foo.proto
+  // import "forward2.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
+  //                          // into "forward.proto", so will not be imported
+  //                          // into either "forward2.proto" or "foo.proto".
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\"");
+
+  BuildFile(
+    "name: \"forward2.proto\""
+    "dependency: \"forward.proto\" "
+    "public_dependency: 0");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"forward2.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+      "which is not imported by \"foo.proto\".  To use it here, please add the "
+      "necessary import.\n");
+}
+
+
+TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
+  // The following should produce an error that Bar.Baz is resolved but
+  // not defined:
+  //   message Bar { message Baz {} }
+  //   message Foo {
+  //     message Bar {
+  //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
+  //       // would fix the error.
+  //     }
+  //     optional Bar.Baz baz = 1;
+  //   }
+  // An one point the lookup code incorrectly did not produce an error in this
+  // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
+  // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
+  // refer to the inner Bar, not the outer one.
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "  nested_type { name: \"Baz\" }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  nested_type { name: \"Bar\" }"
+    "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
+    "          type_name:\"Bar.Baz\" }"
+    "}",
+
+    "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
+    " which is not defined. The innermost scope is searched first in name "
+    "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
+    "from the outermost scope.\n");
+}
+
+TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
+  // This test would find the most local "Bar" first, and does, but
+  // proceeds to find the outer one because the inner one's not an
+  // aggregate.
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "  nested_type { name: \"Baz\" }"
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name: \"Bar\" number:1 type:TYPE_BYTES } "
+    "  field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
+    "          type_name:\"Bar.Baz\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
+  // Imagine we have the following:
+  //
+  // foo.proto:
+  //   package foo.bar;
+  // bar.proto:
+  //   package foo.bar;
+  //   import "foo.proto";
+  //   message Bar {}
+  // baz.proto:
+  //   package foo;
+  //   import "bar.proto"
+  //   message Baz { optional bar.Bar qux = 1; }
+  //
+  // When validating baz.proto, we will look up "bar.Bar".  As part of this
+  // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
+  // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
+  // defined in foo.proto, which is not a direct dependency of baz.proto.  The
+  // implementation of FindSymbol() normally only returns symbols in direct
+  // dependencies, not indirect ones.  This test insures that this does not
+  // prevent it from finding "foo.bar".
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "package: \"foo.bar\" ");
+  BuildFile(
+    "name: \"bar.proto\" "
+    "package: \"foo.bar\" "
+    "dependency: \"foo.proto\" "
+    "message_type { name: \"Bar\" }");
+  BuildFile(
+    "name: \"baz.proto\" "
+    "package: \"foo\" "
+    "dependency: \"bar.proto\" "
+    "message_type { "
+    "  name: \"Baz\" "
+    "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
+    "          type_name:\"bar.Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeNotAType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
+    "          type_name:\".Foo.bar\" }"
+    "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
+}
+
+TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  nested_type {"
+    "    name: \"Bar\""
+    "    field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+    "  }"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
+    "          type_name:\"Bar.Baz\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Bar\""
+    "}"
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Bar\" } "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
+    "          type_name:\"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
+}
+
+TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
+    "          type_name:\"Bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
+}
+
+TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
+    "          default_value:\"NO_SUCH_VALUE\" }"
+    "}",
+
+    "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
+      "\"NO_SUCH_VALUE\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
+    "          default_value:\"0\" }"
+    "}",
+
+    "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
+    "be an identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
+    "          type_name:\"Foo\" }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
+}
+
+TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
+    "}",
+
+    "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
+      "type_name.\n");
+}
+
+TEST_F(ValidationErrorTest, OneofWithNoFields) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  oneof_decl { name:\"bar\" }"
+    "}",
+
+    "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
+}
+
+TEST_F(ValidationErrorTest, OneofLabelMismatch) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
+    "          oneof_index:0 }"
+    "  oneof_decl { name:\"bar\" }"
+    "}",
+
+    "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
+      "LABEL_OPTIONAL.\n");
+}
+
+TEST_F(ValidationErrorTest, InputTypeNotDefined) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    "service {"
+    "  name: \"TestService\""
+    "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
+    "}",
+
+    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
+    );
+}
+
+TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
+    "service {"
+    "  name: \"TestService\""
+    "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
+    "}",
+
+    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
+    );
+}
+
+TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    "service {"
+    "  name: \"TestService\""
+    "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
+    "}",
+
+    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
+    );
+}
+
+TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
+    "service {"
+    "  name: \"TestService\""
+    "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
+    "}",
+
+    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
+    );
+}
+
+
+TEST_F(ValidationErrorTest, IllegalPackedField) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {\n"
+    "  name: \"Foo\""
+    "  field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
+    "          type:TYPE_STRING "
+    "          options { uninterpreted_option {"
+    "            name { name_part: \"packed\" is_extension: false }"
+    "            identifier_value: \"true\" }}}\n"
+    "  field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
+    "          type_name: \"Foo\""
+    "          options { uninterpreted_option {"
+    "            name { name_part: \"packed\" is_extension: false }"
+    "            identifier_value: \"true\" }}}\n"
+    "  field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
+    "          type:TYPE_INT32 "
+    "          options { uninterpreted_option {"
+    "            name { name_part: \"packed\" is_extension: false }"
+    "            identifier_value: \"true\" }}}\n"
+    "}",
+
+    "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
+        "specified for repeated primitive fields.\n"
+    "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
+        "specified for repeated primitive fields.\n"
+    "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
+        "specified for repeated primitive fields.\n"
+        );
+}
+
+TEST_F(ValidationErrorTest, OptionWrongType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"TestMessage\" "
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
+    "          options { uninterpreted_option { name { name_part: \"ctype\" "
+    "                                                  is_extension: false }"
+    "                                           positive_int_value: 1 }"
+    "          }"
+    "  }"
+    "}\n",
+
+    "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
+    "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
+}
+
+TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"TestMessage\" "
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
+    "          options { uninterpreted_option { name { name_part: \"ctype\" "
+    "                                                  is_extension: false }"
+    "                                           name { name_part: \"foo\" "
+    "                                                  is_extension: true }"
+    "                                           positive_int_value: 1 }"
+    "          }"
+    "  }"
+    "}\n",
+
+    "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
+    "atomic type, not a message.\n");
+}
+
+TEST_F(ValidationErrorTest, DupOption) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"TestMessage\" "
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
+    "          options { uninterpreted_option { name { name_part: \"ctype\" "
+    "                                                  is_extension: false }"
+    "                                           identifier_value: \"CORD\" }"
+    "                    uninterpreted_option { name { name_part: \"ctype\" "
+    "                                                  is_extension: false }"
+    "                                           identifier_value: \"CORD\" }"
+    "          }"
+    "  }"
+    "}\n",
+
+    "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
+    "already set.\n");
+}
+
+TEST_F(ValidationErrorTest, InvalidOptionName) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type { "
+    "  name: \"TestMessage\" "
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
+    "          options { uninterpreted_option { "
+    "                      name { name_part: \"uninterpreted_option\" "
+    "                             is_extension: false }"
+    "                      positive_int_value: 1 "
+    "                    }"
+    "          }"
+    "  }"
+    "}\n",
+
+    "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
+    "reserved name \"uninterpreted_option\".\n");
+}
+
+TEST_F(ValidationErrorTest, RepeatedMessageOption) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "message_type: { name: \"Bar\" field: { "
+    "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
+    "} "
+    "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
+    "            type: TYPE_MESSAGE type_name: \"Bar\" "
+    "            extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"bar\" "
+    "                                        is_extension: true } "
+    "                                 name { name_part: \"foo\" "
+    "                                        is_extension: false } "
+    "                                 positive_int_value: 1 } }",
+
+    "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
+    "repeated message. Repeated message options must be initialized "
+    "using an aggregate value.\n");
+}
+
+TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
+  // The following should produce an eror that baz.bar is resolved but not
+  // defined.
+  // foo.proto:
+  //   package baz
+  //   import google/protobuf/descriptor.proto
+  //   message Bar { optional int32 foo = 1; }
+  //   extend FileOptions { optional Bar bar = 7672757; }
+  //
+  // qux.proto:
+  //   package qux.baz
+  //   option (baz.bar).foo = 1;
+  //
+  // Although "baz.bar" is already defined, the lookup code will try
+  // "qux.baz.bar", since it's the match from the innermost scope, which will
+  // cause a symbol not defined error.
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "package: \"baz\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "message_type: { name: \"Bar\" field: { "
+    "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
+    "} "
+    "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_MESSAGE type_name: \"Bar\" "
+    "            extendee: \"google.protobuf.FileOptions\" }");
+
+  BuildFileWithErrors(
+    "name: \"qux.proto\" "
+    "package: \"qux.baz\" "
+    "options { uninterpreted_option { name { name_part: \"baz.bar\" "
+    "                                        is_extension: true } "
+    "                                 name { name_part: \"foo\" "
+    "                                        is_extension: false } "
+    "                                 positive_int_value: 1 } }",
+
+    "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
+    "\"(qux.baz.bar)\","
+    " which is not defined. The innermost scope is searched first in name "
+    "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
+    "from the outermost scope.\n");
+}
+
+TEST_F(ValidationErrorTest, UnknownOption) {
+  BuildFileWithErrors(
+    "name: \"qux.proto\" "
+    "package: \"qux.baz\" "
+    "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
+    "                                        is_extension: true } "
+    "                                 name { name_part: \"foo\" "
+    "                                        is_extension: false } "
+    "                                 positive_int_value: 1 } }",
+
+    "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n");
+}
+
+TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
+    "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
+
+    "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
+    "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
+}
+
+TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 positive_int_value: 0x80000000 } "
+    "}",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+    "for int32 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 negative_int_value: -0x80000001 } "
+    "}",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+    "for int32 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 string_value: \"5\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
+    "for int32 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 positive_int_value: 0x8000000000000000 } "
+    "}",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+    "for int64 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 identifier_value: \"5\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
+    "for int64 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 positive_int_value: 0x100000000 } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+    "for uint32 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 double_value: -5.6 } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
+    "for uint32 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 negative_int_value: -5 } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
+    "for uint64 option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 string_value: \"bar\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
+    "for float option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 string_value: \"bar\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
+    "for double option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 identifier_value: \"bar\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
+    "for boolean option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
+    "                              value { name: \"BAZ\" number: 2 } }"
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_ENUM type_name: \"FooEnum\" "
+    "            extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 string_value: \"QUUX\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
+    "enum-valued option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
+    "                              value { name: \"BAZ\" number: 2 } }"
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_ENUM type_name: \"FooEnum\" "
+    "            extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 identifier_value: \"QUUX\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
+    "named \"QUUX\" for option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
+    "                               value { name: \"BAZ\" number: 2 } }"
+    "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
+    "                               value { name: \"QUUX\" number: 2 } }"
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_ENUM type_name: \"FooEnum1\" "
+    "            extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 identifier_value: \"QUUX\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
+    "named \"QUUX\" for option \"foo\". This appears to be a value from a "
+    "sibling type.\n");
+}
+
+TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"google/protobuf/descriptor.proto\" "
+    "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+    "            type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
+    "options { uninterpreted_option { name { name_part: \"foo\" "
+    "                                        is_extension: true } "
+    "                                 identifier_value: \"QUUX\" } }",
+
+    "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
+    "string option \"foo\".\n");
+}
+
+TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFile(
+      "name: \"foo.proto\" "
+      "dependency: \"google/protobuf/descriptor.proto\" "
+      "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
+      "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
+
+  BuildFileWithWarnings(
+      "name: \"bar.proto\" "
+      "dependency: \"google/protobuf/descriptor.proto\" "
+      "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
+      "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
+      "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
+      "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
+      "foo.proto.\n");
+}
+
+// Helper function for tests that check for aggregate value parsing
+// errors.  The "value" argument is embedded inside the
+// "uninterpreted_option" portion of the result.
+static string EmbedAggregateValue(const char* value) {
+  return strings::Substitute(
+      "name: \"foo.proto\" "
+      "dependency: \"google/protobuf/descriptor.proto\" "
+      "message_type { name: \"Foo\" } "
+      "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+      "            type: TYPE_MESSAGE type_name: \"Foo\" "
+      "            extendee: \"google.protobuf.FileOptions\" }"
+      "options { uninterpreted_option { name { name_part: \"foo\" "
+      "                                        is_extension: true } "
+      "                                 $0 } }",
+      value);
+}
+
+TEST_F(ValidationErrorTest, AggregateValueNotFound) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("string_value: \"\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
+      "To set the entire message, use syntax like "
+      "\"foo = { <proto text format> }\". To set fields within it, use "
+      "syntax like \"foo.foo = value\".\n");
+}
+
+TEST_F(ValidationErrorTest, AggregateValueParseError) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"1+2\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Expected identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"x:100\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
+}
+
+TEST_F(ValidationErrorTest, NotLiteImportsLite) {
+  BuildFile(
+    "name: \"bar.proto\" "
+    "options { optimize_for: LITE_RUNTIME } ");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"bar.proto\" ",
+
+    "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
+      "LITE_RUNTIME cannot import files which do use this option.  This file "
+      "is not lite, but it imports \"bar.proto\" which is.\n");
+}
+
+TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type: {"
+    "  name: \"Bar\""
+    "  extension_range { start: 1 end: 1000 }"
+    "}");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"bar.proto\" "
+    "options { optimize_for: LITE_RUNTIME } "
+    "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
+    "            type: TYPE_INT32 extendee: \"Bar\" }",
+
+    "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
+      "declared in non-lite files.  Note that you cannot extend a non-lite "
+      "type to contain a lite type, but the reverse is allowed.\n");
+}
+
+TEST_F(ValidationErrorTest, NoLiteServices) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "options {"
+    "  optimize_for: LITE_RUNTIME"
+    "  cc_generic_services: true"
+    "  java_generic_services: true"
+    "} "
+    "service { name: \"Foo\" }",
+
+    "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
+    "define services unless you set both options cc_generic_services and "
+    "java_generic_sevices to false.\n");
+
+  BuildFile(
+    "name: \"bar.proto\" "
+    "options {"
+    "  optimize_for: LITE_RUNTIME"
+    "  cc_generic_services: false"
+    "  java_generic_services: false"
+    "} "
+    "service { name: \"Bar\" }");
+}
+
+TEST_F(ValidationErrorTest, RollbackAfterError) {
+  // Build a file which contains every kind of construct but references an
+  // undefined type.  All these constructs will be added to the symbol table
+  // before the undefined type error is noticed.  The DescriptorPool will then
+  // have to roll everything back.
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
+    "} "
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"BAR\" number:1 }"
+    "} "
+    "service {"
+    "  name: \"TestService\""
+    "  method {"
+    "    name: \"Baz\""
+    "    input_type: \"NoSuchType\""    // error
+    "    output_type: \"TestMessage\""
+    "  }"
+    "}",
+
+    "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
+    );
+
+  // Make sure that if we build the same file again with the error fixed,
+  // it works.  If the above rollback was incomplete, then some symbols will
+  // be left defined, and this second attempt will fail since it tries to
+  // re-define the same symbols.
+  BuildFile(
+    "name: \"foo.proto\" "
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
+    "} "
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"BAR\" number:1 }"
+    "} "
+    "service {"
+    "  name: \"TestService\""
+    "  method { name:\"Baz\""
+    "           input_type:\"TestMessage\""
+    "           output_type:\"TestMessage\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
+  // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
+  // provided.
+
+  FileDescriptorProto file_proto;
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"foo.proto\" "
+    "message_type { name: \"Foo\" } "
+    "message_type { name: \"Foo\" } ",
+    &file_proto));
+
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog log;
+    EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
+    errors = log.GetMessages(ERROR);
+  }
+
+  ASSERT_EQ(2, errors.size());
+
+  EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
+  EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
+}
+
+TEST_F(ValidationErrorTest, DisallowEnumAlias) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type {"
+    "  name: \"Bar\""
+    "  value { name:\"ENUM_A\" number:0 }"
+    "  value { name:\"ENUM_B\" number:0 }"
+    "}",
+    "foo.proto: Bar: NUMBER: "
+    "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
+    "If this is intended, set 'option allow_alias = true;' to the enum "
+    "definition.\n");
+}
+
+TEST_F(ValidationErrorTest, AllowEnumAlias) {
+  BuildFile(
+    "name: \"foo.proto\" "
+    "enum_type {"
+    "  name: \"Bar\""
+    "  value { name:\"ENUM_A\" number:0 }"
+    "  value { name:\"ENUM_B\" number:0 }"
+    "  options { allow_alias: true }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, UnusedImportWarning) {
+  pool_.AddUnusedImportTrackFile("bar.proto");
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  pool_.AddUnusedImportTrackFile("base.proto");
+  BuildFile(
+    "name: \"base.proto\" "
+    "message_type { name: \"Base\" }");
+
+  pool_.AddUnusedImportTrackFile("baz.proto");
+  BuildFile(
+    "name: \"baz.proto\" "
+    "message_type { name: \"Baz\" }");
+
+  pool_.AddUnusedImportTrackFile("public.proto");
+  BuildFile(
+    "name: \"public.proto\" "
+    "dependency: \"bar.proto\""
+    "public_dependency: 0");
+
+  // // forward.proto
+  // import "base.proto"       // No warning: Base message is used.
+  // import "bar.proto"        // Will log a warning.
+  // import public "baz.proto" // No warning: Do not track import public.
+  // import "public.proto"     // No warning: public.proto has import public.
+  // message Forward {
+  //   optional Base base = 1;
+  // }
+  //
+  pool_.AddUnusedImportTrackFile("forward.proto");
+  BuildFileWithWarnings(
+    "name: \"forward.proto\""
+    "dependency: \"base.proto\""
+    "dependency: \"bar.proto\""
+    "dependency: \"baz.proto\""
+    "dependency: \"public.proto\""
+    "public_dependency: 2 "
+    "message_type {"
+    "  name: \"Forward\""
+    "  field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }"
+    "}",
+    "forward.proto: bar.proto: OTHER: Import bar.proto but not used.\n");
+}
+
+namespace {
+void FillValidMapEntry(FileDescriptorProto* file_proto) {
+  ASSERT_TRUE(TextFormat::ParseFromString(
+      "name: 'foo.proto' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  field { "
+      "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
+      "    type_name: 'FooMapEntry' "
+      "  } "
+      "  nested_type { "
+      "    name: 'FooMapEntry' "
+      "    options {  map_entry: true } "
+      "    field { "
+      "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
+      "    } "
+      "    field { "
+      "      name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL "
+      "    } "
+      "  } "
+      "} "
+      "message_type { "
+      "  name: 'Bar' "
+      "  extension_range { start: 1 end: 10 }"
+      "} ",
+      file_proto));
+}
+static const char* kMapEntryErrorMessage =
+    "foo.proto: Foo.foo_map: OTHER: map_entry should not be set explicitly. "
+    "Use map<KeyType, ValueType> instead.\n";
+static const char* kMapEntryKeyTypeErrorMessage =
+    "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, "
+    "bytes or message types.\n";
+
+}  // namespace
+
+TEST_F(ValidationErrorTest, MapEntryBase) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  BuildFile(file_proto.DebugString());
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "extension_range { "
+      "  start: 10 end: 20 "
+      "} ",
+      file_proto.mutable_message_type(0)->mutable_nested_type(0));
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtension) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "extension { "
+      "  name: 'foo_ext' extendee: '.Bar' number: 5"
+      "} ",
+      file_proto.mutable_message_type(0)->mutable_nested_type(0));
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryNestedType) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "nested_type { "
+      "  name: 'Bar' "
+      "} ",
+      file_proto.mutable_message_type(0)->mutable_nested_type(0));
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryEnumTypes) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "enum_type { "
+      "  name: 'BarEnum' "
+      "  value { name: 'BAR_BAR' number:0 } "
+      "} ",
+      file_proto.mutable_message_type(0)->mutable_nested_type(0));
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtraField) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "field { "
+      "  name: 'other_field' "
+      "  label: LABEL_OPTIONAL "
+      "  type: TYPE_INT32 "
+      "  number: 3 "
+      "} ",
+      file_proto.mutable_message_type(0)->mutable_nested_type(0));
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryMessageName) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name(
+      "OtherMapEntry");
+  file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name(
+      "OtherMapEntry");
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  file_proto.mutable_message_type(0)->mutable_field(0)->set_label(
+      FieldDescriptorProto::LABEL_OPTIONAL);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  // Move the nested MapEntry message into the top level, which should not pass
+  // the validation.
+  file_proto.mutable_message_type()->AddAllocated(
+      file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast());
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyName) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_name("Key");
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyLabel) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_label(FieldDescriptorProto::LABEL_REQUIRED);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyNumber) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_number(3);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueName) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(1);
+  value->set_name("Value");
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueLabel) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(1);
+  value->set_label(FieldDescriptorProto::LABEL_REQUIRED);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueNumber) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(1);
+  value->set_number(3);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_type(FieldDescriptorProto::TYPE_FLOAT);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_type(FieldDescriptorProto::TYPE_DOUBLE);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->set_type(FieldDescriptorProto::TYPE_BYTES);
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->clear_type();
+  key->set_type_name("BarEnum");
+  EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
+  enum_proto->set_name("BarEnum");
+  EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value();
+  enum_value_proto->set_name("BAR_VALUE0");
+  enum_value_proto->set_number(0);
+  BuildFileWithErrors(file_proto.DebugString(),
+                      "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
+                      "be enum types.\n");
+  // Enum keys are not allowed in proto3 as well.
+  // Get rid of extensions for proto3 to make it proto3 compatible.
+  file_proto.mutable_message_type()->RemoveLast();
+  file_proto.set_syntax("proto3");
+  BuildFileWithErrors(file_proto.DebugString(),
+                      "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
+                      "be enum types.\n");
+}
+
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+      ->mutable_nested_type(0)
+      ->mutable_field(0);
+  key->clear_type();
+  key->set_type_name(".Bar");
+  BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithField) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "field { "
+      "  name: 'FooMapEntry' "
+      "  type: TYPE_INT32 "
+      "  label: LABEL_OPTIONAL "
+      "  number: 100 "
+      "}",
+      file_proto.mutable_message_type(0));
+  BuildFileWithErrors(
+      file_proto.DebugString(),
+      "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+      "\"Foo\".\n"
+      "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
+      "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+      "with an existing field.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "nested_type { "
+      "  name: 'FooMapEntry' "
+      "}",
+      file_proto.mutable_message_type(0));
+  BuildFileWithErrors(
+      file_proto.DebugString(),
+      "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+      "\"Foo\".\n"
+      "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+      "with an existing nested message type.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "enum_type { "
+      "  name: 'FooMapEntry' "
+      "  value { name: 'ENTRY_FOO' number: 0 }"
+      "}",
+      file_proto.mutable_message_type(0));
+  BuildFileWithErrors(
+      file_proto.DebugString(),
+      "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+      "\"Foo\".\n"
+      "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+      "with an existing enum type.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
+  FileDescriptorProto file_proto;
+  FillValidMapEntry(&file_proto);
+  TextFormat::MergeFromString(
+      "oneof_decl { "
+      "  name: 'FooMapEntry' "
+      "}"
+      "field { "
+      "  name: 'int_field' "
+      "  type: TYPE_INT32 "
+      "  label: LABEL_OPTIONAL "
+      "  oneof_index: 0 "
+      "  number: 100 "
+      "} ",
+      file_proto.mutable_message_type(0));
+  BuildFileWithErrors(
+      file_proto.DebugString(),
+      "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+      "\"Foo\".\n"
+      "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
+      "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+      "with an existing oneof type.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type {"
+    "  name: \"Bar\""
+    "  value { name:\"ENUM_A\" number:1 }"
+    "  value { name:\"ENUM_B\" number:2 }"
+    "}"
+    "message_type {"
+    "  name: 'Foo' "
+    "  field { "
+    "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
+    "    type_name: 'FooMapEntry' "
+    "  } "
+    "  nested_type { "
+    "    name: 'FooMapEntry' "
+    "    options {  map_entry: true } "
+    "    field { "
+    "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
+    "    } "
+    "    field { "
+    "      name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
+    "    } "
+    "  } "
+    "}",
+    "foo.proto: Foo.foo_map: "
+    "TYPE: Enum value in map must define 0 as the first value.\n");
+}
+
+TEST_F(ValidationErrorTest, Proto3RequiredFields) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
+      "}",
+      "foo.proto: Foo.foo: OTHER: Required fields are not allowed in "
+      "proto3.\n");
+
+  // applied to nested types as well.
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  nested_type { "
+      "    name : 'Bar' "
+      "    field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
+      "  } "
+      "}",
+      "foo.proto: Foo.Bar.bar: OTHER: Required fields are not allowed in "
+      "proto3.\n");
+
+  // optional and repeated fields are OK.
+  BuildFile(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+      "  field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } "
+      "}");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "          default_value: '1' }"
+      "}",
+      "foo.proto: Foo.foo: OTHER: Explicit default values are not allowed in "
+      "proto3.\n");
+
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  nested_type { "
+      "    name : 'Bar' "
+      "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "            default_value: '1' }"
+      "  } "
+      "}",
+      "foo.proto: Foo.Bar.bar: OTHER: Explicit default values are not allowed "
+      "in proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+      "  extension_range { start:10 end:100 } "
+      "}",
+      "foo.proto: Foo: OTHER: Extension ranges are not allowed in "
+      "proto3.\n");
+
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  nested_type { "
+      "    name : 'Bar' "
+      "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+      "    extension_range { start:10 end:100 } "
+      "  } "
+      "}",
+      "foo.proto: Foo.Bar: OTHER: Extension ranges are not allowed in "
+      "proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  options { message_set_wire_format: true } "
+      "}",
+      "foo.proto: Foo: OTHER: MessageSet is not supported "
+      "in proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3Enum) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "enum_type { "
+      "  name: 'FooEnum' "
+      "  value { name: 'FOO_FOO' number:1 } "
+      "}",
+      "foo.proto: FooEnum: OTHER: The first enum value must be "
+      "zero in proto3.\n");
+
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  enum_type { "
+      "    name: 'FooEnum' "
+      "    value { name: 'FOO_FOO' number:1 } "
+      "  } "
+      "}",
+      "foo.proto: Foo.FooEnum: OTHER: The first enum value must be "
+      "zero in proto3.\n");
+
+  // valid case.
+  BuildFile(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "enum_type { "
+      "  name: 'FooEnum' "
+      "  value { name: 'FOO_FOO' number:0 } "
+      "}");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3Group) {
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "  nested_type { "
+      "    name: 'FooGroup' "
+      "  } "
+      "  field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
+      "          type: TYPE_GROUP type_name:'FooGroup' } "
+      "}",
+      "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
+      "syntax.\n");
+}
+
+
+TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
+  // Define an enum in a proto2 file.
+  BuildFile(
+      "name: 'foo.proto' "
+      "package: 'foo' "
+      "syntax: 'proto2' "
+      "enum_type { "
+      "  name: 'FooEnum' "
+      "  value { name: 'DEFAULT_OPTION' number:0 } "
+      "}");
+
+  // Now try to refer to it. (All tests in the fixture use the same pool, so we
+  // can refer to the enum above in this definition.)
+  BuildFileWithErrors(
+      "name: 'bar.proto' "
+      "dependency: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type { "
+      "  name: 'Foo' "
+      "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM "
+      "            type_name: 'foo.FooEnum' }"
+      "}",
+      "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 "
+      "enum, but is used in \"Foo\" which is a proto3 message type.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3Extension) {
+  // Valid for options.
+  DescriptorPool pool;
+  FileDescriptorProto file_proto;
+  // Add "google/protobuf/descriptor.proto".
+  FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  // Add "foo.proto":
+  //   import "google/protobuf/descriptor.proto";
+  //   extend google.protobuf.FieldOptions {
+  //     optional int32 option1 = 1000;
+  //   }
+  file_proto.Clear();
+  file_proto.set_name("foo.proto");
+  file_proto.set_syntax("proto3");
+  file_proto.add_dependency("google/protobuf/descriptor.proto");
+  AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
+               FieldDescriptorProto::LABEL_OPTIONAL,
+               FieldDescriptorProto::TYPE_INT32);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+  // Copy and change the package of the descriptor.proto
+  BuildFile(
+      "name: 'google.protobuf.proto' "
+      "syntax: 'proto2' "
+      "message_type { "
+      "  name: 'Container' extension_range { start: 1 end: 1000 } "
+      "}");
+  BuildFileWithErrors(
+      "name: 'bar.proto' "
+      "syntax: 'proto3' "
+      "dependency: 'google.protobuf.proto' "
+      "extension { "
+      "  name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 "
+      "  extendee: 'Container' "
+      "}",
+      "bar.proto: bar: OTHER: Extensions in proto3 are only allowed for "
+      "defining options.\n");
+}
+
+// Test that field names that may conflict in JSON is not allowed by protoc.
+TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
+  // The comparison is case-insensitive.
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type {"
+      "  name: 'Foo'"
+      "  field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "  field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "}",
+      "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"Name\" "
+      "conflicts with field \"name\". This is not allowed in proto3.\n");
+  // Underscores are ignored.
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "message_type {"
+      "  name: 'Foo'"
+      "  field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "  field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+      "}",
+      "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"_a__b_\" "
+      "conflicts with field \"ab\". This is not allowed in proto3.\n");
+}
+
+// ===================================================================
+// DescriptorDatabase
+
+static void AddToDatabase(SimpleDescriptorDatabase* database,
+                          const char* file_text) {
+  FileDescriptorProto file_proto;
+  EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+  database->Add(file_proto);
+}
+
+class DatabaseBackedPoolTest : public testing::Test {
+ protected:
+  DatabaseBackedPoolTest() {}
+
+  SimpleDescriptorDatabase database_;
+
+  virtual void SetUp() {
+    AddToDatabase(&database_,
+      "name: 'foo.proto' "
+      "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
+      "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
+      "service { name:'TestService' } ");
+    AddToDatabase(&database_,
+      "name: 'bar.proto' "
+      "dependency: 'foo.proto' "
+      "message_type { name:'Bar' } "
+      "extension { name:'foo_ext' extendee: '.Foo' number:5 "
+      "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+    // Baz has an undeclared dependency on Foo.
+    AddToDatabase(&database_,
+      "name: 'baz.proto' "
+      "message_type { "
+      "  name:'Baz' "
+      "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
+      "}");
+  }
+
+  // We can't inject a file containing errors into a DescriptorPool, so we
+  // need an actual mock DescriptorDatabase to test errors.
+  class ErrorDescriptorDatabase : public DescriptorDatabase {
+   public:
+    ErrorDescriptorDatabase() {}
+    ~ErrorDescriptorDatabase() {}
+
+    // implements DescriptorDatabase ---------------------------------
+    bool FindFileByName(const string& filename,
+                        FileDescriptorProto* output) {
+      // error.proto and error2.proto cyclically import each other.
+      if (filename == "error.proto") {
+        output->Clear();
+        output->set_name("error.proto");
+        output->add_dependency("error2.proto");
+        return true;
+      } else if (filename == "error2.proto") {
+        output->Clear();
+        output->set_name("error2.proto");
+        output->add_dependency("error.proto");
+        return true;
+      } else {
+        return false;
+      }
+    }
+    bool FindFileContainingSymbol(const string& symbol_name,
+                                  FileDescriptorProto* output) {
+      return false;
+    }
+    bool FindFileContainingExtension(const string& containing_type,
+                                     int field_number,
+                                     FileDescriptorProto* output) {
+      return false;
+    }
+  };
+
+  // A DescriptorDatabase that counts how many times each method has been
+  // called and forwards to some other DescriptorDatabase.
+  class CallCountingDatabase : public DescriptorDatabase {
+   public:
+    CallCountingDatabase(DescriptorDatabase* wrapped_db)
+      : wrapped_db_(wrapped_db) {
+      Clear();
+    }
+    ~CallCountingDatabase() {}
+
+    DescriptorDatabase* wrapped_db_;
+
+    int call_count_;
+
+    void Clear() {
+      call_count_ = 0;
+    }
+
+    // implements DescriptorDatabase ---------------------------------
+    bool FindFileByName(const string& filename,
+                        FileDescriptorProto* output) {
+      ++call_count_;
+      return wrapped_db_->FindFileByName(filename, output);
+    }
+    bool FindFileContainingSymbol(const string& symbol_name,
+                                  FileDescriptorProto* output) {
+      ++call_count_;
+      return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
+    }
+    bool FindFileContainingExtension(const string& containing_type,
+                                     int field_number,
+                                     FileDescriptorProto* output) {
+      ++call_count_;
+      return wrapped_db_->FindFileContainingExtension(
+        containing_type, field_number, output);
+    }
+  };
+
+  // A DescriptorDatabase which falsely always returns foo.proto when searching
+  // for any symbol or extension number.  This shouldn't cause the
+  // DescriptorPool to reload foo.proto if it is already loaded.
+  class FalsePositiveDatabase : public DescriptorDatabase {
+   public:
+    FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
+      : wrapped_db_(wrapped_db) {}
+    ~FalsePositiveDatabase() {}
+
+    DescriptorDatabase* wrapped_db_;
+
+    // implements DescriptorDatabase ---------------------------------
+    bool FindFileByName(const string& filename,
+                        FileDescriptorProto* output) {
+      return wrapped_db_->FindFileByName(filename, output);
+    }
+    bool FindFileContainingSymbol(const string& symbol_name,
+                                  FileDescriptorProto* output) {
+      return FindFileByName("foo.proto", output);
+    }
+    bool FindFileContainingExtension(const string& containing_type,
+                                     int field_number,
+                                     FileDescriptorProto* output) {
+      return FindFileByName("foo.proto", output);
+    }
+  };
+};
+
+TEST_F(DatabaseBackedPoolTest, FindFileByName) {
+  DescriptorPool pool(&database_);
+
+  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
+  ASSERT_TRUE(foo != NULL);
+  EXPECT_EQ("foo.proto", foo->name());
+  ASSERT_EQ(1, foo->message_type_count());
+  EXPECT_EQ("Foo", foo->message_type(0)->name());
+
+  EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
+
+  EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
+  DescriptorPool pool(&database_);
+
+  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
+  ASSERT_TRUE(foo != NULL);
+  EXPECT_EQ("foo.proto", foo->name());
+  ASSERT_EQ(1, foo->message_type_count());
+  EXPECT_EQ("Foo", foo->message_type(0)->name());
+
+  const FileDescriptor* bar = pool.FindFileByName("bar.proto");
+  ASSERT_TRUE(bar != NULL);
+  EXPECT_EQ("bar.proto", bar->name());
+  ASSERT_EQ(1, bar->message_type_count());
+  EXPECT_EQ("Bar", bar->message_type(0)->name());
+
+  ASSERT_EQ(1, bar->dependency_count());
+  EXPECT_EQ(foo, bar->dependency(0));
+}
+
+TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
+  DescriptorPool pool(&database_);
+
+  const FileDescriptor* bar = pool.FindFileByName("bar.proto");
+  ASSERT_TRUE(bar != NULL);
+  EXPECT_EQ("bar.proto", bar->name());
+  ASSERT_EQ(1, bar->message_type_count());
+  ASSERT_EQ("Bar", bar->message_type(0)->name());
+
+  const FileDescriptor* foo = pool.FindFileByName("foo.proto");
+  ASSERT_TRUE(foo != NULL);
+  EXPECT_EQ("foo.proto", foo->name());
+  ASSERT_EQ(1, foo->message_type_count());
+  ASSERT_EQ("Foo", foo->message_type(0)->name());
+
+  ASSERT_EQ(1, bar->dependency_count());
+  EXPECT_EQ(foo, bar->dependency(0));
+}
+
+TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
+  DescriptorPool pool(&database_);
+
+  const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
+  ASSERT_TRUE(file != NULL);
+  EXPECT_EQ("foo.proto", file->name());
+  EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
+
+  EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
+  DescriptorPool pool(&database_);
+
+  const Descriptor* type = pool.FindMessageTypeByName("Foo");
+  ASSERT_TRUE(type != NULL);
+  EXPECT_EQ("Foo", type->name());
+  EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
+
+  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
+  DescriptorPool pool(&database_);
+
+  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+  ASSERT_TRUE(foo != NULL);
+
+  const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
+  ASSERT_TRUE(extension != NULL);
+  EXPECT_EQ("foo_ext", extension->name());
+  EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
+
+  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
+  DescriptorPool pool(&database_);
+
+  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+
+  for (int i = 0; i < 2; ++i) {
+    // Repeat the lookup twice, to check that we get consistent
+    // results despite the fallback database lookup mutating the pool.
+    vector<const FieldDescriptor*> extensions;
+    pool.FindAllExtensions(foo, &extensions);
+    ASSERT_EQ(1, extensions.size());
+    EXPECT_EQ(5, extensions[0]->number());
+  }
+}
+
+TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
+  ErrorDescriptorDatabase error_database;
+  DescriptorPool pool(&error_database);
+
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog log;
+    EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
+    errors = log.GetMessages(ERROR);
+  }
+
+  EXPECT_FALSE(errors.empty());
+}
+
+TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
+  ErrorDescriptorDatabase error_database;
+  MockErrorCollector error_collector;
+  DescriptorPool pool(&error_database, &error_collector);
+
+  EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
+  EXPECT_EQ(
+    "error.proto: error.proto: OTHER: File recursively imports itself: "
+      "error.proto -> error2.proto -> error.proto\n"
+    "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
+      "found or had errors.\n"
+    "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
+      "found or had errors.\n",
+    error_collector.text_);
+}
+
+TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
+  // Check that we find and report undeclared dependencies on types that exist
+  // in the descriptor database but that have not not been built yet.
+  MockErrorCollector error_collector;
+  DescriptorPool pool(&database_, &error_collector);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  EXPECT_EQ(
+    "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
+    "which is not imported by \"baz.proto\".  To use it here, please add "
+    "the necessary import.\n",
+    error_collector.text_);
+}
+
+TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
+  // Make sure that all traces of bad types are removed from the pool. This used
+  // to be b/4529436, due to the fact that a symbol resolution failure could
+  // potentially cause another file to be recursively built, which would trigger
+  // a checkpoint _past_ possibly invalid symbols.
+  // Baz is defined in the database, but the file is invalid because it is
+  // missing a necessary import.
+  DescriptorPool pool(&database_);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  // Make sure that searching again for the file or the type fails.
+  EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, UnittestProto) {
+  // Try to load all of unittest.proto from a DescriptorDatabase.  This should
+  // thoroughly test all paths through DescriptorBuilder to insure that there
+  // are no deadlocking problems when pool_->mutex_ is non-NULL.
+  const FileDescriptor* original_file =
+    protobuf_unittest::TestAllTypes::descriptor()->file();
+
+  DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
+  DescriptorPool pool(&database);
+  const FileDescriptor* file_from_database =
+    pool.FindFileByName(original_file->name());
+
+  ASSERT_TRUE(file_from_database != NULL);
+
+  FileDescriptorProto original_file_proto;
+  original_file->CopyTo(&original_file_proto);
+
+  FileDescriptorProto file_from_database_proto;
+  file_from_database->CopyTo(&file_from_database_proto);
+
+  EXPECT_EQ(original_file_proto.DebugString(),
+            file_from_database_proto.DebugString());
+
+  // Also verify that CopyTo() did not omit any information.
+  EXPECT_EQ(original_file->DebugString(),
+            file_from_database->DebugString());
+}
+
+TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
+  // Searching for a child of an existing descriptor should never fall back
+  // to the DescriptorDatabase even if it isn't found, because we know all
+  // children are already loaded.
+  CallCountingDatabase call_counter(&database_);
+  DescriptorPool pool(&call_counter);
+
+  const FileDescriptor* file = pool.FindFileByName("foo.proto");
+  ASSERT_TRUE(file != NULL);
+  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+  ASSERT_TRUE(foo != NULL);
+  const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
+  ASSERT_TRUE(test_enum != NULL);
+  const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
+  ASSERT_TRUE(test_service != NULL);
+
+  EXPECT_NE(0, call_counter.call_count_);
+  call_counter.Clear();
+
+  EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
+  EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
+  EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
+  EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
+  EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
+
+  EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
+  EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
+  EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
+
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
+  EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
+  EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
+  EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
+  EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
+
+  EXPECT_EQ(0, call_counter.call_count_);
+}
+
+TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
+  // If FindFileContainingSymbol() or FindFileContainingExtension() return a
+  // file that is already in the DescriptorPool, it should not attempt to
+  // reload the file.
+  FalsePositiveDatabase false_positive_database(&database_);
+  MockErrorCollector error_collector;
+  DescriptorPool pool(&false_positive_database, &error_collector);
+
+  // First make sure foo.proto is loaded.
+  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+  ASSERT_TRUE(foo != NULL);
+
+  // Try inducing false positives.
+  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
+  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
+
+  // No errors should have been reported.  (If foo.proto was incorrectly
+  // loaded multiple times, errors would have been reported.)
+  EXPECT_EQ("", error_collector.text_);
+}
+
+// DescriptorDatabase that attempts to induce exponentially-bad performance
+// in DescriptorPool. For every positive N, the database contains a file
+// fileN.proto, which defines a message MessageN, which contains fields of
+// type MessageK for all K in [0,N). Message0 is not defined anywhere
+// (file0.proto exists, but is empty), so every other file and message type
+// will fail to build.
+//
+// If the DescriptorPool is not careful to memoize errors, an attempt to
+// build a descriptor for MessageN can require O(2^N) time.
+class ExponentialErrorDatabase : public DescriptorDatabase {
+ public:
+  ExponentialErrorDatabase() {}
+  ~ExponentialErrorDatabase() {}
+
+  // implements DescriptorDatabase ---------------------------------
+  bool FindFileByName(const string& filename,
+                      FileDescriptorProto* output) {
+    int file_num = -1;
+    FullMatch(filename, "file", ".proto", &file_num);
+    if (file_num > -1) {
+      return PopulateFile(file_num, output);
+    } else {
+      return false;
+    }
+  }
+  bool FindFileContainingSymbol(const string& symbol_name,
+                                FileDescriptorProto* output) {
+    int file_num = -1;
+    FullMatch(symbol_name, "Message", "", &file_num);
+    if (file_num > 0) {
+      return PopulateFile(file_num, output);
+    } else {
+      return false;
+    }
+  }
+  bool FindFileContainingExtension(const string& containing_type,
+                                   int field_number,
+                                   FileDescriptorProto* output) {
+    return false;
+  }
+
+ private:
+  void FullMatch(const string& name,
+                 const string& begin_with,
+                 const string& end_with,
+                 int* file_num) {
+    int begin_size = begin_with.size();
+    int end_size = end_with.size();
+    if (name.substr(0, begin_size) != begin_with ||
+        name.substr(name.size()- end_size, end_size) != end_with) {
+      return;
+    }
+    safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size),
+                 file_num);
+  }
+
+  bool PopulateFile(int file_num, FileDescriptorProto* output) {
+    using strings::Substitute;
+    GOOGLE_CHECK_GE(file_num, 0);
+    output->Clear();
+    output->set_name(Substitute("file$0.proto", file_num));
+    // file0.proto doesn't define Message0
+    if (file_num > 0) {
+      DescriptorProto* message = output->add_message_type();
+      message->set_name(Substitute("Message$0", file_num));
+      for (int i = 0; i < file_num; ++i) {
+        output->add_dependency(Substitute("file$0.proto", i));
+        FieldDescriptorProto* field = message->add_field();
+        field->set_name(Substitute("field$0", i));
+        field->set_number(i);
+        field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+        field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
+        field->set_type_name(Substitute("Message$0", i));
+      }
+    }
+    return true;
+  }
+};
+
+TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
+  ExponentialErrorDatabase error_database;
+  DescriptorPool pool(&error_database);
+
+  GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
+
+  EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL);
+}
+
+TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
+  // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
+  // to FindFieldByName()), we should fail fast, without checking the fallback
+  // database.
+  CallCountingDatabase call_counter(&database_);
+  DescriptorPool pool(&call_counter);
+
+  const FileDescriptor* file = pool.FindFileByName("foo.proto");
+  ASSERT_TRUE(file != NULL);
+  const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+  ASSERT_TRUE(foo != NULL);
+  const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
+  ASSERT_TRUE(test_enum != NULL);
+
+  EXPECT_NE(0, call_counter.call_count_);
+  call_counter.Clear();
+
+  EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
+  EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
+
+  EXPECT_EQ(0, call_counter.call_count_);
+}
+
+// ===================================================================
+
+class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  AbortingErrorCollector() {}
+
+  virtual void AddError(
+      const string &filename,
+      const string &element_name,
+      const Message *message,
+      ErrorLocation location,
+      const string &error_message) {
+    GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
+               << element_name << "]: " << error_message;
+  }
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
+};
+
+// A source tree containing only one file.
+class SingletonSourceTree : public compiler::SourceTree {
+ public:
+  SingletonSourceTree(const string& filename, const string& contents)
+      : filename_(filename), contents_(contents) {}
+
+  virtual io::ZeroCopyInputStream* Open(const string& filename) {
+    return filename == filename_ ?
+        new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
+  }
+
+ private:
+  const string filename_;
+  const string contents_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
+};
+
+const char *const kSourceLocationTestInput =
+  "syntax = \"proto2\";\n"
+  "message A {\n"
+  "  optional int32 a = 1;\n"
+  "  message B {\n"
+  "    required double b = 1;\n"
+  "  }\n"
+  "}\n"
+  "enum Indecision {\n"
+  "  YES   = 1;\n"
+  "  NO    = 2;\n"
+  "  MAYBE = 3;\n"
+  "}\n"
+  "service S {\n"
+  "  rpc Method(A) returns (A.B);\n"
+  // Put an empty line here to make the source location range match.
+  "\n"
+  "}\n"
+  "message MessageWithExtensions {\n"
+  "  extensions 1000 to max;\n"
+  "}\n"
+  "extend MessageWithExtensions {\n"
+  "  optional int32 int32_extension = 1001;\n"
+  "}\n"
+  "message C {\n"
+  "  extend MessageWithExtensions {\n"
+  "    optional C message_extension = 1002;\n"
+  "  }\n"
+  "}\n";
+
+class SourceLocationTest : public testing::Test {
+ public:
+  SourceLocationTest()
+      : source_tree_("/test/test.proto", kSourceLocationTestInput),
+        db_(&source_tree_),
+        pool_(&db_, &collector_) {}
+
+  static string PrintSourceLocation(const SourceLocation &loc) {
+    return strings::Substitute("$0:$1-$2:$3",
+                               1 + loc.start_line,
+                               1 + loc.start_column,
+                               1 + loc.end_line,
+                               1 + loc.end_column);
+  }
+
+ private:
+  AbortingErrorCollector collector_;
+  SingletonSourceTree source_tree_;
+  compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+  DescriptorPool pool_;
+};
+
+// TODO(adonovan): implement support for option fields and for
+// subparts of declarations.
+
+TEST_F(SourceLocationTest, GetSourceLocation) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
+  EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
+
+  const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
+  EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
+
+  const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
+  EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
+
+  const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
+  EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
+
+  const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
+  EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
+
+  const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
+  EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
+
+}
+
+TEST_F(SourceLocationTest, ExtensionSourceLocation) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  const FieldDescriptor *int32_extension_desc =
+      file_desc->FindExtensionByName("int32_extension");
+  EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc));
+
+  const Descriptor *c_desc = file_desc->FindMessageTypeByName("C");
+  EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc));
+
+  const FieldDescriptor *message_extension_desc =
+      c_desc->FindExtensionByName("message_extension");
+  EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc));
+}
+
+// Missing SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  FileDescriptorProto proto;
+  file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
+  EXPECT_FALSE(proto.has_source_code_info());
+
+  DescriptorPool bad1_pool(&pool_);
+  const FileDescriptor* bad1_file_desc =
+      GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
+  const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
+  EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
+}
+
+// Corrupt SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  FileDescriptorProto proto;
+  file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
+  EXPECT_FALSE(proto.has_source_code_info());
+  SourceCodeInfo_Location *loc_msg =
+      proto.mutable_source_code_info()->add_location();
+  loc_msg->add_path(1);
+  loc_msg->add_path(2);
+  loc_msg->add_path(3);
+  loc_msg->add_span(4);
+  loc_msg->add_span(5);
+  loc_msg->add_span(6);
+
+  DescriptorPool bad2_pool(&pool_);
+  const FileDescriptor* bad2_file_desc =
+      GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
+  const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
+  EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
+}
+
+// ===================================================================
+
+const char* const kCopySourceCodeInfoToTestInput =
+  "syntax = \"proto2\";\n"
+  "message Foo {}\n";
+
+// Required since source code information is not preserved by
+// FileDescriptorTest.
+class CopySourceCodeInfoToTest : public testing::Test {
+ public:
+  CopySourceCodeInfoToTest()
+      : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
+        db_(&source_tree_),
+        pool_(&db_, &collector_) {}
+
+ private:
+  AbortingErrorCollector collector_;
+  SingletonSourceTree source_tree_;
+  compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+  DescriptorPool pool_;
+};
+
+TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
+  const FileDescriptor* file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+  FileDescriptorProto file_desc_proto;
+  ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+  file_desc->CopyTo(&file_desc_proto);
+  EXPECT_FALSE(file_desc_proto.has_source_code_info());
+}
+
+TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
+  const FileDescriptor* file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+  FileDescriptorProto file_desc_proto;
+  ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+  file_desc->CopySourceCodeInfoTo(&file_desc_proto);
+  const SourceCodeInfo& info = file_desc_proto.source_code_info();
+  ASSERT_EQ(4, info.location_size());
+  // Get the Foo message location
+  const SourceCodeInfo_Location& foo_location = info.location(2);
+  ASSERT_EQ(2, foo_location.path_size());
+  EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
+  EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
+  ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
+  EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
+  EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
+  EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
+}
+
+// ===================================================================
+
+
+}  // namespace descriptor_unittest
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/drop_unknown_fields_test.cc b/src/third_party/protobuf-3/src/google/protobuf/drop_unknown_fields_test.cc
new file mode 100644
index 0000000..6f16dc5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/drop_unknown_fields_test.cc
@@ -0,0 +1,88 @@
+// 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.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/unittest_drop_unknown_fields.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using unittest_drop_unknown_fields::Foo;
+using unittest_drop_unknown_fields::FooWithExtraFields;
+
+namespace protobuf {
+
+TEST(DropUnknownFieldsTest, GeneratedMessage) {
+  FooWithExtraFields foo_with_extra_fields;
+  foo_with_extra_fields.set_int32_value(1);
+  foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+  foo_with_extra_fields.set_extra_int32_value(2);
+
+  Foo foo;
+  ASSERT_TRUE(foo.ParseFromString(foo_with_extra_fields.SerializeAsString()));
+  EXPECT_EQ(1, foo.int32_value());
+  EXPECT_EQ(static_cast<int>(FooWithExtraFields::QUX),
+            static_cast<int>(foo.enum_value()));
+  // We don't generate unknown field accessors but the UnknownFieldSet is
+  // still exposed through reflection API.
+  EXPECT_TRUE(foo.GetReflection()->GetUnknownFields(foo).empty());
+
+  ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo.SerializeAsString()));
+  EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+  EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+  // The "extra_int32_value" field should be lost.
+  EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
+}
+
+TEST(DropUnknownFieldsTest, DynamicMessage) {
+  FooWithExtraFields foo_with_extra_fields;
+  foo_with_extra_fields.set_int32_value(1);
+  foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+  foo_with_extra_fields.set_extra_int32_value(2);
+
+  google::protobuf::DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> foo(
+      factory.GetPrototype(Foo::descriptor())->New());
+  ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
+  EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty());
+
+  ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo->SerializeAsString()));
+  EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+  EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+  // The "extra_int32_value" field should be lost.
+  EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/duration.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/duration.pb.cc
new file mode 100644
index 0000000..e363934
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/duration.pb.cc
@@ -0,0 +1,425 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/duration.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Duration_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Duration_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/duration.proto");
+  GOOGLE_CHECK(file != NULL);
+  Duration_descriptor_ = file->message_type(0);
+  static const int Duration_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, seconds_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, nanos_),
+  };
+  Duration_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Duration_descriptor_,
+      Duration::default_instance_,
+      Duration_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Duration),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Duration_descriptor_, &Duration::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto() {
+  delete Duration::default_instance_;
+  delete Duration_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\036google/protobuf/duration.proto\022\017google"
+    ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
+    "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
+    "rationProtoP\001Z*github.com/golang/protobu"
+    "f/ptypes/duration\240\001\001\242\002\003GPB\252\002\036Google.Prot"
+    "obuf.WellKnownTypesb\006proto3", 227);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/duration.proto", &protobuf_RegisterTypes);
+  Duration::default_instance_ = new Duration();
+  Duration::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fduration_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Duration::kSecondsFieldNumber;
+const int Duration::kNanosFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Duration::Duration()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Duration)
+}
+
+void Duration::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Duration::Duration(const Duration& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
+}
+
+void Duration::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  seconds_ = GOOGLE_LONGLONG(0);
+  nanos_ = 0;
+}
+
+Duration::~Duration() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Duration)
+  SharedDtor();
+}
+
+void Duration::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void Duration::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Duration::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Duration_descriptor_;
+}
+
+const Duration& Duration::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+  return *default_instance_;
+}
+
+Duration* Duration::default_instance_ = NULL;
+
+Duration* Duration::New(::google::protobuf::Arena* arena) const {
+  Duration* n = new Duration;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Duration::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(Duration, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Duration*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(seconds_, nanos_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+}
+
+bool Duration::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Duration)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int64 seconds = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &seconds_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_nanos;
+        break;
+      }
+
+      // optional int32 nanos = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_nanos:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &nanos_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Duration)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Duration)
+  return false;
+#undef DO_
+}
+
+void Duration::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Duration)
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output);
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Duration)
+}
+
+::google::protobuf::uint8* Duration::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration)
+  return target;
+}
+
+int Duration::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
+  int total_size = 0;
+
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->seconds());
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->nanos());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Duration::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Duration* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration)
+    MergeFrom(*source);
+  }
+}
+
+void Duration::MergeFrom(const Duration& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.seconds() != 0) {
+    set_seconds(from.seconds());
+  }
+  if (from.nanos() != 0) {
+    set_nanos(from.nanos());
+  }
+}
+
+void Duration::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Duration::CopyFrom(const Duration& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Duration)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Duration::IsInitialized() const {
+
+  return true;
+}
+
+void Duration::Swap(Duration* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Duration::InternalSwap(Duration* other) {
+  std::swap(seconds_, other->seconds_);
+  std::swap(nanos_, other->nanos_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Duration::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Duration_descriptor_;
+  metadata.reflection = Duration_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Duration
+
+// optional int64 seconds = 1;
+void Duration::clear_seconds() {
+  seconds_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Duration::seconds() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
+  return seconds_;
+}
+ void Duration::set_seconds(::google::protobuf::int64 value) {
+  
+  seconds_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
+}
+
+// optional int32 nanos = 2;
+void Duration::clear_nanos() {
+  nanos_ = 0;
+}
+ ::google::protobuf::int32 Duration::nanos() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
+  return nanos_;
+}
+ void Duration::set_nanos(::google::protobuf::int32 value) {
+  
+  nanos_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/duration.pb.h b/src/third_party/protobuf-3/src/google/protobuf/duration.pb.h
new file mode 100644
index 0000000..215a52c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/duration.pb.h
@@ -0,0 +1,172 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto();
+
+class Duration;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message {
+ public:
+  Duration();
+  virtual ~Duration();
+
+  Duration(const Duration& from);
+
+  inline Duration& operator=(const Duration& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Duration& default_instance();
+
+  void Swap(Duration* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Duration* New() const { return New(NULL); }
+
+  Duration* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Duration& from);
+  void MergeFrom(const Duration& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Duration* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int64 seconds = 1;
+  void clear_seconds();
+  static const int kSecondsFieldNumber = 1;
+  ::google::protobuf::int64 seconds() const;
+  void set_seconds(::google::protobuf::int64 value);
+
+  // optional int32 nanos = 2;
+  void clear_nanos();
+  static const int kNanosFieldNumber = 2;
+  ::google::protobuf::int32 nanos() const;
+  void set_nanos(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Duration)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::int64 seconds_;
+  ::google::protobuf::int32 nanos_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto();
+
+  void InitAsDefaultInstance();
+  static Duration* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Duration
+
+// optional int64 seconds = 1;
+inline void Duration::clear_seconds() {
+  seconds_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Duration::seconds() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
+  return seconds_;
+}
+inline void Duration::set_seconds(::google::protobuf::int64 value) {
+  
+  seconds_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
+}
+
+// optional int32 nanos = 2;
+inline void Duration::clear_nanos() {
+  nanos_ = 0;
+}
+inline ::google::protobuf::int32 Duration::nanos() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
+  return nanos_;
+}
+inline void Duration::set_nanos(::google::protobuf::int32 value) {
+  
+  nanos_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/duration.proto b/src/third_party/protobuf-3/src/google/protobuf/duration.proto
new file mode 100644
index 0000000..96c1796
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/duration.proto
@@ -0,0 +1,98 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/duration";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DurationProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+//     Timestamp start = ...;
+//     Timestamp end = ...;
+//     Duration duration = ...;
+//
+//     duration.seconds = end.seconds - start.seconds;
+//     duration.nanos = end.nanos - start.nanos;
+//
+//     if (duration.seconds < 0 && duration.nanos > 0) {
+//       duration.seconds += 1;
+//       duration.nanos -= 1000000000;
+//     } else if (durations.seconds > 0 && duration.nanos < 0) {
+//       duration.seconds -= 1;
+//       duration.nanos += 1000000000;
+//     }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+//     Timestamp start = ...;
+//     Duration duration = ...;
+//     Timestamp end = ...;
+//
+//     end.seconds = start.seconds + duration.seconds;
+//     end.nanos = start.nanos + duration.nanos;
+//
+//     if (end.nanos < 0) {
+//       end.seconds -= 1;
+//       end.nanos += 1000000000;
+//     } else if (end.nanos >= 1000000000) {
+//       end.seconds += 1;
+//       end.nanos -= 1000000000;
+//     }
+//
+//
+message Duration {
+
+  // Signed seconds of the span of time. Must be from -315,576,000,000
+  // to +315,576,000,000 inclusive.
+  int64 seconds = 1;
+
+  // Signed fractions of a second at nanosecond resolution of the span
+  // of time. Durations less than one second are represented with a 0
+  // `seconds` field and a positive or negative `nanos` field. For durations
+  // of one second or more, a non-zero value for the `nanos` field must be
+  // of the same sign as the `seconds` field. Must be from -999,999,999
+  // to +999,999,999 inclusive.
+  int32 nanos = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.cc b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.cc
new file mode 100644
index 0000000..9e83bd2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.cc
@@ -0,0 +1,874 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// DynamicMessage is implemented by constructing a data structure which
+// has roughly the same memory layout as a generated message would have.
+// Then, we use GeneratedMessageReflection to implement our reflection
+// interface.  All the other operations we need to implement (e.g.
+// parsing, copying, etc.) are already implemented in terms of
+// Reflection, so the rest is easy.
+//
+// The up side of this strategy is that it's very efficient.  We don't
+// need to use hash_maps or generic representations of fields.  The
+// down side is that this is a low-level memory management hack which
+// can be tricky to get right.
+//
+// As mentioned in the header, we only expose a DynamicMessageFactory
+// publicly, not the DynamicMessage class itself.  This is because
+// GenericMessageReflection wants to have a pointer to a "default"
+// copy of the class, with all fields initialized to their default
+// values.  We only want to construct one of these per message type,
+// so DynamicMessageFactory stores a cache of default messages for
+// each type it sees (each unique Descriptor pointer).  The code
+// refers to the "default" copy of the class as the "prototype".
+//
+// Note on memory allocation:  This module often calls "operator new()"
+// to allocate untyped memory, rather than calling something like
+// "new uint8[]".  This is because "operator new()" means "Give me some
+// space which I can use as I please." while "new uint8[]" means "Give
+// me an array of 8-bit integers.".  In practice, the later may return
+// a pointer that is not aligned correctly for general use.  I believe
+// Item 8 of "More Effective C++" discusses this in more detail, though
+// I don't have the book on me right now so I'm not sure.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/map_field.h>
+
+namespace google {
+namespace protobuf {
+
+using internal::WireFormat;
+using internal::ExtensionSet;
+using internal::GeneratedMessageReflection;
+using internal::MapField;
+using internal::DynamicMapField;
+
+
+using internal::ArenaStringPtr;
+
+// ===================================================================
+// Some helper tables and functions...
+
+namespace {
+
+bool IsMapFieldInApi(const FieldDescriptor* field) {
+  return field->is_map();
+}
+
+// Compute the byte size of the in-memory representation of the field.
+int FieldSpaceUsed(const FieldDescriptor* field) {
+  typedef FieldDescriptor FD;  // avoid line wrapping
+  if (field->label() == FD::LABEL_REPEATED) {
+    switch (field->cpp_type()) {
+      case FD::CPPTYPE_INT32  : return sizeof(RepeatedField<int32   >);
+      case FD::CPPTYPE_INT64  : return sizeof(RepeatedField<int64   >);
+      case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField<uint32  >);
+      case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField<uint64  >);
+      case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField<double  >);
+      case FD::CPPTYPE_FLOAT  : return sizeof(RepeatedField<float   >);
+      case FD::CPPTYPE_BOOL   : return sizeof(RepeatedField<bool    >);
+      case FD::CPPTYPE_ENUM   : return sizeof(RepeatedField<int     >);
+      case FD::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          return sizeof(DynamicMapField);
+        } else {
+          return sizeof(RepeatedPtrField<Message>);
+        }
+
+      case FD::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            return sizeof(RepeatedPtrField<string>);
+        }
+        break;
+    }
+  } else {
+    switch (field->cpp_type()) {
+      case FD::CPPTYPE_INT32  : return sizeof(int32   );
+      case FD::CPPTYPE_INT64  : return sizeof(int64   );
+      case FD::CPPTYPE_UINT32 : return sizeof(uint32  );
+      case FD::CPPTYPE_UINT64 : return sizeof(uint64  );
+      case FD::CPPTYPE_DOUBLE : return sizeof(double  );
+      case FD::CPPTYPE_FLOAT  : return sizeof(float   );
+      case FD::CPPTYPE_BOOL   : return sizeof(bool    );
+      case FD::CPPTYPE_ENUM   : return sizeof(int     );
+
+      case FD::CPPTYPE_MESSAGE:
+        return sizeof(Message*);
+
+      case FD::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            return sizeof(ArenaStringPtr);
+        }
+        break;
+    }
+  }
+
+  GOOGLE_LOG(DFATAL) << "Can't get here.";
+  return 0;
+}
+
+// Compute the byte size of in-memory representation of the oneof fields
+// in default oneof instance.
+int OneofFieldSpaceUsed(const FieldDescriptor* field) {
+  typedef FieldDescriptor FD;  // avoid line wrapping
+  switch (field->cpp_type()) {
+    case FD::CPPTYPE_INT32  : return sizeof(int32   );
+    case FD::CPPTYPE_INT64  : return sizeof(int64   );
+    case FD::CPPTYPE_UINT32 : return sizeof(uint32  );
+    case FD::CPPTYPE_UINT64 : return sizeof(uint64  );
+    case FD::CPPTYPE_DOUBLE : return sizeof(double  );
+    case FD::CPPTYPE_FLOAT  : return sizeof(float   );
+    case FD::CPPTYPE_BOOL   : return sizeof(bool    );
+    case FD::CPPTYPE_ENUM   : return sizeof(int     );
+
+    case FD::CPPTYPE_MESSAGE:
+      return sizeof(Message*);
+
+    case FD::CPPTYPE_STRING:
+      switch (field->options().ctype()) {
+        default:
+        case FieldOptions::STRING:
+          return sizeof(ArenaStringPtr);
+      }
+      break;
+  }
+
+  GOOGLE_LOG(DFATAL) << "Can't get here.";
+  return 0;
+}
+
+inline int DivideRoundingUp(int i, int j) {
+  return (i + (j - 1)) / j;
+}
+
+static const int kSafeAlignment = sizeof(uint64);
+static const int kMaxOneofUnionSize = sizeof(uint64);
+
+inline int AlignTo(int offset, int alignment) {
+  return DivideRoundingUp(offset, alignment) * alignment;
+}
+
+// Rounds the given byte offset up to the next offset aligned such that any
+// type may be stored at it.
+inline int AlignOffset(int offset) {
+  return AlignTo(offset, kSafeAlignment);
+}
+
+#define bitsizeof(T) (sizeof(T) * 8)
+
+}  // namespace
+
+// ===================================================================
+
+class DynamicMessage : public Message {
+ public:
+  struct TypeInfo {
+    int size;
+    int has_bits_offset;
+    int oneof_case_offset;
+    int unknown_fields_offset;
+    int extensions_offset;
+    int is_default_instance_offset;
+
+    // Not owned by the TypeInfo.
+    DynamicMessageFactory* factory;  // The factory that created this object.
+    const DescriptorPool* pool;      // The factory's DescriptorPool.
+    const Descriptor* type;          // Type of this DynamicMessage.
+
+    // Warning:  The order in which the following pointers are defined is
+    //   important (the prototype must be deleted *before* the offsets).
+    google::protobuf::scoped_array<int> offsets;
+    google::protobuf::scoped_ptr<const GeneratedMessageReflection> reflection;
+    // Don't use a scoped_ptr to hold the prototype: the destructor for
+    // DynamicMessage needs to know whether it is the prototype, and does so by
+    // looking back at this field. This would assume details about the
+    // implementation of scoped_ptr.
+    const DynamicMessage* prototype;
+    void* default_oneof_instance;
+
+    TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {}
+
+    ~TypeInfo() {
+      delete prototype;
+      operator delete(default_oneof_instance);
+    }
+  };
+
+  DynamicMessage(const TypeInfo* type_info);
+  ~DynamicMessage();
+
+  // Called on the prototype after construction to initialize message fields.
+  void CrossLinkPrototypes();
+
+  // implements Message ----------------------------------------------
+
+  Message* New() const;
+  Message* New(::google::protobuf::Arena* arena) const;
+  ::google::protobuf::Arena* GetArena() const { return NULL; };
+
+  int GetCachedSize() const;
+  void SetCachedSize(int size) const;
+
+  Metadata GetMetadata() const;
+
+  // We actually allocate more memory than sizeof(*this) when this
+  // class's memory is allocated via the global operator new. Thus, we need to
+  // manually call the global operator delete. Calling the destructor is taken
+  // care of for us. This makes DynamicMessage compatible with -fsized-delete.
+  // It doesn't work for MSVC though.
+#ifndef _MSC_VER
+  static void operator delete(void* ptr) {
+    ::operator delete(ptr);
+  }
+#endif  // !_MSC_VER
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
+  DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
+  void SharedCtor();
+
+  inline bool is_prototype() const {
+    return type_info_->prototype == this ||
+           // If type_info_->prototype is NULL, then we must be constructing
+           // the prototype now, which means we must be the prototype.
+           type_info_->prototype == NULL;
+  }
+
+  inline void* OffsetToPointer(int offset) {
+    return reinterpret_cast<uint8*>(this) + offset;
+  }
+  inline const void* OffsetToPointer(int offset) const {
+    return reinterpret_cast<const uint8*>(this) + offset;
+  }
+
+  const TypeInfo* type_info_;
+  // TODO(kenton):  Make this an atomic<int> when C++ supports it.
+  mutable int cached_byte_size_;
+};
+
+DynamicMessage::DynamicMessage(const TypeInfo* type_info)
+  : type_info_(type_info),
+    cached_byte_size_(0) {
+  SharedCtor();
+}
+
+DynamicMessage::DynamicMessage(const TypeInfo* type_info,
+                               ::google::protobuf::Arena* arena)
+  : type_info_(type_info),
+    cached_byte_size_(0) {
+  SharedCtor();
+}
+
+void DynamicMessage::SharedCtor() {
+  // We need to call constructors for various fields manually and set
+  // default values where appropriate.  We use placement new to call
+  // constructors.  If you haven't heard of placement new, I suggest Googling
+  // it now.  We use placement new even for primitive types that don't have
+  // constructors for consistency.  (In theory, placement new should be used
+  // any time you are trying to convert untyped memory to typed memory, though
+  // in practice that's not strictly necessary for types that don't have a
+  // constructor.)
+
+  const Descriptor* descriptor = type_info_->type;
+
+  // Initialize oneof cases.
+  for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) {
+    new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i))
+        uint32(0);
+  }
+
+  if (type_info_->is_default_instance_offset != -1) {
+    *reinterpret_cast<bool*>(
+        OffsetToPointer(type_info_->is_default_instance_offset)) = false;
+  }
+
+  new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
+
+  if (type_info_->extensions_offset != -1) {
+    new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet;
+  }
+
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const FieldDescriptor* field = descriptor->field(i);
+    void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
+    if (field->containing_oneof()) {
+      continue;
+    }
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE)                                           \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                               \
+        if (!field->is_repeated()) {                                         \
+          new(field_ptr) TYPE(field->default_value_##TYPE());                \
+        } else {                                                             \
+          new(field_ptr) RepeatedField<TYPE>();                              \
+        }                                                                    \
+        break;
+
+      HANDLE_TYPE(INT32 , int32 );
+      HANDLE_TYPE(INT64 , int64 );
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE(FLOAT , float );
+      HANDLE_TYPE(BOOL  , bool  );
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_ENUM:
+        if (!field->is_repeated()) {
+          new(field_ptr) int(field->default_value_enum()->number());
+        } else {
+          new(field_ptr) RepeatedField<int>();
+        }
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            if (!field->is_repeated()) {
+              const string* default_value;
+              if (is_prototype()) {
+                default_value = &field->default_value_string();
+              } else {
+                default_value =
+                  &(reinterpret_cast<const ArenaStringPtr*>(
+                    type_info_->prototype->OffsetToPointer(
+                      type_info_->offsets[i]))->Get(NULL));
+              }
+              ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr();
+              asp->UnsafeSetDefault(default_value);
+            } else {
+              new(field_ptr) RepeatedPtrField<string>();
+            }
+            break;
+        }
+        break;
+
+      case FieldDescriptor::CPPTYPE_MESSAGE: {
+        if (!field->is_repeated()) {
+          new(field_ptr) Message*(NULL);
+        } else {
+          if (IsMapFieldInApi(field)) {
+            new (field_ptr) DynamicMapField(
+                type_info_->factory->GetPrototypeNoLock(field->message_type()));
+          } else {
+            new (field_ptr) RepeatedPtrField<Message>();
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+DynamicMessage::~DynamicMessage() {
+  const Descriptor* descriptor = type_info_->type;
+
+  reinterpret_cast<UnknownFieldSet*>(
+    OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet();
+
+  if (type_info_->extensions_offset != -1) {
+    reinterpret_cast<ExtensionSet*>(
+      OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet();
+  }
+
+  // We need to manually run the destructors for repeated fields and strings,
+  // just as we ran their constructors in the DynamicMessage constructor.
+  // We also need to manually delete oneof fields if it is set and is string
+  // or message.
+  // Additionally, if any singular embedded messages have been allocated, we
+  // need to delete them, UNLESS we are the prototype message of this type,
+  // in which case any embedded messages are other prototypes and shouldn't
+  // be touched.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (field->containing_oneof()) {
+      void* field_ptr = OffsetToPointer(
+          type_info_->oneof_case_offset
+          + sizeof(uint32) * field->containing_oneof()->index());
+      if (*(reinterpret_cast<const uint32*>(field_ptr)) ==
+          field->number()) {
+        field_ptr = OffsetToPointer(type_info_->offsets[
+            descriptor->field_count() + field->containing_oneof()->index()]);
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+          switch (field->options().ctype()) {
+            default:
+            case FieldOptions::STRING: {
+              const ::std::string* default_value =
+                  &(reinterpret_cast<const ArenaStringPtr*>(
+                      reinterpret_cast<uint8*>(
+                          type_info_->default_oneof_instance)
+                      + type_info_->offsets[i])
+                    ->Get(NULL));
+              reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+                  default_value, NULL);
+              break;
+            }
+          }
+        } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+            delete *reinterpret_cast<Message**>(field_ptr);
+        }
+      }
+      continue;
+    }
+    void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
+
+    if (field->is_repeated()) {
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+        case FieldDescriptor::CPPTYPE_##UPPERCASE :                           \
+          reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr)              \
+              ->~RepeatedField<LOWERCASE>();                                  \
+          break
+
+        HANDLE_TYPE( INT32,  int32);
+        HANDLE_TYPE( INT64,  int64);
+        HANDLE_TYPE(UINT32, uint32);
+        HANDLE_TYPE(UINT64, uint64);
+        HANDLE_TYPE(DOUBLE, double);
+        HANDLE_TYPE( FLOAT,  float);
+        HANDLE_TYPE(  BOOL,   bool);
+        HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_STRING:
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING:
+              reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
+                  ->~RepeatedPtrField<string>();
+              break;
+          }
+          break;
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          if (IsMapFieldInApi(field)) {
+            reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
+          } else {
+            reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
+                ->~RepeatedPtrField<Message>();
+          }
+          break;
+      }
+
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      switch (field->options().ctype()) {
+        default:  // TODO(kenton):  Support other string reps.
+        case FieldOptions::STRING: {
+          const ::std::string* default_value =
+              &(reinterpret_cast<const ArenaStringPtr*>(
+                  type_info_->prototype->OffsetToPointer(
+                      type_info_->offsets[i]))->Get(NULL));
+          reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+              default_value, NULL);
+          break;
+        }
+      }
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (!is_prototype()) {
+        Message* message = *reinterpret_cast<Message**>(field_ptr);
+        if (message != NULL) {
+          delete message;
+        }
+      }
+    }
+  }
+}
+
+void DynamicMessage::CrossLinkPrototypes() {
+  // This should only be called on the prototype message.
+  GOOGLE_CHECK(is_prototype());
+
+  DynamicMessageFactory* factory = type_info_->factory;
+  const Descriptor* descriptor = type_info_->type;
+
+  // Cross-link default messages.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const FieldDescriptor* field = descriptor->field(i);
+    void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
+    if (field->containing_oneof()) {
+      field_ptr = reinterpret_cast<uint8*>(
+          type_info_->default_oneof_instance) + type_info_->offsets[i];
+    }
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->is_repeated()) {
+      // For fields with message types, we need to cross-link with the
+      // prototype for the field's type.
+      // For singular fields, the field is just a pointer which should
+      // point to the prototype.
+      *reinterpret_cast<const Message**>(field_ptr) =
+        factory->GetPrototypeNoLock(field->message_type());
+    }
+  }
+
+  // Set as the default instance -- this affects field-presence semantics for
+  // proto3.
+  if (type_info_->is_default_instance_offset != -1) {
+    void* is_default_instance_ptr =
+        OffsetToPointer(type_info_->is_default_instance_offset);
+    *reinterpret_cast<bool*>(is_default_instance_ptr) = true;
+  }
+}
+
+Message* DynamicMessage::New() const {
+  void* new_base = operator new(type_info_->size);
+  memset(new_base, 0, type_info_->size);
+  return new(new_base) DynamicMessage(type_info_);
+}
+
+Message* DynamicMessage::New(::google::protobuf::Arena* arena) const {
+  if (arena != NULL) {
+    Message* message = New();
+    arena->Own(message);
+    return message;
+  } else {
+    return New();
+  }
+}
+
+int DynamicMessage::GetCachedSize() const {
+  return cached_byte_size_;
+}
+
+void DynamicMessage::SetCachedSize(int size) const {
+  // This is theoretically not thread-compatible, but in practice it works
+  // because if multiple threads write this simultaneously, they will be
+  // writing the exact same value.
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  cached_byte_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+
+Metadata DynamicMessage::GetMetadata() const {
+  Metadata metadata;
+  metadata.descriptor = type_info_->type;
+  metadata.reflection = type_info_->reflection.get();
+  return metadata;
+}
+
+// ===================================================================
+
+struct DynamicMessageFactory::PrototypeMap {
+  typedef hash_map<const Descriptor*, const DynamicMessage::TypeInfo*> Map;
+  Map map_;
+};
+
+DynamicMessageFactory::DynamicMessageFactory()
+  : pool_(NULL), delegate_to_generated_factory_(false),
+    prototypes_(new PrototypeMap) {
+}
+
+DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
+  : pool_(pool), delegate_to_generated_factory_(false),
+    prototypes_(new PrototypeMap) {
+}
+
+DynamicMessageFactory::~DynamicMessageFactory() {
+  for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
+       iter != prototypes_->map_.end(); ++iter) {
+    DeleteDefaultOneofInstance(iter->second->type,
+                               iter->second->offsets.get(),
+                               iter->second->default_oneof_instance);
+    delete iter->second;
+  }
+}
+
+const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
+  MutexLock lock(&prototypes_mutex_);
+  return GetPrototypeNoLock(type);
+}
+
+const Message* DynamicMessageFactory::GetPrototypeNoLock(
+    const Descriptor* type) {
+  if (delegate_to_generated_factory_ &&
+      type->file()->pool() == DescriptorPool::generated_pool()) {
+    return MessageFactory::generated_factory()->GetPrototype(type);
+  }
+
+  const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
+  if (*target != NULL) {
+    // Already exists.
+    return (*target)->prototype;
+  }
+
+  DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
+  *target = type_info;
+
+  type_info->type = type;
+  type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
+  type_info->factory = this;
+
+  // We need to construct all the structures passed to
+  // GeneratedMessageReflection's constructor.  This includes:
+  // - A block of memory that contains space for all the message's fields.
+  // - An array of integers indicating the byte offset of each field within
+  //   this block.
+  // - A big bitfield containing a bit for each field indicating whether
+  //   or not that field is set.
+
+  // Compute size and offsets.
+  int* offsets = new int[type->field_count() + type->oneof_decl_count()];
+  type_info->offsets.reset(offsets);
+
+  // Decide all field offsets by packing in order.
+  // We place the DynamicMessage object itself at the beginning of the allocated
+  // space.
+  int size = sizeof(DynamicMessage);
+  size = AlignOffset(size);
+
+  // Next the has_bits, which is an array of uint32s.
+  if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    type_info->has_bits_offset = -1;
+  } else {
+    type_info->has_bits_offset = size;
+    int has_bits_array_size =
+      DivideRoundingUp(type->field_count(), bitsizeof(uint32));
+    size += has_bits_array_size * sizeof(uint32);
+    size = AlignOffset(size);
+  }
+
+  // The is_default_instance member, if any.
+  if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    type_info->is_default_instance_offset = size;
+    size += sizeof(bool);
+    size = AlignOffset(size);
+  } else {
+    type_info->is_default_instance_offset = -1;
+  }
+
+  // The oneof_case, if any. It is an array of uint32s.
+  if (type->oneof_decl_count() > 0) {
+    type_info->oneof_case_offset = size;
+    size += type->oneof_decl_count() * sizeof(uint32);
+    size = AlignOffset(size);
+  }
+
+  // The ExtensionSet, if any.
+  if (type->extension_range_count() > 0) {
+    type_info->extensions_offset = size;
+    size += sizeof(ExtensionSet);
+    size = AlignOffset(size);
+  } else {
+    // No extensions.
+    type_info->extensions_offset = -1;
+  }
+
+  // All the fields.
+  for (int i = 0; i < type->field_count(); i++) {
+    // Make sure field is aligned to avoid bus errors.
+    // Oneof fields do not use any space.
+    if (!type->field(i)->containing_oneof()) {
+      int field_size = FieldSpaceUsed(type->field(i));
+      size = AlignTo(size, std::min(kSafeAlignment, field_size));
+      offsets[i] = size;
+      size += field_size;
+    }
+  }
+
+  // The oneofs.
+  for (int i = 0; i < type->oneof_decl_count(); i++) {
+    size = AlignTo(size, kSafeAlignment);
+    offsets[type->field_count() + i] = size;
+    size += kMaxOneofUnionSize;
+  }
+
+  // Add the UnknownFieldSet to the end.
+  size = AlignOffset(size);
+  type_info->unknown_fields_offset = size;
+  size += sizeof(UnknownFieldSet);
+
+  // Align the final size to make sure no clever allocators think that
+  // alignment is not necessary.
+  size = AlignOffset(size);
+  type_info->size = size;
+
+  // Allocate the prototype.
+  void* base = operator new(size);
+  memset(base, 0, size);
+  // The prototype in type_info has to be set before creating the prototype
+  // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
+  // creating prototype for Foo, prototype of the map entry will also be
+  // created, which needs the address of the prototype of Foo (the value in
+  // map). To break the cyclic dependency, we have to assgin the address of
+  // prototype into type_info first.
+  type_info->prototype = static_cast<DynamicMessage*>(base);
+  DynamicMessage* prototype = new(base) DynamicMessage(type_info);
+
+  // Construct the reflection object.
+  if (type->oneof_decl_count() > 0) {
+    // Compute the size of default oneof instance and offsets of default
+    // oneof fields.
+    int oneof_size = 0;
+    for (int i = 0; i < type->oneof_decl_count(); i++) {
+      for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
+        const FieldDescriptor* field = type->oneof_decl(i)->field(j);
+        int field_size = OneofFieldSpaceUsed(field);
+        oneof_size = AlignTo(oneof_size, std::min(kSafeAlignment, field_size));
+        offsets[field->index()] = oneof_size;
+        oneof_size += field_size;
+      }
+    }
+    // Construct default oneof instance.
+    type_info->default_oneof_instance = ::operator new(oneof_size);
+    ConstructDefaultOneofInstance(type_info->type,
+                                  type_info->offsets.get(),
+                                  type_info->default_oneof_instance);
+    type_info->reflection.reset(
+        new GeneratedMessageReflection(
+            type_info->type,
+            type_info->prototype,
+            type_info->offsets.get(),
+            type_info->has_bits_offset,
+            type_info->unknown_fields_offset,
+            type_info->extensions_offset,
+            type_info->default_oneof_instance,
+            type_info->oneof_case_offset,
+            type_info->pool,
+            this,
+            type_info->size,
+            -1 /* arena_offset */,
+            type_info->is_default_instance_offset));
+  } else {
+    type_info->reflection.reset(
+        new GeneratedMessageReflection(
+            type_info->type,
+            type_info->prototype,
+            type_info->offsets.get(),
+            type_info->has_bits_offset,
+            type_info->unknown_fields_offset,
+            type_info->extensions_offset,
+            type_info->pool,
+            this,
+            type_info->size,
+            -1 /* arena_offset */,
+            type_info->is_default_instance_offset));
+  }
+  // Cross link prototypes.
+  prototype->CrossLinkPrototypes();
+
+  return prototype;
+}
+
+void DynamicMessageFactory::ConstructDefaultOneofInstance(
+    const Descriptor* type,
+    const int offsets[],
+    void* default_oneof_instance) {
+  for (int i = 0; i < type->oneof_decl_count(); i++) {
+    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
+      void* field_ptr = reinterpret_cast<uint8*>(
+          default_oneof_instance) + offsets[field->index()];
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE)                                      \
+        case FieldDescriptor::CPPTYPE_##CPPTYPE:                        \
+          new(field_ptr) TYPE(field->default_value_##TYPE());           \
+          break;
+
+        HANDLE_TYPE(INT32 , int32 );
+        HANDLE_TYPE(INT64 , int64 );
+        HANDLE_TYPE(UINT32, uint32);
+        HANDLE_TYPE(UINT64, uint64);
+        HANDLE_TYPE(DOUBLE, double);
+        HANDLE_TYPE(FLOAT , float );
+        HANDLE_TYPE(BOOL  , bool  );
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_ENUM:
+          new(field_ptr) int(field->default_value_enum()->number());
+          break;
+        case FieldDescriptor::CPPTYPE_STRING:
+          switch (field->options().ctype()) {
+            default:
+            case FieldOptions::STRING:
+              ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
+              asp->UnsafeSetDefault(&field->default_value_string());
+              break;
+          }
+          break;
+
+        case FieldDescriptor::CPPTYPE_MESSAGE: {
+          new(field_ptr) Message*(NULL);
+          break;
+        }
+      }
+    }
+  }
+}
+
+void DynamicMessageFactory::DeleteDefaultOneofInstance(
+    const Descriptor* type,
+    const int offsets[],
+    void* default_oneof_instance) {
+  for (int i = 0; i < type->oneof_decl_count(); i++) {
+    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+        switch (field->options().ctype()) {
+          default:
+          case FieldOptions::STRING:
+            break;
+        }
+      }
+    }
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.h b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.h
new file mode 100644
index 0000000..f74cd7d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message.h
@@ -0,0 +1,152 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Defines an implementation of Message which can emulate types which are not
+// known at compile-time.
+
+#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
+#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
+
+namespace google {
+namespace protobuf {
+
+// Defined in other files.
+class Descriptor;        // descriptor.h
+class DescriptorPool;    // descriptor.h
+
+// Constructs implementations of Message which can emulate types which are not
+// known at compile-time.
+//
+// Sometimes you want to be able to manipulate protocol types that you don't
+// know about at compile time.  It would be nice to be able to construct
+// a Message object which implements the message type given by any arbitrary
+// Descriptor.  DynamicMessage provides this.
+//
+// As it turns out, a DynamicMessage needs to construct extra
+// information about its type in order to operate.  Most of this information
+// can be shared between all DynamicMessages of the same type.  But, caching
+// this information in some sort of global map would be a bad idea, since
+// the cached information for a particular descriptor could outlive the
+// descriptor itself.  To avoid this problem, DynamicMessageFactory
+// encapsulates this "cache".  All DynamicMessages of the same type created
+// from the same factory will share the same support data.  Any Descriptors
+// used with a particular factory must outlive the factory.
+class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
+ public:
+  // Construct a DynamicMessageFactory that will search for extensions in
+  // the DescriptorPool in which the extendee is defined.
+  DynamicMessageFactory();
+
+  // Construct a DynamicMessageFactory that will search for extensions in
+  // the given DescriptorPool.
+  //
+  // DEPRECATED:  Use CodedInputStream::SetExtensionRegistry() to tell the
+  //   parser to look for extensions in an alternate pool.  However, note that
+  //   this is almost never what you want to do.  Almost all users should use
+  //   the zero-arg constructor.
+  DynamicMessageFactory(const DescriptorPool* pool);
+
+  ~DynamicMessageFactory();
+
+  // Call this to tell the DynamicMessageFactory that if it is given a
+  // Descriptor d for which:
+  //   d->file()->pool() == DescriptorPool::generated_pool(),
+  // then it should delegate to MessageFactory::generated_factory() instead
+  // of constructing a dynamic implementation of the message.  In theory there
+  // is no down side to doing this, so it may become the default in the future.
+  void SetDelegateToGeneratedFactory(bool enable) {
+    delegate_to_generated_factory_ = enable;
+  }
+
+  // implements MessageFactory ---------------------------------------
+
+  // Given a Descriptor, constructs the default (prototype) Message of that
+  // type.  You can then call that message's New() method to construct a
+  // mutable message of that type.
+  //
+  // Calling this method twice with the same Descriptor returns the same
+  // object.  The returned object remains property of the factory and will
+  // be destroyed when the factory is destroyed.  Also, any objects created
+  // by calling the prototype's New() method share some data with the
+  // prototype, so these must be destroyed before the DynamicMessageFactory
+  // is destroyed.
+  //
+  // The given descriptor must outlive the returned message, and hence must
+  // outlive the DynamicMessageFactory.
+  //
+  // The method is thread-safe.
+  const Message* GetPrototype(const Descriptor* type);
+
+ private:
+  const DescriptorPool* pool_;
+  bool delegate_to_generated_factory_;
+
+  // This struct just contains a hash_map.  We can't #include <google/protobuf/stubs/hash.h> from
+  // this header due to hacks needed for hash_map portability in the open source
+  // release.  Namely, stubs/hash.h, which defines hash_map portably, is not a
+  // public header (for good reason), but dynamic_message.h is, and public
+  // headers may only #include other public headers.
+  struct PrototypeMap;
+  google::protobuf::scoped_ptr<PrototypeMap> prototypes_;
+  mutable Mutex prototypes_mutex_;
+
+  friend class DynamicMessage;
+  const Message* GetPrototypeNoLock(const Descriptor* type);
+
+  // Construct default oneof instance for reflection usage if oneof
+  // is defined.
+  static void ConstructDefaultOneofInstance(const Descriptor* type,
+                                            const int offsets[],
+                                            void* default_oneof_instance);
+  // Delete default oneof instance. Called by ~DynamicMessageFactory.
+  static void DeleteDefaultOneofInstance(const Descriptor* type,
+                                         const int offsets[],
+                                         void* default_oneof_instance);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/dynamic_message_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message_unittest.cc
new file mode 100644
index 0000000..70e437d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/dynamic_message_unittest.cc
@@ -0,0 +1,292 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Since the reflection interface for DynamicMessage is implemented by
+// GenericMessageReflection, the only thing we really have to test is
+// that DynamicMessage correctly sets up the information that
+// GenericMessageReflection needs to use.  So, we focus on that in this
+// test.  Other tests, such as generic_message_reflection_unittest and
+// reflection_ops_unittest, cover the rest of the functionality used by
+// DynamicMessage.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_no_field_presence.pb.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+class DynamicMessageTest : public testing::Test {
+ protected:
+  DescriptorPool pool_;
+  DynamicMessageFactory factory_;
+  const Descriptor* descriptor_;
+  const Message* prototype_;
+  const Descriptor* extensions_descriptor_;
+  const Message* extensions_prototype_;
+  const Descriptor* packed_descriptor_;
+  const Message* packed_prototype_;
+  const Descriptor* oneof_descriptor_;
+  const Message* oneof_prototype_;
+  const Descriptor* proto3_descriptor_;
+  const Message* proto3_prototype_;
+
+  DynamicMessageTest(): factory_(&pool_) {}
+
+  virtual void SetUp() {
+    // We want to make sure that DynamicMessage works (particularly with
+    // extensions) even if we use descriptors that are *not* from compiled-in
+    // types, so we make copies of the descriptors for unittest.proto and
+    // unittest_import.proto.
+    FileDescriptorProto unittest_file;
+    FileDescriptorProto unittest_import_file;
+    FileDescriptorProto unittest_import_public_file;
+    FileDescriptorProto unittest_no_field_presence_file;
+
+    unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file);
+    unittest_import::ImportMessage::descriptor()->file()->CopyTo(
+      &unittest_import_file);
+    unittest_import::PublicImportMessage::descriptor()->file()->CopyTo(
+      &unittest_import_public_file);
+    proto2_nofieldpresence_unittest::TestAllTypes::descriptor()->
+        file()->CopyTo(&unittest_no_field_presence_file);
+
+    ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL);
+    ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL);
+    ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL);
+    ASSERT_TRUE(pool_.BuildFile(unittest_no_field_presence_file) != NULL);
+
+    descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes");
+    ASSERT_TRUE(descriptor_ != NULL);
+    prototype_ = factory_.GetPrototype(descriptor_);
+
+    extensions_descriptor_ =
+      pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions");
+    ASSERT_TRUE(extensions_descriptor_ != NULL);
+    extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_);
+
+    packed_descriptor_ =
+      pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes");
+    ASSERT_TRUE(packed_descriptor_ != NULL);
+    packed_prototype_ = factory_.GetPrototype(packed_descriptor_);
+
+    oneof_descriptor_ =
+      pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2");
+    ASSERT_TRUE(oneof_descriptor_ != NULL);
+    oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_);
+
+    proto3_descriptor_ =
+      pool_.FindMessageTypeByName(
+          "proto2_nofieldpresence_unittest.TestAllTypes");
+    ASSERT_TRUE(proto3_descriptor_ != NULL);
+    proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_);
+  }
+};
+
+TEST_F(DynamicMessageTest, Descriptor) {
+  // Check that the descriptor on the DynamicMessage matches the descriptor
+  // passed to GetPrototype().
+  EXPECT_EQ(prototype_->GetDescriptor(), descriptor_);
+}
+
+TEST_F(DynamicMessageTest, OnePrototype) {
+  // Check that requesting the same prototype twice produces the same object.
+  EXPECT_EQ(prototype_, factory_.GetPrototype(descriptor_));
+}
+
+TEST_F(DynamicMessageTest, Defaults) {
+  // Check that all default values are set correctly in the initial message.
+  TestUtil::ReflectionTester reflection_tester(descriptor_);
+  reflection_tester.ExpectClearViaReflection(*prototype_);
+}
+
+TEST_F(DynamicMessageTest, IndependentOffsets) {
+  // Check that all fields have independent offsets by setting each
+  // one to a unique value then checking that they all still have those
+  // unique values (i.e. they don't stomp each other).
+  google::protobuf::scoped_ptr<Message> message(prototype_->New());
+  TestUtil::ReflectionTester reflection_tester(descriptor_);
+
+  reflection_tester.SetAllFieldsViaReflection(message.get());
+  reflection_tester.ExpectAllFieldsSetViaReflection(*message);
+}
+
+TEST_F(DynamicMessageTest, Extensions) {
+  // Check that extensions work.
+  google::protobuf::scoped_ptr<Message> message(extensions_prototype_->New());
+  TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
+
+  reflection_tester.SetAllFieldsViaReflection(message.get());
+  reflection_tester.ExpectAllFieldsSetViaReflection(*message);
+}
+
+TEST_F(DynamicMessageTest, PackedFields) {
+  // Check that packed fields work properly.
+  google::protobuf::scoped_ptr<Message> message(packed_prototype_->New());
+  TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
+
+  reflection_tester.SetPackedFieldsViaReflection(message.get());
+  reflection_tester.ExpectPackedFieldsSetViaReflection(*message);
+}
+
+TEST_F(DynamicMessageTest, Oneof) {
+  // Check that oneof fields work properly.
+  google::protobuf::scoped_ptr<Message> message(oneof_prototype_->New());
+
+  // Check default values.
+  const Descriptor* descriptor = message->GetDescriptor();
+  const Reflection* reflection = message->GetReflection();
+  EXPECT_EQ(0, reflection->GetInt32(
+      *message, descriptor->FindFieldByName("foo_int")));
+  EXPECT_EQ("", reflection->GetString(
+      *message, descriptor->FindFieldByName("foo_string")));
+  EXPECT_EQ("", reflection->GetString(
+      *message, descriptor->FindFieldByName("foo_cord")));
+  EXPECT_EQ("", reflection->GetString(
+      *message, descriptor->FindFieldByName("foo_string_piece")));
+  EXPECT_EQ("", reflection->GetString(
+      *message, descriptor->FindFieldByName("foo_bytes")));
+  EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum(
+      *message, descriptor->FindFieldByName("foo_enum"))->number());
+  const Descriptor* nested_descriptor;
+  const Message* nested_prototype;
+  nested_descriptor =
+      pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage");
+  nested_prototype = factory_.GetPrototype(nested_descriptor);
+  EXPECT_EQ(nested_prototype,
+            &reflection->GetMessage(
+                *message, descriptor->FindFieldByName("foo_message")));
+  const Descriptor* foogroup_descriptor;
+  const Message* foogroup_prototype;
+  foogroup_descriptor =
+      pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup");
+  foogroup_prototype = factory_.GetPrototype(foogroup_descriptor);
+  EXPECT_EQ(foogroup_prototype,
+            &reflection->GetMessage(
+                *message, descriptor->FindFieldByName("foogroup")));
+  EXPECT_NE(foogroup_prototype,
+            &reflection->GetMessage(
+                *message, descriptor->FindFieldByName("foo_lazy_message")));
+  EXPECT_EQ(5, reflection->GetInt32(
+      *message, descriptor->FindFieldByName("bar_int")));
+  EXPECT_EQ("STRING", reflection->GetString(
+      *message, descriptor->FindFieldByName("bar_string")));
+  EXPECT_EQ("CORD", reflection->GetString(
+      *message, descriptor->FindFieldByName("bar_cord")));
+  EXPECT_EQ("SPIECE", reflection->GetString(
+      *message, descriptor->FindFieldByName("bar_string_piece")));
+  EXPECT_EQ("BYTES", reflection->GetString(
+      *message, descriptor->FindFieldByName("bar_bytes")));
+  EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum(
+      *message, descriptor->FindFieldByName("bar_enum"))->number());
+
+  // Check set functions.
+  TestUtil::ReflectionTester reflection_tester(oneof_descriptor_);
+  reflection_tester.SetOneofViaReflection(message.get());
+  reflection_tester.ExpectOneofSetViaReflection(*message);
+}
+
+TEST_F(DynamicMessageTest, SpaceUsed) {
+  // Test that SpaceUsed() works properly
+
+  // Since we share the implementation with generated messages, we don't need
+  // to test very much here.  Just make sure it appears to be working.
+
+  google::protobuf::scoped_ptr<Message> message(prototype_->New());
+  TestUtil::ReflectionTester reflection_tester(descriptor_);
+
+  int initial_space_used = message->SpaceUsed();
+
+  reflection_tester.SetAllFieldsViaReflection(message.get());
+  EXPECT_LT(initial_space_used, message->SpaceUsed());
+}
+
+TEST_F(DynamicMessageTest, Arena) {
+  Arena arena;
+  Message* message = prototype_->New(&arena);
+  (void)message;  // avoid unused-variable error.
+  // Return without freeing: should not leak.
+}
+
+TEST_F(DynamicMessageTest, Proto3) {
+  Message* message = proto3_prototype_->New();
+  const Reflection* refl = message->GetReflection();
+  const Descriptor* desc = message->GetDescriptor();
+
+  // Just test a single primtive and single message field here to make sure we
+  // are getting the no-field-presence semantics elsewhere. DynamicMessage uses
+  // GeneratedMessageReflection under the hood, so the rest should be fine as
+  // long as GMR recognizes that we're using a proto3 message.
+  const FieldDescriptor* optional_int32 =
+      desc->FindFieldByName("optional_int32");
+  const FieldDescriptor* optional_msg =
+      desc->FindFieldByName("optional_nested_message");
+  EXPECT_TRUE(optional_int32 != NULL);
+  EXPECT_TRUE(optional_msg != NULL);
+
+  EXPECT_EQ(false, refl->HasField(*message, optional_int32));
+  refl->SetInt32(message, optional_int32, 42);
+  EXPECT_EQ(true, refl->HasField(*message, optional_int32));
+  refl->SetInt32(message, optional_int32, 0);
+  EXPECT_EQ(false, refl->HasField(*message, optional_int32));
+
+  EXPECT_EQ(false, refl->HasField(*message, optional_msg));
+  refl->MutableMessage(message, optional_msg);
+  EXPECT_EQ(true, refl->HasField(*message, optional_msg));
+  delete refl->ReleaseMessage(message, optional_msg);
+  EXPECT_EQ(false, refl->HasField(*message, optional_msg));
+
+  // Also ensure that the default instance handles field presence properly.
+  EXPECT_EQ(false, refl->HasField(*proto3_prototype_, optional_msg));
+
+  delete message;
+}
+
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/empty.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/empty.pb.cc
new file mode 100644
index 0000000..dcf8426
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/empty.pb.cc
@@ -0,0 +1,319 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/empty.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Empty_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Empty_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/empty.proto");
+  GOOGLE_CHECK(file != NULL);
+  Empty_descriptor_ = file->message_type(0);
+  static const int Empty_offsets_[1] = {
+  };
+  Empty_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Empty_descriptor_,
+      Empty::default_instance_,
+      Empty_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Empty),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Empty_descriptor_, &Empty::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto() {
+  delete Empty::default_instance_;
+  delete Empty_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\033google/protobuf/empty.proto\022\017google.pr"
+    "otobuf\"\007\n\005EmptyBy\n\023com.google.protobufB\n"
+    "EmptyProtoP\001Z\'github.com/golang/protobuf"
+    "/ptypes/empty\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Proto"
+    "buf.WellKnownTypesb\006proto3", 186);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/empty.proto", &protobuf_RegisterTypes);
+  Empty::default_instance_ = new Empty();
+  Empty::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fempty_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Empty::Empty()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Empty)
+}
+
+Empty::Empty(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty)
+}
+
+void Empty::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Empty::Empty(const Empty& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty)
+}
+
+void Empty::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+}
+
+Empty::~Empty() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Empty)
+  SharedDtor();
+}
+
+void Empty::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void Empty::ArenaDtor(void* object) {
+  Empty* _this = reinterpret_cast< Empty* >(object);
+  (void)_this;
+}
+void Empty::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void Empty::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Empty::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Empty_descriptor_;
+}
+
+const Empty& Empty::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+  return *default_instance_;
+}
+
+Empty* Empty::default_instance_ = NULL;
+
+Empty* Empty::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<Empty>(arena);
+}
+
+void Empty::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
+}
+
+bool Empty::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Empty)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Empty)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Empty)
+  return false;
+#undef DO_
+}
+
+void Empty::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Empty)
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Empty)
+}
+
+::google::protobuf::uint8* Empty::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty)
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Empty)
+  return target;
+}
+
+int Empty::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty)
+  int total_size = 0;
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Empty::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Empty* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty)
+    MergeFrom(*source);
+  }
+}
+
+void Empty::MergeFrom(const Empty& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+}
+
+void Empty::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Empty::CopyFrom(const Empty& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Empty)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Empty::IsInitialized() const {
+
+  return true;
+}
+
+void Empty::Swap(Empty* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    Empty temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void Empty::UnsafeArenaSwap(Empty* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void Empty::InternalSwap(Empty* other) {
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Empty::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Empty_descriptor_;
+  metadata.reflection = Empty_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Empty
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/empty.pb.h b/src/third_party/protobuf-3/src/google/protobuf/empty.pb.h
new file mode 100644
index 0000000..868009f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/empty.pb.h
@@ -0,0 +1,143 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto();
+
+class Empty;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message {
+ public:
+  Empty();
+  virtual ~Empty();
+
+  Empty(const Empty& from);
+
+  inline Empty& operator=(const Empty& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Empty& default_instance();
+
+  void UnsafeArenaSwap(Empty* other);
+  void Swap(Empty* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Empty* New() const { return New(NULL); }
+
+  Empty* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Empty& from);
+  void MergeFrom(const Empty& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Empty* other);
+  protected:
+  explicit Empty(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Empty)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto();
+
+  void InitAsDefaultInstance();
+  static Empty* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Empty
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/empty.proto b/src/third_party/protobuf-3/src/google/protobuf/empty.proto
new file mode 100644
index 0000000..37f4cd1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/empty.proto
@@ -0,0 +1,53 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/empty";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "EmptyProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+option cc_enable_arenas = true;
+
+// A generic empty message that you can re-use to avoid defining duplicated
+// empty messages in your APIs. A typical example is to use it as the request
+// or the response type of an API method. For instance:
+//
+//     service Foo {
+//       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+//     }
+//
+// The JSON representation for `Empty` is empty JSON object `{}`.
+message Empty {}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/extension_set.cc b/src/third_party/protobuf-3/src/google/protobuf/extension_set.cc
new file mode 100644
index 0000000..9afb236
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/extension_set.cc
@@ -0,0 +1,1815 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+
+inline WireFormatLite::FieldType real_type(FieldType type) {
+  GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
+  return static_cast<WireFormatLite::FieldType>(type);
+}
+
+inline WireFormatLite::CppType cpp_type(FieldType type) {
+  return WireFormatLite::FieldTypeToCppType(real_type(type));
+}
+
+inline bool is_packable(WireFormatLite::WireType type) {
+  switch (type) {
+    case WireFormatLite::WIRETYPE_VARINT:
+    case WireFormatLite::WIRETYPE_FIXED64:
+    case WireFormatLite::WIRETYPE_FIXED32:
+      return true;
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED:
+    case WireFormatLite::WIRETYPE_START_GROUP:
+    case WireFormatLite::WIRETYPE_END_GROUP:
+      return false;
+
+    // Do not add a default statement. Let the compiler complain when someone
+    // adds a new wire type.
+  }
+  GOOGLE_LOG(FATAL) << "can't reach here.";
+  return false;
+}
+
+// Registry stuff.
+typedef hash_map<pair<const MessageLite*, int>,
+                 ExtensionInfo> ExtensionRegistry;
+ExtensionRegistry* registry_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
+
+void DeleteRegistry() {
+  delete registry_;
+  registry_ = NULL;
+}
+
+void InitRegistry() {
+  registry_ = new ExtensionRegistry;
+  OnShutdown(&DeleteRegistry);
+}
+
+// This function is only called at startup, so there is no need for thread-
+// safety.
+void Register(const MessageLite* containing_type,
+              int number, ExtensionInfo info) {
+  ::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
+
+  if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number),
+                          info)) {
+    GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
+               << containing_type->GetTypeName()
+               << "\", field number " << number << ".";
+  }
+}
+
+const ExtensionInfo* FindRegisteredExtension(
+    const MessageLite* containing_type, int number) {
+  return (registry_ == NULL)
+             ? NULL
+             : FindOrNull(*registry_, std::make_pair(containing_type, number));
+}
+
+}  // namespace
+
+ExtensionFinder::~ExtensionFinder() {}
+
+bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) {
+  const ExtensionInfo* extension =
+      FindRegisteredExtension(containing_type_, number);
+  if (extension == NULL) {
+    return false;
+  } else {
+    *output = *extension;
+    return true;
+  }
+}
+
+void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
+                                     int number, FieldType type,
+                                     bool is_repeated, bool is_packed) {
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM);
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE);
+  GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP);
+  ExtensionInfo info(type, is_repeated, is_packed);
+  Register(containing_type, number, info);
+}
+
+static bool CallNoArgValidityFunc(const void* arg, int number) {
+  // Note:  Must use C-style cast here rather than reinterpret_cast because
+  //   the C++ standard at one point did not allow casts between function and
+  //   data pointers and some compilers enforce this for C++-style casts.  No
+  //   compiler enforces it for C-style casts since lots of C-style code has
+  //   relied on these kinds of casts for a long time, despite being
+  //   technically undefined.  See:
+  //     http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195
+  // Also note:  Some compilers do not allow function pointers to be "const".
+  //   Which makes sense, I suppose, because it's meaningless.
+  return ((EnumValidityFunc*)arg)(number);
+}
+
+void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type,
+                                         int number, FieldType type,
+                                         bool is_repeated, bool is_packed,
+                                         EnumValidityFunc* is_valid) {
+  GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM);
+  ExtensionInfo info(type, is_repeated, is_packed);
+  info.enum_validity_check.func = CallNoArgValidityFunc;
+  // See comment in CallNoArgValidityFunc() about why we use a c-style cast.
+  info.enum_validity_check.arg = (void*)is_valid;
+  Register(containing_type, number, info);
+}
+
+void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type,
+                                            int number, FieldType type,
+                                            bool is_repeated, bool is_packed,
+                                            const MessageLite* prototype) {
+  GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE ||
+        type == WireFormatLite::TYPE_GROUP);
+  ExtensionInfo info(type, is_repeated, is_packed);
+  info.message_prototype = prototype;
+  Register(containing_type, number, info);
+}
+
+
+// ===================================================================
+// Constructors and basic methods.
+
+ExtensionSet::ExtensionSet(::google::protobuf::Arena* arena) : arena_(arena) {
+  if (arena_ != NULL) {
+    arena_->OwnDestructor(&extensions_);
+  }
+}
+
+ExtensionSet::ExtensionSet() : arena_(NULL) {}
+
+ExtensionSet::~ExtensionSet() {
+  // Deletes all allocated extensions.
+  if (arena_ == NULL) {
+    for (map<int, Extension>::iterator iter = extensions_.begin();
+         iter != extensions_.end(); ++iter) {
+      iter->second.Free();
+    }
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// void ExtensionSet::AppendToList(const Descriptor* containing_type,
+//                                 const DescriptorPool* pool,
+//                                 vector<const FieldDescriptor*>* output) const
+
+bool ExtensionSet::Has(int number) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) return false;
+  GOOGLE_DCHECK(!iter->second.is_repeated);
+  return !iter->second.is_cleared;
+}
+
+int ExtensionSet::NumExtensions() const {
+  int result = 0;
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    if (!iter->second.is_cleared) {
+      ++result;
+    }
+  }
+  return result;
+}
+
+int ExtensionSet::ExtensionSize(int number) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) return false;
+  return iter->second.GetSize();
+}
+
+FieldType ExtensionSet::ExtensionType(int number) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). ";
+    return 0;
+  }
+  if (iter->second.is_cleared) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). ";
+  }
+  return iter->second.type;
+}
+
+void ExtensionSet::ClearExtension(int number) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) return;
+  iter->second.Clear();
+}
+
+// ===================================================================
+// Field accessors
+
+namespace {
+
+enum Cardinality {
+  REPEATED,
+  OPTIONAL
+};
+
+}  // namespace
+
+#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                             \
+  GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED : OPTIONAL, LABEL);         \
+  GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE)
+
+// -------------------------------------------------------------------
+// Primitives
+
+#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE)                   \
+                                                                               \
+LOWERCASE ExtensionSet::Get##CAMELCASE(int number,                             \
+                                       LOWERCASE default_value) const {        \
+  map<int, Extension>::const_iterator iter = extensions_.find(number);         \
+  if (iter == extensions_.end() || iter->second.is_cleared) {                  \
+    return default_value;                                                      \
+  } else {                                                                     \
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, UPPERCASE);                            \
+    return iter->second.LOWERCASE##_value;                                     \
+  }                                                                            \
+}                                                                              \
+                                                                               \
+void ExtensionSet::Set##CAMELCASE(int number, FieldType type,                  \
+                                  LOWERCASE value,                             \
+                                  const FieldDescriptor* descriptor) {         \
+  Extension* extension;                                                        \
+  if (MaybeNewExtension(number, descriptor, &extension)) {                     \
+    extension->type = type;                                                    \
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
+    extension->is_repeated = false;                                            \
+  } else {                                                                     \
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE);                              \
+  }                                                                            \
+  extension->is_cleared = false;                                               \
+  extension->LOWERCASE##_value = value;                                        \
+}                                                                              \
+                                                                               \
+LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) const {  \
+  map<int, Extension>::const_iterator iter = extensions_.find(number);         \
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE);                              \
+  return iter->second.repeated_##LOWERCASE##_value->Get(index);                \
+}                                                                              \
+                                                                               \
+void ExtensionSet::SetRepeated##CAMELCASE(                                     \
+    int number, int index, LOWERCASE value) {                                  \
+  map<int, Extension>::iterator iter = extensions_.find(number);               \
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE);                              \
+  iter->second.repeated_##LOWERCASE##_value->Set(index, value);                \
+}                                                                              \
+                                                                               \
+void ExtensionSet::Add##CAMELCASE(int number, FieldType type,                  \
+                                  bool packed, LOWERCASE value,                \
+                                  const FieldDescriptor* descriptor) {         \
+  Extension* extension;                                                        \
+  if (MaybeNewExtension(number, descriptor, &extension)) {                     \
+    extension->type = type;                                                    \
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
+    extension->is_repeated = true;                                             \
+    extension->is_packed = packed;                                             \
+    extension->repeated_##LOWERCASE##_value =                                  \
+      Arena::CreateMessage<RepeatedField<LOWERCASE> >(arena_);                 \
+  } else {                                                                     \
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE);                              \
+    GOOGLE_DCHECK_EQ(extension->is_packed, packed);                                   \
+  }                                                                            \
+  extension->repeated_##LOWERCASE##_value->Add(value);                         \
+}
+
+PRIMITIVE_ACCESSORS( INT32,  int32,  Int32)
+PRIMITIVE_ACCESSORS( INT64,  int64,  Int64)
+PRIMITIVE_ACCESSORS(UINT32, uint32, UInt32)
+PRIMITIVE_ACCESSORS(UINT64, uint64, UInt64)
+PRIMITIVE_ACCESSORS( FLOAT,  float,  Float)
+PRIMITIVE_ACCESSORS(DOUBLE, double, Double)
+PRIMITIVE_ACCESSORS(  BOOL,   bool,   Bool)
+
+#undef PRIMITIVE_ACCESSORS
+
+const void* ExtensionSet::GetRawRepeatedField(int number,
+                                              const void* default_value) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    return default_value;
+  }
+  // We assume that all the RepeatedField<>* pointers have the same
+  // size and alignment within the anonymous union in Extension.
+  return iter->second.repeated_int32_value;
+}
+
+void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type,
+                                            bool packed,
+                                            const FieldDescriptor* desc) {
+  Extension* extension;
+
+  // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this
+  // extension.
+  if (MaybeNewExtension(number, desc, &extension)) {
+    extension->is_repeated = true;
+    extension->type = field_type;
+    extension->is_packed = packed;
+
+    switch (WireFormatLite::FieldTypeToCppType(
+        static_cast<WireFormatLite::FieldType>(field_type))) {
+      case WireFormatLite::CPPTYPE_INT32:
+        extension->repeated_int32_value =
+            Arena::CreateMessage<RepeatedField<int32> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_INT64:
+        extension->repeated_int64_value =
+            Arena::CreateMessage<RepeatedField<int64> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_UINT32:
+        extension->repeated_uint32_value =
+            Arena::CreateMessage<RepeatedField<uint32> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_UINT64:
+        extension->repeated_uint64_value =
+            Arena::CreateMessage<RepeatedField<uint64> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_DOUBLE:
+        extension->repeated_double_value =
+            Arena::CreateMessage<RepeatedField<double> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_FLOAT:
+        extension->repeated_float_value =
+            Arena::CreateMessage<RepeatedField<float> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_BOOL:
+        extension->repeated_bool_value =
+            Arena::CreateMessage<RepeatedField<bool> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_ENUM:
+        extension->repeated_enum_value =
+            Arena::CreateMessage<RepeatedField<int> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_STRING:
+        extension->repeated_string_value =
+            Arena::CreateMessage<RepeatedPtrField< ::std::string> >(arena_);
+        break;
+      case WireFormatLite::CPPTYPE_MESSAGE:
+        extension->repeated_message_value =
+            Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
+        break;
+    }
+  }
+
+  // We assume that all the RepeatedField<>* pointers have the same
+  // size and alignment within the anonymous union in Extension.
+  return extension->repeated_int32_value;
+}
+
+// Compatible version using old call signature. Does not create extensions when
+// the don't already exist; instead, just GOOGLE_CHECK-fails.
+void* ExtensionSet::MutableRawRepeatedField(int number) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter == extensions_.end()) << "Extension not found.";
+  // We assume that all the RepeatedField<>* pointers have the same
+  // size and alignment within the anonymous union in Extension.
+  return iter->second.repeated_int32_value;
+}
+
+
+// -------------------------------------------------------------------
+// Enums
+
+int ExtensionSet::GetEnum(int number, int default_value) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end() || iter->second.is_cleared) {
+    // Not present.  Return the default value.
+    return default_value;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, ENUM);
+    return iter->second.enum_value;
+  }
+}
+
+void ExtensionSet::SetEnum(int number, FieldType type, int value,
+                           const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
+    extension->is_repeated = false;
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM);
+  }
+  extension->is_cleared = false;
+  extension->enum_value = value;
+}
+
+int ExtensionSet::GetRepeatedEnum(int number, int index) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM);
+  return iter->second.repeated_enum_value->Get(index);
+}
+
+void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM);
+  iter->second.repeated_enum_value->Set(index, value);
+}
+
+void ExtensionSet::AddEnum(int number, FieldType type,
+                           bool packed, int value,
+                           const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
+    extension->is_repeated = true;
+    extension->is_packed = packed;
+    extension->repeated_enum_value =
+        Arena::CreateMessage<RepeatedField<int> >(arena_);
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM);
+    GOOGLE_DCHECK_EQ(extension->is_packed, packed);
+  }
+  extension->repeated_enum_value->Add(value);
+}
+
+// -------------------------------------------------------------------
+// Strings
+
+const string& ExtensionSet::GetString(int number,
+                                      const string& default_value) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end() || iter->second.is_cleared) {
+    // Not present.  Return the default value.
+    return default_value;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, STRING);
+    return *iter->second.string_value;
+  }
+}
+
+string* ExtensionSet::MutableString(int number, FieldType type,
+                                    const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
+    extension->is_repeated = false;
+    extension->string_value = Arena::Create<string>(arena_);
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING);
+  }
+  extension->is_cleared = false;
+  return extension->string_value;
+}
+
+const string& ExtensionSet::GetRepeatedString(int number, int index) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING);
+  return iter->second.repeated_string_value->Get(index);
+}
+
+string* ExtensionSet::MutableRepeatedString(int number, int index) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING);
+  return iter->second.repeated_string_value->Mutable(index);
+}
+
+string* ExtensionSet::AddString(int number, FieldType type,
+                                const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
+    extension->is_repeated = true;
+    extension->is_packed = false;
+    extension->repeated_string_value =
+        Arena::CreateMessage<RepeatedPtrField<string> >(arena_);
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING);
+  }
+  return extension->repeated_string_value->Add();
+}
+
+// -------------------------------------------------------------------
+// Messages
+
+const MessageLite& ExtensionSet::GetMessage(
+    int number, const MessageLite& default_value) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    // Not present.  Return the default value.
+    return default_value;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    if (iter->second.is_lazy) {
+      return iter->second.lazymessage_value->GetMessage(default_value);
+    } else {
+      return *iter->second.message_value;
+    }
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// const MessageLite& ExtensionSet::GetMessage(int number,
+//                                             const Descriptor* message_type,
+//                                             MessageFactory* factory) const
+
+MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
+                                          const MessageLite& prototype,
+                                          const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_lazy = false;
+    extension->message_value = prototype.New(arena_);
+    extension->is_cleared = false;
+    return extension->message_value;
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    extension->is_cleared = false;
+    if (extension->is_lazy) {
+      return extension->lazymessage_value->MutableMessage(prototype);
+    } else {
+      return extension->message_value;
+    }
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
+//                                           const Descriptor* message_type,
+//                                           MessageFactory* factory)
+
+void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
+                                       const FieldDescriptor* descriptor,
+                                       MessageLite* message) {
+  if (message == NULL) {
+    ClearExtension(number);
+    return;
+  }
+  ::google::protobuf::Arena* message_arena = message->GetArena();
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_lazy = false;
+    if (message_arena == arena_) {
+      extension->message_value = message;
+    } else if (message_arena == NULL) {
+      extension->message_value = message;
+      arena_->Own(message);  // not NULL because not equal to message_arena
+    } else {
+      extension->message_value = message->New(arena_);
+      extension->message_value->CheckTypeAndMergeFrom(*message);
+    }
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    if (extension->is_lazy) {
+      extension->lazymessage_value->SetAllocatedMessage(message);
+    } else {
+      if (arena_ == NULL) {
+        delete extension->message_value;
+      }
+      if (message_arena == arena_) {
+        extension->message_value = message;
+      } else if (message_arena == NULL) {
+        extension->message_value = message;
+        arena_->Own(message);  // not NULL because not equal to message_arena
+      } else {
+        extension->message_value = message->New(arena_);
+        extension->message_value->CheckTypeAndMergeFrom(*message);
+      }
+    }
+  }
+  extension->is_cleared = false;
+}
+
+void ExtensionSet::UnsafeArenaSetAllocatedMessage(
+    int number, FieldType type, const FieldDescriptor* descriptor,
+    MessageLite* message) {
+  if (message == NULL) {
+    ClearExtension(number);
+    return;
+  }
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_lazy = false;
+    extension->message_value = message;
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    if (extension->is_lazy) {
+      extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message);
+    } else {
+      if (arena_ == NULL) {
+        delete extension->message_value;
+      }
+      extension->message_value = message;
+    }
+  }
+  extension->is_cleared = false;
+}
+
+
+MessageLite* ExtensionSet::ReleaseMessage(int number,
+                                          const MessageLite& prototype) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    // Not present.  Return NULL.
+    return NULL;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    MessageLite* ret = NULL;
+    if (iter->second.is_lazy) {
+      ret = iter->second.lazymessage_value->ReleaseMessage(prototype);
+      if (arena_ == NULL) {
+        delete iter->second.lazymessage_value;
+      }
+    } else {
+      if (arena_ == NULL) {
+        ret = iter->second.message_value;
+      } else {
+        // ReleaseMessage() always returns a heap-allocated message, and we are
+        // on an arena, so we need to make a copy of this message to return.
+        ret = (iter->second.message_value)->New();
+        ret->CheckTypeAndMergeFrom(*iter->second.message_value);
+      }
+    }
+    extensions_.erase(number);
+    return ret;
+  }
+}
+
+MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
+    int number, const MessageLite& prototype) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    // Not present.  Return NULL.
+    return NULL;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    MessageLite* ret = NULL;
+    if (iter->second.is_lazy) {
+      ret =
+        iter->second.lazymessage_value->UnsafeArenaReleaseMessage(prototype);
+      if (arena_ == NULL) {
+        delete iter->second.lazymessage_value;
+      }
+    } else {
+      ret = iter->second.message_value;
+    }
+    extensions_.erase(number);
+    return ret;
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+//                                           MessageFactory* factory);
+
+const MessageLite& ExtensionSet::GetRepeatedMessage(
+    int number, int index) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
+  return iter->second.repeated_message_value->Get(index);
+}
+
+MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+  GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
+  return iter->second.repeated_message_value->Mutable(index);
+}
+
+MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
+                                      const MessageLite& prototype,
+                                      const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+    extension->is_repeated = true;
+    extension->repeated_message_value =
+        Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
+  }
+
+  // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
+  // allocate an abstract object, so we have to be tricky.
+  MessageLite* result = extension->repeated_message_value
+      ->AddFromCleared<GenericTypeHandler<MessageLite> >();
+  if (result == NULL) {
+    result = prototype.New(arena_);
+    extension->repeated_message_value->AddAllocated(result);
+  }
+  return result;
+}
+
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
+//                                       const Descriptor* message_type,
+//                                       MessageFactory* factory)
+
+#undef GOOGLE_DCHECK_TYPE
+
+void ExtensionSet::RemoveLast(int number) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+
+  Extension* extension = &iter->second;
+  GOOGLE_DCHECK(extension->is_repeated);
+
+  switch(cpp_type(extension->type)) {
+    case WireFormatLite::CPPTYPE_INT32:
+      extension->repeated_int32_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_INT64:
+      extension->repeated_int64_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_UINT32:
+      extension->repeated_uint32_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_UINT64:
+      extension->repeated_uint64_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_FLOAT:
+      extension->repeated_float_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_DOUBLE:
+      extension->repeated_double_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_BOOL:
+      extension->repeated_bool_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_ENUM:
+      extension->repeated_enum_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_STRING:
+      extension->repeated_string_value->RemoveLast();
+      break;
+    case WireFormatLite::CPPTYPE_MESSAGE:
+      extension->repeated_message_value->RemoveLast();
+      break;
+  }
+}
+
+MessageLite* ExtensionSet::ReleaseLast(int number) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+
+  Extension* extension = &iter->second;
+  GOOGLE_DCHECK(extension->is_repeated);
+  GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE);
+  return extension->repeated_message_value->ReleaseLast();
+}
+
+void ExtensionSet::SwapElements(int number, int index1, int index2) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+
+  Extension* extension = &iter->second;
+  GOOGLE_DCHECK(extension->is_repeated);
+
+  switch(cpp_type(extension->type)) {
+    case WireFormatLite::CPPTYPE_INT32:
+      extension->repeated_int32_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_INT64:
+      extension->repeated_int64_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_UINT32:
+      extension->repeated_uint32_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_UINT64:
+      extension->repeated_uint64_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_FLOAT:
+      extension->repeated_float_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_DOUBLE:
+      extension->repeated_double_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_BOOL:
+      extension->repeated_bool_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_ENUM:
+      extension->repeated_enum_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_STRING:
+      extension->repeated_string_value->SwapElements(index1, index2);
+      break;
+    case WireFormatLite::CPPTYPE_MESSAGE:
+      extension->repeated_message_value->SwapElements(index1, index2);
+      break;
+  }
+}
+
+// ===================================================================
+
+void ExtensionSet::Clear() {
+  for (map<int, Extension>::iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    iter->second.Clear();
+  }
+}
+
+void ExtensionSet::MergeFrom(const ExtensionSet& other) {
+  for (map<int, Extension>::const_iterator iter = other.extensions_.begin();
+       iter != other.extensions_.end(); ++iter) {
+    const Extension& other_extension = iter->second;
+    InternalExtensionMergeFrom(iter->first, other_extension);
+  }
+}
+
+void ExtensionSet::InternalExtensionMergeFrom(
+  int number, const Extension& other_extension) {
+  if (other_extension.is_repeated) {
+    Extension* extension;
+    bool is_new = MaybeNewExtension(number, other_extension.descriptor,
+                                    &extension);
+    if (is_new) {
+      // Extension did not already exist in set.
+      extension->type = other_extension.type;
+      extension->is_packed = other_extension.is_packed;
+      extension->is_repeated = true;
+    } else {
+      GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+      GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
+      GOOGLE_DCHECK(extension->is_repeated);
+    }
+
+    switch (cpp_type(other_extension.type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE)                    \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                             \
+        if (is_new) {                                                       \
+          extension->repeated_##LOWERCASE##_value =                         \
+            Arena::CreateMessage<REPEATED_TYPE >(arena_);                   \
+        }                                                                   \
+        extension->repeated_##LOWERCASE##_value->MergeFrom(                 \
+          *other_extension.repeated_##LOWERCASE##_value);                   \
+        break;
+
+      HANDLE_TYPE(  INT32,   int32, RepeatedField   <  int32>);
+      HANDLE_TYPE(  INT64,   int64, RepeatedField   <  int64>);
+      HANDLE_TYPE( UINT32,  uint32, RepeatedField   < uint32>);
+      HANDLE_TYPE( UINT64,  uint64, RepeatedField   < uint64>);
+      HANDLE_TYPE(  FLOAT,   float, RepeatedField   <  float>);
+      HANDLE_TYPE( DOUBLE,  double, RepeatedField   < double>);
+      HANDLE_TYPE(   BOOL,    bool, RepeatedField   <   bool>);
+      HANDLE_TYPE(   ENUM,    enum, RepeatedField   <    int>);
+      HANDLE_TYPE( STRING,  string, RepeatedPtrField< string>);
+#undef HANDLE_TYPE
+
+      case WireFormatLite::CPPTYPE_MESSAGE:
+        if (is_new) {
+          extension->repeated_message_value =
+              Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
+        }
+        // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
+        // it would attempt to allocate new objects.
+        RepeatedPtrField<MessageLite>* other_repeated_message =
+            other_extension.repeated_message_value;
+        for (int i = 0; i < other_repeated_message->size(); i++) {
+          const MessageLite& other_message = other_repeated_message->Get(i);
+          MessageLite* target = extension->repeated_message_value
+                   ->AddFromCleared<GenericTypeHandler<MessageLite> >();
+          if (target == NULL) {
+            target = other_message.New(arena_);
+            extension->repeated_message_value->AddAllocated(target);
+          }
+          target->CheckTypeAndMergeFrom(other_message);
+        }
+        break;
+    }
+  } else {
+    if (!other_extension.is_cleared) {
+      switch (cpp_type(other_extension.type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE)                       \
+        case WireFormatLite::CPPTYPE_##UPPERCASE:                          \
+          Set##CAMELCASE(number, other_extension.type,                     \
+                         other_extension.LOWERCASE##_value,                \
+                         other_extension.descriptor);                      \
+          break;
+
+        HANDLE_TYPE( INT32,  int32,  Int32);
+        HANDLE_TYPE( INT64,  int64,  Int64);
+        HANDLE_TYPE(UINT32, uint32, UInt32);
+        HANDLE_TYPE(UINT64, uint64, UInt64);
+        HANDLE_TYPE( FLOAT,  float,  Float);
+        HANDLE_TYPE(DOUBLE, double, Double);
+        HANDLE_TYPE(  BOOL,   bool,   Bool);
+        HANDLE_TYPE(  ENUM,   enum,   Enum);
+#undef HANDLE_TYPE
+        case WireFormatLite::CPPTYPE_STRING:
+          SetString(number, other_extension.type,
+                    *other_extension.string_value,
+                    other_extension.descriptor);
+          break;
+        case WireFormatLite::CPPTYPE_MESSAGE: {
+          Extension* extension;
+          bool is_new = MaybeNewExtension(number,
+                                          other_extension.descriptor,
+                                          &extension);
+          if (is_new) {
+            extension->type = other_extension.type;
+            extension->is_packed = other_extension.is_packed;
+            extension->is_repeated = false;
+            if (other_extension.is_lazy) {
+              extension->is_lazy = true;
+              extension->lazymessage_value =
+                  other_extension.lazymessage_value->New(arena_);
+              extension->lazymessage_value->MergeFrom(
+                  *other_extension.lazymessage_value);
+            } else {
+              extension->is_lazy = false;
+              extension->message_value =
+                  other_extension.message_value->New(arena_);
+              extension->message_value->CheckTypeAndMergeFrom(
+                  *other_extension.message_value);
+            }
+          } else {
+            GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+            GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed);
+            GOOGLE_DCHECK(!extension->is_repeated);
+            if (other_extension.is_lazy) {
+              if (extension->is_lazy) {
+                extension->lazymessage_value->MergeFrom(
+                    *other_extension.lazymessage_value);
+              } else {
+                extension->message_value->CheckTypeAndMergeFrom(
+                    other_extension.lazymessage_value->GetMessage(
+                        *extension->message_value));
+              }
+            } else {
+              if (extension->is_lazy) {
+                extension->lazymessage_value->MutableMessage(
+                    *other_extension.message_value)->CheckTypeAndMergeFrom(
+                        *other_extension.message_value);
+              } else {
+                extension->message_value->CheckTypeAndMergeFrom(
+                    *other_extension.message_value);
+              }
+            }
+          }
+          extension->is_cleared = false;
+          break;
+        }
+      }
+    }
+  }
+}
+
+void ExtensionSet::Swap(ExtensionSet* x) {
+  if (GetArenaNoVirtual() == x->GetArenaNoVirtual()) {
+    extensions_.swap(x->extensions_);
+  } else {
+    // TODO(cfallin, rohananil): We maybe able to optimize a case where we are
+    // swapping from heap to arena-allocated extension set, by just Own()'ing
+    // the extensions.
+    ExtensionSet extension_set;
+    extension_set.MergeFrom(*x);
+    x->Clear();
+    x->MergeFrom(*this);
+    Clear();
+    MergeFrom(extension_set);
+  }
+}
+
+void ExtensionSet::SwapExtension(ExtensionSet* other,
+                                 int number) {
+  if (this == other) return;
+  map<int, Extension>::iterator this_iter = extensions_.find(number);
+  map<int, Extension>::iterator other_iter = other->extensions_.find(number);
+
+  if (this_iter == extensions_.end() &&
+      other_iter == other->extensions_.end()) {
+    return;
+  }
+
+  if (this_iter != extensions_.end() &&
+      other_iter != other->extensions_.end()) {
+    if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+      using std::swap;
+      swap(this_iter->second, other_iter->second);
+    } else {
+      // TODO(cfallin, rohananil): We could further optimize these cases,
+      // especially avoid creation of ExtensionSet, and move MergeFrom logic
+      // into Extensions itself (which takes arena as an argument).
+      // We do it this way to reuse the copy-across-arenas logic already
+      // implemented in ExtensionSet's MergeFrom.
+      ExtensionSet temp;
+      temp.InternalExtensionMergeFrom(number, other_iter->second);
+      map<int, Extension>::iterator temp_iter = temp.extensions_.find(number);
+      other_iter->second.Clear();
+      other->InternalExtensionMergeFrom(number, this_iter->second);
+      this_iter->second.Clear();
+      InternalExtensionMergeFrom(number, temp_iter->second);
+    }
+    return;
+  }
+
+  if (this_iter == extensions_.end()) {
+    if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+      extensions_.insert(std::make_pair(number, other_iter->second));
+    } else {
+      InternalExtensionMergeFrom(number, other_iter->second);
+    }
+    other->extensions_.erase(number);
+    return;
+  }
+
+  if (other_iter == other->extensions_.end()) {
+    if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+      other->extensions_.insert(std::make_pair(number, this_iter->second));
+    } else {
+      other->InternalExtensionMergeFrom(number, this_iter->second);
+    }
+    extensions_.erase(number);
+    return;
+  }
+}
+
+bool ExtensionSet::IsInitialized() const {
+  // Extensions are never required.  However, we need to check that all
+  // embedded messages are initialized.
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    const Extension& extension = iter->second;
+    if (cpp_type(extension.type) == WireFormatLite::CPPTYPE_MESSAGE) {
+      if (extension.is_repeated) {
+        for (int i = 0; i < extension.repeated_message_value->size(); i++) {
+          if (!extension.repeated_message_value->Get(i).IsInitialized()) {
+            return false;
+          }
+        }
+      } else {
+        if (!extension.is_cleared) {
+          if (extension.is_lazy) {
+            if (!extension.lazymessage_value->IsInitialized()) return false;
+          } else {
+            if (!extension.message_value->IsInitialized()) return false;
+          }
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+bool ExtensionSet::FindExtensionInfoFromTag(
+    uint32 tag, ExtensionFinder* extension_finder, int* field_number,
+    ExtensionInfo* extension, bool* was_packed_on_wire) {
+  *field_number = WireFormatLite::GetTagFieldNumber(tag);
+  WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
+  return FindExtensionInfoFromFieldNumber(wire_type, *field_number,
+                                          extension_finder, extension,
+                                          was_packed_on_wire);
+}
+
+bool ExtensionSet::FindExtensionInfoFromFieldNumber(
+    int wire_type, int field_number, ExtensionFinder* extension_finder,
+    ExtensionInfo* extension, bool* was_packed_on_wire) {
+  if (!extension_finder->Find(field_number, extension)) {
+    return false;
+  }
+
+  WireFormatLite::WireType expected_wire_type =
+      WireFormatLite::WireTypeForFieldType(real_type(extension->type));
+
+  // Check if this is a packed field.
+  *was_packed_on_wire = false;
+  if (extension->is_repeated &&
+      wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED &&
+      is_packable(expected_wire_type)) {
+    *was_packed_on_wire = true;
+    return true;
+  }
+  // Otherwise the wire type must match.
+  return expected_wire_type == wire_type;
+}
+
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              ExtensionFinder* extension_finder,
+                              FieldSkipper* field_skipper) {
+  int number;
+  bool was_packed_on_wire;
+  ExtensionInfo extension;
+  if (!FindExtensionInfoFromTag(
+      tag, extension_finder, &number, &extension, &was_packed_on_wire)) {
+    return field_skipper->SkipField(input, tag);
+  } else {
+    return ParseFieldWithExtensionInfo(
+        number, was_packed_on_wire, extension, input, field_skipper);
+  }
+}
+
+bool ExtensionSet::ParseFieldWithExtensionInfo(
+    int number, bool was_packed_on_wire, const ExtensionInfo& extension,
+    io::CodedInputStream* input,
+    FieldSkipper* field_skipper) {
+  // Explicitly not read extension.is_packed, instead check whether the field
+  // was encoded in packed form on the wire.
+  if (was_packed_on_wire) {
+    uint32 size;
+    if (!input->ReadVarint32(&size)) return false;
+    io::CodedInputStream::Limit limit = input->PushLimit(size);
+
+    switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE)        \
+      case WireFormatLite::TYPE_##UPPERCASE:                                   \
+        while (input->BytesUntilLimit() > 0) {                                 \
+          CPP_LOWERCASE value;                                                 \
+          if (!WireFormatLite::ReadPrimitive<                                  \
+                  CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>(            \
+                input, &value)) return false;                                  \
+          Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,         \
+                             extension.is_packed, value,                       \
+                             extension.descriptor);                            \
+        }                                                                      \
+        break
+
+      HANDLE_TYPE(   INT32,  Int32,   int32);
+      HANDLE_TYPE(   INT64,  Int64,   int64);
+      HANDLE_TYPE(  UINT32, UInt32,  uint32);
+      HANDLE_TYPE(  UINT64, UInt64,  uint64);
+      HANDLE_TYPE(  SINT32,  Int32,   int32);
+      HANDLE_TYPE(  SINT64,  Int64,   int64);
+      HANDLE_TYPE( FIXED32, UInt32,  uint32);
+      HANDLE_TYPE( FIXED64, UInt64,  uint64);
+      HANDLE_TYPE(SFIXED32,  Int32,   int32);
+      HANDLE_TYPE(SFIXED64,  Int64,   int64);
+      HANDLE_TYPE(   FLOAT,  Float,   float);
+      HANDLE_TYPE(  DOUBLE, Double,  double);
+      HANDLE_TYPE(    BOOL,   Bool,    bool);
+#undef HANDLE_TYPE
+
+      case WireFormatLite::TYPE_ENUM:
+        while (input->BytesUntilLimit() > 0) {
+          int value;
+          if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+                  input, &value)) return false;
+          if (extension.enum_validity_check.func(
+                  extension.enum_validity_check.arg, value)) {
+            AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed,
+                    value, extension.descriptor);
+          } else {
+            // Invalid value.  Treat as unknown.
+            field_skipper->SkipUnknownEnum(number, value);
+          }
+        }
+        break;
+
+      case WireFormatLite::TYPE_STRING:
+      case WireFormatLite::TYPE_BYTES:
+      case WireFormatLite::TYPE_GROUP:
+      case WireFormatLite::TYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+        break;
+    }
+
+    input->PopLimit(limit);
+  } else {
+    switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE)                   \
+      case WireFormatLite::TYPE_##UPPERCASE: {                                 \
+        CPP_LOWERCASE value;                                                   \
+        if (!WireFormatLite::ReadPrimitive<                                    \
+                CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>(              \
+               input, &value)) return false;                                   \
+        if (extension.is_repeated) {                                           \
+          Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,         \
+                             extension.is_packed, value,                       \
+                             extension.descriptor);                            \
+        } else {                                                               \
+          Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,  \
+                             extension.descriptor);                            \
+        }                                                                      \
+      } break
+
+      HANDLE_TYPE(   INT32,  Int32,   int32);
+      HANDLE_TYPE(   INT64,  Int64,   int64);
+      HANDLE_TYPE(  UINT32, UInt32,  uint32);
+      HANDLE_TYPE(  UINT64, UInt64,  uint64);
+      HANDLE_TYPE(  SINT32,  Int32,   int32);
+      HANDLE_TYPE(  SINT64,  Int64,   int64);
+      HANDLE_TYPE( FIXED32, UInt32,  uint32);
+      HANDLE_TYPE( FIXED64, UInt64,  uint64);
+      HANDLE_TYPE(SFIXED32,  Int32,   int32);
+      HANDLE_TYPE(SFIXED64,  Int64,   int64);
+      HANDLE_TYPE(   FLOAT,  Float,   float);
+      HANDLE_TYPE(  DOUBLE, Double,  double);
+      HANDLE_TYPE(    BOOL,   Bool,    bool);
+#undef HANDLE_TYPE
+
+      case WireFormatLite::TYPE_ENUM: {
+        int value;
+        if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+                input, &value)) return false;
+
+        if (!extension.enum_validity_check.func(
+                extension.enum_validity_check.arg, value)) {
+          // Invalid value.  Treat as unknown.
+          field_skipper->SkipUnknownEnum(number, value);
+        } else if (extension.is_repeated) {
+          AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
+                  extension.descriptor);
+        } else {
+          SetEnum(number, WireFormatLite::TYPE_ENUM, value,
+                  extension.descriptor);
+        }
+        break;
+      }
+
+      case WireFormatLite::TYPE_STRING:  {
+        string* value = extension.is_repeated ?
+          AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
+          MutableString(number, WireFormatLite::TYPE_STRING,
+                        extension.descriptor);
+        if (!WireFormatLite::ReadString(input, value)) return false;
+        break;
+      }
+
+      case WireFormatLite::TYPE_BYTES:  {
+        string* value = extension.is_repeated ?
+          AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) :
+          MutableString(number, WireFormatLite::TYPE_BYTES,
+                        extension.descriptor);
+        if (!WireFormatLite::ReadBytes(input, value)) return false;
+        break;
+      }
+
+      case WireFormatLite::TYPE_GROUP: {
+        MessageLite* value = extension.is_repeated ?
+            AddMessage(number, WireFormatLite::TYPE_GROUP,
+                       *extension.message_prototype, extension.descriptor) :
+            MutableMessage(number, WireFormatLite::TYPE_GROUP,
+                           *extension.message_prototype, extension.descriptor);
+        if (!WireFormatLite::ReadGroup(number, input, value)) return false;
+        break;
+      }
+
+      case WireFormatLite::TYPE_MESSAGE: {
+        MessageLite* value = extension.is_repeated ?
+            AddMessage(number, WireFormatLite::TYPE_MESSAGE,
+                       *extension.message_prototype, extension.descriptor) :
+            MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
+                           *extension.message_prototype, extension.descriptor);
+        if (!WireFormatLite::ReadMessage(input, value)) return false;
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              const MessageLite* containing_type) {
+  FieldSkipper skipper;
+  GeneratedExtensionFinder finder(containing_type);
+  return ParseField(tag, input, &finder, &skipper);
+}
+
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              const MessageLite* containing_type,
+                              io::CodedOutputStream* unknown_fields) {
+  CodedOutputStreamFieldSkipper skipper(unknown_fields);
+  GeneratedExtensionFinder finder(containing_type);
+  return ParseField(tag, input, &finder, &skipper);
+}
+
+// Defined in extension_set_heavy.cc.
+// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+//                               const MessageLite* containing_type,
+//                               UnknownFieldSet* unknown_fields)
+
+// Defined in extension_set_heavy.cc.
+// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+//                                    const MessageLite* containing_type,
+//                                    UnknownFieldSet* unknown_fields);
+
+void ExtensionSet::SerializeWithCachedSizes(
+    int start_field_number, int end_field_number,
+    io::CodedOutputStream* output) const {
+  map<int, Extension>::const_iterator iter;
+  for (iter = extensions_.lower_bound(start_field_number);
+       iter != extensions_.end() && iter->first < end_field_number;
+       ++iter) {
+    iter->second.SerializeFieldWithCachedSizes(iter->first, output);
+  }
+}
+
+int ExtensionSet::ByteSize() const {
+  int total_size = 0;
+
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    total_size += iter->second.ByteSize(iter->first);
+  }
+
+  return total_size;
+}
+
+// Defined in extension_set_heavy.cc.
+// int ExtensionSet::SpaceUsedExcludingSelf() const
+
+bool ExtensionSet::MaybeNewExtension(int number,
+                                     const FieldDescriptor* descriptor,
+                                     Extension** result) {
+  pair<map<int, Extension>::iterator, bool> insert_result =
+      extensions_.insert(std::make_pair(number, Extension()));
+  *result = &insert_result.first->second;
+  (*result)->descriptor = descriptor;
+  return insert_result.second;
+}
+
+// ===================================================================
+// Methods of ExtensionSet::Extension
+
+void ExtensionSet::Extension::Clear() {
+  if (is_repeated) {
+    switch (cpp_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
+        repeated_##LOWERCASE##_value->Clear();                     \
+        break
+
+      HANDLE_TYPE(  INT32,   int32);
+      HANDLE_TYPE(  INT64,   int64);
+      HANDLE_TYPE( UINT32,  uint32);
+      HANDLE_TYPE( UINT64,  uint64);
+      HANDLE_TYPE(  FLOAT,   float);
+      HANDLE_TYPE( DOUBLE,  double);
+      HANDLE_TYPE(   BOOL,    bool);
+      HANDLE_TYPE(   ENUM,    enum);
+      HANDLE_TYPE( STRING,  string);
+      HANDLE_TYPE(MESSAGE, message);
+#undef HANDLE_TYPE
+    }
+  } else {
+    if (!is_cleared) {
+      switch (cpp_type(type)) {
+        case WireFormatLite::CPPTYPE_STRING:
+          string_value->clear();
+          break;
+        case WireFormatLite::CPPTYPE_MESSAGE:
+          if (is_lazy) {
+            lazymessage_value->Clear();
+          } else {
+            message_value->Clear();
+          }
+          break;
+        default:
+          // No need to do anything.  Get*() will return the default value
+          // as long as is_cleared is true and Set*() will overwrite the
+          // previous value.
+          break;
+      }
+
+      is_cleared = true;
+    }
+  }
+}
+
+void ExtensionSet::Extension::SerializeFieldWithCachedSizes(
+    int number,
+    io::CodedOutputStream* output) const {
+  if (is_repeated) {
+    if (is_packed) {
+      if (cached_size == 0) return;
+
+      WireFormatLite::WriteTag(number,
+          WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+      output->WriteVarint32(cached_size);
+
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            WireFormatLite::Write##CAMELCASE##NoTag(                        \
+              repeated_##LOWERCASE##_value->Get(i), output);                \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,   int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,   int64);
+        HANDLE_TYPE(   FLOAT,    Float,   float);
+        HANDLE_TYPE(  DOUBLE,   Double,  double);
+        HANDLE_TYPE(    BOOL,     Bool,    bool);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+#undef HANDLE_TYPE
+
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_BYTES:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
+          GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+          break;
+      }
+    } else {
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            WireFormatLite::Write##CAMELCASE(number,                        \
+              repeated_##LOWERCASE##_value->Get(i), output);                \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,   int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,   int64);
+        HANDLE_TYPE(   FLOAT,    Float,   float);
+        HANDLE_TYPE(  DOUBLE,   Double,  double);
+        HANDLE_TYPE(    BOOL,     Bool,    bool);
+        HANDLE_TYPE(  STRING,   String,  string);
+        HANDLE_TYPE(   BYTES,    Bytes,  string);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+        HANDLE_TYPE(   GROUP,    Group, message);
+        HANDLE_TYPE( MESSAGE,  Message, message);
+#undef HANDLE_TYPE
+      }
+    }
+  } else if (!is_cleared) {
+    switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                 \
+      case WireFormatLite::TYPE_##UPPERCASE:                     \
+        WireFormatLite::Write##CAMELCASE(number, VALUE, output); \
+        break
+
+      HANDLE_TYPE(   INT32,    Int32,    int32_value);
+      HANDLE_TYPE(   INT64,    Int64,    int64_value);
+      HANDLE_TYPE(  UINT32,   UInt32,   uint32_value);
+      HANDLE_TYPE(  UINT64,   UInt64,   uint64_value);
+      HANDLE_TYPE(  SINT32,   SInt32,    int32_value);
+      HANDLE_TYPE(  SINT64,   SInt64,    int64_value);
+      HANDLE_TYPE( FIXED32,  Fixed32,   uint32_value);
+      HANDLE_TYPE( FIXED64,  Fixed64,   uint64_value);
+      HANDLE_TYPE(SFIXED32, SFixed32,    int32_value);
+      HANDLE_TYPE(SFIXED64, SFixed64,    int64_value);
+      HANDLE_TYPE(   FLOAT,    Float,    float_value);
+      HANDLE_TYPE(  DOUBLE,   Double,   double_value);
+      HANDLE_TYPE(    BOOL,     Bool,     bool_value);
+      HANDLE_TYPE(  STRING,   String,  *string_value);
+      HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
+      HANDLE_TYPE(    ENUM,     Enum,     enum_value);
+      HANDLE_TYPE(   GROUP,    Group, *message_value);
+#undef HANDLE_TYPE
+      case WireFormatLite::TYPE_MESSAGE:
+        if (is_lazy) {
+          lazymessage_value->WriteMessage(number, output);
+        } else {
+          WireFormatLite::WriteMessage(number, *message_value, output);
+        }
+        break;
+    }
+  }
+}
+
+int ExtensionSet::Extension::ByteSize(int number) const {
+  int result = 0;
+
+  if (is_repeated) {
+    if (is_packed) {
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            result += WireFormatLite::CAMELCASE##Size(                      \
+              repeated_##LOWERCASE##_value->Get(i));                        \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+#undef HANDLE_TYPE
+
+        // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          result += WireFormatLite::k##CAMELCASE##Size *                    \
+                    repeated_##LOWERCASE##_value->size();                   \
+          break
+        HANDLE_TYPE( FIXED32,  Fixed32, uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64, uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,  int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,  int64);
+        HANDLE_TYPE(   FLOAT,    Float,  float);
+        HANDLE_TYPE(  DOUBLE,   Double, double);
+        HANDLE_TYPE(    BOOL,     Bool,   bool);
+#undef HANDLE_TYPE
+
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_BYTES:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
+          GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+          break;
+      }
+
+      cached_size = result;
+      if (result > 0) {
+        result += io::CodedOutputStream::VarintSize32(result);
+        result += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(number,
+                WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+      }
+    } else {
+      int tag_size = WireFormatLite::TagSize(number, real_type(type));
+
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          result += tag_size * repeated_##LOWERCASE##_value->size();        \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            result += WireFormatLite::CAMELCASE##Size(                      \
+              repeated_##LOWERCASE##_value->Get(i));                        \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE(  STRING,   String,  string);
+        HANDLE_TYPE(   BYTES,    Bytes,  string);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+        HANDLE_TYPE(   GROUP,    Group, message);
+        HANDLE_TYPE( MESSAGE,  Message, message);
+#undef HANDLE_TYPE
+
+        // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case WireFormatLite::TYPE_##UPPERCASE:                              \
+          result += (tag_size + WireFormatLite::k##CAMELCASE##Size) *       \
+                    repeated_##LOWERCASE##_value->size();                   \
+          break
+        HANDLE_TYPE( FIXED32,  Fixed32, uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64, uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,  int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,  int64);
+        HANDLE_TYPE(   FLOAT,    Float,  float);
+        HANDLE_TYPE(  DOUBLE,   Double, double);
+        HANDLE_TYPE(    BOOL,     Bool,   bool);
+#undef HANDLE_TYPE
+      }
+    }
+  } else if (!is_cleared) {
+    result += WireFormatLite::TagSize(number, real_type(type));
+    switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                      \
+      case WireFormatLite::TYPE_##UPPERCASE:                              \
+        result += WireFormatLite::CAMELCASE##Size(LOWERCASE);             \
+        break
+
+      HANDLE_TYPE(   INT32,    Int32,    int32_value);
+      HANDLE_TYPE(   INT64,    Int64,    int64_value);
+      HANDLE_TYPE(  UINT32,   UInt32,   uint32_value);
+      HANDLE_TYPE(  UINT64,   UInt64,   uint64_value);
+      HANDLE_TYPE(  SINT32,   SInt32,    int32_value);
+      HANDLE_TYPE(  SINT64,   SInt64,    int64_value);
+      HANDLE_TYPE(  STRING,   String,  *string_value);
+      HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
+      HANDLE_TYPE(    ENUM,     Enum,     enum_value);
+      HANDLE_TYPE(   GROUP,    Group, *message_value);
+#undef HANDLE_TYPE
+      case WireFormatLite::TYPE_MESSAGE: {
+        if (is_lazy) {
+          int size = lazymessage_value->ByteSize();
+          result += io::CodedOutputStream::VarintSize32(size) + size;
+        } else {
+          result += WireFormatLite::MessageSize(*message_value);
+        }
+        break;
+      }
+
+      // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE)                                 \
+      case WireFormatLite::TYPE_##UPPERCASE:                              \
+        result += WireFormatLite::k##CAMELCASE##Size;                     \
+        break
+      HANDLE_TYPE( FIXED32,  Fixed32);
+      HANDLE_TYPE( FIXED64,  Fixed64);
+      HANDLE_TYPE(SFIXED32, SFixed32);
+      HANDLE_TYPE(SFIXED64, SFixed64);
+      HANDLE_TYPE(   FLOAT,    Float);
+      HANDLE_TYPE(  DOUBLE,   Double);
+      HANDLE_TYPE(    BOOL,     Bool);
+#undef HANDLE_TYPE
+    }
+  }
+
+  return result;
+}
+
+int ExtensionSet::Extension::GetSize() const {
+  GOOGLE_DCHECK(is_repeated);
+  switch (cpp_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                        \
+    case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
+      return repeated_##LOWERCASE##_value->size()
+
+    HANDLE_TYPE(  INT32,   int32);
+    HANDLE_TYPE(  INT64,   int64);
+    HANDLE_TYPE( UINT32,  uint32);
+    HANDLE_TYPE( UINT64,  uint64);
+    HANDLE_TYPE(  FLOAT,   float);
+    HANDLE_TYPE( DOUBLE,  double);
+    HANDLE_TYPE(   BOOL,    bool);
+    HANDLE_TYPE(   ENUM,    enum);
+    HANDLE_TYPE( STRING,  string);
+    HANDLE_TYPE(MESSAGE, message);
+#undef HANDLE_TYPE
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return 0;
+}
+
+// This function deletes all allocated objects. This function should be only
+// called if the Extension was created with an arena.
+void ExtensionSet::Extension::Free() {
+  if (is_repeated) {
+    switch (cpp_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
+      case WireFormatLite::CPPTYPE_##UPPERCASE:                    \
+        delete repeated_##LOWERCASE##_value;                       \
+        break
+
+      HANDLE_TYPE(  INT32,   int32);
+      HANDLE_TYPE(  INT64,   int64);
+      HANDLE_TYPE( UINT32,  uint32);
+      HANDLE_TYPE( UINT64,  uint64);
+      HANDLE_TYPE(  FLOAT,   float);
+      HANDLE_TYPE( DOUBLE,  double);
+      HANDLE_TYPE(   BOOL,    bool);
+      HANDLE_TYPE(   ENUM,    enum);
+      HANDLE_TYPE( STRING,  string);
+      HANDLE_TYPE(MESSAGE, message);
+#undef HANDLE_TYPE
+    }
+  } else {
+    switch (cpp_type(type)) {
+      case WireFormatLite::CPPTYPE_STRING:
+        delete string_value;
+        break;
+      case WireFormatLite::CPPTYPE_MESSAGE:
+        if (is_lazy) {
+          delete lazymessage_value;
+        } else {
+          delete message_value;
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const
+
+// ==================================================================
+// Default repeated field instances for iterator-compatible accessors
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_);
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_);
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_);
+
+void RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields() {
+  default_repeated_field_int32_ = new RepeatedField<int32>;
+  default_repeated_field_int64_ = new RepeatedField<int64>;
+  default_repeated_field_uint32_ = new RepeatedField<uint32>;
+  default_repeated_field_uint64_ = new RepeatedField<uint64>;
+  default_repeated_field_double_ = new RepeatedField<double>;
+  default_repeated_field_float_ = new RepeatedField<float>;
+  default_repeated_field_bool_ = new RepeatedField<bool>;
+  OnShutdown(&DestroyDefaultRepeatedFields);
+}
+
+void RepeatedPrimitiveGenericTypeTraits::DestroyDefaultRepeatedFields() {
+  delete default_repeated_field_int32_;
+  delete default_repeated_field_int64_;
+  delete default_repeated_field_uint32_;
+  delete default_repeated_field_uint64_;
+  delete default_repeated_field_double_;
+  delete default_repeated_field_float_;
+  delete default_repeated_field_bool_;
+}
+
+void RepeatedStringTypeTraits::InitializeDefaultRepeatedFields() {
+  default_repeated_field_ = new RepeatedFieldType;
+  OnShutdown(&DestroyDefaultRepeatedFields);
+}
+
+void RepeatedStringTypeTraits::DestroyDefaultRepeatedFields() {
+  delete default_repeated_field_;
+}
+
+void RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields() {
+  default_repeated_field_ = new RepeatedFieldType;
+  OnShutdown(&DestroyDefaultRepeatedFields);
+}
+
+void RepeatedMessageGenericTypeTraits::DestroyDefaultRepeatedFields() {
+  delete default_repeated_field_;
+}
+
+const RepeatedField<int32>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = NULL;
+const RepeatedField<int64>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = NULL;
+const RepeatedField<uint32>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = NULL;
+const RepeatedField<uint64>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = NULL;
+const RepeatedField<double>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = NULL;
+const RepeatedField<float>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = NULL;
+const RepeatedField<bool>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = NULL;
+const RepeatedStringTypeTraits::RepeatedFieldType*
+RepeatedStringTypeTraits::default_repeated_field_ = NULL;
+const RepeatedMessageGenericTypeTraits::RepeatedFieldType*
+RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL;
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/extension_set.h b/src/third_party/protobuf-3/src/google/protobuf/extension_set.h
new file mode 100644
index 0000000..bca179b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/extension_set.h
@@ -0,0 +1,1266 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__
+#define GOOGLE_PROTOBUF_EXTENSION_SET_H__
+
+#include <vector>
+#include <map>
+#include <utility>
+#include <string>
+
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/once.h>
+
+#include <google/protobuf/repeated_field.h>
+
+namespace google {
+
+namespace protobuf {
+  class Arena;
+  class Descriptor;                                    // descriptor.h
+  class FieldDescriptor;                               // descriptor.h
+  class DescriptorPool;                                // descriptor.h
+  class MessageLite;                                   // message_lite.h
+  class Message;                                       // message.h
+  class MessageFactory;                                // message.h
+  class UnknownFieldSet;                               // unknown_field_set.h
+  namespace io {
+    class CodedInputStream;                              // coded_stream.h
+    class CodedOutputStream;                             // coded_stream.h
+  }
+  namespace internal {
+    class FieldSkipper;                                  // wire_format_lite.h
+  }
+}
+
+namespace protobuf {
+namespace internal {
+
+// Used to store values of type WireFormatLite::FieldType without having to
+// #include wire_format_lite.h.  Also, ensures that we use only one byte to
+// store these values, which is important to keep the layout of
+// ExtensionSet::Extension small.
+typedef uint8 FieldType;
+
+// A function which, given an integer value, returns true if the number
+// matches one of the defined values for the corresponding enum type.  This
+// is used with RegisterEnumExtension, below.
+typedef bool EnumValidityFunc(int number);
+
+// Version of the above which takes an argument.  This is needed to deal with
+// extensions that are not compiled in.
+typedef bool EnumValidityFuncWithArg(const void* arg, int number);
+
+// Information about a registered extension.
+struct ExtensionInfo {
+  inline ExtensionInfo() {}
+  inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked)
+      : type(type_param), is_repeated(isrepeated), is_packed(ispacked),
+        descriptor(NULL) {}
+
+  FieldType type;
+  bool is_repeated;
+  bool is_packed;
+
+  struct EnumValidityCheck {
+    EnumValidityFuncWithArg* func;
+    const void* arg;
+  };
+
+  union {
+    EnumValidityCheck enum_validity_check;
+    const MessageLite* message_prototype;
+  };
+
+  // The descriptor for this extension, if one exists and is known.  May be
+  // NULL.  Must not be NULL if the descriptor for the extension does not
+  // live in the same pool as the descriptor for the containing type.
+  const FieldDescriptor* descriptor;
+};
+
+// Abstract interface for an object which looks up extension definitions.  Used
+// when parsing.
+class LIBPROTOBUF_EXPORT ExtensionFinder {
+ public:
+  virtual ~ExtensionFinder();
+
+  // Find the extension with the given containing type and number.
+  virtual bool Find(int number, ExtensionInfo* output) = 0;
+};
+
+// Implementation of ExtensionFinder which finds extensions defined in .proto
+// files which have been compiled into the binary.
+class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
+ public:
+  GeneratedExtensionFinder(const MessageLite* containing_type)
+      : containing_type_(containing_type) {}
+  virtual ~GeneratedExtensionFinder() {}
+
+  // Returns true and fills in *output if found, otherwise returns false.
+  virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+  const MessageLite* containing_type_;
+};
+
+// A FieldSkipper used for parsing MessageSet.
+class MessageSetFieldSkipper;
+
+// Note:  extension_set_heavy.cc defines DescriptorPoolExtensionFinder for
+// finding extensions from a DescriptorPool.
+
+// This is an internal helper class intended for use within the protocol buffer
+// library and generated classes.  Clients should not use it directly.  Instead,
+// use the generated accessors such as GetExtension() of the class being
+// extended.
+//
+// This class manages extensions for a protocol message object.  The
+// message's HasExtension(), GetExtension(), MutableExtension(), and
+// ClearExtension() methods are just thin wrappers around the embedded
+// ExtensionSet.  When parsing, if a tag number is encountered which is
+// inside one of the message type's extension ranges, the tag is passed
+// off to the ExtensionSet for parsing.  Etc.
+class LIBPROTOBUF_EXPORT ExtensionSet {
+ public:
+  ExtensionSet();
+  explicit ExtensionSet(::google::protobuf::Arena* arena);
+  ~ExtensionSet();
+
+  // These are called at startup by protocol-compiler-generated code to
+  // register known extensions.  The registrations are used by ParseField()
+  // to look up extensions for parsed field numbers.  Note that dynamic parsing
+  // does not use ParseField(); only protocol-compiler-generated parsing
+  // methods do.
+  static void RegisterExtension(const MessageLite* containing_type,
+                                int number, FieldType type,
+                                bool is_repeated, bool is_packed);
+  static void RegisterEnumExtension(const MessageLite* containing_type,
+                                    int number, FieldType type,
+                                    bool is_repeated, bool is_packed,
+                                    EnumValidityFunc* is_valid);
+  static void RegisterMessageExtension(const MessageLite* containing_type,
+                                       int number, FieldType type,
+                                       bool is_repeated, bool is_packed,
+                                       const MessageLite* prototype);
+
+  // =================================================================
+
+  // Add all fields which are currently present to the given vector.  This
+  // is useful to implement Reflection::ListFields().
+  void AppendToList(const Descriptor* containing_type,
+                    const DescriptorPool* pool,
+                    std::vector<const FieldDescriptor*>* output) const;
+
+  // =================================================================
+  // Accessors
+  //
+  // Generated message classes include type-safe templated wrappers around
+  // these methods.  Generally you should use those rather than call these
+  // directly, unless you are doing low-level memory management.
+  //
+  // When calling any of these accessors, the extension number requested
+  // MUST exist in the DescriptorPool provided to the constructor.  Otherwise,
+  // the method will fail an assert.  Normally, though, you would not call
+  // these directly; you would either call the generated accessors of your
+  // message class (e.g. GetExtension()) or you would call the accessors
+  // of the reflection interface.  In both cases, it is impossible to
+  // trigger this assert failure:  the generated accessors only accept
+  // linked-in extension types as parameters, while the Reflection interface
+  // requires you to provide the FieldDescriptor describing the extension.
+  //
+  // When calling any of these accessors, a protocol-compiler-generated
+  // implementation of the extension corresponding to the number MUST
+  // be linked in, and the FieldDescriptor used to refer to it MUST be
+  // the one generated by that linked-in code.  Otherwise, the method will
+  // die on an assert failure.  The message objects returned by the message
+  // accessors are guaranteed to be of the correct linked-in type.
+  //
+  // These methods pretty much match Reflection except that:
+  // - They're not virtual.
+  // - They identify fields by number rather than FieldDescriptors.
+  // - They identify enum values using integers rather than descriptors.
+  // - Strings provide Mutable() in addition to Set() accessors.
+
+  bool Has(int number) const;
+  int ExtensionSize(int number) const;   // Size of a repeated extension.
+  int NumExtensions() const;  // The number of extensions
+  FieldType ExtensionType(int number) const;
+  void ClearExtension(int number);
+
+  // singular fields -------------------------------------------------
+
+  int32  GetInt32 (int number, int32  default_value) const;
+  int64  GetInt64 (int number, int64  default_value) const;
+  uint32 GetUInt32(int number, uint32 default_value) const;
+  uint64 GetUInt64(int number, uint64 default_value) const;
+  float  GetFloat (int number, float  default_value) const;
+  double GetDouble(int number, double default_value) const;
+  bool   GetBool  (int number, bool   default_value) const;
+  int    GetEnum  (int number, int    default_value) const;
+  const string & GetString (int number, const string&  default_value) const;
+  const MessageLite& GetMessage(int number,
+                                const MessageLite& default_value) const;
+  const MessageLite& GetMessage(int number, const Descriptor* message_type,
+                                MessageFactory* factory) const;
+
+  // |descriptor| may be NULL so long as it is known that the descriptor for
+  // the extension lives in the same pool as the descriptor for the containing
+  // type.
+#define desc const FieldDescriptor* descriptor  // avoid line wrapping
+  void SetInt32 (int number, FieldType type, int32  value, desc);
+  void SetInt64 (int number, FieldType type, int64  value, desc);
+  void SetUInt32(int number, FieldType type, uint32 value, desc);
+  void SetUInt64(int number, FieldType type, uint64 value, desc);
+  void SetFloat (int number, FieldType type, float  value, desc);
+  void SetDouble(int number, FieldType type, double value, desc);
+  void SetBool  (int number, FieldType type, bool   value, desc);
+  void SetEnum  (int number, FieldType type, int    value, desc);
+  void SetString(int number, FieldType type, const string& value, desc);
+  string * MutableString (int number, FieldType type, desc);
+  MessageLite* MutableMessage(int number, FieldType type,
+                              const MessageLite& prototype, desc);
+  MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
+                              MessageFactory* factory);
+  // Adds the given message to the ExtensionSet, taking ownership of the
+  // message object. Existing message with the same number will be deleted.
+  // If "message" is NULL, this is equivalent to "ClearExtension(number)".
+  void SetAllocatedMessage(int number, FieldType type,
+                           const FieldDescriptor* descriptor,
+                           MessageLite* message);
+  void UnsafeArenaSetAllocatedMessage(int number, FieldType type,
+                                      const FieldDescriptor* descriptor,
+                                      MessageLite* message);
+  MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+  MessageLite* UnsafeArenaReleaseMessage(
+      int number, const MessageLite& prototype);
+
+  MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
+                              MessageFactory* factory);
+#undef desc
+  ::google::protobuf::Arena* GetArenaNoVirtual() const { return arena_; }
+
+  // repeated fields -------------------------------------------------
+
+  // Fetches a RepeatedField extension by number; returns |default_value|
+  // if no such extension exists. User should not touch this directly; it is
+  // used by the GetRepeatedExtension() method.
+  const void* GetRawRepeatedField(int number, const void* default_value) const;
+  // Fetches a mutable version of a RepeatedField extension by number,
+  // instantiating one if none exists. Similar to above, user should not use
+  // this directly; it underlies MutableRepeatedExtension().
+  void* MutableRawRepeatedField(int number, FieldType field_type,
+                                bool packed, const FieldDescriptor* desc);
+
+  // This is an overload of MutableRawRepeatedField to maintain compatibility
+  // with old code using a previous API. This version of
+  // MutableRawRepeatedField() will GOOGLE_CHECK-fail on a missing extension.
+  // (E.g.: borg/clients/internal/proto1/proto2_reflection.cc.)
+  void* MutableRawRepeatedField(int number);
+
+  int32  GetRepeatedInt32 (int number, int index) const;
+  int64  GetRepeatedInt64 (int number, int index) const;
+  uint32 GetRepeatedUInt32(int number, int index) const;
+  uint64 GetRepeatedUInt64(int number, int index) const;
+  float  GetRepeatedFloat (int number, int index) const;
+  double GetRepeatedDouble(int number, int index) const;
+  bool   GetRepeatedBool  (int number, int index) const;
+  int    GetRepeatedEnum  (int number, int index) const;
+  const string & GetRepeatedString (int number, int index) const;
+  const MessageLite& GetRepeatedMessage(int number, int index) const;
+
+  void SetRepeatedInt32 (int number, int index, int32  value);
+  void SetRepeatedInt64 (int number, int index, int64  value);
+  void SetRepeatedUInt32(int number, int index, uint32 value);
+  void SetRepeatedUInt64(int number, int index, uint64 value);
+  void SetRepeatedFloat (int number, int index, float  value);
+  void SetRepeatedDouble(int number, int index, double value);
+  void SetRepeatedBool  (int number, int index, bool   value);
+  void SetRepeatedEnum  (int number, int index, int    value);
+  void SetRepeatedString(int number, int index, const string& value);
+  string * MutableRepeatedString (int number, int index);
+  MessageLite* MutableRepeatedMessage(int number, int index);
+
+#define desc const FieldDescriptor* descriptor  // avoid line wrapping
+  void AddInt32 (int number, FieldType type, bool packed, int32  value, desc);
+  void AddInt64 (int number, FieldType type, bool packed, int64  value, desc);
+  void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
+  void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
+  void AddFloat (int number, FieldType type, bool packed, float  value, desc);
+  void AddDouble(int number, FieldType type, bool packed, double value, desc);
+  void AddBool  (int number, FieldType type, bool packed, bool   value, desc);
+  void AddEnum  (int number, FieldType type, bool packed, int    value, desc);
+  void AddString(int number, FieldType type, const string& value, desc);
+  string * AddString (int number, FieldType type, desc);
+  MessageLite* AddMessage(int number, FieldType type,
+                          const MessageLite& prototype, desc);
+  MessageLite* AddMessage(const FieldDescriptor* descriptor,
+                          MessageFactory* factory);
+  void AddAllocatedMessage(const FieldDescriptor* descriptor,
+                           MessageLite* new_entry);
+#undef desc
+
+  void RemoveLast(int number);
+  MessageLite* ReleaseLast(int number);
+  void SwapElements(int number, int index1, int index2);
+
+  // -----------------------------------------------------------------
+  // TODO(kenton):  Hardcore memory management accessors
+
+  // =================================================================
+  // convenience methods for implementing methods of Message
+  //
+  // These could all be implemented in terms of the other methods of this
+  // class, but providing them here helps keep the generated code size down.
+
+  void Clear();
+  void MergeFrom(const ExtensionSet& other);
+  void Swap(ExtensionSet* other);
+  void SwapExtension(ExtensionSet* other, int number);
+  bool IsInitialized() const;
+
+  // Parses a single extension from the input. The input should start out
+  // positioned immediately after the tag.
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  ExtensionFinder* extension_finder,
+                  FieldSkipper* field_skipper);
+
+  // Specific versions for lite or full messages (constructs the appropriate
+  // FieldSkipper automatically).  |containing_type| is the default
+  // instance for the containing message; it is used only to look up the
+  // extension by number.  See RegisterExtension(), above.  Unlike the other
+  // methods of ExtensionSet, this only works for generated message types --
+  // it looks up extensions registered using RegisterExtension().
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  const MessageLite* containing_type);
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  const Message* containing_type,
+                  UnknownFieldSet* unknown_fields);
+  bool ParseField(uint32 tag, io::CodedInputStream* input,
+                  const MessageLite* containing_type,
+                  io::CodedOutputStream* unknown_fields);
+
+  // Parse an entire message in MessageSet format.  Such messages have no
+  // fields, only extensions.
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       ExtensionFinder* extension_finder,
+                       MessageSetFieldSkipper* field_skipper);
+
+  // Specific versions for lite or full messages (constructs the appropriate
+  // FieldSkipper automatically).
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       const MessageLite* containing_type);
+  bool ParseMessageSet(io::CodedInputStream* input,
+                       const Message* containing_type,
+                       UnknownFieldSet* unknown_fields);
+
+  // Write all extension fields with field numbers in the range
+  //   [start_field_number, end_field_number)
+  // to the output stream, using the cached sizes computed when ByteSize() was
+  // last called.  Note that the range bounds are inclusive-exclusive.
+  void SerializeWithCachedSizes(int start_field_number,
+                                int end_field_number,
+                                io::CodedOutputStream* output) const;
+
+  // Same as SerializeWithCachedSizes, but without any bounds checking.
+  // The caller must ensure that target has sufficient capacity for the
+  // serialized extensions.
+  //
+  // Returns a pointer past the last written byte.
+  uint8* SerializeWithCachedSizesToArray(int start_field_number,
+                                         int end_field_number,
+                                         uint8* target) const;
+
+  // Like above but serializes in MessageSet format.
+  void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
+  uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
+
+  // Returns the total serialized size of all the extensions.
+  int ByteSize() const;
+
+  // Like ByteSize() but uses MessageSet format.
+  int MessageSetByteSize() const;
+
+  // Returns (an estimate of) the total number of bytes used for storing the
+  // extensions in memory, excluding sizeof(*this).  If the ExtensionSet is
+  // for a lite message (and thus possibly contains lite messages), the results
+  // are undefined (might work, might crash, might corrupt data, might not even
+  // be linked in).  It's up to the protocol compiler to avoid calling this on
+  // such ExtensionSets (easy enough since lite messages don't implement
+  // SpaceUsed()).
+  int SpaceUsedExcludingSelf() const;
+
+ private:
+
+  // Interface of a lazily parsed singular message extension.
+  class LIBPROTOBUF_EXPORT LazyMessageExtension {
+   public:
+    LazyMessageExtension() {}
+    virtual ~LazyMessageExtension() {}
+
+    virtual LazyMessageExtension* New(::google::protobuf::Arena* arena) const = 0;
+    virtual const MessageLite& GetMessage(
+        const MessageLite& prototype) const = 0;
+    virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
+    virtual void SetAllocatedMessage(MessageLite *message) = 0;
+    virtual void UnsafeArenaSetAllocatedMessage(MessageLite *message) = 0;
+    virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+    virtual MessageLite* UnsafeArenaReleaseMessage(
+        const MessageLite& prototype) = 0;
+
+    virtual bool IsInitialized() const = 0;
+    virtual int ByteSize() const = 0;
+    virtual int SpaceUsed() const = 0;
+
+    virtual void MergeFrom(const LazyMessageExtension& other) = 0;
+    virtual void Clear() = 0;
+
+    virtual bool ReadMessage(const MessageLite& prototype,
+                             io::CodedInputStream* input) = 0;
+    virtual void WriteMessage(int number,
+                              io::CodedOutputStream* output) const = 0;
+    virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0;
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
+  };
+  struct Extension {
+    // The order of these fields packs Extension into 24 bytes when using 8
+    // byte alignment. Consider this when adding or removing fields here.
+    union {
+      int32                 int32_value;
+      int64                 int64_value;
+      uint32                uint32_value;
+      uint64                uint64_value;
+      float                 float_value;
+      double                double_value;
+      bool                  bool_value;
+      int                   enum_value;
+      string*               string_value;
+      MessageLite*          message_value;
+      LazyMessageExtension* lazymessage_value;
+
+      RepeatedField   <int32      >* repeated_int32_value;
+      RepeatedField   <int64      >* repeated_int64_value;
+      RepeatedField   <uint32     >* repeated_uint32_value;
+      RepeatedField   <uint64     >* repeated_uint64_value;
+      RepeatedField   <float      >* repeated_float_value;
+      RepeatedField   <double     >* repeated_double_value;
+      RepeatedField   <bool       >* repeated_bool_value;
+      RepeatedField   <int        >* repeated_enum_value;
+      RepeatedPtrField<string     >* repeated_string_value;
+      RepeatedPtrField<MessageLite>* repeated_message_value;
+    };
+
+    FieldType type;
+    bool is_repeated;
+
+    // For singular types, indicates if the extension is "cleared".  This
+    // happens when an extension is set and then later cleared by the caller.
+    // We want to keep the Extension object around for reuse, so instead of
+    // removing it from the map, we just set is_cleared = true.  This has no
+    // meaning for repeated types; for those, the size of the RepeatedField
+    // simply becomes zero when cleared.
+    bool is_cleared : 4;
+
+    // For singular message types, indicates whether lazy parsing is enabled
+    // for this extension. This field is only valid when type == TYPE_MESSAGE
+    // and !is_repeated because we only support lazy parsing for singular
+    // message types currently. If is_lazy = true, the extension is stored in
+    // lazymessage_value. Otherwise, the extension will be message_value.
+    bool is_lazy : 4;
+
+    // For repeated types, this indicates if the [packed=true] option is set.
+    bool is_packed;
+
+    // For packed fields, the size of the packed data is recorded here when
+    // ByteSize() is called then used during serialization.
+    // TODO(kenton):  Use atomic<int> when C++ supports it.
+    mutable int cached_size;
+
+    // The descriptor for this extension, if one exists and is known.  May be
+    // NULL.  Must not be NULL if the descriptor for the extension does not
+    // live in the same pool as the descriptor for the containing type.
+    const FieldDescriptor* descriptor;
+
+    // Some helper methods for operations on a single Extension.
+    void SerializeFieldWithCachedSizes(
+        int number,
+        io::CodedOutputStream* output) const;
+    uint8* SerializeFieldWithCachedSizesToArray(
+        int number,
+        uint8* target) const;
+    void SerializeMessageSetItemWithCachedSizes(
+        int number,
+        io::CodedOutputStream* output) const;
+    uint8* SerializeMessageSetItemWithCachedSizesToArray(
+        int number,
+        uint8* target) const;
+    int ByteSize(int number) const;
+    int MessageSetItemByteSize(int number) const;
+    void Clear();
+    int GetSize() const;
+    void Free();
+    int SpaceUsedExcludingSelf() const;
+  };
+
+
+  // Merges existing Extension from other_extension
+  void InternalExtensionMergeFrom(int number, const Extension& other_extension);
+
+  // Returns true and fills field_number and extension if extension is found.
+  // Note to support packed repeated field compatibility, it also fills whether
+  // the tag on wire is packed, which can be different from
+  // extension->is_packed (whether packed=true is specified).
+  bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder,
+                                int* field_number, ExtensionInfo* extension,
+                                bool* was_packed_on_wire);
+
+  // Returns true and fills extension if extension is found.
+  // Note to support packed repeated field compatibility, it also fills whether
+  // the tag on wire is packed, which can be different from
+  // extension->is_packed (whether packed=true is specified).
+  bool FindExtensionInfoFromFieldNumber(int wire_type, int field_number,
+                                        ExtensionFinder* extension_finder,
+                                        ExtensionInfo* extension,
+                                        bool* was_packed_on_wire);
+
+  // Parses a single extension from the input. The input should start out
+  // positioned immediately after the wire tag. This method is called in
+  // ParseField() after field number and was_packed_on_wire is extracted from
+  // the wire tag and ExtensionInfo is found by the field number.
+  bool ParseFieldWithExtensionInfo(int field_number,
+                                   bool was_packed_on_wire,
+                                   const ExtensionInfo& extension,
+                                   io::CodedInputStream* input,
+                                   FieldSkipper* field_skipper);
+
+  // Like ParseField(), but this method may parse singular message extensions
+  // lazily depending on the value of FLAGS_eagerly_parse_message_sets.
+  bool ParseFieldMaybeLazily(int wire_type, int field_number,
+                             io::CodedInputStream* input,
+                             ExtensionFinder* extension_finder,
+                             MessageSetFieldSkipper* field_skipper);
+
+  // Gets the extension with the given number, creating it if it does not
+  // already exist.  Returns true if the extension did not already exist.
+  bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
+                         Extension** result);
+
+  // Gets the repeated extension for the given descriptor, creating it if
+  // it does not exist.
+  Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor);
+
+  // Parse a single MessageSet item -- called just after the item group start
+  // tag has been read.
+  bool ParseMessageSetItem(io::CodedInputStream* input,
+                           ExtensionFinder* extension_finder,
+                           MessageSetFieldSkipper* field_skipper);
+
+  // Hack:  RepeatedPtrFieldBase declares ExtensionSet as a friend.  This
+  //   friendship should automatically extend to ExtensionSet::Extension, but
+  //   unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
+  //   correctly.  So, we must provide helpers for calling methods of that
+  //   class.
+
+  // Defined in extension_set_heavy.cc.
+  static inline int RepeatedMessage_SpaceUsedExcludingSelf(
+      RepeatedPtrFieldBase* field);
+
+  // The Extension struct is small enough to be passed by value, so we use it
+  // directly as the value type in the map rather than use pointers.  We use
+  // a map rather than hash_map here because we expect most ExtensionSets will
+  // only contain a small number of extensions whereas hash_map is optimized
+  // for 100 elements or more.  Also, we want AppendToList() to order fields
+  // by field number.
+  std::map<int, Extension> extensions_;
+  ::google::protobuf::Arena* arena_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
+};
+
+// These are just for convenience...
+inline void ExtensionSet::SetString(int number, FieldType type,
+                                    const string& value,
+                                    const FieldDescriptor* descriptor) {
+  MutableString(number, type, descriptor)->assign(value);
+}
+inline void ExtensionSet::SetRepeatedString(int number, int index,
+                                            const string& value) {
+  MutableRepeatedString(number, index)->assign(value);
+}
+inline void ExtensionSet::AddString(int number, FieldType type,
+                                    const string& value,
+                                    const FieldDescriptor* descriptor) {
+  AddString(number, type, descriptor)->assign(value);
+}
+
+// ===================================================================
+// Glue for generated extension accessors
+
+// -------------------------------------------------------------------
+// Template magic
+
+// First we have a set of classes representing "type traits" for different
+// field types.  A type traits class knows how to implement basic accessors
+// for extensions of a particular type given an ExtensionSet.  The signature
+// for a type traits class looks like this:
+//
+//   class TypeTraits {
+//    public:
+//     typedef ? ConstType;
+//     typedef ? MutableType;
+//     // TypeTraits for singular fields and repeated fields will define the
+//     // symbol "Singular" or "Repeated" respectively. These two symbols will
+//     // be used in extension accessors to distinguish between singular
+//     // extensions and repeated extensions. If the TypeTraits for the passed
+//     // in extension doesn't have the expected symbol defined, it means the
+//     // user is passing a repeated extension to a singular accessor, or the
+//     // opposite. In that case the C++ compiler will generate an error
+//     // message "no matching member function" to inform the user.
+//     typedef ? Singular
+//     typedef ? Repeated
+//
+//     static inline ConstType Get(int number, const ExtensionSet& set);
+//     static inline void Set(int number, ConstType value, ExtensionSet* set);
+//     static inline MutableType Mutable(int number, ExtensionSet* set);
+//
+//     // Variants for repeated fields.
+//     static inline ConstType Get(int number, const ExtensionSet& set,
+//                                 int index);
+//     static inline void Set(int number, int index,
+//                            ConstType value, ExtensionSet* set);
+//     static inline MutableType Mutable(int number, int index,
+//                                       ExtensionSet* set);
+//     static inline void Add(int number, ConstType value, ExtensionSet* set);
+//     static inline MutableType Add(int number, ExtensionSet* set);
+//   };
+//
+// Not all of these methods make sense for all field types.  For example, the
+// "Mutable" methods only make sense for strings and messages, and the
+// repeated methods only make sense for repeated types.  So, each type
+// traits class implements only the set of methods from this signature that it
+// actually supports.  This will cause a compiler error if the user tries to
+// access an extension using a method that doesn't make sense for its type.
+// For example, if "foo" is an extension of type "optional int32", then if you
+// try to write code like:
+//   my_message.MutableExtension(foo)
+// you will get a compile error because PrimitiveTypeTraits<int32> does not
+// have a "Mutable()" method.
+
+// -------------------------------------------------------------------
+// PrimitiveTypeTraits
+
+// Since the ExtensionSet has different methods for each primitive type,
+// we must explicitly define the methods of the type traits class for each
+// known type.
+template <typename Type>
+class PrimitiveTypeTraits {
+ public:
+  typedef Type ConstType;
+  typedef Type MutableType;
+  typedef PrimitiveTypeTraits<Type> Singular;
+
+  static inline ConstType Get(int number, const ExtensionSet& set,
+                              ConstType default_value);
+  static inline void Set(int number, FieldType field_type,
+                         ConstType value, ExtensionSet* set);
+};
+
+template <typename Type>
+class RepeatedPrimitiveTypeTraits {
+ public:
+  typedef Type ConstType;
+  typedef Type MutableType;
+  typedef RepeatedPrimitiveTypeTraits<Type> Repeated;
+
+  typedef RepeatedField<Type> RepeatedFieldType;
+
+  static inline Type Get(int number, const ExtensionSet& set, int index);
+  static inline void Set(int number, int index, Type value, ExtensionSet* set);
+  static inline void Add(int number, FieldType field_type,
+                         bool is_packed, Type value, ExtensionSet* set);
+
+  static inline const RepeatedField<ConstType>&
+      GetRepeated(int number, const ExtensionSet& set);
+  static inline RepeatedField<Type>*
+      MutableRepeated(int number, FieldType field_type,
+                      bool is_packed, ExtensionSet* set);
+
+  static const RepeatedFieldType* GetDefaultRepeatedField();
+};
+
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_;
+
+class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits {
+ private:
+  template<typename Type> friend class RepeatedPrimitiveTypeTraits;
+  static void InitializeDefaultRepeatedFields();
+  static void DestroyDefaultRepeatedFields();
+  static const RepeatedField<int32>* default_repeated_field_int32_;
+  static const RepeatedField<int64>* default_repeated_field_int64_;
+  static const RepeatedField<uint32>* default_repeated_field_uint32_;
+  static const RepeatedField<uint64>* default_repeated_field_uint64_;
+  static const RepeatedField<double>* default_repeated_field_double_;
+  static const RepeatedField<float>* default_repeated_field_float_;
+  static const RepeatedField<bool>* default_repeated_field_bool_;
+};
+
+#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD)                       \
+template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get(                     \
+    int number, const ExtensionSet& set, TYPE default_value) {             \
+  return set.Get##METHOD(number, default_value);                           \
+}                                                                          \
+template<> inline void PrimitiveTypeTraits<TYPE>::Set(                     \
+    int number, FieldType field_type, TYPE value, ExtensionSet* set) {     \
+  set->Set##METHOD(number, field_type, value, NULL);                       \
+}                                                                          \
+                                                                           \
+template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get(             \
+    int number, const ExtensionSet& set, int index) {                      \
+  return set.GetRepeated##METHOD(number, index);                           \
+}                                                                          \
+template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set(             \
+    int number, int index, TYPE value, ExtensionSet* set) {                \
+  set->SetRepeated##METHOD(number, index, value);                          \
+}                                                                          \
+template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add(             \
+    int number, FieldType field_type, bool is_packed,                      \
+    TYPE value, ExtensionSet* set) {                                       \
+  set->Add##METHOD(number, field_type, is_packed, value, NULL);            \
+}                                                                          \
+template<> inline const RepeatedField<TYPE>*                               \
+    RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() {         \
+  ::google::protobuf::GoogleOnceInit(                                                          \
+      &repeated_primitive_generic_type_traits_once_init_,                  \
+      &RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
+  return RepeatedPrimitiveGenericTypeTraits::                              \
+      default_repeated_field_##TYPE##_;                                    \
+}                                                                          \
+template<> inline const RepeatedField<TYPE>&                               \
+    RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number,             \
+                                               const ExtensionSet& set) {  \
+  return *reinterpret_cast<const RepeatedField<TYPE>*>(                    \
+                            set.GetRawRepeatedField(                       \
+                                number, GetDefaultRepeatedField()));       \
+}                                                                          \
+template<> inline RepeatedField<TYPE>*                                     \
+    RepeatedPrimitiveTypeTraits<TYPE>::MutableRepeated(int number,         \
+                                                   FieldType field_type,   \
+                                                   bool is_packed,         \
+                                                   ExtensionSet* set) {    \
+  return reinterpret_cast<RepeatedField<TYPE>*>(                           \
+      set->MutableRawRepeatedField(number, field_type, is_packed, NULL));  \
+}
+
+PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32,  Int32)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64,  Int64)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE( float,  Float)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double)
+PROTOBUF_DEFINE_PRIMITIVE_TYPE(  bool,   Bool)
+
+#undef PROTOBUF_DEFINE_PRIMITIVE_TYPE
+
+// -------------------------------------------------------------------
+// StringTypeTraits
+
+// Strings support both Set() and Mutable().
+class LIBPROTOBUF_EXPORT StringTypeTraits {
+ public:
+  typedef const string& ConstType;
+  typedef string* MutableType;
+  typedef StringTypeTraits Singular;
+
+  static inline const string& Get(int number, const ExtensionSet& set,
+                                  ConstType default_value) {
+    return set.GetString(number, default_value);
+  }
+  static inline void Set(int number, FieldType field_type,
+                         const string& value, ExtensionSet* set) {
+    set->SetString(number, field_type, value, NULL);
+  }
+  static inline string* Mutable(int number, FieldType field_type,
+                                ExtensionSet* set) {
+    return set->MutableString(number, field_type, NULL);
+  }
+};
+
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_string_type_traits_once_init_;
+
+class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
+ public:
+  typedef const string& ConstType;
+  typedef string* MutableType;
+  typedef RepeatedStringTypeTraits Repeated;
+
+  typedef RepeatedPtrField<string> RepeatedFieldType;
+
+  static inline const string& Get(int number, const ExtensionSet& set,
+                                  int index) {
+    return set.GetRepeatedString(number, index);
+  }
+  static inline void Set(int number, int index,
+                         const string& value, ExtensionSet* set) {
+    set->SetRepeatedString(number, index, value);
+  }
+  static inline string* Mutable(int number, int index, ExtensionSet* set) {
+    return set->MutableRepeatedString(number, index);
+  }
+  static inline void Add(int number, FieldType field_type,
+                         bool /*is_packed*/, const string& value,
+                         ExtensionSet* set) {
+    set->AddString(number, field_type, value, NULL);
+  }
+  static inline string* Add(int number, FieldType field_type,
+                            ExtensionSet* set) {
+    return set->AddString(number, field_type, NULL);
+  }
+  static inline const RepeatedPtrField<string>&
+      GetRepeated(int number, const ExtensionSet& set) {
+    return *reinterpret_cast<const RepeatedPtrField<string>*>(
+        set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+  }
+
+  static inline RepeatedPtrField<string>*
+      MutableRepeated(int number, FieldType field_type,
+                      bool is_packed, ExtensionSet* set) {
+    return reinterpret_cast<RepeatedPtrField<string>*>(
+        set->MutableRawRepeatedField(number, field_type,
+                                     is_packed, NULL));
+  }
+
+  static const RepeatedFieldType* GetDefaultRepeatedField() {
+    ::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_,
+                   &InitializeDefaultRepeatedFields);
+    return default_repeated_field_;
+  }
+
+ private:
+  static void InitializeDefaultRepeatedFields();
+  static void DestroyDefaultRepeatedFields();
+  static const RepeatedFieldType *default_repeated_field_;
+};
+
+// -------------------------------------------------------------------
+// EnumTypeTraits
+
+// ExtensionSet represents enums using integers internally, so we have to
+// static_cast around.
+template <typename Type, bool IsValid(int)>
+class EnumTypeTraits {
+ public:
+  typedef Type ConstType;
+  typedef Type MutableType;
+  typedef EnumTypeTraits<Type, IsValid> Singular;
+
+  static inline ConstType Get(int number, const ExtensionSet& set,
+                              ConstType default_value) {
+    return static_cast<Type>(set.GetEnum(number, default_value));
+  }
+  static inline void Set(int number, FieldType field_type,
+                         ConstType value, ExtensionSet* set) {
+    GOOGLE_DCHECK(IsValid(value));
+    set->SetEnum(number, field_type, value, NULL);
+  }
+};
+
+template <typename Type, bool IsValid(int)>
+class RepeatedEnumTypeTraits {
+ public:
+  typedef Type ConstType;
+  typedef Type MutableType;
+  typedef RepeatedEnumTypeTraits<Type, IsValid> Repeated;
+
+  typedef RepeatedField<Type> RepeatedFieldType;
+
+  static inline ConstType Get(int number, const ExtensionSet& set, int index) {
+    return static_cast<Type>(set.GetRepeatedEnum(number, index));
+  }
+  static inline void Set(int number, int index,
+                         ConstType value, ExtensionSet* set) {
+    GOOGLE_DCHECK(IsValid(value));
+    set->SetRepeatedEnum(number, index, value);
+  }
+  static inline void Add(int number, FieldType field_type,
+                         bool is_packed, ConstType value, ExtensionSet* set) {
+    GOOGLE_DCHECK(IsValid(value));
+    set->AddEnum(number, field_type, is_packed, value, NULL);
+  }
+  static inline const RepeatedField<Type>& GetRepeated(int number,
+                                                       const ExtensionSet&
+                                                       set) {
+    // Hack: the `Extension` struct stores a RepeatedField<int> for enums.
+    // RepeatedField<int> cannot implicitly convert to RepeatedField<EnumType>
+    // so we need to do some casting magic. See message.h for similar
+    // contortions for non-extension fields.
+    return *reinterpret_cast<const RepeatedField<Type>*>(
+        set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+  }
+
+  static inline RepeatedField<Type>* MutableRepeated(int number,
+                                                     FieldType field_type,
+                                                     bool is_packed,
+                                                     ExtensionSet* set) {
+    return reinterpret_cast<RepeatedField<Type>*>(
+        set->MutableRawRepeatedField(number, field_type, is_packed, NULL));
+  }
+
+  static const RepeatedFieldType* GetDefaultRepeatedField() {
+    // Hack: as noted above, repeated enum fields are internally stored as a
+    // RepeatedField<int>. We need to be able to instantiate global static
+    // objects to return as default (empty) repeated fields on non-existent
+    // extensions. We would not be able to know a-priori all of the enum types
+    // (values of |Type|) to instantiate all of these, so we just re-use int32's
+    // default repeated field object.
+    return reinterpret_cast<const RepeatedField<Type>*>(
+        RepeatedPrimitiveTypeTraits<int32>::GetDefaultRepeatedField());
+  }
+};
+
+// -------------------------------------------------------------------
+// MessageTypeTraits
+
+// ExtensionSet guarantees that when manipulating extensions with message
+// types, the implementation used will be the compiled-in class representing
+// that type.  So, we can static_cast down to the exact type we expect.
+template <typename Type>
+class MessageTypeTraits {
+ public:
+  typedef const Type& ConstType;
+  typedef Type* MutableType;
+  typedef MessageTypeTraits<Type> Singular;
+
+  static inline ConstType Get(int number, const ExtensionSet& set,
+                              ConstType default_value) {
+    return static_cast<const Type&>(
+        set.GetMessage(number, default_value));
+  }
+  static inline MutableType Mutable(int number, FieldType field_type,
+                                    ExtensionSet* set) {
+    return static_cast<Type*>(
+      set->MutableMessage(number, field_type, Type::default_instance(), NULL));
+  }
+  static inline void SetAllocated(int number, FieldType field_type,
+                                  MutableType message, ExtensionSet* set) {
+    set->SetAllocatedMessage(number, field_type, NULL, message);
+  }
+  static inline MutableType Release(int number, FieldType /* field_type */,
+                                    ExtensionSet* set) {
+    return static_cast<Type*>(set->ReleaseMessage(
+        number, Type::default_instance()));
+  }
+};
+
+// forward declaration
+class RepeatedMessageGenericTypeTraits;
+
+template <typename Type>
+class RepeatedMessageTypeTraits {
+ public:
+  typedef const Type& ConstType;
+  typedef Type* MutableType;
+  typedef RepeatedMessageTypeTraits<Type> Repeated;
+
+  typedef RepeatedPtrField<Type> RepeatedFieldType;
+
+  static inline ConstType Get(int number, const ExtensionSet& set, int index) {
+    return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
+  }
+  static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
+    return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
+  }
+  static inline MutableType Add(int number, FieldType field_type,
+                                ExtensionSet* set) {
+    return static_cast<Type*>(
+        set->AddMessage(number, field_type, Type::default_instance(), NULL));
+  }
+  static inline const RepeatedPtrField<Type>& GetRepeated(int number,
+                                                          const ExtensionSet&
+                                                          set) {
+    // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same
+    // casting hack applies here, because a RepeatedPtrField<MessageLite>
+    // cannot naturally become a RepeatedPtrType<Type> even though Type is
+    // presumably a message. google::protobuf::Message goes through similar contortions
+    // with a reinterpret_cast<>.
+    return *reinterpret_cast<const RepeatedPtrField<Type>*>(
+        set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+  }
+  static inline RepeatedPtrField<Type>* MutableRepeated(int number,
+                                                        FieldType field_type,
+                                                        bool is_packed,
+                                                        ExtensionSet* set) {
+    return reinterpret_cast<RepeatedPtrField<Type>*>(
+        set->MutableRawRepeatedField(number, field_type, is_packed, NULL));
+  }
+
+  static const RepeatedFieldType* GetDefaultRepeatedField();
+};
+
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_message_generic_type_traits_once_init_;
+
+// This class exists only to hold a generic default empty repeated field for all
+// message-type repeated field extensions.
+class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
+ public:
+  typedef RepeatedPtrField< ::google::protobuf::MessageLite*> RepeatedFieldType;
+ private:
+  template<typename Type> friend class RepeatedMessageTypeTraits;
+  static void InitializeDefaultRepeatedFields();
+  static void DestroyDefaultRepeatedFields();
+  static const RepeatedFieldType* default_repeated_field_;
+};
+
+template<typename Type> inline
+    const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
+    RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
+  ::google::protobuf::GoogleOnceInit(
+      &repeated_message_generic_type_traits_once_init_,
+      &RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
+  return reinterpret_cast<const RepeatedFieldType*>(
+      RepeatedMessageGenericTypeTraits::default_repeated_field_);
+}
+
+// -------------------------------------------------------------------
+// ExtensionIdentifier
+
+// This is the type of actual extension objects.  E.g. if you have:
+//   extends Foo with optional int32 bar = 1234;
+// then "bar" will be defined in C++ as:
+//   ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 1, false> bar(1234);
+//
+// Note that we could, in theory, supply the field number as a template
+// parameter, and thus make an instance of ExtensionIdentifier have no
+// actual contents.  However, if we did that, then using at extension
+// identifier would not necessarily cause the compiler to output any sort
+// of reference to any simple defined in the extension's .pb.o file.  Some
+// linkers will actually drop object files that are not explicitly referenced,
+// but that would be bad because it would cause this extension to not be
+// registered at static initialization, and therefore using it would crash.
+
+template <typename ExtendeeType, typename TypeTraitsType,
+          FieldType field_type, bool is_packed>
+class ExtensionIdentifier {
+ public:
+  typedef TypeTraitsType TypeTraits;
+  typedef ExtendeeType Extendee;
+
+  ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value)
+      : number_(number), default_value_(default_value) {}
+  inline int number() const { return number_; }
+  typename TypeTraits::ConstType default_value() const {
+    return default_value_;
+  }
+
+ private:
+  const int number_;
+  typename TypeTraits::ConstType default_value_;
+};
+
+// -------------------------------------------------------------------
+// Generated accessors
+
+// This macro should be expanded in the context of a generated type which
+// has extensions.
+//
+// We use "_proto_TypeTraits" as a type name below because "TypeTraits"
+// causes problems if the class has a nested message or enum type with that
+// name and "_TypeTraits" is technically reserved for the C++ library since
+// it starts with an underscore followed by a capital letter.
+//
+// For similar reason, we use "_field_type" and "_is_packed" as parameter names
+// below, so that "field_type" and "is_packed" can be used as field names.
+#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME)                        \
+  /* Has, Size, Clear */                                                      \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline bool HasExtension(                                                   \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
+    return _extensions_.Has(id.number());                                     \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void ClearExtension(                                                 \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    _extensions_.ClearExtension(id.number());                                 \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline int ExtensionSize(                                                   \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
+    return _extensions_.ExtensionSize(id.number());                           \
+  }                                                                           \
+                                                                              \
+  /* Singular accessors */                                                    \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Singular::ConstType GetExtension(        \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
+    return _proto_TypeTraits::Get(id.number(), _extensions_,                  \
+                                  id.default_value());                        \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Singular::MutableType MutableExtension(  \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Mutable(id.number(), _field_type,               \
+                                      &_extensions_);                         \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void SetExtension(                                                   \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      typename _proto_TypeTraits::Singular::ConstType value) {                \
+    _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_);   \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void SetAllocatedExtension(                                          \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      typename _proto_TypeTraits::Singular::MutableType value) {              \
+    _proto_TypeTraits::SetAllocated(id.number(), _field_type,                 \
+                                    value, &_extensions_);                    \
+  }                                                                           \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Singular::MutableType ReleaseExtension(  \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Release(id.number(), _field_type,               \
+                                      &_extensions_);                         \
+  }                                                                           \
+                                                                              \
+  /* Repeated accessors */                                                    \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Repeated::ConstType GetExtension(        \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      int index) const {                                                      \
+    return _proto_TypeTraits::Get(id.number(), _extensions_, index);          \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension(  \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      int index) {                                                            \
+    return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_);     \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void SetExtension(                                                   \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      int index, typename _proto_TypeTraits::Repeated::ConstType value) {     \
+    _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);         \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Repeated::MutableType AddExtension(      \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_);   \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void AddExtension(                                                   \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      typename _proto_TypeTraits::Repeated::ConstType value) {                \
+    _proto_TypeTraits::Add(id.number(), _field_type, _is_packed,              \
+                           value, &_extensions_);                             \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType&       \
+      GetRepeatedExtension(                                                   \
+          const ::google::protobuf::internal::ExtensionIdentifier<                      \
+            CLASSNAME, _proto_TypeTraits, _field_type,                        \
+            _is_packed>& id) const {                                          \
+    return _proto_TypeTraits::GetRepeated(id.number(), _extensions_);         \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::Repeated::RepeatedFieldType*             \
+      MutableRepeatedExtension(                                               \
+          const ::google::protobuf::internal::ExtensionIdentifier<                      \
+              CLASSNAME, _proto_TypeTraits, _field_type,                      \
+              _is_packed>& id) {                                              \
+    return _proto_TypeTraits::MutableRepeated(id.number(), _field_type,       \
+                                              _is_packed, &_extensions_);     \
+  }
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_EXTENSION_SET_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/extension_set_heavy.cc b/src/third_party/protobuf-3/src/google/protobuf/extension_set_heavy.cc
new file mode 100644
index 0000000..82e3e09
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/extension_set_heavy.cc
@@ -0,0 +1,754 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Contains methods defined in extension_set.h which cannot be part of the
+// lite library because they use descriptors or reflection.
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+
+namespace protobuf {
+namespace internal {
+
+// A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
+class MessageSetFieldSkipper
+    : public UnknownFieldSetFieldSkipper {
+ public:
+  explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
+      : UnknownFieldSetFieldSkipper(unknown_fields) {}
+  virtual ~MessageSetFieldSkipper() {}
+
+  virtual bool SkipMessageSetField(io::CodedInputStream* input,
+                                   int field_number);
+};
+bool MessageSetFieldSkipper::SkipMessageSetField(
+    io::CodedInputStream* input, int field_number) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  if (unknown_fields_ == NULL) {
+    return input->Skip(length);
+  } else {
+    return input->ReadString(
+        unknown_fields_->AddLengthDelimited(field_number), length);
+  }
+}
+
+
+// Implementation of ExtensionFinder which finds extensions in a given
+// DescriptorPool, using the given MessageFactory to construct sub-objects.
+// This class is implemented in extension_set_heavy.cc.
+class DescriptorPoolExtensionFinder : public ExtensionFinder {
+ public:
+  DescriptorPoolExtensionFinder(const DescriptorPool* pool,
+                                MessageFactory* factory,
+                                const Descriptor* containing_type)
+      : pool_(pool), factory_(factory), containing_type_(containing_type) {}
+  virtual ~DescriptorPoolExtensionFinder() {}
+
+  virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+  const DescriptorPool* pool_;
+  MessageFactory* factory_;
+  const Descriptor* containing_type_;
+};
+
+void ExtensionSet::AppendToList(
+    const Descriptor* containing_type,
+    const DescriptorPool* pool,
+    std::vector<const FieldDescriptor*>* output) const {
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    bool has = false;
+    if (iter->second.is_repeated) {
+      has = iter->second.GetSize() > 0;
+    } else {
+      has = !iter->second.is_cleared;
+    }
+
+    if (has) {
+      // TODO(kenton): Looking up each field by number is somewhat unfortunate.
+      //   Is there a better way?  The problem is that descriptors are lazily-
+      //   initialized, so they might not even be constructed until
+      //   AppendToList() is called.
+
+      if (iter->second.descriptor == NULL) {
+        output->push_back(pool->FindExtensionByNumber(
+            containing_type, iter->first));
+      } else {
+        output->push_back(iter->second.descriptor);
+      }
+    }
+  }
+}
+
+inline FieldDescriptor::Type real_type(FieldType type) {
+  GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
+  return static_cast<FieldDescriptor::Type>(type);
+}
+
+inline FieldDescriptor::CppType cpp_type(FieldType type) {
+  return FieldDescriptor::TypeToCppType(
+      static_cast<FieldDescriptor::Type>(type));
+}
+
+inline WireFormatLite::FieldType field_type(FieldType type) {
+  GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
+  return static_cast<WireFormatLite::FieldType>(type);
+}
+
+#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
+  GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
+                                  : FieldDescriptor::LABEL_OPTIONAL,      \
+            FieldDescriptor::LABEL_##LABEL);                              \
+  GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
+
+const MessageLite& ExtensionSet::GetMessage(int number,
+                                            const Descriptor* message_type,
+                                            MessageFactory* factory) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end() || iter->second.is_cleared) {
+    // Not present.  Return the default value.
+    return *factory->GetPrototype(message_type);
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    if (iter->second.is_lazy) {
+      return iter->second.lazymessage_value->GetMessage(
+          *factory->GetPrototype(message_type));
+    } else {
+      return *iter->second.message_value;
+    }
+  }
+}
+
+MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
+                                          MessageFactory* factory) {
+  Extension* extension;
+  if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+    extension->type = descriptor->type();
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_packed = false;
+    const MessageLite* prototype =
+        factory->GetPrototype(descriptor->message_type());
+    extension->is_lazy = false;
+    extension->message_value = prototype->New(arena_);
+    extension->is_cleared = false;
+    return extension->message_value;
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    extension->is_cleared = false;
+    if (extension->is_lazy) {
+      return extension->lazymessage_value->MutableMessage(
+          *factory->GetPrototype(descriptor->message_type()));
+    } else {
+      return extension->message_value;
+    }
+  }
+}
+
+MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+                                          MessageFactory* factory) {
+  map<int, Extension>::iterator iter = extensions_.find(descriptor->number());
+  if (iter == extensions_.end()) {
+    // Not present.  Return NULL.
+    return NULL;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    MessageLite* ret = NULL;
+    if (iter->second.is_lazy) {
+      ret = iter->second.lazymessage_value->ReleaseMessage(
+          *factory->GetPrototype(descriptor->message_type()));
+      if (arena_ == NULL) {
+        delete iter->second.lazymessage_value;
+      }
+    } else {
+      if (arena_ != NULL) {
+        ret = (iter->second.message_value)->New();
+        ret->CheckTypeAndMergeFrom(*(iter->second.message_value));
+      } else {
+        ret = iter->second.message_value;
+      }
+    }
+    extensions_.erase(descriptor->number());
+    return ret;
+  }
+}
+
+ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
+  Extension* extension;
+  if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+    extension->type = descriptor->type();
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+    extension->is_repeated = true;
+    extension->repeated_message_value =
+        ::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
+  }
+  return extension;
+}
+
+MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
+                                      MessageFactory* factory) {
+  Extension* extension = MaybeNewRepeatedExtension(descriptor);
+
+  // RepeatedPtrField<Message> does not know how to Add() since it cannot
+  // allocate an abstract object, so we have to be tricky.
+  MessageLite* result = extension->repeated_message_value
+      ->AddFromCleared<GenericTypeHandler<MessageLite> >();
+  if (result == NULL) {
+    const MessageLite* prototype;
+    if (extension->repeated_message_value->size() == 0) {
+      prototype = factory->GetPrototype(descriptor->message_type());
+      GOOGLE_CHECK(prototype != NULL);
+    } else {
+      prototype = &extension->repeated_message_value->Get(0);
+    }
+    result = prototype->New(arena_);
+    extension->repeated_message_value->AddAllocated(result);
+  }
+  return result;
+}
+
+void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
+                                       MessageLite* new_entry) {
+  Extension* extension = MaybeNewRepeatedExtension(descriptor);
+
+  extension->repeated_message_value->AddAllocated(new_entry);
+}
+
+static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
+  return reinterpret_cast<const EnumDescriptor*>(arg)
+      ->FindValueByNumber(number) != NULL;
+}
+
+bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
+  const FieldDescriptor* extension =
+      pool_->FindExtensionByNumber(containing_type_, number);
+  if (extension == NULL) {
+    return false;
+  } else {
+    output->type = extension->type();
+    output->is_repeated = extension->is_repeated();
+    output->is_packed = extension->options().packed();
+    output->descriptor = extension;
+    if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      output->message_prototype =
+          factory_->GetPrototype(extension->message_type());
+      GOOGLE_CHECK(output->message_prototype != NULL)
+          << "Extension factory's GetPrototype() returned NULL for extension: "
+          << extension->full_name();
+    } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      output->enum_validity_check.func = ValidateEnumUsingDescriptor;
+      output->enum_validity_check.arg = extension->enum_type();
+    }
+
+    return true;
+  }
+}
+
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              const Message* containing_type,
+                              UnknownFieldSet* unknown_fields) {
+  UnknownFieldSetFieldSkipper skipper(unknown_fields);
+  if (input->GetExtensionPool() == NULL) {
+    GeneratedExtensionFinder finder(containing_type);
+    return ParseField(tag, input, &finder, &skipper);
+  } else {
+    DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+                                         input->GetExtensionFactory(),
+                                         containing_type->GetDescriptor());
+    return ParseField(tag, input, &finder, &skipper);
+  }
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const Message* containing_type,
+                                   UnknownFieldSet* unknown_fields) {
+  MessageSetFieldSkipper skipper(unknown_fields);
+  if (input->GetExtensionPool() == NULL) {
+    GeneratedExtensionFinder finder(containing_type);
+    return ParseMessageSet(input, &finder, &skipper);
+  } else {
+    DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+                                         input->GetExtensionFactory(),
+                                         containing_type->GetDescriptor());
+    return ParseMessageSet(input, &finder, &skipper);
+  }
+}
+
+int ExtensionSet::SpaceUsedExcludingSelf() const {
+  int total_size =
+      extensions_.size() * sizeof(map<int, Extension>::value_type);
+  for (map<int, Extension>::const_iterator iter = extensions_.begin(),
+       end = extensions_.end();
+       iter != end;
+       ++iter) {
+    total_size += iter->second.SpaceUsedExcludingSelf();
+  }
+  return total_size;
+}
+
+inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
+    RepeatedPtrFieldBase* field) {
+  return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+}
+
+int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
+  int total_size = 0;
+  if (is_repeated) {
+    switch (cpp_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
+        total_size += sizeof(*repeated_##LOWERCASE##_value) +      \
+            repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
+        break
+
+      HANDLE_TYPE(  INT32,   int32);
+      HANDLE_TYPE(  INT64,   int64);
+      HANDLE_TYPE( UINT32,  uint32);
+      HANDLE_TYPE( UINT64,  uint64);
+      HANDLE_TYPE(  FLOAT,   float);
+      HANDLE_TYPE( DOUBLE,  double);
+      HANDLE_TYPE(   BOOL,    bool);
+      HANDLE_TYPE(   ENUM,    enum);
+      HANDLE_TYPE( STRING,  string);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
+        // but MessageLite has no SpaceUsed(), so we must directly call
+        // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
+        // handler.
+        total_size += sizeof(*repeated_message_value) +
+            RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
+        break;
+    }
+  } else {
+    switch (cpp_type(type)) {
+      case FieldDescriptor::CPPTYPE_STRING:
+        total_size += sizeof(*string_value) +
+                      StringSpaceUsedExcludingSelf(*string_value);
+        break;
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (is_lazy) {
+          total_size += lazymessage_value->SpaceUsed();
+        } else {
+          total_size += down_cast<Message*>(message_value)->SpaceUsed();
+        }
+        break;
+      default:
+        // No extra storage costs for primitive types.
+        break;
+    }
+  }
+  return total_size;
+}
+
+// The Serialize*ToArray methods are only needed in the heavy library, as
+// the lite library only generates SerializeWithCachedSizes.
+uint8* ExtensionSet::SerializeWithCachedSizesToArray(
+    int start_field_number, int end_field_number,
+    uint8* target) const {
+  map<int, Extension>::const_iterator iter;
+  for (iter = extensions_.lower_bound(start_field_number);
+       iter != extensions_.end() && iter->first < end_field_number;
+       ++iter) {
+    target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
+                                                               target);
+  }
+  return target;
+}
+
+uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
+    uint8* target) const {
+  map<int, Extension>::const_iterator iter;
+  for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+    target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
+        iter->first, target);
+  }
+  return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
+    int number, uint8* target) const {
+  if (is_repeated) {
+    if (is_packed) {
+      if (cached_size == 0) return target;
+
+      target = WireFormatLite::WriteTagToArray(number,
+          WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
+      target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
+
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            target = WireFormatLite::Write##CAMELCASE##NoTagToArray(        \
+              repeated_##LOWERCASE##_value->Get(i), target);                \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,   int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,   int64);
+        HANDLE_TYPE(   FLOAT,    Float,   float);
+        HANDLE_TYPE(  DOUBLE,   Double,  double);
+        HANDLE_TYPE(    BOOL,     Bool,    bool);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+#undef HANDLE_TYPE
+
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_BYTES:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
+          GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+          break;
+      }
+    } else {
+      switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
+        case FieldDescriptor::TYPE_##UPPERCASE:                             \
+          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
+            target = WireFormatLite::Write##CAMELCASE##ToArray(number,      \
+              repeated_##LOWERCASE##_value->Get(i), target);                \
+          }                                                                 \
+          break
+
+        HANDLE_TYPE(   INT32,    Int32,   int32);
+        HANDLE_TYPE(   INT64,    Int64,   int64);
+        HANDLE_TYPE(  UINT32,   UInt32,  uint32);
+        HANDLE_TYPE(  UINT64,   UInt64,  uint64);
+        HANDLE_TYPE(  SINT32,   SInt32,   int32);
+        HANDLE_TYPE(  SINT64,   SInt64,   int64);
+        HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
+        HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
+        HANDLE_TYPE(SFIXED32, SFixed32,   int32);
+        HANDLE_TYPE(SFIXED64, SFixed64,   int64);
+        HANDLE_TYPE(   FLOAT,    Float,   float);
+        HANDLE_TYPE(  DOUBLE,   Double,  double);
+        HANDLE_TYPE(    BOOL,     Bool,    bool);
+        HANDLE_TYPE(  STRING,   String,  string);
+        HANDLE_TYPE(   BYTES,    Bytes,  string);
+        HANDLE_TYPE(    ENUM,     Enum,    enum);
+        HANDLE_TYPE(   GROUP,    Group, message);
+        HANDLE_TYPE( MESSAGE,  Message, message);
+#undef HANDLE_TYPE
+      }
+    }
+  } else if (!is_cleared) {
+    switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                 \
+      case FieldDescriptor::TYPE_##UPPERCASE:                    \
+        target = WireFormatLite::Write##CAMELCASE##ToArray(      \
+            number, VALUE, target); \
+        break
+
+      HANDLE_TYPE(   INT32,    Int32,    int32_value);
+      HANDLE_TYPE(   INT64,    Int64,    int64_value);
+      HANDLE_TYPE(  UINT32,   UInt32,   uint32_value);
+      HANDLE_TYPE(  UINT64,   UInt64,   uint64_value);
+      HANDLE_TYPE(  SINT32,   SInt32,    int32_value);
+      HANDLE_TYPE(  SINT64,   SInt64,    int64_value);
+      HANDLE_TYPE( FIXED32,  Fixed32,   uint32_value);
+      HANDLE_TYPE( FIXED64,  Fixed64,   uint64_value);
+      HANDLE_TYPE(SFIXED32, SFixed32,    int32_value);
+      HANDLE_TYPE(SFIXED64, SFixed64,    int64_value);
+      HANDLE_TYPE(   FLOAT,    Float,    float_value);
+      HANDLE_TYPE(  DOUBLE,   Double,   double_value);
+      HANDLE_TYPE(    BOOL,     Bool,     bool_value);
+      HANDLE_TYPE(  STRING,   String,  *string_value);
+      HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
+      HANDLE_TYPE(    ENUM,     Enum,     enum_value);
+      HANDLE_TYPE(   GROUP,    Group, *message_value);
+#undef HANDLE_TYPE
+      case FieldDescriptor::TYPE_MESSAGE:
+        if (is_lazy) {
+          target = lazymessage_value->WriteMessageToArray(number, target);
+        } else {
+          target = WireFormatLite::WriteMessageToArray(
+              number, *message_value, target);
+        }
+        break;
+    }
+  }
+  return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
+    int number,
+    uint8* target) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but serialize it the normal way.
+    GOOGLE_LOG(WARNING) << "Invalid message set extension.";
+    return SerializeFieldWithCachedSizesToArray(number, target);
+  }
+
+  if (is_cleared) return target;
+
+  // Start group.
+  target = io::CodedOutputStream::WriteTagToArray(
+      WireFormatLite::kMessageSetItemStartTag, target);
+  // Write type ID.
+  target = WireFormatLite::WriteUInt32ToArray(
+      WireFormatLite::kMessageSetTypeIdNumber, number, target);
+  // Write message.
+  if (is_lazy) {
+    target = lazymessage_value->WriteMessageToArray(
+        WireFormatLite::kMessageSetMessageNumber, target);
+  } else {
+    target = WireFormatLite::WriteMessageToArray(
+        WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+  }
+  // End group.
+  target = io::CodedOutputStream::WriteTagToArray(
+      WireFormatLite::kMessageSetItemEndTag, target);
+  return target;
+}
+
+
+bool ExtensionSet::ParseFieldMaybeLazily(
+    int wire_type, int field_number, io::CodedInputStream* input,
+    ExtensionFinder* extension_finder,
+    MessageSetFieldSkipper* field_skipper) {
+  return ParseField(WireFormatLite::MakeTag(
+      field_number, static_cast<WireFormatLite::WireType>(wire_type)),
+                    input, extension_finder, field_skipper);
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   ExtensionFinder* extension_finder,
+                                   MessageSetFieldSkipper* field_skipper) {
+  while (true) {
+    const uint32 tag = input->ReadTag();
+    switch (tag) {
+      case 0:
+        return true;
+      case WireFormatLite::kMessageSetItemStartTag:
+        if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
+          return false;
+        }
+        break;
+      default:
+        if (!ParseField(tag, input, extension_finder, field_skipper)) {
+          return false;
+        }
+        break;
+    }
+  }
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const MessageLite* containing_type) {
+  MessageSetFieldSkipper skipper(NULL);
+  GeneratedExtensionFinder finder(containing_type);
+  return ParseMessageSet(input, &finder, &skipper);
+}
+
+bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
+                                       ExtensionFinder* extension_finder,
+                                       MessageSetFieldSkipper* field_skipper) {
+  // TODO(kenton):  It would be nice to share code between this and
+  // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
+  // differences would be hard to factor out.
+
+  // This method parses a group which should contain two fields:
+  //   required int32 type_id = 2;
+  //   required data message = 3;
+
+  uint32 last_type_id = 0;
+
+  // If we see message data before the type_id, we'll append it to this so
+  // we can parse it later.
+  string message_data;
+
+  while (true) {
+    const uint32 tag = input->ReadTag();
+    if (tag == 0) return false;
+
+    switch (tag) {
+      case WireFormatLite::kMessageSetTypeIdTag: {
+        uint32 type_id;
+        if (!input->ReadVarint32(&type_id)) return false;
+        last_type_id = type_id;
+
+        if (!message_data.empty()) {
+          // We saw some message data before the type_id.  Have to parse it
+          // now.
+          io::CodedInputStream sub_input(
+              reinterpret_cast<const uint8*>(message_data.data()),
+              message_data.size());
+          if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+                                     last_type_id, &sub_input,
+                                     extension_finder, field_skipper)) {
+            return false;
+          }
+          message_data.clear();
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetMessageTag: {
+        if (last_type_id == 0) {
+          // We haven't seen a type_id yet.  Append this data to message_data.
+          string temp;
+          uint32 length;
+          if (!input->ReadVarint32(&length)) return false;
+          if (!input->ReadString(&temp, length)) return false;
+          io::StringOutputStream output_stream(&message_data);
+          io::CodedOutputStream coded_output(&output_stream);
+          coded_output.WriteVarint32(length);
+          coded_output.WriteString(temp);
+        } else {
+          // Already saw type_id, so we can parse this directly.
+          if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+                                     last_type_id, input,
+                                     extension_finder, field_skipper)) {
+            return false;
+          }
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetItemEndTag: {
+        return true;
+      }
+
+      default: {
+        if (!field_skipper->SkipField(input, tag)) return false;
+      }
+    }
+  }
+}
+
+void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
+    int number,
+    io::CodedOutputStream* output) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but serialize it the normal way.
+    SerializeFieldWithCachedSizes(number, output);
+    return;
+  }
+
+  if (is_cleared) return;
+
+  // Start group.
+  output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
+
+  // Write type ID.
+  WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+                              number,
+                              output);
+  // Write message.
+  if (is_lazy) {
+    lazymessage_value->WriteMessage(
+        WireFormatLite::kMessageSetMessageNumber, output);
+  } else {
+    WireFormatLite::WriteMessageMaybeToArray(
+        WireFormatLite::kMessageSetMessageNumber,
+        *message_value,
+        output);
+  }
+
+  // End group.
+  output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
+}
+
+int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but compute the byte size for it the
+    // normal way.
+    return ByteSize(number);
+  }
+
+  if (is_cleared) return 0;
+
+  int our_size = WireFormatLite::kMessageSetItemTagsSize;
+
+  // type_id
+  our_size += io::CodedOutputStream::VarintSize32(number);
+
+  // message
+  int message_size = 0;
+  if (is_lazy) {
+    message_size = lazymessage_value->ByteSize();
+  } else {
+    message_size = message_value->ByteSize();
+  }
+
+  our_size += io::CodedOutputStream::VarintSize32(message_size);
+  our_size += message_size;
+
+  return our_size;
+}
+
+void ExtensionSet::SerializeMessageSetWithCachedSizes(
+    io::CodedOutputStream* output) const {
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
+  }
+}
+
+int ExtensionSet::MessageSetByteSize() const {
+  int total_size = 0;
+
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    total_size += iter->second.MessageSetItemByteSize(iter->first);
+  }
+
+  return total_size;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/extension_set_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/extension_set_unittest.cc
new file mode 100644
index 0000000..f40fcbc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/extension_set_unittest.cc
@@ -0,0 +1,1207 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+
+namespace protobuf {
+namespace internal {
+namespace {
+
+// This test closely mirrors google/protobuf/compiler/cpp/unittest.cc
+// except that it uses extensions rather than regular fields.
+
+TEST(ExtensionSetTest, Defaults) {
+  // Check that all default values are set correctly in the initial message.
+  unittest::TestAllExtensions message;
+
+  TestUtil::ExpectExtensionsClear(message);
+
+  // Messages should return pointers to default instances until first use.
+  // (This is not checked by ExpectClear() since it is not actually true after
+  // the fields have been set and then cleared.)
+  EXPECT_EQ(&unittest::OptionalGroup_extension::default_instance(),
+            &message.GetExtension(unittest::optionalgroup_extension));
+  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.GetExtension(unittest::optional_nested_message_extension));
+  EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
+            &message.GetExtension(
+              unittest::optional_foreign_message_extension));
+  EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
+            &message.GetExtension(unittest::optional_import_message_extension));
+}
+
+TEST(ExtensionSetTest, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  unittest::TestAllExtensions message;
+
+  TestUtil::SetAllExtensions(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+
+  TestUtil::ModifyRepeatedExtensions(&message);
+  TestUtil::ExpectRepeatedExtensionsModified(message);
+}
+
+TEST(ExtensionSetTest, Clear) {
+  // Set every field to a unique value, clear the message, then check that
+  // it is cleared.
+  unittest::TestAllExtensions message;
+
+  TestUtil::SetAllExtensions(&message);
+  message.Clear();
+  TestUtil::ExpectExtensionsClear(message);
+
+  // Unlike with the defaults test, we do NOT expect that requesting embedded
+  // messages will return a pointer to the default instance.  Instead, they
+  // should return the objects that were created when mutable_blah() was
+  // called.
+  EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(),
+            &message.GetExtension(unittest::optionalgroup_extension));
+  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.GetExtension(unittest::optional_nested_message_extension));
+  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
+            &message.GetExtension(
+              unittest::optional_foreign_message_extension));
+  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
+            &message.GetExtension(unittest::optional_import_message_extension));
+
+  // Make sure setting stuff again after clearing works.  (This takes slightly
+  // different code paths since the objects are reused.)
+  TestUtil::SetAllExtensions(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(ExtensionSetTest, ClearOneField) {
+  // Set every field to a unique value, then clear one value and insure that
+  // only that one value is cleared.
+  unittest::TestAllExtensions message;
+
+  TestUtil::SetAllExtensions(&message);
+  int64 original_value =
+    message.GetExtension(unittest::optional_int64_extension);
+
+  // Clear the field and make sure it shows up as cleared.
+  message.ClearExtension(unittest::optional_int64_extension);
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension));
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_int64_extension));
+
+  // Other adjacent fields should not be cleared.
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension));
+
+  // Make sure if we set it again, then all fields are set.
+  message.SetExtension(unittest::optional_int64_extension, original_value);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(ExtensionSetTest, SetAllocatedExtension) {
+  unittest::TestAllExtensions message;
+  EXPECT_FALSE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+  // Add a extension using SetAllocatedExtension
+  unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                foreign_message);
+  EXPECT_TRUE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+  EXPECT_EQ(foreign_message,
+            message.MutableExtension(
+                unittest::optional_foreign_message_extension));
+  EXPECT_EQ(foreign_message,
+            &message.GetExtension(
+                unittest::optional_foreign_message_extension));
+
+  // SetAllocatedExtension should delete the previously existing extension.
+  // (We reply on unittest to check memory leaks for this case)
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                new unittest::ForeignMessage());
+
+  // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion.
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                NULL);
+  EXPECT_FALSE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+}
+
+TEST(ExtensionSetTest, ReleaseExtension) {
+  proto2_wireformat_unittest::TestMessageSet message;
+  EXPECT_FALSE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // Add a extension using SetAllocatedExtension
+  unittest::TestMessageSetExtension1* extension =
+      new unittest::TestMessageSetExtension1();
+  message.SetAllocatedExtension(
+      unittest::TestMessageSetExtension1::message_set_extension,
+      extension);
+  EXPECT_TRUE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // Release the extension using ReleaseExtension
+  unittest::TestMessageSetExtension1* released_extension =
+      message.ReleaseExtension(
+          unittest::TestMessageSetExtension1::message_set_extension);
+  EXPECT_EQ(extension, released_extension);
+  EXPECT_FALSE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // ReleaseExtension will return the underlying object even after
+  // ClearExtension is called.
+  message.SetAllocatedExtension(
+      unittest::TestMessageSetExtension1::message_set_extension,
+      extension);
+  message.ClearExtension(
+      unittest::TestMessageSetExtension1::message_set_extension);
+  released_extension = message.ReleaseExtension(
+      unittest::TestMessageSetExtension1::message_set_extension);
+  EXPECT_TRUE(released_extension != NULL);
+  delete released_extension;
+}
+
+
+TEST(ExtensionSetTest, CopyFrom) {
+  unittest::TestAllExtensions message1, message2;
+
+  TestUtil::SetAllExtensions(&message1);
+  message2.CopyFrom(message1);
+  TestUtil::ExpectAllExtensionsSet(message2);
+  message2.CopyFrom(message1);  // exercise copy when fields already exist
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensioSetTest, CopyFromPacked) {
+  unittest::TestPackedExtensions message1, message2;
+
+  TestUtil::SetPackedExtensions(&message1);
+  message2.CopyFrom(message1);
+  TestUtil::ExpectPackedExtensionsSet(message2);
+  message2.CopyFrom(message1);  // exercise copy when fields already exist
+  TestUtil::ExpectPackedExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, CopyFromUpcasted) {
+  unittest::TestAllExtensions message1, message2;
+  const Message& upcasted_message = message1;
+
+  TestUtil::SetAllExtensions(&message1);
+  message2.CopyFrom(upcasted_message);
+  TestUtil::ExpectAllExtensionsSet(message2);
+  // exercise copy when fields already exist
+  message2.CopyFrom(upcasted_message);
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, SwapWithEmpty) {
+  unittest::TestAllExtensions message1, message2;
+  TestUtil::SetAllExtensions(&message1);
+
+  TestUtil::ExpectAllExtensionsSet(message1);
+  TestUtil::ExpectExtensionsClear(message2);
+  message1.Swap(&message2);
+  TestUtil::ExpectAllExtensionsSet(message2);
+  TestUtil::ExpectExtensionsClear(message1);
+}
+
+TEST(ExtensionSetTest, SwapWithSelf) {
+  unittest::TestAllExtensions message;
+  TestUtil::SetAllExtensions(&message);
+
+  TestUtil::ExpectAllExtensionsSet(message);
+  message.Swap(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(ExtensionSetTest, SwapExtension) {
+  unittest::TestAllExtensions message1;
+  unittest::TestAllExtensions message2;
+
+  TestUtil::SetAllExtensions(&message1);
+  vector<const FieldDescriptor*> fields;
+
+  // Swap empty fields.
+  const Reflection* reflection = message1.GetReflection();
+  reflection->SwapFields(&message1, &message2, fields);
+  TestUtil::ExpectAllExtensionsSet(message1);
+  TestUtil::ExpectExtensionsClear(message2);
+
+  // Swap two extensions.
+  fields.push_back(
+      reflection->FindKnownExtensionByNumber(12));
+  fields.push_back(
+      reflection->FindKnownExtensionByNumber(25));
+  reflection->SwapFields(&message1, &message2, fields);
+
+  EXPECT_TRUE(message1.HasExtension(unittest::optional_int32_extension));
+  EXPECT_FALSE(message1.HasExtension(unittest::optional_double_extension));
+  EXPECT_FALSE(message1.HasExtension(unittest::optional_cord_extension));
+
+  EXPECT_FALSE(message2.HasExtension(unittest::optional_int32_extension));
+  EXPECT_TRUE(message2.HasExtension(unittest::optional_double_extension));
+  EXPECT_TRUE(message2.HasExtension(unittest::optional_cord_extension));
+}
+
+TEST(ExtensionSetTest, SwapExtensionWithEmpty) {
+  unittest::TestAllExtensions message1;
+  unittest::TestAllExtensions message2;
+  unittest::TestAllExtensions message3;
+
+  TestUtil::SetAllExtensions(&message3);
+
+  const Reflection* reflection = message3.GetReflection();
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message3, &fields);
+
+  reflection->SwapFields(&message1, &message2, fields);
+
+  TestUtil::ExpectExtensionsClear(message1);
+  TestUtil::ExpectExtensionsClear(message2);
+}
+
+TEST(ExtensionSetTest, SwapExtensionBothFull) {
+  unittest::TestAllExtensions message1;
+  unittest::TestAllExtensions message2;
+
+  TestUtil::SetAllExtensions(&message1);
+  TestUtil::SetAllExtensions(&message2);
+
+  const Reflection* reflection = message1.GetReflection();
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message1, &fields);
+
+  reflection->SwapFields(&message1, &message2, fields);
+
+  TestUtil::ExpectAllExtensionsSet(message1);
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, ArenaSetAllExtension) {
+  ::google::protobuf::Arena arena1;
+  unittest::TestAllExtensions* message1 =
+      ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+  TestUtil::SetAllExtensions(message1);
+  TestUtil::ExpectAllExtensionsSet(*message1);
+}
+
+TEST(ExtensionSetTest, ArenaCopyConstructor) {
+  ::google::protobuf::Arena arena1;
+  unittest::TestAllExtensions* message1 =
+      ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+  TestUtil::SetAllExtensions(message1);
+  unittest::TestAllExtensions message2(*message1);
+  arena1.Reset();
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, ArenaMergeFrom) {
+  ::google::protobuf::Arena arena1;
+  unittest::TestAllExtensions* message1 =
+      ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+  TestUtil::SetAllExtensions(message1);
+  unittest::TestAllExtensions message2;
+  message2.MergeFrom(*message1);
+  arena1.Reset();
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
+  ::google::protobuf::Arena arena;
+  unittest::TestAllExtensions* message =
+      ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena);
+  EXPECT_FALSE(message->HasExtension(
+      unittest::optional_foreign_message_extension));
+  // Add a extension using SetAllocatedExtension
+  unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
+  message->SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                 foreign_message);
+  // foreign_message is now owned by the arena.
+  EXPECT_EQ(foreign_message,
+            message->MutableExtension(
+                unittest::optional_foreign_message_extension));
+
+  // Underlying message is copied, and returned.
+  unittest::ForeignMessage* released_message = message->ReleaseExtension(
+      unittest::optional_foreign_message_extension);
+  delete released_message;
+  EXPECT_FALSE(message->HasExtension(
+      unittest::optional_foreign_message_extension));
+}
+
+TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) {
+  ::google::protobuf::Arena arena1;
+  google::protobuf::scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
+
+  unittest::TestAllExtensions* message1 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+  unittest::TestAllExtensions* message2 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(arena2.get());
+
+  TestUtil::SetAllExtensions(message1);
+  TestUtil::SetAllExtensions(message2);
+  message1->SetExtension(unittest::optional_int32_extension, 1);
+  message2->SetExtension(unittest::optional_int32_extension, 2);
+  message1->Swap(message2);
+  EXPECT_EQ(2, message1->GetExtension(unittest::optional_int32_extension));
+  EXPECT_EQ(1, message2->GetExtension(unittest::optional_int32_extension));
+  // Re-set the original values so ExpectAllExtensionsSet is happy.
+  message1->SetExtension(unittest::optional_int32_extension, 101);
+  message2->SetExtension(unittest::optional_int32_extension, 101);
+  TestUtil::ExpectAllExtensionsSet(*message1);
+  TestUtil::ExpectAllExtensionsSet(*message2);
+  arena2.reset(NULL);
+  TestUtil::ExpectAllExtensionsSet(*message1);
+  // Test corner cases, when one is empty and other is not.
+  ::google::protobuf::Arena arena3, arena4;
+
+  unittest::TestAllExtensions* message3 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(&arena3);
+  unittest::TestAllExtensions* message4 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(&arena4);
+  TestUtil::SetAllExtensions(message3);
+  message3->Swap(message4);
+  arena3.Reset();
+  TestUtil::ExpectAllExtensionsSet(*message4);
+}
+
+TEST(ExtensionSetTest, SwapFieldsOfExtensionBothFullWithArena) {
+  google::protobuf::Arena arena1;
+  google::protobuf::Arena* arena2 = new ::google::protobuf::Arena();
+
+  unittest::TestAllExtensions* message1 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+  unittest::TestAllExtensions* message2 =
+      Arena::CreateMessage<unittest::TestAllExtensions>(arena2);
+
+  TestUtil::SetAllExtensions(message1);
+  TestUtil::SetAllExtensions(message2);
+
+  const Reflection* reflection = message1->GetReflection();
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(*message1, &fields);
+  reflection->SwapFields(message1, message2, fields);
+  TestUtil::ExpectAllExtensionsSet(*message1);
+  TestUtil::ExpectAllExtensionsSet(*message2);
+  delete arena2;
+  TestUtil::ExpectAllExtensionsSet(*message1);
+}
+
+TEST(ExtensionSetTest, SwapExtensionWithSelf) {
+  unittest::TestAllExtensions message1;
+
+  TestUtil::SetAllExtensions(&message1);
+
+  vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1.GetReflection();
+  reflection->ListFields(message1, &fields);
+  reflection->SwapFields(&message1, &message1, fields);
+
+  TestUtil::ExpectAllExtensionsSet(message1);
+}
+
+TEST(ExtensionSetTest, SerializationToArray) {
+  // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
+  // compatibility of extensions.
+  //
+  // This checks serialization to a flat array by explicitly reserving space in
+  // the string and calling the generated message's
+  // SerializeWithCachedSizesToArray.
+  unittest::TestAllExtensions source;
+  unittest::TestAllTypes destination;
+  TestUtil::SetAllExtensions(&source);
+  int size = source.ByteSize();
+  string data;
+  data.resize(size);
+  uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = source.SerializeWithCachedSizesToArray(target);
+  EXPECT_EQ(size, end - target);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(destination);
+}
+
+TEST(ExtensionSetTest, SerializationToStream) {
+  // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
+  // compatibility of extensions.
+  //
+  // This checks serialization to an output stream by creating an array output
+  // stream that can only buffer 1 byte at a time - this prevents the message
+  // from ever jumping to the fast path, ensuring that serialization happens via
+  // the CodedOutputStream.
+  unittest::TestAllExtensions source;
+  unittest::TestAllTypes destination;
+  TestUtil::SetAllExtensions(&source);
+  int size = source.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    source.SerializeWithCachedSizes(&output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(destination);
+}
+
+TEST(ExtensionSetTest, PackedSerializationToArray) {
+  // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
+  // wire compatibility of extensions.
+  //
+  // This checks serialization to a flat array by explicitly reserving space in
+  // the string and calling the generated message's
+  // SerializeWithCachedSizesToArray.
+  unittest::TestPackedExtensions source;
+  unittest::TestPackedTypes destination;
+  TestUtil::SetPackedExtensions(&source);
+  int size = source.ByteSize();
+  string data;
+  data.resize(size);
+  uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = source.SerializeWithCachedSizesToArray(target);
+  EXPECT_EQ(size, end - target);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectPackedFieldsSet(destination);
+}
+
+TEST(ExtensionSetTest, PackedSerializationToStream) {
+  // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
+  // wire compatibility of extensions.
+  //
+  // This checks serialization to an output stream by creating an array output
+  // stream that can only buffer 1 byte at a time - this prevents the message
+  // from ever jumping to the fast path, ensuring that serialization happens via
+  // the CodedOutputStream.
+  unittest::TestPackedExtensions source;
+  unittest::TestPackedTypes destination;
+  TestUtil::SetPackedExtensions(&source);
+  int size = source.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    source.SerializeWithCachedSizes(&output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectPackedFieldsSet(destination);
+}
+
+TEST(ExtensionSetTest, Parsing) {
+  // Serialize as TestAllTypes and parse as TestAllExtensions.
+  unittest::TestAllTypes source;
+  unittest::TestAllExtensions destination;
+  string data;
+
+  TestUtil::SetAllFields(&source);
+  source.SerializeToString(&data);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::SetOneofFields(&destination);
+  TestUtil::ExpectAllExtensionsSet(destination);
+}
+
+TEST(ExtensionSetTest, PackedParsing) {
+  // Serialize as TestPackedTypes and parse as TestPackedExtensions.
+  unittest::TestPackedTypes source;
+  unittest::TestPackedExtensions destination;
+  string data;
+
+  TestUtil::SetPackedFields(&source);
+  source.SerializeToString(&data);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectPackedExtensionsSet(destination);
+}
+
+TEST(ExtensionSetTest, PackedToUnpackedParsing) {
+  unittest::TestPackedTypes source;
+  unittest::TestUnpackedExtensions destination;
+  string data;
+
+  TestUtil::SetPackedFields(&source);
+  source.SerializeToString(&data);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectUnpackedExtensionsSet(destination);
+
+  // Reserialize
+  unittest::TestUnpackedTypes unpacked;
+  TestUtil::SetUnpackedFields(&unpacked);
+  EXPECT_TRUE(unpacked.SerializeAsString() == destination.SerializeAsString());
+
+  // Make sure we can add extensions.
+  destination.AddExtension(unittest::unpacked_int32_extension, 1);
+  destination.AddExtension(unittest::unpacked_enum_extension,
+                           protobuf_unittest::FOREIGN_BAR);
+}
+
+TEST(ExtensionSetTest, UnpackedToPackedParsing) {
+  unittest::TestUnpackedTypes source;
+  unittest::TestPackedExtensions destination;
+  string data;
+
+  TestUtil::SetUnpackedFields(&source);
+  source.SerializeToString(&data);
+  EXPECT_TRUE(destination.ParseFromString(data));
+  TestUtil::ExpectPackedExtensionsSet(destination);
+
+  // Reserialize
+  unittest::TestPackedTypes packed;
+  TestUtil::SetPackedFields(&packed);
+  EXPECT_TRUE(packed.SerializeAsString() == destination.SerializeAsString());
+
+  // Make sure we can add extensions.
+  destination.AddExtension(unittest::packed_int32_extension, 1);
+  destination.AddExtension(unittest::packed_enum_extension,
+                           protobuf_unittest::FOREIGN_BAR);
+}
+
+TEST(ExtensionSetTest, IsInitialized) {
+  // Test that IsInitialized() returns false if required fields in nested
+  // extensions are missing.
+  unittest::TestAllExtensions message;
+
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.MutableExtension(unittest::TestRequired::single);
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.MutableExtension(unittest::TestRequired::single)->set_a(1);
+  EXPECT_FALSE(message.IsInitialized());
+  message.MutableExtension(unittest::TestRequired::single)->set_b(2);
+  EXPECT_FALSE(message.IsInitialized());
+  message.MutableExtension(unittest::TestRequired::single)->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.AddExtension(unittest::TestRequired::multi);
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
+  EXPECT_FALSE(message.IsInitialized());
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
+  EXPECT_FALSE(message.IsInitialized());
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(ExtensionSetTest, MutableString) {
+  // Test the mutable string accessors.
+  unittest::TestAllExtensions message;
+
+  message.MutableExtension(unittest::optional_string_extension)->assign("foo");
+  EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension));
+  EXPECT_EQ("foo", message.GetExtension(unittest::optional_string_extension));
+
+  message.AddExtension(unittest::repeated_string_extension)->assign("bar");
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension));
+  EXPECT_EQ("bar",
+            message.GetExtension(unittest::repeated_string_extension, 0));
+}
+
+TEST(ExtensionSetTest, SpaceUsedExcludingSelf) {
+  // Scalar primitive extensions should increase the extension set size by a
+  // minimum of the size of the primitive type.
+#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value)                        \
+  do {                                                                        \
+    unittest::TestAllExtensions message;                                      \
+    const int base_size = message.SpaceUsed();                                \
+    message.SetExtension(unittest::optional_##type##_extension, value);       \
+    int min_expected_size = base_size +                                       \
+        sizeof(message.GetExtension(unittest::optional_##type##_extension));  \
+    EXPECT_LE(min_expected_size, message.SpaceUsed());                        \
+  } while (0)
+
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(int32   , 101);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(int64   , 102);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32  , 103);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64  , 104);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32  , 105);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64  , 106);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32 , 107);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64 , 108);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed32, 109);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed64, 110);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(float   , 111);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(double  , 112);
+  TEST_SCALAR_EXTENSIONS_SPACE_USED(bool    , true);
+#undef TEST_SCALAR_EXTENSIONS_SPACE_USED
+  {
+    unittest::TestAllExtensions message;
+    const int base_size = message.SpaceUsed();
+    message.SetExtension(unittest::optional_nested_enum_extension,
+                         unittest::TestAllTypes::FOO);
+    int min_expected_size = base_size +
+        sizeof(message.GetExtension(unittest::optional_nested_enum_extension));
+    EXPECT_LE(min_expected_size, message.SpaceUsed());
+  }
+  {
+    // Strings may cause extra allocations depending on their length; ensure
+    // that gets included as well.
+    unittest::TestAllExtensions message;
+    const int base_size = message.SpaceUsed();
+    const string s("this is a fairly large string that will cause some "
+                   "allocation in order to store it in the extension");
+    message.SetExtension(unittest::optional_string_extension, s);
+    int min_expected_size = base_size + s.length();
+    EXPECT_LE(min_expected_size, message.SpaceUsed());
+  }
+  {
+    // Messages also have additional allocation that need to be counted.
+    unittest::TestAllExtensions message;
+    const int base_size = message.SpaceUsed();
+    unittest::ForeignMessage foreign;
+    foreign.set_c(42);
+    message.MutableExtension(unittest::optional_foreign_message_extension)->
+        CopyFrom(foreign);
+    int min_expected_size = base_size + foreign.SpaceUsed();
+    EXPECT_LE(min_expected_size, message.SpaceUsed());
+  }
+
+  // Repeated primitive extensions will increase space used by at least a
+  // RepeatedField<T>, and will cause additional allocations when the array
+  // gets too big for the initial space.
+  // This macro:
+  //   - Adds a value to the repeated extension, then clears it, establishing
+  //     the base size.
+  //   - Adds a small number of values, testing that it doesn't increase the
+  //     SpaceUsed()
+  //   - Adds a large number of values (requiring allocation in the repeated
+  //     field), and ensures that that allocation is included in SpaceUsed()
+#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value)              \
+  do {                                                                         \
+    unittest::TestAllExtensions message;                                       \
+    const int base_size = message.SpaceUsed();                                 \
+    int min_expected_size = sizeof(RepeatedField<cpptype>) + base_size;        \
+    message.AddExtension(unittest::repeated_##type##_extension, value);        \
+    message.ClearExtension(unittest::repeated_##type##_extension);             \
+    const int empty_repeated_field_size = message.SpaceUsed();                 \
+    EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type;          \
+    message.AddExtension(unittest::repeated_##type##_extension, value);        \
+    message.AddExtension(unittest::repeated_##type##_extension, value);        \
+    EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type;        \
+    message.ClearExtension(unittest::repeated_##type##_extension);             \
+    for (int i = 0; i < 16; ++i) {                                             \
+      message.AddExtension(unittest::repeated_##type##_extension, value);      \
+    }                                                                          \
+    int expected_size = sizeof(cpptype) * (16 -                                \
+        kMinRepeatedFieldAllocationSize) + empty_repeated_field_size;          \
+    EXPECT_EQ(expected_size, message.SpaceUsed()) << #type;                    \
+  } while (0)
+
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(int32   , int32 , 101);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(int64   , int64 , 102);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32  , uint32, 103);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64  , uint64, 104);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32  , int32 , 105);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64  , int64 , 106);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32 , uint32, 107);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64 , uint64, 108);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32 , 109);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64 , 110);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(float   , float , 111);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(double  , double, 112);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(bool    , bool  , true);
+  TEST_REPEATED_EXTENSIONS_SPACE_USED(nested_enum, int,
+                                      unittest::TestAllTypes::FOO);
+#undef TEST_REPEATED_EXTENSIONS_SPACE_USED
+  // Repeated strings
+  {
+    unittest::TestAllExtensions message;
+    const int base_size = message.SpaceUsed();
+    int min_expected_size = sizeof(RepeatedPtrField<string>) + base_size;
+    const string value(256, 'x');
+    // Once items are allocated, they may stick around even when cleared so
+    // without the hardcore memory management accessors there isn't a notion of
+    // the empty repeated field memory usage as there is with primitive types.
+    for (int i = 0; i < 16; ++i) {
+      message.AddExtension(unittest::repeated_string_extension, value);
+    }
+    min_expected_size += (sizeof(value) + value.size()) *
+        (16 - kMinRepeatedFieldAllocationSize);
+    EXPECT_LE(min_expected_size, message.SpaceUsed());
+  }
+  // Repeated messages
+  {
+    unittest::TestAllExtensions message;
+    const int base_size = message.SpaceUsed();
+    int min_expected_size = sizeof(RepeatedPtrField<unittest::ForeignMessage>) +
+        base_size;
+    unittest::ForeignMessage prototype;
+    prototype.set_c(2);
+    for (int i = 0; i < 16; ++i) {
+      message.AddExtension(unittest::repeated_foreign_message_extension)->
+          CopyFrom(prototype);
+    }
+    min_expected_size +=
+        (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed();
+    EXPECT_LE(min_expected_size, message.SpaceUsed());
+  }
+}
+
+// N.B.: We do not test range-based for here because we remain C++03 compatible.
+template<typename T, typename M, typename ID>
+inline T SumAllExtensions(const M& message, ID extension, T zero) {
+  T sum = zero;
+  typename RepeatedField<T>::const_iterator iter =
+      message.GetRepeatedExtension(extension).begin();
+  typename RepeatedField<T>::const_iterator end =
+      message.GetRepeatedExtension(extension).end();
+  for (; iter != end; ++iter) {
+    sum += *iter;
+  }
+  return sum;
+}
+
+template<typename T, typename M, typename ID>
+inline void IncAllExtensions(M* message, ID extension,
+                          T val) {
+  typename RepeatedField<T>::iterator iter =
+      message->MutableRepeatedExtension(extension)->begin();
+  typename RepeatedField<T>::iterator end  =
+      message->MutableRepeatedExtension(extension)->end();
+  for (; iter != end; ++iter) {
+    *iter += val;
+  }
+}
+
+TEST(ExtensionSetTest, RepeatedFields) {
+  unittest::TestAllExtensions message;
+
+  // Test empty repeated-field case (b/12926163)
+  ASSERT_EQ(0, message.GetRepeatedExtension(
+      unittest::repeated_int32_extension).size());
+  ASSERT_EQ(0, message.GetRepeatedExtension(
+      unittest::repeated_nested_enum_extension).size());
+  ASSERT_EQ(0, message.GetRepeatedExtension(
+      unittest::repeated_string_extension).size());
+  ASSERT_EQ(0, message.GetRepeatedExtension(
+      unittest::repeated_nested_message_extension).size());
+
+  unittest::TestAllTypes::NestedMessage nested_message;
+  nested_message.set_bb(42);
+  unittest::TestAllTypes::NestedEnum nested_enum =
+      unittest::TestAllTypes::NestedEnum_MIN;
+
+  for (int i = 0; i < 10; ++i) {
+    message.AddExtension(unittest::repeated_int32_extension, 1);
+    message.AddExtension(unittest::repeated_int64_extension, 2);
+    message.AddExtension(unittest::repeated_uint32_extension, 3);
+    message.AddExtension(unittest::repeated_uint64_extension, 4);
+    message.AddExtension(unittest::repeated_sint32_extension, 5);
+    message.AddExtension(unittest::repeated_sint64_extension, 6);
+    message.AddExtension(unittest::repeated_fixed32_extension, 7);
+    message.AddExtension(unittest::repeated_fixed64_extension, 8);
+    message.AddExtension(unittest::repeated_sfixed32_extension, 7);
+    message.AddExtension(unittest::repeated_sfixed64_extension, 8);
+    message.AddExtension(unittest::repeated_float_extension, 9.0);
+    message.AddExtension(unittest::repeated_double_extension, 10.0);
+    message.AddExtension(unittest::repeated_bool_extension, true);
+    message.AddExtension(unittest::repeated_nested_enum_extension, nested_enum);
+    message.AddExtension(unittest::repeated_string_extension,
+                         ::std::string("test"));
+    message.AddExtension(unittest::repeated_bytes_extension,
+                         ::std::string("test\xFF"));
+    message.AddExtension(
+        unittest::repeated_nested_message_extension)->CopyFrom(nested_message);
+    message.AddExtension(unittest::repeated_nested_enum_extension,
+                         nested_enum);
+  }
+
+  ASSERT_EQ(10, SumAllExtensions<int32>(
+      message, unittest::repeated_int32_extension, 0));
+  IncAllExtensions<int32>(
+      &message, unittest::repeated_int32_extension, 1);
+  ASSERT_EQ(20, SumAllExtensions<int32>(
+      message, unittest::repeated_int32_extension, 0));
+
+  ASSERT_EQ(20, SumAllExtensions<int64>(
+      message, unittest::repeated_int64_extension, 0));
+  IncAllExtensions<int64>(
+      &message, unittest::repeated_int64_extension, 1);
+  ASSERT_EQ(30, SumAllExtensions<int64>(
+      message, unittest::repeated_int64_extension, 0));
+
+  ASSERT_EQ(30, SumAllExtensions<uint32>(
+      message, unittest::repeated_uint32_extension, 0));
+  IncAllExtensions<uint32>(
+      &message, unittest::repeated_uint32_extension, 1);
+  ASSERT_EQ(40, SumAllExtensions<uint32>(
+      message, unittest::repeated_uint32_extension, 0));
+
+  ASSERT_EQ(40, SumAllExtensions<uint64>(
+      message, unittest::repeated_uint64_extension, 0));
+  IncAllExtensions<uint64>(
+      &message, unittest::repeated_uint64_extension, 1);
+  ASSERT_EQ(50, SumAllExtensions<uint64>(
+      message, unittest::repeated_uint64_extension, 0));
+
+  ASSERT_EQ(50, SumAllExtensions<int32>(
+      message, unittest::repeated_sint32_extension, 0));
+  IncAllExtensions<int32>(
+      &message, unittest::repeated_sint32_extension, 1);
+  ASSERT_EQ(60, SumAllExtensions<int32>(
+      message, unittest::repeated_sint32_extension, 0));
+
+  ASSERT_EQ(60, SumAllExtensions<int64>(
+      message, unittest::repeated_sint64_extension, 0));
+  IncAllExtensions<int64>(
+      &message, unittest::repeated_sint64_extension, 1);
+  ASSERT_EQ(70, SumAllExtensions<int64>(
+      message, unittest::repeated_sint64_extension, 0));
+
+  ASSERT_EQ(70, SumAllExtensions<uint32>(
+      message, unittest::repeated_fixed32_extension, 0));
+  IncAllExtensions<uint32>(
+      &message, unittest::repeated_fixed32_extension, 1);
+  ASSERT_EQ(80, SumAllExtensions<uint32>(
+      message, unittest::repeated_fixed32_extension, 0));
+
+  ASSERT_EQ(80, SumAllExtensions<uint64>(
+      message, unittest::repeated_fixed64_extension, 0));
+  IncAllExtensions<uint64>(
+      &message, unittest::repeated_fixed64_extension, 1);
+  ASSERT_EQ(90, SumAllExtensions<uint64>(
+      message, unittest::repeated_fixed64_extension, 0));
+
+  // Usually, floating-point arithmetic cannot be trusted to be exact, so it is
+  // a Bad Idea to assert equality in a test like this. However, we're dealing
+  // with integers with a small number of significant mantissa bits, so we
+  // should actually have exact precision here.
+  ASSERT_EQ(90, SumAllExtensions<float>(
+      message, unittest::repeated_float_extension, 0));
+  IncAllExtensions<float>(
+      &message, unittest::repeated_float_extension, 1);
+  ASSERT_EQ(100, SumAllExtensions<float>(
+      message, unittest::repeated_float_extension, 0));
+
+  ASSERT_EQ(100, SumAllExtensions<double>(
+      message, unittest::repeated_double_extension, 0));
+  IncAllExtensions<double>(
+      &message, unittest::repeated_double_extension, 1);
+  ASSERT_EQ(110, SumAllExtensions<double>(
+      message, unittest::repeated_double_extension, 0));
+
+  RepeatedPtrField< ::std::string>::iterator string_iter;
+  RepeatedPtrField< ::std::string>::iterator string_end;
+  for (string_iter = message.MutableRepeatedExtension(
+          unittest::repeated_string_extension)->begin(),
+       string_end  = message.MutableRepeatedExtension(
+           unittest::repeated_string_extension)->end();
+       string_iter != string_end; ++string_iter) {
+    *string_iter += "test";
+  }
+  RepeatedPtrField< ::std::string>::const_iterator string_const_iter;
+  RepeatedPtrField< ::std::string>::const_iterator string_const_end;
+  for (string_const_iter = message.GetRepeatedExtension(
+           unittest::repeated_string_extension).begin(),
+       string_const_end  = message.GetRepeatedExtension(
+           unittest::repeated_string_extension).end();
+       string_iter != string_end; ++string_iter) {
+    ASSERT_TRUE(*string_iter == "testtest");
+  }
+
+  RepeatedField<unittest::TestAllTypes_NestedEnum>::iterator enum_iter;
+  RepeatedField<unittest::TestAllTypes_NestedEnum>::iterator enum_end;
+  for (enum_iter = message.MutableRepeatedExtension(
+           unittest::repeated_nested_enum_extension)->begin(),
+       enum_end  = message.MutableRepeatedExtension(
+           unittest::repeated_nested_enum_extension)->end();
+       enum_iter != enum_end; ++enum_iter) {
+    *enum_iter = unittest::TestAllTypes::NestedEnum_MAX;
+  }
+  RepeatedField<unittest::TestAllTypes_NestedEnum>::const_iterator
+      enum_const_iter;
+  RepeatedField<unittest::TestAllTypes_NestedEnum>::const_iterator
+      enum_const_end;
+  for (enum_const_iter = message.GetRepeatedExtension(
+           unittest::repeated_nested_enum_extension).begin(),
+       enum_const_end  = message.GetRepeatedExtension(
+           unittest::repeated_nested_enum_extension).end();
+       enum_iter != enum_end; ++enum_iter) {
+    ASSERT_EQ(*enum_const_iter, unittest::TestAllTypes::NestedEnum_MAX);
+  }
+
+  RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::iterator
+      msg_iter;
+  RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::iterator
+      msg_end;
+  for (msg_iter = message.MutableRepeatedExtension(
+           unittest::repeated_nested_message_extension)->begin(),
+       msg_end  = message.MutableRepeatedExtension(
+           unittest::repeated_nested_message_extension)->end();
+       msg_iter != msg_end; ++msg_iter) {
+    msg_iter->set_bb(1234);
+  }
+  RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::
+      const_iterator msg_const_iter;
+  RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::
+      const_iterator msg_const_end;
+  for (msg_const_iter = message.GetRepeatedExtension(
+           unittest::repeated_nested_message_extension).begin(),
+       msg_const_end  = message.GetRepeatedExtension(
+           unittest::repeated_nested_message_extension).end();
+       msg_const_iter != msg_const_end; ++msg_const_iter) {
+    ASSERT_EQ(msg_const_iter->bb(), 1234);
+  }
+
+  // Test range-based for as well, but only if compiled as C++11.
+#if __cplusplus >= 201103L
+  // Test one primitive field.
+  for (auto& x : *message.MutableRepeatedExtension(
+          unittest::repeated_int32_extension)) {
+    x = 4321;
+  }
+  for (const auto& x : message.GetRepeatedExtension(
+          unittest::repeated_int32_extension)) {
+    ASSERT_EQ(x, 4321);
+  }
+  // Test one string field.
+  for (auto& x : *message.MutableRepeatedExtension(
+          unittest::repeated_string_extension)) {
+    x = "test_range_based_for";
+  }
+  for (const auto& x : message.GetRepeatedExtension(
+          unittest::repeated_string_extension)) {
+    ASSERT_TRUE(x == "test_range_based_for");
+  }
+  // Test one message field.
+  for (auto& x : *message.MutableRepeatedExtension(
+          unittest::repeated_nested_message_extension)) {
+    x.set_bb(4321);
+  }
+  for (const auto& x : *message.MutableRepeatedExtension(
+          unittest::repeated_nested_message_extension)) {
+    ASSERT_EQ(x.bb(), 4321);
+  }
+#endif
+}
+
+// From b/12926163
+TEST(ExtensionSetTest, AbsentExtension) {
+  unittest::TestAllExtensions message;
+  message.MutableRepeatedExtension(unittest::repeated_nested_message_extension)
+      ->Add()->set_bb(123);
+  ASSERT_EQ(1, message.ExtensionSize(
+      unittest::repeated_nested_message_extension));
+  EXPECT_EQ(
+      123, message.GetExtension(
+          unittest::repeated_nested_message_extension, 0).bb());
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+TEST(ExtensionSetTest, InvalidEnumDeath) {
+  unittest::TestAllExtensions message;
+  EXPECT_DEBUG_DEATH(
+    message.SetExtension(unittest::optional_foreign_enum_extension,
+                         static_cast<unittest::ForeignEnum>(53)),
+    "IsValid");
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(ExtensionSetTest, DynamicExtensions) {
+  // Test adding a dynamic extension to a compiled-in message object.
+
+  FileDescriptorProto dynamic_proto;
+  dynamic_proto.set_name("dynamic_extensions_test.proto");
+  dynamic_proto.add_dependency(
+      unittest::TestAllExtensions::descriptor()->file()->name());
+  dynamic_proto.set_package("dynamic_extensions");
+
+  // Copy the fields and nested types from TestDynamicExtensions into our new
+  // proto, converting the fields into extensions.
+  const Descriptor* template_descriptor =
+      unittest::TestDynamicExtensions::descriptor();
+  DescriptorProto template_descriptor_proto;
+  template_descriptor->CopyTo(&template_descriptor_proto);
+  dynamic_proto.mutable_message_type()->MergeFrom(
+      template_descriptor_proto.nested_type());
+  dynamic_proto.mutable_enum_type()->MergeFrom(
+      template_descriptor_proto.enum_type());
+  dynamic_proto.mutable_extension()->MergeFrom(
+      template_descriptor_proto.field());
+
+  // For each extension that we added...
+  for (int i = 0; i < dynamic_proto.extension_size(); i++) {
+    // Set its extendee to TestAllExtensions.
+    FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i);
+    extension->set_extendee(
+        unittest::TestAllExtensions::descriptor()->full_name());
+
+    // If the field refers to one of the types nested in TestDynamicExtensions,
+    // make it refer to the type in our dynamic proto instead.
+    string prefix = "." + template_descriptor->full_name() + ".";
+    if (extension->has_type_name()) {
+      string* type_name = extension->mutable_type_name();
+      if (HasPrefixString(*type_name, prefix)) {
+        type_name->replace(0, prefix.size(), ".dynamic_extensions.");
+      }
+    }
+  }
+
+  // Now build the file, using the generated pool as an underlay.
+  DescriptorPool dynamic_pool(DescriptorPool::generated_pool());
+  const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto);
+  ASSERT_TRUE(file != NULL);
+  DynamicMessageFactory dynamic_factory(&dynamic_pool);
+  dynamic_factory.SetDelegateToGeneratedFactory(true);
+
+  // Construct a message that we can parse with the extensions we defined.
+  // Since the extensions were based off of the fields of TestDynamicExtensions,
+  // we can use that message to create this test message.
+  string data;
+  {
+    unittest::TestDynamicExtensions message;
+    message.set_scalar_extension(123);
+    message.set_enum_extension(unittest::FOREIGN_BAR);
+    message.set_dynamic_enum_extension(
+        unittest::TestDynamicExtensions::DYNAMIC_BAZ);
+    message.mutable_message_extension()->set_c(456);
+    message.mutable_dynamic_message_extension()->set_dynamic_field(789);
+    message.add_repeated_extension("foo");
+    message.add_repeated_extension("bar");
+    message.add_packed_extension(12);
+    message.add_packed_extension(-34);
+    message.add_packed_extension(56);
+    message.add_packed_extension(-78);
+
+    // Also add some unknown fields.
+
+    // An unknown enum value (for a known field).
+    message.mutable_unknown_fields()->AddVarint(
+      unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber,
+      12345);
+    // A regular unknown field.
+    message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown");
+
+    message.SerializeToString(&data);
+  }
+
+  // Now we can parse this using our dynamic extension definitions...
+  unittest::TestAllExtensions message;
+  {
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+    ASSERT_TRUE(message.ParseFromCodedStream(&input));
+    ASSERT_TRUE(input.ConsumedEntireMessage());
+  }
+
+  // Can we print it?
+  EXPECT_EQ(
+    "[dynamic_extensions.scalar_extension]: 123\n"
+    "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n"
+    "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n"
+    "[dynamic_extensions.message_extension] {\n"
+    "  c: 456\n"
+    "}\n"
+    "[dynamic_extensions.dynamic_message_extension] {\n"
+    "  dynamic_field: 789\n"
+    "}\n"
+    "[dynamic_extensions.repeated_extension]: \"foo\"\n"
+    "[dynamic_extensions.repeated_extension]: \"bar\"\n"
+    "[dynamic_extensions.packed_extension]: 12\n"
+    "[dynamic_extensions.packed_extension]: -34\n"
+    "[dynamic_extensions.packed_extension]: 56\n"
+    "[dynamic_extensions.packed_extension]: -78\n"
+    "2002: 12345\n"
+    "54321: \"unknown\"\n",
+    message.DebugString());
+
+  // Can we serialize it?
+  // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the
+  // terminal on failure.)
+  EXPECT_TRUE(message.SerializeAsString() == data);
+
+  // What if we parse using the reflection-based parser?
+  {
+    unittest::TestAllExtensions message2;
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+    ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2));
+    ASSERT_TRUE(input.ConsumedEntireMessage());
+    EXPECT_EQ(message.DebugString(), message2.DebugString());
+  }
+
+  // Are the embedded generated types actually using the generated objects?
+  {
+    const FieldDescriptor* message_extension =
+        file->FindExtensionByName("message_extension");
+    ASSERT_TRUE(message_extension != NULL);
+    const Message& sub_message =
+        message.GetReflection()->GetMessage(message, message_extension);
+    const unittest::ForeignMessage* typed_sub_message =
+#ifdef GOOGLE_PROTOBUF_NO_RTTI
+        static_cast<const unittest::ForeignMessage*>(&sub_message);
+#else
+        dynamic_cast<const unittest::ForeignMessage*>(&sub_message);
+#endif
+    ASSERT_TRUE(typed_sub_message != NULL);
+    EXPECT_EQ(456, typed_sub_message->c());
+  }
+
+  // What does GetMessage() return for the embedded dynamic type if it isn't
+  // present?
+  {
+    const FieldDescriptor* dynamic_message_extension =
+        file->FindExtensionByName("dynamic_message_extension");
+    ASSERT_TRUE(dynamic_message_extension != NULL);
+    const Message& parent = unittest::TestAllExtensions::default_instance();
+    const Message& sub_message =
+        parent.GetReflection()->GetMessage(parent, dynamic_message_extension,
+                                           &dynamic_factory);
+    const Message* prototype =
+        dynamic_factory.GetPrototype(dynamic_message_extension->message_type());
+    EXPECT_EQ(prototype, &sub_message);
+  }
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.cc
new file mode 100644
index 0000000..c49ebce
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.cc
@@ -0,0 +1,405 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/field_mask.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* FieldMask_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FieldMask_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/field_mask.proto");
+  GOOGLE_CHECK(file != NULL);
+  FieldMask_descriptor_ = file->message_type(0);
+  static const int FieldMask_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, paths_),
+  };
+  FieldMask_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FieldMask_descriptor_,
+      FieldMask::default_instance_,
+      FieldMask_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(FieldMask),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FieldMask_descriptor_, &FieldMask::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto() {
+  delete FieldMask::default_instance_;
+  delete FieldMask_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n google/protobuf/field_mask.proto\022\017goog"
+    "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
+    "Q\n\023com.google.protobufB\016FieldMaskProtoP\001"
+    "\240\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTyp"
+    "esb\006proto3", 170);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/field_mask.proto", &protobuf_RegisterTypes);
+  FieldMask::default_instance_ = new FieldMask();
+  FieldMask::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2ffield_5fmask_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FieldMask::kPathsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FieldMask::FieldMask()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FieldMask)
+}
+
+void FieldMask::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+FieldMask::FieldMask(const FieldMask& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask)
+}
+
+void FieldMask::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+}
+
+FieldMask::~FieldMask() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FieldMask)
+  SharedDtor();
+}
+
+void FieldMask::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void FieldMask::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FieldMask::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FieldMask_descriptor_;
+}
+
+const FieldMask& FieldMask::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+  return *default_instance_;
+}
+
+FieldMask* FieldMask::default_instance_ = NULL;
+
+FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const {
+  FieldMask* n = new FieldMask;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void FieldMask::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
+  paths_.Clear();
+}
+
+bool FieldMask::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FieldMask)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated string paths = 1;
+      case 1: {
+        if (tag == 10) {
+         parse_paths:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_paths()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->paths(this->paths_size() - 1).data(),
+            this->paths(this->paths_size() - 1).length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.FieldMask.paths"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_paths;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FieldMask)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FieldMask)
+  return false;
+#undef DO_
+}
+
+void FieldMask::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FieldMask)
+  // repeated string paths = 1;
+  for (int i = 0; i < this->paths_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->paths(i).data(), this->paths(i).length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.FieldMask.paths");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->paths(i), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FieldMask)
+}
+
+::google::protobuf::uint8* FieldMask::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
+  // repeated string paths = 1;
+  for (int i = 0; i < this->paths_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->paths(i).data(), this->paths(i).length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.FieldMask.paths");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(1, this->paths(i), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask)
+  return target;
+}
+
+int FieldMask::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
+  int total_size = 0;
+
+  // repeated string paths = 1;
+  total_size += 1 * this->paths_size();
+  for (int i = 0; i < this->paths_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->paths(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldMask* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask)
+    MergeFrom(*source);
+  }
+}
+
+void FieldMask::MergeFrom(const FieldMask& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  paths_.MergeFrom(from.paths_);
+}
+
+void FieldMask::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldMask::CopyFrom(const FieldMask& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldMask)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FieldMask::IsInitialized() const {
+
+  return true;
+}
+
+void FieldMask::Swap(FieldMask* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void FieldMask::InternalSwap(FieldMask* other) {
+  paths_.UnsafeArenaSwap(&other->paths_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FieldMask::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FieldMask_descriptor_;
+  metadata.reflection = FieldMask_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldMask
+
+// repeated string paths = 1;
+int FieldMask::paths_size() const {
+  return paths_.size();
+}
+void FieldMask::clear_paths() {
+  paths_.Clear();
+}
+ const ::std::string& FieldMask::paths(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
+  return paths_.Get(index);
+}
+ ::std::string* FieldMask::mutable_paths(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
+  return paths_.Mutable(index);
+}
+ void FieldMask::set_paths(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
+  paths_.Mutable(index)->assign(value);
+}
+ void FieldMask::set_paths(int index, const char* value) {
+  paths_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::set_paths(int index, const char* value, size_t size) {
+  paths_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
+}
+ ::std::string* FieldMask::add_paths() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
+  return paths_.Add();
+}
+ void FieldMask::add_paths(const ::std::string& value) {
+  paths_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::add_paths(const char* value) {
+  paths_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::add_paths(const char* value, size_t size) {
+  paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FieldMask::paths() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
+  return paths_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FieldMask::mutable_paths() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
+  return &paths_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.h b/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.h
new file mode 100644
index 0000000..f5e0b65
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/field_mask.pb.h
@@ -0,0 +1,202 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto();
+
+class FieldMask;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message {
+ public:
+  FieldMask();
+  virtual ~FieldMask();
+
+  FieldMask(const FieldMask& from);
+
+  inline FieldMask& operator=(const FieldMask& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FieldMask& default_instance();
+
+  void Swap(FieldMask* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FieldMask* New() const { return New(NULL); }
+
+  FieldMask* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FieldMask& from);
+  void MergeFrom(const FieldMask& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FieldMask* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated string paths = 1;
+  int paths_size() const;
+  void clear_paths();
+  static const int kPathsFieldNumber = 1;
+  const ::std::string& paths(int index) const;
+  ::std::string* mutable_paths(int index);
+  void set_paths(int index, const ::std::string& value);
+  void set_paths(int index, const char* value);
+  void set_paths(int index, const char* value, size_t size);
+  ::std::string* add_paths();
+  void add_paths(const ::std::string& value);
+  void add_paths(const char* value);
+  void add_paths(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& paths() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_paths();
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.FieldMask)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> paths_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto();
+
+  void InitAsDefaultInstance();
+  static FieldMask* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldMask
+
+// repeated string paths = 1;
+inline int FieldMask::paths_size() const {
+  return paths_.size();
+}
+inline void FieldMask::clear_paths() {
+  paths_.Clear();
+}
+inline const ::std::string& FieldMask::paths(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
+  return paths_.Get(index);
+}
+inline ::std::string* FieldMask::mutable_paths(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
+  return paths_.Mutable(index);
+}
+inline void FieldMask::set_paths(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
+  paths_.Mutable(index)->assign(value);
+}
+inline void FieldMask::set_paths(int index, const char* value) {
+  paths_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::set_paths(int index, const char* value, size_t size) {
+  paths_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
+}
+inline ::std::string* FieldMask::add_paths() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
+  return paths_.Add();
+}
+inline void FieldMask::add_paths(const ::std::string& value) {
+  paths_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::add_paths(const char* value) {
+  paths_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::add_paths(const char* value, size_t size) {
+  paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FieldMask::paths() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
+  return paths_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+FieldMask::mutable_paths() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
+  return &paths_;
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/field_mask.proto b/src/third_party/protobuf-3/src/google/protobuf/field_mask.proto
new file mode 100644
index 0000000..6af6dbe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/field_mask.proto
@@ -0,0 +1,194 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldMaskProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option java_generate_equals_and_hash = true;
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+//     paths: "f.a"
+//     paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+//
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+//     f {
+//       a : 22
+//       b {
+//         d : 1
+//         x : 2
+//       }
+//       y : 13
+//     }
+//     z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (their value will be set to the default, and omitted in proto text
+// output):
+//
+//
+//     f {
+//       a : 22
+//       b {
+//         d : 1
+//       }
+//     }
+//
+// A repeated field is not allowed except at the last position of a
+// field mask.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily apply to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API.  In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+//
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+//
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+//
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+//     message Profile {
+//       User user = 1;
+//       Photo photo = 2;
+//     }
+//     message User {
+//       string display_name = 1;
+//       string address = 2;
+//     }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+//     mask {
+//       paths: "user.display_name"
+//       paths: "photo"
+//     }
+//
+// In JSON, the same mask is represented as below:
+//
+//     {
+//       mask: "user.displayName,photo"
+//     }
+//
+// # Field Masks and Oneof Fields
+//
+// Field masks treat fields in oneofs just as regular fields. Consider the
+// following message:
+//
+//     message SampleMessage {
+//       oneof test_oneof {
+//         string name = 4;
+//         SubMessage sub_message = 9;
+//       }
+//     }
+//
+// The field mask can be:
+//
+//     mask {
+//       paths: "name"
+//     }
+//
+// Or:
+//
+//     mask {
+//       paths: "sub_message"
+//     }
+//
+// Note that oneof type names ("test_oneof" in this case) cannot be used in
+// paths.
+message FieldMask {
+  // The set of field mask paths.
+  repeated string paths = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_enum_reflection.h b/src/third_party/protobuf-3/src/google/protobuf/generated_enum_reflection.h
new file mode 100644
index 0000000..fdcdc27
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_enum_reflection.h
@@ -0,0 +1,88 @@
+// 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.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+// It provides reflection support for generated enums, and is included in
+// generated .pb.h files and should have minimal dependencies. The methods are
+// implemented in generated_message_reflection.cc.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/template_util.h>
+#include <google/protobuf/generated_enum_util.h>
+
+namespace google {
+namespace protobuf {
+  class EnumDescriptor;
+}  // namespace protobuf
+
+namespace protobuf {
+
+// Returns the EnumDescriptor for enum type E, which must be a
+// proto-declared enum type.  Code generated by the protocol compiler
+// will include specializations of this template for each enum type declared.
+template <typename E>
+const EnumDescriptor* GetEnumDescriptor();
+
+namespace internal {
+
+// Helper for EnumType_Parse functions: try to parse the string 'name' as an
+// enum name of the given type, returning true and filling in value on success,
+// or returning false and leaving value unchanged on failure.
+LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
+                    const string& name,
+                    int* value);
+
+template<typename EnumType>
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+                    const string& name,
+                    EnumType* value) {
+  int tmp;
+  if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
+  *value = static_cast<EnumType>(tmp);
+  return true;
+}
+
+// Just a wrapper around printing the name of a value. The main point of this
+// function is not to be inlined, so that you can do this without including
+// descriptor.h.
+LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_enum_util.h b/src/third_party/protobuf-3/src/google/protobuf/generated_enum_util.h
new file mode 100644
index 0000000..e424205
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_enum_util.h
@@ -0,0 +1,46 @@
+// 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_GENERATED_ENUM_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+
+#include <google/protobuf/stubs/template_util.h>
+
+namespace google {
+namespace protobuf {
+
+// This type trait can be used to cause templates to only match proto2 enum
+// types.
+template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.cc b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.cc
new file mode 100644
index 0000000..2313181
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.cc
@@ -0,0 +1,2318 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <set>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/repeated_field.h>
+
+
+#define GOOGLE_PROTOBUF_HAS_ONEOF
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+bool IsMapFieldInApi(const FieldDescriptor* field) {
+  return field->is_map();
+}
+}  // anonymous namespace
+
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+                    const string& name,
+                    int* value) {
+  const EnumValueDescriptor* d = descriptor->FindValueByName(name);
+  if (d == NULL) return false;
+  *value = d->number();
+  return true;
+}
+
+const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
+  const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
+  return (d == NULL ? GetEmptyString() : d->name());
+}
+
+namespace {
+inline bool SupportsArenas(const Descriptor* descriptor) {
+  return descriptor->file()->options().cc_enable_arenas();
+}
+}  // anonymous namespace
+
+// ===================================================================
+// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
+// a string field).
+
+namespace {
+
+void ReportReflectionUsageError(
+    const Descriptor* descriptor, const FieldDescriptor* field,
+    const char* method, const char* description) {
+  GOOGLE_LOG(FATAL)
+    << "Protocol Buffer reflection usage error:\n"
+       "  Method      : google::protobuf::Reflection::" << method << "\n"
+       "  Message type: " << descriptor->full_name() << "\n"
+       "  Field       : " << field->full_name() << "\n"
+       "  Problem     : " << description;
+}
+
+const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
+  "INVALID_CPPTYPE",
+  "CPPTYPE_INT32",
+  "CPPTYPE_INT64",
+  "CPPTYPE_UINT32",
+  "CPPTYPE_UINT64",
+  "CPPTYPE_DOUBLE",
+  "CPPTYPE_FLOAT",
+  "CPPTYPE_BOOL",
+  "CPPTYPE_ENUM",
+  "CPPTYPE_STRING",
+  "CPPTYPE_MESSAGE"
+};
+
+static void ReportReflectionUsageTypeError(
+    const Descriptor* descriptor, const FieldDescriptor* field,
+    const char* method,
+    FieldDescriptor::CppType expected_type) {
+  GOOGLE_LOG(FATAL)
+    << "Protocol Buffer reflection usage error:\n"
+       "  Method      : google::protobuf::Reflection::" << method << "\n"
+       "  Message type: " << descriptor->full_name() << "\n"
+       "  Field       : " << field->full_name() << "\n"
+       "  Problem     : Field is not the right type for this message:\n"
+       "    Expected  : " << cpptype_names_[expected_type] << "\n"
+       "    Field type: " << cpptype_names_[field->cpp_type()];
+}
+
+static void ReportReflectionUsageEnumTypeError(
+    const Descriptor* descriptor, const FieldDescriptor* field,
+    const char* method, const EnumValueDescriptor* value) {
+  GOOGLE_LOG(FATAL)
+    << "Protocol Buffer reflection usage error:\n"
+       "  Method      : google::protobuf::Reflection::" << method << "\n"
+       "  Message type: " << descriptor->full_name() << "\n"
+       "  Field       : " << field->full_name() << "\n"
+       "  Problem     : Enum value did not match field type:\n"
+       "    Expected  : " << field->enum_type()->full_name() << "\n"
+       "    Actual    : " << value->full_name();
+}
+
+#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION)                      \
+  if (!(CONDITION))                                                            \
+    ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
+#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION)                        \
+  USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
+#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION)                        \
+  USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
+
+#define USAGE_CHECK_TYPE(METHOD, CPPTYPE)                                      \
+  if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE)                 \
+    ReportReflectionUsageTypeError(descriptor_, field, #METHOD,                \
+                                   FieldDescriptor::CPPTYPE_##CPPTYPE)
+
+#define USAGE_CHECK_ENUM_VALUE(METHOD)                                         \
+  if (value->type() != field->enum_type())                                     \
+    ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
+
+#define USAGE_CHECK_MESSAGE_TYPE(METHOD)                                       \
+  USAGE_CHECK_EQ(field->containing_type(), descriptor_,                        \
+                 METHOD, "Field does not match message type.");
+#define USAGE_CHECK_SINGULAR(METHOD)                                           \
+  USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD,      \
+                 "Field is repeated; the method requires a singular field.")
+#define USAGE_CHECK_REPEATED(METHOD)                                           \
+  USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD,      \
+                 "Field is singular; the method requires a repeated field.")
+
+#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE)                       \
+    USAGE_CHECK_MESSAGE_TYPE(METHOD);                                 \
+    USAGE_CHECK_##LABEL(METHOD);                                      \
+    USAGE_CHECK_TYPE(METHOD, CPPTYPE)
+
+}  // namespace
+
+// ===================================================================
+
+GeneratedMessageReflection::GeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    const DescriptorPool* descriptor_pool,
+    MessageFactory* factory,
+    int object_size,
+    int arena_offset,
+    int is_default_instance_offset)
+  : descriptor_       (descriptor),
+    default_instance_ (default_instance),
+    offsets_          (offsets),
+    has_bits_offset_  (has_bits_offset),
+    unknown_fields_offset_(unknown_fields_offset),
+    extensions_offset_(extensions_offset),
+    arena_offset_     (arena_offset),
+    is_default_instance_offset_(is_default_instance_offset),
+    object_size_      (object_size),
+    descriptor_pool_  ((descriptor_pool == NULL) ?
+                         DescriptorPool::generated_pool() :
+                         descriptor_pool),
+    message_factory_  (factory) {
+}
+
+GeneratedMessageReflection::GeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    const void* default_oneof_instance,
+    int oneof_case_offset,
+    const DescriptorPool* descriptor_pool,
+    MessageFactory* factory,
+    int object_size,
+    int arena_offset,
+    int is_default_instance_offset)
+  : descriptor_       (descriptor),
+    default_instance_ (default_instance),
+    default_oneof_instance_ (default_oneof_instance),
+    offsets_          (offsets),
+    has_bits_offset_  (has_bits_offset),
+    oneof_case_offset_(oneof_case_offset),
+    unknown_fields_offset_(unknown_fields_offset),
+    extensions_offset_(extensions_offset),
+    arena_offset_     (arena_offset),
+    is_default_instance_offset_(is_default_instance_offset),
+    object_size_      (object_size),
+    descriptor_pool_  ((descriptor_pool == NULL) ?
+                         DescriptorPool::generated_pool() :
+                         descriptor_pool),
+    message_factory_  (factory) {
+}
+
+GeneratedMessageReflection::~GeneratedMessageReflection() {}
+
+namespace {
+UnknownFieldSet* empty_unknown_field_set_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
+
+void DeleteEmptyUnknownFieldSet() {
+  delete empty_unknown_field_set_;
+  empty_unknown_field_set_ = NULL;
+}
+
+void InitEmptyUnknownFieldSet() {
+  empty_unknown_field_set_ = new UnknownFieldSet;
+  internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
+}
+
+const UnknownFieldSet& GetEmptyUnknownFieldSet() {
+  ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet);
+  return *empty_unknown_field_set_;
+}
+}  // namespace
+
+const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
+    const Message& message) const {
+  if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    return GetEmptyUnknownFieldSet();
+  }
+  if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+    return GetInternalMetadataWithArena(message).unknown_fields();
+  }
+  const void* ptr = reinterpret_cast<const uint8*>(&message) +
+                    unknown_fields_offset_;
+  return *reinterpret_cast<const UnknownFieldSet*>(ptr);
+}
+
+UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
+    Message* message) const {
+  if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+    return MutableInternalMetadataWithArena(message)->
+        mutable_unknown_fields();
+  }
+  void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
+  return reinterpret_cast<UnknownFieldSet*>(ptr);
+}
+
+int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
+  // object_size_ already includes the in-memory representation of each field
+  // in the message, so we only need to account for additional memory used by
+  // the fields.
+  int total_size = object_size_;
+
+  total_size += GetUnknownFields(message).SpaceUsedExcludingSelf();
+
+  if (extensions_offset_ != -1) {
+    total_size += GetExtensionSet(message).SpaceUsedExcludingSelf();
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+
+    if (field->is_repeated()) {
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+        case FieldDescriptor::CPPTYPE_##UPPERCASE :                           \
+          total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field)     \
+                          .SpaceUsedExcludingSelf();                          \
+          break
+
+        HANDLE_TYPE( INT32,  int32);
+        HANDLE_TYPE( INT64,  int64);
+        HANDLE_TYPE(UINT32, uint32);
+        HANDLE_TYPE(UINT64, uint64);
+        HANDLE_TYPE(DOUBLE, double);
+        HANDLE_TYPE( FLOAT,  float);
+        HANDLE_TYPE(  BOOL,   bool);
+        HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_STRING:
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING:
+              total_size += GetRaw<RepeatedPtrField<string> >(message, field)
+                              .SpaceUsedExcludingSelf();
+              break;
+          }
+          break;
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          if (IsMapFieldInApi(field)) {
+            total_size +=
+                GetRaw<MapFieldBase>(message, field).SpaceUsedExcludingSelf();
+          } else {
+            // We don't know which subclass of RepeatedPtrFieldBase the type is,
+            // so we use RepeatedPtrFieldBase directly.
+            total_size +=
+                GetRaw<RepeatedPtrFieldBase>(message, field)
+                  .SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
+          }
+
+          break;
+      }
+    } else {
+      if (field->containing_oneof() && !HasOneofField(message, field)) {
+        continue;
+      }
+      switch (field->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_INT32 :
+        case FieldDescriptor::CPPTYPE_INT64 :
+        case FieldDescriptor::CPPTYPE_UINT32:
+        case FieldDescriptor::CPPTYPE_UINT64:
+        case FieldDescriptor::CPPTYPE_DOUBLE:
+        case FieldDescriptor::CPPTYPE_FLOAT :
+        case FieldDescriptor::CPPTYPE_BOOL  :
+        case FieldDescriptor::CPPTYPE_ENUM  :
+          // Field is inline, so we've already counted it.
+          break;
+
+        case FieldDescriptor::CPPTYPE_STRING: {
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING: {
+              // Initially, the string points to the default value stored in
+              // the prototype. Only count the string if it has been changed
+              // from the default value.
+              const string* default_ptr =
+                  &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+              const string* ptr =
+                  &GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+
+              if (ptr != default_ptr) {
+                // string fields are represented by just a pointer, so also
+                // include sizeof(string) as well.
+                total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
+              }
+              break;
+            }
+          }
+          break;
+        }
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          if (&message == default_instance_) {
+            // For singular fields, the prototype just stores a pointer to the
+            // external type's prototype, so there is no extra memory usage.
+          } else {
+            const Message* sub_message = GetRaw<const Message*>(message, field);
+            if (sub_message != NULL) {
+              total_size += sub_message->SpaceUsed();
+            }
+          }
+          break;
+      }
+    }
+  }
+
+  return total_size;
+}
+
+void GeneratedMessageReflection::SwapField(
+    Message* message1,
+    Message* message2,
+    const FieldDescriptor* field) const {
+  if (field->is_repeated()) {
+    switch (field->cpp_type()) {
+#define SWAP_ARRAYS(CPPTYPE, TYPE)                                      \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+        MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap(        \
+            MutableRaw<RepeatedField<TYPE> >(message2, field));         \
+        break;
+
+      SWAP_ARRAYS(INT32 , int32 );
+      SWAP_ARRAYS(INT64 , int64 );
+      SWAP_ARRAYS(UINT32, uint32);
+      SWAP_ARRAYS(UINT64, uint64);
+      SWAP_ARRAYS(FLOAT , float );
+      SWAP_ARRAYS(DOUBLE, double);
+      SWAP_ARRAYS(BOOL  , bool  );
+      SWAP_ARRAYS(ENUM  , int   );
+#undef SWAP_ARRAYS
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+                Swap<GenericTypeHandler<string> >(
+                    MutableRaw<RepeatedPtrFieldBase>(message2, field));
+            break;
+        }
+        break;
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message1, field)->
+            MutableRepeatedField()->
+              Swap<GenericTypeHandler<google::protobuf::Message> >(
+                MutableRaw<MapFieldBase>(message2, field)->
+                  MutableRepeatedField());
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+            Swap<GenericTypeHandler<google::protobuf::Message> >(
+              MutableRaw<RepeatedPtrFieldBase>(message2, field));
+        }
+        break;
+
+      default:
+        GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+    }
+  } else {
+    switch (field->cpp_type()) {
+#define SWAP_VALUES(CPPTYPE, TYPE)                                      \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+        std::swap(*MutableRaw<TYPE>(message1, field),                   \
+                  *MutableRaw<TYPE>(message2, field));                  \
+        break;
+
+      SWAP_VALUES(INT32 , int32 );
+      SWAP_VALUES(INT64 , int64 );
+      SWAP_VALUES(UINT32, uint32);
+      SWAP_VALUES(UINT64, uint64);
+      SWAP_VALUES(FLOAT , float );
+      SWAP_VALUES(DOUBLE, double);
+      SWAP_VALUES(BOOL  , bool  );
+      SWAP_VALUES(ENUM  , int   );
+#undef SWAP_VALUES
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (GetArena(message1) == GetArena(message2)) {
+          std::swap(*MutableRaw<Message*>(message1, field),
+                    *MutableRaw<Message*>(message2, field));
+        } else {
+          Message** sub_msg1 = MutableRaw<Message*>(message1, field);
+          Message** sub_msg2 = MutableRaw<Message*>(message2, field);
+          if (*sub_msg1 == NULL && *sub_msg2 == NULL) break;
+          if (*sub_msg1 && *sub_msg2) {
+            (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2);
+            break;
+          }
+          if (*sub_msg1 == NULL) {
+            *sub_msg1 = (*sub_msg2)->New(message1->GetArena());
+            (*sub_msg1)->CopyFrom(**sub_msg2);
+            ClearField(message2, field);
+          } else {
+            *sub_msg2 = (*sub_msg1)->New(message2->GetArena());
+            (*sub_msg2)->CopyFrom(**sub_msg1);
+            ClearField(message1, field);
+          }
+        }
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            {
+              Arena* arena1 = GetArena(message1);
+              Arena* arena2 = GetArena(message2);
+              ArenaStringPtr* string1 =
+                  MutableRaw<ArenaStringPtr>(message1, field);
+              ArenaStringPtr* string2 =
+                  MutableRaw<ArenaStringPtr>(message2, field);
+              if (arena1 == arena2) {
+                string1->Swap(string2);
+              } else {
+                const string* default_ptr =
+                    &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+                const string temp = string1->Get(default_ptr);
+                string1->Set(default_ptr, string2->Get(default_ptr), arena1);
+                string2->Set(default_ptr, temp, arena2);
+              }
+            }
+            break;
+        }
+        break;
+
+      default:
+        GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+    }
+  }
+}
+
+void GeneratedMessageReflection::SwapOneofField(
+    Message* message1,
+    Message* message2,
+    const OneofDescriptor* oneof_descriptor) const {
+  uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
+  uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
+
+  int32 temp_int32;
+  int64 temp_int64;
+  uint32 temp_uint32;
+  uint64 temp_uint64;
+  float temp_float;
+  double temp_double;
+  bool temp_bool;
+  int temp_int;
+  Message* temp_message = NULL;
+  string temp_string;
+
+  // Stores message1's oneof field to a temp variable.
+  const FieldDescriptor* field1 = NULL;
+  if (oneof_case1 > 0) {
+    field1 = descriptor_->FindFieldByNumber(oneof_case1);
+    //oneof_descriptor->field(oneof_case1);
+    switch (field1->cpp_type()) {
+#define GET_TEMP_VALUE(CPPTYPE, TYPE)                                   \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+        temp_##TYPE = GetField<TYPE>(*message1, field1);                \
+        break;
+
+      GET_TEMP_VALUE(INT32 , int32 );
+      GET_TEMP_VALUE(INT64 , int64 );
+      GET_TEMP_VALUE(UINT32, uint32);
+      GET_TEMP_VALUE(UINT64, uint64);
+      GET_TEMP_VALUE(FLOAT , float );
+      GET_TEMP_VALUE(DOUBLE, double);
+      GET_TEMP_VALUE(BOOL  , bool  );
+      GET_TEMP_VALUE(ENUM  , int   );
+#undef GET_TEMP_VALUE
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        temp_message = ReleaseMessage(message1, field1);
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        temp_string = GetString(*message1, field1);
+        break;
+
+      default:
+        GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
+    }
+  }
+
+  // Sets message1's oneof field from the message2's oneof field.
+  if (oneof_case2 > 0) {
+    const FieldDescriptor* field2 =
+        descriptor_->FindFieldByNumber(oneof_case2);
+    switch (field2->cpp_type()) {
+#define SET_ONEOF_VALUE1(CPPTYPE, TYPE)                                 \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+        SetField<TYPE>(message1, field2, GetField<TYPE>(*message2, field2)); \
+        break;
+
+      SET_ONEOF_VALUE1(INT32 , int32 );
+      SET_ONEOF_VALUE1(INT64 , int64 );
+      SET_ONEOF_VALUE1(UINT32, uint32);
+      SET_ONEOF_VALUE1(UINT64, uint64);
+      SET_ONEOF_VALUE1(FLOAT , float );
+      SET_ONEOF_VALUE1(DOUBLE, double);
+      SET_ONEOF_VALUE1(BOOL  , bool  );
+      SET_ONEOF_VALUE1(ENUM  , int   );
+#undef SET_ONEOF_VALUE1
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        SetAllocatedMessage(message1,
+                            ReleaseMessage(message2, field2),
+                            field2);
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        SetString(message1, field2, GetString(*message2, field2));
+        break;
+
+      default:
+        GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type();
+    }
+  } else {
+    ClearOneof(message1, oneof_descriptor);
+  }
+
+  // Sets message2's oneof field from the temp variable.
+  if (oneof_case1 > 0) {
+    switch (field1->cpp_type()) {
+#define SET_ONEOF_VALUE2(CPPTYPE, TYPE)                                 \
+      case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+        SetField<TYPE>(message2, field1, temp_##TYPE);                  \
+        break;
+
+      SET_ONEOF_VALUE2(INT32 , int32 );
+      SET_ONEOF_VALUE2(INT64 , int64 );
+      SET_ONEOF_VALUE2(UINT32, uint32);
+      SET_ONEOF_VALUE2(UINT64, uint64);
+      SET_ONEOF_VALUE2(FLOAT , float );
+      SET_ONEOF_VALUE2(DOUBLE, double);
+      SET_ONEOF_VALUE2(BOOL  , bool  );
+      SET_ONEOF_VALUE2(ENUM  , int   );
+#undef SET_ONEOF_VALUE2
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        SetAllocatedMessage(message2, temp_message, field1);
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        SetString(message2, field1, temp_string);
+        break;
+
+      default:
+        GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type();
+    }
+  } else {
+    ClearOneof(message2, oneof_descriptor);
+  }
+}
+
+void GeneratedMessageReflection::Swap(
+    Message* message1,
+    Message* message2) const {
+  if (message1 == message2) return;
+
+  // TODO(kenton):  Other Reflection methods should probably check this too.
+  GOOGLE_CHECK_EQ(message1->GetReflection(), this)
+    << "First argument to Swap() (of type \""
+    << message1->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
+  GOOGLE_CHECK_EQ(message2->GetReflection(), this)
+    << "Second argument to Swap() (of type \""
+    << message2->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
+
+  // Check that both messages are in the same arena (or both on the heap). We
+  // need to copy all data if not, due to ownership semantics.
+  if (GetArena(message1) != GetArena(message2)) {
+    // Slow copy path.
+    // Use our arena as temp space, if available.
+    Message* temp = message1->New(GetArena(message1));
+    temp->MergeFrom(*message1);
+    message1->CopyFrom(*message2);
+    message2->CopyFrom(*temp);
+    if (GetArena(message1) == NULL) {
+      delete temp;
+    }
+    return;
+  }
+
+  if (has_bits_offset_ != -1) {
+    uint32* has_bits1 = MutableHasBits(message1);
+    uint32* has_bits2 = MutableHasBits(message2);
+    int has_bits_size = (descriptor_->field_count() + 31) / 32;
+
+    for (int i = 0; i < has_bits_size; i++) {
+      std::swap(has_bits1[i], has_bits2[i]);
+    }
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->containing_oneof()) {
+      SwapField(message1, message2, field);
+    }
+  }
+
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    SwapOneofField(message1, message2, descriptor_->oneof_decl(i));
+  }
+
+  if (extensions_offset_ != -1) {
+    MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
+  }
+
+  MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
+}
+
+void GeneratedMessageReflection::SwapFields(
+    Message* message1,
+    Message* message2,
+    const vector<const FieldDescriptor*>& fields) const {
+  if (message1 == message2) return;
+
+  // TODO(kenton):  Other Reflection methods should probably check this too.
+  GOOGLE_CHECK_EQ(message1->GetReflection(), this)
+    << "First argument to SwapFields() (of type \""
+    << message1->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
+  GOOGLE_CHECK_EQ(message2->GetReflection(), this)
+    << "Second argument to SwapFields() (of type \""
+    << message2->GetDescriptor()->full_name()
+    << "\") is not compatible with this reflection object (which is for type \""
+    << descriptor_->full_name()
+    << "\").  Note that the exact same class is required; not just the same "
+       "descriptor.";
+
+  std::set<int> swapped_oneof;
+
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    if (field->is_extension()) {
+      MutableExtensionSet(message1)->SwapExtension(
+          MutableExtensionSet(message2),
+          field->number());
+    } else {
+      if (field->containing_oneof()) {
+        int oneof_index = field->containing_oneof()->index();
+        // Only swap the oneof field once.
+        if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) {
+          continue;
+        }
+        swapped_oneof.insert(oneof_index);
+        SwapOneofField(message1, message2, field->containing_oneof());
+      } else {
+        // Swap has bit.
+        SwapBit(message1, message2, field);
+        // Swap field.
+        SwapField(message1, message2, field);
+      }
+    }
+  }
+}
+
+// -------------------------------------------------------------------
+
+bool GeneratedMessageReflection::HasField(const Message& message,
+                                          const FieldDescriptor* field) const {
+  USAGE_CHECK_MESSAGE_TYPE(HasField);
+  USAGE_CHECK_SINGULAR(HasField);
+
+  if (field->is_extension()) {
+    return GetExtensionSet(message).Has(field->number());
+  } else {
+    if (field->containing_oneof()) {
+      return HasOneofField(message, field);
+    } else {
+      return HasBit(message, field);
+    }
+  }
+}
+
+int GeneratedMessageReflection::FieldSize(const Message& message,
+                                          const FieldDescriptor* field) const {
+  USAGE_CHECK_MESSAGE_TYPE(FieldSize);
+  USAGE_CHECK_REPEATED(FieldSize);
+
+  if (field->is_extension()) {
+    return GetExtensionSet(message).ExtensionSize(field->number());
+  } else {
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
+        } else {
+          return GetRaw<RepeatedPtrFieldBase>(message, field).size();
+        }
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return 0;
+  }
+}
+
+void GeneratedMessageReflection::ClearField(
+    Message* message, const FieldDescriptor* field) const {
+  USAGE_CHECK_MESSAGE_TYPE(ClearField);
+
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->ClearExtension(field->number());
+  } else if (!field->is_repeated()) {
+    if (field->containing_oneof()) {
+      ClearOneofField(message, field);
+      return;
+    }
+
+    if (HasBit(*message, field)) {
+      ClearBit(message, field);
+
+      // We need to set the field back to its default value.
+      switch (field->cpp_type()) {
+#define CLEAR_TYPE(CPPTYPE, TYPE)                                            \
+        case FieldDescriptor::CPPTYPE_##CPPTYPE:                             \
+          *MutableRaw<TYPE>(message, field) =                                \
+            field->default_value_##TYPE();                                   \
+          break;
+
+        CLEAR_TYPE(INT32 , int32 );
+        CLEAR_TYPE(INT64 , int64 );
+        CLEAR_TYPE(UINT32, uint32);
+        CLEAR_TYPE(UINT64, uint64);
+        CLEAR_TYPE(FLOAT , float );
+        CLEAR_TYPE(DOUBLE, double);
+        CLEAR_TYPE(BOOL  , bool  );
+#undef CLEAR_TYPE
+
+        case FieldDescriptor::CPPTYPE_ENUM:
+          *MutableRaw<int>(message, field) =
+            field->default_value_enum()->number();
+          break;
+
+        case FieldDescriptor::CPPTYPE_STRING: {
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING: {
+              const string* default_ptr =
+                  &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+              MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
+                  GetArena(message));
+              break;
+            }
+          }
+          break;
+        }
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          if (has_bits_offset_ == -1) {
+            // Proto3 does not have has-bits and we need to set a message field
+            // to NULL in order to indicate its un-presence.
+            if (GetArena(message) == NULL) {
+              delete *MutableRaw<Message*>(message, field);
+            }
+            *MutableRaw<Message*>(message, field) = NULL;
+          } else {
+            (*MutableRaw<Message*>(message, field))->Clear();
+          }
+          break;
+      }
+    }
+  } else {
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear();       \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING: {
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+            break;
+        }
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_MESSAGE: {
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->Clear<GenericTypeHandler<Message> >();
+        } else {
+          // We don't know which subclass of RepeatedPtrFieldBase the type is,
+          // so we use RepeatedPtrFieldBase directly.
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
+              ->Clear<GenericTypeHandler<Message> >();
+        }
+        break;
+      }
+    }
+  }
+}
+
+void GeneratedMessageReflection::RemoveLast(
+    Message* message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
+  USAGE_CHECK_REPEATED(RemoveLast);
+
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->RemoveLast(field->number());
+  } else {
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast();  \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+            break;
+        }
+        break;
+
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->RemoveLast<GenericTypeHandler<Message> >();
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
+            ->RemoveLast<GenericTypeHandler<Message> >();
+        }
+        break;
+    }
+  }
+}
+
+Message* GeneratedMessageReflection::ReleaseLast(
+    Message* message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->ReleaseLast(field->number()));
+  } else {
+    if (IsMapFieldInApi(field)) {
+      return MutableRaw<MapFieldBase>(message, field)
+          ->MutableRepeatedField()
+          ->ReleaseLast<GenericTypeHandler<Message> >();
+    } else {
+      return MutableRaw<RepeatedPtrFieldBase>(message, field)
+        ->ReleaseLast<GenericTypeHandler<Message> >();
+    }
+  }
+}
+
+void GeneratedMessageReflection::SwapElements(
+    Message* message,
+    const FieldDescriptor* field,
+    int index1,
+    int index2) const {
+  USAGE_CHECK_MESSAGE_TYPE(Swap);
+  USAGE_CHECK_REPEATED(Swap);
+
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
+  } else {
+    switch (field->cpp_type()) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
+      case FieldDescriptor::CPPTYPE_##UPPERCASE :                             \
+        MutableRaw<RepeatedField<LOWERCASE> >(message, field)                 \
+            ->SwapElements(index1, index2);                                   \
+        break
+
+      HANDLE_TYPE( INT32,  int32);
+      HANDLE_TYPE( INT64,  int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE( FLOAT,  float);
+      HANDLE_TYPE(  BOOL,   bool);
+      HANDLE_TYPE(  ENUM,    int);
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::CPPTYPE_STRING:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        if (IsMapFieldInApi(field)) {
+          MutableRaw<MapFieldBase>(message, field)
+              ->MutableRepeatedField()
+              ->SwapElements(index1, index2);
+        } else {
+          MutableRaw<RepeatedPtrFieldBase>(message, field)
+            ->SwapElements(index1, index2);
+        }
+        break;
+    }
+  }
+}
+
+namespace {
+// Comparison functor for sorting FieldDescriptors by field number.
+struct FieldNumberSorter {
+  bool operator()(const FieldDescriptor* left,
+                  const FieldDescriptor* right) const {
+    return left->number() < right->number();
+  }
+};
+}  // namespace
+
+void GeneratedMessageReflection::ListFields(
+    const Message& message,
+    vector<const FieldDescriptor*>* output) const {
+  output->clear();
+
+  // Optimization:  The default instance never has any fields set.
+  if (&message == default_instance_) return;
+
+  output->reserve(descriptor_->field_count());
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->is_repeated()) {
+      if (FieldSize(message, field) > 0) {
+        output->push_back(field);
+      }
+    } else {
+      if (field->containing_oneof()) {
+        if (HasOneofField(message, field)) {
+          output->push_back(field);
+        }
+      } else if (HasBit(message, field)) {
+        output->push_back(field);
+      }
+    }
+  }
+
+  if (extensions_offset_ != -1) {
+    GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_,
+                                          output);
+  }
+
+  // ListFields() must sort output by field number.
+  std::sort(output->begin(), output->end(), FieldNumberSorter());
+}
+
+// -------------------------------------------------------------------
+
+#undef DEFINE_PRIMITIVE_ACCESSORS
+#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE)        \
+  PASSTYPE GeneratedMessageReflection::Get##TYPENAME(                        \
+      const Message& message, const FieldDescriptor* field) const {          \
+    USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE);                       \
+    if (field->is_extension()) {                                             \
+      return GetExtensionSet(message).Get##TYPENAME(                         \
+        field->number(), field->default_value_##PASSTYPE());                 \
+    } else {                                                                 \
+      return GetField<TYPE>(message, field);                                 \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  void GeneratedMessageReflection::Set##TYPENAME(                            \
+      Message* message, const FieldDescriptor* field,                        \
+      PASSTYPE value) const {                                                \
+    USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE);                       \
+    if (field->is_extension()) {                                             \
+      return MutableExtensionSet(message)->Set##TYPENAME(                    \
+        field->number(), field->type(), value, field);                       \
+    } else {                                                                 \
+      SetField<TYPE>(message, field, value);                                 \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME(                \
+      const Message& message,                                                \
+      const FieldDescriptor* field, int index) const {                       \
+    USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE);               \
+    if (field->is_extension()) {                                             \
+      return GetExtensionSet(message).GetRepeated##TYPENAME(                 \
+        field->number(), index);                                             \
+    } else {                                                                 \
+      return GetRepeatedField<TYPE>(message, field, index);                  \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  void GeneratedMessageReflection::SetRepeated##TYPENAME(                    \
+      Message* message, const FieldDescriptor* field,                        \
+      int index, PASSTYPE value) const {                                     \
+    USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE);               \
+    if (field->is_extension()) {                                             \
+      MutableExtensionSet(message)->SetRepeated##TYPENAME(                   \
+        field->number(), index, value);                                      \
+    } else {                                                                 \
+      SetRepeatedField<TYPE>(message, field, index, value);                  \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  void GeneratedMessageReflection::Add##TYPENAME(                            \
+      Message* message, const FieldDescriptor* field,                        \
+      PASSTYPE value) const {                                                \
+    USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE);                       \
+    if (field->is_extension()) {                                             \
+      MutableExtensionSet(message)->Add##TYPENAME(                           \
+        field->number(), field->type(), field->options().packed(), value,    \
+        field);                                                              \
+    } else {                                                                 \
+      AddField<TYPE>(message, field, value);                                 \
+    }                                                                        \
+  }
+
+DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 )
+DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 )
+DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32)
+DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64)
+DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT )
+DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
+DEFINE_PRIMITIVE_ACCESSORS(Bool  , bool  , bool  , BOOL  )
+#undef DEFINE_PRIMITIVE_ACCESSORS
+
+// -------------------------------------------------------------------
+
+string GeneratedMessageReflection::GetString(
+    const Message& message, const FieldDescriptor* field) const {
+  USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
+  if (field->is_extension()) {
+    return GetExtensionSet(message).GetString(field->number(),
+                                              field->default_value_string());
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING: {
+        const string* default_ptr =
+            &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+        return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+      }
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return GetEmptyString();  // Make compiler happy.
+  }
+}
+
+const string& GeneratedMessageReflection::GetStringReference(
+    const Message& message,
+    const FieldDescriptor* field, string* scratch) const {
+  USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
+  if (field->is_extension()) {
+    return GetExtensionSet(message).GetString(field->number(),
+                                              field->default_value_string());
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING: {
+        const string* default_ptr =
+            &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+        return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+      }
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return GetEmptyString();  // Make compiler happy.
+  }
+}
+
+
+void GeneratedMessageReflection::SetString(
+    Message* message, const FieldDescriptor* field,
+    const string& value) const {
+  USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
+  if (field->is_extension()) {
+    return MutableExtensionSet(message)->SetString(field->number(),
+                                                   field->type(), value, field);
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING: {
+        const string* default_ptr =
+            &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+        if (field->containing_oneof() && !HasOneofField(*message, field)) {
+          ClearOneof(message, field->containing_oneof());
+          MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault(
+              default_ptr);
+        }
+        MutableField<ArenaStringPtr>(message, field)->Set(default_ptr,
+            value, GetArena(message));
+        break;
+      }
+    }
+  }
+}
+
+
+string GeneratedMessageReflection::GetRepeatedString(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
+  if (field->is_extension()) {
+    return GetExtensionSet(message).GetRepeatedString(field->number(), index);
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING:
+        return GetRepeatedPtrField<string>(message, field, index);
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return GetEmptyString();  // Make compiler happy.
+  }
+}
+
+const string& GeneratedMessageReflection::GetRepeatedStringReference(
+    const Message& message, const FieldDescriptor* field,
+    int index, string* scratch) const {
+  USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
+  if (field->is_extension()) {
+    return GetExtensionSet(message).GetRepeatedString(field->number(), index);
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING:
+        return GetRepeatedPtrField<string>(message, field, index);
+    }
+
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return GetEmptyString();  // Make compiler happy.
+  }
+}
+
+
+void GeneratedMessageReflection::SetRepeatedString(
+    Message* message, const FieldDescriptor* field,
+    int index, const string& value) const {
+  USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->SetRepeatedString(
+      field->number(), index, value);
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING:
+        *MutableRepeatedField<string>(message, field, index) = value;
+        break;
+    }
+  }
+}
+
+
+void GeneratedMessageReflection::AddString(
+    Message* message, const FieldDescriptor* field,
+    const string& value) const {
+  USAGE_CHECK_ALL(AddString, REPEATED, STRING);
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->AddString(field->number(),
+                                            field->type(), value, field);
+  } else {
+    switch (field->options().ctype()) {
+      default:  // TODO(kenton):  Support other string reps.
+      case FieldOptions::STRING:
+        *AddField<string>(message, field) = value;
+        break;
+    }
+  }
+}
+
+
+// -------------------------------------------------------------------
+
+inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
+  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
+    const Message& message, const FieldDescriptor* field) const {
+  // Usage checked by GetEnumValue.
+  int value = GetEnumValue(message, field);
+  return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
+
+int GeneratedMessageReflection::GetEnumValue(
+    const Message& message, const FieldDescriptor* field) const {
+  USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
+
+  int32 value;
+  if (field->is_extension()) {
+    value = GetExtensionSet(message).GetEnum(
+      field->number(), field->default_value_enum()->number());
+  } else {
+    value = GetField<int>(message, field);
+  }
+  return value;
+}
+
+void GeneratedMessageReflection::SetEnum(
+    Message* message, const FieldDescriptor* field,
+    const EnumValueDescriptor* value) const {
+  // Usage checked by SetEnumValue.
+  USAGE_CHECK_ENUM_VALUE(SetEnum);
+  SetEnumValueInternal(message, field, value->number());
+}
+
+void GeneratedMessageReflection::SetEnumValue(
+    Message* message, const FieldDescriptor* field,
+    int value) const {
+  USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
+  if (!CreateUnknownEnumValues(descriptor_->file())) {
+    // Check that the value is valid if we don't support direct storage of
+    // unknown enum values.
+    const EnumValueDescriptor* value_desc =
+        field->enum_type()->FindValueByNumber(value);
+    if (value_desc == NULL) {
+      GOOGLE_LOG(DFATAL) << "SetEnumValue accepts only valid integer values: value "
+                  << value << " unexpected for field " << field->full_name();
+      // In production builds, DFATAL will not terminate the program, so we have
+      // to do something reasonable: just set the default value.
+      value = field->default_value_enum()->number();
+    }
+  }
+  SetEnumValueInternal(message, field, value);
+}
+
+void GeneratedMessageReflection::SetEnumValueInternal(
+    Message* message, const FieldDescriptor* field,
+    int value) const {
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
+                                          value, field);
+  } else {
+    SetField<int>(message, field, value);
+  }
+}
+
+const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  // Usage checked by GetRepeatedEnumValue.
+  int value = GetRepeatedEnumValue(message, field, index);
+  return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
+
+int GeneratedMessageReflection::GetRepeatedEnumValue(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
+
+  int value;
+  if (field->is_extension()) {
+    value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index);
+  } else {
+    value = GetRepeatedField<int>(message, field, index);
+  }
+  return value;
+}
+
+void GeneratedMessageReflection::SetRepeatedEnum(
+    Message* message,
+    const FieldDescriptor* field, int index,
+    const EnumValueDescriptor* value) const {
+  // Usage checked by SetRepeatedEnumValue.
+  USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
+  SetRepeatedEnumValueInternal(message, field, index, value->number());
+}
+
+void GeneratedMessageReflection::SetRepeatedEnumValue(
+    Message* message,
+    const FieldDescriptor* field, int index,
+    int value) const {
+  USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+  if (!CreateUnknownEnumValues(descriptor_->file())) {
+    // Check that the value is valid if we don't support direct storage of
+    // unknown enum values.
+    const EnumValueDescriptor* value_desc =
+        field->enum_type()->FindValueByNumber(value);
+    if (value_desc == NULL) {
+      GOOGLE_LOG(DFATAL) << "SetRepeatedEnumValue accepts only valid integer values: "
+                  << "value " << value << " unexpected for field "
+                  << field->full_name();
+      // In production builds, DFATAL will not terminate the program, so we have
+      // to do something reasonable: just set the default value.
+      value = field->default_value_enum()->number();
+    }
+  }
+  SetRepeatedEnumValueInternal(message, field, index, value);
+}
+
+void GeneratedMessageReflection::SetRepeatedEnumValueInternal(
+    Message* message,
+    const FieldDescriptor* field, int index,
+    int value) const {
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->SetRepeatedEnum(
+      field->number(), index, value);
+  } else {
+    SetRepeatedField<int>(message, field, index, value);
+  }
+}
+
+void GeneratedMessageReflection::AddEnum(
+    Message* message, const FieldDescriptor* field,
+    const EnumValueDescriptor* value) const {
+  // Usage checked by AddEnumValue.
+  USAGE_CHECK_ENUM_VALUE(AddEnum);
+  AddEnumValueInternal(message, field, value->number());
+}
+
+void GeneratedMessageReflection::AddEnumValue(
+    Message* message, const FieldDescriptor* field,
+    int value) const {
+  USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+  if (!CreateUnknownEnumValues(descriptor_->file())) {
+    // Check that the value is valid if we don't support direct storage of
+    // unknown enum values.
+    const EnumValueDescriptor* value_desc =
+        field->enum_type()->FindValueByNumber(value);
+    if (value_desc == NULL) {
+      GOOGLE_LOG(DFATAL) << "AddEnumValue accepts only valid integer values: value "
+                  << value << " unexpected for field " << field->full_name();
+      // In production builds, DFATAL will not terminate the program, so we have
+      // to do something reasonable: just set the default value.
+      value = field->default_value_enum()->number();
+    }
+  }
+  AddEnumValueInternal(message, field, value);
+}
+
+void GeneratedMessageReflection::AddEnumValueInternal(
+    Message* message, const FieldDescriptor* field,
+    int value) const {
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
+                                          field->options().packed(),
+                                          value, field);
+  } else {
+    AddField<int>(message, field, value);
+  }
+}
+
+// -------------------------------------------------------------------
+
+const Message& GeneratedMessageReflection::GetMessage(
+    const Message& message, const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
+
+  if (factory == NULL) factory = message_factory_;
+
+  if (field->is_extension()) {
+    return static_cast<const Message&>(
+        GetExtensionSet(message).GetMessage(
+          field->number(), field->message_type(), factory));
+  } else {
+    const Message* result;
+    result = GetRaw<const Message*>(message, field);
+    if (result == NULL) {
+      result = DefaultRaw<const Message*>(field);
+    }
+    return *result;
+  }
+}
+
+Message* GeneratedMessageReflection::MutableMessage(
+    Message* message, const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+
+  if (factory == NULL) factory = message_factory_;
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->MutableMessage(field, factory));
+  } else {
+    Message* result;
+    Message** result_holder = MutableRaw<Message*>(message, field);
+
+    if (field->containing_oneof()) {
+      if (!HasOneofField(*message, field)) {
+        ClearOneof(message, field->containing_oneof());
+        result_holder = MutableField<Message*>(message, field);
+        const Message* default_message = DefaultRaw<const Message*>(field);
+        *result_holder = default_message->New(message->GetArena());
+      }
+    } else {
+      SetBit(message, field);
+    }
+
+    if (*result_holder == NULL) {
+      const Message* default_message = DefaultRaw<const Message*>(field);
+      *result_holder = default_message->New(message->GetArena());
+    }
+    result = *result_holder;
+    return result;
+  }
+}
+
+void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage(
+    Message* message,
+    Message* sub_message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
+
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->SetAllocatedMessage(
+        field->number(), field->type(), field, sub_message);
+  } else {
+    if (field->containing_oneof()) {
+      if (sub_message == NULL) {
+        ClearOneof(message, field->containing_oneof());
+        return;
+      }
+        ClearOneof(message, field->containing_oneof());
+        *MutableRaw<Message*>(message, field) = sub_message;
+      SetOneofCase(message, field);
+      return;
+    }
+
+    if (sub_message == NULL) {
+      ClearBit(message, field);
+    } else {
+      SetBit(message, field);
+    }
+    Message** sub_message_holder = MutableRaw<Message*>(message, field);
+    if (GetArena(message) == NULL) {
+      delete *sub_message_holder;
+    }
+    *sub_message_holder = sub_message;
+  }
+}
+
+void GeneratedMessageReflection::SetAllocatedMessage(
+    Message* message,
+    Message* sub_message,
+    const FieldDescriptor* field) const {
+  // If message and sub-message are in different memory ownership domains
+  // (different arenas, or one is on heap and one is not), then we may need to
+  // do a copy.
+  if (sub_message != NULL &&
+      sub_message->GetArena() != message->GetArena()) {
+    if (sub_message->GetArena() == NULL && message->GetArena() != NULL) {
+      // Case 1: parent is on an arena and child is heap-allocated. We can add
+      // the child to the arena's Own() list to free on arena destruction, then
+      // set our pointer.
+      message->GetArena()->Own(sub_message);
+      UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+    } else {
+      // Case 2: all other cases. We need to make a copy. MutableMessage() will
+      // either get the existing message object, or instantiate a new one as
+      // appropriate w.r.t. our arena.
+      Message* sub_message_copy = MutableMessage(message, field);
+      sub_message_copy->CopyFrom(*sub_message);
+    }
+  } else {
+    // Same memory ownership domains.
+    UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+  }
+}
+
+Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
+    Message* message,
+    const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
+
+  if (factory == NULL) factory = message_factory_;
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->ReleaseMessage(field, factory));
+  } else {
+    ClearBit(message, field);
+    if (field->containing_oneof()) {
+      if (HasOneofField(*message, field)) {
+        *MutableOneofCase(message, field->containing_oneof()) = 0;
+      } else {
+        return NULL;
+      }
+    }
+    Message** result = MutableRaw<Message*>(message, field);
+    Message* ret = *result;
+    *result = NULL;
+    return ret;
+  }
+}
+
+Message* GeneratedMessageReflection::ReleaseMessage(
+    Message* message,
+    const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  Message* released = UnsafeArenaReleaseMessage(message, field, factory);
+  if (GetArena(message) != NULL && released != NULL) {
+    Message* copy_from_arena = released->New();
+    copy_from_arena->CopyFrom(*released);
+    released = copy_from_arena;
+  }
+  return released;
+}
+
+const Message& GeneratedMessageReflection::GetRepeatedMessage(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
+
+  if (field->is_extension()) {
+    return static_cast<const Message&>(
+        GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
+  } else {
+    if (IsMapFieldInApi(field)) {
+      return GetRaw<MapFieldBase>(message, field)
+          .GetRepeatedField()
+          .Get<GenericTypeHandler<Message> >(index);
+    } else {
+      return GetRaw<RepeatedPtrFieldBase>(message, field)
+          .Get<GenericTypeHandler<Message> >(index);
+    }
+  }
+}
+
+Message* GeneratedMessageReflection::MutableRepeatedMessage(
+    Message* message, const FieldDescriptor* field, int index) const {
+  USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->MutableRepeatedMessage(
+          field->number(), index));
+  } else {
+    if (IsMapFieldInApi(field)) {
+      return MutableRaw<MapFieldBase>(message, field)
+          ->MutableRepeatedField()
+          ->Mutable<GenericTypeHandler<Message> >(index);
+    } else {
+      return MutableRaw<RepeatedPtrFieldBase>(message, field)
+        ->Mutable<GenericTypeHandler<Message> >(index);
+    }
+  }
+}
+
+Message* GeneratedMessageReflection::AddMessage(
+    Message* message, const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
+
+  if (factory == NULL) factory = message_factory_;
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->AddMessage(field, factory));
+  } else {
+    Message* result = NULL;
+
+    // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
+    // know how to allocate one.
+    RepeatedPtrFieldBase* repeated = NULL;
+    if (IsMapFieldInApi(field)) {
+      repeated =
+          MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+    } else {
+      repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+    }
+    result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
+    if (result == NULL) {
+      // We must allocate a new object.
+      const Message* prototype;
+      if (repeated->size() == 0) {
+        prototype = factory->GetPrototype(field->message_type());
+      } else {
+        prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
+      }
+      result = prototype->New(message->GetArena());
+      // We can guarantee here that repeated and result are either both heap
+      // allocated or arena owned. So it is safe to call the unsafe version
+      // of AddAllocated.
+      repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
+    }
+
+    return result;
+  }
+}
+
+void GeneratedMessageReflection::AddAllocatedMessage(
+    Message* message, const FieldDescriptor* field,
+    Message* new_entry) const {
+  USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
+
+  if (field->is_extension()) {
+    MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
+  } else {
+    RepeatedPtrFieldBase* repeated = NULL;
+    if (IsMapFieldInApi(field)) {
+      repeated =
+          MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+    } else {
+      repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+    }
+    repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry);
+  }
+}
+
+void* GeneratedMessageReflection::MutableRawRepeatedField(
+    Message* message, const FieldDescriptor* field,
+    FieldDescriptor::CppType cpptype,
+    int ctype, const Descriptor* desc) const {
+  USAGE_CHECK_REPEATED("MutableRawRepeatedField");
+  if (field->cpp_type() != cpptype)
+    ReportReflectionUsageTypeError(descriptor_,
+        field, "MutableRawRepeatedField", cpptype);
+  if (ctype >= 0)
+    GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+  if (desc != NULL)
+    GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+  if (field->is_extension()) {
+    return MutableExtensionSet(message)->MutableRawRepeatedField(
+        field->number(), field->type(), field->is_packed(), field);
+  } else {
+    // Trigger transform for MapField
+    if (IsMapFieldInApi(field)) {
+      return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
+                                             offsets_[field->index()])
+          ->MutableRepeatedField();
+    }
+    return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+  }
+}
+
+const void* GeneratedMessageReflection::GetRawRepeatedField(
+    const Message& message, const FieldDescriptor* field,
+    FieldDescriptor::CppType cpptype,
+    int ctype, const Descriptor* desc) const {
+  USAGE_CHECK_REPEATED("GetRawRepeatedField");
+  if (field->cpp_type() != cpptype)
+    ReportReflectionUsageTypeError(descriptor_,
+        field, "GetRawRepeatedField", cpptype);
+  if (ctype >= 0)
+    GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+  if (desc != NULL)
+    GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+  if (field->is_extension()) {
+    // Should use extension_set::GetRawRepeatedField. However, the required
+    // parameter "default repeated value" is not very easy to get here.
+    // Map is not supported in extensions, it is acceptable to use
+    // extension_set::MutableRawRepeatedField which does not change the message.
+    return MutableExtensionSet(const_cast<Message*>(&message))
+        ->MutableRawRepeatedField(
+        field->number(), field->type(), field->is_packed(), field);
+  } else {
+    // Trigger transform for MapField
+    if (IsMapFieldInApi(field)) {
+      return &(reinterpret_cast<const MapFieldBase*>(
+          reinterpret_cast<const uint8*>(&message) +
+          offsets_[field->index()])->GetRepeatedField());
+    }
+    return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()];
+  }
+}
+
+const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
+    const Message& message,
+    const OneofDescriptor* oneof_descriptor) const {
+  uint32 field_number = GetOneofCase(message, oneof_descriptor);
+  if (field_number == 0) {
+    return NULL;
+  }
+  return descriptor_->FindFieldByNumber(field_number);
+}
+
+bool GeneratedMessageReflection::ContainsMapKey(
+    const Message& message,
+    const FieldDescriptor* field,
+    const MapKey& key) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "LookupMapValue",
+              "Field is not a map field.");
+  return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
+}
+
+bool GeneratedMessageReflection::InsertOrLookupMapValue(
+    Message* message,
+    const FieldDescriptor* field,
+    const MapKey& key,
+    MapValueRef* val) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "InsertOrLookupMapValue",
+              "Field is not a map field.");
+  val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+  return MutableRaw<MapFieldBase>(message, field)->InsertOrLookupMapValue(
+      key, val);
+}
+
+bool GeneratedMessageReflection::DeleteMapValue(
+    Message* message,
+    const FieldDescriptor* field,
+    const MapKey& key) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "DeleteMapValue",
+              "Field is not a map field.");
+  return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
+}
+
+MapIterator GeneratedMessageReflection::MapBegin(
+    Message* message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "MapBegin",
+              "Field is not a map field.");
+  MapIterator iter(message, field);
+  GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
+  return iter;
+}
+
+MapIterator GeneratedMessageReflection::MapEnd(
+    Message* message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "MapEnd",
+              "Field is not a map field.");
+  MapIterator iter(message, field);
+  GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
+  return iter;
+}
+
+int GeneratedMessageReflection::MapSize(
+    const Message& message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "MapSize",
+              "Field is not a map field.");
+  return GetRaw<MapFieldBase>(message, field).size();
+}
+
+// -----------------------------------------------------------------------------
+
+const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
+    const string& name) const {
+  if (extensions_offset_ == -1) return NULL;
+
+  const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
+  if (result != NULL && result->containing_type() == descriptor_) {
+    return result;
+  }
+
+  if (descriptor_->options().message_set_wire_format()) {
+    // MessageSet extensions may be identified by type name.
+    const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
+    if (type != NULL) {
+      // Look for a matching extension in the foreign type's scope.
+      for (int i = 0; i < type->extension_count(); i++) {
+        const FieldDescriptor* extension = type->extension(i);
+        if (extension->containing_type() == descriptor_ &&
+            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
+            extension->is_optional() &&
+            extension->message_type() == type) {
+          // Found it.
+          return extension;
+        }
+      }
+    }
+  }
+
+  return NULL;
+}
+
+const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
+    int number) const {
+  if (extensions_offset_ == -1) return NULL;
+  return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
+}
+
+bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
+  return CreateUnknownEnumValues(descriptor_->file());
+}
+
+// ===================================================================
+// Some private helpers.
+
+// These simple template accessors obtain pointers (or references) to
+// the given field.
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRaw(
+    const Message& message, const FieldDescriptor* field) const {
+  if (field->containing_oneof() && !HasOneofField(message, field)) {
+    return DefaultRaw<Type>(field);
+  }
+  int index = field->containing_oneof() ?
+      descriptor_->field_count() + field->containing_oneof()->index() :
+      field->index();
+  const void* ptr = reinterpret_cast<const uint8*>(&message) +
+      offsets_[index];
+  return *reinterpret_cast<const Type*>(ptr);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableRaw(
+    Message* message, const FieldDescriptor* field) const {
+  int index = field->containing_oneof() ?
+      descriptor_->field_count() + field->containing_oneof()->index() :
+      field->index();
+  void* ptr = reinterpret_cast<uint8*>(message) + offsets_[index];
+  return reinterpret_cast<Type*>(ptr);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::DefaultRaw(
+    const FieldDescriptor* field) const {
+  const void* ptr = field->containing_oneof() ?
+      reinterpret_cast<const uint8*>(default_oneof_instance_) +
+      offsets_[field->index()] :
+      reinterpret_cast<const uint8*>(default_instance_) +
+      offsets_[field->index()];
+  return *reinterpret_cast<const Type*>(ptr);
+}
+
+inline const uint32* GeneratedMessageReflection::GetHasBits(
+    const Message& message) const {
+  if (has_bits_offset_ == -1) {  // proto3 with no has-bits.
+    return NULL;
+  }
+  const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
+  return reinterpret_cast<const uint32*>(ptr);
+}
+inline uint32* GeneratedMessageReflection::MutableHasBits(
+    Message* message) const {
+  if (has_bits_offset_ == -1) {
+    return NULL;
+  }
+  void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
+  return reinterpret_cast<uint32*>(ptr);
+}
+
+inline uint32 GeneratedMessageReflection::GetOneofCase(
+    const Message& message,
+    const OneofDescriptor* oneof_descriptor) const {
+  const void* ptr = reinterpret_cast<const uint8*>(&message)
+      + oneof_case_offset_;
+  return reinterpret_cast<const uint32*>(ptr)[oneof_descriptor->index()];
+}
+
+inline uint32* GeneratedMessageReflection::MutableOneofCase(
+    Message* message,
+    const OneofDescriptor* oneof_descriptor) const {
+  void* ptr = reinterpret_cast<uint8*>(message) + oneof_case_offset_;
+  return &(reinterpret_cast<uint32*>(ptr)[oneof_descriptor->index()]);
+}
+
+inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
+    const Message& message) const {
+  GOOGLE_DCHECK_NE(extensions_offset_, -1);
+  const void* ptr = reinterpret_cast<const uint8*>(&message) +
+                    extensions_offset_;
+  return *reinterpret_cast<const ExtensionSet*>(ptr);
+}
+inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
+    Message* message) const {
+  GOOGLE_DCHECK_NE(extensions_offset_, -1);
+  void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_;
+  return reinterpret_cast<ExtensionSet*>(ptr);
+}
+
+inline Arena* GeneratedMessageReflection::GetArena(Message* message) const {
+  if (arena_offset_ == kNoArenaPointer) {
+    return NULL;
+  }
+
+  if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+    // zero-overhead arena pointer overloading UnknownFields
+    return GetInternalMetadataWithArena(*message).arena();
+  }
+
+  // Baseline case: message class has a dedicated arena pointer.
+  void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+  return *reinterpret_cast<Arena**>(ptr);
+}
+
+inline const InternalMetadataWithArena&
+GeneratedMessageReflection::GetInternalMetadataWithArena(
+    const Message& message) const {
+  const void* ptr = reinterpret_cast<const uint8*>(&message) + arena_offset_;
+  return *reinterpret_cast<const InternalMetadataWithArena*>(ptr);
+}
+
+inline InternalMetadataWithArena*
+GeneratedMessageReflection::MutableInternalMetadataWithArena(
+    Message* message) const {
+  void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+  return reinterpret_cast<InternalMetadataWithArena*>(ptr);
+}
+
+inline bool
+GeneratedMessageReflection::GetIsDefaultInstance(
+    const Message& message) const {
+  if (is_default_instance_offset_ == kHasNoDefaultInstanceField) {
+    return false;
+  }
+  const void* ptr = reinterpret_cast<const uint8*>(&message) +
+      is_default_instance_offset_;
+  return *reinterpret_cast<const bool*>(ptr);
+}
+
+// Simple accessors for manipulating has_bits_.
+inline bool GeneratedMessageReflection::HasBit(
+    const Message& message, const FieldDescriptor* field) const {
+  if (has_bits_offset_ == -1) {
+    // proto3: no has-bits. All fields present except messages, which are
+    // present only if their message-field pointer is non-NULL.
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      return !GetIsDefaultInstance(message) &&
+          GetRaw<const Message*>(message, field) != NULL;
+    } else {
+      // Non-message field (and non-oneof, since that was handled in HasField()
+      // before calling us), and singular (again, checked in HasField). So, this
+      // field must be a scalar.
+
+      // Scalar primitive (numeric or string/bytes) fields are present if
+      // their value is non-zero (numeric) or non-empty (string/bytes).  N.B.:
+      // we must use this definition here, rather than the "scalar fields
+      // always present" in the proto3 docs, because MergeFrom() semantics
+      // require presence as "present on wire", and reflection-based merge
+      // (which uses HasField()) needs to be consistent with this.
+      switch (field->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_STRING:
+          switch (field->options().ctype()) {
+            default: {
+              const string* default_ptr =
+                  &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+              return GetField<ArenaStringPtr>(message, field).Get(
+                  default_ptr).size() > 0;
+            }
+          }
+          return false;
+        case FieldDescriptor::CPPTYPE_BOOL:
+          return GetRaw<bool>(message, field) != false;
+        case FieldDescriptor::CPPTYPE_INT32:
+          return GetRaw<int32>(message, field) != 0;
+        case FieldDescriptor::CPPTYPE_INT64:
+          return GetRaw<int64>(message, field) != 0;
+        case FieldDescriptor::CPPTYPE_UINT32:
+          return GetRaw<uint32>(message, field) != 0;
+        case FieldDescriptor::CPPTYPE_UINT64:
+          return GetRaw<uint64>(message, field) != 0;
+        case FieldDescriptor::CPPTYPE_FLOAT:
+          return GetRaw<float>(message, field) != 0.0;
+        case FieldDescriptor::CPPTYPE_DOUBLE:
+          return GetRaw<double>(message, field) != 0.0;
+        case FieldDescriptor::CPPTYPE_ENUM:
+          return GetRaw<int>(message, field) != 0;
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          // handled above; avoid warning
+          GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
+          break;
+      }
+    }
+  }
+  return GetHasBits(message)[field->index() / 32] &
+    (1 << (field->index() % 32));
+}
+
+inline void GeneratedMessageReflection::SetBit(
+    Message* message, const FieldDescriptor* field) const {
+  if (has_bits_offset_ == -1) {
+    return;
+  }
+  MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
+}
+
+inline void GeneratedMessageReflection::ClearBit(
+    Message* message, const FieldDescriptor* field) const {
+  if (has_bits_offset_ == -1) {
+    return;
+  }
+  MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
+}
+
+inline void GeneratedMessageReflection::SwapBit(
+    Message* message1, Message* message2, const FieldDescriptor* field) const {
+  if (has_bits_offset_ == -1) {
+    return;
+  }
+  bool temp_has_bit = HasBit(*message1, field);
+  if (HasBit(*message2, field)) {
+    SetBit(message1, field);
+  } else {
+    ClearBit(message1, field);
+  }
+  if (temp_has_bit) {
+    SetBit(message2, field);
+  } else {
+    ClearBit(message2, field);
+  }
+}
+
+inline bool GeneratedMessageReflection::HasOneof(
+    const Message& message, const OneofDescriptor* oneof_descriptor) const {
+  return (GetOneofCase(message, oneof_descriptor) > 0);
+}
+
+inline bool GeneratedMessageReflection::HasOneofField(
+    const Message& message, const FieldDescriptor* field) const {
+  return (GetOneofCase(message, field->containing_oneof()) == field->number());
+}
+
+inline void GeneratedMessageReflection::SetOneofCase(
+    Message* message, const FieldDescriptor* field) const {
+  *MutableOneofCase(message, field->containing_oneof()) = field->number();
+}
+
+inline void GeneratedMessageReflection::ClearOneofField(
+    Message* message, const FieldDescriptor* field) const {
+  if (HasOneofField(*message, field)) {
+    ClearOneof(message, field->containing_oneof());
+  }
+}
+
+inline void GeneratedMessageReflection::ClearOneof(
+    Message* message, const OneofDescriptor* oneof_descriptor) const {
+  // TODO(jieluo): Consider to cache the unused object instead of deleting
+  // it. It will be much faster if an aplication switches a lot from
+  // a few oneof fields.  Time/space tradeoff
+  uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
+  if (oneof_case > 0) {
+    const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
+    if (GetArena(message) == NULL) {
+      switch (field->cpp_type()) {
+        case FieldDescriptor::CPPTYPE_STRING: {
+          switch (field->options().ctype()) {
+            default:  // TODO(kenton):  Support other string reps.
+            case FieldOptions::STRING: {
+              const string* default_ptr =
+                  &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+              MutableField<ArenaStringPtr>(message, field)->
+                  Destroy(default_ptr, GetArena(message));
+              break;
+            }
+          }
+          break;
+        }
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          delete *MutableRaw<Message*>(message, field);
+          break;
+        default:
+          break;
+      }
+    }
+
+    *MutableOneofCase(message, oneof_descriptor) = 0;
+  }
+}
+
+// Template implementations of basic accessors.  Inline because each
+// template instance is only called from one location.  These are
+// used for all types except messages.
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetField(
+    const Message& message, const FieldDescriptor* field) const {
+  return GetRaw<Type>(message, field);
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::SetField(
+    Message* message, const FieldDescriptor* field, const Type& value) const {
+  if (field->containing_oneof() && !HasOneofField(*message, field)) {
+    ClearOneof(message, field->containing_oneof());
+  }
+  *MutableRaw<Type>(message, field) = value;
+  field->containing_oneof() ?
+      SetOneofCase(message, field) : SetBit(message, field);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableField(
+    Message* message, const FieldDescriptor* field) const {
+  field->containing_oneof() ?
+      SetOneofCase(message, field) : SetBit(message, field);
+  return MutableRaw<Type>(message, field);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRepeatedField(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  return GetRaw<RepeatedField<Type> >(message, field).Get(index);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field, int index) const {
+  return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::SetRepeatedField(
+    Message* message, const FieldDescriptor* field,
+    int index, Type value) const {
+  MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableRepeatedField(
+    Message* message, const FieldDescriptor* field, int index) const {
+  RepeatedPtrField<Type>* repeated =
+    MutableRaw<RepeatedPtrField<Type> >(message, field);
+  return repeated->Mutable(index);
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::AddField(
+    Message* message, const FieldDescriptor* field, const Type& value) const {
+  MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::AddField(
+    Message* message, const FieldDescriptor* field) const {
+  RepeatedPtrField<Type>* repeated =
+    MutableRaw<RepeatedPtrField<Type> >(message, field);
+  return repeated->Add();
+}
+
+MessageFactory* GeneratedMessageReflection::GetMessageFactory() const {
+  return message_factory_;
+}
+
+void* GeneratedMessageReflection::RepeatedFieldData(
+    Message* message, const FieldDescriptor* field,
+    FieldDescriptor::CppType cpp_type,
+    const Descriptor* message_type) const {
+  GOOGLE_CHECK(field->is_repeated());
+  GOOGLE_CHECK(field->cpp_type() == cpp_type ||
+        (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+         cpp_type == FieldDescriptor::CPPTYPE_INT32))
+      << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
+      << "the actual field type (for enums T should be the generated enum "
+      << "type or int32).";
+  if (message_type != NULL) {
+    GOOGLE_CHECK_EQ(message_type, field->message_type());
+  }
+  if (field->is_extension()) {
+    return MutableExtensionSet(message)->MutableRawRepeatedField(
+        field->number(), field->type(), field->is_packed(), field);
+  } else {
+    return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+  }
+}
+
+MapFieldBase* GeneratedMessageReflection::MapData(
+    Message* message, const FieldDescriptor* field) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "GetMapData",
+              "Field is not a map field.");
+  return MutableRaw<MapFieldBase>(message, field);
+}
+
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    const void* default_oneof_instance,
+    int oneof_case_offset,
+    int object_size,
+    int arena_offset,
+    int is_default_instance_offset) {
+  return new GeneratedMessageReflection(descriptor,
+                                        default_instance,
+                                        offsets,
+                                        has_bits_offset,
+                                        unknown_fields_offset,
+                                        extensions_offset,
+                                        default_oneof_instance,
+                                        oneof_case_offset,
+                                        DescriptorPool::generated_pool(),
+                                        MessageFactory::generated_factory(),
+                                        object_size,
+                                        arena_offset,
+                                        is_default_instance_offset);
+}
+
+GeneratedMessageReflection*
+GeneratedMessageReflection::NewGeneratedMessageReflection(
+    const Descriptor* descriptor,
+    const Message* default_instance,
+    const int offsets[],
+    int has_bits_offset,
+    int unknown_fields_offset,
+    int extensions_offset,
+    int object_size,
+    int arena_offset,
+    int is_default_instance_offset) {
+  return new GeneratedMessageReflection(descriptor,
+                                        default_instance,
+                                        offsets,
+                                        has_bits_offset,
+                                        unknown_fields_offset,
+                                        extensions_offset,
+                                        DescriptorPool::generated_pool(),
+                                        MessageFactory::generated_factory(),
+                                        object_size,
+                                        arena_offset,
+                                        is_default_instance_offset);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.h b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.h
new file mode 100644
index 0000000..15fc802
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection.h
@@ -0,0 +1,683 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+// TODO(jasonh): Remove this once the compiler change to directly include this
+// is released to components.
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/unknown_field_set.h>
+
+
+namespace google {
+namespace upb {
+namespace google_opensource {
+class GMR_Handlers;
+}  // namespace google_opensource
+}  // namespace upb
+
+namespace protobuf {
+class DescriptorPool;
+class MapKey;
+class MapValueRef;
+}
+
+namespace protobuf {
+namespace internal {
+class DefaultEmptyOneof;
+
+// Defined in this file.
+class GeneratedMessageReflection;
+
+// Defined in other files.
+class ExtensionSet;             // extension_set.h
+
+// THIS CLASS IS NOT INTENDED FOR DIRECT USE.  It is intended for use
+// by generated code.  This class is just a big hack that reduces code
+// size.
+//
+// A GeneratedMessageReflection is an implementation of Reflection
+// which expects all fields to be backed by simple variables located in
+// memory.  The locations are given using a base pointer and a set of
+// offsets.
+//
+// It is required that the user represents fields of each type in a standard
+// way, so that GeneratedMessageReflection can cast the void* pointer to
+// the appropriate type.  For primitive fields and string fields, each field
+// should be represented using the obvious C++ primitive type.  Enums and
+// Messages are different:
+//  - Singular Message fields are stored as a pointer to a Message.  These
+//    should start out NULL, except for in the default instance where they
+//    should start out pointing to other default instances.
+//  - Enum fields are stored as an int.  This int must always contain
+//    a valid value, such that EnumDescriptor::FindValueByNumber() would
+//    not return NULL.
+//  - Repeated fields are stored as RepeatedFields or RepeatedPtrFields
+//    of whatever type the individual field would be.  Strings and
+//    Messages use RepeatedPtrFields while everything else uses
+//    RepeatedFields.
+class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
+ public:
+  // Constructs a GeneratedMessageReflection.
+  // Parameters:
+  //   descriptor:    The descriptor for the message type being implemented.
+  //   default_instance:  The default instance of the message.  This is only
+  //                  used to obtain pointers to default instances of embedded
+  //                  messages, which GetMessage() will return if the particular
+  //                  sub-message has not been initialized yet.  (Thus, all
+  //                  embedded message fields *must* have non-NULL pointers
+  //                  in the default instance.)
+  //   offsets:       An array of ints giving the byte offsets, relative to
+  //                  the start of the message object, of each field.  These can
+  //                  be computed at compile time using the
+  //                  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro, defined
+  //                  below.
+  //   has_bits_offset:  Offset in the message of an array of uint32s of size
+  //                  descriptor->field_count()/32, rounded up.  This is a
+  //                  bitfield where each bit indicates whether or not the
+  //                  corresponding field of the message has been initialized.
+  //                  The bit for field index i is obtained by the expression:
+  //                    has_bits[i / 32] & (1 << (i % 32))
+  //   unknown_fields_offset:  Offset in the message of the UnknownFieldSet for
+  //                  the message.
+  //   extensions_offset:  Offset in the message of the ExtensionSet for the
+  //                  message, or -1 if the message type has no extension
+  //                  ranges.
+  //   pool:          DescriptorPool to search for extension definitions.  Only
+  //                  used by FindKnownExtensionByName() and
+  //                  FindKnownExtensionByNumber().
+  //   factory:       MessageFactory to use to construct extension messages.
+  //   object_size:   The size of a message object of this type, as measured
+  //                  by sizeof().
+  GeneratedMessageReflection(const Descriptor* descriptor,
+                             const Message* default_instance,
+                             const int offsets[],
+                             int has_bits_offset,
+                             int unknown_fields_offset,
+                             int extensions_offset,
+                             const DescriptorPool* pool,
+                             MessageFactory* factory,
+                             int object_size,
+                             int arena_offset,
+                             int is_default_instance_offset = -1);
+
+  // Similar with the construction above. Call this construction if the
+  // message has oneof definition.
+  // Parameters:
+  //   offsets:       An array of ints giving the byte offsets.
+  //                  For each oneof field, the offset is relative to the
+  //                  default_oneof_instance. These can be computed at compile
+  //                  time using the
+  //                  PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() macro.
+  //                  For each none oneof field, the offset is related to
+  //                  the start of the message object.  These can be computed
+  //                  at compile time using the
+  //                  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro.
+  //                  Besides offsets for all fields, this array also contains
+  //                  offsets for oneof unions. The offset of the i-th oneof
+  //                  union is offsets[descriptor->field_count() + i].
+  //   default_oneof_instance: The default instance of the oneofs. It is a
+  //                  struct holding the default value of all oneof fields
+  //                  for this message. It is only used to obtain pointers
+  //                  to default instances of oneof fields, which Get
+  //                  methods will return if the field is not set.
+  //   oneof_case_offset:  Offset in the message of an array of uint32s of
+  //                  size descriptor->oneof_decl_count().  Each uint32
+  //                  indicates what field is set for each oneof.
+  //   other parameters are the same with the construction above.
+  GeneratedMessageReflection(const Descriptor* descriptor,
+                             const Message* default_instance,
+                             const int offsets[],
+                             int has_bits_offset,
+                             int unknown_fields_offset,
+                             int extensions_offset,
+                             const void* default_oneof_instance,
+                             int oneof_case_offset,
+                             const DescriptorPool* pool,
+                             MessageFactory* factory,
+                             int object_size,
+                             int arena_offset,
+                             int is_default_instance_offset = -1);
+  ~GeneratedMessageReflection();
+
+  // Shorter-to-call helpers for the above two constructions that work if the
+  // pool and factory are the usual, namely, DescriptorPool::generated_pool()
+  // and MessageFactory::generated_factory().
+
+  static GeneratedMessageReflection* NewGeneratedMessageReflection(
+      const Descriptor* descriptor,
+      const Message* default_instance,
+      const int offsets[],
+      int has_bits_offset,
+      int unknown_fields_offset,
+      int extensions_offset,
+      const void* default_oneof_instance,
+      int oneof_case_offset,
+      int object_size,
+      int arena_offset,
+      int is_default_instance_offset = -1);
+
+  static GeneratedMessageReflection* NewGeneratedMessageReflection(
+      const Descriptor* descriptor,
+      const Message* default_instance,
+      const int offsets[],
+      int has_bits_offset,
+      int unknown_fields_offset,
+      int extensions_offset,
+      int object_size,
+      int arena_offset,
+      int is_default_instance_offset = -1);
+
+  // implements Reflection -------------------------------------------
+
+  const UnknownFieldSet& GetUnknownFields(const Message& message) const;
+  UnknownFieldSet* MutableUnknownFields(Message* message) const;
+
+  int SpaceUsed(const Message& message) const;
+
+  bool HasField(const Message& message, const FieldDescriptor* field) const;
+  int FieldSize(const Message& message, const FieldDescriptor* field) const;
+  void ClearField(Message* message, const FieldDescriptor* field) const;
+  bool HasOneof(const Message& message,
+                const OneofDescriptor* oneof_descriptor) const;
+  void ClearOneof(Message* message, const OneofDescriptor* field) const;
+  void RemoveLast(Message* message, const FieldDescriptor* field) const;
+  Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
+  void Swap(Message* message1, Message* message2) const;
+  void SwapFields(Message* message1, Message* message2,
+                  const vector<const FieldDescriptor*>& fields) const;
+  void SwapElements(Message* message, const FieldDescriptor* field,
+                    int index1, int index2) const;
+  void ListFields(const Message& message,
+                  vector<const FieldDescriptor*>* output) const;
+
+  int32  GetInt32 (const Message& message,
+                   const FieldDescriptor* field) const;
+  int64  GetInt64 (const Message& message,
+                   const FieldDescriptor* field) const;
+  uint32 GetUInt32(const Message& message,
+                   const FieldDescriptor* field) const;
+  uint64 GetUInt64(const Message& message,
+                   const FieldDescriptor* field) const;
+  float  GetFloat (const Message& message,
+                   const FieldDescriptor* field) const;
+  double GetDouble(const Message& message,
+                   const FieldDescriptor* field) const;
+  bool   GetBool  (const Message& message,
+                   const FieldDescriptor* field) const;
+  string GetString(const Message& message,
+                   const FieldDescriptor* field) const;
+  const string& GetStringReference(const Message& message,
+                                   const FieldDescriptor* field,
+                                   string* scratch) const;
+  const EnumValueDescriptor* GetEnum(const Message& message,
+                                     const FieldDescriptor* field) const;
+  int GetEnumValue(const Message& message,
+                   const FieldDescriptor* field) const;
+  const Message& GetMessage(const Message& message,
+                            const FieldDescriptor* field,
+                            MessageFactory* factory = NULL) const;
+
+  const FieldDescriptor* GetOneofFieldDescriptor(
+      const Message& message,
+      const OneofDescriptor* oneof_descriptor) const;
+
+ private:
+  bool ContainsMapKey(const Message& message,
+                      const FieldDescriptor* field,
+                      const MapKey& key) const;
+  bool InsertOrLookupMapValue(Message* message,
+                              const FieldDescriptor* field,
+                              const MapKey& key,
+                              MapValueRef* val) const;
+  bool DeleteMapValue(Message* message,
+                      const FieldDescriptor* field,
+                      const MapKey& key) const;
+  MapIterator MapBegin(
+      Message* message,
+      const FieldDescriptor* field) const;
+  MapIterator MapEnd(
+      Message* message,
+      const FieldDescriptor* field) const;
+  int MapSize(const Message& message, const FieldDescriptor* field) const;
+
+ public:
+  void SetInt32 (Message* message,
+                 const FieldDescriptor* field, int32  value) const;
+  void SetInt64 (Message* message,
+                 const FieldDescriptor* field, int64  value) const;
+  void SetUInt32(Message* message,
+                 const FieldDescriptor* field, uint32 value) const;
+  void SetUInt64(Message* message,
+                 const FieldDescriptor* field, uint64 value) const;
+  void SetFloat (Message* message,
+                 const FieldDescriptor* field, float  value) const;
+  void SetDouble(Message* message,
+                 const FieldDescriptor* field, double value) const;
+  void SetBool  (Message* message,
+                 const FieldDescriptor* field, bool   value) const;
+  void SetString(Message* message,
+                 const FieldDescriptor* field,
+                 const string& value) const;
+  void SetEnum  (Message* message, const FieldDescriptor* field,
+                 const EnumValueDescriptor* value) const;
+  void SetEnumValue(Message* message, const FieldDescriptor* field,
+                    int value) const;
+  Message* MutableMessage(Message* message, const FieldDescriptor* field,
+                          MessageFactory* factory = NULL) const;
+  void SetAllocatedMessage(Message* message,
+                           Message* sub_message,
+                           const FieldDescriptor* field) const;
+  Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
+                          MessageFactory* factory = NULL) const;
+
+  int32  GetRepeatedInt32 (const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  int64  GetRepeatedInt64 (const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  uint32 GetRepeatedUInt32(const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  uint64 GetRepeatedUInt64(const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  float  GetRepeatedFloat (const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  double GetRepeatedDouble(const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  bool   GetRepeatedBool  (const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  string GetRepeatedString(const Message& message,
+                           const FieldDescriptor* field, int index) const;
+  const string& GetRepeatedStringReference(const Message& message,
+                                           const FieldDescriptor* field,
+                                           int index, string* scratch) const;
+  const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
+                                             const FieldDescriptor* field,
+                                             int index) const;
+  int GetRepeatedEnumValue(const Message& message,
+                           const FieldDescriptor* field,
+                           int index) const;
+  const Message& GetRepeatedMessage(const Message& message,
+                                    const FieldDescriptor* field,
+                                    int index) const;
+
+  // Set the value of a field.
+  void SetRepeatedInt32 (Message* message,
+                         const FieldDescriptor* field, int index, int32  value) const;
+  void SetRepeatedInt64 (Message* message,
+                         const FieldDescriptor* field, int index, int64  value) const;
+  void SetRepeatedUInt32(Message* message,
+                         const FieldDescriptor* field, int index, uint32 value) const;
+  void SetRepeatedUInt64(Message* message,
+                         const FieldDescriptor* field, int index, uint64 value) const;
+  void SetRepeatedFloat (Message* message,
+                         const FieldDescriptor* field, int index, float  value) const;
+  void SetRepeatedDouble(Message* message,
+                         const FieldDescriptor* field, int index, double value) const;
+  void SetRepeatedBool  (Message* message,
+                         const FieldDescriptor* field, int index, bool   value) const;
+  void SetRepeatedString(Message* message,
+                         const FieldDescriptor* field, int index,
+                         const string& value) const;
+  void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
+                       int index, const EnumValueDescriptor* value) const;
+  void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field,
+                            int index, int value) const;
+  // Get a mutable pointer to a field with a message type.
+  Message* MutableRepeatedMessage(Message* message,
+                                  const FieldDescriptor* field,
+                                  int index) const;
+
+  void AddInt32 (Message* message,
+                 const FieldDescriptor* field, int32  value) const;
+  void AddInt64 (Message* message,
+                 const FieldDescriptor* field, int64  value) const;
+  void AddUInt32(Message* message,
+                 const FieldDescriptor* field, uint32 value) const;
+  void AddUInt64(Message* message,
+                 const FieldDescriptor* field, uint64 value) const;
+  void AddFloat (Message* message,
+                 const FieldDescriptor* field, float  value) const;
+  void AddDouble(Message* message,
+                 const FieldDescriptor* field, double value) const;
+  void AddBool  (Message* message,
+                 const FieldDescriptor* field, bool   value) const;
+  void AddString(Message* message,
+                 const FieldDescriptor* field, const string& value) const;
+  void AddEnum(Message* message,
+               const FieldDescriptor* field,
+               const EnumValueDescriptor* value) const;
+  void AddEnumValue(Message* message,
+                    const FieldDescriptor* field,
+                    int value) const;
+  Message* AddMessage(Message* message, const FieldDescriptor* field,
+                      MessageFactory* factory = NULL) const;
+  void AddAllocatedMessage(
+      Message* message, const FieldDescriptor* field,
+      Message* new_entry) const;
+
+  const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
+  const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
+
+  bool SupportsUnknownEnumValues() const;
+
+  // This value for arena_offset_ indicates that there is no arena pointer in
+  // this message (e.g., old generated code).
+  static const int kNoArenaPointer = -1;
+
+  // This value for unknown_field_offset_ indicates that there is no
+  // UnknownFieldSet in this message, and that instead, we are using the
+  // Zero-Overhead Arena Pointer trick. When this is the case, arena_offset_
+  // actually indexes to an InternalMetadataWithArena instance, which can return
+  // either an arena pointer or an UnknownFieldSet or both. It is never the case
+  // that unknown_field_offset_ == kUnknownFieldSetInMetadata && arena_offset_
+  // == kNoArenaPointer.
+  static const int kUnknownFieldSetInMetadata = -1;
+
+ protected:
+  void* MutableRawRepeatedField(
+      Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+      int ctype, const Descriptor* desc) const;
+
+  const void* GetRawRepeatedField(
+      const Message& message, const FieldDescriptor* field,
+      FieldDescriptor::CppType, int ctype,
+      const Descriptor* desc) const;
+
+  virtual MessageFactory* GetMessageFactory() const;
+
+  virtual void* RepeatedFieldData(
+      Message* message, const FieldDescriptor* field,
+      FieldDescriptor::CppType cpp_type,
+      const Descriptor* message_type) const;
+
+ private:
+  friend class GeneratedMessage;
+
+  // To parse directly into a proto2 generated class, the class GMR_Handlers
+  // needs access to member offsets and hasbits.
+  friend class upb::google_opensource::GMR_Handlers;
+
+  const Descriptor* descriptor_;
+  const Message* default_instance_;
+  const void* default_oneof_instance_;
+  const int* offsets_;
+
+  int has_bits_offset_;
+  int oneof_case_offset_;
+  int unknown_fields_offset_;
+  int extensions_offset_;
+  int arena_offset_;
+  int is_default_instance_offset_;
+  int object_size_;
+
+  static const int kHasNoDefaultInstanceField = -1;
+
+  const DescriptorPool* descriptor_pool_;
+  MessageFactory* message_factory_;
+
+  template <typename Type>
+  inline const Type& GetRaw(const Message& message,
+                            const FieldDescriptor* field) const;
+  template <typename Type>
+  inline Type* MutableRaw(Message* message,
+                          const FieldDescriptor* field) const;
+  template <typename Type>
+  inline const Type& DefaultRaw(const FieldDescriptor* field) const;
+  template <typename Type>
+  inline const Type& DefaultOneofRaw(const FieldDescriptor* field) const;
+
+  inline const uint32* GetHasBits(const Message& message) const;
+  inline uint32* MutableHasBits(Message* message) const;
+  inline uint32 GetOneofCase(
+      const Message& message,
+      const OneofDescriptor* oneof_descriptor) const;
+  inline uint32* MutableOneofCase(
+      Message* message,
+      const OneofDescriptor* oneof_descriptor) const;
+  inline const ExtensionSet& GetExtensionSet(const Message& message) const;
+  inline ExtensionSet* MutableExtensionSet(Message* message) const;
+  inline Arena* GetArena(Message* message) const;
+  inline const internal::InternalMetadataWithArena&
+      GetInternalMetadataWithArena(const Message& message) const;
+  inline internal::InternalMetadataWithArena*
+      MutableInternalMetadataWithArena(Message* message) const;
+
+  inline bool GetIsDefaultInstance(const Message& message) const;
+
+  inline bool HasBit(const Message& message,
+                     const FieldDescriptor* field) const;
+  inline void SetBit(Message* message,
+                     const FieldDescriptor* field) const;
+  inline void ClearBit(Message* message,
+                       const FieldDescriptor* field) const;
+  inline void SwapBit(Message* message1,
+                      Message* message2,
+                      const FieldDescriptor* field) const;
+
+  // This function only swaps the field. Should swap corresponding has_bit
+  // before or after using this function.
+  void SwapField(Message* message1,
+                 Message* message2,
+                 const FieldDescriptor* field) const;
+
+  void SwapOneofField(Message* message1,
+                      Message* message2,
+                      const OneofDescriptor* oneof_descriptor) const;
+
+  inline bool HasOneofField(const Message& message,
+                            const FieldDescriptor* field) const;
+  inline void SetOneofCase(Message* message,
+                           const FieldDescriptor* field) const;
+  inline void ClearOneofField(Message* message,
+                              const FieldDescriptor* field) const;
+
+  template <typename Type>
+  inline const Type& GetField(const Message& message,
+                              const FieldDescriptor* field) const;
+  template <typename Type>
+  inline void SetField(Message* message,
+                       const FieldDescriptor* field, const Type& value) const;
+  template <typename Type>
+  inline Type* MutableField(Message* message,
+                            const FieldDescriptor* field) const;
+  template <typename Type>
+  inline const Type& GetRepeatedField(const Message& message,
+                                      const FieldDescriptor* field,
+                                      int index) const;
+  template <typename Type>
+  inline const Type& GetRepeatedPtrField(const Message& message,
+                                         const FieldDescriptor* field,
+                                         int index) const;
+  template <typename Type>
+  inline void SetRepeatedField(Message* message,
+                               const FieldDescriptor* field, int index,
+                               Type value) const;
+  template <typename Type>
+  inline Type* MutableRepeatedField(Message* message,
+                                    const FieldDescriptor* field,
+                                    int index) const;
+  template <typename Type>
+  inline void AddField(Message* message,
+                       const FieldDescriptor* field, const Type& value) const;
+  template <typename Type>
+  inline Type* AddField(Message* message,
+                        const FieldDescriptor* field) const;
+
+  int GetExtensionNumberOrDie(const Descriptor* type) const;
+
+  // Internal versions of EnumValue API perform no checking. Called after checks
+  // by public methods.
+  void SetEnumValueInternal(Message* message,
+                            const FieldDescriptor* field,
+                            int value) const;
+  void SetRepeatedEnumValueInternal(Message* message,
+                                    const FieldDescriptor* field,
+                                    int index,
+                                    int value) const;
+  void AddEnumValueInternal(Message* message,
+                            const FieldDescriptor* field,
+                            int value) const;
+
+
+  Message* UnsafeArenaReleaseMessage(Message* message,
+                                     const FieldDescriptor* field,
+                                     MessageFactory* factory = NULL) const;
+
+  void UnsafeArenaSetAllocatedMessage(Message* message,
+                                      Message* sub_message,
+                                      const FieldDescriptor* field) const;
+
+  internal::MapFieldBase* MapData(
+      Message* message, const FieldDescriptor* field) const;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
+};
+
+// Returns the offset of the given field within the given aggregate type.
+// This is equivalent to the ANSI C offsetof() macro.  However, according
+// to the C++ standard, offsetof() only works on POD types, and GCC
+// enforces this requirement with a warning.  In practice, this rule is
+// unnecessarily strict; there is probably no compiler or platform on
+// which the offsets of the direct fields of a class are non-constant.
+// Fields inherited from superclasses *can* have non-constant offsets,
+// but that's not what this macro will be used for.
+#if defined(__clang__)
+// For Clang we use __builtin_offsetof() and suppress the warning,
+// to avoid Control Flow Integrity and UBSan vptr sanitizers from
+// crashing while trying to validate the invalid reinterpet_casts.
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD)    \
+  _Pragma("clang diagnostic push")                            \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"")  \
+  __builtin_offsetof(TYPE, FIELD)                             \
+  _Pragma("clang diagnostic pop")
+#else
+// Note that we calculate relative to the pointer value 16 here since if we
+// just use zero, GCC complains about dereferencing a NULL pointer.  We
+// choose 16 rather than some other number just in case the compiler would
+// be confused by an unaligned pointer.
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD)    \
+  static_cast<int>(                                           \
+      reinterpret_cast<const char*>(                          \
+          &reinterpret_cast<const TYPE*>(16)->FIELD) -        \
+      reinterpret_cast<const char*>(16))
+#endif
+
+#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD)     \
+  static_cast<int>(                                                   \
+      reinterpret_cast<const char*>(&(ONEOF->FIELD))                  \
+      - reinterpret_cast<const char*>(ONEOF))
+
+// There are some places in proto2 where dynamic_cast would be useful as an
+// optimization.  For example, take Message::MergeFrom(const Message& other).
+// For a given generated message FooMessage, we generate these two methods:
+//   void MergeFrom(const FooMessage& other);
+//   void MergeFrom(const Message& other);
+// The former method can be implemented directly in terms of FooMessage's
+// inline accessors, but the latter method must work with the reflection
+// interface.  However, if the parameter to the latter method is actually of
+// type FooMessage, then we'd like to be able to just call the other method
+// as an optimization.  So, we use dynamic_cast to check this.
+//
+// That said, dynamic_cast requires RTTI, which many people like to disable
+// for performance and code size reasons.  When RTTI is not available, we
+// still need to produce correct results.  So, in this case we have to fall
+// back to using reflection, which is what we would have done anyway if the
+// objects were not of the exact same class.
+//
+// dynamic_cast_if_available() implements this logic.  If RTTI is
+// enabled, it does a dynamic_cast.  If RTTI is disabled, it just returns
+// NULL.
+//
+// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI.
+// On MSVC, this should be detected automatically.
+template<typename To, typename From>
+inline To dynamic_cast_if_available(From from) {
+#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
+  return NULL;
+#else
+  return dynamic_cast<To>(from);
+#endif
+}
+
+// Tries to downcast this message to a generated message type.
+// Returns NULL if this class is not an instance of T.
+//
+// This is like dynamic_cast_if_available, except it works even when
+// dynamic_cast is not available by using Reflection.  However it only works
+// with Message objects.
+//
+// TODO(haberman): can we remove dynamic_cast_if_available in favor of this?
+template <typename T>
+T* DynamicCastToGenerated(const Message* from) {
+  // Compile-time assert that T is a generated type that has a
+  // default_instance() accessor, but avoid actually calling it.
+  const T&(*get_default_instance)() = &T::default_instance;
+  (void)get_default_instance;
+
+  // Compile-time assert that T is a subclass of google::protobuf::Message.
+  const Message* unused = static_cast<T*>(NULL);
+  (void)unused;
+
+#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \
+  (defined(_MSC_VER) && !defined(_CPPRTTI))
+  bool ok = &T::default_instance() ==
+            from->GetReflection()->GetMessageFactory()->GetPrototype(
+                from->GetDescriptor());
+  return ok ? down_cast<T*>(from) : NULL;
+#else
+  return dynamic_cast<T*>(from);
+#endif
+}
+
+template <typename T>
+T* DynamicCastToGenerated(Message* from) {
+  const Message* message_const = from;
+  return const_cast<T*>(DynamicCastToGenerated<const T>(message_const));
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection_unittest.cc
new file mode 100644
index 0000000..85ebdef
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -0,0 +1,852 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// To test GeneratedMessageReflection, we actually let the protocol compiler
+// generate a full protocol message implementation and then test its
+// reflection interface.  This is much easier and more maintainable than
+// trying to create our own Message class for GeneratedMessageReflection
+// to wrap.
+//
+// The tests here closely mirror some of the tests in
+// compiler/cpp/unittest, except using the reflection interface
+// rather than generated accessors.
+
+#include <google/protobuf/generated_message_reflection.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+const FieldDescriptor* F(const string& name) {
+  const FieldDescriptor* result =
+    unittest::TestAllTypes::descriptor()->FindFieldByName(name);
+  GOOGLE_CHECK(result != NULL);
+  return result;
+}
+
+TEST(GeneratedMessageReflectionTest, Defaults) {
+  // Check that all default values are set correctly in the initial message.
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  reflection_tester.ExpectClearViaReflection(message);
+
+  const Reflection* reflection = message.GetReflection();
+
+  // Messages should return pointers to default instances until first use.
+  // (This is not checked by ExpectClear() since it is not actually true after
+  // the fields have been set and then cleared.)
+  EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(),
+            &reflection->GetMessage(message, F("optionalgroup")));
+  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_nested_message")));
+  EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_foreign_message")));
+  EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_import_message")));
+}
+
+TEST(GeneratedMessageReflectionTest, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+  reflection_tester.ExpectAllFieldsSetViaReflection(message);
+
+  reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
+  TestUtil::ExpectRepeatedFieldsModified(message);
+}
+
+TEST(GeneratedMessageReflectionTest, GetStringReference) {
+  // Test that GetStringReference() returns the underlying string when it is
+  // a normal string field.
+  unittest::TestAllTypes message;
+  message.set_optional_string("foo");
+  message.add_repeated_string("foo");
+
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+
+  EXPECT_EQ(&message.optional_string(),
+      &reflection->GetStringReference(message, F("optional_string"), &scratch))
+    << "For simple string fields, GetStringReference() should return a "
+       "reference to the underlying string.";
+  EXPECT_EQ(&message.repeated_string(0),
+      &reflection->GetRepeatedStringReference(message, F("repeated_string"),
+                                              0, &scratch))
+    << "For simple string fields, GetRepeatedStringReference() should return "
+       "a reference to the underlying string.";
+}
+
+
+TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
+  // Check that after setting all fields and then clearing, getting an
+  // embedded message does NOT return the default instance.
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  TestUtil::SetAllFields(&message);
+  message.Clear();
+
+  const Reflection* reflection = message.GetReflection();
+
+  EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
+            &reflection->GetMessage(message, F("optionalgroup")));
+  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_nested_message")));
+  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_foreign_message")));
+  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
+            &reflection->GetMessage(message, F("optional_import_message")));
+}
+
+
+TEST(GeneratedMessageReflectionTest, Swap) {
+  unittest::TestAllTypes message1;
+  unittest::TestAllTypes message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectClear(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapWithBothSet) {
+  unittest::TestAllTypes message1;
+  unittest::TestAllTypes message2;
+
+  TestUtil::SetAllFields(&message1);
+  TestUtil::SetAllFields(&message2);
+  TestUtil::ModifyRepeatedFields(&message2);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectRepeatedFieldsModified(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  message1.set_optional_int32(532819);
+
+  reflection->Swap(&message1, &message2);
+
+  EXPECT_EQ(532819, message2.optional_int32());
+}
+
+TEST(GeneratedMessageReflectionTest, SwapExtensions) {
+  unittest::TestAllExtensions message1;
+  unittest::TestAllExtensions message2;
+
+  TestUtil::SetAllExtensions(&message1);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectExtensionsClear(message1);
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapUnknown) {
+  unittest::TestEmptyMessage message1, message2;
+
+  message1.mutable_unknown_fields()->AddVarint(1234, 1);
+
+  EXPECT_EQ(1, message1.unknown_fields().field_count());
+  EXPECT_EQ(0, message2.unknown_fields().field_count());
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+  EXPECT_EQ(0, message1.unknown_fields().field_count());
+  EXPECT_EQ(1, message2.unknown_fields().field_count());
+}
+
+TEST(GeneratedMessageReflectionTest, SwapFields) {
+  unittest::TestAllTypes message1, message2;
+  message1.set_optional_double(12.3);
+  message1.mutable_repeated_int32()->Add(10);
+  message1.mutable_repeated_int32()->Add(20);
+
+  message2.set_optional_string("hello");
+  message2.mutable_repeated_int64()->Add(30);
+
+  vector<const FieldDescriptor*> fields;
+  const Descriptor* descriptor = message1.GetDescriptor();
+  fields.push_back(descriptor->FindFieldByName("optional_double"));
+  fields.push_back(descriptor->FindFieldByName("repeated_int32"));
+  fields.push_back(descriptor->FindFieldByName("optional_string"));
+  fields.push_back(descriptor->FindFieldByName("optional_uint64"));
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->SwapFields(&message1, &message2, fields);
+
+  EXPECT_FALSE(message1.has_optional_double());
+  EXPECT_EQ(0, message1.repeated_int32_size());
+  EXPECT_TRUE(message1.has_optional_string());
+  EXPECT_EQ("hello", message1.optional_string());
+  EXPECT_EQ(0, message1.repeated_int64_size());
+  EXPECT_FALSE(message1.has_optional_uint64());
+
+  EXPECT_TRUE(message2.has_optional_double());
+  EXPECT_EQ(12.3, message2.optional_double());
+  EXPECT_EQ(2, message2.repeated_int32_size());
+  EXPECT_EQ(10, message2.repeated_int32(0));
+  EXPECT_EQ(20, message2.repeated_int32(1));
+  EXPECT_FALSE(message2.has_optional_string());
+  EXPECT_EQ(1, message2.repeated_int64_size());
+  EXPECT_FALSE(message2.has_optional_uint64());
+}
+
+TEST(GeneratedMessageReflectionTest, SwapFieldsAll) {
+  unittest::TestAllTypes message1;
+  unittest::TestAllTypes message2;
+
+  TestUtil::SetAllFields(&message2);
+
+  vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1.GetReflection();
+  reflection->ListFields(message2, &fields);
+  reflection->SwapFields(&message1, &message2, fields);
+
+  TestUtil::ExpectAllFieldsSet(message1);
+  TestUtil::ExpectClear(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapFieldsAllExtension) {
+  unittest::TestAllExtensions message1;
+  unittest::TestAllExtensions message2;
+
+  TestUtil::SetAllExtensions(&message1);
+
+  vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1.GetReflection();
+  reflection->ListFields(message1, &fields);
+  reflection->SwapFields(&message1, &message2, fields);
+
+  TestUtil::ExpectExtensionsClear(message1);
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapOneof) {
+  unittest::TestOneof2 message1, message2;
+  TestUtil::SetOneof1(&message1);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectOneofClear(message1);
+  TestUtil::ExpectOneofSet1(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapOneofBothSet) {
+  unittest::TestOneof2 message1, message2;
+  TestUtil::SetOneof1(&message1);
+  TestUtil::SetOneof2(&message2);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectOneofSet2(message1);
+  TestUtil::ExpectOneofSet1(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapFieldsOneof) {
+  unittest::TestOneof2 message1, message2;
+  TestUtil::SetOneof1(&message1);
+
+  vector<const FieldDescriptor*> fields;
+  const Descriptor* descriptor = message1.GetDescriptor();
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields.push_back(descriptor->field(i));
+  }
+  const Reflection* reflection = message1.GetReflection();
+  reflection->SwapFields(&message1, &message2, fields);
+
+  TestUtil::ExpectOneofClear(message1);
+  TestUtil::ExpectOneofSet1(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, RemoveLast) {
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  TestUtil::SetAllFields(&message);
+
+  reflection_tester.RemoveLastRepeatedsViaReflection(&message);
+
+  TestUtil::ExpectLastRepeatedsRemoved(message);
+}
+
+TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) {
+  unittest::TestAllExtensions message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+
+  TestUtil::SetAllExtensions(&message);
+
+  reflection_tester.RemoveLastRepeatedsViaReflection(&message);
+
+  TestUtil::ExpectLastRepeatedExtensionsRemoved(message);
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseLast) {
+  unittest::TestAllTypes message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  TestUtil::ReflectionTester reflection_tester(descriptor);
+
+  TestUtil::SetAllFields(&message);
+
+  reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false);
+
+  TestUtil::ExpectLastRepeatedsReleased(message);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  TestUtil::SetAllFields(&message);
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  const protobuf_unittest::ForeignMessage* expected =
+      message.mutable_repeated_foreign_message(1);
+  google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+      &message, descriptor->FindFieldByName("repeated_foreign_message")));
+  EXPECT_EQ(expected, released.get());
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
+  unittest::TestAllExtensions message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  TestUtil::ReflectionTester reflection_tester(descriptor);
+
+  TestUtil::SetAllExtensions(&message);
+
+  reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true);
+
+  TestUtil::ExpectLastRepeatedExtensionsReleased(message);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  TestUtil::SetAllExtensions(&message);
+  ASSERT_EQ(2, message.ExtensionSize(
+      unittest::repeated_foreign_message_extension));
+  const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
+      unittest::repeated_foreign_message_extension, 1);
+  google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+      &message, descriptor->file()->FindExtensionByName(
+                    "repeated_foreign_message_extension")));
+  EXPECT_EQ(expected, released.get());
+
+}
+
+TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) {
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  TestUtil::SetAllFields(&message);
+
+  // Swap and test that fields are all swapped.
+  reflection_tester.SwapRepeatedsViaReflection(&message);
+  TestUtil::ExpectRepeatedsSwapped(message);
+
+  // Swap back and test that fields are all back to original values.
+  reflection_tester.SwapRepeatedsViaReflection(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapRepeatedElementsExtension) {
+  unittest::TestAllExtensions message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+
+  TestUtil::SetAllExtensions(&message);
+
+  // Swap and test that fields are all swapped.
+  reflection_tester.SwapRepeatedsViaReflection(&message);
+  TestUtil::ExpectRepeatedExtensionsSwapped(message);
+
+  // Swap back and test that fields are all back to original values.
+  reflection_tester.SwapRepeatedsViaReflection(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, Extensions) {
+  // Set every extension to a unique value then go back and check all those
+  // values.
+  unittest::TestAllExtensions message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+  reflection_tester.ExpectAllFieldsSetViaReflection(message);
+
+  reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
+  TestUtil::ExpectRepeatedExtensionsModified(message);
+}
+
+TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) {
+  const Reflection* reflection =
+    unittest::TestAllExtensions::default_instance().GetReflection();
+
+  const FieldDescriptor* extension1 =
+    unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
+      "optional_int32_extension");
+  const FieldDescriptor* extension2 =
+    unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
+      "repeated_string_extension");
+
+  EXPECT_EQ(extension1,
+            reflection->FindKnownExtensionByNumber(extension1->number()));
+  EXPECT_EQ(extension2,
+            reflection->FindKnownExtensionByNumber(extension2->number()));
+
+  // Non-existent extension.
+  EXPECT_TRUE(reflection->FindKnownExtensionByNumber(62341) == NULL);
+
+  // Extensions of TestAllExtensions should not show up as extensions of
+  // other types.
+  EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()->
+              FindKnownExtensionByNumber(extension1->number()) == NULL);
+}
+
+TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
+  const Reflection* reflection =
+    unittest::TestAllExtensions::default_instance().GetReflection();
+
+  const FieldDescriptor* extension1 =
+    unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
+      "optional_int32_extension");
+  const FieldDescriptor* extension2 =
+    unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
+      "repeated_string_extension");
+
+  EXPECT_EQ(extension1,
+            reflection->FindKnownExtensionByName(extension1->full_name()));
+  EXPECT_EQ(extension2,
+            reflection->FindKnownExtensionByName(extension2->full_name()));
+
+  // Non-existent extension.
+  EXPECT_TRUE(reflection->FindKnownExtensionByName("no_such_ext") == NULL);
+
+  // Extensions of TestAllExtensions should not show up as extensions of
+  // other types.
+  EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()->
+              FindKnownExtensionByName(extension1->full_name()) == NULL);
+}
+
+TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) {
+  unittest::TestAllTypes from_message1;
+  unittest::TestAllTypes from_message2;
+  unittest::TestAllTypes to_message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+  reflection_tester.SetAllFieldsViaReflection(&from_message1);
+  reflection_tester.SetAllFieldsViaReflection(&from_message2);
+
+  // Before moving fields, we expect the nested messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are moved we should get non-NULL releases.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+      &from_message1, &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // Another move to make sure that we can SetAllocated several times.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+      &from_message2, &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the
+  // releases to be NULL again.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection(
+      &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::IS_NULL);
+}
+
+TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) {
+  unittest::TestAllExtensions from_message1;
+  unittest::TestAllExtensions from_message2;
+  unittest::TestAllExtensions to_message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+  reflection_tester.SetAllFieldsViaReflection(&from_message1);
+  reflection_tester.SetAllFieldsViaReflection(&from_message2);
+
+  // Before moving fields, we expect the nested messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are moved we should get non-NULL releases.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+      &from_message1, &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // Another move to make sure that we can SetAllocated several times.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+      &from_message2, &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the
+  // releases to be NULL again.
+  reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection(
+      &to_message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &to_message, TestUtil::ReflectionTester::IS_NULL);
+}
+
+TEST(GeneratedMessageReflectionTest, AddRepeatedMessage) {
+  unittest::TestAllTypes message;
+
+  const Reflection* reflection = message.GetReflection();
+  const Reflection* nested_reflection =
+      unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+  const FieldDescriptor* nested_bb =
+      unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+          "bb");
+
+  Message* nested = reflection->AddMessage(
+      &message, F("repeated_nested_message"));
+  nested_reflection->SetInt32(nested, nested_bb, 11);
+
+  EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, MutableRepeatedMessage) {
+  unittest::TestAllTypes message;
+
+  const Reflection* reflection = message.GetReflection();
+  const Reflection* nested_reflection =
+      unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+  const FieldDescriptor* nested_bb =
+      unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+          "bb");
+
+  message.add_repeated_nested_message()->set_bb(12);
+
+  Message* nested = reflection->MutableRepeatedMessage(
+      &message, F("repeated_nested_message"), 0);
+  EXPECT_EQ(12, nested_reflection->GetInt32(*nested, nested_bb));
+  nested_reflection->SetInt32(nested, nested_bb, 13);
+  EXPECT_EQ(13, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, AddAllocatedMessage) {
+  unittest::TestAllTypes message;
+
+  const Reflection* reflection = message.GetReflection();
+
+  unittest::TestAllTypes::NestedMessage* nested =
+      new unittest::TestAllTypes::NestedMessage();
+  nested->set_bb(11);
+  reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), nested);
+  EXPECT_EQ(1, message.repeated_nested_message_size());
+  EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) {
+  unittest::TestOneof2 message;
+  TestUtil::SetOneof1(&message);
+
+  const Reflection* reflection = message.GetReflection();
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+  EXPECT_EQ(4, fields.size());
+}
+
+TEST(GeneratedMessageReflectionTest, Oneof) {
+  unittest::TestOneof2 message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = message.GetReflection();
+
+  // Check default values.
+  EXPECT_EQ(0, reflection->GetInt32(
+      message, descriptor->FindFieldByName("foo_int")));
+  EXPECT_EQ("", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_string")));
+  EXPECT_EQ("", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_cord")));
+  EXPECT_EQ("", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_string_piece")));
+  EXPECT_EQ("", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_bytes")));
+  EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum(
+      message, descriptor->FindFieldByName("foo_enum"))->number());
+  EXPECT_EQ(&unittest::TestOneof2::NestedMessage::default_instance(),
+            &reflection->GetMessage(
+                message, descriptor->FindFieldByName("foo_message")));
+  EXPECT_EQ(&unittest::TestOneof2::FooGroup::default_instance(),
+            &reflection->GetMessage(
+                message, descriptor->FindFieldByName("foogroup")));
+  EXPECT_NE(&unittest::TestOneof2::FooGroup::default_instance(),
+            &reflection->GetMessage(
+                message, descriptor->FindFieldByName("foo_lazy_message")));
+  EXPECT_EQ(5, reflection->GetInt32(
+      message, descriptor->FindFieldByName("bar_int")));
+  EXPECT_EQ("STRING", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_string")));
+  EXPECT_EQ("CORD", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_cord")));
+  EXPECT_EQ("SPIECE", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_string_piece")));
+  EXPECT_EQ("BYTES", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_bytes")));
+  EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum(
+      message, descriptor->FindFieldByName("bar_enum"))->number());
+
+  // Check Set functions.
+  reflection->SetInt32(
+      &message, descriptor->FindFieldByName("foo_int"), 123);
+  EXPECT_EQ(123, reflection->GetInt32(
+      message, descriptor->FindFieldByName("foo_int")));
+  reflection->SetString(
+      &message, descriptor->FindFieldByName("foo_string"), "abc");
+  EXPECT_EQ("abc", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_string")));
+  reflection->SetString(
+      &message, descriptor->FindFieldByName("foo_bytes"), "bytes");
+  EXPECT_EQ("bytes", reflection->GetString(
+      message, descriptor->FindFieldByName("foo_bytes")));
+  reflection->SetString(
+      &message, descriptor->FindFieldByName("bar_cord"), "change_cord");
+  EXPECT_EQ("change_cord", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_cord")));
+  reflection->SetString(
+      &message, descriptor->FindFieldByName("bar_string_piece"),
+      "change_spiece");
+  EXPECT_EQ("change_spiece", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_string_piece")));
+}
+
+TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) {
+  unittest::TestOneof2 from_message1;
+  unittest::TestOneof2 from_message2;
+  unittest::TestOneof2 to_message;
+  const Descriptor* descriptor = unittest::TestOneof2::descriptor();
+  const Reflection* reflection = to_message.GetReflection();
+
+  Message* released = reflection->ReleaseMessage(
+      &to_message, descriptor->FindFieldByName("foo_lazy_message"));
+  EXPECT_TRUE(released == NULL);
+  released = reflection->ReleaseMessage(
+      &to_message, descriptor->FindFieldByName("foo_message"));
+  EXPECT_TRUE(released == NULL);
+
+  TestUtil::ReflectionTester::SetOneofViaReflection(&from_message1);
+  TestUtil::ReflectionTester::ExpectOneofSetViaReflection(from_message1);
+
+  TestUtil::ReflectionTester::
+      SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+          &from_message1, &to_message);
+  const Message& sub_message = reflection->GetMessage(
+      to_message, descriptor->FindFieldByName("foo_lazy_message"));
+  released = reflection->ReleaseMessage(
+      &to_message, descriptor->FindFieldByName("foo_lazy_message"));
+  EXPECT_TRUE(released != NULL);
+  EXPECT_EQ(&sub_message, released);
+  delete released;
+
+  TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2);
+
+  reflection->MutableMessage(
+      &from_message2, descriptor->FindFieldByName("foo_message"));
+
+  TestUtil::ReflectionTester::
+      SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+          &from_message2, &to_message);
+
+  const Message& sub_message2 = reflection->GetMessage(
+      to_message, descriptor->FindFieldByName("foo_message"));
+  released = reflection->ReleaseMessage(
+      &to_message, descriptor->FindFieldByName("foo_message"));
+  EXPECT_TRUE(released != NULL);
+  EXPECT_EQ(&sub_message2, released);
+  delete released;
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) {
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  // When nothing is set, we expect all released messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are set we should get non-NULL releases.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After Clear() we may or may not get a message from ReleaseMessage().
+  // This is implementation specific.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  message.Clear();
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+  // Test a different code path for setting after releasing.
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) {
+  unittest::TestAllExtensions message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+
+  // When nothing is set, we expect all released messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are set we should get non-NULL releases.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After Clear() we may or may not get a message from ReleaseMessage().
+  // This is implementation specific.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  message.Clear();
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+  // Test a different code path for setting after releasing.
+  TestUtil::SetAllExtensions(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseOneofMessageTest) {
+  unittest::TestOneof2 message;
+  TestUtil::ReflectionTester::SetOneofViaReflection(&message);
+
+  const Descriptor* descriptor = unittest::TestOneof2::descriptor();
+  const Reflection* reflection = message.GetReflection();
+  const Message& sub_message = reflection->GetMessage(
+      message, descriptor->FindFieldByName("foo_lazy_message"));
+  Message* released = reflection->ReleaseMessage(
+      &message, descriptor->FindFieldByName("foo_lazy_message"));
+
+  EXPECT_TRUE(released != NULL);
+  EXPECT_EQ(&sub_message, released);
+  delete released;
+
+  released = reflection->ReleaseMessage(
+      &message, descriptor->FindFieldByName("foo_lazy_message"));
+  EXPECT_TRUE(released == NULL);
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+TEST(GeneratedMessageReflectionTest, UsageErrors) {
+  unittest::TestAllTypes message;
+  const Reflection* reflection = message.GetReflection();
+  const Descriptor* descriptor = message.GetDescriptor();
+
+#define f(NAME) descriptor->FindFieldByName(NAME)
+
+  // Testing every single failure mode would be too much work.  Let's just
+  // check a few.
+  EXPECT_DEATH(
+    reflection->GetInt32(
+      message, descriptor->FindFieldByName("optional_int64")),
+    "Protocol Buffer reflection usage error:\n"
+    "  Method      : google::protobuf::Reflection::GetInt32\n"
+    "  Message type: protobuf_unittest\\.TestAllTypes\n"
+    "  Field       : protobuf_unittest\\.TestAllTypes\\.optional_int64\n"
+    "  Problem     : Field is not the right type for this message:\n"
+    "    Expected  : CPPTYPE_INT32\n"
+    "    Field type: CPPTYPE_INT64");
+  EXPECT_DEATH(
+    reflection->GetInt32(
+      message, descriptor->FindFieldByName("repeated_int32")),
+    "Protocol Buffer reflection usage error:\n"
+    "  Method      : google::protobuf::Reflection::GetInt32\n"
+    "  Message type: protobuf_unittest.TestAllTypes\n"
+    "  Field       : protobuf_unittest.TestAllTypes.repeated_int32\n"
+    "  Problem     : Field is repeated; the method requires a singular field.");
+  EXPECT_DEATH(
+    reflection->GetInt32(
+      message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
+    "Protocol Buffer reflection usage error:\n"
+    "  Method      : google::protobuf::Reflection::GetInt32\n"
+    "  Message type: protobuf_unittest.TestAllTypes\n"
+    "  Field       : protobuf_unittest.ForeignMessage.c\n"
+    "  Problem     : Field does not match message type.");
+  EXPECT_DEATH(
+    reflection->HasField(
+      message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
+    "Protocol Buffer reflection usage error:\n"
+    "  Method      : google::protobuf::Reflection::HasField\n"
+    "  Message type: protobuf_unittest.TestAllTypes\n"
+    "  Field       : protobuf_unittest.ForeignMessage.c\n"
+    "  Problem     : Field does not match message type.");
+
+#undef f
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.cc b/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.cc
new file mode 100644
index 0000000..334051a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.cc
@@ -0,0 +1,84 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/generated_message_util.h>
+
+#include <limits>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+double Infinity() {
+  return std::numeric_limits<double>::infinity();
+}
+double NaN() {
+  return std::numeric_limits<double>::quiet_NaN();
+}
+
+const ::std::string* empty_string_;
+GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
+
+void DeleteEmptyString() {
+  delete empty_string_;
+}
+
+void InitEmptyString() {
+  empty_string_ = new string;
+  OnShutdown(&DeleteEmptyString);
+}
+
+const ::std::string& GetEmptyString() {
+  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
+  return GetEmptyStringAlreadyInited();
+}
+
+
+int StringSpaceUsedExcludingSelf(const string& str) {
+  const void* start = &str;
+  const void* end = &str + 1;
+  if (start <= str.data() && str.data() < end) {
+    // The string's data is stored inside the string object itself.
+    return 0;
+  } else {
+    return str.capacity();
+  }
+}
+
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.h b/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.h
new file mode 100644
index 0000000..36f18da
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/generated_message_util.h
@@ -0,0 +1,120 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains miscellaneous helper code used by generated code --
+// including lite types -- but which should not be used directly by users.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
+
+#include <assert.h>
+#include <string>
+
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+
+namespace protobuf {
+
+class Arena;
+namespace io { class CodedInputStream; }
+
+namespace internal {
+
+
+// Annotation for the compiler to emit a deprecation message if a field marked
+// with option 'deprecated=true' is used in the code, or for other things in
+// generated code which are deprecated.
+//
+// For internal use in the pb.cc files, deprecation warnings are suppressed
+// there.
+#undef DEPRECATED_PROTOBUF_FIELD
+#define PROTOBUF_DEPRECATED
+
+#define PROTOBUF_DEPRECATED_ATTR
+
+
+// Constants for special floating point values.
+LIBPROTOBUF_EXPORT double Infinity();
+LIBPROTOBUF_EXPORT double NaN();
+
+// TODO(jieluo): Change to template. We have tried to use template,
+// but it causes net/rpc/python:rpcutil_test fail (the empty string will
+// init twice). It may related to swig. Change to template after we
+// found the solution.
+
+// Default empty string object. Don't use the pointer directly. Instead, call
+// GetEmptyString() to get the reference.
+LIBPROTOBUF_EXPORT extern const ::std::string* empty_string_;
+LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_;
+LIBPROTOBUF_EXPORT void InitEmptyString();
+
+
+LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
+  assert(empty_string_ != NULL);
+  return *empty_string_;
+}
+
+LIBPROTOBUF_EXPORT const ::std::string& GetEmptyString();
+
+LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
+
+
+// True if IsInitialized() is true for all elements of t.  Type is expected
+// to be a RepeatedPtrField<some message type>.  It's useful to have this
+// helper here to keep the protobuf compiler from ever having to emit loops in
+// IsInitialized() methods.  We want the C++ compiler to inline this or not
+// as it sees fit.
+template <class Type> bool AllAreInitialized(const Type& t) {
+  for (int i = t.size(); --i >= 0; ) {
+    if (!t.Get(i).IsInitialized()) return false;
+  }
+  return true;
+}
+
+class ArenaString;
+
+// Read a length (varint32), followed by a string, from *input.  Return a
+// pointer to a copy of the string that resides in *arena.  Requires both
+// args to be non-NULL.  If something goes wrong while reading the data
+// then NULL is returned (e.g., input does not start with a valid varint).
+ArenaString* ReadArenaString(::google::protobuf::io::CodedInputStream* input,
+                             ::google::protobuf::Arena* arena);
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.cc b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.cc
new file mode 100644
index 0000000..d8354c1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.cc
@@ -0,0 +1,917 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This implementation is heavily optimized to make reads and writes
+// of small values (especially varints) as fast as possible.  In
+// particular, we optimize for the common case that a read or a write
+// will not cross the end of the buffer, since we can avoid a lot
+// of branching in this case.
+
+#include <google/protobuf/io/coded_stream_inl.h>
+#include <algorithm>
+#include <utility>
+#include <limits.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+namespace {
+
+static const int kMaxVarintBytes = 10;
+static const int kMaxVarint32Bytes = 5;
+
+
+inline bool NextNonEmpty(ZeroCopyInputStream* input,
+                         const void** data, int* size) {
+  bool success;
+  do {
+    success = input->Next(data, size);
+  } while (success && *size == 0);
+  return success;
+}
+
+}  // namespace
+
+// CodedInputStream ==================================================
+
+CodedInputStream::~CodedInputStream() {
+  if (input_ != NULL) {
+    BackUpInputToCurrentPosition();
+  }
+
+  if (total_bytes_warning_threshold_ == -2) {
+    GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
+  }
+}
+
+// Static.
+int CodedInputStream::default_recursion_limit_ = 100;
+
+
+void CodedOutputStream::EnableAliasing(bool enabled) {
+  aliasing_enabled_ = enabled && output_->AllowsAliasing();
+}
+
+void CodedInputStream::BackUpInputToCurrentPosition() {
+  int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
+  if (backup_bytes > 0) {
+    input_->BackUp(backup_bytes);
+
+    // total_bytes_read_ doesn't include overflow_bytes_.
+    total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
+    buffer_end_ = buffer_;
+    buffer_size_after_limit_ = 0;
+    overflow_bytes_ = 0;
+  }
+}
+
+inline void CodedInputStream::RecomputeBufferLimits() {
+  buffer_end_ += buffer_size_after_limit_;
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
+  if (closest_limit < total_bytes_read_) {
+    // The limit position is in the current buffer.  We must adjust
+    // the buffer size accordingly.
+    buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
+    buffer_end_ -= buffer_size_after_limit_;
+  } else {
+    buffer_size_after_limit_ = 0;
+  }
+}
+
+CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
+  // Current position relative to the beginning of the stream.
+  int current_position = CurrentPosition();
+
+  Limit old_limit = current_limit_;
+
+  // security: byte_limit is possibly evil, so check for negative values
+  // and overflow.
+  if (byte_limit >= 0 &&
+      byte_limit <= INT_MAX - current_position) {
+    current_limit_ = current_position + byte_limit;
+  } else {
+    // Negative or overflow.
+    current_limit_ = INT_MAX;
+  }
+
+  // We need to enforce all limits, not just the new one, so if the previous
+  // limit was before the new requested limit, we continue to enforce the
+  // previous limit.
+  current_limit_ = std::min(current_limit_, old_limit);
+
+  RecomputeBufferLimits();
+  return old_limit;
+}
+
+void CodedInputStream::PopLimit(Limit limit) {
+  // The limit passed in is actually the *old* limit, which we returned from
+  // PushLimit().
+  current_limit_ = limit;
+  RecomputeBufferLimits();
+
+  // We may no longer be at a legitimate message end.  ReadTag() needs to be
+  // called again to find out.
+  legitimate_message_end_ = false;
+}
+
+std::pair<CodedInputStream::Limit, int>
+CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
+  return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
+}
+
+CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
+  uint32 length;
+  return PushLimit(ReadVarint32(&length) ? length : 0);
+}
+
+bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
+  bool result = ConsumedEntireMessage();
+  PopLimit(limit);
+  GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_);
+  ++recursion_budget_;
+  return result;
+}
+
+bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
+  bool result = ConsumedEntireMessage();
+  PopLimit(limit);
+  return result;
+}
+
+int CodedInputStream::BytesUntilLimit() const {
+  if (current_limit_ == INT_MAX) return -1;
+  int current_position = CurrentPosition();
+
+  return current_limit_ - current_position;
+}
+
+void CodedInputStream::SetTotalBytesLimit(
+    int total_bytes_limit, int warning_threshold) {
+  // Make sure the limit isn't already past, since this could confuse other
+  // code.
+  int current_position = CurrentPosition();
+  total_bytes_limit_ = std::max(current_position, total_bytes_limit);
+  if (warning_threshold >= 0) {
+    total_bytes_warning_threshold_ = warning_threshold;
+  } else {
+    // warning_threshold is negative
+    total_bytes_warning_threshold_ = -1;
+  }
+  RecomputeBufferLimits();
+}
+
+int CodedInputStream::BytesUntilTotalBytesLimit() const {
+  if (total_bytes_limit_ == INT_MAX) return -1;
+  return total_bytes_limit_ - CurrentPosition();
+}
+
+void CodedInputStream::PrintTotalBytesLimitError() {
+  GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
+                "big (more than " << total_bytes_limit_
+             << " bytes).  To increase the limit (or to disable these "
+                "warnings), see CodedInputStream::SetTotalBytesLimit() "
+                "in google/protobuf/io/coded_stream.h.";
+}
+
+bool CodedInputStream::Skip(int count) {
+  if (count < 0) return false;  // security: count is often user-supplied
+
+  const int original_buffer_size = BufferSize();
+
+  if (count <= original_buffer_size) {
+    // Just skipping within the current buffer.  Easy.
+    Advance(count);
+    return true;
+  }
+
+  if (buffer_size_after_limit_ > 0) {
+    // We hit a limit inside this buffer.  Advance to the limit and fail.
+    Advance(original_buffer_size);
+    return false;
+  }
+
+  count -= original_buffer_size;
+  buffer_ = NULL;
+  buffer_end_ = buffer_;
+
+  // Make sure this skip doesn't try to skip past the current limit.
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
+  int bytes_until_limit = closest_limit - total_bytes_read_;
+  if (bytes_until_limit < count) {
+    // We hit the limit.  Skip up to it then fail.
+    if (bytes_until_limit > 0) {
+      total_bytes_read_ = closest_limit;
+      input_->Skip(bytes_until_limit);
+    }
+    return false;
+  }
+
+  total_bytes_read_ += count;
+  return input_->Skip(count);
+}
+
+bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
+  if (BufferSize() == 0 && !Refresh()) return false;
+
+  *data = buffer_;
+  *size = BufferSize();
+  return true;
+}
+
+bool CodedInputStream::ReadRaw(void* buffer, int size) {
+  return InternalReadRawInline(buffer, size);
+}
+
+bool CodedInputStream::ReadString(string* buffer, int size) {
+  if (size < 0) return false;  // security: size is often user-supplied
+  return InternalReadStringInline(buffer, size);
+}
+
+bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
+  if (!buffer->empty()) {
+    buffer->clear();
+  }
+
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
+  if (closest_limit != INT_MAX) {
+    int bytes_to_limit = closest_limit - CurrentPosition();
+    if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
+      buffer->reserve(size);
+    }
+  }
+
+  int current_buffer_size;
+  while ((current_buffer_size = BufferSize()) < size) {
+    // Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
+    if (current_buffer_size != 0) {
+      // Note:  string1.append(string2) is O(string2.size()) (as opposed to
+      //   O(string1.size() + string2.size()), which would be bad).
+      buffer->append(reinterpret_cast<const char*>(buffer_),
+                     current_buffer_size);
+    }
+    size -= current_buffer_size;
+    Advance(current_buffer_size);
+    if (!Refresh()) return false;
+  }
+
+  buffer->append(reinterpret_cast<const char*>(buffer_), size);
+  Advance(size);
+
+  return true;
+}
+
+
+bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
+  uint8 bytes[sizeof(*value)];
+
+  const uint8* ptr;
+  if (BufferSize() >= sizeof(*value)) {
+    // Fast path:  Enough bytes in the buffer to read directly.
+    ptr = buffer_;
+    Advance(sizeof(*value));
+  } else {
+    // Slow path:  Had to read past the end of the buffer.
+    if (!ReadRaw(bytes, sizeof(*value))) return false;
+    ptr = bytes;
+  }
+  ReadLittleEndian32FromArray(ptr, value);
+  return true;
+}
+
+bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
+  uint8 bytes[sizeof(*value)];
+
+  const uint8* ptr;
+  if (BufferSize() >= sizeof(*value)) {
+    // Fast path:  Enough bytes in the buffer to read directly.
+    ptr = buffer_;
+    Advance(sizeof(*value));
+  } else {
+    // Slow path:  Had to read past the end of the buffer.
+    if (!ReadRaw(bytes, sizeof(*value))) return false;
+    ptr = bytes;
+  }
+  ReadLittleEndian64FromArray(ptr, value);
+  return true;
+}
+
+namespace {
+
+// Read a varint from the given buffer, write it to *value, and return a pair.
+// The first part of the pair is true iff the read was successful.  The second
+// part is buffer + (number of bytes read).  This function is always inlined,
+// so returning a pair is costless.
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+    uint32 first_byte, const uint8* buffer,
+    uint32* value);
+inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+    uint32 first_byte, const uint8* buffer, uint32* value) {
+  // Fast path:  We have enough bytes left in the buffer to guarantee that
+  // this read won't cross the end, so we can skip the checks.
+  GOOGLE_DCHECK_EQ(*buffer, first_byte);
+  GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
+  const uint8* ptr = buffer;
+  uint32 b;
+  uint32 result = first_byte - 0x80;
+  ++ptr;  // We just processed the first byte.  Move on to the second.
+  b = *(ptr++); result += b <<  7; if (!(b & 0x80)) goto done;
+  result -= 0x80 << 7;
+  b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
+  result -= 0x80 << 14;
+  b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done;
+  result -= 0x80 << 21;
+  b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done;
+  // "result -= 0x80 << 28" is irrevelant.
+
+  // If the input is larger than 32 bits, we still need to read it all
+  // and discard the high-order bits.
+  for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
+    b = *(ptr++); if (!(b & 0x80)) goto done;
+  }
+
+  // We have overrun the maximum size of a varint (10 bytes).  Assume
+  // the data is corrupt.
+  return std::make_pair(false, ptr);
+
+ done:
+  *value = result;
+  return std::make_pair(true, ptr);
+}
+
+}  // namespace
+
+bool CodedInputStream::ReadVarint32Slow(uint32* value) {
+  // Directly invoke ReadVarint64Fallback, since we already tried to optimize
+  // for one-byte varints.
+  std::pair<uint64, bool> p = ReadVarint64Fallback();
+  *value = static_cast<uint32>(p.first);
+  return p.second;
+}
+
+int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
+  if (BufferSize() >= kMaxVarintBytes ||
+      // Optimization:  We're also safe if the buffer is non-empty and it ends
+      // with a byte that would terminate a varint.
+      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+    GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
+        << "Caller should provide us with *buffer_ when buffer is non-empty";
+    uint32 temp;
+    ::std::pair<bool, const uint8*> p =
+          ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
+    if (!p.first) return -1;
+    buffer_ = p.second;
+    return temp;
+  } else {
+    // Really slow case: we will incur the cost of an extra function call here,
+    // but moving this out of line reduces the size of this function, which
+    // improves the common case. In micro benchmarks, this is worth about 10-15%
+    uint32 temp;
+    return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
+  }
+}
+
+uint32 CodedInputStream::ReadTagSlow() {
+  if (buffer_ == buffer_end_) {
+    // Call refresh.
+    if (!Refresh()) {
+      // Refresh failed.  Make sure that it failed due to EOF, not because
+      // we hit total_bytes_limit_, which, unlike normal limits, is not a
+      // valid place to end a message.
+      int current_position = total_bytes_read_ - buffer_size_after_limit_;
+      if (current_position >= total_bytes_limit_) {
+        // Hit total_bytes_limit_.  But if we also hit the normal limit,
+        // we're still OK.
+        legitimate_message_end_ = current_limit_ == total_bytes_limit_;
+      } else {
+        legitimate_message_end_ = true;
+      }
+      return 0;
+    }
+  }
+
+  // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
+  // again, since we have now refreshed the buffer.
+  uint64 result = 0;
+  if (!ReadVarint64(&result)) return 0;
+  return static_cast<uint32>(result);
+}
+
+uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
+  const int buf_size = BufferSize();
+  if (buf_size >= kMaxVarintBytes ||
+      // Optimization:  We're also safe if the buffer is non-empty and it ends
+      // with a byte that would terminate a varint.
+      (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
+    GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
+    if (first_byte_or_zero == 0) {
+      ++buffer_;
+      return 0;
+    }
+    uint32 tag;
+    ::std::pair<bool, const uint8*> p =
+        ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
+    if (!p.first) {
+      return 0;
+    }
+    buffer_ = p.second;
+    return tag;
+  } else {
+    // We are commonly at a limit when attempting to read tags. Try to quickly
+    // detect this case without making another function call.
+    if ((buf_size == 0) &&
+        ((buffer_size_after_limit_ > 0) ||
+         (total_bytes_read_ == current_limit_)) &&
+        // Make sure that the limit we hit is not total_bytes_limit_, since
+        // in that case we still need to call Refresh() so that it prints an
+        // error.
+        total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
+      // We hit a byte limit.
+      legitimate_message_end_ = true;
+      return 0;
+    }
+    return ReadTagSlow();
+  }
+}
+
+bool CodedInputStream::ReadVarint64Slow(uint64* value) {
+  // Slow path:  This read might cross the end of the buffer, so we
+  // need to check and refresh the buffer if and when it does.
+
+  uint64 result = 0;
+  int count = 0;
+  uint32 b;
+
+  do {
+    if (count == kMaxVarintBytes) return false;
+    while (buffer_ == buffer_end_) {
+      if (!Refresh()) return false;
+    }
+    b = *buffer_;
+    result |= static_cast<uint64>(b & 0x7F) << (7 * count);
+    Advance(1);
+    ++count;
+  } while (b & 0x80);
+
+  *value = result;
+  return true;
+}
+
+std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
+  if (BufferSize() >= kMaxVarintBytes ||
+      // Optimization:  We're also safe if the buffer is non-empty and it ends
+      // with a byte that would terminate a varint.
+      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+    // Fast path:  We have enough bytes left in the buffer to guarantee that
+    // this read won't cross the end, so we can skip the checks.
+
+    const uint8* ptr = buffer_;
+    uint32 b;
+
+    // Splitting into 32-bit pieces gives better performance on 32-bit
+    // processors.
+    uint32 part0 = 0, part1 = 0, part2 = 0;
+
+    b = *(ptr++); part0  = b      ; if (!(b & 0x80)) goto done;
+    part0 -= 0x80;
+    b = *(ptr++); part0 += b <<  7; if (!(b & 0x80)) goto done;
+    part0 -= 0x80 << 7;
+    b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done;
+    part0 -= 0x80 << 14;
+    b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done;
+    part0 -= 0x80 << 21;
+    b = *(ptr++); part1  = b      ; if (!(b & 0x80)) goto done;
+    part1 -= 0x80;
+    b = *(ptr++); part1 += b <<  7; if (!(b & 0x80)) goto done;
+    part1 -= 0x80 << 7;
+    b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done;
+    part1 -= 0x80 << 14;
+    b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done;
+    part1 -= 0x80 << 21;
+    b = *(ptr++); part2  = b      ; if (!(b & 0x80)) goto done;
+    part2 -= 0x80;
+    b = *(ptr++); part2 += b <<  7; if (!(b & 0x80)) goto done;
+    // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0.
+
+    // We have overrun the maximum size of a varint (10 bytes).  The data
+    // must be corrupt.
+    return std::make_pair(0, false);
+
+   done:
+    Advance(ptr - buffer_);
+    return std::make_pair((static_cast<uint64>(part0)) |
+                              (static_cast<uint64>(part1) << 28) |
+                              (static_cast<uint64>(part2) << 56),
+                          true);
+  } else {
+    uint64 temp;
+    bool success = ReadVarint64Slow(&temp);
+    return std::make_pair(temp, success);
+  }
+}
+
+bool CodedInputStream::Refresh() {
+  GOOGLE_DCHECK_EQ(0, BufferSize());
+
+  if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
+      total_bytes_read_ == current_limit_) {
+    // We've hit a limit.  Stop.
+    int current_position = total_bytes_read_ - buffer_size_after_limit_;
+
+    if (current_position >= total_bytes_limit_ &&
+        total_bytes_limit_ != current_limit_) {
+      // Hit total_bytes_limit_.
+      PrintTotalBytesLimitError();
+    }
+
+    return false;
+  }
+
+  if (total_bytes_warning_threshold_ >= 0 &&
+      total_bytes_read_ >= total_bytes_warning_threshold_) {
+      GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message.  If the "
+                      "message turns out to be larger than "
+                   << total_bytes_limit_ << " bytes, parsing will be halted "
+                      "for security reasons.  To increase the limit (or to "
+                      "disable these warnings), see "
+                      "CodedInputStream::SetTotalBytesLimit() in "
+                      "google/protobuf/io/coded_stream.h.";
+
+    // Don't warn again for this stream, and print total size at the end.
+    total_bytes_warning_threshold_ = -2;
+  }
+
+  const void* void_buffer;
+  int buffer_size;
+  if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
+    buffer_ = reinterpret_cast<const uint8*>(void_buffer);
+    buffer_end_ = buffer_ + buffer_size;
+    GOOGLE_CHECK_GE(buffer_size, 0);
+
+    if (total_bytes_read_ <= INT_MAX - buffer_size) {
+      total_bytes_read_ += buffer_size;
+    } else {
+      // Overflow.  Reset buffer_end_ to not include the bytes beyond INT_MAX.
+      // We can't get that far anyway, because total_bytes_limit_ is guaranteed
+      // to be less than it.  We need to keep track of the number of bytes
+      // we discarded, though, so that we can call input_->BackUp() to back
+      // up over them on destruction.
+
+      // The following line is equivalent to:
+      //   overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
+      // except that it avoids overflows.  Signed integer overflow has
+      // undefined results according to the C standard.
+      overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
+      buffer_end_ -= overflow_bytes_;
+      total_bytes_read_ = INT_MAX;
+    }
+
+    RecomputeBufferLimits();
+    return true;
+  } else {
+    buffer_ = NULL;
+    buffer_end_ = NULL;
+    return false;
+  }
+}
+
+// CodedOutputStream =================================================
+
+CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
+  : output_(output),
+    buffer_(NULL),
+    buffer_size_(0),
+    total_bytes_(0),
+    had_error_(false),
+    aliasing_enabled_(false) {
+  // Eagerly Refresh() so buffer space is immediately available.
+  Refresh();
+  // The Refresh() may have failed. If the client doesn't write any data,
+  // though, don't consider this an error. If the client does write data, then
+  // another Refresh() will be attempted and it will set the error once again.
+  had_error_ = false;
+}
+
+CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
+                                     bool do_eager_refresh)
+  : output_(output),
+    buffer_(NULL),
+    buffer_size_(0),
+    total_bytes_(0),
+    had_error_(false),
+    aliasing_enabled_(false) {
+  if (do_eager_refresh) {
+    // Eagerly Refresh() so buffer space is immediately available.
+    Refresh();
+    // The Refresh() may have failed. If the client doesn't write any data,
+    // though, don't consider this an error. If the client does write data, then
+    // another Refresh() will be attempted and it will set the error once again.
+    had_error_ = false;
+  }
+}
+
+CodedOutputStream::~CodedOutputStream() {
+  Trim();
+}
+
+void CodedOutputStream::Trim() {
+  if (buffer_size_ > 0) {
+    output_->BackUp(buffer_size_);
+    total_bytes_ -= buffer_size_;
+    buffer_size_ = 0;
+    buffer_ = NULL;
+  }
+}
+
+bool CodedOutputStream::Skip(int count) {
+  if (count < 0) return false;
+
+  while (count > buffer_size_) {
+    count -= buffer_size_;
+    if (!Refresh()) return false;
+  }
+
+  Advance(count);
+  return true;
+}
+
+bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
+  if (buffer_size_ == 0 && !Refresh()) return false;
+
+  *data = buffer_;
+  *size = buffer_size_;
+  return true;
+}
+
+void CodedOutputStream::WriteRaw(const void* data, int size) {
+  while (buffer_size_ < size) {
+    memcpy(buffer_, data, buffer_size_);
+    size -= buffer_size_;
+    data = reinterpret_cast<const uint8*>(data) + buffer_size_;
+    if (!Refresh()) return;
+  }
+
+  memcpy(buffer_, data, size);
+  Advance(size);
+}
+
+uint8* CodedOutputStream::WriteRawToArray(
+    const void* data, int size, uint8* target) {
+  memcpy(target, data, size);
+  return target + size;
+}
+
+
+void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
+  if (size < buffer_size_
+      ) {
+    WriteRaw(data, size);
+  } else {
+    Trim();
+
+    total_bytes_ += size;
+    had_error_ |= !output_->WriteAliasedRaw(data, size);
+  }
+}
+
+void CodedOutputStream::WriteLittleEndian32(uint32 value) {
+  uint8 bytes[sizeof(value)];
+
+  bool use_fast = buffer_size_ >= sizeof(value);
+  uint8* ptr = use_fast ? buffer_ : bytes;
+
+  WriteLittleEndian32ToArray(value, ptr);
+
+  if (use_fast) {
+    Advance(sizeof(value));
+  } else {
+    WriteRaw(bytes, sizeof(value));
+  }
+}
+
+void CodedOutputStream::WriteLittleEndian64(uint64 value) {
+  uint8 bytes[sizeof(value)];
+
+  bool use_fast = buffer_size_ >= sizeof(value);
+  uint8* ptr = use_fast ? buffer_ : bytes;
+
+  WriteLittleEndian64ToArray(value, ptr);
+
+  if (use_fast) {
+    Advance(sizeof(value));
+  } else {
+    WriteRaw(bytes, sizeof(value));
+  }
+}
+
+void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
+  uint8 bytes[kMaxVarint32Bytes];
+  uint8* target = &bytes[0];
+  uint8* end = WriteVarint32ToArray(value, target);
+  int size = end - target;
+  WriteRaw(bytes, size);
+}
+
+inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
+    uint64 value, uint8* target) {
+  // Splitting into 32-bit pieces gives better performance on 32-bit
+  // processors.
+  uint32 part0 = static_cast<uint32>(value      );
+  uint32 part1 = static_cast<uint32>(value >> 28);
+  uint32 part2 = static_cast<uint32>(value >> 56);
+
+  int size;
+
+  // Here we can't really optimize for small numbers, since the value is
+  // split into three parts.  Cheking for numbers < 128, for instance,
+  // would require three comparisons, since you'd have to make sure part1
+  // and part2 are zero.  However, if the caller is using 64-bit integers,
+  // it is likely that they expect the numbers to often be very large, so
+  // we probably don't want to optimize for small numbers anyway.  Thus,
+  // we end up with a hardcoded binary search tree...
+  if (part2 == 0) {
+    if (part1 == 0) {
+      if (part0 < (1 << 14)) {
+        if (part0 < (1 << 7)) {
+          size = 1; goto size1;
+        } else {
+          size = 2; goto size2;
+        }
+      } else {
+        if (part0 < (1 << 21)) {
+          size = 3; goto size3;
+        } else {
+          size = 4; goto size4;
+        }
+      }
+    } else {
+      if (part1 < (1 << 14)) {
+        if (part1 < (1 << 7)) {
+          size = 5; goto size5;
+        } else {
+          size = 6; goto size6;
+        }
+      } else {
+        if (part1 < (1 << 21)) {
+          size = 7; goto size7;
+        } else {
+          size = 8; goto size8;
+        }
+      }
+    }
+  } else {
+    if (part2 < (1 << 7)) {
+      size = 9; goto size9;
+    } else {
+      size = 10; goto size10;
+    }
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+
+  size10: target[9] = static_cast<uint8>((part2 >>  7) | 0x80);
+  size9 : target[8] = static_cast<uint8>((part2      ) | 0x80);
+  size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
+  size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
+  size6 : target[5] = static_cast<uint8>((part1 >>  7) | 0x80);
+  size5 : target[4] = static_cast<uint8>((part1      ) | 0x80);
+  size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
+  size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
+  size2 : target[1] = static_cast<uint8>((part0 >>  7) | 0x80);
+  size1 : target[0] = static_cast<uint8>((part0      ) | 0x80);
+
+  target[size-1] &= 0x7F;
+  return target + size;
+}
+
+void CodedOutputStream::WriteVarint64(uint64 value) {
+  if (buffer_size_ >= kMaxVarintBytes) {
+    // Fast path:  We have enough bytes left in the buffer to guarantee that
+    // this write won't cross the end, so we can skip the checks.
+    uint8* target = buffer_;
+
+    uint8* end = WriteVarint64ToArrayInline(value, target);
+    int size = end - target;
+    Advance(size);
+  } else {
+    // Slow path:  This write might cross the end of the buffer, so we
+    // compose the bytes first then use WriteRaw().
+    uint8 bytes[kMaxVarintBytes];
+    int size = 0;
+    while (value > 0x7F) {
+      bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
+      value >>= 7;
+    }
+    bytes[size++] = static_cast<uint8>(value) & 0x7F;
+    WriteRaw(bytes, size);
+  }
+}
+
+uint8* CodedOutputStream::WriteVarint64ToArray(
+    uint64 value, uint8* target) {
+  return WriteVarint64ToArrayInline(value, target);
+}
+
+bool CodedOutputStream::Refresh() {
+  void* void_buffer;
+  if (output_->Next(&void_buffer, &buffer_size_)) {
+    buffer_ = reinterpret_cast<uint8*>(void_buffer);
+    total_bytes_ += buffer_size_;
+    return true;
+  } else {
+    buffer_ = NULL;
+    buffer_size_ = 0;
+    had_error_ = true;
+    return false;
+  }
+}
+
+int CodedOutputStream::VarintSize32Fallback(uint32 value) {
+  if (value < (1 << 7)) {
+    return 1;
+  } else if (value < (1 << 14)) {
+    return 2;
+  } else if (value < (1 << 21)) {
+    return 3;
+  } else if (value < (1 << 28)) {
+    return 4;
+  } else {
+    return 5;
+  }
+}
+
+int CodedOutputStream::VarintSize64(uint64 value) {
+  if (value < (1ull << 35)) {
+    if (value < (1ull << 7)) {
+      return 1;
+    } else if (value < (1ull << 14)) {
+      return 2;
+    } else if (value < (1ull << 21)) {
+      return 3;
+    } else if (value < (1ull << 28)) {
+      return 4;
+    } else {
+      return 5;
+    }
+  } else {
+    if (value < (1ull << 42)) {
+      return 6;
+    } else if (value < (1ull << 49)) {
+      return 7;
+    } else if (value < (1ull << 56)) {
+      return 8;
+    } else if (value < (1ull << 63)) {
+      return 9;
+    } else {
+      return 10;
+    }
+  }
+}
+
+uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
+                                                     uint8* target) {
+  GOOGLE_DCHECK_LE(str.size(), kuint32max);
+  target = WriteVarint32ToArray(str.size(), target);
+  return WriteStringToArray(str, target);
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.h b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.h
new file mode 100644
index 0000000..c81a33a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream.h
@@ -0,0 +1,1294 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains the CodedInputStream and CodedOutputStream classes,
+// which wrap a ZeroCopyInputStream or ZeroCopyOutputStream, respectively,
+// and allow you to read or write individual pieces of data in various
+// formats.  In particular, these implement the varint encoding for
+// integers, a simple variable-length encoding in which smaller numbers
+// take fewer bytes.
+//
+// Typically these classes will only be used internally by the protocol
+// buffer library in order to encode and decode protocol buffers.  Clients
+// of the library only need to know about this class if they wish to write
+// custom message parsing or serialization procedures.
+//
+// CodedOutputStream example:
+//   // Write some data to "myfile".  First we write a 4-byte "magic number"
+//   // to identify the file type, then write a length-delimited string.  The
+//   // string is composed of a varint giving the length followed by the raw
+//   // bytes.
+//   int fd = open("myfile", O_CREAT | O_WRONLY);
+//   ZeroCopyOutputStream* raw_output = new FileOutputStream(fd);
+//   CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
+//
+//   int magic_number = 1234;
+//   char text[] = "Hello world!";
+//   coded_output->WriteLittleEndian32(magic_number);
+//   coded_output->WriteVarint32(strlen(text));
+//   coded_output->WriteRaw(text, strlen(text));
+//
+//   delete coded_output;
+//   delete raw_output;
+//   close(fd);
+//
+// CodedInputStream example:
+//   // Read a file created by the above code.
+//   int fd = open("myfile", O_RDONLY);
+//   ZeroCopyInputStream* raw_input = new FileInputStream(fd);
+//   CodedInputStream coded_input = new CodedInputStream(raw_input);
+//
+//   coded_input->ReadLittleEndian32(&magic_number);
+//   if (magic_number != 1234) {
+//     cerr << "File not in expected format." << endl;
+//     return;
+//   }
+//
+//   uint32 size;
+//   coded_input->ReadVarint32(&size);
+//
+//   char* text = new char[size + 1];
+//   coded_input->ReadRaw(buffer, size);
+//   text[size] = '\0';
+//
+//   delete coded_input;
+//   delete raw_input;
+//   close(fd);
+//
+//   cout << "Text is: " << text << endl;
+//   delete [] text;
+//
+// For those who are interested, varint encoding is defined as follows:
+//
+// The encoding operates on unsigned integers of up to 64 bits in length.
+// Each byte of the encoded value has the format:
+// * bits 0-6: Seven bits of the number being encoded.
+// * bit 7: Zero if this is the last byte in the encoding (in which
+//   case all remaining bits of the number are zero) or 1 if
+//   more bytes follow.
+// The first byte contains the least-significant 7 bits of the number, the
+// second byte (if present) contains the next-least-significant 7 bits,
+// and so on.  So, the binary number 1011000101011 would be encoded in two
+// bytes as "10101011 00101100".
+//
+// In theory, varint could be used to encode integers of any length.
+// However, for practicality we set a limit at 64 bits.  The maximum encoded
+// length of a number is thus 10 bytes.
+
+#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
+#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
+
+#include <assert.h>
+#include <string>
+#include <utility>
+#ifdef _MSC_VER
+  // Assuming windows is always little-endian.
+  #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+    #define PROTOBUF_LITTLE_ENDIAN 1
+  #endif
+  #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+    // If MSVC has "/RTCc" set, it will complain about truncating casts at
+    // runtime.  This file contains some intentional truncating casts.
+    #pragma runtime_checks("c", off)
+  #endif
+#else
+  #include <sys/param.h>   // __BYTE_ORDER
+  #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
+         (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \
+      !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+    #define PROTOBUF_LITTLE_ENDIAN 1
+  #endif
+#endif
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+
+namespace protobuf {
+
+class DescriptorPool;
+class MessageFactory;
+
+namespace io {
+
+// Defined in this file.
+class CodedInputStream;
+class CodedOutputStream;
+
+// Defined in other files.
+class ZeroCopyInputStream;           // zero_copy_stream.h
+class ZeroCopyOutputStream;          // zero_copy_stream.h
+
+// Class which reads and decodes binary data which is composed of varint-
+// encoded integers and fixed-width pieces.  Wraps a ZeroCopyInputStream.
+// Most users will not need to deal with CodedInputStream.
+//
+// Most methods of CodedInputStream that return a bool return false if an
+// underlying I/O error occurs or if the data is malformed.  Once such a
+// failure occurs, the CodedInputStream is broken and is no longer useful.
+class LIBPROTOBUF_EXPORT CodedInputStream {
+ public:
+  // Create a CodedInputStream that reads from the given ZeroCopyInputStream.
+  explicit CodedInputStream(ZeroCopyInputStream* input);
+
+  // Create a CodedInputStream that reads from the given flat array.  This is
+  // faster than using an ArrayInputStream.  PushLimit(size) is implied by
+  // this constructor.
+  explicit CodedInputStream(const uint8* buffer, int size);
+
+  // Destroy the CodedInputStream and position the underlying
+  // ZeroCopyInputStream at the first unread byte.  If an error occurred while
+  // reading (causing a method to return false), then the exact position of
+  // the input stream may be anywhere between the last value that was read
+  // successfully and the stream's byte limit.
+  ~CodedInputStream();
+
+  // Return true if this CodedInputStream reads from a flat array instead of
+  // a ZeroCopyInputStream.
+  inline bool IsFlat() const;
+
+  // Skips a number of bytes.  Returns false if an underlying read error
+  // occurs.
+  bool Skip(int count);
+
+  // Sets *data to point directly at the unread part of the CodedInputStream's
+  // underlying buffer, and *size to the size of that buffer, but does not
+  // advance the stream's current position.  This will always either produce
+  // a non-empty buffer or return false.  If the caller consumes any of
+  // this data, it should then call Skip() to skip over the consumed bytes.
+  // This may be useful for implementing external fast parsing routines for
+  // types of data not covered by the CodedInputStream interface.
+  bool GetDirectBufferPointer(const void** data, int* size);
+
+  // Like GetDirectBufferPointer, but this method is inlined, and does not
+  // attempt to Refresh() if the buffer is currently empty.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void GetDirectBufferPointerInline(const void** data,
+                                                            int* size);
+
+  // Read raw bytes, copying them into the given buffer.
+  bool ReadRaw(void* buffer, int size);
+
+  // Like the above, with inlined optimizations. This should only be used
+  // by the protobuf implementation.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadRawInline(void* buffer, int size);
+
+  // Like ReadRaw, but reads into a string.
+  //
+  // Implementation Note:  ReadString() grows the string gradually as it
+  // reads in the data, rather than allocating the entire requested size
+  // upfront.  This prevents denial-of-service attacks in which a client
+  // could claim that a string is going to be MAX_INT bytes long in order to
+  // crash the server because it can't allocate this much space at once.
+  bool ReadString(string* buffer, int size);
+  // Like the above, with inlined optimizations. This should only be used
+  // by the protobuf implementation.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadStringInline(string* buffer,
+                                                        int size);
+
+
+  // Read a 32-bit little-endian integer.
+  bool ReadLittleEndian32(uint32* value);
+  // Read a 64-bit little-endian integer.
+  bool ReadLittleEndian64(uint64* value);
+
+  // These methods read from an externally provided buffer. The caller is
+  // responsible for ensuring that the buffer has sufficient space.
+  // Read a 32-bit little-endian integer.
+  static const uint8* ReadLittleEndian32FromArray(const uint8* buffer,
+                                                   uint32* value);
+  // Read a 64-bit little-endian integer.
+  static const uint8* ReadLittleEndian64FromArray(const uint8* buffer,
+                                                   uint64* value);
+
+  // Read an unsigned integer with Varint encoding, truncating to 32 bits.
+  // Reading a 32-bit value is equivalent to reading a 64-bit one and casting
+  // it to uint32, but may be more efficient.
+  bool ReadVarint32(uint32* value);
+  // Read an unsigned integer with Varint encoding.
+  bool ReadVarint64(uint64* value);
+
+  // Read a tag.  This calls ReadVarint32() and returns the result, or returns
+  // zero (which is not a valid tag) if ReadVarint32() fails.  Also, it updates
+  // the last tag value, which can be checked with LastTagWas().
+  // Always inline because this is only called in one place per parse loop
+  // but it is called for every iteration of said loop, so it should be fast.
+  // GCC doesn't want to inline this by default.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag();
+
+  // This usually a faster alternative to ReadTag() when cutoff is a manifest
+  // constant.  It does particularly well for cutoff >= 127.  The first part
+  // of the return value is the tag that was read, though it can also be 0 in
+  // the cases where ReadTag() would return 0.  If the second part is true
+  // then the tag is known to be in [0, cutoff].  If not, the tag either is
+  // above cutoff or is 0.  (There's intentional wiggle room when tag is 0,
+  // because that can arise in several ways, and for best performance we want
+  // to avoid an extra "is tag == 0?" check here.)
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> ReadTagWithCutoff(
+      uint32 cutoff);
+
+  // Usually returns true if calling ReadVarint32() now would produce the given
+  // value.  Will always return false if ReadVarint32() would not return the
+  // given value.  If ExpectTag() returns true, it also advances past
+  // the varint.  For best performance, use a compile-time constant as the
+  // parameter.
+  // Always inline because this collapses to a small number of instructions
+  // when given a constant parameter, but GCC doesn't want to inline by default.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool ExpectTag(uint32 expected);
+
+  // Like above, except this reads from the specified buffer. The caller is
+  // responsible for ensuring that the buffer is large enough to read a varint
+  // of the expected size. For best performance, use a compile-time constant as
+  // the expected tag parameter.
+  //
+  // Returns a pointer beyond the expected tag if it was found, or NULL if it
+  // was not.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static const uint8* ExpectTagFromArray(
+      const uint8* buffer,
+      uint32 expected);
+
+  // Usually returns true if no more bytes can be read.  Always returns false
+  // if more bytes can be read.  If ExpectAtEnd() returns true, a subsequent
+  // call to LastTagWas() will act as if ReadTag() had been called and returned
+  // zero, and ConsumedEntireMessage() will return true.
+  bool ExpectAtEnd();
+
+  // If the last call to ReadTag() or ReadTagWithCutoff() returned the
+  // given value, returns true.  Otherwise, returns false;
+  //
+  // This is needed because parsers for some types of embedded messages
+  // (with field type TYPE_GROUP) don't actually know that they've reached the
+  // end of a message until they see an ENDGROUP tag, which was actually part
+  // of the enclosing message.  The enclosing message would like to check that
+  // tag to make sure it had the right number, so it calls LastTagWas() on
+  // return from the embedded parser to check.
+  bool LastTagWas(uint32 expected);
+
+  // When parsing message (but NOT a group), this method must be called
+  // immediately after MergeFromCodedStream() returns (if it returns true)
+  // to further verify that the message ended in a legitimate way.  For
+  // example, this verifies that parsing did not end on an end-group tag.
+  // It also checks for some cases where, due to optimizations,
+  // MergeFromCodedStream() can incorrectly return true.
+  bool ConsumedEntireMessage();
+
+  // Limits ----------------------------------------------------------
+  // Limits are used when parsing length-delimited embedded messages.
+  // After the message's length is read, PushLimit() is used to prevent
+  // the CodedInputStream from reading beyond that length.  Once the
+  // embedded message has been parsed, PopLimit() is called to undo the
+  // limit.
+
+  // Opaque type used with PushLimit() and PopLimit().  Do not modify
+  // values of this type yourself.  The only reason that this isn't a
+  // struct with private internals is for efficiency.
+  typedef int Limit;
+
+  // Places a limit on the number of bytes that the stream may read,
+  // starting from the current position.  Once the stream hits this limit,
+  // it will act like the end of the input has been reached until PopLimit()
+  // is called.
+  //
+  // As the names imply, the stream conceptually has a stack of limits.  The
+  // shortest limit on the stack is always enforced, even if it is not the
+  // top limit.
+  //
+  // The value returned by PushLimit() is opaque to the caller, and must
+  // be passed unchanged to the corresponding call to PopLimit().
+  Limit PushLimit(int byte_limit);
+
+  // Pops the last limit pushed by PushLimit().  The input must be the value
+  // returned by that call to PushLimit().
+  void PopLimit(Limit limit);
+
+  // Returns the number of bytes left until the nearest limit on the
+  // stack is hit, or -1 if no limits are in place.
+  int BytesUntilLimit() const;
+
+  // Returns current position relative to the beginning of the input stream.
+  int CurrentPosition() const;
+
+  // Total Bytes Limit -----------------------------------------------
+  // To prevent malicious users from sending excessively large messages
+  // and causing integer overflows or memory exhaustion, CodedInputStream
+  // imposes a hard limit on the total number of bytes it will read.
+
+  // Sets the maximum number of bytes that this CodedInputStream will read
+  // before refusing to continue.  To prevent integer overflows in the
+  // protocol buffers implementation, as well as to prevent servers from
+  // allocating enormous amounts of memory to hold parsed messages, the
+  // maximum message length should be limited to the shortest length that
+  // will not harm usability.  The theoretical shortest message that could
+  // cause integer overflows is 512MB.  The default limit is 64MB.  Apps
+  // should set shorter limits if possible.  If warning_threshold is not -1,
+  // a warning will be printed to stderr after warning_threshold bytes are
+  // read.  For backwards compatibility all negative values get squashed to -1,
+  // as other negative values might have special internal meanings.
+  // An error will always be printed to stderr if the limit is reached.
+  //
+  // This is unrelated to PushLimit()/PopLimit().
+  //
+  // Hint:  If you are reading this because your program is printing a
+  //   warning about dangerously large protocol messages, you may be
+  //   confused about what to do next.  The best option is to change your
+  //   design such that excessively large messages are not necessary.
+  //   For example, try to design file formats to consist of many small
+  //   messages rather than a single large one.  If this is infeasible,
+  //   you will need to increase the limit.  Chances are, though, that
+  //   your code never constructs a CodedInputStream on which the limit
+  //   can be set.  You probably parse messages by calling things like
+  //   Message::ParseFromString().  In this case, you will need to change
+  //   your code to instead construct some sort of ZeroCopyInputStream
+  //   (e.g. an ArrayInputStream), construct a CodedInputStream around
+  //   that, then call Message::ParseFromCodedStream() instead.  Then
+  //   you can adjust the limit.  Yes, it's more work, but you're doing
+  //   something unusual.
+  void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold);
+
+  // The Total Bytes Limit minus the Current Position, or -1 if there
+  // is no Total Bytes Limit.
+  int BytesUntilTotalBytesLimit() const;
+
+  // Recursion Limit -------------------------------------------------
+  // To prevent corrupt or malicious messages from causing stack overflows,
+  // we must keep track of the depth of recursion when parsing embedded
+  // messages and groups.  CodedInputStream keeps track of this because it
+  // is the only object that is passed down the stack during parsing.
+
+  // Sets the maximum recursion depth.  The default is 100.
+  void SetRecursionLimit(int limit);
+
+
+  // Increments the current recursion depth.  Returns true if the depth is
+  // under the limit, false if it has gone over.
+  bool IncrementRecursionDepth();
+
+  // Decrements the recursion depth if possible.
+  void DecrementRecursionDepth();
+
+  // Decrements the recursion depth blindly.  This is faster than
+  // DecrementRecursionDepth().  It should be used only if all previous
+  // increments to recursion depth were successful.
+  void UnsafeDecrementRecursionDepth();
+
+  // Shorthand for make_pair(PushLimit(byte_limit), --recursion_budget_).
+  // Using this can reduce code size and complexity in some cases.  The caller
+  // is expected to check that the second part of the result is non-negative (to
+  // bail out if the depth of recursion is too high) and, if all is well, to
+  // later pass the first part of the result to PopLimit() or similar.
+  std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit(
+      int byte_limit);
+
+  // Shorthand for PushLimit(ReadVarint32(&length) ? length : 0).
+  Limit ReadLengthAndPushLimit();
+
+  // Helper that is equivalent to: {
+  //  bool result = ConsumedEntireMessage();
+  //  PopLimit(limit);
+  //  UnsafeDecrementRecursionDepth();
+  //  return result; }
+  // Using this can reduce code size and complexity in some cases.
+  // Do not use unless the current recursion depth is greater than zero.
+  bool DecrementRecursionDepthAndPopLimit(Limit limit);
+
+  // Helper that is equivalent to: {
+  //  bool result = ConsumedEntireMessage();
+  //  PopLimit(limit);
+  //  return result; }
+  // Using this can reduce code size and complexity in some cases.
+  bool CheckEntireMessageConsumedAndPopLimit(Limit limit);
+
+  // Extension Registry ----------------------------------------------
+  // ADVANCED USAGE:  99.9% of people can ignore this section.
+  //
+  // By default, when parsing extensions, the parser looks for extension
+  // definitions in the pool which owns the outer message's Descriptor.
+  // However, you may call SetExtensionRegistry() to provide an alternative
+  // pool instead.  This makes it possible, for example, to parse a message
+  // using a generated class, but represent some extensions using
+  // DynamicMessage.
+
+  // Set the pool used to look up extensions.  Most users do not need to call
+  // this as the correct pool will be chosen automatically.
+  //
+  // WARNING:  It is very easy to misuse this.  Carefully read the requirements
+  //   below.  Do not use this unless you are sure you need it.  Almost no one
+  //   does.
+  //
+  // Let's say you are parsing a message into message object m, and you want
+  // to take advantage of SetExtensionRegistry().  You must follow these
+  // requirements:
+  //
+  // The given DescriptorPool must contain m->GetDescriptor().  It is not
+  // sufficient for it to simply contain a descriptor that has the same name
+  // and content -- it must be the *exact object*.  In other words:
+  //   assert(pool->FindMessageTypeByName(m->GetDescriptor()->full_name()) ==
+  //          m->GetDescriptor());
+  // There are two ways to satisfy this requirement:
+  // 1) Use m->GetDescriptor()->pool() as the pool.  This is generally useless
+  //    because this is the pool that would be used anyway if you didn't call
+  //    SetExtensionRegistry() at all.
+  // 2) Use a DescriptorPool which has m->GetDescriptor()->pool() as an
+  //    "underlay".  Read the documentation for DescriptorPool for more
+  //    information about underlays.
+  //
+  // You must also provide a MessageFactory.  This factory will be used to
+  // construct Message objects representing extensions.  The factory's
+  // GetPrototype() MUST return non-NULL for any Descriptor which can be found
+  // through the provided pool.
+  //
+  // If the provided factory might return instances of protocol-compiler-
+  // generated (i.e. compiled-in) types, or if the outer message object m is
+  // a generated type, then the given factory MUST have this property:  If
+  // GetPrototype() is given a Descriptor which resides in
+  // DescriptorPool::generated_pool(), the factory MUST return the same
+  // prototype which MessageFactory::generated_factory() would return.  That
+  // is, given a descriptor for a generated type, the factory must return an
+  // instance of the generated class (NOT DynamicMessage).  However, when
+  // given a descriptor for a type that is NOT in generated_pool, the factory
+  // is free to return any implementation.
+  //
+  // The reason for this requirement is that generated sub-objects may be
+  // accessed via the standard (non-reflection) extension accessor methods,
+  // and these methods will down-cast the object to the generated class type.
+  // If the object is not actually of that type, the results would be undefined.
+  // On the other hand, if an extension is not compiled in, then there is no
+  // way the code could end up accessing it via the standard accessors -- the
+  // only way to access the extension is via reflection.  When using reflection,
+  // DynamicMessage and generated messages are indistinguishable, so it's fine
+  // if these objects are represented using DynamicMessage.
+  //
+  // Using DynamicMessageFactory on which you have called
+  // SetDelegateToGeneratedFactory(true) should be sufficient to satisfy the
+  // above requirement.
+  //
+  // If either pool or factory is NULL, both must be NULL.
+  //
+  // Note that this feature is ignored when parsing "lite" messages as they do
+  // not have descriptors.
+  void SetExtensionRegistry(const DescriptorPool* pool,
+                            MessageFactory* factory);
+
+  // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool
+  // has been provided.
+  const DescriptorPool* GetExtensionPool();
+
+  // Get the MessageFactory set via SetExtensionRegistry(), or NULL if no
+  // factory has been provided.
+  MessageFactory* GetExtensionFactory();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
+
+  const uint8* buffer_;
+  const uint8* buffer_end_;     // pointer to the end of the buffer.
+  ZeroCopyInputStream* input_;
+  int total_bytes_read_;  // total bytes read from input_, including
+                          // the current buffer
+
+  // If total_bytes_read_ surpasses INT_MAX, we record the extra bytes here
+  // so that we can BackUp() on destruction.
+  int overflow_bytes_;
+
+  // LastTagWas() stuff.
+  uint32 last_tag_;         // result of last ReadTag() or ReadTagWithCutoff().
+
+  // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly
+  // at EOF, or by ExpectAtEnd() when it returns true.  This happens when we
+  // reach the end of a message and attempt to read another tag.
+  bool legitimate_message_end_;
+
+  // See EnableAliasing().
+  bool aliasing_enabled_;
+
+  // Limits
+  Limit current_limit_;   // if position = -1, no limit is applied
+
+  // For simplicity, if the current buffer crosses a limit (either a normal
+  // limit created by PushLimit() or the total bytes limit), buffer_size_
+  // only tracks the number of bytes before that limit.  This field
+  // contains the number of bytes after it.  Note that this implies that if
+  // buffer_size_ == 0 and buffer_size_after_limit_ > 0, we know we've
+  // hit a limit.  However, if both are zero, it doesn't necessarily mean
+  // we aren't at a limit -- the buffer may have ended exactly at the limit.
+  int buffer_size_after_limit_;
+
+  // Maximum number of bytes to read, period.  This is unrelated to
+  // current_limit_.  Set using SetTotalBytesLimit().
+  int total_bytes_limit_;
+
+  // If positive/0: Limit for bytes read after which a warning due to size
+  // should be logged.
+  // If -1: Printing of warning disabled. Can be set by client.
+  // If -2: Internal: Limit has been reached, print full size when destructing.
+  int total_bytes_warning_threshold_;
+
+  // Current recursion budget, controlled by IncrementRecursionDepth() and
+  // similar.  Starts at recursion_limit_ and goes down: if this reaches
+  // -1 we are over budget.
+  int recursion_budget_;
+  // Recursion depth limit, set by SetRecursionLimit().
+  int recursion_limit_;
+
+  // See SetExtensionRegistry().
+  const DescriptorPool* extension_pool_;
+  MessageFactory* extension_factory_;
+
+  // Private member functions.
+
+  // Advance the buffer by a given number of bytes.
+  void Advance(int amount);
+
+  // Back up input_ to the current buffer position.
+  void BackUpInputToCurrentPosition();
+
+  // Recomputes the value of buffer_size_after_limit_.  Must be called after
+  // current_limit_ or total_bytes_limit_ changes.
+  void RecomputeBufferLimits();
+
+  // Writes an error message saying that we hit total_bytes_limit_.
+  void PrintTotalBytesLimitError();
+
+  // Called when the buffer runs out to request more data.  Implies an
+  // Advance(BufferSize()).
+  bool Refresh();
+
+  // When parsing varints, we optimize for the common case of small values, and
+  // then optimize for the case when the varint fits within the current buffer
+  // piece. The Fallback method is used when we can't use the one-byte
+  // optimization. The Slow method is yet another fallback when the buffer is
+  // not large enough. Making the slow path out-of-line speeds up the common
+  // case by 10-15%. The slow path is fairly uncommon: it only triggers when a
+  // message crosses multiple buffers.  Note: ReadVarint32Fallback() and
+  // ReadVarint64Fallback() are called frequently and generally not inlined, so
+  // they have been optimized to avoid "out" parameters.  The former returns -1
+  // if it fails and the uint32 it read otherwise.  The latter has a bool
+  // indicating success or failure as part of its return type.
+  int64 ReadVarint32Fallback(uint32 first_byte_or_zero);
+  std::pair<uint64, bool> ReadVarint64Fallback();
+  bool ReadVarint32Slow(uint32* value);
+  bool ReadVarint64Slow(uint64* value);
+  bool ReadLittleEndian32Fallback(uint32* value);
+  bool ReadLittleEndian64Fallback(uint64* value);
+  // Fallback/slow methods for reading tags. These do not update last_tag_,
+  // but will set legitimate_message_end_ if we are at the end of the input
+  // stream.
+  uint32 ReadTagFallback(uint32 first_byte_or_zero);
+  uint32 ReadTagSlow();
+  bool ReadStringFallback(string* buffer, int size);
+
+  // Return the size of the buffer.
+  int BufferSize() const;
+
+  static const int kDefaultTotalBytesLimit = 64 << 20;  // 64MB
+
+  static const int kDefaultTotalBytesWarningThreshold = 32 << 20;  // 32MB
+
+  static int default_recursion_limit_;  // 100 by default.
+};
+
+// Class which encodes and writes binary data which is composed of varint-
+// encoded integers and fixed-width pieces.  Wraps a ZeroCopyOutputStream.
+// Most users will not need to deal with CodedOutputStream.
+//
+// Most methods of CodedOutputStream which return a bool return false if an
+// underlying I/O error occurs.  Once such a failure occurs, the
+// CodedOutputStream is broken and is no longer useful. The Write* methods do
+// not return the stream status, but will invalidate the stream if an error
+// occurs. The client can probe HadError() to determine the status.
+//
+// Note that every method of CodedOutputStream which writes some data has
+// a corresponding static "ToArray" version. These versions write directly
+// to the provided buffer, returning a pointer past the last written byte.
+// They require that the buffer has sufficient capacity for the encoded data.
+// This allows an optimization where we check if an output stream has enough
+// space for an entire message before we start writing and, if there is, we
+// call only the ToArray methods to avoid doing bound checks for each
+// individual value.
+// i.e., in the example above:
+//
+//   CodedOutputStream coded_output = new CodedOutputStream(raw_output);
+//   int magic_number = 1234;
+//   char text[] = "Hello world!";
+//
+//   int coded_size = sizeof(magic_number) +
+//                    CodedOutputStream::VarintSize32(strlen(text)) +
+//                    strlen(text);
+//
+//   uint8* buffer =
+//       coded_output->GetDirectBufferForNBytesAndAdvance(coded_size);
+//   if (buffer != NULL) {
+//     // The output stream has enough space in the buffer: write directly to
+//     // the array.
+//     buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number,
+//                                                            buffer);
+//     buffer = CodedOutputStream::WriteVarint32ToArray(strlen(text), buffer);
+//     buffer = CodedOutputStream::WriteRawToArray(text, strlen(text), buffer);
+//   } else {
+//     // Make bound-checked writes, which will ask the underlying stream for
+//     // more space as needed.
+//     coded_output->WriteLittleEndian32(magic_number);
+//     coded_output->WriteVarint32(strlen(text));
+//     coded_output->WriteRaw(text, strlen(text));
+//   }
+//
+//   delete coded_output;
+class LIBPROTOBUF_EXPORT CodedOutputStream {
+ public:
+  // Create an CodedOutputStream that writes to the given ZeroCopyOutputStream.
+  explicit CodedOutputStream(ZeroCopyOutputStream* output);
+  CodedOutputStream(ZeroCopyOutputStream* output, bool do_eager_refresh);
+
+  // Destroy the CodedOutputStream and position the underlying
+  // ZeroCopyOutputStream immediately after the last byte written.
+  ~CodedOutputStream();
+
+  // Trims any unused space in the underlying buffer so that its size matches
+  // the number of bytes written by this stream. The underlying buffer will
+  // automatically be trimmed when this stream is destroyed; this call is only
+  // necessary if the underlying buffer is accessed *before* the stream is
+  // destroyed.
+  void Trim();
+
+  // Skips a number of bytes, leaving the bytes unmodified in the underlying
+  // buffer.  Returns false if an underlying write error occurs.  This is
+  // mainly useful with GetDirectBufferPointer().
+  bool Skip(int count);
+
+  // Sets *data to point directly at the unwritten part of the
+  // CodedOutputStream's underlying buffer, and *size to the size of that
+  // buffer, but does not advance the stream's current position.  This will
+  // always either produce a non-empty buffer or return false.  If the caller
+  // writes any data to this buffer, it should then call Skip() to skip over
+  // the consumed bytes.  This may be useful for implementing external fast
+  // serialization routines for types of data not covered by the
+  // CodedOutputStream interface.
+  bool GetDirectBufferPointer(void** data, int* size);
+
+  // If there are at least "size" bytes available in the current buffer,
+  // returns a pointer directly into the buffer and advances over these bytes.
+  // The caller may then write directly into this buffer (e.g. using the
+  // *ToArray static methods) rather than go through CodedOutputStream.  If
+  // there are not enough bytes available, returns NULL.  The return pointer is
+  // invalidated as soon as any other non-const method of CodedOutputStream
+  // is called.
+  inline uint8* GetDirectBufferForNBytesAndAdvance(int size);
+
+  // Write raw bytes, copying them from the given buffer.
+  void WriteRaw(const void* buffer, int size);
+  // Like WriteRaw()  but will try to write aliased data if aliasing is
+  // turned on.
+  void WriteRawMaybeAliased(const void* data, int size);
+  // Like WriteRaw()  but writing directly to the target array.
+  // This is _not_ inlined, as the compiler often optimizes memcpy into inline
+  // copy loops. Since this gets called by every field with string or bytes
+  // type, inlining may lead to a significant amount of code bloat, with only a
+  // minor performance gain.
+  static uint8* WriteRawToArray(const void* buffer, int size, uint8* target);
+
+  // Equivalent to WriteRaw(str.data(), str.size()).
+  void WriteString(const string& str);
+  // Like WriteString()  but writing directly to the target array.
+  static uint8* WriteStringToArray(const string& str, uint8* target);
+  // Write the varint-encoded size of str followed by str.
+  static uint8* WriteStringWithSizeToArray(const string& str, uint8* target);
+
+
+  // Instructs the CodedOutputStream to allow the underlying
+  // ZeroCopyOutputStream to hold pointers to the original structure instead of
+  // copying, if it supports it (i.e. output->AllowsAliasing() is true).  If the
+  // underlying stream does not support aliasing, then enabling it has no
+  // affect.  For now, this only affects the behavior of
+  // WriteRawMaybeAliased().
+  //
+  // NOTE: It is caller's responsibility to ensure that the chunk of memory
+  // remains live until all of the data has been consumed from the stream.
+  void EnableAliasing(bool enabled);
+
+  // Write a 32-bit little-endian integer.
+  void WriteLittleEndian32(uint32 value);
+  // Like WriteLittleEndian32()  but writing directly to the target array.
+  static uint8* WriteLittleEndian32ToArray(uint32 value, uint8* target);
+  // Write a 64-bit little-endian integer.
+  void WriteLittleEndian64(uint64 value);
+  // Like WriteLittleEndian64()  but writing directly to the target array.
+  static uint8* WriteLittleEndian64ToArray(uint64 value, uint8* target);
+
+  // Write an unsigned integer with Varint encoding.  Writing a 32-bit value
+  // is equivalent to casting it to uint64 and writing it as a 64-bit value,
+  // but may be more efficient.
+  void WriteVarint32(uint32 value);
+  // Like WriteVarint32()  but writing directly to the target array.
+  static uint8* WriteVarint32ToArray(uint32 value, uint8* target);
+  // Write an unsigned integer with Varint encoding.
+  void WriteVarint64(uint64 value);
+  // Like WriteVarint64()  but writing directly to the target array.
+  static uint8* WriteVarint64ToArray(uint64 value, uint8* target);
+
+  // Equivalent to WriteVarint32() except when the value is negative,
+  // in which case it must be sign-extended to a full 10 bytes.
+  void WriteVarint32SignExtended(int32 value);
+  // Like WriteVarint32SignExtended()  but writing directly to the target array.
+  static uint8* WriteVarint32SignExtendedToArray(int32 value, uint8* target);
+
+  // This is identical to WriteVarint32(), but optimized for writing tags.
+  // In particular, if the input is a compile-time constant, this method
+  // compiles down to a couple instructions.
+  // Always inline because otherwise the aformentioned optimization can't work,
+  // but GCC by default doesn't want to inline this.
+  void WriteTag(uint32 value);
+  // Like WriteTag()  but writing directly to the target array.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteTagToArray(uint32 value,
+                                                        uint8* target);
+
+  // Returns the number of bytes needed to encode the given value as a varint.
+  static int VarintSize32(uint32 value);
+  // Returns the number of bytes needed to encode the given value as a varint.
+  static int VarintSize64(uint64 value);
+
+  // If negative, 10 bytes.  Otheriwse, same as VarintSize32().
+  static int VarintSize32SignExtended(int32 value);
+
+  // Compile-time equivalent of VarintSize32().
+  template <uint32 Value>
+  struct StaticVarintSize32 {
+    static const int value =
+        (Value < (1 << 7))
+            ? 1
+            : (Value < (1 << 14))
+                ? 2
+                : (Value < (1 << 21))
+                    ? 3
+                    : (Value < (1 << 28))
+                        ? 4
+                        : 5;
+  };
+
+  // Returns the total number of bytes written since this object was created.
+  inline int ByteCount() const;
+
+  // Returns true if there was an underlying I/O error since this object was
+  // created.
+  bool HadError() const { return had_error_; }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
+
+  ZeroCopyOutputStream* output_;
+  uint8* buffer_;
+  int buffer_size_;
+  int total_bytes_;  // Sum of sizes of all buffers seen so far.
+  bool had_error_;   // Whether an error occurred during output.
+  bool aliasing_enabled_;  // See EnableAliasing().
+
+  // Advance the buffer by a given number of bytes.
+  void Advance(int amount);
+
+  // Called when the buffer runs out to request more data.  Implies an
+  // Advance(buffer_size_).
+  bool Refresh();
+
+  // Like WriteRaw() but may avoid copying if the underlying
+  // ZeroCopyOutputStream supports it.
+  void WriteAliasedRaw(const void* buffer, int size);
+
+  // If this write might cross the end of the buffer, we compose the bytes first
+  // then use WriteRaw().
+  void WriteVarint32SlowPath(uint32 value);
+
+  // Always-inlined versions of WriteVarint* functions so that code can be
+  // reused, while still controlling size. For instance, WriteVarint32ToArray()
+  // should not directly call this: since it is inlined itself, doing so
+  // would greatly increase the size of generated code. Instead, it should call
+  // WriteVarint32FallbackToArray.  Meanwhile, WriteVarint32() is already
+  // out-of-line, so it should just invoke this directly to avoid any extra
+  // function call overhead.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteVarint64ToArrayInline(
+      uint64 value, uint8* target);
+
+  static int VarintSize32Fallback(uint32 value);
+};
+
+// inline methods ====================================================
+// The vast majority of varints are only one byte.  These inline
+// methods optimize for that case.
+
+inline bool CodedInputStream::ReadVarint32(uint32* value) {
+  uint32 v = 0;
+  if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+    v = *buffer_;
+    if (v < 0x80) {
+      *value = v;
+      Advance(1);
+      return true;
+    }
+  }
+  int64 result = ReadVarint32Fallback(v);
+  *value = static_cast<uint32>(result);
+  return result >= 0;
+}
+
+inline bool CodedInputStream::ReadVarint64(uint64* value) {
+  if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
+    *value = *buffer_;
+    Advance(1);
+    return true;
+  }
+  std::pair<uint64, bool> p = ReadVarint64Fallback();
+  *value = p.first;
+  return p.second;
+}
+
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian32FromArray(
+    const uint8* buffer,
+    uint32* value) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  memcpy(value, buffer, sizeof(*value));
+  return buffer + sizeof(*value);
+#else
+  *value = (static_cast<uint32>(buffer[0])      ) |
+           (static_cast<uint32>(buffer[1]) <<  8) |
+           (static_cast<uint32>(buffer[2]) << 16) |
+           (static_cast<uint32>(buffer[3]) << 24);
+  return buffer + sizeof(*value);
+#endif
+}
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian64FromArray(
+    const uint8* buffer,
+    uint64* value) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  memcpy(value, buffer, sizeof(*value));
+  return buffer + sizeof(*value);
+#else
+  uint32 part0 = (static_cast<uint32>(buffer[0])      ) |
+                 (static_cast<uint32>(buffer[1]) <<  8) |
+                 (static_cast<uint32>(buffer[2]) << 16) |
+                 (static_cast<uint32>(buffer[3]) << 24);
+  uint32 part1 = (static_cast<uint32>(buffer[4])      ) |
+                 (static_cast<uint32>(buffer[5]) <<  8) |
+                 (static_cast<uint32>(buffer[6]) << 16) |
+                 (static_cast<uint32>(buffer[7]) << 24);
+  *value = static_cast<uint64>(part0) |
+          (static_cast<uint64>(part1) << 32);
+  return buffer + sizeof(*value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian32(uint32* value) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
+    memcpy(value, buffer_, sizeof(*value));
+    Advance(sizeof(*value));
+    return true;
+  } else {
+    return ReadLittleEndian32Fallback(value);
+  }
+#else
+  return ReadLittleEndian32Fallback(value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
+    memcpy(value, buffer_, sizeof(*value));
+    Advance(sizeof(*value));
+    return true;
+  } else {
+    return ReadLittleEndian64Fallback(value);
+  }
+#else
+  return ReadLittleEndian64Fallback(value);
+#endif
+}
+
+inline uint32 CodedInputStream::ReadTag() {
+  uint32 v = 0;
+  if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+    v = *buffer_;
+    if (v < 0x80) {
+      last_tag_ = v;
+      Advance(1);
+      return v;
+    }
+  }
+  last_tag_ = ReadTagFallback(v);
+  return last_tag_;
+}
+
+inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
+    uint32 cutoff) {
+  // In performance-sensitive code we can expect cutoff to be a compile-time
+  // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at
+  // compile time.
+  uint32 first_byte_or_zero = 0;
+  if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+    // Hot case: buffer_ non_empty, buffer_[0] in [1, 128).
+    // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields
+    // is large enough then is it better to check for the two-byte case first?
+    first_byte_or_zero = buffer_[0];
+    if (static_cast<int8>(buffer_[0]) > 0) {
+      const uint32 kMax1ByteVarint = 0x7f;
+      uint32 tag = last_tag_ = buffer_[0];
+      Advance(1);
+      return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
+    }
+    // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available,
+    // and tag is two bytes.  The latter is tested by bitwise-and-not of the
+    // first byte and the second byte.
+    if (cutoff >= 0x80 &&
+        GOOGLE_PREDICT_TRUE(buffer_ + 1 < buffer_end_) &&
+        GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) {
+      const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f;
+      uint32 tag = last_tag_ = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80);
+      Advance(2);
+      // It might make sense to test for tag == 0 now, but it is so rare that
+      // that we don't bother.  A varint-encoded 0 should be one byte unless
+      // the encoder lost its mind.  The second part of the return value of
+      // this function is allowed to be either true or false if the tag is 0,
+      // so we don't have to check for tag == 0.  We may need to check whether
+      // it exceeds cutoff.
+      bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff;
+      return std::make_pair(tag, at_or_below_cutoff);
+    }
+  }
+  // Slow path
+  last_tag_ = ReadTagFallback(first_byte_or_zero);
+  return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
+}
+
+inline bool CodedInputStream::LastTagWas(uint32 expected) {
+  return last_tag_ == expected;
+}
+
+inline bool CodedInputStream::ConsumedEntireMessage() {
+  return legitimate_message_end_;
+}
+
+inline bool CodedInputStream::ExpectTag(uint32 expected) {
+  if (expected < (1 << 7)) {
+    if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) {
+      Advance(1);
+      return true;
+    } else {
+      return false;
+    }
+  } else if (expected < (1 << 14)) {
+    if (GOOGLE_PREDICT_TRUE(BufferSize() >= 2) &&
+        buffer_[0] == static_cast<uint8>(expected | 0x80) &&
+        buffer_[1] == static_cast<uint8>(expected >> 7)) {
+      Advance(2);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    // Don't bother optimizing for larger values.
+    return false;
+  }
+}
+
+inline const uint8* CodedInputStream::ExpectTagFromArray(
+    const uint8* buffer, uint32 expected) {
+  if (expected < (1 << 7)) {
+    if (buffer[0] == expected) {
+      return buffer + 1;
+    }
+  } else if (expected < (1 << 14)) {
+    if (buffer[0] == static_cast<uint8>(expected | 0x80) &&
+        buffer[1] == static_cast<uint8>(expected >> 7)) {
+      return buffer + 2;
+    }
+  }
+  return NULL;
+}
+
+inline void CodedInputStream::GetDirectBufferPointerInline(const void** data,
+                                                           int* size) {
+  *data = buffer_;
+  *size = static_cast<int>(buffer_end_ - buffer_);
+}
+
+inline bool CodedInputStream::ExpectAtEnd() {
+  // If we are at a limit we know no more bytes can be read.  Otherwise, it's
+  // hard to say without calling Refresh(), and we'd rather not do that.
+
+  if (buffer_ == buffer_end_ &&
+      ((buffer_size_after_limit_ != 0) ||
+       (total_bytes_read_ == current_limit_))) {
+    last_tag_ = 0;                   // Pretend we called ReadTag()...
+    legitimate_message_end_ = true;  // ... and it hit EOF.
+    return true;
+  } else {
+    return false;
+  }
+}
+
+inline int CodedInputStream::CurrentPosition() const {
+  return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_);
+}
+
+inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
+  if (buffer_size_ < size) {
+    return NULL;
+  } else {
+    uint8* result = buffer_;
+    Advance(size);
+    return result;
+  }
+}
+
+inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value,
+                                                      uint8* target) {
+  while (value >= 0x80) {
+    *target = static_cast<uint8>(value | 0x80);
+    value >>= 7;
+    ++target;
+  }
+  *target = static_cast<uint8>(value);
+  return target + 1;
+}
+
+inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) {
+  if (value < 0) {
+    WriteVarint64(static_cast<uint64>(value));
+  } else {
+    WriteVarint32(static_cast<uint32>(value));
+  }
+}
+
+inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
+    int32 value, uint8* target) {
+  if (value < 0) {
+    return WriteVarint64ToArray(static_cast<uint64>(value), target);
+  } else {
+    return WriteVarint32ToArray(static_cast<uint32>(value), target);
+  }
+}
+
+inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
+                                                            uint8* target) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  memcpy(target, &value, sizeof(value));
+#else
+  target[0] = static_cast<uint8>(value);
+  target[1] = static_cast<uint8>(value >>  8);
+  target[2] = static_cast<uint8>(value >> 16);
+  target[3] = static_cast<uint8>(value >> 24);
+#endif
+  return target + sizeof(value);
+}
+
+inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
+                                                            uint8* target) {
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+  memcpy(target, &value, sizeof(value));
+#else
+  uint32 part0 = static_cast<uint32>(value);
+  uint32 part1 = static_cast<uint32>(value >> 32);
+
+  target[0] = static_cast<uint8>(part0);
+  target[1] = static_cast<uint8>(part0 >>  8);
+  target[2] = static_cast<uint8>(part0 >> 16);
+  target[3] = static_cast<uint8>(part0 >> 24);
+  target[4] = static_cast<uint8>(part1);
+  target[5] = static_cast<uint8>(part1 >>  8);
+  target[6] = static_cast<uint8>(part1 >> 16);
+  target[7] = static_cast<uint8>(part1 >> 24);
+#endif
+  return target + sizeof(value);
+}
+
+inline void CodedOutputStream::WriteVarint32(uint32 value) {
+  if (buffer_size_ >= 5) {
+    // Fast path:  We have enough bytes left in the buffer to guarantee that
+    // this write won't cross the end, so we can skip the checks.
+    uint8* target = buffer_;
+    uint8* end = WriteVarint32ToArray(value, target);
+    int size = static_cast<int>(end - target);
+    Advance(size);
+  } else {
+    WriteVarint32SlowPath(value);
+  }
+}
+
+inline void CodedOutputStream::WriteTag(uint32 value) {
+  WriteVarint32(value);
+}
+
+inline uint8* CodedOutputStream::WriteTagToArray(
+    uint32 value, uint8* target) {
+  return WriteVarint32ToArray(value, target);
+}
+
+inline int CodedOutputStream::VarintSize32(uint32 value) {
+  if (value < (1 << 7)) {
+    return 1;
+  } else  {
+    return VarintSize32Fallback(value);
+  }
+}
+
+inline int CodedOutputStream::VarintSize32SignExtended(int32 value) {
+  if (value < 0) {
+    return 10;     // TODO(kenton):  Make this a symbolic constant.
+  } else {
+    return VarintSize32(static_cast<uint32>(value));
+  }
+}
+
+inline void CodedOutputStream::WriteString(const string& str) {
+  WriteRaw(str.data(), static_cast<int>(str.size()));
+}
+
+inline void CodedOutputStream::WriteRawMaybeAliased(
+    const void* data, int size) {
+  if (aliasing_enabled_) {
+    WriteAliasedRaw(data, size);
+  } else {
+    WriteRaw(data, size);
+  }
+}
+
+inline uint8* CodedOutputStream::WriteStringToArray(
+    const string& str, uint8* target) {
+  return WriteRawToArray(str.data(), static_cast<int>(str.size()), target);
+}
+
+inline int CodedOutputStream::ByteCount() const {
+  return total_bytes_ - buffer_size_;
+}
+
+inline void CodedInputStream::Advance(int amount) {
+  buffer_ += amount;
+}
+
+inline void CodedOutputStream::Advance(int amount) {
+  buffer_ += amount;
+  buffer_size_ -= amount;
+}
+
+inline void CodedInputStream::SetRecursionLimit(int limit) {
+  recursion_budget_ += limit - recursion_limit_;
+  recursion_limit_ = limit;
+}
+
+inline bool CodedInputStream::IncrementRecursionDepth() {
+  --recursion_budget_;
+  return recursion_budget_ >= 0;
+}
+
+inline void CodedInputStream::DecrementRecursionDepth() {
+  if (recursion_budget_ < recursion_limit_) ++recursion_budget_;
+}
+
+inline void CodedInputStream::UnsafeDecrementRecursionDepth() {
+  assert(recursion_budget_ < recursion_limit_);
+  ++recursion_budget_;
+}
+
+inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
+                                                   MessageFactory* factory) {
+  extension_pool_ = pool;
+  extension_factory_ = factory;
+}
+
+inline const DescriptorPool* CodedInputStream::GetExtensionPool() {
+  return extension_pool_;
+}
+
+inline MessageFactory* CodedInputStream::GetExtensionFactory() {
+  return extension_factory_;
+}
+
+inline int CodedInputStream::BufferSize() const {
+  return static_cast<int>(buffer_end_ - buffer_);
+}
+
+inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
+  : buffer_(NULL),
+    buffer_end_(NULL),
+    input_(input),
+    total_bytes_read_(0),
+    overflow_bytes_(0),
+    last_tag_(0),
+    legitimate_message_end_(false),
+    aliasing_enabled_(false),
+    current_limit_(kint32max),
+    buffer_size_after_limit_(0),
+    total_bytes_limit_(kDefaultTotalBytesLimit),
+    total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+    recursion_budget_(default_recursion_limit_),
+    recursion_limit_(default_recursion_limit_),
+    extension_pool_(NULL),
+    extension_factory_(NULL) {
+  // Eagerly Refresh() so buffer space is immediately available.
+  Refresh();
+}
+
+inline CodedInputStream::CodedInputStream(const uint8* buffer, int size)
+  : buffer_(buffer),
+    buffer_end_(buffer + size),
+    input_(NULL),
+    total_bytes_read_(size),
+    overflow_bytes_(0),
+    last_tag_(0),
+    legitimate_message_end_(false),
+    aliasing_enabled_(false),
+    current_limit_(size),
+    buffer_size_after_limit_(0),
+    total_bytes_limit_(kDefaultTotalBytesLimit),
+    total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+    recursion_budget_(default_recursion_limit_),
+    recursion_limit_(default_recursion_limit_),
+    extension_pool_(NULL),
+    extension_factory_(NULL) {
+  // Note that setting current_limit_ == size is important to prevent some
+  // code paths from trying to access input_ and segfaulting.
+}
+
+inline bool CodedInputStream::IsFlat() const {
+  return input_ == NULL;
+}
+
+}  // namespace io
+}  // namespace protobuf
+
+
+#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+  #pragma runtime_checks("c", restore)
+#endif  // _MSC_VER && !defined(__INTEL_COMPILER)
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_inl.h b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_inl.h
new file mode 100644
index 0000000..d95b06e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_inl.h
@@ -0,0 +1,90 @@
+// 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.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// Implements methods of coded_stream.h that need to be inlined for performance
+// reasons, but should not be defined in a public header.
+
+#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <string>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+inline bool CodedInputStream::InternalReadStringInline(string* buffer,
+                                                       int size) {
+  if (size < 0) return false;  // security: size is often user-supplied
+
+  if (BufferSize() >= size) {
+    STLStringResizeUninitialized(buffer, size);
+    std::pair<char*, bool> z = as_string_data(buffer);
+    if (z.second) {
+      // Oddly enough, memcpy() requires its first two args to be non-NULL even
+      // if we copy 0 bytes.  So, we have ensured that z.first is non-NULL here.
+      GOOGLE_DCHECK(z.first != NULL);
+      memcpy(z.first, buffer_, size);
+      Advance(size);
+    }
+    return true;
+  }
+
+  return ReadStringFallback(buffer, size);
+}
+
+inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) {
+  int current_buffer_size;
+  while ((current_buffer_size = BufferSize()) < size) {
+    // Reading past end of buffer.  Copy what we have, then refresh.
+    memcpy(buffer, buffer_, current_buffer_size);
+    buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
+    size -= current_buffer_size;
+    Advance(current_buffer_size);
+    if (!Refresh()) return false;
+  }
+
+  memcpy(buffer, buffer_, size);
+  Advance(size);
+
+  return true;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_unittest.cc
new file mode 100644
index 0000000..a8108e4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/coded_stream_unittest.cc
@@ -0,0 +1,1385 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains tests and benchmarks.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/io/coded_stream.h>
+
+#include <limits.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+
+// This declares an unsigned long long integer literal in a portable way.
+// (The original macro is way too big and ruins my formatting.)
+#undef ULL
+#define ULL(x) GOOGLE_ULONGLONG(x)
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace {
+
+// ===================================================================
+// Data-Driven Test Infrastructure
+
+// TEST_1D and TEST_2D are macros I'd eventually like to see added to
+// gTest.  These macros can be used to declare tests which should be
+// run multiple times, once for each item in some input array.  TEST_1D
+// tests all cases in a single input array.  TEST_2D tests all
+// combinations of cases from two arrays.  The arrays must be statically
+// defined such that the GOOGLE_ARRAYSIZE() macro works on them.  Example:
+//
+// int kCases[] = {1, 2, 3, 4}
+// TEST_1D(MyFixture, MyTest, kCases) {
+//   EXPECT_GT(kCases_case, 0);
+// }
+//
+// This test iterates through the numbers 1, 2, 3, and 4 and tests that
+// they are all grater than zero.  In case of failure, the exact case
+// which failed will be printed.  The case type must be printable using
+// ostream::operator<<.
+
+// TODO(kenton):  gTest now supports "parameterized tests" which would be
+//   a better way to accomplish this.  Rewrite when time permits.
+
+#define TEST_1D(FIXTURE, NAME, CASES)                                      \
+  class FIXTURE##_##NAME##_DD : public FIXTURE {                           \
+   protected:                                                              \
+    template <typename CaseType>                                           \
+    void DoSingleCase(const CaseType& CASES##_case);                       \
+  };                                                                       \
+                                                                           \
+  TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                    \
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) {                           \
+      SCOPED_TRACE(testing::Message()                                      \
+        << #CASES " case #" << i << ": " << CASES[i]);                     \
+      DoSingleCase(CASES[i]);                                              \
+    }                                                                      \
+  }                                                                        \
+                                                                           \
+  template <typename CaseType>                                             \
+  void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case)
+
+#define TEST_2D(FIXTURE, NAME, CASES1, CASES2)                             \
+  class FIXTURE##_##NAME##_DD : public FIXTURE {                           \
+   protected:                                                              \
+    template <typename CaseType1, typename CaseType2>                      \
+    void DoSingleCase(const CaseType1& CASES1##_case,                      \
+                      const CaseType2& CASES2##_case);                     \
+  };                                                                       \
+                                                                           \
+  TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                    \
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) {                          \
+      for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) {                        \
+        SCOPED_TRACE(testing::Message()                                    \
+          << #CASES1 " case #" << i << ": " << CASES1[i] << ", "           \
+          << #CASES2 " case #" << j << ": " << CASES2[j]);                 \
+        DoSingleCase(CASES1[i], CASES2[j]);                                \
+      }                                                                    \
+    }                                                                      \
+  }                                                                        \
+                                                                           \
+  template <typename CaseType1, typename CaseType2>                        \
+  void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \
+                                           const CaseType2& CASES2##_case)
+
+// ===================================================================
+
+class CodedStreamTest : public testing::Test {
+ protected:
+  // Helper method used by tests for bytes warning. See implementation comment
+  // for further information.
+  static void SetupTotalBytesLimitWarningTest(
+      int total_bytes_limit, int warning_threshold,
+      vector<string>* out_errors, vector<string>* out_warnings);
+
+  // Buffer used during most of the tests. This assumes tests run sequentially.
+  static const int kBufferSize = 1024 * 64;
+  static uint8 buffer_[kBufferSize];
+};
+
+uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize];
+
+// We test each operation over a variety of block sizes to insure that
+// we test cases where reads or writes cross buffer boundaries, cases
+// where they don't, and cases where there is so much buffer left that
+// we can use special optimized paths that don't worry about bounds
+// checks.
+const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024};
+
+
+// -------------------------------------------------------------------
+// Varint tests.
+
+struct VarintCase {
+  uint8 bytes[10];          // Encoded bytes.
+  int size;                 // Encoded size, in bytes.
+  uint64 value;             // Parsed value.
+};
+
+inline std::ostream& operator<<(std::ostream& os, const VarintCase& c) {
+  return os << c.value;
+}
+
+VarintCase kVarintCases[] = {
+  // 32-bit values
+  {{0x00}      , 1, 0},
+  {{0x01}      , 1, 1},
+  {{0x7f}      , 1, 127},
+  {{0xa2, 0x74}, 2, (0x22 << 0) | (0x74 << 7)},          // 14882
+  {{0xbe, 0xf7, 0x92, 0x84, 0x0b}, 5,                    // 2961488830
+    (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+    (ULL(0x0b) << 28)},
+
+  // 64-bit
+  {{0xbe, 0xf7, 0x92, 0x84, 0x1b}, 5,                    // 7256456126
+    (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+    (ULL(0x1b) << 28)},
+  {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, 8,  // 41256202580718336
+    (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+    (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) |
+    (ULL(0x49) << 49)},
+  // 11964378330978735131
+  {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, 10,
+    (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+    (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) |
+    (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)},
+};
+
+TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) {
+  memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint32 value;
+    EXPECT_TRUE(coded_input.ReadVarint32(&value));
+    EXPECT_EQ(static_cast<uint32>(kVarintCases_case.value), value);
+  }
+
+  EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
+}
+
+TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) {
+  memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
+    EXPECT_EQ(expected_value, coded_input.ReadTag());
+
+    EXPECT_TRUE(coded_input.LastTagWas(expected_value));
+    EXPECT_FALSE(coded_input.LastTagWas(expected_value + 1));
+  }
+
+  EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
+}
+
+// This is the regression test that verifies that there is no issues
+// with the empty input buffers handling.
+TEST_F(CodedStreamTest, EmptyInputBeforeEos) {
+  class In : public ZeroCopyInputStream {
+   public:
+    In() : count_(0) {}
+   private:
+    virtual bool Next(const void** data, int* size) {
+      *data = NULL;
+      *size = 0;
+      return count_++ < 2;
+    }
+    virtual void BackUp(int count)  {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+    }
+    virtual bool Skip(int count) {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+      return false;
+    }
+    virtual int64 ByteCount() const { return 0; }
+    int count_;
+  } in;
+  CodedInputStream input(&in);
+  input.ReadTag();
+  EXPECT_TRUE(input.ConsumedEntireMessage());
+}
+
+TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
+  // Leave one byte at the beginning of the buffer so we can read it
+  // to force the first buffer to be loaded.
+  buffer_[0] = '\0';
+  memcpy(buffer_ + 1, kVarintCases_case.bytes, kVarintCases_case.size);
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+
+  {
+    CodedInputStream coded_input(&input);
+
+    // Read one byte to force coded_input.Refill() to be called.  Otherwise,
+    // ExpectTag() will return a false negative.
+    uint8 dummy;
+    coded_input.ReadRaw(&dummy, 1);
+    EXPECT_EQ((uint)'\0', (uint)dummy);
+
+    uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
+
+    // ExpectTag() produces false negatives for large values.
+    if (kVarintCases_case.size <= 2) {
+      EXPECT_FALSE(coded_input.ExpectTag(expected_value + 1));
+      EXPECT_TRUE(coded_input.ExpectTag(expected_value));
+    } else {
+      EXPECT_FALSE(coded_input.ExpectTag(expected_value));
+    }
+  }
+
+  if (kVarintCases_case.size <= 2) {
+    EXPECT_EQ(kVarintCases_case.size + 1, input.ByteCount());
+  } else {
+    EXPECT_EQ(1, input.ByteCount());
+  }
+}
+
+TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) {
+  memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+
+  const uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
+
+  // If the expectation succeeds, it should return a pointer past the tag.
+  if (kVarintCases_case.size <= 2) {
+    EXPECT_TRUE(NULL ==
+                CodedInputStream::ExpectTagFromArray(buffer_,
+                                                     expected_value + 1));
+    EXPECT_TRUE(buffer_ + kVarintCases_case.size ==
+                CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+  } else {
+    EXPECT_TRUE(NULL ==
+                CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+  }
+}
+
+TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) {
+  memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint64 value;
+    EXPECT_TRUE(coded_input.ReadVarint64(&value));
+    EXPECT_EQ(kVarintCases_case.value, value);
+  }
+
+  EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
+}
+
+TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) {
+  if (kVarintCases_case.value > ULL(0x00000000FFFFFFFF)) {
+    // Skip this test for the 64-bit values.
+    return;
+  }
+
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteVarint32(static_cast<uint32>(kVarintCases_case.value));
+    EXPECT_FALSE(coded_output.HadError());
+
+    EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
+  }
+
+  EXPECT_EQ(kVarintCases_case.size, output.ByteCount());
+  EXPECT_EQ(0,
+    memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size));
+}
+
+TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteVarint64(kVarintCases_case.value);
+    EXPECT_FALSE(coded_output.HadError());
+
+    EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
+  }
+
+  EXPECT_EQ(kVarintCases_case.size, output.ByteCount());
+  EXPECT_EQ(0,
+    memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size));
+}
+
+// This test causes gcc 3.3.5 (and earlier?) to give the cryptic error:
+//   "sorry, unimplemented: `method_call_expr' not supported by dump_expr"
+#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
+
+int32 kSignExtendedVarintCases[] = {
+  0, 1, -1, 1237894, -37895138
+};
+
+TEST_2D(CodedStreamTest, WriteVarint32SignExtended,
+        kSignExtendedVarintCases, kBlockSizes) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteVarint32SignExtended(kSignExtendedVarintCases_case);
+    EXPECT_FALSE(coded_output.HadError());
+
+    if (kSignExtendedVarintCases_case < 0) {
+      EXPECT_EQ(10, coded_output.ByteCount());
+    } else {
+      EXPECT_LE(coded_output.ByteCount(), 5);
+    }
+  }
+
+  if (kSignExtendedVarintCases_case < 0) {
+    EXPECT_EQ(10, output.ByteCount());
+  } else {
+    EXPECT_LE(output.ByteCount(), 5);
+  }
+
+  // Read value back in as a varint64 and insure it matches.
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint64 value;
+    EXPECT_TRUE(coded_input.ReadVarint64(&value));
+
+    EXPECT_EQ(kSignExtendedVarintCases_case, static_cast<int64>(value));
+  }
+
+  EXPECT_EQ(output.ByteCount(), input.ByteCount());
+}
+
+#endif
+
+
+// -------------------------------------------------------------------
+// Varint failure test.
+
+struct VarintErrorCase {
+  uint8 bytes[12];
+  int size;
+  bool can_parse;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) {
+  return os << "size " << c.size;
+}
+
+const VarintErrorCase kVarintErrorCases[] = {
+  // Control case.  (Insures that there isn't something else wrong that
+  // makes parsing always fail.)
+  {{0x00}, 1, true},
+
+  // No input data.
+  {{}, 0, false},
+
+  // Input ends unexpectedly.
+  {{0xf0, 0xab}, 2, false},
+
+  // Input ends unexpectedly after 32 bits.
+  {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false},
+
+  // Longer than 10 bytes.
+  {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
+   11, false},
+};
+
+TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) {
+  memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size);
+  ArrayInputStream input(buffer_, kVarintErrorCases_case.size,
+                         kBlockSizes_case);
+  CodedInputStream coded_input(&input);
+
+  uint32 value;
+  EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value));
+}
+
+TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) {
+  memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size);
+  ArrayInputStream input(buffer_, kVarintErrorCases_case.size,
+                         kBlockSizes_case);
+  CodedInputStream coded_input(&input);
+
+  uint64 value;
+  EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value));
+}
+
+// -------------------------------------------------------------------
+// VarintSize
+
+struct VarintSizeCase {
+  uint64 value;
+  int size;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) {
+  return os << c.value;
+}
+
+VarintSizeCase kVarintSizeCases[] = {
+  {0u, 1},
+  {1u, 1},
+  {127u, 1},
+  {128u, 2},
+  {758923u, 3},
+  {4000000000u, 5},
+  {ULL(41256202580718336), 8},
+  {ULL(11964378330978735131), 10},
+};
+
+TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) {
+  if (kVarintSizeCases_case.value > 0xffffffffu) {
+    // Skip 64-bit values.
+    return;
+  }
+
+  EXPECT_EQ(kVarintSizeCases_case.size,
+    CodedOutputStream::VarintSize32(
+      static_cast<uint32>(kVarintSizeCases_case.value)));
+}
+
+TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) {
+  EXPECT_EQ(kVarintSizeCases_case.size,
+    CodedOutputStream::VarintSize64(kVarintSizeCases_case.value));
+}
+
+// -------------------------------------------------------------------
+// Fixed-size int tests
+
+struct Fixed32Case {
+  uint8 bytes[sizeof(uint32)];          // Encoded bytes.
+  uint32 value;                         // Parsed value.
+};
+
+struct Fixed64Case {
+  uint8 bytes[sizeof(uint64)];          // Encoded bytes.
+  uint64 value;                         // Parsed value.
+};
+
+inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) {
+  return os << "0x" << std::hex << c.value << std::dec;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) {
+  return os << "0x" << std::hex << c.value << std::dec;
+}
+
+Fixed32Case kFixed32Cases[] = {
+  {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu},
+  {{0x12, 0x34, 0x56, 0x78}, 0x78563412u},
+};
+
+Fixed64Case kFixed64Cases[] = {
+  {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)},
+  {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)},
+};
+
+TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) {
+  memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint32 value;
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(kFixed32Cases_case.value, value);
+  }
+
+  EXPECT_EQ(sizeof(uint32), input.ByteCount());
+}
+
+TEST_2D(CodedStreamTest, ReadLittleEndian64, kFixed64Cases, kBlockSizes) {
+  memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    uint64 value;
+    EXPECT_TRUE(coded_input.ReadLittleEndian64(&value));
+    EXPECT_EQ(kFixed64Cases_case.value, value);
+  }
+
+  EXPECT_EQ(sizeof(uint64), input.ByteCount());
+}
+
+TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteLittleEndian32(kFixed32Cases_case.value);
+    EXPECT_FALSE(coded_output.HadError());
+
+    EXPECT_EQ(sizeof(uint32), coded_output.ByteCount());
+  }
+
+  EXPECT_EQ(sizeof(uint32), output.ByteCount());
+  EXPECT_EQ(0, memcmp(buffer_, kFixed32Cases_case.bytes, sizeof(uint32)));
+}
+
+TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteLittleEndian64(kFixed64Cases_case.value);
+    EXPECT_FALSE(coded_output.HadError());
+
+    EXPECT_EQ(sizeof(uint64), coded_output.ByteCount());
+  }
+
+  EXPECT_EQ(sizeof(uint64), output.ByteCount());
+  EXPECT_EQ(0, memcmp(buffer_, kFixed64Cases_case.bytes, sizeof(uint64)));
+}
+
+// Tests using the static methods to read fixed-size values from raw arrays.
+
+TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) {
+  memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
+
+  uint32 value;
+  const uint8* end = CodedInputStream::ReadLittleEndian32FromArray(
+      buffer_, &value);
+  EXPECT_EQ(kFixed32Cases_case.value, value);
+  EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
+TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) {
+  memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
+
+  uint64 value;
+  const uint8* end = CodedInputStream::ReadLittleEndian64FromArray(
+      buffer_, &value);
+  EXPECT_EQ(kFixed64Cases_case.value, value);
+  EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
+// -------------------------------------------------------------------
+// Raw reads and writes
+
+const char kRawBytes[] = "Some bytes which will be written and read raw.";
+
+TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+  char read_buffer[sizeof(kRawBytes)];
+
+  {
+    CodedInputStream coded_input(&input);
+
+    EXPECT_TRUE(coded_input.ReadRaw(read_buffer, sizeof(kRawBytes)));
+    EXPECT_EQ(0, memcmp(kRawBytes, read_buffer, sizeof(kRawBytes)));
+  }
+
+  EXPECT_EQ(sizeof(kRawBytes), input.ByteCount());
+}
+
+TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedOutputStream coded_output(&output);
+
+    coded_output.WriteRaw(kRawBytes, sizeof(kRawBytes));
+    EXPECT_FALSE(coded_output.HadError());
+
+    EXPECT_EQ(sizeof(kRawBytes), coded_output.ByteCount());
+  }
+
+  EXPECT_EQ(sizeof(kRawBytes), output.ByteCount());
+  EXPECT_EQ(0, memcmp(buffer_, kRawBytes, sizeof(kRawBytes)));
+}
+
+TEST_1D(CodedStreamTest, ReadString, kBlockSizes) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    EXPECT_EQ(kRawBytes, str);
+  }
+
+  EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
+}
+
+// Check to make sure ReadString doesn't crash on impossibly large strings.
+TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    string str;
+    // Try to read a gigabyte.
+    EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+  }
+}
+
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
+  // Same test as above, except directly use a buffer. This used to cause
+  // crashes while the above did not.
+  uint8 buffer[8];
+  CodedInputStream coded_input(buffer, 8);
+  string str;
+  EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
+  google::protobuf::scoped_array<uint8> buffer(new uint8[8]);
+  CodedInputStream coded_input(buffer.get(), 8);
+  string str;
+  EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
+TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes));
+    EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit());
+
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    EXPECT_EQ(sizeof(kRawBytes) - strlen(kRawBytes),
+              coded_input.BytesUntilTotalBytesLimit());
+    EXPECT_EQ(kRawBytes, str);
+    // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
+    EXPECT_GE(str.capacity(), strlen(kRawBytes));
+  }
+
+  EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
+}
+
+TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(sizeof(buffer_));
+
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    EXPECT_EQ(kRawBytes, str);
+    // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
+    EXPECT_GE(str.capacity(), strlen(kRawBytes));
+  }
+
+  EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
+}
+
+TEST_F(CodedStreamTest, ReadStringNoReservationIfLimitsNotSet) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    EXPECT_EQ(kRawBytes, str);
+    // Note: this check depends on string class implementation. It
+    // expects that string will allocate more than strlen(kRawBytes)
+    // if the content of kRawBytes is appended to string in small
+    // chunks.
+    // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
+    EXPECT_GE(str.capacity(), strlen(kRawBytes));
+  }
+
+  EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
+}
+
+TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsNegative) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(sizeof(buffer_));
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, -1));
+    // Note: this check depends on string class implementation. It
+    // expects that string will always allocate the same amount of
+    // memory for an empty string.
+    EXPECT_EQ(string().capacity(), str.capacity());
+  }
+}
+
+TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsLarge) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(sizeof(buffer_));
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+    EXPECT_GT(1 << 30, str.capacity());
+  }
+}
+
+TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheLimit) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(16);
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    // Note: this check depends on string class implementation. It
+    // expects that string will allocate less than strlen(kRawBytes)
+    // for an empty string.
+    EXPECT_GT(strlen(kRawBytes), str.capacity());
+  }
+}
+
+TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheTotalBytesLimit) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.SetTotalBytesLimit(16, 16);
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    // Note: this check depends on string class implementation. It
+    // expects that string will allocate less than strlen(kRawBytes)
+    // for an empty string.
+    EXPECT_GT(strlen(kRawBytes), str.capacity());
+  }
+}
+
+TEST_F(CodedStreamTest,
+       ReadStringNoReservationSizeIsOverTheClosestLimit_GlobalLimitIsCloser) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(sizeof(buffer_));
+    coded_input.SetTotalBytesLimit(16, 16);
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    // Note: this check depends on string class implementation. It
+    // expects that string will allocate less than strlen(kRawBytes)
+    // for an empty string.
+    EXPECT_GT(strlen(kRawBytes), str.capacity());
+  }
+}
+
+TEST_F(CodedStreamTest,
+       ReadStringNoReservationSizeIsOverTheClosestLimit_LocalLimitIsCloser) {
+  memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
+  // Buffer size in the input must be smaller than sizeof(kRawBytes),
+  // otherwise check against capacity will fail as ReadStringInline()
+  // will handle the reading and will reserve the memory as needed.
+  ArrayInputStream input(buffer_, sizeof(buffer_), 32);
+
+  {
+    CodedInputStream coded_input(&input);
+    coded_input.PushLimit(16);
+    coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_));
+    EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit());
+
+    string str;
+    EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
+    // Note: this check depends on string class implementation. It
+    // expects that string will allocate less than strlen(kRawBytes)
+    // for an empty string.
+    EXPECT_GT(strlen(kRawBytes), str.capacity());
+  }
+}
+
+
+// -------------------------------------------------------------------
+// Skip
+
+const char kSkipTestBytes[] =
+  "<Before skipping><To be skipped><After skipping>";
+
+TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) {
+  memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes));
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen("<Before skipping>")));
+    EXPECT_EQ("<Before skipping>", str);
+    EXPECT_TRUE(coded_input.Skip(strlen("<To be skipped>")));
+    EXPECT_TRUE(coded_input.ReadString(&str, strlen("<After skipping>")));
+    EXPECT_EQ("<After skipping>", str);
+  }
+
+  EXPECT_EQ(strlen(kSkipTestBytes), input.ByteCount());
+}
+
+// -------------------------------------------------------------------
+// GetDirectBufferPointer
+
+TEST_F(CodedStreamTest, GetDirectBufferPointerInput) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), 8);
+  CodedInputStream coded_input(&input);
+
+  const void* ptr;
+  int size;
+
+  EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Peeking again should return the same pointer.
+  EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Skip forward in the same buffer then peek again.
+  EXPECT_TRUE(coded_input.Skip(3));
+  EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_ + 3, ptr);
+  EXPECT_EQ(5, size);
+
+  // Skip to end of buffer and peek -- should get next buffer.
+  EXPECT_TRUE(coded_input.Skip(5));
+  EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_ + 8, ptr);
+  EXPECT_EQ(8, size);
+}
+
+TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), 8);
+  CodedInputStream coded_input(&input);
+
+  const void* ptr;
+  int size;
+
+  coded_input.GetDirectBufferPointerInline(&ptr, &size);
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Peeking again should return the same pointer.
+  coded_input.GetDirectBufferPointerInline(&ptr, &size);
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Skip forward in the same buffer then peek again.
+  EXPECT_TRUE(coded_input.Skip(3));
+  coded_input.GetDirectBufferPointerInline(&ptr, &size);
+  EXPECT_EQ(buffer_ + 3, ptr);
+  EXPECT_EQ(5, size);
+
+  // Skip to end of buffer and peek -- should return false and provide an empty
+  // buffer. It does not try to Refresh().
+  EXPECT_TRUE(coded_input.Skip(5));
+  coded_input.GetDirectBufferPointerInline(&ptr, &size);
+  EXPECT_EQ(buffer_ + 8, ptr);
+  EXPECT_EQ(0, size);
+}
+
+TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) {
+  ArrayOutputStream output(buffer_, sizeof(buffer_), 8);
+  CodedOutputStream coded_output(&output);
+
+  void* ptr;
+  int size;
+
+  EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Peeking again should return the same pointer.
+  EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_, ptr);
+  EXPECT_EQ(8, size);
+
+  // Skip forward in the same buffer then peek again.
+  EXPECT_TRUE(coded_output.Skip(3));
+  EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_ + 3, ptr);
+  EXPECT_EQ(5, size);
+
+  // Skip to end of buffer and peek -- should get next buffer.
+  EXPECT_TRUE(coded_output.Skip(5));
+  EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_ + 8, ptr);
+  EXPECT_EQ(8, size);
+
+  // Skip over multiple buffers.
+  EXPECT_TRUE(coded_output.Skip(22));
+  EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+  EXPECT_EQ(buffer_ + 30, ptr);
+  EXPECT_EQ(2, size);
+}
+
+// -------------------------------------------------------------------
+// Limits
+
+TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    CodedInputStream::Limit limit = coded_input.PushLimit(8);
+
+    // Read until we hit the limit.
+    uint32 value;
+    EXPECT_EQ(8, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(4, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+    EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+
+    coded_input.PopLimit(limit);
+
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+  }
+
+  EXPECT_EQ(12, input.ByteCount());
+}
+
+// Test what happens when we push two limits where the second (top) one is
+// shorter.
+TEST_1D(CodedStreamTest, SmallLimitOnTopOfBigLimit, kBlockSizes) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    CodedInputStream::Limit limit1 = coded_input.PushLimit(8);
+    EXPECT_EQ(8, coded_input.BytesUntilLimit());
+    CodedInputStream::Limit limit2 = coded_input.PushLimit(4);
+
+    uint32 value;
+
+    // Read until we hit limit2, the top and shortest limit.
+    EXPECT_EQ(4, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+    EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+
+    coded_input.PopLimit(limit2);
+
+    // Read until we hit limit1.
+    EXPECT_EQ(4, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+    EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+
+    coded_input.PopLimit(limit1);
+
+    // No more limits.
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+  }
+
+  EXPECT_EQ(12, input.ByteCount());
+}
+
+// Test what happens when we push two limits where the second (top) one is
+// longer.  In this case, the top limit is shortened to match the previous
+// limit.
+TEST_1D(CodedStreamTest, BigLimitOnTopOfSmallLimit, kBlockSizes) {
+  ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
+
+  {
+    CodedInputStream coded_input(&input);
+
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    CodedInputStream::Limit limit1 = coded_input.PushLimit(4);
+    EXPECT_EQ(4, coded_input.BytesUntilLimit());
+    CodedInputStream::Limit limit2 = coded_input.PushLimit(8);
+
+    uint32 value;
+
+    // Read until we hit limit2.  Except, wait!  limit1 is shorter, so
+    // we end up hitting that first, despite having 4 bytes to go on
+    // limit2.
+    EXPECT_EQ(4, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+    EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+
+    coded_input.PopLimit(limit2);
+
+    // OK, popped limit2, now limit1 is on top, which we've already hit.
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+    EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
+    EXPECT_EQ(0, coded_input.BytesUntilLimit());
+
+    coded_input.PopLimit(limit1);
+
+    // No more limits.
+    EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+    EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+  }
+
+  EXPECT_EQ(8, input.ByteCount());
+}
+
+TEST_F(CodedStreamTest, ExpectAtEnd) {
+  // Test ExpectAtEnd(), which is based on limits.
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+
+  EXPECT_FALSE(coded_input.ExpectAtEnd());
+
+  CodedInputStream::Limit limit = coded_input.PushLimit(4);
+
+  uint32 value;
+  EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
+  EXPECT_TRUE(coded_input.ExpectAtEnd());
+
+  coded_input.PopLimit(limit);
+  EXPECT_FALSE(coded_input.ExpectAtEnd());
+}
+
+TEST_F(CodedStreamTest, NegativeLimit) {
+  // Check what happens when we push a negative limit.
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+
+  CodedInputStream::Limit limit = coded_input.PushLimit(-1234);
+  // BytesUntilLimit() returns -1 to mean "no limit", which actually means
+  // "the limit is INT_MAX relative to the beginning of the stream".
+  EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+  coded_input.PopLimit(limit);
+}
+
+TEST_F(CodedStreamTest, NegativeLimitAfterReading) {
+  // Check what happens when we push a negative limit.
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+  ASSERT_TRUE(coded_input.Skip(128));
+
+  CodedInputStream::Limit limit = coded_input.PushLimit(-64);
+  // BytesUntilLimit() returns -1 to mean "no limit", which actually means
+  // "the limit is INT_MAX relative to the beginning of the stream".
+  EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+  coded_input.PopLimit(limit);
+}
+
+TEST_F(CodedStreamTest, OverflowLimit) {
+  // Check what happens when we push a limit large enough that its absolute
+  // position is more than 2GB into the stream.
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+  ASSERT_TRUE(coded_input.Skip(128));
+
+  CodedInputStream::Limit limit = coded_input.PushLimit(INT_MAX);
+  // BytesUntilLimit() returns -1 to mean "no limit", which actually means
+  // "the limit is INT_MAX relative to the beginning of the stream".
+  EXPECT_EQ(-1, coded_input.BytesUntilLimit());
+  coded_input.PopLimit(limit);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimit) {
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+  coded_input.SetTotalBytesLimit(16, -1);
+  EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
+
+  string str;
+  EXPECT_TRUE(coded_input.ReadString(&str, 16));
+  EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit());
+
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog error_log;
+    EXPECT_FALSE(coded_input.ReadString(&str, 1));
+    errors = error_log.GetMessages(ERROR);
+  }
+
+  ASSERT_EQ(1, errors.size());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring,
+    "A protocol message was rejected because it was too big", errors[0]);
+
+  coded_input.SetTotalBytesLimit(32, -1);
+  EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
+  EXPECT_TRUE(coded_input.ReadString(&str, 16));
+  EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit());
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) {
+  // total_bytes_limit_ is not a valid place for a message to end.
+
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+
+  // Set both total_bytes_limit and a regular limit at 16 bytes.
+  coded_input.SetTotalBytesLimit(16, -1);
+  CodedInputStream::Limit limit = coded_input.PushLimit(16);
+
+  // Read 16 bytes.
+  string str;
+  EXPECT_TRUE(coded_input.ReadString(&str, 16));
+
+  // Read a tag.  Should fail, but report being a valid endpoint since it's
+  // a regular limit.
+  EXPECT_EQ(0, coded_input.ReadTag());
+  EXPECT_TRUE(coded_input.ConsumedEntireMessage());
+
+  // Pop the limit.
+  coded_input.PopLimit(limit);
+
+  // Read a tag.  Should fail, and report *not* being a valid endpoint, since
+  // this time we're hitting the total bytes limit.
+  EXPECT_EQ(0, coded_input.ReadTag());
+  EXPECT_FALSE(coded_input.ConsumedEntireMessage());
+}
+
+// This method is used by the tests below.
+// It constructs a CodedInputStream with the given limits and tries to read 2KiB
+// of data from it. Then it returns the logged errors and warnings in the given
+// vectors.
+void CodedStreamTest::SetupTotalBytesLimitWarningTest(
+    int total_bytes_limit, int warning_threshold,
+    vector<string>* out_errors, vector<string>* out_warnings) {
+  ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128);
+
+  ScopedMemoryLog scoped_log;
+  {
+    CodedInputStream input(&raw_input);
+    input.SetTotalBytesLimit(total_bytes_limit, warning_threshold);
+    string str;
+    EXPECT_TRUE(input.ReadString(&str, 2048));
+  }
+
+  *out_errors = scoped_log.GetMessages(ERROR);
+  *out_warnings = scoped_log.GetMessages(WARNING);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarning) {
+  vector<string> errors;
+  vector<string> warnings;
+  SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings);
+
+  EXPECT_EQ(0, errors.size());
+
+  ASSERT_EQ(2, warnings.size());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring,
+    "Reading dangerously large protocol message.  If the message turns out to "
+    "be larger than 10240 bytes, parsing will be halted for security reasons.",
+    warnings[0]);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring,
+    "The total number of bytes read was 2048",
+    warnings[1]);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) {
+  vector<string> errors;
+  vector<string> warnings;
+
+  // Test with -1
+  SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings);
+  EXPECT_EQ(0, errors.size());
+  EXPECT_EQ(0, warnings.size());
+
+  // Test again with -2, expecting the same result
+  SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings);
+  EXPECT_EQ(0, errors.size());
+  EXPECT_EQ(0, warnings.size());
+}
+
+
+TEST_F(CodedStreamTest, RecursionLimit) {
+  ArrayInputStream input(buffer_, sizeof(buffer_));
+  CodedInputStream coded_input(&input);
+  coded_input.SetRecursionLimit(4);
+
+  // This is way too much testing for a counter.
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 1
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 2
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 3
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 4
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 5
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 6
+  coded_input.DecrementRecursionDepth();                   // 5
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 6
+  coded_input.DecrementRecursionDepth();                   // 5
+  coded_input.DecrementRecursionDepth();                   // 4
+  coded_input.DecrementRecursionDepth();                   // 3
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 4
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 5
+  coded_input.DecrementRecursionDepth();                   // 4
+  coded_input.DecrementRecursionDepth();                   // 3
+  coded_input.DecrementRecursionDepth();                   // 2
+  coded_input.DecrementRecursionDepth();                   // 1
+  coded_input.DecrementRecursionDepth();                   // 0
+  coded_input.DecrementRecursionDepth();                   // 0
+  coded_input.DecrementRecursionDepth();                   // 0
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 1
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 2
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 3
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 4
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 5
+
+  coded_input.SetRecursionLimit(6);
+  EXPECT_TRUE(coded_input.IncrementRecursionDepth());      // 6
+  EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 7
+}
+
+
+class ReallyBigInputStream : public ZeroCopyInputStream {
+ public:
+  ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {}
+  ~ReallyBigInputStream() {}
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size) {
+    // We only expect BackUp() to be called at the end.
+    EXPECT_EQ(0, backup_amount_);
+
+    switch (buffer_count_++) {
+      case 0:
+        *data = buffer_;
+        *size = sizeof(buffer_);
+        return true;
+      case 1:
+        // Return an enormously large buffer that, when combined with the 1k
+        // returned already, should overflow the total_bytes_read_ counter in
+        // CodedInputStream.  Note that we'll only read the first 1024 bytes
+        // of this buffer so it's OK that we have it point at buffer_.
+        *data = buffer_;
+        *size = INT_MAX;
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  void BackUp(int count) {
+    backup_amount_ = count;
+  }
+
+  bool Skip(int count)    { GOOGLE_LOG(FATAL) << "Not implemented."; return false; }
+  int64 ByteCount() const { GOOGLE_LOG(FATAL) << "Not implemented."; return 0; }
+
+  int backup_amount_;
+
+ private:
+  char buffer_[1024];
+  int64 buffer_count_;
+};
+
+TEST_F(CodedStreamTest, InputOver2G) {
+  // CodedInputStream should gracefully handle input over 2G and call
+  // input.BackUp() with the correct number of bytes on destruction.
+  ReallyBigInputStream input;
+
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog error_log;
+    CodedInputStream coded_input(&input);
+    string str;
+    EXPECT_TRUE(coded_input.ReadString(&str, 512));
+    EXPECT_TRUE(coded_input.ReadString(&str, 1024));
+    errors = error_log.GetMessages(ERROR);
+  }
+
+  EXPECT_EQ(INT_MAX - 512, input.backup_amount_);
+  EXPECT_EQ(0, errors.size());
+}
+
+// ===================================================================
+
+
+}  // namespace
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.cc b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.cc
new file mode 100644
index 0000000..9c621b6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.cc
@@ -0,0 +1,330 @@
+// 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.
+
+// Author: brianolson@google.com (Brian Olson)
+//
+// This file contains the implementation of classes GzipInputStream and
+// GzipOutputStream.
+
+
+#if HAVE_ZLIB
+#include <google/protobuf/io/gzip_stream.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+static const int kDefaultBufferSize = 65536;
+
+GzipInputStream::GzipInputStream(
+    ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
+    : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
+  zcontext_.state = Z_NULL;
+  zcontext_.zalloc = Z_NULL;
+  zcontext_.zfree = Z_NULL;
+  zcontext_.opaque = Z_NULL;
+  zcontext_.total_out = 0;
+  zcontext_.next_in = NULL;
+  zcontext_.avail_in = 0;
+  zcontext_.total_in = 0;
+  zcontext_.msg = NULL;
+  if (buffer_size == -1) {
+    output_buffer_length_ = kDefaultBufferSize;
+  } else {
+    output_buffer_length_ = buffer_size;
+  }
+  output_buffer_ = operator new(output_buffer_length_);
+  GOOGLE_CHECK(output_buffer_ != NULL);
+  zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
+  zcontext_.avail_out = output_buffer_length_;
+  output_position_ = output_buffer_;
+}
+GzipInputStream::~GzipInputStream() {
+  operator delete(output_buffer_);
+  zerror_ = inflateEnd(&zcontext_);
+}
+
+static inline int internalInflateInit2(
+    z_stream* zcontext, GzipInputStream::Format format) {
+  int windowBitsFormat = 0;
+  switch (format) {
+    case GzipInputStream::GZIP: windowBitsFormat = 16; break;
+    case GzipInputStream::AUTO: windowBitsFormat = 32; break;
+    case GzipInputStream::ZLIB: windowBitsFormat = 0; break;
+  }
+  return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat);
+}
+
+int GzipInputStream::Inflate(int flush) {
+  if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) {
+    // previous inflate filled output buffer. don't change input params yet.
+  } else if (zcontext_.avail_in == 0) {
+    const void* in;
+    int in_size;
+    bool first = zcontext_.next_in == NULL;
+    bool ok = sub_stream_->Next(&in, &in_size);
+    if (!ok) {
+      zcontext_.next_out = NULL;
+      zcontext_.avail_out = 0;
+      return Z_STREAM_END;
+    }
+    zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in));
+    zcontext_.avail_in = in_size;
+    if (first) {
+      int error = internalInflateInit2(&zcontext_, format_);
+      if (error != Z_OK) {
+        return error;
+      }
+    }
+  }
+  zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
+  zcontext_.avail_out = output_buffer_length_;
+  output_position_ = output_buffer_;
+  int error = inflate(&zcontext_, flush);
+  return error;
+}
+
+void GzipInputStream::DoNextOutput(const void** data, int* size) {
+  *data = output_position_;
+  *size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_);
+  output_position_ = zcontext_.next_out;
+}
+
+// implements ZeroCopyInputStream ----------------------------------
+bool GzipInputStream::Next(const void** data, int* size) {
+  bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
+      || (zerror_ == Z_BUF_ERROR);
+  if ((!ok) || (zcontext_.next_out == NULL)) {
+    return false;
+  }
+  if (zcontext_.next_out != output_position_) {
+    DoNextOutput(data, size);
+    return true;
+  }
+  if (zerror_ == Z_STREAM_END) {
+    if (zcontext_.next_out != NULL) {
+      // sub_stream_ may have concatenated streams to follow
+      zerror_ = inflateEnd(&zcontext_);
+      byte_count_ += zcontext_.total_out;
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+      zerror_ = internalInflateInit2(&zcontext_, format_);
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+    } else {
+      *data = NULL;
+      *size = 0;
+      return false;
+    }
+  }
+  zerror_ = Inflate(Z_NO_FLUSH);
+  if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) {
+    // The underlying stream's Next returned false inside Inflate.
+    return false;
+  }
+  ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
+      || (zerror_ == Z_BUF_ERROR);
+  if (!ok) {
+    return false;
+  }
+  DoNextOutput(data, size);
+  return true;
+}
+void GzipInputStream::BackUp(int count) {
+  output_position_ = reinterpret_cast<void*>(
+      reinterpret_cast<uintptr_t>(output_position_) - count);
+}
+bool GzipInputStream::Skip(int count) {
+  const void* data;
+  int size;
+  bool ok = Next(&data, &size);
+  while (ok && (size < count)) {
+    count -= size;
+    ok = Next(&data, &size);
+  }
+  if (size > count) {
+    BackUp(size - count);
+  }
+  return ok;
+}
+int64 GzipInputStream::ByteCount() const {
+  int64 ret = byte_count_ + zcontext_.total_out;
+  if (zcontext_.next_out != NULL && output_position_ != NULL) {
+    ret += reinterpret_cast<uintptr_t>(zcontext_.next_out) -
+           reinterpret_cast<uintptr_t>(output_position_);
+  }
+  return ret;
+}
+
+// =========================================================================
+
+GzipOutputStream::Options::Options()
+    : format(GZIP),
+      buffer_size(kDefaultBufferSize),
+      compression_level(Z_DEFAULT_COMPRESSION),
+      compression_strategy(Z_DEFAULT_STRATEGY) {}
+
+GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream) {
+  Init(sub_stream, Options());
+}
+
+GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream,
+                                   const Options& options) {
+  Init(sub_stream, options);
+}
+
+void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream,
+                            const Options& options) {
+  sub_stream_ = sub_stream;
+  sub_data_ = NULL;
+  sub_data_size_ = 0;
+
+  input_buffer_length_ = options.buffer_size;
+  input_buffer_ = operator new(input_buffer_length_);
+  GOOGLE_CHECK(input_buffer_ != NULL);
+
+  zcontext_.zalloc = Z_NULL;
+  zcontext_.zfree = Z_NULL;
+  zcontext_.opaque = Z_NULL;
+  zcontext_.next_out = NULL;
+  zcontext_.avail_out = 0;
+  zcontext_.total_out = 0;
+  zcontext_.next_in = NULL;
+  zcontext_.avail_in = 0;
+  zcontext_.total_in = 0;
+  zcontext_.msg = NULL;
+  // default to GZIP format
+  int windowBitsFormat = 16;
+  if (options.format == ZLIB) {
+    windowBitsFormat = 0;
+  }
+  zerror_ = deflateInit2(
+      &zcontext_,
+      options.compression_level,
+      Z_DEFLATED,
+      /* windowBits */15 | windowBitsFormat,
+      /* memLevel (default) */8,
+      options.compression_strategy);
+}
+
+GzipOutputStream::~GzipOutputStream() {
+  Close();
+  operator delete(input_buffer_);
+}
+
+// private
+int GzipOutputStream::Deflate(int flush) {
+  int error = Z_OK;
+  do {
+    if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) {
+      bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_);
+      if (!ok) {
+        sub_data_ = NULL;
+        sub_data_size_ = 0;
+        return Z_BUF_ERROR;
+      }
+      GOOGLE_CHECK_GT(sub_data_size_, 0);
+      zcontext_.next_out = static_cast<Bytef*>(sub_data_);
+      zcontext_.avail_out = sub_data_size_;
+    }
+    error = deflate(&zcontext_, flush);
+  } while (error == Z_OK && zcontext_.avail_out == 0);
+  if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) {
+    // Notify lower layer of data.
+    sub_stream_->BackUp(zcontext_.avail_out);
+    // We don't own the buffer anymore.
+    sub_data_ = NULL;
+    sub_data_size_ = 0;
+  }
+  return error;
+}
+
+// implements ZeroCopyOutputStream ---------------------------------
+bool GzipOutputStream::Next(void** data, int* size) {
+  if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
+    return false;
+  }
+  if (zcontext_.avail_in != 0) {
+    zerror_ = Deflate(Z_NO_FLUSH);
+    if (zerror_ != Z_OK) {
+      return false;
+    }
+  }
+  if (zcontext_.avail_in == 0) {
+    // all input was consumed. reset the buffer.
+    zcontext_.next_in = static_cast<Bytef*>(input_buffer_);
+    zcontext_.avail_in = input_buffer_length_;
+    *data = input_buffer_;
+    *size = input_buffer_length_;
+  } else {
+    // The loop in Deflate should consume all avail_in
+    GOOGLE_LOG(DFATAL) << "Deflate left bytes unconsumed";
+  }
+  return true;
+}
+void GzipOutputStream::BackUp(int count) {
+  GOOGLE_CHECK_GE(zcontext_.avail_in, count);
+  zcontext_.avail_in -= count;
+}
+int64 GzipOutputStream::ByteCount() const {
+  return zcontext_.total_in + zcontext_.avail_in;
+}
+
+bool GzipOutputStream::Flush() {
+  zerror_ = Deflate(Z_FULL_FLUSH);
+  // Return true if the flush succeeded or if it was a no-op.
+  return  (zerror_ == Z_OK) ||
+      (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 &&
+       zcontext_.avail_out != 0);
+}
+
+bool GzipOutputStream::Close() {
+  if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
+    return false;
+  }
+  do {
+    zerror_ = Deflate(Z_FINISH);
+  } while (zerror_ == Z_OK);
+  zerror_ = deflateEnd(&zcontext_);
+  bool ok = zerror_ == Z_OK;
+  zerror_ = Z_STREAM_END;
+  return ok;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // HAVE_ZLIB
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.h b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.h
new file mode 100644
index 0000000..15b02fe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream.h
@@ -0,0 +1,209 @@
+// 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.
+
+// Author: brianolson@google.com (Brian Olson)
+//
+// This file contains the definition for classes GzipInputStream and
+// GzipOutputStream.
+//
+// GzipInputStream decompresses data from an underlying
+// ZeroCopyInputStream and provides the decompressed data as a
+// ZeroCopyInputStream.
+//
+// GzipOutputStream is an ZeroCopyOutputStream that compresses data to
+// an underlying ZeroCopyOutputStream.
+
+#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
+#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <zlib.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+// A ZeroCopyInputStream that reads compressed data through zlib
+class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream {
+ public:
+  // Format key for constructor
+  enum Format {
+    // zlib will autodetect gzip header or deflate stream
+    AUTO = 0,
+
+    // GZIP streams have some extra header data for file attributes.
+    GZIP = 1,
+
+    // Simpler zlib stream format.
+    ZLIB = 2,
+  };
+
+  // buffer_size and format may be -1 for default of 64kB and GZIP format
+  explicit GzipInputStream(
+      ZeroCopyInputStream* sub_stream,
+      Format format = AUTO,
+      int buffer_size = -1);
+  virtual ~GzipInputStream();
+
+  // Return last error message or NULL if no error.
+  inline const char* ZlibErrorMessage() const {
+    return zcontext_.msg;
+  }
+  inline int ZlibErrorCode() const {
+    return zerror_;
+  }
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+ private:
+  Format format_;
+
+  ZeroCopyInputStream* sub_stream_;
+
+  z_stream zcontext_;
+  int zerror_;
+
+  void* output_buffer_;
+  void* output_position_;
+  size_t output_buffer_length_;
+  int64 byte_count_;
+
+  int Inflate(int flush);
+  void DoNextOutput(const void** data, int* size);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
+};
+
+
+class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Format key for constructor
+  enum Format {
+    // GZIP streams have some extra header data for file attributes.
+    GZIP = 1,
+
+    // Simpler zlib stream format.
+    ZLIB = 2,
+  };
+
+  struct Options {
+    // Defaults to GZIP.
+    Format format;
+
+    // What size buffer to use internally.  Defaults to 64kB.
+    int buffer_size;
+
+    // A number between 0 and 9, where 0 is no compression and 9 is best
+    // compression.  Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
+    int compression_level;
+
+    // Defaults to Z_DEFAULT_STRATEGY.  Can also be set to Z_FILTERED,
+    // Z_HUFFMAN_ONLY, or Z_RLE.  See the documentation for deflateInit2 in
+    // zlib.h for definitions of these constants.
+    int compression_strategy;
+
+    Options();  // Initializes with default values.
+  };
+
+  // Create a GzipOutputStream with default options.
+  explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
+
+  // Create a GzipOutputStream with the given options.
+  GzipOutputStream(
+      ZeroCopyOutputStream* sub_stream,
+      const Options& options);
+
+  virtual ~GzipOutputStream();
+
+  // Return last error message or NULL if no error.
+  inline const char* ZlibErrorMessage() const {
+    return zcontext_.msg;
+  }
+  inline int ZlibErrorCode() const {
+    return zerror_;
+  }
+
+  // Flushes data written so far to zipped data in the underlying stream.
+  // It is the caller's responsibility to flush the underlying stream if
+  // necessary.
+  // Compression may be less efficient stopping and starting around flushes.
+  // Returns true if no error.
+  //
+  // Please ensure that block size is > 6. Here is an excerpt from the zlib
+  // doc that explains why:
+  //
+  // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
+  // is greater than six to avoid repeated flush markers due to
+  // avail_out == 0 on return.
+  bool Flush();
+
+  // Writes out all data and closes the gzip stream.
+  // It is the caller's responsibility to close the underlying stream if
+  // necessary.
+  // Returns true if no error.
+  bool Close();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  ZeroCopyOutputStream* sub_stream_;
+  // Result from calling Next() on sub_stream_
+  void* sub_data_;
+  int sub_data_size_;
+
+  z_stream zcontext_;
+  int zerror_;
+  void* input_buffer_;
+  size_t input_buffer_length_;
+
+  // Shared constructor code.
+  void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
+
+  // Do some compression.
+  // Takes zlib flush mode.
+  // Returns zlib error code.
+  int Deflate(int flush);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
+};
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream_unittest.sh b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream_unittest.sh
new file mode 100755
index 0000000..16251a9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/gzip_stream_unittest.sh
@@ -0,0 +1,44 @@
+#!/bin/sh -x
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2009 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.
+#
+# Author: brianolson@google.com (Brian Olson)
+#
+# Test compatibility between command line gzip/gunzip binaries and
+# ZeroCopyStream versions.
+
+TESTFILE=Makefile
+
+(./zcgzip < ${TESTFILE} | gunzip | cmp - ${TESTFILE}) && \
+(gzip < ${TESTFILE} | ./zcgunzip | cmp - ${TESTFILE})
+
+# Result of "(cmd) && (cmd)" implicitly becomes result of this script
+# and thus the test.
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/package_info.h b/src/third_party/protobuf-3/src/google/protobuf/io/package_info.h
new file mode 100644
index 0000000..dc1fc91
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/package_info.h
@@ -0,0 +1,54 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file exists solely to document the google::protobuf::io namespace.
+// It is not compiled into anything, but it may be read by an automated
+// documentation generator.
+
+namespace google {
+
+namespace protobuf {
+
+// Auxiliary classes used for I/O.
+//
+// The Protocol Buffer library uses the classes in this package to deal with
+// I/O and encoding/decoding raw bytes.  Most users will not need to
+// deal with this package.  However, users who want to adapt the system to
+// work with their own I/O abstractions -- e.g., to allow Protocol Buffers
+// to be read from a different kind of input stream without the need for a
+// temporary buffer -- should take a closer look.
+namespace io {}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/printer.cc b/src/third_party/protobuf-3/src/google/protobuf/io/printer.cc
new file mode 100644
index 0000000..7532b09
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/printer.cc
@@ -0,0 +1,346 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
+    : variable_delimiter_(variable_delimiter),
+      output_(output),
+      buffer_(NULL),
+      buffer_size_(0),
+      offset_(0),
+      at_start_of_line_(true),
+      failed_(false),
+      annotation_collector_(NULL) {}
+
+Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+                 AnnotationCollector* annotation_collector)
+    : variable_delimiter_(variable_delimiter),
+      output_(output),
+      buffer_(NULL),
+      buffer_size_(0),
+      offset_(0),
+      at_start_of_line_(true),
+      failed_(false),
+      annotation_collector_(annotation_collector) {}
+
+Printer::~Printer() {
+  // Only BackUp() if we have called Next() at least once and never failed.
+  if (buffer_size_ > 0 && !failed_) {
+    output_->BackUp(buffer_size_);
+  }
+}
+
+bool Printer::GetSubstitutionRange(const char* varname,
+                                   pair<size_t, size_t>* range) {
+  map<string, pair<size_t, size_t> >::const_iterator iter =
+      substitutions_.find(varname);
+  if (iter == substitutions_.end()) {
+    GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
+    return false;
+  }
+  if (iter->second.first > iter->second.second) {
+    GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
+                << varname;
+    return false;
+  }
+  *range = iter->second;
+  return true;
+}
+
+void Printer::Annotate(const char* begin_varname, const char* end_varname,
+                       const string& file_path, const vector<int>& path) {
+  if (annotation_collector_ == NULL) {
+    // Can't generate signatures with this Printer.
+    return;
+  }
+  pair<size_t, size_t> begin, end;
+  if (!GetSubstitutionRange(begin_varname, &begin) ||
+      !GetSubstitutionRange(end_varname, &end)) {
+    return;
+  }
+  if (begin.first > end.second) {
+    GOOGLE_LOG(DFATAL) << "  Annotation has negative length from " << begin_varname
+                << " to " << end_varname;
+  } else {
+    annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
+                                         path);
+  }
+}
+
+void Printer::Print(const map<string, string>& variables, const char* text) {
+  int size = strlen(text);
+  int pos = 0;  // The number of bytes we've written so far.
+  substitutions_.clear();
+
+  for (int i = 0; i < size; i++) {
+    if (text[i] == '\n') {
+      // Saw newline.  If there is more text, we may need to insert an indent
+      // here.  So, write what we have so far, including the '\n'.
+      WriteRaw(text + pos, i - pos + 1);
+      pos = i + 1;
+
+      // Setting this true will cause the next WriteRaw() to insert an indent
+      // first.
+      at_start_of_line_ = true;
+
+    } else if (text[i] == variable_delimiter_) {
+      // Saw the start of a variable name.
+
+      // Write what we have so far.
+      WriteRaw(text + pos, i - pos);
+      pos = i + 1;
+
+      // Find closing delimiter.
+      const char* end = strchr(text + pos, variable_delimiter_);
+      if (end == NULL) {
+        GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
+        end = text + pos;
+      }
+      int endpos = end - text;
+
+      string varname(text + pos, endpos - pos);
+      if (varname.empty()) {
+        // Two delimiters in a row reduce to a literal delimiter character.
+        WriteRaw(&variable_delimiter_, 1);
+      } else {
+        // Replace with the variable's value.
+        map<string, string>::const_iterator iter = variables.find(varname);
+        if (iter == variables.end()) {
+          GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
+        } else {
+          size_t begin = offset_;
+          WriteRaw(iter->second.data(), iter->second.size());
+          pair<map<string, pair<size_t, size_t> >::iterator, bool> inserted =
+              substitutions_.insert(
+                  std::make_pair(varname, std::make_pair(begin, offset_)));
+          if (!inserted.second) {
+            // This variable was used multiple times.  Make its span have
+            // negative length so we can detect it if it gets used in an
+            // annotation.
+            inserted.first->second = std::make_pair(1, 0);
+          }
+        }
+      }
+
+      // Advance past this variable.
+      i = endpos;
+      pos = endpos + 1;
+    }
+  }
+
+  // Write the rest.
+  WriteRaw(text + pos, size - pos);
+}
+
+void Printer::Print(const char* text) {
+  static map<string, string> empty;
+  Print(empty, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable, const string& value) {
+  map<string, string> vars;
+  vars[variable] = value;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3,
+                    const char* variable4, const string& value4) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  vars[variable4] = value4;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3,
+                    const char* variable4, const string& value4,
+                    const char* variable5, const string& value5) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  vars[variable4] = value4;
+  vars[variable5] = value5;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3,
+                    const char* variable4, const string& value4,
+                    const char* variable5, const string& value5,
+                    const char* variable6, const string& value6) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  vars[variable4] = value4;
+  vars[variable5] = value5;
+  vars[variable6] = value6;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3,
+                    const char* variable4, const string& value4,
+                    const char* variable5, const string& value5,
+                    const char* variable6, const string& value6,
+                    const char* variable7, const string& value7) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  vars[variable4] = value4;
+  vars[variable5] = value5;
+  vars[variable6] = value6;
+  vars[variable7] = value7;
+  Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3,
+                    const char* variable4, const string& value4,
+                    const char* variable5, const string& value5,
+                    const char* variable6, const string& value6,
+                    const char* variable7, const string& value7,
+                    const char* variable8, const string& value8) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  vars[variable4] = value4;
+  vars[variable5] = value5;
+  vars[variable6] = value6;
+  vars[variable7] = value7;
+  vars[variable8] = value8;
+  Print(vars, text);
+}
+
+void Printer::Indent() {
+  indent_ += "  ";
+}
+
+void Printer::Outdent() {
+  if (indent_.empty()) {
+    GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
+    return;
+  }
+
+  indent_.resize(indent_.size() - 2);
+}
+
+void Printer::PrintRaw(const string& data) {
+  WriteRaw(data.data(), data.size());
+}
+
+void Printer::PrintRaw(const char* data) {
+  if (failed_) return;
+  WriteRaw(data, strlen(data));
+}
+
+void Printer::WriteRaw(const char* data, int size) {
+  if (failed_) return;
+  if (size == 0) return;
+
+  if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
+    // Insert an indent.
+    at_start_of_line_ = false;
+    WriteRaw(indent_.data(), indent_.size());
+    if (failed_) return;
+  }
+
+  while (size > buffer_size_) {
+    // Data exceeds space in the buffer.  Copy what we can and request a
+    // new buffer.
+    memcpy(buffer_, data, buffer_size_);
+    offset_ += buffer_size_;
+    data += buffer_size_;
+    size -= buffer_size_;
+    void* void_buffer;
+    failed_ = !output_->Next(&void_buffer, &buffer_size_);
+    if (failed_) return;
+    buffer_ = reinterpret_cast<char*>(void_buffer);
+  }
+
+  // Buffer is big enough to receive the data; copy it.
+  memcpy(buffer_, data, size);
+  buffer_ += size;
+  buffer_size_ -= size;
+  offset_ += size;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/printer.h b/src/third_party/protobuf-3/src/google/protobuf/io/printer.h
new file mode 100644
index 0000000..2ba8455
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/printer.h
@@ -0,0 +1,333 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Utility class for writing text to a ZeroCopyOutputStream.
+
+#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
+#define GOOGLE_PROTOBUF_IO_PRINTER_H__
+
+#include <string>
+#include <map>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+class ZeroCopyOutputStream;     // zero_copy_stream.h
+
+// Records annotations about a Printer's output.
+class LIBPROTOBUF_EXPORT AnnotationCollector {
+ public:
+  // Records that the bytes in file_path beginning with begin_offset and ending
+  // before end_offset are associated with the SourceCodeInfo-style path.
+  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+                             const string& file_path,
+                             const vector<int>& path) = 0;
+
+  virtual ~AnnotationCollector() {}
+};
+
+// Records annotations about a Printer's output to the given protocol buffer,
+// assuming that the buffer has an ::Annotation message exposing path,
+// source_file, begin and end fields.
+template <typename AnnotationProto>
+class AnnotationProtoCollector : public AnnotationCollector {
+ public:
+  // annotation_proto is the protocol buffer to which new Annotations should be
+  // added. It is not owned by the AnnotationProtoCollector.
+  explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
+      : annotation_proto_(annotation_proto) {}
+
+  // Override for AnnotationCollector::AddAnnotation.
+  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+                             const string& file_path, const vector<int>& path) {
+    typename AnnotationProto::Annotation* annotation =
+        annotation_proto_->add_annotation();
+    for (int i = 0; i < path.size(); ++i) {
+      annotation->add_path(path[i]);
+    }
+    annotation->set_source_file(file_path);
+    annotation->set_begin(begin_offset);
+    annotation->set_end(end_offset);
+  }
+
+ private:
+  // The protocol buffer to which new annotations should be added.
+  AnnotationProto* const annotation_proto_;
+};
+
+// This simple utility class assists in code generation.  It basically
+// allows the caller to define a set of variables and then output some
+// text with variable substitutions.  Example usage:
+//
+//   Printer printer(output, '$');
+//   map<string, string> vars;
+//   vars["name"] = "Bob";
+//   printer.Print(vars, "My name is $name$.");
+//
+// The above writes "My name is Bob." to the output stream.
+//
+// Printer aggressively enforces correct usage, crashing (with assert failures)
+// in the case of undefined variables in debug builds. This helps greatly in
+// debugging code which uses it.
+//
+// If a Printer is constructed with an AnnotationCollector, it will provide it
+// with annotations that connect the Printer's output to paths that can identify
+// various descriptors.  In the above example, if person_ is a descriptor that
+// identifies Bob, we can associate the output string "My name is Bob." with
+// a source path pointing to that descriptor with:
+//
+//   printer.Annotate("name", person_);
+//
+// The AnnotationCollector will be sent an annotation linking the output range
+// covering "Bob" to the logical path provided by person_.  Tools may use
+// this association to (for example) link "Bob" in the output back to the
+// source file that defined the person_ descriptor identifying Bob.
+//
+// Annotate can only examine variables substituted during the last call to
+// Print.  It is invalid to refer to a variable that was used multiple times
+// in a single Print call.
+//
+// In full generality, one may specify a range of output text using a beginning
+// substitution variable and an ending variable.  The resulting annotation will
+// span from the first character of the substituted value for the beginning
+// variable to the last character of the substituted value for the ending
+// variable.  For example, the Annotate call above is equivalent to this one:
+//
+//   printer.Annotate("name", "name", person_);
+//
+// This is useful if multiple variables combine to form a single span of output
+// that should be annotated with the same source path.  For example:
+//
+//   Printer printer(output, '$');
+//   map<string, string> vars;
+//   vars["first"] = "Alice";
+//   vars["last"] = "Smith";
+//   printer.Print(vars, "My name is $first$ $last$.");
+//   printer.Annotate("first", "last", person_);
+//
+// This code would associate the span covering "Alice Smith" in the output with
+// the person_ descriptor.
+//
+// Note that the beginning variable must come before (or overlap with, in the
+// case of zero-sized substitution values) the ending variable.
+//
+// It is also sometimes useful to use variables with zero-sized values as
+// markers.  This avoids issues with multiple references to the same variable
+// and also allows annotation ranges to span literal text from the Print
+// templates:
+//
+//   Printer printer(output, '$');
+//   map<string, string> vars;
+//   vars["foo"] = "bar";
+//   vars["function"] = "call";
+//   vars["mark"] = "";
+//   printer.Print(vars, "$function$($foo$,$foo$)$mark$");
+//   printer.Annotate("function", "rmark", call_);
+//
+// This code associates the span covering "call(bar,bar)" in the output with the
+// call_ descriptor.
+
+class LIBPROTOBUF_EXPORT Printer {
+ public:
+  // Create a printer that writes text to the given output stream.  Use the
+  // given character as the delimiter for variables.
+  Printer(ZeroCopyOutputStream* output, char variable_delimiter);
+
+  // Create a printer that writes text to the given output stream.  Use the
+  // given character as the delimiter for variables.  If annotation_collector
+  // is not null, Printer will provide it with annotations about code written
+  // to the stream.  annotation_collector is not owned by Printer.
+  Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+          AnnotationCollector* annotation_collector);
+
+  ~Printer();
+
+  // Link a subsitution variable emitted by the last call to Print to the object
+  // described by descriptor.
+  template <typename SomeDescriptor>
+  void Annotate(const char* varname, const SomeDescriptor* descriptor) {
+    Annotate(varname, varname, descriptor);
+  }
+
+  // Link the output range defined by the substitution variables as emitted by
+  // the last call to Print to the object described by descriptor. The range
+  // begins at begin_varname's value and ends after the last character of the
+  // value substituted for end_varname.
+  template <typename SomeDescriptor>
+  void Annotate(const char* begin_varname, const char* end_varname,
+                const SomeDescriptor* descriptor) {
+    if (annotation_collector_ == NULL) {
+      // Annotations aren't turned on for this Printer, so don't pay the cost
+      // of building the location path.
+      return;
+    }
+    vector<int> path;
+    descriptor->GetLocationPath(&path);
+    Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
+  }
+
+  // Print some text after applying variable substitutions.  If a particular
+  // variable in the text is not defined, this will crash.  Variables to be
+  // substituted are identified by their names surrounded by delimiter
+  // characters (as given to the constructor).  The variable bindings are
+  // defined by the given map.
+  void Print(const map<string, string>& variables, const char* text);
+
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable, const string& value);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3,
+                               const char* variable4, const string& value4);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3,
+                               const char* variable4, const string& value4,
+                               const char* variable5, const string& value5);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3,
+                               const char* variable4, const string& value4,
+                               const char* variable5, const string& value5,
+                               const char* variable6, const string& value6);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3,
+                               const char* variable4, const string& value4,
+                               const char* variable5, const string& value5,
+                               const char* variable6, const string& value6,
+                               const char* variable7, const string& value7);
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3,
+                               const char* variable4, const string& value4,
+                               const char* variable5, const string& value5,
+                               const char* variable6, const string& value6,
+                               const char* variable7, const string& value7,
+                               const char* variable8, const string& value8);
+
+  // Indent text by two spaces.  After calling Indent(), two spaces will be
+  // inserted at the beginning of each line of text.  Indent() may be called
+  // multiple times to produce deeper indents.
+  void Indent();
+
+  // Reduces the current indent level by two spaces, or crashes if the indent
+  // level is zero.
+  void Outdent();
+
+  // Write a string to the output buffer.
+  // This method does not look for newlines to add indentation.
+  void PrintRaw(const string& data);
+
+  // Write a zero-delimited string to output buffer.
+  // This method does not look for newlines to add indentation.
+  void PrintRaw(const char* data);
+
+  // Write some bytes to the output buffer.
+  // This method does not look for newlines to add indentation.
+  void WriteRaw(const char* data, int size);
+
+  // True if any write to the underlying stream failed.  (We don't just
+  // crash in this case because this is an I/O failure, not a programming
+  // error.)
+  bool failed() const { return failed_; }
+
+ private:
+  // Link the output range defined by the substitution variables as emitted by
+  // the last call to Print to the object found at the SourceCodeInfo-style path
+  // in a file with path file_path. The range begins at the start of
+  // begin_varname's value and ends after the last character of the value
+  // substituted for end_varname. Note that begin_varname and end_varname
+  // may refer to the same variable.
+  void Annotate(const char* begin_varname, const char* end_varname,
+                const string& file_path, const vector<int>& path);
+
+  const char variable_delimiter_;
+
+  ZeroCopyOutputStream* const output_;
+  char* buffer_;
+  int buffer_size_;
+  // The current position, in bytes, in the output stream.  This is equivalent
+  // to the total number of bytes that have been written so far.  This value is
+  // used to calculate annotation ranges in the substitutions_ map below.
+  size_t offset_;
+
+  string indent_;
+  bool at_start_of_line_;
+  bool failed_;
+
+  // A map from variable name to [start, end) offsets in the output buffer.
+  // These refer to the offsets used for a variable after the last call to
+  // Print.  If a variable was used more than once, the entry used in
+  // this map is set to a negative-length span.  For singly-used variables, the
+  // start offset is the beginning of the substitution; the end offset is the
+  // last byte of the substitution plus one (such that (end - start) is the
+  // length of the substituted string).
+  map<string, pair<size_t, size_t> > substitutions_;
+
+  // Returns true and sets range to the substitution range in the output for
+  // varname if varname was used once in the last call to Print. If varname
+  // was not used, or if it was used multiple times, returns false (and
+  // fails a debug assertion).
+  bool GetSubstitutionRange(const char* varname, pair<size_t, size_t>* range);
+
+  // If non-null, annotation_collector_ is used to store annotations about
+  // generated code.
+  AnnotationCollector* const annotation_collector_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
+};
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_PRINTER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/printer_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/io/printer_unittest.cc
new file mode 100644
index 0000000..95f3afa
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/printer_unittest.cc
@@ -0,0 +1,523 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <vector>
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace {
+
+// Each test repeats over several block sizes in order to test both cases
+// where particular writes cross a buffer boundary and cases where they do
+// not.
+
+TEST(Printer, EmptyPrinter) {
+  char buffer[8192];
+  const int block_size = 100;
+  ArrayOutputStream output(buffer, GOOGLE_ARRAYSIZE(buffer), block_size);
+  Printer printer(&output, '\0');
+  EXPECT_TRUE(!printer.failed());
+}
+
+TEST(Printer, BasicPrinting) {
+  char buffer[8192];
+
+  for (int block_size = 1; block_size < 512; block_size *= 2) {
+    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+    {
+      Printer printer(&output, '\0');
+
+      printer.Print("Hello World!");
+      printer.Print("  This is the same line.\n");
+      printer.Print("But this is a new one.\nAnd this is another one.");
+
+      EXPECT_FALSE(printer.failed());
+    }
+
+    buffer[output.ByteCount()] = '\0';
+
+    EXPECT_STREQ("Hello World!  This is the same line.\n"
+                 "But this is a new one.\n"
+                 "And this is another one.",
+                 buffer);
+  }
+}
+
+TEST(Printer, WriteRaw) {
+  char buffer[8192];
+
+  for (int block_size = 1; block_size < 512; block_size *= 2) {
+    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+    {
+      string string_obj = "From an object\n";
+      Printer printer(&output, '$');
+      printer.WriteRaw("Hello World!", 12);
+      printer.PrintRaw("  This is the same line.\n");
+      printer.PrintRaw("But this is a new one.\nAnd this is another one.");
+      printer.WriteRaw("\n", 1);
+      printer.PrintRaw(string_obj);
+      EXPECT_FALSE(printer.failed());
+    }
+
+    buffer[output.ByteCount()] = '\0';
+
+    EXPECT_STREQ("Hello World!  This is the same line.\n"
+                 "But this is a new one.\n"
+                 "And this is another one."
+                 "\n"
+                 "From an object\n",
+                 buffer);
+  }
+}
+
+TEST(Printer, VariableSubstitution) {
+  char buffer[8192];
+
+  for (int block_size = 1; block_size < 512; block_size *= 2) {
+    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+    {
+      Printer printer(&output, '$');
+      map<string, string> vars;
+
+      vars["foo"] = "World";
+      vars["bar"] = "$foo$";
+      vars["abcdefg"] = "1234";
+
+      printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
+      printer.PrintRaw("RawBit\n");
+      printer.Print(vars, "$abcdefg$\nA literal dollar sign:  $$");
+
+      vars["foo"] = "blah";
+      printer.Print(vars, "\nNow foo = $foo$.");
+
+      EXPECT_FALSE(printer.failed());
+    }
+
+    buffer[output.ByteCount()] = '\0';
+
+    EXPECT_STREQ("Hello World!\n"
+                 "bar = $foo$\n"
+                 "RawBit\n"
+                 "1234\n"
+                 "A literal dollar sign:  $\n"
+                 "Now foo = blah.",
+                 buffer);
+  }
+}
+
+TEST(Printer, InlineVariableSubstitution) {
+  char buffer[8192];
+
+  ArrayOutputStream output(buffer, sizeof(buffer));
+
+  {
+    Printer printer(&output, '$');
+    printer.Print("Hello $foo$!\n", "foo", "World");
+    printer.PrintRaw("RawBit\n");
+    printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two");
+    EXPECT_FALSE(printer.failed());
+  }
+
+  buffer[output.ByteCount()] = '\0';
+
+  EXPECT_STREQ("Hello World!\n"
+               "RawBit\n"
+               "one two\n",
+               buffer);
+}
+
+// MockDescriptorFile defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptorFile {
+ public:
+  explicit MockDescriptorFile(const string& file) : file_(file) {}
+
+  // The mock filename for this file.
+  const string& name() const { return file_; }
+
+ private:
+  string file_;
+};
+
+// MockDescriptor defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptor {
+ public:
+  MockDescriptor(const string& file, const vector<int>& path)
+      : file_(file), path_(path) {}
+
+  // The mock file in which this descriptor was defined.
+  const MockDescriptorFile* file() const { return &file_; }
+
+ private:
+  // Allows access to GetLocationPath.
+  friend class ::google::protobuf::io::Printer;
+
+  // Copies the pre-stored path to output.
+  void GetLocationPath(std::vector<int>* output) const { *output = path_; }
+
+  MockDescriptorFile file_;
+  vector<int> path_;
+};
+
+TEST(Printer, AnnotateMap) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    map<string, string> vars;
+    vars["foo"] = "3";
+    vars["bar"] = "5";
+    printer.Print(vars, "012$foo$4$bar$\n");
+    vector<int> path_1;
+    path_1.push_back(33);
+    vector<int> path_2;
+    path_2.push_back(11);
+    path_2.push_back(22);
+    MockDescriptor descriptor_1("path_1", path_1);
+    MockDescriptor descriptor_2("path_2", path_2);
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(2, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(0)
+                                                 : &info.annotation(1);
+  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(1)
+                                                 : &info.annotation(0);
+  ASSERT_EQ(1, foo->path_size());
+  ASSERT_EQ(2, bar->path_size());
+  EXPECT_EQ(33, foo->path(0));
+  EXPECT_EQ(11, bar->path(0));
+  EXPECT_EQ(22, bar->path(1));
+  EXPECT_EQ("path_1", foo->source_file());
+  EXPECT_EQ("path_2", bar->source_file());
+  EXPECT_EQ(3, foo->begin());
+  EXPECT_EQ(4, foo->end());
+  EXPECT_EQ(5, bar->begin());
+  EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateInline) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path_1;
+    path_1.push_back(33);
+    vector<int> path_2;
+    path_2.push_back(11);
+    path_2.push_back(22);
+    MockDescriptor descriptor_1("path_1", path_1);
+    MockDescriptor descriptor_2("path_2", path_2);
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(2, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(0)
+                                                 : &info.annotation(1);
+  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(1)
+                                                 : &info.annotation(0);
+  ASSERT_EQ(1, foo->path_size());
+  ASSERT_EQ(2, bar->path_size());
+  EXPECT_EQ(33, foo->path(0));
+  EXPECT_EQ(11, bar->path(0));
+  EXPECT_EQ(22, bar->path(1));
+  EXPECT_EQ("path_1", foo->source_file());
+  EXPECT_EQ("path_2", bar->source_file());
+  EXPECT_EQ(3, foo->begin());
+  EXPECT_EQ(4, foo->end());
+  EXPECT_EQ(5, bar->begin());
+  EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateRange) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("foo", "bar", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0);
+  ASSERT_EQ(1, foobar->path_size());
+  EXPECT_EQ(33, foobar->path(0));
+  EXPECT_EQ("path", foobar->source_file());
+  EXPECT_EQ(3, foobar->begin());
+  EXPECT_EQ(6, foobar->end());
+}
+
+TEST(Printer, AnnotateEmptyRange) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
+                  "", "bam", "");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("baz", "bam", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0);
+  ASSERT_EQ(1, bazbam->path_size());
+  EXPECT_EQ(33, bazbam->path(0));
+  EXPECT_EQ("path", bazbam->source_file());
+  EXPECT_EQ(5, bazbam->begin());
+  EXPECT_EQ(5, bazbam->end());
+}
+
+TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("bar", "bar", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("0123435\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* bar = &info.annotation(0);
+  ASSERT_EQ(1, bar->path_size());
+  EXPECT_EQ(33, bar->path(0));
+  EXPECT_EQ("path", bar->source_file());
+  EXPECT_EQ(6, bar->begin());
+  EXPECT_EQ(7, bar->end());
+}
+
+TEST(Printer, Indenting) {
+  char buffer[8192];
+
+  for (int block_size = 1; block_size < 512; block_size *= 2) {
+    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+    {
+      Printer printer(&output, '$');
+      map<string, string> vars;
+
+      vars["newline"] = "\n";
+
+      printer.Print("This is not indented.\n");
+      printer.Indent();
+      printer.Print("This is indented\nAnd so is this\n");
+      printer.Outdent();
+      printer.Print("But this is not.");
+      printer.Indent();
+      printer.Print("  And this is still the same line.\n"
+                    "But this is indented.\n");
+      printer.PrintRaw("RawBit has indent at start\n");
+      printer.PrintRaw("but not after a raw newline\n");
+      printer.Print(vars, "Note that a newline in a variable will break "
+                    "indenting, as we see$newline$here.\n");
+      printer.Indent();
+      printer.Print("And this");
+      printer.Outdent();
+      printer.Outdent();
+      printer.Print(" is double-indented\nBack to normal.");
+
+      EXPECT_FALSE(printer.failed());
+    }
+
+    buffer[output.ByteCount()] = '\0';
+
+    EXPECT_STREQ(
+      "This is not indented.\n"
+      "  This is indented\n"
+      "  And so is this\n"
+      "But this is not.  And this is still the same line.\n"
+      "  But this is indented.\n"
+      "  RawBit has indent at start\n"
+      "but not after a raw newline\n"
+      "Note that a newline in a variable will break indenting, as we see\n"
+      "here.\n"
+      "    And this is double-indented\n"
+      "Back to normal.",
+      buffer);
+  }
+}
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(Printer, Death) {
+  char buffer[8192];
+
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  Printer printer(&output, '$');
+
+  EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "Undefined variable");
+  EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
+  EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
+}
+
+TEST(Printer, AnnotateMultipleUsesDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$\n", "foo", "3");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple");
+  }
+}
+
+TEST(Printer, AnnotateNegativeLengthDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative");
+  }
+}
+
+TEST(Printer, AnnotateUndefinedDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$\n", "foo", "3");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor),
+                       "Undefined");
+  }
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(Printer, WriteFailurePartial) {
+  char buffer[17];
+
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  Printer printer(&output, '$');
+
+  // Print 16 bytes to almost fill the buffer (should not fail).
+  printer.Print("0123456789abcdef");
+  EXPECT_FALSE(printer.failed());
+
+  // Try to print 2 chars. Only one fits.
+  printer.Print("<>");
+  EXPECT_TRUE(printer.failed());
+
+  // Anything else should fail too.
+  printer.Print(" ");
+  EXPECT_TRUE(printer.failed());
+  printer.Print("blah");
+  EXPECT_TRUE(printer.failed());
+
+  // Buffer should contain the first 17 bytes written.
+  EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer)));
+}
+
+TEST(Printer, WriteFailureExact) {
+  char buffer[16];
+
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  Printer printer(&output, '$');
+
+  // Print 16 bytes to fill the buffer exactly (should not fail).
+  printer.Print("0123456789abcdef");
+  EXPECT_FALSE(printer.failed());
+
+  // Try to print one more byte (should fail).
+  printer.Print(" ");
+  EXPECT_TRUE(printer.failed());
+
+  // Should not crash
+  printer.Print("blah");
+  EXPECT_TRUE(printer.failed());
+
+  // Buffer should contain the first 16 bytes written.
+  EXPECT_EQ("0123456789abcdef", string(buffer, sizeof(buffer)));
+}
+
+}  // namespace
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/strtod.cc b/src/third_party/protobuf-3/src/google/protobuf/io/strtod.cc
new file mode 100644
index 0000000..a90bb9a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/strtod.cc
@@ -0,0 +1,125 @@
+// 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.
+
+#include <google/protobuf/io/strtod.h>
+
+#include <cstdio>
+#include <cstring>
+#include <limits>
+#include <string>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+// ----------------------------------------------------------------------
+// NoLocaleStrtod()
+//   This code will make you cry.
+// ----------------------------------------------------------------------
+
+namespace {
+
+// Returns a string identical to *input except that the character pointed to
+// by radix_pos (which should be '.') is replaced with the locale-specific
+// radix character.
+string LocalizeRadix(const char* input, const char* radix_pos) {
+  // Determine the locale-specific radix character by calling sprintf() to
+  // print the number 1.5, then stripping off the digits.  As far as I can
+  // tell, this is the only portable, thread-safe way to get the C library
+  // to divuldge the locale's radix character.  No, localeconv() is NOT
+  // thread-safe.
+  char temp[16];
+  int size = sprintf(temp, "%.1f", 1.5);
+  GOOGLE_CHECK_EQ(temp[0], '1');
+  GOOGLE_CHECK_EQ(temp[size-1], '5');
+  GOOGLE_CHECK_LE(size, 6);
+
+  // Now replace the '.' in the input with it.
+  string result;
+  result.reserve(strlen(input) + size - 3);
+  result.append(input, radix_pos);
+  result.append(temp + 1, size - 2);
+  result.append(radix_pos + 1);
+  return result;
+}
+
+}  // namespace
+
+double NoLocaleStrtod(const char* text, char** original_endptr) {
+  // We cannot simply set the locale to "C" temporarily with setlocale()
+  // as this is not thread-safe.  Instead, we try to parse in the current
+  // locale first.  If parsing stops at a '.' character, then this is a
+  // pretty good hint that we're actually in some other locale in which
+  // '.' is not the radix character.
+
+  char* temp_endptr;
+  double result = strtod(text, &temp_endptr);
+  if (original_endptr != NULL) *original_endptr = temp_endptr;
+  if (*temp_endptr != '.') return result;
+
+  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
+  // try to replace the '.' with a locale-specific radix character and
+  // try again.
+  string localized = LocalizeRadix(text, temp_endptr);
+  const char* localized_cstr = localized.c_str();
+  char* localized_endptr;
+  result = strtod(localized_cstr, &localized_endptr);
+  if ((localized_endptr - localized_cstr) >
+      (temp_endptr - text)) {
+    // This attempt got further, so replacing the decimal must have helped.
+    // Update original_endptr to point at the right location.
+    if (original_endptr != NULL) {
+      // size_diff is non-zero if the localized radix has multiple bytes.
+      int size_diff = localized.size() - strlen(text);
+      // const_cast is necessary to match the strtod() interface.
+      *original_endptr = const_cast<char*>(
+        text + (localized_endptr - localized_cstr - size_diff));
+    }
+  }
+
+  return result;
+}
+
+float SafeDoubleToFloat(double value) {
+  if (value > std::numeric_limits<float>::max()) {
+    return std::numeric_limits<float>::infinity();
+  } else if (value < -std::numeric_limits<float>::max()) {
+    return -std::numeric_limits<float>::infinity();
+  } else {
+    return static_cast<float>(value);
+  }
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/strtod.h b/src/third_party/protobuf-3/src/google/protobuf/io/strtod.h
new file mode 100644
index 0000000..f56e41c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/strtod.h
@@ -0,0 +1,55 @@
+// 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.
+
+// A locale-independent version of strtod(), used to parse floating
+// point default values in .proto files, where the decimal separator
+// is always a dot.
+
+#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
+#define GOOGLE_PROTOBUF_IO_STRTOD_H__
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+// A locale-independent version of the standard strtod(), which always
+// uses a dot as the decimal separator.
+double NoLocaleStrtod(const char* str, char** endptr);
+
+// Casts a double value to a float value. If the value is outside of the
+// representable range of float, it will be converted to positive or negative
+// infinity.
+float SafeDoubleToFloat(double value);
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_STRTOD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.cc b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.cc
new file mode 100644
index 0000000..b3550df
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.cc
@@ -0,0 +1,1139 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Here we have a hand-written lexer.  At first you might ask yourself,
+// "Hand-written text processing?  Is Kenton crazy?!"  Well, first of all,
+// yes I am crazy, but that's beside the point.  There are actually reasons
+// why I ended up writing this this way.
+//
+// The traditional approach to lexing is to use lex to generate a lexer for
+// you.  Unfortunately, lex's output is ridiculously ugly and difficult to
+// integrate cleanly with C++ code, especially abstract code or code meant
+// as a library.  Better parser-generators exist but would add dependencies
+// which most users won't already have, which we'd like to avoid.  (GNU flex
+// has a C++ output option, but it's still ridiculously ugly, non-abstract,
+// and not library-friendly.)
+//
+// The next approach that any good software engineer should look at is to
+// use regular expressions.  And, indeed, I did.  I have code which
+// implements this same class using regular expressions.  It's about 200
+// lines shorter.  However:
+// - Rather than error messages telling you "This string has an invalid
+//   escape sequence at line 5, column 45", you get error messages like
+//   "Parse error on line 5".  Giving more precise errors requires adding
+//   a lot of code that ends up basically as complex as the hand-coded
+//   version anyway.
+// - The regular expression to match a string literal looks like this:
+//     kString  = new RE("(\"([^\"\\\\]|"              // non-escaped
+//                       "\\\\[abfnrtv?\"'\\\\0-7]|"   // normal escape
+//                       "\\\\x[0-9a-fA-F])*\"|"       // hex escape
+//                       "\'([^\'\\\\]|"        // Also support single-quotes.
+//                       "\\\\[abfnrtv?\"'\\\\0-7]|"
+//                       "\\\\x[0-9a-fA-F])*\')");
+//   Verifying the correctness of this line noise is actually harder than
+//   verifying the correctness of ConsumeString(), defined below.  I'm not
+//   even confident that the above is correct, after staring at it for some
+//   time.
+// - PCRE is fast, but there's still more overhead involved than the code
+//   below.
+// - Sadly, regular expressions are not part of the C standard library, so
+//   using them would require depending on some other library.  For the
+//   open source release, this could be really annoying.  Nobody likes
+//   downloading one piece of software just to find that they need to
+//   download something else to make it work, and in all likelihood
+//   people downloading Protocol Buffers will already be doing so just
+//   to make something else work.  We could include a copy of PCRE with
+//   our code, but that obligates us to keep it up-to-date and just seems
+//   like a big waste just to save 200 lines of code.
+//
+// On a similar but unrelated note, I'm even scared to use ctype.h.
+// Apparently functions like isalpha() are locale-dependent.  So, if we used
+// that, then if this code is being called from some program that doesn't
+// have its locale set to "C", it would behave strangely.  We can't just set
+// the locale to "C" ourselves since we might break the calling program that
+// way, particularly if it is multi-threaded.  WTF?  Someone please let me
+// (Kenton) know if I'm missing something here...
+//
+// I'd love to hear about other alternatives, though, as this code isn't
+// exactly pretty.
+
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/io/strtod.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace {
+
+// As mentioned above, I don't trust ctype.h due to the presence of "locales".
+// So, I have written replacement functions here.  Someone please smack me if
+// this is a bad idea or if there is some way around this.
+//
+// These "character classes" are designed to be used in template methods.
+// For instance, Tokenizer::ConsumeZeroOrMore<Whitespace>() will eat
+// whitespace.
+
+// Note:  No class is allowed to contain '\0', since this is used to mark end-
+//   of-input and is handled specially.
+
+#define CHARACTER_CLASS(NAME, EXPRESSION)      \
+  class NAME {                                 \
+   public:                                     \
+    static inline bool InClass(char c) {       \
+      return EXPRESSION;                       \
+    }                                          \
+  }
+
+CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
+                            c == '\r' || c == '\v' || c == '\f');
+CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' ||
+                                     c == '\r' || c == '\v' || c == '\f');
+
+CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
+
+CHARACTER_CLASS(Digit, '0' <= c && c <= '9');
+CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7');
+CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') ||
+                          ('a' <= c && c <= 'f') ||
+                          ('A' <= c && c <= 'F'));
+
+CHARACTER_CLASS(Letter, ('a' <= c && c <= 'z') ||
+                        ('A' <= c && c <= 'Z') ||
+                        (c == '_'));
+
+CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') ||
+                              ('A' <= c && c <= 'Z') ||
+                              ('0' <= c && c <= '9') ||
+                              (c == '_'));
+
+CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' ||
+                        c == 'r' || c == 't' || c == 'v' || c == '\\' ||
+                        c == '?' || c == '\'' || c == '\"');
+
+#undef CHARACTER_CLASS
+
+// Given a char, interpret it as a numeric digit and return its value.
+// This supports any number base up to 36.
+inline int DigitValue(char digit) {
+  if ('0' <= digit && digit <= '9') return digit - '0';
+  if ('a' <= digit && digit <= 'z') return digit - 'a' + 10;
+  if ('A' <= digit && digit <= 'Z') return digit - 'A' + 10;
+  return -1;
+}
+
+// Inline because it's only used in one place.
+inline char TranslateEscape(char c) {
+  switch (c) {
+    case 'a':  return '\a';
+    case 'b':  return '\b';
+    case 'f':  return '\f';
+    case 'n':  return '\n';
+    case 'r':  return '\r';
+    case 't':  return '\t';
+    case 'v':  return '\v';
+    case '\\': return '\\';
+    case '?':  return '\?';    // Trigraphs = :(
+    case '\'': return '\'';
+    case '"':  return '\"';
+
+    // We expect escape sequences to have been validated separately.
+    default:   return '?';
+  }
+}
+
+}  // anonymous namespace
+
+ErrorCollector::~ErrorCollector() {}
+
+// ===================================================================
+
+Tokenizer::Tokenizer(ZeroCopyInputStream* input,
+                     ErrorCollector* error_collector)
+  : input_(input),
+    error_collector_(error_collector),
+    buffer_(NULL),
+    buffer_size_(0),
+    buffer_pos_(0),
+    read_error_(false),
+    line_(0),
+    column_(0),
+    record_target_(NULL),
+    record_start_(-1),
+    allow_f_after_float_(false),
+    comment_style_(CPP_COMMENT_STYLE),
+    require_space_after_number_(true),
+    allow_multiline_strings_(false) {
+
+  current_.line = 0;
+  current_.column = 0;
+  current_.end_column = 0;
+  current_.type = TYPE_START;
+
+  Refresh();
+}
+
+Tokenizer::~Tokenizer() {
+  // If we had any buffer left unread, return it to the underlying stream
+  // so that someone else can read it.
+  if (buffer_size_ > buffer_pos_) {
+    input_->BackUp(buffer_size_ - buffer_pos_);
+  }
+}
+
+// -------------------------------------------------------------------
+// Internal helpers.
+
+void Tokenizer::NextChar() {
+  // Update our line and column counters based on the character being
+  // consumed.
+  if (current_char_ == '\n') {
+    ++line_;
+    column_ = 0;
+  } else if (current_char_ == '\t') {
+    column_ += kTabWidth - column_ % kTabWidth;
+  } else {
+    ++column_;
+  }
+
+  // Advance to the next character.
+  ++buffer_pos_;
+  if (buffer_pos_ < buffer_size_) {
+    current_char_ = buffer_[buffer_pos_];
+  } else {
+    Refresh();
+  }
+}
+
+void Tokenizer::Refresh() {
+  if (read_error_) {
+    current_char_ = '\0';
+    return;
+  }
+
+  // If we're in a token, append the rest of the buffer to it.
+  if (record_target_ != NULL && record_start_ < buffer_size_) {
+    record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_);
+    record_start_ = 0;
+  }
+
+  const void* data = NULL;
+  buffer_ = NULL;
+  buffer_pos_ = 0;
+  do {
+    if (!input_->Next(&data, &buffer_size_)) {
+      // end of stream (or read error)
+      buffer_size_ = 0;
+      read_error_ = true;
+      current_char_ = '\0';
+      return;
+    }
+  } while (buffer_size_ == 0);
+
+  buffer_ = static_cast<const char*>(data);
+
+  current_char_ = buffer_[0];
+}
+
+inline void Tokenizer::RecordTo(string* target) {
+  record_target_ = target;
+  record_start_ = buffer_pos_;
+}
+
+inline void Tokenizer::StopRecording() {
+  // Note:  The if() is necessary because some STL implementations crash when
+  //   you call string::append(NULL, 0), presumably because they are trying to
+  //   be helpful by detecting the NULL pointer, even though there's nothing
+  //   wrong with reading zero bytes from NULL.
+  if (buffer_pos_ != record_start_) {
+    record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_);
+  }
+  record_target_ = NULL;
+  record_start_ = -1;
+}
+
+inline void Tokenizer::StartToken() {
+  current_.type = TYPE_START;    // Just for the sake of initializing it.
+  current_.text.clear();
+  current_.line = line_;
+  current_.column = column_;
+  RecordTo(&current_.text);
+}
+
+inline void Tokenizer::EndToken() {
+  StopRecording();
+  current_.end_column = column_;
+}
+
+// -------------------------------------------------------------------
+// Helper methods that consume characters.
+
+template<typename CharacterClass>
+inline bool Tokenizer::LookingAt() {
+  return CharacterClass::InClass(current_char_);
+}
+
+template<typename CharacterClass>
+inline bool Tokenizer::TryConsumeOne() {
+  if (CharacterClass::InClass(current_char_)) {
+    NextChar();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+inline bool Tokenizer::TryConsume(char c) {
+  if (current_char_ == c) {
+    NextChar();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+template<typename CharacterClass>
+inline void Tokenizer::ConsumeZeroOrMore() {
+  while (CharacterClass::InClass(current_char_)) {
+    NextChar();
+  }
+}
+
+template<typename CharacterClass>
+inline void Tokenizer::ConsumeOneOrMore(const char* error) {
+  if (!CharacterClass::InClass(current_char_)) {
+    AddError(error);
+  } else {
+    do {
+      NextChar();
+    } while (CharacterClass::InClass(current_char_));
+  }
+}
+
+// -------------------------------------------------------------------
+// Methods that read whole patterns matching certain kinds of tokens
+// or comments.
+
+void Tokenizer::ConsumeString(char delimiter) {
+  while (true) {
+    switch (current_char_) {
+      case '\0':
+        AddError("Unexpected end of string.");
+        return;
+
+      case '\n': {
+        if (!allow_multiline_strings_) {
+          AddError("String literals cannot cross line boundaries.");
+          return;
+        }
+        NextChar();
+        break;
+      }
+
+      case '\\': {
+        // An escape sequence.
+        NextChar();
+        if (TryConsumeOne<Escape>()) {
+          // Valid escape sequence.
+        } else if (TryConsumeOne<OctalDigit>()) {
+          // Possibly followed by two more octal digits, but these will
+          // just be consumed by the main loop anyway so we don't need
+          // to do so explicitly here.
+        } else if (TryConsume('x')) {
+          if (!TryConsumeOne<HexDigit>()) {
+            AddError("Expected hex digits for escape sequence.");
+          }
+          // Possibly followed by another hex digit, but again we don't care.
+        } else if (TryConsume('u')) {
+          if (!TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>()) {
+            AddError("Expected four hex digits for \\u escape sequence.");
+          }
+        } else if (TryConsume('U')) {
+          // We expect 8 hex digits; but only the range up to 0x10ffff is
+          // legal.
+          if (!TryConsume('0') ||
+              !TryConsume('0') ||
+              !(TryConsume('0') || TryConsume('1')) ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>()) {
+            AddError("Expected eight hex digits up to 10ffff for \\U escape "
+                     "sequence");
+          }
+        } else {
+          AddError("Invalid escape sequence in string literal.");
+        }
+        break;
+      }
+
+      default: {
+        if (current_char_ == delimiter) {
+          NextChar();
+          return;
+        }
+        NextChar();
+        break;
+      }
+    }
+  }
+}
+
+Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero,
+                                              bool started_with_dot) {
+  bool is_float = false;
+
+  if (started_with_zero && (TryConsume('x') || TryConsume('X'))) {
+    // A hex number (started with "0x").
+    ConsumeOneOrMore<HexDigit>("\"0x\" must be followed by hex digits.");
+
+  } else if (started_with_zero && LookingAt<Digit>()) {
+    // An octal number (had a leading zero).
+    ConsumeZeroOrMore<OctalDigit>();
+    if (LookingAt<Digit>()) {
+      AddError("Numbers starting with leading zero must be in octal.");
+      ConsumeZeroOrMore<Digit>();
+    }
+
+  } else {
+    // A decimal number.
+    if (started_with_dot) {
+      is_float = true;
+      ConsumeZeroOrMore<Digit>();
+    } else {
+      ConsumeZeroOrMore<Digit>();
+
+      if (TryConsume('.')) {
+        is_float = true;
+        ConsumeZeroOrMore<Digit>();
+      }
+    }
+
+    if (TryConsume('e') || TryConsume('E')) {
+      is_float = true;
+      TryConsume('-') || TryConsume('+');
+      ConsumeOneOrMore<Digit>("\"e\" must be followed by exponent.");
+    }
+
+    if (allow_f_after_float_ && (TryConsume('f') || TryConsume('F'))) {
+      is_float = true;
+    }
+  }
+
+  if (LookingAt<Letter>() && require_space_after_number_) {
+    AddError("Need space between number and identifier.");
+  } else if (current_char_ == '.') {
+    if (is_float) {
+      AddError(
+        "Already saw decimal point or exponent; can't have another one.");
+    } else {
+      AddError("Hex and octal numbers must be integers.");
+    }
+  }
+
+  return is_float ? TYPE_FLOAT : TYPE_INTEGER;
+}
+
+void Tokenizer::ConsumeLineComment(string* content) {
+  if (content != NULL) RecordTo(content);
+
+  while (current_char_ != '\0' && current_char_ != '\n') {
+    NextChar();
+  }
+  TryConsume('\n');
+
+  if (content != NULL) StopRecording();
+}
+
+void Tokenizer::ConsumeBlockComment(string* content) {
+  int start_line = line_;
+  int start_column = column_ - 2;
+
+  if (content != NULL) RecordTo(content);
+
+  while (true) {
+    while (current_char_ != '\0' &&
+           current_char_ != '*' &&
+           current_char_ != '/' &&
+           current_char_ != '\n') {
+      NextChar();
+    }
+
+    if (TryConsume('\n')) {
+      if (content != NULL) StopRecording();
+
+      // Consume leading whitespace and asterisk;
+      ConsumeZeroOrMore<WhitespaceNoNewline>();
+      if (TryConsume('*')) {
+        if (TryConsume('/')) {
+          // End of comment.
+          break;
+        }
+      }
+
+      if (content != NULL) RecordTo(content);
+    } else if (TryConsume('*') && TryConsume('/')) {
+      // End of comment.
+      if (content != NULL) {
+        StopRecording();
+        // Strip trailing "*/".
+        content->erase(content->size() - 2);
+      }
+      break;
+    } else if (TryConsume('/') && current_char_ == '*') {
+      // Note:  We didn't consume the '*' because if there is a '/' after it
+      //   we want to interpret that as the end of the comment.
+      AddError(
+        "\"/*\" inside block comment.  Block comments cannot be nested.");
+    } else if (current_char_ == '\0') {
+      AddError("End-of-file inside block comment.");
+      error_collector_->AddError(
+        start_line, start_column, "  Comment started here.");
+      if (content != NULL) StopRecording();
+      break;
+    }
+  }
+}
+
+Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() {
+  if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
+    if (TryConsume('/')) {
+      return LINE_COMMENT;
+    } else if (TryConsume('*')) {
+      return BLOCK_COMMENT;
+    } else {
+      // Oops, it was just a slash.  Return it.
+      current_.type = TYPE_SYMBOL;
+      current_.text = "/";
+      current_.line = line_;
+      current_.column = column_ - 1;
+      current_.end_column = column_;
+      return SLASH_NOT_COMMENT;
+    }
+  } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
+    return LINE_COMMENT;
+  } else {
+    return NO_COMMENT;
+  }
+}
+
+// -------------------------------------------------------------------
+
+bool Tokenizer::Next() {
+  previous_ = current_;
+
+  while (!read_error_) {
+    ConsumeZeroOrMore<Whitespace>();
+
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(NULL);
+        continue;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(NULL);
+        continue;
+      case SLASH_NOT_COMMENT:
+        return true;
+      case NO_COMMENT:
+        break;
+    }
+
+    // Check for EOF before continuing.
+    if (read_error_) break;
+
+    if (LookingAt<Unprintable>() || current_char_ == '\0') {
+      AddError("Invalid control characters encountered in text.");
+      NextChar();
+      // Skip more unprintable characters, too.  But, remember that '\0' is
+      // also what current_char_ is set to after EOF / read error.  We have
+      // to be careful not to go into an infinite loop of trying to consume
+      // it, so make sure to check read_error_ explicitly before consuming
+      // '\0'.
+      while (TryConsumeOne<Unprintable>() ||
+             (!read_error_ && TryConsume('\0'))) {
+        // Ignore.
+      }
+
+    } else {
+      // Reading some sort of token.
+      StartToken();
+
+      if (TryConsumeOne<Letter>()) {
+        ConsumeZeroOrMore<Alphanumeric>();
+        current_.type = TYPE_IDENTIFIER;
+      } else if (TryConsume('0')) {
+        current_.type = ConsumeNumber(true, false);
+      } else if (TryConsume('.')) {
+        // This could be the beginning of a floating-point number, or it could
+        // just be a '.' symbol.
+
+        if (TryConsumeOne<Digit>()) {
+          // It's a floating-point number.
+          if (previous_.type == TYPE_IDENTIFIER &&
+              current_.line == previous_.line &&
+              current_.column == previous_.end_column) {
+            // We don't accept syntax like "blah.123".
+            error_collector_->AddError(line_, column_ - 2,
+              "Need space between identifier and decimal point.");
+          }
+          current_.type = ConsumeNumber(false, true);
+        } else {
+          current_.type = TYPE_SYMBOL;
+        }
+      } else if (TryConsumeOne<Digit>()) {
+        current_.type = ConsumeNumber(false, false);
+      } else if (TryConsume('\"')) {
+        ConsumeString('\"');
+        current_.type = TYPE_STRING;
+      } else if (TryConsume('\'')) {
+        ConsumeString('\'');
+        current_.type = TYPE_STRING;
+      } else {
+        // Check if the high order bit is set.
+        if (current_char_ & 0x80) {
+          error_collector_->AddError(line_, column_,
+              StringPrintf("Interpreting non ascii codepoint %d.",
+                           static_cast<unsigned char>(current_char_)));
+        }
+        NextChar();
+        current_.type = TYPE_SYMBOL;
+      }
+
+      EndToken();
+      return true;
+    }
+  }
+
+  // EOF
+  current_.type = TYPE_END;
+  current_.text.clear();
+  current_.line = line_;
+  current_.column = column_;
+  current_.end_column = column_;
+  return false;
+}
+
+namespace {
+
+// Helper class for collecting comments and putting them in the right places.
+//
+// This basically just buffers the most recent comment until it can be decided
+// exactly where that comment should be placed.  When Flush() is called, the
+// current comment goes into either prev_trailing_comments or detached_comments.
+// When the CommentCollector is destroyed, the last buffered comment goes into
+// next_leading_comments.
+class CommentCollector {
+ public:
+  CommentCollector(string* prev_trailing_comments,
+                   vector<string>* detached_comments,
+                   string* next_leading_comments)
+      : prev_trailing_comments_(prev_trailing_comments),
+        detached_comments_(detached_comments),
+        next_leading_comments_(next_leading_comments),
+        has_comment_(false),
+        is_line_comment_(false),
+        can_attach_to_prev_(true) {
+    if (prev_trailing_comments != NULL) prev_trailing_comments->clear();
+    if (detached_comments != NULL) detached_comments->clear();
+    if (next_leading_comments != NULL) next_leading_comments->clear();
+  }
+
+  ~CommentCollector() {
+    // Whatever is in the buffer is a leading comment.
+    if (next_leading_comments_ != NULL && has_comment_) {
+      comment_buffer_.swap(*next_leading_comments_);
+    }
+  }
+
+  // About to read a line comment.  Get the comment buffer pointer in order to
+  // read into it.
+  string* GetBufferForLineComment() {
+    // We want to combine with previous line comments, but not block comments.
+    if (has_comment_ && !is_line_comment_) {
+      Flush();
+    }
+    has_comment_ = true;
+    is_line_comment_ = true;
+    return &comment_buffer_;
+  }
+
+  // About to read a block comment.  Get the comment buffer pointer in order to
+  // read into it.
+  string* GetBufferForBlockComment() {
+    if (has_comment_) {
+      Flush();
+    }
+    has_comment_ = true;
+    is_line_comment_ = false;
+    return &comment_buffer_;
+  }
+
+  void ClearBuffer() {
+    comment_buffer_.clear();
+    has_comment_ = false;
+  }
+
+  // Called once we know that the comment buffer is complete and is *not*
+  // connected to the next token.
+  void Flush() {
+    if (has_comment_) {
+      if (can_attach_to_prev_) {
+        if (prev_trailing_comments_ != NULL) {
+          prev_trailing_comments_->append(comment_buffer_);
+        }
+        can_attach_to_prev_ = false;
+      } else {
+        if (detached_comments_ != NULL) {
+          detached_comments_->push_back(comment_buffer_);
+        }
+      }
+      ClearBuffer();
+    }
+  }
+
+  void DetachFromPrev() {
+    can_attach_to_prev_ = false;
+  }
+
+ private:
+  string* prev_trailing_comments_;
+  vector<string>* detached_comments_;
+  string* next_leading_comments_;
+
+  string comment_buffer_;
+
+  // True if any comments were read into comment_buffer_.  This can be true even
+  // if comment_buffer_ is empty, namely if the comment was "/**/".
+  bool has_comment_;
+
+  // Is the comment in the comment buffer a line comment?
+  bool is_line_comment_;
+
+  // Is it still possible that we could be reading a comment attached to the
+  // previous token?
+  bool can_attach_to_prev_;
+};
+
+} // namespace
+
+bool Tokenizer::NextWithComments(string* prev_trailing_comments,
+                                 vector<string>* detached_comments,
+                                 string* next_leading_comments) {
+  CommentCollector collector(prev_trailing_comments, detached_comments,
+                             next_leading_comments);
+
+  if (current_.type == TYPE_START) {
+    // Ignore unicode byte order mark(BOM) if it appears at the file
+    // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted.
+    if (TryConsume((char)0xEF)) {
+      if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) {
+        AddError("Proto file starts with 0xEF but not UTF-8 BOM. "
+                 "Only UTF-8 is accepted for proto file.");
+        return false;
+      }
+    }
+    collector.DetachFromPrev();
+  } else {
+    // A comment appearing on the same line must be attached to the previous
+    // declaration.
+    ConsumeZeroOrMore<WhitespaceNoNewline>();
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(collector.GetBufferForLineComment());
+
+        // Don't allow comments on subsequent lines to be attached to a trailing
+        // comment.
+        collector.Flush();
+        break;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+        ConsumeZeroOrMore<WhitespaceNoNewline>();
+        if (!TryConsume('\n')) {
+          // Oops, the next token is on the same line.  If we recorded a comment
+          // we really have no idea which token it should be attached to.
+          collector.ClearBuffer();
+          return Next();
+        }
+
+        // Don't allow comments on subsequent lines to be attached to a trailing
+        // comment.
+        collector.Flush();
+        break;
+      case SLASH_NOT_COMMENT:
+        return true;
+      case NO_COMMENT:
+        if (!TryConsume('\n')) {
+          // The next token is on the same line.  There are no comments.
+          return Next();
+        }
+        break;
+    }
+  }
+
+  // OK, we are now on the line *after* the previous token.
+  while (true) {
+    ConsumeZeroOrMore<WhitespaceNoNewline>();
+
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(collector.GetBufferForLineComment());
+        break;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+        // Consume the rest of the line so that we don't interpret it as a
+        // blank line the next time around the loop.
+        ConsumeZeroOrMore<WhitespaceNoNewline>();
+        TryConsume('\n');
+        break;
+      case SLASH_NOT_COMMENT:
+        return true;
+      case NO_COMMENT:
+        if (TryConsume('\n')) {
+          // Completely blank line.
+          collector.Flush();
+          collector.DetachFromPrev();
+        } else {
+          bool result = Next();
+          if (!result ||
+              current_.text == "}" ||
+              current_.text == "]" ||
+              current_.text == ")") {
+            // It looks like we're at the end of a scope.  In this case it
+            // makes no sense to attach a comment to the following token.
+            collector.Flush();
+          }
+          return result;
+        }
+        break;
+    }
+  }
+}
+
+// -------------------------------------------------------------------
+// Token-parsing helpers.  Remember that these don't need to report
+// errors since any errors should already have been reported while
+// tokenizing.  Also, these can assume that whatever text they
+// are given is text that the tokenizer actually parsed as a token
+// of the given type.
+
+bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
+                             uint64* output) {
+  // Sadly, we can't just use strtoul() since it is only 32-bit and strtoull()
+  // is non-standard.  I hate the C standard library.  :(
+
+//  return strtoull(text.c_str(), NULL, 0);
+
+  const char* ptr = text.c_str();
+  int base = 10;
+  if (ptr[0] == '0') {
+    if (ptr[1] == 'x' || ptr[1] == 'X') {
+      // This is hex.
+      base = 16;
+      ptr += 2;
+    } else {
+      // This is octal.
+      base = 8;
+    }
+  }
+
+  uint64 result = 0;
+  for (; *ptr != '\0'; ptr++) {
+    int digit = DigitValue(*ptr);
+    if (digit < 0 || digit >= base) {
+      // The token provided by Tokenizer is invalid. i.e., 099 is an invalid
+      // token, but Tokenizer still think it's integer.
+      return false;
+    }
+    if (digit > max_value || result > (max_value - digit) / base) {
+      // Overflow.
+      return false;
+    }
+    result = result * base + digit;
+  }
+
+  *output = result;
+  return true;
+}
+
+double Tokenizer::ParseFloat(const string& text) {
+  const char* start = text.c_str();
+  char* end;
+  double result = NoLocaleStrtod(start, &end);
+
+  // "1e" is not a valid float, but if the tokenizer reads it, it will
+  // report an error but still return it as a valid token.  We need to
+  // accept anything the tokenizer could possibly return, error or not.
+  if (*end == 'e' || *end == 'E') {
+    ++end;
+    if (*end == '-' || *end == '+') ++end;
+  }
+
+  // If the Tokenizer had allow_f_after_float_ enabled, the float may be
+  // suffixed with the letter 'f'.
+  if (*end == 'f' || *end == 'F') {
+    ++end;
+  }
+
+  GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-')
+    << " Tokenizer::ParseFloat() passed text that could not have been"
+       " tokenized as a float: " << CEscape(text);
+  return result;
+}
+
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies.
+static void AppendUTF8(uint32 code_point, string* output) {
+  uint32 tmp = 0;
+  int len = 0;
+  if (code_point <= 0x7f) {
+    tmp = code_point;
+    len = 1;
+  } else if (code_point <= 0x07ff) {
+    tmp = 0x0000c080 |
+        ((code_point & 0x07c0) << 2) |
+        (code_point & 0x003f);
+    len = 2;
+  } else if (code_point <= 0xffff) {
+    tmp = 0x00e08080 |
+        ((code_point & 0xf000) << 4) |
+        ((code_point & 0x0fc0) << 2) |
+        (code_point & 0x003f);
+    len = 3;
+  } else if (code_point <= 0x1fffff) {
+    tmp = 0xf0808080 |
+        ((code_point & 0x1c0000) << 6) |
+        ((code_point & 0x03f000) << 4) |
+        ((code_point & 0x000fc0) << 2) |
+        (code_point & 0x003f);
+    len = 4;
+  } else {
+    // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
+    // normally only defined up to there as well.
+    StringAppendF(output, "\\U%08x", code_point);
+    return;
+  }
+  tmp = ghtonl(tmp);
+  output->append(reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
+}
+
+// Try to read <len> hex digits from ptr, and stuff the numeric result into
+// *result. Returns true if that many digits were successfully consumed.
+static bool ReadHexDigits(const char* ptr, int len, uint32* result) {
+  *result = 0;
+  if (len == 0) return false;
+  for (const char* end = ptr + len; ptr < end; ++ptr) {
+    if (*ptr == '\0') return false;
+    *result = (*result << 4) + DigitValue(*ptr);
+  }
+  return true;
+}
+
+// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range
+// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail
+// surrogate. These numbers are in a reserved range of Unicode code points, so
+// if we encounter such a pair we know how to parse it and convert it into a
+// single code point.
+static const uint32 kMinHeadSurrogate = 0xd800;
+static const uint32 kMaxHeadSurrogate = 0xdc00;
+static const uint32 kMinTrailSurrogate = 0xdc00;
+static const uint32 kMaxTrailSurrogate = 0xe000;
+
+static inline bool IsHeadSurrogate(uint32 code_point) {
+  return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate);
+}
+
+static inline bool IsTrailSurrogate(uint32 code_point) {
+  return (code_point >= kMinTrailSurrogate) &&
+      (code_point < kMaxTrailSurrogate);
+}
+
+// Combine a head and trail surrogate into a single Unicode code point.
+static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) {
+  GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate));
+  GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate));
+  return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) |
+      (trail_surrogate - kMinTrailSurrogate));
+}
+
+// Convert the escape sequence parameter to a number of expected hex digits.
+static inline int UnicodeLength(char key) {
+  if (key == 'u') return 4;
+  if (key == 'U') return 8;
+  return 0;
+}
+
+// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt
+// to parse that sequence. On success, returns a pointer to the first char
+// beyond that sequence, and fills in *code_point. On failure, returns ptr
+// itself.
+static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
+  const char* p = ptr;
+  // Fetch the code point.
+  const int len = UnicodeLength(*p++);
+  if (!ReadHexDigits(p, len, code_point))
+    return ptr;
+  p += len;
+
+  // Check if the code point we read is a "head surrogate." If so, then we
+  // expect it to be immediately followed by another code point which is a valid
+  // "trail surrogate," and together they form a UTF-16 pair which decodes into
+  // a single Unicode point. Trail surrogates may only use \u, not \U.
+  if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') {
+    uint32 trail_surrogate;
+    if (ReadHexDigits(p + 2, 4, &trail_surrogate) &&
+        IsTrailSurrogate(trail_surrogate)) {
+      *code_point = AssembleUTF16(*code_point, trail_surrogate);
+      p += 6;
+    }
+    // If this failed, then we just emit the head surrogate as a code point.
+    // It's bogus, but so is the string.
+  }
+
+  return p;
+}
+
+// The text string must begin and end with single or double quote
+// characters.
+void Tokenizer::ParseStringAppend(const string& text, string* output) {
+  // Reminder: text[0] is always a quote character.  (If text is
+  // empty, it's invalid, so we'll just return).
+  const size_t text_size = text.size();
+  if (text_size == 0) {
+    GOOGLE_LOG(DFATAL)
+      << " Tokenizer::ParseStringAppend() passed text that could not"
+         " have been tokenized as a string: " << CEscape(text);
+    return;
+  }
+
+  // Reserve room for new string. The branch is necessary because if
+  // there is already space available the reserve() call might
+  // downsize the output.
+  const size_t new_len = text_size + output->size();
+  if (new_len > output->capacity()) {
+    output->reserve(new_len);
+  }
+
+  // Loop through the string copying characters to "output" and
+  // interpreting escape sequences.  Note that any invalid escape
+  // sequences or other errors were already reported while tokenizing.
+  // In this case we do not need to produce valid results.
+  for (const char* ptr = text.c_str() + 1; *ptr != '\0'; ptr++) {
+    if (*ptr == '\\' && ptr[1] != '\0') {
+      // An escape sequence.
+      ++ptr;
+
+      if (OctalDigit::InClass(*ptr)) {
+        // An octal escape.  May one, two, or three digits.
+        int code = DigitValue(*ptr);
+        if (OctalDigit::InClass(ptr[1])) {
+          ++ptr;
+          code = code * 8 + DigitValue(*ptr);
+        }
+        if (OctalDigit::InClass(ptr[1])) {
+          ++ptr;
+          code = code * 8 + DigitValue(*ptr);
+        }
+        output->push_back(static_cast<char>(code));
+
+      } else if (*ptr == 'x') {
+        // A hex escape.  May zero, one, or two digits.  (The zero case
+        // will have been caught as an error earlier.)
+        int code = 0;
+        if (HexDigit::InClass(ptr[1])) {
+          ++ptr;
+          code = DigitValue(*ptr);
+        }
+        if (HexDigit::InClass(ptr[1])) {
+          ++ptr;
+          code = code * 16 + DigitValue(*ptr);
+        }
+        output->push_back(static_cast<char>(code));
+
+      } else if (*ptr == 'u' || *ptr == 'U') {
+        uint32 unicode;
+        const char* end = FetchUnicodePoint(ptr, &unicode);
+        if (end == ptr) {
+          // Failure: Just dump out what we saw, don't try to parse it.
+          output->push_back(*ptr);
+        } else {
+          AppendUTF8(unicode, output);
+          ptr = end - 1;  // Because we're about to ++ptr.
+        }
+      } else {
+        // Some other escape code.
+        output->push_back(TranslateEscape(*ptr));
+      }
+
+    } else if (*ptr == text[0] && ptr[1] == '\0') {
+      // Ignore final quote matching the starting quote.
+    } else {
+      output->push_back(*ptr);
+    }
+  }
+}
+
+template<typename CharacterClass>
+static bool AllInClass(const string& s) {
+  for (int i = 0; i < s.size(); ++i) {
+    if (!CharacterClass::InClass(s[i]))
+      return false;
+  }
+  return true;
+}
+
+bool Tokenizer::IsIdentifier(const string& text) {
+  // Mirrors IDENTIFIER definition in Tokenizer::Next() above.
+  if (text.size() == 0)
+    return false;
+  if (!Letter::InClass(text.at(0)))
+    return false;
+  if (!AllInClass<Alphanumeric>(text.substr(1)))
+    return false;
+  return true;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.h b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.h
new file mode 100644
index 0000000..64ee7d8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer.h
@@ -0,0 +1,411 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Class for parsing tokenized text from a ZeroCopyInputStream.
+
+#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
+#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+class ZeroCopyInputStream;     // zero_copy_stream.h
+
+// Defined in this file.
+class ErrorCollector;
+class Tokenizer;
+
+// By "column number", the proto compiler refers to a count of the number
+// of bytes before a given byte, except that a tab character advances to
+// the next multiple of 8 bytes.  Note in particular that column numbers
+// are zero-based, while many user interfaces use one-based column numbers.
+typedef int ColumnNumber;
+
+// Abstract interface for an object which collects the errors that occur
+// during parsing.  A typical implementation might simply print the errors
+// to stdout.
+class LIBPROTOBUF_EXPORT ErrorCollector {
+ public:
+  inline ErrorCollector() {}
+  virtual ~ErrorCollector();
+
+  // Indicates that there was an error in the input at the given line and
+  // column numbers.  The numbers are zero-based, so you may want to add
+  // 1 to each before printing them.
+  virtual void AddError(int line, ColumnNumber column,
+                        const string& message) = 0;
+
+  // Indicates that there was a warning in the input at the given line and
+  // column numbers.  The numbers are zero-based, so you may want to add
+  // 1 to each before printing them.
+  virtual void AddWarning(int line, ColumnNumber column,
+                          const string& message) { }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
+};
+
+// This class converts a stream of raw text into a stream of tokens for
+// the protocol definition parser to parse.  The tokens recognized are
+// similar to those that make up the C language; see the TokenType enum for
+// precise descriptions.  Whitespace and comments are skipped.  By default,
+// C- and C++-style comments are recognized, but other styles can be used by
+// calling set_comment_style().
+class LIBPROTOBUF_EXPORT Tokenizer {
+ public:
+  // Construct a Tokenizer that reads and tokenizes text from the given
+  // input stream and writes errors to the given error_collector.
+  // The caller keeps ownership of input and error_collector.
+  Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector);
+  ~Tokenizer();
+
+  enum TokenType {
+    TYPE_START,       // Next() has not yet been called.
+    TYPE_END,         // End of input reached.  "text" is empty.
+
+    TYPE_IDENTIFIER,  // A sequence of letters, digits, and underscores, not
+                      // starting with a digit.  It is an error for a number
+                      // to be followed by an identifier with no space in
+                      // between.
+    TYPE_INTEGER,     // A sequence of digits representing an integer.  Normally
+                      // the digits are decimal, but a prefix of "0x" indicates
+                      // a hex number and a leading zero indicates octal, just
+                      // like with C numeric literals.  A leading negative sign
+                      // is NOT included in the token; it's up to the parser to
+                      // interpret the unary minus operator on its own.
+    TYPE_FLOAT,       // A floating point literal, with a fractional part and/or
+                      // an exponent.  Always in decimal.  Again, never
+                      // negative.
+    TYPE_STRING,      // A quoted sequence of escaped characters.  Either single
+                      // or double quotes can be used, but they must match.
+                      // A string literal cannot cross a line break.
+    TYPE_SYMBOL,      // Any other printable character, like '!' or '+'.
+                      // Symbols are always a single character, so "!+$%" is
+                      // four tokens.
+  };
+
+  // Structure representing a token read from the token stream.
+  struct Token {
+    TokenType type;
+    string text;       // The exact text of the token as it appeared in
+                       // the input.  e.g. tokens of TYPE_STRING will still
+                       // be escaped and in quotes.
+
+    // "line" and "column" specify the position of the first character of
+    // the token within the input stream.  They are zero-based.
+    int line;
+    ColumnNumber column;
+    ColumnNumber end_column;
+  };
+
+  // Get the current token.  This is updated when Next() is called.  Before
+  // the first call to Next(), current() has type TYPE_START and no contents.
+  const Token& current();
+
+  // Return the previous token -- i.e. what current() returned before the
+  // previous call to Next().
+  const Token& previous();
+
+  // Advance to the next token.  Returns false if the end of the input is
+  // reached.
+  bool Next();
+
+  // Like Next(), but also collects comments which appear between the previous
+  // and next tokens.
+  //
+  // Comments which appear to be attached to the previous token are stored
+  // in *prev_tailing_comments.  Comments which appear to be attached to the
+  // next token are stored in *next_leading_comments.  Comments appearing in
+  // between which do not appear to be attached to either will be added to
+  // detached_comments.  Any of these parameters can be NULL to simply discard
+  // the comments.
+  //
+  // A series of line comments appearing on consecutive lines, with no other
+  // tokens appearing on those lines, will be treated as a single comment.
+  //
+  // Only the comment content is returned; comment markers (e.g. //) are
+  // stripped out.  For block comments, leading whitespace and an asterisk will
+  // be stripped from the beginning of each line other than the first.  Newlines
+  // are included in the output.
+  //
+  // Examples:
+  //
+  //   optional int32 foo = 1;  // Comment attached to foo.
+  //   // Comment attached to bar.
+  //   optional int32 bar = 2;
+  //
+  //   optional string baz = 3;
+  //   // Comment attached to baz.
+  //   // Another line attached to baz.
+  //
+  //   // Comment attached to qux.
+  //   //
+  //   // Another line attached to qux.
+  //   optional double qux = 4;
+  //
+  //   // Detached comment.  This is not attached to qux or corge
+  //   // because there are blank lines separating it from both.
+  //
+  //   optional string corge = 5;
+  //   /* Block comment attached
+  //    * to corge.  Leading asterisks
+  //    * will be removed. */
+  //   /* Block comment attached to
+  //    * grault. */
+  //   optional int32 grault = 6;
+  bool NextWithComments(string* prev_trailing_comments,
+                        vector<string>* detached_comments,
+                        string* next_leading_comments);
+
+  // Parse helpers ---------------------------------------------------
+
+  // Parses a TYPE_FLOAT token.  This never fails, so long as the text actually
+  // comes from a TYPE_FLOAT token parsed by Tokenizer.  If it doesn't, the
+  // result is undefined (possibly an assert failure).
+  static double ParseFloat(const string& text);
+
+  // Parses a TYPE_STRING token.  This never fails, so long as the text actually
+  // comes from a TYPE_STRING token parsed by Tokenizer.  If it doesn't, the
+  // result is undefined (possibly an assert failure).
+  static void ParseString(const string& text, string* output);
+
+  // Identical to ParseString, but appends to output.
+  static void ParseStringAppend(const string& text, string* output);
+
+  // Parses a TYPE_INTEGER token.  Returns false if the result would be
+  // greater than max_value.  Otherwise, returns true and sets *output to the
+  // result.  If the text is not from a Token of type TYPE_INTEGER originally
+  // parsed by a Tokenizer, the result is undefined (possibly an assert
+  // failure).
+  static bool ParseInteger(const string& text, uint64 max_value,
+                           uint64* output);
+
+  // Options ---------------------------------------------------------
+
+  // Set true to allow floats to be suffixed with the letter 'f'.  Tokens
+  // which would otherwise be integers but which have the 'f' suffix will be
+  // forced to be interpreted as floats.  For all other purposes, the 'f' is
+  // ignored.
+  void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; }
+
+  // Valid values for set_comment_style().
+  enum CommentStyle {
+    // Line comments begin with "//", block comments are delimited by "/*" and
+    // "*/".
+    CPP_COMMENT_STYLE,
+    // Line comments begin with "#".  No way to write block comments.
+    SH_COMMENT_STYLE
+  };
+
+  // Sets the comment style.
+  void set_comment_style(CommentStyle style) { comment_style_ = style; }
+
+  // Whether to require whitespace between a number and a field name.
+  // Default is true. Do not use this; for Google-internal cleanup only.
+  void set_require_space_after_number(bool require) {
+    require_space_after_number_ = require;
+  }
+
+  // Whether to allow string literals to span multiple lines. Default is false.
+  // Do not use this; for Google-internal cleanup only.
+  void set_allow_multiline_strings(bool allow) {
+    allow_multiline_strings_ = allow;
+  }
+
+  // External helper: validate an identifier.
+  static bool IsIdentifier(const string& text);
+
+  // -----------------------------------------------------------------
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
+
+  Token current_;           // Returned by current().
+  Token previous_;          // Returned by previous().
+
+  ZeroCopyInputStream* input_;
+  ErrorCollector* error_collector_;
+
+  char current_char_;       // == buffer_[buffer_pos_], updated by NextChar().
+  const char* buffer_;      // Current buffer returned from input_.
+  int buffer_size_;         // Size of buffer_.
+  int buffer_pos_;          // Current position within the buffer.
+  bool read_error_;         // Did we previously encounter a read error?
+
+  // Line and column number of current_char_ within the whole input stream.
+  int line_;
+  ColumnNumber column_;
+
+  // String to which text should be appended as we advance through it.
+  // Call RecordTo(&str) to start recording and StopRecording() to stop.
+  // E.g. StartToken() calls RecordTo(&current_.text).  record_start_ is the
+  // position within the current buffer where recording started.
+  string* record_target_;
+  int record_start_;
+
+  // Options.
+  bool allow_f_after_float_;
+  CommentStyle comment_style_;
+  bool require_space_after_number_;
+  bool allow_multiline_strings_;
+
+  // Since we count columns we need to interpret tabs somehow.  We'll take
+  // the standard 8-character definition for lack of any way to do better.
+  // This must match the documentation of ColumnNumber.
+  static const int kTabWidth = 8;
+
+  // -----------------------------------------------------------------
+  // Helper methods.
+
+  // Consume this character and advance to the next one.
+  void NextChar();
+
+  // Read a new buffer from the input.
+  void Refresh();
+
+  inline void RecordTo(string* target);
+  inline void StopRecording();
+
+  // Called when the current character is the first character of a new
+  // token (not including whitespace or comments).
+  inline void StartToken();
+  // Called when the current character is the first character after the
+  // end of the last token.  After this returns, current_.text will
+  // contain all text consumed since StartToken() was called.
+  inline void EndToken();
+
+  // Convenience method to add an error at the current line and column.
+  void AddError(const string& message) {
+    error_collector_->AddError(line_, column_, message);
+  }
+
+  // -----------------------------------------------------------------
+  // The following four methods are used to consume tokens of specific
+  // types.  They are actually used to consume all characters *after*
+  // the first, since the calling function consumes the first character
+  // in order to decide what kind of token is being read.
+
+  // Read and consume a string, ending when the given delimiter is
+  // consumed.
+  void ConsumeString(char delimiter);
+
+  // Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER
+  // depending on what was read.  This needs to know if the first
+  // character was a zero in order to correctly recognize hex and octal
+  // numbers.
+  // It also needs to know if the first characted was a . to parse floating
+  // point correctly.
+  TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
+
+  // Consume the rest of a line.
+  void ConsumeLineComment(string* content);
+  // Consume until "*/".
+  void ConsumeBlockComment(string* content);
+
+  enum NextCommentStatus {
+    // Started a line comment.
+    LINE_COMMENT,
+
+    // Started a block comment.
+    BLOCK_COMMENT,
+
+    // Consumed a slash, then realized it wasn't a comment.  current_ has
+    // been filled in with a slash token.  The caller should return it.
+    SLASH_NOT_COMMENT,
+
+    // We do not appear to be starting a comment here.
+    NO_COMMENT
+  };
+
+  // If we're at the start of a new comment, consume it and return what kind
+  // of comment it is.
+  NextCommentStatus TryConsumeCommentStart();
+
+  // -----------------------------------------------------------------
+  // These helper methods make the parsing code more readable.  The
+  // "character classes" referred to are defined at the top of the .cc file.
+  // Basically it is a C++ class with one method:
+  //   static bool InClass(char c);
+  // The method returns true if c is a member of this "class", like "Letter"
+  // or "Digit".
+
+  // Returns true if the current character is of the given character
+  // class, but does not consume anything.
+  template<typename CharacterClass>
+  inline bool LookingAt();
+
+  // If the current character is in the given class, consume it and return
+  // true.  Otherwise return false.
+  // e.g. TryConsumeOne<Letter>()
+  template<typename CharacterClass>
+  inline bool TryConsumeOne();
+
+  // Like above, but try to consume the specific character indicated.
+  inline bool TryConsume(char c);
+
+  // Consume zero or more of the given character class.
+  template<typename CharacterClass>
+  inline void ConsumeZeroOrMore();
+
+  // Consume one or more of the given character class or log the given
+  // error message.
+  // e.g. ConsumeOneOrMore<Digit>("Expected digits.");
+  template<typename CharacterClass>
+  inline void ConsumeOneOrMore(const char* error);
+};
+
+// inline methods ====================================================
+inline const Tokenizer::Token& Tokenizer::current() {
+  return current_;
+}
+
+inline const Tokenizer::Token& Tokenizer::previous() {
+  return previous_;
+}
+
+inline void Tokenizer::ParseString(const string& text, string* output) {
+  output->clear();
+  ParseStringAppend(text, output);
+}
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer_unittest.cc
new file mode 100644
index 0000000..ae0811f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/tokenizer_unittest.cc
@@ -0,0 +1,996 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <limits.h>
+#include <math.h>
+
+#include <vector>
+
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace {
+
+// ===================================================================
+// Data-Driven Test Infrastructure
+
+// TODO(kenton):  This is copied from coded_stream_unittest.  This is
+//   temporary until these fetaures are integrated into gTest itself.
+
+// TEST_1D and TEST_2D are macros I'd eventually like to see added to
+// gTest.  These macros can be used to declare tests which should be
+// run multiple times, once for each item in some input array.  TEST_1D
+// tests all cases in a single input array.  TEST_2D tests all
+// combinations of cases from two arrays.  The arrays must be statically
+// defined such that the GOOGLE_ARRAYSIZE() macro works on them.  Example:
+//
+// int kCases[] = {1, 2, 3, 4}
+// TEST_1D(MyFixture, MyTest, kCases) {
+//   EXPECT_GT(kCases_case, 0);
+// }
+//
+// This test iterates through the numbers 1, 2, 3, and 4 and tests that
+// they are all grater than zero.  In case of failure, the exact case
+// which failed will be printed.  The case type must be printable using
+// ostream::operator<<.
+
+#define TEST_1D(FIXTURE, NAME, CASES)                                      \
+  class FIXTURE##_##NAME##_DD : public FIXTURE {                           \
+   protected:                                                              \
+    template <typename CaseType>                                           \
+    void DoSingleCase(const CaseType& CASES##_case);                       \
+  };                                                                       \
+                                                                           \
+  TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                    \
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) {                           \
+      SCOPED_TRACE(testing::Message()                                      \
+        << #CASES " case #" << i << ": " << CASES[i]);                     \
+      DoSingleCase(CASES[i]);                                              \
+    }                                                                      \
+  }                                                                        \
+                                                                           \
+  template <typename CaseType>                                             \
+  void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case)
+
+#define TEST_2D(FIXTURE, NAME, CASES1, CASES2)                             \
+  class FIXTURE##_##NAME##_DD : public FIXTURE {                           \
+   protected:                                                              \
+    template <typename CaseType1, typename CaseType2>                      \
+    void DoSingleCase(const CaseType1& CASES1##_case,                      \
+                      const CaseType2& CASES2##_case);                     \
+  };                                                                       \
+                                                                           \
+  TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                    \
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) {                          \
+      for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) {                        \
+        SCOPED_TRACE(testing::Message()                                    \
+          << #CASES1 " case #" << i << ": " << CASES1[i] << ", "           \
+          << #CASES2 " case #" << j << ": " << CASES2[j]);                 \
+        DoSingleCase(CASES1[i], CASES2[j]);                                \
+      }                                                                    \
+    }                                                                      \
+  }                                                                        \
+                                                                           \
+  template <typename CaseType1, typename CaseType2>                        \
+  void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \
+                                           const CaseType2& CASES2##_case)
+
+// -------------------------------------------------------------------
+
+// An input stream that is basically like an ArrayInputStream but sometimes
+// returns empty buffers, just to throw us off.
+class TestInputStream : public ZeroCopyInputStream {
+ public:
+  TestInputStream(const void* data, int size, int block_size)
+    : array_stream_(data, size, block_size), counter_(0) {}
+  ~TestInputStream() {}
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size) {
+    // We'll return empty buffers starting with the first buffer, and every
+    // 3 and 5 buffers after that.
+    if (counter_ % 3 == 0 || counter_ % 5 == 0) {
+      *data = NULL;
+      *size = 0;
+      ++counter_;
+      return true;
+    } else {
+      ++counter_;
+      return array_stream_.Next(data, size);
+    }
+  }
+
+  void BackUp(int count)  { return array_stream_.BackUp(count); }
+  bool Skip(int count)    { return array_stream_.Skip(count);   }
+  int64 ByteCount() const { return array_stream_.ByteCount();   }
+
+ private:
+  ArrayInputStream array_stream_;
+  int counter_;
+};
+
+// -------------------------------------------------------------------
+
+// An error collector which simply concatenates all its errors into a big
+// block of text which can be checked.
+class TestErrorCollector : public ErrorCollector {
+ public:
+  TestErrorCollector() {}
+  ~TestErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(int line, int column, const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
+                                 line, column, message);
+  }
+};
+
+// -------------------------------------------------------------------
+
+// We test each operation over a variety of block sizes to insure that
+// we test cases where reads cross buffer boundaries as well as cases
+// where they don't.  This is sort of a brute-force approach to this,
+// but it's easy to write and easy to understand.
+const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024};
+
+class TokenizerTest : public testing::Test {
+ protected:
+  // For easy testing.
+  uint64 ParseInteger(const string& text) {
+    uint64 result;
+    EXPECT_TRUE(Tokenizer::ParseInteger(text, kuint64max, &result));
+    return result;
+  }
+};
+
+// ===================================================================
+
+// These tests causes gcc 3.3.5 (and earlier?) to give the cryptic error:
+//   "sorry, unimplemented: `method_call_expr' not supported by dump_expr"
+#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
+
+// In each test case, the entire input text should parse as a single token
+// of the given type.
+struct SimpleTokenCase {
+  string input;
+  Tokenizer::TokenType type;
+};
+
+inline ostream& operator<<(ostream& out,
+                           const SimpleTokenCase& test_case) {
+  return out << CEscape(test_case.input);
+}
+
+SimpleTokenCase kSimpleTokenCases[] = {
+  // Test identifiers.
+  { "hello",       Tokenizer::TYPE_IDENTIFIER },
+
+  // Test integers.
+  { "123",         Tokenizer::TYPE_INTEGER },
+  { "0xab6",       Tokenizer::TYPE_INTEGER },
+  { "0XAB6",       Tokenizer::TYPE_INTEGER },
+  { "0X1234567",   Tokenizer::TYPE_INTEGER },
+  { "0x89abcdef",  Tokenizer::TYPE_INTEGER },
+  { "0x89ABCDEF",  Tokenizer::TYPE_INTEGER },
+  { "01234567",    Tokenizer::TYPE_INTEGER },
+
+  // Test floats.
+  { "123.45",      Tokenizer::TYPE_FLOAT },
+  { "1.",          Tokenizer::TYPE_FLOAT },
+  { "1e3",         Tokenizer::TYPE_FLOAT },
+  { "1E3",         Tokenizer::TYPE_FLOAT },
+  { "1e-3",        Tokenizer::TYPE_FLOAT },
+  { "1e+3",        Tokenizer::TYPE_FLOAT },
+  { "1.e3",        Tokenizer::TYPE_FLOAT },
+  { "1.2e3",       Tokenizer::TYPE_FLOAT },
+  { ".1",          Tokenizer::TYPE_FLOAT },
+  { ".1e3",        Tokenizer::TYPE_FLOAT },
+  { ".1e-3",       Tokenizer::TYPE_FLOAT },
+  { ".1e+3",       Tokenizer::TYPE_FLOAT },
+
+  // Test strings.
+  { "'hello'",     Tokenizer::TYPE_STRING },
+  { "\"foo\"",     Tokenizer::TYPE_STRING },
+  { "'a\"b'",      Tokenizer::TYPE_STRING },
+  { "\"a'b\"",     Tokenizer::TYPE_STRING },
+  { "'a\\'b'",     Tokenizer::TYPE_STRING },
+  { "\"a\\\"b\"",  Tokenizer::TYPE_STRING },
+  { "'\\xf'",      Tokenizer::TYPE_STRING },
+  { "'\\0'",       Tokenizer::TYPE_STRING },
+
+  // Test symbols.
+  { "+",           Tokenizer::TYPE_SYMBOL },
+  { ".",           Tokenizer::TYPE_SYMBOL },
+};
+
+TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) {
+  // Set up the tokenizer.
+  TestInputStream input(kSimpleTokenCases_case.input.data(),
+                        kSimpleTokenCases_case.input.size(),
+                        kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+
+  // Before Next() is called, the initial token should always be TYPE_START.
+  EXPECT_EQ(Tokenizer::TYPE_START, tokenizer.current().type);
+  EXPECT_EQ("", tokenizer.current().text);
+  EXPECT_EQ(0, tokenizer.current().line);
+  EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
+
+  // Parse the token.
+  ASSERT_TRUE(tokenizer.Next());
+
+  // Check that it has the right type.
+  EXPECT_EQ(kSimpleTokenCases_case.type, tokenizer.current().type);
+  // Check that it contains the complete input text.
+  EXPECT_EQ(kSimpleTokenCases_case.input, tokenizer.current().text);
+  // Check that it is located at the beginning of the input
+  EXPECT_EQ(0, tokenizer.current().line);
+  EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
+
+  // There should be no more input.
+  EXPECT_FALSE(tokenizer.Next());
+
+  // After Next() returns false, the token should have type TYPE_END.
+  EXPECT_EQ(Tokenizer::TYPE_END, tokenizer.current().type);
+  EXPECT_EQ("", tokenizer.current().text);
+  EXPECT_EQ(0, tokenizer.current().line);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
+
+  // There should be no errors.
+  EXPECT_TRUE(error_collector.text_.empty());
+}
+
+TEST_1D(TokenizerTest, FloatSuffix, kBlockSizes) {
+  // Test the "allow_f_after_float" option.
+
+  // Set up the tokenizer.
+  const char* text = "1f 2.5f 6e3f 7F";
+  TestInputStream input(text, strlen(text), kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+  tokenizer.set_allow_f_after_float(true);
+
+  // Advance through tokens and check that they are parsed as expected.
+  ASSERT_TRUE(tokenizer.Next());
+  EXPECT_EQ(tokenizer.current().text, "1f");
+  EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT);
+  ASSERT_TRUE(tokenizer.Next());
+  EXPECT_EQ(tokenizer.current().text, "2.5f");
+  EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT);
+  ASSERT_TRUE(tokenizer.Next());
+  EXPECT_EQ(tokenizer.current().text, "6e3f");
+  EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT);
+  ASSERT_TRUE(tokenizer.Next());
+  EXPECT_EQ(tokenizer.current().text, "7F");
+  EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT);
+
+  // There should be no more input.
+  EXPECT_FALSE(tokenizer.Next());
+  // There should be no errors.
+  EXPECT_TRUE(error_collector.text_.empty());
+}
+
+#endif
+
+// -------------------------------------------------------------------
+
+// In each case, the input is parsed to produce a list of tokens.  The
+// last token in "output" must have type TYPE_END.
+struct MultiTokenCase {
+  string input;
+  Tokenizer::Token output[10];  // The compiler wants a constant array
+                                // size for initialization to work.  There
+                                // is no reason this can't be increased if
+                                // needed.
+};
+
+inline ostream& operator<<(ostream& out,
+                           const MultiTokenCase& test_case) {
+  return out << CEscape(test_case.input);
+}
+
+MultiTokenCase kMultiTokenCases[] = {
+  // Test empty input.
+  { "", {
+    { Tokenizer::TYPE_END       , ""     , 0,  0 },
+  }},
+
+  // Test all token types at the same time.
+  { "foo 1 1.2 + 'bar'", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo"  , 0,  0,  3 },
+    { Tokenizer::TYPE_INTEGER   , "1"    , 0,  4,  5 },
+    { Tokenizer::TYPE_FLOAT     , "1.2"  , 0,  6,  9 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 10, 11 },
+    { Tokenizer::TYPE_STRING    , "'bar'", 0, 12, 17 },
+    { Tokenizer::TYPE_END       , ""     , 0, 17, 17 },
+  }},
+
+  // Test that consecutive symbols are parsed as separate tokens.
+  { "!@+%", {
+    { Tokenizer::TYPE_SYMBOL    , "!"    , 0, 0, 1 },
+    { Tokenizer::TYPE_SYMBOL    , "@"    , 0, 1, 2 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 2, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "%"    , 0, 3, 4 },
+    { Tokenizer::TYPE_END       , ""     , 0, 4, 4 },
+  }},
+
+  // Test that newlines affect line numbers correctly.
+  { "foo bar\nrab oof", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  4, 7 },
+    { Tokenizer::TYPE_IDENTIFIER, "rab", 1,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "oof", 1,  4, 7 },
+    { Tokenizer::TYPE_END       , ""   , 1,  7, 7 },
+  }},
+
+  // Test that tabs affect column numbers correctly.
+  { "foo\tbar  \tbaz", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  8, 11 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 },
+    { Tokenizer::TYPE_END       , ""   , 0, 19, 19 },
+  }},
+
+  // Test that tabs in string literals affect column numbers correctly.
+  { "\"foo\tbar\" baz", {
+    { Tokenizer::TYPE_STRING    , "\"foo\tbar\"", 0,  0, 12 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz"         , 0, 13, 16 },
+    { Tokenizer::TYPE_END       , ""            , 0, 16, 16 },
+  }},
+
+  // Test that line comments are ignored.
+  { "foo // This is a comment\n"
+    "bar // This is another comment", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1,  0,  3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 30, 30 },
+  }},
+
+  // Test that block comments are ignored.
+  { "foo /* This is a block comment */ bar", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 },
+    { Tokenizer::TYPE_END       , ""   , 0, 37, 37 },
+  }},
+
+  // Test that sh-style comments are not ignored by default.
+  { "foo # bar\n"
+    "baz", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "#"  , 0, 4, 5 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 3, 3 },
+  }},
+
+  // Test all whitespace chars
+  { "foo\n\t\r\v\fbar", {
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 },
+    { Tokenizer::TYPE_END       , ""   , 1, 14, 14 },
+  }},
+};
+
+TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) {
+  // Set up the tokenizer.
+  TestInputStream input(kMultiTokenCases_case.input.data(),
+                        kMultiTokenCases_case.input.size(),
+                        kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+
+  // Before Next() is called, the initial token should always be TYPE_START.
+  EXPECT_EQ(Tokenizer::TYPE_START, tokenizer.current().type);
+  EXPECT_EQ("", tokenizer.current().text);
+  EXPECT_EQ(0, tokenizer.current().line);
+  EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
+
+  // Loop through all expected tokens.
+  int i = 0;
+  Tokenizer::Token token;
+  do {
+    token = kMultiTokenCases_case.output[i++];
+
+    SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text);
+
+    Tokenizer::Token previous = tokenizer.current();
+
+    // Next() should only return false when it hits the end token.
+    if (token.type != Tokenizer::TYPE_END) {
+      ASSERT_TRUE(tokenizer.Next());
+    } else {
+      ASSERT_FALSE(tokenizer.Next());
+    }
+
+    // Check that the previous token is set correctly.
+    EXPECT_EQ(previous.type, tokenizer.previous().type);
+    EXPECT_EQ(previous.text, tokenizer.previous().text);
+    EXPECT_EQ(previous.line, tokenizer.previous().line);
+    EXPECT_EQ(previous.column, tokenizer.previous().column);
+    EXPECT_EQ(previous.end_column, tokenizer.previous().end_column);
+
+    // Check that the token matches the expected one.
+    EXPECT_EQ(token.type, tokenizer.current().type);
+    EXPECT_EQ(token.text, tokenizer.current().text);
+    EXPECT_EQ(token.line, tokenizer.current().line);
+    EXPECT_EQ(token.column, tokenizer.current().column);
+    EXPECT_EQ(token.end_column, tokenizer.current().end_column);
+
+  } while (token.type != Tokenizer::TYPE_END);
+
+  // There should be no errors.
+  EXPECT_TRUE(error_collector.text_.empty());
+}
+
+// This test causes gcc 3.3.5 (and earlier?) to give the cryptic error:
+//   "sorry, unimplemented: `method_call_expr' not supported by dump_expr"
+#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
+
+TEST_1D(TokenizerTest, ShCommentStyle, kBlockSizes) {
+  // Test the "comment_style" option.
+
+  const char* text = "foo # bar\n"
+                     "baz // qux\n"
+                     "corge /* grault */\n"
+                     "garply";
+  const char* const kTokens[] = {"foo",  // "# bar" is ignored
+                                 "baz", "/", "/", "qux",
+                                 "corge", "/", "*", "grault", "*", "/",
+                                 "garply"};
+
+  // Set up the tokenizer.
+  TestInputStream input(text, strlen(text), kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+  tokenizer.set_comment_style(Tokenizer::SH_COMMENT_STYLE);
+
+  // Advance through tokens and check that they are parsed as expected.
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(kTokens); i++) {
+    EXPECT_TRUE(tokenizer.Next());
+    EXPECT_EQ(tokenizer.current().text, kTokens[i]);
+  }
+
+  // There should be no more input.
+  EXPECT_FALSE(tokenizer.Next());
+  // There should be no errors.
+  EXPECT_TRUE(error_collector.text_.empty());
+}
+
+#endif
+
+// -------------------------------------------------------------------
+
+// In each case, the input is expected to have two tokens named "prev" and
+// "next" with comments in between.
+struct DocCommentCase {
+  string input;
+
+  const char* prev_trailing_comments;
+  const char* detached_comments[10];
+  const char* next_leading_comments;
+};
+
+inline ostream& operator<<(ostream& out,
+                           const DocCommentCase& test_case) {
+  return out << CEscape(test_case.input);
+}
+
+DocCommentCase kDocCommentCases[] = {
+  {
+    "prev next",
+
+    "",
+    {},
+    ""
+      },
+
+        {
+      "prev /* ignored */ next",
+
+      "",
+      {},
+      ""
+        },
+
+          {
+        "prev // trailing comment\n"
+            "next",
+
+            " trailing comment\n",
+            {},
+            ""
+          },
+
+            {
+          "prev\n"
+              "// leading comment\n"
+              "// line 2\n"
+              "next",
+
+              "",
+              {},
+              " leading comment\n"
+              " line 2\n"
+            },
+
+              {
+            "prev\n"
+                "// trailing comment\n"
+                "// line 2\n"
+                "\n"
+                "next",
+
+                " trailing comment\n"
+                " line 2\n",
+                {},
+                ""
+              },
+
+                {
+              "prev // trailing comment\n"
+                  "// leading comment\n"
+                  "// line 2\n"
+                  "next",
+
+                  " trailing comment\n",
+                  {},
+                  " leading comment\n"
+                  " line 2\n"
+                },
+
+                  {
+                "prev /* trailing block comment */\n"
+                    "/* leading block comment\n"
+                    " * line 2\n"
+                    " * line 3 */"
+                    "next",
+
+                    " trailing block comment ",
+                    {},
+                    " leading block comment\n"
+                    " line 2\n"
+                    " line 3 "
+                  },
+
+                    {
+                  "prev\n"
+                      "/* trailing block comment\n"
+                      " * line 2\n"
+                      " * line 3\n"
+                      " */\n"
+                      "/* leading block comment\n"
+                      " * line 2\n"
+                      " * line 3 */"
+                      "next",
+
+                      " trailing block comment\n"
+                      " line 2\n"
+                      " line 3\n",
+                      {},
+                      " leading block comment\n"
+                      " line 2\n"
+                      " line 3 "
+                    },
+
+                      {
+                    "prev\n"
+                        "// trailing comment\n"
+                        "\n"
+                        "// detached comment\n"
+                        "// line 2\n"
+                        "\n"
+                        "// second detached comment\n"
+                        "/* third detached comment\n"
+                        " * line 2 */\n"
+                        "// leading comment\n"
+                        "next",
+
+                        " trailing comment\n",
+                        {
+                      " detached comment\n"
+                          " line 2\n",
+                          " second detached comment\n",
+                          " third detached comment\n"
+                          " line 2 "
+                        },
+                          " leading comment\n"
+                        },
+
+                          {
+                        "prev /**/\n"
+                            "\n"
+                            "// detached comment\n"
+                            "\n"
+                            "// leading comment\n"
+                            "next",
+
+                            "",
+                            {
+                          " detached comment\n"
+                            },
+                              " leading comment\n"
+                            },
+
+                              {
+                            "prev /**/\n"
+                                "// leading comment\n"
+                                "next",
+
+                                "",
+                                {},
+                                " leading comment\n"
+                              },
+                              };
+
+TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) {
+  // Set up the tokenizer.
+  TestInputStream input(kDocCommentCases_case.input.data(),
+                        kDocCommentCases_case.input.size(),
+                        kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+
+  // Set up a second tokenizer where we'll pass all NULLs to NextWithComments().
+  TestInputStream input2(kDocCommentCases_case.input.data(),
+                        kDocCommentCases_case.input.size(),
+                        kBlockSizes_case);
+  Tokenizer tokenizer2(&input2, &error_collector);
+
+  tokenizer.Next();
+  tokenizer2.Next();
+
+  EXPECT_EQ("prev", tokenizer.current().text);
+  EXPECT_EQ("prev", tokenizer2.current().text);
+
+  string prev_trailing_comments;
+  vector<string> detached_comments;
+  string next_leading_comments;
+  tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments,
+                             &next_leading_comments);
+  tokenizer2.NextWithComments(NULL, NULL, NULL);
+  EXPECT_EQ("next", tokenizer.current().text);
+  EXPECT_EQ("next", tokenizer2.current().text);
+
+  EXPECT_EQ(kDocCommentCases_case.prev_trailing_comments,
+            prev_trailing_comments);
+
+  for (int i = 0; i < detached_comments.size(); i++) {
+    ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases));
+    ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL);
+    EXPECT_EQ(kDocCommentCases_case.detached_comments[i],
+              detached_comments[i]);
+  }
+
+  // Verify that we matched all the detached comments.
+  EXPECT_EQ(NULL,
+      kDocCommentCases_case.detached_comments[detached_comments.size()]);
+
+  EXPECT_EQ(kDocCommentCases_case.next_leading_comments,
+            next_leading_comments);
+}
+
+// -------------------------------------------------------------------
+
+// Test parse helpers.  It's not really worth setting up a full data-driven
+// test here.
+TEST_F(TokenizerTest, ParseInteger) {
+  EXPECT_EQ(0, ParseInteger("0"));
+  EXPECT_EQ(123, ParseInteger("123"));
+  EXPECT_EQ(0xabcdef12u, ParseInteger("0xabcdef12"));
+  EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12"));
+  EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF"));
+  EXPECT_EQ(01234567, ParseInteger("01234567"));
+  EXPECT_EQ(0X123, ParseInteger("0X123"));
+
+  // Test invalid integers that may still be tokenized as integers.
+  EXPECT_EQ(0, ParseInteger("0x"));
+
+  uint64 i;
+
+  // Test invalid integers that will never be tokenized as integers.
+  EXPECT_FALSE(Tokenizer::ParseInteger("zxy", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("1.2", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("08", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("0xg", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("-1", kuint64max, &i));
+
+  // Test overflows.
+  EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("1", 0, &i));
+  EXPECT_TRUE (Tokenizer::ParseInteger("1", 1, &i));
+  EXPECT_TRUE (Tokenizer::ParseInteger("12345", 12345, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("12346", 12345, &i));
+  EXPECT_TRUE (Tokenizer::ParseInteger("0xFFFFFFFFFFFFFFFF" , kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("0x10000000000000000", kuint64max, &i));
+}
+
+TEST_F(TokenizerTest, ParseFloat) {
+  EXPECT_DOUBLE_EQ(1    , Tokenizer::ParseFloat("1."));
+  EXPECT_DOUBLE_EQ(1e3  , Tokenizer::ParseFloat("1e3"));
+  EXPECT_DOUBLE_EQ(1e3  , Tokenizer::ParseFloat("1E3"));
+  EXPECT_DOUBLE_EQ(1.5e3, Tokenizer::ParseFloat("1.5e3"));
+  EXPECT_DOUBLE_EQ(.1   , Tokenizer::ParseFloat(".1"));
+  EXPECT_DOUBLE_EQ(.25  , Tokenizer::ParseFloat(".25"));
+  EXPECT_DOUBLE_EQ(.1e3 , Tokenizer::ParseFloat(".1e3"));
+  EXPECT_DOUBLE_EQ(.25e3, Tokenizer::ParseFloat(".25e3"));
+  EXPECT_DOUBLE_EQ(.1e+3, Tokenizer::ParseFloat(".1e+3"));
+  EXPECT_DOUBLE_EQ(.1e-3, Tokenizer::ParseFloat(".1e-3"));
+  EXPECT_DOUBLE_EQ(5    , Tokenizer::ParseFloat("5"));
+  EXPECT_DOUBLE_EQ(6e-12, Tokenizer::ParseFloat("6e-12"));
+  EXPECT_DOUBLE_EQ(1.2  , Tokenizer::ParseFloat("1.2"));
+  EXPECT_DOUBLE_EQ(1.e2 , Tokenizer::ParseFloat("1.e2"));
+
+  // Test invalid integers that may still be tokenized as integers.
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1e"));
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1e-"));
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1.e"));
+
+  // Test 'f' suffix.
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1f"));
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1.0f"));
+  EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1F"));
+
+  // These should parse successfully even though they are out of range.
+  // Overflows become infinity and underflows become zero.
+  EXPECT_EQ(     0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999"));
+  EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999"));
+
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
+  // Test invalid integers that will never be tokenized as integers.
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("zxy"),
+    "passed text that could not have been tokenized as a float");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("1-e0"),
+    "passed text that could not have been tokenized as a float");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("-1.0"),
+    "passed text that could not have been tokenized as a float");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST_F(TokenizerTest, ParseString) {
+  string output;
+  Tokenizer::ParseString("'hello'", &output);
+  EXPECT_EQ("hello", output);
+  Tokenizer::ParseString("\"blah\\nblah2\"", &output);
+  EXPECT_EQ("blah\nblah2", output);
+  Tokenizer::ParseString("'\\1x\\1\\123\\739\\52\\334n\\3'", &output);
+  EXPECT_EQ("\1x\1\123\739\52\334n\3", output);
+  Tokenizer::ParseString("'\\x20\\x4'", &output);
+  EXPECT_EQ("\x20\x4", output);
+
+  // Test invalid strings that may still be tokenized as strings.
+  Tokenizer::ParseString("\"\\a\\l\\v\\t", &output);  // \l is invalid
+  EXPECT_EQ("\a?\v\t", output);
+  Tokenizer::ParseString("'", &output);
+  EXPECT_EQ("", output);
+  Tokenizer::ParseString("'\\", &output);
+  EXPECT_EQ("\\", output);
+
+  // Experiment with Unicode escapes. Here are one-, two- and three-byte Unicode
+  // characters.
+  Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\U00024b62XX'", &output);
+  EXPECT_EQ("$¢€𤭢XX", output);
+  // Same thing encoded using UTF16.
+  Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\ud852\\udf62XX'", &output);
+  EXPECT_EQ("$¢€𤭢XX", output);
+  // Here's some broken UTF16; there's a head surrogate with no tail surrogate.
+  // We just output this as if it were UTF8; it's not a defined code point, but
+  // it has a defined encoding.
+  Tokenizer::ParseString("'\\ud852XX'", &output);
+  EXPECT_EQ("\xed\xa1\x92XX", output);
+  // Malformed escape: Demons may fly out of the nose.
+  Tokenizer::ParseString("\\u0", &output);
+  EXPECT_EQ("u0", output);
+
+  // Test invalid strings that will never be tokenized as strings.
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output),
+    "passed text that could not have been tokenized as a string");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST_F(TokenizerTest, ParseStringAppend) {
+  // Check that ParseString and ParseStringAppend differ.
+  string output("stuff+");
+  Tokenizer::ParseStringAppend("'hello'", &output);
+  EXPECT_EQ("stuff+hello", output);
+  Tokenizer::ParseString("'hello'", &output);
+  EXPECT_EQ("hello", output);
+}
+
+// -------------------------------------------------------------------
+
+// Each case parses some input text, ignoring the tokens produced, and
+// checks that the error output matches what is expected.
+struct ErrorCase {
+  string input;
+  bool recoverable;  // True if the tokenizer should be able to recover and
+                     // parse more tokens after seeing this error.  Cases
+                     // for which this is true must end with "foo" as
+                     // the last token, which the test will check for.
+  const char* errors;
+};
+
+inline ostream& operator<<(ostream& out,
+                           const ErrorCase& test_case) {
+  return out << CEscape(test_case.input);
+}
+
+ErrorCase kErrorCases[] = {
+  // String errors.
+  { "'\\l' foo", true,
+    "0:2: Invalid escape sequence in string literal.\n" },
+  { "'\\X' foo", true,
+    "0:2: Invalid escape sequence in string literal.\n" },
+  { "'\\x' foo", true,
+    "0:3: Expected hex digits for escape sequence.\n" },
+  { "'foo", false,
+    "0:4: Unexpected end of string.\n" },
+  { "'bar\nfoo", true,
+    "0:4: String literals cannot cross line boundaries.\n" },
+  { "'\\u01' foo", true,
+    "0:5: Expected four hex digits for \\u escape sequence.\n" },
+  { "'\\u01' foo", true,
+    "0:5: Expected four hex digits for \\u escape sequence.\n" },
+  { "'\\uXYZ' foo", true,
+    "0:3: Expected four hex digits for \\u escape sequence.\n" },
+
+  // Integer errors.
+  { "123foo", true,
+    "0:3: Need space between number and identifier.\n" },
+
+  // Hex/octal errors.
+  { "0x foo", true,
+    "0:2: \"0x\" must be followed by hex digits.\n" },
+  { "0541823 foo", true,
+    "0:4: Numbers starting with leading zero must be in octal.\n" },
+  { "0x123z foo", true,
+    "0:5: Need space between number and identifier.\n" },
+  { "0x123.4 foo", true,
+    "0:5: Hex and octal numbers must be integers.\n" },
+  { "0123.4 foo", true,
+    "0:4: Hex and octal numbers must be integers.\n" },
+
+  // Float errors.
+  { "1e foo", true,
+    "0:2: \"e\" must be followed by exponent.\n" },
+  { "1e- foo", true,
+    "0:3: \"e\" must be followed by exponent.\n" },
+  { "1.2.3 foo", true,
+    "0:3: Already saw decimal point or exponent; can't have another one.\n" },
+  { "1e2.3 foo", true,
+    "0:3: Already saw decimal point or exponent; can't have another one.\n" },
+  { "a.1 foo", true,
+    "0:1: Need space between identifier and decimal point.\n" },
+  // allow_f_after_float not enabled, so this should be an error.
+  { "1.0f foo", true,
+    "0:3: Need space between number and identifier.\n" },
+
+  // Block comment errors.
+  { "/*", false,
+    "0:2: End-of-file inside block comment.\n"
+    "0:0:   Comment started here.\n"},
+  { "/*/*/ foo", true,
+    "0:3: \"/*\" inside block comment.  Block comments cannot be nested.\n"},
+
+  // Control characters.  Multiple consecutive control characters should only
+  // produce one error.
+  { "\b foo", true,
+    "0:0: Invalid control characters encountered in text.\n" },
+  { "\b\b foo", true,
+    "0:0: Invalid control characters encountered in text.\n" },
+
+  // Check that control characters at end of input don't result in an
+  // infinite loop.
+  { "\b", false,
+    "0:0: Invalid control characters encountered in text.\n" },
+
+  // Check recovery from '\0'.  We have to explicitly specify the length of
+  // these strings because otherwise the string constructor will just call
+  // strlen() which will see the first '\0' and think that is the end of the
+  // string.
+  { string("\0foo", 4), true,
+    "0:0: Invalid control characters encountered in text.\n" },
+  { string("\0\0foo", 5), true,
+    "0:0: Invalid control characters encountered in text.\n" },
+
+  // Check error from high order bits set
+  { "\300foo", true,
+    "0:0: Interpreting non ascii codepoint 192.\n" },
+};
+
+TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) {
+  // Set up the tokenizer.
+  TestInputStream input(kErrorCases_case.input.data(),
+                        kErrorCases_case.input.size(),
+                        kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+
+  // Ignore all input, except remember if the last token was "foo".
+  bool last_was_foo = false;
+  while (tokenizer.Next()) {
+    last_was_foo = tokenizer.current().text == "foo";
+  }
+
+  // Check that the errors match what was expected.
+  EXPECT_EQ(kErrorCases_case.errors, error_collector.text_);
+
+  // If the error was recoverable, make sure we saw "foo" after it.
+  if (kErrorCases_case.recoverable) {
+    EXPECT_TRUE(last_was_foo);
+  }
+}
+
+// -------------------------------------------------------------------
+
+TEST_1D(TokenizerTest, BackUpOnDestruction, kBlockSizes) {
+  string text = "foo bar";
+  TestInputStream input(text.data(), text.size(), kBlockSizes_case);
+
+  // Create a tokenizer, read one token, then destroy it.
+  {
+    TestErrorCollector error_collector;
+    Tokenizer tokenizer(&input, &error_collector);
+
+    tokenizer.Next();
+  }
+
+  // Only "foo" should have been read.
+  EXPECT_EQ(strlen("foo"), input.ByteCount());
+}
+
+
+}  // namespace
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.cc b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.cc
new file mode 100644
index 0000000..186de00
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.cc
@@ -0,0 +1,58 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+ZeroCopyInputStream::~ZeroCopyInputStream() {}
+ZeroCopyOutputStream::~ZeroCopyOutputStream() {}
+
+
+bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */,
+                                           int /* size */) {
+  GOOGLE_LOG(FATAL) << "This ZeroCopyOutputStream doesn't support aliasing. "
+                "Reaching here usually means a ZeroCopyOutputStream "
+                "implementation bug.";
+  return false;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.h b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.h
new file mode 100644
index 0000000..52650fc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream.h
@@ -0,0 +1,248 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
+// interfaces, which represent abstract I/O streams to and from which
+// protocol buffers can be read and written.  For a few simple
+// implementations of these interfaces, see zero_copy_stream_impl.h.
+//
+// These interfaces are different from classic I/O streams in that they
+// try to minimize the amount of data copying that needs to be done.
+// To accomplish this, responsibility for allocating buffers is moved to
+// the stream object, rather than being the responsibility of the caller.
+// So, the stream can return a buffer which actually points directly into
+// the final data structure where the bytes are to be stored, and the caller
+// can interact directly with that buffer, eliminating an intermediate copy
+// operation.
+//
+// As an example, consider the common case in which you are reading bytes
+// from an array that is already in memory (or perhaps an mmap()ed file).
+// With classic I/O streams, you would do something like:
+//   char buffer[BUFFER_SIZE];
+//   input->Read(buffer, BUFFER_SIZE);
+//   DoSomething(buffer, BUFFER_SIZE);
+// Then, the stream basically just calls memcpy() to copy the data from
+// the array into your buffer.  With a ZeroCopyInputStream, you would do
+// this instead:
+//   const void* buffer;
+//   int size;
+//   input->Next(&buffer, &size);
+//   DoSomething(buffer, size);
+// Here, no copy is performed.  The input stream returns a pointer directly
+// into the backing array, and the caller ends up reading directly from it.
+//
+// If you want to be able to read the old-fashion way, you can create
+// a CodedInputStream or CodedOutputStream wrapping these objects and use
+// their ReadRaw()/WriteRaw() methods.  These will, of course, add a copy
+// step, but Coded*Stream will handle buffering so at least it will be
+// reasonably efficient.
+//
+// ZeroCopyInputStream example:
+//   // Read in a file and print its contents to stdout.
+//   int fd = open("myfile", O_RDONLY);
+//   ZeroCopyInputStream* input = new FileInputStream(fd);
+//
+//   const void* buffer;
+//   int size;
+//   while (input->Next(&buffer, &size)) {
+//     cout.write(buffer, size);
+//   }
+//
+//   delete input;
+//   close(fd);
+//
+// ZeroCopyOutputStream example:
+//   // Copy the contents of "infile" to "outfile", using plain read() for
+//   // "infile" but a ZeroCopyOutputStream for "outfile".
+//   int infd = open("infile", O_RDONLY);
+//   int outfd = open("outfile", O_WRONLY);
+//   ZeroCopyOutputStream* output = new FileOutputStream(outfd);
+//
+//   void* buffer;
+//   int size;
+//   while (output->Next(&buffer, &size)) {
+//     int bytes = read(infd, buffer, size);
+//     if (bytes < size) {
+//       // Reached EOF.
+//       output->BackUp(size - bytes);
+//       break;
+//     }
+//   }
+//
+//   delete output;
+//   close(infd);
+//   close(outfd);
+
+#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
+#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+
+namespace protobuf {
+namespace io {
+
+// Defined in this file.
+class ZeroCopyInputStream;
+class ZeroCopyOutputStream;
+
+// Abstract interface similar to an input stream but designed to minimize
+// copying.
+class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
+ public:
+  inline ZeroCopyInputStream() {}
+  virtual ~ZeroCopyInputStream();
+
+  // Obtains a chunk of data from the stream.
+  //
+  // Preconditions:
+  // * "size" and "data" are not NULL.
+  //
+  // Postconditions:
+  // * If the returned value is false, there is no more data to return or
+  //   an error occurred.  All errors are permanent.
+  // * Otherwise, "size" points to the actual number of bytes read and "data"
+  //   points to a pointer to a buffer containing these bytes.
+  // * Ownership of this buffer remains with the stream, and the buffer
+  //   remains valid only until some other method of the stream is called
+  //   or the stream is destroyed.
+  // * It is legal for the returned buffer to have zero size, as long
+  //   as repeatedly calling Next() eventually yields a buffer with non-zero
+  //   size.
+  virtual bool Next(const void** data, int* size) = 0;
+
+  // Backs up a number of bytes, so that the next call to Next() returns
+  // data again that was already returned by the last call to Next().  This
+  // is useful when writing procedures that are only supposed to read up
+  // to a certain point in the input, then return.  If Next() returns a
+  // buffer that goes beyond what you wanted to read, you can use BackUp()
+  // to return to the point where you intended to finish.
+  //
+  // Preconditions:
+  // * The last method called must have been Next().
+  // * count must be less than or equal to the size of the last buffer
+  //   returned by Next().
+  //
+  // Postconditions:
+  // * The last "count" bytes of the last buffer returned by Next() will be
+  //   pushed back into the stream.  Subsequent calls to Next() will return
+  //   the same data again before producing new data.
+  virtual void BackUp(int count) = 0;
+
+  // Skips a number of bytes.  Returns false if the end of the stream is
+  // reached or some input error occurred.  In the end-of-stream case, the
+  // stream is advanced to the end of the stream (so ByteCount() will return
+  // the total size of the stream).
+  virtual bool Skip(int count) = 0;
+
+  // Returns the total number of bytes read since this object was created.
+  virtual int64 ByteCount() const = 0;
+
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
+};
+
+// Abstract interface similar to an output stream but designed to minimize
+// copying.
+class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
+ public:
+  inline ZeroCopyOutputStream() {}
+  virtual ~ZeroCopyOutputStream();
+
+  // Obtains a buffer into which data can be written.  Any data written
+  // into this buffer will eventually (maybe instantly, maybe later on)
+  // be written to the output.
+  //
+  // Preconditions:
+  // * "size" and "data" are not NULL.
+  //
+  // Postconditions:
+  // * If the returned value is false, an error occurred.  All errors are
+  //   permanent.
+  // * Otherwise, "size" points to the actual number of bytes in the buffer
+  //   and "data" points to the buffer.
+  // * Ownership of this buffer remains with the stream, and the buffer
+  //   remains valid only until some other method of the stream is called
+  //   or the stream is destroyed.
+  // * Any data which the caller stores in this buffer will eventually be
+  //   written to the output (unless BackUp() is called).
+  // * It is legal for the returned buffer to have zero size, as long
+  //   as repeatedly calling Next() eventually yields a buffer with non-zero
+  //   size.
+  virtual bool Next(void** data, int* size) = 0;
+
+  // Backs up a number of bytes, so that the end of the last buffer returned
+  // by Next() is not actually written.  This is needed when you finish
+  // writing all the data you want to write, but the last buffer was bigger
+  // than you needed.  You don't want to write a bunch of garbage after the
+  // end of your data, so you use BackUp() to back up.
+  //
+  // Preconditions:
+  // * The last method called must have been Next().
+  // * count must be less than or equal to the size of the last buffer
+  //   returned by Next().
+  // * The caller must not have written anything to the last "count" bytes
+  //   of that buffer.
+  //
+  // Postconditions:
+  // * The last "count" bytes of the last buffer returned by Next() will be
+  //   ignored.
+  virtual void BackUp(int count) = 0;
+
+  // Returns the total number of bytes written since this object was created.
+  virtual int64 ByteCount() const = 0;
+
+  // Write a given chunk of data to the output.  Some output streams may
+  // implement this in a way that avoids copying. Check AllowsAliasing() before
+  // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
+  // called on a stream that does not allow aliasing.
+  //
+  // NOTE: It is caller's responsibility to ensure that the chunk of memory
+  // remains live until all of the data has been consumed from the stream.
+  virtual bool WriteAliasedRaw(const void* data, int size);
+  virtual bool AllowsAliasing() const { return false; }
+
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
+};
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.cc
new file mode 100644
index 0000000..7ec2b5d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -0,0 +1,474 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+#include <errno.h>
+#include <iostream>
+#include <algorithm>
+
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+#ifdef _WIN32
+// Win32 lseek is broken:  If invoked on a non-seekable file descriptor, its
+// return value is undefined.  We re-define it to always produce an error.
+#define lseek(fd, offset, origin) ((off_t)-1)
+#endif
+
+namespace {
+
+// EINTR sucks.
+int close_no_eintr(int fd) {
+  int result;
+  do {
+    result = close(fd);
+  } while (result < 0 && errno == EINTR);
+  return result;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+FileInputStream::FileInputStream(int file_descriptor, int block_size)
+  : copying_input_(file_descriptor),
+    impl_(&copying_input_, block_size) {
+}
+
+FileInputStream::~FileInputStream() {}
+
+bool FileInputStream::Close() {
+  return copying_input_.Close();
+}
+
+bool FileInputStream::Next(const void** data, int* size) {
+  return impl_.Next(data, size);
+}
+
+void FileInputStream::BackUp(int count) {
+  impl_.BackUp(count);
+}
+
+bool FileInputStream::Skip(int count) {
+  return impl_.Skip(count);
+}
+
+int64 FileInputStream::ByteCount() const {
+  return impl_.ByteCount();
+}
+
+FileInputStream::CopyingFileInputStream::CopyingFileInputStream(
+    int file_descriptor)
+  : file_(file_descriptor),
+    close_on_delete_(false),
+    is_closed_(false),
+    errno_(0),
+    previous_seek_failed_(false) {
+}
+
+FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() {
+  if (close_on_delete_) {
+    if (!Close()) {
+      GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
+    }
+  }
+}
+
+bool FileInputStream::CopyingFileInputStream::Close() {
+  GOOGLE_CHECK(!is_closed_);
+
+  is_closed_ = true;
+  if (close_no_eintr(file_) != 0) {
+    // The docs on close() do not specify whether a file descriptor is still
+    // open after close() fails with EIO.  However, the glibc source code
+    // seems to indicate that it is not.
+    errno_ = errno;
+    return false;
+  }
+
+  return true;
+}
+
+int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) {
+  GOOGLE_CHECK(!is_closed_);
+
+  int result;
+  do {
+    result = read(file_, buffer, size);
+  } while (result < 0 && errno == EINTR);
+
+  if (result < 0) {
+    // Read error (not EOF).
+    errno_ = errno;
+  }
+
+  return result;
+}
+
+int FileInputStream::CopyingFileInputStream::Skip(int count) {
+  GOOGLE_CHECK(!is_closed_);
+
+  if (!previous_seek_failed_ &&
+      lseek(file_, count, SEEK_CUR) != (off_t)-1) {
+    // Seek succeeded.
+    return count;
+  } else {
+    // Failed to seek.
+
+    // Note to self:  Don't seek again.  This file descriptor doesn't
+    // support it.
+    previous_seek_failed_ = true;
+
+    // Use the default implementation.
+    return CopyingInputStream::Skip(count);
+  }
+}
+
+// ===================================================================
+
+FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
+  : copying_output_(file_descriptor),
+    impl_(&copying_output_, block_size) {
+}
+
+FileOutputStream::~FileOutputStream() {
+  impl_.Flush();
+}
+
+bool FileOutputStream::Close() {
+  bool flush_succeeded = impl_.Flush();
+  return copying_output_.Close() && flush_succeeded;
+}
+
+bool FileOutputStream::Flush() {
+  return impl_.Flush();
+}
+
+bool FileOutputStream::Next(void** data, int* size) {
+  return impl_.Next(data, size);
+}
+
+void FileOutputStream::BackUp(int count) {
+  impl_.BackUp(count);
+}
+
+int64 FileOutputStream::ByteCount() const {
+  return impl_.ByteCount();
+}
+
+FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream(
+    int file_descriptor)
+  : file_(file_descriptor),
+    close_on_delete_(false),
+    is_closed_(false),
+    errno_(0) {
+}
+
+FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() {
+  if (close_on_delete_) {
+    if (!Close()) {
+      GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
+    }
+  }
+}
+
+bool FileOutputStream::CopyingFileOutputStream::Close() {
+  GOOGLE_CHECK(!is_closed_);
+
+  is_closed_ = true;
+  if (close_no_eintr(file_) != 0) {
+    // The docs on close() do not specify whether a file descriptor is still
+    // open after close() fails with EIO.  However, the glibc source code
+    // seems to indicate that it is not.
+    errno_ = errno;
+    return false;
+  }
+
+  return true;
+}
+
+bool FileOutputStream::CopyingFileOutputStream::Write(
+    const void* buffer, int size) {
+  GOOGLE_CHECK(!is_closed_);
+  int total_written = 0;
+
+  const uint8* buffer_base = reinterpret_cast<const uint8*>(buffer);
+
+  while (total_written < size) {
+    int bytes;
+    do {
+      bytes = write(file_, buffer_base + total_written, size - total_written);
+    } while (bytes < 0 && errno == EINTR);
+
+    if (bytes <= 0) {
+      // Write error.
+
+      // FIXME(kenton):  According to the man page, if write() returns zero,
+      //   there was no error; write() simply did not write anything.  It's
+      //   unclear under what circumstances this might happen, but presumably
+      //   errno won't be set in this case.  I am confused as to how such an
+      //   event should be handled.  For now I'm treating it as an error, since
+      //   retrying seems like it could lead to an infinite loop.  I suspect
+      //   this never actually happens anyway.
+
+      if (bytes < 0) {
+        errno_ = errno;
+      }
+      return false;
+    }
+    total_written += bytes;
+  }
+
+  return true;
+}
+
+// ===================================================================
+
+IstreamInputStream::IstreamInputStream(istream* input, int block_size)
+  : copying_input_(input),
+    impl_(&copying_input_, block_size) {
+}
+
+IstreamInputStream::~IstreamInputStream() {}
+
+bool IstreamInputStream::Next(const void** data, int* size) {
+  return impl_.Next(data, size);
+}
+
+void IstreamInputStream::BackUp(int count) {
+  impl_.BackUp(count);
+}
+
+bool IstreamInputStream::Skip(int count) {
+  return impl_.Skip(count);
+}
+
+int64 IstreamInputStream::ByteCount() const {
+  return impl_.ByteCount();
+}
+
+IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream(
+    istream* input)
+  : input_(input) {
+}
+
+IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {}
+
+int IstreamInputStream::CopyingIstreamInputStream::Read(
+    void* buffer, int size) {
+  input_->read(reinterpret_cast<char*>(buffer), size);
+  int result = input_->gcount();
+  if (result == 0 && input_->fail() && !input_->eof()) {
+    return -1;
+  }
+  return result;
+}
+
+// ===================================================================
+
+OstreamOutputStream::OstreamOutputStream(ostream* output, int block_size)
+  : copying_output_(output),
+    impl_(&copying_output_, block_size) {
+}
+
+OstreamOutputStream::~OstreamOutputStream() {
+  impl_.Flush();
+}
+
+bool OstreamOutputStream::Next(void** data, int* size) {
+  return impl_.Next(data, size);
+}
+
+void OstreamOutputStream::BackUp(int count) {
+  impl_.BackUp(count);
+}
+
+int64 OstreamOutputStream::ByteCount() const {
+  return impl_.ByteCount();
+}
+
+OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream(
+    ostream* output)
+  : output_(output) {
+}
+
+OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() {
+}
+
+bool OstreamOutputStream::CopyingOstreamOutputStream::Write(
+    const void* buffer, int size) {
+  output_->write(reinterpret_cast<const char*>(buffer), size);
+  return output_->good();
+}
+
+// ===================================================================
+
+ConcatenatingInputStream::ConcatenatingInputStream(
+    ZeroCopyInputStream* const streams[], int count)
+  : streams_(streams), stream_count_(count), bytes_retired_(0) {
+}
+
+ConcatenatingInputStream::~ConcatenatingInputStream() {
+}
+
+bool ConcatenatingInputStream::Next(const void** data, int* size) {
+  while (stream_count_ > 0) {
+    if (streams_[0]->Next(data, size)) return true;
+
+    // That stream is done.  Advance to the next one.
+    bytes_retired_ += streams_[0]->ByteCount();
+    ++streams_;
+    --stream_count_;
+  }
+
+  // No more streams.
+  return false;
+}
+
+void ConcatenatingInputStream::BackUp(int count) {
+  if (stream_count_ > 0) {
+    streams_[0]->BackUp(count);
+  } else {
+    GOOGLE_LOG(DFATAL) << "Can't BackUp() after failed Next().";
+  }
+}
+
+bool ConcatenatingInputStream::Skip(int count) {
+  while (stream_count_ > 0) {
+    // Assume that ByteCount() can be used to find out how much we actually
+    // skipped when Skip() fails.
+    int64 target_byte_count = streams_[0]->ByteCount() + count;
+    if (streams_[0]->Skip(count)) return true;
+
+    // Hit the end of the stream.  Figure out how many more bytes we still have
+    // to skip.
+    int64 final_byte_count = streams_[0]->ByteCount();
+    GOOGLE_DCHECK_LT(final_byte_count, target_byte_count);
+    count = target_byte_count - final_byte_count;
+
+    // That stream is done.  Advance to the next one.
+    bytes_retired_ += final_byte_count;
+    ++streams_;
+    --stream_count_;
+  }
+
+  return false;
+}
+
+int64 ConcatenatingInputStream::ByteCount() const {
+  if (stream_count_ == 0) {
+    return bytes_retired_;
+  } else {
+    return bytes_retired_ + streams_[0]->ByteCount();
+  }
+}
+
+
+// ===================================================================
+
+LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input,
+                                         int64 limit)
+  : input_(input), limit_(limit) {
+  prior_bytes_read_ = input_->ByteCount();
+}
+
+LimitingInputStream::~LimitingInputStream() {
+  // If we overshot the limit, back up.
+  if (limit_ < 0) input_->BackUp(-limit_);
+}
+
+bool LimitingInputStream::Next(const void** data, int* size) {
+  if (limit_ <= 0) return false;
+  if (!input_->Next(data, size)) return false;
+
+  limit_ -= *size;
+  if (limit_ < 0) {
+    // We overshot the limit.  Reduce *size to hide the rest of the buffer.
+    *size += limit_;
+  }
+  return true;
+}
+
+void LimitingInputStream::BackUp(int count) {
+  if (limit_ < 0) {
+    input_->BackUp(count - limit_);
+    limit_ = count;
+  } else {
+    input_->BackUp(count);
+    limit_ += count;
+  }
+}
+
+bool LimitingInputStream::Skip(int count) {
+  if (count > limit_) {
+    if (limit_ < 0) return false;
+    input_->Skip(limit_);
+    limit_ = 0;
+    return false;
+  } else {
+    if (!input_->Skip(count)) return false;
+    limit_ -= count;
+    return true;
+  }
+}
+
+int64 LimitingInputStream::ByteCount() const {
+  if (limit_ < 0) {
+    return input_->ByteCount() + limit_ - prior_bytes_read_;
+  } else {
+    return input_->ByteCount() - prior_bytes_read_;
+  }
+}
+
+
+// ===================================================================
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.h b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.h
new file mode 100644
index 0000000..0746fa6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -0,0 +1,358 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains common implementations of the interfaces defined in
+// zero_copy_stream.h which are only included in the full (non-lite)
+// protobuf library.  These implementations include Unix file descriptors
+// and C++ iostreams.  See also:  zero_copy_stream_impl_lite.h
+
+#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
+#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
+
+#include <string>
+#include <iosfwd>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/stubs/common.h>
+
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+
+// ===================================================================
+
+// A ZeroCopyInputStream which reads from a file descriptor.
+//
+// FileInputStream is preferred over using an ifstream with IstreamInputStream.
+// The latter will introduce an extra layer of buffering, harming performance.
+// Also, it's conceivable that FileInputStream could someday be enhanced
+// to use zero-copy file descriptors on OSs which support them.
+class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
+ public:
+  // Creates a stream that reads from the given Unix file descriptor.
+  // If a block_size is given, it specifies the number of bytes that
+  // should be read and returned with each call to Next().  Otherwise,
+  // a reasonable default is used.
+  explicit FileInputStream(int file_descriptor, int block_size = -1);
+  ~FileInputStream();
+
+  // Flushes any buffers and closes the underlying file.  Returns false if
+  // an error occurs during the process; use GetErrno() to examine the error.
+  // Even if an error occurs, the file descriptor is closed when this returns.
+  bool Close();
+
+  // By default, the file descriptor is not closed when the stream is
+  // destroyed.  Call SetCloseOnDelete(true) to change that.  WARNING:
+  // This leaves no way for the caller to detect if close() fails.  If
+  // detecting close() errors is important to you, you should arrange
+  // to close the descriptor yourself.
+  void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
+
+  // If an I/O error has occurred on this file descriptor, this is the
+  // errno from that error.  Otherwise, this is zero.  Once an error
+  // occurs, the stream is broken and all subsequent operations will
+  // fail.
+  int GetErrno() { return copying_input_.GetErrno(); }
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+ private:
+  class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
+   public:
+    CopyingFileInputStream(int file_descriptor);
+    ~CopyingFileInputStream();
+
+    bool Close();
+    void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
+    int GetErrno() { return errno_; }
+
+    // implements CopyingInputStream ---------------------------------
+    int Read(void* buffer, int size);
+    int Skip(int count);
+
+   private:
+    // The file descriptor.
+    const int file_;
+    bool close_on_delete_;
+    bool is_closed_;
+
+    // The errno of the I/O error, if one has occurred.  Otherwise, zero.
+    int errno_;
+
+    // Did we try to seek once and fail?  If so, we assume this file descriptor
+    // doesn't support seeking and won't try again.
+    bool previous_seek_failed_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
+  };
+
+  CopyingFileInputStream copying_input_;
+  CopyingInputStreamAdaptor impl_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream which writes to a file descriptor.
+//
+// FileOutputStream is preferred over using an ofstream with
+// OstreamOutputStream.  The latter will introduce an extra layer of buffering,
+// harming performance.  Also, it's conceivable that FileOutputStream could
+// someday be enhanced to use zero-copy file descriptors on OSs which
+// support them.
+class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Creates a stream that writes to the given Unix file descriptor.
+  // If a block_size is given, it specifies the size of the buffers
+  // that should be returned by Next().  Otherwise, a reasonable default
+  // is used.
+  explicit FileOutputStream(int file_descriptor, int block_size = -1);
+  ~FileOutputStream();
+
+  // Flushes any buffers and closes the underlying file.  Returns false if
+  // an error occurs during the process; use GetErrno() to examine the error.
+  // Even if an error occurs, the file descriptor is closed when this returns.
+  bool Close();
+
+  // Flushes FileOutputStream's buffers but does not close the
+  // underlying file. No special measures are taken to ensure that
+  // underlying operating system file object is synchronized to disk.
+  bool Flush();
+
+  // By default, the file descriptor is not closed when the stream is
+  // destroyed.  Call SetCloseOnDelete(true) to change that.  WARNING:
+  // This leaves no way for the caller to detect if close() fails.  If
+  // detecting close() errors is important to you, you should arrange
+  // to close the descriptor yourself.
+  void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
+
+  // If an I/O error has occurred on this file descriptor, this is the
+  // errno from that error.  Otherwise, this is zero.  Once an error
+  // occurs, the stream is broken and all subsequent operations will
+  // fail.
+  int GetErrno() { return copying_output_.GetErrno(); }
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
+   public:
+    CopyingFileOutputStream(int file_descriptor);
+    ~CopyingFileOutputStream();
+
+    bool Close();
+    void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
+    int GetErrno() { return errno_; }
+
+    // implements CopyingOutputStream --------------------------------
+    bool Write(const void* buffer, int size);
+
+   private:
+    // The file descriptor.
+    const int file_;
+    bool close_on_delete_;
+    bool is_closed_;
+
+    // The errno of the I/O error, if one has occurred.  Otherwise, zero.
+    int errno_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
+  };
+
+  CopyingFileOutputStream copying_output_;
+  CopyingOutputStreamAdaptor impl_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyInputStream which reads from a C++ istream.
+//
+// Note that for reading files (or anything represented by a file descriptor),
+// FileInputStream is more efficient.
+class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
+ public:
+  // Creates a stream that reads from the given C++ istream.
+  // If a block_size is given, it specifies the number of bytes that
+  // should be read and returned with each call to Next().  Otherwise,
+  // a reasonable default is used.
+  explicit IstreamInputStream(istream* stream, int block_size = -1);
+  ~IstreamInputStream();
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+ private:
+  class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
+   public:
+    CopyingIstreamInputStream(istream* input);
+    ~CopyingIstreamInputStream();
+
+    // implements CopyingInputStream ---------------------------------
+    int Read(void* buffer, int size);
+    // (We use the default implementation of Skip().)
+
+   private:
+    // The stream.
+    istream* input_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
+  };
+
+  CopyingIstreamInputStream copying_input_;
+  CopyingInputStreamAdaptor impl_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream which writes to a C++ ostream.
+//
+// Note that for writing files (or anything represented by a file descriptor),
+// FileOutputStream is more efficient.
+class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Creates a stream that writes to the given C++ ostream.
+  // If a block_size is given, it specifies the size of the buffers
+  // that should be returned by Next().  Otherwise, a reasonable default
+  // is used.
+  explicit OstreamOutputStream(ostream* stream, int block_size = -1);
+  ~OstreamOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream {
+   public:
+    CopyingOstreamOutputStream(ostream* output);
+    ~CopyingOstreamOutputStream();
+
+    // implements CopyingOutputStream --------------------------------
+    bool Write(const void* buffer, int size);
+
+   private:
+    // The stream.
+    ostream* output_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
+  };
+
+  CopyingOstreamOutputStream copying_output_;
+  CopyingOutputStreamAdaptor impl_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyInputStream which reads from several other streams in sequence.
+// ConcatenatingInputStream is unable to distinguish between end-of-stream
+// and read errors in the underlying streams, so it assumes any errors mean
+// end-of-stream.  So, if the underlying streams fail for any other reason,
+// ConcatenatingInputStream may do odd things.  It is suggested that you do
+// not use ConcatenatingInputStream on streams that might produce read errors
+// other than end-of-stream.
+class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
+ public:
+  // All streams passed in as well as the array itself must remain valid
+  // until the ConcatenatingInputStream is destroyed.
+  ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
+  ~ConcatenatingInputStream();
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+
+ private:
+  // As streams are retired, streams_ is incremented and count_ is
+  // decremented.
+  ZeroCopyInputStream* const* streams_;
+  int stream_count_;
+  int64 bytes_retired_;  // Bytes read from previous streams.
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyInputStream which wraps some other stream and limits it to
+// a particular byte count.
+class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
+ public:
+  LimitingInputStream(ZeroCopyInputStream* input, int64 limit);
+  ~LimitingInputStream();
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+
+ private:
+  ZeroCopyInputStream* input_;
+  int64 limit_;  // Decreases as we go, becomes negative if we overshoot.
+  int64 prior_bytes_read_;  // Bytes read on underlying stream at construction
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
+};
+
+// ===================================================================
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
new file mode 100644
index 0000000..e6ca88c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -0,0 +1,438 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+
+#include <algorithm>
+#include <limits>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+namespace {
+
+// Default block size for Copying{In,Out}putStreamAdaptor.
+static const int kDefaultBlockSize = 8192;
+
+}  // namespace
+
+// ===================================================================
+
+ArrayInputStream::ArrayInputStream(const void* data, int size,
+                                   int block_size)
+  : data_(reinterpret_cast<const uint8*>(data)),
+    size_(size),
+    block_size_(block_size > 0 ? block_size : size),
+    position_(0),
+    last_returned_size_(0) {
+}
+
+ArrayInputStream::~ArrayInputStream() {
+}
+
+bool ArrayInputStream::Next(const void** data, int* size) {
+  if (position_ < size_) {
+    last_returned_size_ = std::min(block_size_, size_ - position_);
+    *data = data_ + position_;
+    *size = last_returned_size_;
+    position_ += last_returned_size_;
+    return true;
+  } else {
+    // We're at the end of the array.
+    last_returned_size_ = 0;   // Don't let caller back up.
+    return false;
+  }
+}
+
+void ArrayInputStream::BackUp(int count) {
+  GOOGLE_CHECK_GT(last_returned_size_, 0)
+      << "BackUp() can only be called after a successful Next().";
+  GOOGLE_CHECK_LE(count, last_returned_size_);
+  GOOGLE_CHECK_GE(count, 0);
+  position_ -= count;
+  last_returned_size_ = 0;  // Don't let caller back up further.
+}
+
+bool ArrayInputStream::Skip(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  last_returned_size_ = 0;   // Don't let caller back up.
+  if (count > size_ - position_) {
+    position_ = size_;
+    return false;
+  } else {
+    position_ += count;
+    return true;
+  }
+}
+
+int64 ArrayInputStream::ByteCount() const {
+  return position_;
+}
+
+
+// ===================================================================
+
+ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
+  : data_(reinterpret_cast<uint8*>(data)),
+    size_(size),
+    block_size_(block_size > 0 ? block_size : size),
+    position_(0),
+    last_returned_size_(0) {
+}
+
+ArrayOutputStream::~ArrayOutputStream() {
+}
+
+bool ArrayOutputStream::Next(void** data, int* size) {
+  if (position_ < size_) {
+    last_returned_size_ = std::min(block_size_, size_ - position_);
+    *data = data_ + position_;
+    *size = last_returned_size_;
+    position_ += last_returned_size_;
+    return true;
+  } else {
+    // We're at the end of the array.
+    last_returned_size_ = 0;   // Don't let caller back up.
+    return false;
+  }
+}
+
+void ArrayOutputStream::BackUp(int count) {
+  GOOGLE_CHECK_GT(last_returned_size_, 0)
+      << "BackUp() can only be called after a successful Next().";
+  GOOGLE_CHECK_LE(count, last_returned_size_);
+  GOOGLE_CHECK_GE(count, 0);
+  position_ -= count;
+  last_returned_size_ = 0;  // Don't let caller back up further.
+}
+
+int64 ArrayOutputStream::ByteCount() const {
+  return position_;
+}
+
+// ===================================================================
+
+StringOutputStream::StringOutputStream(string* target)
+  : target_(target) {
+}
+
+StringOutputStream::~StringOutputStream() {
+}
+
+bool StringOutputStream::Next(void** data, int* size) {
+  GOOGLE_CHECK(target_ != NULL);
+  int old_size = target_->size();
+
+  // Grow the string.
+  if (old_size < target_->capacity()) {
+    // Resize the string to match its capacity, since we can get away
+    // without a memory allocation this way.
+    STLStringResizeUninitialized(target_, target_->capacity());
+  } else {
+    // Size has reached capacity, try to double the size.
+    if (old_size > std::numeric_limits<int>::max() / 2) {
+      // Can not double the size otherwise it is going to cause integer
+      // overflow in the expression below: old_size * 2 ";
+      GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for "
+                 << "StringOutputStream.";
+      return false;
+    }
+    // Double the size, also make sure that the new size is at least
+    // kMinimumSize.
+    STLStringResizeUninitialized(
+        target_,
+        std::max(old_size * 2,
+                 kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
+  }
+
+  *data = mutable_string_data(target_) + old_size;
+  *size = target_->size() - old_size;
+  return true;
+}
+
+void StringOutputStream::BackUp(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  GOOGLE_CHECK(target_ != NULL);
+  GOOGLE_CHECK_LE(count, target_->size());
+  target_->resize(target_->size() - count);
+}
+
+int64 StringOutputStream::ByteCount() const {
+  GOOGLE_CHECK(target_ != NULL);
+  return target_->size();
+}
+
+void StringOutputStream::SetString(string* target) {
+  target_ = target;
+}
+
+// ===================================================================
+
+LazyStringOutputStream::LazyStringOutputStream(
+    ResultCallback<string*>* callback)
+    : StringOutputStream(NULL),
+      callback_(GOOGLE_CHECK_NOTNULL(callback)),
+      string_is_set_(false) {
+}
+
+LazyStringOutputStream::~LazyStringOutputStream() {
+}
+
+bool LazyStringOutputStream::Next(void** data, int* size) {
+  if (!string_is_set_) {
+    SetString(callback_->Run());
+    string_is_set_ = true;
+  }
+  return StringOutputStream::Next(data, size);
+}
+
+int64 LazyStringOutputStream::ByteCount() const {
+  return string_is_set_ ? StringOutputStream::ByteCount() : 0;
+}
+
+// ===================================================================
+
+CopyingInputStream::~CopyingInputStream() {}
+
+int CopyingInputStream::Skip(int count) {
+  char junk[4096];
+  int skipped = 0;
+  while (skipped < count) {
+    int bytes =
+        Read(junk, std::min(count - skipped, implicit_cast<int>(sizeof(junk))));
+    if (bytes <= 0) {
+      // EOF or read error.
+      return skipped;
+    }
+    skipped += bytes;
+  }
+  return skipped;
+}
+
+CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
+    CopyingInputStream* copying_stream, int block_size)
+  : copying_stream_(copying_stream),
+    owns_copying_stream_(false),
+    failed_(false),
+    position_(0),
+    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
+    buffer_used_(0),
+    backup_bytes_(0) {
+}
+
+CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
+  if (owns_copying_stream_) {
+    delete copying_stream_;
+  }
+}
+
+bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
+  if (failed_) {
+    // Already failed on a previous read.
+    return false;
+  }
+
+  AllocateBufferIfNeeded();
+
+  if (backup_bytes_ > 0) {
+    // We have data left over from a previous BackUp(), so just return that.
+    *data = buffer_.get() + buffer_used_ - backup_bytes_;
+    *size = backup_bytes_;
+    backup_bytes_ = 0;
+    return true;
+  }
+
+  // Read new data into the buffer.
+  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
+  if (buffer_used_ <= 0) {
+    // EOF or read error.  We don't need the buffer anymore.
+    if (buffer_used_ < 0) {
+      // Read error (not EOF).
+      failed_ = true;
+    }
+    FreeBuffer();
+    return false;
+  }
+  position_ += buffer_used_;
+
+  *size = buffer_used_;
+  *data = buffer_.get();
+  return true;
+}
+
+void CopyingInputStreamAdaptor::BackUp(int count) {
+  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
+    << " BackUp() can only be called after Next().";
+  GOOGLE_CHECK_LE(count, buffer_used_)
+    << " Can't back up over more bytes than were returned by the last call"
+       " to Next().";
+  GOOGLE_CHECK_GE(count, 0)
+    << " Parameter to BackUp() can't be negative.";
+
+  backup_bytes_ = count;
+}
+
+bool CopyingInputStreamAdaptor::Skip(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+
+  if (failed_) {
+    // Already failed on a previous read.
+    return false;
+  }
+
+  // First skip any bytes left over from a previous BackUp().
+  if (backup_bytes_ >= count) {
+    // We have more data left over than we're trying to skip.  Just chop it.
+    backup_bytes_ -= count;
+    return true;
+  }
+
+  count -= backup_bytes_;
+  backup_bytes_ = 0;
+
+  int skipped = copying_stream_->Skip(count);
+  position_ += skipped;
+  return skipped == count;
+}
+
+int64 CopyingInputStreamAdaptor::ByteCount() const {
+  return position_ - backup_bytes_;
+}
+
+void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
+  if (buffer_.get() == NULL) {
+    buffer_.reset(new uint8[buffer_size_]);
+  }
+}
+
+void CopyingInputStreamAdaptor::FreeBuffer() {
+  GOOGLE_CHECK_EQ(backup_bytes_, 0);
+  buffer_used_ = 0;
+  buffer_.reset();
+}
+
+// ===================================================================
+
+CopyingOutputStream::~CopyingOutputStream() {}
+
+CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
+    CopyingOutputStream* copying_stream, int block_size)
+  : copying_stream_(copying_stream),
+    owns_copying_stream_(false),
+    failed_(false),
+    position_(0),
+    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
+    buffer_used_(0) {
+}
+
+CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
+  WriteBuffer();
+  if (owns_copying_stream_) {
+    delete copying_stream_;
+  }
+}
+
+bool CopyingOutputStreamAdaptor::Flush() {
+  return WriteBuffer();
+}
+
+bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
+  if (buffer_used_ == buffer_size_) {
+    if (!WriteBuffer()) return false;
+  }
+
+  AllocateBufferIfNeeded();
+
+  *data = buffer_.get() + buffer_used_;
+  *size = buffer_size_ - buffer_used_;
+  buffer_used_ = buffer_size_;
+  return true;
+}
+
+void CopyingOutputStreamAdaptor::BackUp(int count) {
+  GOOGLE_CHECK_GE(count, 0);
+  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
+    << " BackUp() can only be called after Next().";
+  GOOGLE_CHECK_LE(count, buffer_used_)
+    << " Can't back up over more bytes than were returned by the last call"
+       " to Next().";
+
+  buffer_used_ -= count;
+}
+
+int64 CopyingOutputStreamAdaptor::ByteCount() const {
+  return position_ + buffer_used_;
+}
+
+bool CopyingOutputStreamAdaptor::WriteBuffer() {
+  if (failed_) {
+    // Already failed on a previous write.
+    return false;
+  }
+
+  if (buffer_used_ == 0) return true;
+
+  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
+    position_ += buffer_used_;
+    buffer_used_ = 0;
+    return true;
+  } else {
+    failed_ = true;
+    FreeBuffer();
+    return false;
+  }
+}
+
+void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
+  if (buffer_ == NULL) {
+    buffer_.reset(new uint8[buffer_size_]);
+  }
+}
+
+void CopyingOutputStreamAdaptor::FreeBuffer() {
+  buffer_used_ = 0;
+  buffer_.reset();
+}
+
+// ===================================================================
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.h
new file mode 100644
index 0000000..9d81ccf
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -0,0 +1,411 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains common implementations of the interfaces defined in
+// zero_copy_stream.h which are included in the "lite" protobuf library.
+// These implementations cover I/O on raw arrays and strings, as well as
+// adaptors which make it easy to implement streams based on traditional
+// streams.  Of course, many users will probably want to write their own
+// implementations of these interfaces specific to the particular I/O
+// abstractions they prefer to use, but these should cover the most common
+// cases.
+
+#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
+#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <iosfwd>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+// ===================================================================
+
+// A ZeroCopyInputStream backed by an in-memory array of bytes.
+class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
+ public:
+  // Create an InputStream that returns the bytes pointed to by "data".
+  // "data" remains the property of the caller but must remain valid until
+  // the stream is destroyed.  If a block_size is given, calls to Next()
+  // will return data blocks no larger than the given size.  Otherwise, the
+  // first call to Next() returns the entire array.  block_size is mainly
+  // useful for testing; in production you would probably never want to set
+  // it.
+  ArrayInputStream(const void* data, int size, int block_size = -1);
+  ~ArrayInputStream();
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+
+ private:
+  const uint8* const data_;  // The byte array.
+  const int size_;           // Total size of the array.
+  const int block_size_;     // How many bytes to return at a time.
+
+  int position_;
+  int last_returned_size_;   // How many bytes we returned last time Next()
+                             // was called (used for error checking only).
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream backed by an in-memory array of bytes.
+class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Create an OutputStream that writes to the bytes pointed to by "data".
+  // "data" remains the property of the caller but must remain valid until
+  // the stream is destroyed.  If a block_size is given, calls to Next()
+  // will return data blocks no larger than the given size.  Otherwise, the
+  // first call to Next() returns the entire array.  block_size is mainly
+  // useful for testing; in production you would probably never want to set
+  // it.
+  ArrayOutputStream(void* data, int size, int block_size = -1);
+  ~ArrayOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  uint8* const data_;        // The byte array.
+  const int size_;           // Total size of the array.
+  const int block_size_;     // How many bytes to return at a time.
+
+  int position_;
+  int last_returned_size_;   // How many bytes we returned last time Next()
+                             // was called (used for error checking only).
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
+};
+
+// ===================================================================
+
+// A ZeroCopyOutputStream which appends bytes to a string.
+class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
+ public:
+  // Create a StringOutputStream which appends bytes to the given string.
+  // The string remains property of the caller, but it is mutated in arbitrary
+  // ways and MUST NOT be accessed in any way until you're done with the
+  // stream. Either be sure there's no further usage, or (safest) destroy the
+  // stream before using the contents.
+  //
+  // Hint:  If you call target->reserve(n) before creating the stream,
+  //   the first call to Next() will return at least n bytes of buffer
+  //   space.
+  explicit StringOutputStream(string* target);
+  ~StringOutputStream();
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ protected:
+  void SetString(string* target);
+
+ private:
+  static const int kMinimumSize = 16;
+
+  string* target_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
+};
+
+// LazyStringOutputStream is a StringOutputStream with lazy acquisition of
+// the output string from a callback. The string is owned externally, and not
+// deleted in the stream destructor.
+class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream {
+ public:
+  // Callback should be permanent (non-self-deleting). Ownership is transferred
+  // to the LazyStringOutputStream.
+  explicit LazyStringOutputStream(ResultCallback<string*>* callback);
+  ~LazyStringOutputStream();
+
+  // implements ZeroCopyOutputStream, overriding StringOutputStream -----------
+  bool Next(void** data, int* size);
+  int64 ByteCount() const;
+
+ private:
+  const google::protobuf::scoped_ptr<ResultCallback<string*> > callback_;
+  bool string_is_set_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyStringOutputStream);
+};
+
+// Note:  There is no StringInputStream.  Instead, just create an
+// ArrayInputStream as follows:
+//   ArrayInputStream input(str.data(), str.size());
+
+// ===================================================================
+
+// A generic traditional input stream interface.
+//
+// Lots of traditional input streams (e.g. file descriptors, C stdio
+// streams, and C++ iostreams) expose an interface where every read
+// involves copying bytes into a buffer.  If you want to take such an
+// interface and make a ZeroCopyInputStream based on it, simply implement
+// CopyingInputStream and then use CopyingInputStreamAdaptor.
+//
+// CopyingInputStream implementations should avoid buffering if possible.
+// CopyingInputStreamAdaptor does its own buffering and will read data
+// in large blocks.
+class LIBPROTOBUF_EXPORT CopyingInputStream {
+ public:
+  virtual ~CopyingInputStream();
+
+  // Reads up to "size" bytes into the given buffer.  Returns the number of
+  // bytes read.  Read() waits until at least one byte is available, or
+  // returns zero if no bytes will ever become available (EOF), or -1 if a
+  // permanent read error occurred.
+  virtual int Read(void* buffer, int size) = 0;
+
+  // Skips the next "count" bytes of input.  Returns the number of bytes
+  // actually skipped.  This will always be exactly equal to "count" unless
+  // EOF was reached or a permanent read error occurred.
+  //
+  // The default implementation just repeatedly calls Read() into a scratch
+  // buffer.
+  virtual int Skip(int count);
+};
+
+// A ZeroCopyInputStream which reads from a CopyingInputStream.  This is
+// useful for implementing ZeroCopyInputStreams that read from traditional
+// streams.  Note that this class is not really zero-copy.
+//
+// If you want to read from file descriptors or C++ istreams, this is
+// already implemented for you:  use FileInputStream or IstreamInputStream
+// respectively.
+class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
+ public:
+  // Creates a stream that reads from the given CopyingInputStream.
+  // If a block_size is given, it specifies the number of bytes that
+  // should be read and returned with each call to Next().  Otherwise,
+  // a reasonable default is used.  The caller retains ownership of
+  // copying_stream unless SetOwnsCopyingStream(true) is called.
+  explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
+                                     int block_size = -1);
+  ~CopyingInputStreamAdaptor();
+
+  // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
+  // delete the underlying CopyingInputStream when it is destroyed.
+  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
+
+  // implements ZeroCopyInputStream ----------------------------------
+  bool Next(const void** data, int* size);
+  void BackUp(int count);
+  bool Skip(int count);
+  int64 ByteCount() const;
+
+ private:
+  // Insures that buffer_ is not NULL.
+  void AllocateBufferIfNeeded();
+  // Frees the buffer and resets buffer_used_.
+  void FreeBuffer();
+
+  // The underlying copying stream.
+  CopyingInputStream* copying_stream_;
+  bool owns_copying_stream_;
+
+  // True if we have seen a permenant error from the underlying stream.
+  bool failed_;
+
+  // The current position of copying_stream_, relative to the point where
+  // we started reading.
+  int64 position_;
+
+  // Data is read into this buffer.  It may be NULL if no buffer is currently
+  // in use.  Otherwise, it points to an array of size buffer_size_.
+  google::protobuf::scoped_array<uint8> buffer_;
+  const int buffer_size_;
+
+  // Number of valid bytes currently in the buffer (i.e. the size last
+  // returned by Next()).  0 <= buffer_used_ <= buffer_size_.
+  int buffer_used_;
+
+  // Number of bytes in the buffer which were backed up over by a call to
+  // BackUp().  These need to be returned again.
+  // 0 <= backup_bytes_ <= buffer_used_
+  int backup_bytes_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
+};
+
+// ===================================================================
+
+// A generic traditional output stream interface.
+//
+// Lots of traditional output streams (e.g. file descriptors, C stdio
+// streams, and C++ iostreams) expose an interface where every write
+// involves copying bytes from a buffer.  If you want to take such an
+// interface and make a ZeroCopyOutputStream based on it, simply implement
+// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
+//
+// CopyingOutputStream implementations should avoid buffering if possible.
+// CopyingOutputStreamAdaptor does its own buffering and will write data
+// in large blocks.
+class LIBPROTOBUF_EXPORT CopyingOutputStream {
+ public:
+  virtual ~CopyingOutputStream();
+
+  // Writes "size" bytes from the given buffer to the output.  Returns true
+  // if successful, false on a write error.
+  virtual bool Write(const void* buffer, int size) = 0;
+};
+
+// A ZeroCopyOutputStream which writes to a CopyingOutputStream.  This is
+// useful for implementing ZeroCopyOutputStreams that write to traditional
+// streams.  Note that this class is not really zero-copy.
+//
+// If you want to write to file descriptors or C++ ostreams, this is
+// already implemented for you:  use FileOutputStream or OstreamOutputStream
+// respectively.
+class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
+ public:
+  // Creates a stream that writes to the given Unix file descriptor.
+  // If a block_size is given, it specifies the size of the buffers
+  // that should be returned by Next().  Otherwise, a reasonable default
+  // is used.
+  explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
+                                      int block_size = -1);
+  ~CopyingOutputStreamAdaptor();
+
+  // Writes all pending data to the underlying stream.  Returns false if a
+  // write error occurred on the underlying stream.  (The underlying
+  // stream itself is not necessarily flushed.)
+  bool Flush();
+
+  // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
+  // delete the underlying CopyingOutputStream when it is destroyed.
+  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
+
+  // implements ZeroCopyOutputStream ---------------------------------
+  bool Next(void** data, int* size);
+  void BackUp(int count);
+  int64 ByteCount() const;
+
+ private:
+  // Write the current buffer, if it is present.
+  bool WriteBuffer();
+  // Insures that buffer_ is not NULL.
+  void AllocateBufferIfNeeded();
+  // Frees the buffer.
+  void FreeBuffer();
+
+  // The underlying copying stream.
+  CopyingOutputStream* copying_stream_;
+  bool owns_copying_stream_;
+
+  // True if we have seen a permenant error from the underlying stream.
+  bool failed_;
+
+  // The current position of copying_stream_, relative to the point where
+  // we started writing.
+  int64 position_;
+
+  // Data is written from this buffer.  It may be NULL if no buffer is
+  // currently in use.  Otherwise, it points to an array of size buffer_size_.
+  google::protobuf::scoped_array<uint8> buffer_;
+  const int buffer_size_;
+
+  // Number of valid bytes currently in the buffer (i.e. the size last
+  // returned by Next()).  When BackUp() is called, we just reduce this.
+  // 0 <= buffer_used_ <= buffer_size_.
+  int buffer_used_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
+};
+
+// ===================================================================
+
+// mutable_string_data() and as_string_data() are workarounds to improve
+// the performance of writing new data to an existing string.  Unfortunately
+// the methods provided by the string class are suboptimal, and using memcpy()
+// is mildly annoying because it requires its pointer args to be non-NULL even
+// if we ask it to copy 0 bytes.  Furthermore, string_as_array() has the
+// property that it always returns NULL if its arg is the empty string, exactly
+// what we want to avoid if we're using it in conjunction with memcpy()!
+// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
+// where s is a string*.  Without C++11, &(*s)[0] is not guaranteed to be safe,
+// so we use string_as_array(), and live with the extra logic that tests whether
+// *s is empty.
+
+// Return a pointer to mutable characters underlying the given string.  The
+// return value is valid until the next time the string is resized.  We
+// trust the caller to treat the return value as an array of length s->size().
+inline char* mutable_string_data(string* s) {
+#ifdef LANG_CXX11
+  // This should be simpler & faster than string_as_array() because the latter
+  // is guaranteed to return NULL when *s is empty, so it has to check for that.
+  return &(*s)[0];
+#else
+  return string_as_array(s);
+#endif
+}
+
+// as_string_data(s) is equivalent to
+//  ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
+// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
+// code can avoid that check.
+inline std::pair<char*, bool> as_string_data(string* s) {
+  char *p = mutable_string_data(s);
+#ifdef LANG_CXX11
+  return std::make_pair(p, true);
+#else
+  return make_pair(p, p != NULL);
+#endif
+}
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_unittest.cc
new file mode 100644
index 0000000..a9db887
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -0,0 +1,1007 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Testing strategy:  For each type of I/O (array, string, file, etc.) we
+// create an output stream and write some data to it, then create a
+// corresponding input stream to read the same data back and expect it to
+// match.  When the data is written, it is written in several small chunks
+// of varying sizes, with a BackUp() after each chunk.  It is read back
+// similarly, but with chunks separated at different points.  The whole
+// process is run with a variety of block sizes for both the input and
+// the output.
+//
+// TODO(kenton):  Rewrite this test to bring it up to the standards of all
+//   the other proto2 tests.  May want to wait for gTest to implement
+//   "parametized tests" so that one set of tests can be used on all the
+//   implementations.
+
+
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <sstream>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#if HAVE_ZLIB
+#include <google/protobuf/io/gzip_stream.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/testing/file.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace {
+
+#ifdef _WIN32
+#define pipe(fds) _pipe(fds, 4096, O_BINARY)
+#endif
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
+#endif
+#endif
+
+class IoTest : public testing::Test {
+ protected:
+  // Test helpers.
+
+  // Helper to write an array of data to an output stream.
+  bool WriteToOutput(ZeroCopyOutputStream* output, const void* data, int size);
+  // Helper to read a fixed-length array of data from an input stream.
+  int ReadFromInput(ZeroCopyInputStream* input, void* data, int size);
+  // Write a string to the output stream.
+  void WriteString(ZeroCopyOutputStream* output, const string& str);
+  // Read a number of bytes equal to the size of the given string and checks
+  // that it matches the string.
+  void ReadString(ZeroCopyInputStream* input, const string& str);
+  // Writes some text to the output stream in a particular order.  Returns
+  // the number of bytes written, incase the caller needs that to set up an
+  // input stream.
+  int WriteStuff(ZeroCopyOutputStream* output);
+  // Reads text from an input stream and expects it to match what
+  // WriteStuff() writes.
+  void ReadStuff(ZeroCopyInputStream* input);
+
+  // Similar to WriteStuff, but performs more sophisticated testing.
+  int WriteStuffLarge(ZeroCopyOutputStream* output);
+  // Reads and tests a stream that should have been written to
+  // via WriteStuffLarge().
+  void ReadStuffLarge(ZeroCopyInputStream* input);
+
+#if HAVE_ZLIB
+  string Compress(const string& data, const GzipOutputStream::Options& options);
+  string Uncompress(const string& data);
+#endif
+
+  static const int kBlockSizes[];
+  static const int kBlockSizeCount;
+};
+
+const int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64};
+const int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes);
+
+bool IoTest::WriteToOutput(ZeroCopyOutputStream* output,
+                           const void* data, int size) {
+  const uint8* in = reinterpret_cast<const uint8*>(data);
+  int in_size = size;
+
+  void* out;
+  int out_size;
+
+  while (true) {
+    if (!output->Next(&out, &out_size)) {
+      return false;
+    }
+    EXPECT_GT(out_size, 0);
+
+    if (in_size <= out_size) {
+      memcpy(out, in, in_size);
+      output->BackUp(out_size - in_size);
+      return true;
+    }
+
+    memcpy(out, in, out_size);
+    in += out_size;
+    in_size -= out_size;
+  }
+}
+
+#define MAX_REPEATED_ZEROS 100
+
+int IoTest::ReadFromInput(ZeroCopyInputStream* input, void* data, int size) {
+  uint8* out = reinterpret_cast<uint8*>(data);
+  int out_size = size;
+
+  const void* in;
+  int in_size = 0;
+
+  int repeated_zeros = 0;
+
+  while (true) {
+    if (!input->Next(&in, &in_size)) {
+      return size - out_size;
+    }
+    EXPECT_GT(in_size, -1);
+    if (in_size == 0) {
+      repeated_zeros++;
+    } else {
+      repeated_zeros = 0;
+    }
+    EXPECT_LT(repeated_zeros, MAX_REPEATED_ZEROS);
+
+    if (out_size <= in_size) {
+      memcpy(out, in, out_size);
+      if (in_size > out_size) {
+        input->BackUp(in_size - out_size);
+      }
+      return size;  // Copied all of it.
+    }
+
+    memcpy(out, in, in_size);
+    out += in_size;
+    out_size -= in_size;
+  }
+}
+
+void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) {
+  EXPECT_TRUE(WriteToOutput(output, str.c_str(), str.size()));
+}
+
+void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) {
+  google::protobuf::scoped_array<char> buffer(new char[str.size() + 1]);
+  buffer[str.size()] = '\0';
+  EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
+  EXPECT_STREQ(str.c_str(), buffer.get());
+}
+
+int IoTest::WriteStuff(ZeroCopyOutputStream* output) {
+  WriteString(output, "Hello world!\n");
+  WriteString(output, "Some te");
+  WriteString(output, "xt.  Blah blah.");
+  WriteString(output, "abcdefg");
+  WriteString(output, "01234567890123456789");
+  WriteString(output, "foobar");
+
+  EXPECT_EQ(output->ByteCount(), 68);
+
+  int result = output->ByteCount();
+  return result;
+}
+
+// Reads text from an input stream and expects it to match what WriteStuff()
+// writes.
+void IoTest::ReadStuff(ZeroCopyInputStream* input) {
+  ReadString(input, "Hello world!\n");
+  ReadString(input, "Some text.  ");
+  ReadString(input, "Blah ");
+  ReadString(input, "blah.");
+  ReadString(input, "abcdefg");
+  EXPECT_TRUE(input->Skip(20));
+  ReadString(input, "foo");
+  ReadString(input, "bar");
+
+  EXPECT_EQ(input->ByteCount(), 68);
+
+  uint8 byte;
+  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
+}
+
+int IoTest::WriteStuffLarge(ZeroCopyOutputStream* output) {
+  WriteString(output, "Hello world!\n");
+  WriteString(output, "Some te");
+  WriteString(output, "xt.  Blah blah.");
+  WriteString(output, string(100000, 'x'));  // A very long string
+  WriteString(output, string(100000, 'y'));  // A very long string
+  WriteString(output, "01234567890123456789");
+
+  EXPECT_EQ(output->ByteCount(), 200055);
+
+  int result = output->ByteCount();
+  return result;
+}
+
+// Reads text from an input stream and expects it to match what WriteStuff()
+// writes.
+void IoTest::ReadStuffLarge(ZeroCopyInputStream* input) {
+  ReadString(input, "Hello world!\nSome text.  ");
+  EXPECT_TRUE(input->Skip(5));
+  ReadString(input, "blah.");
+  EXPECT_TRUE(input->Skip(100000 - 10));
+  ReadString(input, string(10, 'x') + string(100000 - 20000, 'y'));
+  EXPECT_TRUE(input->Skip(20000 - 10));
+  ReadString(input, "yyyyyyyyyy01234567890123456789");
+
+  EXPECT_EQ(input->ByteCount(), 200055);
+
+  uint8 byte;
+  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
+}
+
+// ===================================================================
+
+TEST_F(IoTest, ArrayIo) {
+  const int kBufferSize = 256;
+  uint8 buffer[kBufferSize];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      int size;
+      {
+        ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+        size = WriteStuff(&output);
+      }
+      {
+        ArrayInputStream input(buffer, size, kBlockSizes[j]);
+        ReadStuff(&input);
+      }
+    }
+  }
+}
+
+TEST_F(IoTest, TwoSessionWrite) {
+  // Test that two concatenated write sessions read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "WhirledPeas";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      CodedOutputStream* coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strA));
+      coded_output->WriteRaw(strA, strlen(strA));
+      delete coded_output;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strB));
+      coded_output->WriteRaw(strB, strlen(strB));
+      delete coded_output;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      CodedInputStream* coded_input = new CodedInputStream(input);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize));
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize));
+
+      delete coded_input;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
+
+#if HAVE_ZLIB
+TEST_F(IoTest, GzipIo) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      for (int z = 0; z < kBlockSizeCount; z++) {
+        int gzip_buffer_size = kBlockSizes[z];
+        int size;
+        {
+          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::GZIP;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
+          WriteStuff(&gzout);
+          gzout.Close();
+          size = output.ByteCount();
+        }
+        {
+          ArrayInputStream input(buffer, size, kBlockSizes[j]);
+          GzipInputStream gzin(
+              &input, GzipInputStream::GZIP, gzip_buffer_size);
+          ReadStuff(&gzin);
+        }
+      }
+    }
+  }
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoWithFlush) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  // We start with i = 4 as we want a block size > 6. With block size <= 6
+  // Flush() fills up the entire 2K buffer with flush markers and the test
+  // fails. See documentation for Flush() for more detail.
+  for (int i = 4; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      for (int z = 0; z < kBlockSizeCount; z++) {
+        int gzip_buffer_size = kBlockSizes[z];
+        int size;
+        {
+          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::GZIP;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
+          WriteStuff(&gzout);
+          EXPECT_TRUE(gzout.Flush());
+          gzout.Close();
+          size = output.ByteCount();
+        }
+        {
+          ArrayInputStream input(buffer, size, kBlockSizes[j]);
+          GzipInputStream gzin(
+              &input, GzipInputStream::GZIP, gzip_buffer_size);
+          ReadStuff(&gzin);
+        }
+      }
+    }
+  }
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoContiguousFlushes) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+
+  int block_size = kBlockSizes[4];
+  int gzip_buffer_size = block_size;
+  int size;
+
+  ArrayOutputStream output(buffer, kBufferSize, block_size);
+  GzipOutputStream::Options options;
+  options.format = GzipOutputStream::GZIP;
+  if (gzip_buffer_size != -1) {
+    options.buffer_size = gzip_buffer_size;
+  }
+  GzipOutputStream gzout(&output, options);
+  WriteStuff(&gzout);
+  EXPECT_TRUE(gzout.Flush());
+  EXPECT_TRUE(gzout.Flush());
+  gzout.Close();
+  size = output.ByteCount();
+
+  ArrayInputStream input(buffer, size, block_size);
+  GzipInputStream gzin(
+      &input, GzipInputStream::GZIP, gzip_buffer_size);
+  ReadStuff(&gzin);
+
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoReadAfterFlush) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+
+  int block_size = kBlockSizes[4];
+  int gzip_buffer_size = block_size;
+  int size;
+  ArrayOutputStream output(buffer, kBufferSize, block_size);
+  GzipOutputStream::Options options;
+  options.format = GzipOutputStream::GZIP;
+  if (gzip_buffer_size != -1) {
+    options.buffer_size = gzip_buffer_size;
+  }
+
+  GzipOutputStream gzout(&output, options);
+  WriteStuff(&gzout);
+  EXPECT_TRUE(gzout.Flush());
+  size = output.ByteCount();
+
+  ArrayInputStream input(buffer, size, block_size);
+  GzipInputStream gzin(
+      &input, GzipInputStream::GZIP, gzip_buffer_size);
+  ReadStuff(&gzin);
+
+  gzout.Close();
+
+  delete [] buffer;
+}
+
+TEST_F(IoTest, ZlibIo) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      for (int z = 0; z < kBlockSizeCount; z++) {
+        int gzip_buffer_size = kBlockSizes[z];
+        int size;
+        {
+          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::ZLIB;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
+          WriteStuff(&gzout);
+          gzout.Close();
+          size = output.ByteCount();
+        }
+        {
+          ArrayInputStream input(buffer, size, kBlockSizes[j]);
+          GzipInputStream gzin(
+              &input, GzipInputStream::ZLIB, gzip_buffer_size);
+          ReadStuff(&gzin);
+        }
+      }
+    }
+  }
+  delete [] buffer;
+}
+
+TEST_F(IoTest, ZlibIoInputAutodetect) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  int size;
+  {
+    ArrayOutputStream output(buffer, kBufferSize);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::ZLIB;
+    GzipOutputStream gzout(&output, options);
+    WriteStuff(&gzout);
+    gzout.Close();
+    size = output.ByteCount();
+  }
+  {
+    ArrayInputStream input(buffer, size);
+    GzipInputStream gzin(&input, GzipInputStream::AUTO);
+    ReadStuff(&gzin);
+  }
+  {
+    ArrayOutputStream output(buffer, kBufferSize);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::GZIP;
+    GzipOutputStream gzout(&output, options);
+    WriteStuff(&gzout);
+    gzout.Close();
+    size = output.ByteCount();
+  }
+  {
+    ArrayInputStream input(buffer, size);
+    GzipInputStream gzin(&input, GzipInputStream::AUTO);
+    ReadStuff(&gzin);
+  }
+  delete [] buffer;
+}
+
+string IoTest::Compress(const string& data,
+                        const GzipOutputStream::Options& options) {
+  string result;
+  {
+    StringOutputStream output(&result);
+    GzipOutputStream gzout(&output, options);
+    WriteToOutput(&gzout, data.data(), data.size());
+  }
+  return result;
+}
+
+string IoTest::Uncompress(const string& data) {
+  string result;
+  {
+    ArrayInputStream input(data.data(), data.size());
+    GzipInputStream gzin(&input);
+    const void* buffer;
+    int size;
+    while (gzin.Next(&buffer, &size)) {
+      result.append(reinterpret_cast<const char*>(buffer), size);
+    }
+  }
+  return result;
+}
+
+TEST_F(IoTest, CompressionOptions) {
+  // Some ad-hoc testing of compression options.
+
+  string golden;
+  GOOGLE_CHECK_OK(File::GetContents(
+      TestSourceDir() +
+          "/google/protobuf/testdata/golden_message",
+      &golden, true));
+
+  GzipOutputStream::Options options;
+  string gzip_compressed = Compress(golden, options);
+
+  options.compression_level = 0;
+  string not_compressed = Compress(golden, options);
+
+  // Try zlib compression for fun.
+  options = GzipOutputStream::Options();
+  options.format = GzipOutputStream::ZLIB;
+  string zlib_compressed = Compress(golden, options);
+
+  // Uncompressed should be bigger than the original since it should have some
+  // sort of header.
+  EXPECT_GT(not_compressed.size(), golden.size());
+
+  // Higher compression levels should result in smaller sizes.
+  EXPECT_LT(zlib_compressed.size(), not_compressed.size());
+
+  // ZLIB format should differ from GZIP format.
+  EXPECT_TRUE(zlib_compressed != gzip_compressed);
+
+  // Everything should decompress correctly.
+  EXPECT_TRUE(Uncompress(not_compressed) == golden);
+  EXPECT_TRUE(Uncompress(gzip_compressed) == golden);
+  EXPECT_TRUE(Uncompress(zlib_compressed) == golden);
+}
+
+TEST_F(IoTest, TwoSessionWriteGzip) {
+  // Test that two concatenated gzip streams can be read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "QuickBrownFox";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      GzipOutputStream* gzout = new GzipOutputStream(output);
+      CodedOutputStream* coded_output = new CodedOutputStream(gzout);
+      int32 outlen = strlen(strA) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strA, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      gzout = new GzipOutputStream(output);
+      coded_output = new CodedOutputStream(gzout);
+      outlen = strlen(strB) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strB, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      GzipInputStream* gzin = new GzipInputStream(input);
+      CodedInputStream* coded_input = new CodedInputStream(gzin);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize))
+          << "strA=" << strA << " in=" << temp_buffer;
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize))
+          << " out_block_size=" << kBlockSizes[i]
+          << " in_block_size=" << kBlockSizes[j]
+          << " pos=" << pos
+          << " size=" << size
+          << " strB=" << strB << " in=" << temp_buffer;
+
+      delete coded_input;
+      delete gzin;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipInputByteCountAfterClosed) {
+  string golden = "abcdefghijklmnopqrstuvwxyz";
+  string compressed = Compress(golden, GzipOutputStream::Options());
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    ArrayInputStream arr_input(compressed.data(), compressed.size(),
+                               kBlockSizes[i]);
+    GzipInputStream gz_input(&arr_input);
+    const void* buffer;
+    int size;
+    while (gz_input.Next(&buffer, &size)) {
+      EXPECT_LE(gz_input.ByteCount(), golden.size());
+    }
+    EXPECT_EQ(golden.size(), gz_input.ByteCount());
+  }
+}
+
+TEST_F(IoTest, GzipInputByteCountAfterClosedConcatenatedStreams) {
+  string golden1 = "abcdefghijklmnopqrstuvwxyz";
+  string golden2 = "the quick brown fox jumps over the lazy dog";
+  const size_t total_size = golden1.size() + golden2.size();
+  string compressed = Compress(golden1, GzipOutputStream::Options()) +
+                      Compress(golden2, GzipOutputStream::Options());
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    ArrayInputStream arr_input(compressed.data(), compressed.size(),
+                               kBlockSizes[i]);
+    GzipInputStream gz_input(&arr_input);
+    const void* buffer;
+    int size;
+    while (gz_input.Next(&buffer, &size)) {
+      EXPECT_LE(gz_input.ByteCount(), total_size);
+    }
+    EXPECT_EQ(total_size, gz_input.ByteCount());
+  }
+}
+#endif
+
+// There is no string input, only string output.  Also, it doesn't support
+// explicit block sizes.  So, we'll only run one test and we'll use
+// ArrayInput to read back the results.
+TEST_F(IoTest, StringIo) {
+  string str;
+  {
+    StringOutputStream output(&str);
+    WriteStuff(&output);
+  }
+  {
+    ArrayInputStream input(str.data(), str.size());
+    ReadStuff(&input);
+  }
+}
+
+
+// To test files, we create a temporary file, write, read, truncate, repeat.
+TEST_F(IoTest, FileIo) {
+  string filename = TestTempDir() + "/zero_copy_stream_test_file";
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      // Make a temporary file.
+      int file =
+        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
+      ASSERT_GE(file, 0);
+
+      {
+        FileOutputStream output(file, kBlockSizes[i]);
+        WriteStuff(&output);
+        EXPECT_EQ(0, output.GetErrno());
+      }
+
+      // Rewind.
+      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
+
+      {
+        FileInputStream input(file, kBlockSizes[j]);
+        ReadStuff(&input);
+        EXPECT_EQ(0, input.GetErrno());
+      }
+
+      close(file);
+    }
+  }
+}
+
+#if HAVE_ZLIB
+TEST_F(IoTest, GzipFileIo) {
+  string filename = TestTempDir() + "/zero_copy_stream_test_file";
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      // Make a temporary file.
+      int file =
+        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
+      ASSERT_GE(file, 0);
+      {
+        FileOutputStream output(file, kBlockSizes[i]);
+        GzipOutputStream gzout(&output);
+        WriteStuffLarge(&gzout);
+        gzout.Close();
+        output.Flush();
+        EXPECT_EQ(0, output.GetErrno());
+      }
+
+      // Rewind.
+      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
+
+      {
+        FileInputStream input(file, kBlockSizes[j]);
+        GzipInputStream gzin(&input);
+        ReadStuffLarge(&gzin);
+        EXPECT_EQ(0, input.GetErrno());
+      }
+
+      close(file);
+    }
+  }
+}
+#endif
+
+// MSVC raises various debugging exceptions if we try to use a file
+// descriptor of -1, defeating our tests below.  This class will disable
+// these debug assertions while in scope.
+class MsvcDebugDisabler {
+ public:
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+  MsvcDebugDisabler() {
+    old_handler_ = _set_invalid_parameter_handler(MyHandler);
+    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, 0);
+  }
+  ~MsvcDebugDisabler() {
+    old_handler_ = _set_invalid_parameter_handler(old_handler_);
+    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, old_mode_);
+  }
+
+  static void MyHandler(const wchar_t *expr,
+                        const wchar_t *func,
+                        const wchar_t *file,
+                        unsigned int line,
+                        uintptr_t pReserved) {
+    // do nothing
+  }
+
+  _invalid_parameter_handler old_handler_;
+  int old_mode_;
+#else
+  // Dummy constructor and destructor to ensure that GCC doesn't complain
+  // that debug_disabler is an unused variable.
+  MsvcDebugDisabler() {}
+  ~MsvcDebugDisabler() {}
+#endif
+};
+
+// Test that FileInputStreams report errors correctly.
+TEST_F(IoTest, FileReadError) {
+  MsvcDebugDisabler debug_disabler;
+
+  // -1 = invalid file descriptor.
+  FileInputStream input(-1);
+
+  const void* buffer;
+  int size;
+  EXPECT_FALSE(input.Next(&buffer, &size));
+  EXPECT_EQ(EBADF, input.GetErrno());
+}
+
+// Test that FileOutputStreams report errors correctly.
+TEST_F(IoTest, FileWriteError) {
+  MsvcDebugDisabler debug_disabler;
+
+  // -1 = invalid file descriptor.
+  FileOutputStream input(-1);
+
+  void* buffer;
+  int size;
+
+  // The first call to Next() succeeds because it doesn't have anything to
+  // write yet.
+  EXPECT_TRUE(input.Next(&buffer, &size));
+
+  // Second call fails.
+  EXPECT_FALSE(input.Next(&buffer, &size));
+
+  EXPECT_EQ(EBADF, input.GetErrno());
+}
+
+// Pipes are not seekable, so File{Input,Output}Stream ends up doing some
+// different things to handle them.  We'll test by writing to a pipe and
+// reading back from it.
+TEST_F(IoTest, PipeIo) {
+  int files[2];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      // Need to create a new pipe each time because ReadStuff() expects
+      // to see EOF at the end.
+      ASSERT_EQ(pipe(files), 0);
+
+      {
+        FileOutputStream output(files[1], kBlockSizes[i]);
+        WriteStuff(&output);
+        EXPECT_EQ(0, output.GetErrno());
+      }
+      close(files[1]);  // Send EOF.
+
+      {
+        FileInputStream input(files[0], kBlockSizes[j]);
+        ReadStuff(&input);
+        EXPECT_EQ(0, input.GetErrno());
+      }
+      close(files[0]);
+    }
+  }
+}
+
+// Test using C++ iostreams.
+TEST_F(IoTest, IostreamIo) {
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      {
+        stringstream stream;
+
+        {
+          OstreamOutputStream output(&stream, kBlockSizes[i]);
+          WriteStuff(&output);
+          EXPECT_FALSE(stream.fail());
+        }
+
+        {
+          IstreamInputStream input(&stream, kBlockSizes[j]);
+          ReadStuff(&input);
+          EXPECT_TRUE(stream.eof());
+        }
+      }
+
+      {
+        stringstream stream;
+
+        {
+          OstreamOutputStream output(&stream, kBlockSizes[i]);
+          WriteStuffLarge(&output);
+          EXPECT_FALSE(stream.fail());
+        }
+
+        {
+          IstreamInputStream input(&stream, kBlockSizes[j]);
+          ReadStuffLarge(&input);
+          EXPECT_TRUE(stream.eof());
+        }
+      }
+    }
+  }
+}
+
+// To test ConcatenatingInputStream, we create several ArrayInputStreams
+// covering a buffer and then concatenate them.
+TEST_F(IoTest, ConcatenatingInputStream) {
+  const int kBufferSize = 256;
+  uint8 buffer[kBufferSize];
+
+  // Fill the buffer.
+  ArrayOutputStream output(buffer, kBufferSize);
+  WriteStuff(&output);
+
+  // Now split it up into multiple streams of varying sizes.
+  ASSERT_EQ(68, output.ByteCount());  // Test depends on this.
+  ArrayInputStream input1(buffer     , 12);
+  ArrayInputStream input2(buffer + 12,  7);
+  ArrayInputStream input3(buffer + 19,  6);
+  ArrayInputStream input4(buffer + 25, 15);
+  ArrayInputStream input5(buffer + 40,  0);
+  // Note:  We want to make sure we have a stream boundary somewhere between
+  // bytes 42 and 62, which is the range that it Skip()ed by ReadStuff().  This
+  // tests that a bug that existed in the original code for Skip() is fixed.
+  ArrayInputStream input6(buffer + 40, 10);
+  ArrayInputStream input7(buffer + 50, 18);  // Total = 68 bytes.
+
+  ZeroCopyInputStream* streams[] =
+    {&input1, &input2, &input3, &input4, &input5, &input6, &input7};
+
+  // Create the concatenating stream and read.
+  ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams));
+  ReadStuff(&input);
+}
+
+// To test LimitingInputStream, we write our golden text to a buffer, then
+// create an ArrayInputStream that contains the whole buffer (not just the
+// bytes written), then use a LimitingInputStream to limit it just to the
+// bytes written.
+TEST_F(IoTest, LimitingInputStream) {
+  const int kBufferSize = 256;
+  uint8 buffer[kBufferSize];
+
+  // Fill the buffer.
+  ArrayOutputStream output(buffer, kBufferSize);
+  WriteStuff(&output);
+
+  // Set up input.
+  ArrayInputStream array_input(buffer, kBufferSize);
+  LimitingInputStream input(&array_input, output.ByteCount());
+
+  ReadStuff(&input);
+}
+
+// Checks that ByteCount works correctly for LimitingInputStreams where the
+// underlying stream has already been read.
+TEST_F(IoTest, LimitingInputStreamByteCount) {
+  const int kHalfBufferSize = 128;
+  const int kBufferSize = kHalfBufferSize * 2;
+  uint8 buffer[kBufferSize];
+
+  // Set up input. Only allow half to be read at once.
+  ArrayInputStream array_input(buffer, kBufferSize, kHalfBufferSize);
+  const void* data;
+  int size;
+  EXPECT_TRUE(array_input.Next(&data, &size));
+  EXPECT_EQ(kHalfBufferSize, array_input.ByteCount());
+  // kHalfBufferSize - 1 to test limiting logic as well.
+  LimitingInputStream input(&array_input, kHalfBufferSize - 1);
+  EXPECT_EQ(0, input.ByteCount());
+  EXPECT_TRUE(input.Next(&data, &size));
+  EXPECT_EQ(kHalfBufferSize - 1 , input.ByteCount());
+}
+
+// Check that a zero-size array doesn't confuse the code.
+TEST(ZeroSizeArray, Input) {
+  ArrayInputStream input(NULL, 0);
+  const void* data;
+  int size;
+  EXPECT_FALSE(input.Next(&data, &size));
+}
+
+TEST(ZeroSizeArray, Output) {
+  ArrayOutputStream output(NULL, 0);
+  void* data;
+  int size;
+  EXPECT_FALSE(output.Next(&data, &size));
+}
+
+}  // namespace
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/lite_arena_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/lite_arena_unittest.cc
new file mode 100644
index 0000000..f0bee88
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/lite_arena_unittest.cc
@@ -0,0 +1,83 @@
+// 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.
+
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(LiteArenaTest, MapNoHeapAllocation) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  google::protobuf::ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  google::protobuf::Arena arena(options);
+  string data;
+  data.reserve(128 * 1024);
+
+  {
+    // TODO(teboring): Enable no heap check when ArenaStringPtr is used in
+    // Map.
+    // google::protobuf::internal::NoHeapChecker no_heap;
+
+    protobuf_unittest::TestArenaMapLite* from =
+        google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(&arena);
+    google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
+    from->SerializeToString(&data);
+
+    protobuf_unittest::TestArenaMapLite* to =
+        google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(&arena);
+    to->ParseFromString(data);
+    google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
+  }
+}
+
+TEST(LiteArenaTest, UnknownFieldMemLeak) {
+  google::protobuf::Arena arena;
+  protobuf_unittest::ForeignMessageArenaLite* message =
+      google::protobuf::Arena::CreateMessage<protobuf_unittest::ForeignMessageArenaLite>(
+          &arena);
+  string data = "\012\000";
+  int original_capacity = data.capacity();
+  while (data.capacity() <= original_capacity) {
+    data.append("a");
+  }
+  data[1] = data.size() - 2;
+  message->ParseFromString(data);
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/lite_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/lite_unittest.cc
new file mode 100644
index 0000000..3ca3fba
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/lite_unittest.cc
@@ -0,0 +1,718 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <string>
+#include <iostream>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/unittest_lite.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
+
+using namespace std;
+
+namespace {
+// Helper methods to test parsing merge behavior.
+void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) {
+  GOOGLE_CHECK(message.optional_int32() == 3);
+  GOOGLE_CHECK(message.optional_int64() == 2);
+  GOOGLE_CHECK(message.optional_string() == "hello");
+}
+
+void AssignParsingMergeMessages(
+    google::protobuf::unittest::TestAllTypesLite* msg1,
+    google::protobuf::unittest::TestAllTypesLite* msg2,
+    google::protobuf::unittest::TestAllTypesLite* msg3) {
+  msg1->set_optional_int32(1);
+  msg2->set_optional_int64(2);
+  msg3->set_optional_int32(3);
+  msg3->set_optional_string("hello");
+}
+
+void SetAllTypesInEmptyMessageUnknownFields(
+    google::protobuf::unittest::TestEmptyMessageLite* empty_message) {
+  protobuf_unittest::TestAllTypesLite message;
+  google::protobuf::TestUtilLite::ExpectClear(message);
+  google::protobuf::TestUtilLite::SetAllFields(&message);
+  string data = message.SerializeAsString();
+  empty_message->ParseFromString(data);
+}
+
+void SetSomeTypesInEmptyMessageUnknownFields(
+    google::protobuf::unittest::TestEmptyMessageLite* empty_message) {
+  protobuf_unittest::TestAllTypesLite message;
+  google::protobuf::TestUtilLite::ExpectClear(message);
+  message.set_optional_int32(101);
+  message.set_optional_int64(102);
+  message.set_optional_uint32(103);
+  message.set_optional_uint64(104);
+  string data = message.SerializeAsString();
+  empty_message->ParseFromString(data);
+}
+
+}  // namespace
+
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
+int main(int argc, char* argv[]) {
+  string data, data2, packed_data;
+
+  {
+    protobuf_unittest::TestAllTypesLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectClear(message);
+    google::protobuf::TestUtilLite::SetAllFields(&message);
+    message2.CopyFrom(message);
+    data = message.SerializeAsString();
+    message3.ParseFromString(data);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2);
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3);
+    google::protobuf::TestUtilLite::ModifyRepeatedFields(&message);
+    google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectClear(message);
+  }
+
+  {
+    protobuf_unittest::TestAllExtensionsLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetAllExtensions(&message);
+    message2.CopyFrom(message);
+    string extensions_data = message.SerializeAsString();
+    message3.ParseFromString(extensions_data);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2);
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3);
+    google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message);
+    google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedTypesLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+    google::protobuf::TestUtilLite::SetPackedFields(&message);
+    message2.CopyFrom(message);
+    packed_data = message.SerializeAsString();
+    message3.ParseFromString(packed_data);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3);
+    google::protobuf::TestUtilLite::ModifyPackedFields(&message);
+    google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedExtensionsLite message, message2, message3;
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetPackedExtensions(&message);
+    message2.CopyFrom(message);
+    string packed_extensions_data = message.SerializeAsString();
+    GOOGLE_CHECK(packed_extensions_data == packed_data);
+    message3.ParseFromString(packed_extensions_data);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3);
+    google::protobuf::TestUtilLite::ModifyPackedExtensions(&message);
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+  }
+
+  {
+    // Test that if an optional or required message/group field appears multiple
+    // times in the input, they need to be merged.
+    google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator;
+    google::protobuf::unittest::TestAllTypesLite* msg1;
+    google::protobuf::unittest::TestAllTypesLite* msg2;
+    google::protobuf::unittest::TestAllTypesLite* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD)                \
+  msg1 = generator.add_##FIELD();                   \
+  msg2 = generator.add_##FIELD();                   \
+  msg3 = generator.add_##FIELD();                   \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+    ASSIGN_REPEATED_FIELD(field1);
+    ASSIGN_REPEATED_FIELD(field2);
+    ASSIGN_REPEATED_FIELD(field3);
+    ASSIGN_REPEATED_FIELD(ext1);
+    ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD)                \
+  msg1 = generator.add_##FIELD()->mutable_field1(); \
+  msg2 = generator.add_##FIELD()->mutable_field1(); \
+  msg3 = generator.add_##FIELD()->mutable_field1(); \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+    ASSIGN_REPEATED_GROUP(group1);
+    ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+    string buffer;
+    generator.SerializeToString(&buffer);
+    google::protobuf::unittest::TestParsingMergeLite parsing_merge;
+    parsing_merge.ParseFromString(buffer);
+
+    // Required and optional fields should be merged.
+    ExpectMessageMerged(parsing_merge.required_all_types());
+    ExpectMessageMerged(parsing_merge.optional_all_types());
+    ExpectMessageMerged(
+        parsing_merge.optionalgroup().optional_group_all_types());
+    ExpectMessageMerged(parsing_merge.GetExtension(
+        google::protobuf::unittest::TestParsingMergeLite::optional_ext));
+
+    // Repeated fields should not be merged.
+    GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3);
+    GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3);
+    GOOGLE_CHECK(parsing_merge.ExtensionSize(
+        google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3);
+  }
+
+  // Test unknown fields support for lite messages.
+  {
+    protobuf_unittest::TestAllTypesLite message, message2;
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    google::protobuf::TestUtilLite::ExpectClear(message);
+    google::protobuf::TestUtilLite::SetAllFields(&message);
+    data = message.SerializeAsString();
+    empty_message.ParseFromString(data);
+    data.clear();
+    data = empty_message.SerializeAsString();
+    message2.ParseFromString(data);
+    data = message2.SerializeAsString();
+    google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectClear(message);
+  }
+
+  {
+    protobuf_unittest::TestAllExtensionsLite message, message2;
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetAllExtensions(&message);
+    data = message.SerializeAsString();
+    empty_message.ParseFromString(data);
+    data.clear();
+    data = empty_message.SerializeAsString();
+    message2.ParseFromString(data);
+    data = message2.SerializeAsString();
+    google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedTypesLite message, message2;
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+    google::protobuf::TestUtilLite::SetPackedFields(&message);
+    data = message.SerializeAsString();
+    empty_message.ParseFromString(data);
+    data.clear();
+    data = empty_message.SerializeAsString();
+    message2.ParseFromString(data);
+    data = message2.SerializeAsString();
+    google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedClear(message);
+  }
+
+  {
+    protobuf_unittest::TestPackedExtensionsLite message, message2;
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+    google::protobuf::TestUtilLite::SetPackedExtensions(&message);
+    data = message.SerializeAsString();
+    empty_message.ParseFromString(data);
+    data.clear();
+    data = empty_message.SerializeAsString();
+    message2.ParseFromString(data);
+    data = message2.SerializeAsString();
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2);
+    message.Clear();
+    google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
+  }
+
+  {
+    // Test Unknown fields swap
+    protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2;
+    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
+    SetSomeTypesInEmptyMessageUnknownFields(&empty_message2);
+    data = empty_message.SerializeAsString();
+    data2 = empty_message2.SerializeAsString();
+    empty_message.Swap(&empty_message2);
+    GOOGLE_CHECK_EQ(data, empty_message2.SerializeAsString());
+    GOOGLE_CHECK_EQ(data2, empty_message.SerializeAsString());
+  }
+
+  {
+    // Test unknown fields swap with self
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
+    data = empty_message.SerializeAsString();
+    empty_message.Swap(&empty_message);
+    GOOGLE_CHECK_EQ(data, empty_message.SerializeAsString());
+  }
+
+  {
+    // Test MergeFrom with unknown fields
+    protobuf_unittest::TestAllTypesLite message, message2;
+    protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2;
+    message.set_optional_int32(101);
+    message.add_repeated_int32(201);
+    message.set_optional_nested_enum(google::protobuf::unittest::TestAllTypesLite::BAZ);
+    message2.set_optional_int64(102);
+    message2.add_repeated_int64(202);
+    message2.set_optional_foreign_enum(google::protobuf::unittest::FOREIGN_LITE_BAZ);
+
+    data = message.SerializeAsString();
+    empty_message.ParseFromString(data);
+    data = message2.SerializeAsString();
+    empty_message2.ParseFromString(data);
+    message.MergeFrom(message2);
+    empty_message.MergeFrom(empty_message2);
+
+    data = empty_message.SerializeAsString();
+    message2.ParseFromString(data);
+    // We do not compare the serialized output of a normal message and a lite
+    // message because the order of fields do not match. We convert lite message
+    // back into normal message, then compare.
+    GOOGLE_CHECK_EQ(message.SerializeAsString(), message2.SerializeAsString());
+  }
+
+  {
+    // Test unknown enum value
+    protobuf_unittest::TestAllTypesLite message;
+    string buffer;
+    {
+      google::protobuf::io::StringOutputStream output_stream(&buffer);
+      google::protobuf::io::CodedOutputStream coded_output(&output_stream);
+      google::protobuf::internal::WireFormatLite::WriteTag(
+          protobuf_unittest::TestAllTypesLite::kOptionalNestedEnumFieldNumber,
+          google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output);
+      coded_output.WriteVarint32(10);
+      google::protobuf::internal::WireFormatLite::WriteTag(
+          protobuf_unittest::TestAllTypesLite::kRepeatedNestedEnumFieldNumber,
+          google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output);
+      coded_output.WriteVarint32(20);
+    }
+    message.ParseFromString(buffer);
+    data = message.SerializeAsString();
+    GOOGLE_CHECK_EQ(data, buffer);
+  }
+
+  {
+    // Test Clear with unknown fields
+    protobuf_unittest::TestEmptyMessageLite empty_message;
+    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
+    empty_message.Clear();
+    GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size());
+  }
+
+  // Tests for map lite =============================================
+
+  {
+    // Accessors
+    protobuf_unittest::TestMapLite message;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+    google::protobuf::MapLiteTestUtil::ModifyMapFields(&message);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message);
+  }
+
+  {
+    // SetMapFieldsInitialized
+    protobuf_unittest::TestMapLite message;
+
+    google::protobuf::MapLiteTestUtil::SetMapFieldsInitialized(&message);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSetInitialized(message);
+  }
+
+  {
+    // Clear
+    protobuf_unittest::TestMapLite message;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+    message.Clear();
+    google::protobuf::MapLiteTestUtil::ExpectClear(message);
+  }
+
+  {
+    // ClearMessageMap
+    protobuf_unittest::TestMessageMapLite message;
+
+    // Creates a TestAllTypes with default value
+    google::protobuf::TestUtilLite::ExpectClear(
+        (*message.mutable_map_int32_message())[0]);
+  }
+
+  {
+    // CopyFrom
+    protobuf_unittest::TestMapLite message1, message2;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+    message2.CopyFrom(message1);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+    // Copying from self should be a no-op.
+    message2.CopyFrom(message2);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+  {
+    // CopyFromMessageMap
+    protobuf_unittest::TestMessageMapLite message1, message2;
+
+    (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+    (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+    message1.CopyFrom(message2);
+
+    // Checks repeated field is overwritten.
+    EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+    EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+  }
+
+  {
+    // SwapWithEmpty
+    protobuf_unittest::TestMapLite message1, message2;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+    google::protobuf::MapLiteTestUtil::ExpectClear(message2);
+
+    message1.Swap(&message2);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+    google::protobuf::MapLiteTestUtil::ExpectClear(message1);
+  }
+
+  {
+    // SwapWithSelf
+    protobuf_unittest::TestMapLite message;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+    message.Swap(&message);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // SwapWithOther
+    protobuf_unittest::TestMapLite message1, message2;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message2);
+    google::protobuf::MapLiteTestUtil::ModifyMapFields(&message2);
+
+    message1.Swap(&message2);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message1);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+  {
+    // CopyConstructor
+    protobuf_unittest::TestMapLite message1;
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+    protobuf_unittest::TestMapLite message2(message1);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+  {
+    // CopyAssignmentOperator
+    protobuf_unittest::TestMapLite message1;
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+    protobuf_unittest::TestMapLite message2;
+    message2 = message1;
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+    // Make sure that self-assignment does something sane.
+    message2.operator=(message2);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+  {
+    // NonEmptyMergeFrom
+    protobuf_unittest::TestMapLite message1, message2;
+
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+    // This field will test merging into an empty spot.
+    (*message2.mutable_map_int32_int32())[1] = 1;
+    message1.mutable_map_int32_int32()->erase(1);
+
+    // This tests overwriting.
+    (*message2.mutable_map_int32_double())[1] = 1;
+    (*message1.mutable_map_int32_double())[1] = 2;
+
+    message1.MergeFrom(message2);
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+  }
+
+  {
+    // MergeFromMessageMap
+    protobuf_unittest::TestMessageMapLite message1, message2;
+
+    (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+    (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+    message1.MergeFrom(message2);
+
+    // Checks repeated field is overwritten.
+    EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+    EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+  }
+
+  {
+    // Test the generated SerializeWithCachedSizesToArray()
+    protobuf_unittest::TestMapLite message1, message2;
+    string data;
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+    int size = message1.ByteSize();
+    data.resize(size);
+    ::google::protobuf::uint8* start = reinterpret_cast< ::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data));
+    ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+  {
+    // Test the generated SerializeWithCachedSizes()
+    protobuf_unittest::TestMapLite message1, message2;
+    google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+    int size = message1.ByteSize();
+    string data;
+    data.resize(size);
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      google::protobuf::io::ArrayOutputStream array_stream(
+          ::google::protobuf::string_as_array(&data), size, 1);
+      google::protobuf::io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+    EXPECT_TRUE(message2.ParseFromString(data));
+    google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+  }
+
+
+  {
+    // Proto2UnknownEnum
+    protobuf_unittest::TestEnumMapPlusExtraLite from;
+    (*from.mutable_known_map_field())[0] =
+        protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE;
+    (*from.mutable_unknown_map_field())[0] =
+        protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE;
+    string data;
+    from.SerializeToString(&data);
+
+    protobuf_unittest::TestEnumMapLite to;
+    EXPECT_TRUE(to.ParseFromString(data));
+    EXPECT_EQ(0, to.unknown_map_field().size());
+    EXPECT_FALSE(to.mutable_unknown_fields()->empty());
+    EXPECT_EQ(1, to.known_map_field().size());
+    EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE,
+              to.known_map_field().at(0));
+
+    data.clear();
+    from.Clear();
+    to.SerializeToString(&data);
+    EXPECT_TRUE(from.ParseFromString(data));
+    EXPECT_EQ(1, from.known_map_field().size());
+    EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE,
+              from.known_map_field().at(0));
+    EXPECT_EQ(1, from.unknown_map_field().size());
+    EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE,
+              from.unknown_map_field().at(0));
+  }
+
+  {
+    // StandardWireFormat
+    protobuf_unittest::TestMapLite message;
+    string data = "\x0A\x04\x08\x01\x10\x01";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(1, message.map_int32_int32().at(1));
+  }
+
+  {
+    // UnorderedWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // put value before key in wire format
+    string data = "\x0A\x04\x10\x01\x08\x02";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(1, message.map_int32_int32().at(2));
+  }
+
+  {
+    // DuplicatedKeyWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // Two key fields in wire format
+    string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(1, message.map_int32_int32().at(2));
+  }
+
+  {
+    // DuplicatedValueWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // Two value fields in wire format
+    string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(2, message.map_int32_int32().at(1));
+  }
+
+  {
+    // MissedKeyWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // No key field in wire format
+    string data = "\x0A\x02\x10\x01";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(1, message.map_int32_int32().at(0));
+  }
+
+  {
+    // MissedValueWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // No value field in wire format
+    string data = "\x0A\x02\x08\x01";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(0, message.map_int32_int32().at(1));
+  }
+
+  {
+    // UnknownFieldWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // Unknown field in wire format
+    string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+
+    EXPECT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(1, message.map_int32_int32().size());
+    EXPECT_EQ(3, message.map_int32_int32().at(2));
+  }
+
+  {
+    // CorruptedWireFormat
+    protobuf_unittest::TestMapLite message;
+
+    // corrupted data in wire format
+    string data = "\x0A\x06\x08\x02\x11\x03";
+
+    EXPECT_FALSE(message.ParseFromString(data));
+  }
+
+  {
+    // IsInitialized
+    protobuf_unittest::TestRequiredMessageMapLite map_message;
+
+    // Add an uninitialized message.
+    (*map_message.mutable_map_field())[0];
+    EXPECT_FALSE(map_message.IsInitialized());
+
+    // Initialize uninitialized message
+    (*map_message.mutable_map_field())[0].set_a(0);
+    (*map_message.mutable_map_field())[0].set_b(0);
+    (*map_message.mutable_map_field())[0].set_c(0);
+    EXPECT_TRUE(map_message.IsInitialized());
+  }
+
+  {
+      // Check that adding more values to enum does not corrupt message
+      // when passed through an old client.
+      protobuf_unittest::V2MessageLite v2_message;
+      v2_message.set_int_field(800);
+      // Set enum field to the value not understood by the old client.
+      v2_message.set_enum_field(protobuf_unittest::V2_SECOND);
+      string v2_bytes = v2_message.SerializeAsString();
+
+      protobuf_unittest::V1MessageLite v1_message;
+      v1_message.ParseFromString(v2_bytes);
+      EXPECT_TRUE(v1_message.IsInitialized());
+      EXPECT_EQ(v1_message.int_field(), v2_message.int_field());
+      // V1 client does not understand V2_SECOND value, so it discards it and
+      // uses default value instead.
+      EXPECT_EQ(v1_message.enum_field(), protobuf_unittest::V1_FIRST);
+
+      // However, when re-serialized, it should preserve enum value.
+      string v1_bytes = v1_message.SerializeAsString();
+
+      protobuf_unittest::V2MessageLite same_v2_message;
+      same_v2_message.ParseFromString(v1_bytes);
+
+      EXPECT_EQ(v2_message.int_field(), same_v2_message.int_field());
+      EXPECT_EQ(v2_message.enum_field(), same_v2_message.enum_field());
+  }
+
+  std::cout << "PASS" << std::endl;
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map.h b/src/third_party/protobuf-3/src/google/protobuf/map.h
new file mode 100644
index 0000000..6f1a71e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map.h
@@ -0,0 +1,1721 @@
+// 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_MAP_H__
+#define GOOGLE_PROTOBUF_MAP_H__
+
+#include <google/protobuf/stubs/hash.h>
+#include <iterator>
+#include <limits>  // To support Visual Studio 2008
+#include <set>
+#include <utility>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_enum_util.h>
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/descriptor.h>
+#if __cpp_exceptions && LANG_CXX11
+#include <random>
+#endif
+
+namespace google {
+namespace protobuf {
+
+// The Map and MapIterator types are provided by this header file.
+// Please avoid using other types defined here, unless they are public
+// types within Map or MapIterator, such as Map::value_type.
+template <typename Key, typename T>
+class Map;
+
+class MapIterator;
+
+template <typename Enum> struct is_proto_enum;
+
+namespace internal {
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+class MapFieldLite;
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+class MapField;
+
+template <typename Key, typename T>
+class TypeDefinedMapFieldBase;
+
+class DynamicMapField;
+
+class GeneratedMessageReflection;
+}  // namespace internal
+
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD)                        \
+  if (type() != EXPECTEDTYPE) {                                 \
+    GOOGLE_LOG(FATAL)                                                  \
+        << "Protocol Buffer map usage error:\n"                 \
+        << METHOD << " type does not match\n"                   \
+        << "  Expected : "                                      \
+        << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n"   \
+        << "  Actual   : "                                      \
+        << FieldDescriptor::CppTypeName(type());                \
+  }
+
+// MapKey is an union type for representing any possible
+// map key.
+class LIBPROTOBUF_EXPORT MapKey {
+ public:
+  MapKey() : type_(0) {
+  }
+  MapKey(const MapKey& other) : type_(0) {
+    CopyFrom(other);
+  }
+
+  ~MapKey() {
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      delete val_.string_value_;
+    }
+  }
+
+  FieldDescriptor::CppType type() const {
+    if (type_ == 0) {
+      GOOGLE_LOG(FATAL)
+          << "Protocol Buffer map usage error:\n"
+          << "MapKey::type MapKey is not initialized. "
+          << "Call set methods to initialize MapKey.";
+    }
+    return (FieldDescriptor::CppType)type_;
+  }
+
+  void SetInt64Value(int64 value) {
+    SetType(FieldDescriptor::CPPTYPE_INT64);
+    val_.int64_value_ = value;
+  }
+  void SetUInt64Value(uint64 value) {
+    SetType(FieldDescriptor::CPPTYPE_UINT64);
+    val_.uint64_value_ = value;
+  }
+  void SetInt32Value(int32 value) {
+    SetType(FieldDescriptor::CPPTYPE_INT32);
+    val_.int32_value_ = value;
+  }
+  void SetUInt32Value(uint32 value) {
+    SetType(FieldDescriptor::CPPTYPE_UINT32);
+    val_.uint32_value_ = value;
+  }
+  void SetBoolValue(bool value) {
+    SetType(FieldDescriptor::CPPTYPE_BOOL);
+    val_.bool_value_ = value;
+  }
+  void SetStringValue(const string& val) {
+    SetType(FieldDescriptor::CPPTYPE_STRING);
+    *val_.string_value_ = val;
+  }
+
+  int64 GetInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+               "MapKey::GetInt64Value");
+    return val_.int64_value_;
+  }
+  uint64 GetUInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+               "MapKey::GetUInt64Value");
+    return val_.uint64_value_;
+  }
+  int32 GetInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+               "MapKey::GetInt32Value");
+    return val_.int32_value_;
+  }
+  uint32 GetUInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+               "MapKey::GetUInt32Value");
+    return val_.uint32_value_;
+  }
+  bool GetBoolValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+               "MapKey::GetBoolValue");
+    return val_.bool_value_;
+  }
+  const string& GetStringValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+               "MapKey::GetStringValue");
+    return *val_.string_value_;
+  }
+
+  bool operator<(const MapKey& other) const {
+    if (type_ != other.type_) {
+      // We could define a total order that handles this case, but
+      // there currently no need.  So, for now, fail.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+    }
+    switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        return false;
+      case FieldDescriptor::CPPTYPE_STRING:
+        return *val_.string_value_ < *other.val_.string_value_;
+      case FieldDescriptor::CPPTYPE_INT64:
+        return val_.int64_value_ < other.val_.int64_value_;
+      case FieldDescriptor::CPPTYPE_INT32:
+        return val_.int32_value_ < other.val_.int32_value_;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return val_.uint64_value_ < other.val_.uint64_value_;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return val_.uint32_value_ < other.val_.uint32_value_;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return val_.bool_value_ < other.val_.bool_value_;
+    }
+    return false;
+  }
+
+  bool operator==(const MapKey& other) const {
+    if (type_ != other.type_) {
+      // To be consistent with operator<, we don't allow this either.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+    }
+    switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case FieldDescriptor::CPPTYPE_STRING:
+        return *val_.string_value_ == *other.val_.string_value_;
+      case FieldDescriptor::CPPTYPE_INT64:
+        return val_.int64_value_ == other.val_.int64_value_;
+      case FieldDescriptor::CPPTYPE_INT32:
+        return val_.int32_value_ == other.val_.int32_value_;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return val_.uint64_value_ == other.val_.uint64_value_;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return val_.uint32_value_ == other.val_.uint32_value_;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return val_.bool_value_ == other.val_.bool_value_;
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return false;
+  }
+
+  void CopyFrom(const MapKey& other) {
+    SetType(other.type());
+    switch (type_) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case FieldDescriptor::CPPTYPE_STRING:
+        *val_.string_value_ = *other.val_.string_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_INT64:
+        val_.int64_value_ = other.val_.int64_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_INT32:
+        val_.int32_value_ = other.val_.int32_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        val_.uint64_value_ = other.val_.uint64_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        val_.uint32_value_ = other.val_.uint32_value_;
+        break;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        val_.bool_value_ = other.val_.bool_value_;
+        break;
+    }
+  }
+
+ private:
+  template <typename K, typename V>
+  friend class internal::TypeDefinedMapFieldBase;
+  friend class MapIterator;
+  friend class internal::DynamicMapField;
+
+  union KeyValue {
+    KeyValue() {}
+    string* string_value_;
+    int64 int64_value_;
+    int32 int32_value_;
+    uint64 uint64_value_;
+    uint32 uint32_value_;
+    bool bool_value_;
+  } val_;
+
+  void SetType(FieldDescriptor::CppType type) {
+    if (type_ == type) return;
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      delete val_.string_value_;
+    }
+    type_ = type;
+    if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+      val_.string_value_ = new string;
+    }
+  }
+
+  // type_ is 0 or a valid FieldDescriptor::CppType.
+  int type_;
+};
+
+// MapValueRef points to a map value.
+class LIBPROTOBUF_EXPORT MapValueRef {
+ public:
+  MapValueRef() : data_(NULL), type_(0) {}
+
+  void SetInt64Value(int64 value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+               "MapValueRef::SetInt64Value");
+    *reinterpret_cast<int64*>(data_) = value;
+  }
+  void SetUInt64Value(uint64 value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+               "MapValueRef::SetUInt64Value");
+    *reinterpret_cast<uint64*>(data_) = value;
+  }
+  void SetInt32Value(int32 value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+               "MapValueRef::SetInt32Value");
+    *reinterpret_cast<int32*>(data_) = value;
+  }
+  void SetUInt32Value(uint32 value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+               "MapValueRef::SetUInt32Value");
+    *reinterpret_cast<uint32*>(data_) = value;
+  }
+  void SetBoolValue(bool value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+               "MapValueRef::SetBoolValue");
+    *reinterpret_cast<bool*>(data_) = value;
+  }
+  // TODO(jieluo) - Checks that enum is member.
+  void SetEnumValue(int value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+               "MapValueRef::SetEnumValue");
+    *reinterpret_cast<int*>(data_) = value;
+  }
+  void SetStringValue(const string& value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+               "MapValueRef::SetStringValue");
+    *reinterpret_cast<string*>(data_) = value;
+  }
+  void SetFloatValue(float value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+               "MapValueRef::SetFloatValue");
+    *reinterpret_cast<float*>(data_) = value;
+  }
+  void SetDoubleValue(double value) {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+               "MapValueRef::SetDoubleValue");
+    *reinterpret_cast<double*>(data_) = value;
+  }
+
+  int64 GetInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+               "MapValueRef::GetInt64Value");
+    return *reinterpret_cast<int64*>(data_);
+  }
+  uint64 GetUInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+               "MapValueRef::GetUInt64Value");
+    return *reinterpret_cast<uint64*>(data_);
+  }
+  int32 GetInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+               "MapValueRef::GetInt32Value");
+    return *reinterpret_cast<int32*>(data_);
+  }
+  uint32 GetUInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+               "MapValueRef::GetUInt32Value");
+    return *reinterpret_cast<uint32*>(data_);
+  }
+  bool GetBoolValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+               "MapValueRef::GetBoolValue");
+    return *reinterpret_cast<bool*>(data_);
+  }
+  int GetEnumValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+               "MapValueRef::GetEnumValue");
+    return *reinterpret_cast<int*>(data_);
+  }
+  const string& GetStringValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+               "MapValueRef::GetStringValue");
+    return *reinterpret_cast<string*>(data_);
+  }
+  float GetFloatValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+               "MapValueRef::GetFloatValue");
+    return *reinterpret_cast<float*>(data_);
+  }
+  double GetDoubleValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+               "MapValueRef::GetDoubleValue");
+    return *reinterpret_cast<double*>(data_);
+  }
+
+  const Message& GetMessageValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+               "MapValueRef::GetMessageValue");
+    return *reinterpret_cast<Message*>(data_);
+  }
+
+  Message* MutableMessageValue() {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+               "MapValueRef::MutableMessageValue");
+    return reinterpret_cast<Message*>(data_);
+  }
+
+ private:
+  template <typename K, typename V,
+            internal::WireFormatLite::FieldType key_wire_type,
+            internal::WireFormatLite::FieldType value_wire_type,
+            int default_enum_value>
+  friend class internal::MapField;
+  template <typename K, typename V>
+  friend class internal::TypeDefinedMapFieldBase;
+  friend class MapIterator;
+  friend class internal::GeneratedMessageReflection;
+  friend class internal::DynamicMapField;
+
+  void SetType(FieldDescriptor::CppType type) {
+    type_ = type;
+  }
+
+  FieldDescriptor::CppType type() const {
+    if (type_ == 0 || data_ == NULL) {
+      GOOGLE_LOG(FATAL)
+          << "Protocol Buffer map usage error:\n"
+          << "MapValueRef::type MapValueRef is not initialized.";
+    }
+    return (FieldDescriptor::CppType)type_;
+  }
+  void SetValue(const void* val) {
+    data_ = const_cast<void*>(val);
+  }
+  void CopyFrom(const MapValueRef& other) {
+    type_ = other.type_;
+    data_ = other.data_;
+  }
+  // Only used in DynamicMapField
+  void DeleteData() {
+    switch (type_) {
+#define HANDLE_TYPE(CPPTYPE, TYPE)                              \
+      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
+        delete reinterpret_cast<TYPE*>(data_);                  \
+        break;                                                  \
+      }
+      HANDLE_TYPE(INT32, int32);
+      HANDLE_TYPE(INT64, int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE(FLOAT, float);
+      HANDLE_TYPE(BOOL, bool);
+      HANDLE_TYPE(STRING, string);
+      HANDLE_TYPE(ENUM, int32);
+      HANDLE_TYPE(MESSAGE, Message);
+#undef HANDLE_TYPE
+    }
+  }
+  // data_ point to a map value. MapValueRef does not
+  // own this value.
+  void* data_;
+  // type_ is 0 or a valid FieldDescriptor::CppType.
+  int type_;
+};
+
+#undef TYPE_CHECK
+
+// This is the class for google::protobuf::Map's internal value_type. Instead of using
+// std::pair as value_type, we use this class which provides us more control of
+// its process of construction and destruction.
+template <typename Key, typename T>
+class MapPair {
+ public:
+  typedef const Key first_type;
+  typedef T second_type;
+
+  MapPair(const Key& other_first, const T& other_second)
+      : first(other_first), second(other_second) {}
+  explicit MapPair(const Key& other_first) : first(other_first), second() {}
+  MapPair(const MapPair& other)
+      : first(other.first), second(other.second) {}
+
+  ~MapPair() {}
+
+  // Implicitly convertible to std::pair of compatible types.
+  template <typename T1, typename T2>
+  operator std::pair<T1, T2>() const {
+    return std::pair<T1, T2>(first, second);
+  }
+
+  const Key first;
+  T second;
+
+ private:
+  friend class ::google::protobuf::Arena;
+  friend class Map<Key, T>;
+};
+
+// google::protobuf::Map is an associative container type used to store protobuf map
+// fields.  Each Map instance may or may not use a different hash function, a
+// different iteration order, and so on.  E.g., please don't examine
+// implementation details to decide if the following would work:
+//  Map<int, int> m0, m1;
+//  m0[0] = m1[0] = m0[1] = m1[1] = 0;
+//  assert(m0.begin()->first == m1.begin()->first);  // Bug!
+//
+// Map's interface is similar to std::unordered_map, except that Map is not
+// designed to play well with exceptions.
+template <typename Key, typename T>
+class Map {
+ public:
+  typedef Key key_type;
+  typedef T mapped_type;
+  typedef MapPair<Key, T> value_type;
+
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+
+  typedef size_t size_type;
+  typedef hash<Key> hasher;
+
+  Map(bool old_style = true)
+      : arena_(NULL),
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
+  }
+  explicit Map(Arena* arena, bool old_style = true)
+      : arena_(arena),
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
+  }
+  Map(const Map& other)
+      : arena_(NULL),
+        default_enum_value_(other.default_enum_value_),
+        old_style_(other.old_style_) {
+    Init();
+    insert(other.begin(), other.end());
+  }
+  template <class InputIt>
+  Map(const InputIt& first, const InputIt& last, bool old_style = true)
+      : arena_(NULL),
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
+    insert(first, last);
+  }
+
+  ~Map() {
+    clear();
+    if (arena_ == NULL) {
+      if (old_style_)
+        delete deprecated_elements_;
+      else
+        delete elements_;
+    }
+  }
+
+ private:
+  void Init() {
+    if (old_style_)
+      deprecated_elements_ = Arena::Create<DeprecatedInnerMap>(
+          arena_, 0, hasher(), equal_to<Key>(),
+          MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_));
+    else
+      elements_ =
+          Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_));
+  }
+
+  // re-implement std::allocator to use arena allocator for memory allocation.
+  // Used for google::protobuf::Map implementation. Users should not use this class
+  // directly.
+  template <typename U>
+  class MapAllocator {
+   public:
+    typedef U value_type;
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+
+    MapAllocator() : arena_(NULL) {}
+    explicit MapAllocator(Arena* arena) : arena_(arena) {}
+    template <typename X>
+    MapAllocator(const MapAllocator<X>& allocator)
+        : arena_(allocator.arena_) {}
+
+    pointer allocate(size_type n, const_pointer hint = 0) {
+      // If arena is not given, malloc needs to be called which doesn't
+      // construct element object.
+      if (arena_ == NULL) {
+        return reinterpret_cast<pointer>(malloc(n * sizeof(value_type)));
+      } else {
+        return reinterpret_cast<pointer>(
+            Arena::CreateArray<uint8>(arena_, n * sizeof(value_type)));
+      }
+    }
+
+    void deallocate(pointer p, size_type n) {
+      if (arena_ == NULL) {
+        free(p);
+      }
+    }
+
+#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
+    !defined(GOOGLE_PROTOBUF_OS_NACL) &&                            \
+    !defined(GOOGLE_PROTOBUF_OS_ANDROID) &&                         \
+    !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN)
+    template<class NodeType, class... Args>
+    void construct(NodeType* p, Args&&... args) {
+      // Clang 3.6 doesn't compile static casting to void* directly. (Issue
+      // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall
+      // not cast away constness". So first the maybe const pointer is casted to
+      // const void* and after the const void* is const casted.
+      new (const_cast<void*>(static_cast<const void*>(p)))
+          NodeType(std::forward<Args>(args)...);
+    }
+
+    template<class NodeType>
+    void destroy(NodeType* p) {
+      p->~NodeType();
+    }
+#else
+    void construct(pointer p, const_reference t) { new (p) value_type(t); }
+
+    void destroy(pointer p) { p->~value_type(); }
+#endif
+
+    template <typename X>
+    struct rebind {
+      typedef MapAllocator<X> other;
+    };
+
+    template <typename X>
+    bool operator==(const MapAllocator<X>& other) const {
+      return arena_ == other.arena_;
+    }
+
+    template <typename X>
+    bool operator!=(const MapAllocator<X>& other) const {
+      return arena_ != other.arena_;
+    }
+
+    // To support Visual Studio 2008
+    size_type max_size() const {
+      return std::numeric_limits<size_type>::max();
+    }
+
+   private:
+    typedef void DestructorSkippable_;
+    Arena* const arena_;
+
+    template <typename X>
+    friend class MapAllocator;
+  };
+
+  // InnerMap's key type is Key and its value type is value_type*.  We use a
+  // custom class here and for Node, below, to ensure that k_ is at offset 0,
+  // allowing safe conversion from pointer to Node to pointer to Key, and vice
+  // versa when appropriate.
+  class KeyValuePair {
+   public:
+    KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {}
+
+    const Key& key() const { return k_; }
+    Key& key() { return k_; }
+    value_type* const value() const { return v_; }
+    value_type*& value() { return v_; }
+
+   private:
+    Key k_;
+    value_type* v_;
+  };
+
+  typedef MapAllocator<KeyValuePair> Allocator;
+
+  // InnerMap is a generic hash-based map.  It doesn't contain any
+  // protocol-buffer-specific logic.  It is a chaining hash map with the
+  // additional feature that some buckets can be converted to use an ordered
+  // container.  This ensures O(lg n) bounds on find, insert, and erase, while
+  // avoiding the overheads of ordered containers most of the time.
+  //
+  // The implementation doesn't need the full generality of unordered_map,
+  // and it doesn't have it.  More bells and whistles can be added as needed.
+  // Some implementation details:
+  // 1. The hash function has type hasher and the equality function
+  //    equal_to<Key>.  We inherit from hasher to save space
+  //    (empty-base-class optimization).
+  // 2. The number of buckets is a power of two.
+  // 3. Buckets are converted to trees in pairs: if we convert bucket b then
+  //    buckets b and b^1 will share a tree.  Invariant: buckets b and b^1 have
+  //    the same non-NULL value iff they are sharing a tree.  (An alternative
+  //    implementation strategy would be to have a tag bit per bucket.)
+  // 4. As is typical for hash_map and such, the Keys and Values are always
+  //    stored in linked list nodes.  Pointers to elements are never invalidated
+  //    until the element is deleted.
+  // 5. The trees' payload type is pointer to linked-list node.  Tree-converting
+  //    a bucket doesn't copy Key-Value pairs.
+  // 6. Once we've tree-converted a bucket, it is never converted back. However,
+  //    the items a tree contains may wind up assigned to trees or lists upon a
+  //    rehash.
+  // 7. The code requires no C++ features from C++11 or later.
+  // 8. Mutations to a map do not invalidate the map's iterators, pointers to
+  //    elements, or references to elements.
+  // 9. Except for erase(iterator), any non-const method can reorder iterators.
+  class InnerMap : private hasher {
+   public:
+    typedef value_type* Value;
+
+    InnerMap(size_type n, hasher h, Allocator alloc)
+        : hasher(h),
+          num_elements_(0),
+          seed_(Seed()),
+          table_(NULL),
+          alloc_(alloc) {
+      n = TableSize(n);
+      table_ = CreateEmptyTable(n);
+      num_buckets_ = index_of_first_non_null_ = n;
+    }
+
+    ~InnerMap() {
+      if (table_ != NULL) {
+        clear();
+        Dealloc<void*>(table_, num_buckets_);
+      }
+    }
+
+   private:
+    enum { kMinTableSize = 8 };
+
+    // Linked-list nodes, as one would expect for a chaining hash table.
+    struct Node {
+      KeyValuePair kv;
+      Node* next;
+    };
+
+    // This is safe only if the given pointer is known to point to a Key that is
+    // part of a Node.
+    static Node* NodePtrFromKeyPtr(Key* k) {
+      return reinterpret_cast<Node*>(k);
+    }
+
+    static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
+
+    // Trees.  The payload type is pointer to Key, so that we can query the tree
+    // with Keys that are not in any particular data structure.  When we insert,
+    // though, the pointer is always pointing to a Key that is inside a Node.
+    struct KeyCompare {
+      bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
+    };
+    typedef typename Allocator::template rebind<Key*>::other KeyPtrAllocator;
+    typedef std::set<Key*, KeyCompare, KeyPtrAllocator> Tree;
+
+    // iterator and const_iterator are instantiations of iterator_base.
+    template <typename KeyValueType>
+    class iterator_base {
+     public:
+      typedef KeyValueType& reference;
+      typedef KeyValueType* pointer;
+      typedef typename Tree::iterator TreeIterator;
+
+      // Invariants:
+      // node_ is always correct. This is handy because the most common
+      // operations are operator* and operator-> and they only use node_.
+      // When node_ is set to a non-NULL value, all the other non-const fields
+      // are updated to be correct also, but those fields can become stale
+      // if the underlying map is modified.  When those fields are needed they
+      // are rechecked, and updated if necessary.
+      iterator_base() : node_(NULL) {}
+
+      explicit iterator_base(const InnerMap* m) : m_(m) {
+        SearchFrom(m->index_of_first_non_null_);
+      }
+
+      // Any iterator_base can convert to any other.  This is overkill, and we
+      // rely on the enclosing class to use it wisely.  The standard "iterator
+      // can convert to const_iterator" is OK but the reverse direction is not.
+      template <typename U>
+      explicit iterator_base(const iterator_base<U>& it)
+          : node_(it.node_),
+            m_(it.m_),
+            bucket_index_(it.bucket_index_),
+            tree_it_(it.tree_it_) {}
+
+      iterator_base(Node* n, const InnerMap* m, size_type index)
+          : node_(n),
+            m_(m),
+            bucket_index_(index) {}
+
+      iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index)
+          : node_(NodePtrFromKeyPtr(*tree_it)),
+            m_(m),
+            bucket_index_(index),
+            tree_it_(tree_it) {
+        // Invariant: iterators that use tree_it_ have an even bucket_index_.
+        GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0);
+      }
+
+      // Advance through buckets, looking for the first that isn't empty.
+      // If nothing non-empty is found then leave node_ == NULL.
+      void SearchFrom(size_type start_bucket) {
+        GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
+               m_->table_[m_->index_of_first_non_null_] != NULL);
+        node_ = NULL;
+        for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_;
+             bucket_index_++) {
+          if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+            node_ = static_cast<Node*>(m_->table_[bucket_index_]);
+            break;
+          } else if (m_->TableEntryIsTree(bucket_index_)) {
+            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+            GOOGLE_DCHECK(!tree->empty());
+            tree_it_ = tree->begin();
+            node_ = NodePtrFromKeyPtr(*tree_it_);
+            break;
+          }
+        }
+      }
+
+      reference operator*() const { return node_->kv; }
+      pointer operator->() const { return &(operator*()); }
+
+      friend bool operator==(const iterator_base& a, const iterator_base& b) {
+        return a.node_ == b.node_;
+      }
+      friend bool operator!=(const iterator_base& a, const iterator_base& b) {
+        return a.node_ != b.node_;
+      }
+
+      iterator_base& operator++() {
+        if (node_->next == NULL) {
+          const bool is_list = revalidate_if_necessary();
+          if (is_list) {
+            SearchFrom(bucket_index_ + 1);
+          } else {
+            GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0);
+            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+            if (++tree_it_ == tree->end()) {
+              SearchFrom(bucket_index_ + 2);
+            } else {
+              node_ = NodePtrFromKeyPtr(*tree_it_);
+            }
+          }
+        } else {
+          node_ = node_->next;
+        }
+        return *this;
+      }
+
+      iterator_base operator++(int /* unused */) {
+        iterator_base tmp = *this;
+        ++*this;
+        return tmp;
+      }
+
+      // Assumes node_ and m_ are correct and non-NULL, but other fields may be
+      // stale.  Fix them as needed.  Then return true iff node_ points to a
+      // Node in a list.
+      bool revalidate_if_necessary() {
+        GOOGLE_DCHECK(node_ != NULL && m_ != NULL);
+        // Force bucket_index_ to be in range.
+        bucket_index_ &= (m_->num_buckets_ - 1);
+        // Common case: the bucket we think is relevant points to node_.
+        if (m_->table_[bucket_index_] == static_cast<void*>(node_))
+          return true;
+        // Less common: the bucket is a linked list with node_ somewhere in it,
+        // but not at the head.
+        if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+          Node* l = static_cast<Node*>(m_->table_[bucket_index_]);
+          while ((l = l->next) != NULL) {
+            if (l == node_) {
+              return true;
+            }
+          }
+        }
+        // Well, bucket_index_ still might be correct, but probably
+        // not.  Revalidate just to be sure.  This case is rare enough that we
+        // don't worry about potential optimizations, such as having a custom
+        // find-like method that compares Node* instead of const Key&.
+        iterator_base i(m_->find(*KeyPtrFromNodePtr(node_)));
+        bucket_index_ = i.bucket_index_;
+        tree_it_ = i.tree_it_;
+        return m_->TableEntryIsList(bucket_index_);
+      }
+
+      Node* node_;
+      const InnerMap* m_;
+      size_type bucket_index_;
+      TreeIterator tree_it_;
+    };
+
+   public:
+    typedef iterator_base<KeyValuePair> iterator;
+    typedef iterator_base<const KeyValuePair> const_iterator;
+
+    iterator begin() { return iterator(this); }
+    iterator end() { return iterator(); }
+    const_iterator begin() const { return const_iterator(this); }
+    const_iterator end() const { return const_iterator(); }
+
+    void clear() {
+      for (size_type b = 0; b < num_buckets_; b++) {
+        if (TableEntryIsNonEmptyList(b)) {
+          Node* node = static_cast<Node*>(table_[b]);
+          table_[b] = NULL;
+          do {
+            Node* next = node->next;
+            DestroyNode(node);
+            node = next;
+          } while (node != NULL);
+        } else if (TableEntryIsTree(b)) {
+          Tree* tree = static_cast<Tree*>(table_[b]);
+          GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0);
+          table_[b] = table_[b + 1] = NULL;
+          typename Tree::iterator tree_it = tree->begin();
+          do {
+            Node* node = NodePtrFromKeyPtr(*tree_it);
+            typename Tree::iterator next = tree_it;
+            ++next;
+            tree->erase(tree_it);
+            DestroyNode(node);
+            tree_it = next;
+          } while (tree_it != tree->end());
+          DestroyTree(tree);
+          b++;
+        }
+      }
+      num_elements_ = 0;
+      index_of_first_non_null_ = num_buckets_;
+    }
+
+    const hasher& hash_function() const { return *this; }
+
+    static size_type max_size() {
+      return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28);
+    }
+    size_type size() const { return num_elements_; }
+    bool empty() const { return size() == 0; }
+
+    iterator find(const Key& k) { return iterator(FindHelper(k).first); }
+    const_iterator find(const Key& k) const { return FindHelper(k).first; }
+
+    // In traditional C++ style, this performs "insert if not present."
+    std::pair<iterator, bool> insert(const KeyValuePair& kv) {
+      std::pair<const_iterator, size_type> p = FindHelper(kv.key());
+      // Case 1: key was already present.
+      if (p.first.node_ != NULL)
+        return std::make_pair(iterator(p.first), false);
+      // Case 2: insert.
+      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+        p = FindHelper(kv.key());
+      }
+      const size_type b = p.second;  // bucket number
+      Node* node = Alloc<Node>(1);
+      alloc_.construct(&node->kv, kv);
+      iterator result = InsertUnique(b, node);
+      ++num_elements_;
+      return std::make_pair(result, true);
+    }
+
+    // The same, but if an insertion is necessary then the value portion of the
+    // inserted key-value pair is left uninitialized.
+    std::pair<iterator, bool> insert(const Key& k) {
+      std::pair<const_iterator, size_type> p = FindHelper(k);
+      // Case 1: key was already present.
+      if (p.first.node_ != NULL)
+        return std::make_pair(iterator(p.first), false);
+      // Case 2: insert.
+      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+        p = FindHelper(k);
+      }
+      const size_type b = p.second;  // bucket number
+      Node* node = Alloc<Node>(1);
+      typedef typename Allocator::template rebind<Key>::other KeyAllocator;
+      KeyAllocator(alloc_).construct(&node->kv.key(), k);
+      iterator result = InsertUnique(b, node);
+      ++num_elements_;
+      return std::make_pair(result, true);
+    }
+
+    Value& operator[](const Key& k) {
+      KeyValuePair kv(k, Value());
+      return insert(kv).first->value();
+    }
+
+    void erase(iterator it) {
+      GOOGLE_DCHECK_EQ(it.m_, this);
+      const bool is_list = it.revalidate_if_necessary();
+      size_type b = it.bucket_index_;
+      Node* const item = it.node_;
+      if (is_list) {
+        GOOGLE_DCHECK(TableEntryIsNonEmptyList(b));
+        Node* head = static_cast<Node*>(table_[b]);
+        head = EraseFromLinkedList(item, head);
+        table_[b] = static_cast<void*>(head);
+      } else {
+        GOOGLE_DCHECK(TableEntryIsTree(b));
+        Tree* tree = static_cast<Tree*>(table_[b]);
+        tree->erase(it.tree_it_);
+        if (tree->empty()) {
+          // Force b to be the minimum of b and b ^ 1.  This is important
+          // only because we want index_of_first_non_null_ to be correct.
+          b &= ~static_cast<size_type>(1);
+          DestroyTree(tree);
+          table_[b] = table_[b + 1] = NULL;
+        }
+      }
+      DestroyNode(item);
+      --num_elements_;
+      if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) {
+        while (index_of_first_non_null_ < num_buckets_ &&
+               table_[index_of_first_non_null_] == NULL) {
+          ++index_of_first_non_null_;
+        }
+      }
+    }
+
+   private:
+    std::pair<const_iterator, size_type> FindHelper(const Key& k) const {
+      size_type b = BucketNumber(k);
+      if (TableEntryIsNonEmptyList(b)) {
+        Node* node = static_cast<Node*>(table_[b]);
+        do {
+          if (IsMatch(*KeyPtrFromNodePtr(node), k)) {
+            return std::make_pair(const_iterator(node, this, b), b);
+          } else {
+            node = node->next;
+          }
+        } while (node != NULL);
+      } else if (TableEntryIsTree(b)) {
+        GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+        b &= ~static_cast<size_t>(1);
+        Tree* tree = static_cast<Tree*>(table_[b]);
+        Key* key = const_cast<Key*>(&k);
+        typename Tree::iterator tree_it = tree->find(key);
+        if (tree_it != tree->end()) {
+          return std::make_pair(const_iterator(tree_it, this, b), b);
+        }
+      }
+      return std::make_pair(end(), b);
+    }
+
+    // Insert the given Node in bucket b.  If that would make bucket b too big,
+    // and bucket b is not a tree, create a tree for buckets b and b^1 to share.
+    // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
+    // bucket.  num_elements_ is not modified.
+    iterator InsertUnique(size_type b, Node* node) {
+      GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ ||
+             table_[index_of_first_non_null_] != NULL);
+      // In practice, the code that led to this point may have already
+      // determined whether we are inserting into an empty list, a short list,
+      // or whatever.  But it's probably cheap enough to recompute that here;
+      // it's likely that we're inserting into an empty or short list.
+      iterator result;
+      GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end());
+      if (TableEntryIsEmpty(b)) {
+        result = InsertUniqueInList(b, node);
+      } else if (TableEntryIsNonEmptyList(b)) {
+        if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) {
+          TreeConvert(b);
+          result = InsertUniqueInTree(b, node);
+          GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1));
+        } else {
+          // Insert into a pre-existing list.  This case cannot modify
+          // index_of_first_non_null_, so we skip the code to update it.
+          return InsertUniqueInList(b, node);
+        }
+      } else {
+        // Insert into a pre-existing tree.  This case cannot modify
+        // index_of_first_non_null_, so we skip the code to update it.
+        return InsertUniqueInTree(b, node);
+      }
+      index_of_first_non_null_ =
+          std::min(index_of_first_non_null_, result.bucket_index_);
+      return result;
+    }
+
+    // Helper for InsertUnique.  Handles the case where bucket b is a
+    // not-too-long linked list.
+    iterator InsertUniqueInList(size_type b, Node* node) {
+      node->next = static_cast<Node*>(table_[b]);
+      table_[b] = static_cast<void*>(node);
+      return iterator(node, this, b);
+    }
+
+    // Helper for InsertUnique.  Handles the case where bucket b points to a
+    // Tree.
+    iterator InsertUniqueInTree(size_type b, Node* node) {
+      GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+      // Maintain the invariant that node->next is NULL for all Nodes in Trees.
+      node->next = NULL;
+      return iterator(static_cast<Tree*>(table_[b])
+                      ->insert(KeyPtrFromNodePtr(node))
+                      .first,
+                      this, b & ~static_cast<size_t>(1));
+    }
+
+    // Returns whether it did resize.  Currently this is only used when
+    // num_elements_ increases, though it could be used in other situations.
+    // It checks for load too low as well as load too high: because any number
+    // of erases can occur between inserts, the load could be as low as 0 here.
+    // Resizing to a lower size is not always helpful, but failing to do so can
+    // destroy the expected big-O bounds for some operations. By having the
+    // policy that sometimes we resize down as well as up, clients can easily
+    // keep O(size()) = O(number of buckets) if they want that.
+    bool ResizeIfLoadIsOutOfRange(size_type new_size) {
+      const size_type kMaxMapLoadTimes16 = 12;  // controls RAM vs CPU tradeoff
+      const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
+      const size_type lo_cutoff = hi_cutoff / 4;
+      // We don't care how many elements are in trees.  If a lot are,
+      // we may resize even though there are many empty buckets.  In
+      // practice, this seems fine.
+      if (GOOGLE_PREDICT_FALSE(new_size >= hi_cutoff)) {
+        if (num_buckets_ <= max_size() / 2) {
+          Resize(num_buckets_ * 2);
+          return true;
+        }
+      } else if (GOOGLE_PREDICT_FALSE(new_size <= lo_cutoff &&
+                               num_buckets_ > kMinTableSize)) {
+        size_type lg2_of_size_reduction_factor = 1;
+        // It's possible we want to shrink a lot here... size() could even be 0.
+        // So, estimate how much to shrink by making sure we don't shrink so
+        // much that we would need to grow the table after a few inserts.
+        const size_type hypothetical_size = new_size * 5 / 4 + 1;
+        while ((hypothetical_size << lg2_of_size_reduction_factor) <
+               hi_cutoff) {
+          ++lg2_of_size_reduction_factor;
+        }
+        size_type new_num_buckets = std::max<size_type>(
+            kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
+        if (new_num_buckets != num_buckets_) {
+          Resize(new_num_buckets);
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Resize to the given number of buckets.
+    void Resize(size_t new_num_buckets) {
+      GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize);
+      void** const old_table = table_;
+      const size_type old_table_size = num_buckets_;
+      num_buckets_ = new_num_buckets;
+      table_ = CreateEmptyTable(num_buckets_);
+      const size_type start = index_of_first_non_null_;
+      index_of_first_non_null_ = num_buckets_;
+      for (size_type i = start; i < old_table_size; i++) {
+        if (TableEntryIsNonEmptyList(old_table, i)) {
+          TransferList(old_table, i);
+        } else if (TableEntryIsTree(old_table, i)) {
+          TransferTree(old_table, i++);
+        }
+      }
+      Dealloc<void*>(old_table, old_table_size);
+    }
+
+    void TransferList(void* const* table, size_type index) {
+      Node* node = static_cast<Node*>(table[index]);
+      do {
+        Node* next = node->next;
+        InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node);
+        node = next;
+      } while (node != NULL);
+    }
+
+    void TransferTree(void* const* table, size_type index) {
+      Tree* tree = static_cast<Tree*>(table[index]);
+      typename Tree::iterator tree_it = tree->begin();
+      do {
+        Node* node = NodePtrFromKeyPtr(*tree_it);
+        InsertUnique(BucketNumber(**tree_it), node);
+      } while (++tree_it != tree->end());
+      DestroyTree(tree);
+    }
+
+    Node* EraseFromLinkedList(Node* item, Node* head) {
+      if (head == item) {
+        return head->next;
+      } else {
+        head->next = EraseFromLinkedList(item, head->next);
+        return head;
+      }
+    }
+
+    bool TableEntryIsEmpty(size_type b) const {
+      return TableEntryIsEmpty(table_, b);
+    }
+    bool TableEntryIsNonEmptyList(size_type b) const {
+      return TableEntryIsNonEmptyList(table_, b);
+    }
+    bool TableEntryIsTree(size_type b) const {
+      return TableEntryIsTree(table_, b);
+    }
+    bool TableEntryIsList(size_type b) const {
+      return TableEntryIsList(table_, b);
+    }
+    static bool TableEntryIsEmpty(void* const* table, size_type b) {
+      return table[b] == NULL;
+    }
+    static bool TableEntryIsNonEmptyList(void* const* table, size_type b) {
+      return table[b] != NULL && table[b] != table[b ^ 1];
+    }
+    static bool TableEntryIsTree(void* const* table, size_type b) {
+      return !TableEntryIsEmpty(table, b) &&
+          !TableEntryIsNonEmptyList(table, b);
+    }
+    static bool TableEntryIsList(void* const* table, size_type b) {
+      return !TableEntryIsTree(table, b);
+    }
+
+    void TreeConvert(size_type b) {
+      GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
+      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+      Tree* tree = tree_allocator.allocate(1);
+      // We want to use the three-arg form of construct, if it exists, but we
+      // create a temporary and use the two-arg construct that's known to exist.
+      // It's clunky, but the compiler should be able to generate more-or-less
+      // the same code.
+      tree_allocator.construct(tree,
+                               Tree(KeyCompare(), KeyPtrAllocator(alloc_)));
+      // Now the tree is ready to use.
+      size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree);
+      GOOGLE_DCHECK_EQ(count, tree->size());
+      table_[b] = table_[b ^ 1] = static_cast<void*>(tree);
+    }
+
+    // Copy a linked list in the given bucket to a tree.
+    // Returns the number of things it copied.
+    size_type CopyListToTree(size_type b, Tree* tree) {
+      size_type count = 0;
+      Node* node = static_cast<Node*>(table_[b]);
+      while (node != NULL) {
+        tree->insert(KeyPtrFromNodePtr(node));
+        ++count;
+        Node* next = node->next;
+        node->next = NULL;
+        node = next;
+      }
+      return count;
+    }
+
+    // Return whether table_[b] is a linked list that seems awfully long.
+    // Requires table_[b] to point to a non-empty linked list.
+    bool TableEntryIsTooLong(size_type b) {
+      const int kMaxLength = 8;
+      size_type count = 0;
+      Node* node = static_cast<Node*>(table_[b]);
+      do {
+        ++count;
+        node = node->next;
+      } while (node != NULL);
+      // Invariant: no linked list ever is more than kMaxLength in length.
+      GOOGLE_DCHECK_LE(count, kMaxLength);
+      return count >= kMaxLength;
+    }
+
+    size_type BucketNumber(const Key& k) const {
+      // We inherit from hasher, so one-arg operator() provides a hash function.
+      size_type h = (*const_cast<InnerMap*>(this))(k);
+      // To help prevent people from making assumptions about the hash function,
+      // we use the seed differently depending on NDEBUG.  The default hash
+      // function, the seeding, etc., are all likely to change in the future.
+#ifndef NDEBUG
+      return (h * (seed_ | 1)) & (num_buckets_ - 1);
+#else
+      return (h + seed_) & (num_buckets_ - 1);
+#endif
+    }
+
+    bool IsMatch(const Key& k0, const Key& k1) const {
+      return std::equal_to<Key>()(k0, k1);
+    }
+
+    // Return a power of two no less than max(kMinTableSize, n).
+    // Assumes either n < kMinTableSize or n is a power of two.
+    size_type TableSize(size_type n) {
+      return n < kMinTableSize ? kMinTableSize : n;
+    }
+
+    // Use alloc_ to allocate an array of n objects of type U.
+    template <typename U>
+    U* Alloc(size_type n) {
+      typedef typename Allocator::template rebind<U>::other alloc_type;
+      return alloc_type(alloc_).allocate(n);
+    }
+
+    // Use alloc_ to deallocate an array of n objects of type U.
+    template <typename U>
+    void Dealloc(U* t, size_type n) {
+      typedef typename Allocator::template rebind<U>::other alloc_type;
+      alloc_type(alloc_).deallocate(t, n);
+    }
+
+    void DestroyNode(Node* node) {
+      alloc_.destroy(&node->kv);
+      Dealloc<Node>(node, 1);
+    }
+
+    void DestroyTree(Tree* tree) {
+      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+      tree_allocator.destroy(tree);
+      tree_allocator.deallocate(tree, 1);
+    }
+
+    void** CreateEmptyTable(size_type n) {
+      GOOGLE_DCHECK(n >= kMinTableSize);
+      GOOGLE_DCHECK_EQ(n & (n - 1), 0);
+      void** result = Alloc<void*>(n);
+      memset(result, 0, n * sizeof(result[0]));
+      return result;
+    }
+
+    // Return a randomish value.
+    size_type Seed() const {
+      // random_device can throw, so avoid it unless we are compiling with
+      // exceptions enabled.
+#if __cpp_exceptions && LANG_CXX11
+      try {
+        std::random_device rd;
+        std::knuth_b knuth(rd());
+        std::uniform_int_distribution<size_type> u;
+        return u(knuth);
+      } catch (...) { }
+#endif
+      size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
+#if defined(__x86_64__) && defined(__GNUC__)
+      uint32 hi, lo;
+      asm("rdtsc" : "=a" (lo), "=d" (hi));
+      s += ((static_cast<uint64>(hi) << 32) | lo);
+#endif
+      return s;
+    }
+
+    size_type num_elements_;
+    size_type num_buckets_;
+    size_type seed_;
+    size_type index_of_first_non_null_;
+    void** table_;  // an array with num_buckets_ entries
+    Allocator alloc_;
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap);
+  };  // end of class InnerMap
+
+  typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+                   MapAllocator<std::pair<const Key, MapPair<Key, T>*> > >
+      DeprecatedInnerMap;
+
+ public:
+  // Iterators
+  class iterator_base {
+   public:
+    // We support "old style" and "new style" iterators for now. This is
+    // temporary.  Also, for "iterator()" we have an unknown category.
+    // TODO(gpike): get rid of this.
+    enum IteratorStyle { kUnknown, kOld, kNew };
+    explicit iterator_base(IteratorStyle style) : iterator_style_(style) {}
+
+    bool OldStyle() const {
+      GOOGLE_DCHECK_NE(iterator_style_, kUnknown);
+      return iterator_style_ == kOld;
+    }
+    bool UnknownStyle() const {
+      return iterator_style_ == kUnknown;
+    }
+    bool SameStyle(const iterator_base& other) const {
+      return iterator_style_ == other.iterator_style_;
+    }
+
+   private:
+    IteratorStyle iterator_style_;
+  };
+
+  class const_iterator
+      : private iterator_base,
+        public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
+                             const value_type*, const value_type&> {
+    typedef typename InnerMap::const_iterator InnerIt;
+    typedef typename DeprecatedInnerMap::const_iterator DeprecatedInnerIt;
+
+   public:
+    const_iterator() : iterator_base(iterator_base::kUnknown) {}
+    explicit const_iterator(const DeprecatedInnerIt& dit)
+        : iterator_base(iterator_base::kOld), dit_(dit) {}
+    explicit const_iterator(const InnerIt& it)
+        : iterator_base(iterator_base::kNew), it_(it) {}
+
+    const_iterator(const const_iterator& other)
+        : iterator_base(other), it_(other.it_), dit_(other.dit_) {}
+
+    const_reference operator*() const {
+      return this->OldStyle() ? *dit_->second : *it_->value();
+    }
+    const_pointer operator->() const { return &(operator*()); }
+
+    const_iterator& operator++() {
+      if (this->OldStyle())
+        ++dit_;
+      else
+        ++it_;
+      return *this;
+    }
+    const_iterator operator++(int) {
+      return this->OldStyle() ? const_iterator(dit_++) : const_iterator(it_++);
+    }
+
+    friend bool operator==(const const_iterator& a, const const_iterator& b) {
+      if (!a.SameStyle(b)) return false;
+      if (a.UnknownStyle()) return true;
+      return a.OldStyle() ? (a.dit_ == b.dit_) : (a.it_ == b.it_);
+    }
+    friend bool operator!=(const const_iterator& a, const const_iterator& b) {
+      return !(a == b);
+    }
+
+   private:
+    InnerIt it_;
+    DeprecatedInnerIt dit_;
+  };
+
+  class iterator : private iterator_base,
+                   public std::iterator<std::forward_iterator_tag, value_type> {
+    typedef typename InnerMap::iterator InnerIt;
+    typedef typename DeprecatedInnerMap::iterator DeprecatedInnerIt;
+
+   public:
+    iterator() : iterator_base(iterator_base::kUnknown) {}
+    explicit iterator(const DeprecatedInnerIt& dit)
+        : iterator_base(iterator_base::kOld), dit_(dit) {}
+    explicit iterator(const InnerIt& it)
+        : iterator_base(iterator_base::kNew), it_(it) {}
+
+    reference operator*() const {
+      return this->OldStyle() ? *dit_->second : *it_->value();
+    }
+    pointer operator->() const { return &(operator*()); }
+
+    iterator& operator++() {
+      if (this->OldStyle())
+        ++dit_;
+      else
+        ++it_;
+      return *this;
+    }
+    iterator operator++(int) {
+      return this->OldStyle() ? iterator(dit_++) : iterator(it_++);
+    }
+
+    // Allow implicit conversion to const_iterator.
+    operator const_iterator() const {
+      return this->OldStyle() ?
+          const_iterator(typename DeprecatedInnerMap::const_iterator(dit_)) :
+          const_iterator(typename InnerMap::const_iterator(it_));
+    }
+
+    friend bool operator==(const iterator& a, const iterator& b) {
+      if (!a.SameStyle(b)) return false;
+      if (a.UnknownStyle()) return true;
+      return a.OldStyle() ? a.dit_ == b.dit_ : a.it_ == b.it_;
+    }
+    friend bool operator!=(const iterator& a, const iterator& b) {
+      return !(a == b);
+    }
+
+   private:
+    friend class Map;
+
+    InnerIt it_;
+    DeprecatedInnerIt dit_;
+  };
+
+  iterator begin() {
+    return old_style_ ? iterator(deprecated_elements_->begin())
+                      : iterator(elements_->begin());
+  }
+  iterator end() {
+    return old_style_ ? iterator(deprecated_elements_->end())
+                      : iterator(elements_->end());
+  }
+  const_iterator begin() const {
+    return old_style_ ? const_iterator(deprecated_elements_->begin())
+                      : const_iterator(iterator(elements_->begin()));
+  }
+  const_iterator end() const {
+    return old_style_ ? const_iterator(deprecated_elements_->end())
+                      : const_iterator(iterator(elements_->end()));
+  }
+  const_iterator cbegin() const { return begin(); }
+  const_iterator cend() const { return end(); }
+
+  // Capacity
+  size_type size() const {
+    return old_style_ ? deprecated_elements_->size() : elements_->size();
+  }
+  bool empty() const { return size() == 0; }
+
+  // Element access
+  T& operator[](const key_type& key) {
+    value_type** value =
+        old_style_ ? &(*deprecated_elements_)[key] : &(*elements_)[key];
+    if (*value == NULL) {
+      *value = CreateValueTypeInternal(key);
+      internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
+                                    T>::Initialize((*value)->second,
+                                                   default_enum_value_);
+    }
+    return (*value)->second;
+  }
+  const T& at(const key_type& key) const {
+    const_iterator it = find(key);
+    GOOGLE_CHECK(it != end());
+    return it->second;
+  }
+  T& at(const key_type& key) {
+    iterator it = find(key);
+    GOOGLE_CHECK(it != end());
+    return it->second;
+  }
+
+  // Lookup
+  size_type count(const key_type& key) const {
+    if (find(key) != end()) assert(key == find(key)->first);
+    return find(key) == end() ? 0 : 1;
+  }
+  const_iterator find(const key_type& key) const {
+    return old_style_ ? const_iterator(deprecated_elements_->find(key))
+        : const_iterator(iterator(elements_->find(key)));
+  }
+  iterator find(const key_type& key) {
+    return old_style_ ? iterator(deprecated_elements_->find(key))
+                      : iterator(elements_->find(key));
+  }
+  std::pair<const_iterator, const_iterator> equal_range(
+      const key_type& key) const {
+    const_iterator it = find(key);
+    if (it == end()) {
+      return std::pair<const_iterator, const_iterator>(it, it);
+    } else {
+      const_iterator begin = it++;
+      return std::pair<const_iterator, const_iterator>(begin, it);
+    }
+  }
+  std::pair<iterator, iterator> equal_range(const key_type& key) {
+    iterator it = find(key);
+    if (it == end()) {
+      return std::pair<iterator, iterator>(it, it);
+    } else {
+      iterator begin = it++;
+      return std::pair<iterator, iterator>(begin, it);
+    }
+  }
+
+  // insert
+  std::pair<iterator, bool> insert(const value_type& value) {
+    if (old_style_) {
+      iterator it = find(value.first);
+      if (it != end()) {
+        return std::pair<iterator, bool>(it, false);
+      } else {
+        return std::pair<iterator, bool>(
+            iterator(deprecated_elements_->insert(std::pair<Key, value_type*>(
+                value.first, CreateValueTypeInternal(value))).first), true);
+      }
+    } else {
+      std::pair<typename InnerMap::iterator, bool> p =
+          elements_->insert(value.first);
+      if (p.second) {
+        p.first->value() = CreateValueTypeInternal(value);
+      }
+      return std::pair<iterator, bool>(iterator(p.first), p.second);
+    }
+  }
+  template <class InputIt>
+  void insert(InputIt first, InputIt last) {
+    for (InputIt it = first; it != last; ++it) {
+      iterator exist_it = find(it->first);
+      if (exist_it == end()) {
+        operator[](it->first) = it->second;
+      }
+    }
+  }
+
+  // Erase and clear
+  size_type erase(const key_type& key) {
+    iterator it = find(key);
+    if (it == end()) {
+      return 0;
+    } else {
+      erase(it);
+      return 1;
+    }
+  }
+  iterator erase(iterator pos) {
+    if (arena_ == NULL) delete pos.operator->();
+    iterator i = pos++;
+    if (old_style_)
+      deprecated_elements_->erase(i.dit_);
+    else
+      elements_->erase(i.it_);
+    return pos;
+  }
+  void erase(iterator first, iterator last) {
+    while (first != last) {
+      first = erase(first);
+    }
+  }
+  void clear() { erase(begin(), end()); }
+
+  // Assign
+  Map& operator=(const Map& other) {
+    if (this != &other) {
+      clear();
+      insert(other.begin(), other.end());
+    }
+    return *this;
+  }
+
+  // Access to hasher.  Currently this returns a copy, but it may
+  // be modified to return a const reference in the future.
+  hasher hash_function() const {
+    return old_style_ ? deprecated_elements_->hash_function()
+                      : elements_->hash_function();
+  }
+
+ private:
+  // Set default enum value only for proto2 map field whose value is enum type.
+  void SetDefaultEnumValue(int default_enum_value) {
+    default_enum_value_ = default_enum_value;
+  }
+
+  value_type* CreateValueTypeInternal(const Key& key) {
+    if (arena_ == NULL) {
+      return new value_type(key);
+    } else {
+      value_type* value = reinterpret_cast<value_type*>(
+          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+      Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_);
+      Arena::CreateInArenaStorage(&value->second, arena_);
+      const_cast<Key&>(value->first) = key;
+      return value;
+    }
+  }
+
+  value_type* CreateValueTypeInternal(const value_type& value) {
+    if (arena_ == NULL) {
+      return new value_type(value);
+    } else {
+      value_type* p = reinterpret_cast<value_type*>(
+          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+      Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_);
+      Arena::CreateInArenaStorage(&p->second, arena_);
+      const_cast<Key&>(p->first) = value.first;
+      p->second = value.second;
+      return p;
+    }
+  }
+
+  Arena* arena_;
+  int default_enum_value_;
+  // The following is a tagged union because we support two map styles
+  // for now.
+  // TODO(gpike): get rid of the old style.
+  const bool old_style_;
+  union {
+    InnerMap* elements_;
+    DeprecatedInnerMap* deprecated_elements_;
+  };
+
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V,
+            internal::WireFormatLite::FieldType key_wire_type,
+            internal::WireFormatLite::FieldType value_wire_type,
+            int default_enum_value>
+  friend class internal::MapFieldLite;
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+template<>
+struct hash<google::protobuf::MapKey> {
+  size_t
+  operator()(const google::protobuf::MapKey& map_key) const {
+    switch (map_key.type()) {
+      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+        return hash<string>()(map_key.GetStringValue());
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+        return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+        return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+        return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+        return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
+      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+        return hash<bool>()(map_key.GetBoolValue());
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return 0;
+  }
+  bool
+  operator()(const google::protobuf::MapKey& map_key1,
+             const google::protobuf::MapKey& map_key2) const {
+    return map_key1 < map_key2;
+  }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
+#endif  // GOOGLE_PROTOBUF_MAP_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_entry.h b/src/third_party/protobuf-3/src/google/protobuf/map_entry.h
new file mode 100644
index 0000000..987c4e2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_entry.h
@@ -0,0 +1,308 @@
+// 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_MAP_ENTRY_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
+
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/map_entry_lite.h>
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+namespace internal {
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapField;
+}
+}
+
+namespace protobuf {
+namespace internal {
+
+// Register all MapEntry default instances so we can delete them in
+// ShutdownProtobufLibrary().
+void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
+    MessageLite* default_instance);
+
+// This is the common base class for MapEntry. It is used by MapFieldBase in
+// reflection api, in which the static type of key and value is unknown.
+class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
+ public:
+  ::google::protobuf::Metadata GetMetadata() const {
+    ::google::protobuf::Metadata metadata;
+    metadata.descriptor = descriptor_;
+    metadata.reflection = reflection_;
+    return metadata;
+  }
+
+ protected:
+  MapEntryBase() : descriptor_(NULL), reflection_(NULL) {  }
+  virtual ~MapEntryBase() {}
+
+  const Descriptor* descriptor_;
+  const Reflection* reflection_;
+};
+
+// MapEntry is the returned google::protobuf::Message when calling AddMessage of
+// google::protobuf::Reflection. In order to let it work with generated message
+// reflection, its in-memory type is the same as generated message with the same
+// fields. However, in order to decide the in-memory type of key/value, we need
+// to know both their cpp type in generated api and proto type. In
+// implmentation, all in-memory types have related wire format functions to
+// support except ArenaStringPtr. Therefore, we need to define another type with
+// supporting wire format functions. Since this type is only used as return type
+// of MapEntry accessors, it's named MapEntry accessor type.
+//
+// cpp type:               the type visible to users in public API.
+// proto type:             WireFormatLite::FieldType of the field.
+// in-memory type:         type of the data member used to stored this field.
+// MapEntry accessor type: type used in MapEntry getters/mutators to access the
+//                         field.
+//
+// cpp type | proto type  | in-memory type | MapEntry accessor type
+// int32      TYPE_INT32    int32            int32
+// int32      TYPE_FIXED32  int32            int32
+// string     TYPE_STRING   ArenaStringPtr   string
+// FooEnum    TYPE_ENUM     int              int
+// FooMessage TYPE_MESSAGE  FooMessage*      FooMessage
+//
+// The in-memory types of primitive types can be inferred from its proto type,
+// while we need to explicitly specify the cpp type if proto type is
+// TYPE_MESSAGE to infer the in-memory type.  Moreover, default_enum_value is
+// used to initialize enum field in proto2.
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapEntry : public MapEntryBase {
+  // Provide utilities to parse/serialize key/value.  Provide utilities to
+  // manipulate internal stored type.
+  typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+  typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
+
+  // Enum type cannot be used for MapTypeHandler::Read. Define a type
+  // which will replace Enum with int.
+  typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+  typedef typename ValueTypeHandler::MapEntryAccessorType
+      ValueMapEntryAccessorType;
+
+  // Abbreviation for MapEntry
+  typedef typename google::protobuf::internal::MapEntry<
+      Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
+
+  // Abbreviation for MapEntryLite
+  typedef typename google::protobuf::internal::MapEntryLite<
+      Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
+      EntryLiteType;
+
+ public:
+  ~MapEntry() {
+    if (this == default_instance_) {
+      delete reflection_;
+    }
+  }
+
+  // accessors ======================================================
+
+  virtual inline const KeyMapEntryAccessorType& key() const {
+    return entry_lite_.key();
+  }
+  inline KeyMapEntryAccessorType* mutable_key() {
+    return entry_lite_.mutable_key();
+  }
+  virtual inline const ValueMapEntryAccessorType& value() const {
+    return entry_lite_.value();
+  }
+  inline ValueMapEntryAccessorType* mutable_value() {
+    return entry_lite_.mutable_value();
+  }
+
+  // implements Message =============================================
+
+  bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+    return entry_lite_.MergePartialFromCodedStream(input);
+  }
+
+  int ByteSize() const {
+    return entry_lite_.ByteSize();
+  }
+
+  void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+    entry_lite_.SerializeWithCachedSizes(output);
+  }
+
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+    return entry_lite_.SerializeWithCachedSizesToArray(output);
+  }
+
+  int GetCachedSize() const {
+    return entry_lite_.GetCachedSize();
+  }
+
+  bool IsInitialized() const {
+    return entry_lite_.IsInitialized();
+  }
+
+  Message* New() const {
+    MapEntry* entry = new MapEntry;
+    entry->descriptor_ = descriptor_;
+    entry->reflection_ = reflection_;
+    entry->set_default_instance(default_instance_);
+    return entry;
+  }
+
+  Message* New(Arena* arena) const {
+    MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
+    entry->descriptor_ = descriptor_;
+    entry->reflection_ = reflection_;
+    entry->set_default_instance(default_instance_);
+    return entry;
+  }
+
+  int SpaceUsed() const {
+    int size = sizeof(MapEntry);
+    size += entry_lite_.SpaceUsed();
+    return size;
+  }
+
+  void CopyFrom(const ::google::protobuf::Message& from) {
+    Clear();
+    MergeFrom(from);
+  }
+
+  void MergeFrom(const ::google::protobuf::Message& from) {
+    GOOGLE_CHECK_NE(&from, this);
+    const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
+    if (source == NULL) {
+      ReflectionOps::Merge(from, this);
+    } else {
+      MergeFrom(*source);
+    }
+  }
+
+  void CopyFrom(const MapEntry& from) {
+    Clear();
+    MergeFrom(from);
+  }
+
+  void MergeFrom(const MapEntry& from) {
+    entry_lite_.MergeFrom(from.entry_lite_);
+  }
+
+  void Clear() {
+    entry_lite_.Clear();
+  }
+
+  void InitAsDefaultInstance() {
+    entry_lite_.InitAsDefaultInstance();
+  }
+
+  Arena* GetArena() const {
+    return entry_lite_.GetArena();
+  }
+
+  // Create default MapEntry instance for given descriptor. Descriptor has to be
+  // given when creating default MapEntry instance because different map field
+  // may have the same type and MapEntry class. The given descriptor is needed
+  // to distinguish instances of the same MapEntry class.
+  static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
+    MapEntry* entry = new MapEntry;
+    const Reflection* reflection = new GeneratedMessageReflection(
+        descriptor, entry, offsets_,
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
+        DescriptorPool::generated_pool(),
+        ::google::protobuf::MessageFactory::generated_factory(),
+        sizeof(MapEntry),
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_));
+    entry->descriptor_ = descriptor;
+    entry->reflection_ = reflection;
+    entry->set_default_instance(entry);
+    entry->InitAsDefaultInstance();
+    RegisterMapEntryDefaultInstance(entry);
+    return entry;
+  }
+
+ private:
+  MapEntry()
+      : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {}
+
+  explicit MapEntry(Arena* arena)
+      : _internal_metadata_(arena),
+        default_instance_(NULL),
+        entry_lite_(arena) {}
+
+  inline Arena* GetArenaNoVirtual() const {
+    return entry_lite_.GetArenaNoVirtual();
+  }
+
+  void set_default_instance(MapEntry* default_instance) {
+    default_instance_ = default_instance;
+    entry_lite_.set_default_instance(&default_instance->entry_lite_);
+  }
+
+  static int offsets_[2];
+  UnknownFieldSet _unknown_fields_;
+  InternalMetadataWithArena _internal_metadata_;
+  MapEntry* default_instance_;
+  EntryLiteType entry_lite_;
+
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType, int default_enum>
+  friend class internal::MapField;
+  friend class internal::GeneratedMessageReflection;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
+};
+
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
+             default_enum_value>::offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_ENTRY_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_entry_lite.h b/src/third_party/protobuf-3/src/google/protobuf/map_entry_lite.h
new file mode 100644
index 0000000..7cdf1b9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_entry_lite.h
@@ -0,0 +1,401 @@
+// 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_MAP_ENTRY_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+namespace internal {
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapEntry;
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapFieldLite;
+}  // namespace internal
+}  // namespace protobuf
+
+namespace protobuf {
+namespace internal {
+
+// MapEntryLite is used to implement parsing and serialization of map for lite
+// runtime.
+template <typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+class MapEntryLite : public MessageLite {
+  // Provide utilities to parse/serialize key/value.  Provide utilities to
+  // manipulate internal stored type.
+  typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+  typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
+
+  // Define internal memory layout. Strings and messages are stored as
+  // pointers, while other types are stored as values.
+  typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
+  typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
+
+  // Enum type cannot be used for MapTypeHandler::Read. Define a type
+  // which will replace Enum with int.
+  typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+  typedef typename ValueTypeHandler::MapEntryAccessorType
+      ValueMapEntryAccessorType;
+
+  // Constants for field number.
+  static const int kKeyFieldNumber = 1;
+  static const int kValueFieldNumber = 2;
+
+  // Constants for field tag.
+  static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kKeyFieldNumber, KeyTypeHandler::kWireType);
+  static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+      kValueFieldNumber, ValueTypeHandler::kWireType);
+  static const int kTagSize = 1;
+
+ public:
+  ~MapEntryLite() {
+    if (this != default_instance_) {
+      if (GetArenaNoVirtual() != NULL) return;
+      KeyTypeHandler::DeleteNoArena(key_);
+      ValueTypeHandler::DeleteNoArena(value_);
+    }
+  }
+
+  // accessors ======================================================
+
+  virtual inline const KeyMapEntryAccessorType& key() const {
+    return KeyTypeHandler::GetExternalReference(key_);
+  }
+  virtual inline const ValueMapEntryAccessorType& value() const {
+    GOOGLE_CHECK(default_instance_ != NULL);
+    return ValueTypeHandler::DefaultIfNotInitialized(value_,
+                                                    default_instance_->value_);
+  }
+  inline KeyMapEntryAccessorType* mutable_key() {
+    set_has_key();
+    return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+  }
+  inline ValueMapEntryAccessorType* mutable_value() {
+    set_has_value();
+    return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+  }
+
+  // implements MessageLite =========================================
+
+  // MapEntryLite is for implementation only and this function isn't called
+  // anywhere. Just provide a fake implementation here for MessageLite.
+  string GetTypeName() const { return ""; }
+
+  void CheckTypeAndMergeFrom(const MessageLite& other) {
+    MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
+  }
+
+  bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+    uint32 tag;
+
+    for (;;) {
+      // 1) corrupted data: return false;
+      // 2) unknown field: skip without putting into unknown field set;
+      // 3) unknown enum value: keep it in parsing. In proto2, caller should
+      // check the value and put this entry into containing message's unknown
+      // field set if the value is an unknown enum. In proto3, caller doesn't
+      // need to care whether the value is unknown enum;
+      // 4) missing key/value: missed key/value will have default value. caller
+      // should take this entry as if key/value is set to default value.
+      tag = input->ReadTag();
+      switch (tag) {
+        case kKeyTag:
+          if (!KeyTypeHandler::Read(input, mutable_key())) {
+            return false;
+          }
+          set_has_key();
+          if (!input->ExpectTag(kValueTag)) break;
+          GOOGLE_FALLTHROUGH_INTENDED;
+
+        case kValueTag:
+          if (!ValueTypeHandler::Read(input, mutable_value())) {
+            return false;
+          }
+          set_has_value();
+          if (input->ExpectAtEnd()) return true;
+          break;
+
+        default:
+          if (tag == 0 ||
+              WireFormatLite::GetTagWireType(tag) ==
+              WireFormatLite::WIRETYPE_END_GROUP) {
+            return true;
+          }
+          if (!WireFormatLite::SkipField(input, tag)) return false;
+          break;
+      }
+    }
+  }
+
+  int ByteSize() const {
+    int size = 0;
+    size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
+    size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
+    return size;
+  }
+
+  void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+    KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
+    ValueTypeHandler::Write(kValueFieldNumber, value(), output);
+  }
+
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+    output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output);
+    output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output);
+    return output;
+  }
+
+  int GetCachedSize() const {
+    int size = 0;
+    size += has_key()
+        ? kTagSize + KeyTypeHandler::GetCachedSize(key())
+        : 0;
+    size += has_value()
+        ? kTagSize + ValueTypeHandler::GetCachedSize(
+            value())
+        : 0;
+    return size;
+  }
+
+  bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
+
+  MessageLite* New() const {
+    MapEntryLite* entry = new MapEntryLite;
+    entry->default_instance_ = default_instance_;
+    return entry;
+  }
+
+  MessageLite* New(Arena* arena) const {
+    MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
+    entry->default_instance_ = default_instance_;
+    return entry;
+  }
+
+  int SpaceUsed() const {
+    int size = sizeof(MapEntryLite);
+    size += KeyTypeHandler::SpaceUsedInMapEntry(key_);
+    size += ValueTypeHandler::SpaceUsedInMapEntry(value_);
+    return size;
+  }
+
+  void MergeFrom(const MapEntryLite& from) {
+    if (from._has_bits_[0]) {
+      if (from.has_key()) {
+        KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+        KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
+        set_has_key();
+      }
+      if (from.has_value()) {
+        ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+        ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
+        set_has_value();
+      }
+    }
+  }
+
+  void Clear() {
+    KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
+    ValueTypeHandler::ClearMaybeByDefaultEnum(
+        &value_, GetArenaNoVirtual(), default_enum_value);
+    clear_has_key();
+    clear_has_value();
+  }
+
+  void InitAsDefaultInstance() {
+    KeyTypeHandler::AssignDefaultValue(&key_);
+    ValueTypeHandler::AssignDefaultValue(&value_);
+  }
+
+  Arena* GetArena() const {
+    return GetArenaNoVirtual();
+  }
+
+  // Create a MapEntryLite for given key and value from google::protobuf::Map in
+  // serialization. This function is only called when value is enum. Enum is
+  // treated differently because its type in MapEntry is int and its type in
+  // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
+  static MapEntryLite* EnumWrap(const Key& key, const Value value,
+                                Arena* arena) {
+    return Arena::CreateMessage<MapEnumEntryWrapper<
+        Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
+        arena, key, value);
+  }
+
+  // Like above, but for all the other types. This avoids value copy to create
+  // MapEntryLite from google::protobuf::Map in serialization.
+  static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
+    return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
+                                                kValueFieldType,
+                                                default_enum_value> >(
+        arena, key, value);
+  }
+
+ protected:
+  void set_has_key() { _has_bits_[0] |= 0x00000001u; }
+  bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
+  void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
+  void set_has_value() { _has_bits_[0] |= 0x00000002u; }
+  bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
+  void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+
+ private:
+  // Serializing a generated message containing map field involves serializing
+  // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+  // after serialization should be the same as that of a MapEntry message
+  // containing the same key and value inside it.  However, google::protobuf::Map doesn't
+  // store key and value as MapEntry message, which disables us to use existing
+  // code to serialize message. In order to use existing code to serialize
+  // message, we need to construct a MapEntry from key-value pair. But it
+  // involves copy of key and value to construct a MapEntry. In order to avoid
+  // this copy in constructing a MapEntry, we need the following class which
+  // only takes references of given key and value.
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType v_wire_type, int default_enum>
+  class MapEntryWrapper
+      : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+    typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+    typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+    typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
+
+   public:
+    MapEntryWrapper(Arena* arena, const K& key, const V& value)
+        : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+          key_(key),
+          value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyMapEntryAccessorType& key() const { return key_; }
+    inline const ValueMapEntryAccessorType& value() const { return value_; }
+
+   private:
+    const Key& key_;
+    const Value& value_;
+
+    friend class ::google::protobuf::Arena;
+    typedef void InternalArenaConstructable_;
+    typedef void DestructorSkippable_;
+  };
+
+  // Like above, but for enum value only, which stores value instead of
+  // reference of value field inside. This is needed because the type of value
+  // field in constructor is an enum, while we need to store it as an int. If we
+  // initialize a reference to int with a reference to enum, compiler will
+  // generate a temporary int from enum and initialize the reference to int with
+  // the temporary.
+  template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+            WireFormatLite::FieldType v_wire_type, int default_enum>
+  class MapEnumEntryWrapper
+      : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+    typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+    typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+    typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
+
+   public:
+    MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
+        : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+          key_(key),
+          value_(value) {
+      Base::set_has_key();
+      Base::set_has_value();
+    }
+    inline const KeyMapEntryAccessorType& key() const { return key_; }
+    inline const ValueMapEntryAccessorType& value() const { return value_; }
+
+   private:
+    const KeyMapEntryAccessorType& key_;
+    const ValueMapEntryAccessorType value_;
+
+    friend class google::protobuf::Arena;
+    typedef void DestructorSkippable_;
+  };
+
+  MapEntryLite() : default_instance_(NULL), arena_(NULL) {
+    KeyTypeHandler::Initialize(&key_, NULL);
+    ValueTypeHandler::InitializeMaybeByDefaultEnum(
+        &value_, default_enum_value, NULL);
+    _has_bits_[0] = 0;
+  }
+
+  explicit MapEntryLite(Arena* arena)
+      : default_instance_(NULL), arena_(arena) {
+    KeyTypeHandler::Initialize(&key_, arena);
+    ValueTypeHandler::InitializeMaybeByDefaultEnum(
+        &value_, default_enum_value, arena);
+    _has_bits_[0] = 0;
+  }
+
+  inline Arena* GetArenaNoVirtual() const {
+    return arena_;
+  }
+
+  void set_default_instance(MapEntryLite* default_instance) {
+    default_instance_ = default_instance;
+  }
+
+  MapEntryLite* default_instance_;
+
+  KeyOnMemory key_;
+  ValueOnMemory value_;
+  Arena* arena_;
+  uint32 _has_bits_[1];
+
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  template <typename K, typename V, WireFormatLite::FieldType,
+            WireFormatLite::FieldType, int>
+  friend class internal::MapEntry;
+  template <typename K, typename V, WireFormatLite::FieldType,
+            WireFormatLite::FieldType, int>
+  friend class internal::MapFieldLite;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_field.cc b/src/third_party/protobuf-3/src/google/protobuf/map_field.cc
new file mode 100644
index 0000000..49f9181
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_field.cc
@@ -0,0 +1,471 @@
+// 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.
+
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/map_field_inl.h>
+
+#include <vector>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+ProtobufOnceType map_entry_default_instances_once_;
+Mutex* map_entry_default_instances_mutex_;
+vector<MessageLite*>* map_entry_default_instances_;
+
+void DeleteMapEntryDefaultInstances() {
+  for (int i = 0; i < map_entry_default_instances_->size(); ++i) {
+    delete map_entry_default_instances_->at(i);
+  }
+  delete map_entry_default_instances_mutex_;
+  delete map_entry_default_instances_;
+}
+
+void InitMapEntryDefaultInstances() {
+  map_entry_default_instances_mutex_ = new Mutex();
+  map_entry_default_instances_ = new vector<MessageLite*>();
+  OnShutdown(&DeleteMapEntryDefaultInstances);
+}
+
+void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
+  ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
+                 &InitMapEntryDefaultInstances);
+  MutexLock lock(map_entry_default_instances_mutex_);
+  map_entry_default_instances_->push_back(default_instance);
+}
+
+MapFieldBase::~MapFieldBase() {
+  if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
+}
+
+const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
+  SyncRepeatedFieldWithMap();
+  return *repeated_field_;
+}
+
+RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
+  SyncRepeatedFieldWithMap();
+  SetRepeatedDirty();
+  return repeated_field_;
+}
+
+int MapFieldBase::SpaceUsedExcludingSelf() const {
+  mutex_.Lock();
+  int size = SpaceUsedExcludingSelfNoLock();
+  mutex_.Unlock();
+  return size;
+}
+
+int MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
+  if (repeated_field_ != NULL) {
+    return repeated_field_->SpaceUsedExcludingSelf();
+  } else {
+    return 0;
+  }
+}
+
+void MapFieldBase::InitMetadataOnce() const {
+  GOOGLE_CHECK(entry_descriptor_ != NULL);
+  GOOGLE_CHECK(assign_descriptor_callback_ != NULL);
+  (*assign_descriptor_callback_)();
+}
+
+void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
+
+void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
+
+void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
+
+void MapFieldBase::SyncRepeatedFieldWithMap() const {
+  // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
+  // executed before state_ is checked.
+  Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
+  if (state == STATE_MODIFIED_MAP) {
+    mutex_.Lock();
+    // Double check state, because another thread may have seen the same state
+    // and done the synchronization before the current thread.
+    if (state_ == STATE_MODIFIED_MAP) {
+      SyncRepeatedFieldWithMapNoLock();
+      // "Release" insures state_ can only be changed "after"
+      // SyncRepeatedFieldWithMapNoLock is finished.
+      google::protobuf::internal::Release_Store(&state_, CLEAN);
+    }
+    mutex_.Unlock();
+  }
+}
+
+void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
+  if (repeated_field_ == NULL) {
+    repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
+  }
+}
+
+void MapFieldBase::SyncMapWithRepeatedField() const {
+  // "Acquire" insures the operation after SyncMapWithRepeatedField won't get
+  // executed before state_ is checked.
+  Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
+  if (state == STATE_MODIFIED_REPEATED) {
+    mutex_.Lock();
+    // Double check state, because another thread may have seen the same state
+    // and done the synchronization before the current thread.
+    if (state_ == STATE_MODIFIED_REPEATED) {
+      SyncMapWithRepeatedFieldNoLock();
+      // "Release" insures state_ can only be changed "after"
+      // SyncRepeatedFieldWithMapNoLock is finished.
+      google::protobuf::internal::Release_Store(&state_, CLEAN);
+    }
+    mutex_.Unlock();
+  }
+}
+
+// ------------------DynamicMapField------------------
+DynamicMapField::DynamicMapField(const Message* default_entry)
+    : default_entry_(default_entry) {
+}
+
+DynamicMapField::DynamicMapField(const Message* default_entry,
+                                 Arena* arena)
+    : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
+      default_entry_(default_entry) {
+}
+
+DynamicMapField::~DynamicMapField() {
+  // DynamicMapField owns map values. Need to delete them before clearing
+  // the map.
+  for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
+       iter != map_.end(); ++iter) {
+    iter->second.DeleteData();
+  }
+  map_.clear();
+}
+
+int DynamicMapField::size() const {
+  return GetMap().size();
+}
+
+bool DynamicMapField::ContainsMapKey(
+    const MapKey& map_key) const {
+  const Map<MapKey, MapValueRef>& map = GetMap();
+  Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
+  return iter != map.end();
+}
+
+bool DynamicMapField::InsertOrLookupMapValue(
+    const MapKey& map_key, MapValueRef* val) {
+  // Always use mutable map because users may change the map value by
+  // MapValueRef.
+  Map<MapKey, MapValueRef>* map = MutableMap();
+  Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
+  if (iter == map->end()) {
+    // Insert
+    MapValueRef& map_val = (*map)[map_key];
+    const FieldDescriptor* val_des =
+        default_entry_->GetDescriptor()->FindFieldByName("value");
+    map_val.SetType(val_des->cpp_type());
+    // Allocate memory for the inserted MapValueRef, and initialize to
+    // default value.
+    switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE)                              \
+      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
+        TYPE * value = new TYPE();                              \
+        map_val.SetValue(value);                                \
+        break;                                                  \
+      }
+      HANDLE_TYPE(INT32, int32);
+      HANDLE_TYPE(INT64, int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE(FLOAT, float);
+      HANDLE_TYPE(BOOL, bool);
+      HANDLE_TYPE(STRING, string);
+      HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+        const Message& message = default_entry_->GetReflection()->GetMessage(
+            *default_entry_, val_des);
+        Message* value = message.New();
+        map_val.SetValue(value);
+        break;
+      }
+    }
+    val->CopyFrom(map_val);
+    return true;
+  }
+  // map_key is already in the map. Make sure (*map)[map_key] is not called.
+  // [] may reorder the map and iterators.
+  val->CopyFrom(iter->second);
+  return false;
+}
+
+bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
+  MapFieldBase::SyncMapWithRepeatedField();
+  Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
+  if (iter == map_.end()) {
+    return false;
+  }
+  // Set map dirty only if the delete is successful.
+  MapFieldBase::SetMapDirty();
+  iter->second.DeleteData();
+  map_.erase(iter);
+  return true;
+}
+
+const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
+  MapFieldBase::SyncMapWithRepeatedField();
+  return map_;
+}
+
+Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
+  MapFieldBase::SyncMapWithRepeatedField();
+  MapFieldBase::SetMapDirty();
+  return &map_;
+}
+
+void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
+  Map<MapKey, MapValueRef>::const_iterator iter =
+      TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
+          map_iter);
+  if (iter == map_.end()) return;
+  map_iter->key_.CopyFrom(iter->first);
+  map_iter->value_.CopyFrom(iter->second);
+}
+
+void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
+  const Reflection* reflection = default_entry_->GetReflection();
+  const FieldDescriptor* key_des =
+      default_entry_->GetDescriptor()->FindFieldByName("key");
+  const FieldDescriptor* val_des =
+      default_entry_->GetDescriptor()->FindFieldByName("value");
+  if (MapFieldBase::repeated_field_ == NULL) {
+    if (MapFieldBase::arena_ == NULL) {
+      MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
+    } else {
+      MapFieldBase::repeated_field_ =
+          Arena::CreateMessage<RepeatedPtrField<Message> >(
+              MapFieldBase::arena_);
+    }
+  }
+
+  MapFieldBase::repeated_field_->Clear();
+
+  for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+       it != map_.end(); ++it) {
+    Message* new_entry = default_entry_->New();
+    MapFieldBase::repeated_field_->AddAllocated(new_entry);
+    const MapKey& map_key = it->first;
+    switch (key_des->cpp_type()) {
+      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+        reflection->SetString(new_entry, key_des, map_key.GetStringValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+        reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+        reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+        reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+        reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+        reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Can't get here.";
+        break;
+    }
+    const MapValueRef& map_val = it->second;
+    switch (val_des->cpp_type()) {
+      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+        reflection->SetString(new_entry, val_des, map_val.GetStringValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+        reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+        reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+        reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+        reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+        reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+        reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+        reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+        reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+        const Message& message = map_val.GetMessageValue();
+        reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
+        break;
+      }
+    }
+  }
+}
+
+void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
+  Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
+  const Reflection* reflection = default_entry_->GetReflection();
+  const FieldDescriptor* key_des =
+      default_entry_->GetDescriptor()->FindFieldByName("key");
+  const FieldDescriptor* val_des =
+      default_entry_->GetDescriptor()->FindFieldByName("value");
+  // DynamicMapField owns map values. Need to delete them before clearing
+  // the map.
+  for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
+       iter != map->end(); ++iter) {
+    iter->second.DeleteData();
+  }
+  map->clear();
+  for (RepeatedPtrField<Message>::iterator it =
+           MapFieldBase::repeated_field_->begin();
+       it != MapFieldBase::repeated_field_->end(); ++it) {
+    MapKey map_key;
+    switch (key_des->cpp_type()) {
+      case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+        map_key.SetStringValue(reflection->GetString(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+        map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+        map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+        map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+        map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+        map_key.SetBoolValue(reflection->GetBool(*it, key_des));
+        break;
+      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Can't get here.";
+        break;
+    }
+    MapValueRef& map_val = (*map)[map_key];
+    map_val.SetType(val_des->cpp_type());
+    switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD)                      \
+      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
+        TYPE * value = new TYPE;                                \
+        *value = reflection->Get##METHOD(*it, val_des);         \
+            map_val.SetValue(value);                            \
+            break;                                              \
+      }
+      HANDLE_TYPE(INT32, int32, Int32);
+      HANDLE_TYPE(INT64, int64, Int64);
+      HANDLE_TYPE(UINT32, uint32, UInt32);
+      HANDLE_TYPE(UINT64, uint64, UInt64);
+      HANDLE_TYPE(DOUBLE, double, Double);
+      HANDLE_TYPE(FLOAT, float, Float);
+      HANDLE_TYPE(BOOL, bool, Bool);
+      HANDLE_TYPE(STRING, string, String);
+      HANDLE_TYPE(ENUM, int32, EnumValue);
+#undef HANDLE_TYPE
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+        const Message& message = reflection->GetMessage(*it, val_des);
+        Message* value = message.New();
+        value->CopyFrom(message);
+        map_val.SetValue(value);
+        break;
+      }
+    }
+  }
+}
+
+int DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
+  int size = 0;
+  if (MapFieldBase::repeated_field_ != NULL) {
+    size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
+  }
+  size += sizeof(map_);
+  int map_size = map_.size();
+  if (map_size) {
+    Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+    size += sizeof(it->first) * map_size;
+    size += sizeof(it->second) * map_size;
+    // If key is string, add the allocated space.
+    if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
+      size += sizeof(string) * map_size;
+    }
+    // Add the allocated space in MapValueRef.
+    switch (it->second.type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE)                              \
+      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: {        \
+        size += sizeof(TYPE) * map_size;                        \
+        break;                                                  \
+      }
+      HANDLE_TYPE(INT32, int32);
+      HANDLE_TYPE(INT64, int64);
+      HANDLE_TYPE(UINT32, uint32);
+      HANDLE_TYPE(UINT64, uint64);
+      HANDLE_TYPE(DOUBLE, double);
+      HANDLE_TYPE(FLOAT, float);
+      HANDLE_TYPE(BOOL, bool);
+      HANDLE_TYPE(STRING, string);
+      HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+        while (it != map_.end()) {
+          const Message& message = it->second.GetMessageValue();
+          size += message.GetReflection()->SpaceUsed(message);
+          ++it;
+        }
+        break;
+      }
+    }
+  }
+  return size;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_field.h b/src/third_party/protobuf-3/src/google/protobuf/map_field.h
new file mode 100644
index 0000000..4b46f3a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_field.h
@@ -0,0 +1,397 @@
+// 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_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/map_entry.h>
+#include <google/protobuf/map_field_lite.h>
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/unknown_field_set.h>
+
+
+namespace google {
+namespace protobuf {
+class DynamicMessage;
+class MapKey;
+namespace internal {
+
+class ContendedMapCleanTest;
+class GeneratedMessageReflection;
+class MapFieldAccessor;
+
+// This class provides accesss to map field using reflection, which is the same
+// as those provided for RepeatedPtrField<Message>. It is used for internal
+// reflection implentation only. Users should never use this directly.
+class LIBPROTOBUF_EXPORT MapFieldBase {
+ public:
+  MapFieldBase()
+      : arena_(NULL),
+        repeated_field_(NULL),
+        entry_descriptor_(NULL),
+        assign_descriptor_callback_(NULL),
+        state_(STATE_MODIFIED_MAP) {}
+  explicit MapFieldBase(Arena* arena)
+      : arena_(arena),
+        repeated_field_(NULL),
+        entry_descriptor_(NULL),
+        assign_descriptor_callback_(NULL),
+        state_(STATE_MODIFIED_MAP) {
+    // Mutex's destructor needs to be called explicitly to release resources
+    // acquired in its constructor.
+    arena->OwnDestructor(&mutex_);
+  }
+  virtual ~MapFieldBase();
+
+  // Returns reference to internal repeated field. Data written using
+  // google::protobuf::Map's api prior to calling this function is guarantted to be
+  // included in repeated field.
+  const RepeatedPtrFieldBase& GetRepeatedField() const;
+
+  // Like above. Returns mutable pointer to the internal repeated field.
+  RepeatedPtrFieldBase* MutableRepeatedField();
+
+  // Pure virtual map APIs for Map Reflection.
+  virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
+  virtual bool InsertOrLookupMapValue(
+      const MapKey& map_key, MapValueRef* val) = 0;
+  virtual bool DeleteMapValue(const MapKey& map_key) = 0;
+  virtual bool EqualIterator(const MapIterator& a,
+                             const MapIterator& b) const = 0;
+  virtual void MapBegin(MapIterator* map_iter) const = 0;
+  virtual void MapEnd(MapIterator* map_iter) const = 0;
+  // Sync Map with repeated field and returns the size of map.
+  virtual int size() const = 0;
+
+  // Returns the number of bytes used by the repeated field, excluding
+  // sizeof(*this)
+  int SpaceUsedExcludingSelf() const;
+
+ protected:
+  // Gets the size of space used by map field.
+  virtual int SpaceUsedExcludingSelfNoLock() const;
+
+  // Synchronizes the content in Map to RepeatedPtrField if there is any change
+  // to Map after last synchronization.
+  void SyncRepeatedFieldWithMap() const;
+  virtual void SyncRepeatedFieldWithMapNoLock() const;
+
+  // Synchronizes the content in RepeatedPtrField to Map if there is any change
+  // to RepeatedPtrField after last synchronization.
+  void SyncMapWithRepeatedField() const;
+  virtual void SyncMapWithRepeatedFieldNoLock() const {}
+
+  // Tells MapFieldBase that there is new change to Map.
+  void SetMapDirty();
+
+  // Tells MapFieldBase that there is new change to RepeatedPTrField.
+  void SetRepeatedDirty();
+
+  // Provides derived class the access to repeated field.
+  void* MutableRepeatedPtrField() const;
+
+  // Creates descriptor for only one time.
+  void InitMetadataOnce() const;
+
+  enum State {
+    STATE_MODIFIED_MAP = 0,       // map has newly added data that has not been
+                                  // synchronized to repeated field
+    STATE_MODIFIED_REPEATED = 1,  // repeated field has newly added data that
+                                  // has not been synchronized to map
+    CLEAN = 2,  // data in map and repeated field are same
+  };
+
+  Arena* arena_;
+  mutable RepeatedPtrField<Message>* repeated_field_;
+  // MapEntry can only be created from MapField. To create MapEntry, MapField
+  // needs to know its descriptor, because MapEntry is not generated class which
+  // cannot initialize its own descriptor by calling generated
+  // descriptor-assign-function. Thus, we need to register a callback to
+  // initialize MapEntry's descriptor.
+  const Descriptor** entry_descriptor_;
+  void (*assign_descriptor_callback_)();
+
+  mutable Mutex mutex_;  // The thread to synchronize map and repeated field
+                         // needs to get lock first;
+  mutable volatile Atomic32 state_;  // 0: STATE_MODIFIED_MAP
+                                     // 1: STATE_MODIFIED_REPEATED
+                                     // 2: CLEAN
+
+ private:
+  friend class ContendedMapCleanTest;
+  friend class GeneratedMessageReflection;
+  friend class MapFieldAccessor;
+  friend class ::google::protobuf::DynamicMessage;
+
+  // Virtual helper methods for MapIterator. MapIterator doesn't have the
+  // type helper for key and value. Call these help methods to deal with
+  // different types. Real helper methods are implemented in
+  // TypeDefinedMapFieldBase.
+  friend class ::google::protobuf::MapIterator;
+  // Allocate map<...>::iterator for MapIterator.
+  virtual void InitializeIterator(MapIterator* map_iter) const = 0;
+
+  // DeleteIterator() is called by the destructor of MapIterator only.
+  // It deletes map<...>::iterator for MapIterator.
+  virtual void DeleteIterator(MapIterator* map_iter) const = 0;
+
+  // Copy the map<...>::iterator from other_iterator to
+  // this_iterator.
+  virtual void CopyIterator(MapIterator* this_iterator,
+                            const MapIterator& other_iterator) const = 0;
+
+  // IncreaseIterator() is called by operator++() of MapIterator only.
+  // It implements the ++ operator of MapIterator.
+  virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
+};
+
+// This class provides common Map Reflection implementations for generated
+// message and dynamic message.
+template<typename Key, typename T>
+class TypeDefinedMapFieldBase : public MapFieldBase {
+ public:
+  TypeDefinedMapFieldBase() {}
+  explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
+  ~TypeDefinedMapFieldBase() {}
+  void MapBegin(MapIterator* map_iter) const;
+  void MapEnd(MapIterator* map_iter) const;
+  bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
+
+  virtual const Map<Key, T>& GetMap() const = 0;
+  virtual Map<Key, T>* MutableMap() = 0;
+
+ protected:
+  typename Map<Key, T>::const_iterator& InternalGetIterator(
+      const MapIterator* map_iter) const;
+
+ private:
+  void InitializeIterator(MapIterator* map_iter) const;
+  void DeleteIterator(MapIterator* map_iter) const;
+  void CopyIterator(MapIterator* this_iteratorm,
+                    const MapIterator& that_iterator) const;
+  void IncreaseIterator(MapIterator* map_iter) const;
+
+  virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
+};
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value = 0>
+class MapField : public TypeDefinedMapFieldBase<Key, T>,
+                 public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+                                     default_enum_value> {
+  // Provide utilities to parse/serialize key/value.  Provide utilities to
+  // manipulate internal stored type.
+  typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+  typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
+
+  // Define message type for internal repeated field.
+  typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
+      EntryType;
+  typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
+                       default_enum_value> EntryLiteType;
+
+  // Define abbreviation for parent MapFieldLite
+  typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+                       default_enum_value> MapFieldLiteType;
+
+  // Enum needs to be handled differently from other types because it has
+  // different exposed type in google::protobuf::Map's api and repeated field's api. For
+  // details see the comment in the implementation of
+  // SyncMapWithRepeatedFieldNoLock.
+  static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
+  typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
+
+ public:
+  MapField();
+  explicit MapField(Arena* arena);
+  // MapField doesn't own the default_entry, which means default_entry must
+  // outlive the lifetime of MapField.
+  MapField(const Message* default_entry);
+  // For tests only.
+  MapField(Arena* arena, const Message* default_entry);
+  ~MapField();
+
+  // Implement MapFieldBase
+  bool ContainsMapKey(const MapKey& map_key) const;
+  bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
+  bool DeleteMapValue(const MapKey& map_key);
+
+  // Accessors
+  const Map<Key, T>& GetMap() const;
+  Map<Key, T>* MutableMap();
+
+  // Convenient methods for generated message implementation.
+  int size() const;
+  void Clear();
+  void MergeFrom(const MapFieldLiteType& other);
+  void Swap(MapFieldLiteType* other);
+
+  // Allocates metadata only if this MapField is part of a generated message.
+  void SetEntryDescriptor(const Descriptor** descriptor);
+  void SetAssignDescriptorCallback(void (*callback)());
+
+ private:
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+
+  // MapField needs MapEntry's default instance to create new MapEntry.
+  void InitDefaultEntryOnce() const;
+
+  // Manually set default entry instance. For test only.
+  void SetDefaultEntryOnce(const EntryType* default_entry) const;
+
+  // Convenient methods to get internal google::protobuf::Map
+  const Map<Key, T>& GetInternalMap() const;
+  Map<Key, T>* MutableInternalMap();
+
+  // Implements MapFieldBase
+  void SyncRepeatedFieldWithMapNoLock() const;
+  void SyncMapWithRepeatedFieldNoLock() const;
+  int SpaceUsedExcludingSelfNoLock() const;
+
+  void SetMapIteratorValue(MapIterator* map_iter) const;
+
+  mutable const EntryType* default_entry_;
+
+  friend class ::google::protobuf::Arena;
+};
+
+class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
+ public:
+  explicit DynamicMapField(const Message* default_entry);
+  DynamicMapField(const Message* default_entry, Arena* arena);
+  ~DynamicMapField();
+
+  // Implement MapFieldBase
+  bool ContainsMapKey(const MapKey& map_key) const;
+  bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
+  bool DeleteMapValue(const MapKey& map_key);
+
+  const Map<MapKey, MapValueRef>& GetMap() const;
+  Map<MapKey, MapValueRef>* MutableMap();
+
+  int size() const;
+
+ private:
+  Map<MapKey, MapValueRef> map_;
+  const Message* default_entry_;
+
+  // Implements MapFieldBase
+  void SyncRepeatedFieldWithMapNoLock() const;
+  void SyncMapWithRepeatedFieldNoLock() const;
+  int SpaceUsedExcludingSelfNoLock() const;
+  void SetMapIteratorValue(MapIterator* map_iter) const;
+};
+
+}  // namespace internal
+
+class LIBPROTOBUF_EXPORT MapIterator {
+ public:
+  MapIterator(Message* message, const FieldDescriptor* field) {
+    const Reflection* reflection = message->GetReflection();
+    map_ = reflection->MapData(message, field);
+    key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
+    value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+    map_->InitializeIterator(this);
+  }
+  MapIterator(const MapIterator& other) {
+    map_ = other.map_;
+    map_->InitializeIterator(this);
+    map_->CopyIterator(this, other);
+  }
+  ~MapIterator() {
+    map_->DeleteIterator(this);
+  }
+  friend bool operator==(const MapIterator& a, const MapIterator& b) {
+    return a.map_->EqualIterator(a, b);
+  }
+  friend bool operator!=(const MapIterator& a, const MapIterator& b) {
+    return !a.map_->EqualIterator(a, b);
+  }
+  MapIterator& operator++() {
+    map_->IncreaseIterator(this);
+    return *this;
+  }
+  MapIterator operator++(int) {
+    // iter_ is copied from Map<...>::iterator, no need to
+    // copy from its self again. Use the same implementation
+    // with operator++()
+    map_->IncreaseIterator(this);
+    return *this;
+  }
+  const MapKey& GetKey() {
+    return key_;
+  }
+  const MapValueRef& GetValueRef() {
+    return value_;
+  }
+  MapValueRef* MutableValueRef() {
+    map_->SetMapDirty();
+    return &value_;
+  }
+
+ private:
+  template <typename Key, typename T>
+  friend class internal::TypeDefinedMapFieldBase;
+  friend class internal::DynamicMapField;
+  template <typename Key, typename T,
+            internal::WireFormatLite::FieldType kKeyFieldType,
+            internal::WireFormatLite::FieldType kValueFieldType,
+            int default_enum_value>
+  friend class internal::MapField;
+
+  // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
+  // the iterator. It is allocated by MapField<...>::InitializeIterator() called
+  // in constructor and deleted by MapField<...>::DeleteIterator() called in
+  // destructor.
+  void* iter_;
+  // Point to a MapField to call helper methods implemented in MapField.
+  // MapIterator does not own this object.
+  internal::MapFieldBase* map_;
+  MapKey key_;
+  MapValueRef value_;
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_field_inl.h b/src/third_party/protobuf-3/src/google/protobuf/map_field_inl.h
new file mode 100644
index 0000000..01c9b89
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_field_inl.h
@@ -0,0 +1,489 @@
+// 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_MAP_FIELD_INL_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/map_type_handler.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// UnwrapMapKey template
+template<typename T>
+T UnwrapMapKey(const MapKey& map_key);
+template<>
+inline int32 UnwrapMapKey<int32>(const MapKey& map_key) {
+  return map_key.GetInt32Value();
+}
+template<>
+inline uint32 UnwrapMapKey<uint32>(const MapKey& map_key) {
+  return map_key.GetUInt32Value();
+}
+template<>
+inline int64 UnwrapMapKey<int64>(const MapKey& map_key) {
+  return map_key.GetInt64Value();
+}
+template<>
+inline uint64 UnwrapMapKey<uint64>(const MapKey& map_key) {
+  return map_key.GetUInt64Value();
+}
+template<>
+inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
+  return map_key.GetBoolValue();
+}
+template<>
+inline string UnwrapMapKey<string>(const MapKey& map_key) {
+  return map_key.GetStringValue();
+}
+
+// SetMapKey template
+template<typename T>
+inline void SetMapKey(MapKey* map_key, const T& value);
+template<>
+inline void SetMapKey<int32>(MapKey* map_key, const int32& value) {
+  map_key->SetInt32Value(value);
+}
+template<>
+inline void SetMapKey<uint32>(MapKey* map_key, const uint32& value) {
+  map_key->SetUInt32Value(value);
+}
+template<>
+inline void SetMapKey<int64>(MapKey* map_key, const int64& value) {
+  map_key->SetInt64Value(value);
+}
+template<>
+inline void SetMapKey<uint64>(MapKey* map_key, const uint64& value) {
+  map_key->SetUInt64Value(value);
+}
+template<>
+inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
+  map_key->SetBoolValue(value);
+}
+template<>
+inline void SetMapKey<string>(MapKey* map_key, const string& value) {
+  map_key->SetStringValue(value);
+}
+
+// ------------------------TypeDefinedMapFieldBase---------------
+template <typename Key, typename T>
+typename Map<Key, T>::const_iterator&
+TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
+    const MapIterator* map_iter) const {
+  return *reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+      map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const {
+  InternalGetIterator(map_iter) = GetMap().begin();
+  SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const {
+  InternalGetIterator(map_iter) = GetMap().end();
+}
+
+template <typename Key, typename T>
+bool TypeDefinedMapFieldBase<Key, T>::EqualIterator(const MapIterator& a,
+                                                    const MapIterator& b)
+    const {
+  return InternalGetIterator(&a) == InternalGetIterator(&b);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(MapIterator* map_iter)
+    const {
+  ++InternalGetIterator(map_iter);
+  SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
+    MapIterator* map_iter) const {
+  map_iter->iter_ = new typename Map<Key, T>::const_iterator;
+  GOOGLE_CHECK(map_iter->iter_ != NULL);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(MapIterator* map_iter)
+    const {
+  delete reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+      map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
+    MapIterator* this_iter,
+    const MapIterator& that_iter) const {
+  InternalGetIterator(this_iter) = InternalGetIterator(&that_iter);
+  this_iter->key_.SetType(that_iter.key_.type());
+  // MapValueRef::type() fails when containing data is null. However, if
+  // this_iter points to MapEnd, data can be null.
+  this_iter->value_.SetType(
+      static_cast<FieldDescriptor::CppType>(that_iter.value_.type_));
+  SetMapIteratorValue(this_iter);
+}
+
+// ----------------------------------------------------------------------
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField()
+    : default_entry_(NULL) {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+    Arena* arena)
+    : TypeDefinedMapFieldBase<Key, T>(arena),
+      MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+          arena),
+      default_entry_(NULL) {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+    const Message* default_entry)
+    : default_entry_(down_cast<const EntryType*>(default_entry)) {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+    Arena* arena, const Message* default_entry)
+    : TypeDefinedMapFieldBase<Key, T>(arena),
+      MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+          arena),
+      default_entry_(down_cast<const EntryType*>(default_entry)) {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::~MapField() {}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::size() const {
+  MapFieldBase::SyncMapWithRepeatedField();
+  return MapFieldLiteType::GetInternalMap().size();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::Clear() {
+  MapFieldBase::SyncMapWithRepeatedField();
+  MapFieldLiteType::MutableInternalMap()->clear();
+  MapFieldBase::SetMapDirty();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void MapField<Key, T, kKeyFieldType, kValueFieldType,
+              default_enum_value>::SetMapIteratorValue(
+                  MapIterator* map_iter) const {
+  const Map<Key, T>& map = GetMap();
+  typename Map<Key, T>::const_iterator iter =
+      TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
+  if (iter == map.end()) return;
+  SetMapKey(&map_iter->key_, iter->first);
+  map_iter->value_.SetValue(&iter->second);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+              default_enum_value>::ContainsMapKey(
+                  const MapKey& map_key) const {
+  const Map<Key, T>& map = GetMap();
+  const Key& key = UnwrapMapKey<Key>(map_key);
+  typename Map<Key, T>::const_iterator iter = map.find(key);
+  return iter != map.end();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+              default_enum_value>::InsertOrLookupMapValue(
+                  const MapKey& map_key,
+                  MapValueRef* val) {
+  // Always use mutable map because users may change the map value by
+  // MapValueRef.
+  Map<Key, T>* map = MutableMap();
+  const Key& key = UnwrapMapKey<Key>(map_key);
+  typename Map<Key, T>::iterator iter = map->find(key);
+  if (map->end() == iter) {
+    val->SetValue(&((*map)[key]));
+    return true;
+  }
+  // Key is already in the map. Make sure (*map)[key] is not called.
+  // [] may reorder the map and iterators.
+  val->SetValue(&(iter->second));
+  return false;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+              default_enum_value>::DeleteMapValue(
+                  const MapKey& map_key) {
+  const Key& key = UnwrapMapKey<Key>(map_key);
+  return MutableMap()->erase(key);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::GetMap() const {
+  MapFieldBase::SyncMapWithRepeatedField();
+  return MapFieldLiteType::GetInternalMap();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MutableMap() {
+  MapFieldBase::SyncMapWithRepeatedField();
+  Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
+  MapFieldBase::SetMapDirty();
+  return result;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MergeFrom(
+    const MapFieldLiteType& other) {
+  const MapField& down_other = down_cast<const MapField&>(other);
+  MapFieldBase::SyncMapWithRepeatedField();
+  down_other.SyncMapWithRepeatedField();
+  MapFieldLiteType::MergeFrom(other);
+  MapFieldBase::SetMapDirty();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::Swap(
+    MapFieldLiteType* other) {
+  MapField* down_other = down_cast<MapField*>(other);
+  std::swap(MapFieldBase::repeated_field_, down_other->repeated_field_);
+  MapFieldLiteType::Swap(other);
+  std::swap(MapFieldBase::state_, down_other->state_);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SetEntryDescriptor(
+    const Descriptor** descriptor) {
+  MapFieldBase::entry_descriptor_ = descriptor;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
+  MapFieldBase::assign_descriptor_callback_ = callback;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::GetInternalMap() const {
+  return MapFieldLiteType::GetInternalMap();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::MutableInternalMap() {
+  return MapFieldLiteType::MutableInternalMap();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+  if (MapFieldBase::repeated_field_ == NULL) {
+    if (MapFieldBase::arena_ == NULL) {
+      MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
+    } else {
+      MapFieldBase::repeated_field_ =
+          Arena::CreateMessage<RepeatedPtrField<Message> >(
+              MapFieldBase::arena_);
+    }
+  }
+  const Map<Key, T>& map = GetInternalMap();
+  RepeatedPtrField<EntryType>* repeated_field =
+      reinterpret_cast<RepeatedPtrField<EntryType>*>(
+          MapFieldBase::repeated_field_);
+
+  repeated_field->Clear();
+
+  for (typename Map<Key, T>::const_iterator it = map.begin();
+       it != map.end(); ++it) {
+    InitDefaultEntryOnce();
+    GOOGLE_CHECK(default_entry_ != NULL);
+    EntryType* new_entry =
+        down_cast<EntryType*>(default_entry_->New(MapFieldBase::arena_));
+    repeated_field->AddAllocated(new_entry);
+    (*new_entry->mutable_key()) = it->first;
+    (*new_entry->mutable_value()) = it->second;
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+  Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
+  RepeatedPtrField<EntryType>* repeated_field =
+      reinterpret_cast<RepeatedPtrField<EntryType>*>(
+          MapFieldBase::repeated_field_);
+  GOOGLE_CHECK(MapFieldBase::repeated_field_ != NULL);
+  map->clear();
+  for (typename RepeatedPtrField<EntryType>::iterator it =
+           repeated_field->begin(); it != repeated_field->end(); ++it) {
+    // Cast is needed because Map's api and internal storage is different when
+    // value is enum. For enum, we cannot cast an int to enum. Thus, we have to
+    // copy value. For other types, they have same exposed api type and internal
+    // stored type. We should not introduce value copy for them. We achieve this
+    // by casting to value for enum while casting to reference for other types.
+    (*map)[it->key()] = static_cast<CastValueType>(it->value());
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+  int size = 0;
+  if (MapFieldBase::repeated_field_ != NULL) {
+    size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
+  }
+  Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
+  size += sizeof(*map);
+  for (typename Map<Key, T>::iterator it = map->begin();
+       it != map->end(); ++it) {
+    size += KeyTypeHandler::SpaceUsedInMap(it->first);
+    size += ValueTypeHandler::SpaceUsedInMap(it->second);
+  }
+  return size;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType,
+          int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+         default_enum_value>::InitDefaultEntryOnce()
+    const {
+  if (default_entry_ == NULL) {
+    MapFieldBase::InitMetadataOnce();
+    GOOGLE_CHECK(*MapFieldBase::entry_descriptor_ != NULL);
+    default_entry_ = down_cast<const EntryType*>(
+        MessageFactory::generated_factory()->GetPrototype(
+            *MapFieldBase::entry_descriptor_));
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_field_lite.h b/src/third_party/protobuf-3/src/google/protobuf/map_field_lite.h
new file mode 100644
index 0000000..860dae5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_field_lite.h
@@ -0,0 +1,278 @@
+// 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_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value = 0>
+class MapFieldLite {
+  // Define message type for internal repeated field.
+  typedef MapEntryLite<Key, T, key_wire_type, value_wire_type,
+                       default_enum_value> EntryType;
+
+ public:
+  MapFieldLite();
+  explicit MapFieldLite(Arena* arena);
+  virtual ~MapFieldLite();
+
+  // Accessors
+  virtual const Map<Key, T>& GetMap() const;
+  virtual Map<Key, T>* MutableMap();
+
+  // Convenient methods for generated message implementation.
+  virtual int size() const;
+  virtual void Clear();
+  virtual void MergeFrom(const MapFieldLite& other);
+  virtual void Swap(MapFieldLite* other);
+
+  // Set default enum value only for proto2 map field whose value is enum type.
+  void SetDefaultEnumValue();
+
+  // Used in the implementation of parsing. Caller should take the ownership.
+  EntryType* NewEntry() const;
+  // Used in the implementation of serializing enum value type. Caller should
+  // take the ownership.
+  EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
+  // Used in the implementation of serializing other value types. Caller should
+  // take the ownership.
+  EntryType* NewEntryWrapper(const Key& key, const T& t) const;
+
+ protected:
+  // Convenient methods to get internal google::protobuf::Map
+  virtual const Map<Key, T>& GetInternalMap() const;
+  virtual Map<Key, T>* MutableInternalMap();
+
+ private:
+  typedef void DestructorSkippable_;
+
+  Arena* arena_;
+  Map<Key, T>* map_;
+
+  friend class ::google::protobuf::Arena;
+};
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MapFieldLite()
+    : arena_(NULL) {
+  map_ = new Map<Key, T>;
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MapFieldLite(Arena* arena)
+  : arena_(arena) {
+  map_ = Arena::CreateMessage<Map<Key, T> >(arena);
+  SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::~MapFieldLite() {
+  delete map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::GetMap() const {
+  return *map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MutableMap() {
+  return map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+int
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::size() const {
+  return map_->size();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::Clear() {
+  map_->clear();
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MergeFrom(
+    const MapFieldLite& other) {
+  for (typename Map<Key, T>::const_iterator it = other.map_->begin();
+       it != other.map_->end(); ++it) {
+    (*map_)[it->first] = it->second;
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::Swap(
+    MapFieldLite* other) {
+  std::swap(map_, other->map_);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::SetDefaultEnumValue() {
+  MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::GetInternalMap() const {
+  return *map_;
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::MutableInternalMap() {
+  return map_;
+}
+
+#define EntryType \
+  MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value>
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEntry() const {
+  if (arena_ == NULL) {
+    return new EntryType();
+  } else {
+    return Arena::CreateMessage<EntryType>(arena_);
+  }
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEnumEntryWrapper(const Key& key,
+                                                      const T t) const {
+  return EntryType::EnumWrap(key, t, arena_);
+}
+
+template <typename Key, typename T,
+          WireFormatLite::FieldType key_wire_type,
+          WireFormatLite::FieldType value_wire_type,
+          int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+             default_enum_value>::NewEntryWrapper(const Key& key,
+                                                  const T& t) const {
+  return EntryType::Wrap(key, t, arena_);
+}
+
+#undef EntryType
+
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message.  It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+       ++it) {
+    if (!it->second.IsInitialized()) return false;
+  }
+  return true;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_field_test.cc b/src/third_party/protobuf-3/src/google/protobuf/map_field_test.cc
new file mode 100644
index 0000000..223d42f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_field_test.cc
@@ -0,0 +1,494 @@
+// 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.
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+using unittest::TestAllTypes;
+
+class MapFieldBaseStub : public MapFieldBase {
+ public:
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  MapFieldBaseStub() {}
+  explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
+  void SyncRepeatedFieldWithMap() const {
+    MapFieldBase::SyncRepeatedFieldWithMap();
+  }
+  void SyncMapWithRepeatedField() const {
+    MapFieldBase::SyncMapWithRepeatedField();
+  }
+  // Get underlined repeated field without synchronizing map.
+  RepeatedPtrField<Message>* InternalRepeatedField() {
+    return repeated_field_;
+  }
+  bool IsMapClean() { return state_ != 0; }
+  bool IsRepeatedClean() { return state_ != 1; }
+  void SetMapDirty() { state_ = 0; }
+  void SetRepeatedDirty() { state_ = 1; }
+  bool ContainsMapKey(const MapKey& map_key) const {
+    return false;
+  }
+  bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) {
+    return false;
+  }
+  bool DeleteMapValue(const MapKey& map_key) {
+    return false;
+  }
+  bool EqualIterator(const MapIterator& a, const MapIterator& b) const {
+    return false;
+  }
+  int size() const { return 0; }
+  void MapBegin(MapIterator* map_iter) const {}
+  void MapEnd(MapIterator* map_iter) const {}
+  void InitializeIterator(MapIterator* map_iter) const {}
+  void DeleteIterator(MapIterator* map_iter) const {}
+  void CopyIterator(MapIterator* this_iterator,
+                    const MapIterator& other_iterator) const {}
+  void IncreaseIterator(MapIterator* map_iter) const {}
+  void SetDefaultMessageEntry(const Message* message) const {}
+  const Message* GetDefaultMessageEntry() const { return NULL; }
+};
+
+class MapFieldBasePrimitiveTest : public ::testing::Test {
+ protected:
+  typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+                   WireFormatLite::TYPE_INT32, false> MapFieldType;
+
+  MapFieldBasePrimitiveTest() {
+    // Get descriptors
+    map_descriptor_ = unittest::TestMap::descriptor()
+                          ->FindFieldByName("map_int32_int32")
+                          ->message_type();
+    key_descriptor_ = map_descriptor_->FindFieldByName("key");
+    value_descriptor_ = map_descriptor_->FindFieldByName("value");
+
+    // Build map field
+    default_entry_ =
+        MessageFactory::generated_factory()->GetPrototype(map_descriptor_);
+    map_field_.reset(new MapFieldType(default_entry_));
+    map_field_base_ = map_field_.get();
+    map_ = map_field_->MutableMap();
+    initial_value_map_[0] = 100;
+    initial_value_map_[1] = 101;
+    map_->insert(initial_value_map_.begin(), initial_value_map_.end());
+    EXPECT_EQ(2, map_->size());
+  }
+
+  google::protobuf::scoped_ptr<MapFieldType> map_field_;
+  MapFieldBase* map_field_base_;
+  Map<int32, int32>* map_;
+  const Descriptor* map_descriptor_;
+  const FieldDescriptor* key_descriptor_;
+  const FieldDescriptor* value_descriptor_;
+  const Message* default_entry_;
+  std::map<int32, int32> initial_value_map_;  // copy of initial values inserted
+};
+
+TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
+  EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
+}
+
+TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
+  const RepeatedPtrField<Message>& repeated =
+      reinterpret_cast<const RepeatedPtrField<Message>&>(
+          map_field_base_->GetRepeatedField());
+  EXPECT_EQ(2, repeated.size());
+  for (int i = 0; i < repeated.size(); i++) {
+    const Message& message = repeated.Get(i);
+    int key = message.GetReflection()->GetInt32(message, key_descriptor_);
+    int value = message.GetReflection()->GetInt32(message, value_descriptor_);
+    EXPECT_EQ(value, initial_value_map_[key]);
+  }
+}
+
+TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
+  RepeatedPtrField<Message>* repeated =
+      reinterpret_cast<RepeatedPtrField<Message>*>(
+          map_field_base_->MutableRepeatedField());
+  EXPECT_EQ(2, repeated->size());
+  for (int i = 0; i < repeated->size(); i++) {
+    const Message& message = repeated->Get(i);
+    int key = message.GetReflection()->GetInt32(message, key_descriptor_);
+    int value = message.GetReflection()->GetInt32(message, value_descriptor_);
+    EXPECT_EQ(value, initial_value_map_[key]);
+  }
+}
+
+TEST_F(MapFieldBasePrimitiveTest, Arena) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+
+  {
+    // TODO(liujisi): Re-write the test to ensure the memory for the map and
+    // repeated fields are allocated from arenas.
+    // NoHeapChecker no_heap;
+
+    MapFieldType* map_field =
+        Arena::CreateMessage<MapFieldType>(&arena, default_entry_);
+
+    // Set content in map
+    (*map_field->MutableMap())[100] = 101;
+
+    // Trigger conversion to repeated field.
+    map_field->GetRepeatedField();
+  }
+
+  {
+    // TODO(liujisi): Re-write the test to ensure the memory for the map and
+    // repeated fields are allocated from arenas.
+    // NoHeapChecker no_heap;
+
+    MapFieldBaseStub* map_field =
+        Arena::CreateMessage<MapFieldBaseStub>(&arena);
+
+    // Trigger conversion to repeated field.
+    EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
+  }
+}
+
+namespace {
+enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
+}  // anonymous namespace
+
+class MapFieldStateTest
+    : public testing::TestWithParam<State> {
+ public:
+ protected:
+  typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+                   WireFormatLite::TYPE_INT32, false> MapFieldType;
+  typedef MapFieldLite<int32, int32, WireFormatLite::TYPE_INT32,
+                       WireFormatLite::TYPE_INT32, false> MapFieldLiteType;
+  MapFieldStateTest() : state_(GetParam()) {
+    // Build map field
+    const Descriptor* map_descriptor =
+        unittest::TestMap::descriptor()
+            ->FindFieldByName("map_int32_int32")
+            ->message_type();
+    default_entry_ =
+        MessageFactory::generated_factory()->GetPrototype(map_descriptor);
+    map_field_.reset(new MapFieldType(default_entry_));
+    map_field_base_ = map_field_.get();
+
+    Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
+    switch (state_) {
+      case CLEAN:
+        AddOneStillClean(map_field_.get());
+        break;
+      case MAP_DIRTY:
+        MakeMapDirty(map_field_.get());
+        break;
+      case REPEATED_DIRTY:
+        MakeRepeatedDirty(map_field_.get());
+        break;
+      default:
+        break;
+    }
+  }
+
+  void AddOneStillClean(MapFieldType* map_field) {
+    MapFieldBase* map_field_base = map_field;
+    Map<int32, int32>* map = map_field->MutableMap();
+    (*map)[0] = 0;
+    map_field_base->GetRepeatedField();
+    Expect(map_field, CLEAN, 1, 1, false);
+  }
+
+  void MakeMapDirty(MapFieldType* map_field) {
+    Map<int32, int32>* map = map_field->MutableMap();
+    (*map)[0] = 0;
+    Expect(map_field, MAP_DIRTY, 1, 0, true);
+  }
+
+  void MakeRepeatedDirty(MapFieldType* map_field) {
+    MakeMapDirty(map_field);
+    MapFieldBase* map_field_base = map_field;
+    map_field_base->MutableRepeatedField();
+    Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+                                 ->MapFieldLiteType::MutableMap();
+    map->clear();
+
+    Expect(map_field, REPEATED_DIRTY, 0, 1, false);
+  }
+
+  void Expect(MapFieldType* map_field, State state, int map_size,
+              int repeated_size, bool is_repeated_null) {
+    MapFieldBase* map_field_base = map_field;
+    MapFieldBaseStub* stub =
+        reinterpret_cast<MapFieldBaseStub*>(map_field_base);
+
+    Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+                                 ->MapFieldLiteType::MutableMap();
+    RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
+
+    switch (state) {
+      case MAP_DIRTY:
+        EXPECT_FALSE(stub->IsMapClean());
+        EXPECT_TRUE(stub->IsRepeatedClean());
+        break;
+      case REPEATED_DIRTY:
+        EXPECT_TRUE(stub->IsMapClean());
+        EXPECT_FALSE(stub->IsRepeatedClean());
+        break;
+      case CLEAN:
+        EXPECT_TRUE(stub->IsMapClean());
+        EXPECT_TRUE(stub->IsRepeatedClean());
+        break;
+      default:
+        FAIL();
+    }
+
+    EXPECT_EQ(map_size, map->size());
+    if (is_repeated_null) {
+      EXPECT_TRUE(repeated_field == NULL);
+    } else {
+      EXPECT_EQ(repeated_size, repeated_field->size());
+    }
+  }
+
+  google::protobuf::scoped_ptr<MapFieldType> map_field_;
+  MapFieldBase* map_field_base_;
+  State state_;
+  const Message* default_entry_;
+};
+
+INSTANTIATE_TEST_CASE_P(MapFieldStateTestInstance, MapFieldStateTest,
+                        ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
+
+TEST_P(MapFieldStateTest, GetMap) {
+  map_field_->GetMap();
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), CLEAN, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, MutableMap) {
+  map_field_->MutableMap();
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, MergeFromClean) {
+  MapFieldType other(default_entry_);
+  AddOneStillClean(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, CLEAN, 1, 1, false);
+}
+
+TEST_P(MapFieldStateTest, MergeFromMapDirty) {
+  MapFieldType other(default_entry_);
+  MakeMapDirty(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, MAP_DIRTY, 1, 0, true);
+}
+
+TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
+  MapFieldType other(default_entry_);
+  MakeRepeatedDirty(&other);
+
+  map_field_->MergeFrom(other);
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+  }
+
+  Expect(&other, CLEAN, 1, 1, false);
+}
+
+TEST_P(MapFieldStateTest, SwapClean) {
+  MapFieldType other(default_entry_);
+  AddOneStillClean(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), CLEAN, 1, 1, false);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, SwapMapDirty) {
+  MapFieldType other(default_entry_);
+  MakeMapDirty(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
+  MapFieldType other(default_entry_);
+  MakeRepeatedDirty(&other);
+
+  map_field_->Swap(&other);
+
+  Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+
+  switch (state_) {
+    case CLEAN:
+      Expect(&other, CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(&other, MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, Clear) {
+  map_field_->Clear();
+
+  if (state_ != MAP_DIRTY) {
+    Expect(map_field_.get(), MAP_DIRTY, 0, 1, false);
+  } else {
+    Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
+  }
+}
+
+TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
+  map_field_base_->SpaceUsedExcludingSelf();
+
+  switch (state_) {
+    case CLEAN:
+      Expect(map_field_.get(), CLEAN, 1, 1, false);
+      break;
+    case MAP_DIRTY:
+      Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
+      break;
+    case REPEATED_DIRTY:
+      Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+      break;
+    default:
+      break;
+  }
+}
+
+TEST_P(MapFieldStateTest, GetMapField) {
+  map_field_base_->GetRepeatedField();
+
+  if (state_ != REPEATED_DIRTY) {
+    Expect(map_field_.get(), CLEAN, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+  }
+}
+
+TEST_P(MapFieldStateTest, MutableMapField) {
+  map_field_base_->MutableRepeatedField();
+
+  if (state_ != REPEATED_DIRTY) {
+    Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
+  } else {
+    Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
+  }
+}
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.cc b/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.cc
new file mode 100644
index 0000000..b65b4d6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.cc
@@ -0,0 +1,93 @@
+// 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.
+
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_test_util_impl.h>
+
+namespace google {
+namespace protobuf {
+
+void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) {
+  MapTestUtilImpl::SetMapFields<unittest::MapEnumLite,
+                                unittest::MAP_ENUM_BAR_LITE,
+                                unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) {
+  MapTestUtilImpl::SetArenaMapFields<unittest::MapEnumLite,
+                                     unittest::MAP_ENUM_BAR_LITE,
+                                     unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) {
+  MapTestUtilImpl::SetMapFieldsInitialized(message);
+}
+
+void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) {
+  MapTestUtilImpl::ModifyMapFields<unittest::MapEnumLite,
+                                   unittest::MAP_ENUM_FOO_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectClear(message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnumLite,
+                                      unittest::MAP_ENUM_BAR_LITE,
+                                      unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectArenaMapFieldsSet(
+    const unittest::TestArenaMapLite& message) {
+  MapTestUtilImpl::ExpectArenaMapFieldsSet<unittest::MapEnumLite,
+                                           unittest::MAP_ENUM_BAR_LITE,
+                                           unittest::MAP_ENUM_BAZ_LITE>(
+      message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSetInitialized(
+    const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnumLite,
+                                                 unittest::MAP_ENUM_FOO_LITE>(
+      message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsModified(
+    const unittest::TestMapLite& message) {
+  MapTestUtilImpl::ExpectMapFieldsModified<unittest::MapEnumLite,
+                                           unittest::MAP_ENUM_BAR_LITE,
+                                           unittest::MAP_ENUM_FOO_LITE>(
+      message);
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.h b/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.h
new file mode 100644
index 0000000..66dedde
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_lite_test_util.h
@@ -0,0 +1,80 @@
+// 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_MAP_LITE_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+
+#include <google/protobuf/map_lite_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+class MapLiteTestUtil {
+ public:
+  // Set every field in the TestMapLite message to a unique value.
+  static void SetMapFields(protobuf_unittest::TestMapLite* message);
+
+  // Set every field in the TestArenaMapLite message to a unique value.
+  static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message);
+
+  // Set every field in the message to a default value.
+  static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message);
+
+  // Modify all the map fields of the message (which should already have been
+  // initialized with SetMapFields()).
+  static void ModifyMapFields(protobuf_unittest::TestMapLite* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMapLite.
+  static void ExpectArenaMapFieldsSet(
+      const protobuf_unittest::TestArenaMapLite& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  static void ExpectMapFieldsSetInitialized(
+      const protobuf_unittest::TestMapLite& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  static void ExpectMapFieldsModified(
+      const protobuf_unittest::TestMapLite& message);
+
+  // Check that all fields are empty.
+  static void ExpectClear(const protobuf_unittest::TestMapLite& message);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_lite_unittest.proto b/src/third_party/protobuf-3/src/google/protobuf/map_lite_unittest.proto
new file mode 100644
index 0000000..0592dd7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_lite_unittest.proto
@@ -0,0 +1,130 @@
+// 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.
+
+syntax = "proto2";
+
+option cc_enable_arenas = true;
+option optimize_for = LITE_RUNTIME;
+
+import "google/protobuf/unittest_lite.proto";
+import "google/protobuf/unittest_no_arena_lite.proto";
+
+package protobuf_unittest;
+
+message TestMapLite {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnumLite> map_int32_enum     = 16;
+  map<int32   , ForeignMessageLite> map_int32_foreign_message = 17;
+  map<int32, int32> teboring = 18;
+}
+
+message TestArenaMapLite {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnumLite> map_int32_enum     = 16;
+  map<int32   , ForeignMessageArenaLite> map_int32_foreign_message = 17;
+  map<int32, .protobuf_unittest_no_arena.ForeignMessageLite>
+      map_int32_foreign_message_no_arena = 18;
+}
+
+// Test embeded message with required fields
+message TestRequiredMessageMapLite {
+  map<int32, TestRequiredLite> map_field = 1;
+}
+
+message TestEnumMapLite {
+  map<int32, Proto2MapEnumLite> known_map_field = 101;
+  map<int32, Proto2MapEnumLite> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtraLite {
+  map<int32, Proto2MapEnumPlusExtraLite> known_map_field = 101;
+  map<int32, Proto2MapEnumPlusExtraLite> unknown_map_field = 102;
+}
+
+message TestMessageMapLite {
+  map<int32, TestAllTypesLite> map_int32_message = 1;
+}
+
+enum Proto2MapEnumLite {
+  PROTO2_MAP_ENUM_FOO_LITE = 0;
+  PROTO2_MAP_ENUM_BAR_LITE = 1;
+  PROTO2_MAP_ENUM_BAZ_LITE = 2;
+}
+
+enum Proto2MapEnumPlusExtraLite {
+  E_PROTO2_MAP_ENUM_FOO_LITE   = 0;
+  E_PROTO2_MAP_ENUM_BAR_LITE   = 1;
+  E_PROTO2_MAP_ENUM_BAZ_LITE   = 2;
+  E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
+}
+
+enum MapEnumLite {
+  MAP_ENUM_FOO_LITE = 0;
+  MAP_ENUM_BAR_LITE = 1;
+  MAP_ENUM_BAZ_LITE = 2;
+}
+
+message TestRequiredLite {
+  required int32 a = 1;
+  required int32 b = 2;
+  required int32 c = 3;
+}
+
+message ForeignMessageArenaLite {
+  optional int32 c = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_proto2_unittest.proto b/src/third_party/protobuf-3/src/google/protobuf/map_proto2_unittest.proto
new file mode 100644
index 0000000..916cc54
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_proto2_unittest.proto
@@ -0,0 +1,66 @@
+// 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.
+
+syntax = "proto2";
+
+
+import "google/protobuf/unittest_import.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+enum Proto2MapEnum {
+  PROTO2_MAP_ENUM_FOO   = 0;
+  PROTO2_MAP_ENUM_BAR   = 1;
+  PROTO2_MAP_ENUM_BAZ   = 2;
+}
+
+enum Proto2MapEnumPlusExtra {
+  E_PROTO2_MAP_ENUM_FOO   = 0;
+  E_PROTO2_MAP_ENUM_BAR   = 1;
+  E_PROTO2_MAP_ENUM_BAZ   = 2;
+  E_PROTO2_MAP_ENUM_EXTRA = 3;
+}
+
+message TestEnumMap {
+  map<int32, Proto2MapEnum> known_map_field = 101;
+  map<int32, Proto2MapEnum> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtra {
+  map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
+  map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
+}
+
+message TestImportEnumMap {
+  map<int32, protobuf_unittest_import.ImportEnumForMap> import_enum_amp = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_test.cc b/src/third_party/protobuf-3/src/google/protobuf/map_test.cc
new file mode 100644
index 0000000..9d4d6c1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_test.cc
@@ -0,0 +1,2788 @@
+// 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.
+
+// A hack to include windows.h first, which ensures the GetMessage macro can
+// be undefined when we include <google/protobuf/stubs/common.h>
+#if defined(_WIN32)
+#define _WINSOCKAPI_  // to avoid re-definition in WinSock2.h
+#define NOMINMAX      // to avoid defining min/max macros
+#include <windows.h>
+#endif  // _WIN32
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_proto2_unittest.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/util/time_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+
+using google::protobuf::unittest::ForeignMessage;
+using google::protobuf::unittest::TestAllTypes;
+using google::protobuf::unittest::TestMap;
+using google::protobuf::unittest::TestRecursiveMapMessage;
+
+namespace protobuf {
+namespace internal {
+
+// Map API Test =====================================================
+
+// Parameterized tests on whether to use old style maps.
+class MapImplTest : public testing::TestWithParam<bool> {
+ protected:
+  MapImplTest()
+      : map_ptr_(new Map<int32, int32>(GetParam())),
+        map_(*map_ptr_),
+        const_map_(*map_ptr_) {
+    EXPECT_TRUE(map_.empty());
+    EXPECT_EQ(0, map_.size());
+  }
+  ~MapImplTest() {}
+
+  void ExpectSingleElement(int32 key, int32 value) {
+    EXPECT_FALSE(map_.empty());
+    EXPECT_EQ(1, map_.size());
+    ExpectElement(key, value);
+  }
+
+  void ExpectElements(const std::map<int32, int32>& map) {
+    EXPECT_FALSE(map_.empty());
+    EXPECT_EQ(map.size(), map_.size());
+    for (std::map<int32, int32>::const_iterator it = map.begin();
+         it != map.end(); ++it) {
+      ExpectElement(it->first, it->second);
+    }
+  }
+
+  void ExpectElement(int32 key, int32 value) {
+    // Test map size is correct.
+    EXPECT_EQ(value, map_[key]);
+    EXPECT_EQ(1, map_.count(key));
+
+    // Check mutable at and find work correctly.
+    EXPECT_EQ(value, map_.at(key));
+    Map<int32, int32>::iterator it = map_.find(key);
+
+    // interator dereferenceable
+    EXPECT_EQ(key,   (*it).first);
+    EXPECT_EQ(value, (*it).second);
+    EXPECT_EQ(key,   it->first);
+    EXPECT_EQ(value, it->second);
+
+    // iterator mutable
+    ((*it).second) = value + 1;
+    EXPECT_EQ(value + 1, map_[key]);
+    ((*it).second) = value;
+    EXPECT_EQ(value, map_[key]);
+
+    it->second = value + 1;
+    EXPECT_EQ(value + 1, map_[key]);
+    it->second = value;
+    EXPECT_EQ(value, map_[key]);
+
+    // copy constructor
+    Map<int32, int32>::iterator it_copy = it;
+    EXPECT_EQ(key, it_copy->first);
+    EXPECT_EQ(value, it_copy->second);
+
+    // Immutable API ================================================
+
+    // Check immutable at and find work correctly.
+    EXPECT_EQ(value, const_map_.at(key));
+    Map<int32, int32>::const_iterator const_it = const_map_.find(key);
+
+    // interator dereferenceable
+    EXPECT_EQ(key, (*const_it).first);
+    EXPECT_EQ(value, (*const_it).second);
+    EXPECT_EQ(key, const_it->first);
+    EXPECT_EQ(value, const_it->second);
+
+    // copy constructor
+    Map<int32, int32>::const_iterator const_it_copy = const_it;
+    EXPECT_EQ(key, const_it_copy->first);
+    EXPECT_EQ(value, const_it_copy->second);
+  }
+
+  google::protobuf::scoped_ptr<Map<int32, int32> > map_ptr_;
+  Map<int32, int32>& map_;
+  const Map<int32, int32>& const_map_;
+};
+
+TEST_P(MapImplTest, OperatorBracket) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  EXPECT_EQ(0, map_[key]);
+
+  map_[key] = value1;
+  ExpectSingleElement(key, value1);
+
+  map_[key] = value2;
+  ExpectSingleElement(key, value2);
+}
+
+TEST_P(MapImplTest, OperatorBracketNonExist) {
+  int32 key = 0;
+  int32 default_value = 0;
+
+  EXPECT_EQ(default_value, map_[key]);
+  ExpectSingleElement(key, default_value);
+}
+
+TEST_P(MapImplTest, MutableAt) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  map_[key] = value1;
+  ExpectSingleElement(key, value1);
+
+  map_.at(key) = value2;
+  ExpectSingleElement(key, value2);
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+TEST_P(MapImplTest, MutableAtNonExistDeathTest) {
+  EXPECT_DEATH(map_.at(0), "");
+}
+
+TEST_P(MapImplTest, ImmutableAtNonExistDeathTest) {
+  EXPECT_DEATH(const_map_.at(0), "");
+}
+
+TEST_P(MapImplTest, UsageErrors) {
+  MapKey key;
+  key.SetInt64Value(1);
+  EXPECT_DEATH(key.GetUInt64Value(),
+               "Protocol Buffer map usage error:\n"
+               "MapKey::GetUInt64Value type does not match\n"
+               "  Expected : uint64\n"
+               "  Actual   : int64");
+
+  MapValueRef value;
+  EXPECT_DEATH(value.SetFloatValue(0.1),
+               "Protocol Buffer map usage error:\n"
+               "MapValueRef::type MapValueRef is not initialized.");
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST_P(MapImplTest, CountNonExist) {
+  EXPECT_EQ(0, map_.count(0));
+}
+
+TEST_P(MapImplTest, MutableFindNonExist) {
+  EXPECT_TRUE(map_.end() == map_.find(0));
+}
+
+TEST_P(MapImplTest, ImmutableFindNonExist) {
+  EXPECT_TRUE(const_map_.end() == const_map_.find(0));
+}
+
+TEST_P(MapImplTest, ConstEnd) {
+  EXPECT_TRUE(const_map_.end() == const_map_.cend());
+}
+
+TEST_P(MapImplTest, GetReferenceFromIterator) {
+  for (int i = 0; i < 10; i++) {
+    map_[i] = i;
+  }
+
+  for (Map<int32, int32>::const_iterator it = map_.cbegin();
+       it != map_.cend();) {
+    Map<int32, int32>::const_reference entry = *it++;
+    EXPECT_EQ(entry.first, entry.second);
+  }
+
+  for (Map<int32, int32>::const_iterator it = const_map_.begin();
+       it != const_map_.end();) {
+    Map<int32, int32>::const_reference entry = *it++;
+    EXPECT_EQ(entry.first, entry.second);
+  }
+
+  for (Map<int32, int32>::iterator it = map_.begin(); it != map_.end();) {
+    Map<int32, int32>::reference entry = *it++;
+    EXPECT_EQ(entry.first + 1, ++entry.second);
+  }
+}
+
+TEST_P(MapImplTest, IteratorBasic) {
+  map_[0] = 0;
+
+  // Default constructible (per forward iterator requirements).
+  Map<int, int>::const_iterator cit;
+  Map<int, int>::iterator it;
+
+  it = map_.begin();
+  cit = it;  // Converts to const_iterator
+
+  // Can compare between them.
+  EXPECT_TRUE(it == cit);
+  EXPECT_FALSE(cit != it);
+
+  // Pre increment.
+  EXPECT_FALSE(it == ++cit);
+
+  // Post increment.
+  EXPECT_FALSE(it++ == cit);
+  EXPECT_TRUE(it == cit);
+}
+
+template <typename Iterator>
+static int64 median(Iterator i0, Iterator i1) {
+  vector<int64> v(i0, i1);
+  std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end());
+  return v[v.size() / 2];
+}
+
+static int64 Now() {
+  return google::protobuf::util::TimeUtil::TimestampToNanoseconds(
+      google::protobuf::util::TimeUtil::GetCurrentTime());
+}
+
+// Arbitrary odd integers for creating test data.
+static int k0 = 812398771;
+static int k1 = 1312938717;
+static int k2 = 1321555333;
+
+// A naive begin() implementation will cause begin() to get slower and slower
+// if one erases elements at the "front" of the hash map, and we'd like to
+// avoid that, as std::unordered_map does.
+TEST_P(MapImplTest, BeginIsFast) {
+  // Disable this test for both new and old implementations.
+  if (/*GetParam()*/true) return;
+  Map<int32, int32> map(false);  // This test uses new-style maps only.
+  const int kTestSize = 250000;
+  // Create a random-looking map of size n.  Use non-negative integer keys.
+  uint32 frog = 123983;
+  int last_key = 0;
+  int counter = 0;
+  while (map.size() < kTestSize) {
+    frog *= static_cast<uint32>(k0);
+    frog ^= frog >> 17;
+    frog += counter++;
+    last_key =
+        static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1;
+    GOOGLE_DCHECK_GE(last_key, 0);
+    map[last_key] = last_key ^ 1;
+  }
+  vector<int64> times;
+  // We're going to do map.erase(map.begin()) over and over again.  But,
+  // just in case one iteration is fast compared to the granularity of
+  // our time keeping, we measure kChunkSize iterations per outer-loop iter.
+  const int kChunkSize = 1000;
+  GOOGLE_CHECK_EQ(kTestSize % kChunkSize, 0);
+  do {
+    const int64 start = Now();
+    for (int i = 0; i < kChunkSize; i++) {
+      map.erase(map.begin());
+    }
+    const int64 end = Now();
+    if (end > start) {
+      times.push_back(end - start);
+    }
+  } while (!map.empty());
+  if (times.size() < .99 * kTestSize / kChunkSize) {
+    GOOGLE_LOG(WARNING) << "Now() isn't helping us measure time";
+    return;
+  }
+  int64 x0 = median(times.begin(), times.begin() + 9);
+  int64 x1 = median(times.begin() + times.size() - 9, times.end());
+  GOOGLE_LOG(INFO) << "x0=" << x0 << ", x1=" << x1;
+  // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+  // And we'll probably time out and never get here.  So, this test is
+  // intentionally loose: we check that x0 and x1 are within a factor of 8.
+  EXPECT_GE(x1, x0 / 8);
+  EXPECT_GE(x0, x1 / 8);
+}
+
+// Try to create kTestSize keys that will land in just a few buckets, and
+// time the insertions, to get a rough estimate of whether an O(n^2) worst case
+// was triggered.  This test is a hacky, but probably better than nothing.
+TEST_P(MapImplTest, HashFlood) {
+  const int kTestSize = 1024;  // must be a power of 2
+  std::set<int> s;
+  for (int i = 0; s.size() < kTestSize; i++) {
+    if ((map_.hash_function()(i) & (kTestSize - 1)) < 3) {
+      s.insert(i);
+    }
+  }
+  // Create hash table with kTestSize entries that hash flood a table with
+  // 1024 (or 512 or 2048 or ...) entries.  This assumes that map_ uses powers
+  // of 2 for table sizes, and that it's sufficient to "flood" with respect to
+  // the low bits of the output of map_.hash_function().
+  vector<int64> times;
+  std::set<int>::iterator it = s.begin();
+  int count = 0;
+  do {
+    const int64 start = Now();
+    map_[*it] = 0;
+    const int64 end = Now();
+    if (end > start) {
+      times.push_back(end - start);
+    }
+    ++count;
+    ++it;
+  } while (it != s.end());
+  if (times.size() < .99 * count) return;
+  int64 x0 = median(times.begin(), times.begin() + 9);
+  int64 x1 = median(times.begin() + times.size() - 9, times.end());
+  // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+  // But we want to allow O(n log n).  A factor of 20 should be generous enough.
+  EXPECT_LE(x1, x0 * 20);
+}
+
+template <typename T, typename U>
+static void TestValidityForAllKeysExcept(int key_to_avoid,
+                                         const T& check_map,
+                                         const U& map) {
+  typedef typename U::value_type value_type;  // a key-value pair
+  for (typename U::const_iterator it = map.begin(); it != map.end(); ++it) {
+    const int key = it->first;
+    if (key == key_to_avoid) continue;
+    // All iterators relevant to this key, whether old (from check_map) or new,
+    // must point to the same memory.  So, test pointer equality here.
+    const value_type* check_val = &*check_map.find(key)->second;
+    EXPECT_EQ(check_val, &*it);
+    EXPECT_EQ(check_val, &*map.find(key));
+  }
+}
+
+// EXPECT i0 and i1 to be the same.  Advancing them should have the same effect,
+// too.
+template <typename Iter>
+static void TestEqualIterators(Iter i0, Iter i1, Iter end) {
+  const int kMaxAdvance = 10;
+  for (int i = 0; i < kMaxAdvance; i++) {
+    EXPECT_EQ(i0 == end, i1 == end);
+    if (i0 == end) return;
+    EXPECT_EQ(&*i0, &*i1) << "iter " << i;
+    ++i0;
+    ++i1;
+  }
+}
+
+template <typename IteratorType>
+static void TestOldVersusNewIterator(int skip, Map<int, int>* m) {
+  const int initial_size = m->size();
+  IteratorType it = m->begin();
+  for (int i = 0; i < skip && it != m->end(); it++, i++) {}
+  if (it == m->end()) return;
+  const IteratorType old = it;
+  GOOGLE_LOG(INFO) << "skip=" << skip << ", old->first=" << old->first;
+  const int target_size =
+      initial_size < 100 ? initial_size * 5 : initial_size * 5 / 4;
+  for (int i = 0; m->size() <= target_size; i++) {
+    (*m)[i] = 0;
+  }
+  // Iterator 'old' should still work just fine despite the growth of *m.
+  const IteratorType after_growth = m->find(old->first);
+  TestEqualIterators<IteratorType>(old, after_growth, m->end());
+
+  // Now shrink the number of elements.  Do this with a mix of erases and
+  // inserts to increase the chance that the hashtable will resize to a lower
+  // number of buckets.  (But, in any case, the test is still useful.)
+  for (int i = 0; i < 2 * (target_size - initial_size); i++) {
+    if (i != old->first) {
+      m->erase(i);
+    }
+    if (((i ^ m->begin()->first) & 15) == 0) {
+      (*m)[i * 342] = i;
+    }
+  }
+  // Now, the table has grown and shrunk; test again.
+  TestEqualIterators<IteratorType>(old, m->find(old->first), m->end());
+  TestEqualIterators<IteratorType>(old, after_growth, m->end());
+}
+
+// Create and test an n-element Map, with emphasis on iterator correctness.
+static void StressTestIterators(int n, bool test_old_style_proto2_maps) {
+  GOOGLE_LOG(INFO) << "StressTestIterators " << n;
+  GOOGLE_CHECK_GT(n, 0);
+  // Create a random-looking map of size n.  Use non-negative integer keys.
+  Map<int, int> m(test_old_style_proto2_maps);
+  uint32 frog = 123987 + n;
+  int last_key = 0;
+  int counter = 0;
+  while (m.size() < n) {
+    frog *= static_cast<uint32>(k0);
+    frog ^= frog >> 17;
+    frog += counter++;
+    last_key =
+        static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1;
+    GOOGLE_DCHECK_GE(last_key, 0);
+    m[last_key] = last_key ^ 1;
+  }
+  // Test it.
+  ASSERT_EQ(n, m.size());
+  // Create maps of pointers and iterators.
+  // These should remain valid even if we modify m.
+  hash_map<int, Map<int, int>::value_type*> mp(n);
+  hash_map<int, Map<int, int>::iterator> mi(n);
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+    mp[it->first] = &*it;
+    mi[it->first] = it;
+  }
+  ASSERT_EQ(m.size(), mi.size());
+  ASSERT_EQ(m.size(), mp.size());
+  m.erase(last_key);
+  ASSERT_EQ(n - 1, m.size());
+  TestValidityForAllKeysExcept(last_key, mp, m);
+  TestValidityForAllKeysExcept(last_key, mi, m);
+
+  m[last_key] = 0;
+  ASSERT_EQ(n, m.size());
+  // Test old iterator vs new iterator, with table modification in between.
+  TestOldVersusNewIterator<Map<int, int>::const_iterator>(n % 3, &m);
+  TestOldVersusNewIterator<Map<int, int>::iterator>(n % (1 + (n / 40)), &m);
+  // Finally, ensure erase(iterator) doesn't reorder anything, becuase that is
+  // what its documentation says.
+  m[last_key] = m[last_key ^ 999] = 0;
+  vector<Map<int, int>::iterator> v;
+  v.reserve(m.size());
+  int position_of_last_key = 0;
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+    if (it->first == last_key) {
+      position_of_last_key = v.size();
+    }
+    v.push_back(it);
+  }
+  ASSERT_EQ(m.size(), v.size());
+  const Map<int, int>::iterator erase_result = m.erase(m.find(last_key));
+  int index = 0;
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it, ++index) {
+    if (index == position_of_last_key) {
+      EXPECT_EQ(&*erase_result, &*v[++index]);
+    }
+    ASSERT_EQ(&*it, &*v[index]);
+  }
+}
+
+TEST_P(MapImplTest, IteratorInvalidation) {
+  // As multiple underlying hash_map implementations do not follow the
+  // validation requirement, the test is disabled for old-style maps.
+  if (GetParam()) return;
+  // Create a set of pseudo-random sizes to test.
+#ifndef NDEBUG
+  const int kMaxSizeToTest = 100 * 1000;
+#else
+  const int kMaxSizeToTest = 1000 * 1000;
+#endif
+  std::set<int> s;
+  int n = kMaxSizeToTest;
+  int frog = k1 + n;
+  while (n > 1 && s.size() < 25) {
+    s.insert(n);
+    n = static_cast<int>(n * 100 / (101.0 + (frog & 63)));
+    frog *= k2;
+    frog ^= frog >> 17;
+  }
+  // Ensure we test a few small sizes.
+  s.insert(1);
+  s.insert(2);
+  s.insert(3);
+  // Now, the real work.
+  for (std::set<int>::iterator i = s.begin(); i != s.end(); ++i) {
+    StressTestIterators(*i, GetParam());
+  }
+}
+
+// Test that erase() revalidates iterators.
+TEST_P(MapImplTest, EraseRevalidates) {
+  // As multiple underlying hash_map implementations do not follow the
+  // validation requirement, the test is disabled for old-style maps.
+  if (GetParam()) return;
+  map_[3] = map_[13] = map_[20] = 0;
+  const int initial_size = map_.size();
+  EXPECT_EQ(3, initial_size);
+  vector<Map<int, int>::iterator> v;
+  for (Map<int, int>::iterator it = map_.begin(); it != map_.end(); ++it) {
+    v.push_back(it);
+  }
+  EXPECT_EQ(initial_size, v.size());
+  for (int i = 0; map_.size() <= initial_size * 20; i++) {
+    map_[i] = 0;
+  }
+  const int larger_size = map_.size();
+  // We've greatly increased the size of the map, so it is highly likely that
+  // the following will corrupt m if erase() doesn't properly revalidate
+  // iterators passed to it.  Finishing this routine without crashing indicates
+  // success.
+  for (int i = 0; i < v.size(); i++) {
+    map_.erase(v[i]);
+  }
+  EXPECT_EQ(larger_size - v.size(), map_.size());
+}
+
+template <typename T>
+bool IsConstHelper(T& /*t*/) {  // NOLINT. We want to catch non-const refs here.
+  return false;
+}
+template <typename T>
+bool IsConstHelper(const T& /*t*/) {
+  return true;
+}
+
+TEST_P(MapImplTest, IteratorConstness) {
+  map_[0] = 0;
+  EXPECT_TRUE(IsConstHelper(*map_.cbegin()));
+  EXPECT_TRUE(IsConstHelper(*const_map_.begin()));
+  EXPECT_FALSE(IsConstHelper(*map_.begin()));
+}
+
+bool IsForwardIteratorHelper(std::forward_iterator_tag /*tag*/) { return true; }
+template <typename T>
+bool IsForwardIteratorHelper(T /*t*/) {
+  return false;
+}
+
+TEST_P(MapImplTest, IteratorCategory) {
+  EXPECT_TRUE(IsForwardIteratorHelper(
+      std::iterator_traits<Map<int, int>::iterator>::iterator_category()));
+  EXPECT_TRUE(IsForwardIteratorHelper(std::iterator_traits<
+      Map<int, int>::const_iterator>::iterator_category()));
+}
+
+TEST_P(MapImplTest, InsertSingle) {
+  int32 key = 0;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  // Insert a non-existed key.
+  std::pair<Map<int32, int32>::iterator, bool> result1 =
+      map_.insert(Map<int32, int32>::value_type(key, value1));
+  ExpectSingleElement(key, value1);
+
+  Map<int32, int32>::iterator it1 = result1.first;
+  EXPECT_EQ(key, it1->first);
+  EXPECT_EQ(value1, it1->second);
+  EXPECT_TRUE(result1.second);
+
+  // Insert an existed key.
+  std::pair<Map<int32, int32>::iterator, bool> result2 =
+      map_.insert(Map<int32, int32>::value_type(key, value2));
+  ExpectSingleElement(key, value1);
+
+  Map<int32, int32>::iterator it2 = result2.first;
+  EXPECT_TRUE(it1 == it2);
+  EXPECT_FALSE(result2.second);
+}
+
+TEST_P(MapImplTest, InsertByIterator) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1a = 100;
+  int32 value1b = 101;
+  int32 value2a = 200;
+  int32 value2b = 201;
+
+  std::map<int32, int32> map1;
+  map1[key1] = value1a;
+  map1[key2] = value2a;
+
+  map_.insert(map1.begin(), map1.end());
+  ExpectElements(map1);
+
+  std::map<int32, int32> map2;
+  map2[key1] = value1b;
+  map2[key2] = value2b;
+
+  map_.insert(map2.begin(), map2.end());
+  ExpectElements(map1);
+}
+
+TEST_P(MapImplTest, EraseSingleByKey) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  // Erase an existing key.
+  EXPECT_EQ(1, map_.erase(key));
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+
+  // Erase a non-existing key.
+  EXPECT_EQ(0, map_.erase(key));
+}
+
+TEST_P(MapImplTest, EraseMutipleByKey) {
+  // erase in one specific order to trigger corner cases
+  for (int i = 0; i < 5; i++) {
+    map_[i] = i;
+  }
+
+  map_.erase(0);
+  EXPECT_EQ(4, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(0));
+
+  map_.erase(1);
+  EXPECT_EQ(3, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(1));
+
+  map_.erase(3);
+  EXPECT_EQ(2, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(3));
+
+  map_.erase(4);
+  EXPECT_EQ(1, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(4));
+
+  map_.erase(2);
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(2));
+}
+
+TEST_P(MapImplTest, EraseSingleByIterator) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  Map<int32, int32>::iterator it = map_.find(key);
+  map_.erase(it);
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+TEST_P(MapImplTest, ValidIteratorAfterErase) {
+  for (int i = 0; i < 10; i++) {
+    map_[i] = i;
+  }
+
+  int count = 0;
+
+  for (Map<int32, int32>::iterator it = map_.begin(); it != map_.end();) {
+    count++;
+    if (it->first % 2 == 1) {
+      map_.erase(it++);
+    } else {
+      ++it;
+    }
+  }
+
+  EXPECT_EQ(10, count);
+  EXPECT_EQ(5, map_.size());
+}
+
+TEST_P(MapImplTest, EraseByIterator) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  map_.insert(map.begin(), map.end());
+  ExpectElements(map);
+
+  map_.erase(map_.begin(), map_.end());
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key1));
+  EXPECT_TRUE(map_.end() == map_.find(key2));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+TEST_P(MapImplTest, Clear) {
+  int32 key = 0;
+  int32 value = 100;
+
+  map_[key] = value;
+  ExpectSingleElement(key, value);
+
+  map_.clear();
+
+  EXPECT_TRUE(map_.empty());
+  EXPECT_EQ(0, map_.size());
+  EXPECT_TRUE(map_.end() == map_.find(key));
+  EXPECT_TRUE(map_.begin() == map_.end());
+}
+
+static void CopyConstructorHelper(Arena* arena, Map<int32, int32>* m) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  m->insert(map.begin(), map.end());
+
+  Map<int32, int32> other(*m);
+
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+}
+
+TEST_P(MapImplTest, CopyConstructorWithArena) {
+  Arena a;
+  CopyConstructorHelper(&a, &map_);
+}
+
+TEST_P(MapImplTest, CopyConstructorWithoutArena) {
+  CopyConstructorHelper(NULL, &map_);
+}
+
+TEST_P(MapImplTest, IterConstructor) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  Map<int32, int32> new_map(map.begin(), map.end(),
+                            GetParam());
+
+  EXPECT_EQ(2, new_map.size());
+  EXPECT_EQ(value1, new_map.at(key1));
+  EXPECT_EQ(value2, new_map.at(key2));
+}
+
+TEST_P(MapImplTest, Assigner) {
+  int32 key1 = 0;
+  int32 key2 = 1;
+  int32 value1 = 100;
+  int32 value2 = 101;
+
+  std::map<int32, int32> map;
+  map[key1] = value1;
+  map[key2] = value2;
+
+  map_.insert(map.begin(), map.end());
+
+  Map<int32, int32> other(GetParam());
+  int32 key_other = 123;
+  int32 value_other = 321;
+  other[key_other] = value_other;
+  EXPECT_EQ(1, other.size());
+
+  other = map_;
+
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+  EXPECT_TRUE(other.find(key_other) == other.end());
+
+  // Self assign
+  other = other;
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+
+  // Try assignment to a map with a different choice of "style."
+  Map<int32, int32> m(!GetParam());
+  m = other;
+  EXPECT_EQ(2, m.size());
+  EXPECT_EQ(value1, m.at(key1));
+  EXPECT_EQ(value2, m.at(key2));
+}
+
+TEST_P(MapImplTest, Rehash) {
+  const int test_size = 50;
+  std::map<int32, int32> reference_map;
+  for (int i = 0; i < test_size; i++) {
+    reference_map[i] = i;
+  }
+  for (int i = 0; i < test_size; i++) {
+    map_[i] = reference_map[i];
+    EXPECT_EQ(reference_map[i], map_[i]);
+  }
+  for (int i = 0; i < test_size; i++) {
+    map_.erase(i);
+    EXPECT_TRUE(map_.end() == map_.find(i));
+  }
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_P(MapImplTest, EqualRange) {
+  int key = 100, key_missing = 101;
+  map_[key] = 100;
+
+  std::pair<google::protobuf::Map<int32, int32>::iterator,
+            google::protobuf::Map<int32, int32>::iterator> range = map_.equal_range(key);
+  EXPECT_TRUE(map_.find(key) == range.first);
+  EXPECT_TRUE(++map_.find(key) == range.second);
+
+  range = map_.equal_range(key_missing);
+  EXPECT_TRUE(map_.end() == range.first);
+  EXPECT_TRUE(map_.end() == range.second);
+
+  std::pair<google::protobuf::Map<int32, int32>::const_iterator,
+            google::protobuf::Map<int32, int32>::const_iterator> const_range =
+      const_map_.equal_range(key);
+  EXPECT_TRUE(const_map_.find(key) == const_range.first);
+  EXPECT_TRUE(++const_map_.find(key) == const_range.second);
+
+  const_range = const_map_.equal_range(key_missing);
+  EXPECT_TRUE(const_map_.end() == const_range.first);
+  EXPECT_TRUE(const_map_.end() == const_range.second);
+}
+
+TEST_P(MapImplTest, ConvertToStdMap) {
+  map_[100] = 101;
+  std::map<int32, int32> std_map(map_.begin(), map_.end());
+  EXPECT_EQ(1, std_map.size());
+  EXPECT_EQ(101, std_map[100]);
+}
+
+TEST_P(MapImplTest, ConvertToStdVectorOfPairs) {
+  map_[100] = 101;
+  std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
+  EXPECT_EQ(1, std_vec.size());
+  EXPECT_EQ(100, std_vec[0].first);
+  EXPECT_EQ(101, std_vec[0].second);
+}
+
+INSTANTIATE_TEST_CASE_P(BoolSequence, MapImplTest, testing::Bool());
+
+// Map Field Reflection Test ========================================
+
+static int Func(int i, int j) {
+  return i * j;
+}
+
+static string StrFunc(int i, int j) {
+  string str;
+  SStringPrintf(&str, "%d", Func(i, j));
+  return str;
+}
+
+static int Int(const string& value) {
+  int result = 0;
+  std::istringstream(value) >> result;
+  return result;
+}
+
+class MapFieldReflectionTest : public testing::Test {
+ protected:
+  typedef FieldDescriptor FD;
+};
+
+TEST_F(MapFieldReflectionTest, RegularFields) {
+  TestMap message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  Map<int32, int32>* map_int32_int32 = message.mutable_map_int32_int32();
+  Map<int32, double>* map_int32_double = message.mutable_map_int32_double();
+  Map<string, string>* map_string_string = message.mutable_map_string_string();
+  Map<int32, ForeignMessage>* map_int32_foreign_message =
+      message.mutable_map_int32_foreign_message();
+
+  for (int i = 0; i < 10; ++i) {
+    (*map_int32_int32)[i] = Func(i, 1);
+    (*map_int32_double)[i] = Func(i, 2);
+    (*map_string_string)[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*map_int32_foreign_message)[i].set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+  const FieldDescriptor* fd_map_int32_in32_key =
+      fd_map_int32_int32->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_in32_value =
+      fd_map_int32_int32->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_double_key =
+      fd_map_int32_double->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_double_value =
+      fd_map_int32_double->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_string_string_key =
+      fd_map_string_string->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_string_string_value =
+      fd_map_string_string->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_foreign_message_key =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_foreign_message_value =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("value");
+
+  // Get RepeatedPtrField objects for all fields of interest.
+  const RepeatedPtrField<Message>& mf_int32_int32 =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_int32_int32);
+  const RepeatedPtrField<Message>& mf_int32_double =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_int32_double);
+  const RepeatedPtrField<Message>& mf_string_string =
+      refl->GetRepeatedPtrField<Message>(message, fd_map_string_string);
+  const RepeatedPtrField<Message>&
+      mf_int32_foreign_message =
+          refl->GetRepeatedPtrField<Message>(
+              message, fd_map_int32_foreign_message);
+
+  // Get mutable RepeatedPtrField objects for all fields of interest.
+  RepeatedPtrField<Message>* mmf_int32_int32 =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_int32_int32);
+  RepeatedPtrField<Message>* mmf_int32_double =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_int32_double);
+  RepeatedPtrField<Message>* mmf_string_string =
+      refl->MutableRepeatedPtrField<Message>(&message, fd_map_string_string);
+  RepeatedPtrField<Message>* mmf_int32_foreign_message =
+      refl->MutableRepeatedPtrField<Message>(
+          &message, fd_map_int32_foreign_message);
+
+  // Make sure we can do gets through the RepeatedPtrField objects.
+  for (int i = 0; i < 10; ++i) {
+    {
+      // Check gets through const objects.
+      const Message& message_int32_int32 = mf_int32_int32.Get(i);
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double = mf_int32_double.Get(i);
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string = mf_string_string.Get(i);
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message = mf_int32_foreign_message.Get(i);
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+
+    {
+      // Check gets through mutable objects.
+      const Message& message_int32_int32 = mmf_int32_int32->Get(i);
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double = mmf_int32_double->Get(i);
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string = mmf_string_string->Get(i);
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message = mmf_int32_foreign_message->Get(i);
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+  }
+
+  // Do sets through the RepeatedPtrField objects.
+  for (int i = 0; i < 10; i++) {
+    {
+      Message* message_int32_int32 = mmf_int32_int32->Mutable(i);
+      int32 key_int32_int32 = message_int32_int32->GetReflection()->GetInt32(
+          *message_int32_int32, fd_map_int32_in32_key);
+      message_int32_int32->GetReflection()->SetInt32(message_int32_int32,
+                                                     fd_map_int32_in32_value,
+                                                     Func(key_int32_int32, -1));
+
+      Message* message_int32_double = mmf_int32_double->Mutable(i);
+      int32 key_int32_double = message_int32_double->GetReflection()->GetInt32(
+          *message_int32_double, fd_map_int32_double_key);
+      message_int32_double->GetReflection()->SetDouble(
+          message_int32_double, fd_map_int32_double_value,
+          Func(key_int32_double, -2));
+
+      Message* message_string_string = mmf_string_string->Mutable(i);
+      string key_string_string =
+          message_string_string->GetReflection()->GetString(
+              *message_string_string, fd_map_string_string_key);
+      message_string_string->GetReflection()->SetString(
+          message_string_string, fd_map_string_string_value,
+          StrFunc(Int(key_string_string), -5));
+
+      Message* message_int32_message = mmf_int32_foreign_message->Mutable(i);
+      int32 key_int32_message =
+          message_int32_message->GetReflection()->GetInt32(
+              *message_int32_message, fd_map_int32_foreign_message_key);
+      ForeignMessage* value_int32_message = down_cast<ForeignMessage*>(
+          message_int32_message->GetReflection()
+              ->MutableMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      value_int32_message->set_c(Func(key_int32_message, -6));
+    }
+  }
+
+  // Check gets through mutable objects.
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(Func(i, -1), message.map_int32_int32().at(i));
+    EXPECT_EQ(Func(i, -2), message.map_int32_double().at(i));
+    EXPECT_EQ(StrFunc(i, -5), message.map_string_string().at(StrFunc(i, 1)));
+    EXPECT_EQ(Func(i, -6), message.map_int32_foreign_message().at(i).c());
+  }
+}
+
+TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
+  TestMap message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  Map<int32, int32>* map_int32_int32 = message.mutable_map_int32_int32();
+  Map<int32, double>* map_int32_double = message.mutable_map_int32_double();
+  Map<string, string>* map_string_string = message.mutable_map_string_string();
+  Map<int32, ForeignMessage>* map_int32_foreign_message =
+      message.mutable_map_int32_foreign_message();
+
+  for (int i = 0; i < 10; ++i) {
+    (*map_int32_int32)[i] = Func(i, 1);
+    (*map_int32_double)[i] = Func(i, 2);
+    (*map_string_string)[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*map_int32_foreign_message)[i].set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+  const FieldDescriptor* fd_map_int32_in32_key =
+      fd_map_int32_int32->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_in32_value =
+      fd_map_int32_int32->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_double_key =
+      fd_map_int32_double->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_double_value =
+      fd_map_int32_double->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_string_string_key =
+      fd_map_string_string->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_string_string_value =
+      fd_map_string_string->message_type()->FindFieldByName("value");
+  const FieldDescriptor* fd_map_int32_foreign_message_key =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("key");
+  const FieldDescriptor* fd_map_int32_foreign_message_value =
+      fd_map_int32_foreign_message->message_type()->FindFieldByName("value");
+
+  // Get RepeatedFieldRef objects for all fields of interest.
+  const RepeatedFieldRef<Message> mf_int32_int32 =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_int32);
+  const RepeatedFieldRef<Message> mf_int32_double =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_double);
+  const RepeatedFieldRef<Message> mf_string_string =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_string_string);
+  const RepeatedFieldRef<Message> mf_int32_foreign_message =
+      refl->GetRepeatedFieldRef<Message>(message, fd_map_int32_foreign_message);
+
+  // Get mutable RepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<Message> mmf_int32_int32 =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_int32_int32);
+  const MutableRepeatedFieldRef<Message> mmf_int32_double =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_int32_double);
+  const MutableRepeatedFieldRef<Message> mmf_string_string =
+      refl->GetMutableRepeatedFieldRef<Message>(&message, fd_map_string_string);
+  const MutableRepeatedFieldRef<Message>
+      mmf_int32_foreign_message =
+          refl->GetMutableRepeatedFieldRef<Message>(
+              &message, fd_map_int32_foreign_message);
+
+  // Get entry default instances
+  google::protobuf::scoped_ptr<Message> entry_int32_int32(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_int32->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_int32_double(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_double->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_string_string(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_string_string->message_type())
+          ->New());
+  google::protobuf::scoped_ptr<Message> entry_int32_foreign_message(
+      MessageFactory::generated_factory()
+          ->GetPrototype(fd_map_int32_foreign_message->message_type())
+          ->New());
+
+  EXPECT_EQ(10, mf_int32_int32.size());
+  EXPECT_EQ(10, mmf_int32_int32.size());
+  EXPECT_EQ(10, mf_int32_double.size());
+  EXPECT_EQ(10, mmf_int32_double.size());
+  EXPECT_EQ(10, mf_string_string.size());
+  EXPECT_EQ(10, mmf_string_string.size());
+  EXPECT_EQ(10, mf_int32_foreign_message.size());
+  EXPECT_EQ(10, mmf_int32_foreign_message.size());
+
+  EXPECT_FALSE(mf_int32_int32.empty());
+  EXPECT_FALSE(mmf_int32_int32.empty());
+  EXPECT_FALSE(mf_int32_double.empty());
+  EXPECT_FALSE(mmf_int32_double.empty());
+  EXPECT_FALSE(mf_string_string.empty());
+  EXPECT_FALSE(mmf_string_string.empty());
+  EXPECT_FALSE(mf_int32_foreign_message.empty());
+  EXPECT_FALSE(mmf_int32_foreign_message.empty());
+
+  // Make sure we can do gets through the RepeatedFieldRef objects.
+  for (int i = 0; i < 10; ++i) {
+    {
+      // Check gets through const objects.
+      const Message& message_int32_int32 =
+          mf_int32_int32.Get(i, entry_int32_int32.get());
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double =
+          mf_int32_double.Get(i, entry_int32_double.get());
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string =
+          mf_string_string.Get(i, entry_string_string.get());
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message =
+          mf_int32_foreign_message.Get(i, entry_int32_foreign_message.get());
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+
+    {
+      // Check gets through mutable objects.
+      const Message& message_int32_int32 =
+          mmf_int32_int32.Get(i, entry_int32_int32.get());
+      int32 key_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_key);
+      int32 value_int32_int32 = message_int32_int32.GetReflection()->GetInt32(
+          message_int32_int32, fd_map_int32_in32_value);
+      EXPECT_EQ(value_int32_int32, Func(key_int32_int32, 1));
+
+      const Message& message_int32_double =
+          mmf_int32_double.Get(i, entry_int32_double.get());
+      int32 key_int32_double = message_int32_double.GetReflection()->GetInt32(
+          message_int32_double, fd_map_int32_double_key);
+      double value_int32_double =
+          message_int32_double.GetReflection()->GetDouble(
+              message_int32_double, fd_map_int32_double_value);
+      EXPECT_EQ(value_int32_double, Func(key_int32_double, 2));
+
+      const Message& message_string_string =
+          mmf_string_string.Get(i, entry_string_string.get());
+      string key_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_key);
+      string value_string_string =
+          message_string_string.GetReflection()->GetString(
+              message_string_string, fd_map_string_string_value);
+      EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5));
+
+      const Message& message_int32_message =
+          mmf_int32_foreign_message.Get(i, entry_int32_foreign_message.get());
+      int32 key_int32_message = message_int32_message.GetReflection()->GetInt32(
+          message_int32_message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& value_int32_message =
+          down_cast<const ForeignMessage&>(
+              message_int32_message.GetReflection()
+                  ->GetMessage(message_int32_message,
+                               fd_map_int32_foreign_message_value));
+      EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
+    }
+  }
+
+  // Make sure we can do sets through the RepeatedFieldRef objects.
+  for (int i = 0; i < 10; i++) {
+    const Message& message_int32_int32 =
+        mmf_int32_int32.Get(i, entry_int32_int32.get());
+    int key = message_int32_int32.GetReflection()->GetInt32(
+        message_int32_int32, fd_map_int32_in32_key);
+
+    entry_int32_int32->GetReflection()->SetInt32(
+        entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(0),
+        key);
+    entry_int32_int32->GetReflection()->SetInt32(
+        entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(1),
+        Func(key, -1));
+    entry_int32_double->GetReflection()->SetInt32(
+        entry_int32_double.get(), fd_map_int32_double->message_type()->field(0),
+        key);
+    entry_int32_double->GetReflection()->SetDouble(
+        entry_int32_double.get(), fd_map_int32_double->message_type()->field(1),
+        Func(key, -2));
+    entry_string_string->GetReflection()->SetString(
+        entry_string_string.get(),
+        fd_map_string_string->message_type()->field(0), StrFunc(key, 1));
+    entry_string_string->GetReflection()->SetString(
+        entry_string_string.get(),
+        fd_map_string_string->message_type()->field(1), StrFunc(key, -5));
+    entry_int32_foreign_message->GetReflection()->SetInt32(
+        entry_int32_foreign_message.get(),
+        fd_map_int32_foreign_message->message_type()->field(0), key);
+    Message* value_message =
+        entry_int32_foreign_message->GetReflection()->MutableMessage(
+            entry_int32_foreign_message.get(),
+            fd_map_int32_foreign_message->message_type()->field(1));
+    value_message->GetReflection()->SetInt32(
+        value_message, value_message->GetDescriptor()->FindFieldByName("c"),
+        Func(key, -6));
+
+    mmf_int32_int32.Set(i, *entry_int32_int32);
+    mmf_int32_double.Set(i, *entry_int32_double);
+    mmf_string_string.Set(i, *entry_string_string);
+    mmf_int32_foreign_message.Set(i, *entry_int32_foreign_message);
+  }
+
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(Func(i, -1), message.map_int32_int32().at(i));
+    EXPECT_EQ(Func(i, -2), message.map_int32_double().at(i));
+    EXPECT_EQ(StrFunc(i, -5), message.map_string_string().at(StrFunc(i, 1)));
+    EXPECT_EQ(Func(i, -6), message.map_int32_foreign_message().at(i).c());
+  }
+
+  // Test iterators.
+  {
+    int index = 0;
+    hash_map<int32, int32> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_int32_int32.begin();
+         it != mf_int32_int32.end(); ++it) {
+      const Message& message = *it;
+      int32 key =
+          message.GetReflection()->GetInt32(message, fd_map_int32_in32_key);
+      int32 value =
+          message.GetReflection()->GetInt32(message, fd_map_int32_in32_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<int32, int32>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_int32().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    hash_map<int32, double> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_int32_double.begin();
+         it != mf_int32_double.end(); ++it) {
+      const Message& message = *it;
+      int32 key =
+          message.GetReflection()->GetInt32(message, fd_map_int32_double_key);
+      double value = message.GetReflection()->GetDouble(
+          message, fd_map_int32_double_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<int32, double>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_double().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    hash_map<string, string> result;
+    for (RepeatedFieldRef<Message>::iterator it = mf_string_string.begin();
+         it != mf_string_string.end(); ++it) {
+      const Message& message = *it;
+      string key =
+          message.GetReflection()->GetString(message, fd_map_string_string_key);
+      string value = message.GetReflection()->GetString(
+          message, fd_map_string_string_value);
+      result[key] = value;
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (hash_map<string, string>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_string_string().at(it->first), it->second);
+    }
+  }
+
+  {
+    int index = 0;
+    std::map<int32, ForeignMessage> result;
+    for (RepeatedFieldRef<Message>::iterator it =
+             mf_int32_foreign_message.begin();
+         it != mf_int32_foreign_message.end(); ++it) {
+      const Message& message = *it;
+      int32 key = message.GetReflection()->GetInt32(
+          message, fd_map_int32_foreign_message_key);
+      const ForeignMessage& sub_message = down_cast<const ForeignMessage&>(
+          message.GetReflection()
+              ->GetMessage(message, fd_map_int32_foreign_message_value));
+      result[key].MergeFrom(sub_message);
+      ++index;
+    }
+    EXPECT_EQ(10, index);
+    for (std::map<int32, ForeignMessage>::const_iterator it = result.begin();
+         it != result.end(); ++it) {
+      EXPECT_EQ(message.map_int32_foreign_message().at(it->first).c(),
+                it->second.c());
+    }
+  }
+
+  // Test MutableRepeatedFieldRef::Add()
+  entry_int32_int32->GetReflection()->SetInt32(
+      entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(0),
+      4321);
+  entry_int32_int32->GetReflection()->SetInt32(
+      entry_int32_int32.get(), fd_map_int32_int32->message_type()->field(1),
+      1234);
+  mmf_int32_int32.Add(*entry_int32_int32);
+  EXPECT_EQ(1234, message.map_int32_int32().at(4321));
+
+  entry_int32_double->GetReflection()->SetInt32(
+      entry_int32_double.get(), fd_map_int32_double->message_type()->field(0),
+      4321);
+  entry_int32_double->GetReflection()->SetDouble(
+      entry_int32_double.get(), fd_map_int32_double->message_type()->field(1),
+      1234.0);
+  mmf_int32_double.Add(*entry_int32_double);
+  EXPECT_EQ(1234.0, message.map_int32_double().at(4321));
+
+  entry_string_string->GetReflection()->SetString(
+      entry_string_string.get(),
+      fd_map_string_string->message_type()->field(0), "4321");
+  entry_string_string->GetReflection()->SetString(
+      entry_string_string.get(), fd_map_string_string->message_type()->field(1),
+      "1234");
+  mmf_string_string.Add(*entry_string_string);
+  EXPECT_EQ("1234", message.map_string_string().at("4321"));
+
+  entry_int32_foreign_message->GetReflection()->SetInt32(
+      entry_int32_foreign_message.get(),
+      fd_map_int32_foreign_message->message_type()->field(0), 4321);
+  Message* value_message =
+      entry_int32_foreign_message->GetReflection()->MutableMessage(
+          entry_int32_foreign_message.get(),
+          fd_map_int32_foreign_message->message_type()->field(1));
+  ForeignMessage foreign_message;
+  foreign_message.set_c(1234);
+  value_message->CopyFrom(foreign_message);
+
+  mmf_int32_foreign_message.Add(*entry_int32_foreign_message);
+  EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c());
+
+  // Test Reflection::AddAllocatedMessage
+  Message* free_entry_string_string = MessageFactory::generated_factory()
+      ->GetPrototype(fd_map_string_string->message_type())
+      ->New();
+  entry_string_string->GetReflection()->SetString(
+      free_entry_string_string,
+      fd_map_string_string->message_type()->field(0), "4321");
+  entry_string_string->GetReflection()->SetString(
+      free_entry_string_string, fd_map_string_string->message_type()->field(1),
+      "1234");
+  refl->AddAllocatedMessage(&message, fd_map_string_string,
+                            free_entry_string_string);
+
+  // Test MutableRepeatedFieldRef::RemoveLast()
+  mmf_int32_int32.RemoveLast();
+  mmf_int32_double.RemoveLast();
+  mmf_string_string.RemoveLast();
+  mmf_int32_foreign_message.RemoveLast();
+  EXPECT_EQ(10, message.map_int32_int32().size());
+  EXPECT_EQ(10, message.map_int32_double().size());
+  EXPECT_EQ(11, message.map_string_string().size());
+  EXPECT_EQ(10, message.map_int32_foreign_message().size());
+
+  // Test MutableRepeatedFieldRef::SwapElements()
+  {
+    const Message& message0a = mmf_int32_int32.Get(0, entry_int32_int32.get());
+    int32 int32_value0a =
+        message0a.GetReflection()->GetInt32(message0a, fd_map_int32_in32_value);
+    const Message& message9a = mmf_int32_int32.Get(9, entry_int32_int32.get());
+    int32 int32_value9a =
+        message9a.GetReflection()->GetInt32(message9a, fd_map_int32_in32_value);
+
+    mmf_int32_int32.SwapElements(0, 9);
+
+    const Message& message0b = mmf_int32_int32.Get(0, entry_int32_int32.get());
+    int32 int32_value0b =
+        message0b.GetReflection()->GetInt32(message0b, fd_map_int32_in32_value);
+    const Message& message9b = mmf_int32_int32.Get(9, entry_int32_int32.get());
+    int32 int32_value9b =
+        message9b.GetReflection()->GetInt32(message9b, fd_map_int32_in32_value);
+
+    EXPECT_EQ(int32_value9a, int32_value0b);
+    EXPECT_EQ(int32_value0a, int32_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_int32_double.Get(0, entry_int32_double.get());
+    double double_value0a = message0a.GetReflection()->GetDouble(
+        message0a, fd_map_int32_double_value);
+    const Message& message9a =
+        mmf_int32_double.Get(9, entry_int32_double.get());
+    double double_value9a = message9a.GetReflection()->GetDouble(
+        message9a, fd_map_int32_double_value);
+
+    mmf_int32_double.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_int32_double.Get(0, entry_int32_double.get());
+    double double_value0b = message0b.GetReflection()->GetDouble(
+        message0b, fd_map_int32_double_value);
+    const Message& message9b =
+        mmf_int32_double.Get(9, entry_int32_double.get());
+    double double_value9b = message9b.GetReflection()->GetDouble(
+        message9b, fd_map_int32_double_value);
+
+    EXPECT_EQ(double_value9a, double_value0b);
+    EXPECT_EQ(double_value0a, double_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_string_string.Get(0, entry_string_string.get());
+    string string_value0a = message0a.GetReflection()->GetString(
+        message0a, fd_map_string_string_value);
+    const Message& message9a =
+        mmf_string_string.Get(9, entry_string_string.get());
+    string string_value9a = message9a.GetReflection()->GetString(
+        message9a, fd_map_string_string_value);
+
+    mmf_string_string.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_string_string.Get(0, entry_string_string.get());
+    string string_value0b = message0b.GetReflection()->GetString(
+        message0b, fd_map_string_string_value);
+    const Message& message9b =
+        mmf_string_string.Get(9, entry_string_string.get());
+    string string_value9b = message9b.GetReflection()->GetString(
+        message9b, fd_map_string_string_value);
+
+    EXPECT_EQ(string_value9a, string_value0b);
+    EXPECT_EQ(string_value0a, string_value9b);
+  }
+
+  {
+    const Message& message0a =
+        mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message0a = down_cast<const ForeignMessage&>(
+        message0a.GetReflection()
+            ->GetMessage(message0a, fd_map_int32_foreign_message_value));
+    int32 int32_value0a = sub_message0a.c();
+    const Message& message9a =
+        mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message9a = down_cast<const ForeignMessage&>(
+        message9a.GetReflection()
+            ->GetMessage(message9a, fd_map_int32_foreign_message_value));
+    int32 int32_value9a = sub_message9a.c();
+
+    mmf_int32_foreign_message.SwapElements(0, 9);
+
+    const Message& message0b =
+        mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message0b = down_cast<const ForeignMessage&>(
+        message0b.GetReflection()
+            ->GetMessage(message0b, fd_map_int32_foreign_message_value));
+    int32 int32_value0b = sub_message0b.c();
+    const Message& message9b =
+        mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
+    const ForeignMessage& sub_message9b = down_cast<const ForeignMessage&>(
+        message9b.GetReflection()
+            ->GetMessage(message9b, fd_map_int32_foreign_message_value));
+    int32 int32_value9b = sub_message9b.c();
+
+    EXPECT_EQ(int32_value9a, int32_value0b);
+    EXPECT_EQ(int32_value0a, int32_value9b);
+  }
+}
+
+TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
+  // Set-up message content.
+  TestMap m0, m1, m2;
+  for (int i = 0; i < 10; ++i) {
+    (*m0.mutable_map_int32_int32())[i] = Func(i, 1);
+    (*m0.mutable_map_int32_double())[i] = Func(i, 2);
+    (*m0.mutable_map_string_string())[StrFunc(i, 1)] = StrFunc(i, 5);
+    (*m0.mutable_map_int32_foreign_message())[i].set_c(Func(i, 6));
+    (*m1.mutable_map_int32_int32())[i + 10] = Func(i, 11);
+    (*m1.mutable_map_int32_double())[i + 10] = Func(i, 12);
+    (*m1.mutable_map_string_string())[StrFunc(i + 10, 1)] = StrFunc(i, 15);
+    (*m1.mutable_map_int32_foreign_message())[i + 10].set_c(Func(i, 16));
+    (*m2.mutable_map_int32_int32())[i + 20] = Func(i, 21);
+    (*m2.mutable_map_int32_double())[i + 20] = Func(i, 22);
+    (*m2.mutable_map_string_string())[StrFunc(i + 20, 1)] = StrFunc(i, 25);
+    (*m2.mutable_map_int32_foreign_message())[i + 20].set_c(Func(i, 26));
+  }
+
+  const Reflection* refl = m0.GetReflection();
+  const Descriptor* desc = m0.GetDescriptor();
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_map_int32_int32 =
+      desc->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* fd_map_int32_double =
+      desc->FindFieldByName("map_int32_double");
+  const FieldDescriptor* fd_map_string_string =
+      desc->FindFieldByName("map_string_string");
+  const FieldDescriptor* fd_map_int32_foreign_message =
+      desc->FindFieldByName("map_int32_foreign_message");
+
+    // Get MutableRepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<Message> mmf_int32_int32 =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_int32_int32);
+  const MutableRepeatedFieldRef<Message> mmf_int32_double =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_int32_double);
+  const MutableRepeatedFieldRef<Message> mmf_string_string =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m0, fd_map_string_string);
+  const MutableRepeatedFieldRef<Message>
+      mmf_int32_foreign_message =
+          refl->GetMutableRepeatedFieldRef<Message>(
+              &m0, fd_map_int32_foreign_message);
+
+  // Test MutableRepeatedRef::CopyFrom
+  mmf_int32_int32.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_int32));
+  mmf_int32_double.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_double));
+  mmf_string_string.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_string_string));
+  mmf_int32_foreign_message.CopyFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m1, fd_map_int32_foreign_message));
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 11), m0.map_int32_int32().at(i + 10));
+    EXPECT_EQ(Func(i, 12), m0.map_int32_double().at(i + 10));
+    EXPECT_EQ(StrFunc(i, 15), m0.map_string_string().at(StrFunc(i + 10, 1)));
+    EXPECT_EQ(Func(i, 16), m0.map_int32_foreign_message().at(i + 10).c());
+  }
+
+  // Test MutableRepeatedRef::MergeFrom
+  mmf_int32_int32.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_int32));
+  mmf_int32_double.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_double));
+  mmf_string_string.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_string_string));
+  mmf_int32_foreign_message.MergeFrom(
+      refl->GetRepeatedFieldRef<Message>(
+          m2, fd_map_int32_foreign_message));
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m0.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m0.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m0.map_int32_foreign_message().at(i + 20).c());
+  }
+
+  // Test MutableRepeatedRef::Swap
+  // Swap between m0 and m2.
+  mmf_int32_int32.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_int32));
+  mmf_int32_double.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_double));
+  mmf_string_string.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_string_string));
+  mmf_int32_foreign_message.Swap(
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &m2, fd_map_int32_foreign_message));
+  for (int i = 0; i < 10; ++i) {
+    // Check the content of m0.
+    EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m0.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m0.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m0.map_int32_foreign_message().at(i + 20).c());
+
+    // Check the content of m2.
+    EXPECT_EQ(Func(i, 11), m2.map_int32_int32().at(i + 10));
+    EXPECT_EQ(Func(i, 12), m2.map_int32_double().at(i + 10));
+    EXPECT_EQ(StrFunc(i, 15), m2.map_string_string().at(StrFunc(i + 10, 1)));
+    EXPECT_EQ(Func(i, 16), m2.map_int32_foreign_message().at(i + 10).c());
+    EXPECT_EQ(Func(i, 21), m2.map_int32_int32().at(i + 20));
+    EXPECT_EQ(Func(i, 22), m2.map_int32_double().at(i + 20));
+    EXPECT_EQ(StrFunc(i, 25), m2.map_string_string().at(StrFunc(i + 20, 1)));
+    EXPECT_EQ(Func(i, 26), m2.map_int32_foreign_message().at(i + 20).c());
+  }
+
+  // TODO(teboring): add test for duplicated key
+}
+
+// Generated Message Test ===========================================
+
+TEST(GeneratedMapFieldTest, Accessors) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  MapTestUtil::ModifyMapFields(&message);
+  MapTestUtil::ExpectMapFieldsModified(message);
+}
+
+TEST(GeneratedMapFieldTest, SetMapFieldsInitialized) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFieldsInitialized(&message);
+  MapTestUtil::ExpectMapFieldsSetInitialized(message);
+}
+
+TEST(GeneratedMapFieldTest, Proto2SetMapFieldsInitialized) {
+  unittest::TestEnumMap message;
+  EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO,
+            (*message.mutable_known_map_field())[0]);
+}
+
+TEST(GeneratedMapFieldTest, Clear) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  message.Clear();
+  MapTestUtil::ExpectClear(message);
+}
+
+TEST(GeneratedMapFieldTest, ClearMessageMap) {
+  unittest::TestMessageMap message;
+
+  // Creates a TestAllTypes with default value
+  TestUtil::ExpectClear((*message.mutable_map_int32_message())[0]);
+}
+
+TEST(GeneratedMapFieldTest, CopyFrom) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  message2.CopyFrom(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyFromMessageMap) {
+  unittest::TestMessageMap message1, message2;
+
+  (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+  (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+  message1.CopyFrom(message2);
+
+  // Checks repeated field is overwritten.
+  EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+  EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+}
+
+TEST(GeneratedMapFieldTest, SwapWithEmpty) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::ExpectMapFieldsSet(message1);
+  MapTestUtil::ExpectClear(message2);
+
+  message1.Swap(&message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+  MapTestUtil::ExpectClear(message1);
+}
+
+TEST(GeneratedMapFieldTest, SwapWithSelf) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  message.Swap(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(GeneratedMapFieldTest, SwapWithOther) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::SetMapFields(&message2);
+  MapTestUtil::ModifyMapFields(&message2);
+
+  message1.Swap(&message2);
+  MapTestUtil::ExpectMapFieldsModified(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyConstructor) {
+  unittest::TestMap message1;
+  MapTestUtil::SetMapFields(&message1);
+
+  unittest::TestMap message2(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyAssignmentOperator) {
+  unittest::TestMap message1;
+  MapTestUtil::SetMapFields(&message1);
+
+  unittest::TestMap message2;
+  message2 = message1;
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Make sure that self-assignment does something sane.
+  message2.operator=(message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
+        !defined(GOOGLE_PROTOBUF_NO_RTTI)
+TEST(GeneratedMapFieldTest, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+#endif
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) {
+  // Test copying from a DynamicMessage, which must fall back to using
+  // reflection.
+  unittest::TestMap message2;
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(message1.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+  message2.CopyFrom(*message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) {
+  unittest::TestMap message2;
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaMapReflection(message1.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+  message2.CopyFrom(*message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) {
+  // Test copying to a DynamicMessage, which must fall back to using reflection.
+  unittest::TestMap message2;
+  MapTestUtil::SetMapFields(&message2);
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  message1->MergeFrom(message2);
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+}
+
+TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) {
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  unittest::TestMap message2;
+  reflection_tester.SetMapFieldsViaMapReflection(&message2);
+
+  // Construct a dynamic message via the factory.
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message1;
+  message1.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
+  message1->MergeFrom(message2);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+}
+
+TEST(GeneratedMapFieldTest, SyncDynamicMapWithRepeatedField) {
+  // Construct a dynamic message via the factory.
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> message;
+  message.reset(
+      factory.GetPrototype(unittest::TestMap::descriptor())->New());
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) {
+  unittest::TestMap message1, message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  // This field will test merging into an empty spot.
+  (*message2.mutable_map_int32_int32())[1] = 1;
+  message1.mutable_map_int32_int32()->erase(1);
+
+  // This tests overwriting.
+  (*message2.mutable_map_int32_double())[1] = 1;
+  (*message1.mutable_map_int32_double())[1] = 2;
+
+  message1.MergeFrom(message2);
+  MapTestUtil::ExpectMapFieldsSet(message1);
+}
+
+TEST(GeneratedMapFieldTest, MergeFromMessageMap) {
+  unittest::TestMessageMap message1, message2;
+
+  (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+  (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+  message1.MergeFrom(message2);
+
+  // Checks repeated field is overwritten.
+  EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+  EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+}
+
+// Test the generated SerializeWithCachedSizesToArray()
+TEST(GeneratedMapFieldTest, SerializationToArray) {
+  unittest::TestMap message1, message2;
+  string data;
+  MapTestUtil::SetMapFields(&message1);
+  int size = message1.ByteSize();
+  data.resize(size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(size, end - start);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+// Test the generated SerializeWithCachedSizes()
+TEST(GeneratedMapFieldTest, SerializationToStream) {
+  unittest::TestMap message1, message2;
+  MapTestUtil::SetMapFields(&message1);
+  int size = message1.ByteSize();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+
+TEST(GeneratedMapFieldTest, SameTypeMaps) {
+  const Descriptor* map1 = unittest::TestSameTypeMap::descriptor()
+                               ->FindFieldByName("map1")
+                               ->message_type();
+  const Descriptor* map2 = unittest::TestSameTypeMap::descriptor()
+                               ->FindFieldByName("map2")
+                               ->message_type();
+
+  const Message* map1_entry =
+      MessageFactory::generated_factory()->GetPrototype(map1);
+  const Message* map2_entry =
+      MessageFactory::generated_factory()->GetPrototype(map2);
+
+  EXPECT_EQ(map1, map1_entry->GetDescriptor());
+  EXPECT_EQ(map2, map2_entry->GetDescriptor());
+}
+
+TEST(GeneratedMapFieldTest, Proto2UnknownEnum) {
+  unittest::TestEnumMapPlusExtra from;
+  (*from.mutable_known_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_FOO;
+  (*from.mutable_unknown_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_EXTRA;
+  string data;
+  from.SerializeToString(&data);
+
+  unittest::TestEnumMap to;
+  EXPECT_TRUE(to.ParseFromString(data));
+  EXPECT_EQ(0, to.unknown_map_field().size());
+  const UnknownFieldSet& unknown_field_set =
+      to.GetReflection()->GetUnknownFields(to);
+  EXPECT_EQ(1, unknown_field_set.field_count());
+  EXPECT_EQ(1, to.known_map_field().size());
+  EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO, to.known_map_field().at(0));
+
+  data.clear();
+  from.Clear();
+  to.SerializeToString(&data);
+  EXPECT_TRUE(from.ParseFromString(data));
+  EXPECT_EQ(0, from.GetReflection()->GetUnknownFields(from).field_count());
+  EXPECT_EQ(1, from.known_map_field().size());
+  EXPECT_EQ(unittest::E_PROTO2_MAP_ENUM_FOO, from.known_map_field().at(0));
+  EXPECT_EQ(1, from.unknown_map_field().size());
+  EXPECT_EQ(unittest::E_PROTO2_MAP_ENUM_EXTRA, from.unknown_map_field().at(0));
+}
+
+TEST(GeneratedMapFieldTest, StandardWireFormat) {
+  unittest::TestMap message;
+  string data = "\x0A\x04\x08\x01\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, UnorderedWireFormat) {
+  unittest::TestMap message;
+
+  // put value before key in wire format
+  string data = "\x0A\x04\x10\x01\x08\x02";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat) {
+  unittest::TestMap message;
+
+  // Two key fields in wire format
+  string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat) {
+  unittest::TestMap message;
+
+  // Two value fields in wire format
+  string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, MissedKeyWireFormat) {
+  unittest::TestMap message;
+
+  // No key field in wire format
+  string data = "\x0A\x02\x10\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int32_int32().at(0));
+}
+
+TEST(GeneratedMapFieldTest, MissedValueWireFormat) {
+  unittest::TestMap message;
+
+  // No value field in wire format
+  string data = "\x0A\x02\x08\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(0, message.map_int32_int32().at(1));
+}
+
+TEST(GeneratedMapFieldTest, MissedValueTextFormat) {
+  unittest::TestMap message;
+
+  // No value field in text format
+  string text =
+      "map_int32_foreign_message {\n"
+      "  key: 1234567890\n"
+      "}";
+
+  EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message));
+  EXPECT_EQ(1, message.map_int32_foreign_message().size());
+  EXPECT_EQ(11, message.ByteSize());
+}
+
+TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
+  unittest::TestMap message;
+
+  // Unknown field in wire format
+  string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+
+  EXPECT_TRUE(message.ParseFromString(data));
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(3, message.map_int32_int32().at(2));
+}
+
+TEST(GeneratedMapFieldTest, CorruptedWireFormat) {
+  unittest::TestMap message;
+
+  // corrupted data in wire format
+  string data = "\x0A\x06\x08\x02\x11\x03";
+
+  EXPECT_FALSE(message.ParseFromString(data));
+}
+
+TEST(GeneratedMapFieldTest, IsInitialized) {
+  unittest::TestRequiredMessageMap map_message;
+
+  // Add an uninitialized message.
+  (*map_message.mutable_map_field())[0];
+  EXPECT_FALSE(map_message.IsInitialized());
+
+  // Initialize uninitialized message
+  (*map_message.mutable_map_field())[0].set_a(0);
+  (*map_message.mutable_map_field())[0].set_b(0);
+  (*map_message.mutable_map_field())[0].set_c(0);
+  EXPECT_TRUE(map_message.IsInitialized());
+}
+
+// Generated Message Reflection Test ================================
+
+TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(&message);
+
+  EXPECT_LT(0, message.GetReflection()->SpaceUsed(message));
+}
+
+TEST(GeneratedMapFieldReflectionTest, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaReflection(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+  reflection_tester.ExpectMapFieldsSetViaReflection(message);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
+
+  reflection_tester.ModifyMapFieldsViaReflection(&message);
+  MapTestUtil::ExpectMapFieldsModified(message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, Swap) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message1);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  MapTestUtil::ExpectClear(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapWithBothSet) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message1);
+  MapTestUtil::SetMapFields(&message2);
+  MapTestUtil::ModifyMapFields(&message2);
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  MapTestUtil::ExpectMapFieldsModified(message1);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapFields) {
+  unittest::TestMap message1;
+  unittest::TestMap message2;
+
+  MapTestUtil::SetMapFields(&message2);
+
+  vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1.GetReflection();
+  reflection->ListFields(message2, &fields);
+  reflection->SwapFields(&message1, &message2, fields);
+
+  MapTestUtil::ExpectMapFieldsSet(message1);
+  MapTestUtil::ExpectClear(message2);
+}
+
+TEST(GeneratedMapFieldReflectionTest, ClearField) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.ClearMapFieldsViaReflection(&message);
+  reflection_tester.ExpectClearViaReflection(message);
+  reflection_tester.ExpectClearViaReflectionIterator(&message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapsSize(message, 2);
+  std::vector<const Message*> expected_entries =
+      MapTestUtil::GetMapEntries(message, 0);
+
+  reflection_tester.RemoveLastMapsViaReflection(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 1);
+  std::vector<const Message*> remained_entries =
+      MapTestUtil::GetMapEntries(message, 0);
+  EXPECT_TRUE(expected_entries == remained_entries);
+}
+
+TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
+  unittest::TestMap message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  MapReflectionTester reflection_tester(descriptor);
+
+  MapTestUtil::SetMapFields(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 2);
+
+  reflection_tester.ReleaseLastMapsViaReflection(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 1);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  MapTestUtil::SetMapFields(&message);
+
+  MapTestUtil::ExpectMapsSize(message, 2);
+  std::vector<const Message*> expect_last =
+      MapTestUtil::GetMapEntries(message, 1);
+  std::vector<const Message*> release_last =
+      MapTestUtil::GetMapEntriesFromRelease(&message);
+  MapTestUtil::ExpectMapsSize(message, 1);
+  EXPECT_TRUE(expect_last == release_last);
+  for (std::vector<const Message*>::iterator it = release_last.begin();
+       it != release_last.end(); ++it) {
+    delete *it;
+  }
+}
+
+TEST(GeneratedMapFieldReflectionTest, SwapElements) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+
+  MapTestUtil::SetMapFields(&message);
+
+  // Get pointers of map entries at their original position
+  std::vector<const Message*> entries0 = MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1 = MapTestUtil::GetMapEntries(message, 1);
+
+  // Swap the first time.
+  reflection_tester.SwapMapsViaReflection(&message);
+
+  // Get pointer of map entry after swap once.
+  std::vector<const Message*> entries0_once =
+      MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1_once =
+      MapTestUtil::GetMapEntries(message, 1);
+
+  // Test map entries are swapped.
+  MapTestUtil::ExpectMapsSize(message, 2);
+  EXPECT_TRUE(entries0 == entries1_once);
+  EXPECT_TRUE(entries1 == entries0_once);
+
+  // Swap the second time.
+  reflection_tester.SwapMapsViaReflection(&message);
+
+  // Get pointer of map entry after swap once.
+  std::vector<const Message*> entries0_twice =
+      MapTestUtil::GetMapEntries(message, 0);
+  std::vector<const Message*> entries1_twice =
+      MapTestUtil::GetMapEntries(message, 1);
+
+  // Test map entries are swapped back.
+  MapTestUtil::ExpectMapsSize(message, 2);
+  EXPECT_TRUE(entries0 == entries0_twice);
+  EXPECT_TRUE(entries1 == entries1_twice);
+}
+
+TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, EmbedProto2Message) {
+  unittest::TestMessageMap message;
+
+  const FieldDescriptor* map_field =
+      unittest::TestMessageMap::descriptor()->FindFieldByName(
+          "map_int32_message");
+  const FieldDescriptor* value =
+      map_field->message_type()->FindFieldByName("value");
+
+  Message* entry_message =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_EQ(
+      &entry_message->GetReflection()->GetMessage(*entry_message, value),
+      reinterpret_cast<const Message*>(&TestAllTypes::default_instance()));
+
+  Message* proto2_message =
+      entry_message->GetReflection()->MutableMessage(entry_message, value);
+  EXPECT_EQ(unittest::TestAllTypes::descriptor(),
+            proto2_message->GetDescriptor());
+  ASSERT_EQ(1, message.map_int32_message().size());
+}
+
+TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) {
+  unittest::TestMap message;
+  const FieldDescriptor* map_field =
+      unittest::TestMap::descriptor()->FindFieldByName("map_int32_int32");
+  const FieldDescriptor* key =
+      map_field->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value =
+      map_field->message_type()->FindFieldByName("value");
+
+  Message* entry_message1 =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_FALSE(entry_message1->GetReflection()->HasField(*entry_message1, key));
+  EXPECT_FALSE(
+      entry_message1->GetReflection()->HasField(*entry_message1, value));
+
+  Message* entry_message2 =
+      message.GetReflection()->AddMessage(&message, map_field);
+  EXPECT_FALSE(entry_message2->GetReflection()->HasField(*entry_message2, key));
+  EXPECT_FALSE(
+      entry_message2->GetReflection()->HasField(*entry_message2, value));
+
+  entry_message1->MergeFrom(*entry_message2);
+  EXPECT_FALSE(entry_message1->GetReflection()->HasField(*entry_message1, key));
+  EXPECT_FALSE(
+      entry_message1->GetReflection()->HasField(*entry_message1, value));
+}
+
+TEST(GeneratedMapFieldReflectionTest, MapEntryClear) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+    unittest::TestMap::descriptor());
+  reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
+}
+
+TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) {
+  unittest::TestEnumMap message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  const FieldDescriptor* field_descriptor =
+      descriptor->FindFieldByName("known_map_field");
+  const FieldDescriptor* value_descriptor =
+      field_descriptor->message_type()->FindFieldByName("value");
+  Message* sub_message =
+      message.GetReflection()->AddMessage(&message, field_descriptor);
+  EXPECT_EQ(0, sub_message->GetReflection()->GetEnumValue(*sub_message,
+                                                          value_descriptor));
+}
+
+// Map Reflection API Test =========================================
+
+TEST(GeneratedMapFieldReflectionTest, SetViaMapReflection) {
+  unittest::TestMap message;
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaMapReflection(&message);
+  reflection_tester.ExpectMapFieldsSetViaReflection(message);
+  reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
+}
+
+// Dynamic Message Test =============================================
+
+class MapFieldInDynamicMessageTest : public testing::Test {
+ protected:
+  const DescriptorPool* pool_;
+  DynamicMessageFactory factory_;
+  const Descriptor* map_descriptor_;
+  const Descriptor* recursive_map_descriptor_;
+  const Message* map_prototype_;
+
+  MapFieldInDynamicMessageTest()
+      : pool_(DescriptorPool::generated_pool()), factory_(pool_) {}
+
+  virtual void SetUp() {
+    map_descriptor_ =
+      pool_->FindMessageTypeByName("protobuf_unittest.TestMap");
+    recursive_map_descriptor_ =
+        pool_->FindMessageTypeByName("protobuf_unittest.TestRecursiveMapMessage");
+    ASSERT_TRUE(map_descriptor_ != NULL);
+    ASSERT_TRUE(recursive_map_descriptor_ != NULL);
+    map_prototype_ = factory_.GetPrototype(map_descriptor_);
+  }
+};
+
+TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
+  // Check that all fields have independent offsets by setting each
+  // one to a unique value then checking that they all still have those
+  // unique values (i.e. they don't stomp each other).
+  google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
+  MapReflectionTester reflection_tester(map_descriptor_);
+
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
+TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) {
+  // Check that map fields work properly.
+  google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
+
+  // Check set functions.
+  MapReflectionTester reflection_tester(map_descriptor_);
+  reflection_tester.SetMapFieldsViaMapReflection(message.get());
+  reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
+TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
+  // Test that SpaceUsed() works properly
+
+  // Since we share the implementation with generated messages, we don't need
+  // to test very much here.  Just make sure it appears to be working.
+
+  google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
+  MapReflectionTester reflection_tester(map_descriptor_);
+
+  int initial_space_used = message->SpaceUsed();
+
+  reflection_tester.SetMapFieldsViaReflection(message.get());
+  EXPECT_LT(initial_space_used, message->SpaceUsed());
+}
+
+TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) {
+  TestRecursiveMapMessage from;
+  (*from.mutable_a())[""];
+  string data = from.SerializeAsString();
+  google::protobuf::scoped_ptr<Message> to(
+      factory_.GetPrototype(recursive_map_descriptor_)->New());
+  ASSERT_TRUE(to->ParseFromString(data));
+}
+
+// ReflectionOps Test ===============================================
+
+TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MapCopy) {
+  unittest::TestMap message, message2;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Copy(message, &message2);
+
+  MapTestUtil::ExpectMapFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  ReflectionOps::Copy(message2, &message2);
+  MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MergeMap) {
+  // Note:  Copy is implemented in terms of Merge() so technically the Copy
+  //   test already tested most of this.
+
+  unittest::TestMap message, message2;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Merge(message2, &message);
+
+  MapTestUtil::ExpectMapFieldsSet(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, ClearMap) {
+  unittest::TestMap message;
+
+  MapTestUtil::SetMapFields(&message);
+
+  ReflectionOps::Clear(&message);
+
+  MapTestUtil::ExpectClear(message);
+}
+
+TEST(ReflectionOpsForMapFieldTest, MapDiscardUnknownFields) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+
+  // Set some unknown fields in message.
+  message.GetReflection()->MutableUnknownFields(&message)->
+      AddVarint(123456, 654321);
+
+  // Discard them.
+  ReflectionOps::DiscardUnknownFields(&message);
+  MapTestUtil::ExpectMapFieldsSet(message);
+
+  EXPECT_EQ(0, message.GetReflection()->
+      GetUnknownFields(message).field_count());
+}
+
+// Wire Format Test =================================================
+
+TEST(WireFormatForMapFieldTest, ParseMap) {
+  unittest::TestMap source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  MapTestUtil::SetMapFields(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  MapTestUtil::ExpectMapFieldsSet(dest);
+}
+
+TEST(WireFormatForMapFieldTest, MapByteSize) {
+  unittest::TestMap message;
+  MapTestUtil::SetMapFields(&message);
+
+  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatForMapFieldTest, SerializeMap) {
+  unittest::TestMap message;
+  string generated_data;
+  string dynamic_data;
+
+  MapTestUtil::SetMapFields(&message);
+
+  // Serialize using the generated code.
+  {
+    message.ByteSize();
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    int size = WireFormat::ByteSize(message);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+}
+
+TEST(WireFormatForMapFieldTest, MapParseHelpers) {
+  string data;
+
+  {
+    // Set up.
+    protobuf_unittest::TestMap message;
+    MapTestUtil::SetMapFields(&message);
+    message.SerializeToString(&data);
+  }
+
+  {
+    // Test ParseFromString.
+    protobuf_unittest::TestMap message;
+    EXPECT_TRUE(message.ParseFromString(data));
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromIstream.
+    protobuf_unittest::TestMap message;
+    stringstream stream(data);
+    EXPECT_TRUE(message.ParseFromIstream(&stream));
+    EXPECT_TRUE(stream.eof());
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromBoundedZeroCopyStream.
+    string data_with_junk(data);
+    data_with_junk.append("some junk on the end");
+    io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size());
+    protobuf_unittest::TestMap message;
+    EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size()));
+    MapTestUtil::ExpectMapFieldsSet(message);
+  }
+
+  {
+    // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if
+    // EOF is reached before the expected number of bytes.
+    io::ArrayInputStream stream(data.data(), data.size());
+    protobuf_unittest::TestAllTypes message;
+    EXPECT_FALSE(
+      message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1));
+  }
+}
+
+// Text Format Test =================================================
+
+TEST(TextFormatMapTest, SerializeAndParse) {
+  unittest::TestMap source;
+  unittest::TestMap dest;
+  MapTestUtil::SetMapFields(&source);
+  string output;
+
+  // Test compact ASCII
+  TextFormat::Printer printer;
+  printer.PrintToString(source, &output);
+  TextFormat::Parser parser;
+  EXPECT_TRUE(parser.ParseFromString(output, &dest));
+  MapTestUtil::ExpectMapFieldsSet(dest);
+}
+
+TEST(TextFormatMapTest, Sorted) {
+  unittest::TestMap message;
+  MapReflectionTester tester(message.GetDescriptor());
+  tester.SetMapFieldsViaReflection(&message);
+
+  string expected_text;
+  GOOGLE_CHECK_OK(File::GetContents(
+      TestSourceDir() +
+          "/google/protobuf/"
+          "testdata/map_test_data.txt",
+      &expected_text, true));
+
+  EXPECT_EQ(message.DebugString(), expected_text);
+
+  // Test again on the reverse order.
+  unittest::TestMap message2;
+  tester.SetMapFieldsViaReflection(&message2);
+  tester.SwapMapsViaReflection(&message2);
+  EXPECT_EQ(message2.DebugString(), expected_text);
+}
+
+
+// arena support =================================================
+TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
+  // Allocate a large initial block to avoid mallocs during hooked test.
+  std::vector<char> arena_block(128 * 1024);
+  ArenaOptions options;
+  options.initial_block = &arena_block[0];
+  options.initial_block_size = arena_block.size();
+  Arena arena(options);
+  string data;
+  data.reserve(128 * 1024);
+
+  {
+    // TODO(teboring): Enable no heap check when ArenaStringPtr is used in map.
+    // NoHeapChecker no_heap;
+
+    unittest::TestArenaMap* from =
+        Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+    MapTestUtil::SetArenaMapFields(from);
+    from->SerializeToString(&data);
+
+    unittest::TestArenaMap* to =
+        Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+    to->ParseFromString(data);
+    MapTestUtil::ExpectArenaMapFieldsSet(*to);
+  }
+}
+
+// Use text format parsing and serializing to test reflection api.
+TEST(ArenaTest, RelfectionInTextFormat) {
+  Arena arena;
+  string data;
+
+  TextFormat::Printer printer;
+  TextFormat::Parser parser;
+
+  unittest::TestArenaMap* from =
+      Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+  unittest::TestArenaMap* to =
+      Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+
+  MapTestUtil::SetArenaMapFields(from);
+  printer.PrintToString(*from, &data);
+
+  EXPECT_TRUE(parser.ParseFromString(data, to));
+  MapTestUtil::ExpectArenaMapFieldsSet(*to);
+}
+
+// Make sure the memory allocated for string in map is deallocated.
+TEST(ArenaTest, StringMapNoLeak) {
+  Arena arena;
+  unittest::TestArenaMap* message =
+      Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+  string data;
+  // String with length less than 16 will not be allocated from heap.
+  int original_capacity = data.capacity();
+  while (data.capacity() <= original_capacity) {
+    data.append("a");
+  }
+  (*message->mutable_map_string_string())[data] = data;
+  // We rely on heap checkers to detect memory leak for us.
+  ASSERT_FALSE(message == NULL);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_test_util.cc b/src/third_party/protobuf-3/src/google/protobuf/map_test_util.cc
new file mode 100644
index 0000000..ae09464
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_test_util.cc
@@ -0,0 +1,1801 @@
+// 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.
+
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/map_test_util_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+
+void MapTestUtil::SetMapFields(unittest::TestMap* message) {
+  MapTestUtilImpl::SetMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                unittest::MAP_ENUM_BAZ>(message);
+}
+
+void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) {
+  MapTestUtilImpl::SetArenaMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                     unittest::MAP_ENUM_BAZ>(message);
+}
+
+void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) {
+  MapTestUtilImpl::SetMapFieldsInitialized(message);
+}
+
+void MapTestUtil::ModifyMapFields(unittest::TestMap* message) {
+  MapTestUtilImpl::ModifyMapFields<unittest::MapEnum, unittest::MAP_ENUM_FOO>(
+      message);
+}
+
+void MapTestUtil::ExpectClear(const unittest::TestMap& message) {
+  MapTestUtilImpl::ExpectClear(message);
+}
+
+void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) {
+  MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+                                      unittest::MAP_ENUM_BAZ>(message);
+}
+
+void MapTestUtil::ExpectArenaMapFieldsSet(
+    const unittest::TestArenaMap& message) {
+  MapTestUtilImpl::ExpectArenaMapFieldsSet<
+      unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>(
+      message);
+}
+
+void MapTestUtil::ExpectMapFieldsSetInitialized(
+    const unittest::TestMap& message) {
+  MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnum,
+                                                 unittest::MAP_ENUM_FOO>(
+      message);
+}
+
+void MapTestUtil::ExpectMapFieldsModified(
+    const unittest::TestMap& message) {
+  MapTestUtilImpl::ExpectMapFieldsModified<
+      unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>(
+      message);
+}
+
+void MapTestUtil::ExpectMapsSize(
+    const unittest::TestMap& message, int size) {
+  const Descriptor* descriptor = message.GetDescriptor();
+
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_int32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int64_int64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_uint32_uint32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_uint64_uint64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sint32_sint32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sint64_sint64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_float")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_double")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_bool_bool")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_string_string")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_bytes")));
+  EXPECT_EQ(size, message.GetReflection()->FieldSize(
+    message, descriptor->FindFieldByName("map_int32_foreign_message")));
+}
+
+std::vector<const Message*> MapTestUtil::GetMapEntries(
+    const unittest::TestMap& message, int index) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  std::vector<const Message*> result;
+
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_int32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int64_int64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_uint32_uint32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_uint64_uint64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sint32_sint32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sint64_sint64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_float"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_double"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_bool_bool"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_string_string"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_bytes"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_enum"), index));
+  result.push_back(&message.GetReflection()->GetRepeatedMessage(
+    message, descriptor->FindFieldByName("map_int32_foreign_message"), index));
+
+  return result;
+}
+
+std::vector<const Message*> MapTestUtil::GetMapEntriesFromRelease(
+    unittest::TestMap* message) {
+  const Descriptor* descriptor = message->GetDescriptor();
+  std::vector<const Message*> result;
+
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_int32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int64_int64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_uint32_uint32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_uint64_uint64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sint32_sint32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sint64_sint64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_fixed32_fixed32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_fixed64_fixed64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sfixed32_sfixed32")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_sfixed64_sfixed64")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_float")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_double")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_bool_bool")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_string_string")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_bytes")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_enum")));
+  result.push_back(message->GetReflection()->ReleaseLast(
+    message, descriptor->FindFieldByName("map_int32_foreign_message")));
+
+  return result;
+}
+
+MapReflectionTester::MapReflectionTester(
+    const Descriptor* base_descriptor)
+  : base_descriptor_(base_descriptor) {
+  const DescriptorPool* pool = base_descriptor->file()->pool();
+
+  map_enum_foo_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_FOO");
+  map_enum_bar_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAR");
+  map_enum_baz_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAZ");
+
+  foreign_c_ = pool->FindFieldByName(
+      "protobuf_unittest.ForeignMessage.c");
+  map_int32_int32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32Int32Entry.key");
+  map_int32_int32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32Int32Entry.value");
+  map_int64_int64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt64Int64Entry.key");
+  map_int64_int64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt64Int64Entry.value");
+  map_uint32_uint32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint32Uint32Entry.key");
+  map_uint32_uint32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint32Uint32Entry.value");
+  map_uint64_uint64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint64Uint64Entry.key");
+  map_uint64_uint64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapUint64Uint64Entry.value");
+  map_sint32_sint32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint32Sint32Entry.key");
+  map_sint32_sint32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint32Sint32Entry.value");
+  map_sint64_sint64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint64Sint64Entry.key");
+  map_sint64_sint64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSint64Sint64Entry.value");
+  map_fixed32_fixed32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.key");
+  map_fixed32_fixed32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.value");
+  map_fixed64_fixed64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.key");
+  map_fixed64_fixed64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.value");
+  map_sfixed32_sfixed32_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.key");
+  map_sfixed32_sfixed32_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.value");
+  map_sfixed64_sfixed64_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.key");
+  map_sfixed64_sfixed64_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.value");
+  map_int32_float_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32FloatEntry.key");
+  map_int32_float_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32FloatEntry.value");
+  map_int32_double_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32DoubleEntry.key");
+  map_int32_double_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32DoubleEntry.value");
+  map_bool_bool_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapBoolBoolEntry.key");
+  map_bool_bool_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapBoolBoolEntry.value");
+  map_string_string_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapStringStringEntry.key");
+  map_string_string_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapStringStringEntry.value");
+  map_int32_bytes_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32BytesEntry.key");
+  map_int32_bytes_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32BytesEntry.value");
+  map_int32_enum_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32EnumEntry.key");
+  map_int32_enum_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32EnumEntry.value");
+  map_int32_foreign_message_key_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.key");
+  map_int32_foreign_message_val_ = pool->FindFieldByName(
+      "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.value");
+
+  EXPECT_FALSE(map_enum_foo_ == NULL);
+  EXPECT_FALSE(map_enum_bar_ == NULL);
+  EXPECT_FALSE(map_enum_baz_ == NULL);
+  EXPECT_FALSE(map_int32_int32_key_ == NULL);
+  EXPECT_FALSE(map_int32_int32_val_ == NULL);
+  EXPECT_FALSE(map_int64_int64_key_ == NULL);
+  EXPECT_FALSE(map_int64_int64_val_ == NULL);
+  EXPECT_FALSE(map_uint32_uint32_key_ == NULL);
+  EXPECT_FALSE(map_uint32_uint32_val_ == NULL);
+  EXPECT_FALSE(map_uint64_uint64_key_ == NULL);
+  EXPECT_FALSE(map_uint64_uint64_val_ == NULL);
+  EXPECT_FALSE(map_sint32_sint32_key_ == NULL);
+  EXPECT_FALSE(map_sint32_sint32_val_ == NULL);
+  EXPECT_FALSE(map_sint64_sint64_key_ == NULL);
+  EXPECT_FALSE(map_sint64_sint64_val_ == NULL);
+  EXPECT_FALSE(map_fixed32_fixed32_key_ == NULL);
+  EXPECT_FALSE(map_fixed32_fixed32_val_ == NULL);
+  EXPECT_FALSE(map_fixed64_fixed64_key_ == NULL);
+  EXPECT_FALSE(map_fixed64_fixed64_val_ == NULL);
+  EXPECT_FALSE(map_sfixed32_sfixed32_key_ == NULL);
+  EXPECT_FALSE(map_sfixed32_sfixed32_val_ == NULL);
+  EXPECT_FALSE(map_sfixed64_sfixed64_key_ == NULL);
+  EXPECT_FALSE(map_sfixed64_sfixed64_val_ == NULL);
+  EXPECT_FALSE(map_int32_float_key_ == NULL);
+  EXPECT_FALSE(map_int32_float_val_ == NULL);
+  EXPECT_FALSE(map_int32_double_key_ == NULL);
+  EXPECT_FALSE(map_int32_double_val_ == NULL);
+  EXPECT_FALSE(map_bool_bool_key_ == NULL);
+  EXPECT_FALSE(map_bool_bool_val_ == NULL);
+  EXPECT_FALSE(map_string_string_key_ == NULL);
+  EXPECT_FALSE(map_string_string_val_ == NULL);
+  EXPECT_FALSE(map_int32_bytes_key_ == NULL);
+  EXPECT_FALSE(map_int32_bytes_val_ == NULL);
+  EXPECT_FALSE(map_int32_enum_key_ == NULL);
+  EXPECT_FALSE(map_int32_enum_val_ == NULL);
+  EXPECT_FALSE(map_int32_foreign_message_key_ == NULL);
+  EXPECT_FALSE(map_int32_foreign_message_val_ == NULL);
+}
+
+// Shorthand to get a FieldDescriptor for a field of unittest::TestMap.
+const FieldDescriptor* MapReflectionTester::F(const string& name) {
+  const FieldDescriptor* result = NULL;
+  result = base_descriptor_->FindFieldByName(name);
+  GOOGLE_CHECK(result != NULL);
+  return result;
+}
+
+void MapReflectionTester::SetMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message = NULL;
+  Message* sub_foreign_message = NULL;
+
+  // Add first element.
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 0);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 0);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_float_key_, 0);
+  sub_message->GetReflection()
+      ->SetFloat(sub_message, map_int32_float_val_, 0.0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_double_key_, 0);
+  sub_message->GetReflection()
+      ->SetDouble(sub_message, map_int32_double_val_, 0.0);
+
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_key_, false);
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_val_, false);
+
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_key_, "0");
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_val_, "0");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_bytes_key_, 0);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_int32_bytes_val_, "0");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_enum_key_, 0);
+  sub_message->GetReflection()
+      ->SetEnum(sub_message, map_int32_enum_val_, map_enum_bar_);
+
+  sub_message = reflection
+      ->AddMessage(message, F("map_int32_foreign_message"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_foreign_message_key_, 0);
+  sub_foreign_message = sub_message->GetReflection()->
+      MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
+  sub_foreign_message->GetReflection()->
+      SetInt32(sub_foreign_message, foreign_c_, 0);
+
+  // Add second element
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_int32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_int64_int64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_uint32_uint32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_uint64_uint64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sint32_sint32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sint64_sint64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 1);
+  sub_message->GetReflection()
+      ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 1);
+  sub_message->GetReflection()
+      ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 1);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_float_key_, 1);
+  sub_message->GetReflection()
+      ->SetFloat(sub_message, map_int32_float_val_, 1.0);
+
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_double_key_, 1);
+  sub_message->GetReflection()
+      ->SetDouble(sub_message, map_int32_double_val_, 1.0);
+
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_key_, true);
+  sub_message->GetReflection()
+      ->SetBool(sub_message, map_bool_bool_val_, true);
+
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_key_, "1");
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_string_string_val_, "1");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_bytes_key_, 1);
+  sub_message->GetReflection()
+      ->SetString(sub_message, map_int32_bytes_val_, "1");
+
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_enum_key_, 1);
+  sub_message->GetReflection()
+      ->SetEnum(sub_message, map_int32_enum_val_, map_enum_baz_);
+
+  sub_message = reflection
+      ->AddMessage(message, F("map_int32_foreign_message"));
+  sub_message->GetReflection()
+      ->SetInt32(sub_message, map_int32_foreign_message_key_, 1);
+  sub_foreign_message = sub_message->GetReflection()->
+      MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
+  sub_foreign_message->GetReflection()->
+      SetInt32(sub_foreign_message, foreign_c_, 1);
+}
+
+void MapReflectionTester::SetMapFieldsViaMapReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  Message* sub_foreign_message = NULL;
+  MapValueRef map_val;
+
+  // Add first element.
+  MapKey map_key;
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_int32"), map_key, &map_val));
+  map_val.SetInt32Value(0);
+
+  map_key.SetInt64Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int64_int64"), map_key, &map_val));
+  map_val.SetInt64Value(0);
+
+  map_key.SetUInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_uint32_uint32"), map_key, &map_val));
+  map_val.SetUInt32Value(0);
+
+  map_key.SetUInt64Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_uint64_uint64"), map_key, &map_val));
+  map_val.SetUInt64Value(0);
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_sint32_sint32"), map_key, &map_val));
+  map_val.SetInt32Value(0);
+
+  map_key.SetInt64Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_sint64_sint64"), map_key, &map_val));
+  map_val.SetInt64Value(0);
+
+  map_key.SetUInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_fixed32_fixed32"), map_key, &map_val));
+  map_val.SetUInt32Value(0);
+
+  map_key.SetUInt64Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_fixed64_fixed64"), map_key, &map_val));
+  map_val.SetUInt64Value(0);
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed32_sfixed32"), map_key, &map_val));
+  map_val.SetInt32Value(0);
+
+  map_key.SetInt64Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed64_sfixed64"), map_key, &map_val));
+  map_val.SetInt64Value(0);
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_float"), map_key, &map_val));
+  map_val.SetFloatValue(0.0);
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_double"), map_key, &map_val));
+  map_val.SetDoubleValue(0.0);
+
+  map_key.SetBoolValue(false);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_bool_bool"), map_key, &map_val));
+  map_val.SetBoolValue(false);
+
+  map_key.SetStringValue("0");
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_string_string"), map_key, &map_val));
+  map_val.SetStringValue("0");
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_bytes"), map_key, &map_val));
+  map_val.SetStringValue("0");
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_enum"), map_key, &map_val));
+  map_val.SetEnumValue(map_enum_bar_->number());
+
+  map_key.SetInt32Value(0);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_foreign_message"), map_key, &map_val));
+  sub_foreign_message = map_val.MutableMessageValue();
+  sub_foreign_message->GetReflection()->SetInt32(
+      sub_foreign_message, foreign_c_, 0);
+
+  // Add second element
+  map_key.SetInt32Value(1);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_int32"), map_key, &map_val));
+  map_val.SetInt32Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_int32"), map_key, &map_val));
+
+  map_key.SetInt64Value(1);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int64_int64"), map_key, &map_val));
+  map_val.SetInt64Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_int64_int64"), map_key, &map_val));
+
+  map_key.SetUInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_uint32_uint32"), map_key, &map_val);
+  map_val.SetUInt32Value(1);
+
+  map_key.SetUInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_uint64_uint64"), map_key, &map_val);
+  map_val.SetUInt64Value(1);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sint32_sint32"), map_key, &map_val);
+  map_val.SetInt32Value(1);
+
+  map_key.SetInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sint64_sint64"), map_key, &map_val);
+  map_val.SetInt64Value(1);
+
+  map_key.SetUInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_fixed32_fixed32"), map_key, &map_val);
+  map_val.SetUInt32Value(1);
+
+  map_key.SetUInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_fixed64_fixed64"), map_key, &map_val);
+  map_val.SetUInt64Value(1);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+  map_val.SetInt32Value(1);
+
+  map_key.SetInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+  map_val.SetInt64Value(1);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_float"), map_key, &map_val);
+  map_val.SetFloatValue(1.0);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_double"), map_key, &map_val);
+  map_val.SetDoubleValue(1.0);
+
+  map_key.SetBoolValue(true);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_bool_bool"), map_key, &map_val);
+  map_val.SetBoolValue(true);
+
+  map_key.SetStringValue("1");
+  reflection->InsertOrLookupMapValue(
+      message, F("map_string_string"), map_key, &map_val);
+  map_val.SetStringValue("1");
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_bytes"), map_key, &map_val);
+  map_val.SetStringValue("1");
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_enum"), map_key, &map_val);
+  map_val.SetEnumValue(map_enum_baz_->number());
+
+  map_key.SetInt32Value(1);
+  EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_foreign_message"), map_key, &map_val));
+  sub_foreign_message = map_val.MutableMessageValue();
+  sub_foreign_message->GetReflection()->SetInt32(
+      sub_foreign_message, foreign_c_, 1);
+}
+
+void MapReflectionTester::ClearMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  reflection->ClearField(message, F("map_int32_int32"));
+  reflection->ClearField(message, F("map_int64_int64"));
+  reflection->ClearField(message, F("map_uint32_uint32"));
+  reflection->ClearField(message, F("map_uint64_uint64"));
+  reflection->ClearField(message, F("map_sint32_sint32"));
+  reflection->ClearField(message, F("map_sint64_sint64"));
+  reflection->ClearField(message, F("map_fixed32_fixed32"));
+  reflection->ClearField(message, F("map_fixed64_fixed64"));
+  reflection->ClearField(message, F("map_sfixed32_sfixed32"));
+  reflection->ClearField(message, F("map_sfixed64_sfixed64"));
+  reflection->ClearField(message, F("map_int32_float"));
+  reflection->ClearField(message, F("map_int32_double"));
+  reflection->ClearField(message, F("map_bool_bool"));
+  reflection->ClearField(message, F("map_string_string"));
+  reflection->ClearField(message, F("map_int32_bytes"));
+  reflection->ClearField(message, F("map_int32_enum"));
+  reflection->ClearField(message, F("map_int32_foreign_message"));
+}
+
+void MapReflectionTester::ModifyMapFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  MapValueRef map_val;
+  Message* sub_foreign_message;
+
+  // Modify the second element
+  MapKey map_key;
+  map_key.SetInt32Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_int32"), map_key, &map_val));
+  map_val.SetInt32Value(2);
+
+  map_key.SetInt64Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_int64_int64"), map_key, &map_val));
+  map_val.SetInt64Value(2);
+
+  map_key.SetUInt32Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_uint32_uint32"), map_key, &map_val));
+  map_val.SetUInt32Value(2);
+
+  map_key.SetUInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_uint64_uint64"), map_key, &map_val);
+  map_val.SetUInt64Value(2);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sint32_sint32"), map_key, &map_val);
+  map_val.SetInt32Value(2);
+
+  map_key.SetInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sint64_sint64"), map_key, &map_val);
+  map_val.SetInt64Value(2);
+
+  map_key.SetUInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_fixed32_fixed32"), map_key, &map_val);
+  map_val.SetUInt32Value(2);
+
+  map_key.SetUInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_fixed64_fixed64"), map_key, &map_val);
+  map_val.SetUInt64Value(2);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+  map_val.SetInt32Value(2);
+
+  map_key.SetInt64Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+  map_val.SetInt64Value(2);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_float"), map_key, &map_val);
+  map_val.SetFloatValue(2.0);
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_double"), map_key, &map_val);
+  map_val.SetDoubleValue(2.0);
+
+  map_key.SetBoolValue(true);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_bool_bool"), map_key, &map_val);
+  map_val.SetBoolValue(false);
+
+  map_key.SetStringValue("1");
+  reflection->InsertOrLookupMapValue(
+      message, F("map_string_string"), map_key, &map_val);
+  map_val.SetStringValue("2");
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_bytes"), map_key, &map_val);
+  map_val.SetStringValue("2");
+
+  map_key.SetInt32Value(1);
+  reflection->InsertOrLookupMapValue(
+      message, F("map_int32_enum"), map_key, &map_val);
+  map_val.SetEnumValue(map_enum_foo_->number());
+
+  map_key.SetInt32Value(1);
+  EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+      message, F("map_int32_foreign_message"), map_key, &map_val));
+  sub_foreign_message = map_val.MutableMessageValue();
+  sub_foreign_message->GetReflection()->SetInt32(
+      sub_foreign_message, foreign_c_, 2);
+}
+
+void MapReflectionTester::RemoveLastMapsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    reflection->RemoveLast(message, field);
+  }
+}
+
+void MapReflectionTester::ReleaseLastMapsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    Message* released = reflection->ReleaseLast(message, field);
+    ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: "
+                                  << field->name();
+    delete released;
+  }
+}
+
+void MapReflectionTester::SwapMapsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i = 0; i < output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    reflection->SwapElements(message, field, 0, 1);
+  }
+}
+
+void MapReflectionTester::
+    MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message = NULL;
+
+  sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_float"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_double"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_string_string"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+  sub_message = reflection->AddMessage(message, F("map_int32_foreign_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) !=
+              NULL);
+}
+
+void MapReflectionTester::ExpectMapFieldsSetViaReflection(
+    const Message& message) {
+  string scratch;
+  const Reflection* reflection = message.GetReflection();
+  const Message* sub_message;
+  MapKey map_key;
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_int32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int64_int64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint32_uint32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint64_uint64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint32_sint32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint64_sint64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed32_fixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed64_fixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed32_sfixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed64_sfixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_float")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_double")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_bool_bool")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_string_string")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_bytes")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_enum")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message")));
+
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      // Check with RepeatedField Reflection
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_int32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_int32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_int32_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_TRUE(reflection->ContainsMapKey(
+          message, F("map_int32_int32"), map_key));
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      // Check with RepeatedField Reflection
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int64_int64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_int64_int64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_int64_int64_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt64Value(key);
+      EXPECT_TRUE(reflection->ContainsMapKey(
+          message, F("map_int64_int64"), map_key));
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      // Check with RepeatedField Reflection
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i);
+      uint32 key = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_uint32_uint32_key_);
+      uint32 val = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_uint32_uint32_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetUInt32Value(key);
+      EXPECT_TRUE(reflection->ContainsMapKey(
+          message, F("map_uint32_uint32"), map_key));
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_uint64_uint64"), i);
+      uint64 key = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_uint64_uint64_key_);
+      uint64 val = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_uint64_uint64_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetUInt64Value(key);
+      EXPECT_TRUE(reflection->ContainsMapKey(
+          message, F("map_uint64_uint64"), map_key));
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_sint32_sint32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sint32_sint32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sint32_sint32_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_sint32_sint32"), map_key));
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_sint64_sint64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sint64_sint64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sint64_sint64_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt64Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_sint64_sint64"), map_key));
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_fixed32_fixed32"), i);
+      uint32 key = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_fixed32_fixed32_key_);
+      uint32 val = sub_message->GetReflection()->GetUInt32(
+          *sub_message, map_fixed32_fixed32_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetUInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_fixed32_fixed32"), map_key));
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_fixed64_fixed64"), i);
+      uint64 key = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_fixed64_fixed64_key_);
+      uint64 val = sub_message->GetReflection()->GetUInt64(
+          *sub_message, map_fixed64_fixed64_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetUInt64Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_fixed64_fixed64"), map_key));
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_sfixed32_sfixed32"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sfixed32_sfixed32_key_);
+      int32 val = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_sfixed32_sfixed32_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_sfixed32_sfixed32"), map_key));
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_sfixed64_sfixed64"), i);
+      int64 key = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sfixed64_sfixed64_key_);
+      int64 val = sub_message->GetReflection()->GetInt64(
+          *sub_message, map_sfixed64_sfixed64_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt64Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_sfixed64_sfixed64"), map_key));
+    }
+  }
+  {
+    std::map<int32, float> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_float"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_float_key_);
+      float val = sub_message->GetReflection()->GetFloat(
+          *sub_message, map_int32_float_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_int32_float"), map_key));
+    }
+  }
+  {
+    std::map<int32, double> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_double"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_double_key_);
+      double val = sub_message->GetReflection()->GetDouble(
+          *sub_message, map_int32_double_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_int32_double"), map_key));
+    }
+  }
+  {
+    std::map<bool, bool> map;
+    map[false] = false;
+    map[true] = true;
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_bool_bool"), i);
+      bool key = sub_message->GetReflection()->GetBool(
+          *sub_message, map_bool_bool_key_);
+      bool val = sub_message->GetReflection()->GetBool(
+          *sub_message, map_bool_bool_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetBoolValue(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_bool_bool"), map_key));
+    }
+  }
+  {
+    std::map<string, string> map;
+    map["0"] = "0";
+    map["1"] = "1";
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_string_string"), i);
+      string  key = sub_message->GetReflection()->GetString(
+          *sub_message, map_string_string_key_);
+      string val = sub_message->GetReflection()->GetString(
+          *sub_message, map_string_string_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetStringValue(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_string_string"), map_key));
+    }
+  }
+  {
+    std::map<int32, string> map;
+    map[0] = "0";
+    map[1] = "1";
+    for (int i = 0; i < 2; i++) {
+      sub_message =
+          &reflection->GetRepeatedMessage(message, F("map_int32_bytes"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_bytes_key_);
+      string val = sub_message->GetReflection()->GetString(
+          *sub_message, map_int32_bytes_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_int32_bytes"), map_key));
+    }
+  }
+  {
+    std::map<int32, const EnumValueDescriptor*> map;
+    map[0] = map_enum_bar_;
+    map[1] = map_enum_baz_;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_int32_enum"), i);
+      int32 key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_enum_key_);
+      const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum(
+          *sub_message, map_int32_enum_val_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_int32_enum"), map_key));
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (int i = 0; i < 2; i++) {
+      sub_message = &reflection->GetRepeatedMessage(
+          message, F("map_int32_foreign_message"), i);
+      int32  key = sub_message->GetReflection()->GetInt32(
+          *sub_message, map_int32_foreign_message_key_);
+      const Message& foreign_message = sub_message->GetReflection()->GetMessage(
+          *sub_message, map_int32_foreign_message_val_);
+      int32 val = foreign_message.GetReflection()->GetInt32(
+          foreign_message, foreign_c_);
+      EXPECT_EQ(map[key], val);
+      // Check with Map Reflection
+      map_key.SetInt32Value(key);
+      EXPECT_EQ(true, reflection->ContainsMapKey(
+          message, F("map_int32_foreign_message"), map_key));
+    }
+  }
+}
+
+void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
+    Message* message) {
+  string scratch;
+  string serialized;
+  const Reflection* reflection = message->GetReflection();
+
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum")));
+  ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message")));
+
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    int size = 0;
+    for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32"));
+         iter != reflection->MapEnd(message, F("map_int32_int32"));
+         ++iter, ++size) {
+      // Check const methods do not invalidate map.
+      message->DebugString();
+      message->ShortDebugString();
+      message->SerializeToString(&serialized);
+      message->SpaceUsed();
+      message->ByteSize();
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetInt32Value());
+    }
+    EXPECT_EQ(size, 2);
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64"));
+         iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+                iter.GetValueRef().GetInt64Value());
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_uint32_uint32"));
+         iter != reflection->MapEnd(message, F("map_uint32_uint32"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+                iter.GetValueRef().GetUInt32Value());
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_uint64_uint64"));
+         iter != reflection->MapEnd(message, F("map_uint64_uint64"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+                iter.GetValueRef().GetUInt64Value());
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_sint32_sint32"));
+         iter != reflection->MapEnd(message, F("map_sint32_sint32"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetInt32Value());
+    }
+  }
+  {
+    std::map<int64, int64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_sint64_sint64"));
+         iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+                iter.GetValueRef().GetInt64Value());
+    }
+  }
+  {
+    std::map<uint32, uint32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_fixed32_fixed32"));
+         iter != reflection->MapEnd(message, F("map_fixed32_fixed32"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+                iter.GetValueRef().GetUInt32Value());
+    }
+  }
+  {
+    std::map<uint64, uint64> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_fixed64_fixed64"));
+         iter != reflection->MapEnd(message, F("map_fixed64_fixed64"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+                iter.GetValueRef().GetUInt64Value());
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_sfixed32_sfixed32"));
+         iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32"));
+         ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetInt32Value());
+    }
+  }
+  {
+    std::map<int32, float> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float"));
+         iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetFloatValue());
+    }
+  }
+  {
+    std::map<int32, double> map;
+    map[0] = 0.0;
+    map[1] = 1.0;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_int32_double"));
+         iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetDoubleValue());
+    }
+  }
+  {
+    std::map<bool, bool> map;
+    map[false] = false;
+    map[true] = true;
+    for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool"));
+         iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetBoolValue()],
+                iter.GetValueRef().GetBoolValue());
+    }
+  }
+  {
+    std::map<string, string> map;
+    map["0"] = "0";
+    map["1"] = "1";
+    int size = 0;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_string_string"));
+         iter != reflection->MapEnd(message, F("map_string_string"));
+         ++iter, ++size) {
+      // Check const methods do not invalidate map.
+      message->DebugString();
+      message->ShortDebugString();
+      message->SerializeToString(&serialized);
+      message->SpaceUsed();
+      message->ByteSize();
+      EXPECT_EQ(map[iter.GetKey().GetStringValue()],
+                iter.GetValueRef().GetStringValue());
+    }
+    EXPECT_EQ(size, 2);
+  }
+  {
+    std::map<int32, string> map;
+    map[0] = "0";
+    map[1] = "1";
+    for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes"));
+         iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                iter.GetValueRef().GetStringValue());
+    }
+  }
+  {
+    std::map<int32, const EnumValueDescriptor*> map;
+    map[0] = map_enum_bar_;
+    map[1] = map_enum_baz_;
+    for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum"));
+         iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) {
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(),
+                iter.GetValueRef().GetEnumValue());
+    }
+  }
+  {
+    std::map<int32, int32> map;
+    map[0] = 0;
+    map[1] = 1;
+    int size = 0;
+    for (MapIterator iter = reflection->MapBegin(
+             message, F("map_int32_foreign_message"));
+         iter != reflection->MapEnd(message, F("map_int32_foreign_message"));
+         ++iter, ++size) {
+      // Check const methods do not invalidate map.
+      message->DebugString();
+      message->ShortDebugString();
+      message->SerializeToString(&serialized);
+      message->SpaceUsed();
+      message->ByteSize();
+      const Message& sub_message = iter.GetValueRef().GetMessageValue();
+      EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+                sub_message.GetReflection()->GetInt32(sub_message, foreign_c_));
+    }
+    EXPECT_EQ(size, 2);
+  }
+}
+
+void MapReflectionTester::ExpectClearViaReflection(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  // Map fields are empty.
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_int32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int64_int64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint32_uint32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint64_uint64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint32_sint32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint64_sint64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed32_fixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed64_fixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed32_sfixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed64_sfixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_float")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_double")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_bool_bool")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_string_string")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_bytes")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_enum")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message")));
+}
+
+void MapReflectionTester::ExpectClearViaReflectionIterator(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) ==
+              reflection->MapEnd(message, F("map_int32_int32")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) ==
+              reflection->MapEnd(message, F("map_int64_int64")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) ==
+              reflection->MapEnd(message, F("map_uint32_uint32")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) ==
+              reflection->MapEnd(message, F("map_uint64_uint64")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) ==
+              reflection->MapEnd(message, F("map_sint32_sint32")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) ==
+              reflection->MapEnd(message, F("map_sint64_sint64")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) ==
+              reflection->MapEnd(message, F("map_fixed32_fixed32")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) ==
+              reflection->MapEnd(message, F("map_fixed64_fixed64")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) ==
+              reflection->MapEnd(message, F("map_sfixed32_sfixed32")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) ==
+              reflection->MapEnd(message, F("map_sfixed64_sfixed64")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) ==
+              reflection->MapEnd(message, F("map_int32_float")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) ==
+              reflection->MapEnd(message, F("map_int32_double")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) ==
+              reflection->MapEnd(message, F("map_bool_bool")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) ==
+              reflection->MapEnd(message, F("map_string_string")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) ==
+              reflection->MapEnd(message, F("map_int32_bytes")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) ==
+              reflection->MapEnd(message, F("map_int32_enum")));
+  EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) ==
+              reflection->MapEnd(message, F("map_int32_foreign_message")));
+}
+
+void MapReflectionTester::ExpectMapEntryClearViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  const Message* sub_message;
+
+  {
+    const FieldDescriptor* descriptor = F("map_int32_int32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_int32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int64_int64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int64_int64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_uint32_uint32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_uint32_uint32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_uint64_uint64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_uint64_uint64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sint32_sint32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sint32_sint32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sint64_sint64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sint64_sint64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_fixed32_fixed32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_fixed64_fixed64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sfixed32_sfixed32");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_sfixed64_sfixed64");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_float");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_float"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetFloat(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_double");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_double"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetDouble(*sub_message,
+                                                         value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_bool_bool");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_bool_bool"));
+    EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message,
+                                                           key_descriptor));
+    EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message,
+                                                           value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_string_string");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_string_string"));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                          key_descriptor));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                          value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_bytes");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_bytes"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message,
+                                                        value_descriptor));
+  }
+  {
+    const FieldDescriptor* descriptor = F("map_int32_enum");
+    const FieldDescriptor* key_descriptor =
+        descriptor->message_type()->FindFieldByName("key");
+    const FieldDescriptor* value_descriptor =
+        descriptor->message_type()->FindFieldByName("value");
+    sub_message = reflection->AddMessage(message, F("map_int32_enum"));
+    EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
+                                                        key_descriptor));
+    EXPECT_EQ(0, sub_message->GetReflection()
+                     ->GetEnum(*sub_message, value_descriptor)
+                     ->number());
+  }
+  // Map using message as value has been tested in other place. Thus, we don't
+  // test it here.
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_test_util.h b/src/third_party/protobuf-3/src/google/protobuf/map_test_util.h
new file mode 100644
index 0000000..deaf0f4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_test_util.h
@@ -0,0 +1,159 @@
+// 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_MAP_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
+
+#include <google/protobuf/map_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtil {
+ public:
+  // Set every field in the TestMap message to a unique value.
+  static void SetMapFields(unittest::TestMap* message);
+
+  // Set every field in the TestArenaMap message to a unique value.
+  static void SetArenaMapFields(unittest::TestArenaMap* message);
+
+  // Set every field in the message to a default value.
+  static void SetMapFieldsInitialized(unittest::TestMap* message);
+
+  // Modify all the map fields of the message (which should already have been
+  // initialized with SetMapFields()).
+  static void ModifyMapFields(unittest::TestMap* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  static void ExpectMapFieldsSet(const unittest::TestMap& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMap.
+  static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  static void ExpectMapFieldsSetInitialized(
+      const unittest::TestMap& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  static void ExpectMapFieldsModified(const unittest::TestMap& message);
+
+  // Check that all fields are empty.
+  static void ExpectClear(const unittest::TestMap& message);
+
+  // Check that all map fields have the given size.
+  static void ExpectMapsSize(const unittest::TestMap& message, int size);
+
+  // Get pointers of map entries at given index.
+  static std::vector<const Message*> GetMapEntries(
+      const unittest::TestMap& message, int index);
+
+  // Get pointers of map entries from release.
+  static std::vector<const Message*> GetMapEntriesFromRelease(
+      unittest::TestMap* message);
+};
+
+// Like above, but use the reflection interface.
+class MapReflectionTester {
+ public:
+  // base_descriptor must be a descriptor for TestMap, which is used for
+  // MapReflectionTester to fetch the FieldDescriptors needed to use the
+  // reflection interface.
+  explicit MapReflectionTester(const Descriptor* base_descriptor);
+
+  void SetMapFieldsViaReflection(Message* message);
+  void SetMapFieldsViaMapReflection(Message* message);
+  void ClearMapFieldsViaReflection(Message* message);
+  void ModifyMapFieldsViaReflection(Message* message);
+  void RemoveLastMapsViaReflection(Message* message);
+  void ReleaseLastMapsViaReflection(Message* message);
+  void SwapMapsViaReflection(Message* message);
+  void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
+  void ExpectMapFieldsSetViaReflection(const Message& message);
+  void ExpectMapFieldsSetViaReflectionIterator(Message* message);
+  void ExpectClearViaReflection(const Message& message);
+  void ExpectClearViaReflectionIterator(Message* message);
+  void ExpectMapEntryClearViaReflection(Message* message);
+
+ private:
+  const FieldDescriptor* F(const string& name);
+
+  const Descriptor* base_descriptor_;
+
+  const EnumValueDescriptor* map_enum_bar_;
+  const EnumValueDescriptor* map_enum_baz_;
+  const EnumValueDescriptor* map_enum_foo_;
+
+  const FieldDescriptor* foreign_c_;
+  const FieldDescriptor* map_int32_int32_key_;
+  const FieldDescriptor* map_int32_int32_val_;
+  const FieldDescriptor* map_int64_int64_key_;
+  const FieldDescriptor* map_int64_int64_val_;
+  const FieldDescriptor* map_uint32_uint32_key_;
+  const FieldDescriptor* map_uint32_uint32_val_;
+  const FieldDescriptor* map_uint64_uint64_key_;
+  const FieldDescriptor* map_uint64_uint64_val_;
+  const FieldDescriptor* map_sint32_sint32_key_;
+  const FieldDescriptor* map_sint32_sint32_val_;
+  const FieldDescriptor* map_sint64_sint64_key_;
+  const FieldDescriptor* map_sint64_sint64_val_;
+  const FieldDescriptor* map_fixed32_fixed32_key_;
+  const FieldDescriptor* map_fixed32_fixed32_val_;
+  const FieldDescriptor* map_fixed64_fixed64_key_;
+  const FieldDescriptor* map_fixed64_fixed64_val_;
+  const FieldDescriptor* map_sfixed32_sfixed32_key_;
+  const FieldDescriptor* map_sfixed32_sfixed32_val_;
+  const FieldDescriptor* map_sfixed64_sfixed64_key_;
+  const FieldDescriptor* map_sfixed64_sfixed64_val_;
+  const FieldDescriptor* map_int32_float_key_;
+  const FieldDescriptor* map_int32_float_val_;
+  const FieldDescriptor* map_int32_double_key_;
+  const FieldDescriptor* map_int32_double_val_;
+  const FieldDescriptor* map_bool_bool_key_;
+  const FieldDescriptor* map_bool_bool_val_;
+  const FieldDescriptor* map_string_string_key_;
+  const FieldDescriptor* map_string_string_val_;
+  const FieldDescriptor* map_int32_bytes_key_;
+  const FieldDescriptor* map_int32_bytes_val_;
+  const FieldDescriptor* map_int32_enum_key_;
+  const FieldDescriptor* map_int32_enum_val_;
+  const FieldDescriptor* map_int32_foreign_message_key_;
+  const FieldDescriptor* map_int32_foreign_message_val_;
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_test_util_impl.h b/src/third_party/protobuf-3/src/google/protobuf/map_test_util_impl.h
new file mode 100644
index 0000000..b3ba4e0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_test_util_impl.h
@@ -0,0 +1,490 @@
+// 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_MAP_TEST_UTIL_IMPL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf_unittest {}  // forward declaration
+
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtilImpl {
+ public:
+  // Set every field in the TestMap message to a unique value.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void SetMapFields(MapMessage* message);
+
+  // Set every field in the TestArenaMap message to a unique value.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void SetArenaMapFields(MapMessage* message);
+
+  // Set every field in the message to a default value.
+  template <typename MapMessage>
+  static void SetMapFieldsInitialized(MapMessage* message);
+
+  // Modify all the map fields of the message (which should already have been
+  // initialized with SetMapFields()).
+  template <typename EnumType, EnumType enum_value, typename MapMessage>
+  static void ModifyMapFields(MapMessage* message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectMapFieldsSet(const MapMessage& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFields() is called for TestArenaMap.
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectArenaMapFieldsSet(const MapMessage& message);
+
+  // Check that all fields have the values that they should have after
+  // SetMapFieldsInitialized() is called.
+  template <typename EnumType, EnumType enum_value, typename MapMessage>
+  static void ExpectMapFieldsSetInitialized(const MapMessage& message);
+
+  // Expect that the message is modified as would be expected from
+  // ModifyMapFields().
+  template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+  static void ExpectMapFieldsModified(const MapMessage& message);
+
+  // Check that all fields are empty.
+  template <typename MapMessage>
+  static void ExpectClear(const MapMessage& message);
+
+  // // Check that all map fields have the given size.
+  // template <typename MapMessage>
+  // static void ExpectMapsSize(const MapMessage& message, int size);
+
+  // // Get pointers of map entries at given index.
+  // static std::vector<const Message*> GetMapEntries(
+  //     const MapMessage& message, int index);
+
+  // // Get pointers of map entries from release.
+  // static std::vector<const Message*> GetMapEntriesFromRelease(
+  //     MapMessage* message);
+};
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetMapFields(MapMessage* message) {
+  // Add first element.
+  (*message->mutable_map_int32_int32())[0] = 0;
+  (*message->mutable_map_int64_int64())[0] = 0;
+  (*message->mutable_map_uint32_uint32())[0] = 0;
+  (*message->mutable_map_uint64_uint64())[0] = 0;
+  (*message->mutable_map_sint32_sint32())[0] = 0;
+  (*message->mutable_map_sint64_sint64())[0] = 0;
+  (*message->mutable_map_fixed32_fixed32())[0] = 0;
+  (*message->mutable_map_fixed64_fixed64())[0] = 0;
+  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+  (*message->mutable_map_int32_float())[0] = 0.0;
+  (*message->mutable_map_int32_double())[0] = 0.0;
+  (*message->mutable_map_bool_bool())[0] = false;
+  (*message->mutable_map_string_string())["0"] = "0";
+  (*message->mutable_map_int32_bytes())[0] = "0";
+  (*message->mutable_map_int32_enum())[0] = enum_value0;
+  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+  // Add second element
+  (*message->mutable_map_int32_int32())[1] = 1;
+  (*message->mutable_map_int64_int64())[1] = 1;
+  (*message->mutable_map_uint32_uint32())[1] = 1;
+  (*message->mutable_map_uint64_uint64())[1] = 1;
+  (*message->mutable_map_sint32_sint32())[1] = 1;
+  (*message->mutable_map_sint64_sint64())[1] = 1;
+  (*message->mutable_map_fixed32_fixed32())[1] = 1;
+  (*message->mutable_map_fixed64_fixed64())[1] = 1;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+  (*message->mutable_map_int32_float())[1] = 1.0;
+  (*message->mutable_map_int32_double())[1] = 1.0;
+  (*message->mutable_map_bool_bool())[1] = true;
+  (*message->mutable_map_string_string())["1"] = "1";
+  (*message->mutable_map_int32_bytes())[1] = "1";
+  (*message->mutable_map_int32_enum())[1] = enum_value1;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
+  // Add first element.
+  (*message->mutable_map_int32_int32())[0] = 0;
+  (*message->mutable_map_int64_int64())[0] = 0;
+  (*message->mutable_map_uint32_uint32())[0] = 0;
+  (*message->mutable_map_uint64_uint64())[0] = 0;
+  (*message->mutable_map_sint32_sint32())[0] = 0;
+  (*message->mutable_map_sint64_sint64())[0] = 0;
+  (*message->mutable_map_fixed32_fixed32())[0] = 0;
+  (*message->mutable_map_fixed64_fixed64())[0] = 0;
+  (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+  (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+  (*message->mutable_map_int32_float())[0] = 0.0;
+  (*message->mutable_map_int32_double())[0] = 0.0;
+  (*message->mutable_map_bool_bool())[0] = false;
+  (*message->mutable_map_string_string())["0"] = "0";
+  (*message->mutable_map_int32_bytes())[0] = "0";
+  (*message->mutable_map_int32_enum())[0] = enum_value0;
+  (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+  (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0);
+
+  // Add second element
+  (*message->mutable_map_int32_int32())[1] = 1;
+  (*message->mutable_map_int64_int64())[1] = 1;
+  (*message->mutable_map_uint32_uint32())[1] = 1;
+  (*message->mutable_map_uint64_uint64())[1] = 1;
+  (*message->mutable_map_sint32_sint32())[1] = 1;
+  (*message->mutable_map_sint64_sint64())[1] = 1;
+  (*message->mutable_map_fixed32_fixed32())[1] = 1;
+  (*message->mutable_map_fixed64_fixed64())[1] = 1;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+  (*message->mutable_map_int32_float())[1] = 1.0;
+  (*message->mutable_map_int32_double())[1] = 1.0;
+  (*message->mutable_map_bool_bool())[1] = true;
+  (*message->mutable_map_string_string())["1"] = "1";
+  (*message->mutable_map_int32_bytes())[1] = "1";
+  (*message->mutable_map_int32_enum())[1] = enum_value1;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+  (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) {
+  // Add first element using bracket operator, which should assign default
+  // value automatically.
+  (*message->mutable_map_int32_int32())[0];
+  (*message->mutable_map_int64_int64())[0];
+  (*message->mutable_map_uint32_uint32())[0];
+  (*message->mutable_map_uint64_uint64())[0];
+  (*message->mutable_map_sint32_sint32())[0];
+  (*message->mutable_map_sint64_sint64())[0];
+  (*message->mutable_map_fixed32_fixed32())[0];
+  (*message->mutable_map_fixed64_fixed64())[0];
+  (*message->mutable_map_sfixed32_sfixed32())[0];
+  (*message->mutable_map_sfixed64_sfixed64())[0];
+  (*message->mutable_map_int32_float())[0];
+  (*message->mutable_map_int32_double())[0];
+  (*message->mutable_map_bool_bool())[0];
+  (*message->mutable_map_string_string())["0"];
+  (*message->mutable_map_int32_bytes())[0];
+  (*message->mutable_map_int32_enum())[0];
+  (*message->mutable_map_int32_foreign_message())[0];
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ModifyMapFields(MapMessage* message) {
+  (*message->mutable_map_int32_int32())[1] = 2;
+  (*message->mutable_map_int64_int64())[1] = 2;
+  (*message->mutable_map_uint32_uint32())[1] = 2;
+  (*message->mutable_map_uint64_uint64())[1] = 2;
+  (*message->mutable_map_sint32_sint32())[1] = 2;
+  (*message->mutable_map_sint64_sint64())[1] = 2;
+  (*message->mutable_map_fixed32_fixed32())[1] = 2;
+  (*message->mutable_map_fixed64_fixed64())[1] = 2;
+  (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
+  (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
+  (*message->mutable_map_int32_float())[1] = 2.0;
+  (*message->mutable_map_int32_double())[1] = 2.0;
+  (*message->mutable_map_bool_bool())[1] = false;
+  (*message->mutable_map_string_string())["1"] = "2";
+  (*message->mutable_map_int32_bytes())[1] = "2";
+  (*message->mutable_map_int32_enum())[1] = enum_value;
+  (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::ExpectClear(const MapMessage& message) {
+  EXPECT_EQ(0, message.map_int32_int32().size());
+  EXPECT_EQ(0, message.map_int64_int64().size());
+  EXPECT_EQ(0, message.map_uint32_uint32().size());
+  EXPECT_EQ(0, message.map_uint64_uint64().size());
+  EXPECT_EQ(0, message.map_sint32_sint32().size());
+  EXPECT_EQ(0, message.map_sint64_sint64().size());
+  EXPECT_EQ(0, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(0, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(0, message.map_int32_float().size());
+  EXPECT_EQ(0, message.map_int32_double().size());
+  EXPECT_EQ(0, message.map_bool_bool().size());
+  EXPECT_EQ(0, message.map_string_string().size());
+  EXPECT_EQ(0, message.map_int32_bytes().size());
+  EXPECT_EQ(0, message.map_int32_enum().size());
+  EXPECT_EQ(0, message.map_int32_foreign_message().size());
+}
+
+
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) {
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+  EXPECT_EQ(1, message.map_int64_int64().at(1));
+  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(1, message.map_int32_float().at(1));
+  EXPECT_EQ(1, message.map_int32_double().at(1));
+  EXPECT_EQ(true, message.map_bool_bool().at(1));
+  EXPECT_EQ("1", message.map_string_string().at("1"));
+  EXPECT_EQ("1", message.map_int32_bytes().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value0,
+          EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message_no_arena().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+  EXPECT_EQ(0, message.map_int32_foreign_message_no_arena().at(0).c());
+
+  EXPECT_EQ(1, message.map_int32_int32().at(1));
+  EXPECT_EQ(1, message.map_int64_int64().at(1));
+  EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(1, message.map_int32_float().at(1));
+  EXPECT_EQ(1, message.map_int32_double().at(1));
+  EXPECT_EQ(true, message.map_bool_bool().at(1));
+  EXPECT_EQ("1", message.map_string_string().at("1"));
+  EXPECT_EQ("1", message.map_int32_bytes().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+  EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSetInitialized(
+    const MapMessage& message) {
+  EXPECT_EQ(1, message.map_int32_int32().size());
+  EXPECT_EQ(1, message.map_int64_int64().size());
+  EXPECT_EQ(1, message.map_uint32_uint32().size());
+  EXPECT_EQ(1, message.map_uint64_uint64().size());
+  EXPECT_EQ(1, message.map_sint32_sint32().size());
+  EXPECT_EQ(1, message.map_sint64_sint64().size());
+  EXPECT_EQ(1, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(1, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(1, message.map_int32_float().size());
+  EXPECT_EQ(1, message.map_int32_double().size());
+  EXPECT_EQ(1, message.map_bool_bool().size());
+  EXPECT_EQ(1, message.map_string_string().size());
+  EXPECT_EQ(1, message.map_int32_bytes().size());
+  EXPECT_EQ(1, message.map_int32_enum().size());
+  EXPECT_EQ(1, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("", message.map_string_string().at("0"));
+  EXPECT_EQ("", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+}
+
+template <typename EnumType, EnumType enum_value0,
+            EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsModified(
+    const MapMessage& message) {
+  // ModifyMapFields only sets the second element of each field.  In addition to
+  // verifying this, we also verify that the first element and size were *not*
+  // modified.
+  EXPECT_EQ(2, message.map_int32_int32().size());
+  EXPECT_EQ(2, message.map_int64_int64().size());
+  EXPECT_EQ(2, message.map_uint32_uint32().size());
+  EXPECT_EQ(2, message.map_uint64_uint64().size());
+  EXPECT_EQ(2, message.map_sint32_sint32().size());
+  EXPECT_EQ(2, message.map_sint64_sint64().size());
+  EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+  EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+  EXPECT_EQ(2, message.map_int32_float().size());
+  EXPECT_EQ(2, message.map_int32_double().size());
+  EXPECT_EQ(2, message.map_bool_bool().size());
+  EXPECT_EQ(2, message.map_string_string().size());
+  EXPECT_EQ(2, message.map_int32_bytes().size());
+  EXPECT_EQ(2, message.map_int32_enum().size());
+  EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+  EXPECT_EQ(0, message.map_int32_int32().at(0));
+  EXPECT_EQ(0, message.map_int64_int64().at(0));
+  EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+  EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+  EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+  EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+  EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+  EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+  EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+  EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+  EXPECT_EQ(0, message.map_int32_float().at(0));
+  EXPECT_EQ(0, message.map_int32_double().at(0));
+  EXPECT_EQ(false, message.map_bool_bool().at(0));
+  EXPECT_EQ("0", message.map_string_string().at("0"));
+  EXPECT_EQ("0", message.map_int32_bytes().at(0));
+  EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(2, message.map_int32_int32().at(1));
+  EXPECT_EQ(2, message.map_int64_int64().at(1));
+  EXPECT_EQ(2, message.map_uint32_uint32().at(1));
+  EXPECT_EQ(2, message.map_uint64_uint64().at(1));
+  EXPECT_EQ(2, message.map_sint32_sint32().at(1));
+  EXPECT_EQ(2, message.map_sint64_sint64().at(1));
+  EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
+  EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
+  EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
+  EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
+  EXPECT_EQ(2, message.map_int32_float().at(1));
+  EXPECT_EQ(2, message.map_int32_double().at(1));
+  EXPECT_EQ(false, message.map_bool_bool().at(1));
+  EXPECT_EQ("2", message.map_string_string().at("1"));
+  EXPECT_EQ("2", message.map_int32_bytes().at(1));
+  EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+  EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_type_handler.h b/src/third_party/protobuf-3/src/google/protobuf/map_type_handler.h
new file mode 100644
index 0000000..f8ad758
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_type_handler.h
@@ -0,0 +1,727 @@
+// 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/generated_message_util.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 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* WriteToArray(int field,
+                                    const MapEntryAccessorType& value,
+                                    uint8* output);
+
+  // 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 int SpaceUsedInMapEntry(const Type* value);
+  // Return bytes used by value in Map.
+  static inline int SpaceUsedInMap(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* WriteToArray(int field,                              \
+                                      const MapEntryAccessorType& value,      \
+                                      uint8* output);                         \
+    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 int SpaceUsedInMapEntry(const TypeOnMemory& value);         \
+    static inline int SpaceUsedInMap(const TypeOnMemory& value);              \
+    static inline int SpaceUsedInMap(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 int
+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 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 WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
+}
+
+#define GET_CACHED_SIZE(FieldType, DeclaredType)                         \
+  template <typename Type>                                               \
+  inline int                                                             \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
+      const MapEntryAccessorType& value) {                               \
+    return 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>::WriteToArray(
+    int field, const MapEntryAccessorType& value, uint8* output) {
+  return WireFormatLite::WriteMessageToArray(field, value, output);
+}
+
+#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>::WriteToArray(        \
+      int field, const MapEntryAccessorType& value, uint8* output) {           \
+    return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
+  }
+
+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 int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+                        Type>::SpaceUsedInMapEntry(const Type* value) {
+  return value->SpaceUsed();
+}
+
+template <typename Type>
+int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMap(
+    const Type& value) {
+  return value.SpaceUsed();
+}
+
+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::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(&::google::protobuf::internal::GetEmptyString());                   \
+  }                                                                            \
+  template <typename Type>                                                     \
+  inline int                                                                   \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+      const TypeOnMemory& value) {                                             \
+    return sizeof(value);                                                      \
+  }                                                                            \
+  template <typename Type>                                                     \
+  inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType,                  \
+                            Type>::SpaceUsedInMap(const TypeOnMemory& value) { \
+    return sizeof(value);                                                      \
+  }                                                                            \
+  template <typename Type>                                                     \
+  inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType,                  \
+                            Type>::SpaceUsedInMap(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::GetEmptyString(), 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::GetEmptyString(), from, arena);               \
+  }                                                                            \
+  template <typename Type>                                                     \
+  void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena(  \
+      TypeOnMemory& value) {                                                   \
+    value.DestroyNoArena(&::google::protobuf::internal::GetEmptyString());               \
+  }                                                                            \
+  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::GetEmptyString());            \
+  }                                                                            \
+  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::GetEmptyString(), 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(&::google::protobuf::internal::GetEmptyString());                   \
+  }                                                                            \
+  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 int                                                                   \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+      const TypeOnMemory& value) {                                             \
+    return 0;                                                                  \
+  }                                                                            \
+  template <typename Type>                                                     \
+  inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType,                  \
+                            Type>::SpaceUsedInMap(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__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_unittest.proto b/src/third_party/protobuf-3/src/google/protobuf/map_unittest.proto
new file mode 100644
index 0000000..aea1e8c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_unittest.proto
@@ -0,0 +1,129 @@
+// 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.
+
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+
+import "google/protobuf/unittest.proto";
+import "google/protobuf/unittest_no_arena.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Tests maps.
+message TestMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnum > map_int32_enum        = 16;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
+  map<string  , ForeignMessage> map_string_foreign_message = 18;
+}
+
+message TestMapSubmessage {
+  TestMap test_map = 1;
+}
+
+message TestMessageMap {
+  map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+  map<int32, int32> map1 = 1;
+  map<int32, int32> map2 = 2;
+}
+
+
+enum MapEnum {
+  MAP_ENUM_FOO = 0;
+  MAP_ENUM_BAR = 1;
+  MAP_ENUM_BAZ = 2;
+}
+
+// Test embeded message with required fields
+message TestRequiredMessageMap {
+  map<int32, TestRequired> map_field = 1;
+}
+
+message TestArenaMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnum > map_int32_enum        = 16;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
+  map<int32, .protobuf_unittest_no_arena.ForeignMessage>
+      map_int32_foreign_message_no_arena = 18;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+  enum Type {
+    TYPE_FOO = 0;
+  }
+  map<string, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+  map<int32, int32> entry = 1;
+}
+
+message TestRecursiveMapMessage {
+  map<string, TestRecursiveMapMessage> a = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/map_unittest_proto3.proto b/src/third_party/protobuf-3/src/google/protobuf/map_unittest_proto3.proto
new file mode 100644
index 0000000..16be277
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/map_unittest_proto3.proto
@@ -0,0 +1,120 @@
+// 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.
+
+// This file is mostly equivalent to map_unittest.proto, but imports
+// unittest_proto3.proto instead of unittest.proto, so that it only
+// uses proto3 messages. This makes it suitable for testing
+// implementations which only support proto3.
+// The TestRequiredMessageMap message has been removed as there are no
+// required fields in proto3.
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+import "google/protobuf/unittest_proto3.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Tests maps.
+message TestMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnum > map_int32_enum        = 16;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
+}
+
+message TestMapSubmessage {
+  TestMap test_map = 1;
+}
+
+message TestMessageMap {
+  map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+  map<int32, int32> map1 = 1;
+  map<int32, int32> map2 = 2;
+}
+
+enum MapEnum {
+  MAP_ENUM_FOO = 0;
+  MAP_ENUM_BAR = 1;
+  MAP_ENUM_BAZ = 2;
+}
+
+message TestArenaMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<int32   , MapEnum > map_int32_enum        = 14;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 15;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+  enum Type {
+    TYPE_FOO = 0;
+  }
+  map<int32, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+  map<int32, int32> entry = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/message.cc b/src/third_party/protobuf-3/src/google/protobuf/message.cc
new file mode 100644
index 0000000..d62ca79
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/message.cc
@@ -0,0 +1,517 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <iostream>
+#include <stack>
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/message.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/reflection_internal.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/singleton.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+
+using internal::WireFormat;
+using internal::ReflectionOps;
+
+Message::~Message() {}
+
+void Message::MergeFrom(const Message& from) {
+  const Descriptor* descriptor = GetDescriptor();
+  GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
+    << ": Tried to merge from a message with a different type.  "
+       "to: " << descriptor->full_name() << ", "
+       "from: " << from.GetDescriptor()->full_name();
+  ReflectionOps::Merge(from, this);
+}
+
+void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
+  MergeFrom(*down_cast<const Message*>(&other));
+}
+
+void Message::CopyFrom(const Message& from) {
+  const Descriptor* descriptor = GetDescriptor();
+  GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
+    << ": Tried to copy from a message with a different type. "
+       "to: " << descriptor->full_name() << ", "
+       "from: " << from.GetDescriptor()->full_name();
+  ReflectionOps::Copy(from, this);
+}
+
+string Message::GetTypeName() const {
+  return GetDescriptor()->full_name();
+}
+
+void Message::Clear() {
+  ReflectionOps::Clear(this);
+}
+
+bool Message::IsInitialized() const {
+  return ReflectionOps::IsInitialized(*this);
+}
+
+void Message::FindInitializationErrors(vector<string>* errors) const {
+  return ReflectionOps::FindInitializationErrors(*this, "", errors);
+}
+
+string Message::InitializationErrorString() const {
+  vector<string> errors;
+  FindInitializationErrors(&errors);
+  return Join(errors, ", ");
+}
+
+void Message::CheckInitialized() const {
+  GOOGLE_CHECK(IsInitialized())
+    << "Message of type \"" << GetDescriptor()->full_name()
+    << "\" is missing required fields: " << InitializationErrorString();
+}
+
+void Message::DiscardUnknownFields() {
+  return ReflectionOps::DiscardUnknownFields(this);
+}
+
+bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
+  return WireFormat::ParseAndMergePartial(input, this);
+}
+
+bool Message::ParseFromFileDescriptor(int file_descriptor) {
+  io::FileInputStream input(file_descriptor);
+  return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
+}
+
+bool Message::ParsePartialFromFileDescriptor(int file_descriptor) {
+  io::FileInputStream input(file_descriptor);
+  return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
+}
+
+bool Message::ParseFromIstream(istream* input) {
+  io::IstreamInputStream zero_copy_input(input);
+  return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
+}
+
+bool Message::ParsePartialFromIstream(istream* input) {
+  io::IstreamInputStream zero_copy_input(input);
+  return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
+}
+
+
+void Message::SerializeWithCachedSizes(
+    io::CodedOutputStream* output) const {
+  WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
+}
+
+int Message::ByteSize() const {
+  int size = WireFormat::ByteSize(*this);
+  SetCachedSize(size);
+  return size;
+}
+
+void Message::SetCachedSize(int /* size */) const {
+  GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
+             << "\" implements neither SetCachedSize() nor ByteSize().  "
+                "Must implement one or the other.";
+}
+
+int Message::SpaceUsed() const {
+  return GetReflection()->SpaceUsed(*this);
+}
+
+bool Message::SerializeToFileDescriptor(int file_descriptor) const {
+  io::FileOutputStream output(file_descriptor);
+  return SerializeToZeroCopyStream(&output);
+}
+
+bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
+  io::FileOutputStream output(file_descriptor);
+  return SerializePartialToZeroCopyStream(&output);
+}
+
+bool Message::SerializeToOstream(ostream* output) const {
+  {
+    io::OstreamOutputStream zero_copy_output(output);
+    if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
+  }
+  return output->good();
+}
+
+bool Message::SerializePartialToOstream(ostream* output) const {
+  io::OstreamOutputStream zero_copy_output(output);
+  return SerializePartialToZeroCopyStream(&zero_copy_output);
+}
+
+
+// =============================================================================
+// Reflection and associated Template Specializations
+
+Reflection::~Reflection() {}
+
+#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE)                             \
+template<>                                                            \
+const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(        \
+    const Message& message, const FieldDescriptor* field) const {     \
+  return *static_cast<RepeatedField<TYPE>* >(                         \
+      MutableRawRepeatedField(const_cast<Message*>(&message),         \
+                          field, CPPTYPE, CTYPE, NULL));              \
+}                                                                     \
+                                                                      \
+template<>                                                            \
+RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(          \
+    Message* message, const FieldDescriptor* field) const {           \
+  return static_cast<RepeatedField<TYPE>* >(                          \
+      MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
+}
+
+HANDLE_TYPE(int32,  FieldDescriptor::CPPTYPE_INT32,  -1);
+HANDLE_TYPE(int64,  FieldDescriptor::CPPTYPE_INT64,  -1);
+HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
+HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
+HANDLE_TYPE(float,  FieldDescriptor::CPPTYPE_FLOAT,  -1);
+HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
+HANDLE_TYPE(bool,   FieldDescriptor::CPPTYPE_BOOL,   -1);
+
+
+#undef HANDLE_TYPE
+
+void* Reflection::MutableRawRepeatedString(
+    Message* message, const FieldDescriptor* field, bool is_string) const {
+  return MutableRawRepeatedField(message, field,
+      FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
+}
+
+
+// Default EnumValue API implementations. Real reflection implementations should
+// override these. However, there are several legacy implementations that do
+// not, and cannot easily be changed at the same time as the Reflection API, so
+// we provide these for now.
+// TODO: Remove these once all Reflection implementations are updated.
+int Reflection::GetEnumValue(const Message& message,
+                             const FieldDescriptor* field) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+  return 0;
+}
+void Reflection::SetEnumValue(Message* message,
+                  const FieldDescriptor* field,
+                  int value) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+int Reflection::GetRepeatedEnumValue(
+    const Message& message,
+    const FieldDescriptor* field, int index) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+  return 0;
+}
+void Reflection::SetRepeatedEnumValue(Message* message,
+                                  const FieldDescriptor* field, int index,
+                                  int value) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+void Reflection::AddEnumValue(Message* message,
+                  const FieldDescriptor* field,
+                  int value) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+
+MapIterator Reflection::MapBegin(
+    Message* message,
+    const FieldDescriptor* field) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+  MapIterator iter(message, field);
+  return iter;
+}
+
+MapIterator Reflection::MapEnd(
+    Message* message,
+    const FieldDescriptor* field) const {
+  GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+  MapIterator iter(message, field);
+  return iter;
+}
+
+// =============================================================================
+// MessageFactory
+
+MessageFactory::~MessageFactory() {}
+
+namespace {
+
+class GeneratedMessageFactory : public MessageFactory {
+ public:
+  GeneratedMessageFactory();
+  ~GeneratedMessageFactory();
+
+  static GeneratedMessageFactory* singleton();
+
+  typedef void RegistrationFunc(const string&);
+  void RegisterFile(const char* file, RegistrationFunc* registration_func);
+  void RegisterType(const Descriptor* descriptor, const Message* prototype);
+
+  // implements MessageFactory ---------------------------------------
+  const Message* GetPrototype(const Descriptor* type);
+
+ private:
+  // Only written at static init time, so does not require locking.
+  hash_map<const char*, RegistrationFunc*,
+           hash<const char*>, streq> file_map_;
+
+  // Initialized lazily, so requires locking.
+  Mutex mutex_;
+  hash_map<const Descriptor*, const Message*> type_map_;
+};
+
+GeneratedMessageFactory* generated_message_factory_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
+
+void ShutdownGeneratedMessageFactory() {
+  delete generated_message_factory_;
+}
+
+void InitGeneratedMessageFactory() {
+  generated_message_factory_ = new GeneratedMessageFactory;
+  internal::OnShutdown(&ShutdownGeneratedMessageFactory);
+}
+
+GeneratedMessageFactory::GeneratedMessageFactory() {}
+GeneratedMessageFactory::~GeneratedMessageFactory() {}
+
+GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
+  ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
+                 &InitGeneratedMessageFactory);
+  return generated_message_factory_;
+}
+
+void GeneratedMessageFactory::RegisterFile(
+    const char* file, RegistrationFunc* registration_func) {
+  if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
+    GOOGLE_LOG(FATAL) << "File is already registered: " << file;
+  }
+}
+
+void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
+                                           const Message* prototype) {
+  GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
+    << "Tried to register a non-generated type with the generated "
+       "type registry.";
+
+  // This should only be called as a result of calling a file registration
+  // function during GetPrototype(), in which case we already have locked
+  // the mutex.
+  mutex_.AssertHeld();
+  if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
+    GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
+  }
+}
+
+
+const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
+  {
+    ReaderMutexLock lock(&mutex_);
+    const Message* result = FindPtrOrNull(type_map_, type);
+    if (result != NULL) return result;
+  }
+
+  // If the type is not in the generated pool, then we can't possibly handle
+  // it.
+  if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
+
+  // Apparently the file hasn't been registered yet.  Let's do that now.
+  RegistrationFunc* registration_func =
+      FindPtrOrNull(file_map_, type->file()->name().c_str());
+  if (registration_func == NULL) {
+    GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
+                   "registered: " << type->file()->name();
+    return NULL;
+  }
+
+  WriterMutexLock lock(&mutex_);
+
+  // Check if another thread preempted us.
+  const Message* result = FindPtrOrNull(type_map_, type);
+  if (result == NULL) {
+    // Nope.  OK, register everything.
+    registration_func(type->file()->name());
+    // Should be here now.
+    result = FindPtrOrNull(type_map_, type);
+  }
+
+  if (result == NULL) {
+    GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
+                << "registered: " << type->full_name();
+  }
+
+  return result;
+}
+
+}  // namespace
+
+MessageFactory* MessageFactory::generated_factory() {
+  return GeneratedMessageFactory::singleton();
+}
+
+void MessageFactory::InternalRegisterGeneratedFile(
+    const char* filename, void (*register_messages)(const string&)) {
+  GeneratedMessageFactory::singleton()->RegisterFile(filename,
+                                                     register_messages);
+}
+
+void MessageFactory::InternalRegisterGeneratedMessage(
+    const Descriptor* descriptor, const Message* prototype) {
+  GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
+}
+
+
+MessageFactory* Reflection::GetMessageFactory() const {
+  GOOGLE_LOG(FATAL) << "Not implemented.";
+  return NULL;
+}
+
+void* Reflection::RepeatedFieldData(
+    Message* message, const FieldDescriptor* field,
+    FieldDescriptor::CppType cpp_type,
+    const Descriptor* message_type) const {
+  GOOGLE_LOG(FATAL) << "Not implemented.";
+  return NULL;
+}
+
+namespace internal {
+RepeatedFieldAccessor::~RepeatedFieldAccessor() {
+}
+}  // namespace internal
+
+const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
+    const FieldDescriptor* field) const {
+  GOOGLE_CHECK(field->is_repeated());
+  switch (field->cpp_type()) {
+#define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
+    case FieldDescriptor::CPPTYPE_ ## TYPE: \
+      return internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<type> >::get();
+    HANDLE_PRIMITIVE_TYPE(INT32, int32)
+    HANDLE_PRIMITIVE_TYPE(UINT32, uint32)
+    HANDLE_PRIMITIVE_TYPE(INT64, int64)
+    HANDLE_PRIMITIVE_TYPE(UINT64, uint64)
+    HANDLE_PRIMITIVE_TYPE(FLOAT, float)
+    HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
+    HANDLE_PRIMITIVE_TYPE(BOOL, bool)
+    HANDLE_PRIMITIVE_TYPE(ENUM, int32)
+#undef HANDLE_PRIMITIVE_TYPE
+    case FieldDescriptor::CPPTYPE_STRING:
+      switch (field->options().ctype()) {
+        default:
+        case FieldOptions::STRING:
+          return internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::get();
+      }
+      break;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      if (field->is_map()) {
+        return internal::Singleton<internal::MapFieldAccessor>::get();
+      } else {
+        return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
+      }
+  }
+  GOOGLE_LOG(FATAL) << "Should not reach here.";
+  return NULL;
+}
+
+namespace internal {
+namespace {
+void ShutdownRepeatedFieldAccessor() {
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
+  internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
+  internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
+  internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
+  internal::Singleton<internal::MapFieldAccessor>::ShutDown();
+}
+
+struct ShutdownRepeatedFieldRegister {
+  ShutdownRepeatedFieldRegister() {
+    OnShutdown(&ShutdownRepeatedFieldAccessor);
+  }
+} shutdown_;
+
+}  // namespace
+}  // namespace internal
+
+namespace internal {
+template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+Message* GenericTypeHandler<Message>::NewFromPrototype(
+    const Message* prototype, google::protobuf::Arena* arena) {
+  return prototype->New(arena);
+}
+template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
+    Message* value) {
+  return value->GetArena();
+}
+template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
+    Message* value) {
+  return value->GetMaybeArenaPointer();
+}
+}  // namespace internal
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/message.h b/src/third_party/protobuf-3/src/google/protobuf/message.h
new file mode 100644
index 0000000..a4d9277
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/message.h
@@ -0,0 +1,1150 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Defines Message, the abstract interface implemented by non-lite
+// protocol message objects.  Although it's possible to implement this
+// interface manually, most users will use the protocol compiler to
+// generate implementations.
+//
+// Example usage:
+//
+// Say you have a message defined as:
+//
+//   message Foo {
+//     optional string text = 1;
+//     repeated int32 numbers = 2;
+//   }
+//
+// Then, if you used the protocol compiler to generate a class from the above
+// definition, you could use it like so:
+//
+//   string data;  // Will store a serialized version of the message.
+//
+//   {
+//     // Create a message and serialize it.
+//     Foo foo;
+//     foo.set_text("Hello World!");
+//     foo.add_numbers(1);
+//     foo.add_numbers(5);
+//     foo.add_numbers(42);
+//
+//     foo.SerializeToString(&data);
+//   }
+//
+//   {
+//     // Parse the serialized message and check that it contains the
+//     // correct data.
+//     Foo foo;
+//     foo.ParseFromString(data);
+//
+//     assert(foo.text() == "Hello World!");
+//     assert(foo.numbers_size() == 3);
+//     assert(foo.numbers(0) == 1);
+//     assert(foo.numbers(1) == 5);
+//     assert(foo.numbers(2) == 42);
+//   }
+//
+//   {
+//     // Same as the last block, but do it dynamically via the Message
+//     // reflection interface.
+//     Message* foo = new Foo;
+//     const Descriptor* descriptor = foo->GetDescriptor();
+//
+//     // Get the descriptors for the fields we're interested in and verify
+//     // their types.
+//     const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
+//     assert(text_field != NULL);
+//     assert(text_field->type() == FieldDescriptor::TYPE_STRING);
+//     assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
+//     const FieldDescriptor* numbers_field = descriptor->
+//                                            FindFieldByName("numbers");
+//     assert(numbers_field != NULL);
+//     assert(numbers_field->type() == FieldDescriptor::TYPE_INT32);
+//     assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED);
+//
+//     // Parse the message.
+//     foo->ParseFromString(data);
+//
+//     // Use the reflection interface to examine the contents.
+//     const Reflection* reflection = foo->GetReflection();
+//     assert(reflection->GetString(*foo, text_field) == "Hello World!");
+//     assert(reflection->FieldSize(*foo, numbers_field) == 3);
+//     assert(reflection->GetRepeatedInt32(*foo, numbers_field, 0) == 1);
+//     assert(reflection->GetRepeatedInt32(*foo, numbers_field, 1) == 5);
+//     assert(reflection->GetRepeatedInt32(*foo, numbers_field, 2) == 42);
+//
+//     delete foo;
+//   }
+
+#ifndef GOOGLE_PROTOBUF_MESSAGE_H__
+#define GOOGLE_PROTOBUF_MESSAGE_H__
+
+#include <iosfwd>
+#include <string>
+#include <google/protobuf/stubs/type_traits.h>
+#include <vector>
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/message_lite.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+
+
+#define GOOGLE_PROTOBUF_HAS_ONEOF
+#define GOOGLE_PROTOBUF_HAS_ARENAS
+
+namespace google {
+namespace protobuf {
+
+// Defined in this file.
+class Message;
+class Reflection;
+class MessageFactory;
+
+// Defined in other files.
+class MapKey;
+class MapValueRef;
+class MapIterator;
+class MapReflectionTester;
+
+namespace internal {
+class MapFieldBase;
+}
+class UnknownFieldSet;         // unknown_field_set.h
+namespace io {
+class ZeroCopyInputStream;     // zero_copy_stream.h
+class ZeroCopyOutputStream;    // zero_copy_stream.h
+class CodedInputStream;        // coded_stream.h
+class CodedOutputStream;       // coded_stream.h
+}
+namespace python {
+class MapReflectionFriend;     // scalar_map_container.h
+}
+
+
+template<typename T>
+class RepeatedField;     // repeated_field.h
+
+template<typename T>
+class RepeatedPtrField;  // repeated_field.h
+
+// A container to hold message metadata.
+struct Metadata {
+  const Descriptor* descriptor;
+  const Reflection* reflection;
+};
+
+// Abstract interface for protocol messages.
+//
+// See also MessageLite, which contains most every-day operations.  Message
+// adds descriptors and reflection on top of that.
+//
+// The methods of this class that are virtual but not pure-virtual have
+// default implementations based on reflection.  Message classes which are
+// optimized for speed will want to override these with faster implementations,
+// but classes optimized for code size may be happy with keeping them.  See
+// the optimize_for option in descriptor.proto.
+class LIBPROTOBUF_EXPORT Message : public MessageLite {
+ public:
+  inline Message() {}
+  virtual ~Message();
+
+  // Basic Operations ------------------------------------------------
+
+  // Construct a new instance of the same type.  Ownership is passed to the
+  // caller.  (This is also defined in MessageLite, but is defined again here
+  // for return-type covariance.)
+  virtual Message* New() const = 0;
+
+  // Construct a new instance on the arena. Ownership is passed to the caller
+  // if arena is a NULL. Default implementation allows for API compatibility
+  // during the Arena transition.
+  virtual Message* New(::google::protobuf::Arena* arena) const {
+    Message* message = New();
+    if (arena != NULL) {
+      arena->Own(message);
+    }
+    return message;
+  }
+
+  // Make this message into a copy of the given message.  The given message
+  // must have the same descriptor, but need not necessarily be the same class.
+  // By default this is just implemented as "Clear(); MergeFrom(from);".
+  virtual void CopyFrom(const Message& from);
+
+  // Merge the fields from the given message into this message.  Singular
+  // fields will be overwritten, if specified in from, except for embedded
+  // messages which will be merged.  Repeated fields will be concatenated.
+  // The given message must be of the same type as this message (i.e. the
+  // exact same class).
+  virtual void MergeFrom(const Message& from);
+
+  // Verifies that IsInitialized() returns true.  GOOGLE_CHECK-fails otherwise, with
+  // a nice error message.
+  void CheckInitialized() const;
+
+  // Slowly build a list of all required fields that are not set.
+  // This is much, much slower than IsInitialized() as it is implemented
+  // purely via reflection.  Generally, you should not call this unless you
+  // have already determined that an error exists by calling IsInitialized().
+  void FindInitializationErrors(std::vector<string>* errors) const;
+
+  // Like FindInitializationErrors, but joins all the strings, delimited by
+  // commas, and returns them.
+  string InitializationErrorString() const;
+
+  // Clears all unknown fields from this message and all embedded messages.
+  // Normally, if unknown tag numbers are encountered when parsing a message,
+  // the tag and value are stored in the message's UnknownFieldSet and
+  // then written back out when the message is serialized.  This allows servers
+  // which simply route messages to other servers to pass through messages
+  // that have new field definitions which they don't yet know about.  However,
+  // this behavior can have security implications.  To avoid it, call this
+  // method after parsing.
+  //
+  // See Reflection::GetUnknownFields() for more on unknown fields.
+  virtual void DiscardUnknownFields();
+
+  // Computes (an estimate of) the total number of bytes currently used for
+  // storing the message in memory.  The default implementation calls the
+  // Reflection object's SpaceUsed() method.
+  //
+  // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented
+  // using reflection (rather than the generated code implementation for
+  // ByteSize()). Like ByteSize(), its CPU time is linear in the number of
+  // fields defined for the proto.
+  virtual int SpaceUsed() const;
+
+  // Debugging & Testing----------------------------------------------
+
+  // Generates a human readable form of this message, useful for debugging
+  // and other purposes.
+  string DebugString() const;
+  // Like DebugString(), but with less whitespace.
+  string ShortDebugString() const;
+  // Like DebugString(), but do not escape UTF-8 byte sequences.
+  string Utf8DebugString() const;
+  // Convenience function useful in GDB.  Prints DebugString() to stdout.
+  void PrintDebugString() const;
+
+  // Heavy I/O -------------------------------------------------------
+  // Additional parsing and serialization methods not implemented by
+  // MessageLite because they are not supported by the lite library.
+
+  // Parse a protocol buffer from a file descriptor.  If successful, the entire
+  // input will be consumed.
+  bool ParseFromFileDescriptor(int file_descriptor);
+  // Like ParseFromFileDescriptor(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromFileDescriptor(int file_descriptor);
+  // Parse a protocol buffer from a C++ istream.  If successful, the entire
+  // input will be consumed.
+  bool ParseFromIstream(istream* input);
+  // Like ParseFromIstream(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromIstream(istream* input);
+
+  // Serialize the message and write it to the given file descriptor.  All
+  // required fields must be set.
+  bool SerializeToFileDescriptor(int file_descriptor) const;
+  // Like SerializeToFileDescriptor(), but allows missing required fields.
+  bool SerializePartialToFileDescriptor(int file_descriptor) const;
+  // Serialize the message and write it to the given C++ ostream.  All
+  // required fields must be set.
+  bool SerializeToOstream(ostream* output) const;
+  // Like SerializeToOstream(), but allows missing required fields.
+  bool SerializePartialToOstream(ostream* output) const;
+
+
+  // Reflection-based methods ----------------------------------------
+  // These methods are pure-virtual in MessageLite, but Message provides
+  // reflection-based default implementations.
+
+  virtual string GetTypeName() const;
+  virtual void Clear();
+  virtual bool IsInitialized() const;
+  virtual void CheckTypeAndMergeFrom(const MessageLite& other);
+  virtual bool MergePartialFromCodedStream(io::CodedInputStream* input);
+  virtual int ByteSize() const;
+  virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const;
+
+ private:
+  // This is called only by the default implementation of ByteSize(), to
+  // update the cached size.  If you override ByteSize(), you do not need
+  // to override this.  If you do not override ByteSize(), you MUST override
+  // this; the default implementation will crash.
+  //
+  // The method is private because subclasses should never call it; only
+  // override it.  Yes, C++ lets you do that.  Crazy, huh?
+  virtual void SetCachedSize(int size) const;
+
+ public:
+
+  // Introspection ---------------------------------------------------
+
+  // Typedef for backwards-compatibility.
+  typedef google::protobuf::Reflection Reflection;
+
+  // Get a Descriptor for this message's type.  This describes what
+  // fields the message contains, the types of those fields, etc.
+  const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; }
+
+  // Get the Reflection interface for this Message, which can be used to
+  // read and modify the fields of the Message dynamically (in other words,
+  // without knowing the message type at compile time).  This object remains
+  // property of the Message.
+  //
+  // This method remains virtual in case a subclass does not implement
+  // reflection and wants to override the default behavior.
+  virtual const Reflection* GetReflection() const {
+    return GetMetadata().reflection;
+  }
+
+ protected:
+  // Get a struct containing the metadata for the Message. Most subclasses only
+  // need to implement this method, rather than the GetDescriptor() and
+  // GetReflection() wrappers.
+  virtual Metadata GetMetadata() const  = 0;
+
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
+};
+
+namespace internal {
+// Forward-declare interfaces used to implement RepeatedFieldRef.
+// These are protobuf internals that users shouldn't care about.
+class RepeatedFieldAccessor;
+}  // namespace internal
+
+// Forward-declare RepeatedFieldRef templates. The second type parameter is
+// used for SFINAE tricks. Users should ignore it.
+template<typename T, typename Enable = void>
+class RepeatedFieldRef;
+
+template<typename T, typename Enable = void>
+class MutableRepeatedFieldRef;
+
+// This interface contains methods that can be used to dynamically access
+// and modify the fields of a protocol message.  Their semantics are
+// similar to the accessors the protocol compiler generates.
+//
+// To get the Reflection for a given Message, call Message::GetReflection().
+//
+// This interface is separate from Message only for efficiency reasons;
+// the vast majority of implementations of Message will share the same
+// implementation of Reflection (GeneratedMessageReflection,
+// defined in generated_message.h), and all Messages of a particular class
+// should share the same Reflection object (though you should not rely on
+// the latter fact).
+//
+// There are several ways that these methods can be used incorrectly.  For
+// example, any of the following conditions will lead to undefined
+// results (probably assertion failures):
+// - The FieldDescriptor is not a field of this message type.
+// - The method called is not appropriate for the field's type.  For
+//   each field type in FieldDescriptor::TYPE_*, there is only one
+//   Get*() method, one Set*() method, and one Add*() method that is
+//   valid for that type.  It should be obvious which (except maybe
+//   for TYPE_BYTES, which are represented using strings in C++).
+// - A Get*() or Set*() method for singular fields is called on a repeated
+//   field.
+// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated
+//   field.
+// - The Message object passed to any method is not of the right type for
+//   this Reflection object (i.e. message.GetReflection() != reflection).
+//
+// You might wonder why there is not any abstract representation for a field
+// of arbitrary type.  E.g., why isn't there just a "GetField()" method that
+// returns "const Field&", where "Field" is some class with accessors like
+// "GetInt32Value()".  The problem is that someone would have to deal with
+// allocating these Field objects.  For generated message classes, having to
+// allocate space for an additional object to wrap every field would at least
+// double the message's memory footprint, probably worse.  Allocating the
+// objects on-demand, on the other hand, would be expensive and prone to
+// memory leaks.  So, instead we ended up with this flat interface.
+//
+// TODO(kenton):  Create a utility class which callers can use to read and
+//   write fields from a Reflection without paying attention to the type.
+class LIBPROTOBUF_EXPORT Reflection {
+ public:
+  inline Reflection() {}
+  virtual ~Reflection();
+
+  // Get the UnknownFieldSet for the message.  This contains fields which
+  // were seen when the Message was parsed but were not recognized according
+  // to the Message's definition. For proto3 protos, this method will always
+  // return an empty UnknownFieldSet.
+  virtual const UnknownFieldSet& GetUnknownFields(
+      const Message& message) const = 0;
+  // Get a mutable pointer to the UnknownFieldSet for the message.  This
+  // contains fields which were seen when the Message was parsed but were not
+  // recognized according to the Message's definition. For proto3 protos, this
+  // method will return a valid mutable UnknownFieldSet pointer but modifying
+  // it won't affect the serialized bytes of the message.
+  virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
+
+  // Estimate the amount of memory used by the message object.
+  virtual int SpaceUsed(const Message& message) const = 0;
+
+  // Check if the given non-repeated field is set.
+  virtual bool HasField(const Message& message,
+                        const FieldDescriptor* field) const = 0;
+
+  // Get the number of elements of a repeated field.
+  virtual int FieldSize(const Message& message,
+                        const FieldDescriptor* field) const = 0;
+
+  // Clear the value of a field, so that HasField() returns false or
+  // FieldSize() returns zero.
+  virtual void ClearField(Message* message,
+                          const FieldDescriptor* field) const = 0;
+
+  // Check if the oneof is set. Returns true if any field in oneof
+  // is set, false otherwise.
+  // TODO(jieluo) - make it pure virtual after updating all
+  // the subclasses.
+  virtual bool HasOneof(const Message& /*message*/,
+                        const OneofDescriptor* /*oneof_descriptor*/) const {
+    return false;
+  }
+
+  virtual void ClearOneof(Message* /*message*/,
+                          const OneofDescriptor* /*oneof_descriptor*/) const {}
+
+  // Returns the field descriptor if the oneof is set. NULL otherwise.
+  // TODO(jieluo) - make it pure virtual.
+  virtual const FieldDescriptor* GetOneofFieldDescriptor(
+      const Message& /*message*/,
+      const OneofDescriptor* /*oneof_descriptor*/) const {
+    return NULL;
+  }
+
+  // Removes the last element of a repeated field.
+  // We don't provide a way to remove any element other than the last
+  // because it invites inefficient use, such as O(n^2) filtering loops
+  // that should have been O(n).  If you want to remove an element other
+  // than the last, the best way to do it is to re-arrange the elements
+  // (using Swap()) so that the one you want removed is at the end, then
+  // call RemoveLast().
+  virtual void RemoveLast(Message* message,
+                          const FieldDescriptor* field) const = 0;
+  // Removes the last element of a repeated message field, and returns the
+  // pointer to the caller.  Caller takes ownership of the returned pointer.
+  virtual Message* ReleaseLast(Message* message,
+                               const FieldDescriptor* field) const = 0;
+
+  // Swap the complete contents of two messages.
+  virtual void Swap(Message* message1, Message* message2) const = 0;
+
+  // Swap fields listed in fields vector of two messages.
+  virtual void SwapFields(Message* message1,
+                          Message* message2,
+                          const std::vector<const FieldDescriptor*>& fields)
+      const = 0;
+
+  // Swap two elements of a repeated field.
+  virtual void SwapElements(Message* message,
+                            const FieldDescriptor* field,
+                            int index1,
+                            int index2) const = 0;
+
+  // List all fields of the message which are currently set.  This includes
+  // extensions.  Singular fields will only be listed if HasField(field) would
+  // return true and repeated fields will only be listed if FieldSize(field)
+  // would return non-zero.  Fields (both normal fields and extension fields)
+  // will be listed ordered by field number.
+  virtual void ListFields(
+      const Message& message,
+      std::vector<const FieldDescriptor*>* output) const = 0;
+
+  // Singular field getters ------------------------------------------
+  // These get the value of a non-repeated field.  They return the default
+  // value for fields that aren't set.
+
+  virtual int32  GetInt32 (const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual int64  GetInt64 (const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual uint32 GetUInt32(const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual uint64 GetUInt64(const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual float  GetFloat (const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual double GetDouble(const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual bool   GetBool  (const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual string GetString(const Message& message,
+                           const FieldDescriptor* field) const = 0;
+  virtual const EnumValueDescriptor* GetEnum(
+      const Message& message, const FieldDescriptor* field) const = 0;
+
+  // GetEnumValue() returns an enum field's value as an integer rather than
+  // an EnumValueDescriptor*. If the integer value does not correspond to a
+  // known value descriptor, a new value descriptor is created. (Such a value
+  // will only be present when the new unknown-enum-value semantics are enabled
+  // for a message.)
+  virtual int GetEnumValue(
+      const Message& message, const FieldDescriptor* field) const;
+
+  // See MutableMessage() for the meaning of the "factory" parameter.
+  virtual const Message& GetMessage(const Message& message,
+                                    const FieldDescriptor* field,
+                                    MessageFactory* factory = NULL) const = 0;
+
+  // Get a string value without copying, if possible.
+  //
+  // GetString() necessarily returns a copy of the string.  This can be
+  // inefficient when the string is already stored in a string object in the
+  // underlying message.  GetStringReference() will return a reference to the
+  // underlying string in this case.  Otherwise, it will copy the string into
+  // *scratch and return that.
+  //
+  // Note:  It is perfectly reasonable and useful to write code like:
+  //     str = reflection->GetStringReference(field, &str);
+  //   This line would ensure that only one copy of the string is made
+  //   regardless of the field's underlying representation.  When initializing
+  //   a newly-constructed string, though, it's just as fast and more readable
+  //   to use code like:
+  //     string str = reflection->GetString(message, field);
+  virtual const string& GetStringReference(const Message& message,
+                                           const FieldDescriptor* field,
+                                           string* scratch) const = 0;
+
+
+  // Singular field mutators -----------------------------------------
+  // These mutate the value of a non-repeated field.
+
+  virtual void SetInt32 (Message* message,
+                         const FieldDescriptor* field, int32  value) const = 0;
+  virtual void SetInt64 (Message* message,
+                         const FieldDescriptor* field, int64  value) const = 0;
+  virtual void SetUInt32(Message* message,
+                         const FieldDescriptor* field, uint32 value) const = 0;
+  virtual void SetUInt64(Message* message,
+                         const FieldDescriptor* field, uint64 value) const = 0;
+  virtual void SetFloat (Message* message,
+                         const FieldDescriptor* field, float  value) const = 0;
+  virtual void SetDouble(Message* message,
+                         const FieldDescriptor* field, double value) const = 0;
+  virtual void SetBool  (Message* message,
+                         const FieldDescriptor* field, bool   value) const = 0;
+  virtual void SetString(Message* message,
+                         const FieldDescriptor* field,
+                         const string& value) const = 0;
+  virtual void SetEnum  (Message* message,
+                         const FieldDescriptor* field,
+                         const EnumValueDescriptor* value) const = 0;
+  // Set an enum field's value with an integer rather than EnumValueDescriptor.
+  // If the value does not correspond to a known enum value, either behavior is
+  // undefined (for proto2 messages), or the value is accepted silently for
+  // messages with new unknown-enum-value semantics.
+  virtual void SetEnumValue(Message* message,
+                            const FieldDescriptor* field,
+                            int value) const;
+
+  // Get a mutable pointer to a field with a message type.  If a MessageFactory
+  // is provided, it will be used to construct instances of the sub-message;
+  // otherwise, the default factory is used.  If the field is an extension that
+  // does not live in the same pool as the containing message's descriptor (e.g.
+  // it lives in an overlay pool), then a MessageFactory must be provided.
+  // If you have no idea what that meant, then you probably don't need to worry
+  // about it (don't provide a MessageFactory).  WARNING:  If the
+  // FieldDescriptor is for a compiled-in extension, then
+  // factory->GetPrototype(field->message_type() MUST return an instance of the
+  // compiled-in class for this type, NOT DynamicMessage.
+  virtual Message* MutableMessage(Message* message,
+                                  const FieldDescriptor* field,
+                                  MessageFactory* factory = NULL) const = 0;
+  // Replaces the message specified by 'field' with the already-allocated object
+  // sub_message, passing ownership to the message.  If the field contained a
+  // message, that message is deleted.  If sub_message is NULL, the field is
+  // cleared.
+  virtual void SetAllocatedMessage(Message* message,
+                                   Message* sub_message,
+                                   const FieldDescriptor* field) const = 0;
+  // Releases the message specified by 'field' and returns the pointer,
+  // ReleaseMessage() will return the message the message object if it exists.
+  // Otherwise, it may or may not return NULL.  In any case, if the return value
+  // is non-NULL, the caller takes ownership of the pointer.
+  // If the field existed (HasField() is true), then the returned pointer will
+  // be the same as the pointer returned by MutableMessage().
+  // This function has the same effect as ClearField().
+  virtual Message* ReleaseMessage(Message* message,
+                                  const FieldDescriptor* field,
+                                  MessageFactory* factory = NULL) const = 0;
+
+
+  // Repeated field getters ------------------------------------------
+  // These get the value of one element of a repeated field.
+
+  virtual int32  GetRepeatedInt32 (const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual int64  GetRepeatedInt64 (const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual uint32 GetRepeatedUInt32(const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual uint64 GetRepeatedUInt64(const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual float  GetRepeatedFloat (const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual double GetRepeatedDouble(const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual bool   GetRepeatedBool  (const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual string GetRepeatedString(const Message& message,
+                                   const FieldDescriptor* field,
+                                   int index) const = 0;
+  virtual const EnumValueDescriptor* GetRepeatedEnum(
+      const Message& message,
+      const FieldDescriptor* field, int index) const = 0;
+  // GetRepeatedEnumValue() returns an enum field's value as an integer rather
+  // than an EnumValueDescriptor*. If the integer value does not correspond to a
+  // known value descriptor, a new value descriptor is created. (Such a value
+  // will only be present when the new unknown-enum-value semantics are enabled
+  // for a message.)
+  virtual int GetRepeatedEnumValue(
+      const Message& message,
+      const FieldDescriptor* field, int index) const;
+  virtual const Message& GetRepeatedMessage(
+      const Message& message,
+      const FieldDescriptor* field, int index) const = 0;
+
+  // See GetStringReference(), above.
+  virtual const string& GetRepeatedStringReference(
+      const Message& message, const FieldDescriptor* field,
+      int index, string* scratch) const = 0;
+
+
+  // Repeated field mutators -----------------------------------------
+  // These mutate the value of one element of a repeated field.
+
+  virtual void SetRepeatedInt32 (Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, int32  value) const = 0;
+  virtual void SetRepeatedInt64 (Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, int64  value) const = 0;
+  virtual void SetRepeatedUInt32(Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, uint32 value) const = 0;
+  virtual void SetRepeatedUInt64(Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, uint64 value) const = 0;
+  virtual void SetRepeatedFloat (Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, float  value) const = 0;
+  virtual void SetRepeatedDouble(Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, double value) const = 0;
+  virtual void SetRepeatedBool  (Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, bool   value) const = 0;
+  virtual void SetRepeatedString(Message* message,
+                                 const FieldDescriptor* field,
+                                 int index, const string& value) const = 0;
+  virtual void SetRepeatedEnum(Message* message,
+                               const FieldDescriptor* field, int index,
+                               const EnumValueDescriptor* value) const = 0;
+  // Set an enum field's value with an integer rather than EnumValueDescriptor.
+  // If the value does not correspond to a known enum value, either behavior is
+  // undefined (for proto2 messages), or the value is accepted silently for
+  // messages with new unknown-enum-value semantics.
+  virtual void SetRepeatedEnumValue(Message* message,
+                                    const FieldDescriptor* field, int index,
+                                    int value) const;
+  // Get a mutable pointer to an element of a repeated field with a message
+  // type.
+  virtual Message* MutableRepeatedMessage(
+      Message* message, const FieldDescriptor* field, int index) const = 0;
+
+
+  // Repeated field adders -------------------------------------------
+  // These add an element to a repeated field.
+
+  virtual void AddInt32 (Message* message,
+                         const FieldDescriptor* field, int32  value) const = 0;
+  virtual void AddInt64 (Message* message,
+                         const FieldDescriptor* field, int64  value) const = 0;
+  virtual void AddUInt32(Message* message,
+                         const FieldDescriptor* field, uint32 value) const = 0;
+  virtual void AddUInt64(Message* message,
+                         const FieldDescriptor* field, uint64 value) const = 0;
+  virtual void AddFloat (Message* message,
+                         const FieldDescriptor* field, float  value) const = 0;
+  virtual void AddDouble(Message* message,
+                         const FieldDescriptor* field, double value) const = 0;
+  virtual void AddBool  (Message* message,
+                         const FieldDescriptor* field, bool   value) const = 0;
+  virtual void AddString(Message* message,
+                         const FieldDescriptor* field,
+                         const string& value) const = 0;
+  virtual void AddEnum  (Message* message,
+                         const FieldDescriptor* field,
+                         const EnumValueDescriptor* value) const = 0;
+  // Set an enum field's value with an integer rather than EnumValueDescriptor.
+  // If the value does not correspond to a known enum value, either behavior is
+  // undefined (for proto2 messages), or the value is accepted silently for
+  // messages with new unknown-enum-value semantics.
+  virtual void AddEnumValue(Message* message,
+                            const FieldDescriptor* field,
+                            int value) const;
+  // See MutableMessage() for comments on the "factory" parameter.
+  virtual Message* AddMessage(Message* message,
+                              const FieldDescriptor* field,
+                              MessageFactory* factory = NULL) const = 0;
+
+  // Appends an already-allocated object 'new_entry' to the repeated field
+  // specifyed by 'field' passing ownership to the message.
+  // TODO(tmarek): Make virtual after all subclasses have been
+  // updated.
+  virtual void AddAllocatedMessage(Message* /* message */,
+                                   const FieldDescriptor* /*field */,
+                                   Message* /* new_entry */) const {}
+
+
+  // Get a RepeatedFieldRef object that can be used to read the underlying
+  // repeated field. The type parameter T must be set according to the
+  // field's cpp type. The following table shows the mapping from cpp type
+  // to acceptable T.
+  //
+  //   field->cpp_type()      T
+  //   CPPTYPE_INT32        int32
+  //   CPPTYPE_UINT32       uint32
+  //   CPPTYPE_INT64        int64
+  //   CPPTYPE_UINT64       uint64
+  //   CPPTYPE_DOUBLE       double
+  //   CPPTYPE_FLOAT        float
+  //   CPPTYPE_BOOL         bool
+  //   CPPTYPE_ENUM         generated enum type or int32
+  //   CPPTYPE_STRING       string
+  //   CPPTYPE_MESSAGE      generated message type or google::protobuf::Message
+  //
+  // A RepeatedFieldRef object can be copied and the resulted object will point
+  // to the same repeated field in the same message. The object can be used as
+  // long as the message is not destroyed.
+  //
+  // Note that to use this method users need to include the header file
+  // "google/protobuf/reflection.h" (which defines the RepeatedFieldRef
+  // class templates).
+  template<typename T>
+  RepeatedFieldRef<T> GetRepeatedFieldRef(
+      const Message& message, const FieldDescriptor* field) const;
+
+  // Like GetRepeatedFieldRef() but return an object that can also be used
+  // manipulate the underlying repeated field.
+  template<typename T>
+  MutableRepeatedFieldRef<T> GetMutableRepeatedFieldRef(
+      Message* message, const FieldDescriptor* field) const;
+
+  // DEPRECATED. Please use Get(Mutable)RepeatedFieldRef() for repeated field
+  // access. The following repeated field accesors will be removed in the
+  // future.
+  //
+  // Repeated field accessors  -------------------------------------------------
+  // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular
+  // access to the data in a RepeatedField.  The methods below provide aggregate
+  // access by exposing the RepeatedField object itself with the Message.
+  // Applying these templates to inappropriate types will lead to an undefined
+  // reference at link time (e.g. GetRepeatedField<***double>), or possibly a
+  // template matching error at compile time (e.g. GetRepeatedPtrField<File>).
+  //
+  // Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd);
+
+  // DEPRECATED. Please use GetRepeatedFieldRef().
+  //
+  // for T = Cord and all protobuf scalar types except enums.
+  template<typename T>
+  const RepeatedField<T>& GetRepeatedField(
+      const Message&, const FieldDescriptor*) const;
+
+  // DEPRECATED. Please use GetMutableRepeatedFieldRef().
+  //
+  // for T = Cord and all protobuf scalar types except enums.
+  template<typename T>
+  RepeatedField<T>* MutableRepeatedField(
+      Message*, const FieldDescriptor*) const;
+
+  // DEPRECATED. Please use GetRepeatedFieldRef().
+  //
+  // for T = string, google::protobuf::internal::StringPieceField
+  //         google::protobuf::Message & descendants.
+  template<typename T>
+  const RepeatedPtrField<T>& GetRepeatedPtrField(
+      const Message&, const FieldDescriptor*) const;
+
+  // DEPRECATED. Please use GetMutableRepeatedFieldRef().
+  //
+  // for T = string, google::protobuf::internal::StringPieceField
+  //         google::protobuf::Message & descendants.
+  template<typename T>
+  RepeatedPtrField<T>* MutableRepeatedPtrField(
+      Message*, const FieldDescriptor*) const;
+
+  // Extensions ----------------------------------------------------------------
+
+  // Try to find an extension of this message type by fully-qualified field
+  // name.  Returns NULL if no extension is known for this name or number.
+  virtual const FieldDescriptor* FindKnownExtensionByName(
+      const string& name) const = 0;
+
+  // Try to find an extension of this message type by field number.
+  // Returns NULL if no extension is known for this name or number.
+  virtual const FieldDescriptor* FindKnownExtensionByNumber(
+      int number) const = 0;
+
+  // Feature Flags -------------------------------------------------------------
+
+  // Does this message support storing arbitrary integer values in enum fields?
+  // If |true|, GetEnumValue/SetEnumValue and associated repeated-field versions
+  // take arbitrary integer values, and the legacy GetEnum() getter will
+  // dynamically create an EnumValueDescriptor for any integer value without
+  // one. If |false|, setting an unknown enum value via the integer-based
+  // setters results in undefined behavior (in practice, GOOGLE_DCHECK-fails).
+  //
+  // Generic code that uses reflection to handle messages with enum fields
+  // should check this flag before using the integer-based setter, and either
+  // downgrade to a compatible value or use the UnknownFieldSet if not. For
+  // example:
+  //
+  // int new_value = GetValueFromApplicationLogic();
+  // if (reflection->SupportsUnknownEnumValues()) {
+  //     reflection->SetEnumValue(message, field, new_value);
+  // } else {
+  //     if (field_descriptor->enum_type()->
+  //             FindValueByNumver(new_value) != NULL) {
+  //         reflection->SetEnumValue(message, field, new_value);
+  //     } else if (emit_unknown_enum_values) {
+  //         reflection->MutableUnknownFields(message)->AddVarint(
+  //             field->number(),
+  //             new_value);
+  //     } else {
+  //         // convert value to a compatible/default value.
+  //         new_value = CompatibleDowngrade(new_value);
+  //         reflection->SetEnumValue(message, field, new_value);
+  //     }
+  // }
+  virtual bool SupportsUnknownEnumValues() const { return false; }
+
+  // Returns the MessageFactory associated with this message.  This can be
+  // useful for determining if a message is a generated message or not, for
+  // example:
+  //
+  // if (message->GetReflection()->GetMessageFactory() ==
+  //     google::protobuf::MessageFactory::generated_factory()) {
+  //   // This is a generated message.
+  // }
+  //
+  // It can also be used to create more messages of this type, though
+  // Message::New() is an easier way to accomplish this.
+  virtual MessageFactory* GetMessageFactory() const;
+
+  // ---------------------------------------------------------------------------
+
+ protected:
+  // Obtain a pointer to a Repeated Field Structure and do some type checking:
+  //   on field->cpp_type(),
+  //   on field->field_option().ctype() (if ctype >= 0)
+  //   of field->message_type() (if message_type != NULL).
+  // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer).
+  virtual void* MutableRawRepeatedField(
+      Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+      int ctype, const Descriptor* message_type) const = 0;
+
+  // TODO(jieluo) - make it pure virtual after updating all the subclasses.
+  virtual const void* GetRawRepeatedField(
+      const Message& message, const FieldDescriptor* field,
+      FieldDescriptor::CppType cpptype, int ctype,
+      const Descriptor* message_type) const {
+    return MutableRawRepeatedField(
+        const_cast<Message*>(&message), field, cpptype, ctype, message_type);
+  }
+
+  // The following methods are used to implement (Mutable)RepeatedFieldRef.
+  // A Ref object will store a raw pointer to the repeated field data (obtained
+  // from RepeatedFieldData()) and a pointer to a Accessor (obtained from
+  // RepeatedFieldAccessor) which will be used to access the raw data.
+  //
+  // TODO(xiaofeng): Make these methods pure-virtual.
+
+  // Returns a raw pointer to the repeated field
+  //
+  // "cpp_type" and "message_type" are decuded from the type parameter T passed
+  // to Get(Mutable)RepeatedFieldRef. If T is a generated message type,
+  // "message_type" should be set to its descriptor. Otherwise "message_type"
+  // should be set to NULL. Implementations of this method should check whether
+  // "cpp_type"/"message_type" is consistent with the actual type of the field.
+  // We use 1 routine rather than 2 (const vs mutable) because it is protected
+  // and it doesn't change the message.
+  virtual void* RepeatedFieldData(
+      Message* message, const FieldDescriptor* field,
+      FieldDescriptor::CppType cpp_type,
+      const Descriptor* message_type) const;
+
+  // The returned pointer should point to a singleton instance which implements
+  // the RepeatedFieldAccessor interface.
+  virtual const internal::RepeatedFieldAccessor* RepeatedFieldAccessor(
+      const FieldDescriptor* field) const;
+
+ private:
+  template<typename T, typename Enable>
+  friend class RepeatedFieldRef;
+  template<typename T, typename Enable>
+  friend class MutableRepeatedFieldRef;
+  friend class ::google::protobuf::python::MapReflectionFriend;
+
+  // Special version for specialized implementations of string.  We can't call
+  // MutableRawRepeatedField directly here because we don't have access to
+  // FieldOptions::* which are defined in descriptor.pb.h.  Including that
+  // file here is not possible because it would cause a circular include cycle.
+  // We use 1 routine rather than 2 (const vs mutable) because it is private
+  // and mutable a repeated string field doesn't change the message.
+  void* MutableRawRepeatedString(
+      Message* message, const FieldDescriptor* field, bool is_string) const;
+
+  friend class MapReflectionTester;
+  // TODO(jieluo) - make the map APIs pure virtual after updating
+  // all the subclasses.
+  // Returns true if key is in map. Returns false if key is not in map field.
+  virtual bool ContainsMapKey(const Message& /* message*/,
+                              const FieldDescriptor* /* field */,
+                              const MapKey& /* key */) const {
+    return false;
+  }
+
+  // If key is in map field: Saves the value pointer to val and returns
+  // false. If key in not in map field: Insert the key into map, saves
+  // value pointer to val and retuns true.
+  virtual bool InsertOrLookupMapValue(Message* /* message */,
+                                      const FieldDescriptor* /* field */,
+                                      const MapKey& /* key */,
+                                      MapValueRef* /* val */) const {
+    return false;
+  }
+
+  // Delete and returns true if key is in the map field. Returns false
+  // otherwise.
+  virtual bool DeleteMapValue(Message* /* mesage */,
+                              const FieldDescriptor* /* field */,
+                              const MapKey& /* key */) const {
+    return false;
+  }
+
+  // Returns a MapIterator referring to the first element in the map field.
+  // If the map field is empty, this function returns the same as
+  // reflection::MapEnd. Mutation to the field may invalidate the iterator.
+  virtual MapIterator MapBegin(
+      Message* message,
+      const FieldDescriptor* field) const;
+
+  // Returns a MapIterator referring to the theoretical element that would
+  // follow the last element in the map field. It does not point to any
+  // real element. Mutation to the field may invalidate the iterator.
+  virtual MapIterator MapEnd(
+      Message* message,
+      const FieldDescriptor* field) const;
+
+  // Get the number of <key, value> pair of a map field. The result may be
+  // different from FieldSize which can have duplicate keys.
+  virtual int MapSize(const Message& /* message */,
+                      const FieldDescriptor* /* field */) const {
+    return 0;
+  }
+
+  // Help method for MapIterator.
+  friend class MapIterator;
+  virtual internal::MapFieldBase* MapData(
+      Message* /* message */, const FieldDescriptor* /* field */) const {
+    return NULL;
+  }
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
+};
+
+// Abstract interface for a factory for message objects.
+class LIBPROTOBUF_EXPORT MessageFactory {
+ public:
+  inline MessageFactory() {}
+  virtual ~MessageFactory();
+
+  // Given a Descriptor, gets or constructs the default (prototype) Message
+  // of that type.  You can then call that message's New() method to construct
+  // a mutable message of that type.
+  //
+  // Calling this method twice with the same Descriptor returns the same
+  // object.  The returned object remains property of the factory.  Also, any
+  // objects created by calling the prototype's New() method share some data
+  // with the prototype, so these must be destroyed before the MessageFactory
+  // is destroyed.
+  //
+  // The given descriptor must outlive the returned message, and hence must
+  // outlive the MessageFactory.
+  //
+  // Some implementations do not support all types.  GetPrototype() will
+  // return NULL if the descriptor passed in is not supported.
+  //
+  // This method may or may not be thread-safe depending on the implementation.
+  // Each implementation should document its own degree thread-safety.
+  virtual const Message* GetPrototype(const Descriptor* type) = 0;
+
+  // Gets a MessageFactory which supports all generated, compiled-in messages.
+  // In other words, for any compiled-in type FooMessage, the following is true:
+  //   MessageFactory::generated_factory()->GetPrototype(
+  //     FooMessage::descriptor()) == FooMessage::default_instance()
+  // This factory supports all types which are found in
+  // DescriptorPool::generated_pool().  If given a descriptor from any other
+  // pool, GetPrototype() will return NULL.  (You can also check if a
+  // descriptor is for a generated message by checking if
+  // descriptor->file()->pool() == DescriptorPool::generated_pool().)
+  //
+  // This factory is 100% thread-safe; calling GetPrototype() does not modify
+  // any shared data.
+  //
+  // This factory is a singleton.  The caller must not delete the object.
+  static MessageFactory* generated_factory();
+
+  // For internal use only:  Registers a .proto file at static initialization
+  // time, to be placed in generated_factory.  The first time GetPrototype()
+  // is called with a descriptor from this file, |register_messages| will be
+  // called, with the file name as the parameter.  It must call
+  // InternalRegisterGeneratedMessage() (below) to register each message type
+  // in the file.  This strange mechanism is necessary because descriptors are
+  // built lazily, so we can't register types by their descriptor until we
+  // know that the descriptor exists.  |filename| must be a permanent string.
+  static void InternalRegisterGeneratedFile(
+      const char* filename, void (*register_messages)(const string&));
+
+  // For internal use only:  Registers a message type.  Called only by the
+  // functions which are registered with InternalRegisterGeneratedFile(),
+  // above.
+  static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
+                                               const Message* prototype);
+
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
+};
+
+#define DECLARE_GET_REPEATED_FIELD(TYPE)                         \
+template<>                                                       \
+LIBPROTOBUF_EXPORT                                               \
+const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(   \
+    const Message& message, const FieldDescriptor* field) const; \
+                                                                 \
+template<>                                                       \
+LIBPROTOBUF_EXPORT                                               \
+RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(     \
+    Message* message, const FieldDescriptor* field) const;
+
+DECLARE_GET_REPEATED_FIELD(int32)
+DECLARE_GET_REPEATED_FIELD(int64)
+DECLARE_GET_REPEATED_FIELD(uint32)
+DECLARE_GET_REPEATED_FIELD(uint64)
+DECLARE_GET_REPEATED_FIELD(float)
+DECLARE_GET_REPEATED_FIELD(double)
+DECLARE_GET_REPEATED_FIELD(bool)
+
+#undef DECLARE_GET_REPEATED_FIELD
+
+// =============================================================================
+// Implementation details for {Get,Mutable}RawRepeatedPtrField.  We provide
+// specializations for <string>, <StringPieceField> and <Message> and handle
+// everything else with the default template which will match any type having
+// a method with signature "static const google::protobuf::Descriptor* descriptor()".
+// Such a type presumably is a descendant of google::protobuf::Message.
+
+template<>
+inline const RepeatedPtrField<string>& Reflection::GetRepeatedPtrField<string>(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<RepeatedPtrField<string>* >(
+      MutableRawRepeatedString(const_cast<Message*>(&message), field, true));
+}
+
+template<>
+inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<string>* >(
+      MutableRawRepeatedString(message, field, true));
+}
+
+
+// -----
+
+template<>
+inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<const RepeatedPtrField<Message>* >(
+      GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+                          -1, NULL));
+}
+
+template<>
+inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<Message>* >(
+      MutableRawRepeatedField(message, field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          NULL));
+}
+
+template<typename PB>
+inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<const RepeatedPtrField<PB>* >(
+      GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+                          -1, PB::default_instance().GetDescriptor()));
+}
+
+template<typename PB>
+inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<PB>* >(
+      MutableRawRepeatedField(message, field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          PB::default_instance().GetDescriptor()));
+}
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MESSAGE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/message_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/message_lite.cc
new file mode 100644
index 0000000..9d7b64f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/message_lite.cc
@@ -0,0 +1,372 @@
+// 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.
+
+// Authors: wink@google.com (Wink Saville),
+//          kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/repeated_field.h>
+#include <string>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+
+MessageLite::~MessageLite() {}
+
+string MessageLite::InitializationErrorString() const {
+  return "(cannot determine missing fields for lite message)";
+}
+
+namespace {
+
+// When serializing, we first compute the byte size, then serialize the message.
+// If serialization produces a different number of bytes than expected, we
+// call this function, which crashes.  The problem could be due to a bug in the
+// protobuf implementation but is more likely caused by concurrent modification
+// of the message.  This function attempts to distinguish between the two and
+// provide a useful error message.
+void ByteSizeConsistencyError(int byte_size_before_serialization,
+                              int byte_size_after_serialization,
+                              int bytes_produced_by_serialization,
+                              const MessageLite& message) {
+  GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
+      << message.GetTypeName()
+      << " was modified concurrently during serialization.";
+  GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
+      << "Byte size calculation and serialization were inconsistent.  This "
+         "may indicate a bug in protocol buffers or it may be caused by "
+         "concurrent modification of " << message.GetTypeName() << ".";
+  GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
+}
+
+string InitializationErrorMessage(const char* action,
+                                  const MessageLite& message) {
+  // Note:  We want to avoid depending on strutil in the lite library, otherwise
+  //   we'd use:
+  //
+  // return strings::Substitute(
+  //   "Can't $0 message of type \"$1\" because it is missing required "
+  //   "fields: $2",
+  //   action, message.GetTypeName(),
+  //   message.InitializationErrorString());
+
+  string result;
+  result += "Can't ";
+  result += action;
+  result += " message of type \"";
+  result += message.GetTypeName();
+  result += "\" because it is missing required fields: ";
+  result += message.InitializationErrorString();
+  return result;
+}
+
+// Several of the Parse methods below just do one thing and then call another
+// method.  In a naive implementation, we might have ParseFromString() call
+// ParseFromArray() which would call ParseFromZeroCopyStream() which would call
+// ParseFromCodedStream() which would call MergeFromCodedStream() which would
+// call MergePartialFromCodedStream().  However, when parsing very small
+// messages, every function call introduces significant overhead.  To avoid
+// this without reproducing code, we use these forced-inline helpers.
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
+    io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
+    io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
+    io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
+    const void* data, int size, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
+    const void* data, int size, MessageLite* message);
+
+inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
+                                       MessageLite* message) {
+  if (!message->MergePartialFromCodedStream(input)) return false;
+  if (!message->IsInitialized()) {
+    GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
+    return false;
+  }
+  return true;
+}
+
+inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
+                                       MessageLite* message) {
+  message->Clear();
+  return InlineMergeFromCodedStream(input, message);
+}
+
+inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
+                                              MessageLite* message) {
+  message->Clear();
+  return message->MergePartialFromCodedStream(input);
+}
+
+inline bool InlineParseFromArray(
+    const void* data, int size, MessageLite* message) {
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
+  return InlineParseFromCodedStream(&input, message) &&
+         input.ConsumedEntireMessage();
+}
+
+inline bool InlineParsePartialFromArray(
+    const void* data, int size, MessageLite* message) {
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
+  return InlineParsePartialFromCodedStream(&input, message) &&
+         input.ConsumedEntireMessage();
+}
+
+}  // namespace
+
+
+MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
+  MessageLite* message = New();
+  if (arena != NULL) {
+    arena->Own(message);
+  }
+  return message;
+}
+
+bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
+  return InlineMergeFromCodedStream(input, this);
+}
+
+bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
+  return InlineParseFromCodedStream(input, this);
+}
+
+bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
+  return InlineParsePartialFromCodedStream(input, this);
+}
+
+bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
+  io::CodedInputStream decoder(input);
+  return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
+}
+
+bool MessageLite::ParsePartialFromZeroCopyStream(
+    io::ZeroCopyInputStream* input) {
+  io::CodedInputStream decoder(input);
+  return ParsePartialFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage();
+}
+
+bool MessageLite::ParseFromBoundedZeroCopyStream(
+    io::ZeroCopyInputStream* input, int size) {
+  io::CodedInputStream decoder(input);
+  decoder.PushLimit(size);
+  return ParseFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage() &&
+         decoder.BytesUntilLimit() == 0;
+}
+
+bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
+    io::ZeroCopyInputStream* input, int size) {
+  io::CodedInputStream decoder(input);
+  decoder.PushLimit(size);
+  return ParsePartialFromCodedStream(&decoder) &&
+         decoder.ConsumedEntireMessage() &&
+         decoder.BytesUntilLimit() == 0;
+}
+
+bool MessageLite::ParseFromString(const string& data) {
+  return InlineParseFromArray(data.data(), data.size(), this);
+}
+
+bool MessageLite::ParsePartialFromString(const string& data) {
+  return InlineParsePartialFromArray(data.data(), data.size(), this);
+}
+
+bool MessageLite::ParseFromArray(const void* data, int size) {
+  return InlineParseFromArray(data, size, this);
+}
+
+bool MessageLite::ParsePartialFromArray(const void* data, int size) {
+  return InlineParsePartialFromArray(data, size, this);
+}
+
+
+// ===================================================================
+
+uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
+  // We only optimize this when using optimize_for = SPEED.  In other cases
+  // we just use the CodedOutputStream path.
+  int size = GetCachedSize();
+  io::ArrayOutputStream out(target, size);
+  io::CodedOutputStream coded_out(&out);
+  SerializeWithCachedSizes(&coded_out);
+  GOOGLE_CHECK(!coded_out.HadError());
+  return target + size;
+}
+
+bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return SerializePartialToCodedStream(output);
+}
+
+bool MessageLite::SerializePartialToCodedStream(
+    io::CodedOutputStream* output) const {
+  const int size = ByteSize();  // Force size to be cached.
+  if (size < 0) {
+    // Messages >2G cannot be serialized due to overflow computing ByteSize.
+    GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
+    return false;
+  }
+
+  uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
+  if (buffer != NULL) {
+    uint8* end = SerializeWithCachedSizesToArray(buffer);
+    if (end - buffer != size) {
+      ByteSizeConsistencyError(size, ByteSize(), end - buffer, *this);
+    }
+    return true;
+  } else {
+    int original_byte_count = output->ByteCount();
+    SerializeWithCachedSizes(output);
+    if (output->HadError()) {
+      return false;
+    }
+    int final_byte_count = output->ByteCount();
+
+    if (final_byte_count - original_byte_count != size) {
+      ByteSizeConsistencyError(size, ByteSize(),
+                               final_byte_count - original_byte_count, *this);
+    }
+
+    return true;
+  }
+}
+
+bool MessageLite::SerializeToZeroCopyStream(
+    io::ZeroCopyOutputStream* output) const {
+  io::CodedOutputStream encoder(output);
+  return SerializeToCodedStream(&encoder);
+}
+
+bool MessageLite::SerializePartialToZeroCopyStream(
+    io::ZeroCopyOutputStream* output) const {
+  io::CodedOutputStream encoder(output);
+  return SerializePartialToCodedStream(&encoder);
+}
+
+bool MessageLite::AppendToString(string* output) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return AppendPartialToString(output);
+}
+
+bool MessageLite::AppendPartialToString(string* output) const {
+  int old_size = output->size();
+  int byte_size = ByteSize();
+  if (byte_size < 0) {
+    // Messages >2G cannot be serialized due to overflow computing ByteSize.
+    GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
+    return false;
+  }
+
+  STLStringResizeUninitialized(output, old_size + byte_size);
+  uint8* start =
+      reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
+  uint8* end = SerializeWithCachedSizesToArray(start);
+  if (end - start != byte_size) {
+    ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
+  }
+  return true;
+}
+
+bool MessageLite::SerializeToString(string* output) const {
+  output->clear();
+  return AppendToString(output);
+}
+
+bool MessageLite::SerializePartialToString(string* output) const {
+  output->clear();
+  return AppendPartialToString(output);
+}
+
+bool MessageLite::SerializeToArray(void* data, int size) const {
+  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+  return SerializePartialToArray(data, size);
+}
+
+bool MessageLite::SerializePartialToArray(void* data, int size) const {
+  int byte_size = ByteSize();
+  if (size < byte_size) return false;
+  uint8* start = reinterpret_cast<uint8*>(data);
+  uint8* end = SerializeWithCachedSizesToArray(start);
+  if (end - start != byte_size) {
+    ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
+  }
+  return true;
+}
+
+string MessageLite::SerializeAsString() const {
+  // If the compiler implements the (Named) Return Value Optimization,
+  // the local variable 'output' will not actually reside on the stack
+  // of this function, but will be overlaid with the object that the
+  // caller supplied for the return value to be constructed in.
+  string output;
+  if (!AppendToString(&output))
+    output.clear();
+  return output;
+}
+
+string MessageLite::SerializePartialAsString() const {
+  string output;
+  if (!AppendPartialToString(&output))
+    output.clear();
+  return output;
+}
+
+namespace internal {
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+    const MessageLite* prototype, google::protobuf::Arena* arena) {
+  return prototype->New(arena);
+}
+template <>
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+                                            MessageLite* to) {
+  to->CheckTypeAndMergeFrom(from);
+}
+template<>
+void GenericTypeHandler<string>::Merge(const string& from,
+                                              string* to) {
+  *to = from;
+}
+}  // namespace internal
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/message_lite.h b/src/third_party/protobuf-3/src/google/protobuf/message_lite.h
new file mode 100644
index 0000000..4c16f4c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/message_lite.h
@@ -0,0 +1,277 @@
+// 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.
+
+// Authors: wink@google.com (Wink Saville),
+//          kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Defines MessageLite, the abstract interface implemented by all (lite
+// and non-lite) protocol message objects.
+
+#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
+
+#include <google/protobuf/stubs/common.h>
+
+
+namespace google {
+namespace protobuf {
+  class Arena;
+namespace io {
+  class CodedInputStream;
+  class CodedOutputStream;
+  class ZeroCopyInputStream;
+  class ZeroCopyOutputStream;
+}
+
+// Interface to light weight protocol messages.
+//
+// This interface is implemented by all protocol message objects.  Non-lite
+// messages additionally implement the Message interface, which is a
+// subclass of MessageLite.  Use MessageLite instead when you only need
+// the subset of features which it supports -- namely, nothing that uses
+// descriptors or reflection.  You can instruct the protocol compiler
+// to generate classes which implement only MessageLite, not the full
+// Message interface, by adding the following line to the .proto file:
+//
+//   option optimize_for = LITE_RUNTIME;
+//
+// This is particularly useful on resource-constrained systems where
+// the full protocol buffers runtime library is too big.
+//
+// Note that on non-constrained systems (e.g. servers) when you need
+// to link in lots of protocol definitions, a better way to reduce
+// total code footprint is to use optimize_for = CODE_SIZE.  This
+// will make the generated code smaller while still supporting all the
+// same features (at the expense of speed).  optimize_for = LITE_RUNTIME
+// is best when you only have a small number of message types linked
+// into your binary, in which case the size of the protocol buffers
+// runtime itself is the biggest problem.
+class LIBPROTOBUF_EXPORT MessageLite {
+ public:
+  inline MessageLite() {}
+  virtual ~MessageLite();
+
+  // Basic Operations ------------------------------------------------
+
+  // Get the name of this message type, e.g. "foo.bar.BazProto".
+  virtual string GetTypeName() const = 0;
+
+  // Construct a new instance of the same type.  Ownership is passed to the
+  // caller.
+  virtual MessageLite* New() const = 0;
+
+  // Construct a new instance on the arena. Ownership is passed to the caller
+  // if arena is a NULL. Default implementation for backwards compatibility.
+  virtual MessageLite* New(::google::protobuf::Arena* arena) const;
+
+  // Get the arena, if any, associated with this message. Virtual method
+  // required for generic operations but most arena-related operations should
+  // use the GetArenaNoVirtual() generated-code method. Default implementation
+  // to reduce code size by avoiding the need for per-type implementations when
+  // types do not implement arena support.
+  virtual ::google::protobuf::Arena* GetArena() const { return NULL; }
+
+  // Get a pointer that may be equal to this message's arena, or may not be. If
+  // the value returned by this method is equal to some arena pointer, then this
+  // message is on that arena; however, if this message is on some arena, this
+  // method may or may not return that arena's pointer. As a tradeoff, this
+  // method may be more efficient than GetArena(). The intent is to allow
+  // underlying representations that use e.g. tagged pointers to sometimes store
+  // the arena pointer directly, and sometimes in a more indirect way, and allow
+  // a fastpath comparison against the arena pointer when it's easy to obtain.
+  virtual void* GetMaybeArenaPointer() const { return GetArena(); }
+
+  // Clear all fields of the message and set them to their default values.
+  // Clear() avoids freeing memory, assuming that any memory allocated
+  // to hold parts of the message will be needed again to hold the next
+  // message.  If you actually want to free the memory used by a Message,
+  // you must delete it.
+  virtual void Clear() = 0;
+
+  // Quickly check if all required fields have values set.
+  virtual bool IsInitialized() const = 0;
+
+  // This is not implemented for Lite messages -- it just returns "(cannot
+  // determine missing fields for lite message)".  However, it is implemented
+  // for full messages.  See message.h.
+  virtual string InitializationErrorString() const;
+
+  // If |other| is the exact same class as this, calls MergeFrom().  Otherwise,
+  // results are undefined (probably crash).
+  virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
+
+  // Parsing ---------------------------------------------------------
+  // Methods for parsing in protocol buffer format.  Most of these are
+  // just simple wrappers around MergeFromCodedStream().  Clear() will be called
+  // before merging the input.
+
+  // Fill the message with a protocol buffer parsed from the given input stream.
+  // Returns false on a read error or if the input is in the wrong format.  A
+  // successful return does not indicate the entire input is consumed, ensure
+  // you call ConsumedEntireMessage() to check that if applicable.
+  bool ParseFromCodedStream(io::CodedInputStream* input);
+  // Like ParseFromCodedStream(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromCodedStream(io::CodedInputStream* input);
+  // Read a protocol buffer from the given zero-copy input stream.  If
+  // successful, the entire input will be consumed.
+  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  // Like ParseFromZeroCopyStream(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  // Read a protocol buffer from the given zero-copy input stream, expecting
+  // the message to be exactly "size" bytes long.  If successful, exactly
+  // this many bytes will have been consumed from the input.
+  bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
+  // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
+  // missing required fields.
+  bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
+                                             int size);
+  // Parses a protocol buffer contained in a string. Returns true on success.
+  // This function takes a string in the (non-human-readable) binary wire
+  // format, matching the encoding output by MessageLite::SerializeToString().
+  // If you'd like to convert a human-readable string into a protocol buffer
+  // object, see google::protobuf::TextFormat::ParseFromString().
+  bool ParseFromString(const string& data);
+  // Like ParseFromString(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromString(const string& data);
+  // Parse a protocol buffer contained in an array of bytes.
+  bool ParseFromArray(const void* data, int size);
+  // Like ParseFromArray(), but accepts messages that are missing
+  // required fields.
+  bool ParsePartialFromArray(const void* data, int size);
+
+
+  // Reads a protocol buffer from the stream and merges it into this
+  // Message.  Singular fields read from the input overwrite what is
+  // already in the Message and repeated fields are appended to those
+  // already present.
+  //
+  // It is the responsibility of the caller to call input->LastTagWas()
+  // (for groups) or input->ConsumedEntireMessage() (for non-groups) after
+  // this returns to verify that the message's end was delimited correctly.
+  //
+  // ParsefromCodedStream() is implemented as Clear() followed by
+  // MergeFromCodedStream().
+  bool MergeFromCodedStream(io::CodedInputStream* input);
+
+  // Like MergeFromCodedStream(), but succeeds even if required fields are
+  // missing in the input.
+  //
+  // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
+  // followed by IsInitialized().
+  virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
+
+
+  // Serialization ---------------------------------------------------
+  // Methods for serializing in protocol buffer format.  Most of these
+  // are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
+
+  // Write a protocol buffer of this message to the given output.  Returns
+  // false on a write error.  If the message is missing required fields,
+  // this may GOOGLE_CHECK-fail.
+  bool SerializeToCodedStream(io::CodedOutputStream* output) const;
+  // Like SerializeToCodedStream(), but allows missing required fields.
+  bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
+  // Write the message to the given zero-copy output stream.  All required
+  // fields must be set.
+  bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
+  // Like SerializeToZeroCopyStream(), but allows missing required fields.
+  bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
+  // Serialize the message and store it in the given string.  All required
+  // fields must be set.
+  bool SerializeToString(string* output) const;
+  // Like SerializeToString(), but allows missing required fields.
+  bool SerializePartialToString(string* output) const;
+  // Serialize the message and store it in the given byte array.  All required
+  // fields must be set.
+  bool SerializeToArray(void* data, int size) const;
+  // Like SerializeToArray(), but allows missing required fields.
+  bool SerializePartialToArray(void* data, int size) const;
+
+  // Make a string encoding the message. Is equivalent to calling
+  // SerializeToString() on a string and using that.  Returns the empty
+  // string if SerializeToString() would have returned an error.
+  // Note: If you intend to generate many such strings, you may
+  // reduce heap fragmentation by instead re-using the same string
+  // object with calls to SerializeToString().
+  string SerializeAsString() const;
+  // Like SerializeAsString(), but allows missing required fields.
+  string SerializePartialAsString() const;
+
+  // Like SerializeToString(), but appends to the data to the string's existing
+  // contents.  All required fields must be set.
+  bool AppendToString(string* output) const;
+  // Like AppendToString(), but allows missing required fields.
+  bool AppendPartialToString(string* output) const;
+
+  // Computes the serialized size of the message.  This recursively calls
+  // ByteSize() on all embedded messages.  If a subclass does not override
+  // this, it MUST override SetCachedSize().
+  //
+  // ByteSize() is generally linear in the number of fields defined for the
+  // proto.
+  virtual int ByteSize() const = 0;
+
+  // Serializes the message without recomputing the size.  The message must
+  // not have changed since the last call to ByteSize(); if it has, the results
+  // are undefined.
+  virtual void SerializeWithCachedSizes(
+      io::CodedOutputStream* output) const = 0;
+
+  // Like SerializeWithCachedSizes, but writes directly to *target, returning
+  // a pointer to the byte immediately after the last byte written.  "target"
+  // must point at a byte array of at least ByteSize() bytes.
+  virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
+
+  // Returns the result of the last call to ByteSize().  An embedded message's
+  // size is needed both to serialize it (because embedded messages are
+  // length-delimited) and to compute the outer message's size.  Caching
+  // the size avoids computing it multiple times.
+  //
+  // ByteSize() does not automatically use the cached size when available
+  // because this would require invalidating it every time the message was
+  // modified, which would be too hard and expensive.  (E.g. if a deeply-nested
+  // sub-message is changed, all of its parents' cached sizes would need to be
+  // invalidated, which is too much work for an otherwise inlined setter
+  // method.)
+  virtual int GetCachedSize() const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/message_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/message_unittest.cc
new file mode 100644
index 0000000..d668a1a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/message_unittest.cc
@@ -0,0 +1,471 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/message.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <sstream>
+#include <fstream>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
+#endif
+#endif
+
+TEST(MessageTest, SerializeHelpers) {
+  // TODO(kenton):  Test more helpers?  They're all two-liners so it seems
+  //   like a waste of time.
+
+  protobuf_unittest::TestAllTypes message;
+  TestUtil::SetAllFields(&message);
+  stringstream stream;
+
+  string str1("foo");
+  string str2("bar");
+
+  EXPECT_TRUE(message.SerializeToString(&str1));
+  EXPECT_TRUE(message.AppendToString(&str2));
+  EXPECT_TRUE(message.SerializeToOstream(&stream));
+
+  EXPECT_EQ(str1.size() + 3, str2.size());
+  EXPECT_EQ("bar", str2.substr(0, 3));
+  // Don't use EXPECT_EQ because we don't want to dump raw binary data to
+  // stdout.
+  EXPECT_TRUE(str2.substr(3) == str1);
+
+  // GCC gives some sort of error if we try to just do stream.str() == str1.
+  string temp = stream.str();
+  EXPECT_TRUE(temp == str1);
+
+  EXPECT_TRUE(message.SerializeAsString() == str1);
+
+}
+
+TEST(MessageTest, SerializeToBrokenOstream) {
+  ofstream out;
+  protobuf_unittest::TestAllTypes message;
+  message.set_optional_int32(123);
+
+  EXPECT_FALSE(message.SerializeToOstream(&out));
+}
+
+TEST(MessageTest, ParseFromFileDescriptor) {
+  string filename = TestSourceDir() +
+                    "/google/protobuf/testdata/golden_message";
+  int file = open(filename.c_str(), O_RDONLY | O_BINARY);
+
+  unittest::TestAllTypes message;
+  EXPECT_TRUE(message.ParseFromFileDescriptor(file));
+  TestUtil::ExpectAllFieldsSet(message);
+
+  EXPECT_GE(close(file), 0);
+}
+
+TEST(MessageTest, ParsePackedFromFileDescriptor) {
+  string filename =
+      TestSourceDir() +
+      "/google/protobuf/testdata/golden_packed_fields_message";
+  int file = open(filename.c_str(), O_RDONLY | O_BINARY);
+
+  unittest::TestPackedTypes message;
+  EXPECT_TRUE(message.ParseFromFileDescriptor(file));
+  TestUtil::ExpectPackedFieldsSet(message);
+
+  EXPECT_GE(close(file), 0);
+}
+
+TEST(MessageTest, ParseHelpers) {
+  // TODO(kenton):  Test more helpers?  They're all two-liners so it seems
+  //   like a waste of time.
+  string data;
+
+  {
+    // Set up.
+    protobuf_unittest::TestAllTypes message;
+    TestUtil::SetAllFields(&message);
+    message.SerializeToString(&data);
+  }
+
+  {
+    // Test ParseFromString.
+    protobuf_unittest::TestAllTypes message;
+    EXPECT_TRUE(message.ParseFromString(data));
+    TestUtil::ExpectAllFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromIstream.
+    protobuf_unittest::TestAllTypes message;
+    stringstream stream(data);
+    EXPECT_TRUE(message.ParseFromIstream(&stream));
+    EXPECT_TRUE(stream.eof());
+    TestUtil::ExpectAllFieldsSet(message);
+  }
+
+  {
+    // Test ParseFromBoundedZeroCopyStream.
+    string data_with_junk(data);
+    data_with_junk.append("some junk on the end");
+    io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size());
+    protobuf_unittest::TestAllTypes message;
+    EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size()));
+    TestUtil::ExpectAllFieldsSet(message);
+  }
+
+  {
+    // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if
+    // EOF is reached before the expected number of bytes.
+    io::ArrayInputStream stream(data.data(), data.size());
+    protobuf_unittest::TestAllTypes message;
+    EXPECT_FALSE(
+      message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1));
+  }
+}
+
+TEST(MessageTest, ParseFailsIfNotInitialized) {
+  unittest::TestRequired message;
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog log;
+    EXPECT_FALSE(message.ParseFromString(""));
+    errors = log.GetMessages(ERROR);
+  }
+
+  ASSERT_EQ(1, errors.size());
+  EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" "
+            "because it is missing required fields: a, b, c",
+            errors[0]);
+}
+
+TEST(MessageTest, BypassInitializationCheckOnParse) {
+  unittest::TestRequired message;
+  io::ArrayInputStream raw_input(NULL, 0);
+  io::CodedInputStream input(&raw_input);
+  EXPECT_TRUE(message.MergePartialFromCodedStream(&input));
+}
+
+TEST(MessageTest, InitializationErrorString) {
+  unittest::TestRequired message;
+  EXPECT_EQ("a, b, c", message.InitializationErrorString());
+}
+
+TEST(MessageTest, DynamicCastToGenerated) {
+  unittest::TestAllTypes test_all_types;
+
+  google::protobuf::Message* test_all_types_pointer = &test_all_types;
+  EXPECT_EQ(&test_all_types,
+            google::protobuf::internal::DynamicCastToGenerated<unittest::TestAllTypes>(
+                test_all_types_pointer));
+  EXPECT_EQ(NULL,
+            google::protobuf::internal::DynamicCastToGenerated<unittest::TestRequired>(
+                test_all_types_pointer));
+
+  const google::protobuf::Message* test_all_types_pointer_const = &test_all_types;
+  EXPECT_EQ(
+      &test_all_types,
+      google::protobuf::internal::DynamicCastToGenerated<const unittest::TestAllTypes>(
+          test_all_types_pointer_const));
+  EXPECT_EQ(
+      NULL,
+      google::protobuf::internal::DynamicCastToGenerated<const unittest::TestRequired>(
+          test_all_types_pointer_const));
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet.
+
+TEST(MessageTest, SerializeFailsIfNotInitialized) {
+  unittest::TestRequired message;
+  string data;
+  EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)),
+    "Can't serialize message of type \"protobuf_unittest.TestRequired\" because "
+    "it is missing required fields: a, b, c");
+}
+
+TEST(MessageTest, CheckInitialized) {
+  unittest::TestRequired message;
+  EXPECT_DEATH(message.CheckInitialized(),
+    "Message of type \"protobuf_unittest.TestRequired\" is missing required "
+    "fields: a, b, c");
+}
+
+TEST(MessageTest, CheckOverflow) {
+  unittest::TestAllTypes message;
+  // Create a message with size just over 2GB. This triggers integer overflow
+  // when computing message size.
+  const string data(1024, 'x');
+  Cord one_megabyte;
+  for (int i = 0; i < 1024; i++) {
+    one_megabyte.Append(data);
+  }
+
+  for (int i = 0; i < 2 * 1024 + 1; ++i) {
+    message.add_repeated_cord()->CopyFrom(one_megabyte);
+  }
+
+  Cord serialized;
+  EXPECT_FALSE(message.AppendToCord(&serialized));
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+namespace {
+
+class NegativeByteSize : public unittest::TestRequired {
+ public:
+  virtual int ByteSize() const { return -1; }
+};
+
+}  // namespace
+
+TEST(MessageTest, SerializationFailsOnNegativeByteSize) {
+  NegativeByteSize message;
+  string string_output;
+  EXPECT_FALSE(message.AppendPartialToString(&string_output));
+
+  io::ArrayOutputStream coded_raw_output(NULL, 100);
+  io::CodedOutputStream coded_output(&coded_raw_output);
+  EXPECT_FALSE(message.SerializePartialToCodedStream(&coded_output));
+}
+
+TEST(MessageTest, BypassInitializationCheckOnSerialize) {
+  unittest::TestRequired message;
+  io::ArrayOutputStream raw_output(NULL, 0);
+  io::CodedOutputStream output(&raw_output);
+  EXPECT_TRUE(message.SerializePartialToCodedStream(&output));
+}
+
+TEST(MessageTest, FindInitializationErrors) {
+  unittest::TestRequired message;
+  vector<string> errors;
+  message.FindInitializationErrors(&errors);
+  ASSERT_EQ(3, errors.size());
+  EXPECT_EQ("a", errors[0]);
+  EXPECT_EQ("b", errors[1]);
+  EXPECT_EQ("c", errors[2]);
+}
+
+TEST(MessageTest, ParseFailsOnInvalidMessageEnd) {
+  unittest::TestAllTypes message;
+
+  // Control case.
+  EXPECT_TRUE(message.ParseFromArray("", 0));
+
+  // The byte is a valid varint, but not a valid tag (zero).
+  EXPECT_FALSE(message.ParseFromArray("\0", 1));
+
+  // The byte is a malformed varint.
+  EXPECT_FALSE(message.ParseFromArray("\200", 1));
+
+  // The byte is an endgroup tag, but we aren't parsing a group.
+  EXPECT_FALSE(message.ParseFromArray("\014", 1));
+}
+
+namespace {
+
+void ExpectMessageMerged(const unittest::TestAllTypes& message) {
+  EXPECT_EQ(3, message.optional_int32());
+  EXPECT_EQ(2, message.optional_int64());
+  EXPECT_EQ("hello", message.optional_string());
+}
+
+void AssignParsingMergeMessages(
+    unittest::TestAllTypes* msg1,
+    unittest::TestAllTypes* msg2,
+    unittest::TestAllTypes* msg3) {
+  msg1->set_optional_int32(1);
+  msg2->set_optional_int64(2);
+  msg3->set_optional_int32(3);
+  msg3->set_optional_string("hello");
+}
+
+}  // namespace
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+TEST(MessageTest, ParsingMerge) {
+  unittest::TestParsingMerge::RepeatedFieldsGenerator generator;
+  unittest::TestAllTypes* msg1;
+  unittest::TestAllTypes* msg2;
+  unittest::TestAllTypes* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD)                \
+  msg1 = generator.add_##FIELD();                   \
+  msg2 = generator.add_##FIELD();                   \
+  msg3 = generator.add_##FIELD();                   \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+  ASSIGN_REPEATED_FIELD(field1);
+  ASSIGN_REPEATED_FIELD(field2);
+  ASSIGN_REPEATED_FIELD(field3);
+  ASSIGN_REPEATED_FIELD(ext1);
+  ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD)                \
+  msg1 = generator.add_##FIELD()->mutable_field1(); \
+  msg2 = generator.add_##FIELD()->mutable_field1(); \
+  msg3 = generator.add_##FIELD()->mutable_field1(); \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+  ASSIGN_REPEATED_GROUP(group1);
+  ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+  string buffer;
+  generator.SerializeToString(&buffer);
+  unittest::TestParsingMerge parsing_merge;
+  parsing_merge.ParseFromString(buffer);
+
+  // Required and optional fields should be merged.
+  ExpectMessageMerged(parsing_merge.required_all_types());
+  ExpectMessageMerged(parsing_merge.optional_all_types());
+  ExpectMessageMerged(
+      parsing_merge.optionalgroup().optional_group_all_types());
+  ExpectMessageMerged(
+      parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext));
+
+  // Repeated fields should not be merged.
+  EXPECT_EQ(3, parsing_merge.repeated_all_types_size());
+  EXPECT_EQ(3, parsing_merge.repeatedgroup_size());
+  EXPECT_EQ(3, parsing_merge.ExtensionSize(
+      unittest::TestParsingMerge::repeated_ext));
+}
+
+TEST(MessageTest, MergeFrom) {
+  unittest::TestAllTypes source;
+  unittest::TestAllTypes dest;
+
+  // Optional fields
+  source.set_optional_int32(1);  // only source
+  source.set_optional_int64(2);  // both source and dest
+  dest.set_optional_int64(3);
+  dest.set_optional_uint32(4);   // only dest
+
+  // Optional fields with defaults
+  source.set_default_int32(13);  // only source
+  source.set_default_int64(14);  // both source and dest
+  dest.set_default_int64(15);
+  dest.set_default_uint32(16);   // only dest
+
+  // Repeated fields
+  source.add_repeated_int32(5);  // only source
+  source.add_repeated_int32(6);
+  source.add_repeated_int64(7);  // both source and dest
+  source.add_repeated_int64(8);
+  dest.add_repeated_int64(9);
+  dest.add_repeated_int64(10);
+  dest.add_repeated_uint32(11);  // only dest
+  dest.add_repeated_uint32(12);
+
+  dest.MergeFrom(source);
+
+  // Optional fields: source overwrites dest if source is specified
+  EXPECT_EQ(1, dest.optional_int32());  // only source: use source
+  EXPECT_EQ(2, dest.optional_int64());  // source and dest: use source
+  EXPECT_EQ(4, dest.optional_uint32());  // only dest: use dest
+  EXPECT_EQ(0, dest.optional_uint64());  // neither: use default
+
+  // Optional fields with defaults
+  EXPECT_EQ(13, dest.default_int32());  // only source: use source
+  EXPECT_EQ(14, dest.default_int64());  // source and dest: use source
+  EXPECT_EQ(16, dest.default_uint32());  // only dest: use dest
+  EXPECT_EQ(44, dest.default_uint64());  // neither: use default
+
+  // Repeated fields: concatenate source onto the end of dest
+  ASSERT_EQ(2, dest.repeated_int32_size());
+  EXPECT_EQ(5, dest.repeated_int32(0));
+  EXPECT_EQ(6, dest.repeated_int32(1));
+  ASSERT_EQ(4, dest.repeated_int64_size());
+  EXPECT_EQ(9,  dest.repeated_int64(0));
+  EXPECT_EQ(10, dest.repeated_int64(1));
+  EXPECT_EQ(7,  dest.repeated_int64(2));
+  EXPECT_EQ(8,  dest.repeated_int64(3));
+  ASSERT_EQ(2, dest.repeated_uint32_size());
+  EXPECT_EQ(11, dest.repeated_uint32(0));
+  EXPECT_EQ(12, dest.repeated_uint32(1));
+  ASSERT_EQ(0, dest.repeated_uint64_size());
+}
+
+TEST(MessageFactoryTest, GeneratedFactoryLookup) {
+  EXPECT_EQ(
+    MessageFactory::generated_factory()->GetPrototype(
+      protobuf_unittest::TestAllTypes::descriptor()),
+    &protobuf_unittest::TestAllTypes::default_instance());
+}
+
+TEST(MessageFactoryTest, GeneratedFactoryUnknownType) {
+  // Construct a new descriptor.
+  DescriptorPool pool;
+  FileDescriptorProto file;
+  file.set_name("foo.proto");
+  file.add_message_type()->set_name("Foo");
+  const Descriptor* descriptor = pool.BuildFile(file)->message_type(0);
+
+  // Trying to construct it should return NULL.
+  EXPECT_TRUE(
+    MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL);
+}
+
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/metadata.h b/src/third_party/protobuf-3/src/google/protobuf/metadata.h
new file mode 100644
index 0000000..fdee150
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/metadata.h
@@ -0,0 +1,163 @@
+// 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.
+
+// This header file defines an internal class that encapsulates internal message
+// metadata (Unknown-field set, Arena pointer, ...) and allows its
+// representation to be made more space-efficient via various optimizations.
+//
+// Note that this is distinct from google::protobuf::Metadata, which encapsulates
+// Descriptor and Reflection pointers.
+
+#ifndef GOOGLE_PROTOBUF_METADATA_H__
+#define GOOGLE_PROTOBUF_METADATA_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/unknown_field_set.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This is the representation for messages that support arena allocation. It
+// uses a tagged pointer to either store the Arena pointer, if there are no
+// unknown fields, or a pointer to a block of memory with both the Arena pointer
+// and the UnknownFieldSet, if there are unknown fields. This optimization
+// allows for "zero-overhead" storage of the Arena pointer, relative to the
+// above baseline implementation.
+//
+// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
+// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
+// pointer.
+class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
+ public:
+  InternalMetadataWithArena() : ptr_(NULL) {}
+  explicit InternalMetadataWithArena(Arena* arena)
+      : ptr_ (arena) {}
+
+  ~InternalMetadataWithArena() {
+    if (have_unknown_fields() && arena() == NULL) {
+      delete PtrValue<Container>();
+    }
+    ptr_ = NULL;
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const {
+    if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
+      return PtrValue<Container>()->unknown_fields_;
+    } else {
+      return *UnknownFieldSet::default_instance();
+    }
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() {
+    if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
+      return &PtrValue<Container>()->unknown_fields_;
+    } else {
+      return mutable_unknown_fields_slow();
+    }
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const {
+    if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
+      return PtrValue<Container>()->arena_;
+    } else {
+      return PtrValue<Arena>();
+    }
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const {
+    return PtrTag() == kTagContainer;
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) {
+    // Semantics here are that we swap only the unknown fields, not the arena
+    // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
+    // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
+    // different states (direct arena pointer vs. container with UFS) so we
+    // cannot simply swap ptr_ and then restore the arena pointers. We reuse
+    // UFS's swap implementation instead.
+    if (have_unknown_fields() || other->have_unknown_fields()) {
+      mutable_unknown_fields()->Swap(other->mutable_unknown_fields());
+    }
+  }
+
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const {
+    return ptr_;
+  }
+
+ private:
+  void* ptr_;
+
+  // Tagged pointer implementation.
+  enum {
+    // ptr_ is an Arena*.
+    kTagArena = 0,
+    // ptr_ is a Container*.
+    kTagContainer = 1,
+  };
+  static const intptr_t kPtrTagMask = 1;
+  static const intptr_t kPtrValueMask = ~kPtrTagMask;
+
+  // Accessors for pointer tag and pointer value.
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const {
+    return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
+  }
+
+  template<typename T> T* PtrValue() const {
+    return reinterpret_cast<T*>(
+        reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask);
+  }
+
+  // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
+  struct Container {
+    UnknownFieldSet unknown_fields_;
+    Arena* arena_;
+  };
+
+  GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() {
+    Arena* my_arena = arena();
+    Container* container = Arena::Create<Container>(my_arena);
+    ptr_ = reinterpret_cast<void*>(
+        reinterpret_cast<intptr_t>(container) | kTagContainer);
+    container->arena_ = my_arena;
+    return &(container->unknown_fields_);
+  }
+};
+
+// Temporary compatibility typedef. Remove once this is released in components
+// and upb CL is submitted.
+typedef InternalMetadataWithArena InternalMetadata;
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_METADATA_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/no_field_presence_test.cc b/src/third_party/protobuf-3/src/google/protobuf/no_field_presence_test.cc
new file mode 100644
index 0000000..bc41bee
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/no_field_presence_test.cc
@@ -0,0 +1,577 @@
+// 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.
+
+#include <string>
+
+#include <google/protobuf/unittest_no_field_presence.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// Helper: checks that all fields have default (zero/empty) values.
+void CheckDefaultValues(
+    const proto2_nofieldpresence_unittest::TestAllTypes& m) {
+  EXPECT_EQ(0, m.optional_int32());
+  EXPECT_EQ(0, m.optional_int64());
+  EXPECT_EQ(0, m.optional_uint32());
+  EXPECT_EQ(0, m.optional_uint64());
+  EXPECT_EQ(0, m.optional_sint32());
+  EXPECT_EQ(0, m.optional_sint64());
+  EXPECT_EQ(0, m.optional_fixed32());
+  EXPECT_EQ(0, m.optional_fixed64());
+  EXPECT_EQ(0, m.optional_sfixed32());
+  EXPECT_EQ(0, m.optional_sfixed64());
+  EXPECT_EQ(0, m.optional_float());
+  EXPECT_EQ(0, m.optional_double());
+  EXPECT_EQ(false, m.optional_bool());
+  EXPECT_EQ(0, m.optional_string().size());
+  EXPECT_EQ(0, m.optional_bytes().size());
+
+  EXPECT_EQ(false, m.has_optional_nested_message());
+  // accessor for message fields returns default instance when not present
+  EXPECT_EQ(0, m.optional_nested_message().bb());
+  EXPECT_EQ(false, m.has_optional_proto2_message());
+  // Embedded proto2 messages still have proto2 semantics, e.g. non-zero default
+  // values. Here the submessage is not present but its accessor returns the
+  // default instance.
+  EXPECT_EQ(41, m.optional_proto2_message().default_int32());
+  EXPECT_EQ(false, m.has_optional_foreign_message());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO,
+            m.optional_nested_enum());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_FOO,
+            m.optional_foreign_enum());
+
+
+  EXPECT_EQ(0, m.repeated_int32_size());
+  EXPECT_EQ(0, m.repeated_int64_size());
+  EXPECT_EQ(0, m.repeated_uint32_size());
+  EXPECT_EQ(0, m.repeated_uint64_size());
+  EXPECT_EQ(0, m.repeated_sint32_size());
+  EXPECT_EQ(0, m.repeated_sint64_size());
+  EXPECT_EQ(0, m.repeated_fixed32_size());
+  EXPECT_EQ(0, m.repeated_fixed64_size());
+  EXPECT_EQ(0, m.repeated_sfixed32_size());
+  EXPECT_EQ(0, m.repeated_sfixed64_size());
+  EXPECT_EQ(0, m.repeated_float_size());
+  EXPECT_EQ(0, m.repeated_double_size());
+  EXPECT_EQ(0, m.repeated_bool_size());
+  EXPECT_EQ(0, m.repeated_string_size());
+  EXPECT_EQ(0, m.repeated_bytes_size());
+  EXPECT_EQ(0, m.repeated_nested_message_size());
+  EXPECT_EQ(0, m.repeated_foreign_message_size());
+  EXPECT_EQ(0, m.repeated_proto2_message_size());
+  EXPECT_EQ(0, m.repeated_nested_enum_size());
+  EXPECT_EQ(0, m.repeated_foreign_enum_size());
+  EXPECT_EQ(0, m.repeated_lazy_message_size());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::ONEOF_FIELD_NOT_SET,
+            m.oneof_field_case());
+}
+
+void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) {
+  m->set_optional_int32(100);
+  m->set_optional_int64(101);
+  m->set_optional_uint32(102);
+  m->set_optional_uint64(103);
+  m->set_optional_sint32(104);
+  m->set_optional_sint64(105);
+  m->set_optional_fixed32(106);
+  m->set_optional_fixed64(107);
+  m->set_optional_sfixed32(108);
+  m->set_optional_sfixed64(109);
+  m->set_optional_float(110.0);
+  m->set_optional_double(111.0);
+  m->set_optional_bool(true);
+  m->set_optional_string("asdf");
+  m->set_optional_bytes("jkl;");
+  m->mutable_optional_nested_message()->set_bb(42);
+  m->mutable_optional_foreign_message()->set_c(43);
+  m->mutable_optional_proto2_message()->set_optional_int32(44);
+  m->set_optional_nested_enum(
+      proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->set_optional_foreign_enum(
+      proto2_nofieldpresence_unittest::FOREIGN_BAZ);
+  m->mutable_optional_lazy_message()->set_bb(45);
+  m->add_repeated_int32(100);
+  m->add_repeated_int64(101);
+  m->add_repeated_uint32(102);
+  m->add_repeated_uint64(103);
+  m->add_repeated_sint32(104);
+  m->add_repeated_sint64(105);
+  m->add_repeated_fixed32(106);
+  m->add_repeated_fixed64(107);
+  m->add_repeated_sfixed32(108);
+  m->add_repeated_sfixed64(109);
+  m->add_repeated_float(110.0);
+  m->add_repeated_double(111.0);
+  m->add_repeated_bool(true);
+  m->add_repeated_string("asdf");
+  m->add_repeated_bytes("jkl;");
+  m->add_repeated_nested_message()->set_bb(46);
+  m->add_repeated_foreign_message()->set_c(47);
+  m->add_repeated_proto2_message()->set_optional_int32(48);
+  m->add_repeated_nested_enum(
+      proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->add_repeated_foreign_enum(
+      proto2_nofieldpresence_unittest::FOREIGN_BAZ);
+  m->add_repeated_lazy_message()->set_bb(49);
+
+  m->set_oneof_uint32(1);
+  m->mutable_oneof_nested_message()->set_bb(50);
+  m->set_oneof_string("test");  // only this one remains set
+}
+
+void CheckNonDefaultValues(
+const proto2_nofieldpresence_unittest::TestAllTypes& m) {
+  EXPECT_EQ(100, m.optional_int32());
+  EXPECT_EQ(101, m.optional_int64());
+  EXPECT_EQ(102, m.optional_uint32());
+  EXPECT_EQ(103, m.optional_uint64());
+  EXPECT_EQ(104, m.optional_sint32());
+  EXPECT_EQ(105, m.optional_sint64());
+  EXPECT_EQ(106, m.optional_fixed32());
+  EXPECT_EQ(107, m.optional_fixed64());
+  EXPECT_EQ(108, m.optional_sfixed32());
+  EXPECT_EQ(109, m.optional_sfixed64());
+  EXPECT_EQ(110.0, m.optional_float());
+  EXPECT_EQ(111.0, m.optional_double());
+  EXPECT_EQ(true, m.optional_bool());
+  EXPECT_EQ("asdf", m.optional_string());
+  EXPECT_EQ("jkl;", m.optional_bytes());
+  EXPECT_EQ(true, m.has_optional_nested_message());
+  EXPECT_EQ(42, m.optional_nested_message().bb());
+  EXPECT_EQ(true, m.has_optional_foreign_message());
+  EXPECT_EQ(43, m.optional_foreign_message().c());
+  EXPECT_EQ(true, m.has_optional_proto2_message());
+  EXPECT_EQ(44, m.optional_proto2_message().optional_int32());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.optional_nested_enum());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ,
+            m.optional_foreign_enum());
+  EXPECT_EQ(true, m.has_optional_lazy_message());
+  EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+  EXPECT_EQ(1, m.repeated_int32_size());
+  EXPECT_EQ(100, m.repeated_int32(0));
+  EXPECT_EQ(1, m.repeated_int64_size());
+  EXPECT_EQ(101, m.repeated_int64(0));
+  EXPECT_EQ(1, m.repeated_uint32_size());
+  EXPECT_EQ(102, m.repeated_uint32(0));
+  EXPECT_EQ(1, m.repeated_uint64_size());
+  EXPECT_EQ(103, m.repeated_uint64(0));
+  EXPECT_EQ(1, m.repeated_sint32_size());
+  EXPECT_EQ(104, m.repeated_sint32(0));
+  EXPECT_EQ(1, m.repeated_sint64_size());
+  EXPECT_EQ(105, m.repeated_sint64(0));
+  EXPECT_EQ(1, m.repeated_fixed32_size());
+  EXPECT_EQ(106, m.repeated_fixed32(0));
+  EXPECT_EQ(1, m.repeated_fixed64_size());
+  EXPECT_EQ(107, m.repeated_fixed64(0));
+  EXPECT_EQ(1, m.repeated_sfixed32_size());
+  EXPECT_EQ(108, m.repeated_sfixed32(0));
+  EXPECT_EQ(1, m.repeated_sfixed64_size());
+  EXPECT_EQ(109, m.repeated_sfixed64(0));
+  EXPECT_EQ(1, m.repeated_float_size());
+  EXPECT_EQ(110.0, m.repeated_float(0));
+  EXPECT_EQ(1, m.repeated_double_size());
+  EXPECT_EQ(111.0, m.repeated_double(0));
+  EXPECT_EQ(1, m.repeated_bool_size());
+  EXPECT_EQ(true, m.repeated_bool(0));
+  EXPECT_EQ(1, m.repeated_string_size());
+  EXPECT_EQ("asdf", m.repeated_string(0));
+  EXPECT_EQ(1, m.repeated_bytes_size());
+  EXPECT_EQ("jkl;", m.repeated_bytes(0));
+  EXPECT_EQ(1, m.repeated_nested_message_size());
+  EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+  EXPECT_EQ(1, m.repeated_foreign_message_size());
+  EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+  EXPECT_EQ(1, m.repeated_proto2_message_size());
+  EXPECT_EQ(48, m.repeated_proto2_message(0).optional_int32());
+  EXPECT_EQ(1, m.repeated_nested_enum_size());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.repeated_nested_enum(0));
+  EXPECT_EQ(1, m.repeated_foreign_enum_size());
+  EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ,
+            m.repeated_foreign_enum(0));
+  EXPECT_EQ(1, m.repeated_lazy_message_size());
+  EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString,
+            m.oneof_field_case());
+  EXPECT_EQ("test", m.oneof_string());
+}
+
+TEST(NoFieldPresenceTest, BasicMessageTest) {
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  // Check default values, fill all fields, check values. We just want to
+  // exercise the basic getters/setter paths here to make sure no
+  // field-presence-related changes broke these.
+  CheckDefaultValues(message);
+  FillValues(&message);
+  CheckNonDefaultValues(message);
+
+  // Clear() should be equivalent to getting a freshly-constructed message.
+  message.Clear();
+  CheckDefaultValues(message);
+}
+
+TEST(NoFieldPresenceTest, MessageFieldPresenceTest) {
+  // check that presence still works properly for message fields.
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  EXPECT_EQ(false, message.has_optional_nested_message());
+  // Getter should fetch default instance, and not cause the field to become
+  // present.
+  EXPECT_EQ(0, message.optional_nested_message().bb());
+  EXPECT_EQ(false, message.has_optional_nested_message());
+  message.mutable_optional_nested_message()->set_bb(42);
+  EXPECT_EQ(true, message.has_optional_nested_message());
+  message.clear_optional_nested_message();
+  EXPECT_EQ(false, message.has_optional_nested_message());
+
+  // Likewise for a lazy message field.
+  EXPECT_EQ(false, message.has_optional_lazy_message());
+  // Getter should fetch default instance, and not cause the field to become
+  // present.
+  EXPECT_EQ(0, message.optional_lazy_message().bb());
+  EXPECT_EQ(false, message.has_optional_lazy_message());
+  message.mutable_optional_lazy_message()->set_bb(42);
+  EXPECT_EQ(true, message.has_optional_lazy_message());
+  message.clear_optional_lazy_message();
+  EXPECT_EQ(false, message.has_optional_lazy_message());
+
+  // Test field presence of a message field on the default instance.
+  EXPECT_EQ(false, proto2_nofieldpresence_unittest::TestAllTypes::
+            default_instance().has_optional_nested_message());
+}
+
+TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
+  // check that HasField reports true on all scalar fields. Check that it
+  // behaves properly for message fields.
+
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* desc = message.GetDescriptor();
+
+  // Check initial state: scalars not present (due to need to be consistent with
+  // MergeFrom()), message fields not present, oneofs not present.
+  for (int i = 0; i < desc->field_count(); i++) {
+    const google::protobuf::FieldDescriptor* field = desc->field(i);
+    if (field->is_repeated()) continue;
+    EXPECT_EQ(false, r->HasField(message, field));
+  }
+
+  // Test field presence of a message field on the default instance.
+  const google::protobuf::FieldDescriptor* msg_field =
+      desc->FindFieldByName("optional_nested_message");
+  EXPECT_EQ(false, r->HasField(
+      proto2_nofieldpresence_unittest::TestAllTypes::
+      default_instance(), msg_field));
+
+  // Fill all fields, expect everything to report true (check oneofs below).
+  FillValues(&message);
+  for (int i = 0; i < desc->field_count(); i++) {
+    const google::protobuf::FieldDescriptor* field = desc->field(i);
+    if (field->is_repeated() || field->containing_oneof()) {
+      continue;
+    }
+    if (field->options().ctype() != google::protobuf::FieldOptions::STRING) {
+      continue;
+    }
+    EXPECT_EQ(true, r->HasField(message, field));
+  }
+
+  message.Clear();
+
+  // Check zero/empty-means-not-present semantics.
+  const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName(
+      "optional_int32");
+  const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName(
+      "optional_double");
+  const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName(
+      "optional_string");
+
+  EXPECT_EQ(false, r->HasField(message, field_int32));
+  EXPECT_EQ(false, r->HasField(message, field_double));
+  EXPECT_EQ(false, r->HasField(message, field_string));
+
+  message.set_optional_int32(42);
+  EXPECT_EQ(true, r->HasField(message, field_int32));
+  message.set_optional_int32(0);
+  EXPECT_EQ(false, r->HasField(message, field_int32));
+
+  message.set_optional_double(42.0);
+  EXPECT_EQ(true, r->HasField(message, field_double));
+  message.set_optional_double(0.0);
+  EXPECT_EQ(false, r->HasField(message, field_double));
+
+  message.set_optional_string("test");
+  EXPECT_EQ(true, r->HasField(message, field_string));
+  message.set_optional_string("");
+  EXPECT_EQ(false, r->HasField(message, field_string));
+}
+
+TEST(NoFieldPresenceTest, ReflectionClearFieldTest) {
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* desc = message.GetDescriptor();
+
+  const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName(
+      "optional_int32");
+  const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName(
+      "optional_double");
+  const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName(
+      "optional_string");
+  const google::protobuf::FieldDescriptor* field_message = desc->FindFieldByName(
+      "optional_nested_message");
+  const google::protobuf::FieldDescriptor* field_lazy = desc->FindFieldByName(
+      "optional_lazy_message");
+
+  message.set_optional_int32(42);
+  r->ClearField(&message, field_int32);
+  EXPECT_EQ(0, message.optional_int32());
+
+  message.set_optional_double(42.0);
+  r->ClearField(&message, field_double);
+  EXPECT_EQ(0.0, message.optional_double());
+
+  message.set_optional_string("test");
+  r->ClearField(&message, field_string);
+  EXPECT_EQ("", message.optional_string());
+
+  message.mutable_optional_nested_message()->set_bb(1234);
+  r->ClearField(&message, field_message);
+  EXPECT_FALSE(message.has_optional_nested_message());
+  EXPECT_EQ(0, message.optional_nested_message().bb());
+
+  message.mutable_optional_lazy_message()->set_bb(42);
+  r->ClearField(&message, field_lazy);
+  EXPECT_FALSE(message.has_optional_lazy_message());
+  EXPECT_EQ(0, message.optional_lazy_message().bb());
+}
+
+TEST(NoFieldPresenceTest, HasFieldOneofsTest) {
+  // check that HasField behaves properly for oneofs.
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* desc = message.GetDescriptor();
+  const google::protobuf::FieldDescriptor* desc_oneof_uint32 =
+      desc->FindFieldByName("oneof_uint32");
+  const google::protobuf::FieldDescriptor* desc_oneof_nested_message =
+      desc->FindFieldByName("oneof_nested_message");
+  const google::protobuf::FieldDescriptor* desc_oneof_string =
+      desc->FindFieldByName("oneof_string");
+  GOOGLE_CHECK_NOTNULL(desc_oneof_uint32);
+  GOOGLE_CHECK_NOTNULL(desc_oneof_nested_message);
+  GOOGLE_CHECK_NOTNULL(desc_oneof_string);
+
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+
+  message.set_oneof_string("test");
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+  EXPECT_EQ(true, r->HasField(message, desc_oneof_string));
+  message.mutable_oneof_nested_message()->set_bb(42);
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+  EXPECT_EQ(true, r->HasField(message, desc_oneof_nested_message));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+
+  message.Clear();
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+  EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+}
+
+TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) {
+  // check that serialized data contains only non-zero numeric fields/non-empty
+  // string/byte fields.
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  string output;
+
+  // All default values -> no output.
+  message.SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+
+  // Zero values -> still no output.
+  message.set_optional_int32(0);
+  message.set_optional_int64(0);
+  message.set_optional_uint32(0);
+  message.set_optional_uint64(0);
+  message.set_optional_sint32(0);
+  message.set_optional_sint64(0);
+  message.set_optional_fixed32(0);
+  message.set_optional_fixed64(0);
+  message.set_optional_sfixed32(0);
+  message.set_optional_sfixed64(0);
+  message.set_optional_float(0);
+  message.set_optional_double(0);
+  message.set_optional_bool(0);
+  message.set_optional_string("");
+  message.set_optional_bytes("");
+  message.set_optional_nested_enum(
+      proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO);  // first enum entry
+  message.set_optional_foreign_enum(
+      proto2_nofieldpresence_unittest::FOREIGN_FOO);  // first enum entry
+
+  message.SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+
+  message.set_optional_int32(1);
+  message.SerializeToString(&output);
+  EXPECT_EQ(2, output.size());
+  EXPECT_EQ("\x08\x01", output);
+
+  message.set_optional_int32(0);
+  message.SerializeToString(&output);
+  EXPECT_EQ(0, output.size());
+}
+
+TEST(NoFieldPresenceTest, MergeFromIfNonzeroTest) {
+  // check that MergeFrom copies if nonzero/nondefault only.
+  proto2_nofieldpresence_unittest::TestAllTypes source;
+  proto2_nofieldpresence_unittest::TestAllTypes dest;
+
+  dest.set_optional_int32(42);
+  dest.set_optional_string("test");
+  source.set_optional_int32(0);
+  source.set_optional_string("");
+  // MergeFrom() copies only if present in serialization, i.e., non-zero.
+  dest.MergeFrom(source);
+  EXPECT_EQ(42, dest.optional_int32());
+  EXPECT_EQ("test", dest.optional_string());
+
+  source.set_optional_int32(84);
+  source.set_optional_string("test2");
+  dest.MergeFrom(source);
+  EXPECT_EQ(84, dest.optional_int32());
+  EXPECT_EQ("test2", dest.optional_string());
+}
+
+TEST(NoFieldPresenceTest, IsInitializedTest) {
+  // Check that IsInitialized works properly.
+  proto2_nofieldpresence_unittest::TestProto2Required message;
+
+  EXPECT_EQ(true, message.IsInitialized());
+  message.mutable_proto2()->set_a(1);
+  EXPECT_EQ(false, message.IsInitialized());
+  message.mutable_proto2()->set_b(1);
+  EXPECT_EQ(false, message.IsInitialized());
+  message.mutable_proto2()->set_c(1);
+  EXPECT_EQ(true, message.IsInitialized());
+}
+
+TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) {
+  // Check that has-bit interaction with lazy message works (has-bit before and
+  // after lazy decode).
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* desc = message.GetDescriptor();
+  const google::protobuf::FieldDescriptor* field = desc->FindFieldByName(
+      "optional_lazy_message");
+  GOOGLE_CHECK_NOTNULL(field);
+
+  EXPECT_EQ(false, message.has_optional_lazy_message());
+  EXPECT_EQ(false, r->HasField(message, field));
+
+  message.mutable_optional_lazy_message()->set_bb(42);
+  EXPECT_EQ(true, message.has_optional_lazy_message());
+  EXPECT_EQ(true, r->HasField(message, field));
+
+  // Serialize and parse with a new message object so that lazy field on new
+  // object is in unparsed state.
+  string output;
+  message.SerializeToString(&output);
+  proto2_nofieldpresence_unittest::TestAllTypes message2;
+  message2.ParseFromString(output);
+
+  EXPECT_EQ(true, message2.has_optional_lazy_message());
+  EXPECT_EQ(true, r->HasField(message2, field));
+
+  // Access field to force lazy parse.
+  EXPECT_EQ(42, message.optional_lazy_message().bb());
+  EXPECT_EQ(true, message2.has_optional_lazy_message());
+  EXPECT_EQ(true, r->HasField(message2, field));
+}
+
+TEST(NoFieldPresenceTest, OneofPresence) {
+  proto2_nofieldpresence_unittest::TestAllTypes message;
+  // oneof fields still have field presence -- ensure that this goes on the wire
+  // even though its value is the empty string.
+  message.set_oneof_string("");
+  string serialized;
+  message.SerializeToString(&serialized);
+  // Tag: 113 --> tag is (113 << 3) | 2 (length delimited) = 906
+  // varint: 0x8a 0x07
+  // Length: 0x00
+  EXPECT_EQ(3, serialized.size());
+  EXPECT_EQ(static_cast<char>(0x8a), serialized.at(0));
+  EXPECT_EQ(static_cast<char>(0x07), serialized.at(1));
+  EXPECT_EQ(static_cast<char>(0x00), serialized.at(2));
+
+  message.Clear();
+  EXPECT_TRUE(message.ParseFromString(serialized));
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString,
+            message.oneof_field_case());
+
+  // Also test int32 and enum fields.
+  message.Clear();
+  message.set_oneof_uint32(0);  // would not go on wire if ordinary field.
+  message.SerializeToString(&serialized);
+  EXPECT_EQ(3, serialized.size());
+  EXPECT_TRUE(message.ParseFromString(serialized));
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofUint32,
+            message.oneof_field_case());
+
+  message.Clear();
+  message.set_oneof_enum(proto2_nofieldpresence_unittest::
+                         TestAllTypes_NestedEnum_FOO);  // default value.
+  message.SerializeToString(&serialized);
+  EXPECT_EQ(3, serialized.size());
+  EXPECT_TRUE(message.ParseFromString(serialized));
+  EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofEnum,
+            message.oneof_field_case());
+
+  message.Clear();
+  message.set_oneof_string("test");
+  message.clear_oneof_string();
+  EXPECT_EQ(0, message.ByteSize());
+}
+
+}  // namespace
+}  // namespace protobuf
+
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/package_info.h b/src/third_party/protobuf-3/src/google/protobuf/package_info.h
new file mode 100644
index 0000000..935e963
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/package_info.h
@@ -0,0 +1,64 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file exists solely to document the google::protobuf namespace.
+// It is not compiled into anything, but it may be read by an automated
+// documentation generator.
+
+namespace google {
+
+// Core components of the Protocol Buffers runtime library.
+//
+// The files in this package represent the core of the Protocol Buffer
+// system.  All of them are part of the libprotobuf library.
+//
+// A note on thread-safety:
+//
+// Thread-safety in the Protocol Buffer library follows a simple rule:
+// unless explicitly noted otherwise, it is always safe to use an object
+// from multiple threads simultaneously as long as the object is declared
+// const in all threads (or, it is only used in ways that would be allowed
+// if it were declared const).  However, if an object is accessed in one
+// thread in a way that would not be allowed if it were const, then it is
+// not safe to access that object in any other thread simultaneously.
+//
+// Put simply, read-only access to an object can happen in multiple threads
+// simultaneously, but write access can only happen in a single thread at
+// a time.
+//
+// The implementation does contain some "const" methods which actually modify
+// the object behind the scenes -- e.g., to cache results -- but in these cases
+// mutex locking is used to make the access thread-safe.
+namespace protobuf {}
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/preserve_unknown_enum_test.cc b/src/third_party/protobuf-3/src/google/protobuf/preserve_unknown_enum_test.cc
new file mode 100644
index 0000000..1673e8a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -0,0 +1,289 @@
+// 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.
+
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/descriptor.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+void FillMessage(
+    proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
+  message->set_e(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+  message->add_repeated_e(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+  message->add_repeated_packed_e(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+  message->add_repeated_packed_unexpected_e(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+  message->set_oneof_e_1(
+      proto3_preserve_unknown_enum_unittest::E_EXTRA);
+}
+
+void CheckMessage(
+    const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.e());
+  EXPECT_EQ(1, message.repeated_e_size());
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.repeated_e(0));
+  EXPECT_EQ(1, message.repeated_packed_e_size());
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.repeated_packed_e(0));
+  EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.repeated_packed_unexpected_e(0));
+  EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+            message.oneof_e_1());
+}
+
+void CheckMessage(
+    const proto3_preserve_unknown_enum_unittest::MyMessage& message) {
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.e()));
+  EXPECT_EQ(1, message.repeated_e_size());
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.repeated_e(0)));
+  EXPECT_EQ(1, message.repeated_packed_e_size());
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.repeated_packed_e(0)));
+  EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.repeated_packed_unexpected_e(0)));
+  EXPECT_EQ(static_cast<int>(
+              proto3_preserve_unknown_enum_unittest::E_EXTRA),
+            static_cast<int>(message.oneof_e_1()));
+}
+
+}  // anonymous namespace
+
+// Test that parsing preserves an unknown value in the enum field and does not
+// punt it to the UnknownFieldSet.
+TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
+  EXPECT_EQ(true, message.ParseFromString(serialized));
+  CheckMessage(message);
+
+  serialized.clear();
+  message.SerializeToString(&serialized);
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Test that reflection based implementation also keeps unknown enum values and
+// doesn't put them into UnknownFieldSet.
+TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+  string serialized = orig_message.SerializeAsString();
+
+  google::protobuf::DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+      proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+  EXPECT_EQ(true, message->ParseFromString(serialized));
+  message->DiscardUnknownFields();
+
+  serialized = message->SerializeAsString();
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Test that for proto2 messages, unknown values are in unknown fields.
+TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  proto2_preserve_unknown_enum_unittest::MyMessage message;
+  EXPECT_EQ(true, message.ParseFromString(serialized));
+  // The intermediate message has everything in its "unknown fields".
+  proto2_preserve_unknown_enum_unittest::MyMessage message2 = message;
+  message2.DiscardUnknownFields();
+  EXPECT_EQ(0, message2.ByteSize());
+
+  // But when we pass it to the correct structure, all values are there.
+  serialized.clear();
+  message.SerializeToString(&serialized);
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Same as before, for a dynamic message.
+TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  google::protobuf::DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+      proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+  EXPECT_EQ(true, message->ParseFromString(serialized));
+  // The intermediate message has everything in its "unknown fields".
+  proto2_preserve_unknown_enum_unittest::MyMessage message2;
+  message2.CopyFrom(*message);
+  message2.DiscardUnknownFields();
+  EXPECT_EQ(0, message2.ByteSize());
+
+  // But when we pass it to the correct structure, all values are there.
+  serialized.clear();
+  message->SerializeToString(&serialized);
+  EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+  CheckMessage(orig_message);
+}
+
+// Test that reflection provides EnumValueDescriptors for unknown values.
+TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
+  proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+  FillMessage(&orig_message);
+  string serialized;
+  orig_message.SerializeToString(&serialized);
+
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
+  EXPECT_EQ(true, message.ParseFromString(serialized));
+  CheckMessage(message);
+
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* d = message.GetDescriptor();
+  const google::protobuf::FieldDescriptor* field = d->FindFieldByName("e");
+
+  // This should dynamically create an EnumValueDescriptor.
+  const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field);
+  EXPECT_EQ(enum_value->number(),
+            static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
+
+  // Fetching value for a second time should return the same pointer.
+  const google::protobuf::EnumValueDescriptor* enum_value_second =
+      r->GetEnum(message, field);
+  EXPECT_EQ(enum_value, enum_value_second);
+
+  // Check the repeated case too.
+  const google::protobuf::FieldDescriptor* repeated_field =
+      d->FindFieldByName("repeated_e");
+  enum_value = r->GetRepeatedEnum(message, repeated_field, 0);
+  EXPECT_EQ(enum_value->number(),
+            static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
+  // Should reuse the same EnumValueDescriptor, even for a different field.
+  EXPECT_EQ(enum_value, enum_value_second);
+
+  // We should be able to use the returned value descriptor to set a value on
+  // another message.
+  google::protobuf::Message* m = message.New();
+  r->SetEnum(m, field, enum_value);
+  EXPECT_EQ(enum_value, r->GetEnum(*m, field));
+  delete m;
+}
+
+// Test that the new integer-based enum reflection API works.
+TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) {
+  proto3_preserve_unknown_enum_unittest::MyMessage message;
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* d = message.GetDescriptor();
+
+  const google::protobuf::FieldDescriptor* singular_field = d->FindFieldByName("e");
+  const google::protobuf::FieldDescriptor* repeated_field =
+      d->FindFieldByName("repeated_e");
+
+  r->SetEnumValue(&message, singular_field, 42);
+  EXPECT_EQ(42, r->GetEnumValue(message, singular_field));
+  r->AddEnumValue(&message, repeated_field, 42);
+  r->AddEnumValue(&message, repeated_field, 42);
+  EXPECT_EQ(42, r->GetRepeatedEnumValue(message, repeated_field, 0));
+  r->SetRepeatedEnumValue(&message, repeated_field, 1, 84);
+  EXPECT_EQ(84, r->GetRepeatedEnumValue(message, repeated_field, 1));
+  const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message,
+                                                             singular_field);
+  EXPECT_EQ(42, enum_value->number());
+}
+
+// Test that the EnumValue API works properly for proto2 messages as well.
+TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
+  protobuf_unittest::TestAllTypes message;  // proto2 message
+  const google::protobuf::Reflection* r = message.GetReflection();
+  const google::protobuf::Descriptor* d = message.GetDescriptor();
+  const google::protobuf::FieldDescriptor* repeated_field =
+      d->FindFieldByName("repeated_nested_enum");
+  // Add one element to the repeated field so that we can test
+  // SetRepeatedEnumValue.
+  const google::protobuf::EnumValueDescriptor* enum_value =
+      repeated_field->enum_type()->FindValueByName("BAR");
+  EXPECT_TRUE(enum_value != NULL);
+  r->AddEnum(&message, repeated_field, enum_value);
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  const google::protobuf::FieldDescriptor* singular_field =
+      d->FindFieldByName("optional_nested_enum");
+  // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
+  // remain consistent with proto2 generated code.
+  EXPECT_DEBUG_DEATH({
+    r->SetEnumValue(&message, singular_field, 4242);
+    r->GetEnum(message, singular_field)->number();
+  }, "SetEnumValue accepts only valid integer values");
+  EXPECT_DEBUG_DEATH({
+    r->SetRepeatedEnumValue(&message, repeated_field, 0, 4242);
+    r->GetRepeatedEnum(message, repeated_field, 0);
+  }, "SetRepeatedEnumValue accepts only valid integer values");
+  EXPECT_DEBUG_DEATH({
+    r->AddEnumValue(&message, repeated_field, 4242);
+    r->GetRepeatedEnum(message, repeated_field, 1);
+  }, "AddEnumValue accepts only valid integer values");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) {
+  protobuf_unittest::TestAllTypes proto2_message;
+  proto3_preserve_unknown_enum_unittest::MyMessage new_message;
+
+  const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection();
+  const google::protobuf::Reflection* new_reflection = new_message.GetReflection();
+
+  EXPECT_FALSE(proto2_reflection->SupportsUnknownEnumValues());
+  EXPECT_TRUE(new_reflection->SupportsUnknownEnumValues());
+}
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_lite_unittest.cc
new file mode 100644
index 0000000..0f18c02
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_lite_unittest.cc
@@ -0,0 +1,164 @@
+// 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.
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena_lite.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_arena_lite_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of arena support.
+void SetAllFields(TestAllTypes* m) {
+  m->set_optional_int32(100);
+  m->set_optional_string("asdf");
+  m->set_optional_bytes("jkl;");
+  m->mutable_optional_nested_message()->set_bb(42);
+  m->mutable_optional_foreign_message()->set_c(43);
+  m->set_optional_nested_enum(
+      proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->set_optional_foreign_enum(
+      proto3_arena_lite_unittest::FOREIGN_BAZ);
+  m->mutable_optional_lazy_message()->set_bb(45);
+  m->add_repeated_int32(100);
+  m->add_repeated_string("asdf");
+  m->add_repeated_bytes("jkl;");
+  m->add_repeated_nested_message()->set_bb(46);
+  m->add_repeated_foreign_message()->set_c(47);
+  m->add_repeated_nested_enum(
+      proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->add_repeated_foreign_enum(
+      proto3_arena_lite_unittest::FOREIGN_BAZ);
+  m->add_repeated_lazy_message()->set_bb(49);
+
+  m->set_oneof_uint32(1);
+  m->mutable_oneof_nested_message()->set_bb(50);
+  m->set_oneof_string("test");  // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+  EXPECT_EQ(100, m.optional_int32());
+  EXPECT_EQ("asdf", m.optional_string());
+  EXPECT_EQ("jkl;", m.optional_bytes());
+  EXPECT_EQ(true, m.has_optional_nested_message());
+  EXPECT_EQ(42, m.optional_nested_message().bb());
+  EXPECT_EQ(true, m.has_optional_foreign_message());
+  EXPECT_EQ(43, m.optional_foreign_message().c());
+  EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.optional_nested_enum());
+  EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ,
+            m.optional_foreign_enum());
+  EXPECT_EQ(true, m.has_optional_lazy_message());
+  EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+  EXPECT_EQ(1, m.repeated_int32_size());
+  EXPECT_EQ(100, m.repeated_int32(0));
+  EXPECT_EQ(1, m.repeated_string_size());
+  EXPECT_EQ("asdf", m.repeated_string(0));
+  EXPECT_EQ(1, m.repeated_bytes_size());
+  EXPECT_EQ("jkl;", m.repeated_bytes(0));
+  EXPECT_EQ(1, m.repeated_nested_message_size());
+  EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+  EXPECT_EQ(1, m.repeated_foreign_message_size());
+  EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+  EXPECT_EQ(1, m.repeated_nested_enum_size());
+  EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.repeated_nested_enum(0));
+  EXPECT_EQ(1, m.repeated_foreign_enum_size());
+  EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ,
+            m.repeated_foreign_enum(0));
+  EXPECT_EQ(1, m.repeated_lazy_message_size());
+  EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+  EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes::kOneofString,
+            m.oneof_field_case());
+  EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of arena support in
+// proto3 and expect the arena support to be fully tested in proto2 unittests
+// because proto3 shares most code with proto2.
+
+TEST(Proto3ArenaLiteTest, Parsing) {
+  TestAllTypes original;
+  SetAllFields(&original);
+
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+  ExpectAllFieldsSet(*arena_message);
+}
+
+TEST(Proto3ArenaLiteTest, Swap) {
+  Arena arena1;
+  Arena arena2;
+
+  // Test Swap().
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  arena1_message->Swap(arena2_message);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+}
+
+TEST(Proto3ArenaLiteTest, SetAllocatedMessage) {
+  Arena arena;
+  TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+  nested->set_bb(118);
+  arena_message->set_allocated_optional_nested_message(nested);
+  EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+}
+
+TEST(Proto3ArenaLiteTest, ReleaseMessage) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->mutable_optional_nested_message()->set_bb(118);
+  google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
+      arena_message->release_optional_nested_message());
+  EXPECT_EQ(118, nested->bb());
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_unittest.cc
new file mode 100644
index 0000000..2838e0f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/proto3_arena_unittest.cc
@@ -0,0 +1,209 @@
+// 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.
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_arena_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of arena support.
+void SetAllFields(TestAllTypes* m) {
+  m->set_optional_int32(100);
+  m->set_optional_string("asdf");
+  m->set_optional_bytes("jkl;");
+  m->mutable_optional_nested_message()->set_bb(42);
+  m->mutable_optional_foreign_message()->set_c(43);
+  m->set_optional_nested_enum(
+      proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->set_optional_foreign_enum(
+      proto3_arena_unittest::FOREIGN_BAZ);
+  m->mutable_optional_lazy_message()->set_bb(45);
+  m->add_repeated_int32(100);
+  m->add_repeated_string("asdf");
+  m->add_repeated_bytes("jkl;");
+  m->add_repeated_nested_message()->set_bb(46);
+  m->add_repeated_foreign_message()->set_c(47);
+  m->add_repeated_nested_enum(
+      proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->add_repeated_foreign_enum(
+      proto3_arena_unittest::FOREIGN_BAZ);
+  m->add_repeated_lazy_message()->set_bb(49);
+
+  m->set_oneof_uint32(1);
+  m->mutable_oneof_nested_message()->set_bb(50);
+  m->set_oneof_string("test");  // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+  EXPECT_EQ(100, m.optional_int32());
+  EXPECT_EQ("asdf", m.optional_string());
+  EXPECT_EQ("jkl;", m.optional_bytes());
+  EXPECT_EQ(true, m.has_optional_nested_message());
+  EXPECT_EQ(42, m.optional_nested_message().bb());
+  EXPECT_EQ(true, m.has_optional_foreign_message());
+  EXPECT_EQ(43, m.optional_foreign_message().c());
+  EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.optional_nested_enum());
+  EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ,
+            m.optional_foreign_enum());
+  EXPECT_EQ(true, m.has_optional_lazy_message());
+  EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+  EXPECT_EQ(1, m.repeated_int32_size());
+  EXPECT_EQ(100, m.repeated_int32(0));
+  EXPECT_EQ(1, m.repeated_string_size());
+  EXPECT_EQ("asdf", m.repeated_string(0));
+  EXPECT_EQ(1, m.repeated_bytes_size());
+  EXPECT_EQ("jkl;", m.repeated_bytes(0));
+  EXPECT_EQ(1, m.repeated_nested_message_size());
+  EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+  EXPECT_EQ(1, m.repeated_foreign_message_size());
+  EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+  EXPECT_EQ(1, m.repeated_nested_enum_size());
+  EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.repeated_nested_enum(0));
+  EXPECT_EQ(1, m.repeated_foreign_enum_size());
+  EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ,
+            m.repeated_foreign_enum(0));
+  EXPECT_EQ(1, m.repeated_lazy_message_size());
+  EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+  EXPECT_EQ(proto3_arena_unittest::TestAllTypes::kOneofString,
+            m.oneof_field_case());
+  EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of arena support in
+// proto3 and expect the arena support to be fully tested in proto2 unittests
+// because proto3 shares most code with proto2.
+
+TEST(Proto3ArenaTest, Parsing) {
+  TestAllTypes original;
+  SetAllFields(&original);
+
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+  ExpectAllFieldsSet(*arena_message);
+}
+
+TEST(Proto3ArenaTest, UnknownFields) {
+  TestAllTypes original;
+  SetAllFields(&original);
+
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+  ExpectAllFieldsSet(*arena_message);
+
+  // In proto3 we can still get a pointer to the UnknownFieldSet through
+  // reflection API.
+  UnknownFieldSet* unknown_fields =
+      arena_message->GetReflection()->MutableUnknownFields(arena_message);
+  // We can modify this UnknownFieldSet.
+  unknown_fields->AddVarint(1, 2);
+  // But the change will never will serialized back.
+  ASSERT_EQ(original.ByteSize(), arena_message->ByteSize());
+  ASSERT_TRUE(
+      arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
+}
+
+TEST(Proto3ArenaTest, Swap) {
+  Arena arena1;
+  Arena arena2;
+
+  // Test Swap().
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+  arena1_message->Swap(arena2_message);
+  EXPECT_EQ(&arena1, arena1_message->GetArena());
+  EXPECT_EQ(&arena2, arena2_message->GetArena());
+}
+
+TEST(Proto3ArenaTest, SetAllocatedMessage) {
+  Arena arena;
+  TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+  nested->set_bb(118);
+  arena_message->set_allocated_optional_nested_message(nested);
+  EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+}
+
+TEST(Proto3ArenaTest, ReleaseMessage) {
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->mutable_optional_nested_message()->set_bb(118);
+  google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
+      arena_message->release_optional_nested_message());
+  EXPECT_EQ(118, nested->bb());
+}
+
+TEST(Proto3ArenaTest, MessageFieldClear) {
+  // GitHub issue #310: https://github.com/google/protobuf/issues/310
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->mutable_optional_nested_message()->set_bb(118);
+  // This should not crash, but prior to the bugfix, it tried to use `operator
+  // delete` the nested message (which is on the arena):
+  arena_message->Clear();
+}
+
+TEST(Proto3ArenaTest, MessageFieldClearViaReflection) {
+  Arena arena;
+  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+  const Reflection* r = message->GetReflection();
+  const Descriptor* d = message->GetDescriptor();
+  const FieldDescriptor* msg_field = d->FindFieldByName(
+      "optional_nested_message");
+
+  message->mutable_optional_nested_message()->set_bb(1);
+  r->ClearField(message, msg_field);
+  EXPECT_FALSE(message->has_optional_nested_message());
+  EXPECT_EQ(0, message->optional_nested_message().bb());
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/proto3_lite_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/proto3_lite_unittest.cc
new file mode 100644
index 0000000..2e2beea
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/proto3_lite_unittest.cc
@@ -0,0 +1,145 @@
+// 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.
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_lite.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_lite_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of lite support.
+void SetAllFields(TestAllTypes* m) {
+  m->set_optional_int32(100);
+  m->set_optional_string("asdf");
+  m->set_optional_bytes("jkl;");
+  m->mutable_optional_nested_message()->set_bb(42);
+  m->mutable_optional_foreign_message()->set_c(43);
+  m->set_optional_nested_enum(
+      proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->set_optional_foreign_enum(
+      proto3_lite_unittest::FOREIGN_BAZ);
+  m->mutable_optional_lazy_message()->set_bb(45);
+  m->add_repeated_int32(100);
+  m->add_repeated_string("asdf");
+  m->add_repeated_bytes("jkl;");
+  m->add_repeated_nested_message()->set_bb(46);
+  m->add_repeated_foreign_message()->set_c(47);
+  m->add_repeated_nested_enum(
+      proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+  m->add_repeated_foreign_enum(
+      proto3_lite_unittest::FOREIGN_BAZ);
+  m->add_repeated_lazy_message()->set_bb(49);
+
+  m->set_oneof_uint32(1);
+  m->mutable_oneof_nested_message()->set_bb(50);
+  m->set_oneof_string("test");  // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+  EXPECT_EQ(100, m.optional_int32());
+  EXPECT_EQ("asdf", m.optional_string());
+  EXPECT_EQ("jkl;", m.optional_bytes());
+  EXPECT_EQ(true, m.has_optional_nested_message());
+  EXPECT_EQ(42, m.optional_nested_message().bb());
+  EXPECT_EQ(true, m.has_optional_foreign_message());
+  EXPECT_EQ(43, m.optional_foreign_message().c());
+  EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.optional_nested_enum());
+  EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ,
+            m.optional_foreign_enum());
+  EXPECT_EQ(true, m.has_optional_lazy_message());
+  EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+  EXPECT_EQ(1, m.repeated_int32_size());
+  EXPECT_EQ(100, m.repeated_int32(0));
+  EXPECT_EQ(1, m.repeated_string_size());
+  EXPECT_EQ("asdf", m.repeated_string(0));
+  EXPECT_EQ(1, m.repeated_bytes_size());
+  EXPECT_EQ("jkl;", m.repeated_bytes(0));
+  EXPECT_EQ(1, m.repeated_nested_message_size());
+  EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+  EXPECT_EQ(1, m.repeated_foreign_message_size());
+  EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+  EXPECT_EQ(1, m.repeated_nested_enum_size());
+  EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+            m.repeated_nested_enum(0));
+  EXPECT_EQ(1, m.repeated_foreign_enum_size());
+  EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ,
+            m.repeated_foreign_enum(0));
+  EXPECT_EQ(1, m.repeated_lazy_message_size());
+  EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+  EXPECT_EQ(proto3_lite_unittest::TestAllTypes::kOneofString,
+            m.oneof_field_case());
+  EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of in proto3 and expect
+// the rest is fully tested in proto2 unittests because proto3 shares most code
+// with proto2.
+
+TEST(Proto3LiteTest, Parsing) {
+  TestAllTypes original;
+  SetAllFields(&original);
+
+  TestAllTypes msg;
+  msg.ParseFromString(original.SerializeAsString());
+  ExpectAllFieldsSet(msg);
+}
+
+TEST(Proto3LiteTest, Swap) {
+  // Test Swap().
+  TestAllTypes msg1;
+  TestAllTypes msg2;
+  msg1.set_optional_string("123");
+  msg2.set_optional_string("3456");
+  msg1.Swap(&msg2);
+  EXPECT_EQ("3456", msg1.optional_string());
+  EXPECT_EQ("123", msg2.optional_string());
+  EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1);
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/reflection.h b/src/third_party/protobuf-3/src/google/protobuf/reflection.h
new file mode 100755
index 0000000..671aafd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/reflection.h
@@ -0,0 +1,600 @@
+// 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.
+
+// This header defines the RepeatedFieldRef class template used to access
+// repeated fields with protobuf reflection API.
+#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
+#define GOOGLE_PROTOBUF_REFLECTION_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/message.h>
+#include <google/protobuf/generated_enum_util.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T, typename Enable = void>
+struct RefTypeTraits;
+}  // namespace internal
+
+template<typename T>
+RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
+    const Message& message, const FieldDescriptor* field) const {
+  return RepeatedFieldRef<T>(message, field);
+}
+
+template<typename T>
+MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
+    Message* message, const FieldDescriptor* field) const {
+  return MutableRepeatedFieldRef<T>(message, field);
+}
+
+// RepeatedFieldRef definition for non-message types.
+template<typename T>
+class RepeatedFieldRef<
+    T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
+  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
+  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+  bool empty() const {
+    return accessor_->IsEmpty(data_);
+  }
+  int size() const {
+    return accessor_->Size(data_);
+  }
+  T Get(int index) const {
+    return accessor_->template Get<T>(data_, index);
+  }
+
+  typedef IteratorType iterator;
+  typedef IteratorType const_iterator;
+  iterator begin() const {
+    return iterator(data_, accessor_, true);
+  }
+  iterator end() const {
+    return iterator(data_, accessor_, false);
+  }
+
+ private:
+  friend class Reflection;
+  RepeatedFieldRef(
+      const Message& message,
+      const FieldDescriptor* field) {
+    const Reflection* reflection = message.GetReflection();
+    data_ = reflection->RepeatedFieldData(
+        const_cast<Message*>(&message), field,
+        internal::RefTypeTraits<T>::cpp_type, NULL);
+    accessor_ = reflection->RepeatedFieldAccessor(field);
+  }
+
+  const void* data_;
+  const AccessorType* accessor_;
+};
+
+// MutableRepeatedFieldRef definition for non-message types.
+template<typename T>
+class MutableRepeatedFieldRef<
+    T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
+  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+  bool empty() const {
+    return accessor_->IsEmpty(data_);
+  }
+  int size() const {
+    return accessor_->Size(data_);
+  }
+  T Get(int index) const {
+    return accessor_->template Get<T>(data_, index);
+  }
+
+  void Set(int index, const T& value) const {
+    accessor_->template Set<T>(data_, index, value);
+  }
+  void Add(const T& value) const {
+    accessor_->template Add<T>(data_, value);
+  }
+  void RemoveLast() const {
+    accessor_->RemoveLast(data_);
+  }
+  void SwapElements(int index1, int index2) const {
+    accessor_->SwapElements(data_, index1, index2);
+  }
+  void Clear() const {
+    accessor_->Clear(data_);
+  }
+
+  void Swap(const MutableRepeatedFieldRef& other) const {
+    accessor_->Swap(data_, other.accessor_, other.data_);
+  }
+
+  template<typename Container>
+  void MergeFrom(const Container& container) const {
+    typedef typename Container::const_iterator Iterator;
+    for (Iterator it = container.begin(); it != container.end(); ++it) {
+      Add(*it);
+    }
+  }
+  template<typename Container>
+  void CopyFrom(const Container& container) const {
+    Clear();
+    MergeFrom(container);
+  }
+
+ private:
+  friend class Reflection;
+  MutableRepeatedFieldRef(
+      Message* message,
+      const FieldDescriptor* field) {
+    const Reflection* reflection = message->GetReflection();
+    data_ = reflection->RepeatedFieldData(
+        message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
+    accessor_ = reflection->RepeatedFieldAccessor(field);
+  }
+
+  void* data_;
+  const AccessorType* accessor_;
+};
+
+// RepeatedFieldRef definition for message types.
+template<typename T>
+class RepeatedFieldRef<
+    T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
+  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+  bool empty() const {
+    return accessor_->IsEmpty(data_);
+  }
+  int size() const {
+    return accessor_->Size(data_);
+  }
+  // This method returns a reference to the underlying message object if it
+  // exists. If a message object doesn't exist (e.g., data stored in serialized
+  // form), scratch_space will be filled with the data and a reference to it
+  // will be returned.
+  //
+  // Example:
+  //   RepeatedFieldRef<Message> h = ...
+  //   unique_ptr<Message> scratch_space(h.NewMessage());
+  //   const Message& item = h.Get(index, scratch_space.get());
+  const T& Get(int index, T* scratch_space) const {
+    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
+  }
+  // Create a new message of the same type as the messages stored in this
+  // repeated field. Caller takes ownership of the returned object.
+  T* NewMessage() const {
+    return static_cast<T*>(default_instance_->New());
+  }
+
+  typedef IteratorType iterator;
+  typedef IteratorType const_iterator;
+  iterator begin() const {
+    return iterator(data_, accessor_, true, NewMessage());
+  }
+  iterator end() const {
+    return iterator(data_, accessor_, false, NewMessage());
+  }
+
+ private:
+  friend class Reflection;
+  RepeatedFieldRef(
+      const Message& message,
+      const FieldDescriptor* field) {
+    const Reflection* reflection = message.GetReflection();
+    data_ = reflection->RepeatedFieldData(
+        const_cast<Message*>(&message), field,
+        internal::RefTypeTraits<T>::cpp_type,
+        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
+    accessor_ = reflection->RepeatedFieldAccessor(field);
+    default_instance_ =
+        reflection->GetMessageFactory()->GetPrototype(field->message_type());
+  }
+
+  const void* data_;
+  const AccessorType* accessor_;
+  const Message* default_instance_;
+};
+
+// MutableRepeatedFieldRef definition for message types.
+template<typename T>
+class MutableRepeatedFieldRef<
+    T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+  bool empty() const {
+    return accessor_->IsEmpty(data_);
+  }
+  int size() const {
+    return accessor_->Size(data_);
+  }
+  // See comments for RepeatedFieldRef<Message>::Get()
+  const T& Get(int index, T* scratch_space) const {
+    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
+  }
+  // Create a new message of the same type as the messages stored in this
+  // repeated field. Caller takes ownership of the returned object.
+  T* NewMessage() const {
+    return static_cast<T*>(default_instance_->New());
+  }
+
+  void Set(int index, const T& value) const {
+    accessor_->Set(data_, index, &value);
+  }
+  void Add(const T& value) const {
+    accessor_->Add(data_, &value);
+  }
+  void RemoveLast() const {
+    accessor_->RemoveLast(data_);
+  }
+  void SwapElements(int index1, int index2) const {
+    accessor_->SwapElements(data_, index1, index2);
+  }
+  void Clear() const {
+    accessor_->Clear(data_);
+  }
+
+  void Swap(const MutableRepeatedFieldRef& other) const {
+    accessor_->Swap(data_, other.accessor_, other.data_);
+  }
+
+  template<typename Container>
+  void MergeFrom(const Container& container) const {
+    typedef typename Container::const_iterator Iterator;
+    for (Iterator it = container.begin(); it != container.end(); ++it) {
+      Add(*it);
+    }
+  }
+  template<typename Container>
+  void CopyFrom(const Container& container) const {
+    Clear();
+    MergeFrom(container);
+  }
+
+ private:
+  friend class Reflection;
+  MutableRepeatedFieldRef(
+      Message* message,
+      const FieldDescriptor* field) {
+    const Reflection* reflection = message->GetReflection();
+    data_ = reflection->RepeatedFieldData(
+        message, field, internal::RefTypeTraits<T>::cpp_type,
+        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
+    accessor_ = reflection->RepeatedFieldAccessor(field);
+    default_instance_ =
+        reflection->GetMessageFactory()->GetPrototype(field->message_type());
+  }
+
+  void* data_;
+  const AccessorType* accessor_;
+  const Message* default_instance_;
+};
+
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+//   field->cpp_type()      T                Actual type of void*
+//   CPPTYPE_INT32        int32                   int32
+//   CPPTYPE_UINT32       uint32                  uint32
+//   CPPTYPE_INT64        int64                   int64
+//   CPPTYPE_UINT64       uint64                  uint64
+//   CPPTYPE_DOUBLE       double                  double
+//   CPPTYPE_FLOAT        float                   float
+//   CPPTYPE_BOOL         bool                    bool
+//   CPPTYPE_ENUM         generated enum type     int32
+//   CPPTYPE_STRING       string                  string
+//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
+//                        or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+  // Typedefs for clarity.
+  typedef void Field;
+  typedef void Value;
+  typedef void Iterator;
+
+  virtual ~RepeatedFieldAccessor();
+  virtual bool IsEmpty(const Field* data) const = 0;
+  virtual int Size(const Field* data) const = 0;
+  // Depends on the underlying representation of the repeated field, this
+  // method can return a pointer to the underlying object if such an object
+  // exists, or fill the data into scratch_space and return scratch_space.
+  // Callers of this method must ensure scratch_space is a valid pointer
+  // to a mutable object of the correct type.
+  virtual const Value* Get(
+      const Field* data, int index, Value* scratch_space) const = 0;
+
+  virtual void Clear(Field* data) const = 0;
+  virtual void Set(Field* data, int index, const Value* value) const = 0;
+  virtual void Add(Field* data, const Value* value) const = 0;
+  virtual void RemoveLast(Field* data) const = 0;
+  virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+  virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+                    Field* other_data) const = 0;
+
+  // Create an iterator that points at the begining of the repeated field.
+  virtual Iterator* BeginIterator(const Field* data) const = 0;
+  // Create an iterator that points at the end of the repeated field.
+  virtual Iterator* EndIterator(const Field* data) const = 0;
+  // Make a copy of an iterator and return the new copy.
+  virtual Iterator* CopyIterator(const Field* data,
+                                 const Iterator* iterator) const = 0;
+  // Move an iterator to point to the next element.
+  virtual Iterator* AdvanceIterator(const Field* data,
+                                    Iterator* iterator) const = 0;
+  // Compare whether two iterators point to the same element.
+  virtual bool EqualsIterator(const Field* data, const Iterator* a,
+                              const Iterator* b) const = 0;
+  // Delete an iterator created by BeginIterator(), EndIterator() and
+  // CopyIterator().
+  virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+  // Like Get() but for iterators.
+  virtual const Value* GetIteratorValue(const Field* data,
+                                        const Iterator* iterator,
+                                        Value* scratch_space) const = 0;
+
+  // Templated methods that make using this interface easier for non-message
+  // types.
+  template<typename T>
+  T Get(const Field* data, int index) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    ActualType scratch_space;
+    return static_cast<T>(
+        *reinterpret_cast<const ActualType*>(
+            Get(data, index, static_cast<Value*>(&scratch_space))));
+  }
+
+  template<typename T, typename ValueType>
+  void Set(Field* data, int index, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Set(data, index, static_cast<const Value*>(&tmp));
+  }
+
+  template<typename T, typename ValueType>
+  void Add(Field* data, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Add(data, static_cast<const Value*>(&tmp));
+  }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+    : public std::iterator<std::forward_iterator_tag, T> {
+  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+  // Constructor for non-message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(new AccessorValueType) {
+  }
+  // Constructor for message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin,
+                           AccessorValueType* scratch_space)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(scratch_space) {
+  }
+  ~RepeatedFieldRefIterator() {
+    accessor_->DeleteIterator(data_, iterator_);
+  }
+  RepeatedFieldRefIterator operator++(int) {
+    RepeatedFieldRefIterator tmp(*this);
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return tmp;
+  }
+  RepeatedFieldRefIterator& operator++() {
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return *this;
+  }
+  IteratorValueType operator*() const {
+    return static_cast<IteratorValueType>(
+        *static_cast<const AccessorValueType*>(
+            accessor_->GetIteratorValue(
+                data_, iterator_, scratch_space_.get())));
+  }
+  IteratorPointerType operator->() const {
+    return static_cast<IteratorPointerType>(
+        accessor_->GetIteratorValue(
+            data_, iterator_, scratch_space_.get()));
+  }
+  bool operator!=(const RepeatedFieldRefIterator& other) const {
+    assert(data_ == other.data_);
+    assert(accessor_ == other.accessor_);
+    return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+  }
+  bool operator==(const RepeatedFieldRefIterator& other) const {
+    return !this->operator!=(other);
+  }
+
+  RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+      : data_(other.data_), accessor_(other.accessor_),
+        iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+  }
+  RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+    if (this != &other) {
+      accessor_->DeleteIterator(data_, iterator_);
+      data_ = other.data_;
+      accessor_ = other.accessor_;
+      iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+    }
+    return *this;
+  }
+
+ protected:
+  const void* data_;
+  const RepeatedFieldAccessor* accessor_;
+  void* iterator_;
+  google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+  static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+    template<> struct PrimitiveTraits<type> { \
+      static const bool is_primitive = true; \
+      static const FieldDescriptor::CppType cpp_type = \
+          FieldDescriptor::CPPTYPE_ ## TYPE; \
+    };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef T AccessorValueType;
+  typedef T IteratorValueType;
+  typedef T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      PrimitiveTraits<T>::cpp_type;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  // We use int32 for repeated enums in RepeatedFieldAccessor.
+  typedef int32 AccessorValueType;
+  typedef T IteratorValueType;
+  typedef int32* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_ENUM;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if< ::google::protobuf::internal::is_same<string, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef string AccessorValueType;
+  typedef string IteratorValueType;
+  typedef string* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_STRING;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+  static const Descriptor* get() {
+    return T::default_instance().GetDescriptor();
+  }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+  static const Descriptor* get() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef Message AccessorValueType;
+  typedef const T& IteratorValueType;
+  typedef const T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_MESSAGE;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return MessageDescriptorGetter<T>::get();
+  }
+};
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/reflection_internal.h b/src/third_party/protobuf-3/src/google/protobuf/reflection_internal.h
new file mode 100644
index 0000000..fcb4247
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/reflection_internal.h
@@ -0,0 +1,378 @@
+// 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_REFLECTION_INTERNAL_H__
+#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
+
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/reflection.h>
+#include <google/protobuf/repeated_field.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// A base class for RepeatedFieldAccessor implementations that can support
+// random-access efficiently. All iterator methods delegates the work to
+// corresponding random-access methods.
+class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor {
+ public:
+  virtual ~RandomAccessRepeatedFieldAccessor() {}
+
+  virtual Iterator* BeginIterator(const Field* data) const {
+    return PositionToIterator(0);
+  }
+  virtual Iterator* EndIterator(const Field* data) const {
+    return PositionToIterator(this->Size(data));
+  }
+  virtual Iterator* CopyIterator(const Field* data,
+                                 const Iterator* iterator) const {
+    return const_cast<Iterator*>(iterator);
+  }
+  virtual Iterator* AdvanceIterator(const Field* data,
+                                    Iterator* iterator) const {
+    return PositionToIterator(IteratorToPosition(iterator) + 1);
+  }
+  virtual bool EqualsIterator(const Field* data,
+                              const Iterator* a,
+                              const Iterator* b) const {
+    return a == b;
+  }
+  virtual void DeleteIterator(const Field* data, Iterator* iterator) const {
+  }
+  virtual const Value* GetIteratorValue(const Field* data,
+                                        const Iterator* iterator,
+                                        Value* scratch_space) const {
+    return Get(data, static_cast<int>(IteratorToPosition(iterator)),
+               scratch_space);
+  }
+
+ private:
+  static intptr_t IteratorToPosition(const Iterator* iterator) {
+    return reinterpret_cast<intptr_t>(iterator);
+  }
+  static Iterator* PositionToIterator(intptr_t position) {
+    return reinterpret_cast<Iterator*>(position);
+  }
+};
+
+// Base class for RepeatedFieldAccessor implementations that manipulates
+// RepeatedField<T>.
+template<typename T>
+class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor {
+ public:
+  RepeatedFieldWrapper() {}
+  virtual ~RepeatedFieldWrapper() {}
+  virtual bool IsEmpty(const Field* data) const {
+    return GetRepeatedField(data)->empty();
+  }
+  virtual int Size(const Field* data) const {
+    return GetRepeatedField(data)->size();
+  }
+  virtual const Value* Get(const Field* data, int index,
+                          Value* scratch_space) const {
+    return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
+  }
+  virtual void Clear(Field* data) const {
+    MutableRepeatedField(data)->Clear();
+  }
+  virtual void Set(Field* data, int index, const Value* value) const {
+    MutableRepeatedField(data)->Set(index, ConvertToT(value));
+  }
+  virtual void Add(Field* data, const Value* value) const {
+    MutableRepeatedField(data)->Add(ConvertToT(value));
+  }
+  virtual void RemoveLast(Field* data) const {
+    MutableRepeatedField(data)->RemoveLast();
+  }
+  virtual void SwapElements(Field* data, int index1, int index2) const {
+    MutableRepeatedField(data)->SwapElements(index1, index2);
+  }
+
+ protected:
+  typedef RepeatedField<T> RepeatedFieldType;
+  static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+    return reinterpret_cast<const RepeatedFieldType*>(data);
+  }
+  static RepeatedFieldType* MutableRepeatedField(Field* data) {
+    return reinterpret_cast<RepeatedFieldType*>(data);
+  }
+
+  // Convert an object recevied by this accessor to an object to be stored in
+  // the underlying RepeatedField.
+  virtual T ConvertToT(const Value* value) const = 0;
+
+  // Convert an object stored in RepeatedPtrField to an object that will be
+  // returned by this accessor. If the two objects have the same type (true
+  // for string fields with ctype=STRING), a pointer to the source object can
+  // be returned directly. Otherwise, data should be copied from value to
+  // scratch_space and scratch_space should be returned.
+  virtual const Value* ConvertFromT(const T& value,
+                                    Value* scratch_space) const = 0;
+};
+
+// Base class for RepeatedFieldAccessor implementations that manipulates
+// RepeatedPtrField<T>.
+template<typename T>
+class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
+ public:
+  RepeatedPtrFieldWrapper() {}
+  virtual ~RepeatedPtrFieldWrapper() {}
+  virtual bool IsEmpty(const Field* data) const {
+    return GetRepeatedField(data)->empty();
+  }
+  virtual int Size(const Field* data) const {
+    return GetRepeatedField(data)->size();
+  }
+  virtual const Value* Get(const Field* data, int index,
+                           Value* scratch_space) const {
+    return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
+  }
+  virtual void Clear(Field* data) const {
+    MutableRepeatedField(data)->Clear();
+  }
+  virtual void Set(Field* data, int index, const Value* value) const {
+    ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
+  }
+  virtual void Add(Field* data, const Value* value) const {
+    T* allocated = New(value);
+    ConvertToT(value, allocated);
+    MutableRepeatedField(data)->AddAllocated(allocated);
+  }
+  virtual void RemoveLast(Field* data) const {
+    MutableRepeatedField(data)->RemoveLast();
+  }
+  virtual void SwapElements(Field* data, int index1, int index2) const {
+    MutableRepeatedField(data)->SwapElements(index1, index2);
+  }
+
+ protected:
+  typedef RepeatedPtrField<T> RepeatedFieldType;
+  static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+    return reinterpret_cast<const RepeatedFieldType*>(data);
+  }
+  static RepeatedFieldType* MutableRepeatedField(Field* data) {
+    return reinterpret_cast<RepeatedFieldType*>(data);
+  }
+
+  // Create a new T instance. For repeated message fields, T can be specified
+  // as google::protobuf::Message so we can't use "new T()" directly. In that case, value
+  // should be a message of the same type (it's ensured by the caller) and a
+  // new message object will be created using it.
+  virtual T* New(const Value* value) const = 0;
+
+  // Convert an object received by this accessor to an object that will be
+  // stored in the underlying RepeatedPtrField.
+  virtual void ConvertToT(const Value* value, T* result) const = 0;
+
+  // Convert an object stored in RepeatedPtrField to an object that will be
+  // returned by this accessor. If the two objects have the same type (true
+  // for string fields with ctype=STRING), a pointer to the source object can
+  // be returned directly. Otherwise, data should be copied from value to
+  // scratch_space and scratch_space should be returned.
+  virtual const Value* ConvertFromT(const T& value,
+                                    Value* scratch_space) const = 0;
+};
+
+// An implementation of RandomAccessRepeatedFieldAccessor that manipulates
+// MapFieldBase.
+class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor {
+ public:
+  MapFieldAccessor() {}
+  virtual ~MapFieldAccessor() {}
+  virtual bool IsEmpty(const Field* data) const {
+    return GetRepeatedField(data)->empty();
+  }
+  virtual int Size(const Field* data) const {
+    return GetRepeatedField(data)->size();
+  }
+  virtual const Value* Get(const Field* data, int index,
+                           Value* scratch_space) const {
+    return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space);
+  }
+  virtual void Clear(Field* data) const {
+    MutableRepeatedField(data)->Clear();
+  }
+  virtual void Set(Field* data, int index, const Value* value) const {
+    ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
+  }
+  virtual void Add(Field* data, const Value* value) const {
+    Message* allocated = New(value);
+    ConvertToEntry(value, allocated);
+    MutableRepeatedField(data)->AddAllocated(allocated);
+  }
+  virtual void RemoveLast(Field* data) const {
+    MutableRepeatedField(data)->RemoveLast();
+  }
+  virtual void SwapElements(Field* data, int index1, int index2) const {
+    MutableRepeatedField(data)->SwapElements(index1, index2);
+  }
+  virtual void Swap(
+      Field* data,
+      const internal::RepeatedFieldAccessor* other_mutator,
+      Field* other_data) const {
+    GOOGLE_CHECK(this == other_mutator);
+    MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+  }
+
+ protected:
+  typedef RepeatedPtrField<Message> RepeatedFieldType;
+  static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+    return reinterpret_cast<const RepeatedFieldType*>(
+        (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
+  }
+  static RepeatedFieldType* MutableRepeatedField(Field* data) {
+    return reinterpret_cast<RepeatedFieldType*>(
+        reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
+  }
+  virtual Message* New(const Value* value) const {
+    return static_cast<const Message*>(value)->New();
+  }
+  // Convert an object received by this accessor to an MapEntry message to be
+  // stored in the underlying MapFieldBase.
+  virtual void ConvertToEntry(const Value* value, Message* result) const {
+    result->CopyFrom(*static_cast<const Message*>(value));
+  }
+  // Convert a MapEntry message stored in the underlying MapFieldBase to an
+  // object that will be returned by this accessor.
+  virtual const Value* ConvertFromEntry(const Message& value,
+                                        Value* scratch_space) const {
+    return static_cast<const Value*>(&value);
+  }
+};
+
+// Default implementations of RepeatedFieldAccessor for primitive types.
+template<typename T>
+class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
+  typedef void Field;
+  typedef void Value;
+  using RepeatedFieldWrapper<T>::MutableRepeatedField;
+
+ public:
+  RepeatedFieldPrimitiveAccessor() {}
+  virtual ~RepeatedFieldPrimitiveAccessor() {}
+  virtual void Swap(
+      Field* data,
+      const internal::RepeatedFieldAccessor* other_mutator,
+      Field* other_data) const {
+    // Currently RepeatedFieldPrimitiveAccessor is the only implementation of
+    // RepeatedFieldAccessor for primitive types. As we are using singletons
+    // for these accessors, here "other_mutator" must be "this".
+    GOOGLE_CHECK(this == other_mutator);
+    MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+  }
+
+ protected:
+  virtual T ConvertToT(const Value* value) const {
+    return *static_cast<const T*>(value);
+  }
+  virtual const Value* ConvertFromT(const T& value,
+                                    Value* scratch_space) const {
+    return static_cast<const Value*>(&value);
+  }
+};
+
+// Default implementation of RepeatedFieldAccessor for string fields with
+// ctype=STRING.
+class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> {
+  typedef void Field;
+  typedef void Value;
+  using RepeatedFieldAccessor::Add;
+
+ public:
+  RepeatedPtrFieldStringAccessor() {}
+  virtual ~RepeatedPtrFieldStringAccessor() {}
+  virtual void Swap(
+      Field* data,
+      const internal::RepeatedFieldAccessor* other_mutator,
+      Field* other_data) const {
+    if (this == other_mutator) {
+      MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+    } else {
+      RepeatedPtrField<string> tmp;
+      tmp.Swap(MutableRepeatedField(data));
+      int other_size = other_mutator->Size(other_data);
+      for (int i = 0; i < other_size; ++i) {
+        Add<string>(data, other_mutator->Get<string>(other_data, i));
+      }
+      int size = Size(data);
+      other_mutator->Clear(other_data);
+      for (int i = 0; i < size; ++i) {
+        other_mutator->Add<string>(other_data, tmp.Get(i));
+      }
+    }
+  }
+
+ protected:
+  virtual string* New(const Value*) const {
+    return new string();
+  }
+  virtual void ConvertToT(const Value* value, string* result) const {
+    *result = *static_cast<const string*>(value);
+  }
+  virtual const Value* ConvertFromT(const string& value,
+                                    Value* scratch_space) const {
+    return static_cast<const Value*>(&value);
+  }
+};
+
+
+class RepeatedPtrFieldMessageAccessor
+    : public RepeatedPtrFieldWrapper<Message> {
+  typedef void Field;
+  typedef void Value;
+
+ public:
+  RepeatedPtrFieldMessageAccessor() {}
+  virtual ~RepeatedPtrFieldMessageAccessor() {}
+  virtual void Swap(
+      Field* data,
+      const internal::RepeatedFieldAccessor* other_mutator,
+      Field* other_data) const {
+    GOOGLE_CHECK(this == other_mutator);
+    MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+  }
+
+ protected:
+  virtual Message* New(const Value* value) const {
+    return static_cast<const Message*>(value)->New();
+  }
+  virtual void ConvertToT(const Value* value, Message* result) const {
+    result->CopyFrom(*static_cast<const Message*>(value));
+  }
+  virtual const Value* ConvertFromT(const Message& value,
+                                    Value* scratch_space) const {
+    return static_cast<const Value*>(&value);
+  }
+};
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.cc b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.cc
new file mode 100644
index 0000000..4629dec
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.cc
@@ -0,0 +1,269 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+void ReflectionOps::Copy(const Message& from, Message* to) {
+  if (&from == to) return;
+  Clear(to);
+  Merge(from, to);
+}
+
+void ReflectionOps::Merge(const Message& from, Message* to) {
+  GOOGLE_CHECK_NE(&from, to);
+
+  const Descriptor* descriptor = from.GetDescriptor();
+  GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
+    << "Tried to merge messages of different types "
+    << "(merge " << descriptor->full_name()
+    << " to " << to->GetDescriptor()->full_name() << ")";
+
+  const Reflection* from_reflection = from.GetReflection();
+  const Reflection* to_reflection = to->GetReflection();
+
+  vector<const FieldDescriptor*> fields;
+  from_reflection->ListFields(from, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+
+    if (field->is_repeated()) {
+      int count = from_reflection->FieldSize(from, field);
+      for (int j = 0; j < count; j++) {
+        switch (field->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, METHOD)                                     \
+          case FieldDescriptor::CPPTYPE_##CPPTYPE:                       \
+            to_reflection->Add##METHOD(to, field,                        \
+              from_reflection->GetRepeated##METHOD(from, field, j));     \
+            break;
+
+          HANDLE_TYPE(INT32 , Int32 );
+          HANDLE_TYPE(INT64 , Int64 );
+          HANDLE_TYPE(UINT32, UInt32);
+          HANDLE_TYPE(UINT64, UInt64);
+          HANDLE_TYPE(FLOAT , Float );
+          HANDLE_TYPE(DOUBLE, Double);
+          HANDLE_TYPE(BOOL  , Bool  );
+          HANDLE_TYPE(STRING, String);
+          HANDLE_TYPE(ENUM  , Enum  );
+#undef HANDLE_TYPE
+
+          case FieldDescriptor::CPPTYPE_MESSAGE:
+            to_reflection->AddMessage(to, field)->MergeFrom(
+              from_reflection->GetRepeatedMessage(from, field, j));
+            break;
+        }
+      }
+    } else {
+      switch (field->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, METHOD)                                        \
+        case FieldDescriptor::CPPTYPE_##CPPTYPE:                            \
+          to_reflection->Set##METHOD(to, field,                             \
+            from_reflection->Get##METHOD(from, field));                     \
+          break;
+
+        HANDLE_TYPE(INT32 , Int32 );
+        HANDLE_TYPE(INT64 , Int64 );
+        HANDLE_TYPE(UINT32, UInt32);
+        HANDLE_TYPE(UINT64, UInt64);
+        HANDLE_TYPE(FLOAT , Float );
+        HANDLE_TYPE(DOUBLE, Double);
+        HANDLE_TYPE(BOOL  , Bool  );
+        HANDLE_TYPE(STRING, String);
+        HANDLE_TYPE(ENUM  , Enum  );
+#undef HANDLE_TYPE
+
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          to_reflection->MutableMessage(to, field)->MergeFrom(
+            from_reflection->GetMessage(from, field));
+          break;
+      }
+    }
+  }
+
+  to_reflection->MutableUnknownFields(to)->MergeFrom(
+    from_reflection->GetUnknownFields(from));
+}
+
+void ReflectionOps::Clear(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(*message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    reflection->ClearField(message, fields[i]);
+  }
+
+  reflection->MutableUnknownFields(message)->Clear();
+}
+
+bool ReflectionOps::IsInitialized(const Message& message) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = message.GetReflection();
+
+  // Check required fields of this message.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (descriptor->field(i)->is_required()) {
+      if (!reflection->HasField(message, descriptor->field(i))) {
+        return false;
+      }
+    }
+  }
+
+  // Check that sub-messages are initialized.
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+
+      if (field->is_repeated()) {
+        int size = reflection->FieldSize(message, field);
+
+        for (int j = 0; j < size; j++) {
+          if (!reflection->GetRepeatedMessage(message, field, j)
+                          .IsInitialized()) {
+            return false;
+          }
+        }
+      } else {
+        if (!reflection->GetMessage(message, field).IsInitialized()) {
+          return false;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+void ReflectionOps::DiscardUnknownFields(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  reflection->MutableUnknownFields(message)->Clear();
+
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(*message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (field->is_repeated()) {
+        int size = reflection->FieldSize(*message, field);
+        for (int j = 0; j < size; j++) {
+          reflection->MutableRepeatedMessage(message, field, j)
+                    ->DiscardUnknownFields();
+        }
+      } else {
+        reflection->MutableMessage(message, field)->DiscardUnknownFields();
+      }
+    }
+  }
+}
+
+static string SubMessagePrefix(const string& prefix,
+                               const FieldDescriptor* field,
+                               int index) {
+  string result(prefix);
+  if (field->is_extension()) {
+    result.append("(");
+    result.append(field->full_name());
+    result.append(")");
+  } else {
+    result.append(field->name());
+  }
+  if (index != -1) {
+    result.append("[");
+    result.append(SimpleItoa(index));
+    result.append("]");
+  }
+  result.append(".");
+  return result;
+}
+
+void ReflectionOps::FindInitializationErrors(
+    const Message& message,
+    const string& prefix,
+    vector<string>* errors) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = message.GetReflection();
+
+  // Check required fields of this message.
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    if (descriptor->field(i)->is_required()) {
+      if (!reflection->HasField(message, descriptor->field(i))) {
+        errors->push_back(prefix + descriptor->field(i)->name());
+      }
+    }
+  }
+
+  // Check sub-messages.
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+
+      if (field->is_repeated()) {
+        int size = reflection->FieldSize(message, field);
+
+        for (int j = 0; j < size; j++) {
+          const Message& sub_message =
+            reflection->GetRepeatedMessage(message, field, j);
+          FindInitializationErrors(sub_message,
+                                   SubMessagePrefix(prefix, field, j),
+                                   errors);
+        }
+      } else {
+        const Message& sub_message = reflection->GetMessage(message, field);
+        FindInitializationErrors(sub_message,
+                                 SubMessagePrefix(prefix, field, -1),
+                                 errors);
+      }
+    }
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.h b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.h
new file mode 100644
index 0000000..4775911
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops.h
@@ -0,0 +1,81 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
+#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Basic operations that can be performed using reflection.
+// These can be used as a cheap way to implement the corresponding
+// methods of the Message interface, though they are likely to be
+// slower than implementations tailored for the specific message type.
+//
+// This class should stay limited to operations needed to implement
+// the Message interface.
+//
+// This class is really a namespace that contains only static methods.
+class LIBPROTOBUF_EXPORT ReflectionOps {
+ public:
+  static void Copy(const Message& from, Message* to);
+  static void Merge(const Message& from, Message* to);
+  static void Clear(Message* message);
+  static bool IsInitialized(const Message& message);
+  static void DiscardUnknownFields(Message* message);
+
+  // Finds all unset required fields in the message and adds their full
+  // paths (e.g. "foo.bar[5].baz") to *names.  "prefix" will be attached to
+  // the front of each name.
+  static void FindInitializationErrors(const Message& message,
+                                       const string& prefix,
+                                       vector<string>* errors);
+
+ private:
+  // All methods are static.  No need to construct.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps);
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_REFLECTION_OPS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/reflection_ops_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops_unittest.cc
new file mode 100644
index 0000000..88d6bfb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/reflection_ops_unittest.cc
@@ -0,0 +1,476 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(ReflectionOpsTest, SanityCheck) {
+  unittest::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(ReflectionOpsTest, Copy) {
+  unittest::TestAllTypes message, message2;
+
+  TestUtil::SetAllFields(&message);
+
+  ReflectionOps::Copy(message, &message2);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  ReflectionOps::Copy(message2, &message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(ReflectionOpsTest, CopyExtensions) {
+  unittest::TestAllExtensions message, message2;
+
+  TestUtil::SetAllExtensions(&message);
+
+  ReflectionOps::Copy(message, &message2);
+
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ReflectionOpsTest, CopyOneof) {
+  unittest::TestOneof2 message, message2;
+  TestUtil::SetOneof1(&message);
+  ReflectionOps::Copy(message, &message2);
+  TestUtil::ExpectOneofSet1(message2);
+
+  TestUtil::SetOneof2(&message);
+  TestUtil::ExpectOneofSet2(message);
+  ReflectionOps::Copy(message, &message2);
+  TestUtil::ExpectOneofSet2(message2);
+}
+
+TEST(ReflectionOpsTest, Merge) {
+  // Note:  Copy is implemented in terms of Merge() so technically the Copy
+  //   test already tested most of this.
+
+  unittest::TestAllTypes message, message2;
+
+  TestUtil::SetAllFields(&message);
+
+  // This field will test merging into an empty spot.
+  message2.set_optional_int32(message.optional_int32());
+  message.clear_optional_int32();
+
+  // This tests overwriting.
+  message2.set_optional_string(message.optional_string());
+  message.set_optional_string("something else");
+
+  // This tests concatenating.
+  message2.add_repeated_int32(message.repeated_int32(1));
+  int32 i = message.repeated_int32(0);
+  message.clear_repeated_int32();
+  message.add_repeated_int32(i);
+
+  ReflectionOps::Merge(message2, &message);
+
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(ReflectionOpsTest, MergeExtensions) {
+  // Note:  Copy is implemented in terms of Merge() so technically the Copy
+  //   test already tested most of this.
+
+  unittest::TestAllExtensions message, message2;
+
+  TestUtil::SetAllExtensions(&message);
+
+  // This field will test merging into an empty spot.
+  message2.SetExtension(unittest::optional_int32_extension,
+    message.GetExtension(unittest::optional_int32_extension));
+  message.ClearExtension(unittest::optional_int32_extension);
+
+  // This tests overwriting.
+  message2.SetExtension(unittest::optional_string_extension,
+    message.GetExtension(unittest::optional_string_extension));
+  message.SetExtension(unittest::optional_string_extension, "something else");
+
+  // This tests concatenating.
+  message2.AddExtension(unittest::repeated_int32_extension,
+    message.GetExtension(unittest::repeated_int32_extension, 1));
+  int32 i = message.GetExtension(unittest::repeated_int32_extension, 0);
+  message.ClearExtension(unittest::repeated_int32_extension);
+  message.AddExtension(unittest::repeated_int32_extension, i);
+
+  ReflectionOps::Merge(message2, &message);
+
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
+TEST(ReflectionOpsTest, MergeUnknown) {
+  // Test that the messages' UnknownFieldSets are correctly merged.
+  unittest::TestEmptyMessage message1, message2;
+  message1.mutable_unknown_fields()->AddVarint(1234, 1);
+  message2.mutable_unknown_fields()->AddVarint(1234, 2);
+
+  ReflectionOps::Merge(message2, &message1);
+
+  ASSERT_EQ(2, message1.unknown_fields().field_count());
+  ASSERT_EQ(UnknownField::TYPE_VARINT,
+            message1.unknown_fields().field(0).type());
+  EXPECT_EQ(1, message1.unknown_fields().field(0).varint());
+  ASSERT_EQ(UnknownField::TYPE_VARINT,
+            message1.unknown_fields().field(1).type());
+  EXPECT_EQ(2, message1.unknown_fields().field(1).varint());
+}
+
+TEST(ReflectionOpsTest, MergeOneof) {
+  unittest::TestOneof2 message1, message2;
+  TestUtil::SetOneof1(&message1);
+
+  // Merge to empty message
+  ReflectionOps::Merge(message1, &message2);
+  TestUtil::ExpectOneofSet1(message2);
+
+  // Merge with the same oneof fields
+  ReflectionOps::Merge(message1, &message2);
+  TestUtil::ExpectOneofSet1(message2);
+
+  // Merge with different oneof fields
+  TestUtil::SetOneof2(&message1);
+  ReflectionOps::Merge(message1, &message2);
+  TestUtil::ExpectOneofSet2(message2);
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+TEST(ReflectionOpsTest, MergeFromSelf) {
+  // Note:  Copy is implemented in terms of Merge() so technically the Copy
+  //   test already tested most of this.
+
+  unittest::TestAllTypes message;
+
+  EXPECT_DEATH(
+    ReflectionOps::Merge(message, &message),
+    "&from");
+}
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(ReflectionOpsTest, Clear) {
+  unittest::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+
+  ReflectionOps::Clear(&message);
+
+  TestUtil::ExpectClear(message);
+
+  // Check that getting embedded messages returns the objects created during
+  // SetAllFields() rather than default instances.
+  EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
+            &message.optionalgroup());
+  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
+            &message.optional_foreign_message());
+  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
+            &message.optional_import_message());
+}
+
+TEST(ReflectionOpsTest, ClearExtensions) {
+  unittest::TestAllExtensions message;
+
+  TestUtil::SetAllExtensions(&message);
+
+  ReflectionOps::Clear(&message);
+
+  TestUtil::ExpectExtensionsClear(message);
+
+  // Check that getting embedded messages returns the objects created during
+  // SetAllExtensions() rather than default instances.
+  EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(),
+            &message.GetExtension(unittest::optionalgroup_extension));
+  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.GetExtension(unittest::optional_nested_message_extension));
+  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
+            &message.GetExtension(
+              unittest::optional_foreign_message_extension));
+  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
+            &message.GetExtension(unittest::optional_import_message_extension));
+}
+
+TEST(ReflectionOpsTest, ClearUnknown) {
+  // Test that the message's UnknownFieldSet is correctly cleared.
+  unittest::TestEmptyMessage message;
+  message.mutable_unknown_fields()->AddVarint(1234, 1);
+
+  ReflectionOps::Clear(&message);
+
+  EXPECT_EQ(0, message.unknown_fields().field_count());
+}
+
+TEST(ReflectionOpsTest, ClearOneof) {
+  unittest::TestOneof2 message;
+
+  TestUtil::ExpectOneofClear(message);
+  TestUtil::SetOneof1(&message);
+  TestUtil::ExpectOneofSet1(message);
+  ReflectionOps::Clear(&message);
+  TestUtil::ExpectOneofClear(message);
+
+  TestUtil::SetOneof1(&message);
+  TestUtil::ExpectOneofSet1(message);
+  TestUtil::SetOneof2(&message);
+  TestUtil::ExpectOneofSet2(message);
+  ReflectionOps::Clear(&message);
+  TestUtil::ExpectOneofClear(message);
+}
+
+TEST(ReflectionOpsTest, DiscardUnknownFields) {
+  unittest::TestAllTypes message;
+  TestUtil::SetAllFields(&message);
+
+  // Set some unknown fields in message.
+  message.mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+  message.mutable_optional_nested_message()
+        ->mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+  message.mutable_repeated_nested_message(0)
+        ->mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+
+  EXPECT_EQ(1, message.unknown_fields().field_count());
+  EXPECT_EQ(1, message.optional_nested_message()
+                      .unknown_fields().field_count());
+  EXPECT_EQ(1, message.repeated_nested_message(0)
+                      .unknown_fields().field_count());
+
+  // Discard them.
+  ReflectionOps::DiscardUnknownFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+
+  EXPECT_EQ(0, message.unknown_fields().field_count());
+  EXPECT_EQ(0, message.optional_nested_message()
+                      .unknown_fields().field_count());
+  EXPECT_EQ(0, message.repeated_nested_message(0)
+                      .unknown_fields().field_count());
+}
+
+TEST(ReflectionOpsTest, DiscardUnknownExtensions) {
+  unittest::TestAllExtensions message;
+  TestUtil::SetAllExtensions(&message);
+
+  // Set some unknown fields.
+  message.mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+  message.MutableExtension(unittest::optional_nested_message_extension)
+        ->mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+  message.MutableExtension(unittest::repeated_nested_message_extension, 0)
+        ->mutable_unknown_fields()
+        ->AddVarint(123456, 654321);
+
+  EXPECT_EQ(1, message.unknown_fields().field_count());
+  EXPECT_EQ(1,
+    message.GetExtension(unittest::optional_nested_message_extension)
+           .unknown_fields().field_count());
+  EXPECT_EQ(1,
+    message.GetExtension(unittest::repeated_nested_message_extension, 0)
+           .unknown_fields().field_count());
+
+  // Discard them.
+  ReflectionOps::DiscardUnknownFields(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+
+  EXPECT_EQ(0, message.unknown_fields().field_count());
+  EXPECT_EQ(0,
+    message.GetExtension(unittest::optional_nested_message_extension)
+           .unknown_fields().field_count());
+  EXPECT_EQ(0,
+    message.GetExtension(unittest::repeated_nested_message_extension, 0)
+           .unknown_fields().field_count());
+}
+
+TEST(ReflectionOpsTest, IsInitialized) {
+  unittest::TestRequired message;
+
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  message.set_a(1);
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  message.set_b(2);
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  message.set_c(3);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+}
+
+TEST(ReflectionOpsTest, ForeignIsInitialized) {
+  unittest::TestRequiredForeign message;
+
+  // Starts out initialized because the foreign message is itself an optional
+  // field.
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  // Once we create that field, the message is no longer initialized.
+  message.mutable_optional_message();
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+
+  // Initialize it.  Now we're initialized.
+  message.mutable_optional_message()->set_a(1);
+  message.mutable_optional_message()->set_b(2);
+  message.mutable_optional_message()->set_c(3);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  // Add a repeated version of the message.  No longer initialized.
+  unittest::TestRequired* sub_message = message.add_repeated_message();
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+
+  // Initialize that repeated version.
+  sub_message->set_a(1);
+  sub_message->set_b(2);
+  sub_message->set_c(3);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+}
+
+TEST(ReflectionOpsTest, ExtensionIsInitialized) {
+  unittest::TestAllExtensions message;
+
+  // Starts out initialized because the foreign message is itself an optional
+  // field.
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  // Once we create that field, the message is no longer initialized.
+  message.MutableExtension(unittest::TestRequired::single);
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+
+  // Initialize it.  Now we're initialized.
+  message.MutableExtension(unittest::TestRequired::single)->set_a(1);
+  message.MutableExtension(unittest::TestRequired::single)->set_b(2);
+  message.MutableExtension(unittest::TestRequired::single)->set_c(3);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  // Add a repeated version of the message.  No longer initialized.
+  message.AddExtension(unittest::TestRequired::multi);
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+
+  // Initialize that repeated version.
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
+  message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+}
+
+TEST(ReflectionOpsTest, OneofIsInitialized) {
+  unittest::TestRequiredOneof message;
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  message.mutable_foo_message();
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+
+  message.set_foo_int(1);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+
+  message.mutable_foo_message();
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  message.mutable_foo_message()->set_required_double(0.1);
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+}
+
+static string FindInitializationErrors(const Message& message) {
+  vector<string> errors;
+  ReflectionOps::FindInitializationErrors(message, "", &errors);
+  return Join(errors, ",");
+}
+
+TEST(ReflectionOpsTest, FindInitializationErrors) {
+  unittest::TestRequired message;
+  EXPECT_EQ("a,b,c", FindInitializationErrors(message));
+}
+
+TEST(ReflectionOpsTest, FindForeignInitializationErrors) {
+  unittest::TestRequiredForeign message;
+  message.mutable_optional_message();
+  message.add_repeated_message();
+  message.add_repeated_message();
+  EXPECT_EQ("optional_message.a,"
+            "optional_message.b,"
+            "optional_message.c,"
+            "repeated_message[0].a,"
+            "repeated_message[0].b,"
+            "repeated_message[0].c,"
+            "repeated_message[1].a,"
+            "repeated_message[1].b,"
+            "repeated_message[1].c",
+            FindInitializationErrors(message));
+}
+
+TEST(ReflectionOpsTest, FindExtensionInitializationErrors) {
+  unittest::TestAllExtensions message;
+  message.MutableExtension(unittest::TestRequired::single);
+  message.AddExtension(unittest::TestRequired::multi);
+  message.AddExtension(unittest::TestRequired::multi);
+  EXPECT_EQ("(protobuf_unittest.TestRequired.single).a,"
+            "(protobuf_unittest.TestRequired.single).b,"
+            "(protobuf_unittest.TestRequired.single).c,"
+            "(protobuf_unittest.TestRequired.multi)[0].a,"
+            "(protobuf_unittest.TestRequired.multi)[0].b,"
+            "(protobuf_unittest.TestRequired.multi)[0].c,"
+            "(protobuf_unittest.TestRequired.multi)[1].a,"
+            "(protobuf_unittest.TestRequired.multi)[1].b,"
+            "(protobuf_unittest.TestRequired.multi)[1].c",
+            FindInitializationErrors(message));
+}
+
+TEST(ReflectionOpsTest, FindOneofInitializationErrors) {
+  unittest::TestRequiredOneof message;
+  message.mutable_foo_message();
+  EXPECT_EQ("foo_message.required_double",
+            FindInitializationErrors(message));
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/repeated_field.cc b/src/third_party/protobuf-3/src/google/protobuf/repeated_field.cc
new file mode 100644
index 0000000..77004f5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/repeated_field.cc
@@ -0,0 +1,102 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
+  int new_size = current_size_ + extend_amount;
+  if (total_size_ >= new_size) {
+    // N.B.: rep_ is non-NULL because extend_amount is always > 0, hence
+    // total_size must be non-zero since it is lower-bounded by new_size.
+    return &rep_->elements[current_size_];
+  }
+  Rep* old_rep = rep_;
+  Arena* arena = GetArenaNoVirtual();
+  new_size = std::max(kMinRepeatedFieldAllocationSize,
+                      std::max(total_size_ * 2, new_size));
+  GOOGLE_CHECK_LE(new_size,
+           (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+           sizeof(old_rep->elements[0]))
+      << "Requested size is too large to fit into size_t.";
+  if (arena == NULL) {
+    rep_ = reinterpret_cast<Rep*>(
+        new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]);
+  } else {
+    rep_ = reinterpret_cast<Rep*>(
+        ::google::protobuf::Arena::CreateArray<char>(arena,
+            kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size));
+  }
+  total_size_ = new_size;
+  if (old_rep && old_rep->allocated_size > 0) {
+    memcpy(rep_->elements, old_rep->elements,
+           old_rep->allocated_size * sizeof(rep_->elements[0]));
+    rep_->allocated_size = old_rep->allocated_size;
+  } else {
+    rep_->allocated_size = 0;
+  }
+  if (arena == NULL) {
+    delete [] reinterpret_cast<char*>(old_rep);
+  }
+  return &rep_->elements[current_size_];
+}
+
+void RepeatedPtrFieldBase::Reserve(int new_size) {
+  if (new_size > current_size_) {
+    InternalExtend(new_size - current_size_);
+  }
+}
+
+void RepeatedPtrFieldBase::CloseGap(int start, int num) {
+  if (rep_ == NULL) return;
+  // Close up a gap of "num" elements starting at offset "start".
+  for (int i = start + num; i < rep_->allocated_size; ++i)
+    rep_->elements[i - num] = rep_->elements[i];
+  current_size_ -= num;
+  rep_->allocated_size -= num;
+}
+
+}  // namespace internal
+
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/repeated_field.h b/src/third_party/protobuf-3/src/google/protobuf/repeated_field.h
new file mode 100644
index 0000000..1961bc4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/repeated_field.h
@@ -0,0 +1,2483 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// RepeatedField and RepeatedPtrField are used by generated protocol message
+// classes to manipulate repeated fields.  These classes are very similar to
+// STL's vector, but include a number of optimizations found to be useful
+// specifically in the case of Protocol Buffers.  RepeatedPtrField is
+// particularly different from STL vector as it manages ownership of the
+// pointers that it contains.
+//
+// Typically, clients should not need to access RepeatedField objects directly,
+// but should instead use the accessor functions generated automatically by the
+// protocol compiler.
+
+#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
+#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
+
+#ifdef _MSC_VER
+// This is required for min/max on VS2013 only.
+#include <algorithm>
+#endif
+
+#include <string>
+#include <iterator>
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/type_traits.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
+
+namespace google {
+
+namespace upb {
+namespace google_opensource {
+class GMR_Handlers;
+}  // namespace google_opensource
+}  // namespace upb
+
+namespace protobuf {
+
+class Message;
+
+namespace internal {
+
+static const int kMinRepeatedFieldAllocationSize = 4;
+
+// A utility function for logging that doesn't need any template types.
+void LogIndexOutOfBounds(int index, int size);
+
+template <typename Iter>
+inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
+  return std::distance(begin, end);
+}
+
+template <typename Iter>
+inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
+                            std::input_iterator_tag /*unused*/) {
+  return -1;
+}
+
+template <typename Iter>
+inline int CalculateReserve(Iter begin, Iter end) {
+  typedef typename std::iterator_traits<Iter>::iterator_category Category;
+  return CalculateReserve(begin, end, Category());
+}
+}  // namespace internal
+
+
+// RepeatedField is used to represent repeated fields of a primitive type (in
+// other words, everything except strings and nested Messages).  Most users will
+// not ever use a RepeatedField directly; they will use the get-by-index,
+// set-by-index, and add accessors that are generated for all repeated fields.
+template <typename Element>
+class RepeatedField {
+ public:
+  RepeatedField();
+  explicit RepeatedField(Arena* arena);
+  RepeatedField(const RepeatedField& other);
+  template <typename Iter>
+  RepeatedField(Iter begin, const Iter& end);
+  ~RepeatedField();
+
+  RepeatedField& operator=(const RepeatedField& other);
+
+  bool empty() const;
+  int size() const;
+
+  const Element& Get(int index) const;
+  Element* Mutable(int index);
+  void Set(int index, const Element& value);
+  void Add(const Element& value);
+  Element* Add();
+  // Remove the last element in the array.
+  void RemoveLast();
+
+  // Extract elements with indices in "[start .. start+num-1]".
+  // Copy them into "elements[0 .. num-1]" if "elements" is not NULL.
+  // Caution: implementation also moves elements with indices [start+num ..].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  void ExtractSubrange(int start, int num, Element* elements);
+
+  void Clear();
+  void MergeFrom(const RepeatedField& other);
+  void CopyFrom(const RepeatedField& other);
+
+  // Reserve space to expand the field to at least the given size.  If the
+  // array is grown, it will always be at least doubled in size.
+  void Reserve(int new_size);
+
+  // Resize the RepeatedField to a new, smaller size.  This is O(1).
+  void Truncate(int new_size);
+
+  void AddAlreadyReserved(const Element& value);
+  Element* AddAlreadyReserved();
+  int Capacity() const;
+
+  // Like STL resize.  Uses value to fill appended elements.
+  // Like Truncate() if new_size <= size(), otherwise this is
+  // O(new_size - size()).
+  void Resize(int new_size, const Element& value);
+
+  // Gets the underlying array.  This pointer is possibly invalidated by
+  // any add or remove operation.
+  Element* mutable_data();
+  const Element* data() const;
+
+  // Swap entire contents with "other". If they are separate arenas then, copies
+  // data between each other.
+  void Swap(RepeatedField* other);
+
+  // Swap entire contents with "other". Should be called only if the caller can
+  // guarantee that both repeated fields are on the same arena or are on the
+  // heap. Swapping between different arenas is disallowed and caught by a
+  // GOOGLE_DCHECK (see API docs for details).
+  void UnsafeArenaSwap(RepeatedField* other);
+
+  // Swap two elements.
+  void SwapElements(int index1, int index2);
+
+  // STL-like iterator support
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+  typedef Element value_type;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef int size_type;
+  typedef ptrdiff_t difference_type;
+
+  iterator begin();
+  const_iterator begin() const;
+  const_iterator cbegin() const;
+  iterator end();
+  const_iterator end() const;
+  const_iterator cend() const;
+
+  // Reverse iterator support
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  reverse_iterator rbegin() {
+    return reverse_iterator(end());
+  }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  reverse_iterator rend() {
+    return reverse_iterator(begin());
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+
+  // Returns the number of bytes used by the repeated field, excluding
+  // sizeof(*this)
+  int SpaceUsedExcludingSelf() const;
+
+  // Removes the element referenced by position.
+  //
+  // Returns an iterator to the element immediately following the removed
+  // element.
+  //
+  // Invalidates all iterators at or after the removed element, including end().
+  iterator erase(const_iterator position);
+
+  // Removes the elements in the range [first, last).
+  //
+  // Returns an iterator to the element immediately following the removed range.
+  //
+  // Invalidates all iterators at or after the removed range, including end().
+  iterator erase(const_iterator first, const_iterator last);
+
+  // Get the Arena on which this RepeatedField stores its elements.
+  ::google::protobuf::Arena* GetArena() const {
+    return GetArenaNoVirtual();
+  }
+
+ private:
+  static const int kInitialSize = 0;
+  // A note on the representation here (see also comment below for
+  // RepeatedPtrFieldBase's struct Rep):
+  //
+  // We maintain the same sizeof(RepeatedField) as before we added arena support
+  // so that we do not degrade performance by bloating memory usage. Directly
+  // adding an arena_ element to RepeatedField is quite costly. By using
+  // indirection in this way, we keep the same size when the RepeatedField is
+  // empty (common case), and add only an 8-byte header to the elements array
+  // when non-empty. We make sure to place the size fields directly in the
+  // RepeatedField class to avoid costly cache misses due to the indirection.
+  int current_size_;
+  int total_size_;
+  struct Rep {
+    Arena* arena;
+    Element elements[1];
+  };
+  // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on
+  // the struct. We can not use sizeof(Arena*) as well because there might be
+  // a "gap" after the field arena and before the field elements (e.g., when
+  // Element is double and pointer is 32bit).
+  static const size_t kRepHeaderSize;
+  // Contains arena ptr and the elements array. We also keep the invariant that
+  // if rep_ is NULL, then arena is NULL.
+  Rep* rep_;
+
+  friend class Arena;
+  typedef void InternalArenaConstructable_;
+
+  // Move the contents of |from| into |to|, possibly clobbering |from| in the
+  // process.  For primitive types this is just a memcpy(), but it could be
+  // specialized for non-primitive types to, say, swap each element instead.
+  void MoveArray(Element* to, Element* from, int size);
+
+  // Copy the elements of |from| into |to|.
+  void CopyArray(Element* to, const Element* from, int size);
+
+  inline void InternalSwap(RepeatedField* other);
+
+  // Internal helper expected by Arena methods.
+  inline Arena* GetArenaNoVirtual() const {
+    return (rep_ == NULL) ? NULL : rep_->arena;
+  }
+
+  // Internal helper to delete all elements and deallocate the storage.
+  // If Element has a trivial destructor (for example, if it's a fundamental
+  // type, like int32), the loop will be removed by the optimizer.
+  void InternalDeallocate(Rep* rep, int size) {
+    if (rep != NULL) {
+      Element* e = &rep->elements[0];
+      Element* limit = &rep->elements[size];
+      for (; e < limit; e++) {
+        e->Element::~Element();
+      }
+      if (rep->arena == NULL) {
+        delete[] reinterpret_cast<char*>(rep);
+      }
+    }
+  }
+};
+
+template<typename Element>
+const size_t RepeatedField<Element>::kRepHeaderSize =
+    reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16;
+
+namespace internal {
+template <typename It> class RepeatedPtrIterator;
+template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator;
+}  // namespace internal
+
+namespace internal {
+
+// This is a helper template to copy an array of elements effeciently when they
+// have a trivial copy constructor, and correctly otherwise. This really
+// shouldn't be necessary, but our compiler doesn't optimize std::copy very
+// effectively.
+template <typename Element,
+          bool HasTrivialCopy = has_trivial_copy<Element>::value>
+struct ElementCopier {
+  void operator()(Element* to, const Element* from, int array_size);
+};
+
+}  // namespace internal
+
+namespace internal {
+
+// type-traits helper for RepeatedPtrFieldBase: we only want to invoke
+// arena-related "copy if on different arena" behavior if the necessary methods
+// exist on the contained type. In particular, we rely on MergeFrom() existing
+// as a general proxy for the fact that a copy will work, and we also provide a
+// specific override for string*.
+template<typename T>
+struct TypeImplementsMergeBehavior {
+  typedef char HasMerge;
+  typedef long HasNoMerge;
+
+  // We accept either of:
+  // - void MergeFrom(const T& other)
+  // - bool MergeFrom(const T& other)
+  //
+  // We mangle these names a bit to avoid compatibility issues in 'unclean'
+  // include environments that may have, e.g., "#define test ..." (yes, this
+  // exists).
+  template<typename U, typename RetType, RetType (U::*)(const U& arg)>
+      struct CheckType;
+  template<typename U> static HasMerge Check(
+      CheckType<U, void, &U::MergeFrom>*);
+  template<typename U> static HasMerge Check(
+      CheckType<U, bool, &U::MergeFrom>*);
+  template<typename U> static HasNoMerge Check(...);
+
+  // Resovles to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
+  typedef google::protobuf::internal::integral_constant<bool,
+               (sizeof(Check<T>(0)) == sizeof(HasMerge))> type;
+};
+
+template<>
+struct TypeImplementsMergeBehavior< ::std::string > {
+  typedef google::protobuf::internal::true_type type;
+};
+
+// This is the common base class for RepeatedPtrFields.  It deals only in void*
+// pointers.  Users should not use this interface directly.
+//
+// The methods of this interface correspond to the methods of RepeatedPtrField,
+// but may have a template argument called TypeHandler.  Its signature is:
+//   class TypeHandler {
+//    public:
+//     typedef MyType Type;
+//     static Type* New();
+//     static void Delete(Type*);
+//     static void Clear(Type*);
+//     static void Merge(const Type& from, Type* to);
+//
+//     // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
+//     static int SpaceUsed(const Type&);
+//   };
+class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
+ protected:
+  // The reflection implementation needs to call protected methods directly,
+  // reinterpreting pointers as being to Message instead of a specific Message
+  // subclass.
+  friend class GeneratedMessageReflection;
+
+  // ExtensionSet stores repeated message extensions as
+  // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to
+  // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf()
+  // reinterpreting MessageLite as Message.  ExtensionSet also needs to make
+  // use of AddFromCleared(), which is not part of the public interface.
+  friend class ExtensionSet;
+
+  // The MapFieldBase implementation needs to call protected methods directly,
+  // reinterpreting pointers as being to Message instead of a specific Message
+  // subclass.
+  friend class MapFieldBase;
+
+  // To parse directly into a proto2 generated class, the upb class GMR_Handlers
+  // needs to be able to modify a RepeatedPtrFieldBase directly.
+  friend class upb::google_opensource::GMR_Handlers;
+
+  RepeatedPtrFieldBase();
+  explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena);
+  ~RepeatedPtrFieldBase() {}
+
+  // Must be called from destructor.
+  template <typename TypeHandler>
+  void Destroy();
+
+  bool empty() const;
+  int size() const;
+
+  template <typename TypeHandler>
+  const typename TypeHandler::Type& Get(int index) const;
+  template <typename TypeHandler>
+  typename TypeHandler::Type* Mutable(int index);
+  template <typename TypeHandler>
+  void Delete(int index);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL);
+
+  template <typename TypeHandler>
+  void RemoveLast();
+  template <typename TypeHandler>
+  void Clear();
+  template <typename TypeHandler>
+  void MergeFrom(const RepeatedPtrFieldBase& other);
+  template <typename TypeHandler>
+  void CopyFrom(const RepeatedPtrFieldBase& other);
+
+  void CloseGap(int start, int num);
+
+  void Reserve(int new_size);
+
+  int Capacity() const;
+
+  // Used for constructing iterators.
+  void* const* raw_data() const;
+  void** raw_mutable_data() const;
+
+  template <typename TypeHandler>
+  typename TypeHandler::Type** mutable_data();
+  template <typename TypeHandler>
+  const typename TypeHandler::Type* const* data() const;
+
+  template <typename TypeHandler>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
+
+  void SwapElements(int index1, int index2);
+
+  template <typename TypeHandler>
+  int SpaceUsedExcludingSelf() const;
+
+
+  // Advanced memory management --------------------------------------
+
+  // Like Add(), but if there are no cleared objects to use, returns NULL.
+  template <typename TypeHandler>
+  typename TypeHandler::Type* AddFromCleared();
+
+  template<typename TypeHandler>
+  void AddAllocated(typename TypeHandler::Type* value) {
+    typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
+    AddAllocatedInternal<TypeHandler>(value, t);
+  }
+
+  template <typename TypeHandler>
+  void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
+
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseLast() {
+    typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
+    return ReleaseLastInternal<TypeHandler>(t);
+  }
+
+  // Releases last element and returns it, but does not do out-of-arena copy.
+  // And just returns the raw pointer to the contained element in the arena.
+  template <typename TypeHandler>
+  typename TypeHandler::Type* UnsafeArenaReleaseLast();
+
+  int ClearedCount() const;
+  template <typename TypeHandler>
+  void AddCleared(typename TypeHandler::Type* value);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseCleared();
+
+ protected:
+  inline void InternalSwap(RepeatedPtrFieldBase* other);
+
+  template <typename TypeHandler>
+  void AddAllocatedInternal(typename TypeHandler::Type* value,
+                            google::protobuf::internal::true_type);
+  template <typename TypeHandler>
+  void AddAllocatedInternal(typename TypeHandler::Type* value,
+                            google::protobuf::internal::false_type);
+
+  template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+  void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
+                                Arena* value_arena,
+                                Arena* my_arena);
+  template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+  void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value);
+
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type);
+  template <typename TypeHandler>
+  typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type);
+
+  template<typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+  void SwapFallback(RepeatedPtrFieldBase* other);
+
+  inline Arena* GetArenaNoVirtual() const {
+    return arena_;
+  }
+
+ private:
+  static const int kInitialSize = 0;
+  // A few notes on internal representation:
+  //
+  // We use an indirected approach, with struct Rep, to keep
+  // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support
+  // was added, namely, 3 8-byte machine words on x86-64. An instance of Rep is
+  // allocated only when the repeated field is non-empty, and it is a
+  // dynamically-sized struct (the header is directly followed by elements[]).
+  // We place arena_ and current_size_ directly in the object to avoid cache
+  // misses due to the indirection, because these fields are checked frequently.
+  // Placing all fields directly in the RepeatedPtrFieldBase instance costs
+  // significant performance for memory-sensitive workloads.
+  Arena* arena_;
+  int    current_size_;
+  int    total_size_;
+  struct Rep {
+    int    allocated_size;
+    void*  elements[1];
+  };
+  static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*);
+  // Contains arena ptr and the elements array. We also keep the invariant that
+  // if rep_ is NULL, then arena is NULL.
+  Rep* rep_;
+
+  template <typename TypeHandler>
+  static inline typename TypeHandler::Type* cast(void* element) {
+    return reinterpret_cast<typename TypeHandler::Type*>(element);
+  }
+  template <typename TypeHandler>
+  static inline const typename TypeHandler::Type* cast(const void* element) {
+    return reinterpret_cast<const typename TypeHandler::Type*>(element);
+  }
+
+  // Non-templated inner function to avoid code duplication. Takes a function
+  // pointer to the type-specific (templated) inner allocate/merge loop.
+  void MergeFromInternal(
+      const RepeatedPtrFieldBase& other,
+      void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int));
+
+  template<typename TypeHandler>
+  void MergeFromInnerLoop(
+      void** our_elems, void** other_elems, int length, int already_allocated);
+
+  // Internal helper: extend array space if necessary to contain |extend_amount|
+  // more elements, and return a pointer to the element immediately following
+  // the old list of elements.  This interface factors out common behavior from
+  // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
+  void** InternalExtend(int extend_amount);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
+};
+
+template <typename GenericType>
+class GenericTypeHandler {
+ public:
+  typedef GenericType Type;
+  static inline GenericType* New(Arena* arena) {
+    return ::google::protobuf::Arena::CreateMaybeMessage<Type>(
+        arena, static_cast<GenericType*>(0));
+  }
+  // We force NewFromPrototype() and Delete() to be non-inline to reduce code
+  // size: else, several other methods get inlined copies of message types'
+  // constructors and destructors.
+  GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype(
+      const GenericType* prototype, ::google::protobuf::Arena* arena = NULL);
+  GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena);
+  static inline ::google::protobuf::Arena* GetArena(GenericType* value) {
+    return ::google::protobuf::Arena::GetArena<Type>(value);
+  }
+  static inline void* GetMaybeArenaPointer(GenericType* value) {
+    return ::google::protobuf::Arena::GetArena<Type>(value);
+  }
+
+  static inline void Clear(GenericType* value) { value->Clear(); }
+  GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from,
+                                       GenericType* to);
+  static inline int SpaceUsed(const GenericType& value) {
+    return value.SpaceUsed();
+  }
+  static inline const Type& default_instance() {
+    return Type::default_instance();
+  }
+};
+
+template <typename GenericType>
+GenericType* GenericTypeHandler<GenericType>::NewFromPrototype(
+    const GenericType* /* prototype */, ::google::protobuf::Arena* arena) {
+  return New(arena);
+}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Delete(GenericType* value, Arena* arena) {
+  if (arena == NULL) {
+    delete value;
+  }
+}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Merge(const GenericType& from,
+                                            GenericType* to) {
+  to->MergeFrom(from);
+}
+
+// NewFromPrototype() and Merge() cannot be defined here; if they're declared
+// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE
+// above, and if not, compilation will result in multiple definitions.  These
+// are therefore declared as specializations here and defined in
+// message_lite.cc.
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+    const MessageLite* prototype, google::protobuf::Arena* arena);
+template<>
+inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
+    MessageLite* value) {
+  return value->GetArena();
+}
+template<>
+inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
+    MessageLite* value) {
+  return value->GetMaybeArenaPointer();
+}
+template <>
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+                                            MessageLite* to);
+template<>
+inline void GenericTypeHandler<string>::Clear(string* value) {
+  value->clear();
+}
+template<>
+void GenericTypeHandler<string>::Merge(const string& from,
+                                       string* to);
+
+// Declarations of the specialization as we cannot define them here, as the
+// header that defines ProtocolMessage depends on types defined in this header.
+#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName)                 \
+    template<>                                                                 \
+    TypeName* GenericTypeHandler<TypeName>::NewFromPrototype(                  \
+        const TypeName* prototype, google::protobuf::Arena* arena);                      \
+    template<>                                                                 \
+    google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena(                     \
+        TypeName* value);                                                      \
+    template<>                                                                 \
+    void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer(                  \
+        TypeName* value);
+
+// Message specialization bodies defined in message.cc. This split is necessary
+// to allow proto2-lite (which includes this header) to be independent of
+// Message.
+DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message)
+
+
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
+
+template <>
+inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
+  // Yes, the behavior of the code is undefined, but this function is only
+  // called when we're already deep into the world of undefined, because the
+  // caller called Get(index) out of bounds.
+  MessageLite* null = NULL;
+  return *null;
+}
+
+template <>
+inline const Message& GenericTypeHandler<Message>::default_instance() {
+  // Yes, the behavior of the code is undefined, but this function is only
+  // called when we're already deep into the world of undefined, because the
+  // caller called Get(index) out of bounds.
+  Message* null = NULL;
+  return *null;
+}
+
+
+// HACK:  If a class is declared as DLL-exported in MSVC, it insists on
+//   generating copies of all its methods -- even inline ones -- to include
+//   in the DLL.  But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
+//   isn't in the lite library, therefore the lite library cannot link if
+//   StringTypeHandler is exported.  So, we factor out StringTypeHandlerBase,
+//   export that, then make StringTypeHandler be a subclass which is NOT
+//   exported.
+// TODO(kenton):  Now that StringSpaceUsedExcludingSelf() is in the lite
+//   library, this can be cleaned up.
+class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
+ public:
+  typedef string Type;
+
+  static inline string* New(Arena* arena) {
+    return Arena::Create<string>(arena);
+  }
+  static inline string* NewFromPrototype(const string*,
+                                         ::google::protobuf::Arena* arena) {
+    return New(arena);
+  }
+  static inline ::google::protobuf::Arena* GetArena(string*) {
+    return NULL;
+  }
+  static inline void* GetMaybeArenaPointer(string* /* value */) {
+    return NULL;
+  }
+  static inline void Delete(string* value, Arena* arena) {
+    if (arena == NULL) {
+      delete value;
+    }
+  }
+  static inline void Clear(string* value) { value->clear(); }
+  static inline void Merge(const string& from, string* to) { *to = from; }
+  static inline const Type& default_instance() {
+    return ::google::protobuf::internal::GetEmptyString();
+  }
+};
+
+class StringTypeHandler : public StringTypeHandlerBase {
+ public:
+  static int SpaceUsed(const string& value)  {
+    return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value);
+  }
+};
+
+
+}  // namespace internal
+
+// RepeatedPtrField is like RepeatedField, but used for repeated strings or
+// Messages.
+template <typename Element>
+class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
+ public:
+  RepeatedPtrField();
+  explicit RepeatedPtrField(::google::protobuf::Arena* arena);
+
+  RepeatedPtrField(const RepeatedPtrField& other);
+  template <typename Iter>
+  RepeatedPtrField(Iter begin, const Iter& end);
+  ~RepeatedPtrField();
+
+  RepeatedPtrField& operator=(const RepeatedPtrField& other);
+
+  bool empty() const;
+  int size() const;
+
+  const Element& Get(int index) const;
+  Element* Mutable(int index);
+  Element* Add();
+
+  // Remove the last element in the array.
+  // Ownership of the element is retained by the array.
+  void RemoveLast();
+
+  // Delete elements with indices in the range [start .. start+num-1].
+  // Caution: implementation moves all elements with indices [start+num .. ].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  void DeleteSubrange(int start, int num);
+
+  void Clear();
+  void MergeFrom(const RepeatedPtrField& other);
+  void CopyFrom(const RepeatedPtrField& other);
+
+  // Reserve space to expand the field to at least the given size.  This only
+  // resizes the pointer array; it doesn't allocate any objects.  If the
+  // array is grown, it will always be at least doubled in size.
+  void Reserve(int new_size);
+
+  int Capacity() const;
+
+  // Gets the underlying array.  This pointer is possibly invalidated by
+  // any add or remove operation.
+  Element** mutable_data();
+  const Element* const* data() const;
+
+  // Swap entire contents with "other". If they are on separate arenas, then
+  // copies data.
+  void Swap(RepeatedPtrField* other);
+
+  // Swap entire contents with "other". Caller should guarantee that either both
+  // fields are on the same arena or both are on the heap. Swapping between
+  // different arenas with this function is disallowed and is caught via
+  // GOOGLE_DCHECK.
+  void UnsafeArenaSwap(RepeatedPtrField* other);
+
+  // Swap two elements.
+  void SwapElements(int index1, int index2);
+
+  // STL-like iterator support
+  typedef internal::RepeatedPtrIterator<Element> iterator;
+  typedef internal::RepeatedPtrIterator<const Element> const_iterator;
+  typedef Element value_type;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef int size_type;
+  typedef ptrdiff_t difference_type;
+
+  iterator begin();
+  const_iterator begin() const;
+  const_iterator cbegin() const;
+  iterator end();
+  const_iterator end() const;
+  const_iterator cend() const;
+
+  // Reverse iterator support
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  reverse_iterator rbegin() {
+    return reverse_iterator(end());
+  }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  reverse_iterator rend() {
+    return reverse_iterator(begin());
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+
+  // Custom STL-like iterator that iterates over and returns the underlying
+  // pointers to Element rather than Element itself.
+  typedef internal::RepeatedPtrOverPtrsIterator<Element, void*>
+  pointer_iterator;
+  typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
+  const_pointer_iterator;
+  pointer_iterator pointer_begin();
+  const_pointer_iterator pointer_begin() const;
+  pointer_iterator pointer_end();
+  const_pointer_iterator pointer_end() const;
+
+  // Returns (an estimate of) the number of bytes used by the repeated field,
+  // excluding sizeof(*this).
+  int SpaceUsedExcludingSelf() const;
+
+  // Advanced memory management --------------------------------------
+  // When hardcore memory management becomes necessary -- as it sometimes
+  // does here at Google -- the following methods may be useful.
+
+  // Add an already-allocated object, passing ownership to the
+  // RepeatedPtrField.
+  //
+  // Note that some special behavior occurs with respect to arenas:
+  //
+  //   (i) if this field holds submessages, the new submessage will be copied if
+  //   the original is in an arena and this RepeatedPtrField is either in a
+  //   different arena, or on the heap.
+  //   (ii) if this field holds strings, the passed-in string *must* be
+  //   heap-allocated, not arena-allocated. There is no way to dynamically check
+  //   this at runtime, so User Beware.
+  void AddAllocated(Element* value);
+
+  // Remove the last element and return it, passing ownership to the caller.
+  // Requires:  size() > 0
+  //
+  // If this RepeatedPtrField is on an arena, an object copy is required to pass
+  // ownership back to the user (for compatible semantics). Use
+  // UnsafeArenaReleaseLast() if this behavior is undesired.
+  Element* ReleaseLast();
+
+  // Add an already-allocated object, skipping arena-ownership checks. The user
+  // must guarantee that the given object is in the same arena as this
+  // RepeatedPtrField.
+  // It is also useful in legacy code that uses temporary ownership to avoid
+  // copies. Example:
+  // RepeatedPtrField<T> temp_field;
+  // temp_field.AddAllocated(new T);
+  // ... // Do something with temp_field
+  // temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+  // If you put temp_field on the arena this fails, because the ownership
+  // transfers to the arena at the "AddAllocated" call and is not released
+  // anymore causing a double delete. UnsafeArenaAddAllocated prevents this.
+  void UnsafeArenaAddAllocated(Element* value);
+
+  // Remove the last element and return it.  Works only when operating on an
+  // arena. The returned pointer is to the original object in the arena, hence
+  // has the arena's lifetime.
+  // Requires:  current_size_ > 0
+  Element* UnsafeArenaReleaseLast();
+
+  // Extract elements with indices in the range "[start .. start+num-1]".
+  // The caller assumes ownership of the extracted elements and is responsible
+  // for deleting them when they are no longer needed.
+  // If "elements" is non-NULL, then pointers to the extracted elements
+  // are stored in "elements[0 .. num-1]" for the convenience of the caller.
+  // If "elements" is NULL, then the caller must use some other mechanism
+  // to perform any further operations (like deletion) on these elements.
+  // Caution: implementation also moves elements with indices [start+num ..].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  //
+  // Memory copying behavior is identical to ReleaseLast(), described above: if
+  // this RepeatedPtrField is on an arena, an object copy is performed for each
+  // returned element, so that all returned element pointers are to
+  // heap-allocated copies. If this copy is not desired, the user should call
+  // UnsafeArenaExtractSubrange().
+  void ExtractSubrange(int start, int num, Element** elements);
+
+  // Identical to ExtractSubrange() described above, except that when this
+  // repeated field is on an arena, no object copies are performed. Instead, the
+  // raw object pointers are returned. Thus, if on an arena, the returned
+  // objects must not be freed, because they will not be heap-allocated objects.
+  void UnsafeArenaExtractSubrange(int start, int num, Element** elements);
+
+  // When elements are removed by calls to RemoveLast() or Clear(), they
+  // are not actually freed.  Instead, they are cleared and kept so that
+  // they can be reused later.  This can save lots of CPU time when
+  // repeatedly reusing a protocol message for similar purposes.
+  //
+  // Hardcore programs may choose to manipulate these cleared objects
+  // to better optimize memory management using the following routines.
+
+  // Get the number of cleared objects that are currently being kept
+  // around for reuse.
+  int ClearedCount() const;
+  // Add an element to the pool of cleared objects, passing ownership to
+  // the RepeatedPtrField.  The element must be cleared prior to calling
+  // this method.
+  //
+  // This method cannot be called when the repeated field is on an arena or when
+  // |value| is; both cases will trigger a GOOGLE_DCHECK-failure.
+  void AddCleared(Element* value);
+  // Remove a single element from the cleared pool and return it, passing
+  // ownership to the caller.  The element is guaranteed to be cleared.
+  // Requires:  ClearedCount() > 0
+  //
+  //
+  // This method cannot be called when the repeated field is on an arena; doing
+  // so will trigger a GOOGLE_DCHECK-failure.
+  Element* ReleaseCleared();
+
+  // Removes the element referenced by position.
+  //
+  // Returns an iterator to the element immediately following the removed
+  // element.
+  //
+  // Invalidates all iterators at or after the removed element, including end().
+  iterator erase(const_iterator position);
+
+  // Removes the elements in the range [first, last).
+  //
+  // Returns an iterator to the element immediately following the removed range.
+  //
+  // Invalidates all iterators at or after the removed range, including end().
+  iterator erase(const_iterator first, const_iterator last);
+
+  // Gets the arena on which this RepeatedPtrField stores its elements.
+  ::google::protobuf::Arena* GetArena() const {
+    return GetArenaNoVirtual();
+  }
+
+ protected:
+  // Note:  RepeatedPtrField SHOULD NOT be subclassed by users.  We only
+  //   subclass it in one place as a hack for compatibility with proto1.  The
+  //   subclass needs to know about TypeHandler in order to call protected
+  //   methods on RepeatedPtrFieldBase.
+  class TypeHandler;
+
+  // Internal arena accessor expected by helpers in Arena.
+  inline Arena* GetArenaNoVirtual() const;
+
+ private:
+  // Implementations for ExtractSubrange(). The copying behavior must be
+  // included only if the type supports the necessary operations (e.g.,
+  // MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
+  // uses SFINAE to choose one of the below implementations.
+  void ExtractSubrangeInternal(int start, int num, Element** elements,
+                               google::protobuf::internal::true_type);
+  void ExtractSubrangeInternal(int start, int num, Element** elements,
+                               google::protobuf::internal::false_type);
+
+  friend class Arena;
+  typedef void InternalArenaConstructable_;
+
+};
+
+// implementation ====================================================
+
+template <typename Element>
+inline RepeatedField<Element>::RepeatedField()
+  : current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+}
+
+template <typename Element>
+inline RepeatedField<Element>::RepeatedField(Arena* arena)
+  : current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+ // In case arena is NULL, then we do not create rep_, as code has an invariant
+ // `rep_ == NULL then arena == NULL`.
+ if (arena != NULL) {
+  rep_ = reinterpret_cast<Rep*>(
+      ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize));
+  rep_->arena = arena;
+ }
+}
+
+template <typename Element>
+inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
+  : current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+  CopyFrom(other);
+}
+
+template <typename Element>
+template <typename Iter>
+RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+  : current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+  int reserve = internal::CalculateReserve(begin, end);
+  if (reserve != -1) {
+    Reserve(reserve);
+    for (; begin != end; ++begin) {
+      AddAlreadyReserved(*begin);
+    }
+  } else {
+    for (; begin != end; ++begin) {
+      Add(*begin);
+    }
+  }
+}
+
+template <typename Element>
+RepeatedField<Element>::~RepeatedField() {
+  // See explanation in Reserve(): we need to invoke destructors here for the
+  // case that Element has a non-trivial destructor.
+  InternalDeallocate(rep_, total_size_);
+}
+
+template <typename Element>
+inline RepeatedField<Element>&
+RepeatedField<Element>::operator=(const RepeatedField& other) {
+  if (this != &other)
+    CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
+inline bool RepeatedField<Element>::empty() const {
+  return current_size_ == 0;
+}
+
+template <typename Element>
+inline int RepeatedField<Element>::size() const {
+  return current_size_;
+}
+
+template <typename Element>
+inline int RepeatedField<Element>::Capacity() const {
+  return total_size_;
+}
+
+template<typename Element>
+inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
+  GOOGLE_DCHECK_LT(current_size_, total_size_);
+  rep_->elements[current_size_++] = value;
+}
+
+template<typename Element>
+inline Element* RepeatedField<Element>::AddAlreadyReserved() {
+  GOOGLE_DCHECK_LT(current_size_, total_size_);
+  return &rep_->elements[current_size_++];
+}
+
+template<typename Element>
+inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
+  GOOGLE_DCHECK_GE(new_size, 0);
+  if (new_size > current_size_) {
+    Reserve(new_size);
+    std::fill(&rep_->elements[current_size_],
+              &rep_->elements[new_size], value);
+  }
+  current_size_ = new_size;
+}
+
+template <typename Element>
+inline const Element& RepeatedField<Element>::Get(int index) const {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  return rep_->elements[index];
+}
+
+template <typename Element>
+inline Element* RepeatedField<Element>::Mutable(int index) {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  return &rep_->elements[index];
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::Set(int index, const Element& value) {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  rep_->elements[index] = value;
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::Add(const Element& value) {
+  if (current_size_ == total_size_) Reserve(total_size_ + 1);
+  rep_->elements[current_size_++] = value;
+}
+
+template <typename Element>
+inline Element* RepeatedField<Element>::Add() {
+  if (current_size_ == total_size_) Reserve(total_size_ + 1);
+  return &rep_->elements[current_size_++];
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::RemoveLast() {
+  GOOGLE_DCHECK_GT(current_size_, 0);
+  current_size_--;
+}
+
+template <typename Element>
+void RepeatedField<Element>::ExtractSubrange(
+    int start, int num, Element* elements) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, this->current_size_);
+
+  // Save the values of the removed elements if requested.
+  if (elements != NULL) {
+    for (int i = 0; i < num; ++i)
+      elements[i] = this->Get(i + start);
+  }
+
+  // Slide remaining elements down to fill the gap.
+  if (num > 0) {
+    for (int i = start + num; i < this->current_size_; ++i)
+      this->Set(i - num, this->Get(i));
+    this->Truncate(this->current_size_ - num);
+  }
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::Clear() {
+  current_size_ = 0;
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
+  GOOGLE_CHECK_NE(&other, this);
+  if (other.current_size_ != 0) {
+    Reserve(current_size_ + other.current_size_);
+    CopyArray(rep_->elements + current_size_,
+              other.rep_->elements, other.current_size_);
+    current_size_ += other.current_size_;
+  }
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
+  if (&other == this) return;
+  Clear();
+  MergeFrom(other);
+}
+
+template <typename Element>
+inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
+    const_iterator position) {
+  return erase(position, position + 1);
+}
+
+template <typename Element>
+inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
+    const_iterator first, const_iterator last) {
+  size_type first_offset = first - cbegin();
+  if (first != last) {
+    Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
+  }
+  return begin() + first_offset;
+}
+
+template <typename Element>
+inline Element* RepeatedField<Element>::mutable_data() {
+  return rep_ ? rep_->elements : NULL;
+}
+
+template <typename Element>
+inline const Element* RepeatedField<Element>::data() const {
+  return rep_ ? rep_->elements : NULL;
+}
+
+
+template <typename Element>
+inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
+  std::swap(rep_, other->rep_);
+  std::swap(current_size_, other->current_size_);
+  std::swap(total_size_, other->total_size_);
+}
+
+template <typename Element>
+void RepeatedField<Element>::Swap(RepeatedField* other) {
+  if (this == other) return;
+  if (GetArenaNoVirtual() ==  other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    RepeatedField<Element> temp(other->GetArenaNoVirtual());
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->UnsafeArenaSwap(&temp);
+  }
+}
+
+template <typename Element>
+void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
+  if (this == other) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+
+template <typename Element>
+void RepeatedField<Element>::SwapElements(int index1, int index2) {
+  using std::swap;  // enable ADL with fallback
+  swap(rep_->elements[index1], rep_->elements[index2]);
+}
+
+template <typename Element>
+inline typename RepeatedField<Element>::iterator
+RepeatedField<Element>::begin() {
+  return rep_ ? rep_->elements : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::begin() const {
+  return rep_ ? rep_->elements : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::cbegin() const {
+  return rep_ ? rep_->elements : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::iterator
+RepeatedField<Element>::end() {
+  return rep_ ? rep_->elements + current_size_ : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::end() const {
+  return rep_ ? rep_->elements + current_size_ : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::cend() const {
+  return rep_ ? rep_->elements + current_size_ : NULL;
+}
+
+template <typename Element>
+inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
+  return rep_ ?
+      (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
+}
+
+// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
+// amount of code bloat.
+template <typename Element>
+void RepeatedField<Element>::Reserve(int new_size) {
+  if (total_size_ >= new_size) return;
+  Rep* old_rep = rep_;
+  Arena* arena = GetArenaNoVirtual();
+  new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+                      std::max(total_size_ * 2, new_size));
+  GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
+           (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+           sizeof(Element))
+      << "Requested size is too large to fit into size_t.";
+  if (arena == NULL) {
+    rep_ = reinterpret_cast<Rep*>(
+        new char[kRepHeaderSize + sizeof(Element) * new_size]);
+  } else {
+    rep_ = reinterpret_cast<Rep*>(
+            ::google::protobuf::Arena::CreateArray<char>(arena,
+                kRepHeaderSize + sizeof(Element) * new_size));
+  }
+  rep_->arena = arena;
+  int old_total_size = total_size_;
+  total_size_ = new_size;
+  // Invoke placement-new on newly allocated elements. We shouldn't have to do
+  // this, since Element is supposed to be POD, but a previous version of this
+  // code allocated storage with "new Element[size]" and some code uses
+  // RepeatedField with non-POD types, relying on constructor invocation. If
+  // Element has a trivial constructor (e.g., int32), gcc (tested with -O2)
+  // completely removes this loop because the loop body is empty, so this has no
+  // effect unless its side-effects are required for correctness.
+  // Note that we do this before MoveArray() below because Element's copy
+  // assignment implementation will want an initialized instance first.
+  Element* e = &rep_->elements[0];
+  Element* limit = &rep_->elements[total_size_];
+  for (; e < limit; e++) {
+    new (e) Element();
+  }
+  if (current_size_ > 0) {
+    MoveArray(rep_->elements, old_rep->elements, current_size_);
+  }
+
+  // Likewise, we need to invoke destructors on the old array.
+  InternalDeallocate(old_rep, old_total_size);
+
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::Truncate(int new_size) {
+  GOOGLE_DCHECK_LE(new_size, current_size_);
+  if (current_size_ > 0) {
+    current_size_ = new_size;
+  }
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::MoveArray(
+  Element* to, Element* from, int array_size) {
+  CopyArray(to, from, array_size);
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::CopyArray(
+  Element* to, const Element* from, int array_size) {
+  internal::ElementCopier<Element>()(to, from, array_size);
+}
+
+namespace internal {
+
+template <typename Element, bool HasTrivialCopy>
+void ElementCopier<Element, HasTrivialCopy>::operator()(
+  Element* to, const Element* from, int array_size) {
+  std::copy(from, from + array_size, to);
+}
+
+template <typename Element>
+struct ElementCopier<Element, true> {
+  void operator()(Element* to, const Element* from, int array_size) {
+    memcpy(to, from, array_size * sizeof(Element));
+  }
+};
+
+}  // namespace internal
+
+
+// -------------------------------------------------------------------
+
+namespace internal {
+
+inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
+  : arena_(NULL),
+    current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+}
+
+inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* arena)
+  : arena_(arena),
+    current_size_(0),
+    total_size_(0),
+    rep_(NULL) {
+}
+
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::Destroy() {
+  if (rep_ != NULL) {
+    for (int i = 0; i < rep_->allocated_size; i++) {
+      TypeHandler::Delete(cast<TypeHandler>(rep_->elements[i]), arena_);
+    }
+    if (arena_ == NULL) {
+      delete [] reinterpret_cast<char*>(rep_);
+    }
+  }
+  rep_ = NULL;
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
+  if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    SwapFallback<TypeHandler>(other);
+  }
+}
+
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
+  GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual());
+
+  // Copy semantics in this case. We try to improve efficiency by placing the
+  // temporary on |other|'s arena so that messages are copied cross-arena only
+  // once, not twice.
+  RepeatedPtrFieldBase temp(other->GetArenaNoVirtual());
+  temp.MergeFrom<TypeHandler>(*this);
+  this->Clear<TypeHandler>();
+  this->MergeFrom<TypeHandler>(*other);
+  other->Clear<TypeHandler>();
+  other->InternalSwap(&temp);
+  temp.Destroy<TypeHandler>();  // Frees rep_ if `other` had no arena.
+}
+
+inline bool RepeatedPtrFieldBase::empty() const {
+  return current_size_ == 0;
+}
+
+inline int RepeatedPtrFieldBase::size() const {
+  return current_size_;
+}
+
+template <typename TypeHandler>
+inline const typename TypeHandler::Type&
+RepeatedPtrFieldBase::Get(int index) const {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  return *cast<TypeHandler>(rep_->elements[index]);
+}
+
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::Mutable(int index) {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  return cast<TypeHandler>(rep_->elements[index]);
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::Delete(int index) {
+  GOOGLE_DCHECK_GE(index, 0);
+  GOOGLE_DCHECK_LT(index, current_size_);
+  TypeHandler::Delete(cast<TypeHandler>(rep_->elements[index]), arena_);
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add(
+    typename TypeHandler::Type* prototype) {
+  if (rep_ != NULL && current_size_ < rep_->allocated_size) {
+    return cast<TypeHandler>(rep_->elements[current_size_++]);
+  }
+  if (!rep_ || rep_->allocated_size == total_size_) {
+    Reserve(total_size_ + 1);
+  }
+  ++rep_->allocated_size;
+  typename TypeHandler::Type* result =
+      TypeHandler::NewFromPrototype(prototype, arena_);
+  rep_->elements[current_size_++] = result;
+  return result;
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::RemoveLast() {
+  GOOGLE_DCHECK_GT(current_size_, 0);
+  TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_]));
+}
+
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::Clear() {
+  const int n = current_size_;
+  GOOGLE_DCHECK_GE(n, 0);
+  if (n > 0) {
+    void* const* elements = rep_->elements;
+    int i = 0;
+    do {
+      TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
+    } while (i < n);
+    current_size_ = 0;
+  }
+}
+
+// To avoid unnecessary code duplication and reduce binary size, we use a
+// layered approach to implementing MergeFrom(). The toplevel method is
+// templated, so we get a small thunk per concrete message type in the binary.
+// This calls a shared implementation with most of the logic, passing a function
+// pointer to another type-specific piece of code that calls the object-allocate
+// and merge handlers.
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
+  GOOGLE_DCHECK_NE(&other, this);
+  if (other.current_size_ == 0) return;
+  MergeFromInternal(
+      other, &RepeatedPtrFieldBase::MergeFromInnerLoop<TypeHandler>);
+}
+
+inline void RepeatedPtrFieldBase::MergeFromInternal(
+    const RepeatedPtrFieldBase& other,
+    void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)) {
+  // Note: wrapper has already guaranteed that other.rep_ != NULL here.
+  int other_size = other.current_size_;
+  void** other_elements = other.rep_->elements;
+  void** new_elements = InternalExtend(other_size);
+  int allocated_elems = rep_->allocated_size - current_size_;
+  (this->*inner_loop)(new_elements, other_elements,
+                      other_size, allocated_elems);
+  current_size_ += other_size;
+  if (rep_->allocated_size < current_size_) {
+    rep_->allocated_size = current_size_;
+  }
+}
+
+// Merges other_elems to our_elems.
+template<typename TypeHandler>
+void RepeatedPtrFieldBase::MergeFromInnerLoop(
+    void** our_elems, void** other_elems, int length, int already_allocated) {
+  // Split into two loops, over ranges [0, allocated) and [allocated, length),
+  // to avoid a branch within the loop.
+  for (int i = 0; i < already_allocated && i < length; i++) {
+    // Already allocated: use existing element.
+    typename TypeHandler::Type* other_elem =
+        reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
+    typename TypeHandler::Type* new_elem =
+        reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
+    TypeHandler::Merge(*other_elem, new_elem);
+  }
+  Arena* arena = GetArenaNoVirtual();
+  for (int i = already_allocated; i < length; i++) {
+    // Not allocated: alloc a new element first, then merge it.
+    typename TypeHandler::Type* other_elem =
+        reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
+    typename TypeHandler::Type* new_elem =
+        TypeHandler::NewFromPrototype(other_elem, arena);
+    TypeHandler::Merge(*other_elem, new_elem);
+    our_elems[i] = new_elem;
+  }
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) {
+  if (&other == this) return;
+  RepeatedPtrFieldBase::Clear<TypeHandler>();
+  RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
+}
+
+inline int RepeatedPtrFieldBase::Capacity() const {
+  return total_size_;
+}
+
+inline void* const* RepeatedPtrFieldBase::raw_data() const {
+  return rep_ ? rep_->elements : NULL;
+}
+
+inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
+  return rep_ ? const_cast<void**>(rep_->elements) : NULL;
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
+  // TODO(kenton):  Breaks C++ aliasing rules.  We should probably remove this
+  //   method entirely.
+  return reinterpret_cast<typename TypeHandler::Type**>(raw_mutable_data());
+}
+
+template <typename TypeHandler>
+inline const typename TypeHandler::Type* const*
+RepeatedPtrFieldBase::data() const {
+  // TODO(kenton):  Breaks C++ aliasing rules.  We should probably remove this
+  //   method entirely.
+  return reinterpret_cast<const typename TypeHandler::Type* const*>(raw_data());
+}
+
+inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
+  using std::swap;  // enable ADL with fallback
+  swap(rep_->elements[index1], rep_->elements[index2]);
+}
+
+template <typename TypeHandler>
+inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
+  int allocated_bytes = total_size_ * sizeof(void*);
+  if (rep_ != NULL) {
+    for (int i = 0; i < rep_->allocated_size; ++i) {
+      allocated_bytes += TypeHandler::SpaceUsed(
+          *cast<TypeHandler>(rep_->elements[i]));
+    }
+    allocated_bytes += kRepHeaderSize;
+  }
+  return allocated_bytes;
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
+  if (rep_ != NULL && current_size_ < rep_->allocated_size) {
+    return cast<TypeHandler>(rep_->elements[current_size_++]);
+  } else {
+    return NULL;
+  }
+}
+
+// AddAllocated version that implements arena-safe copying behavior.
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::AddAllocatedInternal(
+    typename TypeHandler::Type* value,
+    google::protobuf::internal::true_type) {
+  Arena* element_arena = reinterpret_cast<Arena*>(
+      TypeHandler::GetMaybeArenaPointer(value));
+  Arena* arena = GetArenaNoVirtual();
+  if (arena == element_arena && rep_ &&
+      rep_->allocated_size < total_size_) {
+    // Fast path: underlying arena representation (tagged pointer) is equal to
+    // our arena pointer, and we can add to array without resizing it (at least
+    // one slot that is not allocated).
+    void** elems = rep_->elements;
+    if (current_size_ < rep_->allocated_size) {
+      // Make space at [current] by moving first allocated element to end of
+      // allocated list.
+      elems[rep_->allocated_size] = elems[current_size_];
+    }
+    elems[current_size_] = value;
+    current_size_ = current_size_ + 1;
+    rep_->allocated_size = rep_->allocated_size + 1;
+    return;
+  } else {
+    AddAllocatedSlowWithCopy<TypeHandler>(
+        value, TypeHandler::GetArena(value), arena);
+  }
+}
+
+// Slowpath handles all cases, copying if necessary.
+template<typename TypeHandler>
+void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy(
+    // Pass value_arena and my_arena to avoid duplicate virtual call (value) or
+    // load (mine).
+    typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) {
+  // Ensure that either the value is in the same arena, or if not, we do the
+  // appropriate thing: Own() it (if it's on heap and we're in an arena) or copy
+  // it to our arena/heap (otherwise).
+  if (my_arena != NULL && value_arena == NULL) {
+    my_arena->Own(value);
+  } else if (my_arena != value_arena) {
+    typename TypeHandler::Type* new_value =
+        TypeHandler::NewFromPrototype(value, my_arena);
+    TypeHandler::Merge(*value, new_value);
+    TypeHandler::Delete(value, value_arena);
+    value = new_value;
+  }
+
+  UnsafeArenaAddAllocated<TypeHandler>(value);
+}
+
+// AddAllocated version that does not implement arena-safe copying behavior.
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::AddAllocatedInternal(
+    typename TypeHandler::Type* value,
+    google::protobuf::internal::false_type) {
+  if (rep_ &&  rep_->allocated_size < total_size_) {
+    // Fast path: underlying arena representation (tagged pointer) is equal to
+    // our arena pointer, and we can add to array without resizing it (at least
+    // one slot that is not allocated).
+    void** elems = rep_->elements;
+    if (current_size_ < rep_->allocated_size) {
+      // Make space at [current] by moving first allocated element to end of
+      // allocated list.
+      elems[rep_->allocated_size] = elems[current_size_];
+    }
+    elems[current_size_] = value;
+    current_size_ = current_size_ + 1;
+    ++rep_->allocated_size;
+    return;
+  } else {
+    UnsafeArenaAddAllocated<TypeHandler>(value);
+  }
+}
+
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::UnsafeArenaAddAllocated(
+    typename TypeHandler::Type* value) {
+  // Make room for the new pointer.
+  if (!rep_ || current_size_ == total_size_) {
+    // The array is completely full with no cleared objects, so grow it.
+    Reserve(total_size_ + 1);
+    ++rep_->allocated_size;
+  } else if (rep_->allocated_size == total_size_) {
+    // There is no more space in the pointer array because it contains some
+    // cleared objects awaiting reuse.  We don't want to grow the array in this
+    // case because otherwise a loop calling AddAllocated() followed by Clear()
+    // would leak memory.
+    TypeHandler::Delete(
+        cast<TypeHandler>(rep_->elements[current_size_]), arena_);
+  } else if (current_size_ < rep_->allocated_size) {
+    // We have some cleared objects.  We don't care about their order, so we
+    // can just move the first one to the end to make space.
+    rep_->elements[rep_->allocated_size] = rep_->elements[current_size_];
+    ++rep_->allocated_size;
+  } else {
+    // There are no cleared objects.
+    ++rep_->allocated_size;
+  }
+
+  rep_->elements[current_size_++] = value;
+}
+
+// ReleaseLast() for types that implement merge/copy behavior.
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) {
+  // First, release an element.
+  typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>();
+  // Now perform a copy if we're on an arena.
+  Arena* arena = GetArenaNoVirtual();
+  if (arena == NULL) {
+    return result;
+  } else {
+    typename TypeHandler::Type* new_result =
+        TypeHandler::NewFromPrototype(result, NULL);
+    TypeHandler::Merge(*result, new_result);
+    return new_result;
+  }
+}
+
+// ReleaseLast() for types that *do not* implement merge/copy behavior -- this
+// is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if we're on
+// an arena, since the user really should implement the copy operation in this
+// case.
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+      << "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
+      << "with a type that does not implement MergeFrom. This is unsafe; "
+      << "please implement MergeFrom for your type.";
+  return UnsafeArenaReleaseLast<TypeHandler>();
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+  RepeatedPtrFieldBase::UnsafeArenaReleaseLast() {
+  GOOGLE_DCHECK_GT(current_size_, 0);
+  typename TypeHandler::Type* result =
+      cast<TypeHandler>(rep_->elements[--current_size_]);
+  --rep_->allocated_size;
+  if (current_size_ < rep_->allocated_size) {
+    // There are cleared elements on the end; replace the removed element
+    // with the last allocated element.
+    rep_->elements[current_size_] = rep_->elements[rep_->allocated_size];
+  }
+  return result;
+}
+
+inline int RepeatedPtrFieldBase::ClearedCount() const {
+  return rep_ ? (rep_->allocated_size - current_size_) : 0;
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::AddCleared(
+    typename TypeHandler::Type* value) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+      << "AddCleared() can only be used on a RepeatedPtrField not on an arena.";
+  GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL)
+      << "AddCleared() can only accept values not on an arena.";
+  if (!rep_ || rep_->allocated_size == total_size_) {
+    Reserve(total_size_ + 1);
+  }
+  rep_->elements[rep_->allocated_size++] = value;
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
+  GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+      << "ReleaseCleared() can only be used on a RepeatedPtrField not on "
+      << "an arena.";
+  GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);
+  GOOGLE_DCHECK(rep_ != NULL);
+  GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_);
+  return cast<TypeHandler>(rep_->elements[--rep_->allocated_size]);
+}
+
+}  // namespace internal
+
+// -------------------------------------------------------------------
+
+template <typename Element>
+class RepeatedPtrField<Element>::TypeHandler
+    : public internal::GenericTypeHandler<Element> {
+};
+
+template <>
+class RepeatedPtrField<string>::TypeHandler
+    : public internal::StringTypeHandler {
+};
+
+
+template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField()
+  : RepeatedPtrFieldBase() {}
+
+template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(::google::protobuf::Arena* arena) :
+  RepeatedPtrFieldBase(arena) {}
+
+template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+    const RepeatedPtrField& other)
+  : RepeatedPtrFieldBase() {
+  CopyFrom(other);
+}
+
+template <typename Element>
+template <typename Iter>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+    Iter begin, const Iter& end) {
+  int reserve = internal::CalculateReserve(begin, end);
+  if (reserve != -1) {
+    Reserve(reserve);
+  }
+  for (; begin != end; ++begin) {
+    *Add() = *begin;
+  }
+}
+
+template <typename Element>
+RepeatedPtrField<Element>::~RepeatedPtrField() {
+  Destroy<TypeHandler>();
+}
+
+template <typename Element>
+inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
+    const RepeatedPtrField& other) {
+  if (this != &other)
+    CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
+inline bool RepeatedPtrField<Element>::empty() const {
+  return RepeatedPtrFieldBase::empty();
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::size() const {
+  return RepeatedPtrFieldBase::size();
+}
+
+template <typename Element>
+inline const Element& RepeatedPtrField<Element>::Get(int index) const {
+  return RepeatedPtrFieldBase::Get<TypeHandler>(index);
+}
+
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::Mutable(int index) {
+  return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::Add() {
+  return RepeatedPtrFieldBase::Add<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::RemoveLast() {
+  RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, size());
+  for (int i = 0; i < num; ++i) {
+    RepeatedPtrFieldBase::Delete<TypeHandler>(start + i);
+  }
+  ExtractSubrange(start, num, NULL);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrange(
+    int start, int num, Element** elements) {
+  typename internal::TypeImplementsMergeBehavior<
+      typename TypeHandler::Type>::type t;
+  ExtractSubrangeInternal(start, num, elements, t);
+}
+
+// ExtractSubrange() implementation for types that implement merge/copy
+// behavior.
+template <typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
+    int start, int num, Element** elements, google::protobuf::internal::true_type) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, size());
+
+  if (num > 0) {
+    // Save the values of the removed elements if requested.
+    if (elements != NULL) {
+      if (GetArenaNoVirtual() != NULL) {
+        // If we're on an arena, we perform a copy for each element so that the
+        // returned elements are heap-allocated.
+        for (int i = 0; i < num; ++i) {
+          Element* element = RepeatedPtrFieldBase::
+              Mutable<TypeHandler>(i + start);
+          typename TypeHandler::Type* new_value =
+              TypeHandler::NewFromPrototype(element, NULL);
+          TypeHandler::Merge(*element, new_value);
+          elements[i] = new_value;
+        }
+      } else {
+        for (int i = 0; i < num; ++i) {
+          elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+        }
+      }
+    }
+    CloseGap(start, num);
+  }
+}
+
+// ExtractSubrange() implementation for types that do not implement merge/copy
+// behavior.
+template<typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
+    int start, int num, Element** elements, google::protobuf::internal::false_type) {
+  // This case is identical to UnsafeArenaExtractSubrange(). However, since
+  // ExtractSubrange() must return heap-allocated objects by contract, and we
+  // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that
+  // we are not on an arena.
+  GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+      << "ExtractSubrange() when arena is non-NULL is only supported when "
+      << "the Element type supplies a MergeFrom() operation to make copies.";
+  UnsafeArenaExtractSubrange(start, num, elements);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::UnsafeArenaExtractSubrange(
+    int start, int num, Element** elements) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, size());
+
+  if (num > 0) {
+    // Save the values of the removed elements if requested.
+    if (elements != NULL) {
+      for (int i = 0; i < num; ++i) {
+        elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+      }
+    }
+    CloseGap(start, num);
+  }
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::Clear() {
+  RepeatedPtrFieldBase::Clear<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::MergeFrom(
+    const RepeatedPtrField& other) {
+  RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::CopyFrom(
+    const RepeatedPtrField& other) {
+  RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other);
+}
+
+template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::erase(const_iterator position) {
+  return erase(position, position + 1);
+}
+
+template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
+  size_type pos_offset = std::distance(cbegin(), first);
+  size_type last_offset = std::distance(cbegin(), last);
+  DeleteSubrange(pos_offset, last_offset - pos_offset);
+  return begin() + pos_offset;
+}
+
+template <typename Element>
+inline Element** RepeatedPtrField<Element>::mutable_data() {
+  return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
+}
+
+template <typename Element>
+inline const Element* const* RepeatedPtrField<Element>::data() const {
+  return RepeatedPtrFieldBase::data<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
+  if (this == other)
+    return;
+  RepeatedPtrFieldBase::Swap<TypeHandler>(other);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
+    RepeatedPtrField* other) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  if (this == other)
+      return;
+  RepeatedPtrFieldBase::InternalSwap(other);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
+  RepeatedPtrFieldBase::SwapElements(index1, index2);
+}
+
+template <typename Element>
+inline Arena* RepeatedPtrField<Element>::GetArenaNoVirtual() const {
+  return RepeatedPtrFieldBase::GetArenaNoVirtual();
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
+  return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
+  RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::UnsafeArenaAddAllocated(Element* value) {
+  RepeatedPtrFieldBase::UnsafeArenaAddAllocated<TypeHandler>(value);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::ReleaseLast() {
+  return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::UnsafeArenaReleaseLast() {
+  return RepeatedPtrFieldBase::UnsafeArenaReleaseLast<TypeHandler>();
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::ClearedCount() const {
+  return RepeatedPtrFieldBase::ClearedCount();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
+  return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
+}
+
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
+  return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::Reserve(int new_size) {
+  return RepeatedPtrFieldBase::Reserve(new_size);
+}
+
+template <typename Element>
+inline int RepeatedPtrField<Element>::Capacity() const {
+  return RepeatedPtrFieldBase::Capacity();
+}
+
+// -------------------------------------------------------------------
+
+namespace internal {
+
+// STL-like iterator implementation for RepeatedPtrField.  You should not
+// refer to this class directly; use RepeatedPtrField<T>::iterator instead.
+//
+// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
+// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
+// but adds random-access operators and is modified to wrap a void** base
+// iterator (since RepeatedPtrField stores its array as a void* array and
+// casting void** to T** would violate C++ aliasing rules).
+//
+// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin
+// (jyasskin@google.com).
+template<typename Element>
+class RepeatedPtrIterator
+    : public std::iterator<
+          std::random_access_iterator_tag, Element> {
+ public:
+  typedef RepeatedPtrIterator<Element> iterator;
+  typedef std::iterator<
+          std::random_access_iterator_tag, Element> superclass;
+
+  // Shadow the value_type in std::iterator<> because const_iterator::value_type
+  // needs to be T, not const T.
+  typedef typename remove_const<Element>::type value_type;
+
+  // Let the compiler know that these are type names, so we don't have to
+  // write "typename" in front of them everywhere.
+  typedef typename superclass::reference reference;
+  typedef typename superclass::pointer pointer;
+  typedef typename superclass::difference_type difference_type;
+
+  RepeatedPtrIterator() : it_(NULL) {}
+  explicit RepeatedPtrIterator(void* const* it) : it_(it) {}
+
+  // Allow "upcasting" from RepeatedPtrIterator<T**> to
+  // RepeatedPtrIterator<const T*const*>.
+  template<typename OtherElement>
+  RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
+      : it_(other.it_) {
+    // Force a compiler error if the other type is not convertible to ours.
+    if (false) {
+      implicit_cast<Element*, OtherElement*>(0);
+    }
+  }
+
+  // dereferenceable
+  reference operator*() const { return *reinterpret_cast<Element*>(*it_); }
+  pointer   operator->() const { return &(operator*()); }
+
+  // {inc,dec}rementable
+  iterator& operator++() { ++it_; return *this; }
+  iterator  operator++(int) { return iterator(it_++); }
+  iterator& operator--() { --it_; return *this; }
+  iterator  operator--(int) { return iterator(it_--); }
+
+  // equality_comparable
+  bool operator==(const iterator& x) const { return it_ == x.it_; }
+  bool operator!=(const iterator& x) const { return it_ != x.it_; }
+
+  // less_than_comparable
+  bool operator<(const iterator& x) const { return it_ < x.it_; }
+  bool operator<=(const iterator& x) const { return it_ <= x.it_; }
+  bool operator>(const iterator& x) const { return it_ > x.it_; }
+  bool operator>=(const iterator& x) const { return it_ >= x.it_; }
+
+  // addable, subtractable
+  iterator& operator+=(difference_type d) {
+    it_ += d;
+    return *this;
+  }
+  friend iterator operator+(iterator it, const difference_type d) {
+    it += d;
+    return it;
+  }
+  friend iterator operator+(const difference_type d, iterator it) {
+    it += d;
+    return it;
+  }
+  iterator& operator-=(difference_type d) {
+    it_ -= d;
+    return *this;
+  }
+  friend iterator operator-(iterator it, difference_type d) {
+    it -= d;
+    return it;
+  }
+
+  // indexable
+  reference operator[](difference_type d) const { return *(*this + d); }
+
+  // random access iterator
+  difference_type operator-(const iterator& x) const { return it_ - x.it_; }
+
+ private:
+  template<typename OtherElement>
+  friend class RepeatedPtrIterator;
+
+  // The internal iterator.
+  void* const* it_;
+};
+
+// Provide an iterator that operates on pointers to the underlying objects
+// rather than the objects themselves as RepeatedPtrIterator does.
+// Consider using this when working with stl algorithms that change
+// the array.
+// The VoidPtr template parameter holds the type-agnostic pointer value
+// referenced by the iterator.  It should either be "void *" for a mutable
+// iterator, or "const void *" for a constant iterator.
+template<typename Element, typename VoidPtr>
+class RepeatedPtrOverPtrsIterator
+    : public std::iterator<std::random_access_iterator_tag, Element*> {
+ public:
+  typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
+  typedef std::iterator<
+          std::random_access_iterator_tag, Element*> superclass;
+
+  // Shadow the value_type in std::iterator<> because const_iterator::value_type
+  // needs to be T, not const T.
+  typedef typename remove_const<Element*>::type value_type;
+
+  // Let the compiler know that these are type names, so we don't have to
+  // write "typename" in front of them everywhere.
+  typedef typename superclass::reference reference;
+  typedef typename superclass::pointer pointer;
+  typedef typename superclass::difference_type difference_type;
+
+  RepeatedPtrOverPtrsIterator() : it_(NULL) {}
+  explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
+
+  // dereferenceable
+  reference operator*() const { return *reinterpret_cast<Element**>(it_); }
+  pointer   operator->() const { return &(operator*()); }
+
+  // {inc,dec}rementable
+  iterator& operator++() { ++it_; return *this; }
+  iterator  operator++(int) { return iterator(it_++); }
+  iterator& operator--() { --it_; return *this; }
+  iterator  operator--(int) { return iterator(it_--); }
+
+  // equality_comparable
+  bool operator==(const iterator& x) const { return it_ == x.it_; }
+  bool operator!=(const iterator& x) const { return it_ != x.it_; }
+
+  // less_than_comparable
+  bool operator<(const iterator& x) const { return it_ < x.it_; }
+  bool operator<=(const iterator& x) const { return it_ <= x.it_; }
+  bool operator>(const iterator& x) const { return it_ > x.it_; }
+  bool operator>=(const iterator& x) const { return it_ >= x.it_; }
+
+  // addable, subtractable
+  iterator& operator+=(difference_type d) {
+    it_ += d;
+    return *this;
+  }
+  friend iterator operator+(iterator it, difference_type d) {
+    it += d;
+    return it;
+  }
+  friend iterator operator+(difference_type d, iterator it) {
+    it += d;
+    return it;
+  }
+  iterator& operator-=(difference_type d) {
+    it_ -= d;
+    return *this;
+  }
+  friend iterator operator-(iterator it, difference_type d) {
+    it -= d;
+    return it;
+  }
+
+  // indexable
+  reference operator[](difference_type d) const { return *(*this + d); }
+
+  // random access iterator
+  difference_type operator-(const iterator& x) const { return it_ - x.it_; }
+
+ private:
+  template<typename OtherElement>
+  friend class RepeatedPtrIterator;
+
+  // The internal iterator.
+  VoidPtr* it_;
+};
+
+void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) {
+  std::swap(rep_, other->rep_);
+  std::swap(current_size_, other->current_size_);
+  std::swap(total_size_, other->total_size_);
+}
+
+}  // namespace internal
+
+template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::begin() {
+  return iterator(raw_data());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::begin() const {
+  return iterator(raw_data());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::cbegin() const {
+  return begin();
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::end() {
+  return iterator(raw_data() + size());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::end() const {
+  return iterator(raw_data() + size());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::cend() const {
+  return end();
+}
+
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() {
+  return pointer_iterator(raw_mutable_data());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() const {
+  return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_end() {
+  return pointer_iterator(raw_mutable_data() + size());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_end() const {
+  return const_pointer_iterator(
+      const_cast<const void**>(raw_mutable_data() + size()));
+}
+
+
+// Iterators and helper functions that follow the spirit of the STL
+// std::back_insert_iterator and std::back_inserter but are tailor-made
+// for RepeatedField and RepeatedPtrField. Typical usage would be:
+//
+//   std::copy(some_sequence.begin(), some_sequence.end(),
+//             google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
+//
+// Ported by johannes from util/gtl/proto-array-iterators.h
+
+namespace internal {
+// A back inserter for RepeatedField objects.
+template<typename T> class RepeatedFieldBackInsertIterator
+    : public std::iterator<std::output_iterator_tag, T> {
+ public:
+  explicit RepeatedFieldBackInsertIterator(
+      RepeatedField<T>* const mutable_field)
+      : field_(mutable_field) {
+  }
+  RepeatedFieldBackInsertIterator<T>& operator=(const T& value) {
+    field_->Add(value);
+    return *this;
+  }
+  RepeatedFieldBackInsertIterator<T>& operator*() {
+    return *this;
+  }
+  RepeatedFieldBackInsertIterator<T>& operator++() {
+    return *this;
+  }
+  RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
+    return *this;
+  }
+
+ private:
+  RepeatedField<T>* field_;
+};
+
+// A back inserter for RepeatedPtrField objects.
+template<typename T> class RepeatedPtrFieldBackInsertIterator
+    : public std::iterator<std::output_iterator_tag, T> {
+ public:
+  RepeatedPtrFieldBackInsertIterator(
+      RepeatedPtrField<T>* const mutable_field)
+      : field_(mutable_field) {
+  }
+  RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
+    *field_->Add() = value;
+    return *this;
+  }
+  RepeatedPtrFieldBackInsertIterator<T>& operator=(
+      const T* const ptr_to_value) {
+    *field_->Add() = *ptr_to_value;
+    return *this;
+  }
+  RepeatedPtrFieldBackInsertIterator<T>& operator*() {
+    return *this;
+  }
+  RepeatedPtrFieldBackInsertIterator<T>& operator++() {
+    return *this;
+  }
+  RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
+    return *this;
+  }
+
+ private:
+  RepeatedPtrField<T>* field_;
+};
+
+// A back inserter for RepeatedPtrFields that inserts by transfering ownership
+// of a pointer.
+template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator
+    : public std::iterator<std::output_iterator_tag, T> {
+ public:
+  explicit AllocatedRepeatedPtrFieldBackInsertIterator(
+      RepeatedPtrField<T>* const mutable_field)
+      : field_(mutable_field) {
+  }
+  AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
+      T* const ptr_to_value) {
+    field_->AddAllocated(ptr_to_value);
+    return *this;
+  }
+  AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
+    return *this;
+  }
+  AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
+    return *this;
+  }
+  AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
+      int /* unused */) {
+    return *this;
+  }
+
+ private:
+  RepeatedPtrField<T>* field_;
+};
+
+// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one
+// uses the UnsafeArenaAddAllocated instead.
+template<typename T>
+class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator
+    : public std::iterator<std::output_iterator_tag, T> {
+ public:
+  explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator(
+    ::google::protobuf::RepeatedPtrField<T>* const mutable_field)
+  : field_(mutable_field) {
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
+    T const* const ptr_to_value) {
+    field_->UnsafeArenaAddAllocated(const_cast<T*>(ptr_to_value));
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
+      int /* unused */) {
+    return *this;
+  }
+
+ private:
+  ::google::protobuf::RepeatedPtrField<T>* field_;
+};
+
+}  // namespace internal
+
+// Provides a back insert iterator for RepeatedField instances,
+// similar to std::back_inserter().
+template<typename T> internal::RepeatedFieldBackInsertIterator<T>
+RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
+  return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Provides a back insert iterator for RepeatedPtrField instances,
+// similar to std::back_inserter().
+template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
+RepeatedPtrFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
+  return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Special back insert iterator for RepeatedPtrField instances, just in
+// case someone wants to write generic template code that can access both
+// RepeatedFields and RepeatedPtrFields using a common name.
+template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
+RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
+  return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Provides a back insert iterator for RepeatedPtrField instances
+// similar to std::back_inserter() which transfers the ownership while
+// copying elements.
+template<typename T> internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>
+AllocatedRepeatedPtrFieldBackInserter(
+    RepeatedPtrField<T>* const mutable_field) {
+  return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>(
+      mutable_field);
+}
+
+// Similar to AllocatedRepeatedPtrFieldBackInserter, using
+// UnsafeArenaAddAllocated instead of AddAllocated.
+// This is slightly faster if that matters. It is also useful in legacy code
+// that uses temporary ownership to avoid copies. Example:
+// RepeatedPtrField<T> temp_field;
+// temp_field.AddAllocated(new T);
+// ... // Do something with temp_field
+// temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+// If you put temp_field on the arena this fails, because the ownership
+// transfers to the arena at the "AddAllocated" call and is not released anymore
+// causing a double delete. Using UnsafeArenaAddAllocated prevents this.
+template<typename T>
+internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>
+UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+    ::google::protobuf::RepeatedPtrField<T>* const mutable_field) {
+  return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>(
+      mutable_field);
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection.h b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection.h
new file mode 100644
index 0000000..44d14d5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection.h
@@ -0,0 +1,337 @@
+// 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.
+
+// This header file is protobuf internal. Users should not include this
+// file directly.
+#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
+#define GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/generated_enum_reflection.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+//   field->cpp_type()      T                Actual type of void*
+//   CPPTYPE_INT32        int32                   int32
+//   CPPTYPE_UINT32       uint32                  uint32
+//   CPPTYPE_INT64        int64                   int64
+//   CPPTYPE_UINT64       uint64                  uint64
+//   CPPTYPE_DOUBLE       double                  double
+//   CPPTYPE_FLOAT        float                   float
+//   CPPTYPE_BOOL         bool                    bool
+//   CPPTYPE_ENUM         generated enum type     int32
+//   CPPTYPE_STRING       string                  string
+//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
+//                        or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+  // Typedefs for clarity.
+  typedef void Field;
+  typedef void Value;
+  typedef void Iterator;
+
+  virtual ~RepeatedFieldAccessor();
+  virtual bool IsEmpty(const Field* data) const = 0;
+  virtual int Size(const Field* data) const = 0;
+  // Depends on the underlying representation of the repeated field, this
+  // method can return a pointer to the underlying object if such an object
+  // exists, or fill the data into scratch_space and return scratch_space.
+  // Callers of this method must ensure scratch_space is a valid pointer
+  // to a mutable object of the correct type.
+  virtual const Value* Get(
+      const Field* data, int index, Value* scratch_space) const = 0;
+
+  virtual void Clear(Field* data) const = 0;
+  virtual void Set(Field* data, int index, const Value* value) const = 0;
+  virtual void Add(Field* data, const Value* value) const = 0;
+  virtual void RemoveLast(Field* data) const = 0;
+  virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+  virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+                    Field* other_data) const = 0;
+
+  // Create an iterator that points at the begining of the repeated field.
+  virtual Iterator* BeginIterator(const Field* data) const = 0;
+  // Create an iterator that points at the end of the repeated field.
+  virtual Iterator* EndIterator(const Field* data) const = 0;
+  // Make a copy of an iterator and return the new copy.
+  virtual Iterator* CopyIterator(const Field* data,
+                                 const Iterator* iterator) const = 0;
+  // Move an iterator to point to the next element.
+  virtual Iterator* AdvanceIterator(const Field* data,
+                                    Iterator* iterator) const = 0;
+  // Compare whether two iterators point to the same element.
+  virtual bool EqualsIterator(const Field* data, const Iterator* a,
+                              const Iterator* b) const = 0;
+  // Delete an iterator created by BeginIterator(), EndIterator() and
+  // CopyIterator().
+  virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+  // Like Get() but for iterators.
+  virtual const Value* GetIteratorValue(const Field* data,
+                                        const Iterator* iterator,
+                                        Value* scratch_space) const = 0;
+
+  // Templated methods that make using this interface easier for non-message
+  // types.
+  template<typename T>
+  T Get(const Field* data, int index) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    ActualType scratch_space;
+    return static_cast<T>(
+        *reinterpret_cast<const ActualType*>(
+            Get(data, index, static_cast<Value*>(&scratch_space))));
+  }
+
+  template<typename T, typename ValueType>
+  void Set(Field* data, int index, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Set(data, index, static_cast<const Value*>(&tmp));
+  }
+
+  template<typename T, typename ValueType>
+  void Add(Field* data, const ValueType& value) const {
+    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+    // In this RepeatedFieldAccessor interface we pass/return data using
+    // raw pointers. Type of the data these raw pointers point to should
+    // be ActualType. Here we have a ValueType object and want a ActualType
+    // pointer. We can't cast a ValueType pointer to an ActualType pointer
+    // directly because their type might be different (for enums ValueType
+    // may be a generated enum type while ActualType is int32). To be safe
+    // we make a copy to get a temporary ActualType object and use it.
+    ActualType tmp = static_cast<ActualType>(value);
+    Add(data, static_cast<const Value*>(&tmp));
+  }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+    : public std::iterator<std::forward_iterator_tag, T> {
+  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+  // Constructor for non-message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(new AccessorValueType) {
+  }
+  // Constructor for message fields.
+  RepeatedFieldRefIterator(const void* data,
+                           const RepeatedFieldAccessor* accessor,
+                           bool begin,
+                           AccessorValueType* scratch_space)
+      : data_(data), accessor_(accessor),
+        iterator_(begin ? accessor->BeginIterator(data) :
+                          accessor->EndIterator(data)),
+        scratch_space_(scratch_space) {
+  }
+  ~RepeatedFieldRefIterator() {
+    accessor_->DeleteIterator(data_, iterator_);
+  }
+  RepeatedFieldRefIterator operator++(int) {
+    RepeatedFieldRefIterator tmp(*this);
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return tmp;
+  }
+  RepeatedFieldRefIterator& operator++() {
+    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+    return *this;
+  }
+  IteratorValueType operator*() const {
+    return static_cast<IteratorValueType>(
+        *static_cast<const AccessorValueType*>(
+            accessor_->GetIteratorValue(
+                data_, iterator_, scratch_space_.get())));
+  }
+  IteratorPointerType operator->() const {
+    return static_cast<IteratorPointerType>(
+        accessor_->GetIteratorValue(
+            data_, iterator_, scratch_space_.get()));
+  }
+  bool operator!=(const RepeatedFieldRefIterator& other) const {
+    assert(data_ == other.data_);
+    assert(accessor_ == other.accessor_);
+    return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+  }
+  bool operator==(const RepeatedFieldRefIterator& other) const {
+    return !this->operator!=(other);
+  }
+
+  RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+      : data_(other.data_), accessor_(other.accessor_),
+        iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+  }
+  RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+    if (this != &other) {
+      accessor_->DeleteIterator(data_, iterator_);
+      data_ = other.data_;
+      accessor_ = other.accessor_;
+      iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+    }
+    return *this;
+  }
+
+ protected:
+  const void* data_;
+  const RepeatedFieldAccessor* accessor_;
+  void* iterator_;
+  google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+  static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+    template<> struct PrimitiveTraits<type> { \
+      static const bool is_primitive = true; \
+      static const FieldDescriptor::CppType cpp_type = \
+          FieldDescriptor::CPPTYPE_ ## TYPE; \
+    };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef T AccessorValueType;
+  typedef T IteratorValueType;
+  typedef T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      PrimitiveTraits<T>::cpp_type;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  // We use int32 for repeated enums in RepeatedFieldAccessor.
+  typedef int32 AccessorValueType;
+  typedef T IteratorValueType;
+  typedef int32* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_ENUM;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef string AccessorValueType;
+  typedef string IteratorValueType;
+  typedef string* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_STRING;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+  static const Descriptor* get() {
+    return T::default_instance().GetDescriptor();
+  }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+  static const Descriptor* get() {
+    return NULL;
+  }
+};
+
+template<typename T>
+struct RefTypeTraits<
+    T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+  typedef RepeatedFieldRefIterator<T> iterator;
+  typedef RepeatedFieldAccessor AccessorType;
+  typedef Message AccessorValueType;
+  typedef const T& IteratorValueType;
+  typedef const T* IteratorPointerType;
+  static const FieldDescriptor::CppType cpp_type =
+      FieldDescriptor::CPPTYPE_MESSAGE;
+  static const Descriptor* GetMessageFieldDescriptor() {
+    return MessageDescriptorGetter<T>::get();
+  }
+};
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection_unittest.cc
new file mode 100644
index 0000000..fcebe5c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -0,0 +1,706 @@
+// 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.
+
+// Author: tgs@google.com (Tom Szymanski)
+//
+// Test reflection methods for aggregate access to Repeated[Ptr]Fields.
+// This test proto2 methods on a proto2 layout.
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/reflection.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+using unittest::ForeignMessage;
+using unittest::TestAllTypes;
+using unittest::TestAllExtensions;
+
+namespace {
+
+static int Func(int i, int j) {
+  return i * j;
+}
+
+static string StrFunc(int i, int j) {
+  string str;
+  SStringPrintf(&str, "%d", Func(i, 4));
+  return str;
+}
+
+TEST(RepeatedFieldReflectionTest, RegularFields) {
+  TestAllTypes message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    message.add_repeated_int32(Func(i, 1));
+    message.add_repeated_double(Func(i, 2));
+    message.add_repeated_string(StrFunc(i, 5));
+    message.add_repeated_foreign_message()->set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_repeated_int32 =
+      desc->FindFieldByName("repeated_int32");
+  const FieldDescriptor* fd_repeated_double =
+      desc->FindFieldByName("repeated_double");
+  const FieldDescriptor* fd_repeated_string =
+      desc->FindFieldByName("repeated_string");
+  const FieldDescriptor* fd_repeated_foreign_message =
+      desc->FindFieldByName("repeated_foreign_message");
+
+  // Get RepeatedField objects for all fields of interest.
+  const RepeatedField<int32>& rf_int32 =
+      refl->GetRepeatedField<int32>(message, fd_repeated_int32);
+  const RepeatedField<double>& rf_double =
+      refl->GetRepeatedField<double>(message, fd_repeated_double);
+
+  // Get mutable RepeatedField objects for all fields of interest.
+  RepeatedField<int32>* mrf_int32 =
+      refl->MutableRepeatedField<int32>(&message, fd_repeated_int32);
+  RepeatedField<double>* mrf_double =
+      refl->MutableRepeatedField<double>(&message, fd_repeated_double);
+
+  // Get RepeatedPtrField objects for all fields of interest.
+  const RepeatedPtrField<string>& rpf_string =
+      refl->GetRepeatedPtrField<string>(message, fd_repeated_string);
+  const RepeatedPtrField<ForeignMessage>& rpf_foreign_message =
+      refl->GetRepeatedPtrField<ForeignMessage>(
+          message, fd_repeated_foreign_message);
+  const RepeatedPtrField<Message>& rpf_message =
+      refl->GetRepeatedPtrField<Message>(
+          message, fd_repeated_foreign_message);
+
+  // Get mutable RepeatedPtrField objects for all fields of interest.
+  RepeatedPtrField<string>* mrpf_string =
+      refl->MutableRepeatedPtrField<string>(&message, fd_repeated_string);
+  RepeatedPtrField<ForeignMessage>* mrpf_foreign_message =
+      refl->MutableRepeatedPtrField<ForeignMessage>(
+          &message, fd_repeated_foreign_message);
+  RepeatedPtrField<Message>* mrpf_message =
+      refl->MutableRepeatedPtrField<Message>(
+          &message, fd_repeated_foreign_message);
+
+  // Make sure we can do gets and sets through the Repeated[Ptr]Field objects.
+  for (int i = 0; i < 10; ++i) {
+    // Check gets through const objects.
+    EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
+    EXPECT_EQ(rf_double.Get(i), Func(i, 2));
+    EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5));
+    EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage*>(&rpf_message.Get(i))->c(),
+              Func(i, 6));
+
+    // Check gets through mutable objects.
+    EXPECT_EQ(mrf_int32->Get(i), Func(i, 1));
+    EXPECT_EQ(mrf_double->Get(i), Func(i, 2));
+    EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5));
+    EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage*>(&mrpf_message->Get(i))->c(),
+              Func(i, 6));
+
+    // Check sets through mutable objects.
+    mrf_int32->Set(i, Func(i, -1));
+    mrf_double->Set(i, Func(i, -2));
+    mrpf_string->Mutable(i)->assign(StrFunc(i, -5));
+    mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6));
+    EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
+    EXPECT_EQ(message.repeated_double(i), Func(i, -2));
+    EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
+    down_cast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
+  }
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  // Make sure types are checked correctly at runtime.
+  const FieldDescriptor* fd_optional_int32 =
+      desc->FindFieldByName("optional_int32");
+  EXPECT_DEATH(refl->GetRepeatedField<int32>(
+      message, fd_optional_int32), "requires a repeated field");
+  EXPECT_DEATH(refl->GetRepeatedField<double>(
+      message, fd_repeated_int32), "not the right type");
+  EXPECT_DEATH(refl->GetRepeatedPtrField<TestAllTypes>(
+      message, fd_repeated_foreign_message), "wrong submessage type");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+
+TEST(RepeatedFieldReflectionTest, ExtensionFields) {
+  TestAllExtensions extended_message;
+  const Reflection* refl = extended_message.GetReflection();
+  const Descriptor* desc = extended_message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    extended_message.AddExtension(
+        unittest::repeated_int64_extension, Func(i, 1));
+  }
+
+  const FieldDescriptor* fd_repeated_int64_extension =
+      desc->file()->FindExtensionByName("repeated_int64_extension");
+  GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
+
+  const RepeatedField<int64>& rf_int64_extension =
+      refl->GetRepeatedField<int64>(extended_message,
+                                    fd_repeated_int64_extension);
+
+  RepeatedField<int64>* mrf_int64_extension =
+      refl->MutableRepeatedField<int64>(&extended_message,
+                                        fd_repeated_int64_extension);
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
+    mrf_int64_extension->Set(i, Func(i, -1));
+    EXPECT_EQ(Func(i, -1),
+        extended_message.GetExtension(unittest::repeated_int64_extension, i));
+  }
+}
+
+template<typename Ref, typename MessageType, typename ValueType>
+void TestRepeatedFieldRefIterator(
+    const Ref& handle, const MessageType& message,
+    ValueType (MessageType::*GetFunc)(int) const) {
+  int index = 0;
+  for (typename Ref::const_iterator it = handle.begin();
+       it != handle.end(); ++it) {
+    EXPECT_EQ((message.*GetFunc)(index), *it);
+    ++index;
+  }
+  EXPECT_EQ(handle.size(), index);
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
+  TestAllTypes message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    message.add_repeated_int32(Func(i, 1));
+    message.add_repeated_double(Func(i, 2));
+    message.add_repeated_string(StrFunc(i, 5));
+    message.add_repeated_foreign_message()->set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_repeated_int32 =
+      desc->FindFieldByName("repeated_int32");
+  const FieldDescriptor* fd_repeated_double =
+      desc->FindFieldByName("repeated_double");
+  const FieldDescriptor* fd_repeated_string =
+      desc->FindFieldByName("repeated_string");
+  const FieldDescriptor* fd_repeated_foreign_message =
+      desc->FindFieldByName("repeated_foreign_message");
+
+  // Get RepeatedFieldRef objects for all fields of interest.
+  const RepeatedFieldRef<int32> rf_int32 =
+      refl->GetRepeatedFieldRef<int32>(message, fd_repeated_int32);
+  const RepeatedFieldRef<double> rf_double =
+      refl->GetRepeatedFieldRef<double>(message, fd_repeated_double);
+  const RepeatedFieldRef<string> rf_string =
+      refl->GetRepeatedFieldRef<string>(message, fd_repeated_string);
+  const RepeatedFieldRef<ForeignMessage> rf_foreign_message =
+      refl->GetRepeatedFieldRef<ForeignMessage>(
+          message, fd_repeated_foreign_message);
+  const RepeatedFieldRef<Message> rf_message =
+      refl->GetRepeatedFieldRef<Message>(
+          message, fd_repeated_foreign_message);
+
+  // Get MutableRepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<int32> mrf_int32 =
+      refl->GetMutableRepeatedFieldRef<int32>(&message, fd_repeated_int32);
+  const MutableRepeatedFieldRef<double> mrf_double =
+      refl->GetMutableRepeatedFieldRef<double>(&message, fd_repeated_double);
+  const MutableRepeatedFieldRef<string> mrf_string =
+      refl->GetMutableRepeatedFieldRef<string>(&message, fd_repeated_string);
+  const MutableRepeatedFieldRef<ForeignMessage> mrf_foreign_message =
+      refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+          &message, fd_repeated_foreign_message);
+  const MutableRepeatedFieldRef<Message> mrf_message =
+      refl->GetMutableRepeatedFieldRef<Message>(
+          &message, fd_repeated_foreign_message);
+
+  EXPECT_EQ(message.repeated_int32_size(), rf_int32.size());
+  EXPECT_EQ(message.repeated_int32_size(), mrf_int32.size());
+  EXPECT_EQ(message.repeated_double_size(), rf_double.size());
+  EXPECT_EQ(message.repeated_double_size(), mrf_double.size());
+  EXPECT_EQ(message.repeated_string_size(), rf_string.size());
+  EXPECT_EQ(message.repeated_string_size(), mrf_string.size());
+  EXPECT_EQ(message.repeated_foreign_message_size(),
+            rf_foreign_message.size());
+  EXPECT_EQ(message.repeated_foreign_message_size(),
+            mrf_foreign_message.size());
+  EXPECT_EQ(message.repeated_foreign_message_size(), rf_message.size());
+  EXPECT_EQ(message.repeated_foreign_message_size(), mrf_message.size());
+
+  EXPECT_FALSE(rf_int32.empty());
+  EXPECT_FALSE(mrf_int32.empty());
+  EXPECT_FALSE(rf_double.empty());
+  EXPECT_FALSE(mrf_double.empty());
+  EXPECT_FALSE(rf_string.empty());
+  EXPECT_FALSE(mrf_string.empty());
+  EXPECT_FALSE(rf_foreign_message.empty());
+  EXPECT_FALSE(mrf_foreign_message.empty());
+  EXPECT_FALSE(rf_message.empty());
+  EXPECT_FALSE(mrf_message.empty());
+
+  // Make sure we can do gets and sets through the RepeatedFieldRef objects.
+  for (int i = 0; i < 10; ++i) {
+    // Check gets through const objects.
+    EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
+    EXPECT_EQ(rf_double.Get(i), Func(i, 2));
+    EXPECT_EQ(rf_string.Get(i), StrFunc(i, 5));
+    ForeignMessage scratch_space;
+    EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage&>(
+        rf_message.Get(i, &scratch_space)).c(), Func(i, 6));
+
+    // Check gets through mutable objects.
+    EXPECT_EQ(mrf_int32.Get(i), Func(i, 1));
+    EXPECT_EQ(mrf_double.Get(i), Func(i, 2));
+    EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5));
+    EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage&>(
+        mrf_message.Get(i, &scratch_space)).c(), Func(i, 6));
+
+    // Check sets through mutable objects.
+    mrf_int32.Set(i, Func(i, -1));
+    mrf_double.Set(i, Func(i, -2));
+    mrf_string.Set(i, StrFunc(i, -5));
+    ForeignMessage foreign_message;
+    foreign_message.set_c(Func(i, -6));
+    mrf_foreign_message.Set(i, foreign_message);
+    EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
+    EXPECT_EQ(message.repeated_double(i), Func(i, -2));
+    EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
+    foreign_message.set_c(Func(i, 7));
+    mrf_message.Set(i, foreign_message);
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
+  }
+
+  // Test iterators.
+  TestRepeatedFieldRefIterator(rf_int32, message,
+                               &TestAllTypes::repeated_int32);
+  TestRepeatedFieldRefIterator(rf_double, message,
+                               &TestAllTypes::repeated_double);
+  TestRepeatedFieldRefIterator(rf_string, message,
+                               &TestAllTypes::repeated_string);
+
+  // Test iterators for message fields.
+  typedef RepeatedFieldRef<ForeignMessage>::iterator MessageIterator;
+  int index = 0;
+  for (MessageIterator it = rf_foreign_message.begin();
+       it != rf_foreign_message.end(); ++it) {
+    EXPECT_EQ(message.repeated_foreign_message(index).c(), it->c());
+    ++index;
+  }
+  EXPECT_EQ(10, index);
+
+  // Test iterator operators that are not ususally used in regular for-loops.
+  // Including: post increment, assign, ==.
+  MessageIterator old_it = rf_foreign_message.begin();
+  MessageIterator new_it = old_it++;
+  EXPECT_FALSE(old_it == new_it);
+  // Check that old_it++ increments old_it once.
+  for (index = 1; old_it != rf_foreign_message.end(); ++old_it, ++index) {
+    EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c());
+  }
+  EXPECT_EQ(10, index);
+  // Test assign operator.
+  old_it = new_it;
+  for (index = 0; old_it != rf_foreign_message.end(); ++old_it, ++index) {
+    EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c());
+  }
+  EXPECT_EQ(10, index);
+  // Check that the returned value of old_it++ is the one before increment.
+  for (index = 0; new_it != rf_foreign_message.end(); ++new_it, ++index) {
+    EXPECT_EQ(message.repeated_foreign_message(index).c(), new_it->c());
+  }
+  EXPECT_EQ(10, index);
+
+  // Test MutableRepeatedFieldRef::Add()
+  mrf_int32.Add(1234);
+  mrf_double.Add(1234.0);
+  mrf_string.Add("1234");
+  ForeignMessage foreign_message;
+  foreign_message.set_c(1234);
+  mrf_foreign_message.Add(foreign_message);
+  EXPECT_EQ(1234, message.repeated_int32(10));
+  EXPECT_EQ(1234.0, message.repeated_double(10));
+  EXPECT_EQ("1234", message.repeated_string(10));
+  EXPECT_EQ(1234, message.repeated_foreign_message(10).c());
+
+  // Test MutableRepeatedFieldRef::RemoveLast()
+  mrf_int32.RemoveLast();
+  mrf_double.RemoveLast();
+  mrf_string.RemoveLast();
+  mrf_foreign_message.RemoveLast();
+  EXPECT_EQ(10, message.repeated_int32_size());
+  EXPECT_EQ(10, message.repeated_double_size());
+  EXPECT_EQ(10, message.repeated_string_size());
+  EXPECT_EQ(10, message.repeated_foreign_message_size());
+
+  // Test MutableRepeatedFieldRef::SwapElements()
+  mrf_int32.SwapElements(0, 9);
+  mrf_double.SwapElements(0, 9);
+  mrf_string.SwapElements(0, 9);
+  mrf_foreign_message.SwapElements(0, 9);
+  EXPECT_EQ(Func(9, -1), message.repeated_int32(0));
+  EXPECT_EQ(Func(0, -1), message.repeated_int32(9));
+  EXPECT_EQ(Func(9, -2), message.repeated_double(0));
+  EXPECT_EQ(Func(0, -2), message.repeated_double(9));
+  EXPECT_EQ(StrFunc(9, -5), message.repeated_string(0));
+  EXPECT_EQ(StrFunc(0, -5), message.repeated_string(9));
+  EXPECT_EQ(Func(9, 7), message.repeated_foreign_message(0).c());
+  EXPECT_EQ(Func(0, 7), message.repeated_foreign_message(9).c());
+
+  // Test MutableRepeatedFieldRef::Clear()
+  mrf_int32.Clear();
+  mrf_double.Clear();
+  mrf_string.Clear();
+  mrf_foreign_message.Clear();
+  EXPECT_EQ(0, message.repeated_int32_size());
+  EXPECT_EQ(0, message.repeated_double_size());
+  EXPECT_EQ(0, message.repeated_string_size());
+  EXPECT_EQ(0, message.repeated_foreign_message_size());
+
+  // Test (Mutable)RepeatedFieldRef::empty()
+  EXPECT_TRUE(rf_int32.empty());
+  EXPECT_TRUE(mrf_int32.empty());
+  EXPECT_TRUE(rf_double.empty());
+  EXPECT_TRUE(mrf_double.empty());
+  EXPECT_TRUE(rf_string.empty());
+  EXPECT_TRUE(mrf_string.empty());
+  EXPECT_TRUE(rf_foreign_message.empty());
+  EXPECT_TRUE(mrf_foreign_message.empty());
+  EXPECT_TRUE(rf_message.empty());
+  EXPECT_TRUE(mrf_message.empty());
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+
+  // Make sure types are checked correctly at runtime.
+  const FieldDescriptor* fd_optional_int32 =
+      desc->FindFieldByName("optional_int32");
+  EXPECT_DEATH(refl->GetRepeatedFieldRef<int32>(
+      message, fd_optional_int32), "");
+  EXPECT_DEATH(refl->GetRepeatedFieldRef<double>(
+      message, fd_repeated_int32), "");
+  EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
+      message, fd_repeated_foreign_message), "");
+
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) {
+  TestAllTypes message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    message.add_repeated_nested_enum(TestAllTypes::BAR);
+  }
+
+  const FieldDescriptor* fd_repeated_nested_enum =
+      desc->FindFieldByName("repeated_nested_enum");
+  const RepeatedFieldRef<TestAllTypes::NestedEnum> enum_ref =
+      refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          message, fd_repeated_nested_enum);
+  const MutableRepeatedFieldRef<TestAllTypes::NestedEnum>
+  mutable_enum_ref =
+      refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          &message, fd_repeated_nested_enum);
+  const RepeatedFieldRef<int32> int32_ref =
+      refl->GetRepeatedFieldRef<int32>(
+          message, fd_repeated_nested_enum);
+  const MutableRepeatedFieldRef<int32> mutable_int32_ref =
+      refl->GetMutableRepeatedFieldRef<int32>(
+          &message, fd_repeated_nested_enum);
+
+  EXPECT_EQ(message.repeated_nested_enum_size(), enum_ref.size());
+  EXPECT_EQ(message.repeated_nested_enum_size(), mutable_enum_ref.size());
+  EXPECT_EQ(message.repeated_nested_enum_size(), int32_ref.size());
+  EXPECT_EQ(message.repeated_nested_enum_size(), mutable_int32_ref.size());
+
+  EXPECT_FALSE(enum_ref.empty());
+  EXPECT_FALSE(mutable_enum_ref.empty());
+  EXPECT_FALSE(int32_ref.empty());
+  EXPECT_FALSE(mutable_int32_ref.empty());
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(i));
+    EXPECT_EQ(TestAllTypes::BAR, mutable_enum_ref.Get(i));
+    mutable_enum_ref.Set(i, TestAllTypes::BAZ);
+    EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(i));
+    EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i));
+
+    message.set_repeated_nested_enum(i, TestAllTypes::BAR);
+    EXPECT_EQ(TestAllTypes::BAR, int32_ref.Get(i));
+    EXPECT_EQ(TestAllTypes::BAR, mutable_int32_ref.Get(i));
+    mutable_int32_ref.Set(i, TestAllTypes::BAZ);
+    EXPECT_EQ(TestAllTypes::BAZ, int32_ref.Get(i));
+    EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i));
+  }
+
+  TestRepeatedFieldRefIterator(enum_ref, message,
+                               &TestAllTypes::repeated_nested_enum);
+  TestRepeatedFieldRefIterator(int32_ref, message,
+                               &TestAllTypes::repeated_nested_enum);
+
+  // Test Add()
+  mutable_enum_ref.Add(TestAllTypes::FOO);
+  EXPECT_EQ(TestAllTypes::FOO, message.repeated_nested_enum(10));
+  mutable_int32_ref.Add(TestAllTypes::BAR);
+  EXPECT_EQ(TestAllTypes::BAR, message.repeated_nested_enum(11));
+
+  // Test RemoveLast()
+  mutable_enum_ref.RemoveLast();
+  EXPECT_EQ(11, message.repeated_nested_enum_size());
+  mutable_int32_ref.RemoveLast();
+  EXPECT_EQ(10, message.repeated_nested_enum_size());
+
+  // Test SwapElements()
+  mutable_enum_ref.Set(0, TestAllTypes::BAR);
+  mutable_enum_ref.Set(9, TestAllTypes::BAZ);
+  mutable_enum_ref.SwapElements(0, 9);
+  EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(0));
+  EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(9));
+  mutable_int32_ref.SwapElements(0, 9);
+  EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(0));
+  EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(9));
+
+  // Test Clear()
+  mutable_enum_ref.Clear();
+  EXPECT_EQ(0, message.repeated_nested_enum_size());
+  mutable_enum_ref.Add(TestAllTypes::FOO);
+  EXPECT_EQ(1, message.repeated_nested_enum_size());
+  mutable_int32_ref.Clear();
+  EXPECT_EQ(0, message.repeated_nested_enum_size());
+
+  // Test empty()
+  EXPECT_TRUE(enum_ref.empty());
+  EXPECT_TRUE(mutable_enum_ref.empty());
+  EXPECT_TRUE(int32_ref.empty());
+  EXPECT_TRUE(mutable_int32_ref.empty());
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForExtensionFields) {
+  TestAllExtensions extended_message;
+  const Reflection* refl = extended_message.GetReflection();
+  const Descriptor* desc = extended_message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    extended_message.AddExtension(
+        unittest::repeated_int64_extension, Func(i, 1));
+  }
+
+  const FieldDescriptor* fd_repeated_int64_extension =
+      desc->file()->FindExtensionByName("repeated_int64_extension");
+  GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
+
+  const RepeatedFieldRef<int64> rf_int64_extension =
+      refl->GetRepeatedFieldRef<int64>(extended_message,
+                                          fd_repeated_int64_extension);
+
+  const MutableRepeatedFieldRef<int64> mrf_int64_extension =
+      refl->GetMutableRepeatedFieldRef<int64>(&extended_message,
+                                                 fd_repeated_int64_extension);
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
+    mrf_int64_extension.Set(i, Func(i, -1));
+    EXPECT_EQ(Func(i, -1),
+        extended_message.GetExtension(unittest::repeated_int64_extension, i));
+  }
+}
+
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
+  // Set-up message content.
+  TestAllTypes m0, m1, m2;
+  for (int i = 0; i < 10; ++i) {
+    m0.add_repeated_int32(Func(i, 1));
+    m0.add_repeated_double(Func(i, 2));
+    m0.add_repeated_string(StrFunc(i, 5));
+    m0.add_repeated_foreign_message()->set_c(Func(i, 6));
+    m0.add_repeated_nested_enum(TestAllTypes::FOO);
+    m1.add_repeated_int32(Func(i, 11));
+    m1.add_repeated_double(Func(i, 12));
+    m1.add_repeated_string(StrFunc(i, 15));
+    m1.add_repeated_foreign_message()->set_c(Func(i, 16));
+    m1.add_repeated_nested_enum(TestAllTypes::BAR);
+    m2.add_repeated_int32(Func(i, 21));
+    m2.add_repeated_double(Func(i, 22));
+    m2.add_repeated_string(StrFunc(i, 25));
+    m2.add_repeated_foreign_message()->set_c(Func(i, 26));
+    m2.add_repeated_nested_enum(TestAllTypes::BAZ);
+  }
+
+  const Reflection* refl = m0.GetReflection();
+  const Descriptor* desc = m0.GetDescriptor();
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_repeated_int32 =
+      desc->FindFieldByName("repeated_int32");
+  const FieldDescriptor* fd_repeated_double =
+      desc->FindFieldByName("repeated_double");
+  const FieldDescriptor* fd_repeated_string =
+      desc->FindFieldByName("repeated_string");
+  const FieldDescriptor* fd_repeated_foreign_message =
+      desc->FindFieldByName("repeated_foreign_message");
+  const FieldDescriptor* fd_repeated_nested_enum =
+      desc->FindFieldByName("repeated_nested_enum");
+
+  // Get MutableRepeatedFieldRef objects for all fields of interest.
+  const MutableRepeatedFieldRef<int32> mrf_int32 =
+      refl->GetMutableRepeatedFieldRef<int32>(&m0, fd_repeated_int32);
+  const MutableRepeatedFieldRef<double> mrf_double =
+      refl->GetMutableRepeatedFieldRef<double>(&m0, fd_repeated_double);
+  const MutableRepeatedFieldRef<string> mrf_string =
+      refl->GetMutableRepeatedFieldRef<string>(&m0, fd_repeated_string);
+  const MutableRepeatedFieldRef<ForeignMessage> mrf_foreign_message =
+      refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+          &m0, fd_repeated_foreign_message);
+  const MutableRepeatedFieldRef<TestAllTypes::NestedEnum>
+  mrf_nested_enum =
+      refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          &m0, fd_repeated_nested_enum);
+
+  // Test MutableRepeatedRef::CopyFrom
+  mrf_int32.CopyFrom(
+      refl->GetRepeatedFieldRef<int32>(m1, fd_repeated_int32));
+  mrf_double.CopyFrom(
+      refl->GetRepeatedFieldRef<double>(m1, fd_repeated_double));
+  mrf_string.CopyFrom(
+      refl->GetRepeatedFieldRef<string>(m1, fd_repeated_string));
+  mrf_foreign_message.CopyFrom(
+      refl->GetRepeatedFieldRef<ForeignMessage>(
+          m1, fd_repeated_foreign_message));
+  mrf_nested_enum.CopyFrom(
+      refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          m1, fd_repeated_nested_enum));
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 11), m0.repeated_int32(i));
+    EXPECT_EQ(Func(i, 12), m0.repeated_double(i));
+    EXPECT_EQ(StrFunc(i, 15), m0.repeated_string(i));
+    EXPECT_EQ(Func(i, 16), m0.repeated_foreign_message(i).c());
+    EXPECT_EQ(TestAllTypes::BAR, m0.repeated_nested_enum(i));
+  }
+
+  // Test MutableRepeatedRef::MergeFrom
+  mrf_int32.MergeFrom(
+      refl->GetRepeatedFieldRef<int32>(m2, fd_repeated_int32));
+  mrf_double.MergeFrom(
+      refl->GetRepeatedFieldRef<double>(m2, fd_repeated_double));
+  mrf_string.MergeFrom(
+      refl->GetRepeatedFieldRef<string>(m2, fd_repeated_string));
+  mrf_foreign_message.MergeFrom(
+      refl->GetRepeatedFieldRef<ForeignMessage>(
+          m2, fd_repeated_foreign_message));
+  mrf_nested_enum.MergeFrom(
+      refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          m2, fd_repeated_nested_enum));
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 21), m0.repeated_int32(i + 10));
+    EXPECT_EQ(Func(i, 22), m0.repeated_double(i + 10));
+    EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i + 10));
+    EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i + 10).c());
+    EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i + 10));
+  }
+
+  // Test MutableRepeatedRef::Swap
+  // Swap between m0 and m2.
+  mrf_int32.Swap(
+      refl->GetMutableRepeatedFieldRef<int32>(&m2, fd_repeated_int32));
+  mrf_double.Swap(
+      refl->GetMutableRepeatedFieldRef<double>(&m2, fd_repeated_double));
+  mrf_string.Swap(
+      refl->GetMutableRepeatedFieldRef<string>(&m2, fd_repeated_string));
+  mrf_foreign_message.Swap(
+      refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+          &m2, fd_repeated_foreign_message));
+  mrf_nested_enum.Swap(
+      refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+          &m2, fd_repeated_nested_enum));
+  for (int i = 0; i < 10; ++i) {
+    // Check the content of m0.
+    EXPECT_EQ(Func(i, 21), m0.repeated_int32(i));
+    EXPECT_EQ(Func(i, 22), m0.repeated_double(i));
+    EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i));
+    EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i).c());
+    EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i));
+
+    // Check the content of m2.
+    EXPECT_EQ(Func(i, 11), m2.repeated_int32(i));
+    EXPECT_EQ(Func(i, 12), m2.repeated_double(i));
+    EXPECT_EQ(StrFunc(i, 15), m2.repeated_string(i));
+    EXPECT_EQ(Func(i, 16), m2.repeated_foreign_message(i).c());
+    EXPECT_EQ(TestAllTypes::BAR, m2.repeated_nested_enum(i));
+    EXPECT_EQ(Func(i, 21), m2.repeated_int32(i + 10));
+    EXPECT_EQ(Func(i, 22), m2.repeated_double(i + 10));
+    EXPECT_EQ(StrFunc(i, 25), m2.repeated_string(i + 10));
+    EXPECT_EQ(Func(i, 26), m2.repeated_foreign_message(i + 10).c());
+    EXPECT_EQ(TestAllTypes::BAZ, m2.repeated_nested_enum(i + 10));
+  }
+}
+
+// Test that GetRepeatedFieldRef/MutableRepeatedFieldRef works with
+// DynamicMessage.
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) {
+  // DynamicMessage shares the same memory layout as generated message
+  // and use the same GeneratedMessageReflection code for reflection.
+  // All code paths should already be covered by the other tests for
+  // generated messages. Here we just test one field.
+
+  const Descriptor* desc = TestAllTypes::descriptor();
+  const FieldDescriptor* fd_repeated_int32 =
+      desc->FindFieldByName("repeated_int32");
+
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
+  const Reflection* refl = dynamic_message->GetReflection();
+
+  MutableRepeatedFieldRef<int32> rf_int32 =
+      refl->GetMutableRepeatedFieldRef<int32>(
+          dynamic_message.get(), fd_repeated_int32);
+  rf_int32.Add(1234);
+  EXPECT_EQ(1, refl->FieldSize(*dynamic_message, fd_repeated_int32));
+  EXPECT_EQ(1234, refl->GetRepeatedInt32(*dynamic_message,
+                                         fd_repeated_int32, 0));
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/repeated_field_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_unittest.cc
new file mode 100644
index 0000000..39b24b3
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/repeated_field_unittest.cc
@@ -0,0 +1,1566 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// TODO(kenton):  Improve this unittest to bring it up to the standards of
+//   other proto2 unittests.
+
+#include <algorithm>
+#include <limits>
+#include <list>
+#include <vector>
+
+#include <google/protobuf/repeated_field.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+using protobuf_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+
+// Test operations on a small RepeatedField.
+TEST(RepeatedField, Small) {
+  RepeatedField<int> field;
+
+  EXPECT_TRUE(field.empty());
+  EXPECT_EQ(field.size(), 0);
+
+  field.Add(5);
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 1);
+  EXPECT_EQ(field.Get(0), 5);
+
+  field.Add(42);
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 2);
+  EXPECT_EQ(field.Get(0), 5);
+  EXPECT_EQ(field.Get(1), 42);
+
+  field.Set(1, 23);
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 2);
+  EXPECT_EQ(field.Get(0), 5);
+  EXPECT_EQ(field.Get(1), 23);
+
+  field.RemoveLast();
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 1);
+  EXPECT_EQ(field.Get(0), 5);
+
+  field.Clear();
+
+  EXPECT_TRUE(field.empty());
+  EXPECT_EQ(field.size(), 0);
+  // Additional bytes are for 'struct Rep' header.
+  int expected_usage = 4 * sizeof(int) + sizeof(Arena*);
+  EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
+}
+
+
+// Test operations on a RepeatedField which is large enough to allocate a
+// separate array.
+TEST(RepeatedField, Large) {
+  RepeatedField<int> field;
+
+  for (int i = 0; i < 16; i++) {
+    field.Add(i * i);
+  }
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 16);
+
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field.Get(i), i * i);
+  }
+
+  int expected_usage = 16 * sizeof(int);
+  EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage);
+}
+
+// Test swapping between various types of RepeatedFields.
+TEST(RepeatedField, SwapSmallSmall) {
+  RepeatedField<int> field1;
+  RepeatedField<int> field2;
+
+  field1.Add(5);
+  field1.Add(42);
+
+  EXPECT_FALSE(field1.empty());
+  EXPECT_EQ(field1.size(), 2);
+  EXPECT_EQ(field1.Get(0), 5);
+  EXPECT_EQ(field1.Get(1), 42);
+
+  EXPECT_TRUE(field2.empty());
+  EXPECT_EQ(field2.size(), 0);
+
+  field1.Swap(&field2);
+
+  EXPECT_TRUE(field1.empty());
+  EXPECT_EQ(field1.size(), 0);
+
+  EXPECT_FALSE(field2.empty());
+  EXPECT_EQ(field2.size(), 2);
+  EXPECT_EQ(field2.Get(0), 5);
+  EXPECT_EQ(field2.Get(1), 42);
+}
+
+TEST(RepeatedField, SwapLargeSmall) {
+  RepeatedField<int> field1;
+  RepeatedField<int> field2;
+
+  for (int i = 0; i < 16; i++) {
+    field1.Add(i * i);
+  }
+  field2.Add(5);
+  field2.Add(42);
+  field1.Swap(&field2);
+
+  EXPECT_EQ(field1.size(), 2);
+  EXPECT_EQ(field1.Get(0), 5);
+  EXPECT_EQ(field1.Get(1), 42);
+  EXPECT_EQ(field2.size(), 16);
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field2.Get(i), i * i);
+  }
+}
+
+TEST(RepeatedField, SwapLargeLarge) {
+  RepeatedField<int> field1;
+  RepeatedField<int> field2;
+
+  field1.Add(5);
+  field1.Add(42);
+  for (int i = 0; i < 16; i++) {
+    field1.Add(i);
+    field2.Add(i * i);
+  }
+  field2.Swap(&field1);
+
+  EXPECT_EQ(field1.size(), 16);
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field1.Get(i), i * i);
+  }
+  EXPECT_EQ(field2.size(), 18);
+  EXPECT_EQ(field2.Get(0), 5);
+  EXPECT_EQ(field2.Get(1), 42);
+  for (int i = 2; i < 18; i++) {
+    EXPECT_EQ(field2.Get(i), i - 2);
+  }
+}
+
+// Determines how much space was reserved by the given field by adding elements
+// to it until it re-allocates its space.
+static int ReservedSpace(RepeatedField<int>* field) {
+  const int* ptr = field->data();
+  do {
+    field->Add(0);
+  } while (field->data() == ptr);
+
+  return field->size() - 1;
+}
+
+TEST(RepeatedField, ReserveMoreThanDouble) {
+  // Reserve more than double the previous space in the field and expect the
+  // field to reserve exactly the amount specified.
+  RepeatedField<int> field;
+  field.Reserve(20);
+
+  EXPECT_EQ(20, ReservedSpace(&field));
+}
+
+TEST(RepeatedField, ReserveLessThanDouble) {
+  // Reserve less than double the previous space in the field and expect the
+  // field to grow by double instead.
+  RepeatedField<int> field;
+  field.Reserve(20);
+  field.Reserve(30);
+
+  EXPECT_EQ(40, ReservedSpace(&field));
+}
+
+TEST(RepeatedField, ReserveLessThanExisting) {
+  // Reserve less than the previous space in the field and expect the
+  // field to not re-allocate at all.
+  RepeatedField<int> field;
+  field.Reserve(20);
+  const int* previous_ptr = field.data();
+  field.Reserve(10);
+
+  EXPECT_EQ(previous_ptr, field.data());
+  EXPECT_EQ(20, ReservedSpace(&field));
+}
+
+TEST(RepeatedField, Resize) {
+  RepeatedField<int> field;
+  field.Resize(2, 1);
+  EXPECT_EQ(2, field.size());
+  field.Resize(5, 2);
+  EXPECT_EQ(5, field.size());
+  field.Resize(4, 3);
+  ASSERT_EQ(4, field.size());
+  EXPECT_EQ(1, field.Get(0));
+  EXPECT_EQ(1, field.Get(1));
+  EXPECT_EQ(2, field.Get(2));
+  EXPECT_EQ(2, field.Get(3));
+  field.Resize(0, 4);
+  EXPECT_TRUE(field.empty());
+}
+
+TEST(RepeatedField, MergeFrom) {
+  RepeatedField<int> source, destination;
+  source.Add(4);
+  source.Add(5);
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination.MergeFrom(source);
+
+  ASSERT_EQ(5, destination.size());
+  EXPECT_EQ(1, destination.Get(0));
+  EXPECT_EQ(2, destination.Get(1));
+  EXPECT_EQ(3, destination.Get(2));
+  EXPECT_EQ(4, destination.Get(3));
+  EXPECT_EQ(5, destination.Get(4));
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(RepeatedField, MergeFromSelf) {
+  RepeatedField<int> me;
+  me.Add(3);
+  EXPECT_DEATH(me.MergeFrom(me), "");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(RepeatedField, CopyFrom) {
+  RepeatedField<int> source, destination;
+  source.Add(4);
+  source.Add(5);
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
+TEST(RepeatedField, CopyFromSelf) {
+  RepeatedField<int> me;
+  me.Add(3);
+  me.CopyFrom(me);
+  ASSERT_EQ(1, me.size());
+  EXPECT_EQ(3, me.Get(0));
+}
+
+TEST(RepeatedField, Erase) {
+  RepeatedField<int> me;
+  RepeatedField<int>::iterator it = me.erase(me.begin(), me.end());
+  EXPECT_TRUE(me.begin() == it);
+  EXPECT_EQ(0, me.size());
+
+  me.Add(1);
+  me.Add(2);
+  me.Add(3);
+  it = me.erase(me.begin(), me.end());
+  EXPECT_TRUE(me.begin() == it);
+  EXPECT_EQ(0, me.size());
+
+  me.Add(4);
+  me.Add(5);
+  me.Add(6);
+  it = me.erase(me.begin() + 2, me.end());
+  EXPECT_TRUE(me.begin() + 2 == it);
+  EXPECT_EQ(2, me.size());
+  EXPECT_EQ(4, me.Get(0));
+  EXPECT_EQ(5, me.Get(1));
+
+  me.Add(6);
+  me.Add(7);
+  me.Add(8);
+  it = me.erase(me.begin() + 1, me.begin() + 3);
+  EXPECT_TRUE(me.begin() + 1 == it);
+  EXPECT_EQ(3, me.size());
+  EXPECT_EQ(4, me.Get(0));
+  EXPECT_EQ(7, me.Get(1));
+  EXPECT_EQ(8, me.Get(2));
+}
+
+TEST(RepeatedField, CopyConstruct) {
+  RepeatedField<int> source;
+  source.Add(1);
+  source.Add(2);
+
+  RepeatedField<int> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ(1, destination.Get(0));
+  EXPECT_EQ(2, destination.Get(1));
+}
+
+TEST(RepeatedField, IteratorConstruct) {
+  vector<int> values;
+  values.push_back(1);
+  values.push_back(2);
+
+  RepeatedField<int> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0], field.Get(0));
+  EXPECT_EQ(values[1], field.Get(1));
+
+  RepeatedField<int> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0], other.Get(0));
+  EXPECT_EQ(values[1], other.Get(1));
+}
+
+TEST(RepeatedField, CopyAssign) {
+  RepeatedField<int> source, destination;
+  source.Add(4);
+  source.Add(5);
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
+TEST(RepeatedField, SelfAssign) {
+  // Verify that assignment to self does not destroy data.
+  RepeatedField<int> source, *p;
+  p = &source;
+  source.Add(7);
+  source.Add(8);
+
+  *p = source;
+
+  ASSERT_EQ(2, source.size());
+  EXPECT_EQ(7, source.Get(0));
+  EXPECT_EQ(8, source.Get(1));
+}
+
+TEST(RepeatedField, MutableDataIsMutable) {
+  RepeatedField<int> field;
+  field.Add(1);
+  EXPECT_EQ(1, field.Get(0));
+  // The fact that this line compiles would be enough, but we'll check the
+  // value anyway.
+  *field.mutable_data() = 2;
+  EXPECT_EQ(2, field.Get(0));
+}
+
+TEST(RepeatedField, Truncate) {
+  RepeatedField<int> field;
+
+  field.Add(12);
+  field.Add(34);
+  field.Add(56);
+  field.Add(78);
+  EXPECT_EQ(4, field.size());
+
+  field.Truncate(3);
+  EXPECT_EQ(3, field.size());
+
+  field.Add(90);
+  EXPECT_EQ(4, field.size());
+  EXPECT_EQ(90, field.Get(3));
+
+  // Truncations that don't change the size are allowed, but growing is not
+  // allowed.
+  field.Truncate(field.size());
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size");
+#endif
+}
+
+
+TEST(RepeatedField, ExtractSubrange) {
+  // Exhaustively test every subrange in arrays of all sizes from 0 through 9.
+  for (int sz = 0; sz < 10; ++sz) {
+    for (int num = 0; num <= sz; ++num) {
+      for (int start = 0; start < sz - num; ++start) {
+        // Create RepeatedField with sz elements having values 0 through sz-1.
+        RepeatedField<int32> field;
+        for (int i = 0; i < sz; ++i)
+          field.Add(i);
+        EXPECT_EQ(field.size(), sz);
+
+        // Create a catcher array and call ExtractSubrange.
+        int32 catcher[10];
+        for (int i = 0; i < 10; ++i)
+          catcher[i] = -1;
+        field.ExtractSubrange(start, num, catcher);
+
+        // Does the resulting array have the right size?
+        EXPECT_EQ(field.size(), sz - num);
+
+        // Were the removed elements extracted into the catcher array?
+        for (int i = 0; i < num; ++i)
+          EXPECT_EQ(catcher[i], start + i);
+        EXPECT_EQ(catcher[num], -1);
+
+        // Does the resulting array contain the right values?
+        for (int i = 0; i < start; ++i)
+          EXPECT_EQ(field.Get(i), i);
+        for (int i = start; i < field.size(); ++i)
+          EXPECT_EQ(field.Get(i), i + num);
+      }
+    }
+  }
+}
+
+TEST(RepeatedField, ClearThenReserveMore) {
+  // Test that Reserve properly destroys the old internal array when it's forced
+  // to allocate a new one, even when cleared-but-not-deleted objects are
+  // present. Use a 'string' and > 16 bytes length so that the elements are
+  // non-POD and allocate -- the leak checker will catch any skipped destructor
+  // calls here.
+  RepeatedField<string> field;
+  for (int i = 0; i < 32; i++) {
+    field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789"));
+  }
+  EXPECT_EQ(32, field.size());
+  field.Clear();
+  EXPECT_EQ(0, field.size());
+  EXPECT_EQ(32, field.Capacity());
+
+  field.Reserve(1024);
+  EXPECT_EQ(0, field.size());
+  EXPECT_EQ(1024, field.Capacity());
+  // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed
+  // strings.
+}
+
+// ===================================================================
+// RepeatedPtrField tests.  These pretty much just mirror the RepeatedField
+// tests above.
+
+TEST(RepeatedPtrField, Small) {
+  RepeatedPtrField<string> field;
+
+  EXPECT_TRUE(field.empty());
+  EXPECT_EQ(field.size(), 0);
+
+  field.Add()->assign("foo");
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 1);
+  EXPECT_EQ(field.Get(0), "foo");
+
+  field.Add()->assign("bar");
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 2);
+  EXPECT_EQ(field.Get(0), "foo");
+  EXPECT_EQ(field.Get(1), "bar");
+
+  field.Mutable(1)->assign("baz");
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 2);
+  EXPECT_EQ(field.Get(0), "foo");
+  EXPECT_EQ(field.Get(1), "baz");
+
+  field.RemoveLast();
+
+  EXPECT_FALSE(field.empty());
+  EXPECT_EQ(field.size(), 1);
+  EXPECT_EQ(field.Get(0), "foo");
+
+  field.Clear();
+
+  EXPECT_TRUE(field.empty());
+  EXPECT_EQ(field.size(), 0);
+}
+
+TEST(RepeatedPtrField, Large) {
+  RepeatedPtrField<string> field;
+
+  for (int i = 0; i < 16; i++) {
+    *field.Add() += 'a' + i;
+  }
+
+  EXPECT_EQ(field.size(), 16);
+
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field.Get(i).size(), 1);
+    EXPECT_EQ(field.Get(i)[0], 'a' + i);
+  }
+
+  int min_expected_usage = 16 * sizeof(string);
+  EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
+}
+
+TEST(RepeatedPtrField, SwapSmallSmall) {
+  RepeatedPtrField<string> field1;
+  RepeatedPtrField<string> field2;
+
+  EXPECT_TRUE(field1.empty());
+  EXPECT_EQ(field1.size(), 0);
+  EXPECT_TRUE(field2.empty());
+  EXPECT_EQ(field2.size(), 0);
+
+  field1.Add()->assign("foo");
+  field1.Add()->assign("bar");
+
+  EXPECT_FALSE(field1.empty());
+  EXPECT_EQ(field1.size(), 2);
+  EXPECT_EQ(field1.Get(0), "foo");
+  EXPECT_EQ(field1.Get(1), "bar");
+
+  EXPECT_TRUE(field2.empty());
+  EXPECT_EQ(field2.size(), 0);
+
+  field1.Swap(&field2);
+
+  EXPECT_TRUE(field1.empty());
+  EXPECT_EQ(field1.size(), 0);
+
+  EXPECT_EQ(field2.size(), 2);
+  EXPECT_EQ(field2.Get(0), "foo");
+  EXPECT_EQ(field2.Get(1), "bar");
+}
+
+TEST(RepeatedPtrField, SwapLargeSmall) {
+  RepeatedPtrField<string> field1;
+  RepeatedPtrField<string> field2;
+
+  field2.Add()->assign("foo");
+  field2.Add()->assign("bar");
+  for (int i = 0; i < 16; i++) {
+    *field1.Add() += 'a' + i;
+  }
+  field1.Swap(&field2);
+
+  EXPECT_EQ(field1.size(), 2);
+  EXPECT_EQ(field1.Get(0), "foo");
+  EXPECT_EQ(field1.Get(1), "bar");
+  EXPECT_EQ(field2.size(), 16);
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field2.Get(i).size(), 1);
+    EXPECT_EQ(field2.Get(i)[0], 'a' + i);
+  }
+}
+
+TEST(RepeatedPtrField, SwapLargeLarge) {
+  RepeatedPtrField<string> field1;
+  RepeatedPtrField<string> field2;
+
+  field1.Add()->assign("foo");
+  field1.Add()->assign("bar");
+  for (int i = 0; i < 16; i++) {
+    *field1.Add() += 'A' + i;
+    *field2.Add() += 'a' + i;
+  }
+  field2.Swap(&field1);
+
+  EXPECT_EQ(field1.size(), 16);
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(field1.Get(i).size(), 1);
+    EXPECT_EQ(field1.Get(i)[0], 'a' + i);
+  }
+  EXPECT_EQ(field2.size(), 18);
+  EXPECT_EQ(field2.Get(0), "foo");
+  EXPECT_EQ(field2.Get(1), "bar");
+  for (int i = 2; i < 18; i++) {
+    EXPECT_EQ(field2.Get(i).size(), 1);
+    EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2);
+  }
+}
+
+static int ReservedSpace(RepeatedPtrField<string>* field) {
+  const string* const* ptr = field->data();
+  do {
+    field->Add();
+  } while (field->data() == ptr);
+
+  return field->size() - 1;
+}
+
+TEST(RepeatedPtrField, ReserveMoreThanDouble) {
+  RepeatedPtrField<string> field;
+  field.Reserve(20);
+
+  EXPECT_EQ(20, ReservedSpace(&field));
+}
+
+TEST(RepeatedPtrField, ReserveLessThanDouble) {
+  RepeatedPtrField<string> field;
+  field.Reserve(20);
+  field.Reserve(30);
+
+  EXPECT_EQ(40, ReservedSpace(&field));
+}
+
+TEST(RepeatedPtrField, ReserveLessThanExisting) {
+  RepeatedPtrField<string> field;
+  field.Reserve(20);
+  const string* const* previous_ptr = field.data();
+  field.Reserve(10);
+
+  EXPECT_EQ(previous_ptr, field.data());
+  EXPECT_EQ(20, ReservedSpace(&field));
+}
+
+TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) {
+  // Check that a bug is fixed:  An earlier implementation of Reserve()
+  // failed to copy pointers to allocated-but-cleared objects, possibly
+  // leading to segfaults.
+  RepeatedPtrField<string> field;
+  string* first = field.Add();
+  field.RemoveLast();
+
+  field.Reserve(20);
+  EXPECT_EQ(first, field.Add());
+}
+
+// Clearing elements is tricky with RepeatedPtrFields since the memory for
+// the elements is retained and reused.
+TEST(RepeatedPtrField, ClearedElements) {
+  RepeatedPtrField<string> field;
+
+  string* original = field.Add();
+  *original = "foo";
+
+  EXPECT_EQ(field.ClearedCount(), 0);
+
+  field.RemoveLast();
+  EXPECT_TRUE(original->empty());
+  EXPECT_EQ(field.ClearedCount(), 1);
+
+  EXPECT_EQ(field.Add(), original);  // Should return same string for reuse.
+
+  EXPECT_EQ(field.ReleaseLast(), original);  // We take ownership.
+  EXPECT_EQ(field.ClearedCount(), 0);
+
+  EXPECT_NE(field.Add(), original);  // Should NOT return the same string.
+  EXPECT_EQ(field.ClearedCount(), 0);
+
+  field.AddAllocated(original);  // Give ownership back.
+  EXPECT_EQ(field.ClearedCount(), 0);
+  EXPECT_EQ(field.Mutable(1), original);
+
+  field.Clear();
+  EXPECT_EQ(field.ClearedCount(), 2);
+  EXPECT_EQ(field.ReleaseCleared(), original);  // Take ownership again.
+  EXPECT_EQ(field.ClearedCount(), 1);
+  EXPECT_NE(field.Add(), original);
+  EXPECT_EQ(field.ClearedCount(), 0);
+  EXPECT_NE(field.Add(), original);
+  EXPECT_EQ(field.ClearedCount(), 0);
+
+  field.AddCleared(original);  // Give ownership back, but as a cleared object.
+  EXPECT_EQ(field.ClearedCount(), 1);
+  EXPECT_EQ(field.Add(), original);
+  EXPECT_EQ(field.ClearedCount(), 0);
+}
+
+// Test all code paths in AddAllocated().
+TEST(RepeatedPtrField, AddAlocated) {
+  RepeatedPtrField<string> field;
+  while (field.size() < field.Capacity()) {
+    field.Add()->assign("filler");
+  }
+
+  int index = field.size();
+
+  // First branch:  Field is at capacity with no cleared objects.
+  string* foo = new string("foo");
+  field.AddAllocated(foo);
+  EXPECT_EQ(index + 1, field.size());
+  EXPECT_EQ(0, field.ClearedCount());
+  EXPECT_EQ(foo, &field.Get(index));
+
+  // Last branch:  Field is not at capacity and there are no cleared objects.
+  string* bar = new string("bar");
+  field.AddAllocated(bar);
+  ++index;
+  EXPECT_EQ(index + 1, field.size());
+  EXPECT_EQ(0, field.ClearedCount());
+  EXPECT_EQ(bar, &field.Get(index));
+
+  // Third branch:  Field is not at capacity and there are no cleared objects.
+  field.RemoveLast();
+  string* baz = new string("baz");
+  field.AddAllocated(baz);
+  EXPECT_EQ(index + 1, field.size());
+  EXPECT_EQ(1, field.ClearedCount());
+  EXPECT_EQ(baz, &field.Get(index));
+
+  // Second branch:  Field is at capacity but has some cleared objects.
+  while (field.size() < field.Capacity()) {
+    field.Add()->assign("filler2");
+  }
+  field.RemoveLast();
+  index = field.size();
+  string* qux = new string("qux");
+  field.AddAllocated(qux);
+  EXPECT_EQ(index + 1, field.size());
+  // We should have discarded the cleared object.
+  EXPECT_EQ(0, field.ClearedCount());
+  EXPECT_EQ(qux, &field.Get(index));
+}
+
+TEST(RepeatedPtrField, MergeFrom) {
+  RepeatedPtrField<string> source, destination;
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination.MergeFrom(source);
+
+  ASSERT_EQ(5, destination.size());
+  EXPECT_EQ("1", destination.Get(0));
+  EXPECT_EQ("2", destination.Get(1));
+  EXPECT_EQ("3", destination.Get(2));
+  EXPECT_EQ("4", destination.Get(3));
+  EXPECT_EQ("5", destination.Get(4));
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(RepeatedPtrField, MergeFromSelf) {
+  RepeatedPtrField<string> me;
+  me.Add()->assign("1");
+  EXPECT_DEATH(me.MergeFrom(me), "");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(RepeatedPtrField, CopyFrom) {
+  RepeatedPtrField<string> source, destination;
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, CopyFromSelf) {
+  RepeatedPtrField<string> me;
+  me.Add()->assign("1");
+  me.CopyFrom(me);
+  ASSERT_EQ(1, me.size());
+  EXPECT_EQ("1", me.Get(0));
+}
+
+TEST(RepeatedPtrField, Erase) {
+  RepeatedPtrField<string> me;
+  RepeatedPtrField<string>::iterator it = me.erase(me.begin(), me.end());
+  EXPECT_TRUE(me.begin() == it);
+  EXPECT_EQ(0, me.size());
+
+  *me.Add() = "1";
+  *me.Add() = "2";
+  *me.Add() = "3";
+  it = me.erase(me.begin(), me.end());
+  EXPECT_TRUE(me.begin() == it);
+  EXPECT_EQ(0, me.size());
+
+  *me.Add() = "4";
+  *me.Add() = "5";
+  *me.Add() = "6";
+  it = me.erase(me.begin() + 2, me.end());
+  EXPECT_TRUE(me.begin() + 2 == it);
+  EXPECT_EQ(2, me.size());
+  EXPECT_EQ("4", me.Get(0));
+  EXPECT_EQ("5", me.Get(1));
+
+  *me.Add() = "6";
+  *me.Add() = "7";
+  *me.Add() = "8";
+  it = me.erase(me.begin() + 1, me.begin() + 3);
+  EXPECT_TRUE(me.begin() + 1 == it);
+  EXPECT_EQ(3, me.size());
+  EXPECT_EQ("4", me.Get(0));
+  EXPECT_EQ("7", me.Get(1));
+  EXPECT_EQ("8", me.Get(2));
+}
+
+TEST(RepeatedPtrField, CopyConstruct) {
+  RepeatedPtrField<string> source;
+  source.Add()->assign("1");
+  source.Add()->assign("2");
+
+  RepeatedPtrField<string> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ("1", destination.Get(0));
+  EXPECT_EQ("2", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, IteratorConstruct_String) {
+  vector<string> values;
+  values.push_back("1");
+  values.push_back("2");
+
+  RepeatedPtrField<string> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0], field.Get(0));
+  EXPECT_EQ(values[1], field.Get(1));
+
+  RepeatedPtrField<string> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0], other.Get(0));
+  EXPECT_EQ(values[1], other.Get(1));
+}
+
+TEST(RepeatedPtrField, IteratorConstruct_Proto) {
+  typedef TestAllTypes::NestedMessage Nested;
+  vector<Nested> values;
+  values.push_back(Nested());
+  values.back().set_bb(1);
+  values.push_back(Nested());
+  values.back().set_bb(2);
+
+  RepeatedPtrField<Nested> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0].bb(), field.Get(0).bb());
+  EXPECT_EQ(values[1].bb(), field.Get(1).bb());
+
+  RepeatedPtrField<Nested> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0].bb(), other.Get(0).bb());
+  EXPECT_EQ(values[1].bb(), other.Get(1).bb());
+}
+
+TEST(RepeatedPtrField, CopyAssign) {
+  RepeatedPtrField<string> source, destination;
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, SelfAssign) {
+  // Verify that assignment to self does not destroy data.
+  RepeatedPtrField<string> source, *p;
+  p = &source;
+  source.Add()->assign("7");
+  source.Add()->assign("8");
+
+  *p = source;
+
+  ASSERT_EQ(2, source.size());
+  EXPECT_EQ("7", source.Get(0));
+  EXPECT_EQ("8", source.Get(1));
+}
+
+TEST(RepeatedPtrField, MutableDataIsMutable) {
+  RepeatedPtrField<string> field;
+  *field.Add() = "1";
+  EXPECT_EQ("1", field.Get(0));
+  // The fact that this line compiles would be enough, but we'll check the
+  // value anyway.
+  string** data = field.mutable_data();
+  **data = "2";
+  EXPECT_EQ("2", field.Get(0));
+}
+
+TEST(RepeatedPtrField, ExtractSubrange) {
+  // Exhaustively test every subrange in arrays of all sizes from 0 through 9
+  // with 0 through 3 cleared elements at the end.
+  for (int sz = 0; sz < 10; ++sz) {
+    for (int num = 0; num <= sz; ++num) {
+      for (int start = 0; start < sz - num; ++start) {
+        for (int extra = 0; extra < 4; ++extra) {
+          vector<string*> subject;
+
+          // Create an array with "sz" elements and "extra" cleared elements.
+          RepeatedPtrField<string> field;
+          for (int i = 0; i < sz + extra; ++i) {
+            subject.push_back(new string());
+            field.AddAllocated(subject[i]);
+          }
+          EXPECT_EQ(field.size(), sz + extra);
+          for (int i = 0; i < extra; ++i)
+            field.RemoveLast();
+          EXPECT_EQ(field.size(), sz);
+          EXPECT_EQ(field.ClearedCount(), extra);
+
+          // Create a catcher array and call ExtractSubrange.
+          string* catcher[10];
+          for (int i = 0; i < 10; ++i)
+            catcher[i] = NULL;
+          field.ExtractSubrange(start, num, catcher);
+
+          // Does the resulting array have the right size?
+          EXPECT_EQ(field.size(), sz - num);
+
+          // Were the removed elements extracted into the catcher array?
+          for (int i = 0; i < num; ++i)
+            EXPECT_EQ(catcher[i], subject[start + i]);
+          EXPECT_EQ(NULL, catcher[num]);
+
+          // Does the resulting array contain the right values?
+          for (int i = 0; i < start; ++i)
+            EXPECT_EQ(field.Mutable(i), subject[i]);
+          for (int i = start; i < field.size(); ++i)
+            EXPECT_EQ(field.Mutable(i), subject[i + num]);
+
+          // Reinstate the cleared elements.
+          EXPECT_EQ(field.ClearedCount(), extra);
+          for (int i = 0; i < extra; ++i)
+            field.Add();
+          EXPECT_EQ(field.ClearedCount(), 0);
+          EXPECT_EQ(field.size(), sz - num + extra);
+
+          // Make sure the extra elements are all there (in some order).
+          for (int i = sz; i < sz + extra; ++i) {
+            int count = 0;
+            for (int j = sz; j < sz + extra; ++j) {
+              if (field.Mutable(j - num) == subject[i])
+                count += 1;
+            }
+            EXPECT_EQ(count, 1);
+          }
+
+          // Release the caught elements.
+          for (int i = 0; i < num; ++i)
+            delete catcher[i];
+        }
+      }
+    }
+  }
+}
+
+TEST(RepeatedPtrField, DeleteSubrange) {
+  // DeleteSubrange is a trivial extension of ExtendSubrange.
+}
+
+// ===================================================================
+
+// Iterator tests stolen from net/proto/proto-array_unittest.
+class RepeatedFieldIteratorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    for (int i = 0; i < 3; ++i) {
+      proto_array_.Add(i);
+    }
+  }
+
+  RepeatedField<int> proto_array_;
+};
+
+TEST_F(RepeatedFieldIteratorTest, Convertible) {
+  RepeatedField<int>::iterator iter = proto_array_.begin();
+  RepeatedField<int>::const_iterator c_iter = iter;
+  RepeatedField<int>::value_type value = *c_iter;
+  EXPECT_EQ(0, value);
+}
+
+TEST_F(RepeatedFieldIteratorTest, MutableIteration) {
+  RepeatedField<int>::iterator iter = proto_array_.begin();
+  EXPECT_EQ(0, *iter);
+  ++iter;
+  EXPECT_EQ(1, *iter++);
+  EXPECT_EQ(2, *iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.end() == iter);
+
+  EXPECT_EQ(2, *(proto_array_.end() - 1));
+}
+
+TEST_F(RepeatedFieldIteratorTest, ConstIteration) {
+  const RepeatedField<int>& const_proto_array = proto_array_;
+  RepeatedField<int>::const_iterator iter = const_proto_array.begin();
+  EXPECT_EQ(0, *iter);
+  ++iter;
+  EXPECT_EQ(1, *iter++);
+  EXPECT_EQ(2, *iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.end() == iter);
+  EXPECT_EQ(2, *(proto_array_.end() - 1));
+}
+
+TEST_F(RepeatedFieldIteratorTest, Mutation) {
+  RepeatedField<int>::iterator iter = proto_array_.begin();
+  *iter = 7;
+  EXPECT_EQ(7, proto_array_.Get(0));
+}
+
+// -------------------------------------------------------------------
+
+class RepeatedPtrFieldIteratorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    proto_array_.Add()->assign("foo");
+    proto_array_.Add()->assign("bar");
+    proto_array_.Add()->assign("baz");
+  }
+
+  RepeatedPtrField<string> proto_array_;
+};
+
+TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
+  RepeatedPtrField<string>::iterator iter = proto_array_.begin();
+  RepeatedPtrField<string>::const_iterator c_iter = iter;
+  RepeatedPtrField<string>::value_type value = *c_iter;
+  EXPECT_EQ("foo", value);
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
+  RepeatedPtrField<string>::iterator iter = proto_array_.begin();
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.end() == iter);
+  EXPECT_EQ("baz", *(--proto_array_.end()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) {
+  const RepeatedPtrField<string>& const_proto_array = proto_array_;
+  RepeatedPtrField<string>::const_iterator iter = const_proto_array.begin();
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_TRUE(const_proto_array.end() == iter);
+  EXPECT_EQ("baz", *(--const_proto_array.end()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) {
+  RepeatedPtrField<string>::reverse_iterator iter = proto_array_.rbegin();
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.rend() == iter);
+  EXPECT_EQ("foo", *(--proto_array_.rend()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) {
+  const RepeatedPtrField<string>& const_proto_array = proto_array_;
+  RepeatedPtrField<string>::const_reverse_iterator iter
+      = const_proto_array.rbegin();
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_TRUE(const_proto_array.rend() == iter);
+  EXPECT_EQ("foo", *(--const_proto_array.rend()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
+  RepeatedPtrField<string>::iterator iter = proto_array_.begin();
+  RepeatedPtrField<string>::iterator iter2 = iter;
+  ++iter2;
+  ++iter2;
+  EXPECT_TRUE(iter + 2 == iter2);
+  EXPECT_TRUE(iter == iter2 - 2);
+  EXPECT_EQ("baz", iter[2]);
+  EXPECT_EQ("baz", *(iter + 2));
+  EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, Comparable) {
+  RepeatedPtrField<string>::const_iterator iter = proto_array_.begin();
+  RepeatedPtrField<string>::const_iterator iter2 = iter + 1;
+  EXPECT_TRUE(iter == iter);
+  EXPECT_TRUE(iter != iter2);
+  EXPECT_TRUE(iter < iter2);
+  EXPECT_TRUE(iter <= iter2);
+  EXPECT_TRUE(iter <= iter);
+  EXPECT_TRUE(iter2 > iter);
+  EXPECT_TRUE(iter2 >= iter);
+  EXPECT_TRUE(iter >= iter);
+}
+
+// Uninitialized iterator does not point to any of the RepeatedPtrField.
+TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) {
+  RepeatedPtrField<string>::iterator iter;
+  EXPECT_TRUE(iter != proto_array_.begin());
+  EXPECT_TRUE(iter != proto_array_.begin() + 1);
+  EXPECT_TRUE(iter != proto_array_.begin() + 2);
+  EXPECT_TRUE(iter != proto_array_.begin() + 3);
+  EXPECT_TRUE(iter != proto_array_.end());
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
+  proto_array_.Clear();
+  proto_array_.Add()->assign("a");
+  proto_array_.Add()->assign("c");
+  proto_array_.Add()->assign("d");
+  proto_array_.Add()->assign("n");
+  proto_array_.Add()->assign("p");
+  proto_array_.Add()->assign("x");
+  proto_array_.Add()->assign("y");
+
+  string v = "f";
+  RepeatedPtrField<string>::const_iterator it =
+      std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
+
+  EXPECT_EQ(*it, "n");
+  EXPECT_TRUE(it == proto_array_.begin() + 3);
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
+  RepeatedPtrField<string>::iterator iter = proto_array_.begin();
+  *iter = "qux";
+  EXPECT_EQ("qux", proto_array_.Get(0));
+}
+
+// -------------------------------------------------------------------
+
+class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    proto_array_.Add()->assign("foo");
+    proto_array_.Add()->assign("bar");
+    proto_array_.Add()->assign("baz");
+    const_proto_array_ = &proto_array_;
+  }
+
+  RepeatedPtrField<string> proto_array_;
+  const RepeatedPtrField<string>* const_proto_array_;
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
+  RepeatedPtrField<string>::pointer_iterator iter =
+      proto_array_.pointer_begin();
+  static_cast<void>(iter);
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  static_cast<void>(iter);
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
+  RepeatedPtrField<string>::pointer_iterator iter =
+      proto_array_.pointer_begin();
+  EXPECT_EQ("foo", **iter);
+  ++iter;
+  EXPECT_EQ("bar", **(iter++));
+  EXPECT_EQ("baz", **iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.pointer_end() == iter);
+  EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  EXPECT_EQ("foo", **iter);
+  ++iter;
+  EXPECT_EQ("bar", **(iter++));
+  EXPECT_EQ("baz", **iter);
+  ++iter;
+  EXPECT_TRUE(const_proto_array_->pointer_end() == iter);
+  EXPECT_EQ("baz", **(--const_proto_array_->pointer_end()));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
+  RepeatedPtrField<string>::pointer_iterator iter =
+      proto_array_.pointer_begin();
+  RepeatedPtrField<string>::pointer_iterator iter2 = iter;
+  ++iter2;
+  ++iter2;
+  EXPECT_TRUE(iter + 2 == iter2);
+  EXPECT_TRUE(iter == iter2 - 2);
+  EXPECT_EQ("baz", *iter[2]);
+  EXPECT_EQ("baz", **(iter + 2));
+  EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  RepeatedPtrField<string>::const_pointer_iterator iter2 = iter;
+  ++iter2;
+  ++iter2;
+  EXPECT_TRUE(iter + 2 == iter2);
+  EXPECT_TRUE(iter == iter2 - 2);
+  EXPECT_EQ("baz", *iter[2]);
+  EXPECT_EQ("baz", **(iter + 2));
+  EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin());
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
+  RepeatedPtrField<string>::pointer_iterator iter =
+      proto_array_.pointer_begin();
+  RepeatedPtrField<string>::pointer_iterator iter2 = iter + 1;
+  EXPECT_TRUE(iter == iter);
+  EXPECT_TRUE(iter != iter2);
+  EXPECT_TRUE(iter < iter2);
+  EXPECT_TRUE(iter <= iter2);
+  EXPECT_TRUE(iter <= iter);
+  EXPECT_TRUE(iter2 > iter);
+  EXPECT_TRUE(iter2 >= iter);
+  EXPECT_TRUE(iter >= iter);
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  RepeatedPtrField<string>::const_pointer_iterator iter2 = iter + 1;
+  EXPECT_TRUE(iter == iter);
+  EXPECT_TRUE(iter != iter2);
+  EXPECT_TRUE(iter < iter2);
+  EXPECT_TRUE(iter <= iter2);
+  EXPECT_TRUE(iter <= iter);
+  EXPECT_TRUE(iter2 > iter);
+  EXPECT_TRUE(iter2 >= iter);
+  EXPECT_TRUE(iter >= iter);
+}
+
+// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
+// Dereferencing an uninitialized iterator crashes the process.
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
+  RepeatedPtrField<string>::pointer_iterator iter;
+  EXPECT_TRUE(iter != proto_array_.pointer_begin());
+  EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
+  EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
+  EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
+  EXPECT_TRUE(iter != proto_array_.pointer_end());
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) {
+  RepeatedPtrField<string>::const_pointer_iterator iter;
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin());
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_end());
+}
+
+// This comparison functor is required by the tests for RepeatedPtrOverPtrs.
+// They operate on strings and need to compare strings as strings in
+// any stl algorithm, even though the iterator returns a pointer to a string
+// - i.e. *iter has type string*.
+struct StringLessThan {
+  bool operator()(const string* z, const string& y) {
+    return *z < y;
+  }
+  bool operator()(const string* z, const string* y) const { return *z < *y; }
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
+  proto_array_.Clear();
+  proto_array_.Add()->assign("a");
+  proto_array_.Add()->assign("c");
+  proto_array_.Add()->assign("d");
+  proto_array_.Add()->assign("n");
+  proto_array_.Add()->assign("p");
+  proto_array_.Add()->assign("x");
+  proto_array_.Add()->assign("y");
+
+  {
+    string v = "f";
+    RepeatedPtrField<string>::pointer_iterator it =
+        std::lower_bound(proto_array_.pointer_begin(),
+                         proto_array_.pointer_end(), &v, StringLessThan());
+
+    GOOGLE_CHECK(*it != NULL);
+
+    EXPECT_EQ(**it, "n");
+    EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+  }
+  {
+    string v = "f";
+    RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound(
+        const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
+        &v, StringLessThan());
+
+    GOOGLE_CHECK(*it != NULL);
+
+    EXPECT_EQ(**it, "n");
+    EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3);
+  }
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
+  RepeatedPtrField<string>::pointer_iterator iter =
+      proto_array_.pointer_begin();
+  **iter = "qux";
+  EXPECT_EQ("qux", proto_array_.Get(0));
+
+  EXPECT_EQ("bar", proto_array_.Get(1));
+  EXPECT_EQ("baz", proto_array_.Get(2));
+  ++iter;
+  delete *iter;
+  *iter = new string("a");
+  ++iter;
+  delete *iter;
+  *iter = new string("b");
+  EXPECT_EQ("a", proto_array_.Get(1));
+  EXPECT_EQ("b", proto_array_.Get(2));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
+  proto_array_.Add()->assign("c");
+  proto_array_.Add()->assign("d");
+  proto_array_.Add()->assign("n");
+  proto_array_.Add()->assign("p");
+  proto_array_.Add()->assign("a");
+  proto_array_.Add()->assign("y");
+  proto_array_.Add()->assign("x");
+  EXPECT_EQ("foo", proto_array_.Get(0));
+  EXPECT_EQ("n", proto_array_.Get(5));
+  EXPECT_EQ("x", proto_array_.Get(9));
+  std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+            StringLessThan());
+  EXPECT_EQ("a", proto_array_.Get(0));
+  EXPECT_EQ("baz", proto_array_.Get(2));
+  EXPECT_EQ("y", proto_array_.Get(9));
+}
+
+
+// -----------------------------------------------------------------------------
+// Unit-tests for the insert iterators
+// google::protobuf::RepeatedFieldBackInserter,
+// google::protobuf::AllocatedRepeatedPtrFieldBackInserter
+// Ported from util/gtl/proto-array-iterators_unittest.
+
+class RepeatedFieldInsertionIteratorsTest : public testing::Test {
+ protected:
+  std::list<double> halves;
+  std::list<int> fibonacci;
+  std::vector<string> words;
+  typedef TestAllTypes::NestedMessage Nested;
+  Nested nesteds[2];
+  std::vector<Nested*> nested_ptrs;
+  TestAllTypes protobuffer;
+
+  virtual void SetUp() {
+    fibonacci.push_back(1);
+    fibonacci.push_back(1);
+    fibonacci.push_back(2);
+    fibonacci.push_back(3);
+    fibonacci.push_back(5);
+    fibonacci.push_back(8);
+    std::copy(fibonacci.begin(), fibonacci.end(),
+              RepeatedFieldBackInserter(protobuffer.mutable_repeated_int32()));
+
+    halves.push_back(1.0);
+    halves.push_back(0.5);
+    halves.push_back(0.25);
+    halves.push_back(0.125);
+    halves.push_back(0.0625);
+    std::copy(halves.begin(), halves.end(),
+              RepeatedFieldBackInserter(protobuffer.mutable_repeated_double()));
+
+    words.push_back("Able");
+    words.push_back("was");
+    words.push_back("I");
+    words.push_back("ere");
+    words.push_back("I");
+    words.push_back("saw");
+    words.push_back("Elba");
+    std::copy(words.begin(), words.end(),
+              RepeatedFieldBackInserter(protobuffer.mutable_repeated_string()));
+
+    nesteds[0].set_bb(17);
+    nesteds[1].set_bb(4711);
+    std::copy(&nesteds[0], &nesteds[2],
+              RepeatedFieldBackInserter(
+                  protobuffer.mutable_repeated_nested_message()));
+
+    nested_ptrs.push_back(new Nested);
+    nested_ptrs.back()->set_bb(170);
+    nested_ptrs.push_back(new Nested);
+    nested_ptrs.back()->set_bb(47110);
+    std::copy(nested_ptrs.begin(), nested_ptrs.end(),
+              RepeatedFieldBackInserter(
+                  protobuffer.mutable_repeated_nested_message()));
+  }
+
+  virtual void TearDown() {
+    STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end());
+  }
+};
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) {
+  EXPECT_TRUE(std::equal(fibonacci.begin(),
+                         fibonacci.end(),
+                         protobuffer.repeated_int32().begin()));
+  EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(),
+                         protobuffer.repeated_int32().end(),
+                         fibonacci.begin()));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) {
+  EXPECT_TRUE(std::equal(halves.begin(),
+                         halves.end(),
+                         protobuffer.repeated_double().begin()));
+  EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(),
+                         protobuffer.repeated_double().end(),
+                         halves.begin()));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
+  ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
+  for (int i = 0; i < words.size(); ++i)
+    EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) {
+  words.clear();
+  words.push_back("sing");
+  words.push_back("a");
+  words.push_back("song");
+  words.push_back("of");
+  words.push_back("six");
+  words.push_back("pence");
+  protobuffer.mutable_repeated_string()->Clear();
+  std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter(
+      protobuffer.mutable_repeated_string()));
+  ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
+  for (int i = 0; i < words.size(); ++i)
+    EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
+  ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4);
+  EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17);
+  EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711);
+  EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170);
+  EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110);
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       AllocatedRepeatedPtrFieldWithStringIntData) {
+  vector<Nested*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    Nested* new_data = new Nested;
+    new_data->set_bb(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_nested_message();
+    new_data->set_bb(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(),
+            AllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_nested_message()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       AllocatedRepeatedPtrFieldWithString) {
+  vector<string*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    string* new_data = new string;
+    *new_data = "name-" + SimpleItoa(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_string();
+    *new_data = "name-" + SimpleItoa(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter(
+                                          testproto.mutable_repeated_string()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
+  vector<Nested*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    Nested* new_data = new Nested;
+    new_data->set_bb(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_nested_message();
+    new_data->set_bb(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(),
+            UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_nested_message()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
+  vector<string*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    string* new_data = new string;
+    *new_data = "name-" + SimpleItoa(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_string();
+    *new_data = "name-" + SimpleItoa(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(),
+            UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_string()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+}  // namespace
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/service.cc b/src/third_party/protobuf-3/src/google/protobuf/service.cc
new file mode 100644
index 0000000..ffa919d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/service.cc
@@ -0,0 +1,46 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/service.h>
+
+namespace google {
+namespace protobuf {
+
+Service::~Service() {}
+RpcChannel::~RpcChannel() {}
+RpcController::~RpcController() {}
+
+}  // namespace protobuf
+
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/service.h b/src/third_party/protobuf-3/src/google/protobuf/service.h
new file mode 100644
index 0000000..ad6f968
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/service.h
@@ -0,0 +1,292 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// DEPRECATED:  This module declares the abstract interfaces underlying proto2
+// RPC services.  These are intented to be independent of any particular RPC
+// implementation, so that proto2 services can be used on top of a variety
+// of implementations.  Starting with version 2.3.0, RPC implementations should
+// not try to build on these, but should instead provide code generator plugins
+// which generate code specific to the particular RPC implementation.  This way
+// the generated code can be more appropriate for the implementation in use
+// and can avoid unnecessary layers of indirection.
+//
+//
+// When you use the protocol compiler to compile a service definition, it
+// generates two classes:  An abstract interface for the service (with
+// methods matching the service definition) and a "stub" implementation.
+// A stub is just a type-safe wrapper around an RpcChannel which emulates a
+// local implementation of the service.
+//
+// For example, the service definition:
+//   service MyService {
+//     rpc Foo(MyRequest) returns(MyResponse);
+//   }
+// will generate abstract interface "MyService" and class "MyService::Stub".
+// You could implement a MyService as follows:
+//   class MyServiceImpl : public MyService {
+//    public:
+//     MyServiceImpl() {}
+//     ~MyServiceImpl() {}
+//
+//     // implements MyService ---------------------------------------
+//
+//     void Foo(google::protobuf::RpcController* controller,
+//              const MyRequest* request,
+//              MyResponse* response,
+//              Closure* done) {
+//       // ... read request and fill in response ...
+//       done->Run();
+//     }
+//   };
+// You would then register an instance of MyServiceImpl with your RPC server
+// implementation.  (How to do that depends on the implementation.)
+//
+// To call a remote MyServiceImpl, first you need an RpcChannel connected to it.
+// How to construct a channel depends, again, on your RPC implementation.
+// Here we use a hypothetical "MyRpcChannel" as an example:
+//   MyRpcChannel channel("rpc:hostname:1234/myservice");
+//   MyRpcController controller;
+//   MyServiceImpl::Stub stub(&channel);
+//   FooRequest request;
+//   FooResponse response;
+//
+//   // ... fill in request ...
+//
+//   stub.Foo(&controller, request, &response, NewCallback(HandleResponse));
+//
+// On Thread-Safety:
+//
+// Different RPC implementations may make different guarantees about what
+// threads they may run callbacks on, and what threads the application is
+// allowed to use to call the RPC system.  Portable software should be ready
+// for callbacks to be called on any thread, but should not try to call the
+// RPC system from any thread except for the ones on which it received the
+// callbacks.  Realistically, though, simple software will probably want to
+// use a single-threaded RPC system while high-end software will want to
+// use multiple threads.  RPC implementations should provide multiple
+// choices.
+
+#ifndef GOOGLE_PROTOBUF_SERVICE_H__
+#define GOOGLE_PROTOBUF_SERVICE_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/callback.h>
+
+namespace google {
+namespace protobuf {
+
+// Defined in this file.
+class Service;
+class RpcController;
+class RpcChannel;
+
+// Defined in other files.
+class Descriptor;            // descriptor.h
+class ServiceDescriptor;     // descriptor.h
+class MethodDescriptor;      // descriptor.h
+class Message;               // message.h
+
+// Abstract base interface for protocol-buffer-based RPC services.  Services
+// themselves are abstract interfaces (implemented either by servers or as
+// stubs), but they subclass this base interface.  The methods of this
+// interface can be used to call the methods of the Service without knowing
+// its exact type at compile time (analogous to Reflection).
+class LIBPROTOBUF_EXPORT Service {
+ public:
+  inline Service() {}
+  virtual ~Service();
+
+  // When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second
+  // parameter to the constructor to tell it to delete its RpcChannel when
+  // destroyed.
+  enum ChannelOwnership {
+    STUB_OWNS_CHANNEL,
+    STUB_DOESNT_OWN_CHANNEL
+  };
+
+  // Get the ServiceDescriptor describing this service and its methods.
+  virtual const ServiceDescriptor* GetDescriptor() = 0;
+
+  // Call a method of the service specified by MethodDescriptor.  This is
+  // normally implemented as a simple switch() that calls the standard
+  // definitions of the service's methods.
+  //
+  // Preconditions:
+  // * method->service() == GetDescriptor()
+  // * request and response are of the exact same classes as the objects
+  //   returned by GetRequestPrototype(method) and
+  //   GetResponsePrototype(method).
+  // * After the call has started, the request must not be modified and the
+  //   response must not be accessed at all until "done" is called.
+  // * "controller" is of the correct type for the RPC implementation being
+  //   used by this Service.  For stubs, the "correct type" depends on the
+  //   RpcChannel which the stub is using.  Server-side Service
+  //   implementations are expected to accept whatever type of RpcController
+  //   the server-side RPC implementation uses.
+  //
+  // Postconditions:
+  // * "done" will be called when the method is complete.  This may be
+  //   before CallMethod() returns or it may be at some point in the future.
+  // * If the RPC succeeded, "response" contains the response returned by
+  //   the server.
+  // * If the RPC failed, "response"'s contents are undefined.  The
+  //   RpcController can be queried to determine if an error occurred and
+  //   possibly to get more information about the error.
+  virtual void CallMethod(const MethodDescriptor* method,
+                          RpcController* controller,
+                          const Message* request,
+                          Message* response,
+                          Closure* done) = 0;
+
+  // CallMethod() requires that the request and response passed in are of a
+  // particular subclass of Message.  GetRequestPrototype() and
+  // GetResponsePrototype() get the default instances of these required types.
+  // You can then call Message::New() on these instances to construct mutable
+  // objects which you can then pass to CallMethod().
+  //
+  // Example:
+  //   const MethodDescriptor* method =
+  //     service->GetDescriptor()->FindMethodByName("Foo");
+  //   Message* request  = stub->GetRequestPrototype (method)->New();
+  //   Message* response = stub->GetResponsePrototype(method)->New();
+  //   request->ParseFromString(input);
+  //   service->CallMethod(method, *request, response, callback);
+  virtual const Message& GetRequestPrototype(
+    const MethodDescriptor* method) const = 0;
+  virtual const Message& GetResponsePrototype(
+    const MethodDescriptor* method) const = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service);
+};
+
+// An RpcController mediates a single method call.  The primary purpose of
+// the controller is to provide a way to manipulate settings specific to the
+// RPC implementation and to find out about RPC-level errors.
+//
+// The methods provided by the RpcController interface are intended to be a
+// "least common denominator" set of features which we expect all
+// implementations to support.  Specific implementations may provide more
+// advanced features (e.g. deadline propagation).
+class LIBPROTOBUF_EXPORT RpcController {
+ public:
+  inline RpcController() {}
+  virtual ~RpcController();
+
+  // Client-side methods ---------------------------------------------
+  // These calls may be made from the client side only.  Their results
+  // are undefined on the server side (may crash).
+
+  // Resets the RpcController to its initial state so that it may be reused in
+  // a new call.  Must not be called while an RPC is in progress.
+  virtual void Reset() = 0;
+
+  // After a call has finished, returns true if the call failed.  The possible
+  // reasons for failure depend on the RPC implementation.  Failed() must not
+  // be called before a call has finished.  If Failed() returns true, the
+  // contents of the response message are undefined.
+  virtual bool Failed() const = 0;
+
+  // If Failed() is true, returns a human-readable description of the error.
+  virtual string ErrorText() const = 0;
+
+  // Advises the RPC system that the caller desires that the RPC call be
+  // canceled.  The RPC system may cancel it immediately, may wait awhile and
+  // then cancel it, or may not even cancel the call at all.  If the call is
+  // canceled, the "done" callback will still be called and the RpcController
+  // will indicate that the call failed at that time.
+  virtual void StartCancel() = 0;
+
+  // Server-side methods ---------------------------------------------
+  // These calls may be made from the server side only.  Their results
+  // are undefined on the client side (may crash).
+
+  // Causes Failed() to return true on the client side.  "reason" will be
+  // incorporated into the message returned by ErrorText().  If you find
+  // you need to return machine-readable information about failures, you
+  // should incorporate it into your response protocol buffer and should
+  // NOT call SetFailed().
+  virtual void SetFailed(const string& reason) = 0;
+
+  // If true, indicates that the client canceled the RPC, so the server may
+  // as well give up on replying to it.  The server should still call the
+  // final "done" callback.
+  virtual bool IsCanceled() const = 0;
+
+  // Asks that the given callback be called when the RPC is canceled.  The
+  // callback will always be called exactly once.  If the RPC completes without
+  // being canceled, the callback will be called after completion.  If the RPC
+  // has already been canceled when NotifyOnCancel() is called, the callback
+  // will be called immediately.
+  //
+  // NotifyOnCancel() must be called no more than once per request.
+  virtual void NotifyOnCancel(Closure* callback) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController);
+};
+
+// Abstract interface for an RPC channel.  An RpcChannel represents a
+// communication line to a Service which can be used to call that Service's
+// methods.  The Service may be running on another machine.  Normally, you
+// should not call an RpcChannel directly, but instead construct a stub Service
+// wrapping it.  Example:
+//   RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234");
+//   MyService* service = new MyService::Stub(channel);
+//   service->MyMethod(request, &response, callback);
+class LIBPROTOBUF_EXPORT RpcChannel {
+ public:
+  inline RpcChannel() {}
+  virtual ~RpcChannel();
+
+  // Call the given method of the remote service.  The signature of this
+  // procedure looks the same as Service::CallMethod(), but the requirements
+  // are less strict in one important way:  the request and response objects
+  // need not be of any specific class as long as their descriptors are
+  // method->input_type() and method->output_type().
+  virtual void CallMethod(const MethodDescriptor* method,
+                          RpcController* controller,
+                          const Message* request,
+                          Message* response,
+                          Closure* done) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_SERVICE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.cc
new file mode 100644
index 0000000..c67cd10
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.cc
@@ -0,0 +1,397 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/source_context.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* SourceContext_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceContext_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/source_context.proto");
+  GOOGLE_CHECK(file != NULL);
+  SourceContext_descriptor_ = file->message_type(0);
+  static const int SourceContext_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, file_name_),
+  };
+  SourceContext_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      SourceContext_descriptor_,
+      SourceContext::default_instance_,
+      SourceContext_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(SourceContext),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      SourceContext_descriptor_, &SourceContext::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+  delete SourceContext::default_instance_;
+  delete SourceContext_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n$google/protobuf/source_context.proto\022\017"
+    "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile"
+    "_name\030\001 \001(\tBU\n\023com.google.protobufB\022Sour"
+    "ceContextProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Proto"
+    "buf.WellKnownTypesb\006proto3", 186);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/source_context.proto", &protobuf_RegisterTypes);
+  SourceContext::default_instance_ = new SourceContext();
+  SourceContext::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fsource_5fcontext_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SourceContext::kFileNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SourceContext::SourceContext()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.SourceContext)
+}
+
+void SourceContext::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+SourceContext::SourceContext(const SourceContext& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext)
+}
+
+void SourceContext::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+SourceContext::~SourceContext() {
+  // @@protoc_insertion_point(destructor:google.protobuf.SourceContext)
+  SharedDtor();
+}
+
+void SourceContext::SharedDtor() {
+  file_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void SourceContext::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceContext::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceContext_descriptor_;
+}
+
+const SourceContext& SourceContext::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  return *default_instance_;
+}
+
+SourceContext* SourceContext::default_instance_ = NULL;
+
+SourceContext* SourceContext::New(::google::protobuf::Arena* arena) const {
+  SourceContext* n = new SourceContext;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void SourceContext::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
+  file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool SourceContext::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.SourceContext)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string file_name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_file_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->file_name().data(), this->file_name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.SourceContext.file_name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.SourceContext)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.SourceContext)
+  return false;
+#undef DO_
+}
+
+void SourceContext::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.SourceContext)
+  // optional string file_name = 1;
+  if (this->file_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->file_name().data(), this->file_name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.SourceContext.file_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->file_name(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.SourceContext)
+}
+
+::google::protobuf::uint8* SourceContext::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
+  // optional string file_name = 1;
+  if (this->file_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->file_name().data(), this->file_name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.SourceContext.file_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->file_name(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext)
+  return target;
+}
+
+int SourceContext::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext)
+  int total_size = 0;
+
+  // optional string file_name = 1;
+  if (this->file_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->file_name());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceContext* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext)
+    MergeFrom(*source);
+  }
+}
+
+void SourceContext::MergeFrom(const SourceContext& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.file_name().size() > 0) {
+
+    file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_);
+  }
+}
+
+void SourceContext::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceContext::CopyFrom(const SourceContext& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceContext)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceContext::IsInitialized() const {
+
+  return true;
+}
+
+void SourceContext::Swap(SourceContext* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SourceContext::InternalSwap(SourceContext* other) {
+  file_name_.Swap(&other->file_name_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata SourceContext::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceContext_descriptor_;
+  metadata.reflection = SourceContext_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceContext
+
+// optional string file_name = 1;
+void SourceContext::clear_file_name() {
+  file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& SourceContext::file_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
+  return file_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceContext::set_file_name(const ::std::string& value) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
+}
+ void SourceContext::set_file_name(const char* value) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
+}
+ void SourceContext::set_file_name(const char* value, size_t size) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
+}
+ ::std::string* SourceContext::mutable_file_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
+  return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceContext::release_file_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
+  
+  return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceContext::set_allocated_file_name(::std::string* file_name) {
+  if (file_name != NULL) {
+    
+  } else {
+    
+  }
+  file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.h b/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.h
new file mode 100644
index 0000000..ccfd365
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/source_context.pb.h
@@ -0,0 +1,186 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto();
+
+class SourceContext;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT SourceContext : public ::google::protobuf::Message {
+ public:
+  SourceContext();
+  virtual ~SourceContext();
+
+  SourceContext(const SourceContext& from);
+
+  inline SourceContext& operator=(const SourceContext& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceContext& default_instance();
+
+  void Swap(SourceContext* other);
+
+  // implements Message ----------------------------------------------
+
+  inline SourceContext* New() const { return New(NULL); }
+
+  SourceContext* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceContext& from);
+  void MergeFrom(const SourceContext& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(SourceContext* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string file_name = 1;
+  void clear_file_name();
+  static const int kFileNameFieldNumber = 1;
+  const ::std::string& file_name() const;
+  void set_file_name(const ::std::string& value);
+  void set_file_name(const char* value);
+  void set_file_name(const char* value, size_t size);
+  ::std::string* mutable_file_name();
+  ::std::string* release_file_name();
+  void set_allocated_file_name(::std::string* file_name);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceContext)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr file_name_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto();
+
+  void InitAsDefaultInstance();
+  static SourceContext* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceContext
+
+// optional string file_name = 1;
+inline void SourceContext::clear_file_name() {
+  file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SourceContext::file_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
+  return file_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceContext::set_file_name(const ::std::string& value) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
+}
+inline void SourceContext::set_file_name(const char* value) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
+}
+inline void SourceContext::set_file_name(const char* value, size_t size) {
+  
+  file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
+}
+inline ::std::string* SourceContext::mutable_file_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
+  return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SourceContext::release_file_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
+  
+  return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceContext::set_allocated_file_name(::std::string* file_name) {
+  if (file_name != NULL) {
+    
+  } else {
+    
+  }
+  file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/source_context.proto b/src/third_party/protobuf-3/src/google/protobuf/source_context.proto
new file mode 100644
index 0000000..d76252c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/source_context.proto
@@ -0,0 +1,48 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "SourceContextProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// `SourceContext` represents information about the source of a
+// protobuf element, like the file in which it is defined.
+message SourceContext {
+  // The path-qualified name of the .proto file that contained the associated
+  // protobuf element.  For example: `"google/protobuf/source.proto"`.
+  string file_name = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/struct.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/struct.pb.cc
new file mode 100644
index 0000000..11ccabb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/struct.pb.cc
@@ -0,0 +1,1500 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/struct.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Struct_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Struct_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Struct_FieldsEntry_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Value_reflection_ = NULL;
+struct ValueOneofInstance {
+  int null_value_;
+  double number_value_;
+  ::google::protobuf::internal::ArenaStringPtr string_value_;
+  bool bool_value_;
+  const ::google::protobuf::Struct* struct_value_;
+  const ::google::protobuf::ListValue* list_value_;
+}* Value_default_oneof_instance_ = NULL;
+const ::google::protobuf::Descriptor* ListValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  ListValue_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* NullValue_descriptor_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/struct.proto");
+  GOOGLE_CHECK(file != NULL);
+  Struct_descriptor_ = file->message_type(0);
+  static const int Struct_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, fields_),
+  };
+  Struct_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Struct_descriptor_,
+      Struct::default_instance_,
+      Struct_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Struct),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _is_default_instance_));
+  Struct_FieldsEntry_descriptor_ = Struct_descriptor_->nested_type(0);
+  Value_descriptor_ = file->message_type(1);
+  static const int Value_offsets_[7] = {
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, null_value_),
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, number_value_),
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, string_value_),
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, bool_value_),
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, struct_value_),
+    PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, list_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, kind_),
+  };
+  Value_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Value_descriptor_,
+      Value::default_instance_,
+      Value_offsets_,
+      -1,
+      -1,
+      -1,
+      Value_default_oneof_instance_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _oneof_case_[0]),
+      sizeof(Value),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _is_default_instance_));
+  ListValue_descriptor_ = file->message_type(2);
+  static const int ListValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, values_),
+  };
+  ListValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      ListValue_descriptor_,
+      ListValue::default_instance_,
+      ListValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(ListValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _is_default_instance_));
+  NullValue_descriptor_ = file->enum_type(0);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Struct_descriptor_, &Struct::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+        Struct_FieldsEntry_descriptor_,
+        ::google::protobuf::internal::MapEntry<
+            ::std::string,
+            ::google::protobuf::Value,
+            ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+            ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+            0>::CreateDefaultInstance(
+                Struct_FieldsEntry_descriptor_));
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Value_descriptor_, &Value::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      ListValue_descriptor_, &ListValue::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto() {
+  delete Struct::default_instance_;
+  delete Struct_reflection_;
+  delete Value::default_instance_;
+  delete Value_default_oneof_instance_;
+  delete Value_reflection_;
+  delete ListValue::default_instance_;
+  delete ListValue_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\034google/protobuf/struct.proto\022\017google.p"
+    "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo"
+    "gle.protobuf.Struct.FieldsEntry\032E\n\013Field"
+    "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo"
+    "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull"
+    "_value\030\001 \001(\0162\032.google.protobuf.NullValue"
+    "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val"
+    "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru"
+    "ct_value\030\005 \001(\0132\027.google.protobuf.StructH"
+    "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf."
+    "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu"
+    "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull"
+    "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro"
+    "tobufB\013StructProtoP\001Z1github.com/golang/"
+    "protobuf/ptypes/struct;structpb\240\001\001\242\002\003GPB"
+    "\252\002\036Google.Protobuf.WellKnownTypesb\006proto"
+    "3", 641);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/struct.proto", &protobuf_RegisterTypes);
+  Struct::default_instance_ = new Struct();
+  Value::default_instance_ = new Value();
+  Value_default_oneof_instance_ = new ValueOneofInstance();
+  ListValue::default_instance_ = new ListValue();
+  Struct::default_instance_->InitAsDefaultInstance();
+  Value::default_instance_->InitAsDefaultInstance();
+  ListValue::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fstruct_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fstruct_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fstruct_2eproto_;
+const ::google::protobuf::EnumDescriptor* NullValue_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return NullValue_descriptor_;
+}
+bool NullValue_IsValid(int value) {
+  switch(value) {
+    case 0:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Struct::kFieldsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Struct::Struct()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Struct)
+}
+
+void Struct::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Struct::Struct(const Struct& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct)
+}
+
+void Struct::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  fields_.SetAssignDescriptorCallback(
+      protobuf_AssignDescriptorsOnce);
+  fields_.SetEntryDescriptor(
+      &::google::protobuf::Struct_FieldsEntry_descriptor_);
+}
+
+Struct::~Struct() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Struct)
+  SharedDtor();
+}
+
+void Struct::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void Struct::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Struct::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Struct_descriptor_;
+}
+
+const Struct& Struct::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  return *default_instance_;
+}
+
+Struct* Struct::default_instance_ = NULL;
+
+Struct* Struct::New(::google::protobuf::Arena* arena) const {
+  Struct* n = new Struct;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Struct::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
+  fields_.Clear();
+}
+
+bool Struct::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Struct)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // map<string, .google.protobuf.Value> fields = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_fields:
+          ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry(fields_.NewEntry());
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, entry.get()));
+          (*mutable_fields())[entry->key()].Swap(entry->mutable_value());
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            entry->key().data(), entry->key().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Struct.FieldsEntry.key"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_loop_fields;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Struct)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Struct)
+  return false;
+#undef DO_
+}
+
+void Struct::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Struct)
+  // map<string, .google.protobuf.Value> fields = 1;
+  {
+    ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+    for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+        it = this->fields().begin();
+        it != this->fields().end(); ++it) {
+      entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+      ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+          1, *entry, output);
+      ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+        it->first.data(), it->first.length(),
+        ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+        "google.protobuf.Struct.FieldsEntry.key");
+    }
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Struct)
+}
+
+::google::protobuf::uint8* Struct::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
+  // map<string, .google.protobuf.Value> fields = 1;
+  {
+    ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+    for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+        it = this->fields().begin();
+        it != this->fields().end(); ++it) {
+      entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+      target = ::google::protobuf::internal::WireFormatLite::
+          WriteMessageNoVirtualToArray(
+              1, *entry, target);
+      ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+        it->first.data(), it->first.length(),
+        ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+        "google.protobuf.Struct.FieldsEntry.key");
+    }
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct)
+  return target;
+}
+
+int Struct::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct)
+  int total_size = 0;
+
+  // map<string, .google.protobuf.Value> fields = 1;
+  total_size += 1 * this->fields_size();
+  {
+    ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+    for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+        it = this->fields().begin();
+        it != this->fields().end(); ++it) {
+      entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+      total_size += ::google::protobuf::internal::WireFormatLite::
+          MessageSizeNoVirtual(*entry);
+    }
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Struct::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Struct* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct)
+    MergeFrom(*source);
+  }
+}
+
+void Struct::MergeFrom(const Struct& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  fields_.MergeFrom(from.fields_);
+}
+
+void Struct::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Struct::CopyFrom(const Struct& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Struct)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Struct::IsInitialized() const {
+
+  return true;
+}
+
+void Struct::Swap(Struct* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Struct::InternalSwap(Struct* other) {
+  fields_.Swap(&other->fields_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Struct::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Struct_descriptor_;
+  metadata.reflection = Struct_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Struct
+
+// map<string, .google.protobuf.Value> fields = 1;
+int Struct::fields_size() const {
+  return fields_.size();
+}
+void Struct::clear_fields() {
+  fields_.Clear();
+}
+ const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+Struct::fields() const {
+  // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields)
+  return fields_.GetMap();
+}
+ ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+Struct::mutable_fields() {
+  // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields)
+  return fields_.MutableMap();
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Value::kNullValueFieldNumber;
+const int Value::kNumberValueFieldNumber;
+const int Value::kStringValueFieldNumber;
+const int Value::kBoolValueFieldNumber;
+const int Value::kStructValueFieldNumber;
+const int Value::kListValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Value::Value()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Value)
+}
+
+void Value::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+  Value_default_oneof_instance_->null_value_ = 0;
+  Value_default_oneof_instance_->number_value_ = 0;
+  Value_default_oneof_instance_->string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  Value_default_oneof_instance_->bool_value_ = false;
+  Value_default_oneof_instance_->struct_value_ = const_cast< ::google::protobuf::Struct*>(&::google::protobuf::Struct::default_instance());
+  Value_default_oneof_instance_->list_value_ = const_cast< ::google::protobuf::ListValue*>(&::google::protobuf::ListValue::default_instance());
+}
+
+Value::Value(const Value& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Value)
+}
+
+void Value::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  clear_has_kind();
+}
+
+Value::~Value() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Value)
+  SharedDtor();
+}
+
+void Value::SharedDtor() {
+  if (has_kind()) {
+    clear_kind();
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void Value::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Value::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Value_descriptor_;
+}
+
+const Value& Value::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  return *default_instance_;
+}
+
+Value* Value::default_instance_ = NULL;
+
+Value* Value::New(::google::protobuf::Arena* arena) const {
+  Value* n = new Value;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Value::clear_kind() {
+// @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value)
+  switch(kind_case()) {
+    case kNullValue: {
+      // No need to clear
+      break;
+    }
+    case kNumberValue: {
+      // No need to clear
+      break;
+    }
+    case kStringValue: {
+      kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+      break;
+    }
+    case kBoolValue: {
+      // No need to clear
+      break;
+    }
+    case kStructValue: {
+      delete kind_.struct_value_;
+      break;
+    }
+    case kListValue: {
+      delete kind_.list_value_;
+      break;
+    }
+    case KIND_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = KIND_NOT_SET;
+}
+
+
+void Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Value)
+  clear_kind();
+}
+
+bool Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Value)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional .google.protobuf.NullValue null_value = 1;
+      case 1: {
+        if (tag == 8) {
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_null_value(static_cast< ::google::protobuf::NullValue >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(17)) goto parse_number_value;
+        break;
+      }
+
+      // optional double number_value = 2;
+      case 2: {
+        if (tag == 17) {
+         parse_number_value:
+          clear_kind();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                 input, &kind_.number_value_)));
+          set_has_number_value();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_string_value;
+        break;
+      }
+
+      // optional string string_value = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_string_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_string_value()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->string_value().data(), this->string_value().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Value.string_value"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_bool_value;
+        break;
+      }
+
+      // optional bool bool_value = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_bool_value:
+          clear_kind();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &kind_.bool_value_)));
+          set_has_bool_value();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(42)) goto parse_struct_value;
+        break;
+      }
+
+      // optional .google.protobuf.Struct struct_value = 5;
+      case 5: {
+        if (tag == 42) {
+         parse_struct_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_struct_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_list_value;
+        break;
+      }
+
+      // optional .google.protobuf.ListValue list_value = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_list_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_list_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Value)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Value)
+  return false;
+#undef DO_
+}
+
+void Value::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Value)
+  // optional .google.protobuf.NullValue null_value = 1;
+  if (has_null_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->null_value(), output);
+  }
+
+  // optional double number_value = 2;
+  if (has_number_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->number_value(), output);
+  }
+
+  // optional string string_value = 3;
+  if (has_string_value()) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->string_value().data(), this->string_value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Value.string_value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->string_value(), output);
+  }
+
+  // optional bool bool_value = 4;
+  if (has_bool_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->bool_value(), output);
+  }
+
+  // optional .google.protobuf.Struct struct_value = 5;
+  if (has_struct_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      5, *kind_.struct_value_, output);
+  }
+
+  // optional .google.protobuf.ListValue list_value = 6;
+  if (has_list_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6, *kind_.list_value_, output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Value)
+}
+
+::google::protobuf::uint8* Value::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value)
+  // optional .google.protobuf.NullValue null_value = 1;
+  if (has_null_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->null_value(), target);
+  }
+
+  // optional double number_value = 2;
+  if (has_number_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->number_value(), target);
+  }
+
+  // optional string string_value = 3;
+  if (has_string_value()) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->string_value().data(), this->string_value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Value.string_value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->string_value(), target);
+  }
+
+  // optional bool bool_value = 4;
+  if (has_bool_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(4, this->bool_value(), target);
+  }
+
+  // optional .google.protobuf.Struct struct_value = 5;
+  if (has_struct_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, *kind_.struct_value_, target);
+  }
+
+  // optional .google.protobuf.ListValue list_value = 6;
+  if (has_list_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        6, *kind_.list_value_, target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value)
+  return target;
+}
+
+int Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value)
+  int total_size = 0;
+
+  switch (kind_case()) {
+    // optional .google.protobuf.NullValue null_value = 1;
+    case kNullValue: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->null_value());
+      break;
+    }
+    // optional double number_value = 2;
+    case kNumberValue: {
+      total_size += 1 + 8;
+      break;
+    }
+    // optional string string_value = 3;
+    case kStringValue: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->string_value());
+      break;
+    }
+    // optional bool bool_value = 4;
+    case kBoolValue: {
+      total_size += 1 + 1;
+      break;
+    }
+    // optional .google.protobuf.Struct struct_value = 5;
+    case kStructValue: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *kind_.struct_value_);
+      break;
+    }
+    // optional .google.protobuf.ListValue list_value = 6;
+    case kListValue: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *kind_.list_value_);
+      break;
+    }
+    case KIND_NOT_SET: {
+      break;
+    }
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Value>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value)
+    MergeFrom(*source);
+  }
+}
+
+void Value::MergeFrom(const Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  switch (from.kind_case()) {
+    case kNullValue: {
+      set_null_value(from.null_value());
+      break;
+    }
+    case kNumberValue: {
+      set_number_value(from.number_value());
+      break;
+    }
+    case kStringValue: {
+      set_string_value(from.string_value());
+      break;
+    }
+    case kBoolValue: {
+      set_bool_value(from.bool_value());
+      break;
+    }
+    case kStructValue: {
+      mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value());
+      break;
+    }
+    case kListValue: {
+      mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value());
+      break;
+    }
+    case KIND_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Value::CopyFrom(const Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Value::IsInitialized() const {
+
+  return true;
+}
+
+void Value::Swap(Value* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Value::InternalSwap(Value* other) {
+  std::swap(kind_, other->kind_);
+  std::swap(_oneof_case_[0], other->_oneof_case_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Value::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Value_descriptor_;
+  metadata.reflection = Value_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Value
+
+// optional .google.protobuf.NullValue null_value = 1;
+bool Value::has_null_value() const {
+  return kind_case() == kNullValue;
+}
+void Value::set_has_null_value() {
+  _oneof_case_[0] = kNullValue;
+}
+void Value::clear_null_value() {
+  if (has_null_value()) {
+    kind_.null_value_ = 0;
+    clear_has_kind();
+  }
+}
+ ::google::protobuf::NullValue Value::null_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value)
+  if (has_null_value()) {
+    return static_cast< ::google::protobuf::NullValue >(kind_.null_value_);
+  }
+  return static_cast< ::google::protobuf::NullValue >(0);
+}
+ void Value::set_null_value(::google::protobuf::NullValue value) {
+  if (!has_null_value()) {
+    clear_kind();
+    set_has_null_value();
+  }
+  kind_.null_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
+}
+
+// optional double number_value = 2;
+bool Value::has_number_value() const {
+  return kind_case() == kNumberValue;
+}
+void Value::set_has_number_value() {
+  _oneof_case_[0] = kNumberValue;
+}
+void Value::clear_number_value() {
+  if (has_number_value()) {
+    kind_.number_value_ = 0;
+    clear_has_kind();
+  }
+}
+ double Value::number_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value)
+  if (has_number_value()) {
+    return kind_.number_value_;
+  }
+  return 0;
+}
+ void Value::set_number_value(double value) {
+  if (!has_number_value()) {
+    clear_kind();
+    set_has_number_value();
+  }
+  kind_.number_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value)
+}
+
+// optional string string_value = 3;
+bool Value::has_string_value() const {
+  return kind_case() == kStringValue;
+}
+void Value::set_has_string_value() {
+  _oneof_case_[0] = kStringValue;
+}
+void Value::clear_string_value() {
+  if (has_string_value()) {
+    kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    clear_has_kind();
+  }
+}
+ const ::std::string& Value::string_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
+  if (has_string_value()) {
+    return kind_.string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
+}
+ void Value::set_string_value(const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+}
+ void Value::set_string_value(const char* value) {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
+}
+ void Value::set_string_value(const char* value, size_t size) {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
+}
+ ::std::string* Value::mutable_string_value() {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value)
+  return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Value::release_string_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
+  if (has_string_value()) {
+    clear_has_kind();
+    return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  } else {
+    return NULL;
+  }
+}
+ void Value::set_allocated_string_value(::std::string* string_value) {
+  if (!has_string_value()) {
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  clear_kind();
+  if (string_value != NULL) {
+    set_has_string_value();
+    kind_.string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+        string_value);
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
+}
+
+// optional bool bool_value = 4;
+bool Value::has_bool_value() const {
+  return kind_case() == kBoolValue;
+}
+void Value::set_has_bool_value() {
+  _oneof_case_[0] = kBoolValue;
+}
+void Value::clear_bool_value() {
+  if (has_bool_value()) {
+    kind_.bool_value_ = false;
+    clear_has_kind();
+  }
+}
+ bool Value::bool_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value)
+  if (has_bool_value()) {
+    return kind_.bool_value_;
+  }
+  return false;
+}
+ void Value::set_bool_value(bool value) {
+  if (!has_bool_value()) {
+    clear_kind();
+    set_has_bool_value();
+  }
+  kind_.bool_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value)
+}
+
+// optional .google.protobuf.Struct struct_value = 5;
+bool Value::has_struct_value() const {
+  return kind_case() == kStructValue;
+}
+void Value::set_has_struct_value() {
+  _oneof_case_[0] = kStructValue;
+}
+void Value::clear_struct_value() {
+  if (has_struct_value()) {
+    delete kind_.struct_value_;
+    clear_has_kind();
+  }
+}
+ const ::google::protobuf::Struct& Value::struct_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
+  return has_struct_value()
+      ? *kind_.struct_value_
+      : ::google::protobuf::Struct::default_instance();
+}
+::google::protobuf::Struct* Value::mutable_struct_value() {
+  if (!has_struct_value()) {
+    clear_kind();
+    set_has_struct_value();
+    kind_.struct_value_ = new ::google::protobuf::Struct;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
+  return kind_.struct_value_;
+}
+::google::protobuf::Struct* Value::release_struct_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value)
+  if (has_struct_value()) {
+    clear_has_kind();
+    ::google::protobuf::Struct* temp = kind_.struct_value_;
+    kind_.struct_value_ = NULL;
+    return temp;
+  } else {
+    return NULL;
+  }
+}
+void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
+  clear_kind();
+  if (struct_value) {
+    set_has_struct_value();
+    kind_.struct_value_ = struct_value;
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value)
+}
+
+// optional .google.protobuf.ListValue list_value = 6;
+bool Value::has_list_value() const {
+  return kind_case() == kListValue;
+}
+void Value::set_has_list_value() {
+  _oneof_case_[0] = kListValue;
+}
+void Value::clear_list_value() {
+  if (has_list_value()) {
+    delete kind_.list_value_;
+    clear_has_kind();
+  }
+}
+ const ::google::protobuf::ListValue& Value::list_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
+  return has_list_value()
+      ? *kind_.list_value_
+      : ::google::protobuf::ListValue::default_instance();
+}
+::google::protobuf::ListValue* Value::mutable_list_value() {
+  if (!has_list_value()) {
+    clear_kind();
+    set_has_list_value();
+    kind_.list_value_ = new ::google::protobuf::ListValue;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
+  return kind_.list_value_;
+}
+::google::protobuf::ListValue* Value::release_list_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value)
+  if (has_list_value()) {
+    clear_has_kind();
+    ::google::protobuf::ListValue* temp = kind_.list_value_;
+    kind_.list_value_ = NULL;
+    return temp;
+  } else {
+    return NULL;
+  }
+}
+void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
+  clear_kind();
+  if (list_value) {
+    set_has_list_value();
+    kind_.list_value_ = list_value;
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
+}
+
+bool Value::has_kind() const {
+  return kind_case() != KIND_NOT_SET;
+}
+void Value::clear_has_kind() {
+  _oneof_case_[0] = KIND_NOT_SET;
+}
+Value::KindCase Value::kind_case() const {
+  return Value::KindCase(_oneof_case_[0]);
+}
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ListValue::kValuesFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ListValue::ListValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.ListValue)
+}
+
+void ListValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+ListValue::ListValue(const ListValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue)
+}
+
+void ListValue::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+}
+
+ListValue::~ListValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.ListValue)
+  SharedDtor();
+}
+
+void ListValue::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void ListValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* ListValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return ListValue_descriptor_;
+}
+
+const ListValue& ListValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  return *default_instance_;
+}
+
+ListValue* ListValue::default_instance_ = NULL;
+
+ListValue* ListValue::New(::google::protobuf::Arena* arena) const {
+  ListValue* n = new ListValue;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void ListValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
+  values_.Clear();
+}
+
+bool ListValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.ListValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.Value values = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_values:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_values()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_loop_values;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.ListValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.ListValue)
+  return false;
+#undef DO_
+}
+
+void ListValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.ListValue)
+  // repeated .google.protobuf.Value values = 1;
+  for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->values(i), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.ListValue)
+}
+
+::google::protobuf::uint8* ListValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue)
+  // repeated .google.protobuf.Value values = 1;
+  for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->values(i), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue)
+  return target;
+}
+
+int ListValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue)
+  int total_size = 0;
+
+  // repeated .google.protobuf.Value values = 1;
+  total_size += 1 * this->values_size();
+  for (int i = 0; i < this->values_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->values(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ListValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue)
+    MergeFrom(*source);
+  }
+}
+
+void ListValue::MergeFrom(const ListValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  values_.MergeFrom(from.values_);
+}
+
+void ListValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ListValue::CopyFrom(const ListValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ListValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ListValue::IsInitialized() const {
+
+  return true;
+}
+
+void ListValue::Swap(ListValue* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ListValue::InternalSwap(ListValue* other) {
+  values_.UnsafeArenaSwap(&other->values_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata ListValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = ListValue_descriptor_;
+  metadata.reflection = ListValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ListValue
+
+// repeated .google.protobuf.Value values = 1;
+int ListValue::values_size() const {
+  return values_.size();
+}
+void ListValue::clear_values() {
+  values_.Clear();
+}
+const ::google::protobuf::Value& ListValue::values(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values)
+  return values_.Get(index);
+}
+::google::protobuf::Value* ListValue::mutable_values(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values)
+  return values_.Mutable(index);
+}
+::google::protobuf::Value* ListValue::add_values() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
+  return values_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+ListValue::mutable_values() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
+  return &values_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+  return values_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/struct.pb.h b/src/third_party/protobuf-3/src/google/protobuf/struct.pb.h
new file mode 100644
index 0000000..6a4764a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/struct.pb.h
@@ -0,0 +1,769 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+class ListValue;
+class Struct;
+class Value;
+
+enum NullValue {
+  NULL_VALUE = 0,
+  NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+  NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool NullValue_IsValid(int value);
+const NullValue NullValue_MIN = NULL_VALUE;
+const NullValue NullValue_MAX = NULL_VALUE;
+const int NullValue_ARRAYSIZE = NullValue_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* NullValue_descriptor();
+inline const ::std::string& NullValue_Name(NullValue value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    NullValue_descriptor(), value);
+}
+inline bool NullValue_Parse(
+    const ::std::string& name, NullValue* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<NullValue>(
+    NullValue_descriptor(), name, value);
+}
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Struct : public ::google::protobuf::Message {
+ public:
+  Struct();
+  virtual ~Struct();
+
+  Struct(const Struct& from);
+
+  inline Struct& operator=(const Struct& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Struct& default_instance();
+
+  void Swap(Struct* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Struct* New() const { return New(NULL); }
+
+  Struct* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Struct& from);
+  void MergeFrom(const Struct& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Struct* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+
+  // accessors -------------------------------------------------------
+
+  // map<string, .google.protobuf.Value> fields = 1;
+  int fields_size() const;
+  void clear_fields();
+  static const int kFieldsFieldNumber = 1;
+  const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+      fields() const;
+  ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+      mutable_fields();
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Struct)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  typedef ::google::protobuf::internal::MapEntryLite<
+      ::std::string, ::google::protobuf::Value,
+      ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+      ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+      0 >
+      Struct_FieldsEntry;
+  ::google::protobuf::internal::MapField<
+      ::std::string, ::google::protobuf::Value,
+      ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+      ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+      0 > fields_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+  void InitAsDefaultInstance();
+  static Struct* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message {
+ public:
+  Value();
+  virtual ~Value();
+
+  Value(const Value& from);
+
+  inline Value& operator=(const Value& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Value& default_instance();
+
+  enum KindCase {
+    kNullValue = 1,
+    kNumberValue = 2,
+    kStringValue = 3,
+    kBoolValue = 4,
+    kStructValue = 5,
+    kListValue = 6,
+    KIND_NOT_SET = 0,
+  };
+
+  void Swap(Value* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Value* New() const { return New(NULL); }
+
+  Value* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Value& from);
+  void MergeFrom(const Value& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Value* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional .google.protobuf.NullValue null_value = 1;
+  private:
+  bool has_null_value() const;
+  public:
+  void clear_null_value();
+  static const int kNullValueFieldNumber = 1;
+  ::google::protobuf::NullValue null_value() const;
+  void set_null_value(::google::protobuf::NullValue value);
+
+  // optional double number_value = 2;
+  private:
+  bool has_number_value() const;
+  public:
+  void clear_number_value();
+  static const int kNumberValueFieldNumber = 2;
+  double number_value() const;
+  void set_number_value(double value);
+
+  // optional string string_value = 3;
+  private:
+  bool has_string_value() const;
+  public:
+  void clear_string_value();
+  static const int kStringValueFieldNumber = 3;
+  const ::std::string& string_value() const;
+  void set_string_value(const ::std::string& value);
+  void set_string_value(const char* value);
+  void set_string_value(const char* value, size_t size);
+  ::std::string* mutable_string_value();
+  ::std::string* release_string_value();
+  void set_allocated_string_value(::std::string* string_value);
+
+  // optional bool bool_value = 4;
+  private:
+  bool has_bool_value() const;
+  public:
+  void clear_bool_value();
+  static const int kBoolValueFieldNumber = 4;
+  bool bool_value() const;
+  void set_bool_value(bool value);
+
+  // optional .google.protobuf.Struct struct_value = 5;
+  bool has_struct_value() const;
+  void clear_struct_value();
+  static const int kStructValueFieldNumber = 5;
+  const ::google::protobuf::Struct& struct_value() const;
+  ::google::protobuf::Struct* mutable_struct_value();
+  ::google::protobuf::Struct* release_struct_value();
+  void set_allocated_struct_value(::google::protobuf::Struct* struct_value);
+
+  // optional .google.protobuf.ListValue list_value = 6;
+  bool has_list_value() const;
+  void clear_list_value();
+  static const int kListValueFieldNumber = 6;
+  const ::google::protobuf::ListValue& list_value() const;
+  ::google::protobuf::ListValue* mutable_list_value();
+  ::google::protobuf::ListValue* release_list_value();
+  void set_allocated_list_value(::google::protobuf::ListValue* list_value);
+
+  KindCase kind_case() const;
+  // @@protoc_insertion_point(class_scope:google.protobuf.Value)
+ private:
+  inline void set_has_null_value();
+  inline void set_has_number_value();
+  inline void set_has_string_value();
+  inline void set_has_bool_value();
+  inline void set_has_struct_value();
+  inline void set_has_list_value();
+
+  inline bool has_kind() const;
+  void clear_kind();
+  inline void clear_has_kind();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  union KindUnion {
+    KindUnion() {}
+    int null_value_;
+    double number_value_;
+    ::google::protobuf::internal::ArenaStringPtr string_value_;
+    bool bool_value_;
+    ::google::protobuf::Struct* struct_value_;
+    ::google::protobuf::ListValue* list_value_;
+  } kind_;
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+  void InitAsDefaultInstance();
+  static Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message {
+ public:
+  ListValue();
+  virtual ~ListValue();
+
+  ListValue(const ListValue& from);
+
+  inline ListValue& operator=(const ListValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const ListValue& default_instance();
+
+  void Swap(ListValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline ListValue* New() const { return New(NULL); }
+
+  ListValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const ListValue& from);
+  void MergeFrom(const ListValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(ListValue* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.Value values = 1;
+  int values_size() const;
+  void clear_values();
+  static const int kValuesFieldNumber = 1;
+  const ::google::protobuf::Value& values(int index) const;
+  ::google::protobuf::Value* mutable_values(int index);
+  ::google::protobuf::Value* add_values();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+      mutable_values();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+      values() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.ListValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+  void InitAsDefaultInstance();
+  static ListValue* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Struct
+
+// map<string, .google.protobuf.Value> fields = 1;
+inline int Struct::fields_size() const {
+  return fields_.size();
+}
+inline void Struct::clear_fields() {
+  fields_.Clear();
+}
+inline const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+Struct::fields() const {
+  // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields)
+  return fields_.GetMap();
+}
+inline ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+Struct::mutable_fields() {
+  // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields)
+  return fields_.MutableMap();
+}
+
+// -------------------------------------------------------------------
+
+// Value
+
+// optional .google.protobuf.NullValue null_value = 1;
+inline bool Value::has_null_value() const {
+  return kind_case() == kNullValue;
+}
+inline void Value::set_has_null_value() {
+  _oneof_case_[0] = kNullValue;
+}
+inline void Value::clear_null_value() {
+  if (has_null_value()) {
+    kind_.null_value_ = 0;
+    clear_has_kind();
+  }
+}
+inline ::google::protobuf::NullValue Value::null_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value)
+  if (has_null_value()) {
+    return static_cast< ::google::protobuf::NullValue >(kind_.null_value_);
+  }
+  return static_cast< ::google::protobuf::NullValue >(0);
+}
+inline void Value::set_null_value(::google::protobuf::NullValue value) {
+  if (!has_null_value()) {
+    clear_kind();
+    set_has_null_value();
+  }
+  kind_.null_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
+}
+
+// optional double number_value = 2;
+inline bool Value::has_number_value() const {
+  return kind_case() == kNumberValue;
+}
+inline void Value::set_has_number_value() {
+  _oneof_case_[0] = kNumberValue;
+}
+inline void Value::clear_number_value() {
+  if (has_number_value()) {
+    kind_.number_value_ = 0;
+    clear_has_kind();
+  }
+}
+inline double Value::number_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value)
+  if (has_number_value()) {
+    return kind_.number_value_;
+  }
+  return 0;
+}
+inline void Value::set_number_value(double value) {
+  if (!has_number_value()) {
+    clear_kind();
+    set_has_number_value();
+  }
+  kind_.number_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value)
+}
+
+// optional string string_value = 3;
+inline bool Value::has_string_value() const {
+  return kind_case() == kStringValue;
+}
+inline void Value::set_has_string_value() {
+  _oneof_case_[0] = kStringValue;
+}
+inline void Value::clear_string_value() {
+  if (has_string_value()) {
+    kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    clear_has_kind();
+  }
+}
+inline const ::std::string& Value::string_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
+  if (has_string_value()) {
+    return kind_.string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
+}
+inline void Value::set_string_value(const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+}
+inline void Value::set_string_value(const char* value) {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
+}
+inline void Value::set_string_value(const char* value, size_t size) {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
+}
+inline ::std::string* Value::mutable_string_value() {
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value)
+  return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Value::release_string_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
+  if (has_string_value()) {
+    clear_has_kind();
+    return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  } else {
+    return NULL;
+  }
+}
+inline void Value::set_allocated_string_value(::std::string* string_value) {
+  if (!has_string_value()) {
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  clear_kind();
+  if (string_value != NULL) {
+    set_has_string_value();
+    kind_.string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+        string_value);
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
+}
+
+// optional bool bool_value = 4;
+inline bool Value::has_bool_value() const {
+  return kind_case() == kBoolValue;
+}
+inline void Value::set_has_bool_value() {
+  _oneof_case_[0] = kBoolValue;
+}
+inline void Value::clear_bool_value() {
+  if (has_bool_value()) {
+    kind_.bool_value_ = false;
+    clear_has_kind();
+  }
+}
+inline bool Value::bool_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value)
+  if (has_bool_value()) {
+    return kind_.bool_value_;
+  }
+  return false;
+}
+inline void Value::set_bool_value(bool value) {
+  if (!has_bool_value()) {
+    clear_kind();
+    set_has_bool_value();
+  }
+  kind_.bool_value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value)
+}
+
+// optional .google.protobuf.Struct struct_value = 5;
+inline bool Value::has_struct_value() const {
+  return kind_case() == kStructValue;
+}
+inline void Value::set_has_struct_value() {
+  _oneof_case_[0] = kStructValue;
+}
+inline void Value::clear_struct_value() {
+  if (has_struct_value()) {
+    delete kind_.struct_value_;
+    clear_has_kind();
+  }
+}
+inline  const ::google::protobuf::Struct& Value::struct_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
+  return has_struct_value()
+      ? *kind_.struct_value_
+      : ::google::protobuf::Struct::default_instance();
+}
+inline ::google::protobuf::Struct* Value::mutable_struct_value() {
+  if (!has_struct_value()) {
+    clear_kind();
+    set_has_struct_value();
+    kind_.struct_value_ = new ::google::protobuf::Struct;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
+  return kind_.struct_value_;
+}
+inline ::google::protobuf::Struct* Value::release_struct_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value)
+  if (has_struct_value()) {
+    clear_has_kind();
+    ::google::protobuf::Struct* temp = kind_.struct_value_;
+    kind_.struct_value_ = NULL;
+    return temp;
+  } else {
+    return NULL;
+  }
+}
+inline void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
+  clear_kind();
+  if (struct_value) {
+    set_has_struct_value();
+    kind_.struct_value_ = struct_value;
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value)
+}
+
+// optional .google.protobuf.ListValue list_value = 6;
+inline bool Value::has_list_value() const {
+  return kind_case() == kListValue;
+}
+inline void Value::set_has_list_value() {
+  _oneof_case_[0] = kListValue;
+}
+inline void Value::clear_list_value() {
+  if (has_list_value()) {
+    delete kind_.list_value_;
+    clear_has_kind();
+  }
+}
+inline  const ::google::protobuf::ListValue& Value::list_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
+  return has_list_value()
+      ? *kind_.list_value_
+      : ::google::protobuf::ListValue::default_instance();
+}
+inline ::google::protobuf::ListValue* Value::mutable_list_value() {
+  if (!has_list_value()) {
+    clear_kind();
+    set_has_list_value();
+    kind_.list_value_ = new ::google::protobuf::ListValue;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
+  return kind_.list_value_;
+}
+inline ::google::protobuf::ListValue* Value::release_list_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value)
+  if (has_list_value()) {
+    clear_has_kind();
+    ::google::protobuf::ListValue* temp = kind_.list_value_;
+    kind_.list_value_ = NULL;
+    return temp;
+  } else {
+    return NULL;
+  }
+}
+inline void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
+  clear_kind();
+  if (list_value) {
+    set_has_list_value();
+    kind_.list_value_ = list_value;
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
+}
+
+inline bool Value::has_kind() const {
+  return kind_case() != KIND_NOT_SET;
+}
+inline void Value::clear_has_kind() {
+  _oneof_case_[0] = KIND_NOT_SET;
+}
+inline Value::KindCase Value::kind_case() const {
+  return Value::KindCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// ListValue
+
+// repeated .google.protobuf.Value values = 1;
+inline int ListValue::values_size() const {
+  return values_.size();
+}
+inline void ListValue::clear_values() {
+  values_.Clear();
+}
+inline const ::google::protobuf::Value& ListValue::values(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values)
+  return values_.Get(index);
+}
+inline ::google::protobuf::Value* ListValue::mutable_values(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values)
+  return values_.Mutable(index);
+}
+inline ::google::protobuf::Value* ListValue::add_values() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
+  return values_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+ListValue::mutable_values() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
+  return &values_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+  return values_;
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::google::protobuf::NullValue> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>() {
+  return ::google::protobuf::NullValue_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+#endif  // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/struct.proto b/src/third_party/protobuf-3/src/google/protobuf/struct.proto
new file mode 100644
index 0000000..beeba81
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/struct.proto
@@ -0,0 +1,96 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "StructProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
+message Struct {
+  // Unordered map of dynamically typed values.
+  map<string, Value> fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
+message Value {
+  // The kind of value.
+  oneof kind {
+    // Represents a null value.
+    NullValue null_value = 1;
+    // Represents a double value.
+    double number_value = 2;
+    // Represents a string value.
+    string string_value = 3;
+    // Represents a boolean value.
+    bool bool_value = 4;
+    // Represents a structured value.
+    Struct struct_value = 5;
+    // Represents a repeated `Value`.
+    ListValue list_value = 6;
+  }
+}
+
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+//  The JSON representation for `NullValue` is JSON `null`.
+enum NullValue {
+  // Null value.
+  NULL_VALUE = 0;
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
+message ListValue {
+  // Repeated field of dynamically typed values.
+  repeated Value values = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomic_sequence_num.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomic_sequence_num.h
new file mode 100644
index 0000000..bb20942
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomic_sequence_num.h
@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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_ATOMIC_SEQUENCE_NUM_H_
+#define GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_
+
+#include <google/protobuf/stubs/atomicops.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class SequenceNumber {
+ public:
+  SequenceNumber() : word_(0) {}
+
+  AtomicWord GetNext() {
+    return NoBarrier_AtomicIncrement(&word_, 1) - 1;
+  }
+ private:
+  AtomicWord word_;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops.h
new file mode 100644
index 0000000..9b3d1e6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops.h
@@ -0,0 +1,246 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// The routines exported by this module are subtle.  If you use them, even if
+// you get the code right, it will depend on careful reasoning about atomicity
+// and memory ordering; it will be less readable, and harder to maintain.  If
+// you plan to use these routines, you should have a good reason, such as solid
+// evidence that performance would otherwise suffer, or there being no
+// alternative.  You should assume only properties explicitly guaranteed by the
+// specifications in this file.  You are almost certainly _not_ writing code
+// just for the x86; if you assume x86 semantics, x86 hardware bugs and
+// implementations on other archtectures will cause your code to break.  If you
+// do not know what you are doing, avoid these routines, and use a Mutex.
+//
+// It is incorrect to make direct assignments to/from an atomic variable.
+// You should use one of the Load or Store routines.  The NoBarrier
+// versions are provided when no barriers are needed:
+//   NoBarrier_Store()
+//   NoBarrier_Load()
+// Although there are currently no compiler enforcement, you are encouraged
+// to use these.
+
+// This header and the implementations for each platform (located in
+// atomicops_internals_*) must be kept in sync with the upstream code (V8).
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_H_
+
+// Don't include this file for people not concerned about thread safety.
+#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/platform_macros.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+#if defined(GOOGLE_PROTOBUF_ARCH_POWER)
+#if defined(_LP64) || defined(__LP64__)
+typedef int32 Atomic32;
+typedef intptr_t Atomic64;
+#else
+typedef intptr_t Atomic32;
+typedef int64 Atomic64;
+#endif
+#else
+typedef int32 Atomic32;
+#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
+// We need to be able to go between Atomic64 and AtomicWord implicitly.  This
+// means Atomic64 and AtomicWord should be the same type on 64-bit.
+#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL)
+// NaCl's intptr_t is not actually 64-bits on 64-bit!
+// http://code.google.com/p/nativeclient/issues/detail?id=1162
+// sparcv9's pointer type is 32bits
+typedef int64 Atomic64;
+#else
+typedef intptr_t Atomic64;
+#endif
+#endif
+#endif
+
+// Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
+// Atomic64 routines below, depending on your architecture.
+typedef intptr_t AtomicWord;
+
+// Atomically execute:
+//      result = *ptr;
+//      if (*ptr == old_value)
+//        *ptr = new_value;
+//      return result;
+//
+// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+// Always return the old value of "*ptr"
+//
+// This routine implies no memory barriers.
+Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                  Atomic32 old_value,
+                                  Atomic32 new_value);
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
+
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                 Atomic32 increment);
+
+// These following lower-level operations are typically useful only to people
+// implementing higher-level synchronization operations like spinlocks,
+// mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
+// a store with appropriate memory-ordering instructions.  "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+
+#if defined(__MINGW32__) && defined(MemoryBarrier)
+#undef MemoryBarrier
+#endif
+void MemoryBarrier();
+void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
+void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
+void Release_Store(volatile Atomic32* ptr, Atomic32 value);
+
+Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
+Atomic32 Acquire_Load(volatile const Atomic32* ptr);
+Atomic32 Release_Load(volatile const Atomic32* ptr);
+
+// 64-bit atomic operations (only available on 64-bit processors).
+#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
+Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                  Atomic64 old_value,
+                                  Atomic64 new_value);
+Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
+Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+
+Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                Atomic64 old_value,
+                                Atomic64 new_value);
+Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                Atomic64 old_value,
+                                Atomic64 new_value);
+void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
+void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
+void Release_Store(volatile Atomic64* ptr, Atomic64 value);
+Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
+Atomic64 Acquire_Load(volatile const Atomic64* ptr);
+Atomic64 Release_Load(volatile const Atomic64* ptr);
+#endif  // GOOGLE_PROTOBUF_ARCH_64_BIT
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Include our platform specific implementation.
+#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \
+"Atomic operations are not supported on your platform"
+
+// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html.
+#if defined(THREAD_SANITIZER)
+#include <google/protobuf/stubs/atomicops_internals_tsan.h>
+// MSVC.
+#elif defined(_MSC_VER)
+#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
+#include <google/protobuf/stubs/atomicops_internals_x86_msvc.h>
+#else
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#endif
+
+// Solaris
+#elif defined(GOOGLE_PROTOBUF_OS_SOLARIS)
+#include <google/protobuf/stubs/atomicops_internals_solaris.h>
+
+// AIX
+#elif defined(GOOGLE_PROTOBUF_OS_AIX)
+#include <google/protobuf/stubs/atomicops_internals_power.h>
+
+// Apple.
+#elif defined(GOOGLE_PROTOBUF_OS_APPLE)
+#include <google/protobuf/stubs/atomicops_internals_macosx.h>
+
+// GCC.
+#elif defined(__GNUC__)
+#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
+#include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__)
+#include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64)
+#include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
+#include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64)
+#include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_POWER)
+#include <google/protobuf/stubs/atomicops_internals_power.h>
+#elif defined(__native_client__)
+#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_PPC)
+#include <google/protobuf/stubs/atomicops_internals_ppc_gcc.h>
+#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
+#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
+#elif defined(__clang__)
+#if __has_extension(c_atomic)
+#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
+#else
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#endif
+#else
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#endif
+
+// Unknown.
+#else
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#endif
+
+// On some platforms we need additional declarations to make AtomicWord
+// compatible with our other Atomic* types.
+#if defined(GOOGLE_PROTOBUF_OS_APPLE)
+#include <google/protobuf/stubs/atomicops_internals_atomicword_compat.h>
+#endif
+
+#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+
+#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
new file mode 100644
index 0000000..0a2d2b8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
@@ -0,0 +1,325 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__ ("dmb ish" ::: "memory");  // NOLINT
+}
+
+// NoBarrier versions of the operation include "memory" in the clobber list.
+// This is not required for direct usage of the NoBarrier versions of the
+// operations. However this is required for correctness when they are used as
+// part of the Acquire or Release versions, to ensure that nothing from outside
+// the call is reordered between the operation and the memory barrier. This does
+// not change the code generated, so has no or minimal impact on the
+// NoBarrier operations.
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                       \n\t"
+    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
+    "add %w[result], %w[result], %w[increment]\n\t"
+    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
+    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  MemoryBarrier();
+  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+
+  return prev;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  MemoryBarrier();
+  Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  __asm__ __volatile__ (  // NOLINT
+    "stlr %w[value], %[ptr]  \n\t"
+    : [ptr]"=Q" (*ptr)
+    : [value]"r" (value)
+    : "memory"
+  );  // NOLINT
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value;
+
+  __asm__ __volatile__ (  // NOLINT
+    "ldar %w[value], %[ptr]  \n\t"
+    : [value]"=r" (value)
+    : [ptr]"Q" (*ptr)
+    : "memory"
+  );  // NOLINT
+
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+// 64-bit versions of the operations.
+// See the 32-bit versions for comments.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"IJr" (old_value),
+      [new_value]"r" (new_value)
+    : "cc", "memory"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[result], %[ptr]                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                     \n\t"
+    "ldxr %[result], %[ptr]                 \n\t"
+    "add %[result], %[result], %[increment] \n\t"
+    "stxr %w[temp], %[result], %[ptr]       \n\t"
+    "cbnz %w[temp], 0b                      \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"IJr" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  MemoryBarrier();
+  Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+
+  return prev;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  MemoryBarrier();
+  Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  __asm__ __volatile__ (  // NOLINT
+    "stlr %x[value], %[ptr]  \n\t"
+    : [ptr]"=Q" (*ptr)
+    : [value]"r" (value)
+    : "memory"
+  );  // NOLINT
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value;
+
+  __asm__ __volatile__ (  // NOLINT
+    "ldar %x[value], %[ptr]  \n\t"
+    : [value]"=r" (value)
+    : [ptr]"Q" (*ptr)
+    : "memory"
+  );  // NOLINT
+
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h
new file mode 100644
index 0000000..90e727b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h
@@ -0,0 +1,151 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+//
+// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// 0xffff0fc0 is the hard coded address of a function provided by
+// the kernel which implements an atomic compare-exchange. On older
+// ARM architecture revisions (pre-v6) this may be implemented using
+// a syscall. This address is stable, and in active use (hard coded)
+// by at least glibc-2.7 and the Android C library.
+typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
+                                           Atomic32 new_value,
+                                           volatile Atomic32* ptr);
+LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
+    (LinuxKernelCmpxchgFunc) 0xffff0fc0;
+
+typedef void (*LinuxKernelMemoryBarrierFunc)(void);
+LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
+    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
+
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value = *ptr;
+  do {
+    if (!pLinuxKernelCmpxchg(old_value, new_value,
+                             const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (pLinuxKernelCmpxchg(old_value, new_value,
+                               const_cast<Atomic32*>(ptr)));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  for (;;) {
+    // Atomic exchange the old value with an incremented one.
+    Atomic32 old_value = *ptr;
+    Atomic32 new_value = old_value + increment;
+    if (pLinuxKernelCmpxchg(old_value, new_value,
+                            const_cast<Atomic32*>(ptr)) == 0) {
+      // The exchange took place as expected.
+      return new_value;
+    }
+    // Otherwise, *ptr changed mid-loop and we need to retry.
+  }
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  pLinuxKernelMemoryBarrier();
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h
new file mode 100644
index 0000000..17dfaa5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h
@@ -0,0 +1,146 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_
+
+// For _smp_cmpxchg()
+#include <pthread.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 QNXCmpxchg(Atomic32 old_value,
+                           Atomic32 new_value,
+                           volatile Atomic32* ptr) {
+  return static_cast<Atomic32>(
+      _smp_cmpxchg((volatile unsigned *)ptr,
+                   (unsigned)old_value,
+                   (unsigned)new_value));
+}
+
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value = *ptr;
+  do {
+    if (!QNXCmpxchg(old_value, new_value,
+                    const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (QNXCmpxchg(old_value, new_value,
+                      const_cast<Atomic32*>(ptr)));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  for (;;) {
+    // Atomic exchange the old value with an incremented one.
+    Atomic32 old_value = *ptr;
+    Atomic32 new_value = old_value + increment;
+    if (QNXCmpxchg(old_value, new_value,
+                   const_cast<Atomic32*>(ptr)) == 0) {
+      // The exchange took place as expected.
+      return new_value;
+    }
+    // Otherwise, *ptr changed mid-loop and we need to retry.
+  }
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  __sync_synchronize();
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
new file mode 100644
index 0000000..eb198ff
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
@@ -0,0 +1,122 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
+
+// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32,
+// which in turn means int. On some LP32 platforms, intptr_t is an int, but
+// on others, it's a long. When AtomicWord and Atomic32 are based on different
+// fundamental types, their pointers are incompatible.
+//
+// This file defines function overloads to allow both AtomicWord and Atomic32
+// data to be used with this interface.
+//
+// On LP64 platforms, AtomicWord and Atomic64 are both always long,
+// so this problem doesn't occur.
+
+#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
+                                           AtomicWord old_value,
+                                           AtomicWord new_value) {
+  return NoBarrier_CompareAndSwap(
+      reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
+}
+
+inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
+                                           AtomicWord new_value) {
+  return NoBarrier_AtomicExchange(
+      reinterpret_cast<volatile Atomic32*>(ptr), new_value);
+}
+
+inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
+                                            AtomicWord increment) {
+  return NoBarrier_AtomicIncrement(
+      reinterpret_cast<volatile Atomic32*>(ptr), increment);
+}
+
+inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
+                                          AtomicWord increment) {
+  return Barrier_AtomicIncrement(
+      reinterpret_cast<volatile Atomic32*>(ptr), increment);
+}
+
+inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
+                                         AtomicWord old_value,
+                                         AtomicWord new_value) {
+  return Acquire_CompareAndSwap(
+      reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
+}
+
+inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
+                                         AtomicWord old_value,
+                                         AtomicWord new_value) {
+  return Release_CompareAndSwap(
+      reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
+  NoBarrier_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
+}
+
+inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
+  return Acquire_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
+}
+
+inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
+  return Release_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
+}
+
+inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
+  return NoBarrier_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
+}
+
+inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
+  return Acquire_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
+}
+
+inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
+  return Release_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
+}
+
+}   // namespace internal
+}   // namespace protobuf
+}   // namespace google
+
+#endif  // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
new file mode 100644
index 0000000..a0116a6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
@@ -0,0 +1,137 @@
+// Copyright 2013 Red Hat Inc.  All rights reserved.
+//
+// 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 Red Hat 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+                              __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+                              __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+  return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+                              __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
+  return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline void MemoryBarrier() {
+  __sync_synchronize();
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST);
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_RELAXED);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+}
+
+#ifdef __LP64__
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+                              __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+  return old_value;
+}
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+                              __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+  return old_value;
+}
+
+#endif // defined(__LP64__)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_macosx.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_macosx.h
new file mode 100644
index 0000000..7963324
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_macosx.h
@@ -0,0 +1,225 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
+
+#include <libkern/OSAtomic.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap32(old_value, new_value,
+                                 const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (!OSAtomicCompareAndSwap32(old_value, new_value,
+                                     const_cast<Atomic32*>(ptr)));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline void MemoryBarrier() {
+  OSMemoryBarrier();
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
+                                        const_cast<Atomic32*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return Acquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#ifdef __LP64__
+
+// 64-bit implementation on 64-bit platform
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap64(old_value, new_value,
+                                 reinterpret_cast<volatile int64_t*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 old_value;
+  do {
+    old_value = *ptr;
+  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
+                                     reinterpret_cast<volatile int64_t*>(ptr)));
+  return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  return OSAtomicAdd64Barrier(increment,
+                              reinterpret_cast<volatile int64_t*>(ptr));
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev_value;
+  do {
+    if (OSAtomicCompareAndSwap64Barrier(
+        old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
+      return old_value;
+    }
+    prev_value = *ptr;
+  } while (prev_value == old_value);
+  return prev_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  // The lib kern interface does not distinguish between
+  // Acquire and Release memory barriers; they are equivalent.
+  return Acquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#endif  // defined(__LP64__)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
new file mode 100644
index 0000000..f5837c9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
@@ -0,0 +1,313 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Atomically execute:
+//      result = *ptr;
+//      if (*ptr == old_value)
+//        *ptr = new_value;
+//      return result;
+//
+// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+// Always return the old value of "*ptr"
+//
+// This routine implies no memory barriers.
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev, tmp;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %0, %5\n"  // prev = *ptr
+                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
+                       "move %2, %4\n"  // tmp = new_value
+                       "sc %2, %1\n"  // *ptr = tmp (with atomic check)
+                       "beqz %2, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       "2:\n"
+                       ".set pop\n"
+                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
+                       : "r" (old_value), "r" (new_value), "m" (*ptr)
+                       : "memory");
+  return prev;
+}
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 temp, old;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %1, %4\n"  // old = *ptr
+                       "move %0, %3\n"  // temp = new_value
+                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
+                       "beqz %0, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
+                       : "r" (new_value), "m" (*ptr)
+                       : "memory");
+
+  return old;
+}
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp, temp2;
+
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "ll %0, %4\n"  // temp = *ptr
+                       "addu %1, %0, %3\n"  // temp2 = temp + increment
+                       "sc %1, %2\n"  // *ptr = temp2 (with atomic check)
+                       "beqz %1, 1b\n"  // start again on atomic error
+                       "addu %1, %0, %3\n"  // temp2 = temp + increment
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
+                       : "Ir" (increment), "m" (*ptr)
+                       : "memory");
+  // temp2 now holds the final value.
+  return temp2;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+// "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__("sync" : : : "memory");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#if defined(__LP64__)
+// 64-bit versions of the atomic ops.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev, tmp;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "lld %0, %5\n"  // prev = *ptr
+                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
+                       "move %2, %4\n"  // tmp = new_value
+                       "scd %2, %1\n"  // *ptr = tmp (with atomic check)
+                       "beqz %2, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       "2:\n"
+                       ".set pop\n"
+                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
+                       : "r" (old_value), "r" (new_value), "m" (*ptr)
+                       : "memory");
+  return prev;
+}
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 temp, old;
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "lld %1, %4\n"  // old = *ptr
+                       "move %0, %3\n"  // temp = new_value
+                       "scd %0, %2\n"  // *ptr = temp (with atomic check)
+                       "beqz %0, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
+                       : "r" (new_value), "m" (*ptr)
+                       : "memory");
+
+  return old;
+}
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 temp, temp2;
+
+  __asm__ __volatile__(".set push\n"
+                       ".set noreorder\n"
+                       "1:\n"
+                       "lld %0, %4\n"  // temp = *ptr
+                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
+                       "scd %1, %2\n"  // *ptr = temp2 (with atomic check)
+                       "beqz %1, 1b\n"  // start again on atomic error
+                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
+                       ".set pop\n"
+                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
+                       : "Ir" (increment), "m" (*ptr)
+                       : "memory");
+  // temp2 now holds the final value.
+  return temp2;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  MemoryBarrier();
+  Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+  return res;
+}
+
+// "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+  return res;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  MemoryBarrier();
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+#endif
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_pnacl.h
new file mode 100644
index 0000000..3b314fd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_pnacl.h
@@ -0,0 +1,231 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+
+#include <atomic>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This implementation is transitional and maintains the original API for
+// atomicops.h. This requires casting memory locations to the atomic types, and
+// assumes that the API and the C++11 implementation are layout-compatible,
+// which isn't true for all implementations or hardware platforms. The static
+// assertion should detect this issue, were it to fire then this header
+// shouldn't be used.
+//
+// TODO(jfb) If this header manages to stay committed then the API should be
+//           modified, and all call sites updated.
+typedef volatile std::atomic<Atomic32>* AtomicLocation32;
+static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
+              "incompatible 32-bit atomic layout");
+
+inline void MemoryBarrier() {
+#if defined(__GLIBCXX__)
+  // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
+  // not defined, leading to the linker complaining about undefined references.
+  __atomic_thread_fence(std::memory_order_seq_cst);
+#else
+  std::atomic_thread_fence(std::memory_order_seq_cst);
+#endif
+}
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_relaxed,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  return ((AtomicLocation32)ptr)
+      ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return increment +
+         ((AtomicLocation32)ptr)
+             ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_acquire,
+                                std::memory_order_acquire);
+  return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_release,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+typedef volatile std::atomic<Atomic64>* AtomicLocation64;
+static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
+              "incompatible 64-bit atomic layout");
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_relaxed,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  return ((AtomicLocation64)ptr)
+      ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  return increment +
+         ((AtomicLocation64)ptr)
+             ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_acquire,
+                                std::memory_order_acquire);
+  return old_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_release,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+#endif  // defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_power.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_power.h
new file mode 100644
index 0000000..b8a42f2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_power.h
@@ -0,0 +1,440 @@
+// Copyright 2014 Bloomberg Finance LP. All rights reserved.
+//
+// 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 Bloomberg Finance LP. 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+
+  asm volatile (
+      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpw %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
+      "       bne- 1b                         \n\t"
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+
+  asm volatile (
+      "1:     lwarx %[res], %[zero], %[obj]       \n\t"
+      "       stwcx. %[val], %[zero], %[obj]      \n\t"
+      "       bne- 1b                             \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 result;
+
+  asm volatile (
+      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       add %[res], %[val], %[res]      \n\t"  // add the operand
+      "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
+                                                     // if still reserved
+      "       bne- 1b                         \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (increment),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline void MemoryBarrier(void) {
+  asm volatile (
+      "       lwsync                          \n\t"
+      "       isync                           \n\t"
+              :
+              :
+              : "memory");
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  Atomic32 result;
+
+  asm volatile (
+      "       lwsync                          \n\t"
+
+      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       add %[res], %[val], %[res]      \n\t"  // add the operand
+      "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
+                                                     // if still reserved
+      "       bne- 1b                         \n\t"
+      "       isync                           \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (increment),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 result;
+
+  asm volatile (
+      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpw %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
+      "       bne- 1b                         \n\t"
+
+      "       isync                           \n\t"
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 result;
+
+  asm volatile (
+      "       lwsync                          \n\t"
+
+      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpw %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
+      "       bne- 1b                         \n\t"
+
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  asm volatile (
+      "       stw %[val], %[obj]      \n\t"
+      "       isync                   \n\t"
+              : [obj] "=m" (*ptr)
+              : [val]  "b"  (value));
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  asm volatile (
+      "       lwsync                  \n\t"
+      "       stw %[val], %[obj]      \n\t"
+              : [obj] "=m" (*ptr)
+              : [val]  "b"  (value));
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 result;
+
+  asm volatile (
+      "1:     lwz %[res], %[obj]              \n\t"
+      "       cmpw %[res], %[res]             \n\t" // create data
+                                                    // dependency for
+                                                    // load/load ordering
+      "       bne- 1b                         \n\t" // never taken
+
+      "       isync                           \n\t"
+              : [res]  "=b" (result)
+              : [obj]  "m"  (*ptr),
+                [zero] "i"  (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  Atomic32 result;
+
+  asm volatile (
+      "       lwsync                          \n\t"
+
+      "1:     lwz %[res], %[obj]              \n\t"
+      "       cmpw %[res], %[res]             \n\t" // create data
+                                                    // dependency for
+                                                    // load/load ordering
+      "       bne- 1b                         \n\t" // never taken
+              : [res]  "=b" (result)
+              : [obj]  "m"  (*ptr),
+                [zero] "i"  (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+
+  asm volatile (
+      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpd %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+
+      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
+      "       bne- 1b                         \n\t"
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+
+  asm volatile (
+      "1:     ldarx %[res], %[zero], %[obj]       \n\t"
+      "       stdcx. %[val], %[zero], %[obj]      \n\t"
+      "       bne- 1b                             \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 result;
+
+  asm volatile (
+      "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
+      "       add %[res], %[res], %[val]      \n\t" // add the operand
+      "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
+                                                    // still reserved
+
+      "       bne- 1b                         \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (increment),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+
+  Atomic64 result;
+
+  asm volatile (
+      "       lwsync                          \n\t"
+
+      "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
+      "       add %[res], %[res], %[val]      \n\t" // add the operand
+      "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
+                                                    // still reserved
+
+      "       bne- 1b                         \n\t"
+
+      "       isync                           \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [val]  "b"   (increment),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 result;
+
+  asm volatile (
+      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpd %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+
+      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
+      "       bne- 1b                         \n\t"
+      "       isync                           \n\t"
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 result;
+
+  asm volatile (
+      "       lwsync                          \n\t"
+
+      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
+      "       cmpd %[cmp], %[res]             \n\t"  // compare values
+      "       bne- 2f                         \n\t"
+
+      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
+      "       bne- 1b                         \n\t"
+      "2:                                     \n\t"
+              : [res]  "=&b" (result)
+              : [obj]  "b"   (ptr),
+                [cmp]  "b"   (old_value),
+                [val]  "b"   (new_value),
+                [zero] "i"   (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  asm volatile (
+      "       std %[val], %[obj]          \n\t"
+      "       isync                       \n\t"
+              : [obj] "=m" (*ptr)
+              : [val] "b"  (value));
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  asm volatile (
+      "       lwsync                      \n\t"
+      "       std %[val], %[obj]          \n\t"
+              : [obj] "=m" (*ptr)
+              : [val] "b"  (value));
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 result;
+
+  asm volatile (
+      "1:     ld %[res], %[obj]                   \n\t"
+      "       cmpd %[res], %[res]                 \n\t" // create data
+                                                        // dependency for
+                                                        // load/load ordering
+      "       bne- 1b                             \n\t" // never taken
+
+      "       isync                               \n\t"
+              : [res]  "=b" (result)
+              : [obj]  "m"  (*ptr),
+                [zero] "i"  (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  Atomic64 result;
+
+  asm volatile (
+      "       lwsync                              \n\t"
+
+      "1:     ld %[res], %[obj]                   \n\t"
+      "       cmpd %[res], %[res]                 \n\t" // create data
+                                                        // dependency for
+                                                        // load/load ordering
+      "       bne- 1b                             \n\t" // never taken
+              : [res]  "=b" (result)
+              : [obj]  "m"  (*ptr),
+                [zero] "i"  (0)
+              : "cr0", "ctr");
+
+  return result;
+}
+#endif
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h
new file mode 100644
index 0000000..8231a57
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+// Author: ogabbay@advaoptical.com (Oded Gabbay)
+// Cleaned up by: bsilver16384@gmail.com (Brian Silverman)
+//
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+
+  __asm__ __volatile__(
+      "0:                                  \n\t"
+      "lwarx %[prev],0,%[ptr]              \n\t"
+      "cmpw 0,%[prev],%[old_value]         \n\t"
+      "bne- 1f                             \n\t"
+      "stwcx. %[new_value],0,%[ptr]        \n\t"
+      "bne- 0b                             \n\t"
+      "1:                                  \n\t"
+      : [prev] "=&r"(prev), "+m"(*ptr)
+      : [ptr] "r"(ptr), [old_value] "r"(old_value), [new_value] "r"(new_value)
+      : "cc", "memory");
+
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old;
+
+  __asm__ __volatile__(
+      "0:                                  \n\t"
+      "lwarx %[old],0,%[ptr]               \n\t"
+      "stwcx. %[new_value],0,%[ptr]        \n\t"
+      "bne- 0b                             \n\t"
+      : [old] "=&r"(old), "+m"(*ptr)
+      : [ptr] "r"(ptr), [new_value] "r"(new_value)
+      : "cc", "memory");
+
+  return old;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp;
+
+  __asm__ __volatile__(
+      "0:                                  \n\t"
+      "lwarx %[temp],0,%[ptr]              \n\t"
+      "add %[temp],%[increment],%[temp]    \n\t"
+      "stwcx. %[temp],0,%[ptr]             \n\t"
+      "bne- 0b                             \n\t"
+      : [temp] "=&r"(temp)
+      : [increment] "r"(increment), [ptr] "r"(ptr)
+      : "cc", "memory");
+
+  return temp;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                        Atomic32 increment) {
+  MemoryBarrier();
+  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+  return res;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value, Atomic32 new_value) {
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+  return res;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value, Atomic32 new_value) {
+  MemoryBarrier();
+  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  return res;
+}
+
+inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() { __asm__ __volatile__("sync" : : : "memory"); }
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { return *ptr; }
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_solaris.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_solaris.h
new file mode 100644
index 0000000..d8057ec
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_solaris.h
@@ -0,0 +1,188 @@
+// Copyright 2014 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
+
+#include <atomic.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  return (Atomic32)atomic_cas_32((volatile uint32_t*)ptr, (uint32_t)old_value, (uint32_t)new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  return (Atomic32)atomic_swap_32((volatile uint32_t*)ptr, (uint32_t)new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return (Atomic32)atomic_add_32_nv((volatile uint32_t*)ptr, (uint32_t)increment);
+}
+
+inline void MemoryBarrier(void) {
+	membar_producer();
+	membar_consumer();
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  MemoryBarrier();
+  Atomic32 ret = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return ret;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+
+  return ret;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  MemoryBarrier();
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  membar_producer();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  membar_consumer();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 val = *ptr;
+  membar_consumer();
+  return val;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  membar_producer();
+  return *ptr;
+}
+
+#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  return atomic_cas_64((volatile uint64_t*)ptr, (uint64_t)old_value, (uint64_t)new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value) {
+  return atomic_swap_64((volatile uint64_t*)ptr, (uint64_t)new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) {
+  return atomic_add_64_nv((volatile uint64_t*)ptr, increment);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) {
+  MemoryBarrier();
+  Atomic64 ret = atomic_add_64_nv((volatile uint64_t*)ptr, increment);
+  MemoryBarrier();
+  return ret;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+  return ret;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  MemoryBarrier();
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  membar_producer();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  membar_consumer();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 ret = *ptr;
+  membar_consumer();
+  return ret;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  membar_producer();
+  return *ptr;
+}
+#endif
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_tsan.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_tsan.h
new file mode 100644
index 0000000..0c90354
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_tsan.h
@@ -0,0 +1,219 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+// This file is an internal atomic implementation for compiler-based
+// ThreadSanitizer (http://clang.llvm.org/docs/ThreadSanitizer.html).
+// Use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+#include <sanitizer/tsan_interface_atomic.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+                                         Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr,
+                                       Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_acquire);
+}
+
+inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr,
+                                       Atomic32 new_value) {
+  return __tsan_atomic32_exchange(ptr, new_value,
+      __tsan_memory_order_release);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                          Atomic32 increment) {
+  return increment + __tsan_atomic32_fetch_add(ptr, increment,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+                                        Atomic32 increment) {
+  return increment + __tsan_atomic32_fetch_add(ptr, increment,
+      __tsan_memory_order_acq_rel);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
+  return cmp;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 cmp = old_value;
+  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_release, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+  __tsan_atomic32_store(ptr, value, __tsan_memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
+                                         Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr,
+                                       Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire);
+}
+
+inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr,
+                                       Atomic64 new_value) {
+  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                          Atomic64 increment) {
+  return increment + __tsan_atomic64_fetch_add(ptr, increment,
+      __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+                                        Atomic64 increment) {
+  return increment + __tsan_atomic64_fetch_add(ptr, increment,
+      __tsan_memory_order_acq_rel);
+}
+
+inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
+  __tsan_atomic64_store(ptr, value, __tsan_memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
+  return cmp;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 cmp = old_value;
+  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
+      __tsan_memory_order_release, __tsan_memory_order_relaxed);
+  return cmp;
+}
+
+inline void MemoryBarrier() {
+  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
new file mode 100644
index 0000000..53c9eae
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
@@ -0,0 +1,137 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This module gets enough CPU information to optimize the
+// atomicops module on x86.
+
+#include <cstring>
+
+#include <google/protobuf/stubs/atomicops.h>
+
+// This file only makes sense with atomicops_internals_x86_gcc.h -- it
+// depends on structs that are defined in that file.  If atomicops.h
+// doesn't sub-include that file, then we aren't needed, and shouldn't
+// try to do anything.
+#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
+
+// Inline cpuid instruction.  In PIC compilations, %ebx contains the address
+// of the global offset table.  To avoid breaking such executables, this code
+// must preserve that register's value across cpuid instructions.
+#if defined(__i386__)
+#define cpuid(a, b, c, d, inp) \
+  asm("mov %%ebx, %%edi\n"     \
+      "cpuid\n"                \
+      "xchg %%edi, %%ebx\n"    \
+      : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
+#elif defined(__x86_64__)
+#define cpuid(a, b, c, d, inp) \
+  asm("mov %%rbx, %%rdi\n"     \
+      "cpuid\n"                \
+      "xchg %%rdi, %%rbx\n"    \
+      : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
+#endif
+
+#if defined(cpuid)        // initialize the struct only on x86
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Set the flags so that code will run correctly and conservatively, so even
+// if we haven't been initialized yet, we're probably single threaded, and our
+// default values should hopefully be pretty safe.
+struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
+  false,          // bug can't exist before process spawns multiple threads
+  false,          // no SSE2
+};
+
+namespace {
+
+// Initialize the AtomicOps_Internalx86CPUFeatures struct.
+void AtomicOps_Internalx86CPUFeaturesInit() {
+  uint32_t eax;
+  uint32_t ebx;
+  uint32_t ecx;
+  uint32_t edx;
+
+  // Get vendor string (issue CPUID with eax = 0)
+  cpuid(eax, ebx, ecx, edx, 0);
+  char vendor[13];
+  memcpy(vendor, &ebx, 4);
+  memcpy(vendor + 4, &edx, 4);
+  memcpy(vendor + 8, &ecx, 4);
+  vendor[12] = 0;
+
+  // get feature flags in ecx/edx, and family/model in eax
+  cpuid(eax, ebx, ecx, edx, 1);
+
+  int family = (eax >> 8) & 0xf;        // family and model fields
+  int model = (eax >> 4) & 0xf;
+  if (family == 0xf) {                  // use extended family and model fields
+    family += (eax >> 20) & 0xff;
+    model += ((eax >> 16) & 0xf) << 4;
+  }
+
+  // Opteron Rev E has a bug in which on very rare occasions a locked
+  // instruction doesn't act as a read-acquire barrier if followed by a
+  // non-locked read-modify-write instruction.  Rev F has this bug in
+  // pre-release versions, but not in versions released to customers,
+  // so we test only for Rev E, which is family 15, model 32..63 inclusive.
+  if (strcmp(vendor, "AuthenticAMD") == 0 &&       // AMD
+      family == 15 &&
+      32 <= model && model <= 63) {
+    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
+  } else {
+    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
+  }
+
+  // edx bit 26 is SSE2 which we use to tell use whether we can use mfence
+  AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
+}
+
+class AtomicOpsx86Initializer {
+ public:
+  AtomicOpsx86Initializer() {
+    AtomicOps_Internalx86CPUFeaturesInit();
+  }
+};
+
+// A global to get use initialized on startup via static initialization :/
+AtomicOpsx86Initializer g_initer;
+
+}  // namespace
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // __i386__
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h
new file mode 100644
index 0000000..edccc59
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h
@@ -0,0 +1,293 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This struct is not part of the public API of this module; clients may not
+// use it.
+// Features of this x86.  Values may not be correct before main() is run,
+// but are set conservatively.
+struct AtomicOps_x86CPUFeatureStruct {
+  bool has_amd_lock_mb_bug;  // Processor has AMD memory-barrier bug; do lfence
+                             // after acquire compare-and-swap.
+  bool has_sse2;             // Processor has SSE2.
+};
+extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+// 32-bit low-level operations on any platform.
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  __asm__ __volatile__("lock; cmpxchgl %1,%2"
+                       : "=a" (prev)
+                       : "q" (new_value), "m" (*ptr), "0" (old_value)
+                       : "memory");
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
+                       : "=r" (new_value)
+                       : "m" (*ptr), "0" (new_value)
+                       : "memory");
+  return new_value;  // Now it's the previous value.
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp = increment;
+  __asm__ __volatile__("lock; xaddl %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now holds the old value of *ptr
+  return temp + increment;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  Atomic32 temp = increment;
+  __asm__ __volatile__("lock; xaddl %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now holds the old value of *ptr
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return temp + increment;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return x;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+#if defined(__x86_64__)
+
+// 64-bit implementations of memory barrier can be simpler, because it
+// "mfence" is guaranteed to exist.
+inline void MemoryBarrier() {
+  __asm__ __volatile__("mfence" : : : "memory");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+#else
+
+inline void MemoryBarrier() {
+  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+    __asm__ __volatile__("mfence" : : : "memory");
+  } else {  // mfence is faster but not present on PIII
+    Atomic32 x = 0;
+    NoBarrier_AtomicExchange(&x, 0);  // acts as a barrier on PIII
+  }
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+    *ptr = value;
+    __asm__ __volatile__("mfence" : : : "memory");
+  } else {
+    NoBarrier_AtomicExchange(ptr, value);
+                          // acts as a barrier on PIII
+  }
+}
+#endif
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  *ptr = value;  // An x86 store acts as a release barrier.
+  // See comments in Atomic64 version of Release_Store(), below.
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;  // An x86 load acts as a acquire barrier.
+  // See comments in Atomic64 version of Release_Store(), below.
+  ATOMICOPS_COMPILER_BARRIER();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#if defined(__x86_64__)
+
+// 64-bit low-level operations on 64-bit platform.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  __asm__ __volatile__("lock; cmpxchgq %1,%2"
+                       : "=a" (prev)
+                       : "q" (new_value), "m" (*ptr), "0" (old_value)
+                       : "memory");
+  return prev;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
+                       : "=r" (new_value)
+                       : "m" (*ptr), "0" (new_value)
+                       : "memory");
+  return new_value;  // Now it's the previous value.
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 temp = increment;
+  __asm__ __volatile__("lock; xaddq %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now contains the previous value of *ptr
+  return temp + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  Atomic64 temp = increment;
+  __asm__ __volatile__("lock; xaddq %0,%1"
+                       : "+r" (temp), "+m" (*ptr)
+                       : : "memory");
+  // temp now contains the previous value of *ptr
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return temp + increment;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ATOMICOPS_COMPILER_BARRIER();
+
+  *ptr = value;  // An x86 store acts as a release barrier
+                 // for current AMD/Intel chips as of Jan 2008.
+                 // See also Acquire_Load(), below.
+
+  // When new chips come out, check:
+  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+  //  System Programming Guide, Chatper 7: Multiple-processor management,
+  //  Section 7.2, Memory Ordering.
+  // Last seen at:
+  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
+  //
+  // x86 stores/loads fail to act as barriers for a few instructions (clflush
+  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
+  // not generated by the compiler, and are rare.  Users of these instructions
+  // need to know about cache behaviour in any case since all of these involve
+  // either flushing cache lines or non-temporal cache hints.
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;  // An x86 load acts as a acquire barrier,
+                          // for current AMD/Intel chips as of Jan 2008.
+                          // See also Release_Store(), above.
+  ATOMICOPS_COMPILER_BARRIER();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+    __asm__ __volatile__("lfence" : : : "memory");
+  }
+  return x;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+#endif  // defined(__x86_64__)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
new file mode 100644
index 0000000..741b164
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
@@ -0,0 +1,112 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// The compilation of extension_set.cc fails when windows.h is included.
+// Therefore we move the code depending on windows.h to this separate cc file.
+
+// Don't compile this file for people not concerned about thread safety.
+#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+#include <google/protobuf/stubs/atomicops.h>
+
+#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
+
+#include <windows.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline void MemoryBarrier() {
+  // We use MemoryBarrier from WinNT.h
+  ::MemoryBarrier();
+}
+
+Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                  Atomic32 old_value,
+                                  Atomic32 new_value) {
+  LONG result = InterlockedCompareExchange(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(new_value),
+      static_cast<LONG>(old_value));
+  return static_cast<Atomic32>(result);
+}
+
+Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                  Atomic32 new_value) {
+  LONG result = InterlockedExchange(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(new_value));
+  return static_cast<Atomic32>(result);
+}
+
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                 Atomic32 increment) {
+  return InterlockedExchangeAdd(
+      reinterpret_cast<volatile LONG*>(ptr),
+      static_cast<LONG>(increment)) + increment;
+}
+
+#if defined(_WIN64)
+
+// 64-bit low-level operations on 64-bit platform.
+
+Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                  Atomic64 old_value,
+                                  Atomic64 new_value) {
+  PVOID result = InterlockedCompareExchangePointer(
+    reinterpret_cast<volatile PVOID*>(ptr),
+    reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
+  return reinterpret_cast<Atomic64>(result);
+}
+
+Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                  Atomic64 new_value) {
+  PVOID result = InterlockedExchangePointer(
+    reinterpret_cast<volatile PVOID*>(ptr),
+    reinterpret_cast<PVOID>(new_value));
+  return reinterpret_cast<Atomic64>(result);
+}
+
+Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                 Atomic64 increment) {
+  return InterlockedExchangeAdd64(
+      reinterpret_cast<volatile LONGLONG*>(ptr),
+      static_cast<LONGLONG>(increment)) + increment;
+}
+
+#endif  // defined(_WIN64)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
+#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h
new file mode 100644
index 0000000..e53a641
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h
@@ -0,0 +1,150 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
+#error "We require at least vs2005 for MemoryBarrier"
+#endif
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  NoBarrier_AtomicExchange(ptr, value);
+              // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
+  // See comments in Atomic64 version of Release_Store() below.
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#if defined(_WIN64)
+
+// 64-bit low-level operations on 64-bit platform.
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  NoBarrier_AtomicExchange(ptr, value);
+              // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
+
+  // When new chips come out, check:
+  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+  //  System Programming Guide, Chatper 7: Multiple-processor management,
+  //  Section 7.2, Memory Ordering.
+  // Last seen at:
+  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+#endif  // defined(_WIN64)
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.cc
new file mode 100644
index 0000000..f4af6a5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.cc
@@ -0,0 +1,196 @@
+// 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.
+
+#include <google/protobuf/stubs/bytestream.h>
+
+#include <string.h>
+#include <algorithm>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+void ByteSource::CopyTo(ByteSink* sink, size_t n) {
+  while (n > 0) {
+    StringPiece fragment = Peek();
+    if (fragment.empty()) {
+      GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
+      break;
+    }
+    std::size_t fragment_size = std::min<std::size_t>(n, fragment.size());
+    sink->Append(fragment.data(), fragment_size);
+    Skip(fragment_size);
+    n -= fragment_size;
+  }
+}
+
+void ByteSink::Flush() {}
+
+void UncheckedArrayByteSink::Append(const char* data, size_t n) {
+  if (data != dest_) {
+    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+    GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n)))
+        << "Append() data[] overlaps with dest_[]";
+    memcpy(dest_, data, n);
+  }
+  dest_ += n;
+}
+
+CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity)
+    : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) {
+}
+
+void CheckedArrayByteSink::Append(const char* bytes, size_t n) {
+  size_t available = capacity_ - size_;
+  if (n > available) {
+    n = available;
+    overflowed_ = true;
+  }
+  if (n > 0 && bytes != (outbuf_ + size_)) {
+    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+    GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_)))
+        << "Append() bytes[] overlaps with outbuf_[]";
+    memcpy(outbuf_ + size_, bytes, n);
+  }
+  size_ += n;
+}
+
+GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size)
+    : capacity_(estimated_size),
+      buf_(new char[estimated_size]),
+      size_(0) {
+}
+
+GrowingArrayByteSink::~GrowingArrayByteSink() {
+  delete[] buf_;  // Just in case the user didn't call GetBuffer.
+}
+
+void GrowingArrayByteSink::Append(const char* bytes, size_t n) {
+  size_t available = capacity_ - size_;
+  if (bytes != (buf_ + size_)) {
+    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+    // We need to test for this before calling Expand() which may reallocate.
+    GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_)))
+        << "Append() bytes[] overlaps with buf_[]";
+  }
+  if (n > available) {
+    Expand(n - available);
+  }
+  if (n > 0 && bytes != (buf_ + size_)) {
+    memcpy(buf_ + size_, bytes, n);
+  }
+  size_ += n;
+}
+
+char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) {
+  ShrinkToFit();
+  char* b = buf_;
+  *nbytes = size_;
+  buf_ = NULL;
+  size_ = capacity_ = 0;
+  return b;
+}
+
+void GrowingArrayByteSink::Expand(size_t amount) {  // Expand by at least 50%.
+  size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2);
+  char* bigger = new char[new_capacity];
+  memcpy(bigger, buf_, size_);
+  delete[] buf_;
+  buf_ = bigger;
+  capacity_ = new_capacity;
+}
+
+void GrowingArrayByteSink::ShrinkToFit() {
+  // Shrink only if the buffer is large and size_ is less than 3/4
+  // of capacity_.
+  if (capacity_ > 256 && size_ < (3 * capacity_) / 4) {
+    char* just_enough = new char[size_];
+    memcpy(just_enough, buf_, size_);
+    delete[] buf_;
+    buf_ = just_enough;
+    capacity_ = size_;
+  }
+}
+
+void StringByteSink::Append(const char* data, size_t n) {
+  dest_->append(data, n);
+}
+
+size_t ArrayByteSource::Available() const {
+  return input_.size();
+}
+
+StringPiece ArrayByteSource::Peek() {
+  return input_;
+}
+
+void ArrayByteSource::Skip(size_t n) {
+  GOOGLE_DCHECK_LE(n, input_.size());
+  input_.remove_prefix(n);
+}
+
+LimitByteSource::LimitByteSource(ByteSource *source, size_t limit)
+  : source_(source),
+    limit_(limit) {
+}
+
+size_t LimitByteSource::Available() const {
+  size_t available = source_->Available();
+  if (available > limit_) {
+    available = limit_;
+  }
+
+  return available;
+}
+
+StringPiece LimitByteSource::Peek() {
+  StringPiece piece(source_->Peek());
+  if (piece.size() > limit_) {
+    piece.set(piece.data(), limit_);
+  }
+
+  return piece;
+}
+
+void LimitByteSource::Skip(size_t n) {
+  GOOGLE_DCHECK_LE(n, limit_);
+  source_->Skip(n);
+  limit_ -= n;
+}
+
+void LimitByteSource::CopyTo(ByteSink *sink, size_t n) {
+  GOOGLE_DCHECK_LE(n, limit_);
+  source_->CopyTo(sink, n);
+  limit_ -= n;
+}
+
+}  // namespace strings
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.h
new file mode 100644
index 0000000..de8e020
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream.h
@@ -0,0 +1,348 @@
+// 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.
+
+// This file declares the ByteSink and ByteSource abstract interfaces. These
+// interfaces represent objects that consume (ByteSink) or produce (ByteSource)
+// a sequence of bytes. Using these abstract interfaces in your APIs can help
+// make your code work with a variety of input and output types.
+//
+// This file also declares the following commonly used implementations of these
+// interfaces.
+//
+//   ByteSink:
+//      UncheckedArrayByteSink  Writes to an array, without bounds checking
+//      CheckedArrayByteSink    Writes to an array, with bounds checking
+//      GrowingArrayByteSink    Allocates and writes to a growable buffer
+//      StringByteSink          Writes to an STL string
+//      NullByteSink            Consumes a never-ending stream of bytes
+//
+//   ByteSource:
+//      ArrayByteSource         Reads from an array or string/StringPiece
+//      LimitedByteSource       Limits the number of bytes read from an
+
+#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
+#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
+
+#include <stddef.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+class CordByteSink;
+class MemBlock;
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+// An abstract interface for an object that consumes a sequence of bytes. This
+// interface offers 3 different ways to append data, and a Flush() function.
+//
+// Example:
+//
+//   string my_data;
+//   ...
+//   ByteSink* sink = ...
+//   sink->Append(my_data.data(), my_data.size());
+//   sink->Flush();
+//
+class LIBPROTOBUF_EXPORT ByteSink {
+ public:
+  ByteSink() {}
+  virtual ~ByteSink() {}
+
+  // Appends the "n" bytes starting at "bytes".
+  virtual void Append(const char* bytes, size_t n) = 0;
+
+  // Flushes internal buffers. The default implemenation does nothing. ByteSink
+  // subclasses may use internal buffers that require calling Flush() at the end
+  // of the stream.
+  virtual void Flush();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink);
+};
+
+// An abstract interface for an object that produces a fixed-size sequence of
+// bytes.
+//
+// Example:
+//
+//   ByteSource* source = ...
+//   while (source->Available() > 0) {
+//     StringPiece data = source->Peek();
+//     ... do something with "data" ...
+//     source->Skip(data.length());
+//   }
+//
+class LIBPROTOBUF_EXPORT ByteSource {
+ public:
+  ByteSource() {}
+  virtual ~ByteSource() {}
+
+  // Returns the number of bytes left to read from the source. Available()
+  // should decrease by N each time Skip(N) is called. Available() may not
+  // increase. Available() returning 0 indicates that the ByteSource is
+  // exhausted.
+  //
+  // Note: Size() may have been a more appropriate name as it's more
+  //       indicative of the fixed-size nature of a ByteSource.
+  virtual size_t Available() const = 0;
+
+  // Returns a StringPiece of the next contiguous region of the source. Does not
+  // reposition the source. The returned region is empty iff Available() == 0.
+  //
+  // The returned region is valid until the next call to Skip() or until this
+  // object is destroyed, whichever occurs first.
+  //
+  // The length of the returned StringPiece will be <= Available().
+  virtual StringPiece Peek() = 0;
+
+  // Skips the next n bytes. Invalidates any StringPiece returned by a previous
+  // call to Peek().
+  //
+  // REQUIRES: Available() >= n
+  virtual void Skip(size_t n) = 0;
+
+  // Writes the next n bytes in this ByteSource to the given ByteSink, and
+  // advances this ByteSource past the copied bytes. The default implementation
+  // of this method just copies the bytes normally, but subclasses might
+  // override CopyTo to optimize certain cases.
+  //
+  // REQUIRES: Available() >= n
+  virtual void CopyTo(ByteSink* sink, size_t n);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
+};
+
+//
+// Some commonly used implementations of ByteSink
+//
+
+// Implementation of ByteSink that writes to an unsized byte array. No
+// bounds-checking is performed--it is the caller's responsibility to ensure
+// that the destination array is large enough.
+//
+// Example:
+//
+//   char buf[10];
+//   UncheckedArrayByteSink sink(buf);
+//   sink.Append("hi", 2);    // OK
+//   sink.Append(data, 100);  // WOOPS! Overflows buf[10].
+//
+class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
+ public:
+  explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
+  virtual void Append(const char* data, size_t n);
+
+  // Returns the current output pointer so that a caller can see how many bytes
+  // were produced.
+  //
+  // Note: this method is not part of the ByteSink interface.
+  char* CurrentDestination() const { return dest_; }
+
+ private:
+  char* dest_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
+};
+
+// Implementation of ByteSink that writes to a sized byte array. This sink will
+// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are
+// appended, subsequent bytes will be ignored and Overflowed() will return true.
+// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail).
+//
+// Example:
+//
+//   char buf[10];
+//   CheckedArrayByteSink sink(buf, 10);
+//   sink.Append("hi", 2);    // OK
+//   sink.Append(data, 100);  // Will only write 8 more bytes
+//
+class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
+ public:
+  CheckedArrayByteSink(char* outbuf, size_t capacity);
+  virtual void Append(const char* bytes, size_t n);
+
+  // Returns the number of bytes actually written to the sink.
+  size_t NumberOfBytesWritten() const { return size_; }
+
+  // Returns true if any bytes were discarded, i.e., if there was an
+  // attempt to write more than 'capacity' bytes.
+  bool Overflowed() const { return overflowed_; }
+
+ private:
+  char* outbuf_;
+  const size_t capacity_;
+  size_t size_;
+  bool overflowed_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink);
+};
+
+// Implementation of ByteSink that allocates an internal buffer (a char array)
+// and expands it as needed to accomodate appended data (similar to a string),
+// and allows the caller to take ownership of the internal buffer via the
+// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by
+// the caller with delete[]. GetBuffer() also sets the internal buffer to be
+// empty, and subsequent appends to the sink will create a new buffer. The
+// destructor will free the internal buffer if GetBuffer() was not called.
+//
+// Example:
+//
+//   GrowingArrayByteSink sink(10);
+//   sink.Append("hi", 2);
+//   sink.Append(data, n);
+//   const char* buf = sink.GetBuffer();  // Ownership transferred
+//   delete[] buf;
+//
+class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
+ public:
+  explicit GrowingArrayByteSink(size_t estimated_size);
+  virtual ~GrowingArrayByteSink();
+  virtual void Append(const char* bytes, size_t n);
+
+  // Returns the allocated buffer, and sets nbytes to its size. The caller takes
+  // ownership of the buffer and must delete it with delete[].
+  char* GetBuffer(size_t* nbytes);
+
+ private:
+  void Expand(size_t amount);
+  void ShrinkToFit();
+
+  size_t capacity_;
+  char* buf_;
+  size_t size_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
+};
+
+// Implementation of ByteSink that appends to the given string.
+// Existing contents of "dest" are not modified; new data is appended.
+//
+// Example:
+//
+//   string dest = "Hello ";
+//   StringByteSink sink(&dest);
+//   sink.Append("World", 5);
+//   assert(dest == "Hello World");
+//
+class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink {
+ public:
+  explicit StringByteSink(string* dest) : dest_(dest) {}
+  virtual void Append(const char* data, size_t n);
+
+ private:
+  string* dest_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
+};
+
+// Implementation of ByteSink that discards all data.
+//
+// Example:
+//
+//   NullByteSink sink;
+//   sink.Append(data, data.size());  // All data ignored.
+//
+class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink {
+ public:
+  NullByteSink() {}
+  virtual void Append(const char *data, size_t n) {}
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink);
+};
+
+//
+// Some commonly used implementations of ByteSource
+//
+
+// Implementation of ByteSource that reads from a StringPiece.
+//
+// Example:
+//
+//   string data = "Hello";
+//   ArrayByteSource source(data);
+//   assert(source.Available() == 5);
+//   assert(source.Peek() == "Hello");
+//
+class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource {
+ public:
+  explicit ArrayByteSource(StringPiece s) : input_(s) {}
+
+  virtual size_t Available() const;
+  virtual StringPiece Peek();
+  virtual void Skip(size_t n);
+
+ private:
+  StringPiece   input_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
+};
+
+// Implementation of ByteSource that wraps another ByteSource, limiting the
+// number of bytes returned.
+//
+// The caller maintains ownership of the underlying source, and may not use the
+// underlying source while using the LimitByteSource object.  The underlying
+// source's pointer is advanced by n bytes every time this LimitByteSource
+// object is advanced by n.
+//
+// Example:
+//
+//   string data = "Hello World";
+//   ArrayByteSource abs(data);
+//   assert(abs.Available() == data.size());
+//
+//   LimitByteSource limit(abs, 5);
+//   assert(limit.Available() == 5);
+//   assert(limit.Peek() == "Hello");
+//
+class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource {
+ public:
+  // Returns at most "limit" bytes from "source".
+  LimitByteSource(ByteSource* source, size_t limit);
+
+  virtual size_t Available() const;
+  virtual StringPiece Peek();
+  virtual void Skip(size_t n);
+
+  // We override CopyTo so that we can forward to the underlying source, in
+  // case it has an efficient implementation of CopyTo.
+  virtual void CopyTo(ByteSink* sink, size_t n);
+
+ private:
+  ByteSource* source_;
+  size_t limit_;
+};
+
+}  // namespace strings
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream_unittest.cc
new file mode 100644
index 0000000..06f114a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/bytestream_unittest.cc
@@ -0,0 +1,146 @@
+// 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.
+
+#include <google/protobuf/stubs/bytestream.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <algorithm>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+namespace {
+
+// We use this class instead of ArrayByteSource to simulate a ByteSource that
+// contains multiple fragments.  ArrayByteSource returns the entire array in
+// one fragment.
+class MockByteSource : public ByteSource {
+ public:
+  MockByteSource(StringPiece data, int block_size)
+    : data_(data), block_size_(block_size) {}
+
+  size_t Available() const { return data_.size(); }
+  StringPiece Peek() {
+    return data_.substr(0, block_size_);
+  }
+  void Skip(size_t n) { data_.remove_prefix(n); }
+
+ private:
+  StringPiece data_;
+  int block_size_;
+};
+
+TEST(ByteSourceTest, CopyTo) {
+  StringPiece data("Hello world!");
+  MockByteSource source(data, 3);
+  string str;
+  StringByteSink sink(&str);
+
+  source.CopyTo(&sink, data.size());
+  EXPECT_EQ(data, str);
+}
+
+TEST(ByteSourceTest, CopySubstringTo) {
+  StringPiece data("Hello world!");
+  MockByteSource source(data, 3);
+  source.Skip(1);
+  string str;
+  StringByteSink sink(&str);
+
+  source.CopyTo(&sink, data.size() - 2);
+  EXPECT_EQ(data.substr(1, data.size() - 2), str);
+  EXPECT_EQ("!", source.Peek());
+}
+
+TEST(ByteSourceTest, LimitByteSource) {
+  StringPiece data("Hello world!");
+  MockByteSource source(data, 3);
+  LimitByteSource limit_source(&source, 6);
+  EXPECT_EQ(6, limit_source.Available());
+  limit_source.Skip(1);
+  EXPECT_EQ(5, limit_source.Available());
+
+  {
+    string str;
+    StringByteSink sink(&str);
+    limit_source.CopyTo(&sink, limit_source.Available());
+    EXPECT_EQ("ello ", str);
+    EXPECT_EQ(0, limit_source.Available());
+    EXPECT_EQ(6, source.Available());
+  }
+
+  {
+    string str;
+    StringByteSink sink(&str);
+    source.CopyTo(&sink, source.Available());
+    EXPECT_EQ("world!", str);
+    EXPECT_EQ(0, source.Available());
+  }
+}
+
+TEST(ByteSourceTest, CopyToStringByteSink) {
+  StringPiece data("Hello world!");
+  MockByteSource source(data, 3);
+  string str;
+  StringByteSink sink(&str);
+  source.CopyTo(&sink, data.size());
+  EXPECT_EQ(data, str);
+}
+
+// Verify that ByteSink is subclassable and Flush() overridable.
+class FlushingByteSink : public StringByteSink {
+ public:
+  explicit FlushingByteSink(string* dest) : StringByteSink(dest) {}
+  virtual void Flush() { Append("z", 1); }
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink);
+};
+
+// Write and Flush via the ByteSink superclass interface.
+void WriteAndFlush(ByteSink* s) {
+  s->Append("abc", 3);
+  s->Flush();
+}
+
+TEST(ByteSinkTest, Flush) {
+  string str;
+  FlushingByteSink f_sink(&str);
+  WriteAndFlush(&f_sink);
+  EXPECT_STREQ("abcz", str.c_str());
+}
+
+}  // namespace
+}  // namespace strings
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/callback.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/callback.h
new file mode 100644
index 0000000..87271c5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/callback.h
@@ -0,0 +1,546 @@
+#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
+#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
+
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+// ===================================================================
+// emulates google3/base/callback.h
+
+namespace google {
+namespace protobuf {
+
+// Abstract interface for a callback.  When calling an RPC, you must provide
+// a Closure to call when the procedure completes.  See the Service interface
+// in service.h.
+//
+// To automatically construct a Closure which calls a particular function or
+// method with a particular set of parameters, use the NewCallback() function.
+// Example:
+//   void FooDone(const FooResponse* response) {
+//     ...
+//   }
+//
+//   void CallFoo() {
+//     ...
+//     // When done, call FooDone() and pass it a pointer to the response.
+//     Closure* callback = NewCallback(&FooDone, response);
+//     // Make the call.
+//     service->Foo(controller, request, response, callback);
+//   }
+//
+// Example that calls a method:
+//   class Handler {
+//    public:
+//     ...
+//
+//     void FooDone(const FooResponse* response) {
+//       ...
+//     }
+//
+//     void CallFoo() {
+//       ...
+//       // When done, call FooDone() and pass it a pointer to the response.
+//       Closure* callback = NewCallback(this, &Handler::FooDone, response);
+//       // Make the call.
+//       service->Foo(controller, request, response, callback);
+//     }
+//   };
+//
+// Currently NewCallback() supports binding zero, one, or two arguments.
+//
+// Callbacks created with NewCallback() automatically delete themselves when
+// executed.  They should be used when a callback is to be called exactly
+// once (usually the case with RPC callbacks).  If a callback may be called
+// a different number of times (including zero), create it with
+// NewPermanentCallback() instead.  You are then responsible for deleting the
+// callback (using the "delete" keyword as normal).
+//
+// Note that NewCallback() is a bit touchy regarding argument types.  Generally,
+// the values you provide for the parameter bindings must exactly match the
+// types accepted by the callback function.  For example:
+//   void Foo(string s);
+//   NewCallback(&Foo, "foo");          // WON'T WORK:  const char* != string
+//   NewCallback(&Foo, string("foo"));  // WORKS
+// Also note that the arguments cannot be references:
+//   void Foo(const string& s);
+//   string my_str;
+//   NewCallback(&Foo, my_str);  // WON'T WORK:  Can't use referecnes.
+// However, correctly-typed pointers will work just fine.
+class LIBPROTOBUF_EXPORT Closure {
+ public:
+  Closure() {}
+  virtual ~Closure();
+
+  virtual void Run() = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
+};
+
+template<typename R>
+class ResultCallback {
+ public:
+  ResultCallback() {}
+  virtual ~ResultCallback() {}
+
+  virtual R Run() = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
+};
+
+template<typename R, typename A1>
+class LIBPROTOBUF_EXPORT ResultCallback1 {
+ public:
+  ResultCallback1() {}
+  virtual ~ResultCallback1() {}
+
+  virtual R Run(A1) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
+};
+
+template<typename R, typename A1, typename A2>
+class LIBPROTOBUF_EXPORT ResultCallback2 {
+ public:
+  ResultCallback2() {}
+  virtual ~ResultCallback2() {}
+
+  virtual R Run(A1,A2) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
+};
+
+namespace internal {
+
+class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
+ public:
+  typedef void (*FunctionType)();
+
+  FunctionClosure0(FunctionType function, bool self_deleting)
+    : function_(function), self_deleting_(self_deleting) {}
+  ~FunctionClosure0();
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    function_();
+    if (needs_delete) delete this;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+};
+
+template <typename Class>
+class MethodClosure0 : public Closure {
+ public:
+  typedef void (Class::*MethodType)();
+
+  MethodClosure0(Class* object, MethodType method, bool self_deleting)
+    : object_(object), method_(method), self_deleting_(self_deleting) {}
+  ~MethodClosure0() {}
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    (object_->*method_)();
+    if (needs_delete) delete this;
+  }
+
+ private:
+  Class* object_;
+  MethodType method_;
+  bool self_deleting_;
+};
+
+template <typename Arg1>
+class FunctionClosure1 : public Closure {
+ public:
+  typedef void (*FunctionType)(Arg1 arg1);
+
+  FunctionClosure1(FunctionType function, bool self_deleting,
+                   Arg1 arg1)
+    : function_(function), self_deleting_(self_deleting),
+      arg1_(arg1) {}
+  ~FunctionClosure1() {}
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    function_(arg1_);
+    if (needs_delete) delete this;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+  Arg1 arg1_;
+};
+
+template <typename Class, typename Arg1>
+class MethodClosure1 : public Closure {
+ public:
+  typedef void (Class::*MethodType)(Arg1 arg1);
+
+  MethodClosure1(Class* object, MethodType method, bool self_deleting,
+                 Arg1 arg1)
+    : object_(object), method_(method), self_deleting_(self_deleting),
+      arg1_(arg1) {}
+  ~MethodClosure1() {}
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    (object_->*method_)(arg1_);
+    if (needs_delete) delete this;
+  }
+
+ private:
+  Class* object_;
+  MethodType method_;
+  bool self_deleting_;
+  Arg1 arg1_;
+};
+
+template <typename Arg1, typename Arg2>
+class FunctionClosure2 : public Closure {
+ public:
+  typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
+
+  FunctionClosure2(FunctionType function, bool self_deleting,
+                   Arg1 arg1, Arg2 arg2)
+    : function_(function), self_deleting_(self_deleting),
+      arg1_(arg1), arg2_(arg2) {}
+  ~FunctionClosure2() {}
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    function_(arg1_, arg2_);
+    if (needs_delete) delete this;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+};
+
+template <typename Class, typename Arg1, typename Arg2>
+class MethodClosure2 : public Closure {
+ public:
+  typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
+
+  MethodClosure2(Class* object, MethodType method, bool self_deleting,
+                 Arg1 arg1, Arg2 arg2)
+    : object_(object), method_(method), self_deleting_(self_deleting),
+      arg1_(arg1), arg2_(arg2) {}
+  ~MethodClosure2() {}
+
+  void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    (object_->*method_)(arg1_, arg2_);
+    if (needs_delete) delete this;
+  }
+
+ private:
+  Class* object_;
+  MethodType method_;
+  bool self_deleting_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+};
+
+template<typename R>
+class FunctionResultCallback_0_0 : public ResultCallback<R> {
+ public:
+  typedef R (*FunctionType)();
+
+  FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
+      : function_(function), self_deleting_(self_deleting) {}
+  ~FunctionResultCallback_0_0() {}
+
+  R Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    R result = function_();
+    if (needs_delete) delete this;
+    return result;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+};
+
+template<typename R, typename P1>
+class FunctionResultCallback_1_0 : public ResultCallback<R> {
+ public:
+  typedef R (*FunctionType)(P1);
+
+  FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
+                             P1 p1)
+      : function_(function), self_deleting_(self_deleting), p1_(p1) {}
+  ~FunctionResultCallback_1_0() {}
+
+  R Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    R result = function_(p1_);
+    if (needs_delete) delete this;
+    return result;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+  P1 p1_;
+};
+
+template<typename R, typename Arg1>
+class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
+ public:
+  typedef R (*FunctionType)(Arg1 arg1);
+
+  FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
+      : function_(function), self_deleting_(self_deleting) {}
+  ~FunctionResultCallback_0_1() {}
+
+  R Run(Arg1 a1) {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    R result = function_(a1);
+    if (needs_delete) delete this;
+    return result;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+};
+
+template<typename R, typename P1, typename A1>
+class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
+ public:
+  typedef R (*FunctionType)(P1, A1);
+
+  FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
+                             P1 p1)
+      : function_(function), self_deleting_(self_deleting), p1_(p1) {}
+  ~FunctionResultCallback_1_1() {}
+
+  R Run(A1 a1) {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
+    R result = function_(p1_, a1);
+    if (needs_delete) delete this;
+    return result;
+  }
+
+ private:
+  FunctionType function_;
+  bool self_deleting_;
+  P1 p1_;
+};
+
+template <typename T>
+struct InternalConstRef {
+  typedef typename remove_reference<T>::type base_type;
+  typedef const base_type& type;
+};
+
+template <typename R, typename T, typename P1, typename P2, typename P3,
+          typename P4, typename P5, typename A1, typename A2>
+class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
+ public:
+  typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2);
+  MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting,
+                           P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
+      : object_(object),
+        method_(method),
+        self_deleting_(self_deleting),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5) {}
+  ~MethodResultCallback_5_2() {}
+
+  R Run(A1 a1, A2 a2) {
+    bool needs_delete = self_deleting_;
+    R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2);
+    if (needs_delete) delete this;
+    return result;
+  }
+
+ private:
+  T* object_;
+  MethodType method_;
+  bool self_deleting_;
+  typename remove_reference<P1>::type p1_;
+  typename remove_reference<P2>::type p2_;
+  typename remove_reference<P3>::type p3_;
+  typename remove_reference<P4>::type p4_;
+  typename remove_reference<P5>::type p5_;
+};
+
+// See Closure.
+inline Closure* NewCallback(void (*function)()) {
+  return new internal::FunctionClosure0(function, true);
+}
+
+// See Closure.
+inline Closure* NewPermanentCallback(void (*function)()) {
+  return new internal::FunctionClosure0(function, false);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewCallback(Class* object, void (Class::*method)()) {
+  return new internal::MethodClosure0<Class>(object, method, true);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
+  return new internal::MethodClosure0<Class>(object, method, false);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewCallback(void (*function)(Arg1),
+                            Arg1 arg1) {
+  return new internal::FunctionClosure1<Arg1>(function, true, arg1);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewPermanentCallback(void (*function)(Arg1),
+                                     Arg1 arg1) {
+  return new internal::FunctionClosure1<Arg1>(function, false, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
+                            Arg1 arg1) {
+  return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
+                                     Arg1 arg1) {
+  return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewCallback(void (*function)(Arg1, Arg2),
+                            Arg1 arg1, Arg2 arg2) {
+  return new internal::FunctionClosure2<Arg1, Arg2>(
+    function, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
+                                     Arg1 arg1, Arg2 arg2) {
+  return new internal::FunctionClosure2<Arg1, Arg2>(
+    function, false, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
+                            Arg1 arg1, Arg2 arg2) {
+  return new internal::MethodClosure2<Class, Arg1, Arg2>(
+    object, method, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(
+    Class* object, void (Class::*method)(Arg1, Arg2),
+    Arg1 arg1, Arg2 arg2) {
+  return new internal::MethodClosure2<Class, Arg1, Arg2>(
+    object, method, false, arg1, arg2);
+}
+
+// See ResultCallback
+template<typename R>
+inline ResultCallback<R>* NewCallback(R (*function)()) {
+  return new internal::FunctionResultCallback_0_0<R>(function, true);
+}
+
+// See ResultCallback
+template<typename R>
+inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
+  return new internal::FunctionResultCallback_0_0<R>(function, false);
+}
+
+// See ResultCallback
+template<typename R, typename P1>
+inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
+  return new internal::FunctionResultCallback_1_0<R, P1>(
+      function, true, p1);
+}
+
+// See ResultCallback
+template<typename R, typename P1>
+inline ResultCallback<R>* NewPermanentCallback(
+    R (*function)(P1), P1 p1) {
+  return new internal::FunctionResultCallback_1_0<R, P1>(
+      function, false, p1);
+}
+
+// See ResultCallback1
+template<typename R, typename A1>
+inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
+  return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
+}
+
+// See ResultCallback1
+template<typename R, typename A1>
+inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
+  return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
+}
+
+// See ResultCallback1
+template<typename R, typename P1, typename A1>
+inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
+  return new internal::FunctionResultCallback_1_1<R, P1, A1>(
+      function, true, p1);
+}
+
+// See ResultCallback1
+template<typename R, typename P1, typename A1>
+inline ResultCallback1<R, A1>* NewPermanentCallback(
+    R (*function)(P1, A1), P1 p1) {
+  return new internal::FunctionResultCallback_1_1<R, P1, A1>(
+      function, false, p1);
+}
+
+// See MethodResultCallback_5_2
+template <typename R, typename T, typename P1, typename P2, typename P3,
+          typename P4, typename P5, typename A1, typename A2>
+inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
+    T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2),
+    typename internal::InternalConstRef<P1>::type p1,
+    typename internal::InternalConstRef<P2>::type p2,
+    typename internal::InternalConstRef<P3>::type p3,
+    typename internal::InternalConstRef<P4>::type p4,
+    typename internal::InternalConstRef<P5>::type p5) {
+  return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1,
+                                                A2>(object, function, false, p1,
+                                                    p2, p3, p4, p5);
+}
+
+}  // namespace internal
+
+// A function which does nothing.  Useful for creating no-op callbacks, e.g.:
+//   Closure* nothing = NewCallback(&DoNothing);
+void LIBPROTOBUF_EXPORT DoNothing();
+
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/casts.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/casts.h
new file mode 100644
index 0000000..be65284
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/casts.h
@@ -0,0 +1,133 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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_CASTS_H__
+#define GOOGLE_PROTOBUF_CASTS_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Use implicit_cast as a safe version of static_cast or const_cast
+// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
+// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
+// a const pointer to Foo).
+// When you use implicit_cast, the compiler checks that the cast is safe.
+// Such explicit implicit_casts are necessary in surprisingly many
+// situations where C++ demands an exact type match instead of an
+// argument type convertable to a target type.
+//
+// The From type can be inferred, so the preferred syntax for using
+// implicit_cast is the same as for static_cast etc.:
+//
+//   implicit_cast<ToType>(expr)
+//
+// implicit_cast would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+template<typename To, typename From>
+inline To implicit_cast(From const &f) {
+  return f;
+}
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+
+template<typename To, typename From>     // use like this: down_cast<T*>(foo);
+inline To down_cast(From* f) {                   // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    implicit_cast<From*, To>(0);
+  }
+
+#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+  assert(f == NULL || dynamic_cast<To>(f) != NULL);  // RTTI: debug mode only!
+#endif
+  return static_cast<To>(f);
+}
+
+template<typename To, typename From>    // use like this: down_cast<T&>(foo);
+inline To down_cast(From& f) {
+  typedef typename remove_reference<To>::type* ToAsPointer;
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    implicit_cast<From*, ToAsPointer>(0);
+  }
+
+#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+  // RTTI: debug mode only!
+  assert(dynamic_cast<ToAsPointer>(&f) != NULL);
+#endif
+  return *static_cast<ToAsPointer>(&f);
+}
+
+template<typename To, typename From>
+inline To bit_cast(const From& from) {
+  GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
+                        bit_cast_with_different_sizes);
+  To dest;
+  memcpy(&dest, &from, sizeof(dest));
+  return dest;
+}
+
+}  // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::implicit_cast;
+using internal::down_cast;
+using internal::bit_cast;
+
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_CASTS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/common.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/common.cc
new file mode 100644
index 0000000..54dbafa
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/common.cc
@@ -0,0 +1,459 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/int128.h>
+#include <errno.h>
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN  // We only need minimal includes
+#include <windows.h>
+#define snprintf _snprintf    // see comment in strutil.cc
+#elif defined(HAVE_PTHREAD)
+#include <pthread.h>
+#else
+#error "No suitable threading library available."
+#endif
+#if defined(__ANDROID__)
+#include <android/log.h>
+#endif
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+void VerifyVersion(int headerVersion,
+                   int minLibraryVersion,
+                   const char* filename) {
+  if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) {
+    // Library is too old for headers.
+    GOOGLE_LOG(FATAL)
+      << "This program requires version " << VersionString(minLibraryVersion)
+      << " of the Protocol Buffer runtime library, but the installed version "
+         "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ".  Please update "
+         "your library.  If you compiled the program yourself, make sure that "
+         "your headers are from the same version of Protocol Buffers as your "
+         "link-time library.  (Version verification failed in \""
+      << filename << "\".)";
+  }
+  if (headerVersion < kMinHeaderVersionForLibrary) {
+    // Headers are too old for library.
+    GOOGLE_LOG(FATAL)
+      << "This program was compiled against version "
+      << VersionString(headerVersion) << " of the Protocol Buffer runtime "
+         "library, which is not compatible with the installed version ("
+      << VersionString(GOOGLE_PROTOBUF_VERSION) <<  ").  Contact the program "
+         "author for an update.  If you compiled the program yourself, make "
+         "sure that your headers are from the same version of Protocol Buffers "
+         "as your link-time library.  (Version verification failed in \""
+      << filename << "\".)";
+  }
+}
+
+string VersionString(int version) {
+  int major = version / 1000000;
+  int minor = (version / 1000) % 1000;
+  int micro = version % 1000;
+
+  // 128 bytes should always be enough, but we use snprintf() anyway to be
+  // safe.
+  char buffer[128];
+  snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro);
+
+  // Guard against broken MSVC snprintf().
+  buffer[sizeof(buffer)-1] = '\0';
+
+  return buffer;
+}
+
+}  // namespace internal
+
+// ===================================================================
+// emulates google3/base/logging.cc
+
+namespace internal {
+#if defined(__ANDROID__)
+inline void DefaultLogHandler(LogLevel level, const char* filename, int line,
+                              const string& message) {
+#ifdef GOOGLE_PROTOBUF_MIN_LOG_LEVEL
+  if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
+    return;
+  }
+  static const char* level_names[] = {"INFO", "WARNING", "ERROR", "FATAL"};
+
+  static const int android_log_levels[] = {
+      ANDROID_LOG_INFO,   // LOG(INFO),
+      ANDROID_LOG_WARN,   // LOG(WARNING)
+      ANDROID_LOG_ERROR,  // LOG(ERROR)
+      ANDROID_LOG_FATAL,  // LOG(FATAL)
+  };
+
+  // Bound the logging level.
+  const int android_log_level = android_log_levels[level];
+  ::std::ostringstream ostr;
+  ostr << "[libprotobuf " << level_names[level] << " " << filename << ":"
+       << line << "] " << message.c_str();
+
+  // Output the log string the Android log at the appropriate level.
+  __android_log_write(android_log_level, "libprotobuf-native",
+                      ostr.str().c_str());
+  // Also output to std::cerr.
+  fprintf(stderr, "%s", ostr.str().c_str());
+  fflush(stderr);
+
+  // Indicate termination if needed.
+  if (android_log_level == ANDROID_LOG_FATAL) {
+    __android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native",
+                        "terminating.\n");
+  }
+#endif
+}
+#else
+void DefaultLogHandler(LogLevel level, const char* filename, int line,
+                       const string& message) {
+  static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
+
+  // We use fprintf() instead of cerr because we want this to work at static
+  // initialization time.
+  fprintf(stderr, "[libprotobuf %s %s:%d] %s\n",
+          level_names[level], filename, line, message.c_str());
+  fflush(stderr);  // Needed on MSVC.
+}
+#endif
+
+void NullLogHandler(LogLevel /* level */, const char* /* filename */,
+                    int /* line */, const string& /* message */) {
+  // Nothing.
+}
+
+static LogHandler* log_handler_ = &DefaultLogHandler;
+static int log_silencer_count_ = 0;
+
+static Mutex* log_silencer_count_mutex_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_);
+
+void DeleteLogSilencerCount() {
+  delete log_silencer_count_mutex_;
+  log_silencer_count_mutex_ = NULL;
+}
+void InitLogSilencerCount() {
+  log_silencer_count_mutex_ = new Mutex;
+  OnShutdown(&DeleteLogSilencerCount);
+}
+void InitLogSilencerCountOnce() {
+  GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
+}
+
+LogMessage& LogMessage::operator<<(const string& value) {
+  message_ += value;
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(const char* value) {
+  message_ += value;
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(const StringPiece& value) {
+  message_ += value.ToString();
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(
+    const ::google::protobuf::util::Status& status) {
+  message_ += status.ToString();
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(const uint128& value) {
+  std::ostringstream str;
+  str << value;
+  message_ += str.str();
+  return *this;
+}
+
+// Since this is just for logging, we don't care if the current locale changes
+// the results -- in fact, we probably prefer that.  So we use snprintf()
+// instead of Simple*toa().
+#undef DECLARE_STREAM_OPERATOR
+#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT)                       \
+  LogMessage& LogMessage::operator<<(TYPE value) {                  \
+    /* 128 bytes should be big enough for any of the primitive */   \
+    /* values which we print with this, but well use snprintf() */  \
+    /* anyway to be extra safe. */                                  \
+    char buffer[128];                                               \
+    snprintf(buffer, sizeof(buffer), FORMAT, value);                \
+    /* Guard against broken MSVC snprintf(). */                     \
+    buffer[sizeof(buffer)-1] = '\0';                                \
+    message_ += buffer;                                             \
+    return *this;                                                   \
+  }
+
+DECLARE_STREAM_OPERATOR(char         , "%c" )
+DECLARE_STREAM_OPERATOR(int          , "%d" )
+DECLARE_STREAM_OPERATOR(unsigned int , "%u" )
+DECLARE_STREAM_OPERATOR(long         , "%ld")
+DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
+DECLARE_STREAM_OPERATOR(double       , "%g" )
+DECLARE_STREAM_OPERATOR(void*        , "%p" )
+DECLARE_STREAM_OPERATOR(long long         , "%" GOOGLE_LL_FORMAT "d")
+DECLARE_STREAM_OPERATOR(unsigned long long, "%" GOOGLE_LL_FORMAT "u")
+#undef DECLARE_STREAM_OPERATOR
+
+LogMessage::LogMessage(LogLevel level, const char* filename, int line)
+  : level_(level), filename_(filename), line_(line) {}
+LogMessage::~LogMessage() {}
+
+void LogMessage::Finish() {
+  bool suppress = false;
+
+  if (level_ != LOGLEVEL_FATAL) {
+    InitLogSilencerCountOnce();
+    MutexLock lock(log_silencer_count_mutex_);
+    suppress = log_silencer_count_ > 0;
+  }
+
+  if (!suppress) {
+    log_handler_(level_, filename_, line_, message_);
+  }
+
+  if (level_ == LOGLEVEL_FATAL) {
+#if PROTOBUF_USE_EXCEPTIONS
+    throw FatalException(filename_, line_, message_);
+#else
+    abort();
+#endif
+  }
+}
+
+void LogFinisher::operator=(LogMessage& other) {
+  other.Finish();
+}
+
+}  // namespace internal
+
+LogHandler* SetLogHandler(LogHandler* new_func) {
+  LogHandler* old = internal::log_handler_;
+  if (old == &internal::NullLogHandler) {
+    old = NULL;
+  }
+  if (new_func == NULL) {
+    internal::log_handler_ = &internal::NullLogHandler;
+  } else {
+    internal::log_handler_ = new_func;
+  }
+  return old;
+}
+
+LogSilencer::LogSilencer() {
+  internal::InitLogSilencerCountOnce();
+  MutexLock lock(internal::log_silencer_count_mutex_);
+  ++internal::log_silencer_count_;
+};
+
+LogSilencer::~LogSilencer() {
+  internal::InitLogSilencerCountOnce();
+  MutexLock lock(internal::log_silencer_count_mutex_);
+  --internal::log_silencer_count_;
+};
+
+// ===================================================================
+// emulates google3/base/callback.cc
+
+Closure::~Closure() {}
+
+namespace internal { FunctionClosure0::~FunctionClosure0() {} }
+
+void DoNothing() {}
+
+// ===================================================================
+// emulates google3/base/mutex.cc
+
+#ifdef _WIN32
+
+struct Mutex::Internal {
+  CRITICAL_SECTION mutex;
+#ifndef NDEBUG
+  // Used only to implement AssertHeld().
+  DWORD thread_id;
+#endif
+};
+
+Mutex::Mutex()
+  : mInternal(new Internal) {
+  InitializeCriticalSection(&mInternal->mutex);
+}
+
+Mutex::~Mutex() {
+  DeleteCriticalSection(&mInternal->mutex);
+  delete mInternal;
+}
+
+void Mutex::Lock() {
+  EnterCriticalSection(&mInternal->mutex);
+#ifndef NDEBUG
+  mInternal->thread_id = GetCurrentThreadId();
+#endif
+}
+
+void Mutex::Unlock() {
+#ifndef NDEBUG
+  mInternal->thread_id = 0;
+#endif
+  LeaveCriticalSection(&mInternal->mutex);
+}
+
+void Mutex::AssertHeld() {
+#ifndef NDEBUG
+  GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId());
+#endif
+}
+
+#elif defined(HAVE_PTHREAD)
+
+struct Mutex::Internal {
+  pthread_mutex_t mutex;
+};
+
+Mutex::Mutex()
+  : mInternal(new Internal) {
+  pthread_mutex_init(&mInternal->mutex, NULL);
+}
+
+Mutex::~Mutex() {
+  pthread_mutex_destroy(&mInternal->mutex);
+  delete mInternal;
+}
+
+void Mutex::Lock() {
+  int result = pthread_mutex_lock(&mInternal->mutex);
+  if (result != 0) {
+    GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result);
+  }
+}
+
+void Mutex::Unlock() {
+  int result = pthread_mutex_unlock(&mInternal->mutex);
+  if (result != 0) {
+    GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result);
+  }
+}
+
+void Mutex::AssertHeld() {
+  // pthreads dosn't provide a way to check which thread holds the mutex.
+  // TODO(kenton):  Maybe keep track of locking thread ID like with WIN32?
+}
+
+#endif
+
+// ===================================================================
+// emulates google3/util/endian/endian.h
+//
+// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
+// google/protobuf/io/coded_stream.h and therefore can not be used here.
+// Maybe move that macro definition here in the furture.
+uint32 ghtonl(uint32 x) {
+  union {
+    uint32 result;
+    uint8 result_array[4];
+  };
+  result_array[0] = static_cast<uint8>(x >> 24);
+  result_array[1] = static_cast<uint8>((x >> 16) & 0xFF);
+  result_array[2] = static_cast<uint8>((x >> 8) & 0xFF);
+  result_array[3] = static_cast<uint8>(x & 0xFF);
+  return result;
+}
+
+// ===================================================================
+// Shutdown support.
+
+namespace internal {
+
+typedef void OnShutdownFunc();
+vector<void (*)()>* shutdown_functions = NULL;
+Mutex* shutdown_functions_mutex = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init);
+
+void InitShutdownFunctions() {
+  shutdown_functions = new vector<void (*)()>;
+  shutdown_functions_mutex = new Mutex;
+}
+
+inline void InitShutdownFunctionsOnce() {
+  GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions);
+}
+
+void OnShutdown(void (*func)()) {
+  InitShutdownFunctionsOnce();
+  MutexLock lock(shutdown_functions_mutex);
+  shutdown_functions->push_back(func);
+}
+
+}  // namespace internal
+
+void ShutdownProtobufLibrary() {
+  internal::InitShutdownFunctionsOnce();
+
+  // We don't need to lock shutdown_functions_mutex because it's up to the
+  // caller to make sure that no one is using the library before this is
+  // called.
+
+  // Make it safe to call this multiple times.
+  if (internal::shutdown_functions == NULL) return;
+
+  for (int i = 0; i < internal::shutdown_functions->size(); i++) {
+    internal::shutdown_functions->at(i)();
+  }
+  delete internal::shutdown_functions;
+  internal::shutdown_functions = NULL;
+  delete internal::shutdown_functions_mutex;
+  internal::shutdown_functions_mutex = NULL;
+}
+
+#if PROTOBUF_USE_EXCEPTIONS
+FatalException::~FatalException() throw() {}
+
+const char* FatalException::what() const throw() {
+  return message_.c_str();
+}
+#endif
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/common.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/common.h
new file mode 100644
index 0000000..9c05cac
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/common.h
@@ -0,0 +1,225 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda) and others
+//
+// Contains basic types and utilities used by the rest of the library.
+
+#ifndef GOOGLE_PROTOBUF_COMMON_H__
+#define GOOGLE_PROTOBUF_COMMON_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/platform_macros.h>
+
+// TODO(liujisi): Remove the following includes after the include clean-up.
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/callback.h>
+
+#ifndef PROTOBUF_USE_EXCEPTIONS
+#if defined(_MSC_VER) && defined(_CPPUNWIND)
+  #define PROTOBUF_USE_EXCEPTIONS 1
+#elif defined(__EXCEPTIONS)
+  #define PROTOBUF_USE_EXCEPTIONS 1
+#else
+  #define PROTOBUF_USE_EXCEPTIONS 0
+#endif
+#endif
+
+#if PROTOBUF_USE_EXCEPTIONS
+#include <exception>
+#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h>  // for TARGET_OS_IPHONE
+#endif
+
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+#include <pthread.h>
+#endif
+
+#if defined(_WIN32) && defined(GetMessage)
+// Allow GetMessage to be used as a valid method name in protobuf classes.
+// windows.h defines GetMessage() as a macro.  Let's re-define it as an inline
+// function.  The inline function should be equivalent for C++ users.
+inline BOOL GetMessage_Win32(
+    LPMSG lpMsg, HWND hWnd,
+    UINT wMsgFilterMin, UINT wMsgFilterMax) {
+  return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+#undef GetMessage
+inline BOOL GetMessage(
+    LPMSG lpMsg, HWND hWnd,
+    UINT wMsgFilterMin, UINT wMsgFilterMax) {
+  return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+#endif
+
+namespace std {}
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Some of these constants are macros rather than const ints so that they can
+// be used in #if directives.
+
+// The current version, represented as a single integer to make comparison
+// easier:  major * 10^6 + minor * 10^3 + micro
+#define GOOGLE_PROTOBUF_VERSION 3000000
+
+// The minimum library version which works with the current version of the
+// headers.
+#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3000000
+
+// The minimum header version which works with the current version of
+// the library.  This constant should only be used by protoc's C++ code
+// generator.
+static const int kMinHeaderVersionForLibrary = 3000000;
+
+// The minimum protoc version which works with the current version of the
+// headers.
+#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3000000
+
+// The minimum header version which works with the current version of
+// protoc.  This constant should only be used in VerifyVersion().
+static const int kMinHeaderVersionForProtoc = 3000000;
+
+// Verifies that the headers and libraries are compatible.  Use the macro
+// below to call this.
+void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion,
+                                      const char* filename);
+
+// Converts a numeric version number to a string.
+std::string LIBPROTOBUF_EXPORT VersionString(int version);
+
+}  // namespace internal
+
+// Place this macro in your main() function (or somewhere before you attempt
+// to use the protobuf library) to verify that the version you link against
+// matches the headers you compiled against.  If a version mismatch is
+// detected, the process will abort.
+#define GOOGLE_PROTOBUF_VERIFY_VERSION                                    \
+  ::google::protobuf::internal::VerifyVersion(                            \
+    GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION,         \
+    __FILE__)
+
+
+// ===================================================================
+// from google3/util/utf8/public/unilib.h
+
+class StringPiece;
+namespace internal {
+
+// Checks if the buffer contains structurally-valid UTF-8.  Implemented in
+// structurally_valid.cc.
+LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
+
+inline bool IsStructurallyValidUTF8(const std::string& str) {
+  return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
+}
+
+// Returns initial number of bytes of structually valid UTF-8.
+LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str);
+
+// Coerce UTF-8 byte string in src_str to be
+// a structurally-valid equal-length string by selectively
+// overwriting illegal bytes with replace_char (typically ' ' or '?').
+// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
+// src_str is read-only.
+//
+// Returns pointer to output buffer, src_str.data() if no changes were made,
+//  or idst if some bytes were changed. idst is allocated by the caller
+//  and must be at least as big as src_str
+//
+// Optimized for: all structurally valid and no byte copying is done.
+//
+LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
+    const StringPiece& str, char* dst, char replace_char);
+
+}  // namespace internal
+
+
+// ===================================================================
+// Shutdown support.
+
+// Shut down the entire protocol buffers library, deleting all static-duration
+// objects allocated by the library or by generated .pb.cc files.
+//
+// There are two reasons you might want to call this:
+// * You use a draconian definition of "memory leak" in which you expect
+//   every single malloc() to have a corresponding free(), even for objects
+//   which live until program exit.
+// * You are writing a dynamically-loaded library which needs to clean up
+//   after itself when the library is unloaded.
+//
+// It is safe to call this multiple times.  However, it is not safe to use
+// any other part of the protocol buffers library after
+// ShutdownProtobufLibrary() has been called.
+LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary();
+
+namespace internal {
+
+// Register a function to be called when ShutdownProtocolBuffers() is called.
+LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
+
+}  // namespace internal
+
+#if PROTOBUF_USE_EXCEPTIONS
+class FatalException : public std::exception {
+ public:
+  FatalException(const char* filename, int line, const std::string& message)
+      : filename_(filename), line_(line), message_(message) {}
+  virtual ~FatalException() throw();
+
+  virtual const char* what() const throw();
+
+  const char* filename() const { return filename_; }
+  int line() const { return line_; }
+  const std::string& message() const { return message_; }
+
+ private:
+  const char* filename_;
+  const int line_;
+  const std::string message_;
+};
+#endif
+
+// This is at the end of the file instead of the beginning to work around a bug
+// in some versions of MSVC.
+using namespace std;  // Don't do this at home, kids.
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMMON_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/common_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/common_unittest.cc
new file mode 100644
index 0000000..25bae9b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/common_unittest.cc
@@ -0,0 +1,358 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <vector>
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+using internal::NewCallback;
+using internal::NewPermanentCallback;
+namespace {
+
+// TODO(kenton):  More tests.
+
+#ifdef PACKAGE_VERSION  // only defined when using automake, not MSVC
+
+TEST(VersionTest, VersionMatchesConfig) {
+  // Verify that the version string specified in config.h matches the one
+  // in common.h.  The config.h version is a string which may have a suffix
+  // like "beta" or "rc1", so we remove that.
+  string version = PACKAGE_VERSION;
+  int pos = 0;
+  while (pos < version.size() &&
+         (ascii_isdigit(version[pos]) || version[pos] == '.')) {
+    ++pos;
+  }
+  version.erase(pos);
+
+  EXPECT_EQ(version, internal::VersionString(GOOGLE_PROTOBUF_VERSION));
+}
+
+#endif  // PACKAGE_VERSION
+
+TEST(CommonTest, IntMinMaxConstants) {
+  // kint32min was declared incorrectly in the first release of protobufs.
+  // Ugh.
+  EXPECT_LT(kint32min, kint32max);
+  EXPECT_EQ(static_cast<uint32>(kint32min), static_cast<uint32>(kint32max) + 1);
+  EXPECT_LT(kint64min, kint64max);
+  EXPECT_EQ(static_cast<uint64>(kint64min), static_cast<uint64>(kint64max) + 1);
+  EXPECT_EQ(0, kuint32max + 1);
+  EXPECT_EQ(0, kuint64max + 1);
+}
+
+vector<string> captured_messages_;
+
+void CaptureLog(LogLevel level, const char* filename, int line,
+                const string& message) {
+  captured_messages_.push_back(
+    strings::Substitute("$0 $1:$2: $3",
+      implicit_cast<int>(level), filename, line, message));
+}
+
+TEST(LoggingTest, DefaultLogging) {
+  CaptureTestStderr();
+  int line = __LINE__;
+  GOOGLE_LOG(INFO   ) << "A message.";
+  GOOGLE_LOG(WARNING) << "A warning.";
+  GOOGLE_LOG(ERROR  ) << "An error.";
+
+  string text = GetCapturedTestStderr();
+  EXPECT_EQ(
+    "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n"
+    "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n"
+    "[libprotobuf ERROR " __FILE__ ":" + SimpleItoa(line + 3) + "] An error.\n",
+    text);
+}
+
+TEST(LoggingTest, NullLogging) {
+  LogHandler* old_handler = SetLogHandler(NULL);
+
+  CaptureTestStderr();
+  GOOGLE_LOG(INFO   ) << "A message.";
+  GOOGLE_LOG(WARNING) << "A warning.";
+  GOOGLE_LOG(ERROR  ) << "An error.";
+
+  EXPECT_TRUE(SetLogHandler(old_handler) == NULL);
+
+  string text = GetCapturedTestStderr();
+  EXPECT_EQ("", text);
+}
+
+TEST(LoggingTest, CaptureLogging) {
+  captured_messages_.clear();
+
+  LogHandler* old_handler = SetLogHandler(&CaptureLog);
+
+  int start_line = __LINE__;
+  GOOGLE_LOG(ERROR) << "An error.";
+  GOOGLE_LOG(WARNING) << "A warning.";
+
+  EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
+
+  ASSERT_EQ(2, captured_messages_.size());
+  EXPECT_EQ(
+    "2 " __FILE__ ":" + SimpleItoa(start_line + 1) + ": An error.",
+    captured_messages_[0]);
+  EXPECT_EQ(
+    "1 " __FILE__ ":" + SimpleItoa(start_line + 2) + ": A warning.",
+    captured_messages_[1]);
+}
+
+TEST(LoggingTest, SilenceLogging) {
+  captured_messages_.clear();
+
+  LogHandler* old_handler = SetLogHandler(&CaptureLog);
+
+  int line1 = __LINE__; GOOGLE_LOG(INFO) << "Visible1";
+  LogSilencer* silencer1 = new LogSilencer;
+  GOOGLE_LOG(INFO) << "Not visible.";
+  LogSilencer* silencer2 = new LogSilencer;
+  GOOGLE_LOG(INFO) << "Not visible.";
+  delete silencer1;
+  GOOGLE_LOG(INFO) << "Not visible.";
+  delete silencer2;
+  int line2 = __LINE__; GOOGLE_LOG(INFO) << "Visible2";
+
+  EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
+
+  ASSERT_EQ(2, captured_messages_.size());
+  EXPECT_EQ(
+    "0 " __FILE__ ":" + SimpleItoa(line1) + ": Visible1",
+    captured_messages_[0]);
+  EXPECT_EQ(
+    "0 " __FILE__ ":" + SimpleItoa(line2) + ": Visible2",
+    captured_messages_[1]);
+}
+
+class ClosureTest : public testing::Test {
+ public:
+  void SetA123Method()   { a_ = 123; }
+  static void SetA123Function() { current_instance_->a_ = 123; }
+
+  void SetAMethod(int a)         { a_ = a; }
+  void SetCMethod(string c)      { c_ = c; }
+
+  static void SetAFunction(int a)         { current_instance_->a_ = a; }
+  static void SetCFunction(string c)      { current_instance_->c_ = c; }
+
+  void SetABMethod(int a, const char* b)  { a_ = a; b_ = b; }
+  static void SetABFunction(int a, const char* b) {
+    current_instance_->a_ = a;
+    current_instance_->b_ = b;
+  }
+
+  virtual void SetUp() {
+    current_instance_ = this;
+    a_ = 0;
+    b_ = NULL;
+    c_.clear();
+    permanent_closure_ = NULL;
+  }
+
+  void DeleteClosureInCallback() {
+    delete permanent_closure_;
+  }
+
+  int a_;
+  const char* b_;
+  string c_;
+  Closure* permanent_closure_;
+
+  static ClosureTest* current_instance_;
+};
+
+ClosureTest* ClosureTest::current_instance_ = NULL;
+
+TEST_F(ClosureTest, TestClosureFunction0) {
+  Closure* closure = NewCallback(&SetA123Function);
+  EXPECT_NE(123, a_);
+  closure->Run();
+  EXPECT_EQ(123, a_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod0) {
+  Closure* closure = NewCallback(current_instance_,
+                                 &ClosureTest::SetA123Method);
+  EXPECT_NE(123, a_);
+  closure->Run();
+  EXPECT_EQ(123, a_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction1) {
+  Closure* closure = NewCallback(&SetAFunction, 456);
+  EXPECT_NE(456, a_);
+  closure->Run();
+  EXPECT_EQ(456, a_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod1) {
+  Closure* closure = NewCallback(current_instance_,
+                                 &ClosureTest::SetAMethod, 456);
+  EXPECT_NE(456, a_);
+  closure->Run();
+  EXPECT_EQ(456, a_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction1String) {
+  Closure* closure = NewCallback(&SetCFunction, string("test"));
+  EXPECT_NE("test", c_);
+  closure->Run();
+  EXPECT_EQ("test", c_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod1String) {
+  Closure* closure = NewCallback(current_instance_,
+                                 &ClosureTest::SetCMethod, string("test"));
+  EXPECT_NE("test", c_);
+  closure->Run();
+  EXPECT_EQ("test", c_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction2) {
+  const char* cstr = "hello";
+  Closure* closure = NewCallback(&SetABFunction, 789, cstr);
+  EXPECT_NE(789, a_);
+  EXPECT_NE(cstr, b_);
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod2) {
+  const char* cstr = "hello";
+  Closure* closure = NewCallback(current_instance_,
+                                 &ClosureTest::SetABMethod, 789, cstr);
+  EXPECT_NE(789, a_);
+  EXPECT_NE(cstr, b_);
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+}
+
+// Repeat all of the above with NewPermanentCallback()
+
+TEST_F(ClosureTest, TestPermanentClosureFunction0) {
+  Closure* closure = NewPermanentCallback(&SetA123Function);
+  EXPECT_NE(123, a_);
+  closure->Run();
+  EXPECT_EQ(123, a_);
+  a_ = 0;
+  closure->Run();
+  EXPECT_EQ(123, a_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod0) {
+  Closure* closure = NewPermanentCallback(current_instance_,
+                                          &ClosureTest::SetA123Method);
+  EXPECT_NE(123, a_);
+  closure->Run();
+  EXPECT_EQ(123, a_);
+  a_ = 0;
+  closure->Run();
+  EXPECT_EQ(123, a_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureFunction1) {
+  Closure* closure = NewPermanentCallback(&SetAFunction, 456);
+  EXPECT_NE(456, a_);
+  closure->Run();
+  EXPECT_EQ(456, a_);
+  a_ = 0;
+  closure->Run();
+  EXPECT_EQ(456, a_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod1) {
+  Closure* closure = NewPermanentCallback(current_instance_,
+                                          &ClosureTest::SetAMethod, 456);
+  EXPECT_NE(456, a_);
+  closure->Run();
+  EXPECT_EQ(456, a_);
+  a_ = 0;
+  closure->Run();
+  EXPECT_EQ(456, a_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureFunction2) {
+  const char* cstr = "hello";
+  Closure* closure = NewPermanentCallback(&SetABFunction, 789, cstr);
+  EXPECT_NE(789, a_);
+  EXPECT_NE(cstr, b_);
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+  a_ = 0;
+  b_ = NULL;
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod2) {
+  const char* cstr = "hello";
+  Closure* closure = NewPermanentCallback(current_instance_,
+                                          &ClosureTest::SetABMethod, 789, cstr);
+  EXPECT_NE(789, a_);
+  EXPECT_NE(cstr, b_);
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+  a_ = 0;
+  b_ = NULL;
+  closure->Run();
+  EXPECT_EQ(789, a_);
+  EXPECT_EQ(cstr, b_);
+  delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureDeleteInCallback) {
+  permanent_closure_ = NewPermanentCallback((ClosureTest*) this,
+      &ClosureTest::DeleteClosureInCallback);
+  permanent_closure_->Run();
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/fastmem.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/fastmem.h
new file mode 100644
index 0000000..763a6e6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/fastmem.h
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+// Fast memory copying and comparison routines.
+//   strings::fastmemcmp_inlined() replaces memcmp()
+//   strings::memcpy_inlined() replaces memcpy()
+//   strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0
+//
+// strings::*_inlined() routines are inline versions of the
+// routines exported by this module.  Sometimes using the inlined
+// versions is faster.  Measure before using the inlined versions.
+//
+// Performance measurement:
+//   strings::fastmemcmp_inlined
+//     Analysis: memcmp, fastmemcmp_inlined, fastmemcmp
+//     2012-01-30
+
+#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
+#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Return true if the n bytes at a equal the n bytes at b.
+// The regions are allowed to overlap.
+//
+// The performance is similar to the performance memcmp(), but faster for
+// moderately-sized inputs, or inputs that share a common prefix and differ
+// somewhere in their last 8 bytes. Further optimizations can be added later
+// if it makes sense to do so.:w
+inline bool memeq(const char* a, const char* b, size_t n) {
+  size_t n_rounded_down = n & ~static_cast<size_t>(7);
+  if (GOOGLE_PREDICT_FALSE(n_rounded_down == 0)) {  // n <= 7
+    return memcmp(a, b, n) == 0;
+  }
+  // n >= 8
+  uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
+  uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8);
+  if ((u | v) != 0) {  // The first or last 8 bytes differ.
+    return false;
+  }
+  a += 8;
+  b += 8;
+  n = n_rounded_down - 8;
+  if (n > 128) {
+    // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2
+    // instructions, and while we could try to do something faster, it
+    // doesn't seem worth pursuing.
+    return memcmp(a, b, n) == 0;
+  }
+  for (; n >= 16; n -= 16) {
+    uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
+    uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8);
+    if ((x | y) != 0) {
+      return false;
+    }
+    a += 16;
+    b += 16;
+  }
+  // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop.
+  return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b);
+}
+
+inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) {
+  if (n >= 64) {
+    return memcmp(a, b, n);
+  }
+  const char* a_limit = a + n;
+  while (a + sizeof(uint64) <= a_limit &&
+         GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) {
+    a += sizeof(uint64);
+    b += sizeof(uint64);
+  }
+  if (a + sizeof(uint32) <= a_limit &&
+      GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) {
+    a += sizeof(uint32);
+    b += sizeof(uint32);
+  }
+  while (a < a_limit) {
+    int d = static_cast<uint32>(*a++) - static_cast<uint32>(*b++);
+    if (d) return d;
+  }
+  return 0;
+}
+
+// The standard memcpy operation is slow for variable small sizes.
+// This implementation inlines the optimal realization for sizes 1 to 16.
+// To avoid code bloat don't use it in case of not performance-critical spots,
+// nor when you don't expect very frequent values of size <= 16.
+inline void memcpy_inlined(char *dst, const char *src, size_t size) {
+  // Compiler inlines code with minimal amount of data movement when third
+  // parameter of memcpy is a constant.
+  switch (size) {
+    case  1: memcpy(dst, src, 1); break;
+    case  2: memcpy(dst, src, 2); break;
+    case  3: memcpy(dst, src, 3); break;
+    case  4: memcpy(dst, src, 4); break;
+    case  5: memcpy(dst, src, 5); break;
+    case  6: memcpy(dst, src, 6); break;
+    case  7: memcpy(dst, src, 7); break;
+    case  8: memcpy(dst, src, 8); break;
+    case  9: memcpy(dst, src, 9); break;
+    case 10: memcpy(dst, src, 10); break;
+    case 11: memcpy(dst, src, 11); break;
+    case 12: memcpy(dst, src, 12); break;
+    case 13: memcpy(dst, src, 13); break;
+    case 14: memcpy(dst, src, 14); break;
+    case 15: memcpy(dst, src, 15); break;
+    case 16: memcpy(dst, src, 16); break;
+    default: memcpy(dst, src, size); break;
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/hash.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/hash.h
new file mode 100644
index 0000000..4eac7d5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/hash.h
@@ -0,0 +1,438 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Deals with the fact that hash_map is not defined everywhere.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
+#define GOOGLE_PROTOBUF_STUBS_HASH_H__
+
+#include <string.h>
+#include <google/protobuf/stubs/common.h>
+
+#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
+#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
+
+// Android
+#if defined(__ANDROID__)
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+
+// Use C++11 unordered_{map|set} if available.
+#elif ((_LIBCPP_STD_VER >= 11) || \
+      (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
+      (__GLIBCXX__ > 20090421)))
+# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
+
+// For XCode >= 4.6:  the compiler is clang with libc++.
+// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++.
+// libc++ provides <unordered_map> and friends even in non C++11 mode,
+// and it does not provide the tr1 library. Therefore the following macro
+// checks against this special case.
+// Note that we should not test the __APPLE_CC__ version number or the
+// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in
+// which case <unordered_map> is not compilable without -std=c++11
+#elif defined(__APPLE_CC__)
+# if __GNUC__ >= 4
+#  define GOOGLE_PROTOBUF_HAS_TR1
+# else
+// Not tested for gcc < 4... These setting can compile under 4.2.1 though.
+#  define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx
+#  include <ext/hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <ext/hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# endif
+
+// Version checks for gcc.
+#elif defined(__GNUC__)
+// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the
+// instructions from:
+// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html
+# if __GNUC__ >= 4
+#  define GOOGLE_PROTOBUF_HAS_TR1
+# elif __GNUC__ >= 3
+#  include <backward/hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <backward/hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#  if __GNUC__ == 3 && __GNUC_MINOR__ == 0
+#   define GOOGLE_PROTOBUF_HASH_NAMESPACE std       // GCC 3.0
+#  else
+#   define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later
+#  endif
+# else
+#  define GOOGLE_PROTOBUF_HASH_NAMESPACE
+#  include <hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# endif
+
+// Version checks for MSC.
+// Apparently Microsoft decided to move hash_map *back* to the std namespace in
+// MSVC 2010:
+// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
+// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
+// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
+#elif defined(_MSC_VER)
+# if _MSC_VER >= 1600  // Since Visual Studio 2010
+#  define GOOGLE_PROTOBUF_HAS_CXX11_HASH
+#  define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
+# elif _MSC_VER >= 1500  // Since Visual Studio 2008
+#  define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
+#  include <hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+#  define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
+# elif _MSC_VER >= 1310
+#  define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
+#  include <hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# else
+#  define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+#  include <hash_map>
+#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#  include <hash_set>
+#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# endif
+
+// **ADD NEW COMPILERS SUPPORT HERE.**
+// For other compilers, undefine the macro and fallback to use std::map, in
+// google/protobuf/stubs/hash.h
+#else
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
+#endif
+
+#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+# include <unordered_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+# include <unordered_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#elif defined(GOOGLE_PROTOBUF_HAS_TR1)
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
+# include <tr1/unordered_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+# include <tr1/unordered_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#endif
+
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
+  namespace google {                                      \
+  namespace protobuf {
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
+
+#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
+#undef GOOGLE_PROTOBUF_HAS_TR1
+
+#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
+    defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
+#else
+#define GOOGLE_PROTOBUF_MISSING_HASH
+#include <map>
+#include <set>
+#endif
+
+namespace google {
+namespace protobuf {
+
+#ifdef GOOGLE_PROTOBUF_MISSING_HASH
+#undef GOOGLE_PROTOBUF_MISSING_HASH
+
+// This system doesn't have hash_map or hash_set.  Emulate them using map and
+// set.
+
+// Make hash<T> be the same as less<T>.  Note that everywhere where custom
+// hash functions are defined in the protobuf code, they are also defined such
+// that they can be used as "less" functions, which is required by MSVC anyway.
+template <typename Key>
+struct hash {
+  // Dummy, just to make derivative hash functions compile.
+  int operator()(const Key& key) {
+    GOOGLE_LOG(FATAL) << "Should never be called.";
+    return 0;
+  }
+
+  inline bool operator()(const Key& a, const Key& b) const {
+    return a < b;
+  }
+};
+
+// Make sure char* is compared by value.
+template <>
+struct hash<const char*> {
+  // Dummy, just to make derivative hash functions compile.
+  int operator()(const char* key) {
+    GOOGLE_LOG(FATAL) << "Should never be called.";
+    return 0;
+  }
+
+  inline bool operator()(const char* a, const char* b) const {
+    return strcmp(a, b) < 0;
+  }
+};
+
+template <typename Key, typename Data,
+          typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
+  typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;
+
+ public:
+  hash_map(int a = 0, const HashFcn& b = HashFcn(),
+           const EqualKey& c = EqualKey(),
+           const Alloc& d = Alloc()) : BaseClass(b, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+template <typename Key,
+          typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key> >
+class hash_set : public std::set<Key, HashFcn> {
+ public:
+  hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
+
+template <typename Key>
+struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
+};
+
+// MSVC's hash_compare<const char*> hashes based on the string contents but
+// compares based on the string pointer.  WTF?
+class CstringLess {
+ public:
+  inline bool operator()(const char* a, const char* b) const {
+    return strcmp(a, b) < 0;
+  }
+};
+
+template <>
+struct hash<const char*>
+    : public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};
+
+#ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
+
+template <typename Key, typename HashFcn, typename EqualKey>
+struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
+  InternalHashCompare() {}
+  InternalHashCompare(HashFcn hashfcn, EqualKey equalkey)
+      : hashfcn_(hashfcn), equalkey_(equalkey) {}
+  size_t operator()(const Key& key) const { return hashfcn_(key); }
+  bool operator()(const Key& key1, const Key& key2) const {
+    return !equalkey_(key1, key2);
+  }
+  HashFcn hashfcn_;
+  EqualKey equalkey_;
+};
+
+template <typename Key, typename Data,
+          typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+          Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> {
+  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+      Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> BaseClass;
+
+ public:
+  hash_map(int a = 0, const HashFcn& b = HashFcn(),
+           const EqualKey& c = EqualKey(), const Alloc& d = Alloc())
+      : BaseClass(InternalHashCompare<Key, HashFcn, EqualKey>(b, c), d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+template <typename Key, typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key> >
+class hash_set
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+          Key, InternalHashCompare<Key, HashFcn, EqualKey> > {
+ public:
+  hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+#else  // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
+
+template <typename Key, typename Data,
+          typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+          Key, Data, HashFcn, EqualKey, Alloc> {
+  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+      Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
+
+ public:
+  hash_map(int a = 0, const HashFcn& b = HashFcn(),
+           const EqualKey& c = EqualKey(),
+           const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+template <typename Key, typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key> >
+class hash_set
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+          Key, HashFcn, EqualKey> {
+ public:
+  hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+#endif  // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
+
+#else  // defined(_MSC_VER) && !defined(_STLPORT_VERSION)
+
+template <typename Key>
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
+};
+
+template <typename Key>
+struct hash<const Key*> {
+  inline size_t operator()(const Key* key) const {
+    return reinterpret_cast<size_t>(key);
+  }
+};
+
+// Unlike the old SGI version, the TR1 "hash" does not special-case char*.  So,
+// we go ahead and provide our own implementation.
+template <>
+struct hash<const char*> {
+  inline size_t operator()(const char* str) const {
+    size_t result = 0;
+    for (; *str != '\0'; str++) {
+      result = 5 * result + *str;
+    }
+    return result;
+  }
+};
+
+template<>
+struct hash<bool> {
+  size_t operator()(bool x) const {
+    return static_cast<size_t>(x);
+  }
+};
+
+template <typename Key, typename Data,
+          typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key>,
+          typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+          Key, Data, HashFcn, EqualKey, Alloc> {
+  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+      Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
+
+ public:
+  hash_map(int a = 0, const HashFcn& b = HashFcn(),
+           const EqualKey& c = EqualKey(),
+           const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+template <typename Key, typename HashFcn = hash<Key>,
+          typename EqualKey = std::equal_to<Key> >
+class hash_set
+    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+          Key, HashFcn, EqualKey> {
+ public:
+  hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
+};
+
+#endif  // !GOOGLE_PROTOBUF_MISSING_HASH
+
+template <>
+struct hash<string> {
+  inline size_t operator()(const string& key) const {
+    return hash<const char*>()(key.c_str());
+  }
+
+  static const size_t bucket_size = 4;
+  static const size_t min_buckets = 8;
+  inline bool operator()(const string& a, const string& b) const {
+    return a < b;
+  }
+};
+
+template <typename First, typename Second>
+struct hash<pair<First, Second> > {
+  inline size_t operator()(const pair<First, Second>& key) const {
+    size_t first_hash = hash<First>()(key.first);
+    size_t second_hash = hash<Second>()(key.second);
+
+    // FIXME(kenton):  What is the best way to compute this hash?  I have
+    // no idea!  This seems a bit better than an XOR.
+    return first_hash * ((1 << 16) - 1) + second_hash;
+  }
+
+  static const size_t bucket_size = 4;
+  static const size_t min_buckets = 8;
+  inline bool operator()(const pair<First, Second>& a,
+                           const pair<First, Second>& b) const {
+    return a < b;
+  }
+};
+
+// Used by GCC/SGI STL only.  (Why isn't this provided by the standard
+// library?  :( )
+struct streq {
+  inline bool operator()(const char* a, const char* b) const {
+    return strcmp(a, b) == 0;
+  }
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_HASH_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.cc
new file mode 100644
index 0000000..3a36b4b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.cc
@@ -0,0 +1,201 @@
+// 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.
+
+#include <google/protobuf/stubs/int128.h>
+
+#include <iomanip>
+#include <ostream>  // NOLINT(readability/streams)
+#include <sstream>
+
+namespace google {
+namespace protobuf {
+
+const uint128_pod kuint128max = {
+    static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)),
+    static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF))
+};
+
+// Returns the 0-based position of the last set bit (i.e., most significant bit)
+// in the given uint64. The argument may not be 0.
+//
+// For example:
+//   Given: 5 (decimal) == 101 (binary)
+//   Returns: 2
+#define STEP(T, n, pos, sh)                   \
+  do {                                        \
+    if ((n) >= (static_cast<T>(1) << (sh))) { \
+      (n) = (n) >> (sh);                      \
+      (pos) |= (sh);                          \
+    }                                         \
+  } while (0)
+static inline int Fls64(uint64 n) {
+  GOOGLE_DCHECK_NE(0, n);
+  int pos = 0;
+  STEP(uint64, n, pos, 0x20);
+  uint32 n32 = n;
+  STEP(uint32, n32, pos, 0x10);
+  STEP(uint32, n32, pos, 0x08);
+  STEP(uint32, n32, pos, 0x04);
+  return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3);
+}
+#undef STEP
+
+// Like Fls64() above, but returns the 0-based position of the last set bit
+// (i.e., most significant bit) in the given uint128. The argument may not be 0.
+static inline int Fls128(uint128 n) {
+  if (uint64 hi = Uint128High64(n)) {
+    return Fls64(hi) + 64;
+  }
+  return Fls64(Uint128Low64(n));
+}
+
+// Long division/modulo for uint128 implemented using the shift-subtract
+// division algorithm adapted from:
+// http://stackoverflow.com/questions/5386377/division-without-using
+void uint128::DivModImpl(uint128 dividend, uint128 divisor,
+                         uint128* quotient_ret, uint128* remainder_ret) {
+  if (divisor == 0) {
+    GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_
+                      << ", lo=" << dividend.lo_;
+  }
+
+  if (divisor > dividend) {
+    *quotient_ret = 0;
+    *remainder_ret = dividend;
+    return;
+  }
+
+  if (divisor == dividend) {
+    *quotient_ret = 1;
+    *remainder_ret = 0;
+    return;
+  }
+
+  uint128 denominator = divisor;
+  uint128 position = 1;
+  uint128 quotient = 0;
+
+  // Left aligns the MSB of the denominator and the dividend.
+  int shift = Fls128(dividend) - Fls128(denominator);
+  denominator <<= shift;
+  position <<= shift;
+
+  // Uses shift-subtract algorithm to divide dividend by denominator. The
+  // remainder will be left in dividend.
+  while (position > 0) {
+    if (dividend >= denominator) {
+      dividend -= denominator;
+      quotient |= position;
+    }
+    position >>= 1;
+    denominator >>= 1;
+  }
+
+  *quotient_ret = quotient;
+  *remainder_ret = dividend;
+}
+
+uint128& uint128::operator/=(const uint128& divisor) {
+  uint128 quotient = 0;
+  uint128 remainder = 0;
+  DivModImpl(*this, divisor, &quotient, &remainder);
+  *this = quotient;
+  return *this;
+}
+uint128& uint128::operator%=(const uint128& divisor) {
+  uint128 quotient = 0;
+  uint128 remainder = 0;
+  DivModImpl(*this, divisor, &quotient, &remainder);
+  *this = remainder;
+  return *this;
+}
+
+std::ostream& operator<<(std::ostream& o, const uint128& b) {
+  std::ios_base::fmtflags flags = o.flags();
+
+  // Select a divisor which is the largest power of the base < 2^64.
+  uint128 div;
+  std::streamsize div_base_log;
+  switch (flags & std::ios::basefield) {
+    case std::ios::hex:
+      div = GOOGLE_ULONGLONG(0x1000000000000000);  // 16^15
+      div_base_log = 15;
+      break;
+    case std::ios::oct:
+      div = GOOGLE_ULONGLONG(01000000000000000000000);  // 8^21
+      div_base_log = 21;
+      break;
+    default:  // std::ios::dec
+      div = GOOGLE_ULONGLONG(10000000000000000000);  // 10^19
+      div_base_log = 19;
+      break;
+  }
+
+  // Now piece together the uint128 representation from three chunks of
+  // the original value, each less than "div" and therefore representable
+  // as a uint64.
+  std::ostringstream os;
+  std::ios_base::fmtflags copy_mask =
+      std::ios::basefield | std::ios::showbase | std::ios::uppercase;
+  os.setf(flags & copy_mask, copy_mask);
+  uint128 high = b;
+  uint128 low;
+  uint128::DivModImpl(high, div, &high, &low);
+  uint128 mid;
+  uint128::DivModImpl(high, div, &high, &mid);
+  if (high.lo_ != 0) {
+    os << high.lo_;
+    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
+    os << mid.lo_;
+    os << std::setw(div_base_log);
+  } else if (mid.lo_ != 0) {
+    os << mid.lo_;
+    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
+  }
+  os << low.lo_;
+  std::string rep = os.str();
+
+  // Add the requisite padding.
+  std::streamsize width = o.width(0);
+  if (width > rep.size()) {
+    if ((flags & std::ios::adjustfield) == std::ios::left) {
+      rep.append(width - rep.size(), o.fill());
+    } else {
+      rep.insert(static_cast<std::string::size_type>(0),
+                 width - rep.size(), o.fill());
+    }
+  }
+
+  // Stream the final representation in a single "<<" call.
+  return o << rep;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.h
new file mode 100644
index 0000000..1499bb7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128.h
@@ -0,0 +1,383 @@
+// 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_STUBS_INT128_H_
+#define GOOGLE_PROTOBUF_STUBS_INT128_H_
+
+#include <google/protobuf/stubs/common.h>
+
+#include <iosfwd>
+
+namespace google {
+namespace protobuf {
+
+struct uint128_pod;
+
+// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
+// available.
+#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
+# define UINT128_CONSTEXPR constexpr
+#else
+# define UINT128_CONSTEXPR
+#endif
+
+// An unsigned 128-bit integer type. Thread-compatible.
+class LIBPROTOBUF_EXPORT uint128 {
+ public:
+  UINT128_CONSTEXPR uint128();  // Sets to 0, but don't trust on this behavior.
+  UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
+#ifndef SWIG
+  UINT128_CONSTEXPR uint128(int bottom);
+  UINT128_CONSTEXPR uint128(uint32 bottom);   // Top 96 bits = 0
+#endif
+  UINT128_CONSTEXPR uint128(uint64 bottom);   // hi_ = 0
+  UINT128_CONSTEXPR uint128(const uint128_pod &val);
+
+  // Trivial copy constructor, assignment operator and destructor.
+
+  void Initialize(uint64 top, uint64 bottom);
+
+  // Arithmetic operators.
+  uint128& operator+=(const uint128& b);
+  uint128& operator-=(const uint128& b);
+  uint128& operator*=(const uint128& b);
+  // Long division/modulo for uint128.
+  uint128& operator/=(const uint128& b);
+  uint128& operator%=(const uint128& b);
+  uint128 operator++(int);
+  uint128 operator--(int);
+  uint128& operator<<=(int);
+  uint128& operator>>=(int);
+  uint128& operator&=(const uint128& b);
+  uint128& operator|=(const uint128& b);
+  uint128& operator^=(const uint128& b);
+  uint128& operator++();
+  uint128& operator--();
+
+  friend uint64 Uint128Low64(const uint128& v);
+  friend uint64 Uint128High64(const uint128& v);
+
+  // We add "std::" to avoid including all of port.h.
+  LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
+                                                     const uint128& b);
+
+ private:
+  static void DivModImpl(uint128 dividend, uint128 divisor,
+                         uint128* quotient_ret, uint128* remainder_ret);
+
+  // Little-endian memory order optimizations can benefit from
+  // having lo_ first, hi_ last.
+  // See util/endian/endian.h and Load128/Store128 for storing a uint128.
+  uint64        lo_;
+  uint64        hi_;
+
+  // Not implemented, just declared for catching automatic type conversions.
+  uint128(uint8);
+  uint128(uint16);
+  uint128(float v);
+  uint128(double v);
+};
+
+// This is a POD form of uint128 which can be used for static variables which
+// need to be operated on as uint128.
+struct uint128_pod {
+  // Note: The ordering of fields is different than 'class uint128' but the
+  // same as its 2-arg constructor.  This enables more obvious initialization
+  // of static instances, which is the primary reason for this struct in the
+  // first place.  This does not seem to defeat any optimizations wrt
+  // operations involving this struct.
+  uint64 hi;
+  uint64 lo;
+};
+
+LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max;
+
+// allow uint128 to be logged
+LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
+                                                   const uint128& b);
+
+// Methods to access low and high pieces of 128-bit value.
+// Defined externally from uint128 to facilitate conversion
+// to native 128-bit types when compilers support them.
+inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
+inline uint64 Uint128High64(const uint128& v) { return v.hi_; }
+
+// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
+
+// --------------------------------------------------------------------------
+//                      Implementation details follow
+// --------------------------------------------------------------------------
+inline bool operator==(const uint128& lhs, const uint128& rhs) {
+  return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
+          Uint128High64(lhs) == Uint128High64(rhs));
+}
+inline bool operator!=(const uint128& lhs, const uint128& rhs) {
+  return !(lhs == rhs);
+}
+
+inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
+inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
+    : lo_(bottom), hi_(top) {}
+inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
+    : lo_(v.lo), hi_(v.hi) {}
+inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
+    : lo_(bottom), hi_(0) {}
+#ifndef SWIG
+inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
+    : lo_(bottom), hi_(0) {}
+inline UINT128_CONSTEXPR uint128::uint128(int bottom)
+    : lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
+#endif
+
+#undef UINT128_CONSTEXPR
+
+inline void uint128::Initialize(uint64 top, uint64 bottom) {
+  hi_ = top;
+  lo_ = bottom;
+}
+
+// Comparison operators.
+
+#define CMP128(op)                                                \
+inline bool operator op(const uint128& lhs, const uint128& rhs) { \
+  return (Uint128High64(lhs) == Uint128High64(rhs)) ?             \
+      (Uint128Low64(lhs) op Uint128Low64(rhs)) :                  \
+      (Uint128High64(lhs) op Uint128High64(rhs));                 \
+}
+
+CMP128(<)
+CMP128(>)
+CMP128(>=)
+CMP128(<=)
+
+#undef CMP128
+
+// Unary operators
+
+inline uint128 operator-(const uint128& val) {
+  const uint64 hi_flip = ~Uint128High64(val);
+  const uint64 lo_flip = ~Uint128Low64(val);
+  const uint64 lo_add = lo_flip + 1;
+  if (lo_add < lo_flip) {
+    return uint128(hi_flip + 1, lo_add);
+  }
+  return uint128(hi_flip, lo_add);
+}
+
+inline bool operator!(const uint128& val) {
+  return !Uint128High64(val) && !Uint128Low64(val);
+}
+
+// Logical operators.
+
+inline uint128 operator~(const uint128& val) {
+  return uint128(~Uint128High64(val), ~Uint128Low64(val));
+}
+
+#define LOGIC128(op)                                                 \
+inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
+  return uint128(Uint128High64(lhs) op Uint128High64(rhs),           \
+                 Uint128Low64(lhs) op Uint128Low64(rhs));            \
+}
+
+LOGIC128(|)
+LOGIC128(&)
+LOGIC128(^)
+
+#undef LOGIC128
+
+#define LOGICASSIGN128(op)                                   \
+inline uint128& uint128::operator op(const uint128& other) { \
+  hi_ op other.hi_;                                          \
+  lo_ op other.lo_;                                          \
+  return *this;                                              \
+}
+
+LOGICASSIGN128(|=)
+LOGICASSIGN128(&=)
+LOGICASSIGN128(^=)
+
+#undef LOGICASSIGN128
+
+// Shift operators.
+
+inline uint128 operator<<(const uint128& val, int amount) {
+  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+  if (amount < 64) {
+    if (amount == 0) {
+      return val;
+    }
+    uint64 new_hi = (Uint128High64(val) << amount) |
+                    (Uint128Low64(val) >> (64 - amount));
+    uint64 new_lo = Uint128Low64(val) << amount;
+    return uint128(new_hi, new_lo);
+  } else if (amount < 128) {
+    return uint128(Uint128Low64(val) << (amount - 64), 0);
+  } else {
+    return uint128(0, 0);
+  }
+}
+
+inline uint128 operator>>(const uint128& val, int amount) {
+  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+  if (amount < 64) {
+    if (amount == 0) {
+      return val;
+    }
+    uint64 new_hi = Uint128High64(val) >> amount;
+    uint64 new_lo = (Uint128Low64(val) >> amount) |
+                    (Uint128High64(val) << (64 - amount));
+    return uint128(new_hi, new_lo);
+  } else if (amount < 128) {
+    return uint128(0, Uint128High64(val) >> (amount - 64));
+  } else {
+    return uint128(0, 0);
+  }
+}
+
+inline uint128& uint128::operator<<=(int amount) {
+  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+  if (amount < 64) {
+    if (amount != 0) {
+      hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
+      lo_ = lo_ << amount;
+    }
+  } else if (amount < 128) {
+    hi_ = lo_ << (amount - 64);
+    lo_ = 0;
+  } else {
+    hi_ = 0;
+    lo_ = 0;
+  }
+  return *this;
+}
+
+inline uint128& uint128::operator>>=(int amount) {
+  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+  if (amount < 64) {
+    if (amount != 0) {
+      lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
+      hi_ = hi_ >> amount;
+    }
+  } else if (amount < 128) {
+    lo_ = hi_ >> (amount - 64);
+    hi_ = 0;
+  } else {
+    lo_ = 0;
+    hi_ = 0;
+  }
+  return *this;
+}
+
+inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
+  return uint128(lhs) += rhs;
+}
+
+inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
+  return uint128(lhs) -= rhs;
+}
+
+inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
+  return uint128(lhs) *= rhs;
+}
+
+inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
+  return uint128(lhs) /= rhs;
+}
+
+inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
+  return uint128(lhs) %= rhs;
+}
+
+inline uint128& uint128::operator+=(const uint128& b) {
+  hi_ += b.hi_;
+  uint64 lolo = lo_ + b.lo_;
+  if (lolo < lo_)
+    ++hi_;
+  lo_ = lolo;
+  return *this;
+}
+
+inline uint128& uint128::operator-=(const uint128& b) {
+  hi_ -= b.hi_;
+  if (b.lo_ > lo_)
+    --hi_;
+  lo_ -= b.lo_;
+  return *this;
+}
+
+inline uint128& uint128::operator*=(const uint128& b) {
+  uint64 a96 = hi_ >> 32;
+  uint64 a64 = hi_ & 0xffffffffu;
+  uint64 a32 = lo_ >> 32;
+  uint64 a00 = lo_ & 0xffffffffu;
+  uint64 b96 = b.hi_ >> 32;
+  uint64 b64 = b.hi_ & 0xffffffffu;
+  uint64 b32 = b.lo_ >> 32;
+  uint64 b00 = b.lo_ & 0xffffffffu;
+  // multiply [a96 .. a00] x [b96 .. b00]
+  // terms higher than c96 disappear off the high side
+  // terms c96 and c64 are safe to ignore carry bit
+  uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
+  uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64;
+  this->hi_ = (c96 << 32) + c64;
+  this->lo_ = 0;
+  // add terms after this one at a time to capture carry
+  *this += uint128(a32 * b00) << 32;
+  *this += uint128(a00 * b32) << 32;
+  *this += a00 * b00;
+  return *this;
+}
+
+inline uint128 uint128::operator++(int) {
+  uint128 tmp(*this);
+  *this += 1;
+  return tmp;
+}
+
+inline uint128 uint128::operator--(int) {
+  uint128 tmp(*this);
+  *this -= 1;
+  return tmp;
+}
+
+inline uint128& uint128::operator++() {
+  *this += 1;
+  return *this;
+}
+
+inline uint128& uint128::operator--() {
+  *this -= 1;
+  return *this;
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_INT128_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/int128_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128_unittest.cc
new file mode 100644
index 0000000..5d33292
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/int128_unittest.cc
@@ -0,0 +1,513 @@
+// 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.
+
+#include <google/protobuf/stubs/int128.h>
+
+#include <algorithm>
+#include <sstream>
+#include <utility>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+TEST(Int128, AllTests) {
+  uint128 zero(0);
+  uint128 one(1);
+  uint128 one_2arg(0, 1);
+  uint128 two(0, 2);
+  uint128 three(0, 3);
+  uint128 big(2000, 2);
+  uint128 big_minus_one(2000, 1);
+  uint128 bigger(2001, 1);
+  uint128 biggest(kuint128max);
+  uint128 high_low(1, 0);
+  uint128 low_high(0, kuint64max);
+  EXPECT_LT(one, two);
+  EXPECT_GT(two, one);
+  EXPECT_LT(one, big);
+  EXPECT_LT(one, big);
+  EXPECT_EQ(one, one_2arg);
+  EXPECT_NE(one, two);
+  EXPECT_GT(big, one);
+  EXPECT_GE(big, two);
+  EXPECT_GE(big, big_minus_one);
+  EXPECT_GT(big, big_minus_one);
+  EXPECT_LT(big_minus_one, big);
+  EXPECT_LE(big_minus_one, big);
+  EXPECT_NE(big_minus_one, big);
+  EXPECT_LT(big, biggest);
+  EXPECT_LE(big, biggest);
+  EXPECT_GT(biggest, big);
+  EXPECT_GE(biggest, big);
+  EXPECT_EQ(big, ~~big);
+  EXPECT_EQ(one, one | one);
+  EXPECT_EQ(big, big | big);
+  EXPECT_EQ(one, one | zero);
+  EXPECT_EQ(one, one & one);
+  EXPECT_EQ(big, big & big);
+  EXPECT_EQ(zero, one & zero);
+  EXPECT_EQ(zero, big & ~big);
+  EXPECT_EQ(zero, one ^ one);
+  EXPECT_EQ(zero, big ^ big);
+  EXPECT_EQ(one, one ^ zero);
+
+  // Shift operators.
+  EXPECT_EQ(big, big << 0);
+  EXPECT_EQ(big, big >> 0);
+  EXPECT_GT(big << 1, big);
+  EXPECT_LT(big >> 1, big);
+  EXPECT_EQ(big, (big << 10) >> 10);
+  EXPECT_EQ(big, (big >> 1) << 1);
+  EXPECT_EQ(one, (one << 80) >> 80);
+  EXPECT_EQ(zero, (one >> 80) << 80);
+  EXPECT_EQ(zero, big >> 128);
+  EXPECT_EQ(zero, big << 128);
+
+  // Shift assignments.
+  uint128 big_copy = big;
+  EXPECT_EQ(big << 0, big_copy <<= 0);
+  big_copy = big;
+  EXPECT_EQ(big >> 0, big_copy >>= 0);
+  big_copy = big;
+  EXPECT_EQ(big << 1, big_copy <<= 1);
+  big_copy = big;
+  EXPECT_EQ(big >> 1, big_copy >>= 1);
+  big_copy = big;
+  EXPECT_EQ(big << 10, big_copy <<= 10);
+  big_copy = big;
+  EXPECT_EQ(big >> 10, big_copy >>= 10);
+  big_copy = big;
+  EXPECT_EQ(big << 64, big_copy <<= 64);
+  big_copy = big;
+  EXPECT_EQ(big >> 64, big_copy >>= 64);
+  big_copy = big;
+  EXPECT_EQ(big << 73, big_copy <<= 73);
+  big_copy = big;
+  EXPECT_EQ(big >> 73, big_copy >>= 73);
+  big_copy = big;
+  EXPECT_EQ(big << 128, big_copy <<= 128);
+  big_copy = big;
+  EXPECT_EQ(big >> 128, big_copy >>= 128);
+
+  EXPECT_EQ(Uint128High64(biggest), kuint64max);
+  EXPECT_EQ(Uint128Low64(biggest), kuint64max);
+  EXPECT_EQ(zero + one, one);
+  EXPECT_EQ(one + one, two);
+  EXPECT_EQ(big_minus_one + one, big);
+  EXPECT_EQ(one - one, zero);
+  EXPECT_EQ(one - zero, one);
+  EXPECT_EQ(zero - one, biggest);
+  EXPECT_EQ(big - big, zero);
+  EXPECT_EQ(big - one, big_minus_one);
+  EXPECT_EQ(big + kuint64max, bigger);
+  EXPECT_EQ(biggest + 1, zero);
+  EXPECT_EQ(zero - 1, biggest);
+  EXPECT_EQ(high_low - one, low_high);
+  EXPECT_EQ(low_high + one, high_low);
+  EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0);
+  EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), kuint64max);
+  EXPECT_TRUE(!!one);
+  EXPECT_TRUE(!!high_low);
+  EXPECT_FALSE(!!zero);
+  EXPECT_FALSE(!one);
+  EXPECT_FALSE(!high_low);
+  EXPECT_TRUE(!zero);
+  EXPECT_TRUE(zero == 0);
+  EXPECT_FALSE(zero != 0);
+  EXPECT_FALSE(one == 0);
+  EXPECT_TRUE(one != 0);
+
+  uint128 test = zero;
+  EXPECT_EQ(++test, one);
+  EXPECT_EQ(test, one);
+  EXPECT_EQ(test++, one);
+  EXPECT_EQ(test, two);
+  EXPECT_EQ(test -= 2, zero);
+  EXPECT_EQ(test, zero);
+  EXPECT_EQ(test += 2, two);
+  EXPECT_EQ(test, two);
+  EXPECT_EQ(--test, one);
+  EXPECT_EQ(test, one);
+  EXPECT_EQ(test--, one);
+  EXPECT_EQ(test, zero);
+  EXPECT_EQ(test |= three, three);
+  EXPECT_EQ(test &= one, one);
+  EXPECT_EQ(test ^= three, two);
+  EXPECT_EQ(test >>= 1, one);
+  EXPECT_EQ(test <<= 1, two);
+
+  EXPECT_EQ(big, -(-big));
+  EXPECT_EQ(two, -((-one) - 1));
+  EXPECT_EQ(kuint128max, -one);
+  EXPECT_EQ(zero, -zero);
+
+  GOOGLE_LOG(INFO) << one;
+  GOOGLE_LOG(INFO) << big_minus_one;
+}
+
+TEST(Int128, PodTests) {
+  uint128_pod pod = { 12345, 67890 };
+  uint128 from_pod(pod);
+  EXPECT_EQ(12345, Uint128High64(from_pod));
+  EXPECT_EQ(67890, Uint128Low64(from_pod));
+
+  uint128 zero(0);
+  uint128_pod zero_pod = {0, 0};
+  uint128 one(1);
+  uint128_pod one_pod = {0, 1};
+  uint128 two(2);
+  uint128_pod two_pod = {0, 2};
+  uint128 three(3);
+  uint128_pod three_pod = {0, 3};
+  uint128 big(1, 0);
+  uint128_pod big_pod = {1, 0};
+
+  EXPECT_EQ(zero, zero_pod);
+  EXPECT_EQ(zero_pod, zero);
+  EXPECT_EQ(zero_pod, zero_pod);
+  EXPECT_EQ(one, one_pod);
+  EXPECT_EQ(one_pod, one);
+  EXPECT_EQ(one_pod, one_pod);
+  EXPECT_EQ(two, two_pod);
+  EXPECT_EQ(two_pod, two);
+  EXPECT_EQ(two_pod, two_pod);
+
+  EXPECT_NE(one, two_pod);
+  EXPECT_NE(one_pod, two);
+  EXPECT_NE(one_pod, two_pod);
+
+  EXPECT_LT(one, two_pod);
+  EXPECT_LT(one_pod, two);
+  EXPECT_LT(one_pod, two_pod);
+  EXPECT_LE(one, one_pod);
+  EXPECT_LE(one_pod, one);
+  EXPECT_LE(one_pod, one_pod);
+  EXPECT_LE(one, two_pod);
+  EXPECT_LE(one_pod, two);
+  EXPECT_LE(one_pod, two_pod);
+
+  EXPECT_GT(two, one_pod);
+  EXPECT_GT(two_pod, one);
+  EXPECT_GT(two_pod, one_pod);
+  EXPECT_GE(two, two_pod);
+  EXPECT_GE(two_pod, two);
+  EXPECT_GE(two_pod, two_pod);
+  EXPECT_GE(two, one_pod);
+  EXPECT_GE(two_pod, one);
+  EXPECT_GE(two_pod, one_pod);
+
+  EXPECT_EQ(three, one | two_pod);
+  EXPECT_EQ(three, one_pod | two);
+  EXPECT_EQ(three, one_pod | two_pod);
+  EXPECT_EQ(one, three & one_pod);
+  EXPECT_EQ(one, three_pod & one);
+  EXPECT_EQ(one, three_pod & one_pod);
+  EXPECT_EQ(two, three ^ one_pod);
+  EXPECT_EQ(two, three_pod ^ one);
+  EXPECT_EQ(two, three_pod ^ one_pod);
+  EXPECT_EQ(two, three & (~one));
+  EXPECT_EQ(three, ~~three);
+
+  EXPECT_EQ(two, two_pod << 0);
+  EXPECT_EQ(two, one_pod << 1);
+  EXPECT_EQ(big, one_pod << 64);
+  EXPECT_EQ(zero, one_pod << 128);
+  EXPECT_EQ(two, two_pod >> 0);
+  EXPECT_EQ(one, two_pod >> 1);
+  EXPECT_EQ(one, big_pod >> 64);
+
+  EXPECT_EQ(one, zero + one_pod);
+  EXPECT_EQ(one, zero_pod + one);
+  EXPECT_EQ(one, zero_pod + one_pod);
+  EXPECT_EQ(one, two - one_pod);
+  EXPECT_EQ(one, two_pod - one);
+  EXPECT_EQ(one, two_pod - one_pod);
+}
+
+TEST(Int128, OperatorAssignReturnRef) {
+  uint128 v(1);
+  (v += 4) -= 3;
+  EXPECT_EQ(2, v);
+}
+
+TEST(Int128, Multiply) {
+  uint128 a, b, c;
+
+  // Zero test.
+  a = 0;
+  b = 0;
+  c = a * b;
+  EXPECT_EQ(0, c);
+
+  // Max carries.
+  a = uint128(0) - 1;
+  b = uint128(0) - 1;
+  c = a * b;
+  EXPECT_EQ(1, c);
+
+  // Self-operation with max carries.
+  c = uint128(0) - 1;
+  c *= c;
+  EXPECT_EQ(1, c);
+
+  // 1-bit x 1-bit.
+  for (int i = 0; i < 64; ++i) {
+    for (int j = 0; j < 64; ++j) {
+      a = uint128(1) << i;
+      b = uint128(1) << j;
+      c = a * b;
+      EXPECT_EQ(uint128(1) << (i+j), c);
+    }
+  }
+
+  // Verified with dc.
+  a = uint128(GOOGLE_ULONGLONG(0xffffeeeeddddcccc),
+              GOOGLE_ULONGLONG(0xbbbbaaaa99998888));
+  b = uint128(GOOGLE_ULONGLONG(0x7777666655554444),
+              GOOGLE_ULONGLONG(0x3333222211110000));
+  c = a * b;
+  EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x530EDA741C71D4C3),
+                    GOOGLE_ULONGLONG(0xBF25975319080000)), c);
+  EXPECT_EQ(0, c - b * a);
+  EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+
+  // Verified with dc.
+  a = uint128(GOOGLE_ULONGLONG(0x0123456789abcdef),
+              GOOGLE_ULONGLONG(0xfedcba9876543210));
+  b = uint128(GOOGLE_ULONGLONG(0x02468ace13579bdf),
+              GOOGLE_ULONGLONG(0xfdb97531eca86420));
+  c = a * b;
+  EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x97a87f4f261ba3f2),
+                    GOOGLE_ULONGLONG(0x342d0bbf48948200)), c);
+  EXPECT_EQ(0, c - b * a);
+  EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+}
+
+TEST(Int128, AliasTests) {
+  uint128 x1(1, 2);
+  uint128 x2(2, 4);
+  x1 += x1;
+  EXPECT_EQ(x2, x1);
+
+  uint128 x3(1, static_cast<uint64>(1) << 63);
+  uint128 x4(3, 0);
+  x3 += x3;
+  EXPECT_EQ(x4, x3);
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(Int128, DivideByZeroCheckFails) {
+  uint128 a = 0;
+  uint128 b = 0;
+  EXPECT_DEATH(a / b, "Division or mod by zero:");
+  a = 123;
+  EXPECT_DEATH(a / b, "Division or mod by zero:");
+}
+
+TEST(Int128, ModByZeroCheckFails) {
+  uint128 a = 0;
+  uint128 b = 0;
+  EXPECT_DEATH(a % b, "Division or mod by zero:");
+  a = 123;
+  EXPECT_DEATH(a % b, "Division or mod by zero:");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+TEST(Int128, DivideAndMod) {
+  // a := q * b + r
+  uint128 a, b, q, r;
+
+  // Zero test.
+  a = 0;
+  b = 123;
+  q = a / b;
+  r = a % b;
+  EXPECT_EQ(0, q);
+  EXPECT_EQ(0, r);
+
+  a = uint128(GOOGLE_ULONGLONG(0x530eda741c71d4c3),
+              GOOGLE_ULONGLONG(0xbf25975319080000));
+  q = uint128(GOOGLE_ULONGLONG(0x4de2cab081),
+              GOOGLE_ULONGLONG(0x14c34ab4676e4bab));
+  b = uint128(0x1110001);
+  r = uint128(0x3eb455);
+  ASSERT_EQ(a, q * b + r);  // Sanity-check.
+
+  uint128 result_q, result_r;
+  result_q = a / b;
+  result_r = a % b;
+  EXPECT_EQ(q, result_q);
+  EXPECT_EQ(r, result_r);
+
+  // Try the other way around.
+  swap(q, b);
+  result_q = a / b;
+  result_r = a % b;
+  EXPECT_EQ(q, result_q);
+  EXPECT_EQ(r, result_r);
+  // Restore.
+  swap(b, q);
+
+  // Dividend < divisor; result should be q:0 r:<dividend>.
+  swap(a, b);
+  result_q = a / b;
+  result_r = a % b;
+  EXPECT_EQ(0, result_q);
+  EXPECT_EQ(a, result_r);
+  // Try the other way around.
+  swap(a, q);
+  result_q = a / b;
+  result_r = a % b;
+  EXPECT_EQ(0, result_q);
+  EXPECT_EQ(a, result_r);
+  // Restore.
+  swap(q, a);
+  swap(b, a);
+
+  // Try a large remainder.
+  b = a / 2 + 1;
+  uint128 expected_r(GOOGLE_ULONGLONG(0x29876d3a0e38ea61),
+                     GOOGLE_ULONGLONG(0xdf92cba98c83ffff));
+  // Sanity checks.
+  ASSERT_EQ(a / 2 - 1, expected_r);
+  ASSERT_EQ(a, b + expected_r);
+  result_q = a / b;
+  result_r = a % b;
+  EXPECT_EQ(1, result_q);
+  EXPECT_EQ(expected_r, result_r);
+}
+
+static uint64 RandomUint64() {
+  uint64 v1 = rand();
+  uint64 v2 = rand();
+  uint64 v3 = rand();
+  return v1 * v2 + v3;
+}
+
+TEST(Int128, DivideAndModRandomInputs) {
+  const int kNumIters = 1 << 18;
+  for (int i = 0; i < kNumIters; ++i) {
+    const uint128 a(RandomUint64(), RandomUint64());
+    const uint128 b(RandomUint64(), RandomUint64());
+    if (b == 0) {
+      continue;  // Avoid a div-by-zero.
+    }
+    const uint128 q = a / b;
+    const uint128 r = a % b;
+    ASSERT_EQ(a, b * q + r);
+  }
+}
+
+#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
+TEST(Int128, ConstexprTest) {
+  constexpr uint128 zero;
+  constexpr uint128 one = 1;
+  constexpr uint128_pod pod = {2, 3};
+  constexpr uint128 from_pod = pod;
+  constexpr uint128 minus_two = -2;
+  EXPECT_EQ(one, uint128(1));
+  EXPECT_EQ(from_pod, uint128(2, 3));
+  EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL));
+}
+
+TEST(Int128, Traits) {
+  EXPECT_TRUE(std::is_trivially_copy_constructible<uint128>::value);
+  EXPECT_TRUE(std::is_trivially_copy_assignable<uint128>::value);
+  EXPECT_TRUE(std::is_trivially_destructible<uint128>::value);
+}
+#endif  // GOOGLE_PROTOBUF_HAS_CONSTEXPR
+
+TEST(Int128, OStream) {
+  struct {
+    uint128 val;
+    std::ios_base::fmtflags flags;
+    std::streamsize width;
+    char fill;
+    const char* rep;
+  } cases[] = {
+        // zero with different bases
+        {uint128(0), std::ios::dec, 0, '_', "0"},
+        {uint128(0), std::ios::oct, 0, '_', "0"},
+        {uint128(0), std::ios::hex, 0, '_', "0"},
+        // crossover between lo_ and hi_
+        {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
+        {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
+        {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
+        {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
+        {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
+        {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
+        // just the top bit
+        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, '_',
+         "170141183460469231731687303715884105728"},
+        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, '_',
+         "2000000000000000000000000000000000000000000"},
+        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, '_',
+         "80000000000000000000000000000000"},
+        // maximum uint128 value
+        {uint128(-1, -1), std::ios::dec, 0, '_',
+         "340282366920938463463374607431768211455"},
+        {uint128(-1, -1), std::ios::oct, 0, '_',
+         "3777777777777777777777777777777777777777777"},
+        {uint128(-1, -1), std::ios::hex, 0, '_',
+         "ffffffffffffffffffffffffffffffff"},
+        // uppercase
+        {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
+         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
+        // showbase
+        {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"},
+        {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"},
+        {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"},
+        // showbase does nothing on zero
+        {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"},
+        {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"},
+        {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"},
+        // showpos does nothing on unsigned types
+        {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"},
+        // padding
+        {uint128(9), std::ios::dec, 6, '_', "_____9"},
+        {uint128(12345), std::ios::dec, 6, '_', "_12345"},
+        // left adjustment
+        {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"},
+        {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"},
+  };
+  for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) {
+    ostringstream os;
+    os.flags(cases[i].flags);
+    os.width(cases[i].width);
+    os.fill(cases[i].fill);
+    os << cases[i].val;
+    EXPECT_EQ(cases[i].rep, os.str());
+  }
+}
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/logging.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/logging.h
new file mode 100644
index 0000000..f69605d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/logging.h
@@ -0,0 +1,237 @@
+// 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_STUBS_LOGGING_H_
+#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
+
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/port.h>
+
+// ===================================================================
+// emulates google3/base/logging.h
+
+namespace google {
+namespace protobuf {
+
+enum LogLevel {
+  LOGLEVEL_INFO,     // Informational.  This is never actually used by
+                     // libprotobuf.
+  LOGLEVEL_WARNING,  // Warns about issues that, although not technically a
+                     // problem now, could cause problems in the future.  For
+                     // example, a // warning will be printed when parsing a
+                     // message that is near the message size limit.
+  LOGLEVEL_ERROR,    // An error occurred which should never happen during
+                     // normal use.
+  LOGLEVEL_FATAL,    // An error occurred from which the library cannot
+                     // recover.  This usually indicates a programming error
+                     // in the code which calls the library, especially when
+                     // compiled in debug mode.
+
+#ifdef NDEBUG
+  LOGLEVEL_DFATAL = LOGLEVEL_ERROR
+#else
+  LOGLEVEL_DFATAL = LOGLEVEL_FATAL
+#endif
+};
+
+class StringPiece;
+namespace util {
+class Status;
+}
+class uint128;
+namespace internal {
+
+class LogFinisher;
+
+class LIBPROTOBUF_EXPORT LogMessage {
+ public:
+  LogMessage(LogLevel level, const char* filename, int line);
+  ~LogMessage();
+
+  LogMessage& operator<<(const std::string& value);
+  LogMessage& operator<<(const char* value);
+  LogMessage& operator<<(char value);
+  LogMessage& operator<<(int value);
+  LogMessage& operator<<(uint value);
+  LogMessage& operator<<(long value);
+  LogMessage& operator<<(unsigned long value);
+  LogMessage& operator<<(long long value);
+  LogMessage& operator<<(unsigned long long value);
+  LogMessage& operator<<(double value);
+  LogMessage& operator<<(void* value);
+  LogMessage& operator<<(const StringPiece& value);
+  LogMessage& operator<<(const ::google::protobuf::util::Status& status);
+  LogMessage& operator<<(const uint128& value);
+
+ private:
+  friend class LogFinisher;
+  void Finish();
+
+  LogLevel level_;
+  const char* filename_;
+  int line_;
+  std::string message_;
+};
+
+// Used to make the entire "LOG(BLAH) << etc." expression have a void return
+// type and print a newline after each message.
+class LIBPROTOBUF_EXPORT LogFinisher {
+ public:
+  void operator=(LogMessage& other);
+};
+
+template<typename T>
+bool IsOk(T status) { return status.ok(); }
+template<>
+inline bool IsOk(bool status) { return status; }
+
+}  // namespace internal
+
+// Undef everything in case we're being mixed with some other Google library
+// which already defined them itself.  Presumably all Google libraries will
+// support the same syntax for these so it should not be a big deal if they
+// end up using our definitions instead.
+#undef GOOGLE_LOG
+#undef GOOGLE_LOG_IF
+
+#undef GOOGLE_CHECK
+#undef GOOGLE_CHECK_OK
+#undef GOOGLE_CHECK_EQ
+#undef GOOGLE_CHECK_NE
+#undef GOOGLE_CHECK_LT
+#undef GOOGLE_CHECK_LE
+#undef GOOGLE_CHECK_GT
+#undef GOOGLE_CHECK_GE
+#undef GOOGLE_CHECK_NOTNULL
+
+#undef GOOGLE_DLOG
+#undef GOOGLE_DCHECK
+#undef GOOGLE_DCHECK_OK
+#undef GOOGLE_DCHECK_EQ
+#undef GOOGLE_DCHECK_NE
+#undef GOOGLE_DCHECK_LT
+#undef GOOGLE_DCHECK_LE
+#undef GOOGLE_DCHECK_GT
+#undef GOOGLE_DCHECK_GE
+
+#define GOOGLE_LOG(LEVEL)                                                 \
+  ::google::protobuf::internal::LogFinisher() =                           \
+    ::google::protobuf::internal::LogMessage(                             \
+      ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
+#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
+  !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
+
+#define GOOGLE_CHECK(EXPRESSION) \
+  GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
+#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
+#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
+#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
+#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) <  (B))
+#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
+#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) >  (B))
+#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
+
+namespace internal {
+template<typename T>
+T* CheckNotNull(const char* /* file */, int /* line */,
+                const char* name, T* val) {
+  if (val == NULL) {
+    GOOGLE_LOG(FATAL) << name;
+  }
+  return val;
+}
+}  // namespace internal
+#define GOOGLE_CHECK_NOTNULL(A) \
+  ::google::protobuf::internal::CheckNotNull(\
+      __FILE__, __LINE__, "'" #A "' must not be NULL", (A))
+
+#ifdef NDEBUG
+
+#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false)
+
+#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
+#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
+#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
+#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
+#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) <  (B))
+#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
+#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) >  (B))
+#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
+
+#else  // NDEBUG
+
+#define GOOGLE_DLOG GOOGLE_LOG
+
+#define GOOGLE_DCHECK    GOOGLE_CHECK
+#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK
+#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
+#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
+#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
+#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
+#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
+#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
+
+#endif  // !NDEBUG
+
+typedef void LogHandler(LogLevel level, const char* filename, int line,
+                        const std::string& message);
+
+// The protobuf library sometimes writes warning and error messages to
+// stderr.  These messages are primarily useful for developers, but may
+// also help end users figure out a problem.  If you would prefer that
+// these messages be sent somewhere other than stderr, call SetLogHandler()
+// to set your own handler.  This returns the old handler.  Set the handler
+// to NULL to ignore log messages (but see also LogSilencer, below).
+//
+// Obviously, SetLogHandler is not thread-safe.  You should only call it
+// at initialization time, and probably not from library code.  If you
+// simply want to suppress log messages temporarily (e.g. because you
+// have some code that tends to trigger them frequently and you know
+// the warnings are not important to you), use the LogSilencer class
+// below.
+LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
+
+// Create a LogSilencer if you want to temporarily suppress all log
+// messages.  As long as any LogSilencer objects exist, non-fatal
+// log messages will be discarded (the current LogHandler will *not*
+// be called).  Constructing a LogSilencer is thread-safe.  You may
+// accidentally suppress log messages occurring in another thread, but
+// since messages are generally for debugging purposes only, this isn't
+// a big deal.  If you want to intercept log messages, use SetLogHandler().
+class LIBPROTOBUF_EXPORT LogSilencer {
+ public:
+  LogSilencer();
+  ~LogSilencer();
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/macros.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/macros.h
new file mode 100644
index 0000000..0e9a9ec
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/macros.h
@@ -0,0 +1,168 @@
+// 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_MACROS_H__
+#define GOOGLE_PROTOBUF_MACROS_H__
+
+#include <google/protobuf/stubs/port.h>
+
+namespace google {
+namespace protobuf {
+
+#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
+#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
+  TypeName(const TypeName&);                           \
+  void operator=(const TypeName&)
+
+#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
+#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName();                                           \
+  TypeName(const TypeName&);                            \
+  void operator=(const TypeName&)
+
+// ===================================================================
+// from google3/base/basictypes.h
+
+// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.
+//
+// GOOGLE_ARRAYSIZE catches a few type errors.  If you see a compiler error
+//
+//   "warning: division by zero in ..."
+//
+// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
+// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element).  If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array.  Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size.  Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+//
+// Kudos to Jorg Brown for this simple and elegant implementation.
+
+#undef GOOGLE_ARRAYSIZE
+#define GOOGLE_ARRAYSIZE(a) \
+  ((sizeof(a) / sizeof(*(a))) / \
+   static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+// The COMPILE_ASSERT macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                  content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+namespace internal {
+
+template <bool>
+struct CompileAssert {
+};
+
+}  // namespace internal
+
+#undef GOOGLE_COMPILE_ASSERT
+#if __cplusplus >= 201103L
+#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
+#else
+#define GOOGLE_COMPILE_ASSERT(expr, msg) \
+  ::google::protobuf::internal::CompileAssert<(bool(expr))> \
+          msg[bool(expr) ? 1 : -1]; \
+  (void)msg
+// Implementation details of COMPILE_ASSERT:
+//
+// - COMPILE_ASSERT works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//     #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
+//                               // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     COMPILE_ASSERT(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+#endif  // __cplusplus >= 201103L
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_MACROS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/map_util.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/map_util.h
new file mode 100644
index 0000000..4cccbbe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/map_util.h
@@ -0,0 +1,769 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+// from google3/util/gtl/map_util.h
+// Author: Anton Carver
+
+#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
+
+#include <stddef.h>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Local implementation of RemoveConst to avoid including base/type_traits.h.
+template <class T> struct RemoveConst { typedef T type; };
+template <class T> struct RemoveConst<const T> : RemoveConst<T> {};
+}  // namespace internal
+
+//
+// Find*()
+//
+
+// Returns a const reference to the value associated with the given key if it
+// exists. Crashes otherwise.
+//
+// This is intended as a replacement for operator[] as an rvalue (for reading)
+// when the key is guaranteed to exist.
+//
+// operator[] for lookup is discouraged for several reasons:
+//  * It has a side-effect of inserting missing keys
+//  * It is not thread-safe (even when it is not inserting, it can still
+//      choose to resize the underlying storage)
+//  * It invalidates iterators (when it chooses to resize)
+//  * It default constructs a value object even if it doesn't need to
+//
+// This version assumes the key is printable, and includes it in the fatal log
+// message.
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindOrDie(const Collection& collection,
+          const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
+  return it->second;
+}
+
+// Same as above, but returns a non-const reference.
+template <class Collection>
+typename Collection::value_type::second_type&
+FindOrDie(Collection& collection,  // NOLINT
+          const typename Collection::value_type::first_type& key) {
+  typename Collection::iterator it = collection.find(key);
+  GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
+  return it->second;
+}
+
+// Same as FindOrDie above, but doesn't log the key on failure.
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindOrDieNoPrint(const Collection& collection,
+                 const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  GOOGLE_CHECK(it != collection.end()) << "Map key not found";
+  return it->second;
+}
+
+// Same as above, but returns a non-const reference.
+template <class Collection>
+typename Collection::value_type::second_type&
+FindOrDieNoPrint(Collection& collection,  // NOLINT
+                 const typename Collection::value_type::first_type& key) {
+  typename Collection::iterator it = collection.find(key);
+  GOOGLE_CHECK(it != collection.end()) << "Map key not found";
+  return it->second;
+}
+
+// Returns a const reference to the value associated with the given key if it
+// exists, otherwise returns a const reference to the provided default value.
+//
+// WARNING: If a temporary object is passed as the default "value,"
+// this function will return a reference to that temporary object,
+// which will be destroyed at the end of the statement. A common
+// example: if you have a map with string values, and you pass a char*
+// as the default "value," either use the returned value immediately
+// or store it in a string (not string&).
+// Details: http://go/findwithdefault
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindWithDefault(const Collection& collection,
+                const typename Collection::value_type::first_type& key,
+                const typename Collection::value_type::second_type& value) {
+  typename Collection::const_iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return value;
+  }
+  return it->second;
+}
+
+// Returns a pointer to the const value associated with the given key if it
+// exists, or NULL otherwise.
+template <class Collection>
+const typename Collection::value_type::second_type*
+FindOrNull(const Collection& collection,
+           const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return 0;
+  }
+  return &it->second;
+}
+
+// Same as above but returns a pointer to the non-const value.
+template <class Collection>
+typename Collection::value_type::second_type*
+FindOrNull(Collection& collection,  // NOLINT
+           const typename Collection::value_type::first_type& key) {
+  typename Collection::iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return 0;
+  }
+  return &it->second;
+}
+
+// Returns the pointer value associated with the given key. If none is found,
+// NULL is returned. The function is designed to be used with a map of keys to
+// pointers.
+//
+// This function does not distinguish between a missing key and a key mapped
+// to a NULL value.
+template <class Collection>
+typename Collection::value_type::second_type
+FindPtrOrNull(const Collection& collection,
+              const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return typename Collection::value_type::second_type();
+  }
+  return it->second;
+}
+
+// Same as above, except takes non-const reference to collection.
+//
+// This function is needed for containers that propagate constness to the
+// pointee, such as boost::ptr_map.
+template <class Collection>
+typename Collection::value_type::second_type
+FindPtrOrNull(Collection& collection,  // NOLINT
+              const typename Collection::value_type::first_type& key) {
+  typename Collection::iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return typename Collection::value_type::second_type();
+  }
+  return it->second;
+}
+
+// Finds the pointer value associated with the given key in a map whose values
+// are linked_ptrs. Returns NULL if key is not found.
+template <class Collection>
+typename Collection::value_type::second_type::element_type*
+FindLinkedPtrOrNull(const Collection& collection,
+                    const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return 0;
+  }
+  // Since linked_ptr::get() is a const member returning a non const,
+  // we do not need a version of this function taking a non const collection.
+  return it->second.get();
+}
+
+// Same as above, but dies if the key is not found.
+template <class Collection>
+typename Collection::value_type::second_type::element_type&
+FindLinkedPtrOrDie(const Collection& collection,
+                   const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  CHECK(it != collection.end()) <<  "key not found: " << key;
+  // Since linked_ptr::operator*() is a const member returning a non const,
+  // we do not need a version of this function taking a non const collection.
+  return *it->second;
+}
+
+// Finds the value associated with the given key and copies it to *value (if not
+// NULL). Returns false if the key was not found, true otherwise.
+template <class Collection, class Key, class Value>
+bool FindCopy(const Collection& collection,
+              const Key& key,
+              Value* const value) {
+  typename Collection::const_iterator it = collection.find(key);
+  if (it == collection.end()) {
+    return false;
+  }
+  if (value) {
+    *value = it->second;
+  }
+  return true;
+}
+
+//
+// Contains*()
+//
+
+// Returns true if and only if the given collection contains the given key.
+template <class Collection, class Key>
+bool ContainsKey(const Collection& collection, const Key& key) {
+  return collection.find(key) != collection.end();
+}
+
+// Returns true if and only if the given collection contains the given key-value
+// pair.
+template <class Collection, class Key, class Value>
+bool ContainsKeyValuePair(const Collection& collection,
+                          const Key& key,
+                          const Value& value) {
+  typedef typename Collection::const_iterator const_iterator;
+  std::pair<const_iterator, const_iterator> range = collection.equal_range(key);
+  for (const_iterator it = range.first; it != range.second; ++it) {
+    if (it->second == value) {
+      return true;
+    }
+  }
+  return false;
+}
+
+//
+// Insert*()
+//
+
+// Inserts the given key-value pair into the collection. Returns true if and
+// only if the key from the given pair didn't previously exist. Otherwise, the
+// value in the map is replaced with the value from the given pair.
+template <class Collection>
+bool InsertOrUpdate(Collection* const collection,
+                    const typename Collection::value_type& vt) {
+  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
+  if (!ret.second) {
+    // update
+    ret.first->second = vt.second;
+    return false;
+  }
+  return true;
+}
+
+// Same as above, except that the key and value are passed separately.
+template <class Collection>
+bool InsertOrUpdate(Collection* const collection,
+                    const typename Collection::value_type::first_type& key,
+                    const typename Collection::value_type::second_type& value) {
+  return InsertOrUpdate(
+      collection, typename Collection::value_type(key, value));
+}
+
+// Inserts/updates all the key-value pairs from the range defined by the
+// iterators "first" and "last" into the given collection.
+template <class Collection, class InputIterator>
+void InsertOrUpdateMany(Collection* const collection,
+                        InputIterator first, InputIterator last) {
+  for (; first != last; ++first) {
+    InsertOrUpdate(collection, *first);
+  }
+}
+
+// Change the value associated with a particular key in a map or hash_map
+// of the form map<Key, Value*> which owns the objects pointed to by the
+// value pointers.  If there was an existing value for the key, it is deleted.
+// True indicates an insert took place, false indicates an update + delete.
+template <class Collection>
+bool InsertAndDeleteExisting(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const typename Collection::value_type::second_type& value) {
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, value));
+  if (!ret.second) {
+    delete ret.first->second;
+    ret.first->second = value;
+    return false;
+  }
+  return true;
+}
+
+// Inserts the given key and value into the given collection if and only if the
+// given key did NOT already exist in the collection. If the key previously
+// existed in the collection, the value is not changed. Returns true if the
+// key-value pair was inserted; returns false if the key was already present.
+template <class Collection>
+bool InsertIfNotPresent(Collection* const collection,
+                        const typename Collection::value_type& vt) {
+  return collection->insert(vt).second;
+}
+
+// Same as above except the key and value are passed separately.
+template <class Collection>
+bool InsertIfNotPresent(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const typename Collection::value_type::second_type& value) {
+  return InsertIfNotPresent(
+      collection, typename Collection::value_type(key, value));
+}
+
+// Same as above except dies if the key already exists in the collection.
+template <class Collection>
+void InsertOrDie(Collection* const collection,
+                 const typename Collection::value_type& value) {
+  CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value;
+}
+
+// Same as above except doesn't log the value on error.
+template <class Collection>
+void InsertOrDieNoPrint(Collection* const collection,
+                        const typename Collection::value_type& value) {
+  CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
+}
+
+// Inserts the key-value pair into the collection. Dies if key was already
+// present.
+template <class Collection>
+void InsertOrDie(Collection* const collection,
+                 const typename Collection::value_type::first_type& key,
+                 const typename Collection::value_type::second_type& data) {
+  GOOGLE_CHECK(InsertIfNotPresent(collection, key, data))
+      << "duplicate key: " << key;
+}
+
+// Same as above except doesn't log the key on error.
+template <class Collection>
+void InsertOrDieNoPrint(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const typename Collection::value_type::second_type& data) {
+  GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key.";
+}
+
+// Inserts a new key and default-initialized value. Dies if the key was already
+// present. Returns a reference to the value. Example usage:
+//
+// map<int, SomeProto> m;
+// SomeProto& proto = InsertKeyOrDie(&m, 3);
+// proto.set_field("foo");
+template <class Collection>
+typename Collection::value_type::second_type& InsertKeyOrDie(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key) {
+  typedef typename Collection::value_type value_type;
+  std::pair<typename Collection::iterator, bool> res =
+      collection->insert(value_type(key, typename value_type::second_type()));
+  GOOGLE_CHECK(res.second) << "duplicate key: " << key;
+  return res.first->second;
+}
+
+//
+// Lookup*()
+//
+
+// Looks up a given key and value pair in a collection and inserts the key-value
+// pair if it's not already present. Returns a reference to the value associated
+// with the key.
+template <class Collection>
+typename Collection::value_type::second_type&
+LookupOrInsert(Collection* const collection,
+               const typename Collection::value_type& vt) {
+  return collection->insert(vt).first->second;
+}
+
+// Same as above except the key-value are passed separately.
+template <class Collection>
+typename Collection::value_type::second_type&
+LookupOrInsert(Collection* const collection,
+               const typename Collection::value_type::first_type& key,
+               const typename Collection::value_type::second_type& value) {
+  return LookupOrInsert(
+      collection, typename Collection::value_type(key, value));
+}
+
+// Counts the number of equivalent elements in the given "sequence", and stores
+// the results in "count_map" with element as the key and count as the value.
+//
+// Example:
+//   vector<string> v = {"a", "b", "c", "a", "b"};
+//   map<string, int> m;
+//   AddTokenCounts(v, 1, &m);
+//   assert(m["a"] == 2);
+//   assert(m["b"] == 2);
+//   assert(m["c"] == 1);
+template <typename Sequence, typename Collection>
+void AddTokenCounts(
+    const Sequence& sequence,
+    const typename Collection::value_type::second_type& increment,
+    Collection* const count_map) {
+  for (typename Sequence::const_iterator it = sequence.begin();
+       it != sequence.end(); ++it) {
+    typename Collection::value_type::second_type& value =
+        LookupOrInsert(count_map, *it,
+                       typename Collection::value_type::second_type());
+    value += increment;
+  }
+}
+
+// Returns a reference to the value associated with key. If not found, a value
+// is default constructed on the heap and added to the map.
+//
+// This function is useful for containers of the form map<Key, Value*>, where
+// inserting a new key, value pair involves constructing a new heap-allocated
+// Value, and storing a pointer to that in the collection.
+template <class Collection>
+typename Collection::value_type::second_type&
+LookupOrInsertNew(Collection* const collection,
+                  const typename Collection::value_type::first_type& key) {
+  typedef typename std::iterator_traits<
+    typename Collection::value_type::second_type>::value_type Element;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(
+          key,
+          static_cast<typename Collection::value_type::second_type>(NULL)));
+  if (ret.second) {
+    ret.first->second = new Element();
+  }
+  return ret.first->second;
+}
+
+// Same as above but constructs the value using the single-argument constructor
+// and the given "arg".
+template <class Collection, class Arg>
+typename Collection::value_type::second_type&
+LookupOrInsertNew(Collection* const collection,
+                  const typename Collection::value_type::first_type& key,
+                  const Arg& arg) {
+  typedef typename std::iterator_traits<
+    typename Collection::value_type::second_type>::value_type Element;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(
+          key,
+          static_cast<typename Collection::value_type::second_type>(NULL)));
+  if (ret.second) {
+    ret.first->second = new Element(arg);
+  }
+  return ret.first->second;
+}
+
+// Lookup of linked/shared pointers is used in two scenarios:
+//
+// Use LookupOrInsertNewLinkedPtr if the container owns the elements.
+// In this case it is fine working with the raw pointer as long as it is
+// guaranteed that no other thread can delete/update an accessed element.
+// A mutex will need to lock the container operation as well as the use
+// of the returned elements. Finding an element may be performed using
+// FindLinkedPtr*().
+//
+// Use LookupOrInsertNewSharedPtr if the container does not own the elements
+// for their whole lifetime. This is typically the case when a reader allows
+// parallel updates to the container. In this case a Mutex only needs to lock
+// container operations, but all element operations must be performed on the
+// shared pointer. Finding an element must be performed using FindPtr*() and
+// cannot be done with FindLinkedPtr*() even though it compiles.
+
+// Lookup a key in a map or hash_map whose values are linked_ptrs.  If it is
+// missing, set collection[key].reset(new Value::element_type) and return that.
+// Value::element_type must be default constructable.
+template <class Collection>
+typename Collection::value_type::second_type::element_type*
+LookupOrInsertNewLinkedPtr(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key) {
+  typedef typename Collection::value_type::second_type Value;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, Value()));
+  if (ret.second) {
+    ret.first->second.reset(new typename Value::element_type);
+  }
+  return ret.first->second.get();
+}
+
+// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using
+// a single-parameter constructor.  Note: the constructor argument is computed
+// even if it will not be used, so only values cheap to compute should be passed
+// here.  On the other hand it does not matter how expensive the construction of
+// the actual stored value is, as that only occurs if necessary.
+template <class Collection, class Arg>
+typename Collection::value_type::second_type::element_type*
+LookupOrInsertNewLinkedPtr(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const Arg& arg) {
+  typedef typename Collection::value_type::second_type Value;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, Value()));
+  if (ret.second) {
+    ret.first->second.reset(new typename Value::element_type(arg));
+  }
+  return ret.first->second.get();
+}
+
+// Lookup a key in a map or hash_map whose values are shared_ptrs.  If it is
+// missing, set collection[key].reset(new Value::element_type). Unlike
+// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of
+// the raw pointer. Value::element_type must be default constructable.
+template <class Collection>
+typename Collection::value_type::second_type&
+LookupOrInsertNewSharedPtr(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key) {
+  typedef typename Collection::value_type::second_type SharedPtr;
+  typedef typename Collection::value_type::second_type::element_type Element;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, SharedPtr()));
+  if (ret.second) {
+    ret.first->second.reset(new Element());
+  }
+  return ret.first->second;
+}
+
+// A variant of LookupOrInsertNewSharedPtr where the value is constructed using
+// a single-parameter constructor.  Note: the constructor argument is computed
+// even if it will not be used, so only values cheap to compute should be passed
+// here.  On the other hand it does not matter how expensive the construction of
+// the actual stored value is, as that only occurs if necessary.
+template <class Collection, class Arg>
+typename Collection::value_type::second_type&
+LookupOrInsertNewSharedPtr(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const Arg& arg) {
+  typedef typename Collection::value_type::second_type SharedPtr;
+  typedef typename Collection::value_type::second_type::element_type Element;
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, SharedPtr()));
+  if (ret.second) {
+    ret.first->second.reset(new Element(arg));
+  }
+  return ret.first->second;
+}
+
+//
+// Misc Utility Functions
+//
+
+// Updates the value associated with the given key. If the key was not already
+// present, then the key-value pair are inserted and "previous" is unchanged. If
+// the key was already present, the value is updated and "*previous" will
+// contain a copy of the old value.
+//
+// InsertOrReturnExisting has complementary behavior that returns the
+// address of an already existing value, rather than updating it.
+template <class Collection>
+bool UpdateReturnCopy(Collection* const collection,
+                      const typename Collection::value_type::first_type& key,
+                      const typename Collection::value_type::second_type& value,
+                      typename Collection::value_type::second_type* previous) {
+  std::pair<typename Collection::iterator, bool> ret =
+      collection->insert(typename Collection::value_type(key, value));
+  if (!ret.second) {
+    // update
+    if (previous) {
+      *previous = ret.first->second;
+    }
+    ret.first->second = value;
+    return true;
+  }
+  return false;
+}
+
+// Same as above except that the key and value are passed as a pair.
+template <class Collection>
+bool UpdateReturnCopy(Collection* const collection,
+                      const typename Collection::value_type& vt,
+                      typename Collection::value_type::second_type* previous) {
+  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
+  if (!ret.second) {
+    // update
+    if (previous) {
+      *previous = ret.first->second;
+    }
+    ret.first->second = vt.second;
+    return true;
+  }
+  return false;
+}
+
+// Tries to insert the given key-value pair into the collection. Returns NULL if
+// the insert succeeds. Otherwise, returns a pointer to the existing value.
+//
+// This complements UpdateReturnCopy in that it allows to update only after
+// verifying the old value and still insert quickly without having to look up
+// twice. Unlike UpdateReturnCopy this also does not come with the issue of an
+// undefined previous* in case new data was inserted.
+template <class Collection>
+typename Collection::value_type::second_type* const
+InsertOrReturnExisting(Collection* const collection,
+                       const typename Collection::value_type& vt) {
+  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
+  if (ret.second) {
+    return NULL;  // Inserted, no existing previous value.
+  } else {
+    return &ret.first->second;  // Return address of already existing value.
+  }
+}
+
+// Same as above, except for explicit key and data.
+template <class Collection>
+typename Collection::value_type::second_type* const
+InsertOrReturnExisting(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key,
+    const typename Collection::value_type::second_type& data) {
+  return InsertOrReturnExisting(collection,
+                                typename Collection::value_type(key, data));
+}
+
+// Erases the collection item identified by the given key, and returns the value
+// associated with that key. It is assumed that the value (i.e., the
+// mapped_type) is a pointer. Returns NULL if the key was not found in the
+// collection.
+//
+// Examples:
+//   map<string, MyType*> my_map;
+//
+// One line cleanup:
+//     delete EraseKeyReturnValuePtr(&my_map, "abc");
+//
+// Use returned value:
+//     scoped_ptr<MyType> value_ptr(EraseKeyReturnValuePtr(&my_map, "abc"));
+//     if (value_ptr.get())
+//       value_ptr->DoSomething();
+//
+template <class Collection>
+typename Collection::value_type::second_type EraseKeyReturnValuePtr(
+    Collection* const collection,
+    const typename Collection::value_type::first_type& key) {
+  typename Collection::iterator it = collection->find(key);
+  if (it == collection->end()) {
+    return NULL;
+  }
+  typename Collection::value_type::second_type v = it->second;
+  collection->erase(it);
+  return v;
+}
+
+// Inserts all the keys from map_container into key_container, which must
+// support insert(MapContainer::key_type).
+//
+// Note: any initial contents of the key_container are not cleared.
+template <class MapContainer, class KeyContainer>
+void InsertKeysFromMap(const MapContainer& map_container,
+                       KeyContainer* key_container) {
+  GOOGLE_CHECK(key_container != NULL);
+  for (typename MapContainer::const_iterator it = map_container.begin();
+       it != map_container.end(); ++it) {
+    key_container->insert(it->first);
+  }
+}
+
+// Appends all the keys from map_container into key_container, which must
+// support push_back(MapContainer::key_type).
+//
+// Note: any initial contents of the key_container are not cleared.
+template <class MapContainer, class KeyContainer>
+void AppendKeysFromMap(const MapContainer& map_container,
+                       KeyContainer* key_container) {
+  GOOGLE_CHECK(key_container != NULL);
+  for (typename MapContainer::const_iterator it = map_container.begin();
+       it != map_container.end(); ++it) {
+    key_container->push_back(it->first);
+  }
+}
+
+// A more specialized overload of AppendKeysFromMap to optimize reallocations
+// for the common case in which we're appending keys to a vector and hence can
+// (and sometimes should) call reserve() first.
+//
+// (It would be possible to play SFINAE games to call reserve() for any
+// container that supports it, but this seems to get us 99% of what we need
+// without the complexity of a SFINAE-based solution.)
+template <class MapContainer, class KeyType>
+void AppendKeysFromMap(const MapContainer& map_container,
+                       vector<KeyType>* key_container) {
+  GOOGLE_CHECK(key_container != NULL);
+  // We now have the opportunity to call reserve(). Calling reserve() every
+  // time is a bad idea for some use cases: libstdc++'s implementation of
+  // vector<>::reserve() resizes the vector's backing store to exactly the
+  // given size (unless it's already at least that big). Because of this,
+  // the use case that involves appending a lot of small maps (total size
+  // N) one by one to a vector would be O(N^2). But never calling reserve()
+  // loses the opportunity to improve the use case of adding from a large
+  // map to an empty vector (this improves performance by up to 33%). A
+  // number of heuristics are possible; see the discussion in
+  // cl/34081696. Here we use the simplest one.
+  if (key_container->empty()) {
+    key_container->reserve(map_container.size());
+  }
+  for (typename MapContainer::const_iterator it = map_container.begin();
+       it != map_container.end(); ++it) {
+    key_container->push_back(it->first);
+  }
+}
+
+// Inserts all the values from map_container into value_container, which must
+// support push_back(MapContainer::mapped_type).
+//
+// Note: any initial contents of the value_container are not cleared.
+template <class MapContainer, class ValueContainer>
+void AppendValuesFromMap(const MapContainer& map_container,
+                         ValueContainer* value_container) {
+  GOOGLE_CHECK(value_container != NULL);
+  for (typename MapContainer::const_iterator it = map_container.begin();
+       it != map_container.end(); ++it) {
+    value_container->push_back(it->second);
+  }
+}
+
+// A more specialized overload of AppendValuesFromMap to optimize reallocations
+// for the common case in which we're appending values to a vector and hence
+// can (and sometimes should) call reserve() first.
+//
+// (It would be possible to play SFINAE games to call reserve() for any
+// container that supports it, but this seems to get us 99% of what we need
+// without the complexity of a SFINAE-based solution.)
+template <class MapContainer, class ValueType>
+void AppendValuesFromMap(const MapContainer& map_container,
+                         vector<ValueType>* value_container) {
+  GOOGLE_CHECK(value_container != NULL);
+  // See AppendKeysFromMap for why this is done.
+  if (value_container->empty()) {
+    value_container->reserve(map_container.size());
+  }
+  for (typename MapContainer::const_iterator it = map_container.begin();
+       it != map_container.end(); ++it) {
+    value_container->push_back(it->second);
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.cc
new file mode 100644
index 0000000..0373b2b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.cc
@@ -0,0 +1,144 @@
+// 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.
+
+// All Rights Reserved.
+//
+// Author: Maxim Lifantsev
+//
+
+#include <google/protobuf/stubs/mathlimits.h>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// MSVC++ 2005 and older compilers think the header declaration was a
+// definition, and erroneously flag these as a duplicate definition.
+#if defined(COMPILER_MSVC) || __cpluscplus < 201103L
+
+#define DEF_COMMON_LIMITS(Type)
+#define DEF_UNSIGNED_INT_LIMITS(Type)
+#define DEF_SIGNED_INT_LIMITS(Type)
+#define DEF_PRECISION_LIMITS(Type)
+
+#else
+
+#define DEF_COMMON_LIMITS(Type) \
+const bool MathLimits<Type>::kIsSigned; \
+const bool MathLimits<Type>::kIsInteger; \
+const int MathLimits<Type>::kMin10Exp; \
+const int MathLimits<Type>::kMax10Exp;
+
+#define DEF_UNSIGNED_INT_LIMITS(Type) \
+DEF_COMMON_LIMITS(Type) \
+const Type MathLimits<Type>::kPosMin; \
+const Type MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kMin; \
+const Type MathLimits<Type>::kMax; \
+const Type MathLimits<Type>::kEpsilon; \
+const Type MathLimits<Type>::kStdError;
+
+#define DEF_SIGNED_INT_LIMITS(Type) \
+DEF_UNSIGNED_INT_LIMITS(Type) \
+const Type MathLimits<Type>::kNegMin; \
+const Type MathLimits<Type>::kNegMax;
+
+#define DEF_PRECISION_LIMITS(Type) \
+const int MathLimits<Type>::kPrecisionDigits;
+
+#endif  // not COMPILER_MSVC
+
+// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic
+// With some compilers (gcc 4.6.x) on some platforms (powerpc64),
+// "long double" is implemented as a pair of double: "double double" format.
+// This causes a problem with epsilon (eps).
+// eps is the smallest positive number such that 1.0 + eps > 1.0
+//
+// Normal format:  1.0 + e = 1.0...01      // N-1 zeros for N fraction bits
+// D-D format:     1.0 + e = 1.000...0001  // epsilon can be very small
+//
+// In the normal format, 1.0 + e has to fit in one stretch of bits.
+// The maximum rounding error is half of eps.
+//
+// In the double-double format, 1.0 + e splits across two doubles:
+// 1.0 in the high double, e in the low double, and they do not have to
+// be contiguous.  The maximum rounding error on a value close to 1.0 is
+// much larger than eps.
+//
+// Some code checks for errors by comparing a computed value to a golden
+// value +/- some multiple of the maximum rounding error.  The maximum
+// rounding error is not available so we use eps as an approximation
+// instead.  That fails when long double is in the double-double format.
+// Therefore, we define kStdError as a multiple of
+// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon.
+
+#define DEF_FP_LIMITS(Type, PREFIX) \
+DEF_COMMON_LIMITS(Type) \
+const Type MathLimits<Type>::kPosMin = PREFIX##_MIN; \
+const Type MathLimits<Type>::kPosMax = PREFIX##_MAX; \
+const Type MathLimits<Type>::kMin = -MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kMax = MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kNegMin = -MathLimits<Type>::kPosMin; \
+const Type MathLimits<Type>::kNegMax = -MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kEpsilon = PREFIX##_EPSILON; \
+/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \
+const Type MathLimits<Type>::kStdError = \
+  32 * (DBL_EPSILON * DBL_EPSILON > MathLimits<Type>::kEpsilon \
+      ? DBL_EPSILON * DBL_EPSILON : MathLimits<Type>::kEpsilon); \
+DEF_PRECISION_LIMITS(Type) \
+const Type MathLimits<Type>::kNaN = HUGE_VAL - HUGE_VAL; \
+const Type MathLimits<Type>::kPosInf = HUGE_VAL; \
+const Type MathLimits<Type>::kNegInf = -HUGE_VAL;
+
+// The following are *not* casts!
+DEF_SIGNED_INT_LIMITS(int8)
+DEF_SIGNED_INT_LIMITS(int16)  // NOLINT(readability/casting)
+DEF_SIGNED_INT_LIMITS(int32)  // NOLINT(readability/casting)
+DEF_SIGNED_INT_LIMITS(int64)  // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint8)
+DEF_UNSIGNED_INT_LIMITS(uint16)  // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint32)  // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint64)  // NOLINT(readability/casting)
+
+DEF_SIGNED_INT_LIMITS(long int)
+DEF_UNSIGNED_INT_LIMITS(unsigned long int)
+
+DEF_FP_LIMITS(float, FLT)
+DEF_FP_LIMITS(double, DBL)
+DEF_FP_LIMITS(long double, LDBL);
+
+#undef DEF_COMMON_LIMITS
+#undef DEF_SIGNED_INT_LIMITS
+#undef DEF_UNSIGNED_INT_LIMITS
+#undef DEF_FP_LIMITS
+#undef DEF_PRECISION_LIMITS
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.h
new file mode 100644
index 0000000..d984694
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathlimits.h
@@ -0,0 +1,279 @@
+// 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.
+
+// All Rights Reserved.
+//
+// Author: Maxim Lifantsev
+//
+// Useful integer and floating point limits and type traits.
+//
+// This partially replaces/duplictes numeric_limits<> from <limits>.
+// We get a Google-style class that we have a greater control over
+// and thus can add new features to it or fix whatever happens to be broken in
+// numeric_limits for the compilers we use.
+//
+
+#ifndef UTIL_MATH_MATHLIMITS_H__
+#define UTIL_MATH_MATHLIMITS_H__
+
+// <math.h> lacks a lot of prototypes. However, this file needs <math.h> to
+// access old-fashioned isinf et al. Even worse more: this file must not
+// include <cmath> because that breaks the definition of isinf with gcc 4.9.
+//
+// TODO(mec): after C++11 everywhere, use <cmath> and std::isinf in this file.
+#include <math.h>
+#include <string.h>
+
+#include <cfloat>
+
+#include <google/protobuf/stubs/common.h>
+
+// ========================================================================= //
+
+// Useful integer and floating point limits and type traits.
+// This is just for the documentation;
+// real members are defined in our specializations below.
+namespace google {
+namespace protobuf {
+template<typename T> struct MathLimits {
+  // Type name.
+  typedef T Type;
+  // Unsigned version of the Type with the same byte size.
+  // Same as Type for floating point and unsigned types.
+  typedef T UnsignedType;
+  // If the type supports negative values.
+  static const bool kIsSigned;
+  // If the type supports only integer values.
+  static const bool kIsInteger;
+  // Magnitude-wise smallest representable positive value.
+  static const Type kPosMin;
+  // Magnitude-wise largest representable positive value.
+  static const Type kPosMax;
+  // Smallest representable value.
+  static const Type kMin;
+  // Largest representable value.
+  static const Type kMax;
+  // Magnitude-wise smallest representable negative value.
+  // Present only if kIsSigned.
+  static const Type kNegMin;
+  // Magnitude-wise largest representable negative value.
+  // Present only if kIsSigned.
+  static const Type kNegMax;
+  // Smallest integer x such that 10^x is representable.
+  static const int kMin10Exp;
+  // Largest integer x such that 10^x is representable.
+  static const int kMax10Exp;
+  // Smallest positive value such that Type(1) + kEpsilon != Type(1)
+  static const Type kEpsilon;
+  // Typical rounding error that is enough to cover
+  // a few simple floating-point operations.
+  // Slightly larger than kEpsilon to account for a few rounding errors.
+  // Is zero if kIsInteger.
+  static const Type kStdError;
+  // Number of decimal digits of mantissa precision.
+  // Present only if !kIsInteger.
+  static const int kPrecisionDigits;
+  // Not a number, i.e. result of 0/0.
+  // Present only if !kIsInteger.
+  static const Type kNaN;
+  // Positive infinity, i.e. result of 1/0.
+  // Present only if !kIsInteger.
+  static const Type kPosInf;
+  // Negative infinity, i.e. result of -1/0.
+  // Present only if !kIsInteger.
+  static const Type kNegInf;
+
+  // NOTE: Special floating point values behave
+  // in a special (but mathematically-logical) way
+  // in terms of (in)equalty comparison and mathematical operations
+  // -- see out unittest for examples.
+
+  // Special floating point value testers.
+  // Present in integer types for convenience.
+  static bool IsFinite(const Type x);
+  static bool IsNaN(const Type x);
+  static bool IsInf(const Type x);
+  static bool IsPosInf(const Type x);
+  static bool IsNegInf(const Type x);
+};
+
+// ========================================================================= //
+
+// All #define-s below are simply to refactor the declarations of
+// MathLimits template specializations.
+// They are all #undef-ined below.
+
+// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not
+// get an overflow while computing the constants.
+
+#define SIGNED_INT_MAX(Type) \
+  (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2)))
+
+#define SIGNED_INT_MIN(Type) \
+  (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2)))
+
+#define UNSIGNED_INT_MAX(Type) \
+  (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1)))
+
+// Compile-time selected log10-related constants for integer types.
+#define SIGNED_MAX_10_EXP(Type) \
+  (sizeof(Type) == 1 ? 2 : ( \
+    sizeof(Type) == 2 ? 4 : ( \
+      sizeof(Type) == 4 ? 9 : ( \
+        sizeof(Type) == 8 ? 18 : -1))))
+
+#define UNSIGNED_MAX_10_EXP(Type) \
+  (sizeof(Type) == 1 ? 2 : ( \
+    sizeof(Type) == 2 ? 4 : ( \
+      sizeof(Type) == 4 ? 9 : ( \
+        sizeof(Type) == 8 ? 19 : -1))))
+
+#define DECL_INT_LIMIT_FUNCS \
+  static bool IsFinite(const Type /*x*/) { return true; } \
+  static bool IsNaN(const Type /*x*/) { return false; } \
+  static bool IsInf(const Type /*x*/) { return false; } \
+  static bool IsPosInf(const Type /*x*/) { return false; } \
+  static bool IsNegInf(const Type /*x*/) { return false; }
+
+#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
+  typedef IntType Type; \
+  typedef UnsignedIntType UnsignedType; \
+  static const bool kIsSigned = true; \
+  static const bool kIsInteger = true; \
+  static const Type kPosMin = 1; \
+  static const Type kPosMax = SIGNED_INT_MAX(Type); \
+  static const Type kMin = SIGNED_INT_MIN(Type); \
+  static const Type kMax = kPosMax; \
+  static const Type kNegMin = -1; \
+  static const Type kNegMax = kMin; \
+  static const int kMin10Exp = 0; \
+  static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \
+  static const Type kEpsilon = 1; \
+  static const Type kStdError = 0; \
+  DECL_INT_LIMIT_FUNCS \
+};
+
+#define DECL_UNSIGNED_INT_LIMITS(IntType) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
+  typedef IntType Type; \
+  typedef IntType UnsignedType; \
+  static const bool kIsSigned = false; \
+  static const bool kIsInteger = true; \
+  static const Type kPosMin = 1; \
+  static const Type kPosMax = UNSIGNED_INT_MAX(Type); \
+  static const Type kMin = 0; \
+  static const Type kMax = kPosMax; \
+  static const int kMin10Exp = 0; \
+  static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \
+  static const Type kEpsilon = 1; \
+  static const Type kStdError = 0; \
+  DECL_INT_LIMIT_FUNCS \
+};
+
+DECL_SIGNED_INT_LIMITS(signed char, unsigned char)
+DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int)
+DECL_SIGNED_INT_LIMITS(signed int, unsigned int)
+DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int)
+DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int)
+DECL_UNSIGNED_INT_LIMITS(unsigned char)
+DECL_UNSIGNED_INT_LIMITS(unsigned short int)
+DECL_UNSIGNED_INT_LIMITS(unsigned int)
+DECL_UNSIGNED_INT_LIMITS(unsigned long int)
+DECL_UNSIGNED_INT_LIMITS(unsigned long long int)
+
+#undef DECL_SIGNED_INT_LIMITS
+#undef DECL_UNSIGNED_INT_LIMITS
+#undef SIGNED_INT_MAX
+#undef SIGNED_INT_MIN
+#undef UNSIGNED_INT_MAX
+#undef SIGNED_MAX_10_EXP
+#undef UNSIGNED_MAX_10_EXP
+#undef DECL_INT_LIMIT_FUNCS
+
+// ========================================================================= //
+#ifdef WIN32  // Lacks built-in isnan() and isinf()
+#define DECL_FP_LIMIT_FUNCS \
+  static bool IsFinite(const Type x) { return _finite(x); } \
+  static bool IsNaN(const Type x) { return _isnan(x); } \
+  static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \
+  static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \
+  static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; }
+#else
+#define DECL_FP_LIMIT_FUNCS \
+  static bool IsFinite(const Type x) { return !isinf(x)  &&  !isnan(x); } \
+  static bool IsNaN(const Type x) { return isnan(x); } \
+  static bool IsInf(const Type x) { return isinf(x); } \
+  static bool IsPosInf(const Type x) { return isinf(x)  &&  x > 0; } \
+  static bool IsNegInf(const Type x) { return isinf(x)  &&  x < 0; }
+#endif
+
+// We can't put floating-point constant values in the header here because
+// such constants are not considered to be primitive-type constants by gcc.
+// CAVEAT: Hence, they are going to be initialized only during
+// the global objects construction time.
+#define DECL_FP_LIMITS(FP_Type, PREFIX) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \
+  typedef FP_Type Type; \
+  typedef FP_Type UnsignedType; \
+  static const bool kIsSigned = true; \
+  static const bool kIsInteger = false; \
+  static const Type kPosMin; \
+  static const Type kPosMax; \
+  static const Type kMin; \
+  static const Type kMax; \
+  static const Type kNegMin; \
+  static const Type kNegMax; \
+  static const int kMin10Exp = PREFIX##_MIN_10_EXP; \
+  static const int kMax10Exp = PREFIX##_MAX_10_EXP; \
+  static const Type kEpsilon; \
+  static const Type kStdError; \
+  static const int kPrecisionDigits = PREFIX##_DIG; \
+  static const Type kNaN; \
+  static const Type kPosInf; \
+  static const Type kNegInf; \
+  DECL_FP_LIMIT_FUNCS \
+};
+
+DECL_FP_LIMITS(float, FLT)
+DECL_FP_LIMITS(double, DBL)
+DECL_FP_LIMITS(long double, LDBL)
+
+#undef DECL_FP_LIMITS
+#undef DECL_FP_LIMIT_FUNCS
+
+// ========================================================================= //
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // UTIL_MATH_MATHLIMITS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/mathutil.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathutil.h
new file mode 100644
index 0000000..27956a8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/mathutil.h
@@ -0,0 +1,162 @@
+// 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_STUBS_MATHUTIL_H_
+#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
+
+#include <float.h>
+#include <math.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T>
+bool IsNan(T value) {
+  return false;
+}
+template<>
+inline bool IsNan(float value) {
+#ifdef _MSC_VER
+  return _isnan(value);
+#else
+  return isnan(value);
+#endif
+}
+template<>
+inline bool IsNan(double value) {
+#ifdef _MSC_VER
+  return _isnan(value);
+#else
+  return isnan(value);
+#endif
+}
+
+template<typename T>
+bool AlmostEquals(T a, T b) {
+  return a == b;
+}
+template<>
+inline bool AlmostEquals(float a, float b) {
+  return fabs(a - b) < 32 * FLT_EPSILON;
+}
+
+template<>
+inline bool AlmostEquals(double a, double b) {
+  return fabs(a - b) < 32 * DBL_EPSILON;
+}
+}  // namespace internal
+
+class MathUtil {
+ public:
+  template<typename T>
+  static T Sign(T value) {
+    if (value == T(0) || ::google::protobuf::internal::IsNan<T>(value)) {
+      return value;
+    }
+    return value > T(0) ? 1 : -1;
+  }
+
+  template<typename T>
+  static bool AlmostEquals(T a, T b) {
+    return ::google::protobuf::internal::AlmostEquals(a, b);
+  }
+
+  // Largest of two values.
+  // Works correctly for special floating point values.
+  // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0),
+  // which should be OK because, although they (can) have different
+  // bit representation, they are observably the same when examined
+  // with arithmetic and (in)equality operators.
+  template<typename T>
+  static T Max(const T x, const T y) {
+    return MathLimits<T>::IsNaN(x) || x > y ? x : y;
+  }
+
+  // Absolute value of x
+  // Works correctly for unsigned types and
+  // for special floating point values.
+  // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0),
+  // which should be OK: see the comment for Max above.
+  template<typename T>
+  static T Abs(const T x) {
+    return x > T(0) ? x : -x;
+  }
+
+  // Absolute value of the difference between two numbers.
+  // Works correctly for signed types and special floating point values.
+  template<typename T>
+  static typename MathLimits<T>::UnsignedType AbsDiff(const T x, const T y) {
+    // Carries out arithmetic as unsigned to avoid overflow.
+    typedef typename MathLimits<T>::UnsignedType R;
+    return x > y ? R(x) - R(y) : R(y) - R(x);
+  }
+
+  // If two (usually floating point) numbers are within a certain
+  // fraction of their magnitude or within a certain absolute margin of error.
+  // This is the same as the following but faster:
+  //   WithinFraction(x, y, fraction)  ||  WithinMargin(x, y, margin)
+  // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but
+  //      WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true.
+  template<typename T>
+  static bool WithinFractionOrMargin(const T x, const T y,
+                                     const T fraction, const T margin);
+};
+
+template<typename T>
+bool MathUtil::WithinFractionOrMargin(const T x, const T y,
+                                      const T fraction, const T margin) {
+  // Not just "0 <= fraction" to fool the compiler for unsigned types.
+  GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) &&
+         fraction < T(1) &&
+         margin >= T(0));
+
+  // Template specialization will convert the if() condition to a constant,
+  // which will cause the compiler to generate code for either the "if" part
+  // or the "then" part.  In this way we avoid a compiler warning
+  // about a potential integer overflow in crosstool v12 (gcc 4.3.1).
+  if (MathLimits<T>::kIsInteger) {
+    return x == y;
+  } else {
+    // IsFinite checks are to make kPosInf and kNegInf not within fraction
+    if (!MathLimits<T>::IsFinite(x) && !MathLimits<T>::IsFinite(y)) {
+      return false;
+    }
+    T relative_margin = static_cast<T>(fraction * Max(Abs(x), Abs(y)));
+    return AbsDiff(x, y) <= Max(margin, relative_margin);
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/mutex.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/mutex.h
new file mode 100644
index 0000000..7ef1cb6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/mutex.h
@@ -0,0 +1,148 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// 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_STUBS_MUTEX_H_
+#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
+
+#ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL
+#include <pthread.h>
+#endif
+
+#include <google/protobuf/stubs/macros.h>
+
+// ===================================================================
+// emulates google3/base/mutex.h
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// A Mutex is a non-reentrant (aka non-recursive) mutex.  At most one thread T
+// may hold a mutex at a given time.  If T attempts to Lock() the same Mutex
+// while holding it, T will deadlock.
+class LIBPROTOBUF_EXPORT Mutex {
+ public:
+  // Create a Mutex that is not held by anybody.
+  Mutex();
+
+  // Destructor
+  ~Mutex();
+
+  // Block if necessary until this Mutex is free, then acquire it exclusively.
+  void Lock();
+
+  // Release this Mutex.  Caller must hold it exclusively.
+  void Unlock();
+
+  // Crash if this Mutex is not held exclusively by this thread.
+  // May fail to crash when it should; will never crash when it should not.
+  void AssertHeld();
+
+ private:
+  struct Internal;
+  Internal* mInternal;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
+};
+
+// Undefine the macros  to workaround the conflicts with Google internal
+// MutexLock implementation.
+// TODO(liujisi): Remove the undef once internal macros are removed.
+#undef MutexLock
+#undef ReaderMutexLock
+#undef WriterMutexLock
+#undef MutexLockMaybe
+
+// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class LIBPROTOBUF_EXPORT MutexLock {
+ public:
+  explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
+  ~MutexLock() { this->mu_->Unlock(); }
+ private:
+  Mutex *const mu_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
+};
+
+// TODO(kenton):  Implement these?  Hard to implement portably.
+typedef MutexLock ReaderMutexLock;
+typedef MutexLock WriterMutexLock;
+
+// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
+class LIBPROTOBUF_EXPORT MutexLockMaybe {
+ public:
+  explicit MutexLockMaybe(Mutex *mu) :
+    mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
+  ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
+ private:
+  Mutex *const mu_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
+};
+
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+template<typename T>
+class ThreadLocalStorage {
+ public:
+  ThreadLocalStorage() {
+    pthread_key_create(&key_, &ThreadLocalStorage::Delete);
+  }
+  ~ThreadLocalStorage() {
+    pthread_key_delete(key_);
+  }
+  T* Get() {
+    T* result = static_cast<T*>(pthread_getspecific(key_));
+    if (result == NULL) {
+      result = new T();
+      pthread_setspecific(key_, result);
+    }
+    return result;
+  }
+ private:
+  static void Delete(void* value) {
+    delete static_cast<T*>(value);
+  }
+  pthread_key_t key_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
+};
+#endif
+
+}  // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::Mutex;
+using internal::MutexLock;
+using internal::ReaderMutexLock;
+using internal::WriterMutexLock;
+using internal::MutexLockMaybe;
+
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/once.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/once.cc
new file mode 100644
index 0000000..9667b44
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/once.cc
@@ -0,0 +1,106 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// emulates google3/base/once.h
+//
+// This header is intended to be included only by internal .cc files and
+// generated .pb.cc files.  Users should not use this directly.
+
+#include <google/protobuf/stubs/once.h>
+
+#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sched.h>
+#endif
+
+#include <google/protobuf/stubs/atomicops.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+void SchedYield() {
+#ifdef _WIN32
+  Sleep(0);
+#else  // POSIX
+  sched_yield();
+#endif
+}
+
+}  // namespace
+
+void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
+  if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
+    internal::FunctionClosure0 func(init_func, false);
+    GoogleOnceInitImpl(once, &func);
+  }
+}
+
+void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) {
+  internal::AtomicWord state = internal::Acquire_Load(once);
+  // Fast path. The provided closure was already executed.
+  if (state == ONCE_STATE_DONE) {
+    return;
+  }
+  // The closure execution did not complete yet. The once object can be in one
+  // of the two following states:
+  //   - UNINITIALIZED: We are the first thread calling this function.
+  //   - EXECUTING_CLOSURE: Another thread is already executing the closure.
+  //
+  // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE
+  // atomically.
+  state = internal::Acquire_CompareAndSwap(
+      once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE);
+  if (state == ONCE_STATE_UNINITIALIZED) {
+    // We are the first thread to call this function, so we have to call the
+    // closure.
+    closure->Run();
+    internal::Release_Store(once, ONCE_STATE_DONE);
+  } else {
+    // Another thread has already started executing the closure. We need to
+    // wait until it completes the initialization.
+    while (state == ONCE_STATE_EXECUTING_CLOSURE) {
+      // Note that futex() could be used here on Linux as an improvement.
+      SchedYield();
+      state = internal::Acquire_Load(once);
+    }
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/once.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/once.h
new file mode 100644
index 0000000..9522b22
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/once.h
@@ -0,0 +1,163 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// emulates google3/base/once.h
+//
+// This header is intended to be included only by internal .cc files and
+// generated .pb.cc files.  Users should not use this directly.
+//
+// This is basically a portable version of pthread_once().
+//
+// This header declares:
+// * A type called ProtobufOnceType.
+// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
+//   ProtobufOnceType.  This is the only legal way to declare such a variable.
+//   The macro may only be used at the global scope (you cannot create local or
+//   class member variables of this type).
+// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()).
+//   This function, when invoked multiple times given the same ProtobufOnceType
+//   object, will invoke init_func on the first call only, and will make sure
+//   none of the calls return before that first call to init_func has finished.
+// * The user can provide a parameter which GoogleOnceInit() forwards to the
+//   user-provided function when it is called. Usage example:
+//     int a = 10;
+//     GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a);
+// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no
+//   static initializer generated).
+//
+// This implements a way to perform lazy initialization.  It's more efficient
+// than using mutexes as no lock is needed if initialization has already
+// happened.
+//
+// Example usage:
+//   void Init();
+//   GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
+//
+//   // Calls Init() exactly once.
+//   void InitOnce() {
+//     GoogleOnceInit(&once_init, &Init);
+//   }
+//
+// Note that if GoogleOnceInit() is called before main() has begun, it must
+// only be called by the thread that will eventually call main() -- that is,
+// the thread that performs dynamic initialization.  In general this is a safe
+// assumption since people don't usually construct threads before main() starts,
+// but it is technically not guaranteed.  Unfortunately, Win32 provides no way
+// whatsoever to statically-initialize its synchronization primitives, so our
+// only choice is to assume that dynamic initialization is single-threaded.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
+#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+typedef bool ProtobufOnceType;
+
+#define GOOGLE_PROTOBUF_ONCE_INIT false
+
+inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
+  if (!*once) {
+    *once = true;
+    init_func();
+  }
+}
+
+template <typename Arg>
+inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg),
+    Arg arg) {
+  if (!*once) {
+    *once = true;
+    init_func(arg);
+  }
+}
+
+#else
+
+enum {
+  ONCE_STATE_UNINITIALIZED = 0,
+  ONCE_STATE_EXECUTING_CLOSURE = 1,
+  ONCE_STATE_DONE = 2
+};
+
+typedef internal::AtomicWord ProtobufOnceType;
+
+#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED
+
+LIBPROTOBUF_EXPORT
+void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure);
+
+LIBPROTOBUF_EXPORT
+void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)());
+
+template <typename Arg>
+inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
+    Arg* arg) {
+  if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
+    internal::FunctionClosure1<Arg*> func(init_func, false, arg);
+    GoogleOnceInitImpl(once, &func);
+  }
+}
+
+#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+
+class GoogleOnceDynamic {
+ public:
+  GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { }
+
+  // If this->Init() has not been called before by any thread,
+  // execute (*func_with_arg)(arg) then return.
+  // Otherwise, wait until that prior invocation has finished
+  // executing its function, then return.
+  template<typename T>
+  void Init(void (*func_with_arg)(T*), T* arg) {
+    GoogleOnceInit<T>(&this->state_,
+                      func_with_arg,
+                      arg);
+  }
+ private:
+  ProtobufOnceType state_;
+};
+
+#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
+  ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_ONCE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/once_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/once_unittest.cc
new file mode 100644
index 0000000..37def58
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/once_unittest.cc
@@ -0,0 +1,255 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+using internal::NewCallback;
+namespace {
+
+class OnceInitTest : public testing::Test {
+ protected:
+  void SetUp() {
+    state_ = INIT_NOT_STARTED;
+    current_test_ = this;
+  }
+
+  // Since ProtobufOnceType is only allowed to be allocated in static storage,
+  // each test must use a different pair of ProtobufOnceType objects which it
+  // must declare itself.
+  void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) {
+    once_ = once;
+    recursive_once_ = recursive_once;
+  }
+
+  void InitOnce() {
+    GoogleOnceInit(once_, &InitStatic);
+  }
+  void InitRecursiveOnce() {
+    GoogleOnceInit(recursive_once_, &InitRecursiveStatic);
+  }
+
+  void BlockInit() { init_blocker_.Lock(); }
+  void UnblockInit() { init_blocker_.Unlock(); }
+
+  class TestThread {
+   public:
+    TestThread(Closure* callback)
+        : done_(false), joined_(false), callback_(callback) {
+#ifdef _WIN32
+      thread_ = CreateThread(NULL, 0, &Start, this, 0, NULL);
+#else
+      pthread_create(&thread_, NULL, &Start, this);
+#endif
+    }
+    ~TestThread() {
+      if (!joined_) Join();
+    }
+
+    bool IsDone() {
+      MutexLock lock(&done_mutex_);
+      return done_;
+    }
+    void Join() {
+      joined_ = true;
+#ifdef _WIN32
+      WaitForSingleObject(thread_, INFINITE);
+      CloseHandle(thread_);
+#else
+      pthread_join(thread_, NULL);
+#endif
+    }
+
+   private:
+#ifdef _WIN32
+    HANDLE thread_;
+#else
+    pthread_t thread_;
+#endif
+
+    Mutex done_mutex_;
+    bool done_;
+    bool joined_;
+    Closure* callback_;
+
+#ifdef _WIN32
+    static DWORD WINAPI Start(LPVOID arg) {
+#else
+    static void* Start(void* arg) {
+#endif
+      reinterpret_cast<TestThread*>(arg)->Run();
+      return 0;
+    }
+
+    void Run() {
+      callback_->Run();
+      MutexLock lock(&done_mutex_);
+      done_ = true;
+    }
+  };
+
+  TestThread* RunInitOnceInNewThread() {
+    return new TestThread(internal::NewCallback(this, &OnceInitTest::InitOnce));
+  }
+  TestThread* RunInitRecursiveOnceInNewThread() {
+    return new TestThread(
+        internal::NewCallback(this, &OnceInitTest::InitRecursiveOnce));
+  }
+
+  enum State {
+    INIT_NOT_STARTED,
+    INIT_STARTED,
+    INIT_DONE
+  };
+  State CurrentState() {
+    MutexLock lock(&mutex_);
+    return state_;
+  }
+
+  void WaitABit() {
+#ifdef _WIN32
+    Sleep(1000);
+#else
+    sleep(1);
+#endif
+  }
+
+ private:
+  Mutex mutex_;
+  Mutex init_blocker_;
+  State state_;
+  ProtobufOnceType* once_;
+  ProtobufOnceType* recursive_once_;
+
+  void Init() {
+    MutexLock lock(&mutex_);
+    EXPECT_EQ(INIT_NOT_STARTED, state_);
+    state_ = INIT_STARTED;
+    mutex_.Unlock();
+    init_blocker_.Lock();
+    init_blocker_.Unlock();
+    mutex_.Lock();
+    state_ = INIT_DONE;
+  }
+
+  static OnceInitTest* current_test_;
+  static void InitStatic() { current_test_->Init(); }
+  static void InitRecursiveStatic() { current_test_->InitOnce(); }
+};
+
+OnceInitTest* OnceInitTest::current_test_ = NULL;
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(simple_once);
+
+TEST_F(OnceInitTest, Simple) {
+  SetOnces(&simple_once, NULL);
+
+  EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+  InitOnce();
+  EXPECT_EQ(INIT_DONE, CurrentState());
+
+  // Calling again has no effect.
+  InitOnce();
+  EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once1);
+GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once2);
+
+TEST_F(OnceInitTest, Recursive) {
+  SetOnces(&recursive_once1, &recursive_once2);
+
+  EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+  InitRecursiveOnce();
+  EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_once);
+
+TEST_F(OnceInitTest, MultipleThreads) {
+  SetOnces(&multiple_threads_once, NULL);
+
+  scoped_ptr<TestThread> threads[4];
+  EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+  for (int i = 0; i < 4; i++) {
+    threads[i].reset(RunInitOnceInNewThread());
+  }
+  for (int i = 0; i < 4; i++) {
+    threads[i]->Join();
+  }
+  EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once1);
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once2);
+
+TEST_F(OnceInitTest, MultipleThreadsBlocked) {
+  SetOnces(&multiple_threads_blocked_once1, &multiple_threads_blocked_once2);
+
+  scoped_ptr<TestThread> threads[8];
+  EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+
+  BlockInit();
+  for (int i = 0; i < 4; i++) {
+    threads[i].reset(RunInitOnceInNewThread());
+  }
+  for (int i = 4; i < 8; i++) {
+    threads[i].reset(RunInitRecursiveOnceInNewThread());
+  }
+
+  WaitABit();
+
+  // We should now have one thread blocked inside Init(), four blocked waiting
+  // for Init() to complete, and three blocked waiting for InitRecursive() to
+  // complete.
+  EXPECT_EQ(INIT_STARTED, CurrentState());
+  UnblockInit();
+
+  for (int i = 0; i < 8; i++) {
+    threads[i]->Join();
+  }
+  EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/platform_macros.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/platform_macros.h
new file mode 100644
index 0000000..4ba4b34
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/platform_macros.h
@@ -0,0 +1,125 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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_PLATFORM_MACROS_H_
+#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
+
+#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
+#error "Host platform was not detected as supported by protobuf"
+
+// Processor architecture detection.  For more info on what's defined, see:
+//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+//   http://www.agner.org/optimize/calling_conventions.pdf
+//   or with gcc, run: "echo | gcc -E -dM -"
+#if defined(_M_X64) || defined(__x86_64__)
+#define GOOGLE_PROTOBUF_ARCH_X64 1
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#elif defined(_M_IX86) || defined(__i386__)
+#define GOOGLE_PROTOBUF_ARCH_IA32 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(__QNX__)
+#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(__ARMEL__)
+#define GOOGLE_PROTOBUF_ARCH_ARM 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(__aarch64__)
+#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#elif defined(__MIPSEL__)
+#if defined(__LP64__)
+#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#else
+#define GOOGLE_PROTOBUF_ARCH_MIPS 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#endif
+#elif defined(__pnacl__)
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(sparc)
+#define GOOGLE_PROTOBUF_ARCH_SPARC 1
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#else
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#endif
+#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__)
+#define GOOGLE_PROTOBUF_ARCH_POWER 1
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#elif defined(__PPC__)
+#define GOOGLE_PROTOBUF_ARCH_PPC 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#elif defined(__GNUC__)
+# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
+// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
+# elif defined(__clang__)
+#  if !__has_extension(c_atomic)
+GOOGLE_PROTOBUF_PLATFORM_ERROR
+#  endif
+// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
+# endif
+# if __LP64__
+#  define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+# else
+#  define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+# endif
+#else
+GOOGLE_PROTOBUF_PLATFORM_ERROR
+#endif
+
+#if defined(__APPLE__)
+#define GOOGLE_PROTOBUF_OS_APPLE
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GOOGLE_PROTOBUF_OS_IPHONE
+#endif
+#elif defined(__EMSCRIPTEN__)
+#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN
+#elif defined(__native_client__)
+#define GOOGLE_PROTOBUF_OS_NACL
+#elif defined(sun)
+#define GOOGLE_PROTOBUF_OS_SOLARIS
+#elif defined(_AIX)
+#define GOOGLE_PROTOBUF_OS_AIX
+#elif defined(__ANDROID__)
+#define GOOGLE_PROTOBUF_OS_ANDROID
+#endif
+
+#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
+
+#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+// Android ndk does not support the __thread keyword very well yet. Here
+// we use pthread_key_create()/pthread_getspecific()/... methods for
+// TLS support on android.
+// iOS also does not support the __thread keyword.
+#define GOOGLE_PROTOBUF_NO_THREADLOCAL
+#endif
+
+#endif  // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/port.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/port.h
new file mode 100644
index 0000000..80e6074
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/port.h
@@ -0,0 +1,400 @@
+// 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_STUBS_PORT_H_
+#define GOOGLE_PROTOBUF_STUBS_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <cstddef>
+#include <string>
+#include <string.h>
+#if defined(__osf__)
+// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of
+// what stdint.h would define.
+#include <inttypes.h>
+#elif !defined(_MSC_VER)
+#include <stdint.h>
+#endif
+
+#undef PROTOBUF_LITTLE_ENDIAN
+#ifdef _WIN32
+  // Assuming windows is always little-endian.
+  // TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for
+  // optimization but also for correctness. We should define an
+  // different macro to test the big-endian code path in coded_stream.
+  #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+    #define PROTOBUF_LITTLE_ENDIAN 1
+  #endif
+  #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+    // If MSVC has "/RTCc" set, it will complain about truncating casts at
+    // runtime.  This file contains some intentional truncating casts.
+    #pragma runtime_checks("c", off)
+  #endif
+#else
+  #include <sys/param.h>   // __BYTE_ORDER
+  #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
+         (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \
+      !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+    #define PROTOBUF_LITTLE_ENDIAN 1
+  #endif
+#endif
+
+// The macros defined below are required in order to make protobuf_lite a
+// component on all platforms. See http://crbug.com/172800.
+#if defined(COMPONENT_BUILD) && defined(PROTOBUF_USE_DLLS)
+  #if defined(_MSC_VER)
+    #ifdef LIBPROTOBUF_EXPORTS
+      #define LIBPROTOBUF_EXPORT __declspec(dllexport)
+    #else
+      #define LIBPROTOBUF_EXPORT __declspec(dllimport)
+    #endif
+    #ifdef LIBPROTOC_EXPORTS
+      #define LIBPROTOC_EXPORT   __declspec(dllexport)
+    #else
+      #define LIBPROTOC_EXPORT   __declspec(dllimport)
+    #endif
+  #else  // defined(_MSC_VER)
+    #ifdef LIBPROTOBUF_EXPORTS
+      #define LIBPROTOBUF_EXPORT __attribute__((visibility("default")))
+    #else
+      #define LIBPROTOBUF_EXPORT
+    #endif
+    #ifdef LIBPROTOC_EXPORTS
+      #define LIBPROTOC_EXPORT   __attribute__((visibility("default")))
+    #else
+      #define LIBPROTOC_EXPORT
+    #endif
+  #endif
+#else  // defined(COMPONENT_BUILD) && defined(PROTOBUF_USE_DLLS)
+  #define LIBPROTOBUF_EXPORT
+  #define LIBPROTOC_EXPORT
+#endif
+
+// These #includes are for the byte swap functions declared later on.
+#ifdef _MSC_VER
+#include <stdlib.h>  // NOLINT(build/include)
+#elif defined(__APPLE__)
+#include <libkern/OSByteOrder.h>
+#elif defined(__GLIBC__) || defined(__CYGWIN__)
+#include <byteswap.h>  // IWYU pragma: export
+#endif
+
+// ===================================================================
+// from google3/base/port.h
+namespace google {
+namespace protobuf {
+
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+typedef signed __int8  int8;
+typedef __int16 int16;
+typedef __int32 int32;
+typedef __int64 int64;
+
+typedef unsigned __int8  uint8;
+typedef unsigned __int16 uint16;
+typedef unsigned __int32 uint32;
+typedef unsigned __int64 uint64;
+#else
+typedef int8_t  int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+typedef uint8_t  uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+#endif
+
+// long long macros to be used because gcc and vc++ use different suffixes,
+// and different size specifiers in format strings
+#undef GOOGLE_LONGLONG
+#undef GOOGLE_ULONGLONG
+#undef GOOGLE_LL_FORMAT
+
+#ifdef _MSC_VER
+#define GOOGLE_LONGLONG(x) x##I64
+#define GOOGLE_ULONGLONG(x) x##UI64
+#define GOOGLE_LL_FORMAT "I64"  // As in printf("%I64d", ...)
+#else
+#define GOOGLE_LONGLONG(x) INT64_C(x)
+#define GOOGLE_ULONGLONG(x) UINT64_C(x)
+#define GOOGLE_LL_FORMAT "ll"  // As in "%lld". Note that "q" is poor form also.
+#endif
+
+static const int32 kint32max = 0x7FFFFFFF;
+static const int32 kint32min = -kint32max - 1;
+static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF);
+static const int64 kint64min = -kint64max - 1;
+static const uint32 kuint32max = 0xFFFFFFFFu;
+static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
+
+// -------------------------------------------------------------------
+// Annotations:  Some parts of the code have been annotated in ways that might
+//   be useful to some compilers or tools, but are not supported universally.
+//   You can #define these annotations yourself if the default implementation
+//   is not right for you.
+
+#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#endif
+#endif
+
+#ifndef GOOGLE_ATTRIBUTE_NOINLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force not inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+// Seems to have been around since at least Visual Studio 2005
+#define GOOGLE_ATTRIBUTE_NOINLINE __declspec(noinline)
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+#endif
+
+#ifndef GOOGLE_ATTRIBUTE_DEPRECATED
+#ifdef __GNUC__
+// If the method/variable/type is used anywhere, produce a warning.
+#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
+#else
+#define GOOGLE_ATTRIBUTE_DEPRECATED
+#endif
+#endif
+
+#ifndef GOOGLE_PREDICT_TRUE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_TRUE(x) (x)
+#endif
+#endif
+
+#ifndef GOOGLE_PREDICT_FALSE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#else
+#define GOOGLE_PREDICT_FALSE(x) (x)
+#endif
+#endif
+
+// Delimits a block of code which may write to memory which is simultaneously
+// written by other threads, but which has been determined to be thread-safe
+// (e.g. because it is an idempotent write).
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
+#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
+#endif
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
+#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
+#endif
+
+#if defined(__clang__) && defined(__has_cpp_attribute) \
+    && !defined(GOOGLE_PROTOBUF_OS_APPLE)
+# if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) || \
+     __has_cpp_attribute(clang::fallthrough)
+#  define GOOGLE_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+# endif
+#endif
+
+#ifndef GOOGLE_FALLTHROUGH_INTENDED
+# define GOOGLE_FALLTHROUGH_INTENDED
+#endif
+
+#define GOOGLE_GUARDED_BY(x)
+#define GOOGLE_ATTRIBUTE_COLD
+
+// x86 and x86-64 can perform unaligned loads/stores directly.
+#if defined(_M_X64) || defined(__x86_64__) || \
+    defined(_M_IX86) || defined(__i386__)
+
+#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
+
+#else
+inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
+  uint16 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
+  uint32 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
+  uint64 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
+  memcpy(p, &v, sizeof v);
+}
+#endif
+
+#if defined(_MSC_VER)
+#define GOOGLE_THREAD_LOCAL __declspec(thread)
+#else
+#define GOOGLE_THREAD_LOCAL __thread
+#endif
+
+// The following guarantees declaration of the byte swap functions, and
+// defines __BYTE_ORDER for MSVC
+#ifdef _MSC_VER
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define bswap_16(x) _byteswap_ushort(x)
+#define bswap_32(x) _byteswap_ulong(x)
+#define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+// Mac OS X / Darwin features
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif !defined(__GLIBC__) && !defined(__CYGWIN__)
+
+static inline uint16 bswap_16(uint16 x) {
+  return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8));
+}
+#define bswap_16(x) bswap_16(x)
+static inline uint32 bswap_32(uint32 x) {
+  return (((x & 0xFF) << 24) |
+          ((x & 0xFF00) << 8) |
+          ((x & 0xFF0000) >> 8) |
+          ((x & 0xFF000000) >> 24));
+}
+#define bswap_32(x) bswap_32(x)
+static inline uint64 bswap_64(uint64 x) {
+  return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) |
+          ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) |
+          ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) |
+          ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) |
+          ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) |
+          ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) |
+          ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) |
+          ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56));
+}
+#define bswap_64(x) bswap_64(x)
+
+#endif
+
+// ===================================================================
+// from google3/util/endian/endian.h
+LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
+
+class BigEndian {
+ public:
+#ifdef PROTOBUF_LITTLE_ENDIAN
+
+  static uint16 FromHost16(uint16 x) { return bswap_16(x); }
+  static uint16 ToHost16(uint16 x) { return bswap_16(x); }
+
+  static uint32 FromHost32(uint32 x) { return bswap_32(x); }
+  static uint32 ToHost32(uint32 x) { return bswap_32(x); }
+
+  static uint64 FromHost64(uint64 x) { return bswap_64(x); }
+  static uint64 ToHost64(uint64 x) { return bswap_64(x); }
+
+  static bool IsLittleEndian() { return true; }
+
+#else
+
+  static uint16 FromHost16(uint16 x) { return x; }
+  static uint16 ToHost16(uint16 x) { return x; }
+
+  static uint32 FromHost32(uint32 x) { return x; }
+  static uint32 ToHost32(uint32 x) { return x; }
+
+  static uint64 FromHost64(uint64 x) { return x; }
+  static uint64 ToHost64(uint64 x) { return x; }
+
+  static bool IsLittleEndian() { return false; }
+
+#endif /* ENDIAN */
+
+  // Functions to do unaligned loads and stores in big-endian order.
+  static uint16 Load16(const void *p) {
+    return ToHost16(GOOGLE_UNALIGNED_LOAD16(p));
+  }
+
+  static void Store16(void *p, uint16 v) {
+    GOOGLE_UNALIGNED_STORE16(p, FromHost16(v));
+  }
+
+  static uint32 Load32(const void *p) {
+    return ToHost32(GOOGLE_UNALIGNED_LOAD32(p));
+  }
+
+  static void Store32(void *p, uint32 v) {
+    GOOGLE_UNALIGNED_STORE32(p, FromHost32(v));
+  }
+
+  static uint64 Load64(const void *p) {
+    return ToHost64(GOOGLE_UNALIGNED_LOAD64(p));
+  }
+
+  static void Store64(void *p, uint64 v) {
+    GOOGLE_UNALIGNED_STORE64(p, FromHost64(v));
+  }
+};
+
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_PORT_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/scoped_ptr.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/scoped_ptr.h
new file mode 100644
index 0000000..4423c11
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/scoped_ptr.h
@@ -0,0 +1,236 @@
+// 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_STUBS_SCOPED_PTR_H_
+#define GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_
+
+#include <google/protobuf/stubs/port.h>
+
+namespace google {
+namespace protobuf {
+
+// ===================================================================
+// from google3/base/scoped_ptr.h
+
+namespace internal {
+
+//  This is an implementation designed to match the anticipated future TR2
+//  implementation of the scoped_ptr class, and its closely-related brethren,
+//  scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
+
+template <class C> class scoped_ptr;
+template <class C> class scoped_array;
+
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
+//
+// The size of a scoped_ptr is small:
+// sizeof(scoped_ptr<C>) == sizeof(C*)
+template <class C>
+class scoped_ptr {
+ public:
+
+  // The element type
+  typedef C element_type;
+
+  // Constructor.  Defaults to initializing with NULL.
+  // There is no way to create an uninitialized scoped_ptr.
+  // The input parameter must be allocated with new.
+  explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
+
+  // Destructor.  If there is a C object, delete it.
+  // We don't need to test ptr_ == NULL because C++ does that for us.
+  ~scoped_ptr() {
+    enum { type_must_be_complete = sizeof(C) };
+    delete ptr_;
+  }
+
+  // Reset.  Deletes the current owned object, if any.
+  // Then takes ownership of a new object, if given.
+  // this->reset(this->get()) works.
+  void reset(C* p = NULL) {
+    if (p != ptr_) {
+      enum { type_must_be_complete = sizeof(C) };
+      delete ptr_;
+      ptr_ = p;
+    }
+  }
+
+  // Accessors to get the owned object.
+  // operator* and operator-> will assert() if there is no current object.
+  C& operator*() const {
+    assert(ptr_ != NULL);
+    return *ptr_;
+  }
+  C* operator->() const  {
+    assert(ptr_ != NULL);
+    return ptr_;
+  }
+  C* get() const { return ptr_; }
+
+  // Comparison operators.
+  // These return whether two scoped_ptr refer to the same object, not just to
+  // two different but equal objects.
+  bool operator==(C* p) const { return ptr_ == p; }
+  bool operator!=(C* p) const { return ptr_ != p; }
+
+  // Swap two scoped pointers.
+  void swap(scoped_ptr& p2) {
+    C* tmp = ptr_;
+    ptr_ = p2.ptr_;
+    p2.ptr_ = tmp;
+  }
+
+  // Release a pointer.
+  // The return value is the current pointer held by this object.
+  // If this object holds a NULL pointer, the return value is NULL.
+  // After this operation, this object will hold a NULL pointer,
+  // and will not own the object any more.
+  C* release() {
+    C* retVal = ptr_;
+    ptr_ = NULL;
+    return retVal;
+  }
+
+ private:
+  C* ptr_;
+
+  // Forbid comparison of scoped_ptr types.  If C2 != C, it totally doesn't
+  // make sense, and if C2 == C, it still doesn't make sense because you should
+  // never have the same object owned by two different scoped_ptrs.
+  template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
+  template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
+
+  // Disallow evil constructors
+  scoped_ptr(const scoped_ptr&);
+  void operator=(const scoped_ptr&);
+};
+
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL.  A scoped_array<C> owns the object that it points to.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+  // The element type
+  typedef C element_type;
+
+  // Constructor.  Defaults to initializing with NULL.
+  // There is no way to create an uninitialized scoped_array.
+  // The input parameter must be allocated with new [].
+  explicit scoped_array(C* p = NULL) : array_(p) { }
+
+  // Destructor.  If there is a C object, delete it.
+  // We don't need to test ptr_ == NULL because C++ does that for us.
+  ~scoped_array() {
+    enum { type_must_be_complete = sizeof(C) };
+    delete[] array_;
+  }
+
+  // Reset.  Deletes the current owned object, if any.
+  // Then takes ownership of a new object, if given.
+  // this->reset(this->get()) works.
+  void reset(C* p = NULL) {
+    if (p != array_) {
+      enum { type_must_be_complete = sizeof(C) };
+      delete[] array_;
+      array_ = p;
+    }
+  }
+
+  // Get one element of the current object.
+  // Will assert() if there is no current object, or index i is negative.
+  C& operator[](std::ptrdiff_t i) const {
+    assert(i >= 0);
+    assert(array_ != NULL);
+    return array_[i];
+  }
+
+  // Get a pointer to the zeroth element of the current object.
+  // If there is no current object, return NULL.
+  C* get() const {
+    return array_;
+  }
+
+  // Comparison operators.
+  // These return whether two scoped_array refer to the same object, not just to
+  // two different but equal objects.
+  bool operator==(C* p) const { return array_ == p; }
+  bool operator!=(C* p) const { return array_ != p; }
+
+  // Swap two scoped arrays.
+  void swap(scoped_array& p2) {
+    C* tmp = array_;
+    array_ = p2.array_;
+    p2.array_ = tmp;
+  }
+
+  // Release an array.
+  // The return value is the current pointer held by this object.
+  // If this object holds a NULL pointer, the return value is NULL.
+  // After this operation, this object will hold a NULL pointer,
+  // and will not own the object any more.
+  C* release() {
+    C* retVal = array_;
+    array_ = NULL;
+    return retVal;
+  }
+
+ private:
+  C* array_;
+
+  // Forbid comparison of different scoped_array types.
+  template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+  template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+  // Disallow evil constructors
+  scoped_array(const scoped_array&);
+  void operator=(const scoped_array&);
+};
+
+}  // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::scoped_ptr;
+using internal::scoped_array;
+
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/shared_ptr.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/shared_ptr.h
new file mode 100644
index 0000000..85a1172
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/shared_ptr.h
@@ -0,0 +1,470 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+// from google3/util/gtl/shared_ptr.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
+#define GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+
+#include <algorithm>  // for swap
+#include <stddef.h>
+#include <memory>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Alias to std::shared_ptr for any C++11 platform,
+// and for any supported MSVC compiler.
+#if !defined(UTIL_GTL_USE_STD_SHARED_PTR) && \
+    (defined(COMPILER_MSVC) || defined(LANG_CXX11))
+#define UTIL_GTL_USE_STD_SHARED_PTR 1
+#endif
+
+#if defined(UTIL_GTL_USE_STD_SHARED_PTR) && UTIL_GTL_USE_STD_SHARED_PTR
+
+// These are transitional.  They will be going away soon.
+// Please just #include <memory> and just type std::shared_ptr yourself, instead
+// of relying on this file.
+//
+// Migration doc: http://go/std-shared-ptr-lsc
+using std::enable_shared_from_this;
+using std::shared_ptr;
+using std::static_pointer_cast;
+using std::weak_ptr;
+
+#else  // below, UTIL_GTL_USE_STD_SHARED_PTR not set or set to 0.
+
+// For everything else there is the google3 implementation.
+inline bool RefCountDec(volatile Atomic32 *ptr) {
+  return Barrier_AtomicIncrement(ptr, -1) != 0;
+}
+
+inline void RefCountInc(volatile Atomic32 *ptr) {
+  NoBarrier_AtomicIncrement(ptr, 1);
+}
+
+template <typename T> class shared_ptr;
+template <typename T> class weak_ptr;
+
+// This class is an internal implementation detail for shared_ptr. If two
+// shared_ptrs point to the same object, they also share a control block.
+// An "empty" shared_pointer refers to NULL and also has a NULL control block.
+// It contains all of the state that's needed for reference counting or any
+// other kind of resource management. In this implementation the control block
+// happens to consist of two atomic words, the reference count (the number
+// of shared_ptrs that share ownership of the object) and the weak count
+// (the number of weak_ptrs that observe the object, plus 1 if the
+// refcount is nonzero).
+//
+// The "plus 1" is to prevent a race condition in the shared_ptr and
+// weak_ptr destructors. We need to make sure the control block is
+// only deleted once, so we need to make sure that at most one
+// object sees the weak count decremented from 1 to 0.
+class SharedPtrControlBlock {
+  template <typename T> friend class shared_ptr;
+  template <typename T> friend class weak_ptr;
+ private:
+  SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
+  Atomic32 refcount_;
+  Atomic32 weak_count_;
+};
+
+// Forward declaration. The class is defined below.
+template <typename T> class enable_shared_from_this;
+
+template <typename T>
+class shared_ptr {
+  template <typename U> friend class weak_ptr;
+ public:
+  typedef T element_type;
+
+  shared_ptr() : ptr_(NULL), control_block_(NULL) {}
+
+  explicit shared_ptr(T* ptr)
+      : ptr_(ptr),
+        control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
+    // If p is non-null and T inherits from enable_shared_from_this, we
+    // set up the data that shared_from_this needs.
+    MaybeSetupWeakThis(ptr);
+  }
+
+  // Copy constructor: makes this object a copy of ptr, and increments
+  // the reference count.
+  template <typename U>
+  shared_ptr(const shared_ptr<U>& ptr)
+      : ptr_(NULL),
+        control_block_(NULL) {
+    Initialize(ptr);
+  }
+  // Need non-templated version to prevent the compiler-generated default
+  shared_ptr(const shared_ptr<T>& ptr)
+      : ptr_(NULL),
+        control_block_(NULL) {
+    Initialize(ptr);
+  }
+
+  // Assignment operator. Replaces the existing shared_ptr with ptr.
+  // Increment ptr's reference count and decrement the one being replaced.
+  template <typename U>
+  shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
+    if (ptr_ != ptr.ptr_) {
+      shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
+      swap(me);
+    }
+    return *this;
+  }
+
+  // Need non-templated version to prevent the compiler-generated default
+  shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
+    if (ptr_ != ptr.ptr_) {
+      shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
+      swap(me);
+    }
+    return *this;
+  }
+
+  // TODO(austern): Consider providing this constructor. The draft C++ standard
+  // (20.8.10.2.1) includes it. However, it says that this constructor throws
+  // a bad_weak_ptr exception when ptr is expired. Is it better to provide this
+  // constructor and make it do something else, like fail with a CHECK, or to
+  // leave this constructor out entirely?
+  //
+  // template <typename U>
+  // shared_ptr(const weak_ptr<U>& ptr);
+
+  ~shared_ptr() {
+    if (ptr_ != NULL) {
+      if (!RefCountDec(&control_block_->refcount_)) {
+        delete ptr_;
+
+        // weak_count_ is defined as the number of weak_ptrs that observe
+        // ptr_, plus 1 if refcount_ is nonzero.
+        if (!RefCountDec(&control_block_->weak_count_)) {
+          delete control_block_;
+        }
+      }
+    }
+  }
+
+  // Replaces underlying raw pointer with the one passed in.  The reference
+  // count is set to one (or zero if the pointer is NULL) for the pointer
+  // being passed in and decremented for the one being replaced.
+  //
+  // If you have a compilation error with this code, make sure you aren't
+  // passing NULL, nullptr, or 0 to this function.  Call reset without an
+  // argument to reset to a null ptr.
+  template <typename Y>
+  void reset(Y* p) {
+    if (p != ptr_) {
+      shared_ptr<T> tmp(p);
+      tmp.swap(*this);
+    }
+  }
+
+  void reset() {
+    reset(static_cast<T*>(NULL));
+  }
+
+  // Exchanges the contents of this with the contents of r.  This function
+  // supports more efficient swapping since it eliminates the need for a
+  // temporary shared_ptr object.
+  void swap(shared_ptr<T>& r) {
+    using std::swap;  // http://go/using-std-swap
+    swap(ptr_, r.ptr_);
+    swap(control_block_, r.control_block_);
+  }
+
+  // The following function is useful for gaining access to the underlying
+  // pointer when a shared_ptr remains in scope so the reference-count is
+  // known to be > 0 (e.g. for parameter passing).
+  T* get() const {
+    return ptr_;
+  }
+
+  T& operator*() const {
+    return *ptr_;
+  }
+
+  T* operator->() const {
+    return ptr_;
+  }
+
+  long use_count() const {
+    return control_block_ ? control_block_->refcount_ : 1;
+  }
+
+  bool unique() const {
+    return use_count() == 1;
+  }
+
+ private:
+  // If r is non-empty, initialize *this to share ownership with r,
+  // increasing the underlying reference count.
+  // If r is empty, *this remains empty.
+  // Requires: this is empty, namely this->ptr_ == NULL.
+  template <typename U>
+  void Initialize(const shared_ptr<U>& r) {
+    // This performs a static_cast on r.ptr_ to U*, which is a no-op since it
+    // is already a U*. So initialization here requires that r.ptr_ is
+    // implicitly convertible to T*.
+    InitializeWithStaticCast<U>(r);
+  }
+
+  // Initializes *this as described in Initialize, but additionally performs a
+  // static_cast from r.ptr_ (V*) to U*.
+  // NOTE(gfc): We'd need a more general form to support const_pointer_cast and
+  // dynamic_pointer_cast, but those operations are sufficiently discouraged
+  // that supporting static_pointer_cast is sufficient.
+  template <typename U, typename V>
+  void InitializeWithStaticCast(const shared_ptr<V>& r) {
+    if (r.control_block_ != NULL) {
+      RefCountInc(&r.control_block_->refcount_);
+
+      ptr_ = static_cast<U*>(r.ptr_);
+      control_block_ = r.control_block_;
+    }
+  }
+
+  // Helper function for the constructor that takes a raw pointer. If T
+  // doesn't inherit from enable_shared_from_this<T> then we have nothing to
+  // do, so this function is trivial and inline. The other version is declared
+  // out of line, after the class definition of enable_shared_from_this.
+  void MaybeSetupWeakThis(enable_shared_from_this<T>* ptr);
+  void MaybeSetupWeakThis(...) { }
+
+  T* ptr_;
+  SharedPtrControlBlock* control_block_;
+
+#ifndef SWIG
+  template <typename U>
+  friend class shared_ptr;
+
+  template <typename U, typename V>
+  friend shared_ptr<U> static_pointer_cast(const shared_ptr<V>& rhs);
+#endif
+};
+
+// Matches the interface of std::swap as an aid to generic programming.
+template <typename T> void swap(shared_ptr<T>& r, shared_ptr<T>& s) {
+  r.swap(s);
+}
+
+template <typename T, typename U>
+shared_ptr<T> static_pointer_cast(const shared_ptr<U>& rhs) {
+  shared_ptr<T> lhs;
+  lhs.template InitializeWithStaticCast<T>(rhs);
+  return lhs;
+}
+
+// See comments at the top of the file for a description of why this
+// class exists, and the draft C++ standard (as of July 2009 the
+// latest draft is N2914) for the detailed specification.
+template <typename T>
+class weak_ptr {
+  template <typename U> friend class weak_ptr;
+ public:
+  typedef T element_type;
+
+  // Create an empty (i.e. already expired) weak_ptr.
+  weak_ptr() : ptr_(NULL), control_block_(NULL) { }
+
+  // Create a weak_ptr that observes the same object that ptr points
+  // to.  Note that there is no race condition here: we know that the
+  // control block can't disappear while we're looking at it because
+  // it is owned by at least one shared_ptr, ptr.
+  template <typename U> weak_ptr(const shared_ptr<U>& ptr) {
+    CopyFrom(ptr.ptr_, ptr.control_block_);
+  }
+
+  // Copy a weak_ptr. The object it points to might disappear, but we
+  // don't care: we're only working with the control block, and it can't
+  // disappear while we're looking at because it's owned by at least one
+  // weak_ptr, ptr.
+  template <typename U> weak_ptr(const weak_ptr<U>& ptr) {
+    CopyFrom(ptr.ptr_, ptr.control_block_);
+  }
+
+  // Need non-templated version to prevent default copy constructor
+  weak_ptr(const weak_ptr& ptr) {
+    CopyFrom(ptr.ptr_, ptr.control_block_);
+  }
+
+  // Destroy the weak_ptr. If no shared_ptr owns the control block, and if
+  // we are the last weak_ptr to own it, then it can be deleted. Note that
+  // weak_count_ is defined as the number of weak_ptrs sharing this control
+  // block, plus 1 if there are any shared_ptrs. We therefore know that it's
+  // safe to delete the control block when weak_count_ reaches 0, without
+  // having to perform any additional tests.
+  ~weak_ptr() {
+    if (control_block_ != NULL &&
+        !RefCountDec(&control_block_->weak_count_)) {
+      delete control_block_;
+    }
+  }
+
+  weak_ptr& operator=(const weak_ptr& ptr) {
+    if (&ptr != this) {
+      weak_ptr tmp(ptr);
+      tmp.swap(*this);
+    }
+    return *this;
+  }
+  template <typename U> weak_ptr& operator=(const weak_ptr<U>& ptr) {
+    weak_ptr tmp(ptr);
+    tmp.swap(*this);
+    return *this;
+  }
+  template <typename U> weak_ptr& operator=(const shared_ptr<U>& ptr) {
+    weak_ptr tmp(ptr);
+    tmp.swap(*this);
+    return *this;
+  }
+
+  void swap(weak_ptr& ptr) {
+    using std::swap;  // http://go/using-std-swap
+    swap(ptr_, ptr.ptr_);
+    swap(control_block_, ptr.control_block_);
+  }
+
+  void reset() {
+    weak_ptr tmp;
+    tmp.swap(*this);
+  }
+
+  // Return the number of shared_ptrs that own the object we are observing.
+  // Note that this number can be 0 (if this pointer has expired).
+  long use_count() const {
+    return control_block_ != NULL ? control_block_->refcount_ : 0;
+  }
+
+  bool expired() const { return use_count() == 0; }
+
+  // Return a shared_ptr that owns the object we are observing. If we
+  // have expired, the shared_ptr will be empty. We have to be careful
+  // about concurrency, though, since some other thread might be
+  // destroying the last owning shared_ptr while we're in this
+  // function.  We want to increment the refcount only if it's nonzero
+  // and get the new value, and we want that whole operation to be
+  // atomic.
+  shared_ptr<T> lock() const {
+    shared_ptr<T> result;
+    if (control_block_ != NULL) {
+      Atomic32 old_refcount;
+      do {
+        old_refcount = control_block_->refcount_;
+        if (old_refcount == 0)
+          break;
+      } while (old_refcount !=
+               NoBarrier_CompareAndSwap(
+                   &control_block_->refcount_, old_refcount,
+                   old_refcount + 1));
+      if (old_refcount > 0) {
+        result.ptr_ = ptr_;
+        result.control_block_ = control_block_;
+      }
+    }
+
+    return result;
+  }
+
+ private:
+  void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
+    ptr_ = ptr;
+    control_block_ = control_block;
+    if (control_block_ != NULL)
+      RefCountInc(&control_block_->weak_count_);
+  }
+
+ private:
+  element_type* ptr_;
+  SharedPtrControlBlock* control_block_;
+};
+
+template <typename T> void swap(weak_ptr<T>& r, weak_ptr<T>& s) {
+  r.swap(s);
+}
+
+// See comments at the top of the file for a description of why this class
+// exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009
+// the latest draft is N2914) for the detailed specification.
+template <typename T>
+class enable_shared_from_this {
+  friend class shared_ptr<T>;
+ public:
+  // Precondition: there must be a shared_ptr that owns *this and that was
+  // created, directly or indirectly, from a raw pointer of type T*. (The
+  // latter part of the condition is technical but not quite redundant; it
+  // rules out some complicated uses involving inheritance hierarchies.)
+  shared_ptr<T> shared_from_this() {
+    // Behavior is undefined if the precondition isn't satisfied; we choose
+    // to die with a CHECK failure.
+    CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
+    return weak_this_.lock();
+  }
+  shared_ptr<const T> shared_from_this() const {
+    CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
+    return weak_this_.lock();
+  }
+
+ protected:
+  enable_shared_from_this() { }
+  enable_shared_from_this(const enable_shared_from_this& /*other*/) { }
+  enable_shared_from_this& operator=(const enable_shared_from_this& /*other*/) {
+    return *this;
+  }
+  ~enable_shared_from_this() { }
+
+ private:
+  weak_ptr<T> weak_this_;
+};
+
+// This is a helper function called by shared_ptr's constructor from a raw
+// pointer. If T inherits from enable_shared_from_this<T>, it sets up
+// weak_this_ so that shared_from_this works correctly. If T does not inherit
+// from weak_this we get a different overload, defined inline, which does
+// nothing.
+template<typename T>
+void shared_ptr<T>::MaybeSetupWeakThis(enable_shared_from_this<T>* ptr) {
+  if (ptr) {
+    CHECK(ptr->weak_this_.expired()) << "Object already owned by a shared_ptr";
+    ptr->weak_this_ = *this;
+  }
+}
+
+#endif  // UTIL_GTL_USE_STD_SHARED_PTR
+
+}  // internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/singleton.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/singleton.h
new file mode 100644
index 0000000..9301f54
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/singleton.h
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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_STUBS_SINGLETON_H__
+#define GOOGLE_PROTOBUF_STUBS_SINGLETON_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T>
+class Singleton {
+ public:
+  static T* get() {
+    GoogleOnceInit(&once_, &Singleton<T>::Init);
+    return instance_;
+  }
+  static void ShutDown() {
+    delete instance_;
+    instance_ = NULL;
+  }
+ private:
+  static void Init() {
+    instance_ = new T();
+  }
+  static ProtobufOnceType once_;
+  static T* instance_;
+};
+
+template<typename T>
+ProtobufOnceType Singleton<T>::once_;
+
+template<typename T>
+T* Singleton<T>::instance_ = NULL;
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_SINGLETON_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/status.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/status.cc
new file mode 100644
index 0000000..f5e3bdc
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/status.cc
@@ -0,0 +1,137 @@
+// 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.
+#include <google/protobuf/stubs/status.h>
+
+#include <ostream>
+#include <stdio.h>
+#include <string>
+#include <utility>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace error {
+inline string CodeEnumToString(error::Code code) {
+  switch (code) {
+    case OK:
+      return "OK";
+    case CANCELLED:
+      return "CANCELLED";
+    case UNKNOWN:
+      return "UNKNOWN";
+    case INVALID_ARGUMENT:
+      return "INVALID_ARGUMENT";
+    case DEADLINE_EXCEEDED:
+      return "DEADLINE_EXCEEDED";
+    case NOT_FOUND:
+      return "NOT_FOUND";
+    case ALREADY_EXISTS:
+      return "ALREADY_EXISTS";
+    case PERMISSION_DENIED:
+      return "PERMISSION_DENIED";
+    case UNAUTHENTICATED:
+      return "UNAUTHENTICATED";
+    case RESOURCE_EXHAUSTED:
+      return "RESOURCE_EXHAUSTED";
+    case FAILED_PRECONDITION:
+      return "FAILED_PRECONDITION";
+    case ABORTED:
+      return "ABORTED";
+    case OUT_OF_RANGE:
+      return "OUT_OF_RANGE";
+    case UNIMPLEMENTED:
+      return "UNIMPLEMENTED";
+    case INTERNAL:
+      return "INTERNAL";
+    case UNAVAILABLE:
+      return "UNAVAILABLE";
+    case DATA_LOSS:
+      return "DATA_LOSS";
+  }
+
+  // No default clause, clang will abort if a code is missing from
+  // above switch.
+  return "UNKNOWN";
+}
+}  // namespace error.
+
+const StatusPod Status::OK = { error::OK };
+const StatusPod Status::CANCELLED = { error::CANCELLED };
+const StatusPod Status::UNKNOWN = { error::UNKNOWN };
+
+Status::Status() : error_code_(error::OK) {
+}
+
+Status::Status(error::Code error_code, StringPiece error_message)
+    : error_code_(error_code) {
+  if (error_code != error::OK) {
+    error_message_ = error_message.ToString();
+  }
+}
+
+Status::Status(const Status& other)
+    : error_code_(other.error_code_), error_message_(other.error_message_) {
+}
+
+Status::Status(const StatusPod& status_pod) : error_code_(status_pod.code) {
+}
+
+Status& Status::operator=(const Status& other) {
+  error_code_ = other.error_code_;
+  error_message_ = other.error_message_;
+  return *this;
+}
+
+bool Status::operator==(const Status& x) const {
+  return error_code_ == x.error_code_ &&
+      error_message_ == x.error_message_;
+}
+
+string Status::ToString() const {
+  if (error_code_ == error::OK) {
+    return "OK";
+  } else {
+    if (error_message_.empty()) {
+      return error::CodeEnumToString(error_code_);
+    } else {
+      return error::CodeEnumToString(error_code_) + ":" +
+          error_message_;
+    }
+  }
+}
+
+ostream& operator<<(ostream& os, const Status& x) {
+  os << x.ToString();
+  return os;
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/status.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/status.h
new file mode 100644
index 0000000..5c27d6a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/status.h
@@ -0,0 +1,121 @@
+// 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_STUBS_STATUS_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUS_H_
+
+#include <iosfwd>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace error {
+// These values must match error codes defined in google/rpc/code.proto.
+enum Code {
+  OK = 0,
+  CANCELLED = 1,
+  UNKNOWN = 2,
+  INVALID_ARGUMENT = 3,
+  DEADLINE_EXCEEDED = 4,
+  NOT_FOUND = 5,
+  ALREADY_EXISTS = 6,
+  PERMISSION_DENIED = 7,
+  UNAUTHENTICATED = 16,
+  RESOURCE_EXHAUSTED = 8,
+  FAILED_PRECONDITION = 9,
+  ABORTED = 10,
+  OUT_OF_RANGE = 11,
+  UNIMPLEMENTED = 12,
+  INTERNAL = 13,
+  UNAVAILABLE = 14,
+  DATA_LOSS = 15,
+};
+}  // namespace error
+
+struct StatusPod {
+  error::Code code;
+};
+
+class LIBPROTOBUF_EXPORT Status {
+ public:
+  // Creates a "successful" status.
+  Status();
+
+  // Create a status in the canonical error space with the specified
+  // code, and error message.  If "code == 0", error_message is
+  // ignored and a Status object identical to Status::OK is
+  // constructed.
+  Status(error::Code error_code, StringPiece error_message);
+  Status(const Status&);
+  Status(const StatusPod&);
+  Status& operator=(const Status& x);
+  ~Status() {}
+
+  // Some pre-defined Status objects
+  static const StatusPod OK;
+  static const StatusPod CANCELLED;
+  static const StatusPod UNKNOWN;
+
+  // Accessor
+  bool ok() const {
+    return error_code_ == error::OK;
+  }
+  int error_code() const {
+    return error_code_;
+  }
+  StringPiece error_message() const {
+    return error_message_;
+  }
+
+  bool operator==(const Status& x) const;
+  bool operator!=(const Status& x) const {
+    return !operator==(x);
+  }
+
+  // Return a combination of the error code name and message.
+  string ToString() const;
+
+ private:
+  error::Code error_code_;
+  string error_message_;
+};
+
+// Prints a human-readable representation of 'x' to 'os'.
+LIBPROTOBUF_EXPORT ostream& operator<<(ostream& os, const Status& x);
+
+#define EXPECT_OK(value) EXPECT_TRUE((value).ok())
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/status_macros.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/status_macros.h
new file mode 100644
index 0000000..743e79a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/status_macros.h
@@ -0,0 +1,89 @@
+// 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.
+
+// From: util/task/contrib/status_macros/status_macros.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+// Run a command that returns a util::Status.  If the called code returns an
+// error status, return that status up out of this method too.
+//
+// Example:
+//   RETURN_IF_ERROR(DoThings(4));
+#define RETURN_IF_ERROR(expr) \
+  do { \
+    /* Using _status below to avoid capture problems if expr is "status". */ \
+    const ::google::protobuf::util::Status _status = (expr); \
+    if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \
+  } while (0)
+
+// Internal helper for concatenating macro values.
+#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
+#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)
+
+template<typename T>
+Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
+  if (result.ok()) {
+    lhs = result.ValueOrDie();
+  }
+  return result.status();
+}
+
+#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \
+  Status status = DoAssignOrReturn(lhs, (rexpr)); \
+  if (GOOGLE_PREDICT_FALSE(!status.ok())) return status;
+
+// Executes an expression that returns a util::StatusOr, extracting its value
+// into the variable defined by lhs (or returning on error).
+//
+// Example: Assigning to an existing value
+//   ValueType value;
+//   ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
+//
+// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
+//  in a single statement (e.g. as the body of an if statement without {})!
+#define ASSIGN_OR_RETURN(lhs, rexpr) \
+  ASSIGN_OR_RETURN_IMPL( \
+      STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/status_test.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/status_test.cc
new file mode 100644
index 0000000..c70c33c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/status_test.cc
@@ -0,0 +1,131 @@
+// 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.
+#include <google/protobuf/stubs/status.h>
+
+#include <stdio.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+TEST(Status, Empty) {
+  util::Status status;
+  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
+  EXPECT_EQ("OK", util::Status::OK.ToString());
+}
+
+TEST(Status, GenericCodes) {
+  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
+  EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code());
+  EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code());
+}
+
+TEST(Status, ConstructorZero) {
+  util::Status status(util::error::OK, "msg");
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ("OK", status.ToString());
+}
+
+TEST(Status, CheckOK) {
+  util::Status status;
+  GOOGLE_CHECK_OK(status);
+  GOOGLE_CHECK_OK(status) << "Failed";
+  GOOGLE_DCHECK_OK(status) << "Failed";
+}
+
+TEST(Status, ErrorMessage) {
+  util::Status status(util::error::INVALID_ARGUMENT, "");
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ("", status.error_message().ToString());
+  EXPECT_EQ("INVALID_ARGUMENT", status.ToString());
+  status = util::Status(util::error::INVALID_ARGUMENT, "msg");
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ("msg", status.error_message().ToString());
+  EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString());
+  status = util::Status(util::error::OK, "msg");
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ("", status.error_message().ToString());
+  EXPECT_EQ("OK", status.ToString());
+}
+
+TEST(Status, Copy) {
+  util::Status a(util::error::UNKNOWN, "message");
+  util::Status b(a);
+  ASSERT_EQ(a.ToString(), b.ToString());
+}
+
+TEST(Status, Assign) {
+  util::Status a(util::error::UNKNOWN, "message");
+  util::Status b;
+  b = a;
+  ASSERT_EQ(a.ToString(), b.ToString());
+}
+
+TEST(Status, AssignEmpty) {
+  util::Status a(util::error::UNKNOWN, "message");
+  util::Status b;
+  a = b;
+  ASSERT_EQ(string("OK"), a.ToString());
+  ASSERT_TRUE(b.ok());
+  ASSERT_TRUE(a.ok());
+}
+
+TEST(Status, EqualsOK) {
+  ASSERT_EQ(util::Status::OK, util::Status());
+}
+
+TEST(Status, EqualsSame) {
+  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status b = util::Status(util::error::CANCELLED, "message");
+  ASSERT_EQ(a, b);
+}
+
+TEST(Status, EqualsCopy) {
+  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status b = a;
+  ASSERT_EQ(a, b);
+}
+
+TEST(Status, EqualsDifferentCode) {
+  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status b = util::Status(util::error::UNKNOWN, "message");
+  ASSERT_NE(a, b);
+}
+
+TEST(Status, EqualsDifferentMessage) {
+  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status b = util::Status(util::error::CANCELLED, "another");
+  ASSERT_NE(a, b);
+}
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.cc
new file mode 100644
index 0000000..48d1402
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.cc
@@ -0,0 +1,46 @@
+// 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.
+
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace internal {
+
+void StatusOrHelper::Crash(const Status& status) {
+  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
+                    << status.ToString();
+}
+
+}  // namespace internal
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.h
new file mode 100644
index 0000000..29f869a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor.h
@@ -0,0 +1,259 @@
+// 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.
+
+// StatusOr<T> is the union of a Status object and a T
+// object. StatusOr models the concept of an object that is either a
+// usable value, or an error Status explaining why such a value is
+// not present. To this end, StatusOr<T> does not allow its Status
+// value to be Status::OK. Further, StatusOr<T*> does not allow the
+// contained pointer to be NULL.
+//
+// The primary use-case for StatusOr<T> is as the return value of a
+// function which may fail.
+//
+// Example client usage for a StatusOr<T>, where T is not a pointer:
+//
+//  StatusOr<float> result = DoBigCalculationThatCouldFail();
+//  if (result.ok()) {
+//    float answer = result.ValueOrDie();
+//    printf("Big calculation yielded: %f", answer);
+//  } else {
+//    LOG(ERROR) << result.status();
+//  }
+//
+// Example client usage for a StatusOr<T*>:
+//
+//  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
+//  if (result.ok()) {
+//    std::unique_ptr<Foo> foo(result.ValueOrDie());
+//    foo->DoSomethingCool();
+//  } else {
+//    LOG(ERROR) << result.status();
+//  }
+//
+// Example client usage for a StatusOr<std::unique_ptr<T>>:
+//
+//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (result.ok()) {
+//    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
+//    foo->DoSomethingCool();
+//  } else {
+//    LOG(ERROR) << result.status();
+//  }
+//
+// Example factory implementation returning StatusOr<T*>:
+//
+//  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
+//    if (arg <= 0) {
+//      return ::util::Status(::util::error::INVALID_ARGUMENT,
+//                            "Arg must be positive");
+//    } else {
+//      return new Foo(arg);
+//    }
+//  }
+//
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
+
+#include <new>
+#include <string>
+#include <utility>
+
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+template<typename T>
+class StatusOr {
+  template<typename U> friend class StatusOr;
+
+ public:
+  // Construct a new StatusOr with Status::UNKNOWN status
+  StatusOr();
+
+  // Construct a new StatusOr with the given non-ok status. After calling
+  // this constructor, calls to ValueOrDie() will CHECK-fail.
+  //
+  // NOTE: Not explicit - we want to use StatusOr<T> as a return
+  // value, so it is convenient and sensible to be able to do 'return
+  // Status()' when the return type is StatusOr<T>.
+  //
+  // REQUIRES: status != Status::OK. This requirement is DCHECKed.
+  // In optimized builds, passing Status::OK here will have the effect
+  // of passing PosixErrorSpace::EINVAL as a fallback.
+  StatusOr(const Status& status);  // NOLINT
+
+  // Construct a new StatusOr with the given value. If T is a plain pointer,
+  // value must not be NULL. After calling this constructor, calls to
+  // ValueOrDie() will succeed, and calls to status() will return OK.
+  //
+  // NOTE: Not explicit - we want to use StatusOr<T> as a return type
+  // so it is convenient and sensible to be able to do 'return T()'
+  // when when the return type is StatusOr<T>.
+  //
+  // REQUIRES: if T is a plain pointer, value != NULL. This requirement is
+  // DCHECKed. In optimized builds, passing a NULL pointer here will have
+  // the effect of passing PosixErrorSpace::EINVAL as a fallback.
+  StatusOr(const T& value);  // NOLINT
+
+  // Copy constructor.
+  StatusOr(const StatusOr& other);
+
+  // Conversion copy constructor, T must be copy constructible from U
+  template<typename U>
+  StatusOr(const StatusOr<U>& other);
+
+  // Assignment operator.
+  StatusOr& operator=(const StatusOr& other);
+
+  // Conversion assignment operator, T must be assignable from U
+  template<typename U>
+  StatusOr& operator=(const StatusOr<U>& other);
+
+  // Returns a reference to our status. If this contains a T, then
+  // returns Status::OK.
+  const Status& status() const;
+
+  // Returns this->status().ok()
+  bool ok() const;
+
+  // Returns a reference to our current value, or CHECK-fails if !this->ok().
+  // If you need to initialize a T object from the stored value,
+  // ConsumeValueOrDie() may be more efficient.
+  const T& ValueOrDie() const;
+
+ private:
+  Status status_;
+  T value_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation details for StatusOr<T>
+
+namespace internal {
+
+class LIBPROTOBUF_EXPORT StatusOrHelper {
+ public:
+  // Move type-agnostic error handling to the .cc.
+  static void Crash(const util::Status& status);
+
+  // Customized behavior for StatusOr<T> vs. StatusOr<T*>
+  template<typename T>
+  struct Specialize;
+};
+
+template<typename T>
+struct StatusOrHelper::Specialize {
+  // For non-pointer T, a reference can never be NULL.
+  static inline bool IsValueNull(const T& t) { return false; }
+};
+
+template<typename T>
+struct StatusOrHelper::Specialize<T*> {
+  static inline bool IsValueNull(const T* t) { return t == NULL; }
+};
+
+}  // namespace internal
+
+template<typename T>
+inline StatusOr<T>::StatusOr()
+    : status_(util::Status::UNKNOWN) {
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const Status& status) {
+  if (status.ok()) {
+    status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
+  } else {
+    status_ = status;
+  }
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const T& value) {
+  if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+    status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
+  } else {
+    status_ = Status::OK;
+    value_ = value;
+  }
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
+    : status_(other.status_), value_(other.value_) {
+}
+
+template<typename T>
+inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
+  status_ = other.status_;
+  value_ = other.value_;
+  return *this;
+}
+
+template<typename T>
+template<typename U>
+inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
+    : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
+}
+
+template<typename T>
+template<typename U>
+inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
+  status_ = other.status_;
+  if (status_.ok()) value_ = other.value_;
+  return *this;
+}
+
+template<typename T>
+inline const Status& StatusOr<T>::status() const {
+  return status_;
+}
+
+template<typename T>
+inline bool StatusOr<T>::ok() const {
+  return status().ok();
+}
+
+template<typename T>
+inline const T& StatusOr<T>::ValueOrDie() const {
+  if (!status_.ok()) {
+    internal::StatusOrHelper::Crash(status_);
+  }
+  return value_;
+}
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor_test.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor_test.cc
new file mode 100644
index 0000000..6e2a9e5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/statusor_test.cc
@@ -0,0 +1,274 @@
+// 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.
+
+#include <google/protobuf/stubs/statusor.h>
+
+#include <errno.h>
+#include <memory>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+class Base1 {
+ public:
+  virtual ~Base1() {}
+  int pad;
+};
+
+class Base2 {
+ public:
+  virtual ~Base2() {}
+  int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+  virtual ~Derived() {}
+  int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+  explicit CopyNoAssign(int value) : foo(value) {}
+  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+  int foo;
+ private:
+  const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+TEST(StatusOr, TestDefaultCtor) {
+  StatusOr<int> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(Status::UNKNOWN, thing.status());
+}
+
+TEST(StatusOr, TestStatusCtor) {
+  StatusOr<int> thing(Status::CANCELLED);
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(Status::CANCELLED, thing.status());
+}
+
+TEST(StatusOr, TestValueCtor) {
+  const int kI = 4;
+  StatusOr<int> thing(kI);
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+  const int kI = 4;
+  StatusOr<int> original(kI);
+  StatusOr<int> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+  StatusOr<int> original(Status::CANCELLED);
+  StatusOr<int> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+  const int kI = 4;
+  StatusOr<int>    original(kI);
+  StatusOr<double> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+  StatusOr<int>    original(Status::CANCELLED);
+  StatusOr<double> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+  const int kI = 4;
+  StatusOr<int> source(kI);
+  StatusOr<int> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+  StatusOr<int> source(Status::CANCELLED);
+  StatusOr<int> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+  const int kI = 4;
+  StatusOr<int>    source(kI);
+  StatusOr<double> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+  EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+  StatusOr<int>    source(Status::CANCELLED);
+  StatusOr<double> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestStatus) {
+  StatusOr<int> good(4);
+  EXPECT_TRUE(good.ok());
+  StatusOr<int> bad(Status::CANCELLED);
+  EXPECT_FALSE(bad.ok());
+  EXPECT_EQ(Status::CANCELLED, bad.status());
+}
+
+TEST(StatusOr, TestValue) {
+  const int kI = 4;
+  StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestValueConst) {
+  const int kI = 4;
+  const StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+  StatusOr<int*> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(Status::UNKNOWN, thing.status());
+}
+
+TEST(StatusOr, TestPointerStatusCtor) {
+  StatusOr<int*> thing(Status::CANCELLED);
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(Status::CANCELLED, thing.status());
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+  const int kI = 4;
+  StatusOr<const int*> thing(&kI);
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+  const int kI = 0;
+  StatusOr<const int*> original(&kI);
+  StatusOr<const int*> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+  StatusOr<int*> original(Status::CANCELLED);
+  StatusOr<int*> copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+  Derived derived;
+  StatusOr<Derived*> original(&derived);
+  StatusOr<Base2*>   copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+  EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
+            copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+  StatusOr<Derived*> original(Status::CANCELLED);
+  StatusOr<Base2*>   copy(original);
+  EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+  const int kI = 0;
+  StatusOr<const int*> source(&kI);
+  StatusOr<const int*> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+  StatusOr<int*> source(Status::CANCELLED);
+  StatusOr<int*> target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+  Derived derived;
+  StatusOr<Derived*> source(&derived);
+  StatusOr<Base2*>   target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+  EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()),
+            target.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+  StatusOr<Derived*> source(Status::CANCELLED);
+  StatusOr<Base2*>   target;
+  target = source;
+  EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+  const int kI = 0;
+  StatusOr<const int*> good(&kI);
+  EXPECT_TRUE(good.ok());
+  StatusOr<const int*> bad(Status::CANCELLED);
+  EXPECT_EQ(Status::CANCELLED, bad.status());
+}
+
+TEST(StatusOr, TestPointerValue) {
+  const int kI = 0;
+  StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+  const int kI = 0;
+  const StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+}  // namespace
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stl_util.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/stl_util.h
new file mode 100644
index 0000000..9e4c82a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stl_util.h
@@ -0,0 +1,121 @@
+// 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.
+
+// from google3/util/gtl/stl_util.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// STLDeleteContainerPointers()
+//  For a range within a container of pointers, calls delete
+//  (non-array version) on these pointers.
+// NOTE: for these three functions, we could just implement a DeleteObject
+// functor and then call for_each() on the range and functor, but this
+// requires us to pull in all of algorithm.h, which seems expensive.
+// For hash_[multi]set, it is important that this deletes behind the iterator
+// because the hash_set may call the hash function on the iterator when it is
+// advanced, which could result in the hash function trying to deference a
+// stale pointer.
+template <class ForwardIterator>
+void STLDeleteContainerPointers(ForwardIterator begin,
+                                ForwardIterator end) {
+  while (begin != end) {
+    ForwardIterator temp = begin;
+    ++begin;
+    delete *temp;
+  }
+}
+
+// Inside Google, this function implements a horrible, disgusting hack in which
+// we reach into the string's private implementation and resize it without
+// initializing the new bytes.  In some cases doing this can significantly
+// improve performance.  However, since it's totally non-portable it has no
+// place in open source code.  Feel free to fill this function in with your
+// own disgusting hack if you want the perf boost.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+  s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+  // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+  return str->empty() ? NULL : &*str->begin();
+}
+
+// STLDeleteElements() deletes all the elements in an STL container and clears
+// the container.  This function is suitable for use with a vector, set,
+// hash_set, or any other STL container which defines sensible begin(), end(),
+// and clear() methods.
+//
+// If container is NULL, this function is a no-op.
+//
+// As an alternative to calling STLDeleteElements() directly, consider
+// ElementDeleter (defined below), which ensures that your container's elements
+// are deleted when the ElementDeleter goes out of scope.
+template <class T>
+void STLDeleteElements(T *container) {
+  if (!container) return;
+  STLDeleteContainerPointers(container->begin(), container->end());
+  container->clear();
+}
+
+// Given an STL container consisting of (key, value) pairs, STLDeleteValues
+// deletes all the "value" components and clears the container.  Does nothing
+// in the case it's given a NULL pointer.
+
+template <class T>
+void STLDeleteValues(T *v) {
+  if (!v) return;
+  for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
+    delete i->second;
+  }
+  v->clear();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.cc
new file mode 100644
index 0000000..989474b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.cc
@@ -0,0 +1,268 @@
+// 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.
+#include <google/protobuf/stubs/stringpiece.h>
+
+#include <string.h>
+#include <algorithm>
+#include <climits>
+#include <string>
+#include <ostream>
+
+namespace google {
+namespace protobuf {
+std::ostream& operator<<(std::ostream& o, StringPiece piece) {
+  o.write(piece.data(), piece.size());
+  return o;
+}
+
+// Out-of-line error path.
+void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
+  GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
+}
+
+StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
+    : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
+  GOOGLE_DCHECK_LE(0, pos);
+  GOOGLE_DCHECK_LE(pos, x.length_);
+}
+
+StringPiece::StringPiece(StringPiece x,
+                         stringpiece_ssize_type pos,
+                         stringpiece_ssize_type len)
+    : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
+  GOOGLE_DCHECK_LE(0, pos);
+  GOOGLE_DCHECK_LE(pos, x.length_);
+  GOOGLE_DCHECK_GE(len, 0);
+}
+
+void StringPiece::CopyToString(string* target) const {
+  target->assign(ptr_, length_);
+}
+
+void StringPiece::AppendToString(string* target) const {
+  target->append(ptr_, length_);
+}
+
+bool StringPiece::Consume(StringPiece x) {
+  if (starts_with(x)) {
+    ptr_ += x.length_;
+    length_ -= x.length_;
+    return true;
+  }
+  return false;
+}
+
+bool StringPiece::ConsumeFromEnd(StringPiece x) {
+  if (ends_with(x)) {
+    length_ -= x.length_;
+    return true;
+  }
+  return false;
+}
+
+stringpiece_ssize_type StringPiece::copy(char* buf,
+                                         size_type n,
+                                         size_type pos) const {
+  stringpiece_ssize_type ret = std::min(length_ - pos, n);
+  memcpy(buf, ptr_ + pos, ret);
+  return ret;
+}
+
+bool StringPiece::contains(StringPiece s) const {
+  return find(s, 0) != npos;
+}
+
+stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
+  if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
+    if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
+    return npos;
+  }
+  const char *result = std::search(ptr_ + pos, ptr_ + length_,
+                                   s.ptr_, s.ptr_ + s.length_);
+  return result == ptr_ + length_ ? npos : result - ptr_;
+}
+
+stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
+  if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
+    return npos;
+  }
+  const char* result = static_cast<const char*>(
+      memchr(ptr_ + pos, c, length_ - pos));
+  return result != NULL ? result - ptr_ : npos;
+}
+
+stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
+  if (length_ < s.length_) return npos;
+  const size_t ulen = length_;
+  if (s.length_ == 0) return std::min(ulen, pos);
+
+  const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_;
+  const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
+  return result != last ? result - ptr_ : npos;
+}
+
+// Search range is [0..pos] inclusive.  If pos == npos, search everything.
+stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
+  // Note: memrchr() is not available on Windows.
+  if (length_ <= 0) return npos;
+  for (stringpiece_ssize_type i =
+      std::min(pos, static_cast<size_type>(length_ - 1));
+       i >= 0; --i) {
+    if (ptr_[i] == c) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+// For each character in characters_wanted, sets the index corresponding
+// to the ASCII code of that character to 1 in table.  This is used by
+// the find_.*_of methods below to tell whether or not a character is in
+// the lookup table in constant time.
+// The argument `table' must be an array that is large enough to hold all
+// the possible values of an unsigned char.  Thus it should be be declared
+// as follows:
+//   bool table[UCHAR_MAX + 1]
+static inline void BuildLookupTable(StringPiece characters_wanted,
+                                    bool* table) {
+  const stringpiece_ssize_type length = characters_wanted.length();
+  const char* const data = characters_wanted.data();
+  for (stringpiece_ssize_type i = 0; i < length; ++i) {
+    table[static_cast<unsigned char>(data[i])] = true;
+  }
+}
+
+stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
+                                                  size_type pos) const {
+  if (length_ <= 0 || s.length_ <= 0) {
+    return npos;
+  }
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
+                                                      size_type pos) const {
+  if (length_ <= 0) return npos;
+  if (s.length_ <= 0) return 0;
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_first_not_of(char c,
+                                                      size_type pos) const {
+  if (length_ <= 0) return npos;
+
+  for (; pos < static_cast<size_type>(length_); ++pos) {
+    if (ptr_[pos] != c) {
+      return pos;
+    }
+  }
+  return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
+                                                 size_type pos) const {
+  if (length_ <= 0 || s.length_ <= 0) return npos;
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (stringpiece_ssize_type i =
+       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
+                                                     size_type pos) const {
+  if (length_ <= 0) return npos;
+
+  stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
+  if (s.length_ <= 0) return i;
+
+  // Avoid the cost of BuildLookupTable() for a single-character search.
+  if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
+
+  bool lookup[UCHAR_MAX + 1] = { false };
+  BuildLookupTable(s, lookup);
+  for (; i >= 0; --i) {
+    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_not_of(char c,
+                                                     size_type pos) const {
+  if (length_ <= 0) return npos;
+
+  for (stringpiece_ssize_type i =
+       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+    if (ptr_[i] != c) {
+      return i;
+    }
+  }
+  return npos;
+}
+
+StringPiece StringPiece::substr(size_type pos, size_type n) const {
+  if (pos > length_) pos = length_;
+  if (n > length_ - pos) n = length_ - pos;
+  return StringPiece(ptr_ + pos, n);
+}
+
+const StringPiece::size_type StringPiece::npos = size_type(-1);
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.h
new file mode 100644
index 0000000..9167165
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece.h
@@ -0,0 +1,491 @@
+// 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.
+
+// A StringPiece points to part or all of a string, Cord, double-quoted string
+// literal, or other string-like object.  A StringPiece does *not* own the
+// string to which it points.  A StringPiece is not null-terminated.
+//
+// You can use StringPiece as a function or method parameter.  A StringPiece
+// parameter can receive a double-quoted string literal argument, a "const
+// char*" argument, a string argument, or a StringPiece argument with no data
+// copying.  Systematic use of StringPiece for arguments reduces data
+// copies and strlen() calls.
+//
+// Prefer passing StringPieces by value:
+//   void MyFunction(StringPiece arg);
+// If circumstances require, you may also pass by const reference:
+//   void MyFunction(const StringPiece& arg);  // not preferred
+// Both of these have the same lifetime semantics.  Passing by value
+// generates slightly smaller code.  For more discussion, see the thread
+// go/stringpiecebyvalue on c-users.
+//
+// StringPiece is also suitable for local variables if you know that
+// the lifetime of the underlying object is longer than the lifetime
+// of your StringPiece variable.
+//
+// Beware of binding a StringPiece to a temporary:
+//   StringPiece sp = obj.MethodReturningString();  // BAD: lifetime problem
+//
+// This code is okay:
+//   string str = obj.MethodReturningString();  // str owns its contents
+//   StringPiece sp(str);  // GOOD, because str outlives sp
+//
+// StringPiece is sometimes a poor choice for a return value and usually a poor
+// choice for a data member.  If you do use a StringPiece this way, it is your
+// responsibility to ensure that the object pointed to by the StringPiece
+// outlives the StringPiece.
+//
+// A StringPiece may represent just part of a string; thus the name "Piece".
+// For example, when splitting a string, vector<StringPiece> is a natural data
+// type for the output.  For another example, a Cord is a non-contiguous,
+// potentially very long string-like object.  The Cord class has an interface
+// that iteratively provides StringPiece objects that point to the
+// successive pieces of a Cord object.
+//
+// A StringPiece is not null-terminated.  If you write code that scans a
+// StringPiece, you must check its length before reading any characters.
+// Common idioms that work on null-terminated strings do not work on
+// StringPiece objects.
+//
+// There are several ways to create a null StringPiece:
+//   StringPiece()
+//   StringPiece(NULL)
+//   StringPiece(NULL, 0)
+// For all of the above, sp.data() == NULL, sp.length() == 0,
+// and sp.empty() == true.  Also, if you create a StringPiece with
+// a non-NULL pointer then sp.data() != NULL.  Once created,
+// sp.data() will stay either NULL or not-NULL, except if you call
+// sp.clear() or sp.set().
+//
+// Thus, you can use StringPiece(NULL) to signal an out-of-band value
+// that is different from other StringPiece values.  This is similar
+// to the way that const char* p1 = NULL; is different from
+// const char* p2 = "";.
+//
+// There are many ways to create an empty StringPiece:
+//   StringPiece()
+//   StringPiece(NULL)
+//   StringPiece(NULL, 0)
+//   StringPiece("")
+//   StringPiece("", 0)
+//   StringPiece("abcdef", 0)
+//   StringPiece("abcdef"+6, 0)
+// For all of the above, sp.length() will be 0 and sp.empty() will be true.
+// For some empty StringPiece values, sp.data() will be NULL.
+// For some empty StringPiece values, sp.data() will not be NULL.
+//
+// Be careful not to confuse: null StringPiece and empty StringPiece.
+// The set of empty StringPieces properly includes the set of null StringPieces.
+// That is, every null StringPiece is an empty StringPiece,
+// but some non-null StringPieces are empty Stringpieces too.
+//
+// All empty StringPiece values compare equal to each other.
+// Even a null StringPieces compares equal to a non-null empty StringPiece:
+//  StringPiece() == StringPiece("", 0)
+//  StringPiece(NULL) == StringPiece("abc", 0)
+//  StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0)
+//
+// Look carefully at this example:
+//   StringPiece("") == NULL
+// True or false?  TRUE, because StringPiece::operator== converts
+// the right-hand side from NULL to StringPiece(NULL),
+// and then compares two zero-length spans of characters.
+// However, we are working to make this example produce a compile error.
+//
+// Suppose you want to write:
+//   bool TestWhat?(StringPiece sp) { return sp == NULL; }  // BAD
+// Do not do that.  Write one of these instead:
+//   bool TestNull(StringPiece sp) { return sp.data() == NULL; }
+//   bool TestEmpty(StringPiece sp) { return sp.empty(); }
+// The intent of TestWhat? is unclear.  Did you mean TestNull or TestEmpty?
+// Right now, TestWhat? behaves likes TestEmpty.
+// We are working to make TestWhat? produce a compile error.
+// TestNull is good to test for an out-of-band signal.
+// TestEmpty is good to test for an empty StringPiece.
+//
+// Caveats (again):
+// (1) The lifetime of the pointed-to string (or piece of a string)
+//     must be longer than the lifetime of the StringPiece.
+// (2) There may or may not be a '\0' character after the end of
+//     StringPiece data.
+// (3) A null StringPiece is empty.
+//     An empty StringPiece may or may not be a null StringPiece.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
+#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+#include <iosfwd>
+#include <limits>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/hash.h>
+
+namespace google {
+namespace protobuf {
+// StringPiece has *two* size types.
+// StringPiece::size_type
+//   is unsigned
+//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
+//   no future changes intended
+// stringpiece_ssize_type
+//   is signed
+//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
+//   future changes intended: http://go/64BitStringPiece
+//
+typedef string::difference_type stringpiece_ssize_type;
+
+// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
+// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
+#if !defined(NDEBUG)
+#define STRINGPIECE_CHECK_SIZE 1
+#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+#define STRINGPIECE_CHECK_SIZE 1
+#else
+#define STRINGPIECE_CHECK_SIZE 0
+#endif
+
+class LIBPROTOBUF_EXPORT StringPiece {
+ private:
+  const char* ptr_;
+  stringpiece_ssize_type length_;
+
+  // Prevent overflow in debug mode or fortified mode.
+  // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
+  static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
+#if STRINGPIECE_CHECK_SIZE > 0
+#ifdef max
+#undef max
+#endif
+    if (size > static_cast<size_t>(
+        std::numeric_limits<stringpiece_ssize_type>::max())) {
+      // Some people grep for this message in logs
+      // so take care if you ever change it.
+      LogFatalSizeTooBig(size, "size_t to int conversion");
+    }
+#endif
+    return static_cast<stringpiece_ssize_type>(size);
+  }
+
+  // Out-of-line error path.
+  static void LogFatalSizeTooBig(size_t size, const char* details);
+
+ public:
+  // We provide non-explicit singleton constructors so users can pass
+  // in a "const char*" or a "string" wherever a "StringPiece" is
+  // expected.
+  //
+  // Style guide exception granted:
+  // http://goto/style-guide-exception-20978288
+  StringPiece() : ptr_(NULL), length_(0) {}
+
+  StringPiece(const char* str)  // NOLINT(runtime/explicit)
+      : ptr_(str), length_(0) {
+    if (str != NULL) {
+      length_ = CheckedSsizeTFromSizeT(strlen(str));
+    }
+  }
+
+  template <class Allocator>
+  StringPiece(  // NOLINT(runtime/explicit)
+      const std::basic_string<char, std::char_traits<char>, Allocator>& str)
+      : ptr_(str.data()), length_(0) {
+    length_ = CheckedSsizeTFromSizeT(str.size());
+  }
+#if defined(HAS_GLOBAL_STRING)
+  template <class Allocator>
+  StringPiece(  // NOLINT(runtime/explicit)
+      const basic_string<char, std::char_traits<char>, Allocator>& str)
+      : ptr_(str.data()), length_(0) {
+    length_ = CheckedSsizeTFromSizeT(str.size());
+  }
+#endif
+
+  StringPiece(const char* offset, stringpiece_ssize_type len)
+      : ptr_(offset), length_(len) {
+    assert(len >= 0);
+  }
+
+  // Substring of another StringPiece.
+  // pos must be non-negative and <= x.length().
+  StringPiece(StringPiece x, stringpiece_ssize_type pos);
+  // Substring of another StringPiece.
+  // pos must be non-negative and <= x.length().
+  // len must be non-negative and will be pinned to at most x.length() - pos.
+  StringPiece(StringPiece x,
+              stringpiece_ssize_type pos,
+              stringpiece_ssize_type len);
+
+  // data() may return a pointer to a buffer with embedded NULs, and the
+  // returned buffer may or may not be null terminated.  Therefore it is
+  // typically a mistake to pass data() to a routine that expects a NUL
+  // terminated string.
+  const char* data() const { return ptr_; }
+  stringpiece_ssize_type size() const { return length_; }
+  stringpiece_ssize_type length() const { return length_; }
+  bool empty() const { return length_ == 0; }
+
+  void clear() {
+    ptr_ = NULL;
+    length_ = 0;
+  }
+
+  void set(const char* data, stringpiece_ssize_type len) {
+    assert(len >= 0);
+    ptr_ = data;
+    length_ = len;
+  }
+
+  void set(const char* str) {
+    ptr_ = str;
+    if (str != NULL)
+      length_ = CheckedSsizeTFromSizeT(strlen(str));
+    else
+      length_ = 0;
+  }
+
+  void set(const void* data, stringpiece_ssize_type len) {
+    ptr_ = reinterpret_cast<const char*>(data);
+    length_ = len;
+  }
+
+  char operator[](stringpiece_ssize_type i) const {
+    assert(0 <= i);
+    assert(i < length_);
+    return ptr_[i];
+  }
+
+  void remove_prefix(stringpiece_ssize_type n) {
+    assert(length_ >= n);
+    ptr_ += n;
+    length_ -= n;
+  }
+
+  void remove_suffix(stringpiece_ssize_type n) {
+    assert(length_ >= n);
+    length_ -= n;
+  }
+
+  // returns {-1, 0, 1}
+  int compare(StringPiece x) const {
+    const stringpiece_ssize_type min_size =
+        length_ < x.length_ ? length_ : x.length_;
+    int r = memcmp(ptr_, x.ptr_, min_size);
+    if (r < 0) return -1;
+    if (r > 0) return 1;
+    if (length_ < x.length_) return -1;
+    if (length_ > x.length_) return 1;
+    return 0;
+  }
+
+  string as_string() const {
+    return ToString();
+  }
+  // We also define ToString() here, since many other string-like
+  // interfaces name the routine that converts to a C++ string
+  // "ToString", and it's confusing to have the method that does that
+  // for a StringPiece be called "as_string()".  We also leave the
+  // "as_string()" method defined here for existing code.
+  string ToString() const {
+    if (ptr_ == NULL) return string();
+    return string(data(), size());
+  }
+
+  operator string() const {
+    return ToString();
+  }
+
+  void CopyToString(string* target) const;
+  void AppendToString(string* target) const;
+
+  bool starts_with(StringPiece x) const {
+    return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0);
+  }
+
+  bool ends_with(StringPiece x) const {
+    return ((length_ >= x.length_) &&
+            (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
+  }
+
+  // Checks whether StringPiece starts with x and if so advances the beginning
+  // of it to past the match.  It's basically a shortcut for starts_with
+  // followed by remove_prefix.
+  bool Consume(StringPiece x);
+  // Like above but for the end of the string.
+  bool ConsumeFromEnd(StringPiece x);
+
+  // standard STL container boilerplate
+  typedef char value_type;
+  typedef const char* pointer;
+  typedef const char& reference;
+  typedef const char& const_reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  static const size_type npos;
+  typedef const char* const_iterator;
+  typedef const char* iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  iterator begin() const { return ptr_; }
+  iterator end() const { return ptr_ + length_; }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(ptr_ + length_);
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(ptr_);
+  }
+  stringpiece_ssize_type max_size() const { return length_; }
+  stringpiece_ssize_type capacity() const { return length_; }
+
+  // cpplint.py emits a false positive [build/include_what_you_use]
+  stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
+
+  bool contains(StringPiece s) const;
+
+  stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
+  stringpiece_ssize_type find(char c, size_type pos = 0) const;
+  stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
+  stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
+
+  stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
+  stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
+    return find(c, pos);
+  }
+  stringpiece_ssize_type find_first_not_of(StringPiece s,
+                                           size_type pos = 0) const;
+  stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
+  stringpiece_ssize_type find_last_of(StringPiece s,
+                                      size_type pos = npos) const;
+  stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
+    return rfind(c, pos);
+  }
+  stringpiece_ssize_type find_last_not_of(StringPiece s,
+                                          size_type pos = npos) const;
+  stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
+
+  StringPiece substr(size_type pos, size_type n = npos) const;
+};
+
+// This large function is defined inline so that in a fairly common case where
+// one of the arguments is a literal, the compiler can elide a lot of the
+// following comparisons.
+inline bool operator==(StringPiece x, StringPiece y) {
+  stringpiece_ssize_type len = x.size();
+  if (len != y.size()) {
+    return false;
+  }
+
+  return x.data() == y.data() || len <= 0 ||
+      memcmp(x.data(), y.data(), len) == 0;
+}
+
+inline bool operator!=(StringPiece x, StringPiece y) {
+  return !(x == y);
+}
+
+inline bool operator<(StringPiece x, StringPiece y) {
+  const stringpiece_ssize_type min_size =
+      x.size() < y.size() ? x.size() : y.size();
+  const int r = memcmp(x.data(), y.data(), min_size);
+  return (r < 0) || (r == 0 && x.size() < y.size());
+}
+
+inline bool operator>(StringPiece x, StringPiece y) {
+  return y < x;
+}
+
+inline bool operator<=(StringPiece x, StringPiece y) {
+  return !(x > y);
+}
+
+inline bool operator>=(StringPiece x, StringPiece y) {
+  return !(x < y);
+}
+
+// allow StringPiece to be logged
+extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
+
+namespace internal {
+// StringPiece is not a POD and can not be used in an union (pre C++11). We
+// need a POD version of it.
+struct StringPiecePod {
+  // Create from a StringPiece.
+  static StringPiecePod CreateFromStringPiece(StringPiece str) {
+    StringPiecePod pod;
+    pod.data_ = str.data();
+    pod.size_ = str.size();
+    return pod;
+  }
+
+  // Cast to StringPiece.
+  operator StringPiece() const { return StringPiece(data_, size_); }
+
+  bool operator==(const char* value) const {
+    return StringPiece(data_, size_) == StringPiece(value);
+  }
+
+  char operator[](stringpiece_ssize_type i) const {
+    assert(0 <= i);
+    assert(i < size_);
+    return data_[i];
+  }
+
+  const char* data() const { return data_; }
+
+  stringpiece_ssize_type size() const {
+    return size_;
+  }
+
+  std::string ToString() const { return std::string(data_, size_); }
+ private:
+  const char* data_;
+  stringpiece_ssize_type size_;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+template<> struct hash<StringPiece> {
+  size_t operator()(const StringPiece& s) const {
+    size_t result = 0;
+    for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {  
+      result = 5 * result + *str;
+    }
+    return result;
+  }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
+#endif  // STRINGS_STRINGPIECE_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece_unittest.cc
new file mode 100644
index 0000000..a52d81f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringpiece_unittest.cc
@@ -0,0 +1,794 @@
+// 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.
+#include <google/protobuf/stubs/stringpiece.h>
+
+#include <iterator>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/stubs/hash.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+TEST(StringPiece, Ctor) {
+  {
+    // Null.
+    StringPiece s10;
+    EXPECT_TRUE(s10.data() == NULL);
+    EXPECT_EQ(0, s10.length());
+  }
+
+  {
+    // const char* without length.
+    const char* hello = "hello";
+    StringPiece s20(hello);
+    EXPECT_TRUE(s20.data() == hello);
+    EXPECT_EQ(5, s20.length());
+
+    // const char* with length.
+    StringPiece s21(hello, 4);
+    EXPECT_TRUE(s21.data() == hello);
+    EXPECT_EQ(4, s21.length());
+
+    // Not recommended, but valid C++
+    StringPiece s22(hello, 6);
+    EXPECT_TRUE(s22.data() == hello);
+    EXPECT_EQ(6, s22.length());
+  }
+
+  {
+    // std::string.
+    std::string hola = "hola";
+    StringPiece s30(hola);
+    EXPECT_TRUE(s30.data() == hola.data());
+    EXPECT_EQ(4, s30.length());
+
+    // std::string with embedded '\0'.
+    hola.push_back('\0');
+    hola.append("h2");
+    hola.push_back('\0');
+    StringPiece s31(hola);
+    EXPECT_TRUE(s31.data() == hola.data());
+    EXPECT_EQ(8, s31.length());
+  }
+
+#if defined(HAS_GLOBAL_STRING)
+  {
+    // ::string
+    string bonjour = "bonjour";
+    StringPiece s40(bonjour);
+    EXPECT_TRUE(s40.data() == bonjour.data());
+    EXPECT_EQ(7, s40.length());
+  }
+#endif
+
+  // TODO(mec): StringPiece(StringPiece x, int pos);
+  // TODO(mec): StringPiece(StringPiece x, int pos, int len);
+  // TODO(mec): StringPiece(const StringPiece&);
+}
+
+TEST(StringPiece, STLComparator) {
+  string s1("foo");
+  string s2("bar");
+  string s3("baz");
+
+  StringPiece p1(s1);
+  StringPiece p2(s2);
+  StringPiece p3(s3);
+
+  typedef std::map<StringPiece, int> TestMap;
+  TestMap map;
+
+  map.insert(std::make_pair(p1, 0));
+  map.insert(std::make_pair(p2, 1));
+  map.insert(std::make_pair(p3, 2));
+  EXPECT_EQ(map.size(), 3);
+
+  TestMap::const_iterator iter = map.begin();
+  EXPECT_EQ(iter->second, 1);
+  ++iter;
+  EXPECT_EQ(iter->second, 2);
+  ++iter;
+  EXPECT_EQ(iter->second, 0);
+  ++iter;
+  EXPECT_TRUE(iter == map.end());
+
+  TestMap::iterator new_iter = map.find("zot");
+  EXPECT_TRUE(new_iter == map.end());
+
+  new_iter = map.find("bar");
+  EXPECT_TRUE(new_iter != map.end());
+
+  map.erase(new_iter);
+  EXPECT_EQ(map.size(), 2);
+
+  iter = map.begin();
+  EXPECT_EQ(iter->second, 2);
+  ++iter;
+  EXPECT_EQ(iter->second, 0);
+  ++iter;
+  EXPECT_TRUE(iter == map.end());
+}
+
+TEST(StringPiece, ComparisonOperators) {
+#define COMPARE(result, op, x, y) \
+  EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \
+  EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0)
+
+  COMPARE(true, ==, "",   "");
+  COMPARE(true, ==, "", NULL);
+  COMPARE(true, ==, NULL, "");
+  COMPARE(true, ==, "a",  "a");
+  COMPARE(true, ==, "aa", "aa");
+  COMPARE(false, ==, "a",  "");
+  COMPARE(false, ==, "",   "a");
+  COMPARE(false, ==, "a",  "b");
+  COMPARE(false, ==, "a",  "aa");
+  COMPARE(false, ==, "aa", "a");
+
+  COMPARE(false, !=, "",   "");
+  COMPARE(false, !=, "a",  "a");
+  COMPARE(false, !=, "aa", "aa");
+  COMPARE(true, !=, "a",  "");
+  COMPARE(true, !=, "",   "a");
+  COMPARE(true, !=, "a",  "b");
+  COMPARE(true, !=, "a",  "aa");
+  COMPARE(true, !=, "aa", "a");
+
+  COMPARE(true, <, "a",  "b");
+  COMPARE(true, <, "a",  "aa");
+  COMPARE(true, <, "aa", "b");
+  COMPARE(true, <, "aa", "bb");
+  COMPARE(false, <, "a",  "a");
+  COMPARE(false, <, "b",  "a");
+  COMPARE(false, <, "aa", "a");
+  COMPARE(false, <, "b",  "aa");
+  COMPARE(false, <, "bb", "aa");
+
+  COMPARE(true, <=, "a",  "a");
+  COMPARE(true, <=, "a",  "b");
+  COMPARE(true, <=, "a",  "aa");
+  COMPARE(true, <=, "aa", "b");
+  COMPARE(true, <=, "aa", "bb");
+  COMPARE(false, <=, "b",  "a");
+  COMPARE(false, <=, "aa", "a");
+  COMPARE(false, <=, "b",  "aa");
+  COMPARE(false, <=, "bb", "aa");
+
+  COMPARE(false, >=, "a",  "b");
+  COMPARE(false, >=, "a",  "aa");
+  COMPARE(false, >=, "aa", "b");
+  COMPARE(false, >=, "aa", "bb");
+  COMPARE(true, >=, "a",  "a");
+  COMPARE(true, >=, "b",  "a");
+  COMPARE(true, >=, "aa", "a");
+  COMPARE(true, >=, "b",  "aa");
+  COMPARE(true, >=, "bb", "aa");
+
+  COMPARE(false, >, "a",  "a");
+  COMPARE(false, >, "a",  "b");
+  COMPARE(false, >, "a",  "aa");
+  COMPARE(false, >, "aa", "b");
+  COMPARE(false, >, "aa", "bb");
+  COMPARE(true, >, "b",  "a");
+  COMPARE(true, >, "aa", "a");
+  COMPARE(true, >, "b",  "aa");
+  COMPARE(true, >, "bb", "aa");
+
+  string x;
+  for (int i = 0; i < 256; i++) {
+    x += 'a';
+    string y = x;
+    COMPARE(true, ==, x, y);
+    for (int j = 0; j < i; j++) {
+      string z = x;
+      z[j] = 'b';       // Differs in position 'j'
+      COMPARE(false, ==, x, z);
+      COMPARE(true, <, x, z);
+      COMPARE(true, >, z, x);
+      if (j + 1 < i) {
+        z[j + 1] = 'A';  // Differs in position 'j+1' as well
+        COMPARE(false, ==, x, z);
+        COMPARE(true, <, x, z);
+        COMPARE(true, >, z, x);
+        z[j + 1] = 'z';  // Differs in position 'j+1' as well
+        COMPARE(false, ==, x, z);
+        COMPARE(true, <, x, z);
+        COMPARE(true, >, z, x);
+      }
+    }
+  }
+
+#undef COMPARE
+}
+
+TEST(StringPiece, STL1) {
+  const StringPiece a("abcdefghijklmnopqrstuvwxyz");
+  const StringPiece b("abc");
+  const StringPiece c("xyz");
+  const StringPiece d("foobar");
+  const StringPiece e;
+  string temp("123");
+  temp += '\0';
+  temp += "456";
+  const StringPiece f(temp);
+
+  EXPECT_EQ(a[6], 'g');
+  EXPECT_EQ(b[0], 'a');
+  EXPECT_EQ(c[2], 'z');
+  EXPECT_EQ(f[3], '\0');
+  EXPECT_EQ(f[5], '5');
+
+  EXPECT_EQ(*d.data(), 'f');
+  EXPECT_EQ(d.data()[5], 'r');
+  EXPECT_TRUE(e.data() == NULL);
+
+  EXPECT_EQ(*a.begin(), 'a');
+  EXPECT_EQ(*(b.begin() + 2), 'c');
+  EXPECT_EQ(*(c.end() - 1), 'z');
+
+  EXPECT_EQ(*a.rbegin(), 'z');
+  EXPECT_EQ(*(b.rbegin() + 2), 'a');
+  EXPECT_EQ(*(c.rend() - 1), 'x');
+  EXPECT_TRUE(a.rbegin() + 26 == a.rend());
+
+  EXPECT_EQ(a.size(), 26);
+  EXPECT_EQ(b.size(), 3);
+  EXPECT_EQ(c.size(), 3);
+  EXPECT_EQ(d.size(), 6);
+  EXPECT_EQ(e.size(), 0);
+  EXPECT_EQ(f.size(), 7);
+
+  EXPECT_TRUE(!d.empty());
+  EXPECT_TRUE(d.begin() != d.end());
+  EXPECT_TRUE(d.begin() + 6 == d.end());
+
+  EXPECT_TRUE(e.empty());
+  EXPECT_TRUE(e.begin() == e.end());
+
+  EXPECT_GE(a.max_size(), a.capacity());
+  EXPECT_GE(a.capacity(), a.size());
+
+  char buf[4] = { '%', '%', '%', '%' };
+  EXPECT_EQ(a.copy(buf, 4), 4);
+  EXPECT_EQ(buf[0], a[0]);
+  EXPECT_EQ(buf[1], a[1]);
+  EXPECT_EQ(buf[2], a[2]);
+  EXPECT_EQ(buf[3], a[3]);
+  EXPECT_EQ(a.copy(buf, 3, 7), 3);
+  EXPECT_EQ(buf[0], a[7]);
+  EXPECT_EQ(buf[1], a[8]);
+  EXPECT_EQ(buf[2], a[9]);
+  EXPECT_EQ(buf[3], a[3]);
+  EXPECT_EQ(c.copy(buf, 99), 3);
+  EXPECT_EQ(buf[0], c[0]);
+  EXPECT_EQ(buf[1], c[1]);
+  EXPECT_EQ(buf[2], c[2]);
+  EXPECT_EQ(buf[3], a[3]);
+}
+
+// Separated from STL1() because some compilers produce an overly
+// large stack frame for the combined function.
+TEST(StringPiece, STL2) {
+  const StringPiece a("abcdefghijklmnopqrstuvwxyz");
+  const StringPiece b("abc");
+  const StringPiece c("xyz");
+  StringPiece d("foobar");
+  const StringPiece e;
+  const StringPiece f("123" "\0" "456", 7);
+
+  d.clear();
+  EXPECT_EQ(d.size(), 0);
+  EXPECT_TRUE(d.empty());
+  EXPECT_TRUE(d.data() == NULL);
+  EXPECT_TRUE(d.begin() == d.end());
+
+  EXPECT_EQ(StringPiece::npos, string::npos);
+
+  EXPECT_EQ(a.find(b), 0);
+  EXPECT_EQ(a.find(b, 1), StringPiece::npos);
+  EXPECT_EQ(a.find(c), 23);
+  EXPECT_EQ(a.find(c, 9), 23);
+  EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos);
+  EXPECT_EQ(b.find(c), StringPiece::npos);
+  EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos);
+  EXPECT_EQ(a.find(d), 0);
+  EXPECT_EQ(a.find(e), 0);
+  EXPECT_EQ(a.find(d, 12), 12);
+  EXPECT_EQ(a.find(e, 17), 17);
+  StringPiece g("xx not found bb");
+  EXPECT_EQ(a.find(g), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(d.find(b), StringPiece::npos);
+  EXPECT_EQ(e.find(b), StringPiece::npos);
+  EXPECT_EQ(d.find(b, 4), StringPiece::npos);
+  EXPECT_EQ(e.find(b, 7), StringPiece::npos);
+
+  size_t empty_search_pos = string().find(string());
+  EXPECT_EQ(d.find(d), empty_search_pos);
+  EXPECT_EQ(d.find(e), empty_search_pos);
+  EXPECT_EQ(e.find(d), empty_search_pos);
+  EXPECT_EQ(e.find(e), empty_search_pos);
+  EXPECT_EQ(d.find(d, 4), string().find(string(), 4));
+  EXPECT_EQ(d.find(e, 4), string().find(string(), 4));
+  EXPECT_EQ(e.find(d, 4), string().find(string(), 4));
+  EXPECT_EQ(e.find(e, 4), string().find(string(), 4));
+
+  EXPECT_EQ(a.find('a'), 0);
+  EXPECT_EQ(a.find('c'), 2);
+  EXPECT_EQ(a.find('z'), 25);
+  EXPECT_EQ(a.find('$'), StringPiece::npos);
+  EXPECT_EQ(a.find('\0'), StringPiece::npos);
+  EXPECT_EQ(f.find('\0'), 3);
+  EXPECT_EQ(f.find('3'), 2);
+  EXPECT_EQ(f.find('5'), 5);
+  EXPECT_EQ(g.find('o'), 4);
+  EXPECT_EQ(g.find('o', 4), 4);
+  EXPECT_EQ(g.find('o', 5), 8);
+  EXPECT_EQ(a.find('b', 5), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(d.find('\0'), StringPiece::npos);
+  EXPECT_EQ(e.find('\0'), StringPiece::npos);
+  EXPECT_EQ(d.find('\0', 4), StringPiece::npos);
+  EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
+  EXPECT_EQ(d.find('x'), StringPiece::npos);
+  EXPECT_EQ(e.find('x'), StringPiece::npos);
+  EXPECT_EQ(d.find('x', 4), StringPiece::npos);
+  EXPECT_EQ(e.find('x', 7), StringPiece::npos);
+
+  EXPECT_EQ(a.rfind(b), 0);
+  EXPECT_EQ(a.rfind(b, 1), 0);
+  EXPECT_EQ(a.rfind(c), 23);
+  EXPECT_EQ(a.rfind(c, 22), StringPiece::npos);
+  EXPECT_EQ(a.rfind(c, 1), StringPiece::npos);
+  EXPECT_EQ(a.rfind(c, 0), StringPiece::npos);
+  EXPECT_EQ(b.rfind(c), StringPiece::npos);
+  EXPECT_EQ(b.rfind(c, 0), StringPiece::npos);
+  EXPECT_EQ(a.rfind(d), a.as_string().rfind(string()));
+  EXPECT_EQ(a.rfind(e), a.as_string().rfind(string()));
+  EXPECT_EQ(a.rfind(d, 12), 12);
+  EXPECT_EQ(a.rfind(e, 17), 17);
+  EXPECT_EQ(a.rfind(g), StringPiece::npos);
+  EXPECT_EQ(d.rfind(b), StringPiece::npos);
+  EXPECT_EQ(e.rfind(b), StringPiece::npos);
+  EXPECT_EQ(d.rfind(b, 4), StringPiece::npos);
+  EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(d.rfind(d, 4), string().rfind(string()));
+  EXPECT_EQ(e.rfind(d, 7), string().rfind(string()));
+  EXPECT_EQ(d.rfind(e, 4), string().rfind(string()));
+  EXPECT_EQ(e.rfind(e, 7), string().rfind(string()));
+  EXPECT_EQ(d.rfind(d), string().rfind(string()));
+  EXPECT_EQ(e.rfind(d), string().rfind(string()));
+  EXPECT_EQ(d.rfind(e), string().rfind(string()));
+  EXPECT_EQ(e.rfind(e), string().rfind(string()));
+
+  EXPECT_EQ(g.rfind('o'), 8);
+  EXPECT_EQ(g.rfind('q'), StringPiece::npos);
+  EXPECT_EQ(g.rfind('o', 8), 8);
+  EXPECT_EQ(g.rfind('o', 7), 4);
+  EXPECT_EQ(g.rfind('o', 3), StringPiece::npos);
+  EXPECT_EQ(f.rfind('\0'), 3);
+  EXPECT_EQ(f.rfind('\0', 12), 3);
+  EXPECT_EQ(f.rfind('3'), 2);
+  EXPECT_EQ(f.rfind('5'), 5);
+  // empty string nonsense
+  EXPECT_EQ(d.rfind('o'), StringPiece::npos);
+  EXPECT_EQ(e.rfind('o'), StringPiece::npos);
+  EXPECT_EQ(d.rfind('o', 4), StringPiece::npos);
+  EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
+
+  EXPECT_EQ(a.find_first_of(b), 0);
+  EXPECT_EQ(a.find_first_of(b, 0), 0);
+  EXPECT_EQ(a.find_first_of(b, 1), 1);
+  EXPECT_EQ(a.find_first_of(b, 2), 2);
+  EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos);
+  EXPECT_EQ(a.find_first_of(c), 23);
+  EXPECT_EQ(a.find_first_of(c, 23), 23);
+  EXPECT_EQ(a.find_first_of(c, 24), 24);
+  EXPECT_EQ(a.find_first_of(c, 25), 25);
+  EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos);
+  EXPECT_EQ(g.find_first_of(b), 13);
+  EXPECT_EQ(g.find_first_of(c), 0);
+  EXPECT_EQ(a.find_first_of(f), StringPiece::npos);
+  EXPECT_EQ(f.find_first_of(a), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(a.find_first_of(d), StringPiece::npos);
+  EXPECT_EQ(a.find_first_of(e), StringPiece::npos);
+  EXPECT_EQ(d.find_first_of(b), StringPiece::npos);
+  EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
+  EXPECT_EQ(d.find_first_of(d), StringPiece::npos);
+  EXPECT_EQ(e.find_first_of(d), StringPiece::npos);
+  EXPECT_EQ(d.find_first_of(e), StringPiece::npos);
+  EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
+
+  EXPECT_EQ(a.find_first_not_of(b), 3);
+  EXPECT_EQ(a.find_first_not_of(c), 0);
+  EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos);
+  EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos);
+  EXPECT_EQ(f.find_first_not_of(a), 0);
+  EXPECT_EQ(a.find_first_not_of(f), 0);
+  EXPECT_EQ(a.find_first_not_of(d), 0);
+  EXPECT_EQ(a.find_first_not_of(e), 0);
+  // empty string nonsense
+  EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos);
+  EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
+  EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos);
+  EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos);
+  EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos);
+  EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
+
+  StringPiece h("====");
+  EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos);
+  EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos);
+  EXPECT_EQ(h.find_first_not_of('\0'), 0);
+  EXPECT_EQ(g.find_first_not_of('x'), 2);
+  EXPECT_EQ(f.find_first_not_of('\0'), 0);
+  EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
+  EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
+  // empty string nonsense
+  EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos);
+  EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos);
+  EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos);
+  EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
+
+  //  StringPiece g("xx not found bb");
+  StringPiece i("56");
+  EXPECT_EQ(h.find_last_of(a), StringPiece::npos);
+  EXPECT_EQ(g.find_last_of(a), g.size()-1);
+  EXPECT_EQ(a.find_last_of(b), 2);
+  EXPECT_EQ(a.find_last_of(c), a.size()-1);
+  EXPECT_EQ(f.find_last_of(i), 6);
+  EXPECT_EQ(a.find_last_of('a'), 0);
+  EXPECT_EQ(a.find_last_of('b'), 1);
+  EXPECT_EQ(a.find_last_of('z'), 25);
+  EXPECT_EQ(a.find_last_of('a', 5), 0);
+  EXPECT_EQ(a.find_last_of('b', 5), 1);
+  EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos);
+  EXPECT_EQ(a.find_last_of('z', 25), 25);
+  EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos);
+  EXPECT_EQ(f.find_last_of(i, 5), 5);
+  EXPECT_EQ(f.find_last_of(i, 6), 6);
+  EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(f.find_last_of(d), StringPiece::npos);
+  EXPECT_EQ(f.find_last_of(e), StringPiece::npos);
+  EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos);
+  EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(d), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(e), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(d), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(f), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
+  EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
+
+  EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
+  EXPECT_EQ(a.find_last_not_of(c), 22);
+  EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos);
+  EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos);
+  EXPECT_EQ(f.find_last_not_of(i), 4);
+  EXPECT_EQ(a.find_last_not_of(c, 24), 22);
+  EXPECT_EQ(a.find_last_not_of(b, 3), 3);
+  EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos);
+  // empty string nonsense
+  EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
+  EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
+  EXPECT_EQ(f.find_last_not_of(d, 4), 4);
+  EXPECT_EQ(f.find_last_not_of(e, 4), 4);
+  EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos);
+
+  EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
+  EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos);
+  EXPECT_EQ(b.find_last_not_of('c'), 1);
+  EXPECT_EQ(h.find_last_not_of('x', 2), 2);
+  EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos);
+  EXPECT_EQ(b.find_last_not_of('b', 1), 0);
+  // empty string nonsense
+  EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos);
+  EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos);
+  EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
+
+  EXPECT_EQ(a.substr(0, 3), b);
+  EXPECT_EQ(a.substr(23), c);
+  EXPECT_EQ(a.substr(23, 3), c);
+  EXPECT_EQ(a.substr(23, 99), c);
+  EXPECT_EQ(a.substr(0), a);
+  EXPECT_EQ(a.substr(3, 2), "de");
+  // empty string nonsense
+  EXPECT_EQ(a.substr(99, 2), e);
+  EXPECT_EQ(d.substr(99), e);
+  EXPECT_EQ(d.substr(0, 99), e);
+  EXPECT_EQ(d.substr(99, 99), e);
+  // use of npos
+  EXPECT_EQ(a.substr(0, StringPiece::npos), a);
+  EXPECT_EQ(a.substr(23, StringPiece::npos), c);
+  EXPECT_EQ(a.substr(StringPiece::npos, 0), e);
+  EXPECT_EQ(a.substr(StringPiece::npos, 1), e);
+  EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e);
+
+  // Substring constructors.
+  EXPECT_EQ(StringPiece(a, 0, 3), b);
+  EXPECT_EQ(StringPiece(a, 23), c);
+  EXPECT_EQ(StringPiece(a, 23, 3), c);
+  EXPECT_EQ(StringPiece(a, 23, 99), c);
+  EXPECT_EQ(StringPiece(a, 0), a);
+  EXPECT_EQ(StringPiece(a, 3, 2), "de");
+  // empty string nonsense
+  EXPECT_EQ(StringPiece(d, 0, 99), e);
+  // Verify that they work taking an actual string, not just a StringPiece.
+  string a2 = a.as_string();
+  EXPECT_EQ(StringPiece(a2, 0, 3), b);
+  EXPECT_EQ(StringPiece(a2, 23), c);
+  EXPECT_EQ(StringPiece(a2, 23, 3), c);
+  EXPECT_EQ(StringPiece(a2, 23, 99), c);
+  EXPECT_EQ(StringPiece(a2, 0), a);
+  EXPECT_EQ(StringPiece(a2, 3, 2), "de");
+}
+
+TEST(StringPiece, Custom) {
+  StringPiece a("foobar");
+  string s1("123");
+  s1 += '\0';
+  s1 += "456";
+  StringPiece b(s1);
+  StringPiece e;
+  string s2;
+
+  // CopyToString
+  a.CopyToString(&s2);
+  EXPECT_EQ(s2.size(), 6);
+  EXPECT_EQ(s2, "foobar");
+  b.CopyToString(&s2);
+  EXPECT_EQ(s2.size(), 7);
+  EXPECT_EQ(s1, s2);
+  e.CopyToString(&s2);
+  EXPECT_TRUE(s2.empty());
+
+  // AppendToString
+  s2.erase();
+  a.AppendToString(&s2);
+  EXPECT_EQ(s2.size(), 6);
+  EXPECT_EQ(s2, "foobar");
+  a.AppendToString(&s2);
+  EXPECT_EQ(s2.size(), 12);
+  EXPECT_EQ(s2, "foobarfoobar");
+
+  // starts_with
+  EXPECT_TRUE(a.starts_with(a));
+  EXPECT_TRUE(a.starts_with("foo"));
+  EXPECT_TRUE(a.starts_with(e));
+  EXPECT_TRUE(b.starts_with(s1));
+  EXPECT_TRUE(b.starts_with(b));
+  EXPECT_TRUE(b.starts_with(e));
+  EXPECT_TRUE(e.starts_with(""));
+  EXPECT_TRUE(!a.starts_with(b));
+  EXPECT_TRUE(!b.starts_with(a));
+  EXPECT_TRUE(!e.starts_with(a));
+
+  // ends with
+  EXPECT_TRUE(a.ends_with(a));
+  EXPECT_TRUE(a.ends_with("bar"));
+  EXPECT_TRUE(a.ends_with(e));
+  EXPECT_TRUE(b.ends_with(s1));
+  EXPECT_TRUE(b.ends_with(b));
+  EXPECT_TRUE(b.ends_with(e));
+  EXPECT_TRUE(e.ends_with(""));
+  EXPECT_TRUE(!a.ends_with(b));
+  EXPECT_TRUE(!b.ends_with(a));
+  EXPECT_TRUE(!e.ends_with(a));
+
+  // remove_prefix
+  StringPiece c(a);
+  c.remove_prefix(3);
+  EXPECT_EQ(c, "bar");
+  c = a;
+  c.remove_prefix(0);
+  EXPECT_EQ(c, a);
+  c.remove_prefix(c.size());
+  EXPECT_EQ(c, e);
+
+  // remove_suffix
+  c = a;
+  c.remove_suffix(3);
+  EXPECT_EQ(c, "foo");
+  c = a;
+  c.remove_suffix(0);
+  EXPECT_EQ(c, a);
+  c.remove_suffix(c.size());
+  EXPECT_EQ(c, e);
+
+  // set
+  c.set("foobar", 6);
+  EXPECT_EQ(c, a);
+  c.set("foobar", 0);
+  EXPECT_EQ(c, e);
+  c.set("foobar", 7);
+  EXPECT_NE(c, a);
+
+  c.set("foobar");
+  EXPECT_EQ(c, a);
+
+  c.set(static_cast<const void*>("foobar"), 6);
+  EXPECT_EQ(c, a);
+  c.set(static_cast<const void*>("foobar"), 0);
+  EXPECT_EQ(c, e);
+  c.set(static_cast<const void*>("foobar"), 7);
+  EXPECT_NE(c, a);
+
+  // as_string
+  string s3(a.as_string().c_str(), 7);
+  EXPECT_EQ(c, s3);
+  string s4(e.as_string());
+  EXPECT_TRUE(s4.empty());
+
+  // ToString
+  {
+    string s5(a.ToString().c_str(), 7);
+    EXPECT_EQ(c, s5);
+    string s6(e.ToString());
+    EXPECT_TRUE(s6.empty());
+  }
+
+  // Consume
+  a.set("foobar");
+  EXPECT_TRUE(a.Consume("foo"));
+  EXPECT_EQ(a, "bar");
+  EXPECT_FALSE(a.Consume("foo"));
+  EXPECT_FALSE(a.Consume("barbar"));
+  EXPECT_FALSE(a.Consume("ar"));
+  EXPECT_EQ(a, "bar");
+
+  a.set("foobar");
+  EXPECT_TRUE(a.ConsumeFromEnd("bar"));
+  EXPECT_EQ(a, "foo");
+  EXPECT_FALSE(a.ConsumeFromEnd("bar"));
+  EXPECT_FALSE(a.ConsumeFromEnd("foofoo"));
+  EXPECT_FALSE(a.ConsumeFromEnd("fo"));
+  EXPECT_EQ(a, "foo");
+}
+
+TEST(StringPiece, Contains) {
+  StringPiece a("abcdefg");
+  StringPiece b("abcd");
+  StringPiece c("efg");
+  StringPiece d("gh");
+  EXPECT_TRUE(a.contains(b));
+  EXPECT_TRUE(a.contains(c));
+  EXPECT_TRUE(!a.contains(d));
+}
+
+TEST(StringPiece, NULLInput) {
+  // we used to crash here, but now we don't.
+  StringPiece s(NULL);
+  EXPECT_EQ(s.data(), (const char*)NULL);
+  EXPECT_EQ(s.size(), 0);
+
+  s.set(NULL);
+  EXPECT_EQ(s.data(), (const char*)NULL);
+  EXPECT_EQ(s.size(), 0);
+
+  // .ToString() on a StringPiece with NULL should produce the empty string.
+  EXPECT_EQ("", s.ToString());
+  EXPECT_EQ("", s.as_string());
+}
+
+TEST(StringPiece, Comparisons2) {
+  StringPiece abc("abcdefghijklmnopqrstuvwxyz");
+
+  // check comparison operations on strings longer than 4 bytes.
+  EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz"));
+  EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0);
+
+  EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz"));
+  EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0);
+
+  EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy"));
+  EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0);
+
+  // starts_with
+  EXPECT_TRUE(abc.starts_with(abc));
+  EXPECT_TRUE(abc.starts_with("abcdefghijklm"));
+  EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz"));
+
+  // ends_with
+  EXPECT_TRUE(abc.ends_with(abc));
+  EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz"));
+  EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz"));
+}
+
+TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
+  EXPECT_EQ("hello", string("hello"));
+  EXPECT_LT("hello", string("world"));
+}
+
+TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) {
+  EXPECT_EQ(StringPiece("hello"), string("hello"));
+  EXPECT_EQ("hello", StringPiece("hello"));
+}
+
+TEST(FindOneCharTest, EdgeCases) {
+  StringPiece a("xxyyyxx");
+
+  // Set a = "xyyyx".
+  a.remove_prefix(1);
+  a.remove_suffix(1);
+
+  EXPECT_EQ(0, a.find('x'));
+  EXPECT_EQ(0, a.find('x', 0));
+  EXPECT_EQ(4, a.find('x', 1));
+  EXPECT_EQ(4, a.find('x', 4));
+  EXPECT_EQ(StringPiece::npos, a.find('x', 5));
+
+  EXPECT_EQ(4, a.rfind('x'));
+  EXPECT_EQ(4, a.rfind('x', 5));
+  EXPECT_EQ(4, a.rfind('x', 4));
+  EXPECT_EQ(0, a.rfind('x', 3));
+  EXPECT_EQ(0, a.rfind('x', 0));
+
+  // Set a = "yyy".
+  a.remove_prefix(1);
+  a.remove_suffix(1);
+
+  EXPECT_EQ(StringPiece::npos, a.find('x'));
+  EXPECT_EQ(StringPiece::npos, a.rfind('x'));
+}
+
+#ifndef NDEBUG
+TEST(NonNegativeLenTest, NonNegativeLen) {
+  EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0");
+}
+#endif  // ndef DEBUG
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.cc
new file mode 100644
index 0000000..83fdfe4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.cc
@@ -0,0 +1,174 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// from google3/base/stringprintf.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <errno.h>
+#include <stdarg.h> // For va_list and related operations
+#include <stdio.h> // MSVC requires this for _vsnprintf
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+enum { IS_COMPILER_MSVC = 1 };
+#ifndef va_copy
+// Define va_copy for MSVC. This is a hack, assuming va_list is simply a
+// pointer into the stack and is safe to copy.
+#define va_copy(dest, src) ((dest) = (src))
+#endif
+#else
+enum { IS_COMPILER_MSVC = 0 };
+#endif
+
+void StringAppendV(string* dst, const char* format, va_list ap) {
+  // First try with a small fixed size buffer
+  static const int kSpaceLength = 1024;
+  char space[kSpaceLength];
+
+  // It's possible for methods that use a va_list to invalidate
+  // the data in it upon use.  The fix is to make a copy
+  // of the structure before using it and use that copy instead.
+  va_list backup_ap;
+  va_copy(backup_ap, ap);
+  int result = vsnprintf(space, kSpaceLength, format, backup_ap);
+  va_end(backup_ap);
+
+  if (result < kSpaceLength) {
+    if (result >= 0) {
+      // Normal case -- everything fit.
+      dst->append(space, result);
+      return;
+    }
+
+    if (IS_COMPILER_MSVC) {
+      // Error or MSVC running out of space.  MSVC 8.0 and higher
+      // can be asked about space needed with the special idiom below:
+      va_copy(backup_ap, ap);
+      result = vsnprintf(NULL, 0, format, backup_ap);
+      va_end(backup_ap);
+    }
+
+    if (result < 0) {
+      // Just an error.
+      return;
+    }
+  }
+
+  // Increase the buffer size to the size requested by vsnprintf,
+  // plus one for the closing \0.
+  int length = result+1;
+  char* buf = new char[length];
+
+  // Restore the va_list before we use it again
+  va_copy(backup_ap, ap);
+  result = vsnprintf(buf, length, format, backup_ap);
+  va_end(backup_ap);
+
+  if (result >= 0 && result < length) {
+    // It fit
+    dst->append(buf, result);
+  }
+  delete[] buf;
+}
+
+
+string StringPrintf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  string result;
+  StringAppendV(&result, format, ap);
+  va_end(ap);
+  return result;
+}
+
+const string& SStringPrintf(string* dst, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  dst->clear();
+  StringAppendV(dst, format, ap);
+  va_end(ap);
+  return *dst;
+}
+
+void StringAppendF(string* dst, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  StringAppendV(dst, format, ap);
+  va_end(ap);
+}
+
+// Max arguments supported by StringPrintVector
+const int kStringPrintfVectorMaxArgs = 32;
+
+// An empty block of zero for filler arguments.  This is const so that if
+// printf tries to write to it (via %n) then the program gets a SIGSEGV
+// and we can fix the problem or protect against an attack.
+static const char string_printf_empty_block[256] = { '\0' };
+
+string StringPrintfVector(const char* format, const vector<string>& v) {
+  GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
+      << "StringPrintfVector currently only supports up to "
+      << kStringPrintfVectorMaxArgs << " arguments. "
+      << "Feel free to add support for more if you need it.";
+
+  // Add filler arguments so that bogus format+args have a harder time
+  // crashing the program, corrupting the program (%n),
+  // or displaying random chunks of memory to users.
+
+  const char* cstr[kStringPrintfVectorMaxArgs];
+  for (int i = 0; i < v.size(); ++i) {
+    cstr[i] = v[i].c_str();
+  }
+  for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
+    cstr[i] = &string_printf_empty_block[0];
+  }
+
+  // I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
+  // or any way to build a va_list by hand, or any API for printf
+  // that accepts an array of arguments.  The best I can do is stick
+  // this COMPILE_ASSERT right next to the actual statement.
+
+  GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+  return StringPrintf(format,
+                      cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
+                      cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
+                      cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
+                      cstr[15], cstr[16], cstr[17], cstr[18], cstr[19],
+                      cstr[20], cstr[21], cstr[22], cstr[23], cstr[24],
+                      cstr[25], cstr[26], cstr[27], cstr[28], cstr[29],
+                      cstr[30], cstr[31]);
+}
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.h
new file mode 100644
index 0000000..ab1ab55
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf.h
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// from google3/base/stringprintf.h
+//
+// Printf variants that place their output in a C++ string.
+//
+// Usage:
+//      string result = StringPrintf("%d %s\n", 10, "hello");
+//      SStringPrintf(&result, "%d %s\n", 10, "hello");
+//      StringAppendF(&result, "%d %s\n", 20, "there");
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+
+#include <stdarg.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// Return a C++ string
+LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...);
+
+// Store result into a supplied string and return it
+LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...);
+
+// Append result to a supplied string
+LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...);
+
+// Lower-level routine that takes a va_list and appends to a specified
+// string.  All other routines are just convenience wrappers around it.
+LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap);
+
+// The max arguments supported by StringPrintfVector
+LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;
+
+// You can use this version when all your arguments are strings, but
+// you don't know how many arguments you'll have at compile time.
+// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
+LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector<string>& v);
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf_unittest.cc
new file mode 100644
index 0000000..15895e5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/stringprintf_unittest.cc
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 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.
+
+// from google3/base/stringprintf_unittest.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <cerrno>
+#include <string>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(StringPrintfTest, Empty) {
+#if 0
+  // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this:
+  // warning: zero-length printf format string.
+  // so we do not allow them in google3.
+  EXPECT_EQ("", StringPrintf(""));
+#endif
+  EXPECT_EQ("", StringPrintf("%s", string().c_str()));
+  EXPECT_EQ("", StringPrintf("%s", ""));
+}
+
+TEST(StringPrintfTest, Misc) {
+// MSVC and mingw does not support $ format specifier.
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+  EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123));
+#endif  // !_MSC_VER
+}
+
+TEST(StringAppendFTest, Empty) {
+  string value("Hello");
+  const char* empty = "";
+  StringAppendF(&value, "%s", empty);
+  EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, EmptyString) {
+  string value("Hello");
+  StringAppendF(&value, "%s", "");
+  EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, String) {
+  string value("Hello");
+  StringAppendF(&value, " %s", "World");
+  EXPECT_EQ("Hello World", value);
+}
+
+TEST(StringAppendFTest, Int) {
+  string value("Hello");
+  StringAppendF(&value, " %d", 123);
+  EXPECT_EQ("Hello 123", value);
+}
+
+TEST(StringPrintfTest, Multibyte) {
+  // If we are in multibyte mode and feed invalid multibyte sequence,
+  // StringPrintf should return an empty string instead of running
+  // out of memory while trying to determine destination buffer size.
+  // see b/4194543.
+
+  char* old_locale = setlocale(LC_CTYPE, NULL);
+  // Push locale with multibyte mode
+  setlocale(LC_CTYPE, "en_US.utf8");
+
+  const char kInvalidCodePoint[] = "\375\067s";
+  string value = StringPrintf("%.*s", 3, kInvalidCodePoint);
+
+  // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf
+  // returns error given an invalid codepoint. Other versions
+  // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim.
+  // We test that the output is one of the above.
+  EXPECT_TRUE(value.empty() || value == kInvalidCodePoint);
+
+  // Repeat with longer string, to make sure that the dynamically
+  // allocated path in StringAppendV is handled correctly.
+  int n = 2048;
+  char* buf = new char[n+1];
+  memset(buf, ' ', n-3);
+  memcpy(buf + n - 3, kInvalidCodePoint, 4);
+  value =  StringPrintf("%.*s", n, buf);
+  // See GRTEv2 vs. GRTEv3 comment above.
+  EXPECT_TRUE(value.empty() || value == buf);
+  delete[] buf;
+
+  setlocale(LC_CTYPE, old_locale);
+}
+
+TEST(StringPrintfTest, NoMultibyte) {
+  // No multibyte handling, but the string contains funny chars.
+  char* old_locale = setlocale(LC_CTYPE, NULL);
+  setlocale(LC_CTYPE, "POSIX");
+  string value = StringPrintf("%.*s", 3, "\375\067s");
+  setlocale(LC_CTYPE, old_locale);
+  EXPECT_EQ("\375\067s", value);
+}
+
+TEST(StringPrintfTest, DontOverwriteErrno) {
+  // Check that errno isn't overwritten unless we're printing
+  // something significantly larger than what people are normally
+  // printing in their badly written PLOG() statements.
+  errno = ECHILD;
+  string value = StringPrintf("Hello, %s!", "World");
+  EXPECT_EQ(ECHILD, errno);
+}
+
+TEST(StringPrintfTest, LargeBuf) {
+  // Check that the large buffer is handled correctly.
+  int n = 2048;
+  char* buf = new char[n+1];
+  memset(buf, ' ', n);
+  buf[n] = 0;
+  string value = StringPrintf("%s", buf);
+  EXPECT_EQ(buf, value);
+  delete[] buf;
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid.cc
new file mode 100644
index 0000000..d79a6ee
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid.cc
@@ -0,0 +1,588 @@
+// Copyright 2005-2008 Google Inc. All Rights Reserved.
+// Author: jrm@google.com (Jim Meehan)
+
+#include <google/protobuf/stubs/common.h>
+
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// These four-byte entries compactly encode how many bytes 0..255 to delete
+// in making a string replacement, how many bytes to add 0..255, and the offset
+// 0..64k-1 of the replacement string in remap_string.
+struct RemapEntry {
+  uint8 delete_bytes;
+  uint8 add_bytes;
+  uint16 bytes_offset;
+};
+
+// Exit type codes for state tables. All but the first get stuffed into
+// signed one-byte entries. The first is only generated by executable code.
+// To distinguish from next-state entries, these must be contiguous and
+// all <= kExitNone
+typedef enum {
+  kExitDstSpaceFull = 239,
+  kExitIllegalStructure,  // 240
+  kExitOK,                // 241
+  kExitReject,            // ...
+  kExitReplace1,
+  kExitReplace2,
+  kExitReplace3,
+  kExitReplace21,
+  kExitReplace31,
+  kExitReplace32,
+  kExitReplaceOffset1,
+  kExitReplaceOffset2,
+  kExitReplace1S0,
+  kExitSpecial,
+  kExitDoAgain,
+  kExitRejectAlt,
+  kExitNone               // 255
+} ExitReason;
+
+
+// This struct represents one entire state table. The three initialized byte
+// areas are state_table, remap_base, and remap_string. state0 and state0_size
+// give the byte offset and length within state_table of the initial state --
+// table lookups are expected to start and end in this state, but for
+// truncated UTF-8 strings, may end in a different state. These allow a quick
+// test for that condition. entry_shift is 8 for tables subscripted by a full
+// byte value and 6 for space-optimized tables subscripted by only six
+// significant bits in UTF-8 continuation bytes.
+typedef struct {
+  const uint32 state0;
+  const uint32 state0_size;
+  const uint32 total_size;
+  const int max_expand;
+  const int entry_shift;
+  const int bytes_per_entry;
+  const uint32 losub;
+  const uint32 hiadd;
+  const uint8* state_table;
+  const RemapEntry* remap_base;
+  const uint8* remap_string;
+  const uint8* fast_state;
+} UTF8StateMachineObj;
+
+typedef UTF8StateMachineObj UTF8ScanObj;
+
+#define X__ (kExitIllegalStructure)
+#define RJ_ (kExitReject)
+#define S1_ (kExitReplace1)
+#define S2_ (kExitReplace2)
+#define S3_ (kExitReplace3)
+#define S21 (kExitReplace21)
+#define S31 (kExitReplace31)
+#define S32 (kExitReplace32)
+#define T1_ (kExitReplaceOffset1)
+#define T2_ (kExitReplaceOffset2)
+#define S11 (kExitReplace1S0)
+#define SP_ (kExitSpecial)
+#define D__ (kExitDoAgain)
+#define RJA (kExitRejectAlt)
+
+//  Entire table has 9 state blocks of 256 entries each
+static const unsigned int utf8acceptnonsurrogates_STATE0 = 0;     // state[0]
+static const unsigned int utf8acceptnonsurrogates_STATE0_SIZE = 256;  // =[1]
+static const unsigned int utf8acceptnonsurrogates_TOTAL_SIZE = 2304;
+static const unsigned int utf8acceptnonsurrogates_MAX_EXPAND_X4 = 0;
+static const unsigned int utf8acceptnonsurrogates_SHIFT = 8;
+static const unsigned int utf8acceptnonsurrogates_BYTES = 1;
+static const unsigned int utf8acceptnonsurrogates_LOSUB = 0x20202020;
+static const unsigned int utf8acceptnonsurrogates_HIADD = 0x00000000;
+
+static const uint8 utf8acceptnonsurrogates[] = {
+// state[0] 0x000000 Byte 1
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  2,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   7,   3,   3,
+  4,   5,   5,   5,   6, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[1] 0x000080 Byte 2 of 2
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[2] 0x000000 Byte 2 of 3
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[3] 0x001000 Byte 2 of 3
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[4] 0x000000 Byte 2 of 4
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[5] 0x040000 Byte 2 of 4
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[6] 0x100000 Byte 2 of 4
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[7] 0x00d000 Byte 2 of 3
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
+  8,   8,   8,   8,   8,   8,   8,   8,    8,   8,   8,   8,   8,   8,   8,   8,
+  8,   8,   8,   8,   8,   8,   8,   8,    8,   8,   8,   8,   8,   8,   8,   8,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+// state[8] 0x00d800 Byte 3 of 3
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+
+RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
+RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
+RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
+RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
+
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
+};
+
+// Remap base[0] = (del, add, string_offset)
+static const RemapEntry utf8acceptnonsurrogates_remap_base[] = {
+{0, 0, 0} };
+
+// Remap string[0]
+static const unsigned char utf8acceptnonsurrogates_remap_string[] = {
+0 };
+
+static const unsigned char utf8acceptnonsurrogates_fast[256] = {
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+static const UTF8ScanObj utf8acceptnonsurrogates_obj = {
+  utf8acceptnonsurrogates_STATE0,
+  utf8acceptnonsurrogates_STATE0_SIZE,
+  utf8acceptnonsurrogates_TOTAL_SIZE,
+  utf8acceptnonsurrogates_MAX_EXPAND_X4,
+  utf8acceptnonsurrogates_SHIFT,
+  utf8acceptnonsurrogates_BYTES,
+  utf8acceptnonsurrogates_LOSUB,
+  utf8acceptnonsurrogates_HIADD,
+  utf8acceptnonsurrogates,
+  utf8acceptnonsurrogates_remap_base,
+  utf8acceptnonsurrogates_remap_string,
+  utf8acceptnonsurrogates_fast
+};
+
+
+#undef X__
+#undef RJ_
+#undef S1_
+#undef S2_
+#undef S3_
+#undef S21
+#undef S31
+#undef S32
+#undef T1_
+#undef T2_
+#undef S11
+#undef SP_
+#undef D__
+#undef RJA
+
+// Return true if current Tbl pointer is within state0 range
+// Note that unsigned compare checks both ends of range simultaneously
+static inline bool InStateZero(const UTF8ScanObj* st, const uint8* Tbl) {
+  const uint8* Tbl0 = &st->state_table[st->state0];
+  return (static_cast<uint32>(Tbl - Tbl0) < st->state0_size);
+}
+
+// Scan a UTF-8 string based on state table.
+// Always scan complete UTF-8 characters
+// Set number of bytes scanned. Return reason for exiting
+int UTF8GenericScan(const UTF8ScanObj* st,
+                    const char * str,
+                    int str_length,
+                    int* bytes_consumed) {
+  *bytes_consumed = 0;
+  if (str_length == 0) return kExitOK;
+
+  int eshift = st->entry_shift;
+  const uint8* isrc = reinterpret_cast<const uint8*>(str);
+  const uint8* src = isrc;
+  const uint8* srclimit = isrc + str_length;
+  const uint8* srclimit8 = srclimit - 7;
+  const uint8* Tbl_0 = &st->state_table[st->state0];
+
+ DoAgain:
+  // Do state-table scan
+  int e = 0;
+  uint8 c;
+  const uint8* Tbl2 = &st->fast_state[0];
+  const uint32 losub = st->losub;
+  const uint32 hiadd = st->hiadd;
+  // Check initial few bytes one at a time until 8-byte aligned
+  //----------------------------
+  while ((((uintptr_t)src & 0x07) != 0) &&
+         (src < srclimit) &&
+         Tbl2[src[0]] == 0) {
+    src++;
+  }
+  if (((uintptr_t)src & 0x07) == 0) {
+    // Do fast for groups of 8 identity bytes.
+    // This covers a lot of 7-bit ASCII ~8x faster then the 1-byte loop,
+    // including slowing slightly on cr/lf/ht
+    //----------------------------
+    while (src < srclimit8) {
+      uint32 s0123 = (reinterpret_cast<const uint32 *>(src))[0];
+      uint32 s4567 = (reinterpret_cast<const uint32 *>(src))[1];
+      src += 8;
+      // This is a fast range check for all bytes in [lowsub..0x80-hiadd)
+      uint32 temp = (s0123 - losub) | (s0123 + hiadd) |
+                    (s4567 - losub) | (s4567 + hiadd);
+      if ((temp & 0x80808080) != 0) {
+        // We typically end up here on cr/lf/ht; src was incremented
+        int e0123 = (Tbl2[src[-8]] | Tbl2[src[-7]]) |
+                    (Tbl2[src[-6]] | Tbl2[src[-5]]);
+        if (e0123 != 0) {
+          src -= 8;
+          break;
+        }    // Exit on Non-interchange
+        e0123 = (Tbl2[src[-4]] | Tbl2[src[-3]]) |
+                (Tbl2[src[-2]] | Tbl2[src[-1]]);
+        if (e0123 != 0) {
+          src -= 4;
+          break;
+        }    // Exit on Non-interchange
+        // Else OK, go around again
+      }
+    }
+  }
+  //----------------------------
+
+  // Byte-at-a-time scan
+  //----------------------------
+  const uint8* Tbl = Tbl_0;
+  while (src < srclimit) {
+    c = *src;
+    e = Tbl[c];
+    src++;
+    if (e >= kExitIllegalStructure) {break;}
+    Tbl = &Tbl_0[e << eshift];
+  }
+  //----------------------------
+
+
+  // Exit posibilities:
+  //  Some exit code, !state0, back up over last char
+  //  Some exit code, state0, back up one byte exactly
+  //  source consumed, !state0, back up over partial char
+  //  source consumed, state0, exit OK
+  // For illegal byte in state0, avoid backup up over PREVIOUS char
+  // For truncated last char, back up to beginning of it
+
+  if (e >= kExitIllegalStructure) {
+    // Back up over exactly one byte of rejected/illegal UTF-8 character
+    src--;
+    // Back up more if needed
+    if (!InStateZero(st, Tbl)) {
+      do {
+        src--;
+      } while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
+    }
+  } else if (!InStateZero(st, Tbl)) {
+    // Back up over truncated UTF-8 character
+    e = kExitIllegalStructure;
+    do {
+      src--;
+    } while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
+  } else {
+    // Normal termination, source fully consumed
+    e = kExitOK;
+  }
+
+  if (e == kExitDoAgain) {
+    // Loop back up to the fast scan
+    goto DoAgain;
+  }
+
+  *bytes_consumed = src - isrc;
+  return e;
+}
+
+int UTF8GenericScanFastAscii(const UTF8ScanObj* st,
+                    const char * str,
+                    int str_length,
+                    int* bytes_consumed) {
+  *bytes_consumed = 0;
+  if (str_length == 0) return kExitOK;
+
+  const uint8* isrc =  reinterpret_cast<const uint8*>(str);
+  const uint8* src = isrc;
+  const uint8* srclimit = isrc + str_length;
+  const uint8* srclimit8 = srclimit - 7;
+  int n;
+  int rest_consumed;
+  int exit_reason;
+  do {
+    // Check initial few bytes one at a time until 8-byte aligned
+    while ((((uintptr_t)src & 0x07) != 0) &&
+           (src < srclimit) && (src[0] < 0x80)) {
+      src++;
+    }
+    if (((uintptr_t)src & 0x07) == 0) {
+      while ((src < srclimit8) &&
+             (((reinterpret_cast<const uint32*>(src)[0] |
+                reinterpret_cast<const uint32*>(src)[1]) & 0x80808080) == 0)) {
+        src += 8;
+      }
+    }
+    while ((src < srclimit) && (src[0] < 0x80)) {
+      src++;
+    }
+    // Run state table on the rest
+    n = src - isrc;
+    exit_reason = UTF8GenericScan(st, str + n, str_length - n, &rest_consumed);
+    src += rest_consumed;
+  } while ( exit_reason == kExitDoAgain );
+
+  *bytes_consumed = src - isrc;
+  return exit_reason;
+}
+
+// Hack:  On some compilers the static tables are initialized at startup.
+//   We can't use them until they are initialized.  However, some Protocol
+//   Buffer parsing happens at static init time and may try to validate
+//   UTF-8 strings.  Since UTF-8 validation is only used for debugging
+//   anyway, we simply always return success if initialization hasn't
+//   occurred yet.
+namespace {
+
+bool module_initialized_ = false;
+
+struct InitDetector {
+  InitDetector() {
+    module_initialized_ = true;
+  }
+};
+InitDetector init_detector;
+
+}  // namespace
+
+bool IsStructurallyValidUTF8(const char* buf, int len) {
+  if (!module_initialized_) return true;
+  
+  int bytes_consumed = 0;
+  UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,
+                           buf, len, &bytes_consumed);
+  return (bytes_consumed == len);
+}
+
+int UTF8SpnStructurallyValid(const StringPiece& str) {
+  if (!module_initialized_) return str.size();
+
+  int bytes_consumed = 0;
+  UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,
+                           str.data(), str.size(), &bytes_consumed);
+  return bytes_consumed;
+}
+
+// Coerce UTF-8 byte string in src_str to be
+// a structurally-valid equal-length string by selectively
+// overwriting illegal bytes with replace_char (typically blank).
+// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
+// src_str is read-only. If any overwriting is needed, a modified byte string
+// is created in idst, length isrclen.
+//
+// Returns pointer to output buffer, isrc if no changes were made,
+//  or idst if some bytes were changed.
+//
+// Fast case: all is structurally valid and no byte copying is done.
+//
+char* UTF8CoerceToStructurallyValid(const StringPiece& src_str,
+                                    char* idst,
+                                    const char replace_char) {
+  const char* isrc = src_str.data();
+  const int len = src_str.length();
+  int n = UTF8SpnStructurallyValid(src_str);
+  if (n == len) {               // Normal case -- all is cool, return
+    return const_cast<char*>(isrc);
+  } else {                      // Unusual case -- copy w/o bad bytes
+    const char* src = isrc;
+    const char* srclimit = isrc + len;
+    char* dst = idst;
+    memmove(dst, src, n);       // Copy initial good chunk
+    src += n;
+    dst += n;
+    while (src < srclimit) {    // src points to bogus byte or is off the end
+      dst[0] = replace_char;                    // replace one bad byte
+      src++;
+      dst++;
+      StringPiece str2(src, srclimit - src);
+      n = UTF8SpnStructurallyValid(str2);       // scan the remainder
+      memmove(dst, src, n);                     // copy next good chunk
+      src += n;
+      dst += n;
+    }
+  }
+  return idst;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid_unittest.cc
new file mode 100644
index 0000000..9088888
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/structurally_valid_unittest.cc
@@ -0,0 +1,40 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+// Author: xpeng@google.com (Peter Peng)
+
+#include <google/protobuf/stubs/common.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(StructurallyValidTest, ValidUTF8String) {
+  // On GCC, this string can be written as:
+  //   "abcd 1234 - \u2014\u2013\u2212"
+  // MSVC seems to interpret \u differently.
+  string valid_str("abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789");
+  EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data(),
+                                      valid_str.size()));
+  // Additional check for pointer alignment
+  for (int i = 1; i < 8; ++i) {
+    EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data() + i,
+                                        valid_str.size() - i));
+  }
+}
+
+TEST(StructurallyValidTest, InvalidUTF8String) {
+  const string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789");
+  EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data(),
+                                       invalid_str.size()));
+  // Additional check for pointer alignment
+  for (int i = 1; i < 8; ++i) {
+    EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data() + i,
+                                         invalid_str.size() - i));
+  }
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.cc
new file mode 100644
index 0000000..7ba92e8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.cc
@@ -0,0 +1,2289 @@
+// 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.
+
+// from google3/strings/strutil.cc
+
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+#include <errno.h>
+#include <float.h>    // FLT_DIG and DBL_DIG
+#include <limits>
+#include <limits.h>
+#include <stdio.h>
+#include <iterator>
+
+#include <google/protobuf/stubs/stl_util.h>
+
+#ifdef _WIN32
+// MSVC has only _snprintf, not snprintf.
+//
+// MinGW has both snprintf and _snprintf, but they appear to be different
+// functions.  The former is buggy.  When invoked like so:
+//   char buffer[32];
+//   snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f);
+// it prints "1.23000e+10".  This is plainly wrong:  %g should never print
+// trailing zeros after the decimal point.  For some reason this bug only
+// occurs with some input values, not all.  In any case, _snprintf does the
+// right thing, so we use it.
+#define snprintf _snprintf
+#endif
+
+namespace google {
+namespace protobuf {
+
+// These are defined as macros on some platforms.  #undef them so that we can
+// redefine them.
+#undef isxdigit
+#undef isprint
+
+// The definitions of these in ctype.h change based on locale.  Since our
+// string manipulation is all in relation to the protocol buffer and C++
+// languages, we always want to use the C locale.  So, we re-define these
+// exactly as we want them.
+inline bool isxdigit(char c) {
+  return ('0' <= c && c <= '9') ||
+         ('a' <= c && c <= 'f') ||
+         ('A' <= c && c <= 'F');
+}
+
+inline bool isprint(char c) {
+  return c >= 0x20 && c <= 0x7E;
+}
+
+// ----------------------------------------------------------------------
+// StripString
+//    Replaces any occurrence of the character 'remove' (or the characters
+//    in 'remove') with the character 'replacewith'.
+// ----------------------------------------------------------------------
+void StripString(string* s, const char* remove, char replacewith) {
+  const char * str_start = s->c_str();
+  const char * str = str_start;
+  for (str = strpbrk(str, remove);
+       str != NULL;
+       str = strpbrk(str + 1, remove)) {
+    (*s)[str - str_start] = replacewith;
+  }
+}
+
+void StripWhitespace(string* str) {
+  int str_length = str->length();
+
+  // Strip off leading whitespace.
+  int first = 0;
+  while (first < str_length && ascii_isspace(str->at(first))) {
+    ++first;
+  }
+  // If entire string is white space.
+  if (first == str_length) {
+    str->clear();
+    return;
+  }
+  if (first > 0) {
+    str->erase(0, first);
+    str_length -= first;
+  }
+
+  // Strip off trailing whitespace.
+  int last = str_length - 1;
+  while (last >= 0 && ascii_isspace(str->at(last))) {
+    --last;
+  }
+  if (last != (str_length - 1) && last >= 0) {
+    str->erase(last + 1, string::npos);
+  }
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+//    Replace the "old" pattern with the "new" pattern in a string,
+//    and append the result to "res".  If replace_all is false,
+//    it only replaces the first instance of "old."
+// ----------------------------------------------------------------------
+
+void StringReplace(const string& s, const string& oldsub,
+                   const string& newsub, bool replace_all,
+                   string* res) {
+  if (oldsub.empty()) {
+    res->append(s);  // if empty, append the given string.
+    return;
+  }
+
+  string::size_type start_pos = 0;
+  string::size_type pos;
+  do {
+    pos = s.find(oldsub, start_pos);
+    if (pos == string::npos) {
+      break;
+    }
+    res->append(s, start_pos, pos - start_pos);
+    res->append(newsub);
+    start_pos = pos + oldsub.size();  // start searching again after the "old"
+  } while (replace_all);
+  res->append(s, start_pos, s.length() - start_pos);
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+//    Give me a string and two patterns "old" and "new", and I replace
+//    the first instance of "old" in the string with "new", if it
+//    exists.  If "global" is true; call this repeatedly until it
+//    fails.  RETURN a new string, regardless of whether the replacement
+//    happened or not.
+// ----------------------------------------------------------------------
+
+string StringReplace(const string& s, const string& oldsub,
+                     const string& newsub, bool replace_all) {
+  string ret;
+  StringReplace(s, oldsub, newsub, replace_all, &ret);
+  return ret;
+}
+
+// ----------------------------------------------------------------------
+// SplitStringUsing()
+//    Split a string using a character delimiter. Append the components
+//    to 'result'.
+//
+// Note: For multi-character delimiters, this routine will split on *ANY* of
+// the characters in the string, not the entire string as a single delimiter.
+// ----------------------------------------------------------------------
+template <typename ITR>
+static inline
+void SplitStringToIteratorUsing(const string& full,
+                                const char* delim,
+                                ITR& result) {
+  // Optimize the common case where delim is a single character.
+  if (delim[0] != '\0' && delim[1] == '\0') {
+    char c = delim[0];
+    const char* p = full.data();
+    const char* end = p + full.size();
+    while (p != end) {
+      if (*p == c) {
+        ++p;
+      } else {
+        const char* start = p;
+        while (++p != end && *p != c);
+        *result++ = string(start, p - start);
+      }
+    }
+    return;
+  }
+
+  string::size_type begin_index, end_index;
+  begin_index = full.find_first_not_of(delim);
+  while (begin_index != string::npos) {
+    end_index = full.find_first_of(delim, begin_index);
+    if (end_index == string::npos) {
+      *result++ = full.substr(begin_index);
+      return;
+    }
+    *result++ = full.substr(begin_index, (end_index - begin_index));
+    begin_index = full.find_first_not_of(delim, end_index);
+  }
+}
+
+void SplitStringUsing(const string& full,
+                      const char* delim,
+                      vector<string>* result) {
+  back_insert_iterator< vector<string> > it(*result);
+  SplitStringToIteratorUsing(full, delim, it);
+}
+
+// Split a string using a character delimiter. Append the components
+// to 'result'.  If there are consecutive delimiters, this function
+// will return corresponding empty strings. The string is split into
+// at most the specified number of pieces greedily. This means that the
+// last piece may possibly be split further. To split into as many pieces
+// as possible, specify 0 as the number of pieces.
+//
+// If "full" is the empty string, yields an empty string as the only value.
+//
+// If "pieces" is negative for some reason, it returns the whole string
+// ----------------------------------------------------------------------
+template <typename StringType, typename ITR>
+static inline
+void SplitStringToIteratorAllowEmpty(const StringType& full,
+                                     const char* delim,
+                                     int pieces,
+                                     ITR& result) {
+  string::size_type begin_index, end_index;
+  begin_index = 0;
+
+  for (int i = 0; (i < pieces-1) || (pieces == 0); i++) {
+    end_index = full.find_first_of(delim, begin_index);
+    if (end_index == string::npos) {
+      *result++ = full.substr(begin_index);
+      return;
+    }
+    *result++ = full.substr(begin_index, (end_index - begin_index));
+    begin_index = end_index + 1;
+  }
+  *result++ = full.substr(begin_index);
+}
+
+void SplitStringAllowEmpty(const string& full, const char* delim,
+                           vector<string>* result) {
+  back_insert_iterator<vector<string> > it(*result);
+  SplitStringToIteratorAllowEmpty(full, delim, 0, it);
+}
+
+// ----------------------------------------------------------------------
+// JoinStrings()
+//    This merges a vector of string components with delim inserted
+//    as separaters between components.
+//
+// ----------------------------------------------------------------------
+template <class ITERATOR>
+static void JoinStringsIterator(const ITERATOR& start,
+                                const ITERATOR& end,
+                                const char* delim,
+                                string* result) {
+  GOOGLE_CHECK(result != NULL);
+  result->clear();
+  int delim_length = strlen(delim);
+
+  // Precompute resulting length so we can reserve() memory in one shot.
+  int length = 0;
+  for (ITERATOR iter = start; iter != end; ++iter) {
+    if (iter != start) {
+      length += delim_length;
+    }
+    length += iter->size();
+  }
+  result->reserve(length);
+
+  // Now combine everything.
+  for (ITERATOR iter = start; iter != end; ++iter) {
+    if (iter != start) {
+      result->append(delim, delim_length);
+    }
+    result->append(iter->data(), iter->size());
+  }
+}
+
+void JoinStrings(const vector<string>& components,
+                 const char* delim,
+                 string * result) {
+  JoinStringsIterator(components.begin(), components.end(), delim, result);
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeSequences()
+//    This does all the unescaping that C does: \ooo, \r, \n, etc
+//    Returns length of resulting string.
+//    The implementation of \x parses any positive number of hex digits,
+//    but it is an error if the value requires more than 8 bits, and the
+//    result is truncated to 8 bits.
+//
+//    The second call stores its errors in a supplied string vector.
+//    If the string vector pointer is NULL, it reports the errors with LOG().
+// ----------------------------------------------------------------------
+
+#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7'))
+
+// Protocol buffers doesn't ever care about errors, but I don't want to remove
+// the code.
+#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false)
+
+int UnescapeCEscapeSequences(const char* source, char* dest) {
+  return UnescapeCEscapeSequences(source, dest, NULL);
+}
+
+int UnescapeCEscapeSequences(const char* source, char* dest,
+                             vector<string> *errors) {
+  GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented.";
+
+  char* d = dest;
+  const char* p = source;
+
+  // Small optimization for case where source = dest and there's no escaping
+  while ( p == d && *p != '\0' && *p != '\\' )
+    p++, d++;
+
+  while (*p != '\0') {
+    if (*p != '\\') {
+      *d++ = *p++;
+    } else {
+      switch ( *++p ) {                    // skip past the '\\'
+        case '\0':
+          LOG_STRING(ERROR, errors) << "String cannot end with \\";
+          *d = '\0';
+          return d - dest;   // we're done with p
+        case 'a':  *d++ = '\a';  break;
+        case 'b':  *d++ = '\b';  break;
+        case 'f':  *d++ = '\f';  break;
+        case 'n':  *d++ = '\n';  break;
+        case 'r':  *d++ = '\r';  break;
+        case 't':  *d++ = '\t';  break;
+        case 'v':  *d++ = '\v';  break;
+        case '\\': *d++ = '\\';  break;
+        case '?':  *d++ = '\?';  break;    // \?  Who knew?
+        case '\'': *d++ = '\'';  break;
+        case '"':  *d++ = '\"';  break;
+        case '0': case '1': case '2': case '3':  // octal digit: 1 to 3 digits
+        case '4': case '5': case '6': case '7': {
+          char ch = *p - '0';
+          if ( IS_OCTAL_DIGIT(p[1]) )
+            ch = ch * 8 + *++p - '0';
+          if ( IS_OCTAL_DIGIT(p[1]) )      // safe (and easy) to do this twice
+            ch = ch * 8 + *++p - '0';      // now points at last digit
+          *d++ = ch;
+          break;
+        }
+        case 'x': case 'X': {
+          if (!isxdigit(p[1])) {
+            if (p[1] == '\0') {
+              LOG_STRING(ERROR, errors) << "String cannot end with \\x";
+            } else {
+              LOG_STRING(ERROR, errors) <<
+                "\\x cannot be followed by non-hex digit: \\" << *p << p[1];
+            }
+            break;
+          }
+          unsigned int ch = 0;
+          const char *hex_start = p;
+          while (isxdigit(p[1]))  // arbitrarily many hex digits
+            ch = (ch << 4) + hex_digit_to_int(*++p);
+          if (ch > 0xFF)
+            LOG_STRING(ERROR, errors) << "Value of " <<
+              "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits";
+          *d++ = ch;
+          break;
+        }
+#if 0  // TODO(kenton):  Support \u and \U?  Requires runetochar().
+        case 'u': {
+          // \uhhhh => convert 4 hex digits to UTF-8
+          char32 rune = 0;
+          const char *hex_start = p;
+          for (int i = 0; i < 4; ++i) {
+            if (isxdigit(p[1])) {  // Look one char ahead.
+              rune = (rune << 4) + hex_digit_to_int(*++p);  // Advance p.
+            } else {
+              LOG_STRING(ERROR, errors)
+                << "\\u must be followed by 4 hex digits: \\"
+                <<  string(hex_start, p+1-hex_start);
+              break;
+            }
+          }
+          d += runetochar(d, &rune);
+          break;
+        }
+        case 'U': {
+          // \Uhhhhhhhh => convert 8 hex digits to UTF-8
+          char32 rune = 0;
+          const char *hex_start = p;
+          for (int i = 0; i < 8; ++i) {
+            if (isxdigit(p[1])) {  // Look one char ahead.
+              // Don't change rune until we're sure this
+              // is within the Unicode limit, but do advance p.
+              char32 newrune = (rune << 4) + hex_digit_to_int(*++p);
+              if (newrune > 0x10FFFF) {
+                LOG_STRING(ERROR, errors)
+                  << "Value of \\"
+                  << string(hex_start, p + 1 - hex_start)
+                  << " exceeds Unicode limit (0x10FFFF)";
+                break;
+              } else {
+                rune = newrune;
+              }
+            } else {
+              LOG_STRING(ERROR, errors)
+                << "\\U must be followed by 8 hex digits: \\"
+                <<  string(hex_start, p+1-hex_start);
+              break;
+            }
+          }
+          d += runetochar(d, &rune);
+          break;
+        }
+#endif
+        default:
+          LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p;
+      }
+      p++;                                 // read past letter we escaped
+    }
+  }
+  *d = '\0';
+  return d - dest;
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeString()
+//    This does the same thing as UnescapeCEscapeSequences, but creates
+//    a new string. The caller does not need to worry about allocating
+//    a dest buffer. This should be used for non performance critical
+//    tasks such as printing debug messages. It is safe for src and dest
+//    to be the same.
+//
+//    The second call stores its errors in a supplied string vector.
+//    If the string vector pointer is NULL, it reports the errors with LOG().
+//
+//    In the first and second calls, the length of dest is returned. In the
+//    the third call, the new string is returned.
+// ----------------------------------------------------------------------
+int UnescapeCEscapeString(const string& src, string* dest) {
+  return UnescapeCEscapeString(src, dest, NULL);
+}
+
+int UnescapeCEscapeString(const string& src, string* dest,
+                          vector<string> *errors) {
+  scoped_array<char> unescaped(new char[src.size() + 1]);
+  int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors);
+  GOOGLE_CHECK(dest);
+  dest->assign(unescaped.get(), len);
+  return len;
+}
+
+string UnescapeCEscapeString(const string& src) {
+  scoped_array<char> unescaped(new char[src.size() + 1]);
+  int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), NULL);
+  return string(unescaped.get(), len);
+}
+
+// ----------------------------------------------------------------------
+// CEscapeString()
+// CHexEscapeString()
+//    Copies 'src' to 'dest', escaping dangerous characters using
+//    C-style escape sequences. This is very useful for preparing query
+//    flags. 'src' and 'dest' should not overlap. The 'Hex' version uses
+//    hexadecimal rather than octal sequences.
+//    Returns the number of bytes written to 'dest' (not including the \0)
+//    or -1 if there was insufficient space.
+//
+//    Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
+// ----------------------------------------------------------------------
+int CEscapeInternal(const char* src, int src_len, char* dest,
+                    int dest_len, bool use_hex, bool utf8_safe) {
+  const char* src_end = src + src_len;
+  int used = 0;
+  bool last_hex_escape = false; // true if last output char was \xNN
+
+  for (; src < src_end; src++) {
+    if (dest_len - used < 2)   // Need space for two letter escape
+      return -1;
+
+    bool is_hex_escape = false;
+    switch (*src) {
+      case '\n': dest[used++] = '\\'; dest[used++] = 'n';  break;
+      case '\r': dest[used++] = '\\'; dest[used++] = 'r';  break;
+      case '\t': dest[used++] = '\\'; dest[used++] = 't';  break;
+      case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break;
+      case '\'': dest[used++] = '\\'; dest[used++] = '\''; break;
+      case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break;
+      default:
+        // Note that if we emit \xNN and the src character after that is a hex
+        // digit then that digit must be escaped too to prevent it being
+        // interpreted as part of the character code by C.
+        if ((!utf8_safe || static_cast<uint8>(*src) < 0x80) &&
+            (!isprint(*src) ||
+             (last_hex_escape && isxdigit(*src)))) {
+          if (dest_len - used < 4) // need space for 4 letter escape
+            return -1;
+          sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
+                  static_cast<uint8>(*src));
+          is_hex_escape = use_hex;
+          used += 4;
+        } else {
+          dest[used++] = *src; break;
+        }
+    }
+    last_hex_escape = is_hex_escape;
+  }
+
+  if (dest_len - used < 1)   // make sure that there is room for \0
+    return -1;
+
+  dest[used] = '\0';   // doesn't count towards return value though
+  return used;
+}
+
+// Calculates the length of the C-style escaped version of 'src'.
+// Assumes that non-printable characters are escaped using octal sequences, and
+// that UTF-8 bytes are not handled specially.
+static inline size_t CEscapedLength(StringPiece src) {
+  static char c_escaped_len[256] = {
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // ", '
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // '0'..'9'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'A'..'O'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,  // 'P'..'Z', '\'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'a'..'o'
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,  // 'p'..'z', DEL
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+  };
+
+  size_t escaped_len = 0;
+  for (int i = 0; i < src.size(); ++i) {
+    unsigned char c = static_cast<unsigned char>(src[i]);
+    escaped_len += c_escaped_len[c];
+  }
+  return escaped_len;
+}
+
+// ----------------------------------------------------------------------
+// Escapes 'src' using C-style escape sequences, and appends the escaped string
+// to 'dest'. This version is faster than calling CEscapeInternal as it computes
+// the required space using a lookup table, and also does not do any special
+// handling for Hex or UTF-8 characters.
+// ----------------------------------------------------------------------
+void CEscapeAndAppend(StringPiece src, string* dest) {
+  size_t escaped_len = CEscapedLength(src);
+  if (escaped_len == src.size()) {
+    dest->append(src.data(), src.size());
+    return;
+  }
+
+  size_t cur_dest_len = dest->size();
+  dest->resize(cur_dest_len + escaped_len);
+  char* append_ptr = &(*dest)[cur_dest_len];
+
+  for (int i = 0; i < src.size(); ++i) {
+    unsigned char c = static_cast<unsigned char>(src[i]);
+    switch (c) {
+      case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break;
+      case '\r': *append_ptr++ = '\\'; *append_ptr++ = 'r'; break;
+      case '\t': *append_ptr++ = '\\'; *append_ptr++ = 't'; break;
+      case '\"': *append_ptr++ = '\\'; *append_ptr++ = '\"'; break;
+      case '\'': *append_ptr++ = '\\'; *append_ptr++ = '\''; break;
+      case '\\': *append_ptr++ = '\\'; *append_ptr++ = '\\'; break;
+      default:
+        if (!isprint(c)) {
+          *append_ptr++ = '\\';
+          *append_ptr++ = '0' + c / 64;
+          *append_ptr++ = '0' + (c % 64) / 8;
+          *append_ptr++ = '0' + c % 8;
+        } else {
+          *append_ptr++ = c;
+        }
+        break;
+    }
+  }
+}
+
+string CEscape(const string& src) {
+  string dest;
+  CEscapeAndAppend(src, &dest);
+  return dest;
+}
+
+namespace strings {
+
+string Utf8SafeCEscape(const string& src) {
+  const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+  scoped_array<char> dest(new char[dest_length]);
+  const int len = CEscapeInternal(src.data(), src.size(),
+                                  dest.get(), dest_length, false, true);
+  GOOGLE_DCHECK_GE(len, 0);
+  return string(dest.get(), len);
+}
+
+string CHexEscape(const string& src) {
+  const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+  scoped_array<char> dest(new char[dest_length]);
+  const int len = CEscapeInternal(src.data(), src.size(),
+                                  dest.get(), dest_length, true, false);
+  GOOGLE_DCHECK_GE(len, 0);
+  return string(dest.get(), len);
+}
+
+}  // namespace strings
+
+// ----------------------------------------------------------------------
+// strto32_adaptor()
+// strtou32_adaptor()
+//    Implementation of strto[u]l replacements that have identical
+//    overflow and underflow characteristics for both ILP-32 and LP-64
+//    platforms, including errno preservation in error-free calls.
+// ----------------------------------------------------------------------
+
+int32 strto32_adaptor(const char *nptr, char **endptr, int base) {
+  const int saved_errno = errno;
+  errno = 0;
+  const long result = strtol(nptr, endptr, base);
+  if (errno == ERANGE && result == LONG_MIN) {
+    return kint32min;
+  } else if (errno == ERANGE && result == LONG_MAX) {
+    return kint32max;
+  } else if (errno == 0 && result < kint32min) {
+    errno = ERANGE;
+    return kint32min;
+  } else if (errno == 0 && result > kint32max) {
+    errno = ERANGE;
+    return kint32max;
+  }
+  if (errno == 0)
+    errno = saved_errno;
+  return static_cast<int32>(result);
+}
+
+uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) {
+  const int saved_errno = errno;
+  errno = 0;
+  const unsigned long result = strtoul(nptr, endptr, base);
+  if (errno == ERANGE && result == ULONG_MAX) {
+    return kuint32max;
+  } else if (errno == 0 && result > kuint32max) {
+    errno = ERANGE;
+    return kuint32max;
+  }
+  if (errno == 0)
+    errno = saved_errno;
+  return static_cast<uint32>(result);
+}
+
+inline bool safe_parse_sign(string* text  /*inout*/,
+                            bool* negative_ptr  /*output*/) {
+  const char* start = text->data();
+  const char* end = start + text->size();
+
+  // Consume whitespace.
+  while (start < end && (start[0] == ' ')) {
+    ++start;
+  }
+  while (start < end && (end[-1] == ' ')) {
+    --end;
+  }
+  if (start >= end) {
+    return false;
+  }
+
+  // Consume sign.
+  *negative_ptr = (start[0] == '-');
+  if (*negative_ptr || start[0] == '+') {
+    ++start;
+    if (start >= end) {
+      return false;
+    }
+  }
+  *text = text->substr(start - text->data(), end - start);
+  return true;
+}
+
+template<typename IntType>
+bool safe_parse_positive_int(
+    string text, IntType* value_p) {
+  int base = 10;
+  IntType value = 0;
+  const IntType vmax = std::numeric_limits<IntType>::max();
+  assert(vmax > 0);
+  assert(vmax >= base);
+  const IntType vmax_over_base = vmax / base;
+  const char* start = text.data();
+  const char* end = start + text.size();
+  // loop over digits
+  for (; start < end; ++start) {
+    unsigned char c = static_cast<unsigned char>(start[0]);
+    int digit = c - '0';
+    if (digit >= base || digit < 0) {
+      *value_p = value;
+      return false;
+    }
+    if (value > vmax_over_base) {
+      *value_p = vmax;
+      return false;
+    }
+    value *= base;
+    if (value > vmax - digit) {
+      *value_p = vmax;
+      return false;
+    }
+    value += digit;
+  }
+  *value_p = value;
+  return true;
+}
+
+template<typename IntType>
+bool safe_parse_negative_int(
+    const string& text, IntType* value_p) {
+  int base = 10;
+  IntType value = 0;
+  const IntType vmin = std::numeric_limits<IntType>::min();
+  assert(vmin < 0);
+  assert(vmin <= 0 - base);
+  IntType vmin_over_base = vmin / base;
+  // 2003 c++ standard [expr.mul]
+  // "... the sign of the remainder is implementation-defined."
+  // Although (vmin/base)*base + vmin%base is always vmin.
+  // 2011 c++ standard tightens the spec but we cannot rely on it.
+  if (vmin % base > 0) {
+    vmin_over_base += 1;
+  }
+  const char* start = text.data();
+  const char* end = start + text.size();
+  // loop over digits
+  for (; start < end; ++start) {
+    unsigned char c = static_cast<unsigned char>(start[0]);
+    int digit = c - '0';
+    if (digit >= base || digit < 0) {
+      *value_p = value;
+      return false;
+    }
+    if (value < vmin_over_base) {
+      *value_p = vmin;
+      return false;
+    }
+    value *= base;
+    if (value < vmin + digit) {
+      *value_p = vmin;
+      return false;
+    }
+    value -= digit;
+  }
+  *value_p = value;
+  return true;
+}
+
+template<typename IntType>
+bool safe_int_internal(string text, IntType* value_p) {
+  *value_p = 0;
+  bool negative;
+  if (!safe_parse_sign(&text, &negative)) {
+    return false;
+  }
+  if (!negative) {
+    return safe_parse_positive_int(text, value_p);
+  } else {
+    return safe_parse_negative_int(text, value_p);
+  }
+}
+
+template<typename IntType>
+bool safe_uint_internal(string text, IntType* value_p) {
+  *value_p = 0;
+  bool negative;
+  if (!safe_parse_sign(&text, &negative) || negative) {
+    return false;
+  }
+  return safe_parse_positive_int(text, value_p);
+}
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer()
+// FastInt64ToBuffer()
+// FastHexToBuffer()
+// FastHex64ToBuffer()
+// FastHex32ToBuffer()
+// ----------------------------------------------------------------------
+
+// Offset into buffer where FastInt64ToBuffer places the end of string
+// null character.  Also used by FastInt64ToBufferLeft.
+static const int kFastInt64ToBufferOffset = 21;
+
+char *FastInt64ToBuffer(int64 i, char* buffer) {
+  // We could collapse the positive and negative sections, but that
+  // would be slightly slower for positive numbers...
+  // 22 bytes is enough to store -2**64, -18446744073709551616.
+  char* p = buffer + kFastInt64ToBufferOffset;
+  *p-- = '\0';
+  if (i >= 0) {
+    do {
+      *p-- = '0' + i % 10;
+      i /= 10;
+    } while (i > 0);
+    return p + 1;
+  } else {
+    // On different platforms, % and / have different behaviors for
+    // negative numbers, so we need to jump through hoops to make sure
+    // we don't divide negative numbers.
+    if (i > -10) {
+      i = -i;
+      *p-- = '0' + i;
+      *p = '-';
+      return p;
+    } else {
+      // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+      i = i + 10;
+      i = -i;
+      *p-- = '0' + i % 10;
+      // Undo what we did a moment ago
+      i = i / 10 + 1;
+      do {
+        *p-- = '0' + i % 10;
+        i /= 10;
+      } while (i > 0);
+      *p = '-';
+      return p;
+    }
+  }
+}
+
+// Offset into buffer where FastInt32ToBuffer places the end of string
+// null character.  Also used by FastInt32ToBufferLeft
+static const int kFastInt32ToBufferOffset = 11;
+
+// Yes, this is a duplicate of FastInt64ToBuffer.  But, we need this for the
+// compiler to generate 32 bit arithmetic instructions.  It's much faster, at
+// least with 32 bit binaries.
+char *FastInt32ToBuffer(int32 i, char* buffer) {
+  // We could collapse the positive and negative sections, but that
+  // would be slightly slower for positive numbers...
+  // 12 bytes is enough to store -2**32, -4294967296.
+  char* p = buffer + kFastInt32ToBufferOffset;
+  *p-- = '\0';
+  if (i >= 0) {
+    do {
+      *p-- = '0' + i % 10;
+      i /= 10;
+    } while (i > 0);
+    return p + 1;
+  } else {
+    // On different platforms, % and / have different behaviors for
+    // negative numbers, so we need to jump through hoops to make sure
+    // we don't divide negative numbers.
+    if (i > -10) {
+      i = -i;
+      *p-- = '0' + i;
+      *p = '-';
+      return p;
+    } else {
+      // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+      i = i + 10;
+      i = -i;
+      *p-- = '0' + i % 10;
+      // Undo what we did a moment ago
+      i = i / 10 + 1;
+      do {
+        *p-- = '0' + i % 10;
+        i /= 10;
+      } while (i > 0);
+      *p = '-';
+      return p;
+    }
+  }
+}
+
+char *FastHexToBuffer(int i, char* buffer) {
+  GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i;
+
+  static const char *hexdigits = "0123456789abcdef";
+  char *p = buffer + 21;
+  *p-- = '\0';
+  do {
+    *p-- = hexdigits[i & 15];   // mod by 16
+    i >>= 4;                    // divide by 16
+  } while (i > 0);
+  return p + 1;
+}
+
+char *InternalFastHexToBuffer(uint64 value, char* buffer, int num_byte) {
+  static const char *hexdigits = "0123456789abcdef";
+  buffer[num_byte] = '\0';
+  for (int i = num_byte - 1; i >= 0; i--) {
+#ifdef _M_X64
+    // MSVC x64 platform has a bug optimizing the uint32(value) in the #else
+    // block. Given that the uint32 cast was to improve performance on 32-bit
+    // platforms, we use 64-bit '&' directly.
+    buffer[i] = hexdigits[value & 0xf];
+#else
+    buffer[i] = hexdigits[uint32(value) & 0xf];
+#endif
+    value >>= 4;
+  }
+  return buffer;
+}
+
+char *FastHex64ToBuffer(uint64 value, char* buffer) {
+  return InternalFastHexToBuffer(value, buffer, 16);
+}
+
+char *FastHex32ToBuffer(uint32 value, char* buffer) {
+  return InternalFastHexToBuffer(value, buffer, 8);
+}
+
+// ----------------------------------------------------------------------
+// FastInt32ToBufferLeft()
+// FastUInt32ToBufferLeft()
+// FastInt64ToBufferLeft()
+// FastUInt64ToBufferLeft()
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer (hence the name, as the
+// output is left-aligned).  The caller is responsible for ensuring that
+// the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+static const char two_ASCII_digits[100][2] = {
+  {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'},
+  {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'},
+  {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'},
+  {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'},
+  {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'},
+  {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'},
+  {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'},
+  {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'},
+  {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'},
+  {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'},
+  {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'},
+  {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'},
+  {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'},
+  {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'},
+  {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'},
+  {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'},
+  {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'},
+  {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'},
+  {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'},
+  {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'}
+};
+
+char* FastUInt32ToBufferLeft(uint32 u, char* buffer) {
+  int digits;
+  const char *ASCII_digits = NULL;
+  // The idea of this implementation is to trim the number of divides to as few
+  // as possible by using multiplication and subtraction rather than mod (%),
+  // and by outputting two digits at a time rather than one.
+  // The huge-number case is first, in the hopes that the compiler will output
+  // that case in one branch-free block of code, and only output conditional
+  // branches into it from below.
+  if (u >= 1000000000) {  // >= 1,000,000,000
+    digits = u / 100000000;  // 100,000,000
+    ASCII_digits = two_ASCII_digits[digits];
+    buffer[0] = ASCII_digits[0];
+    buffer[1] = ASCII_digits[1];
+    buffer += 2;
+sublt100_000_000:
+    u -= digits * 100000000;  // 100,000,000
+lt100_000_000:
+    digits = u / 1000000;  // 1,000,000
+    ASCII_digits = two_ASCII_digits[digits];
+    buffer[0] = ASCII_digits[0];
+    buffer[1] = ASCII_digits[1];
+    buffer += 2;
+sublt1_000_000:
+    u -= digits * 1000000;  // 1,000,000
+lt1_000_000:
+    digits = u / 10000;  // 10,000
+    ASCII_digits = two_ASCII_digits[digits];
+    buffer[0] = ASCII_digits[0];
+    buffer[1] = ASCII_digits[1];
+    buffer += 2;
+sublt10_000:
+    u -= digits * 10000;  // 10,000
+lt10_000:
+    digits = u / 100;
+    ASCII_digits = two_ASCII_digits[digits];
+    buffer[0] = ASCII_digits[0];
+    buffer[1] = ASCII_digits[1];
+    buffer += 2;
+sublt100:
+    u -= digits * 100;
+lt100:
+    digits = u;
+    ASCII_digits = two_ASCII_digits[digits];
+    buffer[0] = ASCII_digits[0];
+    buffer[1] = ASCII_digits[1];
+    buffer += 2;
+done:
+    *buffer = 0;
+    return buffer;
+  }
+
+  if (u < 100) {
+    digits = u;
+    if (u >= 10) goto lt100;
+    *buffer++ = '0' + digits;
+    goto done;
+  }
+  if (u  <  10000) {   // 10,000
+    if (u >= 1000) goto lt10_000;
+    digits = u / 100;
+    *buffer++ = '0' + digits;
+    goto sublt100;
+  }
+  if (u  <  1000000) {   // 1,000,000
+    if (u >= 100000) goto lt1_000_000;
+    digits = u / 10000;  //    10,000
+    *buffer++ = '0' + digits;
+    goto sublt10_000;
+  }
+  if (u  <  100000000) {   // 100,000,000
+    if (u >= 10000000) goto lt100_000_000;
+    digits = u / 1000000;  //   1,000,000
+    *buffer++ = '0' + digits;
+    goto sublt1_000_000;
+  }
+  // we already know that u < 1,000,000,000
+  digits = u / 100000000;   // 100,000,000
+  *buffer++ = '0' + digits;
+  goto sublt100_000_000;
+}
+
+char* FastInt32ToBufferLeft(int32 i, char* buffer) {
+  uint32 u = i;
+  if (i < 0) {
+    *buffer++ = '-';
+    u = -i;
+  }
+  return FastUInt32ToBufferLeft(u, buffer);
+}
+
+char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) {
+  int digits;
+  const char *ASCII_digits = NULL;
+
+  uint32 u = static_cast<uint32>(u64);
+  if (u == u64) return FastUInt32ToBufferLeft(u, buffer);
+
+  uint64 top_11_digits = u64 / 1000000000;
+  buffer = FastUInt64ToBufferLeft(top_11_digits, buffer);
+  u = u64 - (top_11_digits * 1000000000);
+
+  digits = u / 10000000;  // 10,000,000
+  GOOGLE_DCHECK_LT(digits, 100);
+  ASCII_digits = two_ASCII_digits[digits];
+  buffer[0] = ASCII_digits[0];
+  buffer[1] = ASCII_digits[1];
+  buffer += 2;
+  u -= digits * 10000000;  // 10,000,000
+  digits = u / 100000;  // 100,000
+  ASCII_digits = two_ASCII_digits[digits];
+  buffer[0] = ASCII_digits[0];
+  buffer[1] = ASCII_digits[1];
+  buffer += 2;
+  u -= digits * 100000;  // 100,000
+  digits = u / 1000;  // 1,000
+  ASCII_digits = two_ASCII_digits[digits];
+  buffer[0] = ASCII_digits[0];
+  buffer[1] = ASCII_digits[1];
+  buffer += 2;
+  u -= digits * 1000;  // 1,000
+  digits = u / 10;
+  ASCII_digits = two_ASCII_digits[digits];
+  buffer[0] = ASCII_digits[0];
+  buffer[1] = ASCII_digits[1];
+  buffer += 2;
+  u -= digits * 10;
+  digits = u;
+  *buffer++ = '0' + digits;
+  *buffer = 0;
+  return buffer;
+}
+
+char* FastInt64ToBufferLeft(int64 i, char* buffer) {
+  uint64 u = i;
+  if (i < 0) {
+    *buffer++ = '-';
+    u = -i;
+  }
+  return FastUInt64ToBufferLeft(u, buffer);
+}
+
+// ----------------------------------------------------------------------
+// SimpleItoa()
+//    Description: converts an integer to a string.
+//
+//    Return value: string
+// ----------------------------------------------------------------------
+
+string SimpleItoa(int i) {
+  char buffer[kFastToBufferSize];
+  return (sizeof(i) == 4) ?
+    FastInt32ToBuffer(i, buffer) :
+    FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned int i) {
+  char buffer[kFastToBufferSize];
+  return string(buffer, (sizeof(i) == 4) ?
+    FastUInt32ToBufferLeft(i, buffer) :
+    FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long i) {
+  char buffer[kFastToBufferSize];
+  return (sizeof(i) == 4) ?
+    FastInt32ToBuffer(i, buffer) :
+    FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long i) {
+  char buffer[kFastToBufferSize];
+  return string(buffer, (sizeof(i) == 4) ?
+    FastUInt32ToBufferLeft(i, buffer) :
+    FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long long i) {
+  char buffer[kFastToBufferSize];
+  return (sizeof(i) == 4) ?
+    FastInt32ToBuffer(i, buffer) :
+    FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long long i) {
+  char buffer[kFastToBufferSize];
+  return string(buffer, (sizeof(i) == 4) ?
+    FastUInt32ToBufferLeft(i, buffer) :
+    FastUInt64ToBufferLeft(i, buffer));
+}
+
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+// DoubleToBuffer()
+// FloatToBuffer()
+//    We want to print the value without losing precision, but we also do
+//    not want to print more digits than necessary.  This turns out to be
+//    trickier than it sounds.  Numbers like 0.2 cannot be represented
+//    exactly in binary.  If we print 0.2 with a very large precision,
+//    e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167".
+//    On the other hand, if we set the precision too low, we lose
+//    significant digits when printing numbers that actually need them.
+//    It turns out there is no precision value that does the right thing
+//    for all numbers.
+//
+//    Our strategy is to first try printing with a precision that is never
+//    over-precise, then parse the result with strtod() to see if it
+//    matches.  If not, we print again with a precision that will always
+//    give a precise result, but may use more digits than necessary.
+//
+//    An arguably better strategy would be to use the algorithm described
+//    in "How to Print Floating-Point Numbers Accurately" by Steele &
+//    White, e.g. as implemented by David M. Gay's dtoa().  It turns out,
+//    however, that the following implementation is about as fast as
+//    DMG's code.  Furthermore, DMG's code locks mutexes, which means it
+//    will not scale well on multi-core machines.  DMG's code is slightly
+//    more accurate (in that it will never use more digits than
+//    necessary), but this is probably irrelevant for most users.
+//
+//    Rob Pike and Ken Thompson also have an implementation of dtoa() in
+//    third_party/fmt/fltfmt.cc.  Their implementation is similar to this
+//    one in that it makes guesses and then uses strtod() to check them.
+//    Their implementation is faster because they use their own code to
+//    generate the digits in the first place rather than use snprintf(),
+//    thus avoiding format string parsing overhead.  However, this makes
+//    it considerably more complicated than the following implementation,
+//    and it is embedded in a larger library.  If speed turns out to be
+//    an issue, we could re-implement this in terms of their
+//    implementation.
+// ----------------------------------------------------------------------
+
+string SimpleDtoa(double value) {
+  char buffer[kDoubleToBufferSize];
+  return DoubleToBuffer(value, buffer);
+}
+
+string SimpleFtoa(float value) {
+  char buffer[kFloatToBufferSize];
+  return FloatToBuffer(value, buffer);
+}
+
+static inline bool IsValidFloatChar(char c) {
+  return ('0' <= c && c <= '9') ||
+         c == 'e' || c == 'E' ||
+         c == '+' || c == '-';
+}
+
+void DelocalizeRadix(char* buffer) {
+  // Fast check:  if the buffer has a normal decimal point, assume no
+  // translation is needed.
+  if (strchr(buffer, '.') != NULL) return;
+
+  // Find the first unknown character.
+  while (IsValidFloatChar(*buffer)) ++buffer;
+
+  if (*buffer == '\0') {
+    // No radix character found.
+    return;
+  }
+
+  // We are now pointing at the locale-specific radix character.  Replace it
+  // with '.'.
+  *buffer = '.';
+  ++buffer;
+
+  if (!IsValidFloatChar(*buffer) && *buffer != '\0') {
+    // It appears the radix was a multi-byte character.  We need to remove the
+    // extra bytes.
+    char* target = buffer;
+    do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0');
+    memmove(target, buffer, strlen(buffer) + 1);
+  }
+}
+
+char* DoubleToBuffer(double value, char* buffer) {
+  // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all
+  // platforms these days.  Just in case some system exists where DBL_DIG
+  // is significantly larger -- and risks overflowing our buffer -- we have
+  // this assert.
+  GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big);
+
+  if (value == numeric_limits<double>::infinity()) {
+    strcpy(buffer, "inf");
+    return buffer;
+  } else if (value == -numeric_limits<double>::infinity()) {
+    strcpy(buffer, "-inf");
+    return buffer;
+  } else if (MathLimits<double>::IsNaN(value)) {
+    strcpy(buffer, "nan");
+    return buffer;
+  }
+
+  int snprintf_result =
+    snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value);
+
+  // The snprintf should never overflow because the buffer is significantly
+  // larger than the precision we asked for.
+  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+
+  // We need to make parsed_value volatile in order to force the compiler to
+  // write it out to the stack.  Otherwise, it may keep the value in a
+  // register, and if it does that, it may keep it as a long double instead
+  // of a double.  This long double may have extra bits that make it compare
+  // unequal to "value" even though it would be exactly equal if it were
+  // truncated to a double.
+  volatile double parsed_value = strtod(buffer, NULL);
+  if (parsed_value != value) {
+    int snprintf_result =
+      snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value);
+
+    // Should never overflow; see above.
+    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+  }
+
+  DelocalizeRadix(buffer);
+  return buffer;
+}
+
+static int memcasecmp(const char *s1, const char *s2, size_t len) {
+  const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1);
+  const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2);
+
+  for ( int i = 0; i < len; i++ ) {
+    const int diff =
+      static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) -
+      static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i])));
+    if (diff != 0) return diff;
+  }
+  return 0;
+}
+
+inline bool CaseEqual(StringPiece s1, StringPiece s2) {
+  if (s1.size() != s2.size()) return false;
+  return memcasecmp(s1.data(), s2.data(), s1.size()) == 0;
+}
+
+bool safe_strtob(StringPiece str, bool* value) {
+  GOOGLE_CHECK(value != NULL) << "NULL output boolean given.";
+  if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
+      CaseEqual(str, "yes") || CaseEqual(str, "y") ||
+      CaseEqual(str, "1")) {
+    *value = true;
+    return true;
+  }
+  if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
+      CaseEqual(str, "no") || CaseEqual(str, "n") ||
+      CaseEqual(str, "0")) {
+    *value = false;
+    return true;
+  }
+  return false;
+}
+
+bool safe_strtof(const char* str, float* value) {
+  char* endptr;
+  errno = 0;  // errno only gets set on errors
+#if defined(_WIN32) || defined (__hpux)  // has no strtof()
+  *value = strtod(str, &endptr);
+#else
+  *value = strtof(str, &endptr);
+#endif
+  return *str != 0 && *endptr == 0 && errno == 0;
+}
+
+bool safe_strtod(const char* str, double* value) {
+  char* endptr;
+  *value = strtod(str, &endptr);
+  if (endptr != str) {
+    while (ascii_isspace(*endptr)) ++endptr;
+  }
+  // Ignore range errors from strtod.  The values it
+  // returns on underflow and overflow are the right
+  // fallback in a robust setting.
+  return *str != '\0' && *endptr == '\0';
+}
+
+bool safe_strto32(const string& str, int32* value) {
+  return safe_int_internal(str, value);
+}
+
+bool safe_strtou32(const string& str, uint32* value) {
+  return safe_uint_internal(str, value);
+}
+
+bool safe_strto64(const string& str, int64* value) {
+  return safe_int_internal(str, value);
+}
+
+bool safe_strtou64(const string& str, uint64* value) {
+  return safe_uint_internal(str, value);
+}
+
+char* FloatToBuffer(float value, char* buffer) {
+  // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
+  // platforms these days.  Just in case some system exists where FLT_DIG
+  // is significantly larger -- and risks overflowing our buffer -- we have
+  // this assert.
+  GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big);
+
+  if (value == numeric_limits<double>::infinity()) {
+    strcpy(buffer, "inf");
+    return buffer;
+  } else if (value == -numeric_limits<double>::infinity()) {
+    strcpy(buffer, "-inf");
+    return buffer;
+  } else if (MathLimits<float>::IsNaN(value)) {
+    strcpy(buffer, "nan");
+    return buffer;
+  }
+
+  int snprintf_result =
+    snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value);
+
+  // The snprintf should never overflow because the buffer is significantly
+  // larger than the precision we asked for.
+  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+
+  float parsed_value;
+  if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
+    int snprintf_result =
+      snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value);
+
+    // Should never overflow; see above.
+    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+  }
+
+  DelocalizeRadix(buffer);
+  return buffer;
+}
+
+namespace strings {
+
+AlphaNum::AlphaNum(strings::Hex hex) {
+  char *const end = &digits[kFastToBufferSize];
+  char *writer = end;
+  uint64 value = hex.value;
+  uint64 width = hex.spec;
+  // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
+  // where 0x10000 is the smallest hex number that is as wide as the user
+  // asked for.
+  uint64 mask = ((static_cast<uint64>(1) << (width - 1) * 4)) | value;
+  static const char hexdigits[] = "0123456789abcdef";
+  do {
+    *--writer = hexdigits[value & 0xF];
+    value >>= 4;
+    mask >>= 4;
+  } while (mask != 0);
+  piece_data_ = writer;
+  piece_size_ = end - writer;
+}
+
+}  // namespace strings
+
+// ----------------------------------------------------------------------
+// StrCat()
+//    This merges the given strings or integers, with no delimiter.  This
+//    is designed to be the fastest possible way to construct a string out
+//    of a mix of raw C strings, C++ strings, and integer values.
+// ----------------------------------------------------------------------
+
+// Append is merely a version of memcpy that returns the address of the byte
+// after the area just overwritten.  It comes in multiple flavors to minimize
+// call overhead.
+static char *Append1(char *out, const AlphaNum &x) {
+  memcpy(out, x.data(), x.size());
+  return out + x.size();
+}
+
+static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
+  memcpy(out, x1.data(), x1.size());
+  out += x1.size();
+
+  memcpy(out, x2.data(), x2.size());
+  return out + x2.size();
+}
+
+static char *Append4(char *out,
+                     const AlphaNum &x1, const AlphaNum &x2,
+                     const AlphaNum &x3, const AlphaNum &x4) {
+  memcpy(out, x1.data(), x1.size());
+  out += x1.size();
+
+  memcpy(out, x2.data(), x2.size());
+  out += x2.size();
+
+  memcpy(out, x3.data(), x3.size());
+  out += x3.size();
+
+  memcpy(out, x4.data(), x4.size());
+  return out + x4.size();
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b) {
+  string result;
+  result.resize(a.size() + b.size());
+  char *const begin = &*result.begin();
+  char *out = Append2(begin, a, b);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+  string result;
+  result.resize(a.size() + b.size() + c.size());
+  char *const begin = &*result.begin();
+  char *out = Append2(begin, a, b);
+  out = Append1(out, c);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append1(out, e);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append2(out, e, f);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append2(out, e, f);
+  out = Append1(out, g);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size() + h.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append4(out, e, f, g, h);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+              const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
+  string result;
+  result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+                f.size() + g.size() + h.size() + i.size());
+  char *const begin = &*result.begin();
+  char *out = Append4(begin, a, b, c, d);
+  out = Append4(out, e, f, g, h);
+  out = Append1(out, i);
+  GOOGLE_DCHECK_EQ(out, begin + result.size());
+  return result;
+}
+
+// It's possible to call StrAppend with a char * pointer that is partway into
+// the string we're appending to.  However the results of this are random.
+// Therefore, check for this in debug mode.  Use unsigned math so we only have
+// to do one comparison.
+#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \
+    GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
+                     uintptr_t((dest).size()))
+
+void StrAppend(string *result, const AlphaNum &a) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  result->append(a.data(), a.size());
+}
+
+void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size());
+  char *const begin = &*result->begin();
+  char *out = Append2(begin + old_size, a, b);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+               const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size() + c.size());
+  char *const begin = &*result->begin();
+  char *out = Append2(begin + old_size, a, b);
+  out = Append1(out, c);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+               const AlphaNum &a, const AlphaNum &b,
+               const AlphaNum &c, const AlphaNum &d) {
+  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+  GOOGLE_DCHECK_NO_OVERLAP(*result, d);
+  string::size_type old_size = result->size();
+  result->resize(old_size + a.size() + b.size() + c.size() + d.size());
+  char *const begin = &*result->begin();
+  char *out = Append4(begin + old_size, a, b, c, d);
+  GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+int GlobalReplaceSubstring(const string& substring,
+                           const string& replacement,
+                           string* s) {
+  GOOGLE_CHECK(s != NULL);
+  if (s->empty() || substring.empty())
+    return 0;
+  string tmp;
+  int num_replacements = 0;
+  int pos = 0;
+  for (int match_pos = s->find(substring.data(), pos, substring.length());
+       match_pos != string::npos;
+       pos = match_pos + substring.length(),
+           match_pos = s->find(substring.data(), pos, substring.length())) {
+    ++num_replacements;
+    // Append the original content before the match.
+    tmp.append(*s, pos, match_pos - pos);
+    // Append the replacement for the match.
+    tmp.append(replacement.begin(), replacement.end());
+  }
+  // Append the content after the last match. If no replacements were made, the
+  // original string is left untouched.
+  if (num_replacements > 0) {
+    tmp.append(*s, pos, s->length() - pos);
+    s->swap(tmp);
+  }
+  return num_replacements;
+}
+
+int CalculateBase64EscapedLen(int input_len, bool do_padding) {
+  // Base64 encodes three bytes of input at a time. If the input is not
+  // divisible by three, we pad as appropriate.
+  //
+  // (from http://tools.ietf.org/html/rfc3548)
+  // Special processing is performed if fewer than 24 bits are available
+  // at the end of the data being encoded.  A full encoding quantum is
+  // always completed at the end of a quantity.  When fewer than 24 input
+  // bits are available in an input group, zero bits are added (on the
+  // right) to form an integral number of 6-bit groups.  Padding at the
+  // end of the data is performed using the '=' character.  Since all base
+  // 64 input is an integral number of octets, only the following cases
+  // can arise:
+
+
+  // Base64 encodes each three bytes of input into four bytes of output.
+  int len = (input_len / 3) * 4;
+
+  if (input_len % 3 == 0) {
+    // (from http://tools.ietf.org/html/rfc3548)
+    // (1) the final quantum of encoding input is an integral multiple of 24
+    // bits; here, the final unit of encoded output will be an integral
+    // multiple of 4 characters with no "=" padding,
+  } else if (input_len % 3 == 1) {
+    // (from http://tools.ietf.org/html/rfc3548)
+    // (2) the final quantum of encoding input is exactly 8 bits; here, the
+    // final unit of encoded output will be two characters followed by two
+    // "=" padding characters, or
+    len += 2;
+    if (do_padding) {
+      len += 2;
+    }
+  } else {  // (input_len % 3 == 2)
+    // (from http://tools.ietf.org/html/rfc3548)
+    // (3) the final quantum of encoding input is exactly 16 bits; here, the
+    // final unit of encoded output will be three characters followed by one
+    // "=" padding character.
+    len += 3;
+    if (do_padding) {
+      len += 1;
+    }
+  }
+
+  assert(len >= input_len);  // make sure we didn't overflow
+  return len;
+}
+
+// Base64Escape does padding, so this calculation includes padding.
+int CalculateBase64EscapedLen(int input_len) {
+  return CalculateBase64EscapedLen(input_len, true);
+}
+
+// ----------------------------------------------------------------------
+// int Base64Unescape() - base64 decoder
+// int Base64Escape() - base64 encoder
+// int WebSafeBase64Unescape() - Google's variation of base64 decoder
+// int WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://tools.ietf.org/html/rfc2045 for formal description, but what we
+// care about is that...
+//   Take the encoded stuff in groups of 4 characters and turn each
+//   character into a code 0 to 63 thus:
+//           A-Z map to 0 to 25
+//           a-z map to 26 to 51
+//           0-9 map to 52 to 61
+//           +(- for WebSafe) maps to 62
+//           /(_ for WebSafe) maps to 63
+//   There will be four numbers, all less than 64 which can be represented
+//   by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+//   Arrange the 6 digit binary numbers into three bytes as such:
+//   aaaaaabb bbbbcccc ccdddddd
+//   Equals signs (one or two) are used at the end of the encoded block to
+//   indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
+int Base64UnescapeInternal(const char *src_param, int szsrc,
+                           char *dest, int szdest,
+                           const signed char* unbase64) {
+  static const char kPad64Equals = '=';
+  static const char kPad64Dot = '.';
+
+  int decode = 0;
+  int destidx = 0;
+  int state = 0;
+  unsigned int ch = 0;
+  unsigned int temp = 0;
+
+  // If "char" is signed by default, using *src as an array index results in
+  // accessing negative array elements. Treat the input as a pointer to
+  // unsigned char to avoid this.
+  const unsigned char *src = reinterpret_cast<const unsigned char*>(src_param);
+
+  // The GET_INPUT macro gets the next input character, skipping
+  // over any whitespace, and stopping when we reach the end of the
+  // string or when we read any non-data character.  The arguments are
+  // an arbitrary identifier (used as a label for goto) and the number
+  // of data bytes that must remain in the input to avoid aborting the
+  // loop.
+#define GET_INPUT(label, remain)                 \
+  label:                                         \
+    --szsrc;                                     \
+    ch = *src++;                                 \
+    decode = unbase64[ch];                       \
+    if (decode < 0) {                            \
+      if (ascii_isspace(ch) && szsrc >= remain)  \
+        goto label;                              \
+      state = 4 - remain;                        \
+      break;                                     \
+    }
+
+  // if dest is null, we're just checking to see if it's legal input
+  // rather than producing output.  (I suspect this could just be done
+  // with a regexp...).  We duplicate the loop so this test can be
+  // outside it instead of in every iteration.
+
+  if (dest) {
+    // This loop consumes 4 input bytes and produces 3 output bytes
+    // per iteration.  We can't know at the start that there is enough
+    // data left in the string for a full iteration, so the loop may
+    // break out in the middle; if so 'state' will be set to the
+    // number of input bytes read.
+
+    while (szsrc >= 4)  {
+      // We'll start by optimistically assuming that the next four
+      // bytes of the string (src[0..3]) are four good data bytes
+      // (that is, no nulls, whitespace, padding chars, or illegal
+      // chars).  We need to test src[0..2] for nulls individually
+      // before constructing temp to preserve the property that we
+      // never read past a null in the string (no matter how long
+      // szsrc claims the string is).
+
+      if (!src[0] || !src[1] || !src[2] ||
+          (temp = ((unsigned(unbase64[src[0]]) << 18) |
+                   (unsigned(unbase64[src[1]]) << 12) |
+                   (unsigned(unbase64[src[2]]) << 6) |
+                   (unsigned(unbase64[src[3]])))) & 0x80000000) {
+        // Iff any of those four characters was bad (null, illegal,
+        // whitespace, padding), then temp's high bit will be set
+        // (because unbase64[] is -1 for all bad characters).
+        //
+        // We'll back up and resort to the slower decoder, which knows
+        // how to handle those cases.
+
+        GET_INPUT(first, 4);
+        temp = decode;
+        GET_INPUT(second, 3);
+        temp = (temp << 6) | decode;
+        GET_INPUT(third, 2);
+        temp = (temp << 6) | decode;
+        GET_INPUT(fourth, 1);
+        temp = (temp << 6) | decode;
+      } else {
+        // We really did have four good data bytes, so advance four
+        // characters in the string.
+
+        szsrc -= 4;
+        src += 4;
+        decode = -1;
+        ch = '\0';
+      }
+
+      // temp has 24 bits of input, so write that out as three bytes.
+
+      if (destidx+3 > szdest) return -1;
+      dest[destidx+2] = temp;
+      temp >>= 8;
+      dest[destidx+1] = temp;
+      temp >>= 8;
+      dest[destidx] = temp;
+      destidx += 3;
+    }
+  } else {
+    while (szsrc >= 4)  {
+      if (!src[0] || !src[1] || !src[2] ||
+          (temp = ((unsigned(unbase64[src[0]]) << 18) |
+                   (unsigned(unbase64[src[1]]) << 12) |
+                   (unsigned(unbase64[src[2]]) << 6) |
+                   (unsigned(unbase64[src[3]])))) & 0x80000000) {
+        GET_INPUT(first_no_dest, 4);
+        GET_INPUT(second_no_dest, 3);
+        GET_INPUT(third_no_dest, 2);
+        GET_INPUT(fourth_no_dest, 1);
+      } else {
+        szsrc -= 4;
+        src += 4;
+        decode = -1;
+        ch = '\0';
+      }
+      destidx += 3;
+    }
+  }
+
+#undef GET_INPUT
+
+  // if the loop terminated because we read a bad character, return
+  // now.
+  if (decode < 0 && ch != '\0' &&
+      ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch))
+    return -1;
+
+  if (ch == kPad64Equals || ch == kPad64Dot) {
+    // if we stopped by hitting an '=' or '.', un-read that character -- we'll
+    // look at it again when we count to check for the proper number of
+    // equals signs at the end.
+    ++szsrc;
+    --src;
+  } else {
+    // This loop consumes 1 input byte per iteration.  It's used to
+    // clean up the 0-3 input bytes remaining when the first, faster
+    // loop finishes.  'temp' contains the data from 'state' input
+    // characters read by the first loop.
+    while (szsrc > 0)  {
+      --szsrc;
+      ch = *src++;
+      decode = unbase64[ch];
+      if (decode < 0) {
+        if (ascii_isspace(ch)) {
+          continue;
+        } else if (ch == '\0') {
+          break;
+        } else if (ch == kPad64Equals || ch == kPad64Dot) {
+          // back up one character; we'll read it again when we check
+          // for the correct number of pad characters at the end.
+          ++szsrc;
+          --src;
+          break;
+        } else {
+          return -1;
+        }
+      }
+
+      // Each input character gives us six bits of output.
+      temp = (temp << 6) | decode;
+      ++state;
+      if (state == 4) {
+        // If we've accumulated 24 bits of output, write that out as
+        // three bytes.
+        if (dest) {
+          if (destidx+3 > szdest) return -1;
+          dest[destidx+2] = temp;
+          temp >>= 8;
+          dest[destidx+1] = temp;
+          temp >>= 8;
+          dest[destidx] = temp;
+        }
+        destidx += 3;
+        state = 0;
+        temp = 0;
+      }
+    }
+  }
+
+  // Process the leftover data contained in 'temp' at the end of the input.
+  int expected_equals = 0;
+  switch (state) {
+    case 0:
+      // Nothing left over; output is a multiple of 3 bytes.
+      break;
+
+    case 1:
+      // Bad input; we have 6 bits left over.
+      return -1;
+
+    case 2:
+      // Produce one more output byte from the 12 input bits we have left.
+      if (dest) {
+        if (destidx+1 > szdest) return -1;
+        temp >>= 4;
+        dest[destidx] = temp;
+      }
+      ++destidx;
+      expected_equals = 2;
+      break;
+
+    case 3:
+      // Produce two more output bytes from the 18 input bits we have left.
+      if (dest) {
+        if (destidx+2 > szdest) return -1;
+        temp >>= 2;
+        dest[destidx+1] = temp;
+        temp >>= 8;
+        dest[destidx] = temp;
+      }
+      destidx += 2;
+      expected_equals = 1;
+      break;
+
+    default:
+      // state should have no other values at this point.
+      GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state;
+  }
+
+  // The remainder of the string should be all whitespace, mixed with
+  // exactly 0 equals signs, or exactly 'expected_equals' equals
+  // signs.  (Always accepting 0 equals signs is a google extension
+  // not covered in the RFC, as is accepting dot as the pad character.)
+
+  int equals = 0;
+  while (szsrc > 0 && *src) {
+    if (*src == kPad64Equals || *src == kPad64Dot)
+      ++equals;
+    else if (!ascii_isspace(*src))
+      return -1;
+    --szsrc;
+    ++src;
+  }
+
+  return (equals == 0 || equals == expected_equals) ? destidx : -1;
+}
+
+// The arrays below were generated by the following code
+// #include <sys/time.h>
+// #include <stdlib.h>
+// #include <string.h>
+// main()
+// {
+//   static const char Base64[] =
+//     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+//   char *pos;
+//   int idx, i, j;
+//   printf("    ");
+//   for (i = 0; i < 255; i += 8) {
+//     for (j = i; j < i + 8; j++) {
+//       pos = strchr(Base64, j);
+//       if ((pos == NULL) || (j == 0))
+//         idx = -1;
+//       else
+//         idx = pos - Base64;
+//       if (idx == -1)
+//         printf(" %2d,     ", idx);
+//       else
+//         printf(" %2d/*%c*/,", idx, j);
+//     }
+//     printf("\n    ");
+//   }
+// }
+//
+// where the value of "Base64[]" was replaced by one of the base-64 conversion
+// tables from the functions below.
+static const signed char kUnBase64[] = {
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
+  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
+  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
+  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
+};
+static const signed char kUnWebSafeBase64[] = {
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      62/*-*/, -1,      -1,
+  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
+  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
+  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      63/*_*/,
+  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
+  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
+};
+
+int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+  return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64);
+}
+
+static bool Base64UnescapeInternal(const char* src, int slen, string* dest,
+                                   const signed char* unbase64) {
+  // Determine the size of the output string.  Base64 encodes every 3 bytes into
+  // 4 characters.  any leftover chars are added directly for good measure.
+  // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
+  const int dest_len = 3 * (slen / 4) + (slen % 4);
+
+  dest->resize(dest_len);
+
+  // We are getting the destination buffer by getting the beginning of the
+  // string and converting it into a char *.
+  const int len = Base64UnescapeInternal(src, slen, string_as_array(dest),
+                                         dest_len, unbase64);
+  if (len < 0) {
+    dest->clear();
+    return false;
+  }
+
+  // could be shorter if there was padding
+  GOOGLE_DCHECK_LE(len, dest_len);
+  dest->erase(len);
+
+  return true;
+}
+
+bool Base64Unescape(StringPiece src, string* dest) {
+  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
+}
+
+bool WebSafeBase64Unescape(StringPiece src, string* dest) {
+  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
+}
+
+int Base64EscapeInternal(const unsigned char *src, int szsrc,
+                         char *dest, int szdest, const char *base64,
+                         bool do_padding) {
+  static const char kPad64 = '=';
+
+  if (szsrc <= 0) return 0;
+
+  if (szsrc * 4 > szdest * 3) return 0;
+
+  char *cur_dest = dest;
+  const unsigned char *cur_src = src;
+
+  char *limit_dest = dest + szdest;
+  const unsigned char *limit_src = src + szsrc;
+
+  // Three bytes of data encodes to four characters of cyphertext.
+  // So we can pump through three-byte chunks atomically.
+  while (cur_src < limit_src - 3) {  // keep going as long as we have >= 32 bits
+    uint32 in = BigEndian::Load32(cur_src) >> 8;
+
+    cur_dest[0] = base64[in >> 18];
+    in &= 0x3FFFF;
+    cur_dest[1] = base64[in >> 12];
+    in &= 0xFFF;
+    cur_dest[2] = base64[in >> 6];
+    in &= 0x3F;
+    cur_dest[3] = base64[in];
+
+    cur_dest += 4;
+    cur_src += 3;
+  }
+  // To save time, we didn't update szdest or szsrc in the loop.  So do it now.
+  szdest = limit_dest - cur_dest;
+  szsrc = limit_src - cur_src;
+
+  /* now deal with the tail (<=3 bytes) */
+  switch (szsrc) {
+    case 0:
+      // Nothing left; nothing more to do.
+      break;
+    case 1: {
+      // One byte left: this encodes to two characters, and (optionally)
+      // two pad characters to round out the four-character cypherblock.
+      if ((szdest -= 2) < 0) return 0;
+      uint32 in = cur_src[0];
+      cur_dest[0] = base64[in >> 2];
+      in &= 0x3;
+      cur_dest[1] = base64[in << 4];
+      cur_dest += 2;
+      if (do_padding) {
+        if ((szdest -= 2) < 0) return 0;
+        cur_dest[0] = kPad64;
+        cur_dest[1] = kPad64;
+        cur_dest += 2;
+      }
+      break;
+    }
+    case 2: {
+      // Two bytes left: this encodes to three characters, and (optionally)
+      // one pad character to round out the four-character cypherblock.
+      if ((szdest -= 3) < 0) return 0;
+      uint32 in = BigEndian::Load16(cur_src);
+      cur_dest[0] = base64[in >> 10];
+      in &= 0x3FF;
+      cur_dest[1] = base64[in >> 4];
+      in &= 0x00F;
+      cur_dest[2] = base64[in << 2];
+      cur_dest += 3;
+      if (do_padding) {
+        if ((szdest -= 1) < 0) return 0;
+        cur_dest[0] = kPad64;
+        cur_dest += 1;
+      }
+      break;
+    }
+    case 3: {
+      // Three bytes left: same as in the big loop above.  We can't do this in
+      // the loop because the loop above always reads 4 bytes, and the fourth
+      // byte is past the end of the input.
+      if ((szdest -= 4) < 0) return 0;
+      uint32 in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1);
+      cur_dest[0] = base64[in >> 18];
+      in &= 0x3FFFF;
+      cur_dest[1] = base64[in >> 12];
+      in &= 0xFFF;
+      cur_dest[2] = base64[in >> 6];
+      in &= 0x3F;
+      cur_dest[3] = base64[in];
+      cur_dest += 4;
+      break;
+    }
+    default:
+      // Should not be reached: blocks of 4 bytes are handled
+      // in the while loop before this switch statement.
+      GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc;
+      break;
+  }
+  return (cur_dest - dest);
+}
+
+static const char kBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char kWebSafeBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
+  return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
+}
+int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
+                        int szdest, bool do_padding) {
+  return Base64EscapeInternal(src, szsrc, dest, szdest,
+                              kWebSafeBase64Chars, do_padding);
+}
+
+void Base64EscapeInternal(const unsigned char* src, int szsrc,
+                          string* dest, bool do_padding,
+                          const char* base64_chars) {
+  const int calc_escaped_size =
+    CalculateBase64EscapedLen(szsrc, do_padding);
+  dest->resize(calc_escaped_size);
+  const int escaped_len = Base64EscapeInternal(src, szsrc,
+                                               string_as_array(dest),
+                                               dest->size(),
+                                               base64_chars,
+                                               do_padding);
+  GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len);
+  dest->erase(escaped_len);
+}
+
+void Base64Escape(const unsigned char *src, int szsrc,
+                  string* dest, bool do_padding) {
+  Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars);
+}
+
+void WebSafeBase64Escape(const unsigned char *src, int szsrc,
+                         string *dest, bool do_padding) {
+  Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars);
+}
+
+void Base64Escape(StringPiece src, string* dest) {
+  Base64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+               src.size(), dest, true);
+}
+
+void WebSafeBase64Escape(StringPiece src, string* dest) {
+  WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+                      src.size(), dest, false);
+}
+
+void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) {
+  WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+                      src.size(), dest, true);
+}
+
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies.
+int EncodeAsUTF8Char(uint32 code_point, char* output) {
+  uint32 tmp = 0;
+  int len = 0;
+  if (code_point <= 0x7f) {
+    tmp = code_point;
+    len = 1;
+  } else if (code_point <= 0x07ff) {
+    tmp = 0x0000c080 |
+        ((code_point & 0x07c0) << 2) |
+        (code_point & 0x003f);
+    len = 2;
+  } else if (code_point <= 0xffff) {
+    tmp = 0x00e08080 |
+        ((code_point & 0xf000) << 4) |
+        ((code_point & 0x0fc0) << 2) |
+        (code_point & 0x003f);
+    len = 3;
+  } else {
+    // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
+    // normally only defined up to there as well.
+    tmp = 0xf0808080 |
+        ((code_point & 0x1c0000) << 6) |
+        ((code_point & 0x03f000) << 4) |
+        ((code_point & 0x000fc0) << 2) |
+        (code_point & 0x003f);
+    len = 4;
+  }
+  tmp = ghtonl(tmp);
+  memcpy(output, reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
+  return len;
+}
+
+// Table of UTF-8 character lengths, based on first byte
+static const unsigned char kUTF8LenTbl[256] = {
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+  2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,
+  3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4
+};
+
+// Return length of a single UTF-8 source character
+int UTF8FirstLetterNumBytes(const char* src, int len) {
+  if (len == 0) {
+    return 0;
+  }
+  return kUTF8LenTbl[*reinterpret_cast<const uint8*>(src)];
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.h
new file mode 100644
index 0000000..8bdd611
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil.h
@@ -0,0 +1,876 @@
+// 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.
+
+// from google3/strings/strutil.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
+
+#include <stdlib.h>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+#define strtoll  _strtoi64
+#define strtoull _strtoui64
+#elif defined(__DECCXX) && defined(__osf__)
+// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
+#define strtoll strtol
+#define strtoull strtoul
+#endif
+
+// ----------------------------------------------------------------------
+// ascii_isalnum()
+//    Check if an ASCII character is alphanumeric.  We can't use ctype's
+//    isalnum() because it is affected by locale.  This function is applied
+//    to identifiers in the protocol buffer language, not to natural-language
+//    strings, so locale should not be taken into account.
+// ascii_isdigit()
+//    Like above, but only accepts digits.
+// ascii_isspace()
+//    Check if the character is a space character.
+// ----------------------------------------------------------------------
+
+inline bool ascii_isalnum(char c) {
+  return ('a' <= c && c <= 'z') ||
+         ('A' <= c && c <= 'Z') ||
+         ('0' <= c && c <= '9');
+}
+
+inline bool ascii_isdigit(char c) {
+  return ('0' <= c && c <= '9');
+}
+
+inline bool ascii_isspace(char c) {
+  return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
+      c == '\r';
+}
+
+inline bool ascii_isupper(char c) {
+  return c >= 'A' && c <= 'Z';
+}
+
+inline bool ascii_islower(char c) {
+  return c >= 'a' && c <= 'z';
+}
+
+inline char ascii_toupper(char c) {
+  return ascii_islower(c) ? c - ('a' - 'A') : c;
+}
+
+inline char ascii_tolower(char c) {
+  return ascii_isupper(c) ? c + ('a' - 'A') : c;
+}
+
+inline int hex_digit_to_int(char c) {
+  /* Assume ASCII. */
+  int x = static_cast<unsigned char>(c);
+  if (x > '9') {
+    x += 9;
+  }
+  return x & 0xf;
+}
+
+// ----------------------------------------------------------------------
+// HasPrefixString()
+//    Check if a string begins with a given prefix.
+// StripPrefixString()
+//    Given a string and a putative prefix, returns the string minus the
+//    prefix string if the prefix matches, otherwise the original
+//    string.
+// ----------------------------------------------------------------------
+inline bool HasPrefixString(const string& str,
+                            const string& prefix) {
+  return str.size() >= prefix.size() &&
+         str.compare(0, prefix.size(), prefix) == 0;
+}
+
+inline string StripPrefixString(const string& str, const string& prefix) {
+  if (HasPrefixString(str, prefix)) {
+    return str.substr(prefix.size());
+  } else {
+    return str;
+  }
+}
+
+// ----------------------------------------------------------------------
+// HasSuffixString()
+//    Return true if str ends in suffix.
+// StripSuffixString()
+//    Given a string and a putative suffix, returns the string minus the
+//    suffix string if the suffix matches, otherwise the original
+//    string.
+// ----------------------------------------------------------------------
+inline bool HasSuffixString(const string& str,
+                            const string& suffix) {
+  return str.size() >= suffix.size() &&
+         str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+inline string StripSuffixString(const string& str, const string& suffix) {
+  if (HasSuffixString(str, suffix)) {
+    return str.substr(0, str.size() - suffix.size());
+  } else {
+    return str;
+  }
+}
+
+// ----------------------------------------------------------------------
+// StripString
+//    Replaces any occurrence of the character 'remove' (or the characters
+//    in 'remove') with the character 'replacewith'.
+//    Good for keeping html characters or protocol characters (\t) out
+//    of places where they might cause a problem.
+// StripWhitespace
+//    Removes whitespaces from both ends of the given string.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
+                                    char replacewith);
+
+LIBPROTOBUF_EXPORT void StripWhitespace(string* s);
+
+
+// ----------------------------------------------------------------------
+// LowerString()
+// UpperString()
+// ToUpper()
+//    Convert the characters in "s" to lowercase or uppercase.  ASCII-only:
+//    these functions intentionally ignore locale because they are applied to
+//    identifiers used in the Protocol Buffer language, not to natural-language
+//    strings.
+// ----------------------------------------------------------------------
+
+inline void LowerString(string * s) {
+  string::iterator end = s->end();
+  for (string::iterator i = s->begin(); i != end; ++i) {
+    // tolower() changes based on locale.  We don't want this!
+    if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
+  }
+}
+
+inline void UpperString(string * s) {
+  string::iterator end = s->end();
+  for (string::iterator i = s->begin(); i != end; ++i) {
+    // toupper() changes based on locale.  We don't want this!
+    if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
+  }
+}
+
+inline string ToUpper(const string& s) {
+  string out = s;
+  UpperString(&out);
+  return out;
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+//    Give me a string and two patterns "old" and "new", and I replace
+//    the first instance of "old" in the string with "new", if it
+//    exists.  RETURN a new string, regardless of whether the replacement
+//    happened or not.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
+                                        const string& newsub, bool replace_all);
+
+// ----------------------------------------------------------------------
+// SplitStringUsing()
+//    Split a string using a character delimiter. Append the components
+//    to 'result'.  If there are consecutive delimiters, this function skips
+//    over all of them.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
+                                         vector<string>* res);
+
+// Split a string using one or more byte delimiters, presented
+// as a nul-terminated c string. Append the components to 'result'.
+// If there are consecutive delimiters, this function will return
+// corresponding empty strings.  If you want to drop the empty
+// strings, try SplitStringUsing().
+//
+// If "full" is the empty string, yields an empty string as the only value.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
+                                              const char* delim,
+                                              vector<string>* result);
+
+// ----------------------------------------------------------------------
+// Split()
+//    Split a string using a character delimiter.
+// ----------------------------------------------------------------------
+inline vector<string> Split(
+    const string& full, const char* delim, bool skip_empty = true) {
+  vector<string> result;
+  if (skip_empty) {
+    SplitStringUsing(full, delim, &result);
+  } else {
+    SplitStringAllowEmpty(full, delim, &result);
+  }
+  return result;
+}
+
+// ----------------------------------------------------------------------
+// JoinStrings()
+//    These methods concatenate a vector of strings into a C++ string, using
+//    the C-string "delim" as a separator between components. There are two
+//    flavors of the function, one flavor returns the concatenated string,
+//    another takes a pointer to the target string. In the latter case the
+//    target string is cleared and overwritten.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void JoinStrings(const vector<string>& components,
+                                    const char* delim, string* result);
+
+inline string JoinStrings(const vector<string>& components,
+                          const char* delim) {
+  string result;
+  JoinStrings(components, delim, &result);
+  return result;
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeSequences()
+//    Copies "source" to "dest", rewriting C-style escape sequences
+//    -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
+//    equivalents.  "dest" must be sufficiently large to hold all
+//    the characters in the rewritten string (i.e. at least as large
+//    as strlen(source) + 1 should be safe, since the replacements
+//    are always shorter than the original escaped sequences).  It's
+//    safe for source and dest to be the same.  RETURNS the length
+//    of dest.
+//
+//    It allows hex sequences \xhh, or generally \xhhhhh with an
+//    arbitrary number of hex digits, but all of them together must
+//    specify a value of a single byte (e.g. \x0045 is equivalent
+//    to \x45, and \x1234 is erroneous).
+//
+//    It also allows escape sequences of the form \uhhhh (exactly four
+//    hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
+//    hex digits, upper or lower case) to specify a Unicode code
+//    point. The dest array will contain the UTF8-encoded version of
+//    that code-point (e.g., if source contains \u2019, then dest will
+//    contain the three bytes 0xE2, 0x80, and 0x99).
+//
+//    Errors: In the first form of the call, errors are reported with
+//    LOG(ERROR). The same is true for the second form of the call if
+//    the pointer to the string vector is NULL; otherwise, error
+//    messages are stored in the vector. In either case, the effect on
+//    the dest array is not defined, but rest of the source will be
+//    processed.
+//    ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
+LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
+                                                vector<string> *errors);
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeString()
+//    This does the same thing as UnescapeCEscapeSequences, but creates
+//    a new string. The caller does not need to worry about allocating
+//    a dest buffer. This should be used for non performance critical
+//    tasks such as printing debug messages. It is safe for src and dest
+//    to be the same.
+//
+//    The second call stores its errors in a supplied string vector.
+//    If the string vector pointer is NULL, it reports the errors with LOG().
+//
+//    In the first and second calls, the length of dest is returned. In the
+//    the third call, the new string is returned.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
+LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
+                                             vector<string> *errors);
+LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);
+
+// ----------------------------------------------------------------------
+// CEscape()
+//    Escapes 'src' using C-style escape sequences and returns the resulting
+//    string.
+//
+//    Escaped chars: \n, \r, \t, ", ', \, and !isprint().
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string CEscape(const string& src);
+
+// ----------------------------------------------------------------------
+// CEscapeAndAppend()
+//    Escapes 'src' using C-style escape sequences, and appends the escaped
+//    string to 'dest'.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest);
+
+namespace strings {
+// Like CEscape() but does not escape bytes with the upper bit set.
+LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
+
+// Like CEscape() but uses hex (\x) escapes instead of octals.
+LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
+}  // namespace strings
+
+// ----------------------------------------------------------------------
+// strto32()
+// strtou32()
+// strto64()
+// strtou64()
+//    Architecture-neutral plug compatible replacements for strtol() and
+//    strtoul().  Long's have different lengths on ILP-32 and LP-64
+//    platforms, so using these is safer, from the point of view of
+//    overflow behavior, than using the standard libc functions.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr,
+                                         int base);
+LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr,
+                                           int base);
+
+inline int32 strto32(const char *nptr, char **endptr, int base) {
+  if (sizeof(int32) == sizeof(long))
+    return strtol(nptr, endptr, base);
+  else
+    return strto32_adaptor(nptr, endptr, base);
+}
+
+inline uint32 strtou32(const char *nptr, char **endptr, int base) {
+  if (sizeof(uint32) == sizeof(unsigned long))
+    return strtoul(nptr, endptr, base);
+  else
+    return strtou32_adaptor(nptr, endptr, base);
+}
+
+// For now, long long is 64-bit on all the platforms we care about, so these
+// functions can simply pass the call to strto[u]ll.
+inline int64 strto64(const char *nptr, char **endptr, int base) {
+  GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
+                        sizeof_int64_is_not_sizeof_long_long);
+  return strtoll(nptr, endptr, base);
+}
+
+inline uint64 strtou64(const char *nptr, char **endptr, int base) {
+  GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
+                        sizeof_uint64_is_not_sizeof_long_long);
+  return strtoull(nptr, endptr, base);
+}
+
+// ----------------------------------------------------------------------
+// safe_strtob()
+// safe_strto32()
+// safe_strtou32()
+// safe_strto64()
+// safe_strtou64()
+// safe_strtof()
+// safe_strtod()
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
+
+LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value);
+LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value);
+inline bool safe_strto32(const char* str, int32* value) {
+  return safe_strto32(string(str), value);
+}
+inline bool safe_strto32(StringPiece str, int32* value) {
+  return safe_strto32(str.ToString(), value);
+}
+inline bool safe_strtou32(const char* str, uint32* value) {
+  return safe_strtou32(string(str), value);
+}
+inline bool safe_strtou32(StringPiece str, uint32* value) {
+  return safe_strtou32(str.ToString(), value);
+}
+
+LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value);
+LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value);
+inline bool safe_strto64(const char* str, int64* value) {
+  return safe_strto64(string(str), value);
+}
+inline bool safe_strto64(StringPiece str, int64* value) {
+  return safe_strto64(str.ToString(), value);
+}
+inline bool safe_strtou64(const char* str, uint64* value) {
+  return safe_strtou64(string(str), value);
+}
+inline bool safe_strtou64(StringPiece str, uint64* value) {
+  return safe_strtou64(str.ToString(), value);
+}
+
+LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
+LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
+inline bool safe_strtof(const string& str, float* value) {
+  return safe_strtof(str.c_str(), value);
+}
+inline bool safe_strtod(const string& str, double* value) {
+  return safe_strtod(str.c_str(), value);
+}
+inline bool safe_strtof(StringPiece str, float* value) {
+  return safe_strtof(str.ToString(), value);
+}
+inline bool safe_strtod(StringPiece str, double* value) {
+  return safe_strtod(str.ToString(), value);
+}
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer()
+// FastHexToBuffer()
+// FastHex64ToBuffer()
+// FastHex32ToBuffer()
+// FastTimeToBuffer()
+//    These are intended for speed.  FastIntToBuffer() assumes the
+//    integer is non-negative.  FastHexToBuffer() puts output in
+//    hex rather than decimal.  FastTimeToBuffer() puts the output
+//    into RFC822 format.
+//
+//    FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
+//    padded to exactly 16 bytes (plus one byte for '\0')
+//
+//    FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
+//    padded to exactly 8 bytes (plus one byte for '\0')
+//
+//       All functions take the output buffer as an arg.
+//    They all return a pointer to the beginning of the output,
+//    which may not be the beginning of the input buffer.
+// ----------------------------------------------------------------------
+
+// Suggested buffer size for FastToBuffer functions.  Also works with
+// DoubleToBuffer() and FloatToBuffer().
+static const int kFastToBufferSize = 32;
+
+LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer);
+char* FastUInt32ToBuffer(uint32 i, char* buffer);  // inline below
+char* FastUInt64ToBuffer(uint64 i, char* buffer);  // inline below
+LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer);
+
+// at least 22 bytes long
+inline char* FastIntToBuffer(int i, char* buffer) {
+  return (sizeof(i) == 4 ?
+          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
+}
+inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
+  return (sizeof(i) == 4 ?
+          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
+}
+inline char* FastLongToBuffer(long i, char* buffer) {
+  return (sizeof(i) == 4 ?
+          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
+}
+inline char* FastULongToBuffer(unsigned long i, char* buffer) {
+  return (sizeof(i) == 4 ?
+          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
+}
+
+// ----------------------------------------------------------------------
+// FastInt32ToBufferLeft()
+// FastUInt32ToBufferLeft()
+// FastInt64ToBufferLeft()
+// FastUInt64ToBufferLeft()
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer (hence the name, as the
+// output is left-aligned).  The caller is responsible for ensuring that
+// the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer);
+
+// Just define these in terms of the above.
+inline char* FastUInt32ToBuffer(uint32 i, char* buffer) {
+  FastUInt32ToBufferLeft(i, buffer);
+  return buffer;
+}
+inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
+  FastUInt64ToBufferLeft(i, buffer);
+  return buffer;
+}
+
+inline string SimpleBtoa(bool value) {
+  return value ? "true" : "false";
+}
+
+// ----------------------------------------------------------------------
+// SimpleItoa()
+//    Description: converts an integer to a string.
+//
+//    Return value: string
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string SimpleItoa(int i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i);
+LIBPROTOBUF_EXPORT string SimpleItoa(long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(long long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i);
+
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+// DoubleToBuffer()
+// FloatToBuffer()
+//    Description: converts a double or float to a string which, if
+//    passed to NoLocaleStrtod(), will produce the exact same original double
+//    (except in case of NaN; all NaNs are considered the same value).
+//    We try to keep the string short but it's not guaranteed to be as
+//    short as possible.
+//
+//    DoubleToBuffer() and FloatToBuffer() write the text to the given
+//    buffer and return it.  The buffer must be at least
+//    kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
+//    bytes for floats.  kFastToBufferSize is also guaranteed to be large
+//    enough to hold either.
+//
+//    Return value: string
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string SimpleDtoa(double value);
+LIBPROTOBUF_EXPORT string SimpleFtoa(float value);
+
+LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
+LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
+
+// In practice, doubles should never need more than 24 bytes and floats
+// should never need more than 14 (including null terminators), but we
+// overestimate to be safe.
+static const int kDoubleToBufferSize = 32;
+static const int kFloatToBufferSize = 24;
+
+namespace strings {
+
+enum PadSpec {
+  NO_PAD = 1,
+  ZERO_PAD_2,
+  ZERO_PAD_3,
+  ZERO_PAD_4,
+  ZERO_PAD_5,
+  ZERO_PAD_6,
+  ZERO_PAD_7,
+  ZERO_PAD_8,
+  ZERO_PAD_9,
+  ZERO_PAD_10,
+  ZERO_PAD_11,
+  ZERO_PAD_12,
+  ZERO_PAD_13,
+  ZERO_PAD_14,
+  ZERO_PAD_15,
+  ZERO_PAD_16,
+};
+
+struct Hex {
+  uint64 value;
+  enum PadSpec spec;
+  template <class Int>
+  explicit Hex(Int v, PadSpec s = NO_PAD)
+      : spec(s) {
+    // Prevent sign-extension by casting integers to
+    // their unsigned counterparts.
+#ifdef LANG_CXX11
+    static_assert(
+        sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
+        "Unknown integer type");
+#endif
+    value = sizeof(v) == 1 ? static_cast<uint8>(v)
+          : sizeof(v) == 2 ? static_cast<uint16>(v)
+          : sizeof(v) == 4 ? static_cast<uint32>(v)
+          : static_cast<uint64>(v);
+  }
+};
+
+struct LIBPROTOBUF_EXPORT AlphaNum {
+  const char *piece_data_;  // move these to string_ref eventually
+  size_t piece_size_;       // move these to string_ref eventually
+
+  char digits[kFastToBufferSize];
+
+  // No bool ctor -- bools convert to an integral type.
+  // A bool ctor would also convert incoming pointers (bletch).
+
+  AlphaNum(int32 i32)
+      : piece_data_(digits),
+        piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
+  AlphaNum(uint32 u32)
+      : piece_data_(digits),
+        piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
+  AlphaNum(int64 i64)
+      : piece_data_(digits),
+        piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
+  AlphaNum(uint64 u64)
+      : piece_data_(digits),
+        piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
+
+  AlphaNum(float f)
+    : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
+  AlphaNum(double f)
+    : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
+
+  AlphaNum(Hex hex);
+
+  AlphaNum(const char* c_str)
+      : piece_data_(c_str), piece_size_(strlen(c_str)) {}
+  // TODO: Add a string_ref constructor, eventually
+  // AlphaNum(const StringPiece &pc) : piece(pc) {}
+
+  AlphaNum(const string& str)
+      : piece_data_(str.data()), piece_size_(str.size()) {}
+
+  AlphaNum(StringPiece str)
+      : piece_data_(str.data()), piece_size_(str.size()) {}
+
+  AlphaNum(internal::StringPiecePod str)
+      : piece_data_(str.data()), piece_size_(str.size()) {}
+
+  size_t size() const { return piece_size_; }
+  const char *data() const { return piece_data_; }
+
+ private:
+  // Use ":" not ':'
+  AlphaNum(char c);  // NOLINT(runtime/explicit)
+
+  // Disallow copy and assign.
+  AlphaNum(const AlphaNum&);
+  void operator=(const AlphaNum&);
+};
+
+}  // namespace strings
+
+using strings::AlphaNum;
+
+// ----------------------------------------------------------------------
+// StrCat()
+//    This merges the given strings or numbers, with no delimiter.  This
+//    is designed to be the fastest possible way to construct a string out
+//    of a mix of raw C strings, strings, bool values,
+//    and numeric values.
+//
+//    Don't use this for user-visible strings.  The localization process
+//    works poorly on strings built up out of fragments.
+//
+//    For clarity and performance, don't use StrCat when appending to a
+//    string.  In particular, avoid using any of these (anti-)patterns:
+//      str.append(StrCat(...)
+//      str += StrCat(...)
+//      str = StrCat(str, ...)
+//    where the last is the worse, with the potential to change a loop
+//    from a linear time operation with O(1) dynamic allocations into a
+//    quadratic time operation with O(n) dynamic allocations.  StrAppend
+//    is a better choice than any of the above, subject to the restriction
+//    of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
+//    be a reference into str.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d,
+                                 const AlphaNum& e);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d,
+                                 const AlphaNum& e, const AlphaNum& f);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d,
+                                 const AlphaNum& e, const AlphaNum& f,
+                                 const AlphaNum& g);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d,
+                                 const AlphaNum& e, const AlphaNum& f,
+                                 const AlphaNum& g, const AlphaNum& h);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d,
+                                 const AlphaNum& e, const AlphaNum& f,
+                                 const AlphaNum& g, const AlphaNum& h,
+                                 const AlphaNum& i);
+
+inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
+
+// ----------------------------------------------------------------------
+// StrAppend()
+//    Same as above, but adds the output to the given string.
+//    WARNING: For speed, StrAppend does not try to check each of its input
+//    arguments to be sure that they are not a subset of the string being
+//    appended to.  That is, while this will work:
+//
+//    string s = "foo";
+//    s += s;
+//
+//    This will not (necessarily) work:
+//
+//    string s = "foo";
+//    StrAppend(&s, s);
+//
+//    Note: while StrCat supports appending up to 9 arguments, StrAppend
+//    is currently limited to 4.  That's rarely an issue except when
+//    automatically transforming StrCat to StrAppend, and can easily be
+//    worked around as consecutive calls to StrAppend are quite efficient.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+                                  const AlphaNum& b);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+                                  const AlphaNum& b, const AlphaNum& c);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+                                  const AlphaNum& b, const AlphaNum& c,
+                                  const AlphaNum& d);
+
+// ----------------------------------------------------------------------
+// Join()
+//    These methods concatenate a range of components into a C++ string, using
+//    the C-string "delim" as a separator between components.
+// ----------------------------------------------------------------------
+template <typename Iterator>
+void Join(Iterator start, Iterator end,
+          const char* delim, string* result) {
+  for (Iterator it = start; it != end; ++it) {
+    if (it != start) {
+      result->append(delim);
+    }
+    StrAppend(result, *it);
+  }
+}
+
+template <typename Range>
+string Join(const Range& components,
+            const char* delim) {
+  string result;
+  Join(components.begin(), components.end(), delim, &result);
+  return result;
+}
+
+// ----------------------------------------------------------------------
+// ToHex()
+//    Return a lower-case hex string representation of the given integer.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string ToHex(uint64 num);
+
+// ----------------------------------------------------------------------
+// GlobalReplaceSubstring()
+//    Replaces all instances of a substring in a string.  Does nothing
+//    if 'substring' is empty.  Returns the number of replacements.
+//
+//    NOTE: The string pieces must not overlap s.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
+                                              const string& replacement,
+                                              string* s);
+
+// ----------------------------------------------------------------------
+// Base64Unescape()
+//    Converts "src" which is encoded in Base64 to its binary equivalent and
+//    writes it to "dest". If src contains invalid characters, dest is cleared
+//    and the function returns false. Returns true on success.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest);
+
+// ----------------------------------------------------------------------
+// WebSafeBase64Unescape()
+//    This is a variation of Base64Unescape which uses '-' instead of '+', and
+//    '_' instead of '/'. src is not null terminated, instead specify len. I
+//    recommend that slen<szdest, but we honor szdest anyway.
+//    RETURNS the length of dest, or -1 if src contains invalid chars.
+
+//    The variation that stores into a string clears the string first, and
+//    returns false (with dest empty) if src contains invalid chars; for
+//    this version src and dest must be different strings.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen,
+                                             char* dest, int szdest);
+LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest);
+
+// Return the length to use for the output buffer given to the base64 escape
+// routines. Make sure to use the same value for do_padding in both.
+// This function may return incorrect results if given input_len values that
+// are extremely high, which should happen rarely.
+LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len,
+                                                 bool do_padding);
+// Use this version when calling Base64Escape without a do_padding arg.
+LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);
+
+// ----------------------------------------------------------------------
+// Base64Escape()
+// WebSafeBase64Escape()
+//    Encode "src" to "dest" using base64 encoding.
+//    src is not null terminated, instead specify len.
+//    'dest' should have at least CalculateBase64EscapedLen() length.
+//    RETURNS the length of dest.
+//    The WebSafe variation use '-' instead of '+' and '_' instead of '/'
+//    so that we can place the out in the URL or cookies without having
+//    to escape them.  It also has an extra parameter "do_padding",
+//    which when set to false will prevent padding with "=".
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen,
+                                    char* dest, int szdest);
+LIBPROTOBUF_EXPORT int WebSafeBase64Escape(
+    const unsigned char* src, int slen, char* dest,
+    int szdest, bool do_padding);
+// Encode src into dest with padding.
+LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest);
+// Encode src into dest web-safely without padding.
+LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest);
+// Encode src into dest web-safely with padding.
+LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
+                                                       string* dest);
+
+LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
+                                     string* dest, bool do_padding);
+LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
+                                            string* dest, bool do_padding);
+
+inline bool IsValidCodePoint(uint32 code_point) {
+  return code_point < 0xD800 ||
+         (code_point >= 0xE000 && code_point <= 0x10FFFF);
+}
+
+static const int UTFmax = 4;
+// ----------------------------------------------------------------------
+// EncodeAsUTF8Char()
+//  Helper to append a Unicode code point to a string as UTF8, without bringing
+//  in any external dependencies. The output buffer must be as least 4 bytes
+//  large.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output);
+
+// ----------------------------------------------------------------------
+// UTF8FirstLetterNumBytes()
+//   Length of the first UTF-8 character.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil_unittest.cc
new file mode 100644
index 0000000..5d62fc4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/strutil_unittest.cc
@@ -0,0 +1,810 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/strutil.h>
+
+#include <locale.h>
+
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// TODO(kenton):  Copy strutil tests from google3?
+
+TEST(StringUtilityTest, ImmuneToLocales) {
+  // Remember the old locale.
+  char* old_locale_cstr = setlocale(LC_NUMERIC, NULL);
+  ASSERT_TRUE(old_locale_cstr != NULL);
+  string old_locale = old_locale_cstr;
+
+  // Set the locale to "C".
+  ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL);
+
+  EXPECT_EQ("1.5", SimpleDtoa(1.5));
+  EXPECT_EQ("1.5", SimpleFtoa(1.5));
+
+  if (setlocale(LC_NUMERIC, "es_ES") == NULL &&
+      setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) {
+    // Some systems may not have the desired locale available.
+    GOOGLE_LOG(WARNING)
+      << "Couldn't set locale to es_ES.  Skipping this test.";
+  } else {
+    EXPECT_EQ("1.5", SimpleDtoa(1.5));
+    EXPECT_EQ("1.5", SimpleFtoa(1.5));
+  }
+
+  // Return to original locale.
+  setlocale(LC_NUMERIC, old_locale.c_str());
+}
+
+#define EXPECT_EQ_ARRAY(len, x, y, msg)                     \
+  for (int j = 0; j < len; ++j) {                           \
+    EXPECT_EQ(x[j], y[j]) << "" # x << " != " # y           \
+                          << " byte " << j << ": " << msg;  \
+  }
+
+static struct {
+  int plain_length;
+  const char* plaintext;
+  const char* cyphertext;
+} base64_tests[] = {
+  // Empty string.
+  { 0, "", ""},
+
+  // Basic bit patterns;
+  // values obtained with "echo -n '...' | uuencode -m test"
+
+  { 1, "\000", "AA==" },
+  { 1, "\001", "AQ==" },
+  { 1, "\002", "Ag==" },
+  { 1, "\004", "BA==" },
+  { 1, "\010", "CA==" },
+  { 1, "\020", "EA==" },
+  { 1, "\040", "IA==" },
+  { 1, "\100", "QA==" },
+  { 1, "\200", "gA==" },
+
+  { 1, "\377", "/w==" },
+  { 1, "\376", "/g==" },
+  { 1, "\375", "/Q==" },
+  { 1, "\373", "+w==" },
+  { 1, "\367", "9w==" },
+  { 1, "\357", "7w==" },
+  { 1, "\337", "3w==" },
+  { 1, "\277", "vw==" },
+  { 1, "\177", "fw==" },
+  { 2, "\000\000", "AAA=" },
+  { 2, "\000\001", "AAE=" },
+  { 2, "\000\002", "AAI=" },
+  { 2, "\000\004", "AAQ=" },
+  { 2, "\000\010", "AAg=" },
+  { 2, "\000\020", "ABA=" },
+  { 2, "\000\040", "ACA=" },
+  { 2, "\000\100", "AEA=" },
+  { 2, "\000\200", "AIA=" },
+  { 2, "\001\000", "AQA=" },
+  { 2, "\002\000", "AgA=" },
+  { 2, "\004\000", "BAA=" },
+  { 2, "\010\000", "CAA=" },
+  { 2, "\020\000", "EAA=" },
+  { 2, "\040\000", "IAA=" },
+  { 2, "\100\000", "QAA=" },
+  { 2, "\200\000", "gAA=" },
+
+  { 2, "\377\377", "//8=" },
+  { 2, "\377\376", "//4=" },
+  { 2, "\377\375", "//0=" },
+  { 2, "\377\373", "//s=" },
+  { 2, "\377\367", "//c=" },
+  { 2, "\377\357", "/+8=" },
+  { 2, "\377\337", "/98=" },
+  { 2, "\377\277", "/78=" },
+  { 2, "\377\177", "/38=" },
+  { 2, "\376\377", "/v8=" },
+  { 2, "\375\377", "/f8=" },
+  { 2, "\373\377", "+/8=" },
+  { 2, "\367\377", "9/8=" },
+  { 2, "\357\377", "7/8=" },
+  { 2, "\337\377", "3/8=" },
+  { 2, "\277\377", "v/8=" },
+  { 2, "\177\377", "f/8=" },
+
+  { 3, "\000\000\000", "AAAA" },
+  { 3, "\000\000\001", "AAAB" },
+  { 3, "\000\000\002", "AAAC" },
+  { 3, "\000\000\004", "AAAE" },
+  { 3, "\000\000\010", "AAAI" },
+  { 3, "\000\000\020", "AAAQ" },
+  { 3, "\000\000\040", "AAAg" },
+  { 3, "\000\000\100", "AABA" },
+  { 3, "\000\000\200", "AACA" },
+  { 3, "\000\001\000", "AAEA" },
+  { 3, "\000\002\000", "AAIA" },
+  { 3, "\000\004\000", "AAQA" },
+  { 3, "\000\010\000", "AAgA" },
+  { 3, "\000\020\000", "ABAA" },
+  { 3, "\000\040\000", "ACAA" },
+  { 3, "\000\100\000", "AEAA" },
+  { 3, "\000\200\000", "AIAA" },
+  { 3, "\001\000\000", "AQAA" },
+  { 3, "\002\000\000", "AgAA" },
+  { 3, "\004\000\000", "BAAA" },
+  { 3, "\010\000\000", "CAAA" },
+  { 3, "\020\000\000", "EAAA" },
+  { 3, "\040\000\000", "IAAA" },
+  { 3, "\100\000\000", "QAAA" },
+  { 3, "\200\000\000", "gAAA" },
+
+  { 3, "\377\377\377", "////" },
+  { 3, "\377\377\376", "///+" },
+  { 3, "\377\377\375", "///9" },
+  { 3, "\377\377\373", "///7" },
+  { 3, "\377\377\367", "///3" },
+  { 3, "\377\377\357", "///v" },
+  { 3, "\377\377\337", "///f" },
+  { 3, "\377\377\277", "//+/" },
+  { 3, "\377\377\177", "//9/" },
+  { 3, "\377\376\377", "//7/" },
+  { 3, "\377\375\377", "//3/" },
+  { 3, "\377\373\377", "//v/" },
+  { 3, "\377\367\377", "//f/" },
+  { 3, "\377\357\377", "/+//" },
+  { 3, "\377\337\377", "/9//" },
+  { 3, "\377\277\377", "/7//" },
+  { 3, "\377\177\377", "/3//" },
+  { 3, "\376\377\377", "/v//" },
+  { 3, "\375\377\377", "/f//" },
+  { 3, "\373\377\377", "+///" },
+  { 3, "\367\377\377", "9///" },
+  { 3, "\357\377\377", "7///" },
+  { 3, "\337\377\377", "3///" },
+  { 3, "\277\377\377", "v///" },
+  { 3, "\177\377\377", "f///" },
+
+  // Random numbers: values obtained with
+  //
+  //  #! /bin/bash
+  //  dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
+  //  od -N $1 -t o1 /tmp/bar.random
+  //  uuencode -m test < /tmp/bar.random
+  //
+  // where $1 is the number of bytes (2, 3)
+
+  { 2, "\243\361", "o/E=" },
+  { 2, "\024\167", "FHc=" },
+  { 2, "\313\252", "y6o=" },
+  { 2, "\046\041", "JiE=" },
+  { 2, "\145\236", "ZZ4=" },
+  { 2, "\254\325", "rNU=" },
+  { 2, "\061\330", "Mdg=" },
+  { 2, "\245\032", "pRo=" },
+  { 2, "\006\000", "BgA=" },
+  { 2, "\375\131", "/Vk=" },
+  { 2, "\303\210", "w4g=" },
+  { 2, "\040\037", "IB8=" },
+  { 2, "\261\372", "sfo=" },
+  { 2, "\335\014", "3Qw=" },
+  { 2, "\233\217", "m48=" },
+  { 2, "\373\056", "+y4=" },
+  { 2, "\247\232", "p5o=" },
+  { 2, "\107\053", "Rys=" },
+  { 2, "\204\077", "hD8=" },
+  { 2, "\276\211", "vok=" },
+  { 2, "\313\110", "y0g=" },
+  { 2, "\363\376", "8/4=" },
+  { 2, "\251\234", "qZw=" },
+  { 2, "\103\262", "Q7I=" },
+  { 2, "\142\312", "Yso=" },
+  { 2, "\067\211", "N4k=" },
+  { 2, "\220\001", "kAE=" },
+  { 2, "\152\240", "aqA=" },
+  { 2, "\367\061", "9zE=" },
+  { 2, "\133\255", "W60=" },
+  { 2, "\176\035", "fh0=" },
+  { 2, "\032\231", "Gpk=" },
+
+  { 3, "\013\007\144", "Cwdk" },
+  { 3, "\030\112\106", "GEpG" },
+  { 3, "\047\325\046", "J9Um" },
+  { 3, "\310\160\022", "yHAS" },
+  { 3, "\131\100\237", "WUCf" },
+  { 3, "\064\342\134", "NOJc" },
+  { 3, "\010\177\004", "CH8E" },
+  { 3, "\345\147\205", "5WeF" },
+  { 3, "\300\343\360", "wOPw" },
+  { 3, "\061\240\201", "MaCB" },
+  { 3, "\225\333\044", "ldsk" },
+  { 3, "\215\137\352", "jV/q" },
+  { 3, "\371\147\160", "+Wdw" },
+  { 3, "\030\320\051", "GNAp" },
+  { 3, "\044\174\241", "JHyh" },
+  { 3, "\260\127\037", "sFcf" },
+  { 3, "\111\045\033", "SSUb" },
+  { 3, "\202\114\107", "gkxH" },
+  { 3, "\057\371\042", "L/ki" },
+  { 3, "\223\247\244", "k6ek" },
+  { 3, "\047\216\144", "J45k" },
+  { 3, "\203\070\327", "gzjX" },
+  { 3, "\247\140\072", "p2A6" },
+  { 3, "\124\115\116", "VE1O" },
+  { 3, "\157\162\050", "b3Io" },
+  { 3, "\357\223\004", "75ME" },
+  { 3, "\052\117\156", "Kk9u" },
+  { 3, "\347\154\000", "52wA" },
+  { 3, "\303\012\142", "wwpi" },
+  { 3, "\060\035\362", "MB3y" },
+  { 3, "\130\226\361", "WJbx" },
+  { 3, "\173\013\071", "ews5" },
+  { 3, "\336\004\027", "3gQX" },
+  { 3, "\357\366\234", "7/ac" },
+  { 3, "\353\304\111", "68RJ" },
+  { 3, "\024\264\131", "FLRZ" },
+  { 3, "\075\114\251", "PUyp" },
+  { 3, "\315\031\225", "zRmV" },
+  { 3, "\154\201\276", "bIG+" },
+  { 3, "\200\066\072", "gDY6" },
+  { 3, "\142\350\267", "Yui3" },
+  { 3, "\033\000\166", "GwB2" },
+  { 3, "\210\055\077", "iC0/" },
+  { 3, "\341\037\124", "4R9U" },
+  { 3, "\161\103\152", "cUNq" },
+  { 3, "\270\142\131", "uGJZ" },
+  { 3, "\337\076\074", "3z48" },
+  { 3, "\375\106\362", "/Uby" },
+  { 3, "\227\301\127", "l8FX" },
+  { 3, "\340\002\234", "4AKc" },
+  { 3, "\121\064\033", "UTQb" },
+  { 3, "\157\134\143", "b1xj" },
+  { 3, "\247\055\327", "py3X" },
+  { 3, "\340\142\005", "4GIF" },
+  { 3, "\060\260\143", "MLBj" },
+  { 3, "\075\203\170", "PYN4" },
+  { 3, "\143\160\016", "Y3AO" },
+  { 3, "\313\013\063", "ywsz" },
+  { 3, "\174\236\135", "fJ5d" },
+  { 3, "\103\047\026", "QycW" },
+  { 3, "\365\005\343", "9QXj" },
+  { 3, "\271\160\223", "uXCT" },
+  { 3, "\362\255\172", "8q16" },
+  { 3, "\113\012\015", "SwoN" },
+
+  // various lengths, generated by this python script:
+  //
+  // from string import lowercase as lc
+  // for i in range(27):
+  //   print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
+  //                                     lc[:i].encode('base64').strip())
+
+  {  0, "",                           "" },
+  {  1, "a",                          "YQ==" },
+  {  2, "ab",                         "YWI=" },
+  {  3, "abc",                        "YWJj" },
+  {  4, "abcd",                       "YWJjZA==" },
+  {  5, "abcde",                      "YWJjZGU=" },
+  {  6, "abcdef",                     "YWJjZGVm" },
+  {  7, "abcdefg",                    "YWJjZGVmZw==" },
+  {  8, "abcdefgh",                   "YWJjZGVmZ2g=" },
+  {  9, "abcdefghi",                  "YWJjZGVmZ2hp" },
+  { 10, "abcdefghij",                 "YWJjZGVmZ2hpag==" },
+  { 11, "abcdefghijk",                "YWJjZGVmZ2hpams=" },
+  { 12, "abcdefghijkl",               "YWJjZGVmZ2hpamts" },
+  { 13, "abcdefghijklm",              "YWJjZGVmZ2hpamtsbQ==" },
+  { 14, "abcdefghijklmn",             "YWJjZGVmZ2hpamtsbW4=" },
+  { 15, "abcdefghijklmno",            "YWJjZGVmZ2hpamtsbW5v" },
+  { 16, "abcdefghijklmnop",           "YWJjZGVmZ2hpamtsbW5vcA==" },
+  { 17, "abcdefghijklmnopq",          "YWJjZGVmZ2hpamtsbW5vcHE=" },
+  { 18, "abcdefghijklmnopqr",         "YWJjZGVmZ2hpamtsbW5vcHFy" },
+  { 19, "abcdefghijklmnopqrs",        "YWJjZGVmZ2hpamtsbW5vcHFycw==" },
+  { 20, "abcdefghijklmnopqrst",       "YWJjZGVmZ2hpamtsbW5vcHFyc3Q=" },
+  { 21, "abcdefghijklmnopqrstu",      "YWJjZGVmZ2hpamtsbW5vcHFyc3R1" },
+  { 22, "abcdefghijklmnopqrstuv",     "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==" },
+  { 23, "abcdefghijklmnopqrstuvw",    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=" },
+  { 24, "abcdefghijklmnopqrstuvwx",   "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" },
+  { 25, "abcdefghijklmnopqrstuvwxy",  "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==" },
+  { 26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" },
+};
+
+static struct {
+  const char* plaintext;
+  const char* cyphertext;
+} base64_strings[] = {
+  // Some google quotes
+  // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+  // (Note that we're testing the websafe encoding, though, so if
+  // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+  { "I was always good at math and science, and I never realized "
+    "that was unusual or somehow undesirable. So one of the things "
+    "I care a lot about is helping to remove that stigma, "
+    "to show girls that you can be feminine, you can like the things "
+    "that girls like, but you can also be really good at technology. "
+    "You can be really good at building things."
+    " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+    "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+    "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+    "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+    "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+    "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+    "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+    "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+    "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+    "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+  { "Typical first year for a new cluster: "
+    "~0.5 overheating "
+    "~1 PDU failure "
+    "~1 rack-move "
+    "~1 network rewiring "
+    "~20 rack failures "
+    "~5 racks go wonky "
+    "~8 network maintenances "
+    "~12 router reloads "
+    "~3 router failures "
+    "~dozens of minor 30-second blips for dns "
+    "~1000 individual machine failures "
+    "~thousands of hard drive failures "
+    "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+    " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+    "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+    "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+    "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+    "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+    "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+    "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+    "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+    "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+    "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+    "ZWFsIEhhcmR3YXJlCg" },
+
+  { "I'm the head of the webspam team at Google.  "
+    "That means that if you type your name into Google and get porn back, "
+    "it's my fault. Unless you're a porn star, in which case porn is a "
+    "completely reasonable response."
+    " - Matt Cutts, Google Plus" "\n",
+
+    "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+    "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+    "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+    "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+    "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+    "IEdvb2dsZSBQbHVzCg" },
+
+  { "It will still be a long time before machines approach human intelligence. "
+    "But luckily, machines don't actually have to be intelligent; "
+    "they just have to fake it. Access to a wealth of information, "
+    "combined with a rudimentary decision-making capacity, "
+    "can often be almost as useful. Of course, the results are better yet "
+    "when coupled with intelligence. A reference librarian with access to "
+    "a good search engine is a formidable tool."
+    " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n",
+
+    "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+    "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+    "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+    "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+    "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+    "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+    "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+    "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+    "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+    "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+    "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+    "NAo" },
+
+  // Degenerate edge case
+  { "",
+    "" },
+};
+
+TEST(Base64, EscapeAndUnescape) {
+  // Check the short strings; this tests the math (and boundaries)
+  for (int i = 0; i < sizeof(base64_tests) / sizeof(base64_tests[0]); ++i) {
+    char encode_buffer[100];
+    int encode_length;
+    char decode_buffer[100];
+    int decode_length;
+    int cypher_length;
+    string decode_str;
+
+    const unsigned char* unsigned_plaintext =
+      reinterpret_cast<const unsigned char*>(base64_tests[i].plaintext);
+
+    StringPiece plaintext(base64_tests[i].plaintext,
+                          base64_tests[i].plain_length);
+
+    cypher_length = strlen(base64_tests[i].cyphertext);
+
+    // The basic escape function:
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = Base64Escape(unsigned_plaintext,
+                                 base64_tests[i].plain_length,
+                                 encode_buffer,
+                                 sizeof(encode_buffer));
+    //    Is it of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+    // Would it have been okay to allocate only CalculateBase64EscapeLen()?
+    EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length),
+              encode_length);
+
+    //    Is it the expected encoded value?
+    ASSERT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+
+    // If we encode it into a buffer of exactly the right length...
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = Base64Escape(unsigned_plaintext,
+                                          base64_tests[i].plain_length,
+                                          encode_buffer,
+                                          cypher_length);
+    //    Is it still of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+
+    //    And is the value still correct?  (i.e., not losing the last byte)
+    EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+
+    // If we decode it back:
+    decode_str.clear();
+    EXPECT_TRUE(Base64Unescape(
+        StringPiece(encode_buffer, cypher_length), &decode_str));
+
+    //    Is it of the expected length?
+    EXPECT_EQ(base64_tests[i].plain_length, decode_str.length());
+
+    //    Is it the expected decoded value?
+    EXPECT_EQ(plaintext, decode_str);
+
+    // Let's try with a pre-populated string.
+    string encoded("this junk should be ignored");
+    Base64Escape(string(base64_tests[i].plaintext,
+                        base64_tests[i].plain_length),
+                 &encoded);
+    EXPECT_EQ(encoded, string(encode_buffer, cypher_length));
+
+    string decoded("this junk should be ignored");
+    EXPECT_TRUE(Base64Unescape(
+        StringPiece(encode_buffer, cypher_length), &decoded));
+    EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+    EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+    // Our decoder treats the padding '=' characters at the end as
+    // optional (but if there are any, there must be the correct
+    // number of them.)  If encode_buffer has any, run some additional
+    // tests that fiddle with them.
+    char* first_equals = strchr(encode_buffer, '=');
+    if (first_equals) {
+      // How many equals signs does the string start with?
+      int equals = (*(first_equals+1) == '=') ? 2 : 1;
+
+      // Try chopping off the equals sign(s) entirely.  The decoder
+      // should still be okay with this.
+      string decoded2("this junk should also be ignored");
+      *first_equals = '\0';
+      EXPECT_TRUE(Base64Unescape(
+          StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2));
+      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+      // Now test chopping off the equals sign(s) and adding
+      // whitespace.  Our decoder should still accept this.
+      decoded2.assign("this junk should be ignored");
+      *first_equals = ' ';
+      *(first_equals+1) = '\0';
+      EXPECT_TRUE(Base64Unescape(
+          StringPiece(encode_buffer, first_equals - encode_buffer + 1),
+          &decoded2));
+      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+      // Now stick a bad character at the end of the string.  The decoder
+      // should refuse this string.
+      decoded2.assign("this junk should be ignored");
+      *first_equals = '?';
+      *(first_equals+1) = '\0';
+      EXPECT_TRUE(
+          !Base64Unescape(
+              StringPiece(encode_buffer, first_equals - encode_buffer + 1),
+              &decoded2));
+
+      int len;
+
+      // Test whitespace mixed with the padding.  (eg "AA = = ")  The
+      // decoder should accept this.
+      if (equals == 2) {
+        snprintf(first_equals, 6, " = = ");
+        len = first_equals - encode_buffer + 5;
+      } else {
+        snprintf(first_equals, 6, " = ");
+        len = first_equals - encode_buffer + 3;
+      }
+      decoded2.assign("this junk should be ignored");
+      EXPECT_TRUE(
+          Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
+      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+      // Test whitespace mixed with the padding, but with the wrong
+      // number of equals signs (eg "AA = ").  The decoder should
+      // refuse these strings.
+      if (equals == 1) {
+        snprintf(first_equals, 6, " = = ");
+        len = first_equals - encode_buffer + 5;
+      } else {
+        snprintf(first_equals, 6, " = ");
+        len = first_equals - encode_buffer + 3;
+      }
+      EXPECT_TRUE(
+          !Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
+    }
+
+    // Cool! the basic Base64 encoder/decoder works.
+    // Let's try the alternate alphabet: tr -- '+/' '-_'
+
+    char websafe[100];
+    memset(websafe, 0, sizeof(websafe));
+    strncpy(websafe, base64_tests[i].cyphertext, cypher_length);
+    for (int c = 0; c < sizeof(websafe); ++c) {
+      if ('+' == websafe[c]) { websafe[c] = '-'; }
+      if ('/' == websafe[c]) { websafe[c] = '_'; }
+    }
+
+    // The websafe escape function:
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = WebSafeBase64Escape(unsigned_plaintext,
+                                                 base64_tests[i].plain_length,
+                                                 encode_buffer,
+                                                 sizeof(encode_buffer),
+                                                 true);
+    //    Is it of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(
+        CalculateBase64EscapedLen(base64_tests[i].plain_length, true),
+        encode_length);
+
+    //    Is it the expected encoded value?
+    EXPECT_STREQ(encode_buffer, websafe);
+
+    //    If we encode it into a buffer of exactly the right length...
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = WebSafeBase64Escape(unsigned_plaintext,
+                                                 base64_tests[i].plain_length,
+                                                 encode_buffer,
+                                                 cypher_length,
+                                                 true);
+    //    Is it still of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+
+    //    And is the value still correct?  (i.e., not losing the last byte)
+    EXPECT_STREQ(encode_buffer, websafe);
+
+    //    Let's try the string version of the encoder
+    encoded = "this junk should be ignored";
+    WebSafeBase64Escape(
+        unsigned_plaintext, base64_tests[i].plain_length,
+        &encoded, true);
+    EXPECT_EQ(encoded.size(), cypher_length);
+    EXPECT_STREQ(encoded.c_str(), websafe);
+
+    //    If we decode it back:
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   sizeof(decode_buffer));
+
+    //    Is it of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    //    Is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+    //    If we decode it into a buffer of exactly the right length...
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   decode_length);
+
+    //    Is it still of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    //    And is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+    // Try using '.' for the pad character.
+    for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) {
+      encode_buffer[c] = '.';
+    }
+
+    // If we decode it back:
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   sizeof(decode_buffer));
+
+    // Is it of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    // Is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+    // If we decode it into a buffer of exactly the right length...
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   decode_length);
+
+    // Is it still of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    // And is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+    // Let's try the string version of the decoder
+    decoded = "this junk should be ignored";
+    EXPECT_TRUE(WebSafeBase64Unescape(
+        StringPiece(encode_buffer, cypher_length), &decoded));
+    EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+    EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+    // Okay! the websafe Base64 encoder/decoder works.
+    // Let's try the unpadded version
+
+    for (int c = 0; c < sizeof(websafe); ++c) {
+      if ('=' == websafe[c]) {
+        websafe[c] = '\0';
+        cypher_length = c;
+        break;
+      }
+    }
+
+    // The websafe escape function:
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = WebSafeBase64Escape(unsigned_plaintext,
+                                                 base64_tests[i].plain_length,
+                                                 encode_buffer,
+                                                 sizeof(encode_buffer),
+                                                 false);
+    //    Is it of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(
+        CalculateBase64EscapedLen(base64_tests[i].plain_length, false),
+        encode_length);
+
+    //    Is it the expected encoded value?
+    EXPECT_STREQ(encode_buffer, websafe);
+
+    //    If we encode it into a buffer of exactly the right length...
+    memset(encode_buffer, 0, sizeof(encode_buffer));
+    encode_length = WebSafeBase64Escape(unsigned_plaintext,
+                                                 base64_tests[i].plain_length,
+                                                 encode_buffer,
+                                                 cypher_length,
+                                                 false);
+    //    Is it still of the expected length?
+    EXPECT_EQ(encode_length, cypher_length);
+
+    //    And is the value still correct?  (i.e., not losing the last byte)
+    EXPECT_STREQ(encode_buffer, websafe);
+
+    // Let's try the (other) string version of the encoder
+    string plain(base64_tests[i].plaintext, base64_tests[i].plain_length);
+    encoded = "this junk should be ignored";
+    WebSafeBase64Escape(plain, &encoded);
+    EXPECT_EQ(encoded.size(), cypher_length);
+    EXPECT_STREQ(encoded.c_str(), websafe);
+
+    //    If we decode it back:
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   sizeof(decode_buffer));
+
+    //    Is it of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    //    Is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+    //    If we decode it into a buffer of exactly the right length...
+    memset(decode_buffer, 0, sizeof(decode_buffer));
+    decode_length = WebSafeBase64Unescape(encode_buffer,
+                                                   cypher_length,
+                                                   decode_buffer,
+                                                   decode_length);
+
+    //    Is it still of the expected length?
+    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+    //    And is it the expected decoded value?
+    EXPECT_EQ(0,
+              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+
+    // Let's try the string version of the decoder
+    decoded = "this junk should be ignored";
+    EXPECT_TRUE(WebSafeBase64Unescape(
+        StringPiece(encode_buffer, cypher_length), &decoded));
+    EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+    EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+    // This value works.  Try the next.
+  }
+
+  // Now try the long strings, this tests the streaming
+  for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]);
+       ++i) {
+    const unsigned char* unsigned_plaintext =
+      reinterpret_cast<const unsigned char*>(base64_strings[i].plaintext);
+    int plain_length = strlen(base64_strings[i].plaintext);
+    int cypher_length = strlen(base64_strings[i].cyphertext);
+    vector<char> buffer(cypher_length+1);
+    int encode_length = WebSafeBase64Escape(unsigned_plaintext,
+                                                     plain_length,
+                                                     &buffer[0],
+                                                     buffer.size(),
+                                                     false);
+    EXPECT_EQ(cypher_length, encode_length);
+    EXPECT_EQ(
+        CalculateBase64EscapedLen(plain_length, false), encode_length);
+    buffer[ encode_length ] = '\0';
+    EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]);
+  }
+
+  // Verify the behavior when decoding bad data
+  {
+    const char* bad_data = "ab-/";
+    string buf;
+    EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf));
+    EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf));
+    EXPECT_TRUE(buf.empty());
+  }
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.cc
new file mode 100644
index 0000000..c9d9589
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.cc
@@ -0,0 +1,134 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+using internal::SubstituteArg;
+
+// Returns the number of args in arg_array which were passed explicitly
+// to Substitute().
+static int CountSubstituteArgs(const SubstituteArg* const* args_array) {
+  int count = 0;
+  while (args_array[count] != NULL && args_array[count]->size() != -1) {
+    ++count;
+  }
+  return count;
+}
+
+string Substitute(
+    const char* format,
+    const SubstituteArg& arg0, const SubstituteArg& arg1,
+    const SubstituteArg& arg2, const SubstituteArg& arg3,
+    const SubstituteArg& arg4, const SubstituteArg& arg5,
+    const SubstituteArg& arg6, const SubstituteArg& arg7,
+    const SubstituteArg& arg8, const SubstituteArg& arg9) {
+  string result;
+  SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4,
+                                       arg5, arg6, arg7, arg8, arg9);
+  return result;
+}
+
+void SubstituteAndAppend(
+    string* output, const char* format,
+    const SubstituteArg& arg0, const SubstituteArg& arg1,
+    const SubstituteArg& arg2, const SubstituteArg& arg3,
+    const SubstituteArg& arg4, const SubstituteArg& arg5,
+    const SubstituteArg& arg6, const SubstituteArg& arg7,
+    const SubstituteArg& arg8, const SubstituteArg& arg9) {
+  const SubstituteArg* const args_array[] = {
+    &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL
+  };
+
+  // Determine total size needed.
+  int size = 0;
+  for (int i = 0; format[i] != '\0'; i++) {
+    if (format[i] == '$') {
+      if (ascii_isdigit(format[i+1])) {
+        int index = format[i+1] - '0';
+        if (args_array[index]->size() == -1) {
+          GOOGLE_LOG(DFATAL)
+            << "strings::Substitute format string invalid: asked for \"$"
+            << index << "\", but only " << CountSubstituteArgs(args_array)
+            << " args were given.  Full format string was: \""
+            << CEscape(format) << "\".";
+          return;
+        }
+        size += args_array[index]->size();
+        ++i;  // Skip next char.
+      } else if (format[i+1] == '$') {
+        ++size;
+        ++i;  // Skip next char.
+      } else {
+        GOOGLE_LOG(DFATAL)
+          << "Invalid strings::Substitute() format string: \""
+          << CEscape(format) << "\".";
+        return;
+      }
+    } else {
+      ++size;
+    }
+  }
+
+  if (size == 0) return;
+
+  // Build the string.
+  int original_size = output->size();
+  STLStringResizeUninitialized(output, original_size + size);
+  char* target = string_as_array(output) + original_size;
+  for (int i = 0; format[i] != '\0'; i++) {
+    if (format[i] == '$') {
+      if (ascii_isdigit(format[i+1])) {
+        const SubstituteArg* src = args_array[format[i+1] - '0'];
+        memcpy(target, src->data(), src->size());
+        target += src->size();
+        ++i;  // Skip next char.
+      } else if (format[i+1] == '$') {
+        *target++ = '$';
+        ++i;  // Skip next char.
+      }
+    } else {
+      *target++ = format[i];
+    }
+  }
+
+  GOOGLE_DCHECK_EQ(target - output->data(), output->size());
+}
+
+}  // namespace strings
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.h
new file mode 100644
index 0000000..7ee442a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/substitute.h
@@ -0,0 +1,170 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// from google3/strings/substitute.h
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
+#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+// ----------------------------------------------------------------------
+// strings::Substitute()
+// strings::SubstituteAndAppend()
+//   Kind of like StringPrintf, but different.
+//
+//   Example:
+//     string GetMessage(string first_name, string last_name, int age) {
+//       return strings::Substitute("My name is $0 $1 and I am $2 years old.",
+//                                  first_name, last_name, age);
+//     }
+//
+//   Differences from StringPrintf:
+//   * The format string does not identify the types of arguments.
+//     Instead, the magic of C++ deals with this for us.  See below
+//     for a list of accepted types.
+//   * Substitutions in the format string are identified by a '$'
+//     followed by a digit.  So, you can use arguments out-of-order and
+//     use the same argument multiple times.
+//   * It's much faster than StringPrintf.
+//
+//   Supported types:
+//   * Strings (const char*, const string&)
+//     * Note that this means you do not have to add .c_str() to all of
+//       your strings.  In fact, you shouldn't; it will be slower.
+//   * int32, int64, uint32, uint64:  Formatted using SimpleItoa().
+//   * float, double:  Formatted using SimpleFtoa() and SimpleDtoa().
+//   * bool:  Printed as "true" or "false".
+//
+//   SubstituteAndAppend() is like Substitute() but appends the result to
+//   *output.  Example:
+//
+//     string str;
+//     strings::SubstituteAndAppend(&str,
+//                                  "My name is $0 $1 and I am $2 years old.",
+//                                  first_name, last_name, age);
+//
+//   Substitute() is significantly faster than StringPrintf().  For very
+//   large strings, it may be orders of magnitude faster.
+// ----------------------------------------------------------------------
+
+namespace internal {  // Implementation details.
+
+class SubstituteArg {
+ public:
+  inline SubstituteArg(const char* value)
+    : text_(value), size_(strlen(text_)) {}
+  inline SubstituteArg(const string& value)
+    : text_(value.data()), size_(value.size()) {}
+
+  // Indicates that no argument was given.
+  inline explicit SubstituteArg()
+    : text_(NULL), size_(-1) {}
+
+  // Primitives
+  // We don't overload for signed and unsigned char because if people are
+  // explicitly declaring their chars as signed or unsigned then they are
+  // probably actually using them as 8-bit integers and would probably
+  // prefer an integer representation.  But, we don't really know.  So, we
+  // make the caller decide what to do.
+  inline SubstituteArg(char value)
+    : text_(scratch_), size_(1) { scratch_[0] = value; }
+  inline SubstituteArg(short value)
+    : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(unsigned short value)
+    : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(int value)
+    : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(unsigned int value)
+    : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(long value)
+    : text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(unsigned long value)
+    : text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(long long value)
+    : text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(unsigned long long value)
+    : text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(float value)
+    : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(double value)
+    : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
+  inline SubstituteArg(bool value)
+    : text_(value ? "true" : "false"), size_(strlen(text_)) {}
+
+  inline const char* data() const { return text_; }
+  inline int size() const { return size_; }
+
+ private:
+  const char* text_;
+  int size_;
+  char scratch_[kFastToBufferSize];
+};
+
+}  // namespace internal
+
+LIBPROTOBUF_EXPORT string Substitute(
+  const char* format,
+  const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg9 = internal::SubstituteArg());
+
+LIBPROTOBUF_EXPORT void SubstituteAndAppend(
+  string* output, const char* format,
+  const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
+  const internal::SubstituteArg& arg9 = internal::SubstituteArg());
+
+}  // namespace strings
+}  // namespace protobuf
+}  // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util.h
new file mode 100644
index 0000000..feef904
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util.h
@@ -0,0 +1,138 @@
+// Copyright 2005 Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// Template metaprogramming utility functions.
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems.  Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+//
+// The names chosen here reflect those used in tr1 and the boost::mpl
+// library, there are similar operations used in the Loki library as
+// well.  I prefer the boost names for 2 reasons:
+// 1.  I think that portions of the Boost libraries are more likely to
+// be included in the c++ standard.
+// 2.  It is not impossible that some of the boost libraries will be
+// included in our own build in the future.
+// Both of these outcomes means that we may be able to directly replace
+// some of these with boost equivalents.
+//
+#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Types small_ and big_ are guaranteed such that sizeof(small_) <
+// sizeof(big_)
+typedef char small_;
+
+struct big_ {
+  char dummy[2];
+};
+
+// Identity metafunction.
+template <class T>
+struct identity_ {
+  typedef T type;
+};
+
+// integral_constant, defined in tr1, is a wrapper for an integer
+// value. We don't really need this generality; we could get away
+// with hardcoding the integer type to bool. We use the fully
+// general integer_constant for compatibility with tr1.
+
+template<class T, T v>
+struct integral_constant {
+  static const T value = v;
+  typedef T value_type;
+  typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+
+// Abbreviations: true_type and false_type are structs that represent boolean
+// true and false values. Also define the boost::mpl versions of those names,
+// true_ and false_.
+typedef integral_constant<bool, true>  true_type;
+typedef integral_constant<bool, false> false_type;
+typedef true_type  true_;
+typedef false_type false_;
+
+// if_ is a templatized conditional statement.
+// if_<cond, A, B> is a compile time evaluation of cond.
+// if_<>::type contains A if cond is true, B otherwise.
+template<bool cond, typename A, typename B>
+struct if_{
+  typedef A type;
+};
+
+template<typename A, typename B>
+struct if_<false, A, B> {
+  typedef B type;
+};
+
+
+// type_equals_ is a template type comparator, similar to Loki IsSameType.
+// type_equals_<A, B>::value is true iff "A" is the same type as "B".
+//
+// New code should prefer base::is_same, defined in base/type_traits.h.
+// It is functionally identical, but is_same is the standard spelling.
+template<typename A, typename B>
+struct type_equals_ : public false_ {
+};
+
+template<typename A>
+struct type_equals_<A, A> : public true_ {
+};
+
+// and_ is a template && operator.
+// and_<A, B>::value evaluates "A::value && B::value".
+template<typename A, typename B>
+struct and_ : public integral_constant<bool, (A::value && B::value)> {
+};
+
+// or_ is a template || operator.
+// or_<A, B>::value evaluates "A::value || B::value".
+template<typename A, typename B>
+struct or_ : public integral_constant<bool, (A::value || B::value)> {
+};
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util_unittest.cc
new file mode 100644
index 0000000..b1745e2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/template_util_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2005 Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// These tests are really compile time tests.
+// If you try to step through this in a debugger
+// you will not see any evaluations, merely that
+// value is assigned true or false sequentially.
+
+#include <google/protobuf/stubs/template_util.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace GOOGLE_NAMESPACE = google::protobuf::internal;
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(TemplateUtilTest, TestSize) {
+  EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_));
+}
+
+TEST(TemplateUtilTest, TestIntegralConstants) {
+  // test the built-in types.
+  EXPECT_TRUE(true_type::value);
+  EXPECT_FALSE(false_type::value);
+
+  typedef integral_constant<int, 1> one_type;
+  EXPECT_EQ(1, one_type::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateIf) {
+  typedef if_<true, true_type, false_type>::type if_true;
+  EXPECT_TRUE(if_true::value);
+
+  typedef if_<false, true_type, false_type>::type if_false;
+  EXPECT_FALSE(if_false::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateTypeEquals) {
+  // Check that the TemplateTypeEquals works correctly.
+  bool value = false;
+
+  // Test the same type is true.
+  value = type_equals_<int, int>::value;
+  EXPECT_TRUE(value);
+
+  // Test different types are false.
+  value = type_equals_<float, int>::value;
+  EXPECT_FALSE(value);
+
+  // Test type aliasing.
+  typedef const int foo;
+  value = type_equals_<const foo, const int>::value;
+  EXPECT_TRUE(value);
+}
+
+TEST(TemplateUtilTest, TestTemplateAndOr) {
+  // Check that the TemplateTypeEquals works correctly.
+  bool value = false;
+
+  // Yes && Yes == true.
+  value = and_<true_, true_>::value;
+  EXPECT_TRUE(value);
+  // Yes && No == false.
+  value = and_<true_, false_>::value;
+  EXPECT_FALSE(value);
+  // No && Yes == false.
+  value = and_<false_, true_>::value;
+  EXPECT_FALSE(value);
+  // No && No == false.
+  value = and_<false_, false_>::value;
+  EXPECT_FALSE(value);
+
+  // Yes || Yes == true.
+  value = or_<true_, true_>::value;
+  EXPECT_TRUE(value);
+  // Yes || No == true.
+  value = or_<true_, false_>::value;
+  EXPECT_TRUE(value);
+  // No || Yes == true.
+  value = or_<false_, true_>::value;
+  EXPECT_TRUE(value);
+  // No || No == false.
+  value = or_<false_, false_>::value;
+  EXPECT_FALSE(value);
+}
+
+TEST(TemplateUtilTest, TestIdentity) {
+  EXPECT_TRUE(
+      (type_equals_<GOOGLE_NAMESPACE::identity_<int>::type, int>::value));
+  EXPECT_TRUE(
+      (type_equals_<GOOGLE_NAMESPACE::identity_<void>::type, void>::value));
+}
+
+}  // anonymous namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/time.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/time.cc
new file mode 100644
index 0000000..49c0412
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/time.cc
@@ -0,0 +1,365 @@
+#include <google/protobuf/stubs/time.h>
+
+#include <ctime>
+
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+static const int64 kSecondsPerMinute = 60;
+static const int64 kSecondsPerHour = 3600;
+static const int64 kSecondsPerDay = kSecondsPerHour * 24;
+static const int64 kSecondsPer400Years =
+    kSecondsPerDay * (400 * 365 + 400 / 4 - 3);
+// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00
+static const int64 kSecondsFromEraToEpoch = 62135596800LL;
+// The range of timestamp values we support.
+static const int64 kMinTime = -62135596800LL;  // 0001-01-01T00:00:00
+static const int64 kMaxTime = 253402300799LL;  // 9999-12-31T23:59:59
+
+static const int kNanosPerMillisecond = 1000000;
+static const int kNanosPerMicrosecond = 1000;
+
+// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years
+// after.
+int64 SecondsPer100Years(int year) {
+  if (year % 400 == 0 || year % 400 > 300) {
+    return kSecondsPerDay * (100 * 365 + 100 / 4);
+  } else {
+    return kSecondsPerDay * (100 * 365 + 100 / 4 - 1);
+  }
+}
+
+// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years
+// after.
+int64 SecondsPer4Years(int year) {
+  if ((year % 100 == 0 || year % 100 > 96) &&
+      !(year % 400 == 0 || year % 400 > 396)) {
+    // No leap years.
+    return kSecondsPerDay * (4 * 365);
+  } else {
+    // One leap years.
+    return kSecondsPerDay * (4 * 365 + 1);
+  }
+}
+
+bool IsLeapYear(int year) {
+  return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
+}
+
+int64 SecondsPerYear(int year) {
+  return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365);
+}
+
+static const int kDaysInMonth[13] = {
+  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+int64 SecondsPerMonth(int month, bool leap) {
+  if (month == 2 && leap) {
+    return kSecondsPerDay * (kDaysInMonth[month] + 1);
+  }
+  return kSecondsPerDay * kDaysInMonth[month];
+}
+
+static const int kDaysSinceJan[13] = {
+  0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+};
+
+bool ValidateDateTime(const DateTime& time) {
+  if (time.year < 1 || time.year > 9999 ||
+      time.month < 1 || time.month > 12 ||
+      time.day < 1 || time.day > 31 ||
+      time.hour < 0 || time.hour > 23 ||
+      time.minute < 0 || time.minute > 59 ||
+      time.second < 0 || time.second > 59) {
+    return false;
+  }
+  if (time.month == 2 && IsLeapYear(time.year)) {
+    return time.month <= kDaysInMonth[time.month] + 1;
+  } else {
+    return time.month <= kDaysInMonth[time.month];
+  }
+}
+
+// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given
+// time.
+int64 SecondsSinceCommonEra(const DateTime& time) {
+  int64 result = 0;
+  // Years should be between 1 and 9999.
+  assert(time.year >= 1 && time.year <= 9999);
+  int year = 1;
+  if ((time.year - year) >= 400) {
+    int count_400years = (time.year - year) / 400;
+    result += kSecondsPer400Years * count_400years;
+    year += count_400years * 400;
+  }
+  while ((time.year - year) >= 100) {
+    result += SecondsPer100Years(year);
+    year += 100;
+  }
+  while ((time.year - year) >= 4) {
+    result += SecondsPer4Years(year);
+    year += 4;
+  }
+  while (time.year > year) {
+    result += SecondsPerYear(year);
+    ++year;
+  }
+  // Months should be between 1 and 12.
+  assert(time.month >= 1 && time.month <= 12);
+  int month = time.month;
+  result += kSecondsPerDay * kDaysSinceJan[month];
+  if (month > 2 && IsLeapYear(year)) {
+    result += kSecondsPerDay;
+  }
+  assert(time.day >= 1 &&
+         time.day <= (month == 2 && IsLeapYear(year)
+                          ? kDaysInMonth[month] + 1
+                          : kDaysInMonth[month]));
+  result += kSecondsPerDay * (time.day - 1);
+  result += kSecondsPerHour * time.hour +
+      kSecondsPerMinute * time.minute +
+      time.second;
+  return result;
+}
+
+// Format nanoseconds with either 3, 6, or 9 digits depending on the required
+// precision to represent the exact value.
+string FormatNanos(int32 nanos) {
+  if (nanos % kNanosPerMillisecond == 0) {
+    return StringPrintf("%03d", nanos / kNanosPerMillisecond);
+  } else if (nanos % kNanosPerMicrosecond == 0) {
+    return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
+  } else {
+    return StringPrintf("%09d", nanos);
+  }
+}
+
+// Parses an integer from a null-terminated char sequence. The method
+// consumes at most "width" chars. Returns a pointer after the consumed
+// integer, or NULL if the data does not start with an integer or the
+// integer value does not fall in the range of [min_value, max_value].
+const char* ParseInt(const char* data, int width, int min_value,
+                     int max_value, int* result) {
+  if (!ascii_isdigit(*data)) {
+    return NULL;
+  }
+  int value = 0;
+  for (int i = 0; i < width; ++i, ++data) {
+    if (ascii_isdigit(*data)) {
+      value = value * 10 + (*data - '0');
+    } else {
+      break;
+    }
+  }
+  if (value >= min_value && value <= max_value) {
+    *result = value;
+    return data;
+  } else {
+    return NULL;
+  }
+}
+
+// Consumes the fractional parts of a second into nanos. For example,
+// "010" will be parsed to 10000000 nanos.
+const char* ParseNanos(const char* data, int32* nanos) {
+  if (!ascii_isdigit(*data)) {
+    return NULL;
+  }
+  int value = 0;
+  int len = 0;
+  // Consume as many digits as there are but only take the first 9 into
+  // account.
+  while (ascii_isdigit(*data)) {
+    if (len < 9) {
+      value = value * 10 + *data - '0';
+    }
+    ++len;
+    ++data;
+  }
+  while (len < 9) {
+    value = value * 10;
+    ++len;
+  }
+  *nanos = value;
+  return data;
+}
+
+const char* ParseTimezoneOffset(const char* data, int64* offset) {
+  // Accept format "HH:MM". E.g., "08:00"
+  int hour;
+  if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) {
+    return NULL;
+  }
+  if (*data++ != ':') {
+    return NULL;
+  }
+  int minute;
+  if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) {
+    return NULL;
+  }
+  *offset = (hour * 60 + minute) * 60;
+  return data;
+}
+}  // namespace
+
+bool SecondsToDateTime(int64 seconds, DateTime* time) {
+  if (seconds < kMinTime || seconds > kMaxTime) {
+    return false;
+  }
+  // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00
+  seconds = seconds + kSecondsFromEraToEpoch;
+  int year = 1;
+  if (seconds >= kSecondsPer400Years) {
+    int count_400years = seconds / kSecondsPer400Years;
+    year += 400 * count_400years;
+    seconds %= kSecondsPer400Years;
+  }
+  while (seconds >= SecondsPer100Years(year)) {
+    seconds -= SecondsPer100Years(year);
+    year += 100;
+  }
+  while (seconds >= SecondsPer4Years(year)) {
+    seconds -= SecondsPer4Years(year);
+    year += 4;
+  }
+  while (seconds >= SecondsPerYear(year)) {
+    seconds -= SecondsPerYear(year);
+    year += 1;
+  }
+  bool leap = IsLeapYear(year);
+  int month = 1;
+  while (seconds >= SecondsPerMonth(month, leap)) {
+    seconds -= SecondsPerMonth(month, leap);
+    ++month;
+  }
+  int day = 1 + seconds / kSecondsPerDay;
+  seconds %= kSecondsPerDay;
+  int hour = seconds / kSecondsPerHour;
+  seconds %= kSecondsPerHour;
+  int minute = seconds / kSecondsPerMinute;
+  seconds %= kSecondsPerMinute;
+  time->year = year;
+  time->month = month;
+  time->day = day;
+  time->hour = hour;
+  time->minute = minute;
+  time->second = static_cast<int>(seconds);
+  return true;
+}
+
+bool DateTimeToSeconds(const DateTime& time, int64* seconds) {
+  if (!ValidateDateTime(time)) {
+    return false;
+  }
+  *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch;
+  return true;
+}
+
+void GetCurrentTime(int64* seconds, int32* nanos) {
+  // TODO(xiaofeng): Improve the accuracy of this implementation (or just
+  // remove this method from protobuf).
+  *seconds = time(NULL);
+  *nanos = 0;
+}
+
+string FormatTime(int64 seconds, int32 nanos) {
+  DateTime time;
+  if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
+    return "InvalidTime";
+  }
+  string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
+                               time.year, time.month, time.day,
+                               time.hour, time.minute, time.second);
+  if (nanos != 0) {
+    result += "." + FormatNanos(nanos);
+  }
+  return result + "Z";
+}
+
+bool ParseTime(const string& value, int64* seconds, int32* nanos) {
+  DateTime time;
+  const char* data = value.c_str();
+  // We only accept:
+  //   Z-normalized: 2015-05-20T13:29:35.120Z
+  //   With UTC offset: 2015-05-20T13:29:35.120-08:00
+
+  // Parse year
+  if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) {
+    return false;
+  }
+  // Expect '-'
+  if (*data++ != '-') return false;
+  // Parse month
+  if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) {
+    return false;
+  }
+  // Expect '-'
+  if (*data++ != '-') return false;
+  // Parse day
+  if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) {
+    return false;
+  }
+  // Expect 'T'
+  if (*data++ != 'T') return false;
+  // Parse hour
+  if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) {
+    return false;
+  }
+  // Expect ':'
+  if (*data++ != ':') return false;
+  // Parse minute
+  if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) {
+    return false;
+  }
+  // Expect ':'
+  if (*data++ != ':') return false;
+  // Parse second
+  if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) {
+    return false;
+  }
+  if (!DateTimeToSeconds(time, seconds)) {
+    return false;
+  }
+  // Parse nanoseconds.
+  if (*data == '.') {
+    ++data;
+    // Parse nanoseconds.
+    if ((data = ParseNanos(data, nanos)) == NULL) {
+      return false;
+    }
+  } else {
+    *nanos = 0;
+  }
+  // Parse UTC offsets.
+  if (*data == 'Z') {
+    ++data;
+  } else if (*data == '+') {
+    ++data;
+    int64 offset;
+    if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
+      return false;
+    }
+    *seconds -= offset;
+  } else if (*data == '-') {
+    ++data;
+    int64 offset;
+    if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
+      return false;
+    }
+    *seconds += offset;
+  } else {
+    return false;
+  }
+  // Done with parsing.
+  return *data == 0;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/time.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/time.h
new file mode 100644
index 0000000..20a6b56
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/time.h
@@ -0,0 +1,75 @@
+// 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_STUBS_TIME_H_
+#define GOOGLE_PROTOBUF_STUBS_TIME_H_
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+struct DateTime {
+  int year;
+  int month;
+  int day;
+  int hour;
+  int minute;
+  int second;
+};
+
+// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
+// negative to represent time before 1970-01-01) to DateTime. Returns false
+// if the timestamp is not in the range between 0001-01-01T00:00:00 and
+// 9999-12-31T23:59:59.
+bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time);
+// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
+// Returns false if the DateTime is not valid or is not in the valid range.
+bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds);
+
+void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos);
+
+// Formats a time string in RFC3339 fromat.
+//
+// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
+// digits will be used depending on how many are required to represent the exact
+// value.
+//
+// Note that "nanos" must in the range of [0, 999999999].
+string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
+// Parses a time string. This method accepts RFC3339 date/time string with UTC
+// offset. For example, "2015-05-20T13:29:35.120-08:00".
+bool LIBPROTOBUF_EXPORT ParseTime(const string& vaule, int64* seconds, int32* nanos);
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_TIME_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/time_test.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/time_test.cc
new file mode 100644
index 0000000..59e9d1c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/time_test.cc
@@ -0,0 +1,208 @@
+// 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.
+#include <google/protobuf/stubs/time.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+static const int64 kSecondsPerDay = 3600 * 24;
+
+// For DateTime, tests will mostly focuse on the date part because that's
+// the tricky one.
+int64 CreateTimestamp(int year, int month, int day) {
+  DateTime time;
+  time.year = year;
+  time.month = month;
+  time.day = day;
+  time.hour = time.minute = time.second = 0;
+  int64 result;
+  GOOGLE_CHECK(DateTimeToSeconds(time, &result));
+  // Check that a roundtrip produces the same result.
+  GOOGLE_CHECK(SecondsToDateTime(result, &time));
+  GOOGLE_CHECK(time.year == year);
+  GOOGLE_CHECK(time.month == month);
+  GOOGLE_CHECK(time.day == day);
+  return result;
+}
+
+TEST(DateTimeTest, SimpleTime) {
+  DateTime time;
+  ASSERT_TRUE(SecondsToDateTime(1, &time));
+  EXPECT_EQ(1970, time.year);
+  EXPECT_EQ(1, time.month);
+  EXPECT_EQ(1, time.day);
+  EXPECT_EQ(0, time.hour);
+  EXPECT_EQ(0, time.minute);
+  EXPECT_EQ(1, time.second);
+  int64 seconds;
+  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+  EXPECT_EQ(1, seconds);
+
+  ASSERT_TRUE(SecondsToDateTime(-1, &time));
+  EXPECT_EQ(1969, time.year);
+  EXPECT_EQ(12, time.month);
+  EXPECT_EQ(31, time.day);
+  EXPECT_EQ(23, time.hour);
+  EXPECT_EQ(59, time.minute);
+  EXPECT_EQ(59, time.second);
+  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+  EXPECT_EQ(-1, seconds);
+
+  DateTime start, end;
+  start.year = 1;
+  start.month = 1;
+  start.day = 1;
+  start.hour = 0;
+  start.minute = 0;
+  start.second = 0;
+  end.year = 9999;
+  end.month = 12;
+  end.day = 31;
+  end.hour = 23;
+  end.minute = 59;
+  end.second = 59;
+  int64 start_time, end_time;
+  ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
+  ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
+  EXPECT_EQ(315537897599LL, end_time - start_time);
+  ASSERT_TRUE(SecondsToDateTime(start_time, &time));
+  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+  EXPECT_EQ(start_time, seconds);
+  ASSERT_TRUE(SecondsToDateTime(end_time, &time));
+  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+  EXPECT_EQ(end_time, seconds);
+}
+
+TEST(DateTimeTest, DayInMonths) {
+  // Check that month boundaries are handled correctly.
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30));
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31));
+}
+
+TEST(DateTimeTest, LeapYear) {
+  // Non-leap year.
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
+  // Leap year.
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29));
+  // Non-leap year.
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28));
+  // Leap year.
+  EXPECT_EQ(kSecondsPerDay,
+            CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29));
+}
+
+TEST(DateTimeTest, StringFormat) {
+  DateTime start, end;
+  start.year = 1;
+  start.month = 1;
+  start.day = 1;
+  start.hour = 0;
+  start.minute = 0;
+  start.second = 0;
+  end.year = 9999;
+  end.month = 12;
+  end.day = 31;
+  end.hour = 23;
+  end.minute = 59;
+  end.second = 59;
+  int64 start_time, end_time;
+  ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
+  ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
+
+  EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0));
+  EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0));
+
+  // Make sure the nanoseconds part is formated correctly.
+  EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000));
+  EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000));
+  EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10));
+}
+
+TEST(DateTimeTest, ParseString) {
+  int64 seconds;
+  int32 nanos;
+  ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos));
+  EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos));
+  ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos));
+  EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos));
+
+  // Test time zone offsets.
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos));
+  EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos));
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos));
+  EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos));
+
+  // Test nanoseconds.
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos));
+  EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos));
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos));
+  EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos));
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos));
+  EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos));
+  // Fractional parts less than 1 nanosecond will be ignored.
+  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos));
+  EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos));
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits.h b/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits.h
new file mode 100644
index 0000000..0d8127e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits.h
@@ -0,0 +1,364 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// ----
+// Author: Matt Austern
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems.  Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+// Define a small subset of tr1 type traits. The traits we define are:
+//   enable_if
+//   is_integral
+//   is_floating_point
+//   is_pointer
+//   is_enum
+//   is_reference
+//   is_pod
+//   has_trivial_constructor
+//   has_trivial_copy
+//   has_trivial_assign
+//   has_trivial_destructor
+//   remove_const
+//   remove_volatile
+//   remove_cv
+//   remove_reference
+//   add_reference
+//   remove_pointer
+//   is_same
+//   is_convertible
+// We can add more type traits as required.
+
+#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+
+#include <cstddef>                  // for NULL
+#include <utility>                  // For pair
+
+#include <google/protobuf/stubs/template_util.h>  // For true_type and false_type
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+template<typename B, typename D>
+struct is_base_of {
+  typedef char (&yes)[1];
+  typedef char (&no)[2];
+
+  // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
+  #undef check
+  // END GOOGLE LOCAL MODIFICATION
+
+  static yes check(const B*);
+  static no check(const void*);
+
+  enum {
+    value = sizeof(check(static_cast<const D*>(NULL))) == sizeof(yes),
+  };
+};
+
+template <bool cond, class T = void> struct enable_if;
+template <class T> struct is_integral;
+template <class T> struct is_floating_point;
+template <class T> struct is_pointer;
+// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+// is_enum uses is_convertible, which is not available on MSVC.
+template <class T> struct is_enum;
+#endif
+template <class T> struct is_reference;
+template <class T> struct is_pod;
+template <class T> struct has_trivial_constructor;
+template <class T> struct has_trivial_copy;
+template <class T> struct has_trivial_assign;
+template <class T> struct has_trivial_destructor;
+template <class T> struct remove_const;
+template <class T> struct remove_volatile;
+template <class T> struct remove_cv;
+template <class T> struct remove_reference;
+template <class T> struct add_reference;
+template <class T> struct remove_pointer;
+template <class T, class U> struct is_same;
+#if !(defined(__GNUC__) && __GNUC__ <= 3)
+template <class From, class To> struct is_convertible;
+#endif
+
+// enable_if, equivalent semantics to c++11 std::enable_if, specifically:
+//   "If B is true, the member typedef type shall equal T; otherwise, there
+//    shall be no member typedef type."
+// Specified by 20.9.7.6 [Other transformations]
+
+template<bool cond, class T> struct enable_if { typedef T type; };
+template<class T> struct enable_if<false, T> {};
+// is_integral is false except for the built-in integer types. A
+// cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_integral : false_type { };
+template<> struct is_integral<bool> : true_type { };
+template<> struct is_integral<char> : true_type { };
+template<> struct is_integral<unsigned char> : true_type { };
+template<> struct is_integral<signed char> : true_type { };
+#if defined(_MSC_VER)
+// wchar_t is not by default a distinct type from unsigned short in
+// Microsoft C.
+// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
+template<> struct is_integral<__wchar_t> : true_type { };
+#else
+template<> struct is_integral<wchar_t> : true_type { };
+#endif
+template<> struct is_integral<short> : true_type { };
+template<> struct is_integral<unsigned short> : true_type { };
+template<> struct is_integral<int> : true_type { };
+template<> struct is_integral<unsigned int> : true_type { };
+template<> struct is_integral<long> : true_type { };
+template<> struct is_integral<unsigned long> : true_type { };
+#ifdef HAVE_LONG_LONG
+template<> struct is_integral<long long> : true_type { };
+template<> struct is_integral<unsigned long long> : true_type { };
+#endif
+template <class T> struct is_integral<const T> : is_integral<T> { };
+template <class T> struct is_integral<volatile T> : is_integral<T> { };
+template <class T> struct is_integral<const volatile T> : is_integral<T> { };
+
+// is_floating_point is false except for the built-in floating-point types.
+// A cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_floating_point : false_type { };
+template<> struct is_floating_point<float> : true_type { };
+template<> struct is_floating_point<double> : true_type { };
+template<> struct is_floating_point<long double> : true_type { };
+template <class T> struct is_floating_point<const T>
+    : is_floating_point<T> { };
+template <class T> struct is_floating_point<volatile T>
+    : is_floating_point<T> { };
+template <class T> struct is_floating_point<const volatile T>
+    : is_floating_point<T> { };
+
+// is_pointer is false except for pointer types. A cv-qualified type (e.g.
+// "int* const", as opposed to "int const*") is cv-qualified if and only if
+// the underlying type is.
+template <class T> struct is_pointer : false_type { };
+template <class T> struct is_pointer<T*> : true_type { };
+template <class T> struct is_pointer<const T> : is_pointer<T> { };
+template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
+template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
+
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+
+namespace type_traits_internal {
+
+template <class T> struct is_class_or_union {
+  template <class U> static small_ tester(void (U::*)());
+  template <class U> static big_ tester(...);
+  static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
+};
+
+// is_convertible chokes if the first argument is an array. That's why
+// we use add_reference here.
+template <bool NotUnum, class T> struct is_enum_impl
+    : is_convertible<typename add_reference<T>::type, int> { };
+
+template <class T> struct is_enum_impl<true, T> : false_type { };
+
+}  // namespace type_traits_internal
+
+// Specified by TR1 [4.5.1] primary type categories.
+
+// Implementation note:
+//
+// Each type is either void, integral, floating point, array, pointer,
+// reference, member object pointer, member function pointer, enum,
+// union or class. Out of these, only integral, floating point, reference,
+// class and enum types are potentially convertible to int. Therefore,
+// if a type is not a reference, integral, floating point or class and
+// is convertible to int, it's a enum. Adding cv-qualification to a type
+// does not change whether it's an enum.
+//
+// Is-convertible-to-int check is done only if all other checks pass,
+// because it can't be used with some types (e.g. void or classes with
+// inaccessible conversion operators).
+template <class T> struct is_enum
+    : type_traits_internal::is_enum_impl<
+          is_same<T, void>::value ||
+              is_integral<T>::value ||
+              is_floating_point<T>::value ||
+              is_reference<T>::value ||
+              type_traits_internal::is_class_or_union<T>::value,
+          T> { };
+
+template <class T> struct is_enum<const T> : is_enum<T> { };
+template <class T> struct is_enum<volatile T> : is_enum<T> { };
+template <class T> struct is_enum<const volatile T> : is_enum<T> { };
+
+#endif
+
+// is_reference is false except for reference types.
+template<typename T> struct is_reference : false_type {};
+template<typename T> struct is_reference<T&> : true_type {};
+
+
+// We can't get is_pod right without compiler help, so fail conservatively.
+// We will assume it's false except for arithmetic types, enumerations,
+// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
+// is not a POD even if T and U are PODs.
+template <class T> struct is_pod
+ : integral_constant<bool, (is_integral<T>::value ||
+                            is_floating_point<T>::value ||
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+                            // is_enum is not available on MSVC.
+                            is_enum<T>::value ||
+#endif
+                            is_pointer<T>::value)> { };
+template <class T> struct is_pod<const T> : is_pod<T> { };
+template <class T> struct is_pod<volatile T> : is_pod<T> { };
+template <class T> struct is_pod<const volatile T> : is_pod<T> { };
+
+
+// We can't get has_trivial_constructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// constructors. (3) array of a type with a trivial constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_constructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_constructor<T>::value &&
+                       has_trivial_constructor<U>::value)> { };
+template <class A, int N> struct has_trivial_constructor<A[N]>
+  : has_trivial_constructor<A> { };
+template <class T> struct has_trivial_constructor<const T>
+  : has_trivial_constructor<T> { };
+
+// We can't get has_trivial_copy right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial copy constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_copy : is_pod<T> { };
+template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_copy<T>::value &&
+                       has_trivial_copy<U>::value)> { };
+template <class A, int N> struct has_trivial_copy<A[N]>
+  : has_trivial_copy<A> { };
+template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
+
+// We can't get has_trivial_assign right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial assign constructor.
+template <class T> struct has_trivial_assign : is_pod<T> { };
+template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_assign<T>::value &&
+                       has_trivial_assign<U>::value)> { };
+template <class A, int N> struct has_trivial_assign<A[N]>
+  : has_trivial_assign<A> { };
+
+// We can't get has_trivial_destructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// destructors. (3) array of a type with a trivial destructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_destructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_destructor<T>::value &&
+                       has_trivial_destructor<U>::value)> { };
+template <class A, int N> struct has_trivial_destructor<A[N]>
+  : has_trivial_destructor<A> { };
+template <class T> struct has_trivial_destructor<const T>
+  : has_trivial_destructor<T> { };
+
+// Specified by TR1 [4.7.1]
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<T const> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<T volatile> { typedef T type; };
+template<typename T> struct remove_cv {
+  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+
+// Specified by TR1 [4.7.2] Reference modifications.
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+template <typename T> struct add_reference { typedef T& type; };
+template <typename T> struct add_reference<T&> { typedef T& type; };
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+  typedef T type; };
+
+// Specified by TR1 [4.6] Relationships between types
+template<typename T, typename U> struct is_same : public false_type { };
+template<typename T> struct is_same<T, T> : public true_type { };
+
+// Specified by TR1 [4.6] Relationships between types
+#if !(defined(__GNUC__) && __GNUC__ <= 3)
+namespace type_traits_internal {
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From.  See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+template <typename From, typename To>
+struct ConvertHelper {
+  static small_ Test(To);
+  static big_ Test(...);
+  static From Create();
+  enum {
+    value = sizeof(Test(Create())) == sizeof(small_)
+  };
+};
+}  // namespace type_traits_internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+template <typename From, typename To>
+struct is_convertible
+    : integral_constant<bool,
+                        type_traits_internal::ConvertHelper<From, To>::value> {
+};
+#endif
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
diff --git a/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits_unittest.cc
new file mode 100644
index 0000000..49c10ac
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/stubs/type_traits_unittest.cc
@@ -0,0 +1,631 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// ----
+// Author: Matt Austern
+
+#include <google/protobuf/stubs/type_traits.h>
+
+#include <stdlib.h>   // for exit()
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+typedef int int32;
+// IBM AIX typedefs `int64` in `sys/inttypes.h`, included transitively above.
+#ifndef _AIX
+typedef long int64;
+#endif
+
+using std::string;
+using std::vector;
+using std::pair;
+
+
+// This assertion produces errors like "error: invalid use of
+// incomplete type 'struct <unnamed>::AssertTypesEq<const int, int>'"
+// when it fails.
+template<typename T, typename U> struct AssertTypesEq;
+template<typename T> struct AssertTypesEq<T, T> {};
+#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast<void>(AssertTypesEq<T, U>())
+
+// A user-defined POD type.
+struct A {
+  int n_;
+};
+
+// A user-defined non-POD type with a trivial copy constructor.
+class B {
+ public:
+  explicit B(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+// Another user-defined non-POD type with a trivial copy constructor.
+// We will explicitly declare C to have a trivial copy constructor
+// by specializing has_trivial_copy.
+class C {
+ public:
+  explicit C(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_copy<C> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial assignment operator.
+// We will explicitly declare C to have a trivial assignment operator
+// by specializing has_trivial_assign.
+class D {
+ public:
+  explicit D(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_assign<D> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial constructor.
+// We will explicitly declare E to have a trivial constructor
+// by specializing has_trivial_constructor.
+class E {
+ public:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_constructor<E> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial destructor.
+// We will explicitly declare E to have a trivial destructor
+// by specializing has_trivial_destructor.
+class F {
+ public:
+  explicit F(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_destructor<F> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+enum G {};
+
+union H {};
+
+class I {
+ public:
+  operator int() const;
+};
+
+class J {
+ private:
+  operator int() const;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+// A base class and a derived class that inherits from it, used for
+// testing conversion type traits.
+class Base {
+ public:
+  virtual ~Base() { }
+};
+
+class Derived : public Base {
+};
+
+TEST(TypeTraitsTest, TestIsInteger) {
+  // Verify that is_integral is true for all integer types.
+  EXPECT_TRUE(is_integral<bool>::value);
+  EXPECT_TRUE(is_integral<char>::value);
+  EXPECT_TRUE(is_integral<unsigned char>::value);
+  EXPECT_TRUE(is_integral<signed char>::value);
+  EXPECT_TRUE(is_integral<wchar_t>::value);
+  EXPECT_TRUE(is_integral<int>::value);
+  EXPECT_TRUE(is_integral<unsigned int>::value);
+  EXPECT_TRUE(is_integral<short>::value);
+  EXPECT_TRUE(is_integral<unsigned short>::value);
+  EXPECT_TRUE(is_integral<long>::value);
+  EXPECT_TRUE(is_integral<unsigned long>::value);
+
+  // Verify that is_integral is false for a few non-integer types.
+  EXPECT_FALSE(is_integral<void>::value);
+  EXPECT_FALSE(is_integral<float>::value);
+  EXPECT_FALSE(is_integral<string>::value);
+  EXPECT_FALSE(is_integral<int*>::value);
+  EXPECT_FALSE(is_integral<A>::value);
+  EXPECT_FALSE((is_integral<pair<int, int> >::value));
+
+  // Verify that cv-qualified integral types are still integral, and
+  // cv-qualified non-integral types are still non-integral.
+  EXPECT_TRUE(is_integral<const char>::value);
+  EXPECT_TRUE(is_integral<volatile bool>::value);
+  EXPECT_TRUE(is_integral<const volatile unsigned int>::value);
+  EXPECT_FALSE(is_integral<const float>::value);
+  EXPECT_FALSE(is_integral<int* volatile>::value);
+  EXPECT_FALSE(is_integral<const volatile string>::value);
+}
+
+TEST(TypeTraitsTest, TestIsFloating) {
+  // Verify that is_floating_point is true for all floating-point types.
+  EXPECT_TRUE(is_floating_point<float>::value);
+  EXPECT_TRUE(is_floating_point<double>::value);
+  EXPECT_TRUE(is_floating_point<long double>::value);
+
+  // Verify that is_floating_point is false for a few non-float types.
+  EXPECT_FALSE(is_floating_point<void>::value);
+  EXPECT_FALSE(is_floating_point<long>::value);
+  EXPECT_FALSE(is_floating_point<string>::value);
+  EXPECT_FALSE(is_floating_point<float*>::value);
+  EXPECT_FALSE(is_floating_point<A>::value);
+  EXPECT_FALSE((is_floating_point<pair<int, int> >::value));
+
+  // Verify that cv-qualified floating point types are still floating, and
+  // cv-qualified non-floating types are still non-floating.
+  EXPECT_TRUE(is_floating_point<const float>::value);
+  EXPECT_TRUE(is_floating_point<volatile double>::value);
+  EXPECT_TRUE(is_floating_point<const volatile long double>::value);
+  EXPECT_FALSE(is_floating_point<const int>::value);
+  EXPECT_FALSE(is_floating_point<volatile string>::value);
+  EXPECT_FALSE(is_floating_point<const volatile char>::value);
+}
+
+TEST(TypeTraitsTest, TestIsPointer) {
+  // Verify that is_pointer is true for some pointer types.
+  EXPECT_TRUE(is_pointer<int*>::value);
+  EXPECT_TRUE(is_pointer<void*>::value);
+  EXPECT_TRUE(is_pointer<string*>::value);
+  EXPECT_TRUE(is_pointer<const void*>::value);
+  EXPECT_TRUE(is_pointer<volatile float* const*>::value);
+
+  // Verify that is_pointer is false for some non-pointer types.
+  EXPECT_FALSE(is_pointer<void>::value);
+  EXPECT_FALSE(is_pointer<float&>::value);
+  EXPECT_FALSE(is_pointer<long>::value);
+  EXPECT_FALSE(is_pointer<vector<int*> >::value);
+  EXPECT_FALSE(is_pointer<int[5]>::value);
+
+  // A function pointer is a pointer, but a function type, or a function
+  // reference type, is not.
+  EXPECT_TRUE(is_pointer<int (*)(int x)>::value);
+  EXPECT_FALSE(is_pointer<void(char x)>::value);
+  EXPECT_FALSE(is_pointer<double (&)(string x)>::value);
+
+  // Verify that is_pointer<T> is true for some cv-qualified pointer types,
+  // and false for some cv-qualified non-pointer types.
+  EXPECT_TRUE(is_pointer<int* const>::value);
+  EXPECT_TRUE(is_pointer<const void* volatile>::value);
+  EXPECT_TRUE(is_pointer<char** const volatile>::value);
+  EXPECT_FALSE(is_pointer<const int>::value);
+  EXPECT_FALSE(is_pointer<volatile vector<int*> >::value);
+  EXPECT_FALSE(is_pointer<const volatile double>::value);
+}
+
+TEST(TypeTraitsTest, TestIsEnum) {
+// is_enum isn't supported on MSVC or gcc 3.x
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+  // Verify that is_enum is true for enum types.
+  EXPECT_TRUE(is_enum<G>::value);
+  EXPECT_TRUE(is_enum<const G>::value);
+  EXPECT_TRUE(is_enum<volatile G>::value);
+  EXPECT_TRUE(is_enum<const volatile G>::value);
+
+  // Verify that is_enum is false for a few non-enum types.
+  EXPECT_FALSE(is_enum<void>::value);
+  EXPECT_FALSE(is_enum<G&>::value);
+  EXPECT_FALSE(is_enum<G[1]>::value);
+  EXPECT_FALSE(is_enum<const G[1]>::value);
+  EXPECT_FALSE(is_enum<G[]>::value);
+  EXPECT_FALSE(is_enum<int>::value);
+  EXPECT_FALSE(is_enum<float>::value);
+  EXPECT_FALSE(is_enum<A>::value);
+  EXPECT_FALSE(is_enum<A*>::value);
+  EXPECT_FALSE(is_enum<const A>::value);
+  EXPECT_FALSE(is_enum<H>::value);
+  EXPECT_FALSE(is_enum<I>::value);
+  EXPECT_FALSE(is_enum<J>::value);
+  EXPECT_FALSE(is_enum<void()>::value);
+  EXPECT_FALSE(is_enum<void(*)()>::value);
+  EXPECT_FALSE(is_enum<int A::*>::value);
+  EXPECT_FALSE(is_enum<void (A::*)()>::value);
+#endif
+}
+
+TEST(TypeTraitsTest, TestIsReference) {
+  // Verifies that is_reference is true for all reference types.
+  typedef float& RefFloat;
+  EXPECT_TRUE(is_reference<float&>::value);
+  EXPECT_TRUE(is_reference<const int&>::value);
+  EXPECT_TRUE(is_reference<const int*&>::value);
+  EXPECT_TRUE(is_reference<int (&)(bool)>::value);
+  EXPECT_TRUE(is_reference<RefFloat>::value);
+  EXPECT_TRUE(is_reference<const RefFloat>::value);
+  EXPECT_TRUE(is_reference<volatile RefFloat>::value);
+  EXPECT_TRUE(is_reference<const volatile RefFloat>::value);
+
+
+  // Verifies that is_reference is false for all non-reference types.
+  EXPECT_FALSE(is_reference<float>::value);
+  EXPECT_FALSE(is_reference<const float>::value);
+  EXPECT_FALSE(is_reference<volatile float>::value);
+  EXPECT_FALSE(is_reference<const volatile float>::value);
+  EXPECT_FALSE(is_reference<const int*>::value);
+  EXPECT_FALSE(is_reference<int()>::value);
+  EXPECT_FALSE(is_reference<void(*)(const char&)>::value);
+}
+
+TEST(TypeTraitsTest, TestAddReference) {
+  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int&,
+                          add_reference<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+                          add_reference<const volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int&,
+                          add_reference<volatile int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+                          add_reference<const volatile int&>::type);
+}
+
+TEST(TypeTraitsTest, TestIsPod) {
+  // Verify that arithmetic types and pointers are marked as PODs.
+  EXPECT_TRUE(is_pod<bool>::value);
+  EXPECT_TRUE(is_pod<char>::value);
+  EXPECT_TRUE(is_pod<unsigned char>::value);
+  EXPECT_TRUE(is_pod<signed char>::value);
+  EXPECT_TRUE(is_pod<wchar_t>::value);
+  EXPECT_TRUE(is_pod<int>::value);
+  EXPECT_TRUE(is_pod<unsigned int>::value);
+  EXPECT_TRUE(is_pod<short>::value);
+  EXPECT_TRUE(is_pod<unsigned short>::value);
+  EXPECT_TRUE(is_pod<long>::value);
+  EXPECT_TRUE(is_pod<unsigned long>::value);
+  EXPECT_TRUE(is_pod<float>::value);
+  EXPECT_TRUE(is_pod<double>::value);
+  EXPECT_TRUE(is_pod<long double>::value);
+  EXPECT_TRUE(is_pod<string*>::value);
+  EXPECT_TRUE(is_pod<A*>::value);
+  EXPECT_TRUE(is_pod<const B*>::value);
+  EXPECT_TRUE(is_pod<C**>::value);
+  EXPECT_TRUE(is_pod<const int>::value);
+  EXPECT_TRUE(is_pod<char* volatile>::value);
+  EXPECT_TRUE(is_pod<const volatile double>::value);
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+  EXPECT_TRUE(is_pod<G>::value);
+  EXPECT_TRUE(is_pod<const G>::value);
+  EXPECT_TRUE(is_pod<volatile G>::value);
+  EXPECT_TRUE(is_pod<const volatile G>::value);
+#endif
+
+  // Verify that some non-POD types are not marked as PODs.
+  EXPECT_FALSE(is_pod<void>::value);
+  EXPECT_FALSE(is_pod<string>::value);
+  EXPECT_FALSE((is_pod<pair<int, int> >::value));
+  EXPECT_FALSE(is_pod<A>::value);
+  EXPECT_FALSE(is_pod<B>::value);
+  EXPECT_FALSE(is_pod<C>::value);
+  EXPECT_FALSE(is_pod<const string>::value);
+  EXPECT_FALSE(is_pod<volatile A>::value);
+  EXPECT_FALSE(is_pod<const volatile B>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialConstructor) {
+  // Verify that arithmetic types and pointers have trivial constructors.
+  EXPECT_TRUE(has_trivial_constructor<bool>::value);
+  EXPECT_TRUE(has_trivial_constructor<char>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_constructor<signed char>::value);
+  EXPECT_TRUE(has_trivial_constructor<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_constructor<int>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_constructor<short>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_constructor<long>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_constructor<float>::value);
+  EXPECT_TRUE(has_trivial_constructor<double>::value);
+  EXPECT_TRUE(has_trivial_constructor<long double>::value);
+  EXPECT_TRUE(has_trivial_constructor<string*>::value);
+  EXPECT_TRUE(has_trivial_constructor<A*>::value);
+  EXPECT_TRUE(has_trivial_constructor<const B*>::value);
+  EXPECT_TRUE(has_trivial_constructor<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // constructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_constructor<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_constructor<int10>::value);
+
+  // Verify that pairs of types without trivial constructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_constructor<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_constructor<pair<string, int> >::value));
+
+  // Verify that types without trivial constructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_constructor<string>::value);
+  EXPECT_FALSE(has_trivial_constructor<vector<int> >::value);
+
+  // Verify that E, which we have declared to have a trivial
+  // constructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_constructor<E>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialCopy) {
+  // Verify that arithmetic types and pointers have trivial copy
+  // constructors.
+  EXPECT_TRUE(has_trivial_copy<bool>::value);
+  EXPECT_TRUE(has_trivial_copy<char>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_copy<signed char>::value);
+  EXPECT_TRUE(has_trivial_copy<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_copy<int>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_copy<short>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_copy<long>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_copy<float>::value);
+  EXPECT_TRUE(has_trivial_copy<double>::value);
+  EXPECT_TRUE(has_trivial_copy<long double>::value);
+  EXPECT_TRUE(has_trivial_copy<string*>::value);
+  EXPECT_TRUE(has_trivial_copy<A*>::value);
+  EXPECT_TRUE(has_trivial_copy<const B*>::value);
+  EXPECT_TRUE(has_trivial_copy<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // copy constructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_copy<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_copy<int10>::value);
+
+  // Verify that pairs of types without trivial copy constructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_copy<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_copy<pair<string, int> >::value));
+
+  // Verify that types without trivial copy constructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_copy<string>::value);
+  EXPECT_FALSE(has_trivial_copy<vector<int> >::value);
+
+  // Verify that C, which we have declared to have a trivial
+  // copy constructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_copy<C>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialAssign) {
+  // Verify that arithmetic types and pointers have trivial assignment
+  // operators.
+  EXPECT_TRUE(has_trivial_assign<bool>::value);
+  EXPECT_TRUE(has_trivial_assign<char>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_assign<signed char>::value);
+  EXPECT_TRUE(has_trivial_assign<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_assign<int>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_assign<short>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_assign<long>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_assign<float>::value);
+  EXPECT_TRUE(has_trivial_assign<double>::value);
+  EXPECT_TRUE(has_trivial_assign<long double>::value);
+  EXPECT_TRUE(has_trivial_assign<string*>::value);
+  EXPECT_TRUE(has_trivial_assign<A*>::value);
+  EXPECT_TRUE(has_trivial_assign<const B*>::value);
+  EXPECT_TRUE(has_trivial_assign<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // assignment operators.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_assign<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_assign<int10>::value);
+
+  // Verify that pairs of types without trivial assignment operators
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_assign<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_assign<pair<string, int> >::value));
+
+  // Verify that types without trivial assignment operators are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_assign<string>::value);
+  EXPECT_FALSE(has_trivial_assign<vector<int> >::value);
+
+  // Verify that D, which we have declared to have a trivial
+  // assignment operator, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_assign<D>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialDestructor) {
+  // Verify that arithmetic types and pointers have trivial destructors.
+  EXPECT_TRUE(has_trivial_destructor<bool>::value);
+  EXPECT_TRUE(has_trivial_destructor<char>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_destructor<signed char>::value);
+  EXPECT_TRUE(has_trivial_destructor<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_destructor<int>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_destructor<short>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_destructor<long>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_destructor<float>::value);
+  EXPECT_TRUE(has_trivial_destructor<double>::value);
+  EXPECT_TRUE(has_trivial_destructor<long double>::value);
+  EXPECT_TRUE(has_trivial_destructor<string*>::value);
+  EXPECT_TRUE(has_trivial_destructor<A*>::value);
+  EXPECT_TRUE(has_trivial_destructor<const B*>::value);
+  EXPECT_TRUE(has_trivial_destructor<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // destructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_destructor<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_destructor<int10>::value);
+
+  // Verify that pairs of types without trivial destructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_destructor<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_destructor<pair<string, int> >::value));
+
+  // Verify that types without trivial destructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_destructor<string>::value);
+  EXPECT_FALSE(has_trivial_destructor<vector<int> >::value);
+
+  // Verify that F, which we have declared to have a trivial
+  // destructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_destructor<F>::value);
+}
+
+// Tests remove_pointer.
+TEST(TypeTraitsTest, TestRemovePointer) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int*>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer<const int*>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* const>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* volatile>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveConst) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_const<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_const<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_const<int * const>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(const int *, remove_const<const int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int,
+                          remove_const<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveVolatile) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile<int * volatile>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(volatile int *,
+                          remove_volatile<volatile int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int,
+                          remove_volatile<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveCV) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_cv<int * const volatile>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(const volatile int *,
+                          remove_cv<const volatile int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(int,
+                          remove_cv<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveReference) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int, remove_reference<const int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(int*, remove_reference<int * &>::type);
+}
+
+TEST(TypeTraitsTest, TestIsSame) {
+  EXPECT_TRUE((is_same<int32, int32>::value));
+  EXPECT_FALSE((is_same<int32, int64>::value));
+  EXPECT_FALSE((is_same<int64, int32>::value));
+  EXPECT_FALSE((is_same<int, const int>::value));
+
+  EXPECT_TRUE((is_same<void, void>::value));
+  EXPECT_FALSE((is_same<void, int>::value));
+  EXPECT_FALSE((is_same<int, void>::value));
+
+  EXPECT_TRUE((is_same<int*, int*>::value));
+  EXPECT_TRUE((is_same<void*, void*>::value));
+  EXPECT_FALSE((is_same<int*, void*>::value));
+  EXPECT_FALSE((is_same<void*, int*>::value));
+  EXPECT_FALSE((is_same<void*, const void*>::value));
+  EXPECT_FALSE((is_same<void*, void* const>::value));
+
+  EXPECT_TRUE((is_same<Base*, Base*>::value));
+  EXPECT_TRUE((is_same<Derived*, Derived*>::value));
+  EXPECT_FALSE((is_same<Base*, Derived*>::value));
+  EXPECT_FALSE((is_same<Derived*, Base*>::value));
+}
+
+TEST(TypeTraitsTest, TestConvertible) {
+#if !(defined(__GNUC__) && __GNUC__ <= 3)
+  EXPECT_TRUE((is_convertible<int, int>::value));
+  EXPECT_TRUE((is_convertible<int, long>::value));
+  EXPECT_TRUE((is_convertible<long, int>::value));
+
+  EXPECT_TRUE((is_convertible<int*, void*>::value));
+  EXPECT_FALSE((is_convertible<void*, int*>::value));
+
+  EXPECT_TRUE((is_convertible<Derived*, Base*>::value));
+  EXPECT_FALSE((is_convertible<Base*, Derived*>::value));
+  EXPECT_TRUE((is_convertible<Derived*, const Base*>::value));
+  EXPECT_FALSE((is_convertible<const Derived*, Base*>::value));
+#endif
+}
+
+}  // anonymous namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/test_util.cc b/src/third_party/protobuf-3/src/google/protobuf/test_util.cc
new file mode 100644
index 0000000..07aa1d7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/test_util.cc
@@ -0,0 +1,3346 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifdef _WIN32
+// Verify that #including windows.h does not break anything (e.g. because
+// windows.h #defines GetMessage() as a macro).
+#include <windows.h>
+#endif
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+void TestUtil::SetAllFields(unittest::TestAllTypes* message) {
+  SetOptionalFields(message);
+  AddRepeatedFields1(message);
+  AddRepeatedFields2(message);
+  SetDefaultFields(message);
+  SetOneofFields(message);
+}
+
+void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) {
+  message->set_optional_int32   (101);
+  message->set_optional_int64   (102);
+  message->set_optional_uint32  (103);
+  message->set_optional_uint64  (104);
+  message->set_optional_sint32  (105);
+  message->set_optional_sint64  (106);
+  message->set_optional_fixed32 (107);
+  message->set_optional_fixed64 (108);
+  message->set_optional_sfixed32(109);
+  message->set_optional_sfixed64(110);
+  message->set_optional_float   (111);
+  message->set_optional_double  (112);
+  message->set_optional_bool    (true);
+  message->set_optional_string  ("115");
+  message->set_optional_bytes   ("116");
+
+  message->mutable_optionalgroup                 ()->set_a(117);
+  message->mutable_optional_nested_message       ()->set_bb(118);
+  message->mutable_optional_foreign_message      ()->set_c(119);
+  message->mutable_optional_import_message       ()->set_d(120);
+  message->mutable_optional_public_import_message()->set_e(126);
+  message->mutable_optional_lazy_message         ()->set_bb(127);
+
+  message->set_optional_nested_enum (unittest::TestAllTypes::BAZ);
+  message->set_optional_foreign_enum(unittest::FOREIGN_BAZ      );
+  message->set_optional_import_enum (unittest_import::IMPORT_BAZ);
+
+  // StringPiece and Cord fields are only accessible via reflection in the
+  // open source release; see comments in compiler/cpp/string_field.cc.
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  message->GetReflection()->SetString(
+    message,
+    message->GetDescriptor()->FindFieldByName("optional_string_piece"),
+    "124");
+  message->GetReflection()->SetString(
+    message,
+    message->GetDescriptor()->FindFieldByName("optional_cord"),
+    "125");
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::AddRepeatedFields1(unittest::TestAllTypes* message) {
+  message->add_repeated_int32   (201);
+  message->add_repeated_int64   (202);
+  message->add_repeated_uint32  (203);
+  message->add_repeated_uint64  (204);
+  message->add_repeated_sint32  (205);
+  message->add_repeated_sint64  (206);
+  message->add_repeated_fixed32 (207);
+  message->add_repeated_fixed64 (208);
+  message->add_repeated_sfixed32(209);
+  message->add_repeated_sfixed64(210);
+  message->add_repeated_float   (211);
+  message->add_repeated_double  (212);
+  message->add_repeated_bool    (true);
+  message->add_repeated_string  ("215");
+  message->add_repeated_bytes   ("216");
+
+  message->add_repeatedgroup           ()->set_a(217);
+  message->add_repeated_nested_message ()->set_bb(218);
+  message->add_repeated_foreign_message()->set_c(219);
+  message->add_repeated_import_message ()->set_d(220);
+  message->add_repeated_lazy_message   ()->set_bb(227);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypes::BAR);
+  message->add_repeated_foreign_enum(unittest::FOREIGN_BAR      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_BAR);
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  message->GetReflection()->AddString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_string_piece"),
+    "224");
+  message->GetReflection()->AddString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_cord"),
+    "225");
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+
+void TestUtil::AddRepeatedFields2(unittest::TestAllTypes* message) {
+  // Add a second one of each field.
+  message->add_repeated_int32   (301);
+  message->add_repeated_int64   (302);
+  message->add_repeated_uint32  (303);
+  message->add_repeated_uint64  (304);
+  message->add_repeated_sint32  (305);
+  message->add_repeated_sint64  (306);
+  message->add_repeated_fixed32 (307);
+  message->add_repeated_fixed64 (308);
+  message->add_repeated_sfixed32(309);
+  message->add_repeated_sfixed64(310);
+  message->add_repeated_float   (311);
+  message->add_repeated_double  (312);
+  message->add_repeated_bool    (false);
+  message->add_repeated_string  ("315");
+  message->add_repeated_bytes   ("316");
+
+  message->add_repeatedgroup           ()->set_a(317);
+  message->add_repeated_nested_message ()->set_bb(318);
+  message->add_repeated_foreign_message()->set_c(319);
+  message->add_repeated_import_message ()->set_d(320);
+  message->add_repeated_lazy_message   ()->set_bb(327);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypes::BAZ);
+  message->add_repeated_foreign_enum(unittest::FOREIGN_BAZ      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_BAZ);
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  message->GetReflection()->AddString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_string_piece"),
+    "324");
+  message->GetReflection()->AddString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_cord"),
+    "325");
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::SetDefaultFields(unittest::TestAllTypes* message) {
+  message->set_default_int32   (401);
+  message->set_default_int64   (402);
+  message->set_default_uint32  (403);
+  message->set_default_uint64  (404);
+  message->set_default_sint32  (405);
+  message->set_default_sint64  (406);
+  message->set_default_fixed32 (407);
+  message->set_default_fixed64 (408);
+  message->set_default_sfixed32(409);
+  message->set_default_sfixed64(410);
+  message->set_default_float   (411);
+  message->set_default_double  (412);
+  message->set_default_bool    (false);
+  message->set_default_string  ("415");
+  message->set_default_bytes   ("416");
+
+  message->set_default_nested_enum (unittest::TestAllTypes::FOO);
+  message->set_default_foreign_enum(unittest::FOREIGN_FOO      );
+  message->set_default_import_enum (unittest_import::IMPORT_FOO);
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  message->GetReflection()->SetString(
+    message,
+    message->GetDescriptor()->FindFieldByName("default_string_piece"),
+    "424");
+  message->GetReflection()->SetString(
+    message,
+    message->GetDescriptor()->FindFieldByName("default_cord"),
+    "425");
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) {
+  message->set_repeated_int32   (1, 501);
+  message->set_repeated_int64   (1, 502);
+  message->set_repeated_uint32  (1, 503);
+  message->set_repeated_uint64  (1, 504);
+  message->set_repeated_sint32  (1, 505);
+  message->set_repeated_sint64  (1, 506);
+  message->set_repeated_fixed32 (1, 507);
+  message->set_repeated_fixed64 (1, 508);
+  message->set_repeated_sfixed32(1, 509);
+  message->set_repeated_sfixed64(1, 510);
+  message->set_repeated_float   (1, 511);
+  message->set_repeated_double  (1, 512);
+  message->set_repeated_bool    (1, true);
+  message->set_repeated_string  (1, "515");
+  message->set_repeated_bytes   (1, "516");
+
+  message->mutable_repeatedgroup           (1)->set_a(517);
+  message->mutable_repeated_nested_message (1)->set_bb(518);
+  message->mutable_repeated_foreign_message(1)->set_c(519);
+  message->mutable_repeated_import_message (1)->set_d(520);
+  message->mutable_repeated_lazy_message   (1)->set_bb(527);
+
+  message->set_repeated_nested_enum (1, unittest::TestAllTypes::FOO);
+  message->set_repeated_foreign_enum(1, unittest::FOREIGN_FOO      );
+  message->set_repeated_import_enum (1, unittest_import::IMPORT_FOO);
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  message->GetReflection()->SetRepeatedString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_string_piece"),
+    1, "524");
+  message->GetReflection()->SetRepeatedString(
+    message,
+    message->GetDescriptor()->FindFieldByName("repeated_cord"),
+    1, "525");
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+
+// ------------------------------------------------------------------
+void TestUtil::SetOneofFields(unittest::TestAllTypes* message) {
+  message->set_oneof_uint32(601);
+  message->mutable_oneof_nested_message()->set_bb(602);
+  message->set_oneof_string("603");
+  message->set_oneof_bytes("604");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) {
+  EXPECT_TRUE(message.has_optional_int32   ());
+  EXPECT_TRUE(message.has_optional_int64   ());
+  EXPECT_TRUE(message.has_optional_uint32  ());
+  EXPECT_TRUE(message.has_optional_uint64  ());
+  EXPECT_TRUE(message.has_optional_sint32  ());
+  EXPECT_TRUE(message.has_optional_sint64  ());
+  EXPECT_TRUE(message.has_optional_fixed32 ());
+  EXPECT_TRUE(message.has_optional_fixed64 ());
+  EXPECT_TRUE(message.has_optional_sfixed32());
+  EXPECT_TRUE(message.has_optional_sfixed64());
+  EXPECT_TRUE(message.has_optional_float   ());
+  EXPECT_TRUE(message.has_optional_double  ());
+  EXPECT_TRUE(message.has_optional_bool    ());
+  EXPECT_TRUE(message.has_optional_string  ());
+  EXPECT_TRUE(message.has_optional_bytes   ());
+
+  EXPECT_TRUE(message.has_optionalgroup                 ());
+  EXPECT_TRUE(message.has_optional_nested_message       ());
+  EXPECT_TRUE(message.has_optional_foreign_message      ());
+  EXPECT_TRUE(message.has_optional_import_message       ());
+  EXPECT_TRUE(message.has_optional_public_import_message());
+  EXPECT_TRUE(message.has_optional_lazy_message         ());
+
+  EXPECT_TRUE(message.optionalgroup                 ().has_a());
+  EXPECT_TRUE(message.optional_nested_message       ().has_bb());
+  EXPECT_TRUE(message.optional_foreign_message      ().has_c());
+  EXPECT_TRUE(message.optional_import_message       ().has_d());
+  EXPECT_TRUE(message.optional_public_import_message().has_e());
+  EXPECT_TRUE(message.optional_lazy_message         ().has_bb());
+
+  EXPECT_TRUE(message.has_optional_nested_enum ());
+  EXPECT_TRUE(message.has_optional_foreign_enum());
+  EXPECT_TRUE(message.has_optional_import_enum ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  EXPECT_TRUE(message.has_optional_string_piece());
+  EXPECT_TRUE(message.has_optional_cord());
+#endif
+
+  EXPECT_EQ(101  , message.optional_int32   ());
+  EXPECT_EQ(102  , message.optional_int64   ());
+  EXPECT_EQ(103  , message.optional_uint32  ());
+  EXPECT_EQ(104  , message.optional_uint64  ());
+  EXPECT_EQ(105  , message.optional_sint32  ());
+  EXPECT_EQ(106  , message.optional_sint64  ());
+  EXPECT_EQ(107  , message.optional_fixed32 ());
+  EXPECT_EQ(108  , message.optional_fixed64 ());
+  EXPECT_EQ(109  , message.optional_sfixed32());
+  EXPECT_EQ(110  , message.optional_sfixed64());
+  EXPECT_EQ(111  , message.optional_float   ());
+  EXPECT_EQ(112  , message.optional_double  ());
+  EXPECT_TRUE(     message.optional_bool    ());
+  EXPECT_EQ("115", message.optional_string  ());
+  EXPECT_EQ("116", message.optional_bytes   ());
+
+  EXPECT_EQ(117, message.optionalgroup                  ().a());
+  EXPECT_EQ(118, message.optional_nested_message        ().bb());
+  EXPECT_EQ(119, message.optional_foreign_message       ().c());
+  EXPECT_EQ(120, message.optional_import_message        ().d());
+  EXPECT_EQ(126, message.optional_public_import_message ().e());
+  EXPECT_EQ(127, message.optional_lazy_message          ().bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.optional_import_enum ());
+
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  ASSERT_EQ(2, message.repeated_string_piece_size());
+  ASSERT_EQ(2, message.repeated_cord_size());
+#endif
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_TRUE(     message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
+
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0));
+
+  EXPECT_EQ(301  , message.repeated_int32   (1));
+  EXPECT_EQ(302  , message.repeated_int64   (1));
+  EXPECT_EQ(303  , message.repeated_uint32  (1));
+  EXPECT_EQ(304  , message.repeated_uint64  (1));
+  EXPECT_EQ(305  , message.repeated_sint32  (1));
+  EXPECT_EQ(306  , message.repeated_sint64  (1));
+  EXPECT_EQ(307  , message.repeated_fixed32 (1));
+  EXPECT_EQ(308  , message.repeated_fixed64 (1));
+  EXPECT_EQ(309  , message.repeated_sfixed32(1));
+  EXPECT_EQ(310  , message.repeated_sfixed64(1));
+  EXPECT_EQ(311  , message.repeated_float   (1));
+  EXPECT_EQ(312  , message.repeated_double  (1));
+  EXPECT_FALSE(    message.repeated_bool    (1));
+  EXPECT_EQ("315", message.repeated_string  (1));
+  EXPECT_EQ("316", message.repeated_bytes   (1));
+
+  EXPECT_EQ(317, message.repeatedgroup           (1).a());
+  EXPECT_EQ(318, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(319, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(320, message.repeated_import_message (1).d());
+  EXPECT_EQ(327, message.repeated_lazy_message   (1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.repeated_import_enum (1));
+
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.has_default_int32   ());
+  EXPECT_TRUE(message.has_default_int64   ());
+  EXPECT_TRUE(message.has_default_uint32  ());
+  EXPECT_TRUE(message.has_default_uint64  ());
+  EXPECT_TRUE(message.has_default_sint32  ());
+  EXPECT_TRUE(message.has_default_sint64  ());
+  EXPECT_TRUE(message.has_default_fixed32 ());
+  EXPECT_TRUE(message.has_default_fixed64 ());
+  EXPECT_TRUE(message.has_default_sfixed32());
+  EXPECT_TRUE(message.has_default_sfixed64());
+  EXPECT_TRUE(message.has_default_float   ());
+  EXPECT_TRUE(message.has_default_double  ());
+  EXPECT_TRUE(message.has_default_bool    ());
+  EXPECT_TRUE(message.has_default_string  ());
+  EXPECT_TRUE(message.has_default_bytes   ());
+
+  EXPECT_TRUE(message.has_default_nested_enum ());
+  EXPECT_TRUE(message.has_default_foreign_enum());
+  EXPECT_TRUE(message.has_default_import_enum ());
+
+
+  EXPECT_EQ(401  , message.default_int32   ());
+  EXPECT_EQ(402  , message.default_int64   ());
+  EXPECT_EQ(403  , message.default_uint32  ());
+  EXPECT_EQ(404  , message.default_uint64  ());
+  EXPECT_EQ(405  , message.default_sint32  ());
+  EXPECT_EQ(406  , message.default_sint64  ());
+  EXPECT_EQ(407  , message.default_fixed32 ());
+  EXPECT_EQ(408  , message.default_fixed64 ());
+  EXPECT_EQ(409  , message.default_sfixed32());
+  EXPECT_EQ(410  , message.default_sfixed64());
+  EXPECT_EQ(411  , message.default_float   ());
+  EXPECT_EQ(412  , message.default_double  ());
+  EXPECT_FALSE(    message.default_bool    ());
+  EXPECT_EQ("415", message.default_string  ());
+  EXPECT_EQ("416", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.default_import_enum ());
+
+
+  EXPECT_FALSE(message.has_oneof_uint32        ());
+  EXPECT_FALSE(message.has_oneof_nested_message());
+  EXPECT_FALSE(message.has_oneof_string        ());
+  EXPECT_TRUE(message.has_oneof_bytes          ());
+
+  EXPECT_EQ("604", message.oneof_bytes());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectClear(const unittest::TestAllTypes& message) {
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.has_optional_int32   ());
+  EXPECT_FALSE(message.has_optional_int64   ());
+  EXPECT_FALSE(message.has_optional_uint32  ());
+  EXPECT_FALSE(message.has_optional_uint64  ());
+  EXPECT_FALSE(message.has_optional_sint32  ());
+  EXPECT_FALSE(message.has_optional_sint64  ());
+  EXPECT_FALSE(message.has_optional_fixed32 ());
+  EXPECT_FALSE(message.has_optional_fixed64 ());
+  EXPECT_FALSE(message.has_optional_sfixed32());
+  EXPECT_FALSE(message.has_optional_sfixed64());
+  EXPECT_FALSE(message.has_optional_float   ());
+  EXPECT_FALSE(message.has_optional_double  ());
+  EXPECT_FALSE(message.has_optional_bool    ());
+  EXPECT_FALSE(message.has_optional_string  ());
+  EXPECT_FALSE(message.has_optional_bytes   ());
+
+  EXPECT_FALSE(message.has_optionalgroup                 ());
+  EXPECT_FALSE(message.has_optional_nested_message       ());
+  EXPECT_FALSE(message.has_optional_foreign_message      ());
+  EXPECT_FALSE(message.has_optional_import_message       ());
+  EXPECT_FALSE(message.has_optional_public_import_message());
+  EXPECT_FALSE(message.has_optional_lazy_message         ());
+
+  EXPECT_FALSE(message.has_optional_nested_enum ());
+  EXPECT_FALSE(message.has_optional_foreign_enum());
+  EXPECT_FALSE(message.has_optional_import_enum ());
+
+  EXPECT_FALSE(message.has_optional_string_piece());
+  EXPECT_FALSE(message.has_optional_cord());
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.optional_int32   ());
+  EXPECT_EQ(0    , message.optional_int64   ());
+  EXPECT_EQ(0    , message.optional_uint32  ());
+  EXPECT_EQ(0    , message.optional_uint64  ());
+  EXPECT_EQ(0    , message.optional_sint32  ());
+  EXPECT_EQ(0    , message.optional_sint64  ());
+  EXPECT_EQ(0    , message.optional_fixed32 ());
+  EXPECT_EQ(0    , message.optional_fixed64 ());
+  EXPECT_EQ(0    , message.optional_sfixed32());
+  EXPECT_EQ(0    , message.optional_sfixed64());
+  EXPECT_EQ(0    , message.optional_float   ());
+  EXPECT_EQ(0    , message.optional_double  ());
+  EXPECT_FALSE(    message.optional_bool    ());
+  EXPECT_EQ(""   , message.optional_string  ());
+  EXPECT_EQ(""   , message.optional_bytes   ());
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.optionalgroup                 ().has_a());
+  EXPECT_FALSE(message.optional_nested_message       ().has_bb());
+  EXPECT_FALSE(message.optional_foreign_message      ().has_c());
+  EXPECT_FALSE(message.optional_import_message       ().has_d());
+  EXPECT_FALSE(message.optional_public_import_message().has_e());
+  EXPECT_FALSE(message.optional_lazy_message         ().has_bb());
+
+  EXPECT_EQ(0, message.optionalgroup                 ().a());
+  EXPECT_EQ(0, message.optional_nested_message       ().bb());
+  EXPECT_EQ(0, message.optional_foreign_message      ().c());
+  EXPECT_EQ(0, message.optional_import_message       ().d());
+  EXPECT_EQ(0, message.optional_public_import_message().e());
+  EXPECT_EQ(0, message.optional_lazy_message         ().bb());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.optional_import_enum ());
+
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.repeated_int32_size   ());
+  EXPECT_EQ(0, message.repeated_int64_size   ());
+  EXPECT_EQ(0, message.repeated_uint32_size  ());
+  EXPECT_EQ(0, message.repeated_uint64_size  ());
+  EXPECT_EQ(0, message.repeated_sint32_size  ());
+  EXPECT_EQ(0, message.repeated_sint64_size  ());
+  EXPECT_EQ(0, message.repeated_fixed32_size ());
+  EXPECT_EQ(0, message.repeated_fixed64_size ());
+  EXPECT_EQ(0, message.repeated_sfixed32_size());
+  EXPECT_EQ(0, message.repeated_sfixed64_size());
+  EXPECT_EQ(0, message.repeated_float_size   ());
+  EXPECT_EQ(0, message.repeated_double_size  ());
+  EXPECT_EQ(0, message.repeated_bool_size    ());
+  EXPECT_EQ(0, message.repeated_string_size  ());
+  EXPECT_EQ(0, message.repeated_bytes_size   ());
+
+  EXPECT_EQ(0, message.repeatedgroup_size           ());
+  EXPECT_EQ(0, message.repeated_nested_message_size ());
+  EXPECT_EQ(0, message.repeated_foreign_message_size());
+  EXPECT_EQ(0, message.repeated_import_message_size ());
+  EXPECT_EQ(0, message.repeated_lazy_message_size   ());
+  EXPECT_EQ(0, message.repeated_nested_enum_size    ());
+  EXPECT_EQ(0, message.repeated_foreign_enum_size   ());
+  EXPECT_EQ(0, message.repeated_import_enum_size    ());
+
+  EXPECT_EQ(0, message.repeated_string_piece_size());
+  EXPECT_EQ(0, message.repeated_cord_size());
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.has_default_int32   ());
+  EXPECT_FALSE(message.has_default_int64   ());
+  EXPECT_FALSE(message.has_default_uint32  ());
+  EXPECT_FALSE(message.has_default_uint64  ());
+  EXPECT_FALSE(message.has_default_sint32  ());
+  EXPECT_FALSE(message.has_default_sint64  ());
+  EXPECT_FALSE(message.has_default_fixed32 ());
+  EXPECT_FALSE(message.has_default_fixed64 ());
+  EXPECT_FALSE(message.has_default_sfixed32());
+  EXPECT_FALSE(message.has_default_sfixed64());
+  EXPECT_FALSE(message.has_default_float   ());
+  EXPECT_FALSE(message.has_default_double  ());
+  EXPECT_FALSE(message.has_default_bool    ());
+  EXPECT_FALSE(message.has_default_string  ());
+  EXPECT_FALSE(message.has_default_bytes   ());
+
+  EXPECT_FALSE(message.has_default_nested_enum ());
+  EXPECT_FALSE(message.has_default_foreign_enum());
+  EXPECT_FALSE(message.has_default_import_enum ());
+
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.default_int32   ());
+  EXPECT_EQ( 42    , message.default_int64   ());
+  EXPECT_EQ( 43    , message.default_uint32  ());
+  EXPECT_EQ( 44    , message.default_uint64  ());
+  EXPECT_EQ(-45    , message.default_sint32  ());
+  EXPECT_EQ( 46    , message.default_sint64  ());
+  EXPECT_EQ( 47    , message.default_fixed32 ());
+  EXPECT_EQ( 48    , message.default_fixed64 ());
+  EXPECT_EQ( 49    , message.default_sfixed32());
+  EXPECT_EQ(-50    , message.default_sfixed64());
+  EXPECT_EQ( 51.5  , message.default_float   ());
+  EXPECT_EQ( 52e3  , message.default_double  ());
+  EXPECT_TRUE(       message.default_bool    ());
+  EXPECT_EQ("hello", message.default_string  ());
+  EXPECT_EQ("world", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.default_import_enum ());
+
+
+  EXPECT_FALSE(message.has_oneof_uint32        ());
+  EXPECT_FALSE(message.has_oneof_nested_message());
+  EXPECT_FALSE(message.has_oneof_string        ());
+  EXPECT_FALSE(message.has_oneof_bytes         ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectRepeatedFieldsModified(
+    const unittest::TestAllTypes& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  ASSERT_EQ(2, message.repeated_string_piece_size());
+  ASSERT_EQ(2, message.repeated_cord_size());
+#endif
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_TRUE(     message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0));
+
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.repeated_int32   (1));
+  EXPECT_EQ(502  , message.repeated_int64   (1));
+  EXPECT_EQ(503  , message.repeated_uint32  (1));
+  EXPECT_EQ(504  , message.repeated_uint64  (1));
+  EXPECT_EQ(505  , message.repeated_sint32  (1));
+  EXPECT_EQ(506  , message.repeated_sint64  (1));
+  EXPECT_EQ(507  , message.repeated_fixed32 (1));
+  EXPECT_EQ(508  , message.repeated_fixed64 (1));
+  EXPECT_EQ(509  , message.repeated_sfixed32(1));
+  EXPECT_EQ(510  , message.repeated_sfixed64(1));
+  EXPECT_EQ(511  , message.repeated_float   (1));
+  EXPECT_EQ(512  , message.repeated_double  (1));
+  EXPECT_TRUE(     message.repeated_bool    (1));
+  EXPECT_EQ("515", message.repeated_string  (1));
+  EXPECT_EQ("516", message.repeated_bytes   (1));
+
+  EXPECT_EQ(517, message.repeatedgroup           (1).a());
+  EXPECT_EQ(518, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(519, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(520, message.repeated_import_message (1).d());
+  EXPECT_EQ(527, message.repeated_lazy_message   (1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.repeated_import_enum (1));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::SetPackedFields(unittest::TestPackedTypes* message) {
+  message->add_packed_int32   (601);
+  message->add_packed_int64   (602);
+  message->add_packed_uint32  (603);
+  message->add_packed_uint64  (604);
+  message->add_packed_sint32  (605);
+  message->add_packed_sint64  (606);
+  message->add_packed_fixed32 (607);
+  message->add_packed_fixed64 (608);
+  message->add_packed_sfixed32(609);
+  message->add_packed_sfixed64(610);
+  message->add_packed_float   (611);
+  message->add_packed_double  (612);
+  message->add_packed_bool    (true);
+  message->add_packed_enum    (unittest::FOREIGN_BAR);
+  // add a second one of each field
+  message->add_packed_int32   (701);
+  message->add_packed_int64   (702);
+  message->add_packed_uint32  (703);
+  message->add_packed_uint64  (704);
+  message->add_packed_sint32  (705);
+  message->add_packed_sint64  (706);
+  message->add_packed_fixed32 (707);
+  message->add_packed_fixed64 (708);
+  message->add_packed_sfixed32(709);
+  message->add_packed_sfixed64(710);
+  message->add_packed_float   (711);
+  message->add_packed_double  (712);
+  message->add_packed_bool    (false);
+  message->add_packed_enum    (unittest::FOREIGN_BAZ);
+}
+
+void TestUtil::SetUnpackedFields(unittest::TestUnpackedTypes* message) {
+  // The values applied here must match those of SetPackedFields.
+
+  message->add_unpacked_int32   (601);
+  message->add_unpacked_int64   (602);
+  message->add_unpacked_uint32  (603);
+  message->add_unpacked_uint64  (604);
+  message->add_unpacked_sint32  (605);
+  message->add_unpacked_sint64  (606);
+  message->add_unpacked_fixed32 (607);
+  message->add_unpacked_fixed64 (608);
+  message->add_unpacked_sfixed32(609);
+  message->add_unpacked_sfixed64(610);
+  message->add_unpacked_float   (611);
+  message->add_unpacked_double  (612);
+  message->add_unpacked_bool    (true);
+  message->add_unpacked_enum    (unittest::FOREIGN_BAR);
+  // add a second one of each field
+  message->add_unpacked_int32   (701);
+  message->add_unpacked_int64   (702);
+  message->add_unpacked_uint32  (703);
+  message->add_unpacked_uint64  (704);
+  message->add_unpacked_sint32  (705);
+  message->add_unpacked_sint64  (706);
+  message->add_unpacked_fixed32 (707);
+  message->add_unpacked_fixed64 (708);
+  message->add_unpacked_sfixed32(709);
+  message->add_unpacked_sfixed64(710);
+  message->add_unpacked_float   (711);
+  message->add_unpacked_double  (712);
+  message->add_unpacked_bool    (false);
+  message->add_unpacked_enum    (unittest::FOREIGN_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyPackedFields(unittest::TestPackedTypes* message) {
+  message->set_packed_int32   (1, 801);
+  message->set_packed_int64   (1, 802);
+  message->set_packed_uint32  (1, 803);
+  message->set_packed_uint64  (1, 804);
+  message->set_packed_sint32  (1, 805);
+  message->set_packed_sint64  (1, 806);
+  message->set_packed_fixed32 (1, 807);
+  message->set_packed_fixed64 (1, 808);
+  message->set_packed_sfixed32(1, 809);
+  message->set_packed_sfixed64(1, 810);
+  message->set_packed_float   (1, 811);
+  message->set_packed_double  (1, 812);
+  message->set_packed_bool    (1, true);
+  message->set_packed_enum    (1, unittest::FOREIGN_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) {
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_TRUE(     message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0));
+
+  EXPECT_EQ(701  , message.packed_int32   (1));
+  EXPECT_EQ(702  , message.packed_int64   (1));
+  EXPECT_EQ(703  , message.packed_uint32  (1));
+  EXPECT_EQ(704  , message.packed_uint64  (1));
+  EXPECT_EQ(705  , message.packed_sint32  (1));
+  EXPECT_EQ(706  , message.packed_sint64  (1));
+  EXPECT_EQ(707  , message.packed_fixed32 (1));
+  EXPECT_EQ(708  , message.packed_fixed64 (1));
+  EXPECT_EQ(709  , message.packed_sfixed32(1));
+  EXPECT_EQ(710  , message.packed_sfixed64(1));
+  EXPECT_EQ(711  , message.packed_float   (1));
+  EXPECT_EQ(712  , message.packed_double  (1));
+  EXPECT_FALSE(    message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1));
+}
+
+void TestUtil::ExpectUnpackedFieldsSet(
+    const unittest::TestUnpackedTypes& message) {
+  // The values expected here must match those of ExpectPackedFieldsSet.
+
+  ASSERT_EQ(2, message.unpacked_int32_size   ());
+  ASSERT_EQ(2, message.unpacked_int64_size   ());
+  ASSERT_EQ(2, message.unpacked_uint32_size  ());
+  ASSERT_EQ(2, message.unpacked_uint64_size  ());
+  ASSERT_EQ(2, message.unpacked_sint32_size  ());
+  ASSERT_EQ(2, message.unpacked_sint64_size  ());
+  ASSERT_EQ(2, message.unpacked_fixed32_size ());
+  ASSERT_EQ(2, message.unpacked_fixed64_size ());
+  ASSERT_EQ(2, message.unpacked_sfixed32_size());
+  ASSERT_EQ(2, message.unpacked_sfixed64_size());
+  ASSERT_EQ(2, message.unpacked_float_size   ());
+  ASSERT_EQ(2, message.unpacked_double_size  ());
+  ASSERT_EQ(2, message.unpacked_bool_size    ());
+  ASSERT_EQ(2, message.unpacked_enum_size    ());
+
+  EXPECT_EQ(601  , message.unpacked_int32   (0));
+  EXPECT_EQ(602  , message.unpacked_int64   (0));
+  EXPECT_EQ(603  , message.unpacked_uint32  (0));
+  EXPECT_EQ(604  , message.unpacked_uint64  (0));
+  EXPECT_EQ(605  , message.unpacked_sint32  (0));
+  EXPECT_EQ(606  , message.unpacked_sint64  (0));
+  EXPECT_EQ(607  , message.unpacked_fixed32 (0));
+  EXPECT_EQ(608  , message.unpacked_fixed64 (0));
+  EXPECT_EQ(609  , message.unpacked_sfixed32(0));
+  EXPECT_EQ(610  , message.unpacked_sfixed64(0));
+  EXPECT_EQ(611  , message.unpacked_float   (0));
+  EXPECT_EQ(612  , message.unpacked_double  (0));
+  EXPECT_TRUE(     message.unpacked_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR, message.unpacked_enum(0));
+
+  EXPECT_EQ(701  , message.unpacked_int32   (1));
+  EXPECT_EQ(702  , message.unpacked_int64   (1));
+  EXPECT_EQ(703  , message.unpacked_uint32  (1));
+  EXPECT_EQ(704  , message.unpacked_uint64  (1));
+  EXPECT_EQ(705  , message.unpacked_sint32  (1));
+  EXPECT_EQ(706  , message.unpacked_sint64  (1));
+  EXPECT_EQ(707  , message.unpacked_fixed32 (1));
+  EXPECT_EQ(708  , message.unpacked_fixed64 (1));
+  EXPECT_EQ(709  , message.unpacked_sfixed32(1));
+  EXPECT_EQ(710  , message.unpacked_sfixed64(1));
+  EXPECT_EQ(711  , message.unpacked_float   (1));
+  EXPECT_EQ(712  , message.unpacked_double  (1));
+  EXPECT_FALSE(    message.unpacked_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ, message.unpacked_enum(1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedClear(
+    const unittest::TestPackedTypes& message) {
+  // Packed repeated fields are empty.
+  EXPECT_EQ(0, message.packed_int32_size   ());
+  EXPECT_EQ(0, message.packed_int64_size   ());
+  EXPECT_EQ(0, message.packed_uint32_size  ());
+  EXPECT_EQ(0, message.packed_uint64_size  ());
+  EXPECT_EQ(0, message.packed_sint32_size  ());
+  EXPECT_EQ(0, message.packed_sint64_size  ());
+  EXPECT_EQ(0, message.packed_fixed32_size ());
+  EXPECT_EQ(0, message.packed_fixed64_size ());
+  EXPECT_EQ(0, message.packed_sfixed32_size());
+  EXPECT_EQ(0, message.packed_sfixed64_size());
+  EXPECT_EQ(0, message.packed_float_size   ());
+  EXPECT_EQ(0, message.packed_double_size  ());
+  EXPECT_EQ(0, message.packed_bool_size    ());
+  EXPECT_EQ(0, message.packed_enum_size    ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedFieldsModified(
+    const unittest::TestPackedTypes& message) {
+  // Do the same for packed repeated fields.
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_TRUE(     message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0));
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.packed_int32   (1));
+  EXPECT_EQ(802  , message.packed_int64   (1));
+  EXPECT_EQ(803  , message.packed_uint32  (1));
+  EXPECT_EQ(804  , message.packed_uint64  (1));
+  EXPECT_EQ(805  , message.packed_sint32  (1));
+  EXPECT_EQ(806  , message.packed_sint64  (1));
+  EXPECT_EQ(807  , message.packed_fixed32 (1));
+  EXPECT_EQ(808  , message.packed_fixed64 (1));
+  EXPECT_EQ(809  , message.packed_sfixed32(1));
+  EXPECT_EQ(810  , message.packed_sfixed64(1));
+  EXPECT_EQ(811  , message.packed_float   (1));
+  EXPECT_EQ(812  , message.packed_double  (1));
+  EXPECT_TRUE(     message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_FOO, message.packed_enum(1));
+}
+
+// ===================================================================
+// Extensions
+//
+// All this code is exactly equivalent to the above code except that it's
+// manipulating extension fields instead of normal ones.
+//
+// I gave up on the 80-char limit here.  Sorry.
+
+void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) {
+  message->SetExtension(unittest::optional_int32_extension   , 101);
+  message->SetExtension(unittest::optional_int64_extension   , 102);
+  message->SetExtension(unittest::optional_uint32_extension  , 103);
+  message->SetExtension(unittest::optional_uint64_extension  , 104);
+  message->SetExtension(unittest::optional_sint32_extension  , 105);
+  message->SetExtension(unittest::optional_sint64_extension  , 106);
+  message->SetExtension(unittest::optional_fixed32_extension , 107);
+  message->SetExtension(unittest::optional_fixed64_extension , 108);
+  message->SetExtension(unittest::optional_sfixed32_extension, 109);
+  message->SetExtension(unittest::optional_sfixed64_extension, 110);
+  message->SetExtension(unittest::optional_float_extension   , 111);
+  message->SetExtension(unittest::optional_double_extension  , 112);
+  message->SetExtension(unittest::optional_bool_extension    , true);
+  message->SetExtension(unittest::optional_string_extension  , "115");
+  message->SetExtension(unittest::optional_bytes_extension   , "116");
+
+  message->MutableExtension(unittest::optionalgroup_extension           )->set_a(117);
+  message->MutableExtension(unittest::optional_nested_message_extension )->set_bb(118);
+  message->MutableExtension(unittest::optional_foreign_message_extension)->set_c(119);
+  message->MutableExtension(unittest::optional_import_message_extension )->set_d(120);
+
+  message->SetExtension(unittest::optional_nested_enum_extension , unittest::TestAllTypes::BAZ);
+  message->SetExtension(unittest::optional_foreign_enum_extension, unittest::FOREIGN_BAZ      );
+  message->SetExtension(unittest::optional_import_enum_extension , unittest_import::IMPORT_BAZ);
+
+  message->SetExtension(unittest::optional_string_piece_extension, "124");
+  message->SetExtension(unittest::optional_cord_extension, "125");
+
+  message->MutableExtension(unittest::optional_public_import_message_extension)->set_e(126);
+  message->MutableExtension(unittest::optional_lazy_message_extension)->set_bb(127);
+
+  // -----------------------------------------------------------------
+
+  message->AddExtension(unittest::repeated_int32_extension   , 201);
+  message->AddExtension(unittest::repeated_int64_extension   , 202);
+  message->AddExtension(unittest::repeated_uint32_extension  , 203);
+  message->AddExtension(unittest::repeated_uint64_extension  , 204);
+  message->AddExtension(unittest::repeated_sint32_extension  , 205);
+  message->AddExtension(unittest::repeated_sint64_extension  , 206);
+  message->AddExtension(unittest::repeated_fixed32_extension , 207);
+  message->AddExtension(unittest::repeated_fixed64_extension , 208);
+  message->AddExtension(unittest::repeated_sfixed32_extension, 209);
+  message->AddExtension(unittest::repeated_sfixed64_extension, 210);
+  message->AddExtension(unittest::repeated_float_extension   , 211);
+  message->AddExtension(unittest::repeated_double_extension  , 212);
+  message->AddExtension(unittest::repeated_bool_extension    , true);
+  message->AddExtension(unittest::repeated_string_extension  , "215");
+  message->AddExtension(unittest::repeated_bytes_extension   , "216");
+
+  message->AddExtension(unittest::repeatedgroup_extension           )->set_a(217);
+  message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(218);
+  message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(219);
+  message->AddExtension(unittest::repeated_import_message_extension )->set_d(220);
+  message->AddExtension(unittest::repeated_lazy_message_extension   )->set_bb(227);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAR);
+  message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAR      );
+  message->AddExtension(unittest::repeated_import_enum_extension , unittest_import::IMPORT_BAR);
+
+  message->AddExtension(unittest::repeated_string_piece_extension, "224");
+  message->AddExtension(unittest::repeated_cord_extension, "225");
+
+  // Add a second one of each field.
+  message->AddExtension(unittest::repeated_int32_extension   , 301);
+  message->AddExtension(unittest::repeated_int64_extension   , 302);
+  message->AddExtension(unittest::repeated_uint32_extension  , 303);
+  message->AddExtension(unittest::repeated_uint64_extension  , 304);
+  message->AddExtension(unittest::repeated_sint32_extension  , 305);
+  message->AddExtension(unittest::repeated_sint64_extension  , 306);
+  message->AddExtension(unittest::repeated_fixed32_extension , 307);
+  message->AddExtension(unittest::repeated_fixed64_extension , 308);
+  message->AddExtension(unittest::repeated_sfixed32_extension, 309);
+  message->AddExtension(unittest::repeated_sfixed64_extension, 310);
+  message->AddExtension(unittest::repeated_float_extension   , 311);
+  message->AddExtension(unittest::repeated_double_extension  , 312);
+  message->AddExtension(unittest::repeated_bool_extension    , false);
+  message->AddExtension(unittest::repeated_string_extension  , "315");
+  message->AddExtension(unittest::repeated_bytes_extension   , "316");
+
+  message->AddExtension(unittest::repeatedgroup_extension           )->set_a(317);
+  message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(318);
+  message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(319);
+  message->AddExtension(unittest::repeated_import_message_extension )->set_d(320);
+  message->AddExtension(unittest::repeated_lazy_message_extension   )->set_bb(327);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAZ);
+  message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAZ      );
+  message->AddExtension(unittest::repeated_import_enum_extension , unittest_import::IMPORT_BAZ);
+
+  message->AddExtension(unittest::repeated_string_piece_extension, "324");
+  message->AddExtension(unittest::repeated_cord_extension, "325");
+
+  // -----------------------------------------------------------------
+
+  message->SetExtension(unittest::default_int32_extension   , 401);
+  message->SetExtension(unittest::default_int64_extension   , 402);
+  message->SetExtension(unittest::default_uint32_extension  , 403);
+  message->SetExtension(unittest::default_uint64_extension  , 404);
+  message->SetExtension(unittest::default_sint32_extension  , 405);
+  message->SetExtension(unittest::default_sint64_extension  , 406);
+  message->SetExtension(unittest::default_fixed32_extension , 407);
+  message->SetExtension(unittest::default_fixed64_extension , 408);
+  message->SetExtension(unittest::default_sfixed32_extension, 409);
+  message->SetExtension(unittest::default_sfixed64_extension, 410);
+  message->SetExtension(unittest::default_float_extension   , 411);
+  message->SetExtension(unittest::default_double_extension  , 412);
+  message->SetExtension(unittest::default_bool_extension    , false);
+  message->SetExtension(unittest::default_string_extension  , "415");
+  message->SetExtension(unittest::default_bytes_extension   , "416");
+
+  message->SetExtension(unittest::default_nested_enum_extension , unittest::TestAllTypes::FOO);
+  message->SetExtension(unittest::default_foreign_enum_extension, unittest::FOREIGN_FOO      );
+  message->SetExtension(unittest::default_import_enum_extension , unittest_import::IMPORT_FOO);
+
+  message->SetExtension(unittest::default_string_piece_extension, "424");
+  message->SetExtension(unittest::default_cord_extension, "425");
+
+  SetOneofFields(message);
+}
+
+void TestUtil::SetOneofFields(unittest::TestAllExtensions* message) {
+  message->SetExtension(unittest::oneof_uint32_extension, 601);
+  message->MutableExtension(unittest::oneof_nested_message_extension)->set_bb(602);
+  message->SetExtension(unittest::oneof_string_extension, "603");
+  message->SetExtension(unittest::oneof_bytes_extension, "604");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::SetAllFieldsAndExtensions(
+    unittest::TestFieldOrderings* message) {
+  GOOGLE_CHECK(message);
+  message->set_my_int(1);
+  message->set_my_string("foo");
+  message->set_my_float(1.0);
+  message->SetExtension(unittest::my_extension_int, 23);
+  message->SetExtension(unittest::my_extension_string, "bar");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyRepeatedExtensions(unittest::TestAllExtensions* message) {
+  message->SetExtension(unittest::repeated_int32_extension   , 1, 501);
+  message->SetExtension(unittest::repeated_int64_extension   , 1, 502);
+  message->SetExtension(unittest::repeated_uint32_extension  , 1, 503);
+  message->SetExtension(unittest::repeated_uint64_extension  , 1, 504);
+  message->SetExtension(unittest::repeated_sint32_extension  , 1, 505);
+  message->SetExtension(unittest::repeated_sint64_extension  , 1, 506);
+  message->SetExtension(unittest::repeated_fixed32_extension , 1, 507);
+  message->SetExtension(unittest::repeated_fixed64_extension , 1, 508);
+  message->SetExtension(unittest::repeated_sfixed32_extension, 1, 509);
+  message->SetExtension(unittest::repeated_sfixed64_extension, 1, 510);
+  message->SetExtension(unittest::repeated_float_extension   , 1, 511);
+  message->SetExtension(unittest::repeated_double_extension  , 1, 512);
+  message->SetExtension(unittest::repeated_bool_extension    , 1, true);
+  message->SetExtension(unittest::repeated_string_extension  , 1, "515");
+  message->SetExtension(unittest::repeated_bytes_extension   , 1, "516");
+
+  message->MutableExtension(unittest::repeatedgroup_extension           , 1)->set_a(517);
+  message->MutableExtension(unittest::repeated_nested_message_extension , 1)->set_bb(518);
+  message->MutableExtension(unittest::repeated_foreign_message_extension, 1)->set_c(519);
+  message->MutableExtension(unittest::repeated_import_message_extension , 1)->set_d(520);
+  message->MutableExtension(unittest::repeated_lazy_message_extension   , 1)->set_bb(527);
+
+  message->SetExtension(unittest::repeated_nested_enum_extension , 1, unittest::TestAllTypes::FOO);
+  message->SetExtension(unittest::repeated_foreign_enum_extension, 1, unittest::FOREIGN_FOO      );
+  message->SetExtension(unittest::repeated_import_enum_extension , 1, unittest_import::IMPORT_FOO);
+
+  message->SetExtension(unittest::repeated_string_piece_extension, 1, "524");
+  message->SetExtension(unittest::repeated_cord_extension, 1, "525");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectAllExtensionsSet(
+    const unittest::TestAllExtensions& message) {
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension    ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension                 ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension      ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension         ));
+
+  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension                 ).has_a());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension       ).has_bb());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension      ).has_c());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension       ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension         ).has_bb());
+
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::optional_string_piece_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_cord_extension));
+
+  EXPECT_EQ(101  , message.GetExtension(unittest::optional_int32_extension   ));
+  EXPECT_EQ(102  , message.GetExtension(unittest::optional_int64_extension   ));
+  EXPECT_EQ(103  , message.GetExtension(unittest::optional_uint32_extension  ));
+  EXPECT_EQ(104  , message.GetExtension(unittest::optional_uint64_extension  ));
+  EXPECT_EQ(105  , message.GetExtension(unittest::optional_sint32_extension  ));
+  EXPECT_EQ(106  , message.GetExtension(unittest::optional_sint64_extension  ));
+  EXPECT_EQ(107  , message.GetExtension(unittest::optional_fixed32_extension ));
+  EXPECT_EQ(108  , message.GetExtension(unittest::optional_fixed64_extension ));
+  EXPECT_EQ(109  , message.GetExtension(unittest::optional_sfixed32_extension));
+  EXPECT_EQ(110  , message.GetExtension(unittest::optional_sfixed64_extension));
+  EXPECT_EQ(111  , message.GetExtension(unittest::optional_float_extension   ));
+  EXPECT_EQ(112  , message.GetExtension(unittest::optional_double_extension  ));
+  EXPECT_TRUE(     message.GetExtension(unittest::optional_bool_extension    ));
+  EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension  ));
+  EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension   ));
+
+  EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension           ).a());
+  EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension ).bb());
+  EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension).c());
+  EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension ).d());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::optional_nested_enum_extension ));
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.GetExtension(unittest::optional_foreign_enum_extension));
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::optional_import_enum_extension ));
+
+  EXPECT_EQ("124", message.GetExtension(unittest::optional_string_piece_extension));
+  EXPECT_EQ("125", message.GetExtension(unittest::optional_cord_extension));
+  EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension ).e());
+  EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension).bb());
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension));
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension  , 0));
+  EXPECT_TRUE(     message.GetExtension(unittest::repeated_bool_extension    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+  EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+  EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
+
+  EXPECT_EQ(301  , message.GetExtension(unittest::repeated_int32_extension   , 1));
+  EXPECT_EQ(302  , message.GetExtension(unittest::repeated_int64_extension   , 1));
+  EXPECT_EQ(303  , message.GetExtension(unittest::repeated_uint32_extension  , 1));
+  EXPECT_EQ(304  , message.GetExtension(unittest::repeated_uint64_extension  , 1));
+  EXPECT_EQ(305  , message.GetExtension(unittest::repeated_sint32_extension  , 1));
+  EXPECT_EQ(306  , message.GetExtension(unittest::repeated_sint64_extension  , 1));
+  EXPECT_EQ(307  , message.GetExtension(unittest::repeated_fixed32_extension , 1));
+  EXPECT_EQ(308  , message.GetExtension(unittest::repeated_fixed64_extension , 1));
+  EXPECT_EQ(309  , message.GetExtension(unittest::repeated_sfixed32_extension, 1));
+  EXPECT_EQ(310  , message.GetExtension(unittest::repeated_sfixed64_extension, 1));
+  EXPECT_EQ(311  , message.GetExtension(unittest::repeated_float_extension   , 1));
+  EXPECT_EQ(312  , message.GetExtension(unittest::repeated_double_extension  , 1));
+  EXPECT_FALSE(    message.GetExtension(unittest::repeated_bool_extension    , 1));
+  EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension  , 1));
+  EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension   , 1));
+
+  EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension           , 1).a());
+  EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
+  EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
+  EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::repeated_import_enum_extension , 1));
+
+  EXPECT_EQ("324", message.GetExtension(unittest::repeated_string_piece_extension, 1));
+  EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 1));
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::default_float_extension   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_double_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension    ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_string_extension  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_string_piece_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::default_cord_extension));
+
+  EXPECT_EQ(401  , message.GetExtension(unittest::default_int32_extension   ));
+  EXPECT_EQ(402  , message.GetExtension(unittest::default_int64_extension   ));
+  EXPECT_EQ(403  , message.GetExtension(unittest::default_uint32_extension  ));
+  EXPECT_EQ(404  , message.GetExtension(unittest::default_uint64_extension  ));
+  EXPECT_EQ(405  , message.GetExtension(unittest::default_sint32_extension  ));
+  EXPECT_EQ(406  , message.GetExtension(unittest::default_sint64_extension  ));
+  EXPECT_EQ(407  , message.GetExtension(unittest::default_fixed32_extension ));
+  EXPECT_EQ(408  , message.GetExtension(unittest::default_fixed64_extension ));
+  EXPECT_EQ(409  , message.GetExtension(unittest::default_sfixed32_extension));
+  EXPECT_EQ(410  , message.GetExtension(unittest::default_sfixed64_extension));
+  EXPECT_EQ(411  , message.GetExtension(unittest::default_float_extension   ));
+  EXPECT_EQ(412  , message.GetExtension(unittest::default_double_extension  ));
+  EXPECT_FALSE(    message.GetExtension(unittest::default_bool_extension    ));
+  EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension  ));
+  EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension   ));
+
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::default_nested_enum_extension ));
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.GetExtension(unittest::default_foreign_enum_extension));
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::default_import_enum_extension ));
+
+  EXPECT_EQ("424", message.GetExtension(unittest::default_string_piece_extension));
+  EXPECT_EQ("425", message.GetExtension(unittest::default_cord_extension));
+
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension));
+  EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb());
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension));
+
+  EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension));
+  EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension).bb());
+  EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension));
+  EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectExtensionsClear(
+    const unittest::TestAllExtensions& message) {
+  string serialized;
+  ASSERT_TRUE(message.SerializeToString(&serialized));
+  EXPECT_EQ("", serialized);
+  EXPECT_EQ(0, message.ByteSize());
+
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension    ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension                 ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension      ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension         ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optional_string_piece_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_cord_extension));
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int32_extension   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int64_extension   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint32_extension  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint64_extension  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint32_extension  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint64_extension  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed32_extension ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed64_extension ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed32_extension));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed64_extension));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_float_extension   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_double_extension  ));
+  EXPECT_FALSE(    message.GetExtension(unittest::optional_bool_extension    ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_string_extension  ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_bytes_extension   ));
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension                 ).has_a());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension       ).has_bb());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension      ).has_c());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension       ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension         ).has_bb());
+
+  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension                 ).a());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension       ).bb());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension      ).c());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension       ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension).e());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension         ).bb());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::optional_nested_enum_extension ));
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.GetExtension(unittest::optional_foreign_enum_extension));
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::optional_import_enum_extension ));
+
+  EXPECT_EQ("", message.GetExtension(unittest::optional_string_piece_extension));
+  EXPECT_EQ("", message.GetExtension(unittest::optional_cord_extension));
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension   ));
+
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
+
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_piece_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_cord_extension));
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::default_float_extension   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_double_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension    ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_string_extension  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::default_string_piece_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::default_cord_extension));
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.GetExtension(unittest::default_int32_extension   ));
+  EXPECT_EQ( 42    , message.GetExtension(unittest::default_int64_extension   ));
+  EXPECT_EQ( 43    , message.GetExtension(unittest::default_uint32_extension  ));
+  EXPECT_EQ( 44    , message.GetExtension(unittest::default_uint64_extension  ));
+  EXPECT_EQ(-45    , message.GetExtension(unittest::default_sint32_extension  ));
+  EXPECT_EQ( 46    , message.GetExtension(unittest::default_sint64_extension  ));
+  EXPECT_EQ( 47    , message.GetExtension(unittest::default_fixed32_extension ));
+  EXPECT_EQ( 48    , message.GetExtension(unittest::default_fixed64_extension ));
+  EXPECT_EQ( 49    , message.GetExtension(unittest::default_sfixed32_extension));
+  EXPECT_EQ(-50    , message.GetExtension(unittest::default_sfixed64_extension));
+  EXPECT_EQ( 51.5  , message.GetExtension(unittest::default_float_extension   ));
+  EXPECT_EQ( 52e3  , message.GetExtension(unittest::default_double_extension  ));
+  EXPECT_TRUE(       message.GetExtension(unittest::default_bool_extension    ));
+  EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension  ));
+  EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension   ));
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::default_nested_enum_extension ));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::default_foreign_enum_extension));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::default_import_enum_extension ));
+
+  EXPECT_EQ("abc", message.GetExtension(unittest::default_string_piece_extension));
+  EXPECT_EQ("123", message.GetExtension(unittest::default_cord_extension));
+
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension));
+  EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb());
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectRepeatedExtensionsModified(
+    const unittest::TestAllExtensions& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension));
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension  , 0));
+  EXPECT_TRUE(     message.GetExtension(unittest::repeated_bool_extension    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+  EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+  EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.GetExtension(unittest::repeated_int32_extension   , 1));
+  EXPECT_EQ(502  , message.GetExtension(unittest::repeated_int64_extension   , 1));
+  EXPECT_EQ(503  , message.GetExtension(unittest::repeated_uint32_extension  , 1));
+  EXPECT_EQ(504  , message.GetExtension(unittest::repeated_uint64_extension  , 1));
+  EXPECT_EQ(505  , message.GetExtension(unittest::repeated_sint32_extension  , 1));
+  EXPECT_EQ(506  , message.GetExtension(unittest::repeated_sint64_extension  , 1));
+  EXPECT_EQ(507  , message.GetExtension(unittest::repeated_fixed32_extension , 1));
+  EXPECT_EQ(508  , message.GetExtension(unittest::repeated_fixed64_extension , 1));
+  EXPECT_EQ(509  , message.GetExtension(unittest::repeated_sfixed32_extension, 1));
+  EXPECT_EQ(510  , message.GetExtension(unittest::repeated_sfixed64_extension, 1));
+  EXPECT_EQ(511  , message.GetExtension(unittest::repeated_float_extension   , 1));
+  EXPECT_EQ(512  , message.GetExtension(unittest::repeated_double_extension  , 1));
+  EXPECT_TRUE(     message.GetExtension(unittest::repeated_bool_extension    , 1));
+  EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension  , 1));
+  EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension   , 1));
+
+  EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension           , 1).a());
+  EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
+  EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
+  EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
+  EXPECT_EQ(unittest::FOREIGN_FOO      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
+  EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::repeated_import_enum_extension , 1));
+
+  EXPECT_EQ("524", message.GetExtension(unittest::repeated_string_piece_extension, 1));
+  EXPECT_EQ("525", message.GetExtension(unittest::repeated_cord_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::SetPackedExtensions(unittest::TestPackedExtensions* message) {
+  message->AddExtension(unittest::packed_int32_extension   , 601);
+  message->AddExtension(unittest::packed_int64_extension   , 602);
+  message->AddExtension(unittest::packed_uint32_extension  , 603);
+  message->AddExtension(unittest::packed_uint64_extension  , 604);
+  message->AddExtension(unittest::packed_sint32_extension  , 605);
+  message->AddExtension(unittest::packed_sint64_extension  , 606);
+  message->AddExtension(unittest::packed_fixed32_extension , 607);
+  message->AddExtension(unittest::packed_fixed64_extension , 608);
+  message->AddExtension(unittest::packed_sfixed32_extension, 609);
+  message->AddExtension(unittest::packed_sfixed64_extension, 610);
+  message->AddExtension(unittest::packed_float_extension   , 611);
+  message->AddExtension(unittest::packed_double_extension  , 612);
+  message->AddExtension(unittest::packed_bool_extension    , true);
+  message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAR);
+  // add a second one of each field
+  message->AddExtension(unittest::packed_int32_extension   , 701);
+  message->AddExtension(unittest::packed_int64_extension   , 702);
+  message->AddExtension(unittest::packed_uint32_extension  , 703);
+  message->AddExtension(unittest::packed_uint64_extension  , 704);
+  message->AddExtension(unittest::packed_sint32_extension  , 705);
+  message->AddExtension(unittest::packed_sint64_extension  , 706);
+  message->AddExtension(unittest::packed_fixed32_extension , 707);
+  message->AddExtension(unittest::packed_fixed64_extension , 708);
+  message->AddExtension(unittest::packed_sfixed32_extension, 709);
+  message->AddExtension(unittest::packed_sfixed64_extension, 710);
+  message->AddExtension(unittest::packed_float_extension   , 711);
+  message->AddExtension(unittest::packed_double_extension  , 712);
+  message->AddExtension(unittest::packed_bool_extension    , false);
+  message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyPackedExtensions(unittest::TestPackedExtensions* message) {
+  message->SetExtension(unittest::packed_int32_extension   , 1, 801);
+  message->SetExtension(unittest::packed_int64_extension   , 1, 802);
+  message->SetExtension(unittest::packed_uint32_extension  , 1, 803);
+  message->SetExtension(unittest::packed_uint64_extension  , 1, 804);
+  message->SetExtension(unittest::packed_sint32_extension  , 1, 805);
+  message->SetExtension(unittest::packed_sint64_extension  , 1, 806);
+  message->SetExtension(unittest::packed_fixed32_extension , 1, 807);
+  message->SetExtension(unittest::packed_fixed64_extension , 1, 808);
+  message->SetExtension(unittest::packed_sfixed32_extension, 1, 809);
+  message->SetExtension(unittest::packed_sfixed64_extension, 1, 810);
+  message->SetExtension(unittest::packed_float_extension   , 1, 811);
+  message->SetExtension(unittest::packed_double_extension  , 1, 812);
+  message->SetExtension(unittest::packed_bool_extension    , 1, true);
+  message->SetExtension(unittest::packed_enum_extension    , 1,
+                        unittest::FOREIGN_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsSet(
+    const unittest::TestPackedExtensions& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension    ));
+
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension  , 0));
+  EXPECT_TRUE(     message.GetExtension(unittest::packed_bool_extension    , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR,
+            message.GetExtension(unittest::packed_enum_extension, 0));
+  EXPECT_EQ(701  , message.GetExtension(unittest::packed_int32_extension   , 1));
+  EXPECT_EQ(702  , message.GetExtension(unittest::packed_int64_extension   , 1));
+  EXPECT_EQ(703  , message.GetExtension(unittest::packed_uint32_extension  , 1));
+  EXPECT_EQ(704  , message.GetExtension(unittest::packed_uint64_extension  , 1));
+  EXPECT_EQ(705  , message.GetExtension(unittest::packed_sint32_extension  , 1));
+  EXPECT_EQ(706  , message.GetExtension(unittest::packed_sint64_extension  , 1));
+  EXPECT_EQ(707  , message.GetExtension(unittest::packed_fixed32_extension , 1));
+  EXPECT_EQ(708  , message.GetExtension(unittest::packed_fixed64_extension , 1));
+  EXPECT_EQ(709  , message.GetExtension(unittest::packed_sfixed32_extension, 1));
+  EXPECT_EQ(710  , message.GetExtension(unittest::packed_sfixed64_extension, 1));
+  EXPECT_EQ(711  , message.GetExtension(unittest::packed_float_extension   , 1));
+  EXPECT_EQ(712  , message.GetExtension(unittest::packed_double_extension  , 1));
+  EXPECT_FALSE(    message.GetExtension(unittest::packed_bool_extension    , 1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ,
+            message.GetExtension(unittest::packed_enum_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsClear(
+    const unittest::TestPackedExtensions& message) {
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension    ));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsModified(
+    const unittest::TestPackedExtensions& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension    ));
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension  , 0));
+  EXPECT_TRUE(     message.GetExtension(unittest::packed_bool_extension    , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR,
+            message.GetExtension(unittest::packed_enum_extension, 0));
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.GetExtension(unittest::packed_int32_extension   , 1));
+  EXPECT_EQ(802  , message.GetExtension(unittest::packed_int64_extension   , 1));
+  EXPECT_EQ(803  , message.GetExtension(unittest::packed_uint32_extension  , 1));
+  EXPECT_EQ(804  , message.GetExtension(unittest::packed_uint64_extension  , 1));
+  EXPECT_EQ(805  , message.GetExtension(unittest::packed_sint32_extension  , 1));
+  EXPECT_EQ(806  , message.GetExtension(unittest::packed_sint64_extension  , 1));
+  EXPECT_EQ(807  , message.GetExtension(unittest::packed_fixed32_extension , 1));
+  EXPECT_EQ(808  , message.GetExtension(unittest::packed_fixed64_extension , 1));
+  EXPECT_EQ(809  , message.GetExtension(unittest::packed_sfixed32_extension, 1));
+  EXPECT_EQ(810  , message.GetExtension(unittest::packed_sfixed64_extension, 1));
+  EXPECT_EQ(811  , message.GetExtension(unittest::packed_float_extension   , 1));
+  EXPECT_EQ(812  , message.GetExtension(unittest::packed_double_extension  , 1));
+  EXPECT_TRUE(     message.GetExtension(unittest::packed_bool_extension    , 1));
+  EXPECT_EQ(unittest::FOREIGN_FOO,
+            message.GetExtension(unittest::packed_enum_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectUnpackedExtensionsSet(
+    const unittest::TestUnpackedExtensions& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_enum_extension    ));
+
+  EXPECT_EQ(601  , message.GetExtension(unittest::unpacked_int32_extension   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::unpacked_int64_extension   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::unpacked_uint32_extension  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::unpacked_uint64_extension  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::unpacked_sint32_extension  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::unpacked_sint64_extension  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::unpacked_fixed32_extension , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::unpacked_fixed64_extension , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::unpacked_sfixed32_extension, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::unpacked_sfixed64_extension, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::unpacked_float_extension   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::unpacked_double_extension  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::unpacked_bool_extension    , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR,
+            message.GetExtension(unittest::unpacked_enum_extension, 0));
+  EXPECT_EQ(701  , message.GetExtension(unittest::unpacked_int32_extension   , 1));
+  EXPECT_EQ(702  , message.GetExtension(unittest::unpacked_int64_extension   , 1));
+  EXPECT_EQ(703  , message.GetExtension(unittest::unpacked_uint32_extension  , 1));
+  EXPECT_EQ(704  , message.GetExtension(unittest::unpacked_uint64_extension  , 1));
+  EXPECT_EQ(705  , message.GetExtension(unittest::unpacked_sint32_extension  , 1));
+  EXPECT_EQ(706  , message.GetExtension(unittest::unpacked_sint64_extension  , 1));
+  EXPECT_EQ(707  , message.GetExtension(unittest::unpacked_fixed32_extension , 1));
+  EXPECT_EQ(708  , message.GetExtension(unittest::unpacked_fixed64_extension , 1));
+  EXPECT_EQ(709  , message.GetExtension(unittest::unpacked_sfixed32_extension, 1));
+  EXPECT_EQ(710  , message.GetExtension(unittest::unpacked_sfixed64_extension, 1));
+  EXPECT_EQ(711  , message.GetExtension(unittest::unpacked_float_extension   , 1));
+  EXPECT_EQ(712  , message.GetExtension(unittest::unpacked_double_extension  , 1));
+  EXPECT_EQ(false, message.GetExtension(unittest::unpacked_bool_extension    , 1));
+  EXPECT_EQ(unittest::FOREIGN_BAZ,
+            message.GetExtension(unittest::unpacked_enum_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) {
+  // We set each field individually, serialize separately, and concatenate all
+  // the strings in canonical order to determine the expected serialization.
+  string expected;
+  unittest::TestFieldOrderings message;
+  message.set_my_int(1);  // Field 1.
+  message.AppendToString(&expected);
+  message.Clear();
+  message.SetExtension(unittest::my_extension_int, 23);  // Field 5.
+  message.AppendToString(&expected);
+  message.Clear();
+  message.set_my_string("foo");  // Field 11.
+  message.AppendToString(&expected);
+  message.Clear();
+  message.SetExtension(unittest::my_extension_string, "bar");  // Field 50.
+  message.AppendToString(&expected);
+  message.Clear();
+  message.set_my_float(1.0);  // Field 101.
+  message.AppendToString(&expected);
+  message.Clear();
+
+  // We don't EXPECT_EQ() since we don't want to print raw bytes to stdout.
+  EXPECT_TRUE(serialized == expected);
+}
+
+void TestUtil::ExpectLastRepeatedsRemoved(
+    const unittest::TestAllTypes& message) {
+  ASSERT_EQ(1, message.repeated_int32_size   ());
+  ASSERT_EQ(1, message.repeated_int64_size   ());
+  ASSERT_EQ(1, message.repeated_uint32_size  ());
+  ASSERT_EQ(1, message.repeated_uint64_size  ());
+  ASSERT_EQ(1, message.repeated_sint32_size  ());
+  ASSERT_EQ(1, message.repeated_sint64_size  ());
+  ASSERT_EQ(1, message.repeated_fixed32_size ());
+  ASSERT_EQ(1, message.repeated_fixed64_size ());
+  ASSERT_EQ(1, message.repeated_sfixed32_size());
+  ASSERT_EQ(1, message.repeated_sfixed64_size());
+  ASSERT_EQ(1, message.repeated_float_size   ());
+  ASSERT_EQ(1, message.repeated_double_size  ());
+  ASSERT_EQ(1, message.repeated_bool_size    ());
+  ASSERT_EQ(1, message.repeated_string_size  ());
+  ASSERT_EQ(1, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(1, message.repeatedgroup_size           ());
+  ASSERT_EQ(1, message.repeated_nested_message_size ());
+  ASSERT_EQ(1, message.repeated_foreign_message_size());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+  ASSERT_EQ(1, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(1, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(1, message.repeated_import_enum_size    ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  ASSERT_EQ(1, message.repeated_string_piece_size());
+  ASSERT_EQ(1, message.repeated_cord_size());
+#endif
+
+  // Test that the remaining element is the correct one.
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_TRUE(     message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0));
+}
+
+void TestUtil::ExpectLastRepeatedExtensionsRemoved(
+    const unittest::TestAllExtensions& message) {
+
+  // Test that one element was removed.
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int32_extension   ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int64_extension   ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint32_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint64_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint32_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint64_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_float_extension   ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_double_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bool_extension    ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension  ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bytes_extension   ));
+
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
+
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_piece_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_cord_extension));
+
+  // Test that the remaining element is the correct one.
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension  , 0));
+  EXPECT_TRUE(     message.GetExtension(unittest::repeated_bool_extension    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+  EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+  EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
+}
+
+void TestUtil::ExpectLastRepeatedsReleased(
+    const unittest::TestAllTypes& message) {
+  ASSERT_EQ(1, message.repeatedgroup_size           ());
+  ASSERT_EQ(1, message.repeated_nested_message_size ());
+  ASSERT_EQ(1, message.repeated_foreign_message_size());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+}
+
+void TestUtil::ExpectLastRepeatedExtensionsReleased(
+    const unittest::TestAllExtensions& message) {
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+}
+
+void TestUtil::ExpectRepeatedsSwapped(
+    const unittest::TestAllTypes& message) {
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+  ASSERT_EQ(2, message.repeated_string_piece_size());
+  ASSERT_EQ(2, message.repeated_cord_size());
+#endif
+
+  // Test that the first element and second element are flipped.
+  EXPECT_EQ(201  , message.repeated_int32   (1));
+  EXPECT_EQ(202  , message.repeated_int64   (1));
+  EXPECT_EQ(203  , message.repeated_uint32  (1));
+  EXPECT_EQ(204  , message.repeated_uint64  (1));
+  EXPECT_EQ(205  , message.repeated_sint32  (1));
+  EXPECT_EQ(206  , message.repeated_sint64  (1));
+  EXPECT_EQ(207  , message.repeated_fixed32 (1));
+  EXPECT_EQ(208  , message.repeated_fixed64 (1));
+  EXPECT_EQ(209  , message.repeated_sfixed32(1));
+  EXPECT_EQ(210  , message.repeated_sfixed64(1));
+  EXPECT_EQ(211  , message.repeated_float   (1));
+  EXPECT_EQ(212  , message.repeated_double  (1));
+  EXPECT_TRUE(     message.repeated_bool    (1));
+  EXPECT_EQ("215", message.repeated_string  (1));
+  EXPECT_EQ("216", message.repeated_bytes   (1));
+
+  EXPECT_EQ(217, message.repeatedgroup           (1).a());
+  EXPECT_EQ(218, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(220, message.repeated_import_message (1).d());
+  EXPECT_EQ(220, message.repeated_import_message (1).d());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (1));
+
+  EXPECT_EQ(301  , message.repeated_int32   (0));
+  EXPECT_EQ(302  , message.repeated_int64   (0));
+  EXPECT_EQ(303  , message.repeated_uint32  (0));
+  EXPECT_EQ(304  , message.repeated_uint64  (0));
+  EXPECT_EQ(305  , message.repeated_sint32  (0));
+  EXPECT_EQ(306  , message.repeated_sint64  (0));
+  EXPECT_EQ(307  , message.repeated_fixed32 (0));
+  EXPECT_EQ(308  , message.repeated_fixed64 (0));
+  EXPECT_EQ(309  , message.repeated_sfixed32(0));
+  EXPECT_EQ(310  , message.repeated_sfixed64(0));
+  EXPECT_EQ(311  , message.repeated_float   (0));
+  EXPECT_EQ(312  , message.repeated_double  (0));
+  EXPECT_FALSE(    message.repeated_bool    (0));
+  EXPECT_EQ("315", message.repeated_string  (0));
+  EXPECT_EQ("316", message.repeated_bytes   (0));
+
+  EXPECT_EQ(317, message.repeatedgroup           (0).a());
+  EXPECT_EQ(318, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(319, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(320, message.repeated_import_message (0).d());
+  EXPECT_EQ(320, message.repeated_import_message (0).d());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.repeated_import_enum (0));
+}
+
+void TestUtil::ExpectRepeatedExtensionsSwapped(
+    const unittest::TestAllExtensions& message) {
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension));
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension   , 1));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension   , 1));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension  , 1));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension  , 1));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension  , 1));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension  , 1));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension , 1));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension , 1));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension, 1));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension, 1));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension   , 1));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension  , 1));
+  EXPECT_TRUE(     message.GetExtension(unittest::repeated_bool_extension    , 1));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension  , 1));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension   , 1));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 1).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
+  EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
+  EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 1));
+
+  EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 1));
+  EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 1));
+
+  EXPECT_EQ(301  , message.GetExtension(unittest::repeated_int32_extension   , 0));
+  EXPECT_EQ(302  , message.GetExtension(unittest::repeated_int64_extension   , 0));
+  EXPECT_EQ(303  , message.GetExtension(unittest::repeated_uint32_extension  , 0));
+  EXPECT_EQ(304  , message.GetExtension(unittest::repeated_uint64_extension  , 0));
+  EXPECT_EQ(305  , message.GetExtension(unittest::repeated_sint32_extension  , 0));
+  EXPECT_EQ(306  , message.GetExtension(unittest::repeated_sint64_extension  , 0));
+  EXPECT_EQ(307  , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+  EXPECT_EQ(308  , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+  EXPECT_EQ(309  , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+  EXPECT_EQ(310  , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+  EXPECT_EQ(311  , message.GetExtension(unittest::repeated_float_extension   , 0));
+  EXPECT_EQ(312  , message.GetExtension(unittest::repeated_double_extension  , 0));
+  EXPECT_FALSE(    message.GetExtension(unittest::repeated_bool_extension    , 0));
+  EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension  , 0));
+  EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension   , 0));
+
+  EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+  EXPECT_EQ(unittest::FOREIGN_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+  EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+  EXPECT_EQ("324", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+  EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 0));
+}
+
+void TestUtil::SetOneof1(unittest::TestOneof2* message) {
+  message->mutable_foo_lazy_message()->set_qux_int(100);
+  message->set_bar_string("101");
+  message->set_baz_int(102);
+  message->set_baz_string("103");
+}
+
+void TestUtil::SetOneof2(unittest::TestOneof2* message) {
+  message->set_foo_int(200);
+  message->set_bar_enum(unittest::TestOneof2::BAZ);
+  message->set_baz_int(202);
+  message->set_baz_string("203");
+}
+
+void TestUtil::ExpectOneofSet1(const unittest::TestOneof2& message) {
+  ExpectAtMostOneFieldSetInOneof(message);
+
+  EXPECT_TRUE(message.has_foo_lazy_message          ());
+  EXPECT_TRUE(message.foo_lazy_message().has_qux_int());
+
+  EXPECT_TRUE(message.has_bar_string());
+  EXPECT_TRUE(message.has_baz_int   ());
+  EXPECT_TRUE(message.has_baz_string());
+
+  ASSERT_EQ(0, message.foo_lazy_message().corge_int_size());
+
+  EXPECT_EQ(100  , message.foo_lazy_message().qux_int());
+  EXPECT_EQ("101", message.bar_string                ());
+  EXPECT_EQ(102  , message.baz_int                   ());
+  EXPECT_EQ("103", message.baz_string                ());
+}
+
+void TestUtil::ExpectOneofSet2(const unittest::TestOneof2& message) {
+  ExpectAtMostOneFieldSetInOneof(message);
+
+  EXPECT_TRUE(message.has_foo_int   ());
+  EXPECT_TRUE(message.has_bar_enum  ());
+  EXPECT_TRUE(message.has_baz_int   ());
+  EXPECT_TRUE(message.has_baz_string());
+
+  EXPECT_EQ(200                      , message.foo_int   ());
+  EXPECT_EQ(unittest::TestOneof2::BAZ, message.bar_enum  ());
+  EXPECT_EQ(202                      , message.baz_int   ());
+  EXPECT_EQ("203"                    , message.baz_string());
+}
+
+void TestUtil::ExpectOneofClear(const unittest::TestOneof2& message) {
+  EXPECT_FALSE(message.has_foo_int());
+  EXPECT_FALSE(message.has_foo_string());
+  EXPECT_FALSE(message.has_foo_bytes());
+  EXPECT_FALSE(message.has_foo_enum());
+  EXPECT_FALSE(message.has_foo_message());
+  EXPECT_FALSE(message.has_foogroup());
+  EXPECT_FALSE(message.has_foo_lazy_message());
+
+  EXPECT_FALSE(message.has_bar_int());
+  EXPECT_FALSE(message.has_bar_string());
+  EXPECT_FALSE(message.has_bar_bytes());
+  EXPECT_FALSE(message.has_bar_enum());
+
+  EXPECT_FALSE(message.has_baz_int());
+  EXPECT_FALSE(message.has_baz_string());
+
+  EXPECT_EQ(unittest::TestOneof2::FOO_NOT_SET, message.foo_case());
+  EXPECT_EQ(unittest::TestOneof2::BAR_NOT_SET, message.bar_case());
+}
+
+void TestUtil::ExpectAtMostOneFieldSetInOneof(
+    const unittest::TestOneof2& message) {
+  int count = 0;
+  if (message.has_foo_int()) count++;
+  if (message.has_foo_string()) count++;
+  if (message.has_foo_bytes()) count++;
+  if (message.has_foo_enum()) count++;
+  if (message.has_foo_message()) count++;
+  if (message.has_foogroup()) count++;
+  if (message.has_foo_lazy_message()) count++;
+  EXPECT_LE(count, 1);
+  count = 0;
+  if (message.has_bar_int()) count++;
+  if (message.has_bar_string()) count++;
+  if (message.has_bar_bytes()) count++;
+  if (message.has_bar_enum()) count++;
+  EXPECT_TRUE(count == 0 || count == 1);
+}
+
+// ===================================================================
+
+TestUtil::ReflectionTester::ReflectionTester(
+    const Descriptor* base_descriptor)
+  : base_descriptor_(base_descriptor) {
+
+  const DescriptorPool* pool = base_descriptor->file()->pool();
+
+  nested_b_ =
+    pool->FindFieldByName("protobuf_unittest.TestAllTypes.NestedMessage.bb");
+  foreign_c_ =
+    pool->FindFieldByName("protobuf_unittest.ForeignMessage.c");
+  import_d_ =
+    pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d");
+  import_e_ =
+    pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e");
+  nested_foo_ =
+    pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO");
+  nested_bar_ =
+    pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAR");
+  nested_baz_ =
+    pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAZ");
+  foreign_foo_ =
+    pool->FindEnumValueByName("protobuf_unittest.FOREIGN_FOO");
+  foreign_bar_ =
+    pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAR");
+  foreign_baz_ =
+    pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAZ");
+  import_foo_ =
+    pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_FOO");
+  import_bar_ =
+    pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAR");
+  import_baz_ =
+    pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAZ");
+
+  if (base_descriptor_->name() == "TestAllExtensions") {
+    group_a_ =
+      pool->FindFieldByName("protobuf_unittest.OptionalGroup_extension.a");
+    repeated_group_a_ =
+      pool->FindFieldByName("protobuf_unittest.RepeatedGroup_extension.a");
+  } else {
+    group_a_ =
+      pool->FindFieldByName("protobuf_unittest.TestAllTypes.OptionalGroup.a");
+    repeated_group_a_ =
+      pool->FindFieldByName("protobuf_unittest.TestAllTypes.RepeatedGroup.a");
+  }
+
+  EXPECT_TRUE(group_a_          != NULL);
+  EXPECT_TRUE(repeated_group_a_ != NULL);
+  EXPECT_TRUE(nested_b_         != NULL);
+  EXPECT_TRUE(foreign_c_        != NULL);
+  EXPECT_TRUE(import_d_         != NULL);
+  EXPECT_TRUE(import_e_         != NULL);
+  EXPECT_TRUE(nested_foo_       != NULL);
+  EXPECT_TRUE(nested_bar_       != NULL);
+  EXPECT_TRUE(nested_baz_       != NULL);
+  EXPECT_TRUE(foreign_foo_      != NULL);
+  EXPECT_TRUE(foreign_bar_      != NULL);
+  EXPECT_TRUE(foreign_baz_      != NULL);
+  EXPECT_TRUE(import_foo_       != NULL);
+  EXPECT_TRUE(import_bar_       != NULL);
+  EXPECT_TRUE(import_baz_       != NULL);
+}
+
+// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+const FieldDescriptor* TestUtil::ReflectionTester::F(const string& name) {
+  const FieldDescriptor* result = NULL;
+  if (base_descriptor_->name() == "TestAllExtensions" ||
+      base_descriptor_->name() == "TestPackedExtensions") {
+    result = base_descriptor_->file()->FindExtensionByName(name + "_extension");
+  } else {
+    result = base_descriptor_->FindFieldByName(name);
+  }
+  GOOGLE_CHECK(result != NULL);
+  return result;
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message;
+
+  reflection->SetInt32 (message, F("optional_int32"   ), 101);
+  reflection->SetInt64 (message, F("optional_int64"   ), 102);
+  reflection->SetUInt32(message, F("optional_uint32"  ), 103);
+  reflection->SetUInt64(message, F("optional_uint64"  ), 104);
+  reflection->SetInt32 (message, F("optional_sint32"  ), 105);
+  reflection->SetInt64 (message, F("optional_sint64"  ), 106);
+  reflection->SetUInt32(message, F("optional_fixed32" ), 107);
+  reflection->SetUInt64(message, F("optional_fixed64" ), 108);
+  reflection->SetInt32 (message, F("optional_sfixed32"), 109);
+  reflection->SetInt64 (message, F("optional_sfixed64"), 110);
+  reflection->SetFloat (message, F("optional_float"   ), 111);
+  reflection->SetDouble(message, F("optional_double"  ), 112);
+  reflection->SetBool  (message, F("optional_bool"    ), true);
+  reflection->SetString(message, F("optional_string"  ), "115");
+  reflection->SetString(message, F("optional_bytes"   ), "116");
+
+  sub_message = reflection->MutableMessage(message, F("optionalgroup"));
+  sub_message->GetReflection()->SetInt32(sub_message, group_a_, 117);
+  sub_message = reflection->MutableMessage(message, F("optional_nested_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 118);
+  sub_message = reflection->MutableMessage(message, F("optional_foreign_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 119);
+  sub_message = reflection->MutableMessage(message, F("optional_import_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, import_d_, 120);
+
+  reflection->SetEnum(message, F("optional_nested_enum" ),  nested_baz_);
+  reflection->SetEnum(message, F("optional_foreign_enum"), foreign_baz_);
+  reflection->SetEnum(message, F("optional_import_enum" ),  import_baz_);
+
+  reflection->SetString(message, F("optional_string_piece"), "124");
+  reflection->SetString(message, F("optional_cord"), "125");
+
+  sub_message = reflection->MutableMessage(message, F("optional_public_import_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126);
+
+  sub_message = reflection->MutableMessage(message, F("optional_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127);
+
+  // -----------------------------------------------------------------
+
+  reflection->AddInt32 (message, F("repeated_int32"   ), 201);
+  reflection->AddInt64 (message, F("repeated_int64"   ), 202);
+  reflection->AddUInt32(message, F("repeated_uint32"  ), 203);
+  reflection->AddUInt64(message, F("repeated_uint64"  ), 204);
+  reflection->AddInt32 (message, F("repeated_sint32"  ), 205);
+  reflection->AddInt64 (message, F("repeated_sint64"  ), 206);
+  reflection->AddUInt32(message, F("repeated_fixed32" ), 207);
+  reflection->AddUInt64(message, F("repeated_fixed64" ), 208);
+  reflection->AddInt32 (message, F("repeated_sfixed32"), 209);
+  reflection->AddInt64 (message, F("repeated_sfixed64"), 210);
+  reflection->AddFloat (message, F("repeated_float"   ), 211);
+  reflection->AddDouble(message, F("repeated_double"  ), 212);
+  reflection->AddBool  (message, F("repeated_bool"    ), true);
+  reflection->AddString(message, F("repeated_string"  ), "215");
+  reflection->AddString(message, F("repeated_bytes"   ), "216");
+
+  sub_message = reflection->AddMessage(message, F("repeatedgroup"));
+  sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 217);
+  sub_message = reflection->AddMessage(message, F("repeated_nested_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 218);
+  sub_message = reflection->AddMessage(message, F("repeated_foreign_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219);
+  sub_message = reflection->AddMessage(message, F("repeated_import_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220);
+  sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227);
+
+  reflection->AddEnum(message, F("repeated_nested_enum" ),  nested_bar_);
+  reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_);
+  reflection->AddEnum(message, F("repeated_import_enum" ),  import_bar_);
+
+  reflection->AddString(message, F("repeated_string_piece"), "224");
+  reflection->AddString(message, F("repeated_cord"), "225");
+
+  // Add a second one of each field.
+  reflection->AddInt32 (message, F("repeated_int32"   ), 301);
+  reflection->AddInt64 (message, F("repeated_int64"   ), 302);
+  reflection->AddUInt32(message, F("repeated_uint32"  ), 303);
+  reflection->AddUInt64(message, F("repeated_uint64"  ), 304);
+  reflection->AddInt32 (message, F("repeated_sint32"  ), 305);
+  reflection->AddInt64 (message, F("repeated_sint64"  ), 306);
+  reflection->AddUInt32(message, F("repeated_fixed32" ), 307);
+  reflection->AddUInt64(message, F("repeated_fixed64" ), 308);
+  reflection->AddInt32 (message, F("repeated_sfixed32"), 309);
+  reflection->AddInt64 (message, F("repeated_sfixed64"), 310);
+  reflection->AddFloat (message, F("repeated_float"   ), 311);
+  reflection->AddDouble(message, F("repeated_double"  ), 312);
+  reflection->AddBool  (message, F("repeated_bool"    ), false);
+  reflection->AddString(message, F("repeated_string"  ), "315");
+  reflection->AddString(message, F("repeated_bytes"   ), "316");
+
+  sub_message = reflection->AddMessage(message, F("repeatedgroup"));
+  sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 317);
+  sub_message = reflection->AddMessage(message, F("repeated_nested_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 318);
+  sub_message = reflection->AddMessage(message, F("repeated_foreign_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319);
+  sub_message = reflection->AddMessage(message, F("repeated_import_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320);
+  sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327);
+
+  reflection->AddEnum(message, F("repeated_nested_enum" ),  nested_baz_);
+  reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_);
+  reflection->AddEnum(message, F("repeated_import_enum" ),  import_baz_);
+
+  reflection->AddString(message, F("repeated_string_piece"), "324");
+  reflection->AddString(message, F("repeated_cord"), "325");
+
+  // -----------------------------------------------------------------
+
+  reflection->SetInt32 (message, F("default_int32"   ), 401);
+  reflection->SetInt64 (message, F("default_int64"   ), 402);
+  reflection->SetUInt32(message, F("default_uint32"  ), 403);
+  reflection->SetUInt64(message, F("default_uint64"  ), 404);
+  reflection->SetInt32 (message, F("default_sint32"  ), 405);
+  reflection->SetInt64 (message, F("default_sint64"  ), 406);
+  reflection->SetUInt32(message, F("default_fixed32" ), 407);
+  reflection->SetUInt64(message, F("default_fixed64" ), 408);
+  reflection->SetInt32 (message, F("default_sfixed32"), 409);
+  reflection->SetInt64 (message, F("default_sfixed64"), 410);
+  reflection->SetFloat (message, F("default_float"   ), 411);
+  reflection->SetDouble(message, F("default_double"  ), 412);
+  reflection->SetBool  (message, F("default_bool"    ), false);
+  reflection->SetString(message, F("default_string"  ), "415");
+  reflection->SetString(message, F("default_bytes"   ), "416");
+
+  reflection->SetEnum(message, F("default_nested_enum" ),  nested_foo_);
+  reflection->SetEnum(message, F("default_foreign_enum"), foreign_foo_);
+  reflection->SetEnum(message, F("default_import_enum" ),  import_foo_);
+
+  reflection->SetString(message, F("default_string_piece"), "424");
+  reflection->SetString(message, F("default_cord"), "425");
+
+  reflection->SetUInt32(message, F("oneof_uint32"   ), 601);
+  sub_message = reflection->MutableMessage(message, F("oneof_nested_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602);
+  reflection->SetString(message, F("oneof_string"), "603");
+  reflection->SetString(message, F("oneof_bytes" ), "604");
+}
+
+void TestUtil::ReflectionTester::SetOneofViaReflection(Message* message) {
+  const Descriptor* descriptor = message->GetDescriptor();
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message = reflection->MutableMessage(
+      message, descriptor->FindFieldByName("foo_lazy_message"));
+  sub_message->GetReflection()->SetInt64(
+      sub_message,
+      descriptor->file()->pool()->FindFieldByName(
+          "protobuf_unittest.TestOneof2.NestedMessage.qux_int"),
+      100);
+
+  reflection->SetString(message,
+                        descriptor->FindFieldByName("bar_cord"),
+                        "101");
+  reflection->SetInt32(message,
+                        descriptor->FindFieldByName("baz_int"),
+                       102);
+  reflection->SetString(message,
+                        descriptor->FindFieldByName("baz_string"),
+                        "103");
+}
+
+void TestUtil::ReflectionTester::ExpectOneofSetViaReflection(
+    const Message& message) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+  EXPECT_TRUE(reflection->HasField(
+      message, descriptor->FindFieldByName("foo_lazy_message")));
+  EXPECT_TRUE(reflection->HasField(
+      message, descriptor->FindFieldByName("bar_cord")));
+  EXPECT_TRUE(reflection->HasField(
+      message, descriptor->FindFieldByName("baz_int")));
+  EXPECT_TRUE(reflection->HasField(
+      message, descriptor->FindFieldByName("baz_string")));
+
+  const Message* sub_message = &reflection->GetMessage(
+      message, descriptor->FindFieldByName("foo_lazy_message"));
+  EXPECT_EQ(100, sub_message->GetReflection()->GetInt64(
+      *sub_message,
+      descriptor->file()->pool()->FindFieldByName(
+          "protobuf_unittest.TestOneof2.NestedMessage.qux_int")));
+
+  EXPECT_EQ("101", reflection->GetString(
+      message, descriptor->FindFieldByName("bar_cord")));
+  EXPECT_EQ("101", reflection->GetStringReference(
+      message, descriptor->FindFieldByName("bar_cord"), &scratch));
+
+  EXPECT_EQ(102, reflection->GetInt32(
+      message, descriptor->FindFieldByName("baz_int")));
+
+  EXPECT_EQ("103", reflection->GetString(
+      message, descriptor->FindFieldByName("baz_string")));
+  EXPECT_EQ("103", reflection->GetStringReference(
+      message, descriptor->FindFieldByName("baz_string"), &scratch));
+}
+
+void TestUtil::ReflectionTester::SetPackedFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  reflection->AddInt32 (message, F("packed_int32"   ), 601);
+  reflection->AddInt64 (message, F("packed_int64"   ), 602);
+  reflection->AddUInt32(message, F("packed_uint32"  ), 603);
+  reflection->AddUInt64(message, F("packed_uint64"  ), 604);
+  reflection->AddInt32 (message, F("packed_sint32"  ), 605);
+  reflection->AddInt64 (message, F("packed_sint64"  ), 606);
+  reflection->AddUInt32(message, F("packed_fixed32" ), 607);
+  reflection->AddUInt64(message, F("packed_fixed64" ), 608);
+  reflection->AddInt32 (message, F("packed_sfixed32"), 609);
+  reflection->AddInt64 (message, F("packed_sfixed64"), 610);
+  reflection->AddFloat (message, F("packed_float"   ), 611);
+  reflection->AddDouble(message, F("packed_double"  ), 612);
+  reflection->AddBool  (message, F("packed_bool"    ), true);
+  reflection->AddEnum  (message, F("packed_enum"    ), foreign_bar_);
+
+  reflection->AddInt32 (message, F("packed_int32"   ), 701);
+  reflection->AddInt64 (message, F("packed_int64"   ), 702);
+  reflection->AddUInt32(message, F("packed_uint32"  ), 703);
+  reflection->AddUInt64(message, F("packed_uint64"  ), 704);
+  reflection->AddInt32 (message, F("packed_sint32"  ), 705);
+  reflection->AddInt64 (message, F("packed_sint64"  ), 706);
+  reflection->AddUInt32(message, F("packed_fixed32" ), 707);
+  reflection->AddUInt64(message, F("packed_fixed64" ), 708);
+  reflection->AddInt32 (message, F("packed_sfixed32"), 709);
+  reflection->AddInt64 (message, F("packed_sfixed64"), 710);
+  reflection->AddFloat (message, F("packed_float"   ), 711);
+  reflection->AddDouble(message, F("packed_double"  ), 712);
+  reflection->AddBool  (message, F("packed_bool"    ), false);
+  reflection->AddEnum  (message, F("packed_enum"    ), foreign_baz_);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
+    const Message& message) {
+  // We have to split this into three function otherwise it creates a stack
+  // frame so large that it triggers a warning.
+  ExpectAllFieldsSetViaReflection1(message);
+  ExpectAllFieldsSetViaReflection2(message);
+  ExpectAllFieldsSetViaReflection3(message);
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+  const Message* sub_message;
+
+  EXPECT_TRUE(reflection->HasField(message, F("optional_int32"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_int64"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_uint32"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_uint64"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_sint32"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_sint64"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_fixed32" )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_fixed64" )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed32")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed64")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_float"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_double"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_bool"    )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_string"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_bytes"   )));
+
+  EXPECT_TRUE(reflection->HasField(message, F("optionalgroup"                 )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message"       )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message"      )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_import_message"       )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_public_import_message")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message"         )));
+
+  sub_message = &reflection->GetMessage(message, F("optionalgroup"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_));
+  sub_message = &reflection->GetMessage(message, F("optional_nested_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+  sub_message = &reflection->GetMessage(message, F("optional_foreign_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_));
+  sub_message = &reflection->GetMessage(message, F("optional_import_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+
+  EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum" )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_import_enum" )));
+
+  EXPECT_TRUE(reflection->HasField(message, F("optional_string_piece")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_cord")));
+
+  EXPECT_EQ(101  , reflection->GetInt32 (message, F("optional_int32"   )));
+  EXPECT_EQ(102  , reflection->GetInt64 (message, F("optional_int64"   )));
+  EXPECT_EQ(103  , reflection->GetUInt32(message, F("optional_uint32"  )));
+  EXPECT_EQ(104  , reflection->GetUInt64(message, F("optional_uint64"  )));
+  EXPECT_EQ(105  , reflection->GetInt32 (message, F("optional_sint32"  )));
+  EXPECT_EQ(106  , reflection->GetInt64 (message, F("optional_sint64"  )));
+  EXPECT_EQ(107  , reflection->GetUInt32(message, F("optional_fixed32" )));
+  EXPECT_EQ(108  , reflection->GetUInt64(message, F("optional_fixed64" )));
+  EXPECT_EQ(109  , reflection->GetInt32 (message, F("optional_sfixed32")));
+  EXPECT_EQ(110  , reflection->GetInt64 (message, F("optional_sfixed64")));
+  EXPECT_EQ(111  , reflection->GetFloat (message, F("optional_float"   )));
+  EXPECT_EQ(112  , reflection->GetDouble(message, F("optional_double"  )));
+  EXPECT_TRUE(     reflection->GetBool  (message, F("optional_bool"    )));
+  EXPECT_EQ("115", reflection->GetString(message, F("optional_string"  )));
+  EXPECT_EQ("116", reflection->GetString(message, F("optional_bytes"   )));
+
+  EXPECT_EQ("115", reflection->GetStringReference(message, F("optional_string"), &scratch));
+  EXPECT_EQ("116", reflection->GetStringReference(message, F("optional_bytes" ), &scratch));
+
+  sub_message = &reflection->GetMessage(message, F("optionalgroup"));
+  EXPECT_EQ(117, sub_message->GetReflection()->GetInt32(*sub_message, group_a_));
+  sub_message = &reflection->GetMessage(message, F("optional_nested_message"));
+  EXPECT_EQ(118, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+  sub_message = &reflection->GetMessage(message, F("optional_foreign_message"));
+  EXPECT_EQ(119, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
+  sub_message = &reflection->GetMessage(message, F("optional_import_message"));
+  EXPECT_EQ(120, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_EQ(126, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_EQ(127, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+
+  EXPECT_EQ( nested_baz_, reflection->GetEnum(message, F("optional_nested_enum" )));
+  EXPECT_EQ(foreign_baz_, reflection->GetEnum(message, F("optional_foreign_enum")));
+  EXPECT_EQ( import_baz_, reflection->GetEnum(message, F("optional_import_enum" )));
+
+  EXPECT_EQ("124", reflection->GetString(message, F("optional_string_piece")));
+  EXPECT_EQ("124", reflection->GetStringReference(message, F("optional_string_piece"), &scratch));
+
+  EXPECT_EQ("125", reflection->GetString(message, F("optional_cord")));
+  EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch));
+
+  EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes" )));
+  EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes"   )));
+
+  if (base_descriptor_->name() == "TestAllTypes") {
+    EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32")));
+    EXPECT_FALSE(reflection->HasField(message, F("oneof_string")));
+  } else {
+    EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32")));
+    EXPECT_TRUE(reflection->HasField(message, F("oneof_string")));
+    EXPECT_EQ(601  , reflection->GetUInt32(message, F("oneof_uint32")));
+    EXPECT_EQ("603", reflection->GetString(message, F("oneof_string")));
+    sub_message = &reflection->GetMessage(message, F("oneof_nested_message"));
+    EXPECT_EQ(602, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+  }
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+  const Message* sub_message;
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int32"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int64"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint32"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint64"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint32"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint64"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed32" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed64" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_float"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_double"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bool"    )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bytes"   )));
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeatedgroup"           )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum"    )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum"    )));
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string_piece")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_cord")));
+
+  EXPECT_EQ(201  , reflection->GetRepeatedInt32 (message, F("repeated_int32"   ), 0));
+  EXPECT_EQ(202  , reflection->GetRepeatedInt64 (message, F("repeated_int64"   ), 0));
+  EXPECT_EQ(203  , reflection->GetRepeatedUInt32(message, F("repeated_uint32"  ), 0));
+  EXPECT_EQ(204  , reflection->GetRepeatedUInt64(message, F("repeated_uint64"  ), 0));
+  EXPECT_EQ(205  , reflection->GetRepeatedInt32 (message, F("repeated_sint32"  ), 0));
+  EXPECT_EQ(206  , reflection->GetRepeatedInt64 (message, F("repeated_sint64"  ), 0));
+  EXPECT_EQ(207  , reflection->GetRepeatedUInt32(message, F("repeated_fixed32" ), 0));
+  EXPECT_EQ(208  , reflection->GetRepeatedUInt64(message, F("repeated_fixed64" ), 0));
+  EXPECT_EQ(209  , reflection->GetRepeatedInt32 (message, F("repeated_sfixed32"), 0));
+  EXPECT_EQ(210  , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 0));
+  EXPECT_EQ(211  , reflection->GetRepeatedFloat (message, F("repeated_float"   ), 0));
+  EXPECT_EQ(212  , reflection->GetRepeatedDouble(message, F("repeated_double"  ), 0));
+  EXPECT_TRUE(     reflection->GetRepeatedBool  (message, F("repeated_bool"    ), 0));
+  EXPECT_EQ("215", reflection->GetRepeatedString(message, F("repeated_string"  ), 0));
+  EXPECT_EQ("216", reflection->GetRepeatedString(message, F("repeated_bytes"   ), 0));
+
+  EXPECT_EQ("215", reflection->GetRepeatedStringReference(message, F("repeated_string"), 0, &scratch));
+  EXPECT_EQ("216", reflection->GetRepeatedStringReference(message, F("repeated_bytes"), 0, &scratch));
+
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 0);
+  EXPECT_EQ(217, sub_message->GetReflection()->GetInt32(*sub_message, repeated_group_a_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 0);
+  EXPECT_EQ(218, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_foreign_message"), 0);
+  EXPECT_EQ(219, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0);
+  EXPECT_EQ(220, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0);
+  EXPECT_EQ(227, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+
+  EXPECT_EQ( nested_bar_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),0));
+  EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),0));
+  EXPECT_EQ( import_bar_, reflection->GetRepeatedEnum(message, F("repeated_import_enum" ),0));
+
+  EXPECT_EQ("224", reflection->GetRepeatedString(message, F("repeated_string_piece"), 0));
+  EXPECT_EQ("224", reflection->GetRepeatedStringReference(
+                        message, F("repeated_string_piece"), 0, &scratch));
+
+  EXPECT_EQ("225", reflection->GetRepeatedString(message, F("repeated_cord"), 0));
+  EXPECT_EQ("225", reflection->GetRepeatedStringReference(
+                        message, F("repeated_cord"), 0, &scratch));
+
+  EXPECT_EQ(301  , reflection->GetRepeatedInt32 (message, F("repeated_int32"   ), 1));
+  EXPECT_EQ(302  , reflection->GetRepeatedInt64 (message, F("repeated_int64"   ), 1));
+  EXPECT_EQ(303  , reflection->GetRepeatedUInt32(message, F("repeated_uint32"  ), 1));
+  EXPECT_EQ(304  , reflection->GetRepeatedUInt64(message, F("repeated_uint64"  ), 1));
+  EXPECT_EQ(305  , reflection->GetRepeatedInt32 (message, F("repeated_sint32"  ), 1));
+  EXPECT_EQ(306  , reflection->GetRepeatedInt64 (message, F("repeated_sint64"  ), 1));
+  EXPECT_EQ(307  , reflection->GetRepeatedUInt32(message, F("repeated_fixed32" ), 1));
+  EXPECT_EQ(308  , reflection->GetRepeatedUInt64(message, F("repeated_fixed64" ), 1));
+  EXPECT_EQ(309  , reflection->GetRepeatedInt32 (message, F("repeated_sfixed32"), 1));
+  EXPECT_EQ(310  , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 1));
+  EXPECT_EQ(311  , reflection->GetRepeatedFloat (message, F("repeated_float"   ), 1));
+  EXPECT_EQ(312  , reflection->GetRepeatedDouble(message, F("repeated_double"  ), 1));
+  EXPECT_FALSE(    reflection->GetRepeatedBool  (message, F("repeated_bool"    ), 1));
+  EXPECT_EQ("315", reflection->GetRepeatedString(message, F("repeated_string"  ), 1));
+  EXPECT_EQ("316", reflection->GetRepeatedString(message, F("repeated_bytes"   ), 1));
+
+  EXPECT_EQ("315", reflection->GetRepeatedStringReference(message, F("repeated_string"),
+                                                          1, &scratch));
+  EXPECT_EQ("316", reflection->GetRepeatedStringReference(message, F("repeated_bytes"),
+                                                          1, &scratch));
+
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 1);
+  EXPECT_EQ(317, sub_message->GetReflection()->GetInt32(*sub_message, repeated_group_a_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 1);
+  EXPECT_EQ(318, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_foreign_message"), 1);
+  EXPECT_EQ(319, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1);
+  EXPECT_EQ(320, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1);
+  EXPECT_EQ(327, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+
+  EXPECT_EQ( nested_baz_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),1));
+  EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),1));
+  EXPECT_EQ( import_baz_, reflection->GetRepeatedEnum(message, F("repeated_import_enum" ),1));
+
+  EXPECT_EQ("324", reflection->GetRepeatedString(message, F("repeated_string_piece"), 1));
+  EXPECT_EQ("324", reflection->GetRepeatedStringReference(
+                        message, F("repeated_string_piece"), 1, &scratch));
+
+  EXPECT_EQ("325", reflection->GetRepeatedString(message, F("repeated_cord"), 1));
+  EXPECT_EQ("325", reflection->GetRepeatedStringReference(
+                        message, F("repeated_cord"), 1, &scratch));
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(reflection->HasField(message, F("default_int32"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_int64"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_uint32"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_uint64"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_sint32"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_sint64"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_fixed32" )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_fixed64" )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_sfixed32")));
+  EXPECT_TRUE(reflection->HasField(message, F("default_sfixed64")));
+  EXPECT_TRUE(reflection->HasField(message, F("default_float"   )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_double"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_bool"    )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_string"  )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_bytes"   )));
+
+  EXPECT_TRUE(reflection->HasField(message, F("default_nested_enum" )));
+  EXPECT_TRUE(reflection->HasField(message, F("default_foreign_enum")));
+  EXPECT_TRUE(reflection->HasField(message, F("default_import_enum" )));
+
+  EXPECT_TRUE(reflection->HasField(message, F("default_string_piece")));
+  EXPECT_TRUE(reflection->HasField(message, F("default_cord")));
+
+  EXPECT_EQ(401  , reflection->GetInt32 (message, F("default_int32"   )));
+  EXPECT_EQ(402  , reflection->GetInt64 (message, F("default_int64"   )));
+  EXPECT_EQ(403  , reflection->GetUInt32(message, F("default_uint32"  )));
+  EXPECT_EQ(404  , reflection->GetUInt64(message, F("default_uint64"  )));
+  EXPECT_EQ(405  , reflection->GetInt32 (message, F("default_sint32"  )));
+  EXPECT_EQ(406  , reflection->GetInt64 (message, F("default_sint64"  )));
+  EXPECT_EQ(407  , reflection->GetUInt32(message, F("default_fixed32" )));
+  EXPECT_EQ(408  , reflection->GetUInt64(message, F("default_fixed64" )));
+  EXPECT_EQ(409  , reflection->GetInt32 (message, F("default_sfixed32")));
+  EXPECT_EQ(410  , reflection->GetInt64 (message, F("default_sfixed64")));
+  EXPECT_EQ(411  , reflection->GetFloat (message, F("default_float"   )));
+  EXPECT_EQ(412  , reflection->GetDouble(message, F("default_double"  )));
+  EXPECT_FALSE(    reflection->GetBool  (message, F("default_bool"    )));
+  EXPECT_EQ("415", reflection->GetString(message, F("default_string"  )));
+  EXPECT_EQ("416", reflection->GetString(message, F("default_bytes"   )));
+
+  EXPECT_EQ("415", reflection->GetStringReference(message, F("default_string"), &scratch));
+  EXPECT_EQ("416", reflection->GetStringReference(message, F("default_bytes" ), &scratch));
+
+  EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("default_nested_enum" )));
+  EXPECT_EQ(foreign_foo_, reflection->GetEnum(message, F("default_foreign_enum")));
+  EXPECT_EQ( import_foo_, reflection->GetEnum(message, F("default_import_enum" )));
+
+  EXPECT_EQ("424", reflection->GetString(message, F("default_string_piece")));
+  EXPECT_EQ("424", reflection->GetStringReference(message, F("default_string_piece"),
+                                                  &scratch));
+
+  EXPECT_EQ("425", reflection->GetString(message, F("default_cord")));
+  EXPECT_EQ("425", reflection->GetStringReference(message, F("default_cord"), &scratch));
+}
+
+void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int32"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int64"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint32"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint64"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint32"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint64"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed32" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed64" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed32")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed64")));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_float"   )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_double"  )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_bool"    )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("packed_enum"    )));
+
+  EXPECT_EQ(601  , reflection->GetRepeatedInt32 (message, F("packed_int32"   ), 0));
+  EXPECT_EQ(602  , reflection->GetRepeatedInt64 (message, F("packed_int64"   ), 0));
+  EXPECT_EQ(603  , reflection->GetRepeatedUInt32(message, F("packed_uint32"  ), 0));
+  EXPECT_EQ(604  , reflection->GetRepeatedUInt64(message, F("packed_uint64"  ), 0));
+  EXPECT_EQ(605  , reflection->GetRepeatedInt32 (message, F("packed_sint32"  ), 0));
+  EXPECT_EQ(606  , reflection->GetRepeatedInt64 (message, F("packed_sint64"  ), 0));
+  EXPECT_EQ(607  , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 0));
+  EXPECT_EQ(608  , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 0));
+  EXPECT_EQ(609  , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 0));
+  EXPECT_EQ(610  , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 0));
+  EXPECT_EQ(611  , reflection->GetRepeatedFloat (message, F("packed_float"   ), 0));
+  EXPECT_EQ(612  , reflection->GetRepeatedDouble(message, F("packed_double"  ), 0));
+  EXPECT_TRUE(     reflection->GetRepeatedBool  (message, F("packed_bool"    ), 0));
+  EXPECT_EQ(foreign_bar_,
+            reflection->GetRepeatedEnum(message, F("packed_enum"), 0));
+
+  EXPECT_EQ(701  , reflection->GetRepeatedInt32 (message, F("packed_int32"   ), 1));
+  EXPECT_EQ(702  , reflection->GetRepeatedInt64 (message, F("packed_int64"   ), 1));
+  EXPECT_EQ(703  , reflection->GetRepeatedUInt32(message, F("packed_uint32"  ), 1));
+  EXPECT_EQ(704  , reflection->GetRepeatedUInt64(message, F("packed_uint64"  ), 1));
+  EXPECT_EQ(705  , reflection->GetRepeatedInt32 (message, F("packed_sint32"  ), 1));
+  EXPECT_EQ(706  , reflection->GetRepeatedInt64 (message, F("packed_sint64"  ), 1));
+  EXPECT_EQ(707  , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 1));
+  EXPECT_EQ(708  , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 1));
+  EXPECT_EQ(709  , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 1));
+  EXPECT_EQ(710  , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 1));
+  EXPECT_EQ(711  , reflection->GetRepeatedFloat (message, F("packed_float"   ), 1));
+  EXPECT_EQ(712  , reflection->GetRepeatedDouble(message, F("packed_double"  ), 1));
+  EXPECT_FALSE(    reflection->GetRepeatedBool  (message, F("packed_bool"    ), 1));
+  EXPECT_EQ(foreign_baz_,
+            reflection->GetRepeatedEnum(message, F("packed_enum"), 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ReflectionTester::ExpectClearViaReflection(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+  string scratch;
+  const Message* sub_message;
+
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(reflection->HasField(message, F("optional_int32"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_int64"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_uint32"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_uint64"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_sint32"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_sint64"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_fixed32" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_fixed64" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed32")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed64")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_float"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_double"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_bool"    )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_string"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_bytes"   )));
+
+  EXPECT_FALSE(reflection->HasField(message, F("optionalgroup"           )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_import_message" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_public_import_message")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message")));
+
+  EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_import_enum" )));
+
+  EXPECT_FALSE(reflection->HasField(message, F("optional_string_piece")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_cord")));
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , reflection->GetInt32 (message, F("optional_int32"   )));
+  EXPECT_EQ(0    , reflection->GetInt64 (message, F("optional_int64"   )));
+  EXPECT_EQ(0    , reflection->GetUInt32(message, F("optional_uint32"  )));
+  EXPECT_EQ(0    , reflection->GetUInt64(message, F("optional_uint64"  )));
+  EXPECT_EQ(0    , reflection->GetInt32 (message, F("optional_sint32"  )));
+  EXPECT_EQ(0    , reflection->GetInt64 (message, F("optional_sint64"  )));
+  EXPECT_EQ(0    , reflection->GetUInt32(message, F("optional_fixed32" )));
+  EXPECT_EQ(0    , reflection->GetUInt64(message, F("optional_fixed64" )));
+  EXPECT_EQ(0    , reflection->GetInt32 (message, F("optional_sfixed32")));
+  EXPECT_EQ(0    , reflection->GetInt64 (message, F("optional_sfixed64")));
+  EXPECT_EQ(0    , reflection->GetFloat (message, F("optional_float"   )));
+  EXPECT_EQ(0    , reflection->GetDouble(message, F("optional_double"  )));
+  EXPECT_FALSE(    reflection->GetBool  (message, F("optional_bool"    )));
+  EXPECT_EQ(""   , reflection->GetString(message, F("optional_string"  )));
+  EXPECT_EQ(""   , reflection->GetString(message, F("optional_bytes"   )));
+
+  EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string"), &scratch));
+  EXPECT_EQ("", reflection->GetStringReference(message, F("optional_bytes" ), &scratch));
+
+  // Embedded messages should also be clear.
+  sub_message = &reflection->GetMessage(message, F("optionalgroup"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, group_a_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, group_a_));
+  sub_message = &reflection->GetMessage(message, F("optional_nested_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+  sub_message = &reflection->GetMessage(message, F("optional_foreign_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
+  sub_message = &reflection->GetMessage(message, F("optional_import_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("optional_nested_enum" )));
+  EXPECT_EQ(foreign_foo_, reflection->GetEnum(message, F("optional_foreign_enum")));
+  EXPECT_EQ( import_foo_, reflection->GetEnum(message, F("optional_import_enum" )));
+
+  EXPECT_EQ("", reflection->GetString(message, F("optional_string_piece")));
+  EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string_piece"), &scratch));
+
+  EXPECT_EQ("", reflection->GetString(message, F("optional_cord")));
+  EXPECT_EQ("", reflection->GetStringReference(message, F("optional_cord"), &scratch));
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int32"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int64"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint32"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint64"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint32"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint64"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed32" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed64" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_float"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_double"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bool"    )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bytes"   )));
+
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeatedgroup"           )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum"    )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum"    )));
+
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string_piece")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_cord")));
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(reflection->HasField(message, F("default_int32"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_int64"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_uint32"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_uint64"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_sint32"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_sint64"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_fixed32" )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_fixed64" )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_sfixed32")));
+  EXPECT_FALSE(reflection->HasField(message, F("default_sfixed64")));
+  EXPECT_FALSE(reflection->HasField(message, F("default_float"   )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_double"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_bool"    )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_string"  )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_bytes"   )));
+
+  EXPECT_FALSE(reflection->HasField(message, F("default_nested_enum" )));
+  EXPECT_FALSE(reflection->HasField(message, F("default_foreign_enum")));
+  EXPECT_FALSE(reflection->HasField(message, F("default_import_enum" )));
+
+  EXPECT_FALSE(reflection->HasField(message, F("default_string_piece")));
+  EXPECT_FALSE(reflection->HasField(message, F("default_cord")));
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , reflection->GetInt32 (message, F("default_int32"   )));
+  EXPECT_EQ( 42    , reflection->GetInt64 (message, F("default_int64"   )));
+  EXPECT_EQ( 43    , reflection->GetUInt32(message, F("default_uint32"  )));
+  EXPECT_EQ( 44    , reflection->GetUInt64(message, F("default_uint64"  )));
+  EXPECT_EQ(-45    , reflection->GetInt32 (message, F("default_sint32"  )));
+  EXPECT_EQ( 46    , reflection->GetInt64 (message, F("default_sint64"  )));
+  EXPECT_EQ( 47    , reflection->GetUInt32(message, F("default_fixed32" )));
+  EXPECT_EQ( 48    , reflection->GetUInt64(message, F("default_fixed64" )));
+  EXPECT_EQ( 49    , reflection->GetInt32 (message, F("default_sfixed32")));
+  EXPECT_EQ(-50    , reflection->GetInt64 (message, F("default_sfixed64")));
+  EXPECT_EQ( 51.5  , reflection->GetFloat (message, F("default_float"   )));
+  EXPECT_EQ( 52e3  , reflection->GetDouble(message, F("default_double"  )));
+  EXPECT_TRUE(       reflection->GetBool  (message, F("default_bool"    )));
+  EXPECT_EQ("hello", reflection->GetString(message, F("default_string"  )));
+  EXPECT_EQ("world", reflection->GetString(message, F("default_bytes"   )));
+
+  EXPECT_EQ("hello", reflection->GetStringReference(message, F("default_string"), &scratch));
+  EXPECT_EQ("world", reflection->GetStringReference(message, F("default_bytes" ), &scratch));
+
+  EXPECT_EQ( nested_bar_, reflection->GetEnum(message, F("default_nested_enum" )));
+  EXPECT_EQ(foreign_bar_, reflection->GetEnum(message, F("default_foreign_enum")));
+  EXPECT_EQ( import_bar_, reflection->GetEnum(message, F("default_import_enum" )));
+
+  EXPECT_EQ("abc", reflection->GetString(message, F("default_string_piece")));
+  EXPECT_EQ("abc", reflection->GetStringReference(message, F("default_string_piece"), &scratch));
+
+  EXPECT_EQ("123", reflection->GetString(message, F("default_cord")));
+  EXPECT_EQ("123", reflection->GetStringReference(message, F("default_cord"), &scratch));
+}
+
+void TestUtil::ReflectionTester::ExpectPackedClearViaReflection(
+    const Message& message) {
+  const Reflection* reflection = message.GetReflection();
+
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int32"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int64"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint32"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint64"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint32"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint64"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed32" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed64" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed32")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed64")));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_float"   )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_double"  )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_bool"    )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("packed_enum"    )));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  Message* sub_message;
+
+  reflection->SetRepeatedInt32 (message, F("repeated_int32"   ), 1, 501);
+  reflection->SetRepeatedInt64 (message, F("repeated_int64"   ), 1, 502);
+  reflection->SetRepeatedUInt32(message, F("repeated_uint32"  ), 1, 503);
+  reflection->SetRepeatedUInt64(message, F("repeated_uint64"  ), 1, 504);
+  reflection->SetRepeatedInt32 (message, F("repeated_sint32"  ), 1, 505);
+  reflection->SetRepeatedInt64 (message, F("repeated_sint64"  ), 1, 506);
+  reflection->SetRepeatedUInt32(message, F("repeated_fixed32" ), 1, 507);
+  reflection->SetRepeatedUInt64(message, F("repeated_fixed64" ), 1, 508);
+  reflection->SetRepeatedInt32 (message, F("repeated_sfixed32"), 1, 509);
+  reflection->SetRepeatedInt64 (message, F("repeated_sfixed64"), 1, 510);
+  reflection->SetRepeatedFloat (message, F("repeated_float"   ), 1, 511);
+  reflection->SetRepeatedDouble(message, F("repeated_double"  ), 1, 512);
+  reflection->SetRepeatedBool  (message, F("repeated_bool"    ), 1, true);
+  reflection->SetRepeatedString(message, F("repeated_string"  ), 1, "515");
+  reflection->SetRepeatedString(message, F("repeated_bytes"   ), 1, "516");
+
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeatedgroup"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 517);
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeated_nested_message"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 518);
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeated_foreign_message"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519);
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeated_import_message"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520);
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeated_lazy_message"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527);
+
+  reflection->SetRepeatedEnum(message, F("repeated_nested_enum" ), 1,  nested_foo_);
+  reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, foreign_foo_);
+  reflection->SetRepeatedEnum(message, F("repeated_import_enum" ), 1,  import_foo_);
+
+  reflection->SetRepeatedString(message, F("repeated_string_piece"), 1, "524");
+  reflection->SetRepeatedString(message, F("repeated_cord"), 1, "525");
+}
+
+void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+  reflection->SetRepeatedInt32 (message, F("packed_int32"   ), 1, 801);
+  reflection->SetRepeatedInt64 (message, F("packed_int64"   ), 1, 802);
+  reflection->SetRepeatedUInt32(message, F("packed_uint32"  ), 1, 803);
+  reflection->SetRepeatedUInt64(message, F("packed_uint64"  ), 1, 804);
+  reflection->SetRepeatedInt32 (message, F("packed_sint32"  ), 1, 805);
+  reflection->SetRepeatedInt64 (message, F("packed_sint64"  ), 1, 806);
+  reflection->SetRepeatedUInt32(message, F("packed_fixed32" ), 1, 807);
+  reflection->SetRepeatedUInt64(message, F("packed_fixed64" ), 1, 808);
+  reflection->SetRepeatedInt32 (message, F("packed_sfixed32"), 1, 809);
+  reflection->SetRepeatedInt64 (message, F("packed_sfixed64"), 1, 810);
+  reflection->SetRepeatedFloat (message, F("packed_float"   ), 1, 811);
+  reflection->SetRepeatedDouble(message, F("packed_double"  ), 1, 812);
+  reflection->SetRepeatedBool  (message, F("packed_bool"    ), 1, true);
+  reflection->SetRepeatedEnum  (message, F("packed_enum"    ), 1, foreign_foo_);
+}
+
+void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i=0; i<output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+
+    reflection->RemoveLast(message, field);
+  }
+}
+
+void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection(
+    Message* message, bool expect_extensions_notnull) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i=0; i<output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    Message* released = reflection->ReleaseLast(message, field);
+    if (!field->is_extension() || expect_extensions_notnull) {
+      ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: "
+                                    << field->name();
+    }
+    delete released;
+  }
+}
+
+void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i=0; i<output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+
+    reflection->SwapElements(message, field, 0, 1);
+  }
+}
+
+void TestUtil::ReflectionTester::
+SetAllocatedOptionalMessageFieldsToNullViaReflection(
+    Message* message) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(*message, &fields);
+
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    if (!field->is_optional() ||
+        field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    reflection->SetAllocatedMessage(message, NULL, field);
+  }
+}
+
+void TestUtil::ReflectionTester::
+SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+    Message* from_message,
+    Message* to_message) {
+  EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor());
+  const Reflection* from_reflection = from_message->GetReflection();
+  const Reflection* to_reflection = to_message->GetReflection();
+
+  vector<const FieldDescriptor*> fields;
+  from_reflection->ListFields(*from_message, &fields);
+
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    if (!field->is_optional() ||
+        field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    Message* sub_message =
+        from_reflection->ReleaseMessage(from_message, field);
+    to_reflection->SetAllocatedMessage(to_message, sub_message, field);
+  }
+}
+
+void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection(
+    Message* message,
+    TestUtil::ReflectionTester::MessageReleaseState expected_release_state) {
+  const Reflection* reflection = message->GetReflection();
+
+  static const char* fields[] = {
+    "optionalgroup",
+    "optional_nested_message",
+    "optional_foreign_message",
+    "optional_import_message",
+  };
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) {
+    const Message& sub_message = reflection->GetMessage(*message, F(fields[i]));
+    Message* released = reflection->ReleaseMessage(message, F(fields[i]));
+    switch (expected_release_state) {
+      case IS_NULL:
+        EXPECT_TRUE(released == NULL);
+        break;
+      case NOT_NULL:
+        EXPECT_TRUE(released != NULL);
+        EXPECT_EQ(&sub_message, released);
+        break;
+      case CAN_BE_NULL:
+        break;
+    }
+    delete released;
+    EXPECT_FALSE(reflection->HasField(*message, F(fields[i])));
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/test_util.h b/src/third_party/protobuf-3/src/google/protobuf/test_util.h
new file mode 100644
index 0000000..1c13a1a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/test_util.h
@@ -0,0 +1,215 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_TEST_UTIL_H__
+
+#include <stack>
+#include <string>
+#include <google/protobuf/message.h>
+#include <google/protobuf/unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+namespace unittest_import = protobuf_unittest_import;
+
+class TestUtil {
+ public:
+  // Set every field in the message to a unique value.
+  static void SetAllFields(unittest::TestAllTypes* message);
+  static void SetOptionalFields(unittest::TestAllTypes* message);
+  static void AddRepeatedFields1(unittest::TestAllTypes* message);
+  static void AddRepeatedFields2(unittest::TestAllTypes* message);
+  static void SetDefaultFields(unittest::TestAllTypes* message);
+  static void SetOneofFields(unittest::TestAllTypes* message);
+  static void SetAllExtensions(unittest::TestAllExtensions* message);
+  static void SetOneofFields(unittest::TestAllExtensions* message);
+  static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
+  static void SetPackedFields(unittest::TestPackedTypes* message);
+  static void SetPackedExtensions(unittest::TestPackedExtensions* message);
+  static void SetUnpackedFields(unittest::TestUnpackedTypes* message);
+  static void SetOneof1(unittest::TestOneof2* message);
+  static void SetOneof2(unittest::TestOneof2* message);
+
+  // Use the repeated versions of the set_*() accessors to modify all the
+  // repeated fields of the message (which should already have been
+  // initialized with Set*Fields()).  Set*Fields() itself only tests
+  // the add_*() accessors.
+  static void ModifyRepeatedFields(unittest::TestAllTypes* message);
+  static void ModifyRepeatedExtensions(unittest::TestAllExtensions* message);
+  static void ModifyPackedFields(unittest::TestPackedTypes* message);
+  static void ModifyPackedExtensions(unittest::TestPackedExtensions* message);
+
+  // Check that all fields have the values that they should have after
+  // Set*Fields() is called.
+  static void ExpectAllFieldsSet(const unittest::TestAllTypes& message);
+  static void ExpectAllExtensionsSet(
+      const unittest::TestAllExtensions& message);
+  static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message);
+  static void ExpectPackedExtensionsSet(
+      const unittest::TestPackedExtensions& message);
+  static void ExpectUnpackedFieldsSet(
+      const unittest::TestUnpackedTypes& message);
+  static void ExpectUnpackedExtensionsSet(
+      const unittest::TestUnpackedExtensions& message);
+  static void ExpectOneofSet1(const unittest::TestOneof2& message);
+  static void ExpectOneofSet2(const unittest::TestOneof2& message);
+
+  // Expect that the message is modified as would be expected from
+  // Modify*Fields().
+  static void ExpectRepeatedFieldsModified(
+      const unittest::TestAllTypes& message);
+  static void ExpectRepeatedExtensionsModified(
+      const unittest::TestAllExtensions& message);
+  static void ExpectPackedFieldsModified(
+      const unittest::TestPackedTypes& message);
+  static void ExpectPackedExtensionsModified(
+      const unittest::TestPackedExtensions& message);
+
+  // Check that all fields have their default values.
+  static void ExpectClear(const unittest::TestAllTypes& message);
+  static void ExpectExtensionsClear(const unittest::TestAllExtensions& message);
+  static void ExpectPackedClear(const unittest::TestPackedTypes& message);
+  static void ExpectPackedExtensionsClear(
+      const unittest::TestPackedExtensions& message);
+  static void ExpectOneofClear(const unittest::TestOneof2& message);
+
+  // Check that the passed-in serialization is the canonical serialization we
+  // expect for a TestFieldOrderings message filled in by
+  // SetAllFieldsAndExtensions().
+  static void ExpectAllFieldsAndExtensionsInOrder(const string& serialized);
+
+  // Check that all repeated fields have had their last elements removed.
+  static void ExpectLastRepeatedsRemoved(
+      const unittest::TestAllTypes& message);
+  static void ExpectLastRepeatedExtensionsRemoved(
+      const unittest::TestAllExtensions& message);
+  static void ExpectLastRepeatedsReleased(
+      const unittest::TestAllTypes& message);
+  static void ExpectLastRepeatedExtensionsReleased(
+      const unittest::TestAllExtensions& message);
+
+  // Check that all repeated fields have had their first and last elements
+  // swapped.
+  static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message);
+  static void ExpectRepeatedExtensionsSwapped(
+      const unittest::TestAllExtensions& message);
+
+  static void ExpectAtMostOneFieldSetInOneof(
+      const unittest::TestOneof2 &message);
+
+  // Like above, but use the reflection interface.
+  class ReflectionTester {
+   public:
+    // base_descriptor must be a descriptor for TestAllTypes or
+    // TestAllExtensions.  In the former case, ReflectionTester fetches from
+    // it the FieldDescriptors needed to use the reflection interface.  In
+    // the latter case, ReflectionTester searches for extension fields in
+    // its file.
+    explicit ReflectionTester(const Descriptor* base_descriptor);
+
+    void SetAllFieldsViaReflection(Message* message);
+    void ModifyRepeatedFieldsViaReflection(Message* message);
+    void ExpectAllFieldsSetViaReflection(const Message& message);
+    void ExpectClearViaReflection(const Message& message);
+
+    void SetPackedFieldsViaReflection(Message* message);
+    void ModifyPackedFieldsViaReflection(Message* message);
+    void ExpectPackedFieldsSetViaReflection(const Message& message);
+    void ExpectPackedClearViaReflection(const Message& message);
+
+    void RemoveLastRepeatedsViaReflection(Message* message);
+    void ReleaseLastRepeatedsViaReflection(
+        Message* message, bool expect_extensions_notnull);
+    void SwapRepeatedsViaReflection(Message* message);
+    void SetAllocatedOptionalMessageFieldsToNullViaReflection(
+        Message* message);
+    static void SetAllocatedOptionalMessageFieldsToMessageViaReflection(
+        Message* from_message,
+        Message* to_message);
+
+    enum MessageReleaseState {
+      IS_NULL,
+      CAN_BE_NULL,
+      NOT_NULL,
+    };
+    void ExpectMessagesReleasedViaReflection(
+        Message* message, MessageReleaseState expected_release_state);
+
+    // Set and check functions for TestOneof2 messages. No need to construct
+    // the ReflectionTester by TestAllTypes nor TestAllExtensions.
+    static void SetOneofViaReflection(Message* message);
+    static void ExpectOneofSetViaReflection(const Message& message);
+
+   private:
+    const FieldDescriptor* F(const string& name);
+
+    const Descriptor* base_descriptor_;
+
+    const FieldDescriptor* group_a_;
+    const FieldDescriptor* repeated_group_a_;
+    const FieldDescriptor* nested_b_;
+    const FieldDescriptor* foreign_c_;
+    const FieldDescriptor* import_d_;
+    const FieldDescriptor* import_e_;
+
+    const EnumValueDescriptor* nested_foo_;
+    const EnumValueDescriptor* nested_bar_;
+    const EnumValueDescriptor* nested_baz_;
+    const EnumValueDescriptor* foreign_foo_;
+    const EnumValueDescriptor* foreign_bar_;
+    const EnumValueDescriptor* foreign_baz_;
+    const EnumValueDescriptor* import_foo_;
+    const EnumValueDescriptor* import_bar_;
+    const EnumValueDescriptor* import_baz_;
+
+    // We have to split this into three function otherwise it creates a stack
+    // frame so large that it triggers a warning.
+    void ExpectAllFieldsSetViaReflection1(const Message& message);
+    void ExpectAllFieldsSetViaReflection2(const Message& message);
+    void ExpectAllFieldsSetViaReflection3(const Message& message);
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester);
+  };
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtil);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_TEST_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.cc
new file mode 100644
index 0000000..388c0cb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.cc
@@ -0,0 +1,1586 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf {
+
+void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) {
+  message->set_optional_int32   (101);
+  message->set_optional_int64   (102);
+  message->set_optional_uint32  (103);
+  message->set_optional_uint64  (104);
+  message->set_optional_sint32  (105);
+  message->set_optional_sint64  (106);
+  message->set_optional_fixed32 (107);
+  message->set_optional_fixed64 (108);
+  message->set_optional_sfixed32(109);
+  message->set_optional_sfixed64(110);
+  message->set_optional_float   (111);
+  message->set_optional_double  (112);
+  message->set_optional_bool    (true);
+  message->set_optional_string  ("115");
+  message->set_optional_bytes   ("116");
+
+  message->mutable_optionalgroup                 ()->set_a(117);
+  message->mutable_optional_nested_message       ()->set_bb(118);
+  message->mutable_optional_foreign_message      ()->set_c(119);
+  message->mutable_optional_import_message       ()->set_d(120);
+  message->mutable_optional_public_import_message()->set_e(126);
+  message->mutable_optional_lazy_message         ()->set_bb(127);
+
+  message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ );
+  message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
+  message->set_optional_import_enum (unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->add_repeated_int32   (201);
+  message->add_repeated_int64   (202);
+  message->add_repeated_uint32  (203);
+  message->add_repeated_uint64  (204);
+  message->add_repeated_sint32  (205);
+  message->add_repeated_sint64  (206);
+  message->add_repeated_fixed32 (207);
+  message->add_repeated_fixed64 (208);
+  message->add_repeated_sfixed32(209);
+  message->add_repeated_sfixed64(210);
+  message->add_repeated_float   (211);
+  message->add_repeated_double  (212);
+  message->add_repeated_bool    (true);
+  message->add_repeated_string  ("215");
+  message->add_repeated_bytes   ("216");
+
+  message->add_repeatedgroup           ()->set_a(217);
+  message->add_repeated_nested_message ()->set_bb(218);
+  message->add_repeated_foreign_message()->set_c(219);
+  message->add_repeated_import_message ()->set_d(220);
+  message->add_repeated_lazy_message   ()->set_bb(227);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR );
+  message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAR);
+
+
+  // Add a second one of each field.
+  message->add_repeated_int32   (301);
+  message->add_repeated_int64   (302);
+  message->add_repeated_uint32  (303);
+  message->add_repeated_uint64  (304);
+  message->add_repeated_sint32  (305);
+  message->add_repeated_sint64  (306);
+  message->add_repeated_fixed32 (307);
+  message->add_repeated_fixed64 (308);
+  message->add_repeated_sfixed32(309);
+  message->add_repeated_sfixed64(310);
+  message->add_repeated_float   (311);
+  message->add_repeated_double  (312);
+  message->add_repeated_bool    (false);
+  message->add_repeated_string  ("315");
+  message->add_repeated_bytes   ("316");
+
+  message->add_repeatedgroup           ()->set_a(317);
+  message->add_repeated_nested_message ()->set_bb(318);
+  message->add_repeated_foreign_message()->set_c(319);
+  message->add_repeated_import_message ()->set_d(320);
+  message->add_repeated_lazy_message   ()->set_bb(327);
+
+  message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ );
+  message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
+  message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->set_default_int32   (401);
+  message->set_default_int64   (402);
+  message->set_default_uint32  (403);
+  message->set_default_uint64  (404);
+  message->set_default_sint32  (405);
+  message->set_default_sint64  (406);
+  message->set_default_fixed32 (407);
+  message->set_default_fixed64 (408);
+  message->set_default_sfixed32(409);
+  message->set_default_sfixed64(410);
+  message->set_default_float   (411);
+  message->set_default_double  (412);
+  message->set_default_bool    (false);
+  message->set_default_string  ("415");
+  message->set_default_bytes   ("416");
+
+  message->set_default_nested_enum (unittest::TestAllTypesLite::FOO );
+  message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO      );
+  message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO);
+
+
+  message->set_oneof_uint32(601);
+  message->mutable_oneof_nested_message()->set_bb(602);
+  message->set_oneof_string("603");
+  message->set_oneof_bytes("604");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) {
+  message->set_repeated_int32   (1, 501);
+  message->set_repeated_int64   (1, 502);
+  message->set_repeated_uint32  (1, 503);
+  message->set_repeated_uint64  (1, 504);
+  message->set_repeated_sint32  (1, 505);
+  message->set_repeated_sint64  (1, 506);
+  message->set_repeated_fixed32 (1, 507);
+  message->set_repeated_fixed64 (1, 508);
+  message->set_repeated_sfixed32(1, 509);
+  message->set_repeated_sfixed64(1, 510);
+  message->set_repeated_float   (1, 511);
+  message->set_repeated_double  (1, 512);
+  message->set_repeated_bool    (1, true);
+  message->set_repeated_string  (1, "515");
+  message->set_repeated_bytes   (1, "516");
+
+  message->mutable_repeatedgroup           (1)->set_a(517);
+  message->mutable_repeated_nested_message (1)->set_bb(518);
+  message->mutable_repeated_foreign_message(1)->set_c(519);
+  message->mutable_repeated_import_message (1)->set_d(520);
+  message->mutable_repeated_lazy_message   (1)->set_bb(527);
+
+  message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO );
+  message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO      );
+  message->set_repeated_import_enum (1, unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectAllFieldsSet(
+    const unittest::TestAllTypesLite& message) {
+  EXPECT_TRUE(message.has_optional_int32   ());
+  EXPECT_TRUE(message.has_optional_int64   ());
+  EXPECT_TRUE(message.has_optional_uint32  ());
+  EXPECT_TRUE(message.has_optional_uint64  ());
+  EXPECT_TRUE(message.has_optional_sint32  ());
+  EXPECT_TRUE(message.has_optional_sint64  ());
+  EXPECT_TRUE(message.has_optional_fixed32 ());
+  EXPECT_TRUE(message.has_optional_fixed64 ());
+  EXPECT_TRUE(message.has_optional_sfixed32());
+  EXPECT_TRUE(message.has_optional_sfixed64());
+  EXPECT_TRUE(message.has_optional_float   ());
+  EXPECT_TRUE(message.has_optional_double  ());
+  EXPECT_TRUE(message.has_optional_bool    ());
+  EXPECT_TRUE(message.has_optional_string  ());
+  EXPECT_TRUE(message.has_optional_bytes   ());
+
+  EXPECT_TRUE(message.has_optionalgroup                 ());
+  EXPECT_TRUE(message.has_optional_nested_message       ());
+  EXPECT_TRUE(message.has_optional_foreign_message      ());
+  EXPECT_TRUE(message.has_optional_import_message       ());
+  EXPECT_TRUE(message.has_optional_public_import_message());
+  EXPECT_TRUE(message.has_optional_lazy_message         ());
+
+  EXPECT_TRUE(message.optionalgroup                 ().has_a());
+  EXPECT_TRUE(message.optional_nested_message       ().has_bb());
+  EXPECT_TRUE(message.optional_foreign_message      ().has_c());
+  EXPECT_TRUE(message.optional_import_message       ().has_d());
+  EXPECT_TRUE(message.optional_public_import_message().has_e());
+  EXPECT_TRUE(message.optional_lazy_message         ().has_bb());
+
+  EXPECT_TRUE(message.has_optional_nested_enum ());
+  EXPECT_TRUE(message.has_optional_foreign_enum());
+  EXPECT_TRUE(message.has_optional_import_enum ());
+
+
+  EXPECT_EQ(101  , message.optional_int32   ());
+  EXPECT_EQ(102  , message.optional_int64   ());
+  EXPECT_EQ(103  , message.optional_uint32  ());
+  EXPECT_EQ(104  , message.optional_uint64  ());
+  EXPECT_EQ(105  , message.optional_sint32  ());
+  EXPECT_EQ(106  , message.optional_sint64  ());
+  EXPECT_EQ(107  , message.optional_fixed32 ());
+  EXPECT_EQ(108  , message.optional_fixed64 ());
+  EXPECT_EQ(109  , message.optional_sfixed32());
+  EXPECT_EQ(110  , message.optional_sfixed64());
+  EXPECT_EQ(111  , message.optional_float   ());
+  EXPECT_EQ(112  , message.optional_double  ());
+  EXPECT_EQ(true , message.optional_bool    ());
+  EXPECT_EQ("115", message.optional_string  ());
+  EXPECT_EQ("116", message.optional_bytes   ());
+
+  EXPECT_EQ(117, message.optionalgroup                 ().a());
+  EXPECT_EQ(118, message.optional_nested_message       ().bb());
+  EXPECT_EQ(119, message.optional_foreign_message      ().c());
+  EXPECT_EQ(120, message.optional_import_message       ().d());
+  EXPECT_EQ(126, message.optional_public_import_message().e());
+  EXPECT_EQ(127, message.optional_lazy_message         ().bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.optional_import_enum ());
+
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_EQ(true , message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
+
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0));
+
+  EXPECT_EQ(301  , message.repeated_int32   (1));
+  EXPECT_EQ(302  , message.repeated_int64   (1));
+  EXPECT_EQ(303  , message.repeated_uint32  (1));
+  EXPECT_EQ(304  , message.repeated_uint64  (1));
+  EXPECT_EQ(305  , message.repeated_sint32  (1));
+  EXPECT_EQ(306  , message.repeated_sint64  (1));
+  EXPECT_EQ(307  , message.repeated_fixed32 (1));
+  EXPECT_EQ(308  , message.repeated_fixed64 (1));
+  EXPECT_EQ(309  , message.repeated_sfixed32(1));
+  EXPECT_EQ(310  , message.repeated_sfixed64(1));
+  EXPECT_EQ(311  , message.repeated_float   (1));
+  EXPECT_EQ(312  , message.repeated_double  (1));
+  EXPECT_EQ(false, message.repeated_bool    (1));
+  EXPECT_EQ("315", message.repeated_string  (1));
+  EXPECT_EQ("316", message.repeated_bytes   (1));
+
+  EXPECT_EQ(317, message.repeatedgroup           (1).a());
+  EXPECT_EQ(318, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(319, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(320, message.repeated_import_message (1).d());
+  EXPECT_EQ(327, message.repeated_lazy_message   (1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.repeated_import_enum (1));
+
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.has_default_int32   ());
+  EXPECT_TRUE(message.has_default_int64   ());
+  EXPECT_TRUE(message.has_default_uint32  ());
+  EXPECT_TRUE(message.has_default_uint64  ());
+  EXPECT_TRUE(message.has_default_sint32  ());
+  EXPECT_TRUE(message.has_default_sint64  ());
+  EXPECT_TRUE(message.has_default_fixed32 ());
+  EXPECT_TRUE(message.has_default_fixed64 ());
+  EXPECT_TRUE(message.has_default_sfixed32());
+  EXPECT_TRUE(message.has_default_sfixed64());
+  EXPECT_TRUE(message.has_default_float   ());
+  EXPECT_TRUE(message.has_default_double  ());
+  EXPECT_TRUE(message.has_default_bool    ());
+  EXPECT_TRUE(message.has_default_string  ());
+  EXPECT_TRUE(message.has_default_bytes   ());
+
+  EXPECT_TRUE(message.has_default_nested_enum ());
+  EXPECT_TRUE(message.has_default_foreign_enum());
+  EXPECT_TRUE(message.has_default_import_enum ());
+
+
+  EXPECT_EQ(401  , message.default_int32   ());
+  EXPECT_EQ(402  , message.default_int64   ());
+  EXPECT_EQ(403  , message.default_uint32  ());
+  EXPECT_EQ(404  , message.default_uint64  ());
+  EXPECT_EQ(405  , message.default_sint32  ());
+  EXPECT_EQ(406  , message.default_sint64  ());
+  EXPECT_EQ(407  , message.default_fixed32 ());
+  EXPECT_EQ(408  , message.default_fixed64 ());
+  EXPECT_EQ(409  , message.default_sfixed32());
+  EXPECT_EQ(410  , message.default_sfixed64());
+  EXPECT_EQ(411  , message.default_float   ());
+  EXPECT_EQ(412  , message.default_double  ());
+  EXPECT_EQ(false, message.default_bool    ());
+  EXPECT_EQ("415", message.default_string  ());
+  EXPECT_EQ("416", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ());
+
+
+  EXPECT_FALSE(message.has_oneof_uint32        ());
+  EXPECT_FALSE(message.has_oneof_nested_message());
+  EXPECT_FALSE(message.has_oneof_string        ());
+  EXPECT_TRUE(message.has_oneof_bytes          ());
+
+  EXPECT_EQ("604", message.oneof_bytes());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) {
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.has_optional_int32   ());
+  EXPECT_FALSE(message.has_optional_int64   ());
+  EXPECT_FALSE(message.has_optional_uint32  ());
+  EXPECT_FALSE(message.has_optional_uint64  ());
+  EXPECT_FALSE(message.has_optional_sint32  ());
+  EXPECT_FALSE(message.has_optional_sint64  ());
+  EXPECT_FALSE(message.has_optional_fixed32 ());
+  EXPECT_FALSE(message.has_optional_fixed64 ());
+  EXPECT_FALSE(message.has_optional_sfixed32());
+  EXPECT_FALSE(message.has_optional_sfixed64());
+  EXPECT_FALSE(message.has_optional_float   ());
+  EXPECT_FALSE(message.has_optional_double  ());
+  EXPECT_FALSE(message.has_optional_bool    ());
+  EXPECT_FALSE(message.has_optional_string  ());
+  EXPECT_FALSE(message.has_optional_bytes   ());
+
+  EXPECT_FALSE(message.has_optionalgroup                 ());
+  EXPECT_FALSE(message.has_optional_nested_message       ());
+  EXPECT_FALSE(message.has_optional_foreign_message      ());
+  EXPECT_FALSE(message.has_optional_import_message       ());
+  EXPECT_FALSE(message.has_optional_public_import_message());
+  EXPECT_FALSE(message.has_optional_lazy_message         ());
+
+  EXPECT_FALSE(message.has_optional_nested_enum ());
+  EXPECT_FALSE(message.has_optional_foreign_enum());
+  EXPECT_FALSE(message.has_optional_import_enum ());
+
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.optional_int32   ());
+  EXPECT_EQ(0    , message.optional_int64   ());
+  EXPECT_EQ(0    , message.optional_uint32  ());
+  EXPECT_EQ(0    , message.optional_uint64  ());
+  EXPECT_EQ(0    , message.optional_sint32  ());
+  EXPECT_EQ(0    , message.optional_sint64  ());
+  EXPECT_EQ(0    , message.optional_fixed32 ());
+  EXPECT_EQ(0    , message.optional_fixed64 ());
+  EXPECT_EQ(0    , message.optional_sfixed32());
+  EXPECT_EQ(0    , message.optional_sfixed64());
+  EXPECT_EQ(0    , message.optional_float   ());
+  EXPECT_EQ(0    , message.optional_double  ());
+  EXPECT_EQ(false, message.optional_bool    ());
+  EXPECT_EQ(""   , message.optional_string  ());
+  EXPECT_EQ(""   , message.optional_bytes   ());
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.optionalgroup                 ().has_a());
+  EXPECT_FALSE(message.optional_nested_message       ().has_bb());
+  EXPECT_FALSE(message.optional_foreign_message      ().has_c());
+  EXPECT_FALSE(message.optional_import_message       ().has_d());
+  EXPECT_FALSE(message.optional_public_import_message().has_e());
+  EXPECT_FALSE(message.optional_lazy_message         ().has_bb());
+
+  EXPECT_EQ(0, message.optionalgroup           ().a());
+  EXPECT_EQ(0, message.optional_nested_message ().bb());
+  EXPECT_EQ(0, message.optional_foreign_message().c());
+  EXPECT_EQ(0, message.optional_import_message ().d());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.optional_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.optional_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.optional_import_enum ());
+
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.repeated_int32_size   ());
+  EXPECT_EQ(0, message.repeated_int64_size   ());
+  EXPECT_EQ(0, message.repeated_uint32_size  ());
+  EXPECT_EQ(0, message.repeated_uint64_size  ());
+  EXPECT_EQ(0, message.repeated_sint32_size  ());
+  EXPECT_EQ(0, message.repeated_sint64_size  ());
+  EXPECT_EQ(0, message.repeated_fixed32_size ());
+  EXPECT_EQ(0, message.repeated_fixed64_size ());
+  EXPECT_EQ(0, message.repeated_sfixed32_size());
+  EXPECT_EQ(0, message.repeated_sfixed64_size());
+  EXPECT_EQ(0, message.repeated_float_size   ());
+  EXPECT_EQ(0, message.repeated_double_size  ());
+  EXPECT_EQ(0, message.repeated_bool_size    ());
+  EXPECT_EQ(0, message.repeated_string_size  ());
+  EXPECT_EQ(0, message.repeated_bytes_size   ());
+
+  EXPECT_EQ(0, message.repeatedgroup_size           ());
+  EXPECT_EQ(0, message.repeated_nested_message_size ());
+  EXPECT_EQ(0, message.repeated_foreign_message_size());
+  EXPECT_EQ(0, message.repeated_import_message_size ());
+  EXPECT_EQ(0, message.repeated_lazy_message_size   ());
+  EXPECT_EQ(0, message.repeated_nested_enum_size    ());
+  EXPECT_EQ(0, message.repeated_foreign_enum_size   ());
+  EXPECT_EQ(0, message.repeated_import_enum_size    ());
+
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.has_default_int32   ());
+  EXPECT_FALSE(message.has_default_int64   ());
+  EXPECT_FALSE(message.has_default_uint32  ());
+  EXPECT_FALSE(message.has_default_uint64  ());
+  EXPECT_FALSE(message.has_default_sint32  ());
+  EXPECT_FALSE(message.has_default_sint64  ());
+  EXPECT_FALSE(message.has_default_fixed32 ());
+  EXPECT_FALSE(message.has_default_fixed64 ());
+  EXPECT_FALSE(message.has_default_sfixed32());
+  EXPECT_FALSE(message.has_default_sfixed64());
+  EXPECT_FALSE(message.has_default_float   ());
+  EXPECT_FALSE(message.has_default_double  ());
+  EXPECT_FALSE(message.has_default_bool    ());
+  EXPECT_FALSE(message.has_default_string  ());
+  EXPECT_FALSE(message.has_default_bytes   ());
+
+  EXPECT_FALSE(message.has_default_nested_enum ());
+  EXPECT_FALSE(message.has_default_foreign_enum());
+  EXPECT_FALSE(message.has_default_import_enum ());
+
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.default_int32   ());
+  EXPECT_EQ( 42    , message.default_int64   ());
+  EXPECT_EQ( 43    , message.default_uint32  ());
+  EXPECT_EQ( 44    , message.default_uint64  ());
+  EXPECT_EQ(-45    , message.default_sint32  ());
+  EXPECT_EQ( 46    , message.default_sint64  ());
+  EXPECT_EQ( 47    , message.default_fixed32 ());
+  EXPECT_EQ( 48    , message.default_fixed64 ());
+  EXPECT_EQ( 49    , message.default_sfixed32());
+  EXPECT_EQ(-50    , message.default_sfixed64());
+  EXPECT_EQ( 51.5  , message.default_float   ());
+  EXPECT_EQ( 52e3  , message.default_double  ());
+  EXPECT_EQ(true   , message.default_bool    ());
+  EXPECT_EQ("hello", message.default_string  ());
+  EXPECT_EQ("world", message.default_bytes   ());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.default_nested_enum ());
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.default_foreign_enum());
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ());
+
+
+  EXPECT_FALSE(message.has_oneof_uint32        ());
+  EXPECT_FALSE(message.has_oneof_nested_message());
+  EXPECT_FALSE(message.has_oneof_string        ());
+  EXPECT_FALSE(message.has_oneof_bytes         ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectRepeatedFieldsModified(
+    const unittest::TestAllTypesLite& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.repeated_int32_size   ());
+  ASSERT_EQ(2, message.repeated_int64_size   ());
+  ASSERT_EQ(2, message.repeated_uint32_size  ());
+  ASSERT_EQ(2, message.repeated_uint64_size  ());
+  ASSERT_EQ(2, message.repeated_sint32_size  ());
+  ASSERT_EQ(2, message.repeated_sint64_size  ());
+  ASSERT_EQ(2, message.repeated_fixed32_size ());
+  ASSERT_EQ(2, message.repeated_fixed64_size ());
+  ASSERT_EQ(2, message.repeated_sfixed32_size());
+  ASSERT_EQ(2, message.repeated_sfixed64_size());
+  ASSERT_EQ(2, message.repeated_float_size   ());
+  ASSERT_EQ(2, message.repeated_double_size  ());
+  ASSERT_EQ(2, message.repeated_bool_size    ());
+  ASSERT_EQ(2, message.repeated_string_size  ());
+  ASSERT_EQ(2, message.repeated_bytes_size   ());
+
+  ASSERT_EQ(2, message.repeatedgroup_size           ());
+  ASSERT_EQ(2, message.repeated_nested_message_size ());
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
+  ASSERT_EQ(2, message.repeated_nested_enum_size    ());
+  ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
+  ASSERT_EQ(2, message.repeated_import_enum_size    ());
+
+
+  EXPECT_EQ(201  , message.repeated_int32   (0));
+  EXPECT_EQ(202  , message.repeated_int64   (0));
+  EXPECT_EQ(203  , message.repeated_uint32  (0));
+  EXPECT_EQ(204  , message.repeated_uint64  (0));
+  EXPECT_EQ(205  , message.repeated_sint32  (0));
+  EXPECT_EQ(206  , message.repeated_sint64  (0));
+  EXPECT_EQ(207  , message.repeated_fixed32 (0));
+  EXPECT_EQ(208  , message.repeated_fixed64 (0));
+  EXPECT_EQ(209  , message.repeated_sfixed32(0));
+  EXPECT_EQ(210  , message.repeated_sfixed64(0));
+  EXPECT_EQ(211  , message.repeated_float   (0));
+  EXPECT_EQ(212  , message.repeated_double  (0));
+  EXPECT_EQ(true , message.repeated_bool    (0));
+  EXPECT_EQ("215", message.repeated_string  (0));
+  EXPECT_EQ("216", message.repeated_bytes   (0));
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.repeated_foreign_enum(0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0));
+
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.repeated_int32   (1));
+  EXPECT_EQ(502  , message.repeated_int64   (1));
+  EXPECT_EQ(503  , message.repeated_uint32  (1));
+  EXPECT_EQ(504  , message.repeated_uint64  (1));
+  EXPECT_EQ(505  , message.repeated_sint32  (1));
+  EXPECT_EQ(506  , message.repeated_sint64  (1));
+  EXPECT_EQ(507  , message.repeated_fixed32 (1));
+  EXPECT_EQ(508  , message.repeated_fixed64 (1));
+  EXPECT_EQ(509  , message.repeated_sfixed32(1));
+  EXPECT_EQ(510  , message.repeated_sfixed64(1));
+  EXPECT_EQ(511  , message.repeated_float   (1));
+  EXPECT_EQ(512  , message.repeated_double  (1));
+  EXPECT_EQ(true , message.repeated_bool    (1));
+  EXPECT_EQ("515", message.repeated_string  (1));
+  EXPECT_EQ("516", message.repeated_bytes   (1));
+
+  EXPECT_EQ(517, message.repeatedgroup           (1).a());
+  EXPECT_EQ(518, message.repeated_nested_message (1).bb());
+  EXPECT_EQ(519, message.repeated_foreign_message(1).c());
+  EXPECT_EQ(520, message.repeated_import_message (1).d());
+  EXPECT_EQ(527, message.repeated_lazy_message   (1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.repeated_foreign_enum(1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum (1));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::SetPackedFields(unittest::TestPackedTypesLite* message) {
+  message->add_packed_int32   (601);
+  message->add_packed_int64   (602);
+  message->add_packed_uint32  (603);
+  message->add_packed_uint64  (604);
+  message->add_packed_sint32  (605);
+  message->add_packed_sint64  (606);
+  message->add_packed_fixed32 (607);
+  message->add_packed_fixed64 (608);
+  message->add_packed_sfixed32(609);
+  message->add_packed_sfixed64(610);
+  message->add_packed_float   (611);
+  message->add_packed_double  (612);
+  message->add_packed_bool    (true);
+  message->add_packed_enum    (unittest::FOREIGN_LITE_BAR);
+  // add a second one of each field
+  message->add_packed_int32   (701);
+  message->add_packed_int64   (702);
+  message->add_packed_uint32  (703);
+  message->add_packed_uint64  (704);
+  message->add_packed_sint32  (705);
+  message->add_packed_sint64  (706);
+  message->add_packed_fixed32 (707);
+  message->add_packed_fixed64 (708);
+  message->add_packed_sfixed32(709);
+  message->add_packed_sfixed64(710);
+  message->add_packed_float   (711);
+  message->add_packed_double  (712);
+  message->add_packed_bool    (false);
+  message->add_packed_enum    (unittest::FOREIGN_LITE_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyPackedFields(unittest::TestPackedTypesLite* message) {
+  message->set_packed_int32   (1, 801);
+  message->set_packed_int64   (1, 802);
+  message->set_packed_uint32  (1, 803);
+  message->set_packed_uint64  (1, 804);
+  message->set_packed_sint32  (1, 805);
+  message->set_packed_sint64  (1, 806);
+  message->set_packed_fixed32 (1, 807);
+  message->set_packed_fixed64 (1, 808);
+  message->set_packed_sfixed32(1, 809);
+  message->set_packed_sfixed64(1, 810);
+  message->set_packed_float   (1, 811);
+  message->set_packed_double  (1, 812);
+  message->set_packed_bool    (1, true);
+  message->set_packed_enum    (1, unittest::FOREIGN_LITE_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedFieldsSet(
+    const unittest::TestPackedTypesLite& message) {
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_EQ(true , message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0));
+
+  EXPECT_EQ(701  , message.packed_int32   (1));
+  EXPECT_EQ(702  , message.packed_int64   (1));
+  EXPECT_EQ(703  , message.packed_uint32  (1));
+  EXPECT_EQ(704  , message.packed_uint64  (1));
+  EXPECT_EQ(705  , message.packed_sint32  (1));
+  EXPECT_EQ(706  , message.packed_sint64  (1));
+  EXPECT_EQ(707  , message.packed_fixed32 (1));
+  EXPECT_EQ(708  , message.packed_fixed64 (1));
+  EXPECT_EQ(709  , message.packed_sfixed32(1));
+  EXPECT_EQ(710  , message.packed_sfixed64(1));
+  EXPECT_EQ(711  , message.packed_float   (1));
+  EXPECT_EQ(712  , message.packed_double  (1));
+  EXPECT_EQ(false, message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedClear(
+    const unittest::TestPackedTypesLite& message) {
+  // Packed repeated fields are empty.
+  EXPECT_EQ(0, message.packed_int32_size   ());
+  EXPECT_EQ(0, message.packed_int64_size   ());
+  EXPECT_EQ(0, message.packed_uint32_size  ());
+  EXPECT_EQ(0, message.packed_uint64_size  ());
+  EXPECT_EQ(0, message.packed_sint32_size  ());
+  EXPECT_EQ(0, message.packed_sint64_size  ());
+  EXPECT_EQ(0, message.packed_fixed32_size ());
+  EXPECT_EQ(0, message.packed_fixed64_size ());
+  EXPECT_EQ(0, message.packed_sfixed32_size());
+  EXPECT_EQ(0, message.packed_sfixed64_size());
+  EXPECT_EQ(0, message.packed_float_size   ());
+  EXPECT_EQ(0, message.packed_double_size  ());
+  EXPECT_EQ(0, message.packed_bool_size    ());
+  EXPECT_EQ(0, message.packed_enum_size    ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedFieldsModified(
+    const unittest::TestPackedTypesLite& message) {
+  // Do the same for packed repeated fields.
+  ASSERT_EQ(2, message.packed_int32_size   ());
+  ASSERT_EQ(2, message.packed_int64_size   ());
+  ASSERT_EQ(2, message.packed_uint32_size  ());
+  ASSERT_EQ(2, message.packed_uint64_size  ());
+  ASSERT_EQ(2, message.packed_sint32_size  ());
+  ASSERT_EQ(2, message.packed_sint64_size  ());
+  ASSERT_EQ(2, message.packed_fixed32_size ());
+  ASSERT_EQ(2, message.packed_fixed64_size ());
+  ASSERT_EQ(2, message.packed_sfixed32_size());
+  ASSERT_EQ(2, message.packed_sfixed64_size());
+  ASSERT_EQ(2, message.packed_float_size   ());
+  ASSERT_EQ(2, message.packed_double_size  ());
+  ASSERT_EQ(2, message.packed_bool_size    ());
+  ASSERT_EQ(2, message.packed_enum_size    ());
+
+  EXPECT_EQ(601  , message.packed_int32   (0));
+  EXPECT_EQ(602  , message.packed_int64   (0));
+  EXPECT_EQ(603  , message.packed_uint32  (0));
+  EXPECT_EQ(604  , message.packed_uint64  (0));
+  EXPECT_EQ(605  , message.packed_sint32  (0));
+  EXPECT_EQ(606  , message.packed_sint64  (0));
+  EXPECT_EQ(607  , message.packed_fixed32 (0));
+  EXPECT_EQ(608  , message.packed_fixed64 (0));
+  EXPECT_EQ(609  , message.packed_sfixed32(0));
+  EXPECT_EQ(610  , message.packed_sfixed64(0));
+  EXPECT_EQ(611  , message.packed_float   (0));
+  EXPECT_EQ(612  , message.packed_double  (0));
+  EXPECT_EQ(true , message.packed_bool    (0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0));
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.packed_int32   (1));
+  EXPECT_EQ(802  , message.packed_int64   (1));
+  EXPECT_EQ(803  , message.packed_uint32  (1));
+  EXPECT_EQ(804  , message.packed_uint64  (1));
+  EXPECT_EQ(805  , message.packed_sint32  (1));
+  EXPECT_EQ(806  , message.packed_sint64  (1));
+  EXPECT_EQ(807  , message.packed_fixed32 (1));
+  EXPECT_EQ(808  , message.packed_fixed64 (1));
+  EXPECT_EQ(809  , message.packed_sfixed32(1));
+  EXPECT_EQ(810  , message.packed_sfixed64(1));
+  EXPECT_EQ(811  , message.packed_float   (1));
+  EXPECT_EQ(812  , message.packed_double  (1));
+  EXPECT_EQ(true , message.packed_bool    (1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.packed_enum(1));
+}
+
+// ===================================================================
+// Extensions
+//
+// All this code is exactly equivalent to the above code except that it's
+// manipulating extension fields instead of normal ones.
+//
+// I gave up on the 80-char limit here.  Sorry.
+
+void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) {
+  message->SetExtension(unittest::optional_int32_extension_lite   , 101);
+  message->SetExtension(unittest::optional_int64_extension_lite   , 102);
+  message->SetExtension(unittest::optional_uint32_extension_lite  , 103);
+  message->SetExtension(unittest::optional_uint64_extension_lite  , 104);
+  message->SetExtension(unittest::optional_sint32_extension_lite  , 105);
+  message->SetExtension(unittest::optional_sint64_extension_lite  , 106);
+  message->SetExtension(unittest::optional_fixed32_extension_lite , 107);
+  message->SetExtension(unittest::optional_fixed64_extension_lite , 108);
+  message->SetExtension(unittest::optional_sfixed32_extension_lite, 109);
+  message->SetExtension(unittest::optional_sfixed64_extension_lite, 110);
+  message->SetExtension(unittest::optional_float_extension_lite   , 111);
+  message->SetExtension(unittest::optional_double_extension_lite  , 112);
+  message->SetExtension(unittest::optional_bool_extension_lite    , true);
+  message->SetExtension(unittest::optional_string_extension_lite  , "115");
+  message->SetExtension(unittest::optional_bytes_extension_lite   , "116");
+
+  message->MutableExtension(unittest::optionalgroup_extension_lite                 )->set_a(117);
+  message->MutableExtension(unittest::optional_nested_message_extension_lite       )->set_bb(118);
+  message->MutableExtension(unittest::optional_foreign_message_extension_lite      )->set_c(119);
+  message->MutableExtension(unittest::optional_import_message_extension_lite       )->set_d(120);
+  message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126);
+  message->MutableExtension(unittest::optional_lazy_message_extension_lite         )->set_bb(127);
+
+  message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
+  message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
+  message->SetExtension(unittest::optional_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->AddExtension(unittest::repeated_int32_extension_lite   , 201);
+  message->AddExtension(unittest::repeated_int64_extension_lite   , 202);
+  message->AddExtension(unittest::repeated_uint32_extension_lite  , 203);
+  message->AddExtension(unittest::repeated_uint64_extension_lite  , 204);
+  message->AddExtension(unittest::repeated_sint32_extension_lite  , 205);
+  message->AddExtension(unittest::repeated_sint64_extension_lite  , 206);
+  message->AddExtension(unittest::repeated_fixed32_extension_lite , 207);
+  message->AddExtension(unittest::repeated_fixed64_extension_lite , 208);
+  message->AddExtension(unittest::repeated_sfixed32_extension_lite, 209);
+  message->AddExtension(unittest::repeated_sfixed64_extension_lite, 210);
+  message->AddExtension(unittest::repeated_float_extension_lite   , 211);
+  message->AddExtension(unittest::repeated_double_extension_lite  , 212);
+  message->AddExtension(unittest::repeated_bool_extension_lite    , true);
+  message->AddExtension(unittest::repeated_string_extension_lite  , "215");
+  message->AddExtension(unittest::repeated_bytes_extension_lite   , "216");
+
+  message->AddExtension(unittest::repeatedgroup_extension_lite           )->set_a(217);
+  message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218);
+  message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219);
+  message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220);
+  message->AddExtension(unittest::repeated_lazy_message_extension_lite   )->set_bb(227);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR );
+  message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR      );
+  message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAR);
+
+
+  // Add a second one of each field.
+  message->AddExtension(unittest::repeated_int32_extension_lite   , 301);
+  message->AddExtension(unittest::repeated_int64_extension_lite   , 302);
+  message->AddExtension(unittest::repeated_uint32_extension_lite  , 303);
+  message->AddExtension(unittest::repeated_uint64_extension_lite  , 304);
+  message->AddExtension(unittest::repeated_sint32_extension_lite  , 305);
+  message->AddExtension(unittest::repeated_sint64_extension_lite  , 306);
+  message->AddExtension(unittest::repeated_fixed32_extension_lite , 307);
+  message->AddExtension(unittest::repeated_fixed64_extension_lite , 308);
+  message->AddExtension(unittest::repeated_sfixed32_extension_lite, 309);
+  message->AddExtension(unittest::repeated_sfixed64_extension_lite, 310);
+  message->AddExtension(unittest::repeated_float_extension_lite   , 311);
+  message->AddExtension(unittest::repeated_double_extension_lite  , 312);
+  message->AddExtension(unittest::repeated_bool_extension_lite    , false);
+  message->AddExtension(unittest::repeated_string_extension_lite  , "315");
+  message->AddExtension(unittest::repeated_bytes_extension_lite   , "316");
+
+  message->AddExtension(unittest::repeatedgroup_extension_lite           )->set_a(317);
+  message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318);
+  message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319);
+  message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320);
+  message->AddExtension(unittest::repeated_lazy_message_extension_lite   )->set_bb(327);
+
+  message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
+  message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
+  message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ);
+
+
+  // -----------------------------------------------------------------
+
+  message->SetExtension(unittest::default_int32_extension_lite   , 401);
+  message->SetExtension(unittest::default_int64_extension_lite   , 402);
+  message->SetExtension(unittest::default_uint32_extension_lite  , 403);
+  message->SetExtension(unittest::default_uint64_extension_lite  , 404);
+  message->SetExtension(unittest::default_sint32_extension_lite  , 405);
+  message->SetExtension(unittest::default_sint64_extension_lite  , 406);
+  message->SetExtension(unittest::default_fixed32_extension_lite , 407);
+  message->SetExtension(unittest::default_fixed64_extension_lite , 408);
+  message->SetExtension(unittest::default_sfixed32_extension_lite, 409);
+  message->SetExtension(unittest::default_sfixed64_extension_lite, 410);
+  message->SetExtension(unittest::default_float_extension_lite   , 411);
+  message->SetExtension(unittest::default_double_extension_lite  , 412);
+  message->SetExtension(unittest::default_bool_extension_lite    , false);
+  message->SetExtension(unittest::default_string_extension_lite  , "415");
+  message->SetExtension(unittest::default_bytes_extension_lite   , "416");
+
+  message->SetExtension(unittest::default_nested_enum_extension_lite , unittest::TestAllTypesLite::FOO );
+  message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO      );
+  message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO);
+
+
+  message->SetExtension(unittest::oneof_uint32_extension_lite, 601);
+  message->MutableExtension(unittest::oneof_nested_message_extension_lite)->set_bb(602);;
+  message->SetExtension(unittest::oneof_string_extension_lite, "603");
+  message->SetExtension(unittest::oneof_bytes_extension_lite, "604");
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyRepeatedExtensions(
+    unittest::TestAllExtensionsLite* message) {
+  message->SetExtension(unittest::repeated_int32_extension_lite   , 1, 501);
+  message->SetExtension(unittest::repeated_int64_extension_lite   , 1, 502);
+  message->SetExtension(unittest::repeated_uint32_extension_lite  , 1, 503);
+  message->SetExtension(unittest::repeated_uint64_extension_lite  , 1, 504);
+  message->SetExtension(unittest::repeated_sint32_extension_lite  , 1, 505);
+  message->SetExtension(unittest::repeated_sint64_extension_lite  , 1, 506);
+  message->SetExtension(unittest::repeated_fixed32_extension_lite , 1, 507);
+  message->SetExtension(unittest::repeated_fixed64_extension_lite , 1, 508);
+  message->SetExtension(unittest::repeated_sfixed32_extension_lite, 1, 509);
+  message->SetExtension(unittest::repeated_sfixed64_extension_lite, 1, 510);
+  message->SetExtension(unittest::repeated_float_extension_lite   , 1, 511);
+  message->SetExtension(unittest::repeated_double_extension_lite  , 1, 512);
+  message->SetExtension(unittest::repeated_bool_extension_lite    , 1, true);
+  message->SetExtension(unittest::repeated_string_extension_lite  , 1, "515");
+  message->SetExtension(unittest::repeated_bytes_extension_lite   , 1, "516");
+
+  message->MutableExtension(unittest::repeatedgroup_extension_lite           , 1)->set_a(517);
+  message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518);
+  message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519);
+  message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520);
+  message->MutableExtension(unittest::repeated_lazy_message_extension_lite   , 1)->set_bb(527);
+
+  message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO );
+  message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO      );
+  message->SetExtension(unittest::repeated_import_enum_extension_lite , 1, unittest_import::IMPORT_LITE_FOO);
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectAllExtensionsSet(
+    const unittest::TestAllExtensionsLite& message) {
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite                 ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite      ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite         ));
+
+  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite                 ).has_a());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite       ).has_bb());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite      ).has_c());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite       ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite         ).has_bb());
+
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  EXPECT_EQ(101  , message.GetExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_EQ(102  , message.GetExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_EQ(103  , message.GetExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_EQ(104  , message.GetExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_EQ(105  , message.GetExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_EQ(106  , message.GetExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_EQ(107  , message.GetExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_EQ(108  , message.GetExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_EQ(109  , message.GetExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_EQ(110  , message.GetExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_EQ(111  , message.GetExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_EQ(112  , message.GetExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite                 ).a());
+  EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite       ).bb());
+  EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite      ).c());
+  EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite       ).d());
+  EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+  EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite         ).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // -----------------------------------------------------------------
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension_lite   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension_lite   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension_lite   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0));
+
+
+  EXPECT_EQ(301  , message.GetExtension(unittest::repeated_int32_extension_lite   , 1));
+  EXPECT_EQ(302  , message.GetExtension(unittest::repeated_int64_extension_lite   , 1));
+  EXPECT_EQ(303  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 1));
+  EXPECT_EQ(304  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 1));
+  EXPECT_EQ(305  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 1));
+  EXPECT_EQ(306  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 1));
+  EXPECT_EQ(307  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1));
+  EXPECT_EQ(308  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1));
+  EXPECT_EQ(309  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1));
+  EXPECT_EQ(310  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1));
+  EXPECT_EQ(311  , message.GetExtension(unittest::repeated_float_extension_lite   , 1));
+  EXPECT_EQ(312  , message.GetExtension(unittest::repeated_double_extension_lite  , 1));
+  EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension_lite    , 1));
+  EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension_lite  , 1));
+  EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension_lite   , 1));
+
+  EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension_lite           , 1).a());
+  EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
+  EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
+  EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1));
+
+
+  // -----------------------------------------------------------------
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite   ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite  ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension_lite ));
+
+
+  EXPECT_EQ(401  , message.GetExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_EQ(402  , message.GetExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_EQ(403  , message.GetExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_EQ(404  , message.GetExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_EQ(405  , message.GetExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_EQ(406  , message.GetExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_EQ(407  , message.GetExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_EQ(408  , message.GetExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_EQ(409  , message.GetExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_EQ(410  , message.GetExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_EQ(411  , message.GetExtension(unittest::default_float_extension_lite   ));
+  EXPECT_EQ(412  , message.GetExtension(unittest::default_double_extension_lite  ));
+  EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension_lite  ));
+  EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite ));
+
+
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension_lite));
+  EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb());
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension_lite));
+
+  EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension_lite));
+  EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension_lite).bb());
+  EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension_lite));
+  EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension_lite));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectExtensionsClear(
+    const unittest::TestAllExtensionsLite& message) {
+  string serialized;
+  ASSERT_TRUE(message.SerializeToString(&serialized));
+  EXPECT_EQ("", serialized);
+  EXPECT_EQ(0, message.ByteSize());
+
+  // has_blah() should initially be false for all optional fields.
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite                 ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite      ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite         ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // Optional fields without defaults are set to zero or something like it.
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int32_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_int64_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint32_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_uint64_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint32_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sint64_extension_lite  ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed32_extension_lite ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_fixed64_extension_lite ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed32_extension_lite));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_sfixed64_extension_lite));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_float_extension_lite   ));
+  EXPECT_EQ(0    , message.GetExtension(unittest::optional_double_extension_lite  ));
+  EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension_lite    ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_string_extension_lite  ));
+  EXPECT_EQ(""   , message.GetExtension(unittest::optional_bytes_extension_lite   ));
+
+  // Embedded messages should also be clear.
+  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite                 ).has_a());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite       ).has_bb());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite      ).has_c());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite       ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite         ).has_bb());
+
+  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite                 ).a());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite       ).bb());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite      ).c());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite       ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite         ).bb());
+
+  // Enums without defaults are set to the first value in the enum.
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::optional_import_enum_extension_lite ));
+
+
+  // Repeated fields are empty.
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  // has_blah() should also be false for all default fields.
+  EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite   ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite  ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension_lite ));
+
+
+  // Fields with defaults have their default values (duh).
+  EXPECT_EQ( 41    , message.GetExtension(unittest::default_int32_extension_lite   ));
+  EXPECT_EQ( 42    , message.GetExtension(unittest::default_int64_extension_lite   ));
+  EXPECT_EQ( 43    , message.GetExtension(unittest::default_uint32_extension_lite  ));
+  EXPECT_EQ( 44    , message.GetExtension(unittest::default_uint64_extension_lite  ));
+  EXPECT_EQ(-45    , message.GetExtension(unittest::default_sint32_extension_lite  ));
+  EXPECT_EQ( 46    , message.GetExtension(unittest::default_sint64_extension_lite  ));
+  EXPECT_EQ( 47    , message.GetExtension(unittest::default_fixed32_extension_lite ));
+  EXPECT_EQ( 48    , message.GetExtension(unittest::default_fixed64_extension_lite ));
+  EXPECT_EQ( 49    , message.GetExtension(unittest::default_sfixed32_extension_lite));
+  EXPECT_EQ(-50    , message.GetExtension(unittest::default_sfixed64_extension_lite));
+  EXPECT_EQ( 51.5  , message.GetExtension(unittest::default_float_extension_lite   ));
+  EXPECT_EQ( 52e3  , message.GetExtension(unittest::default_double_extension_lite  ));
+  EXPECT_EQ(true   , message.GetExtension(unittest::default_bool_extension_lite    ));
+  EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension_lite  ));
+  EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension_lite   ));
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::default_nested_enum_extension_lite ));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::default_foreign_enum_extension_lite));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite ));
+
+
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension_lite));
+  EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb());
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension_lite));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectRepeatedExtensionsModified(
+    const unittest::TestAllExtensionsLite& message) {
+  // ModifyRepeatedFields only sets the second repeated element of each
+  // field.  In addition to verifying this, we also verify that the first
+  // element and size were *not* modified.
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite   ));
+
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite           ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
+
+
+  EXPECT_EQ(201  , message.GetExtension(unittest::repeated_int32_extension_lite   , 0));
+  EXPECT_EQ(202  , message.GetExtension(unittest::repeated_int64_extension_lite   , 0));
+  EXPECT_EQ(203  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 0));
+  EXPECT_EQ(204  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 0));
+  EXPECT_EQ(205  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 0));
+  EXPECT_EQ(206  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 0));
+  EXPECT_EQ(207  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0));
+  EXPECT_EQ(208  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0));
+  EXPECT_EQ(209  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0));
+  EXPECT_EQ(210  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0));
+  EXPECT_EQ(211  , message.GetExtension(unittest::repeated_float_extension_lite   , 0));
+  EXPECT_EQ(212  , message.GetExtension(unittest::repeated_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 0));
+  EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite  , 0));
+  EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite   , 0));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 0).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0));
+
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(501  , message.GetExtension(unittest::repeated_int32_extension_lite   , 1));
+  EXPECT_EQ(502  , message.GetExtension(unittest::repeated_int64_extension_lite   , 1));
+  EXPECT_EQ(503  , message.GetExtension(unittest::repeated_uint32_extension_lite  , 1));
+  EXPECT_EQ(504  , message.GetExtension(unittest::repeated_uint64_extension_lite  , 1));
+  EXPECT_EQ(505  , message.GetExtension(unittest::repeated_sint32_extension_lite  , 1));
+  EXPECT_EQ(506  , message.GetExtension(unittest::repeated_sint64_extension_lite  , 1));
+  EXPECT_EQ(507  , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1));
+  EXPECT_EQ(508  , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1));
+  EXPECT_EQ(509  , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1));
+  EXPECT_EQ(510  , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1));
+  EXPECT_EQ(511  , message.GetExtension(unittest::repeated_float_extension_lite   , 1));
+  EXPECT_EQ(512  , message.GetExtension(unittest::repeated_double_extension_lite  , 1));
+  EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite    , 1));
+  EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension_lite  , 1));
+  EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension_lite   , 1));
+
+  EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension_lite           , 1).a());
+  EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
+  EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
+  EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+  EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 1).bb());
+
+  EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
+  EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1));
+
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::SetPackedExtensions(
+    unittest::TestPackedExtensionsLite* message) {
+  message->AddExtension(unittest::packed_int32_extension_lite   , 601);
+  message->AddExtension(unittest::packed_int64_extension_lite   , 602);
+  message->AddExtension(unittest::packed_uint32_extension_lite  , 603);
+  message->AddExtension(unittest::packed_uint64_extension_lite  , 604);
+  message->AddExtension(unittest::packed_sint32_extension_lite  , 605);
+  message->AddExtension(unittest::packed_sint64_extension_lite  , 606);
+  message->AddExtension(unittest::packed_fixed32_extension_lite , 607);
+  message->AddExtension(unittest::packed_fixed64_extension_lite , 608);
+  message->AddExtension(unittest::packed_sfixed32_extension_lite, 609);
+  message->AddExtension(unittest::packed_sfixed64_extension_lite, 610);
+  message->AddExtension(unittest::packed_float_extension_lite   , 611);
+  message->AddExtension(unittest::packed_double_extension_lite  , 612);
+  message->AddExtension(unittest::packed_bool_extension_lite    , true);
+  message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAR);
+  // add a second one of each field
+  message->AddExtension(unittest::packed_int32_extension_lite   , 701);
+  message->AddExtension(unittest::packed_int64_extension_lite   , 702);
+  message->AddExtension(unittest::packed_uint32_extension_lite  , 703);
+  message->AddExtension(unittest::packed_uint64_extension_lite  , 704);
+  message->AddExtension(unittest::packed_sint32_extension_lite  , 705);
+  message->AddExtension(unittest::packed_sint64_extension_lite  , 706);
+  message->AddExtension(unittest::packed_fixed32_extension_lite , 707);
+  message->AddExtension(unittest::packed_fixed64_extension_lite , 708);
+  message->AddExtension(unittest::packed_sfixed32_extension_lite, 709);
+  message->AddExtension(unittest::packed_sfixed64_extension_lite, 710);
+  message->AddExtension(unittest::packed_float_extension_lite   , 711);
+  message->AddExtension(unittest::packed_double_extension_lite  , 712);
+  message->AddExtension(unittest::packed_bool_extension_lite    , false);
+  message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ModifyPackedExtensions(
+    unittest::TestPackedExtensionsLite* message) {
+  message->SetExtension(unittest::packed_int32_extension_lite   , 1, 801);
+  message->SetExtension(unittest::packed_int64_extension_lite   , 1, 802);
+  message->SetExtension(unittest::packed_uint32_extension_lite  , 1, 803);
+  message->SetExtension(unittest::packed_uint64_extension_lite  , 1, 804);
+  message->SetExtension(unittest::packed_sint32_extension_lite  , 1, 805);
+  message->SetExtension(unittest::packed_sint64_extension_lite  , 1, 806);
+  message->SetExtension(unittest::packed_fixed32_extension_lite , 1, 807);
+  message->SetExtension(unittest::packed_fixed64_extension_lite , 1, 808);
+  message->SetExtension(unittest::packed_sfixed32_extension_lite, 1, 809);
+  message->SetExtension(unittest::packed_sfixed64_extension_lite, 1, 810);
+  message->SetExtension(unittest::packed_float_extension_lite   , 1, 811);
+  message->SetExtension(unittest::packed_double_extension_lite  , 1, 812);
+  message->SetExtension(unittest::packed_bool_extension_lite    , 1, true);
+  message->SetExtension(unittest::packed_enum_extension_lite    , 1,
+                        unittest::FOREIGN_LITE_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsSet(
+    const unittest::TestPackedExtensionsLite& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension_lite   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension_lite   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension_lite  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension_lite  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension_lite  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension_lite  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension_lite , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension_lite , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension_lite   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR,
+            message.GetExtension(unittest::packed_enum_extension_lite, 0));
+  EXPECT_EQ(701  , message.GetExtension(unittest::packed_int32_extension_lite   , 1));
+  EXPECT_EQ(702  , message.GetExtension(unittest::packed_int64_extension_lite   , 1));
+  EXPECT_EQ(703  , message.GetExtension(unittest::packed_uint32_extension_lite  , 1));
+  EXPECT_EQ(704  , message.GetExtension(unittest::packed_uint64_extension_lite  , 1));
+  EXPECT_EQ(705  , message.GetExtension(unittest::packed_sint32_extension_lite  , 1));
+  EXPECT_EQ(706  , message.GetExtension(unittest::packed_sint64_extension_lite  , 1));
+  EXPECT_EQ(707  , message.GetExtension(unittest::packed_fixed32_extension_lite , 1));
+  EXPECT_EQ(708  , message.GetExtension(unittest::packed_fixed64_extension_lite , 1));
+  EXPECT_EQ(709  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1));
+  EXPECT_EQ(710  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1));
+  EXPECT_EQ(711  , message.GetExtension(unittest::packed_float_extension_lite   , 1));
+  EXPECT_EQ(712  , message.GetExtension(unittest::packed_double_extension_lite  , 1));
+  EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension_lite    , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAZ,
+            message.GetExtension(unittest::packed_enum_extension_lite, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsClear(
+    const unittest::TestPackedExtensionsLite& message) {
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtilLite::ExpectPackedExtensionsModified(
+    const unittest::TestPackedExtensionsLite& message) {
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite   ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite  ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite    ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite    ));
+  EXPECT_EQ(601  , message.GetExtension(unittest::packed_int32_extension_lite   , 0));
+  EXPECT_EQ(602  , message.GetExtension(unittest::packed_int64_extension_lite   , 0));
+  EXPECT_EQ(603  , message.GetExtension(unittest::packed_uint32_extension_lite  , 0));
+  EXPECT_EQ(604  , message.GetExtension(unittest::packed_uint64_extension_lite  , 0));
+  EXPECT_EQ(605  , message.GetExtension(unittest::packed_sint32_extension_lite  , 0));
+  EXPECT_EQ(606  , message.GetExtension(unittest::packed_sint64_extension_lite  , 0));
+  EXPECT_EQ(607  , message.GetExtension(unittest::packed_fixed32_extension_lite , 0));
+  EXPECT_EQ(608  , message.GetExtension(unittest::packed_fixed64_extension_lite , 0));
+  EXPECT_EQ(609  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0));
+  EXPECT_EQ(610  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0));
+  EXPECT_EQ(611  , message.GetExtension(unittest::packed_float_extension_lite   , 0));
+  EXPECT_EQ(612  , message.GetExtension(unittest::packed_double_extension_lite  , 0));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 0));
+  EXPECT_EQ(unittest::FOREIGN_LITE_BAR,
+            message.GetExtension(unittest::packed_enum_extension_lite, 0));
+
+  // Actually verify the second (modified) elements now.
+  EXPECT_EQ(801  , message.GetExtension(unittest::packed_int32_extension_lite   , 1));
+  EXPECT_EQ(802  , message.GetExtension(unittest::packed_int64_extension_lite   , 1));
+  EXPECT_EQ(803  , message.GetExtension(unittest::packed_uint32_extension_lite  , 1));
+  EXPECT_EQ(804  , message.GetExtension(unittest::packed_uint64_extension_lite  , 1));
+  EXPECT_EQ(805  , message.GetExtension(unittest::packed_sint32_extension_lite  , 1));
+  EXPECT_EQ(806  , message.GetExtension(unittest::packed_sint64_extension_lite  , 1));
+  EXPECT_EQ(807  , message.GetExtension(unittest::packed_fixed32_extension_lite , 1));
+  EXPECT_EQ(808  , message.GetExtension(unittest::packed_fixed64_extension_lite , 1));
+  EXPECT_EQ(809  , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1));
+  EXPECT_EQ(810  , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1));
+  EXPECT_EQ(811  , message.GetExtension(unittest::packed_float_extension_lite   , 1));
+  EXPECT_EQ(812  , message.GetExtension(unittest::packed_double_extension_lite  , 1));
+  EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite    , 1));
+  EXPECT_EQ(unittest::FOREIGN_LITE_FOO,
+            message.GetExtension(unittest::packed_enum_extension_lite, 1));
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.h b/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.h
new file mode 100644
index 0000000..47a2269
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/test_util_lite.h
@@ -0,0 +1,101 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
+#define GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
+
+#include <google/protobuf/unittest_lite.pb.h>
+
+namespace google {
+namespace protobuf {
+
+namespace unittest = protobuf_unittest;
+namespace unittest_import = protobuf_unittest_import;
+
+class TestUtilLite {
+ public:
+  // Set every field in the message to a unique value.
+  static void SetAllFields(unittest::TestAllTypesLite* message);
+  static void SetAllExtensions(unittest::TestAllExtensionsLite* message);
+  static void SetPackedFields(unittest::TestPackedTypesLite* message);
+  static void SetPackedExtensions(unittest::TestPackedExtensionsLite* message);
+
+  // Use the repeated versions of the set_*() accessors to modify all the
+  // repeated fields of the message (which should already have been
+  // initialized with Set*Fields()).  Set*Fields() itself only tests
+  // the add_*() accessors.
+  static void ModifyRepeatedFields(unittest::TestAllTypesLite* message);
+  static void ModifyRepeatedExtensions(
+      unittest::TestAllExtensionsLite* message);
+  static void ModifyPackedFields(unittest::TestPackedTypesLite* message);
+  static void ModifyPackedExtensions(
+      unittest::TestPackedExtensionsLite* message);
+
+  // Check that all fields have the values that they should have after
+  // Set*Fields() is called.
+  static void ExpectAllFieldsSet(const unittest::TestAllTypesLite& message);
+  static void ExpectAllExtensionsSet(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedFieldsSet(
+      const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsSet(
+      const unittest::TestPackedExtensionsLite& message);
+
+  // Expect that the message is modified as would be expected from
+  // Modify*Fields().
+  static void ExpectRepeatedFieldsModified(
+      const unittest::TestAllTypesLite& message);
+  static void ExpectRepeatedExtensionsModified(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedFieldsModified(
+      const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsModified(
+      const unittest::TestPackedExtensionsLite& message);
+
+  // Check that all fields have their default values.
+  static void ExpectClear(const unittest::TestAllTypesLite& message);
+  static void ExpectExtensionsClear(
+      const unittest::TestAllExtensionsLite& message);
+  static void ExpectPackedClear(const unittest::TestPackedTypesLite& message);
+  static void ExpectPackedExtensionsClear(
+      const unittest::TestPackedExtensionsLite& message);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtilLite);
+};
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message
new file mode 100644
index 0000000..0b7e655
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message
Binary files differ
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_oneof_implemented b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_oneof_implemented
new file mode 100644
index 0000000..b48c898
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_oneof_implemented
Binary files differ
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_proto3 b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_proto3
new file mode 100644
index 0000000..bd646a0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_packed_fields_message b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_packed_fields_message
new file mode 100644
index 0000000..ee28d38
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/golden_packed_fields_message
Binary files differ
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/map_test_data.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/map_test_data.txt
new file mode 100644
index 0000000..bc27232
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/map_test_data.txt
@@ -0,0 +1,140 @@
+map_int32_int32 {
+  key: 0
+  value: 0
+}
+map_int32_int32 {
+  key: 1
+  value: 1
+}
+map_int64_int64 {
+  key: 0
+  value: 0
+}
+map_int64_int64 {
+  key: 1
+  value: 1
+}
+map_uint32_uint32 {
+  key: 0
+  value: 0
+}
+map_uint32_uint32 {
+  key: 1
+  value: 1
+}
+map_uint64_uint64 {
+  key: 0
+  value: 0
+}
+map_uint64_uint64 {
+  key: 1
+  value: 1
+}
+map_sint32_sint32 {
+  key: 0
+  value: 0
+}
+map_sint32_sint32 {
+  key: 1
+  value: 1
+}
+map_sint64_sint64 {
+  key: 0
+  value: 0
+}
+map_sint64_sint64 {
+  key: 1
+  value: 1
+}
+map_fixed32_fixed32 {
+  key: 0
+  value: 0
+}
+map_fixed32_fixed32 {
+  key: 1
+  value: 1
+}
+map_fixed64_fixed64 {
+  key: 0
+  value: 0
+}
+map_fixed64_fixed64 {
+  key: 1
+  value: 1
+}
+map_sfixed32_sfixed32 {
+  key: 0
+  value: 0
+}
+map_sfixed32_sfixed32 {
+  key: 1
+  value: 1
+}
+map_sfixed64_sfixed64 {
+  key: 0
+  value: 0
+}
+map_sfixed64_sfixed64 {
+  key: 1
+  value: 1
+}
+map_int32_float {
+  key: 0
+  value: 0
+}
+map_int32_float {
+  key: 1
+  value: 1
+}
+map_int32_double {
+  key: 0
+  value: 0
+}
+map_int32_double {
+  key: 1
+  value: 1
+}
+map_bool_bool {
+  key: false
+  value: false
+}
+map_bool_bool {
+  key: true
+  value: true
+}
+map_string_string {
+  key: "0"
+  value: "0"
+}
+map_string_string {
+  key: "1"
+  value: "1"
+}
+map_int32_bytes {
+  key: 0
+  value: "0"
+}
+map_int32_bytes {
+  key: 1
+  value: "1"
+}
+map_int32_enum {
+  key: 0
+  value: MAP_ENUM_BAR
+}
+map_int32_enum {
+  key: 1
+  value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+  key: 0
+  value {
+    c: 0
+  }
+}
+map_int32_foreign_message {
+  key: 1
+  value {
+    c: 1
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data.txt
new file mode 100644
index 0000000..7a874b5
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data.txt
@@ -0,0 +1,134 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "116"
+OptionalGroup {
+  a: 117
+}
+optional_nested_message {
+  bb: 118
+}
+optional_foreign_message {
+  c: 119
+}
+optional_import_message {
+  d: 120
+}
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+optional_public_import_message {
+  e: 126
+}
+optional_lazy_message {
+  bb: 127
+}
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: true
+repeated_bool: false
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "216"
+repeated_bytes: "316"
+RepeatedGroup {
+  a: 217
+}
+RepeatedGroup {
+  a: 317
+}
+repeated_nested_message {
+  bb: 218
+}
+repeated_nested_message {
+  bb: 318
+}
+repeated_foreign_message {
+  c: 219
+}
+repeated_foreign_message {
+  c: 319
+}
+repeated_import_message {
+  d: 220
+}
+repeated_import_message {
+  d: 320
+}
+repeated_nested_enum: BAR
+repeated_nested_enum: BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+repeated_lazy_message {
+  bb: 227
+}
+repeated_lazy_message {
+  bb: 327
+}
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "416"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
+oneof_uint32: 601
+oneof_nested_message {
+  bb: 602
+}
+oneof_string: "603"
+oneof_bytes: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt
new file mode 100644
index 0000000..ec95e1e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt
@@ -0,0 +1,129 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "116"
+OptionalGroup {
+  a: 117
+}
+optional_nested_message {
+  bb: 118
+}
+optional_foreign_message {
+  c: 119
+}
+optional_import_message {
+  d: 120
+}
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+optional_public_import_message {
+  e: 126
+}
+optional_lazy_message {
+  bb: 127
+}
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: true
+repeated_bool: false
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "216"
+repeated_bytes: "316"
+RepeatedGroup {
+  a: 217
+}
+RepeatedGroup {
+  a: 317
+}
+repeated_nested_message {
+  bb: 218
+}
+repeated_nested_message {
+  bb: 318
+}
+repeated_foreign_message {
+  c: 219
+}
+repeated_foreign_message {
+  c: 319
+}
+repeated_import_message {
+  d: 220
+}
+repeated_import_message {
+  d: 320
+}
+repeated_nested_enum: BAR
+repeated_nested_enum: BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+repeated_lazy_message {
+  bb: 227
+}
+repeated_lazy_message {
+  bb: 327
+}
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "416"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
+oneof_bytes: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt
new file mode 100644
index 0000000..e1011eb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt
@@ -0,0 +1,134 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "116"
+OptionalGroup <
+  a: 117
+>
+optional_nested_message <
+  bb: 118
+>
+optional_foreign_message <
+  c: 119
+>
+optional_import_message <
+  d: 120
+>
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+optional_public_import_message <
+  e: 126
+>
+optional_lazy_message <
+  bb: 127
+>
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: true
+repeated_bool: false
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "216"
+repeated_bytes: "316"
+RepeatedGroup <
+  a: 217
+>
+RepeatedGroup <
+  a: 317
+>
+repeated_nested_message <
+  bb: 218
+>
+repeated_nested_message <
+  bb: 318
+>
+repeated_foreign_message <
+  c: 219
+>
+repeated_foreign_message <
+  c: 319
+>
+repeated_import_message <
+  d: 220
+>
+repeated_import_message <
+  d: 320
+>
+repeated_nested_enum: BAR
+repeated_nested_enum: BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+repeated_lazy_message <
+  bb: 227
+>
+repeated_lazy_message <
+  bb: 327
+>
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "416"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
+oneof_uint32: 601
+oneof_nested_message <
+  bb: 602
+>
+oneof_string: "603"
+oneof_bytes: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt
new file mode 100644
index 0000000..95109f6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt
@@ -0,0 +1,129 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "116"
+OptionalGroup <
+  a: 117
+>
+optional_nested_message <
+  bb: 118
+>
+optional_foreign_message <
+  c: 119
+>
+optional_import_message <
+  d: 120
+>
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+optional_public_import_message <
+  e: 126
+>
+optional_lazy_message <
+  bb: 127
+>
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: true
+repeated_bool: false
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "216"
+repeated_bytes: "316"
+RepeatedGroup <
+  a: 217
+>
+RepeatedGroup <
+  a: 317
+>
+repeated_nested_message <
+  bb: 218
+>
+repeated_nested_message <
+  bb: 318
+>
+repeated_foreign_message <
+  c: 219
+>
+repeated_foreign_message <
+  c: 319
+>
+repeated_import_message <
+  d: 220
+>
+repeated_import_message <
+  d: 320
+>
+repeated_nested_enum: BAR
+repeated_nested_enum: BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+repeated_lazy_message <
+  bb: 227
+>
+repeated_lazy_message <
+  bb: 327
+>
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "416"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
+oneof_bytes: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
new file mode 100644
index 0000000..8c8b1eb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
@@ -0,0 +1,134 @@
+[protobuf_unittest.optional_int32_extension]: 101
+[protobuf_unittest.optional_int64_extension]: 102
+[protobuf_unittest.optional_uint32_extension]: 103
+[protobuf_unittest.optional_uint64_extension]: 104
+[protobuf_unittest.optional_sint32_extension]: 105
+[protobuf_unittest.optional_sint64_extension]: 106
+[protobuf_unittest.optional_fixed32_extension]: 107
+[protobuf_unittest.optional_fixed64_extension]: 108
+[protobuf_unittest.optional_sfixed32_extension]: 109
+[protobuf_unittest.optional_sfixed64_extension]: 110
+[protobuf_unittest.optional_float_extension]: 111
+[protobuf_unittest.optional_double_extension]: 112
+[protobuf_unittest.optional_bool_extension]: true
+[protobuf_unittest.optional_string_extension]: "115"
+[protobuf_unittest.optional_bytes_extension]: "116"
+[protobuf_unittest.optionalgroup_extension] {
+  a: 117
+}
+[protobuf_unittest.optional_nested_message_extension] {
+  bb: 118
+}
+[protobuf_unittest.optional_foreign_message_extension] {
+  c: 119
+}
+[protobuf_unittest.optional_import_message_extension] {
+  d: 120
+}
+[protobuf_unittest.optional_nested_enum_extension]: BAZ
+[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ
+[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
+[protobuf_unittest.optional_string_piece_extension]: "124"
+[protobuf_unittest.optional_cord_extension]: "125"
+[protobuf_unittest.optional_public_import_message_extension] {
+  e: 126
+}
+[protobuf_unittest.optional_lazy_message_extension] {
+  bb: 127
+}
+[protobuf_unittest.repeated_int32_extension]: 201
+[protobuf_unittest.repeated_int32_extension]: 301
+[protobuf_unittest.repeated_int64_extension]: 202
+[protobuf_unittest.repeated_int64_extension]: 302
+[protobuf_unittest.repeated_uint32_extension]: 203
+[protobuf_unittest.repeated_uint32_extension]: 303
+[protobuf_unittest.repeated_uint64_extension]: 204
+[protobuf_unittest.repeated_uint64_extension]: 304
+[protobuf_unittest.repeated_sint32_extension]: 205
+[protobuf_unittest.repeated_sint32_extension]: 305
+[protobuf_unittest.repeated_sint64_extension]: 206
+[protobuf_unittest.repeated_sint64_extension]: 306
+[protobuf_unittest.repeated_fixed32_extension]: 207
+[protobuf_unittest.repeated_fixed32_extension]: 307
+[protobuf_unittest.repeated_fixed64_extension]: 208
+[protobuf_unittest.repeated_fixed64_extension]: 308
+[protobuf_unittest.repeated_sfixed32_extension]: 209
+[protobuf_unittest.repeated_sfixed32_extension]: 309
+[protobuf_unittest.repeated_sfixed64_extension]: 210
+[protobuf_unittest.repeated_sfixed64_extension]: 310
+[protobuf_unittest.repeated_float_extension]: 211
+[protobuf_unittest.repeated_float_extension]: 311
+[protobuf_unittest.repeated_double_extension]: 212
+[protobuf_unittest.repeated_double_extension]: 312
+[protobuf_unittest.repeated_bool_extension]: true
+[protobuf_unittest.repeated_bool_extension]: false
+[protobuf_unittest.repeated_string_extension]: "215"
+[protobuf_unittest.repeated_string_extension]: "315"
+[protobuf_unittest.repeated_bytes_extension]: "216"
+[protobuf_unittest.repeated_bytes_extension]: "316"
+[protobuf_unittest.repeatedgroup_extension] {
+  a: 217
+}
+[protobuf_unittest.repeatedgroup_extension] {
+  a: 317
+}
+[protobuf_unittest.repeated_nested_message_extension] {
+  bb: 218
+}
+[protobuf_unittest.repeated_nested_message_extension] {
+  bb: 318
+}
+[protobuf_unittest.repeated_foreign_message_extension] {
+  c: 219
+}
+[protobuf_unittest.repeated_foreign_message_extension] {
+  c: 319
+}
+[protobuf_unittest.repeated_import_message_extension] {
+  d: 220
+}
+[protobuf_unittest.repeated_import_message_extension] {
+  d: 320
+}
+[protobuf_unittest.repeated_nested_enum_extension]: BAR
+[protobuf_unittest.repeated_nested_enum_extension]: BAZ
+[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR
+[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ
+[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR
+[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ
+[protobuf_unittest.repeated_string_piece_extension]: "224"
+[protobuf_unittest.repeated_string_piece_extension]: "324"
+[protobuf_unittest.repeated_cord_extension]: "225"
+[protobuf_unittest.repeated_cord_extension]: "325"
+[protobuf_unittest.repeated_lazy_message_extension] {
+  bb: 227
+}
+[protobuf_unittest.repeated_lazy_message_extension] {
+  bb: 327
+}
+[protobuf_unittest.default_int32_extension]: 401
+[protobuf_unittest.default_int64_extension]: 402
+[protobuf_unittest.default_uint32_extension]: 403
+[protobuf_unittest.default_uint64_extension]: 404
+[protobuf_unittest.default_sint32_extension]: 405
+[protobuf_unittest.default_sint64_extension]: 406
+[protobuf_unittest.default_fixed32_extension]: 407
+[protobuf_unittest.default_fixed64_extension]: 408
+[protobuf_unittest.default_sfixed32_extension]: 409
+[protobuf_unittest.default_sfixed64_extension]: 410
+[protobuf_unittest.default_float_extension]: 411
+[protobuf_unittest.default_double_extension]: 412
+[protobuf_unittest.default_bool_extension]: false
+[protobuf_unittest.default_string_extension]: "415"
+[protobuf_unittest.default_bytes_extension]: "416"
+[protobuf_unittest.default_nested_enum_extension]: FOO
+[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO
+[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO
+[protobuf_unittest.default_string_piece_extension]: "424"
+[protobuf_unittest.default_cord_extension]: "425"
+[protobuf_unittest.oneof_uint32_extension]: 601
+[protobuf_unittest.oneof_nested_message_extension] {
+  bb: 602
+}
+[protobuf_unittest.oneof_string_extension]: "603"
+[protobuf_unittest.oneof_bytes_extension]: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt
new file mode 100644
index 0000000..132f744
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt
@@ -0,0 +1,134 @@
+[protobuf_unittest.optional_int32_extension]: 101
+[protobuf_unittest.optional_int64_extension]: 102
+[protobuf_unittest.optional_uint32_extension]: 103
+[protobuf_unittest.optional_uint64_extension]: 104
+[protobuf_unittest.optional_sint32_extension]: 105
+[protobuf_unittest.optional_sint64_extension]: 106
+[protobuf_unittest.optional_fixed32_extension]: 107
+[protobuf_unittest.optional_fixed64_extension]: 108
+[protobuf_unittest.optional_sfixed32_extension]: 109
+[protobuf_unittest.optional_sfixed64_extension]: 110
+[protobuf_unittest.optional_float_extension]: 111
+[protobuf_unittest.optional_double_extension]: 112
+[protobuf_unittest.optional_bool_extension]: true
+[protobuf_unittest.optional_string_extension]: "115"
+[protobuf_unittest.optional_bytes_extension]: "116"
+[protobuf_unittest.optionalgroup_extension] <
+  a: 117
+>
+[protobuf_unittest.optional_nested_message_extension] <
+  bb: 118
+>
+[protobuf_unittest.optional_foreign_message_extension] <
+  c: 119
+>
+[protobuf_unittest.optional_import_message_extension] <
+  d: 120
+>
+[protobuf_unittest.optional_nested_enum_extension]: BAZ
+[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ
+[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
+[protobuf_unittest.optional_string_piece_extension]: "124"
+[protobuf_unittest.optional_cord_extension]: "125"
+[protobuf_unittest.optional_public_import_message_extension] <
+  e: 126
+>
+[protobuf_unittest.optional_lazy_message_extension] <
+  bb: 127
+>
+[protobuf_unittest.repeated_int32_extension]: 201
+[protobuf_unittest.repeated_int32_extension]: 301
+[protobuf_unittest.repeated_int64_extension]: 202
+[protobuf_unittest.repeated_int64_extension]: 302
+[protobuf_unittest.repeated_uint32_extension]: 203
+[protobuf_unittest.repeated_uint32_extension]: 303
+[protobuf_unittest.repeated_uint64_extension]: 204
+[protobuf_unittest.repeated_uint64_extension]: 304
+[protobuf_unittest.repeated_sint32_extension]: 205
+[protobuf_unittest.repeated_sint32_extension]: 305
+[protobuf_unittest.repeated_sint64_extension]: 206
+[protobuf_unittest.repeated_sint64_extension]: 306
+[protobuf_unittest.repeated_fixed32_extension]: 207
+[protobuf_unittest.repeated_fixed32_extension]: 307
+[protobuf_unittest.repeated_fixed64_extension]: 208
+[protobuf_unittest.repeated_fixed64_extension]: 308
+[protobuf_unittest.repeated_sfixed32_extension]: 209
+[protobuf_unittest.repeated_sfixed32_extension]: 309
+[protobuf_unittest.repeated_sfixed64_extension]: 210
+[protobuf_unittest.repeated_sfixed64_extension]: 310
+[protobuf_unittest.repeated_float_extension]: 211
+[protobuf_unittest.repeated_float_extension]: 311
+[protobuf_unittest.repeated_double_extension]: 212
+[protobuf_unittest.repeated_double_extension]: 312
+[protobuf_unittest.repeated_bool_extension]: true
+[protobuf_unittest.repeated_bool_extension]: false
+[protobuf_unittest.repeated_string_extension]: "215"
+[protobuf_unittest.repeated_string_extension]: "315"
+[protobuf_unittest.repeated_bytes_extension]: "216"
+[protobuf_unittest.repeated_bytes_extension]: "316"
+[protobuf_unittest.repeatedgroup_extension] <
+  a: 217
+>
+[protobuf_unittest.repeatedgroup_extension] <
+  a: 317
+>
+[protobuf_unittest.repeated_nested_message_extension] <
+  bb: 218
+>
+[protobuf_unittest.repeated_nested_message_extension] <
+  bb: 318
+>
+[protobuf_unittest.repeated_foreign_message_extension] <
+  c: 219
+>
+[protobuf_unittest.repeated_foreign_message_extension] <
+  c: 319
+>
+[protobuf_unittest.repeated_import_message_extension] <
+  d: 220
+>
+[protobuf_unittest.repeated_import_message_extension] <
+  d: 320
+>
+[protobuf_unittest.repeated_nested_enum_extension]: BAR
+[protobuf_unittest.repeated_nested_enum_extension]: BAZ
+[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR
+[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ
+[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR
+[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ
+[protobuf_unittest.repeated_string_piece_extension]: "224"
+[protobuf_unittest.repeated_string_piece_extension]: "324"
+[protobuf_unittest.repeated_cord_extension]: "225"
+[protobuf_unittest.repeated_cord_extension]: "325"
+[protobuf_unittest.repeated_lazy_message_extension] <
+  bb: 227
+>
+[protobuf_unittest.repeated_lazy_message_extension] <
+  bb: 327
+>
+[protobuf_unittest.default_int32_extension]: 401
+[protobuf_unittest.default_int64_extension]: 402
+[protobuf_unittest.default_uint32_extension]: 403
+[protobuf_unittest.default_uint64_extension]: 404
+[protobuf_unittest.default_sint32_extension]: 405
+[protobuf_unittest.default_sint64_extension]: 406
+[protobuf_unittest.default_fixed32_extension]: 407
+[protobuf_unittest.default_fixed64_extension]: 408
+[protobuf_unittest.default_sfixed32_extension]: 409
+[protobuf_unittest.default_sfixed64_extension]: 410
+[protobuf_unittest.default_float_extension]: 411
+[protobuf_unittest.default_double_extension]: 412
+[protobuf_unittest.default_bool_extension]: false
+[protobuf_unittest.default_string_extension]: "415"
+[protobuf_unittest.default_bytes_extension]: "416"
+[protobuf_unittest.default_nested_enum_extension]: FOO
+[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO
+[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO
+[protobuf_unittest.default_string_piece_extension]: "424"
+[protobuf_unittest.default_cord_extension]: "425"
+[protobuf_unittest.oneof_uint32_extension]: 601
+[protobuf_unittest.oneof_nested_message_extension] <
+  bb: 602
+>
+[protobuf_unittest.oneof_string_extension]: "603"
+[protobuf_unittest.oneof_bytes_extension]: "604"
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/file.cc b/src/third_party/protobuf-3/src/google/protobuf/testing/file.cc
new file mode 100644
index 0000000..3d07b12
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/file.cc
@@ -0,0 +1,200 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// emulates google3/file/base/file.cc
+
+#include <google/protobuf/testing/file.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef _MSC_VER
+#define WIN32_LEAN_AND_MEAN  // yeah, right
+#include <windows.h>         // Find*File().  :(
+#include <io.h>
+#include <direct.h>
+#else
+#include <dirent.h>
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _WIN32
+#define mkdir(name, mode) mkdir(name)
+// Windows doesn't have symbolic links.
+#define lstat stat
+#ifndef F_OK
+#define F_OK 00  // not defined by MSVC for whatever reason
+#endif
+#endif
+
+bool File::Exists(const string& name) {
+  return access(name.c_str(), F_OK) == 0;
+}
+
+bool File::ReadFileToString(const string& name, string* output) {
+  char buffer[1024];
+  FILE* file = fopen(name.c_str(), "rb");
+  if (file == NULL) return false;
+
+  while (true) {
+    size_t n = fread(buffer, 1, sizeof(buffer), file);
+    if (n <= 0) break;
+    output->append(buffer, n);
+  }
+
+  int error = ferror(file);
+  if (fclose(file) != 0) return false;
+  return error == 0;
+}
+
+void File::ReadFileToStringOrDie(const string& name, string* output) {
+  GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name;
+}
+
+bool File::WriteStringToFile(const string& contents, const string& name) {
+  FILE* file = fopen(name.c_str(), "wb");
+  if (file == NULL) {
+    GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno);
+    return false;
+  }
+
+  if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) {
+    GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno);
+    return false;
+  }
+
+  if (fclose(file) != 0) {
+    return false;
+  }
+  return true;
+}
+
+void File::WriteStringToFileOrDie(const string& contents, const string& name) {
+  FILE* file = fopen(name.c_str(), "wb");
+  GOOGLE_CHECK(file != NULL)
+      << "fopen(" << name << ", \"wb\"): " << strerror(errno);
+  GOOGLE_CHECK_EQ(fwrite(contents.data(), 1, contents.size(), file),
+                  contents.size())
+      << "fwrite(" << name << "): " << strerror(errno);
+  GOOGLE_CHECK(fclose(file) == 0)
+      << "fclose(" << name << "): " << strerror(errno);
+}
+
+bool File::CreateDir(const string& name, int mode) {
+  return mkdir(name.c_str(), mode) == 0;
+}
+
+bool File::RecursivelyCreateDir(const string& path, int mode) {
+  if (CreateDir(path, mode)) return true;
+
+  if (Exists(path)) return false;
+
+  // Try creating the parent.
+  string::size_type slashpos = path.find_last_of('/');
+  if (slashpos == string::npos) {
+    // No parent given.
+    return false;
+  }
+
+  return RecursivelyCreateDir(path.substr(0, slashpos), mode) &&
+         CreateDir(path, mode);
+}
+
+void File::DeleteRecursively(const string& name,
+                             void* dummy1, void* dummy2) {
+  if (name.empty()) return;
+
+  // We don't care too much about error checking here since this is only used
+  // in tests to delete temporary directories that are under /tmp anyway.
+
+#ifdef _MSC_VER
+  // This interface is so weird.
+  WIN32_FIND_DATA find_data;
+  HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data);
+  if (find_handle == INVALID_HANDLE_VALUE) {
+    // Just delete it, whatever it is.
+    DeleteFile(name.c_str());
+    RemoveDirectory(name.c_str());
+    return;
+  }
+
+  do {
+    string entry_name = find_data.cFileName;
+    if (entry_name != "." && entry_name != "..") {
+      string path = name + "/" + entry_name;
+      if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+        DeleteRecursively(path, NULL, NULL);
+        RemoveDirectory(path.c_str());
+      } else {
+        DeleteFile(path.c_str());
+      }
+    }
+  } while(FindNextFile(find_handle, &find_data));
+  FindClose(find_handle);
+
+  RemoveDirectory(name.c_str());
+#else
+  // Use opendir()!  Yay!
+  // lstat = Don't follow symbolic links.
+  struct stat stats;
+  if (lstat(name.c_str(), &stats) != 0) return;
+
+  if (S_ISDIR(stats.st_mode)) {
+    DIR* dir = opendir(name.c_str());
+    if (dir != NULL) {
+      while (true) {
+        struct dirent* entry = readdir(dir);
+        if (entry == NULL) break;
+        string entry_name = entry->d_name;
+        if (entry_name != "." && entry_name != "..") {
+          DeleteRecursively(name + "/" + entry_name, NULL, NULL);
+        }
+      }
+    }
+
+    closedir(dir);
+    rmdir(name.c_str());
+
+  } else if (S_ISREG(stats.st_mode)) {
+    remove(name.c_str());
+  }
+#endif
+}
+
+bool File::ChangeWorkingDirectory(const string& new_working_directory) {
+  return chdir(new_working_directory.c_str()) == 0;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/file.h b/src/third_party/protobuf-3/src/google/protobuf/testing/file.h
new file mode 100644
index 0000000..2f63f80
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/file.h
@@ -0,0 +1,100 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// emulates google3/file/base/file.h
+
+#ifndef GOOGLE_PROTOBUF_TESTING_FILE_H__
+#define GOOGLE_PROTOBUF_TESTING_FILE_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+const int DEFAULT_FILE_MODE = 0777;
+
+// Protocol buffer code only uses a couple static methods of File, and only
+// in tests.
+class File {
+ public:
+  // Check if the file exists.
+  static bool Exists(const string& name);
+
+  // Read an entire file to a string.  Return true if successful, false
+  // otherwise.
+  static bool ReadFileToString(const string& name, string* output);
+
+  // Same as above, but crash on failure.
+  static void ReadFileToStringOrDie(const string& name, string* output);
+
+  // Create a file and write a string to it.
+  static bool WriteStringToFile(const string& contents,
+                                const string& name);
+
+  // Same as above, but crash on failure.
+  static void WriteStringToFileOrDie(const string& contents,
+                                     const string& name);
+
+  // Create a directory.
+  static bool CreateDir(const string& name, int mode);
+
+  // Create a directory and all parent directories if necessary.
+  static bool RecursivelyCreateDir(const string& path, int mode);
+
+  // If "name" is a file, we delete it.  If it is a directory, we
+  // call DeleteRecursively() for each file or directory (other than
+  // dot and double-dot) within it, and then delete the directory itself.
+  // The "dummy" parameters have a meaning in the original version of this
+  // method but they are not used anywhere in protocol buffers.
+  static void DeleteRecursively(const string& name,
+                                void* dummy1, void* dummy2);
+
+  // Change working directory to given directory.
+  static bool ChangeWorkingDirectory(const string& new_working_directory);
+
+  static bool GetContents(
+      const string& name, string* output, bool /*is_default*/) {
+    return ReadFileToString(name, output);
+  }
+
+  static bool SetContents(
+      const string& name, const string& contents, bool /*is_default*/) {
+    return WriteStringToFile(contents, name);
+  }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(File);
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_TESTING_FILE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.cc b/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.cc
new file mode 100644
index 0000000..2b9cdde
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.cc
@@ -0,0 +1,267 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// emulates google3/testing/base/public/googletest.cc
+
+#include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <fcntl.h>
+#include <iostream>
+#include <fstream>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _WIN32
+#define mkdir(name, mode) mkdir(name)
+#endif
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
+#endif
+#endif
+
+string TestSourceDir() {
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
+#ifndef _MSC_VER
+  // automake sets the "srcdir" environment variable.
+  char* result = getenv("srcdir");
+  if (result != NULL) {
+    return result;
+  }
+#endif  // _MSC_VER
+
+  // Look for the "src" directory.
+  string prefix = ".";
+
+  while (!File::Exists(prefix + "/src/google/protobuf")) {
+    if (!File::Exists(prefix)) {
+      GOOGLE_LOG(FATAL)
+        << "Could not find protobuf source code.  Please run tests from "
+           "somewhere within the protobuf source package.";
+    }
+    prefix += "/..";
+  }
+  return prefix + "/src";
+#else
+  return "third_party/protobuf/src";
+#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
+}
+
+namespace {
+
+string GetTemporaryDirectoryName() {
+  // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
+  // variable for tests to use instead.
+  char *from_environment = getenv("TEST_TMPDIR");
+  if (from_environment != NULL && from_environment[0] != '\0') {
+    return string(from_environment) + "/protobuf_tmpdir";
+  }
+
+  // tmpnam() is generally not considered safe but we're only using it for
+  // testing.  We cannot use tmpfile() or mkstemp() since we're creating a
+  // directory.
+  char b[L_tmpnam + 1];     // HPUX multithread return 0 if s is 0
+  string result = tmpnam(b);
+#ifdef _WIN32
+  // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
+  // to be used in the current working directory.  WTF?
+  if (HasPrefixString(result, "\\")) {
+    result.erase(0, 1);
+  }
+  // The Win32 API accepts forward slashes as a path delimiter even though
+  // backslashes are standard.  Let's avoid confusion and use only forward
+  // slashes.
+  result = StringReplace(result, "\\", "/", true);
+#endif  // _WIN32
+  return result;
+}
+
+// Creates a temporary directory on demand and deletes it when the process
+// quits.
+class TempDirDeleter {
+ public:
+  TempDirDeleter() {}
+  ~TempDirDeleter() {
+    if (!name_.empty()) {
+      File::DeleteRecursively(name_, NULL, NULL);
+    }
+  }
+
+  string GetTempDir() {
+    if (name_.empty()) {
+      name_ = GetTemporaryDirectoryName();
+      GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno);
+
+      // Stick a file in the directory that tells people what this is, in case
+      // we abort and don't get a chance to delete it.
+      File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS");
+    }
+    return name_;
+  }
+
+ private:
+  string name_;
+};
+
+TempDirDeleter temp_dir_deleter_;
+
+}  // namespace
+
+string TestTempDir() {
+  return temp_dir_deleter_.GetTempDir();
+}
+
+// TODO(kenton):  Share duplicated code below.  Too busy/lazy for now.
+
+static string stdout_capture_filename_;
+static string stderr_capture_filename_;
+static int original_stdout_ = -1;
+static int original_stderr_ = -1;
+
+void CaptureTestStdout() {
+  GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing.";
+
+  stdout_capture_filename_ = TestTempDir() + "/captured_stdout";
+
+  int fd = open(stdout_capture_filename_.c_str(),
+                O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
+  GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
+
+  original_stdout_ = dup(1);
+  close(1);
+  dup2(fd, 1);
+  close(fd);
+}
+
+void CaptureTestStderr() {
+  GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing.";
+
+  stderr_capture_filename_ = TestTempDir() + "/captured_stderr";
+
+  int fd = open(stderr_capture_filename_.c_str(),
+                O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
+  GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
+
+  original_stderr_ = dup(2);
+  close(2);
+  dup2(fd, 2);
+  close(fd);
+}
+
+string GetCapturedTestStdout() {
+  GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing.";
+
+  close(1);
+  dup2(original_stdout_, 1);
+  original_stdout_ = -1;
+
+  string result;
+  File::ReadFileToStringOrDie(stdout_capture_filename_, &result);
+
+  remove(stdout_capture_filename_.c_str());
+
+  return result;
+}
+
+string GetCapturedTestStderr() {
+  GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing.";
+
+  close(2);
+  dup2(original_stderr_, 2);
+  original_stderr_ = -1;
+
+  string result;
+  File::ReadFileToStringOrDie(stderr_capture_filename_, &result);
+
+  remove(stderr_capture_filename_.c_str());
+
+  return result;
+}
+
+ScopedMemoryLog* ScopedMemoryLog::active_log_ = NULL;
+
+ScopedMemoryLog::ScopedMemoryLog() {
+  GOOGLE_CHECK(active_log_ == NULL);
+  active_log_ = this;
+  old_handler_ = SetLogHandler(&HandleLog);
+}
+
+ScopedMemoryLog::~ScopedMemoryLog() {
+  SetLogHandler(old_handler_);
+  active_log_ = NULL;
+}
+
+const vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
+  GOOGLE_CHECK(level == ERROR ||
+               level == WARNING);
+  return messages_[level];
+}
+
+void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
+                                int line, const string& message) {
+  GOOGLE_CHECK(active_log_ != NULL);
+  if (level == ERROR || level == WARNING) {
+    active_log_->messages_[level].push_back(message);
+  }
+}
+
+namespace {
+
+// Force shutdown at process exit so that we can test for memory leaks.  To
+// actually check for leaks, I suggest using the heap checker included with
+// google-perftools.  Set it to "draconian" mode to ensure that every last
+// call to malloc() has a corresponding free().
+struct ForceShutdown {
+  ~ForceShutdown() {
+    ShutdownProtobufLibrary();
+  }
+} force_shutdown;
+
+}  // namespace
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.h b/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.h
new file mode 100644
index 0000000..c0d99e6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/googletest.h
@@ -0,0 +1,102 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// emulates google3/testing/base/public/googletest.h
+
+#ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__
+#define GOOGLE_PROTOBUF_GOOGLETEST_H__
+
+#include <map>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+
+// Disable death tests if we use exceptions in CHECK().
+#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST)
+#define PROTOBUF_HAS_DEATH_TEST
+#endif
+
+namespace google {
+namespace protobuf {
+
+// When running unittests, get the directory containing the source code.
+string TestSourceDir();
+
+// When running unittests, get a directory where temporary files may be
+// placed.
+string TestTempDir();
+
+// Capture all text written to stdout or stderr.
+void CaptureTestStdout();
+void CaptureTestStderr();
+
+// Stop capturing stdout or stderr and return the text captured.
+string GetCapturedTestStdout();
+string GetCapturedTestStderr();
+
+// For use with ScopedMemoryLog::GetMessages().  Inside Google the LogLevel
+// constants don't have the LOGLEVEL_ prefix, so the code that used
+// ScopedMemoryLog refers to LOGLEVEL_ERROR as just ERROR.
+#undef ERROR  // defend against promiscuous windows.h
+static const LogLevel ERROR = LOGLEVEL_ERROR;
+static const LogLevel WARNING = LOGLEVEL_WARNING;
+
+// Receives copies of all LOG(ERROR) messages while in scope.  Sample usage:
+//   {
+//     ScopedMemoryLog log;  // constructor registers object as a log sink
+//     SomeRoutineThatMayLogMessages();
+//     const vector<string>& warnings = log.GetMessages(ERROR);
+//   }  // destructor unregisters object as a log sink
+// This is a dummy implementation which covers only what is used by protocol
+// buffer unit tests.
+class ScopedMemoryLog {
+ public:
+  ScopedMemoryLog();
+  virtual ~ScopedMemoryLog();
+
+  // Fetches all messages with the given severity level.
+  const vector<string>& GetMessages(LogLevel error);
+
+ private:
+  map<LogLevel, vector<string> > messages_;
+  LogHandler* old_handler_;
+
+  static void HandleLog(LogLevel level, const char* filename, int line,
+                        const string& message);
+
+  static ScopedMemoryLog* active_log_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedMemoryLog);
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_GOOGLETEST_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/zcgunzip.cc b/src/third_party/protobuf-3/src/google/protobuf/testing/zcgunzip.cc
new file mode 100644
index 0000000..76f8cfe
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/zcgunzip.cc
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2009 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.
+
+// Author: brianolson@google.com (Brian Olson)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Test program to verify that GzipInputStream is compatible with command line
+// gunzip or java.util.zip.GzipInputStream
+//
+// Reads gzip stream on standard input and writes decompressed data to standard
+// output.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#ifdef _WIN32
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#endif
+
+#include <google/protobuf/io/gzip_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+using google::protobuf::io::FileInputStream;
+using google::protobuf::io::GzipInputStream;
+
+int main(int argc, const char** argv) {
+  FileInputStream fin(STDIN_FILENO);
+  GzipInputStream in(&fin);
+
+  while (true) {
+    const void* inptr;
+    int inlen;
+    bool ok;
+    ok = in.Next(&inptr, &inlen);
+    if (!ok) {
+      break;
+    }
+    if (inlen > 0) {
+      int err = write(STDOUT_FILENO, inptr, inlen);
+      assert(err == inlen);
+    }
+  }
+
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/testing/zcgzip.cc b/src/third_party/protobuf-3/src/google/protobuf/testing/zcgzip.cc
new file mode 100644
index 0000000..992ddc6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/testing/zcgzip.cc
@@ -0,0 +1,86 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2009 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.
+
+// Author: brianolson@google.com (Brian Olson)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Test program to verify that GzipOutputStream is compatible with command line
+// gzip or java.util.zip.GzipOutputStream
+//
+// Reads data on standard input and writes compressed gzip stream to standard
+// output.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#ifdef _WIN32
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#endif
+
+#include <google/protobuf/io/gzip_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+using google::protobuf::io::FileOutputStream;
+using google::protobuf::io::GzipOutputStream;
+
+int main(int argc, const char** argv) {
+  FileOutputStream fout(STDOUT_FILENO);
+  GzipOutputStream out(&fout);
+  int readlen;
+
+  while (true) {
+    void* outptr;
+    int outlen;
+    bool ok;
+    do {
+      ok = out.Next(&outptr, &outlen);
+      if (!ok) {
+        break;
+      }
+    } while (outlen <= 0);
+    readlen = read(STDIN_FILENO, outptr, outlen);
+    if (readlen <= 0) {
+      out.BackUp(outlen);
+      break;
+    }
+    if (readlen < outlen) {
+      out.BackUp(outlen - readlen);
+    }
+  }
+
+  return 0;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/text_format.cc b/src/third_party/protobuf-3/src/google/protobuf/text_format.cc
new file mode 100644
index 0000000..c0dfd53
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/text_format.cc
@@ -0,0 +1,1975 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <stack>
+#include <limits>
+#include <vector>
+
+#include <google/protobuf/text_format.h>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/io/strtod.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/any.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+inline bool IsHexNumber(const string& str) {
+  return (str.length() >= 2 && str[0] == '0' &&
+          (str[1] == 'x' || str[1] == 'X'));
+}
+
+inline bool IsOctNumber(const string& str) {
+  return (str.length() >= 2 && str[0] == '0' &&
+          (str[1] >= '0' && str[1] < '8'));
+}
+
+inline bool GetAnyFieldDescriptors(const Message& message,
+                                   const FieldDescriptor** type_url_field,
+                                   const FieldDescriptor** value_field) {
+    const Descriptor* descriptor = message.GetDescriptor();
+    *type_url_field = descriptor->FindFieldByNumber(1);
+    *value_field = descriptor->FindFieldByNumber(2);
+    return (*type_url_field != NULL &&
+            (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+            *value_field != NULL &&
+            (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
+}  // namespace
+
+string Message::DebugString() const {
+  string debug_string;
+
+  TextFormat::Printer printer;
+  printer.SetExpandAny(true);
+
+  printer.PrintToString(*this, &debug_string);
+
+  return debug_string;
+}
+
+string Message::ShortDebugString() const {
+  string debug_string;
+
+  TextFormat::Printer printer;
+  printer.SetSingleLineMode(true);
+  printer.SetExpandAny(true);
+
+  printer.PrintToString(*this, &debug_string);
+  // Single line mode currently might have an extra space at the end.
+  if (debug_string.size() > 0 &&
+      debug_string[debug_string.size() - 1] == ' ') {
+    debug_string.resize(debug_string.size() - 1);
+  }
+
+  return debug_string;
+}
+
+string Message::Utf8DebugString() const {
+  string debug_string;
+
+  TextFormat::Printer printer;
+  printer.SetUseUtf8StringEscaping(true);
+  printer.SetExpandAny(true);
+
+  printer.PrintToString(*this, &debug_string);
+
+  return debug_string;
+}
+
+void Message::PrintDebugString() const {
+  printf("%s", DebugString().c_str());
+}
+
+
+// ===========================================================================
+// Implementation of the parse information tree class.
+TextFormat::ParseInfoTree::ParseInfoTree() { }
+
+TextFormat::ParseInfoTree::~ParseInfoTree() {
+  // Remove any nested information trees, as they are owned by this tree.
+  for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) {
+    STLDeleteElements(&(it->second));
+  }
+}
+
+void TextFormat::ParseInfoTree::RecordLocation(
+    const FieldDescriptor* field,
+    TextFormat::ParseLocation location) {
+  locations_[field].push_back(location);
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested(
+    const FieldDescriptor* field) {
+  // Owned by us in the map.
+  TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree();
+  vector<TextFormat::ParseInfoTree*>* trees = &nested_[field];
+  GOOGLE_CHECK(trees);
+  trees->push_back(instance);
+  return instance;
+}
+
+void CheckFieldIndex(const FieldDescriptor* field, int index) {
+  if (field == NULL) { return; }
+
+  if (field->is_repeated() && index == -1) {
+    GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. "
+                << "Field: " << field->name();
+  } else if (!field->is_repeated() && index != -1) {
+    GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields."
+                << "Field: " << field->name();
+  }
+}
+
+TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation(
+    const FieldDescriptor* field, int index) const {
+  CheckFieldIndex(field, index);
+  if (index == -1) { index = 0; }
+
+  const vector<TextFormat::ParseLocation>* locations =
+      FindOrNull(locations_, field);
+  if (locations == NULL || index >= locations->size()) {
+    return TextFormat::ParseLocation();
+  }
+
+  return (*locations)[index];
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
+    const FieldDescriptor* field, int index) const {
+  CheckFieldIndex(field, index);
+  if (index == -1) { index = 0; }
+
+  const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field);
+  if (trees == NULL || index >= trees->size()) {
+    return NULL;
+  }
+
+  return (*trees)[index];
+}
+
+
+// ===========================================================================
+// Internal class for parsing an ASCII representation of a Protocol Message.
+// This class makes use of the Protocol Message compiler's tokenizer found
+// in //google/protobuf/io/tokenizer.h. Note that class's Parse
+// method is *not* thread-safe and should only be used in a single thread at
+// a time.
+
+// Makes code slightly more readable.  The meaning of "DO(foo)" is
+// "Execute foo and fail if it fails.", where failure is indicated by
+// returning false. Borrowed from parser.cc (Thanks Kenton!).
+#define DO(STATEMENT) if (STATEMENT) {} else return false
+
+class TextFormat::Parser::ParserImpl {
+ public:
+
+  // Determines if repeated values for non-repeated fields and
+  // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a
+  // required/optional field named "foo", or "baz: 1 qux: 2"
+  // where "baz" and "qux" are members of the same oneof.
+  enum SingularOverwritePolicy {
+    ALLOW_SINGULAR_OVERWRITES = 0,   // the last value is retained
+    FORBID_SINGULAR_OVERWRITES = 1,  // an error is issued
+  };
+
+  ParserImpl(const Descriptor* root_message_type,
+             io::ZeroCopyInputStream* input_stream,
+             io::ErrorCollector* error_collector,
+             TextFormat::Finder* finder,
+             ParseInfoTree* parse_info_tree,
+             SingularOverwritePolicy singular_overwrite_policy,
+             bool allow_case_insensitive_field,
+             bool allow_unknown_field,
+             bool allow_unknown_enum,
+             bool allow_field_number,
+             bool allow_relaxed_whitespace)
+    : error_collector_(error_collector),
+      finder_(finder),
+      parse_info_tree_(parse_info_tree),
+      tokenizer_error_collector_(this),
+      tokenizer_(input_stream, &tokenizer_error_collector_),
+      root_message_type_(root_message_type),
+      singular_overwrite_policy_(singular_overwrite_policy),
+      allow_case_insensitive_field_(allow_case_insensitive_field),
+      allow_unknown_field_(allow_unknown_field),
+      allow_unknown_enum_(allow_unknown_enum),
+      allow_field_number_(allow_field_number),
+      had_errors_(false) {
+    // For backwards-compatibility with proto1, we need to allow the 'f' suffix
+    // for floats.
+    tokenizer_.set_allow_f_after_float(true);
+
+    // '#' starts a comment.
+    tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE);
+
+    if (allow_relaxed_whitespace) {
+      tokenizer_.set_require_space_after_number(false);
+      tokenizer_.set_allow_multiline_strings(true);
+    }
+
+    // Consume the starting token.
+    tokenizer_.Next();
+  }
+  ~ParserImpl() { }
+
+  // Parses the ASCII representation specified in input and saves the
+  // information into the output pointer (a Message). Returns
+  // false if an error occurs (an error will also be logged to
+  // GOOGLE_LOG(ERROR)).
+  bool Parse(Message* output) {
+    // Consume fields until we cannot do so anymore.
+    while (true) {
+      if (LookingAtType(io::Tokenizer::TYPE_END)) {
+        return !had_errors_;
+      }
+
+      DO(ConsumeField(output));
+    }
+  }
+
+  bool ParseField(const FieldDescriptor* field, Message* output) {
+    bool suc;
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      suc = ConsumeFieldMessage(output, output->GetReflection(), field);
+    } else {
+      suc = ConsumeFieldValue(output, output->GetReflection(), field);
+    }
+    return suc && LookingAtType(io::Tokenizer::TYPE_END);
+  }
+
+  void ReportError(int line, int col, const string& message) {
+    had_errors_ = true;
+    if (error_collector_ == NULL) {
+      if (line >= 0) {
+        GOOGLE_LOG(ERROR) << "Error parsing text-format "
+                   << root_message_type_->full_name()
+                   << ": " << (line + 1) << ":"
+                   << (col + 1) << ": " << message;
+      } else {
+        GOOGLE_LOG(ERROR) << "Error parsing text-format "
+                   << root_message_type_->full_name()
+                   << ": " << message;
+      }
+    } else {
+      error_collector_->AddError(line, col, message);
+    }
+  }
+
+  void ReportWarning(int line, int col, const string& message) {
+    if (error_collector_ == NULL) {
+      if (line >= 0) {
+        GOOGLE_LOG(WARNING) << "Warning parsing text-format "
+                     << root_message_type_->full_name()
+                     << ": " << (line + 1) << ":"
+                     << (col + 1) << ": " << message;
+      } else {
+        GOOGLE_LOG(WARNING) << "Warning parsing text-format "
+                     << root_message_type_->full_name()
+                     << ": " << message;
+      }
+    } else {
+      error_collector_->AddWarning(line, col, message);
+    }
+  }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl);
+
+  // Reports an error with the given message with information indicating
+  // the position (as derived from the current token).
+  void ReportError(const string& message) {
+    ReportError(tokenizer_.current().line, tokenizer_.current().column,
+                message);
+  }
+
+  // Reports a warning with the given message with information indicating
+  // the position (as derived from the current token).
+  void ReportWarning(const string& message) {
+    ReportWarning(tokenizer_.current().line, tokenizer_.current().column,
+                  message);
+  }
+
+  // Consumes the specified message with the given starting delimiter.
+  // This method checks to see that the end delimiter at the conclusion of
+  // the consumption matches the starting delimiter passed in here.
+  bool ConsumeMessage(Message* message, const string delimiter) {
+    while (!LookingAt(">") &&  !LookingAt("}")) {
+      DO(ConsumeField(message));
+    }
+
+    // Confirm that we have a valid ending delimiter.
+    DO(Consume(delimiter));
+    return true;
+  }
+
+  // Consume either "<" or "{".
+  bool ConsumeMessageDelimiter(string* delimiter) {
+    if (TryConsume("<")) {
+      *delimiter = ">";
+    } else {
+      DO(Consume("{"));
+      *delimiter = "}";
+    }
+    return true;
+  }
+
+
+  // Consumes the current field (as returned by the tokenizer) on the
+  // passed in message.
+  bool ConsumeField(Message* message) {
+    const Reflection* reflection = message->GetReflection();
+    const Descriptor* descriptor = message->GetDescriptor();
+
+    string field_name;
+
+    const FieldDescriptor* field = NULL;
+    int start_line = tokenizer_.current().line;
+    int start_column = tokenizer_.current().column;
+
+    const FieldDescriptor* any_type_url_field;
+    const FieldDescriptor* any_value_field;
+    if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
+                                         &any_value_field) &&
+        TryConsume("[")) {
+      string full_type_name, prefix;
+      DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
+      DO(Consume("]"));
+      TryConsume(":");  // ':' is optional between message labels and values.
+      string serialized_value;
+      DO(ConsumeAnyValue(full_type_name,
+                         message->GetDescriptor()->file()->pool(),
+                         &serialized_value));
+      reflection->SetString(
+          message, any_type_url_field,
+          string(prefix + full_type_name));
+      reflection->SetString(message, any_value_field, serialized_value);
+      return true;
+    }
+    if (TryConsume("[")) {
+      // Extension.
+      DO(ConsumeFullTypeName(&field_name));
+      DO(Consume("]"));
+
+      field = (finder_ != NULL
+               ? finder_->FindExtension(message, field_name)
+               : reflection->FindKnownExtensionByName(field_name));
+
+      if (field == NULL) {
+        if (!allow_unknown_field_) {
+          ReportError("Extension \"" + field_name + "\" is not defined or "
+                      "is not an extension of \"" +
+                      descriptor->full_name() + "\".");
+          return false;
+        } else {
+          ReportWarning("Extension \"" + field_name + "\" is not defined or "
+                        "is not an extension of \"" +
+                        descriptor->full_name() + "\".");
+        }
+      }
+    } else {
+      DO(ConsumeIdentifier(&field_name));
+
+      int32 field_number;
+      if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
+        if (descriptor->IsExtensionNumber(field_number)) {
+          field = reflection->FindKnownExtensionByNumber(field_number);
+        } else {
+          field = descriptor->FindFieldByNumber(field_number);
+        }
+      } else {
+        field = descriptor->FindFieldByName(field_name);
+        // Group names are expected to be capitalized as they appear in the
+        // .proto file, which actually matches their type names, not their
+        // field names.
+        if (field == NULL) {
+          string lower_field_name = field_name;
+          LowerString(&lower_field_name);
+          field = descriptor->FindFieldByName(lower_field_name);
+          // If the case-insensitive match worked but the field is NOT a group,
+          if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) {
+            field = NULL;
+          }
+        }
+        // Again, special-case group names as described above.
+        if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP
+            && field->message_type()->name() != field_name) {
+          field = NULL;
+        }
+
+        if (field == NULL && allow_case_insensitive_field_) {
+          string lower_field_name = field_name;
+          LowerString(&lower_field_name);
+          field = descriptor->FindFieldByLowercaseName(lower_field_name);
+        }
+      }
+
+      if (field == NULL) {
+        if (!allow_unknown_field_) {
+          ReportError("Message type \"" + descriptor->full_name() +
+                      "\" has no field named \"" + field_name + "\".");
+          return false;
+        } else {
+          ReportWarning("Message type \"" + descriptor->full_name() +
+                        "\" has no field named \"" + field_name + "\".");
+        }
+      }
+    }
+
+    // Skips unknown field.
+    if (field == NULL) {
+      GOOGLE_CHECK(allow_unknown_field_);
+      // Try to guess the type of this field.
+      // If this field is not a message, there should be a ":" between the
+      // field name and the field value and also the field value should not
+      // start with "{" or "<" which indicates the beginning of a message body.
+      // If there is no ":" or there is a "{" or "<" after ":", this field has
+      // to be a message or the input is ill-formed.
+      if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+        return SkipFieldValue();
+      } else {
+        return SkipFieldMessage();
+      }
+    }
+
+    if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
+      // Fail if the field is not repeated and it has already been specified.
+      if (!field->is_repeated() && reflection->HasField(*message, field)) {
+        ReportError("Non-repeated field \"" + field_name +
+                    "\" is specified multiple times.");
+        return false;
+      }
+      // Fail if the field is a member of a oneof and another member has already
+      // been specified.
+      const OneofDescriptor* oneof = field->containing_oneof();
+      if (oneof != NULL && reflection->HasOneof(*message, oneof)) {
+        const FieldDescriptor* other_field =
+            reflection->GetOneofFieldDescriptor(*message, oneof);
+        ReportError("Field \"" + field_name + "\" is specified along with "
+                    "field \"" + other_field->name() + "\", another member "
+                    "of oneof \"" + oneof->name() + "\".");
+        return false;
+      }
+    }
+
+    // Perform special handling for embedded message types.
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // ':' is optional here.
+      TryConsume(":");
+    } else {
+      // ':' is required here.
+      DO(Consume(":"));
+    }
+
+    if (field->is_repeated() && TryConsume("[")) {
+      // Short repeated format, e.g.  "foo: [1, 2, 3]"
+      while (true) {
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+          // Perform special handling for embedded message types.
+          DO(ConsumeFieldMessage(message, reflection, field));
+        } else {
+          DO(ConsumeFieldValue(message, reflection, field));
+        }
+        if (TryConsume("]")) {
+          break;
+        }
+        DO(Consume(","));
+      }
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      DO(ConsumeFieldMessage(message, reflection, field));
+    } else {
+      DO(ConsumeFieldValue(message, reflection, field));
+    }
+
+    // For historical reasons, fields may optionally be separated by commas or
+    // semicolons.
+    TryConsume(";") || TryConsume(",");
+
+    if (field->options().deprecated()) {
+      ReportWarning("text format contains deprecated field \""
+                    + field_name + "\"");
+    }
+
+    // If a parse info tree exists, add the location for the parsed
+    // field.
+    if (parse_info_tree_ != NULL) {
+      RecordLocation(parse_info_tree_, field,
+                     ParseLocation(start_line, start_column));
+    }
+
+    return true;
+  }
+
+  // Skips the next field including the field's name and value.
+  bool SkipField() {
+    string field_name;
+    if (TryConsume("[")) {
+      // Extension name.
+      DO(ConsumeFullTypeName(&field_name));
+      DO(Consume("]"));
+    } else {
+      DO(ConsumeIdentifier(&field_name));
+    }
+
+    // Try to guess the type of this field.
+    // If this field is not a message, there should be a ":" between the
+    // field name and the field value and also the field value should not
+    // start with "{" or "<" which indicates the beginning of a message body.
+    // If there is no ":" or there is a "{" or "<" after ":", this field has
+    // to be a message or the input is ill-formed.
+    if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+      DO(SkipFieldValue());
+    } else {
+      DO(SkipFieldMessage());
+    }
+    // For historical reasons, fields may optionally be separated by commas or
+    // semicolons.
+    TryConsume(";") || TryConsume(",");
+    return true;
+  }
+
+  bool ConsumeFieldMessage(Message* message,
+                           const Reflection* reflection,
+                           const FieldDescriptor* field) {
+
+    // If the parse information tree is not NULL, create a nested one
+    // for the nested message.
+    ParseInfoTree* parent = parse_info_tree_;
+    if (parent != NULL) {
+      parse_info_tree_ = CreateNested(parent, field);
+    }
+
+    string delimiter;
+    DO(ConsumeMessageDelimiter(&delimiter));
+    if (field->is_repeated()) {
+      DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter));
+    } else {
+      DO(ConsumeMessage(reflection->MutableMessage(message, field),
+                        delimiter));
+    }
+
+    // Reset the parse information tree.
+    parse_info_tree_ = parent;
+    return true;
+  }
+
+  // Skips the whole body of a message including the beginning delimiter and
+  // the ending delimiter.
+  bool SkipFieldMessage() {
+    string delimiter;
+    DO(ConsumeMessageDelimiter(&delimiter));
+    while (!LookingAt(">") &&  !LookingAt("}")) {
+      DO(SkipField());
+    }
+    DO(Consume(delimiter));
+    return true;
+  }
+
+  bool ConsumeFieldValue(Message* message,
+                         const Reflection* reflection,
+                         const FieldDescriptor* field) {
+
+// Define an easy to use macro for setting fields. This macro checks
+// to see if the field is repeated (in which case we need to use the Add
+// methods or not (in which case we need to use the Set methods).
+#define SET_FIELD(CPPTYPE, VALUE)                                  \
+        if (field->is_repeated()) {                                \
+          reflection->Add##CPPTYPE(message, field, VALUE);         \
+        } else {                                                   \
+          reflection->Set##CPPTYPE(message, field, VALUE);         \
+        }                                                          \
+
+    switch(field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_INT32: {
+        int64 value;
+        DO(ConsumeSignedInteger(&value, kint32max));
+        SET_FIELD(Int32, static_cast<int32>(value));
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_UINT32: {
+        uint64 value;
+        DO(ConsumeUnsignedInteger(&value, kuint32max));
+        SET_FIELD(UInt32, static_cast<uint32>(value));
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_INT64: {
+        int64 value;
+        DO(ConsumeSignedInteger(&value, kint64max));
+        SET_FIELD(Int64, value);
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_UINT64: {
+        uint64 value;
+        DO(ConsumeUnsignedInteger(&value, kuint64max));
+        SET_FIELD(UInt64, value);
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_FLOAT: {
+        double value;
+        DO(ConsumeDouble(&value));
+        SET_FIELD(Float, io::SafeDoubleToFloat(value));
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_DOUBLE: {
+        double value;
+        DO(ConsumeDouble(&value));
+        SET_FIELD(Double, value);
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_STRING: {
+        string value;
+        DO(ConsumeString(&value));
+        SET_FIELD(String, value);
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_BOOL: {
+        if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          uint64 value;
+          DO(ConsumeUnsignedInteger(&value, 1));
+          SET_FIELD(Bool, value);
+        } else {
+          string value;
+          DO(ConsumeIdentifier(&value));
+          if (value == "true" || value == "True" || value == "t") {
+            SET_FIELD(Bool, true);
+          } else if (value == "false" || value == "False" || value == "f") {
+            SET_FIELD(Bool, false);
+          } else {
+            ReportError("Invalid value for boolean field \"" + field->name()
+                        + "\". Value: \"" + value  + "\".");
+            return false;
+          }
+        }
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_ENUM: {
+        string value;
+        const EnumDescriptor* enum_type = field->enum_type();
+        const EnumValueDescriptor* enum_value = NULL;
+
+        if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+          DO(ConsumeIdentifier(&value));
+          // Find the enumeration value.
+          enum_value = enum_type->FindValueByName(value);
+
+        } else if (LookingAt("-") ||
+                   LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          int64 int_value;
+          DO(ConsumeSignedInteger(&int_value, kint32max));
+          value = SimpleItoa(int_value);        // for error reporting
+          enum_value = enum_type->FindValueByNumber(int_value);
+        } else {
+          ReportError("Expected integer or identifier.");
+          return false;
+        }
+
+        if (enum_value == NULL) {
+          if (!allow_unknown_enum_) {
+            ReportError("Unknown enumeration value of \"" + value  + "\" for "
+                        "field \"" + field->name() + "\".");
+            return false;
+          } else {
+            ReportWarning("Unknown enumeration value of \"" + value  + "\" for "
+                          "field \"" + field->name() + "\".");
+            return true;
+          }
+        }
+
+        SET_FIELD(Enum, enum_value);
+        break;
+      }
+
+      case FieldDescriptor::CPPTYPE_MESSAGE: {
+        // We should never get here. Put here instead of a default
+        // so that if new types are added, we get a nice compiler warning.
+        GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE";
+        break;
+      }
+    }
+#undef SET_FIELD
+    return true;
+  }
+
+  bool SkipFieldValue() {
+    if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+      while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+        tokenizer_.Next();
+      }
+      return true;
+    }
+    // Possible field values other than string:
+    //   12345        => TYPE_INTEGER
+    //   -12345       => TYPE_SYMBOL + TYPE_INTEGER
+    //   1.2345       => TYPE_FLOAT
+    //   -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
+    //   inf          => TYPE_IDENTIFIER
+    //   -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
+    //   TYPE_INTEGER => TYPE_IDENTIFIER
+    // Divides them into two group, one with TYPE_SYMBOL
+    // and the other without:
+    //   Group one:
+    //     12345        => TYPE_INTEGER
+    //     1.2345       => TYPE_FLOAT
+    //     inf          => TYPE_IDENTIFIER
+    //     TYPE_INTEGER => TYPE_IDENTIFIER
+    //   Group two:
+    //     -12345       => TYPE_SYMBOL + TYPE_INTEGER
+    //     -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
+    //     -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
+    // As we can see, the field value consists of an optional '-' and one of
+    // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER.
+    bool has_minus = TryConsume("-");
+    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) &&
+        !LookingAtType(io::Tokenizer::TYPE_FLOAT) &&
+        !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      return false;
+    }
+    // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field
+    // value while other combinations all generate valid values.
+    // We check if the value of this combination is valid here.
+    // TYPE_IDENTIFIER after a '-' should be one of the float values listed
+    // below:
+    //   inf, inff, infinity, nan
+    if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      string text = tokenizer_.current().text;
+      LowerString(&text);
+      if (text != "inf" &&
+          text != "infinity" &&
+          text != "nan") {
+        ReportError("Invalid float number: " + text);
+        return false;
+      }
+    }
+    tokenizer_.Next();
+    return true;
+  }
+
+  // Returns true if the current token's text is equal to that specified.
+  bool LookingAt(const string& text) {
+    return tokenizer_.current().text == text;
+  }
+
+  // Returns true if the current token's type is equal to that specified.
+  bool LookingAtType(io::Tokenizer::TokenType token_type) {
+    return tokenizer_.current().type == token_type;
+  }
+
+  // Consumes an identifier and saves its value in the identifier parameter.
+  // Returns false if the token is not of type IDENTFIER.
+  bool ConsumeIdentifier(string* identifier) {
+    if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      *identifier = tokenizer_.current().text;
+      tokenizer_.Next();
+      return true;
+    }
+
+    // If allow_field_numer_ or allow_unknown_field_ is true, we should able
+    // to parse integer identifiers.
+    if ((allow_field_number_ || allow_unknown_field_)
+        && LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+      *identifier = tokenizer_.current().text;
+      tokenizer_.Next();
+      return true;
+    }
+
+    ReportError("Expected identifier.");
+    return false;
+  }
+
+  // Consume a string of form "<id1>.<id2>....<idN>".
+  bool ConsumeFullTypeName(string* name) {
+    DO(ConsumeIdentifier(name));
+    while (TryConsume(".")) {
+      string part;
+      DO(ConsumeIdentifier(&part));
+      *name += ".";
+      *name += part;
+    }
+    return true;
+  }
+
+  // Consumes a string and saves its value in the text parameter.
+  // Returns false if the token is not of type STRING.
+  bool ConsumeString(string* text) {
+    if (!LookingAtType(io::Tokenizer::TYPE_STRING)) {
+      ReportError("Expected string.");
+      return false;
+    }
+
+    text->clear();
+    while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+      io::Tokenizer::ParseStringAppend(tokenizer_.current().text, text);
+
+      tokenizer_.Next();
+    }
+
+    return true;
+  }
+
+  // Consumes a uint64 and saves its value in the value parameter.
+  // Returns false if the token is not of type INTEGER.
+  bool ConsumeUnsignedInteger(uint64* value, uint64 max_value) {
+    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+      ReportError("Expected integer.");
+      return false;
+    }
+
+    if (!io::Tokenizer::ParseInteger(tokenizer_.current().text,
+                                     max_value, value)) {
+      ReportError("Integer out of range.");
+      return false;
+    }
+
+    tokenizer_.Next();
+    return true;
+  }
+
+  // Consumes an int64 and saves its value in the value parameter.
+  // Note that since the tokenizer does not support negative numbers,
+  // we actually may consume an additional token (for the minus sign) in this
+  // method. Returns false if the token is not an integer
+  // (signed or otherwise).
+  bool ConsumeSignedInteger(int64* value, uint64 max_value) {
+    bool negative = false;
+
+    if (TryConsume("-")) {
+      negative = true;
+      // Two's complement always allows one more negative integer than
+      // positive.
+      ++max_value;
+    }
+
+    uint64 unsigned_value;
+
+    DO(ConsumeUnsignedInteger(&unsigned_value, max_value));
+
+    *value = static_cast<int64>(unsigned_value);
+
+    if (negative) {
+      *value = -*value;
+    }
+
+    return true;
+  }
+
+  // Consumes a uint64 and saves its value in the value parameter.
+  // Accepts decimal numbers only, rejects hex or oct numbers.
+  bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) {
+    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+      ReportError("Expected integer.");
+      return false;
+    }
+
+    const string& text = tokenizer_.current().text;
+    if (IsHexNumber(text) || IsOctNumber(text)) {
+      ReportError("Expect a decimal number.");
+      return false;
+    }
+
+    if (!io::Tokenizer::ParseInteger(text, max_value, value)) {
+      ReportError("Integer out of range.");
+      return false;
+    }
+
+    tokenizer_.Next();
+    return true;
+  }
+
+  // Consumes a double and saves its value in the value parameter.
+  // Note that since the tokenizer does not support negative numbers,
+  // we actually may consume an additional token (for the minus sign) in this
+  // method. Returns false if the token is not a double
+  // (signed or otherwise).
+  bool ConsumeDouble(double* value) {
+    bool negative = false;
+
+    if (TryConsume("-")) {
+      negative = true;
+    }
+
+    // A double can actually be an integer, according to the tokenizer.
+    // Therefore, we must check both cases here.
+    if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+      // We have found an integer value for the double.
+      uint64 integer_value;
+      DO(ConsumeUnsignedDecimalInteger(&integer_value, kuint64max));
+
+      *value = static_cast<double>(integer_value);
+    } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
+      // We have found a float value for the double.
+      *value = io::Tokenizer::ParseFloat(tokenizer_.current().text);
+
+      // Mark the current token as consumed.
+      tokenizer_.Next();
+    } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      string text = tokenizer_.current().text;
+      LowerString(&text);
+      if (text == "inf" ||
+          text == "infinity") {
+        *value = std::numeric_limits<double>::infinity();
+        tokenizer_.Next();
+      } else if (text == "nan") {
+        *value = std::numeric_limits<double>::quiet_NaN();
+        tokenizer_.Next();
+      } else {
+        ReportError("Expected double.");
+        return false;
+      }
+    } else {
+      ReportError("Expected double.");
+      return false;
+    }
+
+    if (negative) {
+      *value = -*value;
+    }
+
+    return true;
+  }
+
+  // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name"
+  // or "type.googleprod.com/full.type.Name"
+  bool ConsumeAnyTypeUrl(string* full_type_name, string* prefix) {
+    // TODO(saito) Extend Consume() to consume multiple tokens at once, so that
+    // this code can be written as just DO(Consume(kGoogleApisTypePrefix)).
+    string url1, url2, url3;
+    DO(ConsumeIdentifier(&url1));  // type
+    DO(Consume("."));
+    DO(ConsumeIdentifier(&url2));  // googleapis
+    DO(Consume("."));
+    DO(ConsumeIdentifier(&url3));  // com
+    DO(Consume("/"));
+    DO(ConsumeFullTypeName(full_type_name));
+
+    *prefix = url1 + "." + url2 + "." + url3 + "/";
+    if (*prefix != internal::kTypeGoogleApisComPrefix &&
+        *prefix != internal::kTypeGoogleProdComPrefix) {
+      ReportError("TextFormat::Parser for Any supports only "
+                  "type.googleapis.com and type.googleprod.com, "
+                  "but found \"" + *prefix + "\"");
+      return false;
+    }
+    return true;
+  }
+
+  // A helper function for reconstructing Any::value. Consumes a text of
+  // full_type_name, then serializes it into serialized_value. "pool" is used to
+  // look up and create a temporary object with full_type_name.
+  bool ConsumeAnyValue(const string& full_type_name, const DescriptorPool* pool,
+                       string* serialized_value) {
+    const Descriptor* value_descriptor =
+        pool->FindMessageTypeByName(full_type_name);
+    if (value_descriptor == NULL) {
+      ReportError("Could not find type \"" + full_type_name +
+                  "\" stored in google.protobuf.Any.");
+      return false;
+    }
+    DynamicMessageFactory factory;
+    const Message* value_prototype = factory.GetPrototype(value_descriptor);
+    if (value_prototype == NULL) {
+      return false;
+    }
+    google::protobuf::scoped_ptr<Message> value(value_prototype->New());
+    string sub_delimiter;
+    DO(ConsumeMessageDelimiter(&sub_delimiter));
+    DO(ConsumeMessage(value.get(), sub_delimiter));
+
+    value->AppendToString(serialized_value);
+    return true;
+  }
+
+  // Consumes a token and confirms that it matches that specified in the
+  // value parameter. Returns false if the token found does not match that
+  // which was specified.
+  bool Consume(const string& value) {
+    const string& current_value = tokenizer_.current().text;
+
+    if (current_value != value) {
+      ReportError("Expected \"" + value + "\", found \"" + current_value
+                  + "\".");
+      return false;
+    }
+
+    tokenizer_.Next();
+
+    return true;
+  }
+
+  // Attempts to consume the supplied value. Returns false if a the
+  // token found does not match the value specified.
+  bool TryConsume(const string& value) {
+    if (tokenizer_.current().text == value) {
+      tokenizer_.Next();
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  // An internal instance of the Tokenizer's error collector, used to
+  // collect any base-level parse errors and feed them to the ParserImpl.
+  class ParserErrorCollector : public io::ErrorCollector {
+   public:
+    explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) :
+        parser_(parser) { }
+
+    virtual ~ParserErrorCollector() { }
+
+    virtual void AddError(int line, int column, const string& message) {
+      parser_->ReportError(line, column, message);
+    }
+
+    virtual void AddWarning(int line, int column, const string& message) {
+      parser_->ReportWarning(line, column, message);
+    }
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector);
+    TextFormat::Parser::ParserImpl* parser_;
+  };
+
+  io::ErrorCollector* error_collector_;
+  TextFormat::Finder* finder_;
+  ParseInfoTree* parse_info_tree_;
+  ParserErrorCollector tokenizer_error_collector_;
+  io::Tokenizer tokenizer_;
+  const Descriptor* root_message_type_;
+  SingularOverwritePolicy singular_overwrite_policy_;
+  const bool allow_case_insensitive_field_;
+  const bool allow_unknown_field_;
+  const bool allow_unknown_enum_;
+  const bool allow_field_number_;
+  bool had_errors_;
+};
+
+#undef DO
+
+// ===========================================================================
+// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
+// from the Printer found in //google/protobuf/io/printer.h
+class TextFormat::Printer::TextGenerator {
+ public:
+  explicit TextGenerator(io::ZeroCopyOutputStream* output,
+                         int initial_indent_level)
+    : output_(output),
+      buffer_(NULL),
+      buffer_size_(0),
+      at_start_of_line_(true),
+      failed_(false),
+      indent_(""),
+      initial_indent_level_(initial_indent_level) {
+    indent_.resize(initial_indent_level_ * 2, ' ');
+  }
+
+  ~TextGenerator() {
+    // Only BackUp() if we're sure we've successfully called Next() at least
+    // once.
+    if (!failed_ && buffer_size_ > 0) {
+      output_->BackUp(buffer_size_);
+    }
+  }
+
+  // Indent text by two spaces.  After calling Indent(), two spaces will be
+  // inserted at the beginning of each line of text.  Indent() may be called
+  // multiple times to produce deeper indents.
+  void Indent() {
+    indent_ += "  ";
+  }
+
+  // Reduces the current indent level by two spaces, or crashes if the indent
+  // level is zero.
+  void Outdent() {
+    if (indent_.empty() ||
+        indent_.size() < initial_indent_level_ * 2) {
+      GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
+      return;
+    }
+
+    indent_.resize(indent_.size() - 2);
+  }
+
+  // Print text to the output stream.
+  void Print(const string& str) {
+    Print(str.data(), str.size());
+  }
+
+  // Print text to the output stream.
+  void Print(const char* text) {
+    Print(text, strlen(text));
+  }
+
+  // Print text to the output stream.
+  void Print(const char* text, size_t size) {
+    size_t pos = 0;  // The number of bytes we've written so far.
+
+    for (size_t i = 0; i < size; i++) {
+      if (text[i] == '\n') {
+        // Saw newline.  If there is more text, we may need to insert an indent
+        // here.  So, write what we have so far, including the '\n'.
+        Write(text + pos, i - pos + 1);
+        pos = i + 1;
+
+        // Setting this true will cause the next Write() to insert an indent
+        // first.
+        at_start_of_line_ = true;
+      }
+    }
+
+    // Write the rest.
+    Write(text + pos, size - pos);
+  }
+
+  // True if any write to the underlying stream failed.  (We don't just
+  // crash in this case because this is an I/O failure, not a programming
+  // error.)
+  bool failed() const { return failed_; }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
+
+  void Write(const char* data, size_t size) {
+    if (failed_) return;
+    if (size == 0) return;
+
+    if (at_start_of_line_) {
+      // Insert an indent.
+      at_start_of_line_ = false;
+      Write(indent_.data(), indent_.size());
+      if (failed_) return;
+    }
+
+    while (size > buffer_size_) {
+      // Data exceeds space in the buffer.  Copy what we can and request a
+      // new buffer.
+      memcpy(buffer_, data, buffer_size_);
+      data += buffer_size_;
+      size -= buffer_size_;
+      void* void_buffer;
+      failed_ = !output_->Next(&void_buffer, &buffer_size_);
+      if (failed_) return;
+      buffer_ = reinterpret_cast<char*>(void_buffer);
+    }
+
+    // Buffer is big enough to receive the data; copy it.
+    memcpy(buffer_, data, size);
+    buffer_ += size;
+    buffer_size_ -= size;
+  }
+
+  io::ZeroCopyOutputStream* const output_;
+  char* buffer_;
+  int buffer_size_;
+  bool at_start_of_line_;
+  bool failed_;
+
+  string indent_;
+  int initial_indent_level_;
+};
+
+// ===========================================================================
+
+TextFormat::Finder::~Finder() {
+}
+
+TextFormat::Parser::Parser()
+  : error_collector_(NULL),
+    finder_(NULL),
+    parse_info_tree_(NULL),
+    allow_partial_(false),
+    allow_case_insensitive_field_(false),
+    allow_unknown_field_(false),
+    allow_unknown_enum_(false),
+    allow_field_number_(false),
+    allow_relaxed_whitespace_(false),
+    allow_singular_overwrites_(false) {
+}
+
+TextFormat::Parser::~Parser() {}
+
+bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input,
+                               Message* output) {
+  output->Clear();
+
+  ParserImpl::SingularOverwritePolicy overwrites_policy =
+      allow_singular_overwrites_
+      ? ParserImpl::ALLOW_SINGULAR_OVERWRITES
+      : ParserImpl::FORBID_SINGULAR_OVERWRITES;
+
+  ParserImpl parser(output->GetDescriptor(), input, error_collector_,
+                    finder_, parse_info_tree_,
+                    overwrites_policy,
+                    allow_case_insensitive_field_, allow_unknown_field_,
+                    allow_unknown_enum_, allow_field_number_,
+                    allow_relaxed_whitespace_);
+  return MergeUsingImpl(input, output, &parser);
+}
+
+bool TextFormat::Parser::ParseFromString(const string& input,
+                                         Message* output) {
+  io::ArrayInputStream input_stream(input.data(), input.size());
+  return Parse(&input_stream, output);
+}
+
+bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
+                               Message* output) {
+  ParserImpl parser(output->GetDescriptor(), input, error_collector_,
+                    finder_, parse_info_tree_,
+                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+                    allow_case_insensitive_field_, allow_unknown_field_,
+                    allow_unknown_enum_, allow_field_number_,
+                    allow_relaxed_whitespace_);
+  return MergeUsingImpl(input, output, &parser);
+}
+
+bool TextFormat::Parser::MergeFromString(const string& input,
+                                         Message* output) {
+  io::ArrayInputStream input_stream(input.data(), input.size());
+  return Merge(&input_stream, output);
+}
+
+bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */,
+                                        Message* output,
+                                        ParserImpl* parser_impl) {
+  if (!parser_impl->Parse(output)) return false;
+  if (!allow_partial_ && !output->IsInitialized()) {
+    vector<string> missing_fields;
+    output->FindInitializationErrors(&missing_fields);
+    parser_impl->ReportError(-1, 0, "Message missing required fields: " +
+                                        Join(missing_fields, ", "));
+    return false;
+  }
+  return true;
+}
+
+bool TextFormat::Parser::ParseFieldValueFromString(
+    const string& input,
+    const FieldDescriptor* field,
+    Message* output) {
+  io::ArrayInputStream input_stream(input.data(), input.size());
+  ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
+                    finder_, parse_info_tree_,
+                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+                    allow_case_insensitive_field_, allow_unknown_field_,
+                    allow_unknown_enum_, allow_field_number_,
+                    allow_relaxed_whitespace_);
+  return parser.ParseField(field, output);
+}
+
+/* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input,
+                                    Message* output) {
+  return Parser().Parse(input, output);
+}
+
+/* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input,
+                                    Message* output) {
+  return Parser().Merge(input, output);
+}
+
+/* static */ bool TextFormat::ParseFromString(const string& input,
+                                              Message* output) {
+  return Parser().ParseFromString(input, output);
+}
+
+/* static */ bool TextFormat::MergeFromString(const string& input,
+                                              Message* output) {
+  return Parser().MergeFromString(input, output);
+}
+
+// ===========================================================================
+
+// The default implementation for FieldValuePrinter. The base class just
+// does simple formatting. That way, deriving classes could decide to fallback
+// to that behavior.
+TextFormat::FieldValuePrinter::FieldValuePrinter() {}
+TextFormat::FieldValuePrinter::~FieldValuePrinter() {}
+string TextFormat::FieldValuePrinter::PrintBool(bool val) const {
+  return val ? "true" : "false";
+}
+string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const {
+  return SimpleItoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const {
+  return SimpleItoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const {
+  return SimpleItoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const {
+  return SimpleItoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintFloat(float val) const {
+  return SimpleFtoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintDouble(double val) const {
+  return SimpleDtoa(val);
+}
+string TextFormat::FieldValuePrinter::PrintString(const string& val) const {
+  string printed("\"");
+  CEscapeAndAppend(val, &printed);
+  printed.push_back('\"');
+  return printed;
+}
+string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const {
+  return PrintString(val);
+}
+string TextFormat::FieldValuePrinter::PrintEnum(int32 val,
+                                                const string& name) const {
+  return name;
+}
+string TextFormat::FieldValuePrinter::PrintFieldName(
+    const Message& message,
+    const Reflection* reflection,
+    const FieldDescriptor* field) const {
+  if (field->is_extension()) {
+    // We special-case MessageSet elements for compatibility with proto1.
+    if (field->containing_type()->options().message_set_wire_format()
+        && field->type() == FieldDescriptor::TYPE_MESSAGE
+        && field->is_optional()
+        && field->extension_scope() == field->message_type()) {
+      return StrCat("[", field->message_type()->full_name(), "]");
+    } else {
+      return StrCat("[", field->full_name(), "]");
+    }
+  } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    // Groups must be serialized with their original capitalization.
+    return field->message_type()->name();
+  } else {
+    return field->name();
+  }
+}
+string TextFormat::FieldValuePrinter::PrintMessageStart(
+    const Message& message,
+    int field_index,
+    int field_count,
+    bool single_line_mode) const {
+  return single_line_mode ? " { " : " {\n";
+}
+string TextFormat::FieldValuePrinter::PrintMessageEnd(
+    const Message& message,
+    int field_index,
+    int field_count,
+    bool single_line_mode) const {
+  return single_line_mode ? "} " : "}\n";
+}
+
+namespace {
+// Our own specialization: for UTF8 escaped strings.
+class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter {
+ public:
+  virtual string PrintString(const string& val) const {
+    return StrCat("\"", strings::Utf8SafeCEscape(val), "\"");
+  }
+  virtual string PrintBytes(const string& val) const {
+    return TextFormat::FieldValuePrinter::PrintString(val);
+  }
+};
+
+}  // namespace
+
+TextFormat::Printer::Printer()
+  : initial_indent_level_(0),
+    single_line_mode_(false),
+    use_field_number_(false),
+    use_short_repeated_primitives_(false),
+    hide_unknown_fields_(false),
+    print_message_fields_in_index_order_(false),
+    expand_any_(false),
+    truncate_string_field_longer_than_(0LL) {
+  SetUseUtf8StringEscaping(false);
+}
+
+TextFormat::Printer::~Printer() {
+  STLDeleteValues(&custom_printers_);
+}
+
+void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) {
+  SetDefaultFieldValuePrinter(as_utf8
+                              ? new FieldValuePrinterUtf8Escaping()
+                              : new FieldValuePrinter());
+}
+
+void TextFormat::Printer::SetDefaultFieldValuePrinter(
+    const FieldValuePrinter* printer) {
+  default_field_value_printer_.reset(printer);
+}
+
+bool TextFormat::Printer::RegisterFieldValuePrinter(
+    const FieldDescriptor* field,
+    const FieldValuePrinter* printer) {
+  return field != NULL && printer != NULL &&
+         custom_printers_.insert(std::make_pair(field, printer)).second;
+}
+
+bool TextFormat::Printer::PrintToString(const Message& message,
+                                        string* output) const {
+  GOOGLE_DCHECK(output) << "output specified is NULL";
+
+  output->clear();
+  io::StringOutputStream output_stream(output);
+
+  return Print(message, &output_stream);
+}
+
+bool TextFormat::Printer::PrintUnknownFieldsToString(
+    const UnknownFieldSet& unknown_fields,
+    string* output) const {
+  GOOGLE_DCHECK(output) << "output specified is NULL";
+
+  output->clear();
+  io::StringOutputStream output_stream(output);
+  return PrintUnknownFields(unknown_fields, &output_stream);
+}
+
+bool TextFormat::Printer::Print(const Message& message,
+                                io::ZeroCopyOutputStream* output) const {
+  TextGenerator generator(output, initial_indent_level_);
+
+  Print(message, generator);
+
+  // Output false if the generator failed internally.
+  return !generator.failed();
+}
+
+bool TextFormat::Printer::PrintUnknownFields(
+    const UnknownFieldSet& unknown_fields,
+    io::ZeroCopyOutputStream* output) const {
+  TextGenerator generator(output, initial_indent_level_);
+
+  PrintUnknownFields(unknown_fields, generator);
+
+  // Output false if the generator failed internally.
+  return !generator.failed();
+}
+
+namespace {
+// Comparison functor for sorting FieldDescriptors by field index.
+struct FieldIndexSorter {
+  bool operator()(const FieldDescriptor* left,
+                  const FieldDescriptor* right) const {
+    return left->index() < right->index();
+  }
+};
+
+}  // namespace
+
+bool TextFormat::Printer::PrintAny(const Message& message,
+                                   TextGenerator& generator) const {
+  const FieldDescriptor* type_url_field;
+  const FieldDescriptor* value_field;
+  if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
+                                        &value_field)) {
+    return false;
+  }
+
+  const Reflection* reflection = message.GetReflection();
+
+  // Extract the full type name from the type_url field.
+  const string& type_url = reflection->GetString(message, type_url_field);
+  string full_type_name;
+  if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
+    return false;
+  }
+
+  // Print the "value" in text.
+  const google::protobuf::Descriptor* value_descriptor =
+      message.GetDescriptor()->file()->pool()->FindMessageTypeByName(
+          full_type_name);
+  if (value_descriptor == NULL) {
+    GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found";
+    return false;
+  }
+  DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> value_message(
+      factory.GetPrototype(value_descriptor)->New());
+  string serialized_value = reflection->GetString(message, value_field);
+  if (!value_message->ParseFromString(serialized_value)) {
+    GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents";
+    return false;
+  }
+  generator.Print(StrCat("[", type_url, "]"));
+  const FieldValuePrinter* printer = FindWithDefault(
+      custom_printers_, value_field, default_field_value_printer_.get());
+  generator.Print(
+      printer->PrintMessageStart(message, -1, 0, single_line_mode_));
+  generator.Indent();
+  Print(*value_message, generator);
+  generator.Outdent();
+  generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_));
+  return true;
+}
+
+void TextFormat::Printer::Print(const Message& message,
+                                TextGenerator& generator) const {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = message.GetReflection();
+  if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
+      PrintAny(message, generator)) {
+    return;
+  }
+  vector<const FieldDescriptor*> fields;
+  reflection->ListFields(message, &fields);
+  if (print_message_fields_in_index_order_) {
+    std::sort(fields.begin(), fields.end(), FieldIndexSorter());
+  }
+  for (int i = 0; i < fields.size(); i++) {
+    PrintField(message, reflection, fields[i], generator);
+  }
+  if (!hide_unknown_fields_) {
+    PrintUnknownFields(reflection->GetUnknownFields(message), generator);
+  }
+}
+
+void TextFormat::Printer::PrintFieldValueToString(
+    const Message& message,
+    const FieldDescriptor* field,
+    int index,
+    string* output) const {
+
+  GOOGLE_DCHECK(output) << "output specified is NULL";
+
+  output->clear();
+  io::StringOutputStream output_stream(output);
+  TextGenerator generator(&output_stream, initial_indent_level_);
+
+  PrintFieldValue(message, message.GetReflection(), field, index, generator);
+}
+
+class MapEntryMessageComparator {
+ public:
+  explicit MapEntryMessageComparator(const Descriptor* descriptor)
+      : field_(descriptor->field(0)) {}
+
+  bool operator()(const Message* a, const Message* b) {
+    const Reflection* reflection = a->GetReflection();
+    switch (field_->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_BOOL: {
+          bool first = reflection->GetBool(*a, field_);
+          bool second = reflection->GetBool(*b, field_);
+          return first < second;
+      }
+      case FieldDescriptor::CPPTYPE_INT32: {
+          int32 first = reflection->GetInt32(*a, field_);
+          int32 second = reflection->GetInt32(*b, field_);
+          return first < second;
+      }
+      case FieldDescriptor::CPPTYPE_INT64: {
+          int64 first = reflection->GetInt64(*a, field_);
+          int64 second = reflection->GetInt64(*b, field_);
+          return first < second;
+      }
+      case FieldDescriptor::CPPTYPE_UINT32: {
+          uint32 first = reflection->GetUInt32(*a, field_);
+          uint32 second = reflection->GetUInt32(*b, field_);
+          return first < second;
+      }
+      case FieldDescriptor::CPPTYPE_UINT64: {
+          uint64 first = reflection->GetUInt64(*a, field_);
+          uint64 second = reflection->GetUInt64(*b, field_);
+          return first < second;
+      }
+      case FieldDescriptor::CPPTYPE_STRING: {
+          string first = reflection->GetString(*a, field_);
+          string second = reflection->GetString(*b, field_);
+          return first < second;
+      }
+      default:
+        GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
+        return true;
+    }
+  }
+
+ private:
+  const FieldDescriptor* field_;
+};
+
+void TextFormat::Printer::PrintField(const Message& message,
+                                     const Reflection* reflection,
+                                     const FieldDescriptor* field,
+                                     TextGenerator& generator) const {
+  if (use_short_repeated_primitives_ &&
+      field->is_repeated() &&
+      field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
+      field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    PrintShortRepeatedField(message, reflection, field, generator);
+    return;
+  }
+
+  int count = 0;
+
+  if (field->is_repeated()) {
+    count = reflection->FieldSize(message, field);
+  } else if (reflection->HasField(message, field)) {
+    count = 1;
+  }
+
+  std::vector<const Message*> sorted_map_field;
+  if (field->is_map()) {
+    const RepeatedPtrField<Message>& map_field =
+        reflection->GetRepeatedPtrField<Message>(message, field);
+    for (RepeatedPtrField<Message>::const_pointer_iterator it =
+             map_field.pointer_begin();
+         it != map_field.pointer_end(); ++it) {
+      sorted_map_field.push_back(*it);
+    }
+
+    MapEntryMessageComparator comparator(field->message_type());
+    std::stable_sort(sorted_map_field.begin(), sorted_map_field.end(),
+                     comparator);
+  }
+
+  for (int j = 0; j < count; ++j) {
+    const int field_index = field->is_repeated() ? j : -1;
+
+    PrintFieldName(message, reflection, field, generator);
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      const FieldValuePrinter* printer = FindWithDefault(
+          custom_printers_, field, default_field_value_printer_.get());
+      const Message& sub_message =
+          field->is_repeated()
+              ? (field->is_map()
+                     ? *sorted_map_field[j]
+                     : reflection->GetRepeatedMessage(message, field, j))
+              : reflection->GetMessage(message, field);
+      generator.Print(
+          printer->PrintMessageStart(
+              sub_message, field_index, count, single_line_mode_));
+      generator.Indent();
+      Print(sub_message, generator);
+      generator.Outdent();
+      generator.Print(
+          printer->PrintMessageEnd(
+              sub_message, field_index, count, single_line_mode_));
+    } else {
+      generator.Print(": ");
+      // Write the field value.
+      PrintFieldValue(message, reflection, field, field_index, generator);
+      if (single_line_mode_) {
+        generator.Print(" ");
+      } else {
+        generator.Print("\n");
+      }
+    }
+  }
+}
+
+void TextFormat::Printer::PrintShortRepeatedField(
+    const Message& message,
+    const Reflection* reflection,
+    const FieldDescriptor* field,
+    TextGenerator& generator) const {
+  // Print primitive repeated field in short form.
+  PrintFieldName(message, reflection, field, generator);
+
+  int size = reflection->FieldSize(message, field);
+  generator.Print(": [");
+  for (int i = 0; i < size; i++) {
+    if (i > 0) generator.Print(", ");
+    PrintFieldValue(message, reflection, field, i, generator);
+  }
+  if (single_line_mode_) {
+    generator.Print("] ");
+  } else {
+    generator.Print("]\n");
+  }
+}
+
+void TextFormat::Printer::PrintFieldName(const Message& message,
+                                         const Reflection* reflection,
+                                         const FieldDescriptor* field,
+                                         TextGenerator& generator) const {
+  // if use_field_number_ is true, prints field number instead
+  // of field name.
+  if (use_field_number_) {
+    generator.Print(SimpleItoa(field->number()));
+    return;
+  }
+
+  const FieldValuePrinter* printer = FindWithDefault(
+      custom_printers_, field, default_field_value_printer_.get());
+  generator.Print(printer->PrintFieldName(message, reflection, field));
+}
+
+void TextFormat::Printer::PrintFieldValue(
+    const Message& message,
+    const Reflection* reflection,
+    const FieldDescriptor* field,
+    int index,
+    TextGenerator& generator) const {
+  GOOGLE_DCHECK(field->is_repeated() || (index == -1))
+      << "Index must be -1 for non-repeated fields";
+
+  const FieldValuePrinter* printer
+      = FindWithDefault(custom_printers_, field,
+                        default_field_value_printer_.get());
+
+  switch (field->cpp_type()) {
+#define OUTPUT_FIELD(CPPTYPE, METHOD)                                   \
+    case FieldDescriptor::CPPTYPE_##CPPTYPE:                            \
+      generator.Print(printer->Print##METHOD(field->is_repeated()       \
+               ? reflection->GetRepeated##METHOD(message, field, index) \
+               : reflection->Get##METHOD(message, field)));             \
+        break
+
+    OUTPUT_FIELD( INT32,  Int32);
+    OUTPUT_FIELD( INT64,  Int64);
+    OUTPUT_FIELD(UINT32, UInt32);
+    OUTPUT_FIELD(UINT64, UInt64);
+    OUTPUT_FIELD( FLOAT,  Float);
+    OUTPUT_FIELD(DOUBLE, Double);
+    OUTPUT_FIELD(  BOOL,   Bool);
+#undef OUTPUT_FIELD
+
+    case FieldDescriptor::CPPTYPE_STRING: {
+      string scratch;
+      const string& value = field->is_repeated()
+          ? reflection->GetRepeatedStringReference(
+              message, field, index, &scratch)
+          : reflection->GetStringReference(message, field, &scratch);
+      const string* value_to_print = &value;
+      string truncated_value;
+      if (truncate_string_field_longer_than_ > 0 &&
+          truncate_string_field_longer_than_ < value.size()) {
+        truncated_value = value.substr(0, truncate_string_field_longer_than_) +
+                          "...<truncated>...";
+        value_to_print = &truncated_value;
+      }
+      if (field->type() == FieldDescriptor::TYPE_STRING) {
+        generator.Print(printer->PrintString(*value_to_print));
+      } else {
+        GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES);
+        generator.Print(printer->PrintBytes(*value_to_print));
+      }
+      break;
+    }
+
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      int enum_value = field->is_repeated()
+          ? reflection->GetRepeatedEnumValue(message, field, index)
+          : reflection->GetEnumValue(message, field);
+      const EnumValueDescriptor* enum_desc =
+          field->enum_type()->FindValueByNumber(enum_value);
+      if (enum_desc != NULL) {
+        generator.Print(printer->PrintEnum(enum_value, enum_desc->name()));
+      } else {
+        // Ordinarily, enum_desc should not be null, because proto2 has the
+        // invariant that set enum field values must be in-range, but with the
+        // new integer-based API for enums (or the RepeatedField<int> loophole),
+        // it is possible for the user to force an unknown integer value.  So we
+        // simply use the integer value itself as the enum value name in this
+        // case.
+        generator.Print(printer->PrintEnum(enum_value,
+                                           StringPrintf("%d", enum_value)));
+      }
+      break;
+    }
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      Print(field->is_repeated()
+            ? reflection->GetRepeatedMessage(message, field, index)
+            : reflection->GetMessage(message, field),
+            generator);
+      break;
+  }
+}
+
+/* static */ bool TextFormat::Print(const Message& message,
+                                    io::ZeroCopyOutputStream* output) {
+  return Printer().Print(message, output);
+}
+
+/* static */ bool TextFormat::PrintUnknownFields(
+    const UnknownFieldSet& unknown_fields,
+    io::ZeroCopyOutputStream* output) {
+  return Printer().PrintUnknownFields(unknown_fields, output);
+}
+
+/* static */ bool TextFormat::PrintToString(
+    const Message& message, string* output) {
+  return Printer().PrintToString(message, output);
+}
+
+/* static */ bool TextFormat::PrintUnknownFieldsToString(
+    const UnknownFieldSet& unknown_fields, string* output) {
+  return Printer().PrintUnknownFieldsToString(unknown_fields, output);
+}
+
+/* static */ void TextFormat::PrintFieldValueToString(
+    const Message& message,
+    const FieldDescriptor* field,
+    int index,
+    string* output) {
+  return Printer().PrintFieldValueToString(message, field, index, output);
+}
+
+/* static */ bool TextFormat::ParseFieldValueFromString(
+    const string& input,
+    const FieldDescriptor* field,
+    Message* message) {
+  return Parser().ParseFieldValueFromString(input, field, message);
+}
+
+// Prints an integer as hex with a fixed number of digits dependent on the
+// integer type.
+template<typename IntType>
+static string PaddedHex(IntType value) {
+  string result;
+  result.reserve(sizeof(value) * 2);
+  for (int i = sizeof(value) * 2 - 1; i >= 0; i--) {
+    result.push_back(int_to_hex_digit(value >> (i*4) & 0x0F));
+  }
+  return result;
+}
+
+void TextFormat::Printer::PrintUnknownFields(
+    const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+    string field_number = SimpleItoa(field.number());
+
+    switch (field.type()) {
+      case UnknownField::TYPE_VARINT:
+        generator.Print(field_number);
+        generator.Print(": ");
+        generator.Print(SimpleItoa(field.varint()));
+        if (single_line_mode_) {
+          generator.Print(" ");
+        } else {
+          generator.Print("\n");
+        }
+        break;
+      case UnknownField::TYPE_FIXED32: {
+        generator.Print(field_number);
+        generator.Print(": 0x");
+        generator.Print(
+            StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
+        if (single_line_mode_) {
+          generator.Print(" ");
+        } else {
+          generator.Print("\n");
+        }
+        break;
+      }
+      case UnknownField::TYPE_FIXED64: {
+        generator.Print(field_number);
+        generator.Print(": 0x");
+        generator.Print(
+            StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
+        if (single_line_mode_) {
+          generator.Print(" ");
+        } else {
+          generator.Print("\n");
+        }
+        break;
+      }
+      case UnknownField::TYPE_LENGTH_DELIMITED: {
+        generator.Print(field_number);
+        const string& value = field.length_delimited();
+        UnknownFieldSet embedded_unknown_fields;
+        if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
+          // This field is parseable as a Message.
+          // So it is probably an embedded message.
+          if (single_line_mode_) {
+            generator.Print(" { ");
+          } else {
+            generator.Print(" {\n");
+            generator.Indent();
+          }
+          PrintUnknownFields(embedded_unknown_fields, generator);
+          if (single_line_mode_) {
+            generator.Print("} ");
+          } else {
+            generator.Outdent();
+            generator.Print("}\n");
+          }
+        } else {
+          // This field is not parseable as a Message.
+          // So it is probably just a plain string.
+          string printed(": \"");
+          CEscapeAndAppend(value, &printed);
+          printed.append(single_line_mode_ ? "\" " : "\"\n");
+          generator.Print(printed);
+        }
+        break;
+      }
+      case UnknownField::TYPE_GROUP:
+        generator.Print(field_number);
+        if (single_line_mode_) {
+          generator.Print(" { ");
+        } else {
+          generator.Print(" {\n");
+          generator.Indent();
+        }
+        PrintUnknownFields(field.group(), generator);
+        if (single_line_mode_) {
+          generator.Print("} ");
+        } else {
+          generator.Outdent();
+          generator.Print("}\n");
+        }
+        break;
+    }
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/text_format.h b/src/third_party/protobuf-3/src/google/protobuf/text_format.h
new file mode 100644
index 0000000..ef3d4a8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/text_format.h
@@ -0,0 +1,517 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Utilities for printing and parsing protocol messages in a human-readable,
+// text-based format.
+
+#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
+#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
+
+#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+  class ErrorCollector;      // tokenizer.h
+}
+
+// This class implements protocol buffer text format.  Printing and parsing
+// protocol messages in text format is useful for debugging and human editing
+// of messages.
+//
+// This class is really a namespace that contains only static methods.
+class LIBPROTOBUF_EXPORT TextFormat {
+ public:
+  // Outputs a textual representation of the given message to the given
+  // output stream.
+  static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
+
+  // Print the fields in an UnknownFieldSet.  They are printed by tag number
+  // only.  Embedded messages are heuristically identified by attempting to
+  // parse them.
+  static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
+                                 io::ZeroCopyOutputStream* output);
+
+  // Like Print(), but outputs directly to a string.
+  static bool PrintToString(const Message& message, string* output);
+
+  // Like PrintUnknownFields(), but outputs directly to a string.
+  static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
+                                         string* output);
+
+  // Outputs a textual representation of the value of the field supplied on
+  // the message supplied. For non-repeated fields, an index of -1 must
+  // be supplied. Note that this method will print the default value for a
+  // field if it is not set.
+  static void PrintFieldValueToString(const Message& message,
+                                      const FieldDescriptor* field,
+                                      int index,
+                                      string* output);
+
+  // The default printer that converts scalar values from fields into
+  // their string representation.
+  // You can derive from this FieldValuePrinter if you want to have
+  // fields to be printed in a different way and register it at the
+  // Printer.
+  class LIBPROTOBUF_EXPORT FieldValuePrinter {
+   public:
+    FieldValuePrinter();
+    virtual ~FieldValuePrinter();
+    virtual string PrintBool(bool val) const;
+    virtual string PrintInt32(int32 val) const;
+    virtual string PrintUInt32(uint32 val) const;
+    virtual string PrintInt64(int64 val) const;
+    virtual string PrintUInt64(uint64 val) const;
+    virtual string PrintFloat(float val) const;
+    virtual string PrintDouble(double val) const;
+    virtual string PrintString(const string& val) const;
+    virtual string PrintBytes(const string& val) const;
+    virtual string PrintEnum(int32 val, const string& name) const;
+    virtual string PrintFieldName(const Message& message,
+                                  const Reflection* reflection,
+                                  const FieldDescriptor* field) const;
+    virtual string PrintMessageStart(const Message& message,
+                                     int field_index,
+                                     int field_count,
+                                     bool single_line_mode) const;
+    virtual string PrintMessageEnd(const Message& message,
+                                   int field_index,
+                                   int field_count,
+                                   bool single_line_mode) const;
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
+  };
+
+  // Class for those users which require more fine-grained control over how
+  // a protobuffer message is printed out.
+  class LIBPROTOBUF_EXPORT Printer {
+   public:
+    Printer();
+    ~Printer();
+
+    // Like TextFormat::Print
+    bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
+    // Like TextFormat::PrintUnknownFields
+    bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
+                            io::ZeroCopyOutputStream* output) const;
+    // Like TextFormat::PrintToString
+    bool PrintToString(const Message& message, string* output) const;
+    // Like TextFormat::PrintUnknownFieldsToString
+    bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
+                                    string* output) const;
+    // Like TextFormat::PrintFieldValueToString
+    void PrintFieldValueToString(const Message& message,
+                                 const FieldDescriptor* field,
+                                 int index,
+                                 string* output) const;
+
+    // Adjust the initial indent level of all output.  Each indent level is
+    // equal to two spaces.
+    void SetInitialIndentLevel(int indent_level) {
+      initial_indent_level_ = indent_level;
+    }
+
+    // If printing in single line mode, then the entire message will be output
+    // on a single line with no line breaks.
+    void SetSingleLineMode(bool single_line_mode) {
+      single_line_mode_ = single_line_mode;
+    }
+
+    bool IsInSingleLineMode() {
+      return single_line_mode_;
+    }
+
+    // If use_field_number is true, uses field number instead of field name.
+    void SetUseFieldNumber(bool use_field_number) {
+      use_field_number_ = use_field_number;
+    }
+
+    // Set true to print repeated primitives in a format like:
+    //   field_name: [1, 2, 3, 4]
+    // instead of printing each value on its own line.  Short format applies
+    // only to primitive values -- i.e. everything except strings and
+    // sub-messages/groups.
+    void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
+      use_short_repeated_primitives_ = use_short_repeated_primitives;
+    }
+
+    // Set true to output UTF-8 instead of ASCII.  The only difference
+    // is that bytes >= 0x80 in string fields will not be escaped,
+    // because they are assumed to be part of UTF-8 multi-byte
+    // sequences. This will change the default FieldValuePrinter.
+    void SetUseUtf8StringEscaping(bool as_utf8);
+
+    // Set the default FieldValuePrinter that is used for all fields that
+    // don't have a field-specific printer registered.
+    // Takes ownership of the printer.
+    void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer);
+
+    // Sets whether we want to hide unknown fields or not.
+    // Usually unknown fields are printed in a generic way that includes the
+    // tag number of the field instead of field name. However, sometimes it
+    // is useful to be able to print the message without unknown fields (e.g.
+    // for the python protobuf version to maintain consistency between its pure
+    // python and c++ implementations).
+    void SetHideUnknownFields(bool hide) {
+      hide_unknown_fields_ = hide;
+    }
+
+    // If print_message_fields_in_index_order is true, print fields of a proto
+    // message using the order defined in source code instead of the field
+    // number. By default, use the field number order.
+    void SetPrintMessageFieldsInIndexOrder(
+        bool print_message_fields_in_index_order) {
+      print_message_fields_in_index_order_ =
+          print_message_fields_in_index_order;
+    }
+
+    // If expand==true, expand google.protobuf.Any payloads. The output
+    // will be of form
+    //    [type_url] { <value_printed_in_text> }
+    //
+    // If expand==false, print Any using the default printer. The output will
+    // look like
+    //    type_url: "<type_url>"  value: "serialized_content"
+    void SetExpandAny(bool expand) {
+      expand_any_ = expand;
+    }
+
+    // If non-zero, we truncate all string fields that are  longer than this
+    // threshold.  This is useful when the proto message has very long strings,
+    // e.g., dump of encoded image file.
+    //
+    // NOTE(hfgong):  Setting a non-zero value breaks round-trip safe
+    // property of TextFormat::Printer.  That is, from the printed message, we
+    // cannot fully recover the original string field any more.
+    void SetTruncateStringFieldLongerThan(
+        const int64 truncate_string_field_longer_than) {
+      truncate_string_field_longer_than_ = truncate_string_field_longer_than;
+    }
+
+    // Register a custom field-specific FieldValuePrinter for fields
+    // with a particular FieldDescriptor.
+    // Returns "true" if the registration succeeded, or "false", if there is
+    // already a printer for that FieldDescriptor.
+    // Takes ownership of the printer on successful registration.
+    bool RegisterFieldValuePrinter(const FieldDescriptor* field,
+                                   const FieldValuePrinter* printer);
+
+   private:
+    // Forward declaration of an internal class used to print the text
+    // output to the OutputStream (see text_format.cc for implementation).
+    class TextGenerator;
+
+    // Internal Print method, used for writing to the OutputStream via
+    // the TextGenerator class.
+    void Print(const Message& message,
+               TextGenerator& generator) const;
+
+    // Print a single field.
+    void PrintField(const Message& message,
+                    const Reflection* reflection,
+                    const FieldDescriptor* field,
+                    TextGenerator& generator) const;
+
+    // Print a repeated primitive field in short form.
+    void PrintShortRepeatedField(const Message& message,
+                                 const Reflection* reflection,
+                                 const FieldDescriptor* field,
+                                 TextGenerator& generator) const;
+
+    // Print the name of a field -- i.e. everything that comes before the
+    // ':' for a single name/value pair.
+    void PrintFieldName(const Message& message,
+                        const Reflection* reflection,
+                        const FieldDescriptor* field,
+                        TextGenerator& generator) const;
+
+    // Outputs a textual representation of the value of the field supplied on
+    // the message supplied or the default value if not set.
+    void PrintFieldValue(const Message& message,
+                         const Reflection* reflection,
+                         const FieldDescriptor* field,
+                         int index,
+                         TextGenerator& generator) const;
+
+    // Print the fields in an UnknownFieldSet.  They are printed by tag number
+    // only.  Embedded messages are heuristically identified by attempting to
+    // parse them.
+    void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
+                            TextGenerator& generator) const;
+
+    bool PrintAny(const Message& message, TextGenerator& generator) const;
+
+    int initial_indent_level_;
+
+    bool single_line_mode_;
+
+    bool use_field_number_;
+
+    bool use_short_repeated_primitives_;
+
+    bool hide_unknown_fields_;
+
+    bool print_message_fields_in_index_order_;
+
+    bool expand_any_;
+
+    int64 truncate_string_field_longer_than_;
+
+    google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
+    typedef map<const FieldDescriptor*,
+                const FieldValuePrinter*> CustomPrinterMap;
+    CustomPrinterMap custom_printers_;
+  };
+
+  // Parses a text-format protocol message from the given input stream to
+  // the given message object. This function parses the human-readable format
+  // written by Print(). Returns true on success. The message is cleared first,
+  // even if the function fails -- See Merge() to avoid this behavior.
+  //
+  // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
+  //
+  // One use for this function is parsing handwritten strings in test code.
+  // Another use is to parse the output from google::protobuf::Message::DebugString()
+  // (or ShortDebugString()), because these functions output using
+  // google::protobuf::TextFormat::Print().
+  //
+  // If you would like to read a protocol buffer serialized in the
+  // (non-human-readable) binary wire format, see
+  // google::protobuf::MessageLite::ParseFromString().
+  static bool Parse(io::ZeroCopyInputStream* input, Message* output);
+  // Like Parse(), but reads directly from a string.
+  static bool ParseFromString(const string& input, Message* output);
+
+  // Like Parse(), but the data is merged into the given message, as if
+  // using Message::MergeFrom().
+  static bool Merge(io::ZeroCopyInputStream* input, Message* output);
+  // Like Merge(), but reads directly from a string.
+  static bool MergeFromString(const string& input, Message* output);
+
+  // Parse the given text as a single field value and store it into the
+  // given field of the given message. If the field is a repeated field,
+  // the new value will be added to the end
+  static bool ParseFieldValueFromString(const string& input,
+                                        const FieldDescriptor* field,
+                                        Message* message);
+
+  // Interface that TextFormat::Parser can use to find extensions.
+  // This class may be extended in the future to find more information
+  // like fields, etc.
+  class LIBPROTOBUF_EXPORT Finder {
+   public:
+    virtual ~Finder();
+
+    // Try to find an extension of *message by fully-qualified field
+    // name.  Returns NULL if no extension is known for this name or number.
+    virtual const FieldDescriptor* FindExtension(
+        Message* message,
+        const string& name) const = 0;
+  };
+
+  // A location in the parsed text.
+  struct ParseLocation {
+    int line;
+    int column;
+
+    ParseLocation() : line(-1), column(-1) {}
+    ParseLocation(int line_param, int column_param)
+        : line(line_param), column(column_param) {}
+  };
+
+  // Data structure which is populated with the locations of each field
+  // value parsed from the text.
+  class LIBPROTOBUF_EXPORT ParseInfoTree {
+   public:
+    ParseInfoTree();
+    ~ParseInfoTree();
+
+    // Returns the parse location for index-th value of the field in the parsed
+    // text. If none exists, returns a location with line = -1. Index should be
+    // -1 for not-repeated fields.
+    ParseLocation GetLocation(const FieldDescriptor* field, int index) const;
+
+    // Returns the parse info tree for the given field, which must be a message
+    // type. The nested information tree is owned by the root tree and will be
+    // deleted when it is deleted.
+    ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
+                                    int index) const;
+
+   private:
+    // Allow the text format parser to record information into the tree.
+    friend class TextFormat;
+
+    // Records the starting location of a single value for a field.
+    void RecordLocation(const FieldDescriptor* field, ParseLocation location);
+
+    // Create and records a nested tree for a nested message field.
+    ParseInfoTree* CreateNested(const FieldDescriptor* field);
+
+    // Defines the map from the index-th field descriptor to its parse location.
+    typedef map<const FieldDescriptor*, vector<ParseLocation> > LocationMap;
+
+    // Defines the map from the index-th field descriptor to the nested parse
+    // info tree.
+    typedef map<const FieldDescriptor*, vector<ParseInfoTree*> > NestedMap;
+
+    LocationMap locations_;
+    NestedMap nested_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree);
+  };
+
+  // For more control over parsing, use this class.
+  class LIBPROTOBUF_EXPORT Parser {
+   public:
+    Parser();
+    ~Parser();
+
+    // Like TextFormat::Parse().
+    bool Parse(io::ZeroCopyInputStream* input, Message* output);
+    // Like TextFormat::ParseFromString().
+    bool ParseFromString(const string& input, Message* output);
+    // Like TextFormat::Merge().
+    bool Merge(io::ZeroCopyInputStream* input, Message* output);
+    // Like TextFormat::MergeFromString().
+    bool MergeFromString(const string& input, Message* output);
+
+    // Set where to report parse errors.  If NULL (the default), errors will
+    // be printed to stderr.
+    void RecordErrorsTo(io::ErrorCollector* error_collector) {
+      error_collector_ = error_collector;
+    }
+
+    // Set how parser finds extensions.  If NULL (the default), the
+    // parser will use the standard Reflection object associated with
+    // the message being parsed.
+    void SetFinder(Finder* finder) {
+      finder_ = finder;
+    }
+
+    // Sets where location information about the parse will be written. If NULL
+    // (the default), then no location will be written.
+    void WriteLocationsTo(ParseInfoTree* tree) {
+      parse_info_tree_ = tree;
+    }
+
+    // Normally parsing fails if, after parsing, output->IsInitialized()
+    // returns false.  Call AllowPartialMessage(true) to skip this check.
+    void AllowPartialMessage(bool allow) {
+      allow_partial_ = allow;
+    }
+
+    // Allow field names to be matched case-insensitively.
+    // This is not advisable if there are fields that only differ in case, or
+    // if you want to enforce writing in the canonical form.
+    // This is 'false' by default.
+    void AllowCaseInsensitiveField(bool allow) {
+      allow_case_insensitive_field_ = allow;
+    }
+
+    // Like TextFormat::ParseFieldValueFromString
+    bool ParseFieldValueFromString(const string& input,
+                                   const FieldDescriptor* field,
+                                   Message* output);
+
+
+    void AllowFieldNumber(bool allow) {
+      allow_field_number_ = allow;
+    }
+
+   private:
+    // Forward declaration of an internal class used to parse text
+    // representations (see text_format.cc for implementation).
+    class ParserImpl;
+
+    // Like TextFormat::Merge().  The provided implementation is used
+    // to do the parsing.
+    bool MergeUsingImpl(io::ZeroCopyInputStream* input,
+                        Message* output,
+                        ParserImpl* parser_impl);
+
+    io::ErrorCollector* error_collector_;
+    Finder* finder_;
+    ParseInfoTree* parse_info_tree_;
+    bool allow_partial_;
+    bool allow_case_insensitive_field_;
+    bool allow_unknown_field_;
+    bool allow_unknown_enum_;
+    bool allow_field_number_;
+    bool allow_relaxed_whitespace_;
+    bool allow_singular_overwrites_;
+  };
+
+
+ private:
+  // Hack: ParseInfoTree declares TextFormat as a friend which should extend
+  // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some
+  // old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide
+  // helpers for ParserImpl to call methods of ParseInfoTree.
+  static inline void RecordLocation(ParseInfoTree* info_tree,
+                                    const FieldDescriptor* field,
+                                    ParseLocation location);
+  static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
+                                            const FieldDescriptor* field);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
+};
+
+inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
+                                       const FieldDescriptor* field,
+                                       ParseLocation location) {
+  info_tree->RecordLocation(field, location);
+}
+
+
+inline TextFormat::ParseInfoTree* TextFormat::CreateNested(
+    ParseInfoTree* info_tree, const FieldDescriptor* field) {
+  return info_tree->CreateNested(field);
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_TEXT_FORMAT_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/text_format_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/text_format_unittest.cc
new file mode 100644
index 0000000..58aa3f8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/text_format_unittest.cc
@@ -0,0 +1,1484 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/text_format.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <limits>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+
+namespace google {
+namespace protobuf {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace text_format_unittest {
+
+// A basic string with different escapable characters for testing.
+const string kEscapeTestString =
+  "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+  "slashes \\ and  multiple   spaces";
+
+// A representation of the above string with all the characters escaped.
+const string kEscapeTestStringEscaped =
+  "\"\\\"A string with \\' characters \\n and \\r newlines "
+  "and \\t tabs and \\001 slashes \\\\ and  multiple   spaces\"";
+
+class TextFormatTest : public testing::Test {
+ public:
+  static void SetUpTestCase() {
+    GOOGLE_CHECK_OK(File::GetContents(
+        TestSourceDir() +
+            "/google/protobuf/"
+            "testdata/text_format_unittest_data_oneof_implemented.txt",
+        &static_proto_debug_string_, true));
+  }
+
+  TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {}
+
+ protected:
+  // Debug string read from text_format_unittest_data.txt.
+  const string proto_debug_string_;
+  unittest::TestAllTypes proto_;
+
+ private:
+  static string static_proto_debug_string_;
+};
+string TextFormatTest::static_proto_debug_string_;
+
+class TextFormatExtensionsTest : public testing::Test {
+ public:
+  static void SetUpTestCase() {
+    GOOGLE_CHECK_OK(File::GetContents(TestSourceDir() +
+                                   "/google/protobuf/testdata/"
+                                   "text_format_unittest_extensions_data.txt",
+                               &static_proto_debug_string_, true));
+  }
+
+  TextFormatExtensionsTest()
+      : proto_debug_string_(static_proto_debug_string_) {}
+
+ protected:
+  // Debug string read from text_format_unittest_data.txt.
+  const string proto_debug_string_;
+  unittest::TestAllExtensions proto_;
+
+ private:
+  static string static_proto_debug_string_;
+};
+string TextFormatExtensionsTest::static_proto_debug_string_;
+
+
+TEST_F(TextFormatTest, Basic) {
+  TestUtil::SetAllFields(&proto_);
+  EXPECT_EQ(proto_debug_string_, proto_.DebugString());
+}
+
+TEST_F(TextFormatExtensionsTest, Extensions) {
+  TestUtil::SetAllExtensions(&proto_);
+  EXPECT_EQ(proto_debug_string_, proto_.DebugString());
+}
+
+TEST_F(TextFormatTest, ShortDebugString) {
+  proto_.set_optional_int32(1);
+  proto_.set_optional_string("hello");
+  proto_.mutable_optional_nested_message()->set_bb(2);
+  proto_.mutable_optional_foreign_message();
+
+  EXPECT_EQ("optional_int32: 1 optional_string: \"hello\" "
+            "optional_nested_message { bb: 2 } "
+            "optional_foreign_message { }",
+            proto_.ShortDebugString());
+}
+
+TEST_F(TextFormatTest, ShortPrimitiveRepeateds) {
+  proto_.set_optional_int32(123);
+  proto_.add_repeated_int32(456);
+  proto_.add_repeated_int32(789);
+  proto_.add_repeated_string("foo");
+  proto_.add_repeated_string("bar");
+  proto_.add_repeated_nested_message()->set_bb(2);
+  proto_.add_repeated_nested_message()->set_bb(3);
+  proto_.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
+  proto_.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
+
+  TextFormat::Printer printer;
+  printer.SetUseShortRepeatedPrimitives(true);
+  string text;
+  printer.PrintToString(proto_, &text);
+
+  EXPECT_EQ("optional_int32: 123\n"
+            "repeated_int32: [456, 789]\n"
+            "repeated_string: \"foo\"\n"
+            "repeated_string: \"bar\"\n"
+            "repeated_nested_message {\n  bb: 2\n}\n"
+            "repeated_nested_message {\n  bb: 3\n}\n"
+            "repeated_nested_enum: [FOO, BAR]\n",
+            text);
+
+  // Try in single-line mode.
+  printer.SetSingleLineMode(true);
+  printer.PrintToString(proto_, &text);
+
+  EXPECT_EQ("optional_int32: 123 "
+            "repeated_int32: [456, 789] "
+            "repeated_string: \"foo\" "
+            "repeated_string: \"bar\" "
+            "repeated_nested_message { bb: 2 } "
+            "repeated_nested_message { bb: 3 } "
+            "repeated_nested_enum: [FOO, BAR] ",
+            text);
+}
+
+
+TEST_F(TextFormatTest, StringEscape) {
+  // Set the string value to test.
+  proto_.set_optional_string(kEscapeTestString);
+
+  // Get the DebugString from the proto.
+  string debug_string = proto_.DebugString();
+  string utf8_debug_string = proto_.Utf8DebugString();
+
+  // Hardcode a correct value to test against.
+  string correct_string = "optional_string: "
+      + kEscapeTestStringEscaped
+       + "\n";
+
+  // Compare.
+  EXPECT_EQ(correct_string, debug_string);
+  // UTF-8 string is the same as non-UTF-8 because
+  // the protocol buffer contains no UTF-8 text.
+  EXPECT_EQ(correct_string, utf8_debug_string);
+
+  string expected_short_debug_string = "optional_string: "
+      + kEscapeTestStringEscaped;
+  EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString());
+}
+
+TEST_F(TextFormatTest, Utf8DebugString) {
+  // Set the string value to test.
+  proto_.set_optional_string("\350\260\267\346\255\214");
+  proto_.set_optional_bytes("\350\260\267\346\255\214");
+
+  // Get the DebugString from the proto.
+  string debug_string = proto_.DebugString();
+  string utf8_debug_string = proto_.Utf8DebugString();
+
+  // Hardcode a correct value to test against.
+  string correct_utf8_string =
+      "optional_string: "
+      "\"\350\260\267\346\255\214\""
+      "\n"
+      "optional_bytes: "
+      "\"\\350\\260\\267\\346\\255\\214\""
+      "\n";
+  string correct_string =
+      "optional_string: "
+      "\"\\350\\260\\267\\346\\255\\214\""
+      "\n"
+      "optional_bytes: "
+      "\"\\350\\260\\267\\346\\255\\214\""
+      "\n";
+
+  // Compare.
+  EXPECT_EQ(correct_utf8_string, utf8_debug_string);
+  EXPECT_EQ(correct_string, debug_string);
+}
+
+TEST_F(TextFormatTest, PrintUnknownFields) {
+  // Test printing of unknown fields in a message.
+
+  unittest::TestEmptyMessage message;
+  UnknownFieldSet* unknown_fields = message.mutable_unknown_fields();
+
+  unknown_fields->AddVarint(5, 1);
+  unknown_fields->AddFixed32(5, 2);
+  unknown_fields->AddFixed64(5, 3);
+  unknown_fields->AddLengthDelimited(5, "4");
+  unknown_fields->AddGroup(5)->AddVarint(10, 5);
+
+  unknown_fields->AddVarint(8, 1);
+  unknown_fields->AddVarint(8, 2);
+  unknown_fields->AddVarint(8, 3);
+
+  EXPECT_EQ(
+    "5: 1\n"
+    "5: 0x00000002\n"
+    "5: 0x0000000000000003\n"
+    "5: \"4\"\n"
+    "5 {\n"
+    "  10: 5\n"
+    "}\n"
+    "8: 1\n"
+    "8: 2\n"
+    "8: 3\n",
+    message.DebugString());
+}
+
+TEST_F(TextFormatTest, PrintUnknownFieldsHidden) {
+  // Test printing of unknown fields in a message when suppressed.
+
+  unittest::OneString message;
+  message.set_data("data");
+  UnknownFieldSet* unknown_fields = message.mutable_unknown_fields();
+
+  unknown_fields->AddVarint(5, 1);
+  unknown_fields->AddFixed32(5, 2);
+  unknown_fields->AddFixed64(5, 3);
+  unknown_fields->AddLengthDelimited(5, "4");
+  unknown_fields->AddGroup(5)->AddVarint(10, 5);
+
+  unknown_fields->AddVarint(8, 1);
+  unknown_fields->AddVarint(8, 2);
+  unknown_fields->AddVarint(8, 3);
+
+  TextFormat::Printer printer;
+  printer.SetHideUnknownFields(true);
+  string output;
+  printer.PrintToString(message, &output);
+
+  EXPECT_EQ("data: \"data\"\n", output);
+}
+
+TEST_F(TextFormatTest, PrintUnknownMessage) {
+  // Test heuristic printing of messages in an UnknownFieldSet.
+
+  protobuf_unittest::TestAllTypes message;
+
+  // Cases which should not be interpreted as sub-messages.
+
+  // 'a' is a valid FIXED64 tag, so for the string to be parseable as a message
+  // it should be followed by 8 bytes.  Since this string only has two
+  // subsequent bytes, it should be treated as a string.
+  message.add_repeated_string("abc");
+
+  // 'd' happens to be a valid ENDGROUP tag.  So,
+  // UnknownFieldSet::MergeFromCodedStream() will successfully parse "def", but
+  // the ConsumedEntireMessage() check should fail.
+  message.add_repeated_string("def");
+
+  // A zero-length string should never be interpreted as a message even though
+  // it is technically valid as one.
+  message.add_repeated_string("");
+
+  // Case which should be interpreted as a sub-message.
+
+  // An actual nested message with content should always be interpreted as a
+  // nested message.
+  message.add_repeated_nested_message()->set_bb(123);
+
+  string data;
+  message.SerializeToString(&data);
+
+  string text;
+  UnknownFieldSet unknown_fields;
+  EXPECT_TRUE(unknown_fields.ParseFromString(data));
+  EXPECT_TRUE(TextFormat::PrintUnknownFieldsToString(unknown_fields, &text));
+  EXPECT_EQ(
+    "44: \"abc\"\n"
+    "44: \"def\"\n"
+    "44: \"\"\n"
+    "48 {\n"
+    "  1: 123\n"
+    "}\n",
+    text);
+}
+
+TEST_F(TextFormatTest, PrintMessageWithIndent) {
+  // Test adding an initial indent to printing.
+
+  protobuf_unittest::TestAllTypes message;
+
+  message.add_repeated_string("abc");
+  message.add_repeated_string("def");
+  message.add_repeated_nested_message()->set_bb(123);
+
+  string text;
+  TextFormat::Printer printer;
+  printer.SetInitialIndentLevel(1);
+  EXPECT_TRUE(printer.PrintToString(message, &text));
+  EXPECT_EQ(
+    "  repeated_string: \"abc\"\n"
+    "  repeated_string: \"def\"\n"
+    "  repeated_nested_message {\n"
+    "    bb: 123\n"
+    "  }\n",
+    text);
+}
+
+TEST_F(TextFormatTest, PrintMessageSingleLine) {
+  // Test printing a message on a single line.
+
+  protobuf_unittest::TestAllTypes message;
+
+  message.add_repeated_string("abc");
+  message.add_repeated_string("def");
+  message.add_repeated_nested_message()->set_bb(123);
+
+  string text;
+  TextFormat::Printer printer;
+  printer.SetInitialIndentLevel(1);
+  printer.SetSingleLineMode(true);
+  EXPECT_TRUE(printer.PrintToString(message, &text));
+  EXPECT_EQ(
+    "  repeated_string: \"abc\" repeated_string: \"def\" "
+    "repeated_nested_message { bb: 123 } ",
+    text);
+}
+
+TEST_F(TextFormatTest, PrintBufferTooSmall) {
+  // Test printing a message to a buffer that is too small.
+
+  protobuf_unittest::TestAllTypes message;
+
+  message.add_repeated_string("abc");
+  message.add_repeated_string("def");
+
+  char buffer[1] = "";
+  io::ArrayOutputStream output_stream(buffer, 1);
+  EXPECT_FALSE(TextFormat::Print(message, &output_stream));
+  EXPECT_EQ(buffer[0], 'r');
+  EXPECT_EQ(output_stream.ByteCount(), 1);
+}
+
+// A printer that appends 'u' to all unsigned int32.
+class CustomUInt32FieldValuePrinter : public TextFormat::FieldValuePrinter {
+ public:
+  virtual string PrintUInt32(uint32 val) const {
+    return StrCat(FieldValuePrinter::PrintUInt32(val), "u");
+  }
+};
+
+TEST_F(TextFormatTest, DefaultCustomFieldPrinter) {
+  protobuf_unittest::TestAllTypes message;
+
+  message.set_optional_uint32(42);
+  message.add_repeated_uint32(1);
+  message.add_repeated_uint32(2);
+  message.add_repeated_uint32(3);
+
+  TextFormat::Printer printer;
+  printer.SetDefaultFieldValuePrinter(new CustomUInt32FieldValuePrinter());
+  // Let's see if that works well together with the repeated primitives:
+  printer.SetUseShortRepeatedPrimitives(true);
+  string text;
+  printer.PrintToString(message, &text);
+  EXPECT_EQ("optional_uint32: 42u\nrepeated_uint32: [1u, 2u, 3u]\n", text);
+}
+
+class CustomInt32FieldValuePrinter : public TextFormat::FieldValuePrinter {
+ public:
+  virtual string PrintInt32(int32 val) const {
+    return StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")");
+  }
+};
+
+TEST_F(TextFormatTest, FieldSpecificCustomPrinter) {
+  protobuf_unittest::TestAllTypes message;
+
+  message.set_optional_int32(42);  // This will be handled by our Printer.
+  message.add_repeated_int32(42);  // This will be printed as number.
+
+  TextFormat::Printer printer;
+  EXPECT_TRUE(printer.RegisterFieldValuePrinter(
+      message.GetDescriptor()->FindFieldByName("optional_int32"),
+      new CustomInt32FieldValuePrinter()));
+  string text;
+  printer.PrintToString(message, &text);
+  EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text);
+}
+
+TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) {
+  protobuf_unittest::TestAllTypes message;
+  TextFormat::Printer printer;
+  // NULL printer.
+  EXPECT_FALSE(printer.RegisterFieldValuePrinter(
+      message.GetDescriptor()->FindFieldByName("optional_int32"),
+      NULL));
+  // Because registration fails, the ownership of this printer is never taken.
+  TextFormat::FieldValuePrinter my_field_printer;
+  // NULL field
+  EXPECT_FALSE(printer.RegisterFieldValuePrinter(NULL, &my_field_printer));
+}
+
+class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter {
+ public:
+  virtual string PrintInt32(int32 v) const {
+    return StrCat(FieldValuePrinter::PrintInt32(v), "  # x", strings::Hex(v));
+  }
+
+  virtual string PrintMessageStart(const Message& message,
+                                   int field_index,
+                                   int field_count,
+                                   bool single_line_mode) const {
+    if (single_line_mode) {
+      return " { ";
+    }
+    return StrCat(
+        " {  # ", message.GetDescriptor()->name(), ": ", field_index, "\n");
+  }
+};
+
+TEST_F(TextFormatTest, CustomPrinterForComments) {
+  protobuf_unittest::TestAllTypes message;
+  message.mutable_optional_nested_message();
+  message.mutable_optional_import_message()->set_d(42);
+  message.add_repeated_nested_message();
+  message.add_repeated_nested_message();
+  message.add_repeated_import_message()->set_d(43);
+  message.add_repeated_import_message()->set_d(44);
+  TextFormat::Printer printer;
+  CustomMessageFieldValuePrinter my_field_printer;
+  printer.SetDefaultFieldValuePrinter(new CustomMessageFieldValuePrinter());
+  string text;
+  printer.PrintToString(message, &text);
+  EXPECT_EQ(
+      "optional_nested_message {  # NestedMessage: -1\n"
+      "}\n"
+      "optional_import_message {  # ImportMessage: -1\n"
+      "  d: 42  # x2a\n"
+      "}\n"
+      "repeated_nested_message {  # NestedMessage: 0\n"
+      "}\n"
+      "repeated_nested_message {  # NestedMessage: 1\n"
+      "}\n"
+      "repeated_import_message {  # ImportMessage: 0\n"
+      "  d: 43  # x2b\n"
+      "}\n"
+      "repeated_import_message {  # ImportMessage: 1\n"
+      "  d: 44  # x2c\n"
+      "}\n",
+      text);
+}
+
+class CustomMultilineCommentPrinter : public TextFormat::FieldValuePrinter {
+ public:
+  virtual string PrintMessageStart(const Message& message,
+                                   int field_index,
+                                   int field_count,
+                                   bool single_line_comment) const {
+    return StrCat(" {  # 1\n", "  # 2\n");
+  }
+};
+
+TEST_F(TextFormatTest, CustomPrinterForMultilineComments) {
+  protobuf_unittest::TestAllTypes message;
+  message.mutable_optional_nested_message();
+  message.mutable_optional_import_message()->set_d(42);
+  TextFormat::Printer printer;
+  CustomMessageFieldValuePrinter my_field_printer;
+  printer.SetDefaultFieldValuePrinter(new CustomMultilineCommentPrinter());
+  string text;
+  printer.PrintToString(message, &text);
+  EXPECT_EQ(
+      "optional_nested_message {  # 1\n"
+      "  # 2\n"
+      "}\n"
+      "optional_import_message {  # 1\n"
+      "  # 2\n"
+      "  d: 42\n"
+      "}\n",
+      text);
+}
+
+TEST_F(TextFormatTest, ParseBasic) {
+  io::ArrayInputStream input_stream(proto_debug_string_.data(),
+                                    proto_debug_string_.size());
+  TextFormat::Parse(&input_stream, &proto_);
+  TestUtil::ExpectAllFieldsSet(proto_);
+}
+
+TEST_F(TextFormatExtensionsTest, ParseExtensions) {
+  io::ArrayInputStream input_stream(proto_debug_string_.data(),
+                                    proto_debug_string_.size());
+  TextFormat::Parse(&input_stream, &proto_);
+  TestUtil::ExpectAllExtensionsSet(proto_);
+}
+
+TEST_F(TextFormatTest, ParseEnumFieldFromNumber) {
+  // Create a parse string with a numerical value for an enum field.
+  string parse_string = strings::Substitute("optional_nested_enum: $0",
+                                            unittest::TestAllTypes::BAZ);
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+  EXPECT_TRUE(proto_.has_optional_nested_enum());
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum());
+}
+
+TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) {
+  ASSERT_LT(unittest::SPARSE_E, 0);
+  string parse_string = strings::Substitute("sparse_enum: $0",
+                                            unittest::SPARSE_E);
+  unittest::SparseEnumMessage proto;
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto));
+  EXPECT_TRUE(proto.has_sparse_enum());
+  EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum());
+}
+
+TEST_F(TextFormatTest, ParseStringEscape) {
+  // Create a parse string with escpaed characters in it.
+  string parse_string = "optional_string: "
+      + kEscapeTestStringEscaped
+      + "\n";
+
+  io::ArrayInputStream input_stream(parse_string.data(),
+                                    parse_string.size());
+  TextFormat::Parse(&input_stream, &proto_);
+
+  // Compare.
+  EXPECT_EQ(kEscapeTestString, proto_.optional_string());
+}
+
+TEST_F(TextFormatTest, ParseConcatenatedString) {
+  // Create a parse string with multiple parts on one line.
+  string parse_string = "optional_string: \"foo\" \"bar\"\n";
+
+  io::ArrayInputStream input_stream1(parse_string.data(),
+                                    parse_string.size());
+  TextFormat::Parse(&input_stream1, &proto_);
+
+  // Compare.
+  EXPECT_EQ("foobar", proto_.optional_string());
+
+  // Create a parse string with multiple parts on separate lines.
+  parse_string = "optional_string: \"foo\"\n"
+                 "\"bar\"\n";
+
+  io::ArrayInputStream input_stream2(parse_string.data(),
+                                    parse_string.size());
+  TextFormat::Parse(&input_stream2, &proto_);
+
+  // Compare.
+  EXPECT_EQ("foobar", proto_.optional_string());
+}
+
+TEST_F(TextFormatTest, ParseFloatWithSuffix) {
+  // Test that we can parse a floating-point value with 'f' appended to the
+  // end.  This is needed for backwards-compatibility with proto1.
+
+  // Have it parse a float with the 'f' suffix.
+  string parse_string = "optional_float: 1.0f\n";
+
+  io::ArrayInputStream input_stream(parse_string.data(),
+                                    parse_string.size());
+
+  TextFormat::Parse(&input_stream, &proto_);
+
+  // Compare.
+  EXPECT_EQ(1.0, proto_.optional_float());
+}
+
+TEST_F(TextFormatTest, ParseShortRepeatedForm) {
+  string parse_string =
+      // Mixed short-form and long-form are simply concatenated.
+      "repeated_int32: 1\n"
+      "repeated_int32: [456, 789]\n"
+      "repeated_nested_enum: [  FOO ,BAR, # comment\n"
+      "                         3]\n"
+      // Note that while the printer won't print repeated strings in short-form,
+      // the parser will accept them.
+      "repeated_string: [ \"foo\", 'bar' ]\n"
+      // Repeated message
+      "repeated_nested_message: [ { bb: 1 }, { bb : 2 }]\n"
+      // Repeated group
+      "RepeatedGroup [{ a: 3 },{ a: 4 }]\n";
+
+  ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+
+  ASSERT_EQ(3, proto_.repeated_int32_size());
+  EXPECT_EQ(1, proto_.repeated_int32(0));
+  EXPECT_EQ(456, proto_.repeated_int32(1));
+  EXPECT_EQ(789, proto_.repeated_int32(2));
+
+  ASSERT_EQ(3, proto_.repeated_nested_enum_size());
+  EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0));
+  EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1));
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2));
+
+  ASSERT_EQ(2, proto_.repeated_string_size());
+  EXPECT_EQ("foo", proto_.repeated_string(0));
+  EXPECT_EQ("bar", proto_.repeated_string(1));
+
+  ASSERT_EQ(2, proto_.repeated_nested_message_size());
+  EXPECT_EQ(1, proto_.repeated_nested_message(0).bb());
+  EXPECT_EQ(2, proto_.repeated_nested_message(1).bb());
+
+  ASSERT_EQ(2, proto_.repeatedgroup_size());
+  EXPECT_EQ(3, proto_.repeatedgroup(0).a());
+  EXPECT_EQ(4, proto_.repeatedgroup(1).a());
+}
+
+
+TEST_F(TextFormatTest, Comments) {
+  // Test that comments are ignored.
+
+  string parse_string = "optional_int32: 1  # a comment\n"
+                        "optional_int64: 2  # another comment";
+
+  io::ArrayInputStream input_stream(parse_string.data(),
+                                    parse_string.size());
+
+  TextFormat::Parse(&input_stream, &proto_);
+
+  // Compare.
+  EXPECT_EQ(1, proto_.optional_int32());
+  EXPECT_EQ(2, proto_.optional_int64());
+}
+
+TEST_F(TextFormatTest, OptionalColon) {
+  // Test that we can place a ':' after the field name of a nested message,
+  // even though we don't have to.
+
+  string parse_string = "optional_nested_message: { bb: 1}\n";
+
+  io::ArrayInputStream input_stream(parse_string.data(),
+                                    parse_string.size());
+
+  TextFormat::Parse(&input_stream, &proto_);
+
+  // Compare.
+  EXPECT_TRUE(proto_.has_optional_nested_message());
+  EXPECT_EQ(1, proto_.optional_nested_message().bb());
+}
+
+// Some platforms (e.g. Windows) insist on padding the exponent to three
+// digits when one or two would be just fine.
+static string RemoveRedundantZeros(string text) {
+  text = StringReplace(text, "e+0", "e+", true);
+  text = StringReplace(text, "e-0", "e-", true);
+  return text;
+}
+
+TEST_F(TextFormatTest, PrintExotic) {
+  unittest::TestAllTypes message;
+
+  // Note:  In C, a negative integer literal is actually the unary negation
+  //   operator being applied to a positive integer literal, and
+  //   9223372036854775808 is outside the range of int64.  However, it is not
+  //   outside the range of uint64.  Confusingly, this means that everything
+  //   works if we make the literal unsigned, even though we are negating it.
+  message.add_repeated_int64(-GOOGLE_ULONGLONG(9223372036854775808));
+  message.add_repeated_uint64(GOOGLE_ULONGLONG(18446744073709551615));
+  message.add_repeated_double(123.456);
+  message.add_repeated_double(1.23e21);
+  message.add_repeated_double(1.23e-18);
+  message.add_repeated_double(std::numeric_limits<double>::infinity());
+  message.add_repeated_double(-std::numeric_limits<double>::infinity());
+  message.add_repeated_double(std::numeric_limits<double>::quiet_NaN());
+  message.add_repeated_string(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12));
+
+  // Fun story:  We used to use 1.23e22 instead of 1.23e21 above, but this
+  //   seemed to trigger an odd case on MinGW/GCC 3.4.5 where GCC's parsing of
+  //   the value differed from strtod()'s parsing.  That is to say, the
+  //   following assertion fails on MinGW:
+  //     assert(1.23e22 == strtod("1.23e22", NULL));
+  //   As a result, SimpleDtoa() would print the value as
+  //   "1.2300000000000001e+22" to make sure strtod() produce the exact same
+  //   result.  Our goal is to test runtime parsing, not compile-time parsing,
+  //   so this wasn't our problem.  It was found that using 1.23e21 did not
+  //   have this problem, so we switched to that instead.
+
+  EXPECT_EQ(
+    "repeated_int64: -9223372036854775808\n"
+    "repeated_uint64: 18446744073709551615\n"
+    "repeated_double: 123.456\n"
+    "repeated_double: 1.23e+21\n"
+    "repeated_double: 1.23e-18\n"
+    "repeated_double: inf\n"
+    "repeated_double: -inf\n"
+    "repeated_double: nan\n"
+    "repeated_string: \"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\'\\\"\"\n",
+    RemoveRedundantZeros(message.DebugString()));
+}
+
+TEST_F(TextFormatTest, PrintFloatPrecision) {
+  unittest::TestAllTypes message;
+
+  message.add_repeated_float(1.2);
+  message.add_repeated_float(1.23);
+  message.add_repeated_float(1.234);
+  message.add_repeated_float(1.2345);
+  message.add_repeated_float(1.23456);
+  message.add_repeated_float(1.2e10);
+  message.add_repeated_float(1.23e10);
+  message.add_repeated_float(1.234e10);
+  message.add_repeated_float(1.2345e10);
+  message.add_repeated_float(1.23456e10);
+  message.add_repeated_double(1.2);
+  message.add_repeated_double(1.23);
+  message.add_repeated_double(1.234);
+  message.add_repeated_double(1.2345);
+  message.add_repeated_double(1.23456);
+  message.add_repeated_double(1.234567);
+  message.add_repeated_double(1.2345678);
+  message.add_repeated_double(1.23456789);
+  message.add_repeated_double(1.234567898);
+  message.add_repeated_double(1.2345678987);
+  message.add_repeated_double(1.23456789876);
+  message.add_repeated_double(1.234567898765);
+  message.add_repeated_double(1.2345678987654);
+  message.add_repeated_double(1.23456789876543);
+  message.add_repeated_double(1.2e100);
+  message.add_repeated_double(1.23e100);
+  message.add_repeated_double(1.234e100);
+  message.add_repeated_double(1.2345e100);
+  message.add_repeated_double(1.23456e100);
+  message.add_repeated_double(1.234567e100);
+  message.add_repeated_double(1.2345678e100);
+  message.add_repeated_double(1.23456789e100);
+  message.add_repeated_double(1.234567898e100);
+  message.add_repeated_double(1.2345678987e100);
+  message.add_repeated_double(1.23456789876e100);
+  message.add_repeated_double(1.234567898765e100);
+  message.add_repeated_double(1.2345678987654e100);
+  message.add_repeated_double(1.23456789876543e100);
+
+  EXPECT_EQ(
+    "repeated_float: 1.2\n"
+    "repeated_float: 1.23\n"
+    "repeated_float: 1.234\n"
+    "repeated_float: 1.2345\n"
+    "repeated_float: 1.23456\n"
+    "repeated_float: 1.2e+10\n"
+    "repeated_float: 1.23e+10\n"
+    "repeated_float: 1.234e+10\n"
+    "repeated_float: 1.2345e+10\n"
+    "repeated_float: 1.23456e+10\n"
+    "repeated_double: 1.2\n"
+    "repeated_double: 1.23\n"
+    "repeated_double: 1.234\n"
+    "repeated_double: 1.2345\n"
+    "repeated_double: 1.23456\n"
+    "repeated_double: 1.234567\n"
+    "repeated_double: 1.2345678\n"
+    "repeated_double: 1.23456789\n"
+    "repeated_double: 1.234567898\n"
+    "repeated_double: 1.2345678987\n"
+    "repeated_double: 1.23456789876\n"
+    "repeated_double: 1.234567898765\n"
+    "repeated_double: 1.2345678987654\n"
+    "repeated_double: 1.23456789876543\n"
+    "repeated_double: 1.2e+100\n"
+    "repeated_double: 1.23e+100\n"
+    "repeated_double: 1.234e+100\n"
+    "repeated_double: 1.2345e+100\n"
+    "repeated_double: 1.23456e+100\n"
+    "repeated_double: 1.234567e+100\n"
+    "repeated_double: 1.2345678e+100\n"
+    "repeated_double: 1.23456789e+100\n"
+    "repeated_double: 1.234567898e+100\n"
+    "repeated_double: 1.2345678987e+100\n"
+    "repeated_double: 1.23456789876e+100\n"
+    "repeated_double: 1.234567898765e+100\n"
+    "repeated_double: 1.2345678987654e+100\n"
+    "repeated_double: 1.23456789876543e+100\n",
+    RemoveRedundantZeros(message.DebugString()));
+}
+
+
+TEST_F(TextFormatTest, AllowPartial) {
+  unittest::TestRequired message;
+  TextFormat::Parser parser;
+  parser.AllowPartialMessage(true);
+  EXPECT_TRUE(parser.ParseFromString("a: 1", &message));
+  EXPECT_EQ(1, message.a());
+  EXPECT_FALSE(message.has_b());
+  EXPECT_FALSE(message.has_c());
+}
+
+TEST_F(TextFormatTest, ParseExotic) {
+  unittest::TestAllTypes message;
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "repeated_int32: -1\n"
+    "repeated_int32: -2147483648\n"
+    "repeated_int64: -1\n"
+    "repeated_int64: -9223372036854775808\n"
+    "repeated_uint32: 4294967295\n"
+    "repeated_uint32: 2147483648\n"
+    "repeated_uint64: 18446744073709551615\n"
+    "repeated_uint64: 9223372036854775808\n"
+    "repeated_double: 123.0\n"
+    "repeated_double: 123.5\n"
+    "repeated_double: 0.125\n"
+    "repeated_double: 1.23E17\n"
+    "repeated_double: 1.235E+22\n"
+    "repeated_double: 1.235e-18\n"
+    "repeated_double: 123.456789\n"
+    "repeated_double: inf\n"
+    "repeated_double: Infinity\n"
+    "repeated_double: -inf\n"
+    "repeated_double: -Infinity\n"
+    "repeated_double: nan\n"
+    "repeated_double: NaN\n"
+    "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\"\n",
+    &message));
+
+  ASSERT_EQ(2, message.repeated_int32_size());
+  EXPECT_EQ(-1, message.repeated_int32(0));
+  // Note:  In C, a negative integer literal is actually the unary negation
+  //   operator being applied to a positive integer literal, and 2147483648 is
+  //   outside the range of int32.  However, it is not outside the range of
+  //   uint32.  Confusingly, this means that everything works if we make the
+  //   literal unsigned, even though we are negating it.
+  EXPECT_EQ(-2147483648u, message.repeated_int32(1));
+
+  ASSERT_EQ(2, message.repeated_int64_size());
+  EXPECT_EQ(-1, message.repeated_int64(0));
+  // Note:  In C, a negative integer literal is actually the unary negation
+  //   operator being applied to a positive integer literal, and
+  //   9223372036854775808 is outside the range of int64.  However, it is not
+  //   outside the range of uint64.  Confusingly, this means that everything
+  //   works if we make the literal unsigned, even though we are negating it.
+  EXPECT_EQ(-GOOGLE_ULONGLONG(9223372036854775808), message.repeated_int64(1));
+
+  ASSERT_EQ(2, message.repeated_uint32_size());
+  EXPECT_EQ(4294967295u, message.repeated_uint32(0));
+  EXPECT_EQ(2147483648u, message.repeated_uint32(1));
+
+  ASSERT_EQ(2, message.repeated_uint64_size());
+  EXPECT_EQ(GOOGLE_ULONGLONG(18446744073709551615), message.repeated_uint64(0));
+  EXPECT_EQ(GOOGLE_ULONGLONG(9223372036854775808), message.repeated_uint64(1));
+
+  ASSERT_EQ(13, message.repeated_double_size());
+  EXPECT_EQ(123.0     , message.repeated_double(0));
+  EXPECT_EQ(123.5     , message.repeated_double(1));
+  EXPECT_EQ(0.125     , message.repeated_double(2));
+  EXPECT_EQ(1.23E17   , message.repeated_double(3));
+  EXPECT_EQ(1.235E22  , message.repeated_double(4));
+  EXPECT_EQ(1.235E-18 , message.repeated_double(5));
+  EXPECT_EQ(123.456789, message.repeated_double(6));
+  EXPECT_EQ(message.repeated_double(7), numeric_limits<double>::infinity());
+  EXPECT_EQ(message.repeated_double(8), numeric_limits<double>::infinity());
+  EXPECT_EQ(message.repeated_double(9), -numeric_limits<double>::infinity());
+  EXPECT_EQ(message.repeated_double(10), -numeric_limits<double>::infinity());
+  EXPECT_TRUE(MathLimits<double>::IsNaN(message.repeated_double(11)));
+  EXPECT_TRUE(MathLimits<double>::IsNaN(message.repeated_double(12)));
+
+  // Note:  Since these string literals have \0's in them, we must explicitly
+  //   pass their sizes to string's constructor.
+  ASSERT_EQ(1, message.repeated_string_size());
+  EXPECT_EQ(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12),
+            message.repeated_string(0));
+}
+
+TEST_F(TextFormatTest, PrintFieldsInIndexOrder) {
+  protobuf_unittest::TestFieldOrderings message;
+  // Fields are listed in index order instead of field number.
+  message.set_my_string("Test String");   // Field number 11
+  message.set_my_int(12345);              // Field number 1
+  message.set_my_float(0.999);            // Field number 101
+  TextFormat::Printer printer;
+  string text;
+
+  // By default, print in field number order.
+  printer.PrintToString(message, &text);
+  EXPECT_EQ("my_int: 12345\nmy_string: \"Test String\"\nmy_float: 0.999\n",
+            text);
+
+  // Print in index order.
+  printer.SetPrintMessageFieldsInIndexOrder(true);
+  printer.PrintToString(message, &text);
+  EXPECT_EQ("my_string: \"Test String\"\nmy_int: 12345\nmy_float: 0.999\n",
+            text);
+}
+
+class TextFormatParserTest : public testing::Test {
+ protected:
+  void ExpectFailure(const string& input, const string& message, int line,
+                     int col) {
+    google::protobuf::scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
+    ExpectFailure(input, message, line, col, proto.get());
+  }
+
+  void ExpectFailure(const string& input, const string& message, int line,
+                     int col, Message* proto) {
+    ExpectMessage(input, message, line, col, proto, false);
+  }
+
+  void ExpectMessage(const string& input, const string& message, int line,
+                     int col, Message* proto, bool expected_result) {
+    TextFormat::Parser parser;
+    MockErrorCollector error_collector;
+    parser.RecordErrorsTo(&error_collector);
+    EXPECT_EQ(expected_result, parser.ParseFromString(input, proto))
+        << input << " -> " << proto->DebugString();
+    EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n",
+              error_collector.text_);
+  }
+
+  void ExpectSuccessAndTree(const string& input, Message* proto,
+                            TextFormat::ParseInfoTree* info_tree) {
+    TextFormat::Parser parser;
+    MockErrorCollector error_collector;
+    parser.RecordErrorsTo(&error_collector);
+    parser.WriteLocationsTo(info_tree);
+
+    EXPECT_TRUE(parser.ParseFromString(input, proto));
+  }
+
+  void ExpectLocation(TextFormat::ParseInfoTree* tree,
+                      const Descriptor* d, const string& field_name,
+                      int index, int line, int column) {
+    TextFormat::ParseLocation location = tree->GetLocation(
+        d->FindFieldByName(field_name), index);
+    EXPECT_EQ(line, location.line);
+    EXPECT_EQ(column, location.column);
+  }
+
+  // An error collector which simply concatenates all its errors into a big
+  // block of text which can be checked.
+  class MockErrorCollector : public io::ErrorCollector {
+   public:
+    MockErrorCollector() {}
+    ~MockErrorCollector() {}
+
+    string text_;
+
+    // implements ErrorCollector -------------------------------------
+    void AddError(int line, int column, const string& message) {
+      strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
+                                   line + 1, column + 1, message);
+    }
+
+    void AddWarning(int line, int column, const string& message) {
+      AddError(line, column, "WARNING:" + message);
+    }
+  };
+};
+
+TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
+  google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+  const Descriptor* d = message->GetDescriptor();
+
+  string stringData =
+      "optional_int32: 1\n"
+      "optional_int64: 2\n"
+      "  optional_double: 2.4\n"
+      "repeated_int32: 5\n"
+      "repeated_int32: 10\n"
+      "optional_nested_message <\n"
+      "  bb: 78\n"
+      ">\n"
+      "repeated_nested_message <\n"
+      "  bb: 79\n"
+      ">\n"
+      "repeated_nested_message <\n"
+      "  bb: 80\n"
+      ">";
+
+
+  TextFormat::ParseInfoTree tree;
+  ExpectSuccessAndTree(stringData, message.get(), &tree);
+
+  // Verify that the tree has the correct positions.
+  ExpectLocation(&tree, d, "optional_int32", -1, 0, 0);
+  ExpectLocation(&tree, d, "optional_int64", -1, 1, 0);
+  ExpectLocation(&tree, d, "optional_double", -1, 2, 2);
+
+  ExpectLocation(&tree, d, "repeated_int32", 0, 3, 0);
+  ExpectLocation(&tree, d, "repeated_int32", 1, 4, 0);
+
+  ExpectLocation(&tree, d, "optional_nested_message", -1, 5, 0);
+  ExpectLocation(&tree, d, "repeated_nested_message", 0, 8, 0);
+  ExpectLocation(&tree, d, "repeated_nested_message", 1, 11, 0);
+
+  // Check for fields not set. For an invalid field, the location returned
+  // should be -1, -1.
+  ExpectLocation(&tree, d, "repeated_int64", 0, -1, -1);
+  ExpectLocation(&tree, d, "repeated_int32", 6, -1, -1);
+  ExpectLocation(&tree, d, "some_unknown_field", -1, -1, -1);
+
+  // Verify inside the nested message.
+  const FieldDescriptor* nested_field =
+      d->FindFieldByName("optional_nested_message");
+
+  TextFormat::ParseInfoTree* nested_tree =
+      tree.GetTreeForNested(nested_field, -1);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 6, 2);
+
+  // Verify inside another nested message.
+  nested_field = d->FindFieldByName("repeated_nested_message");
+  nested_tree = tree.GetTreeForNested(nested_field, 0);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 9, 2);
+
+  nested_tree = tree.GetTreeForNested(nested_field, 1);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 12, 2);
+
+  // Verify a NULL tree for an unknown nested field.
+  TextFormat::ParseInfoTree* unknown_nested_tree =
+      tree.GetTreeForNested(nested_field, 2);
+
+  EXPECT_EQ(NULL, unknown_nested_tree);
+}
+
+TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
+  google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+  const Descriptor* d = message->GetDescriptor();
+
+#define EXPECT_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_BOOL_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_TRUE(message->optional_##name() == value); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_FLOAT_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_FLOAT_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get())); \
+  EXPECT_DOUBLE_EQ(value, message->optional_##name()); \
+  EXPECT_TRUE(message->has_optional_##name());
+
+#define EXPECT_INVALID(name, valuestring) \
+  EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \
+    valuestring, d->FindFieldByName("optional_" #name), message.get()));
+
+  // int32
+  EXPECT_FIELD(int32, 1, "1");
+  EXPECT_FIELD(int32, -1, "-1");
+  EXPECT_FIELD(int32, 0x1234, "0x1234");
+  EXPECT_INVALID(int32, "a");
+  EXPECT_INVALID(int32, "999999999999999999999999999999999999");
+  EXPECT_INVALID(int32, "1,2");
+
+  // int64
+  EXPECT_FIELD(int64, 1, "1");
+  EXPECT_FIELD(int64, -1, "-1");
+  EXPECT_FIELD(int64, 0x1234567812345678LL, "0x1234567812345678");
+  EXPECT_INVALID(int64, "a");
+  EXPECT_INVALID(int64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(int64, "1,2");
+
+  // uint64
+  EXPECT_FIELD(uint64, 1, "1");
+  EXPECT_FIELD(uint64, 0xf234567812345678ULL, "0xf234567812345678");
+  EXPECT_INVALID(uint64, "-1");
+  EXPECT_INVALID(uint64, "a");
+  EXPECT_INVALID(uint64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(uint64, "1,2");
+
+  // fixed32
+  EXPECT_FIELD(fixed32, 1, "1");
+  EXPECT_FIELD(fixed32, 0x12345678, "0x12345678");
+  EXPECT_INVALID(fixed32, "-1");
+  EXPECT_INVALID(fixed32, "a");
+  EXPECT_INVALID(fixed32, "999999999999999999999999999999999999");
+  EXPECT_INVALID(fixed32, "1,2");
+
+  // fixed64
+  EXPECT_FIELD(fixed64, 1, "1");
+  EXPECT_FIELD(fixed64, 0x1234567812345678ULL, "0x1234567812345678");
+  EXPECT_INVALID(fixed64, "-1");
+  EXPECT_INVALID(fixed64, "a");
+  EXPECT_INVALID(fixed64, "999999999999999999999999999999999999");
+  EXPECT_INVALID(fixed64, "1,2");
+
+  // bool
+  EXPECT_BOOL_FIELD(bool, true, "true");
+  EXPECT_BOOL_FIELD(bool, false, "false");
+  EXPECT_BOOL_FIELD(bool, true, "1");
+  EXPECT_BOOL_FIELD(bool, true, "t");
+  EXPECT_BOOL_FIELD(bool, false, "0");
+  EXPECT_BOOL_FIELD(bool, false, "f");
+  EXPECT_FIELD(bool, true, "True");
+  EXPECT_FIELD(bool, false, "False");
+  EXPECT_INVALID(bool, "tRue");
+  EXPECT_INVALID(bool, "faLse");
+  EXPECT_INVALID(bool, "2");
+  EXPECT_INVALID(bool, "-0");
+  EXPECT_INVALID(bool, "on");
+  EXPECT_INVALID(bool, "a");
+
+  // float
+  EXPECT_FIELD(float, 1, "1");
+  EXPECT_FLOAT_FIELD(float, 1.5, "1.5");
+  EXPECT_FLOAT_FIELD(float, 1.5e3, "1.5e3");
+  EXPECT_FLOAT_FIELD(float, -4.55, "-4.55");
+  EXPECT_INVALID(float, "a");
+  EXPECT_INVALID(float, "1,2");
+
+  // double
+  EXPECT_FIELD(double, 1, "1");
+  EXPECT_FIELD(double, -1, "-1");
+  EXPECT_DOUBLE_FIELD(double, 2.3, "2.3");
+  EXPECT_DOUBLE_FIELD(double, 3e5, "3e5");
+  EXPECT_INVALID(double, "a");
+  EXPECT_INVALID(double, "1,2");
+  // Rejects hex and oct numbers for a double field.
+  EXPECT_INVALID(double, "0xf");
+  EXPECT_INVALID(double, "012");
+
+  // string
+  EXPECT_FIELD(string, "hello", "\"hello\"");
+  EXPECT_FIELD(string, "-1.87", "'-1.87'");
+  EXPECT_INVALID(string, "hello");  // without quote for value
+
+  // enum
+  EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
+  EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ,
+               SimpleItoa(unittest::TestAllTypes::BAZ));
+  EXPECT_INVALID(nested_enum, "FOOBAR");
+
+  // message
+  EXPECT_TRUE(TextFormat::ParseFieldValueFromString(
+    "<bb:12>", d->FindFieldByName("optional_nested_message"), message.get()));
+  EXPECT_EQ(12, message->optional_nested_message().bb()); \
+  EXPECT_TRUE(message->has_optional_nested_message());
+  EXPECT_INVALID(nested_message, "any");
+
+#undef EXPECT_FIELD
+#undef EXPECT_BOOL_FIELD
+#undef EXPECT_FLOAT_FIELD
+#undef EXPECT_DOUBLE_FIELD
+#undef EXPECT_INVALID
+}
+
+
+TEST_F(TextFormatParserTest, InvalidToken) {
+  ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.",
+                2, 1);
+
+  ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20);
+  ExpectFailure("\"some string\"", "Expected identifier.", 1, 1);
+}
+
+TEST_F(TextFormatParserTest, InvalidFieldName) {
+  ExpectFailure(
+      "invalid_field: somevalue\n",
+      "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
+      "\"invalid_field\".",
+      1, 14);
+}
+
+TEST_F(TextFormatParserTest, InvalidCapitalization) {
+  // We require that group names be exactly as they appear in the .proto.
+  ExpectFailure(
+      "optionalgroup {\na: 15\n}\n",
+      "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
+      "\"optionalgroup\".",
+      1, 15);
+  ExpectFailure(
+      "OPTIONALgroup {\na: 15\n}\n",
+      "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
+      "\"OPTIONALgroup\".",
+      1, 15);
+  ExpectFailure(
+      "Optional_Double: 10.0\n",
+      "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
+      "\"Optional_Double\".",
+      1, 16);
+}
+
+TEST_F(TextFormatParserTest, AllowIgnoreCapitalizationError) {
+  TextFormat::Parser parser;
+  protobuf_unittest::TestAllTypes proto;
+
+  // These fields have a mismatching case.
+  EXPECT_FALSE(parser.ParseFromString("Optional_Double: 10.0", &proto));
+  EXPECT_FALSE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto));
+
+  // ... but are parsed correctly if we match case insensitive.
+  parser.AllowCaseInsensitiveField(true);
+  EXPECT_TRUE(parser.ParseFromString("Optional_Double: 10.0", &proto));
+  EXPECT_EQ(10.0, proto.optional_double());
+  EXPECT_TRUE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto));
+  EXPECT_EQ(15, proto.optionalgroup().a());
+}
+
+TEST_F(TextFormatParserTest, InvalidFieldValues) {
+  // Invalid values for a double/float field.
+  ExpectFailure("optional_double: \"hello\"\n", "Expected double.", 1, 18);
+  ExpectFailure("optional_double: true\n", "Expected double.", 1, 18);
+  ExpectFailure("optional_double: !\n", "Expected double.", 1, 18);
+  ExpectFailure("optional_double {\n  \n}\n", "Expected \":\", found \"{\".",
+                1, 17);
+
+  // Invalid values for a signed integer field.
+  ExpectFailure("optional_int32: \"hello\"\n", "Expected integer.", 1, 17);
+  ExpectFailure("optional_int32: true\n", "Expected integer.", 1, 17);
+  ExpectFailure("optional_int32: 4.5\n", "Expected integer.", 1, 17);
+  ExpectFailure("optional_int32: !\n", "Expected integer.", 1, 17);
+  ExpectFailure("optional_int32 {\n \n}\n", "Expected \":\", found \"{\".",
+                1, 16);
+  ExpectFailure("optional_int32: 0x80000000\n",
+                "Integer out of range.", 1, 17);
+  ExpectFailure("optional_int64: 0x8000000000000000\n",
+                "Integer out of range.", 1, 17);
+  ExpectFailure("optional_int32: -0x80000001\n",
+                "Integer out of range.", 1, 18);
+  ExpectFailure("optional_int64: -0x8000000000000001\n",
+                "Integer out of range.", 1, 18);
+
+  // Invalid values for an unsigned integer field.
+  ExpectFailure("optional_uint64: \"hello\"\n", "Expected integer.", 1, 18);
+  ExpectFailure("optional_uint64: true\n", "Expected integer.", 1, 18);
+  ExpectFailure("optional_uint64: 4.5\n", "Expected integer.", 1, 18);
+  ExpectFailure("optional_uint64: -5\n", "Expected integer.", 1, 18);
+  ExpectFailure("optional_uint64: !\n", "Expected integer.", 1, 18);
+  ExpectFailure("optional_uint64 {\n \n}\n", "Expected \":\", found \"{\".",
+                1, 17);
+  ExpectFailure("optional_uint32: 0x100000000\n",
+                "Integer out of range.", 1, 18);
+  ExpectFailure("optional_uint64: 0x10000000000000000\n",
+                "Integer out of range.", 1, 18);
+
+  // Invalid values for a boolean field.
+  ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16);
+  ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16);
+  ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16);
+  ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16);
+
+  ExpectFailure(
+      "optional_bool: meh\n",
+      "Invalid value for boolean field \"optional_bool\". Value: \"meh\".",
+      2, 1);
+
+  ExpectFailure("optional_bool {\n \n}\n", "Expected \":\", found \"{\".",
+                1, 15);
+
+  // Invalid values for a string field.
+  ExpectFailure("optional_string: true\n", "Expected string.", 1, 18);
+  ExpectFailure("optional_string: 5\n", "Expected string.", 1, 18);
+  ExpectFailure("optional_string: -7.5\n", "Expected string.", 1, 18);
+  ExpectFailure("optional_string: !\n", "Expected string.", 1, 18);
+  ExpectFailure("optional_string {\n \n}\n", "Expected \":\", found \"{\".",
+                1, 17);
+
+  // Invalid values for an enumeration field.
+  ExpectFailure("optional_nested_enum: \"hello\"\n",
+                "Expected integer or identifier.", 1, 23);
+
+  // Valid token, but enum value is not defined.
+  ExpectFailure("optional_nested_enum: 5\n",
+                "Unknown enumeration value of \"5\" for field "
+                "\"optional_nested_enum\".", 2, 1);
+  // We consume the negative sign, so the error position starts one character
+  // later.
+  ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24);
+  ExpectFailure("optional_nested_enum: !\n",
+                "Expected integer or identifier.", 1, 23);
+
+  ExpectFailure(
+      "optional_nested_enum: grah\n",
+      "Unknown enumeration value of \"grah\" for field "
+      "\"optional_nested_enum\".", 2, 1);
+
+  ExpectFailure(
+      "optional_nested_enum {\n \n}\n",
+      "Expected \":\", found \"{\".", 1, 22);
+}
+
+TEST_F(TextFormatParserTest, MessageDelimiters) {
+  // Non-matching delimiters.
+  ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".",
+                3, 1);
+
+  // Invalid delimiters.
+  ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".",
+                1, 15);
+
+  // Unending message.
+  ExpectFailure("optional_nested_message {\n \nbb: 118\n",
+                "Expected identifier.",
+                4, 1);
+}
+
+TEST_F(TextFormatParserTest, UnknownExtension) {
+  // Non-matching delimiters.
+  ExpectFailure("[blahblah]: 123",
+                "Extension \"blahblah\" is not defined or is not an "
+                "extension of \"protobuf_unittest.TestAllTypes\".",
+                1, 11);
+}
+
+TEST_F(TextFormatParserTest, MissingRequired) {
+  unittest::TestRequired message;
+  ExpectFailure("a: 1",
+                "Message missing required fields: b, c",
+                0, 1, &message);
+}
+
+TEST_F(TextFormatParserTest, ParseDuplicateRequired) {
+  unittest::TestRequired message;
+  ExpectFailure("a: 1 b: 2 c: 3 a: 1",
+                "Non-repeated field \"a\" is specified multiple times.",
+                1, 17, &message);
+}
+
+TEST_F(TextFormatParserTest, ParseDuplicateOptional) {
+  unittest::ForeignMessage message;
+  ExpectFailure("c: 1 c: 2",
+                "Non-repeated field \"c\" is specified multiple times.",
+                1, 7, &message);
+}
+
+TEST_F(TextFormatParserTest, MergeDuplicateRequired) {
+  unittest::TestRequired message;
+  TextFormat::Parser parser;
+  EXPECT_TRUE(parser.MergeFromString("a: 1 b: 2 c: 3 a: 4", &message));
+  EXPECT_EQ(4, message.a());
+}
+
+TEST_F(TextFormatParserTest, MergeDuplicateOptional) {
+  unittest::ForeignMessage message;
+  TextFormat::Parser parser;
+  EXPECT_TRUE(parser.MergeFromString("c: 1 c: 2", &message));
+  EXPECT_EQ(2, message.c());
+}
+
+TEST_F(TextFormatParserTest, ExplicitDelimiters) {
+  unittest::TestRequired message;
+  EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message));
+  EXPECT_EQ(1, message.a());
+  EXPECT_EQ(2, message.b());
+  EXPECT_EQ(3, message.c());
+}
+
+TEST_F(TextFormatParserTest, PrintErrorsToStderr) {
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog log;
+    unittest::TestAllTypes proto;
+    EXPECT_FALSE(TextFormat::ParseFromString("no_such_field: 1", &proto));
+    errors = log.GetMessages(ERROR);
+  }
+
+  ASSERT_EQ(1, errors.size());
+  EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: "
+            "1:14: Message type \"protobuf_unittest.TestAllTypes\" has no field "
+            "named \"no_such_field\".",
+            errors[0]);
+}
+
+TEST_F(TextFormatParserTest, FailsOnTokenizationError) {
+  vector<string> errors;
+
+  {
+    ScopedMemoryLog log;
+    unittest::TestAllTypes proto;
+    EXPECT_FALSE(TextFormat::ParseFromString("\020", &proto));
+    errors = log.GetMessages(ERROR);
+  }
+
+  ASSERT_EQ(1, errors.size());
+  EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: "
+            "1:1: Invalid control characters encountered in text.",
+            errors[0]);
+}
+
+TEST_F(TextFormatParserTest, ParseDeprecatedField) {
+  unittest::TestDeprecatedFields message;
+  ExpectMessage("deprecated_int32: 42",
+                "WARNING:text format contains deprecated field "
+                "\"deprecated_int32\"", 1, 21, &message, true);
+}
+
+class TextFormatMessageSetTest : public testing::Test {
+ protected:
+  static const char proto_debug_string_[];
+};
+const char TextFormatMessageSetTest::proto_debug_string_[] =
+"message_set {\n"
+"  [protobuf_unittest.TestMessageSetExtension1] {\n"
+"    i: 23\n"
+"  }\n"
+"  [protobuf_unittest.TestMessageSetExtension2] {\n"
+"    str: \"foo\"\n"
+"  }\n"
+"}\n";
+
+
+TEST_F(TextFormatMessageSetTest, Serialize) {
+  protobuf_unittest::TestMessageSetContainer proto;
+  protobuf_unittest::TestMessageSetExtension1* item_a =
+    proto.mutable_message_set()->MutableExtension(
+      protobuf_unittest::TestMessageSetExtension1::message_set_extension);
+  item_a->set_i(23);
+  protobuf_unittest::TestMessageSetExtension2* item_b =
+    proto.mutable_message_set()->MutableExtension(
+      protobuf_unittest::TestMessageSetExtension2::message_set_extension);
+  item_b->set_str("foo");
+  EXPECT_EQ(proto_debug_string_, proto.DebugString());
+}
+
+TEST_F(TextFormatMessageSetTest, Deserialize) {
+  protobuf_unittest::TestMessageSetContainer proto;
+  ASSERT_TRUE(TextFormat::ParseFromString(proto_debug_string_, &proto));
+  EXPECT_EQ(23, proto.message_set().GetExtension(
+    protobuf_unittest::TestMessageSetExtension1::message_set_extension).i());
+  EXPECT_EQ("foo", proto.message_set().GetExtension(
+    protobuf_unittest::TestMessageSetExtension2::message_set_extension).str());
+
+  // Ensure that these are the only entries present.
+  vector<const FieldDescriptor*> descriptors;
+  proto.message_set().GetReflection()->ListFields(
+    proto.message_set(), &descriptors);
+  EXPECT_EQ(2, descriptors.size());
+}
+
+
+}  // namespace text_format_unittest
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.cc
new file mode 100644
index 0000000..7cdf509
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.cc
@@ -0,0 +1,451 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/timestamp.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Timestamp_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Timestamp_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/timestamp.proto");
+  GOOGLE_CHECK(file != NULL);
+  Timestamp_descriptor_ = file->message_type(0);
+  static const int Timestamp_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, seconds_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, nanos_),
+  };
+  Timestamp_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Timestamp_descriptor_,
+      Timestamp::default_instance_,
+      Timestamp_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Timestamp),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Timestamp_descriptor_, &Timestamp::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto() {
+  delete Timestamp::default_instance_;
+  delete Timestamp_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\037google/protobuf/timestamp.proto\022\017googl"
+    "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003"
+    "\022\r\n\005nanos\030\002 \001(\005B\201\001\n\023com.google.protobufB"
+    "\016TimestampProtoP\001Z+github.com/golang/pro"
+    "tobuf/ptypes/timestamp\240\001\001\370\001\001\242\002\003GPB\252\002\036Goo"
+    "gle.Protobuf.WellKnownTypesb\006proto3", 235);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/timestamp.proto", &protobuf_RegisterTypes);
+  Timestamp::default_instance_ = new Timestamp();
+  Timestamp::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2ftimestamp_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Timestamp::kSecondsFieldNumber;
+const int Timestamp::kNanosFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Timestamp::Timestamp()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Timestamp)
+}
+
+Timestamp::Timestamp(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp)
+}
+
+void Timestamp::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Timestamp::Timestamp(const Timestamp& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp)
+}
+
+void Timestamp::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  seconds_ = GOOGLE_LONGLONG(0);
+  nanos_ = 0;
+}
+
+Timestamp::~Timestamp() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Timestamp)
+  SharedDtor();
+}
+
+void Timestamp::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void Timestamp::ArenaDtor(void* object) {
+  Timestamp* _this = reinterpret_cast< Timestamp* >(object);
+  (void)_this;
+}
+void Timestamp::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void Timestamp::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Timestamp::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Timestamp_descriptor_;
+}
+
+const Timestamp& Timestamp::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+  return *default_instance_;
+}
+
+Timestamp* Timestamp::default_instance_ = NULL;
+
+Timestamp* Timestamp::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<Timestamp>(arena);
+}
+
+void Timestamp::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(Timestamp, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Timestamp*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(seconds_, nanos_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+}
+
+bool Timestamp::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Timestamp)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int64 seconds = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &seconds_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_nanos;
+        break;
+      }
+
+      // optional int32 nanos = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_nanos:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &nanos_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Timestamp)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Timestamp)
+  return false;
+#undef DO_
+}
+
+void Timestamp::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Timestamp)
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output);
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Timestamp)
+}
+
+::google::protobuf::uint8* Timestamp::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp)
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp)
+  return target;
+}
+
+int Timestamp::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp)
+  int total_size = 0;
+
+  // optional int64 seconds = 1;
+  if (this->seconds() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->seconds());
+  }
+
+  // optional int32 nanos = 2;
+  if (this->nanos() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->nanos());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Timestamp* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp)
+    MergeFrom(*source);
+  }
+}
+
+void Timestamp::MergeFrom(const Timestamp& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.seconds() != 0) {
+    set_seconds(from.seconds());
+  }
+  if (from.nanos() != 0) {
+    set_nanos(from.nanos());
+  }
+}
+
+void Timestamp::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Timestamp::CopyFrom(const Timestamp& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Timestamp)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Timestamp::IsInitialized() const {
+
+  return true;
+}
+
+void Timestamp::Swap(Timestamp* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    Timestamp temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void Timestamp::UnsafeArenaSwap(Timestamp* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void Timestamp::InternalSwap(Timestamp* other) {
+  std::swap(seconds_, other->seconds_);
+  std::swap(nanos_, other->nanos_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Timestamp::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Timestamp_descriptor_;
+  metadata.reflection = Timestamp_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Timestamp
+
+// optional int64 seconds = 1;
+void Timestamp::clear_seconds() {
+  seconds_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Timestamp::seconds() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
+  return seconds_;
+}
+ void Timestamp::set_seconds(::google::protobuf::int64 value) {
+  
+  seconds_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
+}
+
+// optional int32 nanos = 2;
+void Timestamp::clear_nanos() {
+  nanos_ = 0;
+}
+ ::google::protobuf::int32 Timestamp::nanos() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
+  return nanos_;
+}
+ void Timestamp::set_nanos(::google::protobuf::int32 value) {
+  
+  nanos_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.h b/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.h
new file mode 100644
index 0000000..7bf6259
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/timestamp.pb.h
@@ -0,0 +1,185 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto();
+
+class Timestamp;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Timestamp : public ::google::protobuf::Message {
+ public:
+  Timestamp();
+  virtual ~Timestamp();
+
+  Timestamp(const Timestamp& from);
+
+  inline Timestamp& operator=(const Timestamp& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Timestamp& default_instance();
+
+  void UnsafeArenaSwap(Timestamp* other);
+  void Swap(Timestamp* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Timestamp* New() const { return New(NULL); }
+
+  Timestamp* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Timestamp& from);
+  void MergeFrom(const Timestamp& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Timestamp* other);
+  protected:
+  explicit Timestamp(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int64 seconds = 1;
+  void clear_seconds();
+  static const int kSecondsFieldNumber = 1;
+  ::google::protobuf::int64 seconds() const;
+  void set_seconds(::google::protobuf::int64 value);
+
+  // optional int32 nanos = 2;
+  void clear_nanos();
+  static const int kNanosFieldNumber = 2;
+  ::google::protobuf::int32 nanos() const;
+  void set_nanos(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::int64 seconds_;
+  ::google::protobuf::int32 nanos_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto();
+
+  void InitAsDefaultInstance();
+  static Timestamp* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Timestamp
+
+// optional int64 seconds = 1;
+inline void Timestamp::clear_seconds() {
+  seconds_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Timestamp::seconds() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
+  return seconds_;
+}
+inline void Timestamp::set_seconds(::google::protobuf::int64 value) {
+  
+  seconds_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
+}
+
+// optional int32 nanos = 2;
+inline void Timestamp::clear_nanos() {
+  nanos_ = 0;
+}
+inline ::google::protobuf::int32 Timestamp::nanos() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
+  return nanos_;
+}
+inline void Timestamp::set_nanos(::google::protobuf::int32 value) {
+  
+  nanos_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/timestamp.proto b/src/third_party/protobuf-3/src/google/protobuf/timestamp.proto
new file mode 100644
index 0000000..7992a85
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/timestamp.proto
@@ -0,0 +1,111 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TimestampProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from  RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+//     Timestamp timestamp;
+//     timestamp.set_seconds(time(NULL));
+//     timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+//     struct timeval tv;
+//     gettimeofday(&tv, NULL);
+//
+//     Timestamp timestamp;
+//     timestamp.set_seconds(tv.tv_sec);
+//     timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+//     FILETIME ft;
+//     GetSystemTimeAsFileTime(&ft);
+//     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+//     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+//     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+//     Timestamp timestamp;
+//     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+//     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+//     long millis = System.currentTimeMillis();
+//
+//     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+//         .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+//     now = time.time()
+//     seconds = int(now)
+//     nanos = int((now - seconds) * 10**9)
+//     timestamp = Timestamp(seconds=seconds, nanos=nanos)
+//
+//
+message Timestamp {
+
+  // Represents seconds of UTC time since Unix epoch
+  // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+  // 9999-12-31T23:59:59Z inclusive.
+  int64 seconds = 1;
+
+  // Non-negative fractions of a second at nanosecond resolution. Negative
+  // second values with fractions must still have non-negative nanos values
+  // that count forward in time. Must be from 0 to 999,999,999
+  // inclusive.
+  int32 nanos = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/type.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/type.pb.cc
new file mode 100644
index 0000000..759cab2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/type.pb.cc
@@ -0,0 +1,3291 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/type.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Type_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Type_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Field_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Field_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* Enum_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Enum_reflection_ = NULL;
+const ::google::protobuf::Descriptor* EnumValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  EnumValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Option_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Option_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* Syntax_descriptor_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/type.proto");
+  GOOGLE_CHECK(file != NULL);
+  Type_descriptor_ = file->message_type(0);
+  static const int Type_offsets_[6] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, fields_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, oneofs_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, source_context_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, syntax_),
+  };
+  Type_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Type_descriptor_,
+      Type::default_instance_,
+      Type_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Type),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _is_default_instance_));
+  Field_descriptor_ = file->message_type(1);
+  static const int Field_offsets_[10] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, kind_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, cardinality_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, number_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, type_url_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, oneof_index_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, packed_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, json_name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, default_value_),
+  };
+  Field_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Field_descriptor_,
+      Field::default_instance_,
+      Field_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Field),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _is_default_instance_));
+  Field_Kind_descriptor_ = Field_descriptor_->enum_type(0);
+  Field_Cardinality_descriptor_ = Field_descriptor_->enum_type(1);
+  Enum_descriptor_ = file->message_type(2);
+  static const int Enum_offsets_[5] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, enumvalue_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, source_context_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, syntax_),
+  };
+  Enum_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Enum_descriptor_,
+      Enum::default_instance_,
+      Enum_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Enum),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _is_default_instance_));
+  EnumValue_descriptor_ = file->message_type(3);
+  static const int EnumValue_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, number_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, options_),
+  };
+  EnumValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      EnumValue_descriptor_,
+      EnumValue::default_instance_,
+      EnumValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(EnumValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _is_default_instance_));
+  Option_descriptor_ = file->message_type(4);
+  static const int Option_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, value_),
+  };
+  Option_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Option_descriptor_,
+      Option::default_instance_,
+      Option_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Option),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _is_default_instance_));
+  Syntax_descriptor_ = file->enum_type(0);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Type_descriptor_, &Type::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Field_descriptor_, &Field::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Enum_descriptor_, &Enum::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      EnumValue_descriptor_, &EnumValue::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Option_descriptor_, &Option::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto() {
+  delete Type::default_instance_;
+  delete Type_reflection_;
+  delete Field::default_instance_;
+  delete Field_reflection_;
+  delete Enum::default_instance_;
+  delete Enum_reflection_;
+  delete EnumValue::default_instance_;
+  delete EnumValue_reflection_;
+  delete Option::default_instance_;
+  delete Option_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\032google/protobuf/type.proto\022\017google.pro"
+    "tobuf\032\031google/protobuf/any.proto\032$google"
+    "/protobuf/source_context.proto\"\327\001\n\004Type\022"
+    "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
+    "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
+    "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
+    "e_context\030\005 \001(\0132\036.google.protobuf.Source"
+    "Context\022\'\n\006syntax\030\006 \001(\0162\027.google.protobu"
+    "f.Syntax\"\325\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.googl"
+    "e.protobuf.Field.Kind\0227\n\013cardinality\030\002 \001"
+    "(\0162\".google.protobuf.Field.Cardinality\022\016"
+    "\n\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url"
+    "\030\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 "
+    "\001(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.O"
+    "ption\022\021\n\tjson_name\030\n \001(\t\022\025\n\rdefault_valu"
+    "e\030\013 \001(\t\"\310\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TY"
+    "PE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT6"
+    "4\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014"
+    "TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE"
+    "_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n"
+    "\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TY"
+    "PE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXE"
+    "D32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020"
+    "\021\022\017\n\013TYPE_SINT64\020\022\"t\n\013Cardinality\022\027\n\023CAR"
+    "DINALITY_UNKNOWN\020\000\022\030\n\024CARDINALITY_OPTION"
+    "AL\020\001\022\030\n\024CARDINALITY_REQUIRED\020\002\022\030\n\024CARDIN"
+    "ALITY_REPEATED\020\003\"\316\001\n\004Enum\022\014\n\004name\030\001 \001(\t\022"
+    "-\n\tenumvalue\030\002 \003(\0132\032.google.protobuf.Enu"
+    "mValue\022(\n\007options\030\003 \003(\0132\027.google.protobu"
+    "f.Option\0226\n\016source_context\030\004 \001(\0132\036.googl"
+    "e.protobuf.SourceContext\022\'\n\006syntax\030\005 \001(\016"
+    "2\027.google.protobuf.Syntax\"S\n\tEnumValue\022\014"
+    "\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\022(\n\007options\030"
+    "\003 \003(\0132\027.google.protobuf.Option\";\n\006Option"
+    "\022\014\n\004name\030\001 \001(\t\022#\n\005value\030\002 \001(\0132\024.google.p"
+    "rotobuf.Any*.\n\006Syntax\022\021\n\rSYNTAX_PROTO2\020\000"
+    "\022\021\n\rSYNTAX_PROTO3\020\001BL\n\023com.google.protob"
+    "ufB\tTypeProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protob"
+    "uf.WellKnownTypesb\006proto3", 1545);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/type.proto", &protobuf_RegisterTypes);
+  Type::default_instance_ = new Type();
+  Field::default_instance_ = new Field();
+  Enum::default_instance_ = new Enum();
+  EnumValue::default_instance_ = new EnumValue();
+  Option::default_instance_ = new Option();
+  Type::default_instance_->InitAsDefaultInstance();
+  Field::default_instance_->InitAsDefaultInstance();
+  Enum::default_instance_->InitAsDefaultInstance();
+  EnumValue::default_instance_->InitAsDefaultInstance();
+  Option::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2ftype_2eproto_;
+const ::google::protobuf::EnumDescriptor* Syntax_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Syntax_descriptor_;
+}
+bool Syntax_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Type::kNameFieldNumber;
+const int Type::kFieldsFieldNumber;
+const int Type::kOneofsFieldNumber;
+const int Type::kOptionsFieldNumber;
+const int Type::kSourceContextFieldNumber;
+const int Type::kSyntaxFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Type::Type()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Type)
+}
+
+void Type::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+  source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Type::Type(const Type& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Type)
+}
+
+void Type::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  source_context_ = NULL;
+  syntax_ = 0;
+}
+
+Type::~Type() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Type)
+  SharedDtor();
+}
+
+void Type::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete source_context_;
+  }
+}
+
+void Type::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Type::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Type_descriptor_;
+}
+
+const Type& Type::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  return *default_instance_;
+}
+
+Type* Type::default_instance_ = NULL;
+
+Type* Type::New(::google::protobuf::Arena* arena) const {
+  Type* n = new Type;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Type::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+  syntax_ = 0;
+  fields_.Clear();
+  oneofs_.Clear();
+  options_.Clear();
+}
+
+bool Type::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Type)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Type.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_fields;
+        break;
+      }
+
+      // repeated .google.protobuf.Field fields = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_fields:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_fields:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_fields()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_fields;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(26)) goto parse_oneofs;
+        break;
+      }
+
+      // repeated string oneofs = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_oneofs:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_oneofs()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->oneofs(this->oneofs_size() - 1).data(),
+            this->oneofs(this->oneofs_size() - 1).length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Type.oneofs"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_oneofs;
+        if (input->ExpectTag(34)) goto parse_options;
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_options:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(42)) goto parse_source_context;
+        break;
+      }
+
+      // optional .google.protobuf.SourceContext source_context = 5;
+      case 5: {
+        if (tag == 42) {
+         parse_source_context:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_context()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(48)) goto parse_syntax;
+        break;
+      }
+
+      // optional .google.protobuf.Syntax syntax = 6;
+      case 6: {
+        if (tag == 48) {
+         parse_syntax:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Type)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Type)
+  return false;
+#undef DO_
+}
+
+void Type::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Type)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Type.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.Field fields = 2;
+  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->fields(i), output);
+  }
+
+  // repeated string oneofs = 3;
+  for (int i = 0; i < this->oneofs_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->oneofs(i).data(), this->oneofs(i).length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Type.oneofs");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->oneofs(i), output);
+  }
+
+  // repeated .google.protobuf.Option options = 4;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, this->options(i), output);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      5, *this->source_context_, output);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 6;
+  if (this->syntax() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      6, this->syntax(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Type)
+}
+
+::google::protobuf::uint8* Type::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Type.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.Field fields = 2;
+  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->fields(i), target);
+  }
+
+  // repeated string oneofs = 3;
+  for (int i = 0; i < this->oneofs_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->oneofs(i).data(), this->oneofs(i).length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Type.oneofs");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(3, this->oneofs(i), target);
+  }
+
+  // repeated .google.protobuf.Option options = 4;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, this->options(i), target);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        5, *this->source_context_, target);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 6;
+  if (this->syntax() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      6, this->syntax(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type)
+  return target;
+}
+
+int Type::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  if (this->has_source_context()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        *this->source_context_);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 6;
+  if (this->syntax() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+  }
+
+  // repeated .google.protobuf.Field fields = 2;
+  total_size += 1 * this->fields_size();
+  for (int i = 0; i < this->fields_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->fields(i));
+  }
+
+  // repeated string oneofs = 3;
+  total_size += 1 * this->oneofs_size();
+  for (int i = 0; i < this->oneofs_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->oneofs(i));
+  }
+
+  // repeated .google.protobuf.Option options = 4;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Type::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Type* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Type>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Type)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Type)
+    MergeFrom(*source);
+  }
+}
+
+void Type::MergeFrom(const Type& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  fields_.MergeFrom(from.fields_);
+  oneofs_.MergeFrom(from.oneofs_);
+  options_.MergeFrom(from.options_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.has_source_context()) {
+    mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+  }
+  if (from.syntax() != 0) {
+    set_syntax(from.syntax());
+  }
+}
+
+void Type::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Type)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Type::CopyFrom(const Type& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Type)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Type::IsInitialized() const {
+
+  return true;
+}
+
+void Type::Swap(Type* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Type::InternalSwap(Type* other) {
+  name_.Swap(&other->name_);
+  fields_.UnsafeArenaSwap(&other->fields_);
+  oneofs_.UnsafeArenaSwap(&other->oneofs_);
+  options_.UnsafeArenaSwap(&other->options_);
+  std::swap(source_context_, other->source_context_);
+  std::swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Type::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Type_descriptor_;
+  metadata.reflection = Type_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Type
+
+// optional string name = 1;
+void Type::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Type::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Type::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
+}
+ void Type::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
+}
+ void Type::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
+}
+ ::std::string* Type::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Type::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Type.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Type::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
+}
+
+// repeated .google.protobuf.Field fields = 2;
+int Type::fields_size() const {
+  return fields_.size();
+}
+void Type::clear_fields() {
+  fields_.Clear();
+}
+const ::google::protobuf::Field& Type::fields(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
+  return fields_.Get(index);
+}
+::google::protobuf::Field* Type::mutable_fields(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
+  return fields_.Mutable(index);
+}
+::google::protobuf::Field* Type::add_fields() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
+  return fields_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+Type::mutable_fields() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
+  return &fields_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+  return fields_;
+}
+
+// repeated string oneofs = 3;
+int Type::oneofs_size() const {
+  return oneofs_.size();
+}
+void Type::clear_oneofs() {
+  oneofs_.Clear();
+}
+ const ::std::string& Type::oneofs(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs)
+  return oneofs_.Get(index);
+}
+ ::std::string* Type::mutable_oneofs(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs)
+  return oneofs_.Mutable(index);
+}
+ void Type::set_oneofs(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
+  oneofs_.Mutable(index)->assign(value);
+}
+ void Type::set_oneofs(int index, const char* value) {
+  oneofs_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
+}
+ void Type::set_oneofs(int index, const char* value, size_t size) {
+  oneofs_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
+}
+ ::std::string* Type::add_oneofs() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs)
+  return oneofs_.Add();
+}
+ void Type::add_oneofs(const ::std::string& value) {
+  oneofs_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
+}
+ void Type::add_oneofs(const char* value) {
+  oneofs_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
+}
+ void Type::add_oneofs(const char* value, size_t size) {
+  oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+Type::oneofs() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs)
+  return oneofs_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+Type::mutable_oneofs() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs)
+  return &oneofs_;
+}
+
+// repeated .google.protobuf.Option options = 4;
+int Type::options_size() const {
+  return options_.size();
+}
+void Type::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& Type::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* Type::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* Type::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Type::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+  return options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+bool Type::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+void Type::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+const ::google::protobuf::SourceContext& Type::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+::google::protobuf::SourceContext* Type::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
+  return source_context_;
+}
+::google::protobuf::SourceContext* Type::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
+}
+
+// optional .google.protobuf.Syntax syntax = 6;
+void Type::clear_syntax() {
+  syntax_ = 0;
+}
+ ::google::protobuf::Syntax Type::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Type::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Field_Kind_descriptor_;
+}
+bool Field_Kind_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const Field_Kind Field::TYPE_UNKNOWN;
+const Field_Kind Field::TYPE_DOUBLE;
+const Field_Kind Field::TYPE_FLOAT;
+const Field_Kind Field::TYPE_INT64;
+const Field_Kind Field::TYPE_UINT64;
+const Field_Kind Field::TYPE_INT32;
+const Field_Kind Field::TYPE_FIXED64;
+const Field_Kind Field::TYPE_FIXED32;
+const Field_Kind Field::TYPE_BOOL;
+const Field_Kind Field::TYPE_STRING;
+const Field_Kind Field::TYPE_GROUP;
+const Field_Kind Field::TYPE_MESSAGE;
+const Field_Kind Field::TYPE_BYTES;
+const Field_Kind Field::TYPE_UINT32;
+const Field_Kind Field::TYPE_ENUM;
+const Field_Kind Field::TYPE_SFIXED32;
+const Field_Kind Field::TYPE_SFIXED64;
+const Field_Kind Field::TYPE_SINT32;
+const Field_Kind Field::TYPE_SINT64;
+const Field_Kind Field::Kind_MIN;
+const Field_Kind Field::Kind_MAX;
+const int Field::Kind_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Field_Cardinality_descriptor_;
+}
+bool Field_Cardinality_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const Field_Cardinality Field::CARDINALITY_UNKNOWN;
+const Field_Cardinality Field::CARDINALITY_OPTIONAL;
+const Field_Cardinality Field::CARDINALITY_REQUIRED;
+const Field_Cardinality Field::CARDINALITY_REPEATED;
+const Field_Cardinality Field::Cardinality_MIN;
+const Field_Cardinality Field::Cardinality_MAX;
+const int Field::Cardinality_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Field::kKindFieldNumber;
+const int Field::kCardinalityFieldNumber;
+const int Field::kNumberFieldNumber;
+const int Field::kNameFieldNumber;
+const int Field::kTypeUrlFieldNumber;
+const int Field::kOneofIndexFieldNumber;
+const int Field::kPackedFieldNumber;
+const int Field::kOptionsFieldNumber;
+const int Field::kJsonNameFieldNumber;
+const int Field::kDefaultValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Field::Field()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Field)
+}
+
+void Field::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Field::Field(const Field& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
+}
+
+void Field::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  kind_ = 0;
+  cardinality_ = 0;
+  number_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  oneof_index_ = 0;
+  packed_ = false;
+  json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Field::~Field() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Field)
+  SharedDtor();
+}
+
+void Field::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void Field::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Field::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Field_descriptor_;
+}
+
+const Field& Field::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  return *default_instance_;
+}
+
+Field* Field::default_instance_ = NULL;
+
+Field* Field::New(::google::protobuf::Arena* arena) const {
+  Field* n = new Field;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Field::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+  _Pragma("clang diagnostic push") \
+  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+  __builtin_offsetof(Field, f) \
+  _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Field*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+  ::memset(&first, 0,\
+           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+  ZR_(kind_, cardinality_);
+  ZR_(number_, oneof_index_);
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  packed_ = false;
+  json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+
+#undef ZR_HELPER_
+#undef ZR_
+
+  options_.Clear();
+}
+
+bool Field::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Field)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional .google.protobuf.Field.Kind kind = 1;
+      case 1: {
+        if (tag == 8) {
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_kind(static_cast< ::google::protobuf::Field_Kind >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_cardinality;
+        break;
+      }
+
+      // optional .google.protobuf.Field.Cardinality cardinality = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_cardinality:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_cardinality(static_cast< ::google::protobuf::Field_Cardinality >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_number;
+        break;
+      }
+
+      // optional int32 number = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_number:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &number_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(34)) goto parse_name;
+        break;
+      }
+
+      // optional string name = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Field.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(50)) goto parse_type_url;
+        break;
+      }
+
+      // optional string type_url = 6;
+      case 6: {
+        if (tag == 50) {
+         parse_type_url:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_type_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->type_url().data(), this->type_url().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Field.type_url"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(56)) goto parse_oneof_index;
+        break;
+      }
+
+      // optional int32 oneof_index = 7;
+      case 7: {
+        if (tag == 56) {
+         parse_oneof_index:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &oneof_index_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(64)) goto parse_packed;
+        break;
+      }
+
+      // optional bool packed = 8;
+      case 8: {
+        if (tag == 64) {
+         parse_packed:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &packed_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(74)) goto parse_options;
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 9;
+      case 9: {
+        if (tag == 74) {
+         parse_options:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(74)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(82)) goto parse_json_name;
+        break;
+      }
+
+      // optional string json_name = 10;
+      case 10: {
+        if (tag == 82) {
+         parse_json_name:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_json_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->json_name().data(), this->json_name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Field.json_name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(90)) goto parse_default_value;
+        break;
+      }
+
+      // optional string default_value = 11;
+      case 11: {
+        if (tag == 90) {
+         parse_default_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_default_value()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->default_value().data(), this->default_value().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Field.default_value"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Field)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Field)
+  return false;
+#undef DO_
+}
+
+void Field::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Field)
+  // optional .google.protobuf.Field.Kind kind = 1;
+  if (this->kind() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->kind(), output);
+  }
+
+  // optional .google.protobuf.Field.Cardinality cardinality = 2;
+  if (this->cardinality() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->cardinality(), output);
+  }
+
+  // optional int32 number = 3;
+  if (this->number() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
+  }
+
+  // optional string name = 4;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->name(), output);
+  }
+
+  // optional string type_url = 6;
+  if (this->type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->type_url().data(), this->type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.type_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      6, this->type_url(), output);
+  }
+
+  // optional int32 oneof_index = 7;
+  if (this->oneof_index() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->oneof_index(), output);
+  }
+
+  // optional bool packed = 8;
+  if (this->packed() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(8, this->packed(), output);
+  }
+
+  // repeated .google.protobuf.Option options = 9;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      9, this->options(i), output);
+  }
+
+  // optional string json_name = 10;
+  if (this->json_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->json_name().data(), this->json_name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.json_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      10, this->json_name(), output);
+  }
+
+  // optional string default_value = 11;
+  if (this->default_value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.default_value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      11, this->default_value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Field)
+}
+
+::google::protobuf::uint8* Field::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
+  // optional .google.protobuf.Field.Kind kind = 1;
+  if (this->kind() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->kind(), target);
+  }
+
+  // optional .google.protobuf.Field.Cardinality cardinality = 2;
+  if (this->cardinality() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->cardinality(), target);
+  }
+
+  // optional int32 number = 3;
+  if (this->number() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
+  }
+
+  // optional string name = 4;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->name(), target);
+  }
+
+  // optional string type_url = 6;
+  if (this->type_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->type_url().data(), this->type_url().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.type_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        6, this->type_url(), target);
+  }
+
+  // optional int32 oneof_index = 7;
+  if (this->oneof_index() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(7, this->oneof_index(), target);
+  }
+
+  // optional bool packed = 8;
+  if (this->packed() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(8, this->packed(), target);
+  }
+
+  // repeated .google.protobuf.Option options = 9;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        9, this->options(i), target);
+  }
+
+  // optional string json_name = 10;
+  if (this->json_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->json_name().data(), this->json_name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.json_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        10, this->json_name(), target);
+  }
+
+  // optional string default_value = 11;
+  if (this->default_value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->default_value().data(), this->default_value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Field.default_value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        11, this->default_value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field)
+  return target;
+}
+
+int Field::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field)
+  int total_size = 0;
+
+  // optional .google.protobuf.Field.Kind kind = 1;
+  if (this->kind() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->kind());
+  }
+
+  // optional .google.protobuf.Field.Cardinality cardinality = 2;
+  if (this->cardinality() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->cardinality());
+  }
+
+  // optional int32 number = 3;
+  if (this->number() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->number());
+  }
+
+  // optional string name = 4;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional string type_url = 6;
+  if (this->type_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->type_url());
+  }
+
+  // optional int32 oneof_index = 7;
+  if (this->oneof_index() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->oneof_index());
+  }
+
+  // optional bool packed = 8;
+  if (this->packed() != 0) {
+    total_size += 1 + 1;
+  }
+
+  // optional string json_name = 10;
+  if (this->json_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->json_name());
+  }
+
+  // optional string default_value = 11;
+  if (this->default_value().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->default_value());
+  }
+
+  // repeated .google.protobuf.Option options = 9;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Field::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Field* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Field>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Field)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Field)
+    MergeFrom(*source);
+  }
+}
+
+void Field::MergeFrom(const Field& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  options_.MergeFrom(from.options_);
+  if (from.kind() != 0) {
+    set_kind(from.kind());
+  }
+  if (from.cardinality() != 0) {
+    set_cardinality(from.cardinality());
+  }
+  if (from.number() != 0) {
+    set_number(from.number());
+  }
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.type_url().size() > 0) {
+
+    type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
+  }
+  if (from.oneof_index() != 0) {
+    set_oneof_index(from.oneof_index());
+  }
+  if (from.packed() != 0) {
+    set_packed(from.packed());
+  }
+  if (from.json_name().size() > 0) {
+
+    json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_);
+  }
+  if (from.default_value().size() > 0) {
+
+    default_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.default_value_);
+  }
+}
+
+void Field::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Field)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Field::CopyFrom(const Field& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Field)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Field::IsInitialized() const {
+
+  return true;
+}
+
+void Field::Swap(Field* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Field::InternalSwap(Field* other) {
+  std::swap(kind_, other->kind_);
+  std::swap(cardinality_, other->cardinality_);
+  std::swap(number_, other->number_);
+  name_.Swap(&other->name_);
+  type_url_.Swap(&other->type_url_);
+  std::swap(oneof_index_, other->oneof_index_);
+  std::swap(packed_, other->packed_);
+  options_.UnsafeArenaSwap(&other->options_);
+  json_name_.Swap(&other->json_name_);
+  default_value_.Swap(&other->default_value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Field::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Field_descriptor_;
+  metadata.reflection = Field_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Field
+
+// optional .google.protobuf.Field.Kind kind = 1;
+void Field::clear_kind() {
+  kind_ = 0;
+}
+ ::google::protobuf::Field_Kind Field::kind() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.kind)
+  return static_cast< ::google::protobuf::Field_Kind >(kind_);
+}
+ void Field::set_kind(::google::protobuf::Field_Kind value) {
+  
+  kind_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.kind)
+}
+
+// optional .google.protobuf.Field.Cardinality cardinality = 2;
+void Field::clear_cardinality() {
+  cardinality_ = 0;
+}
+ ::google::protobuf::Field_Cardinality Field::cardinality() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality)
+  return static_cast< ::google::protobuf::Field_Cardinality >(cardinality_);
+}
+ void Field::set_cardinality(::google::protobuf::Field_Cardinality value) {
+  
+  cardinality_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality)
+}
+
+// optional int32 number = 3;
+void Field::clear_number() {
+  number_ = 0;
+}
+ ::google::protobuf::int32 Field::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
+  return number_;
+}
+ void Field::set_number(::google::protobuf::int32 value) {
+  
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
+}
+
+// optional string name = 4;
+void Field::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
+}
+ void Field::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
+}
+ void Field::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
+}
+ ::std::string* Field::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
+}
+
+// optional string type_url = 6;
+void Field::clear_type_url() {
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
+  return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_type_url(const ::std::string& value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
+}
+ void Field::set_type_url(const char* value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
+}
+ void Field::set_type_url(const char* value, size_t size) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
+}
+ ::std::string* Field::mutable_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
+  return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url)
+  
+  return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_type_url(::std::string* type_url) {
+  if (type_url != NULL) {
+    
+  } else {
+    
+  }
+  type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
+}
+
+// optional int32 oneof_index = 7;
+void Field::clear_oneof_index() {
+  oneof_index_ = 0;
+}
+ ::google::protobuf::int32 Field::oneof_index() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
+  return oneof_index_;
+}
+ void Field::set_oneof_index(::google::protobuf::int32 value) {
+  
+  oneof_index_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
+}
+
+// optional bool packed = 8;
+void Field::clear_packed() {
+  packed_ = false;
+}
+ bool Field::packed() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.packed)
+  return packed_;
+}
+ void Field::set_packed(bool value) {
+  
+  packed_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.packed)
+}
+
+// repeated .google.protobuf.Option options = 9;
+int Field::options_size() const {
+  return options_.size();
+}
+void Field::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& Field::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* Field::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* Field::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Field::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Field.options)
+  return options_;
+}
+
+// optional string json_name = 10;
+void Field::clear_json_name() {
+  json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::json_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
+  return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_json_name(const ::std::string& value) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
+}
+ void Field::set_json_name(const char* value) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
+}
+ void Field::set_json_name(const char* value, size_t size) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
+}
+ ::std::string* Field::mutable_json_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name)
+  return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_json_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name)
+  
+  return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_json_name(::std::string* json_name) {
+  if (json_name != NULL) {
+    
+  } else {
+    
+  }
+  json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name)
+}
+
+// optional string default_value = 11;
+void Field::clear_default_value() {
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::default_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value)
+  return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_default_value(const ::std::string& value) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
+}
+ void Field::set_default_value(const char* value) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.default_value)
+}
+ void Field::set_default_value(const char* value, size_t size) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.default_value)
+}
+ ::std::string* Field::mutable_default_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.default_value)
+  return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_default_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value)
+  
+  return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_default_value(::std::string* default_value) {
+  if (default_value != NULL) {
+    
+  } else {
+    
+  }
+  default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.default_value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Enum::kNameFieldNumber;
+const int Enum::kEnumvalueFieldNumber;
+const int Enum::kOptionsFieldNumber;
+const int Enum::kSourceContextFieldNumber;
+const int Enum::kSyntaxFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Enum::Enum()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Enum)
+}
+
+void Enum::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+  source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Enum::Enum(const Enum& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum)
+}
+
+void Enum::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  source_context_ = NULL;
+  syntax_ = 0;
+}
+
+Enum::~Enum() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Enum)
+  SharedDtor();
+}
+
+void Enum::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete source_context_;
+  }
+}
+
+void Enum::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Enum::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Enum_descriptor_;
+}
+
+const Enum& Enum::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  return *default_instance_;
+}
+
+Enum* Enum::default_instance_ = NULL;
+
+Enum* Enum::New(::google::protobuf::Arena* arena) const {
+  Enum* n = new Enum;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Enum::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+  syntax_ = 0;
+  enumvalue_.Clear();
+  options_.Clear();
+}
+
+bool Enum::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Enum)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Enum.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_enumvalue;
+        break;
+      }
+
+      // repeated .google.protobuf.EnumValue enumvalue = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_enumvalue:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_enumvalue:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_enumvalue()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_loop_enumvalue;
+        if (input->ExpectTag(26)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 3;
+      case 3: {
+        if (tag == 26) {
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectTag(34)) goto parse_source_context;
+        break;
+      }
+
+      // optional .google.protobuf.SourceContext source_context = 4;
+      case 4: {
+        if (tag == 34) {
+         parse_source_context:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_context()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_syntax;
+        break;
+      }
+
+      // optional .google.protobuf.Syntax syntax = 5;
+      case 5: {
+        if (tag == 40) {
+         parse_syntax:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Enum)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Enum)
+  return false;
+#undef DO_
+}
+
+void Enum::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Enum)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Enum.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // repeated .google.protobuf.EnumValue enumvalue = 2;
+  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, this->enumvalue(i), output);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, this->options(i), output);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 4;
+  if (this->has_source_context()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, *this->source_context_, output);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 5;
+  if (this->syntax() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      5, this->syntax(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Enum)
+}
+
+::google::protobuf::uint8* Enum::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Enum.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // repeated .google.protobuf.EnumValue enumvalue = 2;
+  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->enumvalue(i), target);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(i), target);
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 4;
+  if (this->has_source_context()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        4, *this->source_context_, target);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 5;
+  if (this->syntax() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      5, this->syntax(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum)
+  return target;
+}
+
+int Enum::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional .google.protobuf.SourceContext source_context = 4;
+  if (this->has_source_context()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        *this->source_context_);
+  }
+
+  // optional .google.protobuf.Syntax syntax = 5;
+  if (this->syntax() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+  }
+
+  // repeated .google.protobuf.EnumValue enumvalue = 2;
+  total_size += 1 * this->enumvalue_size();
+  for (int i = 0; i < this->enumvalue_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->enumvalue(i));
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Enum::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Enum* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Enum)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Enum)
+    MergeFrom(*source);
+  }
+}
+
+void Enum::MergeFrom(const Enum& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  enumvalue_.MergeFrom(from.enumvalue_);
+  options_.MergeFrom(from.options_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.has_source_context()) {
+    mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+  }
+  if (from.syntax() != 0) {
+    set_syntax(from.syntax());
+  }
+}
+
+void Enum::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Enum)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Enum::CopyFrom(const Enum& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Enum)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Enum::IsInitialized() const {
+
+  return true;
+}
+
+void Enum::Swap(Enum* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Enum::InternalSwap(Enum* other) {
+  name_.Swap(&other->name_);
+  enumvalue_.UnsafeArenaSwap(&other->enumvalue_);
+  options_.UnsafeArenaSwap(&other->options_);
+  std::swap(source_context_, other->source_context_);
+  std::swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Enum::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Enum_descriptor_;
+  metadata.reflection = Enum_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Enum
+
+// optional string name = 1;
+void Enum::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Enum::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Enum::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
+}
+ void Enum::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
+}
+ void Enum::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
+}
+ ::std::string* Enum::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Enum::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Enum.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Enum::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
+}
+
+// repeated .google.protobuf.EnumValue enumvalue = 2;
+int Enum::enumvalue_size() const {
+  return enumvalue_.size();
+}
+void Enum::clear_enumvalue() {
+  enumvalue_.Clear();
+}
+const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Get(index);
+}
+::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Mutable(index);
+}
+::google::protobuf::EnumValue* Enum::add_enumvalue() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+Enum::mutable_enumvalue() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
+  return &enumvalue_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+  return enumvalue_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+int Enum::options_size() const {
+  return options_.size();
+}
+void Enum::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& Enum::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* Enum::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* Enum::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Enum::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+  return options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 4;
+bool Enum::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+void Enum::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+const ::google::protobuf::SourceContext& Enum::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+::google::protobuf::SourceContext* Enum::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
+  return source_context_;
+}
+::google::protobuf::SourceContext* Enum::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
+}
+
+// optional .google.protobuf.Syntax syntax = 5;
+void Enum::clear_syntax() {
+  syntax_ = 0;
+}
+ ::google::protobuf::Syntax Enum::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Enum::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Enum.syntax)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EnumValue::kNameFieldNumber;
+const int EnumValue::kNumberFieldNumber;
+const int EnumValue::kOptionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EnumValue::EnumValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.EnumValue)
+}
+
+void EnumValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+EnumValue::EnumValue(const EnumValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue)
+}
+
+void EnumValue::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  number_ = 0;
+}
+
+EnumValue::~EnumValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.EnumValue)
+  SharedDtor();
+}
+
+void EnumValue::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+  }
+}
+
+void EnumValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return EnumValue_descriptor_;
+}
+
+const EnumValue& EnumValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  return *default_instance_;
+}
+
+EnumValue* EnumValue::default_instance_ = NULL;
+
+EnumValue* EnumValue::New(::google::protobuf::Arena* arena) const {
+  EnumValue* n = new EnumValue;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void EnumValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  number_ = 0;
+  options_.Clear();
+}
+
+bool EnumValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.EnumValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.EnumValue.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_number;
+        break;
+      }
+
+      // optional int32 number = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_number:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &number_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_options;
+        break;
+      }
+
+      // repeated .google.protobuf.Option options = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_options:
+          DO_(input->IncrementRecursionDepth());
+         parse_loop_options:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+                input, add_options()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_loop_options;
+        input->UnsafeDecrementRecursionDepth();
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.EnumValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValue)
+  return false;
+#undef DO_
+}
+
+void EnumValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValue)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.EnumValue.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional int32 number = 2;
+  if (this->number() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, this->options(i), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValue)
+}
+
+::google::protobuf::uint8* EnumValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.EnumValue.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional int32 number = 2;
+  if (this->number() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->options(i), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue)
+  return target;
+}
+
+int EnumValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional int32 number = 2;
+  if (this->number() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->number());
+  }
+
+  // repeated .google.protobuf.Option options = 3;
+  total_size += 1 * this->options_size();
+  for (int i = 0; i < this->options_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->options(i));
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValue)
+    MergeFrom(*source);
+  }
+}
+
+void EnumValue::MergeFrom(const EnumValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  options_.MergeFrom(from.options_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.number() != 0) {
+    set_number(from.number());
+  }
+}
+
+void EnumValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValue::CopyFrom(const EnumValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EnumValue::IsInitialized() const {
+
+  return true;
+}
+
+void EnumValue::Swap(EnumValue* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EnumValue::InternalSwap(EnumValue* other) {
+  name_.Swap(&other->name_);
+  std::swap(number_, other->number_);
+  options_.UnsafeArenaSwap(&other->options_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata EnumValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = EnumValue_descriptor_;
+  metadata.reflection = EnumValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValue
+
+// optional string name = 1;
+void EnumValue::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& EnumValue::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValue::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
+}
+ void EnumValue::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
+}
+ void EnumValue::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
+}
+ ::std::string* EnumValue::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValue::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValue::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
+}
+
+// optional int32 number = 2;
+void EnumValue::clear_number() {
+  number_ = 0;
+}
+ ::google::protobuf::int32 EnumValue::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
+  return number_;
+}
+ void EnumValue::set_number(::google::protobuf::int32 value) {
+  
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
+}
+
+// repeated .google.protobuf.Option options = 3;
+int EnumValue::options_size() const {
+  return options_.size();
+}
+void EnumValue::clear_options() {
+  options_.Clear();
+}
+const ::google::protobuf::Option& EnumValue::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
+  return options_.Get(index);
+}
+::google::protobuf::Option* EnumValue::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
+  return options_.Mutable(index);
+}
+::google::protobuf::Option* EnumValue::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
+  return options_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+EnumValue::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
+  return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+  return options_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Option::kNameFieldNumber;
+const int Option::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Option::Option()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Option)
+}
+
+void Option::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+  value_ = const_cast< ::google::protobuf::Any*>(&::google::protobuf::Any::default_instance());
+}
+
+Option::Option(const Option& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Option)
+}
+
+void Option::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  value_ = NULL;
+}
+
+Option::~Option() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Option)
+  SharedDtor();
+}
+
+void Option::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != default_instance_) {
+    delete value_;
+  }
+}
+
+void Option::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Option::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Option_descriptor_;
+}
+
+const Option& Option::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  return *default_instance_;
+}
+
+Option* Option::default_instance_ = NULL;
+
+Option* Option::New(::google::protobuf::Arena* arena) const {
+  Option* n = new Option;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Option::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+  value_ = NULL;
+}
+
+bool Option::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Option)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.Option.name"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_value;
+        break;
+      }
+
+      // optional .google.protobuf.Any value = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Option)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Option)
+  return false;
+#undef DO_
+}
+
+void Option::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Option)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Option.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // optional .google.protobuf.Any value = 2;
+  if (this->has_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, *this->value_, output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Option)
+}
+
+::google::protobuf::uint8* Option::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.Option.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // optional .google.protobuf.Any value = 2;
+  if (this->has_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, *this->value_, target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Option)
+  return target;
+}
+
+int Option::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option)
+  int total_size = 0;
+
+  // optional string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // optional .google.protobuf.Any value = 2;
+  if (this->has_value()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        *this->value_);
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Option::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Option* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Option>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Option)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Option)
+    MergeFrom(*source);
+  }
+}
+
+void Option::MergeFrom(const Option& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.has_value()) {
+    mutable_value()->::google::protobuf::Any::MergeFrom(from.value());
+  }
+}
+
+void Option::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Option)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Option::CopyFrom(const Option& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Option)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Option::IsInitialized() const {
+
+  return true;
+}
+
+void Option::Swap(Option* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Option::InternalSwap(Option* other) {
+  name_.Swap(&other->name_);
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Option::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Option_descriptor_;
+  metadata.reflection = Option_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Option
+
+// optional string name = 1;
+void Option::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Option::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Option::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
+}
+ void Option::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
+}
+ void Option::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
+}
+ ::std::string* Option::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Option::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Option.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Option::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
+}
+
+// optional .google.protobuf.Any value = 2;
+bool Option::has_value() const {
+  return !_is_default_instance_ && value_ != NULL;
+}
+void Option::clear_value() {
+  if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+  value_ = NULL;
+}
+const ::google::protobuf::Any& Option::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
+  return value_ != NULL ? *value_ : *default_instance_->value_;
+}
+::google::protobuf::Any* Option::mutable_value() {
+  
+  if (value_ == NULL) {
+    value_ = new ::google::protobuf::Any;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
+  return value_;
+}
+::google::protobuf::Any* Option::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Option.value)
+  
+  ::google::protobuf::Any* temp = value_;
+  value_ = NULL;
+  return temp;
+}
+void Option::set_allocated_value(::google::protobuf::Any* value) {
+  delete value_;
+  value_ = value;
+  if (value) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/type.pb.h b/src/third_party/protobuf-3/src/google/protobuf/type.pb.h
new file mode 100644
index 0000000..4255fa8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/type.pb.h
@@ -0,0 +1,1731 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/source_context.pb.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+class Enum;
+class EnumValue;
+class Field;
+class Option;
+class Type;
+
+enum Field_Kind {
+  Field_Kind_TYPE_UNKNOWN = 0,
+  Field_Kind_TYPE_DOUBLE = 1,
+  Field_Kind_TYPE_FLOAT = 2,
+  Field_Kind_TYPE_INT64 = 3,
+  Field_Kind_TYPE_UINT64 = 4,
+  Field_Kind_TYPE_INT32 = 5,
+  Field_Kind_TYPE_FIXED64 = 6,
+  Field_Kind_TYPE_FIXED32 = 7,
+  Field_Kind_TYPE_BOOL = 8,
+  Field_Kind_TYPE_STRING = 9,
+  Field_Kind_TYPE_GROUP = 10,
+  Field_Kind_TYPE_MESSAGE = 11,
+  Field_Kind_TYPE_BYTES = 12,
+  Field_Kind_TYPE_UINT32 = 13,
+  Field_Kind_TYPE_ENUM = 14,
+  Field_Kind_TYPE_SFIXED32 = 15,
+  Field_Kind_TYPE_SFIXED64 = 16,
+  Field_Kind_TYPE_SINT32 = 17,
+  Field_Kind_TYPE_SINT64 = 18,
+  Field_Kind_Field_Kind_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+  Field_Kind_Field_Kind_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Field_Kind_IsValid(int value);
+const Field_Kind Field_Kind_Kind_MIN = Field_Kind_TYPE_UNKNOWN;
+const Field_Kind Field_Kind_Kind_MAX = Field_Kind_TYPE_SINT64;
+const int Field_Kind_Kind_ARRAYSIZE = Field_Kind_Kind_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor();
+inline const ::std::string& Field_Kind_Name(Field_Kind value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    Field_Kind_descriptor(), value);
+}
+inline bool Field_Kind_Parse(
+    const ::std::string& name, Field_Kind* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<Field_Kind>(
+    Field_Kind_descriptor(), name, value);
+}
+enum Field_Cardinality {
+  Field_Cardinality_CARDINALITY_UNKNOWN = 0,
+  Field_Cardinality_CARDINALITY_OPTIONAL = 1,
+  Field_Cardinality_CARDINALITY_REQUIRED = 2,
+  Field_Cardinality_CARDINALITY_REPEATED = 3,
+  Field_Cardinality_Field_Cardinality_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+  Field_Cardinality_Field_Cardinality_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Field_Cardinality_IsValid(int value);
+const Field_Cardinality Field_Cardinality_Cardinality_MIN = Field_Cardinality_CARDINALITY_UNKNOWN;
+const Field_Cardinality Field_Cardinality_Cardinality_MAX = Field_Cardinality_CARDINALITY_REPEATED;
+const int Field_Cardinality_Cardinality_ARRAYSIZE = Field_Cardinality_Cardinality_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor();
+inline const ::std::string& Field_Cardinality_Name(Field_Cardinality value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    Field_Cardinality_descriptor(), value);
+}
+inline bool Field_Cardinality_Parse(
+    const ::std::string& name, Field_Cardinality* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<Field_Cardinality>(
+    Field_Cardinality_descriptor(), name, value);
+}
+enum Syntax {
+  SYNTAX_PROTO2 = 0,
+  SYNTAX_PROTO3 = 1,
+  Syntax_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+  Syntax_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Syntax_IsValid(int value);
+const Syntax Syntax_MIN = SYNTAX_PROTO2;
+const Syntax Syntax_MAX = SYNTAX_PROTO3;
+const int Syntax_ARRAYSIZE = Syntax_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Syntax_descriptor();
+inline const ::std::string& Syntax_Name(Syntax value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    Syntax_descriptor(), value);
+}
+inline bool Syntax_Parse(
+    const ::std::string& name, Syntax* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<Syntax>(
+    Syntax_descriptor(), name, value);
+}
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
+ public:
+  Type();
+  virtual ~Type();
+
+  Type(const Type& from);
+
+  inline Type& operator=(const Type& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Type& default_instance();
+
+  void Swap(Type* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Type* New() const { return New(NULL); }
+
+  Type* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Type& from);
+  void MergeFrom(const Type& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Type* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.Field fields = 2;
+  int fields_size() const;
+  void clear_fields();
+  static const int kFieldsFieldNumber = 2;
+  const ::google::protobuf::Field& fields(int index) const;
+  ::google::protobuf::Field* mutable_fields(int index);
+  ::google::protobuf::Field* add_fields();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+      mutable_fields();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+      fields() const;
+
+  // repeated string oneofs = 3;
+  int oneofs_size() const;
+  void clear_oneofs();
+  static const int kOneofsFieldNumber = 3;
+  const ::std::string& oneofs(int index) const;
+  ::std::string* mutable_oneofs(int index);
+  void set_oneofs(int index, const ::std::string& value);
+  void set_oneofs(int index, const char* value);
+  void set_oneofs(int index, const char* value, size_t size);
+  ::std::string* add_oneofs();
+  void add_oneofs(const ::std::string& value);
+  void add_oneofs(const char* value);
+  void add_oneofs(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& oneofs() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_oneofs();
+
+  // repeated .google.protobuf.Option options = 4;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 4;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // optional .google.protobuf.SourceContext source_context = 5;
+  bool has_source_context() const;
+  void clear_source_context();
+  static const int kSourceContextFieldNumber = 5;
+  const ::google::protobuf::SourceContext& source_context() const;
+  ::google::protobuf::SourceContext* mutable_source_context();
+  ::google::protobuf::SourceContext* release_source_context();
+  void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+  // optional .google.protobuf.Syntax syntax = 6;
+  void clear_syntax();
+  static const int kSyntaxFieldNumber = 6;
+  ::google::protobuf::Syntax syntax() const;
+  void set_syntax(::google::protobuf::Syntax value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Type)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field > fields_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> oneofs_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  ::google::protobuf::SourceContext* source_context_;
+  int syntax_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+  void InitAsDefaultInstance();
+  static Type* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
+ public:
+  Field();
+  virtual ~Field();
+
+  Field(const Field& from);
+
+  inline Field& operator=(const Field& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Field& default_instance();
+
+  void Swap(Field* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Field* New() const { return New(NULL); }
+
+  Field* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Field& from);
+  void MergeFrom(const Field& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Field* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef Field_Kind Kind;
+  static const Kind TYPE_UNKNOWN =
+    Field_Kind_TYPE_UNKNOWN;
+  static const Kind TYPE_DOUBLE =
+    Field_Kind_TYPE_DOUBLE;
+  static const Kind TYPE_FLOAT =
+    Field_Kind_TYPE_FLOAT;
+  static const Kind TYPE_INT64 =
+    Field_Kind_TYPE_INT64;
+  static const Kind TYPE_UINT64 =
+    Field_Kind_TYPE_UINT64;
+  static const Kind TYPE_INT32 =
+    Field_Kind_TYPE_INT32;
+  static const Kind TYPE_FIXED64 =
+    Field_Kind_TYPE_FIXED64;
+  static const Kind TYPE_FIXED32 =
+    Field_Kind_TYPE_FIXED32;
+  static const Kind TYPE_BOOL =
+    Field_Kind_TYPE_BOOL;
+  static const Kind TYPE_STRING =
+    Field_Kind_TYPE_STRING;
+  static const Kind TYPE_GROUP =
+    Field_Kind_TYPE_GROUP;
+  static const Kind TYPE_MESSAGE =
+    Field_Kind_TYPE_MESSAGE;
+  static const Kind TYPE_BYTES =
+    Field_Kind_TYPE_BYTES;
+  static const Kind TYPE_UINT32 =
+    Field_Kind_TYPE_UINT32;
+  static const Kind TYPE_ENUM =
+    Field_Kind_TYPE_ENUM;
+  static const Kind TYPE_SFIXED32 =
+    Field_Kind_TYPE_SFIXED32;
+  static const Kind TYPE_SFIXED64 =
+    Field_Kind_TYPE_SFIXED64;
+  static const Kind TYPE_SINT32 =
+    Field_Kind_TYPE_SINT32;
+  static const Kind TYPE_SINT64 =
+    Field_Kind_TYPE_SINT64;
+  static inline bool Kind_IsValid(int value) {
+    return Field_Kind_IsValid(value);
+  }
+  static const Kind Kind_MIN =
+    Field_Kind_Kind_MIN;
+  static const Kind Kind_MAX =
+    Field_Kind_Kind_MAX;
+  static const int Kind_ARRAYSIZE =
+    Field_Kind_Kind_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Kind_descriptor() {
+    return Field_Kind_descriptor();
+  }
+  static inline const ::std::string& Kind_Name(Kind value) {
+    return Field_Kind_Name(value);
+  }
+  static inline bool Kind_Parse(const ::std::string& name,
+      Kind* value) {
+    return Field_Kind_Parse(name, value);
+  }
+
+  typedef Field_Cardinality Cardinality;
+  static const Cardinality CARDINALITY_UNKNOWN =
+    Field_Cardinality_CARDINALITY_UNKNOWN;
+  static const Cardinality CARDINALITY_OPTIONAL =
+    Field_Cardinality_CARDINALITY_OPTIONAL;
+  static const Cardinality CARDINALITY_REQUIRED =
+    Field_Cardinality_CARDINALITY_REQUIRED;
+  static const Cardinality CARDINALITY_REPEATED =
+    Field_Cardinality_CARDINALITY_REPEATED;
+  static inline bool Cardinality_IsValid(int value) {
+    return Field_Cardinality_IsValid(value);
+  }
+  static const Cardinality Cardinality_MIN =
+    Field_Cardinality_Cardinality_MIN;
+  static const Cardinality Cardinality_MAX =
+    Field_Cardinality_Cardinality_MAX;
+  static const int Cardinality_ARRAYSIZE =
+    Field_Cardinality_Cardinality_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Cardinality_descriptor() {
+    return Field_Cardinality_descriptor();
+  }
+  static inline const ::std::string& Cardinality_Name(Cardinality value) {
+    return Field_Cardinality_Name(value);
+  }
+  static inline bool Cardinality_Parse(const ::std::string& name,
+      Cardinality* value) {
+    return Field_Cardinality_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // optional .google.protobuf.Field.Kind kind = 1;
+  void clear_kind();
+  static const int kKindFieldNumber = 1;
+  ::google::protobuf::Field_Kind kind() const;
+  void set_kind(::google::protobuf::Field_Kind value);
+
+  // optional .google.protobuf.Field.Cardinality cardinality = 2;
+  void clear_cardinality();
+  static const int kCardinalityFieldNumber = 2;
+  ::google::protobuf::Field_Cardinality cardinality() const;
+  void set_cardinality(::google::protobuf::Field_Cardinality value);
+
+  // optional int32 number = 3;
+  void clear_number();
+  static const int kNumberFieldNumber = 3;
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
+
+  // optional string name = 4;
+  void clear_name();
+  static const int kNameFieldNumber = 4;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional string type_url = 6;
+  void clear_type_url();
+  static const int kTypeUrlFieldNumber = 6;
+  const ::std::string& type_url() const;
+  void set_type_url(const ::std::string& value);
+  void set_type_url(const char* value);
+  void set_type_url(const char* value, size_t size);
+  ::std::string* mutable_type_url();
+  ::std::string* release_type_url();
+  void set_allocated_type_url(::std::string* type_url);
+
+  // optional int32 oneof_index = 7;
+  void clear_oneof_index();
+  static const int kOneofIndexFieldNumber = 7;
+  ::google::protobuf::int32 oneof_index() const;
+  void set_oneof_index(::google::protobuf::int32 value);
+
+  // optional bool packed = 8;
+  void clear_packed();
+  static const int kPackedFieldNumber = 8;
+  bool packed() const;
+  void set_packed(bool value);
+
+  // repeated .google.protobuf.Option options = 9;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 9;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // optional string json_name = 10;
+  void clear_json_name();
+  static const int kJsonNameFieldNumber = 10;
+  const ::std::string& json_name() const;
+  void set_json_name(const ::std::string& value);
+  void set_json_name(const char* value);
+  void set_json_name(const char* value, size_t size);
+  ::std::string* mutable_json_name();
+  ::std::string* release_json_name();
+  void set_allocated_json_name(::std::string* json_name);
+
+  // optional string default_value = 11;
+  void clear_default_value();
+  static const int kDefaultValueFieldNumber = 11;
+  const ::std::string& default_value() const;
+  void set_default_value(const ::std::string& value);
+  void set_default_value(const char* value);
+  void set_default_value(const char* value, size_t size);
+  ::std::string* mutable_default_value();
+  ::std::string* release_default_value();
+  void set_allocated_default_value(::std::string* default_value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Field)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  int kind_;
+  int cardinality_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::int32 number_;
+  ::google::protobuf::int32 oneof_index_;
+  ::google::protobuf::internal::ArenaStringPtr type_url_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  ::google::protobuf::internal::ArenaStringPtr json_name_;
+  ::google::protobuf::internal::ArenaStringPtr default_value_;
+  bool packed_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+  void InitAsDefaultInstance();
+  static Field* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
+ public:
+  Enum();
+  virtual ~Enum();
+
+  Enum(const Enum& from);
+
+  inline Enum& operator=(const Enum& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Enum& default_instance();
+
+  void Swap(Enum* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Enum* New() const { return New(NULL); }
+
+  Enum* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Enum& from);
+  void MergeFrom(const Enum& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Enum* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // repeated .google.protobuf.EnumValue enumvalue = 2;
+  int enumvalue_size() const;
+  void clear_enumvalue();
+  static const int kEnumvalueFieldNumber = 2;
+  const ::google::protobuf::EnumValue& enumvalue(int index) const;
+  ::google::protobuf::EnumValue* mutable_enumvalue(int index);
+  ::google::protobuf::EnumValue* add_enumvalue();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+      mutable_enumvalue();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+      enumvalue() const;
+
+  // repeated .google.protobuf.Option options = 3;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // optional .google.protobuf.SourceContext source_context = 4;
+  bool has_source_context() const;
+  void clear_source_context();
+  static const int kSourceContextFieldNumber = 4;
+  const ::google::protobuf::SourceContext& source_context() const;
+  ::google::protobuf::SourceContext* mutable_source_context();
+  ::google::protobuf::SourceContext* release_source_context();
+  void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+  // optional .google.protobuf.Syntax syntax = 5;
+  void clear_syntax();
+  static const int kSyntaxFieldNumber = 5;
+  ::google::protobuf::Syntax syntax() const;
+  void set_syntax(::google::protobuf::Syntax value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Enum)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue > enumvalue_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  ::google::protobuf::SourceContext* source_context_;
+  int syntax_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+  void InitAsDefaultInstance();
+  static Enum* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumValue : public ::google::protobuf::Message {
+ public:
+  EnumValue();
+  virtual ~EnumValue();
+
+  EnumValue(const EnumValue& from);
+
+  inline EnumValue& operator=(const EnumValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const EnumValue& default_instance();
+
+  void Swap(EnumValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline EnumValue* New() const { return New(NULL); }
+
+  EnumValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const EnumValue& from);
+  void MergeFrom(const EnumValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(EnumValue* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional int32 number = 2;
+  void clear_number();
+  static const int kNumberFieldNumber = 2;
+  ::google::protobuf::int32 number() const;
+  void set_number(::google::protobuf::int32 value);
+
+  // repeated .google.protobuf.Option options = 3;
+  int options_size() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::Option& options(int index) const;
+  ::google::protobuf::Option* mutable_options(int index);
+  ::google::protobuf::Option* add_options();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+      mutable_options();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+      options() const;
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.EnumValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+  ::google::protobuf::int32 number_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+  void InitAsDefaultInstance();
+  static EnumValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Option : public ::google::protobuf::Message {
+ public:
+  Option();
+  virtual ~Option();
+
+  Option(const Option& from);
+
+  inline Option& operator=(const Option& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Option& default_instance();
+
+  void Swap(Option* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Option* New() const { return New(NULL); }
+
+  Option* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Option& from);
+  void MergeFrom(const Option& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Option* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // optional .google.protobuf.Any value = 2;
+  bool has_value() const;
+  void clear_value();
+  static const int kValueFieldNumber = 2;
+  const ::google::protobuf::Any& value() const;
+  ::google::protobuf::Any* mutable_value();
+  ::google::protobuf::Any* release_value();
+  void set_allocated_value(::google::protobuf::Any* value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Option)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::Any* value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+  void InitAsDefaultInstance();
+  static Option* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Type
+
+// optional string name = 1;
+inline void Type::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Type::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Type::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
+}
+inline void Type::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
+}
+inline void Type::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
+}
+inline ::std::string* Type::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Type::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Type.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Type::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
+}
+
+// repeated .google.protobuf.Field fields = 2;
+inline int Type::fields_size() const {
+  return fields_.size();
+}
+inline void Type::clear_fields() {
+  fields_.Clear();
+}
+inline const ::google::protobuf::Field& Type::fields(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
+  return fields_.Get(index);
+}
+inline ::google::protobuf::Field* Type::mutable_fields(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
+  return fields_.Mutable(index);
+}
+inline ::google::protobuf::Field* Type::add_fields() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
+  return fields_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+Type::mutable_fields() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
+  return &fields_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+  return fields_;
+}
+
+// repeated string oneofs = 3;
+inline int Type::oneofs_size() const {
+  return oneofs_.size();
+}
+inline void Type::clear_oneofs() {
+  oneofs_.Clear();
+}
+inline const ::std::string& Type::oneofs(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs)
+  return oneofs_.Get(index);
+}
+inline ::std::string* Type::mutable_oneofs(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs)
+  return oneofs_.Mutable(index);
+}
+inline void Type::set_oneofs(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
+  oneofs_.Mutable(index)->assign(value);
+}
+inline void Type::set_oneofs(int index, const char* value) {
+  oneofs_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
+}
+inline void Type::set_oneofs(int index, const char* value, size_t size) {
+  oneofs_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
+}
+inline ::std::string* Type::add_oneofs() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs)
+  return oneofs_.Add();
+}
+inline void Type::add_oneofs(const ::std::string& value) {
+  oneofs_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
+}
+inline void Type::add_oneofs(const char* value) {
+  oneofs_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
+}
+inline void Type::add_oneofs(const char* value, size_t size) {
+  oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+Type::oneofs() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs)
+  return oneofs_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+Type::mutable_oneofs() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs)
+  return &oneofs_;
+}
+
+// repeated .google.protobuf.Option options = 4;
+inline int Type::options_size() const {
+  return options_.size();
+}
+inline void Type::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& Type::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* Type::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Type::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Type::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+  return options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+inline bool Type::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Type::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Type::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Type::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
+  return source_context_;
+}
+inline ::google::protobuf::SourceContext* Type::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+inline void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
+}
+
+// optional .google.protobuf.Syntax syntax = 6;
+inline void Type::clear_syntax() {
+  syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Type::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Type.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Type::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// Field
+
+// optional .google.protobuf.Field.Kind kind = 1;
+inline void Field::clear_kind() {
+  kind_ = 0;
+}
+inline ::google::protobuf::Field_Kind Field::kind() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.kind)
+  return static_cast< ::google::protobuf::Field_Kind >(kind_);
+}
+inline void Field::set_kind(::google::protobuf::Field_Kind value) {
+  
+  kind_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.kind)
+}
+
+// optional .google.protobuf.Field.Cardinality cardinality = 2;
+inline void Field::clear_cardinality() {
+  cardinality_ = 0;
+}
+inline ::google::protobuf::Field_Cardinality Field::cardinality() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality)
+  return static_cast< ::google::protobuf::Field_Cardinality >(cardinality_);
+}
+inline void Field::set_cardinality(::google::protobuf::Field_Cardinality value) {
+  
+  cardinality_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality)
+}
+
+// optional int32 number = 3;
+inline void Field::clear_number() {
+  number_ = 0;
+}
+inline ::google::protobuf::int32 Field::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
+  return number_;
+}
+inline void Field::set_number(::google::protobuf::int32 value) {
+  
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
+}
+
+// optional string name = 4;
+inline void Field::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
+}
+inline void Field::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
+}
+inline void Field::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
+}
+inline ::std::string* Field::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
+}
+
+// optional string type_url = 6;
+inline void Field::clear_type_url() {
+  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::type_url() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
+  return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_type_url(const ::std::string& value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
+}
+inline void Field::set_type_url(const char* value) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
+}
+inline void Field::set_type_url(const char* value, size_t size) {
+  
+  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
+}
+inline ::std::string* Field::mutable_type_url() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
+  return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_type_url() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url)
+  
+  return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_type_url(::std::string* type_url) {
+  if (type_url != NULL) {
+    
+  } else {
+    
+  }
+  type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
+}
+
+// optional int32 oneof_index = 7;
+inline void Field::clear_oneof_index() {
+  oneof_index_ = 0;
+}
+inline ::google::protobuf::int32 Field::oneof_index() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
+  return oneof_index_;
+}
+inline void Field::set_oneof_index(::google::protobuf::int32 value) {
+  
+  oneof_index_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
+}
+
+// optional bool packed = 8;
+inline void Field::clear_packed() {
+  packed_ = false;
+}
+inline bool Field::packed() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.packed)
+  return packed_;
+}
+inline void Field::set_packed(bool value) {
+  
+  packed_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.packed)
+}
+
+// repeated .google.protobuf.Option options = 9;
+inline int Field::options_size() const {
+  return options_.size();
+}
+inline void Field::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& Field::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* Field::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Field::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Field::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Field.options)
+  return options_;
+}
+
+// optional string json_name = 10;
+inline void Field::clear_json_name() {
+  json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::json_name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
+  return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_json_name(const ::std::string& value) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
+}
+inline void Field::set_json_name(const char* value) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
+}
+inline void Field::set_json_name(const char* value, size_t size) {
+  
+  json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
+}
+inline ::std::string* Field::mutable_json_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name)
+  return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_json_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name)
+  
+  return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_json_name(::std::string* json_name) {
+  if (json_name != NULL) {
+    
+  } else {
+    
+  }
+  json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name)
+}
+
+// optional string default_value = 11;
+inline void Field::clear_default_value() {
+  default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::default_value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value)
+  return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_default_value(const ::std::string& value) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
+}
+inline void Field::set_default_value(const char* value) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.default_value)
+}
+inline void Field::set_default_value(const char* value, size_t size) {
+  
+  default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.default_value)
+}
+inline ::std::string* Field::mutable_default_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.default_value)
+  return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_default_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value)
+  
+  return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_default_value(::std::string* default_value) {
+  if (default_value != NULL) {
+    
+  } else {
+    
+  }
+  default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.default_value)
+}
+
+// -------------------------------------------------------------------
+
+// Enum
+
+// optional string name = 1;
+inline void Enum::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Enum::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Enum::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
+}
+inline void Enum::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
+}
+inline void Enum::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
+}
+inline ::std::string* Enum::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Enum::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Enum.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Enum::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
+}
+
+// repeated .google.protobuf.EnumValue enumvalue = 2;
+inline int Enum::enumvalue_size() const {
+  return enumvalue_.size();
+}
+inline void Enum::clear_enumvalue() {
+  enumvalue_.Clear();
+}
+inline const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Get(index);
+}
+inline ::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Mutable(index);
+}
+inline ::google::protobuf::EnumValue* Enum::add_enumvalue() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
+  return enumvalue_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+Enum::mutable_enumvalue() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
+  return &enumvalue_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+  return enumvalue_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int Enum::options_size() const {
+  return options_.size();
+}
+inline void Enum::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& Enum::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* Enum::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Enum::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Enum::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+  return options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 4;
+inline bool Enum::has_source_context() const {
+  return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Enum::clear_source_context() {
+  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+  source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Enum::source_context() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
+  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Enum::mutable_source_context() {
+  
+  if (source_context_ == NULL) {
+    source_context_ = new ::google::protobuf::SourceContext;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
+  return source_context_;
+}
+inline ::google::protobuf::SourceContext* Enum::release_source_context() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context)
+  
+  ::google::protobuf::SourceContext* temp = source_context_;
+  source_context_ = NULL;
+  return temp;
+}
+inline void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+  delete source_context_;
+  source_context_ = source_context;
+  if (source_context) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
+}
+
+// optional .google.protobuf.Syntax syntax = 5;
+inline void Enum::clear_syntax() {
+  syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Enum::syntax() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Enum.syntax)
+  return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Enum::set_syntax(::google::protobuf::Syntax value) {
+  
+  syntax_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Enum.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// EnumValue
+
+// optional string name = 1;
+inline void EnumValue::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EnumValue::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValue::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
+}
+inline void EnumValue::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
+}
+inline void EnumValue::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
+}
+inline ::std::string* EnumValue::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EnumValue::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValue::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
+}
+
+// optional int32 number = 2;
+inline void EnumValue::clear_number() {
+  number_ = 0;
+}
+inline ::google::protobuf::int32 EnumValue::number() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
+  return number_;
+}
+inline void EnumValue::set_number(::google::protobuf::int32 value) {
+  
+  number_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int EnumValue::options_size() const {
+  return options_.size();
+}
+inline void EnumValue::clear_options() {
+  options_.Clear();
+}
+inline const ::google::protobuf::Option& EnumValue::options(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
+  return options_.Get(index);
+}
+inline ::google::protobuf::Option* EnumValue::mutable_options(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
+  return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* EnumValue::add_options() {
+  // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
+  return options_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+EnumValue::mutable_options() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
+  return &options_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+  return options_;
+}
+
+// -------------------------------------------------------------------
+
+// Option
+
+// optional string name = 1;
+inline void Option::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Option::name() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
+  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Option::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
+}
+inline void Option::set_name(const char* value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
+}
+inline void Option::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
+}
+inline ::std::string* Option::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Option::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Option.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Option::set_allocated_name(::std::string* name) {
+  if (name != NULL) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
+}
+
+// optional .google.protobuf.Any value = 2;
+inline bool Option::has_value() const {
+  return !_is_default_instance_ && value_ != NULL;
+}
+inline void Option::clear_value() {
+  if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+  value_ = NULL;
+}
+inline const ::google::protobuf::Any& Option::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
+  return value_ != NULL ? *value_ : *default_instance_->value_;
+}
+inline ::google::protobuf::Any* Option::mutable_value() {
+  
+  if (value_ == NULL) {
+    value_ = new ::google::protobuf::Any;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
+  return value_;
+}
+inline ::google::protobuf::Any* Option::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.Option.value)
+  
+  ::google::protobuf::Any* temp = value_;
+  value_ = NULL;
+  return temp;
+}
+inline void Option::set_allocated_value(::google::protobuf::Any* value) {
+  delete value_;
+  value_ = value;
+  if (value) {
+    
+  } else {
+    
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::google::protobuf::Field_Kind> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Field_Kind>() {
+  return ::google::protobuf::Field_Kind_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::Field_Cardinality> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Field_Cardinality>() {
+  return ::google::protobuf::Field_Cardinality_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::Syntax> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Syntax>() {
+  return ::google::protobuf::Syntax_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+#endif  // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/type.proto b/src/third_party/protobuf-3/src/google/protobuf/type.proto
new file mode 100644
index 0000000..1c9cf53
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/type.proto
@@ -0,0 +1,180 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/source_context.proto";
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TypeProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// A protocol buffer message type.
+message Type {
+  // The fully qualified message name.
+  string name = 1;
+  // The list of fields.
+  repeated Field fields = 2;
+  // The list of types appearing in `oneof` definitions in this type.
+  repeated string oneofs = 3;
+  // The protocol buffer options.
+  repeated Option options = 4;
+  // The source context.
+  SourceContext source_context = 5;
+  // The source syntax.
+  Syntax syntax = 6;
+}
+
+// A single field of a message type.
+message Field {
+  // Basic field types.
+  enum Kind {
+    // Field type unknown.
+    TYPE_UNKNOWN        = 0;
+    // Field type double.
+    TYPE_DOUBLE         = 1;
+    // Field type float.
+    TYPE_FLOAT          = 2;
+    // Field type int64.
+    TYPE_INT64          = 3;
+    // Field type uint64.
+    TYPE_UINT64         = 4;
+    // Field type int32.
+    TYPE_INT32          = 5;
+    // Field type fixed64.
+    TYPE_FIXED64        = 6;
+    // Field type fixed32.
+    TYPE_FIXED32        = 7;
+    // Field type bool.
+    TYPE_BOOL           = 8;
+    // Field type string.
+    TYPE_STRING         = 9;
+    // Field type group. Proto2 syntax only, and deprecated.
+    TYPE_GROUP          = 10;
+    // Field type message.
+    TYPE_MESSAGE        = 11;
+    // Field type bytes.
+    TYPE_BYTES          = 12;
+    // Field type uint32.
+    TYPE_UINT32         = 13;
+    // Field type enum.
+    TYPE_ENUM           = 14;
+    // Field type sfixed32.
+    TYPE_SFIXED32       = 15;
+    // Field type sfixed64.
+    TYPE_SFIXED64       = 16;
+    // Field type sint32.
+    TYPE_SINT32         = 17;
+    // Field type sint64.
+    TYPE_SINT64         = 18;
+  };
+
+  // Whether a field is optional, required, or repeated.
+  enum Cardinality {
+    // For fields with unknown cardinality.
+    CARDINALITY_UNKNOWN = 0;
+    // For optional fields.
+    CARDINALITY_OPTIONAL = 1;
+    // For required fields. Proto2 syntax only.
+    CARDINALITY_REQUIRED = 2;
+    // For repeated fields.
+    CARDINALITY_REPEATED = 3;
+  };
+
+  // The field type.
+  Kind kind = 1;
+  // The field cardinality.
+  Cardinality cardinality = 2;
+  // The field number.
+  int32 number = 3;
+  // The field name.
+  string name = 4;
+  // The field type URL, without the scheme, for message or enumeration
+  // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+  string type_url = 6;
+  // The index of the field type in `Type.oneofs`, for message or enumeration
+  // types. The first type has index 1; zero means the type is not in the list.
+  int32 oneof_index = 7;
+  // Whether to use alternative packed wire representation.
+  bool packed = 8;
+  // The protocol buffer options.
+  repeated Option options = 9;
+  // The field JSON name.
+  string json_name = 10;
+  // The string value of the default value of this field. Proto2 syntax only.
+  string default_value = 11;
+}
+
+// Enum type definition.
+message Enum {
+  // Enum type name.
+  string name = 1;
+  // Enum value definitions.
+  repeated EnumValue enumvalue = 2;
+  // Protocol buffer options.
+  repeated Option options = 3;
+  // The source context.
+  SourceContext source_context = 4;
+  // The source syntax.
+  Syntax syntax = 5;
+}
+
+// Enum value definition.
+message EnumValue {
+  // Enum value name.
+  string name = 1;
+  // Enum value number.
+  int32 number = 2;
+  // Protocol buffer options.
+  repeated Option options = 3;
+}
+
+// A protocol buffer option, which can be attached to a message, field,
+// enumeration, etc.
+message Option {
+  // The option's name. For example, `"java_package"`.
+  string name = 1;
+  // The option's value. For example, `"com.google.protobuf"`.
+  Any value = 2;
+}
+
+// The syntax in which a protocol buffer element is defined.
+enum Syntax {
+  // Syntax `proto2`.
+  SYNTAX_PROTO2 = 0;
+  // Syntax `proto3`.
+  SYNTAX_PROTO3 = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest.proto
new file mode 100644
index 0000000..da56ae0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest.proto
@@ -0,0 +1,879 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file we will use for unit testing.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;     // auto-added
+option cc_enable_arenas = true;
+
+import "google/protobuf/unittest_import.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage                        optional_nested_message  = 18;
+  optional ForeignMessage                       optional_foreign_message = 19;
+  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  optional NestedEnum                           optional_nested_enum     = 21;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  optional protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
+  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
+  optional protobuf_unittest_import.ImportEnum
+      default_import_enum = 83 [default = IMPORT_BAR];
+
+  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+  optional string default_cord = 85 [ctype=CORD,default="123"];
+
+  // For oneof test
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  optional NestedTestAllTypes child = 1;
+  optional TestAllTypes payload = 2;
+  repeated NestedTestAllTypes repeated_child = 3;
+}
+
+message TestDeprecatedFields {
+  optional int32 deprecated_int32 = 1 [deprecated=true];
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  optional int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestReservedFields {
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
+message TestAllExtensions {
+  extensions 1 to max;
+}
+
+extend TestAllExtensions {
+  // Singular
+  optional    int32 optional_int32_extension    =  1;
+  optional    int64 optional_int64_extension    =  2;
+  optional   uint32 optional_uint32_extension   =  3;
+  optional   uint64 optional_uint64_extension   =  4;
+  optional   sint32 optional_sint32_extension   =  5;
+  optional   sint64 optional_sint64_extension   =  6;
+  optional  fixed32 optional_fixed32_extension  =  7;
+  optional  fixed64 optional_fixed64_extension  =  8;
+  optional sfixed32 optional_sfixed32_extension =  9;
+  optional sfixed64 optional_sfixed64_extension = 10;
+  optional    float optional_float_extension    = 11;
+  optional   double optional_double_extension   = 12;
+  optional     bool optional_bool_extension     = 13;
+  optional   string optional_string_extension   = 14;
+  optional    bytes optional_bytes_extension    = 15;
+
+  optional group OptionalGroup_extension = 16 {
+    optional int32 a = 17;
+  }
+
+  optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
+  optional ForeignMessage optional_foreign_message_extension = 19;
+  optional protobuf_unittest_import.ImportMessage
+    optional_import_message_extension = 20;
+
+  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
+  optional ForeignEnum optional_foreign_enum_extension = 22;
+  optional protobuf_unittest_import.ImportEnum
+    optional_import_enum_extension = 23;
+
+  optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
+  optional string optional_cord_extension = 25 [ctype=CORD];
+
+  optional protobuf_unittest_import.PublicImportMessage
+    optional_public_import_message_extension = 26;
+
+  optional TestAllTypes.NestedMessage
+    optional_lazy_message_extension = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32_extension    = 31;
+  repeated    int64 repeated_int64_extension    = 32;
+  repeated   uint32 repeated_uint32_extension   = 33;
+  repeated   uint64 repeated_uint64_extension   = 34;
+  repeated   sint32 repeated_sint32_extension   = 35;
+  repeated   sint64 repeated_sint64_extension   = 36;
+  repeated  fixed32 repeated_fixed32_extension  = 37;
+  repeated  fixed64 repeated_fixed64_extension  = 38;
+  repeated sfixed32 repeated_sfixed32_extension = 39;
+  repeated sfixed64 repeated_sfixed64_extension = 40;
+  repeated    float repeated_float_extension    = 41;
+  repeated   double repeated_double_extension   = 42;
+  repeated     bool repeated_bool_extension     = 43;
+  repeated   string repeated_string_extension   = 44;
+  repeated    bytes repeated_bytes_extension    = 45;
+
+  repeated group RepeatedGroup_extension = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
+  repeated ForeignMessage repeated_foreign_message_extension = 49;
+  repeated protobuf_unittest_import.ImportMessage
+    repeated_import_message_extension = 50;
+
+  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+  repeated ForeignEnum repeated_foreign_enum_extension = 52;
+  repeated protobuf_unittest_import.ImportEnum
+    repeated_import_enum_extension = 53;
+
+  repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord_extension = 55 [ctype=CORD];
+
+  repeated TestAllTypes.NestedMessage
+    repeated_lazy_message_extension = 57 [lazy=true];
+
+  // Singular with defaults
+  optional    int32 default_int32_extension    = 61 [default =  41    ];
+  optional    int64 default_int64_extension    = 62 [default =  42    ];
+  optional   uint32 default_uint32_extension   = 63 [default =  43    ];
+  optional   uint64 default_uint64_extension   = 64 [default =  44    ];
+  optional   sint32 default_sint32_extension   = 65 [default = -45    ];
+  optional   sint64 default_sint64_extension   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32_extension  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64_extension  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32_extension = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64_extension = 70 [default = -50    ];
+  optional    float default_float_extension    = 71 [default =  51.5  ];
+  optional   double default_double_extension   = 72 [default =  52e3  ];
+  optional     bool default_bool_extension     = 73 [default = true   ];
+  optional   string default_string_extension   = 74 [default = "hello"];
+  optional    bytes default_bytes_extension    = 75 [default = "world"];
+
+  optional TestAllTypes.NestedEnum
+    default_nested_enum_extension = 81 [default = BAR];
+  optional ForeignEnum
+    default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
+  optional protobuf_unittest_import.ImportEnum
+    default_import_enum_extension = 83 [default = IMPORT_BAR];
+
+  optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
+                                                       default="abc"];
+  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
+
+  // For oneof test
+  optional uint32 oneof_uint32_extension = 111;
+  optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112;
+  optional string oneof_string_extension = 113;
+  optional bytes oneof_bytes_extension = 114;
+}
+
+message TestNestedExtension {
+  extend TestAllExtensions {
+    // Check for bug where string extensions declared in tested scope did not
+    // compile.
+    optional string test = 1002 [default="test"];
+    // Used to test if generated extension name is correct when there are
+    // underscores.
+    optional string nested_string_extension = 1003;
+  }
+}
+
+// We have separate messages for testing required fields because it's
+// annoying to have to fill in required fields in TestProto in order to
+// do anything with it.  Note that we don't need to test every type of
+// required filed because the code output is basically identical to
+// optional fields for all types.
+message TestRequired {
+  required int32 a = 1;
+  optional int32 dummy2 = 2;
+  required int32 b = 3;
+
+  extend TestAllExtensions {
+    optional TestRequired single = 1000;
+    repeated TestRequired multi  = 1001;
+  }
+
+  // Pad the field count to 32 so that we can test that IsInitialized()
+  // properly checks multiple elements of has_bits_.
+  optional int32 dummy4  =  4;
+  optional int32 dummy5  =  5;
+  optional int32 dummy6  =  6;
+  optional int32 dummy7  =  7;
+  optional int32 dummy8  =  8;
+  optional int32 dummy9  =  9;
+  optional int32 dummy10 = 10;
+  optional int32 dummy11 = 11;
+  optional int32 dummy12 = 12;
+  optional int32 dummy13 = 13;
+  optional int32 dummy14 = 14;
+  optional int32 dummy15 = 15;
+  optional int32 dummy16 = 16;
+  optional int32 dummy17 = 17;
+  optional int32 dummy18 = 18;
+  optional int32 dummy19 = 19;
+  optional int32 dummy20 = 20;
+  optional int32 dummy21 = 21;
+  optional int32 dummy22 = 22;
+  optional int32 dummy23 = 23;
+  optional int32 dummy24 = 24;
+  optional int32 dummy25 = 25;
+  optional int32 dummy26 = 26;
+  optional int32 dummy27 = 27;
+  optional int32 dummy28 = 28;
+  optional int32 dummy29 = 29;
+  optional int32 dummy30 = 30;
+  optional int32 dummy31 = 31;
+  optional int32 dummy32 = 32;
+
+  required int32 c = 33;
+}
+
+message TestRequiredForeign {
+  optional TestRequired optional_message = 1;
+  repeated TestRequired repeated_message = 2;
+  optional int32 dummy = 3;
+}
+
+// Test that we can use NestedMessage from outside TestAllTypes.
+message TestForeignNested {
+  optional TestAllTypes.NestedMessage foreign_nested = 1;
+}
+
+// TestEmptyMessage is used to test unknown field support.
+message TestEmptyMessage {
+}
+
+// Like above, but declare all field numbers as potential extensions.  No
+// actual extensions should ever be defined for this type.
+message TestEmptyMessageWithExtensions {
+  extensions 1 to max;
+}
+
+message TestMultipleExtensionRanges {
+  extensions 42;
+  extensions 4143 to 4243;
+  extensions 65536 to max;
+}
+
+// Test that really large tag numbers don't break anything.
+message TestReallyLargeTagNumber {
+  // The largest possible tag number is 2^28 - 1, since the wire format uses
+  // three bits to communicate wire type.
+  optional int32 a = 1;
+  optional int32 bb = 268435455;
+}
+
+message TestRecursiveMessage {
+  optional TestRecursiveMessage a = 1;
+  optional int32 i = 2;
+}
+
+// Test that mutual recursion works.
+message TestMutualRecursionA {
+  optional TestMutualRecursionB bb = 1;
+}
+
+message TestMutualRecursionB {
+  optional TestMutualRecursionA a = 1;
+  optional int32 optional_int32 = 2;
+}
+
+// Test that groups have disjoint field numbers from their siblings and
+// parents.  This is NOT possible in proto1; only google.protobuf.  When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in protobuf_unittest_proto.
+message TestDupFieldNumber {                        // NO_PROTO1
+  optional int32 a = 1;                             // NO_PROTO1
+  optional group Foo = 2 { optional int32 a = 1; }  // NO_PROTO1
+  optional group Bar = 3 { optional int32 a = 1; }  // NO_PROTO1
+}                                                   // NO_PROTO1
+
+// Additional messages for testing lazy fields.
+message TestEagerMessage {
+  optional TestAllTypes sub_message = 1 [lazy=false];
+}
+message TestLazyMessage {
+  optional TestAllTypes sub_message = 1 [lazy=true];
+}
+
+// Needed for a Python test.
+message TestNestedMessageHasBits {
+  message NestedMessage {
+    repeated int32 nestedmessage_repeated_int32 = 1;
+    repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
+  }
+  optional NestedMessage optional_nested_message = 1;
+}
+
+
+// Test an enum that has multiple values with the same number.
+enum TestEnumWithDupValue {
+  option allow_alias = true;
+
+  FOO1 = 1;
+  BAR1 = 2;
+  BAZ = 3;
+  FOO2 = 1;
+  BAR2 = 2;
+}
+
+// Test an enum with large, unordered values.
+enum TestSparseEnum {
+  SPARSE_A = 123;
+  SPARSE_B = 62374;
+  SPARSE_C = 12589234;
+  SPARSE_D = -15;
+  SPARSE_E = -53452;
+  SPARSE_F = 0;
+  SPARSE_G = 2;
+}
+
+// Test message with CamelCase field names.  This violates Protocol Buffer
+// standard style.
+message TestCamelCaseFieldNames {
+  optional int32 PrimitiveField = 1;
+  optional string StringField = 2;
+  optional ForeignEnum EnumField = 3;
+  optional ForeignMessage MessageField = 4;
+  optional string StringPieceField = 5 [ctype=STRING_PIECE];
+  optional string CordField = 6 [ctype=CORD];
+
+  repeated int32 RepeatedPrimitiveField = 7;
+  repeated string RepeatedStringField = 8;
+  repeated ForeignEnum RepeatedEnumField = 9;
+  repeated ForeignMessage RepeatedMessageField = 10;
+  repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
+  repeated string RepeatedCordField = 12 [ctype=CORD];
+}
+
+
+// We list fields out of order, to ensure that we're using field number and not
+// field index to determine serialization order.
+message TestFieldOrderings {
+  optional string my_string = 11;
+  extensions 2 to 10;
+  optional int64 my_int = 1;
+  extensions 12 to 100;
+  optional float my_float = 101;
+  message NestedMessage {
+    optional int64 oo = 2;
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    optional int32 bb = 1;
+  }
+
+  optional NestedMessage optional_nested_message  = 200;
+}
+
+
+extend TestFieldOrderings {
+  optional string my_extension_string = 50;
+  optional int32 my_extension_int = 5;
+}
+
+
+message TestExtremeDefaultValues {
+  optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
+  optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
+  optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
+  optional  int32 small_int32  = 4 [default = -0x7FFFFFFF];
+  optional  int64 small_int64  = 5 [default = -0x7FFFFFFFFFFFFFFF];
+  optional  int32 really_small_int32 = 21 [default = -0x80000000];
+  optional  int64 really_small_int64 = 22 [default = -0x8000000000000000];
+
+  // The default value here is UTF-8 for "\u1234".  (We could also just type
+  // the UTF-8 text directly into this text file rather than escape it, but
+  // lots of people use editors that would be confused by this.)
+  optional string utf8_string = 6 [default = "\341\210\264"];
+
+  // Tests for single-precision floating-point values.
+  optional float zero_float = 7 [default = 0];
+  optional float one_float = 8 [default = 1];
+  optional float small_float = 9 [default = 1.5];
+  optional float negative_one_float = 10 [default = -1];
+  optional float negative_float = 11 [default = -1.5];
+  // Using exponents
+  optional float large_float = 12 [default = 2E8];
+  optional float small_negative_float = 13 [default = -8e-28];
+
+  // Text for nonfinite floating-point values.
+  optional double inf_double = 14 [default = inf];
+  optional double neg_inf_double = 15 [default = -inf];
+  optional double nan_double = 16 [default = nan];
+  optional float inf_float = 17 [default = inf];
+  optional float neg_inf_float = 18 [default = -inf];
+  optional float nan_float = 19 [default = nan];
+
+  // Tests for C++ trigraphs.
+  // Trigraphs should be escaped in C++ generated files, but they should not be
+  // escaped for other languages.
+  // Note that in .proto file, "\?" is a valid way to escape ? in string
+  // literals.
+  optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
+
+  // String defaults containing the character '\000'
+  optional string string_with_zero       = 23 [default = "hel\000lo"];
+  optional  bytes bytes_with_zero        = 24 [default = "wor\000ld"];
+  optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
+                                               default="ab\000c"];
+  optional string cord_with_zero         = 26 [ctype=CORD,
+                                               default="12\0003"];
+  optional string replacement_string     = 27 [default="${unknown}"];
+}
+
+message SparseEnumMessage {
+  optional TestSparseEnum sparse_enum = 1;
+}
+
+// Test String and Bytes: string is for valid UTF-8 strings
+message OneString {
+  optional string data = 1;
+}
+
+message MoreString {
+  repeated string data = 1;
+}
+
+message OneBytes {
+  optional bytes data = 1;
+}
+
+message MoreBytes {
+  repeated bytes data = 1;
+}
+
+// Test int32, uint32, int64, uint64, and bool are all compatible
+message Int32Message {
+  optional int32 data = 1;
+}
+
+message Uint32Message {
+  optional uint32 data = 1;
+}
+
+message Int64Message {
+  optional int64 data = 1;
+}
+
+message Uint64Message {
+  optional uint64 data = 1;
+}
+
+message BoolMessage {
+  optional bool data = 1;
+}
+
+// Test oneofs.
+message TestOneof {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    TestAllTypes foo_message = 3;
+    group FooGroup = 4 {
+      optional int32 a = 5;
+      optional string b = 6;
+    }
+  }
+}
+
+message TestOneofBackwardsCompatible {
+  optional int32 foo_int = 1;
+  optional string foo_string = 2;
+  optional TestAllTypes foo_message = 3;
+  optional group FooGroup = 4 {
+    optional int32 a = 5;
+    optional string b = 6;
+  }
+}
+
+message TestOneof2 {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    string foo_cord = 3 [ctype=CORD];
+    string foo_string_piece = 4 [ctype=STRING_PIECE];
+    bytes foo_bytes = 5;
+    NestedEnum foo_enum = 6;
+    NestedMessage foo_message = 7;
+    group FooGroup = 8 {
+      optional int32 a = 9;
+      optional string b = 10;
+    }
+    NestedMessage foo_lazy_message = 11 [lazy=true];
+  }
+
+  oneof bar {
+    int32 bar_int = 12 [default = 5];
+    string bar_string = 13 [default = "STRING"];
+    string bar_cord = 14 [ctype=CORD, default = "CORD"];
+    string bar_string_piece = 15 [ctype=STRING_PIECE, default = "SPIECE"];
+    bytes bar_bytes = 16 [default = "BYTES"];
+    NestedEnum bar_enum = 17 [default = BAR];
+  }
+
+  optional int32 baz_int = 18;
+  optional string baz_string = 19 [default = "BAZ"];
+
+  message NestedMessage {
+    optional int64 qux_int = 1;
+    repeated int32 corge_int = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+}
+
+message TestRequiredOneof {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    NestedMessage foo_message = 3;
+  }
+  message NestedMessage {
+    required double required_double = 1;
+  }
+}
+
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+  repeated    int32 unpacked_int32    =  90 [packed = false];
+  repeated    int64 unpacked_int64    =  91 [packed = false];
+  repeated   uint32 unpacked_uint32   =  92 [packed = false];
+  repeated   uint64 unpacked_uint64   =  93 [packed = false];
+  repeated   sint32 unpacked_sint32   =  94 [packed = false];
+  repeated   sint64 unpacked_sint64   =  95 [packed = false];
+  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
+  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
+  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
+  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
+  repeated    float unpacked_float    = 100 [packed = false];
+  repeated   double unpacked_double   = 101 [packed = false];
+  repeated     bool unpacked_bool     = 102 [packed = false];
+  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
+}
+
+message TestPackedExtensions {
+  extensions 1 to max;
+}
+
+extend TestPackedExtensions {
+  repeated    int32 packed_int32_extension    =  90 [packed = true];
+  repeated    int64 packed_int64_extension    =  91 [packed = true];
+  repeated   uint32 packed_uint32_extension   =  92 [packed = true];
+  repeated   uint64 packed_uint64_extension   =  93 [packed = true];
+  repeated   sint32 packed_sint32_extension   =  94 [packed = true];
+  repeated   sint64 packed_sint64_extension   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32_extension  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64_extension  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32_extension =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64_extension =  99 [packed = true];
+  repeated    float packed_float_extension    = 100 [packed = true];
+  repeated   double packed_double_extension   = 101 [packed = true];
+  repeated     bool packed_bool_extension     = 102 [packed = true];
+  repeated ForeignEnum packed_enum_extension  = 103 [packed = true];
+}
+
+message TestUnpackedExtensions {
+  extensions 1 to max;
+}
+
+extend TestUnpackedExtensions {
+  repeated    int32 unpacked_int32_extension    =  90 [packed = false];
+  repeated    int64 unpacked_int64_extension    =  91 [packed = false];
+  repeated   uint32 unpacked_uint32_extension   =  92 [packed = false];
+  repeated   uint64 unpacked_uint64_extension   =  93 [packed = false];
+  repeated   sint32 unpacked_sint32_extension   =  94 [packed = false];
+  repeated   sint64 unpacked_sint64_extension   =  95 [packed = false];
+  repeated  fixed32 unpacked_fixed32_extension  =  96 [packed = false];
+  repeated  fixed64 unpacked_fixed64_extension  =  97 [packed = false];
+  repeated sfixed32 unpacked_sfixed32_extension =  98 [packed = false];
+  repeated sfixed64 unpacked_sfixed64_extension =  99 [packed = false];
+  repeated    float unpacked_float_extension    = 100 [packed = false];
+  repeated   double unpacked_double_extension   = 101 [packed = false];
+  repeated     bool unpacked_bool_extension     = 102 [packed = false];
+  repeated ForeignEnum unpacked_enum_extension  = 103 [packed = false];
+}
+
+// Used by ExtensionSetTest/DynamicExtensions.  The test actually builds
+// a set of extensions to TestAllExtensions dynamically, based on the fields
+// of this message type.
+message TestDynamicExtensions {
+  enum DynamicEnumType {
+    DYNAMIC_FOO = 2200;
+    DYNAMIC_BAR = 2201;
+    DYNAMIC_BAZ = 2202;
+  }
+  message DynamicMessageType {
+    optional int32 dynamic_field = 2100;
+  }
+
+  optional fixed32 scalar_extension = 2000;
+  optional ForeignEnum enum_extension = 2001;
+  optional DynamicEnumType dynamic_enum_extension = 2002;
+
+  optional ForeignMessage message_extension = 2003;
+  optional DynamicMessageType dynamic_message_extension = 2004;
+
+  repeated string repeated_extension = 2005;
+  repeated sint32 packed_extension = 2006 [packed = true];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+  // Parsing repeated fixed size values used to fail. This message needs to be
+  // used in order to get a tag of the right size; all of the repeated fields
+  // in TestAllTypes didn't trigger the check.
+  repeated fixed32 repeated_fixed32 = 12;
+  // Check for a varint type, just for good measure.
+  repeated int32   repeated_int32   = 13;
+
+  // These have two-byte tags.
+  repeated fixed64 repeated_fixed64 = 2046;
+  repeated int64   repeated_int64   = 2047;
+
+  // Three byte tags.
+  repeated float   repeated_float   = 262142;
+  repeated uint64  repeated_uint64  = 262143;
+}
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+message TestParsingMerge {
+  // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
+  // except that all fields are repeated. In the tests, we will serialize the
+  // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
+  // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
+  // the corresponding required/optional fields in TestParsingMerge.
+  message RepeatedFieldsGenerator {
+    repeated TestAllTypes field1 = 1;
+    repeated TestAllTypes field2 = 2;
+    repeated TestAllTypes field3 = 3;
+    repeated group Group1 = 10 {
+      optional TestAllTypes field1 = 11;
+    }
+    repeated group Group2 = 20 {
+      optional TestAllTypes field1 = 21;
+    }
+    repeated TestAllTypes ext1 = 1000;
+    repeated TestAllTypes ext2 = 1001;
+  }
+  required TestAllTypes required_all_types = 1;
+  optional TestAllTypes optional_all_types = 2;
+  repeated TestAllTypes repeated_all_types = 3;
+  optional group OptionalGroup = 10 {
+    optional TestAllTypes optional_group_all_types = 11;
+  }
+  repeated group RepeatedGroup = 20 {
+    optional TestAllTypes repeated_group_all_types = 21;
+  }
+  extensions 1000 to max;
+  extend TestParsingMerge {
+    optional TestAllTypes optional_ext = 1000;
+    repeated TestAllTypes repeated_ext = 1001;
+  }
+}
+
+message TestCommentInjectionMessage {
+  // */ <- This should not close the generated doc comment
+  optional string a = 1 [default="*/ <- Neither should this."];
+}
+
+
+// Test that RPC services work.
+message FooRequest  {}
+message FooResponse {}
+
+message FooClientMessage {}
+message FooServerMessage{}
+
+service TestService {
+  rpc Foo(FooRequest) returns (FooResponse);
+  rpc Bar(BarRequest) returns (BarResponse);
+}
+
+
+message BarRequest  {}
+message BarResponse {}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_arena.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_arena.proto
new file mode 100644
index 0000000..cd7e437
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_arena.proto
@@ -0,0 +1,46 @@
+// 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.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest_no_arena_import.proto";
+
+package proto2_arena_unittest;
+
+option cc_enable_arenas = true;
+
+message NestedMessage {
+  optional int32 d = 1;
+}
+
+message ArenaMessage {
+  repeated NestedMessage  repeated_nested_message = 1;
+  repeated ImportNoArenaNestedMessage  repeated_import_no_arena_message = 2;
+};
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_custom_options.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_custom_options.proto
new file mode 100644
index 0000000..4cc0e36
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_custom_options.proto
@@ -0,0 +1,421 @@
+// 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.
+
+// Author: benjy@google.com (Benjy Weinberger)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file used to test the "custom options" feature of google.protobuf.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;
+
+// A custom file option (defined below).
+option (file_opt1) = 9876543210;
+
+import "google/protobuf/descriptor.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+package protobuf_unittest;
+
+
+// Some simple test custom options of various types.
+
+extend google.protobuf.FileOptions {
+  optional uint64 file_opt1 = 7736974;
+}
+
+extend google.protobuf.MessageOptions {
+  optional int32 message_opt1 = 7739036;
+}
+
+extend google.protobuf.FieldOptions {
+  optional fixed64 field_opt1 = 7740936;
+  // This is useful for testing that we correctly register default values for
+  // extension options.
+  optional int32 field_opt2 = 7753913 [default=42];
+}
+
+extend google.protobuf.EnumOptions {
+  optional sfixed32 enum_opt1 = 7753576;
+}
+
+extend google.protobuf.EnumValueOptions {
+  optional int32 enum_value_opt1 = 1560678;
+}
+
+extend google.protobuf.ServiceOptions {
+  optional sint64 service_opt1 = 7887650;
+}
+
+enum MethodOpt1 {
+  METHODOPT1_VAL1 = 1;
+  METHODOPT1_VAL2 = 2;
+}
+
+extend google.protobuf.MethodOptions {
+  optional MethodOpt1 method_opt1 = 7890860;
+}
+
+// A test message with custom options at all possible locations (and also some
+// regular options, to make sure they interact nicely).
+message TestMessageWithCustomOptions {
+  option message_set_wire_format = false;
+
+  option (message_opt1) = -56;
+
+  optional string field1 = 1 [ctype=CORD,
+                              (field_opt1)=8765432109];
+
+  enum AnEnum {
+    option (enum_opt1) = -789;
+
+    ANENUM_VAL1 = 1;
+    ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
+  }
+}
+
+
+// A test RPC service with custom options at all possible locations (and also
+// some regular options, to make sure they interact nicely).
+message CustomOptionFooRequest {
+}
+
+message CustomOptionFooResponse {
+}
+
+message CustomOptionFooClientMessage {
+}
+
+message CustomOptionFooServerMessage {
+}
+
+service TestServiceWithCustomOptions {
+  option (service_opt1) = -9876543210;
+
+  rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
+    option (method_opt1) = METHODOPT1_VAL2;
+  }
+}
+
+
+
+// Options of every possible field type, so we can test them all exhaustively.
+
+message DummyMessageContainingEnum {
+  enum TestEnumType {
+    TEST_OPTION_ENUM_TYPE1 = 22;
+    TEST_OPTION_ENUM_TYPE2 = -23;
+  }
+}
+
+message DummyMessageInvalidAsOptionType {
+}
+
+extend google.protobuf.MessageOptions {
+  optional         bool     bool_opt = 7706090;
+  optional        int32    int32_opt = 7705709;
+  optional        int64    int64_opt = 7705542;
+  optional       uint32   uint32_opt = 7704880;
+  optional       uint64   uint64_opt = 7702367;
+  optional       sint32   sint32_opt = 7701568;
+  optional       sint64   sint64_opt = 7700863;
+  optional      fixed32  fixed32_opt = 7700307;
+  optional      fixed64  fixed64_opt = 7700194;
+  optional     sfixed32 sfixed32_opt = 7698645;
+  optional     sfixed64 sfixed64_opt = 7685475;
+  optional        float    float_opt = 7675390;
+  optional       double   double_opt = 7673293;
+  optional       string   string_opt = 7673285;
+  optional        bytes    bytes_opt = 7673238;
+  optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
+  optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
+}
+
+message CustomOptionMinIntegerValues {
+  option     (bool_opt) = false;
+  option    (int32_opt) = -0x80000000;
+  option    (int64_opt) = -0x8000000000000000;
+  option   (uint32_opt) = 0;
+  option   (uint64_opt) = 0;
+  option   (sint32_opt) = -0x80000000;
+  option   (sint64_opt) = -0x8000000000000000;
+  option  (fixed32_opt) = 0;
+  option  (fixed64_opt) = 0;
+  option (sfixed32_opt) = -0x80000000;
+  option (sfixed64_opt) = -0x8000000000000000;
+}
+
+message CustomOptionMaxIntegerValues {
+  option     (bool_opt) = true;
+  option    (int32_opt) = 0x7FFFFFFF;
+  option    (int64_opt) = 0x7FFFFFFFFFFFFFFF;
+  option   (uint32_opt) = 0xFFFFFFFF;
+  option   (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
+  option   (sint32_opt) = 0x7FFFFFFF;
+  option   (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
+  option  (fixed32_opt) = 0xFFFFFFFF;
+  option  (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
+  option (sfixed32_opt) = 0x7FFFFFFF;
+  option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
+}
+
+message CustomOptionOtherValues {
+  option  (int32_opt) = -100;  // To test sign-extension.
+  option  (float_opt) = 12.3456789;
+  option (double_opt) = 1.234567890123456789;
+  option (string_opt) = "Hello, \"World\"";
+  option  (bytes_opt) = "Hello\0World";
+  option   (enum_opt) = TEST_OPTION_ENUM_TYPE2;
+}
+
+message SettingRealsFromPositiveInts {
+  option  (float_opt) = 12;
+  option (double_opt) = 154;
+}
+
+message SettingRealsFromNegativeInts {
+  option  (float_opt) = -12;
+  option  (double_opt) = -154;
+}
+
+// Options of complex message types, themselves combined and extended in
+// various ways.
+
+message ComplexOptionType1 {
+  optional int32 foo = 1;
+  optional int32 foo2 = 2;
+  optional int32 foo3 = 3;
+  repeated int32 foo4 = 4;
+
+  extensions 100 to max;
+}
+
+message ComplexOptionType2 {
+  optional ComplexOptionType1 bar = 1;
+  optional int32 baz = 2;
+
+  message ComplexOptionType4 {
+    optional int32 waldo = 1;
+
+    extend google.protobuf.MessageOptions {
+      optional ComplexOptionType4 complex_opt4 = 7633546;
+    }
+  }
+
+  optional ComplexOptionType4 fred = 3;
+  repeated ComplexOptionType4 barney = 4;
+
+  extensions 100 to max;
+}
+
+message ComplexOptionType3 {
+  optional int32 qux = 1;
+
+  optional group ComplexOptionType5 = 2 {
+    optional int32 plugh = 3;
+  }
+}
+
+extend ComplexOptionType1 {
+  optional int32 quux = 7663707;
+  optional ComplexOptionType3 corge = 7663442;
+}
+
+extend ComplexOptionType2 {
+  optional int32 grault = 7650927;
+  optional ComplexOptionType1 garply = 7649992;
+}
+
+extend google.protobuf.MessageOptions {
+  optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
+  optional ComplexOptionType2 complex_opt2 = 7636949;
+  optional ComplexOptionType3 complex_opt3 = 7636463;
+  optional group ComplexOpt6 = 7595468 {
+    optional int32 xyzzy = 7593951;
+  }
+}
+
+// Note that we try various different ways of naming the same extension.
+message VariousComplexOptions {
+  option (.protobuf_unittest.complex_opt1).foo = 42;
+  option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
+  option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
+  option (protobuf_unittest.complex_opt1).foo4 = 99;
+  option (protobuf_unittest.complex_opt1).foo4 = 88;
+  option (complex_opt2).baz = 987;
+  option (complex_opt2).(grault) = 654;
+  option (complex_opt2).bar.foo = 743;
+  option (complex_opt2).bar.(quux) = 1999;
+  option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
+  option (complex_opt2).(garply).foo = 741;
+  option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
+  option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
+  option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
+  option (complex_opt2).fred.waldo = 321;
+  option (complex_opt2).barney = { waldo: 101 };
+  option (complex_opt2).barney = { waldo: 212 };
+  option (protobuf_unittest.complex_opt3).qux = 9;
+  option (complex_opt3).complexoptiontype5.plugh = 22;
+  option (complexopt6).xyzzy = 24;
+}
+
+// ------------------------------------------------------
+// Definitions for testing aggregate option parsing.
+// See descriptor_unittest.cc.
+
+message AggregateMessageSet {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message AggregateMessageSetElement {
+  extend AggregateMessageSet {
+    optional AggregateMessageSetElement message_set_extension = 15447542;
+  }
+  optional string s = 1;
+}
+
+// A helper type used to test aggregate option parsing
+message Aggregate {
+  optional int32 i = 1;
+  optional string s = 2;
+
+  // A nested object
+  optional Aggregate sub = 3;
+
+  // To test the parsing of extensions inside aggregate values
+  optional google.protobuf.FileOptions file = 4;
+  extend google.protobuf.FileOptions {
+    optional Aggregate nested = 15476903;
+  }
+
+  // An embedded message set
+  optional AggregateMessageSet mset = 5;
+}
+
+// Allow Aggregate to be used as an option at all possible locations
+// in the .proto grammer.
+extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
+extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
+extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
+extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
+extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
+extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
+extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
+
+// Try using AggregateOption at different points in the proto grammar
+option (fileopt) = {
+  s: 'FileAnnotation'
+  // Also test the handling of comments
+  /* of both types */ i: 100
+
+  sub { s: 'NestedFileAnnotation' }
+
+  // Include a google.protobuf.FileOptions and recursively extend it with
+  // another fileopt.
+  file {
+    [protobuf_unittest.fileopt] {
+      s:'FileExtensionAnnotation'
+    }
+  }
+
+  // A message set inside an option value
+  mset {
+    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
+      s: 'EmbeddedMessageSetElement'
+    }
+  }
+};
+
+message AggregateMessage {
+  option (msgopt) = { i:101 s:'MessageAnnotation' };
+  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
+}
+
+service AggregateService {
+  option (serviceopt) = { s:'ServiceAnnotation' };
+  rpc Method (AggregateMessage) returns (AggregateMessage) {
+    option (methodopt) = { s:'MethodAnnotation' };
+  }
+}
+
+enum AggregateEnum {
+  option (enumopt) = { s:'EnumAnnotation' };
+  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
+}
+
+// Test custom options for nested type.
+message NestedOptionType {
+  message NestedMessage {
+    option (message_opt1) = 1001;
+    optional int32 nested_field = 1 [(field_opt1) = 1002];
+  }
+  enum NestedEnum {
+    option (enum_opt1) = 1003;
+    NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
+  }
+  extend google.protobuf.FileOptions {
+    optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
+  }
+}
+
+// Custom message option that has a required enum field.
+// WARNING: this is strongly discouraged!
+message OldOptionType {
+  enum TestEnum {
+    OLD_VALUE = 0;
+  }
+  required TestEnum value = 1;
+}
+
+// Updated version of the custom option above.
+message NewOptionType {
+  enum TestEnum {
+    OLD_VALUE = 0;
+    NEW_VALUE = 1;
+  }
+  required TestEnum value = 1;
+}
+
+extend google.protobuf.MessageOptions {
+  optional OldOptionType required_enum_opt = 106161807;
+}
+
+// Test message using the "required_enum_opt" option defined above.
+message TestMessageWithRequiredEnumOption {
+  option (required_enum_opt) = { value: OLD_VALUE };
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_drop_unknown_fields.proto
new file mode 100644
index 0000000..8aa3a37
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_drop_unknown_fields.proto
@@ -0,0 +1,58 @@
+// 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.
+
+syntax = "proto3";
+
+package unittest_drop_unknown_fields;
+option objc_class_prefix = "DropUnknowns";
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+message Foo {
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+  }
+  int32 int32_value = 1;
+  NestedEnum enum_value = 2;
+}
+
+message FooWithExtraFields {
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    QUX = 3;
+  }
+  int32 int32_value = 1;
+  NestedEnum enum_value = 2;
+  int32 extra_int32_value = 3;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_embed_optimize_for.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_embed_optimize_for.proto
new file mode 100644
index 0000000..d8b0f9b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_embed_optimize_for.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
+
+syntax = "proto2";
+import "google/protobuf/unittest_optimize_for.proto";
+
+package protobuf_unittest;
+
+// We optimize for speed here, but we are importing a proto that is optimized
+// for code size.
+option optimize_for = SPEED;
+
+message TestEmbedOptimizedForSize {
+  // Test that embedding a message which has optimize_for = CODE_SIZE into
+  // one optimized for speed works.
+  optional TestOptimizedForSize optional_message = 1;
+  repeated TestOptimizedForSize repeated_message = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_empty.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_empty.proto
new file mode 100644
index 0000000..36443e7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_empty.proto
@@ -0,0 +1,38 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file intentionally left blank.  (At one point this wouldn't compile
+// correctly.)
+
+syntax = "proto2";
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_enormous_descriptor.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_enormous_descriptor.proto
new file mode 100644
index 0000000..6e65dc1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -0,0 +1,1048 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file that has an extremely large descriptor.  Used to test that
+// descriptors over 64k don't break language-specific limits in generated code,
+// such as the string literal length limit in Java.
+
+syntax = "proto2";
+
+package google.protobuf;
+option java_package = "com.google.protobuf";
+
+// Avoid generating insanely long methods.
+option optimize_for = CODE_SIZE;
+
+message TestEnormousDescriptor {
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1 = 1 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_2 = 2 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_3 = 3 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_4 = 4 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_5 = 5 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_6 = 6 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_7 = 7 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_8 = 8 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_9 = 9 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_10 = 10 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_11 = 11 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_12 = 12 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_13 = 13 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_14 = 14 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_15 = 15 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_16 = 16 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_17 = 17 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_18 = 18 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_19 = 19 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_20 = 20 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_21 = 21 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_22 = 22 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_23 = 23 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_24 = 24 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_25 = 25 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_26 = 26 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_27 = 27 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_28 = 28 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_29 = 29 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_30 = 30 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_31 = 31 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_32 = 32 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_33 = 33 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_34 = 34 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_35 = 35 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_36 = 36 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_37 = 37 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_38 = 38 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_39 = 39 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_40 = 40 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_41 = 41 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_42 = 42 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_43 = 43 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_44 = 44 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_45 = 45 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_46 = 46 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_47 = 47 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_48 = 48 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_49 = 49 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_50 = 50 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_51 = 51 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_52 = 52 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_53 = 53 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_54 = 54 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_55 = 55 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_56 = 56 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_57 = 57 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_58 = 58 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_59 = 59 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_60 = 60 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_61 = 61 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_62 = 62 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_63 = 63 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_64 = 64 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_65 = 65 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_66 = 66 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_67 = 67 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_68 = 68 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_69 = 69 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_70 = 70 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_71 = 71 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_72 = 72 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_73 = 73 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_74 = 74 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_75 = 75 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_76 = 76 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_77 = 77 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_78 = 78 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_79 = 79 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_80 = 80 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_81 = 81 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_82 = 82 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_83 = 83 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_84 = 84 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_85 = 85 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_86 = 86 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_87 = 87 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_88 = 88 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_89 = 89 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_90 = 90 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_91 = 91 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_92 = 92 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_93 = 93 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_94 = 94 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_95 = 95 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_96 = 96 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_97 = 97 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_98 = 98 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_99 = 99 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_100 = 100 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_101 = 101 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_102 = 102 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_103 = 103 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_104 = 104 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_105 = 105 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_106 = 106 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_107 = 107 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_108 = 108 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_109 = 109 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_110 = 110 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_111 = 111 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_112 = 112 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_113 = 113 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_114 = 114 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_115 = 115 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_116 = 116 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_117 = 117 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_118 = 118 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_119 = 119 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_120 = 120 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_121 = 121 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_122 = 122 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_123 = 123 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_124 = 124 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_125 = 125 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_126 = 126 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_127 = 127 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_128 = 128 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_129 = 129 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_130 = 130 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_131 = 131 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_132 = 132 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_133 = 133 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_134 = 134 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_135 = 135 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_136 = 136 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_137 = 137 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_138 = 138 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_139 = 139 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_140 = 140 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_141 = 141 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_142 = 142 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_143 = 143 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_144 = 144 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_145 = 145 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_146 = 146 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_147 = 147 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_148 = 148 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_149 = 149 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_150 = 150 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_151 = 151 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_152 = 152 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_153 = 153 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_154 = 154 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_155 = 155 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_156 = 156 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_157 = 157 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_158 = 158 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_159 = 159 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_160 = 160 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_161 = 161 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_162 = 162 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_163 = 163 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_164 = 164 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_165 = 165 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_166 = 166 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_167 = 167 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_168 = 168 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_169 = 169 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_170 = 170 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_171 = 171 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_172 = 172 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_173 = 173 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_174 = 174 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_175 = 175 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_176 = 176 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_177 = 177 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_178 = 178 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_179 = 179 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_180 = 180 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_181 = 181 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_182 = 182 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_183 = 183 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_184 = 184 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_185 = 185 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_186 = 186 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_187 = 187 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_188 = 188 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_189 = 189 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_190 = 190 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_191 = 191 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_192 = 192 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_193 = 193 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_194 = 194 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_195 = 195 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_196 = 196 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_197 = 197 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_198 = 198 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_199 = 199 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_200 = 200 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_201 = 201 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_202 = 202 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_203 = 203 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_204 = 204 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_205 = 205 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_206 = 206 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_207 = 207 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_208 = 208 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_209 = 209 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_210 = 210 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_211 = 211 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_212 = 212 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_213 = 213 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_214 = 214 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_215 = 215 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_216 = 216 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_217 = 217 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_218 = 218 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_219 = 219 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_220 = 220 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_221 = 221 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_222 = 222 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_223 = 223 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_224 = 224 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_225 = 225 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_226 = 226 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_227 = 227 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_228 = 228 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_229 = 229 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_230 = 230 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_231 = 231 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_232 = 232 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_233 = 233 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_234 = 234 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_235 = 235 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_236 = 236 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_237 = 237 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_238 = 238 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_239 = 239 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_240 = 240 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_241 = 241 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_242 = 242 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_243 = 243 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_244 = 244 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_245 = 245 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_246 = 246 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_247 = 247 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_248 = 248 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_249 = 249 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_250 = 250 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_251 = 251 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_252 = 252 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_253 = 253 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_254 = 254 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_255 = 255 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_256 = 256 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_257 = 257 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_258 = 258 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_259 = 259 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_260 = 260 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_261 = 261 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_262 = 262 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_263 = 263 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_264 = 264 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_265 = 265 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_266 = 266 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_267 = 267 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_268 = 268 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_269 = 269 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_270 = 270 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_271 = 271 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_272 = 272 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_273 = 273 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_274 = 274 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_275 = 275 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_276 = 276 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_277 = 277 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_278 = 278 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_279 = 279 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_280 = 280 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_281 = 281 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_282 = 282 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_283 = 283 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_284 = 284 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_285 = 285 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_286 = 286 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_287 = 287 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_288 = 288 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_289 = 289 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_290 = 290 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_291 = 291 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_292 = 292 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_293 = 293 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_294 = 294 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_295 = 295 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_296 = 296 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_297 = 297 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_298 = 298 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_299 = 299 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_300 = 300 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_301 = 301 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_302 = 302 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_303 = 303 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_304 = 304 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_305 = 305 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_306 = 306 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_307 = 307 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_308 = 308 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_309 = 309 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_310 = 310 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_311 = 311 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_312 = 312 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_313 = 313 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_314 = 314 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_315 = 315 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_316 = 316 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_317 = 317 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_318 = 318 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_319 = 319 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_320 = 320 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_321 = 321 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_322 = 322 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_323 = 323 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_324 = 324 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_325 = 325 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_326 = 326 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_327 = 327 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_328 = 328 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_329 = 329 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_330 = 330 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_331 = 331 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_332 = 332 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_333 = 333 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_334 = 334 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_335 = 335 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_336 = 336 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_337 = 337 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_338 = 338 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_339 = 339 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_340 = 340 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_341 = 341 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_342 = 342 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_343 = 343 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_344 = 344 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_345 = 345 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_346 = 346 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_347 = 347 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_348 = 348 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_349 = 349 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_350 = 350 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_351 = 351 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_352 = 352 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_353 = 353 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_354 = 354 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_355 = 355 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_356 = 356 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_357 = 357 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_358 = 358 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_359 = 359 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_360 = 360 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_361 = 361 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_362 = 362 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_363 = 363 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_364 = 364 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_365 = 365 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_366 = 366 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_367 = 367 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_368 = 368 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_369 = 369 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_370 = 370 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_371 = 371 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_372 = 372 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_373 = 373 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_374 = 374 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_375 = 375 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_376 = 376 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_377 = 377 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_378 = 378 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_379 = 379 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_380 = 380 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_381 = 381 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_382 = 382 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_383 = 383 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_384 = 384 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_385 = 385 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_386 = 386 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_387 = 387 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_388 = 388 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_389 = 389 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_390 = 390 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_391 = 391 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_392 = 392 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_393 = 393 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_394 = 394 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_395 = 395 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_396 = 396 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_397 = 397 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_398 = 398 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_399 = 399 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_400 = 400 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_401 = 401 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_402 = 402 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_403 = 403 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_404 = 404 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_405 = 405 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_406 = 406 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_407 = 407 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_408 = 408 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_409 = 409 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_410 = 410 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_411 = 411 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_412 = 412 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_413 = 413 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_414 = 414 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_415 = 415 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_416 = 416 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_417 = 417 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_418 = 418 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_419 = 419 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_420 = 420 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_421 = 421 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_422 = 422 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_423 = 423 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_424 = 424 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_425 = 425 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_426 = 426 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_427 = 427 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_428 = 428 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_429 = 429 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_430 = 430 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_431 = 431 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_432 = 432 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_433 = 433 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_434 = 434 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_435 = 435 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_436 = 436 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_437 = 437 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_438 = 438 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_439 = 439 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_440 = 440 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_441 = 441 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_442 = 442 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_443 = 443 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_444 = 444 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_445 = 445 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_446 = 446 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_447 = 447 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_448 = 448 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_449 = 449 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_450 = 450 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_451 = 451 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_452 = 452 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_453 = 453 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_454 = 454 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_455 = 455 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_456 = 456 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_457 = 457 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_458 = 458 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_459 = 459 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_460 = 460 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_461 = 461 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_462 = 462 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_463 = 463 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_464 = 464 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_465 = 465 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_466 = 466 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_467 = 467 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_468 = 468 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_469 = 469 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_470 = 470 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_471 = 471 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_472 = 472 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_473 = 473 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_474 = 474 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_475 = 475 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_476 = 476 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_477 = 477 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_478 = 478 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_479 = 479 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_480 = 480 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_481 = 481 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_482 = 482 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_483 = 483 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_484 = 484 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_485 = 485 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_486 = 486 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_487 = 487 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_488 = 488 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_489 = 489 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_490 = 490 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_491 = 491 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_492 = 492 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_493 = 493 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_494 = 494 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_495 = 495 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_496 = 496 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_497 = 497 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_498 = 498 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_499 = 499 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_500 = 500 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_501 = 501 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_502 = 502 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_503 = 503 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_504 = 504 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_505 = 505 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_506 = 506 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_507 = 507 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_508 = 508 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_509 = 509 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_510 = 510 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_511 = 511 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_512 = 512 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_513 = 513 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_514 = 514 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_515 = 515 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_516 = 516 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_517 = 517 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_518 = 518 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_519 = 519 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_520 = 520 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_521 = 521 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_522 = 522 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_523 = 523 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_524 = 524 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_525 = 525 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_526 = 526 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_527 = 527 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_528 = 528 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_529 = 529 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_530 = 530 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_531 = 531 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_532 = 532 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_533 = 533 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_534 = 534 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_535 = 535 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_536 = 536 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_537 = 537 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_538 = 538 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_539 = 539 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_540 = 540 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_541 = 541 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_542 = 542 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_543 = 543 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_544 = 544 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_545 = 545 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_546 = 546 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_547 = 547 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_548 = 548 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_549 = 549 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_550 = 550 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_551 = 551 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_552 = 552 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_553 = 553 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_554 = 554 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_555 = 555 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_556 = 556 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_557 = 557 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_558 = 558 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_559 = 559 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_560 = 560 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_561 = 561 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_562 = 562 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_563 = 563 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_564 = 564 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_565 = 565 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_566 = 566 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_567 = 567 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_568 = 568 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_569 = 569 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_570 = 570 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_571 = 571 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_572 = 572 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_573 = 573 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_574 = 574 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_575 = 575 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_576 = 576 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_577 = 577 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_578 = 578 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_579 = 579 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_580 = 580 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_581 = 581 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_582 = 582 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_583 = 583 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_584 = 584 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_585 = 585 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_586 = 586 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_587 = 587 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_588 = 588 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_589 = 589 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_590 = 590 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_591 = 591 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_592 = 592 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_593 = 593 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_594 = 594 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_595 = 595 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_596 = 596 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_597 = 597 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_598 = 598 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_599 = 599 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_600 = 600 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_601 = 601 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_602 = 602 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_603 = 603 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_604 = 604 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_605 = 605 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_606 = 606 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_607 = 607 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_608 = 608 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_609 = 609 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_610 = 610 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_611 = 611 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_612 = 612 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_613 = 613 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_614 = 614 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_615 = 615 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_616 = 616 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_617 = 617 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_618 = 618 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_619 = 619 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_620 = 620 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_621 = 621 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_622 = 622 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_623 = 623 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_624 = 624 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_625 = 625 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_626 = 626 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_627 = 627 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_628 = 628 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_629 = 629 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_630 = 630 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_631 = 631 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_632 = 632 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_633 = 633 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_634 = 634 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_635 = 635 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_636 = 636 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_637 = 637 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_638 = 638 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_639 = 639 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_640 = 640 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_641 = 641 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_642 = 642 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_643 = 643 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_644 = 644 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_645 = 645 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_646 = 646 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_647 = 647 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_648 = 648 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_649 = 649 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_650 = 650 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_651 = 651 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_652 = 652 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_653 = 653 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_654 = 654 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_655 = 655 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_656 = 656 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_657 = 657 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_658 = 658 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_659 = 659 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_660 = 660 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_661 = 661 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_662 = 662 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_663 = 663 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_664 = 664 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_665 = 665 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_666 = 666 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_667 = 667 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_668 = 668 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_669 = 669 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_670 = 670 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_671 = 671 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_672 = 672 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_673 = 673 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_674 = 674 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_675 = 675 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_676 = 676 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_677 = 677 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_678 = 678 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_679 = 679 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_680 = 680 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_681 = 681 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_682 = 682 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_683 = 683 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_684 = 684 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_685 = 685 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_686 = 686 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_687 = 687 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_688 = 688 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_689 = 689 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_690 = 690 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_691 = 691 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_692 = 692 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_693 = 693 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_694 = 694 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_695 = 695 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_696 = 696 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_697 = 697 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_698 = 698 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_699 = 699 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_700 = 700 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_701 = 701 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_702 = 702 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_703 = 703 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_704 = 704 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_705 = 705 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_706 = 706 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_707 = 707 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_708 = 708 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_709 = 709 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_710 = 710 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_711 = 711 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_712 = 712 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_713 = 713 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_714 = 714 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_715 = 715 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_716 = 716 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_717 = 717 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_718 = 718 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_719 = 719 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_720 = 720 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_721 = 721 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_722 = 722 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_723 = 723 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_724 = 724 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_725 = 725 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_726 = 726 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_727 = 727 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_728 = 728 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_729 = 729 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_730 = 730 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_731 = 731 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_732 = 732 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_733 = 733 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_734 = 734 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_735 = 735 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_736 = 736 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_737 = 737 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_738 = 738 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_739 = 739 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_740 = 740 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_741 = 741 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_742 = 742 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_743 = 743 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_744 = 744 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_745 = 745 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_746 = 746 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_747 = 747 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_748 = 748 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_749 = 749 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_750 = 750 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_751 = 751 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_752 = 752 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_753 = 753 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_754 = 754 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_755 = 755 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_756 = 756 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_757 = 757 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_758 = 758 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_759 = 759 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_760 = 760 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_761 = 761 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_762 = 762 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_763 = 763 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_764 = 764 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_765 = 765 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_766 = 766 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_767 = 767 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_768 = 768 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_769 = 769 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_770 = 770 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_771 = 771 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_772 = 772 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_773 = 773 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_774 = 774 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_775 = 775 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_776 = 776 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_777 = 777 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_778 = 778 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_779 = 779 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_780 = 780 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_781 = 781 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_782 = 782 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_783 = 783 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_784 = 784 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_785 = 785 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_786 = 786 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_787 = 787 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_788 = 788 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_789 = 789 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_790 = 790 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_791 = 791 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_792 = 792 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_793 = 793 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_794 = 794 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_795 = 795 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_796 = 796 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_797 = 797 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_798 = 798 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_799 = 799 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_800 = 800 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_801 = 801 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_802 = 802 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_803 = 803 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_804 = 804 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_805 = 805 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_806 = 806 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_807 = 807 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_808 = 808 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_809 = 809 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_810 = 810 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_811 = 811 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_812 = 812 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_813 = 813 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_814 = 814 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_815 = 815 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_816 = 816 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_817 = 817 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_818 = 818 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_819 = 819 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_820 = 820 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_821 = 821 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_822 = 822 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_823 = 823 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_824 = 824 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_825 = 825 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_826 = 826 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_827 = 827 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_828 = 828 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_829 = 829 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_830 = 830 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_831 = 831 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_832 = 832 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_833 = 833 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_834 = 834 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_835 = 835 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_836 = 836 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_837 = 837 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_838 = 838 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_839 = 839 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_840 = 840 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_841 = 841 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_842 = 842 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_843 = 843 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_844 = 844 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_845 = 845 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_846 = 846 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_847 = 847 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_848 = 848 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_849 = 849 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_850 = 850 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_851 = 851 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_852 = 852 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_853 = 853 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_854 = 854 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_855 = 855 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_856 = 856 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_857 = 857 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_858 = 858 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_859 = 859 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_860 = 860 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_861 = 861 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_862 = 862 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_863 = 863 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_864 = 864 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_865 = 865 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_866 = 866 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_867 = 867 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_868 = 868 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_869 = 869 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_870 = 870 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_871 = 871 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_872 = 872 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_873 = 873 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_874 = 874 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_875 = 875 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_876 = 876 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_877 = 877 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_878 = 878 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_879 = 879 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_880 = 880 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_881 = 881 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_882 = 882 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_883 = 883 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_884 = 884 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_885 = 885 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_886 = 886 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_887 = 887 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_888 = 888 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_889 = 889 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_890 = 890 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_891 = 891 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_892 = 892 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_893 = 893 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_894 = 894 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_895 = 895 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_896 = 896 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_897 = 897 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_898 = 898 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_899 = 899 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_900 = 900 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_901 = 901 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_902 = 902 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_903 = 903 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_904 = 904 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_905 = 905 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_906 = 906 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_907 = 907 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_908 = 908 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_909 = 909 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_910 = 910 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_911 = 911 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_912 = 912 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_913 = 913 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_914 = 914 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_915 = 915 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_916 = 916 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_917 = 917 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_918 = 918 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_919 = 919 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_920 = 920 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_921 = 921 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_922 = 922 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_923 = 923 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_924 = 924 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_925 = 925 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_926 = 926 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_927 = 927 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_928 = 928 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_929 = 929 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_930 = 930 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_931 = 931 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_932 = 932 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_933 = 933 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_934 = 934 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_935 = 935 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_936 = 936 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_937 = 937 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_938 = 938 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_939 = 939 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_940 = 940 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_941 = 941 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_942 = 942 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_943 = 943 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_944 = 944 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_945 = 945 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_946 = 946 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_947 = 947 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_948 = 948 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_949 = 949 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_950 = 950 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_951 = 951 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_952 = 952 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_953 = 953 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_954 = 954 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_955 = 955 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_956 = 956 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_957 = 957 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_958 = 958 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_959 = 959 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_960 = 960 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_961 = 961 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_962 = 962 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_963 = 963 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_964 = 964 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_965 = 965 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_966 = 966 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_967 = 967 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_968 = 968 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_969 = 969 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_970 = 970 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_971 = 971 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_972 = 972 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_973 = 973 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_974 = 974 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_975 = 975 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_976 = 976 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_977 = 977 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_978 = 978 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_979 = 979 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_980 = 980 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_981 = 981 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_982 = 982 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_983 = 983 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_984 = 984 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_985 = 985 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_986 = 986 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_987 = 987 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_988 = 988 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_989 = 989 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_990 = 990 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_991 = 991 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_992 = 992 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_993 = 993 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_994 = 994 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_995 = 995 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_996 = 996 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_997 = 997 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_998 = 998 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_999 = 999 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000 = 1000 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import.proto
new file mode 100644
index 0000000..8d03e38
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import.proto
@@ -0,0 +1,73 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which is imported by unittest.proto to test importing.
+
+syntax = "proto2";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do
+// "using namespace unittest_import = protobuf_unittest_import".
+package protobuf_unittest_import;
+
+option optimize_for = SPEED;
+option cc_enable_arenas = true;
+
+// Exercise the java_package option.
+option java_package = "com.google.protobuf.test";
+
+// Do not set a java_outer_classname here to verify that Proto2 works without
+// one.
+
+// Test public import
+import public "google/protobuf/unittest_import_public.proto";
+
+message ImportMessage {
+  optional int32 d = 1;
+}
+
+enum ImportEnum {
+  IMPORT_FOO = 7;
+  IMPORT_BAR = 8;
+  IMPORT_BAZ = 9;
+}
+
+
+// To use an enum in a map, it must has the first value as 0.
+enum ImportEnumForMap {
+  UNKNOWN = 0;
+  FOO = 1;
+  BAR = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_lite.proto
new file mode 100644
index 0000000..a7afa45
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_lite.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
+
+syntax = "proto2";
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+import public "google/protobuf/unittest_import_public_lite.proto";
+
+message ImportMessageLite {
+  optional int32 d = 1;
+}
+
+enum ImportEnumLite {
+  IMPORT_LITE_FOO = 7;
+  IMPORT_LITE_BAR = 8;
+  IMPORT_LITE_BAZ = 9;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import_proto3.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_proto3.proto
new file mode 100644
index 0000000..59673ea
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_proto3.proto
@@ -0,0 +1,68 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which is imported by unittest_proto3.proto to test importing.
+
+syntax = "proto3";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do
+// "using namespace unittest_import = protobuf_unittest_import".
+package protobuf_unittest_import;
+
+option optimize_for = SPEED;
+option cc_enable_arenas = true;
+
+// Exercise the java_package option.
+option java_package = "com.google.protobuf.test";
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+// Do not set a java_outer_classname here to verify that Proto2 works without
+// one.
+
+// Test public import
+import public "google/protobuf/unittest_import_public_proto3.proto";
+
+message ImportMessage {
+  int32 d = 1;
+}
+
+enum ImportEnum {
+  IMPORT_ENUM_UNSPECIFIED = 0;
+  IMPORT_FOO = 7;
+  IMPORT_BAR = 8;
+  IMPORT_BAZ = 9;
+}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000..ffaf773
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public.proto
@@ -0,0 +1,41 @@
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+syntax = "proto2";
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+
+message PublicImportMessage {
+  optional int32 e = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000..33549c2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_lite.proto
@@ -0,0 +1,43 @@
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+syntax = "proto2";
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message PublicImportMessageLite {
+  optional int32 e = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_proto3.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_proto3.proto
new file mode 100644
index 0000000..d6f11e2
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_import_public_proto3.proto
@@ -0,0 +1,42 @@
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+syntax = "proto3";
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+message PublicImportMessage {
+ int32 e = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_lite.proto
new file mode 100644
index 0000000..878ec7c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_lite.proto
@@ -0,0 +1,407 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
+
+syntax = "proto2";
+package protobuf_unittest;
+
+import "google/protobuf/unittest_import_lite.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+// Same as TestAllTypes but with the lite runtime.
+message TestAllTypesLite {
+
+  message NestedMessage {
+    optional int32 bb = 1;
+    optional int64 cc = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage      optional_nested_message  = 18;
+  optional ForeignMessageLite optional_foreign_message = 19;
+  optional protobuf_unittest_import.ImportMessageLite
+    optional_import_message = 20;
+
+  optional NestedEnum      optional_nested_enum     = 21;
+  optional ForeignEnumLite optional_foreign_enum    = 22;
+  optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  optional protobuf_unittest_import.PublicImportMessageLite
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage      repeated_nested_message  = 48;
+  repeated ForeignMessageLite repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessageLite
+    repeated_import_message = 50;
+
+  repeated NestedEnum      repeated_nested_enum  = 51;
+  repeated ForeignEnumLite repeated_foreign_enum = 52;
+  repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+  optional NestedEnum default_nested_enum = 81 [default = BAR];
+  optional ForeignEnumLite default_foreign_enum = 82
+      [default = FOREIGN_LITE_BAR];
+  optional protobuf_unittest_import.ImportEnumLite
+      default_import_enum = 83 [default = IMPORT_LITE_BAR];
+
+  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+  optional string default_cord = 85 [ctype=CORD,default="123"];
+
+  // For oneof test
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+    NestedMessage oneof_lazy_nested_message = 115 [lazy = true];
+  }
+}
+
+message ForeignMessageLite {
+  optional int32 c = 1;
+}
+
+enum ForeignEnumLite {
+  FOREIGN_LITE_FOO = 4;
+  FOREIGN_LITE_BAR = 5;
+  FOREIGN_LITE_BAZ = 6;
+}
+
+message TestPackedTypesLite {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnumLite packed_enum  = 103 [packed = true];
+}
+
+message TestAllExtensionsLite {
+  extensions 1 to max;
+}
+
+extend TestAllExtensionsLite {
+  // Singular
+  optional    int32 optional_int32_extension_lite    =  1;
+  optional    int64 optional_int64_extension_lite    =  2;
+  optional   uint32 optional_uint32_extension_lite   =  3;
+  optional   uint64 optional_uint64_extension_lite   =  4;
+  optional   sint32 optional_sint32_extension_lite   =  5;
+  optional   sint64 optional_sint64_extension_lite   =  6;
+  optional  fixed32 optional_fixed32_extension_lite  =  7;
+  optional  fixed64 optional_fixed64_extension_lite  =  8;
+  optional sfixed32 optional_sfixed32_extension_lite =  9;
+  optional sfixed64 optional_sfixed64_extension_lite = 10;
+  optional    float optional_float_extension_lite    = 11;
+  optional   double optional_double_extension_lite   = 12;
+  optional     bool optional_bool_extension_lite     = 13;
+  optional   string optional_string_extension_lite   = 14;
+  optional    bytes optional_bytes_extension_lite    = 15;
+
+  optional group OptionalGroup_extension_lite = 16 {
+    optional int32 a = 17;
+  }
+
+  optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
+      = 18;
+  optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
+  optional protobuf_unittest_import.ImportMessageLite
+    optional_import_message_extension_lite = 20;
+
+  optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
+  optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
+  optional protobuf_unittest_import.ImportEnumLite
+    optional_import_enum_extension_lite = 23;
+
+  optional string optional_string_piece_extension_lite = 24
+      [ctype=STRING_PIECE];
+  optional string optional_cord_extension_lite = 25 [ctype=CORD];
+
+  optional protobuf_unittest_import.PublicImportMessageLite
+    optional_public_import_message_extension_lite = 26;
+
+  optional TestAllTypesLite.NestedMessage
+    optional_lazy_message_extension_lite = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32_extension_lite    = 31;
+  repeated    int64 repeated_int64_extension_lite    = 32;
+  repeated   uint32 repeated_uint32_extension_lite   = 33;
+  repeated   uint64 repeated_uint64_extension_lite   = 34;
+  repeated   sint32 repeated_sint32_extension_lite   = 35;
+  repeated   sint64 repeated_sint64_extension_lite   = 36;
+  repeated  fixed32 repeated_fixed32_extension_lite  = 37;
+  repeated  fixed64 repeated_fixed64_extension_lite  = 38;
+  repeated sfixed32 repeated_sfixed32_extension_lite = 39;
+  repeated sfixed64 repeated_sfixed64_extension_lite = 40;
+  repeated    float repeated_float_extension_lite    = 41;
+  repeated   double repeated_double_extension_lite   = 42;
+  repeated     bool repeated_bool_extension_lite     = 43;
+  repeated   string repeated_string_extension_lite   = 44;
+  repeated    bytes repeated_bytes_extension_lite    = 45;
+
+  repeated group RepeatedGroup_extension_lite = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
+      = 48;
+  repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
+  repeated protobuf_unittest_import.ImportMessageLite
+    repeated_import_message_extension_lite = 50;
+
+  repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
+  repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
+  repeated protobuf_unittest_import.ImportEnumLite
+    repeated_import_enum_extension_lite = 53;
+
+  repeated string repeated_string_piece_extension_lite = 54
+      [ctype=STRING_PIECE];
+  repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
+
+  repeated TestAllTypesLite.NestedMessage
+    repeated_lazy_message_extension_lite = 57 [lazy=true];
+
+  // Singular with defaults
+  optional    int32 default_int32_extension_lite    = 61 [default =  41    ];
+  optional    int64 default_int64_extension_lite    = 62 [default =  42    ];
+  optional   uint32 default_uint32_extension_lite   = 63 [default =  43    ];
+  optional   uint64 default_uint64_extension_lite   = 64 [default =  44    ];
+  optional   sint32 default_sint32_extension_lite   = 65 [default = -45    ];
+  optional   sint64 default_sint64_extension_lite   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32_extension_lite  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64_extension_lite  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32_extension_lite = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50    ];
+  optional    float default_float_extension_lite    = 71 [default =  51.5  ];
+  optional   double default_double_extension_lite   = 72 [default =  52e3  ];
+  optional     bool default_bool_extension_lite     = 73 [default = true   ];
+  optional   string default_string_extension_lite   = 74 [default = "hello"];
+  optional    bytes default_bytes_extension_lite    = 75 [default = "world"];
+
+  optional TestAllTypesLite.NestedEnum
+    default_nested_enum_extension_lite = 81 [default = BAR];
+  optional ForeignEnumLite
+    default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
+  optional protobuf_unittest_import.ImportEnumLite
+    default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
+
+  optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
+                                                            default="abc"];
+  optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
+
+  // For oneof test
+  optional uint32 oneof_uint32_extension_lite = 111;
+  optional TestAllTypesLite.NestedMessage oneof_nested_message_extension_lite = 112;
+  optional string oneof_string_extension_lite = 113;
+  optional bytes oneof_bytes_extension_lite = 114;
+}
+
+message TestPackedExtensionsLite {
+  extensions 1 to max;
+}
+
+extend TestPackedExtensionsLite {
+  repeated    int32 packed_int32_extension_lite    =  90 [packed = true];
+  repeated    int64 packed_int64_extension_lite    =  91 [packed = true];
+  repeated   uint32 packed_uint32_extension_lite   =  92 [packed = true];
+  repeated   uint64 packed_uint64_extension_lite   =  93 [packed = true];
+  repeated   sint32 packed_sint32_extension_lite   =  94 [packed = true];
+  repeated   sint64 packed_sint64_extension_lite   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32_extension_lite  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64_extension_lite  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32_extension_lite =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64_extension_lite =  99 [packed = true];
+  repeated    float packed_float_extension_lite    = 100 [packed = true];
+  repeated   double packed_double_extension_lite   = 101 [packed = true];
+  repeated     bool packed_bool_extension_lite     = 102 [packed = true];
+  repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
+}
+
+message TestNestedExtensionLite {
+  extend TestAllExtensionsLite {
+    optional int32 nested_extension = 12345;
+  }
+}
+
+// Test that deprecated fields work.  We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedLite {
+  optional int32 deprecated_field = 1 [deprecated = true];
+}
+
+// See the comments of the same type in unittest.proto.
+message TestParsingMergeLite {
+  message RepeatedFieldsGenerator {
+    repeated TestAllTypesLite field1 = 1;
+    repeated TestAllTypesLite field2 = 2;
+    repeated TestAllTypesLite field3 = 3;
+    repeated group Group1 = 10 {
+      optional TestAllTypesLite field1 = 11;
+    }
+    repeated group Group2 = 20 {
+      optional TestAllTypesLite field1 = 21;
+    }
+    repeated TestAllTypesLite ext1 = 1000;
+    repeated TestAllTypesLite ext2 = 1001;
+  }
+  required TestAllTypesLite required_all_types = 1;
+  optional TestAllTypesLite optional_all_types = 2;
+  repeated TestAllTypesLite repeated_all_types = 3;
+  optional group OptionalGroup = 10 {
+    optional TestAllTypesLite optional_group_all_types = 11;
+  }
+  repeated group RepeatedGroup = 20 {
+    optional TestAllTypesLite repeated_group_all_types = 21;
+  }
+  extensions 1000 to max;
+  extend TestParsingMergeLite {
+    optional TestAllTypesLite optional_ext = 1000;
+    repeated TestAllTypesLite repeated_ext = 1001;
+  }
+}
+
+// TestEmptyMessageLite is used to test unknown fields support in lite mode.
+message TestEmptyMessageLite{
+}
+
+// Like above, but declare all field numbers as potential extensions.  No
+// actual extensions should ever be defined for this type.
+message TestEmptyMessageWithExtensionsLite {
+  extensions 1 to max;
+}
+
+enum V1EnumLite {
+    V1_FIRST = 1;
+}
+
+enum V2EnumLite {
+    V2_FIRST = 1;
+    V2_SECOND = 2;
+}
+
+message V1MessageLite {
+    required int32 int_field = 1;
+    optional V1EnumLite enum_field = 2 [ default = V1_FIRST ];
+}
+
+message V2MessageLite {
+    required int32 int_field = 1;
+    optional V2EnumLite enum_field = 2 [ default = V2_FIRST ];
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_lite_imports_nonlite.proto
new file mode 100644
index 0000000..132d6a8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -0,0 +1,44 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Tests that a "lite" message can import a regular message.
+
+syntax = "proto2";
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+message TestLiteImportsNonlite {
+  optional TestAllTypes message = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_mset.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_mset.proto
new file mode 100644
index 0000000..49d9ada
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_mset.proto
@@ -0,0 +1,82 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file is similar to unittest_mset_wire_format.proto, but does not
+// have a TestMessageSet, so it can be downgraded to proto1.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest_mset_wire_format.proto";
+
+package protobuf_unittest;
+
+option cc_enable_arenas = true;
+option optimize_for = SPEED;
+
+message TestMessageSetContainer {
+  optional proto2_wireformat_unittest.TestMessageSet message_set = 1;
+}
+
+message TestMessageSetExtension1 {
+  extend proto2_wireformat_unittest.TestMessageSet {
+    optional TestMessageSetExtension1 message_set_extension = 1545008;
+  }
+  optional int32 i = 15;
+}
+
+message TestMessageSetExtension2 {
+  extend proto2_wireformat_unittest.TestMessageSet {
+    optional TestMessageSetExtension2 message_set_extension = 1547769;
+  }
+  optional string str = 25;
+}
+
+// This message was used to generate
+// //net/proto2/python/internal/testdata/message_set_message, but is commented
+// out since it must not actually exist in code, to simulate an "unknown"
+// extension.
+// message TestMessageSetUnknownExtension {
+//   extend TestMessageSet {
+//     optional TestMessageSetUnknownExtension message_set_extension = 56141421;
+//   }
+//   optional int64 a = 1;
+// }
+
+// MessageSet wire format is equivalent to this.
+message RawMessageSet {
+  repeated group Item = 1 {
+    required int32 type_id = 2;
+    required bytes message = 3;
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_mset_wire_format.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_mset_wire_format.proto
new file mode 100644
index 0000000..04e4352
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_mset_wire_format.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing message_set_wire_format.
+
+syntax = "proto2";
+package proto2_wireformat_unittest;
+
+option cc_enable_arenas = true;
+option optimize_for = SPEED;
+option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message TestMessageSetWireFormatContainer {
+  optional TestMessageSet message_set = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena.proto
new file mode 100644
index 0000000..41518df
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena.proto
@@ -0,0 +1,202 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This proto file contains copies of TestAllTypes and friends, but with arena
+// support disabled in code generation. It allows us to test the performance
+// impact against baseline (non-arena) google.protobuf.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;     // auto-added
+option cc_enable_arenas = false;
+option objc_class_prefix = "NOARN";
+
+import "google/protobuf/unittest_import.proto";
+import "google/protobuf/unittest_arena.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest_no_arena;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    optional int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional NestedMessage                        optional_nested_message  = 18;
+  optional ForeignMessage                       optional_foreign_message = 19;
+  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  optional NestedEnum                           optional_nested_enum     = 21;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  optional protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  // Singular with defaults
+  optional    int32 default_int32    = 61 [default =  41    ];
+  optional    int64 default_int64    = 62 [default =  42    ];
+  optional   uint32 default_uint32   = 63 [default =  43    ];
+  optional   uint64 default_uint64   = 64 [default =  44    ];
+  optional   sint32 default_sint32   = 65 [default = -45    ];
+  optional   sint64 default_sint64   = 66 [default =  46    ];
+  optional  fixed32 default_fixed32  = 67 [default =  47    ];
+  optional  fixed64 default_fixed64  = 68 [default =  48    ];
+  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
+  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
+  optional    float default_float    = 71 [default =  51.5  ];
+  optional   double default_double   = 72 [default =  52e3  ];
+  optional     bool default_bool     = 73 [default = true   ];
+  optional   string default_string   = 74 [default = "hello"];
+  optional    bytes default_bytes    = 75 [default = "world"];
+
+  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
+  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
+  optional protobuf_unittest_import.ImportEnum
+      default_import_enum = 83 [default = IMPORT_BAR];
+
+  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+  optional string default_cord = 85 [ctype=CORD,default="123"];
+
+  // For oneof test
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+    NestedMessage lazy_oneof_nested_message = 115 [lazy=true];
+  }
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  optional int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestNoArenaMessage {
+  optional proto2_arena_unittest.ArenaMessage arena_message = 1;
+};
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_import.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_import.proto
new file mode 100644
index 0000000..072af49
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_import.proto
@@ -0,0 +1,37 @@
+// 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.
+
+syntax = "proto2";
+
+package proto2_arena_unittest;
+
+message ImportNoArenaNestedMessage {
+  optional int32 d = 1;
+};
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_lite.proto
new file mode 100644
index 0000000..34c7b7c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_arena_lite.proto
@@ -0,0 +1,42 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest_no_arena;
+
+message ForeignMessageLite {
+  optional int32 c = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_no_field_presence.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_field_presence.proto
new file mode 100644
index 0000000..994afff
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_field_presence.proto
@@ -0,0 +1,138 @@
+// 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.
+
+// A proto file used to test a message type with no explicit field presence.
+
+syntax = "proto3";
+
+// We want to test embedded proto2 messages, so include some proto2 types.
+import "google/protobuf/unittest.proto";
+
+package proto2_nofieldpresence_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+  }
+
+  // Singular
+  // TODO: remove 'optional' labels as soon as CL 69188077 is LGTM'd to make
+  // 'optional' optional.
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+  protobuf_unittest.TestAllTypes         optional_proto2_message = 20;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+  // N.B.: proto2-enum-type fields not allowed, because their default values
+  // might not be zero.
+  //optional protobuf_unittest.ForeignEnum          optional_proto2_enum     = 23;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  NestedMessage optional_lazy_message = 30 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest.TestAllTypes         repeated_proto2_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    NestedEnum oneof_enum = 114;
+  }
+}
+
+message TestProto2Required {
+  protobuf_unittest.TestRequired proto2 = 1;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 0;
+  FOREIGN_BAR = 1;
+  FOREIGN_BAZ = 2;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_no_generic_services.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_generic_services.proto
new file mode 100644
index 0000000..8fc7713
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_no_generic_services.proto
@@ -0,0 +1,54 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+syntax = "proto2";
+package google.protobuf.no_generic_services_test;
+
+
+// *_generic_services are false by default.
+
+message TestMessage {
+  optional int32 a = 1;
+  extensions 1000 to max;
+}
+
+enum TestEnum {
+  FOO = 1;
+}
+
+extend TestMessage {
+  optional int32 test_extension = 1000;
+}
+
+service TestService {
+  rpc Foo(TestMessage) returns(TestMessage);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_optimize_for.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_optimize_for.proto
new file mode 100644
index 0000000..ee9cc7b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_optimize_for.proto
@@ -0,0 +1,67 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which uses optimize_for = CODE_SIZE.
+
+syntax = "proto2";
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+option optimize_for = CODE_SIZE;
+
+message TestOptimizedForSize {
+  optional int32 i = 1;
+  optional ForeignMessage msg = 19;
+
+  extensions 1000 to max;
+
+  extend TestOptimizedForSize {
+    optional int32 test_extension = 1234;
+    optional TestRequiredOptimizedForSize test_extension2 = 1235;
+  }
+
+  oneof foo {
+    int32 integer_field = 2;
+    string string_field = 3;
+  }
+}
+
+message TestRequiredOptimizedForSize {
+  required int32 x = 1;
+}
+
+message TestOptionalOptimizedForSize {
+  optional TestRequiredOptimizedForSize o = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum.proto
new file mode 100644
index 0000000..2f91332
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -0,0 +1,71 @@
+// 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.
+
+syntax = "proto3";
+
+package proto3_preserve_unknown_enum_unittest;
+option objc_class_prefix = "UnknownEnums";
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+enum MyEnum {
+  FOO = 0;
+  BAR = 1;
+  BAZ = 2;
+}
+
+enum MyEnumPlusExtra {
+  E_FOO = 0;
+  E_BAR = 1;
+  E_BAZ = 2;
+  E_EXTRA = 3;
+}
+
+message MyMessage {
+  MyEnum e = 1;
+  repeated MyEnum repeated_e = 2;
+  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4;  // not packed
+  oneof o {
+    MyEnum oneof_e_1 = 5;
+    MyEnum oneof_e_2 = 6;
+  }
+}
+
+message MyMessagePlusExtra {
+  MyEnumPlusExtra e = 1;
+  repeated MyEnumPlusExtra repeated_e = 2;
+  repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
+  oneof o {
+    MyEnumPlusExtra oneof_e_1 = 5;
+    MyEnumPlusExtra oneof_e_2 = 6;
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum2.proto
new file mode 100644
index 0000000..adf4296
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_preserve_unknown_enum2.proto
@@ -0,0 +1,50 @@
+// 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.
+
+syntax = "proto2";
+
+package proto2_preserve_unknown_enum_unittest;
+
+enum MyEnum {
+  FOO = 0;
+  BAR = 1;
+  BAZ = 2;
+}
+
+message MyMessage {
+  optional MyEnum e = 1;
+  repeated MyEnum repeated_e = 2;
+  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnum repeated_packed_unexpected_e = 4;  // not packed
+  oneof o {
+    MyEnum oneof_e_1 = 5;
+    MyEnum oneof_e_2 = 6;
+  }
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3.proto
new file mode 100644
index 0000000..f59d217
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3.proto
@@ -0,0 +1,388 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file we will use for unit testing.
+
+syntax = "proto3";
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;     // auto-added
+option cc_enable_arenas = true;
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+import "google/protobuf/unittest_import_proto3.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    NESTED_ENUM_UNSPECIFIED = 0;
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  int32 single_int32 = 1;
+  int64 single_int64 = 2;
+  uint32 single_uint32 = 3;
+  uint64 single_uint64 = 4;
+  sint32 single_sint32 = 5;
+  sint64 single_sint64 = 6;
+  fixed32 single_fixed32 = 7;
+  fixed64 single_fixed64 = 8;
+  sfixed32 single_sfixed32 = 9;
+  sfixed64 single_sfixed64 = 10;
+  float single_float = 11;
+  double single_double = 12;
+  bool single_bool = 13;
+  string single_string = 14;
+  bytes single_bytes = 15;
+
+  NestedMessage single_nested_message = 18;
+  ForeignMessage single_foreign_message = 19;
+  protobuf_unittest_import.ImportMessage single_import_message = 20;
+
+  NestedEnum single_nested_enum = 21;
+  ForeignEnum single_foreign_enum = 22;
+  protobuf_unittest_import.ImportEnum single_import_enum = 23;
+
+  // Defined in unittest_import_public.proto
+  protobuf_unittest_import.PublicImportMessage
+      single_public_import_message = 26;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
+  // Defined in unittest_import_public.proto
+  repeated protobuf_unittest_import.PublicImportMessage
+      repeated_public_import_message = 54;
+
+  // For oneof test
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
+  repeated NestedTestAllTypes repeated_child = 3;
+}
+
+message TestDeprecatedFields {
+  int32 deprecated_int32 = 1 [deprecated=true];
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_UNSPECIFIED = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestReservedFields {
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
+
+// Test that we can use NestedMessage from outside TestAllTypes.
+message TestForeignNested {
+  TestAllTypes.NestedMessage foreign_nested = 1;
+}
+
+// Test that really large tag numbers don't break anything.
+message TestReallyLargeTagNumber {
+  // The largest possible tag number is 2^28 - 1, since the wire format uses
+  // three bits to communicate wire type.
+  int32 a = 1;
+  int32 bb = 268435455;
+}
+
+message TestRecursiveMessage {
+  TestRecursiveMessage a = 1;
+  int32 i = 2;
+}
+
+// Test that mutual recursion works.
+message TestMutualRecursionA {
+  TestMutualRecursionB bb = 1;
+}
+
+message TestMutualRecursionB {
+  TestMutualRecursionA a = 1;
+  int32 optional_int32 = 2;
+}
+
+
+// Test an enum that has multiple values with the same number.
+enum TestEnumWithDupValue {
+  TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0;
+  option allow_alias = true;
+
+  FOO1 = 1;
+  BAR1 = 2;
+  BAZ = 3;
+  FOO2 = 1;
+  BAR2 = 2;
+}
+
+// Test an enum with large, unordered values.
+enum TestSparseEnum {
+  TEST_SPARSE_ENUM_UNSPECIFIED = 0;
+  SPARSE_A = 123;
+  SPARSE_B = 62374;
+  SPARSE_C = 12589234;
+  SPARSE_D = -15;
+  SPARSE_E = -53452;
+  // In proto3, value 0 must be the first one specified
+  // SPARSE_F = 0;
+  SPARSE_G = 2;
+}
+
+// Test message with CamelCase field names.  This violates Protocol Buffer
+// standard style.
+message TestCamelCaseFieldNames {
+  int32 PrimitiveField = 1;
+  string StringField = 2;
+  ForeignEnum EnumField = 3;
+  ForeignMessage MessageField = 4;
+
+  repeated int32 RepeatedPrimitiveField = 7;
+  repeated string RepeatedStringField = 8;
+  repeated ForeignEnum RepeatedEnumField = 9;
+  repeated ForeignMessage RepeatedMessageField = 10;
+}
+
+
+// We list fields out of order, to ensure that we're using field number and not
+// field index to determine serialization order.
+message TestFieldOrderings {
+  string my_string = 11;
+  int64 my_int = 1;
+  float my_float = 101;
+  message NestedMessage {
+    int64 oo = 2;
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    int32 bb = 1;
+  }
+
+  NestedMessage single_nested_message  = 200;
+}
+
+message SparseEnumMessage {
+  TestSparseEnum sparse_enum = 1;
+}
+
+// Test String and Bytes: string is for valid UTF-8 strings
+message OneString {
+  string data = 1;
+}
+
+message MoreString {
+  repeated string data = 1;
+}
+
+message OneBytes {
+  bytes data = 1;
+}
+
+message MoreBytes {
+  bytes data = 1;
+}
+
+// Test int32, uint32, int64, uint64, and bool are all compatible
+message Int32Message {
+  int32 data = 1;
+}
+
+message Uint32Message {
+  uint32 data = 1;
+}
+
+message Int64Message {
+  int64 data = 1;
+}
+
+message Uint64Message {
+  uint64 data = 1;
+}
+
+message BoolMessage {
+  bool data = 1;
+}
+
+// Test oneofs.
+message TestOneof {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    TestAllTypes foo_message = 3;
+  }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+  repeated    int32 unpacked_int32    =  90 [packed = false];
+  repeated    int64 unpacked_int64    =  91 [packed = false];
+  repeated   uint32 unpacked_uint32   =  92 [packed = false];
+  repeated   uint64 unpacked_uint64   =  93 [packed = false];
+  repeated   sint32 unpacked_sint32   =  94 [packed = false];
+  repeated   sint64 unpacked_sint64   =  95 [packed = false];
+  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
+  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
+  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
+  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
+  repeated    float unpacked_float    = 100 [packed = false];
+  repeated   double unpacked_double   = 101 [packed = false];
+  repeated     bool unpacked_bool     = 102 [packed = false];
+  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+  // Parsing repeated fixed size values used to fail. This message needs to be
+  // used in order to get a tag of the right size; all of the repeated fields
+  // in TestAllTypes didn't trigger the check.
+  repeated fixed32 repeated_fixed32 = 12;
+  // Check for a varint type, just for good measure.
+  repeated int32   repeated_int32   = 13;
+
+  // These have two-byte tags.
+  repeated fixed64 repeated_fixed64 = 2046;
+  repeated int64   repeated_int64   = 2047;
+
+  // Three byte tags.
+  repeated float   repeated_float   = 262142;
+  repeated uint64  repeated_uint64  = 262143;
+}
+
+message TestCommentInjectionMessage {
+  // */ <- This should not close the generated doc comment
+  string a = 1;
+}
+
+
+// Test that RPC services work.
+message FooRequest  {}
+message FooResponse {}
+
+message FooClientMessage {}
+message FooServerMessage{}
+
+service TestService {
+  rpc Foo(FooRequest) returns (FooResponse);
+  rpc Bar(BarRequest) returns (BarResponse);
+}
+
+
+message BarRequest  {}
+message BarResponse {}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena.proto
new file mode 100644
index 0000000..b835a6b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena.proto
@@ -0,0 +1,206 @@
+// 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.
+
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_arena_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    ZERO = 0;
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  // Groups are not allowed in proto3.
+  // optional group OptionalGroup = 16 {
+  //   optional int32 a = 17;
+  // }
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+  protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // optional protobuf_unittest_import.ImportEnum    optional_import_enum  = 23;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  NestedMessage optional_lazy_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  // Groups are not allowed in proto3.
+  // repeated group RepeatedGroup = 46 {
+  //   optional int32 a = 47;
+  // }
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // repeated protobuf_unittest_import.ImportEnum    repeated_import_enum  = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// Explicitly set packed to false
+message TestUnpackedTypes {
+  repeated    int32 repeated_int32    =  1 [packed = false];
+  repeated    int64 repeated_int64    =  2 [packed = false];
+  repeated   uint32 repeated_uint32   =  3 [packed = false];
+  repeated   uint64 repeated_uint64   =  4 [packed = false];
+  repeated   sint32 repeated_sint32   =  5 [packed = false];
+  repeated   sint64 repeated_sint64   =  6 [packed = false];
+  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
+  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+  repeated    float repeated_float    = 11 [packed = false];
+  repeated   double repeated_double   = 12 [packed = false];
+  repeated     bool repeated_bool     = 13 [packed = false];
+  repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_ZERO = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena_lite.proto
new file mode 100644
index 0000000..5a60b90
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_arena_lite.proto
@@ -0,0 +1,207 @@
+// 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.
+
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+option optimize_for = LITE_RUNTIME;
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_arena_lite_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    ZERO = 0;
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  // Groups are not allowed in proto3.
+  // optional group OptionalGroup = 16 {
+  //   optional int32 a = 17;
+  // }
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+  protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // optional protobuf_unittest_import.ImportEnum    optional_import_enum  = 23;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  NestedMessage optional_lazy_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  // Groups are not allowed in proto3.
+  // repeated group RepeatedGroup = 46 {
+  //   optional int32 a = 47;
+  // }
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // repeated protobuf_unittest_import.ImportEnum    repeated_import_enum  = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// Explicitly set packed to false
+message TestUnpackedTypes {
+  repeated    int32 repeated_int32    =  1 [packed = false];
+  repeated    int64 repeated_int64    =  2 [packed = false];
+  repeated   uint32 repeated_uint32   =  3 [packed = false];
+  repeated   uint64 repeated_uint64   =  4 [packed = false];
+  repeated   sint32 repeated_sint32   =  5 [packed = false];
+  repeated   sint64 repeated_sint64   =  6 [packed = false];
+  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
+  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+  repeated    float repeated_float    = 11 [packed = false];
+  repeated   double repeated_double   = 12 [packed = false];
+  repeated     bool repeated_bool     = 13 [packed = false];
+  repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_ZERO = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_lite.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_lite.proto
new file mode 100644
index 0000000..874ade6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_proto3_lite.proto
@@ -0,0 +1,206 @@
+// 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.
+
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_lite_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    // The field name "b" fails to compile in proto1 because it conflicts with
+    // a local variable named "b" in one of the generated methods.  Doh.
+    // This file needs to compile in proto1 to test backwards-compatibility.
+    int32 bb = 1;
+  }
+
+  enum NestedEnum {
+    ZERO = 0;
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  // Groups are not allowed in proto3.
+  // optional group OptionalGroup = 16 {
+  //   optional int32 a = 17;
+  // }
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+  protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // optional protobuf_unittest_import.ImportEnum    optional_import_enum  = 23;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  // Defined in unittest_import_public.proto
+  protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  NestedMessage optional_lazy_message = 27 [lazy=true];
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  // Groups are not allowed in proto3.
+  // repeated group RepeatedGroup = 46 {
+  //   optional int32 a = 47;
+  // }
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // repeated protobuf_unittest_import.ImportEnum    repeated_import_enum  = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+  repeated    int32 packed_int32    =  90 [packed = true];
+  repeated    int64 packed_int64    =  91 [packed = true];
+  repeated   uint32 packed_uint32   =  92 [packed = true];
+  repeated   uint64 packed_uint64   =  93 [packed = true];
+  repeated   sint32 packed_sint32   =  94 [packed = true];
+  repeated   sint64 packed_sint64   =  95 [packed = true];
+  repeated  fixed32 packed_fixed32  =  96 [packed = true];
+  repeated  fixed64 packed_fixed64  =  97 [packed = true];
+  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
+  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
+  repeated    float packed_float    = 100 [packed = true];
+  repeated   double packed_double   = 101 [packed = true];
+  repeated     bool packed_bool     = 102 [packed = true];
+  repeated ForeignEnum packed_enum  = 103 [packed = true];
+}
+
+// Explicitly set packed to false
+message TestUnpackedTypes {
+  repeated    int32 repeated_int32    =  1 [packed = false];
+  repeated    int64 repeated_int64    =  2 [packed = false];
+  repeated   uint32 repeated_uint32   =  3 [packed = false];
+  repeated   uint64 repeated_uint64   =  4 [packed = false];
+  repeated   sint32 repeated_sint32   =  5 [packed = false];
+  repeated   sint64 repeated_sint64   =  6 [packed = false];
+  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
+  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+  repeated    float repeated_float    = 11 [packed = false];
+  repeated   double repeated_double   = 12 [packed = false];
+  repeated     bool repeated_bool     = 13 [packed = false];
+  repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_ZERO = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unittest_well_known_types.proto b/src/third_party/protobuf-3/src/google/protobuf/unittest_well_known_types.proto
new file mode 100644
index 0000000..c907524
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unittest_well_known_types.proto
@@ -0,0 +1,114 @@
+syntax = "proto3";
+
+package protobuf_unittest;
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
+option java_multiple_files = true;
+option java_package = "com.google.protobuf.test";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/api.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/source_context.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/type.proto";
+import "google/protobuf/wrappers.proto";
+
+// Test that we can include all well-known types.
+// Each wrapper type is included separately, as languages
+// map handle different wrappers in different ways.
+message TestWellKnownTypes {
+  google.protobuf.Any any_field = 1;
+  google.protobuf.Api api_field = 2;
+  google.protobuf.Duration duration_field = 3;
+  google.protobuf.Empty empty_field = 4;
+  google.protobuf.FieldMask field_mask_field = 5;
+  google.protobuf.SourceContext source_context_field = 6;
+  google.protobuf.Struct struct_field = 7;
+  google.protobuf.Timestamp timestamp_field = 8;
+  google.protobuf.Type type_field = 9;
+  google.protobuf.DoubleValue double_field = 10;
+  google.protobuf.FloatValue float_field = 11;
+  google.protobuf.Int64Value int64_field = 12;
+  google.protobuf.UInt64Value uint64_field = 13;
+  google.protobuf.Int32Value int32_field = 14;
+  google.protobuf.UInt32Value uint32_field = 15;
+  google.protobuf.BoolValue bool_field = 16;
+  google.protobuf.StringValue string_field = 17;
+  google.protobuf.BytesValue bytes_field = 18;
+  // Part of struct, but useful to be able to test separately
+  google.protobuf.Value value_field = 19;
+}
+
+// A repeated field for each well-known type.
+message RepeatedWellKnownTypes {
+  repeated google.protobuf.Any any_field = 1;
+  repeated google.protobuf.Api api_field = 2;
+  repeated google.protobuf.Duration duration_field = 3;
+  repeated google.protobuf.Empty empty_field = 4;
+  repeated google.protobuf.FieldMask field_mask_field = 5;
+  repeated google.protobuf.SourceContext source_context_field = 6;
+  repeated google.protobuf.Struct struct_field = 7;
+  repeated google.protobuf.Timestamp timestamp_field = 8;
+  repeated google.protobuf.Type type_field = 9;
+  // These don't actually make a lot of sense, but they're not prohibited...
+  repeated google.protobuf.DoubleValue double_field = 10;
+  repeated google.protobuf.FloatValue float_field = 11;
+  repeated google.protobuf.Int64Value int64_field = 12;
+  repeated google.protobuf.UInt64Value uint64_field = 13;
+  repeated google.protobuf.Int32Value int32_field = 14;
+  repeated google.protobuf.UInt32Value uint32_field = 15;
+  repeated google.protobuf.BoolValue bool_field = 16;
+  repeated google.protobuf.StringValue string_field = 17;
+  repeated google.protobuf.BytesValue bytes_field = 18;
+}
+
+message OneofWellKnownTypes {
+  oneof oneof_field {
+    google.protobuf.Any any_field = 1;
+    google.protobuf.Api api_field = 2;
+    google.protobuf.Duration duration_field = 3;
+    google.protobuf.Empty empty_field = 4;
+    google.protobuf.FieldMask field_mask_field = 5;
+    google.protobuf.SourceContext source_context_field = 6;
+    google.protobuf.Struct struct_field = 7;
+    google.protobuf.Timestamp timestamp_field = 8;
+    google.protobuf.Type type_field = 9;
+    google.protobuf.DoubleValue double_field = 10;
+    google.protobuf.FloatValue float_field = 11;
+    google.protobuf.Int64Value int64_field = 12;
+    google.protobuf.UInt64Value uint64_field = 13;
+    google.protobuf.Int32Value int32_field = 14;
+    google.protobuf.UInt32Value uint32_field = 15;
+    google.protobuf.BoolValue bool_field = 16;
+    google.protobuf.StringValue string_field = 17;
+    google.protobuf.BytesValue bytes_field = 18;
+  }
+}
+
+// A map field for each well-known type. We only
+// need to worry about the value part of the map being the
+// well-known types, as messages can't be map keys.
+message MapWellKnownTypes {
+  map<int32,google.protobuf.Any> any_field = 1;
+  map<int32,google.protobuf.Api> api_field = 2;
+  map<int32,google.protobuf.Duration> duration_field = 3;
+  map<int32,google.protobuf.Empty> empty_field = 4;
+  map<int32,google.protobuf.FieldMask> field_mask_field = 5;
+  map<int32,google.protobuf.SourceContext> source_context_field = 6;
+  map<int32,google.protobuf.Struct> struct_field = 7;
+  map<int32,google.protobuf.Timestamp> timestamp_field = 8;
+  map<int32,google.protobuf.Type> type_field = 9;
+  map<int32,google.protobuf.DoubleValue> double_field = 10;
+  map<int32,google.protobuf.FloatValue> float_field = 11;
+  map<int32,google.protobuf.Int64Value> int64_field = 12;
+  map<int32,google.protobuf.UInt64Value> uint64_field = 13;
+  map<int32,google.protobuf.Int32Value> int32_field = 14;
+  map<int32,google.protobuf.UInt32Value> uint32_field = 15;
+  map<int32,google.protobuf.BoolValue> bool_field = 16;
+  map<int32,google.protobuf.StringValue> string_field = 17;
+  map<int32,google.protobuf.BytesValue> bytes_field = 18;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.cc b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.cc
new file mode 100644
index 0000000..d4e383d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.cc
@@ -0,0 +1,347 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/unknown_field_set.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+// This global instance is returned by unknown_fields() on any message class
+// when the object has no unknown fields. This is necessary because we now
+// instantiate the UnknownFieldSet dynamically only when required.
+UnknownFieldSet* default_unknown_field_set_instance_ = NULL;
+
+void DeleteDefaultUnknownFieldSet() {
+  delete default_unknown_field_set_instance_;
+}
+
+void InitDefaultUnknownFieldSet() {
+  default_unknown_field_set_instance_ = new UnknownFieldSet();
+  internal::OnShutdown(&DeleteDefaultUnknownFieldSet);
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
+}
+
+const UnknownFieldSet* UnknownFieldSet::default_instance() {
+  ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_,
+                 &InitDefaultUnknownFieldSet);
+  return default_unknown_field_set_instance_;
+}
+
+UnknownFieldSet::UnknownFieldSet()
+    : fields_(NULL) {}
+
+UnknownFieldSet::~UnknownFieldSet() {
+  Clear();
+  delete fields_;
+}
+
+void UnknownFieldSet::ClearFallback() {
+  if (fields_ != NULL) {
+    for (int i = 0; i < fields_->size(); i++) {
+      (*fields_)[i].Delete();
+    }
+    delete fields_;
+    fields_ = NULL;
+  }
+}
+
+void UnknownFieldSet::ClearAndFreeMemory() {
+  if (fields_ != NULL) {
+    Clear();
+  }
+}
+
+void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
+  int other_field_count = other.field_count();
+  if (other_field_count > 0) {
+    fields_ = new vector<UnknownField>();
+    for (int i = 0; i < other_field_count; i++) {
+      fields_->push_back((*other.fields_)[i]);
+      fields_->back().DeepCopy((*other.fields_)[i]);
+    }
+  }
+}
+
+void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
+  int other_field_count = other.field_count();
+  if (other_field_count > 0) {
+    if (fields_ == NULL) fields_ = new vector<UnknownField>();
+    for (int i = 0; i < other_field_count; i++) {
+      fields_->push_back((*other.fields_)[i]);
+      fields_->back().DeepCopy((*other.fields_)[i]);
+    }
+  }
+}
+
+// A specialized MergeFrom for performance when we are merging from an UFS that
+// is temporary and can be destroyed in the process.
+void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
+  int other_field_count = other->field_count();
+  if (other_field_count > 0) {
+    if (fields_ == NULL) fields_ = new vector<UnknownField>();
+    for (int i = 0; i < other_field_count; i++) {
+      fields_->push_back((*other->fields_)[i]);
+      (*other->fields_)[i].Reset();
+    }
+  }
+  delete other->fields_;
+  other->fields_ = NULL;
+}
+
+int UnknownFieldSet::SpaceUsedExcludingSelf() const {
+  if (fields_ == NULL) return 0;
+
+  int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
+
+  for (int i = 0; i < fields_->size(); i++) {
+    const UnknownField& field = (*fields_)[i];
+    switch (field.type()) {
+      case UnknownField::TYPE_LENGTH_DELIMITED:
+        total_size += sizeof(*field.length_delimited_.string_value_) +
+                      internal::StringSpaceUsedExcludingSelf(
+                          *field.length_delimited_.string_value_);
+        break;
+      case UnknownField::TYPE_GROUP:
+        total_size += field.group_->SpaceUsed();
+        break;
+      default:
+        break;
+    }
+  }
+  return total_size;
+}
+
+int UnknownFieldSet::SpaceUsed() const {
+  return sizeof(*this) + SpaceUsedExcludingSelf();
+}
+
+void UnknownFieldSet::AddVarint(int number, uint64 value) {
+  UnknownField field;
+  field.number_ = number;
+  field.SetType(UnknownField::TYPE_VARINT);
+  field.varint_ = value;
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+}
+
+void UnknownFieldSet::AddFixed32(int number, uint32 value) {
+  UnknownField field;
+  field.number_ = number;
+  field.SetType(UnknownField::TYPE_FIXED32);
+  field.fixed32_ = value;
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+}
+
+void UnknownFieldSet::AddFixed64(int number, uint64 value) {
+  UnknownField field;
+  field.number_ = number;
+  field.SetType(UnknownField::TYPE_FIXED64);
+  field.fixed64_ = value;
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+}
+
+string* UnknownFieldSet::AddLengthDelimited(int number) {
+  UnknownField field;
+  field.number_ = number;
+  field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
+  field.length_delimited_.string_value_ = new string;
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+  return field.length_delimited_.string_value_;
+}
+
+
+UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
+  UnknownField field;
+  field.number_ = number;
+  field.SetType(UnknownField::TYPE_GROUP);
+  field.group_ = new UnknownFieldSet;
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+  return field.group_;
+}
+
+void UnknownFieldSet::AddField(const UnknownField& field) {
+  if (fields_ == NULL) fields_ = new vector<UnknownField>();
+  fields_->push_back(field);
+  fields_->back().DeepCopy(field);
+}
+
+void UnknownFieldSet::DeleteSubrange(int start, int num) {
+  // Delete the specified fields.
+  for (int i = 0; i < num; ++i) {
+    (*fields_)[i + start].Delete();
+  }
+  // Slide down the remaining fields.
+  for (int i = start + num; i < fields_->size(); ++i) {
+    (*fields_)[i - num] = (*fields_)[i];
+  }
+  // Pop off the # of deleted fields.
+  for (int i = 0; i < num; ++i) {
+    fields_->pop_back();
+  }
+  if (fields_ && fields_->size() == 0) {
+    // maintain invariant: never hold fields_ if empty.
+    delete fields_;
+    fields_ = NULL;
+  }
+}
+
+void UnknownFieldSet::DeleteByNumber(int number) {
+  if (fields_ == NULL) return;
+  int left = 0;  // The number of fields left after deletion.
+  for (int i = 0; i < fields_->size(); ++i) {
+    UnknownField* field = &(*fields_)[i];
+    if (field->number() == number) {
+      field->Delete();
+    } else {
+      if (i != left) {
+        (*fields_)[left] = (*fields_)[i];
+      }
+      ++left;
+    }
+  }
+  fields_->resize(left);
+  if (left == 0) {
+    // maintain invariant: never hold fields_ if empty.
+    delete fields_;
+    fields_ = NULL;
+  }
+}
+
+bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
+  UnknownFieldSet other;
+  if (internal::WireFormat::SkipMessage(input, &other) &&
+      input->ConsumedEntireMessage()) {
+    MergeFromAndDestroy(&other);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
+  Clear();
+  return MergeFromCodedStream(input);
+}
+
+bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
+  io::CodedInputStream coded_input(input);
+  return (ParseFromCodedStream(&coded_input) &&
+          coded_input.ConsumedEntireMessage());
+}
+
+bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
+  io::ArrayInputStream input(data, size);
+  return ParseFromZeroCopyStream(&input);
+}
+
+void UnknownField::Delete() {
+  switch (type()) {
+    case UnknownField::TYPE_LENGTH_DELIMITED:
+      delete length_delimited_.string_value_;
+      break;
+    case UnknownField::TYPE_GROUP:
+      delete group_;
+      break;
+    default:
+      break;
+  }
+}
+
+// Reset all owned ptrs, a special function for performance, to avoid double
+// owning the ptrs, when we merge from a temporary UnknownFieldSet objects.
+void UnknownField::Reset() {
+  switch (type()) {
+    case UnknownField::TYPE_LENGTH_DELIMITED:
+      length_delimited_.string_value_ = NULL;
+      break;
+    case UnknownField::TYPE_GROUP: {
+      group_ = NULL;
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void UnknownField::DeepCopy(const UnknownField& other) {
+  switch (type()) {
+    case UnknownField::TYPE_LENGTH_DELIMITED:
+      length_delimited_.string_value_ = new string(
+          *length_delimited_.string_value_);
+      break;
+    case UnknownField::TYPE_GROUP: {
+      UnknownFieldSet* group = new UnknownFieldSet();
+      group->InternalMergeFrom(*group_);
+      group_ = group;
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+
+void UnknownField::SerializeLengthDelimitedNoTag(
+    io::CodedOutputStream* output) const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
+  const string& data = *length_delimited_.string_value_;
+  output->WriteVarint32(data.size());
+  output->WriteRawMaybeAliased(data.data(), data.size());
+}
+
+uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
+  const string& data = *length_delimited_.string_value_;
+  target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
+  target = io::CodedOutputStream::WriteStringToArray(data, target);
+  return target;
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.h b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.h
new file mode 100644
index 0000000..612a942
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set.h
@@ -0,0 +1,340 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Contains classes used to keep track of unrecognized fields seen while
+// parsing a protocol message.
+
+#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
+#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
+
+#include <assert.h>
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class CodedInputStream;         // coded_stream.h
+    class CodedOutputStream;        // coded_stream.h
+    class ZeroCopyInputStream;      // zero_copy_stream.h
+  }
+  namespace internal {
+    class WireFormat;               // wire_format.h
+    class MessageSetFieldSkipperUsingCord;
+                                    // extension_set_heavy.cc
+  }
+
+class Message;                      // message.h
+class UnknownField;                 // below
+
+// An UnknownFieldSet contains fields that were encountered while parsing a
+// message but were not defined by its type.  Keeping track of these can be
+// useful, especially in that they may be written if the message is serialized
+// again without being cleared in between.  This means that software which
+// simply receives messages and forwards them to other servers does not need
+// to be updated every time a new field is added to the message definition.
+//
+// To get the UnknownFieldSet attached to any message, call
+// Reflection::GetUnknownFields().
+//
+// This class is necessarily tied to the protocol buffer wire format, unlike
+// the Reflection interface which is independent of any serialization scheme.
+class LIBPROTOBUF_EXPORT UnknownFieldSet {
+ public:
+  UnknownFieldSet();
+  ~UnknownFieldSet();
+
+  // Remove all fields.
+  inline void Clear();
+
+  // Remove all fields and deallocate internal data objects
+  void ClearAndFreeMemory();
+
+  // Is this set empty?
+  inline bool empty() const;
+
+  // Merge the contents of some other UnknownFieldSet with this one.
+  void MergeFrom(const UnknownFieldSet& other);
+
+  // Similar to above, but this function will destroy the contents of other.
+  void MergeFromAndDestroy(UnknownFieldSet* other);
+
+  // Swaps the contents of some other UnknownFieldSet with this one.
+  inline void Swap(UnknownFieldSet* x);
+
+  // Computes (an estimate of) the total number of bytes currently used for
+  // storing the unknown fields in memory. Does NOT include
+  // sizeof(*this) in the calculation.
+  int SpaceUsedExcludingSelf() const;
+
+  // Version of SpaceUsed() including sizeof(*this).
+  int SpaceUsed() const;
+
+  // Returns the number of fields present in the UnknownFieldSet.
+  inline int field_count() const;
+  // Get a field in the set, where 0 <= index < field_count().  The fields
+  // appear in the order in which they were added.
+  inline const UnknownField& field(int index) const;
+  // Get a mutable pointer to a field in the set, where
+  // 0 <= index < field_count().  The fields appear in the order in which
+  // they were added.
+  inline UnknownField* mutable_field(int index);
+
+  // Adding fields ---------------------------------------------------
+
+  void AddVarint(int number, uint64 value);
+  void AddFixed32(int number, uint32 value);
+  void AddFixed64(int number, uint64 value);
+  void AddLengthDelimited(int number, const string& value);
+  string* AddLengthDelimited(int number);
+  UnknownFieldSet* AddGroup(int number);
+
+  // Adds an unknown field from another set.
+  void AddField(const UnknownField& field);
+
+  // Delete fields with indices in the range [start .. start+num-1].
+  // Caution: implementation moves all fields with indices [start+num .. ].
+  void DeleteSubrange(int start, int num);
+
+  // Delete all fields with a specific field number. The order of left fields
+  // is preserved.
+  // Caution: implementation moves all fields after the first deleted field.
+  void DeleteByNumber(int number);
+
+  // Parsing helpers -------------------------------------------------
+  // These work exactly like the similarly-named methods of Message.
+
+  bool MergeFromCodedStream(io::CodedInputStream* input);
+  bool ParseFromCodedStream(io::CodedInputStream* input);
+  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  bool ParseFromArray(const void* data, int size);
+  inline bool ParseFromString(const string& data) {
+    return ParseFromArray(data.data(), static_cast<int>(data.size()));
+  }
+
+  static const UnknownFieldSet* default_instance();
+ private:
+  // For InternalMergeFrom
+  friend class UnknownField;
+  // Merges from other UnknownFieldSet. This method assumes, that this object
+  // is newly created and has fields_ == NULL;
+  void InternalMergeFrom(const UnknownFieldSet& other);
+  void ClearFallback();
+
+  // fields_ is either NULL, or a pointer to a vector that is *non-empty*. We
+  // never hold the empty vector because we want the 'do we have any unknown
+  // fields' check to be fast, and avoid a cache miss: the UFS instance gets
+  // embedded in the message object, so 'fields_ != NULL' tests a member
+  // variable hot in the cache, without the need to go touch a vector somewhere
+  // else in memory.
+  std::vector<UnknownField>* fields_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
+};
+
+// Represents one field in an UnknownFieldSet.
+class LIBPROTOBUF_EXPORT UnknownField {
+ public:
+  enum Type {
+    TYPE_VARINT,
+    TYPE_FIXED32,
+    TYPE_FIXED64,
+    TYPE_LENGTH_DELIMITED,
+    TYPE_GROUP
+  };
+
+  // The field's tag number, as seen on the wire.
+  inline int number() const;
+
+  // The field type.
+  inline Type type() const;
+
+  // Accessors -------------------------------------------------------
+  // Each method works only for UnknownFields of the corresponding type.
+
+  inline uint64 varint() const;
+  inline uint32 fixed32() const;
+  inline uint64 fixed64() const;
+  inline const string& length_delimited() const;
+  inline const UnknownFieldSet& group() const;
+
+  inline void set_varint(uint64 value);
+  inline void set_fixed32(uint32 value);
+  inline void set_fixed64(uint64 value);
+  inline void set_length_delimited(const string& value);
+  inline string* mutable_length_delimited();
+  inline UnknownFieldSet* mutable_group();
+
+  // Serialization API.
+  // These methods can take advantage of the underlying implementation and may
+  // archieve a better performance than using getters to retrieve the data and
+  // do the serialization yourself.
+  void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
+  uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
+
+  inline int GetLengthDelimitedSize() const;
+
+ private:
+  friend class UnknownFieldSet;
+
+  // If this UnknownField contains a pointer, delete it.
+  void Delete();
+
+  // Reset all the underlying pointers to NULL. A special function to be only
+  // used while merging from a temporary UFS.
+  void Reset();
+
+  // Make a deep copy of any pointers in this UnknownField.
+  void DeepCopy(const UnknownField& other);
+
+  // Set the wire type of this UnknownField. Should only be used when this
+  // UnknownField is being created.
+  inline void SetType(Type type);
+
+  union LengthDelimited {
+    string* string_value_;
+  };
+
+  uint32 number_;
+  uint32 type_;
+  union {
+    uint64 varint_;
+    uint32 fixed32_;
+    uint64 fixed64_;
+    mutable union LengthDelimited length_delimited_;
+    UnknownFieldSet* group_;
+  };
+};
+
+// ===================================================================
+// inline implementations
+
+inline void UnknownFieldSet::Clear() {
+  if (fields_) {
+    ClearFallback();
+  }
+}
+
+inline bool UnknownFieldSet::empty() const {
+  // Invariant: fields_ is never empty if present.
+  return !fields_;
+}
+
+inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
+  std::swap(fields_, x->fields_);
+}
+
+inline int UnknownFieldSet::field_count() const {
+  return fields_ ? static_cast<int>(fields_->size()) : 0;
+}
+inline const UnknownField& UnknownFieldSet::field(int index) const {
+  GOOGLE_DCHECK(fields_ != NULL);
+  return (*fields_)[index];
+}
+inline UnknownField* UnknownFieldSet::mutable_field(int index) {
+  return &(*fields_)[index];
+}
+
+inline void UnknownFieldSet::AddLengthDelimited(
+    int number, const string& value) {
+  AddLengthDelimited(number)->assign(value);
+}
+
+
+inline int UnknownField::number() const { return number_; }
+inline UnknownField::Type UnknownField::type() const {
+  return static_cast<Type>(type_);
+}
+
+inline uint64 UnknownField::varint() const {
+  assert(type() == TYPE_VARINT);
+  return varint_;
+}
+inline uint32 UnknownField::fixed32() const {
+  assert(type() == TYPE_FIXED32);
+  return fixed32_;
+}
+inline uint64 UnknownField::fixed64() const {
+  assert(type() == TYPE_FIXED64);
+  return fixed64_;
+}
+inline const string& UnknownField::length_delimited() const {
+  assert(type() == TYPE_LENGTH_DELIMITED);
+  return *length_delimited_.string_value_;
+}
+inline const UnknownFieldSet& UnknownField::group() const {
+  assert(type() == TYPE_GROUP);
+  return *group_;
+}
+
+inline void UnknownField::set_varint(uint64 value) {
+  assert(type() == TYPE_VARINT);
+  varint_ = value;
+}
+inline void UnknownField::set_fixed32(uint32 value) {
+  assert(type() == TYPE_FIXED32);
+  fixed32_ = value;
+}
+inline void UnknownField::set_fixed64(uint64 value) {
+  assert(type() == TYPE_FIXED64);
+  fixed64_ = value;
+}
+inline void UnknownField::set_length_delimited(const string& value) {
+  assert(type() == TYPE_LENGTH_DELIMITED);
+  length_delimited_.string_value_->assign(value);
+}
+inline string* UnknownField::mutable_length_delimited() {
+  assert(type() == TYPE_LENGTH_DELIMITED);
+  return length_delimited_.string_value_;
+}
+inline UnknownFieldSet* UnknownField::mutable_group() {
+  assert(type() == TYPE_GROUP);
+  return group_;
+}
+
+inline int UnknownField::GetLengthDelimitedSize() const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
+  return static_cast<int>(length_delimited_.string_value_->size());
+}
+
+inline void UnknownField::SetType(Type type) {
+  type_ = type;
+}
+
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set_unittest.cc
new file mode 100644
index 0000000..5de7263
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/unknown_field_set_unittest.cc
@@ -0,0 +1,609 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This test is testing a lot more than just the UnknownFieldSet class.  It
+// tests handling of unknown fields throughout the system.
+
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+
+using internal::WireFormat;
+
+class UnknownFieldSetTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    descriptor_ = unittest::TestAllTypes::descriptor();
+    TestUtil::SetAllFields(&all_fields_);
+    all_fields_.SerializeToString(&all_fields_data_);
+    ASSERT_TRUE(empty_message_.ParseFromString(all_fields_data_));
+    unknown_fields_ = empty_message_.mutable_unknown_fields();
+  }
+
+  const UnknownField* GetField(const string& name) {
+    const FieldDescriptor* field = descriptor_->FindFieldByName(name);
+    if (field == NULL) return NULL;
+    for (int i = 0; i < unknown_fields_->field_count(); i++) {
+      if (unknown_fields_->field(i).number() == field->number()) {
+        return &unknown_fields_->field(i);
+      }
+    }
+    return NULL;
+  }
+
+  // Constructs a protocol buffer which contains fields with all the same
+  // numbers as all_fields_data_ except that each field is some other wire
+  // type.
+  string GetBizarroData() {
+    unittest::TestEmptyMessage bizarro_message;
+    UnknownFieldSet* bizarro_unknown_fields =
+      bizarro_message.mutable_unknown_fields();
+    for (int i = 0; i < unknown_fields_->field_count(); i++) {
+      const UnknownField& unknown_field = unknown_fields_->field(i);
+      if (unknown_field.type() == UnknownField::TYPE_VARINT) {
+        bizarro_unknown_fields->AddFixed32(unknown_field.number(), 1);
+      } else {
+        bizarro_unknown_fields->AddVarint(unknown_field.number(), 1);
+      }
+    }
+
+    string data;
+    EXPECT_TRUE(bizarro_message.SerializeToString(&data));
+    return data;
+  }
+
+  const Descriptor* descriptor_;
+  unittest::TestAllTypes all_fields_;
+  string all_fields_data_;
+
+  // An empty message that has been parsed from all_fields_data_.  So, it has
+  // unknown fields of every type.
+  unittest::TestEmptyMessage empty_message_;
+  UnknownFieldSet* unknown_fields_;
+};
+
+namespace {
+
+TEST_F(UnknownFieldSetTest, AllFieldsPresent) {
+  // All fields of TestAllTypes should be present, in numeric order (because
+  // that's the order we parsed them in).  Fields that are not valid field
+  // numbers of TestAllTypes should NOT be present.
+
+  int pos = 0;
+
+  for (int i = 0; i < 1000; i++) {
+    const FieldDescriptor* field = descriptor_->FindFieldByNumber(i);
+    if (field != NULL) {
+      ASSERT_LT(pos, unknown_fields_->field_count());
+      // Do not check oneof field if it is not set.
+      if (field->containing_oneof() == NULL) {
+        EXPECT_EQ(i, unknown_fields_->field(pos++).number());
+      } else if (i == unknown_fields_->field(pos).number()) {
+        pos++;
+      }
+      if (field->is_repeated()) {
+        // Should have a second instance.
+        ASSERT_LT(pos, unknown_fields_->field_count());
+        EXPECT_EQ(i, unknown_fields_->field(pos++).number());
+      }
+    }
+  }
+  EXPECT_EQ(unknown_fields_->field_count(), pos);
+}
+
+TEST_F(UnknownFieldSetTest, Varint) {
+  const UnknownField* field = GetField("optional_int32");
+  ASSERT_TRUE(field != NULL);
+
+  ASSERT_EQ(UnknownField::TYPE_VARINT, field->type());
+  EXPECT_EQ(all_fields_.optional_int32(), field->varint());
+}
+
+TEST_F(UnknownFieldSetTest, Fixed32) {
+  const UnknownField* field = GetField("optional_fixed32");
+  ASSERT_TRUE(field != NULL);
+
+  ASSERT_EQ(UnknownField::TYPE_FIXED32, field->type());
+  EXPECT_EQ(all_fields_.optional_fixed32(), field->fixed32());
+}
+
+TEST_F(UnknownFieldSetTest, Fixed64) {
+  const UnknownField* field = GetField("optional_fixed64");
+  ASSERT_TRUE(field != NULL);
+
+  ASSERT_EQ(UnknownField::TYPE_FIXED64, field->type());
+  EXPECT_EQ(all_fields_.optional_fixed64(), field->fixed64());
+}
+
+TEST_F(UnknownFieldSetTest, LengthDelimited) {
+  const UnknownField* field = GetField("optional_string");
+  ASSERT_TRUE(field != NULL);
+
+  ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED, field->type());
+  EXPECT_EQ(all_fields_.optional_string(), field->length_delimited());
+}
+
+TEST_F(UnknownFieldSetTest, Group) {
+  const UnknownField* field = GetField("optionalgroup");
+  ASSERT_TRUE(field != NULL);
+
+  ASSERT_EQ(UnknownField::TYPE_GROUP, field->type());
+  ASSERT_EQ(1, field->group().field_count());
+
+  const UnknownField& nested_field = field->group().field(0);
+  const FieldDescriptor* nested_field_descriptor =
+    unittest::TestAllTypes::OptionalGroup::descriptor()->FindFieldByName("a");
+  ASSERT_TRUE(nested_field_descriptor != NULL);
+
+  EXPECT_EQ(nested_field_descriptor->number(), nested_field.number());
+  ASSERT_EQ(UnknownField::TYPE_VARINT, nested_field.type());
+  EXPECT_EQ(all_fields_.optionalgroup().a(), nested_field.varint());
+}
+
+TEST_F(UnknownFieldSetTest, SerializeFastAndSlowAreEquivalent) {
+  int size = WireFormat::ComputeUnknownFieldsSize(
+      empty_message_.unknown_fields());
+  string slow_buffer;
+  string fast_buffer;
+  slow_buffer.resize(size);
+  fast_buffer.resize(size);
+
+  uint8* target = reinterpret_cast<uint8*>(string_as_array(&fast_buffer));
+  uint8* result = WireFormat::SerializeUnknownFieldsToArray(
+          empty_message_.unknown_fields(), target);
+  EXPECT_EQ(size, result - target);
+
+  {
+    io::ArrayOutputStream raw_stream(string_as_array(&slow_buffer), size, 1);
+    io::CodedOutputStream output_stream(&raw_stream);
+    WireFormat::SerializeUnknownFields(empty_message_.unknown_fields(),
+                                       &output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+  EXPECT_TRUE(fast_buffer == slow_buffer);
+}
+
+TEST_F(UnknownFieldSetTest, Serialize) {
+  // Check that serializing the UnknownFieldSet produces the original data
+  // again.
+
+  string data;
+  empty_message_.SerializeToString(&data);
+
+  // Don't use EXPECT_EQ because we don't want to dump raw binary data to
+  // stdout.
+  EXPECT_TRUE(data == all_fields_data_);
+}
+
+TEST_F(UnknownFieldSetTest, ParseViaReflection) {
+  // Make sure fields are properly parsed to the UnknownFieldSet when parsing
+  // via reflection.
+
+  unittest::TestEmptyMessage message;
+  io::ArrayInputStream raw_input(all_fields_data_.data(),
+                                 all_fields_data_.size());
+  io::CodedInputStream input(&raw_input);
+  ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message));
+
+  EXPECT_EQ(message.DebugString(), empty_message_.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, SerializeViaReflection) {
+  // Make sure fields are properly written from the UnknownFieldSet when
+  // serializing via reflection.
+
+  string data;
+
+  {
+    io::StringOutputStream raw_output(&data);
+    io::CodedOutputStream output(&raw_output);
+    int size = WireFormat::ByteSize(empty_message_);
+    WireFormat::SerializeWithCachedSizes(empty_message_, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Don't use EXPECT_EQ because we don't want to dump raw binary data to
+  // stdout.
+  EXPECT_TRUE(data == all_fields_data_);
+}
+
+TEST_F(UnknownFieldSetTest, CopyFrom) {
+  unittest::TestEmptyMessage message;
+
+  message.CopyFrom(empty_message_);
+
+  EXPECT_EQ(empty_message_.DebugString(), message.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, Swap) {
+  unittest::TestEmptyMessage other_message;
+  ASSERT_TRUE(other_message.ParseFromString(GetBizarroData()));
+
+  EXPECT_GT(empty_message_.unknown_fields().field_count(), 0);
+  EXPECT_GT(other_message.unknown_fields().field_count(), 0);
+  const string debug_string = empty_message_.DebugString();
+  const string other_debug_string = other_message.DebugString();
+  EXPECT_NE(debug_string, other_debug_string);
+
+  empty_message_.Swap(&other_message);
+  EXPECT_EQ(debug_string, other_message.DebugString());
+  EXPECT_EQ(other_debug_string, empty_message_.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, SwapWithSelf) {
+  const string debug_string = empty_message_.DebugString();
+  EXPECT_GT(empty_message_.unknown_fields().field_count(), 0);
+
+  empty_message_.Swap(&empty_message_);
+  EXPECT_GT(empty_message_.unknown_fields().field_count(), 0);
+  EXPECT_EQ(debug_string, empty_message_.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, MergeFrom) {
+  unittest::TestEmptyMessage source, destination;
+
+  destination.mutable_unknown_fields()->AddVarint(1, 1);
+  destination.mutable_unknown_fields()->AddVarint(3, 2);
+  source.mutable_unknown_fields()->AddVarint(2, 3);
+  source.mutable_unknown_fields()->AddVarint(3, 4);
+
+  destination.MergeFrom(source);
+
+  EXPECT_EQ(
+    // Note:  The ordering of fields here depends on the ordering of adds
+    //   and merging, above.
+    "1: 1\n"
+    "3: 2\n"
+    "2: 3\n"
+    "3: 4\n",
+    destination.DebugString());
+}
+
+
+TEST_F(UnknownFieldSetTest, Clear) {
+  // Clear the set.
+  empty_message_.Clear();
+  EXPECT_EQ(0, unknown_fields_->field_count());
+}
+
+TEST_F(UnknownFieldSetTest, ClearAndFreeMemory) {
+  EXPECT_GT(unknown_fields_->field_count(), 0);
+  unknown_fields_->ClearAndFreeMemory();
+  EXPECT_EQ(0, unknown_fields_->field_count());
+  unknown_fields_->AddVarint(123456, 654321);
+  EXPECT_EQ(1, unknown_fields_->field_count());
+}
+
+TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) {
+  // Test mixing known and unknown fields when parsing.
+
+  unittest::TestEmptyMessage source;
+  source.mutable_unknown_fields()->AddVarint(123456, 654321);
+  string data;
+  ASSERT_TRUE(source.SerializeToString(&data));
+
+  unittest::TestAllTypes destination;
+  ASSERT_TRUE(destination.ParseFromString(all_fields_data_ + data));
+
+  TestUtil::ExpectAllFieldsSet(destination);
+  ASSERT_EQ(1, destination.unknown_fields().field_count());
+  ASSERT_EQ(UnknownField::TYPE_VARINT,
+            destination.unknown_fields().field(0).type());
+  EXPECT_EQ(654321, destination.unknown_fields().field(0).varint());
+}
+
+TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknown) {
+  // Test that fields of the wrong wire type are treated like unknown fields
+  // when parsing.
+
+  unittest::TestAllTypes all_types_message;
+  unittest::TestEmptyMessage empty_message;
+  string bizarro_data = GetBizarroData();
+  ASSERT_TRUE(all_types_message.ParseFromString(bizarro_data));
+  ASSERT_TRUE(empty_message.ParseFromString(bizarro_data));
+
+  // All fields should have been interpreted as unknown, so the debug strings
+  // should be the same.
+  EXPECT_EQ(empty_message.DebugString(), all_types_message.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknownViaReflection) {
+  // Same as WrongTypeTreatedAsUnknown but via the reflection interface.
+
+  unittest::TestAllTypes all_types_message;
+  unittest::TestEmptyMessage empty_message;
+  string bizarro_data = GetBizarroData();
+  io::ArrayInputStream raw_input(bizarro_data.data(), bizarro_data.size());
+  io::CodedInputStream input(&raw_input);
+  ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &all_types_message));
+  ASSERT_TRUE(empty_message.ParseFromString(bizarro_data));
+
+  EXPECT_EQ(empty_message.DebugString(), all_types_message.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, UnknownExtensions) {
+  // Make sure fields are properly parsed to the UnknownFieldSet even when
+  // they are declared as extension numbers.
+
+  unittest::TestEmptyMessageWithExtensions message;
+  ASSERT_TRUE(message.ParseFromString(all_fields_data_));
+
+  EXPECT_EQ(message.DebugString(), empty_message_.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, UnknownExtensionsReflection) {
+  // Same as UnknownExtensions except parsing via reflection.
+
+  unittest::TestEmptyMessageWithExtensions message;
+  io::ArrayInputStream raw_input(all_fields_data_.data(),
+                                 all_fields_data_.size());
+  io::CodedInputStream input(&raw_input);
+  ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message));
+
+  EXPECT_EQ(message.DebugString(), empty_message_.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, WrongExtensionTypeTreatedAsUnknown) {
+  // Test that fields of the wrong wire type are treated like unknown fields
+  // when parsing extensions.
+
+  unittest::TestAllExtensions all_extensions_message;
+  unittest::TestEmptyMessage empty_message;
+  string bizarro_data = GetBizarroData();
+  ASSERT_TRUE(all_extensions_message.ParseFromString(bizarro_data));
+  ASSERT_TRUE(empty_message.ParseFromString(bizarro_data));
+
+  // All fields should have been interpreted as unknown, so the debug strings
+  // should be the same.
+  EXPECT_EQ(empty_message.DebugString(), all_extensions_message.DebugString());
+}
+
+TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
+  using unittest::TestAllTypes;
+  using unittest::TestAllExtensions;
+  using unittest::TestEmptyMessage;
+
+  const FieldDescriptor* singular_field =
+    TestAllTypes::descriptor()->FindFieldByName("optional_nested_enum");
+  const FieldDescriptor* repeated_field =
+    TestAllTypes::descriptor()->FindFieldByName("repeated_nested_enum");
+  ASSERT_TRUE(singular_field != NULL);
+  ASSERT_TRUE(repeated_field != NULL);
+
+  string data;
+
+  {
+    TestEmptyMessage empty_message;
+    UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
+    unknown_fields->AddVarint(singular_field->number(), TestAllTypes::BAR);
+    unknown_fields->AddVarint(singular_field->number(), 5);  // not valid
+    unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::FOO);
+    unknown_fields->AddVarint(repeated_field->number(), 4);  // not valid
+    unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::BAZ);
+    unknown_fields->AddVarint(repeated_field->number(), 6);  // not valid
+    empty_message.SerializeToString(&data);
+  }
+
+  {
+    TestAllTypes message;
+    ASSERT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(TestAllTypes::BAR, message.optional_nested_enum());
+    ASSERT_EQ(2, message.repeated_nested_enum_size());
+    EXPECT_EQ(TestAllTypes::FOO, message.repeated_nested_enum(0));
+    EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(1));
+
+    const UnknownFieldSet& unknown_fields = message.unknown_fields();
+    ASSERT_EQ(3, unknown_fields.field_count());
+
+    EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type());
+    EXPECT_EQ(5, unknown_fields.field(0).varint());
+
+    EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type());
+    EXPECT_EQ(4, unknown_fields.field(1).varint());
+
+    EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type());
+    EXPECT_EQ(6, unknown_fields.field(2).varint());
+  }
+
+  {
+    using unittest::optional_nested_enum_extension;
+    using unittest::repeated_nested_enum_extension;
+
+    TestAllExtensions message;
+    ASSERT_TRUE(message.ParseFromString(data));
+    EXPECT_EQ(TestAllTypes::BAR,
+              message.GetExtension(optional_nested_enum_extension));
+    ASSERT_EQ(2, message.ExtensionSize(repeated_nested_enum_extension));
+    EXPECT_EQ(TestAllTypes::FOO,
+              message.GetExtension(repeated_nested_enum_extension, 0));
+    EXPECT_EQ(TestAllTypes::BAZ,
+              message.GetExtension(repeated_nested_enum_extension, 1));
+
+    const UnknownFieldSet& unknown_fields = message.unknown_fields();
+    ASSERT_EQ(3, unknown_fields.field_count());
+
+    EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type());
+    EXPECT_EQ(5, unknown_fields.field(0).varint());
+
+    EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type());
+    EXPECT_EQ(4, unknown_fields.field(1).varint());
+
+    EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number());
+    ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type());
+    EXPECT_EQ(6, unknown_fields.field(2).varint());
+  }
+}
+
+TEST_F(UnknownFieldSetTest, SpaceUsedExcludingSelf) {
+  UnknownFieldSet empty;
+  empty.AddVarint(1, 0);
+  EXPECT_EQ(sizeof(vector<UnknownField>) + sizeof(UnknownField),
+            empty.SpaceUsedExcludingSelf());
+}
+
+TEST_F(UnknownFieldSetTest, SpaceUsed) {
+  unittest::TestEmptyMessage empty_message;
+
+  // Make sure an unknown field set has zero space used until a field is
+  // actually added.
+  int base_size = empty_message.SpaceUsed();
+  UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
+  EXPECT_EQ(base_size, empty_message.SpaceUsed());
+
+  // Make sure each thing we add to the set increases the SpaceUsed().
+  unknown_fields->AddVarint(1, 0);
+  EXPECT_LT(base_size, empty_message.SpaceUsed());
+  base_size = empty_message.SpaceUsed();
+
+  string* str = unknown_fields->AddLengthDelimited(1);
+  EXPECT_LT(base_size, empty_message.SpaceUsed());
+  base_size = empty_message.SpaceUsed();
+
+  str->assign(sizeof(string) + 1, 'x');
+  EXPECT_LT(base_size, empty_message.SpaceUsed());
+  base_size = empty_message.SpaceUsed();
+
+  UnknownFieldSet* group = unknown_fields->AddGroup(1);
+  EXPECT_LT(base_size, empty_message.SpaceUsed());
+  base_size = empty_message.SpaceUsed();
+
+  group->AddVarint(1, 0);
+  EXPECT_LT(base_size, empty_message.SpaceUsed());
+}
+
+
+TEST_F(UnknownFieldSetTest, Empty) {
+  UnknownFieldSet unknown_fields;
+  EXPECT_TRUE(unknown_fields.empty());
+  unknown_fields.AddVarint(6, 123);
+  EXPECT_FALSE(unknown_fields.empty());
+  unknown_fields.Clear();
+  EXPECT_TRUE(unknown_fields.empty());
+}
+
+TEST_F(UnknownFieldSetTest, DeleteSubrange) {
+  // Exhaustively test the deletion of every possible subrange in arrays of all
+  // sizes from 0 through 9.
+  for (int size = 0; size < 10; ++size) {
+    for (int num = 0; num <= size; ++num) {
+      for (int start = 0; start < size - num; ++start) {
+        // Create a set with "size" fields.
+        UnknownFieldSet unknown;
+        for (int i = 0; i < size; ++i) {
+          unknown.AddFixed32(i, i);
+        }
+        // Delete the specified subrange.
+        unknown.DeleteSubrange(start, num);
+        // Make sure the resulting field values are still correct.
+        EXPECT_EQ(size - num, unknown.field_count());
+        for (int i = 0; i < unknown.field_count(); ++i) {
+          if (i < start) {
+            EXPECT_EQ(i, unknown.field(i).fixed32());
+          } else {
+            EXPECT_EQ(i + num, unknown.field(i).fixed32());
+          }
+        }
+      }
+    }
+  }
+}
+
+void CheckDeleteByNumber(const vector<int>& field_numbers, int deleted_number,
+                        const vector<int>& expected_field_nubmers) {
+  UnknownFieldSet unknown_fields;
+  for (int i = 0; i < field_numbers.size(); ++i) {
+    unknown_fields.AddFixed32(field_numbers[i], i);
+  }
+  unknown_fields.DeleteByNumber(deleted_number);
+  ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count());
+  for (int i = 0; i < expected_field_nubmers.size(); ++i) {
+    EXPECT_EQ(expected_field_nubmers[i],
+              unknown_fields.field(i).number());
+  }
+}
+
+#define MAKE_VECTOR(x) vector<int>(x, x + GOOGLE_ARRAYSIZE(x))
+TEST_F(UnknownFieldSetTest, DeleteByNumber) {
+  CheckDeleteByNumber(vector<int>(), 1, vector<int>());
+  static const int kTestFieldNumbers1[] = {1, 2, 3};
+  static const int kFieldNumberToDelete1 = 1;
+  static const int kExpectedFieldNumbers1[] = {2, 3};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers1), kFieldNumberToDelete1,
+                      MAKE_VECTOR(kExpectedFieldNumbers1));
+  static const int kTestFieldNumbers2[] = {1, 2, 3};
+  static const int kFieldNumberToDelete2 = 2;
+  static const int kExpectedFieldNumbers2[] = {1, 3};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers2), kFieldNumberToDelete2,
+                      MAKE_VECTOR(kExpectedFieldNumbers2));
+  static const int kTestFieldNumbers3[] = {1, 2, 3};
+  static const int kFieldNumberToDelete3 = 3;
+  static const int kExpectedFieldNumbers3[] = {1, 2};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers3), kFieldNumberToDelete3,
+                      MAKE_VECTOR(kExpectedFieldNumbers3));
+  static const int kTestFieldNumbers4[] = {1, 2, 1, 4, 1};
+  static const int kFieldNumberToDelete4 = 1;
+  static const int kExpectedFieldNumbers4[] = {2, 4};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers4), kFieldNumberToDelete4,
+                      MAKE_VECTOR(kExpectedFieldNumbers4));
+  static const int kTestFieldNumbers5[] = {1, 2, 3, 4, 5};
+  static const int kFieldNumberToDelete5 = 6;
+  static const int kExpectedFieldNumbers5[] = {1, 2, 3, 4, 5};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers5), kFieldNumberToDelete5,
+                      MAKE_VECTOR(kExpectedFieldNumbers5));
+}
+#undef MAKE_VECTOR
+}  // namespace
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.cc b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.cc
new file mode 100644
index 0000000..60b8b8a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.cc
@@ -0,0 +1,208 @@
+// 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.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#include <google/protobuf/util/field_comparator.h>
+
+#include <string>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/mathutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+FieldComparator::FieldComparator() {}
+FieldComparator::~FieldComparator() {}
+
+DefaultFieldComparator::DefaultFieldComparator()
+    : float_comparison_(EXACT),
+      treat_nan_as_equal_(false),
+      has_default_tolerance_(false) {
+}
+
+DefaultFieldComparator::~DefaultFieldComparator() {}
+
+FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
+      const google::protobuf::Message& message_1,
+      const google::protobuf::Message& message_2,
+      const google::protobuf::FieldDescriptor* field,
+      int index_1, int index_2,
+      const google::protobuf::util::FieldContext* field_context) {
+  const Reflection* reflection_1 = message_1.GetReflection();
+  const Reflection* reflection_2 = message_2.GetReflection();
+
+  switch (field->cpp_type()) {
+#define COMPARE_FIELD(METHOD)                                              \
+    if (field->is_repeated()) {                                            \
+      return ResultFromBoolean(Compare##METHOD(                            \
+          *field,                                                          \
+          reflection_1->GetRepeated##METHOD(message_1, field, index_1),    \
+          reflection_2->GetRepeated##METHOD(message_2, field, index_2)));  \
+    } else {                                                               \
+      return ResultFromBoolean(Compare##METHOD(                            \
+          *field,                                                          \
+          reflection_1->Get##METHOD(message_1, field),                     \
+          reflection_2->Get##METHOD(message_2, field)));                   \
+    }                                                                      \
+    break;  // Make sure no fall-through is introduced.
+
+    case FieldDescriptor::CPPTYPE_BOOL:
+      COMPARE_FIELD(Bool);
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      COMPARE_FIELD(Double);
+    case FieldDescriptor::CPPTYPE_ENUM:
+      COMPARE_FIELD(Enum);
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      COMPARE_FIELD(Float);
+    case FieldDescriptor::CPPTYPE_INT32:
+      COMPARE_FIELD(Int32);
+    case FieldDescriptor::CPPTYPE_INT64:
+      COMPARE_FIELD(Int64);
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (field->is_repeated()) {
+        // Allocate scratch strings to store the result if a conversion is
+        // needed.
+        string scratch1;
+        string scratch2;
+        return ResultFromBoolean(
+            CompareString(*field, reflection_1->GetRepeatedStringReference(
+                                      message_1, field, index_1, &scratch1),
+                          reflection_2->GetRepeatedStringReference(
+                              message_2, field, index_2, &scratch2)));
+      } else {
+        // Allocate scratch strings to store the result if a conversion is
+        // needed.
+        string scratch1;
+        string scratch2;
+        return ResultFromBoolean(CompareString(
+            *field,
+            reflection_1->GetStringReference(message_1, field, &scratch1),
+            reflection_2->GetStringReference(message_2, field, &scratch2)));
+      }
+      break;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      COMPARE_FIELD(UInt32);
+    case FieldDescriptor::CPPTYPE_UINT64:
+      COMPARE_FIELD(UInt64);
+
+#undef COMPARE_FIELD
+
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return RECURSE;
+
+    default:
+      GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name()
+                 << " of CppType = " << field->cpp_type();
+      return DIFFERENT;
+  }
+}
+
+void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction,
+                                                         double margin) {
+  default_tolerance_ = Tolerance(fraction, margin);
+  has_default_tolerance_ = true;
+}
+
+void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
+                                                  double fraction,
+                                                  double margin) {
+  GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() ||
+        FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
+      << "Field has to be float or double type. Field name is: "
+      << field->full_name();
+  map_tolerance_[field] = Tolerance(fraction, margin);
+}
+
+bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field,
+                                           double value_1, double value_2) {
+  return CompareDoubleOrFloat(field, value_1, value_2);
+}
+
+bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field,
+                                         const EnumValueDescriptor* value_1,
+                                         const EnumValueDescriptor* value_2) {
+  return value_1->number() == value_2->number();
+}
+
+bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field,
+                                          float value_1, float value_2) {
+  return CompareDoubleOrFloat(field, value_1, value_2);
+}
+
+template<typename T>
+bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
+                                                  T value_1, T value_2) {
+  if (value_1 == value_2) {
+    // Covers +inf and -inf (which are not within margin or fraction of
+    // themselves), and is a shortcut for finite values.
+    return true;
+  } else if (float_comparison_ == EXACT) {
+    if (treat_nan_as_equal_ &&
+        MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
+      return true;
+    }
+    return false;
+  } else {
+    if (treat_nan_as_equal_ &&
+        MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
+      return true;
+    }
+    // float_comparison_ == APPROXIMATE covers two use cases.
+    Tolerance* tolerance = FindOrNull(map_tolerance_, &field);
+    if (tolerance == NULL && has_default_tolerance_) {
+      tolerance = &default_tolerance_;
+    }
+    if (tolerance == NULL) {
+      return MathUtil::AlmostEquals(value_1, value_2);
+    } else {
+      // Use user-provided fraction and margin. Since they are stored as
+      // doubles, we explicitely cast them to types of values provided. This
+      // is very likely to fail if provided values are not numeric.
+      return MathUtil::WithinFractionOrMargin(
+          value_1, value_2, static_cast<T>(tolerance->fraction),
+          static_cast<T>(tolerance->margin));
+    }
+  }
+}
+
+FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean(
+    bool boolean_result) const {
+  return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.h b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.h
new file mode 100644
index 0000000..1b4d65b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator.h
@@ -0,0 +1,259 @@
+// 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.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
+#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+class EnumValueDescriptor;
+class FieldDescriptor;
+
+namespace util {
+
+class FieldContext;
+
+// Base class specifying the interface for comparing protocol buffer fields.
+// Regular users should consider using or subclassing DefaultFieldComparator
+// rather than this interface.
+// Currently, this does not support comparing unknown fields.
+class LIBPROTOBUF_EXPORT FieldComparator {
+ public:
+  FieldComparator();
+  virtual ~FieldComparator();
+
+  enum ComparisonResult {
+    SAME,       // Compared fields are equal. In case of comparing submessages,
+                // user should not recursively compare their contents.
+    DIFFERENT,  // Compared fields are different. In case of comparing
+                // submessages, user should not recursively compare their
+                // contents.
+    RECURSE,    // Compared submessages need to be compared recursively.
+                // FieldComparator does not specify the semantics of recursive
+                // comparison. This value should not be returned for simple
+                // values.
+  };
+
+  // Compares the values of a field in two protocol buffer messages.
+  // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
+  // for submessages. Returning RECURSE for fields not being submessages is
+  // illegal.
+  // In case the given FieldDescriptor points to a repeated field, the indices
+  // need to be valid. Otherwise they should be ignored.
+  //
+  // FieldContext contains information about the specific instances of the
+  // fields being compared, versus FieldDescriptor which only contains general
+  // type information about the fields.
+  virtual ComparisonResult Compare(
+      const google::protobuf::Message& message_1,
+      const google::protobuf::Message& message_2,
+      const google::protobuf::FieldDescriptor* field,
+      int index_1, int index_2,
+      const google::protobuf::util::FieldContext* field_context) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
+};
+
+// Basic implementation of FieldComparator.  Supports three modes of floating
+// point value comparison: exact, approximate using MathUtil::AlmostEqual
+// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
+class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
+ public:
+  enum FloatComparison {
+     EXACT,               // Floats and doubles are compared exactly.
+     APPROXIMATE,         // Floats and doubles are compared using the
+                          // MathUtil::AlmostEqual method or
+                          // MathUtil::WithinFractionOrMargin method.
+     // TODO(ksroka): Introduce third value to differenciate uses of AlmostEqual
+     //               and WithinFractionOrMargin.
+  };
+
+  // Creates new comparator with float comparison set to EXACT.
+  DefaultFieldComparator();
+
+  virtual ~DefaultFieldComparator();
+
+  virtual ComparisonResult Compare(
+      const google::protobuf::Message& message_1,
+      const google::protobuf::Message& message_2,
+      const google::protobuf::FieldDescriptor* field,
+      int index_1, int index_2,
+      const google::protobuf::util::FieldContext* field_context);
+
+  void set_float_comparison(FloatComparison float_comparison) {
+    float_comparison_ = float_comparison;
+  }
+
+  FloatComparison float_comparison() const {
+    return float_comparison_;
+  }
+
+  // Set whether the FieldComparator shall treat floats or doubles that are both
+  // NaN as equal (treat_nan_as_equal = true) or as different
+  // (treat_nan_as_equal = false). Default is treating NaNs always as different.
+  void set_treat_nan_as_equal(bool treat_nan_as_equal) {
+    treat_nan_as_equal_ = treat_nan_as_equal;
+  }
+
+  bool treat_nan_as_equal() const {
+    return treat_nan_as_equal_;
+  }
+
+  // Sets the fraction and margin for the float comparison of a given field.
+  // Uses MathUtil::WithinFractionOrMargin to compare the values.
+  //
+  // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
+  //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
+  // REQUIRES: float_comparison_ == APPROXIMATE
+  void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
+                            double margin);
+
+  // Sets the fraction and margin for the float comparison of all float and
+  // double fields, unless a field has been given a specific setting via
+  // SetFractionAndMargin() above.
+  // Uses MathUtil::WithinFractionOrMargin to compare the values.
+  //
+  // REQUIRES: float_comparison_ == APPROXIMATE
+  void SetDefaultFractionAndMargin(double fraction, double margin);
+
+ private:
+  // Defines the tolerance for floating point comparison (fraction and margin).
+  struct Tolerance {
+    double fraction;
+    double margin;
+    Tolerance()
+        : fraction(0.0),
+          margin(0.0) {}
+    Tolerance(double f, double m)
+        : fraction(f),
+          margin(m) {}
+  };
+
+  // Defines the map to store the tolerances for floating point comparison.
+  typedef map<const FieldDescriptor*, Tolerance> ToleranceMap;
+
+  // The following methods get executed when CompareFields is called for the
+  // basic types (instead of submessages). They return true on success. One
+  // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
+  // value.
+  bool CompareBool(const google::protobuf::FieldDescriptor& field,
+                   bool value_1, bool value_2) {
+    return value_1 == value_2;
+  }
+
+  // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
+  // CompareFloat.
+  bool CompareDouble(const google::protobuf::FieldDescriptor& field,
+                     double value_1, double value_2);
+
+  bool CompareEnum(const google::protobuf::FieldDescriptor& field,
+                   const EnumValueDescriptor* value_1,
+                   const EnumValueDescriptor* value_2);
+
+  // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
+  // CompareFloat.
+  bool CompareFloat(const google::protobuf::FieldDescriptor& field,
+                    float value_1, float value_2);
+
+  bool CompareInt32(const google::protobuf::FieldDescriptor& field,
+                    int32 value_1, int32 value_2) {
+    return value_1 == value_2;
+  }
+
+  bool CompareInt64(const google::protobuf::FieldDescriptor& field,
+                    int64 value_1, int64 value_2) {
+    return value_1 == value_2;
+  }
+
+  bool CompareString(const google::protobuf::FieldDescriptor& field,
+                     const string& value_1, const string& value_2) {
+    return value_1 == value_2;
+  }
+
+  bool CompareUInt32(const google::protobuf::FieldDescriptor& field,
+                     uint32 value_1, uint32 value_2) {
+    return value_1 == value_2;
+  }
+
+  bool CompareUInt64(const google::protobuf::FieldDescriptor& field,
+                     uint64 value_1, uint64 value_2) {
+    return value_1 == value_2;
+  }
+
+  // This function is used by CompareDouble and CompareFloat to avoid code
+  // duplication. There are no checks done against types of the values passed,
+  // but it's likely to fail if passed non-numeric arguments.
+  template<typename T>
+  bool CompareDoubleOrFloat(const google::protobuf::FieldDescriptor& field,
+                            T value_1, T value_2);
+
+  // Returns FieldComparator::SAME if boolean_result is true and
+  // FieldComparator::DIFFERENT otherwise.
+  ComparisonResult ResultFromBoolean(bool boolean_result) const;
+
+  FloatComparison float_comparison_;
+
+  // If true, floats and doubles that are both NaN are considered to be
+  // equal. Otherwise, two floats or doubles that are NaN are considered to be
+  // different.
+  bool treat_nan_as_equal_;
+
+  // True iff default_tolerance_ has been explicitly set.
+  //
+  // If false, then the default tolerance for flaots and doubles is that which
+  // is used by MathUtil::AlmostEquals().
+  bool has_default_tolerance_;
+
+  // Default float/double tolerance. Only meaningful if
+  // has_default_tolerance_ == true.
+  Tolerance default_tolerance_;
+
+  // Field-specific float/double tolerances, which override any default for
+  // those particular fields.
+  ToleranceMap map_tolerance_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator);
+};
+
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator_test.cc
new file mode 100644
index 0000000..6fd631d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_comparator_test.cc
@@ -0,0 +1,488 @@
+// 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.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#include <google/protobuf/util/field_comparator.h>
+
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/mathutil.h>
+// This gtest header is put after mathutil.h intentionally. We have to do
+// this because mathutil.h includes mathlimits.h which requires cmath not
+// being included to compile on some versions of gcc:
+//   https://github.com/google/protobuf/blob/818c5eee08840355d70d2f3bdf1a2f17986a5e70/src/google/protobuf/stubs/mathlimits.h#L48
+// and the opensource version gtest.h header includes cmath transitively
+// somehow.
+#include <gtest/gtest.h>
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+using protobuf_unittest::TestAllTypes;
+
+class DefaultFieldComparatorTest : public ::testing::Test {
+ protected:
+  void SetUp() {
+    descriptor_ = TestAllTypes::descriptor();
+  }
+
+  const Descriptor* descriptor_;
+  DefaultFieldComparator comparator_;
+  TestAllTypes message_1_;
+  TestAllTypes message_2_;
+};
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optionalgroup");
+  EXPECT_EQ(FieldComparator::RECURSE,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_nested_message");
+  EXPECT_EQ(FieldComparator::RECURSE,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_foreign_message");
+  EXPECT_EQ(FieldComparator::RECURSE,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, Int32Comparison) {
+  const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32");
+  message_1_.set_optional_int32(1);
+  message_2_.set_optional_int32(1);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_int32(-1);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, Int64Comparison) {
+  const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64");
+  message_1_.set_optional_int64(1L);
+  message_2_.set_optional_int64(1L);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_int64(-1L);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, UInt32Comparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_uint32");
+  message_1_.set_optional_uint32(1);
+  message_2_.set_optional_uint32(1);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_uint32(2);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, UInt64Comparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_uint64");
+  message_1_.set_optional_uint64(1L);
+  message_2_.set_optional_uint64(1L);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_uint64(2L);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, BooleanComparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_bool");
+  message_1_.set_optional_bool(true);
+  message_2_.set_optional_bool(true);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_bool(false);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, EnumComparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_nested_enum");
+  message_1_.set_optional_nested_enum(TestAllTypes::BAR);
+  message_2_.set_optional_nested_enum(TestAllTypes::BAR);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_nested_enum(TestAllTypes::BAZ);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, StringComparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("optional_string");
+  message_1_.set_optional_string("foo");
+  message_2_.set_optional_string("foo");
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+  message_2_.set_optional_string("bar");
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) {
+  const FieldDescriptor* field_float =
+      descriptor_->FindFieldByName("optional_float");
+  const FieldDescriptor* field_double =
+      descriptor_->FindFieldByName("optional_double");
+
+  message_1_.set_optional_float(0.1f);
+  message_2_.set_optional_float(0.1f);
+  message_1_.set_optional_double(0.1);
+  message_2_.set_optional_double(0.1);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  message_2_.set_optional_float(0.2f);
+  message_2_.set_optional_double(0.2);
+
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) {
+  const FieldDescriptor* field_float =
+      descriptor_->FindFieldByName("optional_float");
+  const FieldDescriptor* field_double =
+      descriptor_->FindFieldByName("optional_double");
+
+  message_1_.set_optional_float(2.300005f);
+  message_2_.set_optional_float(2.300006f);
+  message_1_.set_optional_double(2.3000000000000003);
+  message_2_.set_optional_double(2.3000000000000007);
+
+  // Approximate comparison depends on MathUtil, so we assert on MathUtil
+  // results first to check if that's where the failure was introduced.
+  ASSERT_NE(message_1_.optional_float(), message_2_.optional_float());
+  ASSERT_NE(message_1_.optional_double(), message_2_.optional_double());
+  ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(),
+                                     message_2_.optional_float()));
+  ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(),
+                                     message_2_.optional_double()));
+
+  // DefaultFieldComparator's default float comparison mode is EXACT.
+  ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) {
+  const FieldDescriptor* field_float =
+      descriptor_->FindFieldByName("optional_float");
+  const FieldDescriptor* field_double =
+      descriptor_->FindFieldByName("optional_double");
+
+  message_1_.set_optional_float(MathLimits<float>::kNaN);
+  message_2_.set_optional_float(MathLimits<float>::kNaN);
+  message_1_.set_optional_double(MathLimits<double>::kNaN);
+  message_2_.set_optional_double(MathLimits<double>::kNaN);
+
+  // DefaultFieldComparator's default float comparison mode is EXACT with
+  // treating NaNs as different.
+  ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
+  ASSERT_EQ(false, comparator_.treat_nan_as_equal());
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  comparator_.set_treat_nan_as_equal(true);
+  ASSERT_EQ(true, comparator_.treat_nan_as_equal());
+  comparator_.set_float_comparison(DefaultFieldComparator::EXACT);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest,
+       FloatingPointComparisonWithinFractionOrMargin) {
+  const FieldDescriptor* field_float =
+      descriptor_->FindFieldByName("optional_float");
+  const FieldDescriptor* field_double =
+      descriptor_->FindFieldByName("optional_double");
+
+  message_1_.set_optional_float(100.0f);
+  message_2_.set_optional_float(109.9f);
+  message_1_.set_optional_double(100.0);
+  message_2_.set_optional_double(109.9);
+
+  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Should fail since the fraction is too low.
+  comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
+  comparator_.SetFractionAndMargin(field_double, 0.01, 0.0);
+
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Should fail since the margin is too low.
+  comparator_.SetFractionAndMargin(field_float, 0.0, 9.0);
+  comparator_.SetFractionAndMargin(field_double, 0.0, 9.0);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Should succeed since the fraction is high enough.
+  comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
+  comparator_.SetFractionAndMargin(field_double, 0.2, 0.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Should succeed since the margin is high enough.
+  comparator_.SetFractionAndMargin(field_float, 0.0, 10.0);
+  comparator_.SetFractionAndMargin(field_double, 0.0, 10.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Setting values for one of the fields should not affect the other.
+  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // +inf should be equal even though they are not technically within margin or
+  // fraction.
+  message_1_.set_optional_float(numeric_limits<float>::infinity());
+  message_2_.set_optional_float(numeric_limits<float>::infinity());
+  message_1_.set_optional_double(numeric_limits<double>::infinity());
+  message_2_.set_optional_double(numeric_limits<double>::infinity());
+  comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
+  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // -inf should be equal even though they are not technically within margin or
+  // fraction.
+  message_1_.set_optional_float(-numeric_limits<float>::infinity());
+  message_2_.set_optional_float(-numeric_limits<float>::infinity());
+  message_1_.set_optional_double(-numeric_limits<double>::infinity());
+  message_2_.set_optional_double(-numeric_limits<double>::infinity());
+  comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
+  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest,
+       FloatingPointComparisonWithinDefaultFractionOrMargin) {
+  const FieldDescriptor* field_float =
+      descriptor_->FindFieldByName("optional_float");
+  const FieldDescriptor* field_double =
+      descriptor_->FindFieldByName("optional_double");
+
+  message_1_.set_optional_float(100.0f);
+  message_2_.set_optional_float(109.9f);
+  message_1_.set_optional_double(100.0);
+  message_2_.set_optional_double(109.9);
+
+  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Set default fraction and margin.
+  comparator_.SetDefaultFractionAndMargin(0.01, 0.0);
+
+  // Float comparisons should fail since the fraction is too low.
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Set field-specific fraction and margin for one field (field_float) but not
+  // the other (field_double)
+  comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
+
+  // The field with the override should succeed, since its field-specific
+  // fraction is high enough.
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  // The field with no override should fail, since the default fraction is too
+  // low
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // Set the default fraction and margin high enough so that fields that use
+  // the default should succeed
+  comparator_.SetDefaultFractionAndMargin(0.2, 0.0);
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+
+  // The field with an override should still be OK
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+
+  // Set fraction and margin for the field with an override to be too low
+  comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
+
+  // Now our default is high enough but field_float's override is too low.
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_,
+                                field_float, -1, -1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_,
+                                field_double, -1, -1, NULL));
+}
+
+// Simple test checking whether we compare values at correct indices.
+TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) {
+  const FieldDescriptor* field =
+      descriptor_->FindFieldByName("repeated_string");
+
+  message_1_.add_repeated_string("foo");
+  message_1_.add_repeated_string("bar");
+  message_2_.add_repeated_string("bar");
+  message_2_.add_repeated_string("baz");
+
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL));
+  EXPECT_EQ(FieldComparator::DIFFERENT,
+            comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL));
+  EXPECT_EQ(FieldComparator::SAME,
+            comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL));
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.cc b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.cc
new file mode 100644
index 0000000..547c9fb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.cc
@@ -0,0 +1,494 @@
+// 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.
+
+#include <google/protobuf/util/field_mask_util.h>
+
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::FieldMask;
+
+string FieldMaskUtil::ToString(const FieldMask& mask) {
+  return Join(mask.paths(), ",");
+}
+
+void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
+  out->Clear();
+  vector<string> paths = Split(str, ",");
+  for (int i = 0; i < paths.size(); ++i) {
+    if (paths[i].empty()) continue;
+    out->add_paths(paths[i]);
+  }
+}
+
+bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) {
+  output->clear();
+  bool after_underscore = false;
+  for (int i = 0; i < input.size(); ++i) {
+    if (input[i] >= 'A' && input[i] <= 'Z') {
+      // The field name must not contain uppercase letters.
+      return false;
+    }
+    if (after_underscore) {
+      if (input[i] >= 'a' && input[i] <= 'z') {
+        output->push_back(input[i] + 'A' - 'a');
+        after_underscore = false;
+      } else {
+        // The character after a "_" must be a lowercase letter.
+        return false;
+      }
+    } else if (input[i] == '_') {
+      after_underscore = true;
+    } else {
+      output->push_back(input[i]);
+    }
+  }
+  if (after_underscore) {
+    // Trailing "_".
+    return false;
+  }
+  return true;
+}
+
+bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) {
+  output->clear();
+  for (int i = 0; i < input.size(); ++i) {
+    if (input[i] == '_') {
+      // The field name must not contain "_"s.
+      return false;
+    }
+    if (input[i] >= 'A' && input[i] <= 'Z') {
+      output->push_back('_');
+      output->push_back(input[i] + 'a' - 'A');
+    } else {
+      output->push_back(input[i]);
+    }
+  }
+  return true;
+}
+
+bool FieldMaskUtil::ToJsonString(const FieldMask& mask, string* out) {
+  out->clear();
+  for (int i = 0; i < mask.paths_size(); ++i) {
+    const string& path = mask.paths(i);
+    string camelcase_path;
+    if (!SnakeCaseToCamelCase(path, &camelcase_path)) {
+      return false;
+    }
+    if (i > 0) {
+      out->push_back(',');
+    }
+    out->append(camelcase_path);
+  }
+  return true;
+}
+
+bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
+  out->Clear();
+  vector<string> paths = Split(str, ",");
+  for (int i = 0; i < paths.size(); ++i) {
+    if (paths[i].empty()) continue;
+    string snakecase_path;
+    if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) {
+      return false;
+    }
+    out->add_paths(snakecase_path);
+  }
+  return true;
+}
+
+bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
+                                        StringPiece path) {
+  vector<string> parts = Split(path, ".");
+  for (int i = 0; i < parts.size(); ++i) {
+    const string& field_name = parts[i];
+    if (descriptor == NULL) {
+      return false;
+    }
+    const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
+    if (field == NULL) {
+      return false;
+    }
+    if (!field->is_repeated() &&
+        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      descriptor = field->message_type();
+    } else {
+      descriptor = NULL;
+    }
+  }
+  return true;
+}
+
+void FieldMaskUtil::InternalGetFieldMaskForAllFields(
+    const Descriptor* descriptor, FieldMask* out) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    out->add_paths(descriptor->field(i)->name());
+  }
+}
+
+namespace {
+// A FieldMaskTree represents a FieldMask in a tree structure. For example,
+// given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be:
+//
+//   [root] -+- foo -+- bar
+//           |       |
+//           |       +- baz
+//           |
+//           +- bar --- baz
+//
+// In the tree, each leaf node represents a field path.
+class FieldMaskTree {
+ public:
+  FieldMaskTree();
+  ~FieldMaskTree();
+
+  void MergeFromFieldMask(const FieldMask& mask);
+  void MergeToFieldMask(FieldMask* mask);
+
+  // Add a field path into the tree. In a FieldMask, each field path matches
+  // the specified field and also all its sub-fields. If the field path to
+  // add is a sub-path of an existing field path in the tree (i.e., a leaf
+  // node), it means the tree already matches the given path so nothing will
+  // be added to the tree. If the path matches an existing non-leaf node in the
+  // tree, that non-leaf node will be turned into a leaf node with all its
+  // children removed because the path matches all the node's children.
+  void AddPath(const string& path);
+
+  // Calculate the intersection part of a field path with this tree and add
+  // the intersection field path into out.
+  void IntersectPath(const string& path, FieldMaskTree* out);
+
+  // Merge all fields specified by this tree from one message to another.
+  void MergeMessage(const Message& source,
+                    const FieldMaskUtil::MergeOptions& options,
+                    Message* destination) {
+    // Do nothing if the tree is empty.
+    if (root_.children.empty()) {
+      return;
+    }
+    MergeMessage(&root_, source, options, destination);
+  }
+
+ private:
+  struct Node {
+    Node() {}
+
+    ~Node() { ClearChildren(); }
+
+    void ClearChildren() {
+      for (map<string, Node*>::iterator it = children.begin();
+           it != children.end(); ++it) {
+        delete it->second;
+      }
+      children.clear();
+    }
+
+    map<string, Node*> children;
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
+  };
+
+  // Merge a sub-tree to mask. This method adds the field paths represented
+  // by all leaf nodes descended from "node" to mask.
+  void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out);
+
+  // Merge all leaf nodes of a sub-tree to another tree.
+  void MergeLeafNodesToTree(const string& prefix, const Node* node,
+                            FieldMaskTree* out);
+
+  // Merge all fields specified by a sub-tree from one message to another.
+  void MergeMessage(const Node* node, const Message& source,
+                    const FieldMaskUtil::MergeOptions& options,
+                    Message* destination);
+
+  Node root_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
+};
+
+FieldMaskTree::FieldMaskTree() {}
+
+FieldMaskTree::~FieldMaskTree() {}
+
+void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) {
+  for (int i = 0; i < mask.paths_size(); ++i) {
+    AddPath(mask.paths(i));
+  }
+}
+
+void FieldMaskTree::MergeToFieldMask(FieldMask* mask) {
+  MergeToFieldMask("", &root_, mask);
+}
+
+void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node,
+                                     FieldMask* out) {
+  if (node->children.empty()) {
+    if (prefix.empty()) {
+      // This is the root node.
+      return;
+    }
+    out->add_paths(prefix);
+    return;
+  }
+  for (map<string, Node*>::const_iterator it = node->children.begin();
+       it != node->children.end(); ++it) {
+    string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
+    MergeToFieldMask(current_path, it->second, out);
+  }
+}
+
+void FieldMaskTree::AddPath(const string& path) {
+  vector<string> parts = Split(path, ".");
+  if (parts.empty()) {
+    return;
+  }
+  bool new_branch = false;
+  Node* node = &root_;
+  for (int i = 0; i < parts.size(); ++i) {
+    if (!new_branch && node != &root_ && node->children.empty()) {
+      // Path matches an existing leaf node. This means the path is already
+      // coverred by this tree (for example, adding "foo.bar.baz" to a tree
+      // which already contains "foo.bar").
+      return;
+    }
+    const string& node_name = parts[i];
+    Node*& child = node->children[node_name];
+    if (child == NULL) {
+      new_branch = true;
+      child = new Node();
+    }
+    node = child;
+  }
+  if (!node->children.empty()) {
+    node->ClearChildren();
+  }
+}
+
+void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) {
+  vector<string> parts = Split(path, ".");
+  if (parts.empty()) {
+    return;
+  }
+  const Node* node = &root_;
+  for (int i = 0; i < parts.size(); ++i) {
+    if (node->children.empty()) {
+      if (node != &root_) {
+        out->AddPath(path);
+      }
+      return;
+    }
+    const string& node_name = parts[i];
+    const Node* result = FindPtrOrNull(node->children, node_name);
+    if (result == NULL) {
+      // No intersection found.
+      return;
+    }
+    node = result;
+  }
+  // Now we found a matching node with the given path. Add all leaf nodes
+  // to out.
+  MergeLeafNodesToTree(path, node, out);
+}
+
+void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node,
+                                         FieldMaskTree* out) {
+  if (node->children.empty()) {
+    out->AddPath(prefix);
+  }
+  for (map<string, Node*>::const_iterator it = node->children.begin();
+       it != node->children.end(); ++it) {
+    string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
+    MergeLeafNodesToTree(current_path, it->second, out);
+  }
+}
+
+void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
+                                 const FieldMaskUtil::MergeOptions& options,
+                                 Message* destination) {
+  GOOGLE_DCHECK(!node->children.empty());
+  const Reflection* source_reflection = source.GetReflection();
+  const Reflection* destination_reflection = destination->GetReflection();
+  const Descriptor* descriptor = source.GetDescriptor();
+  for (map<string, Node*>::const_iterator it = node->children.begin();
+       it != node->children.end(); ++it) {
+    const string& field_name = it->first;
+    const Node* child = it->second;
+    const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
+    if (field == NULL) {
+      GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in message "
+                 << descriptor->full_name();
+      continue;
+    }
+    if (!child->children.empty()) {
+      // Sub-paths are only allowed for singular message fields.
+      if (field->is_repeated() ||
+          field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+        GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message "
+                   << descriptor->full_name()
+                   << " is not a singular message field and cannot "
+                   << "have sub-fields.";
+        continue;
+      }
+      MergeMessage(child, source_reflection->GetMessage(source, field), options,
+                   destination_reflection->MutableMessage(destination, field));
+      continue;
+    }
+    if (!field->is_repeated()) {
+      switch (field->cpp_type()) {
+#define COPY_VALUE(TYPE, Name)                                            \
+  case FieldDescriptor::CPPTYPE_##TYPE: {                                 \
+    destination_reflection->Set##Name(                                    \
+        destination, field, source_reflection->Get##Name(source, field)); \
+    break;                                                                \
+  }
+        COPY_VALUE(BOOL, Bool)
+        COPY_VALUE(INT32, Int32)
+        COPY_VALUE(INT64, Int64)
+        COPY_VALUE(UINT32, UInt32)
+        COPY_VALUE(UINT64, UInt64)
+        COPY_VALUE(FLOAT, Float)
+        COPY_VALUE(DOUBLE, Double)
+        COPY_VALUE(ENUM, Enum)
+        COPY_VALUE(STRING, String)
+#undef COPY_VALUE
+        case FieldDescriptor::CPPTYPE_MESSAGE: {
+          if (options.replace_message_fields()) {
+            destination_reflection->ClearField(destination, field);
+          }
+          if (source_reflection->HasField(source, field)) {
+            destination_reflection->MutableMessage(destination, field)
+                ->MergeFrom(source_reflection->GetMessage(source, field));
+          }
+          break;
+        }
+      }
+    } else {
+      if (options.replace_repeated_fields()) {
+        destination_reflection->ClearField(destination, field);
+      }
+      switch (field->cpp_type()) {
+#define COPY_REPEATED_VALUE(TYPE, Name)                            \
+  case FieldDescriptor::CPPTYPE_##TYPE: {                          \
+    int size = source_reflection->FieldSize(source, field);        \
+    for (int i = 0; i < size; ++i) {                               \
+      destination_reflection->Add##Name(                           \
+          destination, field,                                      \
+          source_reflection->GetRepeated##Name(source, field, i)); \
+    }                                                              \
+    break;                                                         \
+  }
+        COPY_REPEATED_VALUE(BOOL, Bool)
+        COPY_REPEATED_VALUE(INT32, Int32)
+        COPY_REPEATED_VALUE(INT64, Int64)
+        COPY_REPEATED_VALUE(UINT32, UInt32)
+        COPY_REPEATED_VALUE(UINT64, UInt64)
+        COPY_REPEATED_VALUE(FLOAT, Float)
+        COPY_REPEATED_VALUE(DOUBLE, Double)
+        COPY_REPEATED_VALUE(ENUM, Enum)
+        COPY_REPEATED_VALUE(STRING, String)
+#undef COPY_REPEATED_VALUE
+        case FieldDescriptor::CPPTYPE_MESSAGE: {
+          int size = source_reflection->FieldSize(source, field);
+          for (int i = 0; i < size; ++i) {
+            destination_reflection->AddMessage(destination, field)
+                ->MergeFrom(
+                    source_reflection->GetRepeatedMessage(source, field, i));
+          }
+          break;
+        }
+      }
+    }
+  }
+}
+
+}  // namespace
+
+void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) {
+  FieldMaskTree tree;
+  tree.MergeFromFieldMask(mask);
+  out->Clear();
+  tree.MergeToFieldMask(out);
+}
+
+void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2,
+                          FieldMask* out) {
+  FieldMaskTree tree;
+  tree.MergeFromFieldMask(mask1);
+  tree.MergeFromFieldMask(mask2);
+  out->Clear();
+  tree.MergeToFieldMask(out);
+}
+
+void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2,
+                              FieldMask* out) {
+  FieldMaskTree tree, intersection;
+  tree.MergeFromFieldMask(mask1);
+  for (int i = 0; i < mask2.paths_size(); ++i) {
+    tree.IntersectPath(mask2.paths(i), &intersection);
+  }
+  out->Clear();
+  intersection.MergeToFieldMask(out);
+}
+
+bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, const FieldMask& mask) {
+  for (int i = 0; i < mask.paths_size(); ++i) {
+    const string& mask_path = mask.paths(i);
+    if (path == mask_path) {
+      return true;
+    } else if (mask_path.length() < path.length()) {
+      // Also check whether mask.paths(i) is a prefix of path.
+      if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") ==
+          0) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask,
+                                   const MergeOptions& options,
+                                   Message* destination) {
+  GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor());
+  // Build a FieldMaskTree and walk through the tree to merge all specified
+  // fields.
+  FieldMaskTree tree;
+  tree.MergeFromFieldMask(mask);
+  tree.MergeMessage(source, options, destination);
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.h b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.h
new file mode 100644
index 0000000..644161b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util.h
@@ -0,0 +1,183 @@
+// 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_UTIL_FIELD_MASK_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
+
+#include <string>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+class LIBPROTOBUF_EXPORT FieldMaskUtil {
+  typedef google::protobuf::FieldMask FieldMask;
+
+ public:
+  // Converts FieldMask to/from string, formatted by separating each path
+  // with a comma (e.g., "foo_bar,baz.quz").
+  static string ToString(const FieldMask& mask);
+  static void FromString(StringPiece str, FieldMask* out);
+
+  // Converts FieldMask to/from string, formatted according to proto3 JSON
+  // spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not
+  // style conforming (i.e., not snake_case when converted to string, or not
+  // camelCase when converted from string), the conversion will fail.
+  static bool ToJsonString(const FieldMask& mask, string* out);
+  static bool FromJsonString(StringPiece str, FieldMask* out);
+
+  // Checks whether the given path is valid for type T.
+  template <typename T>
+  static bool IsValidPath(StringPiece path) {
+    return InternalIsValidPath(T::descriptor(), path);
+  }
+
+  // Checks whether the given FieldMask is valid for type T.
+  template <typename T>
+  static bool IsValidFieldMask(const FieldMask& mask) {
+    for (int i = 0; i < mask.paths_size(); ++i) {
+      if (!InternalIsValidPath(T::descriptor(), mask.paths(i))) return false;
+    }
+    return true;
+  }
+
+  // Adds a path to FieldMask after checking whether the given path is valid.
+  // This method check-fails if the path is not a valid path for type T.
+  template <typename T>
+  static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
+    GOOGLE_CHECK(IsValidPath<T>(path));
+    mask->add_paths(path);
+  }
+
+  // Creates a FieldMask with all fields of type T. This FieldMask only
+  // contains fields of T but not any sub-message fields.
+  template <typename T>
+  static void GetFieldMaskForAllFields(FieldMask* out) {
+    InternalGetFieldMaskForAllFields(T::descriptor(), out);
+  }
+
+  // Converts a FieldMask to the canonical form. It will:
+  //   1. Remove paths that are covered by another path. For example,
+  //      "foo.bar" is covered by "foo" and will be removed if "foo"
+  //      is also in the FieldMask.
+  //   2. Sort all paths in alphabetical order.
+  static void ToCanonicalForm(const FieldMask& mask, FieldMask* out);
+
+  // Creates an union of two FieldMasks.
+  static void Union(const FieldMask& mask1, const FieldMask& mask2,
+                    FieldMask* out);
+
+  // Creates an intersection of two FieldMasks.
+  static void Intersect(const FieldMask& mask1, const FieldMask& mask2,
+                        FieldMask* out);
+
+  // Returns true if path is covered by the given FieldMask. Note that path
+  // "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
+  static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
+
+  class MergeOptions;
+  // Merges fields specified in a FieldMask into another message.
+  static void MergeMessageTo(const Message& source, const FieldMask& mask,
+                             const MergeOptions& options, Message* destination);
+
+ private:
+  friend class SnakeCaseCamelCaseTest;
+  // Converts a field name from snake_case to camelCase:
+  //   1. Every character after "_" will be converted to uppercase.
+  //   2. All "_"s are removed.
+  // The conversion will fail if:
+  //   1. The field name contains uppercase letters.
+  //   2. Any character after a "_" is not a lowercase letter.
+  // If the conversion succeeds, it's guaranteed that the resulted
+  // camelCase name will yield the original snake_case name when
+  // converted using CamelCaseToSnakeCase().
+  //
+  // Note that the input can contain characters not allowed in C identifiers.
+  // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
+  // successfully.
+  static bool SnakeCaseToCamelCase(StringPiece input, string* output);
+  // Converts a field name from camelCase to snake_case:
+  //   1. Every uppercase letter is converted to lowercase with a additional
+  //      preceding "-".
+  // The conversion will fail if:
+  //   1. The field name contains "_"s.
+  // If the conversion succeeds, it's guaranteed that the resulted
+  // snake_case name will yield the original camelCase name when
+  // converted using SnakeCaseToCamelCase().
+  //
+  // Note that the input can contain characters not allowed in C identifiers.
+  // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
+  // successfully.
+  static bool CamelCaseToSnakeCase(StringPiece input, string* output);
+
+  static bool InternalIsValidPath(const Descriptor* descriptor,
+                                  StringPiece path);
+
+  static void InternalGetFieldMaskForAllFields(const Descriptor* descriptor,
+                                               FieldMask* out);
+};
+
+class LIBPROTOBUF_EXPORT FieldMaskUtil::MergeOptions {
+ public:
+  MergeOptions()
+      : replace_message_fields_(false), replace_repeated_fields_(false) {}
+  // When merging message fields, the default behavior is to merge the
+  // content of two message fields together. If you instead want to use
+  // the field from the source message to replace the corresponding field
+  // in the destination message, set this flag to true. When this flag is set,
+  // specified submessage fields that are missing in source will be cleared in
+  // destination.
+  void set_replace_message_fields(bool value) {
+    replace_message_fields_ = value;
+  }
+  bool replace_message_fields() const { return replace_message_fields_; }
+  // The default merging behavior will append entries from the source
+  // repeated field to the destination repeated field. If you only want
+  // to keep the entries from the source repeated field, set this flag
+  // to true.
+  void set_replace_repeated_fields(bool value) {
+    replace_repeated_fields_ = value;
+  }
+  bool replace_repeated_fields() const { return replace_repeated_fields_; }
+
+ private:
+  bool replace_message_fields_;
+  bool replace_repeated_fields_;
+};
+
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util_test.cc
new file mode 100644
index 0000000..9b7fb62
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/field_mask_util_test.cc
@@ -0,0 +1,491 @@
+// 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.
+
+#include <google/protobuf/util/field_mask_util.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+class SnakeCaseCamelCaseTest : public ::testing::Test {
+ protected:
+  string SnakeCaseToCamelCase(const string& input) {
+    string output;
+    if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
+      return output;
+    } else {
+      return "#FAIL#";
+    }
+  }
+
+  string CamelCaseToSnakeCase(const string& input) {
+    string output;
+    if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
+      return output;
+    } else {
+      return "#FAIL#";
+    }
+  }
+};
+
+namespace {
+
+TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
+  EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
+  EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
+  EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
+  // No uppercase letter is allowed.
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
+  // Any character after a "_" must be a lowercase letter.
+  //   1. "_" cannot be followed by another "_".
+  //   2. "_" cannot be followed by a digit.
+  //   3. "_" cannot appear as the last character.
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
+  EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
+  EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
+  EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
+  // "_"s are not allowed.
+  EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
+  // Enumerates all possible snake_case names and test that converting it to
+  // camelCase and then to snake_case again will yield the original name.
+  string name = "___abc123";
+  std::sort(name.begin(), name.end());
+  do {
+    string camelName = SnakeCaseToCamelCase(name);
+    if (camelName != "#FAIL#") {
+      EXPECT_EQ(name, CamelCaseToSnakeCase(camelName));
+    }
+  } while (std::next_permutation(name.begin(), name.end()));
+
+  // Enumerates all possible camelCase names and test that converting it to
+  // snake_case and then to camelCase again will yield the original name.
+  name = "abcABC123";
+  std::sort(name.begin(), name.end());
+  do {
+    string camelName = CamelCaseToSnakeCase(name);
+    if (camelName != "#FAIL#") {
+      EXPECT_EQ(name, SnakeCaseToCamelCase(camelName));
+    }
+  } while (std::next_permutation(name.begin(), name.end()));
+}
+
+using protobuf_unittest::TestAllTypes;
+using protobuf_unittest::NestedTestAllTypes;
+using google::protobuf::FieldMask;
+
+TEST(FieldMaskUtilTest, StringFormat) {
+  FieldMask mask;
+  EXPECT_EQ("", FieldMaskUtil::ToString(mask));
+  mask.add_paths("foo_bar");
+  EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
+  mask.add_paths("baz_quz");
+  EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
+
+  FieldMaskUtil::FromString("", &mask);
+  EXPECT_EQ(0, mask.paths_size());
+  FieldMaskUtil::FromString("fooBar", &mask);
+  EXPECT_EQ(1, mask.paths_size());
+  EXPECT_EQ("fooBar", mask.paths(0));
+  FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
+  EXPECT_EQ(2, mask.paths_size());
+  EXPECT_EQ("fooBar", mask.paths(0));
+  EXPECT_EQ("bazQuz", mask.paths(1));
+}
+
+TEST(FieldMaskUtilTest, JsonStringFormat) {
+  FieldMask mask;
+  string value;
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("", value);
+  mask.add_paths("foo_bar");
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("fooBar", value);
+  mask.add_paths("bar_quz");
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("fooBar,barQuz", value);
+
+  FieldMaskUtil::FromJsonString("", &mask);
+  EXPECT_EQ(0, mask.paths_size());
+  FieldMaskUtil::FromJsonString("fooBar", &mask);
+  EXPECT_EQ(1, mask.paths_size());
+  EXPECT_EQ("foo_bar", mask.paths(0));
+  FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
+  EXPECT_EQ(2, mask.paths_size());
+  EXPECT_EQ("foo_bar", mask.paths(0));
+  EXPECT_EQ("baz_quz", mask.paths(1));
+}
+
+TEST(FieldMaskUtilTest, TestIsVaildPath) {
+  EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32"));
+  EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist"));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb"));
+  EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>(
+      "optional_nested_message.nonexist"));
+  // FieldMask cannot be used to specify sub-fields of a repeated message.
+  EXPECT_FALSE(
+      FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb"));
+}
+
+TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
+  FieldMask mask;
+  FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask);
+  EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
+
+  FieldMaskUtil::FromString(
+      "optional_int32,optional_nested_message.bb,optional_nonexist", &mask);
+  EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
+}
+
+TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
+  FieldMask mask;
+  FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>(&mask);
+  EXPECT_EQ(1, mask.paths_size());
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
+
+  FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>(&mask);
+  EXPECT_EQ(76, mask.paths_size());
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask));
+  EXPECT_TRUE(
+      FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask));
+}
+
+TEST(FieldMaskUtilTest, TestToCanonicalForm) {
+  FieldMask in, out;
+  // Paths will be sorted.
+  FieldMaskUtil::FromString("baz.quz,bar,foo", &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out));
+  // Duplicated paths will be removed.
+  FieldMaskUtil::FromString("foo,bar,foo", &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out));
+  // Sub-paths of other paths will be removed.
+  FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out));
+
+  // Test more deeply nested cases.
+  FieldMaskUtil::FromString(
+      "foo.bar.baz1,"
+      "foo.bar.baz2.quz,"
+      "foo.bar.baz2",
+      &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
+  FieldMaskUtil::FromString(
+      "foo.bar.baz1,"
+      "foo.bar.baz2,"
+      "foo.bar.baz2.quz",
+      &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
+  FieldMaskUtil::FromString(
+      "foo.bar.baz1,"
+      "foo.bar.baz2,"
+      "foo.bar.baz2.quz,"
+      "foo.bar",
+      &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out));
+  FieldMaskUtil::FromString(
+      "foo.bar.baz1,"
+      "foo.bar.baz2,"
+      "foo.bar.baz2.quz,"
+      "foo",
+      &in);
+  FieldMaskUtil::ToCanonicalForm(in, &out);
+  EXPECT_EQ("foo", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestUnion) {
+  FieldMask mask1, mask2, out;
+  // Test cases without overlapping.
+  FieldMaskUtil::FromString("foo,baz", &mask1);
+  FieldMaskUtil::FromString("bar,quz", &mask2);
+  FieldMaskUtil::Union(mask1, mask2, &out);
+  EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out));
+  // Overlap with duplicated paths.
+  FieldMaskUtil::FromString("foo,baz.bb", &mask1);
+  FieldMaskUtil::FromString("baz.bb,quz", &mask2);
+  FieldMaskUtil::Union(mask1, mask2, &out);
+  EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out));
+  // Overlap with paths covering some other paths.
+  FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
+  FieldMaskUtil::FromString("foo.bar,bar", &mask2);
+  FieldMaskUtil::Union(mask1, mask2, &out);
+  EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestIntersect) {
+  FieldMask mask1, mask2, out;
+  // Test cases without overlapping.
+  FieldMaskUtil::FromString("foo,baz", &mask1);
+  FieldMaskUtil::FromString("bar,quz", &mask2);
+  FieldMaskUtil::Intersect(mask1, mask2, &out);
+  EXPECT_EQ("", FieldMaskUtil::ToString(out));
+  // Overlap with duplicated paths.
+  FieldMaskUtil::FromString("foo,baz.bb", &mask1);
+  FieldMaskUtil::FromString("baz.bb,quz", &mask2);
+  FieldMaskUtil::Intersect(mask1, mask2, &out);
+  EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out));
+  // Overlap with paths covering some other paths.
+  FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
+  FieldMaskUtil::FromString("foo.bar,bar", &mask2);
+  FieldMaskUtil::Intersect(mask1, mask2, &out);
+  EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestIspathInFieldMask) {
+  FieldMask mask;
+  FieldMaskUtil::FromString("foo.bar", &mask);
+  EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask));
+  EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask));
+  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask));
+  EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask));
+}
+
+TEST(FieldMaskUtilTest, MergeMessage) {
+  TestAllTypes src, dst;
+  TestUtil::SetAllFields(&src);
+  FieldMaskUtil::MergeOptions options;
+
+#define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name)           \
+  {                                                          \
+    TestAllTypes tmp;                                        \
+    tmp.set_##field_name(src.field_name());                  \
+    FieldMask mask;                                          \
+    mask.add_paths(#field_name);                             \
+    dst.Clear();                                             \
+    FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
+    EXPECT_EQ(tmp.DebugString(), dst.DebugString());         \
+  }
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
+  TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
+#undef TEST_MERGE_ONE_PRIMITIVE_FIELD
+
+#define TEST_MERGE_ONE_FIELD(field_name)                     \
+  {                                                          \
+    TestAllTypes tmp;                                        \
+    *tmp.mutable_##field_name() = src.field_name();          \
+    FieldMask mask;                                          \
+    mask.add_paths(#field_name);                             \
+    dst.Clear();                                             \
+    FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
+    EXPECT_EQ(tmp.DebugString(), dst.DebugString());         \
+  }
+  TEST_MERGE_ONE_FIELD(optional_nested_message)
+  TEST_MERGE_ONE_FIELD(optional_foreign_message)
+  TEST_MERGE_ONE_FIELD(optional_import_message)
+
+  TEST_MERGE_ONE_FIELD(repeated_int32)
+  TEST_MERGE_ONE_FIELD(repeated_int64)
+  TEST_MERGE_ONE_FIELD(repeated_uint32)
+  TEST_MERGE_ONE_FIELD(repeated_uint64)
+  TEST_MERGE_ONE_FIELD(repeated_sint32)
+  TEST_MERGE_ONE_FIELD(repeated_sint64)
+  TEST_MERGE_ONE_FIELD(repeated_fixed32)
+  TEST_MERGE_ONE_FIELD(repeated_fixed64)
+  TEST_MERGE_ONE_FIELD(repeated_sfixed32)
+  TEST_MERGE_ONE_FIELD(repeated_sfixed64)
+  TEST_MERGE_ONE_FIELD(repeated_float)
+  TEST_MERGE_ONE_FIELD(repeated_double)
+  TEST_MERGE_ONE_FIELD(repeated_bool)
+  TEST_MERGE_ONE_FIELD(repeated_string)
+  TEST_MERGE_ONE_FIELD(repeated_bytes)
+  TEST_MERGE_ONE_FIELD(repeated_nested_message)
+  TEST_MERGE_ONE_FIELD(repeated_foreign_message)
+  TEST_MERGE_ONE_FIELD(repeated_import_message)
+  TEST_MERGE_ONE_FIELD(repeated_nested_enum)
+  TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
+  TEST_MERGE_ONE_FIELD(repeated_import_enum)
+#undef TEST_MERGE_ONE_FIELD
+
+  // Test merge nested fields.
+  NestedTestAllTypes nested_src, nested_dst;
+  nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
+  nested_src.mutable_child()
+      ->mutable_child()
+      ->mutable_payload()
+      ->set_optional_int32(5678);
+  FieldMask mask;
+  FieldMaskUtil::FromString("child.payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
+
+  FieldMaskUtil::FromString("child.child.payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+  nested_dst.Clear();
+  FieldMaskUtil::FromString("child.child.payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+  nested_dst.Clear();
+  FieldMaskUtil::FromString("child", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+  // Test MergeOptions.
+
+  nested_dst.Clear();
+  nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
+  // Message fields will be merged by default.
+  FieldMaskUtil::FromString("child.payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
+  // Change the behavior to replace message fields.
+  options.set_replace_message_fields(true);
+  FieldMaskUtil::FromString("child.payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+  EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
+
+  // By default, fields missing in source are not cleared in destination.
+  options.set_replace_message_fields(false);
+  nested_dst.mutable_payload();
+  EXPECT_TRUE(nested_dst.has_payload());
+  FieldMaskUtil::FromString("payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_TRUE(nested_dst.has_payload());
+  // But they are cleared when replacing message fields.
+  options.set_replace_message_fields(true);
+  nested_dst.Clear();
+  nested_dst.mutable_payload();
+  FieldMaskUtil::FromString("payload", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  EXPECT_FALSE(nested_dst.has_payload());
+
+  nested_src.mutable_payload()->add_repeated_int32(1234);
+  nested_dst.mutable_payload()->add_repeated_int32(5678);
+  // Repeated fields will be appended by default.
+  FieldMaskUtil::FromString("payload.repeated_int32", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
+  EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
+  EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
+  // Change the behavior to replace repeated fields.
+  options.set_replace_repeated_fields(true);
+  FieldMaskUtil::FromString("payload.repeated_int32", &mask);
+  FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+  ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
+  EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
+}
+
+
+}  // namespace
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/constants.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/constants.h
new file mode 100644
index 0000000..e556888
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/constants.h
@@ -0,0 +1,103 @@
+// 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_UTIL_CONVERTER_CONSTANTS_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
+
+#include <google/protobuf/stubs/common.h>
+
+// This file contains constants used by //net/proto2/util/converter.
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+// Prefix for type URLs.
+const char kTypeServiceBaseUrl[] = "type.googleapis.com";
+
+// Format string for RFC3339 timestamp formatting.
+const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
+
+// Same as above, but the year value is not zero-padded i.e. this accepts
+// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
+const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
+
+// Minimun seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMinSeconds = -62135596800;
+
+// Maximum seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMaxSeconds = 253402300799;
+
+// Minimum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMinSeconds = -315576000000;
+
+// Maximum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMaxSeconds = 315576000000;
+
+// Nano seconds in a second.
+const int32 kNanosPerSecond = 1000000000;
+
+// Type url representing NULL values in google.protobuf.Struct type.
+const char kStructNullValueTypeUrl[] =
+    "type.googleapis.com/google.protobuf.NullValue";
+
+// Type string for google.protobuf.Struct
+const char kStructType[] = "google.protobuf.Struct";
+
+// Type string for struct.proto's google.protobuf.Value value type.
+const char kStructValueType[] = "google.protobuf.Value";
+
+// Type string for struct.proto's google.protobuf.ListValue value type.
+const char kStructListValueType[] = "google.protobuf.ListValue";
+
+// Type string for google.protobuf.Timestamp
+const char kTimestampType[] = "google.protobuf.Timestamp";
+
+// Type string for google.protobuf.Duration
+const char kDurationType[] = "google.protobuf.Duration";
+
+// Type URL for struct value type google.protobuf.Value
+const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value";
+
+// Type URL for struct value type google.protobuf.Value
+const char kStructTypeUrl[] = "type.googleapis.com/google.protobuf.Struct";
+
+// Type string for google.protobuf.Any
+const char kAnyType[] = "google.protobuf.Any";
+
+// The type URL of google.protobuf.FieldMask;
+const char kFieldMaskTypeUrl[] =
+    "type.googleapis.com/google.protobuf.FieldMask";
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.cc
new file mode 100644
index 0000000..72c0aca
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.cc
@@ -0,0 +1,360 @@
+// 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.
+
+#include <google/protobuf/util/internal/datapiece.h>
+
+#include <google/protobuf/struct.pb.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/mathutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::EnumDescriptor;
+using google::protobuf::EnumValueDescriptor;
+;
+;
+;
+using util::error::Code;
+using util::Status;
+using util::StatusOr;
+
+namespace {
+
+inline Status InvalidArgument(StringPiece value_str) {
+  return Status(util::error::INVALID_ARGUMENT, value_str);
+}
+
+template <typename To, typename From>
+StatusOr<To> ValidateNumberConversion(To after, From before) {
+  if (after == before &&
+      MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
+    return after;
+  } else {
+    return InvalidArgument(::google::protobuf::internal::is_integral<From>::value
+                               ? ValueAsString(before)
+                               : ::google::protobuf::internal::is_same<From, double>::value
+                                     ? DoubleAsString(before)
+                                     : FloatAsString(before));
+  }
+}
+
+// For general conversion between
+//     int32, int64, uint32, uint64, double and float
+// except conversion between double and float.
+template <typename To, typename From>
+StatusOr<To> NumberConvertAndCheck(From before) {
+  if (::google::protobuf::internal::is_same<From, To>::value) return before;
+
+  To after = static_cast<To>(before);
+  return ValidateNumberConversion(after, before);
+}
+
+// For conversion to integer types (int32, int64, uint32, uint64) from floating
+// point types (double, float) only.
+template <typename To, typename From>
+StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
+  if (::google::protobuf::internal::is_same<From, To>::value) return before;
+
+  To after = static_cast<To>(before);
+  return ValidateNumberConversion(after, before);
+}
+
+// For conversion between double and float only.
+template <typename To, typename From>
+StatusOr<To> FloatingPointConvertAndCheck(From before) {
+  if (MathLimits<From>::IsNaN(before)) {
+    return std::numeric_limits<To>::quiet_NaN();
+  }
+
+  To after = static_cast<To>(before);
+  if (MathUtil::AlmostEquals<To>(after, before)) {
+    return after;
+  } else {
+    return InvalidArgument(::google::protobuf::internal::is_same<From, double>::value
+                               ? DoubleAsString(before)
+                               : FloatAsString(before));
+  }
+}
+
+}  // namespace
+
+StatusOr<int32> DataPiece::ToInt32() const {
+  if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<int32, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<int32, float>(float_);
+
+  return GenericConvert<int32>();
+}
+
+StatusOr<uint32> DataPiece::ToUint32() const {
+  if (type_ == TYPE_STRING) return StringToNumber<uint32>(safe_strtou32);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<uint32, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<uint32, float>(float_);
+
+  return GenericConvert<uint32>();
+}
+
+StatusOr<int64> DataPiece::ToInt64() const {
+  if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<int64, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<int64, float>(float_);
+
+  return GenericConvert<int64>();
+}
+
+StatusOr<uint64> DataPiece::ToUint64() const {
+  if (type_ == TYPE_STRING) return StringToNumber<uint64>(safe_strtou64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<uint64, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<uint64, float>(float_);
+
+  return GenericConvert<uint64>();
+}
+
+StatusOr<double> DataPiece::ToDouble() const {
+  if (type_ == TYPE_FLOAT) {
+    return FloatingPointConvertAndCheck<double, float>(float_);
+  }
+  if (type_ == TYPE_STRING) {
+    if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
+    if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
+    if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
+    return StringToNumber<double>(safe_strtod);
+  }
+  return GenericConvert<double>();
+}
+
+StatusOr<float> DataPiece::ToFloat() const {
+  if (type_ == TYPE_DOUBLE) {
+    return FloatingPointConvertAndCheck<float, double>(double_);
+  }
+  if (type_ == TYPE_STRING) {
+    if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
+    if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity();
+    if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN();
+    // SafeStrToFloat() is used instead of safe_strtof() because the later
+    // does not fail on inputs like SimpleDtoa(DBL_MAX).
+    return StringToNumber<float>(SafeStrToFloat);
+  }
+  return GenericConvert<float>();
+}
+
+StatusOr<bool> DataPiece::ToBool() const {
+  switch (type_) {
+    case TYPE_BOOL:
+      return bool_;
+    case TYPE_STRING:
+      return StringToNumber<bool>(safe_strtob);
+    default:
+      return InvalidArgument(
+          ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
+  }
+}
+
+StatusOr<string> DataPiece::ToString() const {
+  switch (type_) {
+    case TYPE_STRING:
+      return str_.ToString();
+    case TYPE_BYTES: {
+      string base64;
+      Base64Escape(str_, &base64);
+      return base64;
+    }
+    default:
+      return InvalidArgument(
+          ValueAsStringOrDefault("Cannot convert to string."));
+  }
+}
+
+string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const {
+  switch (type_) {
+    case TYPE_INT32:
+      return SimpleItoa(i32_);
+    case TYPE_INT64:
+      return SimpleItoa(i64_);
+    case TYPE_UINT32:
+      return SimpleItoa(u32_);
+    case TYPE_UINT64:
+      return SimpleItoa(u64_);
+    case TYPE_DOUBLE:
+      return DoubleAsString(double_);
+    case TYPE_FLOAT:
+      return FloatAsString(float_);
+    case TYPE_BOOL:
+      return SimpleBtoa(bool_);
+    case TYPE_STRING:
+      return StrCat("\"", str_.ToString(), "\"");
+    case TYPE_BYTES: {
+      string base64;
+      WebSafeBase64Escape(str_, &base64);
+      return StrCat("\"", base64, "\"");
+    }
+    case TYPE_NULL:
+      return "null";
+    default:
+      return default_string.ToString();
+  }
+}
+
+StatusOr<string> DataPiece::ToBytes() const {
+  if (type_ == TYPE_BYTES) return str_.ToString();
+  if (type_ == TYPE_STRING) {
+    string decoded;
+    if (!DecodeBase64(str_, &decoded)) {
+      return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
+    }
+    return decoded;
+  } else {
+    return InvalidArgument(ValueAsStringOrDefault(
+        "Wrong type. Only String or Bytes can be converted to Bytes."));
+  }
+}
+
+StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const {
+  if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
+
+  if (type_ == TYPE_STRING) {
+    // First try the given value as a name.
+    string enum_name = str_.ToString();
+    const google::protobuf::EnumValue* value =
+        FindEnumValueByNameOrNull(enum_type, enum_name);
+    if (value != NULL) return value->number();
+    // Next try a normalized name.
+    for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) {
+      *it = *it == '-' ? '_' : ascii_toupper(*it);
+    }
+    value = FindEnumValueByNameOrNull(enum_type, enum_name);
+    if (value != NULL) return value->number();
+  } else {
+    StatusOr<int32> value = ToInt32();
+    if (value.ok()) {
+      if (const google::protobuf::EnumValue* enum_value =
+              FindEnumValueByNumberOrNull(enum_type, value.ValueOrDie())) {
+        return enum_value->number();
+      }
+    }
+  }
+  return InvalidArgument(
+      ValueAsStringOrDefault("Cannot find enum with given value."));
+}
+
+template <typename To>
+StatusOr<To> DataPiece::GenericConvert() const {
+  switch (type_) {
+    case TYPE_INT32:
+      return NumberConvertAndCheck<To, int32>(i32_);
+    case TYPE_INT64:
+      return NumberConvertAndCheck<To, int64>(i64_);
+    case TYPE_UINT32:
+      return NumberConvertAndCheck<To, uint32>(u32_);
+    case TYPE_UINT64:
+      return NumberConvertAndCheck<To, uint64>(u64_);
+    case TYPE_DOUBLE:
+      return NumberConvertAndCheck<To, double>(double_);
+    case TYPE_FLOAT:
+      return NumberConvertAndCheck<To, float>(float_);
+    default:  // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
+      return InvalidArgument(ValueAsStringOrDefault(
+          "Wrong type. Bool, Enum, String and Cord not supported in "
+          "GenericConvert."));
+  }
+}
+
+template <typename To>
+StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const {
+  if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
+    return InvalidArgument(StrCat("\"", str_, "\""));
+  }
+  To result;
+  if (func(str_, &result)) return result;
+  return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
+}
+
+bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
+  // Try web-safe decode first, if it fails, try the non-web-safe decode.
+  if (WebSafeBase64Unescape(src, dest)) {
+    if (use_strict_base64_decoding_) {
+      // In strict mode, check if the escaped version gives us the same value as
+      // unescaped.
+      string encoded;
+      // WebSafeBase64Escape does no padding by default.
+      WebSafeBase64Escape(*dest, &encoded);
+      // Remove trailing padding '=' characters before comparison.
+      StringPiece src_no_padding(src, 0, src.ends_with("=")
+                                             ? src.find_last_not_of('=') + 1
+                                             : src.length());
+      return encoded == src_no_padding;
+    }
+    return true;
+  }
+
+  if (Base64Unescape(src, dest)) {
+    if (use_strict_base64_decoding_) {
+      string encoded;
+      Base64Escape(
+          reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
+          &encoded, false);
+      StringPiece src_no_padding(src, 0, src.ends_with("=")
+                                             ? src.find_last_not_of('=') + 1
+                                             : src.length());
+      return encoded == src_no_padding;
+    }
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.h
new file mode 100644
index 0000000..8b2e35d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/datapiece.h
@@ -0,0 +1,200 @@
+// 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_UTIL_CONVERTER_DATAPIECE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+class Enum;
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// Container for a single piece of data together with its data type.
+//
+// For primitive types (int32, int64, uint32, uint64, double, float, bool),
+// the data is stored by value.
+//
+// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored.
+// Just like StringPiece, the DataPiece class does not own the storage for
+// the actual string or Cord, so it is the user's responsiblity to guarantee
+// that the underlying storage is still valid when the DataPiece is accessed.
+class LIBPROTOBUF_EXPORT DataPiece {
+ public:
+  // Identifies data type of the value.
+  // These are the types supported by DataPiece.
+  enum Type {
+    TYPE_INT32 = 1,
+    TYPE_INT64 = 2,
+    TYPE_UINT32 = 3,
+    TYPE_UINT64 = 4,
+    TYPE_DOUBLE = 5,
+    TYPE_FLOAT = 6,
+    TYPE_BOOL = 7,
+    TYPE_ENUM = 8,
+    TYPE_STRING = 9,
+    TYPE_BYTES = 10,
+    TYPE_NULL = 11,  // explicit NULL type
+  };
+
+  // Constructors and Destructor
+  explicit DataPiece(const int32 value) : type_(TYPE_INT32), i32_(value) {}
+  explicit DataPiece(const int64 value) : type_(TYPE_INT64), i64_(value) {}
+  explicit DataPiece(const uint32 value) : type_(TYPE_UINT32), u32_(value) {}
+  explicit DataPiece(const uint64 value) : type_(TYPE_UINT64), u64_(value) {}
+  explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {}
+  explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {}
+  explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {}
+  DataPiece(StringPiece value, bool use_strict_base64_decoding)
+      : type_(TYPE_STRING),
+        str_(StringPiecePod::CreateFromStringPiece(value)),
+        use_strict_base64_decoding_(use_strict_base64_decoding) {}
+  // Constructor for bytes. The second parameter is not used.
+  DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding)
+      : type_(TYPE_BYTES),
+        str_(StringPiecePod::CreateFromStringPiece(value)),
+        use_strict_base64_decoding_(use_strict_base64_decoding) {}
+  DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {}
+  DataPiece& operator=(const DataPiece& x) {
+    type_ = x.type_;
+    str_ = x.str_;
+    return *this;
+  }
+
+  static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); }
+
+  virtual ~DataPiece() {
+  }
+
+  // Accessors
+  Type type() const { return type_; }
+
+  StringPiece str() const {
+    GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type.";
+    return str_;
+  }
+
+
+  // Parses, casts or converts the value stored in the DataPiece into an int32.
+  util::StatusOr<int32> ToInt32() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a uint32.
+  util::StatusOr<uint32> ToUint32() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into an int64.
+  util::StatusOr<int64> ToInt64() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a uint64.
+  util::StatusOr<uint64> ToUint64() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a double.
+  util::StatusOr<double> ToDouble() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a float.
+  util::StatusOr<float> ToFloat() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a bool.
+  util::StatusOr<bool> ToBool() const;
+
+  // Parses, casts or converts the value stored in the DataPiece into a string.
+  util::StatusOr<string> ToString() const;
+
+  // Tries to convert the value contained in this datapiece to string. If the
+  // conversion fails, it returns the default_string.
+  string ValueAsStringOrDefault(StringPiece default_string) const;
+
+  util::StatusOr<string> ToBytes() const;
+
+  // Converts a value into protocol buffer enum number. If the value is a
+  // string, first attempts conversion by name, trying names as follows:
+  //   1) the directly provided string value.
+  //   2) the value upper-cased and replacing '-' by '_'
+  // If the value is not a string, attempts to convert to a 32-bit integer.
+  // If none of these succeeds, returns a conversion error status.
+  util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type) const;
+
+ private:
+  // Disallow implicit constructor.
+  DataPiece();
+
+  // Helper to create NULL or ENUM types.
+  DataPiece(Type type, int32 val) : type_(type), i32_(val) {}
+
+  // For numeric conversion between
+  //     int32, int64, uint32, uint64, double, float and bool
+  template <typename To>
+  util::StatusOr<To> GenericConvert() const;
+
+  // For conversion from string to
+  //     int32, int64, uint32, uint64, double, float and bool
+  template <typename To>
+  util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
+
+  // Decodes a base64 string. Returns true on success.
+  bool DecodeBase64(StringPiece src, string* dest) const;
+
+  // Data type for this piece of data.
+  Type type_;
+
+  typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
+
+  // Stored piece of data.
+  union {
+    int32 i32_;
+    int64 i64_;
+    uint32 u32_;
+    uint64 u64_;
+    double double_;
+    float float_;
+    bool bool_;
+    StringPiecePod str_;
+  };
+
+  // Uses a stricter version of base64 decoding for byte fields.
+  bool use_strict_base64_decoding_;
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.cc
new file mode 100644
index 0000000..21d7a2e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -0,0 +1,591 @@
+// 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.
+
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+using util::StatusOr;
+namespace converter {
+
+namespace {
+// Helper function to convert string value to given data type by calling the
+// passed converter function on the DataPiece created from "value" argument.
+// If value is empty or if conversion fails, the default_value is returned.
+template <typename T>
+T ConvertTo(StringPiece value, StatusOr<T> (DataPiece::*converter_fn)() const,
+            T default_value) {
+  if (value.empty()) return default_value;
+  StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
+  return result.ok() ? result.ValueOrDie() : default_value;
+}
+}  // namespace
+
+DefaultValueObjectWriter::DefaultValueObjectWriter(
+    TypeResolver* type_resolver, const google::protobuf::Type& type,
+    ObjectWriter* ow)
+    : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+      own_typeinfo_(true),
+      type_(type),
+      current_(NULL),
+      root_(NULL),
+      field_scrub_callback_(NULL),
+      ow_(ow) {}
+
+DefaultValueObjectWriter::~DefaultValueObjectWriter() {
+  for (int i = 0; i < string_values_.size(); ++i) {
+    delete string_values_[i];
+  }
+  if (own_typeinfo_) {
+    delete typeinfo_;
+  }
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name,
+                                                               bool value) {
+  if (current_ == NULL) {
+    ow_->RenderBool(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
+    StringPiece name, int32 value) {
+  if (current_ == NULL) {
+    ow_->RenderInt32(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
+    StringPiece name, uint32 value) {
+  if (current_ == NULL) {
+    ow_->RenderUint32(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
+    StringPiece name, int64 value) {
+  if (current_ == NULL) {
+    ow_->RenderInt64(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
+    StringPiece name, uint64 value) {
+  if (current_ == NULL) {
+    ow_->RenderUint64(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble(
+    StringPiece name, double value) {
+  if (current_ == NULL) {
+    ow_->RenderDouble(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat(
+    StringPiece name, float value) {
+  if (current_ == NULL) {
+    ow_->RenderBool(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
+    StringPiece name, StringPiece value) {
+  if (current_ == NULL) {
+    ow_->RenderString(name, value);
+  } else {
+    // Since StringPiece is essentially a pointer, takes a copy of "value" to
+    // avoid ownership issues.
+    string_values_.push_back(new string(value.ToString()));
+    RenderDataPiece(name, DataPiece(*string_values_.back(), true));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
+    StringPiece name, StringPiece value) {
+  if (current_ == NULL) {
+    ow_->RenderBytes(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value, false, true));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
+    StringPiece name) {
+  if (current_ == NULL) {
+    ow_->RenderNull(name);
+  } else {
+    RenderDataPiece(name, DataPiece::NullData());
+  }
+  return this;
+}
+
+void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
+    FieldScrubCallBackPtr field_scrub_callback) {
+  field_scrub_callback_.reset(field_scrub_callback.release());
+}
+
+DefaultValueObjectWriter::Node::Node(const string& name,
+                                     const google::protobuf::Type* type,
+                                     NodeKind kind, const DataPiece& data,
+                                     bool is_placeholder,
+                                     const vector<string>& path,
+                                     FieldScrubCallBack* field_scrub_callback)
+    : name_(name),
+      type_(type),
+      kind_(kind),
+      is_any_(false),
+      data_(data),
+      is_placeholder_(is_placeholder),
+      path_(path),
+      field_scrub_callback_(field_scrub_callback) {}
+
+DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
+    StringPiece name) {
+  if (name.empty() || kind_ != OBJECT) {
+    return NULL;
+  }
+  for (int i = 0; i < children_.size(); ++i) {
+    Node* child = children_[i];
+    if (child->name() == name) {
+      return child;
+    }
+  }
+  return NULL;
+}
+
+void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
+  if (kind_ == PRIMITIVE) {
+    ObjectWriter::RenderDataPieceTo(data_, name_, ow);
+    return;
+  }
+
+  // Render maps. Empty maps are rendered as "{}".
+  if (kind_ == MAP) {
+    ow->StartObject(name_);
+    WriteChildren(ow);
+    ow->EndObject();
+    return;
+  }
+
+  // Write out lists. If we didn't have any list in response, write out empty
+  // list.
+  if (kind_ == LIST) {
+    ow->StartList(name_);
+    WriteChildren(ow);
+    ow->EndList();
+    return;
+  }
+
+  // If is_placeholder_ = true, we didn't see this node in the response, so
+  // skip output.
+  if (is_placeholder_) return;
+
+  ow->StartObject(name_);
+  WriteChildren(ow);
+  ow->EndObject();
+}
+
+void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
+  for (int i = 0; i < children_.size(); ++i) {
+    Node* child = children_[i];
+    child->WriteTo(ow);
+  }
+}
+
+const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
+    const google::protobuf::Type& found_type, const TypeInfo* typeinfo) {
+  // If this field is a map, we should use the type of its "Value" as
+  // the type of the child node.
+  for (int i = 0; i < found_type.fields_size(); ++i) {
+    const google::protobuf::Field& sub_field = found_type.fields(i);
+    if (sub_field.number() != 2) {
+      continue;
+    }
+    if (sub_field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE) {
+      // This map's value type is not a message type. We don't need to
+      // get the field_type in this case.
+      break;
+    }
+    util::StatusOr<const google::protobuf::Type*> sub_type =
+        typeinfo->ResolveTypeUrl(sub_field.type_url());
+    if (!sub_type.ok()) {
+      GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'.";
+    } else {
+      return sub_type.ValueOrDie();
+    }
+    break;
+  }
+  return NULL;
+}
+
+void DefaultValueObjectWriter::Node::PopulateChildren(
+    const TypeInfo* typeinfo) {
+  // Ignores well known types that don't require automatically populating their
+  // primitive children. For type "Any", we only populate its children when the
+  // "@type" field is set.
+  // TODO(tsun): remove "kStructValueType" from the list. It's being checked
+  //     now because of a bug in the tool-chain that causes the "oneof_index"
+  //     of kStructValueType to not be set correctly.
+  if (type_ == NULL || type_->name() == kAnyType ||
+      type_->name() == kStructType || type_->name() == kTimestampType ||
+      type_->name() == kDurationType || type_->name() == kStructValueType) {
+    return;
+  }
+  std::vector<Node*> new_children;
+  hash_map<string, int> orig_children_map;
+
+  // Creates a map of child nodes to speed up lookup.
+  for (int i = 0; i < children_.size(); ++i) {
+    InsertIfNotPresent(&orig_children_map, children_[i]->name_, i);
+  }
+
+  for (int i = 0; i < type_->fields_size(); ++i) {
+    const google::protobuf::Field& field = type_->fields(i);
+
+    // This code is checking if the field to be added to the tree should be
+    // scrubbed or not by calling the field_scrub_callback_ callback function.
+    vector<string> path;
+    if (!path_.empty()) {
+      path.insert(path.begin(), path_.begin(), path_.end());
+    }
+    path.push_back(field.name());
+    if (field_scrub_callback_ != NULL &&
+        field_scrub_callback_->Run(path, &field)) {
+      continue;
+    }
+
+    hash_map<string, int>::iterator found =
+        orig_children_map.find(field.name());
+    // If the child field has already been set, we just add it to the new list
+    // of children.
+    if (found != orig_children_map.end()) {
+      new_children.push_back(children_[found->second]);
+      children_[found->second] = NULL;
+      continue;
+    }
+
+    const google::protobuf::Type* field_type = NULL;
+    bool is_map = false;
+    NodeKind kind = PRIMITIVE;
+
+    if (field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+      kind = OBJECT;
+      util::StatusOr<const google::protobuf::Type*> found_result =
+          typeinfo->ResolveTypeUrl(field.type_url());
+      if (!found_result.ok()) {
+        // "field" is of an unknown type.
+        GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'.";
+      } else {
+        const google::protobuf::Type* found_type = found_result.ValueOrDie();
+        is_map = IsMap(field, *found_type);
+
+        if (!is_map) {
+          field_type = found_type;
+        } else {
+          // If this field is a map, we should use the type of its "Value" as
+          // the type of the child node.
+          field_type = GetMapValueType(*found_type, typeinfo);
+          kind = MAP;
+        }
+      }
+    }
+
+    if (!is_map &&
+        field.cardinality() ==
+            google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+      kind = LIST;
+    }
+
+    // If oneof_index() != 0, the child field is part of a "oneof", which means
+    // the child field is optional and we shouldn't populate its default value.
+    if (field.oneof_index() != 0) continue;
+
+    // If the child field is of primitive type, sets its data to the default
+    // value of its type.
+    google::protobuf::scoped_ptr<Node> child(new Node(
+        field.json_name(), field_type, kind,
+        kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
+                          : DataPiece::NullData(),
+        true, path, field_scrub_callback_));
+    new_children.push_back(child.release());
+  }
+  // Adds all leftover nodes in children_ to the beginning of new_child.
+  for (int i = 0; i < children_.size(); ++i) {
+    if (children_[i] == NULL) {
+      continue;
+    }
+    new_children.insert(new_children.begin(), children_[i]);
+    children_[i] = NULL;
+  }
+  children_.swap(new_children);
+}
+
+void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
+  // If this is an "Any" node with "@type" already given and no other children
+  // have been added, populates its children.
+  if (node != NULL && node->is_any() && node->type() != NULL &&
+      node->type()->name() != kAnyType && node->number_of_children() == 1) {
+    node->PopulateChildren(typeinfo_);
+  }
+}
+
+DataPiece DefaultValueObjectWriter::FindEnumDefault(
+    const google::protobuf::Field& field, const TypeInfo* typeinfo) {
+  if (!field.default_value().empty())
+    return DataPiece(field.default_value(), true);
+
+  const google::protobuf::Enum* enum_type =
+      typeinfo->GetEnumByTypeUrl(field.type_url());
+  if (!enum_type) {
+    GOOGLE_LOG(WARNING) << "Could not find enum with type '" << field.type_url()
+                 << "'";
+    return DataPiece::NullData();
+  }
+  // We treat the first value as the default if none is specified.
+  return enum_type->enumvalue_size() > 0
+             ? DataPiece(enum_type->enumvalue(0).name(), true)
+             : DataPiece::NullData();
+}
+
+DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
+    const google::protobuf::Field& field, const TypeInfo* typeinfo) {
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+      return DataPiece(ConvertTo<double>(
+          field.default_value(), &DataPiece::ToDouble, static_cast<double>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_FLOAT: {
+      return DataPiece(ConvertTo<float>(
+          field.default_value(), &DataPiece::ToFloat, static_cast<float>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_INT64:
+    case google::protobuf::Field_Kind_TYPE_SINT64:
+    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+      return DataPiece(ConvertTo<int64>(
+          field.default_value(), &DataPiece::ToInt64, static_cast<int64>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT64:
+    case google::protobuf::Field_Kind_TYPE_FIXED64: {
+      return DataPiece(ConvertTo<uint64>(
+          field.default_value(), &DataPiece::ToUint64, static_cast<uint64>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_INT32:
+    case google::protobuf::Field_Kind_TYPE_SINT32:
+    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+      return DataPiece(ConvertTo<int32>(
+          field.default_value(), &DataPiece::ToInt32, static_cast<int32>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_BOOL: {
+      return DataPiece(
+          ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false));
+    }
+    case google::protobuf::Field_Kind_TYPE_STRING: {
+      return DataPiece(field.default_value(), true);
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      return DataPiece(field.default_value(), false, true);
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT32:
+    case google::protobuf::Field_Kind_TYPE_FIXED32: {
+      return DataPiece(ConvertTo<uint32>(
+          field.default_value(), &DataPiece::ToUint32, static_cast<uint32>(0)));
+    }
+    case google::protobuf::Field_Kind_TYPE_ENUM: {
+      return FindEnumDefault(field, typeinfo);
+    }
+    default: { return DataPiece::NullData(); }
+  }
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
+    StringPiece name) {
+  if (current_ == NULL) {
+    vector<string> path;
+    root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
+                         false, path, field_scrub_callback_.get()));
+    root_->PopulateChildren(typeinfo_);
+    current_ = root_.get();
+    return this;
+  }
+  MaybePopulateChildrenOfAny(current_);
+  Node* child = current_->FindChild(name);
+  if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) {
+    // If current_ is a list or a map node, we should create a new child and use
+    // the type of current_ as the type of the new child.
+    google::protobuf::scoped_ptr<Node> node(new Node(
+        name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP)
+                              ? current_->type()
+                              : NULL),
+        OBJECT, DataPiece::NullData(), false,
+        child == NULL ? current_->path() : child->path(),
+        field_scrub_callback_.get()));
+    child = node.get();
+    current_->AddChild(node.release());
+  }
+
+  child->set_is_placeholder(false);
+  if (child->kind() == OBJECT && child->number_of_children() == 0) {
+    child->PopulateChildren(typeinfo_);
+  }
+
+  stack_.push(current_);
+  current_ = child;
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
+  if (stack_.empty()) {
+    // The root object ends here. Writes out the tree.
+    WriteRoot();
+    return this;
+  }
+  current_ = stack_.top();
+  stack_.pop();
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
+    StringPiece name) {
+  if (current_ == NULL) {
+    vector<string> path;
+    root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
+                         false, path, field_scrub_callback_.get()));
+    current_ = root_.get();
+    return this;
+  }
+  MaybePopulateChildrenOfAny(current_);
+  Node* child = current_->FindChild(name);
+  if (child == NULL || child->kind() != LIST) {
+    google::protobuf::scoped_ptr<Node> node(
+        new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
+                 child == NULL ? current_->path() : child->path(),
+                 field_scrub_callback_.get()));
+    child = node.get();
+    current_->AddChild(node.release());
+  }
+  child->set_is_placeholder(false);
+
+  stack_.push(current_);
+  current_ = child;
+  return this;
+}
+
+void DefaultValueObjectWriter::WriteRoot() {
+  root_->WriteTo(ow_);
+  root_.reset(NULL);
+  current_ = NULL;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() {
+  if (stack_.empty()) {
+    WriteRoot();
+    return this;
+  }
+  current_ = stack_.top();
+  stack_.pop();
+  return this;
+}
+
+void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
+                                               const DataPiece& data) {
+  MaybePopulateChildrenOfAny(current_);
+  util::StatusOr<string> data_string = data.ToString();
+  if (current_->type() != NULL && current_->type()->name() == kAnyType &&
+      name == "@type" && data_string.ok()) {
+    const string& string_value = data_string.ValueOrDie();
+    // If the type of current_ is "Any" and its "@type" field is being set here,
+    // sets the type of current_ to be the type specified by the "@type".
+    util::StatusOr<const google::protobuf::Type*> found_type =
+        typeinfo_->ResolveTypeUrl(string_value);
+    if (!found_type.ok()) {
+      GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
+    } else {
+      current_->set_type(found_type.ValueOrDie());
+    }
+    current_->set_is_any(true);
+    // If the "@type" field is placed after other fields, we should populate
+    // other children of primitive type now. Otherwise, we should wait until the
+    // first value field is rendered before we populate the children, because
+    // the "value" field of a Any message could be omitted.
+    if (current_->number_of_children() > 1 && current_->type() != NULL) {
+      current_->PopulateChildren(typeinfo_);
+    }
+  }
+  Node* child = current_->FindChild(name);
+  if (child == NULL || child->kind() != PRIMITIVE) {
+    // No children are found, creates a new child.
+    google::protobuf::scoped_ptr<Node> node(
+        new Node(name.ToString(), NULL, PRIMITIVE, data, false,
+                 child == NULL ? current_->path() : child->path(),
+                 field_scrub_callback_.get()));
+    child = node.get();
+    current_->AddChild(node.release());
+  } else {
+    child->set_data(data);
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.h
new file mode 100644
index 0000000..1d85bed
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -0,0 +1,274 @@
+// 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_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <stack>
+#include <vector>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/datapiece.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An ObjectWriter that renders non-repeated primitive fields of proto messages
+// with their default values. DefaultValueObjectWriter holds objects, lists and
+// fields it receives in a tree structure and writes them out to another
+// ObjectWriter when EndObject() is called on the root object. It also writes
+// out all non-repeated primitive fields that haven't been explicitly rendered
+// with their default values (0 for numbers, "" for strings, etc).
+class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
+ public:
+  // A Callback function to check whether a field needs to be scrubbed.
+  //
+  // Returns true if the field should not be present in the output. Returns
+  // false otherwise.
+  //
+  // The 'path' parameter is a vector of path to the field from root. For
+  // example: if a nested field "a.b.c" (b is the parent message field of c and
+  // a is the parent message field of b), then the vector should contain { "a",
+  // "b", "c" }.
+  //
+  // The Field* should point to the google::protobuf::Field of "c".
+  typedef ResultCallback2<bool /*return*/,
+                          const std::vector<string>& /*path of the field*/,
+                          const google::protobuf::Field* /*field*/>
+      FieldScrubCallBack;
+
+  // A unique pointer to a DefaultValueObjectWriter::FieldScrubCallBack.
+  typedef google::protobuf::scoped_ptr<FieldScrubCallBack> FieldScrubCallBackPtr;
+
+  DefaultValueObjectWriter(TypeResolver* type_resolver,
+                           const google::protobuf::Type& type,
+                           ObjectWriter* ow);
+
+  virtual ~DefaultValueObjectWriter();
+
+  // ObjectWriter methods.
+  virtual DefaultValueObjectWriter* StartObject(StringPiece name);
+
+  virtual DefaultValueObjectWriter* EndObject();
+
+  virtual DefaultValueObjectWriter* StartList(StringPiece name);
+
+  virtual DefaultValueObjectWriter* EndList();
+
+  virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value);
+
+  virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value);
+
+  virtual DefaultValueObjectWriter* RenderUint32(StringPiece name,
+                                                 uint32 value);
+
+  virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value);
+
+  virtual DefaultValueObjectWriter* RenderUint64(StringPiece name,
+                                                 uint64 value);
+
+  virtual DefaultValueObjectWriter* RenderDouble(StringPiece name,
+                                                 double value);
+
+  virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value);
+
+  virtual DefaultValueObjectWriter* RenderString(StringPiece name,
+                                                 StringPiece value);
+  virtual DefaultValueObjectWriter* RenderBytes(StringPiece name,
+                                                StringPiece value);
+
+  virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
+
+  // Register the callback for scrubbing of fields. Owership of
+  // field_scrub_callback pointer is also transferred to this class
+  void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback);
+
+ private:
+  enum NodeKind {
+    PRIMITIVE = 0,
+    OBJECT = 1,
+    LIST = 2,
+    MAP = 3,
+  };
+
+  // "Node" represents a node in the tree that holds the input of
+  // DefaultValueObjectWriter.
+  class LIBPROTOBUF_EXPORT Node {
+   public:
+    Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
+         const DataPiece& data, bool is_placeholder, const vector<string>& path,
+         FieldScrubCallBack* field_scrub_callback);
+    virtual ~Node() {
+      for (int i = 0; i < children_.size(); ++i) {
+        delete children_[i];
+      }
+    }
+
+    // Adds a child to this node. Takes ownership of this child.
+    void AddChild(Node* child) { children_.push_back(child); }
+
+    // Finds the child given its name.
+    Node* FindChild(StringPiece name);
+
+    // Populates children of this Node based on its type. If there are already
+    // children created, they will be merged to the result. Caller should pass
+    // in TypeInfo for looking up types of the children.
+    void PopulateChildren(const TypeInfo* typeinfo);
+
+    // If this node is a leaf (has data), writes the current node to the
+    // ObjectWriter; if not, then recursively writes the children to the
+    // ObjectWriter.
+    void WriteTo(ObjectWriter* ow);
+
+    // Accessors
+    const string& name() const { return name_; }
+
+    const vector<string>& path() const { return path_; }
+
+    const google::protobuf::Type* type() const { return type_; }
+
+    void set_type(const google::protobuf::Type* type) { type_ = type; }
+
+    NodeKind kind() const { return kind_; }
+
+    int number_of_children() const { return children_.size(); }
+
+    void set_data(const DataPiece& data) { data_ = data; }
+
+    bool is_any() const { return is_any_; }
+
+    void set_is_any(bool is_any) { is_any_ = is_any; }
+
+    void set_is_placeholder(bool is_placeholder) {
+      is_placeholder_ = is_placeholder;
+    }
+
+   private:
+    // Returns the Value Type of a map given the Type of the map entry and a
+    // TypeInfo instance.
+    const google::protobuf::Type* GetMapValueType(
+        const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
+
+    // Calls WriteTo() on every child in children_.
+    void WriteChildren(ObjectWriter* ow);
+
+    // The name of this node.
+    string name_;
+    // google::protobuf::Type of this node. Owned by TypeInfo.
+    const google::protobuf::Type* type_;
+    // The kind of this node.
+    NodeKind kind_;
+    // Whether this is a node for "Any".
+    bool is_any_;
+    // The data of this node when it is a leaf node.
+    DataPiece data_;
+    // Children of this node.
+    std::vector<Node*> children_;
+    // Whether this node is a placeholder for an object or list automatically
+    // generated when creating the parent node. Should be set to false after
+    // the parent node's StartObject()/StartList() method is called with this
+    // node's name.
+    bool is_placeholder_;
+
+    // Path of the field of this node
+    std::vector<string> path_;
+
+    // Pointer to function for determining whether a field needs to be scrubbed
+    // or not. This callback is owned by the creator of this node.
+    FieldScrubCallBack* field_scrub_callback_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
+  };
+
+  // Populates children of "node" if it is an "any" Node and its real type has
+  // been given.
+  void MaybePopulateChildrenOfAny(Node* node);
+
+  // Writes the root_ node to ow_ and resets the root_ and current_ pointer to
+  // NULL.
+  void WriteRoot();
+
+  // Creates a DataPiece containing the default value of the type of the field.
+  static DataPiece CreateDefaultDataPieceForField(
+      const google::protobuf::Field& field, const TypeInfo* typeinfo);
+
+  // Adds or replaces the data_ of a primitive child node.
+  void RenderDataPiece(StringPiece name, const DataPiece& data);
+
+  // Returns the default enum value as a DataPiece, or the first enum value if
+  // there is no default. For proto3, where we cannot specify an explicit
+  // default, a zero value will always be returned.
+  static DataPiece FindEnumDefault(const google::protobuf::Field& field,
+                                   const TypeInfo* typeinfo);
+
+  // Type information for all the types used in the descriptor. Used to find
+  // google::protobuf::Type of nested messages/enums.
+  const TypeInfo* typeinfo_;
+  // Whether the TypeInfo object is owned by this class.
+  bool own_typeinfo_;
+  // google::protobuf::Type of the root message type.
+  const google::protobuf::Type& type_;
+  // Holds copies of strings passed to RenderString.
+  vector<string*> string_values_;
+
+  // The current Node. Owned by its parents.
+  Node* current_;
+  // The root Node.
+  google::protobuf::scoped_ptr<Node> root_;
+  // The stack to hold the path of Nodes from current_ to root_;
+  std::stack<Node*> stack_;
+
+  // Unique Pointer to function for determining whether a field needs to be
+  // scrubbed or not.
+  FieldScrubCallBackPtr field_scrub_callback_;
+
+  ObjectWriter* ow_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
new file mode 100644
index 0000000..8254c0f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -0,0 +1,156 @@
+// 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.
+
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/testdata/default_value_test.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+using google::protobuf::testing::DefaultValueTest;
+
+// Base class for setting up required state for running default values tests on
+// different descriptors.
+class BaseDefaultValueObjectWriterTest
+    : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+  explicit BaseDefaultValueObjectWriterTest(const Descriptor* descriptor)
+      : helper_(GetParam()), mock_(), expects_(&mock_) {
+    helper_.ResetTypeInfo(descriptor);
+    testing_.reset(helper_.NewDefaultValueWriter(
+        string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(), &mock_));
+  }
+
+  virtual ~BaseDefaultValueObjectWriterTest() {}
+
+  TypeInfoTestHelper helper_;
+  MockObjectWriter mock_;
+  ExpectingObjectWriter expects_;
+  google::protobuf::scoped_ptr<DefaultValueObjectWriter> testing_;
+};
+
+// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are
+// in the marshalling_test.cc and translator_integration_test.cc.
+class DefaultValueObjectWriterTest : public BaseDefaultValueObjectWriterTest {
+ protected:
+  DefaultValueObjectWriterTest()
+      : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {}
+  virtual ~DefaultValueObjectWriterTest() {}
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        DefaultValueObjectWriterTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(DefaultValueObjectWriterTest, Empty) {
+  // Set expectation
+  expects_.StartObject("")
+      ->RenderDouble("doubleValue", 0.0)
+      ->StartList("repeatedDouble")
+      ->EndList()
+      ->RenderFloat("floatValue", 0.0)
+      ->RenderInt64("int64Value", 0)
+      ->RenderUint64("uint64Value", 0)
+      ->RenderInt32("int32Value", 0)
+      ->RenderUint32("uint32Value", 0)
+      ->RenderBool("boolValue", false)
+      ->RenderString("stringValue", "")
+      ->RenderBytes("bytesValue", "")
+      ->RenderString("enumValue", "ENUM_FIRST")
+      ->EndObject();
+
+  // Actual testing
+  testing_->StartObject("")->EndObject();
+}
+
+TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
+  // Set expectation
+  expects_.StartObject("")
+      ->RenderDouble("doubleValue", 1.0)
+      ->StartList("repeatedDouble")
+      ->EndList()
+      ->RenderFloat("floatValue", 0.0)
+      ->RenderInt64("int64Value", 0)
+      ->RenderUint64("uint64Value", 0)
+      ->RenderInt32("int32Value", 0)
+      ->RenderUint32("uint32Value", 0)
+      ->RenderBool("boolValue", false)
+      ->RenderString("stringValue", "")
+      ->RenderString("enumValue", "ENUM_FIRST")
+      ->EndObject();
+
+  // Actual testing
+  testing_->StartObject("")->RenderDouble("doubleValue", 1.0)->EndObject();
+}
+
+TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
+  // Set expectation
+  expects_.StartObject("")
+      ->RenderDouble("doubleValue", 1.0)
+      ->StartList("repeatedDouble")
+      ->EndList()
+      ->RenderFloat("floatValue", 0.0)
+      ->RenderInt64("int64Value", 0)
+      ->RenderUint64("uint64Value", 0)
+      ->RenderInt32("int32Value", 0)
+      ->RenderUint32("uint32Value", 0)
+      ->RenderBool("boolValue", false)
+      ->RenderString("stringValue", "")
+      ->RenderString("unknown", "abc")
+      ->StartObject("unknownObject")
+      ->RenderString("unknown", "def")
+      ->EndObject()
+      ->RenderString("enumValue", "ENUM_FIRST")
+      ->EndObject();
+
+  // Actual testing
+  testing_->StartObject("")
+      ->RenderDouble("doubleValue", 1.0)
+      ->RenderString("unknown", "abc")
+      ->StartObject("unknownObject")
+      ->RenderString("unknown", "def")
+      ->EndObject()
+      ->EndObject();
+}
+
+
+}  // namespace testing
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.cc
new file mode 100644
index 0000000..538307b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.cc
@@ -0,0 +1,42 @@
+// 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.
+
+#include <google/protobuf/util/internal/error_listener.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.h
new file mode 100644
index 0000000..3f06393
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/error_listener.h
@@ -0,0 +1,103 @@
+// 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_UTIL_CONVERTER_ERROR_LISTENER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
+
+#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// Interface for error listener.
+class LIBPROTOBUF_EXPORT ErrorListener {
+ public:
+  virtual ~ErrorListener() {}
+
+  // Reports an invalid name at the given location.
+  virtual void InvalidName(const LocationTrackerInterface& loc,
+                           StringPiece unknown_name, StringPiece message) = 0;
+
+  // Reports an invalid value for a field.
+  virtual void InvalidValue(const LocationTrackerInterface& loc,
+                            StringPiece type_name, StringPiece value) = 0;
+
+  // Reports a missing required field.
+  virtual void MissingField(const LocationTrackerInterface& loc,
+                            StringPiece missing_name) = 0;
+
+ protected:
+  ErrorListener() {}
+
+ private:
+  // Do not add any data members to this class.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener);
+};
+
+// An error listener that ignores all errors.
+class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener {
+ public:
+  NoopErrorListener() {}
+  virtual ~NoopErrorListener() {}
+
+  virtual void InvalidName(const LocationTrackerInterface& loc,
+                           StringPiece unknown_name, StringPiece message) {}
+
+  virtual void InvalidValue(const LocationTrackerInterface& loc,
+                            StringPiece type_name, StringPiece value) {}
+
+  virtual void MissingField(const LocationTrackerInterface& loc,
+                            StringPiece missing_name) {}
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener);
+};
+
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/expecting_objectwriter.h
new file mode 100644
index 0000000..ae98ddd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/expecting_objectwriter.h
@@ -0,0 +1,238 @@
+// 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_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
+
+// An implementation of ObjectWriter that automatically sets the
+// gmock expectations for the response to a method. Every method
+// returns the object itself for chaining.
+//
+// Usage:
+//   // Setup
+//   MockObjectWriter mock;
+//   ExpectingObjectWriter ow(&mock);
+//
+//   // Set expectation
+//   ow.StartObject("")
+//       ->RenderString("key", "value")
+//     ->EndObject();
+//
+//   // Actual testing
+//   mock.StartObject(StringPiece())
+//         ->RenderString("key", "value")
+//       ->EndObject();
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <gmock/gmock.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using testing::IsEmpty;
+using testing::NanSensitiveDoubleEq;
+using testing::NanSensitiveFloatEq;
+using testing::Return;
+using testing::StrEq;
+using testing::TypedEq;
+
+class MockObjectWriter : public ObjectWriter {
+ public:
+  MockObjectWriter() {}
+
+  MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece));
+  MOCK_METHOD0(EndObject, ObjectWriter*());
+  MOCK_METHOD1(StartList, ObjectWriter*(StringPiece));
+  MOCK_METHOD0(EndList, ObjectWriter*());
+  MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, bool));
+  MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, int32));
+  MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, uint32));
+  MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, int64));
+  MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64));
+  MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double));
+  MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float));
+  MOCK_METHOD2(RenderString, ObjectWriter*(StringPiece, StringPiece));
+  MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece));
+  MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece));
+};
+
+class ExpectingObjectWriter : public ObjectWriter {
+ public:
+  explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {}
+
+  virtual ObjectWriter* StartObject(StringPiece name) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, StartObject(IsEmpty()))
+         : EXPECT_CALL(*mock_, StartObject(StrEq(name.ToString()))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* EndObject() {
+    EXPECT_CALL(*mock_, EndObject())
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* StartList(StringPiece name) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, StartList(IsEmpty()))
+         : EXPECT_CALL(*mock_, StartList(StrEq(name.ToString()))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* EndList() {
+    EXPECT_CALL(*mock_, EndList())
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderBool(StringPiece name, bool value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value)))
+         : EXPECT_CALL(*mock_, RenderBool(StrEq(name.ToString()),
+                                          TypedEq<bool>(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value)))
+         : EXPECT_CALL(*mock_, RenderInt32(StrEq(name.ToString()),
+                                           TypedEq<int32>(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value)))
+         : EXPECT_CALL(*mock_, RenderUint32(StrEq(name.ToString()),
+                                            TypedEq<uint32>(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value)))
+         : EXPECT_CALL(*mock_, RenderInt64(StrEq(name.ToString()),
+                                           TypedEq<int64>(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value)))
+         : EXPECT_CALL(*mock_, RenderUint64(StrEq(name.ToString()),
+                                            TypedEq<uint64>(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderDouble(StringPiece name, double value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderDouble(IsEmpty(),
+                                            NanSensitiveDoubleEq(value)))
+         : EXPECT_CALL(*mock_, RenderDouble(StrEq(name.ToString()),
+                                            NanSensitiveDoubleEq(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderFloat(StringPiece name, float value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderFloat(IsEmpty(),
+                                           NanSensitiveFloatEq(value)))
+         : EXPECT_CALL(*mock_, RenderFloat(StrEq(name.ToString()),
+                                           NanSensitiveFloatEq(value))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderString(IsEmpty(),
+               TypedEq<StringPiece>(value.ToString())))
+         : EXPECT_CALL(*mock_, RenderString(StrEq(name.ToString()),
+               TypedEq<StringPiece>(value.ToString()))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+  virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) {
+    (name.empty()
+         ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>(
+                                                          value.ToString())))
+         : EXPECT_CALL(*mock_,
+                       RenderBytes(StrEq(name.ToString()),
+                                   TypedEq<StringPiece>(value.ToString()))))
+        .WillOnce(Return(mock_))
+        .RetiresOnSaturation();
+    return this;
+  }
+
+  virtual ObjectWriter* RenderNull(StringPiece name) {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty()))
+                  : EXPECT_CALL(*mock_, RenderNull(StrEq(name.ToString())))
+                        .WillOnce(Return(mock_))
+                        .RetiresOnSaturation());
+    return this;
+  }
+
+ private:
+  MockObjectWriter* mock_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.cc
new file mode 100644
index 0000000..f0e8fc8
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -0,0 +1,225 @@
+// 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.
+
+#include <google/protobuf/util/internal/field_mask_utility.h>
+
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+inline util::Status CallPathSink(PathSinkCallback path_sink,
+                                   StringPiece arg) {
+  return path_sink->Run(arg);
+}
+
+util::Status CreatePublicError(util::error::Code code,
+                                 const string& message) {
+  return util::Status(code, message);
+}
+
+// Appends a FieldMask path segment to a prefix.
+string AppendPathSegmentToPrefix(StringPiece prefix, StringPiece segment) {
+  if (prefix.empty()) {
+    return segment.ToString();
+  }
+  if (segment.empty()) {
+    return prefix.ToString();
+  }
+  // If the segment is a map key, appends it to the prefix without the ".".
+  if (segment.starts_with("[\"")) {
+    return StrCat(prefix, segment);
+  }
+  return StrCat(prefix, ".", segment);
+}
+
+}  // namespace
+
+string ConvertFieldMaskPath(const StringPiece path,
+                            ConverterCallback converter) {
+  string result;
+  result.reserve(path.size() << 1);
+
+  bool is_quoted = false;
+  bool is_escaping = false;
+  int current_segment_start = 0;
+
+  // Loops until 1 passed the end of the input to make handling the last
+  // segment easier.
+  for (size_t i = 0; i <= path.size(); ++i) {
+    // Outputs quoted string as-is.
+    if (is_quoted) {
+      if (i == path.size()) {
+        break;
+      }
+      result.push_back(path[i]);
+      if (is_escaping) {
+        is_escaping = false;
+      } else if (path[i] == '\\') {
+        is_escaping = true;
+      } else if (path[i] == '\"') {
+        current_segment_start = i + 1;
+        is_quoted = false;
+      }
+      continue;
+    }
+    if (i == path.size() || path[i] == '.' || path[i] == '(' ||
+        path[i] == ')' || path[i] == '\"') {
+      result += converter(
+          path.substr(current_segment_start, i - current_segment_start));
+      if (i < path.size()) {
+        result.push_back(path[i]);
+      }
+      current_segment_start = i + 1;
+    }
+    if (i < path.size() && path[i] == '\"') {
+      is_quoted = true;
+    }
+  }
+  return result;
+}
+
+util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
+                                           PathSinkCallback path_sink) {
+  stack<string> prefix;
+  int length = paths.length();
+  int previous_position = 0;
+  bool in_map_key = false;
+  bool is_escaping = false;
+  // Loops until 1 passed the end of the input to make the handle of the last
+  // segment easier.
+  for (int i = 0; i <= length; ++i) {
+    if (i != length) {
+      // Skips everything in a map key until we hit the end of it, which is
+      // marked by an un-escaped '"' immediately followed by a ']'.
+      if (in_map_key) {
+        if (is_escaping) {
+          is_escaping = false;
+          continue;
+        }
+        if (paths[i] == '\\') {
+          is_escaping = true;
+          continue;
+        }
+        if (paths[i] != '\"') {
+          continue;
+        }
+        // Un-escaped '"' must be followed with a ']'.
+        if (i >= length - 1 || paths[i + 1] != ']') {
+          return util::Status(
+              util::error::INVALID_ARGUMENT,
+              StrCat("Invalid FieldMask '", paths,
+                     "'. Map keys should be represented as [\"some_key\"]."));
+        }
+        // The end of the map key ("\"]") has been found.
+        in_map_key = false;
+        // Skips ']'.
+        i++;
+        // Checks whether the key ends at the end of a path segment.
+        if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
+            paths[i + 1] != ')' && paths[i + 1] != '(') {
+          return util::Status(
+              util::error::INVALID_ARGUMENT,
+              StrCat("Invalid FieldMask '", paths,
+                     "'. Map keys should be at the end of a path segment."));
+        }
+        is_escaping = false;
+        continue;
+      }
+
+      // We are not in a map key, look for the start of one.
+      if (paths[i] == '[') {
+        if (i >= length - 1 || paths[i + 1] != '\"') {
+          return util::Status(
+              util::error::INVALID_ARGUMENT,
+              StrCat("Invalid FieldMask '", paths,
+                     "'. Map keys should be represented as [\"some_key\"]."));
+        }
+        // "[\"" starts a map key.
+        in_map_key = true;
+        i++;  // Skips the '\"'.
+        continue;
+      }
+      // If the current character is not a special character (',', '(' or ')'),
+      // continue to the next.
+      if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') {
+        continue;
+      }
+    }
+    // Gets the current segment - sub-string between previous position (after
+    // '(', ')', ',', or the beginning of the input) and the current position.
+    StringPiece segment =
+        paths.substr(previous_position, i - previous_position);
+    string current_prefix = prefix.empty() ? "" : prefix.top();
+
+    if (i < length && paths[i] == '(') {
+      // Builds a prefix and save it into the stack.
+      prefix.push(AppendPathSegmentToPrefix(current_prefix, segment));
+    } else if (!segment.empty()) {
+      // When the current charactor is ')', ',' or the current position has
+      // passed the end of the input, builds and outputs a new paths by
+      // concatenating the last prefix with the current segment.
+      RETURN_IF_ERROR(CallPathSink(
+          path_sink, AppendPathSegmentToPrefix(current_prefix, segment)));
+    }
+
+    // Removes the last prefix after seeing a ')'.
+    if (i < length && paths[i] == ')') {
+      if (prefix.empty()) {
+        return util::Status(
+            util::error::INVALID_ARGUMENT,
+            StrCat("Invalid FieldMask '", paths,
+                   "'. Cannot find matching '(' for all ')'."));
+      }
+      prefix.pop();
+    }
+    previous_position = i + 1;
+  }
+  if (in_map_key) {
+    return util::Status(util::error::INVALID_ARGUMENT,
+                          StrCat("Invalid FieldMask '", paths,
+                                 "'. Cannot find matching ']' for all '['."));
+  }
+  if (!prefix.empty()) {
+    return util::Status(util::error::INVALID_ARGUMENT,
+                          StrCat("Invalid FieldMask '", paths,
+                                 "'. Cannot find matching ')' for all '('."));
+  }
+  return util::Status::OK;
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.h
new file mode 100644
index 0000000..59f36f7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/field_mask_utility.h
@@ -0,0 +1,72 @@
+// 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.
+
+// FieldMask related utility methods.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
+
+#include <functional>
+#include <stack>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+typedef string (*ConverterCallback)(StringPiece);
+typedef ResultCallback1<util::Status, StringPiece>* PathSinkCallback;
+
+// Applies a 'converter' to each segment of a FieldMask path and returns the
+// result. Quoted strings in the 'path' are copied to the output as-is without
+// converting their content. Escaping is supported within quoted strings.
+// For example, "ab\"_c" will be returned as "ab\"_c" without any changes.
+string ConvertFieldMaskPath(const StringPiece path,
+                            ConverterCallback converter);
+
+// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be
+// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results
+// will be sent to 'path_sink', i.e. 'path_sink' will be called once per
+// resulting path.
+// Note that we also support Apiary style FieldMask form. The above example in
+// the Apiary style will look like "a.b,a.c(d,e)".
+util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
+                                           PathSinkCallback path_sink);
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.cc
new file mode 100644
index 0000000..24bd554
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.cc
@@ -0,0 +1,404 @@
+// 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.
+
+#include <google/protobuf/util/internal/json_escaping.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+
+// Array of hex characters for conversion to hex.
+static const char kHex[] = "0123456789abcdef";
+
+// Characters 0x00 to 0x9f are very commonly used, so we provide a special
+// table lookup.
+//
+// For unicode code point ch < 0xa0:
+// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed;
+//                    or an empty string, if escaping is not needed.
+static const char kCommonEscapes[160][7] = {
+  // C0 (ASCII and derivatives) control characters
+  "\\u0000", "\\u0001", "\\u0002", "\\u0003",  // 0x00
+  "\\u0004", "\\u0005", "\\u0006", "\\u0007",
+  "\\b",     "\\t",     "\\n",     "\\u000b",
+  "\\f",     "\\r",     "\\u000e", "\\u000f",
+  "\\u0010", "\\u0011", "\\u0012", "\\u0013",  // 0x10
+  "\\u0014", "\\u0015", "\\u0016", "\\u0017",
+  "\\u0018", "\\u0019", "\\u001a", "\\u001b",
+  "\\u001c", "\\u001d", "\\u001e", "\\u001f",
+  // Escaping of " and \ are required by www.json.org string definition.
+  // Escaping of < and > are required for HTML security.
+  "", "", "\\\"", "", "",        "", "",        "",  // 0x20
+  "", "", "",     "", "",        "", "",        "",
+  "", "", "",     "", "",        "", "",        "",  // 0x30
+  "", "", "",     "", "\\u003c", "", "\\u003e", "",
+  "", "", "",     "", "",        "", "",        "",  // 0x40
+  "", "", "",     "", "",        "", "",        "",
+  "", "", "",     "", "",        "", "",        "",  // 0x50
+  "", "", "",     "", "\\\\",    "", "",        "",
+  "", "", "",     "", "",        "", "",        "",  // 0x60
+  "", "", "",     "", "",        "", "",        "",
+  "", "", "",     "", "",        "", "",        "",  // 0x70
+  "", "", "",     "", "",        "", "",        "\\u007f",
+  // C1 (ISO 8859 and Unicode) extended control characters
+  "\\u0080", "\\u0081", "\\u0082", "\\u0083",  // 0x80
+  "\\u0084", "\\u0085", "\\u0086", "\\u0087",
+  "\\u0088", "\\u0089", "\\u008a", "\\u008b",
+  "\\u008c", "\\u008d", "\\u008e", "\\u008f",
+  "\\u0090", "\\u0091", "\\u0092", "\\u0093",  // 0x90
+  "\\u0094", "\\u0095", "\\u0096", "\\u0097",
+  "\\u0098", "\\u0099", "\\u009a", "\\u009b",
+  "\\u009c", "\\u009d", "\\u009e", "\\u009f"
+};
+
+// Determines if the given char value is a unicode high-surrogate code unit.
+// Such values do not represent characters by themselves, but are used in the
+// representation of supplementary characters in the utf-16 encoding.
+inline bool IsHighSurrogate(uint16 c) {
+  // Optimized form of:
+  // return c >= kMinHighSurrogate && c <= kMaxHighSurrogate;
+  // (Reduced from 3 ALU instructions to 2 ALU instructions)
+  return (c & ~(JsonEscaping::kMaxHighSurrogate -
+                JsonEscaping::kMinHighSurrogate))
+      == JsonEscaping::kMinHighSurrogate;
+}
+
+// Determines if the given char value is a unicode low-surrogate code unit.
+// Such values do not represent characters by themselves, but are used in the
+// representation of supplementary characters in the utf-16 encoding.
+inline bool IsLowSurrogate(uint16 c) {
+  // Optimized form of:
+  // return c >= kMinLowSurrogate && c <= kMaxLowSurrogate;
+  // (Reduced from 3 ALU instructions to 2 ALU instructions)
+  return (c & ~(JsonEscaping::kMaxLowSurrogate -
+                JsonEscaping::kMinLowSurrogate))
+      == JsonEscaping::kMinLowSurrogate;
+}
+
+// Determines if the given char value is a unicode surrogate code unit (either
+// high-surrogate or low-surrogate).
+inline bool IsSurrogate(uint32 c) {
+  // Optimized form of:
+  // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
+  // (Reduced from 3 ALU instructions to 2 ALU instructions)
+  return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate;
+}
+
+// Returns true if the given unicode code point cp is
+// in the supplementary character range.
+inline bool IsSupplementalCodePoint(uint32 cp) {
+  // Optimized form of:
+  // return kMinSupplementaryCodePoint <= cp && cp <= kMaxCodePoint;
+  // (Reduced from 3 ALU instructions to 2 ALU instructions)
+  return (cp & ~(JsonEscaping::kMinSupplementaryCodePoint - 1))
+      < JsonEscaping::kMaxCodePoint;
+}
+
+// Returns true if the given unicode code point cp is a valid
+// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint).
+inline bool IsValidCodePoint(uint32 cp) {
+  return cp <= JsonEscaping::kMaxCodePoint;
+}
+
+// Converts the specified surrogate pair to its supplementary code point value.
+// It is the callers' responsibility to validate the specified surrogate pair.
+inline uint32 ToCodePoint(uint16 high, uint16 low) {
+  // Optimized form of:
+  // return ((high - kMinHighSurrogate) << 10)
+  //     + (low - kMinLowSurrogate)
+  //     + kMinSupplementaryCodePoint;
+  // (Reduced from 5 ALU instructions to 3 ALU instructions)
+  return (high << 10) + low +
+      (JsonEscaping::kMinSupplementaryCodePoint
+       - (static_cast<unsigned>(JsonEscaping::kMinHighSurrogate) << 10)
+       - JsonEscaping::kMinLowSurrogate);
+}
+
+// Returns the low surrogate for the given unicode code point. The result is
+// meaningless if the given code point is not a supplementary character.
+inline uint16 ToLowSurrogate(uint32 cp) {
+  return (cp & (JsonEscaping::kMaxLowSurrogate
+                - JsonEscaping::kMinLowSurrogate))
+      + JsonEscaping::kMinLowSurrogate;
+}
+
+// Returns the high surrogate for the given unicode code point. The result is
+// meaningless if the given code point is not a supplementary character.
+inline uint16 ToHighSurrogate(uint32 cp) {
+  return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
+                       (JsonEscaping::kMinSupplementaryCodePoint >> 10));
+}
+
+// Input str is encoded in UTF-8. A unicode code point could be encoded in
+// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple
+// reads of the ByteSource.
+//
+// This function reads the next unicode code point from the input (str) at
+// the given position (index), taking into account any left-over partial
+// code point from the previous iteration (cp), together with the number
+// of characters left to read to complete this code point (num_left).
+//
+// This function assumes that the input (str) is valid at the given position
+// (index). In order words, at least one character could be read successfully.
+//
+// The code point read (partial or complete) is stored in (cp). Upon return,
+// (num_left) stores the number of characters that has yet to be read in
+// order to complete the current unicode code point. If the read is complete,
+// then (num_left) is 0. Also, (num_read) is the number of characters read.
+//
+// Returns false if we encounter an invalid UTF-8 string. Returns true
+// otherwise, including the case when we reach the end of the input (str)
+// before a complete unicode code point is read.
+bool ReadCodePoint(StringPiece str, int index,
+                   uint32 *cp, int* num_left, int *num_read) {
+  if (*num_left == 0) {
+    // Last read was complete. Start reading a new unicode code point.
+    *cp = static_cast<uint8>(str[index++]);
+    *num_read = 1;
+    // The length of the code point is determined from reading the first byte.
+    //
+    // If the first byte is between:
+    //    0..0x7f: that's the value of the code point.
+    // 0x80..0xbf: <invalid>
+    // 0xc0..0xdf: 11-bit code point encoded in 2 bytes.
+    //                                   bit 10-6, bit 5-0
+    // 0xe0..0xef: 16-bit code point encoded in 3 bytes.
+    //                        bit 15-12, bit 11-6, bit 5-0
+    // 0xf0..0xf7: 21-bit code point encoded in 4 bytes.
+    //             bit 20-18, bit 17-12, bit 11-6, bit 5-0
+    // 0xf8..0xff: <invalid>
+    //
+    // Meaning of each bit:
+    // <msb> bit 7: 0 - single byte code point: bits 6-0 are values.
+    //              1 - multibyte code point
+    //       bit 6: 0 - subsequent bytes of multibyte code point:
+    //                  bits 5-0 are values.
+    //              1 - first byte of multibyte code point
+    //       bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values.
+    //              1 - first byte of code point with >= 3 bytes.
+    //       bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values.
+    //              1 - first byte of code point with >= 4 bytes.
+    //       bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values.
+    //              1 - reserved for future expansion.
+    if (*cp <= 0x7f) {
+      return true;
+    } else if (*cp <= 0xbf) {
+      return false;
+    } else if (*cp <= 0xdf) {
+      *cp &= 0x1f;
+      *num_left = 1;
+    } else if (*cp <= 0xef) {
+      *cp &= 0x0f;
+      *num_left = 2;
+    } else if (*cp <= 0xf7) {
+      *cp &= 0x07;
+      *num_left = 3;
+    } else {
+      return false;
+    }
+  } else {
+    // Last read was partial. Initialize num_read to 0 and continue reading
+    // the last unicode code point.
+    *num_read = 0;
+  }
+  while (*num_left > 0 && index < str.size()) {
+    uint32 ch = static_cast<uint8>(str[index++]);
+    --(*num_left);
+    ++(*num_read);
+    *cp = (*cp << 6) | (ch & 0x3f);
+    if (ch < 0x80 || ch > 0xbf) return false;
+  }
+  return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp));
+}
+
+// Stores the 16-bit unicode code point as its hexadecimal digits in buffer
+// and returns a StringPiece that points to this buffer. The input buffer needs
+// to be at least 6 bytes long.
+StringPiece ToHex(uint16 cp, char* buffer) {
+  buffer[5] = kHex[cp & 0x0f];
+  cp >>= 4;
+  buffer[4] = kHex[cp & 0x0f];
+  cp >>= 4;
+  buffer[3] = kHex[cp & 0x0f];
+  cp >>= 4;
+  buffer[2] = kHex[cp & 0x0f];
+  return StringPiece(buffer, 0, 6);
+}
+
+// Stores the 32-bit unicode code point as its hexadecimal digits in buffer
+// and returns a StringPiece that points to this buffer. The input buffer needs
+// to be at least 12 bytes long.
+StringPiece ToSurrogateHex(uint32 cp, char* buffer) {
+  uint16 low = ToLowSurrogate(cp);
+  uint16 high = ToHighSurrogate(cp);
+
+  buffer[11] = kHex[low & 0x0f];
+  low >>= 4;
+  buffer[10] = kHex[low & 0x0f];
+  low >>= 4;
+  buffer[9] = kHex[low & 0x0f];
+  low >>= 4;
+  buffer[8] = kHex[low & 0x0f];
+
+  buffer[5] = kHex[high & 0x0f];
+  high >>= 4;
+  buffer[4] = kHex[high & 0x0f];
+  high >>= 4;
+  buffer[3] = kHex[high & 0x0f];
+  high >>= 4;
+  buffer[2] = kHex[high & 0x0f];
+
+  return StringPiece(buffer, 12);
+}
+
+// If the given unicode code point needs escaping, then returns the
+// escaped form. The returned StringPiece either points to statically
+// pre-allocated char[] or to the given buffer. The input buffer needs
+// to be at least 12 bytes long.
+//
+// If the given unicode code point does not need escaping, an empty
+// StringPiece is returned.
+StringPiece EscapeCodePoint(uint32 cp, char* buffer) {
+  if (cp < 0xa0) return kCommonEscapes[cp];
+  switch (cp) {
+    // These are not required by json spec
+    // but used to prevent security bugs in javascript.
+    case 0xfeff:  // Zero width no-break space
+    case 0xfff9:  // Interlinear annotation anchor
+    case 0xfffa:  // Interlinear annotation separator
+    case 0xfffb:  // Interlinear annotation terminator
+
+    case 0x00ad:  // Soft-hyphen
+    case 0x06dd:  // Arabic end of ayah
+    case 0x070f:  // Syriac abbreviation mark
+    case 0x17b4:  // Khmer vowel inherent Aq
+    case 0x17b5:  // Khmer vowel inherent Aa
+      return ToHex(cp, buffer);
+
+    default:
+      if ((cp >= 0x0600 && cp <= 0x0603) ||  // Arabic signs
+          (cp >= 0x200b && cp <= 0x200f) ||  // Zero width etc.
+          (cp >= 0x2028 && cp <= 0x202e) ||  // Separators etc.
+          (cp >= 0x2060 && cp <= 0x2064) ||  // Invisible etc.
+          (cp >= 0x206a && cp <= 0x206f)) {  // Shaping etc.
+        return ToHex(cp, buffer);
+      }
+
+      if (cp == 0x000e0001 ||                        // Language tag
+          (cp >= 0x0001d173 && cp <= 0x0001d17a) ||  // Music formatting
+          (cp >= 0x000e0020 && cp <= 0x000e007f)) {  // TAG symbols
+        return ToSurrogateHex(cp, buffer);
+      }
+  }
+  return StringPiece();
+}
+
+// Tries to escape the given code point first. If the given code point
+// does not need to be escaped, but force_output is true, then render
+// the given multi-byte code point in UTF8 in the buffer and returns it.
+StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) {
+  StringPiece sp = EscapeCodePoint(cp, buffer);
+  if (force_output && sp.empty()) {
+    buffer[5] = (cp & 0x3f) | 0x80;
+    cp >>= 6;
+    if (cp <= 0x1f) {
+      buffer[4] = cp | 0xc0;
+      sp.set(buffer + 4, 2);
+      return sp;
+    }
+    buffer[4] = (cp & 0x3f) | 0x80;
+    cp >>= 6;
+    if (cp <= 0x0f) {
+      buffer[3] = cp | 0xe0;
+      sp.set(buffer + 3, 3);
+      return sp;
+    }
+    buffer[3] = (cp & 0x3f) | 0x80;
+    buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
+    sp.set(buffer + 2, 4);
+  }
+  return sp;
+}
+
+}  // namespace
+
+void JsonEscaping::Escape(strings::ByteSource* input,
+                          strings::ByteSink* output) {
+  char buffer[12] = "\\udead\\ubee";
+  uint32 cp = 0;     // Current unicode code point.
+  int num_left = 0;  // Num of chars to read to complete the code point.
+  while (input->Available() > 0) {
+    StringPiece str = input->Peek();
+    StringPiece escaped;
+    int i = 0;
+    int num_read;
+    bool ok;
+    bool cp_was_split = num_left > 0;
+    // Loop until we encounter either
+    //   i) a code point that needs to be escaped; or
+    //  ii) a split code point is completely read; or
+    // iii) a character that is not a valid utf8; or
+    //  iv) end of the StringPiece str is reached.
+    do {
+      ok = ReadCodePoint(str, i, &cp, &num_left, &num_read);
+      if (num_left > 0 || !ok) break;  // case iii or iv
+      escaped = EscapeCodePoint(cp, buffer, cp_was_split);
+      if (!escaped.empty()) break;     // case i or ii
+      i += num_read;
+      num_read = 0;
+    } while (i < str.length());        // case iv
+    // First copy the un-escaped prefix, if any, to the output ByteSink.
+    if (i > 0) input->CopyTo(output, i);
+    if (num_read > 0) input->Skip(num_read);
+    if (!ok) {
+      // Case iii: Report error.
+      // TODO(wpoon): Add error reporting.
+      num_left = 0;
+    } else if (num_left == 0 && !escaped.empty()) {
+      // Case i or ii: Append the escaped code point to the output ByteSink.
+      output->Append(escaped.data(), escaped.size());
+    }
+  }
+  if (num_left > 0) {
+    // Treat as case iii: report error.
+    // TODO(wpoon): Add error reporting.
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.h
new file mode 100644
index 0000000..e3e329f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_escaping.h
@@ -0,0 +1,91 @@
+// 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 NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+#define NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class JsonEscaping {
+ public:
+  // The minimum value of a unicode high-surrogate code unit in the utf-16
+  // encoding. A high-surrogate is also known as a leading-surrogate.
+  // See http://www.unicode.org/glossary/#high_surrogate_code_unit
+  static const uint16 kMinHighSurrogate = 0xd800;
+
+  // The maximum value of a unicide high-surrogate code unit in the utf-16
+  // encoding. A high-surrogate is also known as a leading-surrogate.
+  // See http://www.unicode.org/glossary/#high_surrogate_code_unit
+  static const uint16 kMaxHighSurrogate = 0xdbff;
+
+  // The minimum value of a unicode low-surrogate code unit in the utf-16
+  // encoding. A low-surrogate is also known as a trailing-surrogate.
+  // See http://www.unicode.org/glossary/#low_surrogate_code_unit
+  static const uint16 kMinLowSurrogate = 0xdc00;
+
+  // The maximum value of a unicode low-surrogate code unit in the utf-16
+  // encoding. A low-surrogate is also known as a trailing surrogate.
+  // See http://www.unicode.org/glossary/#low_surrogate_code_unit
+  static const uint16 kMaxLowSurrogate = 0xdfff;
+
+  // The minimum value of a unicode supplementary code point.
+  // See http://www.unicode.org/glossary/#supplementary_code_point
+  static const uint32 kMinSupplementaryCodePoint = 0x010000;
+
+  // The minimum value of a unicode code point.
+  // See http://www.unicode.org/glossary/#code_point
+  static const uint32 kMinCodePoint = 0x000000;
+
+  // The maximum value of a unicode code point.
+  // See http://www.unicode.org/glossary/#code_point
+  static const uint32 kMaxCodePoint = 0x10ffff;
+
+  JsonEscaping() {}
+  virtual ~JsonEscaping() {}
+
+  // Escape the given ByteSource to the given ByteSink.
+  static void Escape(strings::ByteSource* input, strings::ByteSink* output);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+#endif  // NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.cc
new file mode 100644
index 0000000..b84210c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -0,0 +1,183 @@
+// 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.
+
+#include <google/protobuf/util/internal/json_objectwriter.h>
+
+#include <math.h>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using strings::ArrayByteSource;
+;
+
+JsonObjectWriter::~JsonObjectWriter() {
+  if (!element_->is_root()) {
+    GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed.";
+  }
+}
+
+JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) {
+  WritePrefix(name);
+  WriteChar('{');
+  Push();
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::EndObject() {
+  Pop();
+  WriteChar('}');
+  if (element()->is_root()) NewLine();
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) {
+  WritePrefix(name);
+  WriteChar('[');
+  Push();
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::EndList() {
+  Pop();
+  WriteChar(']');
+  if (element()->is_root()) NewLine();
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, bool value) {
+  return RenderSimple(name, value ? "true" : "false");
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, int32 value) {
+  return RenderSimple(name, SimpleItoa(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
+                                                 uint32 value) {
+  return RenderSimple(name, SimpleItoa(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, int64 value) {
+  WritePrefix(name);
+  WriteChar('"');
+  stream_->WriteString(SimpleItoa(value));
+  WriteChar('"');
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
+                                                 uint64 value) {
+  WritePrefix(name);
+  WriteChar('"');
+  stream_->WriteString(SimpleItoa(value));
+  WriteChar('"');
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
+                                                 double value) {
+  if (MathLimits<double>::IsFinite(value)) {
+    return RenderSimple(name, SimpleDtoa(value));
+  }
+
+  // Render quoted with NaN/Infinity-aware DoubleAsString.
+  return RenderString(name, DoubleAsString(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) {
+  if (MathLimits<float>::IsFinite(value)) {
+    return RenderSimple(name, SimpleFtoa(value));
+  }
+
+  // Render quoted with NaN/Infinity-aware FloatAsString.
+  return RenderString(name, FloatAsString(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name,
+                                                 StringPiece value) {
+  WritePrefix(name);
+  WriteChar('"');
+  ArrayByteSource source(value);
+  JsonEscaping::Escape(&source, &sink_);
+  WriteChar('"');
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
+                                                StringPiece value) {
+  WritePrefix(name);
+  string base64;
+
+  if (use_websafe_base64_for_bytes_)
+    WebSafeBase64Escape(value.ToString(), &base64);
+  else
+    Base64Escape(value, &base64);
+
+  WriteChar('"');
+  // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
+  //              directly to the stream, rather than first putting them
+  //              into a string and then writing them to the stream.
+  stream_->WriteRaw(base64.data(), base64.size());
+  WriteChar('"');
+  return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) {
+  return RenderSimple(name, "null");
+}
+
+void JsonObjectWriter::WritePrefix(StringPiece name) {
+  bool not_first = !element()->is_first();
+  if (not_first) WriteChar(',');
+  if (not_first || !element()->is_root()) NewLine();
+  if (!name.empty()) {
+    WriteChar('"');
+    ArrayByteSource source(name);
+    JsonEscaping::Escape(&source, &sink_);
+    stream_->WriteString("\":");
+    if (!indent_string_.empty()) WriteChar(' ');
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.h
new file mode 100644
index 0000000..cb7e2fb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter.h
@@ -0,0 +1,215 @@
+// 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_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/util/internal/structured_objectwriter.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An ObjectWriter implementation that outputs JSON. This ObjectWriter
+// supports writing a compact form or a pretty printed form.
+//
+// Sample usage:
+//   string output;
+//   StringOutputStream* str_stream = new StringOutputStream(&output);
+//   CodedOutputStream* out_stream = new CodedOutputStream(str_stream);
+//   JsonObjectWriter* ow = new JsonObjectWriter("  ", out_stream);
+//   ow->StartObject("")
+//       ->RenderString("name", "value")
+//       ->RenderString("emptystring", string())
+//       ->StartObject("nested")
+//         ->RenderInt64("light", 299792458);
+//         ->RenderDouble("pi", 3.141592653589793);
+//       ->EndObject()
+//       ->StartList("empty")
+//       ->EndList()
+//     ->EndObject();
+//
+// And then the output string would become:
+// {
+//   "name": "value",
+//   "emptystring": "",
+//   "nested": {
+//     "light": "299792458",
+//     "pi": 3.141592653589793
+//   },
+//   "empty": []
+// }
+//
+// JsonObjectWriter does not validate if calls actually result in valid JSON.
+// For example, passing an empty name when one would be required won't result
+// in an error, just an invalid output.
+//
+// Note that all int64 and uint64 are rendered as strings instead of numbers.
+// This is because JavaScript parses numbers as 64-bit float thus int64 and
+// uint64 would lose precision if rendered as numbers.
+//
+// JsonObjectWriter is thread-unsafe.
+class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
+ public:
+  JsonObjectWriter(StringPiece indent_string,
+                   google::protobuf::io::CodedOutputStream* out)
+      : element_(new Element(NULL)),
+        stream_(out),
+        sink_(out),
+        indent_string_(indent_string.ToString()),
+        use_websafe_base64_for_bytes_(false) {}
+  virtual ~JsonObjectWriter();
+
+  // ObjectWriter methods.
+  virtual JsonObjectWriter* StartObject(StringPiece name);
+  virtual JsonObjectWriter* EndObject();
+  virtual JsonObjectWriter* StartList(StringPiece name);
+  virtual JsonObjectWriter* EndList();
+  virtual JsonObjectWriter* RenderBool(StringPiece name, bool value);
+  virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value);
+  virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value);
+  virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value);
+  virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value);
+  virtual JsonObjectWriter* RenderDouble(StringPiece name, double value);
+  virtual JsonObjectWriter* RenderFloat(StringPiece name, float value);
+  virtual JsonObjectWriter* RenderString(StringPiece name, StringPiece value);
+  virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value);
+  virtual JsonObjectWriter* RenderNull(StringPiece name);
+
+  void set_use_websafe_base64_for_bytes(bool value) {
+    use_websafe_base64_for_bytes_ = value;
+  }
+
+ protected:
+  class LIBPROTOBUF_EXPORT Element : public BaseElement {
+   public:
+    explicit Element(Element* parent) : BaseElement(parent), is_first_(true) {}
+
+    // Called before each field of the Element is to be processed.
+    // Returns true if this is the first call (processing the first field).
+    bool is_first() {
+      if (is_first_) {
+        is_first_ = false;
+        return true;
+      }
+      return false;
+    }
+
+   private:
+    bool is_first_;
+
+    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element);
+  };
+
+  virtual Element* element() { return element_.get(); }
+
+ private:
+  class LIBPROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink {
+   public:
+    explicit ByteSinkWrapper(google::protobuf::io::CodedOutputStream* stream)
+        : stream_(stream) {}
+    virtual ~ByteSinkWrapper() {}
+
+    // ByteSink methods.
+    virtual void Append(const char* bytes, size_t n) {
+      stream_->WriteRaw(bytes, n);
+    }
+
+   private:
+    google::protobuf::io::CodedOutputStream* stream_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper);
+  };
+
+  // Renders a simple value as a string. By default all non-string Render
+  // methods convert their argument to a string and call this method. This
+  // method can then be used to render the simple value without escaping it.
+  JsonObjectWriter* RenderSimple(StringPiece name, const string& value) {
+    WritePrefix(name);
+    stream_->WriteString(value);
+    return this;
+  }
+
+  // Pushes a new element to the stack.
+  void Push() { element_.reset(new Element(element_.release())); }
+
+  // Pops an element off of the stack and deletes the popped element.
+  void Pop() {
+    bool needs_newline = !element_->is_first();
+    element_.reset(element_->pop<Element>());
+    if (needs_newline) NewLine();
+  }
+
+  // If pretty printing is enabled, this will write a newline to the output,
+  // followed by optional indentation. Otherwise this method is a noop.
+  void NewLine() {
+    if (!indent_string_.empty()) {
+      WriteChar('\n');
+      for (int i = 0; i < element()->level(); i++) {
+        stream_->WriteString(indent_string_);
+      }
+    }
+  }
+
+  // Writes a prefix. This will write out any pretty printing and
+  // commas that are required, followed by the name and a ':' if
+  // the name is not null.
+  void WritePrefix(StringPiece name);
+
+  // Writes an individual character to the output.
+  void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); }
+
+  google::protobuf::scoped_ptr<Element> element_;
+  google::protobuf::io::CodedOutputStream* stream_;
+  ByteSinkWrapper sink_;
+  const string indent_string_;
+
+  // Whether to use regular or websafe base64 encoding for byte fields. Defaults
+  // to regular base64 encoding.
+  bool use_websafe_base64_for_bytes_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter_test.cc
new file mode 100644
index 0000000..b87b06a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -0,0 +1,313 @@
+// 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.
+
+#include <google/protobuf/util/internal/json_objectwriter.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::io::CodedOutputStream;
+using google::protobuf::io::StringOutputStream;
+
+class JsonObjectWriterTest : public ::testing::Test {
+ protected:
+  JsonObjectWriterTest()
+      : str_stream_(new StringOutputStream(&output_)),
+        out_stream_(new CodedOutputStream(str_stream_)),
+        ow_(NULL) {}
+
+  virtual ~JsonObjectWriterTest() {
+    delete ow_;
+    delete out_stream_;
+    delete str_stream_;
+  }
+
+  string output_;
+  StringOutputStream* const str_stream_;
+  CodedOutputStream* const out_stream_;
+  JsonObjectWriter* ow_;
+};
+
+TEST_F(JsonObjectWriterTest, EmptyRootObject) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")->EndObject();
+  EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyObject) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderString("test", "value")
+      ->StartObject("empty")
+      ->EndObject()
+      ->EndObject();
+  EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyRootList) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartList("")->EndList();
+  EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyList) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderString("test", "value")
+      ->StartList("empty")
+      ->EndList()
+      ->EndObject();
+  EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ObjectInObject) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->StartObject("nested")
+      ->RenderString("field", "value")
+      ->EndObject()
+      ->EndObject();
+  EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ListInObject) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->StartList("nested")
+      ->RenderString("", "value")
+      ->EndList()
+      ->EndObject();
+  EXPECT_EQ("{\"nested\":[\"value\"]}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ObjectInList) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartList("")
+      ->StartObject("")
+      ->RenderString("field", "value")
+      ->EndObject()
+      ->EndList();
+  EXPECT_EQ("[{\"field\":\"value\"}]",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ListInList) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartList("")
+      ->StartList("")
+      ->RenderString("", "value")
+      ->EndList()
+      ->EndList();
+  EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, RenderPrimitives) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderBool("bool", true)
+      ->RenderDouble("double", std::numeric_limits<double>::max())
+      ->RenderFloat("float", std::numeric_limits<float>::max())
+      ->RenderInt32("int", std::numeric_limits<int32>::min())
+      ->RenderInt64("long", std::numeric_limits<int64>::min())
+      ->RenderBytes("bytes", "abracadabra")
+      ->RenderString("string", "string")
+      ->RenderBytes("emptybytes", "")
+      ->RenderString("emptystring", string())
+      ->EndObject();
+  EXPECT_EQ(
+      "{\"bool\":true,"
+      "\"double\":" +
+          ValueAsString<double>(std::numeric_limits<double>::max()) +
+          ","
+          "\"float\":" +
+          ValueAsString<float>(std::numeric_limits<float>::max()) +
+          ","
+          "\"int\":-2147483648,"
+          "\"long\":\"-9223372036854775808\","
+          "\"bytes\":\"YWJyYWNhZGFicmE=\","
+          "\"string\":\"string\","
+          "\"emptybytes\":\"\","
+          "\"emptystring\":\"\"}",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) {
+  string s;
+  s.push_back('\377');
+  s.push_back('\357');
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
+  // Non-web-safe would encode this as "/+8="
+  EXPECT_EQ("{\"bytes\":\"/+8=\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintList) {
+  ow_ = new JsonObjectWriter(" ", out_stream_);
+  ow_->StartObject("")
+      ->StartList("items")
+      ->RenderString("", "item1")
+      ->RenderString("", "item2")
+      ->RenderString("", "item3")
+      ->EndList()
+      ->StartList("empty")
+      ->EndList()
+      ->EndObject();
+  EXPECT_EQ(
+      "{\n"
+      " \"items\": [\n"
+      "  \"item1\",\n"
+      "  \"item2\",\n"
+      "  \"item3\"\n"
+      " ],\n"
+      " \"empty\": []\n"
+      "}\n",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
+  ow_ = new JsonObjectWriter(" ", out_stream_);
+  ow_->StartObject("")
+      ->StartObject("items")
+      ->RenderString("key1", "item1")
+      ->RenderString("key2", "item2")
+      ->RenderString("key3", "item3")
+      ->EndObject()
+      ->StartObject("empty")
+      ->EndObject()
+      ->EndObject();
+  EXPECT_EQ(
+      "{\n"
+      " \"items\": {\n"
+      "  \"key1\": \"item1\",\n"
+      "  \"key2\": \"item2\",\n"
+      "  \"key3\": \"item3\"\n"
+      " },\n"
+      " \"empty\": {}\n"
+      "}\n",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
+  ow_ = new JsonObjectWriter(" ", out_stream_);
+  ow_->StartObject("")
+      ->StartList("list")
+      ->StartObject("")
+      ->EndObject()
+      ->EndList()
+      ->EndObject();
+  EXPECT_EQ(
+      "{\n"
+      " \"list\": [\n"
+      "  {}\n"
+      " ]\n"
+      "}\n",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
+  ow_ = new JsonObjectWriter("  ", out_stream_);
+  ow_->StartObject("")
+      ->RenderBool("bool", true)
+      ->RenderInt32("int", 42)
+      ->EndObject();
+  EXPECT_EQ(
+      "{\n"
+      "  \"bool\": true,\n"
+      "  \"int\": 42\n"
+      "}\n",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
+  EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, Stringification) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
+      ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
+      ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
+      ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
+      ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
+      ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
+      ->EndObject();
+  EXPECT_EQ(
+      "{\"double_nan\":\"NaN\","
+      "\"float_nan\":\"NaN\","
+      "\"double_pos\":\"Infinity\","
+      "\"float_pos\":\"Infinity\","
+      "\"double_neg\":\"-Infinity\","
+      "\"float_neg\":\"-Infinity\"}",
+      output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, TestRegularByteEncoding) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderBytes("bytes", "\x03\xef\xc0")
+      ->EndObject();
+
+  // Test that we get regular (non websafe) base64 encoding on byte fields by
+  // default.
+  EXPECT_EQ("{\"bytes\":\"A+/A\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, TestWebsafeByteEncoding) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->set_use_websafe_base64_for_bytes(true);
+  ow_->StartObject("")
+      ->RenderBytes("bytes", "\x03\xef\xc0")
+      ->EndObject();
+
+  // Test that we get websafe base64 encoding when explicitly asked.
+  EXPECT_EQ("{\"bytes\":\"A-_A\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.cc
new file mode 100644
index 0000000..39be7b0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -0,0 +1,820 @@
+// 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.
+
+#include <google/protobuf/util/internal/json_stream_parser.h>
+
+#include <algorithm>
+#include <cctype>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+// Allow these symbols to be referenced as util::Status, util::error::* in
+// this file.
+using util::Status;
+namespace error {
+using util::error::INTERNAL;
+using util::error::INVALID_ARGUMENT;
+}  // namespace error
+
+namespace converter {
+
+// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
+static const int kUnicodeEscapedLength = 6;
+
+// Length of the true, false, and null literals.
+static const int true_len = strlen("true");
+static const int false_len = strlen("false");
+static const int null_len = strlen("null");
+
+inline bool IsLetter(char c) {
+  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') ||
+         (c == '$');
+}
+
+inline bool IsAlphanumeric(char c) {
+  return IsLetter(c) || ('0' <= c && c <= '9');
+}
+
+static bool ConsumeKey(StringPiece* input, StringPiece* key) {
+  if (input->empty() || !IsLetter((*input)[0])) return false;
+  int len = 1;
+  for (; len < input->size(); ++len) {
+    if (!IsAlphanumeric((*input)[len])) {
+      break;
+    }
+  }
+  *key = StringPiece(input->data(), len);
+  *input = StringPiece(input->data() + len, input->size() - len);
+  return true;
+}
+
+static bool MatchKey(StringPiece input) {
+  return !input.empty() && IsLetter(input[0]);
+}
+
+JsonStreamParser::JsonStreamParser(ObjectWriter* ow)
+    : ow_(ow),
+      stack_(),
+      leftover_(),
+      json_(),
+      p_(),
+      key_(),
+      key_storage_(),
+      finishing_(false),
+      parsed_(),
+      parsed_storage_(),
+      string_open_(0),
+      chunk_storage_(),
+      coerce_to_utf8_(false) {
+  // Initialize the stack with a single value to be parsed.
+  stack_.push(VALUE);
+}
+
+JsonStreamParser::~JsonStreamParser() {}
+
+
+util::Status JsonStreamParser::Parse(StringPiece json) {
+  StringPiece chunk = json;
+  // If we have leftovers from a previous chunk, append the new chunk to it
+  // and create a new StringPiece pointing at the string's data. This could
+  // be large but we rely on the chunks to be small, assuming they are
+  // fragments of a Cord.
+  if (!leftover_.empty()) {
+    // Don't point chunk to leftover_ because leftover_ will be updated in
+    // ParseChunk(chunk).
+    chunk_storage_.swap(leftover_);
+    json.AppendToString(&chunk_storage_);
+    chunk = StringPiece(chunk_storage_);
+  }
+
+  // Find the structurally valid UTF8 prefix and parse only that.
+  int n = internal::UTF8SpnStructurallyValid(chunk);
+  if (n > 0) {
+    util::Status status = ParseChunk(chunk.substr(0, n));
+
+    // Any leftover characters are stashed in leftover_ for later parsing when
+    // there is more data available.
+    chunk.substr(n).AppendToString(&leftover_);
+    return status;
+  } else {
+    chunk.CopyToString(&leftover_);
+    return util::Status::OK;
+  }
+}
+
+util::Status JsonStreamParser::FinishParse() {
+  // If we do not expect anything and there is nothing left to parse we're all
+  // done.
+  if (stack_.empty() && leftover_.empty()) {
+    return util::Status::OK;
+  }
+
+  // Storage for UTF8-coerced string.
+  google::protobuf::scoped_array<char> utf8;
+  if (coerce_to_utf8_) {
+    utf8.reset(new char[leftover_.size()]);
+    char* coerced = internal::UTF8CoerceToStructurallyValid(leftover_, utf8.get(), ' ');
+    p_ = json_ = StringPiece(coerced, leftover_.size());
+  } else {
+    p_ = json_ = leftover_;
+    if (!internal::IsStructurallyValidUTF8(leftover_)) {
+      return ReportFailure("Encountered non UTF-8 code points.");
+    }
+  }
+
+  // Parse the remainder in finishing mode, which reports errors for things like
+  // unterminated strings or unknown tokens that would normally be retried.
+  finishing_ = true;
+  util::Status result = RunParser();
+  if (result.ok()) {
+    SkipWhitespace();
+    if (!p_.empty()) {
+      result = ReportFailure("Parsing terminated before end of input.");
+    }
+  }
+  return result;
+}
+
+util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
+  // Do not do any work if the chunk is empty.
+  if (chunk.empty()) return util::Status::OK;
+
+  p_ = json_ = chunk;
+
+  finishing_ = false;
+  util::Status result = RunParser();
+  if (!result.ok()) return result;
+
+  SkipWhitespace();
+  if (p_.empty()) {
+    // If we parsed everything we had, clear the leftover.
+    leftover_.clear();
+  } else {
+    // If we do not expect anything i.e. stack is empty, and we have non-empty
+    // string left to parse, we report an error.
+    if (stack_.empty()) {
+      return ReportFailure("Parsing terminated before end of input.");
+    }
+    // If we expect future data i.e. stack is non-empty, and we have some
+    // unparsed data left, we save it for later parse.
+    leftover_ = p_.ToString();
+  }
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::RunParser() {
+  while (!stack_.empty()) {
+    ParseType type = stack_.top();
+    TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING;
+    stack_.pop();
+    util::Status result;
+    switch (type) {
+      case VALUE:
+        result = ParseValue(t);
+        break;
+
+      case OBJ_MID:
+        result = ParseObjectMid(t);
+        break;
+
+      case ENTRY:
+        result = ParseEntry(t);
+        break;
+
+      case ENTRY_MID:
+        result = ParseEntryMid(t);
+        break;
+
+      case ARRAY_VALUE:
+        result = ParseArrayValue(t);
+        break;
+
+      case ARRAY_MID:
+        result = ParseArrayMid(t);
+        break;
+
+      default:
+        result = util::Status(util::error::INTERNAL,
+                              StrCat("Unknown parse type: ", type));
+        break;
+    }
+    if (!result.ok()) {
+      // If we were cancelled, save our state and try again later.
+      if (!finishing_ && result == util::Status::CANCELLED) {
+        stack_.push(type);
+        // If we have a key we still need to render, make sure to save off the
+        // contents in our own storage.
+        if (!key_.empty() && key_storage_.empty()) {
+          key_.AppendToString(&key_storage_);
+          key_ = StringPiece(key_storage_);
+        }
+        result = util::Status::OK;
+      }
+      return result;
+    }
+  }
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseValue(TokenType type) {
+  switch (type) {
+    case BEGIN_OBJECT:
+      return HandleBeginObject();
+    case BEGIN_ARRAY:
+      return HandleBeginArray();
+    case BEGIN_STRING:
+      return ParseString();
+    case BEGIN_NUMBER:
+      return ParseNumber();
+    case BEGIN_TRUE:
+      return ParseTrue();
+    case BEGIN_FALSE:
+      return ParseFalse();
+    case BEGIN_NULL:
+      return ParseNull();
+    case UNKNOWN:
+      return ReportUnknown("Expected a value.");
+    default: {
+      // Special case for having been cut off while parsing, wait for more data.
+      // This handles things like 'fals' being at the end of the string, we
+      // don't know if the next char would be e, completing it, or something
+      // else, making it invalid.
+      if (!finishing_ && p_.length() < false_len) {
+        return util::Status::CANCELLED;
+      }
+      return ReportFailure("Unexpected token.");
+    }
+  }
+}
+
+util::Status JsonStreamParser::ParseString() {
+  util::Status result = ParseStringHelper();
+  if (result.ok()) {
+    ow_->RenderString(key_, parsed_);
+    key_.clear();
+    parsed_.clear();
+    parsed_storage_.clear();
+  }
+  return result;
+}
+
+util::Status JsonStreamParser::ParseStringHelper() {
+  // If we haven't seen the start quote, grab it and remember it for later.
+  if (string_open_ == 0) {
+    string_open_ = *p_.data();
+    GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\'');
+    Advance();
+  }
+  // Track where we last copied data from so we can minimize copying.
+  const char* last = p_.data();
+  while (!p_.empty()) {
+    const char* data = p_.data();
+    if (*data == '\\') {
+      // We're about to handle an escape, copy all bytes from last to data.
+      if (last < data) {
+        parsed_storage_.append(last, data - last);
+        last = data;
+      }
+      // If we ran out of string after the \, cancel or report an error
+      // depending on if we expect more data later.
+      if (p_.length() == 1) {
+        if (!finishing_) {
+          return util::Status::CANCELLED;
+        }
+        return ReportFailure("Closing quote expected in string.");
+      }
+      // Parse a unicode escape if we found \u in the string.
+      if (data[1] == 'u') {
+        util::Status result = ParseUnicodeEscape();
+        if (!result.ok()) {
+          return result;
+        }
+        // Move last pointer past the unicode escape and continue.
+        last = p_.data();
+        continue;
+      }
+      // Handle the standard set of backslash-escaped characters.
+      switch (data[1]) {
+        case 'b':
+          parsed_storage_.push_back('\b');
+          break;
+        case 'f':
+          parsed_storage_.push_back('\f');
+          break;
+        case 'n':
+          parsed_storage_.push_back('\n');
+          break;
+        case 'r':
+          parsed_storage_.push_back('\r');
+          break;
+        case 't':
+          parsed_storage_.push_back('\t');
+          break;
+        case 'v':
+          parsed_storage_.push_back('\v');
+          break;
+        default:
+          parsed_storage_.push_back(data[1]);
+      }
+      // We handled two characters, so advance past them and continue.
+      p_.remove_prefix(2);
+      last = p_.data();
+      continue;
+    }
+    // If we found the closing quote note it, advance past it, and return.
+    if (*data == string_open_) {
+      // If we didn't copy anything, reuse the input buffer.
+      if (parsed_storage_.empty()) {
+        parsed_ = StringPiece(last, data - last);
+      } else {
+        if (last < data) {
+          parsed_storage_.append(last, data - last);
+          last = data;
+        }
+        parsed_ = StringPiece(parsed_storage_);
+      }
+      // Clear the quote char so next time we try to parse a string we'll
+      // start fresh.
+      string_open_ = 0;
+      Advance();
+      return util::Status::OK;
+    }
+    // Normal character, just advance past it.
+    Advance();
+  }
+  // If we ran out of characters, copy over what we have so far.
+  if (last < p_.data()) {
+    parsed_storage_.append(last, p_.data() - last);
+  }
+  // If we didn't find the closing quote but we expect more data, cancel for now
+  if (!finishing_) {
+    return util::Status::CANCELLED;
+  }
+  // End of string reached without a closing quote, report an error.
+  string_open_ = 0;
+  return ReportFailure("Closing quote expected in string.");
+}
+
+// Converts a unicode escaped character to a decimal value stored in a char32
+// for use in UTF8 encoding utility.  We assume that str begins with \uhhhh and
+// convert that from the hex number to a decimal value.
+//
+// There are some security exploits with UTF-8 that we should be careful of:
+//   - http://www.unicode.org/reports/tr36/#UTF-8_Exploit
+//   - http://sites/intl-eng/design-guide/core-application
+util::Status JsonStreamParser::ParseUnicodeEscape() {
+  if (p_.length() < kUnicodeEscapedLength) {
+    if (!finishing_) {
+      return util::Status::CANCELLED;
+    }
+    return ReportFailure("Illegal hex string.");
+  }
+  GOOGLE_DCHECK_EQ('\\', p_.data()[0]);
+  GOOGLE_DCHECK_EQ('u', p_.data()[1]);
+  uint32 code = 0;
+  for (int i = 2; i < kUnicodeEscapedLength; ++i) {
+    if (!isxdigit(p_.data()[i])) {
+      return ReportFailure("Invalid escape sequence.");
+    }
+    code = (code << 4) + hex_digit_to_int(p_.data()[i]);
+  }
+  if (code >= JsonEscaping::kMinHighSurrogate &&
+      code <= JsonEscaping::kMaxHighSurrogate) {
+    if (p_.length() < 2 * kUnicodeEscapedLength) {
+      if (!finishing_) {
+        return util::Status::CANCELLED;
+      }
+      if (!coerce_to_utf8_) {
+        return ReportFailure("Missing low surrogate.");
+      }
+    } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
+               p_.data()[kUnicodeEscapedLength + 1] == 'u') {
+      uint32 low_code = 0;
+      for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
+           ++i) {
+        if (!isxdigit(p_.data()[i])) {
+          return ReportFailure("Invalid escape sequence.");
+        }
+        low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
+      }
+      if (low_code >= JsonEscaping::kMinLowSurrogate &&
+          low_code <= JsonEscaping::kMaxLowSurrogate) {
+        // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint.
+        code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) +
+               JsonEscaping::kMinSupplementaryCodePoint;
+        // Advance past the first code unit escape.
+        p_.remove_prefix(kUnicodeEscapedLength);
+      } else if (!coerce_to_utf8_) {
+        return ReportFailure("Invalid low surrogate.");
+      }
+    } else if (!coerce_to_utf8_) {
+      return ReportFailure("Missing low surrogate.");
+    }
+  }
+  if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
+    return ReportFailure("Invalid unicode code point.");
+  }
+  char buf[UTFmax];
+  int len = EncodeAsUTF8Char(code, buf);
+  // Advance past the [final] code unit escape.
+  p_.remove_prefix(kUnicodeEscapedLength);
+  parsed_storage_.append(buf, len);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseNumber() {
+  NumberResult number;
+  util::Status result = ParseNumberHelper(&number);
+  if (result.ok()) {
+    switch (number.type) {
+      case NumberResult::DOUBLE:
+        ow_->RenderDouble(key_, number.double_val);
+        key_.clear();
+        break;
+
+      case NumberResult::INT:
+        ow_->RenderInt64(key_, number.int_val);
+        key_.clear();
+        break;
+
+      case NumberResult::UINT:
+        ow_->RenderUint64(key_, number.uint_val);
+        key_.clear();
+        break;
+
+      default:
+        return ReportFailure("Unable to parse number.");
+    }
+  }
+  return result;
+}
+
+util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
+  const char* data = p_.data();
+  int length = p_.length();
+
+  // Look for the first non-numeric character, or the end of the string.
+  int index = 0;
+  bool floating = false;
+  bool negative = data[index] == '-';
+  // Find the first character that cannot be part of the number. Along the way
+  // detect if the number needs to be parsed as a double.
+  // Note that this restricts numbers to the JSON specification, so for example
+  // we do not support hex or octal notations.
+  for (; index < length; ++index) {
+    char c = data[index];
+    if (isdigit(c)) continue;
+    if (c == '.' || c == 'e' || c == 'E') {
+      floating = true;
+      continue;
+    }
+    if (c == '+' || c == '-' || c == 'x') continue;
+    // Not a valid number character, break out.
+    break;
+  }
+
+  // If the entire input is a valid number, and we may have more content in the
+  // future, we abort for now and resume when we know more.
+  if (index == length && !finishing_) {
+    return util::Status::CANCELLED;
+  }
+
+  // Create a string containing just the number, so we can use safe_strtoX
+  string number = p_.substr(0, index).ToString();
+
+  // Floating point number, parse as a double.
+  if (floating) {
+    if (!safe_strtod(number, &result->double_val)) {
+      return ReportFailure("Unable to parse number.");
+    }
+    result->type = NumberResult::DOUBLE;
+    p_.remove_prefix(index);
+    return util::Status::OK;
+  }
+
+  // Positive non-floating point number, parse as a uint64.
+  if (!negative) {
+    // Octal/Hex numbers are not valid JSON values.
+    if (number.length() >= 2 && number[0] == '0') {
+      return ReportFailure("Octal/hex numbers are not valid JSON values.");
+    }
+    if (!safe_strtou64(number, &result->uint_val)) {
+      return ReportFailure("Unable to parse number.");
+    }
+    result->type = NumberResult::UINT;
+    p_.remove_prefix(index);
+    return util::Status::OK;
+  }
+
+  // Octal/Hex numbers are not valid JSON values.
+  if (number.length() >= 3 && number[1] == '0') {
+    return ReportFailure("Octal/hex numbers are not valid JSON values.");
+  }
+  // Negative non-floating point number, parse as an int64.
+  if (!safe_strto64(number, &result->int_val)) {
+    return ReportFailure("Unable to parse number.");
+  }
+  result->type = NumberResult::INT;
+  p_.remove_prefix(index);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::HandleBeginObject() {
+  GOOGLE_DCHECK_EQ('{', *p_.data());
+  Advance();
+  ow_->StartObject(key_);
+  key_.clear();
+  stack_.push(ENTRY);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
+  if (type == UNKNOWN) {
+    return ReportUnknown("Expected , or } after key:value pair.");
+  }
+
+  // Object is complete, advance past the comma and render the EndObject.
+  if (type == END_OBJECT) {
+    Advance();
+    ow_->EndObject();
+    return util::Status::OK;
+  }
+  // Found a comma, advance past it and get ready for an entry.
+  if (type == VALUE_SEPARATOR) {
+    Advance();
+    stack_.push(ENTRY);
+    return util::Status::OK;
+  }
+  // Illegal token after key:value pair.
+  return ReportFailure("Expected , or } after key:value pair.");
+}
+
+util::Status JsonStreamParser::ParseEntry(TokenType type) {
+  if (type == UNKNOWN) {
+    return ReportUnknown("Expected an object key or }.");
+  }
+
+  // Close the object and return. This allows for trailing commas.
+  if (type == END_OBJECT) {
+    ow_->EndObject();
+    Advance();
+    return util::Status::OK;
+  }
+
+  util::Status result;
+  if (type == BEGIN_STRING) {
+    // Key is a string (standard JSON), parse it and store the string.
+    result = ParseStringHelper();
+    if (result.ok()) {
+      key_storage_.clear();
+      if (!parsed_storage_.empty()) {
+        parsed_storage_.swap(key_storage_);
+        key_ = StringPiece(key_storage_);
+      } else {
+        key_ = parsed_;
+      }
+      parsed_.clear();
+    }
+  } else if (type == BEGIN_KEY) {
+    // Key is a bare key (back compat), create a StringPiece pointing to it.
+    result = ParseKey();
+  } else {
+    // Unknown key type, report an error.
+    result = ReportFailure("Expected an object key or }.");
+  }
+  // On success we next expect an entry mid ':' then an object mid ',' or '}'
+  if (result.ok()) {
+    stack_.push(OBJ_MID);
+    stack_.push(ENTRY_MID);
+  }
+  return result;
+}
+
+util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
+  if (type == UNKNOWN) {
+    return ReportUnknown("Expected : between key:value pair.");
+  }
+  if (type == ENTRY_SEPARATOR) {
+    Advance();
+    stack_.push(VALUE);
+    return util::Status::OK;
+  }
+  return ReportFailure("Expected : between key:value pair.");
+}
+
+util::Status JsonStreamParser::HandleBeginArray() {
+  GOOGLE_DCHECK_EQ('[', *p_.data());
+  Advance();
+  ow_->StartList(key_);
+  key_.clear();
+  stack_.push(ARRAY_VALUE);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
+  if (type == UNKNOWN) {
+    return ReportUnknown("Expected a value or ] within an array.");
+  }
+
+  if (type == END_ARRAY) {
+    ow_->EndList();
+    Advance();
+    return util::Status::OK;
+  }
+
+  // The ParseValue call may push something onto the stack so we need to make
+  // sure an ARRAY_MID is after it, so we push it on now.
+  stack_.push(ARRAY_MID);
+  util::Status result = ParseValue(type);
+  if (result == util::Status::CANCELLED) {
+    // If we were cancelled, pop back off the ARRAY_MID so we don't try to
+    // push it on again when we try over.
+    stack_.pop();
+  }
+  return result;
+}
+
+util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
+  if (type == UNKNOWN) {
+    return ReportUnknown("Expected , or ] after array value.");
+  }
+
+  if (type == END_ARRAY) {
+    ow_->EndList();
+    Advance();
+    return util::Status::OK;
+  }
+
+  // Found a comma, advance past it and expect an array value next.
+  if (type == VALUE_SEPARATOR) {
+    Advance();
+    stack_.push(ARRAY_VALUE);
+    return util::Status::OK;
+  }
+  // Illegal token after array value.
+  return ReportFailure("Expected , or ] after array value.");
+}
+
+util::Status JsonStreamParser::ParseTrue() {
+  ow_->RenderBool(key_, true);
+  key_.clear();
+  p_.remove_prefix(true_len);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseFalse() {
+  ow_->RenderBool(key_, false);
+  key_.clear();
+  p_.remove_prefix(false_len);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseNull() {
+  ow_->RenderNull(key_);
+  key_.clear();
+  p_.remove_prefix(null_len);
+  return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ReportFailure(StringPiece message) {
+  static const int kContextLength = 20;
+  const char* p_start = p_.data();
+  const char* json_start = json_.data();
+  const char* begin = std::max(p_start - kContextLength, json_start);
+  const char* end =
+      std::min(p_start + kContextLength, json_start + json_.size());
+  StringPiece segment(begin, end - begin);
+  string location(p_start - begin, ' ');
+  location.push_back('^');
+  return util::Status(util::error::INVALID_ARGUMENT,
+                      StrCat(message, "\n", segment, "\n", location));
+}
+
+util::Status JsonStreamParser::ReportUnknown(StringPiece message) {
+  // If we aren't finishing the parse, cancel parsing and try later.
+  if (!finishing_) {
+    return util::Status::CANCELLED;
+  }
+  if (p_.empty()) {
+    return ReportFailure(StrCat("Unexpected end of string. ", message));
+  }
+  return ReportFailure(message);
+}
+
+void JsonStreamParser::SkipWhitespace() {
+  while (!p_.empty() && ascii_isspace(*p_.data())) {
+    Advance();
+  }
+}
+
+void JsonStreamParser::Advance() {
+  // Advance by moving one UTF8 character while making sure we don't go beyond
+  // the length of StringPiece.
+  p_.remove_prefix(std::min<int>(
+      p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
+}
+
+util::Status JsonStreamParser::ParseKey() {
+  StringPiece original = p_;
+  if (!ConsumeKey(&p_, &key_)) {
+    return ReportFailure("Invalid key or variable name.");
+  }
+  // If we consumed everything but expect more data, reset p_ and cancel since
+  // we can't know if the key was complete or not.
+  if (!finishing_ && p_.empty()) {
+    p_ = original;
+    return util::Status::CANCELLED;
+  }
+  // Since we aren't using the key storage, clear it out.
+  key_storage_.clear();
+  return util::Status::OK;
+}
+
+JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() {
+  SkipWhitespace();
+
+  int size = p_.size();
+  if (size == 0) {
+    // If we ran out of data, report unknown and we'll place the previous parse
+    // type onto the stack and try again when we have more data.
+    return UNKNOWN;
+  }
+  // TODO(sven): Split this method based on context since different contexts
+  // support different tokens. Would slightly speed up processing?
+  const char* data = p_.data();
+  if (*data == '\"' || *data == '\'') return BEGIN_STRING;
+  if (*data == '-' || ('0' <= *data && *data <= '9')) {
+    return BEGIN_NUMBER;
+  }
+  if (size >= true_len && !strncmp(data, "true", true_len)) {
+    return BEGIN_TRUE;
+  }
+  if (size >= false_len && !strncmp(data, "false", false_len)) {
+    return BEGIN_FALSE;
+  }
+  if (size >= null_len && !strncmp(data, "null", null_len)) {
+    return BEGIN_NULL;
+  }
+  if (*data == '{') return BEGIN_OBJECT;
+  if (*data == '}') return END_OBJECT;
+  if (*data == '[') return BEGIN_ARRAY;
+  if (*data == ']') return END_ARRAY;
+  if (*data == ':') return ENTRY_SEPARATOR;
+  if (*data == ',') return VALUE_SEPARATOR;
+  if (MatchKey(p_)) {
+    return BEGIN_KEY;
+  }
+
+  // We don't know that we necessarily have an invalid token here, just that we
+  // can't parse what we have so far. So we don't report an error and just
+  // return UNKNOWN so we can try again later when we have more data, or if we
+  // finish and we have leftovers.
+  return UNKNOWN;
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.h
new file mode 100644
index 0000000..0278c28
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser.h
@@ -0,0 +1,258 @@
+// 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_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
+
+#include <stack>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace util {
+class Status;
+}  // namespace util
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectWriter;
+
+// A JSON parser that can parse a stream of JSON chunks rather than needing the
+// entire JSON string up front. It is a modified version of the parser in
+// //net/proto/json/json-parser.h that has been changed in the following ways:
+// - Changed from recursion to an explicit stack to allow resumption
+// - Added support for int64 and uint64 numbers
+// - Removed support for octal and decimal escapes
+// - Removed support for numeric keys
+// - Removed support for functions (javascript)
+// - Removed some lax-comma support (but kept trailing comma support)
+// - Writes directly to an ObjectWriter rather than using subclassing
+//
+// Here is an example usage:
+// JsonStreamParser parser(ow_.get());
+// util::Status result = parser.Parse(chunk1);
+// result.Update(parser.Parse(chunk2));
+// result.Update(parser.FinishParse());
+// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON";
+//
+// This parser is thread-compatible as long as only one thread is calling a
+// Parse() method at a time.
+class LIBPROTOBUF_EXPORT JsonStreamParser {
+ public:
+  // Creates a JsonStreamParser that will write to the given ObjectWriter.
+  explicit JsonStreamParser(ObjectWriter* ow);
+  virtual ~JsonStreamParser();
+
+  // Parses a UTF-8 encoded JSON string from a StringPiece.
+  util::Status Parse(StringPiece json);
+
+
+  // Finish parsing the JSON string.
+  util::Status FinishParse();
+
+
+ private:
+  enum TokenType {
+    BEGIN_STRING,     // " or '
+    BEGIN_NUMBER,     // - or digit
+    BEGIN_TRUE,       // true
+    BEGIN_FALSE,      // false
+    BEGIN_NULL,       // null
+    BEGIN_OBJECT,     // {
+    END_OBJECT,       // }
+    BEGIN_ARRAY,      // [
+    END_ARRAY,        // ]
+    ENTRY_SEPARATOR,  // :
+    VALUE_SEPARATOR,  // ,
+    BEGIN_KEY,        // letter, _, $ or digit.  Must begin with non-digit
+    UNKNOWN           // Unknown token or we ran out of the stream.
+  };
+
+  enum ParseType {
+    VALUE,        // Expects a {, [, true, false, null, string or number
+    OBJ_MID,      // Expects a ',' or }
+    ENTRY,        // Expects a key or }
+    ENTRY_MID,    // Expects a :
+    ARRAY_VALUE,  // Expects a value or ]
+    ARRAY_MID     // Expects a ',' or ]
+  };
+
+  // Holds the result of parsing a number
+  struct NumberResult {
+    enum Type { DOUBLE, INT, UINT };
+    Type type;
+    union {
+      double double_val;
+      int64 int_val;
+      uint64 uint_val;
+    };
+  };
+
+  // Parses a single chunk of JSON, returning an error if the JSON was invalid.
+  util::Status ParseChunk(StringPiece json);
+
+  // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs
+  // out of data. If we unexpectedly run out of p_ we push the latest back onto
+  // the stack and return.
+  util::Status RunParser();
+
+  // Parses a value from p_ and writes it to ow_.
+  // A value may be an object, array, true, false, null, string or number.
+  util::Status ParseValue(TokenType type);
+
+  // Parses a string and writes it out to the ow_.
+  util::Status ParseString();
+
+  // Parses a string, storing the result in parsed_.
+  util::Status ParseStringHelper();
+
+  // This function parses unicode escape sequences in strings. It returns an
+  // error when there's a parsing error, either the size is not the expected
+  // size or a character is not a hex digit.  When it returns str will contain
+  // what has been successfully parsed so far.
+  util::Status ParseUnicodeEscape();
+
+  // Expects p_ to point to a JSON number, writes the number to the writer using
+  // the appropriate Render method based on the type of number.
+  util::Status ParseNumber();
+
+  // Parse a number into a NumberResult, reporting an error if no number could
+  // be parsed. This method will try to parse into a uint64, int64, or double
+  // based on whether the number was positive or negative or had a decimal
+  // component.
+  util::Status ParseNumberHelper(NumberResult* result);
+
+  // Handles a { during parsing of a value.
+  util::Status HandleBeginObject();
+
+  // Parses from the ENTRY state.
+  util::Status ParseEntry(TokenType type);
+
+  // Parses from the ENTRY_MID state.
+  util::Status ParseEntryMid(TokenType type);
+
+  // Parses from the OBJ_MID state.
+  util::Status ParseObjectMid(TokenType type);
+
+  // Handles a [ during parsing of a value.
+  util::Status HandleBeginArray();
+
+  // Parses from the ARRAY_VALUE state.
+  util::Status ParseArrayValue(TokenType type);
+
+  // Parses from the ARRAY_MID state.
+  util::Status ParseArrayMid(TokenType type);
+
+  // Expects p_ to point to an unquoted literal
+  util::Status ParseTrue();
+  util::Status ParseFalse();
+  util::Status ParseNull();
+
+  // Report a failure as a util::Status.
+  util::Status ReportFailure(StringPiece message);
+
+  // Report a failure due to an UNKNOWN token type. We check if we hit the
+  // end of the stream and if we're finishing or not to detect what type of
+  // status to return in this case.
+  util::Status ReportUnknown(StringPiece message);
+
+  // Advance p_ past all whitespace or until the end of the string.
+  void SkipWhitespace();
+
+  // Advance p_ one UTF-8 character
+  void Advance();
+
+  // Expects p_ to point to the beginning of a key.
+  util::Status ParseKey();
+
+  // Return the type of the next token at p_.
+  TokenType GetNextTokenType();
+
+  // The object writer to write parse events to.
+  ObjectWriter* ow_;
+
+  // The stack of parsing we still need to do. When the stack runs empty we will
+  // have parsed a single value from the root (e.g. an object or list).
+  std::stack<ParseType> stack_;
+
+  // Contains any leftover text from a previous chunk that we weren't able to
+  // fully parse, for example the start of a key or number.
+  string leftover_;
+
+  // The current chunk of JSON being parsed. Primarily used for providing
+  // context during error reporting.
+  StringPiece json_;
+
+  // A pointer within the current JSON being parsed, used to track location.
+  StringPiece p_;
+
+  // Stores the last key read, as we separate parsing of keys and values.
+  StringPiece key_;
+
+  // Storage for key_ if we need to keep ownership, for example between chunks
+  // or if the key was unescaped from a JSON string.
+  string key_storage_;
+
+  // True during the FinishParse() call, so we know that any errors are fatal.
+  // For example an unterminated string will normally result in cancelling and
+  // trying during the next chunk, but during FinishParse() it is an error.
+  bool finishing_;
+
+  // String we parsed during a call to ParseStringHelper().
+  StringPiece parsed_;
+
+  // Storage for the string we parsed. This may be empty if the string was able
+  // to be parsed directly from the input.
+  string parsed_storage_;
+
+  // The character that opened the string, either ' or ".
+  // A value of 0 indicates that string parsing is not in process.
+  char string_open_;
+
+  // Storage for the chunk that are being parsed in ParseChunk().
+  string chunk_storage_;
+
+  // Whether to allow non UTF-8 encoded input and replace invalid code points.
+  bool coerce_to_utf8_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser_test.cc
new file mode 100644
index 0000000..059ea6d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -0,0 +1,819 @@
+// 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.
+
+#include <google/protobuf/util/internal/json_stream_parser.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/status.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+namespace error {
+using util::error::INVALID_ARGUMENT;
+}  // namespace error
+namespace converter {
+
+using util::Status;
+
+// Tests for the JSON Stream Parser. These tests are intended to be
+// comprehensive and cover the following:
+//
+// Positive tests:
+// - true, false, null
+// - empty object or array.
+// - negative and positive double and int, unsigned int
+// - single and double quoted strings
+// - string key, unquoted key, numeric key
+// - array containing array, object, value
+// - object containing array, object, value
+// - unicode handling in strings
+// - ascii escaping (\b, \f, \n, \r, \t, \v)
+// - trailing commas
+//
+// Negative tests:
+// - illegal literals
+// - mismatched quotes failure on strings
+// - unterminated string failure
+// - unexpected end of string failure
+// - mismatched object and array closing
+// - Failure to close array or object
+// - numbers too large
+// - invalid unicode escapes.
+// - invalid unicode sequences.
+// - numbers as keys
+//
+// For each test we split the input string on every possible character to ensure
+// the parser is able to handle arbitrarily split input for all cases. We also
+// do a final test of the entire test case one character at a time.
+class JsonStreamParserTest : public ::testing::Test {
+ protected:
+  JsonStreamParserTest() : mock_(), ow_(&mock_) {}
+  virtual ~JsonStreamParserTest() {}
+
+  util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) {
+    JsonStreamParser parser(&mock_);
+
+    // Special case for split == length, test parsing one character at a time.
+    if (split == json.length()) {
+      GOOGLE_LOG(INFO) << "Testing split every char: " << json;
+      for (int i = 0; i < json.length(); ++i) {
+        StringPiece single = json.substr(i, 1);
+        util::Status result = parser.Parse(single);
+        if (!result.ok()) {
+          return result;
+        }
+      }
+      return parser.FinishParse();
+    }
+
+    // Normal case, split at the split point and parse two substrings.
+    StringPiece first = json.substr(0, split);
+    StringPiece rest = json.substr(split);
+    GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest;
+    util::Status result = parser.Parse(first);
+    if (result.ok()) {
+      result = parser.Parse(rest);
+      if (result.ok()) {
+        result = parser.FinishParse();
+      }
+    }
+    return result;
+  }
+
+  void DoTest(StringPiece json, int split, bool coerce_utf8 = false) {
+    util::Status result = RunTest(json, split, coerce_utf8);
+    if (!result.ok()) {
+      GOOGLE_LOG(WARNING) << result;
+    }
+    EXPECT_OK(result);
+  }
+
+  void DoErrorTest(StringPiece json, int split, StringPiece error_prefix,
+                   bool coerce_utf8 = false) {
+    util::Status result = RunTest(json, split, coerce_utf8);
+    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
+    StringPiece error_message(result.error_message());
+    EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
+  }
+
+
+  MockObjectWriter mock_;
+  ExpectingObjectWriter ow_;
+};
+
+
+// Positive tests
+
+// - true, false, null
+TEST_F(JsonStreamParserTest, SimpleTrue) {
+  StringPiece str = "true";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderBool("", true);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleFalse) {
+  StringPiece str = "false";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderBool("", false);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNull) {
+  StringPiece str = "null";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderNull("");
+    DoTest(str, i);
+  }
+}
+
+// - empty object and array.
+TEST_F(JsonStreamParserTest, EmptyObject) {
+  StringPiece str = "{}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->EndObject();
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, EmptyList) {
+  StringPiece str = "[]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")->EndList();
+    DoTest(str, i);
+  }
+}
+
+// - negative and positive double and int, unsigned int
+TEST_F(JsonStreamParserTest, SimpleDouble) {
+  StringPiece str = "42.5";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderDouble("", 42.5);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, ScientificDouble) {
+  StringPiece str = "1.2345e-10";
+  for (int i = 0; i < str.length(); ++i) {
+    ow_.RenderDouble("", 1.2345e-10);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNegativeDouble) {
+  StringPiece str = "-1045.235";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderDouble("", -1045.235);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleInt) {
+  StringPiece str = "123456";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderUint64("", 123456);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
+  StringPiece str = "-79497823553162765";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderInt64("", -79497823553162765LL);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
+  StringPiece str = "11779497823553162765";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderUint64("", 11779497823553162765ULL);
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
+  StringPiece str = "01234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "-01234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
+  StringPiece str = "0x1234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "-0x1234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "12x34";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
+// - single and double quoted strings
+TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
+  StringPiece str = "\"\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderString("", "");
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, EmptySingleQuotedString) {
+  StringPiece str = "''";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderString("", "");
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) {
+  StringPiece str = "\"Some String\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderString("", "Some String");
+    DoTest(str, i);
+  }
+}
+
+TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) {
+  StringPiece str = "'Another String'";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderString("", "Another String");
+    DoTest(str, i);
+  }
+}
+
+// - string key, unquoted key, numeric key
+TEST_F(JsonStreamParserTest, ObjectKeyTypes) {
+  StringPiece str =
+      "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")
+        ->RenderBool("s", true)
+        ->RenderBool("d", false)
+        ->RenderNull("key")
+        ->StartList("snake_key")
+        ->EndList()
+        ->StartObject("camelKey")
+        ->EndObject()
+        ->EndObject();
+    DoTest(str, i);
+  }
+}
+
+// - array containing array, object, values (true, false, null, num, string)
+TEST_F(JsonStreamParserTest, ArrayValues) {
+  StringPiece str =
+      "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, "
+      "-1056.4, 11779497823553162765], {'key': true}]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->RenderBool("", true)
+        ->RenderBool("", false)
+        ->RenderNull("")
+        ->RenderString("", "a string")
+        ->RenderString("", "another string")
+        ->StartList("")
+        ->RenderUint64("", 22)
+        ->RenderInt64("", -127)
+        ->RenderDouble("", 45.3)
+        ->RenderDouble("", -1056.4)
+        ->RenderUint64("", 11779497823553162765ULL)
+        ->EndList()
+        ->StartObject("")
+        ->RenderBool("key", true)
+        ->EndObject()
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+// - object containing array, object, value (true, false, null, num, string)
+TEST_F(JsonStreamParserTest, ObjectValues) {
+  StringPiece str =
+      "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: "
+      "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], "
+      "o: {'key': true}}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")
+        ->RenderBool("t", true)
+        ->RenderBool("f", false)
+        ->RenderNull("n")
+        ->RenderString("s", "a string")
+        ->RenderString("d", "another string")
+        ->RenderUint64("pi", 22)
+        ->RenderInt64("ni", -127)
+        ->RenderDouble("pd", 45.3)
+        ->RenderDouble("nd", -1056.4)
+        ->RenderUint64("pl", 11779497823553162765ULL)
+        ->StartList("l")
+        ->StartList("")
+        ->EndList()
+        ->EndList()
+        ->StartObject("o")
+        ->RenderBool("key", true)
+        ->EndObject()
+        ->EndObject();
+    DoTest(str, i);
+  }
+}
+
+
+TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
+  StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
+  for (int i = 0; i <= json.length(); ++i) {
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+  }
+  json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
+  for (int i = 0; i <= json.length(); ++i) {
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+  }
+  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
+}
+
+// - unicode handling in strings
+TEST_F(JsonStreamParserTest, UnicodeEscaping) {
+  StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+// - unicode UTF-16 surrogate pair handling in strings
+TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
+  StringPiece str =
+      "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\\uD83C\\uDF6F\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->RenderString("",
+                       "\xE0\xAF\xAE\xF0\x90\x87\xB1\xF0\x93\x86\xA4\xF0"
+                       "\x9F\x90\x9D\xF0\x9F\x8D\xAF")
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
+  // A low surrogate alone.
+  StringPiece str = "[\"\\ude36\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid unicode code point.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
+  // A high surrogate alone.
+  StringPiece str = "[\"\\ud83d\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Missing low surrogate.");
+  }
+  // A high surrogate with some trailing characters.
+  str = "[\"\\ud83d|ude36\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Missing low surrogate.");
+  }
+  // A high surrogate with half a low surrogate.
+  str = "[\"\\ud83d\\ude--\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+  // Two high surrogates.
+  str = "[\"\\ud83d\\ud83d\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid low surrogate.");
+  }
+}
+
+// - ascii escaping (\b, \f, \n, \r, \t, \v)
+TEST_F(JsonStreamParserTest, AsciiEscaping) {
+  StringPiece str =
+      "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->RenderString("", "\b")
+        ->RenderString("", "\ning")
+        ->RenderString("", "test\f")
+        ->RenderString("", "\r\t")
+        ->RenderString("", "test\\\ving")
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+// - trailing commas, we support a single trailing comma but no internal commas.
+TEST_F(JsonStreamParserTest, TrailingCommas) {
+  StringPiece str = "[['a',true,], {b: null,},]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->StartList("")
+        ->RenderString("", "a")
+        ->RenderBool("", true)
+        ->EndList()
+        ->StartObject("")
+        ->RenderNull("b")
+        ->EndObject()
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+// Negative tests
+
+// illegal literals
+TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) {
+  StringPiece str = "truee";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderBool("", true);
+    DoErrorTest(str, i, "Parsing terminated before end of input.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
+  StringPiece str = "-";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
+  StringPiece str = "-foo";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralInArray) {
+  StringPiece str = "[nule]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Unexpected token.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralInObject) {
+  StringPiece str = "{123false}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+// mismatched quotes failure on strings
+TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
+  StringPiece str = "'Some str\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
+  StringPiece str = "\"Another string that ends poorly!'";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+// unterminated strings
+TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
+  StringPiece str = "\"Forgot the rest of i";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
+  StringPiece str = "\"Forgot the rest of \\";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringInArray) {
+  StringPiece str = "[\"Forgot to close the string]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringInObject) {
+  StringPiece str = "{f: \"Forgot to close the string}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedObject) {
+  StringPiece str = "{";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Unexpected end of string.");
+  }
+}
+
+
+// mismatched object and array closing
+TEST_F(JsonStreamParserTest, MismatchedCloseObject) {
+  StringPiece str = "{'key': true]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->RenderBool("key", true);
+    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MismatchedCloseArray) {
+  StringPiece str = "[true, null}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")->RenderBool("", true)->RenderNull("");
+    DoErrorTest(str, i, "Expected , or ] after array value.");
+  }
+}
+
+// Invalid object keys.
+TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) {
+  StringPiece str = "{42: true}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) {
+  StringPiece str = "{{bob: true}}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) {
+  StringPiece str = "{[null]}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) {
+  StringPiece str = "{false}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) {
+  StringPiece str = "{\"key\"}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected : between key:value pair.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) {
+  StringPiece str = "{key}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected : between key:value pair.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) {
+  StringPiece str = "{key";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Unexpected end of string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) {
+  StringPiece str = "{key:}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Unexpected token.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) {
+  StringPiece str = "{key:20 'hello': true}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->RenderUint64("key", 20);
+    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) {
+  StringPiece str = "{false: 20}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
+  StringPiece str = "{}}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->EndObject();
+    DoErrorTest(str, i, "Parsing terminated before end of input.");
+  }
+}
+
+// numbers too large
+TEST_F(JsonStreamParserTest, PositiveNumberTooBig) {
+  StringPiece str = "[18446744073709551616]";  // 2^64
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, NegativeNumberTooBig) {
+  StringPiece str = "[-18446744073709551616]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
+/*
+TODO(sven): Fail parsing when parsing a double that is too large.
+
+TEST_F(JsonStreamParserTest, DoubleTooBig) {
+  StringPiece str = "[184464073709551232321616.45]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Unable to parse number");
+  }
+}
+*/
+
+// invalid bare backslash.
+TEST_F(JsonStreamParserTest, UnfinishedEscape) {
+  StringPiece str = "\"\\";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+// invalid bare backslash u.
+TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
+  StringPiece str = "\"\\u";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Illegal hex string.");
+  }
+}
+
+// invalid unicode sequence.
+TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
+  StringPiece str = "\"\\u12";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Illegal hex string.");
+  }
+}
+
+// invalid unicode sequence (valid in modern EcmaScript but not in JSON).
+TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
+  StringPiece str = "\"\\u{1f36f}\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+}
+
+
+TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
+  StringPiece str = "\"\\u12$4hello";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+}
+
+// invalid unicode sequence in low half surrogate: g is not a hex digit.
+TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
+  StringPiece str = "\"\\ud800\\udcfg\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+}
+
+// Extra commas with an object or array.
+TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
+  StringPiece str = "{'k1': true,,'k2': false}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->RenderBool("k1", true);
+    DoErrorTest(str, i, "Expected an object key or }.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, ExtraCommaInArray) {
+  StringPiece str = "[true,,false}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")->RenderBool("", true);
+    DoErrorTest(str, i, "Unexpected token.");
+  }
+}
+
+// Extra text beyond end of value.
+TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) {
+  StringPiece str = "'hello', 'world'";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.RenderString("", "hello");
+    DoErrorTest(str, i, "Parsing terminated before end of input.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, ExtraTextAfterObject) {
+  StringPiece str = "{'key': true} 'oops'";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("")->RenderBool("key", true)->EndObject();
+    DoErrorTest(str, i, "Parsing terminated before end of input.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, ExtraTextAfterArray) {
+  StringPiece str = "[null] 'oops'";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")->RenderNull("")->EndList();
+    DoErrorTest(str, i, "Parsing terminated before end of input.");
+  }
+}
+
+// Random unknown text in the value.
+TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
+  StringPiece str = "*&#25";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Expected a value.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnknownCharactersInArray) {
+  StringPiece str = "[*&#25]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("");
+    DoErrorTest(str, i, "Expected a value or ] within an array.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnknownCharactersInObject) {
+  StringPiece str = "{'key': *&#25}";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartObject("");
+    DoErrorTest(str, i, "Expected a value.");
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/location_tracker.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/location_tracker.h
new file mode 100644
index 0000000..0864b05
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/location_tracker.h
@@ -0,0 +1,65 @@
+// 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_UTIL_CONVERTER_LOCATION_TRACKER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// LocationTrackerInterface is an interface for classes that track
+// the location information for the purpose of error reporting.
+class LIBPROTOBUF_EXPORT LocationTrackerInterface {
+ public:
+  virtual ~LocationTrackerInterface() {}
+
+  // Returns the object location as human readable string.
+  virtual string ToString() const = 0;
+
+ protected:
+  LocationTrackerInterface() {}
+
+ private:
+  // Please do not add any data members to this class.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/mock_error_listener.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/mock_error_listener.h
new file mode 100644
index 0000000..591c35d
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/mock_error_listener.h
@@ -0,0 +1,63 @@
+// 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_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
+
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+#include <gmock/gmock.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class MockErrorListener : public ErrorListener {
+ public:
+  MockErrorListener() {}
+  virtual ~MockErrorListener() {}
+
+  MOCK_METHOD3(InvalidName, void(const LocationTrackerInterface& loc,
+                                 StringPiece unknown_name,
+                                 StringPiece message));
+  MOCK_METHOD3(InvalidValue, void(const LocationTrackerInterface& loc,
+                                  StringPiece type_name, StringPiece value));
+  MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc,
+                                  StringPiece missing_name));
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_location_tracker.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_location_tracker.h
new file mode 100644
index 0000000..8586cec
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_location_tracker.h
@@ -0,0 +1,64 @@
+// 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_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An empty concrete implementation of LocationTrackerInterface.
+class ObjectLocationTracker : public LocationTrackerInterface {
+ public:
+  // Creates an empty location tracker.
+  ObjectLocationTracker() {}
+
+  virtual ~ObjectLocationTracker() {}
+
+  // Returns empty because nothing is tracked.
+  virtual string ToString() const { return ""; }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_source.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_source.h
new file mode 100644
index 0000000..2c31cfb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_source.h
@@ -0,0 +1,79 @@
+// 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_UTIL_CONVERTER_OBJECT_SOURCE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectWriter;
+
+// An ObjectSource is anything that can write to an ObjectWriter.
+// Implementation of this interface typically provide constructors or
+// factory methods to create an instance based on some source data, for
+// example, a character stream, or protobuf.
+//
+// Derived classes could be thread-unsafe.
+class LIBPROTOBUF_EXPORT ObjectSource {
+ public:
+  virtual ~ObjectSource() {}
+
+  // Writes to the ObjectWriter
+  virtual util::Status WriteTo(ObjectWriter* ow) const {
+    return NamedWriteTo("", ow);
+  }
+
+  // Writes to the ObjectWriter with a custom name for the message.
+  // This is useful when you chain ObjectSource together by embedding one
+  // within another.
+  virtual util::Status NamedWriteTo(StringPiece name,
+                                      ObjectWriter* ow) const = 0;
+
+ protected:
+  ObjectSource() {}
+
+ private:
+  // Do not add any data members to this class.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.cc
new file mode 100644
index 0000000..57cc08a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.cc
@@ -0,0 +1,92 @@
+// 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.
+
+#include <google/protobuf/util/internal/object_writer.h>
+
+#include <google/protobuf/util/internal/datapiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// static
+void ObjectWriter::RenderDataPieceTo(const DataPiece& data, StringPiece name,
+                                     ObjectWriter* ow) {
+  switch (data.type()) {
+    case DataPiece::TYPE_INT32: {
+      ow->RenderInt32(name, data.ToInt32().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_INT64: {
+      ow->RenderInt64(name, data.ToInt64().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_UINT32: {
+      ow->RenderUint32(name, data.ToUint32().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_UINT64: {
+      ow->RenderUint64(name, data.ToUint64().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_DOUBLE: {
+      ow->RenderDouble(name, data.ToDouble().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_FLOAT: {
+      ow->RenderFloat(name, data.ToFloat().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_BOOL: {
+      ow->RenderBool(name, data.ToBool().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_STRING: {
+      ow->RenderString(name, data.ToString().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_BYTES: {
+      ow->RenderBytes(name, data.ToBytes().ValueOrDie());
+      break;
+    }
+    case DataPiece::TYPE_NULL: {
+      ow->RenderNull(name);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.h
new file mode 100644
index 0000000..9f07363
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/object_writer.h
@@ -0,0 +1,138 @@
+// 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_UTIL_CONVERTER_OBJECT_WRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class DataPiece;
+
+// An ObjectWriter is an interface for writing a stream of events
+// representing objects and collections. Implementation of this
+// interface can be used to write an object stream to an in-memory
+// structure, protobufs, JSON, XML, or any other output format
+// desired. The ObjectSource interface is typically used as the
+// source of an object stream.
+//
+// See JsonObjectWriter for a sample implementation of ObjectWriter
+// and its use.
+//
+// Derived classes could be thread-unsafe.
+//
+// TODO(xinb): seems like a prime candidate to apply the RAII paradigm
+// and get rid the need to call EndXXX().
+class LIBPROTOBUF_EXPORT ObjectWriter {
+ public:
+  virtual ~ObjectWriter() {}
+
+  // Starts an object. If the name is empty, the object will not be named.
+  virtual ObjectWriter* StartObject(StringPiece name) = 0;
+
+  // Ends an object.
+  virtual ObjectWriter* EndObject() = 0;
+
+  // Starts a list. If the name is empty, the list will not be named.
+  virtual ObjectWriter* StartList(StringPiece name) = 0;
+
+  // Ends a list.
+  virtual ObjectWriter* EndList() = 0;
+
+  // Renders a boolean value.
+  virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
+
+  // Renders an 32-bit integer value.
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0;
+
+  // Renders an 32-bit unsigned integer value.
+  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0;
+
+  // Renders a 64-bit integer value.
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0;
+
+  // Renders an 64-bit unsigned integer value.
+  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0;
+
+  // Renders a double value.
+  virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0;
+
+  // Renders a float value.
+  virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0;
+
+  // Renders a StringPiece value. This is for rendering strings.
+  virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) = 0;
+
+  // Renders a bytes value.
+  virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0;
+
+  // Renders a Null value.
+  virtual ObjectWriter* RenderNull(StringPiece name) = 0;
+
+  // Renders a DataPiece object to a ObjectWriter.
+  static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
+                                ObjectWriter* ow);
+
+  // Indicates whether this ObjectWriter has completed writing the root message,
+  // usually this means writing of one complete object. Subclasses must override
+  // this behavior appropriately.
+  virtual bool done() { return false; }
+
+  void set_use_strict_base64_decoding(bool value) {
+    use_strict_base64_decoding_ = value;
+  }
+
+  bool use_strict_base64_decoding() const {
+    return use_strict_base64_decoding_;
+  }
+
+ protected:
+  ObjectWriter() : use_strict_base64_decoding_(true) {}
+
+ private:
+  // If set to true, we use the stricter version of base64 decoding for byte
+  // fields by making sure decoded version encodes back to the original string.
+  bool use_strict_base64_decoding_;
+
+  // Do not add any data members to this class.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.cc
new file mode 100644
index 0000000..36b7941
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.cc
@@ -0,0 +1,762 @@
+// 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.
+
+#include <google/protobuf/util/internal/proto_writer.h>
+
+#include <functional>
+#include <stack>
+
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/util/internal/field_mask_utility.h>
+#include <google/protobuf/util/internal/object_location_tracker.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::internal::WireFormatLite;
+using google::protobuf::io::CodedOutputStream;
+using util::error::INVALID_ARGUMENT;
+using util::Status;
+using util::StatusOr;
+
+
+ProtoWriter::ProtoWriter(TypeResolver* type_resolver,
+                         const google::protobuf::Type& type,
+                         strings::ByteSink* output, ErrorListener* listener)
+    : master_type_(type),
+      typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+      own_typeinfo_(true),
+      done_(false),
+      element_(NULL),
+      size_insert_(),
+      output_(output),
+      buffer_(),
+      adapter_(&buffer_),
+      stream_(new CodedOutputStream(&adapter_)),
+      listener_(listener),
+      invalid_depth_(0),
+      tracker_(new ObjectLocationTracker()) {}
+
+ProtoWriter::ProtoWriter(const TypeInfo* typeinfo,
+                         const google::protobuf::Type& type,
+                         strings::ByteSink* output, ErrorListener* listener)
+    : master_type_(type),
+      typeinfo_(typeinfo),
+      own_typeinfo_(false),
+      done_(false),
+      element_(NULL),
+      size_insert_(),
+      output_(output),
+      buffer_(),
+      adapter_(&buffer_),
+      stream_(new CodedOutputStream(&adapter_)),
+      listener_(listener),
+      invalid_depth_(0),
+      tracker_(new ObjectLocationTracker()) {}
+
+ProtoWriter::~ProtoWriter() {
+  if (own_typeinfo_) {
+    delete typeinfo_;
+  }
+  if (element_ == NULL) return;
+  // Cleanup explicitly in order to avoid destructor stack overflow when input
+  // is deeply nested.
+  // Cast to BaseElement to avoid doing additional checks (like missing fields)
+  // during pop().
+  google::protobuf::scoped_ptr<BaseElement> element(
+      static_cast<BaseElement*>(element_.get())->pop<BaseElement>());
+  while (element != NULL) {
+    element.reset(element->pop<BaseElement>());
+  }
+}
+
+namespace {
+
+// Writes an INT32 field, including tag to the stream.
+inline Status WriteInt32(int field_number, const DataPiece& data,
+                         CodedOutputStream* stream) {
+  StatusOr<int32> i32 = data.ToInt32();
+  if (i32.ok()) {
+    WireFormatLite::WriteInt32(field_number, i32.ValueOrDie(), stream);
+  }
+  return i32.status();
+}
+
+// writes an SFIXED32 field, including tag, to the stream.
+inline Status WriteSFixed32(int field_number, const DataPiece& data,
+                            CodedOutputStream* stream) {
+  StatusOr<int32> i32 = data.ToInt32();
+  if (i32.ok()) {
+    WireFormatLite::WriteSFixed32(field_number, i32.ValueOrDie(), stream);
+  }
+  return i32.status();
+}
+
+// Writes an SINT32 field, including tag, to the stream.
+inline Status WriteSInt32(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<int32> i32 = data.ToInt32();
+  if (i32.ok()) {
+    WireFormatLite::WriteSInt32(field_number, i32.ValueOrDie(), stream);
+  }
+  return i32.status();
+}
+
+// Writes a FIXED32 field, including tag, to the stream.
+inline Status WriteFixed32(int field_number, const DataPiece& data,
+                           CodedOutputStream* stream) {
+  StatusOr<uint32> u32 = data.ToUint32();
+  if (u32.ok()) {
+    WireFormatLite::WriteFixed32(field_number, u32.ValueOrDie(), stream);
+  }
+  return u32.status();
+}
+
+// Writes a UINT32 field, including tag, to the stream.
+inline Status WriteUInt32(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<uint32> u32 = data.ToUint32();
+  if (u32.ok()) {
+    WireFormatLite::WriteUInt32(field_number, u32.ValueOrDie(), stream);
+  }
+  return u32.status();
+}
+
+// Writes an INT64 field, including tag, to the stream.
+inline Status WriteInt64(int field_number, const DataPiece& data,
+                         CodedOutputStream* stream) {
+  StatusOr<int64> i64 = data.ToInt64();
+  if (i64.ok()) {
+    WireFormatLite::WriteInt64(field_number, i64.ValueOrDie(), stream);
+  }
+  return i64.status();
+}
+
+// Writes an SFIXED64 field, including tag, to the stream.
+inline Status WriteSFixed64(int field_number, const DataPiece& data,
+                            CodedOutputStream* stream) {
+  StatusOr<int64> i64 = data.ToInt64();
+  if (i64.ok()) {
+    WireFormatLite::WriteSFixed64(field_number, i64.ValueOrDie(), stream);
+  }
+  return i64.status();
+}
+
+// Writes an SINT64 field, including tag, to the stream.
+inline Status WriteSInt64(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<int64> i64 = data.ToInt64();
+  if (i64.ok()) {
+    WireFormatLite::WriteSInt64(field_number, i64.ValueOrDie(), stream);
+  }
+  return i64.status();
+}
+
+// Writes a FIXED64 field, including tag, to the stream.
+inline Status WriteFixed64(int field_number, const DataPiece& data,
+                           CodedOutputStream* stream) {
+  StatusOr<uint64> u64 = data.ToUint64();
+  if (u64.ok()) {
+    WireFormatLite::WriteFixed64(field_number, u64.ValueOrDie(), stream);
+  }
+  return u64.status();
+}
+
+// Writes a UINT64 field, including tag, to the stream.
+inline Status WriteUInt64(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<uint64> u64 = data.ToUint64();
+  if (u64.ok()) {
+    WireFormatLite::WriteUInt64(field_number, u64.ValueOrDie(), stream);
+  }
+  return u64.status();
+}
+
+// Writes a DOUBLE field, including tag, to the stream.
+inline Status WriteDouble(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<double> d = data.ToDouble();
+  if (d.ok()) {
+    WireFormatLite::WriteDouble(field_number, d.ValueOrDie(), stream);
+  }
+  return d.status();
+}
+
+// Writes a FLOAT field, including tag, to the stream.
+inline Status WriteFloat(int field_number, const DataPiece& data,
+                         CodedOutputStream* stream) {
+  StatusOr<float> f = data.ToFloat();
+  if (f.ok()) {
+    WireFormatLite::WriteFloat(field_number, f.ValueOrDie(), stream);
+  }
+  return f.status();
+}
+
+// Writes a BOOL field, including tag, to the stream.
+inline Status WriteBool(int field_number, const DataPiece& data,
+                        CodedOutputStream* stream) {
+  StatusOr<bool> b = data.ToBool();
+  if (b.ok()) {
+    WireFormatLite::WriteBool(field_number, b.ValueOrDie(), stream);
+  }
+  return b.status();
+}
+
+// Writes a BYTES field, including tag, to the stream.
+inline Status WriteBytes(int field_number, const DataPiece& data,
+                         CodedOutputStream* stream) {
+  StatusOr<string> c = data.ToBytes();
+  if (c.ok()) {
+    WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream);
+  }
+  return c.status();
+}
+
+// Writes a STRING field, including tag, to the stream.
+inline Status WriteString(int field_number, const DataPiece& data,
+                          CodedOutputStream* stream) {
+  StatusOr<string> s = data.ToString();
+  if (s.ok()) {
+    WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream);
+  }
+  return s.status();
+}
+
+// Writes an ENUM field, including tag, to the stream.
+inline Status WriteEnum(int field_number, const DataPiece& data,
+                        const google::protobuf::Enum* enum_type,
+                        CodedOutputStream* stream) {
+  StatusOr<int> e = data.ToEnum(enum_type);
+  if (e.ok()) {
+    WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream);
+  }
+  return e.status();
+}
+
+// Given a google::protobuf::Type, returns the set of all required fields.
+std::set<const google::protobuf::Field*> GetRequiredFields(
+    const google::protobuf::Type& type) {
+  std::set<const google::protobuf::Field*> required;
+  for (int i = 0; i < type.fields_size(); i++) {
+    const google::protobuf::Field& field = type.fields(i);
+    if (field.cardinality() ==
+        google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) {
+      required.insert(&field);
+    }
+  }
+  return required;
+}
+
+}  // namespace
+
+ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo,
+                                        const google::protobuf::Type& type,
+                                        ProtoWriter* enclosing)
+    : BaseElement(NULL),
+      ow_(enclosing),
+      parent_field_(NULL),
+      typeinfo_(typeinfo),
+      type_(type),
+      required_fields_(GetRequiredFields(type)),
+      size_index_(-1),
+      array_index_(-1) {}
+
+ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent,
+                                        const google::protobuf::Field* field,
+                                        const google::protobuf::Type& type,
+                                        bool is_list)
+    : BaseElement(parent),
+      ow_(this->parent()->ow_),
+      parent_field_(field),
+      typeinfo_(this->parent()->typeinfo_),
+      type_(type),
+      size_index_(
+          !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE
+              ? ow_->size_insert_.size()
+              : -1),
+      array_index_(is_list ? 0 : -1) {
+  if (!is_list) {
+    if (ow_->IsRepeated(*field)) {
+      // Update array_index_ if it is an explicit list.
+      if (this->parent()->array_index_ >= 0) this->parent()->array_index_++;
+    } else {
+      this->parent()->RegisterField(field);
+    }
+
+    if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+      required_fields_ = GetRequiredFields(type_);
+      int start_pos = ow_->stream_->ByteCount();
+      // length of serialized message is the final buffer position minus
+      // starting buffer position, plus length adjustments for size fields
+      // of any nested messages. We start with -start_pos here, so we only
+      // need to add the final buffer position to it at the end.
+      SizeInfo info = {start_pos, -start_pos};
+      ow_->size_insert_.push_back(info);
+    }
+  }
+}
+
+ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() {
+  // Calls the registered error listener for any required field(s) not yet
+  // seen.
+  for (set<const google::protobuf::Field*>::iterator it =
+           required_fields_.begin();
+       it != required_fields_.end(); ++it) {
+    ow_->MissingField((*it)->name());
+  }
+  // Computes the total number of proto bytes used by a message, also adjusts
+  // the size of all parent messages by the length of this size field.
+  // If size_index_ < 0, this is not a message, so no size field is added.
+  if (size_index_ >= 0) {
+    // Add the final buffer position to compute the total length of this
+    // serialized message. The stored value (before this addition) already
+    // contains the total length of the size fields of all nested messages
+    // minus the initial buffer position.
+    ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount();
+    // Calculate the length required to serialize the size field of the
+    // message, and propagate this additional size information upward to
+    // all enclosing messages.
+    int size = ow_->size_insert_[size_index_].size;
+    int length = CodedOutputStream::VarintSize32(size);
+    for (ProtoElement* e = parent(); e != NULL; e = e->parent()) {
+      // Only nested messages have size field, lists do not have size field.
+      if (e->size_index_ >= 0) {
+        ow_->size_insert_[e->size_index_].size += length;
+      }
+    }
+  }
+  return BaseElement::pop<ProtoElement>();
+}
+
+void ProtoWriter::ProtoElement::RegisterField(
+    const google::protobuf::Field* field) {
+  if (!required_fields_.empty() &&
+      field->cardinality() ==
+          google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) {
+    required_fields_.erase(field);
+  }
+}
+
+string ProtoWriter::ProtoElement::ToString() const {
+  if (parent() == NULL) return "";
+  string loc = parent()->ToString();
+  if (!ow_->IsRepeated(*parent_field_) ||
+      parent()->parent_field_ != parent_field_) {
+    string name = parent_field_->name();
+    int i = 0;
+    while (i < name.size() && (ascii_isalnum(name[i]) || name[i] == '_')) ++i;
+    if (i > 0 && i == name.size()) {  // safe field name
+      if (loc.empty()) {
+        loc = name;
+      } else {
+        StrAppend(&loc, ".", name);
+      }
+    } else {
+      StrAppend(&loc, "[\"", CEscape(name), "\"]");
+    }
+  }
+  if (ow_->IsRepeated(*parent_field_) && array_index_ > 0) {
+    StrAppend(&loc, "[", array_index_ - 1, "]");
+  }
+  return loc.empty() ? "." : loc;
+}
+
+bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) {
+  return ContainsKey(oneof_indices_, index);
+}
+
+void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) {
+  InsertIfNotPresent(&oneof_indices_, index);
+}
+
+void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) {
+  listener_->InvalidName(location(), ToSnakeCase(unknown_name), message);
+}
+
+void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) {
+  listener_->InvalidValue(location(), type_name, value);
+}
+
+void ProtoWriter::MissingField(StringPiece missing_name) {
+  listener_->MissingField(location(), missing_name);
+}
+
+ProtoWriter* ProtoWriter::StartObject(StringPiece name) {
+  // Starting the root message. Create the root ProtoElement and return.
+  if (element_ == NULL) {
+    if (!name.empty()) {
+      InvalidName(name, "Root element should not be named.");
+    }
+    element_.reset(new ProtoElement(typeinfo_, master_type_, this));
+    return this;
+  }
+
+  const google::protobuf::Field* field = NULL;
+  field = BeginNamed(name, false);
+  if (field == NULL) return this;
+
+  // Check to see if this field is a oneof and that no oneof in that group has
+  // already been set.
+  if (!ValidOneof(*field, name)) {
+    ++invalid_depth_;
+    return this;
+  }
+
+  const google::protobuf::Type* type = LookupType(field);
+  if (type == NULL) {
+    ++invalid_depth_;
+    InvalidName(name,
+                StrCat("Missing descriptor for field: ", field->type_url()));
+    return this;
+  }
+
+  return StartObjectField(*field, *type);
+}
+
+ProtoWriter* ProtoWriter::EndObject() {
+  if (invalid_depth_ > 0) {
+    --invalid_depth_;
+    return this;
+  }
+
+  if (element_ != NULL) {
+    element_.reset(element_->pop());
+  }
+
+
+  // If ending the root element,
+  // then serialize the full message with calculated sizes.
+  if (element_ == NULL) {
+    WriteRootMessage();
+  }
+  return this;
+}
+
+ProtoWriter* ProtoWriter::StartList(StringPiece name) {
+  const google::protobuf::Field* field = BeginNamed(name, true);
+  if (field == NULL) return this;
+
+  if (!ValidOneof(*field, name)) {
+    ++invalid_depth_;
+    return this;
+  }
+
+  const google::protobuf::Type* type = LookupType(field);
+  if (type == NULL) {
+    ++invalid_depth_;
+    InvalidName(name,
+                StrCat("Missing descriptor for field: ", field->type_url()));
+    return this;
+  }
+
+  return StartListField(*field, *type);
+}
+
+ProtoWriter* ProtoWriter::EndList() {
+  if (invalid_depth_ > 0) {
+    --invalid_depth_;
+  } else if (element_ != NULL) {
+    element_.reset(element_->pop());
+  }
+  return this;
+}
+
+ProtoWriter* ProtoWriter::RenderDataPiece(StringPiece name,
+                                          const DataPiece& data) {
+  Status status;
+  if (invalid_depth_ > 0) return this;
+
+  const google::protobuf::Field* field = Lookup(name);
+  if (field == NULL) return this;
+
+  if (!ValidOneof(*field, name)) return this;
+
+  const google::protobuf::Type* type = LookupType(field);
+  if (type == NULL) {
+    InvalidName(name,
+                StrCat("Missing descriptor for field: ", field->type_url()));
+    return this;
+  }
+
+  return RenderPrimitiveField(*field, *type, data);
+}
+
+bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
+                             StringPiece unnormalized_name) {
+  if (element_ == NULL) return true;
+
+  if (field.oneof_index() > 0) {
+    if (element_->IsOneofIndexTaken(field.oneof_index())) {
+      InvalidValue(
+          "oneof",
+          StrCat("oneof field '",
+                 element_->type().oneofs(field.oneof_index() - 1),
+                 "' is already set. Cannot set '", unnormalized_name, "'"));
+      return false;
+    }
+    element_->TakeOneofIndex(field.oneof_index());
+  }
+  return true;
+}
+
+bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) {
+  return field.cardinality() ==
+         google::protobuf::Field_Cardinality_CARDINALITY_REPEATED;
+}
+
+ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field,
+                                           const google::protobuf::Type& type) {
+    WriteTag(field);
+  element_.reset(new ProtoElement(element_.release(), &field, type, false));
+  return this;
+}
+
+ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field,
+                                         const google::protobuf::Type& type) {
+  element_.reset(new ProtoElement(element_.release(), &field, type, true));
+  return this;
+}
+
+ProtoWriter* ProtoWriter::RenderPrimitiveField(
+    const google::protobuf::Field& field, const google::protobuf::Type& type,
+    const DataPiece& data) {
+  Status status;
+
+  // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
+  // error location reporting and required field accounting.
+  element_.reset(new ProtoElement(element_.release(), &field, type, false));
+
+  if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
+      field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+    InvalidValue(field.type_url().empty()
+                     ? google::protobuf::Field_Kind_Name(field.kind())
+                     : field.type_url(),
+                 data.ValueAsStringOrDefault(""));
+    element_.reset(element()->pop());
+    return this;
+  }
+
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_INT32: {
+      status = WriteInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+      status = WriteSFixed32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT32: {
+      status = WriteSInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED32: {
+      status = WriteFixed32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT32: {
+      status = WriteUInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT64: {
+      status = WriteInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+      status = WriteSFixed64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT64: {
+      status = WriteSInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED64: {
+      status = WriteFixed64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT64: {
+      status = WriteUInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+      status = WriteDouble(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FLOAT: {
+      status = WriteFloat(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BOOL: {
+      status = WriteBool(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      status = WriteBytes(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_STRING: {
+      status = WriteString(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_ENUM: {
+      status = WriteEnum(field.number(), data,
+                         typeinfo_->GetEnumByTypeUrl(field.type_url()),
+                         stream_.get());
+      break;
+    }
+    default:  // TYPE_GROUP or TYPE_MESSAGE
+      status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie());
+  }
+
+  if (!status.ok()) {
+    InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
+                 status.error_message());
+  }
+
+  element_.reset(element()->pop());
+  return this;
+}
+
+const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name,
+                                                       bool is_list) {
+  if (invalid_depth_ > 0) {
+    ++invalid_depth_;
+    return NULL;
+  }
+  const google::protobuf::Field* field = Lookup(name);
+  if (field == NULL) {
+    ++invalid_depth_;
+    // InvalidName() already called in Lookup().
+    return NULL;
+  }
+  if (is_list && !IsRepeated(*field)) {
+    ++invalid_depth_;
+    InvalidName(name, "Proto field is not repeating, cannot start list.");
+    return NULL;
+  }
+  return field;
+}
+
+const google::protobuf::Field* ProtoWriter::Lookup(
+    StringPiece unnormalized_name) {
+  ProtoElement* e = element();
+  if (e == NULL) {
+    InvalidName(unnormalized_name, "Root element must be a message.");
+    return NULL;
+  }
+  if (unnormalized_name.empty()) {
+    // Objects in repeated field inherit the same field descriptor.
+    if (e->parent_field() == NULL) {
+      InvalidName(unnormalized_name, "Proto fields must have a name.");
+    } else if (!IsRepeated(*e->parent_field())) {
+      InvalidName(unnormalized_name, "Proto fields must have a name.");
+      return NULL;
+    }
+    return e->parent_field();
+  }
+  const google::protobuf::Field* field =
+      typeinfo_->FindField(&e->type(), unnormalized_name);
+  if (field == NULL) InvalidName(unnormalized_name, "Cannot find field.");
+  return field;
+}
+
+const google::protobuf::Type* ProtoWriter::LookupType(
+    const google::protobuf::Field* field) {
+  return ((field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE ||
+           field->kind() == google::protobuf::Field_Kind_TYPE_GROUP)
+              ? typeinfo_->GetTypeByTypeUrl(field->type_url())
+              : &element_->type());
+}
+
+void ProtoWriter::WriteRootMessage() {
+  GOOGLE_DCHECK(!done_);
+  int curr_pos = 0;
+  // Calls the destructor of CodedOutputStream to remove any uninitialized
+  // memory from the Cord before we read it.
+  stream_.reset(NULL);
+  const void* data;
+  int length;
+  google::protobuf::io::ArrayInputStream input_stream(buffer_.data(), buffer_.size());
+  while (input_stream.Next(&data, &length)) {
+    if (length == 0) continue;
+    int num_bytes = length;
+    // Write up to where we need to insert the size field.
+    // The number of bytes we may write is the smaller of:
+    //   - the current fragment size
+    //   - the distance to the next position where a size field needs to be
+    //     inserted.
+    if (!size_insert_.empty() &&
+        size_insert_.front().pos - curr_pos < num_bytes) {
+      num_bytes = size_insert_.front().pos - curr_pos;
+    }
+    output_->Append(static_cast<const char*>(data), num_bytes);
+    if (num_bytes < length) {
+      input_stream.BackUp(length - num_bytes);
+    }
+    curr_pos += num_bytes;
+    // Insert the size field.
+    //   size_insert_.front():      the next <index, size> pair to be written.
+    //   size_insert_.front().pos:  position of the size field.
+    //   size_insert_.front().size: the size (integer) to be inserted.
+    if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) {
+      // Varint32 occupies at most 10 bytes.
+      uint8 insert_buffer[10];
+      uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
+          size_insert_.front().size, insert_buffer);
+      output_->Append(reinterpret_cast<const char*>(insert_buffer),
+                      insert_buffer_pos - insert_buffer);
+      size_insert_.pop_front();
+    }
+  }
+  output_->Flush();
+  stream_.reset(new CodedOutputStream(&adapter_));
+  done_ = true;
+}
+
+void ProtoWriter::WriteTag(const google::protobuf::Field& field) {
+  WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+      static_cast<WireFormatLite::FieldType>(field.kind()));
+  stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type));
+}
+
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.h
new file mode 100644
index 0000000..957565e
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/proto_writer.h
@@ -0,0 +1,330 @@
+// 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_UTIL_CONVERTER_PROTO_WRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
+
+#include <deque>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/datapiece.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/structured_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class CodedOutputStream;
+}  // namespace io
+}  // namespace protobuf
+
+
+namespace protobuf {
+class Type;
+class Field;
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectLocationTracker;
+
+// An ObjectWriter that can write protobuf bytes directly from writer events.
+// This class does not support special types like Struct or Map. However, since
+// this class supports raw protobuf, it can be used to provide support for
+// special types by inheriting from it or by wrapping it.
+//
+// It also supports streaming.
+class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
+ public:
+// Constructor. Does not take ownership of any parameter passed in.
+  ProtoWriter(TypeResolver* type_resolver, const google::protobuf::Type& type,
+              strings::ByteSink* output, ErrorListener* listener);
+  virtual ~ProtoWriter();
+
+  // ObjectWriter methods.
+  virtual ProtoWriter* StartObject(StringPiece name);
+  virtual ProtoWriter* EndObject();
+  virtual ProtoWriter* StartList(StringPiece name);
+  virtual ProtoWriter* EndList();
+  virtual ProtoWriter* RenderBool(StringPiece name, bool value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderInt32(StringPiece name, int32 value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderUint32(StringPiece name, uint32 value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderInt64(StringPiece name, int64 value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderUint64(StringPiece name, uint64 value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderDouble(StringPiece name, double value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderFloat(StringPiece name, float value) {
+    return RenderDataPiece(name, DataPiece(value));
+  }
+  virtual ProtoWriter* RenderString(StringPiece name, StringPiece value) {
+    return RenderDataPiece(name,
+                           DataPiece(value, use_strict_base64_decoding()));
+  }
+  virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) {
+    return RenderDataPiece(
+        name, DataPiece(value, false, use_strict_base64_decoding()));
+  }
+  virtual ProtoWriter* RenderNull(StringPiece name) {
+    return RenderDataPiece(name, DataPiece::NullData());
+  }
+
+  // Renders a DataPiece 'value' into a field whose wire type is determined
+  // from the given field 'name'.
+  virtual ProtoWriter* RenderDataPiece(StringPiece name,
+                                       const DataPiece& value);
+
+  // Returns the location tracker to use for tracking locations for errors.
+  const LocationTrackerInterface& location() {
+    return element_ != NULL ? *element_ : *tracker_;
+  }
+
+  // When true, we finished writing to output a complete message.
+  bool done() { return done_; }
+
+  // Returns the proto stream object.
+  google::protobuf::io::CodedOutputStream* stream() { return stream_.get(); }
+
+  // Getters and mutators of invalid_depth_.
+  void IncrementInvalidDepth() { ++invalid_depth_; }
+  void DecrementInvalidDepth() { --invalid_depth_; }
+  int invalid_depth() { return invalid_depth_; }
+
+  ErrorListener* listener() { return listener_; }
+
+  const TypeInfo* typeinfo() { return typeinfo_; }
+
+ protected:
+  class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface {
+   public:
+    // Constructor for the root element. No parent nor field.
+    ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type,
+                 ProtoWriter* enclosing);
+
+    // Constructor for a field of an element.
+    ProtoElement(ProtoElement* parent, const google::protobuf::Field* field,
+                 const google::protobuf::Type& type, bool is_list);
+
+    virtual ~ProtoElement() {}
+
+    // Called just before the destructor for clean up:
+    //   - reports any missing required fields
+    //   - computes the space needed by the size field, and augment the
+    //     length of all parent messages by this additional space.
+    //   - releases and returns the parent pointer.
+    ProtoElement* pop();
+
+    // Accessors
+    // parent_field() may be NULL if we are at root.
+    const google::protobuf::Field* parent_field() const {
+      return parent_field_;
+    }
+    const google::protobuf::Type& type() const { return type_; }
+
+    // Registers field for accounting required fields.
+    void RegisterField(const google::protobuf::Field* field);
+
+    // To report location on error messages.
+    virtual string ToString() const;
+
+    virtual ProtoElement* parent() const {
+      return static_cast<ProtoElement*>(BaseElement::parent());
+    }
+
+    // Returns true if the index is already taken by a preceeding oneof input.
+    bool IsOneofIndexTaken(int32 index);
+
+    // Marks the oneof 'index' as taken. Future inputs to this oneof will
+    // generate an error.
+    void TakeOneofIndex(int32 index);
+
+   private:
+    // Used for access to variables of the enclosing instance of
+    // ProtoWriter.
+    ProtoWriter* ow_;
+
+    // Describes the element as a field in the parent message.
+    // parent_field_ is NULL if and only if this element is the root element.
+    const google::protobuf::Field* parent_field_;
+
+    // TypeInfo to lookup types.
+    const TypeInfo* typeinfo_;
+
+    // Additional variables if this element is a message:
+    // (Root element is always a message).
+    // type_             : the type of this element.
+    // required_fields_  : set of required fields.
+    // size_index_       : index into ProtoWriter::size_insert_
+    //                     for later insertion of serialized message length.
+    const google::protobuf::Type& type_;
+    std::set<const google::protobuf::Field*> required_fields_;
+    const int size_index_;
+
+    // Tracks position in repeated fields, needed for LocationTrackerInterface.
+    int array_index_;
+
+    // Set of oneof indices already seen for the type_. Used to validate
+    // incoming messages so no more than one oneof is set.
+    hash_set<int32> oneof_indices_;
+
+    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
+  };
+
+  // Container for inserting 'size' information at the 'pos' position.
+  struct SizeInfo {
+    const int pos;
+    int size;
+  };
+
+  ProtoWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type,
+              strings::ByteSink* output, ErrorListener* listener);
+
+  virtual ProtoElement* element() { return element_.get(); }
+
+  // Helper methods for calling ErrorListener. See error_listener.h.
+  void InvalidName(StringPiece unknown_name, StringPiece message);
+  void InvalidValue(StringPiece type_name, StringPiece value);
+  void MissingField(StringPiece missing_name);
+
+  // Common code for BeginObject() and BeginList() that does invalid_depth_
+  // bookkeeping associated with name lookup.
+  const google::protobuf::Field* BeginNamed(StringPiece name, bool is_list);
+
+  // Lookup the field in the current element. Looks in the base descriptor
+  // and in any extension. This will report an error if the field cannot be
+  // found or if multiple matching extensions are found.
+  const google::protobuf::Field* Lookup(StringPiece name);
+
+  // Lookup the field type in the type descriptor. Returns NULL if the type
+  // is not known.
+  const google::protobuf::Type* LookupType(
+      const google::protobuf::Field* field);
+
+  // Write serialized output to the final output ByteSink, inserting all
+  // the size information for nested messages that are missing from the
+  // intermediate Cord buffer.
+  void WriteRootMessage();
+
+  // Helper method to write proto tags based on the given field.
+  void WriteTag(const google::protobuf::Field& field);
+
+
+  // Returns true if the field for type_ can be set as a oneof. If field is not
+  // a oneof type, this function does nothing and returns true.
+  // If another field for this oneof is already set, this function returns
+  // false. It also calls the appropriate error callback.
+  // unnormalized_name is used for error string.
+  bool ValidOneof(const google::protobuf::Field& field,
+                  StringPiece unnormalized_name);
+
+  // Returns true if the field is repeated.
+  bool IsRepeated(const google::protobuf::Field& field);
+
+  // Starts an object given the field and the enclosing type.
+  ProtoWriter* StartObjectField(const google::protobuf::Field& field,
+                                const google::protobuf::Type& type);
+
+  // Starts a list given the field and the enclosing type.
+  ProtoWriter* StartListField(const google::protobuf::Field& field,
+                              const google::protobuf::Type& type);
+
+  // Renders a primitve field given the field and the enclosing type.
+  ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field,
+                                    const google::protobuf::Type& type,
+                                    const DataPiece& value);
+
+ private:
+  // Variables for describing the structure of the input tree:
+  // master_type_: descriptor for the whole protobuf message.
+  // typeinfo_ : the TypeInfo object to lookup types.
+  const google::protobuf::Type& master_type_;
+  const TypeInfo* typeinfo_;
+  // Whether we own the typeinfo_ object.
+  bool own_typeinfo_;
+
+  // Indicates whether we finished writing root message completely.
+  bool done_;
+
+  // Variable for internal state processing:
+  // element_    : the current element.
+  // size_insert_: sizes of nested messages.
+  //               pos  - position to insert the size field.
+  //               size - size value to be inserted.
+  google::protobuf::scoped_ptr<ProtoElement> element_;
+  std::deque<SizeInfo> size_insert_;
+
+  // Variables for output generation:
+  // output_  : pointer to an external ByteSink for final user-visible output.
+  // buffer_  : buffer holding partial message before being ready for output_.
+  // adapter_ : internal adapter between CodedOutputStream and buffer_.
+  // stream_  : wrapper for writing tags and other encodings in wire format.
+  strings::ByteSink* output_;
+  string buffer_;
+  google::protobuf::io::StringOutputStream adapter_;
+  google::protobuf::scoped_ptr<google::protobuf::io::CodedOutputStream> stream_;
+
+  // Variables for error tracking and reporting:
+  // listener_     : a place to report any errors found.
+  // invalid_depth_: number of enclosing invalid nested messages.
+  // tracker_      : the root location tracker interface.
+  ErrorListener* listener_;
+  int invalid_depth_;
+  google::protobuf::scoped_ptr<LocationTrackerInterface> tracker_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.cc
new file mode 100644
index 0000000..1f3781a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -0,0 +1,1108 @@
+// 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.
+
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+
+#include <utility>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/util/internal/field_mask_utility.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+using util::StatusOr;
+namespace error {
+using util::error::Code;
+using util::error::INTERNAL;
+}
+namespace converter {
+
+using google::protobuf::Descriptor;
+using google::protobuf::EnumValueDescriptor;
+using google::protobuf::FieldDescriptor;
+using google::protobuf::internal::WireFormat;
+using google::protobuf::internal::WireFormatLite;
+using util::Status;
+using util::StatusOr;
+
+namespace {
+
+static int kDefaultMaxRecursionDepth = 64;
+
+// Finds a field with the given number. NULL if none found.
+const google::protobuf::Field* FindFieldByNumber(
+    const google::protobuf::Type& type, int number);
+
+// Returns true if the field is packable.
+bool IsPackable(const google::protobuf::Field& field);
+
+// Finds an enum value with the given number. NULL if none found.
+const google::protobuf::EnumValue* FindEnumValueByNumber(
+    const google::protobuf::Enum& tech_enum, int number);
+
+// Utility function to format nanos.
+const string FormatNanos(uint32 nanos);
+
+StatusOr<string> MapKeyDefaultValueAsString(
+    const google::protobuf::Field& field) {
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_BOOL:
+      return string("false");
+    case google::protobuf::Field_Kind_TYPE_INT32:
+    case google::protobuf::Field_Kind_TYPE_INT64:
+    case google::protobuf::Field_Kind_TYPE_UINT32:
+    case google::protobuf::Field_Kind_TYPE_UINT64:
+    case google::protobuf::Field_Kind_TYPE_SINT32:
+    case google::protobuf::Field_Kind_TYPE_SINT64:
+    case google::protobuf::Field_Kind_TYPE_SFIXED32:
+    case google::protobuf::Field_Kind_TYPE_SFIXED64:
+    case google::protobuf::Field_Kind_TYPE_FIXED32:
+    case google::protobuf::Field_Kind_TYPE_FIXED64:
+      return string("0");
+    case google::protobuf::Field_Kind_TYPE_STRING:
+      return string();
+    default:
+      return Status(util::error::INTERNAL, "Invalid map key type.");
+  }
+}
+}  // namespace
+
+
+ProtoStreamObjectSource::ProtoStreamObjectSource(
+    google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver,
+    const google::protobuf::Type& type)
+    : stream_(stream),
+      typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+      own_typeinfo_(true),
+      type_(type),
+      use_lower_camel_for_enums_(false),
+      recursion_depth_(0),
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
+  GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
+}
+
+ProtoStreamObjectSource::ProtoStreamObjectSource(
+    google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
+    const google::protobuf::Type& type)
+    : stream_(stream),
+      typeinfo_(typeinfo),
+      own_typeinfo_(false),
+      type_(type),
+      use_lower_camel_for_enums_(false),
+      recursion_depth_(0),
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
+  GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
+}
+
+ProtoStreamObjectSource::~ProtoStreamObjectSource() {
+  if (own_typeinfo_) {
+    delete typeinfo_;
+  }
+}
+
+Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
+                                             ObjectWriter* ow) const {
+  return WriteMessage(type_, name, 0, true, ow);
+}
+
+const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField(
+    const google::protobuf::Type& type, uint32 tag) const {
+  // Lookup the new field in the type by tag number.
+  const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3);
+  // Verify if the field corresponds to the wire type in tag.
+  // If there is any discrepancy, mark the field as not found.
+  if (field != NULL) {
+    WireFormatLite::WireType expected_type =
+        WireFormatLite::WireTypeForFieldType(
+            static_cast<WireFormatLite::FieldType>(field->kind()));
+    WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag);
+    if (actual_type != expected_type &&
+        (!IsPackable(*field) ||
+         actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
+      field = NULL;
+    }
+  }
+  return field;
+}
+
+Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
+                                             StringPiece name,
+                                             const uint32 end_tag,
+                                             bool include_start_and_end,
+                                             ObjectWriter* ow) const {
+
+    const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
+    if (type_renderer != NULL) {
+      return (*type_renderer)(this, type, name, ow);
+    }
+
+  const google::protobuf::Field* field = NULL;
+  string field_name;
+  // last_tag set to dummy value that is different from tag.
+  uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
+
+  if (include_start_and_end) {
+    ow->StartObject(name);
+  }
+  while (tag != end_tag) {
+    if (tag != last_tag) {  // Update field only if tag is changed.
+      last_tag = tag;
+      field = FindAndVerifyField(type, tag);
+      if (field != NULL) {
+        field_name = field->json_name();
+      }
+    }
+    if (field == NULL) {
+      // If we didn't find a field, skip this unknown tag.
+      // TODO(wpoon): Check return boolean value.
+      WireFormat::SkipField(stream_, tag, NULL);
+      tag = stream_->ReadTag();
+      continue;
+    }
+
+    if (field->cardinality() ==
+        google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+      bool check_maps = true;
+
+      if (check_maps && IsMap(*field)) {
+        ow->StartObject(field_name);
+        ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow));
+        ow->EndObject();
+      } else {
+        ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow));
+      }
+    } else {
+      // Render the field.
+      RETURN_IF_ERROR(RenderField(field, field_name, ow));
+      tag = stream_->ReadTag();
+    }
+  }
+  if (include_start_and_end) {
+    ow->EndObject();
+  }
+  return Status::OK;
+}
+
+StatusOr<uint32> ProtoStreamObjectSource::RenderList(
+    const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
+    ObjectWriter* ow) const {
+  uint32 tag_to_return = 0;
+  ow->StartList(name);
+  if (IsPackable(*field) &&
+      list_tag ==
+          WireFormatLite::MakeTag(field->number(),
+                                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
+    RETURN_IF_ERROR(RenderPacked(field, ow));
+    // Since packed fields have a single tag, read another tag from stream to
+    // return.
+    tag_to_return = stream_->ReadTag();
+  } else {
+    do {
+      RETURN_IF_ERROR(RenderField(field, "", ow));
+    } while ((tag_to_return = stream_->ReadTag()) == list_tag);
+  }
+  ow->EndList();
+  return tag_to_return;
+}
+
+StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
+    const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
+    ObjectWriter* ow) const {
+  const google::protobuf::Type* field_type =
+      typeinfo_->GetTypeByTypeUrl(field->type_url());
+  uint32 tag_to_return = 0;
+  do {
+    // Render map entry message type.
+    uint32 buffer32;
+    stream_->ReadVarint32(&buffer32);  // message length
+    int old_limit = stream_->PushLimit(buffer32);
+    string map_key;
+    for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+      const google::protobuf::Field* field =
+          FindAndVerifyField(*field_type, tag);
+      if (field == NULL) {
+        WireFormat::SkipField(stream_, tag, NULL);
+        continue;
+      }
+      // Map field numbers are key = 1 and value = 2
+      if (field->number() == 1) {
+        map_key = ReadFieldValueAsString(*field);
+      } else if (field->number() == 2) {
+        if (map_key.empty()) {
+          // An absent map key is treated as the default.
+          const google::protobuf::Field* key_field =
+              FindFieldByNumber(*field_type, 1);
+          if (key_field == NULL) {
+            // The Type info for this map entry is incorrect. It should always
+            // have a field named "key" and with field number 1.
+            return Status(util::error::INTERNAL, "Invalid map entry.");
+          }
+          ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
+        }
+        RETURN_IF_ERROR(RenderField(field, map_key, ow));
+      } else {
+        // The Type info for this map entry is incorrect. It should contain
+        // exactly two fields with field number 1 and 2.
+        return Status(util::error::INTERNAL, "Invalid map entry.");
+      }
+    }
+    stream_->PopLimit(old_limit);
+  } while ((tag_to_return = stream_->ReadTag()) == list_tag);
+  return tag_to_return;
+}
+
+Status ProtoStreamObjectSource::RenderPacked(
+    const google::protobuf::Field* field, ObjectWriter* ow) const {
+  uint32 length;
+  stream_->ReadVarint32(&length);
+  int old_limit = stream_->PushLimit(length);
+  while (stream_->BytesUntilLimit() > 0) {
+    RETURN_IF_ERROR(RenderField(field, StringPiece(), ow));
+  }
+  stream_->PopLimit(old_limit);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderTimestamp(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  pair<int64, int32> p = os->ReadSecondsAndNanos(type);
+  int64 seconds = p.first;
+  int32 nanos = p.second;
+  if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
+    return Status(
+        util::error::INTERNAL,
+        StrCat("Timestamp seconds exceeds limit for field: ", field_name));
+  }
+
+  if (nanos < 0 || nanos >= kNanosPerSecond) {
+    return Status(
+        util::error::INTERNAL,
+        StrCat("Timestamp nanos exceeds limit for field: ", field_name));
+  }
+
+  ow->RenderString(field_name,
+                   ::google::protobuf::internal::FormatTime(seconds, nanos));
+
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderDuration(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  pair<int64, int32> p = os->ReadSecondsAndNanos(type);
+  int64 seconds = p.first;
+  int32 nanos = p.second;
+  if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
+    return Status(
+        util::error::INTERNAL,
+        StrCat("Duration seconds exceeds limit for field: ", field_name));
+  }
+
+  if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+    return Status(
+        util::error::INTERNAL,
+        StrCat("Duration nanos exceeds limit for field: ", field_name));
+  }
+
+  string sign = "";
+  if (seconds < 0) {
+    if (nanos > 0) {
+      return Status(util::error::INTERNAL,
+                    StrCat("Duration nanos is non-negative, but seconds is "
+                           "negative for field: ",
+                           field_name));
+    }
+    sign = "-";
+    seconds = -seconds;
+    nanos = -nanos;
+  } else if (seconds == 0 && nanos < 0) {
+    sign = "-";
+    nanos = -nanos;
+  }
+  string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds,
+                                           FormatNanos(nanos).c_str());
+  ow->RenderString(field_name, formatted_duration);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os,
+                                             const google::protobuf::Type& type,
+                                             StringPiece field_name,
+                                             ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint64 buffer64 = 0;  // default value of Double wrapper value
+  if (tag != 0) {
+    os->stream_->ReadLittleEndian64(&buffer64);
+    os->stream_->ReadTag();
+  }
+  ow->RenderDouble(field_name, bit_cast<double>(buffer64));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece field_name,
+                                            ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint32 buffer32 = 0;  // default value of Float wrapper value
+  if (tag != 0) {
+    os->stream_->ReadLittleEndian32(&buffer32);
+    os->stream_->ReadTag();
+  }
+  ow->RenderFloat(field_name, bit_cast<float>(buffer32));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece field_name,
+                                            ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint64 buffer64 = 0;  // default value of Int64 wrapper value
+  if (tag != 0) {
+    os->stream_->ReadVarint64(&buffer64);
+    os->stream_->ReadTag();
+  }
+  ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os,
+                                             const google::protobuf::Type& type,
+                                             StringPiece field_name,
+                                             ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint64 buffer64 = 0;  // default value of UInt64 wrapper value
+  if (tag != 0) {
+    os->stream_->ReadVarint64(&buffer64);
+    os->stream_->ReadTag();
+  }
+  ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece field_name,
+                                            ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint32 buffer32 = 0;  // default value of Int32 wrapper value
+  if (tag != 0) {
+    os->stream_->ReadVarint32(&buffer32);
+    os->stream_->ReadTag();
+  }
+  ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os,
+                                             const google::protobuf::Type& type,
+                                             StringPiece field_name,
+                                             ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint32 buffer32 = 0;  // default value of UInt32 wrapper value
+  if (tag != 0) {
+    os->stream_->ReadVarint32(&buffer32);
+    os->stream_->ReadTag();
+  }
+  ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os,
+                                           const google::protobuf::Type& type,
+                                           StringPiece field_name,
+                                           ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint64 buffer64 = 0;  // results in 'false' value as default, which is the
+                        // default value of Bool wrapper
+  if (tag != 0) {
+    os->stream_->ReadVarint64(&buffer64);
+    os->stream_->ReadTag();
+  }
+  ow->RenderBool(field_name, buffer64 != 0);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os,
+                                             const google::protobuf::Type& type,
+                                             StringPiece field_name,
+                                             ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint32 buffer32;
+  string str;  // default value of empty for String wrapper
+  if (tag != 0) {
+    os->stream_->ReadVarint32(&buffer32);  // string size.
+    os->stream_->ReadString(&str, buffer32);
+    os->stream_->ReadTag();
+  }
+  ow->RenderString(field_name, str);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece field_name,
+                                            ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+  uint32 buffer32;
+  string str;
+  if (tag != 0) {
+    os->stream_->ReadVarint32(&buffer32);
+    os->stream_->ReadString(&str, buffer32);
+    os->stream_->ReadTag();
+  }
+  ow->RenderBytes(field_name, str);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os,
+                                             const google::protobuf::Type& type,
+                                             StringPiece field_name,
+                                             ObjectWriter* ow) {
+  const google::protobuf::Field* field = NULL;
+  uint32 tag = os->stream_->ReadTag();
+  ow->StartObject(field_name);
+  while (tag != 0) {
+    field = os->FindAndVerifyField(type, tag);
+    // google.protobuf.Struct has only one field that is a map. Hence we use
+    // RenderMap to render that field.
+    if (os->IsMap(*field)) {
+      ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow));
+    }
+  }
+  ow->EndObject();
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderStructValue(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  const google::protobuf::Field* field = NULL;
+  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+       tag = os->stream_->ReadTag()) {
+    field = os->FindAndVerifyField(type, tag);
+    if (field == NULL) {
+      WireFormat::SkipField(os->stream_, tag, NULL);
+      continue;
+    }
+    RETURN_IF_ERROR(os->RenderField(field, field_name, ow));
+  }
+  return Status::OK;
+}
+
+// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
+Status ProtoStreamObjectSource::RenderStructListValue(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32 tag = os->stream_->ReadTag();
+
+  // Render empty list when we find empty ListValue message.
+  if (tag == 0) {
+    ow->StartList(field_name);
+    ow->EndList();
+    return Status::OK;
+  }
+
+  while (tag != 0) {
+    const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+    if (field == NULL) {
+      WireFormat::SkipField(os->stream_, tag, NULL);
+      tag = os->stream_->ReadTag();
+      continue;
+    }
+    ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow));
+  }
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os,
+                                          const google::protobuf::Type& type,
+                                          StringPiece field_name,
+                                          ObjectWriter* ow) {
+  // An Any is of the form { string type_url = 1; bytes value = 2; }
+  uint32 tag;
+  string type_url;
+  string value;
+
+  // First read out the type_url and value from the proto stream
+  for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) {
+    const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+    if (field == NULL) {
+      WireFormat::SkipField(os->stream_, tag, NULL);
+      continue;
+    }
+    // 'type_url' has field number of 1 and 'value' has field number 2
+    // //google/protobuf/any.proto
+    if (field->number() == 1) {
+      // read type_url
+      uint32 type_url_size;
+      os->stream_->ReadVarint32(&type_url_size);
+      os->stream_->ReadString(&type_url, type_url_size);
+    } else if (field->number() == 2) {
+      // read value
+      uint32 value_size;
+      os->stream_->ReadVarint32(&value_size);
+      os->stream_->ReadString(&value, value_size);
+    }
+  }
+
+  // If there is no value, we don't lookup the type, we just output it (if
+  // present). If both type and value are empty we output an empty object.
+  if (value.empty()) {
+    ow->StartObject(field_name);
+    if (!type_url.empty()) {
+      ow->RenderString("@type", type_url);
+    }
+    ow->EndObject();
+    return util::Status::OK;
+  }
+
+  // If there is a value but no type, we cannot render it, so report an error.
+  if (type_url.empty()) {
+    // TODO(sven): Add an external message once those are ready.
+    return util::Status(util::error::INTERNAL,
+                        "Invalid Any, the type_url is missing.");
+  }
+
+  util::StatusOr<const google::protobuf::Type*> resolved_type =
+      os->typeinfo_->ResolveTypeUrl(type_url);
+
+  if (!resolved_type.ok()) {
+    // Convert into an internal error, since this means the backend gave us
+    // an invalid response (missing or invalid type information).
+    return util::Status(util::error::INTERNAL,
+                        resolved_type.status().error_message());
+  }
+  // nested_type cannot be null at this time.
+  const google::protobuf::Type* nested_type = resolved_type.ValueOrDie();
+
+  google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size());
+  google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream);
+  // We know the type so we can render it. Recursively parse the nested stream
+  // using a nested ProtoStreamObjectSource using our nested type information.
+  ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type);
+
+  // We manually call start and end object here so we can inject the @type.
+  ow->StartObject(field_name);
+  ow->RenderString("@type", type_url);
+  util::Status result =
+      nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow);
+  ow->EndObject();
+  return result;
+}
+
+Status ProtoStreamObjectSource::RenderFieldMask(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  string combined;
+  uint32 buffer32;
+  uint32 paths_field_tag = 0;
+  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+       tag = os->stream_->ReadTag()) {
+    if (paths_field_tag == 0) {
+      const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+      if (field != NULL && field->number() == 1 &&
+          field->name() == "paths") {
+        paths_field_tag = tag;
+      }
+    }
+    if (paths_field_tag != tag) {
+      return util::Status(util::error::INTERNAL,
+                          "Invalid FieldMask, unexpected field.");
+    }
+    string str;
+    os->stream_->ReadVarint32(&buffer32);  // string size.
+    os->stream_->ReadString(&str, buffer32);
+    if (!combined.empty()) {
+      combined.append(",");
+    }
+    combined.append(ConvertFieldMaskPath(str, &ToCamelCase));
+  }
+  ow->RenderString(field_name, combined);
+  return Status::OK;
+}
+
+
+hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
+    ProtoStreamObjectSource::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
+
+void ProtoStreamObjectSource::InitRendererMap() {
+  renderers_ = new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
+  (*renderers_)["google.protobuf.Timestamp"] =
+      &ProtoStreamObjectSource::RenderTimestamp;
+  (*renderers_)["google.protobuf.Duration"] =
+      &ProtoStreamObjectSource::RenderDuration;
+  (*renderers_)["google.protobuf.DoubleValue"] =
+      &ProtoStreamObjectSource::RenderDouble;
+  (*renderers_)["google.protobuf.FloatValue"] =
+      &ProtoStreamObjectSource::RenderFloat;
+  (*renderers_)["google.protobuf.Int64Value"] =
+      &ProtoStreamObjectSource::RenderInt64;
+  (*renderers_)["google.protobuf.UInt64Value"] =
+      &ProtoStreamObjectSource::RenderUInt64;
+  (*renderers_)["google.protobuf.Int32Value"] =
+      &ProtoStreamObjectSource::RenderInt32;
+  (*renderers_)["google.protobuf.UInt32Value"] =
+      &ProtoStreamObjectSource::RenderUInt32;
+  (*renderers_)["google.protobuf.BoolValue"] =
+      &ProtoStreamObjectSource::RenderBool;
+  (*renderers_)["google.protobuf.StringValue"] =
+      &ProtoStreamObjectSource::RenderString;
+  (*renderers_)["google.protobuf.BytesValue"] =
+      &ProtoStreamObjectSource::RenderBytes;
+  (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
+  (*renderers_)["google.protobuf.Struct"] =
+      &ProtoStreamObjectSource::RenderStruct;
+  (*renderers_)["google.protobuf.Value"] =
+      &ProtoStreamObjectSource::RenderStructValue;
+  (*renderers_)["google.protobuf.ListValue"] =
+      &ProtoStreamObjectSource::RenderStructListValue;
+  (*renderers_)["google.protobuf.FieldMask"] =
+      &ProtoStreamObjectSource::RenderFieldMask;
+  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectSource::DeleteRendererMap() {
+  delete ProtoStreamObjectSource::renderers_;
+  renderers_ = NULL;
+}
+
+// static
+ProtoStreamObjectSource::TypeRenderer*
+ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) {
+  ::google::protobuf::GoogleOnceInit(&source_renderers_init_, &InitRendererMap);
+  return FindOrNull(*renderers_, type_url);
+}
+
+Status ProtoStreamObjectSource::RenderField(
+    const google::protobuf::Field* field, StringPiece field_name,
+    ObjectWriter* ow) const {
+  // Short-circuit message types as it tends to call WriteMessage recursively
+  // and ends up using a lot of stack space. Keep the stack usage of this
+  // message small in order to preserve stack space and not crash.
+  if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+    uint32 buffer32;
+    stream_->ReadVarint32(&buffer32);  // message length
+    int old_limit = stream_->PushLimit(buffer32);
+    // Get the nested message type for this field.
+    const google::protobuf::Type* type =
+        typeinfo_->GetTypeByTypeUrl(field->type_url());
+    if (type == NULL) {
+      return Status(util::error::INTERNAL,
+                    StrCat("Invalid configuration. Could not find the type: ",
+                           field->type_url()));
+    }
+
+    // Short-circuit any special type rendering to save call-stack space.
+    const TypeRenderer* type_renderer = FindTypeRenderer(type->name());
+
+    bool use_type_renderer = type_renderer != NULL;
+
+    if (use_type_renderer) {
+      RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
+    } else {
+      RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
+      RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
+      --recursion_depth_;
+    }
+    if (!stream_->ConsumedEntireMessage()) {
+      return Status(util::error::INVALID_ARGUMENT,
+                    "Nested protocol message not parsed in its entirety.");
+    }
+    stream_->PopLimit(old_limit);
+  } else {
+    // Render all other non-message types.
+    return RenderNonMessageField(field, field_name, ow);
+  }
+  return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderNonMessageField(
+    const google::protobuf::Field* field, StringPiece field_name,
+    ObjectWriter* ow) const {
+  // Temporary buffers of different types.
+  uint32 buffer32;
+  uint64 buffer64;
+  string strbuffer;
+  switch (field->kind()) {
+    case google::protobuf::Field_Kind_TYPE_BOOL: {
+      stream_->ReadVarint64(&buffer64);
+      ow->RenderBool(field_name, buffer64 != 0);
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT32: {
+      stream_->ReadVarint32(&buffer32);
+      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT64: {
+      stream_->ReadVarint64(&buffer64);
+      ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT32: {
+      stream_->ReadVarint32(&buffer32);
+      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT64: {
+      stream_->ReadVarint64(&buffer64);
+      ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT32: {
+      stream_->ReadVarint32(&buffer32);
+      ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT64: {
+      stream_->ReadVarint64(&buffer64);
+      ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+      stream_->ReadLittleEndian32(&buffer32);
+      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+      stream_->ReadLittleEndian64(&buffer64);
+      ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED32: {
+      stream_->ReadLittleEndian32(&buffer32);
+      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED64: {
+      stream_->ReadLittleEndian64(&buffer64);
+      ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FLOAT: {
+      stream_->ReadLittleEndian32(&buffer32);
+      ow->RenderFloat(field_name, bit_cast<float>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+      stream_->ReadLittleEndian64(&buffer64);
+      ow->RenderDouble(field_name, bit_cast<double>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_ENUM: {
+      stream_->ReadVarint32(&buffer32);
+
+      // If the field represents an explicit NULL value, render null.
+      if (field->type_url() == kStructNullValueTypeUrl) {
+        ow->RenderNull(field_name);
+        break;
+      }
+
+      // Get the nested enum type for this field.
+      // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
+      // up.
+      const google::protobuf::Enum* en =
+          typeinfo_->GetEnumByTypeUrl(field->type_url());
+      // Lookup the name of the enum, and render that. Skips unknown enums.
+      if (en != NULL) {
+        const google::protobuf::EnumValue* enum_value =
+            FindEnumValueByNumber(*en, buffer32);
+        if (enum_value != NULL) {
+          if (use_lower_camel_for_enums_)
+            ow->RenderString(field_name, ToCamelCase(enum_value->name()));
+          else
+            ow->RenderString(field_name, enum_value->name());
+        }
+      } else {
+        GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url();
+      }
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_STRING: {
+      stream_->ReadVarint32(&buffer32);  // string size.
+      stream_->ReadString(&strbuffer, buffer32);
+      ow->RenderString(field_name, strbuffer);
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      stream_->ReadVarint32(&buffer32);  // bytes size.
+      stream_->ReadString(&strbuffer, buffer32);
+      ow->RenderBytes(field_name, strbuffer);
+      break;
+    }
+    default:
+      break;
+  }
+  return Status::OK;
+}
+
+// TODO(skarvaje): Fix this to avoid code duplication.
+const string ProtoStreamObjectSource::ReadFieldValueAsString(
+    const google::protobuf::Field& field) const {
+  string result;
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_BOOL: {
+      uint64 buffer64;
+      stream_->ReadVarint64(&buffer64);
+      result = buffer64 != 0 ? "true" : "false";
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT32: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);
+      result = SimpleItoa(bit_cast<int32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT64: {
+      uint64 buffer64;
+      stream_->ReadVarint64(&buffer64);
+      result = SimpleItoa(bit_cast<int64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT32: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);
+      result = SimpleItoa(bit_cast<uint32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT64: {
+      uint64 buffer64;
+      stream_->ReadVarint64(&buffer64);
+      result = SimpleItoa(bit_cast<uint64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT32: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);
+      result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT64: {
+      uint64 buffer64;
+      stream_->ReadVarint64(&buffer64);
+      result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+      uint32 buffer32;
+      stream_->ReadLittleEndian32(&buffer32);
+      result = SimpleItoa(bit_cast<int32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+      uint64 buffer64;
+      stream_->ReadLittleEndian64(&buffer64);
+      result = SimpleItoa(bit_cast<int64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED32: {
+      uint32 buffer32;
+      stream_->ReadLittleEndian32(&buffer32);
+      result = SimpleItoa(bit_cast<uint32>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED64: {
+      uint64 buffer64;
+      stream_->ReadLittleEndian64(&buffer64);
+      result = SimpleItoa(bit_cast<uint64>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FLOAT: {
+      uint32 buffer32;
+      stream_->ReadLittleEndian32(&buffer32);
+      result = SimpleFtoa(bit_cast<float>(buffer32));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+      uint64 buffer64;
+      stream_->ReadLittleEndian64(&buffer64);
+      result = SimpleDtoa(bit_cast<double>(buffer64));
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_ENUM: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);
+      // Get the nested enum type for this field.
+      // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
+      // up.
+      const google::protobuf::Enum* en =
+          typeinfo_->GetEnumByTypeUrl(field.type_url());
+      // Lookup the name of the enum, and render that. Skips unknown enums.
+      if (en != NULL) {
+        const google::protobuf::EnumValue* enum_value =
+            FindEnumValueByNumber(*en, buffer32);
+        if (enum_value != NULL) {
+          result = enum_value->name();
+        }
+      }
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_STRING: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);  // string size.
+      stream_->ReadString(&result, buffer32);
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      uint32 buffer32;
+      stream_->ReadVarint32(&buffer32);  // bytes size.
+      stream_->ReadString(&result, buffer32);
+      break;
+    }
+    default:
+      break;
+  }
+  return result;
+}
+
+// Field is a map if it is a repeated message and it has an option "map_type".
+// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly.
+bool ProtoStreamObjectSource::IsMap(
+    const google::protobuf::Field& field) const {
+  const google::protobuf::Type* field_type =
+      typeinfo_->GetTypeByTypeUrl(field.type_url());
+
+  // TODO(xiaofeng): Unify option names.
+  return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
+         (GetBoolOptionOrDefault(field_type->options(),
+                                 "google.protobuf.MessageOptions.map_entry", false) ||
+          GetBoolOptionOrDefault(field_type->options(), "map_entry", false));
+}
+
+std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
+    const google::protobuf::Type& type) const {
+  uint64 seconds = 0;
+  uint32 nanos = 0;
+  uint32 tag = 0;
+  int64 signed_seconds = 0;
+  int32 signed_nanos = 0;
+
+  for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+    const google::protobuf::Field* field = FindAndVerifyField(type, tag);
+    if (field == NULL) {
+      WireFormat::SkipField(stream_, tag, NULL);
+      continue;
+    }
+    // 'seconds' has field number of 1 and 'nanos' has field number 2
+    // //google/protobuf/timestamp.proto & duration.proto
+    if (field->number() == 1) {
+      // read seconds
+      stream_->ReadVarint64(&seconds);
+      signed_seconds = bit_cast<int64>(seconds);
+    } else if (field->number() == 2) {
+      // read nanos
+      stream_->ReadVarint32(&nanos);
+      signed_nanos = bit_cast<int32>(nanos);
+    }
+  }
+  return std::pair<int64, int32>(signed_seconds, signed_nanos);
+}
+
+Status ProtoStreamObjectSource::IncrementRecursionDepth(
+    StringPiece type_name, StringPiece field_name) const {
+  if (++recursion_depth_ > max_recursion_depth_) {
+    return Status(
+        util::error::INVALID_ARGUMENT,
+        StrCat("Message too deep. Max recursion depth reached for type '",
+               type_name, "', field '", field_name, "'"));
+  }
+  return Status::OK;
+}
+
+namespace {
+// TODO(skarvaje): Speed this up by not doing a linear scan.
+const google::protobuf::Field* FindFieldByNumber(
+    const google::protobuf::Type& type, int number) {
+  for (int i = 0; i < type.fields_size(); ++i) {
+    if (type.fields(i).number() == number) {
+      return &type.fields(i);
+    }
+  }
+  return NULL;
+}
+
+// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable()
+// using tech Field.
+bool IsPackable(const google::protobuf::Field& field) {
+  return field.cardinality() ==
+             google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+         google::protobuf::FieldDescriptor::IsTypePackable(
+             static_cast<google::protobuf::FieldDescriptor::Type>(field.kind()));
+}
+
+// TODO(skarvaje): Speed this up by not doing a linear scan.
+const google::protobuf::EnumValue* FindEnumValueByNumber(
+    const google::protobuf::Enum& tech_enum, int number) {
+  for (int i = 0; i < tech_enum.enumvalue_size(); ++i) {
+    const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i);
+    if (ev.number() == number) {
+      return &ev;
+    }
+  }
+  return NULL;
+}
+
+// TODO(skarvaje): Look into optimizing this by not doing computation on
+// double.
+const string FormatNanos(uint32 nanos) {
+  const char* format =
+      (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f";
+  string formatted =
+      StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond);
+  // remove the leading 0 before decimal.
+  return formatted.substr(1);
+}
+}  // namespace
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.h
new file mode 100644
index 0000000..d7d4347
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -0,0 +1,298 @@
+// 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_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
+
+#include <functional>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/internal/object_source.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+class Field;
+class Type;
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class TypeInfo;
+
+// An ObjectSource that can parse a stream of bytes as a protocol buffer.
+// Its WriteTo() method can be given an ObjectWriter.
+// This implementation uses a google.protobuf.Type for tag and name lookup.
+// The field names are converted into lower camel-case when writing to the
+// ObjectWriter.
+//
+// Sample usage: (suppose input is: string proto)
+//   ArrayInputStream arr_stream(proto.data(), proto.size());
+//   CodedInputStream in_stream(&arr_stream);
+//   ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
+//                              <your message google::protobuf::Type>);
+//
+//   Status status = os.WriteTo(<some ObjectWriter>);
+class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
+ public:
+  ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
+                          TypeResolver* type_resolver,
+                          const google::protobuf::Type& type);
+
+  virtual ~ProtoStreamObjectSource();
+
+  virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
+
+  // Sets whether or not to use lowerCamelCase casing for enum values. If set to
+  // false, enum values are output without any case conversions.
+  //
+  // For example, if we have an enum:
+  // enum Type {
+  //   ACTION_AND_ADVENTURE = 1;
+  // }
+  // Type type = 20;
+  //
+  // And this option is set to true. Then the rendered "type" field will have
+  // the string "actionAndAdventure".
+  // {
+  //   ...
+  //   "type": "actionAndAdventure",
+  //   ...
+  // }
+  //
+  // If set to false, the rendered "type" field will have the string
+  // "ACTION_AND_ADVENTURE".
+  // {
+  //   ...
+  //   "type": "ACTION_AND_ADVENTURE",
+  //   ...
+  // }
+  void set_use_lower_camel_for_enums(bool value) {
+    use_lower_camel_for_enums_ = value;
+  }
+
+  // Sets the max recursion depth of proto message to be deserialized. Proto
+  // messages over this depth will fail to be deserialized.
+  // Default value is 64.
+  void set_max_recursion_depth(int max_depth) {
+    max_recursion_depth_ = max_depth;
+  }
+
+ protected:
+  // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
+  // found this method will complete, allowing it to be used for parsing both
+  // nested messages (end with 0) and nested groups (end with group end tag).
+  // The include_start_and_end parameter allows this method to be called when
+  // already inside of an object, and skip calling StartObject and EndObject.
+  virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
+                                      StringPiece name, const uint32 end_tag,
+                                      bool include_start_and_end,
+                                      ObjectWriter* ow) const;
+
+ private:
+  ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
+                          const TypeInfo* typeinfo,
+                          const google::protobuf::Type& type);
+  // Function that renders a well known type with a modified behavior.
+  typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
+                                         const google::protobuf::Type&,
+                                         StringPiece, ObjectWriter*);
+
+  // Looks up a field and verify its consistency with wire type in tag.
+  const google::protobuf::Field* FindAndVerifyField(
+      const google::protobuf::Type& type, uint32 tag) const;
+
+  // TODO(skarvaje): Mark these methods as non-const as they modify internal
+  // state (stream_).
+  //
+  // Renders a repeating field (packed or unpacked).
+  // Returns the next tag after reading all sequential repeating elements. The
+  // caller should use this tag before reading more tags from the stream.
+  util::StatusOr<uint32> RenderList(const google::protobuf::Field* field,
+                                      StringPiece name, uint32 list_tag,
+                                      ObjectWriter* ow) const;
+  // Renders a NWP map.
+  // Returns the next tag after reading all map entries. The caller should use
+  // this tag before reading more tags from the stream.
+  util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
+                                     StringPiece name, uint32 list_tag,
+                                     ObjectWriter* ow) const;
+
+  // Renders a packed repeating field. A packed field is stored as:
+  // {tag length item1 item2 item3} instead of the less efficient
+  // {tag item1 tag item2 tag item3}.
+  util::Status RenderPacked(const google::protobuf::Field* field,
+                              ObjectWriter* ow) const;
+
+  // Renders a google.protobuf.Timestamp value to ObjectWriter
+  static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
+                                        const google::protobuf::Type& type,
+                                        StringPiece name, ObjectWriter* ow);
+
+  // Renders a google.protobuf.Duration value to ObjectWriter
+  static util::Status RenderDuration(const ProtoStreamObjectSource* os,
+                                       const google::protobuf::Type& type,
+                                       StringPiece name, ObjectWriter* ow);
+
+  // Following RenderTYPE functions render well known types in
+  // google/protobuf/wrappers.proto corresponding to TYPE.
+  static util::Status RenderDouble(const ProtoStreamObjectSource* os,
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
+  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
+                                    const google::protobuf::Type& type,
+                                    StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
+                                    const google::protobuf::Type& type,
+                                    StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
+                                    const google::protobuf::Type& type,
+                                    StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
+  static util::Status RenderBool(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+  static util::Status RenderString(const ProtoStreamObjectSource* os,
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
+  static util::Status RenderBytes(const ProtoStreamObjectSource* os,
+                                    const google::protobuf::Type& type,
+                                    StringPiece name, ObjectWriter* ow);
+
+  // Renders a google.protobuf.Struct to ObjectWriter.
+  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
+
+  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
+  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
+                                          const google::protobuf::Type& type,
+                                          StringPiece name, ObjectWriter* ow);
+
+  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
+  static util::Status RenderStructListValue(
+      const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+      StringPiece name, ObjectWriter* ow);
+
+  // Render the "Any" type.
+  static util::Status RenderAny(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+
+  // Render the "FieldMask" type.
+  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+                                        const google::protobuf::Type& type,
+                                        StringPiece name, ObjectWriter* ow);
+
+  static hash_map<string, TypeRenderer>* renderers_;
+  static void InitRendererMap();
+  static void DeleteRendererMap();
+  static TypeRenderer* FindTypeRenderer(const string& type_url);
+
+  // Renders a field value to the ObjectWriter.
+  util::Status RenderField(const google::protobuf::Field* field,
+                             StringPiece field_name, ObjectWriter* ow) const;
+
+  // Same as above but renders all non-message field types. Callers don't call
+  // this function directly. They just use RenderField.
+  util::Status RenderNonMessageField(const google::protobuf::Field* field,
+                                       StringPiece field_name,
+                                       ObjectWriter* ow) const;
+
+
+  // Reads field value according to Field spec in 'field' and returns the read
+  // value as string. This only works for primitive datatypes (no message
+  // types).
+  const string ReadFieldValueAsString(
+      const google::protobuf::Field& field) const;
+
+  // Utility function to detect proto maps. The 'field' MUST be repeated.
+  bool IsMap(const google::protobuf::Field& field) const;
+
+  // Utility to read int64 and int32 values from a message type in stream_.
+  // Used for reading google.protobuf.Timestamp and Duration messages.
+  std::pair<int64, int32> ReadSecondsAndNanos(
+      const google::protobuf::Type& type) const;
+
+  // Helper function to check recursion depth and increment it. It will return
+  // Status::OK if the current depth is allowed. Otherwise an error is returned.
+  // type_name and field_name are used for error reporting.
+  util::Status IncrementRecursionDepth(StringPiece type_name,
+                                         StringPiece field_name) const;
+
+  // Input stream to read from. Ownership rests with the caller.
+  google::protobuf::io::CodedInputStream* stream_;
+
+  // Type information for all the types used in the descriptor. Used to find
+  // google::protobuf::Type of nested messages/enums.
+  const TypeInfo* typeinfo_;
+  // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
+  // should be deleted in the destructor.
+  bool own_typeinfo_;
+
+  // google::protobuf::Type of the message source.
+  const google::protobuf::Type& type_;
+
+
+  // Whether to render enums using lowerCamelCase. Defaults to false.
+  bool use_lower_camel_for_enums_;
+
+  // Tracks current recursion depth.
+  mutable int recursion_depth_;
+
+  // Maximum allowed recursion depth.
+  int max_recursion_depth_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource_test.cc
new file mode 100644
index 0000000..3f6fdf9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -0,0 +1,1007 @@
+// 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.
+
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <sstream>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/testdata/books.pb.h>
+#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/internal/testdata/anys.pb.h>
+#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::FileDescriptorProto;
+using google::protobuf::Message;
+using google::protobuf::io::ArrayInputStream;
+using google::protobuf::io::CodedInputStream;
+using util::Status;
+using google::protobuf::testing::Author;
+using google::protobuf::testing::BadAuthor;
+using google::protobuf::testing::BadNestedBook;
+using google::protobuf::testing::Book;
+using google::protobuf::testing::Cyclic;
+using google::protobuf::testing::Book_Label;
+using google::protobuf::testing::NestedBook;
+using google::protobuf::testing::PackedPrimitive;
+using google::protobuf::testing::Primitive;
+using google::protobuf::testing::more_author;
+using google::protobuf::testing::maps::MapOut;
+using google::protobuf::testing::maps::MapOutWireFormat;
+using google::protobuf::testing::timestampduration::TimestampDuration;
+using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::anys::AnyM;
+using google::protobuf::testing::FieldMaskTest;
+using google::protobuf::testing::NestedFieldMask;
+using google::protobuf::testing::structs::StructType;
+using ::testing::_;
+
+
+namespace {
+string GetTypeUrl(const Descriptor* descriptor) {
+  return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
+}
+}  // namespace
+
+class ProtostreamObjectSourceTest
+    : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+  ProtostreamObjectSourceTest()
+      : helper_(GetParam()),
+        mock_(),
+        ow_(&mock_),
+        use_lower_camel_for_enums_(false) {
+    helper_.ResetTypeInfo(Book::descriptor());
+  }
+
+  virtual ~ProtostreamObjectSourceTest() {}
+
+  void DoTest(const Message& msg, const Descriptor* descriptor) {
+    Status status = ExecuteTest(msg, descriptor);
+    EXPECT_EQ(Status::OK, status);
+  }
+
+  Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
+    ostringstream oss;
+    msg.SerializePartialToOstream(&oss);
+    string proto = oss.str();
+    ArrayInputStream arr_stream(proto.data(), proto.size());
+    CodedInputStream in_stream(&arr_stream);
+
+    google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
+        helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
+    if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
+    os->set_max_recursion_depth(64);
+    return os->WriteTo(&mock_);
+  }
+
+  void PrepareExpectingObjectWriterForRepeatedPrimitive() {
+    ow_.StartObject("")
+        ->StartList("repFix32")
+        ->RenderUint32("", bit_cast<uint32>(3201))
+        ->RenderUint32("", bit_cast<uint32>(0))
+        ->RenderUint32("", bit_cast<uint32>(3202))
+        ->EndList()
+        ->StartList("repU32")
+        ->RenderUint32("", bit_cast<uint32>(3203))
+        ->RenderUint32("", bit_cast<uint32>(0))
+        ->EndList()
+        ->StartList("repI32")
+        ->RenderInt32("", 0)
+        ->RenderInt32("", 3204)
+        ->RenderInt32("", 3205)
+        ->EndList()
+        ->StartList("repSf32")
+        ->RenderInt32("", 3206)
+        ->RenderInt32("", 0)
+        ->EndList()
+        ->StartList("repS32")
+        ->RenderInt32("", 0)
+        ->RenderInt32("", 3207)
+        ->RenderInt32("", 3208)
+        ->EndList()
+        ->StartList("repFix64")
+        ->RenderUint64("", bit_cast<uint64>(6401LL))
+        ->RenderUint64("", bit_cast<uint64>(0LL))
+        ->EndList()
+        ->StartList("repU64")
+        ->RenderUint64("", bit_cast<uint64>(0LL))
+        ->RenderUint64("", bit_cast<uint64>(6402LL))
+        ->RenderUint64("", bit_cast<uint64>(6403LL))
+        ->EndList()
+        ->StartList("repI64")
+        ->RenderInt64("", 6404L)
+        ->RenderInt64("", 0L)
+        ->EndList()
+        ->StartList("repSf64")
+        ->RenderInt64("", 0L)
+        ->RenderInt64("", 6405L)
+        ->RenderInt64("", 6406L)
+        ->EndList()
+        ->StartList("repS64")
+        ->RenderInt64("", 6407L)
+        ->RenderInt64("", 0L)
+        ->EndList()
+        ->StartList("repFloat")
+        ->RenderFloat("", 0.0f)
+        ->RenderFloat("", 32.1f)
+        ->RenderFloat("", 32.2f)
+        ->EndList()
+        ->StartList("repDouble")
+        ->RenderDouble("", 64.1L)
+        ->RenderDouble("", 0.0L)
+        ->EndList()
+        ->StartList("repBool")
+        ->RenderBool("", true)
+        ->RenderBool("", false)
+        ->EndList()
+        ->EndObject();
+  }
+
+  Primitive PrepareRepeatedPrimitive() {
+    Primitive primitive;
+    primitive.add_rep_fix32(3201);
+    primitive.add_rep_fix32(0);
+    primitive.add_rep_fix32(3202);
+    primitive.add_rep_u32(3203);
+    primitive.add_rep_u32(0);
+    primitive.add_rep_i32(0);
+    primitive.add_rep_i32(3204);
+    primitive.add_rep_i32(3205);
+    primitive.add_rep_sf32(3206);
+    primitive.add_rep_sf32(0);
+    primitive.add_rep_s32(0);
+    primitive.add_rep_s32(3207);
+    primitive.add_rep_s32(3208);
+    primitive.add_rep_fix64(6401L);
+    primitive.add_rep_fix64(0L);
+    primitive.add_rep_u64(0L);
+    primitive.add_rep_u64(6402L);
+    primitive.add_rep_u64(6403L);
+    primitive.add_rep_i64(6404L);
+    primitive.add_rep_i64(0L);
+    primitive.add_rep_sf64(0L);
+    primitive.add_rep_sf64(6405L);
+    primitive.add_rep_sf64(6406L);
+    primitive.add_rep_s64(6407L);
+    primitive.add_rep_s64(0L);
+    primitive.add_rep_float(0.0f);
+    primitive.add_rep_float(32.1f);
+    primitive.add_rep_float(32.2f);
+    primitive.add_rep_double(64.1L);
+    primitive.add_rep_double(0.0);
+    primitive.add_rep_bool(true);
+    primitive.add_rep_bool(false);
+
+    PrepareExpectingObjectWriterForRepeatedPrimitive();
+    return primitive;
+  }
+
+  PackedPrimitive PreparePackedPrimitive() {
+    PackedPrimitive primitive;
+    primitive.add_rep_fix32(3201);
+    primitive.add_rep_fix32(0);
+    primitive.add_rep_fix32(3202);
+    primitive.add_rep_u32(3203);
+    primitive.add_rep_u32(0);
+    primitive.add_rep_i32(0);
+    primitive.add_rep_i32(3204);
+    primitive.add_rep_i32(3205);
+    primitive.add_rep_sf32(3206);
+    primitive.add_rep_sf32(0);
+    primitive.add_rep_s32(0);
+    primitive.add_rep_s32(3207);
+    primitive.add_rep_s32(3208);
+    primitive.add_rep_fix64(6401L);
+    primitive.add_rep_fix64(0L);
+    primitive.add_rep_u64(0L);
+    primitive.add_rep_u64(6402L);
+    primitive.add_rep_u64(6403L);
+    primitive.add_rep_i64(6404L);
+    primitive.add_rep_i64(0L);
+    primitive.add_rep_sf64(0L);
+    primitive.add_rep_sf64(6405L);
+    primitive.add_rep_sf64(6406L);
+    primitive.add_rep_s64(6407L);
+    primitive.add_rep_s64(0L);
+    primitive.add_rep_float(0.0f);
+    primitive.add_rep_float(32.1f);
+    primitive.add_rep_float(32.2f);
+    primitive.add_rep_double(64.1L);
+    primitive.add_rep_double(0.0);
+    primitive.add_rep_bool(true);
+    primitive.add_rep_bool(false);
+
+    PrepareExpectingObjectWriterForRepeatedPrimitive();
+    return primitive;
+  }
+
+  void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
+
+  testing::TypeInfoTestHelper helper_;
+
+  ::testing::NiceMock<MockObjectWriter> mock_;
+  ExpectingObjectWriter ow_;
+  bool use_lower_camel_for_enums_;
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
+  Book empty;
+  ow_.StartObject("")->EndObject();
+  DoTest(empty, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, Primitives) {
+  Primitive primitive;
+  primitive.set_fix32(3201);
+  primitive.set_u32(3202);
+  primitive.set_i32(3203);
+  primitive.set_sf32(3204);
+  primitive.set_s32(3205);
+  primitive.set_fix64(6401L);
+  primitive.set_u64(6402L);
+  primitive.set_i64(6403L);
+  primitive.set_sf64(6404L);
+  primitive.set_s64(6405L);
+  primitive.set_str("String Value");
+  primitive.set_bytes("Some Bytes");
+  primitive.set_float_(32.1f);
+  primitive.set_double_(64.1L);
+  primitive.set_bool_(true);
+
+  ow_.StartObject("")
+      ->RenderUint32("fix32", bit_cast<uint32>(3201))
+      ->RenderUint32("u32", bit_cast<uint32>(3202))
+      ->RenderInt32("i32", 3203)
+      ->RenderInt32("sf32", 3204)
+      ->RenderInt32("s32", 3205)
+      ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
+      ->RenderUint64("u64", bit_cast<uint64>(6402LL))
+      ->RenderInt64("i64", 6403L)
+      ->RenderInt64("sf64", 6404L)
+      ->RenderInt64("s64", 6405L)
+      ->RenderString("str", "String Value")
+      ->RenderBytes("bytes", "Some Bytes")
+      ->RenderFloat("float", 32.1f)
+      ->RenderDouble("double", 64.1L)
+      ->RenderBool("bool", true)
+      ->EndObject();
+  DoTest(primitive, Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
+  Primitive primitive = PrepareRepeatedPrimitive();
+  primitive.add_rep_str("String One");
+  primitive.add_rep_str("String Two");
+  primitive.add_rep_bytes("Some Bytes");
+
+  ow_.StartList("repStr")
+      ->RenderString("", "String One")
+      ->RenderString("", "String Two")
+      ->EndList()
+      ->StartList("repBytes")
+      ->RenderBytes("", "Some Bytes")
+      ->EndList();
+  DoTest(primitive, Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
+  Author author;
+  author.set_id(12345);
+
+  ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
+  DoTest(author, Author::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
+  Author* author = new Author();
+  author->set_name("Tolstoy");
+  Book book;
+  book.set_title("My Book");
+  book.set_allocated_author(author);
+
+  ow_.StartObject("")
+      ->RenderString("title", "My Book")
+      ->StartObject("author")
+      ->RenderString("name", "Tolstoy")
+      ->EndObject()
+      ->EndObject();
+  DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
+  Author author;
+  author.set_alive(false);
+  author.set_name("john");
+  author.add_pseudonym("phil");
+  author.add_pseudonym("bob");
+
+  ow_.StartObject("")
+      ->RenderBool("alive", false)
+      ->RenderString("name", "john")
+      ->StartList("pseudonym")
+      ->RenderString("", "phil")
+      ->RenderString("", "bob")
+      ->EndList()
+      ->EndObject();
+  DoTest(author, Author::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
+  DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
+  // Protostream is packed, but parse with non-packed Primitive.
+  DoTest(PreparePackedPrimitive(), Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
+  // Protostream is not packed, but parse with PackedPrimitive.
+  DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
+  Author author;
+  author.set_alive(false);
+  author.set_name("john");
+  author.set_id(1234L);
+  author.add_pseudonym("phil");
+  author.add_pseudonym("bob");
+
+  ow_.StartObject("")
+      ->StartList("alive")
+      ->RenderBool("", false)
+      ->EndList()
+      ->StartList("name")
+      ->RenderUint64("", static_cast<uint64>('j'))
+      ->RenderUint64("", static_cast<uint64>('o'))
+      ->RenderUint64("", static_cast<uint64>('h'))
+      ->RenderUint64("", static_cast<uint64>('n'))
+      ->EndList()
+      ->RenderString("pseudonym", "phil")
+      ->RenderString("pseudonym", "bob")
+      ->EndObject();
+  // Protostream created with Author, but parsed with BadAuthor.
+  DoTest(author, BadAuthor::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
+  Book* book = new Book();
+  book->set_length(250);
+  book->set_published(2014L);
+  NestedBook nested;
+  nested.set_allocated_book(book);
+
+  ow_.StartObject("")
+      ->StartList("book")
+      ->RenderUint32("", 24)  // tag for field length (3 << 3)
+      ->RenderUint32("", 250)
+      ->RenderUint32("", 32)  // tag for field published (4 << 3)
+      ->RenderUint32("", 2014)
+      ->EndList()
+      ->EndObject();
+  // Protostream created with NestedBook, but parsed with BadNestedBook.
+  DoTest(nested, BadNestedBook::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
+  BadNestedBook nested;
+  nested.add_book(1);
+  nested.add_book(2);
+  nested.add_book(3);
+  nested.add_book(4);
+  nested.add_book(5);
+  nested.add_book(6);
+  nested.add_book(7);
+
+  ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
+  // Protostream created with BadNestedBook, but parsed with NestedBook.
+  DoTest(nested, NestedBook::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest,
+       LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
+  Book book;
+
+  int repeat = 10000;
+  for (int i = 0; i < repeat; ++i) {
+    Book_Label* label = book.add_labels();
+    label->set_key(StrCat("i", i));
+    label->set_value(StrCat("v", i));
+  }
+
+  // Make sure StartList and EndList are called exactly once (see b/18227499 for
+  // problems when this doesn't happen)
+  EXPECT_CALL(mock_, StartList(_)).Times(1);
+  EXPECT_CALL(mock_, EndList()).Times(1);
+
+  DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputTest) {
+  Book book;
+  book.set_type(Book::ACTION_AND_ADVENTURE);
+
+  UseLowerCamelForEnums();
+
+  ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
+  DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
+  Book book;
+  book.set_type(Book::ACTION_AND_ADVENTURE);
+  ow_.StartObject("")
+      ->RenderString("type", "ACTION_AND_ADVENTURE")
+      ->EndObject();
+  DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
+  Cyclic cyclic;
+  cyclic.set_m_int(123);
+
+  Book* book = cyclic.mutable_m_book();
+  book->set_title("book title");
+  Cyclic* current = cyclic.mutable_m_cyclic();
+  Author* current_author = cyclic.add_m_author();
+  for (int i = 0; i < 63; ++i) {
+    Author* next = current_author->add_friend_();
+    next->set_id(i);
+    next->set_name(StrCat("author_name_", i));
+    next->set_alive(true);
+    current_author = next;
+  }
+
+  // Recursive message with depth (65) > max (max is 64).
+  for (int i = 0; i < 64; ++i) {
+    Cyclic* next = current->mutable_m_cyclic();
+    next->set_m_str(StrCat("count_", i));
+    current = next;
+  }
+
+  Status status = ExecuteTest(cyclic, Cyclic::descriptor());
+  EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
+}
+
+class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceMapsTest() {
+    helper_.ResetTypeInfo(MapOut::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceMapsTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+// Tests JSON map.
+//
+// This is the example expected output.
+// {
+//   "map1": {
+//     "key1": {
+//       "foo": "foovalue"
+//     },
+//     "key2": {
+//       "foo": "barvalue"
+//     }
+//   },
+//   "map2": {
+//     "nestedself": {
+//       "map1": {
+//         "nested_key1": {
+//           "foo": "nested_foo"
+//         }
+//       },
+//       "bar": "nested_bar_string"
+//     }
+//   },
+//   "map3": {
+//     "111": "one one one"
+//   },
+//   "bar": "top bar"
+// }
+TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
+  MapOut out;
+  (*out.mutable_map1())["key1"].set_foo("foovalue");
+  (*out.mutable_map1())["key2"].set_foo("barvalue");
+
+  MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
+  (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
+  nested_value->set_bar("nested_bar_string");
+
+  (*out.mutable_map3())[111] = "one one one";
+
+  out.set_bar("top bar");
+
+  ow_.StartObject("")
+      ->StartObject("map1")
+      ->StartObject("key1")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->StartObject("key2")
+      ->RenderString("foo", "barvalue")
+      ->EndObject()
+      ->StartObject("map2")
+      ->StartObject("nestedself")
+      ->StartObject("map1")
+      ->StartObject("nested_key1")
+      ->RenderString("foo", "nested_foo")
+      ->EndObject()
+      ->EndObject()
+      ->RenderString("bar", "nested_bar_string")
+      ->EndObject()
+      ->EndObject()
+      ->StartObject("map3")
+      ->RenderString("111", "one one one")
+      ->EndObject()
+      ->EndObject()
+      ->RenderString("bar", "top bar")
+      ->EndObject();
+
+  DoTest(out, MapOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
+  // MapOutWireFormat has the same wire representation with MapOut but uses
+  // repeated message fields to represent map fields so we can intentionally
+  // leave out the key field or the value field of a map entry.
+  MapOutWireFormat out;
+  // Create some map entries without keys. They will be rendered with the
+  // default values ("" for strings, "0" for integers, etc.).
+  // {
+  //   "map1": {
+  //     "": {
+  //       "foo": "foovalue"
+  //     }
+  //   },
+  //   "map2": {
+  //     "": {
+  //       "map1": {
+  //         "nested_key1": {
+  //           "foo": "nested_foo"
+  //         }
+  //       }
+  //     }
+  //   },
+  //   "map3": {
+  //     "0": "one one one"
+  //   },
+  //   "map4": {
+  //     "false": "bool"
+  //   }
+  // }
+  out.add_map1()->mutable_value()->set_foo("foovalue");
+  MapOut* nested = out.add_map2()->mutable_value();
+  (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
+  out.add_map3()->set_value("one one one");
+  out.add_map4()->set_value("bool");
+
+  ow_.StartObject("")
+      ->StartObject("map1")
+      ->StartObject("")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->StartObject("map2")
+      ->StartObject("")
+      ->StartObject("map1")
+      ->StartObject("nested_key1")
+      ->RenderString("foo", "nested_foo")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->StartObject("map3")
+      ->RenderString("0", "one one one")
+      ->EndObject()
+      ->StartObject("map4")
+      ->RenderString("false", "bool")
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, MapOut::descriptor());
+}
+
+class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceAnysTest() {
+    helper_.ResetTypeInfo(AnyOut::descriptor(),
+                          google::protobuf::Any::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceAnysTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+// Tests JSON any support.
+//
+// This is the example expected output.
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
+//     "foo": "foovalue"
+//   }
+// }
+TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+
+  AnyM m;
+  m.set_foo("foovalue");
+  any->PackFrom(m);
+
+  ow_.StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type",
+                     "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any nested_any;
+  nested_any.set_type_url(
+      "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  nested_any.set_value(m.SerializeAsString());
+
+  any->set_value(nested_any.SerializeAsString());
+
+  ow_.StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type",
+                     "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any nested_any;
+  nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any second_nested_any;
+  second_nested_any.set_type_url(
+      "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  second_nested_any.set_value(m.SerializeAsString());
+  nested_any.set_value(second_nested_any.SerializeAsString());
+  any->set_value(nested_any.SerializeAsString());
+
+  ow_.StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type",
+                     "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
+  AnyOut out;
+  out.mutable_any();
+
+  ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
+
+  DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
+  AnyOut out;
+  out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
+
+  ow_.StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "foo.googleapis.com/my.Type")
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+
+  AnyM m;
+  m.set_foo("foovalue");
+  any->set_value(m.SerializeAsString());
+
+  // We start the "AnyOut" part and then fail when we hit the Any object.
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("foo.googleapis.com/my.own.Type");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  any->set_value(m.SerializeAsString());
+
+  // We start the "AnyOut" part and then fail when we hit the Any object.
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("type.googleapis.com/unknown.Type");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  any->set_value(m.SerializeAsString());
+
+  // We start the "AnyOut" part and then fail when we hit the Any object.
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceStructTest() {
+    helper_.ResetTypeInfo(StructType::descriptor(),
+                          google::protobuf::Struct::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceStructTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+// Tests struct
+//
+//  "object": {
+//    "k1": 123,
+//    "k2": true
+//  }
+TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
+  StructType out;
+  google::protobuf::Struct* s = out.mutable_object();
+  s->mutable_fields()->operator[]("k1").set_number_value(123);
+  s->mutable_fields()->operator[]("k2").set_bool_value(true);
+
+  ow_.StartObject("")
+      ->StartObject("object")
+      ->RenderDouble("k1", 123)
+      ->RenderBool("k2", true)
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, StructType::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
+  StructType out;
+  google::protobuf::Struct* s = out.mutable_object();
+  s->mutable_fields()->operator[]("k1");
+
+  ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
+
+  DoTest(out, StructType::descriptor());
+}
+
+class ProtostreamObjectSourceFieldMaskTest
+    : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceFieldMaskTest() {
+    helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
+                          google::protobuf::FieldMask::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceFieldMaskTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
+  FieldMaskTest out;
+  out.set_id("1");
+  out.mutable_single_mask()->add_paths("path1");
+  out.mutable_single_mask()->add_paths("snake_case_path2");
+  ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
+  mask->add_paths("path3");
+  mask = out.add_repeated_mask();
+  mask->add_paths("snake_case_path4");
+  mask->add_paths("path5");
+  NestedFieldMask* nested = out.add_nested_mask();
+  nested->set_data("data");
+  nested->mutable_single_mask()->add_paths("nested.path1");
+  nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
+  mask = nested->add_repeated_mask();
+  mask->add_paths("nested_field.path3");
+  mask->add_paths("nested.snake_case_path4");
+  mask = nested->add_repeated_mask();
+  mask->add_paths("nested.path5");
+  mask = nested->add_repeated_mask();
+  mask->add_paths(
+      "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
+      "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
+
+  ow_.StartObject("")
+      ->RenderString("id", "1")
+      ->RenderString("singleMask", "path1,snakeCasePath2")
+      ->StartList("repeatedMask")
+      ->RenderString("", "path3")
+      ->RenderString("", "snakeCasePath4,path5")
+      ->EndList()
+      ->StartList("nestedMask")
+      ->StartObject("")
+      ->RenderString("data", "data")
+      ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
+      ->StartList("repeatedMask")
+      ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
+      ->RenderString("", "nested.path5")
+      ->RenderString("",
+                     "snakeCase.mapField[\"map_key_should_be_ignored\"]."
+                     "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
+                     "ignored\"]")
+      ->EndList()
+      ->EndObject()
+      ->EndList()
+      ->EndObject();
+
+  DoTest(out, FieldMaskTest::descriptor());
+}
+
+class ProtostreamObjectSourceTimestampTest
+    : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceTimestampTest() {
+    helper_.ResetTypeInfo(TimestampDuration::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceTimestampTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
+  TimestampDuration out;
+  google::protobuf::Timestamp* ts = out.mutable_ts();
+  // Min allowed seconds - 1
+  ts->set_seconds(kTimestampMinSeconds - 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
+  TimestampDuration out;
+  google::protobuf::Timestamp* ts = out.mutable_ts();
+  // Max allowed seconds + 1
+  ts->set_seconds(kTimestampMaxSeconds + 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
+  TimestampDuration out;
+  google::protobuf::Duration* dur = out.mutable_dur();
+  // Min allowed seconds - 1
+  dur->set_seconds(kDurationMinSeconds - 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
+  TimestampDuration out;
+  google::protobuf::Duration* dur = out.mutable_dur();
+  // Min allowed seconds + 1
+  dur->set_seconds(kDurationMaxSeconds + 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.cc
new file mode 100644
index 0000000..97a7909
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -0,0 +1,1206 @@
+// 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.
+
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+
+#include <functional>
+#include <stack>
+
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/util/internal/field_mask_utility.h>
+#include <google/protobuf/util/internal/object_location_tracker.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::internal::WireFormatLite;
+using util::error::INVALID_ARGUMENT;
+using util::Status;
+using util::StatusOr;
+
+
+ProtoStreamObjectWriter::ProtoStreamObjectWriter(
+    TypeResolver* type_resolver, const google::protobuf::Type& type,
+    strings::ByteSink* output, ErrorListener* listener,
+    const ProtoStreamObjectWriter::Options& options)
+    : ProtoWriter(type_resolver, type, output, listener),
+      master_type_(type),
+      current_(NULL),
+      options_(options) {}
+
+ProtoStreamObjectWriter::ProtoStreamObjectWriter(
+    const TypeInfo* typeinfo, const google::protobuf::Type& type,
+    strings::ByteSink* output, ErrorListener* listener)
+    : ProtoWriter(typeinfo, type, output, listener),
+      master_type_(type),
+      current_(NULL),
+      options_(ProtoStreamObjectWriter::Options::Defaults()) {}
+
+ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
+  if (current_ == NULL) return;
+  // Cleanup explicitly in order to avoid destructor stack overflow when input
+  // is deeply nested.
+  // Cast to BaseElement to avoid doing additional checks (like missing fields)
+  // during pop().
+  google::protobuf::scoped_ptr<BaseElement> element(
+      static_cast<BaseElement*>(current_.get())->pop<BaseElement>());
+  while (element != NULL) {
+    element.reset(element->pop<BaseElement>());
+  }
+}
+
+namespace {
+// Utility method to split a string representation of Timestamp or Duration and
+// return the parts.
+void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds,
+                          StringPiece* nanos) {
+  size_t idx = input.rfind('.');
+  if (idx != string::npos) {
+    *seconds = input.substr(0, idx);
+    *nanos = input.substr(idx + 1);
+  } else {
+    *seconds = input;
+    *nanos = StringPiece();
+  }
+}
+
+Status GetNanosFromStringPiece(StringPiece s_nanos,
+                               const char* parse_failure_message,
+                               const char* exceeded_limit_message,
+                               int32* nanos) {
+  *nanos = 0;
+
+  // Count the number of leading 0s and consume them.
+  int num_leading_zeros = 0;
+  while (s_nanos.Consume("0")) {
+    num_leading_zeros++;
+  }
+  int32 i_nanos = 0;
+  // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to
+  // "0." + s_nanos.ToString() seconds. An int32 is used for the
+  // conversion to 'nanos', rather than a double, so that there is no
+  // loss of precision.
+  if (!s_nanos.empty() && !safe_strto32(s_nanos.ToString(), &i_nanos)) {
+    return Status(INVALID_ARGUMENT, parse_failure_message);
+  }
+  if (i_nanos > kNanosPerSecond || i_nanos < 0) {
+    return Status(INVALID_ARGUMENT, exceeded_limit_message);
+  }
+  // s_nanos should only have digits. No whitespace.
+  if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) {
+    return Status(INVALID_ARGUMENT, parse_failure_message);
+  }
+
+  if (i_nanos > 0) {
+    // 'scale' is the number of digits to the right of the decimal
+    // point in "0." + s_nanos.ToString()
+    int32 scale = num_leading_zeros + s_nanos.size();
+    // 'conversion' converts i_nanos into nanoseconds.
+    // conversion = kNanosPerSecond / static_cast<int32>(std::pow(10, scale))
+    // For efficiency, we precompute the conversion factor.
+    int32 conversion = 0;
+    switch (scale) {
+      case 1:
+        conversion = 100000000;
+        break;
+      case 2:
+        conversion = 10000000;
+        break;
+      case 3:
+        conversion = 1000000;
+        break;
+      case 4:
+        conversion = 100000;
+        break;
+      case 5:
+        conversion = 10000;
+        break;
+      case 6:
+        conversion = 1000;
+        break;
+      case 7:
+        conversion = 100;
+        break;
+      case 8:
+        conversion = 10;
+        break;
+      case 9:
+        conversion = 1;
+        break;
+      default:
+        return Status(INVALID_ARGUMENT, exceeded_limit_message);
+    }
+    *nanos = i_nanos * conversion;
+  }
+
+  return Status::OK;
+}
+
+}  // namespace
+
+ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
+    : parent_(parent),
+      ow_(),
+      invalid_(false),
+      data_(),
+      output_(&data_),
+      depth_(0),
+      is_well_known_type_(false),
+      well_known_type_render_(NULL) {}
+
+ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
+
+void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
+  ++depth_;
+  // If an object writer is absent, that means we have not called StartAny()
+  // before reaching here. This is an invalid state. StartAny() gets called
+  // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece).
+  if (ow_ == NULL) {
+    // Make sure we are not already in an invalid state. This avoids making
+    // multiple unnecessary InvalidValue calls.
+    if (!invalid_) {
+      parent_->InvalidValue("Any",
+                            StrCat("Missing or invalid @type for any field in ",
+                                   parent_->master_type_.name()));
+      invalid_ = true;
+    }
+  } else if (is_well_known_type_ && depth_ == 1) {
+    // For well-known types, the only other field besides "@type" should be a
+    // "value" field.
+    if (name != "value" && !invalid_) {
+      parent_->InvalidValue("Any",
+                            "Expect a \"value\" field for well-known types.");
+      invalid_ = true;
+    }
+    ow_->StartObject("");
+  } else {
+    // Forward the call to the child writer if:
+    //   1. the type is not a well-known type.
+    //   2. or, we are in a nested Any, Struct, or Value object.
+    ow_->StartObject(name);
+  }
+}
+
+bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
+  --depth_;
+  // As long as depth_ >= 0, we know we haven't reached the end of Any.
+  // Propagate these EndObject() calls to the contained ow_. For regular
+  // message types, we propagate the end of Any as well.
+  if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) {
+    ow_->EndObject();
+  }
+  // A negative depth_ implies that we have reached the end of Any
+  // object. Now we write out its contents.
+  if (depth_ < 0) {
+    WriteAny();
+    return false;
+  }
+  return true;
+}
+
+void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
+  ++depth_;
+  // We expect ow_ to be present as this call only makes sense inside an Any.
+  if (ow_ == NULL) {
+    if (!invalid_) {
+      parent_->InvalidValue("Any",
+                            StrCat("Missing or invalid @type for any field in ",
+                                   parent_->master_type_.name()));
+      invalid_ = true;
+    }
+  } else if (is_well_known_type_ && depth_ == 1) {
+    if (name != "value" && !invalid_) {
+      parent_->InvalidValue("Any",
+                            "Expect a \"value\" field for well-known types.");
+      invalid_ = true;
+    }
+    ow_->StartList("");
+  } else {
+    ow_->StartList(name);
+  }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::EndList() {
+  --depth_;
+  if (depth_ < 0) {
+    GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible";
+    depth_ = 0;
+  }
+  // We don't write an error on the close, only on the open
+  if (ow_ != NULL) {
+    ow_->EndList();
+  }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
+    StringPiece name, const DataPiece& value) {
+  // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type"
+  // should go to the contained ow_ as they indicate nested Anys.
+  if (depth_ == 0 && ow_ == NULL && name == "@type") {
+    StartAny(value);
+  } else if (ow_ == NULL) {
+    if (!invalid_) {
+      parent_->InvalidValue("Any",
+                            StrCat("Missing or invalid @type for any field in ",
+                                   parent_->master_type_.name()));
+      invalid_ = true;
+    }
+  } else if (depth_ == 0 && is_well_known_type_) {
+    if (name != "value" && !invalid_) {
+      parent_->InvalidValue("Any",
+                            "Expect a \"value\" field for well-known types.");
+      invalid_ = true;
+    }
+    if (well_known_type_render_ == NULL) {
+      // Only Any and Struct don't have a special type render but both of
+      // them expect a JSON object (i.e., a StartObject() call).
+      if (!invalid_) {
+        parent_->InvalidValue("Any", "Expect a JSON object.");
+        invalid_ = true;
+      }
+    } else {
+      ow_->ProtoWriter::StartObject("");
+      Status status = (*well_known_type_render_)(ow_.get(), value);
+      if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
+      ow_->ProtoWriter::EndObject();
+    }
+  } else {
+    ow_->RenderDataPiece(name, value);
+  }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
+  // Figure out the type url. This is a copy-paste from WriteString but we also
+  // need the value, so we can't just call through to that.
+  if (value.type() == DataPiece::TYPE_STRING) {
+    type_url_ = value.str().ToString();
+  } else {
+    StatusOr<string> s = value.ToString();
+    if (!s.ok()) {
+      parent_->InvalidValue("String", s.status().error_message());
+      invalid_ = true;
+      return;
+    }
+    type_url_ = s.ValueOrDie();
+  }
+  // Resolve the type url, and report an error if we failed to resolve it.
+  StatusOr<const google::protobuf::Type*> resolved_type =
+      parent_->typeinfo()->ResolveTypeUrl(type_url_);
+  if (!resolved_type.ok()) {
+    parent_->InvalidValue("Any", resolved_type.status().error_message());
+    invalid_ = true;
+    return;
+  }
+  // At this point, type is never null.
+  const google::protobuf::Type* type = resolved_type.ValueOrDie();
+
+  well_known_type_render_ = FindTypeRenderer(type_url_);
+  if (well_known_type_render_ != NULL ||
+      // Explicitly list Any and Struct here because they don't have a
+      // custom renderer.
+      type->name() == kAnyType || type->name() == kStructType) {
+    is_well_known_type_ = true;
+  }
+
+  // Create our object writer and initialize it with the first StartObject
+  // call.
+  ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
+                                        parent_->listener()));
+
+  // Don't call StartObject() for well-known types yet. Depending on the
+  // type of actual data, we may not need to call StartObject(). For
+  // example:
+  // {
+  //   "@type": "type.googleapis.com/google.protobuf.Value",
+  //   "value": [1, 2, 3],
+  // }
+  // With the above JSON representation, we will only call StartList() on the
+  // contained ow_.
+  if (!is_well_known_type_) {
+    ow_->StartObject("");
+  }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
+  if (ow_ == NULL) {
+    // If we had no object writer, we never got any content, so just return
+    // immediately, which is equivalent to writing an empty Any.
+    return;
+  }
+  // Render the type_url and value fields directly to the stream.
+  // type_url has tag 1 and value has tag 2.
+  WireFormatLite::WriteString(1, type_url_, parent_->stream());
+  if (!data_.empty()) {
+    WireFormatLite::WriteBytes(2, data_, parent_->stream());
+  }
+}
+
+ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing,
+                                    ItemType item_type, bool is_placeholder,
+                                    bool is_list)
+    : BaseElement(NULL),
+      ow_(enclosing),
+      any_(),
+      item_type_(item_type),
+      is_placeholder_(is_placeholder),
+      is_list_(is_list) {
+  if (item_type_ == ANY) {
+    any_.reset(new AnyWriter(ow_));
+  }
+}
+
+ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent,
+                                    ItemType item_type, bool is_placeholder,
+                                    bool is_list)
+    : BaseElement(parent),
+      ow_(this->parent()->ow_),
+      any_(),
+      item_type_(item_type),
+      is_placeholder_(is_placeholder),
+      is_list_(is_list) {
+  if (item_type == ANY) {
+    any_.reset(new AnyWriter(ow_));
+  }
+}
+
+bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent(
+    StringPiece map_key) {
+  return InsertIfNotPresent(&map_keys_, map_key.ToString());
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
+    StringPiece name) {
+  if (invalid_depth() > 0) {
+    IncrementInvalidDepth();
+    return this;
+  }
+
+  // Starting the root message. Create the root Item and return.
+  // ANY message type does not need special handling, just set the ItemType
+  // to ANY.
+  if (current_ == NULL) {
+    ProtoWriter::StartObject(name);
+    current_.reset(new Item(
+        this, master_type_.name() == kAnyType ? Item::ANY : Item::MESSAGE,
+        false, false));
+
+    // If master type is a special type that needs extra values to be written to
+    // stream, we write those values.
+    if (master_type_.name() == kStructType) {
+      // Struct has a map<string, Value> field called "fields".
+      // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
+      // "fields": [
+      Push("fields", Item::MAP, true, true);
+      return this;
+    }
+
+    if (master_type_.name() == kStructValueType) {
+      // We got a StartObject call with google.protobuf.Value field. The only
+      // object within that type is a struct type. So start a struct.
+      //
+      // The struct field in Value type is named "struct_value"
+      // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
+      // Also start the map field "fields" within the struct.
+      // "struct_value": {
+      //   "fields": [
+      Push("struct_value", Item::MESSAGE, true, false);
+      Push("fields", Item::MAP, true, true);
+      return this;
+    }
+
+    if (master_type_.name() == kStructListValueType) {
+      InvalidValue(kStructListValueType,
+                   "Cannot start root message with ListValue.");
+    }
+
+    return this;
+  }
+
+  // Send all ANY events to AnyWriter.
+  if (current_->IsAny()) {
+    current_->any()->StartObject(name);
+    return this;
+  }
+
+  // If we are within a map, we render name as keys and send StartObject to the
+  // value field.
+  if (current_->IsMap()) {
+    if (!ValidMapKey(name)) {
+      IncrementInvalidDepth();
+      return this;
+    }
+
+    // Map is a repeated field of message type with a "key" and a "value" field.
+    // https://developers.google.com/protocol-buffers/docs/proto3?hl=en#maps
+    // message MapFieldEntry {
+    //   key_type key = 1;
+    //   value_type value = 2;
+    // }
+    //
+    // repeated MapFieldEntry map_field = N;
+    //
+    // That means, we render the following element within a list (hence no
+    // name):
+    // { "key": "<name>", "value": {
+    Push("", Item::MESSAGE, false, false);
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
+    Push("value", Item::MESSAGE, true, false);
+
+    // Make sure we are valid so far after starting map fields.
+    if (invalid_depth() > 0) return this;
+
+    // If top of stack is g.p.Struct type, start the struct the map field within
+    // it.
+    if (element() != NULL && IsStruct(*element()->parent_field())) {
+      // Render "fields": [
+      Push("fields", Item::MAP, true, true);
+      return this;
+    }
+
+    // If top of stack is g.p.Value type, start the Struct within it.
+    if (element() != NULL && IsStructValue(*element()->parent_field())) {
+      // Render
+      // "struct_value": {
+      //   "fields": [
+      Push("struct_value", Item::MESSAGE, true, false);
+      Push("fields", Item::MAP, true, true);
+    }
+    return this;
+  }
+
+  const google::protobuf::Field* field = BeginNamed(name, false);
+  if (field == NULL) return this;
+
+  if (IsStruct(*field)) {
+    // Start a struct object.
+    // Render
+    // "<name>": {
+    //   "fields": {
+    Push(name, Item::MESSAGE, false, false);
+    Push("fields", Item::MAP, true, true);
+    return this;
+  }
+
+  if (IsStructValue(*field)) {
+    // We got a StartObject call with google.protobuf.Value field.  The only
+    // object within that type is a struct type. So start a struct.
+    // Render
+    // "<name>": {
+    //   "struct_value": {
+    //     "fields": {
+    Push(name, Item::MESSAGE, false, false);
+    Push("struct_value", Item::MESSAGE, true, false);
+    Push("fields", Item::MAP, true, true);
+    return this;
+  }
+
+  if (IsMap(*field)) {
+    // Begin a map. A map is triggered by a StartObject() call if the current
+    // field has a map type.
+    // A map type is always repeated, hence set is_list to true.
+    // Render
+    // "<name>": [
+    Push(name, Item::MAP, false, true);
+    return this;
+  }
+
+  // A regular message type. Pass it directly to ProtoWriter.
+  // Render
+  // "<name>": {
+  Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false);
+  return this;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() {
+  if (invalid_depth() > 0) {
+    DecrementInvalidDepth();
+    return this;
+  }
+
+  if (current_ == NULL) return this;
+
+  if (current_->IsAny()) {
+    if (current_->any()->EndObject()) return this;
+  }
+
+  Pop();
+
+  return this;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
+  if (invalid_depth() > 0) {
+    IncrementInvalidDepth();
+    return this;
+  }
+
+  // Since we cannot have a top-level repeated item in protobuf, the only way
+  // this is valid is if we start a special type google.protobuf.ListValue or
+  // google.protobuf.Value.
+  if (current_ == NULL) {
+    if (!name.empty()) {
+      InvalidName(name, "Root element should not be named.");
+      IncrementInvalidDepth();
+      return this;
+    }
+
+    // If master type is a special type that needs extra values to be written to
+    // stream, we write those values.
+    if (master_type_.name() == kStructValueType) {
+      // We got a StartList with google.protobuf.Value master type. This means
+      // we have to start the "list_value" within google.protobuf.Value.
+      //
+      // See
+      // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
+      //
+      // Render
+      // "<name>": {
+      //   "list_value": {
+      //     "values": [  // Start this list.
+      ProtoWriter::StartObject(name);
+      current_.reset(new Item(this, Item::MESSAGE, false, false));
+      Push("list_value", Item::MESSAGE, true, false);
+      Push("values", Item::MESSAGE, true, true);
+      return this;
+    }
+
+    if (master_type_.name() == kStructListValueType) {
+      // We got a StartList with google.protobuf.ListValue master type. This
+      // means we have to start the "values" within google.protobuf.ListValue.
+      //
+      // Render
+      // "<name>": {
+      //   "values": [  // Start this list.
+      ProtoWriter::StartObject(name);
+      current_.reset(new Item(this, Item::MESSAGE, false, false));
+      Push("values", Item::MESSAGE, true, true);
+      return this;
+    }
+
+    // Send the event to ProtoWriter so proper errors can be reported.
+    //
+    // Render a regular list:
+    // "<name>": [
+    ProtoWriter::StartList(name);
+    current_.reset(new Item(this, Item::MESSAGE, false, true));
+    return this;
+  }
+
+  if (current_->IsAny()) {
+    current_->any()->StartList(name);
+    return this;
+  }
+
+  // If the top of stack is a map, we are starting a list value within a map.
+  // Since map does not allow repeated values, this can only happen when the map
+  // value is of a special type that renders a list in JSON.  These can be one
+  // of 3 cases:
+  // i. We are rendering a list value within google.protobuf.Struct
+  // ii. We are rendering a list value within google.protobuf.Value
+  // iii. We are rendering a list value with type google.protobuf.ListValue.
+  if (current_->IsMap()) {
+    if (!ValidMapKey(name)) {
+      IncrementInvalidDepth();
+      return this;
+    }
+
+    // Start the repeated map entry object.
+    // Render
+    // { "key": "<name>", "value": {
+    Push("", Item::MESSAGE, false, false);
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
+    Push("value", Item::MESSAGE, true, false);
+
+    // Make sure we are valid after pushing all above items.
+    if (invalid_depth() > 0) return this;
+
+    // case i and ii above. Start "list_value" field within g.p.Value
+    if (element() != NULL && element()->parent_field() != NULL) {
+      // Render
+      // "list_value": {
+      //   "values": [  // Start this list
+      if (IsStructValue(*element()->parent_field())) {
+        Push("list_value", Item::MESSAGE, true, false);
+        Push("values", Item::MESSAGE, true, true);
+        return this;
+      }
+
+      // Render
+      // "values": [
+      if (IsStructListValue(*element()->parent_field())) {
+        // case iii above. Bind directly to g.p.ListValue
+        Push("values", Item::MESSAGE, true, true);
+        return this;
+      }
+    }
+
+    // Report an error.
+    InvalidValue("Map", StrCat("Cannot have repeated items ('", name,
+                               "') within a map."));
+    return this;
+  }
+
+  // When name is empty and stack is not empty, we are rendering an item within
+  // a list.
+  if (name.empty()) {
+    if (element() != NULL && element()->parent_field() != NULL) {
+      if (IsStructValue(*element()->parent_field())) {
+        // Since it is g.p.Value, we bind directly to the list_value.
+        // Render
+        // {  // g.p.Value item within the list
+        //   "list_value": {
+        //     "values": [
+        Push("", Item::MESSAGE, false, false);
+        Push("list_value", Item::MESSAGE, true, false);
+        Push("values", Item::MESSAGE, true, true);
+        return this;
+      }
+
+      if (IsStructListValue(*element()->parent_field())) {
+        // Since it is g.p.ListValue, we bind to it directly.
+        // Render
+        // {  // g.p.ListValue item within the list
+        //   "values": [
+        Push("", Item::MESSAGE, false, false);
+        Push("values", Item::MESSAGE, true, true);
+        return this;
+      }
+    }
+
+    // Pass the event to underlying ProtoWriter.
+    Push(name, Item::MESSAGE, false, true);
+    return this;
+  }
+
+  // name is not empty
+  const google::protobuf::Field* field = Lookup(name);
+  if (field == NULL) {
+    IncrementInvalidDepth();
+    return this;
+  }
+
+  if (IsStructValue(*field)) {
+    // If g.p.Value is repeated, start that list. Otherwise, start the
+    // "list_value" within it.
+    if (IsRepeated(*field)) {
+      // Render it just like a regular repeated field.
+      // "<name>": [
+      Push(name, Item::MESSAGE, false, true);
+      return this;
+    }
+
+    // Start the "list_value" field.
+    // Render
+    // "<name>": {
+    //   "list_value": {
+    //     "values": [
+    Push(name, Item::MESSAGE, false, false);
+    Push("list_value", Item::MESSAGE, true, false);
+    Push("values", Item::MESSAGE, true, true);
+    return this;
+  }
+
+  if (IsStructListValue(*field)) {
+    // If g.p.ListValue is repeated, start that list. Otherwise, start the
+    // "values" within it.
+    if (IsRepeated(*field)) {
+      // Render it just like a regular repeated field.
+      // "<name>": [
+      Push(name, Item::MESSAGE, false, true);
+      return this;
+    }
+
+    // Start the "values" field within g.p.ListValue.
+    // Render
+    // "<name>": {
+    //   "values": [
+    Push(name, Item::MESSAGE, false, false);
+    Push("values", Item::MESSAGE, true, true);
+    return this;
+  }
+
+  // If we are here, the field should be repeated. Report an error otherwise.
+  if (!IsRepeated(*field)) {
+    IncrementInvalidDepth();
+    InvalidName(name, "Proto field is not repeating, cannot start list.");
+    return this;
+  }
+
+  if (IsMap(*field)) {
+    InvalidValue("Map",
+                 StrCat("Cannot bind a list to map for field '", name, "'."));
+    IncrementInvalidDepth();
+    return this;
+  }
+
+  // Pass the event to ProtoWriter.
+  // Render
+  // "<name>": [
+  Push(name, Item::MESSAGE, false, true);
+  return this;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() {
+  if (invalid_depth() > 0) {
+    DecrementInvalidDepth();
+    return this;
+  }
+
+  if (current_ == NULL) return this;
+
+  if (current_->IsAny()) {
+    current_->any()->EndList();
+    return this;
+  }
+
+  Pop();
+  return this;
+}
+
+Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
+                                                  const DataPiece& data) {
+  string struct_field_name;
+  switch (data.type()) {
+    // Our JSON parser parses numbers as either int64, uint64, or double.
+    case DataPiece::TYPE_INT64: {
+      // If the option to treat integers as strings is set, then render them as
+      // strings. Otherwise, fallback to rendering them as double.
+      if (ow->options_.struct_integers_as_strings) {
+        StatusOr<int64> int_value = data.ToInt64();
+        if (int_value.ok()) {
+          ow->ProtoWriter::RenderDataPiece(
+              "string_value",
+              DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+          return Status::OK;
+        }
+      }
+      struct_field_name = "number_value";
+      break;
+    }
+    case DataPiece::TYPE_UINT64: {
+      // If the option to treat integers as strings is set, then render them as
+      // strings. Otherwise, fallback to rendering them as double.
+      if (ow->options_.struct_integers_as_strings) {
+        StatusOr<uint64> int_value = data.ToUint64();
+        if (int_value.ok()) {
+          ow->ProtoWriter::RenderDataPiece(
+              "string_value",
+              DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+          return Status::OK;
+        }
+      }
+      struct_field_name = "number_value";
+      break;
+    }
+    case DataPiece::TYPE_DOUBLE: {
+      struct_field_name = "number_value";
+      break;
+    }
+    case DataPiece::TYPE_STRING: {
+      struct_field_name = "string_value";
+      break;
+    }
+    case DataPiece::TYPE_BOOL: {
+      struct_field_name = "bool_value";
+      break;
+    }
+    case DataPiece::TYPE_NULL: {
+      struct_field_name = "null_value";
+      break;
+    }
+    default: {
+      return Status(INVALID_ARGUMENT,
+                    "Invalid struct data type. Only number, string, boolean or "
+                    "null values are supported.");
+    }
+  }
+  ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
+  return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
+                                                const DataPiece& data) {
+  if (data.type() != DataPiece::TYPE_STRING) {
+    return Status(INVALID_ARGUMENT,
+                  StrCat("Invalid data type for timestamp, value is ",
+                         data.ValueAsStringOrDefault("")));
+  }
+
+  StringPiece value(data.str());
+
+  int64 seconds;
+  int32 nanos;
+  if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
+                                               &nanos)) {
+    return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value));
+  }
+
+
+  ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
+  ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
+  return Status::OK;
+}
+
+static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
+                                                StringPiece path) {
+  ow->ProtoWriter::RenderDataPiece(
+      "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
+                                                const DataPiece& data) {
+  if (data.type() != DataPiece::TYPE_STRING) {
+    return Status(INVALID_ARGUMENT,
+                  StrCat("Invalid data type for field mask, value is ",
+                         data.ValueAsStringOrDefault("")));
+  }
+
+// TODO(tsun): figure out how to do proto descriptor based snake case
+// conversions as much as possible. Because ToSnakeCase sometimes returns the
+// wrong value.
+  google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
+      ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
+  return DecodeCompactFieldMaskPaths(data.str(), callback.get());
+}
+
+Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
+                                               const DataPiece& data) {
+  if (data.type() != DataPiece::TYPE_STRING) {
+    return Status(INVALID_ARGUMENT,
+                  StrCat("Invalid data type for duration, value is ",
+                         data.ValueAsStringOrDefault("")));
+  }
+
+  StringPiece value(data.str());
+
+  if (!value.ends_with("s")) {
+    return Status(INVALID_ARGUMENT,
+                  "Illegal duration format; duration must end with 's'");
+  }
+  value = value.substr(0, value.size() - 1);
+  int sign = 1;
+  if (value.starts_with("-")) {
+    sign = -1;
+    value = value.substr(1);
+  }
+
+  StringPiece s_secs, s_nanos;
+  SplitSecondsAndNanos(value, &s_secs, &s_nanos);
+  uint64 unsigned_seconds;
+  if (!safe_strtou64(s_secs, &unsigned_seconds)) {
+    return Status(INVALID_ARGUMENT,
+                  "Invalid duration format, failed to parse seconds");
+  }
+
+  int32 nanos = 0;
+  Status nanos_status = GetNanosFromStringPiece(
+      s_nanos, "Invalid duration format, failed to parse nano seconds",
+      "Duration value exceeds limits", &nanos);
+  if (!nanos_status.ok()) {
+    return nanos_status;
+  }
+  nanos = sign * nanos;
+
+  int64 seconds = sign * unsigned_seconds;
+  if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
+      nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+    return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
+  }
+
+  ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
+  ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
+  return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
+                                                  const DataPiece& data) {
+  ow->ProtoWriter::RenderDataPiece("value", data);
+  return Status::OK;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
+    StringPiece name, const DataPiece& data) {
+  Status status;
+  if (invalid_depth() > 0) return this;
+
+  if (current_ == NULL) {
+    const TypeRenderer* type_renderer =
+        FindTypeRenderer(GetFullTypeWithUrl(master_type_.name()));
+    if (type_renderer == NULL) {
+      InvalidName(name, "Root element must be a message.");
+      return this;
+    }
+    // Render the special type.
+    // "<name>": {
+    //   ... Render special type ...
+    // }
+    ProtoWriter::StartObject(name);
+    status = (*type_renderer)(this, data);
+    if (!status.ok()) {
+      InvalidValue(master_type_.name(),
+                   StrCat("Field '", name, "', ", status.error_message()));
+    }
+    ProtoWriter::EndObject();
+    return this;
+  }
+
+  if (current_->IsAny()) {
+    current_->any()->RenderDataPiece(name, data);
+    return this;
+  }
+
+  const google::protobuf::Field* field = NULL;
+  if (current_->IsMap()) {
+    if (!ValidMapKey(name)) return this;
+
+    // Render an item in repeated map list.
+    // { "key": "<name>", "value":
+    Push("", Item::MESSAGE, false, false);
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
+    field = Lookup("value");
+    if (field == NULL) {
+      GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
+      return this;
+    }
+
+    const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
+    if (type_renderer != NULL) {
+      // Map's value type is a special type. Render it like a message:
+      // "value": {
+      //   ... Render special type ...
+      // }
+      Push("value", Item::MESSAGE, true, false);
+      status = (*type_renderer)(this, data);
+      if (!status.ok()) {
+        InvalidValue(field->type_url(),
+                     StrCat("Field '", name, "', ", status.error_message()));
+      }
+      Pop();
+      return this;
+    }
+
+    // If we are rendering explicit null values and the backend proto field is
+    // not of the google.protobuf.NullType type, we do nothing.
+    if (data.type() == DataPiece::TYPE_NULL &&
+        field->type_url() != kStructNullValueTypeUrl) {
+      Pop();
+      return this;
+    }
+
+    // Render the map value as a primitive type.
+    ProtoWriter::RenderDataPiece("value", data);
+    Pop();
+    return this;
+  }
+
+  field = Lookup(name);
+  if (field == NULL) return this;
+
+  // Check if the field is of special type. Render it accordingly if so.
+  const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
+  if (type_renderer != NULL) {
+    Push(name, Item::MESSAGE, false, false);
+    status = (*type_renderer)(this, data);
+    if (!status.ok()) {
+      InvalidValue(field->type_url(),
+                   StrCat("Field '", name, "', ", status.error_message()));
+    }
+    Pop();
+    return this;
+  }
+
+  // If we are rendering explicit null values and the backend proto field is
+  // not of the google.protobuf.NullType type, we do nothing.
+  if (data.type() == DataPiece::TYPE_NULL &&
+      field->type_url() != kStructNullValueTypeUrl) {
+    return this;
+  }
+
+  ProtoWriter::RenderDataPiece(name, data);
+  return this;
+}
+
+// Map of functions that are responsible for rendering well known type
+// represented by the key.
+hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
+    ProtoStreamObjectWriter::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_);
+
+void ProtoStreamObjectWriter::InitRendererMap() {
+  renderers_ = new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>();
+  (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] =
+      &ProtoStreamObjectWriter::RenderTimestamp;
+  (*renderers_)["type.googleapis.com/google.protobuf.Duration"] =
+      &ProtoStreamObjectWriter::RenderDuration;
+  (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] =
+      &ProtoStreamObjectWriter::RenderFieldMask;
+  (*renderers_)["type.googleapis.com/google.protobuf.Double"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Float"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Int64"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Int32"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Bool"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.String"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] =
+      &ProtoStreamObjectWriter::RenderWrapperType;
+  (*renderers_)["type.googleapis.com/google.protobuf.Value"] =
+      &ProtoStreamObjectWriter::RenderStructValue;
+  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectWriter::DeleteRendererMap() {
+  delete ProtoStreamObjectWriter::renderers_;
+  renderers_ = NULL;
+}
+
+ProtoStreamObjectWriter::TypeRenderer*
+ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
+  ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap);
+  return FindOrNull(*renderers_, type_url);
+}
+
+bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) {
+  if (current_ == NULL) return true;
+
+  if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) {
+    listener()->InvalidName(
+        location(), unnormalized_name,
+        StrCat("Repeated map key: '", unnormalized_name, "' is already set."));
+    return false;
+  }
+
+  return true;
+}
+
+void ProtoStreamObjectWriter::Push(StringPiece name, Item::ItemType item_type,
+                                   bool is_placeholder, bool is_list) {
+  is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name);
+
+  // invalid_depth == 0 means it is a successful StartObject or StartList.
+  if (invalid_depth() == 0)
+    current_.reset(
+        new Item(current_.release(), item_type, is_placeholder, is_list));
+}
+
+void ProtoStreamObjectWriter::Pop() {
+  // Pop all placeholder items sending StartObject or StartList events to
+  // ProtoWriter according to is_list value.
+  while (current_ != NULL && current_->is_placeholder()) {
+    PopOneElement();
+  }
+  if (current_ != NULL) {
+    PopOneElement();
+  }
+}
+
+void ProtoStreamObjectWriter::PopOneElement() {
+  current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject();
+  current_.reset(current_->pop<Item>());
+}
+
+bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
+  if (field.type_url().empty() ||
+      field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE ||
+      field.cardinality() !=
+          google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+    return false;
+  }
+  const google::protobuf::Type* field_type =
+      typeinfo()->GetTypeByTypeUrl(field.type_url());
+
+  // TODO(xiaofeng): Unify option names.
+  return GetBoolOptionOrDefault(field_type->options(),
+                                "google.protobuf.MessageOptions.map_entry", false) ||
+         GetBoolOptionOrDefault(field_type->options(), "map_entry", false);
+}
+
+bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
+  return GetTypeWithoutUrl(field.type_url()) == kAnyType;
+}
+
+bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) {
+  return GetTypeWithoutUrl(field.type_url()) == kStructType;
+}
+
+bool ProtoStreamObjectWriter::IsStructValue(
+    const google::protobuf::Field& field) {
+  return GetTypeWithoutUrl(field.type_url()) == kStructValueType;
+}
+
+bool ProtoStreamObjectWriter::IsStructListValue(
+    const google::protobuf::Field& field) {
+  return GetTypeWithoutUrl(field.type_url()) == kStructListValueType;
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.h
new file mode 100644
index 0000000..e1162d4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -0,0 +1,340 @@
+// 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_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
+
+#include <deque>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/datapiece.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/proto_writer.h>
+#include <google/protobuf/util/internal/structured_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class CodedOutputStream;
+}  // namespace io
+}  // namespace protobuf
+
+
+namespace protobuf {
+class Type;
+class Field;
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectLocationTracker;
+
+// An ObjectWriter that can write protobuf bytes directly from writer events.
+// This class supports all special types like Struct and Map. It uses
+// the ProtoWriter class to write raw proto bytes.
+//
+// It also supports streaming.
+class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
+ public:
+  // Options that control ProtoStreamObjectWriter class's behavior.
+  struct Options {
+    // Treats integer inputs in google.protobuf.Struct as strings. Normally,
+    // integer values are returned in double field "number_value" of
+    // google.protobuf.Struct. However, this can cause precision loss for
+    // int64/uint64 inputs. This option is provided for cases that want to
+    // preserve integer precision.
+    bool struct_integers_as_strings;
+
+    Options() : struct_integers_as_strings(false) {}
+
+    // Default instance of Options with all options set to defaults.
+    static const Options& Defaults() {
+      static Options defaults;
+      return defaults;
+    }
+  };
+
+// Constructor. Does not take ownership of any parameter passed in.
+  ProtoStreamObjectWriter(TypeResolver* type_resolver,
+                          const google::protobuf::Type& type,
+                          strings::ByteSink* output, ErrorListener* listener,
+                          const ProtoStreamObjectWriter::Options& options =
+                              ProtoStreamObjectWriter::Options::Defaults());
+  virtual ~ProtoStreamObjectWriter();
+
+  // ObjectWriter methods.
+  virtual ProtoStreamObjectWriter* StartObject(StringPiece name);
+  virtual ProtoStreamObjectWriter* EndObject();
+  virtual ProtoStreamObjectWriter* StartList(StringPiece name);
+  virtual ProtoStreamObjectWriter* EndList();
+
+  // Renders a DataPiece 'value' into a field whose wire type is determined
+  // from the given field 'name'.
+  virtual ProtoStreamObjectWriter* RenderDataPiece(StringPiece name,
+                                                   const DataPiece& value);
+
+ protected:
+  // Function that renders a well known type with modified behavior.
+  typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
+                                         const DataPiece&);
+
+  // Handles writing Anys out using nested object writers and the like.
+  class LIBPROTOBUF_EXPORT AnyWriter {
+   public:
+    explicit AnyWriter(ProtoStreamObjectWriter* parent);
+    ~AnyWriter();
+
+    // Passes a StartObject call through to the Any writer.
+    void StartObject(StringPiece name);
+
+    // Passes an EndObject call through to the Any. Returns true if the any
+    // handled the EndObject call, false if the Any is now all done and is no
+    // longer needed.
+    bool EndObject();
+
+    // Passes a StartList call through to the Any writer.
+    void StartList(StringPiece name);
+
+    // Passes an EndList call through to the Any writer.
+    void EndList();
+
+    // Renders a data piece on the any.
+    void RenderDataPiece(StringPiece name, const DataPiece& value);
+
+   private:
+    // Handles starting up the any once we have a type.
+    void StartAny(const DataPiece& value);
+
+    // Writes the Any out to the parent writer in its serialized form.
+    void WriteAny();
+
+    // The parent of this writer, needed for various bits such as type info and
+    // the listeners.
+    ProtoStreamObjectWriter* parent_;
+
+    // The nested object writer, used to write events.
+    google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+
+    // The type_url_ that this Any represents.
+    string type_url_;
+
+    // Whether this any is invalid. This allows us to only report an invalid
+    // Any message a single time rather than every time we get a nested field.
+    bool invalid_;
+
+    // The output data and wrapping ByteSink.
+    string data_;
+    strings::StringByteSink output_;
+
+    // The depth within the Any, so we can track when we're done.
+    int depth_;
+
+    // True if the type is a well-known type. Well-known types in Any
+    // has a special formating:
+    // {
+    //   "@type": "type.googleapis.com/google.protobuf.XXX",
+    //   "value": <JSON representation of the type>,
+    // }
+    bool is_well_known_type_;
+    TypeRenderer* well_known_type_render_;
+  };
+
+  // Represents an item in a stack of items used to keep state between
+  // ObjectWrier events.
+  class LIBPROTOBUF_EXPORT Item : public BaseElement {
+   public:
+    // Indicates the type of item.
+    enum ItemType {
+      MESSAGE,  // Simple message
+      MAP,      // Proto3 map type
+      ANY,      // Proto3 Any type
+    };
+
+    // Constructor for the root item.
+    Item(ProtoStreamObjectWriter* enclosing, ItemType item_type,
+         bool is_placeholder, bool is_list);
+
+    // Constructor for a field of a message.
+    Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list);
+
+    virtual ~Item() {}
+
+    // These functions return true if the element type is corresponding to the
+    // type in function name.
+    bool IsMap() { return item_type_ == MAP; }
+    bool IsAny() { return item_type_ == ANY; }
+
+    AnyWriter* any() const { return any_.get(); }
+
+    virtual Item* parent() const {
+      return static_cast<Item*>(BaseElement::parent());
+    }
+
+    // Inserts map key into hash set if and only if the key did NOT already
+    // exist in hash set.
+    // The hash set (map_keys_) is ONLY used to keep track of map keys.
+    // Return true if insert successfully; returns false if the map key was
+    // already present.
+    bool InsertMapKeyIfNotPresent(StringPiece map_key);
+
+    bool is_placeholder() const { return is_placeholder_; }
+    bool is_list() const { return is_list_; }
+
+   private:
+    // Used for access to variables of the enclosing instance of
+    // ProtoStreamObjectWriter.
+    ProtoStreamObjectWriter* ow_;
+
+    // A writer for Any objects, handles all Any-related nonsense.
+    google::protobuf::scoped_ptr<AnyWriter> any_;
+
+    // The type of this element, see enum for permissible types.
+    ItemType item_type_;
+
+    // Set of map keys already seen for the type_. Used to validate incoming
+    // messages so no map key appears more than once.
+    hash_set<string> map_keys_;
+
+    // Conveys whether this Item is a placeholder or not. Placeholder items are
+    // pushed to stack to account for special types.
+    bool is_placeholder_;
+
+    // Conveys whether this Item is a list or not. This is used to send
+    // StartList or EndList calls to underlying ObjectWriter.
+    bool is_list_;
+
+    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item);
+  };
+
+  ProtoStreamObjectWriter(const TypeInfo* typeinfo,
+                          const google::protobuf::Type& type,
+                          strings::ByteSink* output, ErrorListener* listener);
+
+  // Returns true if the field is a map.
+  bool IsMap(const google::protobuf::Field& field);
+
+  // Returns true if the field is an any.
+  bool IsAny(const google::protobuf::Field& field);
+
+  // Returns true if the field is google.protobuf.Struct.
+  bool IsStruct(const google::protobuf::Field& field);
+
+  // Returns true if the field is google.protobuf.Value.
+  bool IsStructValue(const google::protobuf::Field& field);
+
+  // Returns true if the field is google.protobuf.ListValue.
+  bool IsStructListValue(const google::protobuf::Field& field);
+
+  // Renders google.protobuf.Value in struct.proto. It picks the right oneof
+  // type based on value's type.
+  static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
+                                          const DataPiece& value);
+
+  // Renders google.protobuf.Timestamp value.
+  static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
+                                        const DataPiece& value);
+
+  // Renders google.protobuf.FieldMask value.
+  static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
+                                        const DataPiece& value);
+
+  // Renders google.protobuf.Duration value.
+  static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
+                                       const DataPiece& value);
+
+  // Renders wrapper message types for primitive types in
+  // google/protobuf/wrappers.proto.
+  static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
+                                          const DataPiece& value);
+
+  static void InitRendererMap();
+  static void DeleteRendererMap();
+  static TypeRenderer* FindTypeRenderer(const string& type_url);
+
+  // Returns true if the map key for type_ is not duplicated key.
+  // If map key is duplicated key, this function returns false.
+  // Note that caller should make sure that the current proto element (current_)
+  // is of element type MAP or STRUCT_MAP.
+  // It also calls the appropriate error callback and unnormalzied_name is used
+  // for error string.
+  bool ValidMapKey(StringPiece unnormalized_name);
+
+  // Pushes an item on to the stack. Also calls either StartObject or StartList
+  // on the underlying ObjectWriter depending on whether is_list is false or
+  // not.
+  // is_placeholder conveys whether the item is a placeholder item or not.
+  // Placeholder items are pushed when adding auxillary types' StartObject or
+  // StartList calls.
+  void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder,
+            bool is_list);
+
+  // Pops items from the stack. All placeholder items are popped until a
+  // non-placeholder item is found.
+  void Pop();
+
+  // Pops one element from the stack. Calls EndObject() or EndList() on the
+  // underlying ObjectWriter depending on the value of is_list_.
+  void PopOneElement();
+
+ private:
+  // Helper functions to create the map and find functions responsible for
+  // rendering well known types, keyed by type URL.
+  static hash_map<string, TypeRenderer>* renderers_;
+
+  // Variables for describing the structure of the input tree:
+  // master_type_: descriptor for the whole protobuf message.
+  const google::protobuf::Type& master_type_;
+
+  // The current element, variable for internal state processing.
+  google::protobuf::scoped_ptr<Item> current_;
+
+  // Reference to the options that control this class's behavior.
+  const ProtoStreamObjectWriter::Options options_;
+
+  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
new file mode 100644
index 0000000..9a0dcde
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -0,0 +1,2277 @@
+// 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.
+
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+
+#include <stddef.h>  // For size_t
+
+#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/timestamp.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/util/internal/mock_error_listener.h>
+#include <google/protobuf/util/internal/testdata/books.pb.h>
+#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/internal/testdata/anys.pb.h>
+#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/oneofs.pb.h>
+#include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::testing::Author;
+using google::protobuf::testing::Book;
+using google::protobuf::testing::Book_Data;
+using google::protobuf::testing::Primitive;
+using google::protobuf::testing::Publisher;
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::DynamicMessageFactory;
+using google::protobuf::FileDescriptorProto;
+using google::protobuf::Message;
+using google::protobuf::io::ArrayInputStream;
+using strings::GrowingArrayByteSink;
+using ::testing::_;
+using ::testing::Args;
+using google::protobuf::testing::anys::AnyM;
+using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::oneofs::OneOfsRequest;
+using google::protobuf::testing::FieldMaskTest;
+using google::protobuf::testing::maps::MapIn;
+using google::protobuf::testing::structs::StructType;
+using google::protobuf::testing::timestampduration::TimestampDuration;
+
+
+namespace {
+string GetTypeUrl(const Descriptor* descriptor) {
+  return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
+}
+}  // namespace
+
+#if __cplusplus >= 201103L
+  using std::get;
+#else
+  using std::tr1::get;
+#endif
+
+class BaseProtoStreamObjectWriterTest
+    : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+  BaseProtoStreamObjectWriterTest()
+      : helper_(GetParam()),
+        listener_(),
+        output_(new GrowingArrayByteSink(1000)),
+        ow_() {}
+
+  explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor)
+      : helper_(GetParam()),
+        listener_(),
+        output_(new GrowingArrayByteSink(1000)),
+        ow_() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(descriptor);
+    ResetTypeInfo(descriptors);
+  }
+
+  explicit BaseProtoStreamObjectWriterTest(
+      vector<const Descriptor*> descriptors)
+      : helper_(GetParam()),
+        listener_(),
+        output_(new GrowingArrayByteSink(1000)),
+        ow_() {
+    ResetTypeInfo(descriptors);
+  }
+
+  void ResetTypeInfo(vector<const Descriptor*> descriptors) {
+    GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
+    helper_.ResetTypeInfo(descriptors);
+    ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
+                                     &listener_, options_));
+  }
+
+  void ResetTypeInfo(const Descriptor* descriptor) {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(descriptor);
+    ResetTypeInfo(descriptors);
+  }
+
+  virtual ~BaseProtoStreamObjectWriterTest() {}
+
+  void CheckOutput(const Message& expected, int expected_length) {
+    size_t nbytes;
+    google::protobuf::scoped_array<char> buffer(output_->GetBuffer(&nbytes));
+    if (expected_length >= 0) {
+      EXPECT_EQ(expected_length, nbytes);
+    }
+    string str(buffer.get(), nbytes);
+
+    std::stringbuf str_buf(str, std::ios_base::in);
+    std::istream istream(&str_buf);
+    google::protobuf::scoped_ptr<Message> message(expected.New());
+    message->ParsePartialFromIstream(&istream);
+
+    if (!MessageDifferencer::Equivalent(expected, *message)) {
+      EXPECT_EQ(expected.DebugString(), message->DebugString());
+    }
+  }
+
+  void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
+
+  const google::protobuf::Type* GetType(const Descriptor* descriptor) {
+    return helper_.GetTypeInfo()->GetTypeByTypeUrl(GetTypeUrl(descriptor));
+  }
+
+  testing::TypeInfoTestHelper helper_;
+  MockErrorListener listener_;
+  google::protobuf::scoped_ptr<GrowingArrayByteSink> output_;
+  google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+  ProtoStreamObjectWriter::Options options_;
+};
+
+MATCHER_P(HasObjectLocation, expected,
+          "Verifies the expected object location") {
+  string actual = get<0>(arg).ToString();
+  if (actual.compare(expected) == 0) return true;
+  *result_listener << "actual location is: " << actual;
+  return false;
+}
+
+class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterTest()
+      : BaseProtoStreamObjectWriterTest(Book::descriptor()) {}
+
+  virtual ~ProtoStreamObjectWriterTest() {}
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterTest, EmptyObject) {
+  Book empty;
+  ow_->StartObject("")->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, SimpleObject) {
+  string content("My content");
+
+  Book book;
+  book.set_title("My Title");
+  book.set_length(222);
+  book.set_content(content);
+
+  ow_->StartObject("")
+      ->RenderString("title", "My Title")
+      ->RenderInt32("length", 222)
+      ->RenderBytes("content", content)
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) {
+  Book book;
+  book.set_title("Some Book");
+  book.set_length(102);
+  Publisher* publisher = book.mutable_publisher();
+  publisher->set_name("My Publisher");
+  Author* robert = book.mutable_author();
+  robert->set_alive(true);
+  robert->set_name("robert");
+  robert->add_pseudonym("bob");
+  robert->add_pseudonym("bobby");
+  robert->add_friend_()->set_name("john");
+
+  ow_->StartObject("")
+      ->RenderString("title", "Some Book")
+      ->RenderInt32("length", 102)
+      ->StartObject("publisher")
+      ->RenderString("name", "My Publisher")
+      ->EndObject()
+      ->StartObject("author")
+      ->RenderBool("alive", true)
+      ->RenderString("name", "robert")
+      ->StartList("pseudonym")
+      ->RenderString("", "bob")
+      ->RenderString("", "bobby")
+      ->EndList()
+      ->StartList("friend")
+      ->StartObject("")
+      ->RenderString("name", "john")
+      ->EndObject()
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, CustomJsonName) {
+  Book book;
+  Author* robert = book.mutable_author();
+  robert->set_id(12345);
+  robert->set_name("robert");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderUint64("@id", 12345)
+      ->RenderString("name", "robert")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) {
+  Primitive full;
+  full.set_fix32(101);
+  full.set_u32(102);
+  full.set_i32(-103);
+  full.set_sf32(-104);
+  full.set_s32(-105);
+  full.set_fix64(40000000001L);
+  full.set_u64(40000000002L);
+  full.set_i64(-40000000003L);
+  full.set_sf64(-40000000004L);
+  full.set_s64(-40000000005L);
+  full.set_str("string1");
+  full.set_bytes("Some Bytes");
+  full.set_float_(3.14f);
+  full.set_double_(-4.05L);
+  full.set_bool_(true);
+  full.add_rep_fix32(201);
+  full.add_rep_u32(202);
+  full.add_rep_i32(-203);
+  full.add_rep_sf32(-204);
+  full.add_rep_s32(-205);
+  full.add_rep_fix64(80000000001L);
+  full.add_rep_u64(80000000002L);
+  full.add_rep_i64(-80000000003L);
+  full.add_rep_sf64(-80000000004L);
+  full.add_rep_s64(-80000000005L);
+  full.add_rep_str("string2");
+  full.add_rep_bytes("More Bytes");
+  full.add_rep_float(6.14f);
+  full.add_rep_double(-8.05L);
+  full.add_rep_bool(false);
+
+  ResetTypeInfo(Primitive::descriptor());
+
+  ow_->StartObject("")
+      ->RenderString("fix32", "101")
+      ->RenderString("u32", "102")
+      ->RenderString("i32", "-103")
+      ->RenderString("sf32", "-104")
+      ->RenderString("s32", "-105")
+      ->RenderString("fix64", "40000000001")
+      ->RenderString("u64", "40000000002")
+      ->RenderString("i64", "-40000000003")
+      ->RenderString("sf64", "-40000000004")
+      ->RenderString("s64", "-40000000005")
+      ->RenderString("str", "string1")
+      ->RenderString("bytes", "U29tZSBCeXRlcw==")  // "Some Bytes"
+      ->RenderString("float", "3.14")
+      ->RenderString("double", "-4.05")
+      ->RenderString("bool", "true")
+      ->StartList("rep_fix32")
+      ->RenderString("", "201")
+      ->EndList()
+      ->StartList("rep_u32")
+      ->RenderString("", "202")
+      ->EndList()
+      ->StartList("rep_i32")
+      ->RenderString("", "-203")
+      ->EndList()
+      ->StartList("rep_sf32")
+      ->RenderString("", "-204")
+      ->EndList()
+      ->StartList("rep_s32")
+      ->RenderString("", "-205")
+      ->EndList()
+      ->StartList("rep_fix64")
+      ->RenderString("", "80000000001")
+      ->EndList()
+      ->StartList("rep_u64")
+      ->RenderString("", "80000000002")
+      ->EndList()
+      ->StartList("rep_i64")
+      ->RenderString("", "-80000000003")
+      ->EndList()
+      ->StartList("rep_sf64")
+      ->RenderString("", "-80000000004")
+      ->EndList()
+      ->StartList("rep_s64")
+      ->RenderString("", "-80000000005")
+      ->EndList()
+      ->StartList("rep_str")
+      ->RenderString("", "string2")
+      ->EndList()
+      ->StartList("rep_bytes")
+      ->RenderString("", "TW9yZSBCeXRlcw==")  // "More Bytes"
+      ->EndList()
+      ->StartList("rep_float")
+      ->RenderString("", "6.14")
+      ->EndList()
+      ->StartList("rep_double")
+      ->RenderString("", "-8.05")
+      ->EndList()
+      ->StartList("rep_bool")
+      ->RenderString("", "false")
+      ->EndList()
+      ->EndObject();
+  CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) {
+  Primitive full;
+  full.set_double_(std::numeric_limits<double>::infinity());
+  full.set_float_(std::numeric_limits<float>::infinity());
+  full.set_str("-Infinity");
+
+  ResetTypeInfo(Primitive::descriptor());
+
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
+                                      StringPiece("\"Infinity\"")))
+      .With(Args<0>(HasObjectLocation("i32")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+                                      StringPiece("\"Infinity\"")))
+      .With(Args<0>(HasObjectLocation("u32")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
+                                      StringPiece("\"-Infinity\"")))
+      .With(Args<0>(HasObjectLocation("sf64")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
+                                      StringPiece("\"Infinity\"")))
+      .With(Args<0>(HasObjectLocation("bool")));
+
+  ow_->StartObject("")
+      ->RenderString("double", "Infinity")
+      ->RenderString("float", "Infinity")
+      ->RenderString("i32", "Infinity")
+      ->RenderString("u32", "Infinity")
+      ->RenderString("sf64", "-Infinity")
+      ->RenderString("str", "-Infinity")
+      ->RenderString("bool", "Infinity")
+      ->EndObject();
+  CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) {
+  Primitive full;
+  full.set_double_(std::numeric_limits<double>::quiet_NaN());
+  full.set_float_(std::numeric_limits<float>::quiet_NaN());
+  full.set_str("NaN");
+
+  ResetTypeInfo(Primitive::descriptor());
+
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
+                                      StringPiece("\"NaN\"")))
+      .With(Args<0>(HasObjectLocation("i32")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+                                      StringPiece("\"NaN\"")))
+      .With(Args<0>(HasObjectLocation("u32")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
+                                      StringPiece("\"NaN\"")))
+      .With(Args<0>(HasObjectLocation("sf64")));
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("TYPE_BOOL"), StringPiece("\"NaN\"")))
+      .With(Args<0>(HasObjectLocation("bool")));
+
+  ow_->StartObject("")
+      ->RenderString("double", "NaN")
+      ->RenderString("float", "NaN")
+      ->RenderString("i32", "NaN")
+      ->RenderString("u32", "NaN")
+      ->RenderString("sf64", "NaN")
+      ->RenderString("str", "NaN")
+      ->RenderString("bool", "NaN")
+      ->EndObject();
+
+  CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("The Author");
+  author->add_pseudonym("first");
+  author->add_pseudonym("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "The Author")
+      ->RenderString("pseudonym", "first")
+      ->RenderString("pseudonym", "second")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
+       LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "first")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("The Author");
+  author->add_pseudonym("first");
+  author->add_pseudonym("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "The Author")
+      ->StartList("pseudonym")
+      ->RenderString("", "first")
+      ->RenderString("", "second")
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) {
+  Book expected;
+  expected.set_allocated_author(new Author());
+
+  EXPECT_CALL(
+      listener_,
+      InvalidName(
+          _, StringPiece("name"),
+          StringPiece("Proto field is not repeating, cannot start list.")))
+      .With(Args<0>(HasObjectLocation("author")));
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->StartList("name")
+      ->RenderString("", "first")
+      ->RenderString("", "second")
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) {
+  Book expected;
+  Author* outer = expected.mutable_author();
+  outer->set_name("outer");
+  outer->set_alive(true);
+  Author* first = outer->add_friend_();
+  first->set_name("first");
+  Author* second = outer->add_friend_();
+  second->set_name("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "outer")
+      ->RenderBool("alive", true)
+      ->StartObject("friend")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("friend")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
+       LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("The Author");
+  Publisher* publisher = expected.mutable_publisher();
+  publisher->set_name("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "The Author")
+      ->EndObject()
+      ->StartObject("publisher")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("publisher")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) {
+  Book expected;
+  Author* outer = expected.mutable_author();
+  outer->set_name("outer");
+  outer->set_alive(true);
+  Author* first = outer->add_friend_();
+  first->set_name("first");
+  Author* second = outer->add_friend_();
+  second->set_name("second");
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "outer")
+      ->RenderBool("alive", true)
+      ->StartList("friend")
+      ->StartObject("")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("The Author");
+
+  EXPECT_CALL(
+      listener_,
+      InvalidName(
+          _, StringPiece("publisher"),
+          StringPiece("Proto field is not repeating, cannot start list.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "The Author")
+      ->EndObject()
+      ->StartList("publisher")
+      ->StartObject("")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndList()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) {
+  Book empty;
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) {
+  Book expected;
+  Author* paul = expected.mutable_author();
+  paul->set_name("Paul");
+  Author* mark = paul->add_friend_();
+  mark->set_name("Mark");
+  Author* john = paul->add_friend_();
+  john->set_name("John");
+  Author* luke = paul->add_friend_();
+  luke->set_name("Luke");
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("author.friend[1]")));
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "Paul")
+      ->StartList("friend")
+      ->StartObject("")
+      ->RenderString("name", "Mark")
+      ->EndObject()
+      ->StartObject("")
+      ->RenderString("name", "John")
+      ->RenderString("address", "Patmos")
+      ->EndObject()
+      ->StartObject("")
+      ->RenderString("name", "Luke")
+      ->EndObject()
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) {
+  Book empty;
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) {
+  Book expected;
+  Author* author = expected.mutable_author();
+  author->set_name("William");
+  author->add_pseudonym("Bill");
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("author")));
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderString("name", "William")
+      ->StartObject("wife")
+      ->RenderString("name", "Hilary")
+      ->EndObject()
+      ->RenderString("pseudonym", "Bill")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) {
+  Book empty;
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) {
+  Book expected;
+  expected.set_title("Brainwashing");
+  Publisher* publisher = expected.mutable_publisher();
+  publisher->set_name("propaganda");
+
+  EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"),
+                                     StringPiece("Cannot find field.")))
+      .With(Args<0>(HasObjectLocation("publisher")));
+  ow_->StartObject("")
+      ->StartObject("publisher")
+      ->RenderString("name", "propaganda")
+      ->StartList("alliance")
+      ->EndList()
+      ->EndObject()
+      ->RenderString("title", "Brainwashing")
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) {
+  Book expected;
+  expected.set_title("My Title");
+  expected.set_allocated_publisher(new Publisher());
+
+  EXPECT_CALL(listener_, MissingField(_, StringPiece("name")))
+      .With(Args<0>(HasObjectLocation("publisher")));
+  ow_->StartObject("")
+      ->StartObject("publisher")
+      ->EndObject()
+      ->RenderString("title", "My Title")
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) {
+  Book empty;
+
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+                                      StringPiece("\"garbage\"")))
+      .With(Args<0>(HasObjectLocation("length")));
+  ow_->StartObject("")->RenderString("length", "garbage")->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) {
+  Book expected;
+  expected.set_title("My Title");
+
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+                                      StringPiece("\"-400\"")))
+      .With(Args<0>(HasObjectLocation("length")));
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"),
+                                      StringPiece("\"3.14\"")))
+      .With(Args<0>(HasObjectLocation("published")));
+  ow_->StartObject("")
+      ->RenderString("length", "-400")
+      ->RenderString("published", "3.14")
+      ->RenderString("title", "My Title")
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) {
+  Book empty;
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece(""),
+                          StringPiece("Proto fields must have a name.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")->RenderFloat("", 3.14)->EndObject();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) {
+  Book expected;
+  expected.set_title("noname");
+  expected.set_allocated_author(new Author());
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece(""),
+                          StringPiece("Proto fields must have a name.")))
+      .With(Args<0>(HasObjectLocation("author")));
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->RenderInt32("", 123)
+      ->EndObject()
+      ->RenderString("title", "noname")
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) {
+  Book expected;
+  expected.set_title("noname");
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece(""),
+                          StringPiece("Proto fields must have a name.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")
+      ->StartList("")
+      ->EndList()
+      ->RenderString("title", "noname")
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) {
+  Book expected;
+  expected.set_title("Annie");
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece("oops"),
+                          StringPiece("Root element should not be named.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject();
+  CheckOutput(expected, 7);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedList) {
+  Book empty;
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece("oops"),
+                          StringPiece("Root element should not be named.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartList("oops")->RenderString("", "item")->EndList();
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) {
+  Book empty;
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece(""),
+                          StringPiece("Root element must be a message.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->RenderBool("", true);
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedField) {
+  Book empty;
+
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece("oops"),
+                          StringPiece("Root element must be a message.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->RenderBool("oops", true);
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValue) {
+  Book empty;
+
+  ow_->RenderNull("");
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) {
+  Book empty;
+
+  ow_->RenderNull("author");
+  CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) {
+  Book empty;
+
+  ow_->RenderNull("length");
+  CheckOutput(empty, 0);
+}
+
+class ProtoStreamObjectWriterTimestampDurationTest
+    : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterTimestampDurationTest() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(TimestampDuration::descriptor());
+    descriptors.push_back(google::protobuf::Timestamp::descriptor());
+    descriptors.push_back(google::protobuf::Duration::descriptor());
+    ResetTypeInfo(descriptors);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterTimestampDurationTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseTimestamp) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(1448249855);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2015-11-23T03:37:35.033155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampYearNotZeroPadded) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(-61665654145);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "15-11-23T03:37:35.033155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampYearZeroPadded) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(-61665654145);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "0015-11-23T03:37:35.033155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampWithPositiveOffset) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(1448249855);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2015-11-23T11:47:35.033155+08:10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampWithNegativeOffset) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(1448249855);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2015-11-22T19:47:35.033155-07:50")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset1) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+")));
+
+  ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset2) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+08-10")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+08-10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset3) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+24:10")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+24:10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset4) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+04:60")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+04:60")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: ")));
+
+  ow_->StartObject("")->RenderString("ts", "")->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: Z")));
+
+  ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "1970-01-01T00:00:00.ABZ")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "-8031-10-18T00:00:00.000Z")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError5) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2015-11-23T03:37:35.033155   Z")));
+
+  ow_->StartObject("")
+      // Whitespace in the Timestamp nanos is not allowed.
+      ->RenderString("ts", "2015-11-23T03:37:35.033155   Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError6) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2015-11-23T03:37:35.033155 1234Z")));
+
+  ow_->StartObject("")
+      // Whitespace in the Timestamp nanos is not allowed.
+      ->RenderString("ts", "2015-11-23T03:37:35.033155 1234Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError7) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2015-11-23T03:37:35.033abc155Z")));
+
+  ow_->StartObject("")
+      // Non-numeric characters in the Timestamp nanos is not allowed.
+      ->RenderString("ts", "2015-11-23T03:37:35.033abc155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "0-12-31T23:59:59.000Z")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "0-12-31T23:59:59.000Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseDuration) {
+  TimestampDuration duration;
+  google::protobuf::Duration* dur = duration.mutable_dur();
+  dur->set_seconds(1448216930);
+  dur->set_nanos(132262000);
+
+  ow_->StartObject("")->RenderString("dur", "1448216930.132262s")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
+  TimestampDuration duration;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+          StringPiece("Field 'dur', Illegal duration format; duration must "
+                      "end with 's'")));
+
+  ow_->StartObject("")->RenderString("dur", "")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
+  TimestampDuration duration;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+          StringPiece("Field 'dur', Invalid duration format, failed to parse "
+                      "seconds")));
+
+  ow_->StartObject("")->RenderString("dur", "s")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
+  TimestampDuration duration;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+          StringPiece("Field 'dur', Invalid duration format, failed to "
+                      "parse nano seconds")));
+
+  ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) {
+  TimestampDuration duration;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Duration"),
+                   StringPiece("Field 'dur', Duration value exceeds limits")));
+
+  ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError5) {
+  TimestampDuration duration;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Duration"),
+                   StringPiece("Field 'dur', Duration value exceeds limits")));
+
+  ow_->StartObject("")->RenderString("dur", "0.1000000001s")->EndObject();
+  CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       MismatchedTimestampTypeInput) {
+  TimestampDuration timestamp;
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+          StringPiece(
+              "Field 'ts', Invalid data type for timestamp, value is null")))
+      .With(Args<0>(HasObjectLocation("ts")));
+  ow_->StartObject("")->RenderNull("ts")->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       MismatchedDurationTypeInput) {
+  TimestampDuration duration;
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+          StringPiece(
+              "Field 'dur', Invalid data type for duration, value is null")))
+      .With(Args<0>(HasObjectLocation("dur")));
+  ow_->StartObject("")->RenderNull("dur")->EndObject();
+  CheckOutput(duration);
+}
+
+class ProtoStreamObjectWriterStructTest
+    : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
+
+  // Resets ProtoWriter with current set of options and other state.
+  void ResetProtoWriter() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(StructType::descriptor());
+    descriptors.push_back(google::protobuf::Struct::descriptor());
+    ResetTypeInfo(descriptors);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterStructTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+// TODO(skarvaje): Write tests for failure cases.
+TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) {
+  StructType struct_type;
+  google::protobuf::Struct* s = struct_type.mutable_object();
+  s->mutable_fields()->operator[]("k1").set_number_value(123);
+  s->mutable_fields()->operator[]("k2").set_bool_value(true);
+
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->RenderDouble("k1", 123)
+      ->RenderBool("k2", true)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(struct_type);
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) {
+  StructType struct_type;
+  EXPECT_CALL(listener_,
+              InvalidName(_, StringPiece(""),
+                          StringPiece("Proto fields must have a name.")))
+      .With(Args<0>(HasObjectLocation("")));
+  ow_->StartObject("")->RenderNull("")->EndObject();
+  CheckOutput(struct_type);
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) {
+  StructType struct_type;
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Struct"),
+                   StringPiece("true")))
+      .With(Args<0>(HasObjectLocation("object")));
+
+  ow_->StartObject("")->RenderBool("object", true)->EndObject();
+  CheckOutput(struct_type);
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
+  EXPECT_CALL(
+      listener_,
+      InvalidName(_, StringPiece("gBike"),
+                  StringPiece("Repeated map key: 'gBike' is already set.")));
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->RenderString("gBike", "v1")
+      ->RenderString("gBike", "v2")
+      ->EndObject()
+      ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) {
+  EXPECT_CALL(
+      listener_,
+      InvalidName(_, StringPiece("k1"),
+                  StringPiece("Repeated map key: 'k1' is already set.")));
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->RenderString("k1", "v1")
+      ->StartList("k1")
+      ->RenderString("", "v2")
+      ->EndList()
+      ->EndObject()
+      ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
+  EXPECT_CALL(
+      listener_,
+      InvalidName(_, StringPiece("k1"),
+                  StringPiece("Repeated map key: 'k1' is already set.")));
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->StartObject("k1")
+      ->RenderString("sub_k1", "v1")
+      ->EndObject()
+      ->StartObject("k1")
+      ->RenderString("sub_k2", "v2")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) {
+  StructType struct_type;
+  google::protobuf::Struct* s = struct_type.mutable_object();
+  s->mutable_fields()->operator[]("k1").set_number_value(123);
+  s->mutable_fields()->operator[]("k2").set_bool_value(true);
+  s->mutable_fields()->operator[]("k3").set_string_value("-222222222");
+  s->mutable_fields()->operator[]("k4").set_string_value("33333333");
+
+  options_.struct_integers_as_strings = true;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->RenderDouble("k1", 123)
+      ->RenderBool("k2", true)
+      ->RenderInt64("k3", -222222222)
+      ->RenderUint64("k4", 33333333)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(struct_type);
+}
+
+class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterMapTest()
+      : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {}
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterMapTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
+  MapIn mm;
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("Map"),
+          StringPiece("Cannot bind a list to map for field 'map_input'.")));
+  ow_->StartObject("")
+      ->StartList("map_input")
+      ->RenderString("a", "b")
+      ->EndList()
+      ->EndObject();
+  CheckOutput(mm);
+}
+
+TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) {
+  EXPECT_CALL(
+      listener_,
+      InvalidName(_, StringPiece("k1"),
+                  StringPiece("Repeated map key: 'k1' is already set.")));
+  ow_->StartObject("")
+      ->RenderString("other", "test")
+      ->StartObject("map_input")
+      ->RenderString("k1", "v1")
+      ->RenderString("k1", "v2")
+      ->EndObject()
+      ->EndObject();
+}
+
+class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterAnyTest() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(AnyOut::descriptor());
+    descriptors.push_back(google::protobuf::DoubleValue::descriptor());
+    descriptors.push_back(google::protobuf::Timestamp::descriptor());
+    descriptors.push_back(google::protobuf::Any::descriptor());
+    descriptors.push_back(google::protobuf::Value::descriptor());
+    descriptors.push_back(google::protobuf::Struct::descriptor());
+    ResetTypeInfo(descriptors);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterAnyTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue");
+  google::protobuf::DoubleValue d;
+  d.set_value(40.2);
+  any_type->set_value(d.SerializeAsString());
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
+      ->RenderDouble("value", 40.2)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any nested_any;
+  nested_any.set_type_url(
+      "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  nested_any.set_value(m.SerializeAsString());
+
+  any->set_value(nested_any.SerializeAsString());
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type",
+                     "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+  any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any nested_any;
+  nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ::google::protobuf::Any second_nested_any;
+  second_nested_any.set_type_url(
+      "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+  AnyM m;
+  m.set_foo("foovalue");
+  second_nested_any.set_value(m.SerializeAsString());
+
+  nested_any.set_value(second_nested_any.SerializeAsString());
+  any->set_value(nested_any.SerializeAsString());
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->StartObject("value")
+      ->RenderString("@type",
+                     "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
+  AnyOut out;
+  out.mutable_any();
+
+  ow_->StartObject("")->StartObject("any")->EndObject()->EndObject();
+
+  CheckOutput(out, 2);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
+  AnyOut any;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_, StringPiece("Any"),
+                   StringPiece("Missing or invalid @type for any field in "
+                               "google.protobuf.testing.anys.AnyOut")));
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->StartObject("another")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
+  AnyOut any;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_, StringPiece("Any"),
+                   StringPiece("Missing or invalid @type for any field in "
+                               "google.protobuf.testing.anys.AnyOut")));
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->StartList("another")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
+  AnyOut any;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_, StringPiece("Any"),
+                   StringPiece("Missing or invalid @type for any field in "
+                               "google.protobuf.testing.anys.AnyOut")));
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("value", "somevalue")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
+  AnyOut any;
+
+  EXPECT_CALL(listener_,
+              InvalidValue(
+                  _, StringPiece("Any"),
+                  StringPiece("Invalid type URL, type URLs must be of the form "
+                              "'type.googleapis.com/<typename>', got: "
+                              "type.other.com/some.Type")));
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.other.com/some.Type")
+      ->RenderDouble("value", 40.2)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) {
+  AnyOut any;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_, StringPiece("Any"),
+                   StringPiece("Invalid type URL, unknown type: some.Type")));
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/some.Type")
+      ->RenderDouble("value", 40.2)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) {
+  AnyOut any;
+
+  ow_->StartObject("")->RenderNull("any")->EndObject();
+  CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+                                      StringPiece("Invalid time format: ")));
+
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
+      ->RenderString("value", "")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "value": "abc"
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedPrimitiveValue) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+
+  ::google::protobuf::Value value;
+  value.set_string_value("abc");
+  any->PackFrom(value);
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->RenderString("value", "abc")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "value": {
+//       "foo": "abc"
+//     }
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedObjectValue) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+
+  ::google::protobuf::Value value;
+  (*value.mutable_struct_value()->mutable_fields())["foo"].set_string_value(
+      "abc");
+  any->PackFrom(value);
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->StartObject("value")
+      ->RenderString("foo", "abc")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "value": ["hello"],
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedArrayValue) {
+  AnyOut out;
+  ::google::protobuf::Any* any = out.mutable_any();
+
+  ::google::protobuf::Value value;
+  value.mutable_list_value()->add_values()->set_string_value("hello");
+  any->PackFrom(value);
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->StartList("value")
+      ->RenderString("", "hello")
+      ->EndList()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "not_value": ""
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest,
+       AnyWellKnownTypesNoValueFieldForPrimitive) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("Any"),
+          StringPiece("Expect a \"value\" field for well-known types.")));
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->RenderString("not_value", "")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "not_value": {}
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForObject) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("Any"),
+          StringPiece("Expect a \"value\" field for well-known types.")));
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->StartObject("not_value")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Value",
+//     "not_value": [],
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("Any"),
+          StringPiece("Expect a \"value\" field for well-known types.")));
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+      ->StartList("not_value")
+      ->EndList()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Struct",
+//     "value": "",
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) {
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+                                      StringPiece("Expect a JSON object.")));
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Struct");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Struct")
+      ->RenderString("value", "")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+//   "any": {
+//     "@type": "type.googleapis.com/google.protobuf.Any",
+//     "value": "",
+//   }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) {
+  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+                                      StringPiece("Expect a JSON object.")));
+  AnyOut any;
+  google::protobuf::Any* any_type = any.mutable_any();
+  any_type->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+  ow_->StartObject("")
+      ->StartObject("any")
+      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+      ->RenderString("value", "")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(any);
+}
+
+class ProtoStreamObjectWriterFieldMaskTest
+    : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterFieldMaskTest() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(FieldMaskTest::descriptor());
+    descriptors.push_back(google::protobuf::FieldMask::descriptor());
+    ResetTypeInfo(descriptors);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterFieldMaskTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
+  FieldMaskTest expected;
+  expected.set_id("1");
+  expected.mutable_single_mask()->add_paths("path1");
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->RenderString("single_mask", "path1");
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MutipleMasksInCompactForm) {
+  FieldMaskTest expected;
+  expected.set_id("1");
+  expected.mutable_single_mask()->add_paths("camel_case1");
+  expected.mutable_single_mask()->add_paths("camel_case2");
+  expected.mutable_single_mask()->add_paths("camel_case3");
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3");
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) {
+  FieldMaskTest expected;
+  expected.set_id("1");
+  google::protobuf::FieldMask* mask = expected.add_repeated_mask();
+  mask->add_paths("field1");
+  mask->add_paths("field2");
+  expected.add_repeated_mask()->add_paths("field3");
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->StartList("repeated_mask");
+  ow_->RenderString("", "field1,field2");
+  ow_->RenderString("", "field3");
+  ow_->EndList();
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) {
+  FieldMaskTest expected;
+  expected.set_id("1");
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->RenderString("single_mask", "");
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
+  FieldMaskTest expected;
+  expected.set_id("1");
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  // Case1
+  ow_->RenderString("single_mask",
+                    "outerField(camelCase1,camelCase2,camelCase3)");
+  expected.mutable_single_mask()->add_paths("outer_field.camel_case1");
+  expected.mutable_single_mask()->add_paths("outer_field.camel_case2");
+  expected.mutable_single_mask()->add_paths("outer_field.camel_case3");
+
+  ow_->StartList("repeated_mask");
+
+  ow_->RenderString("", "a(field1,field2)");
+  google::protobuf::FieldMask* mask = expected.add_repeated_mask();
+  mask->add_paths("a.field1");
+  mask->add_paths("a.field2");
+
+  ow_->RenderString("", "a(field3)");
+  mask = expected.add_repeated_mask();
+  mask->add_paths("a.field3");
+
+  ow_->RenderString("", "a()");
+  expected.add_repeated_mask();
+
+  ow_->RenderString("", "a(,)");
+  expected.add_repeated_mask();
+
+  ow_->RenderString("", "a(field1(field2(field3)))");
+  mask = expected.add_repeated_mask();
+  mask->add_paths("a.field1.field2.field3");
+
+  ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)");
+  mask = expected.add_repeated_mask();
+  mask->add_paths("a.field1.field2.field3");
+  mask->add_paths("a.field1.field2.field4");
+  mask->add_paths("a.field1.field5");
+  mask->add_paths("a.field6");
+
+  ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)");
+  mask = expected.add_repeated_mask();
+  mask->add_paths("a.id");
+  mask->add_paths("a.field1.id");
+  mask->add_paths("a.field1.field2.field3");
+  mask->add_paths("a.field1.field2.field4");
+  mask->add_paths("a.field1.field5");
+  mask->add_paths("a.field6");
+
+  ow_->RenderString("", "a(((field3,field4)))");
+  mask = expected.add_repeated_mask();
+  mask->add_paths("a.field3");
+  mask->add_paths("a.field4");
+
+  ow_->EndList();
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+          StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
+                      "Cannot find matching '(' for all ')'.")));
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->RenderString("single_mask", "a(b,c))");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+          StringPiece(
+              "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
+              "find matching ')' for all '('.")));
+
+  ow_->StartObject("");
+  ow_->RenderString("id", "1");
+  ow_->RenderString("single_mask", "a(((b,c)");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) {
+  FieldMaskTest expected;
+  expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]");
+  expected.mutable_single_mask()->add_paths(
+      "path.to.map[\"e\\\"[]][scape\\\"\"]");
+  expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
+
+  ow_->StartObject("");
+  ow_->RenderString("single_mask",
+                    "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"],"
+                    "path.to.map[\"key2\"]");
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest,
+       MapKeyMustBeAtTheEndOfAPathSegment) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+          StringPiece("Field 'single_mask', Invalid FieldMask "
+                      "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
+                      "Map keys should be at the end of a path segment.")));
+
+  ow_->StartObject("");
+  ow_->RenderString("single_mask",
+                    "path.to.map[\"key1\"]a,path.to.map[\"key2\"]");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+                   StringPiece("Field 'single_mask', Invalid FieldMask "
+                               "'path.to.map[\"key1\"'. Map keys should be "
+                               "represented as [\"some_key\"].")));
+
+  ow_->StartObject("");
+  ow_->RenderString("single_mask", "path.to.map[\"key1\"");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+                   StringPiece("Field 'single_mask', Invalid FieldMask "
+                               "'path.to.map[\"ke\"y1\"]'. Map keys should be "
+                               "represented as [\"some_key\"].")));
+
+  ow_->StartObject("");
+  ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
+  FieldMaskTest expected;
+  expected.mutable_single_mask()->add_paths(
+      // \xE5\xAD\x99 is the UTF-8 byte sequence for chinese character 孙.
+      // We cannot embed non-ASCII characters in the code directly because
+      // some windows compilers will try to interpret them using the system's
+      // current encoding and end up with invalid UTF-8 byte sequence.
+      "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"]");
+  expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
+
+  ow_->StartObject("");
+  ow_->RenderString(
+      "single_mask",
+      "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"],"
+      "path.to.map[\"key2\"]");
+  ow_->EndObject();
+
+  CheckOutput(expected);
+}
+
+class ProtoStreamObjectWriterOneOfsTest
+    : public BaseProtoStreamObjectWriterTest {
+ protected:
+  ProtoStreamObjectWriterOneOfsTest() {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(OneOfsRequest::descriptor());
+    descriptors.push_back(google::protobuf::Struct::descriptor());
+    ResetTypeInfo(descriptors);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtoStreamObjectWriterOneOfsTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForPrimitiveTypesTest) {
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("oneof"),
+          StringPiece(
+              "oneof field 'data' is already set. Cannot set 'intData'")));
+
+  ow_->StartObject("");
+  ow_->RenderString("strData", "blah");
+  ow_->RenderString("intData", "123");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
+  // Test for setting primitive oneof field first and then message field.
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'messageData'")));
+
+  // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
+  ow_->StartObject("");
+  ow_->RenderString("strData", "blah");
+  ow_->StartObject("messageData");
+  ow_->RenderInt32("dataValue", 123);
+  ow_->EndObject();
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForMessageTypesMessageFirstTest) {
+  // Test for setting message oneof field first and then primitive field.
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'strData'")));
+
+  // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
+  ow_->StartObject("");
+  ow_->StartObject("messageData");
+  ow_->RenderInt32("dataValue", 123);
+  ow_->EndObject();
+  ow_->RenderString("strData", "blah");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'structData'")));
+
+  // JSON: { "strData": "blah", "structData": { "a": "b" } }
+  ow_->StartObject("");
+  ow_->RenderString("strData", "blah");
+  ow_->StartObject("structData");
+  ow_->RenderString("a", "b");
+  ow_->EndObject();
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForStructTypesStructFirstTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'strData'")));
+
+  // JSON: { "structData": { "a": "b" }, "strData": "blah" }
+  ow_->StartObject("");
+  ow_->StartObject("structData");
+  ow_->RenderString("a", "b");
+  ow_->EndObject();
+  ow_->RenderString("strData", "blah");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForStructValueTypesTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'valueData'")));
+
+  // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
+  ow_->StartObject("");
+  ow_->StartObject("messageData");
+  ow_->RenderInt32("dataValue", 123);
+  ow_->EndObject();
+  ow_->StartObject("valueData");
+  ow_->RenderString("a", "b");
+  ow_->EndObject();
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'tsData'")));
+
+  // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
+  ow_->StartObject("");
+  ow_->RenderInt32("intData", 123);
+  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForWellKnownTypesWktFirstTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'intData'")));
+
+  // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
+  ow_->StartObject("");
+  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+  ow_->RenderInt32("intData", 123);
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForWellKnownTypesAndMessageTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'messageData'")));
+
+  // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
+  //         "messageData": { "dataValue": 123 } }
+  ow_->StartObject("");
+  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+  ow_->StartObject("messageData");
+  ow_->RenderInt32("dataValue", 123);
+  ow_->EndObject();
+  ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+       MultipleOneofsFailForOneofWithinAnyTest) {
+  EXPECT_CALL(listener_,
+              InvalidValue(_, StringPiece("oneof"),
+                           StringPiece("oneof field 'data' is already set. "
+                                       "Cannot set 'intData'")));
+
+  using google::protobuf::testing::oneofs::OneOfsRequest;
+  // JSON:
+  // { "anyData":
+  //    { "@type":
+  //       "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest",
+  //     "strData": "blah",
+  //     "intData": 123
+  //    }
+  // }
+  ow_->StartObject("");
+  ow_->StartObject("anyData");
+  ow_->RenderString(
+      "@type",
+      "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest");
+  ow_->RenderString("strData", "blah");
+  ow_->RenderInt32("intData", 123);
+  ow_->EndObject();
+  ow_->EndObject();
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/structured_objectwriter.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/structured_objectwriter.h
new file mode 100644
index 0000000..3f065d6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/structured_objectwriter.h
@@ -0,0 +1,118 @@
+// 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_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/object_writer.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An StructuredObjectWriter is an ObjectWriter for writing
+// tree-structured data in a stream of events representing objects
+// and collections. Implementation of this interface can be used to
+// write an object stream to an in-memory structure, protobufs,
+// JSON, XML, or any other output format desired. The ObjectSource
+// interface is typically used as the source of an object stream.
+//
+// See JsonObjectWriter for a sample implementation of
+// StructuredObjectWriter and its use.
+//
+// Derived classes could be thread-unsafe.
+class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter {
+ public:
+  virtual ~StructuredObjectWriter() {}
+
+ protected:
+  // A base element class for subclasses to extend, makes tracking state easier.
+  //
+  // StructuredObjectWriter behaves as a visitor. BaseElement represents a node
+  // in the input tree. Implementation of StructuredObjectWriter should also
+  // extend BaseElement to keep track of the location in the input tree.
+  class LIBPROTOBUF_EXPORT BaseElement {
+   public:
+    // Takes ownership of the parent Element.
+    explicit BaseElement(BaseElement* parent)
+        : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {}
+    virtual ~BaseElement() {}
+
+    // Releases ownership of the parent and returns a pointer to it.
+    template <typename ElementType>
+    ElementType* pop() {
+      return down_cast<ElementType*>(parent_.release());
+    }
+
+    // Returns true if this element is the root.
+    bool is_root() const { return parent_ == NULL; }
+
+    // Returns the number of hops from this element to the root element.
+    int level() const { return level_; }
+
+   protected:
+    // Returns pointer to parent element without releasing ownership.
+    virtual BaseElement* parent() const { return parent_.get(); }
+
+   private:
+    // Pointer to the parent Element.
+    google::protobuf::scoped_ptr<BaseElement> parent_;
+
+    // Number of hops to the root Element.
+    // The root Element has NULL parent_ and a level_ of 0.
+    const int level_;
+
+    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement);
+  };
+
+  StructuredObjectWriter() {}
+
+  // Returns the current element. Used for indentation and name overrides.
+  virtual BaseElement* element() = 0;
+
+ private:
+  // Do not add any data members to this class.
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/anys.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/anys.proto
new file mode 100644
index 0000000..18c59cb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/anys.proto
@@ -0,0 +1,53 @@
+// 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.
+
+// Proto to test Proto3 Any serialization.
+syntax = "proto3";
+
+package google.protobuf.testing.anys;
+option java_package = "com.google.protobuf.testing.anys";
+
+import "google/protobuf/any.proto";
+
+message AnyIn {
+  string something = 1;
+}
+
+message AnyOut {
+  google.protobuf.Any any = 1;
+}
+
+message AnyM {
+  string foo = 1;
+}
+
+service TestService {
+  rpc Call(AnyIn) returns (AnyOut);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/books.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/books.proto
new file mode 100644
index 0000000..1cbbba4
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/books.proto
@@ -0,0 +1,187 @@
+// 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.
+
+// Author: sven@google.com (Sven Mawson)
+//
+// Sample protos for testing.
+syntax = "proto2";
+
+package google.protobuf.testing;
+
+// A book
+message Book {
+  optional string title = 1;
+  optional Author author = 2;
+  optional uint32 length = 3;
+  optional int64 published = 4;
+  optional bytes content = 5;
+
+  optional group Data = 6 {
+    optional uint32 year = 7;
+    optional string copyright = 8;
+  }
+
+  message Label {
+    optional string key = 1;
+    optional string value = 2;
+  }
+
+  optional Publisher publisher = 9;
+  repeated Label labels = 10;
+
+  enum Type {
+    FICTION = 1;
+    KIDS = 2;
+    ACTION_AND_ADVENTURE = 3;
+  }
+  optional Type type = 11;
+
+  extensions 200 to 499;
+}
+
+// A publisher of a book, tests required fields.
+message Publisher {
+  required string name = 1;
+}
+
+// An author of a book
+message Author {
+  optional uint64 id = 1 [json_name = "@id"];
+  optional string name = 2;
+  repeated string pseudonym = 3;
+  optional bool alive = 4;
+  repeated Author friend = 5;
+}
+
+// For testing resiliency of our protostream parser.
+// Field numbers of Author are reused for something else.
+message BadAuthor {
+  optional string id = 1;  // non-length-delimited to length-delimited.
+  repeated uint64 name = 2;  // string to repeated (both length-delimited).
+  optional string pseudonym = 3;  // Repeated to optional.
+  repeated bool alive = 4 [packed=true];  // Optional to repeated.
+}
+
+// All primitive types
+message Primitive {
+  // 32 bit numbers:
+  optional fixed32 fix32 = 1;
+  optional uint32 u32 = 2;
+  optional int32 i32 = 3;
+  optional sfixed32 sf32 = 4;
+  optional sint32 s32 = 5;
+
+  // 64 bit numbers:
+  optional fixed64 fix64 = 6;
+  optional uint64 u64 = 7;
+  optional int64 i64 = 8;
+  optional sfixed64 sf64 = 9;
+  optional sint64 s64 = 10;
+
+  // The other stuff.
+  optional string str = 11;
+  optional bytes bytes = 12;
+  optional float float = 13;
+  optional double double = 14;
+  optional bool bool = 15;
+
+  // repeated 32 bit numbers:
+  repeated fixed32 rep_fix32 = 16;
+  repeated uint32 rep_u32 = 17;
+  repeated int32 rep_i32 = 18;
+  repeated sfixed32 rep_sf32 = 19;
+  repeated sint32 rep_s32 = 20;
+
+  // repeated 64 bit numbers:
+  repeated fixed64 rep_fix64 = 21;
+  repeated uint64 rep_u64 = 22;
+  repeated int64 rep_i64 = 23;
+  repeated sfixed64 rep_sf64 = 24;
+  repeated sint64 rep_s64 = 25;
+
+  // repeated other stuff:
+  repeated string rep_str = 26;
+  repeated bytes rep_bytes = 27;
+  repeated float rep_float = 28;
+  repeated double rep_double = 29;
+  repeated bool rep_bool = 30;
+}
+
+// Test packed versions of all repeated primitives.
+// The field numbers should match their non-packed version in Primitive message.
+message PackedPrimitive {
+  // repeated 32 bit numbers:
+  repeated fixed32 rep_fix32 = 16 [packed=true];
+  repeated uint32 rep_u32 = 17 [packed=true];
+  repeated int32 rep_i32 = 18 [packed=true];
+  repeated sfixed32 rep_sf32 = 19 [packed=true];
+  repeated sint32 rep_s32 = 20 [packed=true];
+
+  // repeated 64 bit numbers:
+  repeated fixed64 rep_fix64 = 21 [packed=true];
+  repeated uint64 rep_u64 = 22 [packed=true];
+  repeated int64 rep_i64 = 23 [packed=true];
+  repeated sfixed64 rep_sf64 = 24 [packed=true];
+  repeated sint64 rep_s64 = 25 [packed=true];
+
+  // repeated other stuff:
+  repeated float rep_float = 28 [packed=true];
+  repeated double rep_double = 29 [packed=true];
+  repeated bool rep_bool = 30 [packed=true];
+}
+
+// Test extensions.
+extend Book {
+  repeated Author more_author = 201;
+}
+
+// Test nested extensions.
+message NestedBook {
+  extend Book {
+    optional NestedBook another_book = 301;
+  }
+  // Recurse
+  optional Book book = 1;
+}
+
+// For testing resiliency of our protostream parser.
+// Field number of NestedBook is reused for something else.
+message BadNestedBook {
+  repeated uint32 book = 1 [packed=true];  // Packed to optional message.
+}
+
+// A recursively defined message.
+message Cyclic {
+  optional int32 m_int = 1;
+  optional string m_str = 2;
+  optional Book m_book = 3;
+  repeated Author m_author = 5;
+  optional Cyclic m_cyclic = 4;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value.proto
new file mode 100644
index 0000000..cccc741
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value.proto
@@ -0,0 +1,170 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/wrappers.proto";
+
+message DefaultValueTestCases {
+  DoubleMessage empty_double = 1;
+  DoubleMessage double_with_default_value = 2;
+  DoubleMessage double_with_nondefault_value = 3;
+  DoubleMessage repeated_double = 4;
+  DoubleMessage nested_message = 5;
+  DoubleMessage repeated_nested_message = 6;
+  DoubleMessage double_message_with_oneof = 7;
+  StructMessage empty_struct = 201;
+  StructMessage empty_struct2 = 202;
+  StructMessage struct_with_null_value = 203;
+  StructMessage struct_with_values = 204;
+  StructMessage struct_with_nested_struct = 205;
+  StructMessage struct_with_nested_list = 206;
+  StructMessage struct_with_list_of_nulls = 207;
+  StructMessage struct_with_list_of_lists = 208;
+  StructMessage struct_with_list_of_structs = 209;
+  google.protobuf.Struct top_level_struct = 210;
+  ValueMessage value_wrapper_simple = 212;
+  ValueMessage value_wrapper_with_struct = 213;
+  ValueMessage value_wrapper_with_list = 214;
+  ListValueMessage list_value_wrapper = 215;
+  google.protobuf.Value top_level_value_simple = 216;
+  google.protobuf.Value top_level_value_with_struct = 217;
+  google.protobuf.Value top_level_value_with_list = 218;
+  google.protobuf.ListValue top_level_listvalue = 219;
+  AnyMessage empty_any = 301;
+  AnyMessage type_only_any = 302;
+  AnyMessage recursive_any = 303;
+  AnyMessage any_with_message_value = 304;
+  AnyMessage any_with_nested_message = 305;
+  AnyMessage any_with_message_containing_map = 306;
+  AnyMessage any_with_message_containing_struct = 307;
+  google.protobuf.Any top_level_any = 308;
+  StringtoIntMap empty_map = 401;
+  StringtoIntMap string_to_int = 402;
+  IntToStringMap int_to_string = 403;
+  MixedMap mixed1 = 404;
+  MixedMap2 mixed2 = 405;
+  MixedMap2 empty_mixed2 = 406;
+  MessageMap map_of_objects = 407;
+  MixedMap mixed_empty = 408;
+  MessageMap message_map_empty = 409;
+  DoubleValueMessage double_value = 501;
+  DoubleValueMessage double_value_default = 502;
+}
+
+message DoubleMessage {
+  double double_value = 1;
+  repeated double repeated_double = 2;
+  DoubleMessage nested_message = 3;
+  repeated DoubleMessage repeated_nested_message = 4;
+  google.protobuf.DoubleValue double_wrapper = 100;
+  oneof value {
+    string str_value = 112;
+    int64 num_value = 113;
+  }
+}
+
+message StructMessage {
+  google.protobuf.Struct struct = 1;
+}
+
+message ValueMessage {
+  google.protobuf.Value value = 1;
+}
+
+message ListValueMessage {
+  google.protobuf.ListValue shopping_list = 1;
+}
+message RequestMessage {
+  string content = 1;
+}
+
+// A test service.
+service DefaultValueTestService {
+  // A test method.
+  rpc Call(RequestMessage) returns (DefaultValueTestCases);
+}
+
+message AnyMessage {
+  google.protobuf.Any any = 1;
+  AnyData data = 2;
+}
+
+message AnyData {
+  int32 attr = 1;
+  string str = 2;
+  repeated string msgs = 3;
+  AnyData nested_data = 4;
+  map<string, string> map_data = 7;
+  google.protobuf.Struct struct_data = 8;
+  repeated AnyData repeated_data = 9;
+}
+
+message StringtoIntMap {
+  map<string, int32> map = 1;
+}
+
+message IntToStringMap {
+  map<int32, string> map = 1;
+}
+
+message MixedMap {
+  string msg = 1;
+  map<string, float> map = 2;
+  int32 int_value = 3;
+}
+
+message MixedMap2 {
+  enum E {
+    E0 = 0;
+    E1 = 1;
+    E2 = 2;
+    E3 = 3;
+  }
+  map<int32, bool> map = 1;
+  E ee = 2;
+  string msg = 4;
+}
+
+message MessageMap {
+  message M {
+    int32 inner_int = 1;
+    string inner_text = 2;
+  }
+  map<string, M> map = 1;
+}
+
+message DoubleValueMessage {
+  google.protobuf.DoubleValue double = 1;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value_test.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value_test.proto
new file mode 100644
index 0000000..9328834
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/default_value_test.proto
@@ -0,0 +1,53 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+message DefaultValueTest {
+  double double_value = 1;
+  repeated double repeated_double = 2;
+  float float_value = 3;
+  int64 int64_value = 5;
+  uint64 uint64_value = 7;
+  int32 int32_value = 9;
+  uint32 uint32_value = 11;
+  bool bool_value = 13;
+  string string_value = 15;
+  bytes bytes_value = 17 [ctype = CORD];
+
+  enum EnumDefault {
+    ENUM_FIRST = 0;
+    ENUM_SECOND = 1;
+    ENUM_THIRD = 2;
+  }
+  EnumDefault enum_value = 18;
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/field_mask.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/field_mask.proto
new file mode 100644
index 0000000..e8b2bc5f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/field_mask.proto
@@ -0,0 +1,71 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/field_mask.proto";
+
+message NestedFieldMask {
+  string data = 1;
+  google.protobuf.FieldMask single_mask = 2;
+  repeated google.protobuf.FieldMask repeated_mask = 3;
+}
+
+message FieldMaskTest {
+  string id = 1;
+  google.protobuf.FieldMask single_mask = 2;
+  repeated google.protobuf.FieldMask repeated_mask = 3;
+  repeated NestedFieldMask nested_mask = 4;
+}
+
+message FieldMaskTestCases {
+  FieldMaskWrapper single_mask = 1;
+  FieldMaskWrapper multiple_mask = 2;
+  FieldMaskWrapper snake_camel = 3;
+  FieldMaskWrapper empty_field = 4;
+  FieldMaskWrapper apiary_format1 = 5;
+  FieldMaskWrapper apiary_format2 = 6;
+  FieldMaskWrapper apiary_format3 = 7;
+  FieldMaskWrapper map_key1 = 8;
+  FieldMaskWrapper map_key2 = 9;
+  FieldMaskWrapper map_key3 = 10;
+  FieldMaskWrapper map_key4 = 11;
+  FieldMaskWrapper map_key5 = 12;
+}
+
+message FieldMaskWrapper {
+  google.protobuf.FieldMask mask = 1;
+}
+
+service FieldMaskTestService {
+  rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/maps.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/maps.proto
new file mode 100644
index 0000000..6475ecd
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/maps.proto
@@ -0,0 +1,86 @@
+// 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.
+
+// Proto to test proto3 maps.
+syntax = "proto3";
+
+package google.protobuf.testing.maps;
+option java_package = "com.google.protobuf.testing.maps";
+
+message MapIn {
+  string other = 1;
+  repeated string things = 2;
+  map<string, string> map_input = 3;
+}
+
+message MapOut {
+  map<string, MapM> map1 = 1;
+  map<string, MapOut> map2 = 2;
+  map<int32, string> map3 = 3;
+  map<bool, string> map4 = 5;
+  string bar = 4;
+}
+
+// A message with exactly the same wire representation as MapOut, but using
+// repeated message fields instead of map fields. We use this message to test
+// the wire-format compatibility of the JSON transcoder (e.g., whether it
+// handles missing keys correctly).
+message MapOutWireFormat {
+  message Map1Entry {
+    string key = 1;
+    MapM value = 2;
+  }
+  repeated Map1Entry map1 = 1;
+  message Map2Entry {
+    string key = 1;
+    MapOut value = 2;
+  }
+  repeated Map2Entry map2 = 2;
+  message Map3Entry {
+    int32 key = 1;
+    string value = 2;
+  }
+  repeated Map3Entry map3 = 3;
+  message Map4Entry {
+    bool key = 1;
+    string value = 2;
+  }
+  repeated Map4Entry map4 = 5;
+  string bar = 4;
+}
+
+message MapM {
+  string foo = 1;
+}
+
+service TestService {
+  rpc Call1(MapIn) returns (MapOut);
+  rpc Call2(MapIn) returns (MapOut);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/oneofs.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/oneofs.proto
new file mode 100644
index 0000000..5bc9fa0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/oneofs.proto
@@ -0,0 +1,68 @@
+// 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.
+
+// Proto to test oneofs.
+syntax = "proto3";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+
+package google.protobuf.testing.oneofs;
+option java_package = "com.google.protobuf.testing.oneofs";
+
+message OneOfsRequest {
+  string value = 1;
+  oneof data {
+    string str_data = 2;
+    int32 int_data = 3;
+    // Simple message
+    Data message_data = 4;
+    // Well known types
+    google.protobuf.Struct struct_data = 5;
+    google.protobuf.Value value_data = 6;
+    google.protobuf.ListValue list_value_data = 7;
+    google.protobuf.Timestamp ts_data = 8;
+  }
+  google.protobuf.Any any_data = 19;
+}
+
+message Data {
+  int32 data_value = 1;
+}
+
+message Response {
+  string value = 1;
+}
+
+service TestService {
+  // Test call.
+  rpc Call(OneOfsRequest) returns (Response);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/struct.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/struct.proto
new file mode 100644
index 0000000..c15aba0
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/struct.proto
@@ -0,0 +1,45 @@
+// 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.
+
+// Proto to test proto3 struct.
+syntax = "proto3";
+
+package google.protobuf.testing.structs;
+option java_package = "com.google.protobuf.testing.structs";
+
+import "google/protobuf/struct.proto";
+
+message StructType {
+  google.protobuf.Struct object = 1;
+}
+
+service TestService {
+  rpc Call(StructType) returns (StructType);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/timestamp_duration.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
new file mode 100644
index 0000000..56351f1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
@@ -0,0 +1,47 @@
+// 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.
+
+// Proto to test proto3 Timestamp and Duration.
+syntax = "proto3";
+
+package google.protobuf.testing.timestampduration;
+option java_package = "com.google.protobuf.testing.timestampduration";
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+
+message TimestampDuration {
+  google.protobuf.Timestamp ts = 1;
+  google.protobuf.Duration dur = 2;
+}
+
+service TestService {
+  rpc Call(TimestampDuration) returns (TimestampDuration);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/wrappers.proto b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/wrappers.proto
new file mode 100644
index 0000000..eabc99f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/testdata/wrappers.proto
@@ -0,0 +1,100 @@
+// 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.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/wrappers.proto";
+
+// Top-level test cases proto used by MarshallingTest. See description
+// at the top of the class MarshallingTest for details on how to write
+// test cases.
+message WrappersTestCases {
+  DoubleWrapper double_wrapper = 1;
+  FloatWrapper float_wrapper = 2;
+  Int64Wrapper int64_wrapper = 3;
+  UInt64Wrapper uint64_wrapper = 4;
+  Int32Wrapper int32_wrapper = 5;
+  UInt32Wrapper uint32_wrapper = 6;
+  BoolWrapper bool_wrapper = 7;
+  StringWrapper string_wrapper = 8;
+  BytesWrapper bytes_wrapper = 9;
+
+  DoubleWrapper double_wrapper_default = 10;
+  FloatWrapper float_wrapper_default = 11;
+  Int64Wrapper int64_wrapper_default = 12;
+  UInt64Wrapper uint64_wrapper_default = 13;
+  Int32Wrapper int32_wrapper_default = 14;
+  UInt32Wrapper uint32_wrapper_default = 15;
+  BoolWrapper bool_wrapper_default = 16;
+  StringWrapper string_wrapper_default = 17;
+  BytesWrapper bytes_wrapper_default = 18;
+}
+
+message DoubleWrapper {
+  google.protobuf.DoubleValue double = 1;
+}
+
+message FloatWrapper {
+  google.protobuf.FloatValue float = 1;
+}
+
+message Int64Wrapper {
+  google.protobuf.Int64Value int64 = 1;
+}
+
+message UInt64Wrapper {
+  google.protobuf.UInt64Value uint64 = 1;
+}
+
+message Int32Wrapper {
+  google.protobuf.Int32Value int32 = 1;
+}
+
+message UInt32Wrapper {
+  google.protobuf.UInt32Value uint32 = 1;
+}
+
+message BoolWrapper {
+  google.protobuf.BoolValue bool = 1;
+}
+
+message StringWrapper {
+  google.protobuf.StringValue string = 1;
+}
+
+message BytesWrapper {
+  google.protobuf.BytesValue bytes = 1;
+}
+
+service WrappersTestService {
+  rpc Call(WrappersTestCases) returns (WrappersTestCases);
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.cc
new file mode 100644
index 0000000..00a8ee7
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.cc
@@ -0,0 +1,171 @@
+// 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.
+
+#include <google/protobuf/util/internal/type_info.h>
+
+#include <map>
+#include <set>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+// A TypeInfo that looks up information provided by a TypeResolver.
+class TypeInfoForTypeResolver : public TypeInfo {
+ public:
+  explicit TypeInfoForTypeResolver(TypeResolver* type_resolver)
+      : type_resolver_(type_resolver) {}
+
+  virtual ~TypeInfoForTypeResolver() {
+    DeleteCachedTypes(&cached_types_);
+    DeleteCachedTypes(&cached_enums_);
+  }
+
+  virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+      StringPiece type_url) const {
+    map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url);
+    if (it != cached_types_.end()) {
+      return it->second;
+    }
+    // Stores the string value so it can be referenced using StringPiece in the
+    // cached_types_ map.
+    const string& string_type_url =
+        *string_storage_.insert(type_url.ToString()).first;
+    google::protobuf::scoped_ptr<google::protobuf::Type> type(new google::protobuf::Type());
+    util::Status status =
+        type_resolver_->ResolveMessageType(string_type_url, type.get());
+    StatusOrType result =
+        status.ok() ? StatusOrType(type.release()) : StatusOrType(status);
+    cached_types_[string_type_url] = result;
+    return result;
+  }
+
+  virtual const google::protobuf::Type* GetTypeByTypeUrl(
+      StringPiece type_url) const {
+    StatusOrType result = ResolveTypeUrl(type_url);
+    return result.ok() ? result.ValueOrDie() : NULL;
+  }
+
+  virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+      StringPiece type_url) const {
+    map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url);
+    if (it != cached_enums_.end()) {
+      return it->second.ok() ? it->second.ValueOrDie() : NULL;
+    }
+    // Stores the string value so it can be referenced using StringPiece in the
+    // cached_enums_ map.
+    const string& string_type_url =
+        *string_storage_.insert(type_url.ToString()).first;
+    google::protobuf::scoped_ptr<google::protobuf::Enum> enum_type(
+        new google::protobuf::Enum());
+    util::Status status =
+        type_resolver_->ResolveEnumType(string_type_url, enum_type.get());
+    StatusOrEnum result =
+        status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status);
+    cached_enums_[string_type_url] = result;
+    return result.ok() ? result.ValueOrDie() : NULL;
+  }
+
+  virtual const google::protobuf::Field* FindField(
+      const google::protobuf::Type* type, StringPiece camel_case_name) const {
+    if (indexed_types_.find(type) == indexed_types_.end()) {
+      PopulateNameLookupTable(type);
+      indexed_types_.insert(type);
+    }
+    StringPiece name =
+        FindWithDefault(camel_case_name_table_, camel_case_name, StringPiece());
+    if (name.empty()) {
+      // Didn't find a mapping. Use whatever provided.
+      name = camel_case_name;
+    }
+    return FindFieldInTypeOrNull(type, name);
+  }
+
+ private:
+  typedef util::StatusOr<const google::protobuf::Type*> StatusOrType;
+  typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum;
+
+  template <typename T>
+  static void DeleteCachedTypes(map<StringPiece, T>* cached_types) {
+    for (typename map<StringPiece, T>::iterator it = cached_types->begin();
+         it != cached_types->end(); ++it) {
+      if (it->second.ok()) {
+        delete it->second.ValueOrDie();
+      }
+    }
+  }
+
+  void PopulateNameLookupTable(const google::protobuf::Type* type) const {
+    for (int i = 0; i < type->fields_size(); ++i) {
+      const google::protobuf::Field& field = type->fields(i);
+      StringPiece name = field.name();
+      StringPiece camel_case_name = field.json_name();
+      const StringPiece* existing = InsertOrReturnExisting(
+          &camel_case_name_table_, camel_case_name, name);
+      if (existing && *existing != name) {
+        GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing
+                     << "' map to the same camel case name '" << camel_case_name
+                     << "'.";
+      }
+    }
+  }
+
+  TypeResolver* type_resolver_;
+
+  // Stores string values that will be referenced by StringPieces in
+  // cached_types_, cached_enums_ and camel_case_name_table_.
+  mutable set<string> string_storage_;
+
+  mutable map<StringPiece, StatusOrType> cached_types_;
+  mutable map<StringPiece, StatusOrEnum> cached_enums_;
+
+  mutable set<const google::protobuf::Type*> indexed_types_;
+  mutable map<StringPiece, StringPiece> camel_case_name_table_;
+};
+}  // namespace
+
+TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) {
+  return new TypeInfoForTypeResolver(type_resolver);
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.h
new file mode 100644
index 0000000..d813317
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info.h
@@ -0,0 +1,92 @@
+// 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_UTIL_CONVERTER_TYPE_INFO_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+// Internal helper class for type resolving. Note that this class is not
+// thread-safe and should only be accessed in one thread.
+class LIBPROTOBUF_EXPORT TypeInfo {
+ public:
+  TypeInfo() {}
+  virtual ~TypeInfo() {}
+
+  // Resolves a type url into a Type. If the type url is invalid, returns
+  // INVALID_ARGUMENT error status. If the type url is valid but the
+  // corresponding type cannot be found, returns a NOT_FOUND error status.
+  //
+  // This TypeInfo class retains the ownership of the returned pointer.
+  virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+      StringPiece type_url) const = 0;
+
+  // Resolves a type url into a Type. Like ResolveTypeUrl() but returns
+  // NULL if the type url is invalid or the type cannot be found.
+  //
+  // This TypeInfo class retains the ownership of the returned pointer.
+  virtual const google::protobuf::Type* GetTypeByTypeUrl(
+      StringPiece type_url) const = 0;
+
+  // Resolves a type url for an enum. Returns NULL if the type url is
+  // invalid or the type cannot be found.
+  //
+  // This TypeInfo class retains the ownership of the returned pointer.
+  virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+      StringPiece type_url) const = 0;
+
+  // Looks up a field in the specified type given a CamelCase name.
+  virtual const google::protobuf::Field* FindField(
+      const google::protobuf::Type* type,
+      StringPiece camel_case_name) const = 0;
+
+  // Creates a TypeInfo object that looks up type information from a
+  // TypeResolver. Caller takes ownership of the returned pointer.
+  static TypeInfo* NewTypeInfo(TypeResolver* type_resolver);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo);
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.cc
new file mode 100644
index 0000000..49e18ed
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -0,0 +1,134 @@
+// 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.
+
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+
+void TypeInfoTestHelper::ResetTypeInfo(
+    const vector<const Descriptor*>& descriptors) {
+  switch (type_) {
+    case USE_TYPE_RESOLVER: {
+      const DescriptorPool* pool = descriptors[0]->file()->pool();
+      for (int i = 1; i < descriptors.size(); ++i) {
+        GOOGLE_CHECK(pool == descriptors[i]->file()->pool())
+            << "Descriptors from different pools are not supported.";
+      }
+      type_resolver_.reset(
+          NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool));
+      typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get()));
+      return;
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Can not reach here.";
+}
+
+void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) {
+  vector<const Descriptor*> descriptors;
+  descriptors.push_back(descriptor);
+  ResetTypeInfo(descriptors);
+}
+
+void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1,
+                                       const Descriptor* descriptor2) {
+  vector<const Descriptor*> descriptors;
+  descriptors.push_back(descriptor1);
+  descriptors.push_back(descriptor2);
+  ResetTypeInfo(descriptors);
+}
+
+TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
+
+ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
+    io::CodedInputStream* coded_input, const string& type_url) {
+  const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
+  switch (type_) {
+    case USE_TYPE_RESOLVER: {
+      return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
+                                         *type);
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Can not reach here.";
+  return NULL;
+}
+
+ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
+    const string& type_url, strings::ByteSink* output, ErrorListener* listener,
+    const ProtoStreamObjectWriter::Options& options) {
+  const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
+  switch (type_) {
+    case USE_TYPE_RESOLVER: {
+      return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
+                                         listener, options);
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Can not reach here.";
+  return NULL;
+}
+
+DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
+    const string& type_url, ObjectWriter* writer) {
+  const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
+  switch (type_) {
+    case USE_TYPE_RESOLVER: {
+      return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer);
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Can not reach here.";
+  return NULL;
+}
+
+}  // namespace testing
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.h
new file mode 100644
index 0000000..1a27984
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -0,0 +1,98 @@
+// 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_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+enum TypeInfoSource {
+  USE_TYPE_RESOLVER,
+};
+
+// In the unit-tests we want to test two scenarios: one with type info from
+// ServiceTypeInfo, the other with type info from TypeResolver. This class
+// wraps the detail of where the type info is from and provides the same
+// interface so the same unit-test code can test both scenarios.
+class TypeInfoTestHelper {
+ public:
+  explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {}
+
+  // Creates a TypeInfo object for the given set of descriptors.
+  void ResetTypeInfo(const vector<const Descriptor*>& descriptors);
+
+  // Convinent overloads.
+  void ResetTypeInfo(const Descriptor* descriptor);
+  void ResetTypeInfo(const Descriptor* descriptor1,
+                     const Descriptor* descriptor2);
+
+  // Returns the TypeInfo created after ResetTypeInfo.
+  TypeInfo* GetTypeInfo();
+
+  ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
+                                          const string& type_url);
+
+  ProtoStreamObjectWriter* NewProtoWriter(
+      const string& type_url, strings::ByteSink* output,
+      ErrorListener* listener, const ProtoStreamObjectWriter::Options& options);
+
+  DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url,
+                                                  ObjectWriter* writer);
+
+ private:
+  TypeInfoSource type_;
+  google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
+  google::protobuf::scoped_ptr<TypeResolver> type_resolver_;
+};
+}  // namespace testing
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.cc b/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.cc
new file mode 100644
index 0000000..ee7a51f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.cc
@@ -0,0 +1,361 @@
+// 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.
+
+#include <google/protobuf/util/internal/utility.h>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+const StringPiece SkipWhiteSpace(StringPiece str) {
+  StringPiece::size_type i;
+  for (i = 0; i < str.size() && isspace(str[i]); ++i) {
+  }
+  GOOGLE_DCHECK(i == str.size() || !isspace(str[i]));
+  return StringPiece(str, i);
+}
+}  // namespace
+
+bool GetBoolOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, bool default_value) {
+  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+  if (opt == NULL) {
+    return default_value;
+  }
+  return GetBoolFromAny(opt->value());
+}
+
+int64 GetInt64OptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, int64 default_value) {
+  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+  if (opt == NULL) {
+    return default_value;
+  }
+  return GetInt64FromAny(opt->value());
+}
+
+double GetDoubleOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, double default_value) {
+  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+  if (opt == NULL) {
+    return default_value;
+  }
+  return GetDoubleFromAny(opt->value());
+}
+
+string GetStringOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, const string& default_value) {
+  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+  if (opt == NULL) {
+    return default_value;
+  }
+  return GetStringFromAny(opt->value());
+}
+
+template <typename T>
+void ParseFromAny(const string& data, T* result) {
+  result->ParseFromString(data);
+}
+
+// Returns a boolean value contained in Any type.
+// TODO(skarvaje): Add type checking & error messages here.
+bool GetBoolFromAny(const google::protobuf::Any& any) {
+  google::protobuf::BoolValue b;
+  ParseFromAny(any.value(), &b);
+  return b.value();
+}
+
+int64 GetInt64FromAny(const google::protobuf::Any& any) {
+  google::protobuf::Int64Value i;
+  ParseFromAny(any.value(), &i);
+  return i.value();
+}
+
+double GetDoubleFromAny(const google::protobuf::Any& any) {
+  google::protobuf::DoubleValue i;
+  ParseFromAny(any.value(), &i);
+  return i.value();
+}
+
+string GetStringFromAny(const google::protobuf::Any& any) {
+  google::protobuf::StringValue s;
+  ParseFromAny(any.value(), &s);
+  return s.value();
+}
+
+const StringPiece GetTypeWithoutUrl(StringPiece type_url) {
+  size_t idx = type_url.rfind('/');
+  return type_url.substr(idx + 1);
+}
+
+const string GetFullTypeWithUrl(StringPiece simple_type) {
+  return StrCat(kTypeServiceBaseUrl, "/", simple_type);
+}
+
+const google::protobuf::Option* FindOptionOrNull(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name) {
+  for (int i = 0; i < options.size(); ++i) {
+    const google::protobuf::Option& opt = options.Get(i);
+    if (opt.name() == option_name) {
+      return &opt;
+    }
+  }
+  return NULL;
+}
+
+const google::protobuf::Field* FindFieldInTypeOrNull(
+    const google::protobuf::Type* type, StringPiece field_name) {
+  if (type != NULL) {
+    for (int i = 0; i < type->fields_size(); ++i) {
+      const google::protobuf::Field& field = type->fields(i);
+      if (field.name() == field_name) {
+        return &field;
+      }
+    }
+  }
+  return NULL;
+}
+
+const google::protobuf::Field* FindJsonFieldInTypeOrNull(
+    const google::protobuf::Type* type, StringPiece json_name) {
+  if (type != NULL) {
+    for (int i = 0; i < type->fields_size(); ++i) {
+      const google::protobuf::Field& field = type->fields(i);
+      if (field.json_name() == json_name) {
+        return &field;
+      }
+    }
+  }
+  return NULL;
+}
+
+const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+    const google::protobuf::Enum* enum_type, StringPiece enum_name) {
+  if (enum_type != NULL) {
+    for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
+      const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
+      if (enum_value.name() == enum_name) {
+        return &enum_value;
+      }
+    }
+  }
+  return NULL;
+}
+
+const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+    const google::protobuf::Enum* enum_type, int32 value) {
+  if (enum_type != NULL) {
+    for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
+      const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
+      if (enum_value.number() == value) {
+        return &enum_value;
+      }
+    }
+  }
+  return NULL;
+}
+
+string ToCamelCase(const StringPiece input) {
+  bool capitalize_next = false;
+  bool was_cap = true;
+  bool is_cap = false;
+  bool first_word = true;
+  string result;
+  result.reserve(input.size());
+
+  for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
+    is_cap = ascii_isupper(input[i]);
+    if (input[i] == '_') {
+      capitalize_next = true;
+      if (!result.empty()) first_word = false;
+      continue;
+    } else if (first_word) {
+      // Consider when the current character B is capitalized,
+      // first word ends when:
+      // 1) following a lowercase:   "...aB..."
+      // 2) followed by a lowercase: "...ABc..."
+      if (!result.empty() && is_cap &&
+          (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+        first_word = false;
+        result.push_back(input[i]);
+      } else {
+        result.push_back(ascii_tolower(input[i]));
+        continue;
+      }
+    } else if (capitalize_next) {
+      capitalize_next = false;
+      if (ascii_islower(input[i])) {
+        result.push_back(ascii_toupper(input[i]));
+        continue;
+      } else {
+        result.push_back(input[i]);
+        continue;
+      }
+    } else {
+      result.push_back(ascii_tolower(input[i]));
+    }
+  }
+  return result;
+}
+
+string ToSnakeCase(StringPiece input) {
+  bool was_not_underscore = false;  // Initialize to false for case 1 (below)
+  bool was_not_cap = false;
+  string result;
+  result.reserve(input.size() << 1);
+
+  for (size_t i = 0; i < input.size(); ++i) {
+    if (ascii_isupper(input[i])) {
+      // Consider when the current character B is capitalized:
+      // 1) At beginning of input:   "B..." => "b..."
+      //    (e.g. "Biscuit" => "biscuit")
+      // 2) Following a lowercase:   "...aB..." => "...a_b..."
+      //    (e.g. "gBike" => "g_bike")
+      // 3) At the end of input:     "...AB" => "...ab"
+      //    (e.g. "GoogleLAB" => "google_lab")
+      // 4) Followed by a lowercase: "...ABc..." => "...a_bc..."
+      //    (e.g. "GBike" => "g_bike")
+      if (was_not_underscore &&               //            case 1 out
+          (was_not_cap ||                     // case 2 in, case 3 out
+           (i + 1 < input.size() &&           //            case 3 out
+            ascii_islower(input[i + 1])))) {  // case 4 in
+        // We add an underscore for case 2 and case 4.
+        result.push_back('_');
+      }
+      result.push_back(ascii_tolower(input[i]));
+      was_not_underscore = true;
+      was_not_cap = false;
+    } else {
+      result.push_back(input[i]);
+      was_not_underscore = input[i] != '_';
+      was_not_cap = true;
+    }
+  }
+  return result;
+}
+
+set<string>* well_known_types_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_);
+const char* well_known_types_name_array_[] = {
+    "google.protobuf.Timestamp",   "google.protobuf.Duration",
+    "google.protobuf.DoubleValue", "google.protobuf.FloatValue",
+    "google.protobuf.Int64Value",  "google.protobuf.UInt64Value",
+    "google.protobuf.Int32Value",  "google.protobuf.UInt32Value",
+    "google.protobuf.BoolValue",   "google.protobuf.StringValue",
+    "google.protobuf.BytesValue",  "google.protobuf.FieldMask"};
+
+void DeleteWellKnownTypes() { delete well_known_types_; }
+
+void InitWellKnownTypes() {
+  well_known_types_ = new set<string>;
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
+    well_known_types_->insert(well_known_types_name_array_[i]);
+  }
+  google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes);
+}
+
+bool IsWellKnownType(const string& type_name) {
+  InitWellKnownTypes();
+  return ContainsKey(*well_known_types_, type_name);
+}
+
+bool IsValidBoolString(const string& bool_string) {
+  return bool_string == "true" || bool_string == "false" ||
+         bool_string == "1" || bool_string == "0";
+}
+
+bool IsMap(const google::protobuf::Field& field,
+           const google::protobuf::Type& type) {
+  return (field.cardinality() ==
+              google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+          GetBoolOptionOrDefault(type.options(),
+                                 "google.protobuf.MessageOptions.map_entry", false));
+}
+
+bool IsMessageSetWireFormat(const google::protobuf::Type& type) {
+  return GetBoolOptionOrDefault(
+      type.options(), "google.protobuf.MessageOptions.message_set_wire_format", false);
+}
+
+string DoubleAsString(double value) {
+  if (MathLimits<double>::IsPosInf(value)) return "Infinity";
+  if (MathLimits<double>::IsNegInf(value)) return "-Infinity";
+  if (MathLimits<double>::IsNaN(value)) return "NaN";
+
+  return SimpleDtoa(value);
+}
+
+string FloatAsString(float value) {
+  if (MathLimits<float>::IsFinite(value)) return SimpleFtoa(value);
+  return DoubleAsString(value);
+}
+
+bool SafeStrToFloat(StringPiece str, float* value) {
+  double double_value;
+  if (!safe_strtod(str, &double_value)) {
+    return false;
+  }
+
+  if (MathLimits<double>::IsInf(double_value) ||
+      MathLimits<double>::IsNaN(double_value))
+    return false;
+
+  // Fail if the value is not representable in float.
+  if (double_value > std::numeric_limits<float>::max() ||
+      double_value < -std::numeric_limits<float>::max()) {
+    return false;
+  }
+
+  *value = static_cast<float>(double_value);
+  return true;
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.h b/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.h
new file mode 100644
index 0000000..33df8ed
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/internal/utility.h
@@ -0,0 +1,193 @@
+// 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_UTIL_CONVERTER_UTILITY_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <utility>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+class Method;
+class Any;
+class Bool;
+class Option;
+class Field;
+class Type;
+class Enum;
+class EnumValue;
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+// Finds the tech option identified by option_name. Parses the boolean value and
+// returns it.
+// When the option with the given name is not found, default_value is returned.
+LIBPROTOBUF_EXPORT bool GetBoolOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, bool default_value);
+
+// Returns int64 option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT int64 GetInt64OptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, int64 default_value);
+
+// Returns double option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT double GetDoubleOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, double default_value);
+
+// Returns string option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT string GetStringOptionOrDefault(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name, const string& default_value);
+
+// Returns a boolean value contained in Any type.
+// TODO(skarvaje): Make these utilities dealing with Any types more generic,
+// add more error checking and move to a more public/sharable location so others
+// can use.
+LIBPROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any);
+
+// Returns int64 value contained in Any type.
+LIBPROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any);
+
+// Returns double value contained in Any type.
+LIBPROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any);
+
+// Returns string value contained in Any type.
+LIBPROTOBUF_EXPORT string GetStringFromAny(const google::protobuf::Any& any);
+
+// Returns the type string without the url prefix. e.g.: If the passed type is
+// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'.
+LIBPROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(StringPiece type_url);
+
+// Returns the simple_type with the base type url (kTypeServiceBaseUrl)
+// prefixed.
+//
+// E.g:
+// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string
+// "type.googleapis.com/google.protobuf.Timestamp".
+LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type);
+
+// Finds and returns option identified by name and option_name within the
+// provided map. Returns NULL if none found.
+const google::protobuf::Option* FindOptionOrNull(
+    const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+    const string& option_name);
+
+// Finds and returns the field identified by field_name in the passed tech Type
+// object. Returns NULL if none found.
+const google::protobuf::Field* FindFieldInTypeOrNull(
+    const google::protobuf::Type* type, StringPiece field_name);
+
+// Similar to FindFieldInTypeOrNull, but this looks up fields with given
+// json_name.
+const google::protobuf::Field* FindJsonFieldInTypeOrNull(
+    const google::protobuf::Type* type, StringPiece json_name);
+
+// Finds and returns the EnumValue identified by enum_name in the passed tech
+// Enum object. Returns NULL if none found.
+const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+    const google::protobuf::Enum* enum_type, StringPiece enum_name);
+
+// Finds and returns the EnumValue identified by value in the passed tech
+// Enum object. Returns NULL if none found.
+const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+    const google::protobuf::Enum* enum_type, int32 value);
+
+// Converts input to camel-case and returns it.
+LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input);
+
+// Converts input to snake_case and returns it.
+LIBPROTOBUF_EXPORT string ToSnakeCase(StringPiece input);
+
+// Returns true if type_name represents a well-known type.
+LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name);
+
+// Returns true if 'bool_string' represents a valid boolean value. Only "true",
+// "false", "0" and "1" are allowed.
+LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string);
+
+// Returns true if "field" is a protobuf map field based on its type.
+LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
+           const google::protobuf::Type& type);
+
+// Returns true if the given type has special MessageSet wire format.
+bool IsMessageSetWireFormat(const google::protobuf::Type& type);
+
+// Infinity/NaN-aware conversion to string.
+LIBPROTOBUF_EXPORT string DoubleAsString(double value);
+LIBPROTOBUF_EXPORT string FloatAsString(float value);
+
+// Convert from int32, int64, uint32, uint64, double or float to string.
+template <typename T>
+string ValueAsString(T value) {
+  return SimpleItoa(value);
+}
+
+template <>
+inline string ValueAsString(float value) {
+  return FloatAsString(value);
+}
+
+template <>
+inline string ValueAsString(double value) {
+  return DoubleAsString(value);
+}
+
+// Converts a string to float. Unlike safe_strtof, conversion will fail if the
+// value fits into double but not float (e.g., DBL_MAX).
+LIBPROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value);
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/json_format_proto3.proto b/src/third_party/protobuf-3/src/google/protobuf/util/json_format_proto3.proto
new file mode 100644
index 0000000..a1e24c1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/json_format_proto3.proto
@@ -0,0 +1,176 @@
+// 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.
+
+syntax = "proto3";
+
+package proto3;
+
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/any.proto";
+import "google/protobuf/field_mask.proto";
+
+enum EnumType {
+  FOO = 0;
+  BAR = 1;
+}
+
+message MessageType {
+  int32 value = 1;
+}
+
+message TestMessage {
+  bool bool_value = 1;
+  int32 int32_value = 2;
+  int64 int64_value = 3;
+  uint32 uint32_value = 4;
+  uint64 uint64_value = 5;
+  float float_value = 6;
+  double double_value = 7;
+  string string_value = 8;
+  bytes bytes_value = 9;
+  EnumType enum_value = 10;
+  MessageType message_value = 11;
+
+  repeated bool repeated_bool_value = 21;
+  repeated int32 repeated_int32_value = 22;
+  repeated int64 repeated_int64_value = 23;
+  repeated uint32 repeated_uint32_value = 24;
+  repeated uint64 repeated_uint64_value = 25;
+  repeated float repeated_float_value = 26;
+  repeated double repeated_double_value = 27;
+  repeated string repeated_string_value = 28;
+  repeated bytes repeated_bytes_value = 29;
+  repeated EnumType repeated_enum_value = 30;
+  repeated MessageType repeated_message_value = 31;
+}
+
+message TestOneof {
+  // In JSON format oneof fields behave mostly the same as optional
+  // fields except that:
+  //   1. Oneof fields have field presence information and will be
+  //      printed if it's set no matter whether it's the default value.
+  //   2. Multiple oneof fields in the same oneof cannot appear at the
+  //      same time in the input.
+  oneof oneof_value {
+    int32 oneof_int32_value = 1;
+    string oneof_string_value = 2;
+    bytes oneof_bytes_value = 3;
+    EnumType oneof_enum_value = 4;
+    MessageType oneof_message_value = 5;
+  }
+}
+
+message TestMap {
+  map<bool, int32> bool_map = 1;
+  map<int32, int32> int32_map = 2;
+  map<int64, int32> int64_map = 3;
+  map<uint32, int32> uint32_map = 4;
+  map<uint64, int32> uint64_map = 5;
+  map<string, int32> string_map = 6;
+}
+
+message TestNestedMap {
+  map<bool, int32> bool_map = 1;
+  map<int32, int32> int32_map = 2;
+  map<int64, int32> int64_map = 3;
+  map<uint32, int32> uint32_map = 4;
+  map<uint64, int32> uint64_map = 5;
+  map<string, int32> string_map = 6;
+  map<string, TestNestedMap> map_map = 7;
+}
+
+message TestWrapper {
+  google.protobuf.BoolValue bool_value = 1;
+  google.protobuf.Int32Value int32_value = 2;
+  google.protobuf.Int64Value int64_value = 3;
+  google.protobuf.UInt32Value uint32_value = 4;
+  google.protobuf.UInt64Value uint64_value = 5;
+  google.protobuf.FloatValue float_value = 6;
+  google.protobuf.DoubleValue double_value = 7;
+  google.protobuf.StringValue string_value = 8;
+  google.protobuf.BytesValue bytes_value = 9;
+
+  repeated google.protobuf.BoolValue repeated_bool_value = 11;
+  repeated google.protobuf.Int32Value repeated_int32_value = 12;
+  repeated google.protobuf.Int64Value repeated_int64_value = 13;
+  repeated google.protobuf.UInt32Value repeated_uint32_value = 14;
+  repeated google.protobuf.UInt64Value repeated_uint64_value = 15;
+  repeated google.protobuf.FloatValue repeated_float_value = 16;
+  repeated google.protobuf.DoubleValue repeated_double_value = 17;
+  repeated google.protobuf.StringValue repeated_string_value = 18;
+  repeated google.protobuf.BytesValue repeated_bytes_value = 19;
+}
+
+message TestTimestamp {
+  google.protobuf.Timestamp value = 1;
+  repeated google.protobuf.Timestamp repeated_value = 2;
+}
+
+message TestDuration {
+  google.protobuf.Duration value = 1;
+  repeated google.protobuf.Duration repeated_value = 2;
+}
+
+message TestFieldMask {
+  google.protobuf.FieldMask value = 1;
+}
+
+message TestStruct {
+  google.protobuf.Struct value = 1;
+  repeated google.protobuf.Struct repeated_value = 2;
+}
+
+message TestAny {
+  google.protobuf.Any value = 1;
+  repeated google.protobuf.Any repeated_value = 2;
+}
+
+message TestValue {
+  google.protobuf.Value value = 1;
+  repeated google.protobuf.Value repeated_value = 2;
+}
+
+message TestListValue {
+  google.protobuf.ListValue value = 1;
+  repeated google.protobuf.ListValue repeated_value = 2;
+}
+
+message TestBoolValue {
+  bool bool_value = 1;
+  map<bool, int32> bool_map = 2;
+}
+
+message TestCustomJsonName {
+  int32 value = 1 [json_name = "@value"];
+}
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/json_util.cc b/src/third_party/protobuf-3/src/google/protobuf/util/json_util.cc
new file mode 100644
index 0000000..2659320
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/json_util.cc
@@ -0,0 +1,176 @@
+// 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.
+
+#include <google/protobuf/util/json_util.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/json_objectwriter.h>
+#include <google/protobuf/util/internal/json_stream_parser.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+namespace internal {
+void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
+  while (len > 0) {
+    void* buffer;
+    int length;
+    if (!stream_->Next(&buffer, &length)) {
+      // There isn't a way for ByteSink to report errors.
+      return;
+    }
+    if (len < length) {
+      memcpy(buffer, bytes, len);
+      stream_->BackUp(length - len);
+      break;
+    } else {
+      memcpy(buffer, bytes, length);
+      bytes += length;
+      len -= length;
+    }
+  }
+}
+}  // namespace internal
+
+util::Status BinaryToJsonStream(TypeResolver* resolver,
+                                  const string& type_url,
+                                  io::ZeroCopyInputStream* binary_input,
+                                  io::ZeroCopyOutputStream* json_output,
+                                  const JsonOptions& options) {
+  io::CodedInputStream in_stream(binary_input);
+  google::protobuf::Type type;
+  RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
+  converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type);
+  io::CodedOutputStream out_stream(json_output);
+  converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
+                                          &out_stream);
+  if (options.always_print_primitive_fields) {
+    converter::DefaultValueObjectWriter default_value_writer(
+        resolver, type, &json_writer);
+    return proto_source.WriteTo(&default_value_writer);
+  } else {
+    return proto_source.WriteTo(&json_writer);
+  }
+}
+
+util::Status BinaryToJsonString(TypeResolver* resolver,
+                                  const string& type_url,
+                                  const string& binary_input,
+                                  string* json_output,
+                                  const JsonOptions& options) {
+  io::ArrayInputStream input_stream(binary_input.data(), binary_input.size());
+  io::StringOutputStream output_stream(json_output);
+  return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream,
+                            options);
+}
+
+namespace {
+class StatusErrorListener : public converter::ErrorListener {
+ public:
+  StatusErrorListener() : status_(util::Status::OK) {}
+  virtual ~StatusErrorListener() {}
+
+  util::Status GetStatus() { return status_; }
+
+  virtual void InvalidName(const converter::LocationTrackerInterface& loc,
+                           StringPiece unknown_name, StringPiece message) {
+    status_ = util::Status(util::error::INVALID_ARGUMENT,
+                             loc.ToString() + ": " + message.ToString());
+  }
+
+  virtual void InvalidValue(const converter::LocationTrackerInterface& loc,
+                            StringPiece type_name, StringPiece value) {
+    status_ =
+        util::Status(util::error::INVALID_ARGUMENT,
+                       loc.ToString() + ": invalid value " + value.ToString() +
+                           " for type " + type_name.ToString());
+  }
+
+  virtual void MissingField(const converter::LocationTrackerInterface& loc,
+                            StringPiece missing_name) {
+    status_ = util::Status(
+        util::error::INVALID_ARGUMENT,
+        loc.ToString() + ": missing field " + missing_name.ToString());
+  }
+
+ private:
+  util::Status status_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
+};
+}  // namespace
+
+util::Status JsonToBinaryStream(TypeResolver* resolver,
+                                  const string& type_url,
+                                  io::ZeroCopyInputStream* json_input,
+                                  io::ZeroCopyOutputStream* binary_output) {
+  google::protobuf::Type type;
+  RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
+  internal::ZeroCopyStreamByteSink sink(binary_output);
+  StatusErrorListener listener;
+  converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
+                                                  &listener);
+
+  converter::JsonStreamParser parser(&proto_writer);
+  const void* buffer;
+  int length;
+  while (json_input->Next(&buffer, &length)) {
+    if (length == 0) continue;
+    RETURN_IF_ERROR(
+        parser.Parse(StringPiece(static_cast<const char*>(buffer), length)));
+  }
+  RETURN_IF_ERROR(parser.FinishParse());
+
+  return listener.GetStatus();
+}
+
+util::Status JsonToBinaryString(TypeResolver* resolver,
+                                  const string& type_url,
+                                  const string& json_input,
+                                  string* binary_output) {
+  io::ArrayInputStream input_stream(json_input.data(), json_input.size());
+  io::StringOutputStream output_stream(binary_output);
+  return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream);
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/json_util.h b/src/third_party/protobuf-3/src/google/protobuf/util/json_util.h
new file mode 100644
index 0000000..1718bfb
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/json_util.h
@@ -0,0 +1,136 @@
+// 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.
+
+// Utility functions to convert between protobuf binary format and proto3 JSON
+// format.
+#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
+
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class ZeroCopyInputStream;
+class ZeroCopyOutputStream;
+}  // namespace io
+namespace util {
+
+struct JsonOptions {
+  // Whether to add spaces, line breaks and indentation to make the JSON output
+  // easy to read.
+  bool add_whitespace;
+  // Whether to always print primitive fields. By default primitive fields with
+  // default values will be omitted in JSON joutput. For example, an int32 field
+  // set to 0 will be omitted. Set this flag to true will override the default
+  // behavior and print primitive fields regardless of their values.
+  bool always_print_primitive_fields;
+
+  JsonOptions() : add_whitespace(false),
+                  always_print_primitive_fields(false) {
+  }
+};
+
+// Converts protobuf binary data to JSON.
+// The conversion will fail if:
+//   1. TypeResolver fails to resolve a type.
+//   2. input is not valid protobuf wire format, or conflicts with the type
+//      information returned by TypeResolver.
+// Note that unknown fields will be discarded silently.
+util::Status BinaryToJsonStream(
+    TypeResolver* resolver,
+    const string& type_url,
+    io::ZeroCopyInputStream* binary_input,
+    io::ZeroCopyOutputStream* json_output,
+    const JsonOptions& options);
+
+inline util::Status BinaryToJsonStream(
+    TypeResolver* resolver, const string& type_url,
+    io::ZeroCopyInputStream* binary_input,
+    io::ZeroCopyOutputStream* json_output) {
+  return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
+                            JsonOptions());
+}
+
+LIBPROTOBUF_EXPORT util::Status BinaryToJsonString(
+    TypeResolver* resolver,
+    const string& type_url,
+    const string& binary_input,
+    string* json_output,
+    const JsonOptions& options);
+
+inline util::Status BinaryToJsonString(TypeResolver* resolver,
+                                         const string& type_url,
+                                         const string& binary_input,
+                                         string* json_output) {
+  return BinaryToJsonString(resolver, type_url, binary_input, json_output,
+                            JsonOptions());
+}
+
+// Converts JSON data to protobuf binary format.
+// The conversion will fail if:
+//   1. TypeResolver fails to resolve a type.
+//   2. input is not valid JSON format, or conflicts with the type
+//      information returned by TypeResolver.
+//   3. input has unknown fields.
+util::Status JsonToBinaryStream(
+    TypeResolver* resolver,
+    const string& type_url,
+    io::ZeroCopyInputStream* json_input,
+    io::ZeroCopyOutputStream* binary_output);
+
+LIBPROTOBUF_EXPORT util::Status JsonToBinaryString(
+    TypeResolver* resolver,
+    const string& type_url,
+    const string& json_input,
+    string* binary_output);
+
+namespace internal {
+// Internal helper class. Put in the header so we can write unit-tests for it.
+class LIBPROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink {
+ public:
+  explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
+      : stream_(stream) {}
+
+  virtual void Append(const char* bytes, size_t len);
+
+ private:
+  io::ZeroCopyOutputStream* stream_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink);
+};
+}  // namespace internal
+
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/json_util_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/json_util_test.cc
new file mode 100644
index 0000000..a4d3cc9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/json_util_test.cc
@@ -0,0 +1,309 @@
+// 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.
+
+#include <google/protobuf/util/json_util.h>
+
+#include <list>
+#include <string>
+
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/util/json_format_proto3.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+using proto3::FOO;
+using proto3::BAR;
+using proto3::TestMessage;
+using proto3::TestMap;
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+  return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+// As functions defined in json_util.h are just thin wrappers around the
+// JSON conversion code in //net/proto2/util/converter, in this test we
+// only cover some very basic cases to make sure the wrappers have forwarded
+// parameters to the underlying implementation correctly. More detailed
+// tests are contained in the //net/proto2/util/converter directory.
+class JsonUtilTest : public testing::Test {
+ protected:
+  JsonUtilTest() {
+    resolver_.reset(NewTypeResolverForDescriptorPool(
+        kTypeUrlPrefix, DescriptorPool::generated_pool()));
+  }
+
+  string ToJson(const Message& message, const JsonOptions& options) {
+    string result;
+    GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(),
+                                GetTypeUrl(message.GetDescriptor()),
+                                message.SerializeAsString(), &result, options));
+    return result;
+  }
+
+  bool FromJson(const string& json, Message* message) {
+    string binary;
+    if (!JsonToBinaryString(resolver_.get(),
+                            GetTypeUrl(message->GetDescriptor()), json, &binary)
+             .ok()) {
+      return false;
+    }
+    return message->ParseFromString(binary);
+  }
+
+  google::protobuf::scoped_ptr<TypeResolver> resolver_;
+};
+
+TEST_F(JsonUtilTest, TestWhitespaces) {
+  TestMessage m;
+  m.mutable_message_value();
+
+  JsonOptions options;
+  EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
+  options.add_whitespace = true;
+  EXPECT_EQ(
+      "{\n"
+      " \"messageValue\": {}\n"
+      "}\n",
+      ToJson(m, options));
+}
+
+TEST_F(JsonUtilTest, TestDefaultValues) {
+  TestMessage m;
+  JsonOptions options;
+  EXPECT_EQ("{}", ToJson(m, options));
+  options.always_print_primitive_fields = true;
+  EXPECT_EQ(
+      "{\"boolValue\":false,"
+      "\"int32Value\":0,"
+      "\"int64Value\":\"0\","
+      "\"uint32Value\":0,"
+      "\"uint64Value\":\"0\","
+      "\"floatValue\":0,"
+      "\"doubleValue\":0,"
+      "\"stringValue\":\"\","
+      "\"bytesValue\":\"\","
+      "\"enumValue\":\"FOO\","
+      "\"repeatedBoolValue\":[],"
+      "\"repeatedInt32Value\":[],"
+      "\"repeatedInt64Value\":[],"
+      "\"repeatedUint32Value\":[],"
+      "\"repeatedUint64Value\":[],"
+      "\"repeatedFloatValue\":[],"
+      "\"repeatedDoubleValue\":[],"
+      "\"repeatedStringValue\":[],"
+      "\"repeatedBytesValue\":[],"
+      "\"repeatedEnumValue\":[],"
+      "\"repeatedMessageValue\":[]"
+      "}",
+      ToJson(m, options));
+}
+
+TEST_F(JsonUtilTest, ParseMessage) {
+  // Some random message but good enough to verify that the parsing warpper
+  // functions are working properly.
+  string input =
+      "{\n"
+      "  \"int32Value\": 1024,\n"
+      "  \"repeatedInt32Value\": [1, 2],\n"
+      "  \"messageValue\": {\n"
+      "    \"value\": 2048\n"
+      "  },\n"
+      "  \"repeatedMessageValue\": [\n"
+      "    {\"value\": 40}, {\"value\": 96}\n"
+      "  ]\n"
+      "}\n";
+  TestMessage m;
+  ASSERT_TRUE(FromJson(input, &m));
+  EXPECT_EQ(1024, m.int32_value());
+  ASSERT_EQ(2, m.repeated_int32_value_size());
+  EXPECT_EQ(1, m.repeated_int32_value(0));
+  EXPECT_EQ(2, m.repeated_int32_value(1));
+  EXPECT_EQ(2048, m.message_value().value());
+  ASSERT_EQ(2, m.repeated_message_value_size());
+  EXPECT_EQ(40, m.repeated_message_value(0).value());
+  EXPECT_EQ(96, m.repeated_message_value(1).value());
+}
+
+TEST_F(JsonUtilTest, ParseMap) {
+  TestMap message;
+  (*message.mutable_string_map())["hello"] = 1234;
+  JsonOptions options;
+  EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, options));
+  TestMap other;
+  ASSERT_TRUE(FromJson(ToJson(message, options), &other));
+  EXPECT_EQ(message.DebugString(), other.DebugString());
+}
+
+TEST_F(JsonUtilTest, TestParseErrors) {
+  TestMessage m;
+  JsonOptions options;
+  // Parsing should fail if the field name can not be recognized.
+  EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m));
+  // Parsing should fail if the value is invalid.
+  EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m));
+}
+
+typedef pair<char*, int> Segment;
+// A ZeroCopyOutputStream that writes to multiple buffers.
+class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
+ public:
+  explicit SegmentedZeroCopyOutputStream(list<Segment> segments)
+      : segments_(segments), last_segment_(static_cast<char*>(NULL), 0), byte_count_(0) {}
+
+  virtual bool Next(void** buffer, int* length) {
+    if (segments_.empty()) {
+      return false;
+    }
+    last_segment_ = segments_.front();
+    segments_.pop_front();
+    *buffer = last_segment_.first;
+    *length = last_segment_.second;
+    byte_count_ += *length;
+    return true;
+  }
+
+  virtual void BackUp(int length) {
+    GOOGLE_CHECK(length <= last_segment_.second);
+    segments_.push_front(
+        Segment(last_segment_.first + last_segment_.second - length, length));
+    last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
+    byte_count_ -= length;
+  }
+
+  virtual int64 ByteCount() const { return byte_count_; }
+
+ private:
+  list<Segment> segments_;
+  Segment last_segment_;
+  int64 byte_count_;
+};
+
+// This test splits the output buffer and also the input data into multiple
+// segments and checks that the implementation of ZeroCopyStreamByteSink
+// handles all possible cases correctly.
+TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
+  static const int kOutputBufferLength = 10;
+  // An exhaustive test takes too long, skip some combinations to make the test
+  // run faster.
+  static const int kSkippedPatternCount = 7;
+
+  char buffer[kOutputBufferLength];
+  for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
+       split_pattern += kSkippedPatternCount) {
+    // Split the buffer into small segments according to the split_pattern.
+    list<Segment> segments;
+    int segment_start = 0;
+    for (int i = 0; i < kOutputBufferLength - 1; ++i) {
+      if (split_pattern & (1 << i)) {
+        segments.push_back(
+            Segment(buffer + segment_start, i - segment_start + 1));
+        segment_start = i + 1;
+      }
+    }
+    segments.push_back(
+        Segment(buffer + segment_start, kOutputBufferLength - segment_start));
+
+    // Write exactly 10 bytes through the ByteSink.
+    string input_data = "0123456789";
+    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+         input_pattern += kSkippedPatternCount) {
+      memset(buffer, 0, sizeof(buffer));
+      {
+        SegmentedZeroCopyOutputStream output_stream(segments);
+        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+        int start = 0;
+        for (int j = 0; j < input_data.length() - 1; ++j) {
+          if (input_pattern & (1 << j)) {
+            byte_sink.Append(&input_data[start], j - start + 1);
+            start = j + 1;
+          }
+        }
+        byte_sink.Append(&input_data[start], input_data.length() - start);
+      }
+      EXPECT_EQ(input_data, string(buffer, input_data.length()));
+    }
+
+    // Write only 9 bytes through the ByteSink.
+    input_data = "012345678";
+    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+         input_pattern += kSkippedPatternCount) {
+      memset(buffer, 0, sizeof(buffer));
+      {
+        SegmentedZeroCopyOutputStream output_stream(segments);
+        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+        int start = 0;
+        for (int j = 0; j < input_data.length() - 1; ++j) {
+          if (input_pattern & (1 << j)) {
+            byte_sink.Append(&input_data[start], j - start + 1);
+            start = j + 1;
+          }
+        }
+        byte_sink.Append(&input_data[start], input_data.length() - start);
+      }
+      EXPECT_EQ(input_data, string(buffer, input_data.length()));
+      EXPECT_EQ(0, buffer[input_data.length()]);
+    }
+
+    // Write 11 bytes through the ByteSink. The extra byte will just
+    // be ignored.
+    input_data = "0123456789A";
+    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+         input_pattern += kSkippedPatternCount) {
+      memset(buffer, 0, sizeof(buffer));
+      {
+        SegmentedZeroCopyOutputStream output_stream(segments);
+        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+        int start = 0;
+        for (int j = 0; j < input_data.length() - 1; ++j) {
+          if (input_pattern & (1 << j)) {
+            byte_sink.Append(&input_data[start], j - start + 1);
+            start = j + 1;
+          }
+        }
+        byte_sink.Append(&input_data[start], input_data.length() - start);
+      }
+      EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
+                string(buffer, kOutputBufferLength));
+    }
+  }
+}
+
+}  // namespace
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.cc b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.cc
new file mode 100644
index 0000000..fe8119b
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.cc
@@ -0,0 +1,1689 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file defines static methods and classes for comparing Protocol
+// Messages (see //google/protobuf/util/message_differencer.h for more
+// information).
+
+#include <google/protobuf/util/message_differencer.h>
+
+#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <utility>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/any.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+
+namespace util {
+
+// When comparing a repeated field as map, MultipleFieldMapKeyComparator can
+// be used to specify multiple fields as key for key comparison.
+// Two elements of a repeated field will be regarded as having the same key
+// iff they have the same value for every specified key field.
+// Note that you can also specify only one field as key.
+class MessageDifferencer::MultipleFieldsMapKeyComparator
+    : public MessageDifferencer::MapKeyComparator {
+ public:
+  MultipleFieldsMapKeyComparator(
+      MessageDifferencer* message_differencer,
+      const vector<vector<const FieldDescriptor*> >& key_field_paths)
+        : message_differencer_(message_differencer),
+          key_field_paths_(key_field_paths) {
+    GOOGLE_CHECK(!key_field_paths_.empty());
+    for (int i = 0; i < key_field_paths_.size(); ++i) {
+      GOOGLE_CHECK(!key_field_paths_[i].empty());
+    }
+  }
+  MultipleFieldsMapKeyComparator(
+      MessageDifferencer* message_differencer,
+      const FieldDescriptor* key)
+        : message_differencer_(message_differencer) {
+    vector<const FieldDescriptor*> key_field_path;
+    key_field_path.push_back(key);
+    key_field_paths_.push_back(key_field_path);
+  }
+  virtual bool IsMatch(
+      const Message& message1,
+      const Message& message2,
+      const vector<SpecificField>& parent_fields) const {
+    for (int i = 0; i < key_field_paths_.size(); ++i) {
+      if (!IsMatchInternal(message1, message2, parent_fields,
+                           key_field_paths_[i], 0)) {
+        return false;
+      }
+    }
+    return true;
+  }
+ private:
+  bool IsMatchInternal(
+      const Message& message1,
+      const Message& message2,
+      const vector<SpecificField>& parent_fields,
+      const vector<const FieldDescriptor*>& key_field_path,
+      int path_index) const {
+    const FieldDescriptor* field = key_field_path[path_index];
+    vector<SpecificField> current_parent_fields(parent_fields);
+    if (path_index == key_field_path.size() - 1) {
+      if (field->is_repeated()) {
+        if (!message_differencer_->CompareRepeatedField(
+            message1, message2, field, &current_parent_fields)) {
+          return false;
+        }
+      } else {
+        if (!message_differencer_->CompareFieldValueUsingParentFields(
+            message1, message2, field, -1, -1, &current_parent_fields)) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      const Reflection* reflection1 = message1.GetReflection();
+      const Reflection* reflection2 = message2.GetReflection();
+      bool has_field1 = reflection1->HasField(message1, field);
+      bool has_field2 = reflection2->HasField(message2, field);
+      if (!has_field1 && !has_field2) {
+        return true;
+      }
+      if (has_field1 != has_field2) {
+        return false;
+      }
+      SpecificField specific_field;
+      specific_field.field = field;
+      current_parent_fields.push_back(specific_field);
+      return IsMatchInternal(
+          reflection1->GetMessage(message1, field),
+          reflection2->GetMessage(message2, field),
+          current_parent_fields,
+          key_field_path,
+          path_index + 1);
+    }
+  }
+  MessageDifferencer* message_differencer_;
+  vector<vector<const FieldDescriptor*> > key_field_paths_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
+};
+
+bool MessageDifferencer::Equals(const Message& message1,
+                                const Message& message2) {
+  MessageDifferencer differencer;
+
+  return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::Equivalent(const Message& message1,
+                                    const Message& message2) {
+  MessageDifferencer differencer;
+  differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
+
+  return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
+                                             const Message& message2) {
+  MessageDifferencer differencer;
+  differencer.set_float_comparison(
+      MessageDifferencer::APPROXIMATE);
+
+  return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
+                                                 const Message& message2) {
+  MessageDifferencer differencer;
+  differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
+  differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
+
+  return differencer.Compare(message1, message2);
+}
+
+// ===========================================================================
+
+MessageDifferencer::MessageDifferencer()
+    : reporter_(NULL),
+      field_comparator_(NULL),
+      message_field_comparison_(EQUAL),
+      scope_(FULL),
+      repeated_field_comparison_(AS_LIST),
+      report_matches_(false),
+      output_string_(NULL) { }
+
+MessageDifferencer::~MessageDifferencer() {
+  for (int i = 0; i < owned_key_comparators_.size(); ++i) {
+    delete owned_key_comparators_[i];
+  }
+  for (int i = 0; i < ignore_criteria_.size(); ++i) {
+    delete ignore_criteria_[i];
+  }
+}
+
+void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
+  GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
+  field_comparator_ = comparator;
+}
+
+void MessageDifferencer::set_message_field_comparison(
+    MessageFieldComparison comparison) {
+  message_field_comparison_ = comparison;
+}
+
+void MessageDifferencer::set_scope(Scope scope) {
+  scope_ = scope;
+}
+
+MessageDifferencer::Scope MessageDifferencer::scope() {
+  return scope_;
+}
+
+void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
+  default_field_comparator_.set_float_comparison(
+      comparison == EXACT ?
+      DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE);
+}
+
+void MessageDifferencer::set_repeated_field_comparison(
+    RepeatedFieldComparison comparison) {
+  repeated_field_comparison_ = comparison;
+}
+
+void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
+  GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+                               << field->full_name();
+  const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
+  GOOGLE_CHECK(key_comparator == NULL)
+      << "Cannot treat this repeated field as both Map and Set for"
+      << " comparison.  Field name is: " << field->full_name();
+  GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
+      << "Cannot treat the same field as both SET and LIST. Field name is: "
+      << field->full_name();
+  set_fields_.insert(field);
+}
+
+void MessageDifferencer::TreatAsList(const FieldDescriptor* field) {
+  GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+                              << field->full_name();
+  const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
+  GOOGLE_CHECK(key_comparator == NULL)
+      << "Cannot treat this repeated field as both Map and Set for"
+      << " comparison.  Field name is: " << field->full_name();
+  GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+      << "Cannot treat the same field as both SET and LIST. Field name is: "
+      << field->full_name();
+  list_fields_.insert(field);
+}
+
+void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
+                                    const FieldDescriptor* key) {
+  GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+                               << field->full_name();
+  GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+      << "Field has to be message type.  Field name is: "
+      << field->full_name();
+  GOOGLE_CHECK(key->containing_type() == field->message_type())
+      << key->full_name()
+      << " must be a direct subfield within the repeated field "
+      << field->full_name() << ", not " << key->containing_type()->full_name();
+  GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+      << "Cannot treat this repeated field as both Map and Set for "
+      << "comparison.";
+  GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
+      << "Cannot treat this repeated field as both Map and List for "
+      << "comparison.";
+  MapKeyComparator* key_comparator =
+      new MultipleFieldsMapKeyComparator(this, key);
+  owned_key_comparators_.push_back(key_comparator);
+  map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
+    const FieldDescriptor* field,
+    const vector<const FieldDescriptor*>& key_fields) {
+  vector<vector<const FieldDescriptor*> > key_field_paths;
+  for (int i = 0; i < key_fields.size(); ++i) {
+    vector<const FieldDescriptor*> key_field_path;
+    key_field_path.push_back(key_fields[i]);
+    key_field_paths.push_back(key_field_path);
+  }
+  TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
+}
+
+void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
+    const FieldDescriptor* field,
+    const vector<vector<const FieldDescriptor*> >& key_field_paths) {
+  GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+                              << field->full_name();
+  GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+      << "Field has to be message type.  Field name is: "
+      << field->full_name();
+  for (int i = 0; i < key_field_paths.size(); ++i) {
+    const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i];
+    for (int j = 0; j < key_field_path.size(); ++j) {
+      const FieldDescriptor* parent_field =
+          j == 0 ? field : key_field_path[j - 1];
+      const FieldDescriptor* child_field = key_field_path[j];
+      GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
+          << child_field->full_name()
+          << " must be a direct subfield within the field: "
+          << parent_field->full_name();
+      if (j != 0) {
+        GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type())
+            << parent_field->full_name() << " has to be of type message.";
+        GOOGLE_CHECK(!parent_field->is_repeated())
+            << parent_field->full_name() << " cannot be a repeated field.";
+      }
+    }
+  }
+  GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+      << "Cannot treat this repeated field as both Map and Set for "
+      << "comparison.";
+  MapKeyComparator* key_comparator =
+      new MultipleFieldsMapKeyComparator(this, key_field_paths);
+  owned_key_comparators_.push_back(key_comparator);
+  map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::TreatAsMapUsingKeyComparator(
+    const FieldDescriptor* field,
+    const MapKeyComparator* key_comparator) {
+  GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+                               << field->full_name();
+  GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+      << "Field has to be message type.  Field name is: "
+      << field->full_name();
+  GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+      << "Cannot treat this repeated field as both Map and Set for "
+      << "comparison.";
+  map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
+  ignore_criteria_.push_back(ignore_criteria);
+}
+
+void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
+  ignored_fields_.insert(field);
+}
+
+void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
+                                              double fraction, double margin) {
+  default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
+}
+
+void MessageDifferencer::ReportDifferencesToString(string* output) {
+  GOOGLE_DCHECK(output) << "Specified output string was NULL";
+
+  output_string_ = output;
+  output_string_->clear();
+}
+
+void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
+  // If an output string is set, clear it to prevent
+  // it superceding the specified reporter.
+  if (output_string_) {
+    output_string_ = NULL;
+  }
+
+  reporter_ = reporter;
+}
+
+bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
+                                     const FieldDescriptor* field2) {
+  // Handle sentinel values (i.e. make sure NULLs are always ordered
+  // at the end of the list).
+  if (field1 == NULL) {
+    return false;
+  }
+
+  if (field2 == NULL) {
+    return true;
+  }
+
+  // Always order fields by their tag number
+  return (field1->number() < field2->number());
+}
+
+bool MessageDifferencer::Compare(const Message& message1,
+                                 const Message& message2) {
+  vector<SpecificField> parent_fields;
+
+  bool result = false;
+
+  // Setup the internal reporter if need be.
+  if (output_string_) {
+    io::StringOutputStream output_stream(output_string_);
+    StreamReporter reporter(&output_stream);
+    reporter_ = &reporter;
+    result = Compare(message1, message2, &parent_fields);
+    reporter_ = NULL;
+  } else {
+    result = Compare(message1, message2, &parent_fields);
+  }
+
+  return result;
+}
+
+bool MessageDifferencer::CompareWithFields(
+    const Message& message1,
+    const Message& message2,
+    const vector<const FieldDescriptor*>& message1_fields_arg,
+    const vector<const FieldDescriptor*>& message2_fields_arg) {
+  if (message1.GetDescriptor() != message2.GetDescriptor()) {
+    GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
+                << "descriptors.";
+    return false;
+  }
+
+  vector<SpecificField> parent_fields;
+
+  bool result = false;
+
+  vector<const FieldDescriptor*> message1_fields(message1_fields_arg);
+  vector<const FieldDescriptor*> message2_fields(message2_fields_arg);
+
+  std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
+  std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
+  // Append NULL sentinel values.
+  message1_fields.push_back(NULL);
+  message2_fields.push_back(NULL);
+
+  // Setup the internal reporter if need be.
+  if (output_string_) {
+    io::StringOutputStream output_stream(output_string_);
+    StreamReporter reporter(&output_stream);
+    reporter_ = &reporter;
+    result = CompareRequestedFieldsUsingSettings(
+        message1, message2, message1_fields, message2_fields, &parent_fields);
+    reporter_ = NULL;
+  } else {
+    result = CompareRequestedFieldsUsingSettings(
+        message1, message2, message1_fields, message2_fields, &parent_fields);
+  }
+
+  return result;
+}
+
+bool MessageDifferencer::Compare(
+    const Message& message1,
+    const Message& message2,
+    vector<SpecificField>* parent_fields) {
+  const Descriptor* descriptor1 = message1.GetDescriptor();
+  const Descriptor* descriptor2 = message2.GetDescriptor();
+  if (descriptor1 != descriptor2) {
+    GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
+                << "descriptors. "
+                << descriptor1->full_name() << " vs "
+                << descriptor2->full_name();
+    return false;
+  }
+  // Expand google.protobuf.Any payload if possible.
+  if (descriptor1->full_name() == internal::kAnyFullTypeName) {
+    google::protobuf::scoped_ptr<Message> data1;
+    google::protobuf::scoped_ptr<Message> data2;
+    if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
+      return Compare(*data1, *data2, parent_fields);
+    }
+  }
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+
+  // Retrieve all the set fields, including extensions.
+  vector<const FieldDescriptor*> message1_fields;
+  vector<const FieldDescriptor*> message2_fields;
+
+  reflection1->ListFields(message1, &message1_fields);
+  reflection2->ListFields(message2, &message2_fields);
+
+  // Add sentinel values to deal with the
+  // case where the number of the fields in
+  // each list are different.
+  message1_fields.push_back(NULL);
+  message2_fields.push_back(NULL);
+
+  bool unknown_compare_result = true;
+  // Ignore unknown fields in EQUIVALENT mode
+  if (message_field_comparison_ != EQUIVALENT) {
+    const google::protobuf::UnknownFieldSet* unknown_field_set1 =
+        &reflection1->GetUnknownFields(message1);
+    const google::protobuf::UnknownFieldSet* unknown_field_set2 =
+        &reflection2->GetUnknownFields(message2);
+    if (!CompareUnknownFields(message1, message2,
+                              *unknown_field_set1, *unknown_field_set2,
+                              parent_fields)) {
+      if (reporter_ == NULL) {
+        return false;
+      };
+      unknown_compare_result = false;
+    }
+  }
+
+  return CompareRequestedFieldsUsingSettings(
+      message1, message2,
+      message1_fields, message2_fields,
+      parent_fields) && unknown_compare_result;
+}
+
+bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
+    const Message& message1,
+    const Message& message2,
+    const vector<const FieldDescriptor*>& message1_fields,
+    const vector<const FieldDescriptor*>& message2_fields,
+    vector<SpecificField>* parent_fields) {
+  if (scope_ == FULL) {
+    if (message_field_comparison_ == EQUIVALENT) {
+      // We need to merge the field lists of both messages (i.e.
+      // we are merely checking for a difference in field values,
+      // rather than the addition or deletion of fields).
+      vector<const FieldDescriptor*> fields_union;
+      CombineFields(message1_fields, FULL, message2_fields, FULL,
+                    &fields_union);
+      return CompareWithFieldsInternal(message1, message2, fields_union,
+                                       fields_union, parent_fields);
+    } else {
+      // Simple equality comparison, use the unaltered field lists.
+      return CompareWithFieldsInternal(message1, message2, message1_fields,
+                                       message2_fields, parent_fields);
+    }
+  } else {
+    if (message_field_comparison_ == EQUIVALENT) {
+      // We use the list of fields for message1 for both messages when
+      // comparing.  This way, extra fields in message2 are ignored,
+      // and missing fields in message2 use their default value.
+      return CompareWithFieldsInternal(message1, message2, message1_fields,
+                                       message1_fields, parent_fields);
+    } else {
+      // We need to consider the full list of fields for message1
+      // but only the intersection for message2.  This way, any fields
+      // only present in message2 will be ignored, but any fields only
+      // present in message1 will be marked as a difference.
+      vector<const FieldDescriptor*> fields_intersection;
+      CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL,
+                    &fields_intersection);
+      return CompareWithFieldsInternal(message1, message2, message1_fields,
+                                       fields_intersection, parent_fields);
+    }
+  }
+}
+
+void MessageDifferencer::CombineFields(
+    const vector<const FieldDescriptor*>& fields1,
+    Scope fields1_scope,
+    const vector<const FieldDescriptor*>& fields2,
+    Scope fields2_scope,
+    vector<const FieldDescriptor*>* combined_fields) {
+
+  int index1 = 0;
+  int index2 = 0;
+
+  while (index1 < fields1.size() && index2 < fields2.size()) {
+    const FieldDescriptor* field1 = fields1[index1];
+    const FieldDescriptor* field2 = fields2[index2];
+
+    if (FieldBefore(field1, field2)) {
+      if (fields1_scope == FULL) {
+        combined_fields->push_back(fields1[index1]);
+      }
+      ++index1;
+    } else if (FieldBefore(field2, field1)) {
+      if (fields2_scope == FULL) {
+        combined_fields->push_back(fields2[index2]);
+      }
+      ++index2;
+    } else {
+      combined_fields->push_back(fields1[index1]);
+      ++index1;
+      ++index2;
+    }
+  }
+}
+
+bool MessageDifferencer::CompareWithFieldsInternal(
+    const Message& message1,
+    const Message& message2,
+    const vector<const FieldDescriptor*>& message1_fields,
+    const vector<const FieldDescriptor*>& message2_fields,
+    vector<SpecificField>* parent_fields) {
+  bool isDifferent = false;
+  int field_index1 = 0;
+  int field_index2 = 0;
+
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+
+  while (true) {
+    const FieldDescriptor* field1 = message1_fields[field_index1];
+    const FieldDescriptor* field2 = message2_fields[field_index2];
+
+    // Once we have reached sentinel values, we are done the comparison.
+    if (field1 == NULL && field2 == NULL) {
+      break;
+    }
+
+    // Check for differences in the field itself.
+    if (FieldBefore(field1, field2)) {
+      // Field 1 is not in the field list for message 2.
+      if (IsIgnored(message1, message2, field1, *parent_fields)) {
+        // We are ignoring field1. Report the ignore and move on to
+        // the next field in message1_fields.
+        if (reporter_ != NULL) {
+          SpecificField specific_field;
+          specific_field.field = field1;
+
+          parent_fields->push_back(specific_field);
+          reporter_->ReportIgnored(message1, message2, *parent_fields);
+          parent_fields->pop_back();
+        }
+        ++field_index1;
+        continue;
+      }
+
+      if (reporter_ != NULL) {
+        int count = field1->is_repeated() ?
+            reflection1->FieldSize(message1, field1) : 1;
+
+        for (int i = 0; i < count; ++i) {
+          SpecificField specific_field;
+          specific_field.field = field1;
+          specific_field.index = field1->is_repeated() ? i : -1;
+
+          parent_fields->push_back(specific_field);
+          reporter_->ReportDeleted(message1, message2, *parent_fields);
+          parent_fields->pop_back();
+        }
+
+        isDifferent = true;
+      } else {
+        return false;
+      }
+
+      ++field_index1;
+      continue;
+    } else if (FieldBefore(field2, field1)) {
+      // Field 2 is not in the field list for message 1.
+      if (IsIgnored(message1, message2, field2, *parent_fields)) {
+        // We are ignoring field2. Report the ignore and move on to
+        // the next field in message2_fields.
+        if (reporter_ != NULL) {
+          SpecificField specific_field;
+          specific_field.field = field2;
+
+          parent_fields->push_back(specific_field);
+          reporter_->ReportIgnored(message1, message2, *parent_fields);
+          parent_fields->pop_back();
+        }
+        ++field_index2;
+        continue;
+      }
+
+      if (reporter_ != NULL) {
+        int count = field2->is_repeated() ?
+            reflection2->FieldSize(message2, field2) : 1;
+
+        for (int i = 0; i < count; ++i) {
+          SpecificField specific_field;
+          specific_field.field = field2;
+          specific_field.index = field2->is_repeated() ? i : -1;
+          specific_field.new_index = specific_field.index;
+
+          parent_fields->push_back(specific_field);
+          reporter_->ReportAdded(message1, message2, *parent_fields);
+          parent_fields->pop_back();
+        }
+
+        isDifferent = true;
+      } else {
+        return false;
+      }
+
+      ++field_index2;
+      continue;
+    }
+
+    // By this point, field1 and field2 are guarenteed to point to the same
+    // field, so we can now compare the values.
+    if (IsIgnored(message1, message2, field1, *parent_fields)) {
+      // Ignore this field. Report and move on.
+      if (reporter_ != NULL) {
+        SpecificField specific_field;
+        specific_field.field = field1;
+
+        parent_fields->push_back(specific_field);
+        reporter_->ReportIgnored(message1, message2, *parent_fields);
+        parent_fields->pop_back();
+      }
+
+      ++field_index1;
+      ++field_index2;
+      continue;
+    }
+
+    bool fieldDifferent = false;
+    if (field1->is_repeated()) {
+      fieldDifferent = !CompareRepeatedField(message1, message2, field1,
+                                             parent_fields);
+      if (fieldDifferent) {
+        if (reporter_ == NULL) return false;
+        isDifferent = true;
+      }
+    } else {
+      fieldDifferent = !CompareFieldValueUsingParentFields(
+          message1, message2, field1, -1, -1, parent_fields);
+
+      // If we have found differences, either report them or terminate if
+      // no reporter is present.
+      if (fieldDifferent && reporter_ == NULL) {
+        return false;
+      }
+
+      if (reporter_ != NULL) {
+        SpecificField specific_field;
+        specific_field.field = field1;
+        parent_fields->push_back(specific_field);
+        if (fieldDifferent) {
+          reporter_->ReportModified(message1, message2, *parent_fields);
+          isDifferent = true;
+        } else if (report_matches_) {
+          reporter_->ReportMatched(message1, message2, *parent_fields);
+        }
+        parent_fields->pop_back();
+      }
+    }
+    // Increment the field indicies.
+    ++field_index1;
+    ++field_index2;
+  }
+
+  return !isDifferent;
+}
+
+bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field,
+                                 const MapKeyComparator* key_comparator,
+                                 const Message* message1,
+                                 const Message* message2,
+                                 const vector<SpecificField>& parent_fields,
+                                 int index1, int index2) {
+  vector<SpecificField> current_parent_fields(parent_fields);
+  if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    return CompareFieldValueUsingParentFields(
+        *message1, *message2, repeated_field, index1, index2,
+        &current_parent_fields);
+  }
+  // Back up the Reporter and output_string_.  They will be reset in the
+  // following code.
+  Reporter* backup_reporter = reporter_;
+  string* output_string = output_string_;
+  reporter_ = NULL;
+  output_string_ = NULL;
+  bool match;
+
+  if (key_comparator == NULL) {
+    match = CompareFieldValueUsingParentFields(
+        *message1, *message2, repeated_field, index1, index2,
+        &current_parent_fields);
+  } else {
+    const Reflection* reflection1 = message1->GetReflection();
+    const Reflection* reflection2 = message2->GetReflection();
+    const Message& m1 =
+        reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
+    const Message& m2 =
+        reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
+    SpecificField specific_field;
+    specific_field.field = repeated_field;
+    current_parent_fields.push_back(specific_field);
+    match = key_comparator->IsMatch(m1, m2, current_parent_fields);
+  }
+
+  reporter_ = backup_reporter;
+  output_string_ = output_string;
+  return match;
+}
+
+bool MessageDifferencer::CompareRepeatedField(
+    const Message& message1,
+    const Message& message2,
+    const FieldDescriptor* repeated_field,
+    vector<SpecificField>* parent_fields) {
+  // the input FieldDescriptor is guaranteed to be repeated field.
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+  const int count1 = reflection1->FieldSize(message1, repeated_field);
+  const int count2 = reflection2->FieldSize(message2, repeated_field);
+  const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
+
+  // If the field is not treated as subset and no detailed reports is needed,
+  // we do a quick check on the number of the elements to avoid unnecessary
+  // comparison.
+  if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
+    return false;
+  }
+  // A match can never be found if message1 has more items than message2.
+  if (count1 > count2 && reporter_ == NULL) {
+    return false;
+  }
+
+  // These two list are used for store the index of the correspondent
+  // element in peer repeated field.
+  vector<int> match_list1;
+  vector<int> match_list2;
+
+  // Try to match indices of the repeated fields. Return false if match fails
+  // and there's no detailed report needed.
+  if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
+                                 *parent_fields, &match_list1, &match_list2) &&
+      reporter_ == NULL) {
+    return false;
+  }
+
+  bool fieldDifferent = false;
+  SpecificField specific_field;
+  specific_field.field = repeated_field;
+
+  // At this point, we have already matched pairs of fields (with the reporting
+  // to be done later). Now to check if the paired elements are different.
+  for (int i = 0; i < count1; i++) {
+    if (match_list1[i] == -1) continue;
+    specific_field.index = i;
+    specific_field.new_index = match_list1[i];
+
+    const bool result = CompareFieldValueUsingParentFields(
+        message1, message2, repeated_field, i, specific_field.new_index,
+        parent_fields);
+
+    // If we have found differences, either report them or terminate if
+    // no reporter is present. Note that ReportModified, ReportMoved, and
+    // ReportMatched are all mutually exclusive.
+    if (!result) {
+      if (reporter_ == NULL) return false;
+      parent_fields->push_back(specific_field);
+      reporter_->ReportModified(message1, message2, *parent_fields);
+      parent_fields->pop_back();
+      fieldDifferent = true;
+    } else if (reporter_ != NULL &&
+               specific_field.index != specific_field.new_index) {
+      parent_fields->push_back(specific_field);
+      reporter_->ReportMoved(message1, message2, *parent_fields);
+      parent_fields->pop_back();
+    } else if (report_matches_ && reporter_ != NULL) {
+      parent_fields->push_back(specific_field);
+      reporter_->ReportMatched(message1, message2, *parent_fields);
+      parent_fields->pop_back();
+    }
+  }
+
+  // Report any remaining additions or deletions.
+  for (int i = 0; i < count2; ++i) {
+    if (match_list2[i] != -1) continue;
+    if (!treated_as_subset) {
+      fieldDifferent = true;
+    }
+
+    if (reporter_ == NULL) continue;
+    specific_field.index = i;
+    specific_field.new_index = i;
+    parent_fields->push_back(specific_field);
+    reporter_->ReportAdded(message1, message2, *parent_fields);
+    parent_fields->pop_back();
+  }
+
+  for (int i = 0; i < count1; ++i) {
+    if (match_list1[i] != -1) continue;
+    specific_field.index = i;
+    parent_fields->push_back(specific_field);
+    reporter_->ReportDeleted(message1, message2, *parent_fields);
+    parent_fields->pop_back();
+    fieldDifferent = true;
+  }
+  return !fieldDifferent;
+}
+
+bool MessageDifferencer::CompareFieldValue(const Message& message1,
+                                           const Message& message2,
+                                           const FieldDescriptor* field,
+                                           int index1,
+                                           int index2) {
+  return CompareFieldValueUsingParentFields(message1, message2, field, index1,
+                                            index2, NULL);
+}
+
+bool MessageDifferencer::CompareFieldValueUsingParentFields(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* field, int index1, int index2,
+    vector<SpecificField>* parent_fields) {
+  FieldContext field_context(parent_fields);
+  FieldComparator::ComparisonResult result = GetFieldComparisonResult(
+      message1, message2, field, index1, index2, &field_context);
+
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+      result == FieldComparator::RECURSE) {
+    // Get the nested messages and compare them using one of the Compare
+    // methods.
+    const Reflection* reflection1 = message1.GetReflection();
+    const Reflection* reflection2 = message2.GetReflection();
+    const Message& m1 = field->is_repeated() ?
+        reflection1->GetRepeatedMessage(message1, field, index1) :
+        reflection1->GetMessage(message1, field);
+    const Message& m2 = field->is_repeated() ?
+        reflection2->GetRepeatedMessage(message2, field, index2) :
+        reflection2->GetMessage(message2, field);
+
+    // parent_fields is used in calls to Reporter methods.
+    if (parent_fields != NULL) {
+      // Append currently compared field to the end of parent_fields.
+      SpecificField specific_field;
+      specific_field.field = field;
+      specific_field.index = index1;
+      specific_field.new_index = index2;
+      parent_fields->push_back(specific_field);
+      const bool compare_result = Compare(m1, m2, parent_fields);
+      parent_fields->pop_back();
+      return compare_result;
+    } else {
+      // Recreates parent_fields as if m1 and m2 had no parents.
+      return Compare(m1, m2);
+    }
+  } else {
+    return (result == FieldComparator::SAME);
+  }
+}
+
+bool MessageDifferencer::CheckPathChanged(
+    const vector<SpecificField>& field_path) {
+  for (int i = 0; i < field_path.size(); ++i) {
+    if (field_path[i].index != field_path[i].new_index) return true;
+  }
+  return false;
+}
+
+bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
+  if (!field->is_repeated()) return false;
+  if (field->is_map()) return true;
+  if (repeated_field_comparison_ == AS_SET)
+    return list_fields_.find(field) == list_fields_.end();
+  return (set_fields_.find(field) != set_fields_.end());
+}
+
+bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
+  return scope_ == PARTIAL &&
+      (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
+}
+
+bool MessageDifferencer::IsIgnored(
+    const Message& message1,
+    const Message& message2,
+    const FieldDescriptor* field,
+    const vector<SpecificField>& parent_fields) {
+  if (ignored_fields_.find(field) != ignored_fields_.end()) {
+    return true;
+  }
+  for (int i = 0; i < ignore_criteria_.size(); ++i) {
+    if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
+                                       parent_fields)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool MessageDifferencer::IsUnknownFieldIgnored(
+    const Message& message1, const Message& message2,
+    const SpecificField& field, const vector<SpecificField>& parent_fields) {
+  for (int i = 0; i < ignore_criteria_.size(); ++i) {
+    if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
+                                                   parent_fields)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+const MessageDifferencer::MapKeyComparator* MessageDifferencer
+    ::GetMapKeyComparator(const FieldDescriptor* field) {
+  if (!field->is_repeated()) return NULL;
+  if (map_field_key_comparator_.find(field) !=
+      map_field_key_comparator_.end()) {
+    return map_field_key_comparator_[field];
+  }
+  return NULL;
+}
+
+namespace {
+
+typedef pair<int, const UnknownField*> IndexUnknownFieldPair;
+
+struct UnknownFieldOrdering {
+  inline bool operator()(const IndexUnknownFieldPair& a,
+                         const IndexUnknownFieldPair& b) const {
+    if (a.second->number() < b.second->number()) return true;
+    if (a.second->number() > b.second->number()) return false;
+    return a.second->type() < b.second->type();
+  }
+};
+
+}  // namespace
+
+bool MessageDifferencer::UnpackAny(const Message& any,
+                                   google::protobuf::scoped_ptr<Message>* data) {
+  const Reflection* reflection = any.GetReflection();
+  const FieldDescriptor* type_url_field;
+  const FieldDescriptor* value_field;
+  if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
+    return false;
+  }
+  const string& type_url = reflection->GetString(any, type_url_field);
+  string full_type_name;
+  if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
+    return false;
+  }
+
+  const google::protobuf::Descriptor* desc =
+      any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
+          full_type_name);
+  if (desc == NULL) {
+    GOOGLE_DLOG(ERROR) << "Proto type '" << full_type_name << "' not found";
+    return false;
+  }
+
+  if (dynamic_message_factory_ == NULL) {
+    dynamic_message_factory_.reset(new DynamicMessageFactory());
+  }
+  data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
+  string serialized_value = reflection->GetString(any, value_field);
+  if (!(*data)->ParseFromString(serialized_value)) {
+    GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
+    return false;
+  }
+  return true;
+}
+
+bool MessageDifferencer::CompareUnknownFields(
+    const Message& message1, const Message& message2,
+    const google::protobuf::UnknownFieldSet& unknown_field_set1,
+    const google::protobuf::UnknownFieldSet& unknown_field_set2,
+    vector<SpecificField>* parent_field) {
+  // Ignore unknown fields in EQUIVALENT mode.
+  if (message_field_comparison_ == EQUIVALENT) return true;
+
+  if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
+    return true;
+  }
+
+  bool is_different = false;
+
+  // We first sort the unknown fields by field number and type (in other words,
+  // in tag order), making sure to preserve ordering of values with the same
+  // tag.  This allows us to report only meaningful differences between the
+  // two sets -- that is, differing values for the same tag.  We use
+  // IndexUnknownFieldPairs to keep track of the field's original index for
+  // reporting purposes.
+  vector<IndexUnknownFieldPair> fields1;  // unknown_field_set1, sorted
+  vector<IndexUnknownFieldPair> fields2;  // unknown_field_set2, sorted
+  fields1.reserve(unknown_field_set1.field_count());
+  fields2.reserve(unknown_field_set2.field_count());
+
+  for (int i = 0; i < unknown_field_set1.field_count(); i++) {
+    fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
+  }
+  for (int i = 0; i < unknown_field_set2.field_count(); i++) {
+    fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
+  }
+
+  UnknownFieldOrdering is_before;
+  std::stable_sort(fields1.begin(), fields1.end(), is_before);
+  std::stable_sort(fields2.begin(), fields2.end(), is_before);
+
+  // In order to fill in SpecificField::index, we have to keep track of how
+  // many values we've seen with the same field number and type.
+  // current_repeated points at the first field in this range, and
+  // current_repeated_start{1,2} are the indexes of the first field in the
+  // range within fields1 and fields2.
+  const UnknownField* current_repeated = NULL;
+  int current_repeated_start1 = 0;
+  int current_repeated_start2 = 0;
+
+  // Now that we have two sorted lists, we can detect fields which appear only
+  // in one list or the other by traversing them simultaneously.
+  int index1 = 0;
+  int index2 = 0;
+  while (index1 < fields1.size() || index2 < fields2.size()) {
+    enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS,
+      NO_CHANGE } change_type;
+
+    // focus_field is the field we're currently reporting on.  (In the case
+    // of a modification, it's the field on the left side.)
+    const UnknownField* focus_field;
+    bool match = false;
+
+    if (index2 == fields2.size() ||
+        (index1 < fields1.size() &&
+          is_before(fields1[index1], fields2[index2]))) {
+      // fields1[index1] is not present in fields2.
+      change_type = DELETION;
+      focus_field = fields1[index1].second;
+    } else if (index1 == fields1.size() ||
+               is_before(fields2[index2], fields1[index1])) {
+      // fields2[index2] is not present in fields1.
+      if (scope_ == PARTIAL) {
+        // Ignore.
+        ++index2;
+        continue;
+      }
+      change_type = ADDITION;
+      focus_field = fields2[index2].second;
+    } else {
+      // Field type and number are the same.  See if the values differ.
+      change_type = MODIFICATION;
+      focus_field = fields1[index1].second;
+
+      switch (focus_field->type()) {
+        case UnknownField::TYPE_VARINT:
+          match = fields1[index1].second->varint() ==
+                  fields2[index2].second->varint();
+          break;
+        case UnknownField::TYPE_FIXED32:
+          match = fields1[index1].second->fixed32() ==
+                  fields2[index2].second->fixed32();
+          break;
+        case UnknownField::TYPE_FIXED64:
+          match = fields1[index1].second->fixed64() ==
+                  fields2[index2].second->fixed64();
+          break;
+        case UnknownField::TYPE_LENGTH_DELIMITED:
+          match = fields1[index1].second->length_delimited() ==
+                  fields2[index2].second->length_delimited();
+          break;
+        case UnknownField::TYPE_GROUP:
+          // We must deal with this later, after building the SpecificField.
+          change_type = COMPARE_GROUPS;
+          break;
+      }
+      if (match && change_type != COMPARE_GROUPS) {
+        change_type = NO_CHANGE;
+      }
+    }
+
+    if (current_repeated == NULL ||
+        focus_field->number() != current_repeated->number() ||
+        focus_field->type() != current_repeated->type()) {
+      // We've started a new repeated field.
+      current_repeated = focus_field;
+      current_repeated_start1 = index1;
+      current_repeated_start2 = index2;
+    }
+
+    if (change_type == NO_CHANGE && reporter_ == NULL) {
+      // Fields were already compared and matched and we have no reporter.
+      ++index1;
+      ++index2;
+      continue;
+    }
+
+    // Build the SpecificField.  This is slightly complicated.
+    SpecificField specific_field;
+    specific_field.unknown_field_number = focus_field->number();
+    specific_field.unknown_field_type = focus_field->type();
+
+    specific_field.unknown_field_set1 = &unknown_field_set1;
+    specific_field.unknown_field_set2 = &unknown_field_set2;
+
+    if (change_type != ADDITION) {
+      specific_field.unknown_field_index1 = fields1[index1].first;
+    }
+    if (change_type != DELETION) {
+      specific_field.unknown_field_index2 = fields2[index2].first;
+    }
+
+    // Calculate the field index.
+    if (change_type == ADDITION) {
+      specific_field.index = index2 - current_repeated_start2;
+      specific_field.new_index = index2 - current_repeated_start2;
+    } else {
+      specific_field.index = index1 - current_repeated_start1;
+      specific_field.new_index = index2 - current_repeated_start2;
+    }
+
+    if (IsUnknownFieldIgnored(message1, message2, specific_field,
+                              *parent_field)) {
+      if (reporter_ != NULL) {
+        parent_field->push_back(specific_field);
+        reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
+        parent_field->pop_back();
+      }
+      return true;
+    }
+
+    if (change_type == ADDITION || change_type == DELETION ||
+        change_type == MODIFICATION) {
+      if (reporter_ == NULL) {
+        // We found a difference and we have no reproter.
+        return false;
+      }
+      is_different = true;
+    }
+
+    parent_field->push_back(specific_field);
+
+    switch (change_type) {
+      case ADDITION:
+        reporter_->ReportAdded(message1, message2, *parent_field);
+        ++index2;
+        break;
+      case DELETION:
+        reporter_->ReportDeleted(message1, message2, *parent_field);
+        ++index1;
+        break;
+      case MODIFICATION:
+        reporter_->ReportModified(message1, message2, *parent_field);
+        ++index1;
+        ++index2;
+        break;
+      case COMPARE_GROUPS:
+        if (!CompareUnknownFields(message1, message2,
+                                  fields1[index1].second->group(),
+                                  fields2[index2].second->group(),
+                                  parent_field)) {
+          if (reporter_ == NULL) return false;
+          is_different = true;
+          reporter_->ReportModified(message1, message2, *parent_field);
+        }
+        ++index1;
+        ++index2;
+        break;
+      case NO_CHANGE:
+        ++index1;
+        ++index2;
+        if (report_matches_) {
+          reporter_->ReportMatched(message1, message2, *parent_field);
+        }
+    }
+
+    parent_field->pop_back();
+  }
+
+  return !is_different;
+}
+
+namespace {
+
+// Find maximum bipartite matching using the argumenting path algorithm.
+class MaximumMatcher {
+ public:
+  typedef ResultCallback2<bool, int, int> NodeMatchCallback;
+  // MaximumMatcher takes ownership of the passed in callback and uses it to
+  // determine whether a node on the left side of the bipartial graph matches
+  // a node on the right side. count1 is the number of nodes on the left side
+  // of the graph and count2 to is the number of nodes on the right side.
+  // Every node is referred to using 0-based indices.
+  // If a maximum match is found, the result will be stored in match_list1 and
+  // match_list2. match_list1[i] == j means the i-th node on the left side is
+  // matched to the j-th node on the right side and match_list2[x] == y means
+  // the x-th node on the right side is matched to y-th node on the left side.
+  // match_list1[i] == -1 means the node is not matched. Same with match_list2.
+  MaximumMatcher(int count1, int count2, NodeMatchCallback* callback,
+                 vector<int>* match_list1, vector<int>* match_list2);
+  // Find a maximum match and return the number of matched node pairs.
+  // If early_return is true, this method will return 0 immediately when it
+  // finds that not all nodes on the left side can be matched.
+  int FindMaximumMatch(bool early_return);
+ private:
+  // Determines whether the node on the left side of the bipartial graph
+  // matches the one on the right side.
+  bool Match(int left, int right);
+  // Find an argumenting path starting from the node v on the left side. If a
+  // path can be found, update match_list2_ to reflect the path and return
+  // true.
+  bool FindArgumentPathDFS(int v, vector<bool>* visited);
+
+  int count1_;
+  int count2_;
+  google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_;
+  map<pair<int, int>, bool> cached_match_results_;
+  vector<int>* match_list1_;
+  vector<int>* match_list2_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
+};
+
+MaximumMatcher::MaximumMatcher(int count1, int count2,
+                               NodeMatchCallback* callback,
+                               vector<int>* match_list1,
+                               vector<int>* match_list2)
+    : count1_(count1), count2_(count2), match_callback_(callback),
+      match_list1_(match_list1), match_list2_(match_list2) {
+  match_list1_->assign(count1, -1);
+  match_list2_->assign(count2, -1);
+}
+
+int MaximumMatcher::FindMaximumMatch(bool early_return) {
+  int result = 0;
+  for (int i = 0; i < count1_; ++i) {
+    vector<bool> visited(count1_);
+    if (FindArgumentPathDFS(i, &visited)) {
+      ++result;
+    } else if (early_return) {
+      return 0;
+    }
+  }
+  // Backfill match_list1_ as we only filled match_list2_ when finding
+  // argumenting pathes.
+  for (int i = 0; i < count2_; ++i) {
+    if ((*match_list2_)[i] != -1) {
+      (*match_list1_)[(*match_list2_)[i]] = i;
+    }
+  }
+  return result;
+}
+
+bool MaximumMatcher::Match(int left, int right) {
+  pair<int, int> p(left, right);
+  map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p);
+  if (it != cached_match_results_.end()) {
+    return it->second;
+  }
+  cached_match_results_[p] = match_callback_->Run(left, right);
+  return cached_match_results_[p];
+}
+
+bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) {
+  (*visited)[v] = true;
+  // We try to match those un-matched nodes on the right side first. This is
+  // the step that the navie greedy matching algorithm uses. In the best cases
+  // where the greedy algorithm can find a maximum matching, we will always
+  // find a match in this step and the performance will be identical to the
+  // greedy algorithm.
+  for (int i = 0; i < count2_; ++i) {
+    int matched = (*match_list2_)[i];
+    if (matched == -1 && Match(v, i)) {
+      (*match_list2_)[i] = v;
+      return true;
+    }
+  }
+  // Then we try those already matched nodes and see if we can find an
+  // alternaive match for the node matched to them.
+  // The greedy algorithm will stop before this and fail to produce the
+  // correct result.
+  for (int i = 0; i < count2_; ++i) {
+    int matched = (*match_list2_)[i];
+    if (matched != -1 && Match(v, i)) {
+      if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
+        (*match_list2_)[i] = v;
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+bool MessageDifferencer::MatchRepeatedFieldIndices(
+    const Message& message1,
+    const Message& message2,
+    const FieldDescriptor* repeated_field,
+    const vector<SpecificField>& parent_fields,
+    vector<int>* match_list1,
+    vector<int>* match_list2) {
+  const int count1 =
+      message1.GetReflection()->FieldSize(message1, repeated_field);
+  const int count2 =
+      message2.GetReflection()->FieldSize(message2, repeated_field);
+  const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
+
+  match_list1->assign(count1, -1);
+  match_list2->assign(count2, -1);
+
+  SpecificField specific_field;
+  specific_field.field = repeated_field;
+
+  bool success = true;
+  // Find potential match if this is a special repeated field.
+  if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) {
+    if (scope_ == PARTIAL) {
+      // When partial matching is enabled, Compare(a, b) && Compare(a, c)
+      // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy
+      // algorithm will fail to find a maximum matching.
+      // Here we use the argumenting path algorithm.
+      MaximumMatcher::NodeMatchCallback* callback =
+          ::google::protobuf::internal::NewPermanentCallback(
+              this, &MessageDifferencer::IsMatch,
+              repeated_field, key_comparator,
+              &message1, &message2, parent_fields);
+      MaximumMatcher matcher(count1, count2, callback, match_list1,
+                             match_list2);
+      // If diff info is not needed, we should end the matching process as
+      // soon as possible if not all items can be matched.
+      bool early_return = (reporter_ == NULL);
+      int match_count = matcher.FindMaximumMatch(early_return);
+      if (match_count != count1 && reporter_ == NULL) return false;
+      success = success && (match_count == count1);
+    } else {
+      for (int i = 0; i < count1; ++i) {
+        // Indicates any matched elements for this repeated field.
+        bool match = false;
+
+        specific_field.index = i;
+        specific_field.new_index = i;
+
+        for (int j = 0; j < count2; j++) {
+          if (match_list2->at(j) != -1) continue;
+          specific_field.index = i;
+          specific_field.new_index = j;
+
+          match = IsMatch(repeated_field, key_comparator,
+                          &message1, &message2, parent_fields, i, j);
+
+          if (match) {
+            match_list1->at(specific_field.index) = specific_field.new_index;
+            match_list2->at(specific_field.new_index) = specific_field.index;
+            break;
+          }
+        }
+        if (!match && reporter_ == NULL) return false;
+        success = success && match;
+      }
+    }
+  } else {
+    // If this field should be treated as list, just label the match_list.
+    for (int i = 0; i < count1 && i < count2; i++) {
+      match_list1->at(i) = i;
+      match_list2->at(i) = i;
+    }
+  }
+
+  return success;
+}
+
+FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* field, int index1, int index2,
+    const FieldContext* field_context) {
+  FieldComparator* comparator = field_comparator_ != NULL ?
+      field_comparator_ : &default_field_comparator_;
+  return comparator->Compare(message1, message2, field,
+                             index1, index2, field_context);
+}
+
+// ===========================================================================
+
+MessageDifferencer::Reporter::Reporter() { }
+MessageDifferencer::Reporter::~Reporter() {}
+
+// ===========================================================================
+
+MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
+MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
+
+// ===========================================================================
+
+MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
+MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
+
+// ===========================================================================
+
+// Note that the printer's delimiter is not used, because if we are given a
+// printer, we don't know its delimiter.
+MessageDifferencer::StreamReporter::StreamReporter(
+    io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')),
+                                        delete_printer_(true),
+                                        report_modified_aggregates_(false) { }
+
+MessageDifferencer::StreamReporter::StreamReporter(
+    io::Printer* printer) : printer_(printer),
+                            delete_printer_(false),
+                            report_modified_aggregates_(false) { }
+
+MessageDifferencer::StreamReporter::~StreamReporter() {
+  if (delete_printer_) delete printer_;
+}
+
+void MessageDifferencer::StreamReporter::PrintPath(
+    const vector<SpecificField>& field_path, bool left_side) {
+  for (int i = 0; i < field_path.size(); ++i) {
+    if (i > 0) {
+      printer_->Print(".");
+    }
+
+    SpecificField specific_field = field_path[i];
+
+    if (specific_field.field != NULL) {
+      if (specific_field.field->is_extension()) {
+        printer_->Print("($name$)", "name",
+                        specific_field.field->full_name());
+      } else {
+        printer_->PrintRaw(specific_field.field->name());
+      }
+    } else {
+      printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number));
+    }
+    if (left_side && specific_field.index >= 0) {
+      printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index));
+    }
+    if (!left_side && specific_field.new_index >= 0) {
+      printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index));
+    }
+  }
+}
+
+void MessageDifferencer::
+StreamReporter::PrintValue(const Message& message,
+                           const vector<SpecificField>& field_path,
+                           bool left_side) {
+  const SpecificField& specific_field = field_path.back();
+  const FieldDescriptor* field = specific_field.field;
+  if (field != NULL) {
+    string output;
+    int index = left_side ? specific_field.index : specific_field.new_index;
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      const Reflection* reflection = message.GetReflection();
+      const Message& field_message = field->is_repeated() ?
+          reflection->GetRepeatedMessage(message, field, index) :
+          reflection->GetMessage(message, field);
+      output = field_message.ShortDebugString();
+      if (output.empty()) {
+        printer_->Print("{ }");
+      } else {
+        printer_->Print("{ $name$ }", "name", output);
+      }
+    } else {
+      TextFormat::PrintFieldValueToString(message, field, index, &output);
+      printer_->PrintRaw(output);
+    }
+  } else {
+    const UnknownFieldSet* unknown_fields =
+        (left_side ?
+         specific_field.unknown_field_set1 :
+         specific_field.unknown_field_set2);
+    const UnknownField* unknown_field = &unknown_fields->field(
+        left_side ?
+        specific_field.unknown_field_index1 :
+        specific_field.unknown_field_index2);
+    PrintUnknownFieldValue(unknown_field);
+  }
+}
+
+void MessageDifferencer::
+StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) {
+  GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
+
+  string output;
+  switch (unknown_field->type()) {
+    case UnknownField::TYPE_VARINT:
+      output = SimpleItoa(unknown_field->varint());
+      break;
+    case UnknownField::TYPE_FIXED32:
+      output = StrCat("0x", strings::Hex(unknown_field->fixed32(),
+                                         strings::ZERO_PAD_8));
+      break;
+    case UnknownField::TYPE_FIXED64:
+      output = StrCat("0x", strings::Hex(unknown_field->fixed64(),
+                                         strings::ZERO_PAD_16));
+      break;
+    case UnknownField::TYPE_LENGTH_DELIMITED:
+      output = StringPrintf("\"%s\"",
+          CEscape(unknown_field->length_delimited()).c_str());
+      break;
+    case UnknownField::TYPE_GROUP:
+      // TODO(kenton):  Print the contents of the group like we do for
+      //   messages.  Requires an equivalent of ShortDebugString() for
+      //   UnknownFieldSet.
+      output = "{ ... }";
+      break;
+  }
+  printer_->PrintRaw(output);
+}
+
+void MessageDifferencer::StreamReporter::Print(const string& str) {
+  printer_->Print(str.c_str());
+}
+
+void MessageDifferencer::StreamReporter::ReportAdded(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("added: ");
+  PrintPath(field_path, false);
+  printer_->Print(": ");
+  PrintValue(message2, field_path, false);
+  printer_->Print("\n");  // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportDeleted(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("deleted: ");
+  PrintPath(field_path, true);
+  printer_->Print(": ");
+  PrintValue(message1, field_path, true);
+  printer_->Print("\n");  // Print for newlines
+}
+
+void MessageDifferencer::StreamReporter::ReportModified(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  if (!report_modified_aggregates_ && field_path.back().field == NULL) {
+    if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
+      // Any changes to the subfields have already been printed.
+      return;
+    }
+  } else if (!report_modified_aggregates_) {
+    if (field_path.back().field->cpp_type() ==
+        FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Any changes to the subfields have already been printed.
+      return;
+    }
+  }
+
+  printer_->Print("modified: ");
+  PrintPath(field_path, true);
+  if (CheckPathChanged(field_path)) {
+    printer_->Print(" -> ");
+    PrintPath(field_path, false);
+  }
+  printer_->Print(": ");
+  PrintValue(message1, field_path, true);
+  printer_->Print(" -> ");
+  PrintValue(message2, field_path, false);
+  printer_->Print("\n");  // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportMoved(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("moved: ");
+  PrintPath(field_path, true);
+  printer_->Print(" -> ");
+  PrintPath(field_path, false);
+  printer_->Print(" : ");
+  PrintValue(message1, field_path, true);
+  printer_->Print("\n");  // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportMatched(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("matched: ");
+  PrintPath(field_path, true);
+  if (CheckPathChanged(field_path)) {
+    printer_->Print(" -> ");
+    PrintPath(field_path, false);
+  }
+  printer_->Print(" : ");
+  PrintValue(message1, field_path, true);
+  printer_->Print("\n");  // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportIgnored(
+    const Message& message1,
+    const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("ignored: ");
+  PrintPath(field_path, true);
+  if (CheckPathChanged(field_path)) {
+    printer_->Print(" -> ");
+    PrintPath(field_path, false);
+  }
+  printer_->Print("\n");  // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
+    const Message& message1, const Message& message2,
+    const vector<SpecificField>& field_path) {
+  printer_->Print("ignored: ");
+  PrintPath(field_path, true);
+  if (CheckPathChanged(field_path)) {
+    printer_->Print(" -> ");
+    PrintPath(field_path, false);
+  }
+  printer_->Print("\n");  // Print for newlines.
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.h b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.h
new file mode 100644
index 0000000..3ea74e6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer.h
@@ -0,0 +1,843 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file defines static methods and classes for comparing Protocol
+// Messages.
+//
+// Aug. 2008: Added Unknown Fields Comparison for messages.
+// Aug. 2009: Added different options to compare repeated fields.
+// Apr. 2010: Moved field comparison to FieldComparator.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
+#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h>  // FieldDescriptor
+#include <google/protobuf/message.h>  // Message
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/util/field_comparator.h>
+
+namespace google {
+namespace protobuf {
+
+class DynamicMessageFactory;
+class FieldDescriptor;
+
+namespace io {
+class ZeroCopyOutputStream;
+class Printer;
+}
+
+namespace util {
+
+class FieldContext;  // declared below MessageDifferencer
+
+// A basic differencer that can be used to determine
+// the differences between two specified Protocol Messages. If any differences
+// are found, the Compare method will return false, and any differencer reporter
+// specified via ReportDifferencesTo will have its reporting methods called (see
+// below for implementation of the report). Based off of the original
+// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
+// (Thanks Todd!).
+//
+// MessageDifferencer REQUIRES that compared messages be the same type, defined
+// as messages that share the same descriptor.  If not, the behavior of this
+// class is undefined.
+//
+// People disagree on what MessageDifferencer should do when asked to compare
+// messages with different descriptors.  Some people think it should always
+// return false.  Others expect it to try to look for similar fields and
+// compare them anyway -- especially if the descriptors happen to be identical.
+// If we chose either of these behaviors, some set of people would find it
+// surprising, and could end up writing code expecting the other behavior
+// without realizing their error.  Therefore, we forbid that usage.
+//
+// This class is implemented based on the proto2 reflection. The performance
+// should be good enough for normal usages. However, for places where the
+// performance is extremely sensitive, there are several alternatives:
+// - Comparing serialized string
+// Downside: false negatives (there are messages that are the same but their
+// serialized strings are different).
+// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
+// Downside: more generated code; maintenance overhead for the additional rule
+// (must be in sync with the original proto_library).
+//
+// Note on handling of google.protobuf.Any: MessageDifferencer automatically
+// unpacks Any::value into a Message and compares its individual fields.
+// Messages encoded in a repeated Any cannot be compared using TreatAsMap.
+//
+//
+// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
+// guard it with a lock to use the same MessageDifferencer instance from
+// multiple threads. Note that it's fine to call static comparison methods
+// (like MessageDifferencer::Equals) concurrently.
+class LIBPROTOBUF_EXPORT MessageDifferencer {
+ public:
+  // Determines whether the supplied messages are equal. Equality is defined as
+  // all fields within the two messages being set to the same value. Primitive
+  // fields and strings are compared by value while embedded messages/groups
+  // are compared as if via a recursive call. Use IgnoreField() and Compare()
+  // if some fields should be ignored in the comparison.
+  //
+  // This method REQUIRES that the two messages have the same
+  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+  static bool Equals(const Message& message1, const Message& message2);
+
+  // Determines whether the supplied messages are equivalent. Equivalency is
+  // defined as all fields within the two messages having the same value. This
+  // differs from the Equals method above in that fields with default values
+  // are considered set to said value automatically. For details on how default
+  // values are defined for each field type, see http://shortn/_x2Gv6XFrWt.
+  // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
+  // if some fields should be ignored in the comparison.
+  //
+  // This method REQUIRES that the two messages have the same
+  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+  static bool Equivalent(const Message& message1, const Message& message2);
+
+  // Determines whether the supplied messages are approximately equal.
+  // Approximate equality is defined as all fields within the two messages
+  // being approximately equal.  Primitive (non-float) fields and strings are
+  // compared by value, floats are compared using MathUtil::AlmostEquals() and
+  // embedded messages/groups are compared as if via a recursive call. Use
+  // IgnoreField() and Compare() if some fields should be ignored in the
+  // comparison.
+  //
+  // This method REQUIRES that the two messages have the same
+  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+  static bool ApproximatelyEquals(const Message& message1,
+                                  const Message& message2);
+
+  // Determines whether the supplied messages are approximately equivalent.
+  // Approximate equivalency is defined as all fields within the two messages
+  // being approximately equivalent. As in
+  // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
+  // strings are compared by value, floats are compared using
+  // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
+  // via a recursive call. However, fields with default values are considered
+  // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
+  // and Compare() if some fields should be ignored in the comparison.
+  //
+  // This method REQUIRES that the two messages have the same
+  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+  static bool ApproximatelyEquivalent(const Message& message1,
+                                      const Message& message2);
+
+  // Identifies an individual field in a message instance.  Used for field_path,
+  // below.
+  struct SpecificField {
+    // For known fields, "field" is filled in and "unknown_field_number" is -1.
+    // For unknown fields, "field" is NULL, "unknown_field_number" is the field
+    // number, and "unknown_field_type" is its type.
+    const FieldDescriptor* field;
+    int unknown_field_number;
+    UnknownField::Type unknown_field_type;
+
+    // If this a repeated field, "index" is the index within it.  For unknown
+    // fields, this is the index of the field among all unknown fields of the
+    // same field number and type.
+    int index;
+
+    // If "field" is a repeated field which is being treated as a map or
+    // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
+    // the index the position to which the element has moved.  This only
+    // applies to ReportMoved() and (in the case of TreatAsMap())
+    // ReportModified().  In all other cases, "new_index" will have the same
+    // value as "index".
+    int new_index;
+
+    // For unknown fields, these are the pointers to the UnknownFieldSet
+    // containing the unknown fields. In certain cases (e.g. proto1's
+    // MessageSet, or nested groups of unknown fields), these may differ from
+    // the messages' internal UnknownFieldSets.
+    const UnknownFieldSet* unknown_field_set1;
+    const UnknownFieldSet* unknown_field_set2;
+
+    // For unknown fields, these are the index of the field within the
+    // UnknownFieldSets. One or the other will be -1 when
+    // reporting an addition or deletion.
+    int unknown_field_index1;
+    int unknown_field_index2;
+
+    SpecificField()
+        : field(NULL),
+          unknown_field_number(-1),
+          index(-1),
+          new_index(-1),
+          unknown_field_set1(NULL),
+          unknown_field_set2(NULL),
+          unknown_field_index1(-1),
+          unknown_field_index2(-1) {}
+  };
+
+  // Abstract base class from which all MessageDifferencer
+  // reporters derive. The five Report* methods below will be called when
+  // a field has been added, deleted, modified, moved, or matched. The third
+  // argument is a vector of FieldDescriptor pointers which describes the chain
+  // of fields that was taken to find the current field. For example, for a
+  // field found in an embedded message, the vector will contain two
+  // FieldDescriptors. The first will be the field of the embedded message
+  // itself and the second will be the actual field in the embedded message
+  // that was added/deleted/modified.
+  class LIBPROTOBUF_EXPORT Reporter {
+   public:
+    Reporter();
+    virtual ~Reporter();
+
+    // Reports that a field has been added into Message2.
+    virtual void ReportAdded(
+        const Message& message1, const Message& message2,
+        const vector<SpecificField>& field_path) = 0;
+
+    // Reports that a field has been deleted from Message1.
+    virtual void ReportDeleted(
+        const Message& message1,
+        const Message& message2,
+        const vector<SpecificField>& field_path) = 0;
+
+    // Reports that the value of a field has been modified.
+    virtual void ReportModified(
+        const Message& message1,
+        const Message& message2,
+        const vector<SpecificField>& field_path) = 0;
+
+    // Reports that a repeated field has been moved to another location.  This
+    // only applies when using TreatAsSet or TreatAsMap()  -- see below. Also
+    // note that for any given field, ReportModified and ReportMoved are
+    // mutually exclusive. If a field has been both moved and modified, then
+    // only ReportModified will be called.
+    virtual void ReportMoved(
+        const Message& message1,
+        const Message& message2,
+        const vector<SpecificField>& field_path) { }
+
+    // Reports that two fields match. Useful for doing side-by-side diffs.
+    // This function is mutually exclusive with ReportModified and ReportMoved.
+    // Note that you must call set_report_matches(true) before calling Compare
+    // to make use of this function.
+    virtual void ReportMatched(
+        const Message& message1,
+        const Message& message2,
+        const vector<SpecificField>& field_path) { }
+
+    // Reports that two fields would have been compared, but the
+    // comparison has been skipped because the field was marked as
+    // 'ignored' using IgnoreField().  This function is mutually
+    // exclusive with all the other Report() functions.
+    //
+    // The contract of ReportIgnored is slightly different than the
+    // other Report() functions, in that |field_path.back().index| is
+    // always equal to -1, even if the last field is repeated. This is
+    // because while the other Report() functions indicate where in a
+    // repeated field the action (Addition, Deletion, etc...)
+    // happened, when a repeated field is 'ignored', the differencer
+    // simply calls ReportIgnored on the repeated field as a whole and
+    // moves on without looking at its individual elements.
+    //
+    // Furthermore, ReportIgnored() does not indicate whether the
+    // fields were in fact equal or not, as Compare() does not inspect
+    // these fields at all. It is up to the Reporter to decide whether
+    // the fields are equal or not (perhaps with a second call to
+    // Compare()), if it cares.
+    virtual void ReportIgnored(
+        const Message& message1,
+        const Message& message2,
+        const vector<SpecificField>& field_path) { }
+
+    // Report that an unkown field is ignored. (see comment above).
+    // Note this is a different function since the last SpecificField in field
+    // path has a null field.  This could break existing Reporter.
+    virtual void ReportUnknownFieldIgnored(
+        const Message& message1, const Message& message2,
+        const vector<SpecificField>& field_path) {}
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
+  };
+
+  // MapKeyComparator is used to determine if two elements have the same key
+  // when comparing elements of a repeated field as a map.
+  class LIBPROTOBUF_EXPORT MapKeyComparator {
+   public:
+    MapKeyComparator();
+    virtual ~MapKeyComparator();
+
+    virtual bool IsMatch(const Message& message1,
+                         const Message& message2,
+                         const vector<SpecificField>& parent_fields) const {
+      GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
+      return false;
+    }
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
+  };
+
+  // Abstract base class from which all IgnoreCriteria derive.
+  // By adding IgnoreCriteria more complex ignore logic can be implemented.
+  // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared
+  // field IsIgnored is called on each added IgnoreCriteria until one returns
+  // true or all return false.
+  // IsIgnored is called for fields where at least one side has a value.
+  class LIBPROTOBUF_EXPORT IgnoreCriteria {
+   public:
+    IgnoreCriteria();
+    virtual ~IgnoreCriteria();
+
+    // Returns true if the field should be ignored.
+    virtual bool IsIgnored(
+        const Message& message1,
+        const Message& message2,
+        const FieldDescriptor* field,
+        const vector<SpecificField>& parent_fields) = 0;
+
+    // Returns true if the unknown field should be ignored.
+    // Note: This will be called for unknown fields as well in which case
+    //       field.field will be null.
+    virtual bool IsUnknownFieldIgnored(
+        const Message& message1, const Message& message2,
+        const SpecificField& field,
+        const vector<SpecificField>& parent_fields) {
+      return false;
+    }
+  };
+
+  // To add a Reporter, construct default here, then use ReportDifferencesTo or
+  // ReportDifferencesToString.
+  explicit MessageDifferencer();
+
+  ~MessageDifferencer();
+
+  enum MessageFieldComparison {
+    EQUAL,       // Fields must be present in both messages
+                 // for the messages to be considered the same.
+    EQUIVALENT,  // Fields with default values are considered set
+                 // for comparison purposes even if not explicitly
+                 // set in the messages themselves.  Unknown fields
+                 // are ignored.
+  };
+
+  enum Scope {
+    FULL,    // All fields of both messages are considered in the comparison.
+    PARTIAL  // Only fields present in the first message are considered; fields
+             // set only in the second message will be skipped during
+             // comparison.
+  };
+
+  // DEPRECATED. Use FieldComparator::FloatComparison instead.
+  enum FloatComparison {
+    EXACT,       // Floats and doubles are compared exactly.
+    APPROXIMATE  // Floats and doubles are compared using the
+                 // MathUtil::AlmostEquals method.
+  };
+
+  enum RepeatedFieldComparison {
+    AS_LIST,     // Repeated fields are compared in order.  Differing values at
+                 // the same index are reported using ReportModified().  If the
+                 // repeated fields have different numbers of elements, the
+                 // unpaired elements are reported using ReportAdded() or
+                 // ReportDeleted().
+    AS_SET,      // Treat all the repeated fields as sets by default.
+                 // See TreatAsSet(), as below.
+  };
+
+  // The elements of the given repeated field will be treated as a set for
+  // diffing purposes, so different orderings of the same elements will be
+  // considered equal.  Elements which are present on both sides of the
+  // comparison but which have changed position will be reported with
+  // ReportMoved().  Elements which only exist on one side or the other are
+  // reported with ReportAdded() and ReportDeleted() regardless of their
+  // positions.  ReportModified() is never used for this repeated field.  If
+  // the only differences between the compared messages is that some fields
+  // have been moved, then the comparison returns true.
+  //
+  // If the scope of comparison is set to PARTIAL, then in addition to what's
+  // above, extra values added to repeated fields of the second message will
+  // not cause the comparison to fail.
+  //
+  // Note that set comparison is currently O(k * n^2) (where n is the total
+  // number of elements, and k is the average size of each element). In theory
+  // it could be made O(n * k) with a more complex hashing implementation. Feel
+  // free to contribute one if the current implementation is too slow for you.
+  // If partial matching is also enabled, the time complexity will be O(k * n^2
+  // + n^3) in which n^3 is the time complexity of the maximum matching
+  // algorithm.
+  //
+  // REQUIRES:  field->is_repeated() and field not registered with TreatAsList
+  void TreatAsSet(const FieldDescriptor* field);
+
+  // The elements of the given repeated field will be treated as a list for
+  // diffing purposes, so different orderings of the same elements will NOT be
+  // considered equal.
+  //
+  // REQUIRED: field->is_repeated() and field not registered with TreatAsSet
+  void TreatAsList(const FieldDescriptor* field);
+
+  // The elements of the given repeated field will be treated as a map for
+  // diffing purposes, with |key| being the map key.  Thus, elements with the
+  // same key will be compared even if they do not appear at the same index.
+  // Differences are reported similarly to TreatAsSet(), except that
+  // ReportModified() is used to report elements with the same key but
+  // different values.  Note that if an element is both moved and modified,
+  // only ReportModified() will be called.  As with TreatAsSet, if the only
+  // differences between the compared messages is that some fields have been
+  // moved, then the comparison returns true. See TreatAsSet for notes on
+  // performance.
+  //
+  // REQUIRES:  field->is_repeated()
+  // REQUIRES:  field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+  // REQUIRES:  key->containing_type() == field->message_type()
+  void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
+  // Same as TreatAsMap except that this method will use multiple fields as
+  // the key in comparison. All specified fields in 'key_fields' should be
+  // present in the compared elements. Two elements will be treated as having
+  // the same key iff they have the same value for every specified field. There
+  // are two steps in the comparison process. The first one is key matching.
+  // Every element from one message will be compared to every element from
+  // the other message. Only fields in 'key_fields' are compared in this step
+  // to decide if two elements have the same key. The second step is value
+  // comparison. Those pairs of elements with the same key (with equal value
+  // for every field in 'key_fields') will be compared in this step.
+  // Time complexity of the first step is O(s * m * n ^ 2) where s is the
+  // average size of the fields specified in 'key_fields', m is the number of
+  // fields in 'key_fields' and n is the number of elements. If partial
+  // matching is enabled, an extra O(n^3) will be incured by the maximum
+  // matching algorithm. The second step is O(k * n) where k is the average
+  // size of each element.
+  void TreatAsMapWithMultipleFieldsAsKey(
+      const FieldDescriptor* field,
+      const vector<const FieldDescriptor*>& key_fields);
+  // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
+  // do not necessarily need to be a direct subfield. Each element in
+  // key_field_paths indicate a path from the message being compared, listing
+  // successive subfield to reach the key field.
+  //
+  // REQUIRES:
+  //   for key_field_path in key_field_paths:
+  //     key_field_path[0]->containing_type() == field->message_type()
+  //     for i in [0, key_field_path.size() - 1):
+  //       key_field_path[i+1]->containing_type() ==
+  //           key_field_path[i]->message_type()
+  //       key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+  //       !key_field_path[i]->is_repeated()
+  void TreatAsMapWithMultipleFieldPathsAsKey(
+      const FieldDescriptor* field,
+      const vector<vector<const FieldDescriptor*> >& key_field_paths);
+
+  // Uses a custom MapKeyComparator to determine if two elements have the same
+  // key when comparing a repeated field as a map.
+  // The caller is responsible to delete the key_comparator.
+  // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
+  // first key matching step. Rather than comparing some specified fields, it
+  // will invoke the IsMatch method of the given 'key_comparator' to decide if
+  // two elements have the same key.
+  void TreatAsMapUsingKeyComparator(
+      const FieldDescriptor* field,
+      const MapKeyComparator* key_comparator);
+
+  // Add a custom ignore criteria that is evaluated in addition to the
+  // ignored fields added with IgnoreField.
+  // Takes ownership of ignore_criteria.
+  void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
+
+  // Indicates that any field with the given descriptor should be
+  // ignored for the purposes of comparing two messages. This applies
+  // to fields nested in the message structure as well as top level
+  // ones. When the MessageDifferencer encounters an ignored field,
+  // ReportIgnored is called on the reporter, if one is specified.
+  //
+  // The only place where the field's 'ignored' status is not applied is when
+  // it is being used as a key in a field passed to TreatAsMap or is one of
+  // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
+  // In this case it is compared in key matching but after that it's ignored
+  // in value comparison.
+  void IgnoreField(const FieldDescriptor* field);
+
+  // Sets the field comparator used to determine differences between protocol
+  // buffer fields. By default it's set to a DefaultFieldComparator instance.
+  // MessageDifferencer doesn't take ownership over the passed object.
+  // Note that this method must be called before Compare for the comparator to
+  // be used.
+  void set_field_comparator(FieldComparator* comparator);
+
+  // DEPRECATED. Pass a DefaultFieldComparator instance instead.
+  // Sets the fraction and margin for the float comparison of a given field.
+  // Uses MathUtil::WithinFractionOrMargin to compare the values.
+  // NOTE: this method does nothing if differencer's field comparator has been
+  //       set to a custom object.
+  //
+  // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
+  //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
+  // REQUIRES: float_comparison_ == APPROXIMATE
+  void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
+                            double margin);
+
+  // Sets the type of comparison (as defined in the MessageFieldComparison
+  // enumeration above) that is used by this differencer when determining how
+  // to compare fields in messages.
+  void set_message_field_comparison(MessageFieldComparison comparison);
+
+  // Tells the differencer whether or not to report matches. This method must
+  // be called before Compare. The default for a new differencer is false.
+  void set_report_matches(bool report_matches) {
+    report_matches_ = report_matches;
+  }
+
+  // Sets the scope of the comparison (as defined in the Scope enumeration
+  // above) that is used by this differencer when determining which fields to
+  // compare between the messages.
+  void set_scope(Scope scope);
+
+  // Returns the current scope used by this differencer.
+  Scope scope();
+
+  // DEPRECATED. Pass a DefaultFieldComparator instance instead.
+  // Sets the type of comparison (as defined in the FloatComparison enumeration
+  // above) that is used by this differencer when comparing float (and double)
+  // fields in messages.
+  // NOTE: this method does nothing if differencer's field comparator has been
+  //       set to a custom object.
+  void set_float_comparison(FloatComparison comparison);
+
+  // Sets the type of comparison for repeated field (as defined in the
+  // RepeatedFieldComparison enumeration above) that is used by this
+  // differencer when compare repeated fields in messages.
+  void set_repeated_field_comparison(RepeatedFieldComparison comparison);
+
+  // Compares the two specified messages, returning true if they are the same,
+  // false otherwise. If this method returns false, any changes between the
+  // two messages will be reported if a Reporter was specified via
+  // ReportDifferencesTo (see also ReportDifferencesToString).
+  //
+  // This method REQUIRES that the two messages have the same
+  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+  bool Compare(const Message& message1, const Message& message2);
+
+  // Same as above, except comparing only the list of fields specified by the
+  // two vectors of FieldDescriptors.
+  bool CompareWithFields(const Message& message1, const Message& message2,
+                         const vector<const FieldDescriptor*>& message1_fields,
+                         const vector<const FieldDescriptor*>& message2_fields);
+
+  // Automatically creates a reporter that will output the differences
+  // found (if any) to the specified output string pointer. Note that this
+  // method must be called before Compare.
+  void ReportDifferencesToString(string* output);
+
+  // Tells the MessageDifferencer to report differences via the specified
+  // reporter. Note that this method must be called before Compare for
+  // the reporter to be used. It is the responsibility of the caller to delete
+  // this object.
+  // If the provided pointer equals NULL, the MessageDifferencer stops reporting
+  // differences to any previously set reporters or output strings.
+  void ReportDifferencesTo(Reporter* reporter);
+
+  // An implementation of the MessageDifferencer Reporter that outputs
+  // any differences found in human-readable form to the supplied
+  // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
+  // *must* be '$'.
+  class LIBPROTOBUF_EXPORT StreamReporter : public Reporter {
+   public:
+    explicit StreamReporter(io::ZeroCopyOutputStream* output);
+    explicit StreamReporter(io::Printer* printer);  // delimiter '$'
+    virtual ~StreamReporter();
+
+    // When set to true, the stream reporter will also output aggregates nodes
+    // (i.e. messages and groups) whose subfields have been modified. When
+    // false, will only report the individual subfields. Defaults to false.
+    void set_report_modified_aggregates(bool report) {
+      report_modified_aggregates_ = report;
+    }
+
+    // The following are implementations of the methods described above.
+    virtual void ReportAdded(const Message& message1, const Message& message2,
+                             const vector<SpecificField>& field_path);
+
+    virtual void ReportDeleted(const Message& message1,
+                               const Message& message2,
+                               const vector<SpecificField>& field_path);
+
+    virtual void ReportModified(const Message& message1,
+                                const Message& message2,
+                                const vector<SpecificField>& field_path);
+
+    virtual void ReportMoved(const Message& message1,
+                             const Message& message2,
+                             const vector<SpecificField>& field_path);
+
+    virtual void ReportMatched(const Message& message1,
+                               const Message& message2,
+                               const vector<SpecificField>& field_path);
+
+    virtual void ReportIgnored(const Message& message1,
+                               const Message& message2,
+                               const vector<SpecificField>& field_path);
+
+    virtual void ReportUnknownFieldIgnored(
+        const Message& message1, const Message& message2,
+        const vector<SpecificField>& field_path);
+
+   protected:
+    // Prints the specified path of fields to the buffer.
+    virtual void PrintPath(const vector<SpecificField>& field_path,
+                           bool left_side);
+
+    // Prints the value of fields to the buffer.  left_side is true if the
+    // given message is from the left side of the comparison, false if it
+    // was the right.  This is relevant only to decide whether to follow
+    // unknown_field_index1 or unknown_field_index2 when an unknown field
+    // is encountered in field_path.
+    virtual void PrintValue(const Message& message,
+                            const vector<SpecificField>& field_path,
+                            bool left_side);
+
+    // Prints the specified path of unknown fields to the buffer.
+    virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
+
+    // Just print a string
+    void Print(const string& str);
+
+   private:
+    io::Printer* printer_;
+    bool delete_printer_;
+    bool report_modified_aggregates_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
+  };
+
+ private:
+  // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
+  // Implementation of this class needs to do field value comparison which
+  // relies on some private methods of MessageDifferencer. That's why this
+  // class is declared as a nested class of MessageDifferencer.
+  class MultipleFieldsMapKeyComparator;
+  // Returns true if field1's number() is less than field2's.
+  static bool FieldBefore(const FieldDescriptor* field1,
+                          const FieldDescriptor* field2);
+
+  // Combine the two lists of fields into the combined_fields output vector.
+  // All fields present in both lists will always be included in the combined
+  // list.  Fields only present in one of the lists will only appear in the
+  // combined list if the corresponding fields_scope option is set to FULL.
+  void CombineFields(const vector<const FieldDescriptor*>& fields1,
+                     Scope fields1_scope,
+                     const vector<const FieldDescriptor*>& fields2,
+                     Scope fields2_scope,
+                     vector<const FieldDescriptor*>* combined_fields);
+
+  // Internal version of the Compare method which performs the actual
+  // comparison. The parent_fields vector is a vector containing field
+  // descriptors of all fields accessed to get to this comparison operation
+  // (i.e. if the current message is an embedded message, the parent_fields
+  // vector will contain the field that has this embedded message).
+  bool Compare(const Message& message1, const Message& message2,
+               vector<SpecificField>* parent_fields);
+
+  // Compares all the unknown fields in two messages.
+  bool CompareUnknownFields(const Message& message1, const Message& message2,
+                            const google::protobuf::UnknownFieldSet&,
+                            const google::protobuf::UnknownFieldSet&,
+                            vector<SpecificField>* parent_fields);
+
+  // Compares the specified messages for the requested field lists. The field
+  // lists are modified depending on comparison settings, and then passed to
+  // CompareWithFieldsInternal.
+  bool CompareRequestedFieldsUsingSettings(
+      const Message& message1, const Message& message2,
+      const vector<const FieldDescriptor*>& message1_fields,
+      const vector<const FieldDescriptor*>& message2_fields,
+      vector<SpecificField>* parent_fields);
+
+  // Compares the specified messages with the specified field lists.
+  bool CompareWithFieldsInternal(
+      const Message& message1, const Message& message2,
+      const vector<const FieldDescriptor*>& message1_fields,
+      const vector<const FieldDescriptor*>& message2_fields,
+      vector<SpecificField>* parent_fields);
+
+  // Compares the repeated fields, and report the error.
+  bool CompareRepeatedField(const Message& message1, const Message& message2,
+                            const FieldDescriptor* field,
+                            vector<SpecificField>* parent_fields);
+
+  // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
+  bool CompareFieldValue(const Message& message1,
+                         const Message& message2,
+                         const FieldDescriptor* field,
+                         int index1,
+                         int index2);
+
+  // Compares the specified field on the two messages, returning
+  // true if they are the same, false otherwise. For repeated fields,
+  // this method only compares the value in the specified index. This method
+  // uses Compare functions to recurse into submessages.
+  // The parent_fields vector is used in calls to a Reporter instance calls.
+  // It can be NULL, in which case the MessageDifferencer will create new
+  // list of parent messages if it needs to recursively compare the given field.
+  // To avoid confusing users you should not set it to NULL unless you modified
+  // Reporter to handle the change of parent_fields correctly.
+  bool CompareFieldValueUsingParentFields(const Message& message1,
+                                          const Message& message2,
+                                          const FieldDescriptor* field,
+                                          int index1,
+                                          int index2,
+                                          vector<SpecificField>* parent_fields);
+
+  // Compares the specified field on the two messages, returning comparison
+  // result, as returned by appropriate FieldComparator.
+  FieldComparator::ComparisonResult GetFieldComparisonResult(
+      const Message& message1, const Message& message2,
+      const FieldDescriptor* field, int index1, int index2,
+      const FieldContext* field_context);
+
+  // Check if the two elements in the repeated field are match to each other.
+  // if the key_comprator is NULL, this function returns true when the two
+  // elements are equal.
+  bool IsMatch(const FieldDescriptor* repeated_field,
+               const MapKeyComparator* key_comparator,
+               const Message* message1, const Message* message2,
+               const vector<SpecificField>& parent_fields,
+               int index1, int index2);
+
+  // Returns true when this repeated field has been configured to be treated
+  // as a set.
+  bool IsTreatedAsSet(const FieldDescriptor* field);
+
+  // Returns true when this repeated field is to be compared as a subset, ie.
+  // has been configured to be treated as a set or map and scope is set to
+  // PARTIAL.
+  bool IsTreatedAsSubset(const FieldDescriptor* field);
+
+  // Returns true if this field is to be ignored when this
+  // MessageDifferencer compares messages.
+  bool IsIgnored(
+      const Message& message1,
+      const Message& message2,
+      const FieldDescriptor* field,
+      const vector<SpecificField>& parent_fields);
+
+  // Returns true if this unknown field is to be ignored when this
+  // MessageDifferencer compares messages.
+  bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
+                             const SpecificField& field,
+                             const vector<SpecificField>& parent_fields);
+
+  // Returns MapKeyComparator* when this field has been configured to
+  // be treated as a map.  If not, returns NULL.
+  const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
+
+  // Attempts to match indices of a repeated field, so that the contained values
+  // match. Clears output vectors and sets their values to indices of paired
+  // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
+  // and match_list2[1] == 0. The unmatched indices are indicated by -1.
+  // This method returns false if the match failed. However, it doesn't mean
+  // that the comparison succeeds when this method returns true (you need to
+  // double-check in this case).
+  bool MatchRepeatedFieldIndices(const Message& message1,
+                                 const Message& message2,
+                                 const FieldDescriptor* repeated_field,
+                                 const vector<SpecificField>& parent_fields,
+                                 vector<int>* match_list1,
+                                 vector<int>* match_list2);
+
+  // If "any" is of type google.protobuf.Any, extract its payload using
+  // DynamicMessageFactory and store in "data".
+  bool UnpackAny(const Message& any, google::protobuf::scoped_ptr<Message>* data);
+
+  // Checks if index is equal to new_index in all the specific fields.
+  static bool CheckPathChanged(const vector<SpecificField>& parent_fields);
+
+  // Defines a map between field descriptors and their MapKeyComparators.
+  // Used for repeated fields when they are configured as TreatAsMap.
+  typedef map<const FieldDescriptor*,
+              const MapKeyComparator*> FieldKeyComparatorMap;
+
+  // Defines a set to store field descriptors.  Used for repeated fields when
+  // they are configured as TreatAsSet.
+  typedef set<const FieldDescriptor*> FieldSet;
+
+  Reporter* reporter_;
+  DefaultFieldComparator default_field_comparator_;
+  FieldComparator* field_comparator_;
+  MessageFieldComparison message_field_comparison_;
+  Scope scope_;
+  RepeatedFieldComparison repeated_field_comparison_;
+
+  FieldSet set_fields_;
+  FieldSet list_fields_;
+  // Keeps track of MapKeyComparators that are created within
+  // MessageDifferencer. These MapKeyComparators should be deleted
+  // before MessageDifferencer is destroyed.
+  // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
+  // store the supplied FieldDescriptors directly. Instead, a new
+  // MapKeyComparator is created for comparison purpose.
+  vector<MapKeyComparator*> owned_key_comparators_;
+  FieldKeyComparatorMap map_field_key_comparator_;
+  vector<IgnoreCriteria*> ignore_criteria_;
+
+  FieldSet ignored_fields_;
+
+  bool compare_unknown_fields_;
+  bool report_matches_;
+
+  string* output_string_;
+
+  google::protobuf::scoped_ptr<DynamicMessageFactory> dynamic_message_factory_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
+};
+
+// This class provides extra information to the FieldComparator::Compare
+// function.
+class LIBPROTOBUF_EXPORT FieldContext {
+ public:
+  explicit FieldContext(
+      vector<MessageDifferencer::SpecificField>* parent_fields)
+      : parent_fields_(parent_fields) {}
+
+  vector<MessageDifferencer::SpecificField>* parent_fields() const {
+    return parent_fields_;
+  }
+
+ private:
+  vector<MessageDifferencer::SpecificField>* parent_fields_;
+};
+
+}
+}
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.cc
new file mode 100755
index 0000000..a867c88
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.cc
@@ -0,0 +1,3151 @@
+// 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.
+
+// Author: jschorr@google.com (Joseph Schorr)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// TODO(ksroka): Move some of these tests to field_comparator_test.cc.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/util/message_differencer_unittest.pb.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/any_test.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/test_util.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+
+const FieldDescriptor* GetFieldDescriptor(
+    const Message& message, const string& field_name) {
+  vector<string> field_path =
+      Split(field_name, ".", true);
+  const Descriptor* descriptor = message.GetDescriptor();
+  const FieldDescriptor* field = NULL;
+  for (int i = 0; i < field_path.size(); i++) {
+    field = descriptor->FindFieldByName(field_path[i]);
+    descriptor = field->message_type();
+  }
+  return field;
+}
+
+void ExpectEqualsWithDifferencer(util::MessageDifferencer* differencer,
+                                 const Message& msg1,
+                                 const Message& msg2) {
+  differencer->set_scope(util::MessageDifferencer::FULL);
+  EXPECT_TRUE(differencer->Compare(msg1, msg2));
+
+  differencer->set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer->Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicEqualityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicInequalityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldInequalityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.add_repeated_int32(-1);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, MapFieldEqualityTest) {
+  // Create the testing protos
+  unittest::TestMap msg1;
+  unittest::TestMap msg2;
+
+  MapReflectionTester tester(unittest::TestMap::descriptor());
+  tester.SetMapFieldsViaReflection(&msg1);
+  tester.SetMapFieldsViaReflection(&msg2);
+  tester.SwapMapsViaReflection(&msg1);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialEqualityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEqualityTestExtraField) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.clear_optional_int32();
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEqualityTestSkipRequiredField) {
+  // Create the testing protos
+  unittest::TestRequired msg1;
+  unittest::TestRequired msg2;
+
+  msg1.set_a(401);
+  msg2.set_a(401);
+  msg2.set_b(402);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequalityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialInequalityMissingFieldTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg2.clear_optional_int32();
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldPartialInequalityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.add_repeated_int32(-1);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicEquivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, EquivalencyNotEqualTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.clear_optional_int32();
+  msg2.set_optional_int32(0);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+  EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicInequivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicEquivalencyNonSetTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicInequivalencyNonSetTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicPartialEquivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyNotEqualTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.set_optional_int32(0);
+  msg2.clear_optional_int32();
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyTestExtraField) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.clear_optional_int32();
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyTestSkipRequiredField) {
+  // Create the testing protos
+  unittest::TestRequired msg1;
+  unittest::TestRequired msg2;
+
+  msg1.set_a(401);
+  msg2.set_a(401);
+  msg2.set_b(402);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialEquivalencyNonSetTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequivalencyNonSetTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  msg1.set_optional_int32(-1);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateEqualityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateModifiedEqualityTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  const float v1 = 2.300005f;
+  const float v2 = 2.300006f;
+  msg1.set_optional_float(v1);
+  msg2.set_optional_float(v2);
+
+  // Compare
+  ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2;
+  ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2;
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateEquivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateModifiedEquivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Modify the approximateness requirement
+  const float v1 = 2.300005f;
+  const float v2 = 2.300006f;
+  msg1.set_optional_float(v1);
+  msg2.set_optional_float(v2);
+
+  // Compare
+  ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2;
+  ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2;
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                msg2));
+
+  // Modify the equivalency requirement too
+  msg1.clear_optional_int32();
+  msg2.set_optional_int32(0);
+
+  // Compare. Now should only pass on ApproximatelyEquivalent
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+  EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+  EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateInequivalencyTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Should fail on equivalency
+  msg1.set_optional_int32(-1);
+  EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                 msg2));
+
+  // Make these fields the same again.
+  msg1.set_optional_int32(0);
+  msg2.set_optional_int32(0);
+  EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                msg2));
+
+  // Should fail on approximate equality check
+  const float v1 = 2.3f;
+  const float v2 = 9.3f;
+  msg1.set_optional_float(v1);
+  msg2.set_optional_float(v2);
+  EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+                                                                 msg2));
+}
+
+TEST(MessageDifferencerTest, WithinFractionOrMarginFloatTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Should fail on approximate equality check
+  const float v1 = 100.0f;
+  const float v2 = 109.9f;
+  msg1.set_optional_float(v1);
+  msg2.set_optional_float(v2);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  const FieldDescriptor* fd =
+      msg1.GetDescriptor()->FindFieldByName("optional_float");
+
+  // Set float comparison to exact, margin and fraction value should not matter.
+  differencer.set_float_comparison(util::MessageDifferencer::EXACT);
+  // Set margin for float comparison.
+  differencer.SetFractionAndMargin(fd, 0.0, 10.0);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Margin and fraction float comparison is activated when float comparison is
+  // set to approximate.
+  differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Test out float comparison with fraction.
+  differencer.SetFractionAndMargin(fd, 0.2, 0.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Should fail since the fraction is smaller than error.
+  differencer.SetFractionAndMargin(fd, 0.01, 0.0);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Should pass if either fraction or margin are satisfied.
+  differencer.SetFractionAndMargin(fd, 0.01, 10.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Make sure that the margin and fraction only affects the field that it was
+  // set for.
+  msg1.set_default_float(v1);
+  msg2.set_default_float(v2);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  msg1.set_default_float(v1);
+  msg2.set_default_float(v1);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, WithinFractionOrMarginDoubleTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Should fail on approximate equality check
+  const double v1 = 100.0;
+  const double v2 = 109.9;
+  msg1.set_optional_double(v1);
+  msg2.set_optional_double(v2);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Set comparison to exact, margin and fraction value should not matter.
+  differencer.set_float_comparison(util::MessageDifferencer::EXACT);
+  // Set margin for float comparison.
+  const FieldDescriptor* fd =
+      msg1.GetDescriptor()->FindFieldByName("optional_double");
+  differencer.SetFractionAndMargin(fd, 0.0, 10.0);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Margin and fraction comparison is activated when float comparison is
+  // set to approximate.
+  differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Test out comparison with fraction.
+  differencer.SetFractionAndMargin(fd, 0.2, 0.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Should fail since the fraction is smaller than error.
+  differencer.SetFractionAndMargin(fd, 0.01, 0.0);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Should pass if either fraction or margin are satisfied.
+  differencer.SetFractionAndMargin(fd, 0.01, 10.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Make sure that the margin and fraction only affects the field that it was
+  // set for.
+  msg1.set_default_double(v1);
+  msg2.set_default_double(v2);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  msg1.set_default_double(v1);
+  msg2.set_default_double(v1);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, WithinDefaultFractionOrMarginDoubleTest) {
+  // Create the testing protos
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  // Should fail on approximate equality check
+  const double v1 = 100.0;
+  const double v2 = 109.9;
+  msg1.set_optional_double(v1);
+  msg2.set_optional_double(v2);
+
+  util::MessageDifferencer differencer;
+
+  // Compare
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Set up a custom field comparitor, with a default fraction and margin for
+  // float and double comparison.
+  util::DefaultFieldComparator field_comparitor;
+  field_comparitor.SetDefaultFractionAndMargin(0.0, 10.0);
+  differencer.set_field_comparator(&field_comparitor);
+
+  // Set comparison to exact, margin and fraction value should not matter.
+  field_comparitor.set_float_comparison(util::DefaultFieldComparator::EXACT);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Margin and fraction comparison is activated when float comparison is
+  // set to approximate.
+  field_comparitor.set_float_comparison(
+      util::DefaultFieldComparator::APPROXIMATE);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Test out comparison with fraction.
+  field_comparitor.SetDefaultFractionAndMargin(0.2, 0.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Should fail since the fraction is smaller than error.
+  field_comparitor.SetDefaultFractionAndMargin(0.01, 0.0);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Should pass if either fraction or margin are satisfied.
+  field_comparitor.SetDefaultFractionAndMargin(0.01, 10.0);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Make sure that the default margin and fraction affects all fields
+  msg1.set_default_double(v1);
+  msg2.set_default_double(v2);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicFieldOrderingsTest) {
+  // Create the testing protos
+  unittest::TestFieldOrderings msg1;
+  unittest::TestFieldOrderings msg2;
+
+  TestUtil::SetAllFieldsAndExtensions(&msg1);
+  TestUtil::SetAllFieldsAndExtensions(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicFieldOrderingInequalityTest) {
+  // Create the testing protos
+  unittest::TestFieldOrderings msg1;
+  unittest::TestFieldOrderings msg2;
+
+  TestUtil::SetAllFieldsAndExtensions(&msg1);
+  TestUtil::SetAllFieldsAndExtensions(&msg2);
+
+  msg1.set_my_float(15.00);
+  msg2.set_my_float(16.00);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicExtensionTest) {
+  // Create the testing protos
+  unittest::TestAllExtensions msg1;
+  unittest::TestAllExtensions msg2;
+
+  TestUtil::SetAllExtensions(&msg1);
+  TestUtil::SetAllExtensions(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicExtensionInequalityTest) {
+  // Create the testing protos
+  unittest::TestAllExtensions msg1;
+  unittest::TestAllExtensions msg2;
+
+  TestUtil::SetAllExtensions(&msg1);
+  TestUtil::SetAllExtensions(&msg2);
+
+  msg1.SetExtension(unittest::optional_int32_extension, 101);
+  msg2.SetExtension(unittest::optional_int32_extension, 102);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, OneofTest) {
+  // Create the testing protos
+  unittest::TestOneof2 msg1;
+  unittest::TestOneof2 msg2;
+
+  TestUtil::SetOneof1(&msg1);
+  TestUtil::SetOneof1(&msg2);
+
+  // Compare
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, OneofInequalityTest) {
+  // Create the testing protos
+  unittest::TestOneof2 msg1;
+  unittest::TestOneof2 msg2;
+
+  TestUtil::SetOneof1(&msg1);
+  TestUtil::SetOneof2(&msg2);
+
+  // Compare
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, UnknownFieldPartialEqualTest) {
+  unittest::TestEmptyMessage empty1;
+  unittest::TestEmptyMessage empty2;
+
+  UnknownFieldSet* unknown1 = empty1.mutable_unknown_fields();
+  UnknownFieldSet* unknown2 = empty2.mutable_unknown_fields();
+
+  unknown1->AddVarint(243, 122);
+  unknown1->AddLengthDelimited(245, "abc");
+  unknown1->AddGroup(246)->AddFixed32(248, 1);
+  unknown1->mutable_field(2)->mutable_group()->AddFixed32(248, 2);
+
+  unknown2->AddVarint(243, 122);
+  unknown2->AddLengthDelimited(245, "abc");
+  unknown2->AddGroup(246)->AddFixed32(248, 1);
+  unknown2->mutable_field(2)->mutable_group()->AddFixed32(248, 2);
+
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(empty1, empty2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllTest) {
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  vector<const FieldDescriptor*> fields2;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+  msg2.GetReflection()->ListFields(msg2, &fields2);
+
+  util::MessageDifferencer differencer;
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsInequalityAllTest) {
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+
+  vector<const FieldDescriptor*> fields1;
+  vector<const FieldDescriptor*> fields2;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+  msg2.GetReflection()->ListFields(msg2, &fields2);
+
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEmptyListAlwaysSucceeds) {
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+
+  vector<const FieldDescriptor*> empty_fields;
+
+  util::MessageDifferencer differencer;
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+                                            empty_fields, empty_fields));
+
+  TestUtil::SetAllFields(&msg2);
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+                                            empty_fields, empty_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsCompareWithSelf) {
+  unittest::TestAllTypes msg1;
+  TestUtil::SetAllFields(&msg1);
+
+  vector<const FieldDescriptor*> fields;
+  msg1.GetReflection()->ListFields(msg1, &fields);
+
+  util::MessageDifferencer differencer;
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, fields, fields));
+
+  {
+    // Compare with a subset of fields.
+    vector<const FieldDescriptor*> compare_fields;
+    for (int i = 0; i < fields.size(); ++i) {
+      if (i % 2 == 0) {
+        compare_fields.push_back(fields[i]);
+      }
+    }
+    EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1,
+                                              compare_fields, compare_fields));
+  }
+  {
+    // Specify a different set of fields to compare, even though we're using the
+    // same message. This should fail, since we are explicitly saying that the
+    // set of fields are different.
+    vector<const FieldDescriptor*> compare_fields1;
+    vector<const FieldDescriptor*> compare_fields2;
+    for (int i = 0; i < fields.size(); ++i) {
+      if (i % 2 == 0) {
+        compare_fields1.push_back(fields[i]);
+      } else {
+        compare_fields2.push_back(fields[i]);
+      }
+    }
+    EXPECT_FALSE(differencer.CompareWithFields(
+        msg1, msg1, compare_fields1, compare_fields2));
+  }
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllShuffledTest) {
+  // This is a public function, so make sure there are no assumptions about the
+  // list of fields. Randomly shuffle them to make sure that they are properly
+  // ordered for comparison.
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  vector<const FieldDescriptor*> fields2;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+  msg2.GetReflection()->ListFields(msg2, &fields2);
+
+  std::random_shuffle(fields1.begin(), fields1.end());
+  std::random_shuffle(fields2.begin(), fields2.end());
+
+  util::MessageDifferencer differencer;
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsSubsetEqualityTest) {
+  // Specify a set of fields to compare. All the fields are equal.
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+
+  vector<const FieldDescriptor*> compare_fields;
+  // Only compare the field descriptors with even indices.
+  for (int i = 0; i < fields1.size(); ++i) {
+    if (i % 2 == 0) {
+      compare_fields.push_back(fields1[i]);
+    }
+  }
+
+  util::MessageDifferencer differencer;
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+                                            compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest,
+     SpecifiedFieldsSubsetIgnoresOtherFieldDifferencesTest) {
+  // Specify a set of fields to compare, but clear all the other fields in one
+  // of the messages. This should fail a regular compare, but CompareWithFields
+  // should succeed.
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  const Reflection* reflection = msg1.GetReflection();
+  reflection->ListFields(msg1, &fields1);
+
+  vector<const FieldDescriptor*> compare_fields;
+  // Only compare the field descriptors with even indices.
+  for (int i = 0; i < fields1.size(); ++i) {
+    if (i % 2 == 0) {
+      compare_fields.push_back(fields1[i]);
+    } else {
+      reflection->ClearField(&msg2, fields1[i]);
+    }
+  }
+
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+                                            compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsDetectsDifferencesTest) {
+  // Change all of the repeated fields in one of the messages, and use only
+  // those fields for comparison.
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+  TestUtil::ModifyRepeatedFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+
+  vector<const FieldDescriptor*> compare_fields;
+  // Only compare the repeated field descriptors.
+  for (int i = 0; i < fields1.size(); ++i) {
+    if (fields1[i]->is_repeated()) {
+      compare_fields.push_back(fields1[i]);
+    }
+  }
+
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2,
+                                             compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEquivalenceAllTest) {
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+
+  TestUtil::SetAllFields(&msg1);
+  TestUtil::SetAllFields(&msg2);
+
+  vector<const FieldDescriptor*> fields1;
+  vector<const FieldDescriptor*> fields2;
+  msg1.GetReflection()->ListFields(msg1, &fields1);
+  msg2.GetReflection()->ListFields(msg2, &fields2);
+
+  util::MessageDifferencer differencer;
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest,
+     SpecifiedFieldsEquivalenceIgnoresOtherFieldDifferencesTest) {
+  unittest::TestAllTypes msg1;
+  unittest::TestAllTypes msg2;
+  const Descriptor* desc = msg1.GetDescriptor();
+
+  const FieldDescriptor* optional_int32_desc =
+      desc->FindFieldByName("optional_int32");
+  const FieldDescriptor* optional_int64_desc =
+      desc->FindFieldByName("optional_int64");
+  const FieldDescriptor* default_int64_desc =
+      desc->FindFieldByName("default_int64");
+  ASSERT_TRUE(optional_int32_desc != NULL);
+  ASSERT_TRUE(optional_int64_desc != NULL);
+  ASSERT_TRUE(default_int64_desc != NULL);
+  msg1.set_optional_int32(0);
+  msg2.set_optional_int64(0);
+  msg1.set_default_int64(default_int64_desc->default_value_int64());
+
+  // Set a field to a non-default value so we know that field selection is
+  // actually doing something.
+  msg2.set_optional_uint64(23);
+
+  vector<const FieldDescriptor*> fields1;
+  vector<const FieldDescriptor*> fields2;
+  fields1.push_back(optional_int32_desc);
+  fields1.push_back(default_int64_desc);
+
+  fields2.push_back(optional_int64_desc);
+
+  util::MessageDifferencer differencer;
+  EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+  differencer.set_message_field_comparison(
+      util::MessageDifferencer::EQUIVALENT);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_SetOfSet) {
+  // Create the testing protos
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->add_ra(1); item->add_ra(2); item->add_ra(3);
+  item = msg1.add_item();
+  item->add_ra(5); item->add_ra(6);
+  item = msg1.add_item();
+  item->add_ra(1); item->add_ra(3);
+  item = msg1.add_item();
+  item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+  item = msg2.add_item();
+  item->add_ra(6); item->add_ra(5);
+  item = msg2.add_item();
+  item->add_ra(6); item->add_ra(8); item->add_ra(7);
+  item = msg2.add_item();
+  item->add_ra(1); item->add_ra(3);
+  item = msg2.add_item();
+  item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Combination) {
+  // Create the testing protos
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, with key = "a"
+  // Treat "item.ra" also as Set
+  // Treat "rv" as Set
+  // Treat "rw" as List
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->set_a(3);
+  item->add_ra(1); item->add_ra(2); item->add_ra(3);
+  item = msg1.add_item();
+  item->set_a(4);
+  item->add_ra(5); item->add_ra(6);
+  item = msg1.add_item();
+  item->set_a(1);
+  item->add_ra(1); item->add_ra(3);
+  item = msg1.add_item();
+  item->set_a(2);
+  item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+  item = msg2.add_item();
+  item->set_a(4);
+  item->add_ra(6); item->add_ra(5);
+  item = msg2.add_item();
+  item->set_a(2);
+  item->add_ra(6); item->add_ra(8); item->add_ra(7);
+  item = msg2.add_item();
+  item->set_a(1);
+  item->add_ra(1); item->add_ra(3);
+  item = msg2.add_item();
+  item->set_a(3);
+  item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+  msg1.add_rv(3);
+  msg1.add_rv(4);
+  msg1.add_rv(7);
+  msg1.add_rv(0);
+  msg2.add_rv(4);
+  msg2.add_rv(3);
+  msg2.add_rv(0);
+  msg2.add_rv(7);
+
+  msg1.add_rw("nothing"); msg2.add_rw("nothing");
+  msg1.add_rw("should"); msg2.add_rw("should");
+  msg1.add_rw("change"); msg2.add_rw("change");
+
+  // Compare
+  util::MessageDifferencer differencer1;
+  differencer1.TreatAsMap(msg1.GetDescriptor()->FindFieldByName("item"),
+                          item->GetDescriptor()->FindFieldByName("a"));
+  differencer1.TreatAsSet(msg1.GetDescriptor()->FindFieldByName("rv"));
+  differencer1.TreatAsSet(item->GetDescriptor()->FindFieldByName("ra"));
+  EXPECT_TRUE(differencer1.Compare(msg1, msg2));
+
+  util::MessageDifferencer differencer2;
+  differencer2.TreatAsMap(msg1.GetDescriptor()->FindFieldByName("item"),
+                          item->GetDescriptor()->FindFieldByName("a"));
+  differencer2.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+  differencer2.TreatAsList(msg1.GetDescriptor()->FindFieldByName("rw"));
+  EXPECT_TRUE(differencer2.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_Partial) {
+  protobuf_unittest::TestDiffMessage msg1;
+  // message msg1 {
+  //   item { a: 1; b: "11" }
+  // }
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->set_a(1);
+  item->set_b("11");
+
+  protobuf_unittest::TestDiffMessage msg2;
+  // message msg2 {
+  //   item { a: 2; b: "22" }
+  //   item { a: 1; b: "11" }
+  // }
+  item = msg2.add_item();
+  item->set_a(2);
+  item->set_b("22");
+  item = msg2.add_item();
+  item->set_a(1);
+  item->set_b("11");
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.TreatAsMap(GetFieldDescriptor(msg1, "item"),
+                         GetFieldDescriptor(msg1, "item.a"));
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Duplicates) {
+  protobuf_unittest::TestDiffMessage a, b, c;
+  // message a: {
+  //   rv: 0
+  //   rv: 1
+  //   rv: 0
+  // }
+  a.add_rv(0);
+  a.add_rv(1);
+  a.add_rv(0);
+  // message b: {
+  //   rv: 0
+  //   rv: 0
+  //   rv: 1
+  // }
+  b.add_rv(0);
+  b.add_rv(0);
+  b.add_rv(1);
+  // message c: {
+  //   rv: 0
+  //   rv: 1
+  // }
+  c.add_rv(0);
+  c.add_rv(1);
+  util::MessageDifferencer differencer;
+  differencer.TreatAsSet(GetFieldDescriptor(a, "rv"));
+  EXPECT_TRUE(differencer.Compare(b, a));
+  EXPECT_FALSE(differencer.Compare(c, a));
+
+  util::MessageDifferencer differencer1;
+  differencer1.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+  EXPECT_TRUE(differencer1.Compare(b, a));
+  EXPECT_FALSE(differencer1.Compare(c, a));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_PartialSimple) {
+  protobuf_unittest::TestDiffMessage a, b, c;
+  // message a: {
+  //   rm { c: 1 }
+  //   rm { c: 0 }
+  // }
+  a.add_rm()->set_c(1);
+  a.add_rm()->set_c(0);
+  // message b: {
+  //   rm { c: 1 }
+  //   rm {}
+  // }
+  b.add_rm()->set_c(1);
+  b.add_rm();
+  // message c: {
+  //   rm {}
+  //   rm { c: 1 }
+  // }
+  c.add_rm();
+  c.add_rm()->set_c(1);
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  differencer.TreatAsSet(GetFieldDescriptor(a, "rm"));
+  EXPECT_TRUE(differencer.Compare(b, a));
+  EXPECT_TRUE(differencer.Compare(c, a));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Partial) {
+  protobuf_unittest::TestDiffMessage msg1, msg2;
+  // message msg1: {
+  //   rm { a: 1 }
+  //   rm { b: 2 }
+  //   rm { c: 3 }
+  // }
+  msg1.add_rm()->set_a(1);
+  msg1.add_rm()->set_b(2);
+  msg1.add_rm()->set_c(3);
+  // message msg2: {
+  //   rm { a: 1; c: 3 }
+  //   rm { b: 2; c: 3 }
+  //   rm { b: 2 }
+  // }
+  protobuf_unittest::TestField* field = msg2.add_rm();
+  field->set_a(1);
+  field->set_c(3);
+  field = msg2.add_rm();
+  field->set_b(2);
+  field->set_c(3);
+  field = msg2.add_rm();
+  field->set_b(2);
+
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  differencer.TreatAsSet(GetFieldDescriptor(msg1, "rm"));
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldsAsKey) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, with key = ("a", "ra")
+  // Treat "item.ra" as Set
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  // key => value: (1, {2, 3}) => "a"
+  item->set_a(1);
+  item->add_ra(2);
+  item->add_ra(3);
+  item->set_b("a");
+  item = msg1.add_item();
+  // key => value: (2, {1, 3}) => "b"
+  item->set_a(2);
+  item->add_ra(1);
+  item->add_ra(3);
+  item->set_b("b");
+  item = msg1.add_item();
+  // key => value: (1, {1, 3}) => "c"
+  item->set_a(1);
+  item->add_ra(1);
+  item->add_ra(3);
+  item->set_b("c");
+
+  item = msg2.add_item();
+  // key => value: (1, {1, 3}) => "c"
+  item->set_a(1);
+  item->add_ra(3);
+  item->add_ra(1);
+  item->set_b("c");
+  item = msg2.add_item();
+  // key => value: (1, {2, 3}) => "a"
+  item->set_a(1);
+  item->add_ra(3);
+  item->add_ra(2);
+  item->set_b("a");
+  item = msg2.add_item();
+  // key => value: (2, {1, 3}) => "b"
+  item->set_a(2);
+  item->add_ra(3);
+  item->add_ra(1);
+  item->set_b("b");
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.ra"));
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  vector<const FieldDescriptor*> key_fields;
+  key_fields.push_back(GetFieldDescriptor(msg1, "item.a"));
+  key_fields.push_back(GetFieldDescriptor(msg1, "item.ra"));
+  differencer.TreatAsMapWithMultipleFieldsAsKey(
+      GetFieldDescriptor(msg1, "item"), key_fields);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Introduce some differences.
+  msg1.clear_item();
+  msg2.clear_item();
+  item = msg1.add_item();
+  item->set_a(4);
+  item->add_ra(5);
+  item->add_ra(6);
+  item->set_b("hello");
+  item = msg2.add_item();
+  item->set_a(4);
+  item->add_ra(6);
+  item->add_ra(5);
+  item->set_b("world");
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "moved: item[0].ra[0] -> item[0].ra[1] : 5\n"
+      "moved: item[0].ra[1] -> item[0].ra[0] : 6\n"
+      "modified: item[0].b: \"hello\" -> \"world\"\n",
+      output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldPathsAsKey) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, with key = ("m.a", "m.rc")
+  // Treat "item.m.rc" as Set
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  // key => value: (1, {2, 3}) => "a"
+  item->mutable_m()->set_a(1);
+  item->mutable_m()->add_rc(2);
+  item->mutable_m()->add_rc(3);
+  item->set_b("a");
+  item = msg1.add_item();
+  // key => value: (2, {1, 3}) => "b"
+  item->mutable_m()->set_a(2);
+  item->mutable_m()->add_rc(1);
+  item->mutable_m()->add_rc(3);
+  item->set_b("b");
+  item = msg1.add_item();
+  // key => value: (1, {1, 3}) => "c"
+  item->mutable_m()->set_a(1);
+  item->mutable_m()->add_rc(1);
+  item->mutable_m()->add_rc(3);
+  item->set_b("c");
+
+  item = msg2.add_item();
+  // key => value: (1, {1, 3}) => "c"
+  item->mutable_m()->set_a(1);
+  item->mutable_m()->add_rc(3);
+  item->mutable_m()->add_rc(1);
+  item->set_b("c");
+  item = msg2.add_item();
+  // key => value: (1, {2, 3}) => "a"
+  item->mutable_m()->set_a(1);
+  item->mutable_m()->add_rc(3);
+  item->mutable_m()->add_rc(2);
+  item->set_b("a");
+  item = msg2.add_item();
+  // key => value: (2, {1, 3}) => "b"
+  item->mutable_m()->set_a(2);
+  item->mutable_m()->add_rc(3);
+  item->mutable_m()->add_rc(1);
+  item->set_b("b");
+
+  // Compare
+  util::MessageDifferencer differencer;
+  differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.m.rc"));
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  vector<vector<const FieldDescriptor*> > key_field_paths;
+  vector<const FieldDescriptor*> key_field_path1;
+  key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m"));
+  key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m.a"));
+  vector<const FieldDescriptor*> key_field_path2;
+  key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m"));
+  key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m.rc"));
+  key_field_paths.push_back(key_field_path1);
+  key_field_paths.push_back(key_field_path2);
+  differencer.TreatAsMapWithMultipleFieldPathsAsKey(
+      GetFieldDescriptor(msg1, "item"), key_field_paths);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+  // Introduce some differences.
+  msg1.clear_item();
+  msg2.clear_item();
+  item = msg1.add_item();
+  item->mutable_m()->set_a(4);
+  item->mutable_m()->add_rc(5);
+  item->mutable_m()->add_rc(6);
+  item->set_b("hello");
+  item = msg2.add_item();
+  item->mutable_m()->set_a(4);
+  item->mutable_m()->add_rc(6);
+  item->mutable_m()->add_rc(5);
+  item->set_b("world");
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "modified: item[0].b: \"hello\" -> \"world\"\n"
+      "moved: item[0].m.rc[0] -> item[0].m.rc[1] : 5\n"
+      "moved: item[0].m.rc[1] -> item[0].m.rc[0] : 6\n",
+      output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_IgnoredKeyFields) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, with key = ("a", "ra")
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->set_a(1);
+  item->add_ra(2);
+  item->set_b("hello");
+  item = msg2.add_item();
+  item->set_a(1);
+  item->add_ra(3);
+  item->set_b("world");
+  // Compare
+  util::MessageDifferencer differencer;
+  vector<const FieldDescriptor*> key_fields;
+  key_fields.push_back(GetFieldDescriptor(msg1, "item.a"));
+  key_fields.push_back(GetFieldDescriptor(msg1, "item.ra"));
+  differencer.TreatAsMapWithMultipleFieldsAsKey(
+      GetFieldDescriptor(msg1, "item"), key_fields);
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n"
+      "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n",
+      output);
+  // Ignored fields that are listed as parts of the key are still used
+  // in key comparison, but they're not used in value comparison.
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+  output.clear();
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n"
+      "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n",
+      output);
+  // Ignoring a field in the key is different from treating the left fields
+  // as key. That is:
+  //   (key = ("a", "ra") && ignore "ra") != (key = ("a") && ignore "ra")
+  util::MessageDifferencer differencer2;
+  differencer2.TreatAsMap(GetFieldDescriptor(msg1, "item"),
+                          GetFieldDescriptor(msg1, "item.a"));
+  differencer2.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+  output.clear();
+  differencer2.ReportDifferencesToString(&output);
+  EXPECT_FALSE(differencer2.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "ignored: item[0].ra\n"
+      "modified: item[0].b: \"hello\" -> \"world\"\n",
+      output);
+}
+
+static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"};
+
+class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
+ public:
+  virtual bool IsIgnored(
+      const Message& message1, const Message& message2,
+      const FieldDescriptor* field,
+      const vector<util::MessageDifferencer::SpecificField>& parent_fields) {
+    string name = "";
+    for (int i = 0; i < parent_fields.size(); ++i) {
+      name += parent_fields[i].field->name() + ".";
+    }
+    name += field->name();
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(kIgnoredFields); ++i) {
+      if (name.compare(kIgnoredFields[i]) == 0) {
+        return true;
+      }
+    }
+    return false;
+  }
+};
+
+TEST(MessageDifferencerTest, TreatRepeatedFieldAsSetWithIgnoredFields) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  TextFormat::MergeFromString("rm { a: 11\n b: 12 }", &msg1);
+  TextFormat::MergeFromString("rm { a: 11\n b: 13 }", &msg2);
+  util::MessageDifferencer differ;
+  differ.TreatAsSet(GetFieldDescriptor(msg1, "rm"));
+  differ.AddIgnoreCriteria(new TestIgnorer);
+  EXPECT_TRUE(differ.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, TreatRepeatedFieldAsMapWithIgnoredKeyFields) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 13\n } }", &msg1);
+  TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 14\n } }", &msg2);
+  util::MessageDifferencer differ;
+  differ.TreatAsMap(GetFieldDescriptor(msg1, "rm"),
+                    GetFieldDescriptor(msg1, "rm.m"));
+  differ.AddIgnoreCriteria(new TestIgnorer);
+  EXPECT_TRUE(differ.Compare(msg1, msg2));
+}
+
+// Takes the product of all elements of item.ra as the key for key comparison.
+class ValueProductMapKeyComparator
+    : public util::MessageDifferencer::MapKeyComparator {
+ public:
+  typedef util::MessageDifferencer::SpecificField SpecificField;
+  virtual bool IsMatch(
+      const Message &message1, const Message &message2,
+      const vector<SpecificField>& parent_fields) const {
+    const Reflection* reflection1 = message1.GetReflection();
+    const Reflection* reflection2 = message2.GetReflection();
+    // FieldDescriptor for item.ra
+    const FieldDescriptor* ra_field =
+        message1.GetDescriptor()->FindFieldByName("ra");
+    // Get the product of all elements in item.ra
+    int result1 = 1, result2 = 1;
+    for (int i = 0; i < reflection1->FieldSize(message1, ra_field); ++i) {
+      result1 *= reflection1->GetRepeatedInt32(message1, ra_field, i);
+    }
+    for (int i = 0; i < reflection2->FieldSize(message2, ra_field); ++i) {
+      result2 *= reflection2->GetRepeatedInt32(message2, ra_field, i);
+    }
+    return result1 == result2;
+  }
+};
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_CustomMapKeyComparator) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, using custom key comparator to determine if two
+  // elements have the same key.
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->add_ra(6);
+  item->add_ra(35);
+  item->set_b("hello");
+  item = msg2.add_item();
+  item->add_ra(10);
+  item->add_ra(21);
+  item->set_b("hello");
+  util::MessageDifferencer differencer;
+  ValueProductMapKeyComparator key_comparator;
+  differencer.TreatAsMapUsingKeyComparator(
+      GetFieldDescriptor(msg1, "item"), &key_comparator);
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  // Though the above two messages have different values for item.ra, they
+  // are regarded as having the same key because 6 * 35 == 10 * 21. That's
+  // how the key comparator determines if the two have the same key.
+  // However, in value comparison, all fields of the message are taken into
+  // consideration, so they are different because their item.ra fields have
+  // different values using normal value comparison.
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "modified: item[0].ra[0]: 6 -> 10\n"
+      "modified: item[0].ra[1]: 35 -> 21\n",
+      output);
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+  output.clear();
+  // item.ra is ignored in value comparison, so the two messages equal.
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ("ignored: item[0].ra\n", output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Subset) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  msg1.add_rv(3);
+  msg1.add_rv(8);
+  msg1.add_rv(2);
+  msg2.add_rv(2);
+  msg2.add_rv(3);
+  msg2.add_rv(5);
+  msg2.add_rv(8);
+
+  util::MessageDifferencer differencer;
+
+  // Fail with only partial scope set.
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_LIST);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Fail with only set-like comparison set.
+  differencer.set_scope(util::MessageDifferencer::FULL);
+  differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+  // Succeed with scope and repeated field comparison set properly.
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Single) {
+  protobuf_unittest::TestField msg1;
+  protobuf_unittest::TestField msg2;
+
+  msg1.set_c(3);
+  msg1.add_rc(1);
+
+  msg2.set_c(5);
+  msg2.add_rc(1);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "c"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Repeated) {
+  protobuf_unittest::TestField msg1;
+  protobuf_unittest::TestField msg2;
+
+  msg1.set_c(3);
+  msg1.add_rc(1);
+  msg1.add_rc(2);
+
+  msg2.set_c(3);
+  msg2.add_rc(1);
+  msg2.add_rc(3);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "rc"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Message) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestField* field;
+
+  field = msg1.add_rm();
+  field->set_c(3);
+
+  field = msg2.add_rm();
+  field->set_c(4);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "rm"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Group) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item;
+
+  item = msg1.add_item();
+  item->set_a(3);
+
+  item = msg2.add_item();
+  item->set_a(4);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "item"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Missing) {
+  protobuf_unittest::TestField msg1;
+  protobuf_unittest::TestField msg2;
+
+  msg1.set_c(3);
+  msg1.add_rc(1);
+
+  msg2.add_rc(1);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "c"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+  ExpectEqualsWithDifferencer(&differencer, msg2, msg1);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Multiple) {
+  protobuf_unittest::TestField msg1;
+  protobuf_unittest::TestField msg2;
+
+  msg1.set_c(3);
+  msg1.add_rc(1);
+  msg1.add_rc(2);
+
+  msg2.set_c(5);
+  msg2.add_rc(1);
+  msg2.add_rc(3);
+
+  const FieldDescriptor* c = GetFieldDescriptor(msg1, "c");
+  const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc");
+
+  { // Ignore c
+    util::MessageDifferencer differencer;
+    differencer.IgnoreField(c);
+
+    EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  }
+  { // Ignore rc
+    util::MessageDifferencer differencer;
+    differencer.IgnoreField(rc);
+
+    EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  }
+  { // Ignore both
+    util::MessageDifferencer differencer;
+    differencer.IgnoreField(c);
+    differencer.IgnoreField(rc);
+
+    ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+  }
+}
+
+TEST(MessageDifferencerTest, IgnoreField_NestedMessage) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestField* field;
+
+  field = msg1.add_rm();
+  field->set_c(3);
+  field->add_rc(1);
+
+  field = msg2.add_rm();
+  field->set_c(4);
+  field->add_rc(1);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "rm.c"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_NestedGroup) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item;
+
+  item = msg1.add_item();
+  item->set_a(3);
+  item->set_b("foo");
+
+  item = msg2.add_item();
+  item->set_a(4);
+  item->set_b("foo");
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(GetFieldDescriptor(msg1, "item.a"));
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_InsideSet) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item;
+
+  item = msg1.add_item();
+  item->set_a(1);
+  item->set_b("foo");
+  item->add_ra(1);
+
+  item = msg1.add_item();
+  item->set_a(2);
+  item->set_b("bar");
+  item->add_ra(2);
+
+  item = msg2.add_item();
+  item->set_a(2);
+  item->set_b("bar");
+  item->add_ra(2);
+
+  item = msg2.add_item();
+  item->set_a(1);
+  item->set_b("baz");
+  item->add_ra(1);
+
+  const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+  const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b");
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(b);
+  differencer.TreatAsSet(item_desc);
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_InsideMap) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item;
+
+  item = msg1.add_item();
+  item->set_a(1);
+  item->set_b("foo");
+  item->add_ra(1);
+
+  item = msg1.add_item();
+  item->set_a(2);
+  item->set_b("bar");
+  item->add_ra(2);
+
+  item = msg2.add_item();
+  item->set_a(2);
+  item->set_b("bar");
+  item->add_ra(2);
+
+  item = msg2.add_item();
+  item->set_a(1);
+  item->set_b("baz");
+  item->add_ra(1);
+
+  const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+  const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a");
+  const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b");
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(b);
+  differencer.TreatAsMap(item_desc, a);
+
+  ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_DoesNotIgnoreKey) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item;
+
+  item = msg1.add_item();
+  item->set_a(1);
+  item->set_b("foo");
+  item->add_ra(1);
+
+  item = msg2.add_item();
+  item->set_a(2);
+  item->set_b("foo");
+  item->add_ra(1);
+
+  const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+  const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a");
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(a);
+  differencer.TreatAsMap(item_desc, a);
+
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, IgnoreField_TrumpsCompareWithFields) {
+  protobuf_unittest::TestField msg1;
+  protobuf_unittest::TestField msg2;
+
+  msg1.set_c(3);
+  msg1.add_rc(1);
+  msg1.add_rc(2);
+
+  msg2.set_c(3);
+  msg2.add_rc(1);
+  msg2.add_rc(3);
+
+  const FieldDescriptor* c = GetFieldDescriptor(msg1, "c");
+  const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc");
+
+  vector<const FieldDescriptor*> fields;
+  fields.push_back(c);
+  fields.push_back(rc);
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(rc);
+
+  differencer.set_scope(util::MessageDifferencer::FULL);
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields));
+
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields));
+}
+
+
+// Test class to save a copy of the last field_context.parent_fields() vector
+// passed to the comparison function.
+class ParentSavingFieldComparator : public util::FieldComparator {
+ public:
+  ParentSavingFieldComparator() {}
+
+  virtual ComparisonResult Compare(
+      const google::protobuf::Message& message_1,
+      const google::protobuf::Message& message_2,
+      const google::protobuf::FieldDescriptor* field,
+      int index_1, int index_2,
+      const google::protobuf::util::FieldContext* field_context) {
+    if (field_context)
+      parent_fields_ = *(field_context->parent_fields());
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      return RECURSE;
+    } else {
+      return SAME;
+    }
+  }
+
+  vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields() {
+    return parent_fields_;
+  }
+
+ private:
+  vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields_;
+};
+
+// Tests if MessageDifferencer sends the parent fields in the FieldContext
+// parameter.
+TEST(MessageDifferencerTest, FieldContextParentFieldsTest) {
+  protobuf_unittest::TestDiffMessage msg1;
+  msg1.add_rm()->set_c(1);
+  protobuf_unittest::TestDiffMessage msg2;
+  msg2.add_rm()->set_c(1);
+
+  ParentSavingFieldComparator field_comparator;
+  util::MessageDifferencer differencer;
+  differencer.set_field_comparator(&field_comparator);
+  differencer.Compare(msg1, msg2);
+
+  // We want only one parent with the name "rm"
+  ASSERT_EQ(1, field_comparator.parent_fields().size());
+  EXPECT_EQ("rm", field_comparator.parent_fields()[0].field->name());
+}
+
+
+class ComparisonTest : public testing::Test {
+ protected:
+  ComparisonTest() : use_equivalency_(false), repeated_field_as_set_(false) {
+    // Setup the test.
+    TestUtil::SetAllFields(&proto1_);
+    TestUtil::SetAllFields(&proto2_);
+
+    TestUtil::SetAllExtensions(&proto1ex_);
+    TestUtil::SetAllExtensions(&proto2ex_);
+
+    TestUtil::SetAllFieldsAndExtensions(&orderings_proto1_);
+    TestUtil::SetAllFieldsAndExtensions(&orderings_proto2_);
+
+    unknown1_ = empty1_.mutable_unknown_fields();
+    unknown2_ = empty2_.mutable_unknown_fields();
+  }
+
+  ~ComparisonTest() { }
+
+  void SetSpecialFieldOption(const Message& message,
+                              util::MessageDifferencer* d) {
+    if (!ignored_field_.empty()) {
+      d->IgnoreField(GetFieldDescriptor(message, ignored_field_));
+    }
+
+    if (repeated_field_as_set_) {
+      d->set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+    }
+
+    if (!set_field_.empty()) {
+      d->TreatAsSet(GetFieldDescriptor(message, set_field_));
+    }
+
+    if (!map_field_.empty() && !map_key_.empty()) {
+      d->TreatAsMap(GetFieldDescriptor(message, map_field_),
+                    GetFieldDescriptor(message, map_field_ + "." + map_key_));
+    }
+  }
+
+  string Run(const Message& msg1, const Message& msg2) {
+    string output;
+
+    // Setup the comparison.
+    util::MessageDifferencer differencer;
+    differencer.ReportDifferencesToString(&output);
+
+    if (use_equivalency_) {
+      differencer.set_message_field_comparison(
+          util::MessageDifferencer::EQUIVALENT);
+    }
+
+    SetSpecialFieldOption(msg1, &differencer);
+
+    // Conduct the comparison.
+    EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+    return output;
+  }
+
+  string Run() {
+    return Run(proto1_, proto2_);
+  }
+
+  string RunOrder() {
+    return Run(orderings_proto1_, orderings_proto2_);
+  }
+
+  string RunEx() {
+    return Run(proto1ex_, proto2ex_);
+  }
+
+  string RunDiff() {
+    return Run(proto1diff_, proto2diff_);
+  }
+
+  string RunUn() {
+    return Run(empty1_, empty2_);
+  }
+
+  void use_equivalency() {
+    use_equivalency_ = true;
+  }
+
+  void repeated_field_as_set() {
+    repeated_field_as_set_ = true;
+  }
+
+  void field_as_set(const string& field) {
+    set_field_ = field;
+  }
+
+  void field_as_map(const string& field, const string& key) {
+    map_field_ = field;
+    map_key_   = key;
+  }
+
+  void ignore_field(const string& field) {
+    ignored_field_ = field;
+  }
+
+  unittest::TestAllTypes proto1_;
+  unittest::TestAllTypes proto2_;
+
+  unittest::TestFieldOrderings orderings_proto1_;
+  unittest::TestFieldOrderings orderings_proto2_;
+
+  unittest::TestAllExtensions proto1ex_;
+  unittest::TestAllExtensions proto2ex_;
+
+  unittest::TestDiffMessage proto1diff_;
+  unittest::TestDiffMessage proto2diff_;
+
+  unittest::TestEmptyMessage empty1_;
+  unittest::TestEmptyMessage empty2_;
+
+  UnknownFieldSet* unknown1_;
+  UnknownFieldSet* unknown2_;
+
+  bool use_equivalency_;
+  bool repeated_field_as_set_;
+
+  string set_field_;
+  string map_field_;
+  string map_key_;
+  string ignored_field_;
+};
+
+// Basic tests.
+TEST_F(ComparisonTest, AdditionTest) {
+  proto1_.clear_optional_int32();
+
+  EXPECT_EQ("added: optional_int32: 101\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, Addition_OrderTest) {
+  orderings_proto1_.clear_my_int();
+
+  EXPECT_EQ("added: my_int: 1\n",
+            RunOrder());
+}
+
+TEST_F(ComparisonTest, DeletionTest) {
+  proto2_.clear_optional_int32();
+
+  EXPECT_EQ("deleted: optional_int32: 101\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, Deletion_OrderTest) {
+  orderings_proto2_.clear_my_string();
+
+  EXPECT_EQ("deleted: my_string: \"foo\"\n",
+            RunOrder());
+}
+
+TEST_F(ComparisonTest, RepeatedDeletionTest) {
+  proto2_.clear_repeated_int32();
+
+  EXPECT_EQ("deleted: repeated_int32[0]: 201\n"
+            "deleted: repeated_int32[1]: 301\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, ModificationTest) {
+  proto1_.set_optional_int32(-1);
+
+  EXPECT_EQ("modified: optional_int32: -1 -> 101\n",
+            Run());
+}
+
+// Basic equivalency tests.
+TEST_F(ComparisonTest, EquivalencyAdditionTest) {
+  use_equivalency();
+
+  proto1_.clear_optional_int32();
+
+  EXPECT_EQ("modified: optional_int32: 0 -> 101\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EquivalencyDeletionTest) {
+  use_equivalency();
+
+  proto2_.clear_optional_int32();
+
+  EXPECT_EQ("modified: optional_int32: 101 -> 0\n",
+            Run());
+}
+
+// Group tests.
+TEST_F(ComparisonTest, GroupAdditionTest) {
+  proto1_.mutable_optionalgroup()->clear_a();
+
+  EXPECT_EQ("added: optionalgroup.a: 117\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, GroupDeletionTest) {
+  proto2_.mutable_optionalgroup()->clear_a();
+
+  EXPECT_EQ("deleted: optionalgroup.a: 117\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, GroupModificationTest) {
+  proto1_.mutable_optionalgroup()->set_a(2);
+
+  EXPECT_EQ("modified: optionalgroup.a: 2 -> 117\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, GroupFullAdditionTest) {
+  proto1_.clear_optionalgroup();
+
+  // Note the difference in the output between this and GroupAdditionTest.
+  EXPECT_EQ("added: optionalgroup: { a: 117 }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, GroupFullDeletionTest) {
+  proto2_.clear_optionalgroup();
+
+  EXPECT_EQ("deleted: optionalgroup: { a: 117 }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest) {
+  repeated_field_as_set();
+
+  proto2_.clear_repeatedgroup();
+  proto1_.clear_repeatedgroup();
+  proto1_.add_repeatedgroup()->set_a(317);
+  proto2_.add_repeatedgroup()->set_a(909);
+  proto2_.add_repeatedgroup()->set_a(907);
+  proto1_.add_repeatedgroup()->set_a(904);
+  proto1_.add_repeatedgroup()->set_a(907);
+  proto1_.add_repeatedgroup()->set_a(909);
+
+  EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n"
+            "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+            "deleted: repeatedgroup[0]: { a: 317 }\n"
+            "deleted: repeatedgroup[1]: { a: 904 }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest_Ex) {
+  repeated_field_as_set();
+
+  proto1ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension);
+  proto2ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension);
+  proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+      ->set_bb(909);
+  proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+      ->set_bb(907);
+  proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+      ->set_bb(904);
+  proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+      ->set_bb(907);
+  proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+      ->set_bb(909);
+
+  EXPECT_EQ("moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->"
+            " (protobuf_unittest.repeated_nested_message_extension)[0] :"
+            " { bb: 909 }\n"
+            "deleted: (protobuf_unittest.repeated_nested_message_extension)[0]:"
+            " { bb: 904 }\n",
+            RunEx());
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_Group) {
+  field_as_map("repeatedgroup", "a");
+  proto1_.clear_repeatedgroup();
+  proto2_.clear_repeatedgroup();
+
+  proto1_.add_repeatedgroup()->set_a(317);  // deleted
+  proto1_.add_repeatedgroup()->set_a(904);  // deleted
+  proto1_.add_repeatedgroup()->set_a(907);  // moved from
+  proto1_.add_repeatedgroup()->set_a(909);  // moved from
+
+  proto2_.add_repeatedgroup()->set_a(909);  // moved to
+  proto2_.add_repeatedgroup()->set_a(318);  // added
+  proto2_.add_repeatedgroup()->set_a(907);  // moved to
+
+  EXPECT_EQ("moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+            "added: repeatedgroup[1]: { a: 318 }\n"
+            "deleted: repeatedgroup[0]: { a: 317 }\n"
+            "deleted: repeatedgroup[1]: { a: 904 }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_MessageKey) {
+  // Use m as key, but use b as value.
+  field_as_map("item", "m");
+
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+
+  // The following code creates one deletion, one addition and two moved fields
+  // on the messages.
+  item->mutable_m()->set_c(0);
+  item->set_b("first");
+  item = msg1.add_item();
+  item->mutable_m()->set_c(2);
+  item->set_b("second");
+  item = msg1.add_item(); item->set_b("null");  // empty key moved
+  item = msg1.add_item();
+  item->mutable_m()->set_c(3);
+  item->set_b("third");   // deletion
+  item = msg1.add_item();
+  item->mutable_m()->set_c(2);
+  item->set_b("second");  // duplicated key ( deletion )
+  item = msg2.add_item();
+  item->mutable_m()->set_c(2);
+  item->set_b("second");  // modification
+  item = msg2.add_item();
+  item->mutable_m()->set_c(4);
+  item->set_b("fourth");  // addition
+  item = msg2.add_item();
+  item->mutable_m()->set_c(0);
+  item->set_b("fist");    // move with change
+  item = msg2.add_item(); item->set_b("null");
+
+  EXPECT_EQ(
+      "modified: item[0].b -> item[2].b: \"first\" -> \"fist\"\n"
+      "moved: item[1] -> item[0] : { b: \"second\" m { c: 2 } }\n"
+      "moved: item[2] -> item[3] : { b: \"null\" }\n"
+      "added: item[1]: { b: \"fourth\" m { c: 4 } }\n"
+      "deleted: item[3]: { b: \"third\" m { c: 3 } }\n"
+      "deleted: item[4]: { b: \"second\" m { c: 2 } }\n",
+      Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedFieldSetTest_SetOfSet) {
+  repeated_field_as_set();
+  // Create the testing protos
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->add_ra(1); item->add_ra(2); item->add_ra(3);
+  item = msg1.add_item();
+  item->add_ra(5); item->add_ra(6);
+  item = msg1.add_item();
+  item->add_ra(1); item->add_ra(3);
+  item = msg1.add_item();
+  item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+  item = msg2.add_item();
+  item->add_ra(6); item->add_ra(5);
+  item = msg2.add_item();
+  item->add_ra(6); item->add_ra(8);
+  item = msg2.add_item();
+  item->add_ra(1); item->add_ra(3);
+  item = msg2.add_item();
+  item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+  // Compare
+  EXPECT_EQ("moved: item[0].ra[0] -> item[3].ra[2] : 1\n"
+            "moved: item[0].ra[2] -> item[3].ra[0] : 3\n"
+            "moved: item[0] -> item[3] : { ra: 1 ra: 2 ra: 3 }\n"
+            "moved: item[1].ra[0] -> item[0].ra[1] : 5\n"
+            "moved: item[1].ra[1] -> item[0].ra[0] : 6\n"
+            "moved: item[1] -> item[0] : { ra: 5 ra: 6 }\n"
+            "added: item[1]: { ra: 6 ra: 8 }\n"
+            "deleted: item[3]: { ra: 6 ra: 7 ra: 8 }\n",
+            Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedKey) {
+  // used rb as a key, but b is the value.
+  repeated_field_as_set();
+  field_as_map("item", "rb");
+
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->add_rb("a");
+  item->add_rb("b");
+  item->set_b("first");
+
+  item = msg2.add_item();
+  item->add_rb("c");
+  item->set_b("second");
+
+  item = msg2.add_item();
+  item->add_rb("b");
+  item->add_rb("a");
+  item->set_b("fist");
+
+
+  EXPECT_EQ("modified: item[0].b -> item[1].b: \"first\" -> \"fist\"\n"
+            "moved: item[0].rb[0] -> item[1].rb[1] : \"a\"\n"
+            "moved: item[0].rb[1] -> item[1].rb[0] : \"b\"\n"
+            "added: item[0]: { b: \"second\" rb: \"c\" }\n",
+            Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedMessageKey) {
+  field_as_map("item", "rm");
+
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  protobuf_unittest::TestField* key = item->add_rm();
+  key->set_c(2); key->add_rc(10); key->add_rc(10);
+  item = msg1.add_item(); key = item->add_rm();
+  key->set_c(0); key->add_rc(1); key->add_rc(2);
+  key = item->add_rm();
+  key->set_c(0);
+  item->add_rb("first");
+
+  item = msg2.add_item();
+  item->CopyFrom(msg1.item(1));
+  item->add_rb("second");
+
+  EXPECT_EQ("added: item[0].rb[1]: \"second\"\n"
+            "deleted: item[0]: { rm { c: 2 rc: 10 rc: 10 } }\n",
+            Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest_Unknown) {
+  // Currently, as_set option doens't have affects on unknown field.
+  // If needed, this feature will be added by request.
+  repeated_field_as_set();
+  unknown1_->AddGroup(245)->AddFixed32(248, 1);
+  unknown2_->AddGroup(245)->AddFixed32(248, 3);
+  unknown2_->AddGroup(245)->AddFixed32(248, 1);
+
+  // We expect it behaves the same as normal comparison.
+  EXPECT_EQ("modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n"
+            "added: 245[1]: { ... }\n",
+            RunUn());
+}
+
+TEST_F(ComparisonTest, Matching_Unknown) {
+  unknown1_->AddGroup(245)->AddFixed32(248, 1);
+  unknown2_->AddGroup(245)->AddFixed32(248, 1);
+  unknown1_->AddGroup(245)->AddFixed32(248, 3);
+  unknown2_->AddGroup(245)->AddFixed32(248, 3);
+  unknown2_->AddLengthDelimited(242, "cat");
+  unknown2_->AddGroup(246)->AddFixed32(248, 4);
+
+  // report_match is false so only added/modified fields are expected.
+  EXPECT_EQ("added: 242[0]: \"cat\"\n"
+            "added: 246[0]: { ... }\n",
+            RunUn());
+}
+
+TEST_F(ComparisonTest, RepeatedSetFieldTest) {
+  field_as_set("repeatedgroup");
+
+  proto1_.clear_repeatedgroup();
+  proto2_.clear_repeatedgroup();
+  proto2_.add_repeatedgroup()->set_a(909);
+  proto2_.add_repeatedgroup()->set_a(907);
+  proto1_.add_repeatedgroup()->set_a(317);
+  proto1_.add_repeatedgroup()->set_a(904);
+  proto1_.add_repeatedgroup()->set_a(907);
+  proto1_.add_repeatedgroup()->set_a(909);
+
+  EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n"
+            "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+            "deleted: repeatedgroup[0]: { a: 317 }\n"
+            "deleted: repeatedgroup[1]: { a: 904 }\n",
+            Run());
+}
+
+// Embedded message tests.
+TEST_F(ComparisonTest, EmbeddedAdditionTest) {
+  proto1_.mutable_optional_nested_message()->clear_bb();
+
+  EXPECT_EQ("added: optional_nested_message.bb: 118\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedDeletionTest) {
+  proto2_.mutable_optional_nested_message()->clear_bb();
+
+  EXPECT_EQ("deleted: optional_nested_message.bb: 118\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedModificationTest) {
+  proto1_.mutable_optional_nested_message()->set_bb(2);
+
+  EXPECT_EQ("modified: optional_nested_message.bb: 2 -> 118\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedFullAdditionTest) {
+  proto1_.clear_optional_nested_message();
+
+  EXPECT_EQ("added: optional_nested_message: { bb: 118 }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedPartialAdditionTest) {
+  proto1_.clear_optional_nested_message();
+  proto2_.mutable_optional_nested_message()->clear_bb();
+
+  EXPECT_EQ("added: optional_nested_message: { }\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedFullDeletionTest) {
+  proto2_.clear_optional_nested_message();
+
+  EXPECT_EQ("deleted: optional_nested_message: { bb: 118 }\n",
+            Run());
+}
+
+// Repeated element tests.
+TEST_F(ComparisonTest, BasicRepeatedTest) {
+  proto1_.clear_repeated_int32();
+  proto2_.clear_repeated_int32();
+
+  proto1_.add_repeated_int32(500);
+  proto1_.add_repeated_int32(501);
+  proto1_.add_repeated_int32(502);
+  proto1_.add_repeated_int32(503);
+  proto1_.add_repeated_int32(500);
+
+  proto2_.add_repeated_int32(500);
+  proto2_.add_repeated_int32(509);
+  proto2_.add_repeated_int32(502);
+  proto2_.add_repeated_int32(504);
+
+  EXPECT_EQ("modified: repeated_int32[1]: 501 -> 509\n"
+            "modified: repeated_int32[3]: 503 -> 504\n"
+            "deleted: repeated_int32[4]: 500\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, BasicRepeatedTest_SetOption) {
+  repeated_field_as_set();
+  proto1_.clear_repeated_int32();
+  proto2_.clear_repeated_int32();
+
+  proto1_.add_repeated_int32(501);
+  proto1_.add_repeated_int32(502);
+  proto1_.add_repeated_int32(503);
+  proto1_.add_repeated_int32(500);
+  proto1_.add_repeated_int32(500);
+
+  proto2_.add_repeated_int32(500);
+  proto2_.add_repeated_int32(509);
+  proto2_.add_repeated_int32(503);
+  proto2_.add_repeated_int32(502);
+  proto2_.add_repeated_int32(504);
+
+  EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n"
+            "moved: repeated_int32[3] -> repeated_int32[0] : 500\n"
+            "added: repeated_int32[1]: 509\n"
+            "added: repeated_int32[4]: 504\n"
+            "deleted: repeated_int32[0]: 501\n"
+            "deleted: repeated_int32[4]: 500\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, BasicRepeatedTest_SetField) {
+  field_as_set("repeated_int32");
+  proto1_.clear_repeated_int32();
+  proto2_.clear_repeated_int32();
+
+  proto1_.add_repeated_int32(501);
+  proto1_.add_repeated_int32(502);
+  proto1_.add_repeated_int32(503);
+  proto1_.add_repeated_int32(500);
+  proto1_.add_repeated_int32(500);
+
+  proto2_.add_repeated_int32(500);
+  proto2_.add_repeated_int32(509);
+  proto2_.add_repeated_int32(503);
+  proto2_.add_repeated_int32(502);
+  proto2_.add_repeated_int32(504);
+
+  EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n"
+            "moved: repeated_int32[3] -> repeated_int32[0] : 500\n"
+            "added: repeated_int32[1]: 509\n"
+            "added: repeated_int32[4]: 504\n"
+            "deleted: repeated_int32[0]: 501\n"
+            "deleted: repeated_int32[4]: 500\n",
+            Run());
+}
+
+// Multiple action tests.
+TEST_F(ComparisonTest, AddDeleteTest) {
+  proto1_.clear_optional_int32();
+  proto2_.clear_optional_int64();
+
+  EXPECT_EQ("added: optional_int32: 101\n"
+            "deleted: optional_int64: 102\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, AddDelete_FieldOrderingTest) {
+  orderings_proto1_.ClearExtension(unittest::my_extension_string);
+  orderings_proto2_.clear_my_int();
+
+  EXPECT_EQ("deleted: my_int: 1\n"
+            "added: (protobuf_unittest.my_extension_string): \"bar\"\n",
+            RunOrder());
+}
+
+TEST_F(ComparisonTest, AllThreeTest) {
+  proto1_.clear_optional_int32();
+  proto2_.clear_optional_float();
+  proto2_.set_optional_string("hello world!");
+
+  EXPECT_EQ("added: optional_int32: 101\n"
+            "deleted: optional_float: 111\n"
+            "modified: optional_string: \"115\" -> \"hello world!\"\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, SandwhichTest) {
+  proto1_.clear_optional_int64();
+  proto1_.clear_optional_uint32();
+
+  proto2_.clear_optional_uint64();
+
+  EXPECT_EQ("added: optional_int64: 102\n"
+            "added: optional_uint32: 103\n"
+            "deleted: optional_uint64: 104\n",
+            Run());
+}
+
+TEST_F(ComparisonTest, IgnoredNoChangeTest) {
+  proto1diff_.set_v(3);
+  proto2diff_.set_v(3);
+  proto2diff_.set_w("foo");
+
+  ignore_field("v");
+
+  EXPECT_EQ("ignored: v\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredAddTest) {
+  proto2diff_.set_v(3);
+  proto2diff_.set_w("foo");
+
+  ignore_field("v");
+
+  EXPECT_EQ("ignored: v\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredDeleteTest) {
+  proto1diff_.set_v(3);
+  proto2diff_.set_w("foo");
+
+  ignore_field("v");
+
+  EXPECT_EQ("ignored: v\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredModifyTest) {
+  proto1diff_.set_v(3);
+  proto2diff_.set_v(4);
+  proto2diff_.set_w("foo");
+
+  ignore_field("v");
+
+  EXPECT_EQ("ignored: v\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedAddTest) {
+  proto1diff_.add_rv(3);
+  proto1diff_.add_rv(4);
+
+  proto2diff_.add_rv(3);
+  proto2diff_.add_rv(4);
+  proto2diff_.add_rv(5);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("rv");
+
+  EXPECT_EQ("ignored: rv\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedDeleteTest) {
+  proto1diff_.add_rv(3);
+  proto1diff_.add_rv(4);
+  proto1diff_.add_rv(5);
+
+  proto2diff_.add_rv(3);
+  proto2diff_.add_rv(4);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("rv");
+
+  EXPECT_EQ("ignored: rv\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedModifyTest) {
+  proto1diff_.add_rv(3);
+  proto1diff_.add_rv(4);
+
+  proto2diff_.add_rv(3);
+  proto2diff_.add_rv(5);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("rv");
+
+  EXPECT_EQ("ignored: rv\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredWholeNestedMessage) {
+  proto1diff_.mutable_m()->set_c(3);
+  proto2diff_.mutable_m()->set_c(4);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("m");
+
+  EXPECT_EQ("added: w: \"foo\"\n"
+            "ignored: m\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredNestedField) {
+  proto1diff_.mutable_m()->set_c(3);
+  proto2diff_.mutable_m()->set_c(4);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("m.c");
+
+  EXPECT_EQ("added: w: \"foo\"\n"
+            "ignored: m.c\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedNested) {
+  proto1diff_.add_rm()->set_c(0);
+  proto1diff_.add_rm()->set_c(1);
+  proto2diff_.add_rm()->set_c(2);
+  proto2diff_.add_rm()->set_c(3);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("rm.c");
+
+  EXPECT_EQ("ignored: rm[0].c\n"
+            "ignored: rm[1].c\n"
+            "added: w: \"foo\"\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredNestedRepeated) {
+  proto1diff_.mutable_m()->add_rc(23);
+  proto1diff_.mutable_m()->add_rc(24);
+  proto2diff_.mutable_m()->add_rc(25);
+
+  proto2diff_.set_w("foo");
+
+  ignore_field("m.rc");
+
+  EXPECT_EQ("added: w: \"foo\"\n"
+            "ignored: m.rc\n",
+            RunDiff());
+}
+
+TEST_F(ComparisonTest, ExtensionTest) {
+  proto1ex_.SetExtension(unittest::optional_int32_extension, 401);
+  proto2ex_.SetExtension(unittest::optional_int32_extension, 402);
+
+  proto1ex_.ClearExtension(unittest::optional_int64_extension);
+  proto2ex_.SetExtension(unittest::optional_int64_extension, 403);
+
+  EXPECT_EQ(
+      "modified: (protobuf_unittest.optional_int32_extension): 401 -> 402\n"
+      "added: (protobuf_unittest.optional_int64_extension): 403\n",
+      RunEx());
+}
+
+TEST_F(ComparisonTest, MatchedUnknownFieldTagTest) {
+  unknown1_->AddVarint(240, 122);
+  unknown2_->AddVarint(240, 121);
+  unknown1_->AddFixed32(241, 1);
+  unknown2_->AddFixed64(241, 2);
+  unknown1_->AddLengthDelimited(242, "cat");
+  unknown2_->AddLengthDelimited(242, "dog");
+
+  EXPECT_EQ(
+      "modified: 240[0]: 122 -> 121\n"
+      "deleted: 241[0]: 0x00000001\n"
+      "added: 241[0]: 0x0000000000000002\n"
+      "modified: 242[0]: \"cat\" -> \"dog\"\n",
+      RunUn());
+}
+
+TEST_F(ComparisonTest, UnmatchedUnknownFieldTagTest) {
+  unknown1_->AddFixed32(243, 1);
+  unknown2_->AddVarint(244, 2);
+  unknown2_->AddVarint(244, 4);
+
+  EXPECT_EQ(
+      "deleted: 243[0]: 0x00000001\n"
+      "added: 244[0]: 2\n"
+      "added: 244[1]: 4\n",
+      RunUn());
+}
+
+TEST_F(ComparisonTest, DifferentSizedUnknownFieldTest) {
+  unknown1_->AddVarint(240, 1);
+  unknown1_->AddVarint(240, 3);
+  unknown1_->AddVarint(240, 4);
+  unknown2_->AddVarint(240, 2);
+  unknown2_->AddVarint(240, 3);
+  unknown2_->AddVarint(240, 2);
+  unknown2_->AddVarint(240, 5);
+
+  EXPECT_EQ(
+      "modified: 240[0]: 1 -> 2\n"
+      "modified: 240[2]: 4 -> 2\n"
+      "added: 240[3]: 5\n",
+      RunUn());
+}
+
+TEST_F(ComparisonTest, UnknownFieldsAll) {
+  unknown1_->AddVarint(243, 122);
+  unknown1_->AddFixed64(244, 0x0172356);
+  unknown1_->AddFixed64(244, 0x098);
+  unknown1_->AddGroup(245)->AddFixed32(248, 1);
+  unknown1_->mutable_field(3)->mutable_group()->AddFixed32(248, 2);
+  unknown1_->AddGroup(249)->AddFixed64(250, 1);
+
+  unknown2_->AddVarint(243, 121);
+  unknown2_->AddLengthDelimited(73882, "test 123");
+  unknown2_->AddGroup(245)->AddFixed32(248, 3);
+  unknown2_->AddGroup(247);
+
+  EXPECT_EQ(
+      "modified: 243[0]: 122 -> 121\n"
+      "deleted: 244[0]: 0x0000000000172356\n"
+      "deleted: 244[1]: 0x0000000000000098\n"
+      "modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n"
+      "deleted: 245[0].248[1]: 0x00000002\n"
+      "added: 247[0]: { ... }\n"
+      "deleted: 249[0]: { ... }\n"
+      "added: 73882[0]: \"test 123\"\n",
+      RunUn());
+}
+
+TEST_F(ComparisonTest, EquivalentIgnoresUnknown) {
+  unittest::ForeignMessage message1, message2;
+
+  message1.set_c(5);
+  message1.mutable_unknown_fields()->AddVarint(123, 456);
+  message2.set_c(5);
+  message2.mutable_unknown_fields()->AddVarint(321, 654);
+
+  EXPECT_FALSE(util::MessageDifferencer::Equals(message1, message2));
+  EXPECT_TRUE(util::MessageDifferencer::Equivalent(message1, message2));
+}
+
+class MatchingTest : public testing::Test {
+ public:
+  typedef util::MessageDifferencer MessageDifferencer;
+
+ protected:
+  MatchingTest() {
+  }
+
+  ~MatchingTest() {
+  }
+
+  string RunWithResult(MessageDifferencer* differencer,
+                              const Message& msg1, const Message& msg2,
+                              bool result) {
+    string output;
+    {
+      // Before we return the "output" string, we must make sure the
+      // StreamReporter is destructored because its destructor will
+      // flush the stream.
+      io::StringOutputStream output_stream(&output);
+      MessageDifferencer::StreamReporter reporter(&output_stream);
+      reporter.set_report_modified_aggregates(true);
+      differencer->set_report_matches(true);
+      differencer->ReportDifferencesTo(&reporter);
+      if (result) {
+        EXPECT_TRUE(differencer->Compare(msg1, msg2));
+      } else {
+        EXPECT_FALSE(differencer->Compare(msg1, msg2));
+      }
+    }
+    return output;
+  }
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MatchingTest);
+};
+
+TEST_F(MatchingTest, StreamReporterMatching) {
+  protobuf_unittest::TestField msg1, msg2;
+  msg1.set_c(72);
+  msg2.set_c(72);
+  msg1.add_rc(13);
+  msg2.add_rc(13);
+  msg1.add_rc(17);
+  msg2.add_rc(17);
+  string output;
+  MessageDifferencer differencer;
+  differencer.set_report_matches(true);
+  differencer.ReportDifferencesToString(&output);
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "matched: c : 72\n"
+      "matched: rc[0] : 13\n"
+      "matched: rc[1] : 17\n",
+      output);
+}
+
+TEST_F(MatchingTest, DontReportMatchedWhenIgnoring) {
+  protobuf_unittest::TestField msg1, msg2;
+  msg1.set_c(72);
+  msg2.set_c(72);
+  msg1.add_rc(13);
+  msg2.add_rc(13);
+  msg1.add_rc(17);
+  msg2.add_rc(17);
+  string output;
+  MessageDifferencer differencer;
+  differencer.set_report_matches(true);
+  differencer.ReportDifferencesToString(&output);
+
+  differencer.IgnoreField(msg1.GetDescriptor()->FindFieldByName("c"));
+
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "ignored: c\n"
+      "matched: rc[0] : 13\n"
+      "matched: rc[1] : 17\n",
+      output);
+}
+
+TEST_F(MatchingTest, ReportMatchedForMovedFields) {
+  protobuf_unittest::TestDiffMessage msg1, msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->set_a(53);
+  item->set_b("hello");
+  item = msg2.add_item();
+  item->set_a(27);
+  item = msg2.add_item();
+  item->set_a(53);
+  item->set_b("hello");
+  item = msg1.add_item();
+  item->set_a(27);
+  MessageDifferencer differencer;
+  const FieldDescriptor* desc;
+  desc = msg1.GetDescriptor()->FindFieldByName("item");
+  differencer.TreatAsSet(desc);
+
+  EXPECT_EQ(
+      "matched: item[0].a -> item[1].a : 53\n"
+      "matched: item[0].b -> item[1].b : \"hello\"\n"
+      "moved: item[0] -> item[1] : { a: 53 b: \"hello\" }\n"
+      "matched: item[1].a -> item[0].a : 27\n"
+      "moved: item[1] -> item[0] : { a: 27 }\n",
+      RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST_F(MatchingTest, MatchesAppearInPostTraversalOrderForMovedFields) {
+  protobuf_unittest::TestDiffMessage msg1, msg2;
+  protobuf_unittest::TestDiffMessage::Item* item;
+  protobuf_unittest::TestField* field;
+
+  const FieldDescriptor* desc;
+  const FieldDescriptor* nested_desc;
+  const FieldDescriptor* double_nested_desc;
+  desc = msg1.GetDescriptor()->FindFieldByName("item");
+  nested_desc = desc->message_type()->FindFieldByName("rm");
+  double_nested_desc = nested_desc->message_type()->FindFieldByName("rc");
+  MessageDifferencer differencer;
+  differencer.TreatAsSet(desc);
+  differencer.TreatAsSet(nested_desc);
+  differencer.TreatAsSet(double_nested_desc);
+
+  item = msg1.add_item();
+  field = item->add_rm();
+  field->set_c(1);
+  field->add_rc(2);
+  field->add_rc(3);
+  field = item->add_rm();
+  field->set_c(4);
+  field->add_rc(5);
+  field->add_rc(6);
+  field->add_rc(7);
+  item = msg2.add_item();
+  field = item->add_rm();
+  field->set_c(4);
+  field->add_rc(7);
+  field->add_rc(6);
+  field->add_rc(5);
+  field = item->add_rm();
+  field->set_c(1);
+  field->add_rc(3);
+  field->add_rc(2);
+  item = msg1.add_item();
+  field = item->add_rm();
+  field->set_c(8);
+  field->add_rc(10);
+  field->add_rc(11);
+  field->add_rc(9);
+  item = msg2.add_item();
+  field = item->add_rm();
+  field->set_c(8);
+  field->add_rc(9);
+  field->add_rc(10);
+  field->add_rc(11);
+
+  EXPECT_EQ(
+      "matched: item[0].rm[0].c -> item[0].rm[1].c : 1\n"
+      "moved: item[0].rm[0].rc[0] -> item[0].rm[1].rc[1] : 2\n"
+      "moved: item[0].rm[0].rc[1] -> item[0].rm[1].rc[0] : 3\n"
+      "moved: item[0].rm[0] -> item[0].rm[1] : { c: 1 rc: 2 rc: 3 }\n"
+      "matched: item[0].rm[1].c -> item[0].rm[0].c : 4\n"
+      "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 5\n"
+      "matched: item[0].rm[1].rc[1] -> item[0].rm[0].rc[1] : 6\n"
+      "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 7\n"
+      "moved: item[0].rm[1] -> item[0].rm[0] : { c: 4 rc: 5 rc: 6 rc: 7 }\n"
+      "matched: item[0] : { rm { c: 1 rc: 2 rc: 3 }"
+                          " rm { c: 4 rc: 5 rc: 6 rc: 7 } }\n"
+      "matched: item[1].rm[0].c : 8\n"
+      "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 10\n"
+      "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[2] : 11\n"
+      "moved: item[1].rm[0].rc[2] -> item[1].rm[0].rc[0] : 9\n"
+      "matched: item[1].rm[0] : { c: 8 rc: 10 rc: 11 rc: 9 }\n"
+      "matched: item[1] : { rm { c: 8 rc: 10 rc: 11 rc: 9 } }\n",
+      RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST_F(MatchingTest, MatchAndModifiedInterleaveProperly) {
+  protobuf_unittest::TestDiffMessage msg1, msg2;
+  protobuf_unittest::TestDiffMessage::Item* item;
+  protobuf_unittest::TestField* field;
+
+  const FieldDescriptor* desc;
+  const FieldDescriptor* nested_key;
+  const FieldDescriptor* nested_desc;
+  const FieldDescriptor* double_nested_key;
+  const FieldDescriptor* double_nested_desc;
+  desc = msg1.GetDescriptor()->FindFieldByName("item");
+  nested_key = desc->message_type()->FindFieldByName("a");
+  nested_desc = desc->message_type()->FindFieldByName("rm");
+  double_nested_key = nested_desc->message_type()->FindFieldByName("c");
+  double_nested_desc = nested_desc->message_type()->FindFieldByName("rc");
+
+  MessageDifferencer differencer;
+  differencer.TreatAsMap(desc, nested_key);
+  differencer.TreatAsMap(nested_desc, double_nested_key);
+  differencer.TreatAsSet(double_nested_desc);
+
+  item = msg1.add_item();
+  item->set_a(1);
+  field = item->add_rm();
+  field->set_c(2);
+  field->add_rc(3);
+  field->add_rc(4);
+  field = item->add_rm();
+  field->set_c(5);
+  field->add_rc(6);
+  field->add_rc(7);
+  field->add_rc(8);
+  item = msg1.add_item();
+  item->set_a(9);
+  field = item->add_rm();
+  field->set_c(10);
+  field->add_rc(11);
+  field->add_rc(12);
+  field = item->add_rm();
+  field->set_c(13);
+
+  item = msg2.add_item();
+  item->set_a(1);
+  field = item->add_rm();
+  field->set_c(5);
+  field->add_rc(8);
+  field->add_rc(8);
+  field->add_rc(6);
+  field = item->add_rm();
+  field->set_c(3);
+  field->add_rc(2);
+  field->add_rc(4);
+  item = msg2.add_item();
+  item->set_a(9);
+  field = item->add_rm();
+  field->set_c(10);
+  field->add_rc(12);
+  field->add_rc(11);
+  field = item->add_rm();
+  field->set_c(13);
+
+  EXPECT_EQ(
+      "matched: item[0].a : 1\n"
+      "matched: item[0].rm[1].c -> item[0].rm[0].c : 5\n"
+      "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 6\n"
+      "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 8\n"
+      "added: item[0].rm[0].rc[1]: 8\n"
+      "deleted: item[0].rm[1].rc[1]: 7\n"
+      "modified: item[0].rm[1] -> item[0].rm[0]: { c: 5 rc: 6 rc: 7 rc: 8 } ->"
+                                               " { c: 5 rc: 8 rc: 8 rc: 6 }\n"
+      "added: item[0].rm[1]: { c: 3 rc: 2 rc: 4 }\n"
+      "deleted: item[0].rm[0]: { c: 2 rc: 3 rc: 4 }\n"
+      "modified: item[0]: { a: 1 rm { c: 2 rc: 3 rc: 4 }"
+                               " rm { c: 5 rc: 6 rc: 7 rc: 8 } } ->"
+                        " { a: 1 rm { c: 5 rc: 8 rc: 8 rc: 6 }"
+                               " rm { c: 3 rc: 2 rc: 4 } }\n"
+      "matched: item[1].a : 9\n"
+      "matched: item[1].rm[0].c : 10\n"
+      "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 11\n"
+      "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[0] : 12\n"
+      "matched: item[1].rm[0] : { c: 10 rc: 11 rc: 12 }\n"
+      "matched: item[1].rm[1].c : 13\n"
+      "matched: item[1].rm[1] : { c: 13 }\n"
+      "matched: item[1] : { a: 9 rm { c: 10 rc: 11 rc: 12 } rm { c: 13 } }\n",
+      RunWithResult(&differencer, msg1, msg2, false));
+}
+
+TEST_F(MatchingTest, MatchingWorksWithExtensions) {
+  protobuf_unittest::TestAllExtensions msg1, msg2;
+  protobuf_unittest::TestAllTypes::NestedMessage* nested;
+  using protobuf_unittest::repeated_nested_message_extension;
+
+  const FileDescriptor* descriptor;
+  const FieldDescriptor* desc;
+  const FieldDescriptor* nested_key;
+  descriptor = msg1.GetDescriptor()->file();
+  desc = descriptor->FindExtensionByName("repeated_nested_message_extension");
+  ASSERT_FALSE(desc == NULL);
+  nested_key = desc->message_type()->FindFieldByName("bb");
+
+  MessageDifferencer differencer;
+  differencer.TreatAsMap(desc, nested_key);
+
+  nested = msg1.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(7);
+  nested = msg1.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(13);
+  nested = msg1.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(11);
+  nested = msg2.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(11);
+  nested = msg2.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(13);
+  nested = msg2.AddExtension(repeated_nested_message_extension);
+  nested->set_bb(7);
+
+  EXPECT_EQ(
+      "matched: (protobuf_unittest.repeated_nested_message_extension)[0].bb ->"
+              " (protobuf_unittest.repeated_nested_message_extension)[2].bb : 7\n"
+      "moved: (protobuf_unittest.repeated_nested_message_extension)[0] ->"
+            " (protobuf_unittest.repeated_nested_message_extension)[2] :"
+                " { bb: 7 }\n"
+      "matched: (protobuf_unittest.repeated_nested_message_extension)[1].bb :"
+                  " 13\n"
+      "matched: (protobuf_unittest.repeated_nested_message_extension)[1] :"
+                  " { bb: 13 }\n"
+      "matched: (protobuf_unittest.repeated_nested_message_extension)[2].bb ->"
+              " (protobuf_unittest.repeated_nested_message_extension)[0].bb :"
+                  " 11\n"
+      "moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->"
+            " (protobuf_unittest.repeated_nested_message_extension)[0] :"
+                " { bb: 11 }\n",
+      RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST(AnyTest, Simple) {
+  protobuf_unittest::TestField value1, value2;
+  value1.set_a(20);
+  value2.set_a(21);
+
+  protobuf_unittest::TestAny m1, m2;
+  m1.mutable_any_value()->PackFrom(value1);
+  m2.mutable_any_value()->PackFrom(value2);
+  util::MessageDifferencer message_differencer;
+  string difference_string;
+  message_differencer.ReportDifferencesToString(&difference_string);
+  EXPECT_FALSE(message_differencer.Compare(m1, m2));
+  EXPECT_EQ("modified: any_value.a: 20 -> 21\n", difference_string);
+}
+
+TEST(Anytest, TreatAsSet) {
+  protobuf_unittest::TestField value1, value2;
+  value1.set_a(20);
+  value1.set_b(30);
+  value2.set_a(20);
+  value2.set_b(31);
+
+  protobuf_unittest::TestAny m1, m2;
+  m1.add_repeated_any_value()->PackFrom(value1);
+  m1.add_repeated_any_value()->PackFrom(value2);
+  m2.add_repeated_any_value()->PackFrom(value2);
+  m2.add_repeated_any_value()->PackFrom(value1);
+
+  util::MessageDifferencer message_differencer;
+  message_differencer.TreatAsSet(GetFieldDescriptor(m1, "repeated_any_value"));
+  EXPECT_TRUE(message_differencer.Compare(m1, m2));
+}
+
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.proto b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.proto
new file mode 100644
index 0000000..698775f
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/message_differencer_unittest.proto
@@ -0,0 +1,74 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing repeated field comparison
+
+syntax = "proto2";
+package protobuf_unittest;
+
+option optimize_for = SPEED;
+
+message TestField {
+  optional int32 a = 3;
+  optional int32 b = 4;
+  optional int32 c = 1;
+  repeated int32 rc = 2;
+  optional TestField m = 5;
+
+  extend TestDiffMessage {
+    optional TestField tf = 100;
+  }
+}
+
+message TestDiffMessage {
+  repeated group Item = 1 {
+    optional int32  a  =  2;     // Test basic repeated field comparison.
+    optional string b  =  4;     // Test basic repeated field comparison.
+    repeated int32  ra =  3;     // Test SetOfSet Comparison.
+    repeated string rb =  5;     // Test TreatAsMap when key is repeated
+    optional TestField m  = 6;   // Test TreatAsMap when key is a message
+    repeated TestField rm = 7;   // Test TreatAsMap when key is a repeated
+                                 // message
+  }
+
+  optional int32  v  = 13 [deprecated = true];
+  optional string w  = 14;
+  optional TestField m  = 15;
+  repeated int32  rv = 11;       // Test for combinations
+  repeated string rw = 10;       // Test for combinations
+  repeated TestField rm = 12 [deprecated = true];    // Test for combinations
+
+  extensions 100 to 199;
+}
+
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/time_util.cc b/src/third_party/protobuf-3/src/google/protobuf/util/time_util.cc
new file mode 100644
index 0000000..c782d69
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/time_util.cc
@@ -0,0 +1,525 @@
+// 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.
+
+#include <google/protobuf/util/time_util.h>
+
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/stubs/int128.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/timestamp.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::Timestamp;
+using google::protobuf::Duration;
+
+namespace {
+static const int kNanosPerSecond = 1000000000;
+static const int kMicrosPerSecond = 1000000;
+static const int kMillisPerSecond = 1000;
+static const int kNanosPerMillisecond = 1000000;
+static const int kMicrosPerMillisecond = 1000;
+static const int kNanosPerMicrosecond = 1000;
+static const int kSecondsPerMinute = 60;  // Note that we ignore leap seconds.
+static const int kSecondsPerHour = 3600;
+static const char kTimestampFormat[] = "%E4Y-%m-%dT%H:%M:%S";
+
+template <typename T>
+T CreateNormalized(int64 seconds, int64 nanos);
+
+template <>
+Timestamp CreateNormalized(int64 seconds, int64 nanos) {
+  // Make sure nanos is in the range.
+  if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+    seconds += nanos / kNanosPerSecond;
+    nanos = nanos % kNanosPerSecond;
+  }
+  // For Timestamp nanos should be in the range [0, 999999999]
+  if (nanos < 0) {
+    seconds -= 1;
+    nanos += kNanosPerSecond;
+  }
+  GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
+         seconds <= TimeUtil::kTimestampMaxSeconds);
+  Timestamp result;
+  result.set_seconds(seconds);
+  result.set_nanos(static_cast<int32>(nanos));
+  return result;
+}
+
+template <>
+Duration CreateNormalized(int64 seconds, int64 nanos) {
+  // Make sure nanos is in the range.
+  if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+    seconds += nanos / kNanosPerSecond;
+    nanos = nanos % kNanosPerSecond;
+  }
+  // nanos should have the same sign as seconds.
+  if (seconds < 0 && nanos > 0) {
+    seconds += 1;
+    nanos -= kNanosPerSecond;
+  } else if (seconds > 0 && nanos < 0) {
+    seconds -= 1;
+    nanos += kNanosPerSecond;
+  }
+  GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
+         seconds <= TimeUtil::kDurationMaxSeconds);
+  Duration result;
+  result.set_seconds(seconds);
+  result.set_nanos(static_cast<int32>(nanos));
+  return result;
+}
+
+// Format nanoseconds with either 3, 6, or 9 digits depending on the required
+// precision to represent the exact value.
+string FormatNanos(int32 nanos) {
+  if (nanos % kNanosPerMillisecond == 0) {
+    return StringPrintf("%03d", nanos / kNanosPerMillisecond);
+  } else if (nanos % kNanosPerMicrosecond == 0) {
+    return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
+  } else {
+    return StringPrintf("%09d", nanos);
+  }
+}
+
+string FormatTime(int64 seconds, int32 nanos) {
+  return ::google::protobuf::internal::FormatTime(seconds, nanos);
+}
+
+bool ParseTime(const string& value, int64* seconds, int32* nanos) {
+  return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
+}
+
+void CurrentTime(int64* seconds, int32* nanos) {
+  return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
+}
+
+// Truncates the remainder part after division.
+int64 RoundTowardZero(int64 value, int64 divider) {
+  int64 result = value / divider;
+  int64 remainder = value % divider;
+  // Before C++11, the sign of the remainder is implementation dependent if
+  // any of the operands is negative. Here we try to enforce C++11's "rounded
+  // toward zero" semantics. For example, for (-5) / 2 an implementation may
+  // give -3 as the result with the remainder being 1. This function ensures
+  // we always return -2 (closer to zero) regardless of the implementation.
+  if (result < 0 && remainder > 0) {
+    return result + 1;
+  } else {
+    return result;
+  }
+}
+}  // namespace
+
+string TimeUtil::ToString(const Timestamp& timestamp) {
+  return FormatTime(timestamp.seconds(), timestamp.nanos());
+}
+
+bool TimeUtil::FromString(const string& value, Timestamp* timestamp) {
+  int64 seconds;
+  int32 nanos;
+  if (!ParseTime(value, &seconds, &nanos)) {
+    return false;
+  }
+  *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
+  return true;
+}
+
+Timestamp TimeUtil::GetCurrentTime() {
+  int64 seconds;
+  int32 nanos;
+  CurrentTime(&seconds, &nanos);
+  return CreateNormalized<Timestamp>(seconds, nanos);
+}
+
+Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
+
+string TimeUtil::ToString(const Duration& duration) {
+  string result;
+  int64 seconds = duration.seconds();
+  int32 nanos = duration.nanos();
+  if (seconds < 0 || nanos < 0) {
+    result += "-";
+    seconds = -seconds;
+    nanos = -nanos;
+  }
+  result += StringPrintf("%" GOOGLE_LL_FORMAT "d", seconds);
+  if (nanos != 0) {
+    result += "." + FormatNanos(nanos);
+  }
+  result += "s";
+  return result;
+}
+
+static int64 Pow(int64 x, int y) {
+  int64 result = 1;
+  for (int i = 0; i < y; ++i) {
+    result *= x;
+  }
+  return result;
+}
+
+bool TimeUtil::FromString(const string& value, Duration* duration) {
+  if (value.length() <= 1 || value[value.length() - 1] != 's') {
+    return false;
+  }
+  bool negative = (value[0] == '-');
+  int sign_length = (negative ? 1 : 0);
+  // Parse the duration value as two integers rather than a float value
+  // to avoid precision loss.
+  string seconds_part, nanos_part;
+  size_t pos = value.find_last_of(".");
+  if (pos == string::npos) {
+    seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
+    nanos_part = "0";
+  } else {
+    seconds_part = value.substr(sign_length, pos - sign_length);
+    nanos_part = value.substr(pos + 1, value.length() - pos - 2);
+  }
+  char* end;
+  int64 seconds = strto64(seconds_part.c_str(), &end, 10);
+  if (end != seconds_part.c_str() + seconds_part.length()) {
+    return false;
+  }
+  int64 nanos = strto64(nanos_part.c_str(), &end, 10);
+  if (end != nanos_part.c_str() + nanos_part.length()) {
+    return false;
+  }
+  nanos = nanos * Pow(10, 9 - nanos_part.length());
+  if (negative) {
+    // If a Duration is negative, both seconds and nanos should be negative.
+    seconds = -seconds;
+    nanos = -nanos;
+  }
+  duration->set_seconds(seconds);
+  duration->set_nanos(static_cast<int32>(nanos));
+  return true;
+}
+
+Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
+  return CreateNormalized<Duration>(nanos / kNanosPerSecond,
+                                    nanos % kNanosPerSecond);
+}
+
+Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
+  return CreateNormalized<Duration>(
+      micros / kMicrosPerSecond,
+      (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
+}
+
+Duration TimeUtil::MillisecondsToDuration(int64 millis) {
+  return CreateNormalized<Duration>(
+      millis / kMillisPerSecond,
+      (millis % kMillisPerSecond) * kNanosPerMillisecond);
+}
+
+Duration TimeUtil::SecondsToDuration(int64 seconds) {
+  return CreateNormalized<Duration>(seconds, 0);
+}
+
+Duration TimeUtil::MinutesToDuration(int64 minutes) {
+  return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
+}
+
+Duration TimeUtil::HoursToDuration(int64 hours) {
+  return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
+}
+
+int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
+  return duration.seconds() * kNanosPerSecond + duration.nanos();
+}
+
+int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
+  return duration.seconds() * kMicrosPerSecond +
+         RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
+}
+
+int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
+  return duration.seconds() * kMillisPerSecond +
+         RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
+}
+
+int64 TimeUtil::DurationToSeconds(const Duration& duration) {
+  return duration.seconds();
+}
+
+int64 TimeUtil::DurationToMinutes(const Duration& duration) {
+  return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
+}
+
+int64 TimeUtil::DurationToHours(const Duration& duration) {
+  return RoundTowardZero(duration.seconds(), kSecondsPerHour);
+}
+
+Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
+  return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
+                                     nanos % kNanosPerSecond);
+}
+
+Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
+  return CreateNormalized<Timestamp>(
+      micros / kMicrosPerSecond,
+      micros % kMicrosPerSecond * kNanosPerMicrosecond);
+}
+
+Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
+  return CreateNormalized<Timestamp>(
+      millis / kMillisPerSecond,
+      millis % kMillisPerSecond * kNanosPerMillisecond);
+}
+
+Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
+  return CreateNormalized<Timestamp>(seconds, 0);
+}
+
+int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
+  return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
+}
+
+int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
+  return timestamp.seconds() * kMicrosPerSecond +
+         RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
+}
+
+int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
+  return timestamp.seconds() * kMillisPerSecond +
+         RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
+}
+
+int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
+  return timestamp.seconds();
+}
+
+Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
+  return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
+}
+
+time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
+  return static_cast<time_t>(value.seconds());
+}
+
+Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
+  return CreateNormalized<Timestamp>(value.tv_sec,
+                                     value.tv_usec * kNanosPerMicrosecond);
+}
+
+timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
+  timeval result;
+  result.tv_sec = value.seconds();
+  result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
+  return result;
+}
+
+Duration TimeUtil::TimevalToDuration(const timeval& value) {
+  return CreateNormalized<Duration>(value.tv_sec,
+                                    value.tv_usec * kNanosPerMicrosecond);
+}
+
+timeval TimeUtil::DurationToTimeval(const Duration& value) {
+  timeval result;
+  result.tv_sec = value.seconds();
+  result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
+  // timeval.tv_usec's range is [0, 1000000)
+  if (result.tv_usec < 0) {
+    result.tv_sec -= 1;
+    result.tv_usec += kMicrosPerSecond;
+  }
+  return result;
+}
+
+}  // namespace util
+}  // namespace protobuf
+
+
+namespace protobuf {
+namespace {
+using google::protobuf::util::kNanosPerSecond;
+using google::protobuf::util::CreateNormalized;
+
+// Convert a Timestamp to uint128.
+void ToUint128(const Timestamp& value, uint128* result, bool* negative) {
+  if (value.seconds() < 0) {
+    *negative = true;
+    *result = static_cast<uint64>(-value.seconds());
+    *result = *result * kNanosPerSecond - static_cast<uint32>(value.nanos());
+  } else {
+    *negative = false;
+    *result = static_cast<uint64>(value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+  }
+}
+
+// Convert a Duration to uint128.
+void ToUint128(const Duration& value, uint128* result, bool* negative) {
+  if (value.seconds() < 0 || value.nanos() < 0) {
+    *negative = true;
+    *result = static_cast<uint64>(-value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
+  } else {
+    *negative = false;
+    *result = static_cast<uint64>(value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+  }
+}
+
+void ToTimestamp(const uint128& value, bool negative, Timestamp* timestamp) {
+  int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
+  int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+  if (negative) {
+    seconds = -seconds;
+    nanos = -nanos;
+    if (nanos < 0) {
+      nanos += kNanosPerSecond;
+      seconds -= 1;
+    }
+  }
+  timestamp->set_seconds(seconds);
+  timestamp->set_nanos(nanos);
+}
+
+void ToDuration(const uint128& value, bool negative, Duration* duration) {
+  int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
+  int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+  if (negative) {
+    seconds = -seconds;
+    nanos = -nanos;
+  }
+  duration->set_seconds(seconds);
+  duration->set_nanos(nanos);
+}
+}  // namespace
+
+Duration& operator+=(Duration& d1, const Duration& d2) {
+  d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
+                                  d1.nanos() + d2.nanos());
+  return d1;
+}
+
+Duration& operator-=(Duration& d1, const Duration& d2) {  // NOLINT
+  d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
+                                  d1.nanos() - d2.nanos());
+  return d1;
+}
+
+Duration& operator*=(Duration& d, int64 r) {  // NOLINT
+  bool negative;
+  uint128 value;
+  ToUint128(d, &value, &negative);
+  if (r > 0) {
+    value *= static_cast<uint64>(r);
+  } else {
+    negative = !negative;
+    value *= static_cast<uint64>(-r);
+  }
+  ToDuration(value, negative, &d);
+  return d;
+}
+
+Duration& operator*=(Duration& d, double r) {  // NOLINT
+  double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
+  int64 seconds = static_cast<int64>(result);
+  int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
+  // Note that we normalize here not just because nanos can have a different
+  // sign from seconds but also that nanos can be any arbitrary value when
+  // overflow happens (i.e., the result is a much larger value than what
+  // int64 can represent).
+  d = CreateNormalized<Duration>(seconds, nanos);
+  return d;
+}
+
+Duration& operator/=(Duration& d, int64 r) {  // NOLINT
+  bool negative;
+  uint128 value;
+  ToUint128(d, &value, &negative);
+  if (r > 0) {
+    value /= static_cast<uint64>(r);
+  } else {
+    negative = !negative;
+    value /= static_cast<uint64>(-r);
+  }
+  ToDuration(value, negative, &d);
+  return d;
+}
+
+Duration& operator/=(Duration& d, double r) {  // NOLINT
+  return d *= 1.0 / r;
+}
+
+Duration& operator%=(Duration& d1, const Duration& d2) {  // NOLINT
+  bool negative1, negative2;
+  uint128 value1, value2;
+  ToUint128(d1, &value1, &negative1);
+  ToUint128(d2, &value2, &negative2);
+  uint128 result = value1 % value2;
+  // When negative values are involved in division, we round the division
+  // result towards zero. With this semantics, sign of the remainder is the
+  // same as the dividend. For example:
+  //     -5 / 10    = 0, -5 % 10    = -5
+  //     -5 / (-10) = 0, -5 % (-10) = -5
+  //      5 / (-10) = 0,  5 % (-10) = 5
+  ToDuration(result, negative1, &d1);
+  return d1;
+}
+
+int64 operator/(const Duration& d1, const Duration& d2) {
+  bool negative1, negative2;
+  uint128 value1, value2;
+  ToUint128(d1, &value1, &negative1);
+  ToUint128(d2, &value2, &negative2);
+  int64 result = Uint128Low64(value1 / value2);
+  if (negative1 != negative2) {
+    result = -result;
+  }
+  return result;
+}
+
+Timestamp& operator+=(Timestamp& t, const Duration& d) {  // NOLINT
+  t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
+                                  t.nanos() + d.nanos());
+  return t;
+}
+
+Timestamp& operator-=(Timestamp& t, const Duration& d) {  // NOLINT
+  t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
+                                  t.nanos() - d.nanos());
+  return t;
+}
+
+Duration operator-(const Timestamp& t1, const Timestamp& t2) {
+  return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
+                                    t1.nanos() - t2.nanos());
+}
+}  // namespace protobuf
+
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/time_util.h b/src/third_party/protobuf-3/src/google/protobuf/util/time_util.h
new file mode 100644
index 0000000..1bac089
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/time_util.h
@@ -0,0 +1,293 @@
+// 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_UTIL_TIME_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
+
+#include <ctime>
+#include <ostream>
+#include <string>
+#ifdef _MSC_VER
+#include <winsock2.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/timestamp.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+class LIBPROTOBUF_EXPORT TimeUtil {
+  typedef google::protobuf::Timestamp Timestamp;
+  typedef google::protobuf::Duration Duration;
+
+ public:
+  // The min/max Timestamp/Duration values we support.
+  //
+  // For "0001-01-01T00:00:00Z".
+  static const int64 kTimestampMinSeconds = -62135596800LL;
+  // For "9999-12-31T23:59:59.999999999Z".
+  static const int64 kTimestampMaxSeconds = 253402300799LL;
+  static const int64 kDurationMinSeconds = -315576000000LL;
+  static const int64 kDurationMaxSeconds = 315576000000LL;
+
+  // Converts Timestamp to/from RFC 3339 date string format.
+  // Generated output will always be Z-normalized and uses 3, 6 or 9
+  // fractional digits as required to represent the exact time. When
+  // parsing, any fractional digits (or none) and any offset are
+  // accepted as long as they fit into nano-seconds precision.
+  // Note that Timestamp can only represent time from
+  // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting
+  // a Timestamp outside of this range is undefined behavior.
+  // See https://www.ietf.org/rfc/rfc3339.txt
+  //
+  // Example of generated format:
+  //   "1972-01-01T10:00:20.021Z"
+  //
+  // Example of accepted format:
+  //   "1972-01-01T10:00:20.021-05:00"
+  static string ToString(const Timestamp& timestamp);
+  static bool FromString(const string& value, Timestamp* timestamp);
+
+  // Converts Duration to/from string format. The string format will contains
+  // 3, 6, or 9 fractional digits depending on the precision required to
+  // represent the exact Duration value. For example:
+  //   "1s", "1.010s", "1.000000100s", "-3.100s"
+  // The range that can be represented by Duration is from -315,576,000,000
+  // to +315,576,000,000 inclusive (in seconds).
+  static string ToString(const Duration& duration);
+  static bool FromString(const string& value, Duration* timestamp);
+
+#ifdef GetCurrentTime
+#undef GetCurrentTime  // Visual Studio has macro GetCurrentTime
+#endif
+  // Gets the current UTC time.
+  static Timestamp GetCurrentTime();
+  // Returns the Time representing "1970-01-01 00:00:00".
+  static Timestamp GetEpoch();
+
+  // Converts between Duration and integer types. The behavior is undefined if
+  // the input value is not in the valid range of Duration.
+  static Duration NanosecondsToDuration(int64 nanos);
+  static Duration MicrosecondsToDuration(int64 micros);
+  static Duration MillisecondsToDuration(int64 millis);
+  static Duration SecondsToDuration(int64 seconds);
+  static Duration MinutesToDuration(int64 minutes);
+  static Duration HoursToDuration(int64 hours);
+  // Result will be truncated towards zero. For example, "-1.5s" will be
+  // truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
+  // It's undefined behavior if the input duration is not valid or the result
+  // exceeds the range of int64. A duration is not valid if it's not in the
+  // valid range of Duration, or have an invalid nanos value (i.e., larger
+  // than 999999999, less than -999999999, or have a different sign from the
+  // seconds part).
+  static int64 DurationToNanoseconds(const Duration& duration);
+  static int64 DurationToMicroseconds(const Duration& duration);
+  static int64 DurationToMilliseconds(const Duration& duration);
+  static int64 DurationToSeconds(const Duration& duration);
+  static int64 DurationToMinutes(const Duration& duration);
+  static int64 DurationToHours(const Duration& duration);
+  // Creates Timestamp from integer types. The integer value indicates the
+  // time elapsed from Epoch time. The behavior is undefined if the input
+  // value is not in the valid range of Timestamp.
+  static Timestamp NanosecondsToTimestamp(int64 nanos);
+  static Timestamp MicrosecondsToTimestamp(int64 micros);
+  static Timestamp MillisecondsToTimestamp(int64 millis);
+  static Timestamp SecondsToTimestamp(int64 seconds);
+  // Result will be truncated down to the nearest integer value. For example,
+  // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
+  // and TimestampToSeconds() returns -1. It's undefined behavior if the input
+  // Timestamp is not valid (i.e., its seconds part or nanos part does not fall
+  // in the valid range) or the return value doesn't fit into int64.
+  static int64 TimestampToNanoseconds(const Timestamp& timestamp);
+  static int64 TimestampToMicroseconds(const Timestamp& timestamp);
+  static int64 TimestampToMilliseconds(const Timestamp& timestamp);
+  static int64 TimestampToSeconds(const Timestamp& timestamp);
+
+  // Conversion to/from other time/date types. Note that these types may
+  // have a different precision and time range from Timestamp/Duration.
+  // When converting to a lower precision type, the value will be truncated
+  // to the nearest value that can be represented. If the value is
+  // out of the range of the result type, the return value is undefined.
+  //
+  // Conversion to/from time_t
+  static Timestamp TimeTToTimestamp(time_t value);
+  static time_t TimestampToTimeT(const Timestamp& value);
+
+  // Conversion to/from timeval
+  static Timestamp TimevalToTimestamp(const timeval& value);
+  static timeval TimestampToTimeval(const Timestamp& value);
+  static Duration TimevalToDuration(const timeval& value);
+  static timeval DurationToTimeval(const Duration& value);
+};
+
+}  // namespace util
+}  // namespace protobuf
+
+
+namespace protobuf {
+// Overloaded operators for Duration.
+//
+// Assignment operators.
+LIBPROTOBUF_EXPORT Duration& operator+=(Duration& d1, const Duration& d2);  // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator-=(Duration& d1, const Duration& d2);  // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator*=(Duration& d, int64 r);  // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator*=(Duration& d, double r);  // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator/=(Duration& d, int64 r);  // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator/=(Duration& d, double r);  // NOLINT
+// Overload for other integer types.
+template <typename T>
+Duration& operator*=(Duration& d, T r) {  // NOLINT
+  int64 x = r;
+  return d *= x;
+}
+template <typename T>
+Duration& operator/=(Duration& d, T r) {  // NOLINT
+  int64 x = r;
+  return d /= x;
+}
+LIBPROTOBUF_EXPORT Duration& operator%=(Duration& d1, const Duration& d2);  // NOLINT
+// Relational operators.
+inline bool operator<(const Duration& d1, const Duration& d2) {
+  if (d1.seconds() == d2.seconds()) {
+    return d1.nanos() < d2.nanos();
+  }
+  return d1.seconds() < d2.seconds();
+}
+inline bool operator>(const Duration& d1, const Duration& d2) {
+  return d2 < d1;
+}
+inline bool operator>=(const Duration& d1, const Duration& d2) {
+  return !(d1 < d2);
+}
+inline bool operator<=(const Duration& d1, const Duration& d2) {
+  return !(d2 < d1);
+}
+inline bool operator==(const Duration& d1, const Duration& d2) {
+  return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos();
+}
+inline bool operator!=(const Duration& d1, const Duration& d2) {
+  return !(d1 == d2);
+}
+// Additive operators
+inline Duration operator-(const Duration& d) {
+  Duration result;
+  result.set_seconds(-d.seconds());
+  result.set_nanos(-d.nanos());
+  return result;
+}
+inline Duration operator+(const Duration& d1, const Duration& d2) {
+  Duration result = d1;
+  return result += d2;
+}
+inline Duration operator-(const Duration& d1, const Duration& d2) {
+  Duration result = d1;
+  return result -= d2;
+}
+// Multiplicative operators
+template<typename T>
+inline Duration operator*(Duration d, T r) {
+  return d *= r;
+}
+template<typename T>
+inline Duration operator*(T r, Duration d) {
+  return d *= r;
+}
+template<typename T>
+inline Duration operator/(Duration d, T r) {
+  return d /= r;
+}
+LIBPROTOBUF_EXPORT int64 operator/(const Duration& d1, const Duration& d2);
+
+inline Duration operator%(const Duration& d1, const Duration& d2) {
+  Duration result = d1;
+  return result %= d2;
+}
+
+inline ostream& operator<<(ostream& out, const Duration& d) {
+  out << google::protobuf::util::TimeUtil::ToString(d);
+  return out;
+}
+
+// Overloaded operators for Timestamp
+//
+// Assignement operators.
+LIBPROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t, const Duration& d);  // NOLINT
+LIBPROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t, const Duration& d);  // NOLINT
+// Relational operators.
+inline bool operator<(const Timestamp& t1, const Timestamp& t2) {
+  if (t1.seconds() == t2.seconds()) {
+    return t1.nanos() < t2.nanos();
+  }
+  return t1.seconds() < t2.seconds();
+}
+inline bool operator>(const Timestamp& t1, const Timestamp& t2) {
+  return t2 < t1;
+}
+inline bool operator>=(const Timestamp& t1, const Timestamp& t2) {
+  return !(t1 < t2);
+}
+inline bool operator<=(const Timestamp& t1, const Timestamp& t2) {
+  return !(t2 < t1);
+}
+inline bool operator==(const Timestamp& t1, const Timestamp& t2) {
+  return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos();
+}
+inline bool operator!=(const Timestamp& t1, const Timestamp& t2) {
+  return !(t1 == t2);
+}
+// Additive operators.
+inline Timestamp operator+(const Timestamp& t, const Duration& d) {
+  Timestamp result = t;
+  return result += d;
+}
+inline Timestamp operator+(const Duration& d, const Timestamp& t) {
+  Timestamp result = t;
+  return result += d;
+}
+inline Timestamp operator-(const Timestamp& t, const Duration& d) {
+  Timestamp result = t;
+  return result -= d;
+}
+LIBPROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2);
+
+inline ostream& operator<<(ostream& out, const Timestamp& t) {
+  out << google::protobuf::util::TimeUtil::ToString(t);
+  return out;
+}
+
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/time_util_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/time_util_test.cc
new file mode 100644
index 0000000..285740a
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/time_util_test.cc
@@ -0,0 +1,380 @@
+// 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.
+
+#include <google/protobuf/util/time_util.h>
+
+#include <ctime>
+
+#include <google/protobuf/timestamp.pb.h>
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::Timestamp;
+using google::protobuf::Duration;
+
+namespace {
+
+TEST(TimeUtilTest, TimestampStringFormat) {
+  Timestamp begin, end;
+  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+  EXPECT_EQ(TimeUtil::kTimestampMinSeconds, begin.seconds());
+  EXPECT_EQ(0, begin.nanos());
+  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+  EXPECT_EQ(TimeUtil::kTimestampMaxSeconds, end.seconds());
+  EXPECT_EQ(999999999, end.nanos());
+  EXPECT_EQ("0001-01-01T00:00:00Z", TimeUtil::ToString(begin));
+  EXPECT_EQ("9999-12-31T23:59:59.999999999Z", TimeUtil::ToString(end));
+
+  // Test negative timestamps.
+  Timestamp time = TimeUtil::NanosecondsToTimestamp(-1);
+  EXPECT_EQ(-1, time.seconds());
+  // Timestamp's nano part is always non-negative.
+  EXPECT_EQ(999999999, time.nanos());
+  EXPECT_EQ("1969-12-31T23:59:59.999999999Z", TimeUtil::ToString(time));
+
+  // Generated output should contain 3, 6, or 9 fractional digits.
+  EXPECT_EQ("1970-01-01T00:00:00Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(0)));
+  EXPECT_EQ("1970-01-01T00:00:00.010Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000000)));
+  EXPECT_EQ("1970-01-01T00:00:00.000010Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000)));
+  EXPECT_EQ("1970-01-01T00:00:00.000000010Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10)));
+
+  // Parsing accepts an fractional digits as long as they fit into nano
+  // precision.
+  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.1Z", &time));
+  EXPECT_EQ(100000000, TimeUtil::TimestampToNanoseconds(time));
+  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0001Z", &time));
+  EXPECT_EQ(100000, TimeUtil::TimestampToNanoseconds(time));
+  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0000001Z", &time));
+  EXPECT_EQ(100, TimeUtil::TimestampToNanoseconds(time));
+
+  // Also accpets offsets.
+  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00-08:00", &time));
+  EXPECT_EQ(8 * 3600, TimeUtil::TimestampToSeconds(time));
+}
+
+TEST(TimeUtilTest, DurationStringFormat) {
+  Timestamp begin, end;
+  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+
+  EXPECT_EQ("315537897599.999999999s", TimeUtil::ToString(end - begin));
+  EXPECT_EQ(999999999, (end - begin).nanos());
+  EXPECT_EQ("-315537897599.999999999s", TimeUtil::ToString(begin - end));
+  EXPECT_EQ(-999999999, (begin - end).nanos());
+
+  // Generated output should contain 3, 6, or 9 fractional digits.
+  EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
+  EXPECT_EQ("0.010s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(10)));
+  EXPECT_EQ("0.000010s",
+            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(10)));
+  EXPECT_EQ("0.000000010s",
+            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(10)));
+
+  // Parsing accepts an fractional digits as long as they fit into nano
+  // precision.
+  Duration d;
+  EXPECT_TRUE(TimeUtil::FromString("0.1s", &d));
+  EXPECT_EQ(100, TimeUtil::DurationToMilliseconds(d));
+  EXPECT_TRUE(TimeUtil::FromString("0.0001s", &d));
+  EXPECT_EQ(100, TimeUtil::DurationToMicroseconds(d));
+  EXPECT_TRUE(TimeUtil::FromString("0.0000001s", &d));
+  EXPECT_EQ(100, TimeUtil::DurationToNanoseconds(d));
+
+  // Duration must support range from -315,576,000,000s to +315576000000s
+  // which includes negative values.
+  EXPECT_TRUE(TimeUtil::FromString("315576000000.999999999s", &d));
+  EXPECT_EQ(315576000000LL, d.seconds());
+  EXPECT_EQ(999999999, d.nanos());
+  EXPECT_TRUE(TimeUtil::FromString("-315576000000.999999999s", &d));
+  EXPECT_EQ(-315576000000LL, d.seconds());
+  EXPECT_EQ(-999999999, d.nanos());
+}
+
+TEST(TimeUtilTest, GetEpoch) {
+  EXPECT_EQ(0, TimeUtil::TimestampToNanoseconds(TimeUtil::GetEpoch()));
+}
+
+TEST(TimeUtilTest, DurationIntegerConversion) {
+  EXPECT_EQ("0.000000001s",
+            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(1)));
+  EXPECT_EQ("-0.000000001s",
+            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(-1)));
+  EXPECT_EQ("0.000001s",
+            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(1)));
+  EXPECT_EQ("-0.000001s",
+            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(-1)));
+  EXPECT_EQ("0.001s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(1)));
+  EXPECT_EQ("-0.001s",
+            TimeUtil::ToString(TimeUtil::MillisecondsToDuration(-1)));
+  EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
+  EXPECT_EQ("-1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(-1)));
+  EXPECT_EQ("60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(1)));
+  EXPECT_EQ("-60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(-1)));
+  EXPECT_EQ("3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(1)));
+  EXPECT_EQ("-3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(-1)));
+
+  EXPECT_EQ(
+      1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(1)));
+  EXPECT_EQ(
+      -1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(-1)));
+  EXPECT_EQ(
+      1, TimeUtil::DurationToMicroseconds(TimeUtil::MicrosecondsToDuration(1)));
+  EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
+                    TimeUtil::MicrosecondsToDuration(-1)));
+  EXPECT_EQ(
+      1, TimeUtil::DurationToMilliseconds(TimeUtil::MillisecondsToDuration(1)));
+  EXPECT_EQ(-1, TimeUtil::DurationToMilliseconds(
+                    TimeUtil::MillisecondsToDuration(-1)));
+  EXPECT_EQ(1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(1)));
+  EXPECT_EQ(-1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(-1)));
+  EXPECT_EQ(1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(1)));
+  EXPECT_EQ(-1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(-1)));
+  EXPECT_EQ(1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(1)));
+  EXPECT_EQ(-1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(-1)));
+
+  // Test truncation behavior.
+  EXPECT_EQ(1, TimeUtil::DurationToMicroseconds(
+                   TimeUtil::NanosecondsToDuration(1999)));
+  // For negative values, Duration will be rounded towards 0.
+  EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
+                    TimeUtil::NanosecondsToDuration(-1999)));
+}
+
+TEST(TestUtilTest, TimestampIntegerConversion) {
+  EXPECT_EQ("1970-01-01T00:00:00.000000001Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(1)));
+  EXPECT_EQ("1969-12-31T23:59:59.999999999Z",
+            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(-1)));
+  EXPECT_EQ("1970-01-01T00:00:00.000001Z",
+            TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(1)));
+  EXPECT_EQ("1969-12-31T23:59:59.999999Z",
+            TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(-1)));
+  EXPECT_EQ("1970-01-01T00:00:00.001Z",
+            TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(1)));
+  EXPECT_EQ("1969-12-31T23:59:59.999Z",
+            TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(-1)));
+  EXPECT_EQ("1970-01-01T00:00:01Z",
+            TimeUtil::ToString(TimeUtil::SecondsToTimestamp(1)));
+  EXPECT_EQ("1969-12-31T23:59:59Z",
+            TimeUtil::ToString(TimeUtil::SecondsToTimestamp(-1)));
+
+  EXPECT_EQ(
+      1, TimeUtil::TimestampToNanoseconds(TimeUtil::NanosecondsToTimestamp(1)));
+  EXPECT_EQ(-1, TimeUtil::TimestampToNanoseconds(
+                    TimeUtil::NanosecondsToTimestamp(-1)));
+  EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
+                   TimeUtil::MicrosecondsToTimestamp(1)));
+  EXPECT_EQ(-1, TimeUtil::TimestampToMicroseconds(
+                    TimeUtil::MicrosecondsToTimestamp(-1)));
+  EXPECT_EQ(1, TimeUtil::TimestampToMilliseconds(
+                   TimeUtil::MillisecondsToTimestamp(1)));
+  EXPECT_EQ(-1, TimeUtil::TimestampToMilliseconds(
+                    TimeUtil::MillisecondsToTimestamp(-1)));
+  EXPECT_EQ(1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(1)));
+  EXPECT_EQ(-1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(-1)));
+
+  // Test truncation behavior.
+  EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
+                   TimeUtil::NanosecondsToTimestamp(1999)));
+  // For negative values, Timestamp will be rounded down.
+  // For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds
+  // will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than
+  // "1970-01-01T00:00:00Z" (i.e., 0s).
+  EXPECT_EQ(-2, TimeUtil::TimestampToMicroseconds(
+                    TimeUtil::NanosecondsToTimestamp(-1999)));
+}
+
+TEST(TimeUtilTest, TimeTConversion) {
+  time_t value = time(NULL);
+  EXPECT_EQ(value,
+            TimeUtil::TimestampToTimeT(TimeUtil::TimeTToTimestamp(value)));
+  EXPECT_EQ(
+      1, TimeUtil::TimestampToTimeT(TimeUtil::MillisecondsToTimestamp(1999)));
+}
+
+TEST(TimeUtilTest, TimevalConversion) {
+  timeval value = TimeUtil::TimestampToTimeval(
+      TimeUtil::NanosecondsToTimestamp(1999999999));
+  EXPECT_EQ(1, value.tv_sec);
+  EXPECT_EQ(999999, value.tv_usec);
+  value = TimeUtil::TimestampToTimeval(
+      TimeUtil::NanosecondsToTimestamp(-1999999999));
+  EXPECT_EQ(-2, value.tv_sec);
+  EXPECT_EQ(0, value.tv_usec);
+
+  value =
+      TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(1999999999));
+  EXPECT_EQ(1, value.tv_sec);
+  EXPECT_EQ(999999, value.tv_usec);
+  value =
+      TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(-1999999999));
+  EXPECT_EQ(-2, value.tv_sec);
+  EXPECT_EQ(1, value.tv_usec);
+}
+
+TEST(TimeUtilTest, DurationOperators) {
+  Duration one_second = TimeUtil::SecondsToDuration(1);
+  Duration one_nano = TimeUtil::NanosecondsToDuration(1);
+
+  // Test +/-
+  Duration a = one_second;
+  a += one_second;
+  a -= one_nano;
+  EXPECT_EQ("1.999999999s", TimeUtil::ToString(a));
+  Duration b = -a;
+  EXPECT_EQ("-1.999999999s", TimeUtil::ToString(b));
+  EXPECT_EQ("3.999999998s", TimeUtil::ToString(a + a));
+  EXPECT_EQ("0s", TimeUtil::ToString(a + b));
+  EXPECT_EQ("0s", TimeUtil::ToString(b + a));
+  EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b + b));
+  EXPECT_EQ("3.999999998s", TimeUtil::ToString(a - b));
+  EXPECT_EQ("0s", TimeUtil::ToString(a - a));
+  EXPECT_EQ("0s", TimeUtil::ToString(b - b));
+  EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b - a));
+
+  // Test *
+  EXPECT_EQ(a + a, a * 2);
+  EXPECT_EQ(b + b, a * (-2));
+  EXPECT_EQ(b + b, b * 2);
+  EXPECT_EQ(a + a, b * (-2));
+  EXPECT_EQ("0.999999999s", TimeUtil::ToString(a * 0.5));
+  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b * 0.5));
+  // Multiplication should not overflow if the result fits into the supported
+  // range of Duration (intermediate result may be larger than int64).
+  EXPECT_EQ("315575999684.424s",
+            TimeUtil::ToString((one_second - one_nano) * 315576000000LL));
+  EXPECT_EQ("-315575999684.424s",
+            TimeUtil::ToString((one_nano - one_second) * 315576000000LL));
+  EXPECT_EQ("-315575999684.424s",
+            TimeUtil::ToString((one_second - one_nano) * (-315576000000LL)));
+
+  // Test / and %
+  EXPECT_EQ("0.999999999s", TimeUtil::ToString(a / 2));
+  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b / 2));
+  Duration large = TimeUtil::SecondsToDuration(315576000000LL) - one_nano;
+  // We have to handle division with values beyond 64 bits.
+  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / 315576000000LL));
+  EXPECT_EQ("-0.999999999s", TimeUtil::ToString((-large) / 315576000000LL));
+  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(large / (-315576000000LL)));
+  Duration large2 = large + one_nano;
+  EXPECT_EQ(large, large % large2);
+  EXPECT_EQ(-large, (-large) % large2);
+  EXPECT_EQ(large, large % (-large2));
+  EXPECT_EQ(one_nano, large2 % large);
+  EXPECT_EQ(-one_nano, (-large2) % large);
+  EXPECT_EQ(one_nano, large2 % (-large));
+  // Some corner cases about negative values.
+  //
+  // (-5) / 2 = -2, remainder = -1
+  // (-5) / (-2) = 2, remainder = -1
+  a = TimeUtil::NanosecondsToDuration(-5);
+  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-2), a / 2);
+  EXPECT_EQ(TimeUtil::NanosecondsToDuration(2), a / (-2));
+  b = TimeUtil::NanosecondsToDuration(2);
+  EXPECT_EQ(-2, a / b);
+  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % b);
+  EXPECT_EQ(2, a / (-b));
+  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % (-b));
+
+  // Test relational operators.
+  EXPECT_TRUE(one_nano < one_second);
+  EXPECT_FALSE(one_second < one_second);
+  EXPECT_FALSE(one_second < one_nano);
+  EXPECT_FALSE(-one_nano < -one_second);
+  EXPECT_FALSE(-one_second < -one_second);
+  EXPECT_TRUE(-one_second < -one_nano);
+  EXPECT_TRUE(-one_nano < one_nano);
+  EXPECT_FALSE(one_nano < -one_nano);
+
+  EXPECT_FALSE(one_nano > one_second);
+  EXPECT_FALSE(one_nano > one_nano);
+  EXPECT_TRUE(one_second > one_nano);
+
+  EXPECT_FALSE(one_nano >= one_second);
+  EXPECT_TRUE(one_nano >= one_nano);
+  EXPECT_TRUE(one_second >= one_nano);
+
+  EXPECT_TRUE(one_nano <= one_second);
+  EXPECT_TRUE(one_nano <= one_nano);
+  EXPECT_FALSE(one_second <= one_nano);
+
+  EXPECT_TRUE(one_nano == one_nano);
+  EXPECT_FALSE(one_nano == one_second);
+
+  EXPECT_FALSE(one_nano != one_nano);
+  EXPECT_TRUE(one_nano != one_second);
+}
+
+TEST(TimeUtilTest, TimestampOperators) {
+  Timestamp begin, end;
+  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+  Duration d = end - begin;
+  EXPECT_TRUE(end == begin + d);
+  EXPECT_TRUE(end == d + begin);
+  EXPECT_TRUE(begin == end - d);
+
+  // Test relational operators
+  Timestamp t1 = begin + d / 4;
+  Timestamp t2 = end - d / 4;
+  EXPECT_TRUE(t1 < t2);
+  EXPECT_FALSE(t1 < t1);
+  EXPECT_FALSE(t2 < t1);
+  EXPECT_FALSE(t1 > t2);
+  EXPECT_FALSE(t1 > t1);
+  EXPECT_TRUE(t2 > t1);
+  EXPECT_FALSE(t1 >= t2);
+  EXPECT_TRUE(t1 >= t1);
+  EXPECT_TRUE(t2 >= t1);
+  EXPECT_TRUE(t1 <= t2);
+  EXPECT_TRUE(t1 <= t1);
+  EXPECT_FALSE(t2 <= t1);
+
+  EXPECT_FALSE(t1 == t2);
+  EXPECT_TRUE(t1 == t1);
+  EXPECT_FALSE(t2 == t1);
+  EXPECT_TRUE(t1 != t2);
+  EXPECT_FALSE(t1 != t1);
+  EXPECT_TRUE(t2 != t1);
+}
+
+}  // namespace
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver.h b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver.h
new file mode 100644
index 0000000..77d4416
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver.h
@@ -0,0 +1,75 @@
+// 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_UTIL_TYPE_RESOLVER_H__
+#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
+
+
+namespace google {
+namespace protobuf {
+class Type;
+class Enum;
+}  // namespace protobuf
+
+
+namespace protobuf {
+class DescriptorPool;
+namespace util {
+
+// Abstract interface for a type resovler.
+//
+// Implementations of this interface must be thread-safe.
+class LIBPROTOBUF_EXPORT TypeResolver {
+ public:
+  TypeResolver() {}
+  virtual ~TypeResolver() {}
+
+  // Resolves a type url for a message type.
+  virtual util::Status ResolveMessageType(
+      const string& type_url, google::protobuf::Type* message_type) = 0;
+
+  // Resolves a type url for an enum type.
+  virtual util::Status ResolveEnumType(const string& type_url,
+                                         google::protobuf::Enum* enum_type) = 0;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
+};
+
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.cc b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.cc
new file mode 100644
index 0000000..9639390
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.cc
@@ -0,0 +1,259 @@
+// 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.
+
+#include <google/protobuf/util/type_resolver_util.h>
+
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+using google::protobuf::BoolValue;
+using google::protobuf::Enum;
+using google::protobuf::EnumValue;
+using google::protobuf::Field;
+using google::protobuf::Option;
+using google::protobuf::Type;
+
+using util::Status;
+using util::error::INVALID_ARGUMENT;
+using util::error::NOT_FOUND;
+
+bool SplitTypeUrl(const string& type_url, string* url_prefix,
+                  string* message_name) {
+  size_t pos = type_url.find_last_of("/");
+  if (pos == string::npos) {
+    return false;
+  }
+  *url_prefix = type_url.substr(0, pos);
+  *message_name = type_url.substr(pos + 1);
+  return true;
+}
+
+class DescriptorPoolTypeResolver : public TypeResolver {
+ public:
+  DescriptorPoolTypeResolver(const string& url_prefix,
+                             const DescriptorPool* pool)
+      : url_prefix_(url_prefix), pool_(pool) {}
+
+  Status ResolveMessageType(const string& type_url, Type* type) {
+    string url_prefix, message_name;
+    if (!SplitTypeUrl(type_url, &url_prefix, &message_name) ||
+        url_prefix != url_prefix_) {
+      return Status(INVALID_ARGUMENT,
+                    StrCat("Invalid type URL, type URLs must be of the form '",
+                           url_prefix_, "/<typename>', got: ", type_url));
+    }
+    if (url_prefix != url_prefix_) {
+      return Status(INVALID_ARGUMENT,
+                    "Cannot resolve types from URL: " + url_prefix);
+    }
+    const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name);
+    if (descriptor == NULL) {
+      return Status(NOT_FOUND,
+                    "Invalid type URL, unknown type: " + message_name);
+    }
+    ConvertDescriptor(descriptor, type);
+    return Status();
+  }
+
+  Status ResolveEnumType(const string& type_url, Enum* enum_type) {
+    string url_prefix, type_name;
+    if (!SplitTypeUrl(type_url, &url_prefix, &type_name) ||
+        url_prefix != url_prefix_) {
+      return Status(INVALID_ARGUMENT,
+                    StrCat("Invalid type URL, type URLs must be of the form '",
+                           url_prefix_, "/<typename>', got: ", type_url));
+    }
+    if (url_prefix != url_prefix_) {
+      return Status(INVALID_ARGUMENT,
+                    "Cannot resolve types from URL: " + url_prefix);
+    }
+    const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
+    if (descriptor == NULL) {
+      return Status(NOT_FOUND, "Invalid type URL, unknown type: " + type_name);
+    }
+    ConvertEnumDescriptor(descriptor, enum_type);
+    return Status();
+  }
+
+ private:
+  void ConvertDescriptor(const Descriptor* descriptor, Type* type) {
+    type->Clear();
+    type->set_name(descriptor->full_name());
+    for (int i = 0; i < descriptor->field_count(); ++i) {
+      const FieldDescriptor* field = descriptor->field(i);
+      if (field->type() == FieldDescriptor::TYPE_GROUP) {
+        // Group fields cannot be represented with Type. We discard them.
+        continue;
+      }
+      ConvertFieldDescriptor(descriptor->field(i), type->add_fields());
+    }
+    for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
+      type->add_oneofs(descriptor->oneof_decl(i)->name());
+    }
+    type->mutable_source_context()->set_file_name(descriptor->file()->name());
+    ConvertMessageOptions(descriptor->options(), type->mutable_options());
+  }
+
+  void ConvertMessageOptions(const MessageOptions& options,
+                             RepeatedPtrField<Option>* output) {
+    if (options.map_entry()) {
+      Option* option = output->Add();
+      option->set_name("map_entry");
+      BoolValue value;
+      value.set_value(true);
+      option->mutable_value()->PackFrom(value);
+    }
+
+    // TODO(xiaofeng): Set other "options"?
+  }
+
+  void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) {
+    field->set_kind(static_cast<Field::Kind>(descriptor->type()));
+    switch (descriptor->label()) {
+      case FieldDescriptor::LABEL_OPTIONAL:
+        field->set_cardinality(Field::CARDINALITY_OPTIONAL);
+        break;
+      case FieldDescriptor::LABEL_REPEATED:
+        field->set_cardinality(Field::CARDINALITY_REPEATED);
+        break;
+      case FieldDescriptor::LABEL_REQUIRED:
+        field->set_cardinality(Field::CARDINALITY_REQUIRED);
+        break;
+    }
+    field->set_number(descriptor->number());
+    field->set_name(descriptor->name());
+    field->set_json_name(descriptor->json_name());
+    if (descriptor->has_default_value()) {
+      field->set_default_value(DefaultValueAsString(descriptor));
+    }
+    if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
+      field->set_type_url(GetTypeUrl(descriptor->message_type()));
+    } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+      field->set_type_url(GetTypeUrl(descriptor->enum_type()));
+    }
+    if (descriptor->containing_oneof() != NULL) {
+      field->set_oneof_index(descriptor->containing_oneof()->index() + 1);
+    }
+    if (descriptor->is_packed()) {
+      field->set_packed(true);
+    }
+
+    // TODO(xiaofeng): Set other field "options"?
+  }
+
+  void ConvertEnumDescriptor(const EnumDescriptor* descriptor,
+                             Enum* enum_type) {
+    enum_type->Clear();
+    enum_type->set_name(descriptor->full_name());
+    enum_type->mutable_source_context()->set_file_name(
+        descriptor->file()->name());
+    for (int i = 0; i < descriptor->value_count(); ++i) {
+      const EnumValueDescriptor* value_descriptor = descriptor->value(i);
+      EnumValue* value = enum_type->mutable_enumvalue()->Add();
+      value->set_name(value_descriptor->name());
+      value->set_number(value_descriptor->number());
+
+      // TODO(xiaofeng): Set EnumValue options.
+    }
+    // TODO(xiaofeng): Set Enum "options".
+  }
+
+  string GetTypeUrl(const Descriptor* descriptor) {
+    return url_prefix_ + "/" + descriptor->full_name();
+  }
+
+  string GetTypeUrl(const EnumDescriptor* descriptor) {
+    return url_prefix_ + "/" + descriptor->full_name();
+  }
+
+  string DefaultValueAsString(const FieldDescriptor* descriptor) {
+    switch (descriptor->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_INT32:
+        return SimpleItoa(descriptor->default_value_int32());
+        break;
+      case FieldDescriptor::CPPTYPE_INT64:
+        return SimpleItoa(descriptor->default_value_int64());
+        break;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return SimpleItoa(descriptor->default_value_uint32());
+        break;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return SimpleItoa(descriptor->default_value_uint64());
+        break;
+      case FieldDescriptor::CPPTYPE_FLOAT:
+        return SimpleFtoa(descriptor->default_value_float());
+        break;
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+        return SimpleDtoa(descriptor->default_value_double());
+        break;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return descriptor->default_value_bool() ? "true" : "false";
+        break;
+      case FieldDescriptor::CPPTYPE_STRING:
+        if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+          return CEscape(descriptor->default_value_string());
+        } else {
+          return descriptor->default_value_string();
+        }
+        break;
+      case FieldDescriptor::CPPTYPE_ENUM:
+        return descriptor->default_value_enum()->name();
+        break;
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
+        break;
+    }
+    return "";
+  }
+
+  string url_prefix_;
+  const DescriptorPool* pool_;
+};
+
+}  // namespace
+
+TypeResolver* NewTypeResolverForDescriptorPool(const string& url_prefix,
+                                               const DescriptorPool* pool) {
+  return new DescriptorPoolTypeResolver(url_prefix, pool);
+}
+
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.h b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.h
new file mode 100644
index 0000000..c0ef3c1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util.h
@@ -0,0 +1,52 @@
+// 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_UTIL_TYPE_RESOLVER_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+class DescriptorPool;
+namespace util {
+class TypeResolver;
+
+// Creates a TypeResolver that serves type information in the given descriptor
+// pool. Caller takes ownership of the returned TypeResolver.
+LIBPROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
+    const string& url_prefix, const DescriptorPool* pool);
+
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util_test.cc b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util_test.cc
new file mode 100644
index 0000000..8a0bf65
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/util/type_resolver_util_test.cc
@@ -0,0 +1,352 @@
+// 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.
+
+#include <google/protobuf/util/type_resolver_util.h>
+
+#include <limits>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/util/json_format_proto3.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+using google::protobuf::Type;
+using google::protobuf::Enum;
+using google::protobuf::Field;
+using google::protobuf::Option;
+using google::protobuf::BoolValue;
+
+static const char kUrlPrefix[] = "type.googleapis.com";
+
+class DescriptorPoolTypeResolverTest : public testing::Test {
+ public:
+  DescriptorPoolTypeResolverTest() {
+    resolver_.reset(NewTypeResolverForDescriptorPool(
+        kUrlPrefix, DescriptorPool::generated_pool()));
+  }
+
+  const Field* FindField(const Type& type, const string& name) {
+    for (int i = 0; i < type.fields_size(); ++i) {
+      const Field& field = type.fields(i);
+      if (field.name() == name) {
+        return &field;
+      }
+    }
+    return NULL;
+  }
+
+  bool HasField(const Type& type, const string& name) {
+    return FindField(type, name) != NULL;
+  }
+
+  bool HasField(const Type& type, Field::Cardinality cardinality,
+                Field::Kind kind, const string& name, int number) {
+    const Field* field = FindField(type, name);
+    if (field == NULL) {
+      return false;
+    }
+    return field->cardinality() == cardinality &&
+        field->kind() == kind && field->number() == number;
+  }
+
+  bool CheckFieldTypeUrl(const Type& type, const string& name,
+                         const string& type_url) {
+    const Field* field = FindField(type, name);
+    if (field == NULL) {
+      return false;
+    }
+    return field->type_url() == type_url;
+  }
+
+  bool FieldInOneof(const Type& type, const string& name,
+                    const string& oneof_name) {
+    const Field* field = FindField(type, name);
+    if (field == NULL || field->oneof_index() <= 0 ||
+        field->oneof_index() > type.oneofs_size()) {
+      return false;
+    }
+    return type.oneofs(field->oneof_index() - 1) == oneof_name;
+  }
+
+  bool IsPacked(const Type& type, const string& name) {
+    const Field* field = FindField(type, name);
+    if (field == NULL) {
+      return false;
+    }
+    return field->packed();
+  }
+
+  bool EnumHasValue(const Enum& type, const string& name, int number) {
+    for (int i = 0; i < type.enumvalue_size(); ++i) {
+      if (type.enumvalue(i).name() == name &&
+          type.enumvalue(i).number() == number) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool HasBoolOption(const RepeatedPtrField<Option>& options,
+                     const string& name, bool value) {
+    for (int i = 0; i < options.size(); ++i) {
+      const Option& option = options.Get(i);
+      if (option.name() == name) {
+        BoolValue bool_value;
+        if (option.value().UnpackTo(&bool_value) &&
+            bool_value.value() == value) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  string GetTypeUrl(string full_name) {
+    return kUrlPrefix + string("/") + full_name;
+  }
+
+  template<typename T>
+  string GetTypeUrl() {
+    return GetTypeUrl(T::descriptor()->full_name());
+  }
+
+ protected:
+  google::protobuf::scoped_ptr<TypeResolver> resolver_;
+};
+
+TEST_F(DescriptorPoolTypeResolverTest, TestAllTypes) {
+  Type type;
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+      GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
+  // Check all optional fields.
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_INT32, "optional_int32", 1));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_INT64, "optional_int64", 2));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_UINT32, "optional_uint32", 3));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_UINT64, "optional_uint64", 4));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_SINT32, "optional_sint32", 5));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_SINT64, "optional_sint64", 6));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_FIXED32, "optional_fixed32", 7));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_FIXED64, "optional_fixed64", 8));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_SFIXED32, "optional_sfixed32", 9));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_SFIXED64, "optional_sfixed64", 10));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_FLOAT, "optional_float", 11));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_DOUBLE, "optional_double", 12));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_BOOL, "optional_bool", 13));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_STRING, "optional_string", 14));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_BYTES, "optional_bytes", 15));
+
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_MESSAGE, "optional_nested_message", 18));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_MESSAGE, "optional_foreign_message", 19));
+
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "optional_nested_message",
+      GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "optional_foreign_message",
+      GetTypeUrl<protobuf_unittest::ForeignMessage>()));
+
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_ENUM, "optional_nested_enum", 21));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_ENUM, "optional_foreign_enum", 22));
+
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "optional_nested_enum",
+      GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "optional_foreign_enum",
+      GetTypeUrl("protobuf_unittest.ForeignEnum")));
+
+  // Check all repeated fields.
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_INT32, "repeated_int32", 31));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_INT64, "repeated_int64", 32));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_UINT32, "repeated_uint32", 33));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_UINT64, "repeated_uint64", 34));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_SINT32, "repeated_sint32", 35));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_SINT64, "repeated_sint64", 36));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_FIXED32, "repeated_fixed32", 37));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_FIXED64, "repeated_fixed64", 38));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_SFIXED32, "repeated_sfixed32", 39));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_SFIXED64, "repeated_sfixed64", 40));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_FLOAT, "repeated_float", 41));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_DOUBLE, "repeated_double", 42));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_BOOL, "repeated_bool", 43));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_STRING, "repeated_string", 44));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_BYTES, "repeated_bytes", 45));
+
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_MESSAGE, "repeated_nested_message", 48));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_MESSAGE, "repeated_foreign_message", 49));
+
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "repeated_nested_message",
+      GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "repeated_foreign_message",
+      GetTypeUrl<protobuf_unittest::ForeignMessage>()));
+
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_ENUM, "repeated_nested_enum", 51));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_ENUM, "repeated_foreign_enum", 52));
+
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "repeated_nested_enum",
+      GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "repeated_foreign_enum",
+      GetTypeUrl("protobuf_unittest.ForeignEnum")));
+
+  // Groups are discarded when converting to Type.
+  const Descriptor* descriptor = protobuf_unittest::TestAllTypes::descriptor();
+  EXPECT_TRUE(descriptor->FindFieldByName("optionalgroup") != NULL);
+  EXPECT_TRUE(descriptor->FindFieldByName("repeatedgroup") != NULL);
+  ASSERT_FALSE(HasField(type, "optionalgroup"));
+  ASSERT_FALSE(HasField(type, "repeatedgroup"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestPackedField) {
+  Type type;
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+      GetTypeUrl<protobuf_unittest::TestPackedTypes>(), &type).ok());
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_INT32, "packed_int32", 90));
+  EXPECT_TRUE(IsPacked(type, "packed_int32"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestOneof) {
+  Type type;
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+      GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_UINT32, "oneof_uint32", 111));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_MESSAGE, "oneof_nested_message", 112));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_STRING, "oneof_string", 113));
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+                       Field::TYPE_BYTES, "oneof_bytes", 114));
+  EXPECT_TRUE(FieldInOneof(type, "oneof_uint32", "oneof_field"));
+  EXPECT_TRUE(FieldInOneof(type, "oneof_nested_message", "oneof_field"));
+  EXPECT_TRUE(FieldInOneof(type, "oneof_string", "oneof_field"));
+  EXPECT_TRUE(FieldInOneof(type, "oneof_bytes", "oneof_field"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestMap) {
+  Type type;
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+      GetTypeUrl<protobuf_unittest::TestMap>(), &type).ok());
+  EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+                       Field::TYPE_MESSAGE, "map_int32_int32", 1));
+  EXPECT_TRUE(CheckFieldTypeUrl(
+      type, "map_int32_int32",
+      GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry")));
+
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+      GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry"),
+      &type).ok());
+  EXPECT_TRUE(HasBoolOption(type.options(), "map_entry", true));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestEnum) {
+  Enum type;
+  ASSERT_TRUE(resolver_->ResolveEnumType(
+      GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"), &type).ok());
+  EnumHasValue(type, "FOO", 1);
+  EnumHasValue(type, "BAR", 2);
+  EnumHasValue(type, "BAZ", 3);
+  EnumHasValue(type, "NEG", -1);
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestJsonName) {
+  Type type;
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+                           GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type)
+                  .ok());
+  EXPECT_EQ("optionalInt32", FindField(type, "optional_int32")->json_name());
+
+  ASSERT_TRUE(resolver_->ResolveMessageType(
+                           GetTypeUrl<proto3::TestCustomJsonName>(), &type)
+                  .ok());
+  EXPECT_EQ("@value", FindField(type, "value")->json_name());
+}
+
+}  // namespace
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/well_known_types_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/well_known_types_unittest.cc
new file mode 100644
index 0000000..c9a9aa1
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/well_known_types_unittest.cc
@@ -0,0 +1,60 @@
+// 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.
+#include <google/protobuf/unittest_well_known_types.pb.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// This test only checks whether well-known types are included in protobuf
+// runtime library. The test passes if it compiles.
+TEST(WellKnownTypesTest, AllKnownTypesAreIncluded) {
+  protobuf_unittest::TestWellKnownTypes message;
+  EXPECT_EQ(0, message.any_field().ByteSize());
+  EXPECT_EQ(0, message.api_field().ByteSize());
+  EXPECT_EQ(0, message.duration_field().ByteSize());
+  EXPECT_EQ(0, message.empty_field().ByteSize());
+  EXPECT_EQ(0, message.field_mask_field().ByteSize());
+  EXPECT_EQ(0, message.source_context_field().ByteSize());
+  EXPECT_EQ(0, message.struct_field().ByteSize());
+  EXPECT_EQ(0, message.timestamp_field().ByteSize());
+  EXPECT_EQ(0, message.type_field().ByteSize());
+  EXPECT_EQ(0, message.int32_field().ByteSize());
+}
+
+}  // namespace
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format.cc b/src/third_party/protobuf-3/src/google/protobuf/wire_format.cc
new file mode 100644
index 0000000..5ee4e25
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format.cc
@@ -0,0 +1,1133 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/unknown_field_set.h>
+
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// ===================================================================
+
+bool UnknownFieldSetFieldSkipper::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  return WireFormat::SkipField(input, tag, unknown_fields_);
+}
+
+bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) {
+  return WireFormat::SkipMessage(input, unknown_fields_);
+}
+
+void UnknownFieldSetFieldSkipper::SkipUnknownEnum(
+    int field_number, int value) {
+  unknown_fields_->AddVarint(field_number, value);
+}
+
+bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
+                           UnknownFieldSet* unknown_fields) {
+  int number = WireFormatLite::GetTagFieldNumber(tag);
+
+  switch (WireFormatLite::GetTagWireType(tag)) {
+    case WireFormatLite::WIRETYPE_VARINT: {
+      uint64 value;
+      if (!input->ReadVarint64(&value)) return false;
+      if (unknown_fields != NULL) unknown_fields->AddVarint(number, value);
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_FIXED64: {
+      uint64 value;
+      if (!input->ReadLittleEndian64(&value)) return false;
+      if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value);
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+      uint32 length;
+      if (!input->ReadVarint32(&length)) return false;
+      if (unknown_fields == NULL) {
+        if (!input->Skip(length)) return false;
+      } else {
+        if (!input->ReadString(unknown_fields->AddLengthDelimited(number),
+                               length)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_START_GROUP: {
+      if (!input->IncrementRecursionDepth()) return false;
+      if (!SkipMessage(input, (unknown_fields == NULL) ?
+                              NULL : unknown_fields->AddGroup(number))) {
+        return false;
+      }
+      input->DecrementRecursionDepth();
+      // Check that the ending tag matched the starting tag.
+      if (!input->LastTagWas(WireFormatLite::MakeTag(
+          WireFormatLite::GetTagFieldNumber(tag),
+          WireFormatLite::WIRETYPE_END_GROUP))) {
+        return false;
+      }
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_END_GROUP: {
+      return false;
+    }
+    case WireFormatLite::WIRETYPE_FIXED32: {
+      uint32 value;
+      if (!input->ReadLittleEndian32(&value)) return false;
+      if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value);
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+bool WireFormat::SkipMessage(io::CodedInputStream* input,
+                             UnknownFieldSet* unknown_fields) {
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) {
+      // End of input.  This is a valid place to end, so return true.
+      return true;
+    }
+
+    WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
+
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+      // Must be the end of the message.
+      return true;
+    }
+
+    if (!SkipField(input, tag, unknown_fields)) return false;
+  }
+}
+
+bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+                                                uint32 field_number,
+                                                bool (*is_valid)(int),
+                                                UnknownFieldSet* unknown_fields,
+                                                RepeatedField<int>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    int value;
+    if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+        int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+      return false;
+    }
+    if (is_valid == NULL || is_valid(value)) {
+      values->Add(value);
+    } else {
+      unknown_fields->AddVarint(field_number, value);
+    }
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
+
+void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
+                                        io::CodedOutputStream* output) {
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+    switch (field.type()) {
+      case UnknownField::TYPE_VARINT:
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_VARINT));
+        output->WriteVarint64(field.varint());
+        break;
+      case UnknownField::TYPE_FIXED32:
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED32));
+        output->WriteLittleEndian32(field.fixed32());
+        break;
+      case UnknownField::TYPE_FIXED64:
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED64));
+        output->WriteLittleEndian64(field.fixed64());
+        break;
+      case UnknownField::TYPE_LENGTH_DELIMITED:
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+        output->WriteVarint32(field.length_delimited().size());
+        output->WriteRawMaybeAliased(field.length_delimited().data(),
+                                     field.length_delimited().size());
+        break;
+      case UnknownField::TYPE_GROUP:
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_START_GROUP));
+        SerializeUnknownFields(field.group(), output);
+        output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_END_GROUP));
+        break;
+    }
+  }
+}
+
+uint8* WireFormat::SerializeUnknownFieldsToArray(
+    const UnknownFieldSet& unknown_fields,
+    uint8* target) {
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+
+    switch (field.type()) {
+      case UnknownField::TYPE_VARINT:
+        target = WireFormatLite::WriteInt64ToArray(
+            field.number(), field.varint(), target);
+        break;
+      case UnknownField::TYPE_FIXED32:
+        target = WireFormatLite::WriteFixed32ToArray(
+            field.number(), field.fixed32(), target);
+        break;
+      case UnknownField::TYPE_FIXED64:
+        target = WireFormatLite::WriteFixed64ToArray(
+            field.number(), field.fixed64(), target);
+        break;
+      case UnknownField::TYPE_LENGTH_DELIMITED:
+        target = WireFormatLite::WriteBytesToArray(
+            field.number(), field.length_delimited(), target);
+        break;
+      case UnknownField::TYPE_GROUP:
+        target = WireFormatLite::WriteTagToArray(
+            field.number(), WireFormatLite::WIRETYPE_START_GROUP, target);
+        target = SerializeUnknownFieldsToArray(field.group(), target);
+        target = WireFormatLite::WriteTagToArray(
+            field.number(), WireFormatLite::WIRETYPE_END_GROUP, target);
+        break;
+    }
+  }
+  return target;
+}
+
+void WireFormat::SerializeUnknownMessageSetItems(
+    const UnknownFieldSet& unknown_fields,
+    io::CodedOutputStream* output) {
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+    // The only unknown fields that are allowed to exist in a MessageSet are
+    // messages, which are length-delimited.
+    if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+      // Start group.
+      output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
+
+      // Write type ID.
+      output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
+      output->WriteVarint32(field.number());
+
+      // Write message.
+      output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
+      field.SerializeLengthDelimitedNoTag(output);
+
+      // End group.
+      output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
+    }
+  }
+}
+
+uint8* WireFormat::SerializeUnknownMessageSetItemsToArray(
+    const UnknownFieldSet& unknown_fields,
+    uint8* target) {
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+
+    // The only unknown fields that are allowed to exist in a MessageSet are
+    // messages, which are length-delimited.
+    if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+      // Start group.
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetItemStartTag, target);
+
+      // Write type ID.
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetTypeIdTag, target);
+      target = io::CodedOutputStream::WriteVarint32ToArray(
+          field.number(), target);
+
+      // Write message.
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetMessageTag, target);
+      target = field.SerializeLengthDelimitedNoTagToArray(target);
+
+      // End group.
+      target = io::CodedOutputStream::WriteTagToArray(
+          WireFormatLite::kMessageSetItemEndTag, target);
+    }
+  }
+
+  return target;
+}
+
+int WireFormat::ComputeUnknownFieldsSize(
+    const UnknownFieldSet& unknown_fields) {
+  int size = 0;
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+
+    switch (field.type()) {
+      case UnknownField::TYPE_VARINT:
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_VARINT));
+        size += io::CodedOutputStream::VarintSize64(field.varint());
+        break;
+      case UnknownField::TYPE_FIXED32:
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED32));
+        size += sizeof(int32);
+        break;
+      case UnknownField::TYPE_FIXED64:
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_FIXED64));
+        size += sizeof(int64);
+        break;
+      case UnknownField::TYPE_LENGTH_DELIMITED:
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+        size += io::CodedOutputStream::VarintSize32(
+            field.length_delimited().size());
+        size += field.length_delimited().size();
+        break;
+      case UnknownField::TYPE_GROUP:
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_START_GROUP));
+        size += ComputeUnknownFieldsSize(field.group());
+        size += io::CodedOutputStream::VarintSize32(
+            WireFormatLite::MakeTag(field.number(),
+            WireFormatLite::WIRETYPE_END_GROUP));
+        break;
+    }
+  }
+
+  return size;
+}
+
+int WireFormat::ComputeUnknownMessageSetItemsSize(
+    const UnknownFieldSet& unknown_fields) {
+  int size = 0;
+  for (int i = 0; i < unknown_fields.field_count(); i++) {
+    const UnknownField& field = unknown_fields.field(i);
+
+    // The only unknown fields that are allowed to exist in a MessageSet are
+    // messages, which are length-delimited.
+    if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+      size += WireFormatLite::kMessageSetItemTagsSize;
+      size += io::CodedOutputStream::VarintSize32(field.number());
+
+      int field_size = field.GetLengthDelimitedSize();
+      size += io::CodedOutputStream::VarintSize32(field_size);
+      size += field_size;
+    }
+  }
+
+  return size;
+}
+
+// ===================================================================
+
+bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
+                                      Message* message) {
+  const Descriptor* descriptor = message->GetDescriptor();
+  const Reflection* message_reflection = message->GetReflection();
+
+  while(true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) {
+      // End of input.  This is a valid place to end, so return true.
+      return true;
+    }
+
+    if (WireFormatLite::GetTagWireType(tag) ==
+        WireFormatLite::WIRETYPE_END_GROUP) {
+      // Must be the end of the message.
+      return true;
+    }
+
+    const FieldDescriptor* field = NULL;
+
+    if (descriptor != NULL) {
+      int field_number = WireFormatLite::GetTagFieldNumber(tag);
+      field = descriptor->FindFieldByNumber(field_number);
+
+      // If that failed, check if the field is an extension.
+      if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
+        if (input->GetExtensionPool() == NULL) {
+          field = message_reflection->FindKnownExtensionByNumber(field_number);
+        } else {
+          field = input->GetExtensionPool()
+                       ->FindExtensionByNumber(descriptor, field_number);
+        }
+      }
+
+      // If that failed, but we're a MessageSet, and this is the tag for a
+      // MessageSet item, then parse that.
+      if (field == NULL &&
+          descriptor->options().message_set_wire_format() &&
+          tag == WireFormatLite::kMessageSetItemStartTag) {
+        if (!ParseAndMergeMessageSetItem(input, message)) {
+          return false;
+        }
+        continue;  // Skip ParseAndMergeField(); already taken care of.
+      }
+    }
+
+    if (!ParseAndMergeField(tag, field, message, input)) {
+      return false;
+    }
+  }
+}
+
+bool WireFormat::SkipMessageSetField(io::CodedInputStream* input,
+                                     uint32 field_number,
+                                     UnknownFieldSet* unknown_fields) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  return input->ReadString(
+      unknown_fields->AddLengthDelimited(field_number), length);
+}
+
+bool WireFormat::ParseAndMergeMessageSetField(uint32 field_number,
+                                              const FieldDescriptor* field,
+                                              Message* message,
+                                              io::CodedInputStream* input) {
+  const Reflection* message_reflection = message->GetReflection();
+  if (field == NULL) {
+    // We store unknown MessageSet extensions as groups.
+    return SkipMessageSetField(
+        input, field_number, message_reflection->MutableUnknownFields(message));
+  } else if (field->is_repeated() ||
+             field->type() != FieldDescriptor::TYPE_MESSAGE) {
+    // This shouldn't happen as we only allow optional message extensions to
+    // MessageSet.
+    GOOGLE_LOG(ERROR) << "Extensions of MessageSets must be optional messages.";
+    return false;
+  } else {
+    Message* sub_message = message_reflection->MutableMessage(
+        message, field, input->GetExtensionFactory());
+    return WireFormatLite::ReadMessage(input, sub_message);
+  }
+}
+
+static bool StrictUtf8Check(const FieldDescriptor* field) {
+  return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool WireFormat::ParseAndMergeField(
+    uint32 tag,
+    const FieldDescriptor* field,        // May be NULL for unknown
+    Message* message,
+    io::CodedInputStream* input) {
+  const Reflection* message_reflection = message->GetReflection();
+
+  enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
+
+  if (field == NULL) {
+    value_format = UNKNOWN;
+  } else if (WireFormatLite::GetTagWireType(tag) ==
+             WireTypeForFieldType(field->type())) {
+    value_format = NORMAL_FORMAT;
+  } else if (field->is_packable() &&
+             WireFormatLite::GetTagWireType(tag) ==
+             WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+    value_format = PACKED_FORMAT;
+  } else {
+    // We don't recognize this field. Either the field number is unknown
+    // or the wire type doesn't match. Put it in our unknown field set.
+    value_format = UNKNOWN;
+  }
+
+  if (value_format == UNKNOWN) {
+    return SkipField(input, tag,
+                     message_reflection->MutableUnknownFields(message));
+  } else if (value_format == PACKED_FORMAT) {
+    uint32 length;
+    if (!input->ReadVarint32(&length)) return false;
+    io::CodedInputStream::Limit limit = input->PushLimit(length);
+
+    switch (field->type()) {
+#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                      \
+      case FieldDescriptor::TYPE_##TYPE: {                                     \
+        while (input->BytesUntilLimit() > 0) {                                 \
+          CPPTYPE value;                                                       \
+          if (!WireFormatLite::ReadPrimitive<                                  \
+                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value))          \
+            return false;                                                      \
+          message_reflection->Add##CPPTYPE_METHOD(message, field, value);      \
+        }                                                                      \
+        break;                                                                 \
+      }
+
+      HANDLE_PACKED_TYPE( INT32,  int32,  Int32)
+      HANDLE_PACKED_TYPE( INT64,  int64,  Int64)
+      HANDLE_PACKED_TYPE(SINT32,  int32,  Int32)
+      HANDLE_PACKED_TYPE(SINT64,  int64,  Int64)
+      HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
+      HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
+
+      HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
+      HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
+      HANDLE_PACKED_TYPE(SFIXED32,  int32,  Int32)
+      HANDLE_PACKED_TYPE(SFIXED64,  int64,  Int64)
+
+      HANDLE_PACKED_TYPE(FLOAT , float , Float )
+      HANDLE_PACKED_TYPE(DOUBLE, double, Double)
+
+      HANDLE_PACKED_TYPE(BOOL, bool, Bool)
+#undef HANDLE_PACKED_TYPE
+
+      case FieldDescriptor::TYPE_ENUM: {
+        while (input->BytesUntilLimit() > 0) {
+          int value;
+          if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+                  input, &value)) return false;
+          if (message->GetDescriptor()->file()->syntax() ==
+              FileDescriptor::SYNTAX_PROTO3) {
+            message_reflection->AddEnumValue(message, field, value);
+          } else {
+            const EnumValueDescriptor* enum_value =
+                field->enum_type()->FindValueByNumber(value);
+            if (enum_value != NULL) {
+              message_reflection->AddEnum(message, field, enum_value);
+            } else {
+              // The enum value is not one of the known values.  Add it to the
+              // UnknownFieldSet.
+              int64 sign_extended_value = static_cast<int64>(value);
+              message_reflection->MutableUnknownFields(message)
+                  ->AddVarint(
+                      WireFormatLite::GetTagFieldNumber(tag),
+                      sign_extended_value);
+            }
+          }
+        }
+
+        break;
+      }
+
+      case FieldDescriptor::TYPE_STRING:
+      case FieldDescriptor::TYPE_GROUP:
+      case FieldDescriptor::TYPE_MESSAGE:
+      case FieldDescriptor::TYPE_BYTES:
+        // Can't have packed fields of these types: these should be caught by
+        // the protocol compiler.
+        return false;
+        break;
+    }
+
+    input->PopLimit(limit);
+  } else {
+    // Non-packed value (value_format == NORMAL_FORMAT)
+    switch (field->type()) {
+#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                            \
+      case FieldDescriptor::TYPE_##TYPE: {                                    \
+        CPPTYPE value;                                                        \
+        if (!WireFormatLite::ReadPrimitive<                                   \
+                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value))         \
+          return false;                                                       \
+        if (field->is_repeated()) {                                           \
+          message_reflection->Add##CPPTYPE_METHOD(message, field, value);     \
+        } else {                                                              \
+          message_reflection->Set##CPPTYPE_METHOD(message, field, value);     \
+        }                                                                     \
+        break;                                                                \
+      }
+
+      HANDLE_TYPE( INT32,  int32,  Int32)
+      HANDLE_TYPE( INT64,  int64,  Int64)
+      HANDLE_TYPE(SINT32,  int32,  Int32)
+      HANDLE_TYPE(SINT64,  int64,  Int64)
+      HANDLE_TYPE(UINT32, uint32, UInt32)
+      HANDLE_TYPE(UINT64, uint64, UInt64)
+
+      HANDLE_TYPE( FIXED32, uint32, UInt32)
+      HANDLE_TYPE( FIXED64, uint64, UInt64)
+      HANDLE_TYPE(SFIXED32,  int32,  Int32)
+      HANDLE_TYPE(SFIXED64,  int64,  Int64)
+
+      HANDLE_TYPE(FLOAT , float , Float )
+      HANDLE_TYPE(DOUBLE, double, Double)
+
+      HANDLE_TYPE(BOOL, bool, Bool)
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::TYPE_ENUM: {
+        int value;
+        if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+                input, &value)) return false;
+        if (message->GetDescriptor()->file()->syntax() ==
+            FileDescriptor::SYNTAX_PROTO3) {
+          if (field->is_repeated()) {
+            message_reflection->AddEnumValue(message, field, value);
+          } else {
+            message_reflection->SetEnumValue(message, field, value);
+          }
+        } else {
+          const EnumValueDescriptor* enum_value =
+              field->enum_type()->FindValueByNumber(value);
+          if (enum_value != NULL) {
+            if (field->is_repeated()) {
+              message_reflection->AddEnum(message, field, enum_value);
+            } else {
+              message_reflection->SetEnum(message, field, enum_value);
+            }
+          } else {
+            // The enum value is not one of the known values.  Add it to the
+            // UnknownFieldSet.
+            int64 sign_extended_value = static_cast<int64>(value);
+            message_reflection->MutableUnknownFields(message)
+                              ->AddVarint(
+                                  WireFormatLite::GetTagFieldNumber(tag),
+                                  sign_extended_value);
+          }
+        }
+        break;
+      }
+
+      // Handle strings separately so that we can optimize the ctype=CORD case.
+      case FieldDescriptor::TYPE_STRING: {
+        bool strict_utf8_check = StrictUtf8Check(field);
+        string value;
+        if (!WireFormatLite::ReadString(input, &value)) return false;
+        if (strict_utf8_check) {
+          if (!WireFormatLite::VerifyUtf8String(
+                  value.data(), value.length(), WireFormatLite::PARSE,
+                  field->full_name().c_str())) {
+            return false;
+          }
+        } else {
+          VerifyUTF8StringNamedField(value.data(), value.length(), PARSE,
+                                     field->full_name().c_str());
+        }
+        if (field->is_repeated()) {
+          message_reflection->AddString(message, field, value);
+        } else {
+          message_reflection->SetString(message, field, value);
+        }
+        break;
+      }
+
+      case FieldDescriptor::TYPE_BYTES: {
+        string value;
+        if (!WireFormatLite::ReadBytes(input, &value)) return false;
+        if (field->is_repeated()) {
+          message_reflection->AddString(message, field, value);
+        } else {
+          message_reflection->SetString(message, field, value);
+        }
+        break;
+      }
+
+      case FieldDescriptor::TYPE_GROUP: {
+        Message* sub_message;
+        if (field->is_repeated()) {
+          sub_message = message_reflection->AddMessage(
+              message, field, input->GetExtensionFactory());
+        } else {
+          sub_message = message_reflection->MutableMessage(
+              message, field, input->GetExtensionFactory());
+        }
+
+        if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
+                                       input, sub_message))
+          return false;
+        break;
+      }
+
+      case FieldDescriptor::TYPE_MESSAGE: {
+        Message* sub_message;
+        if (field->is_repeated()) {
+          sub_message = message_reflection->AddMessage(
+              message, field, input->GetExtensionFactory());
+        } else {
+          sub_message = message_reflection->MutableMessage(
+              message, field, input->GetExtensionFactory());
+        }
+
+        if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool WireFormat::ParseAndMergeMessageSetItem(
+    io::CodedInputStream* input,
+    Message* message) {
+  const Reflection* message_reflection = message->GetReflection();
+
+  // This method parses a group which should contain two fields:
+  //   required int32 type_id = 2;
+  //   required data message = 3;
+
+  uint32 last_type_id = 0;
+
+  // Once we see a type_id, we'll look up the FieldDescriptor for the
+  // extension.
+  const FieldDescriptor* field = NULL;
+
+  // If we see message data before the type_id, we'll append it to this so
+  // we can parse it later.
+  string message_data;
+
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) return false;
+
+    switch (tag) {
+      case WireFormatLite::kMessageSetTypeIdTag: {
+        uint32 type_id;
+        if (!input->ReadVarint32(&type_id)) return false;
+        last_type_id = type_id;
+        field = message_reflection->FindKnownExtensionByNumber(type_id);
+
+        if (!message_data.empty()) {
+          // We saw some message data before the type_id.  Have to parse it
+          // now.
+          io::ArrayInputStream raw_input(message_data.data(),
+                                         message_data.size());
+          io::CodedInputStream sub_input(&raw_input);
+          if (!ParseAndMergeMessageSetField(last_type_id, field, message,
+                                            &sub_input)) {
+            return false;
+          }
+          message_data.clear();
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetMessageTag: {
+        if (last_type_id == 0) {
+          // We haven't seen a type_id yet.  Append this data to message_data.
+          string temp;
+          uint32 length;
+          if (!input->ReadVarint32(&length)) return false;
+          if (!input->ReadString(&temp, length)) return false;
+          io::StringOutputStream output_stream(&message_data);
+          io::CodedOutputStream coded_output(&output_stream);
+          coded_output.WriteVarint32(length);
+          coded_output.WriteString(temp);
+        } else {
+          // Already saw type_id, so we can parse this directly.
+          if (!ParseAndMergeMessageSetField(last_type_id, field, message,
+                                            input)) {
+            return false;
+          }
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetItemEndTag: {
+        return true;
+      }
+
+      default: {
+        if (!SkipField(input, tag, NULL)) return false;
+      }
+    }
+  }
+}
+
+// ===================================================================
+
+void WireFormat::SerializeWithCachedSizes(
+    const Message& message,
+    int size, io::CodedOutputStream* output) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* message_reflection = message.GetReflection();
+  int expected_endpoint = output->ByteCount() + size;
+
+  vector<const FieldDescriptor*> fields;
+  message_reflection->ListFields(message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    SerializeFieldWithCachedSizes(fields[i], message, output);
+  }
+
+  if (descriptor->options().message_set_wire_format()) {
+    SerializeUnknownMessageSetItems(
+        message_reflection->GetUnknownFields(message), output);
+  } else {
+    SerializeUnknownFields(
+        message_reflection->GetUnknownFields(message), output);
+  }
+
+  GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint)
+    << ": Protocol message serialized to a size different from what was "
+       "originally expected.  Perhaps it was modified by another thread "
+       "during serialization?";
+}
+
+void WireFormat::SerializeFieldWithCachedSizes(
+    const FieldDescriptor* field,
+    const Message& message,
+    io::CodedOutputStream* output) {
+  const Reflection* message_reflection = message.GetReflection();
+
+  if (field->is_extension() &&
+      field->containing_type()->options().message_set_wire_format() &&
+      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+      !field->is_repeated()) {
+    SerializeMessageSetItemWithCachedSizes(field, message, output);
+    return;
+  }
+
+  int count = 0;
+
+  if (field->is_repeated()) {
+    count = message_reflection->FieldSize(message, field);
+  } else if (message_reflection->HasField(message, field)) {
+    count = 1;
+  }
+
+  const bool is_packed = field->is_packed();
+  if (is_packed && count > 0) {
+    WireFormatLite::WriteTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    const int data_size = FieldDataOnlyByteSize(field, message);
+    output->WriteVarint32(data_size);
+  }
+
+  for (int j = 0; j < count; j++) {
+    switch (field->type()) {
+#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD)      \
+      case FieldDescriptor::TYPE_##TYPE: {                                     \
+        const CPPTYPE value = field->is_repeated() ?                           \
+                              message_reflection->GetRepeated##CPPTYPE_METHOD( \
+                                message, field, j) :                           \
+                              message_reflection->Get##CPPTYPE_METHOD(         \
+                                message, field);                               \
+        if (is_packed) {                                                       \
+          WireFormatLite::Write##TYPE_METHOD##NoTag(value, output);            \
+        } else {                                                               \
+          WireFormatLite::Write##TYPE_METHOD(field->number(), value, output);  \
+        }                                                                      \
+        break;                                                                 \
+      }
+
+      HANDLE_PRIMITIVE_TYPE( INT32,  int32,  Int32,  Int32)
+      HANDLE_PRIMITIVE_TYPE( INT64,  int64,  Int64,  Int64)
+      HANDLE_PRIMITIVE_TYPE(SINT32,  int32, SInt32,  Int32)
+      HANDLE_PRIMITIVE_TYPE(SINT64,  int64, SInt64,  Int64)
+      HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32)
+      HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64)
+
+      HANDLE_PRIMITIVE_TYPE( FIXED32, uint32,  Fixed32, UInt32)
+      HANDLE_PRIMITIVE_TYPE( FIXED64, uint64,  Fixed64, UInt64)
+      HANDLE_PRIMITIVE_TYPE(SFIXED32,  int32, SFixed32,  Int32)
+      HANDLE_PRIMITIVE_TYPE(SFIXED64,  int64, SFixed64,  Int64)
+
+      HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float )
+      HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double)
+
+      HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool)
+#undef HANDLE_PRIMITIVE_TYPE
+
+#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                       \
+      case FieldDescriptor::TYPE_##TYPE:                                     \
+        WireFormatLite::Write##TYPE_METHOD(                                  \
+              field->number(),                                               \
+              field->is_repeated() ?                                         \
+                message_reflection->GetRepeated##CPPTYPE_METHOD(             \
+                  message, field, j) :                                       \
+                message_reflection->Get##CPPTYPE_METHOD(message, field),     \
+              output);                                                       \
+        break;
+
+      HANDLE_TYPE(GROUP  , Group  , Message)
+      HANDLE_TYPE(MESSAGE, Message, Message)
+#undef HANDLE_TYPE
+
+      case FieldDescriptor::TYPE_ENUM: {
+        const EnumValueDescriptor* value = field->is_repeated() ?
+          message_reflection->GetRepeatedEnum(message, field, j) :
+          message_reflection->GetEnum(message, field);
+        if (is_packed) {
+          WireFormatLite::WriteEnumNoTag(value->number(), output);
+        } else {
+          WireFormatLite::WriteEnum(field->number(), value->number(), output);
+        }
+        break;
+      }
+
+      // Handle strings separately so that we can get string references
+      // instead of copying.
+      case FieldDescriptor::TYPE_STRING: {
+        bool strict_utf8_check = StrictUtf8Check(field);
+        string scratch;
+        const string& value = field->is_repeated() ?
+          message_reflection->GetRepeatedStringReference(
+            message, field, j, &scratch) :
+          message_reflection->GetStringReference(message, field, &scratch);
+        if (strict_utf8_check) {
+          WireFormatLite::VerifyUtf8String(value.data(), value.length(),
+                                           WireFormatLite::SERIALIZE,
+                                           field->full_name().c_str());
+        } else {
+          VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE,
+                                     field->full_name().c_str());
+        }
+        WireFormatLite::WriteString(field->number(), value, output);
+        break;
+      }
+
+      case FieldDescriptor::TYPE_BYTES: {
+        string scratch;
+        const string& value = field->is_repeated() ?
+          message_reflection->GetRepeatedStringReference(
+            message, field, j, &scratch) :
+          message_reflection->GetStringReference(message, field, &scratch);
+        WireFormatLite::WriteBytes(field->number(), value, output);
+        break;
+      }
+    }
+  }
+}
+
+void WireFormat::SerializeMessageSetItemWithCachedSizes(
+    const FieldDescriptor* field,
+    const Message& message,
+    io::CodedOutputStream* output) {
+  const Reflection* message_reflection = message.GetReflection();
+
+  // Start group.
+  output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
+
+  // Write type ID.
+  output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
+  output->WriteVarint32(field->number());
+
+  // Write message.
+  output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
+
+  const Message& sub_message = message_reflection->GetMessage(message, field);
+  output->WriteVarint32(sub_message.GetCachedSize());
+  sub_message.SerializeWithCachedSizes(output);
+
+  // End group.
+  output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
+}
+
+// ===================================================================
+
+int WireFormat::ByteSize(const Message& message) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* message_reflection = message.GetReflection();
+
+  int our_size = 0;
+
+  vector<const FieldDescriptor*> fields;
+  message_reflection->ListFields(message, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    our_size += FieldByteSize(fields[i], message);
+  }
+
+  if (descriptor->options().message_set_wire_format()) {
+    our_size += ComputeUnknownMessageSetItemsSize(
+      message_reflection->GetUnknownFields(message));
+  } else {
+    our_size += ComputeUnknownFieldsSize(
+      message_reflection->GetUnknownFields(message));
+  }
+
+  return our_size;
+}
+
+int WireFormat::FieldByteSize(
+    const FieldDescriptor* field,
+    const Message& message) {
+  const Reflection* message_reflection = message.GetReflection();
+
+  if (field->is_extension() &&
+      field->containing_type()->options().message_set_wire_format() &&
+      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+      !field->is_repeated()) {
+    return MessageSetItemByteSize(field, message);
+  }
+
+  int count = 0;
+  if (field->is_repeated()) {
+    count = message_reflection->FieldSize(message, field);
+  } else if (message_reflection->HasField(message, field)) {
+    count = 1;
+  }
+
+  const int data_size = FieldDataOnlyByteSize(field, message);
+  int our_size = data_size;
+  if (field->is_packed()) {
+    if (data_size > 0) {
+      // Packed fields get serialized like a string, not their native type.
+      // Technically this doesn't really matter; the size only changes if it's
+      // a GROUP
+      our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING);
+      our_size += io::CodedOutputStream::VarintSize32(data_size);
+    }
+  } else {
+    our_size += count * TagSize(field->number(), field->type());
+  }
+  return our_size;
+}
+
+int WireFormat::FieldDataOnlyByteSize(
+    const FieldDescriptor* field,
+    const Message& message) {
+  const Reflection* message_reflection = message.GetReflection();
+
+  int count = 0;
+  if (field->is_repeated()) {
+    count = message_reflection->FieldSize(message, field);
+  } else if (message_reflection->HasField(message, field)) {
+    count = 1;
+  }
+
+  int data_size = 0;
+  switch (field->type()) {
+#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                     \
+    case FieldDescriptor::TYPE_##TYPE:                                     \
+      if (field->is_repeated()) {                                          \
+        for (int j = 0; j < count; j++) {                                  \
+          data_size += WireFormatLite::TYPE_METHOD##Size(                  \
+            message_reflection->GetRepeated##CPPTYPE_METHOD(               \
+              message, field, j));                                         \
+        }                                                                  \
+      } else {                                                             \
+        data_size += WireFormatLite::TYPE_METHOD##Size(                    \
+          message_reflection->Get##CPPTYPE_METHOD(message, field));        \
+      }                                                                    \
+      break;
+
+#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD)                               \
+    case FieldDescriptor::TYPE_##TYPE:                                     \
+      data_size += count * WireFormatLite::k##TYPE_METHOD##Size;           \
+      break;
+
+    HANDLE_TYPE( INT32,  Int32,  Int32)
+    HANDLE_TYPE( INT64,  Int64,  Int64)
+    HANDLE_TYPE(SINT32, SInt32,  Int32)
+    HANDLE_TYPE(SINT64, SInt64,  Int64)
+    HANDLE_TYPE(UINT32, UInt32, UInt32)
+    HANDLE_TYPE(UINT64, UInt64, UInt64)
+
+    HANDLE_FIXED_TYPE( FIXED32,  Fixed32)
+    HANDLE_FIXED_TYPE( FIXED64,  Fixed64)
+    HANDLE_FIXED_TYPE(SFIXED32, SFixed32)
+    HANDLE_FIXED_TYPE(SFIXED64, SFixed64)
+
+    HANDLE_FIXED_TYPE(FLOAT , Float )
+    HANDLE_FIXED_TYPE(DOUBLE, Double)
+
+    HANDLE_FIXED_TYPE(BOOL, Bool)
+
+    HANDLE_TYPE(GROUP  , Group  , Message)
+    HANDLE_TYPE(MESSAGE, Message, Message)
+#undef HANDLE_TYPE
+#undef HANDLE_FIXED_TYPE
+
+    case FieldDescriptor::TYPE_ENUM: {
+      if (field->is_repeated()) {
+        for (int j = 0; j < count; j++) {
+          data_size += WireFormatLite::EnumSize(
+            message_reflection->GetRepeatedEnum(message, field, j)->number());
+        }
+      } else {
+        data_size += WireFormatLite::EnumSize(
+          message_reflection->GetEnum(message, field)->number());
+      }
+      break;
+    }
+
+    // Handle strings separately so that we can get string references
+    // instead of copying.
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES: {
+      for (int j = 0; j < count; j++) {
+        string scratch;
+        const string& value = field->is_repeated() ?
+          message_reflection->GetRepeatedStringReference(
+            message, field, j, &scratch) :
+          message_reflection->GetStringReference(message, field, &scratch);
+        data_size += WireFormatLite::StringSize(value);
+      }
+      break;
+    }
+  }
+  return data_size;
+}
+
+int WireFormat::MessageSetItemByteSize(
+    const FieldDescriptor* field,
+    const Message& message) {
+  const Reflection* message_reflection = message.GetReflection();
+
+  int our_size = WireFormatLite::kMessageSetItemTagsSize;
+
+  // type_id
+  our_size += io::CodedOutputStream::VarintSize32(field->number());
+
+  // message
+  const Message& sub_message = message_reflection->GetMessage(message, field);
+  int message_size = sub_message.ByteSize();
+
+  our_size += io::CodedOutputStream::VarintSize32(message_size);
+  our_size += message_size;
+
+  return our_size;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format.h b/src/third_party/protobuf-3/src/google/protobuf/wire_format.h
new file mode 100644
index 0000000..941be75
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format.h
@@ -0,0 +1,337 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//         atenasio@google.com (Chris Atenasio) (ZigZag transform)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_H__
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/wire_format_lite.h>
+
+// Do UTF-8 validation on string type in Debug build only
+#ifndef NDEBUG
+#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+#endif
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class CodedInputStream;      // coded_stream.h
+    class CodedOutputStream;     // coded_stream.h
+  }
+  class UnknownFieldSet;         // unknown_field_set.h
+}
+
+namespace protobuf {
+namespace internal {
+
+// This class is for internal use by the protocol buffer library and by
+// protocol-complier-generated message classes.  It must not be called
+// directly by clients.
+//
+// This class contains code for implementing the binary protocol buffer
+// wire format via reflection.  The WireFormatLite class implements the
+// non-reflection based routines.
+//
+// This class is really a namespace that contains only static methods
+class LIBPROTOBUF_EXPORT WireFormat {
+ public:
+
+  // Given a field return its WireType
+  static inline WireFormatLite::WireType WireTypeForField(
+      const FieldDescriptor* field);
+
+  // Given a FieldDescriptor::Type return its WireType
+  static inline WireFormatLite::WireType WireTypeForFieldType(
+      FieldDescriptor::Type type);
+
+  // Compute the byte size of a tag.  For groups, this includes both the start
+  // and end tags.
+  static inline int TagSize(int field_number, FieldDescriptor::Type type);
+
+  // These procedures can be used to implement the methods of Message which
+  // handle parsing and serialization of the protocol buffer wire format
+  // using only the Reflection interface.  When you ask the protocol
+  // compiler to optimize for code size rather than speed, it will implement
+  // those methods in terms of these procedures.  Of course, these are much
+  // slower than the specialized implementations which the protocol compiler
+  // generates when told to optimize for speed.
+
+  // Read a message in protocol buffer wire format.
+  //
+  // This procedure reads either to the end of the input stream or through
+  // a WIRETYPE_END_GROUP tag ending the message, whichever comes first.
+  // It returns false if the input is invalid.
+  //
+  // Required fields are NOT checked by this method.  You must call
+  // IsInitialized() on the resulting message yourself.
+  static bool ParseAndMergePartial(io::CodedInputStream* input,
+                                   Message* message);
+
+  // Serialize a message in protocol buffer wire format.
+  //
+  // Any embedded messages within the message must have their correct sizes
+  // cached.  However, the top-level message need not; its size is passed as
+  // a parameter to this procedure.
+  //
+  // These return false iff the underlying stream returns a write error.
+  static void SerializeWithCachedSizes(
+      const Message& message,
+      int size, io::CodedOutputStream* output);
+
+  // Implements Message::ByteSize() via reflection.  WARNING:  The result
+  // of this method is *not* cached anywhere.  However, all embedded messages
+  // will have their ByteSize() methods called, so their sizes will be cached.
+  // Therefore, calling this method is sufficient to allow you to call
+  // WireFormat::SerializeWithCachedSizes() on the same object.
+  static int ByteSize(const Message& message);
+
+  // -----------------------------------------------------------------
+  // Helpers for dealing with unknown fields
+
+  // Skips a field value of the given WireType.  The input should start
+  // positioned immediately after the tag.  If unknown_fields is non-NULL,
+  // the contents of the field will be added to it.
+  static bool SkipField(io::CodedInputStream* input, uint32 tag,
+                        UnknownFieldSet* unknown_fields);
+
+  // Reads and ignores a message from the input.  If unknown_fields is non-NULL,
+  // the contents will be added to it.
+  static bool SkipMessage(io::CodedInputStream* input,
+                          UnknownFieldSet* unknown_fields);
+
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are appended to unknown_fields_stream.
+  static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+                                             uint32 field_number,
+                                             bool (*is_valid)(int),
+                                             UnknownFieldSet* unknown_fields,
+                                             RepeatedField<int>* values);
+
+  // Write the contents of an UnknownFieldSet to the output.
+  static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
+                                     io::CodedOutputStream* output);
+  // Same as above, except writing directly to the provided buffer.
+  // Requires that the buffer have sufficient capacity for
+  // ComputeUnknownFieldsSize(unknown_fields).
+  //
+  // Returns a pointer past the last written byte.
+  static uint8* SerializeUnknownFieldsToArray(
+      const UnknownFieldSet& unknown_fields,
+      uint8* target);
+
+  // Same thing except for messages that have the message_set_wire_format
+  // option.
+  static void SerializeUnknownMessageSetItems(
+      const UnknownFieldSet& unknown_fields,
+      io::CodedOutputStream* output);
+  // Same as above, except writing directly to the provided buffer.
+  // Requires that the buffer have sufficient capacity for
+  // ComputeUnknownMessageSetItemsSize(unknown_fields).
+  //
+  // Returns a pointer past the last written byte.
+  static uint8* SerializeUnknownMessageSetItemsToArray(
+      const UnknownFieldSet& unknown_fields,
+      uint8* target);
+
+  // Compute the size of the UnknownFieldSet on the wire.
+  static int ComputeUnknownFieldsSize(const UnknownFieldSet& unknown_fields);
+
+  // Same thing except for messages that have the message_set_wire_format
+  // option.
+  static int ComputeUnknownMessageSetItemsSize(
+      const UnknownFieldSet& unknown_fields);
+
+
+  // Helper functions for encoding and decoding tags.  (Inlined below and in
+  // _inl.h)
+  //
+  // This is different from MakeTag(field->number(), field->type()) in the case
+  // of packed repeated fields.
+  static uint32 MakeTag(const FieldDescriptor* field);
+
+  // Parse a single field.  The input should start out positioned immediately
+  // after the tag.
+  static bool ParseAndMergeField(
+      uint32 tag,
+      const FieldDescriptor* field,        // May be NULL for unknown
+      Message* message,
+      io::CodedInputStream* input);
+
+  // Serialize a single field.
+  static void SerializeFieldWithCachedSizes(
+      const FieldDescriptor* field,        // Cannot be NULL
+      const Message& message,
+      io::CodedOutputStream* output);
+
+  // Compute size of a single field.  If the field is a message type, this
+  // will call ByteSize() for the embedded message, insuring that it caches
+  // its size.
+  static int FieldByteSize(
+      const FieldDescriptor* field,        // Cannot be NULL
+      const Message& message);
+
+  // Parse/serialize a MessageSet::Item group.  Used with messages that use
+  // opion message_set_wire_format = true.
+  static bool ParseAndMergeMessageSetItem(
+      io::CodedInputStream* input,
+      Message* message);
+  static void SerializeMessageSetItemWithCachedSizes(
+      const FieldDescriptor* field,
+      const Message& message,
+      io::CodedOutputStream* output);
+  static int MessageSetItemByteSize(
+      const FieldDescriptor* field,
+      const Message& message);
+
+  // Computes the byte size of a field, excluding tags. For packed fields, it
+  // only includes the size of the raw data, and not the size of the total
+  // length, but for other length-delimited types, the size of the length is
+  // included.
+  static int FieldDataOnlyByteSize(
+      const FieldDescriptor* field,        // Cannot be NULL
+      const Message& message);
+
+  enum Operation {
+    PARSE = 0,
+    SERIALIZE = 1,
+  };
+
+  // Verifies that a string field is valid UTF8, logging an error if not.
+  // This function will not be called by newly generated protobuf code
+  // but remains present to support existing code.
+  static void VerifyUTF8String(const char* data, int size, Operation op);
+  // The NamedField variant takes a field name in order to produce an
+  // informative error message if verification fails.
+  static void VerifyUTF8StringNamedField(const char* data,
+                                         int size,
+                                         Operation op,
+                                         const char* field_name);
+
+ private:
+  // Skip a MessageSet field.
+  static bool SkipMessageSetField(io::CodedInputStream* input,
+                                  uint32 field_number,
+                                  UnknownFieldSet* unknown_fields);
+
+  // Parse a MessageSet field.
+  static bool ParseAndMergeMessageSetField(uint32 field_number,
+                                           const FieldDescriptor* field,
+                                           Message* message,
+                                           io::CodedInputStream* input);
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
+};
+
+// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet.
+class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
+ public:
+  UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields)
+      : unknown_fields_(unknown_fields) {}
+  virtual ~UnknownFieldSetFieldSkipper() {}
+
+  // implements FieldSkipper -----------------------------------------
+  virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
+  virtual bool SkipMessage(io::CodedInputStream* input);
+  virtual void SkipUnknownEnum(int field_number, int value);
+
+ protected:
+  UnknownFieldSet* unknown_fields_;
+};
+
+// inline methods ====================================================
+
+inline WireFormatLite::WireType WireFormat::WireTypeForField(
+    const FieldDescriptor* field) {
+  if (field->is_packed()) {
+    return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+  } else {
+    return WireTypeForFieldType(field->type());
+  }
+}
+
+inline WireFormatLite::WireType WireFormat::WireTypeForFieldType(
+    FieldDescriptor::Type type) {
+  // Some compilers don't like enum -> enum casts, so we implicit_cast to
+  // int first.
+  return WireFormatLite::WireTypeForFieldType(
+      static_cast<WireFormatLite::FieldType>(
+        implicit_cast<int>(type)));
+}
+
+inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
+  return WireFormatLite::MakeTag(field->number(), WireTypeForField(field));
+}
+
+inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) {
+  // Some compilers don't like enum -> enum casts, so we implicit_cast to
+  // int first.
+  return WireFormatLite::TagSize(field_number,
+      static_cast<WireFormatLite::FieldType>(
+        implicit_cast<int>(type)));
+}
+
+inline void WireFormat::VerifyUTF8String(const char* data, int size,
+    WireFormat::Operation op) {
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  WireFormatLite::VerifyUtf8String(
+      data, size, static_cast<WireFormatLite::Operation>(op), NULL);
+#else
+  // Avoid the compiler warning about unsued variables.
+  (void)data; (void)size; (void)op;
+#endif
+}
+
+inline void WireFormat::VerifyUTF8StringNamedField(
+    const char* data, int size, WireFormat::Operation op,
+    const char* field_name) {
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  WireFormatLite::VerifyUtf8String(
+      data, size, static_cast<WireFormatLite::Operation>(op), field_name);
+#endif
+}
+
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.cc b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.cc
new file mode 100644
index 0000000..f251707
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.cc
@@ -0,0 +1,543 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/wire_format_lite_inl.h>
+
+#include <stack>
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/io/coded_stream_inl.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+// Old version of MSVC doesn't like definitions of inline constants, GCC
+// requires them.
+const int WireFormatLite::kMessageSetItemStartTag;
+const int WireFormatLite::kMessageSetItemEndTag;
+const int WireFormatLite::kMessageSetTypeIdTag;
+const int WireFormatLite::kMessageSetMessageTag;
+
+#endif
+
+// IBM xlC requires prefixing constants with WireFormatLite::
+const int WireFormatLite::kMessageSetItemTagsSize =
+  io::CodedOutputStream::StaticVarintSize32<
+      WireFormatLite::kMessageSetItemStartTag>::value +
+  io::CodedOutputStream::StaticVarintSize32<
+      WireFormatLite::kMessageSetItemEndTag>::value +
+  io::CodedOutputStream::StaticVarintSize32<
+      WireFormatLite::kMessageSetTypeIdTag>::value +
+  io::CodedOutputStream::StaticVarintSize32<
+      WireFormatLite::kMessageSetMessageTag>::value;
+
+const WireFormatLite::CppType
+WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
+  static_cast<CppType>(0),  // 0 is reserved for errors
+
+  CPPTYPE_DOUBLE,   // TYPE_DOUBLE
+  CPPTYPE_FLOAT,    // TYPE_FLOAT
+  CPPTYPE_INT64,    // TYPE_INT64
+  CPPTYPE_UINT64,   // TYPE_UINT64
+  CPPTYPE_INT32,    // TYPE_INT32
+  CPPTYPE_UINT64,   // TYPE_FIXED64
+  CPPTYPE_UINT32,   // TYPE_FIXED32
+  CPPTYPE_BOOL,     // TYPE_BOOL
+  CPPTYPE_STRING,   // TYPE_STRING
+  CPPTYPE_MESSAGE,  // TYPE_GROUP
+  CPPTYPE_MESSAGE,  // TYPE_MESSAGE
+  CPPTYPE_STRING,   // TYPE_BYTES
+  CPPTYPE_UINT32,   // TYPE_UINT32
+  CPPTYPE_ENUM,     // TYPE_ENUM
+  CPPTYPE_INT32,    // TYPE_SFIXED32
+  CPPTYPE_INT64,    // TYPE_SFIXED64
+  CPPTYPE_INT32,    // TYPE_SINT32
+  CPPTYPE_INT64,    // TYPE_SINT64
+};
+
+const WireFormatLite::WireType
+WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
+  static_cast<WireFormatLite::WireType>(-1),  // invalid
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_DOUBLE
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_FLOAT
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_INT64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_UINT64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_INT32
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_FIXED64
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_FIXED32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_BOOL
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_STRING
+  WireFormatLite::WIRETYPE_START_GROUP,       // TYPE_GROUP
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_MESSAGE
+  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,  // TYPE_BYTES
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_UINT32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_ENUM
+  WireFormatLite::WIRETYPE_FIXED32,           // TYPE_SFIXED32
+  WireFormatLite::WIRETYPE_FIXED64,           // TYPE_SFIXED64
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_SINT32
+  WireFormatLite::WIRETYPE_VARINT,            // TYPE_SINT64
+};
+
+bool WireFormatLite::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  switch (WireFormatLite::GetTagWireType(tag)) {
+    case WireFormatLite::WIRETYPE_VARINT: {
+      uint64 value;
+      if (!input->ReadVarint64(&value)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_FIXED64: {
+      uint64 value;
+      if (!input->ReadLittleEndian64(&value)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+      uint32 length;
+      if (!input->ReadVarint32(&length)) return false;
+      if (!input->Skip(length)) return false;
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_START_GROUP: {
+      if (!input->IncrementRecursionDepth()) return false;
+      if (!SkipMessage(input)) return false;
+      input->DecrementRecursionDepth();
+      // Check that the ending tag matched the starting tag.
+      if (!input->LastTagWas(WireFormatLite::MakeTag(
+          WireFormatLite::GetTagFieldNumber(tag),
+          WireFormatLite::WIRETYPE_END_GROUP))) {
+        return false;
+      }
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_END_GROUP: {
+      return false;
+    }
+    case WireFormatLite::WIRETYPE_FIXED32: {
+      uint32 value;
+      if (!input->ReadLittleEndian32(&value)) return false;
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+bool WireFormatLite::SkipField(
+    io::CodedInputStream* input, uint32 tag, io::CodedOutputStream* output) {
+  switch (WireFormatLite::GetTagWireType(tag)) {
+    case WireFormatLite::WIRETYPE_VARINT: {
+      uint64 value;
+      if (!input->ReadVarint64(&value)) return false;
+      output->WriteVarint32(tag);
+      output->WriteVarint64(value);
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_FIXED64: {
+      uint64 value;
+      if (!input->ReadLittleEndian64(&value)) return false;
+      output->WriteVarint32(tag);
+      output->WriteLittleEndian64(value);
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+      uint32 length;
+      if (!input->ReadVarint32(&length)) return false;
+      output->WriteVarint32(tag);
+      output->WriteVarint32(length);
+      // TODO(mkilavuz): Provide API to prevent extra string copying.
+      string temp;
+      if (!input->ReadString(&temp, length)) return false;
+      output->WriteString(temp);
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_START_GROUP: {
+      output->WriteVarint32(tag);
+      if (!input->IncrementRecursionDepth()) return false;
+      if (!SkipMessage(input, output)) return false;
+      input->DecrementRecursionDepth();
+      // Check that the ending tag matched the starting tag.
+      if (!input->LastTagWas(WireFormatLite::MakeTag(
+          WireFormatLite::GetTagFieldNumber(tag),
+          WireFormatLite::WIRETYPE_END_GROUP))) {
+        return false;
+      }
+      return true;
+    }
+    case WireFormatLite::WIRETYPE_END_GROUP: {
+      return false;
+    }
+    case WireFormatLite::WIRETYPE_FIXED32: {
+      uint32 value;
+      if (!input->ReadLittleEndian32(&value)) return false;
+      output->WriteVarint32(tag);
+      output->WriteLittleEndian32(value);
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) {
+      // End of input.  This is a valid place to end, so return true.
+      return true;
+    }
+
+    WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
+
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+      // Must be the end of the message.
+      return true;
+    }
+
+    if (!SkipField(input, tag)) return false;
+  }
+}
+
+bool WireFormatLite::SkipMessage(io::CodedInputStream* input,
+    io::CodedOutputStream* output) {
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) {
+      // End of input.  This is a valid place to end, so return true.
+      return true;
+    }
+
+    WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
+
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+      output->WriteVarint32(tag);
+      // Must be the end of the message.
+      return true;
+    }
+
+    if (!SkipField(input, tag, output)) return false;
+  }
+}
+
+bool FieldSkipper::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  return WireFormatLite::SkipField(input, tag);
+}
+
+bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
+  return WireFormatLite::SkipMessage(input);
+}
+
+void FieldSkipper::SkipUnknownEnum(
+    int /* field_number */, int /* value */) {
+  // Nothing.
+}
+
+bool CodedOutputStreamFieldSkipper::SkipField(
+    io::CodedInputStream* input, uint32 tag) {
+  return WireFormatLite::SkipField(input, tag, unknown_fields_);
+}
+
+bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
+  return WireFormatLite::SkipMessage(input, unknown_fields_);
+}
+
+void CodedOutputStreamFieldSkipper::SkipUnknownEnum(
+    int field_number, int value) {
+  unknown_fields_->WriteVarint32(field_number);
+  unknown_fields_->WriteVarint64(value);
+}
+
+bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
+                                            bool (*is_valid)(int),
+                                            RepeatedField<int>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    int value;
+    if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+        int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+      return false;
+    }
+    if (is_valid == NULL || is_valid(value)) {
+      values->Add(value);
+    }
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
+bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
+    io::CodedInputStream* input,
+    int field_number,
+    bool (*is_valid)(int),
+    io::CodedOutputStream* unknown_fields_stream,
+    RepeatedField<int>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    int value;
+    if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+        int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+      return false;
+    }
+    if (is_valid == NULL || is_valid(value)) {
+      values->Add(value);
+    } else {
+      uint32 tag = WireFormatLite::MakeTag(field_number,
+                                           WireFormatLite::WIRETYPE_VARINT);
+      unknown_fields_stream->WriteVarint32(tag);
+      unknown_fields_stream->WriteVarint32(value);
+    }
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
+void WireFormatLite::WriteInt32(int field_number, int32 value,
+                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteInt32NoTag(value, output);
+}
+void WireFormatLite::WriteInt64(int field_number, int64 value,
+                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteInt64NoTag(value, output);
+}
+void WireFormatLite::WriteUInt32(int field_number, uint32 value,
+                                 io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteUInt32NoTag(value, output);
+}
+void WireFormatLite::WriteUInt64(int field_number, uint64 value,
+                                 io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteUInt64NoTag(value, output);
+}
+void WireFormatLite::WriteSInt32(int field_number, int32 value,
+                                 io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteSInt32NoTag(value, output);
+}
+void WireFormatLite::WriteSInt64(int field_number, int64 value,
+                                 io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteSInt64NoTag(value, output);
+}
+void WireFormatLite::WriteFixed32(int field_number, uint32 value,
+                                  io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteFixed64(int field_number, uint64 value,
+                                  io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed32(int field_number, int32 value,
+                                   io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteSFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed64(int field_number, int64 value,
+                                   io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteSFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteFloat(int field_number, float value,
+                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED32, output);
+  WriteFloatNoTag(value, output);
+}
+void WireFormatLite::WriteDouble(int field_number, double value,
+                                 io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_FIXED64, output);
+  WriteDoubleNoTag(value, output);
+}
+void WireFormatLite::WriteBool(int field_number, bool value,
+                               io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteBoolNoTag(value, output);
+}
+void WireFormatLite::WriteEnum(int field_number, int value,
+                               io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_VARINT, output);
+  WriteEnumNoTag(value, output);
+}
+
+void WireFormatLite::WriteString(int field_number, const string& value,
+                                 io::CodedOutputStream* output) {
+  // String is for UTF-8 text only
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
+  output->WriteVarint32(value.size());
+  output->WriteString(value);
+}
+void WireFormatLite::WriteStringMaybeAliased(
+    int field_number, const string& value,
+    io::CodedOutputStream* output) {
+  // String is for UTF-8 text only
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
+  output->WriteVarint32(value.size());
+  output->WriteRawMaybeAliased(value.data(), value.size());
+}
+void WireFormatLite::WriteBytes(int field_number, const string& value,
+                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
+  output->WriteVarint32(value.size());
+  output->WriteString(value);
+}
+void WireFormatLite::WriteBytesMaybeAliased(
+    int field_number, const string& value,
+    io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
+  output->WriteVarint32(value.size());
+  output->WriteRawMaybeAliased(value.data(), value.size());
+}
+
+
+void WireFormatLite::WriteGroup(int field_number,
+                                const MessageLite& value,
+                                io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_START_GROUP, output);
+  value.SerializeWithCachedSizes(output);
+  WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+
+void WireFormatLite::WriteMessage(int field_number,
+                                  const MessageLite& value,
+                                  io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  const int size = value.GetCachedSize();
+  output->WriteVarint32(size);
+  value.SerializeWithCachedSizes(output);
+}
+
+void WireFormatLite::WriteGroupMaybeToArray(int field_number,
+                                            const MessageLite& value,
+                                            io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_START_GROUP, output);
+  const int size = value.GetCachedSize();
+  uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+  if (target != NULL) {
+    uint8* end = value.SerializeWithCachedSizesToArray(target);
+    GOOGLE_DCHECK_EQ(end - target, size);
+  } else {
+    value.SerializeWithCachedSizes(output);
+  }
+  WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+
+void WireFormatLite::WriteMessageMaybeToArray(int field_number,
+                                              const MessageLite& value,
+                                              io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  const int size = value.GetCachedSize();
+  output->WriteVarint32(size);
+  uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+  if (target != NULL) {
+    uint8* end = value.SerializeWithCachedSizesToArray(target);
+    GOOGLE_DCHECK_EQ(end - target, size);
+  } else {
+    value.SerializeWithCachedSizes(output);
+  }
+}
+
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
+    io::CodedInputStream* input, string* value);
+inline static bool ReadBytesToString(io::CodedInputStream* input,
+                                     string* value) {
+  uint32 length;
+  return input->ReadVarint32(&length) &&
+      input->InternalReadStringInline(value, length);
+}
+
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string* value) {
+  return ReadBytesToString(input, value);
+}
+
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
+  if (*p == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    *p = new ::std::string();
+  }
+  return ReadBytesToString(input, *p);
+}
+
+bool WireFormatLite::VerifyUtf8String(const char* data,
+                                      int size,
+                                      Operation op,
+                                      const char* field_name) {
+  if (!IsStructurallyValidUTF8(data, size)) {
+    const char* operation_str = NULL;
+    switch (op) {
+      case PARSE:
+        operation_str = "parsing";
+        break;
+      case SERIALIZE:
+        operation_str = "serializing";
+        break;
+      // no default case: have the compiler warn if a case is not covered.
+    }
+    string quoted_field_name = "";
+    if (field_name != NULL) {
+      quoted_field_name = StringPrintf(" '%s'", field_name);
+    }
+    // no space below to avoid double space when the field name is missing.
+    GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
+               << "UTF-8 data when " << operation_str << " a protocol "
+               << "buffer. Use the 'bytes' type if you intend to send raw "
+               << "bytes. ";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.h b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.h
new file mode 100644
index 0000000..55fc7ec
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite.h
@@ -0,0 +1,696 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//         atenasio@google.com (Chris Atenasio) (ZigZag transform)
+//         wink@google.com (Wink Saville) (refactored from wire_format.h)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/io/coded_stream.h>  // for CodedOutputStream::Varint32Size
+
+namespace google {
+
+namespace protobuf {
+  template <typename T> class RepeatedField;  // repeated_field.h
+}
+
+namespace protobuf {
+namespace internal {
+
+class StringPieceField;
+
+// This class is for internal use by the protocol buffer library and by
+// protocol-complier-generated message classes.  It must not be called
+// directly by clients.
+//
+// This class contains helpers for implementing the binary protocol buffer
+// wire format without the need for reflection. Use WireFormat when using
+// reflection.
+//
+// This class is really a namespace that contains only static methods.
+class LIBPROTOBUF_EXPORT WireFormatLite {
+ public:
+
+  // -----------------------------------------------------------------
+  // Helper constants and functions related to the format.  These are
+  // mostly meant for internal and generated code to use.
+
+  // The wire format is composed of a sequence of tag/value pairs, each
+  // of which contains the value of one field (or one element of a repeated
+  // field).  Each tag is encoded as a varint.  The lower bits of the tag
+  // identify its wire type, which specifies the format of the data to follow.
+  // The rest of the bits contain the field number.  Each type of field (as
+  // declared by FieldDescriptor::Type, in descriptor.h) maps to one of
+  // these wire types.  Immediately following each tag is the field's value,
+  // encoded in the format specified by the wire type.  Because the tag
+  // identifies the encoding of this data, it is possible to skip
+  // unrecognized fields for forwards compatibility.
+
+  enum WireType {
+    WIRETYPE_VARINT           = 0,
+    WIRETYPE_FIXED64          = 1,
+    WIRETYPE_LENGTH_DELIMITED = 2,
+    WIRETYPE_START_GROUP      = 3,
+    WIRETYPE_END_GROUP        = 4,
+    WIRETYPE_FIXED32          = 5,
+  };
+
+  // Lite alternative to FieldDescriptor::Type.  Must be kept in sync.
+  enum FieldType {
+    TYPE_DOUBLE         = 1,
+    TYPE_FLOAT          = 2,
+    TYPE_INT64          = 3,
+    TYPE_UINT64         = 4,
+    TYPE_INT32          = 5,
+    TYPE_FIXED64        = 6,
+    TYPE_FIXED32        = 7,
+    TYPE_BOOL           = 8,
+    TYPE_STRING         = 9,
+    TYPE_GROUP          = 10,
+    TYPE_MESSAGE        = 11,
+    TYPE_BYTES          = 12,
+    TYPE_UINT32         = 13,
+    TYPE_ENUM           = 14,
+    TYPE_SFIXED32       = 15,
+    TYPE_SFIXED64       = 16,
+    TYPE_SINT32         = 17,
+    TYPE_SINT64         = 18,
+    MAX_FIELD_TYPE      = 18,
+  };
+
+  // Lite alternative to FieldDescriptor::CppType.  Must be kept in sync.
+  enum CppType {
+    CPPTYPE_INT32       = 1,
+    CPPTYPE_INT64       = 2,
+    CPPTYPE_UINT32      = 3,
+    CPPTYPE_UINT64      = 4,
+    CPPTYPE_DOUBLE      = 5,
+    CPPTYPE_FLOAT       = 6,
+    CPPTYPE_BOOL        = 7,
+    CPPTYPE_ENUM        = 8,
+    CPPTYPE_STRING      = 9,
+    CPPTYPE_MESSAGE     = 10,
+    MAX_CPPTYPE         = 10,
+  };
+
+  // Helper method to get the CppType for a particular Type.
+  static CppType FieldTypeToCppType(FieldType type);
+
+  // Given a FieldSescriptor::Type return its WireType
+  static inline WireFormatLite::WireType WireTypeForFieldType(
+      WireFormatLite::FieldType type) {
+    return kWireTypeForFieldType[type];
+  }
+
+  // Number of bits in a tag which identify the wire type.
+  static const int kTagTypeBits = 3;
+  // Mask for those bits.
+  static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
+
+  // Helper functions for encoding and decoding tags.  (Inlined below and in
+  // _inl.h)
+  //
+  // This is different from MakeTag(field->number(), field->type()) in the case
+  // of packed repeated fields.
+  static uint32 MakeTag(int field_number, WireType type);
+  static WireType GetTagWireType(uint32 tag);
+  static int GetTagFieldNumber(uint32 tag);
+
+  // Compute the byte size of a tag.  For groups, this includes both the start
+  // and end tags.
+  static inline int TagSize(int field_number, WireFormatLite::FieldType type);
+
+  // Skips a field value with the given tag.  The input should start
+  // positioned immediately after the tag.  Skipped values are simply discarded,
+  // not recorded anywhere.  See WireFormat::SkipField() for a version that
+  // records to an UnknownFieldSet.
+  static bool SkipField(io::CodedInputStream* input, uint32 tag);
+
+  // Skips a field value with the given tag.  The input should start
+  // positioned immediately after the tag. Skipped values are recorded to a
+  // CodedOutputStream.
+  static bool SkipField(io::CodedInputStream* input, uint32 tag,
+                        io::CodedOutputStream* output);
+
+  // Reads and ignores a message from the input.  Skipped values are simply
+  // discarded, not recorded anywhere.  See WireFormat::SkipMessage() for a
+  // version that records to an UnknownFieldSet.
+  static bool SkipMessage(io::CodedInputStream* input);
+
+  // Reads and ignores a message from the input.  Skipped values are recorded
+  // to a CodedOutputStream.
+  static bool SkipMessage(io::CodedInputStream* input,
+                          io::CodedOutputStream* output);
+
+// This macro does the same thing as WireFormatLite::MakeTag(), but the
+// result is usable as a compile-time constant, which makes it usable
+// as a switch case or a template input.  WireFormatLite::MakeTag() is more
+// type-safe, though, so prefer it if possible.
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE)                  \
+  static_cast<uint32>(                                                   \
+    ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \
+      | (TYPE))
+
+  // These are the tags for the old MessageSet format, which was defined as:
+  //   message MessageSet {
+  //     repeated group Item = 1 {
+  //       required int32 type_id = 2;
+  //       required string message = 3;
+  //     }
+  //   }
+  static const int kMessageSetItemNumber = 1;
+  static const int kMessageSetTypeIdNumber = 2;
+  static const int kMessageSetMessageNumber = 3;
+  static const int kMessageSetItemStartTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+                                WireFormatLite::WIRETYPE_START_GROUP);
+  static const int kMessageSetItemEndTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+                                WireFormatLite::WIRETYPE_END_GROUP);
+  static const int kMessageSetTypeIdTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
+                                WireFormatLite::WIRETYPE_VARINT);
+  static const int kMessageSetMessageTag =
+    GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
+                                WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+  // Byte size of all tags of a MessageSet::Item combined.
+  static const int kMessageSetItemTagsSize;
+
+  // Helper functions for converting between floats/doubles and IEEE-754
+  // uint32s/uint64s so that they can be written.  (Assumes your platform
+  // uses IEEE-754 floats.)
+  static uint32 EncodeFloat(float value);
+  static float DecodeFloat(uint32 value);
+  static uint64 EncodeDouble(double value);
+  static double DecodeDouble(uint64 value);
+
+  // Helper functions for mapping signed integers to unsigned integers in
+  // such a way that numbers with small magnitudes will encode to smaller
+  // varints.  If you simply static_cast a negative number to an unsigned
+  // number and varint-encode it, it will always take 10 bytes, defeating
+  // the purpose of varint.  So, for the "sint32" and "sint64" field types,
+  // we ZigZag-encode the values.
+  static uint32 ZigZagEncode32(int32 n);
+  static int32  ZigZagDecode32(uint32 n);
+  static uint64 ZigZagEncode64(int64 n);
+  static int64  ZigZagDecode64(uint64 n);
+
+  // =================================================================
+  // Methods for reading/writing individual field.  The implementations
+  // of these methods are defined in wire_format_lite_inl.h; you must #include
+  // that file to use these.
+
+// Avoid ugly line wrapping
+#define input  io::CodedInputStream*  input_arg
+#define output io::CodedOutputStream* output_arg
+#define field_number int field_number_arg
+#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+
+  // Read fields, not including tags.  The assumption is that you already
+  // read the tag to determine what field to read.
+
+  // For primitive fields, we just use a templatized routine parameterized by
+  // the represented type and the FieldType. These are specialized with the
+  // appropriate definition for each declared type.
+  template <typename CType, enum FieldType DeclaredType> INL
+  static bool ReadPrimitive(input, CType* value);
+
+  // Reads repeated primitive values, with optimizations for repeats.
+  // tag_size and tag should both be compile-time constants provided by the
+  // protocol compiler.
+  template <typename CType, enum FieldType DeclaredType> INL
+  static bool ReadRepeatedPrimitive(int tag_size,
+                                    uint32 tag,
+                                    input,
+                                    RepeatedField<CType>* value);
+
+  // Identical to ReadRepeatedPrimitive, except will not inline the
+  // implementation.
+  template <typename CType, enum FieldType DeclaredType>
+  static bool ReadRepeatedPrimitiveNoInline(int tag_size,
+                                            uint32 tag,
+                                            input,
+                                            RepeatedField<CType>* value);
+
+  // Reads a primitive value directly from the provided buffer. It returns a
+  // pointer past the segment of data that was read.
+  //
+  // This is only implemented for the types with fixed wire size, e.g.
+  // float, double, and the (s)fixed* types.
+  template <typename CType, enum FieldType DeclaredType> INL
+  static const uint8* ReadPrimitiveFromArray(const uint8* buffer, CType* value);
+
+  // Reads a primitive packed field.
+  //
+  // This is only implemented for packable types.
+  template <typename CType, enum FieldType DeclaredType> INL
+  static bool ReadPackedPrimitive(input, RepeatedField<CType>* value);
+
+  // Identical to ReadPackedPrimitive, except will not inline the
+  // implementation.
+  template <typename CType, enum FieldType DeclaredType>
+  static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
+
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are silently dropped.
+  static bool ReadPackedEnumNoInline(input,
+                                     bool (*is_valid)(int),
+                                     RepeatedField<int>* values);
+
+  // Read a packed enum field. If the is_valid function is not NULL, values for
+  // which is_valid(value) returns false are appended to unknown_fields_stream.
+  static bool ReadPackedEnumPreserveUnknowns(
+      input,
+      field_number,
+      bool (*is_valid)(int),
+      io::CodedOutputStream* unknown_fields_stream,
+      RepeatedField<int>* values);
+
+  // Read a string.  ReadString(..., string* value) requires an existing string.
+  static inline bool ReadString(input, string* value);
+  // ReadString(..., string** p) is internal-only, and should only be called
+  // from generated code. It starts by setting *p to "new string"
+  // if *p == &GetEmptyStringAlreadyInited().  It then invokes
+  // ReadString(input, *p).  This is useful for reducing code size.
+  static inline bool ReadString(input, string** p);
+  // Analogous to ReadString().
+  static bool ReadBytes(input, string* value);
+  static bool ReadBytes(input, string** p);
+
+
+  enum Operation {
+    PARSE = 0,
+    SERIALIZE = 1,
+  };
+
+  // Returns true if the data is valid UTF-8.
+  static bool VerifyUtf8String(const char* data, int size,
+                               Operation op,
+                               const char* field_name);
+
+  static inline bool ReadGroup  (field_number, input, MessageLite* value);
+  static inline bool ReadMessage(input, MessageLite* value);
+
+  // Like above, but de-virtualize the call to MergePartialFromCodedStream().
+  // The pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override MergePartialFromCodedStream()).
+  template<typename MessageType>
+  static inline bool ReadGroupNoVirtual(field_number, input,
+                                        MessageType* value);
+  template<typename MessageType>
+  static inline bool ReadMessageNoVirtual(input, MessageType* value);
+
+  // The same, but do not modify input's recursion depth.  This is useful
+  // when reading a bunch of groups or messages in a loop, because then the
+  // recursion depth can be incremented before the loop and decremented after.
+  template<typename MessageType>
+  static inline bool ReadGroupNoVirtualNoRecursionDepth(field_number, input,
+                                                        MessageType* value);
+
+  template<typename MessageType>
+  static inline bool ReadMessageNoVirtualNoRecursionDepth(input,
+                                                          MessageType* value);
+
+  // Write a tag.  The Write*() functions typically include the tag, so
+  // normally there's no need to call this unless using the Write*NoTag()
+  // variants.
+  INL static void WriteTag(field_number, WireType type, output);
+
+  // Write fields, without tags.
+  INL static void WriteInt32NoTag   (int32 value, output);
+  INL static void WriteInt64NoTag   (int64 value, output);
+  INL static void WriteUInt32NoTag  (uint32 value, output);
+  INL static void WriteUInt64NoTag  (uint64 value, output);
+  INL static void WriteSInt32NoTag  (int32 value, output);
+  INL static void WriteSInt64NoTag  (int64 value, output);
+  INL static void WriteFixed32NoTag (uint32 value, output);
+  INL static void WriteFixed64NoTag (uint64 value, output);
+  INL static void WriteSFixed32NoTag(int32 value, output);
+  INL static void WriteSFixed64NoTag(int64 value, output);
+  INL static void WriteFloatNoTag   (float value, output);
+  INL static void WriteDoubleNoTag  (double value, output);
+  INL static void WriteBoolNoTag    (bool value, output);
+  INL static void WriteEnumNoTag    (int value, output);
+
+  // Write fields, including tags.
+  static void WriteInt32   (field_number,  int32 value, output);
+  static void WriteInt64   (field_number,  int64 value, output);
+  static void WriteUInt32  (field_number, uint32 value, output);
+  static void WriteUInt64  (field_number, uint64 value, output);
+  static void WriteSInt32  (field_number,  int32 value, output);
+  static void WriteSInt64  (field_number,  int64 value, output);
+  static void WriteFixed32 (field_number, uint32 value, output);
+  static void WriteFixed64 (field_number, uint64 value, output);
+  static void WriteSFixed32(field_number,  int32 value, output);
+  static void WriteSFixed64(field_number,  int64 value, output);
+  static void WriteFloat   (field_number,  float value, output);
+  static void WriteDouble  (field_number, double value, output);
+  static void WriteBool    (field_number,   bool value, output);
+  static void WriteEnum    (field_number,    int value, output);
+
+  static void WriteString(field_number, const string& value, output);
+  static void WriteBytes (field_number, const string& value, output);
+  static void WriteStringMaybeAliased(
+      field_number, const string& value, output);
+  static void WriteBytesMaybeAliased(
+      field_number, const string& value, output);
+
+  static void WriteGroup(
+    field_number, const MessageLite& value, output);
+  static void WriteMessage(
+    field_number, const MessageLite& value, output);
+  // Like above, but these will check if the output stream has enough
+  // space to write directly to a flat array.
+  static void WriteGroupMaybeToArray(
+    field_number, const MessageLite& value, output);
+  static void WriteMessageMaybeToArray(
+    field_number, const MessageLite& value, output);
+
+  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override SerializeWithCachedSizes()).
+  template<typename MessageType>
+  static inline void WriteGroupNoVirtual(
+    field_number, const MessageType& value, output);
+  template<typename MessageType>
+  static inline void WriteMessageNoVirtual(
+    field_number, const MessageType& value, output);
+
+#undef output
+#define output uint8* target
+
+  // Like above, but use only *ToArray methods of CodedOutputStream.
+  INL static uint8* WriteTagToArray(field_number, WireType type, output);
+
+  // Write fields, without tags.
+  INL static uint8* WriteInt32NoTagToArray   (int32 value, output);
+  INL static uint8* WriteInt64NoTagToArray   (int64 value, output);
+  INL static uint8* WriteUInt32NoTagToArray  (uint32 value, output);
+  INL static uint8* WriteUInt64NoTagToArray  (uint64 value, output);
+  INL static uint8* WriteSInt32NoTagToArray  (int32 value, output);
+  INL static uint8* WriteSInt64NoTagToArray  (int64 value, output);
+  INL static uint8* WriteFixed32NoTagToArray (uint32 value, output);
+  INL static uint8* WriteFixed64NoTagToArray (uint64 value, output);
+  INL static uint8* WriteSFixed32NoTagToArray(int32 value, output);
+  INL static uint8* WriteSFixed64NoTagToArray(int64 value, output);
+  INL static uint8* WriteFloatNoTagToArray   (float value, output);
+  INL static uint8* WriteDoubleNoTagToArray  (double value, output);
+  INL static uint8* WriteBoolNoTagToArray    (bool value, output);
+  INL static uint8* WriteEnumNoTagToArray    (int value, output);
+
+  // Write fields, including tags.
+  INL static uint8* WriteInt32ToArray(field_number, int32 value, output);
+  INL static uint8* WriteInt64ToArray(field_number, int64 value, output);
+  INL static uint8* WriteUInt32ToArray(field_number, uint32 value, output);
+  INL static uint8* WriteUInt64ToArray(field_number, uint64 value, output);
+  INL static uint8* WriteSInt32ToArray(field_number, int32 value, output);
+  INL static uint8* WriteSInt64ToArray(field_number, int64 value, output);
+  INL static uint8* WriteFixed32ToArray(field_number, uint32 value, output);
+  INL static uint8* WriteFixed64ToArray(field_number, uint64 value, output);
+  INL static uint8* WriteSFixed32ToArray(field_number, int32 value, output);
+  INL static uint8* WriteSFixed64ToArray(field_number, int64 value, output);
+  INL static uint8* WriteFloatToArray(field_number, float value, output);
+  INL static uint8* WriteDoubleToArray(field_number, double value, output);
+  INL static uint8* WriteBoolToArray(field_number, bool value, output);
+  INL static uint8* WriteEnumToArray(field_number, int value, output);
+
+  INL static uint8* WriteStringToArray(
+    field_number, const string& value, output);
+  INL static uint8* WriteBytesToArray(
+    field_number, const string& value, output);
+
+  INL static uint8* WriteGroupToArray(
+      field_number, const MessageLite& value, output);
+  INL static uint8* WriteMessageToArray(
+      field_number, const MessageLite& value, output);
+
+  // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override SerializeWithCachedSizes()).
+  template<typename MessageType>
+  INL static uint8* WriteGroupNoVirtualToArray(
+    field_number, const MessageType& value, output);
+  template<typename MessageType>
+  INL static uint8* WriteMessageNoVirtualToArray(
+    field_number, const MessageType& value, output);
+
+#undef output
+#undef input
+#undef INL
+
+#undef field_number
+
+  // Compute the byte size of a field.  The XxSize() functions do NOT include
+  // the tag, so you must also call TagSize().  (This is because, for repeated
+  // fields, you should only call TagSize() once and multiply it by the element
+  // count, but you may have to call XxSize() for each individual element.)
+  static inline int Int32Size   ( int32 value);
+  static inline int Int64Size   ( int64 value);
+  static inline int UInt32Size  (uint32 value);
+  static inline int UInt64Size  (uint64 value);
+  static inline int SInt32Size  ( int32 value);
+  static inline int SInt64Size  ( int64 value);
+  static inline int EnumSize    (   int value);
+
+  // These types always have the same size.
+  static const int kFixed32Size  = 4;
+  static const int kFixed64Size  = 8;
+  static const int kSFixed32Size = 4;
+  static const int kSFixed64Size = 8;
+  static const int kFloatSize    = 4;
+  static const int kDoubleSize   = 8;
+  static const int kBoolSize     = 1;
+
+  static inline int StringSize(const string& value);
+  static inline int BytesSize (const string& value);
+
+  static inline int GroupSize  (const MessageLite& value);
+  static inline int MessageSize(const MessageLite& value);
+
+  // Like above, but de-virtualize the call to ByteSize().  The
+  // pointer must point at an instance of MessageType, *not* a subclass (or
+  // the subclass must not override ByteSize()).
+  template<typename MessageType>
+  static inline int GroupSizeNoVirtual  (const MessageType& value);
+  template<typename MessageType>
+  static inline int MessageSizeNoVirtual(const MessageType& value);
+
+  // Given the length of data, calculate the byte size of the data on the
+  // wire if we encode the data as a length delimited field.
+  static inline int LengthDelimitedSize(int length);
+
+ private:
+  // A helper method for the repeated primitive reader. This method has
+  // optimizations for primitive types that have fixed size on the wire, and
+  // can be read using potentially faster paths.
+  template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static bool ReadRepeatedFixedSizePrimitive(
+      int tag_size,
+      uint32 tag,
+      google::protobuf::io::CodedInputStream* input,
+      RepeatedField<CType>* value);
+
+  // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
+  template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  static bool ReadPackedFixedSizePrimitive(google::protobuf::io::CodedInputStream* input,
+                                           RepeatedField<CType>* value);
+
+  static const CppType kFieldTypeToCppTypeMap[];
+  static const WireFormatLite::WireType kWireTypeForFieldType[];
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
+};
+
+// A class which deals with unknown values.  The default implementation just
+// discards them.  WireFormat defines a subclass which writes to an
+// UnknownFieldSet.  This class is used by ExtensionSet::ParseField(), since
+// ExtensionSet is part of the lite library but UnknownFieldSet is not.
+class LIBPROTOBUF_EXPORT FieldSkipper {
+ public:
+  FieldSkipper() {}
+  virtual ~FieldSkipper() {}
+
+  // Skip a field whose tag has already been consumed.
+  virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
+
+  // Skip an entire message or group, up to an end-group tag (which is consumed)
+  // or end-of-stream.
+  virtual bool SkipMessage(io::CodedInputStream* input);
+
+  // Deal with an already-parsed unrecognized enum value.  The default
+  // implementation does nothing, but the UnknownFieldSet-based implementation
+  // saves it as an unknown varint.
+  virtual void SkipUnknownEnum(int field_number, int value);
+};
+
+// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream.
+
+class LIBPROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper {
+ public:
+  explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields)
+      : unknown_fields_(unknown_fields) {}
+  virtual ~CodedOutputStreamFieldSkipper() {}
+
+  // implements FieldSkipper -----------------------------------------
+  virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
+  virtual bool SkipMessage(io::CodedInputStream* input);
+  virtual void SkipUnknownEnum(int field_number, int value);
+
+ protected:
+  io::CodedOutputStream* unknown_fields_;
+};
+
+
+// inline methods ====================================================
+
+inline WireFormatLite::CppType
+WireFormatLite::FieldTypeToCppType(FieldType type) {
+  return kFieldTypeToCppTypeMap[type];
+}
+
+inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) {
+  return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
+}
+
+inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) {
+  return static_cast<WireType>(tag & kTagTypeMask);
+}
+
+inline int WireFormatLite::GetTagFieldNumber(uint32 tag) {
+  return static_cast<int>(tag >> kTagTypeBits);
+}
+
+inline int WireFormatLite::TagSize(int field_number,
+                                   WireFormatLite::FieldType type) {
+  int result = io::CodedOutputStream::VarintSize32(
+    field_number << kTagTypeBits);
+  if (type == TYPE_GROUP) {
+    // Groups have both a start and an end tag.
+    return result * 2;
+  } else {
+    return result;
+  }
+}
+
+inline uint32 WireFormatLite::EncodeFloat(float value) {
+  union {float f; uint32 i;};
+  f = value;
+  return i;
+}
+
+inline float WireFormatLite::DecodeFloat(uint32 value) {
+  union {float f; uint32 i;};
+  i = value;
+  return f;
+}
+
+inline uint64 WireFormatLite::EncodeDouble(double value) {
+  union {double f; uint64 i;};
+  f = value;
+  return i;
+}
+
+inline double WireFormatLite::DecodeDouble(uint64 value) {
+  union {double f; uint64 i;};
+  i = value;
+  return f;
+}
+
+// ZigZag Transform:  Encodes signed integers so that they can be
+// effectively used with varint encoding.
+//
+// varint operates on unsigned integers, encoding smaller numbers into
+// fewer bytes.  If you try to use it on a signed integer, it will treat
+// this number as a very large unsigned integer, which means that even
+// small signed numbers like -1 will take the maximum number of bytes
+// (10) to encode.  ZigZagEncode() maps signed integers to unsigned
+// in such a way that those with a small absolute value will have smaller
+// encoded values, making them appropriate for encoding using varint.
+//
+//       int32 ->     uint32
+// -------------------------
+//           0 ->          0
+//          -1 ->          1
+//           1 ->          2
+//          -2 ->          3
+//         ... ->        ...
+//  2147483647 -> 4294967294
+// -2147483648 -> 4294967295
+//
+//        >> encode >>
+//        << decode <<
+
+inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
+  // Note:  the right-shift must be arithmetic
+  return (static_cast<uint32>(n) << 1) ^ (n >> 31);
+}
+
+inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
+  return (n >> 1) ^ -static_cast<int32>(n & 1);
+}
+
+inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
+  // Note:  the right-shift must be arithmetic
+  return (static_cast<uint64>(n) << 1) ^ (n >> 63);
+}
+
+inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
+  return (n >> 1) ^ -static_cast<int64>(n & 1);
+}
+
+// String is for UTF-8 text only, but, even so, ReadString() can simply
+// call ReadBytes().
+
+inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
+                                       string* value) {
+  return ReadBytes(input, value);
+}
+
+inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
+                                       string** p) {
+  return ReadBytes(input, p);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite_inl.h b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite_inl.h
new file mode 100644
index 0000000..7bce21c
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format_lite_inl.h
@@ -0,0 +1,878 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//         wink@google.com (Wink Saville) (refactored from wire_format.h)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
+#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
+
+#ifdef _MSC_VER
+// This is required for min/max on VS2013 only.
+#include <algorithm>
+#endif
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arenastring.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Implementation details of ReadPrimitive.
+
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(
+    io::CodedInputStream* input,
+    int32* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = static_cast<int32>(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>(
+    io::CodedInputStream* input,
+    int64* value) {
+  uint64 temp;
+  if (!input->ReadVarint64(&temp)) return false;
+  *value = static_cast<int64>(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(
+    io::CodedInputStream* input,
+    uint32* value) {
+  return input->ReadVarint32(value);
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(
+    io::CodedInputStream* input,
+    uint64* value) {
+  return input->ReadVarint64(value);
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(
+    io::CodedInputStream* input,
+    int32* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = ZigZagDecode32(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(
+    io::CodedInputStream* input,
+    int64* value) {
+  uint64 temp;
+  if (!input->ReadVarint64(&temp)) return false;
+  *value = ZigZagDecode64(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>(
+    io::CodedInputStream* input,
+    uint32* value) {
+  return input->ReadLittleEndian32(value);
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>(
+    io::CodedInputStream* input,
+    uint64* value) {
+  return input->ReadLittleEndian64(value);
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>(
+    io::CodedInputStream* input,
+    int32* value) {
+  uint32 temp;
+  if (!input->ReadLittleEndian32(&temp)) return false;
+  *value = static_cast<int32>(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>(
+    io::CodedInputStream* input,
+    int64* value) {
+  uint64 temp;
+  if (!input->ReadLittleEndian64(&temp)) return false;
+  *value = static_cast<int64>(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>(
+    io::CodedInputStream* input,
+    float* value) {
+  uint32 temp;
+  if (!input->ReadLittleEndian32(&temp)) return false;
+  *value = DecodeFloat(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>(
+    io::CodedInputStream* input,
+    double* value) {
+  uint64 temp;
+  if (!input->ReadLittleEndian64(&temp)) return false;
+  *value = DecodeDouble(temp);
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
+    io::CodedInputStream* input,
+    bool* value) {
+  uint64 temp;
+  if (!input->ReadVarint64(&temp)) return false;
+  *value = temp != 0;
+  return true;
+}
+template <>
+inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+    io::CodedInputStream* input,
+    int* value) {
+  uint32 temp;
+  if (!input->ReadVarint32(&temp)) return false;
+  *value = static_cast<int>(temp);
+  return true;
+}
+
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  uint32, WireFormatLite::TYPE_FIXED32>(
+    const uint8* buffer,
+    uint32* value) {
+  return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  uint64, WireFormatLite::TYPE_FIXED64>(
+    const uint8* buffer,
+    uint64* value) {
+  return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  int32, WireFormatLite::TYPE_SFIXED32>(
+    const uint8* buffer,
+    int32* value) {
+  uint32 temp;
+  buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+  *value = static_cast<int32>(temp);
+  return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  int64, WireFormatLite::TYPE_SFIXED64>(
+    const uint8* buffer,
+    int64* value) {
+  uint64 temp;
+  buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+  *value = static_cast<int64>(temp);
+  return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  float, WireFormatLite::TYPE_FLOAT>(
+    const uint8* buffer,
+    float* value) {
+  uint32 temp;
+  buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+  *value = DecodeFloat(temp);
+  return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+  double, WireFormatLite::TYPE_DOUBLE>(
+    const uint8* buffer,
+    double* value) {
+  uint64 temp;
+  buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+  *value = DecodeDouble(temp);
+  return buffer;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedPrimitive(
+    int,  // tag_size, unused.
+    uint32 tag,
+    io::CodedInputStream* input,
+    RepeatedField<CType>* values) {
+  CType value;
+  if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+  values->Add(value);
+  int elements_already_reserved = values->Capacity() - values->size();
+  while (elements_already_reserved > 0 && input->ExpectTag(tag)) {
+    if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+    values->AddAlreadyReserved(value);
+    elements_already_reserved--;
+  }
+  return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
+    int tag_size,
+    uint32 tag,
+    io::CodedInputStream* input,
+    RepeatedField<CType>* values) {
+  GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size);
+  CType value;
+  if (!ReadPrimitive<CType, DeclaredType>(input, &value))
+    return false;
+  values->Add(value);
+
+  // For fixed size values, repeated values can be read more quickly by
+  // reading directly from a raw array.
+  //
+  // We can get a tight loop by only reading as many elements as can be
+  // added to the RepeatedField without having to do any resizing. Additionally,
+  // we only try to read as many elements as are available from the current
+  // buffer space. Doing so avoids having to perform boundary checks when
+  // reading the value: the maximum number of elements that can be read is
+  // known outside of the loop.
+  const void* void_pointer;
+  int size;
+  input->GetDirectBufferPointerInline(&void_pointer, &size);
+  if (size > 0) {
+    const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
+    // The number of bytes each type occupies on the wire.
+    const int per_value_size = tag_size + sizeof(value);
+
+    int elements_available =
+        std::min(values->Capacity() - values->size(), size / per_value_size);
+    int num_read = 0;
+    while (num_read < elements_available &&
+           (buffer = io::CodedInputStream::ExpectTagFromArray(
+               buffer, tag)) != NULL) {
+      buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value);
+      values->AddAlreadyReserved(value);
+      ++num_read;
+    }
+    const int read_bytes = num_read * per_value_size;
+    if (read_bytes > 0) {
+      input->Skip(read_bytes);
+    }
+  }
+  return true;
+}
+
+// Specializations of ReadRepeatedPrimitive for the fixed size types, which use
+// the optimized code path.
+#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE)             \
+template <>                                                                    \
+inline bool WireFormatLite::ReadRepeatedPrimitive<                             \
+  CPPTYPE, WireFormatLite::DECLARED_TYPE>(                                     \
+    int tag_size,                                                              \
+    uint32 tag,                                                                \
+    io::CodedInputStream* input,                                               \
+    RepeatedField<CPPTYPE>* values) {                                          \
+  return ReadRepeatedFixedSizePrimitive<                                       \
+    CPPTYPE, WireFormatLite::DECLARED_TYPE>(                                   \
+      tag_size, tag, input, values);                                           \
+}
+
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32)
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64)
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32)
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64)
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT)
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE)
+
+#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadRepeatedPrimitiveNoInline(
+    int tag_size,
+    uint32 tag,
+    io::CodedInputStream* input,
+    RepeatedField<CType>* value) {
+  return ReadRepeatedPrimitive<CType, DeclaredType>(
+      tag_size, tag, input, value);
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
+                                                RepeatedField<CType>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  io::CodedInputStream::Limit limit = input->PushLimit(length);
+  while (input->BytesUntilLimit() > 0) {
+    CType value;
+    if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+    values->Add(value);
+  }
+  input->PopLimit(limit);
+  return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
+    io::CodedInputStream* input, RepeatedField<CType>* values) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  const uint32 old_entries = values->size();
+  const uint32 new_entries = length / sizeof(CType);
+  const uint32 new_bytes = new_entries * sizeof(CType);
+  if (new_bytes != length) return false;
+  // We would *like* to pre-allocate the buffer to write into (for
+  // speed), but *must* avoid performing a very large allocation due
+  // to a malicious user-supplied "length" above.  So we have a fast
+  // path that pre-allocates when the "length" is less than a bound.
+  // We determine the bound by calling BytesUntilTotalBytesLimit() and
+  // BytesUntilLimit().  These return -1 to mean "no limit set".
+  // There are four cases:
+  // TotalBytesLimit  Limit
+  // -1               -1     Use slow path.
+  // -1               >= 0   Use fast path if length <= Limit.
+  // >= 0             -1     Use slow path.
+  // >= 0             >= 0   Use fast path if length <= min(both limits).
+  int64 bytes_limit = input->BytesUntilTotalBytesLimit();
+  if (bytes_limit == -1) {
+    bytes_limit = input->BytesUntilLimit();
+  } else {
+    bytes_limit =
+        std::min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
+  }
+  if (bytes_limit >= new_bytes) {
+    // Fast-path that pre-allocates *values to the final size.
+#if defined(PROTOBUF_LITTLE_ENDIAN)
+    values->Resize(old_entries + new_entries, 0);
+    // values->mutable_data() may change after Resize(), so do this after:
+    void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries);
+    if (!input->ReadRaw(dest, new_bytes)) {
+      values->Truncate(old_entries);
+      return false;
+    }
+#else
+    values->Reserve(old_entries + new_entries);
+    CType value;
+    for (uint32 i = 0; i < new_entries; ++i) {
+      if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+      values->AddAlreadyReserved(value);
+    }
+#endif
+  } else {
+    // This is the slow-path case where "length" may be too large to
+    // safely allocate.  We read as much as we can into *values
+    // without pre-allocating "length" bytes.
+    CType value;
+    for (uint32 i = 0; i < new_entries; ++i) {
+      if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+      values->Add(value);
+    }
+  }
+  return true;
+}
+
+// Specializations of ReadPackedPrimitive for the fixed size types, which use
+// an optimized code path.
+#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE)      \
+template <>                                                                    \
+inline bool WireFormatLite::ReadPackedPrimitive<                               \
+  CPPTYPE, WireFormatLite::DECLARED_TYPE>(                                     \
+    io::CodedInputStream* input,                                               \
+    RepeatedField<CPPTYPE>* values) {                                          \
+  return ReadPackedFixedSizePrimitive<                                         \
+      CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values);                  \
+}
+
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32)
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64)
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32)
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64)
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT)
+READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE)
+
+#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
+                                                 RepeatedField<CType>* values) {
+  return ReadPackedPrimitive<CType, DeclaredType>(input, values);
+}
+
+
+
+inline bool WireFormatLite::ReadGroup(int field_number,
+                                      io::CodedInputStream* input,
+                                      MessageLite* value) {
+  if (!input->IncrementRecursionDepth()) return false;
+  if (!value->MergePartialFromCodedStream(input)) return false;
+  input->DecrementRecursionDepth();
+  // Make sure the last thing read was an end tag for this group.
+  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
+    return false;
+  }
+  return true;
+}
+inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input,
+                                        MessageLite* value) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  std::pair<io::CodedInputStream::Limit, int> p =
+      input->IncrementRecursionDepthAndPushLimit(length);
+  if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false;
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  return input->DecrementRecursionDepthAndPopLimit(p.first);
+}
+
+// We name the template parameter something long and extremely unlikely to occur
+// elsewhere because a *qualified* member access expression designed to avoid
+// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the
+// name of the qualifying class to be looked up both in the context of the full
+// expression (finding the template parameter) and in the context of the object
+// whose member we are accessing. This could potentially find a nested type
+// within that object. The standard goes on to require these names to refer to
+// the same entity, which this collision would violate. The lack of a safe way
+// to avoid this collision appears to be a defect in the standard, but until it
+// is corrected, we choose the name to avoid accidental collisions.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtual(
+    int field_number, io::CodedInputStream* input,
+    MessageType_WorkAroundCppLookupDefect* value) {
+  if (!input->IncrementRecursionDepth()) return false;
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
+  input->UnsafeDecrementRecursionDepth();
+  // Make sure the last thing read was an end tag for this group.
+  if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
+    return false;
+  }
+  return true;
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtualNoRecursionDepth(
+    int field_number, io::CodedInputStream* input,
+    MessageType_WorkAroundCppLookupDefect* value) {
+  return value->MessageType_WorkAroundCppLookupDefect::
+             MergePartialFromCodedStream(input) &&
+         input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP));
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtual(
+    io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
+  uint32 length;
+  if (!input->ReadVarint32(&length)) return false;
+  std::pair<io::CodedInputStream::Limit, int> p =
+      input->IncrementRecursionDepthAndPushLimit(length);
+  if (p.second < 0 || !value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  return input->DecrementRecursionDepthAndPopLimit(p.first);
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+    io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
+  io::CodedInputStream::Limit old_limit = input->ReadLengthAndPushLimit();
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  return input->CheckEntireMessageConsumedAndPopLimit(old_limit);
+}
+
+// ===================================================================
+
+inline void WireFormatLite::WriteTag(int field_number, WireType type,
+                                     io::CodedOutputStream* output) {
+  output->WriteTag(MakeTag(field_number, type));
+}
+
+inline void WireFormatLite::WriteInt32NoTag(int32 value,
+                                            io::CodedOutputStream* output) {
+  output->WriteVarint32SignExtended(value);
+}
+inline void WireFormatLite::WriteInt64NoTag(int64 value,
+                                            io::CodedOutputStream* output) {
+  output->WriteVarint64(static_cast<uint64>(value));
+}
+inline void WireFormatLite::WriteUInt32NoTag(uint32 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint32(value);
+}
+inline void WireFormatLite::WriteUInt64NoTag(uint64 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint64(value);
+}
+inline void WireFormatLite::WriteSInt32NoTag(int32 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint32(ZigZagEncode32(value));
+}
+inline void WireFormatLite::WriteSInt64NoTag(int64 value,
+                                             io::CodedOutputStream* output) {
+  output->WriteVarint64(ZigZagEncode64(value));
+}
+inline void WireFormatLite::WriteFixed32NoTag(uint32 value,
+                                              io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(value);
+}
+inline void WireFormatLite::WriteFixed64NoTag(uint64 value,
+                                              io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(value);
+}
+inline void WireFormatLite::WriteSFixed32NoTag(int32 value,
+                                               io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(static_cast<uint32>(value));
+}
+inline void WireFormatLite::WriteSFixed64NoTag(int64 value,
+                                               io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(static_cast<uint64>(value));
+}
+inline void WireFormatLite::WriteFloatNoTag(float value,
+                                            io::CodedOutputStream* output) {
+  output->WriteLittleEndian32(EncodeFloat(value));
+}
+inline void WireFormatLite::WriteDoubleNoTag(double value,
+                                             io::CodedOutputStream* output) {
+  output->WriteLittleEndian64(EncodeDouble(value));
+}
+inline void WireFormatLite::WriteBoolNoTag(bool value,
+                                           io::CodedOutputStream* output) {
+  output->WriteVarint32(value ? 1 : 0);
+}
+inline void WireFormatLite::WriteEnumNoTag(int value,
+                                           io::CodedOutputStream* output) {
+  output->WriteVarint32SignExtended(value);
+}
+
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteGroupNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_START_GROUP, output);
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
+  WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteMessageNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
+  WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  output->WriteVarint32(
+      value.MessageType_WorkAroundCppLookupDefect::GetCachedSize());
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
+}
+
+// ===================================================================
+
+inline uint8* WireFormatLite::WriteTagToArray(int field_number,
+                                              WireType type,
+                                              uint8* target) {
+  return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
+                                                target);
+}
+
+inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(
+      static_cast<uint64>(value), target);
+}
+inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
+                                                     target);
+}
+inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
+                                                     target);
+}
+inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value,
+                                                       uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value,
+                                                       uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value,
+                                                        uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(
+      static_cast<uint32>(value), target);
+}
+inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value,
+                                                        uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(
+      static_cast<uint64>(value), target);
+}
+inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value,
+                                                     uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
+                                                           target);
+}
+inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value,
+                                                      uint8* target) {
+  return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
+                                                           target);
+}
+inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value,
+                                                    uint8* target) {
+  return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
+}
+inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value,
+                                                    uint8* target) {
+  return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+
+inline uint8* WireFormatLite::WriteInt32ToArray(int field_number,
+                                                int32 value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteInt64ToArray(int field_number,
+                                                int64 value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number,
+                                                 uint32 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteUInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number,
+                                                 uint64 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteUInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number,
+                                                 int32 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteSInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number,
+                                                 int64 value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteSInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number,
+                                                  uint32 value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number,
+                                                  uint64 value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number,
+                                                   int32 value,
+                                                   uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteSFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number,
+                                                   int64 value,
+                                                   uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteSFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteFloatToArray(int field_number,
+                                                float value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+  return WriteFloatNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteDoubleToArray(int field_number,
+                                                 double value,
+                                                 uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+  return WriteDoubleNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteBoolToArray(int field_number,
+                                               bool value,
+                                               uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteBoolNoTagToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteEnumToArray(int field_number,
+                                               int value,
+                                               uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+  return WriteEnumNoTagToArray(value, target);
+}
+
+inline uint8* WireFormatLite::WriteStringToArray(int field_number,
+                                                 const string& value,
+                                                 uint8* target) {
+  // String is for UTF-8 text only
+  // WARNING:  In wire_format.cc, both strings and bytes are handled by
+  //   WriteString() to avoid code duplication.  If the implementations become
+  //   different, you will need to update that usage.
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
+}
+inline uint8* WireFormatLite::WriteBytesToArray(int field_number,
+                                                const string& value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
+}
+
+
+inline uint8* WireFormatLite::WriteGroupToArray(int field_number,
+                                                const MessageLite& value,
+                                                uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+  target = value.SerializeWithCachedSizesToArray(target);
+  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+inline uint8* WireFormatLite::WriteMessageToArray(int field_number,
+                                                  const MessageLite& value,
+                                                  uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(
+    value.GetCachedSize(), target);
+  return value.SerializeWithCachedSizesToArray(target);
+}
+
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline uint8* WireFormatLite::WriteGroupNoVirtualToArray(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+  target = value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
+  return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline uint8* WireFormatLite::WriteMessageNoVirtualToArray(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
+  target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+  target = io::CodedOutputStream::WriteVarint32ToArray(
+    value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target);
+  return value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
+}
+
+// ===================================================================
+
+inline int WireFormatLite::Int32Size(int32 value) {
+  return io::CodedOutputStream::VarintSize32SignExtended(value);
+}
+inline int WireFormatLite::Int64Size(int64 value) {
+  return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value));
+}
+inline int WireFormatLite::UInt32Size(uint32 value) {
+  return io::CodedOutputStream::VarintSize32(value);
+}
+inline int WireFormatLite::UInt64Size(uint64 value) {
+  return io::CodedOutputStream::VarintSize64(value);
+}
+inline int WireFormatLite::SInt32Size(int32 value) {
+  return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value));
+}
+inline int WireFormatLite::SInt64Size(int64 value) {
+  return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value));
+}
+inline int WireFormatLite::EnumSize(int value) {
+  return io::CodedOutputStream::VarintSize32SignExtended(value);
+}
+
+inline int WireFormatLite::StringSize(const string& value) {
+  return static_cast<int>(
+      io::CodedOutputStream::VarintSize32(static_cast<uint32>(value.size())) +
+      value.size());
+}
+inline int WireFormatLite::BytesSize(const string& value) {
+  return static_cast<int>(
+      io::CodedOutputStream::VarintSize32(static_cast<uint32>(value.size())) +
+      value.size());
+}
+
+
+inline int WireFormatLite::GroupSize(const MessageLite& value) {
+  return value.ByteSize();
+}
+inline int WireFormatLite::MessageSize(const MessageLite& value) {
+  return LengthDelimitedSize(value.ByteSize());
+}
+
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::GroupSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  return value.MessageType_WorkAroundCppLookupDefect::ByteSize();
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::MessageSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  return LengthDelimitedSize(
+      value.MessageType_WorkAroundCppLookupDefect::ByteSize());
+}
+
+inline int WireFormatLite::LengthDelimitedSize(int length) {
+  return io::CodedOutputStream::VarintSize32(length) + length;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wire_format_unittest.cc b/src/third_party/protobuf-3/src/google/protobuf/wire_format_unittest.cc
new file mode 100644
index 0000000..4e4add6
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wire_format_unittest.cc
@@ -0,0 +1,1289 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
+#include <google/protobuf/test_util.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(WireFormatTest, EnumsInSync) {
+  // Verify that WireFormatLite::FieldType and WireFormatLite::CppType match
+  // FieldDescriptor::Type and FieldDescriptor::CppType.
+
+  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_TYPE),
+            implicit_cast<int>(WireFormatLite::MAX_FIELD_TYPE));
+  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_CPPTYPE),
+            implicit_cast<int>(WireFormatLite::MAX_CPPTYPE));
+
+  for (int i = 1; i <= WireFormatLite::MAX_FIELD_TYPE; i++) {
+    EXPECT_EQ(
+      implicit_cast<int>(FieldDescriptor::TypeToCppType(
+        static_cast<FieldDescriptor::Type>(i))),
+      implicit_cast<int>(WireFormatLite::FieldTypeToCppType(
+        static_cast<WireFormatLite::FieldType>(i))));
+  }
+}
+
+TEST(WireFormatTest, MaxFieldNumber) {
+  // Make sure the max field number constant is accurate.
+  EXPECT_EQ((1 << (32 - WireFormatLite::kTagTypeBits)) - 1,
+            FieldDescriptor::kMaxNumber);
+}
+
+TEST(WireFormatTest, Parse) {
+  unittest::TestAllTypes source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  TestUtil::SetAllFields(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectAllFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParseExtensions) {
+  unittest::TestAllExtensions source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  TestUtil::SetAllExtensions(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectAllExtensionsSet(dest);
+}
+
+TEST(WireFormatTest, ParsePacked) {
+  unittest::TestPackedTypes source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  TestUtil::SetPackedFields(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectPackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParsePackedFromUnpacked) {
+  // Serialize using the generated code.
+  unittest::TestUnpackedTypes source;
+  TestUtil::SetUnpackedFields(&source);
+  string data = source.SerializeAsString();
+
+  // Parse using WireFormat.
+  unittest::TestPackedTypes dest;
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectPackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParseUnpackedFromPacked) {
+  // Serialize using the generated code.
+  unittest::TestPackedTypes source;
+  TestUtil::SetPackedFields(&source);
+  string data = source.SerializeAsString();
+
+  // Parse using WireFormat.
+  unittest::TestUnpackedTypes dest;
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectUnpackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParsePackedExtensions) {
+  unittest::TestPackedExtensions source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  TestUtil::SetPackedExtensions(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectPackedExtensionsSet(dest);
+}
+
+TEST(WireFormatTest, ParseOneof) {
+  unittest::TestOneof2 source, dest;
+  string data;
+
+  // Serialize using the generated code.
+  TestUtil::SetOneof1(&source);
+  source.SerializeToString(&data);
+
+  // Parse using WireFormat.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &dest);
+
+  // Check.
+  TestUtil::ExpectOneofSet1(dest);
+}
+
+TEST(WireFormatTest, OneofOnlySetLast) {
+  unittest::TestOneofBackwardsCompatible source;
+  unittest::TestOneof oneof_dest;
+  string data;
+
+  // Set two fields
+  source.set_foo_int(100);
+  source.set_foo_string("101");
+
+  // Serialize and parse to oneof message.
+  source.SerializeToString(&data);
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream input(&raw_input);
+  WireFormat::ParseAndMergePartial(&input, &oneof_dest);
+
+  // Only the last field is set.
+  EXPECT_FALSE(oneof_dest.has_foo_int());
+  EXPECT_TRUE(oneof_dest.has_foo_string());
+}
+
+TEST(WireFormatTest, ByteSize) {
+  unittest::TestAllTypes message;
+  TestUtil::SetAllFields(&message);
+
+  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, ByteSizeExtensions) {
+  unittest::TestAllExtensions message;
+  TestUtil::SetAllExtensions(&message);
+
+  EXPECT_EQ(message.ByteSize(),
+            WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, ByteSizePacked) {
+  unittest::TestPackedTypes message;
+  TestUtil::SetPackedFields(&message);
+
+  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, ByteSizePackedExtensions) {
+  unittest::TestPackedExtensions message;
+  TestUtil::SetPackedExtensions(&message);
+
+  EXPECT_EQ(message.ByteSize(),
+            WireFormat::ByteSize(message));
+  message.Clear();
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, ByteSizeOneof) {
+  unittest::TestOneof2 message;
+  TestUtil::SetOneof1(&message);
+
+  EXPECT_EQ(message.ByteSize(),
+  WireFormat::ByteSize(message));
+  message.Clear();
+
+  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, Serialize) {
+  unittest::TestAllTypes message;
+  string generated_data;
+  string dynamic_data;
+
+  TestUtil::SetAllFields(&message);
+  int size = message.ByteSize();
+
+  // Serialize using the generated code.
+  {
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+}
+
+TEST(WireFormatTest, SerializeExtensions) {
+  unittest::TestAllExtensions message;
+  string generated_data;
+  string dynamic_data;
+
+  TestUtil::SetAllExtensions(&message);
+  int size = message.ByteSize();
+
+  // Serialize using the generated code.
+  {
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+}
+
+TEST(WireFormatTest, SerializeFieldsAndExtensions) {
+  unittest::TestFieldOrderings message;
+  string generated_data;
+  string dynamic_data;
+
+  TestUtil::SetAllFieldsAndExtensions(&message);
+  int size = message.ByteSize();
+
+  // Serialize using the generated code.
+  {
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+
+  // Should output in canonical order.
+  TestUtil::ExpectAllFieldsAndExtensionsInOrder(dynamic_data);
+  TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data);
+}
+
+TEST(WireFormatTest, SerializeOneof) {
+  unittest::TestOneof2 message;
+  string generated_data;
+  string dynamic_data;
+
+  TestUtil::SetOneof1(&message);
+  int size = message.ByteSize();
+
+  // Serialize using the generated code.
+  {
+    io::StringOutputStream raw_output(&generated_data);
+    io::CodedOutputStream output(&raw_output);
+    message.SerializeWithCachedSizes(&output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Serialize using WireFormat.
+  {
+    io::StringOutputStream raw_output(&dynamic_data);
+    io::CodedOutputStream output(&raw_output);
+    WireFormat::SerializeWithCachedSizes(message, size, &output);
+    ASSERT_FALSE(output.HadError());
+  }
+
+  // Should be the same.
+  // Don't use EXPECT_EQ here because we're comparing raw binary data and
+  // we really don't want it dumped to stdout on failure.
+  EXPECT_TRUE(dynamic_data == generated_data);
+}
+
+TEST(WireFormatTest, ParseMultipleExtensionRanges) {
+  // Make sure we can parse a message that contains multiple extensions ranges.
+  unittest::TestFieldOrderings source;
+  string data;
+
+  TestUtil::SetAllFieldsAndExtensions(&source);
+  source.SerializeToString(&data);
+
+  {
+    unittest::TestFieldOrderings dest;
+    EXPECT_TRUE(dest.ParseFromString(data));
+    EXPECT_EQ(source.DebugString(), dest.DebugString());
+  }
+
+  // Also test using reflection-based parsing.
+  {
+    unittest::TestFieldOrderings dest;
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream coded_input(&raw_input);
+    EXPECT_TRUE(WireFormat::ParseAndMergePartial(&coded_input, &dest));
+    EXPECT_EQ(source.DebugString(), dest.DebugString());
+  }
+}
+
+const int kUnknownTypeId = 1550055;
+
+TEST(WireFormatTest, SerializeMessageSet) {
+  // Set up a TestMessageSet with two known messages and an unknown one.
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  message_set.MutableExtension(
+    unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
+  message_set.MutableExtension(
+    unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo");
+  message_set.mutable_unknown_fields()->AddLengthDelimited(
+    kUnknownTypeId, "bar");
+
+  string data;
+  ASSERT_TRUE(message_set.SerializeToString(&data));
+
+  // Parse back using RawMessageSet and check the contents.
+  unittest::RawMessageSet raw;
+  ASSERT_TRUE(raw.ParseFromString(data));
+
+  EXPECT_EQ(0, raw.unknown_fields().field_count());
+
+  ASSERT_EQ(3, raw.item_size());
+  EXPECT_EQ(
+    unittest::TestMessageSetExtension1::descriptor()->extension(0)->number(),
+    raw.item(0).type_id());
+  EXPECT_EQ(
+    unittest::TestMessageSetExtension2::descriptor()->extension(0)->number(),
+    raw.item(1).type_id());
+  EXPECT_EQ(kUnknownTypeId, raw.item(2).type_id());
+
+  unittest::TestMessageSetExtension1 message1;
+  EXPECT_TRUE(message1.ParseFromString(raw.item(0).message()));
+  EXPECT_EQ(123, message1.i());
+
+  unittest::TestMessageSetExtension2 message2;
+  EXPECT_TRUE(message2.ParseFromString(raw.item(1).message()));
+  EXPECT_EQ("foo", message2.str());
+
+  EXPECT_EQ("bar", raw.item(2).message());
+}
+
+TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) {
+  // Serialize a MessageSet to a stream and to a flat array using generated
+  // code, and also using WireFormat, and check that the results are equal.
+  // Set up a TestMessageSet with two known messages and an unknown one, as
+  // above.
+
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  message_set.MutableExtension(
+    unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
+  message_set.MutableExtension(
+    unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo");
+  message_set.mutable_unknown_fields()->AddLengthDelimited(
+    kUnknownTypeId, "bar");
+
+  int size = message_set.ByteSize();
+  EXPECT_EQ(size, message_set.GetCachedSize());
+  ASSERT_EQ(size, WireFormat::ByteSize(message_set));
+
+  string flat_data;
+  string stream_data;
+  string dynamic_data;
+  flat_data.resize(size);
+  stream_data.resize(size);
+
+  // Serialize to flat array
+  {
+    uint8* target = reinterpret_cast<uint8*>(string_as_array(&flat_data));
+    uint8* end = message_set.SerializeWithCachedSizesToArray(target);
+    EXPECT_EQ(size, end - target);
+  }
+
+  // Serialize to buffer
+  {
+    io::ArrayOutputStream array_stream(string_as_array(&stream_data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message_set.SerializeWithCachedSizes(&output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+
+  // Serialize to buffer with WireFormat.
+  {
+    io::StringOutputStream string_stream(&dynamic_data);
+    io::CodedOutputStream output_stream(&string_stream);
+    WireFormat::SerializeWithCachedSizes(message_set, size, &output_stream);
+    ASSERT_FALSE(output_stream.HadError());
+  }
+
+  EXPECT_TRUE(flat_data == stream_data);
+  EXPECT_TRUE(flat_data == dynamic_data);
+}
+
+TEST(WireFormatTest, ParseMessageSet) {
+  // Set up a RawMessageSet with two known messages and an unknown one.
+  unittest::RawMessageSet raw;
+
+  {
+    unittest::RawMessageSet::Item* item = raw.add_item();
+    item->set_type_id(
+      unittest::TestMessageSetExtension1::descriptor()->extension(0)->number());
+    unittest::TestMessageSetExtension1 message;
+    message.set_i(123);
+    message.SerializeToString(item->mutable_message());
+  }
+
+  {
+    unittest::RawMessageSet::Item* item = raw.add_item();
+    item->set_type_id(
+      unittest::TestMessageSetExtension2::descriptor()->extension(0)->number());
+    unittest::TestMessageSetExtension2 message;
+    message.set_str("foo");
+    message.SerializeToString(item->mutable_message());
+  }
+
+  {
+    unittest::RawMessageSet::Item* item = raw.add_item();
+    item->set_type_id(kUnknownTypeId);
+    item->set_message("bar");
+  }
+
+  string data;
+  ASSERT_TRUE(raw.SerializeToString(&data));
+
+  // Parse as a TestMessageSet and check the contents.
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  ASSERT_TRUE(message_set.ParseFromString(data));
+
+  EXPECT_EQ(123, message_set.GetExtension(
+    unittest::TestMessageSetExtension1::message_set_extension).i());
+  EXPECT_EQ("foo", message_set.GetExtension(
+    unittest::TestMessageSetExtension2::message_set_extension).str());
+
+  ASSERT_EQ(1, message_set.unknown_fields().field_count());
+  ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED,
+            message_set.unknown_fields().field(0).type());
+  EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited());
+
+  // Also parse using WireFormat.
+  proto2_wireformat_unittest::TestMessageSet dynamic_message_set;
+  io::CodedInputStream input(reinterpret_cast<const uint8*>(data.data()),
+                             data.size());
+  ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set));
+  EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString());
+}
+
+TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
+  string data;
+  {
+    unittest::TestMessageSetExtension1 message;
+    message.set_i(123);
+    // Build a MessageSet manually with its message content put before its
+    // type_id.
+    io::StringOutputStream output_stream(&data);
+    io::CodedOutputStream coded_output(&output_stream);
+    coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag);
+    // Write the message content first.
+    WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber,
+                             WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+                             &coded_output);
+    coded_output.WriteVarint32(message.ByteSize());
+    message.SerializeWithCachedSizes(&coded_output);
+    // Write the type id.
+    uint32 type_id = message.GetDescriptor()->extension(0)->number();
+    WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+                                type_id, &coded_output);
+    coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag);
+  }
+  {
+    proto2_wireformat_unittest::TestMessageSet message_set;
+    ASSERT_TRUE(message_set.ParseFromString(data));
+
+    EXPECT_EQ(123, message_set.GetExtension(
+        unittest::TestMessageSetExtension1::message_set_extension).i());
+  }
+  {
+    // Test parse the message via Reflection.
+    proto2_wireformat_unittest::TestMessageSet message_set;
+    io::CodedInputStream input(
+        reinterpret_cast<const uint8*>(data.data()), data.size());
+    EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set));
+    EXPECT_TRUE(input.ConsumedEntireMessage());
+
+    EXPECT_EQ(123, message_set.GetExtension(
+        unittest::TestMessageSetExtension1::message_set_extension).i());
+  }
+}
+
+TEST(WireFormatTest, ParseBrokenMessageSet) {
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  string input("goodbye");  // Invalid wire format data.
+  EXPECT_FALSE(message_set.ParseFromString(input));
+}
+
+TEST(WireFormatTest, RecursionLimit) {
+  unittest::TestRecursiveMessage message;
+  message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1);
+  string data;
+  message.SerializeToString(&data);
+
+  {
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetRecursionLimit(4);
+    unittest::TestRecursiveMessage message2;
+    EXPECT_TRUE(message2.ParseFromCodedStream(&input));
+  }
+
+  {
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetRecursionLimit(3);
+    unittest::TestRecursiveMessage message2;
+    EXPECT_FALSE(message2.ParseFromCodedStream(&input));
+  }
+}
+
+TEST(WireFormatTest, UnknownFieldRecursionLimit) {
+  unittest::TestEmptyMessage message;
+  message.mutable_unknown_fields()
+        ->AddGroup(1234)
+        ->AddGroup(1234)
+        ->AddGroup(1234)
+        ->AddGroup(1234)
+        ->AddVarint(1234, 123);
+  string data;
+  message.SerializeToString(&data);
+
+  {
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetRecursionLimit(4);
+    unittest::TestEmptyMessage message2;
+    EXPECT_TRUE(message2.ParseFromCodedStream(&input));
+  }
+
+  {
+    io::ArrayInputStream raw_input(data.data(), data.size());
+    io::CodedInputStream input(&raw_input);
+    input.SetRecursionLimit(3);
+    unittest::TestEmptyMessage message2;
+    EXPECT_FALSE(message2.ParseFromCodedStream(&input));
+  }
+}
+
+TEST(WireFormatTest, ZigZag) {
+// avoid line-wrapping
+#define LL(x) GOOGLE_LONGLONG(x)
+#define ULL(x) GOOGLE_ULONGLONG(x)
+#define ZigZagEncode32(x) WireFormatLite::ZigZagEncode32(x)
+#define ZigZagDecode32(x) WireFormatLite::ZigZagDecode32(x)
+#define ZigZagEncode64(x) WireFormatLite::ZigZagEncode64(x)
+#define ZigZagDecode64(x) WireFormatLite::ZigZagDecode64(x)
+
+  EXPECT_EQ(0u, ZigZagEncode32( 0));
+  EXPECT_EQ(1u, ZigZagEncode32(-1));
+  EXPECT_EQ(2u, ZigZagEncode32( 1));
+  EXPECT_EQ(3u, ZigZagEncode32(-2));
+  EXPECT_EQ(0x7FFFFFFEu, ZigZagEncode32(0x3FFFFFFF));
+  EXPECT_EQ(0x7FFFFFFFu, ZigZagEncode32(0xC0000000));
+  EXPECT_EQ(0xFFFFFFFEu, ZigZagEncode32(0x7FFFFFFF));
+  EXPECT_EQ(0xFFFFFFFFu, ZigZagEncode32(0x80000000));
+
+  EXPECT_EQ( 0, ZigZagDecode32(0u));
+  EXPECT_EQ(-1, ZigZagDecode32(1u));
+  EXPECT_EQ( 1, ZigZagDecode32(2u));
+  EXPECT_EQ(-2, ZigZagDecode32(3u));
+  EXPECT_EQ(0x3FFFFFFF, ZigZagDecode32(0x7FFFFFFEu));
+  EXPECT_EQ(0xC0000000, ZigZagDecode32(0x7FFFFFFFu));
+  EXPECT_EQ(0x7FFFFFFF, ZigZagDecode32(0xFFFFFFFEu));
+  EXPECT_EQ(0x80000000, ZigZagDecode32(0xFFFFFFFFu));
+
+  EXPECT_EQ(0u, ZigZagEncode64( 0));
+  EXPECT_EQ(1u, ZigZagEncode64(-1));
+  EXPECT_EQ(2u, ZigZagEncode64( 1));
+  EXPECT_EQ(3u, ZigZagEncode64(-2));
+  EXPECT_EQ(ULL(0x000000007FFFFFFE), ZigZagEncode64(LL(0x000000003FFFFFFF)));
+  EXPECT_EQ(ULL(0x000000007FFFFFFF), ZigZagEncode64(LL(0xFFFFFFFFC0000000)));
+  EXPECT_EQ(ULL(0x00000000FFFFFFFE), ZigZagEncode64(LL(0x000000007FFFFFFF)));
+  EXPECT_EQ(ULL(0x00000000FFFFFFFF), ZigZagEncode64(LL(0xFFFFFFFF80000000)));
+  EXPECT_EQ(ULL(0xFFFFFFFFFFFFFFFE), ZigZagEncode64(LL(0x7FFFFFFFFFFFFFFF)));
+  EXPECT_EQ(ULL(0xFFFFFFFFFFFFFFFF), ZigZagEncode64(LL(0x8000000000000000)));
+
+  EXPECT_EQ( 0, ZigZagDecode64(0u));
+  EXPECT_EQ(-1, ZigZagDecode64(1u));
+  EXPECT_EQ( 1, ZigZagDecode64(2u));
+  EXPECT_EQ(-2, ZigZagDecode64(3u));
+  EXPECT_EQ(LL(0x000000003FFFFFFF), ZigZagDecode64(ULL(0x000000007FFFFFFE)));
+  EXPECT_EQ(LL(0xFFFFFFFFC0000000), ZigZagDecode64(ULL(0x000000007FFFFFFF)));
+  EXPECT_EQ(LL(0x000000007FFFFFFF), ZigZagDecode64(ULL(0x00000000FFFFFFFE)));
+  EXPECT_EQ(LL(0xFFFFFFFF80000000), ZigZagDecode64(ULL(0x00000000FFFFFFFF)));
+  EXPECT_EQ(LL(0x7FFFFFFFFFFFFFFF), ZigZagDecode64(ULL(0xFFFFFFFFFFFFFFFE)));
+  EXPECT_EQ(LL(0x8000000000000000), ZigZagDecode64(ULL(0xFFFFFFFFFFFFFFFF)));
+
+  // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
+  // were chosen semi-randomly via keyboard bashing.
+  EXPECT_EQ(    0, ZigZagDecode32(ZigZagEncode32(    0)));
+  EXPECT_EQ(    1, ZigZagDecode32(ZigZagEncode32(    1)));
+  EXPECT_EQ(   -1, ZigZagDecode32(ZigZagEncode32(   -1)));
+  EXPECT_EQ(14927, ZigZagDecode32(ZigZagEncode32(14927)));
+  EXPECT_EQ(-3612, ZigZagDecode32(ZigZagEncode32(-3612)));
+
+  EXPECT_EQ(    0, ZigZagDecode64(ZigZagEncode64(    0)));
+  EXPECT_EQ(    1, ZigZagDecode64(ZigZagEncode64(    1)));
+  EXPECT_EQ(   -1, ZigZagDecode64(ZigZagEncode64(   -1)));
+  EXPECT_EQ(14927, ZigZagDecode64(ZigZagEncode64(14927)));
+  EXPECT_EQ(-3612, ZigZagDecode64(ZigZagEncode64(-3612)));
+
+  EXPECT_EQ(LL(856912304801416), ZigZagDecode64(ZigZagEncode64(
+            LL(856912304801416))));
+  EXPECT_EQ(LL(-75123905439571256), ZigZagDecode64(ZigZagEncode64(
+            LL(-75123905439571256))));
+}
+
+TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) {
+  // At one point checks would trigger when parsing repeated fixed scalar
+  // fields.
+  protobuf_unittest::TestRepeatedScalarDifferentTagSizes msg1, msg2;
+  for (int i = 0; i < 100; ++i) {
+    msg1.add_repeated_fixed32(i);
+    msg1.add_repeated_int32(i);
+    msg1.add_repeated_fixed64(i);
+    msg1.add_repeated_int64(i);
+    msg1.add_repeated_float(i);
+    msg1.add_repeated_uint64(i);
+  }
+
+  // Make sure that we have a variety of tag sizes.
+  const google::protobuf::Descriptor* desc = msg1.GetDescriptor();
+  const google::protobuf::FieldDescriptor* field;
+  field = desc->FindFieldByName("repeated_fixed32");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+  field = desc->FindFieldByName("repeated_int32");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+  field = desc->FindFieldByName("repeated_fixed64");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+  field = desc->FindFieldByName("repeated_int64");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+  field = desc->FindFieldByName("repeated_float");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+  field = desc->FindFieldByName("repeated_uint64");
+  ASSERT_TRUE(field != NULL);
+  ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+
+  EXPECT_TRUE(msg2.ParseFromString(msg1.SerializeAsString()));
+  EXPECT_EQ(msg1.DebugString(), msg2.DebugString());
+}
+
+TEST(WireFormatTest, CompatibleTypes) {
+  const int64 data = 0x100000000LL;
+  unittest::Int64Message msg1;
+  msg1.set_data(data);
+  string serialized;
+  msg1.SerializeToString(&serialized);
+
+  // Test int64 is compatible with bool
+  unittest::BoolMessage msg2;
+  ASSERT_TRUE(msg2.ParseFromString(serialized));
+  ASSERT_EQ(static_cast<bool>(data), msg2.data());
+
+  // Test int64 is compatible with uint64
+  unittest::Uint64Message msg3;
+  ASSERT_TRUE(msg3.ParseFromString(serialized));
+  ASSERT_EQ(static_cast<uint64>(data), msg3.data());
+
+  // Test int64 is compatible with int32
+  unittest::Int32Message msg4;
+  ASSERT_TRUE(msg4.ParseFromString(serialized));
+  ASSERT_EQ(static_cast<int32>(data), msg4.data());
+
+  // Test int64 is compatible with uint32
+  unittest::Uint32Message msg5;
+  ASSERT_TRUE(msg5.ParseFromString(serialized));
+  ASSERT_EQ(static_cast<uint32>(data), msg5.data());
+}
+
+class Proto3PrimitiveRepeatedWireFormatTest : public ::testing::Test {
+ protected:
+  Proto3PrimitiveRepeatedWireFormatTest()
+      : packedTestAllTypes_(
+            "\xFA\x01\x01\x01"
+            "\x82\x02\x01\x01"
+            "\x8A\x02\x01\x01"
+            "\x92\x02\x01\x01"
+            "\x9A\x02\x01\x02"
+            "\xA2\x02\x01\x02"
+            "\xAA\x02\x04\x01\x00\x00\x00"
+            "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\xBA\x02\x04\x01\x00\x00\x00"
+            "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\xCA\x02\x04\x00\x00\x80\x3f"
+            "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f"
+            "\xDA\x02\x01\x01"
+            "\x9A\x03\x01\x01",
+            86),
+        packedTestUnpackedTypes_(
+            "\x0A\x01\x01"
+            "\x12\x01\x01"
+            "\x1A\x01\x01"
+            "\x22\x01\x01"
+            "\x2A\x01\x02"
+            "\x32\x01\x02"
+            "\x3A\x04\x01\x00\x00\x00"
+            "\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\x4A\x04\x01\x00\x00\x00"
+            "\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\x5A\x04\x00\x00\x80\x3f"
+            "\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f"
+            "\x6A\x01\x01"
+            "\x72\x01\x01",
+            72),
+        unpackedTestAllTypes_(
+            "\xF8\x01\x01"
+            "\x80\x02\x01"
+            "\x88\x02\x01"
+            "\x90\x02\x01"
+            "\x98\x02\x02"
+            "\xA0\x02\x02"
+            "\xAD\x02\x01\x00\x00\x00"
+            "\xB1\x02\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\xBD\x02\x01\x00\x00\x00"
+            "\xC1\x02\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\xCD\x02\x00\x00\x80\x3f"
+            "\xD1\x02\x00\x00\x00\x00\x00\x00\xf0\x3f"
+            "\xD8\x02\x01"
+            "\x98\x03\x01",
+            72),
+        unpackedTestUnpackedTypes_(
+            "\x08\x01"
+            "\x10\x01"
+            "\x18\x01"
+            "\x20\x01"
+            "\x28\x02"
+            "\x30\x02"
+            "\x3D\x01\x00\x00\x00"
+            "\x41\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\x4D\x01\x00\x00\x00"
+            "\x51\x01\x00\x00\x00\x00\x00\x00\x00"
+            "\x5D\x00\x00\x80\x3f"
+            "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f"
+            "\x68\x01"
+            "\x70\x01",
+            58) {}
+  template <class Proto>
+  void SetProto3PrimitiveRepeatedFields(Proto* message) {
+    message->add_repeated_int32(1);
+    message->add_repeated_int64(1);
+    message->add_repeated_uint32(1);
+    message->add_repeated_uint64(1);
+    message->add_repeated_sint32(1);
+    message->add_repeated_sint64(1);
+    message->add_repeated_fixed32(1);
+    message->add_repeated_fixed64(1);
+    message->add_repeated_sfixed32(1);
+    message->add_repeated_sfixed64(1);
+    message->add_repeated_float(1.0);
+    message->add_repeated_double(1.0);
+    message->add_repeated_bool(true);
+    message->add_repeated_nested_enum(
+        proto3_arena_unittest::TestAllTypes_NestedEnum_FOO);
+  }
+
+  template <class Proto>
+  void ExpectProto3PrimitiveRepeatedFieldsSet(const Proto& message) {
+    EXPECT_EQ(1, message.repeated_int32(0));
+    EXPECT_EQ(1, message.repeated_int64(0));
+    EXPECT_EQ(1, message.repeated_uint32(0));
+    EXPECT_EQ(1, message.repeated_uint64(0));
+    EXPECT_EQ(1, message.repeated_sint32(0));
+    EXPECT_EQ(1, message.repeated_sint64(0));
+    EXPECT_EQ(1, message.repeated_fixed32(0));
+    EXPECT_EQ(1, message.repeated_fixed64(0));
+    EXPECT_EQ(1, message.repeated_sfixed32(0));
+    EXPECT_EQ(1, message.repeated_sfixed64(0));
+    EXPECT_EQ(1.0, message.repeated_float(0));
+    EXPECT_EQ(1.0, message.repeated_double(0));
+    EXPECT_EQ(true, message.repeated_bool(0));
+    EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_FOO,
+              message.repeated_nested_enum(0));
+  }
+
+  template <class Proto>
+  void TestSerialization(Proto* message, const string& expected) {
+    SetProto3PrimitiveRepeatedFields(message);
+
+    int size = message->ByteSize();
+
+    // Serialize using the generated code.
+    string generated_data;
+    {
+      io::StringOutputStream raw_output(&generated_data);
+      io::CodedOutputStream output(&raw_output);
+      message->SerializeWithCachedSizes(&output);
+      ASSERT_FALSE(output.HadError());
+    }
+    EXPECT_TRUE(expected == generated_data);
+
+    // Serialize using the dynamic code.
+    string dynamic_data;
+    {
+      io::StringOutputStream raw_output(&dynamic_data);
+      io::CodedOutputStream output(&raw_output);
+      WireFormat::SerializeWithCachedSizes(*message, size, &output);
+      ASSERT_FALSE(output.HadError());
+    }
+    EXPECT_TRUE(expected == dynamic_data);
+  }
+
+  template <class Proto>
+  void TestParsing(Proto* message, const string& compatible_data) {
+    message->Clear();
+    message->ParseFromString(compatible_data);
+    ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+
+    message->Clear();
+    io::CodedInputStream input(
+        reinterpret_cast<const uint8*>(compatible_data.data()),
+        compatible_data.size());
+    WireFormat::ParseAndMergePartial(&input, message);
+    ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+  }
+
+  const string packedTestAllTypes_;
+  const string packedTestUnpackedTypes_;
+  const string unpackedTestAllTypes_;
+  const string unpackedTestUnpackedTypes_;
+};
+
+TEST_F(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) {
+  proto3_arena_unittest::TestAllTypes packed_message;
+  proto3_arena_unittest::TestUnpackedTypes unpacked_message;
+  TestSerialization(&packed_message, packedTestAllTypes_);
+  TestParsing(&packed_message, packedTestAllTypes_);
+  TestParsing(&packed_message, unpackedTestAllTypes_);
+  TestSerialization(&unpacked_message, unpackedTestUnpackedTypes_);
+  TestParsing(&unpacked_message, packedTestUnpackedTypes_);
+  TestParsing(&unpacked_message, unpackedTestUnpackedTypes_);
+}
+
+class WireFormatInvalidInputTest : public testing::Test {
+ protected:
+  // Make a serialized TestAllTypes in which the field optional_nested_message
+  // contains exactly the given bytes, which may be invalid.
+  string MakeInvalidEmbeddedMessage(const char* bytes, int size) {
+    const FieldDescriptor* field =
+      unittest::TestAllTypes::descriptor()->FindFieldByName(
+        "optional_nested_message");
+    GOOGLE_CHECK(field != NULL);
+
+    string result;
+
+    {
+      io::StringOutputStream raw_output(&result);
+      io::CodedOutputStream output(&raw_output);
+
+      WireFormatLite::WriteBytes(field->number(), string(bytes, size), &output);
+    }
+
+    return result;
+  }
+
+  // Make a serialized TestAllTypes in which the field optionalgroup
+  // contains exactly the given bytes -- which may be invalid -- and
+  // possibly no end tag.
+  string MakeInvalidGroup(const char* bytes, int size, bool include_end_tag) {
+    const FieldDescriptor* field =
+      unittest::TestAllTypes::descriptor()->FindFieldByName(
+        "optionalgroup");
+    GOOGLE_CHECK(field != NULL);
+
+    string result;
+
+    {
+      io::StringOutputStream raw_output(&result);
+      io::CodedOutputStream output(&raw_output);
+
+      output.WriteVarint32(WireFormat::MakeTag(field));
+      output.WriteString(string(bytes, size));
+      if (include_end_tag) {
+        output.WriteVarint32(WireFormatLite::MakeTag(
+          field->number(), WireFormatLite::WIRETYPE_END_GROUP));
+      }
+    }
+
+    return result;
+  }
+};
+
+TEST_F(WireFormatInvalidInputTest, InvalidSubMessage) {
+  unittest::TestAllTypes message;
+
+  // Control case.
+  EXPECT_TRUE(message.ParseFromString(MakeInvalidEmbeddedMessage("", 0)));
+
+  // The byte is a valid varint, but not a valid tag (zero).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\0", 1)));
+
+  // The byte is a malformed varint.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\200", 1)));
+
+  // The byte is an endgroup tag, but we aren't parsing a group.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\014", 1)));
+
+  // The byte is a valid varint but not a valid tag (bad wire type).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\017", 1)));
+}
+
+TEST_F(WireFormatInvalidInputTest, InvalidGroup) {
+  unittest::TestAllTypes message;
+
+  // Control case.
+  EXPECT_TRUE(message.ParseFromString(MakeInvalidGroup("", 0, true)));
+
+  // Missing end tag.  Groups cannot end at EOF.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("", 0, false)));
+
+  // The byte is a valid varint, but not a valid tag (zero).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\0", 1, false)));
+
+  // The byte is a malformed varint.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\200", 1, false)));
+
+  // The byte is an endgroup tag, but not the right one for this group.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\014", 1, false)));
+
+  // The byte is a valid varint but not a valid tag (bad wire type).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\017", 1, true)));
+}
+
+TEST_F(WireFormatInvalidInputTest, InvalidUnknownGroup) {
+  // Use TestEmptyMessage so that the group made by MakeInvalidGroup will not
+  // be a known tag number.
+  unittest::TestEmptyMessage message;
+
+  // Control case.
+  EXPECT_TRUE(message.ParseFromString(MakeInvalidGroup("", 0, true)));
+
+  // Missing end tag.  Groups cannot end at EOF.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("", 0, false)));
+
+  // The byte is a valid varint, but not a valid tag (zero).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\0", 1, false)));
+
+  // The byte is a malformed varint.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\200", 1, false)));
+
+  // The byte is an endgroup tag, but not the right one for this group.
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\014", 1, false)));
+
+  // The byte is a valid varint but not a valid tag (bad wire type).
+  EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\017", 1, true)));
+}
+
+TEST_F(WireFormatInvalidInputTest, InvalidStringInUnknownGroup) {
+  // Test a bug fix:  SkipMessage should fail if the message contains a string
+  // whose length would extend beyond the message end.
+
+  unittest::TestAllTypes message;
+  message.set_optional_string("foo foo foo foo");
+  string data;
+  message.SerializeToString(&data);
+
+  // Chop some bytes off the end.
+  data.resize(data.size() - 4);
+
+  // Try to skip it.  Note that the bug was only present when parsing to an
+  // UnknownFieldSet.
+  io::ArrayInputStream raw_input(data.data(), data.size());
+  io::CodedInputStream coded_input(&raw_input);
+  UnknownFieldSet unknown_fields;
+  EXPECT_FALSE(WireFormat::SkipMessage(&coded_input, &unknown_fields));
+}
+
+// Test differences between string and bytes.
+// Value of a string type must be valid UTF-8 string.  When UTF-8
+// validation is enabled (GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED):
+// WriteInvalidUTF8String:  see error message.
+// ReadInvalidUTF8String:  see error message.
+// WriteValidUTF8String: fine.
+// ReadValidUTF8String:  fine.
+// WriteAnyBytes: fine.
+// ReadAnyBytes: fine.
+const char * kInvalidUTF8String = "Invalid UTF-8: \xA0\xB0\xC0\xD0";
+// This used to be "Valid UTF-8: \x01\x02\u8C37\u6B4C", but MSVC seems to
+// interpret \u differently from GCC.
+const char * kValidUTF8String = "Valid UTF-8: \x01\x02\350\260\267\346\255\214";
+
+template<typename T>
+bool WriteMessage(const char *value, T *message, string *wire_buffer) {
+  message->set_data(value);
+  wire_buffer->clear();
+  message->AppendToString(wire_buffer);
+  return (wire_buffer->size() > 0);
+}
+
+template<typename T>
+bool ReadMessage(const string &wire_buffer, T *message) {
+  return message->ParseFromArray(wire_buffer.data(), wire_buffer.size());
+}
+
+bool StartsWith(const string& s, const string& prefix) {
+  return s.substr(0, prefix.length()) == prefix;
+}
+
+class Utf8ValidationTest : public ::testing::Test {
+ protected:
+  Utf8ValidationTest() {}
+  virtual ~Utf8ValidationTest() {}
+  virtual void SetUp() {
+  }
+
+};
+
+TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) {
+  string wire_buffer;
+  protobuf_unittest::OneString input;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    WriteMessage(kInvalidUTF8String, &input, &wire_buffer);
+    errors = log.GetMessages(ERROR);
+  }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  ASSERT_EQ(1, errors.size());
+  EXPECT_TRUE(StartsWith(errors[0],
+                         "String field 'protobuf_unittest.OneString.data' "
+                         "contains invalid UTF-8 data when "
+                         "serializing a protocol buffer. Use the "
+                         "'bytes' type if you intend to send raw bytes."));
+#else
+  ASSERT_EQ(0, errors.size());
+#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+}
+
+
+TEST_F(Utf8ValidationTest, ReadInvalidUTF8String) {
+  string wire_buffer;
+  protobuf_unittest::OneString input;
+  WriteMessage(kInvalidUTF8String, &input, &wire_buffer);
+  protobuf_unittest::OneString output;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    ReadMessage(wire_buffer, &output);
+    errors = log.GetMessages(ERROR);
+  }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  ASSERT_EQ(1, errors.size());
+  EXPECT_TRUE(StartsWith(errors[0],
+                         "String field 'protobuf_unittest.OneString.data' "
+                         "contains invalid UTF-8 data when "
+                         "parsing a protocol buffer. Use the "
+                         "'bytes' type if you intend to send raw bytes."));
+
+#else
+  ASSERT_EQ(0, errors.size());
+#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+}
+
+
+TEST_F(Utf8ValidationTest, WriteValidUTF8String) {
+  string wire_buffer;
+  protobuf_unittest::OneString input;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    WriteMessage(kValidUTF8String, &input, &wire_buffer);
+    errors = log.GetMessages(ERROR);
+  }
+  ASSERT_EQ(0, errors.size());
+}
+
+TEST_F(Utf8ValidationTest, ReadValidUTF8String) {
+  string wire_buffer;
+  protobuf_unittest::OneString input;
+  WriteMessage(kValidUTF8String, &input, &wire_buffer);
+  protobuf_unittest::OneString output;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    ReadMessage(wire_buffer, &output);
+    errors = log.GetMessages(ERROR);
+  }
+  ASSERT_EQ(0, errors.size());
+  EXPECT_EQ(input.data(), output.data());
+}
+
+// Bytes: anything can pass as bytes, use invalid UTF-8 string to test
+TEST_F(Utf8ValidationTest, WriteArbitraryBytes) {
+  string wire_buffer;
+  protobuf_unittest::OneBytes input;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    WriteMessage(kInvalidUTF8String, &input, &wire_buffer);
+    errors = log.GetMessages(ERROR);
+  }
+  ASSERT_EQ(0, errors.size());
+}
+
+TEST_F(Utf8ValidationTest, ReadArbitraryBytes) {
+  string wire_buffer;
+  protobuf_unittest::OneBytes input;
+  WriteMessage(kInvalidUTF8String, &input, &wire_buffer);
+  protobuf_unittest::OneBytes output;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    ReadMessage(wire_buffer, &output);
+    errors = log.GetMessages(ERROR);
+  }
+  ASSERT_EQ(0, errors.size());
+  EXPECT_EQ(input.data(), output.data());
+}
+
+TEST_F(Utf8ValidationTest, ParseRepeatedString) {
+  protobuf_unittest::MoreBytes input;
+  input.add_data(kValidUTF8String);
+  input.add_data(kInvalidUTF8String);
+  input.add_data(kInvalidUTF8String);
+  string wire_buffer = input.SerializeAsString();
+
+  protobuf_unittest::MoreString output;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    ReadMessage(wire_buffer, &output);
+    errors = log.GetMessages(ERROR);
+  }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  ASSERT_EQ(2, errors.size());
+#else
+  ASSERT_EQ(0, errors.size());
+#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  EXPECT_EQ(wire_buffer, output.SerializeAsString());
+}
+
+// Test the old VerifyUTF8String() function, which may still be called by old
+// generated code.
+TEST_F(Utf8ValidationTest, OldVerifyUTF8String) {
+  string data(kInvalidUTF8String);
+
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    WireFormat::VerifyUTF8String(data.data(), data.size(),
+                                 WireFormat::SERIALIZE);
+    errors = log.GetMessages(ERROR);
+  }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  ASSERT_EQ(1, errors.size());
+  EXPECT_TRUE(StartsWith(errors[0],
+                         "String field contains invalid UTF-8 data when "
+                         "serializing a protocol buffer. Use the "
+                         "'bytes' type if you intend to send raw bytes."));
+#else
+  ASSERT_EQ(0, errors.size());
+#endif
+}
+
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.cc b/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.cc
new file mode 100644
index 0000000..6080142
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.cc
@@ -0,0 +1,2772 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include <google/protobuf/wrappers.pb.h>
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* DoubleValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  DoubleValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FloatValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  FloatValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Int64Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Int64Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UInt64Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  UInt64Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Int32Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Int32Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UInt32Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  UInt32Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* BoolValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  BoolValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* StringValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  StringValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* BytesValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  BytesValue_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/wrappers.proto");
+  GOOGLE_CHECK(file != NULL);
+  DoubleValue_descriptor_ = file->message_type(0);
+  static const int DoubleValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, value_),
+  };
+  DoubleValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      DoubleValue_descriptor_,
+      DoubleValue::default_instance_,
+      DoubleValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(DoubleValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, _is_default_instance_));
+  FloatValue_descriptor_ = file->message_type(1);
+  static const int FloatValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, value_),
+  };
+  FloatValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      FloatValue_descriptor_,
+      FloatValue::default_instance_,
+      FloatValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(FloatValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, _is_default_instance_));
+  Int64Value_descriptor_ = file->message_type(2);
+  static const int Int64Value_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, value_),
+  };
+  Int64Value_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Int64Value_descriptor_,
+      Int64Value::default_instance_,
+      Int64Value_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Int64Value),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, _is_default_instance_));
+  UInt64Value_descriptor_ = file->message_type(3);
+  static const int UInt64Value_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, value_),
+  };
+  UInt64Value_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      UInt64Value_descriptor_,
+      UInt64Value::default_instance_,
+      UInt64Value_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(UInt64Value),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, _is_default_instance_));
+  Int32Value_descriptor_ = file->message_type(4);
+  static const int Int32Value_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, value_),
+  };
+  Int32Value_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      Int32Value_descriptor_,
+      Int32Value::default_instance_,
+      Int32Value_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(Int32Value),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, _is_default_instance_));
+  UInt32Value_descriptor_ = file->message_type(5);
+  static const int UInt32Value_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, value_),
+  };
+  UInt32Value_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      UInt32Value_descriptor_,
+      UInt32Value::default_instance_,
+      UInt32Value_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(UInt32Value),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, _is_default_instance_));
+  BoolValue_descriptor_ = file->message_type(6);
+  static const int BoolValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, value_),
+  };
+  BoolValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      BoolValue_descriptor_,
+      BoolValue::default_instance_,
+      BoolValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(BoolValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, _is_default_instance_));
+  StringValue_descriptor_ = file->message_type(7);
+  static const int StringValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, value_),
+  };
+  StringValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      StringValue_descriptor_,
+      StringValue::default_instance_,
+      StringValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(StringValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, _is_default_instance_));
+  BytesValue_descriptor_ = file->message_type(8);
+  static const int BytesValue_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, value_),
+  };
+  BytesValue_reflection_ =
+    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+      BytesValue_descriptor_,
+      BytesValue::default_instance_,
+      BytesValue_offsets_,
+      -1,
+      -1,
+      -1,
+      sizeof(BytesValue),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, _internal_metadata_),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      DoubleValue_descriptor_, &DoubleValue::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      FloatValue_descriptor_, &FloatValue::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Int64Value_descriptor_, &Int64Value::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      UInt64Value_descriptor_, &UInt64Value::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      Int32Value_descriptor_, &Int32Value::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      UInt32Value_descriptor_, &UInt32Value::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      BoolValue_descriptor_, &BoolValue::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      StringValue_descriptor_, &StringValue::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+      BytesValue_descriptor_, &BytesValue::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto() {
+  delete DoubleValue::default_instance_;
+  delete DoubleValue_reflection_;
+  delete FloatValue::default_instance_;
+  delete FloatValue_reflection_;
+  delete Int64Value::default_instance_;
+  delete Int64Value_reflection_;
+  delete UInt64Value::default_instance_;
+  delete UInt64Value_reflection_;
+  delete Int32Value::default_instance_;
+  delete Int32Value_reflection_;
+  delete UInt32Value::default_instance_;
+  delete UInt32Value_reflection_;
+  delete BoolValue::default_instance_;
+  delete BoolValue_reflection_;
+  delete StringValue::default_instance_;
+  delete StringValue_reflection_;
+  delete BytesValue::default_instance_;
+  delete BytesValue_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\036google/protobuf/wrappers.proto\022\017google"
+    ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\""
+    "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val"
+    "ue\022\r\n\005value\030\001 \001(\003\"\034\n\013UInt64Value\022\r\n\005valu"
+    "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013"
+    "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022"
+    "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001"
+    " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\177\n\023com"
+    ".google.protobufB\rWrappersProtoP\001Z*githu"
+    "b.com/golang/protobuf/ptypes/wrappers\240\001\001"
+    "\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTyp"
+    "esb\006proto3", 450);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
+  DoubleValue::default_instance_ = new DoubleValue();
+  FloatValue::default_instance_ = new FloatValue();
+  Int64Value::default_instance_ = new Int64Value();
+  UInt64Value::default_instance_ = new UInt64Value();
+  Int32Value::default_instance_ = new Int32Value();
+  UInt32Value::default_instance_ = new UInt32Value();
+  BoolValue::default_instance_ = new BoolValue();
+  StringValue::default_instance_ = new StringValue();
+  BytesValue::default_instance_ = new BytesValue();
+  DoubleValue::default_instance_->InitAsDefaultInstance();
+  FloatValue::default_instance_->InitAsDefaultInstance();
+  Int64Value::default_instance_->InitAsDefaultInstance();
+  UInt64Value::default_instance_->InitAsDefaultInstance();
+  Int32Value::default_instance_->InitAsDefaultInstance();
+  UInt32Value::default_instance_->InitAsDefaultInstance();
+  BoolValue::default_instance_->InitAsDefaultInstance();
+  StringValue::default_instance_->InitAsDefaultInstance();
+  BytesValue::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fwrappers_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+}  // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int DoubleValue::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+DoubleValue::DoubleValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.DoubleValue)
+}
+
+DoubleValue::DoubleValue(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.DoubleValue)
+}
+
+void DoubleValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+DoubleValue::DoubleValue(const DoubleValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.DoubleValue)
+}
+
+void DoubleValue::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = 0;
+}
+
+DoubleValue::~DoubleValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.DoubleValue)
+  SharedDtor();
+}
+
+void DoubleValue::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void DoubleValue::ArenaDtor(void* object) {
+  DoubleValue* _this = reinterpret_cast< DoubleValue* >(object);
+  (void)_this;
+}
+void DoubleValue::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void DoubleValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DoubleValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return DoubleValue_descriptor_;
+}
+
+const DoubleValue& DoubleValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+DoubleValue* DoubleValue::default_instance_ = NULL;
+
+DoubleValue* DoubleValue::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<DoubleValue>(arena);
+}
+
+void DoubleValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
+  value_ = 0;
+}
+
+bool DoubleValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.DoubleValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional double value = 1;
+      case 1: {
+        if (tag == 9) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.DoubleValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.DoubleValue)
+  return false;
+#undef DO_
+}
+
+void DoubleValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.DoubleValue)
+  // optional double value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.DoubleValue)
+}
+
+::google::protobuf::uint8* DoubleValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue)
+  // optional double value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DoubleValue)
+  return target;
+}
+
+int DoubleValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue)
+  int total_size = 0;
+
+  // optional double value = 1;
+  if (this->value() != 0) {
+    total_size += 1 + 8;
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DoubleValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DoubleValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DoubleValue)
+    MergeFrom(*source);
+  }
+}
+
+void DoubleValue::MergeFrom(const DoubleValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void DoubleValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DoubleValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DoubleValue::CopyFrom(const DoubleValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DoubleValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DoubleValue::IsInitialized() const {
+
+  return true;
+}
+
+void DoubleValue::Swap(DoubleValue* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    DoubleValue temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void DoubleValue::UnsafeArenaSwap(DoubleValue* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void DoubleValue::InternalSwap(DoubleValue* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DoubleValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = DoubleValue_descriptor_;
+  metadata.reflection = DoubleValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DoubleValue
+
+// optional double value = 1;
+void DoubleValue::clear_value() {
+  value_ = 0;
+}
+ double DoubleValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DoubleValue.value)
+  return value_;
+}
+ void DoubleValue::set_value(double value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DoubleValue.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int FloatValue::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+FloatValue::FloatValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.FloatValue)
+}
+
+FloatValue::FloatValue(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.FloatValue)
+}
+
+void FloatValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+FloatValue::FloatValue(const FloatValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.FloatValue)
+}
+
+void FloatValue::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = 0;
+}
+
+FloatValue::~FloatValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.FloatValue)
+  SharedDtor();
+}
+
+void FloatValue::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void FloatValue::ArenaDtor(void* object) {
+  FloatValue* _this = reinterpret_cast< FloatValue* >(object);
+  (void)_this;
+}
+void FloatValue::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void FloatValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FloatValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return FloatValue_descriptor_;
+}
+
+const FloatValue& FloatValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+FloatValue* FloatValue::default_instance_ = NULL;
+
+FloatValue* FloatValue::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<FloatValue>(arena);
+}
+
+void FloatValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
+  value_ = 0;
+}
+
+bool FloatValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.FloatValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional float value = 1;
+      case 1: {
+        if (tag == 13) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.FloatValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.FloatValue)
+  return false;
+#undef DO_
+}
+
+void FloatValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.FloatValue)
+  // optional float value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.FloatValue)
+}
+
+::google::protobuf::uint8* FloatValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue)
+  // optional float value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FloatValue)
+  return target;
+}
+
+int FloatValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue)
+  int total_size = 0;
+
+  // optional float value = 1;
+  if (this->value() != 0) {
+    total_size += 1 + 4;
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FloatValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FloatValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FloatValue)
+    MergeFrom(*source);
+  }
+}
+
+void FloatValue::MergeFrom(const FloatValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void FloatValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FloatValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FloatValue::CopyFrom(const FloatValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FloatValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool FloatValue::IsInitialized() const {
+
+  return true;
+}
+
+void FloatValue::Swap(FloatValue* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    FloatValue temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void FloatValue::UnsafeArenaSwap(FloatValue* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void FloatValue::InternalSwap(FloatValue* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FloatValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = FloatValue_descriptor_;
+  metadata.reflection = FloatValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FloatValue
+
+// optional float value = 1;
+void FloatValue::clear_value() {
+  value_ = 0;
+}
+ float FloatValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FloatValue.value)
+  return value_;
+}
+ void FloatValue::set_value(float value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FloatValue.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Int64Value::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Int64Value::Int64Value()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Int64Value)
+}
+
+Int64Value::Int64Value(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.Int64Value)
+}
+
+void Int64Value::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Int64Value::Int64Value(const Int64Value& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Int64Value)
+}
+
+void Int64Value::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = GOOGLE_LONGLONG(0);
+}
+
+Int64Value::~Int64Value() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Int64Value)
+  SharedDtor();
+}
+
+void Int64Value::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void Int64Value::ArenaDtor(void* object) {
+  Int64Value* _this = reinterpret_cast< Int64Value* >(object);
+  (void)_this;
+}
+void Int64Value::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void Int64Value::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Int64Value::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Int64Value_descriptor_;
+}
+
+const Int64Value& Int64Value::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+Int64Value* Int64Value::default_instance_ = NULL;
+
+Int64Value* Int64Value::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<Int64Value>(arena);
+}
+
+void Int64Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
+  value_ = GOOGLE_LONGLONG(0);
+}
+
+bool Int64Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Int64Value)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int64 value = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Int64Value)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Int64Value)
+  return false;
+#undef DO_
+}
+
+void Int64Value::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Int64Value)
+  // optional int64 value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Int64Value)
+}
+
+::google::protobuf::uint8* Int64Value::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value)
+  // optional int64 value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int64Value)
+  return target;
+}
+
+int Int64Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value)
+  int total_size = 0;
+
+  // optional int64 value = 1;
+  if (this->value() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Int64Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int64Value)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int64Value)
+    MergeFrom(*source);
+  }
+}
+
+void Int64Value::MergeFrom(const Int64Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void Int64Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int64Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Int64Value::CopyFrom(const Int64Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int64Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Int64Value::IsInitialized() const {
+
+  return true;
+}
+
+void Int64Value::Swap(Int64Value* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    Int64Value temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void Int64Value::UnsafeArenaSwap(Int64Value* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void Int64Value::InternalSwap(Int64Value* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Int64Value::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Int64Value_descriptor_;
+  metadata.reflection = Int64Value_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Int64Value
+
+// optional int64 value = 1;
+void Int64Value::clear_value() {
+  value_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Int64Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value)
+  return value_;
+}
+ void Int64Value::set_value(::google::protobuf::int64 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int UInt64Value::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+UInt64Value::UInt64Value()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.UInt64Value)
+}
+
+UInt64Value::UInt64Value(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt64Value)
+}
+
+void UInt64Value::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+UInt64Value::UInt64Value(const UInt64Value& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt64Value)
+}
+
+void UInt64Value::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = GOOGLE_ULONGLONG(0);
+}
+
+UInt64Value::~UInt64Value() {
+  // @@protoc_insertion_point(destructor:google.protobuf.UInt64Value)
+  SharedDtor();
+}
+
+void UInt64Value::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void UInt64Value::ArenaDtor(void* object) {
+  UInt64Value* _this = reinterpret_cast< UInt64Value* >(object);
+  (void)_this;
+}
+void UInt64Value::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void UInt64Value::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UInt64Value::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return UInt64Value_descriptor_;
+}
+
+const UInt64Value& UInt64Value::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+UInt64Value* UInt64Value::default_instance_ = NULL;
+
+UInt64Value* UInt64Value::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<UInt64Value>(arena);
+}
+
+void UInt64Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
+  value_ = GOOGLE_ULONGLONG(0);
+}
+
+bool UInt64Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.UInt64Value)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional uint64 value = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.UInt64Value)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.UInt64Value)
+  return false;
+#undef DO_
+}
+
+void UInt64Value::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.UInt64Value)
+  // optional uint64 value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.UInt64Value)
+}
+
+::google::protobuf::uint8* UInt64Value::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value)
+  // optional uint64 value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt64Value)
+  return target;
+}
+
+int UInt64Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value)
+  int total_size = 0;
+
+  // optional uint64 value = 1;
+  if (this->value() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt64Size(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UInt64Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt64Value)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt64Value)
+    MergeFrom(*source);
+  }
+}
+
+void UInt64Value::MergeFrom(const UInt64Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void UInt64Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt64Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UInt64Value::CopyFrom(const UInt64Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt64Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UInt64Value::IsInitialized() const {
+
+  return true;
+}
+
+void UInt64Value::Swap(UInt64Value* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    UInt64Value temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void UInt64Value::UnsafeArenaSwap(UInt64Value* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void UInt64Value::InternalSwap(UInt64Value* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UInt64Value::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UInt64Value_descriptor_;
+  metadata.reflection = UInt64Value_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UInt64Value
+
+// optional uint64 value = 1;
+void UInt64Value::clear_value() {
+  value_ = GOOGLE_ULONGLONG(0);
+}
+ ::google::protobuf::uint64 UInt64Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value)
+  return value_;
+}
+ void UInt64Value::set_value(::google::protobuf::uint64 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Int32Value::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Int32Value::Int32Value()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.Int32Value)
+}
+
+Int32Value::Int32Value(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.Int32Value)
+}
+
+void Int32Value::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+Int32Value::Int32Value(const Int32Value& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.Int32Value)
+}
+
+void Int32Value::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = 0;
+}
+
+Int32Value::~Int32Value() {
+  // @@protoc_insertion_point(destructor:google.protobuf.Int32Value)
+  SharedDtor();
+}
+
+void Int32Value::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void Int32Value::ArenaDtor(void* object) {
+  Int32Value* _this = reinterpret_cast< Int32Value* >(object);
+  (void)_this;
+}
+void Int32Value::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void Int32Value::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Int32Value::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Int32Value_descriptor_;
+}
+
+const Int32Value& Int32Value::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+Int32Value* Int32Value::default_instance_ = NULL;
+
+Int32Value* Int32Value::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<Int32Value>(arena);
+}
+
+void Int32Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
+  value_ = 0;
+}
+
+bool Int32Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.Int32Value)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int32 value = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.Int32Value)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.Int32Value)
+  return false;
+#undef DO_
+}
+
+void Int32Value::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.Int32Value)
+  // optional int32 value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.Int32Value)
+}
+
+::google::protobuf::uint8* Int32Value::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value)
+  // optional int32 value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int32Value)
+  return target;
+}
+
+int Int32Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value)
+  int total_size = 0;
+
+  // optional int32 value = 1;
+  if (this->value() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Int32Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int32Value)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int32Value)
+    MergeFrom(*source);
+  }
+}
+
+void Int32Value::MergeFrom(const Int32Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void Int32Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int32Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Int32Value::CopyFrom(const Int32Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int32Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Int32Value::IsInitialized() const {
+
+  return true;
+}
+
+void Int32Value::Swap(Int32Value* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    Int32Value temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void Int32Value::UnsafeArenaSwap(Int32Value* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void Int32Value::InternalSwap(Int32Value* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Int32Value::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Int32Value_descriptor_;
+  metadata.reflection = Int32Value_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Int32Value
+
+// optional int32 value = 1;
+void Int32Value::clear_value() {
+  value_ = 0;
+}
+ ::google::protobuf::int32 Int32Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value)
+  return value_;
+}
+ void Int32Value::set_value(::google::protobuf::int32 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int UInt32Value::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+UInt32Value::UInt32Value()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.UInt32Value)
+}
+
+UInt32Value::UInt32Value(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt32Value)
+}
+
+void UInt32Value::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+UInt32Value::UInt32Value(const UInt32Value& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt32Value)
+}
+
+void UInt32Value::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = 0u;
+}
+
+UInt32Value::~UInt32Value() {
+  // @@protoc_insertion_point(destructor:google.protobuf.UInt32Value)
+  SharedDtor();
+}
+
+void UInt32Value::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void UInt32Value::ArenaDtor(void* object) {
+  UInt32Value* _this = reinterpret_cast< UInt32Value* >(object);
+  (void)_this;
+}
+void UInt32Value::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void UInt32Value::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UInt32Value::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return UInt32Value_descriptor_;
+}
+
+const UInt32Value& UInt32Value::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+UInt32Value* UInt32Value::default_instance_ = NULL;
+
+UInt32Value* UInt32Value::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<UInt32Value>(arena);
+}
+
+void UInt32Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
+  value_ = 0u;
+}
+
+bool UInt32Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.UInt32Value)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional uint32 value = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.UInt32Value)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.UInt32Value)
+  return false;
+#undef DO_
+}
+
+void UInt32Value::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.UInt32Value)
+  // optional uint32 value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.UInt32Value)
+}
+
+::google::protobuf::uint8* UInt32Value::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value)
+  // optional uint32 value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt32Value)
+  return target;
+}
+
+int UInt32Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value)
+  int total_size = 0;
+
+  // optional uint32 value = 1;
+  if (this->value() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt32Size(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UInt32Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt32Value)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt32Value)
+    MergeFrom(*source);
+  }
+}
+
+void UInt32Value::MergeFrom(const UInt32Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void UInt32Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt32Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UInt32Value::CopyFrom(const UInt32Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt32Value)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UInt32Value::IsInitialized() const {
+
+  return true;
+}
+
+void UInt32Value::Swap(UInt32Value* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    UInt32Value temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void UInt32Value::UnsafeArenaSwap(UInt32Value* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void UInt32Value::InternalSwap(UInt32Value* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UInt32Value::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = UInt32Value_descriptor_;
+  metadata.reflection = UInt32Value_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UInt32Value
+
+// optional uint32 value = 1;
+void UInt32Value::clear_value() {
+  value_ = 0u;
+}
+ ::google::protobuf::uint32 UInt32Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value)
+  return value_;
+}
+ void UInt32Value::set_value(::google::protobuf::uint32 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int BoolValue::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+BoolValue::BoolValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.BoolValue)
+}
+
+BoolValue::BoolValue(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.BoolValue)
+}
+
+void BoolValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+BoolValue::BoolValue(const BoolValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.BoolValue)
+}
+
+void BoolValue::SharedCtor() {
+    _is_default_instance_ = false;
+  _cached_size_ = 0;
+  value_ = false;
+}
+
+BoolValue::~BoolValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.BoolValue)
+  SharedDtor();
+}
+
+void BoolValue::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  if (this != default_instance_) {
+  }
+}
+
+void BoolValue::ArenaDtor(void* object) {
+  BoolValue* _this = reinterpret_cast< BoolValue* >(object);
+  (void)_this;
+}
+void BoolValue::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void BoolValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* BoolValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return BoolValue_descriptor_;
+}
+
+const BoolValue& BoolValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+BoolValue* BoolValue::default_instance_ = NULL;
+
+BoolValue* BoolValue::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<BoolValue>(arena);
+}
+
+void BoolValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
+  value_ = false;
+}
+
+bool BoolValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.BoolValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool value = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &value_)));
+
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.BoolValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.BoolValue)
+  return false;
+#undef DO_
+}
+
+void BoolValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.BoolValue)
+  // optional bool value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.BoolValue)
+}
+
+::google::protobuf::uint8* BoolValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue)
+  // optional bool value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BoolValue)
+  return target;
+}
+
+int BoolValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue)
+  int total_size = 0;
+
+  // optional bool value = 1;
+  if (this->value() != 0) {
+    total_size += 1 + 1;
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const BoolValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BoolValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BoolValue)
+    MergeFrom(*source);
+  }
+}
+
+void BoolValue::MergeFrom(const BoolValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void BoolValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BoolValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void BoolValue::CopyFrom(const BoolValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BoolValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool BoolValue::IsInitialized() const {
+
+  return true;
+}
+
+void BoolValue::Swap(BoolValue* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    BoolValue temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void BoolValue::UnsafeArenaSwap(BoolValue* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void BoolValue::InternalSwap(BoolValue* other) {
+  std::swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata BoolValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = BoolValue_descriptor_;
+  metadata.reflection = BoolValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// BoolValue
+
+// optional bool value = 1;
+void BoolValue::clear_value() {
+  value_ = false;
+}
+ bool BoolValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.BoolValue.value)
+  return value_;
+}
+ void BoolValue::set_value(bool value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.BoolValue.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StringValue::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StringValue::StringValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.StringValue)
+}
+
+StringValue::StringValue(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.StringValue)
+}
+
+void StringValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+StringValue::StringValue(const StringValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.StringValue)
+}
+
+void StringValue::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+StringValue::~StringValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.StringValue)
+  SharedDtor();
+}
+
+void StringValue::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  if (this != default_instance_) {
+  }
+}
+
+void StringValue::ArenaDtor(void* object) {
+  StringValue* _this = reinterpret_cast< StringValue* >(object);
+  (void)_this;
+}
+void StringValue::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void StringValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* StringValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return StringValue_descriptor_;
+}
+
+const StringValue& StringValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+StringValue* StringValue::default_instance_ = NULL;
+
+StringValue* StringValue::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<StringValue>(arena);
+}
+
+void StringValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+
+bool StringValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.StringValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string value = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_value()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->value().data(), this->value().length(),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "google.protobuf.StringValue.value"));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.StringValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.StringValue)
+  return false;
+#undef DO_
+}
+
+void StringValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.StringValue)
+  // optional string value = 1;
+  if (this->value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->value().data(), this->value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.StringValue.value");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.StringValue)
+}
+
+::google::protobuf::uint8* StringValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
+  // optional string value = 1;
+  if (this->value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->value().data(), this->value().length(),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "google.protobuf.StringValue.value");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.StringValue)
+  return target;
+}
+
+int StringValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue)
+  int total_size = 0;
+
+  // optional string value = 1;
+  if (this->value().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const StringValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.StringValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.StringValue)
+    MergeFrom(*source);
+  }
+}
+
+void StringValue::MergeFrom(const StringValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value().size() > 0) {
+    set_value(from.value());
+  }
+}
+
+void StringValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.StringValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StringValue::CopyFrom(const StringValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.StringValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StringValue::IsInitialized() const {
+
+  return true;
+}
+
+void StringValue::Swap(StringValue* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    StringValue temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void StringValue::UnsafeArenaSwap(StringValue* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void StringValue::InternalSwap(StringValue* other) {
+  value_.Swap(&other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata StringValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = StringValue_descriptor_;
+  metadata.reflection = StringValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// StringValue
+
+// optional string value = 1;
+void StringValue::clear_value() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ const ::std::string& StringValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
+  return value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void StringValue::set_value(const ::std::string& value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
+}
+ void StringValue::set_value(const char* value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+              GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
+}
+ void StringValue::set_value(const char* value,
+    size_t size) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
+}
+ ::std::string* StringValue::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value)
+  return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* StringValue::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value)
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* StringValue::unsafe_arena_release_value() {
+  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value)
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  
+  return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      GetArenaNoVirtual());
+}
+ void StringValue::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value,
+      GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+}
+ void StringValue::unsafe_arena_set_allocated_value(
+    ::std::string* value) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int BytesValue::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+BytesValue::BytesValue()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.BytesValue)
+}
+
+BytesValue::BytesValue(::google::protobuf::Arena* arena)
+  : ::google::protobuf::Message(),
+  _internal_metadata_(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:google.protobuf.BytesValue)
+}
+
+void BytesValue::InitAsDefaultInstance() {
+  _is_default_instance_ = true;
+}
+
+BytesValue::BytesValue(const BytesValue& from)
+  : ::google::protobuf::Message(),
+    _internal_metadata_(NULL) {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.BytesValue)
+}
+
+void BytesValue::SharedCtor() {
+    _is_default_instance_ = false;
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+BytesValue::~BytesValue() {
+  // @@protoc_insertion_point(destructor:google.protobuf.BytesValue)
+  SharedDtor();
+}
+
+void BytesValue::SharedDtor() {
+  if (GetArenaNoVirtual() != NULL) {
+    return;
+  }
+
+  value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  if (this != default_instance_) {
+  }
+}
+
+void BytesValue::ArenaDtor(void* object) {
+  BytesValue* _this = reinterpret_cast< BytesValue* >(object);
+  (void)_this;
+}
+void BytesValue::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
+void BytesValue::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* BytesValue::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return BytesValue_descriptor_;
+}
+
+const BytesValue& BytesValue::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  return *default_instance_;
+}
+
+BytesValue* BytesValue::default_instance_ = NULL;
+
+BytesValue* BytesValue::New(::google::protobuf::Arena* arena) const {
+  return ::google::protobuf::Arena::CreateMessage<BytesValue>(arena);
+}
+
+void BytesValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+
+bool BytesValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.BytesValue)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bytes value = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_value()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.BytesValue)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.BytesValue)
+  return false;
+#undef DO_
+}
+
+void BytesValue::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.BytesValue)
+  // optional bytes value = 1;
+  if (this->value().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      1, this->value(), output);
+  }
+
+  // @@protoc_insertion_point(serialize_end:google.protobuf.BytesValue)
+}
+
+::google::protobuf::uint8* BytesValue::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue)
+  // optional bytes value = 1;
+  if (this->value().size() > 0) {
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        1, this->value(), target);
+  }
+
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BytesValue)
+  return target;
+}
+
+int BytesValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue)
+  int total_size = 0;
+
+  // optional bytes value = 1;
+  if (this->value().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::BytesSize(
+        this->value());
+  }
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const BytesValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BytesValue)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BytesValue)
+    MergeFrom(*source);
+  }
+}
+
+void BytesValue::MergeFrom(const BytesValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue)
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value().size() > 0) {
+    set_value(from.value());
+  }
+}
+
+void BytesValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BytesValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void BytesValue::CopyFrom(const BytesValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BytesValue)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool BytesValue::IsInitialized() const {
+
+  return true;
+}
+
+void BytesValue::Swap(BytesValue* other) {
+  if (other == this) return;
+  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+    InternalSwap(other);
+  } else {
+    BytesValue temp;
+    temp.MergeFrom(*this);
+    CopyFrom(*other);
+    other->CopyFrom(temp);
+  }
+}
+void BytesValue::UnsafeArenaSwap(BytesValue* other) {
+  if (other == this) return;
+  GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+  InternalSwap(other);
+}
+void BytesValue::InternalSwap(BytesValue* other) {
+  value_.Swap(&other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata BytesValue::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = BytesValue_descriptor_;
+  metadata.reflection = BytesValue_reflection_;
+  return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// BytesValue
+
+// optional bytes value = 1;
+void BytesValue::clear_value() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ const ::std::string& BytesValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
+  return value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void BytesValue::set_value(const ::std::string& value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
+}
+ void BytesValue::set_value(const char* value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+              GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
+}
+ void BytesValue::set_value(const void* value,
+    size_t size) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
+}
+ ::std::string* BytesValue::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value)
+  return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* BytesValue::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* BytesValue::unsafe_arena_release_value() {
+  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value)
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  
+  return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      GetArenaNoVirtual());
+}
+ void BytesValue::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value,
+      GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+}
+ void BytesValue::unsafe_arena_set_allocated_value(
+    ::std::string* value) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.h b/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.h
new file mode 100644
index 0000000..1078477
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wrappers.pb.h
@@ -0,0 +1,1180 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+class BoolValue;
+class BytesValue;
+class DoubleValue;
+class FloatValue;
+class Int32Value;
+class Int64Value;
+class StringValue;
+class UInt32Value;
+class UInt64Value;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT DoubleValue : public ::google::protobuf::Message {
+ public:
+  DoubleValue();
+  virtual ~DoubleValue();
+
+  DoubleValue(const DoubleValue& from);
+
+  inline DoubleValue& operator=(const DoubleValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const DoubleValue& default_instance();
+
+  void UnsafeArenaSwap(DoubleValue* other);
+  void Swap(DoubleValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline DoubleValue* New() const { return New(NULL); }
+
+  DoubleValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const DoubleValue& from);
+  void MergeFrom(const DoubleValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(DoubleValue* other);
+  protected:
+  explicit DoubleValue(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional double value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  double value() const;
+  void set_value(double value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  double value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static DoubleValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FloatValue : public ::google::protobuf::Message {
+ public:
+  FloatValue();
+  virtual ~FloatValue();
+
+  FloatValue(const FloatValue& from);
+
+  inline FloatValue& operator=(const FloatValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const FloatValue& default_instance();
+
+  void UnsafeArenaSwap(FloatValue* other);
+  void Swap(FloatValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline FloatValue* New() const { return New(NULL); }
+
+  FloatValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const FloatValue& from);
+  void MergeFrom(const FloatValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(FloatValue* other);
+  protected:
+  explicit FloatValue(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional float value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  float value() const;
+  void set_value(float value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.FloatValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  float value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static FloatValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Int64Value : public ::google::protobuf::Message {
+ public:
+  Int64Value();
+  virtual ~Int64Value();
+
+  Int64Value(const Int64Value& from);
+
+  inline Int64Value& operator=(const Int64Value& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Int64Value& default_instance();
+
+  void UnsafeArenaSwap(Int64Value* other);
+  void Swap(Int64Value* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Int64Value* New() const { return New(NULL); }
+
+  Int64Value* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Int64Value& from);
+  void MergeFrom(const Int64Value& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Int64Value* other);
+  protected:
+  explicit Int64Value(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int64 value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  ::google::protobuf::int64 value() const;
+  void set_value(::google::protobuf::int64 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Int64Value)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::int64 value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static Int64Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UInt64Value : public ::google::protobuf::Message {
+ public:
+  UInt64Value();
+  virtual ~UInt64Value();
+
+  UInt64Value(const UInt64Value& from);
+
+  inline UInt64Value& operator=(const UInt64Value& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const UInt64Value& default_instance();
+
+  void UnsafeArenaSwap(UInt64Value* other);
+  void Swap(UInt64Value* other);
+
+  // implements Message ----------------------------------------------
+
+  inline UInt64Value* New() const { return New(NULL); }
+
+  UInt64Value* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const UInt64Value& from);
+  void MergeFrom(const UInt64Value& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(UInt64Value* other);
+  protected:
+  explicit UInt64Value(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional uint64 value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  ::google::protobuf::uint64 value() const;
+  void set_value(::google::protobuf::uint64 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::uint64 value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static UInt64Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Int32Value : public ::google::protobuf::Message {
+ public:
+  Int32Value();
+  virtual ~Int32Value();
+
+  Int32Value(const Int32Value& from);
+
+  inline Int32Value& operator=(const Int32Value& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Int32Value& default_instance();
+
+  void UnsafeArenaSwap(Int32Value* other);
+  void Swap(Int32Value* other);
+
+  // implements Message ----------------------------------------------
+
+  inline Int32Value* New() const { return New(NULL); }
+
+  Int32Value* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Int32Value& from);
+  void MergeFrom(const Int32Value& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(Int32Value* other);
+  protected:
+  explicit Int32Value(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional int32 value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  ::google::protobuf::int32 value() const;
+  void set_value(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.Int32Value)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::int32 value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static Int32Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UInt32Value : public ::google::protobuf::Message {
+ public:
+  UInt32Value();
+  virtual ~UInt32Value();
+
+  UInt32Value(const UInt32Value& from);
+
+  inline UInt32Value& operator=(const UInt32Value& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const UInt32Value& default_instance();
+
+  void UnsafeArenaSwap(UInt32Value* other);
+  void Swap(UInt32Value* other);
+
+  // implements Message ----------------------------------------------
+
+  inline UInt32Value* New() const { return New(NULL); }
+
+  UInt32Value* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const UInt32Value& from);
+  void MergeFrom(const UInt32Value& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(UInt32Value* other);
+  protected:
+  explicit UInt32Value(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional uint32 value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  ::google::protobuf::uint32 value() const;
+  void set_value(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::uint32 value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static UInt32Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT BoolValue : public ::google::protobuf::Message {
+ public:
+  BoolValue();
+  virtual ~BoolValue();
+
+  BoolValue(const BoolValue& from);
+
+  inline BoolValue& operator=(const BoolValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const BoolValue& default_instance();
+
+  void UnsafeArenaSwap(BoolValue* other);
+  void Swap(BoolValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline BoolValue* New() const { return New(NULL); }
+
+  BoolValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const BoolValue& from);
+  void MergeFrom(const BoolValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(BoolValue* other);
+  protected:
+  explicit BoolValue(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bool value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  bool value() const;
+  void set_value(bool value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.BoolValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  bool value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static BoolValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT StringValue : public ::google::protobuf::Message {
+ public:
+  StringValue();
+  virtual ~StringValue();
+
+  StringValue(const StringValue& from);
+
+  inline StringValue& operator=(const StringValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const StringValue& default_instance();
+
+  void UnsafeArenaSwap(StringValue* other);
+  void Swap(StringValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline StringValue* New() const { return New(NULL); }
+
+  StringValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const StringValue& from);
+  void MergeFrom(const StringValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(StringValue* other);
+  protected:
+  explicit StringValue(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  const ::std::string& value() const;
+  void set_value(const ::std::string& value);
+  void set_value(const char* value);
+  void set_value(const char* value, size_t size);
+  ::std::string* mutable_value();
+  ::std::string* release_value();
+  void set_allocated_value(::std::string* value);
+  ::std::string* unsafe_arena_release_value();
+  void unsafe_arena_set_allocated_value(
+      ::std::string* value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.StringValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static StringValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT BytesValue : public ::google::protobuf::Message {
+ public:
+  BytesValue();
+  virtual ~BytesValue();
+
+  BytesValue(const BytesValue& from);
+
+  inline BytesValue& operator=(const BytesValue& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+  inline void* GetMaybeArenaPointer() const {
+    return MaybeArenaPtr();
+  }
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const BytesValue& default_instance();
+
+  void UnsafeArenaSwap(BytesValue* other);
+  void Swap(BytesValue* other);
+
+  // implements Message ----------------------------------------------
+
+  inline BytesValue* New() const { return New(NULL); }
+
+  BytesValue* New(::google::protobuf::Arena* arena) const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const BytesValue& from);
+  void MergeFrom(const BytesValue& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  void InternalSwap(BytesValue* other);
+  protected:
+  explicit BytesValue(::google::protobuf::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return _internal_metadata_.arena();
+  }
+  inline void* MaybeArenaPtr() const {
+    return _internal_metadata_.raw_arena_ptr();
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional bytes value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  const ::std::string& value() const;
+  void set_value(const ::std::string& value);
+  void set_value(const char* value);
+  void set_value(const void* value, size_t size);
+  ::std::string* mutable_value();
+  ::std::string* release_value();
+  void set_allocated_value(::std::string* value);
+  ::std::string* unsafe_arena_release_value();
+  void unsafe_arena_set_allocated_value(
+      ::std::string* value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.BytesValue)
+ private:
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  friend class ::google::protobuf::Arena;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  bool _is_default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr value_;
+  mutable int _cached_size_;
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+  void InitAsDefaultInstance();
+  static BytesValue* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// DoubleValue
+
+// optional double value = 1;
+inline void DoubleValue::clear_value() {
+  value_ = 0;
+}
+inline double DoubleValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.DoubleValue.value)
+  return value_;
+}
+inline void DoubleValue::set_value(double value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.DoubleValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// FloatValue
+
+// optional float value = 1;
+inline void FloatValue::clear_value() {
+  value_ = 0;
+}
+inline float FloatValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FloatValue.value)
+  return value_;
+}
+inline void FloatValue::set_value(float value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FloatValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// Int64Value
+
+// optional int64 value = 1;
+inline void Int64Value::clear_value() {
+  value_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Int64Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value)
+  return value_;
+}
+inline void Int64Value::set_value(::google::protobuf::int64 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// UInt64Value
+
+// optional uint64 value = 1;
+inline void UInt64Value::clear_value() {
+  value_ = GOOGLE_ULONGLONG(0);
+}
+inline ::google::protobuf::uint64 UInt64Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value)
+  return value_;
+}
+inline void UInt64Value::set_value(::google::protobuf::uint64 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// Int32Value
+
+// optional int32 value = 1;
+inline void Int32Value::clear_value() {
+  value_ = 0;
+}
+inline ::google::protobuf::int32 Int32Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value)
+  return value_;
+}
+inline void Int32Value::set_value(::google::protobuf::int32 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// UInt32Value
+
+// optional uint32 value = 1;
+inline void UInt32Value::clear_value() {
+  value_ = 0u;
+}
+inline ::google::protobuf::uint32 UInt32Value::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value)
+  return value_;
+}
+inline void UInt32Value::set_value(::google::protobuf::uint32 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// BoolValue
+
+// optional bool value = 1;
+inline void BoolValue::clear_value() {
+  value_ = false;
+}
+inline bool BoolValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.BoolValue.value)
+  return value_;
+}
+inline void BoolValue::set_value(bool value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.BoolValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// StringValue
+
+// optional string value = 1;
+inline void StringValue::clear_value() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline const ::std::string& StringValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
+  return value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StringValue::set_value(const ::std::string& value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
+}
+inline void StringValue::set_value(const char* value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+              GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
+}
+inline void StringValue::set_value(const char* value,
+    size_t size) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
+}
+inline ::std::string* StringValue::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value)
+  return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* StringValue::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value)
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* StringValue::unsafe_arena_release_value() {
+  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value)
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  
+  return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      GetArenaNoVirtual());
+}
+inline void StringValue::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value,
+      GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+}
+inline void StringValue::unsafe_arena_set_allocated_value(
+    ::std::string* value) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// BytesValue
+
+// optional bytes value = 1;
+inline void BytesValue::clear_value() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline const ::std::string& BytesValue::value() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
+  return value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void BytesValue::set_value(const ::std::string& value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
+}
+inline void BytesValue::set_value(const char* value) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+              GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
+}
+inline void BytesValue::set_value(const void* value,
+    size_t size) {
+  
+  value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
+}
+inline ::std::string* BytesValue::mutable_value() {
+  
+  // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value)
+  return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* BytesValue::release_value() {
+  // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* BytesValue::unsafe_arena_release_value() {
+  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value)
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  
+  return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      GetArenaNoVirtual());
+}
+inline void BytesValue::set_allocated_value(::std::string* value) {
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value,
+      GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+}
+inline void BytesValue::unsafe_arena_set_allocated_value(
+    ::std::string* value) {
+  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+  if (value != NULL) {
+    
+  } else {
+    
+  }
+  value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      value, GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
+}
+
+#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
diff --git a/src/third_party/protobuf-3/src/google/protobuf/wrappers.proto b/src/third_party/protobuf-3/src/google/protobuf/wrappers.proto
new file mode 100644
index 0000000..4828ad9
--- /dev/null
+++ b/src/third_party/protobuf-3/src/google/protobuf/wrappers.proto
@@ -0,0 +1,119 @@
+// 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.
+
+// Wrappers for primitive (non-message) types. These types are useful
+// for embedding primitives in the `google.protobuf.Any` type and for places
+// where we need to distinguish between the absence of a primitive
+// typed field and its default value.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/wrappers";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "WrappersProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
+option objc_class_prefix = "GPB";
+
+// Wrapper message for `double`.
+//
+// The JSON representation for `DoubleValue` is JSON number.
+message DoubleValue {
+  // The double value.
+  double value = 1;
+}
+
+// Wrapper message for `float`.
+//
+// The JSON representation for `FloatValue` is JSON number.
+message FloatValue {
+  // The float value.
+  float value = 1;
+}
+
+// Wrapper message for `int64`.
+//
+// The JSON representation for `Int64Value` is JSON string.
+message Int64Value {
+  // The int64 value.
+  int64 value = 1;
+}
+
+// Wrapper message for `uint64`.
+//
+// The JSON representation for `UInt64Value` is JSON string.
+message UInt64Value {
+  // The uint64 value.
+  uint64 value = 1;
+}
+
+// Wrapper message for `int32`.
+//
+// The JSON representation for `Int32Value` is JSON number.
+message Int32Value {
+  // The int32 value.
+  int32 value = 1;
+}
+
+// Wrapper message for `uint32`.
+//
+// The JSON representation for `UInt32Value` is JSON number.
+message UInt32Value {
+  // The uint32 value.
+  uint32 value = 1;
+}
+
+// Wrapper message for `bool`.
+//
+// The JSON representation for `BoolValue` is JSON `true` and `false`.
+message BoolValue {
+  // The bool value.
+  bool value = 1;
+}
+
+// Wrapper message for `string`.
+//
+// The JSON representation for `StringValue` is JSON string.
+message StringValue {
+  // The string value.
+  string value = 1;
+}
+
+// Wrapper message for `bytes`.
+//
+// The JSON representation for `BytesValue` is JSON string.
+message BytesValue {
+  // The bytes value.
+  bytes value = 1;
+}
diff --git a/src/third_party/protobuf-3/tests.sh b/src/third_party/protobuf-3/tests.sh
new file mode 100755
index 0000000..6a9439a
--- /dev/null
+++ b/src/third_party/protobuf-3/tests.sh
@@ -0,0 +1,347 @@
+#!/bin/bash
+#
+# Build and runs tests for the protobuf project.  The tests as written here are
+# used by both Jenkins and Travis, though some specialized logic is required to
+# handle the differences between them.
+
+on_travis() {
+  if [ "$TRAVIS" == "true" ]; then
+    "$@"
+  fi
+}
+
+# For when some other test needs the C++ main build, including protoc and
+# libprotobuf.
+internal_build_cpp() {
+  if [ -f src/protoc ]; then
+    # Already built.
+    return
+  fi
+
+  if [[ $(uname -s) == "Linux" && "$TRAVIS" == "true" ]]; then
+    # Install GCC 4.8 to replace the default GCC 4.6. We need 4.8 for more
+    # decent C++ 11 support in order to compile conformance tests.
+    sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+    sudo apt-get update -qq
+    sudo apt-get install -qq g++-4.8
+    export CXX="g++-4.8" CC="gcc-4.8"
+  fi
+
+  ./autogen.sh
+  ./configure
+  make -j2
+}
+
+build_cpp() {
+  internal_build_cpp
+  make check -j2
+  cd conformance && make test_cpp && cd ..
+
+  # Verify benchmarking code can build successfully.
+  cd benchmarks && make && ./generate-datasets && cd ..
+}
+
+build_cpp_distcheck() {
+  ./autogen.sh
+  ./configure
+  make distcheck -j2
+}
+
+build_csharp() {
+  # Just for the conformance tests. We don't currently
+  # need to really build protoc, but it's simplest to keep with the
+  # conventions of the other builds.
+  internal_build_cpp
+  NUGET=/usr/local/bin/nuget.exe
+
+  if [ "$TRAVIS" == "true" ]; then
+    # Install latest version of Mono
+    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+    echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
+    echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
+    sudo apt-get update -qq
+    sudo apt-get install -qq mono-devel referenceassemblies-pcl nunit
+    wget www.nuget.org/NuGet.exe -O nuget.exe
+    NUGET=../../nuget.exe
+  fi
+
+  (cd csharp/src; mono $NUGET restore)
+  csharp/buildall.sh
+  cd conformance && make test_csharp && cd ..
+}
+
+build_golang() {
+  # Go build needs `protoc`.
+  internal_build_cpp
+  # Add protoc to the path so that the examples build finds it.
+  export PATH="`pwd`/src:$PATH"
+
+  # Install Go and the Go protobuf compiler plugin.
+  sudo apt-get update -qq
+  sudo apt-get install -qq golang
+  export GOPATH="$HOME/gocode"
+  mkdir -p "$GOPATH/src/github.com/google"
+  ln -s "`pwd`" "$GOPATH/src/github.com/google/protobuf"
+  export PATH="$GOPATH/bin:$PATH"
+  go get github.com/golang/protobuf/protoc-gen-go
+
+  cd examples && make gotest && cd ..
+}
+
+use_java() {
+  version=$1
+  case "$version" in
+    jdk6)
+      on_travis sudo apt-get install openjdk-6-jdk
+      export PATH=/usr/lib/jvm/java-6-openjdk-amd64/bin:$PATH
+      ;;
+    jdk7)
+      on_travis sudo apt-get install openjdk-7-jdk
+      export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
+      ;;
+    oracle7)
+      if [ "$TRAVIS" == "true" ]; then
+        sudo apt-get install python-software-properties # for apt-add-repository
+        echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | \
+          sudo debconf-set-selections
+        yes | sudo apt-add-repository ppa:webupd8team/java
+        yes | sudo apt-get install oracle-java7-installer
+      fi;
+      export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH
+      ;;
+  esac
+
+  if [ "$TRAVIS" != "true" ]; then
+    MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository
+    MVN="$MVN -e -X --offline -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY"
+  fi;
+
+  which java
+  java -version
+}
+
+# --batch-mode supresses download progress output that spams the logs.
+MVN="mvn --batch-mode"
+
+build_java() {
+  version=$1
+  dir=java_$version
+  # Java build needs `protoc`.
+  internal_build_cpp
+  cp -r java $dir
+  cd $dir && $MVN clean && $MVN test
+  cd ../..
+}
+
+# The conformance tests are hard-coded to work with the $ROOT/java directory.
+# So this can't run in parallel with two different sets of tests.
+build_java_with_conformance_tests() {
+  # Java build needs `protoc`.
+  internal_build_cpp
+  cd java && $MVN test && $MVN install
+  cd util && $MVN package assembly:single
+  cd ../..
+  cd conformance && make test_java && cd ..
+}
+
+build_javanano() {
+  # Java build needs `protoc`.
+  internal_build_cpp
+  cd javanano && $MVN test && cd ..
+}
+
+build_java_jdk6() {
+  use_java jdk6
+  build_java jdk6
+}
+build_java_jdk7() {
+  use_java jdk7
+  build_java_with_conformance_tests
+}
+build_java_oracle7() {
+  use_java oracle7
+  build_java oracle7
+}
+
+build_javanano_jdk6() {
+  use_java jdk6
+  build_javanano
+}
+build_javanano_jdk7() {
+  use_java jdk7
+  build_javanano
+}
+build_javanano_oracle7() {
+  use_java oracle7
+  build_javanano
+}
+
+internal_install_python_deps() {
+  if [ "$TRAVIS" != "true" ]; then
+    return;
+  fi
+  # Install tox (OS X doesn't have pip).
+  if [ $(uname -s) == "Darwin" ]; then
+    sudo easy_install tox
+  else
+    sudo pip install tox
+  fi
+  # Only install Python2.6/3.x on Linux.
+  if [ $(uname -s) == "Linux" ]; then
+    sudo apt-get install -y python-software-properties # for apt-add-repository
+    sudo apt-add-repository -y ppa:fkrull/deadsnakes
+    sudo apt-get update -qq
+    sudo apt-get install -y python2.6 python2.6-dev
+    sudo apt-get install -y python3.3 python3.3-dev
+    sudo apt-get install -y python3.4 python3.4-dev
+  fi
+}
+
+internal_objectivec_common () {
+  # Make sure xctool is up to date. Adapted from
+  #  http://docs.travis-ci.com/user/osx-ci-environment/
+  # We don't use a before_install because we test multiple OSes.
+  brew update
+  brew outdated xctool || brew upgrade xctool
+  # Reused the build script that takes care of configuring and ensuring things
+  # are up to date. Xcode and conformance tests will be directly invoked.
+  objectivec/DevTools/full_mac_build.sh \
+      --core-only --skip-xcode --skip-objc-conformance
+}
+
+internal_xctool_debug_and_release() {
+  # Always use -reporter plain to avoid escape codes in output (makes travis
+  # logs easier to read).
+  xctool -reporter plain -configuration Debug "$@"
+  xctool -reporter plain -configuration Release "$@"
+}
+
+build_objectivec_ios() {
+  internal_objectivec_common
+  # https://github.com/facebook/xctool/issues/509 - unlike xcodebuild, xctool
+  # doesn't support >1 destination, so we have to build first and then run the
+  # tests one destination at a time.
+  internal_xctool_debug_and_release \
+    -project objectivec/ProtocolBuffers_iOS.xcodeproj \
+    -scheme ProtocolBuffers \
+    -sdk iphonesimulator \
+    build-tests
+  IOS_DESTINATIONS=(
+    "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+    "platform=iOS Simulator,name=iPhone 6,OS=9.2" # 64bit
+    "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+    "platform=iOS Simulator,name=iPad Air,OS=9.2" # 64bit
+  )
+  for i in "${IOS_DESTINATIONS[@]}" ; do
+    internal_xctool_debug_and_release \
+      -project objectivec/ProtocolBuffers_iOS.xcodeproj \
+      -scheme ProtocolBuffers \
+      -sdk iphonesimulator \
+      -destination "${i}" \
+      run-tests
+  done
+}
+
+build_objectivec_osx() {
+  internal_objectivec_common
+  internal_xctool_debug_and_release \
+    -project objectivec/ProtocolBuffers_OSX.xcodeproj \
+    -scheme ProtocolBuffers \
+    -destination "platform=OS X,arch=x86_64" \
+    test
+  cd conformance && make test_objc && cd ..
+}
+
+build_python() {
+  internal_build_cpp
+  internal_install_python_deps
+  cd python
+  # Only test Python 2.6/3.x on Linux
+  if [ $(uname -s) == "Linux" ]; then
+    envlist=py\{26,27,33,34\}-python
+  else
+    envlist=py27-python
+  fi
+  tox -e $envlist
+  cd ..
+}
+
+build_python_cpp() {
+  internal_build_cpp
+  internal_install_python_deps
+  export LD_LIBRARY_PATH=../src/.libs # for Linux
+  export DYLD_LIBRARY_PATH=../src/.libs # for OS X
+  cd python
+  # Only test Python 2.6/3.x on Linux
+  if [ $(uname -s) == "Linux" ]; then
+    # py26 is currently disabled due to json_format
+    envlist=py\{27,33,34\}-cpp
+  else
+    envlist=py27-cpp
+  fi
+  tox -e $envlist
+  cd ..
+}
+
+build_ruby19() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-1.9 && cd ..
+}
+build_ruby20() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-2.0 && cd ..
+}
+build_ruby21() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-2.1 && cd ..
+}
+build_ruby22() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-2.2 && cd ..
+}
+build_jruby() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh jruby && cd ..
+}
+
+build_javascript() {
+  internal_build_cpp
+  cd js && npm install && npm test && cd ..
+}
+
+# Note: travis currently does not support testing more than one language so the
+# .travis.yml cheats and claims to only be cpp.  If they add multiple language
+# support, this should probably get updated to install steps and/or
+# rvm/gemfile/jdk/etc. entries rather than manually doing the work.
+
+# .travis.yml uses matrix.exclude to block the cases where app-get can't be
+# use to install things.
+
+# -------- main --------
+
+if [ "$#" -ne 1 ]; then
+  echo "
+Usage: $0 { cpp |
+            csharp |
+            java_jdk6 |
+            java_jdk7 |
+            java_oracle7 |
+            javanano_jdk6 |
+            javanano_jdk7 |
+            javanano_oracle7 |
+            objectivec_ios |
+            objectivec_osx |
+            python |
+            python_cpp |
+            ruby19 |
+            ruby20 |
+            ruby21 |
+            ruby22 |
+            jruby }
+"
+  exit 1
+fi
+
+set -e  # exit immediately on error
+set -x  # display all commands
+eval "build_$1"
diff --git a/src/third_party/protobuf-3/third_party/six/six.py b/src/third_party/protobuf-3/third_party/six/six.py
new file mode 100644
index 0000000..190c023
--- /dev/null
+++ b/src/third_party/protobuf-3/third_party/six/six.py
@@ -0,0 +1,868 @@
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+# Copyright (c) 2010-2015 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+from __future__ import absolute_import
+
+import functools
+import itertools
+import operator
+import sys
+import types
+
+__author__ = "Benjamin Peterson <benjamin@python.org>"
+__version__ = "1.10.0"
+
+
+# Useful for very coarse version differentiation.
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+PY34 = sys.version_info[0:2] >= (3, 4)
+
+if PY3:
+    string_types = str,
+    integer_types = int,
+    class_types = type,
+    text_type = str
+    binary_type = bytes
+
+    MAXSIZE = sys.maxsize
+else:
+    string_types = basestring,
+    integer_types = (int, long)
+    class_types = (type, types.ClassType)
+    text_type = unicode
+    binary_type = str
+
+    if sys.platform.startswith("java"):
+        # Jython always uses 32 bits.
+        MAXSIZE = int((1 << 31) - 1)
+    else:
+        # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
+        class X(object):
+
+            def __len__(self):
+                return 1 << 31
+        try:
+            len(X())
+        except OverflowError:
+            # 32-bit
+            MAXSIZE = int((1 << 31) - 1)
+        else:
+            # 64-bit
+            MAXSIZE = int((1 << 63) - 1)
+        del X
+
+
+def _add_doc(func, doc):
+    """Add documentation to a function."""
+    func.__doc__ = doc
+
+
+def _import_module(name):
+    """Import module, returning the module after the last dot."""
+    __import__(name)
+    return sys.modules[name]
+
+
+class _LazyDescr(object):
+
+    def __init__(self, name):
+        self.name = name
+
+    def __get__(self, obj, tp):
+        result = self._resolve()
+        setattr(obj, self.name, result)  # Invokes __set__.
+        try:
+            # This is a bit ugly, but it avoids running this again by
+            # removing this descriptor.
+            delattr(obj.__class__, self.name)
+        except AttributeError:
+            pass
+        return result
+
+
+class MovedModule(_LazyDescr):
+
+    def __init__(self, name, old, new=None):
+        super(MovedModule, self).__init__(name)
+        if PY3:
+            if new is None:
+                new = name
+            self.mod = new
+        else:
+            self.mod = old
+
+    def _resolve(self):
+        return _import_module(self.mod)
+
+    def __getattr__(self, attr):
+        _module = self._resolve()
+        value = getattr(_module, attr)
+        setattr(self, attr, value)
+        return value
+
+
+class _LazyModule(types.ModuleType):
+
+    def __init__(self, name):
+        super(_LazyModule, self).__init__(name)
+        self.__doc__ = self.__class__.__doc__
+
+    def __dir__(self):
+        attrs = ["__doc__", "__name__"]
+        attrs += [attr.name for attr in self._moved_attributes]
+        return attrs
+
+    # Subclasses should override this
+    _moved_attributes = []
+
+
+class MovedAttribute(_LazyDescr):
+
+    def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
+        super(MovedAttribute, self).__init__(name)
+        if PY3:
+            if new_mod is None:
+                new_mod = name
+            self.mod = new_mod
+            if new_attr is None:
+                if old_attr is None:
+                    new_attr = name
+                else:
+                    new_attr = old_attr
+            self.attr = new_attr
+        else:
+            self.mod = old_mod
+            if old_attr is None:
+                old_attr = name
+            self.attr = old_attr
+
+    def _resolve(self):
+        module = _import_module(self.mod)
+        return getattr(module, self.attr)
+
+
+class _SixMetaPathImporter(object):
+
+    """
+    A meta path importer to import six.moves and its submodules.
+
+    This class implements a PEP302 finder and loader. It should be compatible
+    with Python 2.5 and all existing versions of Python3
+    """
+
+    def __init__(self, six_module_name):
+        self.name = six_module_name
+        self.known_modules = {}
+
+    def _add_module(self, mod, *fullnames):
+        for fullname in fullnames:
+            self.known_modules[self.name + "." + fullname] = mod
+
+    def _get_module(self, fullname):
+        return self.known_modules[self.name + "." + fullname]
+
+    def find_module(self, fullname, path=None):
+        if fullname in self.known_modules:
+            return self
+        return None
+
+    def __get_module(self, fullname):
+        try:
+            return self.known_modules[fullname]
+        except KeyError:
+            raise ImportError("This loader does not know module " + fullname)
+
+    def load_module(self, fullname):
+        try:
+            # in case of a reload
+            return sys.modules[fullname]
+        except KeyError:
+            pass
+        mod = self.__get_module(fullname)
+        if isinstance(mod, MovedModule):
+            mod = mod._resolve()
+        else:
+            mod.__loader__ = self
+        sys.modules[fullname] = mod
+        return mod
+
+    def is_package(self, fullname):
+        """
+        Return true, if the named module is a package.
+
+        We need this method to get correct spec objects with
+        Python 3.4 (see PEP451)
+        """
+        return hasattr(self.__get_module(fullname), "__path__")
+
+    def get_code(self, fullname):
+        """Return None
+
+        Required, if is_package is implemented"""
+        self.__get_module(fullname)  # eventually raises ImportError
+        return None
+    get_source = get_code  # same as get_code
+
+_importer = _SixMetaPathImporter(__name__)
+
+
+class _MovedItems(_LazyModule):
+
+    """Lazy loading of moved objects"""
+    __path__ = []  # mark as package
+
+
+_moved_attributes = [
+    MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
+    MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
+    MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
+    MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
+    MovedAttribute("intern", "__builtin__", "sys"),
+    MovedAttribute("map", "itertools", "builtins", "imap", "map"),
+    MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
+    MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
+    MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
+    MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
+    MovedAttribute("reduce", "__builtin__", "functools"),
+    MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
+    MovedAttribute("StringIO", "StringIO", "io"),
+    MovedAttribute("UserDict", "UserDict", "collections"),
+    MovedAttribute("UserList", "UserList", "collections"),
+    MovedAttribute("UserString", "UserString", "collections"),
+    MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
+    MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
+    MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
+    MovedModule("builtins", "__builtin__"),
+    MovedModule("configparser", "ConfigParser"),
+    MovedModule("copyreg", "copy_reg"),
+    MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
+    MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
+    MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
+    MovedModule("http_cookies", "Cookie", "http.cookies"),
+    MovedModule("html_entities", "htmlentitydefs", "html.entities"),
+    MovedModule("html_parser", "HTMLParser", "html.parser"),
+    MovedModule("http_client", "httplib", "http.client"),
+    MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
+    MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
+    MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
+    MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
+    MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
+    MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
+    MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
+    MovedModule("cPickle", "cPickle", "pickle"),
+    MovedModule("queue", "Queue"),
+    MovedModule("reprlib", "repr"),
+    MovedModule("socketserver", "SocketServer"),
+    MovedModule("_thread", "thread", "_thread"),
+    MovedModule("tkinter", "Tkinter"),
+    MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
+    MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
+    MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
+    MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
+    MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
+    MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
+    MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
+    MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
+    MovedModule("tkinter_colorchooser", "tkColorChooser",
+                "tkinter.colorchooser"),
+    MovedModule("tkinter_commondialog", "tkCommonDialog",
+                "tkinter.commondialog"),
+    MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
+    MovedModule("tkinter_font", "tkFont", "tkinter.font"),
+    MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
+    MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
+                "tkinter.simpledialog"),
+    MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
+    MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
+    MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
+    MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
+    MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
+    MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
+]
+# Add windows specific modules.
+if sys.platform == "win32":
+    _moved_attributes += [
+        MovedModule("winreg", "_winreg"),
+    ]
+
+for attr in _moved_attributes:
+    setattr(_MovedItems, attr.name, attr)
+    if isinstance(attr, MovedModule):
+        _importer._add_module(attr, "moves." + attr.name)
+del attr
+
+_MovedItems._moved_attributes = _moved_attributes
+
+moves = _MovedItems(__name__ + ".moves")
+_importer._add_module(moves, "moves")
+
+
+class Module_six_moves_urllib_parse(_LazyModule):
+
+    """Lazy loading of moved objects in six.moves.urllib_parse"""
+
+
+_urllib_parse_moved_attributes = [
+    MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
+    MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
+    MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
+    MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
+    MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
+    MovedAttribute("urljoin", "urlparse", "urllib.parse"),
+    MovedAttribute("urlparse", "urlparse", "urllib.parse"),
+    MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
+    MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
+    MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
+    MovedAttribute("quote", "urllib", "urllib.parse"),
+    MovedAttribute("quote_plus", "urllib", "urllib.parse"),
+    MovedAttribute("unquote", "urllib", "urllib.parse"),
+    MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
+    MovedAttribute("urlencode", "urllib", "urllib.parse"),
+    MovedAttribute("splitquery", "urllib", "urllib.parse"),
+    MovedAttribute("splittag", "urllib", "urllib.parse"),
+    MovedAttribute("splituser", "urllib", "urllib.parse"),
+    MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_params", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_query", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
+]
+for attr in _urllib_parse_moved_attributes:
+    setattr(Module_six_moves_urllib_parse, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
+                      "moves.urllib_parse", "moves.urllib.parse")
+
+
+class Module_six_moves_urllib_error(_LazyModule):
+
+    """Lazy loading of moved objects in six.moves.urllib_error"""
+
+
+_urllib_error_moved_attributes = [
+    MovedAttribute("URLError", "urllib2", "urllib.error"),
+    MovedAttribute("HTTPError", "urllib2", "urllib.error"),
+    MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
+]
+for attr in _urllib_error_moved_attributes:
+    setattr(Module_six_moves_urllib_error, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
+                      "moves.urllib_error", "moves.urllib.error")
+
+
+class Module_six_moves_urllib_request(_LazyModule):
+
+    """Lazy loading of moved objects in six.moves.urllib_request"""
+
+
+_urllib_request_moved_attributes = [
+    MovedAttribute("urlopen", "urllib2", "urllib.request"),
+    MovedAttribute("install_opener", "urllib2", "urllib.request"),
+    MovedAttribute("build_opener", "urllib2", "urllib.request"),
+    MovedAttribute("pathname2url", "urllib", "urllib.request"),
+    MovedAttribute("url2pathname", "urllib", "urllib.request"),
+    MovedAttribute("getproxies", "urllib", "urllib.request"),
+    MovedAttribute("Request", "urllib2", "urllib.request"),
+    MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
+    MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
+    MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
+    MovedAttribute("FileHandler", "urllib2", "urllib.request"),
+    MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
+    MovedAttribute("urlretrieve", "urllib", "urllib.request"),
+    MovedAttribute("urlcleanup", "urllib", "urllib.request"),
+    MovedAttribute("URLopener", "urllib", "urllib.request"),
+    MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
+    MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
+]
+for attr in _urllib_request_moved_attributes:
+    setattr(Module_six_moves_urllib_request, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
+                      "moves.urllib_request", "moves.urllib.request")
+
+
+class Module_six_moves_urllib_response(_LazyModule):
+
+    """Lazy loading of moved objects in six.moves.urllib_response"""
+
+
+_urllib_response_moved_attributes = [
+    MovedAttribute("addbase", "urllib", "urllib.response"),
+    MovedAttribute("addclosehook", "urllib", "urllib.response"),
+    MovedAttribute("addinfo", "urllib", "urllib.response"),
+    MovedAttribute("addinfourl", "urllib", "urllib.response"),
+]
+for attr in _urllib_response_moved_attributes:
+    setattr(Module_six_moves_urllib_response, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
+                      "moves.urllib_response", "moves.urllib.response")
+
+
+class Module_six_moves_urllib_robotparser(_LazyModule):
+
+    """Lazy loading of moved objects in six.moves.urllib_robotparser"""
+
+
+_urllib_robotparser_moved_attributes = [
+    MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
+]
+for attr in _urllib_robotparser_moved_attributes:
+    setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
+                      "moves.urllib_robotparser", "moves.urllib.robotparser")
+
+
+class Module_six_moves_urllib(types.ModuleType):
+
+    """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
+    __path__ = []  # mark as package
+    parse = _importer._get_module("moves.urllib_parse")
+    error = _importer._get_module("moves.urllib_error")
+    request = _importer._get_module("moves.urllib_request")
+    response = _importer._get_module("moves.urllib_response")
+    robotparser = _importer._get_module("moves.urllib_robotparser")
+
+    def __dir__(self):
+        return ['parse', 'error', 'request', 'response', 'robotparser']
+
+_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
+                      "moves.urllib")
+
+
+def add_move(move):
+    """Add an item to six.moves."""
+    setattr(_MovedItems, move.name, move)
+
+
+def remove_move(name):
+    """Remove item from six.moves."""
+    try:
+        delattr(_MovedItems, name)
+    except AttributeError:
+        try:
+            del moves.__dict__[name]
+        except KeyError:
+            raise AttributeError("no such move, %r" % (name,))
+
+
+if PY3:
+    _meth_func = "__func__"
+    _meth_self = "__self__"
+
+    _func_closure = "__closure__"
+    _func_code = "__code__"
+    _func_defaults = "__defaults__"
+    _func_globals = "__globals__"
+else:
+    _meth_func = "im_func"
+    _meth_self = "im_self"
+
+    _func_closure = "func_closure"
+    _func_code = "func_code"
+    _func_defaults = "func_defaults"
+    _func_globals = "func_globals"
+
+
+try:
+    advance_iterator = next
+except NameError:
+    def advance_iterator(it):
+        return it.next()
+next = advance_iterator
+
+
+try:
+    callable = callable
+except NameError:
+    def callable(obj):
+        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+
+if PY3:
+    def get_unbound_function(unbound):
+        return unbound
+
+    create_bound_method = types.MethodType
+
+    def create_unbound_method(func, cls):
+        return func
+
+    Iterator = object
+else:
+    def get_unbound_function(unbound):
+        return unbound.im_func
+
+    def create_bound_method(func, obj):
+        return types.MethodType(func, obj, obj.__class__)
+
+    def create_unbound_method(func, cls):
+        return types.MethodType(func, None, cls)
+
+    class Iterator(object):
+
+        def next(self):
+            return type(self).__next__(self)
+
+    callable = callable
+_add_doc(get_unbound_function,
+         """Get the function out of a possibly unbound function""")
+
+
+get_method_function = operator.attrgetter(_meth_func)
+get_method_self = operator.attrgetter(_meth_self)
+get_function_closure = operator.attrgetter(_func_closure)
+get_function_code = operator.attrgetter(_func_code)
+get_function_defaults = operator.attrgetter(_func_defaults)
+get_function_globals = operator.attrgetter(_func_globals)
+
+
+if PY3:
+    def iterkeys(d, **kw):
+        return iter(d.keys(**kw))
+
+    def itervalues(d, **kw):
+        return iter(d.values(**kw))
+
+    def iteritems(d, **kw):
+        return iter(d.items(**kw))
+
+    def iterlists(d, **kw):
+        return iter(d.lists(**kw))
+
+    viewkeys = operator.methodcaller("keys")
+
+    viewvalues = operator.methodcaller("values")
+
+    viewitems = operator.methodcaller("items")
+else:
+    def iterkeys(d, **kw):
+        return d.iterkeys(**kw)
+
+    def itervalues(d, **kw):
+        return d.itervalues(**kw)
+
+    def iteritems(d, **kw):
+        return d.iteritems(**kw)
+
+    def iterlists(d, **kw):
+        return d.iterlists(**kw)
+
+    viewkeys = operator.methodcaller("viewkeys")
+
+    viewvalues = operator.methodcaller("viewvalues")
+
+    viewitems = operator.methodcaller("viewitems")
+
+_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
+_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
+_add_doc(iteritems,
+         "Return an iterator over the (key, value) pairs of a dictionary.")
+_add_doc(iterlists,
+         "Return an iterator over the (key, [values]) pairs of a dictionary.")
+
+
+if PY3:
+    def b(s):
+        return s.encode("latin-1")
+
+    def u(s):
+        return s
+    unichr = chr
+    import struct
+    int2byte = struct.Struct(">B").pack
+    del struct
+    byte2int = operator.itemgetter(0)
+    indexbytes = operator.getitem
+    iterbytes = iter
+    import io
+    StringIO = io.StringIO
+    BytesIO = io.BytesIO
+    _assertCountEqual = "assertCountEqual"
+    if sys.version_info[1] <= 1:
+        _assertRaisesRegex = "assertRaisesRegexp"
+        _assertRegex = "assertRegexpMatches"
+    else:
+        _assertRaisesRegex = "assertRaisesRegex"
+        _assertRegex = "assertRegex"
+else:
+    def b(s):
+        return s
+    # Workaround for standalone backslash
+
+    def u(s):
+        return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
+    unichr = unichr
+    int2byte = chr
+
+    def byte2int(bs):
+        return ord(bs[0])
+
+    def indexbytes(buf, i):
+        return ord(buf[i])
+    iterbytes = functools.partial(itertools.imap, ord)
+    import StringIO
+    StringIO = BytesIO = StringIO.StringIO
+    _assertCountEqual = "assertItemsEqual"
+    _assertRaisesRegex = "assertRaisesRegexp"
+    _assertRegex = "assertRegexpMatches"
+_add_doc(b, """Byte literal""")
+_add_doc(u, """Text literal""")
+
+
+def assertCountEqual(self, *args, **kwargs):
+    return getattr(self, _assertCountEqual)(*args, **kwargs)
+
+
+def assertRaisesRegex(self, *args, **kwargs):
+    return getattr(self, _assertRaisesRegex)(*args, **kwargs)
+
+
+def assertRegex(self, *args, **kwargs):
+    return getattr(self, _assertRegex)(*args, **kwargs)
+
+
+if PY3:
+    exec_ = getattr(moves.builtins, "exec")
+
+    def reraise(tp, value, tb=None):
+        if value is None:
+            value = tp()
+        if value.__traceback__ is not tb:
+            raise value.with_traceback(tb)
+        raise value
+
+else:
+    def exec_(_code_, _globs_=None, _locs_=None):
+        """Execute code in a namespace."""
+        if _globs_ is None:
+            frame = sys._getframe(1)
+            _globs_ = frame.f_globals
+            if _locs_ is None:
+                _locs_ = frame.f_locals
+            del frame
+        elif _locs_ is None:
+            _locs_ = _globs_
+        exec("""exec _code_ in _globs_, _locs_""")
+
+    exec_("""def reraise(tp, value, tb=None):
+    raise tp, value, tb
+""")
+
+
+if sys.version_info[:2] == (3, 2):
+    exec_("""def raise_from(value, from_value):
+    if from_value is None:
+        raise value
+    raise value from from_value
+""")
+elif sys.version_info[:2] > (3, 2):
+    exec_("""def raise_from(value, from_value):
+    raise value from from_value
+""")
+else:
+    def raise_from(value, from_value):
+        raise value
+
+
+print_ = getattr(moves.builtins, "print", None)
+if print_ is None:
+    def print_(*args, **kwargs):
+        """The new-style print function for Python 2.4 and 2.5."""
+        fp = kwargs.pop("file", sys.stdout)
+        if fp is None:
+            return
+
+        def write(data):
+            if not isinstance(data, basestring):
+                data = str(data)
+            # If the file has an encoding, encode unicode with it.
+            if (isinstance(fp, file) and
+                    isinstance(data, unicode) and
+                    fp.encoding is not None):
+                errors = getattr(fp, "errors", None)
+                if errors is None:
+                    errors = "strict"
+                data = data.encode(fp.encoding, errors)
+            fp.write(data)
+        want_unicode = False
+        sep = kwargs.pop("sep", None)
+        if sep is not None:
+            if isinstance(sep, unicode):
+                want_unicode = True
+            elif not isinstance(sep, str):
+                raise TypeError("sep must be None or a string")
+        end = kwargs.pop("end", None)
+        if end is not None:
+            if isinstance(end, unicode):
+                want_unicode = True
+            elif not isinstance(end, str):
+                raise TypeError("end must be None or a string")
+        if kwargs:
+            raise TypeError("invalid keyword arguments to print()")
+        if not want_unicode:
+            for arg in args:
+                if isinstance(arg, unicode):
+                    want_unicode = True
+                    break
+        if want_unicode:
+            newline = unicode("\n")
+            space = unicode(" ")
+        else:
+            newline = "\n"
+            space = " "
+        if sep is None:
+            sep = space
+        if end is None:
+            end = newline
+        for i, arg in enumerate(args):
+            if i:
+                write(sep)
+            write(arg)
+        write(end)
+if sys.version_info[:2] < (3, 3):
+    _print = print_
+
+    def print_(*args, **kwargs):
+        fp = kwargs.get("file", sys.stdout)
+        flush = kwargs.pop("flush", False)
+        _print(*args, **kwargs)
+        if flush and fp is not None:
+            fp.flush()
+
+_add_doc(reraise, """Reraise an exception.""")
+
+if sys.version_info[0:2] < (3, 4):
+    def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
+              updated=functools.WRAPPER_UPDATES):
+        def wrapper(f):
+            f = functools.wraps(wrapped, assigned, updated)(f)
+            f.__wrapped__ = wrapped
+            return f
+        return wrapper
+else:
+    wraps = functools.wraps
+
+
+def with_metaclass(meta, *bases):
+    """Create a base class with a metaclass."""
+    # This requires a bit of explanation: the basic idea is to make a dummy
+    # metaclass for one level of class instantiation that replaces itself with
+    # the actual metaclass.
+    class metaclass(meta):
+
+        def __new__(cls, name, this_bases, d):
+            return meta(name, bases, d)
+    return type.__new__(metaclass, 'temporary_class', (), {})
+
+
+def add_metaclass(metaclass):
+    """Class decorator for creating a class with a metaclass."""
+    def wrapper(cls):
+        orig_vars = cls.__dict__.copy()
+        slots = orig_vars.get('__slots__')
+        if slots is not None:
+            if isinstance(slots, str):
+                slots = [slots]
+            for slots_var in slots:
+                orig_vars.pop(slots_var)
+        orig_vars.pop('__dict__', None)
+        orig_vars.pop('__weakref__', None)
+        return metaclass(cls.__name__, cls.__bases__, orig_vars)
+    return wrapper
+
+
+def python_2_unicode_compatible(klass):
+    """
+    A decorator that defines __unicode__ and __str__ methods under Python 2.
+    Under Python 3 it does nothing.
+
+    To support Python 2 and 3 with a single code base, define a __str__ method
+    returning text and apply this decorator to the class.
+    """
+    if PY2:
+        if '__str__' not in klass.__dict__:
+            raise ValueError("@python_2_unicode_compatible cannot be applied "
+                             "to %s because it doesn't define __str__()." %
+                             klass.__name__)
+        klass.__unicode__ = klass.__str__
+        klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
+    return klass
+
+
+# Complete the moves implementation.
+# This code is at the end of this module to speed up module loading.
+# Turn this module into a package.
+__path__ = []  # required for PEP 302 and PEP 451
+__package__ = __name__  # see PEP 366 @ReservedAssignment
+if globals().get("__spec__") is not None:
+    __spec__.submodule_search_locations = []  # PEP 451 @UndefinedVariable
+# Remove other six meta path importers, since they cause problems. This can
+# happen if six is removed from sys.modules and then reloaded. (Setuptools does
+# this for some reason.)
+if sys.meta_path:
+    for i, importer in enumerate(sys.meta_path):
+        # Here's some real nastiness: Another "instance" of the six module might
+        # be floating around. Therefore, we can't use isinstance() to check for
+        # the six meta path importer, since the other six instance will have
+        # inserted an importer with different class.
+        if (type(importer).__name__ == "_SixMetaPathImporter" and
+                importer.name == __name__):
+            del sys.meta_path[i]
+            break
+    del i, importer
+# Finally, add the importer to the meta path import hook.
+sys.meta_path.append(_importer)
diff --git a/src/third_party/protobuf-3/update_file_lists.sh b/src/third_party/protobuf-3/update_file_lists.sh
new file mode 100755
index 0000000..d76a161
--- /dev/null
+++ b/src/third_party/protobuf-3/update_file_lists.sh
@@ -0,0 +1,191 @@
+#!/bin/sh
+
+# This script copies source file lists from src/Makefile.am to cmake files.
+
+get_variable_value() {
+  local FILENAME=$1
+  local VARNAME=$2
+  awk "
+    BEGIN { start = 0; }
+    /^$VARNAME =/ { start = 1; }
+    { if (start) { print \$0; } }
+    /\\\\\$/ { next; }
+    { start = 0; }
+  " $FILENAME \
+    | sed "s/^$VARNAME =//" \
+    | sed "s/[ \\]//g" \
+    | grep -v "^\\$" \
+    | grep -v "^$" \
+    | LC_ALL=C sort | uniq
+}
+
+get_header_files() {
+  get_variable_value $@ | grep '\.h$'
+}
+
+get_source_files() {
+  get_variable_value $@ | grep "cc$"
+}
+
+get_proto_files_blacklisted() {
+  get_proto_files $@ | sed '/^google\/protobuf\/unittest_enormous_descriptor.proto$/d'
+}
+
+get_proto_files() {
+  get_variable_value $@ | grep "pb.cc$" | sed "s/pb.cc/proto/"
+}
+
+sort_files() {
+  for FILE in $@; do
+    echo $FILE
+  done | LC_ALL=C sort | uniq
+}
+
+MAKEFILE=src/Makefile.am
+
+[ -f "$MAKEFILE" ] || {
+  echo "Cannot find: $MAKEFILE"
+  exit 1
+}
+
+# Extract file lists from src/Makefile.am
+GZHEADERS=$(get_variable_value $MAKEFILE GZHEADERS)
+HEADERS=$(get_variable_value $MAKEFILE nobase_include_HEADERS)
+PUBLIC_HEADERS=$(sort_files $GZHEADERS $HEADERS)
+LIBPROTOBUF_LITE_SOURCES=$(get_source_files $MAKEFILE libprotobuf_lite_la_SOURCES)
+LIBPROTOBUF_SOURCES=$(get_source_files $MAKEFILE libprotobuf_la_SOURCES)
+LIBPROTOC_SOURCES=$(get_source_files $MAKEFILE libprotoc_la_SOURCES)
+LITE_PROTOS=$(get_proto_files $MAKEFILE protoc_lite_outputs)
+PROTOS=$(get_proto_files $MAKEFILE protoc_outputs)
+PROTOS_BLACKLISTED=$(get_proto_files_blacklisted $MAKEFILE protoc_outputs)
+WKT_PROTOS=$(get_variable_value $MAKEFILE nobase_dist_proto_DATA)
+COMMON_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_TEST_SOURCES)
+COMMON_LITE_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_LITE_TEST_SOURCES)
+TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_test_SOURCES)
+LITE_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_test_SOURCES)
+LITE_ARENA_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_arena_test_SOURCES)
+TEST_PLUGIN_SOURCES=$(get_source_files $MAKEFILE test_plugin_SOURCES)
+
+################################################################################
+# Update cmake files.
+################################################################################
+
+CMAKE_DIR=cmake
+EXTRACT_INCLUDES_BAT=cmake/extract_includes.bat.in
+[ -d "$CMAKE_DIR" ] || {
+  echo "Cannot find: $CMAKE_DIR"
+  exit 1
+}
+
+[ -f "$EXTRACT_INCLUDES_BAT" ] || {
+  echo "Cannot find: $EXTRACT_INCLUDES_BAT"
+  exit 1
+}
+
+set_cmake_value() {
+  local FILENAME=$1
+  local VARNAME=$2
+  local PREFIX=$3
+  shift
+  shift
+  shift
+  awk -v values="$*" -v prefix="$PREFIX" "
+    BEGIN { start = 0; }
+    /^set\\($VARNAME/ {
+      start = 1;
+      print \$0;
+      len = split(values, vlist, \" \");
+      for (i = 1; i <= len; ++i) {
+        printf(\"  %s%s\\n\", prefix, vlist[i]);
+      }
+      next;
+    }
+    start && /^\\)/ {
+      start = 0;
+    }
+    !start {
+      print \$0;
+    }
+  " $FILENAME > /tmp/$$
+  cp /tmp/$$ $FILENAME
+}
+
+
+# Replace file lists in cmake files.
+CMAKE_PREFIX="\${protobuf_source_dir}/src/"
+set_cmake_value $CMAKE_DIR/libprotobuf-lite.cmake libprotobuf_lite_files $CMAKE_PREFIX $LIBPROTOBUF_LITE_SOURCES
+set_cmake_value $CMAKE_DIR/libprotobuf.cmake libprotobuf_files $CMAKE_PREFIX $LIBPROTOBUF_SOURCES
+set_cmake_value $CMAKE_DIR/libprotoc.cmake libprotoc_files $CMAKE_PREFIX $LIBPROTOC_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake lite_test_protos "" $LITE_PROTOS
+set_cmake_value $CMAKE_DIR/tests.cmake tests_protos "" $PROTOS_BLACKLISTED
+set_cmake_value $CMAKE_DIR/tests.cmake common_test_files $CMAKE_PREFIX $COMMON_TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake common_lite_test_files $CMAKE_PREFIX $COMMON_LITE_TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake tests_files $CMAKE_PREFIX $TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake lite_test_files $CMAKE_PREFIX $LITE_TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake lite_arena_test_files $CMAKE_PREFIX $LITE_ARENA_TEST_SOURCES
+
+# Generate extract_includes.bat
+echo "mkdir include" > $EXTRACT_INCLUDES_BAT
+for HEADER in $PUBLIC_HEADERS; do
+  HEADER_DIR=$(dirname $HEADER)
+  while [ ! "$HEADER_DIR" = "." ]; do
+    echo $HEADER_DIR | sed "s/\\//\\\\/g"
+    HEADER_DIR=$(dirname $HEADER_DIR)
+  done
+done | sort | uniq | sed "s/^/mkdir include\\\\/" >> $EXTRACT_INCLUDES_BAT
+for HEADER in $PUBLIC_HEADERS; do
+  WINPATH=$(echo $HEADER | sed 's;/;\\;g')
+  echo "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\..\\src\\$WINPATH include\\$WINPATH" >> $EXTRACT_INCLUDES_BAT
+done
+
+################################################################################
+# Update bazel BUILD files.
+################################################################################
+
+set_bazel_value() {
+  local FILENAME=$1
+  local VARNAME=$2
+  local PREFIX=$3
+  shift
+  shift
+  shift
+  awk -v values="$*" -v prefix="$PREFIX" "
+    BEGIN { start = 0; }
+    /# AUTOGEN\\($VARNAME\\)/ {
+      start = 1;
+      print \$0;
+      # replace \$0 with indent.
+      sub(/#.*/, \"\", \$0)
+      len = split(values, vlist, \" \");
+      for (i = 1; i <= len; ++i) {
+        printf(\"%s\\\"%s%s\\\",\n\", \$0, prefix, vlist[i]);
+      }
+      next;
+    }
+    start && /\]/ {
+      start = 0
+    }
+    !start {
+      print \$0;
+    }
+  " $FILENAME > /tmp/$$
+  cp /tmp/$$ $FILENAME
+}
+
+
+BAZEL_BUILD=./BUILD
+BAZEL_PREFIX="src/"
+if [ -f "$BAZEL_BUILD" ]; then
+  set_bazel_value $BAZEL_BUILD protobuf_lite_srcs $BAZEL_PREFIX $LIBPROTOBUF_LITE_SOURCES
+  set_bazel_value $BAZEL_BUILD protobuf_srcs $BAZEL_PREFIX $LIBPROTOBUF_SOURCES
+  set_bazel_value $BAZEL_BUILD protoc_lib_srcs $BAZEL_PREFIX $LIBPROTOC_SOURCES
+  set_bazel_value $BAZEL_BUILD lite_test_protos "" $LITE_PROTOS
+  set_bazel_value $BAZEL_BUILD well_known_protos "" $WKT_PROTOS
+  set_bazel_value $BAZEL_BUILD test_protos "" $PROTOS
+  set_bazel_value $BAZEL_BUILD common_test_srcs $BAZEL_PREFIX $COMMON_TEST_SOURCES
+  set_bazel_value $BAZEL_BUILD test_srcs $BAZEL_PREFIX $TEST_SOURCES
+  set_bazel_value $BAZEL_BUILD test_plugin_srcs $BAZEL_PREFIX $TEST_PLUGIN_SOURCES
+else
+  echo "Skipped BUILD file update."
+fi
+
diff --git a/src/third_party/protobuf-3/util/python/BUILD b/src/third_party/protobuf-3/util/python/BUILD
new file mode 100644
index 0000000..3ac0385
--- /dev/null
+++ b/src/third_party/protobuf-3/util/python/BUILD
@@ -0,0 +1,18 @@
+# This is a placeholder for python headers. Projects needing to use
+# fast cpp protos in protobuf's python interface should build with
+# --define=use_fast_cpp_protos=true, and in addition, provide
+# //external:python_headers dependency that in turn provides Python.h.
+#
+# Projects that include protobuf using a Bazel external repository will need to
+# add a workspace rule to their WORKSPACE files to add an external workspace
+# that includes the Python headers. For example, the protobuf WORKSPACE file
+# includes the following local_repository rule that points to this directory:
+#
+# new_local_repository(
+#   name = "python",
+#   path = __workspace_dir__ + "/util/python",
+# )
+cc_library(
+    name = "python_headers",
+    visibility = ["//visibility:public"],
+)
diff --git a/src/third_party/skia/src/core/SkUtilsArm.h b/src/third_party/skia/src/core/SkUtilsArm.h
index f156481..3bb7051 100644
--- a/src/third_party/skia/src/core/SkUtilsArm.h
+++ b/src/third_party/skia/src/core/SkUtilsArm.h
@@ -23,7 +23,10 @@
 
 #if defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_OPTIONAL_NEON)
 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_DYNAMIC
-#elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON) || defined(SK_CPU_ARM64)
+// TODO: We ignore neon even on ARM64... determine if it would be beneficial and
+// if so add back '|| defined(SK_CPU_ARM64)' to this #elif and include the neon
+// source files in cobalt/renderer/rasterizer/skia/skia/skia_library_opts.gyp.
+#elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_ALWAYS
 #else
 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_NONE